From b3448a433eec29071664ed899b18288eb5bfd30f Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sun, 27 Sep 2026 12:44:12 +0200 Subject: [PATCH 01/21] feat(flow-php/etl): columnar Rows batch with Row as a view - Rows holds a Schema plus one Column per definition; Row is a (Rows, index) view - Rows::of(Schema, Row ...) and Rows::fromColumns() replace the constructor, trusted() and conformed() - new Column / ColumnBuilder / Backend contracts with a PHP backend, Config::backend() replaces hydrator() - FloeEngine, NativeFloeEncoder, adaptive/native hydrators and extension gates removed - core consumers ported to column operations (gather, slice, project, withColumns) - a date is midnight at UTC; join collisions suggest a prefix for every join shape --- .../src/Format/Floe/FloeReadScenario.php | 12 +- .../src/Format/Floe/FloeWriteScenario.php | 16 +- .../suites/Format/Floe/FloeReadBench.php | 16 +- .../suites/Format/Floe/FloeWriteBench.php | 16 +- bootstrap.php | 3 + documentation/components/adapters/json.md | 2 + .../components/core/building-blocks.md | 6 +- .../components/extensions/flow-php-ext.md | 77 +- documentation/installation/docker.md | 12 +- documentation/upgrading-0.16-0.35.md | 414 ++++ documentation/upgrading-0.3-0.8.md | 368 ++++ documentation/upgrading-0.35-0.40.md | 739 +++++++ documentation/upgrading-0.8-0.16.md | 155 ++ documentation/upgrading.md | 1742 ++--------------- .../Adapter/Avro/FlixTech/AvroExtractor.php | 2 +- .../Integration/CSVHydratorParityTest.php | 59 - .../Adapter/Doctrine/DbalQueryExtractor.php | 4 +- .../Tests/Integration/ExcelExtractorTest.php | 25 - .../Integration/ExcelHydratorParityTest.php | 19 - .../GoogleSheetHydratorParityTest.php | 38 +- .../Tests/Unit/GoogleSheetExtractorTest.php | 4 +- .../Flow/ETL/Adapter/JSON/SchemaConverter.php | 5 +- .../JSONMachine/JsonHydratorParityTest.php | 31 - .../JsonLinesHydratorParityTest.php | 55 - .../JSON/Tests/Unit/SchemaConverterTest.php | 8 +- .../Integration/ParquetHydratorParityTest.php | 8 +- .../Integration/TextHydratorParityTest.php | 18 - .../Integration/XMLHydratorParityTest.php | 18 - .../src/Flow/ETL/Bucketing/HashBucketing.php | 2 +- .../src/Flow/ETL/Bucketing/KeyGrouping.php | 2 +- .../Flow/ETL/Bucketing/SortedRunBucketing.php | 2 +- .../ETL/Bucketing/Storage/MemoryBuckets.php | 2 +- src/core/etl/src/Flow/ETL/Column/Backend.php | 30 + src/core/etl/src/Flow/ETL/Column/Column.php | 73 + .../etl/src/Flow/ETL/Column/ColumnBuilder.php | 37 + .../src/Flow/ETL/Column/DefaultBackend.php | 32 + .../src/Flow/ETL/Column/Php/BooleanLayout.php | 60 + .../etl/src/Flow/ETL/Column/Php/Buffers.php | 35 + .../ETL/Column/Php/CastingColumnBuilder.php | 137 ++ .../src/Flow/ETL/Column/Php/ColumnDecoder.php | 107 + .../Flow/ETL/Column/Php/ConstantColumn.php | 125 ++ .../src/Flow/ETL/Column/Php/DatePhysical.php | 66 + .../Flow/ETL/Column/Php/DateTimePhysical.php | 116 ++ .../src/Flow/ETL/Column/Php/DaysFromCivil.php | 24 + .../src/Flow/ETL/Column/Php/EnumPhysical.php | 48 + .../ETL/Column/Php/FixedBinary16Layout.php | 57 + .../src/Flow/ETL/Column/Php/Float64Layout.php | 57 + .../ETL/Column/Php/HtmlDocumentPhysical.php | 43 + .../ETL/Column/Php/HtmlElementPhysical.php | 42 + .../Flow/ETL/Column/Php/IdentityPhysical.php | 23 + .../src/Flow/ETL/Column/Php/Int32Layout.php | 61 + .../src/Flow/ETL/Column/Php/Int64Layout.php | 57 + .../src/Flow/ETL/Column/Php/JsonFactory.php | 45 + .../src/Flow/ETL/Column/Php/JsonPhysical.php | 44 + .../etl/src/Flow/ETL/Column/Php/Layout.php | 22 + .../etl/src/Flow/ETL/Column/Php/LayoutFor.php | 66 + .../src/Flow/ETL/Column/Php/ListColumn.php | 183 ++ .../Flow/ETL/Column/Php/ListColumnBuilder.php | 66 + .../src/Flow/ETL/Column/Php/ListPhysical.php | 52 + .../etl/src/Flow/ETL/Column/Php/MapColumn.php | 228 +++ .../Flow/ETL/Column/Php/MapColumnBuilder.php | 69 + .../src/Flow/ETL/Column/Php/MapPhysical.php | 54 + .../Flow/ETL/Column/Php/NullColumnBuilder.php | 42 + .../etl/src/Flow/ETL/Column/Php/NullCount.php | 25 + .../src/Flow/ETL/Column/Php/NullPhysical.php | 26 + .../etl/src/Flow/ETL/Column/Php/Offsets.php | 72 + .../Flow/ETL/Column/Php/PhpColumnBuilder.php | 25 + .../etl/src/Flow/ETL/Column/Php/Physical.php | 25 + .../ETL/Column/Php/PhysicalBuilderFor.php | 50 + .../src/Flow/ETL/Column/Php/PhysicalFor.php | 164 ++ .../etl/src/Flow/ETL/Column/Php/Retype.php | 52 + .../src/Flow/ETL/Column/Php/ScalarColumn.php | 130 ++ .../ETL/Column/Php/ScalarColumnBuilder.php | 74 + .../src/Flow/ETL/Column/Php/StructColumn.php | 289 +++ .../ETL/Column/Php/StructColumnBuilder.php | 75 + .../Flow/ETL/Column/Php/StructPhysical.php | 77 + .../src/Flow/ETL/Column/Php/TimePhysical.php | 94 + .../Flow/ETL/Column/Php/TimeZonePhysical.php | 45 + .../src/Flow/ETL/Column/Php/Utf8Layout.php | 63 + .../src/Flow/ETL/Column/Php/UuidPhysical.php | 42 + .../etl/src/Flow/ETL/Column/Php/Validity.php | 137 ++ .../ETL/Column/Php/XmlDocumentPhysical.php | 42 + .../ETL/Column/Php/XmlElementPhysical.php | 54 + .../etl/src/Flow/ETL/Column/PhpBackend.php | 66 + src/core/etl/src/Flow/ETL/Config.php | 8 + .../etl/src/Flow/ETL/Config/ConfigBuilder.php | 37 +- src/core/etl/src/Flow/ETL/DSL/functions.php | 26 +- .../ETL/Exception/ColumnMismatchException.php | 56 +- src/core/etl/src/Flow/ETL/Executor.php | 4 +- .../etl/src/Flow/ETL/Executor/Segment.php | 2 +- .../src/Flow/ETL/Extractor/ArrayExtractor.php | 4 +- .../Flow/ETL/Extractor/BatchByExtractor.php | 4 +- .../src/Flow/ETL/Extractor/BatchExtractor.php | 39 +- .../ETL/Extractor/CollectingExtractor.php | 2 +- .../Flow/ETL/Extractor/DataFrameExtractor.php | 2 +- .../src/Flow/ETL/Extractor/FeedExtractor.php | 2 +- .../src/Flow/ETL/Extractor/FileConstants.php | 28 +- .../src/Flow/ETL/Extractor/FilesExtractor.php | 4 +- .../src/Flow/ETL/Extractor/InferredRows.php | 6 +- .../Flow/ETL/Extractor/MemoryExtractor.php | 4 +- .../Flow/ETL/Extractor/PartitionColumns.php | 2 +- .../ETL/Extractor/PathPartitionsExtractor.php | 4 +- .../Flow/ETL/Extractor/SequenceExtractor.php | 4 +- src/core/etl/src/Flow/ETL/FlowContext.php | 6 + src/core/etl/src/Flow/ETL/Function/OnEach.php | 4 +- src/core/etl/src/Flow/ETL/GroupBy.php | 7 +- .../src/Flow/ETL/GroupBy/AggregatedGroups.php | 22 +- .../etl/src/Flow/ETL/GroupBy/PivotedTable.php | 4 +- .../etl/src/Flow/ETL/Join/HashJoin/Joiner.php | 73 +- .../Flow/ETL/Join/HashJoin/NullRowBuilder.php | 23 +- .../src/Flow/ETL/Join/HashJoin/RowMerger.php | 6 +- src/core/etl/src/Flow/ETL/Join/JoinSchema.php | 21 +- .../src/Flow/ETL/Loader/PartitionRouter.php | 17 +- .../ETL/Processor/BatchingByProcessor.php | 4 +- .../Flow/ETL/Processor/BatchingProcessor.php | 9 +- .../Flow/ETL/Processor/BucketingProcessor.php | 2 +- .../ETL/Processor/CollectingProcessor.php | 2 +- .../Processor/GroupByAggregationProcessor.php | 9 +- .../Flow/ETL/Processor/HashJoinProcessor.php | 4 +- .../ETL/Processor/MemorySortProcessor.php | 8 +- .../src/Flow/ETL/Processor/TopNProcessor.php | 11 +- .../src/Flow/ETL/Processor/VoidProcessor.php | 2 +- .../Flow/ETL/Processor/WindowProcessor.php | 17 +- src/core/etl/src/Flow/ETL/Row.php | 189 +- .../src/Flow/ETL/Row/AdaptiveRowHydrator.php | 33 - .../Row/Formatter/ASCIISchemaFormatter.php | 9 +- .../etl/src/Flow/ETL/Row/HydratedBatch.php | 84 - .../etl/src/Flow/ETL/Row/InferredBatch.php | 55 +- .../src/Flow/ETL/Row/NativeRowHydrator.php | 46 - .../etl/src/Flow/ETL/Row/PhpRowHydrator.php | 59 +- src/core/etl/src/Flow/ETL/Row/RowRenaming.php | 41 - src/core/etl/src/Flow/ETL/Row/RowsBuffer.php | 6 +- src/core/etl/src/Flow/ETL/Rows.php | 804 +++++--- .../etl/src/Flow/ETL/Rows/RowsBuilder.php | 329 ++++ src/core/etl/src/Flow/ETL/Schema.php | 15 - .../ETL/Schema/Definition/ZoneAlignment.php | 79 - .../Formatter/InlineSchemaFormatter.php | 24 + .../src/Flow/ETL/Serializer/DomValueCodec.php | 128 -- .../etl/src/Flow/ETL/Sort/Merge/KWayMerge.php | 6 +- .../Transformer/AddRowIndexTransformer.php | 14 +- .../Flow/ETL/Transformer/DerivedColumns.php | 11 +- .../Transformer/DropDuplicatesTransformer.php | 2 +- .../Transformer/DuplicateRowTransformer.php | 4 +- .../Transformer/NestedExpandTransformer.php | 50 +- .../Flow/ETL/Transformer/NestedExpansion.php | 47 +- .../Transformer/PruneEntriesTransformer.php | 21 +- .../RenameEachEntryTransformer.php | 25 +- .../Transformer/RenameEntryTransformer.php | 10 +- .../ScalarFunctionFilterTransformer.php | 2 +- .../Transformer/ScalarFunctionTransformer.php | 54 +- .../ETL/Transformer/SerializeTransformer.php | 13 +- .../Transformer/SerializedPayloadDecoder.php | 57 +- .../Flow/ETL/Transformer/UnpackedColumns.php | 7 +- .../Transformer/UnserializeTransformer.php | 23 +- .../Flow/ETL/Transformer/UntilTransformer.php | 4 +- src/core/etl/src/Flow/Floe/DSL/functions.php | 7 +- .../src/Flow/Floe/Decoding/JsonDecoder.php | 34 +- src/core/etl/src/Flow/Floe/FloeEngine.php | 25 - src/core/etl/src/Flow/Floe/FloeExtractor.php | 4 +- src/core/etl/src/Flow/Floe/FloeLoader.php | 2 - src/core/etl/src/Flow/Floe/FloeReader.php | 4 +- src/core/etl/src/Flow/Floe/FloeSerializer.php | 18 +- .../etl/src/Flow/Floe/FloeStreamReader.php | 11 +- .../etl/src/Flow/Floe/FloeStreamWriter.php | 7 +- src/core/etl/src/Flow/Floe/FloeWriter.php | 5 +- .../etl/src/Flow/Floe/NativeFloeEncoder.php | 117 -- .../ETL/Tests/Comparator/RowComparator.php | 60 + .../ETL/Tests/Comparator/RowsComparator.php | 60 + .../Context/RowsSerializationContext.php | 31 + .../ETL/Tests/Double/AcceptingBackend.php | 32 + .../Tests/Double/AcceptingColumnBuilder.php | 48 + .../AddStampToStringEntryTransformer.php | 3 +- .../ETL/Tests/Double/CountingExtractor.php | 5 +- .../ETL/Tests/Double/DeclaringExtractor.php | 2 +- .../Double/FakeRandomOrdersExtractor.php | 2 +- .../Double/FakeStaticOrdersExtractor.php | 10 +- .../Tests/Double/OneRowBatchesExtractor.php | 4 +- .../ETL/Tests/Double/RepeatableExtractor.php | 2 +- .../Tests/Double/StopIgnoringExtractor.php | 6 +- .../DataFrame/ConfigBuilderTest.php | 12 +- .../Integration/DataFrame/SchemaTest.php | 4 +- .../Extractor/CacheExtractorTest.php | 16 +- .../Function/DOMElementNextSiblingTest.php | 15 +- .../DOMElementPreviousSiblingTest.php | 15 +- .../Tests/Integration/Function/OnEachTest.php | 3 +- .../Flow/ETL/Tests/Mother/ColumnMother.php | 24 + .../ETL/Tests/Mother/DateIntervalMother.php | 30 + .../tests/Flow/ETL/Tests/Mother/XmlMother.php | 18 + .../Tests/Unit/Column/ColumnConcatTest.php | 115 ++ .../Tests/Unit/Column/ColumnEncodeTest.php | 115 ++ .../Tests/Unit/Column/ColumnWithTypeTest.php | 139 ++ .../Tests/Unit/Column/DefaultBackendTest.php | 44 + .../Unit/Column/Php/BooleanLayoutTest.php | 50 + .../ETL/Tests/Unit/Column/Php/BuffersTest.php | 34 + .../Column/Php/CastingColumnBuilderTest.php | 89 + .../Unit/Column/Php/ColumnDecoderTest.php | 67 + .../Unit/Column/Php/ConstantColumnTest.php | 126 ++ .../Unit/Column/Php/DatePhysicalTest.php | 46 + .../Unit/Column/Php/DateTimePhysicalTest.php | 50 + .../Unit/Column/Php/DaysFromCivilTest.php | 26 + .../Unit/Column/Php/EnumPhysicalTest.php | 21 + .../Column/Php/FixedBinary16LayoutTest.php | 40 + .../Unit/Column/Php/Float64LayoutTest.php | 43 + .../Column/Php/HtmlDocumentPhysicalTest.php | 28 + .../Column/Php/HtmlElementPhysicalTest.php | 26 + .../Unit/Column/Php/IdentityPhysicalTest.php | 20 + .../Tests/Unit/Column/Php/Int32LayoutTest.php | 47 + .../Tests/Unit/Column/Php/Int64LayoutTest.php | 47 + .../Tests/Unit/Column/Php/JsonFactoryTest.php | 28 + .../Unit/Column/Php/JsonPhysicalTest.php | 21 + .../Tests/Unit/Column/Php/LayoutForTest.php | 89 + .../Unit/Column/Php/ListColumnBuilderTest.php | 36 + .../Tests/Unit/Column/Php/ListColumnTest.php | 61 + .../Unit/Column/Php/ListPhysicalTest.php | 22 + .../Unit/Column/Php/MapColumnBuilderTest.php | 39 + .../Tests/Unit/Column/Php/MapColumnTest.php | 68 + .../Tests/Unit/Column/Php/MapPhysicalTest.php | 28 + .../Unit/Column/Php/NullColumnBuilderTest.php | 28 + .../Tests/Unit/Column/Php/NullCountTest.php | 17 + .../Unit/Column/Php/NullPhysicalTest.php | 21 + .../ETL/Tests/Unit/Column/Php/OffsetsTest.php | 62 + .../Column/Php/PhysicalBuilderForTest.php | 53 + .../Tests/Unit/Column/Php/PhysicalForTest.php | 136 ++ .../ETL/Tests/Unit/Column/Php/RetypeTest.php | 103 + .../Column/Php/ScalarColumnBuilderTest.php | 42 + .../Unit/Column/Php/ScalarColumnTest.php | 55 + .../Column/Php/StructColumnBuilderTest.php | 36 + .../Unit/Column/Php/StructColumnTest.php | 71 + .../Unit/Column/Php/StructPhysicalTest.php | 37 + .../Unit/Column/Php/TimePhysicalTest.php | 72 + .../Unit/Column/Php/TimeZonePhysicalTest.php | 21 + .../Tests/Unit/Column/Php/Utf8LayoutTest.php | 42 + .../Unit/Column/Php/UuidPhysicalTest.php | 32 + .../Tests/Unit/Column/Php/ValidityTest.php | 73 + .../Column/Php/XmlDocumentPhysicalTest.php | 27 + .../Column/Php/XmlElementPhysicalTest.php | 42 + .../ETL/Tests/Unit/Column/PhpBackendTest.php | 568 ++++++ .../Unit/Comparator/RowComparatorTest.php | 82 + .../Unit/Comparator/RowsComparatorTest.php | 108 + .../Flow/ETL/Tests/Unit/DataFrameTest.php | 19 +- .../Exception/ColumnMismatchExceptionTest.php | 6 + .../Unit/Extractor/ArrayExtractorTest.php | 4 +- .../Unit/Extractor/BatchExtractorTest.php | 28 + .../Tests/Unit/Extractor/InferredRowsTest.php | 10 +- .../Flow/ETL/Tests/Unit/FlowContextTest.php | 3 +- .../Flow/ETL/Tests/Unit/Function/CastTest.php | 3 +- .../Unit/Function/DOMElementParentTest.php | 17 +- .../Tests/Unit/Function/ToDateTimeTest.php | 6 +- .../Unit/Join/HashJoin/RowMergerTest.php | 31 +- .../ETL/Tests/Unit/Join/JoinSchemaTest.php | 21 + .../ETL/Tests/Unit/Join/JoinShapeTest.php | 16 +- .../Unit/Row/AdaptiveRowHydratorTest.php | 62 - .../ETL/Tests/Unit/Row/ArrayToRowTest.php | 19 +- .../ETL/Tests/Unit/Row/HydratedBatchTest.php | 163 -- .../ETL/Tests/Unit/Row/InferredBatchTest.php | 61 +- .../Tests/Unit/Row/NativeRowHydratorTest.php | 742 ------- .../ETL/Tests/Unit/Row/PhpRowHydratorTest.php | 310 ++- .../ETL/Tests/Unit/Row/RowRenamingTest.php | 33 - .../ETL/Tests/Unit/Row/RowsBufferTest.php | 18 +- .../etl/tests/Flow/ETL/Tests/Unit/RowTest.php | 238 +-- .../ETL/Tests/Unit/Rows/ArrayToRowsTest.php | 14 +- .../ETL/Tests/Unit/Rows/RowsBuilderTest.php | 286 +++ .../ETL/Tests/Unit/RowsSerializationTest.php | 161 ++ .../tests/Flow/ETL/Tests/Unit/RowsTest.php | 477 ++++- .../Schema/Definition/ZoneAlignmentTest.php | 107 - .../Formatter/InlineSchemaFormatterTest.php | 35 + .../Flow/ETL/Tests/Unit/Schema/SchemaTest.php | 10 - .../Unit/Serializer/DomValueCodecTest.php | 174 -- .../Unit/Transformer/DerivedColumnsTest.php | 30 +- .../NestedExpandTransformerTest.php | 3 +- .../Unit/Transformer/NestedExpansionTest.php | 15 - .../RenameEntryTransformerTest.php | 11 + .../SerializedPayloadDecoderTest.php | 34 +- .../Unit/Transformer/UnpackedColumnsTest.php | 4 +- .../UnserializeTransformerTest.php | 17 + ...EngineContext.php => FloeFilesContext.php} | 16 +- .../Floe/Tests/Context/FloeGoldenContext.php | 4 +- .../Tests/Context/FloeStreamReaderContext.php | 6 +- .../Flow/Floe/Tests/Double/SpyHydrator.php | 6 +- .../Tests/Fixtures/v2/all-entry-types.floe | Bin 3537 -> 3527 bytes .../Tests/Integration/FloeDataFrameTest.php | 32 +- .../Floe/Tests/Integration/FloeGoldenTest.php | 10 +- .../Tests/Integration/FloeHardBreakTest.php | 4 +- .../FloePreAllowExtraRemovalTest.php | 22 +- .../FloeReaderExtensionParityTest.php | 207 -- .../Integration/FloeWriteContractTest.php | 102 +- .../FloeWriterExtensionParityTest.php | 165 -- .../Flow/Floe/Tests/Mother/RowsMother.php | 2 +- .../Flow/Floe/Tests/Unit/FloeEngineTest.php | 54 - .../Floe/Tests/Unit/FloeExtractorTest.php | 36 +- .../Flow/Floe/Tests/Unit/FloeLoaderTest.php | 16 - .../Flow/Floe/Tests/Unit/FloeReaderTest.php | 16 +- .../Floe/Tests/Unit/FloeSourceFileTest.php | 14 +- .../Floe/Tests/Unit/FloeStreamReaderTest.php | 125 -- .../Floe/Tests/Unit/FloeStreamWriterTest.php | 143 -- .../Tests/Unit/FloeValueRoundTripTest.php | 2 +- .../Floe/Tests/Unit/NativeFloeEncoderTest.php | 215 -- src/extension/flow-php-ext/README.md | 7 +- .../tests/phpt/002_scalar_round_trip.phpt | 47 - .../tests/phpt/003_null_flags.phpt | 42 - .../flow-php-ext/tests/phpt/004_datetime.phpt | 56 - .../tests/phpt/005_time_uuid.phpt | 57 - .../phpt/006_schema_change_mid_stream.phpt | 32 - .../tests/phpt/007_empty_rows.phpt | 22 - .../flow-php-ext/tests/phpt/010_no_leaks.phpt | 114 -- .../tests/phpt/011_containers.phpt | 93 - .../tests/phpt/012_enum_json_date.phpt | 67 - .../tests/phpt/013_xml_fallback.phpt | 42 - .../tests/phpt/016_numeric_string_keys.phpt | 70 - .../tests/phpt/017_rows_decoder.phpt | 51 - .../tests/phpt/019_html_fallback.phpt | 40 - .../tests/phpt/020_row_encoder_parity.phpt | 102 - .../tests/phpt/021_batched_decode.phpt | 79 - .../phpt/022_row_encoder_round_trip.phpt | 79 - .../phpt/023_encoder_datetime_subclass.phpt | 31 - .../tests/phpt/024_row_hydrator_parity.phpt | 137 -- .../tests/phpt/025_hydrator_no_leaks.phpt | 92 - .../phpt/026_row_hydrator_cast_parity.phpt | 341 ---- .../phpt/027_cast_fallback_exceptions.phpt | 133 -- .../tests/phpt/028_cast_no_leaks.phpt | 129 -- .../030_encode_typed_object_class_check.phpt | 45 - .../tests/phpt/031_structure_v2_guards.phpt | 51 - .../032_structure_numeric_name_parity.phpt | 43 - .../phpt/034_floe_encoder_nullability.phpt | 60 - .../phpt/035_list_numeric_promotion.phpt | 71 - .../tests/phpt/052_json_cast_parity.phpt | 71 - .../phpt/055_datetime_iso_fast_path.phpt | 207 -- .../tests/phpt/056_fused_decode_rows.phpt | 182 -- .../tests/phpt/057_decode_rows_no_leaks.phpt | 98 - .../058_datetime_from_timestamp_parity.phpt | 133 -- .../tests/phpt/059_encode_frames.phpt | 137 -- .../phpt/060_encode_frames_no_leaks.phpt | 98 - .../tests/phpt/061_date_iso_fast_path.phpt | 114 -- .../phpt/062_datetime_zone_version_skew.phpt | 34 - .../flow-php-ext/tests/phpt/bootstrap.php | 141 +- .../types/src/Flow/Types/Type/Comparator.php | 8 +- .../src/Flow/Types/Type/Logical/DateType.php | 6 +- .../Flow/Types/Type/Logical/StructureType.php | 4 +- src/lib/types/src/Flow/Types/Value/Uuid.php | 28 + .../Tests/Unit/Type/Logical/DateTypeTest.php | 10 + .../Flow/Types/Tests/Unit/Value/UuidTest.php | 27 + web/landing/resources/dsl.json | 2 +- 342 files changed, 12294 insertions(+), 9801 deletions(-) create mode 100644 documentation/upgrading-0.16-0.35.md create mode 100644 documentation/upgrading-0.3-0.8.md create mode 100644 documentation/upgrading-0.35-0.40.md create mode 100644 documentation/upgrading-0.8-0.16.md create mode 100644 src/core/etl/src/Flow/ETL/Column/Backend.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Column.php create mode 100644 src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/DefaultBackend.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/BooleanLayout.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Buffers.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ConstantColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/DatePhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/DateTimePhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/DaysFromCivil.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/EnumPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/FixedBinary16Layout.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Float64Layout.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/IdentityPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Int32Layout.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Int64Layout.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/JsonFactory.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/JsonPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Layout.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/LayoutFor.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ListColumnBuilder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ListPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/MapColumnBuilder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/MapPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/NullColumnBuilder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/NullCount.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/NullPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Offsets.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/PhpColumnBuilder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Physical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/PhysicalBuilderFor.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Retype.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ScalarColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ScalarColumnBuilder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/StructColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/StructColumnBuilder.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/StructPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/TimePhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Utf8Layout.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/UuidPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Validity.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php create mode 100644 src/core/etl/src/Flow/ETL/Column/PhpBackend.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/AdaptiveRowHydrator.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/HydratedBatch.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/NativeRowHydrator.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/RowRenaming.php create mode 100644 src/core/etl/src/Flow/ETL/Rows/RowsBuilder.php delete mode 100644 src/core/etl/src/Flow/ETL/Schema/Definition/ZoneAlignment.php create mode 100644 src/core/etl/src/Flow/ETL/Schema/Formatter/InlineSchemaFormatter.php delete mode 100644 src/core/etl/src/Flow/ETL/Serializer/DomValueCodec.php delete mode 100644 src/core/etl/src/Flow/Floe/FloeEngine.php delete mode 100644 src/core/etl/src/Flow/Floe/NativeFloeEncoder.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Comparator/RowComparator.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Comparator/RowsComparator.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingBackend.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingColumnBuilder.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/ColumnMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/DateIntervalMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/XmlMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnConcatTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnEncodeTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnWithTypeTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BooleanLayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BuffersTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/CastingColumnBuilderTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ConstantColumnTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DatePhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DateTimePhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DaysFromCivilTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/EnumPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/FixedBinary16LayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Float64LayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/IdentityPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int32LayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int64LayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonFactoryTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/LayoutForTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnBuilderTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullColumnBuilderTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullCountTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalBuilderForTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/RetypeTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimePhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonePhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Utf8LayoutTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/UuidPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValidityTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/AdaptiveRowHydratorTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/HydratedBatchTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/NativeRowHydratorTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowRenamingTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Definition/ZoneAlignmentTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Formatter/InlineSchemaFormatterTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Serializer/DomValueCodecTest.php rename src/core/etl/tests/Flow/Floe/Tests/Context/{FloeEngineContext.php => FloeFilesContext.php} (85%) delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Integration/FloeReaderExtensionParityTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriterExtensionParityTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/FloeEngineTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/NativeFloeEncoderTest.php delete mode 100644 src/extension/flow-php-ext/tests/phpt/002_scalar_round_trip.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/003_null_flags.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/004_datetime.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/005_time_uuid.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/006_schema_change_mid_stream.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/007_empty_rows.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/010_no_leaks.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/011_containers.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/012_enum_json_date.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/013_xml_fallback.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/016_numeric_string_keys.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/017_rows_decoder.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/019_html_fallback.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/020_row_encoder_parity.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/021_batched_decode.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/022_row_encoder_round_trip.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/023_encoder_datetime_subclass.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/024_row_hydrator_parity.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/025_hydrator_no_leaks.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/026_row_hydrator_cast_parity.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/027_cast_fallback_exceptions.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/028_cast_no_leaks.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/030_encode_typed_object_class_check.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/031_structure_v2_guards.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/032_structure_numeric_name_parity.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/034_floe_encoder_nullability.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/035_list_numeric_promotion.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/052_json_cast_parity.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/055_datetime_iso_fast_path.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/056_fused_decode_rows.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/057_decode_rows_no_leaks.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/058_datetime_from_timestamp_parity.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/059_encode_frames.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/060_encode_frames_no_leaks.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/061_date_iso_fast_path.phpt delete mode 100644 src/extension/flow-php-ext/tests/phpt/062_datetime_zone_version_skew.phpt diff --git a/benchmarks/src/Format/Floe/FloeReadScenario.php b/benchmarks/src/Format/Floe/FloeReadScenario.php index ed4e408c6f..557bc4d9a3 100644 --- a/benchmarks/src/Format/Floe/FloeReadScenario.php +++ b/benchmarks/src/Format/Floe/FloeReadScenario.php @@ -5,10 +5,7 @@ namespace Flow\Benchmarks\Format\Floe; use Flow\Benchmarks\Datasets\Datasets; -use Flow\ETL\Row\PhpRowHydrator; -use Flow\Floe\FloeEngine; -use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\Floe\DSL\from_floe; @@ -16,17 +13,10 @@ { public function __construct( private int $rows, - private FloeEngine $engine, ) {} public function run(): void { - $config = config_builder(); - - if ($this->engine === FloeEngine::php) { - $config->hydrator(new PhpRowHydrator()); - } - - data_frame($config)->read(from_floe(Datasets::orders($this->rows)->floe(), engine: $this->engine))->run(); + data_frame()->read(from_floe(Datasets::orders($this->rows)->floe()))->run(); } } diff --git a/benchmarks/src/Format/Floe/FloeWriteScenario.php b/benchmarks/src/Format/Floe/FloeWriteScenario.php index 3fb0c64e35..c835ad9e44 100644 --- a/benchmarks/src/Format/Floe/FloeWriteScenario.php +++ b/benchmarks/src/Format/Floe/FloeWriteScenario.php @@ -6,10 +6,7 @@ use Flow\Benchmarks\Datasets\Datasets; use Flow\Benchmarks\Datasets\Paths; -use Flow\ETL\Row\PhpRowHydrator; -use Flow\Floe\FloeEngine; -use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\Floe\DSL\from_floe; use function Flow\Floe\DSL\to_floe; @@ -19,20 +16,13 @@ { public function __construct( private int $rows, - private FloeEngine $engine, ) {} public function run(): void { - $config = config_builder(); - - if ($this->engine === FloeEngine::php) { - $config->hydrator(new PhpRowHydrator()); - } - - data_frame($config) - ->read(from_floe(Datasets::orders($this->rows)->floe(), engine: $this->engine)) - ->write(to_floe(Paths::var() . '/format_write_floe_' . uniqid('', true) . '.floe', engine: $this->engine)) + data_frame() + ->read(from_floe(Datasets::orders($this->rows)->floe())) + ->write(to_floe(Paths::var() . '/format_write_floe_' . uniqid('', true) . '.floe')) ->run(); } } diff --git a/benchmarks/suites/Format/Floe/FloeReadBench.php b/benchmarks/suites/Format/Floe/FloeReadBench.php index e877411b3b..2fc3753998 100644 --- a/benchmarks/suites/Format/Floe/FloeReadBench.php +++ b/benchmarks/suites/Format/Floe/FloeReadBench.php @@ -6,12 +6,9 @@ use Flow\Benchmarks\BenchmarkRows; use Flow\Benchmarks\Datasets\Datasets; -use Flow\Floe\FloeEngine; use Generator; use PhpBench\Attributes as Bench; -use function extension_loaded; - #[Bench\BeforeMethods('warm')] final class FloeReadBench { @@ -20,11 +17,11 @@ public function warm(array $params): void Datasets::orders((int) $params['rows'])->floe(); } - #[Bench\ParamProviders(['rows', 'engines'])] + #[Bench\ParamProviders(['rows'])] #[Bench\Groups(['format', 'format-floe'])] public function bench_floe_read(array $params): void { - (new FloeReadScenario((int) $params['rows'], FloeEngine::from((string) $params['engine'])))->run(); + (new FloeReadScenario((int) $params['rows']))->run(); } public function rows(): Generator @@ -33,13 +30,4 @@ public function rows(): Generator yield number_format($rows) => ['rows' => $rows]; } - - public function engines(): Generator - { - yield 'php' => ['engine' => FloeEngine::php->value]; - - if (extension_loaded('flow_php')) { - yield 'native' => ['engine' => FloeEngine::native->value]; - } - } } diff --git a/benchmarks/suites/Format/Floe/FloeWriteBench.php b/benchmarks/suites/Format/Floe/FloeWriteBench.php index 940b2ab2bc..aaada5f55b 100644 --- a/benchmarks/suites/Format/Floe/FloeWriteBench.php +++ b/benchmarks/suites/Format/Floe/FloeWriteBench.php @@ -6,12 +6,9 @@ use Flow\Benchmarks\BenchmarkRows; use Flow\Benchmarks\Datasets\Datasets; -use Flow\Floe\FloeEngine; use Generator; use PhpBench\Attributes as Bench; -use function extension_loaded; - #[Bench\BeforeMethods('warm')] final class FloeWriteBench { @@ -20,11 +17,11 @@ public function warm(array $params): void Datasets::orders((int) $params['rows'])->floe(); } - #[Bench\ParamProviders(['rows', 'engines'])] + #[Bench\ParamProviders(['rows'])] #[Bench\Groups(['format', 'format-floe'])] public function bench_floe_write(array $params): void { - (new FloeWriteScenario((int) $params['rows'], FloeEngine::from((string) $params['engine'])))->run(); + (new FloeWriteScenario((int) $params['rows']))->run(); } public function rows(): Generator @@ -33,13 +30,4 @@ public function rows(): Generator yield number_format($rows) => ['rows' => $rows]; } - - public function engines(): Generator - { - yield 'php' => ['engine' => FloeEngine::php->value]; - - if (extension_loaded('flow_php')) { - yield 'native' => ['engine' => FloeEngine::native->value]; - } - } } diff --git a/bootstrap.php b/bootstrap.php index f3329ef219..43202e1a42 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -35,3 +35,6 @@ $resolvedCacheDir, )); } + +SebastianBergmann\Comparator\Factory::getInstance()->register(new Flow\ETL\Tests\Comparator\RowsComparator()); +SebastianBergmann\Comparator\Factory::getInstance()->register(new Flow\ETL\Tests\Comparator\RowComparator()); diff --git a/documentation/components/adapters/json.md b/documentation/components/adapters/json.md index 83dd41cb78..065a27a56d 100644 --- a/documentation/components/adapters/json.md +++ b/documentation/components/adapters/json.md @@ -119,8 +119,10 @@ file. | `string` (+ `format: date` / `date-time` / `time` / `uuid` / `html` / `xml`) | `string` / `date` / `datetime` / `time` / `uuid` / `html` / `xml` | | `integer` / `number` / `boolean` / `null` | `integer` / `float` / `boolean` / null column | | `array` + `items` | `list` | +| `array` without `items` | `json` | | `object` + `properties` | `structure` (`required` controls optional members) | | `object` + `additionalProperties: ` | `map` | +| `object` without `properties` / `additionalProperties` | `json` | | `type: ["object", "array"]` | `json` | | empty schema `{}` / boolean schema `true` | `json` (accept anything, marked in metadata) | | `enum` / `const` | scalar type derived from the values, values preserved in metadata | diff --git a/documentation/components/core/building-blocks.md b/documentation/components/core/building-blocks.md index 95ddb96b37..4c1be61c0a 100644 --- a/documentation/components/core/building-blocks.md +++ b/documentation/components/core/building-blocks.md @@ -88,9 +88,9 @@ A column holds exactly one type. `null|T` spells a nullable column, and a nullab structure element; every other union is refused. Declare the widest common type with `str_schema()`, or `json_schema()` when the shape is genuinely dynamic. -The schema is declared, never guessed: `array_to_rows()` takes it as its second argument and a -[Hydrator](/src/core/etl/src/Flow/ETL/Row/Hydrator.php) turns the raw values into `Rows` against it, -casting each one to the type its column declares. A value the declared type refuses aborts the batch +The schema is declared, never guessed: `array_to_rows()` takes it as its second argument and the column backend +([`Backend`](/src/core/etl/src/Flow/ETL/Column/Backend.php)) builds `Rows` against it, casting each value to the type +its column declares. A value the declared type refuses aborts the batch with a `SchemaMismatchException` naming the column and its row. Schema *inference* belongs to the readers, which sample a source and derive a schema from it before any diff --git a/documentation/components/extensions/flow-php-ext.md b/documentation/components/extensions/flow-php-ext.md index fc4281f73c..41ed20abaf 100644 --- a/documentation/components/extensions/flow-php-ext.md +++ b/documentation/components/extensions/flow-php-ext.md @@ -8,19 +8,9 @@ package: flow-php/flow-php-ext [TOC] -Flow stores durable datasets (`to_floe()`) and caches intermediate ones (`DataFrame::cache()`, -sort / join / group-by spill buckets) using the native **Floe** binary format (`.floe`) - the schema -is written once per file and rows carry raw values only, which makes both the payload and the -hydration dramatically cheaper than native PHP `serialize()`/`unserialize()`. - -This extension encodes and decodes Floe **frames** natively in Rust via -[ext-php-rs](https://github.com/extphprs/ext-php-rs). The pure-PHP implementation in `Flow\Floe` -(flow-php/etl) is the canonical behavior reference and works without the extension - loading it is -purely an optimization. File header and footer assembly always stay in PHP. - -> You never need to call this extension directly. `Flow\Floe\FloeReader`/`FloeWriter` - used by -> `from_floe()`/`to_floe()`, the cache and the sort / join / group-by buckets caches - route whole -> batches to it automatically when `extension_loaded('flow_php')` is true. +This extension reads CSV and narrows string columns to their types natively in Rust via +[ext-php-rs](https://github.com/extphprs/ext-php-rs). The pure-PHP implementations in `flow-php/etl` are the canonical +behaviour reference and work without the extension - loading it is purely an optimization. ## Loading the Extension @@ -38,65 +28,20 @@ php -d extension=./ext/modules/flow_php.so your_script.php ## Usage -The extension is used implicitly through the ETL cache: +The extension is used implicitly by the CSV reader: ```php read(from_array($bigDataset)) - ->cache('my-dataset') // serialized with the extension when loaded - ->write(to_stream(__DIR__ . '/output.csv')) + ->read(from_csv(__DIR__ . '/input.csv')) // read natively when the extension is loaded + ->write(to_stream(__DIR__ . '/output.txt')) ->run(); ``` -The extension registers two native classes; the PHP side (`FloeStreamWriter`/`FloeStreamReader`) owns -file framing, sectioning, partitions, footer and - on read - skip/limit/padding, and picks the native -implementation automatically: - -- **`Flow\Floe\RustFloeEncoderNative`** - the Floe ROW frame-body codec: - `encode(list, schemaBody)` returns the encoded frame bodies, - `decode(list, schemaBody)` returns `list`, and - `decodeRows(list, schemaBody, Schema)` decodes and casts straight into `Flow\ETL\Rows` in one pass, and - `encodeFrames(Rows, schemaBody, Schema)` turns `Rows` straight into one string of complete ROW frames - what the - reader and the writer use when the configured hydrator is the native one. The userland wrapper - `Flow\Floe\NativeFloeEncoder` carries the `Flow\Floe\FloeEncoder` interface, and `FloeEngine::adaptive` - the - engine every writer/reader defaults to - builds it over `Flow\Floe\PhpFloeEncoder` when the extension is loaded. -- **`Flow\ETL\Row\RustRowHydratorNative`** - the native `hydrate`/`cast`/`dehydrate` behind - `Flow\ETL\Row\NativeRowHydrator`, which `Flow\ETL\Row\AdaptiveRowHydrator` (the config default) - selects when the extension is loaded - used by adapter loaders and raw-scalar extractors such as - CSV, JSON or XML. `cast(batch, Schema)` casts raw scalars and builds entries in a single native - pass; values outside the proven native subset (and every exotic type such as enum, xml or time) - cast per value through the schema's PHP `Type::cast`, so results and exceptions match - `PhpRowHydrator` exactly. Schema-less `cast` (type inference) stays PHP. Hydrate and cast plans are - cached on the `Schema` object identity and rebuilt only when a different schema arrives. - -All extension failures throw `Flow\Floe\Exception\ExtensionException`; `FloeReader`/`FloeWriter` wrap -it as `Flow\Floe\Exception\FloeException`. There is no silent fallback to the PHP engine. - -## Structure columns across the PHP/Rust boundary - -A structure column crosses to Rust in the schema JSON as tag `structure_v2` with an ordered `fields` -list - one `{name, type, optional}` object per field, `name` always a JSON string (PHP casts integer -element names on `normalize()`). The Rust side reads the list in order; the per-field `optional` flag -is used only by the cast plan (`required = !optional`), never by the encoder or decoder, which emit -and read one flag byte per field in declared order. - -A version-skewed pair fails loudly instead of writing wrong bytes: - -- new `flow-php/etl` with a pre-`structure_v2` extension: - `flow_php does not support values of type "structure_v2" in this build` -- old `flow-php/etl` with a current extension: - `flow_php does not support values of type "structure" in this build` - -Either message means the extension and `flow-php/etl` disagree on the structure schema format: -reinstall one to match the other, or set the Floe engine to `FloeEngine::php` while upgrading. - -Datetime column zones do not fail, they degrade: - -- new `flow-php/etl` with an extension that predates column zones: the extension is ignored and the - PHP engine runs -- old `flow-php/etl` with a current extension: a zone-less `datetime` column keeps that library's - behaviour, each value in its stored zone +The extension registers `Flow\ETL\Adapter\CSV\RustCSVReaderNative` and +`Flow\ETL\Adapter\CSV\RustColumnFoldNative`, used by `Flow\ETL\Adapter\CSV\NativeCSVOpenSource` for CSV reading and +string-type narrowing. The Floe codec and the row hydrator run in PHP until the native column backend lands. diff --git a/documentation/installation/docker.md b/documentation/installation/docker.md index 63286b992f..43ff05d7e4 100644 --- a/documentation/installation/docker.md +++ b/documentation/installation/docker.md @@ -75,7 +75,7 @@ that Flow detects and uses automatically: | Extension | Package | Effect when loaded | |------------|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| -| `flow_php` | [flow-php/flow-php-ext](/documentation/components/extensions/flow-php-ext.md) | `AdaptiveRowHydrator` and the adaptive Floe engine run native, fusing every Floe read/write and every raw-scalar hydration into one native call per batch | +| `flow_php` | [flow-php/flow-php-ext](/documentation/components/extensions/flow-php-ext.md) | the CSV reader and the schema narrower run native | | `arrow` | [flow-php/arrow-ext](/documentation/components/extensions/arrow-ext.md) | `AdaptiveParquetEngine` selects `ArrowParquetEngine`, so Parquet reads and writes run native | | `pg_query` | [flow-php/pg-query-ext](/documentation/components/extensions/pg-query-ext.md) | `Flow\PostgreSql\Parser` becomes usable at all - SQL parsing, normalization and AST manipulation | | `protobuf` | `pecl/protobuf` | `Flow\PostgreSql\Parser` decodes the parse tree in C instead of pure PHP - measured ~69x faster end to end | @@ -90,22 +90,20 @@ that Flow detects and uses automatically: ### Opting out of the native path -Engine selection happens per read and per write, so a single step can be pinned to the PHP implementation: +Parquet engine selection happens per read: ```php hydrator(new PhpRowHydrator())) +return data_frame() ->read(from_parquet(__DIR__ . '/input.parquet', engine: new PhpParquetEngine())) - ->write(to_floe(__DIR__ . '/output.floe', engine: FloeEngine::php)); + ->write(to_floe(__DIR__ . '/output.floe')); ``` To take the whole container off one native path, mount an empty file over that extension's ini: diff --git a/documentation/upgrading-0.16-0.35.md b/documentation/upgrading-0.16-0.35.md new file mode 100644 index 0000000000..1ffcf62b98 --- /dev/null +++ b/documentation/upgrading-0.16-0.35.md @@ -0,0 +1,414 @@ +# Upgrade Guide 0.16.x - 0.35.x + +[TOC] + +This document provides guidelines for upgrading between versions of Flow PHP. Please follow the instructions for your +specific version to ensure a smooth upgrade process. + +Upgrading from older versions: [0.8.x to 0.16.x](/documentation/upgrading-0.8-0.16.md) + +--- + +## Upgrading from 0.34.x to 0.35.x + +### 1) `flow-php/postgresql` - `DataType` renamed to `ColumnType` + +The `DataType` class used for schema/DDL definitions has been renamed to `ColumnType` to better communicate its purpose. +All related DSL functions have been renamed from `data_type_*` to `column_type_*`. + +| Removed | Replacement | +|------------------------------------------------|--------------------------------------------------| +| `Flow\PostgreSql\QueryBuilder\Schema\DataType` | `Flow\PostgreSql\QueryBuilder\Schema\ColumnType` | +| `Flow\PostgreSql\Parser\DataTypeParser` | `Flow\PostgreSql\Parser\ColumnTypeParser` | +| `data_type_integer()` | `column_type_integer()` | +| `data_type_smallint()` | `column_type_smallint()` | +| `data_type_bigint()` | `column_type_bigint()` | +| `data_type_boolean()` | `column_type_boolean()` | +| `data_type_text()` | `column_type_text()` | +| `data_type_varchar()` | `column_type_varchar()` | +| `data_type_char()` | `column_type_char()` | +| `data_type_numeric()` | `column_type_numeric()` | +| `data_type_decimal()` | `column_type_decimal()` | +| `data_type_real()` | `column_type_real()` | +| `data_type_double_precision()` | `column_type_double_precision()` | +| `data_type_date()` | `column_type_date()` | +| `data_type_time()` | `column_type_time()` | +| `data_type_timestamp()` | `column_type_timestamp()` | +| `data_type_timestamptz()` | `column_type_timestamptz()` | +| `data_type_interval()` | `column_type_interval()` | +| `data_type_uuid()` | `column_type_uuid()` | +| `data_type_json()` | `column_type_json()` | +| `data_type_jsonb()` | `column_type_jsonb()` | +| `data_type_bytea()` | `column_type_bytea()` | +| `data_type_inet()` | `column_type_inet()` | +| `data_type_cidr()` | `column_type_cidr()` | +| `data_type_macaddr()` | `column_type_macaddr()` | +| `data_type_serial()` | `column_type_serial()` | +| `data_type_smallserial()` | `column_type_smallserial()` | +| `data_type_bigserial()` | `column_type_bigserial()` | +| `data_type_array()` | `column_type_array()` | +| `data_type_custom()` | `column_type_custom()` | +| `data_type_from_string()` | `column_type_from_string()` | + +Before: + +```php +use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use function Flow\PostgreSql\DSL\data_type_integer; +use function Flow\PostgreSql\DSL\data_type_varchar; + +column('age', data_type_integer()); +column('name', data_type_varchar(255)); +cast(ref('id'), DataType::bigint()); +``` + +After: + +```php +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; +use function Flow\PostgreSql\DSL\column_type_integer; +use function Flow\PostgreSql\DSL\column_type_varchar; + +column('age', column_type_integer()); +column('name', column_type_varchar(255)); +cast(ref('id'), ColumnType::bigint()); +``` + +### 2) `flow-php/postgresql` - `PostgreSqlType` renamed to `ValueType` + +The `PostgreSqlType` enum used for value binding/casting has been renamed to `ValueType` to better communicate its +purpose. All related DSL functions have been renamed from `pgsql_type_*` to `value_type_*`. + +| Removed | Replacement | +|-----------------------------------------------|------------------------------------------| +| `Flow\PostgreSql\Client\Types\PostgreSqlType` | `Flow\PostgreSql\Client\Types\ValueType` | +| `pgsql_type_text()` | `value_type_text()` | +| `pgsql_type_varchar()` | `value_type_varchar()` | +| `pgsql_type_integer()` | `value_type_integer()` | +| `pgsql_type_bigint()` | `value_type_bigint()` | +| `pgsql_type_smallint()` | `value_type_smallint()` | +| `pgsql_type_boolean()` | `value_type_boolean()` | +| `pgsql_type_float4()` | `value_type_float4()` | +| `pgsql_type_float8()` | `value_type_float8()` | +| `pgsql_type_numeric()` | `value_type_numeric()` | +| `pgsql_type_date()` | `value_type_date()` | +| `pgsql_type_timestamp()` | `value_type_timestamp()` | +| `pgsql_type_timestamptz()` | `value_type_timestamptz()` | +| `pgsql_type_json()` | `value_type_json()` | +| `pgsql_type_jsonb()` | `value_type_jsonb()` | +| `pgsql_type_uuid()` | `value_type_uuid()` | +| `pgsql_type_bytea()` | `value_type_bytea()` | +| `pgsql_type_inet()` | `value_type_inet()` | +| `pgsql_type_cidr()` | `value_type_cidr()` | +| All other `pgsql_type_*()` functions | Corresponding `value_type_*()` functions | + +Before: + +```php +use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\pgsql_type_uuid; +use function Flow\PostgreSql\DSL\pgsql_type_text_array; + +typed('550e8400-e29b-41d4-a716-446655440000', pgsql_type_uuid()); +typed(['tag1', 'tag2'], pgsql_type_text_array()); +typed(42, PostgreSqlType::INT4); +``` + +After: + +```php +use Flow\PostgreSql\Client\Types\ValueType; +use function Flow\PostgreSql\DSL\value_type_uuid; +use function Flow\PostgreSql\DSL\value_type_text_array; + +typed('550e8400-e29b-41d4-a716-446655440000', value_type_uuid()); +typed(['tag1', 'tag2'], value_type_text_array()); +typed(42, ValueType::INT4); +``` + +--- + +## Upgrading from 0.31.x to 0.32.x + +### 1) Removal of Meilisearch Adapter + +The Meilisearch adapter has been removed from Flow PHP. If you were using it, please migrate to Elasticsearch adapter. + +### 2) Removed deprecated DSL functions + +All type-related DSL functions have been moved from `Flow\ETL\DSL` to `Flow\Types\DSL`. Update your imports accordingly. + +| Removed Function | Replacement | +|---------------------------|-------------------------------------------| +| `chunks_from()` | `batches()` | +| `type_structure()` | `\Flow\Types\DSL\type_structure()` | +| `type_union()` | `\Flow\Types\DSL\type_union()` | +| `type_optional()` | `\Flow\Types\DSL\type_optional()` | +| `type_from_array()` | `\Flow\Types\DSL\type_from_array()` | +| `is_nullable()` | `\Flow\Types\DSL\type_is_nullable()` | +| `type_equals()` | `\Flow\Types\DSL\type_equals()` | +| `types()` | `\Flow\Types\DSL\types()` | +| `type_list()` | `\Flow\Types\DSL\type_list()` | +| `type_map()` | `\Flow\Types\DSL\type_map()` | +| `type_json()` | `\Flow\Types\DSL\type_json()` | +| `type_datetime()` | `\Flow\Types\DSL\type_datetime()` | +| `type_date()` | `\Flow\Types\DSL\type_date()` | +| `type_time()` | `\Flow\Types\DSL\type_time()` | +| `type_xml()` | `\Flow\Types\DSL\type_xml()` | +| `type_xml_element()` | `\Flow\Types\DSL\type_xml_element()` | +| `type_uuid()` | `\Flow\Types\DSL\type_uuid()` | +| `type_int()` | `\Flow\Types\DSL\type_integer()` | +| `type_integer()` | `\Flow\Types\DSL\type_integer()` | +| `type_string()` | `\Flow\Types\DSL\type_string()` | +| `type_float()` | `\Flow\Types\DSL\type_float()` | +| `type_boolean()` | `\Flow\Types\DSL\type_boolean()` | +| `type_instance_of()` | `\Flow\Types\DSL\type_instance_of()` | +| `type_resource()` | `\Flow\Types\DSL\type_resource()` | +| `type_array()` | `\Flow\Types\DSL\type_array()` | +| `type_callable()` | `\Flow\Types\DSL\type_callable()` | +| `type_null()` | `\Flow\Types\DSL\type_null()` | +| `type_enum()` | `\Flow\Types\DSL\type_enum()` | +| `struct_schema()` | `structure_schema()` | +| `get_type()` | `\Flow\Types\DSL\get_type()` | +| `print_schema()` | `schema_to_ascii()` | +| `type_is()` | `\Flow\Types\DSL\type_is()` | +| `type_is_any()` | `\Flow\Types\DSL\type_is_any()` | +| `dom_element_to_string()` | `\Flow\Types\DSL\dom_element_to_string()` | + +### 3) Removed deprecated DataFrame methods + +| Removed Method | Replacement | +|----------------------------------------|--------------------------------------------------------------| +| `DataFrame::validate()` | `DataFrame::match()` | +| `DataFrame::renameAll()` | `DataFrame::renameEach(rename_replace(...))` | +| `DataFrame::renameAllLowerCase()` | `DataFrame::renameEach(rename_style(StringStyles::LOWER))` | +| `DataFrame::renameAllUpperCase()` | `DataFrame::renameEach(rename_style(StringStyles::UPPER))` | +| `DataFrame::renameAllUpperCaseFirst()` | `DataFrame::renameEach(rename_style(StringStyles::UCFIRST))` | +| `DataFrame::renameAllUpperCaseWord()` | `DataFrame::renameEach(rename_style(StringStyles::UCWORDS))` | +| `DataFrame::renameAllStyle()` | `DataFrame::renameEach(rename_style(...))` | + +### 4) Removed deprecated Schema methods + +| Removed Method | Replacement | +|---------------------------|-------------------------------| +| `Schema::entries()` | `Schema::references()->all()` | +| `Schema::getDefinition()` | `Schema::get()` | +| `Schema::nullable()` | `Schema::makeNullable()` | + +### 5) Removed deprecated Definition methods + +| Removed Method | Replacement | +|--------------------------|------------------------------| +| `Definition::nullable()` | `Definition::makeNullable()` | + +This applies to all Definition implementations: `BooleanDefinition`, `DateDefinition`, `DateTimeDefinition`, +`EnumDefinition`, `FloatDefinition`, `HTMLDefinition`, `HTMLElementDefinition`, `IntegerDefinition`, `JsonDefinition`, +`ListDefinition`, `MapDefinition`, `StringDefinition`, `StructureDefinition`, `TimeDefinition`, `UuidDefinition`, +`XMLDefinition`, `XMLElementDefinition`. + +### 6) Removed deprecated FileExtractor and PathFiltering methods + +| Removed Method | Replacement | +|------------------------------|-----------------------------------| +| `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 | +|----------------------------------------------|---------------------------------------------------| +| `ScalarFunctionChain::domElementAttribute()` | `ScalarFunctionChain::domElementAttributeValue()` | + +### 8) Removed deprecated Config constants + +| Removed Constant | Replacement | +|-------------------------------|-----------------------------------| +| `Config::CACHE_DIR_ENV` | `CacheConfig::CACHE_DIR_ENV` | +| `Config::SORT_MAX_MEMORY_ENV` | `SortConfig::SORT_MAX_MEMORY_ENV` | + +### 9) Removed deprecated Transformers + +| Removed Transformer | Replacement | +|-----------------------------------------|--------------------------------------------------| +| `EntryNameStyleConverterTransformer` | Use `DataFrame::renameEach(rename_style(...))` | +| `RenameAllCaseTransformer` | Use `DataFrame::renameEach(rename_style(...))` | +| `RenameStrReplaceAllEntriesTransformer` | Use `DataFrame::renameEach(rename_replace(...))` | + +### 10) Removed deprecated classes + +| Removed Class | Replacement | +|-------------------------------------------------|--------------------------------| +| `Flow\ETL\Function\StyleConverter\StringStyles` | `Flow\ETL\String\StringStyles` | + +--- + +## Upgrading from 0.28.x to 0.29.x + +### 1) JsonType now uses Json value object instead of string + +The `JsonType` has been refactored to use a dedicated `Json` value object (similar to `Uuid`/`UuidType` pattern). This +allows static analysis tools to distinguish between regular strings and JSON strings. + +**Breaking Changes:** + +- `JsonType::assert()` now returns `Json` instance instead of `string` +- `JsonType::cast()` now returns `Json` instance instead of `string` +- `JsonType::isValid()` now checks for `Json` instance (plain strings are no longer valid) +- `Cast::cast('json', $value)` function now returns `Json` object instead of string +- `type_json()` return type annotation changed from `Type` to `Type` +- `JsonEntry::value()` now returns `?Json` instead of `?array` (consistent with `UuidEntry::value()` returning `?Uuid`) +- `JsonEntry::json()` method removed (use `value()` instead) + +**Migration:** + +If you were using `type_json()->cast($value)` and expected a string, use `->toString()`: + +Before: + +```php +$jsonString = type_json()->cast($array); // was string +``` + +After: + +```php +$json = type_json()->cast($array); // now Json object +$jsonString = $json->toString(); // get the string +$jsonArray = $json->toArray(); // get as array +``` + +If you were using `JsonEntry::value()` and expected an array: + +Before: + +```php +$entry = json_entry('data', ['key' => 'value']); +$array = $entry->value(); // was array +``` + +After: + +```php +$entry = json_entry('data', ['key' => 'value']); +$json = $entry->value(); // now Json object +$array = $json?->toArray(); // get as array +$string = $json?->toString(); // get as string +``` + +If you were using `JsonEntry::json()`: + +Before: + +```php +$json = $entry->json(); +``` + +After: + +```php +$json = $entry->value(); // json() method removed, use value() instead +``` + +**New Json value object features:** + +```php +use Flow\Types\Value\Json; + +// Create from string +$json = new Json('{"key": "value"}'); + +// Create from array +$json = Json::fromArray(['key' => 'value']); + +// Check if valid JSON +Json::isValid('{"key": "value"}'); // true + +// Convert to string/array +$json->toString(); // '{"key":"value"}' +$json->toArray(); // ['key' => 'value'] + +// Json implements Stringable +(string) $json; // '{"key":"value"}' + +// Json implements JsonSerializable +json_encode($json); // '{"key":"value"}' +``` + +**Note:** `JsonEntry::value()` now returns `?Json` for consistency with `UuidEntry::value()` returning `?Uuid`. Use +`->toArray()` or `->toString()` on the Json object to get the underlying data. + +**Row methods behavior:** + +```php +// Row::toArray() converts Json to array automatically (for convenient serialization) +$row->toArray(); // Returns ['data' => ['key' => 'value']] not ['data' => Json(...)] + +// Row::valueOf() returns the raw value (Json object for json entries) +$row->valueOf('data'); // Returns Json object (use ->toArray() if you need array) + +// Entry value() returns the typed value +$row->get('data')->value(); // Returns Json object (use ->toArray() if you need array) +``` + +--- + +## Upgrading from 0.26.x to 0.27.x + +### 1) Force `EntryFactory $entryFactory` to be required on `array_to_row` & `array_to_row(s)` + +Before: + +```php +to_entry('name', 'data'); +array_to_row([]); +array_to_rows([]); +``` + +After: + +```php +to_entry('name', 'data', flow_context(config())->entryFactory()); +array_to_row([], flow_context(config())->entryFactory()); +array_to_rows([], flow_context(config())->entryFactory()); +``` + +--- + +## Upgrading from 0.16.x to 0.17.x + +### 1) Removed $nullable property from all types + +Before: + +```php +type_string(nullable:true)->toString() // ?string +``` + +After: + +```php +type_optional(string())->toString() // ?string +``` + +### 2) Removed precision from `float_type()` + +Before `float_type()` use to have default precision 6. This means that any operations on float had to round values to +given precision. The problem with this approach is that all operations now need to receive a dedicated rounding option. + +Instead, end users should handle precision of float columns through `round()` scalar function. + +### 3) Moved all Types to `Flow\Types\Type` namespace + +Before + +```php +\Flow\ETL\DSL\type_string(); // now deprecated, alias for \Flow\Types\DSL\type_string(); +``` + +After + +```php +\Flow\Types\DSL\type_string(); +``` diff --git a/documentation/upgrading-0.3-0.8.md b/documentation/upgrading-0.3-0.8.md new file mode 100644 index 0000000000..2ca4797ef5 --- /dev/null +++ b/documentation/upgrading-0.3-0.8.md @@ -0,0 +1,368 @@ +# Upgrade Guide 0.3.x - 0.8.x + +[TOC] + +This document provides guidelines for upgrading between versions of Flow PHP. Please follow the instructions for your +specific version to ensure a smooth upgrade process. + +--- + +## Upgrading from 0.7.x to 0.8.x + +### 1) Joins + +To support joining bigger datasets, we had to move from initial NestedLoop join algorithm into Hash Join algorithm. + +- the only supported coin expression is `=` (equals) that can be grouped with `AND` and `OR` operators. +- `joinPrefix` is now always required, and by default is set to 'joined_' +- join will always result all columns from both datasets, columns used in join condition will be prefixed with + `joinPrefix`. + +Other than that, API stays the same. + +Above changes were introduced in all 3 types of joins: + +- `DataFrame::join()` +- `DataFrame::joinEach()` +- `DataFrame::crossJoin()` + +### 2) GroupBy + +From now on, `DataFrame::groupBy()` method will return `GroupedDataFrame` object, which is nothing more than a GroupBy +statement Builder. To get the results, you first need to define the aggregation functions or optionally pivot the data. + +--- + +## Upgrading from 0.6.x to 0.7.x + +### 1) DataFrame::appendSafe () method was removed + +`DataFrame::appendSafe()` aka `DataFrame::threadSafe()` method was removed as it was introducing additional complexity +and was not used in any of the adapters. + +--- + +## Upgrading from 0.5.x to 0.6.x + +### 1) Rows::merge () accepts single instance of Rows + +Before: + +```php +Rows::merge(Rows ...$rows) : Rows +``` + +After: + +```php +Rows::merge(Rows $rows) : Rows +``` + +--- + +## Upgrading from 0.4.x to 0.5.x + +### 1) Entry factory moved from extractors to `FlowContext` + +To improve code quality and reduce code coupling `EntryFactory` was removed from all constructors of extractors, in +favor of passing it into `FlowContext` & re-using same entry factory in a whole pipeline. + +### 2) Invalid schema has no fallback in `NativeEntryFactory` + +Before, passing `Schema` into `NativeEntryFactory::create()` had fallback when the given entry was not found in a passed +schema, now the schema has higher priority & fallback is no longer available, instead when the definition is missing in +a passed schema, `InvalidArgumentException` will be thrown. + +### 3) BufferLoader was removed + +BufferLoader was removed in favor of `DataFrame::collect(int $batchSize = null)` method which now accepts additional +argument `$batchSize` that will keep collecting Rows from Extractor until the given batch size is reached. Which does +exactly the same thing as BufferLoader did, but in a more generic way. + +### 4) Pipeline Closure + +Pipeline Closure was reduced to be only Loader Closure and it was moved to \Flow\ETL\Loader namespace. Additionally, +\Closure::close method no longer requires Rows to be passed as an argument. + +### 5) Parallelize + +DataFrame::parallelize () method is deprecated, and it will be removed, instead use DataFrame::batchSize (int $size) +method. + +### 6) Rows in batch - Extractors + +From now, file-based Extractors will always throw one Row at time, in order to merge them into bigger groups use +`DataFrame::batchSize(int $size)` just after extractor method. + +Before: + +```php +read(CSV::from(__DIR__ . '/1_mln_rows.csv', rows_in_batch: 100)) + ->write(To::output()) + ->count(); +``` + +After: + +```php +(new Flow()) + ->read(CSV::from(__DIR__ . '/1_mln_rows.csv',)) + ->batchSize(100) + ->write(To::output()) + ->count(); +``` + +Affected extractors: + +- CSV +- Parquet +- JSON +- Text +- XML +- Avro +- DoctrineDBAL - `rows_in_batch` wasn't removed, but now results are thrown row by row, instead of whole page. +- GoogleSheet + +### 7) `GoogleSheetExtractor` + +Argument `$rows_in_batch` was renamed to `$rows_per_page` which no longer determines the size of the batch, but the size +of the page that will be fetched from Google API. Rows are yielded one by one. + +### 8) `DataFrame::threadSafe()` method was replaced by `DataFrame::appendSafe()` + +`DataFrame::appendSafe()` is doing exactly the same thing as the old method, it's just more descriptive and +self-explanatory. It's no longer mandatory to set this flat to true when using SaveMode::APPEND, it's now set +automatically. + +### 9) Loaders - chunk size + +Loaders are no longer accepting chunk_size parameter, from now in order to control the number of rows saved at once use +`DataFrame::batchSize(int $size)` method. + +### 10) Removed DSL functions: `datetime_string()`, `json_string()` + +Those functions were removed in favor of accepting string values in related DSL functions: + +- `datetime_string()` => `datetime()`, +- `json_string()` => `json()` & `json_object()` + +### 11) Removed Asynchronous Processing + +More details can be found in [this issue](https://github.com/flow-php/flow/issues/793). + +- Removed etl-adapter-amphp +- Removed etl-adapter-reactphp +- Removed `LocalSocketPipeline` +- Removed `DataFrame::pipeline()` + +### 12) `CollectionEntry` removal + +After adding native & logical types into the Flow, we remove the `CollectionEntry` as obsolete. New types that cover it +better are: `ListType`, `MapType` & `StructureType` along with related new entry types. + +### 13) Removed `from*()` methods from scalar entries + +Removed `BooleanEntry::from()`, `FloatEntry::from()`, `IntegerEntry::from()`, `StringEntry::fromDateTime()` methods in +favor of using DSL functions. + +### 14) Removed deprecated `Sha1IdFactory` + +Class `Sha1IdFactory` was removed, use `HashIdFactory` class: + +```php +(new HashIdFactory('entry_name'))->withAlgorithm('sha1'); +``` + +### 15) Deprecate DSL Static classes + +DSL static classes were deprecated in favor of using functions defined in `src/core/etl/src/Flow/ETL/DSL/functions.php` +file. + +Deprecated classes: + +- `src/core/etl/src/Flow/ETL/DSL/From.php` +- `src/core/etl/src/Flow/ETL/DSL/Handler.php` +- `src/core/etl/src/Flow/ETL/DSL/To.php` +- `src/core/etl/src/Flow/ETL/DSL/Transform.php` +- `src/core/etl/src/Flow/ETL/DSL/Partitions.php` +- `src/adapter/etl-adapter-avro/src/Flow/ETL/DSL/Avro.php` +- `src/adapter/etl-adapter-chartjs/src/Flow/ETL/DSL/ChartJS.php` +- `src/adapter/etl-adapter-csv/src/Flow/ETL/DSL/CSV.php` +- `src/adapter/etl-adapter-doctrine/src/Flow/ETL/DSL/Dbal.php` +- `src/adapter/etl-adapter-elasticsearch/src/Flow/ETL/DSL/Elasticsearch.php` +- `src/adapter/etl-adapter-google-sheet/src/Flow/ETL/DSL/GoogleSheet.php` +- `src/adapter/etl-adapter-json/src/Flow/ETL/DSL/Json.php` +- `src/adapter/etl-adapter-meilisearch/src/Flow/ETL/DSL/Meilisearch.php` +- `src/adapter/etl-adapter-parquet/src/Flow/ETL/DSL/Parquet.php` +- `src/adapter/etl-adapter-text/src/Flow/ETL/DSL/Text.php` +- `src/adapter/etl-adapter-xml/src/Flow/ETL/DSL/XML.php` + +--- + +## Upgrading from 0.3.x to 0.4.x + +### 1) Transformers replaced with scalar functions + +Transformers are a really powerful tool that was used in Flow since the beginning, but that tool was too powerful for +the simple cases that were needed, and introduced additional complexity and maintenance issues when they were +handwritten. + +We reworked most of the internal transformers to new scalar functions and entry scalar functions (based on the built-in +functions), and we still internally use that powerful tool, but we don't expose it to end users, instead, we provide +easy-to-use, covering all user needs functions. + +All available functions can be found in [`ETL\Row\Function` folder](src/core/etl/src/Flow/ETL/Function) or in [ +`ETL\DSL\functions` file](src/core/etl/src/Flow/ETL/DSL/functions.php), and entry scalar functions are defined in +`EntryScalarFunction`. + +Before: + +```php +read(new MemoryExtractor()) + ->rows(Transform::string_concat(['name', 'last name'], ' ', 'name')) +``` + +After: + +```php +read(new MemoryExtractor()) + ->withEntry('name', concat(ref('name'), lit(' '), ref('last name'))) +``` + +### 2) `ref` function nullability + +`ref("entry_name")` is no longer returning null when the entry is not found. Instead, it throws an exception. The same +behavior can be achieved through using a newly introduced `optional` function: + +Before: + +```php +cast('string'); +``` + +After: + +```php +cast('string'); +// or +optional(ref('non_existing_column')->cast('string')); +``` + +### 3) Extractors output + +Affected extractors: + +* CSV +* JSON +* Avro +* DBAL +* GoogleSheet +* Parquet +* Text +* XML + +Extractors are no longer returning data under an array entry called `row`, thanks to this unpacking row become +redundant. + +Because of that all DSL functions are no longer expecting `$entry_row_name` parameter, if it was used anywhere, please +remove it. + +Before: + +```php +read(From::array([['id' => 1, 'array' => ['a' => 1, 'b' => 2, 'c' => 3]]])) + ->withEntry('row', ref('row')->unpack()) + ->renameAll('row.', '') + ->drop('row') + ->withEntry('array', ref('array')->arrayMerge(lit(['d' => 4]))) + ->write(To::memory($memory = new ArrayMemory())) + ->run(); +``` + +After: + +```php +read(From::array([['id' => 1, 'array' => ['a' => 1, 'b' => 2, 'c' => 3]]])) + ->withEntry('array', ref('array')->arrayMerge(lit(['d' => 4]))) + ->write(To::memory($memory = new ArrayMemory())) + ->run(); +``` + +### 4) ConfigBuilder::putInputIntoRows () output is now prefixed with _ (underscore) + +In order to avoid collisions with datasets columns, additional columns created after using putInputIntoRows () +would now be prefixed with `_` (underscore) symbol. + +Before: + +```php +putInputIntoRows())) + ->read(Json::from(__DIR__ . '/../Fixtures/timezones.json', 5)) + ->fetch(); + +foreach ($rows as $row) { + $this->assertSame( + [ + ... + '_input_file_uri', + ], + \array_keys($row->toArray()) + ); +} +``` + +After: + +```php +putInputIntoRows())) + ->read(Json::from(__DIR__ . '/../Fixtures/timezones.json', 5)) + ->fetch(); + +foreach ($rows as $row) { + $this->assertSame( + [ + ... + '_input_file_uri', + ], + \array_keys($row->toArray()) + ); +} +``` diff --git a/documentation/upgrading-0.35-0.40.md b/documentation/upgrading-0.35-0.40.md new file mode 100644 index 0000000000..5f7ce54a62 --- /dev/null +++ b/documentation/upgrading-0.35-0.40.md @@ -0,0 +1,739 @@ +# Upgrade Guide 0.35.x - 0.40.x + +[TOC] + +This document provides guidelines for upgrading between versions of Flow PHP. Please follow the instructions for your +specific version to ensure a smooth upgrade process. + +Upgrading from older versions: [0.16.x to 0.35.x](/documentation/upgrading-0.16-0.35.md) + +--- + +## Upgrading from 0.39.x to 0.40.x + +### 1) `flow-php/postgresql` - column and domain defaults are modeled as `ColumnDefault` + +| Before | After | +|---------------------------------------------------------------|-----------------------------------------------------------------------------| +| `Column::$default` / `Domain::$default` type `?string` | `?Flow\PostgreSql\Schema\ColumnDefault` | +| `new Column('c', $type, true, "'0'")` | `new Column('c', $type, true, ColumnDefault::fromExpression("'0'", $type))` | +| `$column->default` (string) | `$column->default?->literal` / `$column->default?->applicableSql()` | +| `ColumnShape['default']` / `DomainShape['default']` `?string` | `?array{literal: string, type: ?ColumnTypeShape, kind: string}` | + +`Column::create()` / `Domain::create()` still accept `bool|float|int|string|Expression|null`. Schema arrays serialized +by `Column::normalize()` / `Domain::normalize()` before 0.40 must be regenerated - `fromArray()` reads the nested +`default` shape only. + +### 2) `flow-php/telemetry` - Log severity filtering moved to a pipeline middleware + +| Before | After | +|-----------------------------------------------------------------|-----------------------------------------------------------------------------------------| +| `Flow\Telemetry\Logger\Processor\SeverityFilteringLogProcessor` | `Flow\Telemetry\Logger\Middleware\SeverityFilteringLogMiddleware` | +| `new SeverityFilteringLogProcessor($inner, $minSeverity)` | `new PipelineLogProcessor([new SeverityFilteringLogMiddleware($minSeverity)], $inner)` | +| `severity_filtering_log_processor($processor, $minSeverity)` | `pipeline_log_processor([severity_filtering_log_middleware($minSeverity)], $processor)` | + +The previously wrapped processor is now the pipeline's **sink** and must implement +`Flow\Telemetry\Logger\LogSink` (the built-in `batching`, `pass_through`, `memory`, `void` and `composite` +log processors already do). + +Before: + +```php +$processor = severity_filtering_log_processor( + batching_log_processor($exporter), + Severity::WARN, +); +``` + +After: + +```php +$processor = pipeline_log_processor( + [severity_filtering_log_middleware(Severity::WARN)], + batching_log_processor($exporter), +); +``` + +### 2) `flow-php/symfony-telemetry-bundle` - `severity_filtering` log processor type replaced by `pipeline` + +The `severity_filtering` processor type (with its `inner_processor`) is no longer a `logger_provider` +processor type; it is a middleware inside a `pipeline`. + +Before: + +```yaml +flow_telemetry: + logger_provider: + processor: + type: severity_filtering + minimum_severity: warn + inner_processor: + type: batching + exporter: otlp +``` + +After: + +```yaml +flow_telemetry: + logger_provider: + processor: + type: pipeline + middleware: + - { type: severity_filtering, minimum_severity: warn } + sink: + type: batching + exporter: otlp +``` + +### 3) `flow-php/symfony-telemetry-bundle` - named scope `attributes` split into `scope` and `signal` + +Applies to `tracers`, `meters`, and `loggers`. The `attributes` map is no longer a flat list of scope attributes; scope +attributes move under `attributes.scope`. + +Before: + +```yaml +flow_telemetry: + loggers: + audit: + attributes: + team: checkout +``` + +After: + +```yaml +flow_telemetry: + loggers: + audit: + attributes: + scope: + team: checkout +``` + +### 4) `flow-php/postgresql` - `DateTimeConverter` split into `TimestampConverter` and `TimestampTzConverter` + +| Before | After | +|------------------------------------------------------------|-------------------------------------------------------------------------------| +| `Flow\PostgreSql\Client\Types\Converter\DateTimeConverter` | `TimestampConverter` (`TIMESTAMP`) and `TimestampTzConverter` (`TIMESTAMPTZ`) | +| `typed($value, ValueType::TIMESTAMP)` keeps the offset | `typed($value, ValueType::TIMESTAMP)` normalizes the value to UTC | +| `timestamp` column read as `2024-01-15 10:30:00` | `timestamp` column read as `2024-01-15 10:30:00+00:00` | + +### 5) `flow-php/etl-adapter-postgresql` - `DateTimeEntry` maps to `timestamp` instead of `timestamptz` + +| Flow type | Before | After | +|---------------------------|---------------|-------------| +| `DateTimeEntry` (binding) | `TIMESTAMPTZ` | `TIMESTAMP` | +| `DateTimeType` (DDL) | `timestamptz` | `timestamp` | + +To keep the previous behavior, pass overrides to `EntryTypesMap`: + +```php +to_pgsql_table($client, 'users')->withTypesMap(new EntryTypesMap( + [DateTimeEntry::class => ValueType::TIMESTAMPTZ], + [DateTimeType::class => ColumnType::timestamptz()], +)); +``` + +### 6) `flow-php/symfony-postgresql-messenger` - `messenger_messages` time columns use `timestamp` instead of + +`timestamptz` + +| Column type for `created_at`, `available_at`, `delivered_at` | Before | After | +|--------------------------------------------------------------|---------------|-------------| +| `MessengerCatalogProvider` (DDL) | `timestamptz` | `timestamp` | +| `Connection` bindings | `TIMESTAMPTZ` | `TIMESTAMP` | + +Existing tables, realign the column type (UTC instants preserved): + +```sql +ALTER TABLE messenger_messages + ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC', + ALTER COLUMN available_at TYPE TIMESTAMP USING available_at AT TIME ZONE 'UTC', + ALTER COLUMN delivered_at TYPE TIMESTAMP USING delivered_at AT TIME ZONE 'UTC'; +``` + +### 7) `flow-php/telemetry` - `OTEL_RESOURCE_ATTRIBUTES` keys and values are percent-decoded, not backslash-escaped + +| Escaping a `,` or `=` in `OTEL_RESOURCE_ATTRIBUTES` | Before | After | +|-----------------------------------------------------|---------------------------|-----------------------------| +| literal comma in a value | `key=value\,with\,commas` | `key=value%2Cwith%2Ccommas` | +| literal `=` in a value | not supported | `key=a%3Db` | + +Re-encode any `OTEL_RESOURCE_ATTRIBUTES` that relied on backslash escaping; both keys and values are now +percent-decoded. + +--- + +## Upgrading from 0.37.x to 0.38.x + +### 1) `flow-php/types` - PHPStan extension extracted to `flow-php/phpstan-types-bridge` + +The `StructureTypeReturnTypeExtension` - which narrows the return type of `type_structure()` for PHPStan - has been +moved out of `flow-php/types` into a dedicated package, `flow-php/phpstan-types-bridge`. +`flow-php/types` no longer ships any PHPStan code. + +| Before | After | +|-------------------------------------------------------|--------------------------------------------------------------| +| `Flow\Types\PHPStan\StructureTypeReturnTypeExtension` | `Flow\Bridge\PHPStan\Types\StructureTypeReturnTypeExtension` | +| shipped inside `flow-php/types` | shipped inside `flow-php/phpstan-types-bridge` | + +If you used `type_structure()` together with PHPStan, install the new package: + +``` +composer require --dev flow-php/phpstan-types-bridge +``` + +With [phpstan/extension-installer](https://github.com/phpstan/extension-installer) the extension is registered +automatically. If you registered it manually, update your `phpstan.neon`: + +Before: + +```neon +services: + - + class: Flow\Types\PHPStan\StructureTypeReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension +``` + +After: + +```neon +includes: + - vendor/flow-php/phpstan-types-bridge/extension.neon +``` + +--- + +## Upgrading from 0.36.x to 0.37.x + +### 1) `flow-php/telemetry` - Per-signal exporter contracts merged into `Exporter` + +| Before | After | +|------------------------------------------------------------------------------------|------------------------------------------------------------------| +| `Flow\Telemetry\Tracer\SpanExporter` (interface) | `Flow\Telemetry\Exporter\Exporter` | +| `Flow\Telemetry\Meter\MetricExporter` (interface) | `Flow\Telemetry\Exporter\Exporter` | +| `Flow\Telemetry\Logger\LogExporter` (interface) | `Flow\Telemetry\Exporter\Exporter` | +| `VoidSpanExporter`, `VoidMetricExporter`, `VoidLogExporter` | `Flow\Telemetry\Provider\Void\VoidExporter` | +| `MemorySpanExporter`, `MemoryMetricExporter`, `MemoryLogExporter` | `Flow\Telemetry\Provider\Memory\MemoryExporter` | +| `ConsoleSpanExporter`, `ConsoleMetricExporter`, `ConsoleLogExporter` | `Flow\Telemetry\Provider\Console\ConsoleExporter` | +| `void_span_exporter()` / `void_metric_exporter()` / `void_log_exporter()` | `void_exporter()` | +| `memory_span_exporter()` / `memory_metric_exporter()` / `memory_log_exporter()` | `memory_exporter()` | +| `console_span_exporter()` / `console_metric_exporter()` / `console_log_exporter()` | `console_exporter()` | +| `MemoryLogExporter::entries()` | `MemoryExporter::logs()` | +| `MemorySpanExporter::spans()` | `MemoryExporter::spans()` | +| `MemoryMetricExporter::metrics()` | `MemoryExporter::metrics()` | +| `Exporter::transports()` | removed | +| `(Span\|Metric\|Log)Exporter::export(array $items) : bool` | `Exporter::export(Flow\Telemetry\Signal\Signals $signal) : bool` | +| - | `Exporter::shutdown() : void` (added) | + +### 2) `flow-php/telemetry` - `Transport` contract relocated to OTLP bridge + +| Before | After | +|-----------------------------------------------------------|-----------------------------------------------------------| +| `Flow\Telemetry\Transport\Transport` | `Flow\Bridge\Telemetry\OTLP\Transport\Transport` | +| `Flow\Telemetry\Transport\TransportException` | `Flow\Bridge\Telemetry\OTLP\Transport\TransportException` | +| `Flow\Telemetry\Transport\VoidTransport` | removed | +| `Transport::sendSpans()` / `sendMetrics()` / `sendLogs()` | `Transport::send(Flow\Telemetry\Signal\Signals $signal)` | +| `Flow\Bridge\Telemetry\OTLP\Exception\Exception` | removed | +| `Flow\Bridge\Telemetry\OTLP\Exception\TransportException` | `Flow\Bridge\Telemetry\OTLP\Transport\TransportException` | + +### 3) `flow-php/telemetry` - Processor interfaces + +Applies to `SpanProcessor`, `MetricProcessor`, `LogProcessor`. + +| Before | After | +|------------------------------------|-----------------------------| +| `exporter() : SpanExporter` (etc.) | removed | +| - | `shutdown() : void` (added) | + +### 4) `flow-php/telemetry` - `Serializer` contract removed + +| Before | After | +|------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| +| `Flow\Telemetry\Serializer\Serializer` | removed | +| `Flow\Bridge\Telemetry\OTLP\Serializer\GrpcSerializer` (interface) | renamed to `Flow\Bridge\Telemetry\OTLP\Serializer\GrpcRequestFactory` (class) | +| `CurlTransport(string $endpoint, Serializer $serializer, ...)` | `CurlTransport(string $endpoint, JsonSerializer\|ProtobufSerializer $serializer = new JsonSerializer(), ...)` | +| `GrpcTransport(string $endpoint, ProtobufSerializer $serializer, ...)` | `GrpcTransport(string $endpoint, ...)` - serializer parameter removed | + +### 5) `flow-php/telemetry` - `ErrorHandler` contract added + +New namespace `Flow\Telemetry\ErrorHandler` with: `ErrorHandler` (interface), `ErrorLogHandler`, `NullErrorHandler`, +`StreamHandler`, `SyslogHandler`, `UdpSyslogHandler`, `CompositeErrorHandler`. + +| Before | After | +|---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| +| `otlp_exporter($transport)` | `otlp_exporter($transport, ErrorHandler $errorHandler = new ErrorLogHandler())` | +| `telemetry_handler($logger, $converter, $level, $bubble)` (Monolog) | `telemetry_handler($logger, $converter, $level, $bubble, ErrorHandler $errorHandler = new ErrorLogHandler())` | + +### 6) `flow-php/telemetry-otlp-bridge` - `HttpTransport` removed + +| Before | After | +|------------------------------------------------------|---------------------------------------| +| `Flow\Bridge\Telemetry\OTLP\Transport\HttpTransport` | removed | +| `otlp_http_transport()` | removed (use `otlp_curl_transport()`) | +| `psr/http-client` (runtime require) | removed (dev only) | +| `psr/http-factory` (runtime require) | removed (dev only) | + +### 7) `flow-php/telemetry-otlp-bridge` - Per-signal OTLP exporters merged + +| Before | After | +|-------------------------------------------------------------|----------------------------------------------------| +| `OTLPSpanExporter`, `OTLPMetricExporter`, `OTLPLogExporter` | `Flow\Bridge\Telemetry\OTLP\Exporter\OTLPExporter` | +| `otlp_span_exporter($transport)` | `otlp_exporter($transport)` | +| `otlp_metric_exporter($transport)` | `otlp_exporter($transport)` | +| `otlp_log_exporter($transport)` | `otlp_exporter($transport)` | + +### 8) `flow-php/telemetry-otlp-bridge` - Curl/gRPC timeouts switched to milliseconds + +| Before | After | +|---------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `CurlTransportOptions::withTimeout(int $seconds)`, default `30` | `CurlTransportOptions::withTimeout(int $milliseconds)`, default `250` | +| `CurlTransportOptions::withConnectTimeout(int $seconds)`, default `10` | `CurlTransportOptions::withConnectTimeout(int $milliseconds)`, default `250` | +| `CurlTransportOptions::timeout()` | `CurlTransportOptions::timeoutMs()` | +| `CurlTransportOptions::connectTimeout()` | `CurlTransportOptions::connectTimeoutMs()` | +| - | `CurlTransportOptions::withShutdownTimeout(int $milliseconds)` / `shutdownTimeoutMs()`, default `5000` (added) | +| `otlp_curl_transport(string $endpoint, Serializer $serializer, CurlTransportOptions $options)` | `otlp_curl_transport(string $endpoint, JsonSerializer\|ProtobufSerializer $serializer = new JsonSerializer(), CurlTransportOptions $options = new CurlTransportOptions(), ?Transport $failover = null)` | +| `otlp_grpc_transport(string $endpoint, ProtobufSerializer $serializer, array $headers = [], bool $insecure = true)` | `otlp_grpc_transport(string $endpoint, array $headers = [], bool $insecure = true, int $timeoutMs = 250, int $shutdownTimeoutMs = 5000, ?Transport $failover = null)` | + +### 9) `flow-php/telemetry-otlp-bridge` - `StreamTransport` added + +New transport, no removal counterpart. + +| Before | After | +|--------|-----------------------------------------------------------------------------------------------------------| +| - | `Flow\Bridge\Telemetry\OTLP\Transport\StreamTransport` | +| - | `otlp_stream_transport(string $destination, int $filePermissions = 0644, bool $createDirectories = true)` | + +### 10) `flow-php/telemetry-otlp-bridge` - `open-telemetry/gen-otlp-protobuf` dependency dropped + +| Before | After | +|---------------------------------------------------|--------------------------------------------------------------------------------------------------------| +| `open-telemetry/gen-otlp-protobuf` (required dep) | removed; protobuf classes shipped inside the bridge under the same `Opentelemetry\Proto\...` namespace | + +### 11) `flow-php/symfony-telemetry-bundle` - Configuration schema rewrite + +No BC shim. Configurations from 0.36 must be rewritten. + +| Before | After | +|-------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------| +| `exporters..type: otlp\|service\|console\|memory\|void` | sub-block keyed by implementation: `otlp:`, `service:`, `console:`, `memory:`, `void:` | +| `exporters..service_id: ` (under `type: service`) | `exporters..service: { id: }` | +| Inline `processor.exporter: { type: otlp, transport: {...} }` | `processor.exporter: ` referencing top-level `exporters:` map | +| `transport.type: http` | removed | +| `transport.timeout` (seconds, default `30`) | `transport.timeout_ms` (default `250`) | +| `transport.connect_timeout` (seconds, default `10`) | `transport.connect_timeout_ms` (default `250`) | +| `transport.http_client_service_id` / `request_factory_service_id` / `stream_factory_service_id` | removed | +| - | `transport.type: stream` (added) | +| - | `transport.shutdown_timeout_ms` default `5000` (added) | +| - | `transport.failover: { type: ..., ... }` on curl/grpc primaries (added) | +| - | top-level `error_handlers:` map (added) | +| - | `error_handler: ` references on providers, processors, otlp exporter (added) | +| - | top-level `framework_logger: ` (added) | + +Before: + +```yaml +flow_telemetry: + exporters: + otlp: + type: otlp + transport: + type: curl + endpoint: 'http://otel-collector:4318' + timeout: 30 + connect_timeout: 10 + custom: { type: service, service_id: 'app.x' } + debug: { type: console } + + tracer_provider: + processor: + type: batching + exporter: { type: otlp, transport: { type: curl, endpoint: 'http://otel-collector:4318' } } +``` + +After: + +```yaml +flow_telemetry: + error_handlers: + default: { type: error_log } + + exporters: + otlp: + otlp: + transport: + type: curl + endpoint: 'http://otel-collector:4318' + timeout_ms: 250 + connect_timeout_ms: 250 + custom: { service: { id: 'app.x' } } + debug: { console: ~ } + + tracer_provider: + processor: + type: batching + exporter: otlp +``` + +### 12) `flow-php/phpunit-telemetry-bridge` - Configuration parameters + +| Before (parameter / default) | After (parameter / default) | +|--------------------------------------------------|----------------------------------------------------------------------------------| +| `curl_timeout` / `30` (seconds) | `curl_timeout_ms` / `250` (ms) | +| `curl_connect_timeout` / `10` (s) | `curl_connect_timeout_ms` / `250` (ms) | +| `transport: curl\|grpc` | `transport: curl\|grpc\|stream` | +| - | `grpc_timeout_ms` / `250` (added) | +| - | `shutdown_timeout_ms` / `5000` (added) | +| - | `batch_size` / `512` (added) | +| - | `error_handler` / `error_log` and `error_handler_*` family (added) | +| - | `stream_file_permissions` / `0644`, `stream_create_directories` / `true` (added) | +| Default span/metric/log processors: pass-through | Default span/metric/log processors: batching (`batch_size: 512`) | + +`otel_collector_url` / `FLOW_PHPUNIT_OTEL_COLLECTOR_URL` remain deprecated aliases for `endpoint` with +`transport=curl`. + +--- + +## Upgrading from 0.35.x to 0.36.x + +### 1) `flow-php/postgresql` - `RawCondition` and `RawExpression` removed + +The `raw_cond()` and `raw_expr()` escape hatches have been removed. All query builder operations are now covered by +type-safe DSL functions. + +| Removed | Replacement | +|---------------------------------------|---------------------------------------------------------------------------| +| `raw_cond('NOT col')` | `not_(is_true(col('col')))` | +| `raw_cond('a = ANY(b)')` | `any_(col('a'), ComparisonOperator::EQ, col('b'))` | +| `raw_cond("x IN ('a', 'b')")` | `in_(col('x'), [literal('a'), literal('b')])` | +| `raw_cond("x NOT LIKE 'pg_%'")` | `not_like(col('x'), literal('pg_%'))` | +| `raw_expr('NOT col')` | `not_(col('col'))` | +| `raw_expr('a \|\| b')` | `concat(col('a'), col('b'))` or `binary_expr(col('a'), '\|\|', col('b'))` | +| `raw_expr('CASE x WHEN ...')` | `case_when([when(...)], operand: col('x'))` | +| `raw_expr('array_agg(DISTINCT ...)')` | `agg('array_agg', [...], distinct: true)->withOrderBy(...)` | +| `RawCondition` class | Use specific condition classes | +| `RawExpression` class | Use specific expression classes | + +### 2) `flow-php/postgresql` - `Condition` now extends `Expression` + +Conditions are now expressions - they can be used in SELECT lists, CASE WHEN, ORDER BY, etc. + +```php +// Conditions can now be aliased and used as expressions: +select(eq(col('a'), col('b'))->as('is_equal')); + +// NOT works in both WHERE and SELECT: +not_(col('is_deleted'))->as('is_active'); + +// CASE WHEN accepts conditions directly: +case_when([when(eq(col('x'), literal(0)), literal('zero'))]); +``` + +### 3) `flow-php/postgresql` - DSL condition function renames + +Function names have been unified following standard SQL builder conventions (jOOQ, Diesel, SQLAlchemy). + +| Removed | Replacement | Reason | +|----------------------|---------------------------|-----------------------------------------------------------| +| `neq()` | `ne()` | Standard short form | +| `lte()` | `le()` | Standard short form | +| `gte()` | `ge()` | Standard short form | +| `is_in()` | `in_()` | Drop `is_` prefix, trailing underscore for PHP keyword | +| `is_distinct_from()` | `distinct_from()` | Drop `is_` prefix | +| `cond_and()` | `and_()` | Drop `cond_` prefix, trailing underscore for PHP keyword | +| `cond_or()` | `or_()` | Drop `cond_` prefix, trailing underscore for PHP keyword | +| `cond_not()` | `not_()` | Drop `cond_` prefix, trailing underscore for PHP keyword | +| `any_sub_select()` | `any_()` | Unified - accepts both `Expression` and `SelectFinalStep` | +| `all_sub_select()` | `all_()` | Unified - accepts both `Expression` and `SelectFinalStep` | +| `cond_true()` | `is_true(literal(true))` | Use `is_true()` with literal | +| `cond_false()` | `is_true(literal(false))` | Use `is_true()` with literal | +| `bool_cond()` | `is_true()` | Wraps expression as boolean condition | +| `any_array()` | `any_()` | Merged into unified `any_()` | +| `all_array()` | `all_()` | Merged into unified `all_()` | + +New functions added: + +| Function | Purpose | +|------------------------------------|------------------------------------------------| +| `is_true(Expression)` | Wrap expression as boolean condition for WHERE | +| `not_like(Expression, Expression)` | NOT LIKE condition | +| `concat(Expression, ...)` | String concatenation with `\|\|` operator | + +Before: + +```php +use function Flow\PostgreSql\DSL\{cond_and, cond_not, cond_true, neq, lte, gte, is_in, any_sub_select}; + +select(col('name')) + ->where(cond_and( + neq(col('status'), literal('deleted')), + lte(col('age'), literal(65)), + gte(col('age'), literal(18)), + is_in(col('role'), [literal('admin'), literal('user')]), + )); +``` + +After: + +```php +use function Flow\PostgreSql\DSL\{and_, ne, le, ge, in_}; + +select(col('name')) + ->where(and_( + ne(col('status'), literal('deleted')), + le(col('age'), literal(65)), + ge(col('age'), literal(18)), + in_(col('role'), [literal('admin'), literal('user')]), + )); +``` + +### 4) `flow-php/postgresql` - Schema builder methods accept `Expression`/`Condition` instead of strings + +Methods that previously accepted raw SQL strings now require typed `Expression` or `Condition` objects. + +| Method | Before (string) | After (typed) | +|----------------------------------------------|-------------------------------------------|---------------------------------------------------------| +| `ColumnDefinition::check()` | `->check('age > 0')` | `->check(gt(col('age'), literal(0)))` | +| `ColumnDefinition::defaultRaw()` | `->defaultRaw('CURRENT_TIMESTAMP')` | `->defaultRaw(current_timestamp())` | +| `ColumnDefinition::generatedAs()` | `->generatedAs("a \|\| b")` | `->generatedAs(concat(col('a'), col('b')))` | +| `CheckConstraint::create()` | `::create('age > 0')` | `::create(gt(col('age'), literal(0)))` | +| `ExcludeConstraint::element()` | `->element('col', '=')` | `->element(col('col'), '=')` | +| `ExcludeConstraint::where()` | `->where('active = true')` | `->where(eq(col('active'), literal(true)))` | +| `CreateDomainBuilder::check()` | `->check('VALUE > 0')` | `->check(gt(col('VALUE'), literal(0)))` | +| `CreateDomainBuilder::default()` | `->default("'text'")` | `->default(literal('text'))` | +| `AlterDomainBuilder::addConstraint()` | `->addConstraint('name', 'VALUE > 0')` | `->addConstraint('name', gt(col('VALUE'), literal(0)))` | +| `AlterDomainBuilder::setDefault()` | `->setDefault('100')` | `->setDefault(literal(100))` | +| `AlterTableBuilder::alterColumnSetDefault()` | `->alterColumnSetDefault('col', "'val'")` | `->alterColumnSetDefault('col', literal('val'))` | +| `CreateRuleBuilder::where()` | `->where("OLD.role = 'admin'")` | `->where(eq(col('role', 'OLD'), literal('admin')))` | + +### 5) `flow-php/postgresql` - DSL functions split into separate files + +The monolithic `functions.php` has been split into 5 focused files (same namespace, no import changes needed): + +| File | Purpose | +|-----------------|--------------------------------------------------------------------------------------------| +| `query.php` | Query building, expressions, tables, ordering, CTE, window, locking, transactions, cursors | +| `condition.php` | Comparisons, predicates, logic, JSON/array/regex operators | +| `schema.php` | DDL, constraints, indexes, maintenance, privileges, types, schema definitions | +| `client.php` | Connections, telemetry, mappers | +| `parser.php` | SQL parsing, formatting, analysis | + +### 6) `flow-php/filesystem` - `Protocol` and `Backend` removed, `Mount` rewritten + +The filesystem library has been redesigned around a single mount-protocol string. The `Protocol` and +`Backend` value types are gone; `Mount` now wraps just a protocol name. + +**`Protocol` class removed.** `Path::protocol()` now returns `string` instead of a `Protocol` object. Callsites that +unpacked `Protocol::$name` / `Protocol::scheme()` / `Protocol::is()` are mechanical updates: + +| Before | After | +|------------------------------------------|----------------------------------------------------------------------------------------------------| +| `$path->protocol()->name` | `$path->protocol()` | +| `$path->protocol()->scheme()` | `$path->protocol() . '://'` | +| `$path->protocol()->is('file')` | `$path->protocol() === 'file'` | +| `$fs->protocol()->validateScheme($path)` | `$fs->mount()->supports($path) \|\| throw new InvalidSchemeException(...)` | +| `new Protocol('file')` | `new Mount('file')` (if you need a Mount) or plain `'file'` (FilesystemTable::for accepts strings) | + +**`Backend` enum removed.** There's no closed set of backends anymore - any filesystem can mount under any protocol. The +Symfony bundle schema now uses a plain string `type:` field (see below). If you branched on `Backend` cases in +application code, replace with string comparisons against the factory `type()` or the mount protocol, whichever fits. + +**`Mount` rewritten.** The shape is now: + +```php +final readonly class Mount +{ + public string $protocol; + + public function __construct(string $protocol); // validates against PROTOCOL_REGEX + public function supports(Path|string $path) : bool; +} +``` + +**`Filesystem::protocol()` renamed to `Filesystem::mount()`.** The return type changed from +`Protocol` to `Mount`. Every `Filesystem` implementation must rename the method. + +**`Filesystem` ctors take `Mount` directly.** `NativeLocalFilesystem`, `MemoryFilesystem`, +`StdOutFilesystem`, `AsyncAWSS3Filesystem`, `AzureBlobFilesystem` now accept `Mount` as the first constructor argument +(local filesystems have a sensible default). DSL factory functions (`native_local_filesystem`, `memory_filesystem`, +`stdout_filesystem`, `aws_s3_filesystem`, +`azure_filesystem`) accept `string $protocol` as the **last** argument with a sensible default (`'file'`, `'memory'`, +`'stdout'`, `'aws-s3'`, `'azure-blob'`) and build the `Mount` internally - no caller change needed unless you +instantiate the filesystem class directly or mount two filesystems of the same backend under distinct protocols. + +**Auto-alias dropped.** Previously, mounting a single filesystem of a given backend would auto-register its canonical +scheme as an additional alias (e.g. mounting S3 as `warehouse` also made `aws-s3` +available). That behavior is gone - every mount is registered under exactly the protocol you pick. If you need two +protocols for the same filesystem, mount it twice explicitly. + +**`FilesystemTable::for(Path|Protocol)` → `for(Path|string)`.** Pass a `Path` or a plain protocol string. + +### 7) `flow-php/filesystem` - `NativeLocalFilesystem::list()` no longer sorts results + +`Glob::glob()` was replaced with lazy `Webmozart\Glob\Iterator\GlobIterator` to avoid materializing the entire matching +set up front (this gives a ~30× speedup on large trees when the caller only needs the first N entries). + +**Side effect:** `NativeLocalFilesystem::list()` no longer returns results in alphabetical order. Output now follows +filesystem traversal order. If your code depends on sort order, sort client-side after consuming the generator: + +```php +$statuses = iterator_to_array($fs->list(path('/some/dir/**/*.txt'))); +usort($statuses, static fn (FileStatus $a, FileStatus $b) => $a->path->uri() <=> $b->path->uri()); +``` + +### 8) `flow-php/symfony-filesystem-bundle` - YAML schema now uses `type:` + protocol-as-key + +The configuration schema changed significantly. The YAML key under `filesystems:` is now the **mount protocol** (any +valid URI scheme), and a separate `type:` field picks the factory. + +**Before:** + +```yaml +flow_filesystem: + fstabs: + default: + filesystems: + file: ~ + memory: ~ + aws-s3: + bucket: '%env(S3_BUCKET)%' +``` + +**After:** + +```yaml +flow_filesystem: + fstabs: + default: + filesystems: + file: + type: file + memory: + type: memory + aws-s3: # mount protocol - can be any valid URI scheme + type: aws_s3 # factory lookup key + bucket: '%env(S3_BUCKET)%' +``` + +Benefits of the new shape: + +- Mount the same backend twice under different protocols (e.g. `warehouse` + `archive` both `type: aws_s3` with + different buckets). +- Protocol names are no longer tied to factory names - pick whatever reads well in your application. + +Built-in `type` values: `file`, `memory`, `stdout`, `aws_s3`, `azure_blob`. + +### 9) `flow-php/symfony-filesystem-bundle` - `FilesystemFactory` interface and attribute changed + +```php +// Before +interface FilesystemFactory +{ + public function protocol() : Protocol; + public function create(string $mountName, array $config) : Filesystem; +} + +#[AsFilesystemFactory(protocol: 'my-fs')] + +// After +interface FilesystemFactory +{ + public function type() : string; + public function create(string $protocol, array $config) : Filesystem; +} + +#[AsFilesystemFactory(type: 'my_backend')] +``` + +The DI tag attribute is renamed from `protocol` to `type`. `FilesystemFactoryRegistry::get()` takes a +`string $type` instead of a `Backend`. + +### 10) `flow-php/symfony-filesystem-bundle` - `flow:filesystem:ls` CLI flags reshuffled + +| Before | After | +|------------------------------|--------------------------------------------------------------| +| `--long` (default: off) | 4-column output is now the default; use `--short` to drop it | +| `--no-limit` | Removed - default is unlimited now. Use `--limit=N` to cap. | +| (no `--page-size`) | New `--page-size=N` (default `10`) controls table page size | +| (no `--offset`) | New `--offset=N` skips the first N entries | +| `--format=json` → JSON array | `--format=json` now emits NDJSON (one JSON object per line) | + +Default behavior: list all entries, paginated in tables of 10 rows; interactive terminals prompt between pages (Enter +continues, "no" stops), piped output flows continuously. Size is formatted with binary units, Modified as ISO-8601 - +both read from the backend listing response, no per-file HEAD. + +### 11) `flow-php/symfony-filesystem-bundle` - `flow:filesystem:stat` rejects pattern paths + +`stat` now returns `Command::FAILURE` with a clear error when given a pattern path (`memory://*.txt`, +`**/*.parquet`, ...). Previously it returned metadata for the first match - confusing semantics. Use +`flow:filesystem:ls` for pattern inspection. + +### 12) `flow-php/filesystem-async-aws-bridge`, + +`flow-php/filesystem-azure-bridge` - DSL protocol is the last argument with a default + +The DSL factories expose the mount protocol as an optional last argument, defaulted to the conventional scheme. Common +cases work without passing it: + +```php +aws_s3_filesystem($bucket, $client); // mounts under 'aws-s3' +azure_filesystem($blobService); // mounts under 'azure-blob' + +// Pick a different protocol - e.g. mount the same bucket twice +aws_s3_filesystem($bucket, $client, protocol: 'warehouse'); +azure_filesystem($blobService, protocol: 'archive'); +``` + +### 13) `flow-php/filesystem` - `path_memory()` and `path_stdout()` DSL helpers removed + +Build `Path` directly instead: + +```php +// Before +$mem = path_memory(); +$out = path_stdout(['stream' => 'output']); + +// After +$mem = path('memory://' . bin2hex(random_bytes(16)) . '.memory'); +$out = path('stdout://' . bin2hex(random_bytes(16)) . '.stdout', ['stream' => 'output']); +``` + +### 14) `flow-php/etl` - `ConfigBuilder::cacheFilesystem()` and `externalSortFilesystem()` added + +Point cache and external-sort mechanisms at any mounted protocol; defaults remain `'file'`. The +`CacheConfig` and `SortConfig` value objects expose the chosen protocol as `->filesystemProtocol`. + +```php +$config = config_builder() + ->mount(aws_s3_filesystem($bucket, $client, protocol: 'sort-scratch')) + ->externalSortFilesystem('sort-scratch') + ->build(); +``` + +### 15) `flow-php/symfony-http-foundation-bridge` - `Output` interface collapsed to a single `loader(Path)` + +`Output::memoryLoader(string $id)` and `Output::stdoutLoader()` were replaced by +`Output::loader(Path $path)`. `FlowBufferedResponse` gained a `string $filesystem = 'memory'` +constructor argument (buffer protocol); `FlowStreamedResponse` gained +`string $stdoutFilesystemProtocol = 'stdout'`. Each response builds the path with its configured protocol and passes it +to the Output. + +```php +// Before +new FlowBufferedResponse($extractor, new CsvOutput(), $transformations); + +// After - same defaults, new constructor param available +new FlowBufferedResponse($extractor, new CsvOutput(), $transformations, filesystem: 'memory'); +``` + +### 16) `flow-php/filesystem` - `StdOutFilesystem` tracks open streams per php:// target + +Previously the "only one stdout stream" guard lived in `FilesystemStreams` (ETL core) and fired when two writing streams +used the `stdout://` protocol. The check now lives in `StdOutFilesystem` itself and is precise per underlying php:// +target (`stdout` / `stderr` / `output`): two streams with +`['stream' => 'stdout']` conflict; one stdout stream + one stderr stream do not. Error message changed from *"Only one +stdout filesystem stream can be open at the same time"* to *"Only one stream can be open at the same time for php: +//{target}"*. diff --git a/documentation/upgrading-0.8-0.16.md b/documentation/upgrading-0.8-0.16.md new file mode 100644 index 0000000000..ce8d4ff24c --- /dev/null +++ b/documentation/upgrading-0.8-0.16.md @@ -0,0 +1,155 @@ +# Upgrade Guide 0.8.x - 0.16.x + +[TOC] + +This document provides guidelines for upgrading between versions of Flow PHP. Please follow the instructions for your +specific version to ensure a smooth upgrade process. + +Upgrading from older versions: [0.3.x to 0.8.x](/documentation/upgrading-0.3-0.8.md) + +--- + +## Upgrading from 0.15.x to 0.16.x + +### 1) Deprecated `Flow\ETL\DataFrame::renameAll*` methods + +Methods: + +- `Flow\ETL\DataFrame::renameAll()`, +- `Flow\ETL\DataFrame::renameAllLowerCase()`, +- `Flow\ETL\DataFrame::renameAllUpperCase()`, +- `Flow\ETL\DataFrame::renameAllUpperCaseFirst()`, +- `Flow\ETL\DataFrame::renameAllUpperCaseWord()`, + +Were deprecated in favor of using new method: `DataFrame::renameEach()` with proper `RenameEntryStrategy` object. + +### 2) Deprecated `RenameAllCaseTransformer` & `RenameStrReplaceAllEntriesTransformer` + +Selected transformers were deprecated in favor of using `DataFrame::renameEach()` with related `RenameEntryStrategy`: + +- `RenameAllCaseTransformer` -> `RenameCaseTransformer`, +- `RenameStrReplaceAllEntriesTransformer` -> `RenameReplaceStrategy`, + +--- + +## Upgrading from 0.14.x to 0.15.x + +### 1) Removed `Flow\ETL\Row\Schema\Matcher` and implementations + +Schema Matcher was the initial attempt to implement a schema evolution next to schema validation that over time got +replaced with a different implementation of Schema Validator. + +### 2) Renamed `Flow\ETL\Row\Schema` namespace into `Flow\ETL\Schema`. + +This means all classes related to Schema now live under `Flow\ETL\Schema` namespace. + +--- + +## Upgrading from 0.11.x to 0.14.x + +### 1) Replaced `Flow\ETL\DataFrame::validate()` with `Flow\ETL\DataFrame::match()` + +The old method is now deprecated and will be removed in the next release. + +### 2) Replaced `Flow\ETL\Function\ScalarFunction\TypedScalarFunction` with + +`Flow\ETL\Function\ScalarFunction\ScalarResult`. + +The old interface was used to allow defining the return type of the ScalarFunctions. It was replaced with a ScalarResult +value object that is much more flexible than the interface, because it's allowing to return any type dynamically without +making the scalar function stateful. + +--- + +## Upgrading from 0.10.x to 0.11.x + +### 1) Removed StructureElement/struct_element/structure_element from StructureType Definition + +Before: + +```php +type_structure([ + struct_element('name', string()), + struct_element('age', integer()), +]); +``` + +After: + +```php +type_structure([ + 'name' => string(), + 'age' => integer(), +]); +``` + +### 2) Doctrine DBAL Adapter + +From now options for: + +- `to_dbal_table_insert()` +- `to_db_table_update()` + +are passed as objects (instance of UpdateOptions|InsertOptions interfaces) and they are platform specific, so please use +the proper class for the platform you are using. + +- PostgreSQL + - PostgreSQLInsertOptions + - PostgreSQLUpdateOptions +- MySQL + - MySQLInsertOptions + - MySQLUpdateOptions +- Sqlite + - SQLiteInsertOptions + - SQLiteUpdateOptions + +--- + +## Upgrading from 0.8.x to 0.10.x + +### 1) Providing multiple paths to a single extractor + +From now to read from multiple locations use `from_all(Extractor ...$extractors) : Exctractor` extractor. + +Before: + +```php +withSchema($schema); +``` diff --git a/documentation/upgrading.md b/documentation/upgrading.md index 3a48fcf309..84ef20a0a1 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -5,6 +5,8 @@ This document provides guidelines for upgrading between versions of Flow PHP. Please follow the instructions for your specific version to ensure a smooth upgrade process. +Upgrading from older versions: [0.35.x to 0.40.x](/documentation/upgrading-0.35-0.40.md) + --- ## Upgrading from 0.44.x to 0.45.x @@ -484,6 +486,114 @@ A value with a key its structure does not declare is invalid. Declare every elem `type_json()` when the keys are dynamic. flow-php 0.44.x cannot read a Floe file, cached schema or `schema_to_json()` document written by 0.45.x that has a structure column. Clear APCu and natively serialized caches after upgrading. +### 49) `flow-php/etl` - `Rows` is a columnar batch, `Row` is a view + +| Before | After | +|------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------| +| `new Rows($schema, ...$rows)` | `Rows::of($schema, ...$rows)` / `rows($schema, ...$rows)` | +| `Rows::trusted($schema, $rows)` / `Rows::conformed($schema, $rows)` | `Rows::of($schema, ...$rows)` (views) / `Rows::fromColumns($schema, $columns, $count)` (columns) | +| `new Row(array $values)` | `row($values)` / `array_to_row($values, $schema)` | +| - | `new Row(Rows $rows, int $index)` - a view over row `$index` of `$rows` | +| `Row::matchTo()` / `Row::conformTo()` / `Row::project()` | removed - `Rows::matchTo()` / `Rows::project()` | +| `Rows::empty(): bool` | `Rows::isEmpty(): bool` | +| `Row::get()` of a datetime / date / time / uuid / json / xml / html cell - the instance handed in | a new object per call - compare with `assertEquals`, not `assertSame` | +| a `DOMElement` / `HTMLElement` cell keeps its document (parent and siblings reachable) | the cell is the element's own markup - navigate from the document column (`xpath()`) | +| an optional and nullable structure element given `null` | reads back absent (the element's validity bit) | +| `$row == $other` - compares the rows' values | compares both views' whole batches and indices - compare `toArray()` | +| `serialize(Rows)` payload `{schema, rows}` | `{schema, count, columns}` - payloads of 0.44.x cannot be unserialized | +| `Rows::drop()` / `dropRight()` / `take()` / `takeRight()` with a negative size - `array_slice()` semantics | `InvalidArgumentException` | + +### 50) `flow-php/etl` - `row()` infers through a batch + +| Before | After | +|------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| +| `row(['a' => [1, 'x']])` - an `array` value | a `Json` value (`json` column) | +| `row(['a' => new stdClass()])` / a closure - refused later by `rows()` | refused by `row()` (`RuntimeException` / `InvalidArgumentException`) | +| `row(['at' => $datetimeInWarsaw])` - the instance with its zone | a `datetime` (UTC) column - the instant reads back in UTC; declare the zone with `datetime_schema(zone: ...)` | + +### 51) `flow-php/etl` - date and time columns store days and microseconds + +| Before | After | +|-----------------------------------------------------------------------------------------|----------------------------------------------------------------------| +| a `date` cell - the value as given | midnight UTC (zone `UTC`) of its calendar day | +| a `time` cell - `d` kept | `d` folded into hours, `$days` is `false` | +| a `time` string with months / years (`'P1M'`) - accepted by the hydrate path | `SchemaMismatchException` "could not convert 'P1M' (string) to time" | +| a `datetime` / `time` beyond ±9 223 372 036 854.775807 s (about year ±292 000) - stored | refused | +| a `date` beyond the `i32` day range (about year ±5 880 000) - stored | refused | +| a PHP 8.4 `\Dom\Element` in an `xml_element` column - kept | read back as a `DOMElement` | + +### 52) `flow-php/etl` - batch columns refuse wildcard enums, `mixed` elements and foreign definitions + +| Before | After | +|--------------------------------------------------------------------|------------------------------------------------------| +| `enum_schema('x', UnitEnum::class)` / `BackedEnum::class` - stored | `ColumnMismatchException` "cannot be a batch column" | +| `list` / `map` / `structure{a: mixed}` - stored | `ColumnMismatchException` "cannot be a batch column" | +| a `Definition` class outside the 19 of `flow-php/etl` - stored | `ColumnMismatchException` "cannot be a batch column" | + +### 53) `flow-php/etl` - the column backend replaces the adaptive hydrator + +| Before | After | +|------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `AdaptiveRowHydrator`, `NativeRowHydrator` | removed - `PhpRowHydrator(Backend $backend = new DefaultBackend())` | +| `array_to_row(..., Hydrator $hydrator)` / `array_to_rows(..., Hydrator $hydrator)` | `Backend $backend` | +| `ConfigBuilder::hydrator(Hydrator)` | removed - `ConfigBuilder::backend(Backend)` | +| - | `Config::backend()`, `FlowContext::backend()` | + +### 54) `flow-php/etl` - `FloeEngine` and `NativeFloeEncoder` removed + +| Before | After | +|-----------------------------------------------------------------------------------------------------------------------------|--------------------------------------| +| `from_floe(..., engine: ...)` / `to_floe(..., engine: ...)` | removed - Floe runs `PhpFloeEncoder` | +| the `engine` parameter of `FloeReader`, `FloeWriter`, `FloeStreamReader`, `FloeStreamWriter`, `FloeExtractor`, `FloeLoader` | removed | + +### 55) `flow-php/etl` - engine classes follow the batch + +| Before | After | +|------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------| +| `Schema::zonedDefinitions()`, `ZoneAlignment`, `HydratedBatch`, `RowRenaming`, `DomValueCodec` | removed | +| `GroupBy::aggregatedRow(): Row` | `GroupBy::aggregatedValues(): array` | +| `RowMerger::merge(): Row` | `RowMerger::merge(): array` | +| `DerivedColumns::rows(Schema, Schema, list)` | `DerivedColumns::rows(Rows, Schema, Schema, string, Column)` | +| `UnpackedColumns::values(array, string, Schema, array)` | `UnpackedColumns::values(string, Schema, array)` | +| `InferredBatch::of(list)` | `InferredBatch::of(list)` | +| `InferredRows::of(..., Hydrator)` | `InferredRows::of(..., Backend)` | +| `FileConstants::fillRows(Rows, Schema)` | `FileConstants::fillRows(Rows, Schema, Backend $backend = new DefaultBackend())` | + +### 56) `flow-php/etl-adapter-json` - untyped JSON Schema arrays and objects become `json` + +| Before | After | +|-------------------------------------------------------------------------------------------|---------------------------------| +| `{"type": "array"}` without `items` → `list` | `json` | +| `{"type": "object"}` without `properties` / `additionalProperties` → `map` | `json` | +| `schema_to_json_schema(schema_from_json_schema(...))` of an untyped `array` / `object` | `{"type": ["object", "array"]}` | + +### 57) `flow-php/etl` - a join name collision suggests a prefix + +| Before | After | +|-------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| +| `SchemaDefinitionNotUniqueException`: `Entry definitions must be unique, duplicated entries: [id], all: [id, id]` | the same message with `. Please consider using join prefix option` appended - the text before it is unchanged | + +Every join shape (`joinCross()`, `join()`, `joinEach()`) reports the collision through `JoinSchema::of()`; the original +exception is the new one's `previous`. Only an exact match on the whole message is affected. + +### 58) `flow-php/types` - a date is midnight at UTC + +| Before | After | +|------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------| +| `type_date()->isValid()` / `DateDefinition::matches()` - midnight in any zone (`2026-01-01 00:00 Europe/Warsaw`) | only midnight at UTC offset `+00:00` | +| `row(['at' => new DateTimeImmutable('2026-01-01', new DateTimeZone('Europe/Warsaw'))])` - a `date` column | a `datetime` column - the instant is kept | +| `rows(schema(date_schema('at')), $rowWithWarsawMidnight)` / `matchTo()` - accepted | `SchemaMismatchException` "could not convert 2026-01-01T00:00:00.000000+01:00 (datetime) to date" | +| `type_date()->cast($warsawMidnight)` | unchanged - the value's own calendar day | + +A date column stores days and reads back midnight UTC (row 51), so a midnight in another zone was silently moved to a +different instant; it now stays a `datetime` unless it is cast to a date explicitly. + +### 59) `flow-php/types` - `Comparator` takes no arguments + +| Before | After | +|---------------------------------------------------|--------------------| +| `new Comparator(StructureComparison $structures)` | `new Comparator()` | + --- ## Upgrading from 0.43.x to 0.44.x @@ -2838,1635 +2948,3 @@ Remove `propagation_style` from config - `continue` mode is gone (it made the co config is rejected. When `trace` excludes the worker, the transport's poll instrumentation (Doctrine DBAL, HTTP client, ...) is suppressed during the receive loop so it does not surface as orphan spans - no `messenger.receive` span, no orphans either way. - ---- - -## Upgrading from 0.39.x to 0.40.x - -### 1) `flow-php/postgresql` - column and domain defaults are modeled as `ColumnDefault` - -| Before | After | -|---------------------------------------------------------------|-----------------------------------------------------------------------------| -| `Column::$default` / `Domain::$default` type `?string` | `?Flow\PostgreSql\Schema\ColumnDefault` | -| `new Column('c', $type, true, "'0'")` | `new Column('c', $type, true, ColumnDefault::fromExpression("'0'", $type))` | -| `$column->default` (string) | `$column->default?->literal` / `$column->default?->applicableSql()` | -| `ColumnShape['default']` / `DomainShape['default']` `?string` | `?array{literal: string, type: ?ColumnTypeShape, kind: string}` | - -`Column::create()` / `Domain::create()` still accept `bool|float|int|string|Expression|null`. Schema arrays serialized -by `Column::normalize()` / `Domain::normalize()` before 0.40 must be regenerated - `fromArray()` reads the nested -`default` shape only. - -### 2) `flow-php/telemetry` - Log severity filtering moved to a pipeline middleware - -| Before | After | -|-----------------------------------------------------------------|-----------------------------------------------------------------------------------------| -| `Flow\Telemetry\Logger\Processor\SeverityFilteringLogProcessor` | `Flow\Telemetry\Logger\Middleware\SeverityFilteringLogMiddleware` | -| `new SeverityFilteringLogProcessor($inner, $minSeverity)` | `new PipelineLogProcessor([new SeverityFilteringLogMiddleware($minSeverity)], $inner)` | -| `severity_filtering_log_processor($processor, $minSeverity)` | `pipeline_log_processor([severity_filtering_log_middleware($minSeverity)], $processor)` | - -The previously wrapped processor is now the pipeline's **sink** and must implement -`Flow\Telemetry\Logger\LogSink` (the built-in `batching`, `pass_through`, `memory`, `void` and `composite` -log processors already do). - -Before: - -```php -$processor = severity_filtering_log_processor( - batching_log_processor($exporter), - Severity::WARN, -); -``` - -After: - -```php -$processor = pipeline_log_processor( - [severity_filtering_log_middleware(Severity::WARN)], - batching_log_processor($exporter), -); -``` - -### 2) `flow-php/symfony-telemetry-bundle` - `severity_filtering` log processor type replaced by `pipeline` - -The `severity_filtering` processor type (with its `inner_processor`) is no longer a `logger_provider` -processor type; it is a middleware inside a `pipeline`. - -Before: - -```yaml -flow_telemetry: - logger_provider: - processor: - type: severity_filtering - minimum_severity: warn - inner_processor: - type: batching - exporter: otlp -``` - -After: - -```yaml -flow_telemetry: - logger_provider: - processor: - type: pipeline - middleware: - - { type: severity_filtering, minimum_severity: warn } - sink: - type: batching - exporter: otlp -``` - -### 3) `flow-php/symfony-telemetry-bundle` - named scope `attributes` split into `scope` and `signal` - -Applies to `tracers`, `meters`, and `loggers`. The `attributes` map is no longer a flat list of scope attributes; scope -attributes move under `attributes.scope`. - -Before: - -```yaml -flow_telemetry: - loggers: - audit: - attributes: - team: checkout -``` - -After: - -```yaml -flow_telemetry: - loggers: - audit: - attributes: - scope: - team: checkout -``` - -### 4) `flow-php/postgresql` - `DateTimeConverter` split into `TimestampConverter` and `TimestampTzConverter` - -| Before | After | -|------------------------------------------------------------|-------------------------------------------------------------------------------| -| `Flow\PostgreSql\Client\Types\Converter\DateTimeConverter` | `TimestampConverter` (`TIMESTAMP`) and `TimestampTzConverter` (`TIMESTAMPTZ`) | -| `typed($value, ValueType::TIMESTAMP)` keeps the offset | `typed($value, ValueType::TIMESTAMP)` normalizes the value to UTC | -| `timestamp` column read as `2024-01-15 10:30:00` | `timestamp` column read as `2024-01-15 10:30:00+00:00` | - -### 5) `flow-php/etl-adapter-postgresql` - `DateTimeEntry` maps to `timestamp` instead of `timestamptz` - -| Flow type | Before | After | -|---------------------------|---------------|-------------| -| `DateTimeEntry` (binding) | `TIMESTAMPTZ` | `TIMESTAMP` | -| `DateTimeType` (DDL) | `timestamptz` | `timestamp` | - -To keep the previous behavior, pass overrides to `EntryTypesMap`: - -```php -to_pgsql_table($client, 'users')->withTypesMap(new EntryTypesMap( - [DateTimeEntry::class => ValueType::TIMESTAMPTZ], - [DateTimeType::class => ColumnType::timestamptz()], -)); -``` - -### 6) `flow-php/symfony-postgresql-messenger` - `messenger_messages` time columns use `timestamp` instead of - -`timestamptz` - -| Column type for `created_at`, `available_at`, `delivered_at` | Before | After | -|--------------------------------------------------------------|---------------|-------------| -| `MessengerCatalogProvider` (DDL) | `timestamptz` | `timestamp` | -| `Connection` bindings | `TIMESTAMPTZ` | `TIMESTAMP` | - -Existing tables, realign the column type (UTC instants preserved): - -```sql -ALTER TABLE messenger_messages - ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC', - ALTER COLUMN available_at TYPE TIMESTAMP USING available_at AT TIME ZONE 'UTC', - ALTER COLUMN delivered_at TYPE TIMESTAMP USING delivered_at AT TIME ZONE 'UTC'; -``` - -### 7) `flow-php/telemetry` - `OTEL_RESOURCE_ATTRIBUTES` keys and values are percent-decoded, not backslash-escaped - -| Escaping a `,` or `=` in `OTEL_RESOURCE_ATTRIBUTES` | Before | After | -|-----------------------------------------------------|---------------------------|-----------------------------| -| literal comma in a value | `key=value\,with\,commas` | `key=value%2Cwith%2Ccommas` | -| literal `=` in a value | not supported | `key=a%3Db` | - -Re-encode any `OTEL_RESOURCE_ATTRIBUTES` that relied on backslash escaping; both keys and values are now -percent-decoded. - ---- - -## Upgrading from 0.37.x to 0.38.x - -### 1) `flow-php/types` - PHPStan extension extracted to `flow-php/phpstan-types-bridge` - -The `StructureTypeReturnTypeExtension` - which narrows the return type of `type_structure()` for PHPStan - has been -moved out of `flow-php/types` into a dedicated package, `flow-php/phpstan-types-bridge`. -`flow-php/types` no longer ships any PHPStan code. - -| Before | After | -|-------------------------------------------------------|--------------------------------------------------------------| -| `Flow\Types\PHPStan\StructureTypeReturnTypeExtension` | `Flow\Bridge\PHPStan\Types\StructureTypeReturnTypeExtension` | -| shipped inside `flow-php/types` | shipped inside `flow-php/phpstan-types-bridge` | - -If you used `type_structure()` together with PHPStan, install the new package: - -``` -composer require --dev flow-php/phpstan-types-bridge -``` - -With [phpstan/extension-installer](https://github.com/phpstan/extension-installer) the extension is registered -automatically. If you registered it manually, update your `phpstan.neon`: - -Before: - -```neon -services: - - - class: Flow\Types\PHPStan\StructureTypeReturnTypeExtension - tags: - - phpstan.broker.dynamicFunctionReturnTypeExtension -``` - -After: - -```neon -includes: - - vendor/flow-php/phpstan-types-bridge/extension.neon -``` - ---- - -## Upgrading from 0.36.x to 0.37.x - -### 1) `flow-php/telemetry` - Per-signal exporter contracts merged into `Exporter` - -| Before | After | -|------------------------------------------------------------------------------------|------------------------------------------------------------------| -| `Flow\Telemetry\Tracer\SpanExporter` (interface) | `Flow\Telemetry\Exporter\Exporter` | -| `Flow\Telemetry\Meter\MetricExporter` (interface) | `Flow\Telemetry\Exporter\Exporter` | -| `Flow\Telemetry\Logger\LogExporter` (interface) | `Flow\Telemetry\Exporter\Exporter` | -| `VoidSpanExporter`, `VoidMetricExporter`, `VoidLogExporter` | `Flow\Telemetry\Provider\Void\VoidExporter` | -| `MemorySpanExporter`, `MemoryMetricExporter`, `MemoryLogExporter` | `Flow\Telemetry\Provider\Memory\MemoryExporter` | -| `ConsoleSpanExporter`, `ConsoleMetricExporter`, `ConsoleLogExporter` | `Flow\Telemetry\Provider\Console\ConsoleExporter` | -| `void_span_exporter()` / `void_metric_exporter()` / `void_log_exporter()` | `void_exporter()` | -| `memory_span_exporter()` / `memory_metric_exporter()` / `memory_log_exporter()` | `memory_exporter()` | -| `console_span_exporter()` / `console_metric_exporter()` / `console_log_exporter()` | `console_exporter()` | -| `MemoryLogExporter::entries()` | `MemoryExporter::logs()` | -| `MemorySpanExporter::spans()` | `MemoryExporter::spans()` | -| `MemoryMetricExporter::metrics()` | `MemoryExporter::metrics()` | -| `Exporter::transports()` | removed | -| `(Span\|Metric\|Log)Exporter::export(array $items) : bool` | `Exporter::export(Flow\Telemetry\Signal\Signals $signal) : bool` | -| - | `Exporter::shutdown() : void` (added) | - -### 2) `flow-php/telemetry` - `Transport` contract relocated to OTLP bridge - -| Before | After | -|-----------------------------------------------------------|-----------------------------------------------------------| -| `Flow\Telemetry\Transport\Transport` | `Flow\Bridge\Telemetry\OTLP\Transport\Transport` | -| `Flow\Telemetry\Transport\TransportException` | `Flow\Bridge\Telemetry\OTLP\Transport\TransportException` | -| `Flow\Telemetry\Transport\VoidTransport` | removed | -| `Transport::sendSpans()` / `sendMetrics()` / `sendLogs()` | `Transport::send(Flow\Telemetry\Signal\Signals $signal)` | -| `Flow\Bridge\Telemetry\OTLP\Exception\Exception` | removed | -| `Flow\Bridge\Telemetry\OTLP\Exception\TransportException` | `Flow\Bridge\Telemetry\OTLP\Transport\TransportException` | - -### 3) `flow-php/telemetry` - Processor interfaces - -Applies to `SpanProcessor`, `MetricProcessor`, `LogProcessor`. - -| Before | After | -|------------------------------------|-----------------------------| -| `exporter() : SpanExporter` (etc.) | removed | -| - | `shutdown() : void` (added) | - -### 4) `flow-php/telemetry` - `Serializer` contract removed - -| Before | After | -|------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| -| `Flow\Telemetry\Serializer\Serializer` | removed | -| `Flow\Bridge\Telemetry\OTLP\Serializer\GrpcSerializer` (interface) | renamed to `Flow\Bridge\Telemetry\OTLP\Serializer\GrpcRequestFactory` (class) | -| `CurlTransport(string $endpoint, Serializer $serializer, ...)` | `CurlTransport(string $endpoint, JsonSerializer\|ProtobufSerializer $serializer = new JsonSerializer(), ...)` | -| `GrpcTransport(string $endpoint, ProtobufSerializer $serializer, ...)` | `GrpcTransport(string $endpoint, ...)` - serializer parameter removed | - -### 5) `flow-php/telemetry` - `ErrorHandler` contract added - -New namespace `Flow\Telemetry\ErrorHandler` with: `ErrorHandler` (interface), `ErrorLogHandler`, `NullErrorHandler`, -`StreamHandler`, `SyslogHandler`, `UdpSyslogHandler`, `CompositeErrorHandler`. - -| Before | After | -|---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| -| `otlp_exporter($transport)` | `otlp_exporter($transport, ErrorHandler $errorHandler = new ErrorLogHandler())` | -| `telemetry_handler($logger, $converter, $level, $bubble)` (Monolog) | `telemetry_handler($logger, $converter, $level, $bubble, ErrorHandler $errorHandler = new ErrorLogHandler())` | - -### 6) `flow-php/telemetry-otlp-bridge` - `HttpTransport` removed - -| Before | After | -|------------------------------------------------------|---------------------------------------| -| `Flow\Bridge\Telemetry\OTLP\Transport\HttpTransport` | removed | -| `otlp_http_transport()` | removed (use `otlp_curl_transport()`) | -| `psr/http-client` (runtime require) | removed (dev only) | -| `psr/http-factory` (runtime require) | removed (dev only) | - -### 7) `flow-php/telemetry-otlp-bridge` - Per-signal OTLP exporters merged - -| Before | After | -|-------------------------------------------------------------|----------------------------------------------------| -| `OTLPSpanExporter`, `OTLPMetricExporter`, `OTLPLogExporter` | `Flow\Bridge\Telemetry\OTLP\Exporter\OTLPExporter` | -| `otlp_span_exporter($transport)` | `otlp_exporter($transport)` | -| `otlp_metric_exporter($transport)` | `otlp_exporter($transport)` | -| `otlp_log_exporter($transport)` | `otlp_exporter($transport)` | - -### 8) `flow-php/telemetry-otlp-bridge` - Curl/gRPC timeouts switched to milliseconds - -| Before | After | -|---------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `CurlTransportOptions::withTimeout(int $seconds)`, default `30` | `CurlTransportOptions::withTimeout(int $milliseconds)`, default `250` | -| `CurlTransportOptions::withConnectTimeout(int $seconds)`, default `10` | `CurlTransportOptions::withConnectTimeout(int $milliseconds)`, default `250` | -| `CurlTransportOptions::timeout()` | `CurlTransportOptions::timeoutMs()` | -| `CurlTransportOptions::connectTimeout()` | `CurlTransportOptions::connectTimeoutMs()` | -| - | `CurlTransportOptions::withShutdownTimeout(int $milliseconds)` / `shutdownTimeoutMs()`, default `5000` (added) | -| `otlp_curl_transport(string $endpoint, Serializer $serializer, CurlTransportOptions $options)` | `otlp_curl_transport(string $endpoint, JsonSerializer\|ProtobufSerializer $serializer = new JsonSerializer(), CurlTransportOptions $options = new CurlTransportOptions(), ?Transport $failover = null)` | -| `otlp_grpc_transport(string $endpoint, ProtobufSerializer $serializer, array $headers = [], bool $insecure = true)` | `otlp_grpc_transport(string $endpoint, array $headers = [], bool $insecure = true, int $timeoutMs = 250, int $shutdownTimeoutMs = 5000, ?Transport $failover = null)` | - -### 9) `flow-php/telemetry-otlp-bridge` - `StreamTransport` added - -New transport, no removal counterpart. - -| Before | After | -|--------|-----------------------------------------------------------------------------------------------------------| -| - | `Flow\Bridge\Telemetry\OTLP\Transport\StreamTransport` | -| - | `otlp_stream_transport(string $destination, int $filePermissions = 0644, bool $createDirectories = true)` | - -### 10) `flow-php/telemetry-otlp-bridge` - `open-telemetry/gen-otlp-protobuf` dependency dropped - -| Before | After | -|---------------------------------------------------|--------------------------------------------------------------------------------------------------------| -| `open-telemetry/gen-otlp-protobuf` (required dep) | removed; protobuf classes shipped inside the bridge under the same `Opentelemetry\Proto\...` namespace | - -### 11) `flow-php/symfony-telemetry-bundle` - Configuration schema rewrite - -No BC shim. Configurations from 0.36 must be rewritten. - -| Before | After | -|-------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------| -| `exporters..type: otlp\|service\|console\|memory\|void` | sub-block keyed by implementation: `otlp:`, `service:`, `console:`, `memory:`, `void:` | -| `exporters..service_id: ` (under `type: service`) | `exporters..service: { id: }` | -| Inline `processor.exporter: { type: otlp, transport: {...} }` | `processor.exporter: ` referencing top-level `exporters:` map | -| `transport.type: http` | removed | -| `transport.timeout` (seconds, default `30`) | `transport.timeout_ms` (default `250`) | -| `transport.connect_timeout` (seconds, default `10`) | `transport.connect_timeout_ms` (default `250`) | -| `transport.http_client_service_id` / `request_factory_service_id` / `stream_factory_service_id` | removed | -| - | `transport.type: stream` (added) | -| - | `transport.shutdown_timeout_ms` default `5000` (added) | -| - | `transport.failover: { type: ..., ... }` on curl/grpc primaries (added) | -| - | top-level `error_handlers:` map (added) | -| - | `error_handler: ` references on providers, processors, otlp exporter (added) | -| - | top-level `framework_logger: ` (added) | - -Before: - -```yaml -flow_telemetry: - exporters: - otlp: - type: otlp - transport: - type: curl - endpoint: 'http://otel-collector:4318' - timeout: 30 - connect_timeout: 10 - custom: { type: service, service_id: 'app.x' } - debug: { type: console } - - tracer_provider: - processor: - type: batching - exporter: { type: otlp, transport: { type: curl, endpoint: 'http://otel-collector:4318' } } -``` - -After: - -```yaml -flow_telemetry: - error_handlers: - default: { type: error_log } - - exporters: - otlp: - otlp: - transport: - type: curl - endpoint: 'http://otel-collector:4318' - timeout_ms: 250 - connect_timeout_ms: 250 - custom: { service: { id: 'app.x' } } - debug: { console: ~ } - - tracer_provider: - processor: - type: batching - exporter: otlp -``` - -### 12) `flow-php/phpunit-telemetry-bridge` - Configuration parameters - -| Before (parameter / default) | After (parameter / default) | -|--------------------------------------------------|----------------------------------------------------------------------------------| -| `curl_timeout` / `30` (seconds) | `curl_timeout_ms` / `250` (ms) | -| `curl_connect_timeout` / `10` (s) | `curl_connect_timeout_ms` / `250` (ms) | -| `transport: curl\|grpc` | `transport: curl\|grpc\|stream` | -| - | `grpc_timeout_ms` / `250` (added) | -| - | `shutdown_timeout_ms` / `5000` (added) | -| - | `batch_size` / `512` (added) | -| - | `error_handler` / `error_log` and `error_handler_*` family (added) | -| - | `stream_file_permissions` / `0644`, `stream_create_directories` / `true` (added) | -| Default span/metric/log processors: pass-through | Default span/metric/log processors: batching (`batch_size: 512`) | - -`otel_collector_url` / `FLOW_PHPUNIT_OTEL_COLLECTOR_URL` remain deprecated aliases for `endpoint` with -`transport=curl`. - ---- - -## Upgrading from 0.35.x to 0.36.x - -### 1) `flow-php/postgresql` - `RawCondition` and `RawExpression` removed - -The `raw_cond()` and `raw_expr()` escape hatches have been removed. All query builder operations are now covered by -type-safe DSL functions. - -| Removed | Replacement | -|---------------------------------------|---------------------------------------------------------------------------| -| `raw_cond('NOT col')` | `not_(is_true(col('col')))` | -| `raw_cond('a = ANY(b)')` | `any_(col('a'), ComparisonOperator::EQ, col('b'))` | -| `raw_cond("x IN ('a', 'b')")` | `in_(col('x'), [literal('a'), literal('b')])` | -| `raw_cond("x NOT LIKE 'pg_%'")` | `not_like(col('x'), literal('pg_%'))` | -| `raw_expr('NOT col')` | `not_(col('col'))` | -| `raw_expr('a \|\| b')` | `concat(col('a'), col('b'))` or `binary_expr(col('a'), '\|\|', col('b'))` | -| `raw_expr('CASE x WHEN ...')` | `case_when([when(...)], operand: col('x'))` | -| `raw_expr('array_agg(DISTINCT ...)')` | `agg('array_agg', [...], distinct: true)->withOrderBy(...)` | -| `RawCondition` class | Use specific condition classes | -| `RawExpression` class | Use specific expression classes | - -### 2) `flow-php/postgresql` - `Condition` now extends `Expression` - -Conditions are now expressions - they can be used in SELECT lists, CASE WHEN, ORDER BY, etc. - -```php -// Conditions can now be aliased and used as expressions: -select(eq(col('a'), col('b'))->as('is_equal')); - -// NOT works in both WHERE and SELECT: -not_(col('is_deleted'))->as('is_active'); - -// CASE WHEN accepts conditions directly: -case_when([when(eq(col('x'), literal(0)), literal('zero'))]); -``` - -### 3) `flow-php/postgresql` - DSL condition function renames - -Function names have been unified following standard SQL builder conventions (jOOQ, Diesel, SQLAlchemy). - -| Removed | Replacement | Reason | -|----------------------|---------------------------|-----------------------------------------------------------| -| `neq()` | `ne()` | Standard short form | -| `lte()` | `le()` | Standard short form | -| `gte()` | `ge()` | Standard short form | -| `is_in()` | `in_()` | Drop `is_` prefix, trailing underscore for PHP keyword | -| `is_distinct_from()` | `distinct_from()` | Drop `is_` prefix | -| `cond_and()` | `and_()` | Drop `cond_` prefix, trailing underscore for PHP keyword | -| `cond_or()` | `or_()` | Drop `cond_` prefix, trailing underscore for PHP keyword | -| `cond_not()` | `not_()` | Drop `cond_` prefix, trailing underscore for PHP keyword | -| `any_sub_select()` | `any_()` | Unified - accepts both `Expression` and `SelectFinalStep` | -| `all_sub_select()` | `all_()` | Unified - accepts both `Expression` and `SelectFinalStep` | -| `cond_true()` | `is_true(literal(true))` | Use `is_true()` with literal | -| `cond_false()` | `is_true(literal(false))` | Use `is_true()` with literal | -| `bool_cond()` | `is_true()` | Wraps expression as boolean condition | -| `any_array()` | `any_()` | Merged into unified `any_()` | -| `all_array()` | `all_()` | Merged into unified `all_()` | - -New functions added: - -| Function | Purpose | -|------------------------------------|------------------------------------------------| -| `is_true(Expression)` | Wrap expression as boolean condition for WHERE | -| `not_like(Expression, Expression)` | NOT LIKE condition | -| `concat(Expression, ...)` | String concatenation with `\|\|` operator | - -Before: - -```php -use function Flow\PostgreSql\DSL\{cond_and, cond_not, cond_true, neq, lte, gte, is_in, any_sub_select}; - -select(col('name')) - ->where(cond_and( - neq(col('status'), literal('deleted')), - lte(col('age'), literal(65)), - gte(col('age'), literal(18)), - is_in(col('role'), [literal('admin'), literal('user')]), - )); -``` - -After: - -```php -use function Flow\PostgreSql\DSL\{and_, ne, le, ge, in_}; - -select(col('name')) - ->where(and_( - ne(col('status'), literal('deleted')), - le(col('age'), literal(65)), - ge(col('age'), literal(18)), - in_(col('role'), [literal('admin'), literal('user')]), - )); -``` - -### 4) `flow-php/postgresql` - Schema builder methods accept `Expression`/`Condition` instead of strings - -Methods that previously accepted raw SQL strings now require typed `Expression` or `Condition` objects. - -| Method | Before (string) | After (typed) | -|----------------------------------------------|-------------------------------------------|---------------------------------------------------------| -| `ColumnDefinition::check()` | `->check('age > 0')` | `->check(gt(col('age'), literal(0)))` | -| `ColumnDefinition::defaultRaw()` | `->defaultRaw('CURRENT_TIMESTAMP')` | `->defaultRaw(current_timestamp())` | -| `ColumnDefinition::generatedAs()` | `->generatedAs("a \|\| b")` | `->generatedAs(concat(col('a'), col('b')))` | -| `CheckConstraint::create()` | `::create('age > 0')` | `::create(gt(col('age'), literal(0)))` | -| `ExcludeConstraint::element()` | `->element('col', '=')` | `->element(col('col'), '=')` | -| `ExcludeConstraint::where()` | `->where('active = true')` | `->where(eq(col('active'), literal(true)))` | -| `CreateDomainBuilder::check()` | `->check('VALUE > 0')` | `->check(gt(col('VALUE'), literal(0)))` | -| `CreateDomainBuilder::default()` | `->default("'text'")` | `->default(literal('text'))` | -| `AlterDomainBuilder::addConstraint()` | `->addConstraint('name', 'VALUE > 0')` | `->addConstraint('name', gt(col('VALUE'), literal(0)))` | -| `AlterDomainBuilder::setDefault()` | `->setDefault('100')` | `->setDefault(literal(100))` | -| `AlterTableBuilder::alterColumnSetDefault()` | `->alterColumnSetDefault('col', "'val'")` | `->alterColumnSetDefault('col', literal('val'))` | -| `CreateRuleBuilder::where()` | `->where("OLD.role = 'admin'")` | `->where(eq(col('role', 'OLD'), literal('admin')))` | - -### 5) `flow-php/postgresql` - DSL functions split into separate files - -The monolithic `functions.php` has been split into 5 focused files (same namespace, no import changes needed): - -| File | Purpose | -|-----------------|--------------------------------------------------------------------------------------------| -| `query.php` | Query building, expressions, tables, ordering, CTE, window, locking, transactions, cursors | -| `condition.php` | Comparisons, predicates, logic, JSON/array/regex operators | -| `schema.php` | DDL, constraints, indexes, maintenance, privileges, types, schema definitions | -| `client.php` | Connections, telemetry, mappers | -| `parser.php` | SQL parsing, formatting, analysis | - -### 6) `flow-php/filesystem` - `Protocol` and `Backend` removed, `Mount` rewritten - -The filesystem library has been redesigned around a single mount-protocol string. The `Protocol` and -`Backend` value types are gone; `Mount` now wraps just a protocol name. - -**`Protocol` class removed.** `Path::protocol()` now returns `string` instead of a `Protocol` object. Callsites that -unpacked `Protocol::$name` / `Protocol::scheme()` / `Protocol::is()` are mechanical updates: - -| Before | After | -|------------------------------------------|----------------------------------------------------------------------------------------------------| -| `$path->protocol()->name` | `$path->protocol()` | -| `$path->protocol()->scheme()` | `$path->protocol() . '://'` | -| `$path->protocol()->is('file')` | `$path->protocol() === 'file'` | -| `$fs->protocol()->validateScheme($path)` | `$fs->mount()->supports($path) \|\| throw new InvalidSchemeException(...)` | -| `new Protocol('file')` | `new Mount('file')` (if you need a Mount) or plain `'file'` (FilesystemTable::for accepts strings) | - -**`Backend` enum removed.** There's no closed set of backends anymore - any filesystem can mount under any protocol. The -Symfony bundle schema now uses a plain string `type:` field (see below). If you branched on `Backend` cases in -application code, replace with string comparisons against the factory `type()` or the mount protocol, whichever fits. - -**`Mount` rewritten.** The shape is now: - -```php -final readonly class Mount -{ - public string $protocol; - - public function __construct(string $protocol); // validates against PROTOCOL_REGEX - public function supports(Path|string $path) : bool; -} -``` - -**`Filesystem::protocol()` renamed to `Filesystem::mount()`.** The return type changed from -`Protocol` to `Mount`. Every `Filesystem` implementation must rename the method. - -**`Filesystem` ctors take `Mount` directly.** `NativeLocalFilesystem`, `MemoryFilesystem`, -`StdOutFilesystem`, `AsyncAWSS3Filesystem`, `AzureBlobFilesystem` now accept `Mount` as the first constructor argument -(local filesystems have a sensible default). DSL factory functions (`native_local_filesystem`, `memory_filesystem`, -`stdout_filesystem`, `aws_s3_filesystem`, -`azure_filesystem`) accept `string $protocol` as the **last** argument with a sensible default (`'file'`, `'memory'`, -`'stdout'`, `'aws-s3'`, `'azure-blob'`) and build the `Mount` internally - no caller change needed unless you -instantiate the filesystem class directly or mount two filesystems of the same backend under distinct protocols. - -**Auto-alias dropped.** Previously, mounting a single filesystem of a given backend would auto-register its canonical -scheme as an additional alias (e.g. mounting S3 as `warehouse` also made `aws-s3` -available). That behavior is gone - every mount is registered under exactly the protocol you pick. If you need two -protocols for the same filesystem, mount it twice explicitly. - -**`FilesystemTable::for(Path|Protocol)` → `for(Path|string)`.** Pass a `Path` or a plain protocol string. - -### 7) `flow-php/filesystem` - `NativeLocalFilesystem::list()` no longer sorts results - -`Glob::glob()` was replaced with lazy `Webmozart\Glob\Iterator\GlobIterator` to avoid materializing the entire matching -set up front (this gives a ~30× speedup on large trees when the caller only needs the first N entries). - -**Side effect:** `NativeLocalFilesystem::list()` no longer returns results in alphabetical order. Output now follows -filesystem traversal order. If your code depends on sort order, sort client-side after consuming the generator: - -```php -$statuses = iterator_to_array($fs->list(path('/some/dir/**/*.txt'))); -usort($statuses, static fn (FileStatus $a, FileStatus $b) => $a->path->uri() <=> $b->path->uri()); -``` - -### 8) `flow-php/symfony-filesystem-bundle` - YAML schema now uses `type:` + protocol-as-key - -The configuration schema changed significantly. The YAML key under `filesystems:` is now the **mount protocol** (any -valid URI scheme), and a separate `type:` field picks the factory. - -**Before:** - -```yaml -flow_filesystem: - fstabs: - default: - filesystems: - file: ~ - memory: ~ - aws-s3: - bucket: '%env(S3_BUCKET)%' -``` - -**After:** - -```yaml -flow_filesystem: - fstabs: - default: - filesystems: - file: - type: file - memory: - type: memory - aws-s3: # mount protocol - can be any valid URI scheme - type: aws_s3 # factory lookup key - bucket: '%env(S3_BUCKET)%' -``` - -Benefits of the new shape: - -- Mount the same backend twice under different protocols (e.g. `warehouse` + `archive` both `type: aws_s3` with - different buckets). -- Protocol names are no longer tied to factory names - pick whatever reads well in your application. - -Built-in `type` values: `file`, `memory`, `stdout`, `aws_s3`, `azure_blob`. - -### 9) `flow-php/symfony-filesystem-bundle` - `FilesystemFactory` interface and attribute changed - -```php -// Before -interface FilesystemFactory -{ - public function protocol() : Protocol; - public function create(string $mountName, array $config) : Filesystem; -} - -#[AsFilesystemFactory(protocol: 'my-fs')] - -// After -interface FilesystemFactory -{ - public function type() : string; - public function create(string $protocol, array $config) : Filesystem; -} - -#[AsFilesystemFactory(type: 'my_backend')] -``` - -The DI tag attribute is renamed from `protocol` to `type`. `FilesystemFactoryRegistry::get()` takes a -`string $type` instead of a `Backend`. - -### 10) `flow-php/symfony-filesystem-bundle` - `flow:filesystem:ls` CLI flags reshuffled - -| Before | After | -|------------------------------|--------------------------------------------------------------| -| `--long` (default: off) | 4-column output is now the default; use `--short` to drop it | -| `--no-limit` | Removed - default is unlimited now. Use `--limit=N` to cap. | -| (no `--page-size`) | New `--page-size=N` (default `10`) controls table page size | -| (no `--offset`) | New `--offset=N` skips the first N entries | -| `--format=json` → JSON array | `--format=json` now emits NDJSON (one JSON object per line) | - -Default behavior: list all entries, paginated in tables of 10 rows; interactive terminals prompt between pages (Enter -continues, "no" stops), piped output flows continuously. Size is formatted with binary units, Modified as ISO-8601 - -both read from the backend listing response, no per-file HEAD. - -### 11) `flow-php/symfony-filesystem-bundle` - `flow:filesystem:stat` rejects pattern paths - -`stat` now returns `Command::FAILURE` with a clear error when given a pattern path (`memory://*.txt`, -`**/*.parquet`, ...). Previously it returned metadata for the first match - confusing semantics. Use -`flow:filesystem:ls` for pattern inspection. - -### 12) `flow-php/filesystem-async-aws-bridge`, - -`flow-php/filesystem-azure-bridge` - DSL protocol is the last argument with a default - -The DSL factories expose the mount protocol as an optional last argument, defaulted to the conventional scheme. Common -cases work without passing it: - -```php -aws_s3_filesystem($bucket, $client); // mounts under 'aws-s3' -azure_filesystem($blobService); // mounts under 'azure-blob' - -// Pick a different protocol - e.g. mount the same bucket twice -aws_s3_filesystem($bucket, $client, protocol: 'warehouse'); -azure_filesystem($blobService, protocol: 'archive'); -``` - -### 13) `flow-php/filesystem` - `path_memory()` and `path_stdout()` DSL helpers removed - -Build `Path` directly instead: - -```php -// Before -$mem = path_memory(); -$out = path_stdout(['stream' => 'output']); - -// After -$mem = path('memory://' . bin2hex(random_bytes(16)) . '.memory'); -$out = path('stdout://' . bin2hex(random_bytes(16)) . '.stdout', ['stream' => 'output']); -``` - -### 14) `flow-php/etl` - `ConfigBuilder::cacheFilesystem()` and `externalSortFilesystem()` added - -Point cache and external-sort mechanisms at any mounted protocol; defaults remain `'file'`. The -`CacheConfig` and `SortConfig` value objects expose the chosen protocol as `->filesystemProtocol`. - -```php -$config = config_builder() - ->mount(aws_s3_filesystem($bucket, $client, protocol: 'sort-scratch')) - ->externalSortFilesystem('sort-scratch') - ->build(); -``` - -### 15) `flow-php/symfony-http-foundation-bridge` - `Output` interface collapsed to a single `loader(Path)` - -`Output::memoryLoader(string $id)` and `Output::stdoutLoader()` were replaced by -`Output::loader(Path $path)`. `FlowBufferedResponse` gained a `string $filesystem = 'memory'` -constructor argument (buffer protocol); `FlowStreamedResponse` gained -`string $stdoutFilesystemProtocol = 'stdout'`. Each response builds the path with its configured protocol and passes it -to the Output. - -```php -// Before -new FlowBufferedResponse($extractor, new CsvOutput(), $transformations); - -// After - same defaults, new constructor param available -new FlowBufferedResponse($extractor, new CsvOutput(), $transformations, filesystem: 'memory'); -``` - -### 16) `flow-php/filesystem` - `StdOutFilesystem` tracks open streams per php:// target - -Previously the "only one stdout stream" guard lived in `FilesystemStreams` (ETL core) and fired when two writing streams -used the `stdout://` protocol. The check now lives in `StdOutFilesystem` itself and is precise per underlying php:// -target (`stdout` / `stderr` / `output`): two streams with -`['stream' => 'stdout']` conflict; one stdout stream + one stderr stream do not. Error message changed from *"Only one -stdout filesystem stream can be open at the same time"* to *"Only one stream can be open at the same time for php: -//{target}"*. - ---- - -## Upgrading from 0.34.x to 0.35.x - -### 1) `flow-php/postgresql` - `DataType` renamed to `ColumnType` - -The `DataType` class used for schema/DDL definitions has been renamed to `ColumnType` to better communicate its purpose. -All related DSL functions have been renamed from `data_type_*` to `column_type_*`. - -| Removed | Replacement | -|------------------------------------------------|--------------------------------------------------| -| `Flow\PostgreSql\QueryBuilder\Schema\DataType` | `Flow\PostgreSql\QueryBuilder\Schema\ColumnType` | -| `Flow\PostgreSql\Parser\DataTypeParser` | `Flow\PostgreSql\Parser\ColumnTypeParser` | -| `data_type_integer()` | `column_type_integer()` | -| `data_type_smallint()` | `column_type_smallint()` | -| `data_type_bigint()` | `column_type_bigint()` | -| `data_type_boolean()` | `column_type_boolean()` | -| `data_type_text()` | `column_type_text()` | -| `data_type_varchar()` | `column_type_varchar()` | -| `data_type_char()` | `column_type_char()` | -| `data_type_numeric()` | `column_type_numeric()` | -| `data_type_decimal()` | `column_type_decimal()` | -| `data_type_real()` | `column_type_real()` | -| `data_type_double_precision()` | `column_type_double_precision()` | -| `data_type_date()` | `column_type_date()` | -| `data_type_time()` | `column_type_time()` | -| `data_type_timestamp()` | `column_type_timestamp()` | -| `data_type_timestamptz()` | `column_type_timestamptz()` | -| `data_type_interval()` | `column_type_interval()` | -| `data_type_uuid()` | `column_type_uuid()` | -| `data_type_json()` | `column_type_json()` | -| `data_type_jsonb()` | `column_type_jsonb()` | -| `data_type_bytea()` | `column_type_bytea()` | -| `data_type_inet()` | `column_type_inet()` | -| `data_type_cidr()` | `column_type_cidr()` | -| `data_type_macaddr()` | `column_type_macaddr()` | -| `data_type_serial()` | `column_type_serial()` | -| `data_type_smallserial()` | `column_type_smallserial()` | -| `data_type_bigserial()` | `column_type_bigserial()` | -| `data_type_array()` | `column_type_array()` | -| `data_type_custom()` | `column_type_custom()` | -| `data_type_from_string()` | `column_type_from_string()` | - -Before: - -```php -use Flow\PostgreSql\QueryBuilder\Schema\DataType; -use function Flow\PostgreSql\DSL\data_type_integer; -use function Flow\PostgreSql\DSL\data_type_varchar; - -column('age', data_type_integer()); -column('name', data_type_varchar(255)); -cast(ref('id'), DataType::bigint()); -``` - -After: - -```php -use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; -use function Flow\PostgreSql\DSL\column_type_integer; -use function Flow\PostgreSql\DSL\column_type_varchar; - -column('age', column_type_integer()); -column('name', column_type_varchar(255)); -cast(ref('id'), ColumnType::bigint()); -``` - -### 2) `flow-php/postgresql` - `PostgreSqlType` renamed to `ValueType` - -The `PostgreSqlType` enum used for value binding/casting has been renamed to `ValueType` to better communicate its -purpose. All related DSL functions have been renamed from `pgsql_type_*` to `value_type_*`. - -| Removed | Replacement | -|-----------------------------------------------|------------------------------------------| -| `Flow\PostgreSql\Client\Types\PostgreSqlType` | `Flow\PostgreSql\Client\Types\ValueType` | -| `pgsql_type_text()` | `value_type_text()` | -| `pgsql_type_varchar()` | `value_type_varchar()` | -| `pgsql_type_integer()` | `value_type_integer()` | -| `pgsql_type_bigint()` | `value_type_bigint()` | -| `pgsql_type_smallint()` | `value_type_smallint()` | -| `pgsql_type_boolean()` | `value_type_boolean()` | -| `pgsql_type_float4()` | `value_type_float4()` | -| `pgsql_type_float8()` | `value_type_float8()` | -| `pgsql_type_numeric()` | `value_type_numeric()` | -| `pgsql_type_date()` | `value_type_date()` | -| `pgsql_type_timestamp()` | `value_type_timestamp()` | -| `pgsql_type_timestamptz()` | `value_type_timestamptz()` | -| `pgsql_type_json()` | `value_type_json()` | -| `pgsql_type_jsonb()` | `value_type_jsonb()` | -| `pgsql_type_uuid()` | `value_type_uuid()` | -| `pgsql_type_bytea()` | `value_type_bytea()` | -| `pgsql_type_inet()` | `value_type_inet()` | -| `pgsql_type_cidr()` | `value_type_cidr()` | -| All other `pgsql_type_*()` functions | Corresponding `value_type_*()` functions | - -Before: - -```php -use Flow\PostgreSql\Client\Types\PostgreSqlType; -use function Flow\PostgreSql\DSL\pgsql_type_uuid; -use function Flow\PostgreSql\DSL\pgsql_type_text_array; - -typed('550e8400-e29b-41d4-a716-446655440000', pgsql_type_uuid()); -typed(['tag1', 'tag2'], pgsql_type_text_array()); -typed(42, PostgreSqlType::INT4); -``` - -After: - -```php -use Flow\PostgreSql\Client\Types\ValueType; -use function Flow\PostgreSql\DSL\value_type_uuid; -use function Flow\PostgreSql\DSL\value_type_text_array; - -typed('550e8400-e29b-41d4-a716-446655440000', value_type_uuid()); -typed(['tag1', 'tag2'], value_type_text_array()); -typed(42, ValueType::INT4); -``` - ---- - -## Upgrading from 0.31.x to 0.32.x - -### 1) Removal of Meilisearch Adapter - -The Meilisearch adapter has been removed from Flow PHP. If you were using it, please migrate to Elasticsearch adapter. - -### 2) Removed deprecated DSL functions - -All type-related DSL functions have been moved from `Flow\ETL\DSL` to `Flow\Types\DSL`. Update your imports accordingly. - -| Removed Function | Replacement | -|---------------------------|-------------------------------------------| -| `chunks_from()` | `batches()` | -| `type_structure()` | `\Flow\Types\DSL\type_structure()` | -| `type_union()` | `\Flow\Types\DSL\type_union()` | -| `type_optional()` | `\Flow\Types\DSL\type_optional()` | -| `type_from_array()` | `\Flow\Types\DSL\type_from_array()` | -| `is_nullable()` | `\Flow\Types\DSL\type_is_nullable()` | -| `type_equals()` | `\Flow\Types\DSL\type_equals()` | -| `types()` | `\Flow\Types\DSL\types()` | -| `type_list()` | `\Flow\Types\DSL\type_list()` | -| `type_map()` | `\Flow\Types\DSL\type_map()` | -| `type_json()` | `\Flow\Types\DSL\type_json()` | -| `type_datetime()` | `\Flow\Types\DSL\type_datetime()` | -| `type_date()` | `\Flow\Types\DSL\type_date()` | -| `type_time()` | `\Flow\Types\DSL\type_time()` | -| `type_xml()` | `\Flow\Types\DSL\type_xml()` | -| `type_xml_element()` | `\Flow\Types\DSL\type_xml_element()` | -| `type_uuid()` | `\Flow\Types\DSL\type_uuid()` | -| `type_int()` | `\Flow\Types\DSL\type_integer()` | -| `type_integer()` | `\Flow\Types\DSL\type_integer()` | -| `type_string()` | `\Flow\Types\DSL\type_string()` | -| `type_float()` | `\Flow\Types\DSL\type_float()` | -| `type_boolean()` | `\Flow\Types\DSL\type_boolean()` | -| `type_instance_of()` | `\Flow\Types\DSL\type_instance_of()` | -| `type_resource()` | `\Flow\Types\DSL\type_resource()` | -| `type_array()` | `\Flow\Types\DSL\type_array()` | -| `type_callable()` | `\Flow\Types\DSL\type_callable()` | -| `type_null()` | `\Flow\Types\DSL\type_null()` | -| `type_enum()` | `\Flow\Types\DSL\type_enum()` | -| `struct_schema()` | `structure_schema()` | -| `get_type()` | `\Flow\Types\DSL\get_type()` | -| `print_schema()` | `schema_to_ascii()` | -| `type_is()` | `\Flow\Types\DSL\type_is()` | -| `type_is_any()` | `\Flow\Types\DSL\type_is_any()` | -| `dom_element_to_string()` | `\Flow\Types\DSL\dom_element_to_string()` | - -### 3) Removed deprecated DataFrame methods - -| Removed Method | Replacement | -|----------------------------------------|--------------------------------------------------------------| -| `DataFrame::validate()` | `DataFrame::match()` | -| `DataFrame::renameAll()` | `DataFrame::renameEach(rename_replace(...))` | -| `DataFrame::renameAllLowerCase()` | `DataFrame::renameEach(rename_style(StringStyles::LOWER))` | -| `DataFrame::renameAllUpperCase()` | `DataFrame::renameEach(rename_style(StringStyles::UPPER))` | -| `DataFrame::renameAllUpperCaseFirst()` | `DataFrame::renameEach(rename_style(StringStyles::UCFIRST))` | -| `DataFrame::renameAllUpperCaseWord()` | `DataFrame::renameEach(rename_style(StringStyles::UCWORDS))` | -| `DataFrame::renameAllStyle()` | `DataFrame::renameEach(rename_style(...))` | - -### 4) Removed deprecated Schema methods - -| Removed Method | Replacement | -|---------------------------|-------------------------------| -| `Schema::entries()` | `Schema::references()->all()` | -| `Schema::getDefinition()` | `Schema::get()` | -| `Schema::nullable()` | `Schema::makeNullable()` | - -### 5) Removed deprecated Definition methods - -| Removed Method | Replacement | -|--------------------------|------------------------------| -| `Definition::nullable()` | `Definition::makeNullable()` | - -This applies to all Definition implementations: `BooleanDefinition`, `DateDefinition`, `DateTimeDefinition`, -`EnumDefinition`, `FloatDefinition`, `HTMLDefinition`, `HTMLElementDefinition`, `IntegerDefinition`, `JsonDefinition`, -`ListDefinition`, `MapDefinition`, `StringDefinition`, `StructureDefinition`, `TimeDefinition`, `UuidDefinition`, -`XMLDefinition`, `XMLElementDefinition`. - -### 6) Removed deprecated FileExtractor and PathFiltering methods - -| Removed Method | Replacement | -|------------------------------|-----------------------------------| -| `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 | -|----------------------------------------------|---------------------------------------------------| -| `ScalarFunctionChain::domElementAttribute()` | `ScalarFunctionChain::domElementAttributeValue()` | - -### 8) Removed deprecated Config constants - -| Removed Constant | Replacement | -|-------------------------------|-----------------------------------| -| `Config::CACHE_DIR_ENV` | `CacheConfig::CACHE_DIR_ENV` | -| `Config::SORT_MAX_MEMORY_ENV` | `SortConfig::SORT_MAX_MEMORY_ENV` | - -### 9) Removed deprecated Transformers - -| Removed Transformer | Replacement | -|-----------------------------------------|--------------------------------------------------| -| `EntryNameStyleConverterTransformer` | Use `DataFrame::renameEach(rename_style(...))` | -| `RenameAllCaseTransformer` | Use `DataFrame::renameEach(rename_style(...))` | -| `RenameStrReplaceAllEntriesTransformer` | Use `DataFrame::renameEach(rename_replace(...))` | - -### 10) Removed deprecated classes - -| Removed Class | Replacement | -|-------------------------------------------------|--------------------------------| -| `Flow\ETL\Function\StyleConverter\StringStyles` | `Flow\ETL\String\StringStyles` | - ---- - -## Upgrading from 0.28.x to 0.29.x - -### 1) JsonType now uses Json value object instead of string - -The `JsonType` has been refactored to use a dedicated `Json` value object (similar to `Uuid`/`UuidType` pattern). This -allows static analysis tools to distinguish between regular strings and JSON strings. - -**Breaking Changes:** - -- `JsonType::assert()` now returns `Json` instance instead of `string` -- `JsonType::cast()` now returns `Json` instance instead of `string` -- `JsonType::isValid()` now checks for `Json` instance (plain strings are no longer valid) -- `Cast::cast('json', $value)` function now returns `Json` object instead of string -- `type_json()` return type annotation changed from `Type` to `Type` -- `JsonEntry::value()` now returns `?Json` instead of `?array` (consistent with `UuidEntry::value()` returning `?Uuid`) -- `JsonEntry::json()` method removed (use `value()` instead) - -**Migration:** - -If you were using `type_json()->cast($value)` and expected a string, use `->toString()`: - -Before: - -```php -$jsonString = type_json()->cast($array); // was string -``` - -After: - -```php -$json = type_json()->cast($array); // now Json object -$jsonString = $json->toString(); // get the string -$jsonArray = $json->toArray(); // get as array -``` - -If you were using `JsonEntry::value()` and expected an array: - -Before: - -```php -$entry = json_entry('data', ['key' => 'value']); -$array = $entry->value(); // was array -``` - -After: - -```php -$entry = json_entry('data', ['key' => 'value']); -$json = $entry->value(); // now Json object -$array = $json?->toArray(); // get as array -$string = $json?->toString(); // get as string -``` - -If you were using `JsonEntry::json()`: - -Before: - -```php -$json = $entry->json(); -``` - -After: - -```php -$json = $entry->value(); // json() method removed, use value() instead -``` - -**New Json value object features:** - -```php -use Flow\Types\Value\Json; - -// Create from string -$json = new Json('{"key": "value"}'); - -// Create from array -$json = Json::fromArray(['key' => 'value']); - -// Check if valid JSON -Json::isValid('{"key": "value"}'); // true - -// Convert to string/array -$json->toString(); // '{"key":"value"}' -$json->toArray(); // ['key' => 'value'] - -// Json implements Stringable -(string) $json; // '{"key":"value"}' - -// Json implements JsonSerializable -json_encode($json); // '{"key":"value"}' -``` - -**Note:** `JsonEntry::value()` now returns `?Json` for consistency with `UuidEntry::value()` returning `?Uuid`. Use -`->toArray()` or `->toString()` on the Json object to get the underlying data. - -**Row methods behavior:** - -```php -// Row::toArray() converts Json to array automatically (for convenient serialization) -$row->toArray(); // Returns ['data' => ['key' => 'value']] not ['data' => Json(...)] - -// Row::valueOf() returns the raw value (Json object for json entries) -$row->valueOf('data'); // Returns Json object (use ->toArray() if you need array) - -// Entry value() returns the typed value -$row->get('data')->value(); // Returns Json object (use ->toArray() if you need array) -``` - ---- - -## Upgrading from 0.26.x to 0.27.x - -### 1) Force `EntryFactory $entryFactory` to be required on `array_to_row` & `array_to_row(s)` - -Before: - -```php -to_entry('name', 'data'); -array_to_row([]); -array_to_rows([]); -``` - -After: - -```php -to_entry('name', 'data', flow_context(config())->entryFactory()); -array_to_row([], flow_context(config())->entryFactory()); -array_to_rows([], flow_context(config())->entryFactory()); -``` - -## Upgrading from 0.16.x to 0.17.x - -### 1) Removed $nullable property from all types - -Before: - -```php -type_string(nullable:true)->toString() // ?string -``` - -After: - -```php -type_optional(string())->toString() // ?string -``` - -### 2) Removed precision from `float_type()` - -Before `float_type()` use to have default precision 6. This means that any operations on float had to round values to -given precision. The problem with this approach is that all operations now need to receive a dedicated rounding option. - -Instead, end users should handle precision of float columns through `round()` scalar function. - -### 3) Moved all Types to `Flow\Types\Type` namespace - -Before - -```php -\Flow\ETL\DSL\type_string(); // now deprecated, alias for \Flow\Types\DSL\type_string(); -``` - -After - -```php -\Flow\Types\DSL\type_string(); -``` - -## Upgrading from 0.15.x to 0.16.x - -### 1) Deprecated `Flow\ETL\DataFrame::renameAll*` methods - -Methods: - -- `Flow\ETL\DataFrame::renameAll()`, -- `Flow\ETL\DataFrame::renameAllLowerCase()`, -- `Flow\ETL\DataFrame::renameAllUpperCase()`, -- `Flow\ETL\DataFrame::renameAllUpperCaseFirst()`, -- `Flow\ETL\DataFrame::renameAllUpperCaseWord()`, - -Were deprecated in favor of using new method: `DataFrame::renameEach()` with proper `RenameEntryStrategy` object. - -### 2) Deprecated `RenameAllCaseTransformer` & `RenameStrReplaceAllEntriesTransformer` - -Selected transformers were deprecated in favor of using `DataFrame::renameEach()` with related `RenameEntryStrategy`: - -- `RenameAllCaseTransformer` -> `RenameCaseTransformer`, -- `RenameStrReplaceAllEntriesTransformer` -> `RenameReplaceStrategy`, - ---- - -## Upgrading from 0.14.x to 0.15.x - -### 1) Removed `Flow\ETL\Row\Schema\Matcher` and implementations - -Schema Matcher was the initial attempt to implement a schema evolution next to schema validation that over time got -replaced with a different implementation of Schema Validator. - -### 2) Renamed `Flow\ETL\Row\Schema` namespace into `Flow\ETL\Schema`. - -This means all classes related to Schema now live under `Flow\ETL\Schema` namespace. - ---- - -## Upgrading from 0.11.x to 0.14.x - -### 1) Replaced `Flow\ETL\DataFrame::validate()` with `Flow\ETL\DataFrame::match()` - -The old method is now deprecated and will be removed in the next release. - -### 2) Replaced `Flow\ETL\Function\ScalarFunction\TypedScalarFunction` with - -`Flow\ETL\Function\ScalarFunction\ScalarResult`. - -The old interface was used to allow defining the return type of the ScalarFunctions. It was replaced with a ScalarResult -value object that is much more flexible than the interface, because it's allowing to return any type dynamically without -making the scalar function stateful. - -## Upgrading from 0.10.x to 0.11.x - -### 1) Removed StructureElement/struct_element/structure_element from StructureType Definition - -Before: - -```php -type_structure([ - struct_element('name', string()), - struct_element('age', integer()), -]); -``` - -After: - -```php -type_structure([ - 'name' => string(), - 'age' => integer(), -]); -``` - -### 2) Doctrine DBAL Adapter - -From now options for: - -- `to_dbal_table_insert()` -- `to_db_table_update()` - -are passed as objects (instance of UpdateOptions|InsertOptions interfaces) and they are platform specific, so please use -the proper class for the platform you are using. - -- PostgreSQL - - PostgreSQLInsertOptions - - PostgreSQLUpdateOptions -- MySQL - - MySQLInsertOptions - - MySQLUpdateOptions -- Sqlite - - SQLiteInsertOptions - - SQLiteUpdateOptions - -## Upgrading from 0.8.x to 0.10.x - -### 1) Providing multiple paths to a single extractor - -From now to read from multiple locations use `from_all(Extractor ...$extractors) : Exctractor` extractor. - -Before: - -```php -withSchema($schema); -``` - -## Upgrading from 0.7.x to 0.8.x - -### 1) Joins - -To support joining bigger datasets, we had to move from initial NestedLoop join algorithm into Hash Join algorithm. - -- the only supported coin expression is `=` (equals) that can be grouped with `AND` and `OR` operators. -- `joinPrefix` is now always required, and by default is set to 'joined_' -- join will always result all columns from both datasets, columns used in join condition will be prefixed with - `joinPrefix`. - -Other than that, API stays the same. - -Above changes were introduced in all 3 types of joins: - -- `DataFrame::join()` -- `DataFrame::joinEach()` -- `DataFrame::crossJoin()` - -### 2) GroupBy - -From now on, `DataFrame::groupBy()` method will return `GroupedDataFrame` object, which is nothing more than a GroupBy -statement Builder. To get the results, you first need to define the aggregation functions or optionally pivot the data. - -## Upgrading from 0.6.x to 0.7.x - -### 1) DataFrame::appendSafe () method was removed - -`DataFrame::appendSafe()` aka `DataFrame::threadSafe()` method was removed as it was introducing additional complexity -and was not used in any of the adapters. - -## Upgrading from 0.5.x to 0.6.x - -### 1) Rows::merge () accepts single instance of Rows - -Before: - -```php -Rows::merge(Rows ...$rows) : Rows -``` - -After: - -```php -Rows::merge(Rows $rows) : Rows -``` - ---- - -## Upgrading from 0.4.x to 0.5.x - -### 1) Entry factory moved from extractors to `FlowContext` - -To improve code quality and reduce code coupling `EntryFactory` was removed from all constructors of extractors, in -favor of passing it into `FlowContext` & re-using same entry factory in a whole pipeline. - -### 2) Invalid schema has no fallback in `NativeEntryFactory` - -Before, passing `Schema` into `NativeEntryFactory::create()` had fallback when the given entry was not found in a passed -schema, now the schema has higher priority & fallback is no longer available, instead when the definition is missing in -a passed schema, `InvalidArgumentException` will be thrown. - -### 3) BufferLoader was removed - -BufferLoader was removed in favor of `DataFrame::collect(int $batchSize = null)` method which now accepts additional -argument `$batchSize` that will keep collecting Rows from Extractor until the given batch size is reached. Which does -exactly the same thing as BufferLoader did, but in a more generic way. - -### 4) Pipeline Closure - -Pipeline Closure was reduced to be only Loader Closure and it was moved to \Flow\ETL\Loader namespace. Additionally, -\Closure::close method no longer requires Rows to be passed as an argument. - -### 5) Parallelize - -DataFrame::parallelize () method is deprecated, and it will be removed, instead use DataFrame::batchSize (int $size) -method. - -### 6) Rows in batch - Extractors - -From now, file-based Extractors will always throw one Row at time, in order to merge them into bigger groups use -`DataFrame::batchSize(int $size)` just after extractor method. - -Before: - -```php -read(CSV::from(__DIR__ . '/1_mln_rows.csv', rows_in_batch: 100)) - ->write(To::output()) - ->count(); -``` - -After: - -```php -(new Flow()) - ->read(CSV::from(__DIR__ . '/1_mln_rows.csv',)) - ->batchSize(100) - ->write(To::output()) - ->count(); -``` - -Affected extractors: - -- CSV -- Parquet -- JSON -- Text -- XML -- Avro -- DoctrineDBAL - `rows_in_batch` wasn't removed, but now results are thrown row by row, instead of whole page. -- GoogleSheet - -### 7) `GoogleSheetExtractor` - -Argument `$rows_in_batch` was renamed to `$rows_per_page` which no longer determines the size of the batch, but the size -of the page that will be fetched from Google API. Rows are yielded one by one. - -### 8) `DataFrame::threadSafe()` method was replaced by `DataFrame::appendSafe()` - -`DataFrame::appendSafe()` is doing exactly the same thing as the old method, it's just more descriptive and -self-explanatory. It's no longer mandatory to set this flat to true when using SaveMode::APPEND, it's now set -automatically. - -### 9) Loaders - chunk size - -Loaders are no longer accepting chunk_size parameter, from now in order to control the number of rows saved at once use -`DataFrame::batchSize(int $size)` method. - -### 10) Removed DSL functions: `datetime_string()`, `json_string()` - -Those functions were removed in favor of accepting string values in related DSL functions: - -- `datetime_string()` => `datetime()`, -- `json_string()` => `json()` & `json_object()` - -### 11) Removed Asynchronous Processing - -More details can be found in [this issue](https://github.com/flow-php/flow/issues/793). - -- Removed etl-adapter-amphp -- Removed etl-adapter-reactphp -- Removed `LocalSocketPipeline` -- Removed `DataFrame::pipeline()` - -### 12) `CollectionEntry` removal - -After adding native & logical types into the Flow, we remove the `CollectionEntry` as obsolete. New types that cover it -better are: `ListType`, `MapType` & `StructureType` along with related new entry types. - -### 13) Removed `from*()` methods from scalar entries - -Removed `BooleanEntry::from()`, `FloatEntry::from()`, `IntegerEntry::from()`, `StringEntry::fromDateTime()` methods in -favor of using DSL functions. - -### 14) Removed deprecated `Sha1IdFactory` - -Class `Sha1IdFactory` was removed, use `HashIdFactory` class: - -```php -(new HashIdFactory('entry_name'))->withAlgorithm('sha1'); -``` - -### 15) Deprecate DSL Static classes - -DSL static classes were deprecated in favor of using functions defined in `src/core/etl/src/Flow/ETL/DSL/functions.php` -file. - -Deprecated classes: - -- `src/core/etl/src/Flow/ETL/DSL/From.php` -- `src/core/etl/src/Flow/ETL/DSL/Handler.php` -- `src/core/etl/src/Flow/ETL/DSL/To.php` -- `src/core/etl/src/Flow/ETL/DSL/Transform.php` -- `src/core/etl/src/Flow/ETL/DSL/Partitions.php` -- `src/adapter/etl-adapter-avro/src/Flow/ETL/DSL/Avro.php` -- `src/adapter/etl-adapter-chartjs/src/Flow/ETL/DSL/ChartJS.php` -- `src/adapter/etl-adapter-csv/src/Flow/ETL/DSL/CSV.php` -- `src/adapter/etl-adapter-doctrine/src/Flow/ETL/DSL/Dbal.php` -- `src/adapter/etl-adapter-elasticsearch/src/Flow/ETL/DSL/Elasticsearch.php` -- `src/adapter/etl-adapter-google-sheet/src/Flow/ETL/DSL/GoogleSheet.php` -- `src/adapter/etl-adapter-json/src/Flow/ETL/DSL/Json.php` -- `src/adapter/etl-adapter-meilisearch/src/Flow/ETL/DSL/Meilisearch.php` -- `src/adapter/etl-adapter-parquet/src/Flow/ETL/DSL/Parquet.php` -- `src/adapter/etl-adapter-text/src/Flow/ETL/DSL/Text.php` -- `src/adapter/etl-adapter-xml/src/Flow/ETL/DSL/XML.php` - ---- - -## Upgrading from 0.3.x to 0.4.x - -### 1) Transformers replaced with scalar functions - -Transformers are a really powerful tool that was used in Flow since the beginning, but that tool was too powerful for -the simple cases that were needed, and introduced additional complexity and maintenance issues when they were -handwritten. - -We reworked most of the internal transformers to new scalar functions and entry scalar functions (based on the built-in -functions), and we still internally use that powerful tool, but we don't expose it to end users, instead, we provide -easy-to-use, covering all user needs functions. - -All available functions can be found in [`ETL\Row\Function` folder](src/core/etl/src/Flow/ETL/Function) or in [ -`ETL\DSL\functions` file](src/core/etl/src/Flow/ETL/DSL/functions.php), and entry scalar functions are defined in -`EntryScalarFunction`. - -Before: - -```php -read(new MemoryExtractor()) - ->rows(Transform::string_concat(['name', 'last name'], ' ', 'name')) -``` - -After: - -```php -read(new MemoryExtractor()) - ->withEntry('name', concat(ref('name'), lit(' '), ref('last name'))) -``` - -### 2) `ref` function nullability - -`ref("entry_name")` is no longer returning null when the entry is not found. Instead, it throws an exception. The same -behavior can be achieved through using a newly introduced `optional` function: - -Before: - -```php -cast('string'); -``` - -After: - -```php -cast('string'); -// or -optional(ref('non_existing_column')->cast('string')); -``` - -### 3) Extractors output - -Affected extractors: - -* CSV -* JSON -* Avro -* DBAL -* GoogleSheet -* Parquet -* Text -* XML - -Extractors are no longer returning data under an array entry called `row`, thanks to this unpacking row become -redundant. - -Because of that all DSL functions are no longer expecting `$entry_row_name` parameter, if it was used anywhere, please -remove it. - -Before: - -```php -read(From::array([['id' => 1, 'array' => ['a' => 1, 'b' => 2, 'c' => 3]]])) - ->withEntry('row', ref('row')->unpack()) - ->renameAll('row.', '') - ->drop('row') - ->withEntry('array', ref('array')->arrayMerge(lit(['d' => 4]))) - ->write(To::memory($memory = new ArrayMemory())) - ->run(); -``` - -After: - -```php -read(From::array([['id' => 1, 'array' => ['a' => 1, 'b' => 2, 'c' => 3]]])) - ->withEntry('array', ref('array')->arrayMerge(lit(['d' => 4]))) - ->write(To::memory($memory = new ArrayMemory())) - ->run(); -``` - -### 4) ConfigBuilder::putInputIntoRows () output is now prefixed with _ (underscore) - -In order to avoid collisions with datasets columns, additional columns created after using putInputIntoRows () -would now be prefixed with `_` (underscore) symbol. - -Before: - -```php -putInputIntoRows())) - ->read(Json::from(__DIR__ . '/../Fixtures/timezones.json', 5)) - ->fetch(); - -foreach ($rows as $row) { - $this->assertSame( - [ - ... - '_input_file_uri', - ], - \array_keys($row->toArray()) - ); -} -``` - -After: - -```php -putInputIntoRows())) - ->read(Json::from(__DIR__ . '/../Fixtures/timezones.json', 5)) - ->fetch(); - -foreach ($rows as $row) { - $this->assertSame( - [ - ... - '_input_file_uri', - ], - \array_keys($row->toArray()) - ); -} -``` 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 e1c982a389..f50bcc1f35 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 @@ -37,7 +37,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - yield new Rows(new Schema()); + yield Rows::of(new Schema()); } public function schema(): Schema diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVHydratorParityTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVHydratorParityTest.php index d2408c3e79..11ad67c833 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVHydratorParityTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVHydratorParityTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\CSV\Tests\Integration; use Flow\ETL\Config; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\CSV\from_csv; @@ -46,64 +45,6 @@ public function test_hydrates_typed_columns_with_empty_to_null_and_input_uri(): ); } - public function test_honours_a_hydrator_configured_on_the_context(): void - { - $extractor = from_csv(path_real(__DIR__ . '/../Fixtures/file_with_empty_columns.csv')) - ->withSchema(schema( - int_schema('id', nullable: true), - str_schema('name', nullable: true), - bool_schema('active', nullable: true), - )); - - $actual = []; - - foreach ($extractor->extract( - flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build()), - ) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); - } - } - - static::assertSame( - [ - ['id' => null, 'name' => null, 'active' => false], - ['id' => 1, 'name' => 'Norbert', 'active' => null], - ], - $actual, - ); - } - - public function test_honours_a_hydrator_configured_on_the_context_without_a_declared_schema(): void - { - $default = []; - - foreach (from_csv(path_real(__DIR__ . '/../Fixtures/file_with_empty_columns.csv')) - ->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $default[] = $row->toArray(); - } - } - - $adaptive = []; - - foreach (from_csv(path_real(__DIR__ . '/../Fixtures/file_with_empty_columns.csv')) - ->extract(flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build())) as $rows) { - foreach ($rows as $row) { - $adaptive[] = $row->toArray(); - } - } - - static::assertSame($default, $adaptive); - static::assertSame( - [ - ['id' => null, 'name' => null, 'active' => false], - ['id' => 1, 'name' => 'Norbert', 'active' => null], - ], - $default, - ); - } - public function test_reads_partitioned_files_with_schema_typed_partition_values(): void { $extractor = from_csv(__DIR__ . '/../Fixtures/partitioned/group=*/*.csv')->withSchema(schema( 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 686b22063c..f1de450992 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 @@ -119,7 +119,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $yielded++; if (count($buffer) === $this->batchSize) { - $signal = yield Rows::trusted($hydrated->schema(), $buffer); + $signal = yield Rows::of($hydrated->schema(), ...$buffer); if ($signal === Signal::STOP) { return; @@ -134,7 +134,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator } if ($buffer !== []) { - $signal = yield Rows::trusted($hydrated->schema(), $buffer); + $signal = yield Rows::of($hydrated->schema(), ...$buffer); if ($signal === Signal::STOP) { return; 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 d4744e3146..0eeb7ffb20 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 @@ -15,7 +15,6 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Extractor\Signal; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Double\CountingFilesystem; @@ -550,30 +549,6 @@ public function test_schema_then_extract_on_the_same_instance(string $fixtureNam static::assertCount(10, df()->extract($extractor)->fetch()->toArray()); } - public function test_the_same_schema_on_both_hydrators(): void - { - $extractor = from_excel(ExcelFixtureContext::file('fixture.xlsx')); - - $default = df() - ->extract(from_excel(ExcelFixtureContext::file('fixture.xlsx'))) - ->fetch() - ->toArray(); - $adaptive = []; - - foreach ($extractor->extract( - flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build()), - ) as $rows) { - static::assertEquals($extractor->schema(), $rows->schema()); - - foreach ($rows->toArray() as $row) { - $adaptive[] = $row; - } - } - - static::assertCount(10, $adaptive); - static::assertSame($default, $adaptive); - } - public function test_the_sample_leaves_no_shared_strings_temp_folder(): void { $before = ExcelFixtureContext::sharedStringsFolders(); diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelHydratorParityTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelHydratorParityTest.php index 3552d48c2b..4f0b66a8d5 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelHydratorParityTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelHydratorParityTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\Excel\Tests\Integration; use Flow\ETL\Config; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\Excel\DSL\from_excel; @@ -47,22 +46,4 @@ public function test_appends_input_file_uri_when_metadata_columns_are_enabled(): } } } - - public function test_honours_a_hydrator_configured_on_the_context(): void - { - $extractor = from_excel(path_real(__DIR__ . '/../Fixtures/fixture.xlsx')); - - $count = 0; - - foreach ($extractor->extract( - flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build()), - ) as $rows) { - static::assertEquals($extractor->schema(), $rows->schema()); - static::assertEquals(type_integer(), $rows->schema()->get('id')->type()); - - $count += $rows->count(); - } - - static::assertSame(10, $count); - } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetHydratorParityTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetHydratorParityTest.php index bd5dd50e6d..107a93381b 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetHydratorParityTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetHydratorParityTest.php @@ -6,11 +6,7 @@ use Flow\ETL\Adapter\GoogleSheet\Tests\GoogleSheetsContext; use Flow\ETL\Config; -use Flow\ETL\Row\AdaptiveRowHydrator; -use Flow\ETL\Row\Hydrator; -use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Tests\FlowTestCase; -use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\Adapter\GoogleSheet\from_google_sheet; use function Flow\ETL\DSL\bool_schema; @@ -25,12 +21,6 @@ final class GoogleSheetHydratorParityTest extends FlowTestCase { - public static function hydrators(): iterable - { - yield 'php' => [new PhpRowHydrator()]; - yield 'adaptive' => [new AdaptiveRowHydrator()]; - } - public function test_appends_spread_sheet_id_and_sheet_name_to_the_schema_when_metadata_columns_are_enabled(): void { $extractor = from_google_sheet( @@ -57,31 +47,7 @@ public function test_appends_spread_sheet_id_and_sheet_name_to_the_schema_when_m } } - public function test_honours_a_hydrator_configured_on_the_context(): void - { - $extractor = from_google_sheet( - (new GoogleSheetsContext())->sheets( - __DIR__ . '/../Fixtures/sample-batch.json', - __DIR__ . '/../Fixtures/batch.json', - ), - '1234567890', - 'Sheet', - ); - - $count = 0; - - foreach ($extractor->extract( - flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build()), - ) as $batch) { - static::assertTrue($batch->schema()->isSame($extractor->schema())); - $count += $batch->count(); - } - - static::assertSame(19, $count); - } - - #[DataProvider('hydrators')] - public function test_infers_the_same_typed_rows_on_both_hydrators(Hydrator $hydrator): void + public function test_infers_typed_rows(): void { $extractor = from_google_sheet( (new GoogleSheetsContext())->sheetsOfGrid( @@ -95,7 +61,7 @@ public function test_infers_the_same_typed_rows_on_both_hydrators(Hydrator $hydr $rows = []; - foreach ($extractor->extract(flow_context(Config::builder()->hydrator($hydrator)->build())) as $batch) { + foreach ($extractor->extract(flow_context(Config::builder()->build())) as $batch) { static::assertTrue( $batch ->schema() diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php index a9f72d5cea..ce25c15aae 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php @@ -121,11 +121,11 @@ public function test_its_stop_fetching_data_if_processed_row_count_is_less_then_ static::assertCount(2, $rows); static::assertEquals( - row(['_sheet_name' => 'sheet', '_spread_sheet_id' => 'spread-id', 'header' => 'row1']), + row(['header' => 'row1', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet']), $rows->all()[0], ); static::assertEquals( - row(['_sheet_name' => 'sheet', '_spread_sheet_id' => 'spread-id', 'header' => 'row2']), + row(['header' => 'row2', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet']), $rows->all()[1], ); } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/SchemaConverter.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/SchemaConverter.php index c055118dbb..4474b0fbda 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/SchemaConverter.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/SchemaConverter.php @@ -63,7 +63,6 @@ use function Flow\Types\DSL\type_json; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; -use function Flow\Types\DSL\type_mixed; use function Flow\Types\DSL\type_null; use function Flow\Types\DSL\type_optional; use function Flow\Types\DSL\type_string; @@ -321,7 +320,7 @@ private function convertArray(array $schema, string $path): Type return type_list($this->convert($items, $path . '.items')); } - return type_list(type_mixed()); + return type_json(); } /** @@ -469,7 +468,7 @@ private function convertObject(array $schema, string $path): Type return type_map(type_string(), $this->convert($additionalProperties, $path . '.additionalProperties')); } - return type_map(type_string(), type_mixed()); + return type_json(); } /** diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonHydratorParityTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonHydratorParityTest.php index ffe0db0677..9f9610b69c 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonHydratorParityTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonHydratorParityTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\JSON\Tests\Integration\JSONMachine; use Flow\ETL\Config; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\JSON\from_json; @@ -95,34 +94,4 @@ public function test_appends_partition_columns_absent_from_the_schema(): void $actual, ); } - - public function test_honours_a_hydrator_configured_on_the_context_without_a_declared_schema(): void - { - $default = []; - - foreach (from_json(path_real(__DIR__ . '/../../Fixtures/parity_people.json')) - ->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $default[] = $row->toArray(); - } - } - - $adaptive = []; - - foreach (from_json(path_real(__DIR__ . '/../../Fixtures/parity_people.json')) - ->extract(flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build())) as $rows) { - foreach ($rows as $row) { - $adaptive[] = $row->toArray(); - } - } - - static::assertSame( - [ - ['id' => 1, 'name' => 'Alice', 'active' => true], - ['id' => 2, 'name' => null, 'active' => false], - ], - $default, - ); - static::assertSame($default, $adaptive); - } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesHydratorParityTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesHydratorParityTest.php index c09e980294..a3711c8435 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesHydratorParityTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesHydratorParityTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\JSON\Tests\Integration\JSONMachine; use Flow\ETL\Config; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\JSON\from_json_lines; @@ -39,58 +38,4 @@ public function test_hydrates_typed_columns_with_missing_column_null(): void $actual, ); } - - public function test_honours_a_hydrator_configured_on_the_context(): void - { - $extractor = from_json_lines(path_real(__DIR__ . '/../../Fixtures/parity_people.jsonl')) - ->withSchema(schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('active'))); - - $actual = []; - - foreach ($extractor->extract( - flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build()), - ) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); - } - } - - static::assertSame( - [ - ['id' => 1, 'name' => 'Alice', 'active' => true], - ['id' => 2, 'name' => null, 'active' => false], - ], - $actual, - ); - } - - public function test_honours_a_hydrator_configured_on_the_context_without_a_declared_schema(): void - { - $default = []; - - foreach (from_json_lines(path_real(__DIR__ . '/../../Fixtures/parity_people.jsonl')) - ->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $default[] = $row->toArray(); - } - } - - $adaptive = []; - - foreach (from_json_lines(path_real(__DIR__ . '/../../Fixtures/parity_people.jsonl')) - ->extract(flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build())) as $rows) { - foreach ($rows as $row) { - $adaptive[] = $row->toArray(); - } - } - - static::assertSame( - [ - ['id' => 1, 'name' => 'Alice', 'active' => true], - ['id' => 2, 'name' => null, 'active' => false], - ], - $default, - ); - static::assertSame($default, $adaptive); - } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/SchemaConverterTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/SchemaConverterTest.php index a720b6d8cf..cc19394e04 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/SchemaConverterTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/SchemaConverterTest.php @@ -121,7 +121,7 @@ public function test_to_flow_any_of_with_only_null_members_becomes_null_definiti static::assertEquals(schema(null_schema('value')), $flowSchema); } - public function test_to_flow_array_without_items_becomes_list_of_mixed(): void + public function test_to_flow_array_without_items_becomes_json(): void { $flowSchema = (new SchemaConverter())->toFlow([ 'type' => 'object', @@ -131,7 +131,7 @@ public function test_to_flow_array_without_items_becomes_list_of_mixed(): void ], ]); - static::assertEquals(schema(list_schema('values', type_list(type_mixed()))), $flowSchema); + static::assertEquals(schema(json_schema('values')), $flowSchema); } public function test_to_flow_basic_types(): void @@ -315,7 +315,7 @@ public function test_to_flow_enum_with_null_value_becomes_nullable(): void ); } - public function test_to_flow_free_form_object_becomes_map_of_mixed(): void + public function test_to_flow_free_form_object_becomes_json(): void { $flowSchema = (new SchemaConverter())->toFlow([ 'type' => 'object', @@ -325,7 +325,7 @@ public function test_to_flow_free_form_object_becomes_map_of_mixed(): void ], ]); - static::assertEquals(schema(map_schema('attributes', type_map(type_string(), type_mixed()))), $flowSchema); + static::assertEquals(schema(json_schema('attributes')), $flowSchema); } public function test_to_flow_internal_reference_via_defs(): void diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetHydratorParityTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetHydratorParityTest.php index 6dfad7a5d3..aacb11ffcf 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetHydratorParityTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetHydratorParityTest.php @@ -6,7 +6,7 @@ use Flow\ETL\Adapter\Parquet\ParquetEncoder; use Flow\ETL\Adapter\Parquet\SchemaConverter; -use Flow\ETL\Row\AdaptiveRowHydrator; +use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Row\RawRowValues; use Flow\ETL\Tests\Double\FakeExtractor; use Flow\ETL\Tests\FlowTestCase; @@ -26,7 +26,7 @@ /** * Guards the Parquet read path: the trusted (no-cast) read - reader values normalized to Flow-native * by ParquetEncoder::decode, then hydrated without casting - must be byte-identical to the previous - * casting read (AdaptiveRowHydrator over the raw reader values). If the reader ever returns a value the + * casting read (PhpRowHydrator over the raw reader values). If the reader ever returns a value the * casting read fixed but decode does not, this fails loudly. */ final class ParquetHydratorParityTest extends FlowTestCase @@ -55,8 +55,8 @@ public function test_trusted_read_is_identical_to_a_casting_read(): void $encoder = new ParquetEncoder($file->schema()); $decodedRows = $encoder->decode($rawRows); - $trusted = (new AdaptiveRowHydrator())->hydrate($decodedRows, $flowSchema); - $cast = (new AdaptiveRowHydrator())->hydrate( + $trusted = (new PhpRowHydrator())->hydrate($decodedRows, $flowSchema); + $cast = (new PhpRowHydrator())->hydrate( array_map(static fn(array $values): RawRowValues => new RawRowValues($values), $rawRows), $flowSchema, ); diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextHydratorParityTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextHydratorParityTest.php index 142867a760..b3fe83c723 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextHydratorParityTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextHydratorParityTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\Text\Tests\Integration; use Flow\ETL\Config; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\Text\from_text; @@ -53,21 +52,4 @@ public function test_appends_input_file_uri_when_metadata_columns_are_enabled(): $actual, ); } - - public function test_honours_a_hydrator_configured_on_the_context(): void - { - $extractor = from_text(path_real(__DIR__ . '/../Fixtures/parity_lines.txt')); - - $actual = []; - - foreach ($extractor->extract( - flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build()), - ) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); - } - } - - static::assertSame([['text' => 'alpha'], ['text' => 'beta'], ['text' => 'gamma']], $actual); - } } diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLHydratorParityTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLHydratorParityTest.php index e4fb5466de..9441f6575e 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLHydratorParityTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLHydratorParityTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\XML\Tests\Integration; use Flow\ETL\Config; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\XML\from_xml; @@ -45,21 +44,4 @@ public function test_appends_input_file_uri_when_metadata_columns_are_enabled(): } } } - - public function test_honours_a_hydrator_configured_on_the_context(): void - { - $extractor = from_xml(path_real(__DIR__ . '/../Fixtures/simple_items.xml'))->withXMLNodePath('root/items/item'); - - $count = 0; - - foreach ($extractor->extract( - flow_context(Config::builder()->hydrator(new AdaptiveRowHydrator())->build()), - ) as $batch) { - static::assertEquals(type_xml(), $batch->schema()->get('node')->type()); - - $count += $batch->count(); - } - - static::assertSame(5, $count); - } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/HashBucketing.php b/src/core/etl/src/Flow/ETL/Bucketing/HashBucketing.php index 4c87a5e71f..b09c63872b 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/HashBucketing.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/HashBucketing.php @@ -70,7 +70,7 @@ public function bucketize(Generator $rows, BucketsStorage $storage): Generator // a bucket is a subset of a batch that already passed the gate, under the same schema foreach ($groups as $id => $groupRows) { - $storage->append($id, Rows::trusted($batch->schema(), $groupRows)); + $storage->append($id, Rows::of($batch->schema(), ...$groupRows)); $totals[$id] = ($totals[$id] ?? 0) + count($groupRows); } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php b/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php index 2f8151a65b..d93d4cf999 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php @@ -50,7 +50,7 @@ public function group(Generator $rows): Generator } foreach ($groups as $rowsOfKey) { - yield new Rows($schema, ...$rowsOfKey); + yield Rows::of($schema, ...$rowsOfKey); } } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/SortedRunBucketing.php b/src/core/etl/src/Flow/ETL/Bucketing/SortedRunBucketing.php index 2433817a56..56829b45c9 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/SortedRunBucketing.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/SortedRunBucketing.php @@ -50,7 +50,7 @@ public function bucketize(Generator $rows, BucketsStorage $storage): Generator } } - if ($buffer !== null && !$buffer->empty()) { + if ($buffer !== null && !$buffer->isEmpty()) { yield $this->spill($buffer, $storage, $runId, $index); } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Storage/MemoryBuckets.php b/src/core/etl/src/Flow/ETL/Bucketing/Storage/MemoryBuckets.php index e31a16e685..9ca5edfb62 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/Storage/MemoryBuckets.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/Storage/MemoryBuckets.php @@ -17,7 +17,7 @@ final class MemoryBuckets implements ResidentBucketsStorage public function append(string $bucketId, Rows $rows): void { - if (!$rows->empty()) { + if (!$rows->isEmpty()) { $this->buckets[$bucketId][] = $rows; } } diff --git a/src/core/etl/src/Flow/ETL/Column/Backend.php b/src/core/etl/src/Flow/ETL/Column/Backend.php new file mode 100644 index 0000000000..8cb947c07b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Backend.php @@ -0,0 +1,30 @@ + $definition nullability, the enum class, the datetime zone and the cast plan + */ + public function builder(Definition $definition): ColumnBuilder; + + /** + * $value is logical or raw and is cast once through the Definition exactly like ColumnBuilder::append(). + * + * @param Definition $definition + */ + public function constant(Definition $definition, mixed $value, int $count): Column; + + /** + * Child node lengths and null counts are derived from the buffers, so only the top node travels. + * + * @param Definition $definition + * @param list $buffers the column's subtree buffers as Column::encode() produced them ('' = omitted validity) + */ + public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column; +} diff --git a/src/core/etl/src/Flow/ETL/Column/Column.php b/src/core/etl/src/Flow/ETL/Column/Column.php new file mode 100644 index 0000000000..49cf3fd143 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Column.php @@ -0,0 +1,73 @@ + + */ + public function type(): Type; + + public function count(): int; + + public function isNull(int $i): bool; + + public function nullCount(): int; + + /** + * PHYSICAL cell: int|float|bool|string|array|null - never a DateTimeImmutable, Uuid, Json … + */ + public function at(int $i): mixed; + + /** + * @return list physical, whole column - PHP returns its backing list (refcount), native copies once + */ + public function physicals(): array; + + /** + * LOGICAL cell - PHP: Physical::fromPhysical(at($i)); native: built in Rust. + */ + public function value(int $i): mixed; + + /** + * @return list logical, whole column (encoders, statistics, reduceToArray) + */ + public function values(): array; + + /** + * `self`, never `static`: the extension declares these too and ext-php-rs has no `static` return binding. + */ + public function slice(int $offset, int $length): self; + + /** + * @param list $indices every index in [0, count()) + */ + public function take(array $indices): self; + + /** + * The one type-changing operation: same buffers, a new Type of the same column kind, checked recursively. + * Dropping an OptionalType or an element's optionality at any depth requires that child column's + * nullCount() === 0. + * + * @param Type $type + */ + public function withType(Type $type): self; + + /** + * Same-class lane; a mixed-class concat never reaches here - Rows::concat routes it through PhpBackend. + */ + public function concat(self ...$others): self; + + /** + * @return list the column's frame buffers in the kind's buffer order, pre-order for nested kinds, in + * canonical form; an omitted validity buffer is '' + */ + public function encode(): array; +} diff --git a/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php new file mode 100644 index 0000000000..a6ece37bfe --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php @@ -0,0 +1,37 @@ + $values one cast loop per column - the bulk door + * + * @throws SchemaMismatchException at the first refused value, its row the value's position in $values + */ + public function appendMany(array $values): void; + + /** + * Copies one physical cell, no materialisation. + */ + public function appendFrom(Column $column, int $i): void; + + /** + * @param list $indices gathered physically from $column + */ + public function appendTake(Column $column, array $indices): void; + + public function count(): int; + + public function finish(): Column; +} diff --git a/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php b/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php new file mode 100644 index 0000000000..a75a75bb10 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php @@ -0,0 +1,32 @@ +php = new PhpBackend(); + } + + public function builder(Definition $definition): ColumnBuilder + { + return $this->php->builder($definition); + } + + public function constant(Definition $definition, mixed $value, int $count): Column + { + return $this->php->constant($definition, $value, $count); + } + + public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column + { + return $this->php->decode($definition, $buffers, $count, $nullCount); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/BooleanLayout.php b/src/core/etl/src/Flow/ETL/Column/Php/BooleanLayout.php new file mode 100644 index 0000000000..ed5f1a9ff4 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/BooleanLayout.php @@ -0,0 +1,60 @@ +next(); + + if (strlen($buffer) < intdiv($count + 7, 8)) { + throw new InvalidArgumentException(sprintf( + 'Boolean values buffer of %d bytes, expected %d for %d rows', + strlen($buffer), + intdiv($count + 7, 8), + $count, + )); + } + + $physicals = []; + + for ($i = 0; $i < $count; $i++) { + $physicals[] = $valid[$i] ? ((ord($buffer[$i >> 3]) >> ($i & 7)) & 1) === 1 : null; + } + + return $physicals; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Buffers.php b/src/core/etl/src/Flow/ETL/Column/Php/Buffers.php new file mode 100644 index 0000000000..50a4274214 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/Buffers.php @@ -0,0 +1,35 @@ + $buffers + */ + public function __construct( + private readonly array $buffers, + ) {} + + public function next(): string + { + if ($this->position >= count($this->buffers)) { + throw new InvalidArgumentException('Column buffers exhausted: the column needs more buffers than given'); + } + + return $this->buffers[$this->position++]; + } + + public function remaining(): int + { + return count($this->buffers) - $this->position; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php new file mode 100644 index 0000000000..70666b1427 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php @@ -0,0 +1,137 @@ + + */ + private readonly Type $type; + + /** + * @param Definition $definition + */ + public function __construct( + private readonly Definition $definition, + private readonly Physical $physical, + private readonly PhpColumnBuilder $physicals, + ) { + $this->identity = $physical instanceof IdentityPhysical; + $this->nullable = $definition->isNullable() || $definition instanceof NullDefinition; + $this->type = $definition->type(); + } + + public function append(mixed $value): void + { + if ($value === null) { + if (!$this->nullable) { + throw ColumnMismatchException::valueDoesNotMatch($this->definition, null); + } + + $this->physicals->appendPhysical(null); + + return; + } + + $this->physicals->appendPhysical($this->physical->toPhysical($this->type->cast($value))); + } + + public function appendFrom(Column $column, int $i): void + { + if (!$this->nullable && $column->isNull($i)) { + throw ColumnMismatchException::valueDoesNotMatch($this->definition, null); + } + + $this->physicals->appendPhysical($column->at($i)); + } + + public function appendMany(array $values): void + { + $physicals = []; + $nulls = 0; + $position = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $position => $value) { + if ($value === null) { + if (!$this->nullable) { + throw ColumnMismatchException::valueDoesNotMatch($this->definition, null); + } + + $physicals[] = null; + $nulls++; + + continue; + } + + // @mago-ignore analysis:mixed-assignment + $cast = $this->type->cast($value); + + if ($this->identity) { + $physicals[] = $cast; + + continue; + } + + try { + $physicals[] = $this->physical->toPhysical($cast); + } catch (TypesException $e) { + // the value cast, so only the physical form's reason (a range) tells the user why it was refused + throw ColumnMismatchException::valueDoesNotMatch($this->definition, $value, $e); + } + } + } catch (ColumnMismatchException $e) { + throw new SchemaMismatchException($position, $e); + } catch (TypesException) { + throw new SchemaMismatchException($position, ColumnMismatchException::valueDoesNotMatch( + $this->definition, + $values[$position], + )); + } + + $this->physicals->appendPhysicalMany($physicals, $nulls); + } + + public function appendTake(Column $column, array $indices): void + { + $all = $column->physicals(); + $physicals = []; + + foreach ($indices as $index) { + if (!$this->nullable && $all[$index] === null) { + throw ColumnMismatchException::valueDoesNotMatch($this->definition, null); + } + + $physicals[] = $all[$index]; + } + + $this->physicals->appendPhysicalMany($physicals); + } + + public function count(): int + { + return $this->physicals->count(); + } + + public function finish(): Column + { + return $this->physicals->finish(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php b/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php new file mode 100644 index 0000000000..bfcbfbb860 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php @@ -0,0 +1,107 @@ + $type + * @param int $nullCount -1 derives the null count from the validity buffer + * + * @throws InvalidArgumentException + */ + public function decode(Type $type, Buffers $buffers, int $count, int $nullCount): Column + { + $base = $type instanceof OptionalType ? $type->base() : $type; + + if ($base instanceof NullType) { + if ($nullCount !== -1 && $nullCount !== $count) { + throw new InvalidArgumentException(sprintf( + 'Null column of %d rows carries a null count of %d', + $count, + $nullCount, + )); + } + + return new ConstantColumn($type, new NullPhysical(), null, $count); + } + + $validity = new Validity(); + $bitmap = $buffers->next(); + $valid = $validity->valid($bitmap, $count); + $derived = $validity->nullCount($bitmap, $count); + + if ($nullCount !== -1 && $nullCount !== $derived) { + throw new InvalidArgumentException(sprintf( + 'Column null count %d disagrees with its validity bitmap (%d nulls in %d rows)', + $nullCount, + $derived, + $count, + )); + } + + if ($base instanceof ListType) { + $offsets = (new Offsets())->unpack($buffers->next(), $count, 'List'); + + return new ListColumn( + $type, + $offsets, + $this->decode($base->element(), $buffers, $offsets[$count], -1), + $validity->nulls($valid), + ); + } + + if ($base instanceof MapType) { + $offsets = (new Offsets())->unpack($buffers->next(), $count, 'Map'); + $entries = $buffers->next(); + + if ($entries !== '') { + throw new InvalidArgumentException(sprintf( + 'Map entries validity must be omitted, got %d bytes', + strlen($entries), + )); + } + + return new MapColumn( + $type, + $offsets, + $this->decode($base->key(), $buffers, $offsets[$count], -1), + $this->decode($base->value(), $buffers, $offsets[$count], -1), + $validity->nulls($valid), + ); + } + + if ($base instanceof StructureType) { + $children = []; + + foreach ($base->elements() as $element) { + $children[$element->name] = $this->decode($element->type, $buffers, $count, -1); + } + + return new StructColumn($type, $children, $validity->nulls($valid)); + } + + return new ScalarColumn( + $type, + (new PhysicalFor())->type($type), + (new LayoutFor()) + ->type($type) + ->decode($buffers, $count, $valid), + $derived, + ); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ConstantColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/ConstantColumn.php new file mode 100644 index 0000000000..c6c988b314 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ConstantColumn.php @@ -0,0 +1,125 @@ + $type + */ + public function __construct( + public Type $type, + public Physical $physical, + public mixed $physicalValue, + public int $count, + ) {} + + public function at(int $i): mixed + { + return $this->physicalValue; + } + + public function concat(Column ...$others): Column + { + $count = $this->count; + + foreach ($others as $other) { + if (!$other instanceof self || $other->physicalValue !== $this->physicalValue) { + return $this->expand()->concat(...array_map(static fn(Column $column): Column => $column instanceof self + ? $column->expand() + : $column, $others)); + } + + $count += $other->count; + } + + return new self($this->type, $this->physical, $this->physicalValue, $count); + } + + public function count(): int + { + return $this->count; + } + + public function encode(): array + { + return $this->isNullKind() ? [] : $this->expand()->encode(); + } + + public function expand(): Column + { + if ($this->isNullKind()) { + return $this; + } + + $builder = (new PhysicalBuilderFor())->type($this->type); + $builder->appendPhysicalMany($this->physicals()); + + return $builder->finish(); + } + + public function isNull(int $i): bool + { + return $this->physicalValue === null; + } + + public function isNullKind(): bool + { + return ($this->type instanceof OptionalType ? $this->type->base() : $this->type) instanceof NullType; + } + + public function nullCount(): int + { + return $this->physicalValue === null ? $this->count : 0; + } + + public function physicals(): array + { + // @mago-ignore analysis:possibly-invalid-argument + return $this->count === 0 ? [] : array_fill(0, $this->count, $this->physicalValue); + } + + public function slice(int $offset, int $length): Column + { + return new self($this->type, $this->physical, $this->physicalValue, $length); + } + + public function take(array $indices): Column + { + return new self($this->type, $this->physical, $this->physicalValue, count($indices)); + } + + public function type(): Type + { + return $this->type; + } + + public function value(int $i): mixed + { + return $this->physicalValue === null ? null : $this->physical->fromPhysical($this->physicalValue); + } + + public function values(): array + { + // @mago-ignore analysis:possibly-invalid-argument + return $this->count === 0 ? [] : array_fill(0, $this->count, $this->value(0)); + } + + public function withType(Type $type): Column + { + (new Retype())->assert($this->type, $type, $this->nullCount()); + + return new self($type, (new PhysicalFor())->type($type), $this->physicalValue, $this->count); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/DatePhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/DatePhysical.php new file mode 100644 index 0000000000..0ab9fc63b9 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/DatePhysical.php @@ -0,0 +1,66 @@ +days = new DaysFromCivil(); + $this->utc = new DateTimeZone('UTC'); + } + + public function toPhysical(mixed $value): mixed + { + assert($value instanceof DateTimeInterface); + + $days = $this->days->of((int) $value->format('Y'), (int) $value->format('n'), (int) $value->format('j')); + + if ($days < -2_147_483_648 || $days > 2_147_483_647) { + throw new CastingException($value, type_date(), reason: 'outside the day range of a date column'); + } + + return $days; + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_int($physical)); + + return (new DateTimeImmutable('@' . ($physical * 86_400)))->setTimezone($this->utc); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + if ($physical === null) { + $values[] = null; + + continue; + } + + assert(is_int($physical)); + $values[] = (new DateTimeImmutable('@' . ($physical * 86_400)))->setTimezone($this->utc); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/DateTimePhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/DateTimePhysical.php new file mode 100644 index 0000000000..061b9b072b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/DateTimePhysical.php @@ -0,0 +1,116 @@ +getTimestamp() * 1_000_000) + (int) $value->format('u'); + + // an i64 overflow of the multiplication or the addition yields a float at runtime + // @mago-ignore analysis:impossible-condition,redundant-type-comparison + if (!is_int($us)) { + throw new CastingException( + $value, + type_datetime(), + reason: 'outside the microsecond range of a datetime column', + ); + } + + return $us; + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_int($physical)); + + if (PHP_VERSION_ID >= 80400) { + $seconds = intdiv($physical, 1_000_000); + $micros = $physical % 1_000_000; + + if ($micros < 0) { + $micros += 1_000_000; + $seconds--; + } + + // @mago-ignore analysis:unavailable-method + $instant = DateTimeImmutable::createFromTimestamp($seconds); + + // @mago-ignore analysis:unavailable-method + return $instant->setMicrosecond($micros)->setTimezone($this->zone); + } + + return (new DateTimeImmutable(sprintf( + '@%s%d.%06d', + $physical < 0 ? '-' : '', + intdiv(abs($physical), 1_000_000), + abs($physical) % 1_000_000, + )))->setTimezone($this->zone); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + $modern = PHP_VERSION_ID >= 80400; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + if ($physical === null) { + $values[] = null; + + continue; + } + + assert(is_int($physical)); + + if ($modern) { + $seconds = intdiv($physical, 1_000_000); + $micros = $physical % 1_000_000; + + if ($micros < 0) { + $micros += 1_000_000; + $seconds--; + } + + // @mago-ignore analysis:unavailable-method + $instant = DateTimeImmutable::createFromTimestamp($seconds); + // @mago-ignore analysis:unavailable-method + $values[] = $instant->setMicrosecond($micros)->setTimezone($this->zone); + + continue; + } + + $values[] = (new DateTimeImmutable(sprintf( + '@%s%d.%06d', + $physical < 0 ? '-' : '', + intdiv(abs($physical), 1_000_000), + abs($physical) % 1_000_000, + )))->setTimezone($this->zone); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/DaysFromCivil.php b/src/core/etl/src/Flow/ETL/Column/Php/DaysFromCivil.php new file mode 100644 index 0000000000..d6064170f3 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/DaysFromCivil.php @@ -0,0 +1,24 @@ += 0 ? $year : $year - 399, 400); + $yearOfEra = $year - ($era * 400); + $dayOfYear = intdiv((153 * ($month > 2 ? $month - 3 : $month + 9)) + 2, 5) + $day - 1; + $dayOfEra = ($yearOfEra * 365) + intdiv($yearOfEra, 4) - intdiv($yearOfEra, 100) + $dayOfYear; + + return ($era * 146_097) + $dayOfEra - 719_468; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/EnumPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/EnumPhysical.php new file mode 100644 index 0000000000..b05a5e9ff4 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/EnumPhysical.php @@ -0,0 +1,48 @@ + $class + */ + public function __construct( + private string $class, + ) {} + + public function toPhysical(mixed $value): mixed + { + assert($value instanceof UnitEnum); + + return $value->name; + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_string($physical)); + + return constant($this->class . '::' . $physical); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert($physical === null || is_string($physical)); + $values[] = $physical === null ? null : constant($this->class . '::' . $physical); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/FixedBinary16Layout.php b/src/core/etl/src/Flow/ETL/Column/Php/FixedBinary16Layout.php new file mode 100644 index 0000000000..ba548ff9ae --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/FixedBinary16Layout.php @@ -0,0 +1,57 @@ +next(); + + if (strlen($buffer) !== (16 * $count)) { + throw new InvalidArgumentException(sprintf( + 'FixedBinary16 values buffer of %d bytes, expected %d for %d rows', + strlen($buffer), + 16 * $count, + $count, + )); + } + + if ($count === 0) { + return []; + } + + $physicals = []; + + foreach (str_split($buffer, 16) as $i => $value) { + $physicals[] = $valid[$i] ? $value : null; + } + + return $physicals; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Float64Layout.php b/src/core/etl/src/Flow/ETL/Column/Php/Float64Layout.php new file mode 100644 index 0000000000..eafd3e7512 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/Float64Layout.php @@ -0,0 +1,57 @@ +next(); + + if (strlen($buffer) !== (8 * $count)) { + throw new InvalidArgumentException(sprintf( + 'Float64 values buffer of %d bytes, expected %d for %d rows', + strlen($buffer), + 8 * $count, + $count, + )); + } + + if ($count === 0) { + return []; + } + + /** @var list $physicals */ + $physicals = array_values((array) unpack('e*', $buffer)); + + foreach ($valid as $i => $isValid) { + if (!$isValid) { + $physicals[$i] = null; + } + } + + return $physicals; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php new file mode 100644 index 0000000000..828a2d8e23 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php @@ -0,0 +1,43 @@ +saveHtml(); + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_string($physical)); + + return ValueDecoder::htmlDocumentFromString($physical); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert($physical === null || is_string($physical)); + $values[] = $physical === null ? null : ValueDecoder::htmlDocumentFromString($physical); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php new file mode 100644 index 0000000000..ec76bad956 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php @@ -0,0 +1,42 @@ +next(); + + if (strlen($buffer) !== (4 * $count)) { + throw new InvalidArgumentException(sprintf( + 'Int32 values buffer of %d bytes, expected %d for %d rows', + strlen($buffer), + 4 * $count, + $count, + )); + } + + if ($count === 0) { + return []; + } + + $physicals = []; + + foreach (array_values((array) unpack('V*', $buffer)) as $i => $value) { + if (!$valid[$i]) { + $physicals[] = null; + + continue; + } + + $unsigned = (int) $value; + $physicals[] = $unsigned >= 2_147_483_648 ? $unsigned - 4_294_967_296 : $unsigned; + } + + return $physicals; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Int64Layout.php b/src/core/etl/src/Flow/ETL/Column/Php/Int64Layout.php new file mode 100644 index 0000000000..670680f4bf --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/Int64Layout.php @@ -0,0 +1,57 @@ +next(); + + if (strlen($buffer) !== (8 * $count)) { + throw new InvalidArgumentException(sprintf( + 'Int64 values buffer of %d bytes, expected %d for %d rows', + strlen($buffer), + 8 * $count, + $count, + )); + } + + if ($count === 0) { + return []; + } + + /** @var list $physicals */ + $physicals = array_values((array) unpack('P*', $buffer)); + + foreach ($valid as $i => $isValid) { + if (!$isValid) { + $physicals[$i] = null; + } + } + + return $physicals; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/JsonFactory.php b/src/core/etl/src/Flow/ETL/Column/Php/JsonFactory.php new file mode 100644 index 0000000000..139ed2837d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/JsonFactory.php @@ -0,0 +1,45 @@ +newInstanceWithoutConstructor(); + $json->value = $value; + $json->isObject = $value[0] === '{'; + + return $json; + }, + null, + Json::class, + ); + + $this->create = $create; + } + + public function create(string $json): Json + { + return ($this->create)($json); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/JsonPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/JsonPhysical.php new file mode 100644 index 0000000000..49e1138185 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/JsonPhysical.php @@ -0,0 +1,44 @@ +toString(); + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_string($physical)); + + return $this->factory->create($physical); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert($physical === null || is_string($physical)); + $values[] = $physical === null ? null : $this->factory->create($physical); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Layout.php b/src/core/etl/src/Flow/ETL/Column/Php/Layout.php new file mode 100644 index 0000000000..356480e74c --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/Layout.php @@ -0,0 +1,22 @@ + $physicals nulls allowed + * + * @return list value buffers, null slots in canonical form + */ + public function encode(array $physicals): array; + + /** + * @param list $valid + * + * @return list physicals, null where !$valid[$i] + */ + public function decode(Buffers $buffers, int $count, array $valid): array; +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/LayoutFor.php b/src/core/etl/src/Flow/ETL/Column/Php/LayoutFor.php new file mode 100644 index 0000000000..6e166e38b2 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/LayoutFor.php @@ -0,0 +1,66 @@ + $type + */ + public function type(Type $type): Layout + { + $base = $type instanceof OptionalType ? $type->base() : $type; + + return match (true) { + $base instanceof IntegerType, + $base instanceof PositiveIntegerType, + $base instanceof DateTimeType, + $base instanceof TimeType, + => new Int64Layout(), + $base instanceof FloatType => new Float64Layout(), + $base instanceof DateType => new Int32Layout(), + $base instanceof BooleanType => new BooleanLayout(), + $base instanceof StringType, + $base instanceof NonEmptyStringType, + $base instanceof NumericStringType, + $base instanceof ClassStringType, + $base instanceof TimeZoneType, + $base instanceof JsonType, + $base instanceof EnumType, + $base instanceof XMLType, + $base instanceof XMLElementType, + $base instanceof HTMLType, + $base instanceof HTMLElementType, + => new Utf8Layout(), + $base instanceof UuidType => new FixedBinary16Layout(), + default => throw new InvalidArgumentException(sprintf('type %s has no scalar layout', $base->toString())), + }; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php new file mode 100644 index 0000000000..91d4e3abee --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php @@ -0,0 +1,183 @@ + $type a ListType, or an OptionalType over one for a child column + * @param list $offsets count() + 1 offsets, from 0 + * @param array $nulls + */ + public function __construct( + public Type $type, + public array $offsets, + public Column $element, + public array $nulls, + ) {} + + public function at(int $i): mixed + { + if (array_key_exists($i, $this->nulls)) { + return null; + } + + return array_slice( + $this->element->physicals(), + $this->offsets[$i], + $this->offsets[$i + 1] - $this->offsets[$i], + ); + } + + public function concat(Column ...$others): Column + { + $offsets = $this->offsets; + $nulls = $this->nulls; + $rows = $this->count(); + $elements = []; + + foreach ($others as $other) { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot concat %s', self::class, $other::class)); + } + + $base = $offsets[count($offsets) - 1]; + + for ($k = 1, $last = count($other->offsets); $k < $last; $k++) { + $offsets[] = $base + $other->offsets[$k]; + } + + foreach ($other->nulls as $index => $_) { + $nulls[$rows + $index] = true; + } + + $rows += $other->count(); + $elements[] = $other->element; + } + + return new self($this->type, $offsets, $this->element->concat(...$elements), $nulls); + } + + public function count(): int + { + return count($this->offsets) - 1; + } + + public function encode(): array + { + return [ + (new Validity())->fromNulls($this->nulls, $this->count()), + (new Offsets())->pack($this->offsets), + ...$this->element->encode(), + ]; + } + + public function isNull(int $i): bool + { + return array_key_exists($i, $this->nulls); + } + + public function nullCount(): int + { + return count($this->nulls); + } + + public function physicals(): array + { + $elements = $this->element->physicals(); + $physicals = []; + + for ($i = 0, $count = $this->count(); $i < $count; $i++) { + $physicals[] = array_key_exists($i, $this->nulls) + ? null + : array_slice($elements, $this->offsets[$i], $this->offsets[$i + 1] - $this->offsets[$i]); + } + + return $physicals; + } + + public function slice(int $offset, int $length): Column + { + return $this->take($length === 0 ? [] : range($offset, $offset + $length - 1)); + } + + public function take(array $indices): Column + { + $offsets = [0]; + $nulls = []; + $elementIndices = []; + + foreach ($indices as $position => $index) { + if (array_key_exists($index, $this->nulls)) { + $nulls[$position] = true; + } + + for ($j = $this->offsets[$index], $end = $this->offsets[$index + 1]; $j < $end; $j++) { + $elementIndices[] = $j; + } + + $offsets[] = count($elementIndices); + } + + return new self($this->type, $offsets, $this->element->take($elementIndices), $nulls); + } + + public function type(): Type + { + return $this->type; + } + + public function value(int $i): mixed + { + if (array_key_exists($i, $this->nulls)) { + return null; + } + + $value = []; + + for ($j = $this->offsets[$i], $end = $this->offsets[$i + 1]; $j < $end; $j++) { + $value[] = $this->element->value($j); + } + + return $value; + } + + public function values(): array + { + $elements = $this->element->values(); + $values = []; + + for ($i = 0, $count = $this->count(); $i < $count; $i++) { + $values[] = array_key_exists($i, $this->nulls) + ? null + : array_slice($elements, $this->offsets[$i], $this->offsets[$i + 1] - $this->offsets[$i]); + } + + return $values; + } + + public function withType(Type $type): Column + { + (new Retype())->assert($this->type, $type, count($this->nulls)); + + $list = $type instanceof OptionalType ? $type->base() : $type; + assert($list instanceof ListType); + + return new self($type, $this->offsets, $this->element->withType($list->element()), $this->nulls); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ListColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/ListColumnBuilder.php new file mode 100644 index 0000000000..b6838db674 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ListColumnBuilder.php @@ -0,0 +1,66 @@ + + */ + private array $nulls = []; + + /** + * @var list + */ + private array $offsets = [0]; + + /** + * @param Type $type + */ + public function __construct( + private readonly Type $type, + private readonly PhpColumnBuilder $element, + ) {} + + public function appendPhysical(mixed $physical): void + { + if ($physical === null) { + $this->nulls[count($this->offsets) - 1] = true; + $this->offsets[] = $this->offsets[count($this->offsets) - 1]; + + return; + } + + assert(is_array($physical)); + $this->element->appendPhysicalMany(array_values($physical)); + $this->offsets[] = $this->element->count(); + } + + public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + { + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + $this->appendPhysical($physical); + } + } + + public function count(): int + { + return count($this->offsets) - 1; + } + + public function finish(): Column + { + return new ListColumn($this->type, $this->offsets, $this->element->finish(), $this->nulls); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ListPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/ListPhysical.php new file mode 100644 index 0000000000..a933bb8696 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ListPhysical.php @@ -0,0 +1,52 @@ +element->toPhysical($element); + } + + return $physicals; + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_array($physical)); + + /** @var list $physical */ + return $this->element->fromPhysicalAll($physical); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert($physical === null || is_array($physical)); + + /** @var null|list $physical */ + $values[] = $physical === null ? null : $this->element->fromPhysicalAll($physical); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php new file mode 100644 index 0000000000..300890ec9b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php @@ -0,0 +1,228 @@ + $type a MapType, or an OptionalType over one for a child column + * @param list $offsets count() + 1 offsets, from 0 + * @param array $nulls + */ + public function __construct( + public Type $type, + public array $offsets, + public Column $keys, + public Column $values, + public array $nulls, + ) {} + + public function at(int $i): mixed + { + if (array_key_exists($i, $this->nulls)) { + return null; + } + + $length = $this->offsets[$i + 1] - $this->offsets[$i]; + + /** @var list $keys */ + $keys = array_slice($this->keys->physicals(), $this->offsets[$i], $length); + + return array_combine($keys, array_slice($this->values->physicals(), $this->offsets[$i], $length)); + } + + public function concat(Column ...$others): Column + { + $offsets = $this->offsets; + $nulls = $this->nulls; + $rows = $this->count(); + $keys = []; + $values = []; + + foreach ($others as $other) { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot concat %s', self::class, $other::class)); + } + + $base = $offsets[count($offsets) - 1]; + + for ($k = 1, $last = count($other->offsets); $k < $last; $k++) { + $offsets[] = $base + $other->offsets[$k]; + } + + foreach ($other->nulls as $index => $_) { + $nulls[$rows + $index] = true; + } + + $rows += $other->count(); + $keys[] = $other->keys; + $values[] = $other->values; + } + + return new self( + $this->type, + $offsets, + $this->keys->concat(...$keys), + $this->values->concat(...$values), + $nulls, + ); + } + + public function count(): int + { + return count($this->offsets) - 1; + } + + public function encode(): array + { + return [ + (new Validity())->fromNulls($this->nulls, $this->count()), + (new Offsets())->pack($this->offsets), + '', + ...$this->keys->encode(), + ...$this->values->encode(), + ]; + } + + public function isNull(int $i): bool + { + return array_key_exists($i, $this->nulls); + } + + public function nullCount(): int + { + return count($this->nulls); + } + + public function physicals(): array + { + $keys = $this->keys->physicals(); + $values = $this->values->physicals(); + $physicals = []; + + for ($i = 0, $count = $this->count(); $i < $count; $i++) { + if (array_key_exists($i, $this->nulls)) { + $physicals[] = null; + + continue; + } + + $length = $this->offsets[$i + 1] - $this->offsets[$i]; + + /** @var list $rowKeys */ + $rowKeys = array_slice($keys, $this->offsets[$i], $length); + $physicals[] = array_combine($rowKeys, array_slice($values, $this->offsets[$i], $length)); + } + + return $physicals; + } + + public function slice(int $offset, int $length): Column + { + return $this->take($length === 0 ? [] : range($offset, $offset + $length - 1)); + } + + public function take(array $indices): Column + { + $offsets = [0]; + $nulls = []; + $entryIndices = []; + + foreach ($indices as $position => $index) { + if (array_key_exists($index, $this->nulls)) { + $nulls[$position] = true; + } + + for ($j = $this->offsets[$index], $end = $this->offsets[$index + 1]; $j < $end; $j++) { + $entryIndices[] = $j; + } + + $offsets[] = count($entryIndices); + } + + return new self( + $this->type, + $offsets, + $this->keys->take($entryIndices), + $this->values->take($entryIndices), + $nulls, + ); + } + + public function type(): Type + { + return $this->type; + } + + public function value(int $i): mixed + { + if (array_key_exists($i, $this->nulls)) { + return null; + } + + $value = []; + + for ($j = $this->offsets[$i], $end = $this->offsets[$i + 1]; $j < $end; $j++) { + /** @var int|string $key */ + $key = $this->keys->value($j); + $value[$key] = $this->values->value($j); + } + + return $value; + } + + public function values(): array + { + $keys = $this->keys->values(); + $values = $this->values->values(); + $result = []; + + for ($i = 0, $count = $this->count(); $i < $count; $i++) { + if (array_key_exists($i, $this->nulls)) { + $result[] = null; + + continue; + } + + $length = $this->offsets[$i + 1] - $this->offsets[$i]; + + /** @var list $rowKeys */ + $rowKeys = array_slice($keys, $this->offsets[$i], $length); + $result[] = array_combine($rowKeys, array_slice($values, $this->offsets[$i], $length)); + } + + return $result; + } + + public function withType(Type $type): Column + { + (new Retype())->assert($this->type, $type, count($this->nulls)); + + $map = $type instanceof OptionalType ? $type->base() : $type; + assert($map instanceof MapType); + + return new self( + $type, + $this->offsets, + $this->keys->withType($map->key()), + $this->values->withType($map->value()), + $this->nulls, + ); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/MapColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/MapColumnBuilder.php new file mode 100644 index 0000000000..1ebf6313a2 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/MapColumnBuilder.php @@ -0,0 +1,69 @@ + + */ + private array $nulls = []; + + /** + * @var list + */ + private array $offsets = [0]; + + /** + * @param Type $type + */ + public function __construct( + private readonly Type $type, + private readonly PhpColumnBuilder $keys, + private readonly PhpColumnBuilder $values, + ) {} + + public function appendPhysical(mixed $physical): void + { + if ($physical === null) { + $this->nulls[count($this->offsets) - 1] = true; + $this->offsets[] = $this->offsets[count($this->offsets) - 1]; + + return; + } + + assert(is_array($physical)); + $this->keys->appendPhysicalMany(array_keys($physical)); + $this->values->appendPhysicalMany(array_values($physical)); + $this->offsets[] = $this->keys->count(); + } + + public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + { + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + $this->appendPhysical($physical); + } + } + + public function count(): int + { + return count($this->offsets) - 1; + } + + public function finish(): Column + { + return new MapColumn($this->type, $this->offsets, $this->keys->finish(), $this->values->finish(), $this->nulls); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/MapPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/MapPhysical.php new file mode 100644 index 0000000000..ef55b0795a --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/MapPhysical.php @@ -0,0 +1,54 @@ + $element) { + $physicals[$key] = $element === null ? null : $this->value->toPhysical($element); + } + + return $physicals; + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_array($physical)); + + return array_combine(array_keys($physical), $this->value->fromPhysicalAll(array_values($physical))); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert($physical === null || is_array($physical)); + $values[] = $physical === null + ? null + : array_combine(array_keys($physical), $this->value->fromPhysicalAll(array_values($physical))); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/NullColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/NullColumnBuilder.php new file mode 100644 index 0000000000..6da20f1822 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/NullColumnBuilder.php @@ -0,0 +1,42 @@ + $type + */ + public function __construct( + private readonly Type $type, + ) {} + + public function appendPhysical(mixed $physical): void + { + $this->count++; + } + + public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + { + $this->count += count($physicals); + } + + public function count(): int + { + return $this->count; + } + + public function finish(): Column + { + return new ConstantColumn($this->type, new NullPhysical(), null, $this->count); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/NullCount.php b/src/core/etl/src/Flow/ETL/Column/Php/NullCount.php new file mode 100644 index 0000000000..f043badcdc --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/NullCount.php @@ -0,0 +1,25 @@ + $values + */ + public function of(array $values): int + { + $nulls = 0; + + // @mago-ignore analysis:mixed-assignment + foreach ($values as $value) { + if ($value === null) { + $nulls++; + } + } + + return $nulls; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/NullPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/NullPhysical.php new file mode 100644 index 0000000000..e24da61b97 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/NullPhysical.php @@ -0,0 +1,26 @@ + $offsets + */ + public function pack(array $offsets): string + { + $last = $offsets[count($offsets) - 1]; + + if ($last > 2_147_483_647) { + throw new InvalidArgumentException(sprintf( + 'Offsets exceed the i32 range of a batch buffer: the last offset is %d', + $last, + )); + } + + return pack('V*', ...$offsets); + } + + /** + * @return list $count + 1 offsets, the first 0, monotonic + */ + public function unpack(string $buffer, int $count, string $layout): array + { + if (strlen($buffer) !== (($count + 1) * 4)) { + throw new InvalidArgumentException(sprintf( + '%s offsets buffer of %d bytes, expected %d for %d rows', + $layout, + strlen($buffer), + ($count + 1) * 4, + $count, + )); + } + + /** @var list $offsets */ + $offsets = array_values((array) unpack('V*', $buffer)); + + if ($offsets[0] !== 0) { + throw new InvalidArgumentException(sprintf('%s offsets start at %d, not 0', $layout, $offsets[0])); + } + + for ($i = 1; $i <= $count; $i++) { + if ($offsets[$i] < $offsets[$i - 1]) { + throw new InvalidArgumentException(sprintf( + '%s offsets are not monotonic: offset %d is %d, offset %d is %d', + $layout, + $i - 1, + $offsets[$i - 1], + $i, + $offsets[$i], + )); + } + } + + return $offsets; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/PhpColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/PhpColumnBuilder.php new file mode 100644 index 0000000000..5d4260280d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/PhpColumnBuilder.php @@ -0,0 +1,25 @@ + $physicals + * @param null|int $nullCount the nulls among $physicals when the caller already counted them + */ + public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void; + + public function count(): int; + + public function finish(): Column; +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Physical.php b/src/core/etl/src/Flow/ETL/Column/Php/Physical.php new file mode 100644 index 0000000000..64a1ae88dc --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/Physical.php @@ -0,0 +1,25 @@ + $physicals nulls stay null + * + * @return list + */ + public function fromPhysicalAll(array $physicals): array; +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/PhysicalBuilderFor.php b/src/core/etl/src/Flow/ETL/Column/Php/PhysicalBuilderFor.php new file mode 100644 index 0000000000..f35e4e7d5c --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/PhysicalBuilderFor.php @@ -0,0 +1,50 @@ + $type + * + * @throws InvalidArgumentException + */ + public function type(Type $type): PhpColumnBuilder + { + $base = $type instanceof OptionalType ? $type->base() : $type; + + if ($base instanceof ListType) { + return new ListColumnBuilder($type, $this->type($base->element())); + } + + if ($base instanceof MapType) { + return new MapColumnBuilder($type, $this->type($base->key()), $this->type($base->value())); + } + + if ($base instanceof StructureType) { + $children = []; + + foreach ($base->elements() as $element) { + $children[$element->name] = $this->type($element->type); + } + + return new StructColumnBuilder($type, $children); + } + + if ($base instanceof NullType) { + return new NullColumnBuilder($type); + } + + return new ScalarColumnBuilder($type, (new PhysicalFor())->type($type)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php b/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php new file mode 100644 index 0000000000..970ce93cda --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php @@ -0,0 +1,164 @@ + $definition + * + * @throws ColumnMismatchException + */ + public function definition(Definition $definition): Physical + { + if (!in_array($definition::class, self::DEFINITIONS, true)) { + throw ColumnMismatchException::unsupportedType( + $definition, + 'only the 19 Flow definitions have a column kind', + ); + } + + try { + return $this->type($definition->type()); + } catch (InvalidArgumentException $e) { + throw ColumnMismatchException::unsupportedType($definition, $e->getMessage()); + } + } + + /** + * @param Type $type + * + * @throws InvalidArgumentException + */ + public function type(Type $type): Physical + { + $base = $type instanceof OptionalType ? $type->base() : $type; + + return match (true) { + $base instanceof IntegerType, + $base instanceof PositiveIntegerType, + $base instanceof FloatType, + $base instanceof BooleanType, + $base instanceof StringType, + $base instanceof NonEmptyStringType, + $base instanceof NumericStringType, + $base instanceof ClassStringType, + => new IdentityPhysical(), + $base instanceof DateTimeType => new DateTimePhysical($base->zone()), + $base instanceof DateType => new DatePhysical(), + $base instanceof TimeType => new TimePhysical(), + $base instanceof UuidType => new UuidPhysical(), + $base instanceof TimeZoneType => new TimeZonePhysical(), + $base instanceof JsonType => new JsonPhysical(), + $base instanceof EnumType => $base->class === UnitEnum::class || $base->class === BackedEnum::class + ? throw new InvalidArgumentException('declare the concrete enum class') + : new EnumPhysical($base->class), + $base instanceof XMLType => new XmlDocumentPhysical(), + $base instanceof XMLElementType => new XmlElementPhysical(), + $base instanceof HTMLType => new HtmlDocumentPhysical(), + $base instanceof HTMLElementType => new HtmlElementPhysical(), + $base instanceof ListType => new ListPhysical($this->type($base->element())), + $base instanceof MapType => new MapPhysical($this->type($base->value())), + $base instanceof StructureType => new StructPhysical($this->elements($base)), + $base instanceof NullType => new NullPhysical(), + $base instanceof MixedType => throw new InvalidArgumentException( + 'a mixed element has no column kind, declare it or use json', + ), + default => throw new InvalidArgumentException(sprintf('type %s has no column kind', $base->toString())), + }; + } + + /** + * @param StructureType $type + * + * @return array + */ + public function elements(StructureType $type): array + { + $elements = []; + + foreach ($type->elements() as $element) { + $elements[$element->name] = $this->type($element->type); + } + + return $elements; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Retype.php b/src/core/etl/src/Flow/ETL/Column/Php/Retype.php new file mode 100644 index 0000000000..b10240f29d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/Retype.php @@ -0,0 +1,52 @@ + $from + * @param Type $to + * + * @throws InvalidArgumentException + */ + public function assert(Type $from, Type $to, int $nullCount): void + { + if ($from instanceof OptionalType && !$to instanceof OptionalType && $nullCount > 0) { + throw new InvalidArgumentException(sprintf('%d null values under a required type', $nullCount)); + } + + $fromBase = $from instanceof OptionalType ? $from->base() : $from; + $toBase = $to instanceof OptionalType ? $to->base() : $to; + + $sameKind = match (true) { + $fromBase::class !== $toBase::class => false, + $fromBase instanceof EnumType && $toBase instanceof EnumType => $fromBase->class === $toBase->class, + $fromBase instanceof StructureType && $toBase instanceof StructureType => array_map( + static fn(StructureElement $element): int|string => $element->name, + $fromBase->elements(), + ) === array_map(static fn(StructureElement $element): int|string => $element->name, $toBase->elements()), + default => true, + }; + + if (!$sameKind) { + throw new InvalidArgumentException(sprintf( + '%s and %s are different column kinds', + $from->toString(), + $to->toString(), + )); + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumn.php new file mode 100644 index 0000000000..41963d8301 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumn.php @@ -0,0 +1,130 @@ + $type + * @param list $values physicals, null for a null cell + */ + public function __construct( + public Type $type, + public Physical $physical, + public array $values, + public int $nullCount, + ) {} + + public function at(int $i): mixed + { + return $this->values[$i]; + } + + public function concat(Column ...$others): Column + { + $values = [$this->values]; + $nullCount = $this->nullCount; + + foreach ($others as $other) { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot concat %s', self::class, $other::class)); + } + + $values[] = $other->values; + $nullCount += $other->nullCount; + } + + return new self($this->type, $this->physical, array_merge(...$values), $nullCount); + } + + public function count(): int + { + return count($this->values); + } + + public function encode(): array + { + return [ + (new Validity())->fromValues($this->values), + ...(new LayoutFor()) + ->type($this->type) + ->encode($this->values), + ]; + } + + public function isNull(int $i): bool + { + return $this->values[$i] === null; + } + + public function nullCount(): int + { + return $this->nullCount; + } + + public function physicals(): array + { + return $this->values; + } + + public function slice(int $offset, int $length): Column + { + $values = array_slice($this->values, $offset, $length); + + return new self( + $this->type, + $this->physical, + $values, + $this->nullCount === 0 ? 0 : (new NullCount())->of($values), + ); + } + + public function take(array $indices): Column + { + $values = []; + + foreach ($indices as $index) { + $values[] = $this->values[$index]; + } + + return new self( + $this->type, + $this->physical, + $values, + $this->nullCount === 0 ? 0 : (new NullCount())->of($values), + ); + } + + public function type(): Type + { + return $this->type; + } + + public function value(int $i): mixed + { + return $this->values[$i] === null ? null : $this->physical->fromPhysical($this->values[$i]); + } + + public function values(): array + { + return $this->physical->fromPhysicalAll($this->values); + } + + public function withType(Type $type): Column + { + (new Retype())->assert($this->type, $type, $this->nullCount); + + return new self($type, (new PhysicalFor())->type($type), $this->values, $this->nullCount); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumnBuilder.php new file mode 100644 index 0000000000..1c5c42150e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumnBuilder.php @@ -0,0 +1,74 @@ + + */ + private array $values = []; + + /** + * @param Type $type + */ + public function __construct( + private readonly Type $type, + private readonly Physical $physical, + ) {} + + public function appendPhysical(mixed $physical): void + { + assert(!is_array($physical) && !is_object($physical)); + + if ($physical === null) { + $this->nullCount++; + } + + $this->values[] = $physical; + } + + public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + { + if ($nullCount !== null) { + $this->nullCount += $nullCount; + array_push($this->values, ...$physicals); + + return; + } + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert(!is_array($physical) && !is_object($physical)); + + if ($physical === null) { + $this->nullCount++; + } + + $this->values[] = $physical; + } + } + + public function count(): int + { + return count($this->values); + } + + public function finish(): Column + { + return new ScalarColumn($this->type, $this->physical, $this->values, $this->nullCount); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/StructColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/StructColumn.php new file mode 100644 index 0000000000..995c4b7dd4 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/StructColumn.php @@ -0,0 +1,289 @@ + $type a StructureType, or an OptionalType over one for a child column + * @param non-empty-array $children keyed by element name, in element order + * @param array $nulls + */ + public function __construct( + public Type $type, + public array $children, + public array $nulls, + ) {} + + public function at(int $i): mixed + { + if (array_key_exists($i, $this->nulls)) { + return null; + } + + $physical = []; + + foreach ($this->structure()->elements() as $element) { + $child = $this->children[$element->name]; + + if ($child->isNull($i)) { + if (!$element->optional) { + $physical[$element->name] = null; + } + + continue; + } + + $physical[$element->name] = $child->at($i); + } + + return $physical; + } + + public function concat(Column ...$others): Column + { + $nulls = $this->nulls; + $rows = $this->count(); + $children = []; + + foreach ($others as $other) { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot concat %s', self::class, $other::class)); + } + + foreach ($other->nulls as $index => $_) { + $nulls[$rows + $index] = true; + } + + $rows += $other->count(); + + foreach ($other->children as $name => $child) { + $children[$name][] = $child; + } + } + + $concatenated = []; + + foreach ($this->children as $name => $child) { + $concatenated[$name] = $child->concat(...$children[$name] ?? []); + } + + return new self($this->type, $concatenated, $nulls); + } + + public function count(): int + { + return $this->children[array_key_first($this->children)]->count(); + } + + public function encode(): array + { + $buffers = [(new Validity())->fromNulls($this->nulls, $this->count())]; + + foreach ($this->children as $child) { + foreach ($child->encode() as $buffer) { + $buffers[] = $buffer; + } + } + + return $buffers; + } + + public function isNull(int $i): bool + { + return array_key_exists($i, $this->nulls); + } + + public function nullCount(): int + { + return count($this->nulls); + } + + public function physicals(): array + { + $elements = $this->structure()->elements(); + $children = []; + + foreach ($elements as $element) { + $children[$element->name] = $this->children[$element->name]->physicals(); + } + + $physicals = []; + + for ($i = 0, $count = $this->count(); $i < $count; $i++) { + if (array_key_exists($i, $this->nulls)) { + $physicals[] = null; + + continue; + } + + $physical = []; + + foreach ($elements as $element) { + // @mago-ignore analysis:mixed-assignment + $cell = $children[$element->name][$i]; + + if ($cell === null && $element->optional) { + continue; + } + + $physical[$element->name] = $cell; + } + + $physicals[] = $physical; + } + + return $physicals; + } + + public function slice(int $offset, int $length): Column + { + return $this->take($length === 0 ? [] : range($offset, $offset + $length - 1)); + } + + public function structure(): StructureType + { + $structure = $this->type instanceof OptionalType ? $this->type->base() : $this->type; + assert($structure instanceof StructureType); + + return $structure; + } + + public function take(array $indices): Column + { + $nulls = []; + + foreach ($indices as $position => $index) { + if (array_key_exists($index, $this->nulls)) { + $nulls[$position] = true; + } + } + + $children = []; + + foreach ($this->children as $name => $child) { + $children[$name] = $child->take($indices); + } + + return new self($this->type, $children, $nulls); + } + + public function type(): Type + { + return $this->type; + } + + public function value(int $i): mixed + { + if (array_key_exists($i, $this->nulls)) { + return null; + } + + $value = []; + + foreach ($this->structure()->elements() as $element) { + $child = $this->children[$element->name]; + + if ($child->isNull($i)) { + if (!$element->optional) { + $value[$element->name] = null; + } + + continue; + } + + $value[$element->name] = $child->value($i); + } + + return $value; + } + + public function values(): array + { + $elements = $this->structure()->elements(); + $children = []; + + foreach ($elements as $element) { + $children[$element->name] = $this->children[$element->name]->values(); + } + + $values = []; + + for ($i = 0, $count = $this->count(); $i < $count; $i++) { + if (array_key_exists($i, $this->nulls)) { + $values[] = null; + + continue; + } + + $value = []; + + foreach ($elements as $element) { + // @mago-ignore analysis:mixed-assignment + $cell = $children[$element->name][$i]; + + if ($cell === null && $element->optional) { + continue; + } + + $value[$element->name] = $cell; + } + + $values[] = $value; + } + + return $values; + } + + public function withType(Type $type): Column + { + (new Retype())->assert($this->type, $type, count($this->nulls)); + + $structure = $type instanceof OptionalType ? $type->base() : $type; + assert($structure instanceof StructureType); + + $from = $this->structure()->elements(); + $children = []; + + foreach ($structure->elements() as $position => $element) { + $child = $this->children[$element->name]; + + if ($from[$position]->optional && !$element->optional) { + $absent = 0; + + for ($i = 0, $count = $child->count(); $i < $count; $i++) { + if (!array_key_exists($i, $this->nulls) && $child->isNull($i)) { + $absent++; + } + } + + if ($absent > 0) { + throw new InvalidArgumentException(sprintf( + '%d absent values under the required element "%s"', + $absent, + $element->name, + )); + } + } + + $children[$element->name] = $child->withType($element->type); + } + + return new self($type, $children, $this->nulls); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/StructColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/StructColumnBuilder.php new file mode 100644 index 0000000000..8331eaa65e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/StructColumnBuilder.php @@ -0,0 +1,75 @@ + + */ + private array $nulls = []; + + /** + * @param Type $type + * @param non-empty-array $children keyed by element name, in element order + */ + public function __construct( + private readonly Type $type, + private readonly array $children, + ) {} + + public function appendPhysical(mixed $physical): void + { + if ($physical === null) { + $this->nulls[$this->count++] = true; + + foreach ($this->children as $child) { + $child->appendPhysical(null); + } + + return; + } + + assert(is_array($physical)); + $this->count++; + + foreach ($this->children as $name => $child) { + $child->appendPhysical(array_key_exists($name, $physical) ? $physical[$name] : null); + } + } + + public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + { + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + $this->appendPhysical($physical); + } + } + + public function count(): int + { + return $this->count; + } + + public function finish(): Column + { + $children = []; + + foreach ($this->children as $name => $child) { + $children[$name] = $child->finish(); + } + + return new StructColumn($this->type, $children, $this->nulls); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/StructPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/StructPhysical.php new file mode 100644 index 0000000000..7215e7134d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/StructPhysical.php @@ -0,0 +1,77 @@ + $elements in element order + */ + public function __construct( + private array $elements, + ) {} + + public function toPhysical(mixed $value): mixed + { + assert(is_array($value)); + + $physicals = []; + + foreach ($this->elements as $name => $element) { + if (array_key_exists($name, $value)) { + $physicals[$name] = $value[$name] === null ? null : $element->toPhysical($value[$name]); + } + } + + return $physicals; + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_array($physical)); + + $values = []; + + foreach ($this->elements as $name => $element) { + if (array_key_exists($name, $physical)) { + $values[$name] = $physical[$name] === null ? null : $element->fromPhysical($physical[$name]); + } + } + + return $values; + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + if ($physical === null) { + $values[] = null; + + continue; + } + + assert(is_array($physical)); + + $value = []; + + foreach ($this->elements as $name => $element) { + if (array_key_exists($name, $physical)) { + $value[$name] = $physical[$name] === null ? null : $element->fromPhysical($physical[$name]); + } + } + + $values[] = $value; + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/TimePhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/TimePhysical.php new file mode 100644 index 0000000000..bd2dd6efc1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/TimePhysical.php @@ -0,0 +1,94 @@ +y !== 0 || $value->m !== 0) { + throw new CastingException( + $value, + type_time(), + reason: "Relative DateInterval (with months/years) can't be stored in a time column", + ); + } + + $seconds = ((($value->d * 24) + $value->h) * 3600) + ($value->i * 60) + $value->s; + // an i64 overflow yields a float at runtime + // @mago-ignore analysis:redundant-type-comparison,redundant-condition + $us = is_int($seconds) ? ($seconds * 1_000_000) + (int) round($value->f * 1_000_000) : null; + + // @mago-ignore analysis:impossible-condition,redundant-type-comparison + if (!is_int($us)) { + throw new CastingException($value, type_time(), reason: 'outside the microsecond range of a time column'); + } + + return $value->invert === 1 ? -$us : $us; + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_int($physical)); + + $magnitude = abs($physical); + $interval = new DateInterval(sprintf( + 'PT%dH%dM%dS', + intdiv($magnitude, 3_600_000_000), + intdiv($magnitude, 60_000_000) % 60, + intdiv($magnitude, 1_000_000) % 60, + )); + // @mago-ignore analysis:invalid-property-write + $interval->f = ($magnitude % 1_000_000) / 1_000_000; + // @mago-ignore analysis:invalid-property-write + $interval->invert = $physical < 0 ? 1 : 0; + + return $interval; + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + if ($physical === null) { + $values[] = null; + + continue; + } + + assert(is_int($physical)); + + $magnitude = abs($physical); + $interval = new DateInterval(sprintf( + 'PT%dH%dM%dS', + intdiv($magnitude, 3_600_000_000), + intdiv($magnitude, 60_000_000) % 60, + intdiv($magnitude, 1_000_000) % 60, + )); + // @mago-ignore analysis:invalid-property-write + $interval->f = ($magnitude % 1_000_000) / 1_000_000; + // @mago-ignore analysis:invalid-property-write + $interval->invert = $physical < 0 ? 1 : 0; + $values[] = $interval; + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php new file mode 100644 index 0000000000..e25daf6e8f --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php @@ -0,0 +1,45 @@ +getName(); + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_string($physical)); + + return $this->zones->get($physical); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert($physical === null || is_string($physical)); + $values[] = $physical === null ? null : $this->zones->get($physical); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Utf8Layout.php b/src/core/etl/src/Flow/ETL/Column/Php/Utf8Layout.php new file mode 100644 index 0000000000..3e619d4846 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/Utf8Layout.php @@ -0,0 +1,63 @@ +offsets->pack($offsets), implode('', $values)]; + } + + public function decode(Buffers $buffers, int $count, array $valid): array + { + $offsets = $this->offsets->unpack($buffers->next(), $count, 'Utf8'); + $data = $buffers->next(); + + if ($offsets[$count] !== strlen($data)) { + throw new InvalidArgumentException(sprintf( + 'Utf8 data buffer of %d bytes, the last offset is %d', + strlen($data), + $offsets[$count], + )); + } + + $physicals = []; + + for ($i = 0; $i < $count; $i++) { + $physicals[] = $valid[$i] ? substr($data, $offsets[$i], $offsets[$i + 1] - $offsets[$i]) : null; + } + + return $physicals; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/UuidPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/UuidPhysical.php new file mode 100644 index 0000000000..36f8687b6b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/UuidPhysical.php @@ -0,0 +1,42 @@ +toString())); + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_string($physical)); + + return Uuid::fromBytes($physical); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert($physical === null || is_string($physical)); + $values[] = $physical === null ? null : Uuid::fromBytes($physical); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Validity.php b/src/core/etl/src/Flow/ETL/Column/Php/Validity.php new file mode 100644 index 0000000000..c441ba23be --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/Validity.php @@ -0,0 +1,137 @@ + $values + */ + public function fromValues(array $values): string + { + $bitmap = ''; + $byte = 0; + $bit = 0; + $hasNull = false; + + // @mago-ignore analysis:mixed-assignment + foreach ($values as $value) { + if ($value === null) { + $hasNull = true; + } else { + $byte |= 1 << $bit; + } + + if (++$bit === 8) { + $bitmap .= chr($byte); + $byte = 0; + $bit = 0; + } + } + + if (!$hasNull) { + return ''; + } + + return $bit === 0 ? $bitmap : $bitmap . chr($byte); + } + + /** + * @param array $nulls + */ + public function fromNulls(array $nulls, int $count): string + { + if ($nulls === []) { + return ''; + } + + // @mago-ignore analysis:possibly-invalid-argument + $bitmap = str_repeat("\xFF", intdiv($count, 8)); + $tail = $count % 8; + + if ($tail !== 0) { + $bitmap .= chr((1 << $tail) - 1); + } + + foreach ($nulls as $index => $_) { + $byte = intdiv($index, 8); + $bitmap[$byte] = chr(ord($bitmap[$byte]) & ~(1 << ($index % 8)) & 0xFF); + } + + return $bitmap; + } + + /** + * @return list + */ + public function valid(string $bitmap, int $count): array + { + if ($bitmap === '') { + // @mago-ignore analysis:possibly-invalid-argument + return $count === 0 ? [] : array_fill(0, $count, true); + } + + if (strlen($bitmap) < intdiv($count + 7, 8)) { + throw new InvalidArgumentException(sprintf( + 'Validity bitmap of %d bytes is too short for %d rows', + strlen($bitmap), + $count, + )); + } + + $valid = []; + + for ($i = 0; $i < $count; $i++) { + $valid[] = ((ord($bitmap[$i >> 3]) >> ($i & 7)) & 1) === 1; + } + + return $valid; + } + + public function nullCount(string $bitmap, int $count): int + { + if ($bitmap === '') { + return 0; + } + + $nulls = 0; + + foreach ($this->valid($bitmap, $count) as $valid) { + if (!$valid) { + $nulls++; + } + } + + return $nulls; + } + + /** + * @param list $valid + * + * @return array + */ + public function nulls(array $valid): array + { + $nulls = []; + + foreach ($valid as $index => $isValid) { + if (!$isValid) { + $nulls[$index] = true; + } + } + + return $nulls; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php new file mode 100644 index 0000000000..57c42045e7 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php @@ -0,0 +1,42 @@ +ownerDocument?->saveXml($value); + assert(is_string($markup)); + + return $markup; + } + + public function fromPhysical(mixed $physical): mixed + { + assert(is_string($physical)); + + return ValueDecoder::xmlElementFromString($physical); + } + + public function fromPhysicalAll(array $physicals): array + { + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + assert($physical === null || is_string($physical)); + $values[] = $physical === null ? null : ValueDecoder::xmlElementFromString($physical); + } + + return $values; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/PhpBackend.php b/src/core/etl/src/Flow/ETL/Column/PhpBackend.php new file mode 100644 index 0000000000..13e2a74a20 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/PhpBackend.php @@ -0,0 +1,66 @@ +definition($definition), + (new PhysicalBuilderFor())->type($definition->type()), + ); + } + + public function constant(Definition $definition, mixed $value, int $count): Column + { + $physical = (new PhysicalFor())->definition($definition); + + if ($value === null) { + if (!$definition->isNullable() && !$definition instanceof NullDefinition) { + throw ColumnMismatchException::valueDoesNotMatch($definition, null); + } + + return new ConstantColumn($definition->type(), $physical, null, $count); + } + + return new ConstantColumn( + $definition->type(), + $physical, + $physical->toPhysical($definition->type()->cast($value)), + $count, + ); + } + + public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column + { + $cursor = new Buffers($buffers); + $column = (new ColumnDecoder())->decode($definition->type(), $cursor, $count, $nullCount); + + if ($cursor->remaining() !== 0) { + throw new InvalidArgumentException(sprintf( + 'Column "%s": %d buffers left after decoding', + $definition->entry()->name(), + $cursor->remaining(), + )); + } + + return $column; + } +} diff --git a/src/core/etl/src/Flow/ETL/Config.php b/src/core/etl/src/Flow/ETL/Config.php index 11d2f8015e..252e96e60b 100644 --- a/src/core/etl/src/Flow/ETL/Config.php +++ b/src/core/etl/src/Flow/ETL/Config.php @@ -5,6 +5,8 @@ namespace Flow\ETL; use Flow\Calculator\Calculator; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Config\Cache\CacheConfig; use Flow\ETL\Config\ConfigBuilder; use Flow\ETL\Config\Grouping\HashGroupByConfig; @@ -46,6 +48,7 @@ public function __construct( public HashRepartitionConfig $repartition, private Calculator $calculator = new Calculator(), private RandomValueGenerator $randomValueGenerator = new NativePHPRandomValueGenerator(), + private Backend $backend = new DefaultBackend(), ) { $this->planner = new Planner($optimizer); } @@ -65,6 +68,11 @@ public function analyze(): ?Analyze return $this->analyze; } + public function backend(): Backend + { + return $this->backend; + } + public function calculator(): Calculator { return $this->calculator; diff --git a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php index d6f23317ea..76788fabb6 100644 --- a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php @@ -7,6 +7,8 @@ use Flow\Clock\SystemClock; use Flow\ETL\Analyze; use Flow\ETL\Cache; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Config; use Flow\ETL\Config\Cache\CacheConfigBuilder; use Flow\ETL\Config\Grouping\GroupByAlgorithmBuilder; @@ -23,8 +25,7 @@ use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\Optimizer; use Flow\ETL\RandomValueGenerator; -use Flow\ETL\Row\AdaptiveRowHydrator; -use Flow\ETL\Row\Hydrator; +use Flow\ETL\Row\PhpRowHydrator; use Flow\Filesystem\Path; use Flow\Floe\FloeSerializer; use Flow\Serializer\Serializer; @@ -40,12 +41,9 @@ final class ConfigBuilder private ?ClockInterface $clock; - private ?GroupByAlgorithmBuilder $groupBy; + private Backend $backend; - /** - * @var null|Hydrator - */ - private ?Hydrator $hydrator; + private ?GroupByAlgorithmBuilder $groupBy; private ?JoinAlgorithmBuilder $join; @@ -74,7 +72,7 @@ public function __construct() $this->id = null; $this->name = null; $this->serializer = null; - $this->hydrator = null; + $this->backend = new DefaultBackend(); $this->optimizer = null; $this->executor = null; $this->clock = null; @@ -98,19 +96,25 @@ public function analyze(Analyze $analyze): self return $this; } + public function backend(Backend $backend): self + { + $this->backend = $backend; + + return $this; + } + public function build(): Config { $id = $this->id ??= 'flow-php-' . $this->randomValueGenerator->string(32); $this->optimizer ??= Optimizer::default(); $this->executor ??= new Executor(); - $this->hydrator ??= new AdaptiveRowHydrator(); + $hydrator = new PhpRowHydrator($this->backend); // the default serializer shares the context hydrator - one source of Row objects - $this->serializer ??= new FloeSerializer(hydrator: $this->hydrator); + $this->serializer ??= new FloeSerializer(hydrator: $hydrator); $serializer = $this->serializer; $optimizer = $this->optimizer; $executor = $this->executor; - $hydrator = $this->hydrator; $dataframeName = $this->name ?? 'flow_dataframe'; $cacheConfig = $this->cache->build($serializer, $this->telemetryConfig, $dataframeName); @@ -132,6 +136,7 @@ public function build(): Config ($this->join ?? new HashJoinBuilder())->build($cacheConfig->localFilesystemCacheDir), ($this->repartition ?? new HashRepartitionBuilder())->build($cacheConfig->localFilesystemCacheDir), randomValueGenerator: $this->randomValueGenerator, + backend: $this->backend, ); } @@ -163,16 +168,6 @@ public function groupBy(GroupByAlgorithmBuilder $algorithm): self return $this; } - /** - * @param Hydrator $hydrator - */ - public function hydrator(Hydrator $hydrator): self - { - $this->hydrator = $hydrator; - - return $this; - } - public function id(string $id): self { $this->id = $id; diff --git a/src/core/etl/src/Flow/ETL/DSL/functions.php b/src/core/etl/src/Flow/ETL/DSL/functions.php index ae47b26c35..97f70f09ea 100644 --- a/src/core/etl/src/Flow/ETL/DSL/functions.php +++ b/src/core/etl/src/Flow/ETL/DSL/functions.php @@ -17,6 +17,8 @@ use Flow\ETL\Analyze; use Flow\ETL\Cache; use Flow\ETL\Cache\Implementation\FilesystemCache; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Config; use Flow\ETL\Config\ConfigBuilder; use Flow\ETL\Config\Grouping\HashGroupByBuilder; @@ -146,16 +148,15 @@ use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\RandomValueGenerator; use Flow\ETL\Row; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Row\ColumnName; use Flow\ETL\Row\Formatter\ASCIISchemaFormatter; -use Flow\ETL\Row\Hydrator; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Row\InferredBatch; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; use Flow\ETL\Row\SortOrder; use Flow\ETL\Row\UnresolvedReference; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; use Flow\ETL\Schema\Definition\BooleanDefinition; @@ -575,13 +576,13 @@ function rename_map(array $renames): RenameMapEntryStrategy #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] function row(array $values): Row { - return new Row($values); + return (new InferredBatch())->of([$values])->first(); } #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] function rows(Schema $schema, Row ...$row): Rows { - return new Rows($schema, ...$row); + return Rows::of($schema, ...$row); } /** @@ -1179,7 +1180,7 @@ function number_format( function array_to_row( array $data, Schema $schema, - Hydrator $hydrator = new AdaptiveRowHydrator(), + Backend $backend = new DefaultBackend(), array|Partitions $partitions = [], ): Row { $map = []; @@ -1195,14 +1196,17 @@ function array_to_row( } } - return $hydrator->hydrate([new RawRowValues($map)], $schema)->first(); + return (new RowsBuilder($schema, $backend)) + ->appendRows([$map]) + ->finish() + ->first(); } /** * @param array>|array $data */ #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] -function array_to_rows(array $data, Schema $schema, Hydrator $hydrator = new AdaptiveRowHydrator()): Rows +function array_to_rows(array $data, Schema $schema, Backend $backend = new DefaultBackend()): Rows { $isRows = true; @@ -1232,10 +1236,12 @@ function array_to_rows(array $data, Schema $schema, Hydrator $hydrator = new Ada $map[$declared === null ? (new ColumnName())->of($key) : (string) $key] = $value; } - $maps[] = new RawRowValues($map); + $maps[] = $map; } - return $hydrator->hydrate($maps, $schema); + return (new RowsBuilder($schema, $backend)) + ->appendRows($maps) + ->finish(); } #[DocumentationDSL(module: Module::CORE, type: DSLType::WINDOW_FUNCTION)] diff --git a/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php b/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php index b2ff42e379..fe66d77537 100644 --- a/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php +++ b/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php @@ -4,8 +4,11 @@ namespace Flow\ETL\Exception; +use DateTimeInterface; use Flow\ETL\Schema\Definition; +use Flow\Types\Exception\Exception as TypesException; use Flow\Types\Type\TypeDetector; +use Throwable; use function get_debug_type; use function is_bool; @@ -21,8 +24,9 @@ final class ColumnMismatchException extends InvalidArgumentException private function __construct( public readonly string $column, public readonly string $detail, + ?Throwable $previous = null, ) { - parent::__construct('Row does not match its schema: column "' . $column . '"' . $detail); + parent::__construct('Row does not match its schema: column "' . $column . '"' . $detail, 0, $previous); } /** @@ -41,20 +45,47 @@ public static function unexpectedColumn(string $column): self /** * @param Definition $definition */ - public static function valueDoesNotMatch(Definition $definition, mixed $value): self + public static function retype(Definition $definition, string $reason): self + { + return new self($definition->entry()->name(), sprintf( + ': cannot retype the column to %s, %s', + $definition->type()->toString(), + $reason, + )); + } + + /** + * @param Definition $definition + */ + public static function unsupportedType(Definition $definition, string $reason): self + { + return new self($definition->entry()->name(), sprintf( + ': %s cannot be a batch column, %s', + $definition->type()->toString(), + $reason, + )); + } + + /** + * @param Definition $definition + */ + public static function valueDoesNotMatch(Definition $definition, mixed $value, ?TypesException $reason = null): self { return new self( $definition->entry()->name(), - $value === null - ? sprintf(': could not convert null to %s, column is not nullable', $definition->type()->toString()) - : sprintf( - ': could not convert %s (%s) to %s', - self::describe($value), - (new TypeDetector()) - ->detectType($value) - ->toString(), - $definition->type()->toString(), - ), + ( + $value === null + ? sprintf(': could not convert null to %s, column is not nullable', $definition->type()->toString()) + : sprintf( + ': could not convert %s (%s) to %s', + self::describe($value), + (new TypeDetector()) + ->detectType($value) + ->toString(), + $definition->type()->toString(), + ) + ) . ($reason === null ? '' : ' - ' . $reason->getMessage()), + $reason, ); } @@ -64,6 +95,7 @@ private static function describe(mixed $value): string is_string($value) => "'" . (strlen($value) > 32 ? substr($value, 0, 32) . '...' : $value) . "'", is_bool($value) => $value ? 'true' : 'false', is_int($value), is_float($value) => (string) $value, + $value instanceof DateTimeInterface => $value->format('Y-m-d\TH:i:s.uP'), default => get_debug_type($value), }; } diff --git a/src/core/etl/src/Flow/ETL/Executor.php b/src/core/etl/src/Flow/ETL/Executor.php index cf51e2bbea..63e2543660 100644 --- a/src/core/etl/src/Flow/ETL/Executor.php +++ b/src/core/etl/src/Flow/ETL/Executor.php @@ -105,9 +105,9 @@ public function merge(Generator $batches, PhysicalPlan $plan): Rows } try { - return new Rows($plan->schema()); + return Rows::of($plan->schema()); } catch (SchemaNotDerivableException) { - return new Rows(new Schema()); + return Rows::of(new Schema()); } } diff --git a/src/core/etl/src/Flow/ETL/Executor/Segment.php b/src/core/etl/src/Flow/ETL/Executor/Segment.php index 09eb6554be..965693ff22 100644 --- a/src/core/etl/src/Flow/ETL/Executor/Segment.php +++ b/src/core/etl/src/Flow/ETL/Executor/Segment.php @@ -130,7 +130,7 @@ public function execute(Generator $input, FlowContext $context): Generator } catch (LimitReachedException $limit) { $context->telemetry()->limitReached(['limit' => $limit->limit]); // the remaining steps still run, on the trimmed batch - $rows = $limit->rows ?? new Rows($rows->schema()); + $rows = $limit->rows ?? Rows::of($rows->schema()); $stop = true; } catch (Throwable $failure) { if ($failure instanceof SinkFailure) { diff --git a/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php index 4e44843471..4832f04613 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php @@ -86,7 +86,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator continue; } - $signal = yield $batches->of($buffer, $schema, $context->hydrator()); + $signal = yield $batches->of($buffer, $schema, $context->backend()); if ($signal === Signal::STOP) { return; @@ -96,7 +96,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator } if ($buffer !== []) { - yield $batches->of($buffer, $schema, $context->hydrator()); + yield $batches->of($buffer, $schema, $context->backend()); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php index 81ae95d6f2..4bba4d0e2e 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php @@ -62,7 +62,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $currentGroupValue = $groupValue; } elseif ($currentGroupValue !== $groupValue) { if ($this->minSize === null || count($buffer) >= $this->minSize) { - $signal = yield Rows::trusted($schema, $buffer); + $signal = yield Rows::of($schema, ...$buffer); if ($signal === Signal::STOP) { return; @@ -79,7 +79,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator } if (count($buffer) > 0) { - yield Rows::trusted($schema ?? $this->schema(), $buffer); + yield Rows::of($schema ?? $this->schema(), ...$buffer); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php index ccf19c498b..57d9a5ae02 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php @@ -10,8 +10,6 @@ use Flow\ETL\Schema; use Generator; -use function count; - final class BatchExtractor implements BatchableExtractor, Extractor, OverridingExtractor, RewindableExtractor { use Batches; @@ -30,33 +28,38 @@ public function __construct( */ 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() + // pinned from the declaration or the first child batch, then every later batch is matched to it - a window + // spans child batches, so they must all answer to one schema before they are concatenated $schema = $this->schema; - $buffer = []; + /** @var list $pending */ + $pending = []; + $pendingCount = 0; foreach ($this->extractor->extract($context) as $rows) { $schema ??= $rows->schema(); - $rows = $rows->matchTo($schema); - - foreach ($rows->all() as $row) { - $buffer[] = $row; + $pending[] = $rows->matchTo($schema); + $pendingCount += $rows->count(); - if (count($buffer) === $this->batchSize) { - $signal = yield Rows::trusted($schema, $buffer); + while ($pendingCount >= $this->batchSize) { + // one variadic concat per window copies each row once; a pairwise concat per child batch would + // re-copy everything pending + $window = Rows::of($schema)->concat(...$pending); + $signal = yield $window->slice(0, $this->batchSize); - if ($signal === Signal::STOP) { - return; - } - - $buffer = []; + if ($signal === Signal::STOP) { + return; } + + $pending = $window->count() > $this->batchSize + ? [$window->slice($this->batchSize, $window->count() - $this->batchSize)] + : []; + $pendingCount -= $this->batchSize; } } - if ($buffer !== []) { - yield Rows::trusted($schema ?? $this->schema(), $buffer); + if ($pendingCount > 0) { + yield Rows::of($schema ?? $this->schema())->concat(...$pending); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php index 159e1c1602..bed4f53ad8 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php @@ -32,7 +32,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $collectedRows = $collectedRows === null ? $rows : $collectedRows->merge($rows); } - yield $collectedRows ?? new Rows($this->schema()); + yield $collectedRows ?? Rows::of($this->schema()); } public function isRepeatable(): bool diff --git a/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php index cf3c7a86ea..83b6c66dd5 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php @@ -46,7 +46,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator 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()); + $rows = array_to_rows($rows->toArray(), $this->schema, $context->backend()); } $signal = yield $rows; diff --git a/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php index e242faafd5..94139bf31a 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php @@ -59,7 +59,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator // is parked, so both operands can change between the yield and this check. if ($this->batch === null && !$this->finished) { // a downstream projection still sees the columns it was built against - $signal = yield new Rows($this->schema); + $signal = yield Rows::of($this->schema); if ($signal === Signal::STOP) { return; diff --git a/src/core/etl/src/Flow/ETL/Extractor/FileConstants.php b/src/core/etl/src/Flow/ETL/Extractor/FileConstants.php index e478dda5e1..51170cfa61 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FileConstants.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FileConstants.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Extractor; -use Flow\ETL\Row; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Rows; use Flow\ETL\Schema; +use function array_key_exists; + final readonly class FileConstants { /** @@ -42,19 +45,30 @@ public function fill(array $row): array * fill() over a batch the reader already matched to the file's body schema, adopting $declared - the schema * FileColumns::declare() built over that body schema. A batch with nothing to add is returned as it is. */ - public function fillRows(Rows $rows, Schema $declared): Rows + public function fillRows(Rows $rows, Schema $declared, Backend $backend = new DefaultBackend()): Rows { if ($this->uri === null && $this->partitionNames === []) { return $rows; } - $filled = []; + $added = []; + + if ($this->uri !== null) { + $added['_input_file_uri'] = $backend->constant( + $declared->get('_input_file_uri'), + $this->uri, + $rows->count(), + ); + } - foreach ($rows->all() as $row) { - $filled[] = new Row($this->fill($row->values())); + foreach ($this->partitionNames as $name => $_) { + $added[$name] = $backend->constant( + $declared->get($name), + array_key_exists($name, $this->partitionValues) ? $this->partitionValues[$name] : null, + $rows->count(), + ); } - // declare() appends the tail in the order fill() writes it, so the rows need no second check - return Rows::trusted($declared, $filled); + return $rows->withColumns($declared, $added); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php index 3f4383ab28..30e920a768 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php @@ -90,7 +90,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $yielded += count($buffer); - $signal = yield array_to_rows($buffer, $schema, $context->hydrator()); + $signal = yield array_to_rows($buffer, $schema, $context->backend()); if ($signal === Signal::STOP) { return; @@ -104,7 +104,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } if ($buffer !== []) { - yield array_to_rows($buffer, $schema, $context->hydrator()); + yield array_to_rows($buffer, $schema, $context->backend()); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php b/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php index 4ffd696729..b64724d7a1 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php +++ b/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Extractor; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Row\Hydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; @@ -35,10 +35,10 @@ public function __construct( * * @throws InferredSchemaException|SchemaMismatchException */ - public function of(array $rows, Schema $schema, Hydrator $hydrator): Rows + public function of(array $rows, Schema $schema, Backend $backend): Rows { try { - $batch = array_to_rows($rows, $schema, $hydrator); + $batch = array_to_rows($rows, $schema, $backend); } catch (SchemaMismatchException $mismatch) { $row = $this->offset + $mismatch->rowIndex; diff --git a/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php index 2c62187509..cf23c8822c 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php @@ -54,7 +54,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator continue; } - $signal = yield $batches->of($buffer, $schema, $context->hydrator()); + $signal = yield $batches->of($buffer, $schema, $context->backend()); if ($signal === Signal::STOP) { return; @@ -64,7 +64,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator } if ($buffer !== []) { - yield $batches->of($buffer, $schema, $context->hydrator()); + yield $batches->of($buffer, $schema, $context->backend()); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/PartitionColumns.php b/src/core/etl/src/Flow/ETL/Extractor/PartitionColumns.php index 3c3bc991f3..563c4984b7 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/PartitionColumns.php +++ b/src/core/etl/src/Flow/ETL/Extractor/PartitionColumns.php @@ -101,7 +101,7 @@ public function apply(Rows $rows, array $names, PartitionTypes $types = new Part : str_schema($name, nullable: $nullable); } - return new Rows($rows->schema()->gracefulRemove(...array_keys($names))->add(...$definitions), ...$rows->all()); + return $rows->matchTo($rows->schema()->gracefulRemove(...array_keys($names))->add(...$definitions)); } /** diff --git a/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php index 567f4a823b..b68aff1262 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php @@ -90,7 +90,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $yielded += count($buffer); - $signal = yield array_to_rows($buffer, $schema, $context->hydrator()); + $signal = yield array_to_rows($buffer, $schema, $context->backend()); if ($signal === Signal::STOP) { return; @@ -104,7 +104,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } if ($buffer !== []) { - yield array_to_rows($buffer, $schema, $context->hydrator()); + yield array_to_rows($buffer, $schema, $context->backend()); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php index 80b299ef89..0567a7672e 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php @@ -59,7 +59,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator continue; } - $signal = yield $batches->of($buffer, $schema, $context->hydrator()); + $signal = yield $batches->of($buffer, $schema, $context->backend()); if ($signal === Signal::STOP) { return; @@ -69,7 +69,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator } if ($buffer !== []) { - yield $batches->of($buffer, $schema, $context->hydrator()); + yield $batches->of($buffer, $schema, $context->backend()); } } diff --git a/src/core/etl/src/Flow/ETL/FlowContext.php b/src/core/etl/src/Flow/ETL/FlowContext.php index 9a81873b84..a81c12f6fc 100644 --- a/src/core/etl/src/Flow/ETL/FlowContext.php +++ b/src/core/etl/src/Flow/ETL/FlowContext.php @@ -5,6 +5,7 @@ namespace Flow\ETL; use Flow\Calculator\Calculator; +use Flow\ETL\Column\Backend; use Flow\ETL\Config\Telemetry\TelemetryContext; use Flow\ETL\ErrorHandler\ThrowError; use Flow\ETL\Row\Hydrator; @@ -40,6 +41,11 @@ public function errorHandler(): ErrorHandler return $this->errorHandler; } + public function backend(): Backend + { + return $this->config->backend(); + } + /** * @return Hydrator */ diff --git a/src/core/etl/src/Flow/ETL/Function/OnEach.php b/src/core/etl/src/Flow/ETL/Function/OnEach.php index 2e531ed8e8..8bb1bb9905 100644 --- a/src/core/etl/src/Flow/ETL/Function/OnEach.php +++ b/src/core/etl/src/Flow/ETL/Function/OnEach.php @@ -101,14 +101,14 @@ public function eval(Row $row, FlowContext $context): mixed $output = []; - $hydrator = $context->hydrator(); + $backend = $context->backend(); // hoisted: array_to_row() runs per element, and the schema is the same for every one of them $elementSchema = $this->elementSchema->of(type_bare($this->array->returns())); // @mago-ignore analysis:mixed-assignment foreach ($value as $key => $item) { $result = (new Parameter($this->function))->eval( - array_to_row(['element' => $item], $elementSchema, $hydrator), + array_to_row(['element' => $item], $elementSchema, $backend), $context, ); diff --git a/src/core/etl/src/Flow/ETL/GroupBy.php b/src/core/etl/src/Flow/ETL/GroupBy.php index 9fa6ab4d08..4f4a52e820 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy.php +++ b/src/core/etl/src/Flow/ETL/GroupBy.php @@ -48,7 +48,10 @@ public function aggregate(AggregatingFunction ...$aggregator): void $this->aggregations = new Aggregators(...$aggregator); } - public function aggregatedRow(GroupKey $key, Aggregators $aggregators, Schema $output): Row + /** + * @return array + */ + public function aggregatedValues(GroupKey $key, Aggregators $aggregators, Schema $output): array { $values = []; @@ -64,7 +67,7 @@ public function aggregatedRow(GroupKey $key, Aggregators $aggregators, Schema $o $values[$aggregator->outputName()] = $value === null ? null : $definition->type()->cast($value); } - return new Row($values); + return $values; } /** diff --git a/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php b/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php index 10161f7178..6b6c14dadf 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php @@ -4,12 +4,15 @@ namespace Flow\ETL\GroupBy; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\FlowContext; use Flow\ETL\GroupBy; -use Flow\ETL\Row\RowsBuffer; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Generator; +use function count; + final class AggregatedGroups { /** @@ -38,18 +41,23 @@ public function accumulate(Rows $batch, FlowContext $context): void */ public function flush(int $batchSize): Generator { - $buffer = new RowsBuffer($this->shape->output, $batchSize); + $pending = []; foreach ($this->groups as $group) { - $aggregated = $this->groupBy->aggregatedRow($group->key, $group->aggregators, $this->shape->output); + $pending[] = $this->groupBy->aggregatedValues($group->key, $group->aggregators, $this->shape->output); - if (null !== ($batch = $buffer->add($aggregated))) { - yield $batch; + if (count($pending) >= $batchSize) { + yield (new RowsBuilder($this->shape->output, new DefaultBackend())) + ->appendRows($pending) + ->finish(); + $pending = []; } } - if (null !== ($batch = $buffer->flush())) { - yield $batch; + if ($pending !== []) { + yield (new RowsBuilder($this->shape->output, new DefaultBackend())) + ->appendRows($pending) + ->finish(); } } } diff --git a/src/core/etl/src/Flow/ETL/GroupBy/PivotedTable.php b/src/core/etl/src/Flow/ETL/GroupBy/PivotedTable.php index 4ee00dfb0c..b91fc71eb9 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/PivotedTable.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/PivotedTable.php @@ -88,13 +88,13 @@ public function flush(int $batchSize, FlowContext $context): Generator $buffer[] = $row; if (count($buffer) >= $batchSize) { - yield array_to_rows($buffer, $this->shape->output, $context->hydrator()); + yield array_to_rows($buffer, $this->shape->output, $context->backend()); $buffer = []; } } if ($buffer !== []) { - yield array_to_rows($buffer, $this->shape->output, $context->hydrator()); + yield array_to_rows($buffer, $this->shape->output, $context->backend()); } } } diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php index ffa525b55e..d504f5361f 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php @@ -8,6 +8,7 @@ use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\SingleBucketHasher; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Exception\DuplicatedEntriesException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Join\Expression; @@ -15,11 +16,13 @@ use Flow\ETL\Join\JoinSchema; use Flow\ETL\Join\JoinShape; use Flow\ETL\Row; -use Flow\ETL\Row\RowsBuffer; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; +use function count; + final class Joiner { private readonly Hasher $hasher; @@ -134,22 +137,17 @@ public function join(JoinSide $left, JoinSide $right, bool $buildLeft = false): } if (!$matched && $this->type === Join::left_anti) { - $joined[] = $leftRow; + $joined[] = $leftRow->values(); } } if ($joined !== []) { - // a later batch can be wider than the side schema the output was derived from, and - // every arm answers for the same declared output - so all of them project, not one - $projected = []; - - foreach ($joined as $joinedRow) { - $projected[] = $joinedRow->project($outputSchema); - } - - // every joined value passed the gate on its own side - conforming checks the joined shape and the - // nulls the join introduced, not the values again - yield Rows::conformed($outputSchema, $projected); + // a later batch can be wider than the side schema the output was derived from, and every arm answers + // for the same declared output - the builder ignores the undeclared keys and pads the nulls the join + // introduced + yield (new RowsBuilder($outputSchema, new DefaultBackend())) + ->appendRows($joined) + ->finish(); } } @@ -157,16 +155,23 @@ public function join(JoinSide $left, JoinSide $right, bool $buildLeft = false): $leftSchema ??= new Schema(); $nullLeftRow ??= (new NullRowBuilder($leftSchema))->row(); $outputSchema ??= $this->joinSchema->of($this->type, $leftSchema, $rightSchema); - $buffer = new RowsBuffer($outputSchema, $this->batchSize, Rows::conformed(...)); + $pending = []; foreach ($hashTable->unmatchedRows() as $rightRow) { - if (null !== ($batch = $buffer->add($this->merge($nullLeftRow, $rightRow)->project($outputSchema)))) { - yield $batch; + $pending[] = $this->merge($nullLeftRow, $rightRow); + + if (count($pending) >= $this->batchSize) { + yield (new RowsBuilder($outputSchema, new DefaultBackend())) + ->appendRows($pending) + ->finish(); + $pending = []; } } - if (null !== ($batch = $buffer->flush())) { - yield $batch; + if ($pending !== []) { + yield (new RowsBuilder($outputSchema, new DefaultBackend())) + ->appendRows($pending) + ->finish(); } } } @@ -247,13 +252,9 @@ private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator } if ($joined !== []) { - $projected = []; - - foreach ($joined as $joinedRow) { - $projected[] = $joinedRow->project($outputSchema); - } - - yield Rows::conformed($outputSchema, $projected); + yield (new RowsBuilder($outputSchema, new DefaultBackend())) + ->appendRows($joined) + ->finish(); } } @@ -262,23 +263,31 @@ private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator if ($this->type === Join::left || $this->type === Join::left_anti) { $nullRightRow ??= (new NullRowBuilder($rightSchema))->row(); $outputSchema ??= $this->joinSchema->of($this->type, $leftSchema, $rightSchema); - $buffer = new RowsBuffer($outputSchema, $this->batchSize, Rows::conformed(...)); + $pending = []; foreach ($hashTable->unmatchedRows() as $leftRow) { - $joined = $this->type === Join::left ? $this->merge($leftRow, $nullRightRow) : $leftRow; + $pending[] = $this->type === Join::left ? $this->merge($leftRow, $nullRightRow) : $leftRow->values(); - if (null !== ($batch = $buffer->add($joined->project($outputSchema)))) { - yield $batch; + if (count($pending) >= $this->batchSize) { + yield (new RowsBuilder($outputSchema, new DefaultBackend())) + ->appendRows($pending) + ->finish(); + $pending = []; } } - if (null !== ($batch = $buffer->flush())) { - yield $batch; + if ($pending !== []) { + yield (new RowsBuilder($outputSchema, new DefaultBackend())) + ->appendRows($pending) + ->finish(); } } } - private function merge(Row $left, Row $right): Row + /** + * @return array + */ + private function merge(Row $left, Row $right): array { try { return $this->merger->merge($left, $right); diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php index ca54921c03..f456fc286f 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php @@ -4,19 +4,30 @@ namespace Flow\ETL\Join\HashJoin; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\ETL\Schema; -use function array_fill_keys; - final readonly class NullRowBuilder { - public function __construct( - private Schema $schema, - ) {} + private Row $row; + + public function __construct(Schema $schema) + { + $nullable = $schema->makeNullable(); + $backend = new PhpBackend(); + $columns = []; + + foreach ($nullable->definitions() as $name => $definition) { + $columns[$name] = $backend->constant($definition, null, 1); + } + + $this->row = Rows::fromColumns($nullable, $columns, 1)->row(0); + } public function row(): Row { - return new Row(array_fill_keys($this->schema->references()->names(), null)); + return $this->row; } } diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/RowMerger.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/RowMerger.php index 731d290599..3e9a7b0d55 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/RowMerger.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/RowMerger.php @@ -56,8 +56,10 @@ public function __construct( /** * @throws DuplicatedEntriesException + * + * @return array */ - public function merge(Row $left, Row $right): Row + public function merge(Row $left, Row $right): array { $leftValues = $left->values(); $rightValues = $right->values(); @@ -85,7 +87,7 @@ public function merge(Row $left, Row $right): Row $values[$renames[$name] ?? $name] = $value; } - return new Row($values); + return $values; } /** diff --git a/src/core/etl/src/Flow/ETL/Join/JoinSchema.php b/src/core/etl/src/Flow/ETL/Join/JoinSchema.php index 74d1013a29..b1da2293f5 100644 --- a/src/core/etl/src/Flow/ETL/Join/JoinSchema.php +++ b/src/core/etl/src/Flow/ETL/Join/JoinSchema.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Join; +use Flow\ETL\Exception\SchemaDefinitionNotUniqueException; use Flow\ETL\Schema; final readonly class JoinSchema @@ -34,11 +35,19 @@ public function of(Join $type, Schema $left, Schema $right): Schema } } - return match ($type) { - Join::left_anti => $leftSide, - Join::left => $leftSide->add(...$rightSide->makeNullable()->definitions()), - Join::right => $leftSide->makeNullable()->add(...$rightSide->definitions()), - Join::inner => $leftSide->add(...$rightSide->definitions()), - }; + try { + return match ($type) { + Join::left_anti => $leftSide, + Join::left => $leftSide->add(...$rightSide->makeNullable()->definitions()), + Join::right => $leftSide->makeNullable()->add(...$rightSide->definitions()), + Join::inner => $leftSide->add(...$rightSide->definitions()), + }; + } catch (SchemaDefinitionNotUniqueException $e) { + throw new SchemaDefinitionNotUniqueException( + $e->getMessage() . '. Please consider using join prefix option', + (int) $e->getCode(), + $e, + ); + } } } diff --git a/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php b/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php index 325ff9361c..bfbe0c831e 100644 --- a/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php +++ b/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php @@ -14,7 +14,6 @@ use Flow\Filesystem\Partitions; use Generator; -use function array_diff_key; use function array_flip; use function array_keys; use function array_values; @@ -72,22 +71,10 @@ public function route(Rows $rows): Generator $stripped = $this->dropped === [] ? $schema : $schema->gracefulRemove(...$this->partitioning->by->names()); - // a group is a subset of a batch that already passed the gate, and stripping removes the same - // columns from its rows and from the schema, so neither needs checking again foreach ($groups as [$partitions, $rowsOfGroup]) { - if ($this->dropped === []) { - yield [$partitions, Rows::trusted($schema, $rowsOfGroup)]; + $group = Rows::of($schema, ...$rowsOfGroup); - continue; - } - - $strippedRows = []; - - foreach ($rowsOfGroup as $row) { - $strippedRows[] = new Row(array_diff_key($row->values(), $this->dropped)); - } - - yield [$partitions, Rows::trusted($stripped, $strippedRows)]; + yield [$partitions, $this->dropped === [] ? $group : $group->project($stripped)]; } } diff --git a/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php index 3900d9a64c..5bb915a52b 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php @@ -73,7 +73,7 @@ public function process(Generator $rows, FlowContext $context): Generator if ($value !== $currentValue) { if ($this->minSize === null || count($buffer) >= $this->minSize) { if ($buffer !== []) { - $signal = yield new Rows($schema, ...$buffer); + $signal = yield Rows::of($schema, ...$buffer); if ($signal === Signal::STOP) { $rows->send(Signal::STOP); @@ -94,7 +94,7 @@ public function process(Generator $rows, FlowContext $context): Generator } if ($buffer !== []) { - yield new Rows($schema ?? new Schema(), ...$buffer); + yield Rows::of($schema ?? new Schema(), ...$buffer); } } } diff --git a/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php index e9608210f7..8d607c739d 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php @@ -53,21 +53,16 @@ public function process(Generator $rows, FlowContext $context): Generator $schema = null; - // rows re-batched from batches under one schema already passed the gate under it - only a batch that - // arrives under another schema needs the full gate to conform it to the first one - $uniform = true; - while ($rows->valid()) { $batch = $rows->current(); $schema ??= $batch->schema(); - $uniform = $uniform && $batch->schema()->isSame($schema); foreach ($batch as $row) { $buffer[] = $row; if (count($buffer) >= $this->size) { $chunk = array_splice($buffer, 0, $this->size); - $signal = yield $uniform ? Rows::trusted($schema, $chunk) : new Rows($schema, ...$chunk); + $signal = yield Rows::of($schema, ...$chunk); if ($signal === Signal::STOP) { $rows->send(Signal::STOP); @@ -83,7 +78,7 @@ public function process(Generator $rows, FlowContext $context): Generator if ($buffer !== []) { $schema ??= new Schema(); - yield $uniform ? Rows::trusted($schema, $buffer) : new Rows($schema, ...$buffer); + yield Rows::of($schema, ...$buffer); } } } diff --git a/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php index 0771eb56f5..bfccdd1522 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php @@ -31,7 +31,7 @@ public function process(Generator $rows, FlowContext $context): Generator foreach ($this->strategy->bucketize($rows, $this->buckets->storage()) as $bucket) { $this->buckets->add($bucket); - yield new Rows(Bucket::schema(), $bucket->toRow()); + yield Rows::of(Bucket::schema(), $bucket->toRow()); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php index 4c988fd0d9..0ffea693c8 100644 --- a/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php @@ -37,6 +37,6 @@ public function process(Generator $rows, FlowContext $context): Generator $collected = $collected === null ? $batch : $collected->merge($batch); } - yield $collected ?? new Rows($this->declared ?? new Schema()); + yield $collected ?? Rows::of($this->declared ?? new Schema()); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php index 77d8b765f1..61f2ac6ee5 100644 --- a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php @@ -7,6 +7,7 @@ use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\BucketShape; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\FlowContext; @@ -16,6 +17,7 @@ use Flow\ETL\GroupBy\GroupKey; use Flow\ETL\Processor; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; @@ -89,14 +91,13 @@ public function process(Generator $rows, FlowContext $context): Generator // SQL's scalar aggregate: no input and no grouping key is one row of the initial accumulators, // not no row. Only reachable bound - an unbound plan has no schema to type the defaults with. if (!$emitted && $this->shape !== null && $this->groupBy->isGlobal()) { - yield new Rows( - $this->shape->output, - $this->groupBy->aggregatedRow( + yield (new RowsBuilder($this->shape->output, new DefaultBackend()))->appendRows([ + $this->groupBy->aggregatedValues( new GroupKey([]), $this->shape->aggregators->cloned(), $this->shape->output, ), - ); + ])->finish(); } } finally { $this->buckets->clear(); diff --git a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php index 8453c718f6..20c4edd9a7 100644 --- a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php @@ -299,9 +299,9 @@ private function tap(Generator $rows, ?Schema &$schema, ?array $dropNullKeyRefs) $kept[] = $row; } - $batch = Rows::trusted($batch->schema(), $kept); + $batch = Rows::of($batch->schema(), ...$kept); - if ($batch->empty()) { + if ($batch->isEmpty()) { continue; } } diff --git a/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php b/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php index ffbb7a23ae..fef523e3b0 100644 --- a/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php @@ -36,7 +36,7 @@ public function process(Generator $rows, FlowContext $context): Generator foreach ($rows as $batch) { $schema ??= $batch->schema(); - if ($batch->empty()) { + if ($batch->isEmpty()) { continue; } @@ -47,9 +47,9 @@ public function process(Generator $rows, FlowContext $context): Generator } } - yield from (new Rows($this->declared ?? $schema ?? new Schema(), ...$buffer)) - ->sortBy(...$this->refs->all()) - ->chunks($maxSize); + yield from Rows::of($this->declared ?? $schema ?? new Schema(), ...$buffer)->sortBy( + ...$this->refs->all(), + )->chunks($maxSize); } public function bind(Schema $input): BoundStep diff --git a/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php b/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php index 92e2a4860f..92ed8cc5a1 100644 --- a/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php @@ -52,7 +52,7 @@ public function process(Generator $rows, FlowContext $context): Generator foreach ($rows as $batch) { $schema ??= $batch->schema(); - if ($batch->empty()) { + if ($batch->isEmpty()) { continue; } @@ -68,7 +68,7 @@ public function process(Generator $rows, FlowContext $context): Generator } } - yield from (new Rows($this->declared ?? $schema ?? new Schema(), ...$this->top($kept, $schema)))->chunks( + yield from Rows::of($this->declared ?? $schema ?? new Schema(), ...$this->top($kept, $schema))->chunks( $maxSize, ); } @@ -80,9 +80,8 @@ public function process(Generator $rows, FlowContext $context): Generator */ 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(); + return Rows::of($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 33077907ba..64dba96775 100644 --- a/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php @@ -31,6 +31,6 @@ public function process(Generator $rows, FlowContext $context): Generator } // void() drops rows, not columns - yield new Rows($this->declared ?? new Schema()); + yield Rows::of($this->declared ?? new Schema()); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php b/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php index 7cc8772789..cb62ce6857 100644 --- a/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php @@ -5,7 +5,9 @@ namespace Flow\ETL\Processor; use Flow\ETL\BoundStep; +use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\FlowContext; use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\FrameAccumulating; @@ -56,7 +58,7 @@ public function process(Generator $rows, FlowContext $context): Generator $bound ??= $this->boundTo($batch->schema()); if (!$batch->count()) { - yield new Rows($bound->output); + yield Rows::of($bound->output); continue; } @@ -182,7 +184,7 @@ private function processPartition(BoundWindow $bound, array $rows, FlowContext $ $partitionRows = rows($bound->input, ...$rows)->sortBy(...$sortBy); $frame = $window->frame(); - $processedRows = []; + $builder = $context->backend()->builder($derived); $values = match (true) { $resolved instanceof PartitionRanking => $resolved->rankPartition($partitionRows), @@ -200,12 +202,13 @@ private function processPartition(BoundWindow $bound, array $rows, FlowContext $ ? $resolved->apply(new WindowContext($row, $index, $partitionRows, $frame, $context)) : $values[$index]; - $processedRows[] = new Row([ - ...$row->values(), - $derived->entry()->name() => $value === null ? null : $derived->type()->cast($value), - ]); + try { + $builder->append($value === null ? null : $derived->type()->cast($value)); + } catch (ColumnMismatchException $e) { + throw new SchemaMismatchException($index, $e); + } } - return rows($bound->output, ...$processedRows); + return $partitionRows->withColumns($bound->output, [$derived->entry()->name() => $builder->finish()]); } } diff --git a/src/core/etl/src/Flow/ETL/Row.php b/src/core/etl/src/Flow/ETL/Row.php index 6eaa1e9fd1..85e92082c8 100644 --- a/src/core/etl/src/Flow/ETL/Row.php +++ b/src/core/etl/src/Flow/ETL/Row.php @@ -4,71 +4,31 @@ namespace Flow\ETL; -use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Hash\Algorithm; use Flow\ETL\Hash\NativePHPHash; use Flow\ETL\Row\Reference; -use Flow\ETL\Schema\Definition\ZoneAlignment; -use Flow\ETL\Schema\SimilarNames; use Flow\Types\Type\TypedValueFormatter; use Flow\Types\Value\Json; -use function array_diff_key; -use function array_key_exists; -use function array_keys; -use function array_map; use function array_values; -use function count; -use function implode; final readonly class Row { /** - * @param array $values storage keyed by name; the Schema defines column order (Rows::schema()->references()) + * @throws InvalidArgumentException */ public function __construct( - private array $values, - ) {} - - /** - * Rewrites the storage to satisfy $schema: columns take the Schema's order and a declared - * nullable column the row omits is padded with null. The row does not know its position in a - * batch - Rows places the violation with SchemaMismatchException. - * - * @throws ColumnMismatchException - */ - public function matchTo(Schema $schema): self - { - return $this->conform($schema, checkValues: true); - } - - /** - * matchTo() without its value check: the order, padding, missing, unknown and null rules all hold, but a non-null - * value is not validated against its type - the caller produced it by casting to, or decoding from, that type. - * - * @throws ColumnMismatchException - */ - public function conformTo(Schema $schema): self - { - return $this->conform($schema, checkValues: false); - } - - /** - * Drops the columns $schema does not declare and carries its order into the row. Unlike - * matchTo() it validates nothing - the caller is changing the shape, not checking it. - */ - public function project(Schema $schema): self - { - $projected = []; - - foreach ($schema->definitions() as $name => $_) { - if (array_key_exists($name, $this->values)) { - $projected[$name] = $this->values[$name]; - } + public Rows $rows, + public int $index, + ) { + if ($index < 0 || $index >= $rows->count()) { + throw InvalidArgumentException::because( + 'Row %d does not exist in a batch of %d rows', + $index, + $rows->count(), + ); } - - return new self($projected); } /** @@ -78,34 +38,19 @@ public function project(Schema $schema): self */ public function get(string|Reference $reference): mixed { - $name = $reference instanceof Reference ? $reference->base() : $reference; - - if (!array_key_exists($name, $this->values)) { - $suggestions = (new SimilarNames())->closestTo( - $name, - array_values(array_map( - static fn(int|string $column): string => (string) $column, - array_keys($this->values), - )), - ); - - throw new InvalidArgumentException( - $suggestions === [] - ? "Column \"{$name}\" does not exist." - : "Column \"{$name}\" does not exist. Did you mean one of the following? [\"" - . implode('", "', $suggestions) - . '"]', - ); - } - // @mago-ignore analysis:mixed-return-statement - return $this->values[$name]; + return $this->rows + ->column($reference instanceof Reference ? $reference->base() : $reference) + ->value($this->index); } public function has(string|Reference ...$references): bool { foreach ($references as $reference) { - if (!array_key_exists($reference instanceof Reference ? $reference->base() : $reference, $this->values)) { + if ( + $this->rows->schema()->findDefinition($reference instanceof Reference ? $reference->base() : $reference) + === null + ) { return false; } } @@ -120,7 +65,7 @@ public function hash(Schema $schema, Algorithm $algorithm = new NativePHPHash()) foreach ($schema->sort()->definitions() as $definition) { $name = $definition->entry()->name(); - $string .= $name . $formatter->format($definition->type(), $this->values[$name] ?? null); + $string .= $name . $formatter->format($definition->type(), $this->has($name) ? $this->get($name) : null); } return $algorithm->hash($string); @@ -131,7 +76,7 @@ public function hash(Schema $schema, Algorithm $algorithm = new NativePHPHash()) */ public function names(): array { - return array_map(strval(...), array_keys($this->values)); + return array_values($this->rows->schema()->references()->names()); } /** @@ -142,7 +87,7 @@ public function toArray(bool $withKeys = true): array $data = []; // @mago-ignore analysis:mixed-assignment - foreach ($this->values as $name => $value) { + foreach ($this->values() as $name => $value) { if ($value instanceof Json) { $value = $value->toArray(); } @@ -158,98 +103,6 @@ public function toArray(bool $withKeys = true): array */ public function values(): array { - return $this->values; - } - - /** - * @throws ColumnMismatchException - */ - private function conform(Schema $schema, bool $checkValues): self - { - $definitions = $schema->definitions(); - $columns = $checkValues ? $schema->zonedDefinitions() : []; - $changed = false; - - if (count($this->values) === count($definitions) && array_keys($this->values) === array_keys($definitions)) { - foreach ($columns === [] ? $definitions : array_diff_key($definitions, $columns) as $name => $definition) { - if ( - $checkValues - ? !$definition->matches($this->values[$name]) - : $this->values[$name] === null && !$definition->isNullable() - ) { - throw ColumnMismatchException::valueDoesNotMatch($definition, $this->values[$name]); - } - } - - if ($columns === []) { - return $this; - } - - $values = $this->values; - } else { - $matched = []; - $taken = 0; - - foreach ($definitions as $name => $definition) { - if (!array_key_exists($name, $this->values)) { - if (!$definition->isNullable()) { - throw ColumnMismatchException::missingColumn($definition); - } - - $matched[$name] = null; - - continue; - } - - $taken++; - - if ( - $checkValues - ? !$definition->matches($this->values[$name]) - : $this->values[$name] === null && !$definition->isNullable() - ) { - throw ColumnMismatchException::valueDoesNotMatch($definition, $this->values[$name]); - } - - $matched[$name] = $this->values[$name]; - } - - if ($taken !== count($this->values)) { - foreach ($this->values as $name => $_) { - if (!array_key_exists($name, $definitions)) { - throw ColumnMismatchException::unexpectedColumn((string) $name); - } - } - } - - if ($columns === []) { - return new self($matched); - } - - $values = $matched; - $changed = true; - } - - $alignment = new ZoneAlignment(); - - foreach ($columns as $name => $definition) { - if ($alignment->inZone($definition, $values[$name])) { - continue; - } - - if (!$definition->matches($values[$name])) { - throw ColumnMismatchException::valueDoesNotMatch($definition, $values[$name]); - } - - // @mago-ignore analysis:mixed-assignment - $aligned = $alignment->align($definition, $values[$name]); - - if ($aligned !== $values[$name]) { - $values[$name] = $aligned; - $changed = true; - } - } - - return $changed ? new self($values) : $this; + return $this->rows->values($this->index); } } diff --git a/src/core/etl/src/Flow/ETL/Row/AdaptiveRowHydrator.php b/src/core/etl/src/Flow/ETL/Row/AdaptiveRowHydrator.php deleted file mode 100644 index 91017e3e52..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/AdaptiveRowHydrator.php +++ /dev/null @@ -1,33 +0,0 @@ -delegate = NativeRowHydrator::isSupported() ? new NativeRowHydrator() : new PhpRowHydrator(); - } - - public function isNative(): bool - { - return $this->delegate instanceof NativeRowHydrator; - } - - public function dehydrate(Rows $rows): array - { - return $this->delegate->dehydrate($rows); - } - - public function hydrate(array $batch, Schema $schema): Rows - { - return $this->delegate->hydrate($batch, $schema); - } -} diff --git a/src/core/etl/src/Flow/ETL/Row/Formatter/ASCIISchemaFormatter.php b/src/core/etl/src/Flow/ETL/Row/Formatter/ASCIISchemaFormatter.php index 23f563f02e..aa6cbd85bd 100644 --- a/src/core/etl/src/Flow/ETL/Row/Formatter/ASCIISchemaFormatter.php +++ b/src/core/etl/src/Flow/ETL/Row/Formatter/ASCIISchemaFormatter.php @@ -4,9 +4,10 @@ namespace Flow\ETL\Row\Formatter; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Formatter\AsciiTableFormatter; -use Flow\ETL\Row; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; use Flow\ETL\Schema\SchemaFormatter; @@ -68,7 +69,7 @@ private function table(Schema $schema): Rows $values['metadata'] = json_encode($definition->metadata()->normalize(), JSON_THROW_ON_ERROR); } - $rows[] = new Row($values); + $rows[] = $values; } $columns = [str_schema('name'), str_schema('type'), bool_schema('nullable')]; @@ -77,7 +78,9 @@ private function table(Schema $schema): Rows $columns[] = str_schema('metadata'); } - return new Rows(schema(...$columns), ...$rows); + return (new RowsBuilder(schema(...$columns), new DefaultBackend())) + ->appendRows($rows) + ->finish(); } /** diff --git a/src/core/etl/src/Flow/ETL/Row/HydratedBatch.php b/src/core/etl/src/Flow/ETL/Row/HydratedBatch.php deleted file mode 100644 index 0e81ad170e..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/HydratedBatch.php +++ /dev/null @@ -1,84 +0,0 @@ - $batch - * - * @throws SchemaMismatchException - */ - public function of(array $batch, Schema $schema): Rows - { - // Nullability is a Definition flag, never a property of a Type: definition_from_type() - // unwraps OptionalType into nullable: true over a BARE type, so $definition->type() is - // non-nullable even for a nullable column and would refuse every legitimate null. - $prepare = static fn(mixed $value, Definition $definition): mixed => ( - $value === null - ? ($definition->isNullable() ? null : throw new CastingException(null, $definition->type())) - : $definition->type()->cast($value) - ); - - foreach ($batch as $rowValues) { - foreach ($rowValues->metadata as $name => $metadata) { - // PHP casts a numeric array key to int, column names are always strings - $name = (string) $name; - - if ($schema->findDefinition($name) !== null) { - $schema = $schema->setMetadata($name, $metadata); - } - } - } - - $definitions = $schema->definitions(); - $rows = []; - - foreach ($batch as $rowIndex => $rowValues) { - $values = []; - - foreach ($definitions as $definition) { - $name = $definition->entry()->name(); - - if (!array_key_exists($name, $rowValues->values)) { - // never fill: Rows::conformed() runs Row::conformTo(), which pads a declared-nullable - // absence and refuses a NOT-NULL one as a missing column rather than as a null value - continue; - } - - try { - $values[$name] = $prepare($rowValues->values[$name], $definition); - } catch (TypesException) { - // Rows' gate reports a misfit this way, but $prepare runs before the Rows - // constructor, so the batch has to place the violation itself. - throw new SchemaMismatchException($rowIndex, ColumnMismatchException::valueDoesNotMatch( - $definition, - $rowValues->values[$name], - )); - } - } - - $rows[] = new Row($values); - } - - // every non-null value was just cast to its column's type - the one place a value is validated - return Rows::conformed($schema, $rows); - } -} diff --git a/src/core/etl/src/Flow/ETL/Row/InferredBatch.php b/src/core/etl/src/Flow/ETL/Row/InferredBatch.php index ee78177a1a..98eb658091 100644 --- a/src/core/etl/src/Flow/ETL/Row/InferredBatch.php +++ b/src/core/etl/src/Flow/ETL/Row/InferredBatch.php @@ -4,12 +4,13 @@ namespace Flow\ETL\Row; -use Flow\ETL\Row; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\Types\Type\TypeDetector; -use function array_key_exists; +use function count; use function Flow\ETL\DSL\definition_from_type; /** @@ -22,52 +23,46 @@ public function __construct( ) {} /** - * @param list $batch + * @param list> $batch */ public function of(array $batch): Rows { $schema = new Schema(); - foreach ($batch as $rowValues) { + foreach ($batch as $values) { $definitions = []; /** @var mixed $value */ - foreach ($rowValues->values as $name => $value) { - // RawRowValues::$values is declared array, but PHP hands a numeric - // column name back as an INT key - a pivot names its columns by their own values. - // definition_from_type() takes Reference|string, so the cast is not redundant at runtime. - $name = (string) $name; - $definition = definition_from_type($name, $this->typeDetector->detectType($value), $value === null); - - if (array_key_exists($name, $rowValues->metadata)) { - $definition = $definition->setMetadata($rowValues->metadata[$name]); - } - - $definitions[] = $definition; + foreach ($values as $name => $value) { + // PHP hands a numeric column name back as an INT key - a pivot names its columns by their own values + $definitions[] = definition_from_type( + (string) $name, + $this->typeDetector->detectType($value), + $value === null, + ); } $schema = $schema->merge(new Schema(...$definitions)); } - $rows = []; + $backend = new DefaultBackend(); - // the fold widens a column typed from one row's value to cover every row's - so a value the - // widened definition no longer accepts follows the schema this method just derived - foreach ($batch as $rowValues) { - $values = []; - - /** @var mixed $value */ - foreach ($rowValues->values as $name => $value) { - // see above - an int key here would miss the column the schema declares as "5" - $name = (string) $name; - $definition = $schema->get($name); + // one row's schema is typed from its own values, so every value already fits: one constant per column spares + // the builders a single-row batch does not need + if (count($batch) === 1) { + $columns = []; - $values[$name] = $definition->matches($value) ? $value : $definition->type()->cast($value); + foreach ($schema->definitions() as $name => $definition) { + $columns[$name] = $backend->constant($definition, $batch[0][$name], 1); } - $rows[] = new Row($values); + return Rows::fromColumns($schema, $columns, 1); } - return new Rows($schema, ...$rows); + // the fold widens a column typed from one row's value to cover every row's, so the builder casts each value + // to the schema this method just derived + return (new RowsBuilder($schema, $backend)) + ->appendRows($batch) + ->finish(); } } diff --git a/src/core/etl/src/Flow/ETL/Row/NativeRowHydrator.php b/src/core/etl/src/Flow/ETL/Row/NativeRowHydrator.php deleted file mode 100644 index e4dca59f8d..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/NativeRowHydrator.php +++ /dev/null @@ -1,46 +0,0 @@ -native = new RustRowHydratorNative(); - } - - public static function isSupported(): bool - { - return ( - extension_loaded('flow_php') - && class_exists(RustRowHydratorNative::class, false) - && method_exists(RustRowHydratorNative::class, 'datetimeZones') - ); - } - - public function dehydrate(Rows $rows): array - { - return $this->native->dehydrate($rows); - } - - public function hydrate(array $batch, Schema $schema): Rows - { - return $this->native->hydrate($batch, $schema); - } -} diff --git a/src/core/etl/src/Flow/ETL/Row/PhpRowHydrator.php b/src/core/etl/src/Flow/ETL/Row/PhpRowHydrator.php index 013fd25707..664868c543 100644 --- a/src/core/etl/src/Flow/ETL/Row/PhpRowHydrator.php +++ b/src/core/etl/src/Flow/ETL/Row/PhpRowHydrator.php @@ -4,32 +4,46 @@ namespace Flow\ETL\Row; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; -final class PhpRowHydrator implements Hydrator +use function array_map; + +final readonly class PhpRowHydrator implements Hydrator { + public function __construct( + private Backend $backend = new DefaultBackend(), + ) {} + public function dehydrate(Rows $rows): array { - $batch = []; + $values = []; + $types = []; + $metadata = []; - foreach ($rows as $row) { - $values = []; - $types = []; - $metadata = []; + foreach ($rows->schema()->definitions() as $definition) { + $name = $definition->entry()->name(); + $values[$name] = $rows->column($name)->values(); + $types[$name] = $definition->type(); - foreach ($rows->schema()->definitions() as $definition) { - $name = $definition->entry()->name(); + if (!$definition->metadata()->isEmpty()) { + $metadata[$name] = $definition->metadata(); + } + } - $values[$name] = $row->get($name); - $types[$name] = $definition->type(); + $batch = []; - if (!$definition->metadata()->isEmpty()) { - $metadata[$name] = $definition->metadata(); - } + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $row = []; + + foreach ($values as $name => $column) { + $row[$name] = $column[$i]; } - $batch[] = new TypedRowValues($values, $types, $metadata); + $batch[] = new TypedRowValues($row, $types, $metadata); } return $batch; @@ -37,6 +51,21 @@ public function dehydrate(Rows $rows): array public function hydrate(array $batch, Schema $schema): Rows { - return (new HydratedBatch())->of($batch, $schema); + // metadata belongs to the column, so it is folded into the schema once - a per-row divergent Metadata is + // no longer representable + foreach ($batch as $rowValues) { + foreach ($rowValues->metadata as $name => $metadata) { + // PHP casts a numeric array key to int, column names are always strings + $name = (string) $name; + + if ($schema->findDefinition($name) !== null) { + $schema = $schema->setMetadata($name, $metadata); + } + } + } + + return (new RowsBuilder($schema, $this->backend)) + ->appendRows(array_map(static fn(RawRowValues $row): array => $row->values, $batch)) + ->finish(); } } diff --git a/src/core/etl/src/Flow/ETL/Row/RowRenaming.php b/src/core/etl/src/Flow/ETL/Row/RowRenaming.php deleted file mode 100644 index 466a10d80e..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/RowRenaming.php +++ /dev/null @@ -1,41 +0,0 @@ - $renames current_name => new_name - */ - private function __construct( - private array $renames, - ) {} - - /** - * @param array $renames current_name => new_name - */ - public static function of(array $renames): self - { - return new self($renames); - } - - public function apply(Row $row): Row - { - if ($this->renames === []) { - return $row; - } - - $values = []; - - // @mago-ignore analysis:mixed-assignment - foreach ($row->values() as $name => $value) { - $values[$this->renames[$name] ?? $name] = $value; - } - - return new Row($values); - } -} diff --git a/src/core/etl/src/Flow/ETL/Row/RowsBuffer.php b/src/core/etl/src/Flow/ETL/Row/RowsBuffer.php index 1e3bdef4f5..f9487800de 100644 --- a/src/core/etl/src/Flow/ETL/Row/RowsBuffer.php +++ b/src/core/etl/src/Flow/ETL/Row/RowsBuffer.php @@ -29,9 +29,7 @@ final class RowsBuffer /** * @param int<1, max> $size - * @param null|Closure(Schema, list): Rows $batch builds each released batch - Rows::trusted(...) or - * Rows::conformed(...) for rows that already passed the gate; - * null checks every row through new Rows() + * @param null|Closure(Schema, list): Rows $batch builds each released batch; null uses Rows::of() */ public function __construct( private readonly Schema $schema, @@ -49,7 +47,7 @@ public function __construct( /** * @param list $rows */ - static fn(Schema $schema, array $rows): Rows => new Rows($schema, ...$rows); + static fn(Schema $schema, array $rows): Rows => Rows::of($schema, ...$rows); } public function add(Row $row): ?Rows diff --git a/src/core/etl/src/Flow/ETL/Rows.php b/src/core/etl/src/Flow/ETL/Rows.php index 3b735c54fc..1709588b33 100644 --- a/src/core/etl/src/Flow/ETL/Rows.php +++ b/src/core/etl/src/Flow/ETL/Rows.php @@ -7,6 +7,9 @@ use ArrayAccess; use ArrayIterator; use Countable; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; @@ -23,160 +26,162 @@ use Flow\ETL\Row\Comparator\NativeComparator; use Flow\ETL\Row\Reference; use Flow\ETL\Row\SortOrder; -use Flow\ETL\Schema\Definition; -use Flow\ETL\Serializer\DomValueCodec; +use Flow\ETL\Rows\RowsBuilder; +use Flow\ETL\Schema\Formatter\InlineSchemaFormatter; +use Flow\ETL\Schema\SimilarNames; use Flow\ETL\Sort\ValuesSorter; use Flow\Types\Exception\InvalidTypeException; use Generator; use Iterator; use IteratorAggregate; +use function array_diff_key; use function array_key_exists; +use function array_keys; use function array_map; use function array_reverse; -use function array_slice; +use function array_shift; use function array_values; use function count; use function Flow\Types\DSL\type_integer; use function implode; use function is_int; -use function iterator_to_array; +use function min; use function sprintf; /** + * @type RowsPayload = array{ + * schema: Schema, + * count: int, + * columns: array, nullCount: int}> + * } + * * @implements \ArrayAccess * @implements \IteratorAggregate */ final class Rows implements ArrayAccess, Countable, IteratorAggregate { /** - * @var array + * @param array $columns keyed and ordered by $schema */ - private array $rows; + private function __construct( + private Schema $schema, + private array $columns, + private int $count, + ) {} /** - * @throws SchemaMismatchException + * @return RowsPayload */ - public function __construct( - private Schema $schema, - Row ...$rows, - ) { - $this->rows = []; + public function __serialize(): array + { + $columns = []; - foreach ($rows as $row) { - try { - $this->rows[] = $row->matchTo($schema); - } catch (ColumnMismatchException $e) { - throw new SchemaMismatchException(count($this->rows), $e); - } + foreach ($this->columns as $name => $column) { + $columns[$name] = ['buffers' => $column->encode(), 'nullCount' => $column->nullCount()]; } + + return ['schema' => $this->schema, 'count' => $this->count, 'columns' => $columns]; } /** - * Skips the shape check the constructor performs. The caller vouches that every row already - * satisfies $schema and stores its columns in the Schema's order - which holds when the same - * operation produced the schema and the rows, or when the rows are a subset or a permutation of - * a batch that already passed. - * - * Engine paths only. - * - * @param array $rows re-indexed here - first(), last(), chunks() and offsetGet() read by position + * @param RowsPayload $data */ - public static function trusted(Schema $schema, array $rows): self + public function __unserialize(array $data): void { - $instance = new self($schema); - $instance->rows = array_values($rows); + if (array_keys($data['columns']) !== array_keys($data['schema']->definitions())) { + throw new InvalidArgumentException(sprintf( + 'Rows::fromColumns() expects columns [%s], got [%s]', + implode(', ', array_keys($data['schema']->definitions())), + implode(', ', array_keys($data['columns'])), + )); + } + + $backend = new PhpBackend(); + $columns = []; + + foreach ($data['schema']->definitions() as $name => $definition) { + $column = $data['columns'][$name]; + $columns[$name] = $backend->decode($definition, $column['buffers'], $data['count'], $column['nullCount']); + } - return $instance; + $rows = self::fromColumns($data['schema'], $columns, $data['count']); + + $this->schema = $rows->schema; + $this->columns = $rows->columns; + $this->count = $rows->count; } /** - * The constructor's shape check without its value check. Columns take the Schema's order, a declared-nullable - * absence is padded, and a missing NOT NULL column, an unknown column or a null under NOT NULL is refused - but a - * 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. - * - * Engine paths only. - * - * @param array $rows - * * @throws SchemaMismatchException */ - public static function conformed(Schema $schema, array $rows): self + public static function of(Schema $schema, Row ...$rows): self { - $instance = new self($schema); + if ($rows === []) { + $backend = new PhpBackend(); + $columns = []; - foreach ($rows as $row) { - try { - $instance->rows[] = $row->conformTo($schema); - } catch (ColumnMismatchException $e) { - throw new SchemaMismatchException(count($instance->rows), $e); + foreach ($schema->definitions() as $name => $definition) { + $columns[$name] = $backend->builder($definition)->finish(); } + + return new self($schema, $columns, 0); } - return $instance; - } + $rows = array_values($rows); + $batch = $rows[0]->rows; + $single = true; - /** - * @return array{schema: Schema, rows: list>} - */ - public function __serialize(): array - { - $codec = new DomValueCodec(); - $domColumns = []; + foreach ($rows as $row) { + if ($row->rows !== $batch) { + $single = false; - foreach ($this->schema->definitions() as $definition) { - if ($codec->handles($definition->type())) { - $domColumns[$definition->entry()->name()] = $definition->type(); + break; } } - $rows = []; + if ($single && $batch->schema->isSame($schema)) { + $gathered = $batch->gather(array_map(static fn(Row $row): int => $row->index, $rows)); - foreach ($this->rows as $row) { - $values = $row->values(); + return new self($schema, $gathered->columns, $gathered->count); + } - foreach ($domColumns as $name => $type) { - if (array_key_exists($name, $values)) { - $values[$name] = $codec->encode($type, $values[$name]); - } - } + $builder = new RowsBuilder($schema, new PhpBackend()); - $rows[] = $values; + foreach ($rows as $row) { + $builder->appendFrom($row->rows, $row->index); } - return ['schema' => $this->schema, 'rows' => $rows]; + return $builder->finish(); } /** - * @param array{schema: Schema, rows: list>} $data + * @param array $columns keyed and ordered by $schema, every one of $count rows + * + * @throws InvalidArgumentException */ - public function __unserialize(array $data): void + public static function fromColumns(Schema $schema, array $columns, int $count): self { - $this->schema = $data['schema']; - - $codec = new DomValueCodec(); - $domColumns = []; - - foreach ($this->schema->definitions() as $definition) { - if ($codec->handles($definition->type())) { - $domColumns[$definition->entry()->name()] = $definition->type(); - } + if (array_keys($columns) !== array_keys($schema->definitions())) { + throw new InvalidArgumentException(sprintf( + 'Rows::fromColumns() expects columns [%s], got [%s]', + implode(', ', array_keys($schema->definitions())), + implode(', ', array_keys($columns)), + )); } - $rows = []; - - foreach ($data['rows'] as $values) { - foreach ($domColumns as $name => $type) { - if (array_key_exists($name, $values)) { - $values[$name] = $codec->decode($type, $values[$name]); - } + foreach ($columns as $name => $column) { + if ($column->count() !== $count) { + throw new InvalidArgumentException(sprintf( + 'Column "%s" holds %d rows, the batch %d', + $name, + $column->count(), + $count, + )); } - - $rows[] = new Row($values); } - $this->rows = (new self($this->schema, ...$rows))->rows; + return new self($schema, $columns, $count); } /** @@ -184,64 +189,147 @@ public function __unserialize(array $data): void */ public function add(Row ...$rows): self { - $matched = $this->rows; - - foreach ($rows as $row) { - try { - $matched[] = $row->matchTo($this->schema); - } catch (ColumnMismatchException $e) { - throw new SchemaMismatchException(count($matched), $e); - } + try { + $added = self::of($this->schema, ...$rows); + } catch (SchemaMismatchException $e) { + throw new SchemaMismatchException($e->rowIndex + $this->count, $e->cause); } - return self::trusted($this->schema, $matched); + return $this->concat($added); } /** - * @return array + * @return list */ public function all(): array { - return $this->rows; + $rows = []; + + for ($i = 0; $i < $this->count; $i++) { + $rows[] = new Row($this, $i); + } + + return $rows; } /** * @param int<1, max> $size * - * @return \Generator + * @return \Generator */ public function chunks(int $size): Generator { - foreach (array_chunk($this->rows, $size) as $chunk) { - yield self::trusted($this->schema, $chunk); + for ($offset = 0; $offset < $this->count; $offset += $size) { + yield $this->slice($offset, min($size, $this->count - $offset)); } } /** - * Re-checks the batch against a different Schema and adopts it - the door the constructor opens, - * for rows already gathered into a batch. - * - * @throws SchemaMismatchException + * @throws InvalidArgumentException */ - public function matchTo(Schema $schema): self + public function column(string $name): Column { - return new self($schema, ...$this->rows); + if (array_key_exists($name, $this->columns)) { + return $this->columns[$name]; + } + + $suggestions = (new SimilarNames())->closestTo($name, array_values($this->schema->references()->names())); + + throw new InvalidArgumentException( + $suggestions === [] + ? "Column \"{$name}\" does not exist." + : "Column \"{$name}\" does not exist. Did you mean one of the following? [\"" + . implode('", "', $suggestions) + . '"]', + ); + } + + /** + * @return array schema order + */ + public function columns(): array + { + return $this->columns; + } + + /** + * Every input carries this schema; zero-row inputs add no rows. + * + * @throws InvalidArgumentException + */ + public function concat(self ...$others): self + { + $inputs = $this->count > 0 ? [$this] : []; + $count = $this->count; + + foreach ($others as $other) { + if (!$other->schema->isSame($this->schema)) { + throw InvalidArgumentException::because( + 'Cannot merge Rows with different schemas: [%s] and [%s]', + (new InlineSchemaFormatter())->format($this->schema), + (new InlineSchemaFormatter())->format($other->schema), + ); + } + + if ($other->count > 0) { + $inputs[] = $other; + $count += $other->count; + } + } + + $head = array_shift($inputs); + + if ($head === null) { + return self::of($this->schema); + } + + $backend = new PhpBackend(); + $columns = []; + + foreach ($this->schema->definitions() as $name => $definition) { + $first = $head->columns[$name]; + $rest = []; + $sameClass = true; + + foreach ($inputs as $input) { + $part = $input->columns[$name]; + $rest[] = $part; + $sameClass = $sameClass && $part::class === $first::class; + } + + if ($sameClass) { + $columns[$name] = $first->concat(...$rest); + + continue; + } + + $builder = $backend->builder($definition); + + foreach ([$first, ...$rest] as $part) { + $builder->appendTake($part, range(0, $part->count() - 1)); + } + + $columns[$name] = $builder->finish(); + } + + return new self($this->schema, $columns, $count); } public function count(): int { - return count($this->rows); + return $this->count; } public function diffLeft(self $rows): self { $comparator = new NativeComparator(); - $differentRows = []; + $others = $rows->all(); + $kept = []; - foreach ($this->rows as $row) { + foreach ($this->all() as $row) { $found = false; - foreach ($rows->rows as $otherRow) { + foreach ($others as $otherRow) { if ($comparator->equals($row, $otherRow, $this->schema)) { $found = true; @@ -250,22 +338,23 @@ public function diffLeft(self $rows): self } if (!$found) { - $differentRows[] = $row; + $kept[] = $row->index; } } - return self::trusted($this->schema, $differentRows); + return $this->gather($kept); } public function diffRight(self $rows): self { $comparator = new NativeComparator(); - $differentRows = []; + $own = $this->all(); + $kept = []; - foreach ($rows->rows as $row) { + foreach ($rows->all() as $row) { $found = false; - foreach ($this->rows as $otherRow) { + foreach ($own as $otherRow) { if ($comparator->equals($row, $otherRow, $this->schema)) { $found = true; @@ -274,40 +363,73 @@ public function diffRight(self $rows): self } if (!$found) { - $differentRows[] = $row; + $kept[] = $row->index; } } // the surviving rows come from the right side, so the right side's schema describes them - return self::trusted($rows->schema, $differentRows); + return $rows->gather($kept); } public function drop(int $size): self { + if ($size < 0) { + throw new InvalidArgumentException('Size must be greater than or equal to 0'); + } + if ($size === 0) { return $this; } - return self::trusted($this->schema, array_slice($this->rows, $size)); + return $this->slice(min($size, $this->count), $this->count - min($size, $this->count)); } public function dropRight(int $size): self { + if ($size < 0) { + throw new InvalidArgumentException('Size must be greater than or equal to 0'); + } + if ($size === 0) { return $this; } - return self::trusted($this->schema, array_slice($this->rows, 0, -$size)); + return $this->slice(0, $this->count - min($size, $this->count)); } - public function empty(): bool + public function first(): Row { - return $this->count() === 0; + if ($this->count === 0) { + throw new RuntimeException('First row does not exist in empty collection'); + } + + return new Row($this, 0); } - public function first(): Row - { - return $this->rows[0] ?? throw new RuntimeException('First row does not exist in empty collection'); + /** + * @param list $indices rows to keep, in the order given + * + * @throws InvalidArgumentException + */ + public function gather(array $indices): self + { + foreach ($indices as $index) { + if ($index < 0 || $index >= $this->count) { + throw new InvalidArgumentException(sprintf( + 'Rows::gather() index %d is outside a batch of %d rows', + $index, + $this->count, + )); + } + } + + $columns = []; + + foreach ($this->columns as $name => $column) { + $columns[$name] = $column->take($indices); + } + + return new self($this->schema, $columns, count($indices)); } /** @@ -315,15 +437,15 @@ public function first(): Row */ public function getIterator(): Iterator { - return new ArrayIterator($this->rows); + return new ArrayIterator($this->all()); } public function hash(Algorithm $algorithm = new NativePHPHash()): string { $hash = ''; - foreach ($this->rows as $row) { - $hash .= $row->hash($this->schema, $algorithm); + for ($i = 0; $i < $this->count; $i++) { + $hash .= (new Row($this, $i))->hash($this->schema, $algorithm); } return $algorithm->hash($hash); @@ -342,35 +464,30 @@ public function head(int $count): self throw new InvalidArgumentException('Count must be greater than or equal to 0'); } - if ($count === 0) { - return self::trusted($this->schema, []); - } + return $this->slice(0, min($count, $this->count)); + } - return self::trusted($this->schema, array_slice($this->rows, 0, $count)); + public function isEmpty(): bool + { + return $this->count === 0; } public function joinCross(self $right, string $joinPrefix = 'joined_'): self { $schema = (new JoinSchema($joinPrefix))->cross($this->schema, $right->schema); - - /** - * @var array $joined - */ - $joined = []; - $merger = new RowMerger($joinPrefix); + $rightRows = $right->all(); + $joined = []; - foreach ($this->rows as $leftRow) { - foreach ($right->rows as $rightRow) { - try { - $joined[] = $merger->merge($leftRow, $rightRow); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException($e->getMessage() . '. Please consider using join prefix option'); - } + foreach ($this->all() as $leftRow) { + foreach ($rightRows as $rightRow) { + $joined[] = $merger->merge($leftRow, $rightRow); } } - return new self($schema, ...$joined); + return (new RowsBuilder($schema, new DefaultBackend())) + ->appendRows($joined) + ->finish(); } /** @@ -405,70 +522,117 @@ public function joinRight(self $right, Expression $expression): self return $this->joinUsing($right, $expression, Join::right); } + public function last(): ?Row + { + return $this->count === 0 ? null : new Row($this, $this->count - 1); + } + /** - * @throws InvalidArgumentException + * Adopts $schema, checking every column whose definition it changes (Definition::matches per value). + * + * @throws SchemaMismatchException */ - private function joinUsing(self $right, Expression $expression, Join $type): self + public function matchTo(Schema $schema): self { - $single = static function (self $rows): Generator { - yield $rows; - }; + if ($schema->isSame($this->schema)) { + return new self($schema, $this->columns, $this->count); + } - $joiner = new Joiner($expression, $type); + foreach ($this->schema->definitions() as $definition) { + $name = $definition->entry()->name(); - /** - * @var array $joined - */ - $joined = []; + if ($this->count > 0 && $schema->findDefinition($name) === null) { + throw new SchemaMismatchException(0, ColumnMismatchException::unexpectedColumn($name)); + } + } - foreach ($joiner->join(JoinSide::of($single($this)), JoinSide::of($single($right))) as $batch) { - foreach ($batch as $row) { - $joined[] = $row; + $backend = new PhpBackend(); + $columns = []; + $changed = []; + + foreach ($schema->definitions() as $name => $definition) { + $own = $this->schema->findDefinition($definition->entry()->name()); + + if ($own === null) { + if (!$definition->isNullable()) { + if ($this->count > 0) { + throw new SchemaMismatchException(0, ColumnMismatchException::missingColumn($definition)); + } + + $columns[$name] = $backend->builder($definition)->finish(); + + continue; + } + + $columns[$name] = $backend->constant($definition, null, $this->count); + + continue; + } + + if ($own->isSame($definition)) { + $columns[$name] = $this->columns[$name]; + + continue; } + + $changed[$name] = $definition; } - return new self($joiner->schema($this->schema, $right->schema), ...$joined); - } + for ($i = 0; $i < $this->count; $i++) { + foreach ($changed as $name => $definition) { + // @mago-ignore analysis:mixed-assignment + $value = $this->columns[$name]->value($i); - public function last(): ?Row - { - if (empty($this->rows)) { - return null; + if ($value === null ? !$definition->isNullable() : !$definition->matches($value)) { + throw new SchemaMismatchException($i, ColumnMismatchException::valueDoesNotMatch( + $definition, + $value, + )); + } + } + } + + foreach ($changed as $name => $definition) { + try { + $columns[$name] = $this->columns[$name]->withType($definition->type()); + } catch (InvalidArgumentException) { + $builder = $backend->builder($definition); + $builder->appendMany($this->columns[$name]->values()); + $columns[$name] = $builder->finish(); + } } - return $this->rows[count($this->rows) - 1]; + $ordered = []; + + foreach ($schema->definitions() as $name => $_) { + $ordered[$name] = $columns[$name]; + } + + return self::fromColumns($schema, $ordered, $this->count); } + /** + * @throws InvalidArgumentException + */ public function merge(self $rows): self { - if ($this->empty()) { + if ($this->isEmpty()) { return $rows; } - if ($rows->empty()) { + if ($rows->isEmpty()) { return $this; } if (!$this->schema->isSame($rows->schema())) { - // names alone cannot show a type-only disagreement - both sides would print identically - $describe = static fn(Schema $schema): string => implode(', ', array_map( - static fn(Definition $definition): string => ( - $definition->entry()->name() - . ': ' - . ($definition->isNullable() ? '?' : '') - . $definition->type()->toString() - ), - $schema->definitions(), - )); - - throw new InvalidArgumentException(sprintf( + throw InvalidArgumentException::because( 'Cannot merge Rows with different schemas: [%s] and [%s]', - $describe($this->schema), - $describe($rows->schema()), - )); + (new InlineSchemaFormatter())->format($this->schema), + (new InlineSchemaFormatter())->format($rows->schema), + ); } - return self::trusted($this->schema, [...$this->rows, ...$rows->rows]); + return $this->concat($rows); } /** @@ -483,7 +647,7 @@ public function offsetExists($offset): bool throw new InvalidArgumentException('Rows accepts only integer offsets'); } - return isset($this->rows[$offset]); + return $offset >= 0 && $offset < $this->count; } /** @@ -494,7 +658,7 @@ public function offsetExists($offset): bool public function offsetGet($offset): Row { if ($this->offsetExists($offset)) { - return $this->rows[$offset]; + return new Row($this, $offset); } throw new InvalidArgumentException("Row {$offset} does not exists."); @@ -515,17 +679,6 @@ public function offsetUnset(mixed $offset): void throw new RuntimeException('In order to remove rows use Rows::remove(int $offset) : self'); } - /** - * @param Reference|string $reference - * @param Reference|string ...$references - * - * @throws InvalidArgumentException - * - * @return array - */ - /** - * @return array - */ /** * Drops the columns $schema does not declare and adopts it. Widening or retyping the batch is * not a projection - that goes through matchTo(). @@ -534,33 +687,33 @@ public function offsetUnset(mixed $offset): void */ public function project(Schema $schema): self { - $projected = []; - - foreach ($this->rows as $row) { - $projected[] = $row->project($schema); - } + $definitions = []; + $columns = []; foreach ($schema->definitions() as $name => $definition) { - $own = $this->schema->findDefinition($name); + $own = $this->schema->findDefinition($definition->entry()->name()); - if ($own === null || !$own->isSame($definition)) { - return new self($schema, ...$projected); + if ($own !== null) { + $definitions[] = $own; + $columns[$name] = $this->columns[$name]; } } - // every kept column kept its definition, so each value already passed the gate under it - return self::trusted($schema, $projected); + return (new self(new Schema(...$definitions), $columns, $this->count))->matchTo($schema); } + /** + * @throws InvalidArgumentException + * + * @return list + */ public function reduceToArray(string|Reference $reference): array { - $ids = []; - - foreach ($this->rows as $row) { - $ids[] = $row->get($reference); + if ($this->count === 0) { + return []; } - return $ids; + return $this->column($reference instanceof Reference ? $reference->base() : $reference)->values(); } public function remove(int $offset): self @@ -569,15 +722,23 @@ public function remove(int $offset): self throw new InvalidArgumentException("Rows does not have {$offset} offset"); } - $rows = iterator_to_array($this->getIterator()); - unset($rows[$offset]); - - return self::trusted($this->schema, array_values($rows)); + return $this->gather(array_values(array_diff_key(range(0, $this->count - 1), [$offset => true]))); } public function reverse(): self { - return self::trusted($this->schema, array_reverse($this->rows)); + $indices = []; + + for ($i = $this->count - 1; $i >= 0; $i--) { + $indices[] = $i; + } + + return $this->gather($indices); + } + + public function row(int $i): Row + { + return new Row($this, $i); } public function schema(): Schema @@ -588,21 +749,42 @@ public function schema(): Schema /** * @throws InvalidArgumentException */ - public function sortAscending(string|Reference $reference): self + public function slice(int $offset, int $length): self { - $values = []; + if ($offset < 0 || $length < 0 || ($offset + $length) > $this->count) { + throw new InvalidArgumentException(sprintf( + 'Rows::slice(%d, %d) is outside a batch of %d rows', + $offset, + $length, + $this->count, + )); + } - foreach ($this->rows as $index => $row) { - $values[$index] = $row->get($reference); + $columns = []; + + foreach ($this->columns as $name => $column) { + $columns[$name] = $column->slice($offset, $length); } - $rows = []; + return new self($this->schema, $columns, $length); + } - foreach (array_keys(ValuesSorter::sort($values, SortOrder::ASC)) as $index) { - $rows[] = $this->rows[$index]; + /** + * @throws InvalidArgumentException + */ + public function sortAscending(string|Reference $reference): self + { + if ($this->count === 0) { + return $this; } - return self::trusted($this->schema, $rows); + /** @var list $order */ + $order = array_keys(ValuesSorter::sort( + $this->column($reference instanceof Reference ? $reference->base() : $reference)->values(), + SortOrder::ASC, + )); + + return $this->gather($order); } /** @@ -624,19 +806,17 @@ public function sortBy(Reference ...$references): self */ public function sortDescending(string|Reference $reference): self { - $values = []; - - foreach ($this->rows as $index => $row) { - $values[$index] = $row->get($reference); + if ($this->count === 0) { + return $this; } - $rows = []; - - foreach (array_keys(ValuesSorter::sort($values, SortOrder::DESC)) as $index) { - $rows[] = $this->rows[$index]; - } + /** @var list $order */ + $order = array_keys(ValuesSorter::sort( + $this->column($reference instanceof Reference ? $reference->base() : $reference)->values(), + SortOrder::DESC, + )); - return self::trusted($this->schema, $rows); + return $this->gather($order); } /** @@ -652,27 +832,29 @@ public function tail(int $count): self throw new InvalidArgumentException('Count must be greater than or equal to 0'); } - if ($count === 0) { - return self::trusted($this->schema, []); - } - - $rowsCount = count($this->rows); - - if ($count >= $rowsCount) { - return self::trusted($this->schema, $this->rows); + if ($count >= $this->count) { + return $this; } - return self::trusted($this->schema, array_slice($this->rows, -$count)); + return $this->slice($this->count - $count, $count); } public function take(int $size): self { - return self::trusted($this->schema, array_slice($this->rows, 0, $size)); + if ($size < 0) { + throw new InvalidArgumentException('Size must be greater than or equal to 0'); + } + + return $this->slice(0, min($size, $this->count)); } public function takeRight(int $size): self { - return self::trusted($this->schema, array_reverse(array_slice($this->rows, -$size, $size))); + if ($size < 0) { + throw new InvalidArgumentException('Size must be greater than or equal to 0'); + } + + return $this->slice($this->count - min($size, $this->count), min($size, $this->count))->reverse(); } /** @@ -682,8 +864,8 @@ public function toArray(bool $withKeys = true): array { $array = []; - foreach ($this->rows as $row) { - $array[] = $row->toArray($withKeys); + for ($i = 0; $i < $this->count; $i++) { + $array[] = (new Row($this, $i))->toArray($withKeys); } return $array; @@ -691,27 +873,121 @@ public function toArray(bool $withKeys = true): array public function unique(Comparator $comparator = new NativeComparator()): self { - /** - * @var array $uniqueRows - */ - $uniqueRows = []; + $unique = []; - foreach ($this->rows as $row) { - $alreadyAdded = false; - - foreach ($uniqueRows as $uniqueRow) { + foreach ($this->all() as $row) { + foreach ($unique as $uniqueRow) { if ($comparator->equals($row, $uniqueRow, $this->schema)) { - $alreadyAdded = true; - - break; + continue 2; } } - if (!$alreadyAdded) { - $uniqueRows[] = $row; + $unique[] = $row; + } + + return $this->gather(array_map(static fn(Row $row): int => $row->index, $unique)); + } + + /** + * @return array the logical row, schema order + */ + public function values(int $i): array + { + $values = []; + + foreach ($this->columns as $name => $column) { + $values[$name] = $column->value($i); + } + + return $values; + } + + /** + * @param array $columns each of count() rows; a same-named column is replaced in place + * + * @throws InvalidArgumentException + */ + public function withColumns(Schema $schema, array $columns): self + { + foreach ($columns as $name => $column) { + if ($column->count() !== $this->count) { + throw new InvalidArgumentException(sprintf( + 'Column "%s" holds %d rows, the batch %d', + $name, + $column->count(), + $this->count, + )); + } + } + + $merged = []; + + foreach ($schema->definitions() as $name => $_) { + if (array_key_exists($name, $columns)) { + $merged[$name] = $columns[$name]; + } elseif (array_key_exists($name, $this->columns)) { + $merged[$name] = $this->columns[$name]; + } + } + + return self::fromColumns($schema, $merged, $this->count); + } + + /** + * Positional restamp: the n-th definition of $schema retypes the n-th column (Column::withType). + * + * @throws ColumnMismatchException + * @throws InvalidArgumentException + */ + public function withSchema(Schema $schema): self + { + if ($schema->count() !== $this->schema->count()) { + throw new InvalidArgumentException(sprintf( + 'Rows::withSchema() expects %d definitions, got %d', + $this->schema->count(), + $schema->count(), + )); + } + + $columns = array_values($this->columns); + $retyped = []; + $position = 0; + + foreach ($schema->definitions() as $name => $definition) { + $column = $columns[$position++]; + + if (!$definition->isNullable() && $column->nullCount() > 0) { + throw ColumnMismatchException::valueDoesNotMatch($definition, null); + } + + try { + $retyped[$name] = $column->withType($definition->type()); + } catch (InvalidArgumentException $e) { + throw ColumnMismatchException::retype($definition, $e->getMessage()); + } + } + + return new self($schema, $retyped, $this->count); + } + + /** + * @throws InvalidArgumentException + */ + private function joinUsing(self $right, Expression $expression, Join $type): self + { + $single = static function (self $rows): Generator { + yield $rows; + }; + + $joiner = new Joiner($expression, $type); + $joined = []; + + foreach ($joiner->join(JoinSide::of($single($this)), JoinSide::of($single($right))) as $batch) { + foreach ($batch->all() as $row) { + $joined[] = $row; } } - return self::trusted($this->schema, array_values($uniqueRows)); + return self::of($joiner->schema($this->schema, $right->schema), ...$joined); } } diff --git a/src/core/etl/src/Flow/ETL/Rows/RowsBuilder.php b/src/core/etl/src/Flow/ETL/Rows/RowsBuilder.php new file mode 100644 index 0000000000..6ddd31c120 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Rows/RowsBuilder.php @@ -0,0 +1,329 @@ + + */ + private array $builders = []; + + private int $count = 0; + + /** + * @var list + */ + private array $names = []; + + /** + * @var list> + */ + private array $definitions = []; + + private ?Rows $source = null; + + /** + * @var list per target position: the source column of the same name, null when the source lacks it + */ + private array $columns = []; + + /** + * @var list per target position: the source column shares the target definition + */ + private array $shared = []; + + /** + * @var array per target position, filled only when every target column is copied from the source + */ + private array $copies = []; + + private ?string $unexpected = null; + + public function __construct( + private readonly Schema $schema, + Backend $backend, + ) { + foreach ($schema->definitions() as $name => $definition) { + $this->builders[$name] = $backend->builder($definition); + $this->names[] = $definition->entry()->name(); + $this->definitions[] = $definition; + } + } + + /** + * @param array $row name-keyed; a key the schema lacks is ignored + * + * @throws SchemaMismatchException + */ + public function append(array $row): self + { + return $this->appendRows([$row]); + } + + /** + * A column sharing its definition with the target is copied physically; any other is refused unless its value + * matches the target definition as it is - views are never cast. + * + * @throws SchemaMismatchException + */ + public function appendFrom(Rows $rows, int $i): self + { + if ($rows !== $this->source) { + $sources = $rows->schema()->definitions(); + $present = 0; + $copies = []; + $this->unexpected = null; + + foreach ($this->names as $position => $name) { + if (!array_key_exists($name, $sources)) { + $this->columns[$position] = null; + $this->shared[$position] = false; + + continue; + } + + $present++; + $column = $rows->column($name); + $this->columns[$position] = $column; + $this->shared[$position] = $sources[$name]->isSame($this->definitions[$position]); + + if ($this->shared[$position]) { + $copies[$position] = $column; + } + } + + if (count($sources) > $present) { + foreach ($sources as $definition) { + if (!array_key_exists($definition->entry()->name(), $this->builders)) { + $this->unexpected = $definition->entry()->name(); + + break; + } + } + } + + $this->copies = $this->unexpected === null && count($copies) === count($this->names) ? $copies : []; + $this->source = $rows; + } + + if ($this->copies !== []) { + foreach ($this->copies as $position => $column) { + $this->builders[$this->names[$position]]->appendFrom($column, $i); + } + + $this->count++; + + return $this; + } + + $values = []; + + foreach ($this->definitions as $position => $definition) { + $column = $this->columns[$position]; + + if ($column === null) { + if (!$definition->isNullable()) { + throw new SchemaMismatchException( + $this->count, + ColumnMismatchException::missingColumn($definition), + ); + } + + $values[$position] = null; + + continue; + } + + if ($this->shared[$position]) { + continue; + } + + // @mago-ignore analysis:mixed-assignment + $value = $column->value($i); + + if ($value === null ? !$definition->isNullable() : !$definition->matches($value)) { + throw new SchemaMismatchException( + $this->count, + ColumnMismatchException::valueDoesNotMatch($definition, $value), + ); + } + + $values[$position] = $value; + } + + if ($this->unexpected !== null) { + throw new SchemaMismatchException( + $this->count, + ColumnMismatchException::unexpectedColumn($this->unexpected), + ); + } + + foreach ($this->names as $position => $name) { + $column = $this->columns[$position]; + + if ($column === null || !$this->shared[$position]) { + $this->builders[$name]->append($values[$position] ?? null); + + continue; + } + + $this->builders[$name]->appendFrom($column, $i); + } + + $this->count++; + + return $this; + } + + /** + * @param list> $rows name-keyed; a declared key a row lacks is null, or a missing column + * under NOT NULL; a key the schema lacks is ignored + * + * @throws SchemaMismatchException + */ + public function appendRows(array $rows): self + { + if ($rows === []) { + return $this; + } + + $refusal = null; + $absence = null; + + foreach ($this->definitions as $position => $definition) { + $name = $this->names[$position]; + $values = []; + $absent = null; + + foreach ($rows as $index => $row) { + if (array_key_exists($name, $row)) { + $values[] = $row[$name]; + + continue; + } + + if (!$definition->isNullable()) { + $absent ??= $index; + } + + $values[] = null; + } + + // an absence under NOT NULL is refused below; the values the rows do carry are still checked, because a + // refused value wins over an absence + $present = null; + + if ($absent !== null) { + if ($absence === null || ($this->count + $absent) < $absence->rowIndex) { + $absence = new SchemaMismatchException( + $this->count + $absent, + ColumnMismatchException::missingColumn($definition), + ); + } + + $present = array_keys(array_filter($rows, static fn(array $row): bool => array_key_exists( + $name, + $row, + ))); + $values = array_map(static fn(int $index): mixed => $rows[$index][$name], $present); + } + + try { + $this->builders[$name]->appendMany($values); + } catch (SchemaMismatchException $e) { + $row = $this->count + ($present === null ? $e->rowIndex : $present[$e->rowIndex]); + + if ($refusal === null || $row < $refusal->rowIndex) { + $refusal = new SchemaMismatchException($row, $e->cause); + } + } + } + + if ($refusal !== null) { + throw $refusal; + } + + if ($absence !== null) { + throw $absence; + } + + $this->count += count($rows); + + return $this; + } + + /** + * @param list $indices + */ + public function appendTake(Rows $rows, array $indices): self + { + foreach ($this->schema->definitions() as $definition) { + $name = $definition->entry()->name(); + $this->builders[$name]->appendTake($rows->column($name), $indices); + } + + $this->count += count($indices); + + return $this; + } + + public function column(string $name): ColumnBuilder + { + return ( + $this->builders[$name] ?? throw new InvalidArgumentException(sprintf( + 'RowsBuilder has no column "%s"', + $name, + )) + ); + } + + public function count(): int + { + foreach ($this->builders as $builder) { + return $builder->count(); + } + + return $this->count; + } + + public function finish(): Rows + { + $columns = []; + $counts = []; + + foreach ($this->builders as $name => $builder) { + $columns[$name] = $builder->finish(); + $counts[$columns[$name]->count()][] = $name; + } + + if (count($counts) > 1) { + $ragged = []; + + foreach ($counts as $count => $names) { + $ragged[] = sprintf('%d rows in [%s]', $count, implode(', ', $names)); + } + + throw new InvalidArgumentException('Ragged columns: ' . implode(', ', $ragged)); + } + + return Rows::fromColumns($this->schema, $columns, $this->count()); + } +} diff --git a/src/core/etl/src/Flow/ETL/Schema.php b/src/core/etl/src/Flow/ETL/Schema.php index a51d95223c..78d362f9ac 100644 --- a/src/core/etl/src/Flow/ETL/Schema.php +++ b/src/core/etl/src/Flow/ETL/Schema.php @@ -12,7 +12,6 @@ use Flow\ETL\Row\References; use Flow\ETL\Row\UnresolvedReference; use Flow\ETL\Schema\Definition; -use Flow\ETL\Schema\Definition\ZoneAlignment; use Flow\ETL\Schema\Metadata; use Flow\ETL\Schema\SortingStrategy; use Flow\ETL\Schema\SortingStrategy\AlphabeticalStrategy; @@ -37,11 +36,6 @@ */ private array $definitions; - /** - * @var array> - */ - private array $zonedDefinitions; - /** * @param Definition ...$definitions */ @@ -561,14 +555,6 @@ public function sort(SortingStrategy $strategy = new AlphabeticalStrategy()): se return new self(...$definitions); } - /** - * @return array> - */ - public function zonedDefinitions(): array - { - return $this->zonedDefinitions; - } - private function indexOf(string|Reference $reference): int { $index = array_search(UnresolvedReference::init($reference)->name(), array_keys($this->definitions), true); @@ -642,6 +628,5 @@ private function setDefinitions(Definition ...$definitions): void } $this->definitions = $uniqueDefinitions; - $this->zonedDefinitions = (new ZoneAlignment())->columns($uniqueDefinitions); } } diff --git a/src/core/etl/src/Flow/ETL/Schema/Definition/ZoneAlignment.php b/src/core/etl/src/Flow/ETL/Schema/Definition/ZoneAlignment.php deleted file mode 100644 index a8ec54d639..0000000000 --- a/src/core/etl/src/Flow/ETL/Schema/Definition/ZoneAlignment.php +++ /dev/null @@ -1,79 +0,0 @@ - $definition - */ - public function align(Definition $definition, mixed $value): mixed - { - return match (true) { - $value === null => null, - $this->inZone($definition, $value) => $value, - default => $definition->type()->cast($value), - }; - } - - /** - * @param Type $type - */ - public function carriesDateTime(Type $type): bool - { - return match (true) { - $type instanceof DateTimeType => true, - $type instanceof OptionalType => $this->carriesDateTime($type->base()), - $type instanceof ListType => $this->carriesDateTime($type->element()), - $type instanceof MapType => $this->carriesDateTime($type->value()), - $type instanceof StructureType - => array_filter($type->elements(), fn(StructureElement $element): bool => $this->carriesDateTime($element->type)) - !== [], - default => false, - }; - } - - /** - * @param array> $definitions - * - * @return array> - */ - public function columns(array $definitions): array - { - $zoned = []; - - foreach ($definitions as $name => $definition) { - if ($this->carriesDateTime($definition->type())) { - $zoned[$name] = $definition; - } - } - - return $zoned; - } - - /** - * @param Definition $definition - */ - public function inZone(Definition $definition, mixed $value): bool - { - return ( - $definition instanceof DateTimeDefinition - && $value instanceof DateTimeInterface - && $value->getTimezone()->getName() === $definition->type()->zoneName() - ); - } -} diff --git a/src/core/etl/src/Flow/ETL/Schema/Formatter/InlineSchemaFormatter.php b/src/core/etl/src/Flow/ETL/Schema/Formatter/InlineSchemaFormatter.php new file mode 100644 index 0000000000..b51ea7e28c --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Schema/Formatter/InlineSchemaFormatter.php @@ -0,0 +1,24 @@ +definitions() as $name => $definition) { + $columns[] = $name . ': ' . ($definition->isNullable() ? '?' : '') . $definition->type()->toString(); + } + + return implode(', ', $columns); + } +} diff --git a/src/core/etl/src/Flow/ETL/Serializer/DomValueCodec.php b/src/core/etl/src/Flow/ETL/Serializer/DomValueCodec.php deleted file mode 100644 index 281ea1f857..0000000000 --- a/src/core/etl/src/Flow/ETL/Serializer/DomValueCodec.php +++ /dev/null @@ -1,128 +0,0 @@ - $type - */ - public function decode(Type $type, mixed $value): mixed - { - if (!$this->handles($type) || $value === null) { - return $value; - } - - $decoded = base64_decode(type_string()->assert($value), true); - - if ($decoded === false) { - throw new InvalidArgumentException('Given value is not valid base64'); - } - - $xml = @gzuncompress($decoded); - - if ($xml === false) { - throw new InvalidArgumentException('Given value is not valid gzcompressed XML'); - } - - if ($type instanceof HTMLType) { - // @mago-expect analysis:unavailable-method - return HTMLDocument::createFromString($xml, LIBXML_NOERROR); - } - - if ($type instanceof HTMLElementType) { - return ValueDecoder::htmlElementFromString($xml); - } - - $document = new DOMDocument(); - - if (!@$document->loadXML($xml)) { - throw new InvalidArgumentException(sprintf('Given string "%s" is not valid XML', $xml)); - } - - if ($type instanceof XMLType) { - return $document; - } - - $documentElement = $document->documentElement; - - if ($documentElement === null) { - throw new InvalidArgumentException('Given XML does not contain a document element'); - } - - $target = new DOMDocument(); - $imported = $target->importNode($documentElement, true); - - if (!$imported instanceof DOMElement) { - throw new InvalidArgumentException('Imported node is not a DOMElement'); - } - - // an unparented node canonicalizes to "", which would make every restored element compare equal - $target->appendChild($imported); - - return $imported; - } - - /** - * @param Type $type - */ - public function encode(Type $type, mixed $value): mixed - { - if (!$this->handles($type) || $value === null) { - return $value; - } - - $compressed = gzcompress( - $type instanceof HTMLElementType - ? ValueEncoder::htmlElementToString(type_html_element()->assert($value)) - : type_string()->cast($value), - ); - - if ($compressed === false) { - throw new RuntimeException('Failed to gzcompress XML column value.'); - } - - return base64_encode($compressed); - } - - /** - * @param Type $type - */ - public function handles(Type $type): bool - { - return ( - $type instanceof XMLType - || $type instanceof XMLElementType - || $type instanceof HTMLType - || $type instanceof HTMLElementType - ); - } -} diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php index 37b53bffa5..75c4052912 100644 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php +++ b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php @@ -40,23 +40,19 @@ public function merge(array $runs): Generator /** @var array $cursors */ $cursors = []; $schema = null; - $uniform = true; foreach ($runs as $run) { $cursor = new BucketCursor($run->rows()); if ($cursor->valid()) { $schema ??= $cursor->schema(); - $uniform = $uniform && $cursor->schema()->isSame($schema); $heap->push($cursor->current(), $run->id); $cursor->next(); $cursors[$run->id] = $cursor; } } - // every run's rows passed the gate when they were read back - merged under the one schema they share, a - // batch needs no second check - $buffer = new RowsBuffer($schema ?? new Schema(), $this->batchSize, $uniform ? Rows::trusted(...) : null); + $buffer = new RowsBuffer($schema ?? new Schema(), $this->batchSize); while (!$heap->isEmpty()) { $top = $heap->extract(); diff --git a/src/core/etl/src/Flow/ETL/Transformer/AddRowIndexTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/AddRowIndexTransformer.php index bf24502ee5..c85a228264 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/AddRowIndexTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/AddRowIndexTransformer.php @@ -7,13 +7,13 @@ use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformation\AddRowIndex\StartFrom; use Throwable; use function Flow\ETL\DSL\int_schema; +use function range; final class AddRowIndexTransformer implements Stateful { @@ -41,14 +41,16 @@ public function transform(Rows $rows, FlowContext $context): Rows $context->telemetry()->transformationStarted($this); try { - $indexed = []; + $column = $context->backend()->builder(int_schema($this->indexColumn)); - foreach ($rows->all() as $row) { - $indexed[] = new Row([...$row->values(), $this->indexColumn => $this->index]); - $this->index++; + if ($rows->count() > 0) { + $column->appendMany(range($this->index, $this->index + $rows->count() - 1)); + $this->index += $rows->count(); } - $result = new Rows($rows->schema()->add(int_schema($this->indexColumn)), ...$indexed); + $result = $rows->withColumns($rows->schema()->add(int_schema($this->indexColumn)), [ + $this->indexColumn => $column->finish(), + ]); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php b/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php index fd635caba0..68b187fa68 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\Column\Column; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; @@ -40,11 +40,10 @@ public function value(Definition $derived, mixed $value, int $rowIndex): mixed return $cast; } - /** - * @param list $rows each carrying a derived column checked by value() - */ - public function rows(Schema $declared, Schema $output, array $rows): Rows + public function rows(Rows $input, Schema $declared, Schema $output, string $name, Column $derived): Rows { - return $declared->isSame($output) ? Rows::trusted($output, $rows) : new Rows($output, ...$rows); + $withDerived = $input->withColumns($declared, [$name => $derived]); + + return $declared->isSame($output) ? $withDerived : $withDerived->matchTo($output); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php index 07f4c4fffb..974c9baa39 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php @@ -72,7 +72,7 @@ public function transform(Rows $rows, FlowContext $context): Rows } } - $result = new Rows($rows->schema(), ...$newRows); + $result = Rows::of($rows->schema(), ...$newRows); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php index 3ecddd0409..70114cbd48 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php @@ -102,9 +102,9 @@ public function transform(Rows $rows, FlowContext $context): Rows } } - $rows = new Rows($output, ...$interleaved); + $rows = Rows::of($output, ...$interleaved); } else { - $rows = new Rows($output, ...$rows->all()); + $rows = Rows::of($output, ...$rows->all()); } $context->telemetry()->transformationCompleted($this, [ diff --git a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php index 8a9f49819b..e45884745b 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php @@ -7,8 +7,8 @@ use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; use Flow\ETL\Transformer; @@ -66,36 +66,56 @@ private function map(Rows $rows, FlowContext $context, Definition $derived): Row { $columns = new DerivedColumns(); $declared = $columns->declare($rows->schema(), $derived); - $name = $derived->entry()->name(); - $mapped = []; + $cast = []; + $sources = []; - foreach ($rows->all() as $r) { + foreach ($rows->all() as $index => $r) { // @mago-ignore analysis:mixed-assignment foreach ($this->expansion->eval($r, $context) as $value) { - $mapped[] = new Row([...$r->values(), $name => $columns->value($derived, $value, count($mapped))]); + $sources[] = $index; + $cast[] = $columns->value($derived, $value, count($cast)); } } - return $columns->rows($declared, $this->output, $mapped); + $builder = $context->backend()->builder($derived); + $builder->appendMany($cast); + + return $columns->rows( + $rows->gather($sources), + $declared, + $this->output, + $derived->entry()->name(), + $builder->finish(), + ); } private function unpack(Rows $rows, FlowContext $context, Schema $declared): Rows { $columns = new UnpackedColumns(); - $unpacked = []; + $prefix = $this->entryName . '.'; + $prefixed = []; + + foreach ($declared->definitions() as $name => $_) { + $prefixed[] = $prefix . $name; + } + + $payloads = []; + $sources = []; - foreach ($rows->all() as $r) { + foreach ($rows->all() as $index => $r) { // @mago-ignore analysis:mixed-assignment foreach ($this->expansion->eval($r, $context) as $payload) { - $unpacked[] = new Row($columns->values( - $r->values(), - $this->entryName . '.', - $declared, - type_array()->assert($payload), - )); + $sources[] = $index; + $payloads[] = $columns->values($prefix, $declared, type_array()->assert($payload)); } } - return new Rows($this->output, ...$unpacked); + return $rows->gather($sources)->withColumns( + $this->output, + (new RowsBuilder($this->output->keep(...$prefixed), $context->backend())) + ->appendRows($payloads) + ->finish() + ->columns(), + ); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php b/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php index 168d2e3f64..d48e698fa3 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php +++ b/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php @@ -12,13 +12,17 @@ use Flow\ETL\Row; use Flow\ETL\Row\ResolvedReference; use Flow\ETL\Schema; +use Flow\ETL\Schema\Definition; use Flow\Types\Type; +use Flow\Types\Type\Logical\OptionalType; use Flow\Types\Type\TypeWidener; +use function array_fill; use function array_key_exists; use function array_map; use function array_values; use function count; +use function Flow\ETL\DSL\definition_from_type; use function max; use function spl_object_id; @@ -27,10 +31,15 @@ /** * @param non-empty-array $expands keyed by the synthesized column the root reads * each element from + * @param array> $expandDefinitions the synthesized columns, keyed like $expands + * @param Schema $elementSchema $input with the synthesized columns, built once */ private function __construct( private ScalarFunction $root, private array $expands, + private Schema $input, + private array $expandDefinitions, + private Schema $elementSchema, ) {} public static function of(ScalarFunction $resolved, Schema $input): ?self @@ -54,6 +63,7 @@ public static function of(ScalarFunction $resolved, Schema $input): ?self $pads = count($distinct) > 1; $references = []; $expands = []; + $expandDefinitions = []; $suffix = 0; foreach ($distinct as $id => $expand) { @@ -61,9 +71,12 @@ public static function of(ScalarFunction $resolved, Schema $input): ?self $name = "\0expand:" . $suffix++; } while ($input->findDefinition($name) !== null); - $references[$id] = new ResolvedReference( + $type = $pads ? (new TypeWidener())->nullable($expand->returns()) : $expand->returns(); + $references[$id] = new ResolvedReference($name, $type); + $expandDefinitions[$name] = definition_from_type( $name, - $pads ? (new TypeWidener())->nullable($expand->returns()) : $expand->returns(), + $type instanceof OptionalType ? $type->base() : $type, + nullable: true, ); $expands[$name] = $expand; } @@ -71,7 +84,7 @@ public static function of(ScalarFunction $resolved, Schema $input): ?self /** @var ScalarFunction $root the root is not an expand, so rewrite() rebuilds it with its own class */ $root = self::rewrite($resolved, $references); - return new self($root, $expands); + return new self($root, $expands, $input, $expandDefinitions, $input->add(...array_values($expandDefinitions))); } /** @@ -93,16 +106,30 @@ public function eval(Row $row, FlowContext $context): array $lists[$name] = array_values($expand->eval($row, $context)); } - $values = []; $length = max(array_map(count(...), $lists)); - $element = $row->values(); - - for ($position = 0; $position < $length; $position++) { - foreach ($lists as $name => $list) { - $element[$name] = $list[$position] ?? null; + $elements = $row->rows->gather(array_fill(0, $length, $row->index)); + $schema = $elements->schema()->isSame($this->input) + ? $this->elementSchema + : $elements->schema()->add(...array_values($this->expandDefinitions)); + $columns = []; + + foreach ($lists as $name => $list) { + $builder = $context->backend()->builder($this->expandDefinitions[$name]); + $cells = []; + + for ($position = 0; $position < $length; $position++) { + $cells[] = $list[$position] ?? null; } - $values[] = $this->root->eval(new Row($element), $context); + $builder->appendMany($cells); + $columns[$name] = $builder->finish(); + } + + $batch = $elements->withColumns($schema, $columns); + $values = []; + + for ($position = 0; $position < $length; $position++) { + $values[] = $this->root->eval($batch->row($position), $context); } return $values; diff --git a/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php index 8e2fd241dd..e2d335ae42 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php @@ -14,10 +14,6 @@ use Flow\ETL\Transformer; use Throwable; -use function array_key_exists; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; - /** * Unlike {@see SelectEntriesTransformer}, which throws when a reference is not declared by the * schema, prune keeps what is there and silently skips absent references - pruned rows are spilled @@ -59,22 +55,7 @@ public function transform(Rows $rows, FlowContext $context): Rows } $schema = $rows->schema()->keep(...$present)->reorder(...$present); - $newRows = []; - - foreach ($rows as $row) { - $values = $row->values(); - $pruned = []; - - foreach ($this->refs as $ref) { - if (array_key_exists($ref->name(), $values)) { - $pruned[$ref->name()] = $values[$ref->name()]; - } - } - - $newRows[] = row($pruned); - } - - $result = rows($schema, ...$newRows); + $result = $rows->project($schema); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/RenameEachEntryTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/RenameEachEntryTransformer.php index be7ad8b77f..73c5e2b8bd 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/RenameEachEntryTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/RenameEachEntryTransformer.php @@ -8,15 +8,12 @@ use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row\RowRenaming; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; use Flow\ETL\Transformer\Rename\RenameEntryStrategy; use Throwable; -use function array_search; - final readonly class RenameEachEntryTransformer implements Transformer { /** @@ -52,31 +49,15 @@ public function transform(Rows $rows, FlowContext $context): Rows try { $schema = $rows->schema(); - $renames = []; - + // strategies chain, so a later one renames what an earlier one produced foreach ($this->strategies as $strategy) { foreach ($strategy->renames($schema) as $from => $to) { // a numeric entry name arrives as int - PHP casts numeric-string array keys - $from = (string) $from; - - $schema = $schema->rename($from, $to); - - // strategies chain, so a later one renames what an earlier one produced; the map - // has to stay keyed by the row's original name or the projection lands short - $original = array_search($from, $renames, true); - - $renames[false === $original ? $from : $original] = $to; + $schema = $schema->rename((string) $from, $to); } } - $renaming = RowRenaming::of($renames); - $renamed = []; - - foreach ($rows->all() as $row) { - $renamed[] = $renaming->apply($row); - } - - $result = new Rows($schema, ...$renamed); + $result = $rows->withSchema($schema); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/RenameEntryTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/RenameEntryTransformer.php index 1b79ed4af6..c9f56b1b0d 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/RenameEntryTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/RenameEntryTransformer.php @@ -7,7 +7,6 @@ use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Row\RowRenaming; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; @@ -38,14 +37,7 @@ public function transform(Rows $rows, FlowContext $context): Rows $context->telemetry()->transformationStarted($this); try { - $renaming = RowRenaming::of([$this->from => $this->to]); - $renamed = []; - - foreach ($rows->all() as $row) { - $renamed[] = $renaming->apply($row); - } - - $result = new Rows($rows->schema()->rename($this->from, $this->to), ...$renamed); + $result = $rows->withSchema($rows->schema()->rename($this->from, $this->to)); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php index 0a01576ea9..f6cbf85996 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php @@ -51,7 +51,7 @@ public function transform(Rows $rows, FlowContext $context): Rows } } - $result = Rows::trusted($rows->schema(), $kept); + $result = Rows::of($rows->schema(), ...$kept); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php index 717d7be21d..e8bad2afa8 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php @@ -15,8 +15,8 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\ScalarFunction\ExpandResults; use Flow\ETL\Function\ScalarFunction\UnpackResults; -use Flow\ETL\Row; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; use Flow\ETL\Transformer; @@ -143,29 +143,33 @@ private function map(Rows $rows, FlowContext $context): Rows $derived = $this->derived ?? $this->derived($function); $declared = $columns->declare($rows->schema(), $derived); $output = $this->output ?? $declared; - $name = $derived->entry()->name(); - $mapped = []; + $cast = []; + $sources = []; - foreach ($rows->all() as $r) { + foreach ($rows->all() as $index => $r) { if ($function instanceof ExpandResults) { // @mago-ignore analysis:mixed-assignment foreach (type_array()->assert($function->eval($r, $context)) as $val) { - $mapped[] = new Row([ - ...$r->values(), - $name => $columns->value($derived, $val, count($mapped)), - ]); + $sources[] = $index; + $cast[] = $columns->value($derived, $val, count($cast)); } continue; } - $mapped[] = new Row([ - ...$r->values(), - $name => $columns->value($derived, $function->eval($r, $context), count($mapped)), - ]); + $cast[] = $columns->value($derived, $function->eval($r, $context), $index); } - return $columns->rows($declared, $output, $mapped); + $builder = $context->backend()->builder($derived); + $builder->appendMany($cast); + + return $columns->rows( + $function instanceof ExpandResults ? $rows->gather($sources) : $rows, + $declared, + $output, + $derived->entry()->name(), + $builder->finish(), + ); } /** @@ -201,17 +205,25 @@ private function unpack(Rows $rows, FlowContext $context): Rows $declared = $this->unpacked($function); $columns = new UnpackedColumns(); $output = $this->output ?? $columns->of($rows->schema(), $this->entryName() . '.', $declared); - $unpacked = []; + $prefix = $this->entryName() . '.'; + $prefixed = []; + + foreach ($declared->definitions() as $name => $_) { + $prefixed[] = $prefix . $name; + } + + $payloads = []; foreach ($rows->all() as $r) { - $unpacked[] = new Row($columns->values( - $r->values(), - $this->entryName() . '.', - $declared, - $function->eval($r, $context), - )); + $payloads[] = $columns->values($prefix, $declared, $function->eval($r, $context)); } - return new Rows($output, ...$unpacked); + return $rows->withColumns( + $output, + (new RowsBuilder($output->keep(...$prefixed), $context->backend())) + ->appendRows($payloads) + ->finish() + ->columns(), + ); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php index aa69a0adc7..b19e4ad1df 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php @@ -15,7 +15,6 @@ use Throwable; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -62,17 +61,15 @@ public function transform(Rows $rows, FlowContext $context): Rows : $inputSchema->replace($target->name(), $column) ); - $serialized = []; + $serialized = $context->backend()->builder($column); foreach ($rows->all() as $row) { - $payload = serialize_to_string($serializer, rows($inputSchema, $row)); - - $serialized[] = $this->standalone - ? row([$target->name() => $payload]) - : row([...$row->values(), $target->name() => $payload]); + $serialized->append(serialize_to_string($serializer, rows($inputSchema, $row))); } - $result = new Rows($outputSchema, ...$serialized); + $result = $this->standalone + ? Rows::fromColumns($outputSchema, [$target->name() => $serialized->finish()], $rows->count()) + : $rows->withColumns($outputSchema, [$target->name() => $serialized->finish()]); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/SerializedPayloadDecoder.php b/src/core/etl/src/Flow/ETL/Transformer/SerializedPayloadDecoder.php index cae2b7f040..6b2528ccaa 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/SerializedPayloadDecoder.php +++ b/src/core/etl/src/Flow/ETL/Transformer/SerializedPayloadDecoder.php @@ -6,78 +6,75 @@ use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; +use Flow\ETL\Schema; use Flow\Serializer\Exception\SerializationException; use Flow\Serializer\Serializer; -use function array_key_exists; use function Flow\Serializer\DSL\unserialize_from_string; use function is_string; -/** - * A payload that does not decode still has to produce the declared shape, so every branch that gives - * up answers with the declared columns as nulls - the rule from_json follows. - */ final readonly class SerializedPayloadDecoder { /** - * @param array $declared output column name => column name in the payload - * @param array $nulls + * @param list $names the payload columns to read */ private function __construct( private Reference $source, private Serializer $serializer, - private array $declared, - private array $nulls, + private array $names, + private string $prefix, + private Row $nothing, ) {} /** - * @param array $declared output column name => column name in the payload + * @param list $names the payload columns to read, each landing under $prefix . name */ - public static function of(Reference $source, Serializer $serializer, array $declared): self + public static function of(Reference $source, Serializer $serializer, array $names, string $prefix = ''): self { - $nulls = []; - - foreach ($declared as $name => $_) { - $nulls[$name] = null; - } - - return new self($source, $serializer, $declared, $nulls); + return new self($source, $serializer, $names, $prefix, Rows::fromColumns(new Schema(), [], 1)->row(0)); } /** - * @return array + * A view of the payload's declared columns under their output names; a payload that cannot be read is a view with + * no columns at all. */ - public function decode(Row $row): array + public function decode(Row $row): Row { if (!$row->has($this->source->name())) { - return $this->nulls; + return $this->nothing; } $serialized = $row->get($this->source->name()); if (!is_string($serialized)) { - return $this->nulls; + return $this->nothing; } try { $decoded = unserialize_from_string($this->serializer, $serialized); } catch (SerializationException) { - return $this->nulls; + return $this->nothing; } if ($decoded->count() !== 1) { - return $this->nulls; + return $this->nothing; } - $payload = $decoded->first()->values(); - $values = $this->nulls; + $definitions = []; + $columns = []; - foreach ($this->declared as $name => $payloadName) { - if (array_key_exists($payloadName, $payload)) { - $values[$name] = $payload[$payloadName]; + foreach ($this->names as $name) { + $definition = $decoded->schema()->findDefinition($name); + + if ($definition === null) { + continue; } + + $definitions[] = $definition->rename($this->prefix . $name); + $columns[$this->prefix . $name] = $decoded->column($name); } - return $values; + return Rows::fromColumns(new Schema(...$definitions), $columns, 1)->row(0); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer/UnpackedColumns.php b/src/core/etl/src/Flow/ETL/Transformer/UnpackedColumns.php index 1dd1da23df..7486640ef5 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/UnpackedColumns.php +++ b/src/core/etl/src/Flow/ETL/Transformer/UnpackedColumns.php @@ -28,13 +28,14 @@ public function of(Schema $base, string $prefix, Schema $declared): Schema } /** - * @param array $values * @param array $payload * - * @return array + * @return array the cast values, keyed "$prefix$column" */ - public function values(array $values, string $prefix, Schema $declared, array $payload): array + public function values(string $prefix, Schema $declared, array $payload): array { + $values = []; + foreach ($declared->definitions() as $name => $definition) { // @mago-ignore analysis:mixed-assignment $value = $payload[$name] ?? null; diff --git a/src/core/etl/src/Flow/ETL/Transformer/UnserializeTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/UnserializeTransformer.php index ca0c6f962a..72d9f24841 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/UnserializeTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/UnserializeTransformer.php @@ -7,9 +7,9 @@ use Flow\ETL\BoundStep; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Transformer; use Flow\Serializer\Base64Serializer; @@ -50,24 +50,25 @@ public function transform(Rows $rows, FlowContext $context): Rows // a payload that fails to decode still has to produce the declared shape, so every declared // column is nullable - the same rule from_json follows $outputSchema = $this->bind($rows->schema())->output; - $declared = []; + $prefix = $this->merge ? $this->mergePrefix : ''; + $names = []; + $outputNames = []; foreach ($this->target->definitions() as $definition) { - $payloadName = $definition->entry()->name(); - $declared[$this->merge ? $this->mergePrefix . $payloadName : $payloadName] = $payloadName; + $names[] = $definition->entry()->name(); + $outputNames[] = $prefix . $definition->entry()->name(); } - $decoder = SerializedPayloadDecoder::of($source, $serializer, $declared); - $unserialized = []; + $decoder = SerializedPayloadDecoder::of($source, $serializer, $names, $prefix); + $builder = new RowsBuilder($outputSchema->keep(...$outputNames), $context->backend()); foreach ($rows->all() as $row) { - $unserialized[] = new Row([ - ...($this->merge ? $row->values() : []), - ...$decoder->decode($row), - ]); + $payload = $decoder->decode($row); + $builder->appendFrom($payload->rows, $payload->index); } - $result = new Rows($outputSchema, ...$unserialized); + $decoded = $builder->finish(); + $result = $this->merge ? $rows->withColumns($outputSchema, $decoded->columns()) : $decoded; $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php index 6b60597ad6..c68c0a0c7a 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php @@ -51,7 +51,7 @@ public function transform(Rows $rows, FlowContext $context): Rows TelemetryAttributes::ATTR_TRANSFORMATION_OUTPUT_ROWS => 0, ]); - throw new LimitReachedException(0, new Rows($rows->schema())); + throw new LimitReachedException(0, Rows::of($rows->schema())); } // the unbound path has no plan to hold the resolved predicate, so it is memoised here - @@ -68,7 +68,7 @@ public function transform(Rows $rows, FlowContext $context): Rows TelemetryAttributes::ATTR_TRANSFORMATION_OUTPUT_ROWS => count($nextRows), ]); - throw new LimitReachedException(0, new Rows($rows->schema(), ...$nextRows)); + throw new LimitReachedException(0, Rows::of($rows->schema(), ...$nextRows)); } $nextRows[] = $row; diff --git a/src/core/etl/src/Flow/Floe/DSL/functions.php b/src/core/etl/src/Flow/Floe/DSL/functions.php index 70343179bc..b277ea5289 100644 --- a/src/core/etl/src/Flow/Floe/DSL/functions.php +++ b/src/core/etl/src/Flow/Floe/DSL/functions.php @@ -13,7 +13,6 @@ use Flow\Filesystem\Path; use Flow\Floe\Codec; use Flow\Floe\Codec\NoopCodec; -use Flow\Floe\FloeEngine; use Flow\Floe\FloeExtractor; use Flow\Floe\FloeLoader; use Flow\Floe\FloeMerger; @@ -32,10 +31,9 @@ function from_floe( string|Path $path, Codec $codec = new NoopCodec(), int $chunk_size = 65536, - FloeEngine $engine = FloeEngine::adaptive, Filesystem $filesystem = new NativeLocalFilesystem(), ): FloeExtractor { - return new FloeExtractor(is_string($path) ? path_real($path) : $path, $codec, $chunk_size, $engine, $filesystem); + return new FloeExtractor(is_string($path) ? path_real($path) : $path, $codec, $chunk_size, $filesystem); } /** @@ -46,10 +44,9 @@ function to_floe( string|Path $path, ?Metadata $metadata = null, Options $options = new Options(), - FloeEngine $engine = FloeEngine::adaptive, Filesystem $filesystem = new NativeLocalFilesystem(), ): FloeLoader { - return new FloeLoader(is_string($path) ? path_real($path) : $path, $metadata, $options, $engine, $filesystem); + return new FloeLoader(is_string($path) ? path_real($path) : $path, $metadata, $options, $filesystem); } #[DocumentationDSL(module: Module::FLOE, type: DSLType::HELPER)] diff --git a/src/core/etl/src/Flow/Floe/Decoding/JsonDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/JsonDecoder.php index 73582d409d..fd0c7f831a 100644 --- a/src/core/etl/src/Flow/Floe/Decoding/JsonDecoder.php +++ b/src/core/etl/src/Flow/Floe/Decoding/JsonDecoder.php @@ -4,46 +4,24 @@ namespace Flow\Floe\Decoding; -use Closure; +use Flow\ETL\Column\Php\JsonFactory; use Flow\Types\Value\Json; -use ReflectionClass; use function substr; use function unpack; final class JsonDecoder implements ValueDecoder { - /** - * @var \Closure(string, bool): Json - */ - private readonly Closure $create; - - public function __construct() - { - $reflection = new ReflectionClass(Json::class); - - /** @var \Closure(string, bool): Json $create */ - $create = Closure::bind( - static function (string $value, bool $isObject) use ($reflection): Json { - $json = $reflection->newInstanceWithoutConstructor(); - $json->value = $value; - $json->isObject = $isObject; - - return $json; - }, - null, - Json::class, - ); - - $this->create = $create; - } + public function __construct( + private readonly JsonFactory $factory = new JsonFactory(), + ) {} public function decode(string $data, int &$position): Json { $length = unpack('V', $data, $position)[1]; $json = substr($data, $position + 4, $length); - $position += 4 + $length; + $position += 5 + $length; - return ($this->create)($json, $data[$position++] === "\x01"); + return $this->factory->create($json); } } diff --git a/src/core/etl/src/Flow/Floe/FloeEngine.php b/src/core/etl/src/Flow/Floe/FloeEngine.php deleted file mode 100644 index 15e45f0a41..0000000000 --- a/src/core/etl/src/Flow/Floe/FloeEngine.php +++ /dev/null @@ -1,25 +0,0 @@ - NativeFloeEncoder::isSupported() - ? new NativeFloeEncoder($schema) - : new PhpFloeEncoder($schema), - self::native => new NativeFloeEncoder($schema), - self::php => new PhpFloeEncoder($schema), - }; - } -} diff --git a/src/core/etl/src/Flow/Floe/FloeExtractor.php b/src/core/etl/src/Flow/Floe/FloeExtractor.php index 27b8b2a9df..1147b82d9d 100644 --- a/src/core/etl/src/Flow/Floe/FloeExtractor.php +++ b/src/core/etl/src/Flow/Floe/FloeExtractor.php @@ -54,7 +54,6 @@ public function __construct( private readonly Path $path, private readonly Codec $codec = new NoopCodec(), private readonly int $chunkSize = 65536, - private readonly FloeEngine $engine = FloeEngine::adaptive, Filesystem $filesystem = new NativeLocalFilesystem(), ) { if (!$filesystem->supports($path)) { @@ -123,7 +122,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi foreach ($file->reader->rows($this->batchSize(), $fileOffset, $remaining) as $rows) { // R7: the stamp stays post-hydration - FloeStreamReader::rows() yields hydrated Rows and // must not learn about paths - but the constants are the shared ones, already typed - $rows = $constants->fillRows($rows, $fileSchema); + $rows = $constants->fillRows($rows, $fileSchema, $context->backend()); if ($matchTo !== null) { $rows = $rows->matchTo($matchTo); @@ -224,7 +223,6 @@ private function files(?Hydrator $hydrator = null, Filter $pathFilter = new Only $this->codec, $this->chunkSize, hydrator: $hydrator, - engine: $this->engine, ))->read($source->path), $source, ); diff --git a/src/core/etl/src/Flow/Floe/FloeLoader.php b/src/core/etl/src/Flow/Floe/FloeLoader.php index 3878e5a930..5fd2516052 100644 --- a/src/core/etl/src/Flow/Floe/FloeLoader.php +++ b/src/core/etl/src/Flow/Floe/FloeLoader.php @@ -56,7 +56,6 @@ public function __construct( private readonly Path $path, private readonly ?Metadata $metadata = null, private readonly Options $options = new Options(), - private readonly FloeEngine $engine = FloeEngine::adaptive, Filesystem $filesystem = new NativeLocalFilesystem(), ) { if (!$filesystem->supports($path)) { @@ -172,7 +171,6 @@ private function openWriter(DestinationStream $stream, FlowContext $context): Fl $declared->gracefulRemove(...$this->router->droppedNames()), $this->options, hydrator: $context->hydrator(), - engine: $this->engine, ); $writer->createForStream($stream, $this->metadata); diff --git a/src/core/etl/src/Flow/Floe/FloeReader.php b/src/core/etl/src/Flow/Floe/FloeReader.php index 0378ea72a5..aa47277a66 100644 --- a/src/core/etl/src/Flow/Floe/FloeReader.php +++ b/src/core/etl/src/Flow/Floe/FloeReader.php @@ -13,14 +13,13 @@ final readonly class FloeReader { /** - * @param null|Hydrator $hydrator null uses the adaptive hydrator + * @param null|Hydrator $hydrator null uses `new PhpRowHydrator()` */ public function __construct( private Filesystem $filesystem, private Codec $codec = new NoopCodec(), private int $chunkSize = 65536, private ?Hydrator $hydrator = null, - private FloeEngine $engine = FloeEngine::adaptive, ) {} /** @@ -33,7 +32,6 @@ public function read(Path $path): FloeStreamReader $this->codec, $this->chunkSize, $this->hydrator, - $this->engine, ); } } diff --git a/src/core/etl/src/Flow/Floe/FloeSerializer.php b/src/core/etl/src/Flow/Floe/FloeSerializer.php index 3b7c8d0e90..d6ba72fa18 100644 --- a/src/core/etl/src/Flow/Floe/FloeSerializer.php +++ b/src/core/etl/src/Flow/Floe/FloeSerializer.php @@ -14,7 +14,6 @@ use Flow\Serializer\Exception\SerializationException; use Flow\Serializer\Serializer; -use function count; use function sprintf; final class FloeSerializer implements Serializer @@ -23,7 +22,7 @@ final class FloeSerializer implements Serializer /** * @param int<1, max> $batchSize - * @param null|Hydrator $hydrator null uses the adaptive hydrator + * @param null|Hydrator $hydrator null uses `new PhpRowHydrator()` */ public function __construct( private readonly int $batchSize = 1000, @@ -55,24 +54,23 @@ public function unserialize(SourceStream $source): Rows $footer = $reader->footer(); - $rows = []; + $batches = []; + $decoded = 0; foreach ($reader->rows($this->batchSize) as $batch) { - foreach ($batch->all() as $row) { - $rows[] = $row; - } + $batches[] = $batch; + $decoded += $batch->count(); } - if (count($rows) !== $footer->statistics->rows) { + if ($decoded !== $footer->statistics->rows) { throw new FloeException(sprintf( 'Floe payload is corrupted, decoded %d of %d rows', - count($rows), + $decoded, $footer->statistics->rows, )); } - // every row came out of a reader batch already conformed to this schema - return Rows::trusted($reader->schema(), $rows); + return Rows::of($reader->schema())->concat(...$batches); } catch (FloeException|ExtensionException $e) { throw new SerializationException($e->getMessage(), 0, $e); } finally { diff --git a/src/core/etl/src/Flow/Floe/FloeStreamReader.php b/src/core/etl/src/Flow/Floe/FloeStreamReader.php index 18bfe2bdee..c7d1d14174 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamReader.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamReader.php @@ -4,8 +4,8 @@ namespace Flow\Floe; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Row\Hydrator; +use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -36,7 +36,7 @@ final class FloeStreamReader private readonly Hydrator $hydrator; /** - * @param null|Hydrator $hydrator null uses the adaptive hydrator + * @param null|Hydrator $hydrator null uses `new PhpRowHydrator()` * * @throws FloeException */ @@ -45,10 +45,9 @@ public function __construct( private readonly Codec $codec, private readonly int $chunkSize, ?Hydrator $hydrator = null, - private readonly FloeEngine $engine = FloeEngine::adaptive, ) { Format::validateCodecId($this->codec->id()); - $this->hydrator = $hydrator ?? new AdaptiveRowHydrator(); + $this->hydrator = $hydrator ?? new PhpRowHydrator(); } public function close(): void @@ -58,7 +57,7 @@ public function close(): void private function encoder(Schema $schema): FloeEncoder { - return $this->encoder ??= $this->engine->encoder($schema); + return $this->encoder ??= new PhpFloeEncoder($schema); } /** @@ -270,7 +269,7 @@ private function decode(Schema $schema, array $pending): Rows { $rows = $this->encoder($schema)->decodeRows($pending, $schema, $this->hydrator); - return $rows->schema() === $schema ? $rows : Rows::trusted($schema, $rows->all()); + return $rows->schema() === $schema ? $rows : $rows->withSchema($schema); } /** diff --git a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php index b82b5975a3..9620f7ec06 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php @@ -5,8 +5,8 @@ namespace Flow\Floe; use Composer\InstalledVersions; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Row\Hydrator; +use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -66,11 +66,10 @@ public function __construct( Schema $schema, private readonly Options $options = new Options(), ?Hydrator $hydrator = null, - private readonly FloeEngine $engine = FloeEngine::adaptive, ) { Format::validateCodecId($this->options->codec->id()); $this->sessionSchema = $schema; - $this->hydrator = $hydrator ?? new AdaptiveRowHydrator(); + $this->hydrator = $hydrator ?? new PhpRowHydrator(); } /** @@ -192,7 +191,7 @@ private function openSession(): void return; } - $this->sessionEncoder = $this->engine->encoder($this->sessionSchema); + $this->sessionEncoder = new PhpFloeEncoder($this->sessionSchema); } /** diff --git a/src/core/etl/src/Flow/Floe/FloeWriter.php b/src/core/etl/src/Flow/Floe/FloeWriter.php index dd9df37b69..da3e8cc51b 100644 --- a/src/core/etl/src/Flow/Floe/FloeWriter.php +++ b/src/core/etl/src/Flow/Floe/FloeWriter.php @@ -21,7 +21,7 @@ final class FloeWriter /** * @param Schema $schema fixes the session schema for the writer's life - * @param null|Hydrator $hydrator null uses the adaptive hydrator + * @param null|Hydrator $hydrator null uses `new PhpRowHydrator()` * * @throws FloeException */ @@ -30,9 +30,8 @@ public function __construct( Schema $schema, private readonly Options $options = new Options(), ?Hydrator $hydrator = null, - FloeEngine $engine = FloeEngine::adaptive, ) { - $this->inner = new FloeStreamWriter($schema, $this->options, $hydrator, $engine); + $this->inner = new FloeStreamWriter($schema, $this->options, $hydrator); } /** diff --git a/src/core/etl/src/Flow/Floe/NativeFloeEncoder.php b/src/core/etl/src/Flow/Floe/NativeFloeEncoder.php deleted file mode 100644 index 2de0bd41da..0000000000 --- a/src/core/etl/src/Flow/Floe/NativeFloeEncoder.php +++ /dev/null @@ -1,117 +0,0 @@ -native = new RustFloeEncoderNative(); - } - - public static function isSupported(): bool - { - // an extension older than this library lacks decodeRows()/encodeFrames()/datetimeZones() - it falls back to the PHP engine instead - return ( - extension_loaded('flow_php') - && class_exists(RustFloeEncoderNative::class, false) - && method_exists(RustFloeEncoderNative::class, 'decodeRows') - && method_exists(RustFloeEncoderNative::class, 'encodeFrames') - && method_exists(RustFloeEncoderNative::class, 'datetimeZones') - ); - } - - public function decode(array $batch): array - { - try { - return $this->native->decode($batch, $this->schemaBody()); - } catch (ExtensionException $e) { - throw new FloeException($e->getMessage(), 0, $e); - } - } - - public function decodeRows(array $bodies, Schema $schema, Hydrator $hydrator): Rows - { - if (!self::isNativeHydrator($hydrator)) { - return $hydrator->hydrate($this->decode($bodies), $schema); - } - - try { - return $this->native->decodeRows($bodies, $this->schemaBody(), $schema); - } catch (ExtensionException $e) { - throw new FloeException($e->getMessage(), 0, $e); - } - } - - public function encodeFrames(Rows $rows, Hydrator $hydrator): string - { - if (!self::isNativeHydrator($hydrator)) { - return Format::rowFrames($this->encode($hydrator->dehydrate($rows))); - } - - try { - return $this->native->encodeFrames($rows, $this->schemaBody(), $this->schema); - } catch (ExtensionException $e) { - throw new FloeException($e->getMessage(), 0, $e); - } - } - - public function encode(array $batch): array - { - try { - return $this->native->encode($batch, $this->schemaBody(), $this->schema); - } catch (ExtensionException $e) { - throw new FloeException($e->getMessage(), 0, $e); - } - } - - private static function isNativeHydrator(Hydrator $hydrator): bool - { - return ( - $hydrator instanceof NativeRowHydrator - || $hydrator instanceof AdaptiveRowHydrator - && $hydrator->isNative() - ); - } - - private function schemaBody(): string - { - if ($this->schemaBody !== null) { - return $this->schemaBody; - } - - try { - return $this->schemaBody = json_encode($this->schema->normalize(), JSON_THROW_ON_ERROR); - } catch (JsonException $e) { - throw new FloeException('Floe failed to encode schema as JSON: ' . $e->getMessage(), 0, $e); - } - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowComparator.php b/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowComparator.php new file mode 100644 index 0000000000..5dcb4604e8 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowComparator.php @@ -0,0 +1,60 @@ +names() !== $actual->names()) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expected->names()), + $exporter->export($actual->names()), + 'Failed asserting that two Row objects have the same names.', + ); + } + + $expectedArray = $expected->toArray(); + $actualArray = $actual->toArray(); + + try { + $this + ->factory() + ->getComparatorFor($expectedArray, $actualArray) + ->assertEquals($expectedArray, $actualArray, $delta, $canonicalize, $ignoreCase); + } catch (ComparisonFailure) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expectedArray), + $exporter->export($actualArray), + 'Failed asserting that two Row objects are equal.', + ); + } + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowsComparator.php b/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowsComparator.php new file mode 100644 index 0000000000..717780e149 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowsComparator.php @@ -0,0 +1,60 @@ +schema()->isSame($actual->schema())) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expected->schema()->normalize()), + $exporter->export($actual->schema()->normalize()), + 'Failed asserting that two Rows have the same schema.', + ); + } + + $expectedArray = $expected->toArray(); + $actualArray = $actual->toArray(); + + try { + $this + ->factory() + ->getComparatorFor($expectedArray, $actualArray) + ->assertEquals($expectedArray, $actualArray, $delta, $canonicalize, $ignoreCase); + } catch (ComparisonFailure) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expectedArray), + $exporter->export($actualArray), + 'Failed asserting that two Rows are equal.', + ); + } + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php new file mode 100644 index 0000000000..a54b8f4a83 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php @@ -0,0 +1,31 @@ +assert(unserialize(serialize($rows))); + } + + /** + * @param array{schema: \Flow\ETL\Schema, count: int, columns: array, nullCount: int}>} $payload + */ + public static function unserialize(array $payload): Rows + { + $rows = (new ReflectionClass(Rows::class))->newInstanceWithoutConstructor(); + $rows->__unserialize($payload); + + return $rows; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingBackend.php b/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingBackend.php new file mode 100644 index 0000000000..f289e8078a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingBackend.php @@ -0,0 +1,32 @@ +constant($definition, $value, $count); + } + + public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column + { + return (new PhpBackend())->decode($definition, $buffers, $count, $nullCount); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingColumnBuilder.php b/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingColumnBuilder.php new file mode 100644 index 0000000000..d147154801 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingColumnBuilder.php @@ -0,0 +1,48 @@ +count++; + } + + public function appendFrom(Column $column, int $i): void + { + $this->count++; + } + + public function appendMany(array $values): void + { + $this->count += count($values); + } + + public function appendTake(Column $column, array $indices): void + { + $this->count += count($indices); + } + + public function count(): int + { + return $this->count; + } + + public function finish(): Column + { + return new ConstantColumn(type_null(), new NullPhysical(), null, $this->count); + } +} 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 590373f8d9..fe8606f745 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php @@ -11,6 +11,7 @@ use Flow\ETL\Transformer; use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\rows; use function Flow\Types\DSL\type_string; use function sprintf; @@ -48,6 +49,6 @@ public function transform(Rows $rows, FlowContext $context): Rows ]); } - return new Rows($rows->schema(), ...$stamped); + return rows($rows->schema(), ...$stamped); } } 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 08010bdf56..030092d774 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php @@ -17,6 +17,7 @@ use function array_values; use function count; +use function Flow\ETL\DSL\rows; /** * Counts how many times extract() was pulled, so a test can prove the plan bind read no row, and how @@ -63,7 +64,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator if (count($buffer) === $this->batchSize()) { $this->batchesYielded++; - $signal = yield Rows::trusted($this->schema, $buffer); + $signal = yield rows($this->schema, ...$buffer); if ($signal === Signal::STOP) { return; @@ -77,7 +78,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator if ($buffer !== []) { $this->batchesYielded++; - yield Rows::trusted($this->schema, $buffer); + yield rows($this->schema, ...$buffer); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php index 7a70182d65..199af1e31c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php @@ -19,7 +19,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null): Generator { - yield new Rows($this->schema()); + yield Rows::of($this->schema()); } public function schema(): Schema 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 fc44c791f7..7ef3e86fdd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeRandomOrdersExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeRandomOrdersExtractor.php @@ -79,7 +79,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $schema = self::schema(); foreach ($this->rawData() as $row) { - yield array_to_rows($row, $schema, $context->hydrator()); + yield array_to_rows($row, $schema, $context->backend()); } } 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 5446922670..b5168a55f6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php @@ -5,12 +5,12 @@ namespace Flow\ETL\Tests\Double; use DateTimeImmutable; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Extractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; -use Flow\ETL\Row\AdaptiveRowHydrator; -use Flow\ETL\Row\Hydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; @@ -78,7 +78,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $schema = self::schema(); foreach ($this->rawData() as $row) { - yield array_to_rows($row, $schema, $context->hydrator()); + yield array_to_rows($row, $schema, $context->backend()); } } @@ -138,13 +138,13 @@ public function rawData(): Generator } } - public function toRows(Hydrator $hydrator = new AdaptiveRowHydrator()): Rows + public function toRows(Backend $backend = new DefaultBackend()): Rows { $rows = rows(schema()); $schema = self::schema(); foreach ($this->rawData() as $row) { - $rows = $rows->merge(array_to_rows($row, $schema, $hydrator)); + $rows = $rows->merge(array_to_rows($row, $schema, $backend)); } return $rows; 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 de0daac4e3..1661e3e89a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/OneRowBatchesExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/OneRowBatchesExtractor.php @@ -15,6 +15,8 @@ use Flow\ETL\Schema; use Generator; +use function Flow\ETL\DSL\rows; + /** * Breaks exactly one clause of the batch contract: whatever its batch size, it never puts more than * one row in a batch. @@ -30,7 +32,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null): Generator { foreach ($this->rows->all() as $row) { - $signal = yield Rows::trusted($this->rows->schema(), [$row]); + $signal = yield rows($this->rows->schema(), $row); if ($signal === Signal::STOP) { return; 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 fc488b488b..1211caaa85 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php @@ -35,7 +35,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null): Generator { - yield new Rows($this->schema()); + yield Rows::of($this->schema()); } /** 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 93bfa17393..7bbb15aa7e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/StopIgnoringExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/StopIgnoringExtractor.php @@ -14,8 +14,6 @@ use Flow\ETL\Schema; use Generator; -use function array_chunk; - /** * Breaks exactly one clause of the batch contract: it batches at its size, but never reads what is * sent into it, so Signal::STOP does not end it. @@ -30,9 +28,7 @@ public function __construct( 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); - } + yield from $this->rows->chunks($this->batchSize()); } public function isRepeatable(): bool 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 0d7e55e024..3e4ee98133 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 @@ -15,7 +15,6 @@ 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; use Flow\ETL\Tests\FlowIntegrationTestCase; @@ -149,9 +148,9 @@ public function test_default_external_sort_builds_filesystem_storage(): void static::assertInstanceOf(FilesystemBuckets::class, $config->sort->bucketing->storage); } - public function test_default_hydrator_is_the_adaptive_hydrator(): void + public function test_default_hydrator_is_the_php_hydrator(): void { - static::assertInstanceOf(AdaptiveRowHydrator::class, config_builder()->build()->hydrator()); + static::assertInstanceOf(PhpRowHydrator::class, config_builder()->build()->hydrator()); } public function test_default_sorting_algorithm_is_external_sort(): void @@ -164,13 +163,6 @@ public function test_memory_sort_algorithm_override(): void static::assertInstanceOf(MemorySortConfig::class, config_builder()->sort(memory_sort())->build()->sort); } - public function test_hydrator_override_wins_over_the_default(): void - { - $hydrator = new PhpRowHydrator(); - - static::assertSame($hydrator, config_builder()->hydrator($hydrator)->build()->hydrator()); - } - public function test_external_sort_storage_override(): void { $storage = new MemoryBuckets(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SchemaTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SchemaTest.php index 91a6e0f69f..2602009804 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SchemaTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SchemaTest.php @@ -139,7 +139,7 @@ public function test_getting_schema(): void range(1, 100), ), schema(int_schema('id'), str_schema('name'), bool_schema('active')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( @@ -165,7 +165,7 @@ public function test_limit_does_not_narrow_the_schema(): void range(1, 100), ), schema(int_schema('id'), str_schema('name'), bool_schema('active'), str_schema('union', nullable: true)), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/CacheExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/CacheExtractorTest.php index d4b0ce9658..295dee42e5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/CacheExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/CacheExtractorTest.php @@ -114,17 +114,17 @@ public function test_extracting_rows_from_cache(): void $cache->set('rows_01', array_to_rows( [['id' => 1], ['id' => 2]], schema(int_schema('id')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), )); $cache->set('rows_02', array_to_rows( [['id' => 3], ['id' => 4]], schema(int_schema('id')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), )); $cache->set('rows_03', array_to_rows( [['id' => 5]], schema(int_schema('id')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), )); $cache->set('key', $index->toRows()); @@ -152,17 +152,17 @@ public function test_extracting_rows_from_cache_with_clearing_cache_afterwards() $cache->set('rows_01', array_to_rows( [['id' => 1], ['id' => 2]], schema(int_schema('id')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), )); $cache->set('rows_02', array_to_rows( [['id' => 3], ['id' => 4]], schema(int_schema('id')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), )); $cache->set('rows_03', array_to_rows( [['id' => 5]], schema(int_schema('id')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), )); $cache->set('key', $index->toRows()); @@ -195,7 +195,7 @@ public function test_extracting_rows_from_filesystem_cache(): void ['id' => 5], ], schema(int_schema('id')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), )); $cache->set('key', $index->toRows()); @@ -229,7 +229,7 @@ public function test_stop_signal_stops_extraction_and_skips_clearing(): void ['id' => 5], ], schema(int_schema('id')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), )); $cache->set('key', $index->toRows()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php index 31a4830840..733ee81945 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php @@ -16,7 +16,7 @@ use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; -use function Flow\ETL\DSL\xml_element_schema; +use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_html_element; final class DOMElementNextSiblingTest extends FlowTestCase @@ -84,13 +84,14 @@ public function test_xml_sibling_element_value(): void $dom = new DOMDocument(); $dom->loadXML('User Name01'); + // a batch stores an element's own markup, so siblings are reached from the document it belongs to $rows = df() - ->read(from_rows(rows( - schema(xml_element_schema('xml_element')), - row(['xml_element' => $dom->getElementsByTagName('name')->item(0)]), - ))) - ->withEntry('user_name', ref('xml_element')->domElementValue()) - ->withEntry('user_id', ref('xml_element')->domElementNextSibling()->domElementValue()) + ->read(from_rows(rows(schema(xml_schema('xml')), row(['xml' => $dom])))) + ->withEntry('user_name', ref('xml')->xpath('/user/name')->arrayGet('0')->domElementValue()) + ->withEntry( + 'user_id', + ref('xml')->xpath('/user/name')->arrayGet('0')->domElementNextSibling()->domElementValue(), + ) ->select('user_name', 'user_id') ->fetch(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementPreviousSiblingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementPreviousSiblingTest.php index 5489385f66..ae4499122c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementPreviousSiblingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementPreviousSiblingTest.php @@ -16,7 +16,7 @@ use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; -use function Flow\ETL\DSL\xml_element_schema; +use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_html_element; final class DOMElementPreviousSiblingTest extends FlowTestCase @@ -84,13 +84,14 @@ public function test_xml_sibling_element_value(): void $dom = new DOMDocument(); $dom->loadXML('User Name01'); + // a batch stores an element's own markup, so siblings are reached from the document it belongs to $rows = df() - ->read(from_rows(rows( - schema(xml_element_schema('xml_element')), - row(['xml_element' => $dom->getElementsByTagName('number')->item(0)]), - ))) - ->withEntry('user_id', ref('xml_element')->domElementValue()) - ->withEntry('user_name', ref('xml_element')->domElementPreviousSibling()->domElementValue()) + ->read(from_rows(rows(schema(xml_schema('xml')), row(['xml' => $dom])))) + ->withEntry('user_id', ref('xml')->xpath('/user/number')->arrayGet('0')->domElementValue()) + ->withEntry( + 'user_name', + ref('xml')->xpath('/user/number')->arrayGet('0')->domElementPreviousSibling()->domElementValue(), + ) ->select('user_name', 'user_id') ->fetch(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/OnEachTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/OnEachTest.php index c97c622a8a..fa8e4d1cb0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/OnEachTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/OnEachTest.php @@ -28,7 +28,8 @@ public function test_on_each_function(): void static::assertEquals( [ ['array' => ['a' => '1', 'b' => '2', 'c' => '3', 'd' => '4', 'e' => '5']], - ['array' => ['f' => '1', 'g' => '2.3', 'h' => '3', 'i' => '4', 'j' => null]], + // an optional and nullable structure element given null reads back absent (ruling 4) + ['array' => ['f' => '1', 'g' => '2.3', 'h' => '3', 'i' => '4']], ], $results, ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/ColumnMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/ColumnMother.php new file mode 100644 index 0000000000..2cd18d6541 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/ColumnMother.php @@ -0,0 +1,24 @@ + $definition + * @param list $values + */ + public static function of(Definition $definition, array $values): Column + { + $builder = (new PhpBackend())->builder($definition); + $builder->appendMany($values); + + return $builder->finish(); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/DateIntervalMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/DateIntervalMother.php new file mode 100644 index 0000000000..e7e7997f2a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/DateIntervalMother.php @@ -0,0 +1,30 @@ +f = $fraction; + // @mago-ignore analysis:invalid-property-write + $interval->invert = $invert; + + return $interval; + } + + public static function seconds(int $seconds, float $fraction, int $invert): DateInterval + { + $interval = self::of('PT0S', $fraction, $invert); + // @mago-ignore analysis:invalid-property-write + $interval->s = $seconds; + + return $interval; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/XmlMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/XmlMother.php new file mode 100644 index 0000000000..b29f09fd53 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/XmlMother.php @@ -0,0 +1,18 @@ +loadXML($xml); + + return $document; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnConcatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnConcatTest.php new file mode 100644 index 0000000000..541fa57135 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnConcatTest.php @@ -0,0 +1,115 @@ +concat(ColumnMother::of( + int_schema('a', nullable: true), + [null, 4], + )); + + static::assertSame([1, null, null, 4], $column->values()); + static::assertSame(2, $column->nullCount()); + } + + public function test_list_columns_rebase_offsets_and_rekey_nulls(): void + { + $definition = list_schema('a', type_list(type_integer()), nullable: true); + $column = ColumnMother::of($definition, [[1], null])->concat(ColumnMother::of($definition, [null, [2, 3]])); + + static::assertSame([[1], null, null, [2, 3]], $column->values()); + static::assertSame(2, $column->nullCount()); + static::assertTrue($column->isNull(2)); + } + + public function test_map_columns_rebase_offsets_and_rekey_nulls(): void + { + $definition = map_schema('a', type_map(type_string(), type_integer()), nullable: true); + $column = ColumnMother::of($definition, [['x' => 1], null])->concat(ColumnMother::of($definition, [ + null, + ['y' => 2, 'z' => 3], + ])); + + static::assertSame([['x' => 1], null, null, ['y' => 2, 'z' => 3]], $column->values()); + static::assertTrue($column->isNull(2)); + } + + public function test_structure_columns(): void + { + $definition = structure_schema('a', type_structure(['x' => type_integer()]), nullable: true); + $column = ColumnMother::of($definition, [['x' => 1]])->concat(ColumnMother::of($definition, [ + null, + ['x' => 2], + ])); + + static::assertSame([['x' => 1], null, ['x' => 2]], $column->values()); + static::assertTrue($column->isNull(1)); + } + + public function test_constant_columns_with_the_same_value_collapse(): void + { + $backend = new PhpBackend(); + $column = $backend->constant(int_schema('a'), 7, 2)->concat($backend->constant(int_schema('a'), 7, 3)); + + static::assertInstanceOf(ConstantColumn::class, $column); + static::assertSame(5, $column->count()); + } + + public function test_constant_columns_with_different_values_expand(): void + { + $backend = new PhpBackend(); + $column = $backend->constant(int_schema('a'), 7, 2)->concat($backend->constant(int_schema('a'), 8, 1)); + + static::assertInstanceOf(ScalarColumn::class, $column); + static::assertSame([7, 7, 8], $column->values()); + } + + public function test_a_mixed_class_concat_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('cannot concat'); + + ColumnMother::of(int_schema('a'), [1])->concat((new PhpBackend())->constant(int_schema('a'), 7, 2)); + } + + public function test_container_columns_refuse_another_column_class(): void + { + $constant = (new PhpBackend())->constant(int_schema('a'), 1, 1); + $containers = [ + ColumnMother::of(list_schema('a', type_list(type_integer())), [[1]]), + ColumnMother::of(map_schema('a', type_map(type_string(), type_integer())), [['x' => 1]]), + ColumnMother::of(structure_schema('a', type_structure(['x' => type_integer()])), [['x' => 1]]), + ]; + + foreach ($containers as $container) { + try { + $container->concat($constant); + static::fail($container::class . ' concatenated another column class'); + } catch (InvalidArgumentException $e) { + static::assertStringContainsString('cannot concat', $e->getMessage()); + } + } + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnEncodeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnEncodeTest.php new file mode 100644 index 0000000000..48babf1a09 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnEncodeTest.php @@ -0,0 +1,115 @@ +}> + */ + public static function columns(): Generator + { + yield 'integer' => [ + ColumnMother::of(int_schema('id'), [1, 2]), + ['', '01000000000000000200000000000000'], + ]; + yield 'nullable string' => [ + ColumnMother::of(str_schema('name', nullable: true), ['ab', null]), + ['01', '000000000200000002000000', '6162'], + ]; + yield 'float' => [ColumnMother::of(float_schema('a'), [1.5]), ['', '000000000000f83f']]; + yield 'date before the epoch' => [ + ColumnMother::of(date_schema('a'), [new DateTimeImmutable('1969-12-29 00:00:00 UTC')]), + ['', 'fdffffff'], + ]; + yield 'boolean' => [ColumnMother::of(bool_schema('a'), [true, false, true]), ['', '05']]; + yield 'nullable boolean with a null slot at 0' => [ + ColumnMother::of(bool_schema('a', nullable: true), [true, null, true]), + ['05', '05'], + ]; + yield 'uuid' => [ + ColumnMother::of(uuid_schema('a'), ['6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f']), + ['', '6c2f1d4e8b3a4c5d9e6f0a1b2c3d4e5f'], + ]; + yield 'list with a null slot' => [ + ColumnMother::of(list_schema('a', type_list(type_integer()), nullable: true), [[1], null, [2, 3]]), + ['05', '00000000010000000100000003000000', '', '010000000000000002000000000000000300000000000000'], + ]; + yield 'map' => [ + ColumnMother::of(map_schema('a', type_map(type_string(), type_integer())), [['a' => 1]]), + ['', '0000000001000000', '', '', '0000000001000000', '61', '', '0100000000000000'], + ]; + yield 'structure: the child bit is 0 under a null parent' => [ + ColumnMother::of(structure_schema('a', type_structure(['x' => type_integer()]), nullable: true), [ + ['x' => 1], + null, + ]), + ['01', '01', '01000000000000000000000000000000'], + ]; + yield 'a null column has no buffers' => [ColumnMother::of(null_schema('a'), [null, null, null]), []]; + yield 'a null element of a structure has no buffers' => [ + ColumnMother::of(structure_schema('a', type_structure(['x' => type_integer(), 'n' => type_null()])), [ + ['x' => 1, 'n' => null], + ]), + ['', '', '0100000000000000'], + ]; + yield 'an optional null element of a structure has no buffers' => [ + ColumnMother::of( + structure_schema('a', type_structure(['x' => type_integer(), 'n' => type_optional(type_null())])), + [['x' => 1, 'n' => null]], + ), + ['', '', '0100000000000000'], + ]; + yield 'a constant is expanded' => [ + (new PhpBackend())->constant(int_schema('a'), 7, 2), + ['', '07000000000000000700000000000000'], + ]; + yield 'a slice re-bases offsets and re-packs validity from bit 0' => [ + ColumnMother::of(list_schema('a', type_list(type_integer()), nullable: true), [ + [1], + [2, 3], + null, + ])->slice(1, 2), + ['01', '000000000200000002000000', '', '02000000000000000300000000000000'], + ]; + } + + /** + * @param list $hex + */ + #[DataProvider('columns')] + public function test_encodes(Column $column, array $hex): void + { + static::assertSame($hex, array_map(bin2hex(...), $column->encode())); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnWithTypeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnWithTypeTest.php new file mode 100644 index 0000000000..605416f3e9 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnWithTypeTest.php @@ -0,0 +1,139 @@ +withType(type_integer())->values()); + } + + public function test_a_datetime_zone_change_keeps_the_instants(): void + { + $column = ColumnMother::of(datetime_schema('a'), [new DateTimeImmutable('2024-01-02 03:04:05 UTC')]); + $warsaw = $column->withType(type_datetime('Europe/Warsaw')); + $value = type_instance_of(DateTimeImmutable::class)->assert($warsaw->value(0)); + + static::assertSame($column->physicals(), $warsaw->physicals()); + static::assertInstanceOf(DateTimeImmutable::class, $value); + static::assertSame('Europe/Warsaw', $value->getTimezone()->getName()); + static::assertSame('2024-01-02 04:04:05', $value->format('Y-m-d H:i:s')); + } + + public function test_a_nullable_list_element_narrows_without_nulls(): void + { + $column = ColumnMother::of(list_schema('a', type_list(type_optional(type_integer()))), [[1, 2]]); + + static::assertSame([[1, 2]], $column->withType(type_list(type_integer()))->values()); + } + + public function test_a_nullable_list_element_with_a_null_does_not_narrow(): void + { + $column = ColumnMother::of(list_schema('a', type_list(type_optional(type_integer()))), [[1, null]]); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('1 null values under a required type'); + + $column->withType(type_list(type_integer())); + } + + public function test_a_map_retypes_its_values(): void + { + $column = ColumnMother::of(map_schema('a', type_map(type_string(), type_optional(type_integer()))), [[ + 'x' => 1, + ]]); + + static::assertSame([['x' => 1]], $column->withType(type_map(type_string(), type_integer()))->values()); + } + + public function test_an_optional_structure_element_with_an_absent_value_does_not_become_required(): void + { + $column = ColumnMother::of( + structure_schema('a', type_structure([ + 'x' => type_integer(), + 'y' => structure_element('y', type_integer(), true), + ])), + [['x' => 1]], + ); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('1 absent values under the required element "y"'); + + $column->withType(type_structure(['x' => type_integer(), 'y' => type_integer()])); + } + + public function test_an_optional_structure_element_without_absent_values_becomes_required(): void + { + $column = ColumnMother::of( + structure_schema( + 'a', + type_structure(['x' => type_integer(), 'y' => structure_element('y', type_integer(), true)]), + nullable: true, + ), + [['x' => 1, 'y' => 2], null], + ); + + static::assertSame( + [['x' => 1, 'y' => 2], null], + $column->withType(type_structure(['x' => type_integer(), 'y' => type_integer()]))->values(), + ); + } + + public function test_a_renamed_structure_element_is_another_kind(): void + { + $column = ColumnMother::of(structure_schema('a', type_structure(['x' => type_integer()])), [['x' => 1]]); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('structure{x: integer} and structure{z: integer} are different column kinds'); + + $column->withType(type_structure(['z' => type_integer()])); + } + + public function test_an_integer_does_not_become_a_string(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('integer and string are different column kinds'); + + ColumnMother::of(int_schema('id'), [1])->withType(type_string()); + } + + public function test_an_enum_does_not_change_its_class(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('are different column kinds'); + + ColumnMother::of( + enum_schema('a', BackedStringEnum::class), + [BackedStringEnum::one], + )->withType(type_enum(BackedIntEnum::class)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php new file mode 100644 index 0000000000..a16df60540 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php @@ -0,0 +1,44 @@ +builder(str_schema('a')); + $default->append('x'); + $php = (new PhpBackend())->builder(str_schema('a')); + $php->append('x'); + + static::assertEquals($php->finish(), $default->finish()); + } + + public function test_constant_is_what_the_php_backend_builds(): void + { + static::assertEquals( + (new PhpBackend())->constant(int_schema('a'), 7, 3), + (new DefaultBackend())->constant(int_schema('a'), 7, 3), + ); + } + + public function test_decode_is_what_the_php_backend_decodes(): void + { + $buffers = ColumnMother::of(int_schema('a', nullable: true), [1, null])->encode(); + + static::assertEquals( + (new PhpBackend())->decode(int_schema('a', nullable: true), $buffers, 2, 1), + (new DefaultBackend())->decode(int_schema('a', nullable: true), $buffers, 2, 1), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BooleanLayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BooleanLayoutTest.php new file mode 100644 index 0000000000..4c41264f34 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BooleanLayoutTest.php @@ -0,0 +1,50 @@ +encode([true, null, true, false]))); + static::assertSame(['ff01'], array_map(bin2hex(...), (new BooleanLayout())->encode(array_fill(0, 9, true)))); + static::assertSame(['ff'], array_map(bin2hex(...), (new BooleanLayout())->encode(array_fill(0, 8, true)))); + } + + public function test_round_trips(): void + { + $layout = new BooleanLayout(); + $values = [true, null, false, true, true, true, true, true, false]; + + static::assertSame($values, $layout->decode(new Buffers($layout->encode($values)), 9, [ + true, + false, + true, + true, + true, + true, + true, + true, + true, + ])); + } + + public function test_refuses_a_short_buffer(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Boolean values buffer of 1 bytes, expected 2 for 9 rows'); + + (new BooleanLayout())->decode(new Buffers(["\xFF"]), 9, array_fill(0, 9, true)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BuffersTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BuffersTest.php new file mode 100644 index 0000000000..852e3142e1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BuffersTest.php @@ -0,0 +1,34 @@ +remaining()); + static::assertSame('a', $buffers->next()); + static::assertSame(1, $buffers->remaining()); + static::assertSame('b', $buffers->next()); + static::assertSame(0, $buffers->remaining()); + } + + public function test_refuses_when_exhausted(): void + { + $buffers = new Buffers(['a']); + $buffers->next(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column buffers exhausted'); + + $buffers->next(); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/CastingColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/CastingColumnBuilderTest.php new file mode 100644 index 0000000000..7f6c277fc1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/CastingColumnBuilderTest.php @@ -0,0 +1,89 @@ +builder(int_schema('a', nullable: true)); + $builder->append('1'); + $builder->appendMany(['2', null]); + + static::assertSame(3, $builder->count()); + static::assertSame([1, 2, null], $builder->finish()->physicals()); + } + + public function test_append_many_is_atomic_on_a_refusal(): void + { + $builder = (new PhpBackend())->builder(int_schema('a')); + + try { + $builder->appendMany(['1', 'x']); + } catch (SchemaMismatchException) { + } + + static::assertSame(0, $builder->count()); + } + + public function test_append_many_refuses_null_under_not_null(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "a" (row 1): could not convert null to integer, column is not nullable'); + + (new PhpBackend()) + ->builder(int_schema('a')) + ->appendMany([1, null]); + } + + public function test_the_null_definition_accepts_null(): void + { + $builder = (new PhpBackend())->builder(null_schema('a')); + $builder->append(null); + $builder->appendMany([null]); + + static::assertSame(2, $builder->count()); + } + + public function test_append_from_copies_a_physical_cell(): void + { + $source = ColumnMother::of(int_schema('a', nullable: true), [1, null, 3]); + $builder = (new PhpBackend())->builder(int_schema('a', nullable: true)); + $builder->appendFrom($source, 2); + $builder->appendFrom($source, 1); + $builder->appendTake($source, [0, 1, 2]); + + static::assertSame([3, null, 1, null, 3], $builder->finish()->physicals()); + } + + public function test_append_from_refuses_null_under_not_null(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage('could not convert null to integer, column is not nullable'); + + (new PhpBackend()) + ->builder(int_schema('a')) + ->appendFrom(ColumnMother::of(int_schema('a', nullable: true), [null]), 0); + } + + public function test_append_take_refuses_null_under_not_null(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage('could not convert null to integer, column is not nullable'); + + (new PhpBackend()) + ->builder(int_schema('a')) + ->appendTake(ColumnMother::of(int_schema('a', nullable: true), [1, null]), [0, 1]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php new file mode 100644 index 0000000000..fe0006d346 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php @@ -0,0 +1,67 @@ +decode($type, new Buffers($column->encode()), 2, 0); + + static::assertSame([[1, null], [null]], $decoded->values()); + } + + public function test_a_null_kind_consumes_no_buffer(): void + { + $type = type_structure(['n' => type_optional(type_null()), 'a' => type_integer()]); + $column = ColumnMother::of(structure_schema('s', $type), [['n' => null, 'a' => 1]]); + $buffers = new Buffers($column->encode()); + $decoded = (new ColumnDecoder())->decode($type, $buffers, 1, 0); + + static::assertSame(0, $buffers->remaining()); + static::assertSame([['n' => null, 'a' => 1]], $decoded->values()); + } + + public function test_a_top_level_null_column(): void + { + static::assertInstanceOf(ConstantColumn::class, (new ColumnDecoder())->decode( + type_null(), + new Buffers([]), + 3, + 3, + )); + static::assertInstanceOf(ConstantColumn::class, (new ColumnDecoder())->decode( + type_null(), + new Buffers([]), + 3, + -1, + )); + } + + public function test_refuses_a_null_count_other_than_the_bitmap(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column null count 1 disagrees with its validity bitmap (0 nulls in 1 rows)'); + + (new ColumnDecoder())->decode(type_integer(), new Buffers(['', "\0\0\0\0\0\0\0\0"]), 1, 1); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ConstantColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ConstantColumnTest.php new file mode 100644 index 0000000000..1e974d8220 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ConstantColumnTest.php @@ -0,0 +1,126 @@ +count()); + static::assertSame('UTC', $column->at(2)); + static::assertSame(['UTC', 'UTC', 'UTC'], $column->physicals()); + static::assertEquals(new DateTimeZone('UTC'), $column->value(1)); + static::assertEquals( + [new DateTimeZone('UTC'), new DateTimeZone('UTC'), new DateTimeZone('UTC')], + $column->values(), + ); + static::assertFalse($column->isNull(0)); + static::assertSame(0, $column->nullCount()); + static::assertSame(2, $column->slice(1, 2)->count()); + static::assertSame(4, $column->take([0, 0, 1, 2])->count()); + static::assertEquals(type_time_zone(), $column->type()); + } + + public function test_zero_rows(): void + { + $column = new ConstantColumn(type_integer(), new IdentityPhysical(), 1, 0); + + static::assertSame([], $column->physicals()); + static::assertSame([], $column->values()); + } + + public function test_null(): void + { + $column = new ConstantColumn(type_optional(type_integer()), new NullPhysical(), null, 2); + + static::assertTrue($column->isNull(0)); + static::assertSame(2, $column->nullCount()); + static::assertNull($column->value(0)); + static::assertSame(['00', str_repeat('0', 32)], array_map(bin2hex(...), $column->encode())); + } + + public function test_expands_to_the_column_kind(): void + { + $column = new ConstantColumn(type_list(type_integer()), new IdentityPhysical(), [1, 2], 2); + $expanded = $column->expand(); + + static::assertInstanceOf(ListColumn::class, $expanded); + static::assertSame([[1, 2], [1, 2]], $expanded->physicals()); + } + + public function test_the_null_kind_does_not_expand_and_has_no_buffers(): void + { + foreach ([type_null(), type_optional(type_null())] as $type) { + $column = new ConstantColumn($type, new NullPhysical(), null, 2); + + static::assertTrue($column->isNullKind()); + static::assertSame($column, $column->expand()); + static::assertSame([], $column->encode()); + } + } + + public function test_concat_with_a_scalar_column_expands(): void + { + $constant = new ConstantColumn(type_integer(), new IdentityPhysical(), 7, 1); + + static::assertSame([7, 1, 2], $constant->concat(ColumnMother::of(int_schema('a'), [1, 2]))->physicals()); + static::assertSame( + [7, 8, 8], + $constant->concat(new ConstantColumn(type_integer(), new IdentityPhysical(), 8, 2))->physicals(), + ); + } + + public function test_with_type_restamps_the_value(): void + { + $column = (new PhpBackend())->constant( + datetime_schema('a'), + new DateTimeImmutable('2024-01-02 03:04:05 UTC'), + 2, + ); + $warsaw = type_instance_of(DateTimeImmutable::class)->assert( + $column->withType(type_datetime('Europe/Warsaw'))->value(1), + ); + + static::assertSame('2024-01-02 04:04:05 Europe/Warsaw', $warsaw->format('Y-m-d H:i:s e')); + } + + public function test_with_type_refuses_another_column_kind(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('integer and string are different column kinds'); + + (new PhpBackend()) + ->constant(int_schema('a'), 1, 2) + ->withType(type_string()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DatePhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DatePhysicalTest.php new file mode 100644 index 0000000000..323fec34ca --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DatePhysicalTest.php @@ -0,0 +1,46 @@ +toPhysical( + new DateTimeImmutable('2024-03-05 00:30:00', new DateTimeZone('Asia/Tokyo')), + ), + ); + static::assertSame(-1, (new DatePhysical())->toPhysical(new DateTimeImmutable('1969-12-31 23:59:59 UTC'))); + } + + public function test_reads_back_midnight_utc(): void + { + $physical = new DatePhysical(); + $value = type_instance_of(DateTimeImmutable::class)->assert($physical->fromPhysical(-1)); + $all = type_instance_of(DateTimeImmutable::class)->assert($physical->fromPhysicalAll([-1, null])[0]); + + static::assertSame('1969-12-31 00:00:00 UTC', $value->format('Y-m-d H:i:s e')); + static::assertSame('1969-12-31 00:00:00 UTC', $all->format('Y-m-d H:i:s e')); + static::assertNull($physical->fromPhysicalAll([-1, null])[1]); + } + + public function test_refuses_a_day_outside_the_i32_range(): void + { + $this->expectException(CastingException::class); + $this->expectExceptionMessage('outside the day range of a date column'); + + (new DatePhysical())->toPhysical(new DateTimeImmutable('@' . ((2 ** 31) * 86_400))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DateTimePhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DateTimePhysicalTest.php new file mode 100644 index 0000000000..e3057c888e --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DateTimePhysicalTest.php @@ -0,0 +1,50 @@ +toPhysical($value)); + static::assertEquals($value, $physical->fromPhysical($microseconds)); + static::assertEquals([$value, null], $physical->fromPhysicalAll([$microseconds, null])); + } + + public function test_reads_back_in_the_zone(): void + { + $physical = new DateTimePhysical(new DateTimeZone('Asia/Tokyo')); + $value = type_instance_of(DateTimeImmutable::class)->assert($physical->fromPhysical(0)); + $all = type_instance_of(DateTimeImmutable::class)->assert($physical->fromPhysicalAll([0])[0]); + + static::assertSame('1970-01-01 09:00:00 Asia/Tokyo', $value->format('Y-m-d H:i:s e')); + static::assertSame('1970-01-01 09:00:00 Asia/Tokyo', $all->format('Y-m-d H:i:s e')); + } + + public function test_refuses_a_value_outside_the_microsecond_range(): void + { + $this->expectException(CastingException::class); + $this->expectExceptionMessage('outside the microsecond range of a datetime column'); + + (new DateTimePhysical(new DateTimeZone('UTC')))->toPhysical(new DateTimeImmutable('@9223372036855')); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DaysFromCivilTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DaysFromCivilTest.php new file mode 100644 index 0000000000..4b955a6c34 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DaysFromCivilTest.php @@ -0,0 +1,26 @@ +of($year, $month, $day)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/EnumPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/EnumPhysicalTest.php new file mode 100644 index 0000000000..cc4a409a37 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/EnumPhysicalTest.php @@ -0,0 +1,21 @@ +toPhysical(BasicEnum::one)); + static::assertSame(BasicEnum::one, $physical->fromPhysical('one')); + static::assertSame([BasicEnum::two, null], $physical->fromPhysicalAll(['two', null])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/FixedBinary16LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/FixedBinary16LayoutTest.php new file mode 100644 index 0000000000..d698c858ba --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/FixedBinary16LayoutTest.php @@ -0,0 +1,40 @@ +encode([str_repeat('a', 16), null]), + ); + } + + public function test_round_trips(): void + { + $layout = new FixedBinary16Layout(); + $values = [str_repeat('a', 16), null, str_repeat('b', 16)]; + + static::assertSame($values, $layout->decode(new Buffers($layout->encode($values)), 3, [true, false, true])); + static::assertSame([], $layout->decode(new Buffers(['']), 0, [])); + } + + public function test_refuses_a_wrong_length(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('FixedBinary16 values buffer of 15 bytes, expected 16 for 1 rows'); + + (new FixedBinary16Layout())->decode(new Buffers([str_repeat('a', 15)]), 1, [true]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Float64LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Float64LayoutTest.php new file mode 100644 index 0000000000..fde9eeee8b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Float64LayoutTest.php @@ -0,0 +1,43 @@ +encode([1.5, null])), + ); + } + + public function test_round_trips(): void + { + $layout = new Float64Layout(); + + static::assertSame( + [-0.25, null], + $layout->decode(new Buffers($layout->encode([-0.25, null])), 2, [true, false]), + ); + static::assertSame([], $layout->decode(new Buffers(['']), 0, [])); + } + + public function test_refuses_a_wrong_length(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Float64 values buffer of 9 bytes, expected 8 for 1 rows'); + + (new Float64Layout())->decode(new Buffers([str_repeat("\0", 9)]), 1, [true]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php new file mode 100644 index 0000000000..d493650b4f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php @@ -0,0 +1,28 @@ += 8.4.0')] +final class HtmlDocumentPhysicalTest extends TestCase +{ + public function test_the_markup(): void + { + $document = type_html()->cast('

a

'); + $physical = new HtmlDocumentPhysical(); + $markup = type_string()->assert($physical->toPhysical($document)); + + static::assertIsString($markup); + static::assertStringContainsString('

a

', $markup); + static::assertEquals($markup, $physical->toPhysical($physical->fromPhysical($markup))); + static::assertNull($physical->fromPhysicalAll([$markup, null])[1]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php new file mode 100644 index 0000000000..be5de3a483 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php @@ -0,0 +1,26 @@ += 8.4.0')] +final class HtmlElementPhysicalTest extends TestCase +{ + public function test_the_markup(): void + { + $physical = new HtmlElementPhysical(); + $markup = type_string()->assert($physical->toPhysical(type_html_element()->cast('

a

'))); + + static::assertSame('

a

', $markup); + static::assertSame('

a

', $physical->toPhysical($physical->fromPhysical('

a

'))); + static::assertNull($physical->fromPhysicalAll(['

a

', null])[1]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/IdentityPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/IdentityPhysicalTest.php new file mode 100644 index 0000000000..f9320df5b8 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/IdentityPhysicalTest.php @@ -0,0 +1,20 @@ +toPhysical('a')); + static::assertSame(1.5, $physical->fromPhysical(1.5)); + static::assertSame([1, null, true], $physical->fromPhysicalAll([1, null, true])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int32LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int32LayoutTest.php new file mode 100644 index 0000000000..0716ba4d61 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int32LayoutTest.php @@ -0,0 +1,47 @@ +encode([-3, null, 1])), + ); + } + + public function test_round_trips_signed_values(): void + { + $layout = new Int32Layout(); + $values = [-2_147_483_648, null, 2_147_483_647, -3, 0]; + + static::assertSame($values, $layout->decode(new Buffers($layout->encode($values)), 5, [ + true, + false, + true, + true, + true, + ])); + static::assertSame([], $layout->decode(new Buffers(['']), 0, [])); + } + + public function test_refuses_a_wrong_length(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Int32 values buffer of 3 bytes, expected 4 for 1 rows'); + + (new Int32Layout())->decode(new Buffers(["\0\0\0"]), 1, [true]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int64LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int64LayoutTest.php new file mode 100644 index 0000000000..36727b58ef --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int64LayoutTest.php @@ -0,0 +1,47 @@ +encode([1, null, -1])), + ); + } + + public function test_round_trips_the_extremes(): void + { + $layout = new Int64Layout(); + + static::assertSame( + [PHP_INT_MIN, null, PHP_INT_MAX], + $layout->decode(new Buffers($layout->encode([PHP_INT_MIN, null, PHP_INT_MAX])), 3, [true, false, true]), + ); + } + + public function test_decodes_zero_rows(): void + { + static::assertSame([], (new Int64Layout())->decode(new Buffers(['']), 0, [])); + } + + public function test_refuses_a_wrong_length(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Int64 values buffer of 7 bytes, expected 8 for 1 rows'); + + (new Int64Layout())->decode(new Buffers(["\0\0\0\0\0\0\0"]), 1, [true]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonFactoryTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonFactoryTest.php new file mode 100644 index 0000000000..156008240d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonFactoryTest.php @@ -0,0 +1,28 @@ +create('{"a":1}')); + static::assertEquals(Json::fromString('[1,2]'), (new JsonFactory())->create('[1,2]')); + static::assertTrue( + (new JsonFactory()) + ->create('{}') + ->isObject(), + ); + static::assertFalse( + (new JsonFactory()) + ->create('[]') + ->isObject(), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonPhysicalTest.php new file mode 100644 index 0000000000..8fd48f25ee --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonPhysicalTest.php @@ -0,0 +1,21 @@ +toPhysical(Json::fromString('{"a":1}'))); + static::assertEquals(Json::fromString('{"a":1}'), $physical->fromPhysical('{"a":1}')); + static::assertEquals([Json::fromString('[1]'), null], $physical->fromPhysicalAll(['[1]', null])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/LayoutForTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/LayoutForTest.php new file mode 100644 index 0000000000..0538bece0a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/LayoutForTest.php @@ -0,0 +1,89 @@ +, class-string}> + */ + public static function types(): Generator + { + yield 'integer' => [type_integer(), Int64Layout::class]; + yield 'positive integer' => [type_positive_integer(), Int64Layout::class]; + yield 'datetime' => [type_datetime(), Int64Layout::class]; + yield 'time' => [type_time(), Int64Layout::class]; + yield 'optional integer' => [type_optional(type_integer()), Int64Layout::class]; + yield 'float' => [type_float(), Float64Layout::class]; + yield 'date' => [type_date(), Int32Layout::class]; + yield 'boolean' => [type_boolean(), BooleanLayout::class]; + yield 'string' => [type_string(), Utf8Layout::class]; + yield 'non-empty string' => [type_non_empty_string(), Utf8Layout::class]; + yield 'numeric string' => [type_numeric_string(), Utf8Layout::class]; + yield 'class string' => [type_class_string(), Utf8Layout::class]; + yield 'timezone' => [type_time_zone(), Utf8Layout::class]; + yield 'json' => [type_json(), Utf8Layout::class]; + yield 'enum' => [type_enum(BasicEnum::class), Utf8Layout::class]; + yield 'xml' => [type_xml(), Utf8Layout::class]; + yield 'xml element' => [type_xml_element(), Utf8Layout::class]; + yield 'html' => [type_html(), Utf8Layout::class]; + yield 'html element' => [type_html_element(), Utf8Layout::class]; + yield 'uuid' => [type_uuid(), FixedBinary16Layout::class]; + } + + /** + * @param Type $type + * @param class-string $class + */ + #[DataProvider('types')] + public function test_maps_the_type_to_its_layout(Type $type, string $class): void + { + static::assertInstanceOf($class, (new LayoutFor())->type($type)); + } + + public function test_a_container_has_no_scalar_layout(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('type list has no scalar layout'); + + (new LayoutFor())->type(type_list(type_integer())); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php new file mode 100644 index 0000000000..432865bafa --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php @@ -0,0 +1,36 @@ +appendPhysical([5 => 1, 9 => 2]); + $builder->appendPhysicalMany([null, [], [3]]); + + static::assertSame(4, $builder->count()); + + $column = $builder->finish(); + + static::assertInstanceOf(ListColumn::class, $column); + static::assertSame([0, 2, 2, 2, 3], $column->offsets); + static::assertSame([1 => true], $column->nulls); + static::assertSame([[1, 2], null, [], [3]], $column->physicals()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnTest.php new file mode 100644 index 0000000000..16a931a028 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnTest.php @@ -0,0 +1,61 @@ +count()); + static::assertSame(1, $column->nullCount()); + static::assertSame(['UTC', 'Europe/Warsaw'], $column->at(3)); + static::assertNull($column->at(1)); + static::assertSame([], $column->at(2)); + static::assertSame([['UTC'], null, [], ['UTC', 'Europe/Warsaw']], $column->physicals()); + static::assertEquals([new DateTimeZone('UTC'), new DateTimeZone('Europe/Warsaw')], $column->value(3)); + static::assertNull($column->value(1)); + static::assertEquals( + [[new DateTimeZone('UTC')], null, [], [new DateTimeZone('UTC'), new DateTimeZone('Europe/Warsaw')]], + $column->values(), + ); + static::assertTrue($column->isNull(1)); + static::assertFalse($column->isNull(2)); + static::assertEquals(type_list(type_time_zone()), $column->type()); + } + + public function test_slice_and_take_rebuild_offsets_from_zero(): void + { + $column = ColumnMother::of(list_schema('a', type_list(type_time_zone()), nullable: true), [ + ['UTC'], + null, + ['Europe/Warsaw', 'UTC'], + ]); + $taken = $column->take([2, 1, 0]); + + static::assertInstanceOf(ListColumn::class, $taken); + static::assertSame([0, 2, 2, 3], $taken->offsets); + static::assertSame([1 => true], $taken->nulls); + static::assertSame([['Europe/Warsaw', 'UTC'], null, ['UTC']], $taken->physicals()); + static::assertSame([null, ['Europe/Warsaw', 'UTC']], $column->slice(1, 2)->physicals()); + static::assertSame(0, $column->slice(0, 0)->count()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListPhysicalTest.php new file mode 100644 index 0000000000..c8b54febb0 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListPhysicalTest.php @@ -0,0 +1,22 @@ +toPhysical([1 => new DateTimeZone('UTC'), 3 => null])); + static::assertEquals([new DateTimeZone('UTC'), null], $physical->fromPhysical(['UTC', null])); + static::assertEquals([[new DateTimeZone('UTC')], null], $physical->fromPhysicalAll([['UTC'], null])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnBuilderTest.php new file mode 100644 index 0000000000..0d60d4a2e9 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnBuilderTest.php @@ -0,0 +1,39 @@ +appendPhysical(['a' => 1, 'b' => 2]); + $builder->appendPhysicalMany([null, ['c' => 3]]); + + static::assertSame(3, $builder->count()); + + $column = $builder->finish(); + + static::assertInstanceOf(MapColumn::class, $column); + static::assertSame([0, 2, 2, 3], $column->offsets); + static::assertSame([1 => true], $column->nulls); + static::assertSame(['a', 'b', 'c'], $column->keys->physicals()); + static::assertSame([1, 2, 3], $column->values->physicals()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnTest.php new file mode 100644 index 0000000000..620fe52a65 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnTest.php @@ -0,0 +1,68 @@ + 'UTC'], + null, + [], + ['y' => 'UTC', 'z' => 'Europe/Warsaw'], + ]); + + static::assertInstanceOf(MapColumn::class, $column); + static::assertSame(4, $column->count()); + static::assertSame(1, $column->nullCount()); + static::assertSame(['y' => 'UTC', 'z' => 'Europe/Warsaw'], $column->at(3)); + static::assertNull($column->at(1)); + static::assertSame([], $column->at(2)); + static::assertSame([['x' => 'UTC'], null, [], ['y' => 'UTC', 'z' => 'Europe/Warsaw']], $column->physicals()); + static::assertEquals( + ['y' => new DateTimeZone('UTC'), 'z' => new DateTimeZone('Europe/Warsaw')], + $column->value(3), + ); + static::assertNull($column->value(1)); + static::assertEquals( + [ + ['x' => new DateTimeZone('UTC')], + null, + [], + ['y' => new DateTimeZone('UTC'), 'z' => new DateTimeZone('Europe/Warsaw')], + ], + $column->values(), + ); + static::assertTrue($column->isNull(1)); + static::assertEquals(type_map(type_string(), type_time_zone()), $column->type()); + } + + public function test_slice_and_take_rebuild_offsets_from_zero(): void + { + $column = ColumnMother::of(map_schema('a', type_map(type_string(), type_string()), nullable: true), [ + ['a' => 'x'], + null, + ['b' => 'y', 'c' => 'z'], + ]); + $taken = $column->take([2, 1, 0]); + + static::assertInstanceOf(MapColumn::class, $taken); + static::assertSame([0, 2, 2, 3], $taken->offsets); + static::assertSame([['b' => 'y', 'c' => 'z'], null, ['a' => 'x']], $taken->values()); + static::assertSame([null, ['b' => 'y', 'c' => 'z']], $column->slice(1, 2)->values()); + static::assertSame(0, $column->slice(0, 0)->count()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapPhysicalTest.php new file mode 100644 index 0000000000..43f9524834 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapPhysicalTest.php @@ -0,0 +1,28 @@ + 'UTC', 'b' => null], + $physical->toPhysical(['a' => new DateTimeZone('UTC'), 'b' => null]), + ); + static::assertEquals( + ['a' => new DateTimeZone('UTC'), 'b' => null], + $physical->fromPhysical(['a' => 'UTC', 'b' => null]), + ); + static::assertEquals([[5 => new DateTimeZone('UTC')], null], $physical->fromPhysicalAll([[5 => 'UTC'], null])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullColumnBuilderTest.php new file mode 100644 index 0000000000..54741532e7 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullColumnBuilderTest.php @@ -0,0 +1,28 @@ +appendPhysical(null); + $builder->appendPhysicalMany([null, null]); + + static::assertSame(3, $builder->count()); + + $column = $builder->finish(); + + static::assertInstanceOf(ConstantColumn::class, $column); + static::assertSame(3, $column->nullCount()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullCountTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullCountTest.php new file mode 100644 index 0000000000..ba4f3f5c16 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullCountTest.php @@ -0,0 +1,17 @@ +of([null, 0, '', null, false])); + static::assertSame(0, (new NullCount())->of([])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullPhysicalTest.php new file mode 100644 index 0000000000..1a003f45b6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullPhysicalTest.php @@ -0,0 +1,21 @@ +toPhysical('a')); + static::assertNull($physical->fromPhysical('a')); + static::assertSame([null, null], $physical->fromPhysicalAll([1, null])); + static::assertSame([], $physical->fromPhysicalAll([])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php new file mode 100644 index 0000000000..e589b1fa12 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php @@ -0,0 +1,62 @@ +pack([0, 2, 2]))); + } + + public function test_packs_the_last_i32_offset(): void + { + static::assertSame('00000000ffffff7f', bin2hex((new Offsets())->pack([0, 2_147_483_647]))); + } + + public function test_refuses_an_offset_past_the_i32_range(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Offsets exceed the i32 range of a batch buffer: the last offset is 2147483648'); + + (new Offsets())->pack([0, 2_147_483_648]); + } + + public function test_unpacks(): void + { + static::assertSame([0, 2, 2], (new Offsets())->unpack((string) hex2bin('000000000200000002000000'), 2, 'List')); + } + + public function test_unpack_refuses_a_wrong_length(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('List offsets buffer of 8 bytes, expected 12 for 2 rows'); + + (new Offsets())->unpack((string) hex2bin('0000000002000000'), 2, 'List'); + } + + public function test_unpack_refuses_offsets_that_do_not_start_at_0(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('List offsets start at 1, not 0'); + + (new Offsets())->unpack((string) hex2bin('0100000002000000'), 1, 'List'); + } + + public function test_unpack_refuses_offsets_that_decrease(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('List offsets are not monotonic: offset 1 is 3, offset 2 is 2'); + + (new Offsets())->unpack((string) hex2bin('000000000300000002000000'), 2, 'List'); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalBuilderForTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalBuilderForTest.php new file mode 100644 index 0000000000..f06dd1e386 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalBuilderForTest.php @@ -0,0 +1,53 @@ +type(type_integer())); + static::assertInstanceOf(ListColumnBuilder::class, $builders->type(type_optional(type_list(type_integer())))); + static::assertInstanceOf(MapColumnBuilder::class, $builders->type(type_map(type_string(), type_integer()))); + static::assertInstanceOf(StructColumnBuilder::class, $builders->type(type_structure(['a' => type_integer()]))); + static::assertInstanceOf(NullColumnBuilder::class, $builders->type(type_null())); + } + + public function test_an_optional_container_keeps_its_optional_type(): void + { + $builder = (new PhysicalBuilderFor())->type(type_optional(type_list(type_integer()))); + $builder->appendPhysical(null); + + static::assertEquals(type_optional(type_list(type_integer())), $builder->finish()->type()); + } + + public function test_refuses_a_mixed_element(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('a mixed element has no column kind'); + + (new PhysicalBuilderFor())->type(type_list(type_mixed())); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php new file mode 100644 index 0000000000..39d640571d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php @@ -0,0 +1,136 @@ +, class-string}> + */ + public static function types(): Generator + { + yield 'integer' => [type_integer(), IdentityPhysical::class]; + yield 'positive integer' => [type_positive_integer(), IdentityPhysical::class]; + yield 'float' => [type_float(), IdentityPhysical::class]; + yield 'boolean' => [type_boolean(), IdentityPhysical::class]; + yield 'string' => [type_string(), IdentityPhysical::class]; + yield 'non-empty string' => [type_non_empty_string(), IdentityPhysical::class]; + yield 'numeric string' => [type_numeric_string(), IdentityPhysical::class]; + yield 'class string' => [type_class_string(), IdentityPhysical::class]; + yield 'optional integer' => [type_optional(type_integer()), IdentityPhysical::class]; + yield 'datetime' => [type_datetime(), DateTimePhysical::class]; + yield 'date' => [type_date(), DatePhysical::class]; + yield 'time' => [type_time(), TimePhysical::class]; + yield 'uuid' => [type_uuid(), UuidPhysical::class]; + yield 'timezone' => [type_time_zone(), TimeZonePhysical::class]; + yield 'json' => [type_json(), JsonPhysical::class]; + yield 'enum' => [type_enum(BasicEnum::class), EnumPhysical::class]; + yield 'xml' => [type_xml(), XmlDocumentPhysical::class]; + yield 'xml element' => [type_xml_element(), XmlElementPhysical::class]; + yield 'html' => [type_html(), HtmlDocumentPhysical::class]; + yield 'html element' => [type_html_element(), HtmlElementPhysical::class]; + yield 'list' => [type_list(type_integer()), ListPhysical::class]; + yield 'map' => [type_map(type_string(), type_integer()), MapPhysical::class]; + yield 'structure' => [type_structure(['a' => type_integer()]), StructPhysical::class]; + yield 'null' => [type_null(), NullPhysical::class]; + } + + /** + * @return Generator, string}> + */ + public static function refusals(): Generator + { + yield 'mixed' => [type_mixed(), 'a mixed element has no column kind, declare it or use json']; + yield 'nested mixed' => [type_map(type_string(), type_mixed()), 'a mixed element has no column kind']; + yield 'unit enum wildcard' => [type_enum(UnitEnum::class), 'declare the concrete enum class']; + yield 'backed enum wildcard' => [type_enum(BackedEnum::class), 'declare the concrete enum class']; + yield 'instance of' => [type_instance_of(stdClass::class), 'type object has no column kind']; + yield 'structure element' => [type_structure(['a' => type_mixed()]), 'a mixed element has no column kind']; + } + + /** + * @param Type $type + * @param class-string $class + */ + #[DataProvider('types')] + public function test_maps_the_type_to_its_physical(Type $type, string $class): void + { + static::assertInstanceOf($class, (new PhysicalFor())->type($type)); + } + + /** + * @param Type $type + */ + #[DataProvider('refusals')] + public function test_refuses(Type $type, string $message): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage($message); + + (new PhysicalFor())->type($type); + } + + public function test_structure_elements_are_keyed_by_name(): void + { + static::assertSame( + ['a', 'b'], + array_keys((new PhysicalFor())->elements(type_structure(['a' => type_integer(), 'b' => type_string()]))), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/RetypeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/RetypeTest.php new file mode 100644 index 0000000000..9c987cae65 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/RetypeTest.php @@ -0,0 +1,103 @@ +, Type, int}> + */ + public static function accepted(): Generator + { + yield 'same type' => [type_integer(), type_integer(), 0]; + yield 'optional to required without nulls' => [type_optional(type_integer()), type_integer(), 0]; + yield 'required to optional with nulls' => [type_integer(), type_optional(type_integer()), 3]; + yield 'datetime zone change' => [type_datetime('UTC'), type_datetime('Europe/Warsaw'), 0]; + yield 'same enum class' => [type_enum(BackedIntEnum::class), type_enum(BackedIntEnum::class), 0]; + yield 'same structure element names' => [ + type_structure(['a' => type_integer()]), + type_structure(['a' => type_optional(type_integer())]), + 0, + ]; + } + + /** + * @return Generator, Type, int, string}> + */ + public static function refused(): Generator + { + yield 'optional to required with nulls' => [ + type_optional(type_integer()), + type_integer(), + 2, + '2 null values under a required type', + ]; + yield 'integer to string' => [ + type_integer(), + type_string(), + 0, + 'integer and string are different column kinds', + ]; + yield 'enum class change' => [ + type_enum(BackedIntEnum::class), + type_enum(BackedStringEnum::class), + 0, + 'are different column kinds', + ]; + yield 'structure element rename' => [ + type_structure(['a' => type_integer()]), + type_structure(['b' => type_integer()]), + 0, + 'are different column kinds', + ]; + yield 'structure element reorder' => [ + type_structure(['a' => type_integer(), 'b' => type_integer()]), + type_structure(['b' => type_integer(), 'a' => type_integer()]), + 0, + 'are different column kinds', + ]; + } + + /** + * @param Type $from + * @param Type $to + */ + #[DataProvider('accepted')] + public function test_accepts(Type $from, Type $to, int $nullCount): void + { + (new Retype())->assert($from, $to, $nullCount); + + $this->addToAssertionCount(1); + } + + /** + * @param Type $from + * @param Type $to + */ + #[DataProvider('refused')] + public function test_refuses(Type $from, Type $to, int $nullCount, string $message): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage($message); + + (new Retype())->assert($from, $to, $nullCount); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php new file mode 100644 index 0000000000..e62a316812 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php @@ -0,0 +1,42 @@ +appendPhysical(1); + $builder->appendPhysical(null); + $builder->appendPhysicalMany([null, 4]); + + static::assertSame(4, $builder->count()); + + $column = $builder->finish(); + + static::assertSame([1, null, null, 4], $column->physicals()); + static::assertSame(2, $column->nullCount()); + } + + public function test_takes_the_null_count_the_caller_already_counted(): void + { + $builder = new ScalarColumnBuilder(type_optional(type_integer()), new IdentityPhysical()); + $builder->appendPhysicalMany([1, null], 1); + $builder->appendPhysicalMany([null, null, 5], 2); + + $column = $builder->finish(); + + static::assertSame([1, null, null, null, 5], $column->physicals()); + static::assertSame(3, $column->nullCount()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnTest.php new file mode 100644 index 0000000000..fab8565de0 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnTest.php @@ -0,0 +1,55 @@ +count()); + static::assertSame('UTC', $column->at(0)); + static::assertNull($column->at(1)); + static::assertSame(['UTC', null], $column->physicals()); + static::assertEquals(new DateTimeZone('UTC'), $column->value(0)); + static::assertNull($column->value(1)); + static::assertTrue($column->isNull(1)); + static::assertFalse($column->isNull(0)); + static::assertSame(1, $column->nullCount()); + static::assertEquals(type_time_zone(), $column->type()); + } + + public function test_slice_and_take_recount_nulls(): void + { + $column = ColumnMother::of(int_schema('a', nullable: true), [1, null, 3, null]); + + static::assertSame([null, 3], $column->slice(1, 2)->physicals()); + static::assertSame(1, $column->slice(1, 2)->nullCount()); + static::assertSame(0, $column->slice(2, 1)->nullCount()); + static::assertSame([3, 1, 3], $column->take([2, 0, 2])->physicals()); + static::assertSame(0, $column->take([2, 0, 2])->nullCount()); + static::assertSame(2, $column->take([1, 3, 0])->nullCount()); + } + + public function test_a_column_without_nulls_slices_without_counting(): void + { + $column = new ScalarColumn(type_time_zone(), new TimeZonePhysical(), ['UTC', 'UTC'], 0); + + static::assertSame(0, $column->slice(0, 1)->nullCount()); + static::assertSame(0, $column->take([1])->nullCount()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php new file mode 100644 index 0000000000..ba86e0cf97 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php @@ -0,0 +1,36 @@ + type_integer(), 'b' => type_integer()]), [ + 'a' => new ScalarColumnBuilder(type_integer(), new IdentityPhysical()), + 'b' => new ScalarColumnBuilder(type_integer(), new IdentityPhysical()), + ]); + $builder->appendPhysical(['b' => 2, 'a' => 1]); + $builder->appendPhysicalMany([null, ['a' => 3]]); + + static::assertSame(3, $builder->count()); + + $column = $builder->finish(); + + static::assertInstanceOf(StructColumn::class, $column); + static::assertSame([1 => true], $column->nulls); + static::assertSame([1, null, 3], $column->children['a']->physicals()); + static::assertSame([2, null, null], $column->children['b']->physicals()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnTest.php new file mode 100644 index 0000000000..2249845e5d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnTest.php @@ -0,0 +1,71 @@ + type_integer(), + 'zone' => structure_element('zone', type_optional(type_time_zone()), optional: true), + 'tag' => type_optional(type_integer()), + ]); + $column = ColumnMother::of(structure_schema('a', $type, nullable: true), [ + ['id' => 1, 'zone' => 'UTC', 'tag' => 2], + null, + ['id' => 3, 'tag' => null], + ]); + + static::assertInstanceOf(StructColumn::class, $column); + static::assertSame(3, $column->count()); + static::assertSame(1, $column->nullCount()); + static::assertTrue($column->isNull(1)); + static::assertSame(['id' => 1, 'zone' => 'UTC', 'tag' => 2], $column->at(0)); + static::assertNull($column->at(1)); + static::assertSame(['id' => 3, 'tag' => null], $column->at(2)); + static::assertSame( + [['id' => 1, 'zone' => 'UTC', 'tag' => 2], null, ['id' => 3, 'tag' => null]], + $column->physicals(), + ); + static::assertEquals(['id' => 1, 'zone' => new DateTimeZone('UTC'), 'tag' => 2], $column->value(0)); + static::assertNull($column->value(1)); + static::assertSame(['id' => 3, 'tag' => null], $column->value(2)); + static::assertEquals( + [['id' => 1, 'zone' => new DateTimeZone('UTC'), 'tag' => 2], null, ['id' => 3, 'tag' => null]], + $column->values(), + ); + static::assertSame($type, $column->structure()); + static::assertSame($type, $column->type()); + } + + public function test_slice_and_take_rekey_nulls(): void + { + $column = ColumnMother::of(structure_schema('a', type_structure(['id' => type_integer()]), nullable: true), [ + ['id' => 1], + null, + ['id' => 3], + ]); + $taken = $column->take([1, 2]); + + static::assertInstanceOf(StructColumn::class, $taken); + static::assertSame([0 => true], $taken->nulls); + static::assertSame([null, ['id' => 3]], $taken->values()); + static::assertSame([null, ['id' => 3]], $column->slice(1, 2)->values()); + static::assertSame(0, $column->slice(0, 0)->count()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructPhysicalTest.php new file mode 100644 index 0000000000..57d74ef195 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructPhysicalTest.php @@ -0,0 +1,37 @@ + new IdentityPhysical(), + 'zone' => new TimeZonePhysical(), + 'note' => new IdentityPhysical(), + ]); + + static::assertSame( + ['id' => 1, 'zone' => 'UTC'], + $physical->toPhysical(['zone' => new DateTimeZone('UTC'), 'id' => 1]), + ); + static::assertSame(['id' => 1, 'zone' => null], $physical->toPhysical(['id' => 1, 'zone' => null])); + static::assertEquals( + ['id' => 1, 'zone' => new DateTimeZone('UTC')], + $physical->fromPhysical(['id' => 1, 'zone' => 'UTC']), + ); + static::assertEquals( + [['id' => 1, 'zone' => null], null], + $physical->fromPhysicalAll([['id' => 1, 'zone' => null], null]), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimePhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimePhysicalTest.php new file mode 100644 index 0000000000..b5263e1139 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimePhysicalTest.php @@ -0,0 +1,72 @@ +f = 0.5; + + static::assertSame(93_784_500_000, (new TimePhysical())->toPhysical($interval)); + + // @mago-ignore analysis:invalid-property-write + $interval->invert = 1; + + static::assertSame(-93_784_500_000, (new TimePhysical())->toPhysical($interval)); + } + + public function test_reads_back_hours_minutes_seconds_and_fraction(): void + { + $physical = new TimePhysical(); + $intervals = type_list(type_instance_of(DateInterval::class))->assert([ + $physical->fromPhysical(-93_784_500_000), + $physical->fromPhysicalAll([-93_784_500_000, null])[0], + ]); + + foreach ($intervals as $interval) { + static::assertSame([0, 26, 3, 4, 0.5, 1], [ + $interval->d, + $interval->h, + $interval->i, + $interval->s, + $interval->f, + $interval->invert, + ]); + } + + static::assertNull($physical->fromPhysicalAll([-93_784_500_000, null])[1]); + } + + public function test_refuses_months(): void + { + $this->expectException(CastingException::class); + $this->expectExceptionMessage("Relative DateInterval (with months/years) can't be stored in a time column"); + + (new TimePhysical())->toPhysical(new DateInterval('P1Y')); + } + + public function test_refuses_a_duration_outside_the_microsecond_range(): void + { + $this->expectException(CastingException::class); + $this->expectExceptionMessage('outside the microsecond range of a time column'); + + $interval = new DateInterval('PT0S'); + // @mago-ignore analysis:invalid-property-write + $interval->s = 9_223_372_036_855; + + (new TimePhysical())->toPhysical($interval); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonePhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonePhysicalTest.php new file mode 100644 index 0000000000..a59329ccec --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonePhysicalTest.php @@ -0,0 +1,21 @@ +toPhysical(new DateTimeZone('Europe/Warsaw'))); + static::assertEquals(new DateTimeZone('Europe/Warsaw'), $physical->fromPhysical('Europe/Warsaw')); + static::assertEquals([new DateTimeZone('UTC'), null], $physical->fromPhysicalAll(['UTC', null])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Utf8LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Utf8LayoutTest.php new file mode 100644 index 0000000000..81350102ff --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Utf8LayoutTest.php @@ -0,0 +1,42 @@ +encode(['ab', null, 'c'])), + ); + } + + public function test_round_trips(): void + { + $layout = new Utf8Layout(); + + static::assertSame( + ['ab', null, '', 'c'], + $layout->decode(new Buffers($layout->encode(['ab', null, '', 'c'])), 4, [true, false, true, true]), + ); + } + + public function test_refuses_a_last_offset_other_than_the_data_length(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Utf8 data buffer of 3 bytes, the last offset is 2'); + + (new Utf8Layout())->decode(new Buffers(["\0\0\0\0\x02\0\0\0", 'abc']), 1, [true]); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/UuidPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/UuidPhysicalTest.php new file mode 100644 index 0000000000..b0647fd102 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/UuidPhysicalTest.php @@ -0,0 +1,32 @@ +assert($physical->toPhysical(new Uuid('6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f'))); + + static::assertIsString($bytes); + static::assertSame('6c2f1d4e8b3a4c5d9e6f0a1b2c3d4e5f', bin2hex($bytes)); + static::assertEquals(new Uuid('6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f'), $physical->fromPhysical($bytes)); + static::assertEquals( + [new Uuid('6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f'), null], + $physical->fromPhysicalAll([ + $bytes, + null, + ]), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValidityTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValidityTest.php new file mode 100644 index 0000000000..2f2abf0036 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValidityTest.php @@ -0,0 +1,73 @@ +fromValues([1, 2, 3])); + static::assertSame('', (new Validity())->fromValues([])); + static::assertSame('', (new Validity())->fromNulls([], 3)); + } + + #[TestWith([7, '3f'])] + #[TestWith([8, '7f'])] + #[TestWith([9, 'ff00'])] + public function test_the_last_row_null_packs_lsb_first(int $count, string $hex): void + { + $values = array_fill(0, 9, 1); + $values = array_slice($values, 0, $count); + $values[$count - 1] = null; + + static::assertSame($hex, bin2hex((new Validity())->fromValues($values))); + static::assertSame($hex, bin2hex((new Validity())->fromNulls([$count - 1 => true], $count))); + } + + public function test_the_first_row_null(): void + { + static::assertSame('fe01', bin2hex((new Validity())->fromValues([null, 1, 1, 1, 1, 1, 1, 1, 1]))); + static::assertSame('fe01', bin2hex((new Validity())->fromNulls([0 => true], 9))); + } + + public function test_reads_the_valid_flags(): void + { + static::assertSame( + [false, true, true, true, true, true, true, true, true], + (new Validity())->valid("\xFE\x01", 9), + ); + static::assertSame([true, true], (new Validity())->valid('', 2)); + static::assertSame([], (new Validity())->valid('', 0)); + } + + public function test_counts_nulls_ignoring_padding_bits(): void + { + static::assertSame(1, (new Validity())->nullCount("\xFE\x01", 9)); + static::assertSame(0, (new Validity())->nullCount('', 9)); + static::assertSame(7, (new Validity())->nullCount("\x01", 8)); + } + + public function test_the_nulls_of_the_flags(): void + { + static::assertSame([0 => true, 2 => true], (new Validity())->nulls([false, true, false])); + } + + public function test_refuses_a_short_bitmap(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Validity bitmap of 1 bytes is too short for 9 rows'); + + (new Validity())->valid("\xFF", 9); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php new file mode 100644 index 0000000000..f822a8ada8 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php @@ -0,0 +1,27 @@ +loadXML('1'); + $physical = new XmlDocumentPhysical(); + $markup = type_string()->assert($physical->toPhysical($document)); + + static::assertIsString($markup); + static::assertStringContainsString('1', $markup); + static::assertEquals($document, $physical->fromPhysical($markup)); + static::assertEquals([$document, null], $physical->fromPhysicalAll([$markup, null])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php new file mode 100644 index 0000000000..9e84e260fb --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php @@ -0,0 +1,42 @@ +loadXML('1'); + $element = $document->documentElement; + $physical = new XmlElementPhysical(); + + static::assertNotNull($element); + static::assertSame('1', $physical->toPhysical($element)); + static::assertEquals($element, $physical->fromPhysical('1')); + static::assertEquals([$element, null], $physical->fromPhysicalAll(['1', null])); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_a_dom_element_of_the_new_api_reads_back_as_a_dom_element(): void + { + // @mago-ignore analysis:unavailable-method + $element = XMLDocument::createFromString('1')->documentElement; + $physical = new XmlElementPhysical(); + $markup = type_string()->assert($physical->toPhysical($element)); + + static::assertSame('1', $markup); + static::assertInstanceOf(DOMElement::class, $physical->fromPhysical($markup)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php new file mode 100644 index 0000000000..99f86abc66 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php @@ -0,0 +1,568 @@ +, mixed, mixed}> + */ + public static function definitions(): Generator + { + $structure = type_structure([ + 'id' => type_integer(), + 'note' => structure_element('note', type_optional(type_string()), optional: true), + 'tag' => type_optional(type_string()), + ]); + + yield 'integer' => [int_schema('a'), '5', 5]; + yield 'float' => [float_schema('a'), 1.5, 1.5]; + yield 'boolean' => [bool_schema('a'), true, true]; + yield 'string' => [str_schema('a'), 'text', 'text']; + yield 'datetime' => [ + datetime_schema('a'), + '2024-01-02 03:04:05.123456', + new DateTimeImmutable('2024-01-02 03:04:05.123456 UTC'), + ]; + yield 'datetime in the column zone' => [ + datetime_schema('a', zone: 'Europe/Warsaw'), + new DateTimeImmutable('2024-01-02 03:04:05.5 UTC'), + new DateTimeImmutable('2024-01-02 04:04:05.5', new DateTimeZone('Europe/Warsaw')), + ]; + yield 'datetime one microsecond before the epoch' => [ + datetime_schema('a'), + new DateTimeImmutable('@-0.000001'), + new DateTimeImmutable('1969-12-31 23:59:59.999999 UTC'), + ]; + yield 'datetime one and a half seconds before the epoch' => [ + datetime_schema('a'), + new DateTimeImmutable('@-1.500000'), + new DateTimeImmutable('1969-12-31 23:59:58.5 UTC'), + ]; + yield 'date east of UTC keeps its calendar day' => [ + date_schema('a'), + new DateTimeImmutable('2024-03-05 00:30:00', new DateTimeZone('Asia/Tokyo')), + new DateTimeImmutable('2024-03-05 00:00:00 UTC'), + ]; + yield 'date before the epoch' => [ + date_schema('a'), + new DateTimeImmutable('1969-12-29 00:00:00 UTC'), + new DateTimeImmutable('1969-12-29 00:00:00 UTC'), + ]; + yield 'time folds days into hours' => [ + time_schema('a'), + DateIntervalMother::of('P1DT2H3M4S', 0.25, 1), + DateIntervalMother::of('PT26H3M4S', 0.25, 1), + ]; + yield 'uuid' => [ + uuid_schema('a'), + '6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f', + new Uuid('6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f'), + ]; + yield 'timezone' => [time_zone_schema('a'), 'Europe/Warsaw', new DateTimeZone('Europe/Warsaw')]; + yield 'json object' => [json_schema('a'), '{"a":1}', Json::fromString('{"a":1}')]; + yield 'json list' => [json_schema('a'), [1, 2], Json::fromString('[1,2]')]; + yield 'enum' => [enum_schema('a', BackedStringEnum::class), 'one', BackedStringEnum::one]; + yield 'xml' => [xml_schema('a'), '1', XmlMother::document('1')]; + yield 'xml element' => [ + xml_element_schema('a'), + XmlMother::document('1')->documentElement, + XmlMother::document('1')->documentElement, + ]; + yield 'list with a null element' => [ + list_schema('a', type_list(type_optional(type_integer()))), + [1, null, 3], + [1, null, 3], + ]; + yield 'list of datetimes in the column zone' => [ + list_schema('a', type_list(type_datetime('Europe/Warsaw'))), + [new DateTimeImmutable('2024-01-02 03:04:05 UTC')], + [new DateTimeImmutable('2024-01-02 04:04:05', new DateTimeZone('Europe/Warsaw'))], + ]; + yield 'map with a null value' => [ + map_schema('a', type_map(type_string(), type_optional(type_integer()))), + ['x' => 1, 'y' => null], + ['x' => 1, 'y' => null], + ]; + yield 'structure with every element' => [ + structure_schema('a', $structure), + ['id' => 1, 'note' => 'x', 'tag' => 'y'], + ['id' => 1, 'note' => 'x', 'tag' => 'y'], + ]; + yield 'structure: an optional nullable element given null reads back absent' => [ + structure_schema('a', $structure), + ['id' => 1, 'note' => null, 'tag' => null], + ['id' => 1, 'tag' => null], + ]; + yield 'structure: an absent optional element stays absent' => [ + structure_schema('a', $structure), + ['id' => 1, 'tag' => 'y'], + ['id' => 1, 'tag' => 'y'], + ]; + } + + /** + * @return Generator}> + */ + public static function not_null_definitions(): Generator + { + foreach (self::definitions() as $name => [$definition]) { + yield $name => [$definition]; + } + } + + /** + * @return Generator, string}> + */ + public static function refusals(): Generator + { + yield 'a definition outside the nineteen' => [ + new ForeignTypeDefinition('a', type_integer()), + 'Row does not match its schema: column "a": integer cannot be a batch column, only the 19 Flow definitions have a column kind', + ]; + yield 'a mixed element' => [ + list_schema('a', type_list(type_mixed())), + 'Row does not match its schema: column "a": list cannot be a batch column, a mixed element has no column kind, declare it or use json', + ]; + yield 'a wildcard enum' => [ + enum_schema('a', UnitEnum::class), + 'Row does not match its schema: column "a": enum cannot be a batch column, declare the concrete enum class', + ]; + yield 'a type without a column kind' => [ + list_schema('a', type_list(type_instance_of(stdClass::class))), + 'Row does not match its schema: column "a": list> cannot be a batch column, type object has no column kind', + ]; + } + + /** + * @return Generator, mixed, bool}> + */ + public static function temporal_range(): Generator + { + yield 'datetime at the upper bound' => [ + datetime_schema('a'), + new DateTimeImmutable('@9223372036854.775807'), + true, + ]; + yield 'datetime past the upper bound' => [ + datetime_schema('a'), + new DateTimeImmutable('@9223372036854.775808'), + false, + ]; + yield 'datetime at the lower bound' => [datetime_schema('a'), new DateTimeImmutable('@-9223372036854'), true]; + yield 'datetime past the lower bound' => [ + datetime_schema('a'), + new DateTimeImmutable('@-9223372036855'), + false, + ]; + yield 'date at the upper bound' => [ + date_schema('a'), + new DateTimeImmutable('@' . ((2 ** 31 - 1) * 86_400)), + true, + ]; + yield 'date past the upper bound' => [ + date_schema('a'), + new DateTimeImmutable('@' . ((2 ** 31) * 86_400)), + false, + ]; + yield 'date at the lower bound' => [date_schema('a'), new DateTimeImmutable('@' . (-2 ** 31 * 86_400)), true]; + yield 'date past the lower bound' => [ + date_schema('a'), + new DateTimeImmutable('@' . ((-2 ** 31 - 1) * 86_400)), + false, + ]; + yield 'time at the upper bound' => [ + time_schema('a'), + DateIntervalMother::seconds(9_223_372_036_854, 0.775807, 0), + true, + ]; + yield 'time past the upper bound' => [ + time_schema('a'), + DateIntervalMother::seconds(9_223_372_036_854, 0.775808, 0), + false, + ]; + yield 'negative time at the bound' => [ + time_schema('a'), + DateIntervalMother::seconds(9_223_372_036_854, 0.775807, 1), + true, + ]; + yield 'negative time past the bound' => [ + time_schema('a'), + DateIntervalMother::seconds(9_223_372_036_854, 0.775808, 1), + false, + ]; + yield 'time with a negative component past the bound' => [ + time_schema('a'), + DateInterval::createFromDateString('-9223372036860 seconds'), + false, + ]; + } + + /** + * @param Definition $definition + */ + #[DataProvider('definitions')] + public function test_round_trips(Definition $definition, mixed $value, mixed $expected): void + { + static::assertEquals($expected, ColumnMother::of($definition, [$value])->value(0)); + static::assertEquals([$expected], ColumnMother::of($definition, [$value])->values()); + } + + /** + * @param Definition $definition + */ + #[DataProvider('definitions')] + public function test_round_trips_null_under_a_nullable_definition( + Definition $definition, + mixed $value, + mixed $expected, + ): void { + $column = ColumnMother::of($definition->makeNullable(), [$value, null]); + + static::assertEquals([$expected, null], $column->values()); + static::assertSame(1, $column->nullCount()); + static::assertTrue($column->isNull(1)); + static::assertFalse($column->isNull(0)); + } + + /** + * @param Definition $definition + */ + #[DataProvider('not_null_definitions')] + public function test_refuses_null_under_a_not_null_definition(Definition $definition): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage('could not convert null to'); + + (new PhpBackend()) + ->builder($definition) + ->append(null); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_html_round_trips(): void + { + $document = type_instance_of(HTMLDocument::class)->assert(ColumnMother::of( + html_schema('a'), + ['

a

'], + )->value(0)); + $element = type_instance_of(HTMLElement::class)->assert(ColumnMother::of(html_element_schema('a'), [ + type_html_element()->cast('

a

'), + ])->value(0)); + + static::assertStringContainsString( + '

a

', + type_string()->assert((new HtmlDocumentPhysical())->toPhysical($document)), + ); + static::assertSame('

a

', (new HtmlElementPhysical())->toPhysical($element)); + } + + public function test_the_null_definition_holds_nulls_only(): void + { + $column = ColumnMother::of(null_schema('a'), [null, null, null]); + + static::assertSame(3, $column->count()); + static::assertSame(3, $column->nullCount()); + static::assertSame([null, null, null], $column->values()); + } + + /** + * @param Definition $definition + */ + #[DataProvider('refusals')] + public function test_refuses(Definition $definition, string $message): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage($message); + + (new PhpBackend())->builder($definition); + } + + public function test_time_refuses_months(): void + { + $this->expectException(CastingException::class); + $this->expectExceptionMessage("Relative DateInterval (with months/years) can't be stored in a time column"); + + (new PhpBackend()) + ->builder(time_schema('a')) + ->append('P1M'); + } + + /** + * @param Definition $definition + */ + #[DataProvider('temporal_range')] + public function test_temporal_range(Definition $definition, mixed $value, bool $accepted): void + { + if (!$accepted) { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('outside the'); + } + + static::assertIsInt(ColumnMother::of($definition, [$value])->at(0)); + } + + public function test_date_reads_back_in_utc(): void + { + $date = type_instance_of(DateTimeImmutable::class)->assert(ColumnMother::of(date_schema('a'), [ + new DateTimeImmutable('2024-03-05 00:30:00', new DateTimeZone('Asia/Tokyo')), + ])->value(0)); + + static::assertInstanceOf(DateTimeImmutable::class, $date); + static::assertSame('UTC', $date->getTimezone()->getName()); + static::assertSame('2024-03-05 00:00:00', $date->format('Y-m-d H:i:s')); + } + + public function test_datetime_reads_back_in_the_column_zone(): void + { + $datetime = type_instance_of(DateTimeImmutable::class)->assert(ColumnMother::of( + datetime_schema('a', zone: 'Europe/Warsaw'), + [ + new DateTimeImmutable('2024-01-02 03:04:05 UTC'), + ], + )->value(0)); + + static::assertInstanceOf(DateTimeImmutable::class, $datetime); + static::assertSame('Europe/Warsaw', $datetime->getTimezone()->getName()); + } + + public function test_time_reads_back_with_days_folded_and_no_days_count(): void + { + $time = type_instance_of(DateInterval::class)->assert(ColumnMother::of(time_schema('a'), [new DateInterval( + 'P2DT1H', + )])->value(0)); + + static::assertInstanceOf(DateInterval::class, $time); + static::assertSame(0, $time->d); + static::assertSame(49, $time->h); + static::assertFalse($time->days); + } + + public function test_constant_holds_one_value(): void + { + $column = (new PhpBackend())->constant(int_schema('a'), '7', 3); + + static::assertSame(3, $column->count()); + static::assertSame(0, $column->nullCount()); + static::assertSame([7, 7, 7], $column->values()); + static::assertSame(7, $column->value(2)); + static::assertSame(7, $column->at(1)); + } + + public function test_constant_null(): void + { + $column = (new PhpBackend())->constant(int_schema('a', nullable: true), null, 2); + + static::assertSame(2, $column->nullCount()); + static::assertSame([null, null], $column->values()); + static::assertTrue($column->isNull(0)); + } + + public function test_constant_refuses_null_under_a_not_null_definition(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage('column "a": could not convert null to integer, column is not nullable'); + + (new PhpBackend())->constant(int_schema('a'), null, 2); + } + + public function test_constant_null_under_the_null_definition(): void + { + static::assertSame( + 2, + (new PhpBackend()) + ->constant(null_schema('a'), null, 2) + ->nullCount(), + ); + } + + public function test_constant_slice_take_and_concat(): void + { + $backend = new PhpBackend(); + $column = $backend->constant(int_schema('a'), 7, 5); + + static::assertSame([7, 7], $column->slice(1, 2)->values()); + static::assertSame([7, 7, 7], $column->take([0, 4, 2])->values()); + static::assertSame([7, 7, 7, 7, 7, 7], $column->concat($backend->constant(int_schema('a'), 7, 1))->values()); + static::assertSame([7, 7, 7, 7, 7, 8], $column->concat($backend->constant(int_schema('a'), 8, 1))->values()); + } + + /** + * @param Definition $definition + */ + #[DataProvider('definitions')] + public function test_decode_round_trips(Definition $definition, mixed $value, mixed $expected): void + { + $nullable = $definition->makeNullable(); + $column = ColumnMother::of($nullable, [$value, null, $value]); + $backend = new PhpBackend(); + + foreach ([$column, $column->slice(1, 2), $column->take([2, 1])] as $variant) { + static::assertEquals( + $variant->values(), + $backend->decode($nullable, $variant->encode(), $variant->count(), $variant->nullCount())->values(), + ); + } + } + + public function test_decode_round_trips_a_null_column(): void + { + $column = ColumnMother::of(null_schema('a'), [null, null]); + + static::assertSame( + [null, null], + (new PhpBackend()) + ->decode(null_schema('a'), $column->encode(), 2, 2) + ->values(), + ); + } + + /** + * @return Generator, list, int, int, string}> + */ + public static function corrupt_buffers(): Generator + { + yield 'too few buffers' => [int_schema('a'), [''], 1, 0, 'Column buffers exhausted']; + yield 'short fixed buffer' => [ + int_schema('a'), + ['', "\x01\x00"], + 1, + 0, + 'Int64 values buffer of 2 bytes, expected 8 for 1 rows', + ]; + yield 'offsets not from 0' => [ + str_schema('a'), + ['', "\x01\x00\x00\x00\x02\x00\x00\x00", 'ab'], + 1, + 0, + 'Utf8 offsets start at 1, not 0', + ]; + yield 'offsets not monotonic' => [ + str_schema('a'), + ['', "\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00", 'ab'], + 2, + 0, + 'Utf8 offsets are not monotonic', + ]; + yield 'offsets past the data' => [ + str_schema('a'), + ['', "\x00\x00\x00\x00\x03\x00\x00\x00", 'ab'], + 1, + 0, + 'Utf8 data buffer of 2 bytes, the last offset is 3', + ]; + yield 'map entries validity present' => [ + map_schema('a', type_map(type_string(), type_integer())), + ['', "\x00\x00\x00\x00\x00\x00\x00\x00", "\x01"], + 1, + 0, + 'Map entries validity must be omitted, got 1 bytes', + ]; + yield 'null count disagreeing with the bitmap' => [ + int_schema('a', nullable: true), + ["\x01", "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"], + 2, + 0, + 'Column null count 0 disagrees with its validity bitmap (1 nulls in 2 rows)', + ]; + yield 'short validity bitmap' => [ + int_schema('a', nullable: true), + ['', ''], + 9, + 0, + 'Int64 values buffer of 0 bytes, expected 72 for 9 rows', + ]; + yield 'null column with a wrong null count' => [ + null_schema('a'), + [], + 2, + 1, + 'Null column of 2 rows carries a null count of 1', + ]; + yield 'leftover buffers' => [ + int_schema('a'), + ['', "\x01\x00\x00\x00\x00\x00\x00\x00", ''], + 1, + 0, + 'Column "a": 1 buffers left after decoding', + ]; + } + + /** + * @param Definition $definition + * @param list $buffers + */ + #[DataProvider('corrupt_buffers')] + public function test_decode_refuses( + Definition $definition, + array $buffers, + int $count, + int $nullCount, + string $message, + ): void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage($message); + + (new PhpBackend())->decode($definition, $buffers, $count, $nullCount); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php new file mode 100644 index 0000000000..72b29df04c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php @@ -0,0 +1,82 @@ + 1]); + + static::assertTrue($comparator->accepts($row, $row)); + static::assertFalse($comparator->accepts($row, rows(schema(int_schema('id')), $row))); + static::assertFalse($comparator->accepts($row, ['id' => 1])); + } + + public function test_rows_of_different_batches_with_equal_values_pass(): void + { + $comparator = new RowComparator(); + $comparator->setFactory(Factory::getInstance()); + + $comparator->assertEquals( + rows(schema(int_schema('id')), row(['id' => 1]))->first(), + rows(schema(int_schema('id')), row(['id' => 0]), row(['id' => 1]))->last(), + ); + + $this->addToAssertionCount(1); + } + + public function test_the_schema_is_not_compared(): void + { + $comparator = new RowComparator(); + $comparator->setFactory(Factory::getInstance()); + + $comparator->assertEquals(row([ + 'phase' => null, + ]), rows(schema(int_schema('phase', nullable: true)), row(['phase' => null]))->first()); + + $this->addToAssertionCount(1); + } + + public function test_a_name_order_difference_fails(): void + { + $comparator = new RowComparator(); + $comparator->setFactory(Factory::getInstance()); + + $this->expectException(ComparisonFailure::class); + $this->expectExceptionMessage('Failed asserting that two Row objects have the same names.'); + + $comparator->assertEquals(row(['a' => 1, 'b' => 2]), row(['b' => 2, 'a' => 1])); + } + + public function test_a_value_difference_fails(): void + { + $comparator = new RowComparator(); + $comparator->setFactory(Factory::getInstance()); + + try { + $comparator->assertEquals(row(['id' => 1]), row(['id' => 2])); + } catch (ComparisonFailure $failure) { + static::assertSame('Failed asserting that two Row objects are equal.', $failure->getMessage()); + static::assertStringContainsString('1', $failure->getExpectedAsString()); + static::assertStringContainsString('2', $failure->getActualAsString()); + + return; + } + + static::fail('two Row objects with different values compared equal'); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php new file mode 100644 index 0000000000..12a197ecfb --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php @@ -0,0 +1,108 @@ + 1])); + + static::assertTrue($comparator->accepts($rows, $rows)); + static::assertFalse($comparator->accepts($rows, row(['id' => 1]))); + static::assertFalse($comparator->accepts([], $rows)); + } + + public function test_equal_rows_of_two_batches_pass(): void + { + $comparator = new RowsComparator(); + $comparator->setFactory(Factory::getInstance()); + + $comparator->assertEquals( + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + ); + + $this->addToAssertionCount(1); + } + + public function test_equal_across_column_classes(): void + { + $comparator = new RowsComparator(); + $comparator->setFactory(Factory::getInstance()); + + $comparator->assertEquals( + Rows::fromColumns( + schema(int_schema('id')), + ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], + 2, + ), + rows(schema(int_schema('id')), row(['id' => 7]), row(['id' => 7])), + ); + + $this->addToAssertionCount(1); + } + + public function test_a_schema_difference_fails(): void + { + $comparator = new RowsComparator(); + $comparator->setFactory(Factory::getInstance()); + + $this->expectException(ComparisonFailure::class); + $this->expectExceptionMessage('Failed asserting that two Rows have the same schema.'); + + $comparator->assertEquals( + rows(schema(int_schema('id')), row(['id' => 1])), + rows(schema(int_schema('id', nullable: true)), row(['id' => 1])), + ); + } + + public function test_a_value_difference_fails(): void + { + $comparator = new RowsComparator(); + $comparator->setFactory(Factory::getInstance()); + + try { + $comparator->assertEquals( + rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])), + rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'b'])), + ); + } catch (ComparisonFailure $failure) { + static::assertSame('Failed asserting that two Rows are equal.', $failure->getMessage()); + static::assertStringContainsString("'a'", $failure->getExpectedAsString()); + static::assertStringContainsString("'b'", $failure->getActualAsString()); + + return; + } + + static::fail('two Rows with different values compared equal'); + } + + public function test_assert_equals_uses_the_registered_comparator(): void + { + static::assertEquals( + rows(schema(int_schema('id')), row(['id' => 1])), + rows(schema(int_schema('id')), row(['id' => 1])), + ); + static::assertNotEquals( + rows(schema(int_schema('id')), row(['id' => 1])), + rows(schema(int_schema('id')), row(['id' => 2])), + ); + } +} 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 dc403af5a5..ca235f6b8e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php @@ -23,7 +23,6 @@ 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; @@ -557,7 +556,7 @@ public function transform(Rows $rows, FlowContext $context): Rows $stamped[] = row([...$row->values(), 'stamp' => 'zero']); } - return new Rows($rows->schema()->add(str_schema('stamp')), ...$stamped); + return rows($rows->schema()->add(str_schema('stamp')), ...$stamped); } }; @@ -837,13 +836,7 @@ public function bind(Schema $input): BoundStep public function transform(Rows $rows, FlowContext $context): Rows { - $renamed = []; - - foreach ($rows->all() as $row) { - $renamed[] = RowRenaming::of(['id' => 'new_id'])->apply($row); - } - - return new Rows($rows->schema()->rename('id', 'new_id'), ...$renamed); + return $rows->withSchema($rows->schema()->rename('id', 'new_id')); } }) ->batchSize(2) @@ -895,13 +888,7 @@ public function bind(Schema $input): BoundStep public function transform(Rows $rows, FlowContext $context): Rows { - $renamed = []; - - foreach ($rows->all() as $row) { - $renamed[] = RowRenaming::of(['id' => 'new_id'])->apply($row); - } - - return new Rows($rows->schema()->rename('id', 'new_id'), ...$renamed); + return $rows->withSchema($rows->schema()->rename('id', 'new_id')); } }) ->collect() diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/ColumnMismatchExceptionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/ColumnMismatchExceptionTest.php index b23fb9d150..a837c861c9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/ColumnMismatchExceptionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/ColumnMismatchExceptionTest.php @@ -4,6 +4,8 @@ namespace Flow\ETL\Tests\Unit\Exception; +use DateTimeImmutable; +use DateTimeZone; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Tests\FlowTestCase; use Generator; @@ -29,6 +31,10 @@ public static function provide_rendered_values(): Generator yield 'true' => [true, 'could not convert true (boolean) to integer']; yield 'false' => [false, 'could not convert false (boolean) to integer']; yield 'array' => [[1, 2], 'could not convert array (list) to integer']; + yield 'datetime with its offset' => [ + new DateTimeImmutable('2026-01-01 00:00:00.5', new DateTimeZone('Europe/Warsaw')), + 'could not convert 2026-01-01T00:00:00.500000+01:00 (datetime) to integer', + ]; } public function test_a_message_carries_no_row_coordinate(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ArrayExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ArrayExtractorTest.php index 0fb182c67f..dd6426169d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ArrayExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ArrayExtractorTest.php @@ -7,11 +7,11 @@ use ArrayIterator; use ArrayObject; use Flow\ETL\Cardinality; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Extractor\ArrayExtractor; use Flow\ETL\Extractor\Statistics; -use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Schema\Definition; use Flow\ETL\Tests\Double\FixedTmpDirFilesystem; use Flow\ETL\Tests\Double\FreshRowsAggregate; @@ -310,7 +310,7 @@ public function test_a_bounded_sample_types_only_its_prefix(): void iterator_to_array( from_array($dataset) ->inferSchema(infer_schema()->sampleSize(3)) - ->extract(execution_context(config_builder()->hydrator(new PhpRowHydrator())->build())), + ->extract(execution_context(config_builder()->backend(new PhpBackend())->build())), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchExtractorTest.php index 5b34d76fd4..6088e5a998 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchExtractorTest.php @@ -10,12 +10,16 @@ use Flow\ETL\Extractor\BatchExtractor; use Flow\ETL\Extractor\Statistics; use Flow\ETL\Memory\ArrayMemory; +use Flow\ETL\Rows; use Flow\ETL\Tests\Double\DeclaringExtractor; use Flow\ETL\Tests\Double\FakeExtractor; use Flow\ETL\Tests\Double\VaryingBatchesExtractor; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use function array_map; +use function array_merge; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\batches; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_memory; @@ -26,9 +30,33 @@ use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; +use function range; final class BatchExtractorTest extends FlowTestCase { + public function test_windows_built_from_many_child_batches_keep_counts_and_order(): void + { + $children = []; + + for ($batch = 0; $batch < 25; $batch++) { + $children[] = array_to_rows( + array_map(static fn(int $id): array => ['id' => $id], range(($batch * 100) + 1, ($batch * 100) + 100)), + schema(int_schema('id')), + ); + } + + $windows = iterator_to_array( + batches(new VaryingBatchesExtractor(...$children), 1_000)->extract(flow_context()), + false, + ); + + static::assertSame([1000, 1000, 500], array_map(static fn(Rows $rows): int => $rows->count(), $windows)); + static::assertSame( + range(1, 2_500), + array_merge(...array_map(static fn(Rows $rows): array => $rows->reduceToArray('id'), $windows)), + ); + } + public function test_a_buffer_spanning_child_batches_answers_to_the_first_batch_schema(): void { // the second child batch omits a column the first declares nullable - the buffer that spans diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php index c72c9ddb93..c22b9e0dce 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php @@ -4,10 +4,10 @@ namespace Flow\ETL\Tests\Unit\Extractor; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Extractor\InferredRows; -use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\TestWith; @@ -20,7 +20,7 @@ final class InferredRowsTest extends FlowTestCase public function test_a_row_past_the_sample_is_reported_at_its_position_in_the_whole_source(): void { $rows = new InferredRows('from_array()', new SchemaInference(sampleSize: 2)); - $rows->of([['code' => 1], ['code' => 2]], schema(int_schema('code', true)), new PhpRowHydrator()); + $rows->of([['code' => 1], ['code' => 2]], schema(int_schema('code', true)), new PhpBackend()); $this->expectException(InferredSchemaException::class); $this->expectExceptionMessage( @@ -29,7 +29,7 @@ public function test_a_row_past_the_sample_is_reported_at_its_position_in_the_wh . 'or declare the schema with ->withSchema(...).', ); - $rows->of([['code' => 3], ['code' => 'x']], schema(int_schema('code', true)), new PhpRowHydrator()); + $rows->of([['code' => 3], ['code' => 'x']], schema(int_schema('code', true)), new PhpBackend()); } public function test_a_row_past_the_sample_keeps_the_refusal_it_was_raised_from(): void @@ -38,7 +38,7 @@ public function test_a_row_past_the_sample_keeps_the_refusal_it_was_raised_from( (new InferredRows('from_array()', new SchemaInference(sampleSize: 1)))->of( [['code' => 1], ['code' => 'x']], schema(int_schema('code', true)), - new PhpRowHydrator(), + new PhpBackend(), ); static::fail('The row past the sample was not refused.'); @@ -61,6 +61,6 @@ public function test_a_refusal_the_sample_does_not_explain_stays_the_gate_s_own( (new InferredRows( 'from_array()', $sampleSize === null ? null : new SchemaInference(sampleSize: $sampleSize), - ))->of([['code' => 1], ['code' => 'x']], schema(int_schema('code', true)), new PhpRowHydrator()); + ))->of([['code' => 1], ['code' => 'x']], schema(int_schema('code', true)), new PhpBackend()); } } 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 880deb6336..4065cffa72 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowContextTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowContextTest.php @@ -58,7 +58,7 @@ public function test_config_constructor_takes_no_filesystem_table(): void $constructor = (new ReflectionClass(Config::class))->getConstructor(); static::assertNotNull($constructor); - static::assertCount(17, $constructor->getParameters()); + static::assertCount(18, $constructor->getParameters()); static::assertSame( [], array_filter( @@ -77,6 +77,7 @@ public function test_flow_context_exposes_no_filesystem_and_no_streams(): void 'cache', 'calculator', 'errorHandler', + 'backend', 'hydrator', 'setErrorHandler', 'withErrorHandler', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php index ccc8c83a88..077987dff8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php @@ -138,10 +138,11 @@ public static function cast_provider(): array ], 'string_to_timezone' => ['UTC', 'timezone', new DateTimeZone('UTC')], 'string_to_timezone_america' => ['America/New_York', 'timezone', new DateTimeZone('America/New_York')], + // row() infers a UTC datetime column, so the value reads back under the column zone 'datetime_to_timezone' => [ new DateTimeImmutable('2023-01-01 00:00:00', new DateTimeZone('Europe/London')), 'timezone', - new DateTimeZone('Europe/London'), + new DateTimeZone('UTC'), ], 'uuid' => [ Uuid::fromString('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php index 7e6ca3acc6..45e4a67e17 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php @@ -12,6 +12,7 @@ use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\row; @@ -44,7 +45,7 @@ public function test_html_getting_parent_element(): void ); static::assertEquals( $element->documentElement, - ref('value')->domElementParent()->eval(row(['value' => $element->querySelector('span')]), flow_context()), + lit($element->querySelector('span'))->domElementParent()->eval(row([]), flow_context()), ); } @@ -53,9 +54,7 @@ public function test_html_getting_parent_element_when_not_available(): void { // @mago-ignore analysis:unavailable-method $element = HTMLDocument::createFromString('bar', LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); - static::assertNull( - ref('value')->domElementParent()->eval(row(['value' => $element->documentElement]), flow_context()), - ); + static::assertNull(lit($element->documentElement)->domElementParent()->eval(row([]), flow_context())); } public function test_xml_fails_when_parent_not_available_in_strict_mode(): void @@ -76,13 +75,9 @@ public function test_xml_getting_parent_element(): void $xml->loadXML('foobar'); static::assertEquals( $xml->documentElement, - ref('value') - ->domElementParent() - ->eval( - // @mago-ignore analysis:possibly-null-property-access - row(['value' => $xml->documentElement->firstChild]), - flow_context(), - ), + // a batch stores the element's markup, so the parent is only reachable on the live node + // @mago-ignore analysis:possibly-null-property-access + lit($xml->documentElement->firstChild)->domElementParent()->eval(row([]), flow_context()), ); } 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 e69b488498..956a4e35a8 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 @@ -7,7 +7,7 @@ use DateTime; use DateTimeImmutable; use DateTimeZone; -use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\FlowTestCase; use stdClass; @@ -153,8 +153,8 @@ public function test_mutable_datetime_is_converted_without_mutation(): void public function test_non_datetime_object_is_refused(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('ToDateTime function requires DateTimeInterface object'); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Cannot create Definition from type'); to_date_time(ref('at'))->eval(row(['at' => new stdClass()]), flow_context()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php index 14b9d22333..17757d3dac 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php @@ -26,7 +26,7 @@ public function test_drop_left_skips_duplicated_join_columns(): void static::assertSame( ['amount' => 100, 'id' => 1, 'name' => 'Alice'], - $merger->merge(row(['id' => 1, 'amount' => 100]), row(['id' => 1, 'name' => 'Alice']))->toArray(), + $merger->merge(row(['id' => 1, 'amount' => 100]), row(['id' => 1, 'name' => 'Alice'])), ); } @@ -36,7 +36,7 @@ public function test_drop_right_skips_duplicated_join_columns(): void static::assertSame( ['id' => 1, 'amount' => 100, 'name' => 'Alice'], - $merger->merge(row(['id' => 1, 'amount' => 100]), row(['id' => 1, 'name' => 'Alice']))->toArray(), + $merger->merge(row(['id' => 1, 'amount' => 100]), row(['id' => 1, 'name' => 'Alice'])), ); } @@ -44,9 +44,7 @@ public function test_merge_without_prefix_keeps_right_names(): void { static::assertSame( ['id' => 1, 'name' => 'Alice'], - (new RowMerger()) - ->merge(row(['id' => 1]), row(['name' => 'Alice'])) - ->toArray(), + (new RowMerger())->merge(row(['id' => 1]), row(['name' => 'Alice'])), ); } @@ -61,9 +59,7 @@ public function test_prefix_renames_every_right_entry(): void { static::assertSame( ['id' => 1, 'right_id' => 1, 'right_name' => 'Alice'], - (new RowMerger('right_')) - ->merge(row(['id' => 1]), row(['id' => 1, 'name' => 'Alice'])) - ->toArray(), + (new RowMerger('right_'))->merge(row(['id' => 1]), row(['id' => 1, 'name' => 'Alice'])), ); } @@ -71,33 +67,26 @@ public function test_renamed_entries_carry_renamed_names(): void { $merged = (new RowMerger('r_'))->merge(row(['id' => 1]), row(['name' => 'Alice'])); - static::assertSame(['id', 'r_name'], $merged->names()); - static::assertSame('Alice', $merged->get('r_name')); + static::assertSame(['id' => 1, 'r_name' => 'Alice'], $merged); } public function test_reused_plan_renames_rows_with_identical_name_sets(): void { $merger = new RowMerger('r_'); - static::assertSame(['id' => 1, 'r_x' => 'a'], $merger->merge(row(['id' => 1]), row(['x' => 'a']))->toArray()); - static::assertSame(['id' => 2, 'r_x' => 5], $merger->merge(row(['id' => 2]), row(['x' => 5]))->toArray()); + static::assertSame(['id' => 1, 'r_x' => 'a'], $merger->merge(row(['id' => 1]), row(['x' => 'a']))); + static::assertSame(['id' => 2, 'r_x' => 5], $merger->merge(row(['id' => 2]), row(['x' => 5]))); } public function test_reused_merger_handles_rows_with_different_entry_sets(): void { $merger = new RowMerger(); - static::assertSame( - ['id' => 1, 'name' => 'Alice'], - $merger->merge(row(['id' => 1]), row(['name' => 'Alice']))->toArray(), - ); + static::assertSame(['id' => 1, 'name' => 'Alice'], $merger->merge(row(['id' => 1]), row(['name' => 'Alice']))); static::assertSame( ['id' => 2, 'name' => 'Bob', 'age' => 30], - $merger->merge(row(['id' => 2]), row(['name' => 'Bob', 'age' => 30]))->toArray(), - ); - static::assertSame( - ['id' => 3, 'name' => 'Cid'], - $merger->merge(row(['id' => 3]), row(['name' => 'Cid']))->toArray(), + $merger->merge(row(['id' => 2]), row(['name' => 'Bob', 'age' => 30])), ); + static::assertSame(['id' => 3, 'name' => 'Cid'], $merger->merge(row(['id' => 3]), row(['name' => 'Cid']))); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinSchemaTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinSchemaTest.php index 1f8d52e90a..0ad49db36a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinSchemaTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinSchemaTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Join; +use Flow\ETL\Exception\SchemaDefinitionNotUniqueException; use Flow\ETL\Join\Join; use Flow\ETL\Join\JoinSchema; use Flow\ETL\Tests\FlowTestCase; @@ -120,4 +121,24 @@ public function test_right_makes_the_left_side_nullable(): void ), ); } + + public function test_a_cross_name_collision_suggests_a_prefix(): void + { + $this->expectException(SchemaDefinitionNotUniqueException::class); + $this->expectExceptionMessageMatches( + '/Entry definitions must be unique.*\. Please consider using join prefix option$/', + ); + + (new JoinSchema())->cross(schema(int_schema('id')), schema(int_schema('id'))); + } + + public function test_a_keyed_join_name_collision_suggests_a_prefix(): void + { + $this->expectException(SchemaDefinitionNotUniqueException::class); + $this->expectExceptionMessageMatches( + '/Entry definitions must be unique.*\. Please consider using join prefix option$/', + ); + + (new JoinSchema())->of(Join::left, schema(int_schema('id'), str_schema('name')), schema(str_schema('name'))); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php index a847100c5c..341f0962ed 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php @@ -105,10 +105,10 @@ public function test_the_merger_drops_the_same_column_the_schema_does(): void { static::assertSame( ['id' => 1, 'country' => 'PL', 'name' => 'Norbert'], - JoinShape::of(join_on(['id' => 'id']), Join::inner) - ->merger() - ->merge(row(['id' => 1, 'country' => 'PL']), row(['id' => 1, 'name' => 'Norbert'])) - ->toArray(), + JoinShape::of(join_on(['id' => 'id']), Join::inner)->merger()->merge( + row(['id' => 1, 'country' => 'PL']), + row(['id' => 1, 'name' => 'Norbert']), + ), ); } @@ -116,10 +116,10 @@ public function test_the_merger_of_a_right_join_keeps_the_right_side_value(): vo { static::assertSame( ['country' => 'PL', 'id' => 2, 'name' => 'Norbert'], - JoinShape::of(join_on(['id' => 'id']), Join::right) - ->merger() - ->merge(row(['id' => 1, 'country' => 'PL']), row(['id' => 2, 'name' => 'Norbert'])) - ->toArray(), + JoinShape::of(join_on(['id' => 'id']), Join::right)->merger()->merge( + row(['id' => 1, 'country' => 'PL']), + row(['id' => 2, 'name' => 'Norbert']), + ), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/AdaptiveRowHydratorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/AdaptiveRowHydratorTest.php deleted file mode 100644 index 07bb3601d2..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/AdaptiveRowHydratorTest.php +++ /dev/null @@ -1,62 +0,0 @@ -hydrate( - [new RawRowValues(['id' => 1, 'name' => 'flow']), new RawRowValues(['id' => 2, 'name' => null])], - schema(int_schema('id'), str_schema('name', nullable: true)), - ); - - static::assertSame(2, $rows->count()); - static::assertSame(1, $rows->first()->get('id')); - static::assertNull($rows->all()[1]->get('name')); - } - - public function test_dehydrate_turns_rows_into_typed_values(): void - { - $dehydrated = (new AdaptiveRowHydrator())->dehydrate(rows( - schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'flow']), - )); - - static::assertCount(1, $dehydrated); - static::assertSame(['id' => 1, 'name' => 'flow'], $dehydrated[0]->values); - } - - public function test_hydrate_throws_on_missing_required_structure_element(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('Rows do not match their schema: column "data" (row 0)'); - - (new AdaptiveRowHydrator())->hydrate([new RawRowValues(['data' => [ - 'id' => 1, - ]])], schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()])))); - } - - public function test_is_native_when_the_native_hydrator_is_supported(): void - { - static::assertSame(NativeRowHydrator::isSupported(), (new AdaptiveRowHydrator())->isNative()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php index 3a15848672..1330f9c77a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php @@ -11,14 +11,12 @@ use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_list; -use function Flow\Types\DSL\type_map; -use function Flow\Types\DSL\type_mixed; use function Flow\Types\DSL\type_string; final class ArrayToRowTest extends FlowTestCase @@ -28,7 +26,7 @@ public function test_building_array_to_row_with_entry_that_is_list_of_strings(): $row = array_to_row( ['data' => ['a', 'b', 'c', 'd']], schema(list_schema('data', type_list(type_string()))), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals(row(['data' => ['a', 'b', 'c', 'd']]), $row); @@ -41,11 +39,8 @@ public function test_building_single_row_from_array_with_rows_fails(): void ['id' => 1234, 'deleted' => false, 'phase' => null], ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], ], - schema( - map_schema('e00', type_map(type_string(), type_mixed()), nullable: true), - map_schema('e01', type_map(type_string(), type_mixed()), nullable: true), - ), - flow_context(config())->hydrator(), + schema(json_schema('e00', nullable: true), json_schema('e01', nullable: true)), + flow_context(config())->backend(), ); static::assertEquals( @@ -62,7 +57,7 @@ public function test_building_single_row_from_array_with_schema_and_additional_f $row = array_to_row( ['id' => 1234, 'deleted' => false, 'phase' => null], schema(int_schema('id'), bool_schema('deleted')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals(row(['id' => 1234, 'deleted' => false]), $row); @@ -73,7 +68,7 @@ public function test_building_single_row_from_array_with_schema_but_entries_not_ $row = array_to_row( ['id' => 1234, 'deleted' => false], schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', true)), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals(row(['id' => 1234, 'deleted' => false, 'phase' => null]), $row); @@ -88,7 +83,7 @@ public function test_building_single_row_from_flat_array(): void 'phase' => null, ], schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', true)), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals(row(['id' => 1234, 'deleted' => false, 'phase' => null]), $row); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/HydratedBatchTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/HydratedBatchTest.php deleted file mode 100644 index 4173e8556d..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/HydratedBatchTest.php +++ /dev/null @@ -1,163 +0,0 @@ - 1, 'name' => null])), - (new HydratedBatch())->of( - [new RawRowValues(['id' => 1])], - schema(int_schema('id'), str_schema('name', nullable: true)), - ), - ); - } - - public function test_a_missing_nullable_column_is_padded_by_the_batch_door(): void - { - static::assertSame( - ['id', 'name'], - (new HydratedBatch()) - ->of([new RawRowValues(['id' => 1])], schema(int_schema('id'), str_schema('name', nullable: true))) - ->first() - ->names(), - ); - } - - public function test_a_refused_value_in_the_first_row_reports_row_zero(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage( - 'Rows do not match their schema: column "i" (row 0): could not convert \'abc\' (string) to integer', - ); - - (new HydratedBatch())->of([new RawRowValues(['i' => 'abc'])], schema(int_schema('i'))); - } - - public function test_a_refusal_in_the_second_row_reports_row_one(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage( - 'Rows do not match their schema: column "i" (row 1): could not convert \'abc\' (string) to integer', - ); - - (new HydratedBatch())->of([ - new RawRowValues(['i' => 1]), - new RawRowValues(['i' => 'abc']), - ], schema(int_schema('i'))); - } - - public function test_a_refused_value_is_reported_with_its_column_and_row(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage( - 'Rows do not match their schema: column "i" (row 1): could not convert \'n/a\' (string) to integer', - ); - - (new HydratedBatch())->of([ - new RawRowValues(['i' => 1]), - new RawRowValues(['i' => 'n/a']), - new RawRowValues(['i' => 3]), - ], schema(int_schema('i'))); - } - - public function test_a_null_on_a_not_null_column_is_reported_as_a_value_that_does_not_match(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage( - 'Rows do not match their schema: column "i" (row 0): could not convert null to integer, column is not nullable', - ); - - (new HydratedBatch())->of([new RawRowValues(['i' => null])], schema(int_schema('i'))); - } - - public function test_a_value_the_schema_does_not_declare_is_dropped(): void - { - static::assertSame( - ['id'], - (new HydratedBatch()) - ->of([new RawRowValues(['id' => 1, 'undeclared' => 'x'])], schema(int_schema('id'))) - ->first() - ->names(), - ); - } - - public function test_metadata_is_folded_onto_the_column_with_last_write_winning(): void - { - static::assertSame( - ['k' => 'v2'], - (new HydratedBatch()) - ->of([ - new RawRowValues(['id' => 1], ['id' => Metadata::fromArray(['k' => 'v1'])]), - new RawRowValues(['id' => 2], ['id' => Metadata::fromArray(['k' => 'v2'])]), - ], schema(int_schema('id'))) - ->schema() - ->get('id') - ->metadata() - ->normalize(), - ); - } - - public function test_metadata_is_folded_onto_a_numeric_column_name(): void - { - static::assertSame( - ['k' => 'v'], - (new HydratedBatch()) - ->of([new RawRowValues([], ['0' => Metadata::fromArray([ - 'k' => 'v', - ])])], schema(int_schema('0', nullable: true))) - ->schema() - ->get('0') - ->metadata() - ->normalize(), - ); - } - - public function test_metadata_for_an_undeclared_column_is_ignored(): void - { - static::assertEquals( - schema(int_schema('id')), - (new HydratedBatch())->of([new RawRowValues(['id' => 1], ['nope' => Metadata::fromArray([ - 'k' => 'v', - ])])], schema(int_schema('id')))->schema(), - ); - } - - public function test_rows_follow_the_schema_column_order(): void - { - static::assertSame( - ['id', 'name'], - (new HydratedBatch()) - ->of([new RawRowValues(['name' => 'a', 'id' => 1])], schema(int_schema('id'), str_schema('name'))) - ->first() - ->names(), - ); - } - - public function test_every_value_is_cast_against_its_own_column(): void - { - static::assertEquals( - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => '2'])), - (new HydratedBatch())->of( - [new RawRowValues(['id' => '1', 'name' => 2])], - schema(int_schema('id'), str_schema('name')), - ), - ); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/InferredBatchTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/InferredBatchTest.php index 894983b80b..46ffab9a81 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/InferredBatchTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/InferredBatchTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Row; +use DateTimeImmutable; +use DateTimeZone; use Flow\ETL\Row\InferredBatch; -use Flow\ETL\Row\RawRowValues; -use Flow\ETL\Schema\Metadata; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\int_schema; @@ -22,8 +22,8 @@ public function test_a_column_absent_from_one_row_is_nullable(): void static::assertEquals( schema(int_schema('id'), str_schema('name', nullable: true)), (new InferredBatch())->of([ - new RawRowValues(['id' => 1, 'name' => 'a']), - new RawRowValues(['id' => 2]), + ['id' => 1, 'name' => 'a'], + ['id' => 2], ])->schema(), ); } @@ -38,8 +38,8 @@ public function test_an_explicit_null_makes_the_column_nullable(): void static::assertEquals( schema(int_schema('id'), str_schema('name', nullable: true)), (new InferredBatch())->of([ - new RawRowValues(['id' => 1, 'name' => 'a']), - new RawRowValues(['id' => 2, 'name' => null]), + ['id' => 1, 'name' => 'a'], + ['id' => 2, 'name' => null], ])->schema(), ); } @@ -55,32 +55,17 @@ public function test_a_numeric_column_name_is_a_string_column(): void } // PHP cannot hold '0' as a string key, which is precisely the shape under test - $inferred = (new InferredBatch())->of([new RawRowValues($values)]); + $inferred = (new InferredBatch())->of([$values]); static::assertSame(['0', '7'], $inferred->schema()->references()->names()); static::assertSame([['0' => 1, '7' => 8]], $inferred->toArray()); } - public function test_metadata_travels_from_the_raw_values_onto_the_definition(): void - { - static::assertSame( - ['origin' => 'csv'], - (new InferredBatch()) - ->of([ - new RawRowValues(['id' => 1], ['id' => Metadata::fromArray(['origin' => 'csv'])]), - ]) - ->schema() - ->get('id') - ->metadata() - ->normalize(), - ); - } - public function test_rows_keep_their_values_verbatim(): void { static::assertEquals( rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])), - (new InferredBatch())->of([new RawRowValues(['id' => 1, 'name' => 'a'])]), + (new InferredBatch())->of([['id' => 1, 'name' => 'a']]), ); } @@ -91,11 +76,37 @@ public function test_rows_keep_their_values_verbatim(): void public function test_widening_folds_int_and_string_into_one_column_and_converts_the_values(): void { $rows = (new InferredBatch())->of([ - new RawRowValues(['v' => 1]), - new RawRowValues(['v' => 'text']), + ['v' => 1], + ['v' => 'text'], ]); static::assertSame('string', $rows->schema()->get('v')->type()->toString()); static::assertSame([['v' => '1'], ['v' => 'text']], $rows->toArray()); } + + public function test_a_midnight_outside_utc_infers_datetime(): void + { + static::assertSame( + 'datetime', + (new InferredBatch()) + ->of([['at' => new DateTimeImmutable('2026-01-01 00:00:00', new DateTimeZone('Europe/Warsaw'))]]) + ->schema() + ->get('at') + ->type() + ->toString(), + ); + } + + public function test_a_midnight_in_utc_infers_date(): void + { + static::assertSame( + 'date', + (new InferredBatch()) + ->of([['at' => new DateTimeImmutable('2026-01-01 00:00:00', new DateTimeZone('UTC'))]]) + ->schema() + ->get('at') + ->type() + ->toString(), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/NativeRowHydratorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/NativeRowHydratorTest.php deleted file mode 100644 index ce00a48721..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/NativeRowHydratorTest.php +++ /dev/null @@ -1,742 +0,0 @@ -}> - */ - public static function serializable_datasets(): Generator - { - yield 'scalars over multiple rows' => [ - schema(int_schema('id'), str_schema('name', nullable: true), float_schema('p'), bool_schema('a')), - [ - new RawRowValues(['id' => 1, 'name' => 'x', 'p' => 1.5, 'a' => true]), - new RawRowValues(['id' => 2, 'name' => null, 'p' => -0.25, 'a' => false]), - new RawRowValues(['id' => 3, 'name' => 'z', 'p' => 0.0, 'a' => true]), - ], - ]; - - yield 'null values across rows' => [ - schema(int_schema('id'), str_schema('name', nullable: true)), - [ - new RawRowValues(['id' => 1, 'name' => null]), - new RawRowValues(['id' => 2, 'name' => null]), - ], - ]; - - yield 'absent columns are skipped' => [ - schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('flag', nullable: true)), - [ - new RawRowValues(['id' => 1]), - new RawRowValues(['id' => 2, 'name' => 'y']), - ], - ]; - - yield 'per-value metadata divergence across rows' => [ - schema(int_schema('id')), - [ - new RawRowValues(['id' => 1], ['id' => Metadata::fromArray(['k' => 'v1'])]), - new RawRowValues(['id' => 2], ['id' => Metadata::fromArray(['k' => 'v2'])]), - ], - ]; - - yield 'per-value metadata together with a null value' => [ - schema(int_schema('id', nullable: true)), - [new RawRowValues(['id' => null], ['id' => Metadata::fromArray(['k' => 'v'])])], - ]; - - yield 'temporal and uuid values' => [ - schema(datetime_schema('at'), date_schema('d'), time_schema('t'), uuid_schema('u')), - [new RawRowValues([ - 'at' => new DateTimeImmutable('2025-01-01 12:00:00.123456', new DateTimeZone('Europe/Warsaw')), - 'd' => new DateTimeImmutable('2025-03-01'), - 't' => new DateInterval('PT2H30M5S'), - 'u' => new Uuid('01234567-89ab-4def-8123-456789abcdef'), - ])], - ]; - - yield 'containers and json' => [ - schema( - list_schema('l', type_list(type_integer())), - map_schema('m', type_map(type_string(), type_integer())), - structure_schema('st', type_structure(['a' => type_integer(), 'b' => type_string()])), - list_schema('opt', type_list(type_optional(type_integer()))), - json_schema('j'), - ), - [new RawRowValues([ - 'l' => [1, 2, 3], - 'm' => ['a' => 1], - 'st' => ['a' => 1, 'b' => 'kept'], - 'opt' => [1, null], - 'j' => Json::fromArray(['x' => 1]), - ])], - ]; - - yield 'enum values including a null variant' => [ - schema(enum_schema('s', ParitySuit::class, nullable: true)), - [ - new RawRowValues(['s' => ParitySuit::Hearts]), - new RawRowValues(['s' => ParitySuit::Spades]), - new RawRowValues(['s' => null]), - ], - ]; - - yield 'null definition column' => [ - schema(null_schema('n'), int_schema('id', nullable: true)), - [ - new RawRowValues(['n' => null, 'id' => null]), - new RawRowValues(['n' => null, 'id' => 5]), - ], - ]; - - yield 'empty batch' => [schema(int_schema('id')), []]; - } - - /** - * @return \Generator}> - */ - public static function hydratable_datasets(): Generator - { - yield 'scalar columns from raw strings and coercion edges' => [ - schema(int_schema('id'), float_schema('price'), bool_schema('active'), str_schema('name', nullable: true)), - [ - new RawRowValues(['id' => '42', 'price' => '3.14', 'active' => 'yes', 'name' => 7]), - new RawRowValues(['id' => ' 7', 'price' => '1e3', 'active' => 'OFF', 'name' => 1.5]), - new RawRowValues(['id' => '007', 'price' => '.5', 'active' => 'ON', 'name' => true]), - new RawRowValues(['id' => '1e2', 'price' => true, 'active' => 0, 'name' => false]), - new RawRowValues(['id' => '9223372036854775807', 'price' => 7, 'active' => 3.5, 'name' => null]), - new RawRowValues(['id' => 5, 'price' => 2.5, 'active' => true, 'name' => 'text']), - ], - ]; - - yield 'nested optional datetimes and structures move into the declared shape' => [ - schema( - list_schema('at', type_list(type_optional(type_datetime('Europe/Warsaw')))), - structure_schema('s', type_structure([ - 'at' => type_optional(type_datetime('Europe/Warsaw')), - 'inner' => type_optional(type_structure(['a' => type_integer(), 'b' => type_string()])), - ])), - ), - [ - new RawRowValues([ - 'at' => [new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), null], - 's' => [ - 'at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), - 'inner' => ['b' => 'x', 'a' => 1], - ], - ]), - ], - ]; - - yield 'nested positive integer and string family elements' => [ - schema( - list_schema('counts', type_list(type_positive_integer())), - structure_schema('labels', type_structure(['label' => type_non_empty_string()])), - structure_schema('codes', type_structure(['code' => type_numeric_string()])), - ), - [ - new RawRowValues([ - 'counts' => [5, 7], - 'labels' => ['label' => 'x'], - 'codes' => ['code' => '42'], - ]), - new RawRowValues([ - 'counts' => ['5', 8], - 'labels' => ['label' => 9], - 'codes' => ['code' => 42], - ]), - new RawRowValues([ - 'counts' => [], - 'labels' => ['label' => 1.5], - 'codes' => ['code' => '3.14'], - ]), - new RawRowValues([ - 'counts' => [1], - 'labels' => ['label' => true], - 'codes' => ['code' => 42.5], - ]), - ], - ]; - - $shared = new DateTimeImmutable('2025-01-01 12:00:00.123456', new DateTimeZone('Europe/Warsaw')); - - yield 'temporal columns preserving object identity topology' => [ - schema( - datetime_schema('at', zone: 'Europe/Warsaw'), - datetime_schema('at2', zone: 'Europe/Warsaw'), - date_schema('d'), - ), - [ - new RawRowValues(['at' => $shared, 'at2' => $shared, 'd' => $shared]), - new RawRowValues([ - 'at' => $shared, - 'at2' => '2024-03-01 10:20:30', - 'd' => new DateTimeImmutable('2025-03-01'), - ]), - new RawRowValues(['at' => 1700000000, 'at2' => 1700000000.5, 'd' => '2024-03-05 08:30:00']), - new RawRowValues(['at' => '2024-02-29T12:00:00+02:00', 'at2' => '2024-06-01', 'd' => 1700000000]), - ], - ]; - - yield 'uuid and json columns from raw values' => [ - schema(uuid_schema('u', nullable: true), json_schema('j')), - [ - new RawRowValues(['u' => '01234567-89ab-4def-8123-456789abcdef', 'j' => '["a","b"]']), - new RawRowValues(['u' => new Uuid('01234567-89ab-4def-8123-456789abcdef'), 'j' => '{"a":1}']), - new RawRowValues(['u' => null, 'j' => ['a' => 1]]), - new RawRowValues(['u' => '11234567-89ab-4def-8123-456789abcdef', 'j' => []]), - new RawRowValues(['u' => '21234567-89ab-4def-8123-456789abcdef', 'j' => Json::fromArray(['x' => 1])]), - ], - ]; - - yield 'containers from raw values' => [ - schema( - list_schema('l', type_list(type_integer())), - list_schema('ll', type_list(type_list(type_integer()))), - map_schema('m', type_map(type_string(), type_integer())), - map_schema('mi', type_map(type_integer(), type_string())), - list_schema('lo', type_list(type_optional(type_integer()))), - structure_schema('st', type_structure([ - 'a' => type_integer(), - 'b' => structure_element('b', type_string(), optional: true), - ])), - ), - [ - new RawRowValues([ - 'l' => ['1', 2, '3'], - 'll' => [['1', '2'], [3]], - 'm' => ['a' => '1', 'b' => 2], - 'mi' => [0 => 'x', 5 => 7], - 'lo' => ['1', null, 3], - 'st' => ['a' => '5', 'extra' => 'dropped'], - ]), - new RawRowValues([ - 'l' => [], - 'll' => [], - 'm' => [], - 'mi' => [], - 'lo' => [], - 'st' => ['a' => 1, 'b' => 'present'], - ]), - ], - ]; - - yield 'exotic columns cast through the per-value fallback' => [ - schema(enum_schema('s', ParitySuit::class), xml_schema('x'), time_schema('t')), - [ - new RawRowValues([ - 's' => ParitySuit::Hearts, - 'x' => 'v', - 't' => new DateInterval('PT2H30M5S'), - ]), - new RawRowValues(['s' => 'h', 'x' => '', 't' => 'PT2H']), - ], - ]; - - yield 'metadata variants fill-missing and extra raw keys' => [ - schema( - int_schema('id', nullable: true), - str_schema('name', nullable: true), - bool_schema('flag', nullable: true), - ), - [ - new RawRowValues(['id' => '1'], ['id' => Metadata::fromArray(['k' => 'v1'])]), - new RawRowValues([]), - new RawRowValues(['id' => 2, 'name' => null, 'unknown' => 'dropped', 'flag' => 'on']), - new RawRowValues(['id' => null], ['id' => Metadata::fromArray(['k' => 'v2'])]), - ], - ]; - - yield 'empty cast batch' => [schema(int_schema('id')), []]; - - yield 'all-optional structure with no matching keys' => [ - schema(structure_schema('st', type_structure(['b' => structure_element( - 'b', - type_string(), - optional: true, - )]))), - [new RawRowValues(['st' => ['other' => 1]])], - ]; - - yield 'interleaved structure' => [ - schema(structure_schema('st', type_structure([ - 'z' => type_integer(), - 'a' => structure_element('a', type_string(), optional: true), - 'b' => type_string(), - ]))), - [ - new RawRowValues(['st' => ['b' => 'x', 'z' => '5']]), - new RawRowValues(['st' => ['z' => 1, 'a' => 'present', 'b' => 'y']]), - ], - ]; - } - - /** - * @return \Generator, class-string<\Throwable>, string}> - */ - public static function refusing_datasets(): Generator - { - yield 'null in a not null column' => [ - schema(int_schema('id'), str_schema('name')), - [new RawRowValues(['id' => 1, 'name' => null])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "name" (row 0): could not convert null to string, column is not nullable', - ]; - - yield 'non numeric string in an integer column' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => 'abc'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 0): could not convert \'abc\' (string) to integer', - ]; - - yield 'trailing garbage after digits in an integer column' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => '12abc'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 0): could not convert \'12abc\' (string) to integer', - ]; - - yield 'hex string in a float column' => [ - schema(float_schema('price')), - [new RawRowValues(['price' => '0x1A'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "price" (row 0): could not convert \'0x1A\' (string) to float', - ]; - - yield 'unrecognised word in a boolean column' => [ - schema(bool_schema('active')), - [new RawRowValues(['active' => 'weird'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "active" (row 0): could not convert \'weird\' (string) to boolean', - ]; - - yield 'array in an integer column' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => [1, 2, 3]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 0): could not convert array (list) to integer', - ]; - - yield 'invalid uuid string' => [ - schema(uuid_schema('u')), - [new RawRowValues(['u' => 'not-a-uuid'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "u" (row 0): could not convert \'not-a-uuid\' (string) to uuid', - ]; - - yield 'uppercase uuid string' => [ - schema(uuid_schema('u')), - [new RawRowValues(['u' => '01234567-89AB-4DEF-8123-456789ABCDEF'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "u" (row 0): could not convert \'01234567-89AB-4DEF-8123-456789AB...\' (string) to uuid', - ]; - - yield 'json from a scalar' => [ - schema(json_schema('j')), - [new RawRowValues(['j' => 5])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "j" (row 0): could not convert 5 (integer) to json', - ]; - - yield 'json from an invalid json string' => [ - schema(json_schema('j')), - [new RawRowValues(['j' => '{oops'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "j" (row 0): could not convert \'{oops\' (string) to json', - ]; - - yield 'json from a plain string' => [ - schema(json_schema('j')), - [new RawRowValues(['j' => 'plain'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "j" (row 0): could not convert \'plain\' (string) to json', - ]; - - yield 'datetime from garbage' => [ - schema(datetime_schema('at')), - [new RawRowValues(['at' => 'not-a-date'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "at" (row 0): could not convert \'not-a-date\' (string) to datetime', - ]; - - yield 'datetime from an array' => [ - schema(datetime_schema('at')), - [new RawRowValues(['at' => ['nope']])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "at" (row 0): could not convert array (list) to datetime', - ]; - - yield 'date from garbage' => [ - schema(date_schema('d')), - [new RawRowValues(['d' => 'not-a-date'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "d" (row 0): could not convert \'not-a-date\' (string) to date', - ]; - - yield 'string map with integer keys' => [ - schema(map_schema('m', type_map(type_string(), type_integer()))), - [new RawRowValues(['m' => [5 => 1]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "m" (row 0): could not convert array (map) to map', - ]; - - yield 'list with non-sequential keys' => [ - schema(list_schema('l', type_list(type_integer()))), - [new RawRowValues(['l' => [1 => 'x']])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert array (map) to list', - ]; - - yield 'positive integer list from a non-numeric string' => [ - schema(list_schema('l', type_list(type_positive_integer()))), - [new RawRowValues(['l' => ['abc']])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', - ]; - - yield 'positive integer list from a negative int' => [ - schema(list_schema('l', type_list(type_positive_integer()))), - [new RawRowValues(['l' => [-3]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', - ]; - - yield 'structure missing required element' => [ - schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), - [new RawRowValues(['data' => ['id' => 1]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer}) to structure{id: integer, name: string}', - ]; - - yield 'structure present-null required element' => [ - schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), - [new RawRowValues(['data' => ['id' => 1, 'name' => null]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer, name: null}) to structure{id: integer, name: string}', - ]; - - yield 'structure present-null optional element' => [ - schema(structure_schema('data', type_structure([ - 'id' => type_integer(), - 'name' => structure_element('name', type_string(), optional: true), - ]))), - [new RawRowValues(['data' => ['id' => 1, 'name' => null]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer, name: null}) to structure{id: integer, name?: string}', - ]; - - // the refusal is placed at the batch position, so a constant row index would diverge here - yield 'non numeric string in the second row of an integer column' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => '1']), new RawRowValues(['id' => 'x'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 1): could not convert \'x\' (string) to integer', - ]; - - yield 'a not null column the row does not carry' => [ - schema(int_schema('id'), str_schema('name')), - [new RawRowValues(['id' => 1])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "name" (row 0) declared by the schema is missing from the row', - ]; - - yield 'integer overflow' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => '9223372036854775808'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 0): could not convert \'9223372036854775808\' (string) to integer', - ]; - - yield 'date from an empty string' => [ - schema(date_schema('d')), - [new RawRowValues(['d' => ''])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "d" (row 0): could not convert \'\' (string) to date', - ]; - - yield 'datetime from a relative word' => [ - schema(datetime_schema('at')), - [new RawRowValues(['at' => 'now'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "at" (row 0): could not convert \'now\' (string) to datetime', - ]; - - yield 'string from a null element inside a list' => [ - schema(list_schema('l', type_list(type_string()))), - [new RawRowValues(['l' => ['a', null]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', - ]; - - yield 'list from a scalar' => [ - schema(list_schema('l', type_list(type_integer()))), - [new RawRowValues(['l' => 5])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert 5 (integer) to list', - ]; - - // ordering: an absence must not pre-empt a refusal that PHP reports first, or the two - // hydrators name different columns - and different ROWS - for the same batch - yield 'an absent column before a cast refusal in the same row' => [ - schema(int_schema('a'), int_schema('b')), - [new RawRowValues(['b' => 'abc'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "b" (row 0): could not convert \'abc\' (string) to integer', - ]; - - yield 'an absent column in row 0 before a cast refusal in row 1' => [ - schema(int_schema('a'), int_schema('b')), - [new RawRowValues(['a' => 1]), new RawRowValues(['a' => 1, 'b' => 'abc'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "b" (row 1): could not convert \'abc\' (string) to integer', - ]; - - yield 'an absent column in row 0 before a present null in row 1' => [ - schema(int_schema('a'), int_schema('b')), - [new RawRowValues(['a' => 1]), new RawRowValues(['a' => 1, 'b' => null])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "b" (row 1): could not convert null to integer, column is not nullable', - ]; - - // an exception the types package did not raise is not a refusal, so neither engine wraps it - yield 'a type raising an exception outside the types package' => [ - schema( - new ForeignTypeDefinition('a', new ThrowingType(new LogicException('stub type refuses everything'))), - ), - [new RawRowValues(['a' => [1, 2]])], - LogicException::class, - 'stub type refuses everything', - ]; - } - - /** - * @param list $batch - */ - #[DataProvider('serializable_datasets')] - public function test_native_hydrate_of_typed_values_is_serialize_identical_to_php( - Schema $schema, - array $batch, - ): void { - if (!NativeRowHydrator::isSupported()) { - static::markTestSkipped('flow_php extension with the native hydrator is not loaded.'); - } - - static::assertSame( - serialize((new PhpRowHydrator())->hydrate($batch, $schema)), - serialize((new NativeRowHydrator())->hydrate($batch, $schema)), - ); - } - - /** - * @param list $batch - */ - #[DataProvider('serializable_datasets')] - public function test_native_dehydrate_is_serialize_identical_to_php(Schema $schema, array $batch): void - { - if (!NativeRowHydrator::isSupported()) { - static::markTestSkipped('flow_php extension with the native hydrator is not loaded.'); - } - - $php = new PhpRowHydrator(); - $rows = $php->hydrate($batch, $schema); - - static::assertSame(serialize($php->dehydrate($rows)), serialize((new NativeRowHydrator())->dehydrate($rows))); - } - - /** - * @param list $batch - */ - #[DataProvider('hydratable_datasets')] - public function test_native_hydrate_of_raw_values_is_serialize_identical_to_php(Schema $schema, array $batch): void - { - if (!NativeRowHydrator::isSupported()) { - static::markTestSkipped('flow_php extension with the native hydrator is not loaded.'); - } - - static::assertSame( - serialize((new PhpRowHydrator())->hydrate($batch, $schema)), - serialize((new NativeRowHydrator())->hydrate($batch, $schema)), - ); - } - - /** - * The expected class and message are pinned literally rather than compared between the two - * hydrators, so a drift they share still reddens. - * - * @param list $batch - * @param class-string<\Throwable> $exception - */ - #[DataProvider('refusing_datasets')] - public function test_php_and_native_refuse_identically( - Schema $schema, - array $batch, - string $exception, - string $message, - ): void { - $refusal = static function (Hydrator $hydrator) use ($batch, $schema): Throwable { - try { - $hydrator->hydrate($batch, $schema); - } catch (Throwable $e) { - return $e; - } - - throw new LogicException('the batch was accepted, but the schema declares it a refusal'); - }; - - $php = $refusal(new PhpRowHydrator()); - - static::assertSame($exception, $php::class); - static::assertSame($message, $php->getMessage()); - - if (!NativeRowHydrator::isSupported()) { - return; - } - - $native = $refusal(new NativeRowHydrator()); - - static::assertSame($exception, $native::class); - static::assertSame($message, $native->getMessage()); - } - - /** - * @param list $batch - */ - #[DataProvider('hydratable_datasets')] - public function test_native_hydrate_is_idempotent_on_already_hydrated_values(Schema $schema, array $batch): void - { - if (!NativeRowHydrator::isSupported()) { - static::markTestSkipped('flow_php extension with the native hydrator is not loaded.'); - } - - $php = new PhpRowHydrator(); - $recastBatch = []; - - foreach ($php->hydrate($batch, $schema) as $row) { - $recastBatch[] = new RawRowValues($row->values()); - } - - static::assertSame( - serialize($php->hydrate($recastBatch, $schema)), - serialize((new NativeRowHydrator())->hydrate($recastBatch, $schema)), - ); - } - - public function test_native_hydrate_follows_schema_changes(): void - { - if (!NativeRowHydrator::isSupported()) { - static::markTestSkipped('flow_php extension with the native hydrator is not loaded.'); - } - - $schema = schema(int_schema('id'), str_schema('name')); - $php = new PhpRowHydrator(); - $native = new NativeRowHydrator(); - - $batch = [new RawRowValues(['id' => '1', 'name' => 7])]; - static::assertSame(serialize($php->hydrate($batch, $schema)), serialize($native->hydrate($batch, $schema))); - - $schema = $schema->add(bool_schema('active', nullable: true)); - - $batch = [new RawRowValues(['id' => '2', 'name' => 'b', 'active' => 'yes'])]; - static::assertSame(serialize($php->hydrate($batch, $schema)), serialize($native->hydrate($batch, $schema))); - - $schema = $schema->makeNullable(); - - $batch = [new RawRowValues(['id' => null, 'name' => null, 'active' => null])]; - static::assertSame(serialize($php->hydrate($batch, $schema)), serialize($native->hydrate($batch, $schema))); - } - - public function test_native_moves_markup_values_verbatim(): void - { - if (!NativeRowHydrator::isSupported()) { - static::markTestSkipped('flow_php extension with the native hydrator is not loaded.'); - } - - $document = new DOMDocument(); - $document->loadXML('v'); - - $rows = rows(schema(xml_schema('doc')), row(['doc' => $document])); - - $php = new PhpRowHydrator(); - $native = new NativeRowHydrator(); - - $phpDehydrated = $php->dehydrate($rows); - $nativeDehydrated = $native->dehydrate($rows); - - static::assertSame($phpDehydrated[0]->values['doc'], $nativeDehydrated[0]->values['doc']); - static::assertEquals($phpDehydrated[0]->types['doc'], $nativeDehydrated[0]->types['doc']); - } - - public function test_supports_extension_requires_the_native_class(): void - { - static::assertSame( - extension_loaded('flow_php') && class_exists(RustRowHydratorNative::class, false), - NativeRowHydrator::isSupported(), - ); - } -} - -enum ParitySuit: string -{ - case Hearts = 'h'; - case Spades = 's'; -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/PhpRowHydratorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/PhpRowHydratorTest.php index 47e6eadf6d..a974e8b264 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/PhpRowHydratorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/PhpRowHydratorTest.php @@ -5,10 +5,13 @@ namespace Flow\ETL\Tests\Unit\Row; use DateTimeImmutable; +use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Row\RawRowValues; use Flow\ETL\Row\TypedRowValues; +use Flow\ETL\Schema; +use Flow\ETL\Schema\Metadata; use Flow\ETL\Tests\Double\ForeignTypeDefinition; use Flow\ETL\Tests\Double\ThrowingType; use Flow\ETL\Tests\FlowTestCase; @@ -16,27 +19,274 @@ use Flow\Types\Type\Logical\MapType; use Flow\Types\Type\Logical\StructureType; use Flow\Types\Value\Uuid; +use Generator; use LogicException; +use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; use function Flow\ETL\DSL\uuid_schema; +use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_positive_integer; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; -use function serialize; final class PhpRowHydratorTest extends FlowTestCase { + /** + * @return \Generator, class-string<\Throwable>, string}> + */ + public static function refusing_datasets(): Generator + { + yield 'null in a not null column' => [ + schema(int_schema('id'), str_schema('name')), + [new RawRowValues(['id' => 1, 'name' => null])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "name" (row 0): could not convert null to string, column is not nullable', + ]; + + yield 'non numeric string in an integer column' => [ + schema(int_schema('id')), + [new RawRowValues(['id' => 'abc'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 0): could not convert \'abc\' (string) to integer', + ]; + + yield 'trailing garbage after digits in an integer column' => [ + schema(int_schema('id')), + [new RawRowValues(['id' => '12abc'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 0): could not convert \'12abc\' (string) to integer', + ]; + + yield 'hex string in a float column' => [ + schema(float_schema('price')), + [new RawRowValues(['price' => '0x1A'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "price" (row 0): could not convert \'0x1A\' (string) to float', + ]; + + yield 'unrecognised word in a boolean column' => [ + schema(bool_schema('active')), + [new RawRowValues(['active' => 'weird'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "active" (row 0): could not convert \'weird\' (string) to boolean', + ]; + + yield 'array in an integer column' => [ + schema(int_schema('id')), + [new RawRowValues(['id' => [1, 2, 3]])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 0): could not convert array (list) to integer', + ]; + + yield 'invalid uuid string' => [ + schema(uuid_schema('u')), + [new RawRowValues(['u' => 'not-a-uuid'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "u" (row 0): could not convert \'not-a-uuid\' (string) to uuid', + ]; + + yield 'uppercase uuid string' => [ + schema(uuid_schema('u')), + [new RawRowValues(['u' => '01234567-89AB-4DEF-8123-456789ABCDEF'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "u" (row 0): could not convert \'01234567-89AB-4DEF-8123-456789AB...\' (string) to uuid', + ]; + + yield 'json from a scalar' => [ + schema(json_schema('j')), + [new RawRowValues(['j' => 5])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "j" (row 0): could not convert 5 (integer) to json', + ]; + + yield 'json from an invalid json string' => [ + schema(json_schema('j')), + [new RawRowValues(['j' => '{oops'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "j" (row 0): could not convert \'{oops\' (string) to json', + ]; + + yield 'json from a plain string' => [ + schema(json_schema('j')), + [new RawRowValues(['j' => 'plain'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "j" (row 0): could not convert \'plain\' (string) to json', + ]; + + yield 'datetime from garbage' => [ + schema(datetime_schema('at')), + [new RawRowValues(['at' => 'not-a-date'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "at" (row 0): could not convert \'not-a-date\' (string) to datetime', + ]; + + yield 'datetime from an array' => [ + schema(datetime_schema('at')), + [new RawRowValues(['at' => ['nope']])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "at" (row 0): could not convert array (list) to datetime', + ]; + + yield 'date from garbage' => [ + schema(date_schema('d')), + [new RawRowValues(['d' => 'not-a-date'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "d" (row 0): could not convert \'not-a-date\' (string) to date', + ]; + + yield 'string map with integer keys' => [ + schema(map_schema('m', type_map(type_string(), type_integer()))), + [new RawRowValues(['m' => [5 => 1]])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "m" (row 0): could not convert array (map) to map', + ]; + + yield 'list with non-sequential keys' => [ + schema(list_schema('l', type_list(type_integer()))), + [new RawRowValues(['l' => [1 => 'x']])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert array (map) to list', + ]; + + yield 'positive integer list from a non-numeric string' => [ + schema(list_schema('l', type_list(type_positive_integer()))), + [new RawRowValues(['l' => ['abc']])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', + ]; + + yield 'positive integer list from a negative int' => [ + schema(list_schema('l', type_list(type_positive_integer()))), + [new RawRowValues(['l' => [-3]])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', + ]; + + yield 'structure missing required element' => [ + schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), + [new RawRowValues(['data' => ['id' => 1]])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer}) to structure{id: integer, name: string}', + ]; + + yield 'structure present-null required element' => [ + schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), + [new RawRowValues(['data' => ['id' => 1, 'name' => null]])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer, name: null}) to structure{id: integer, name: string}', + ]; + + yield 'structure present-null optional element' => [ + schema(structure_schema('data', type_structure([ + 'id' => type_integer(), + 'name' => structure_element('name', type_string(), optional: true), + ]))), + [new RawRowValues(['data' => ['id' => 1, 'name' => null]])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer, name: null}) to structure{id: integer, name?: string}', + ]; + + // the refusal is placed at the batch position, so a constant row index would diverge here + yield 'non numeric string in the second row of an integer column' => [ + schema(int_schema('id')), + [new RawRowValues(['id' => '1']), new RawRowValues(['id' => 'x'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 1): could not convert \'x\' (string) to integer', + ]; + + yield 'a not null column the row does not carry' => [ + schema(int_schema('id'), str_schema('name')), + [new RawRowValues(['id' => 1])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "name" (row 0) declared by the schema is missing from the row', + ]; + + yield 'integer overflow' => [ + schema(int_schema('id')), + [new RawRowValues(['id' => '9223372036854775808'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 0): could not convert \'9223372036854775808\' (string) to integer', + ]; + + yield 'date from an empty string' => [ + schema(date_schema('d')), + [new RawRowValues(['d' => ''])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "d" (row 0): could not convert \'\' (string) to date', + ]; + + yield 'datetime from a relative word' => [ + schema(datetime_schema('at')), + [new RawRowValues(['at' => 'now'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "at" (row 0): could not convert \'now\' (string) to datetime', + ]; + + yield 'string from a null element inside a list' => [ + schema(list_schema('l', type_list(type_string()))), + [new RawRowValues(['l' => ['a', null]])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', + ]; + + yield 'list from a scalar' => [ + schema(list_schema('l', type_list(type_integer()))), + [new RawRowValues(['l' => 5])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert 5 (integer) to list', + ]; + + // ordering: an absence must not pre-empt a refusal that PHP reports first, or the two + // hydrators name different columns - and different ROWS - for the same batch + yield 'an absent column before a cast refusal in the same row' => [ + schema(int_schema('a'), int_schema('b')), + [new RawRowValues(['b' => 'abc'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "b" (row 0): could not convert \'abc\' (string) to integer', + ]; + + yield 'an absent column in row 0 before a cast refusal in row 1' => [ + schema(int_schema('a'), int_schema('b')), + [new RawRowValues(['a' => 1]), new RawRowValues(['a' => 1, 'b' => 'abc'])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "b" (row 1): could not convert \'abc\' (string) to integer', + ]; + + yield 'an absent column in row 0 before a present null in row 1' => [ + schema(int_schema('a'), int_schema('b')), + [new RawRowValues(['a' => 1]), new RawRowValues(['a' => 1, 'b' => null])], + SchemaMismatchException::class, + 'Rows do not match their schema: column "b" (row 1): could not convert null to integer, column is not nullable', + ]; + } + + /** + * @param list $batch + * @param class-string<\Throwable> $exception + */ + #[DataProvider('refusing_datasets')] + public function test_refuses(Schema $schema, array $batch, string $exception, string $message): void + { + $this->expectException($exception); + $this->expectExceptionMessage($message); + + (new PhpRowHydrator())->hydrate($batch, $schema); + } + public function test_absent_schema_column_is_filled_with_typed_null(): void { $rows = (new PhpRowHydrator())->hydrate( @@ -50,10 +300,12 @@ public function test_absent_schema_column_is_filled_with_typed_null(): void static::assertSame(['id' => 1, 'name' => null], $rows->first()->toArray()); } - public function test_hydrate_does_not_wrap_an_exception_the_types_package_did_not_raise(): void + public function test_refuses_a_definition_outside_the_nineteen(): void { - $this->expectException(LogicException::class); - $this->expectExceptionMessage('stub type refuses everything'); + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage( + 'Row does not match its schema: column "a": throwing cannot be a batch column, only the 19 Flow definitions have a column kind', + ); (new PhpRowHydrator())->hydrate([new RawRowValues(['a' => [ 1, @@ -201,6 +453,49 @@ public function test_plan_is_rebuilt_when_the_schema_changes(): void static::assertSame(['id' => 1.0], $prices->first()->toArray()); } + public function test_metadata_is_folded_onto_the_column_with_last_write_winning(): void + { + static::assertSame( + ['k' => 'v2'], + (new PhpRowHydrator()) + ->hydrate([ + new RawRowValues(['id' => 1], ['id' => Metadata::fromArray(['k' => 'v1'])]), + new RawRowValues(['id' => 2], ['id' => Metadata::fromArray(['k' => 'v2'])]), + ], schema(int_schema('id'))) + ->schema() + ->get('id') + ->metadata() + ->normalize(), + ); + } + + public function test_metadata_is_folded_onto_a_numeric_column_name(): void + { + static::assertSame( + ['k' => 'v'], + (new PhpRowHydrator()) + ->hydrate([new RawRowValues([], ['0' => Metadata::fromArray([ + 'k' => 'v', + ])])], schema(int_schema('0', nullable: true))) + ->schema() + ->get('0') + ->metadata() + ->normalize(), + ); + } + + public function test_metadata_for_an_undeclared_column_is_ignored(): void + { + static::assertEquals( + schema(int_schema('id')), + (new PhpRowHydrator()) + ->hydrate([new RawRowValues(['id' => 1], ['nope' => Metadata::fromArray([ + 'k' => 'v', + ])])], schema(int_schema('id'))) + ->schema(), + ); + } + public function test_rows_share_the_declared_schema_instance(): void { $schema = schema(int_schema('id')); @@ -223,7 +518,7 @@ public function test_hydrate_does_not_cast_native_values(): void ); static::assertSame(1, $rows->first()->get('id')); - static::assertSame($createdAt, $rows->first()->get('created_at')); + static::assertEquals($createdAt, $rows->first()->get('created_at')); } public function test_hydrate_does_not_cast_nested_list_map_and_structure(): void @@ -271,9 +566,6 @@ public function test_hydrating_already_typed_values_is_idempotent(): void 'created_at' => new DateTimeImmutable('2024-01-01 00:00:00 UTC'), ])], $schema); - static::assertSame( - serialize($rows), - serialize($hydrator->hydrate([new RawRowValues($rows->first()->values())], $schema)), - ); + static::assertEquals($rows, $hydrator->hydrate([new RawRowValues($rows->first()->values())], $schema)); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowRenamingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowRenamingTest.php deleted file mode 100644 index ced421efc1..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowRenamingTest.php +++ /dev/null @@ -1,33 +0,0 @@ - 1]); - - static::assertSame($row, RowRenaming::of([])->apply($row)); - } - - public function test_it_keeps_positions_and_leaves_unlisted_columns_alone(): void - { - static::assertSame(['x', 'b'], RowRenaming::of(['a' => 'x'])->apply(row(['a' => 1, 'b' => 2]))->names()); - } - - public function test_it_maps_values_onto_their_new_names(): void - { - static::assertEquals( - row(['x' => 1, 'y' => 2]), - RowRenaming::of(['a' => 'x', 'b' => 'y'])->apply(row(['a' => 1, 'b' => 2])), - ); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php index 39d2329be1..e91ad83952 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php @@ -8,20 +8,30 @@ use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Row\RowsBuffer; use Flow\ETL\Rows; +use Flow\ETL\Schema; use Flow\ETL\Tests\FlowTestCase; 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; final class RowsBufferTest extends FlowTestCase { public function test_a_batch_factory_builds_each_released_batch(): void { - // Rows::trusted() takes the rows as given - a value the default gate would refuse passes through - $buffer = new RowsBuffer(schema(int_schema('id')), 1, Rows::trusted(...)); - - static::assertSame([['id' => 'x']], $buffer->add(row(['id' => 'x']))?->toArray()); + $buffer = new RowsBuffer(schema(int_schema('id')), 1, static fn(Schema $schema, array $rows): Rows => rows( + schema(int_schema('id', nullable: true)), + ...$rows, + )); + + static::assertTrue( + $buffer + ->add(row(['id' => 1])) + ?->schema() + ->get('id') + ->isNullable(), + ); } public function test_the_default_batch_checks_every_row(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php index ab1f58053b..cc3483d06a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php @@ -5,10 +5,9 @@ namespace Flow\ETL\Tests\Unit; use DateTimeImmutable; -use DateTimeZone; -use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; @@ -19,7 +18,6 @@ use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; -use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; @@ -28,175 +26,22 @@ final class RowTest extends FlowTestCase { - public function test_conform_to_a_schema_in_a_different_order_reorders_the_values(): void - { - static::assertSame( - ['b' => 2, 'a' => 1], - row(['a' => 1, 'b' => 2])->conformTo(schema(int_schema('b'), int_schema('a')))->values(), - ); - } - - public function test_conform_to_a_schema_the_row_already_matches_returns_an_equal_row(): void - { - $row = row(['a' => 1, 'b' => 'x']); - - static::assertEquals($row, $row->conformTo(schema(int_schema('a'), str_schema('b')))); - } - - public function test_conform_to_a_schema_with_as_many_but_other_columns_refuses_the_row(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage( - 'Row does not match its schema: column "b" declared by the schema is missing from the row', - ); - - row(['a' => 1, 'z' => 2])->conformTo(schema(int_schema('a'), int_schema('b'))); - } - - public function test_conform_to_does_not_validate_a_non_null_value(): void - { - // the caller produced the value by casting to the column's type - conformTo() checks the shape only - static::assertSame( - ['a' => 'not-an-integer'], - row(['a' => 'not-an-integer'])->conformTo(schema(int_schema('a')))->values(), - ); - } - - public function test_conform_to_carries_the_schema_order_and_pads_a_nullable_absence(): void - { - static::assertSame( - ['c' => 3, 'a' => 1, 'b' => null], - row(['a' => 1, 'c' => 3])->conformTo(schema( - int_schema('c'), - int_schema('a'), - str_schema('b', true), - ))->values(), - ); - } - - public function test_conform_to_refuses_a_null_under_not_null(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage('column "a"'); - - row(['a' => null])->conformTo(schema(int_schema('a'))); - } - - public function test_conform_to_refuses_a_missing_not_null_column(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage('column "b"'); - - row(['a' => 1])->conformTo(schema(int_schema('a'), int_schema('b'))); - } - - public function test_conform_to_refuses_an_unknown_column(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage('column "z"'); - - row(['a' => 1, 'z' => 2])->conformTo(schema(int_schema('a'))); - } - - public function test_match_to_accepts_null_in_a_nullable_column(): void - { - static::assertSame(['a' => null], row(['a' => null])->matchTo(schema(str_schema('a', true)))->values()); - } - - public function test_match_to_carries_the_schema_order_into_the_row(): void - { - static::assertSame( - ['c', 'a', 'b'], - row(['a' => 1, 'b' => 2, 'c' => 3])->matchTo(schema( - int_schema('c'), - int_schema('a'), - int_schema('b'), - ))->names(), - ); - } - - public function test_match_to_leaves_a_matching_row_unchanged(): void - { - static::assertSame(['a' => 1], row(['a' => 1])->matchTo(schema(int_schema('a')))->values()); - } - - public function test_match_to_pads_a_declared_nullable_column_the_row_omits(): void - { - static::assertSame( - ['a' => 1, 'b' => null], - row(['a' => 1])->matchTo(schema(int_schema('a'), str_schema('b', true)))->values(), - ); - } - - public function test_match_to_rejects_a_column_the_schema_does_not_declare(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage('Row does not match its schema: column "b" is not declared by the schema'); - - row(['a' => 1, 'b' => 2])->matchTo(schema(int_schema('a'))); - } - - public function test_match_to_rejects_a_row_against_an_empty_schema(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage('Row does not match its schema: column "a" is not declared by the schema'); - - row(['a' => 1])->matchTo(schema()); - } - - public function test_match_to_rejects_a_value_of_the_wrong_type(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage( - 'Row does not match its schema: column "code": could not convert 1000 (integer) to string', - ); - - row(['code' => 1000])->matchTo(schema(str_schema('code'))); - } - - public function test_match_to_rejects_null_in_a_column_that_is_not_nullable(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage('column "a": could not convert null to string, column is not nullable'); - - row(['a' => null])->matchTo(schema(str_schema('a'))); - } - - public function test_match_to_rejects_when_a_declared_column_that_is_not_nullable_is_missing(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage( - 'Row does not match its schema: column "b" declared by the schema is missing from the row', - ); - - row(['a' => 1])->matchTo(schema(int_schema('a'), int_schema('b'))); - } - - public function test_match_to_reports_no_row_coordinate_of_its_own(): void - { - // the row does not know its position - Rows attaches it, see RowsTest - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage('Row does not match its schema: column "a" is not declared by the schema'); - - row(['a' => 1])->matchTo(schema()); - } - - public function test_match_to_with_the_same_keys_still_validates_every_value(): void + public function test_get_throws_when_the_column_is_absent(): void { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage( - 'Row does not match its schema: column "c": could not convert 3 (integer) to string', - ); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column "missing" does not exist'); - row(['a' => 1, 'b' => 'x', 'c' => 3])->matchTo(schema(int_schema('a'), str_schema('b'), str_schema('c'))); + row(['id' => 1])->get('missing'); } - public function test_get_throws_when_the_column_is_absent(): void + #[TestWith([-1])] + #[TestWith([1])] + public function test_a_view_outside_its_batch_is_refused(int $index): void { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Column "missing" does not exist'); + $this->expectExceptionMessage("Row {$index} does not exist in a batch of 1 rows"); - row(['id' => 1])->get('missing'); + row(['id' => 1])->rows->row($index); } public function test_has(): void @@ -243,32 +88,6 @@ public function test_names_and_values_keep_storage_order(): void static::assertSame(['b' => 2, 'a' => 1], $row->values()); } - public function test_project_carries_the_schema_order_into_the_row(): void - { - static::assertSame( - ['c', 'a'], - row(['a' => 1, 'c' => 3])->project(schema(int_schema('c'), int_schema('a')))->names(), - ); - } - - public function test_project_drops_the_columns_the_schema_does_not_declare(): void - { - static::assertSame(['a' => 1], row(['a' => 1, 'b' => 2])->project(schema(int_schema('a')))->values()); - } - - public function test_project_leaves_a_column_the_row_omits_absent_instead_of_padding_it(): void - { - static::assertSame( - ['a' => 1], - row(['a' => 1])->project(schema(int_schema('a'), str_schema('b', true)))->values(), - ); - } - - public function test_project_validates_nothing(): void - { - static::assertSame(['code' => 1000], row(['code' => 1000])->project(schema(str_schema('code')))->values()); - } - public function test_transforms_row_to_array(): void { $row = row([ @@ -325,7 +144,7 @@ public function test_values_are_read_by_the_schema(): void $values[$name] = $row->get($name); } - static::assertSame( + static::assertEquals( [ 'id' => 1, 'name' => 'one', @@ -336,39 +155,4 @@ public function test_values_are_read_by_the_schema(): void $values, ); } - - public function test_match_to_hops_a_reordered_row_into_the_column_zone(): void - { - static::assertSame( - '2026-01-02 04:04:05 Europe/Warsaw', - type_datetime() - ->assert( - row(['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), 'id' => 1]) - ->matchTo(schema(int_schema('id'), datetime_schema('at', zone: 'Europe/Warsaw'))) - ->get('at'), - ) - ->format('Y-m-d H:i:s e'), - ); - } - - public function test_match_to_refuses_a_reordered_row_with_a_wrong_typed_value(): void - { - $this->expectException(ColumnMismatchException::class); - - row(['b' => 'x', 'a' => 1])->matchTo(schema(int_schema('a'), int_schema('b'))); - } - - public function test_match_to_refuses_null_in_a_non_nullable_datetime_column(): void - { - $this->expectException(ColumnMismatchException::class); - - row(['at' => null])->matchTo(schema(datetime_schema('at'))); - } - - public function test_match_to_refuses_a_non_datetime_in_a_datetime_column(): void - { - $this->expectException(ColumnMismatchException::class); - - row(['at' => '2026-01-02 03:04:05'])->matchTo(schema(datetime_schema('at'))); - } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php index fcba4848c6..aa85ae8c34 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php @@ -29,7 +29,7 @@ public function test_building_array_to_rows_with_entry_that_is_list_of_strings() ['data' => ['e', 'f', 'g', 'd']], ], schema(list_schema('data', type_list(type_string()))), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( @@ -49,7 +49,7 @@ public function test_building_array_to_rows_with_entry_that_is_list_of_strings_w ['data' => ['e', 'f', 'g', 'd']], ], schema(list_schema('data', type_list(type_string()))), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( @@ -63,7 +63,7 @@ public function test_building_row_from_array_with_schema_and_additional_fields_n $rows = array_to_rows( ['id' => 1234, 'deleted' => false, 'phase' => null], schema(int_schema('id'), bool_schema('deleted')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( @@ -77,7 +77,7 @@ public function test_building_row_from_array_with_schema_but_entries_not_availab $rows = array_to_rows( ['id' => 1234, 'deleted' => false], schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', true)), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( @@ -97,7 +97,7 @@ public function test_building_rows_from_array(): void ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], ], schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', nullable: true)), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( @@ -118,7 +118,7 @@ public function test_building_rows_from_array_with_schema_and_additional_fields_ ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], ], schema(int_schema('id'), bool_schema('deleted')), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( @@ -139,7 +139,7 @@ public function test_building_rows_from_array_with_schema_but_entries_not_availa ['id' => 4321, 'deleted' => true], ], schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', true)), - flow_context(config())->hydrator(), + flow_context(config())->backend(), ); static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php new file mode 100644 index 0000000000..7d43717f3e --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php @@ -0,0 +1,286 @@ + + */ + public static function refused_views(): Generator + { + yield 'a not null column the source lacks' => [ + rows(schema(int_schema('id')), row(['id' => 1])), + schema(int_schema('id'), str_schema('name')), + 'column "name" (row 0) declared by the schema is missing from the row', + ]; + yield 'null under not null' => [ + rows(schema(int_schema('id', nullable: true)), row(['id' => null])), + schema(int_schema('id')), + 'column "id" (row 0): could not convert null to integer, column is not nullable', + ]; + yield 'a value that matches only after a cast' => [ + rows(schema(str_schema('id')), row(['id' => '2'])), + schema(int_schema('id')), + 'column "id" (row 0): could not convert \'2\' (string) to integer', + ]; + yield 'a column the target does not declare' => [ + rows(schema(int_schema('id'), int_schema('extra')), row(['id' => 1, 'extra' => 2])), + schema(int_schema('id')), + 'column "extra" (row 0) is not declared by the schema', + ]; + } + + public function test_a_refused_value_wins_over_an_earlier_absence(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "b" (row 1): could not convert null to integer, column is not nullable'); + + (new RowsBuilder(schema(int_schema('a'), int_schema('b')), new PhpBackend()))->appendRows([ + ['a' => 1], + ['a' => 1, 'b' => null], + ]); + } + + public function test_an_absence_is_placed_after_the_rows_already_appended(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "c" (row 2) declared by the schema is missing from the row'); + + (new RowsBuilder( + schema(int_schema('a'), int_schema('b', nullable: true), int_schema('c')), + new PhpBackend(), + ))->appendRows([['a' => 0, 'c' => 0]])->appendRows([['a' => 1, 'c' => 1], ['a' => 2]]); + } + + public function test_the_first_refused_value_in_row_order_across_columns(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "b" (row 1): could not convert \'x\' (string) to integer'); + + (new RowsBuilder(schema(int_schema('a'), int_schema('b')), new PhpBackend()))->appendRows([[ + 'a' => 0, + 'b' => 0, + ]])->appendRows([['a' => 1, 'b' => 'x'], ['a' => 'y', 'b' => 2]]); + } + + public function test_a_view_of_another_definition_keeps_a_value_that_matches_the_target(): void + { + static::assertSame( + [['id' => 5, 'name' => null]], + (new RowsBuilder(schema(int_schema('id'), str_schema('name', nullable: true)), new PhpBackend())) + ->appendFrom(rows(schema(int_schema('id', nullable: true)), row(['id' => 5])), 0) + ->finish() + ->toArray(), + ); + } + + public function test_a_refused_view_is_placed_at_its_output_row(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "id" (row 1): could not convert \'x\' (string) to integer'); + + (new RowsBuilder(schema(int_schema('id')), new PhpBackend())) + ->appendFrom(rows(schema(int_schema('id')), row(['id' => 1])), 0) + ->appendFrom(rows(schema(str_schema('id')), row(['id' => 'x'])), 0); + } + + #[DataProvider('refused_views')] + public function test_refuses_a_view_that_does_not_fit_the_target( + Rows $source, + Schema $target, + string $message, + ): void { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage($message); + + (new RowsBuilder($target, new PhpBackend()))->appendFrom($source, 0); + } + + public function test_a_missing_nullable_column_is_padded_with_null(): void + { + static::assertEquals( + rows(schema(int_schema('id'), str_schema('name', nullable: true)), row(['id' => 1, 'name' => null])), + (new RowsBuilder( + schema(int_schema('id'), str_schema('name', nullable: true)), + new PhpBackend(), + ))->appendRows([['id' => 1]])->finish(), + ); + } + + public function test_a_missing_not_null_column_is_refused_with_its_row(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "name" (row 1) declared by the schema is missing from the row', + ); + + (new RowsBuilder(schema(int_schema('id'), str_schema('name')), new PhpBackend()))->appendRows([ + ['id' => 1, 'name' => 'a'], + ['id' => 2], + ]); + } + + public function test_a_refused_value_in_the_first_row_reports_row_zero(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "i" (row 0): could not convert \'abc\' (string) to integer', + ); + + (new RowsBuilder(schema(int_schema('i')), new PhpBackend()))->appendRows([['i' => 'abc']]); + } + + public function test_a_refused_value_is_reported_with_its_column_and_row(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "i" (row 1): could not convert \'n/a\' (string) to integer', + ); + + (new RowsBuilder(schema(int_schema('i')), new PhpBackend()))->appendRows([ + ['i' => 1], + ['i' => 'n/a'], + ['i' => 3], + ]); + } + + public function test_a_refusal_in_a_later_append_reports_its_row_in_the_whole_batch(): void + { + $builder = new RowsBuilder(schema(int_schema('i')), new PhpBackend()); + $builder->appendRows([['i' => 1], ['i' => 2]]); + + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "i" (row 3): could not convert \'x\' (string) to integer'); + + $builder->appendRows([['i' => 3], ['i' => 'x']]); + } + + public function test_a_null_on_a_not_null_column_is_reported_as_a_value_that_does_not_match(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "i" (row 0): could not convert null to integer, column is not nullable', + ); + + (new RowsBuilder(schema(int_schema('i')), new PhpBackend()))->append(['i' => null]); + } + + public function test_a_value_the_schema_does_not_declare_is_dropped(): void + { + static::assertSame( + ['id'], + (new RowsBuilder(schema(int_schema('id')), new PhpBackend())) + ->append(['id' => 1, 'undeclared' => 'x']) + ->finish() + ->first() + ->names(), + ); + } + + public function test_rows_follow_the_schema_column_order(): void + { + static::assertSame( + [['id' => 1, 'name' => 'a']], + (new RowsBuilder(schema(int_schema('id'), str_schema('name')), new PhpBackend())) + ->append(['name' => 'a', 'id' => 1]) + ->finish() + ->toArray(), + ); + } + + public function test_every_value_is_cast_against_its_own_column(): void + { + static::assertEquals( + rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => '2'])), + (new RowsBuilder(schema(int_schema('id'), str_schema('name')), new PhpBackend()))->append([ + 'id' => '1', + 'name' => 2, + ])->finish(), + ); + } + + public function test_a_schema_without_definitions_counts_rows(): void + { + $builder = new RowsBuilder(schema(), new PhpBackend()); + $builder->append([]); + $builder->append([]); + $builder->appendRows([[]]); + + static::assertSame(3, $builder->count()); + static::assertSame(3, $builder->finish()->count()); + } + + public function test_appending_no_rows_changes_nothing(): void + { + static::assertSame(0, (new RowsBuilder(schema(int_schema('id')), new PhpBackend()))->appendRows([])->count()); + } + + public function test_copies_physical_cells_from_another_batch(): void + { + $source = rows( + schema(int_schema('id'), str_schema('name')), + row(['id' => 1, 'name' => 'a']), + row([ + 'id' => 2, + 'name' => 'b', + ]), + ); + + static::assertSame( + [['id' => 2, 'name' => 'b'], ['id' => 2, 'name' => 'b'], ['id' => 1, 'name' => 'a']], + (new RowsBuilder(schema(int_schema('id'), str_schema('name')), new PhpBackend())) + ->appendFrom($source, 1) + ->appendTake($source, [1, 0]) + ->finish() + ->toArray(), + ); + } + + public function test_feeds_one_column(): void + { + $builder = new RowsBuilder(schema(int_schema('id')), new PhpBackend()); + $builder->column('id')->appendMany([1, 2]); + + static::assertSame(2, $builder->count()); + static::assertSame([['id' => 1], ['id' => 2]], $builder->finish()->toArray()); + } + + public function test_an_unknown_column_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('RowsBuilder has no column "nope"'); + + (new RowsBuilder(schema(int_schema('id')), new PhpBackend()))->column('nope'); + } + + public function test_ragged_columns_are_refused_at_finish(): void + { + $builder = new RowsBuilder(schema(int_schema('a'), int_schema('b')), new PhpBackend()); + $builder->column('a')->appendMany([1, 2]); + $builder->column('b')->append(1); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Ragged columns: 2 rows in [a], 1 rows in [b]'); + + $builder->finish(); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php index 6848ced1d5..4aa407aeb8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php @@ -5,17 +5,37 @@ namespace Flow\ETL\Tests\Unit; use DOMDocument; +use DOMElement; +use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Rows; use Flow\ETL\Schema\Metadata; +use Flow\ETL\Tests\Context\RowsSerializationContext; use Flow\ETL\Tests\FlowTestCase; +use Flow\Floe\ValueDecoder; +use PHPUnit\Framework\Attributes\RequiresPhp; use function assert; +use function Flow\ETL\DSL\html_element_schema; +use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\ETL\DSL\xml_element_schema; use function Flow\ETL\DSL\xml_schema; +use function Flow\Types\DSL\structure_element; +use function Flow\Types\DSL\type_instance_of; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_optional; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; use function serialize; use function unserialize; @@ -55,4 +75,145 @@ public function test_xml_column_metadata_survives_a_serialize_round_trip(): void static::assertSame($rows->schema()->get('x')->isNullable(), $restored->schema()->get('x')->isNullable()); static::assertSame($document->C14N(), $restoredDocument->C14N()); } + + public function test_xml_document_survives_a_round_trip(): void + { + $document = new DOMDocument(); + $document->loadXML('1'); + + $restored = type_instance_of(DOMDocument::class)->assert(RowsSerializationContext::roundTrip(rows( + schema(xml_schema('x')), + row(['x' => $document]), + ))->first()->get('x')); + + static::assertSame($document->C14N(), $restored->C14N()); + } + + public function test_xml_element_survives_a_round_trip(): void + { + $document = new DOMDocument(); + $document->loadXML('1'); + + $restored = type_instance_of(DOMElement::class)->assert(RowsSerializationContext::roundTrip(rows( + schema(xml_element_schema('x')), + row(['x' => $document->documentElement]), + ))->first()->get('x')); + + static::assertSame('1', $restored->C14N()); + } + + public function test_restored_xml_elements_do_not_canonicalize_to_an_empty_string(): void + { + $left = new DOMDocument(); + $left->loadXML('1'); + $right = new DOMDocument(); + $right->loadXML('999'); + + $restored = RowsSerializationContext::roundTrip(rows( + schema(xml_element_schema('x')), + row(['x' => $left->documentElement]), + row(['x' => $right->documentElement]), + )); + $restoredLeft = type_instance_of(DOMElement::class)->assert($restored->first()->get('x')); + $restoredRight = type_instance_of(DOMElement::class)->assert($restored->row(1)->get('x')); + + static::assertNotSame('', $restoredLeft->C14N()); + static::assertNotSame($restoredLeft->C14N(), $restoredRight->C14N()); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_html_document_survives_a_round_trip(): void + { + $document = ValueDecoder::htmlDocumentFromString('

x

'); + + static::assertSame( + type_string()->cast($document), + type_string()->cast(RowsSerializationContext::roundTrip(rows( + schema(html_schema('x')), + row(['x' => $document]), + ))->first()->get('x')), + ); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_html_element_survives_a_round_trip(): void + { + $element = ValueDecoder::htmlElementFromString('

x

'); + + static::assertSame( + type_string()->cast($element), + type_string()->cast(RowsSerializationContext::roundTrip(rows( + schema(html_element_schema('x')), + row(['x' => $element]), + ))->first()->get('x')), + ); + } + + public function test_container_columns_survive_a_round_trip(): void + { + $rows = rows( + schema( + list_schema('l', type_list(type_optional(type_integer())), nullable: true), + map_schema('m', type_map(type_string(), type_integer())), + structure_schema('s', type_structure([ + 'id' => type_integer(), + 'note' => structure_element('note', type_string(), optional: true), + ])), + ), + row(['l' => [1, null], 'm' => ['a' => 1], 's' => ['id' => 1, 'note' => 'x']]), + row(['l' => null, 'm' => [], 's' => ['id' => 2]]), + ); + + static::assertEquals($rows, RowsSerializationContext::roundTrip($rows)); + } + + public function test_constant_columns_survive_a_round_trip(): void + { + $schema = schema(int_schema('id'), str_schema('tag', nullable: true)); + $backend = new PhpBackend(); + $rows = Rows::fromColumns( + $schema, + [ + 'id' => $backend->constant(int_schema('id'), 7, 3), + 'tag' => $backend->constant(str_schema('tag', nullable: true), null, 3), + ], + 3, + ); + + static::assertSame( + [['id' => 7, 'tag' => null], ['id' => 7, 'tag' => null], ['id' => 7, 'tag' => null]], + RowsSerializationContext::roundTrip($rows)->toArray(), + ); + } + + public function test_a_batch_without_columns_keeps_its_row_count(): void + { + $rows = rows(schema(), row([]), row([]), row([])); + + static::assertSame(3, RowsSerializationContext::roundTrip($rows)->count()); + } + + public function test_unserialize_refuses_columns_that_disagree_with_the_schema(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Rows::fromColumns() expects columns [id], got [other]'); + + RowsSerializationContext::unserialize([ + 'schema' => schema(int_schema('id')), + 'count' => 1, + 'columns' => ['other' => ['buffers' => ['', "\x01\x00\x00\x00\x00\x00\x00\x00"], 'nullCount' => 0]], + ]); + } + + public function test_unserialize_refuses_a_corrupt_buffer(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Int64 values buffer of 2 bytes, expected 8 for 1 rows'); + + RowsSerializationContext::unserialize([ + 'schema' => schema(int_schema('id')), + 'count' => 1, + 'columns' => ['id' => ['buffers' => ['', "\x01\x00"], 'nullCount' => 0]], + ]); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php index 11363a8618..cf61feba44 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Tests\Unit; +use Closure; use DateTimeImmutable; use DateTimeZone; +use Flow\ETL\Column\Php\ScalarColumn; +use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaMismatchException; @@ -13,11 +17,13 @@ use Flow\ETL\Row\Comparator; use Flow\ETL\Row\Comparator\NativeComparator; use Flow\ETL\Rows; +use Flow\ETL\Schema; use Flow\ETL\Tests\FlowTestCase; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; @@ -36,10 +42,34 @@ use function Flow\Types\DSL\type_structure; use function iterator_to_array; use function serialize; +use function sprintf; use function unserialize; final class RowsTest extends FlowTestCase { + /** + * @return Generator + */ + public static function negative_sizes(): Generator + { + yield 'drop' => [static fn(Rows $rows): Rows => $rows->drop(-1)]; + yield 'dropRight' => [static fn(Rows $rows): Rows => $rows->dropRight(-1)]; + yield 'take' => [static fn(Rows $rows): Rows => $rows->take(-1)]; + yield 'takeRight' => [static fn(Rows $rows): Rows => $rows->takeRight(-1)]; + } + + /** + * @param Closure(Rows): Rows $call + */ + #[DataProvider('negative_sizes')] + public function test_a_negative_size_is_refused(Closure $call): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Size must be greater than or equal to 0'); + + $call(rows(schema(int_schema('id')), row(['id' => 1]))); + } + public static function rows_diff_left_provider(): Generator { yield 'one entry identical row' => [ @@ -115,14 +145,6 @@ public static function unique_rows_provider(): Generator ]; } - public function test_add_checks_only_the_added_rows(): void - { - // the existing rows are not re-checked, so one that never passed a door survives add() - $rows = Rows::trusted(schema(int_schema('number')), [row(['number' => 'x'])])->add(row(['number' => 2])); - - static::assertSame([['number' => 'x'], ['number' => 2]], $rows->toArray()); - } - public function test_add_reports_the_violating_row_at_its_position_in_the_batch(): void { $this->expectException(SchemaMismatchException::class); @@ -153,12 +175,9 @@ public function test_match_to_adopts_a_wider_schema_and_pads_the_new_nullable_co public function test_match_to_reports_the_violating_row_at_its_position_in_the_batch(): void { $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('column "id" (row 1) declared by the schema is missing from the row'); + $this->expectExceptionMessage('column "id" (row 0): could not convert 1 (integer) to string'); - Rows::trusted(schema(int_schema('id')), [ - row(['id' => 1]), - row(['other' => 2]), - ])->matchTo(schema(int_schema('id'))); + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))->matchTo(schema(str_schema('id'))); } public function test_project_drops_the_columns_the_schema_does_not_declare(): void @@ -173,6 +192,13 @@ public function test_project_drops_the_columns_the_schema_does_not_declare(): vo ->project(schema(int_schema('id'))) ->toArray(), ); + static::assertSame( + ['name', 'id'], + rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])) + ->project(schema(str_schema('name'), int_schema('id'))) + ->first() + ->names(), + ); } public function test_project_rejects_a_schema_that_widens_the_batch(): void @@ -194,38 +220,6 @@ public function test_project_rejects_a_schema_that_retypes_a_column(): void ))); } - public function test_project_does_not_recheck_columns_that_keep_their_definition(): void - { - // the rows passed a door under these definitions, and a subset of them needs no second check - static::assertSame( - [['id' => 'not-an-integer']], - Rows::trusted(schema(int_schema('id'), str_schema('name')), [row([ - 'id' => 'not-an-integer', - 'name' => 'a', - ])]) - ->project(schema(int_schema('id'))) - ->toArray(), - ); - } - - public function test_conformed_pads_the_shape_without_revalidating_values(): void - { - static::assertSame( - [['id' => 'not-an-integer', 'name' => null]], - Rows::conformed(schema(int_schema('id'), str_schema('name', true)), [row([ - 'id' => 'not-an-integer', - ])])->toArray(), - ); - } - - public function test_conformed_reports_the_violating_row_at_its_position_in_the_batch(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('column "id" (row 1)'); - - Rows::conformed(schema(int_schema('id')), [row(['id' => 1]), row(['id' => null])]); - } - public function test_construct_reorders_row_storage_into_schema_order(): void { static::assertSame( @@ -254,26 +248,6 @@ public function test_the_epic_repro_is_unconstructible(): void rows(schema(str_schema('code')), row(['code' => 'AB-01']), row(['code' => 1000])); } - public function test_trusted_takes_a_matching_batch_verbatim(): void - { - static::assertSame([['number' => 1], ['number' => 2]], Rows::trusted(schema(int_schema('number')), [ - row(['number' => 1]), - row(['number' => 2]), - ])->toArray()); - } - - public function test_unserialize_rejects_a_payload_whose_rows_contradict_its_schema(): void - { - // a persisted payload is foreign input - cache reads and both serializers land here - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('column "number" (row 0) declared by the schema is missing from the row'); - - rows(schema(int_schema('number')))->__unserialize([ - 'schema' => schema(int_schema('number')), - 'rows' => [['other' => 1]], - ]); - } - public function test_array_access_exists(): void { $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); @@ -418,8 +392,8 @@ public function test_drop_right_more_than_exists(): void public function test_empty_rows(): void { - static::assertTrue(rows(schema())->empty()); - static::assertFalse(rows(schema(int_schema('id')), row(['id' => 1]))->empty()); + static::assertTrue(rows(schema())->isEmpty()); + static::assertFalse(rows(schema(int_schema('id')), row(['id' => 1]))->isEmpty()); } public function test_first_on_empty_rows(): void @@ -1059,13 +1033,6 @@ public function test_structure_field_order_is_a_schema_difference_not_a_value_di $left->merge($right); } - public function test_a_row_in_zone_is_kept(): void - { - $row = row(['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('Europe/Warsaw'))]); - - static::assertSame($row, $row->matchTo(schema(datetime_schema('at', zone: 'Europe/Warsaw')))); - } - public function test_rows_hop_a_foreign_zone_at_ingest(): void { static::assertSame( @@ -1102,4 +1069,366 @@ public function test_rows_hop_nested_optional_datetimes(): void )->first()->get('l'))[0]?->format('Y-m-d H:i:s e'), ); } + + /** + * @return Generator + */ + public static function from_rows_refusals(): Generator + { + yield 'other column, same count' => [ + schema(int_schema('a'), int_schema('b')), + row(['a' => 1, 'z' => 2]), + 'Rows do not match their schema: column "b" (row 0) declared by the schema is missing from the row', + ]; + yield 'null under not-null' => [ + schema(str_schema('a')), + row(['a' => null]), + 'column "a" (row 0): could not convert null to string, column is not nullable', + ]; + yield 'missing not-null column' => [ + schema(int_schema('a'), int_schema('b')), + row(['a' => 1]), + 'Rows do not match their schema: column "b" (row 0) declared by the schema is missing from the row', + ]; + yield 'unknown column' => [ + schema(int_schema('a')), + row(['a' => 1, 'b' => 2]), + 'Rows do not match their schema: column "b" (row 0) is not declared by the schema', + ]; + yield 'any column against schema()' => [ + schema(), + row(['a' => 1]), + 'Rows do not match their schema: column "a" (row 0) is not declared by the schema', + ]; + yield 'same names, third value wrong' => [ + schema(int_schema('a'), str_schema('b'), str_schema('c')), + row(['a' => 1, 'b' => 'x', 'c' => 3]), + 'Rows do not match their schema: column "c" (row 0): could not convert 3 (integer) to string', + ]; + yield 'reordered, wrong type' => [ + schema(int_schema('a'), int_schema('b')), + row(['b' => 'x', 'a' => 1]), + 'Rows do not match their schema: column "b" (row 0): could not convert \'x\' (string) to integer', + ]; + yield 'null under not-null datetime' => [ + schema(datetime_schema('at')), + row(['at' => null]), + 'column "at" (row 0): could not convert null to datetime, column is not nullable', + ]; + yield 'string in a datetime column' => [ + schema(datetime_schema('at')), + row(['at' => '2026-01-02 03:04:05']), + 'column "at" (row 0): could not convert \'2026-01-02 03:04:05\' (string) to datetime', + ]; + } + + #[DataProvider('from_rows_refusals')] + public function test_from_rows_refuses(Schema $schema, Row $row, string $message): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage($message); + + rows($schema, $row); + } + + public function test_from_rows_refuses_null_under_not_null_in_row_1(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "id" (row 1)'); + + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => null])); + } + + public function test_from_rows_gathers_views_of_one_batch_whose_schema_is_same(): void + { + $schema = schema(int_schema('id')); + $batch = rows($schema, row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + + static::assertSame([['id' => 3], ['id' => 1]], rows($schema, $batch->row(2), $batch->row(0))->toArray()); + } + + public function test_from_rows_copies_views_of_two_batches_with_the_same_schema(): void + { + $schema = schema(int_schema('id')); + $constant = Rows::fromColumns($schema, ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], 2); + $scalar = rows($schema, row(['id' => 1]), row(['id' => 2])); + + $copied = rows($schema, $scalar->row(1), $constant->row(0), $scalar->row(0)); + + static::assertSame([['id' => 2], ['id' => 7], ['id' => 1]], $copied->toArray()); + static::assertInstanceOf(ScalarColumn::class, $copied->column('id')); + } + + public function test_from_rows_reorders_and_hops_into_the_column_zone(): void + { + static::assertSame( + '2026-01-02 04:04:05 Europe/Warsaw', + type_datetime() + ->assert(rows( + schema(int_schema('id'), datetime_schema('at', zone: 'Europe/Warsaw')), + row(['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), 'id' => 1]), + )->first()->get('at')) + ->format('Y-m-d H:i:s e'), + ); + } + + public function test_of_takes_columns_verbatim(): void + { + $schema = schema(int_schema('number')); + $column = (new PhpBackend())->constant(int_schema('number'), 1, 2); + $rows = Rows::fromColumns($schema, ['number' => $column], 2); + + static::assertSame($column, $rows->column('number')); + static::assertSame([['number' => 1], ['number' => 1]], $rows->toArray()); + } + + public function test_of_checks_names_and_counts_only(): void + { + // a column of another type passes the structural tier - values are checked where they enter a column + $rows = Rows::fromColumns( + schema(str_schema('id')), + ['id' => (new PhpBackend())->constant(int_schema('id'), 1, 1)], + 1, + ); + + static::assertSame(1, $rows->count()); + } + + public function test_of_refuses_other_column_names(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Rows::fromColumns() expects columns [id], got [other]'); + + Rows::fromColumns( + schema(int_schema('id')), + ['other' => (new PhpBackend())->constant(int_schema('other'), 1, 1)], + 1, + ); + } + + public function test_of_refuses_a_column_of_another_count(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column "id" holds 2 rows, the batch 1'); + + Rows::fromColumns(schema(int_schema('id')), ['id' => (new PhpBackend())->constant(int_schema('id'), 1, 2)], 1); + } + + public function test_project_shares_kept_columns(): void + { + $rows = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])); + + static::assertSame($rows->column('id'), $rows->project(schema(int_schema('id')))->column('id')); + } + + public function test_concat_of_a_constant_and_a_scalar_column_yields_php_columns(): void + { + $schema = schema(int_schema('id')); + $constant = Rows::fromColumns($schema, ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], 2); + $concatenated = $constant->concat(rows($schema, row(['id' => 1]))); + + static::assertSame([['id' => 7], ['id' => 7], ['id' => 1]], $concatenated->toArray()); + static::assertInstanceOf(ScalarColumn::class, $concatenated->column('id')); + } + + public function test_concat_refuses_a_zero_row_input_with_another_schema(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Cannot merge Rows with different schemas'); + + rows(schema(int_schema('id')), row(['id' => 1]))->concat(rows(schema(str_schema('id')))); + } + + public function test_concat_of_empty_inputs_is_an_empty_batch(): void + { + $schema = schema(int_schema('id')); + + static::assertSame(0, rows($schema)->concat(rows($schema))->count()); + } + + public function test_with_columns_beside_a_constant_column(): void + { + $schema = schema(int_schema('id'), str_schema('tag'), int_schema('n')); + $rows = Rows::fromColumns( + schema(int_schema('id'), str_schema('tag')), + [ + 'id' => (new PhpBackend())->constant(int_schema('id'), 1, 2), + 'tag' => (new PhpBackend())->constant(str_schema('tag'), 'a', 2), + ], + 2, + ); + $builder = (new PhpBackend())->builder(str_schema('tag')); + $builder->appendMany(['x', 'y']); + $n = (new PhpBackend())->builder(int_schema('n')); + $n->appendMany([5, 6]); + + static::assertSame( + [['id' => 1, 'tag' => 'x', 'n' => 5], ['id' => 1, 'tag' => 'y', 'n' => 6]], + $rows->withColumns($schema, ['n' => $n->finish(), 'tag' => $builder->finish()])->toArray(), + ); + } + + public function test_with_columns_refuses_a_column_of_another_count(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column "n" holds 1 rows, the batch 2'); + + rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))->withColumns( + schema(int_schema('id'), int_schema('n')), + ['n' => (new PhpBackend())->constant(int_schema('n'), 1, 1)], + ); + } + + public function test_with_schema_renames_and_retypes_positionally(): void + { + $renamed = rows(schema(int_schema('id', nullable: true)), row(['id' => 1]))->withSchema(schema(int_schema( + 'key', + ))); + + static::assertSame([['key' => 1]], $renamed->toArray()); + } + + public function test_with_schema_refuses_another_definition_count(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Rows::withSchema() expects 1 definitions, got 2'); + + rows(schema(int_schema('id')), row(['id' => 1]))->withSchema(schema(int_schema('a'), int_schema('b'))); + } + + public function test_with_schema_refuses_nulls_under_not_null(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage('column "key": could not convert null to integer, column is not nullable'); + + rows(schema(int_schema('id', nullable: true)), row(['id' => null]))->withSchema(schema(int_schema('key'))); + } + + public function test_with_schema_refuses_another_column_kind(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage( + 'column "id": cannot retype the column to string, integer and string are different column kinds', + ); + + rows(schema(int_schema('id')), row(['id' => 1]))->withSchema(schema(str_schema('id'))); + } + + /** + * @return Generator + */ + public static function slices_out_of_range(): Generator + { + $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + + yield 'negative offset' => [$rows, -1, 1]; + yield 'negative length' => [$rows, 0, -1]; + yield 'past the end' => [$rows, 2, 2]; + yield 'past the end of a batch without columns' => [rows(schema(), row([]), row([]), row([])), 1, 3]; + } + + #[DataProvider('slices_out_of_range')] + public function test_slice_refuses_out_of_range(Rows $rows, int $offset, int $length): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(sprintf( + 'Rows::slice(%d, %d) is outside a batch of %d rows', + $offset, + $length, + $rows->count(), + )); + + $rows->slice($offset, $length); + } + + /** + * @return Generator + */ + public static function gathers_out_of_range(): Generator + { + $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + + yield 'negative' => [$rows, -1]; + yield 'the count' => [$rows, 3]; + yield 'the count of a batch without columns' => [rows(schema(), row([]), row([]), row([])), 3]; + } + + #[DataProvider('gathers_out_of_range')] + public function test_gather_refuses_out_of_range(Rows $rows, int $index): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(sprintf( + 'Rows::gather() index %d is outside a batch of %d rows', + $index, + $rows->count(), + )); + + $rows->gather([$index]); + } + + public function test_gather_nothing_is_an_empty_batch(): void + { + static::assertSame(0, rows(schema(int_schema('id')), row(['id' => 1]))->gather([])->count()); + } + + public function test_a_batch_without_columns_keeps_its_rows(): void + { + $rows = rows(schema(), row([]), row([]), row([])); + + static::assertSame(3, $rows->count()); + static::assertSame(2, $rows->slice(1, 2)->count()); + static::assertSame([[], []], $rows->gather([0, 2])->toArray()); + } + + public function test_dropping_nothing_keeps_the_batch(): void + { + $rows = rows(schema(int_schema('id')), row(['id' => 1])); + + static::assertSame($rows, $rows->drop(0)); + static::assertSame($rows, $rows->dropRight(0)); + } + + public function test_an_empty_batch_sorts_to_itself_and_reduces_to_nothing(): void + { + $rows = rows(schema(int_schema('id'))); + + static::assertSame($rows, $rows->sortAscending('id')); + static::assertSame($rows, $rows->sortDescending('id')); + static::assertSame([], $rows->reduceToArray('id')); + } + + public function test_match_to_rebuilds_a_column_its_type_cannot_restamp(): void + { + // the child of a nullable structure carries null under the null parent row, so narrowing ?int to int cannot be a + // restamp - the matching values are rebuilt under the new type instead + $matched = rows( + schema(structure_schema('s', type_structure(['a' => type_optional(type_integer())]), nullable: true)), + row(['s' => ['a' => 1]]), + row(['s' => null]), + )->matchTo(schema(structure_schema('s', type_structure(['a' => type_integer()]), nullable: true))); + + static::assertSame([['s' => ['a' => 1]], ['s' => null]], $matched->toArray()); + static::assertSame('structure{a: integer}', $matched->column('s')->type()->toString()); + } + + public function test_match_to_adopts_a_not_null_column_an_empty_batch_lacks(): void + { + $matched = rows(schema(int_schema('id')))->matchTo(schema(int_schema('id'), str_schema('name'))); + + static::assertSame(0, $matched->count()); + static::assertSame(['id', 'name'], $matched->schema()->references()->names()); + } + + public function test_match_to_refuses_a_midnight_outside_utc_in_a_date_column(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'column "at" (row 0): could not convert 2026-01-01T00:00:00.000000+01:00 (datetime) to date', + ); + + rows( + schema(datetime_schema('at', zone: 'Europe/Warsaw')), + row(['at' => new DateTimeImmutable('2026-01-01 00:00:00', new DateTimeZone('Europe/Warsaw'))]), + )->matchTo(schema(date_schema('at'))); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Definition/ZoneAlignmentTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Definition/ZoneAlignmentTest.php deleted file mode 100644 index b3bda662fd..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Definition/ZoneAlignmentTest.php +++ /dev/null @@ -1,107 +0,0 @@ -assert((new ZoneAlignment())->align( - datetime_schema('at', zone: 'Europe/Warsaw'), - new DateTimeImmutable('2026-01-02 03:04:05+05:00'), - )) - ->format('Y-m-d H:i:s e'), - ); - } - - public function test_align_keeps_null(): void - { - static::assertNull((new ZoneAlignment())->align(datetime_schema('at', nullable: true), null)); - } - - public function test_align_recasts_a_nested_list(): void - { - static::assertSame( - '2026-01-02 04:04:05 Europe/Warsaw', - type_list(type_datetime()) - ->assert((new ZoneAlignment())->align( - list_schema('l', type_list(type_datetime('Europe/Warsaw'))), - [new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC'))], - ))[0]->format('Y-m-d H:i:s e'), - ); - } - - public function test_align_returns_the_same_object_in_zone(): void - { - $value = new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('Europe/Warsaw')); - - static::assertSame($value, (new ZoneAlignment())->align(datetime_schema('at', zone: 'Europe/Warsaw'), $value)); - } - - public function test_columns_find_top_level_and_nested_datetimes(): void - { - static::assertSame( - ['at', 'optional', 'list', 'map', 'structure'], - array_keys((new ZoneAlignment())->columns([ - 'at' => datetime_schema('at'), - 'optional' => list_schema('optional', type_list(type_optional(type_datetime()))), - 'list' => list_schema('list', type_list(type_datetime())), - 'map' => map_schema('map', type_map(type_string(), type_datetime())), - 'structure' => structure_schema('structure', type_structure(['at' => type_datetime()])), - 'integers' => list_schema('integers', type_list(type_integer())), - 'on' => date_schema('on'), - ])), - ); - static::assertTrue((new ZoneAlignment())->carriesDateTime(type_optional(type_datetime()))); - } - - public function test_columns_of_a_scalar_schema_are_empty(): void - { - static::assertSame( - [], - (new ZoneAlignment())->columns([ - 'id' => int_schema('id'), - 'name' => string_schema('name'), - ]), - ); - } - - public function test_in_zone_needs_a_datetime_column_in_the_same_zone(): void - { - $value = new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('Europe/Warsaw')); - - static::assertTrue((new ZoneAlignment())->inZone(datetime_schema('at', zone: 'Europe/Warsaw'), $value)); - static::assertFalse((new ZoneAlignment())->inZone(datetime_schema('at'), $value)); - static::assertFalse((new ZoneAlignment())->inZone( - list_schema('at', type_list(type_datetime('Europe/Warsaw'))), - $value, - )); - static::assertFalse((new ZoneAlignment())->inZone(datetime_schema('at', zone: 'Europe/Warsaw'), '2026-01-02')); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Formatter/InlineSchemaFormatterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Formatter/InlineSchemaFormatterTest.php new file mode 100644 index 0000000000..1d4fb38e0a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Formatter/InlineSchemaFormatterTest.php @@ -0,0 +1,35 @@ +format(schema())); + } + + public function test_formatting_names_nullability_and_types_in_schema_order(): void + { + static::assertSame( + 'id: integer, name: ?string, tags: list', + (new InlineSchemaFormatter())->format(schema( + int_schema('id'), + str_schema('name', nullable: true), + list_schema('tags', type_list(type_integer())), + )), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/SchemaTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/SchemaTest.php index f4287925cb..ccf89efad6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/SchemaTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/SchemaTest.php @@ -20,7 +20,6 @@ use function array_keys; use function Flow\ETL\DSL\bool_schema; -use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\json_schema; @@ -930,13 +929,4 @@ public function test_match_order_to_adds_and_drops_nothing(): void ), ); } - - public function test_zoned_definitions_are_computed_in_the_constructor(): void - { - $schema = schema(int_schema('i'), datetime_schema('at')); - - static::assertSame(['at'], array_keys($schema->zonedDefinitions())); - static::assertSame(['b'], array_keys($schema->rename('at', 'b')->zonedDefinitions())); - static::assertSame([], $schema->remove('at')->zonedDefinitions()); - } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Serializer/DomValueCodecTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Serializer/DomValueCodecTest.php deleted file mode 100644 index 089de187de..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Serializer/DomValueCodecTest.php +++ /dev/null @@ -1,174 +0,0 @@ - [type_xml()]; - yield 'xml_element' => [type_xml_element()]; - yield 'html' => [type_html()]; - yield 'html_element' => [type_html_element()]; - } - - public static function nonDomTypes(): iterable - { - yield 'string' => [type_string()]; - yield 'integer' => [type_integer()]; - } - - #[DataProvider('domTypes')] - public function test_handles_dom_types(Type $type): void - { - static::assertTrue((new DomValueCodec())->handles($type)); - } - - #[DataProvider('nonDomTypes')] - public function test_handles_rejects_non_dom_types(Type $type): void - { - static::assertFalse((new DomValueCodec())->handles($type)); - } - - #[DataProvider('domTypes')] - public function test_null_passes_through_untouched(Type $type): void - { - static::assertNull((new DomValueCodec())->encode($type, null)); - static::assertNull((new DomValueCodec())->decode($type, null)); - } - - #[DataProvider('nonDomTypes')] - public function test_non_dom_type_passes_through_untouched(Type $type): void - { - static::assertSame('1', (new DomValueCodec())->encode($type, '1')); - static::assertSame('1', (new DomValueCodec())->decode($type, '1')); - } - - public function test_xml_document_survives_a_round_trip(): void - { - $document = new DOMDocument(); - $document->loadXML('1'); - - $codec = new DomValueCodec(); - - /** @var DOMDocument $restored */ - $restored = $codec->decode(type_xml(), $codec->encode(type_xml(), $document)); - - static::assertInstanceOf(DOMDocument::class, $restored); - static::assertSame($document->C14N(), $restored->C14N()); - } - - public function test_xml_element_survives_a_round_trip(): void - { - $document = new DOMDocument(); - $document->loadXML('1'); - $element = $document->documentElement; - static::assertInstanceOf(DOMElement::class, $element); - - $codec = new DomValueCodec(); - - /** @var DOMElement $restored */ - $restored = $codec->decode(type_xml_element(), $codec->encode(type_xml_element(), $element)); - - static::assertInstanceOf(DOMElement::class, $restored); - static::assertSame('1', $restored->C14N()); - } - - public function test_a_restored_xml_element_does_not_canonicalize_to_an_empty_string(): void - { - $codec = new DomValueCodec(); - - $left = new DOMDocument(); - $left->loadXML('1'); - $right = new DOMDocument(); - $right->loadXML('999'); - - /** @var DOMElement $restoredLeft */ - $restoredLeft = $codec->decode(type_xml_element(), $codec->encode(type_xml_element(), $left->documentElement)); - /** @var DOMElement $restoredRight */ - $restoredRight = $codec->decode(type_xml_element(), $codec->encode( - type_xml_element(), - $right->documentElement, - )); - - static::assertNotSame('', $restoredLeft->C14N()); - static::assertNotSame($restoredLeft->C14N(), $restoredRight->C14N()); - } - - public function test_html_document_survives_a_round_trip(): void - { - if (!class_exists('\Dom\HTMLDocument')) { - static::markTestSkipped('\Dom\HTMLDocument requires PHP 8.4+'); - } - - $document = ValueDecoder::htmlDocumentFromString('

x

'); - - $codec = new DomValueCodec(); - - static::assertSame( - type_string()->cast($document), - type_string()->cast($codec->decode(type_html(), $codec->encode(type_html(), $document))), - ); - } - - public function test_html_element_survives_a_round_trip(): void - { - if (!class_exists('\Dom\HTMLDocument')) { - static::markTestSkipped('\Dom\HTMLDocument requires PHP 8.4+'); - } - - $element = ValueDecoder::htmlElementFromString('

x

'); - - $codec = new DomValueCodec(); - - static::assertSame( - type_string()->cast($element), - type_string()->cast($codec->decode(type_html_element(), $codec->encode(type_html_element(), $element))), - ); - } - - public function test_decode_rejects_a_value_that_is_not_base64(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Given value is not valid base64'); - - (new DomValueCodec())->decode(type_xml(), '!!! not base64 !!!'); - } - - public function test_decode_rejects_a_value_that_is_not_gzcompressed(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Given value is not valid gzcompressed XML'); - - (new DomValueCodec())->decode(type_xml(), base64_encode('plain, uncompressed')); - } - - public function test_decode_rejects_a_payload_that_is_not_xml(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('is not valid XML'); - - (new DomValueCodec())->decode(type_xml(), base64_encode((string) gzcompress('not xml at all'))); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php index f99b465acb..33cdad3d5d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php @@ -4,12 +4,14 @@ namespace Flow\ETL\Tests\Unit\Transformer; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\DerivedColumns; 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; use function Flow\ETL\DSL\str_schema; @@ -51,26 +53,38 @@ public function test_value_names_the_row_of_a_null_under_a_not_null_definition() (new DerivedColumns())->value(int_schema('a'), null, 3); } - public function test_rows_trusts_a_batch_declared_under_the_output_schema(): void + public function test_rows_adds_the_derived_column_under_the_output_schema(): void { $output = schema(int_schema('a'), str_schema('note', nullable: true)); static::assertSame( - [['a' => 1]], + [['a' => 1, 'note' => 'x']], (new DerivedColumns()) - ->rows($output, $output, [row(['a' => 1])]) + ->rows( + rows(schema(int_schema('a')), row(['a' => 1])), + $output, + $output, + 'note', + (new PhpBackend())->constant(str_schema('note', nullable: true), 'x', 1), + ) ->toArray(), ); } - public function test_rows_conforms_a_batch_declared_under_another_schema(): void + public function test_rows_matches_a_batch_declared_under_another_schema(): void { + $declared = schema(int_schema('a'), str_schema('note', nullable: true)); + static::assertSame( - [['a' => 1, 'note' => null]], + [['a' => 1, 'note' => 'x', 'extra' => null]], (new DerivedColumns()) - ->rows(schema(int_schema('a')), schema(int_schema('a'), str_schema('note', nullable: true)), [row([ - 'a' => 1, - ])]) + ->rows( + rows(schema(int_schema('a')), row(['a' => 1])), + $declared, + $declared->add(str_schema('extra', nullable: true)), + 'note', + (new PhpBackend())->constant(str_schema('note', nullable: true), 'x', 1), + ) ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php index e457088287..0dd9b9b297 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php @@ -10,6 +10,7 @@ use Flow\ETL\Transformer\NestedExpandTransformer; use Flow\ETL\Transformer\ScalarFunctionTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\concat; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; @@ -154,6 +155,6 @@ public function test_a_null_under_a_not_null_definition_names_its_output_row(): $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "s" (row 1)'); - $step->transform(rows($input, row(['tags' => ['x']]), row(['tags' => [null]])), flow_context(config())); + $step->transform(array_to_rows([['tags' => ['x']], ['tags' => [null]]], $input), flow_context(config())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php index 831c2372e6..c57df979d3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php @@ -29,7 +29,6 @@ use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; -use function Flow\Types\DSL\type_mixed; use function Flow\Types\DSL\type_string; final class NestedExpansionTest extends FlowTestCase @@ -159,20 +158,6 @@ public function test_of_is_null_without_an_expand(): void )); } - public function test_zipped_expands_over_mixed_lists_stay_mixed(): void - { - $expansion = NestedExpansionContext::of( - structure(['a' => ref('a')->expand(), 'b' => ref('b')->expand()]), - schema(list_schema('a', type_list(type_mixed())), list_schema('b', type_list(type_mixed()))), - ); - - static::assertSame('structure{a: mixed, b: mixed}', $expansion->returns()->toString()); - static::assertSame( - [['a' => 1, 'b' => 'x'], ['a' => 2, 'b' => null]], - $expansion->eval(row(['a' => [1, 2], 'b' => ['x']]), flow_context(config())), - ); - } - public function test_an_expand_over_a_map_reads_its_values_by_position(): void { static::assertSame( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/RenameEntryTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/RenameEntryTransformerTest.php index 7a399b354f..714f63b51a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/RenameEntryTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/RenameEntryTransformerTest.php @@ -23,6 +23,17 @@ final class RenameEntryTransformerTest extends FlowTestCase { + public function test_renaming_keeps_the_column_position_and_its_values(): void + { + $renamed = (new RenameEntryTransformer('a', 'x'))->transform( + rows(schema(integer_schema('a'), integer_schema('b')), row(['a' => 1, 'b' => 2])), + flow_context(config()), + ); + + static::assertSame(['x', 'b'], $renamed->first()->names()); + static::assertSame([['x' => 1, 'b' => 2]], $renamed->toArray()); + } + public function test_bind_renames_the_column_in_place(): void { static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php index cf974571b6..b94006e735 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php @@ -26,27 +26,41 @@ public function test_a_multi_row_payload_gives_up(): void ); static::assertSame( - ['id' => null], - SerializedPayloadDecoderTest::decoder()->decode(row(['serialized' => $payload])), + [], + SerializedPayloadDecoderTest::decoder() + ->decode(row(['serialized' => $payload])) + ->values(), ); } public function test_a_non_string_value_gives_up(): void { - static::assertSame(['id' => null], SerializedPayloadDecoderTest::decoder()->decode(row(['serialized' => 123]))); + static::assertSame( + [], + SerializedPayloadDecoderTest::decoder() + ->decode(row(['serialized' => 123])) + ->values(), + ); } public function test_a_payload_that_does_not_deserialize_gives_up(): void { static::assertSame( - ['id' => null], - SerializedPayloadDecoderTest::decoder()->decode(row(['serialized' => 'not-serialized'])), + [], + SerializedPayloadDecoderTest::decoder() + ->decode(row(['serialized' => 'not-serialized'])) + ->values(), ); } public function test_a_row_without_the_source_column_gives_up(): void { - static::assertSame(['id' => null], SerializedPayloadDecoderTest::decoder()->decode(row(['other' => 1]))); + static::assertSame( + [], + SerializedPayloadDecoderTest::decoder() + ->decode(row(['other' => 1])) + ->values(), + ); } public function test_it_reads_the_declared_columns_out_of_the_payload(): void @@ -58,14 +72,14 @@ public function test_it_reads_the_declared_columns_out_of_the_payload(): void static::assertSame( ['id' => 7], - SerializedPayloadDecoderTest::decoder()->decode(row(['serialized' => $payload])), + SerializedPayloadDecoderTest::decoder() + ->decode(row(['serialized' => $payload])) + ->values(), ); } public static function decoder(): SerializedPayloadDecoder { - return SerializedPayloadDecoder::of(ref('serialized'), new Base64Serializer(new FloeSerializer()), [ - 'id' => 'id', - ]); + return SerializedPayloadDecoder::of(ref('serialized'), new Base64Serializer(new FloeSerializer()), ['id']); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnpackedColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnpackedColumnsTest.php index 0a21880813..86f12aa8dd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnpackedColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnpackedColumnsTest.php @@ -41,8 +41,8 @@ public function test_every_declared_column_is_added_nullable_and_prefixed(): voi public function test_values_prefixes_declared_keys_drops_undeclared_and_nulls_absent(): void { static::assertSame( - ['id' => 1, 'u.a' => 1, 'u.b' => null], - (new UnpackedColumns())->values(['id' => 1], 'u.', schema(int_schema('a'), str_schema('b')), [ + ['u.a' => 1, 'u.b' => null], + (new UnpackedColumns())->values('u.', schema(int_schema('a'), str_schema('b')), [ 'a' => '1', 'c' => 'x', ]), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php index e89a0eea42..92d5113ab6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Transformer; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\UnserializeTransformer; use Flow\Floe\FloeSerializer; @@ -23,6 +24,22 @@ final class UnserializeTransformerTest extends FlowTestCase { + public function test_a_payload_written_with_another_type_is_refused(): void + { + $payload = serialize_to_string( + new Base64Serializer(new FloeSerializer()), + rows(schema(str_schema('id')), row(['id' => '12'])), + ); + + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "id" (row 0): could not convert \'12\' (string) to integer'); + + (new UnserializeTransformer('serialized', schema(int_schema('id'))))->transform( + rows(schema(str_schema('serialized')), row(['serialized' => $payload])), + flow_context(), + ); + } + public function test_bind_expands_the_declared_target_into_nullable_columns(): void { static::assertEquals( diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeEngineContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php similarity index 85% rename from src/core/etl/tests/Flow/Floe/Tests/Context/FloeEngineContext.php rename to src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php index 8d5e1043d4..3eb0614f35 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeEngineContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php @@ -5,7 +5,6 @@ namespace Flow\Floe\Tests\Context; use Flow\ETL\Row; -use Flow\ETL\Row\NativeRowHydrator; use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -23,31 +22,18 @@ use function Flow\ETL\DSL\schema; use function Flow\Filesystem\DSL\path; -final class FloeEngineContext +final class FloeFilesContext { public static function phpWriter(Filesystem $filesystem, Schema $schema, Codec $codec = new NoopCodec()): FloeWriter { return new FloeWriter($filesystem, $schema, new Options(codec: $codec), new PhpRowHydrator()); } - public static function nativeWriter( - Filesystem $filesystem, - Schema $schema, - Codec $codec = new NoopCodec(), - ): FloeWriter { - return new FloeWriter($filesystem, $schema, new Options(codec: $codec), new NativeRowHydrator()); - } - public static function phpReader(Filesystem $filesystem, Codec $codec = new NoopCodec()): FloeReader { return new FloeReader($filesystem, $codec, hydrator: new PhpRowHydrator()); } - public static function nativeReader(Filesystem $filesystem, Codec $codec = new NoopCodec()): FloeReader - { - return new FloeReader($filesystem, $codec, hydrator: new NativeRowHydrator()); - } - /** * @return list */ diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeGoldenContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeGoldenContext.php index 7057b91052..13518c9b7d 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeGoldenContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeGoldenContext.php @@ -54,8 +54,8 @@ public static function regenerate(string $version = self::VERSION_DIRECTORY): vo $filesystem->rm($path); } - FloeEngineContext::writeAll( - FloeEngineContext::phpWriter($filesystem, self::schema($batches)), + FloeFilesContext::writeAll( + FloeFilesContext::phpWriter($filesystem, self::schema($batches)), $path, $batches, ); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php index 188c81e6ac..3c937c5ad1 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php @@ -12,7 +12,6 @@ use Flow\Filesystem\Path; use Flow\Floe\Codec; use Flow\Floe\Codec\NoopCodec; -use Flow\Floe\FloeEngine; use Flow\Floe\FloeReader; use Flow\Floe\FloeWriter; use Flow\Floe\Footer; @@ -118,7 +117,7 @@ public static function reconstruct(Filesystem $filesystem, Path $path): Rows } } - return new Rows($file->footer()->schema(), ...$rows); + return rows($file->footer()->schema(), ...$rows); } /** @@ -189,9 +188,8 @@ public static function writeBatches( array $batches, Options $options = new Options(), ?Hydrator $hydrator = null, - FloeEngine $engine = FloeEngine::adaptive, ): string { - $writer = new FloeWriter($filesystem, $schema, $options, $hydrator, $engine); + $writer = new FloeWriter($filesystem, $schema, $options, $hydrator); $writer->create($path); foreach ($batches as $batch) { diff --git a/src/core/etl/tests/Flow/Floe/Tests/Double/SpyHydrator.php b/src/core/etl/tests/Flow/Floe/Tests/Double/SpyHydrator.php index 5bf885e8cb..cbc7bcb184 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Double/SpyHydrator.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Double/SpyHydrator.php @@ -4,8 +4,8 @@ namespace Flow\Floe\Tests\Double; -use Flow\ETL\Row\AdaptiveRowHydrator; use Flow\ETL\Row\Hydrator; +use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -19,13 +19,13 @@ public function dehydrate(Rows $rows): array { $this->dehydrateCalls++; - return (new AdaptiveRowHydrator())->dehydrate($rows); + return (new PhpRowHydrator())->dehydrate($rows); } public function hydrate(array $batch, Schema $schema): Rows { $this->hydrateCalls++; - return (new AdaptiveRowHydrator())->hydrate($batch, $schema); + return (new PhpRowHydrator())->hydrate($batch, $schema); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Fixtures/v2/all-entry-types.floe b/src/core/etl/tests/Flow/Floe/Tests/Fixtures/v2/all-entry-types.floe index 4426c57609dee7e974b2259831d656733c1dc724..8211db1961bd477785f6aec9da66af3ae07398a9 100644 GIT binary patch delta 67 zcmca8eO#Ku&Bx!BiGgYIM2=&^47`3B3{b!fq(eiTH@-f@BV}e%tD}^gT9TNOSdyq@ ORb5*v!_B||(g^@43lQ1> delta 56 zcmX>ueNmdj&Bx!BiGgYEM2=&!4?g&2FhBt>kajIC$}dRO4^J#APAuQ}@C*;5`Q&xH Fk^spQ5Xk@l diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php index 4e81f57ab2..efa1973663 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php @@ -5,13 +5,10 @@ namespace Flow\Floe\Tests\Integration; use DateTimeZone; -use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Tests\Context\LoaderEndingContext; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Filesystem\Exception\RuntimeException as FilesystemRuntimeException; use Flow\Filesystem\Tests\Double\FailingCloseFilesystem; -use Flow\Floe\FloeEngine; -use Flow\Floe\NativeFloeEncoder; use Flow\Types\Value\Json; use function array_keys; @@ -60,37 +57,16 @@ public function test_append_writes_sibling_files_read_as_union(): void static::assertSame(2, data_frame()->read(from_floe($dir . '/*.floe'))->count()); } - public function test_writing_and_reading_with_explicit_native_engine(): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension is not loaded'); - } - - $path = $this->cacheDir->suffix('native-engine.floe'); - - data_frame() - ->read(from_array([['id' => 1], ['id' => 2]])) - ->write(to_floe($path, engine: FloeEngine::native)->saveMode(overwrite())) - ->run(); - - static::assertSame(2, data_frame()->read(from_floe($path, engine: FloeEngine::native))->count()); - } - - public function test_writing_and_reading_with_explicit_php_engine(): void + public function test_writing_and_reading_with_the_php_hydrator(): void { $path = $this->cacheDir->suffix('php-engine.floe'); - data_frame(config_builder()->hydrator(new PhpRowHydrator())) + data_frame(config_builder()) ->read(from_array([['id' => 1], ['id' => 2]])) - ->write(to_floe($path, engine: FloeEngine::php)->saveMode(overwrite())) + ->write(to_floe($path)->saveMode(overwrite())) ->run(); - static::assertSame( - 2, - data_frame(config_builder()->hydrator(new PhpRowHydrator())) - ->read(from_floe($path, engine: FloeEngine::php)) - ->count(), - ); + static::assertSame(2, data_frame(config_builder())->read(from_floe($path))->count()); } public function test_a_timezone_column_round_trips_through_floe(): void diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeGoldenTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeGoldenTest.php index 6f573af36b..bc6f45a67c 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeGoldenTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeGoldenTest.php @@ -6,7 +6,7 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\FlowIntegrationTestCase; -use Flow\Floe\Tests\Context\FloeEngineContext; +use Flow\Floe\Tests\Context\FloeFilesContext; use Flow\Floe\Tests\Context\FloeGoldenContext; use Generator; use PHPUnit\Framework\Attributes\DataProvider; @@ -43,8 +43,8 @@ public function test_golden_bytes_are_unchanged(string $name, array $batches): v { $written = $this->cacheDir->suffix('golden-' . $name . '.floe'); - FloeEngineContext::writeAll( - FloeEngineContext::phpWriter($this->fs(), FloeGoldenContext::schema($batches)), + FloeFilesContext::writeAll( + FloeFilesContext::phpWriter($this->fs(), FloeGoldenContext::schema($batches)), $written, $batches, ); @@ -69,8 +69,8 @@ public function test_golden_files_read_back_to_the_rows_that_wrote_them(string $ } } - static::assertEquals($expected, FloeEngineContext::readRows( - FloeEngineContext::phpReader($this->fs()), + static::assertEquals($expected, FloeFilesContext::readRows( + FloeFilesContext::phpReader($this->fs()), FloeGoldenContext::path($name), )); } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeHardBreakTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeHardBreakTest.php index 3bdef57169..8a7bc43036 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeHardBreakTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeHardBreakTest.php @@ -6,7 +6,7 @@ use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\Exception\FloeException; -use Flow\Floe\Tests\Context\FloeEngineContext; +use Flow\Floe\Tests\Context\FloeFilesContext; use function Flow\Filesystem\DSL\path; @@ -21,7 +21,7 @@ public function test_reading_a_file_written_before_the_statistics_block_fails_an $this->expectException(FloeException::class); $this->expectExceptionMessageMatches('/Floe footer is malformed: .*statistics/'); - FloeEngineContext::phpReader($this->fs()) + FloeFilesContext::phpReader($this->fs()) ->read(path(__DIR__ . '/../Fixtures/pre-statistics/heterogeneous.floe')) ->schema(); } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloePreAllowExtraRemovalTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloePreAllowExtraRemovalTest.php index 1bc671a8e3..54a93e3b74 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloePreAllowExtraRemovalTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloePreAllowExtraRemovalTest.php @@ -5,8 +5,7 @@ namespace Flow\Floe\Tests\Integration; use Flow\ETL\Tests\FlowIntegrationTestCase; -use Flow\Floe\NativeFloeEncoder; -use Flow\Floe\Tests\Context\FloeEngineContext; +use Flow\Floe\Tests\Context\FloeFilesContext; use Flow\Floe\Tests\Mother\RowsMother; use function array_values; @@ -31,23 +30,8 @@ public function test_php_reader_reads_a_footer_that_carries_allow_extra(): void { static::assertEquals( array_values(RowsMother::withAllEntryTypes()->all()), - FloeEngineContext::readRows( - FloeEngineContext::phpReader($this->fs()), - path(__DIR__ . '/../Fixtures/pre-allow-extra-removal/all-entry-types.floe'), - ), - ); - } - - public function test_native_reader_reads_a_footer_that_carries_allow_extra(): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with the RawRowValues pipeline is not loaded.'); - } - - static::assertEquals( - array_values(RowsMother::withAllEntryTypes()->all()), - FloeEngineContext::readRows( - FloeEngineContext::nativeReader($this->fs()), + FloeFilesContext::readRows( + FloeFilesContext::phpReader($this->fs()), path(__DIR__ . '/../Fixtures/pre-allow-extra-removal/all-entry-types.floe'), ), ); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeReaderExtensionParityTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeReaderExtensionParityTest.php deleted file mode 100644 index 9d95a8f07b..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeReaderExtensionParityTest.php +++ /dev/null @@ -1,207 +0,0 @@ - [RowsMother::withAllEntryTypes()], - 'heterogeneous' => [RowsMother::heterogeneous()], - 'empty' => [rows(schema())], - ]; - } - - #[Override] - protected function setUp(): void - { - parent::setUp(); - - if (!NativeFloeEncoder::isSupported()) { - self::markTestSkipped('flow_php extension with the RawRowValues pipeline is not loaded.'); - } - } - - #[DataProvider('rows_datasets')] - public function test_extension_and_pure_php_hydrate_identical_rows(Rows $rows): void - { - $path = $this->cacheDir->suffix('parity.floe'); - - $writer = new FloeWriter($this->fs(), $rows->schema()); - $writer->create($path); - $writer->write($rows); - $writer->close(); - - static::assertEquals( - iterator_to_array(FloeEngineContext::phpReader($this->fs())->read($path)->rows()), - iterator_to_array(FloeEngineContext::nativeReader($this->fs())->read($path)->rows()), - ); - } - - public function test_extension_and_pure_php_seek_offset_identically(): void - { - $path = $this->cacheDir->suffix('parity-offset.floe'); - - $data = rows( - schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4, 'email' => null]), - row(['id' => 5, 'email' => 'x']), - row(['id' => 6]), - ); - $writer = new FloeWriter($this->fs(), $data->schema()); - $writer->create($path); - $writer->write($data); - $writer->close(); - - static::assertEquals( - iterator_to_array(FloeEngineContext::phpReader($this->fs())->read($path)->rows(1000, 2, 3)), - iterator_to_array(FloeEngineContext::nativeReader($this->fs())->read($path)->rows(1000, 2, 3)), - ); - } - - /** - * @return array - */ - public static function codec_matrix(): array - { - return [ - 'noop codec' => [new NoopCodec()], - 'transforming codec' => [new PrefixingCodecStub()], - ]; - } - - #[DataProvider('rows_datasets')] - public function test_extension_and_pure_php_read_identical_rows_with_transforming_codec(Rows $rows): void - { - $codec = new PrefixingCodecStub(); - $path = $this->cacheDir->suffix('read-codec.floe'); - - $writer = new FloeWriter($this->fs(), $rows->schema(), new Options(codec: $codec)); - $writer->create($path); - $writer->write($rows); - $writer->close(); - - static::assertEquals( - iterator_to_array(FloeEngineContext::phpReader($this->fs(), $codec)->read($path)->rows()), - iterator_to_array(FloeEngineContext::nativeReader($this->fs(), $codec)->read($path)->rows()), - ); - } - - /** - * Full write->read parity across the engine switch for both codecs and for - * plain, partitioned and schema-evolving files: a pure-PHP round-trip and a - * native round-trip must yield identical rows in every cell. - */ - #[DataProvider('codec_matrix')] - public function test_round_trip_matrix_matches_across_engines(Codec $codec): void - { - $cases = [ - 'plain' => [RowsMother::heterogeneous()], - 'multi-write' => [ - rows(schema(int_schema('id'), str_schema('email')), row(['id' => 1, 'email' => 'a'])), - rows(schema(int_schema('id'), str_schema('email')), row(['id' => 2, 'email' => 'x'])), - ], - ]; - - foreach ($cases as $name => $batches) { - $schema = array_reduce( - $batches, - static fn(Schema $carry, Rows $batch): Schema => $carry->merge($batch->schema()), - schema(), - ); - - $purePath = $this->cacheDir->suffix("matrix-{$name}-pure.floe"); - $extPath = $this->cacheDir->suffix("matrix-{$name}-ext.floe"); - - foreach ([[$purePath, false], [$extPath, true]] as [$path, $native]) { - $writer = $native - ? FloeEngineContext::nativeWriter($this->fs(), $schema, $codec) - : FloeEngineContext::phpWriter($this->fs(), $schema, $codec); - $writer->create($path); - - foreach ($batches as $batch) { - $writer->write($batch); - } - - $writer->close(); - } - - static::assertSame( - $this->fs()->readFrom($purePath)->content(), - $this->fs()->readFrom($extPath)->content(), - "byte-identity failed for {$name}", - ); - - static::assertEquals( - iterator_to_array(FloeEngineContext::phpReader($this->fs(), $codec)->read($purePath)->rows()), - iterator_to_array(FloeEngineContext::nativeReader($this->fs(), $codec)->read($extPath)->rows()), - "row parity failed for {$name}", - ); - } - } - - public function test_extension_and_pure_php_pad_merged_sections_identically(): void - { - // a merged file re-encodes to one union schema; base rows lack email and must pad - // identically across engines on read - $path = $this->cacheDir->suffix('parity-evolved.floe'); - $base = $this->cacheDir->suffix('parity-base.floe'); - $evolved = $this->cacheDir->suffix('parity-new.floe'); - - $baseRows = rows(schema(int_schema('id')), row(['id' => 1])); - $writer = new FloeWriter($this->fs(), $baseRows->schema()); - $writer->create($base); - $writer->write($baseRows); - $writer->close(); - - $evolvedRows = rows( - schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 2, 'email' => null]), - ); - $writer = new FloeWriter($this->fs(), $evolvedRows->schema()); - $writer->create($evolved); - $writer->write($evolvedRows); - $writer->close(); - - (new FloeMerger($this->fs()))->merge([$base, $evolved], $path); - - static::assertEquals( - iterator_to_array(FloeEngineContext::phpReader($this->fs())->read($path)->rows()), - iterator_to_array(FloeEngineContext::nativeReader($this->fs())->read($path)->rows()), - ); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php index a55bef734a..0a6f4e12e3 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php @@ -8,15 +8,11 @@ use Flow\ETL\Schema; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\Exception\IncompatibleSchemaException; -use Flow\Floe\FloeEngine; use Flow\Floe\FloeWriter; -use Flow\Floe\NativeFloeEncoder; use Flow\Floe\Options; use Flow\Floe\Tests\Context\FloeStreamReaderContext; use PHPUnit\Framework\Attributes\DataProvider; -use Throwable; -use function array_key_exists; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\row; @@ -26,11 +22,6 @@ final class FloeWriteContractTest extends FlowIntegrationTestCase { - public static function engines(): array - { - return ['php' => [FloeEngine::php], 'native' => [FloeEngine::native]]; - } - public static function rejected_values(): array { return [ @@ -63,62 +54,35 @@ public static function rejected_values(): array } #[DataProvider('rejected_values')] - public function test_both_engines_reject_the_same_value_with_the_same_message( + public function test_the_writer_rejects_the_value_with_the_message( Schema $schema, Rows $batch, string $expectedMessage, ): void { - $messages = []; - - foreach ([FloeEngine::php, FloeEngine::native] as $engine) { - if ($engine === FloeEngine::native && !NativeFloeEncoder::isSupported()) { - continue; - } - - $name = $engine->value; - $path = $this->cacheDir->suffix('contract-' . $name . '-' . md5($expectedMessage) . '.floe'); - $writer = new FloeWriter($this->fs(), $schema, new Options(), null, $engine); - $writer->create($path); - - try { - $writer->write($batch); - static::fail($name . ' engine accepted a value it must reject'); - } catch (Throwable $e) { - $messages[$name] = $e::class . ': ' . $e->getMessage(); - } - - $writer->close(); - - static::assertSame( - [], - FloeStreamReaderContext::readAll($this->fs(), $path)->toArray(), - $name . ' engine emitted bytes for a rejected batch', - ); - } + $path = $this->cacheDir->suffix('contract-' . md5($expectedMessage) . '.floe'); + $writer = new FloeWriter($this->fs(), $schema, new Options()); + $writer->create($path); - foreach ($messages as $name => $message) { - static::assertStringContainsString($expectedMessage, $message, $name . ' engine message'); - static::assertStringContainsString( - IncompatibleSchemaException::class, - $message, - $name . ' exception class', - ); + try { + $writer->write($batch); + static::fail('the writer accepted a value it must reject'); + } catch (IncompatibleSchemaException $e) { + static::assertStringContainsString($expectedMessage, $e->getMessage()); } - if (array_key_exists('php', $messages) && array_key_exists('native', $messages)) { - static::assertSame($messages['php'], $messages['native'], 'engines disagree on the rejection'); - } + $writer->close(); + + static::assertSame( + [], + FloeStreamReaderContext::readAll($this->fs(), $path)->toArray(), + 'the writer emitted bytes for a rejected batch', + ); } - #[DataProvider('engines')] - public function test_a_rejected_batch_leaves_previously_written_rows_readable(FloeEngine $engine): void + public function test_a_rejected_batch_leaves_previously_written_rows_readable(): void { - if ($engine === FloeEngine::native && !NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension is not loaded.'); - } - - $path = $this->cacheDir->suffix('contract-survivor-' . $engine->value . '.floe'); - $writer = new FloeWriter($this->fs(), schema(int_schema('id')), new Options(), null, $engine); + $path = $this->cacheDir->suffix('contract-survivor.floe'); + $writer = new FloeWriter($this->fs(), schema(int_schema('id')), new Options()); $writer->create($path); $writer->write(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); @@ -133,25 +97,18 @@ public function test_a_rejected_batch_leaves_previously_written_rows_readable(Fl static::assertSame([['id' => 1], ['id' => 2]], FloeStreamReaderContext::readAll($this->fs(), $path)->toArray()); } - #[DataProvider('engines')] /** * SCHEMA EVOLUTION: the reverse - a first batch WITHOUT the column and a later one WITH it - * is rejected as a new column. Once append supports adding an optional column, that case * belongs here too. */ - public function test_a_batch_omitting_a_nullable_column_still_writes(FloeEngine $engine): void + public function test_a_batch_omitting_a_nullable_column_still_writes(): void { - if ($engine === FloeEngine::native && !NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension is not loaded.'); - } - - $path = $this->cacheDir->suffix('contract-absent-' . $engine->value . '.floe'); + $path = $this->cacheDir->suffix('contract-absent.floe'); $writer = new FloeWriter( $this->fs(), schema(int_schema('id'), str_schema('name', nullable: true)), new Options(), - null, - $engine, ); $writer->create($path); $writer->write(rows( @@ -171,21 +128,10 @@ public function test_a_batch_omitting_a_nullable_column_still_writes(FloeEngine * b57's writer half: the old check walked the row's own values, so a NOT NULL column the batch * simply omitted was never looked at and was encoded as VALUE_ABSENT. */ - #[DataProvider('engines')] - public function test_a_batch_omitting_a_not_null_column_is_refused(FloeEngine $engine): void + public function test_a_batch_omitting_a_not_null_column_is_refused(): void { - if ($engine === FloeEngine::native && !NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension is not loaded.'); - } - - $path = $this->cacheDir->suffix('contract-absent-not-null-' . $engine->value . '.floe'); - $writer = new FloeWriter( - $this->fs(), - schema(int_schema('id'), str_schema('name')), - new Options(), - null, - $engine, - ); + $path = $this->cacheDir->suffix('contract-absent-not-null.floe'); + $writer = new FloeWriter($this->fs(), schema(int_schema('id'), str_schema('name')), new Options()); $writer->create($path); $writer->write(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a']))); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriterExtensionParityTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriterExtensionParityTest.php deleted file mode 100644 index 680ffe765b..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriterExtensionParityTest.php +++ /dev/null @@ -1,165 +0,0 @@ - [RowsMother::withAllEntryTypes()], - 'heterogeneous' => [RowsMother::heterogeneous()], - 'empty' => [rows(schema())], - ]; - } - - #[Override] - protected function setUp(): void - { - parent::setUp(); - - if (!NativeFloeEncoder::isSupported()) { - self::markTestSkipped('flow_php extension is not loaded.'); - } - } - - public function test_extension_and_pure_php_reject_datetime_subclass_identically(): void - { - $rows = rows(schema(datetime_schema('at')), row(['at' => new CustomDateTime('2025-01-01 00:00:00 UTC')])); - $schema = $rows->schema(); - - $writers = [ - 'php' => FloeEngineContext::phpWriter($this->fs(), $schema), - 'ext' => FloeEngineContext::nativeWriter($this->fs(), $schema), - ]; - - foreach ($writers as $engine => $writer) { - $writer->create($this->cacheDir->suffix('subclass-' . $engine . '.floe')); - - try { - $writer->write($rows); - static::fail('Expected a FloeException for a custom datetime subclass'); - } catch (FloeException $e) { - static::assertStringContainsString('DateTime and DateTimeImmutable', $e->getMessage()); - } - } - } - - #[DataProvider('rows_datasets')] - public function test_extension_and_pure_php_write_byte_identical_files(Rows $rows): void - { - $purePath = $this->cacheDir->suffix('write-pure.floe'); - $extPath = $this->cacheDir->suffix('write-ext.floe'); - - $schema = $rows->schema(); - - FloeEngineContext::writeAll(FloeEngineContext::phpWriter($this->fs(), $schema), $purePath, [$rows]); - FloeEngineContext::writeAll(FloeEngineContext::nativeWriter($this->fs(), $schema), $extPath, [$rows]); - - static::assertSame($this->fs()->readFrom($purePath)->content(), $this->fs()->readFrom($extPath)->content()); - } - - public function test_extension_and_pure_php_write_byte_identical_files_across_multiple_writes(): void - { - $batches = [ - rows( - schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => 'b']), - ), - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 3, 'name' => 'c'])), - rows( - schema(int_schema('id'), str_schema('name')), - row(['id' => 4, 'name' => 'd']), - row(['id' => 5, 'name' => 'e']), - ), - ]; - - $purePath = $this->cacheDir->suffix('multi-write-pure.floe'); - $extPath = $this->cacheDir->suffix('multi-write-ext.floe'); - - $schema = schema(int_schema('id'), str_schema('name')); - - FloeEngineContext::writeAll(FloeEngineContext::phpWriter($this->fs(), $schema), $purePath, $batches); - FloeEngineContext::writeAll(FloeEngineContext::nativeWriter($this->fs(), $schema), $extPath, $batches); - - static::assertSame($this->fs()->readFrom($purePath)->content(), $this->fs()->readFrom($extPath)->content()); - } - - /** - * A transforming (non-identity) codec must not fork the engine: the native - * body-encode produces the same ROW bodies as the PHP engine, the codec runs - * in PHP either way, so the files stay byte-identical (the A1 fix). - */ - #[DataProvider('rows_datasets')] - public function test_extension_and_pure_php_write_byte_identical_files_with_transforming_codec(Rows $rows): void - { - $codec = new PrefixingCodecStub(); - - $purePath = $this->cacheDir->suffix('write-codec-pure.floe'); - $extPath = $this->cacheDir->suffix('write-codec-ext.floe'); - - $schema = $rows->schema(); - - FloeEngineContext::writeAll(FloeEngineContext::phpWriter($this->fs(), $schema, $codec), $purePath, [$rows]); - FloeEngineContext::writeAll(FloeEngineContext::nativeWriter($this->fs(), $schema, $codec), $extPath, [$rows]); - - static::assertSame($this->fs()->readFrom($purePath)->content(), $this->fs()->readFrom($extPath)->content()); - } - - public function test_extension_and_pure_php_append_byte_identically(): void - { - $purePath = $this->cacheDir->suffix('append-pure.floe'); - $extPath = $this->cacheDir->suffix('append-ext.floe'); - - $createRows = rows( - schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 1, 'email' => null]), - ); - $appendRows = rows(schema(int_schema('id'), str_schema('email')), row(['id' => 2, 'email' => 'x'])); - $schema = $createRows->schema()->merge($appendRows->schema()); - - foreach ([[$purePath, false], [$extPath, true]] as [$path, $native]) { - $create = $native - ? FloeEngineContext::nativeWriter($this->fs(), $schema) - : FloeEngineContext::phpWriter($this->fs(), $schema); - $create->create($path); - $create->write($createRows); - $create->close(); - - $append = $native - ? FloeEngineContext::nativeWriter($this->fs(), $schema) - : FloeEngineContext::phpWriter($this->fs(), $schema); - $append->append($path); - $append->write($appendRows); - $append->close(); - } - - static::assertSame($this->fs()->readFrom($purePath)->content(), $this->fs()->readFrom($extPath)->content()); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Mother/RowsMother.php b/src/core/etl/tests/Flow/Floe/Tests/Mother/RowsMother.php index d41a36763d..36889fb1a2 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Mother/RowsMother.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Mother/RowsMother.php @@ -152,7 +152,7 @@ enum_schema('enum_basic', BasicEnum::class), ), 'datetime_mutable' => new DateTime('2025-06-15 12:30:45.654321', new DateTimeZone('America/New_York')), 'datetime_before_epoch' => new DateTimeImmutable('1969-07-20 20:17:00.500000 UTC'), - 'date' => new DateTimeImmutable('2025-06-15 00:00:00', new DateTimeZone('Europe/Warsaw')), + 'date' => new DateTimeImmutable('2025-06-15 00:00:00', new DateTimeZone('UTC')), 'time' => new DateInterval('PT2H30M15S'), 'uuid' => type_uuid()->cast('0196aecb-b568-7e57-a381-8ec8d3e4a531'), 'json' => type_json()->cast('[1,2,3]'), diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeEngineTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeEngineTest.php deleted file mode 100644 index fe6e249af9..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeEngineTest.php +++ /dev/null @@ -1,54 +0,0 @@ -encoder($this->schema()), - ); - } - - public function test_native_engine_builds_native_encoder_when_supported(): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension is not loaded'); - } - - static::assertInstanceOf(NativeFloeEncoder::class, FloeEngine::native->encoder($this->schema())); - } - - public function test_php_engine_builds_php_encoder(): void - { - static::assertInstanceOf(PhpFloeEncoder::class, FloeEngine::php->encoder($this->schema())); - } - - public function test_case_values_are_stable_identifiers(): void - { - static::assertSame('adaptive', FloeEngine::adaptive->value); - static::assertSame('native', FloeEngine::native->value); - static::assertSame('php', FloeEngine::php->value); - } - - private function schema(): Schema - { - return schema_from_json(FloeSchemaContext::schemaBody(schema(int_schema('id'), str_schema('name')))); - } -} 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 2c598399fc..a7c83cbb20 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php @@ -12,7 +12,7 @@ use Flow\ETL\Tests\Mother\RowsMother; use Flow\Filesystem\Tests\Double\RejectingFilter; use Flow\Floe\FloeExtractor; -use Flow\Floe\Tests\Context\FloeEngineContext; +use Flow\Floe\Tests\Context\FloeFilesContext; use function array_sum; use function Flow\ETL\DSL\config; @@ -38,7 +38,7 @@ final class FloeExtractorTest extends FlowTestCase public function test_a_later_file_with_other_columns_throws_naming_both_files(): void { $memory = memory_filesystem(); - FloeEngineContext::writeFiles($memory, [ + FloeFilesContext::writeFiles($memory, [ 'memory://glob/a.floe' => rows(schema(int_schema('id')), row(['id' => 1])), 'memory://glob/b.floe' => rows( schema(int_schema('id'), str_schema('extra')), @@ -64,7 +64,7 @@ public function test_a_later_file_with_other_columns_throws_naming_both_files(): public function test_a_later_file_with_another_column_type_throws(): void { $memory = memory_filesystem(); - FloeEngineContext::writeFiles($memory, [ + FloeFilesContext::writeFiles($memory, [ 'memory://glob/a.floe' => rows(schema(int_schema('id')), row(['id' => 1])), 'memory://glob/b.floe' => rows(schema(str_schema('id')), row(['id' => 'x'])), ]); @@ -80,7 +80,7 @@ public function test_a_later_file_with_another_column_type_throws(): void public function test_a_later_file_with_the_columns_in_another_order_follows_the_first(): void { $memory = memory_filesystem(); - FloeEngineContext::writeFiles($memory, [ + FloeFilesContext::writeFiles($memory, [ 'memory://glob/a.floe' => rows( schema(int_schema('id'), str_schema('name')), row([ @@ -109,7 +109,7 @@ public function test_a_later_file_with_the_columns_in_another_order_follows_the_ public function test_union_by_name_reads_every_file_under_one_schema(): void { $memory = memory_filesystem(); - FloeEngineContext::writeFiles($memory, [ + FloeFilesContext::writeFiles($memory, [ 'memory://glob/a.floe' => rows(schema(int_schema('id')), row(['id' => 1])), 'memory://glob/b.floe' => rows( schema(int_schema('id'), str_schema('extra')), @@ -318,7 +318,7 @@ public function test_schema_reads_footer_only(): void public function test_schema_declares_partition_columns_from_the_path(): void { $memory = memory_filesystem(); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); static::assertSame( ['id', 'country'], @@ -329,7 +329,7 @@ public function test_schema_declares_partition_columns_from_the_path(): void public function test_extract_fills_partition_columns_from_the_path(): void { $memory = memory_filesystem(); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); $extractor = from_floe(path('memory://parts/*/*.floe'), filesystem: $memory); $values = []; @@ -346,7 +346,7 @@ public function test_extract_fills_partition_columns_from_the_path(): void public function test_schema_opens_only_the_first_file(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); from_floe(path('memory://parts/*/*.floe'), filesystem: $counting)->schema(); @@ -356,7 +356,7 @@ public function test_schema_opens_only_the_first_file(): void public function test_schema_is_memoised(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); $extractor = from_floe(path('memory://parts/*/*.floe'), filesystem: $counting); @@ -367,7 +367,7 @@ public function test_schema_is_memoised(): void public function test_union_by_name_opens_every_file(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); from_floe(path('memory://parts/*/*.floe'), filesystem: $counting)->unionByName()->schema(); @@ -377,7 +377,7 @@ public function test_union_by_name_opens_every_file(): void public function test_schema_closes_every_reader_it_opens(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); from_floe(path('memory://parts/*/*.floe'), filesystem: $counting)->unionByName()->schema(); @@ -387,7 +387,7 @@ public function test_schema_closes_every_reader_it_opens(): void public function test_declared_partition_types_reach_the_rows(): void { $memory = memory_filesystem(); - FloeEngineContext::writeYearPartitionedFiles($memory); + FloeFilesContext::writeYearPartitionedFiles($memory); $extractor = from_floe(path('memory://years/*/*.floe'), filesystem: $memory)->partitionTypes( partition_types(year: type_integer()), @@ -406,7 +406,7 @@ public function test_declared_partition_types_reach_the_rows(): void public function test_a_declared_schema_may_name_the_partition_column(): void { $memory = memory_filesystem(); - FloeEngineContext::writeYearPartitionedFiles($memory); + FloeFilesContext::writeYearPartitionedFiles($memory); $extractor = from_floe(path('memory://years/*/*.floe'), filesystem: $memory)->withSchema(schema( int_schema('id'), @@ -425,7 +425,7 @@ public function test_a_declared_schema_may_name_the_partition_column(): void public function test_extract_closes_the_reader_when_the_generator_is_abandoned(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); $generator = from_floe(path('memory://parts/*/*.floe'), filesystem: $counting)->extract(flow_context(config())); $generator->current(); @@ -437,7 +437,7 @@ public function test_extract_closes_the_reader_when_the_generator_is_abandoned() public function test_extract_closes_every_reader_it_opens(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); foreach (from_floe(path('memory://parts/*/*.floe'), filesystem: $counting)->extract( flow_context(config()), @@ -450,7 +450,7 @@ public function test_extract_closes_every_reader_it_opens(): void public function test_extract_closes_the_reader_it_skips_for_the_offset(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); foreach (from_floe(path('memory://parts/*/*.floe'), filesystem: $counting) ->withOffset(1) @@ -463,7 +463,7 @@ public function test_extract_closes_the_reader_it_skips_for_the_offset(): void public function test_extract_closes_the_reader_when_the_pipeline_stops(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); $generator = from_floe(path('memory://parts/*/*.floe'), filesystem: $counting)->extract(flow_context(config())); @@ -476,7 +476,7 @@ public function test_extract_closes_the_reader_when_the_pipeline_stops(): void public function test_a_path_filter_narrows_the_read_but_not_the_schema(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); $extractor = from_floe(path('memory://parts/*/*.floe'), filesystem: $counting); $schema = $extractor->schema(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php index 9f1f96b68b..021a4441fa 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php @@ -6,11 +6,9 @@ use Flow\ETL\Exception\RuntimeException; use Flow\Floe\Exception\IncompatibleSchemaException; -use Flow\Floe\Tests\Double\SpyHydrator; use PHPUnit\Framework\TestCase; use function Flow\ETL\DSL\config; -use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_array; @@ -49,20 +47,6 @@ public function test_closure_writes_a_readable_non_torn_file(): void static::assertSame([1, 2], $ids); } - public function test_load_honors_the_context_hydrator(): void - { - $hydrator = new SpyHydrator(); - $context = flow_context(config_builder()->hydrator($hydrator)->build()); - $memory = memory_filesystem(); - $path = path('memory://hydrator.floe'); - - $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), $context); - $loader->closure($context); - - static::assertGreaterThan(0, $hydrator->dehydrateCalls); - } - public function test_destination_returns_path(): void { $memory = memory_filesystem(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php index e054630a2b..5380981b21 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php @@ -4,7 +4,7 @@ namespace Flow\Floe\Tests\Unit; -use Flow\ETL\Row\AdaptiveRowHydrator; +use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; @@ -652,9 +652,10 @@ public function test_rows_through_a_custom_identity_codec_with_long_row_body_thr $filesystem = memory_filesystem(); $path = path('memory://custom-codec-long-row.floe'); $schemaBody = FloeSchemaContext::schemaBody(schema(int_schema('id'))); - $rowBody = (new PhpFloeEncoder(schema_from_json( - $schemaBody, - )))->encode((new AdaptiveRowHydrator())->dehydrate(rows(schema(int_schema('id')), row(['id' => 1]))))[0]; + $rowBody = (new PhpFloeEncoder(schema_from_json($schemaBody)))->encode((new PhpRowHydrator())->dehydrate(rows( + schema(int_schema('id')), + row(['id' => 1]), + )))[0]; $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); $stream = $filesystem->writeTo($path); $stream->append( @@ -700,9 +701,10 @@ public function test_row_body_longer_than_hydrated_content_throws(): void $filesystem = memory_filesystem(); $path = path('memory://long-row.floe'); $schemaBody = FloeSchemaContext::schemaBody(schema(int_schema('id'))); - $rowBody = (new PhpFloeEncoder(schema_from_json( - $schemaBody, - )))->encode((new AdaptiveRowHydrator())->dehydrate(rows(schema(int_schema('id')), row(['id' => 1]))))[0]; + $rowBody = (new PhpFloeEncoder(schema_from_json($schemaBody)))->encode((new PhpRowHydrator())->dehydrate(rows( + schema(int_schema('id')), + row(['id' => 1]), + )))[0]; $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); $stream = $filesystem->writeTo($path); $stream->append( diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSourceFileTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSourceFileTest.php index 19a4b5c34e..19eaba2a8a 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSourceFileTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSourceFileTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Floe\FloeSourceFile; -use Flow\Floe\Tests\Context\FloeEngineContext; +use Flow\Floe\Tests\Context\FloeFilesContext; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -20,10 +20,10 @@ final class FloeSourceFileTest extends FlowTestCase public function test_close_releases_the_reader(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); (new FloeSourceFile( - FloeEngineContext::phpReader($counting)->read(path('memory://parts/country=PL/data.floe')), + FloeFilesContext::phpReader($counting)->read(path('memory://parts/country=PL/data.floe')), new SourceFile(path('memory://parts/country=PL/data.floe')), ))->close(); @@ -33,12 +33,12 @@ public function test_close_releases_the_reader(): void public function test_schema_comes_from_the_footer(): void { $memory = memory_filesystem(); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); static::assertEquals( schema(int_schema('id')), (new FloeSourceFile( - FloeEngineContext::phpReader($memory)->read(path('memory://parts/country=PL/data.floe')), + FloeFilesContext::phpReader($memory)->read(path('memory://parts/country=PL/data.floe')), new SourceFile(path('memory://parts/country=PL/data.floe')), ))->schema(), ); @@ -47,12 +47,12 @@ public function test_schema_comes_from_the_footer(): void public function test_source_returns_the_listed_file(): void { $memory = memory_filesystem(); - FloeEngineContext::writePartitionedFiles($memory); + FloeFilesContext::writePartitionedFiles($memory); static::assertEquals( new SourceFile(path('memory://parts/country=PL/data.floe')), (new FloeSourceFile( - FloeEngineContext::phpReader($memory)->read(path('memory://parts/country=PL/data.floe')), + FloeFilesContext::phpReader($memory)->read(path('memory://parts/country=PL/data.floe')), new SourceFile(path('memory://parts/country=PL/data.floe')), ))->source(), ); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php index 66a178f70e..e5e931fa98 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php @@ -4,25 +4,17 @@ namespace Flow\Floe\Tests\Unit; -use Closure; use Flow\ETL\Row\Hydrator; use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Row\TypedRowValues; -use Flow\ETL\Rows; use Flow\ETL\Schema\Metadata; use Flow\Floe\Codec\NoopCodec; -use Flow\Floe\FloeEngine; use Flow\Floe\FloeReader; use Flow\Floe\FloeStreamReader; use Flow\Floe\FloeWriter; -use Flow\Floe\NativeFloeEncoder; use Flow\Floe\PhpFloeEncoder; use Flow\Floe\Tests\Context\FloeStreamReaderContext; use Flow\Floe\Tests\Double\ClosingSpySourceStream; -use Flow\Floe\Tests\Double\PrefixingCodecStub; -use Flow\Floe\Tests\Double\SpyHydrator; -use Flow\Floe\Tests\Mother\RowsMother; -use Generator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -34,53 +26,9 @@ use function Flow\Filesystem\DSL\path; use function Flow\Types\DSL\type_integer; use function iterator_to_array; -use function range; -use function serialize; final class FloeStreamReaderTest extends TestCase { - /** - * @return array>}> - */ - public static function reads(): array - { - return [ - 'every row' => [ - static fn(FloeStreamReader $reader): Generator => $reader->rows(10), - [range(1, 10), range(11, 20), range(21, 25)], - ], - 'batch larger than the file' => [ - static fn(FloeStreamReader $reader): Generator => $reader->rows(100), - [range(1, 25)], - ], - 'limit below the batch size' => [ - static fn(FloeStreamReader $reader): Generator => $reader->rows(10, 0, 3), - [range(1, 3)], - ], - 'limit on a batch boundary' => [ - static fn(FloeStreamReader $reader): Generator => $reader->rows(10, 0, 20), - [range(1, 10), range(11, 20)], - ], - 'limit inside a batch' => [ - static fn(FloeStreamReader $reader): Generator => $reader->rows(10, 0, 15), - [range(1, 10), range(11, 15)], - ], - 'offset' => [ - static fn(FloeStreamReader $reader): Generator => $reader->rows(10, 4), - [range(5, 14), range(15, 24), [25]], - ], - 'offset and limit' => [ - static fn(FloeStreamReader $reader): Generator => $reader->rows(10, 4, 12), - [range(5, 14), [15, 16]], - ], - 'head' => [static fn(FloeStreamReader $reader): Generator => $reader->head(7, 5), [range(1, 5), [6, 7]]], - 'tail' => [ - static fn(FloeStreamReader $reader): Generator => $reader->tail(7, 5), - [range(19, 23), [24, 25]], - ], - ]; - } - public function test_close_closes_the_source_stream(): void { $filesystem = memory_filesystem(); @@ -99,79 +47,6 @@ public function test_close_closes_the_source_stream(): void static::assertSame(1, $source->closeCount); } - /** - * @param Closure(FloeStreamReader): Generator $read - * @param list> $batches - */ - #[DataProvider('reads')] - public function test_fused_read_yields_the_batches_of_the_two_step_read(Closure $read, array $batches): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with RustFloeEncoderNative is not loaded'); - } - - $filesystem = memory_filesystem(); - $path = path('memory://fused.floe'); - FloeStreamReaderContext::write($filesystem, $path, RowsMother::numbered(25)); - $spy = new SpyHydrator(); - - $twoStep = iterator_to_array($read((new FloeReader($filesystem, hydrator: $spy))->read($path))); - $fused = iterator_to_array($read((new FloeReader($filesystem))->read($path))); - - static::assertSame($batches, array_map(static fn(Rows $rows): array => $rows->reduceToArray('id'), $fused)); - static::assertEquals($twoStep, $fused); - static::assertGreaterThan(0, $spy->hydrateCalls); - } - - /** - * @param Closure(FloeStreamReader): Generator $read - * @param list> $batches - */ - #[DataProvider('reads')] - public function test_native_engine_reads_a_transforming_codec_like_the_php_engine( - Closure $read, - array $batches, - ): void { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with RustFloeEncoderNative is not loaded'); - } - - $filesystem = memory_filesystem(); - $codec = new PrefixingCodecStub(); - $path = path('memory://codec.floe'); - FloeStreamReaderContext::write($filesystem, $path, RowsMother::numbered(25), codec: $codec); - - $php = iterator_to_array($read((new FloeReader($filesystem, $codec, engine: FloeEngine::php))->read($path))); - $native = iterator_to_array($read((new FloeReader($filesystem, $codec, engine: FloeEngine::native))->read( - $path, - ))); - - static::assertEquals($php, $native); - static::assertSame($batches, array_map(static fn(Rows $rows): array => $rows->reduceToArray('id'), $native)); - } - - /** - * @param Closure(FloeStreamReader): Generator $read - * @param list> $batches - */ - #[DataProvider('reads')] - public function test_native_engine_reads_like_the_php_engine(Closure $read, array $batches): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with RustFloeEncoderNative is not loaded'); - } - - $filesystem = memory_filesystem(); - $path = path('memory://engines.floe'); - FloeStreamReaderContext::write($filesystem, $path, RowsMother::numbered(25)); - - $php = iterator_to_array($read((new FloeReader($filesystem, engine: FloeEngine::php))->read($path))); - $native = iterator_to_array($read((new FloeReader($filesystem, engine: FloeEngine::native))->read($path))); - - static::assertSame(serialize($php), serialize($native)); - static::assertSame($batches, array_map(static fn(Rows $rows): array => $rows->reduceToArray('id'), $native)); - } - /** * @return array */ diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php index d3f7986bd4..5b5f9eee36 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php @@ -4,24 +4,17 @@ namespace Flow\Floe\Tests\Unit; -use DateTimeImmutable; use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; use Flow\Floe\Exception\IncompatibleSchemaException; -use Flow\Floe\FloeEngine; use Flow\Floe\FloeStreamWriter; use Flow\Floe\FloeWriter; use Flow\Floe\Format; -use Flow\Floe\NativeFloeEncoder; use Flow\Floe\Options; use Flow\Floe\Tests\Context\FloeStreamReaderContext; use Flow\Floe\Tests\Double\CodecStub; -use Flow\Floe\Tests\Double\PrefixingCodecStub; -use Flow\Floe\Tests\Double\SpyHydrator; -use Flow\Floe\Tests\Mother\RowsMother; use PHPUnit\Framework\TestCase; -use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; @@ -364,140 +357,4 @@ public function test_column_absent_from_the_session_schema_throws(): void $writer->write(rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 2]))); } - - public function test_fused_write_is_byte_identical_to_the_two_step_write_across_sections(): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with RustFloeEncoderNative is not loaded'); - } - - $filesystem = memory_filesystem(); - $schema = schema(int_schema('id')); - $batches = [RowsMother::ids(1, 100_000), RowsMother::ids(100_001, 100_002)]; - $spy = new SpyHydrator(); - - $twoStep = FloeStreamReaderContext::writeBatches( - $filesystem, - path('memory://two-step.floe'), - $schema, - $batches, - hydrator: $spy, - ); - $fused = FloeStreamReaderContext::writeBatches($filesystem, path('memory://fused.floe'), $schema, $batches); - - static::assertSame($twoStep, $fused); - static::assertSame(2, $spy->dehydrateCalls); - static::assertCount(2, FloeStreamReaderContext::footer($filesystem, path('memory://fused.floe'))->sections); - } - - public function test_fused_write_is_byte_identical_to_the_two_step_write_around_an_empty_batch(): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with RustFloeEncoderNative is not loaded'); - } - - $filesystem = memory_filesystem(); - $numbered = RowsMother::numbered(5); - $batches = [rows($numbered->schema()), $numbered, rows($numbered->schema())]; - - static::assertSame( - FloeStreamReaderContext::writeBatches( - $filesystem, - path('memory://two-step.floe'), - $numbered->schema(), - $batches, - hydrator: new SpyHydrator(), - ), - FloeStreamReaderContext::writeBatches( - $filesystem, - path('memory://fused.floe'), - $numbered->schema(), - $batches, - ), - ); - } - - public function test_fused_write_is_byte_identical_to_the_two_step_write_for_a_batch_that_needs_match_to(): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with RustFloeEncoderNative is not loaded'); - } - - $filesystem = memory_filesystem(); - $session = RowsMother::numbered(1)->schema(); - $batches = [rows( - schema(datetime_schema('at'), int_schema('id')), - row(['at' => new DateTimeImmutable('2026-01-01 00:00:00'), 'id' => 1]), - )]; - - static::assertSame( - FloeStreamReaderContext::writeBatches( - $filesystem, - path('memory://two-step.floe'), - $session, - $batches, - hydrator: new SpyHydrator(), - ), - FloeStreamReaderContext::writeBatches($filesystem, path('memory://fused.floe'), $session, $batches), - ); - } - - public function test_native_engine_writes_a_transforming_codec_like_the_php_engine(): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with RustFloeEncoderNative is not loaded'); - } - - $filesystem = memory_filesystem(); - $options = new Options(codec: new PrefixingCodecStub()); - $numbered = RowsMother::numbered(10); - $batches = [$numbered, RowsMother::numbered(3)]; - - static::assertSame( - FloeStreamReaderContext::writeBatches( - $filesystem, - path('memory://php.floe'), - $numbered->schema(), - $batches, - $options, - engine: FloeEngine::php, - ), - FloeStreamReaderContext::writeBatches( - $filesystem, - path('memory://native.floe'), - $numbered->schema(), - $batches, - $options, - engine: FloeEngine::native, - ), - ); - } - - public function test_native_engine_writes_like_the_php_engine(): void - { - if (!NativeFloeEncoder::isSupported()) { - static::markTestSkipped('flow_php extension with RustFloeEncoderNative is not loaded'); - } - - $filesystem = memory_filesystem(); - $numbered = RowsMother::numbered(10); - $batches = [$numbered, RowsMother::numbered(3)]; - - static::assertSame( - FloeStreamReaderContext::writeBatches( - $filesystem, - path('memory://php.floe'), - $numbered->schema(), - $batches, - engine: FloeEngine::php, - ), - FloeStreamReaderContext::writeBatches( - $filesystem, - path('memory://native.floe'), - $numbered->schema(), - $batches, - engine: FloeEngine::native, - ), - ); - } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php index 4393d24d29..63c186c721 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php @@ -78,7 +78,7 @@ public function test_datetime_entries(): void 'mutable' => new DateTime('2025-06-15 12:30:45.654321', new DateTimeZone('America/New_York')), 'offset_timezone' => new DateTimeImmutable('2025-06-15 12:30:45', new DateTimeZone('+02:30')), 'before_epoch' => new DateTimeImmutable('1969-07-20 20:17:00 UTC'), - 'date' => new DateTimeImmutable('2025-06-15 00:00:00', new DateTimeZone('Europe/Warsaw')), + 'date' => new DateTimeImmutable('2025-06-15 00:00:00', new DateTimeZone('UTC')), ]), ), FloeStreamReaderContext::roundTrip($rows), diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/NativeFloeEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/NativeFloeEncoderTest.php deleted file mode 100644 index 83db5c9b0b..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/NativeFloeEncoderTest.php +++ /dev/null @@ -1,215 +0,0 @@ - 1, 'name' => 'flow'], [ - 'id' => type_integer(), - 'name' => type_string(), - ])]; - - static::assertSame( - (new PhpFloeEncoder($schema))->encode($encoded), - (new NativeFloeEncoder($schema))->encode($encoded), - ); - } - - public function test_native_decode_matches_the_php_engine(): void - { - $data = rows( - schema(int_schema('id'), str_schema('name', nullable: true)), - row(['id' => 1, 'name' => 'flow']), - row(['id' => 2, 'name' => null]), - ); - - $schema = schema_from_json(FloeSchemaContext::schemaBody($data->schema())); - $bodies = (new PhpFloeEncoder($schema))->encode((new PhpRowHydrator())->dehydrate($data)); - - static::assertEquals( - (new PhpFloeEncoder($schema))->decode($bodies), - (new NativeFloeEncoder($schema))->decode($bodies), - ); - } - - public function test_native_metadata_bearing_frames_match_the_php_engine(): void - { - $schema = schema_from_json(FloeSchemaContext::schemaBody(schema( - int_schema('id'), - str_schema('name', nullable: true), - ))); - - $encoded = [new TypedRowValues( - ['id' => 2, 'name' => null], - ['id' => type_integer(), 'name' => type_string()], - ['id' => Metadata::fromArray(['source' => 'trusted', 'weight' => 3])], - )]; - - $bodies = (new PhpFloeEncoder($schema))->encode($encoded); - - static::assertEquals( - (new PhpFloeEncoder($schema))->decode($bodies), - (new NativeFloeEncoder($schema))->decode($bodies), - ); - static::assertSame( - (new PhpFloeEncoder($schema))->encode($encoded), - (new NativeFloeEncoder($schema))->encode($encoded), - ); - } - - /** - * Flags, not instances: PHPUnit builds provider data before setUp() skips, and a native hydrator cannot be - * constructed without the extension. - * - * @return array - */ - public static function native_hydrators(): array - { - return [ - 'native' => [false], - 'adaptive' => [true], - ]; - } - - #[DataProvider('native_hydrators')] - public function test_decode_rows_matches_hydrate_of_decode(bool $adaptive): void - { - $data = rows( - schema(int_schema('id'), str_schema('name', nullable: true), datetime_schema('at')), - row([ - 'id' => 1, - 'name' => 'flow', - 'at' => new DateTimeImmutable('2026-01-01 10:00:00.5', new DateTimeZone('Europe/Warsaw')), - ]), - row(['id' => 2, 'name' => null, 'at' => new DateTimeImmutable('2026-01-02T00:00:00Z')]), - ); - $schema = schema_from_json(FloeSchemaContext::schemaBody($data->schema())); - $encoder = new NativeFloeEncoder($schema); - $bodies = $encoder->encode((new PhpRowHydrator())->dehydrate($data)); - - static::assertEquals( - (new NativeRowHydrator())->hydrate($encoder->decode($bodies), $schema), - $encoder->decodeRows($bodies, $schema, $adaptive ? new AdaptiveRowHydrator() : new NativeRowHydrator()), - ); - } - - public function test_decode_rows_hands_a_non_native_hydrator_the_decoded_values(): void - { - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); - $schema = schema_from_json(FloeSchemaContext::schemaBody($data->schema())); - $encoder = new NativeFloeEncoder($schema); - $bodies = $encoder->encode((new PhpRowHydrator())->dehydrate($data)); - $spy = new SpyHydrator(); - - static::assertEquals( - (new PhpRowHydrator())->hydrate($encoder->decode($bodies), $schema), - $encoder->decodeRows($bodies, $schema, $spy), - ); - static::assertSame(1, $spy->hydrateCalls); - } - - public function test_decode_rows_throws_the_schema_mismatch_the_hydrator_throws(): void - { - $data = rows(schema(int_schema('id')), row(['id' => 1])); - $schema = schema_from_json(FloeSchemaContext::schemaBody($data->schema())); - $encoder = new NativeFloeEncoder($schema); - $bodies = $encoder->encode((new PhpRowHydrator())->dehydrate($data)); - - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('column "name" (row 0) declared by the schema is missing from the row'); - - $encoder->decodeRows($bodies, schema(int_schema('id'), str_schema('name')), new NativeRowHydrator()); - } - - public function test_decode_rows_turns_a_corrupt_frame_into_a_floe_exception(): void - { - $data = rows(schema(int_schema('id')), row(['id' => 1])); - $schema = schema_from_json(FloeSchemaContext::schemaBody($data->schema())); - $encoder = new NativeFloeEncoder($schema); - $bodies = $encoder->encode((new PhpRowHydrator())->dehydrate($data)); - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('flow_php row frame length does not match its content'); - - $encoder->decodeRows([$bodies[0] . "\xEF"], $schema, new NativeRowHydrator()); - } - - #[DataProvider('native_hydrators')] - public function test_encode_frames_matches_framing_encode_of_dehydrate(bool $adaptive): void - { - $data = RowsMother::numbered(4); - $encoder = new NativeFloeEncoder($data->schema()); - - static::assertSame( - Format::rowFrames($encoder->encode((new PhpRowHydrator())->dehydrate($data))), - $encoder->encodeFrames($data, $adaptive ? new AdaptiveRowHydrator() : new NativeRowHydrator()), - ); - } - - public function test_encode_frames_hands_a_non_native_hydrator_the_rows(): void - { - $data = RowsMother::numbered(2); - $encoder = new NativeFloeEncoder($data->schema()); - $spy = new SpyHydrator(); - - static::assertSame( - Format::rowFrames($encoder->encode((new PhpRowHydrator())->dehydrate($data))), - $encoder->encodeFrames($data, $spy), - ); - static::assertSame(1, $spy->dehydrateCalls); - } - - public function test_encode_frames_turns_a_row_without_a_declared_column_into_a_floe_exception(): void - { - $schema = schema(int_schema('id'), str_schema('name')); - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('flow_php found a row that does not carry the declared column "name"'); - - (new NativeFloeEncoder($schema))->encodeFrames(Rows::trusted($schema, [row([ - 'id' => 1, - ])]), new NativeRowHydrator()); - } -} diff --git a/src/extension/flow-php-ext/README.md b/src/extension/flow-php-ext/README.md index e56869c4de..ca4c8fa1cd 100644 --- a/src/extension/flow-php-ext/README.md +++ b/src/extension/flow-php-ext/README.md @@ -1,10 +1,7 @@ # Extension: Flow PHP -A Rust-powered PHP extension using [ext-php-rs](https://github.com/extphprs/ext-php-rs) providing native -implementations for performance-critical parts of the Flow DataFrame framework: encoding and decoding of the -Floe binary format frames and row hydration/casting against a schema. The extension is optional — the pure-PHP -implementations in `flow-php/etl` are the canonical behavior reference, and Flow routes to the native ones -automatically when the extension is loaded. +A Rust-powered PHP extension using [ext-php-rs](https://github.com/extphprs/ext-php-rs) providing native CSV reading +and string-type narrowing; the pure-PHP implementations in `flow-php/etl` are the canonical behaviour reference. > [!IMPORTANT] > This repository is a subtree split from our monorepo. If you'd like to contribute, please visit our main monorepo [flow-php/flow](https://github.com/flow-php/flow). diff --git a/src/extension/flow-php-ext/tests/phpt/002_scalar_round_trip.phpt b/src/extension/flow-php-ext/tests/phpt/002_scalar_round_trip.phpt deleted file mode 100644 index 8f25bbdecf..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/002_scalar_round_trip.phpt +++ /dev/null @@ -1,47 +0,0 @@ ---TEST-- -scalar columns round-trip identically to the pure-PHP decoder ---SKIPIF-- - ---FILE-- - 0, 'name' => null, 'email' => "binary \x00 unsafe \n string", 'price' => 12345.678, 'active' => true, 'score' => -1000]), row(['id' => PHP_INT_MAX, 'name' => 'user_1', 'email' => '', 'price' => -0.5, 'active' => false, 'score' => PHP_INT_MIN])); - -$frames = php_frames($rows); -$actual = ext_decode_frames($frames); - -var_dump(count($actual) === 2); -assert_rows_identical(php_decode_frames($frames), $actual); - -var_dump($actual[0]->get('id')); -var_dump($actual[0]->get('name')); -var_dump($schema->get('name')->isNullable()); -var_dump($actual[0]->get('email') === "binary \x00 unsafe \n string"); -var_dump($schema->get('email')->isNullable()); -var_dump($actual[1]->get('id') === PHP_INT_MAX); -var_dump($actual[1]->get('score') === PHP_INT_MIN); -var_dump($actual[1]->get('price')); -var_dump($actual[1]->get('active')); -?> ---EXPECT-- -bool(true) -identical -int(0) -NULL -bool(true) -bool(true) -bool(false) -bool(true) -bool(true) -float(-0.5) -bool(false) diff --git a/src/extension/flow-php-ext/tests/phpt/003_null_flags.phpt b/src/extension/flow-php-ext/tests/phpt/003_null_flags.phpt deleted file mode 100644 index 24b6d2625f..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/003_null_flags.phpt +++ /dev/null @@ -1,42 +0,0 @@ ---TEST-- -null values and null-typed columns hydrate the matching definitions ---SKIPIF-- - ---FILE-- - 1, 'nullable' => null, 'null_typed' => null, 'present' => 'value'])); - -$frames = php_frames($rows); -$actual = ext_decode_frames($frames); - -assert_rows_identical(php_decode_frames($frames), $actual); - -var_dump($actual[0]->get('nullable')); -var_dump($schema->get('nullable')->isNullable()); -var_dump($schema->get('nullable')->type()->toString()); -var_dump($actual[0]->get('null_typed')); -var_dump($schema->get('null_typed')->isNullable()); -var_dump($schema->get('null_typed')->type()->toString()); -var_dump($schema->get('present')->isNullable()); -var_dump($schema->get('present')->type()->toString()); -?> ---EXPECT-- -identical -NULL -bool(true) -string(6) "string" -NULL -bool(true) -string(4) "null" -bool(false) -string(6) "string" diff --git a/src/extension/flow-php-ext/tests/phpt/004_datetime.phpt b/src/extension/flow-php-ext/tests/phpt/004_datetime.phpt deleted file mode 100644 index 9e35377fed..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/004_datetime.phpt +++ /dev/null @@ -1,56 +0,0 @@ ---TEST-- -datetime columns: a mutable input normalises to immutable, non-UTC timezone, microseconds ---SKIPIF-- - ---FILE-- - 1, - 'immutable' => new DateTimeImmutable('2025-01-01 12:00:00.123456', new DateTimeZone('Europe/Warsaw')), - // the class is not stored: a datetime column always hydrates to DateTimeImmutable, so a - // DateTime written here comes back immutable, carrying the same instant and timezone - 'mutable' => new DateTime('1969-12-31 23:59:59.999999', new DateTimeZone('America/New_York')), - 'nullable' => null, - // regression: timelib's trailing-data check reads the byte after the - // parsed input - pre-1970 fractional epochs exposed a missing NUL - // terminator in the extension's date construction - 'before_epoch' => new DateTimeImmutable('1969-07-20 20:17:00.5', new DateTimeZone('Europe/Warsaw')), - ]), -); - -$frames = php_frames($rows); -$actual = ext_decode_frames($frames); - -assert_rows_identical(php_decode_frames($frames), $actual); - -var_dump(get_class($actual[0]->get('immutable'))); -var_dump($actual[0]->get('immutable')->format('Y-m-d H:i:s.u e')); -var_dump(get_class($actual[0]->get('mutable'))); -var_dump($actual[0]->get('mutable')->format('Y-m-d H:i:s.u e')); -var_dump($actual[0]->get('nullable')); -var_dump($actual[0]->get('before_epoch')->format('Y-m-d H:i:s.u e')); -?> ---EXPECT-- -identical -string(17) "DateTimeImmutable" -string(40) "2025-01-01 12:00:00.123456 Europe/Warsaw" -string(17) "DateTimeImmutable" -string(43) "1969-12-31 23:59:59.999999 America/New_York" -NULL -string(40) "1969-07-20 20:17:00.500000 Europe/Warsaw" diff --git a/src/extension/flow-php-ext/tests/phpt/005_time_uuid.phpt b/src/extension/flow-php-ext/tests/phpt/005_time_uuid.phpt deleted file mode 100644 index e132827faa..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/005_time_uuid.phpt +++ /dev/null @@ -1,57 +0,0 @@ ---TEST-- -time (DateInterval) and uuid columns round-trip identically ---SKIPIF-- - ---FILE-- -diff(new DateTimeImmutable('2025-01-01')); -$fractional = new DateInterval('PT1S'); -$fractional->f = 0.123456; - -$rows = rows( - schema( - int_schema('id'), - time_schema('duration'), - time_schema('negative'), - time_schema('fractional'), - uuid_schema('uuid'), - ), - row([ - 'id' => 1, - 'duration' => new DateInterval('P3DT4H5M6S'), - 'negative' => $negative, - 'fractional' => $fractional, - 'uuid' => type_uuid()->cast('01234567-89ab-4def-8123-456789abcdef'), - ]), -); - -$frames = php_frames($rows); -$actual = ext_decode_frames($frames); - -assert_rows_identical(php_decode_frames($frames), $actual); - -$duration = $actual[0]->get('duration'); -var_dump($duration->d, $duration->h, $duration->i, $duration->s); -var_dump($actual[0]->get('negative')->invert); -var_dump($actual[0]->get('fractional')->f); -var_dump((string) $actual[0]->get('uuid')); -?> ---EXPECT-- -identical -int(3) -int(4) -int(5) -int(6) -int(1) -float(0.123456) -string(36) "01234567-89ab-4def-8123-456789abcdef" diff --git a/src/extension/flow-php-ext/tests/phpt/006_schema_change_mid_stream.phpt b/src/extension/flow-php-ext/tests/phpt/006_schema_change_mid_stream.phpt deleted file mode 100644 index 4bfe227998..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/006_schema_change_mid_stream.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -heterogeneous Rows conform to one union schema (columns follow union order) ---SKIPIF-- - ---FILE-- - 1, 'name' => 'a']), row(['id' => 2, 'name' => 'b']), row(['id' => 3, 'price' => 1.5]), row(['name' => 'c', 'id' => 4])); - -$frames = php_frames($rows); -$actual = ext_decode_frames($frames); - -var_dump(count($actual)); -assert_rows_identical(php_decode_frames($frames), $actual); - -var_dump($actual[2]->get('price')); -// row written as (name, id) comes back in the single union schema's column order -var_dump(implode(',', $actual[3]->names())); -?> ---EXPECT-- -int(4) -identical -float(1.5) -string(13) "id,name,price" diff --git a/src/extension/flow-php-ext/tests/phpt/007_empty_rows.phpt b/src/extension/flow-php-ext/tests/phpt/007_empty_rows.phpt deleted file mode 100644 index 6f06ab18b4..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/007_empty_rows.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -empty Rows produce no frame bodies and decode to an empty row list ---SKIPIF-- - ---FILE-- - ---EXPECT-- -bool(true) -int(0) -identical diff --git a/src/extension/flow-php-ext/tests/phpt/010_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/010_no_leaks.phpt deleted file mode 100644 index 72210fa2a4..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/010_no_leaks.phpt +++ /dev/null @@ -1,114 +0,0 @@ ---TEST-- -repeated frame-body encode and decode do not leak memory ---SKIPIF-- - ---FILE-- - type_integer(), 'tags' => type_list(type_string())])), - xml_schema('doc'), - json_schema('json'), -); - -$build = static function (int $i): Flow\ETL\Row { - return row([ - 'id' => $i, - 'name' => $i % 10 === 0 ? null : 'user_' . $i, - 'price' => $i / 100.0, - 'active' => $i % 3 === 0, - 'created_at' => new DateTimeImmutable('2025-01-01 00:00:00.123456', new DateTimeZone('Europe/Warsaw')), - 'duration' => new DateInterval('PT1H2M3S'), - 'uuid' => type_uuid()->cast('01234567-89ab-4def-8123-456789abcdef'), - 'metrics' => ['cpu' => 0.5, 'mem' => 0.25], - 'nested' => ['a' => $i, 'tags' => ['x']], - 'doc' => type_xml()->cast('' . $i . ''), - 'json' => type_json()->cast([$i, ['a' => true]]), - ]); -}; - -$sourceRows = array_map($build, range(1, 100)); -$frames = php_frames(rows($schema, ...$sourceRows)); - -$schemaBody = null; -$rowBodies = []; - -foreach ($frames as $frame) { - if ($frame['type'] === SCHEMA_ENTRY) { - $schemaBody = $frame['body']; - } else { - $rowBodies[] = $frame['body']; - } -} - -$decodeSchema = schema_from_json($schemaBody); - -$cycle = static function () use ($schemaBody, $decodeSchema, $rowBodies, $schema, $sourceRows): void { - $decoder = new RustFloeEncoderNative(); - $hydrator = new PhpRowHydrator(); - $hydrator->hydrate($decoder->decode($rowBodies, $schemaBody), $decodeSchema); - - foreach ($rowBodies as $body) { - $hydrator->hydrate($decoder->decode([$body], $schemaBody), $decodeSchema); - } - - $encoder = new RustFloeEncoderNative(); - $encoder->encode($hydrator->dehydrate(new Rows($schema, ...$sourceRows)), $schemaBody, $schema); -}; - -for ($i = 0; $i < 10; $i++) { - $cycle(); -} -gc_collect_cycles(); -// memory_get_usage(false) counts emalloc'd bytes exactly - any per-call leak -// (even one zval) shows up here; (true) only tracks arena chunks and grows -// from GC-buffer expansion without any leak. -$baseline = memory_get_usage(false); - -for ($i = 0; $i < 100; $i++) { - $cycle(); -} -gc_collect_cycles(); - -var_dump(memory_get_usage(false) <= $baseline); -?> ---EXPECT-- -bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/011_containers.phpt b/src/extension/flow-php-ext/tests/phpt/011_containers.phpt deleted file mode 100644 index 68e7515d57..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/011_containers.phpt +++ /dev/null @@ -1,93 +0,0 @@ ---TEST-- -list, map and structure columns round-trip identically to the pure-PHP decoder ---SKIPIF-- - ---FILE-- - type_string(), - 'geo' => type_structure(['lat' => type_float(), 'lon' => type_float()]), - 'tags' => type_list(type_string()), - ])), structure_schema('optional_absent', type_structure(['a' => type_integer(), 'b' => structure_element('b', type_string(), optional: true)])), structure_schema('optional_typed_null', type_structure(['a' => type_integer(), 'b' => type_optional(type_string())])), structure_schema('interleaved', type_structure(['z' => type_integer(), 'a' => structure_element('a', type_string(), optional: true), 'b' => type_string()]))), row(['id' => 1, 'ints' => [1, -2, PHP_INT_MAX], 'floats' => [1.5, -0.25], 'strings' => ['a', '', "b\x00c"], 'empty' => [], 'nullable_ints' => [1, null, 3], 'by_int' => [10 => 'a', -5 => 'b'], 'by_string' => ['cpu' => 1.5, 'mem' => 2.5], 'empty_map' => [], 'address' => [ - 'street' => 'Main 7', - 'geo' => ['lat' => 1.5, 'lon' => -2.5], - 'tags' => ['x', 'y'], - ], 'optional_absent' => ['a' => 1], 'optional_typed_null' => ['a' => 1, 'b' => null], 'interleaved' => ['z' => 1, 'b' => 'x']])); - -$frames = php_frames($rows); -$actual = ext_decode_frames($frames); - -assert_rows_identical(php_decode_frames($frames), $actual); - -var_dump($actual[0]->get('ints')); -var_dump($actual[0]->get('nullable_ints')); -var_dump($actual[0]->get('by_int')); -var_dump($actual[0]->get('address')['geo']); -var_dump($actual[0]->get('optional_absent')); -var_dump($actual[0]->get('optional_typed_null')); -var_dump($actual[0]->get('interleaved')); -?> ---EXPECT-- -identical -array(3) { - [0]=> - int(1) - [1]=> - int(-2) - [2]=> - int(9223372036854775807) -} -array(3) { - [0]=> - int(1) - [1]=> - NULL - [2]=> - int(3) -} -array(2) { - [10]=> - string(1) "a" - [-5]=> - string(1) "b" -} -array(2) { - ["lat"]=> - float(1.5) - ["lon"]=> - float(-2.5) -} -array(1) { - ["a"]=> - int(1) -} -array(2) { - ["a"]=> - int(1) - ["b"]=> - NULL -} -array(2) { - ["z"]=> - int(1) - ["b"]=> - string(1) "x" -} diff --git a/src/extension/flow-php-ext/tests/phpt/012_enum_json_date.phpt b/src/extension/flow-php-ext/tests/phpt/012_enum_json_date.phpt deleted file mode 100644 index fe6ab9477a..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/012_enum_json_date.phpt +++ /dev/null @@ -1,67 +0,0 @@ ---TEST-- -enum, json and date columns round-trip identically ---SKIPIF-- - ---FILE-- - 1, - 'backed' => PhptSuit::Hearts, - 'pure' => PhptDirection::Down, - 'json_array' => Json::fromArray([1, 2, ['a' => true]]), - 'json_object' => Json::fromArray(['name' => 'flow', 'nested' => ['x' => 1]], asObject: true), - 'date' => new DateTimeImmutable('2025-03-01'), - ]), -); - -$frames = php_frames($rows); -$actual = ext_decode_frames($frames); - -assert_rows_identical(php_decode_frames($frames), $actual); - -var_dump($actual[0]->get('backed') === PhptSuit::Hearts); -var_dump($actual[0]->get('pure') === PhptDirection::Down); -var_dump((string) $actual[0]->get('json_array')); -var_dump((string) $actual[0]->get('json_object')); -var_dump($actual[0]->get('date')->format('Y-m-d')); -?> ---EXPECT-- -identical -bool(true) -bool(true) -string(16) "[1,2,{"a":true}]" -string(32) "{"name":"flow","nested":{"x":1}}" -string(10) "2025-03-01" diff --git a/src/extension/flow-php-ext/tests/phpt/013_xml_fallback.phpt b/src/extension/flow-php-ext/tests/phpt/013_xml_fallback.phpt deleted file mode 100644 index 2c051779a1..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/013_xml_fallback.phpt +++ /dev/null @@ -1,42 +0,0 @@ ---TEST-- -xml and xml_element columns decode through the ValueDecoder static fallback ---SKIPIF-- - ---FILE-- -loadXML('ab'); - -$element = (new DOMDocument()); -$element->loadXML('value'); - -$schema = schema(int_schema('id'), xml_schema('doc'), xml_element_schema('el')); - -$frames = php_frames(rows($schema, row(['id' => 1, 'doc' => $document, 'el' => $element->documentElement]))); -$actual = ext_decode_frames($frames); - -// DOM values are not serializable on their own, so the decoded rows are compared -// through their re-encoded frame bodies instead of through serialize(). -var_dump(php_frames(rows($schema, ...$actual)) === php_frames(rows($schema, ...php_decode_frames($frames)))); - -var_dump(get_class($actual[0]->get('doc'))); -var_dump(trim($actual[0]->get('doc')->saveXML())); -var_dump(get_class($actual[0]->get('el'))); -var_dump($actual[0]->get('el')->getAttribute('id')); -?> ---EXPECT-- -bool(true) -string(11) "DOMDocument" -string(72) " -ab" -string(10) "DOMElement" -string(1) "7" diff --git a/src/extension/flow-php-ext/tests/phpt/016_numeric_string_keys.phpt b/src/extension/flow-php-ext/tests/phpt/016_numeric_string_keys.phpt deleted file mode 100644 index 32059879c6..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/016_numeric_string_keys.phpt +++ /dev/null @@ -1,70 +0,0 @@ ---TEST-- -array-key semantics: numeric column names coerce, non-canonical keys stay strings ---SKIPIF-- - ---FILE-- - 1, '7' => 'numeric column name', 'keys' => [ - '05' => 'leading-zero', - '5x' => 'suffix', - '-0' => 'minus-zero', - '9223372036854775808' => 'overflow', - ]])); - -$frames = php_frames($rows); -$actual = ext_decode_frames($frames); - -assert_rows_identical(php_decode_frames($frames), $actual); - -var_dump(array_map(fn($k) => gettype($k) . ':' . $k, array_keys($actual[0]->get('keys')))); -var_dump($actual[0]->get('7')); -// storage cannot hold '7' as a string key, so the decoded row must carry an int key - -// this is the parity window: the Rust decoder has to coerce exactly as PHP does -var_dump(array_keys($actual[0]->values())); -// names() inverts that coercion, because the column name is the entry's identity -var_dump($actual[0]->names()); -?> ---EXPECT-- -identical -array(4) { - [0]=> - string(9) "string:05" - [1]=> - string(9) "string:5x" - [2]=> - string(9) "string:-0" - [3]=> - string(26) "string:9223372036854775808" -} -string(19) "numeric column name" -array(3) { - [0]=> - string(2) "id" - [1]=> - int(7) - [2]=> - string(4) "keys" -} -array(3) { - [0]=> - string(2) "id" - [1]=> - string(1) "7" - [2]=> - string(4) "keys" -} \ No newline at end of file diff --git a/src/extension/flow-php-ext/tests/phpt/017_rows_decoder.phpt b/src/extension/flow-php-ext/tests/phpt/017_rows_decoder.phpt deleted file mode 100644 index 01d5828301..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/017_rows_decoder.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -RowValues pipeline decodes streamed frame bodies identically to the pure-PHP pipeline ---SKIPIF-- - ---FILE-- - 1, 'name' => 'a']), row(['id' => 2, 'name' => null]), row(['id' => 3, 'price' => 1.5]), row(['id' => 4, 'at' => new DateTimeImmutable('2025-01-01 00:00:00.123456', new DateTimeZone('Europe/Warsaw'))])); - -$frames = php_frames($rows); -$decoded = ext_decode_frames($frames); - -var_dump(count($decoded)); - -assert_rows_identical(php_decode_frames($frames), $decoded); - -$schemaBody = null; -$rowBody = null; - -foreach ($frames as $frame) { - if ($frame['type'] === SCHEMA_ENTRY) { - if ($schemaBody === null) { - $schemaBody = $frame['body']; - } - } elseif ($rowBody === null && $schemaBody !== null) { - $rowBody = $frame['body']; - } -} - -try { - (new RustFloeEncoderNative())->decode([$rowBody . "\xEF"], $schemaBody); - echo "FAIL: no exception\n"; -} catch (Flow\Floe\Exception\ExtensionException $e) { - echo $e->getMessage(), "\n"; -} -?> ---EXPECT-- -int(4) -identical -flow_php row frame length does not match its content diff --git a/src/extension/flow-php-ext/tests/phpt/019_html_fallback.phpt b/src/extension/flow-php-ext/tests/phpt/019_html_fallback.phpt deleted file mode 100644 index c43743dcd2..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/019_html_fallback.phpt +++ /dev/null @@ -1,40 +0,0 @@ ---TEST-- -html and html_element columns decode through the ValueDecoder static fallback (PHP 8.4+) ---SKIPIF-- - ---FILE-- - 1, - 'doc' => type_html()->cast('

hello

'), - 'el' => type_html_element()->cast('
content
'), -]))); -$actual = ext_decode_frames($frames); - -var_dump(php_frames(rows($schema, ...$actual)) === php_frames(rows($schema, ...php_decode_frames($frames)))); - -var_dump(get_class($actual[0]->get('doc'))); -var_dump($actual[0]->get('doc')->getElementById('x')->textContent); -var_dump($actual[0]->get('el')->getAttribute('class')); -?> ---EXPECT-- -bool(true) -string(16) "Dom\HTMLDocument" -string(5) "hello" -string(1) "c" diff --git a/src/extension/flow-php-ext/tests/phpt/020_row_encoder_parity.phpt b/src/extension/flow-php-ext/tests/phpt/020_row_encoder_parity.phpt deleted file mode 100644 index 81c1fcd939..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/020_row_encoder_parity.phpt +++ /dev/null @@ -1,102 +0,0 @@ ---TEST-- -RustFloeEncoderNative produces ROW frame bodies byte-identical to PhpFloeEncoder ---SKIPIF-- - ---FILE-- - rows(schema(int_schema('id'), str_schema('name', nullable: true), str_schema('e'), float_schema('p'), bool_schema('a'), int_schema('s')), row(['id' => 1, 'name' => null, 'e' => "b\x00in", 'p' => -1.5, 'a' => true, 's' => PHP_INT_MIN]), row(['id' => 2, 'name' => 'x', 'e' => '', 'p' => 0.25, 'a' => false, 's' => PHP_INT_MAX])), - 'from_null' => rows(schema(int_schema('id'), null_schema('n')), row(['id' => 1, 'n' => null])), - 'datetime' => rows(schema(datetime_schema('at'), date_schema('d'), time_schema('t'), uuid_schema('u')), row(['at' => new DateTimeImmutable('2025-01-01 12:00:00.123456', new DateTimeZone('Europe/Warsaw')), 'd' => new DateTimeImmutable('2025-03-01'), 't' => new DateInterval('PT2H30M5S'), 'u' => type_uuid()->cast('01234567-89ab-4def-8123-456789abcdef')])), - 'containers' => rows(schema(list_schema('ints', type_list(type_integer())), map_schema('m', type_map(type_string(), type_float())), map_schema('mi', type_map(type_integer(), type_string())), structure_schema('st', type_structure(['a' => type_integer(), 'b' => structure_element('b', type_string(), optional: true)])), structure_schema('st_interleaved', type_structure(['z' => type_integer(), 'a' => structure_element('a', type_string(), optional: true), 'b' => type_string()])), list_schema('opt', type_list(type_optional(type_integer())))), row(['ints' => [1, 2, 3], 'm' => ['cpu' => 1.5], 'mi' => [7 => 'a', -1 => 'b'], 'st' => ['a' => 1], 'st_interleaved' => ['z' => 1, 'b' => 'x'], 'opt' => [1, null]])), - 'enum_json_xml' => rows(schema(enum_schema('en', PhptColor::class), json_schema('j'), xml_schema('x')), row(['en' => PhptColor::Red, 'j' => type_json()->cast(['a' => 1]), 'x' => type_xml()->cast('v')])), - 'heterogeneous' => rows(schema(int_schema('id'), str_schema('n', nullable: true)), row(['id' => 1]), row(['id' => 2, 'n' => 'x']), row(['n' => 'y', 'id' => 3])), - 'two_columns' => rows(schema(int_schema('id'), str_schema('g')), row(['id' => 1, 'g' => 'a'])), - 'empty' => rows(schema()), -]; - -foreach ($datasets as $label => $data) { - printf("%-14s frames-identical:%s\n", $label, php_frames($data) === ext_frames($data) ? 'yes' : 'NO'); -} - -// A row that does not carry a column the plan declares is a broken contract, not a -// value the format can express: VALUE_ABSENT (0x03) is a structure-element flag only. -// Both encoders must refuse it. -$wideBody = json_encode(schema(int_schema('a'), str_schema('b'), float_schema('c'))->normalize(), JSON_THROW_ON_ERROR); - -$hydrator = new PhpRowHydrator(); -$narrowTyped = $hydrator->dehydrate(new Rows(schema(int_schema('a'), float_schema('c')), row(['a' => 7, 'c' => 2.5]))); - -$php = new PhpFloeEncoder(schema_from_json($wideBody)); -$ext = new RustFloeEncoderNative(); - -foreach (['php' => fn() => $php->encode($narrowTyped), 'ext' => fn() => $ext->encode($narrowTyped, $wideBody, schema_from_json($wideBody))] as $side => $encode) { - try { - $encode(); - printf("%-14s %s\n", 'absent-' . $side, 'NO EXCEPTION'); - } catch (Throwable $e) { - printf("%-14s %s\n", 'absent-' . $side, $e->getMessage()); - } -} - -$badSchema = schema(list_schema('bad', type_list(type_mixed()))); -$badTyped = $hydrator->dehydrate(new Rows($badSchema, row(['bad' => [new SplStack()]]))); -$badExt = new RustFloeEncoderNative(); -expect_exception(fn() => $badExt->encode($badTyped, json_encode($badSchema->normalize(), JSON_THROW_ON_ERROR), $badSchema)); -?> ---EXPECT-- -scalar frames-identical:yes -from_null frames-identical:yes -datetime frames-identical:yes -containers frames-identical:yes -enum_json_xml frames-identical:yes -heterogeneous frames-identical:yes -two_columns frames-identical:yes -empty frames-identical:yes -absent-php Floe found a row that does not carry the declared column "b" -absent-ext flow_php found a row that does not carry the declared column "b" -Flow\Floe\Exception\ExtensionException: flow_php does not support values of type "mixed" in this build diff --git a/src/extension/flow-php-ext/tests/phpt/021_batched_decode.phpt b/src/extension/flow-php-ext/tests/phpt/021_batched_decode.phpt deleted file mode 100644 index bfbc368da9..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/021_batched_decode.phpt +++ /dev/null @@ -1,79 +0,0 @@ ---TEST-- -RustFloeEncoderNative + RowHydrator decode a batch identically to the pure-PHP pipeline ---SKIPIF-- - ---FILE-- - row(['id' => $i, 'name' => $i % 7 === 0 ? null : 'user_' . $i, 'price' => $i / 4.0]); - -$rows = rows( - schema(int_schema('id'), str_schema('name', nullable: true), float_schema('price')), - ...array_map($build, range(1, 500)), -); -$frames = php_frames($rows); - -$schemaBody = null; -$rowBodies = []; - -foreach ($frames as $frame) { - if ($frame['type'] === SCHEMA_ENTRY) { - $schemaBody = $frame['body']; - } else { - $rowBodies[] = $frame['body']; - } -} - -var_dump(count($rowBodies)); - -$decoder = new RustFloeEncoderNative(); -$hydrator = new PhpRowHydrator(); -$schema = schema_from_json($schemaBody); - -$decodedValues = $decoder->decode($rowBodies, $schemaBody); -var_dump($decodedValues[0] instanceof RawRowValues); - -$batched = $hydrator->hydrate($decodedValues, $schema); -var_dump($batched instanceof Rows); -var_dump($batched->count()); - -$php = php_decode_frames($frames); -$batchedRows = $batched->all(); - -$identical = true; - -foreach ($php as $i => $expected) { - if (serialize($expected) !== serialize($batchedRows[$i])) { - $identical = false; - echo "FAIL: batched row {$i} differs\n"; - } -} - -var_dump($identical); - -$empty = $hydrator->hydrate($decoder->decode([], $schemaBody), $schema); -var_dump($empty instanceof Rows); -var_dump($empty->count()); -?> ---EXPECT-- -int(500) -bool(true) -bool(true) -int(500) -bool(true) -bool(true) -int(0) diff --git a/src/extension/flow-php-ext/tests/phpt/022_row_encoder_round_trip.phpt b/src/extension/flow-php-ext/tests/phpt/022_row_encoder_round_trip.phpt deleted file mode 100644 index 52b3c9d17b..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/022_row_encoder_round_trip.phpt +++ /dev/null @@ -1,79 +0,0 @@ ---TEST-- -RustFloeEncoderNative frame bodies round-trip through the RawRowValues pipeline ---SKIPIF-- - ---FILE-- - 1, 'name' => 'a', 'price' => 1.5, 'at' => new DateTimeImmutable('2025-01-01 10:00:00.5', new DateTimeZone('UTC')), 'u' => type_uuid()->cast('01234567-89ab-4def-8123-456789abcdef'), 'nums' => [1, 2, 3]]), - row(['id' => 2, 'name' => null, 'price' => -0.25, 'at' => new DateTimeImmutable('1999-12-31 23:59:59.999999', new DateTimeZone('Europe/Warsaw')), 'u' => type_uuid()->cast('abcdef01-2345-4678-9abc-def012345678'), 'nums' => []]), - row(['id' => 3, 'name' => 'c', 'price' => 99.0, 'at' => new DateTimeImmutable('2030-06-15 08:30:00', new DateTimeZone('America/New_York')), 'u' => type_uuid()->cast('11111111-2222-4333-8444-555566667777'), 'nums' => [-1, 0, PHP_INT_MAX]]), -]; - -$schemaBody = json_encode($schema->normalize(), JSON_THROW_ON_ERROR); -$hydrator = new PhpRowHydrator(); - -$encoder = new RustFloeEncoderNative(); -$bodies = $encoder->encode($hydrator->dehydrate(new Rows($schema, ...$sourceRows)), $schemaBody, $schema); - -$decoded = $hydrator->hydrate((new RustFloeEncoderNative())->decode($bodies, $schemaBody), schema_from_json($schemaBody)); - -var_dump($decoded instanceof Rows); -var_dump($decoded->count()); - -$reEncoder = new RustFloeEncoderNative(); -$reBodies = $reEncoder->encode($hydrator->dehydrate($decoded), $schemaBody, $schema); -var_dump($bodies === $reBodies); - -$frames = array_merge( - [['type' => SCHEMA_ENTRY, 'body' => $schemaBody]], - array_map(fn($body) => ['type' => Format::FRAME_ROW, 'body' => $body], $bodies), -); -assert_rows_identical(php_decode_frames($frames), $decoded->all()); - -var_dump($decoded->all()[1]->get('name')); -var_dump($decoded->all()[2]->get('nums')); -?> ---EXPECT-- -bool(true) -int(3) -bool(true) -identical -NULL -array(3) { - [0]=> - int(-1) - [1]=> - int(0) - [2]=> - int(9223372036854775807) -} diff --git a/src/extension/flow-php-ext/tests/phpt/023_encoder_datetime_subclass.phpt b/src/extension/flow-php-ext/tests/phpt/023_encoder_datetime_subclass.phpt deleted file mode 100644 index 663c2c60c4..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/023_encoder_datetime_subclass.phpt +++ /dev/null @@ -1,31 +0,0 @@ ---TEST-- -RustFloeEncoderNative rejects DateTime subclasses with the Floe parity error ---SKIPIF-- - ---FILE-- -dehydrate( - new Rows($schema, row(['custom' => new PhptCustomDateTime('2020-05-05 10:20:30.000042', new DateTimeZone('Europe/Warsaw'))])), -); - -$encoder = new RustFloeEncoderNative(); - -expect_exception(fn() => $encoder->encode($typed, json_encode($schema->normalize(), JSON_THROW_ON_ERROR), $schema)); -?> ---EXPECT-- -Flow\Floe\Exception\ExtensionException: Floe supports only DateTime and DateTimeImmutable, got PhptCustomDateTime - convert custom datetime instances before writing diff --git a/src/extension/flow-php-ext/tests/phpt/024_row_hydrator_parity.phpt b/src/extension/flow-php-ext/tests/phpt/024_row_hydrator_parity.phpt deleted file mode 100644 index 13d29787ec..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/024_row_hydrator_parity.phpt +++ /dev/null @@ -1,137 +0,0 @@ ---TEST-- -NativeRowHydrator hydrate/dehydrate are serialize-identical to PhpRowHydrator ---SKIPIF-- - ---FILE-- - [ - schema(int_schema('id'), str_schema('name', nullable: true), float_schema('p'), bool_schema('a')), - [ - new RawRowValues(['id' => 1, 'name' => 'x', 'p' => 1.5, 'a' => true]), - new RawRowValues(['id' => 2, 'name' => null, 'p' => -0.25, 'a' => false]), - ], - ], - 'null_nonnullable' => [ - schema(int_schema('id'), str_schema('name', nullable: true)), - [new RawRowValues(['id' => 1, 'name' => null]), new RawRowValues(['id' => 2, 'name' => null])], - ], - 'absent' => [ - schema(int_schema('id'), str_schema('name', nullable: true)), - [new RawRowValues(['id' => 1]), new RawRowValues(['id' => 2, 'name' => 'y'])], - ], - 'metadata' => [ - schema(int_schema('id')), - [ - new RawRowValues(['id' => 1], ['id' => Metadata::fromArray(['k' => 'v1'])]), - new RawRowValues(['id' => 2], ['id' => Metadata::fromArray(['k' => 'v2'])]), - ], - ], - 'numeric_name_metadata' => [ - schema(int_schema('7'), int_schema('id')), - [new RawRowValues(['7' => 1, 'id' => 1], ['7' => Metadata::fromArray(['k' => 'v']), 'id' => Metadata::fromArray(['n' => 1])])], - ], - 'temporal' => [ - schema(datetime_schema('at'), date_schema('d'), time_schema('t'), uuid_schema('u')), - [new RawRowValues([ - 'at' => new DateTimeImmutable('2025-01-01 12:00:00.123456', new DateTimeZone('Europe/Warsaw')), - 'd' => new DateTimeImmutable('2025-03-01'), - 't' => new DateInterval('PT2H30M5S'), - 'u' => new Flow\Types\Value\Uuid('01234567-89ab-4def-8123-456789abcdef'), - ])], - ], - 'containers' => [ - schema( - list_schema('l', type_list(type_integer())), - map_schema('m', type_map(type_string(), type_integer())), - structure_schema('st', type_structure(['a' => type_integer(), 'b' => structure_element('b', type_string(), optional: true)], true)), - list_schema('opt', type_list(type_optional(type_integer()))), - json_schema('j'), - ), - [new RawRowValues([ - 'l' => [1, 2, 3], - 'm' => ['a' => 1], - 'st' => ['a' => 1, 'extra' => 'kept'], - 'opt' => [1, null], - 'j' => Flow\Types\Value\Json::fromArray(['x' => 1]), - ])], - ], - 'enum_and_null' => [ - schema(enum_schema('s', PhptSuit::class, nullable: true), null_schema('n')), - [new RawRowValues(['s' => PhptSuit::Hearts, 'n' => null]), new RawRowValues(['s' => null, 'n' => null])], - ], - 'empty' => [schema(int_schema('id')), []], -]; - -$php = new PhpRowHydrator(); -$native = new NativeRowHydrator(); - -foreach ($datasets as $label => [$s, $batch]) { - $hydrateOk = serialize($php->hydrate($batch, $s)) === serialize($native->hydrate($batch, $s)); - $rows = $php->hydrate($batch, $s); - $dehydrateOk = serialize($php->dehydrate($rows)) === serialize($native->dehydrate($rows)); - printf("%-16s hydrate:%s dehydrate:%s\n", $label, $hydrateOk ? 'yes' : 'NO', $dehydrateOk ? 'yes' : 'NO'); -} - -$mutated = schema(int_schema('id')); -$php->hydrate([new RawRowValues(['id' => 1])], $mutated); -$native->hydrate([new RawRowValues(['id' => 1])], $mutated); -$mutated->add(str_schema('name', nullable: true))->makeNullable(); -// Schema is immutable, so $mutated never gained "name" - the column is simply not hydrated -$batch = [new RawRowValues(['id' => 1, 'name' => 'x'])]; -printf( - "%-16s hydrate:%s\n", - 'schema_mutation', - serialize($php->hydrate($batch, $mutated)) === serialize($native->hydrate($batch, $mutated)) ? 'yes' : 'NO', -); - -printf("native class registered:%s\n", class_exists(RustRowHydratorNative::class, false) ? 'yes' : 'NO'); -?> ---EXPECT-- -scalars hydrate:yes dehydrate:yes -null_nonnullable hydrate:yes dehydrate:yes -absent hydrate:yes dehydrate:yes -metadata hydrate:yes dehydrate:yes -numeric_name_metadata hydrate:yes dehydrate:yes -temporal hydrate:yes dehydrate:yes -containers hydrate:yes dehydrate:yes -enum_and_null hydrate:yes dehydrate:yes -empty hydrate:yes dehydrate:yes -schema_mutation hydrate:yes -native class registered:yes diff --git a/src/extension/flow-php-ext/tests/phpt/025_hydrator_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/025_hydrator_no_leaks.phpt deleted file mode 100644 index 3079feea9f..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/025_hydrator_no_leaks.phpt +++ /dev/null @@ -1,92 +0,0 @@ ---TEST-- -repeated native hydrate and dehydrate do not leak memory ---SKIPIF-- - ---FILE-- - type_integer(), 'tags' => type_list(type_string())])), - json_schema('json'), -); - -$batch = []; - -for ($i = 1; $i <= 100; $i++) { - $batch[] = new RawRowValues( - [ - 'id' => $i, - 'name' => $i % 10 === 0 ? null : 'user_' . $i, // null values under a nullable declaration - 'price' => (float) $i / 100, - 'active' => $i % 3 === 0, - 'created_at' => new DateTimeImmutable('2025-01-01 00:00:00.123456', new DateTimeZone('Europe/Warsaw')), - 'duration' => new DateInterval('PT1H2M3S'), - 'uuid' => new Flow\Types\Value\Uuid('01234567-89ab-4def-8123-456789abcdef'), - 'mixed' => [$i, 'x', null, ['k' => 1.5]], - 'metrics' => ['cpu' => 0.5, 'mem' => 0.25], - 'nested' => ['a' => $i, 'tags' => ['x']], - 'json' => Flow\Types\Value\Json::fromArray([$i, ['a' => true]]), - ], - $i % 5 === 0 ? ['id' => Metadata::fromArray(['batch' => $i])] : [], // exercises the clone + setMetadata path - ); -} - -$phpRows = (new PhpRowHydrator())->hydrate($batch, $schema); - -$cycle = static function () use ($batch, $schema, $phpRows): void { - $native = new RustRowHydratorNative(); - $rows = $native->hydrate($batch, $schema); - $native->dehydrate($rows); - $native->dehydrate($phpRows); -}; - -for ($i = 0; $i < 10; $i++) { - $cycle(); -} -gc_collect_cycles(); -$baseline = memory_get_usage(false); - -for ($i = 0; $i < 100; $i++) { - $cycle(); -} -gc_collect_cycles(); - -var_dump(memory_get_usage(false) <= $baseline); -?> ---EXPECT-- -bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/026_row_hydrator_cast_parity.phpt b/src/extension/flow-php-ext/tests/phpt/026_row_hydrator_cast_parity.phpt deleted file mode 100644 index a466225608..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/026_row_hydrator_cast_parity.phpt +++ /dev/null @@ -1,341 +0,0 @@ ---TEST-- -NativeRowHydrator cast is serialize-identical to PhpRowHydrator ---SKIPIF-- - ---FILE-- - [ - schema(int_schema('id'), float_schema('p'), bool_schema('a'), str_schema('n', nullable: true)), - [ - new RawRowValues(['id' => '42', 'p' => '3.14', 'a' => 'yes', 'n' => 7]), - new RawRowValues(['id' => ' 7', 'p' => '1e3', 'a' => 'OFF', 'n' => 1.5]), - new RawRowValues(['id' => '007', 'p' => '.5', 'a' => 'ON', 'n' => true]), - new RawRowValues(['id' => '9223372036854775807', 'p' => true, 'a' => 3.5, 'n' => null]), - new RawRowValues(['id' => 5, 'p' => 2.5, 'a' => true, 'n' => 'text']), - ], - ], - 'nested_families' => [ - schema( - list_schema('counts', type_list(type_positive_integer())), - structure_schema('labels', type_structure(['label' => type_non_empty_string()])), - structure_schema('codes', type_structure(['code' => type_numeric_string()])), - ), - [ - new RawRowValues(['counts' => [5, 7], 'labels' => ['label' => 'x'], 'codes' => ['code' => '42']]), - new RawRowValues(['counts' => ['5', 8], 'labels' => ['label' => 9], 'codes' => ['code' => 42]]), - ], - ], - 'temporal' => [ - schema(datetime_schema('at'), datetime_schema('at2'), date_schema('d')), - [ - new RawRowValues(['at' => $shared, 'at2' => $shared, 'd' => $shared]), - new RawRowValues(['at' => $shared, 'at2' => '2024-03-01 10:20:30', 'd' => new DateTimeImmutable('2025-03-01')]), - new RawRowValues(['at' => 1700000000, 'at2' => 1700000000.5, 'd' => '2024-03-05 08:30:00']), - ], - ], - 'uuid_json' => [ - schema(uuid_schema('u', nullable: true), json_schema('j')), - [ - new RawRowValues(['u' => '01234567-89ab-4def-8123-456789abcdef', 'j' => '["a","b"]']), - new RawRowValues(['u' => new Flow\Types\Value\Uuid('01234567-89ab-4def-8123-456789abcdef'), 'j' => '{"a":1}']), - new RawRowValues(['u' => null, 'j' => ['a' => 1]]), - new RawRowValues(['u' => '11234567-89ab-4def-8123-456789abcdef', 'j' => Flow\Types\Value\Json::fromArray(['x' => 1])]), - ], - ], - 'containers' => [ - schema( - list_schema('l', type_list(type_integer())), - map_schema('m', type_map(type_string(), type_integer())), - map_schema('mi', type_map(type_integer(), type_string())), - list_schema('lo', type_list(type_optional(type_integer()))), - list_schema('lf', type_list(type_float())), - structure_schema('st', type_structure(['a' => type_integer(), 'b' => structure_element('b', type_string(), optional: true)], true)), - ), - [ - new RawRowValues([ - 'l' => ['1', 2, '3'], - 'm' => ['a' => '1', 'b' => 2], - 'mi' => [0 => 'x', 5 => 7], - 'lo' => ['1', null, 3], - 'lf' => [33, 65.5], - 'st' => ['a' => '5', 'extra' => 'dropped'], - ]), - new RawRowValues(['l' => [], 'm' => [], 'mi' => [], 'lo' => [], 'lf' => [], 'st' => ['a' => 1, 'b' => 'kept']]), - ], - ], - 'exotic_fallback' => [ - schema(enum_schema('s', CastSuit::class), xml_schema('x'), time_schema('t')), - [ - new RawRowValues(['s' => CastSuit::Hearts, 'x' => 'v', 't' => new DateInterval('PT2H30M5S')]), - new RawRowValues(['s' => 'h', 'x' => '', 't' => 'PT2H']), - ], - ], - 'fill_and_metadata' => [ - schema(int_schema('id', nullable: true), str_schema('name', nullable: true), bool_schema('flag', nullable: true)), - [ - new RawRowValues(['id' => '1'], ['id' => Metadata::fromArray(['k' => 'v1'])]), - new RawRowValues([]), - new RawRowValues(['id' => 2, 'name' => null, 'unknown' => 'dropped', 'flag' => 'on']), - new RawRowValues(['id' => null], ['id' => Metadata::fromArray(['k' => 'v2'])]), - ], - ], - 'all_optional_st' => [ - schema(structure_schema('st', type_structure(['b' => structure_element('b', type_string(), optional: true)]))), - [new RawRowValues(['st' => ['other' => 1]])], - ], - 'interleaved_st' => [ - schema(structure_schema('st', type_structure(['z' => type_integer(), 'a' => structure_element('a', type_string(), optional: true), 'b' => type_string()]))), - [ - new RawRowValues(['st' => ['b' => 'x', 'z' => '5']]), - new RawRowValues(['st' => ['z' => 1, 'a' => 'present', 'b' => 'y']]), - ], - ], - 'empty' => [schema(int_schema('id')), []], - // every column present in every row: the batch skips Row::conform(), which would return each row unchanged - 'all_present' => [ - schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('a'), float_schema('p', nullable: true)), - [ - new RawRowValues(['id' => '1', 'name' => 'x', 'a' => 'yes', 'p' => '1.5']), - new RawRowValues(['id' => '2', 'name' => null, 'a' => 'no', 'p' => null]), - new RawRowValues(['p' => 3, 'a' => true, 'name' => 'z', 'id' => 3]), - ], - ], - 'absent_nullable' => [ - schema(int_schema('id'), str_schema('name', nullable: true)), - [ - new RawRowValues(['id' => 1, 'name' => 'a']), - new RawRowValues(['id' => 2, 'name' => 'b']), - new RawRowValues(['id' => 3, 'name' => 'c']), - new RawRowValues(['id' => 4]), - new RawRowValues(['id' => 5, 'name' => 'e']), - ], - ], - 'numeric_names' => [ - schema(int_schema('id'), str_schema('7'), int_schema('10', nullable: true)), - [ - new RawRowValues(['id' => '1', '7' => 'seven', '10' => '10']), - new RawRowValues(['10' => null, '7' => 'eight', 'id' => 2]), - ], - ], -]; - -$php = new PhpRowHydrator(); -$native = new NativeRowHydrator(); - -foreach ($datasets as $label => [$s, $batch]) { - $hydrateOk = serialize($php->hydrate($batch, $s)) === serialize($native->hydrate($batch, $s)); - printf("%-16s hydrate:%s\n", $label, $hydrateOk ? 'yes' : 'NO'); -} - -// TypeDetector types [33, 65.5] as list; both hydrators must materialize it as floats. -$promotion = schema(list_schema('lf', type_list(type_float()))); -$promotionBatch = [new RawRowValues(['lf' => [33, 65.5]])]; -printf( - "%-16s php:%s native:%s\n", - 'list_promotion', - json_encode($php->hydrate($promotionBatch, $promotion)->first()->get('lf'), JSON_PRESERVE_ZERO_FRACTION), - json_encode($native->hydrate($promotionBatch, $promotion)->first()->get('lf'), JSON_PRESERVE_ZERO_FRACTION), -); - -$mutated = schema(int_schema('id')); -$php->hydrate([new RawRowValues(['id' => '1'])], $mutated); -$native->hydrate([new RawRowValues(['id' => '1'])], $mutated); -$mutated->add(str_schema('name', nullable: true))->makeNullable(); -// Schema is immutable, so $mutated never gained "name" - the column is simply not cast -$batch = [new RawRowValues(['id' => '1', 'name' => 7])]; -printf( - "%-16s hydrate:%s\n", - 'schema_mutation', - serialize($php->hydrate($batch, $mutated)) === serialize($native->hydrate($batch, $mutated)) ? 'yes' : 'NO', -); - -// row 3 lacks a NOT NULL column and row 5 is refused by its cast: the cast refusal is raised while the batch is -// built, before Rows::conformed() could report the absence, so both paths name row 5 -$refused = schema(int_schema('id'), int_schema('n')); -$refusedBatch = [ - new RawRowValues(['id' => 0, 'n' => 0]), - new RawRowValues(['id' => 1, 'n' => 1]), - new RawRowValues(['id' => 2, 'n' => 2]), - new RawRowValues(['id' => 3]), - new RawRowValues(['id' => 4, 'n' => 4]), - new RawRowValues(['id' => 5, 'n' => 'five']), -]; -$refusals = []; - -foreach (['php' => $php, 'native' => $native] as $side => $hydrator) { - try { - $hydrator->hydrate($refusedBatch, $refused); - $refusals[$side] = 'none'; - } catch (Throwable $e) { - $refusals[$side] = $e::class . ': ' . $e->getMessage(); - } -} - -printf("%-16s identical:%s\n", 'absent_then_refused', $refusals['php'] === $refusals['native'] ? 'yes' : 'NO'); -echo $refusals['native'], "\n"; - -// a value held by reference is cast by value: the hydrated row must not change when the caller's variable does -$referenced = [ - 'ref_json' => [schema(json_schema('c')), '{"a":1}', static fn(&$v): array => ['c' => &$v]], - 'ref_uuid' => [schema(uuid_schema('c')), '01234567-89ab-4def-8123-456789abcdef', static fn(&$v): array => ['c' => &$v]], - 'ref_null' => [schema(str_schema('c', nullable: true)), null, static fn(&$v): array => ['c' => &$v]], - 'ref_datetime' => [schema(datetime_schema('c')), new DateTimeImmutable('2020-01-01 00:00:00'), static fn(&$v): array => ['c' => &$v]], - 'ref_list_item' => [schema(list_schema('c', type_list(type_positive_integer()))), 5, static fn(&$v): array => ['c' => [&$v]]], - 'ref_st_element' => [ - schema(structure_schema('c', type_structure(['s' => type_non_empty_string()]))), - 'text', - static fn(&$v): array => ['c' => ['s' => &$v]], - ], -]; - -foreach ($referenced as $label => [$s, $value, $wrap]) { - $hydrated = []; - - foreach (['php' => $php, 'native' => $native] as $side => $hydrator) { - $v = $value; - $rows = $hydrator->hydrate([new RawRowValues($wrap($v))], $s); - $v = 'mutated'; - $hydrated[$side] = serialize($rows); - } - - printf("%-16s hydrate:%s\n", $label, $hydrated['php'] === $hydrated['native'] ? 'yes' : 'NO'); -} - -$isoStrings = [ - '2026-07-13T10:20:30+00:00', - "2026-07-13T10:20:30+00:00\n", - "2026-07-13T10:20:30+00:00\n\n", - '2026-07-13T10:20:30Z', - '2026-07-13T10:20:30+05', - '2026-07-13T10:20:30+0530', - '2026-07-13T10:20:30+05:30', - '2026-07-13T10:20:30-12:00', - '2026-07-13 10:20:30', - '2026-07-13T10:20', - '2026-07-13T10:20:30.1Z', - '2026-07-13T10:20:30.12Z', - '2026-07-13T10:20:30.123Z', - '2026-07-13T10:20:30.1234Z', - '2026-07-13T10:20:30.12345Z', - '2026-07-13T10:20:30.123456Z', - '2026-07-13T10:20:30.1234567Z', - '2026-07-13T10:20:30.12345678Z', - '2026-07-13T10:20:30.123456789Z', - '2026-07-13T10:20:30.1234567890Z', - '2026-02-30T00:00:00Z', - '2024-02-29T00:00:00Z', - '2023-02-29T00:00:00Z', - '0000-01-01T00:00:00Z', - '2026-07-13T25:99:99Z', - '2026-07-13T10:20:30Z', - 'now', -]; - -// the gate's only outcome-changing check is checkdate(): PHP throws on an impossible day, the constructor rolls it over -foreach (['0000', '0001', '1900', '2000', '2023', '2024', '2100'] as $year) { - for ($month = 0; $month <= 13; $month++) { - for ($day = 0; $day <= 32; $day++) { - $isoStrings[] = sprintf('%s-%02d-%02dT00:00:00Z', $year, $month, $day); - } - } -} - -$isoSchema = schema(datetime_schema('at')); - -foreach (['UTC', 'Europe/Warsaw'] as $zone) { - ini_set('date.timezone', $zone); - $mismatches = 0; - - foreach ($isoStrings as $isoString) { - $results = []; - - foreach (['php' => $php, 'native' => $native] as $side => $hydrator) { - try { - $at = $hydrator->hydrate([new RawRowValues(['at' => $isoString])], $isoSchema)->first()->get('at'); - $results[$side] = $at::class . ' ' . $at->format('Y-m-d\TH:i:s.uP') . ' ' . $at->getTimezone()->getName(); - } catch (Throwable $e) { - $results[$side] = $e::class . ': ' . $e->getMessage(); - } - } - - if ($results['php'] !== $results['native']) { - $mismatches++; - echo ' ', var_export($isoString, true), ": php[{$results['php']}] native[{$results['native']}]\n"; - } - } - - printf("iso datetime %-13s %d strings, %d mismatches\n", $zone, count($isoStrings), $mismatches); -} - -printf("native class registered:%s\n", class_exists(RustRowHydratorNative::class, false) ? 'yes' : 'NO'); -?> ---EXPECT-- -scalars hydrate:yes -nested_families hydrate:yes -temporal hydrate:yes -uuid_json hydrate:yes -containers hydrate:yes -exotic_fallback hydrate:yes -fill_and_metadata hydrate:yes -all_optional_st hydrate:yes -interleaved_st hydrate:yes -empty hydrate:yes -all_present hydrate:yes -absent_nullable hydrate:yes -numeric_names hydrate:yes -list_promotion php:[33.0,65.5] native:[33.0,65.5] -schema_mutation hydrate:yes -absent_then_refused identical:yes -Flow\ETL\Exception\SchemaMismatchException: Rows do not match their schema: column "n" (row 5): could not convert 'five' (string) to integer -ref_json hydrate:yes -ref_uuid hydrate:yes -ref_null hydrate:yes -ref_datetime hydrate:yes -ref_list_item hydrate:yes -ref_st_element hydrate:yes -iso datetime UTC 3261 strings, 0 mismatches -iso datetime Europe/Warsaw 3261 strings, 0 mismatches -native class registered:yes diff --git a/src/extension/flow-php-ext/tests/phpt/027_cast_fallback_exceptions.phpt b/src/extension/flow-php-ext/tests/phpt/027_cast_fallback_exceptions.phpt deleted file mode 100644 index 94751cec92..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/027_cast_fallback_exceptions.phpt +++ /dev/null @@ -1,133 +0,0 @@ ---TEST-- -native cast propagates the exact PHP cast exceptions and aborts the batch ---SKIPIF-- - ---FILE-- - [schema(int_schema('id')), [new RawRowValues(['id' => 'abc'])]], - 'float from a hex string' => [schema(float_schema('p')), [new RawRowValues(['p' => '0x1A'])]], - 'boolean from an unrecognised word' => [schema(bool_schema('a')), [new RawRowValues(['a' => 'weird'])]], - 'integer from an array' => [schema(int_schema('id')), [new RawRowValues(['id' => [1, 2, 3]])]], - 'uuid invalid' => [schema(uuid_schema('u')), [new RawRowValues(['u' => 'not-a-uuid'])]], - 'uuid uppercase' => [schema(uuid_schema('u')), [new RawRowValues(['u' => '01234567-89AB-4DEF-8123-456789ABCDEF'])]], - 'json scalar' => [schema(json_schema('j')), [new RawRowValues(['j' => 5])]], - 'json invalid string' => [schema(json_schema('j')), [new RawRowValues(['j' => '{oops'])]], - 'json plain string' => [schema(json_schema('j')), [new RawRowValues(['j' => 'plain'])]], - 'datetime garbage' => [schema(datetime_schema('at')), [new RawRowValues(['at' => 'not-a-date'])]], - 'datetime array' => [schema(datetime_schema('at')), [new RawRowValues(['at' => ['nope']])]], - 'date garbage' => [schema(date_schema('d')), [new RawRowValues(['d' => 'not-a-date'])]], - 'string map int keys' => [ - schema(map_schema('m', type_map(type_string(), type_integer()))), - [new RawRowValues(['m' => [5 => 1]])], - ], - 'list bad keys' => [ - schema(list_schema('l', type_list(type_integer()))), - [new RawRowValues(['l' => [1 => 'x']])], - ], - 'positive int list string' => [ - schema(list_schema('l', type_list(type_positive_integer()))), - [new RawRowValues(['l' => ['abc']])], - ], - 'positive int list negative' => [ - schema(list_schema('l', type_list(type_positive_integer()))), - [new RawRowValues(['l' => [-3]])], - ], - 'row index is 1' => [ - schema(int_schema('i')), - [new RawRowValues(['i' => '1']), new RawRowValues(['i' => 'x'])], - ], - 'integer overflow' => [schema(int_schema('id')), [new RawRowValues(['id' => '9223372036854775808'])]], - 'date from an empty string' => [schema(date_schema('d')), [new RawRowValues(['d' => ''])]], - 'datetime from a relative word' => [schema(datetime_schema('at')), [new RawRowValues(['at' => 'now'])]], - 'string from null' => [ - schema(list_schema('l', type_list(type_string()))), - [new RawRowValues(['l' => ['a', null]])], - ], - 'list from a scalar' => [ - schema(list_schema('l', type_list(type_integer()))), - [new RawRowValues(['l' => 5])], - ], - 'exception outside the types package' => [ - schema(new ForeignTypeDefinition('a', new ThrowingType(new LogicException('stub type refuses everything')))), - [new RawRowValues(['a' => [1, 2]])], - ], -]; - -$php = new PhpRowHydrator(); -$native = new NativeRowHydrator(); - -foreach ($throwing as $label => [$s, $batch]) { - $phpException = null; - - try { - $php->hydrate($batch, $s); - } catch (Throwable $e) { - $phpException = $e::class . '|' . $e->getMessage(); - } - - $nativeException = null; - $nativeResult = null; - - try { - $nativeResult = $native->hydrate($batch, $s); - } catch (Throwable $e) { - $nativeException = $e::class . '|' . $e->getMessage(); - } - - printf( - "%-27s exception:%s aborted:%s\n", - $label, - $phpException !== null && $phpException === $nativeException ? 'match' : "MISMATCH php[{$phpException}] native[{$nativeException}]", - $nativeResult === null ? 'yes' : 'NO', - ); -} -?> ---EXPECT-- -integer from a non numeric string exception:match aborted:yes -float from a hex string exception:match aborted:yes -boolean from an unrecognised word exception:match aborted:yes -integer from an array exception:match aborted:yes -uuid invalid exception:match aborted:yes -uuid uppercase exception:match aborted:yes -json scalar exception:match aborted:yes -json invalid string exception:match aborted:yes -json plain string exception:match aborted:yes -datetime garbage exception:match aborted:yes -datetime array exception:match aborted:yes -date garbage exception:match aborted:yes -string map int keys exception:match aborted:yes -list bad keys exception:match aborted:yes -positive int list string exception:match aborted:yes -positive int list negative exception:match aborted:yes -row index is 1 exception:match aborted:yes -integer overflow exception:match aborted:yes -date from an empty string exception:match aborted:yes -datetime from a relative word exception:match aborted:yes -string from null exception:match aborted:yes -list from a scalar exception:match aborted:yes -exception outside the types package exception:match aborted:yes diff --git a/src/extension/flow-php-ext/tests/phpt/028_cast_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/028_cast_no_leaks.phpt deleted file mode 100644 index 0d54410bdc..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/028_cast_no_leaks.phpt +++ /dev/null @@ -1,129 +0,0 @@ ---TEST-- -repeated native cast does not leak memory, including the throwing fallback path ---SKIPIF-- - ---FILE-- - type_integer(), 'b' => structure_element('b', type_string(), optional: true)])), - list_schema('names', type_list(type_string())), - json_schema('json'), - enum_schema('suit', LeakSuit::class), // exotic - per-value PHP fallback -); - -$batch = []; - -for ($i = 1; $i <= 100; $i++) { - $batch[] = new RawRowValues( - [ - 'id' => (string) $i, - 'name' => $i % 10 === 0 ? null : 'user_' . $i, // null values under a nullable declaration - 'price' => \sprintf('%d.%02d', $i, $i % 100), - 'active' => $i % 2 === 0 ? 'yes' : 'off', - 'created_at' => \sprintf('2024-03-%02d 10:20:%02d', 1 + $i % 28, $i % 60), - 'day' => \sprintf('2024-03-%02d', 1 + $i % 28), - 'uuid' => \sprintf('550e8400-e29b-41d4-a716-%012d', $i), - 'ints' => [(string) $i, null, $i], - 'metrics' => ['cpu' => (string) $i, 'mem' => $i], - 'nested' => ['a' => (string) $i, 'b' => $i], - 'names' => ['a', 'b'], - 'json' => '["a","b"]', - 'suit' => 'h', - ], - $i % 5 === 0 ? ['id' => Metadata::fromArray(['batch' => $i])] : [], // exercises the clone + setMetadata path - ); -} - -// a container column carrying a null element is the only way the deleted CastKind::String null arm -// is reachable, so the leak check has to exercise the List/Map recursion too -$throwingBatch = [ - new RawRowValues(['id' => 1]), - new RawRowValues(['uuid' => 'not-a-uuid', 'id' => 2, 'names' => ['a', null]]), -]; - -// an absent NOT-NULL column aborts before any row_values insertion - a different leak path -$missingBatch = [new RawRowValues(['name' => 'no id here'])]; - -$jsonSchema = schema(json_schema('json')); - -$cycle = static function () use ($batch, $throwingBatch, $missingBatch, $schema, $jsonSchema): void { - $native = new RustRowHydratorNative(); - $native->hydrate($batch, $schema); - - foreach (json_leak_cells() as $cell) { - try { - $native->hydrate([new RawRowValues(['json' => $cell])], $jsonSchema); - } catch (Throwable) { - // a refused cell aborts its batch; nothing it touched may leak - } - } - - try { - $native->hydrate($throwingBatch, $schema); - } catch (Throwable) { - // the aborted batch must not leak its partially built rows - } - - try { - $native->hydrate($missingBatch, $schema); - } catch (Throwable) { - // the same, aborted before the first insertion - } -}; - -for ($i = 0; $i < 10; $i++) { - $cycle(); -} -gc_collect_cycles(); -$baseline = memory_get_usage(false); - -for ($i = 0; $i < 100; $i++) { - $cycle(); -} -gc_collect_cycles(); - -var_dump(memory_get_usage(false) <= $baseline); -?> ---EXPECT-- -bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/030_encode_typed_object_class_check.phpt b/src/extension/flow-php-ext/tests/phpt/030_encode_typed_object_class_check.phpt deleted file mode 100644 index 1141281501..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/030_encode_typed_object_class_check.phpt +++ /dev/null @@ -1,45 +0,0 @@ ---TEST-- -Typed uuid/json columns reject a foreign object instead of reading its memory layout ---SKIPIF-- - ---FILE-- - 'not-an-object-of-that-class'], ['v' => $columnType])]; - - expect_exception(fn() => $encoder->encode($typed, json_encode($columnSchema->normalize(), JSON_THROW_ON_ERROR), $columnSchema)); -} - -$typedObject = (new PhpRowHydrator())->dehydrate( - new Rows(schema(datetime_schema('v')), row(['v' => new DateTimeImmutable('2020-01-01 00:00:00 UTC')])), -); - -$uuidSchema = schema(uuid_schema('v')); -expect_exception(fn() => $encoder->encode($typedObject, json_encode($uuidSchema->normalize(), JSON_THROW_ON_ERROR), $uuidSchema)); -?> ---EXPECT-- -Flow\Floe\Exception\ExtensionException: flow_php expected a uuid value to be an object -Flow\Floe\Exception\ExtensionException: flow_php expected a json value to be an object -Flow\Floe\Exception\ExtensionException: flow_php expected a uuid value to be an object diff --git a/src/extension/flow-php-ext/tests/phpt/031_structure_v2_guards.phpt b/src/extension/flow-php-ext/tests/phpt/031_structure_v2_guards.phpt deleted file mode 100644 index 179978b43b..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/031_structure_v2_guards.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -structure schema-shape skew guards: the legacy two-bucket shape and an empty fields list are rejected loudly ---SKIPIF-- - ---FILE-- -dehydrate(new Rows($schema, row(['id' => 1]))); - -// direction 2 of the skew guard: a new binary reading the legacy two-bucket shape -// has no "structure" arm and rejects the unknown tag. -$legacy = json_encode([[ - 'ref' => 'st', - 'type' => [ - 'type' => 'structure', - 'elements' => ['a' => ['type' => 'integer']], - 'optional_elements' => [], - 'allow_extra' => false, - ], - 'nullable' => false, - 'metadata' => [], -]], JSON_THROW_ON_ERROR); - -expect_exception(fn() => (new RustFloeEncoderNative())->encode($typed, $legacy, $schema)); - -// the belt: a structure_v2 whose fields deserialized empty for any other reason. -$emptyFields = json_encode([[ - 'ref' => 'st', - 'type' => [ - 'type' => 'structure_v2', - 'fields' => [], - ], - 'nullable' => false, - 'metadata' => [], -]], JSON_THROW_ON_ERROR); - -expect_exception(fn() => (new RustFloeEncoderNative())->encode($typed, $emptyFields, $schema)); -?> ---EXPECT-- -Flow\Floe\Exception\ExtensionException: flow_php does not support values of type "structure" in this build -Flow\Floe\Exception\ExtensionException: flow_php read a structure type with no fields; the loaded flow_php extension and the flow-php/etl in use disagree on the structure schema format - reinstall one to match the other, or set the Floe engine to FloeEngine::php diff --git a/src/extension/flow-php-ext/tests/phpt/032_structure_numeric_name_parity.phpt b/src/extension/flow-php-ext/tests/phpt/032_structure_numeric_name_parity.phpt deleted file mode 100644 index 92f60db288..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/032_structure_numeric_name_parity.phpt +++ /dev/null @@ -1,43 +0,0 @@ ---TEST-- -a numeric element name ("0" on the wire, always a JSON string) keeps its DeclaredKey::Index encoding and its cast fallback ---SKIPIF-- - ---FILE-- - type_integer(), 'b' => type_string()]); - -$rows = rows(schema(structure_schema('st', $numericNamed)), row(['st' => [0 => 1, 'b' => 'x']])); - -printf("frames-identical:%s\n", php_frames($rows) === ext_frames($rows) ? 'yes' : 'NO'); - -$frames = php_frames($rows); -assert_rows_identical(php_decode_frames($frames), ext_decode_frames($frames)); - -// build_structure_kind still bails to CastKind::Fallback for a numeric name - -// parity with the pure-PHP hydrator proves it took the same code path. -$schema = schema(structure_schema('st', $numericNamed)); -$batch = [new RawRowValues(['st' => [0 => '1', 'b' => 2]])]; - -printf( - "cast-parity:%s\n", - serialize((new PhpRowHydrator())->hydrate($batch, $schema)) === serialize((new NativeRowHydrator())->hydrate($batch, $schema)) ? 'yes' : 'NO', -); -?> ---EXPECT-- -frames-identical:yes -identical -cast-parity:yes diff --git a/src/extension/flow-php-ext/tests/phpt/034_floe_encoder_nullability.phpt b/src/extension/flow-php-ext/tests/phpt/034_floe_encoder_nullability.phpt deleted file mode 100644 index f6caa49c57..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/034_floe_encoder_nullability.phpt +++ /dev/null @@ -1,60 +0,0 @@ ---TEST-- -both Floe encoders refuse a null on a NOT-NULL column with the same class and message ---SKIPIF-- - ---FILE-- - 1, 'name' => 'a', 'note' => null], ['id' => type_integer(), 'name' => type_string(), 'note' => type_string()]), - new TypedRowValues(['id' => 2, 'name' => null, 'note' => null], ['id' => type_integer(), 'name' => type_string(), 'note' => type_string()]), -]; - -$php = new PhpFloeEncoder($schema); -$native = new NativeFloeEncoder($schema); - -$describe = static function (callable $encode): string { - try { - $encode(); - - return 'NO EXCEPTION'; - } catch (Throwable $e) { - return $e::class . '|' . $e->getMessage(); - } -}; - -$phpRefusal = $describe(static fn() => $php->encode($refused)); -$nativeRefusal = $describe(static fn() => $native->encode($refused)); - -printf("refusal:%s\n", $phpRefusal === $nativeRefusal ? 'match' : "MISMATCH php[{$phpRefusal}] native[{$nativeRefusal}]"); -printf("%s\n", $phpRefusal); - -// a null under a nullable declaration still encodes, on both sides, to the same bytes -$allowed = (new PhpRowHydrator())->dehydrate( - new Rows($schema, row(['id' => 1, 'name' => 'a', 'note' => null])), -); - -printf("nullable:%s\n", $php->encode($allowed) === $native->encode($allowed) ? 'identical' : 'DIFFERENT'); -?> ---EXPECT-- -refusal:match -Flow\ETL\Exception\SchemaMismatchException|Rows do not match their schema: column "name" (row 1): could not convert null to string, column is not nullable -nullable:identical diff --git a/src/extension/flow-php-ext/tests/phpt/035_list_numeric_promotion.phpt b/src/extension/flow-php-ext/tests/phpt/035_list_numeric_promotion.phpt deleted file mode 100644 index 4882f7c04e..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/035_list_numeric_promotion.phpt +++ /dev/null @@ -1,71 +0,0 @@ ---TEST-- -list promotes long elements and list keeps a null, identically in both hydrators ---SKIPIF-- - ---FILE-- - is a schema a -// schemaless source can produce. The cast door has to promote every long element to a double, -// and it has to do it the same way on both sides of the extension boundary. -$php = new PhpRowHydrator(); -$native = new NativeRowHydrator(); - -$cases = [ - 'longs' => [ - schema(list_schema('l', type_list(type_float()))), - [new RawRowValues(['l' => [33, 65.5]]), new RawRowValues(['l' => [1, 2, 3]])], - ], - 'nullable' => [ - schema(list_schema('l', type_list(type_optional(type_float())))), - [new RawRowValues(['l' => [1, null, 2.5]]), new RawRowValues(['l' => [null]])], - ], - 'numeric_strings' => [ - schema(list_schema('l', type_list(type_float()))), - [new RawRowValues(['l' => ['1', 2, '3.5']])], - ], - 'empty' => [ - schema(list_schema('l', type_list(type_float()))), - [new RawRowValues(['l' => []])], - ], -]; - -foreach ($cases as $label => [$s, $batch]) { - $phpRows = $php->hydrate($batch, $s); - $nativeRows = $native->hydrate($batch, $s); - - printf("%-16s parity:%s\n", $label, serialize($phpRows) === serialize($nativeRows) ? 'yes' : 'NO'); - - foreach ($phpRows->all() as $i => $row) { - printf( - "%-16s row%d php:%s native:%s\n", - $label, - $i, - json_encode($row->get('l'), JSON_PRESERVE_ZERO_FRACTION), - json_encode($nativeRows->all()[$i]->get('l'), JSON_PRESERVE_ZERO_FRACTION), - ); - } -} -?> ---EXPECT-- -longs parity:yes -longs row0 php:[33.0,65.5] native:[33.0,65.5] -longs row1 php:[1.0,2.0,3.0] native:[1.0,2.0,3.0] -nullable parity:yes -nullable row0 php:[1.0,null,2.5] native:[1.0,null,2.5] -nullable row1 php:[null] native:[null] -numeric_strings parity:yes -numeric_strings row0 php:[1.0,2.0,3.5] native:[1.0,2.0,3.5] -empty parity:yes -empty row0 php:[] native:[] diff --git a/src/extension/flow-php-ext/tests/phpt/052_json_cast_parity.phpt b/src/extension/flow-php-ext/tests/phpt/052_json_cast_parity.phpt deleted file mode 100644 index ae839d5e4d..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/052_json_cast_parity.phpt +++ /dev/null @@ -1,71 +0,0 @@ ---TEST-- -native JSON cast matches PhpRowHydrator on the JSON parity cases and a deterministic fuzz corpus ---SKIPIF-- - ---FILE-- - substr($fuzzed, 0, $at) . $insert . substr($fuzzed, $at), - 1 => substr($fuzzed, 0, $at) . substr($fuzzed, $at + 1), - default => substr($fuzzed, 0, $at) . $insert . substr($fuzzed, $at + 1), - }; - } - } - - $cases["fuzz_{$i}"] = $fuzzed; -} - -$schema = schema(json_schema('j', nullable: false)); -$php = new PhpRowHydrator(); -$native = new NativeRowHydrator(); - -$outcome = static function (Flow\ETL\Row\Hydrator $hydrator, string $value) use ($schema): string { - try { - return 'json ' . $hydrator->hydrate([new RawRowValues(['j' => $value])], $schema)->first()->get('j')->toString(); - } catch (Throwable $e) { - return $e::class . ': ' . $e->getMessage(); - } -}; - -$mismatches = 0; - -foreach ($cases as $name => $value) { - if ($outcome($php, $value) !== $outcome($native, $value)) { - $mismatches++; - echo ' ', $name, ' ', bin2hex(substr($value, 0, 60)), "\n"; - } -} - -printf("json cast parity: %d cases, %d mismatches\n", count($cases), $mismatches); -?> ---EXPECT-- -json cast parity: 20054 cases, 0 mismatches diff --git a/src/extension/flow-php-ext/tests/phpt/055_datetime_iso_fast_path.phpt b/src/extension/flow-php-ext/tests/phpt/055_datetime_iso_fast_path.phpt deleted file mode 100644 index 2325aa529b..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/055_datetime_iso_fast_path.phpt +++ /dev/null @@ -1,207 +0,0 @@ ---TEST-- -datetime ISO strings: both hydrators build the value in the column zone - naive text read in it, Z and offsets converted to it, date.timezone ignored ---SKIPIF-- - ---FILE-- - $value])]; - $expected = (new DateTimeImmutable($value, $tz))->setTimezone($tz); - $phpAt = $php->hydrate($batch, $schema)->first()->get('at'); - $nativeAt = $native->hydrate($batch, $schema)->first()->get('at'); - - printf( - "%-38s %s %s type:%d php:%s native:%s\n", - json_encode($value), - $nativeAt->format('Y-m-d H:i:s.u P'), - $nativeAt->getTimezone()->getName(), - json_decode(json_encode($nativeAt), true)['timezone_type'], - serialize($phpAt) === serialize($expected) ? 'yes' : 'NO', - serialize($nativeAt) === serialize($expected) ? 'yes' : 'NO', - ); - } -} - -$schema = schema(datetime_schema('at')); - -foreach (['2026-01-02T25:99:99Z', '2026-01-02T03:60:00Z', '2026-01-02T03:04:05+25:00'] as $value) { - $batch = [new RawRowValues(['at' => $value])]; - - foreach (['php' => $php, 'native' => $native] as $label => $hydrator) { - try { - $hydrator->hydrate($batch, $schema); - echo "{$label} {$value}: FAIL no exception\n"; - } catch (Throwable $e) { - echo "{$label} {$value}: ", $e::class, "\n"; - } - } -} -?> ---EXPECT-- -column zone UTC -"2026-01-02T03:04:05Z" 2026-01-02 03:04:05.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02 03:04:05Z" 2026-01-02 03:04:05.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04Z" 2026-01-02 03:04:00.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05Z\n" 2026-01-02 03:04:05.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.1Z" 2026-01-02 03:04:05.100000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.12Z" 2026-01-02 03:04:05.120000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.123Z" 2026-01-02 03:04:05.123000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.1234Z" 2026-01-02 03:04:05.123400 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.12345Z" 2026-01-02 03:04:05.123450 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.123456Z" 2026-01-02 03:04:05.123456 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.1234567Z" 2026-01-02 03:04:05.123456 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.12345678Z" 2026-01-02 03:04:05.123456 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.123456789Z" 2026-01-02 03:04:05.123456 +00:00 UTC type:3 php:yes native:yes -"2026-12-31T23:59:60Z" 2027-01-01 00:00:00.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T24:00:00Z" 2026-01-03 00:00:00.000000 +00:00 UTC type:3 php:yes native:yes -"0001-01-01T00:00:00Z" 0001-01-01 00:00:00.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05.123456789+02:00" 2026-01-02 01:04:05.123456 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05-0530" 2026-01-02 08:34:05.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05-05" 2026-01-02 08:04:05.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05+00:00" 2026-01-02 03:04:05.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02 03:04" 2026-01-02 03:04:00.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04:05" 2026-01-02 03:04:05.000000 +00:00 UTC type:3 php:yes native:yes -"2026-01-02T03:04\n" 2026-01-02 03:04:00.000000 +00:00 UTC type:3 php:yes native:yes -"2026-03-29T02:30:00" 2026-03-29 02:30:00.000000 +00:00 UTC type:3 php:yes native:yes -"2026-10-25T02:30:00" 2026-10-25 02:30:00.000000 +00:00 UTC type:3 php:yes native:yes -"2026-03-08T02:30:00" 2026-03-08 02:30:00.000000 +00:00 UTC type:3 php:yes native:yes -"2026-11-01T01:30:00" 2026-11-01 01:30:00.000000 +00:00 UTC type:3 php:yes native:yes -column zone Europe/Warsaw -"2026-01-02T03:04:05Z" 2026-01-02 04:04:05.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02 03:04:05Z" 2026-01-02 04:04:05.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04Z" 2026-01-02 04:04:00.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05Z\n" 2026-01-02 04:04:05.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.1Z" 2026-01-02 04:04:05.100000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.12Z" 2026-01-02 04:04:05.120000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.123Z" 2026-01-02 04:04:05.123000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.1234Z" 2026-01-02 04:04:05.123400 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.12345Z" 2026-01-02 04:04:05.123450 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.123456Z" 2026-01-02 04:04:05.123456 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.1234567Z" 2026-01-02 04:04:05.123456 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.12345678Z" 2026-01-02 04:04:05.123456 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.123456789Z" 2026-01-02 04:04:05.123456 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-12-31T23:59:60Z" 2027-01-01 01:00:00.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T24:00:00Z" 2026-01-03 01:00:00.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"0001-01-01T00:00:00Z" 0001-01-01 01:24:00.000000 +01:24 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05.123456789+02:00" 2026-01-02 02:04:05.123456 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05-0530" 2026-01-02 09:34:05.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05-05" 2026-01-02 09:04:05.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05+00:00" 2026-01-02 04:04:05.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02 03:04" 2026-01-02 03:04:00.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04:05" 2026-01-02 03:04:05.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-01-02T03:04\n" 2026-01-02 03:04:00.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-03-29T02:30:00" 2026-03-29 03:30:00.000000 +02:00 Europe/Warsaw type:3 php:yes native:yes -"2026-10-25T02:30:00" 2026-10-25 02:30:00.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-03-08T02:30:00" 2026-03-08 02:30:00.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -"2026-11-01T01:30:00" 2026-11-01 01:30:00.000000 +01:00 Europe/Warsaw type:3 php:yes native:yes -column zone America/New_York -"2026-01-02T03:04:05Z" 2026-01-01 22:04:05.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02 03:04:05Z" 2026-01-01 22:04:05.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04Z" 2026-01-01 22:04:00.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05Z\n" 2026-01-01 22:04:05.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.1Z" 2026-01-01 22:04:05.100000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.12Z" 2026-01-01 22:04:05.120000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.123Z" 2026-01-01 22:04:05.123000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.1234Z" 2026-01-01 22:04:05.123400 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.12345Z" 2026-01-01 22:04:05.123450 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.123456Z" 2026-01-01 22:04:05.123456 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.1234567Z" 2026-01-01 22:04:05.123456 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.12345678Z" 2026-01-01 22:04:05.123456 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.123456789Z" 2026-01-01 22:04:05.123456 -05:00 America/New_York type:3 php:yes native:yes -"2026-12-31T23:59:60Z" 2026-12-31 19:00:00.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T24:00:00Z" 2026-01-02 19:00:00.000000 -05:00 America/New_York type:3 php:yes native:yes -"0001-01-01T00:00:00Z" 0000-12-31 19:03:58.000000 -04:56 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05.123456789+02:00" 2026-01-01 20:04:05.123456 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05-0530" 2026-01-02 03:34:05.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05-05" 2026-01-02 03:04:05.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05+00:00" 2026-01-01 22:04:05.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02 03:04" 2026-01-02 03:04:00.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04:05" 2026-01-02 03:04:05.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-01-02T03:04\n" 2026-01-02 03:04:00.000000 -05:00 America/New_York type:3 php:yes native:yes -"2026-03-29T02:30:00" 2026-03-29 02:30:00.000000 -04:00 America/New_York type:3 php:yes native:yes -"2026-10-25T02:30:00" 2026-10-25 02:30:00.000000 -04:00 America/New_York type:3 php:yes native:yes -"2026-03-08T02:30:00" 2026-03-08 03:30:00.000000 -04:00 America/New_York type:3 php:yes native:yes -"2026-11-01T01:30:00" 2026-11-01 01:30:00.000000 -04:00 America/New_York type:3 php:yes native:yes -column zone +05:30 -"2026-01-02T03:04:05Z" 2026-01-02 08:34:05.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02 03:04:05Z" 2026-01-02 08:34:05.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04Z" 2026-01-02 08:34:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05Z\n" 2026-01-02 08:34:05.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.1Z" 2026-01-02 08:34:05.100000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.12Z" 2026-01-02 08:34:05.120000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.123Z" 2026-01-02 08:34:05.123000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.1234Z" 2026-01-02 08:34:05.123400 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.12345Z" 2026-01-02 08:34:05.123450 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.123456Z" 2026-01-02 08:34:05.123456 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.1234567Z" 2026-01-02 08:34:05.123456 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.12345678Z" 2026-01-02 08:34:05.123456 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.123456789Z" 2026-01-02 08:34:05.123456 +05:30 +05:30 type:1 php:yes native:yes -"2026-12-31T23:59:60Z" 2027-01-01 05:30:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T24:00:00Z" 2026-01-03 05:30:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"0001-01-01T00:00:00Z" 0001-01-01 05:30:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05.123456789+02:00" 2026-01-02 06:34:05.123456 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05-0530" 2026-01-02 14:04:05.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05-05" 2026-01-02 13:34:05.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05+00:00" 2026-01-02 08:34:05.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02 03:04" 2026-01-02 03:04:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04:05" 2026-01-02 03:04:05.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-01-02T03:04\n" 2026-01-02 03:04:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-03-29T02:30:00" 2026-03-29 02:30:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-10-25T02:30:00" 2026-10-25 02:30:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-03-08T02:30:00" 2026-03-08 02:30:00.000000 +05:30 +05:30 type:1 php:yes native:yes -"2026-11-01T01:30:00" 2026-11-01 01:30:00.000000 +05:30 +05:30 type:1 php:yes native:yes -php 2026-01-02T25:99:99Z: Flow\ETL\Exception\SchemaMismatchException -native 2026-01-02T25:99:99Z: Flow\ETL\Exception\SchemaMismatchException -php 2026-01-02T03:60:00Z: Flow\ETL\Exception\SchemaMismatchException -native 2026-01-02T03:60:00Z: Flow\ETL\Exception\SchemaMismatchException -php 2026-01-02T03:04:05+25:00: Flow\ETL\Exception\SchemaMismatchException -native 2026-01-02T03:04:05+25:00: Flow\ETL\Exception\SchemaMismatchException diff --git a/src/extension/flow-php-ext/tests/phpt/056_fused_decode_rows.phpt b/src/extension/flow-php-ext/tests/phpt/056_fused_decode_rows.phpt deleted file mode 100644 index 3e0183108b..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/056_fused_decode_rows.phpt +++ /dev/null @@ -1,182 +0,0 @@ ---TEST-- -RustFloeEncoderNative::decodeRows() yields the same Rows, and refuses with the same message, as hydrate(decode()) ---SKIPIF-- - ---FILE-- - - */ -function bodies(Rows $rows, Schema $fileSchema): array -{ - $schemaBody = json_encode($fileSchema->normalize(), JSON_THROW_ON_ERROR); - - return (new RustFloeEncoderNative())->encode((new NativeRowHydrator())->dehydrate($rows), $schemaBody, $fileSchema); -} - -function outcome(callable $read): string -{ - try { - return serialize($read()); - } catch (Throwable $e) { - $previous = $e->getPrevious(); - - return get_class($e) . ': ' . $e->getMessage() . ($previous === null ? '' : ' <- ' . get_class($previous) . ': ' . $previous->getMessage()); - } -} - -/** - * @param list $bodies - */ -function compare(string $label, array $bodies, string $schemaBody, Schema $schema): void -{ - $twoStep = outcome(static fn(): Rows => (new RustRowHydratorNative())->hydrate((new RustFloeEncoderNative())->decode($bodies, $schemaBody), $schema)); - $fused = outcome(static fn(): Rows => (new RustFloeEncoderNative())->decodeRows($bodies, $schemaBody, $schema)); - - echo $label, ': ', $twoStep === $fused ? 'identical' : "FAIL\n two-step: {$twoStep}\n fused: {$fused}", "\n"; - - if (!str_starts_with($fused, 'O:')) { - echo ' ', $fused, "\n"; - } -} - -function compare_rows(string $label, Rows $rows, ?Schema $readSchema = null): void -{ - $fileSchema = $rows->schema(); - - compare( - $label, - bodies($rows, $fileSchema), - json_encode($fileSchema->normalize(), JSON_THROW_ON_ERROR), - $readSchema ?? $fileSchema, - ); -} - -compare_rows('017 rows', rows( - schema(int_schema('id'), str_schema('name', nullable: true), float_schema('price', nullable: true), datetime_schema('at', nullable: true)), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => null]), - row(['id' => 3, 'price' => 1.5]), - row(['id' => 4, 'at' => new DateTimeImmutable('2025-01-01 00:00:00.123456', new DateTimeZone('Europe/Warsaw'))]), -)); - -compare_rows('021 rows', rows( - schema(int_schema('id'), str_schema('name', nullable: true), float_schema('price')), - ...array_map(static fn(int $i) => row(['id' => $i, 'name' => $i % 7 === 0 ? null : 'user_' . $i, 'price' => $i / 4.0]), range(1, 500)), -)); - -$containers = rows( - schema( - int_schema('id'), - datetime_schema('utc'), - datetime_schema('zoned', nullable: true), - list_schema('tags', type_list(type_string()), nullable: true), - map_schema('scores', type_map(type_string(), type_integer())), - structure_schema('address', type_structure(['street' => type_string(), 'zip' => type_integer()]), nullable: true), - bool_schema('active'), - int_schema('1', nullable: true), - ), - row(['id' => 1, 'utc' => new DateTimeImmutable('2026-03-01T10:11:12.654321Z'), 'zoned' => new DateTimeImmutable('2026-03-01 10:11:12', new DateTimeZone('+02:00')), 'tags' => ['a', 'b'], 'scores' => ['x' => 1], 'address' => ['street' => 'Main', 'zip' => 12345], 'active' => true, '1' => 7]), - row(['id' => 2, 'utc' => new DateTimeImmutable('1970-01-01T00:00:00Z'), 'zoned' => null, 'tags' => null, 'scores' => [], 'address' => null, 'active' => false, '1' => null]), - row(['id' => 3, 'utc' => new DateTimeImmutable('2026-12-31 23:59:59.000001', new DateTimeZone('Europe/Warsaw')), 'zoned' => new DateTimeImmutable('2026-06-01', new DateTimeZone('America/New_York')), 'tags' => [], 'scores' => ['y' => -2, 'z' => 3], 'address' => ['street' => '', 'zip' => 0], 'active' => true, '1' => 0]), -); - -compare_rows('nullable / datetime / list / map / structure / numeric name', $containers); - -$fileSchema = schema(int_schema('id'), str_schema('name', nullable: true), int_schema('7', nullable: true)); -$tagged = rows( - schema(int_schema('id'), str_schema('name', nullable: true, metadata: Metadata::fromArray(['source' => 'crm'])), int_schema('7', nullable: true, metadata: Metadata::fromArray(['n' => 1]))), - row(['id' => 1, 'name' => 'a', '7' => 1]), - row(['id' => 2, 'name' => null, '7' => null]), -); -compare('per-value metadata', bodies($tagged, $fileSchema), json_encode($fileSchema->normalize(), JSON_THROW_ON_ERROR), $fileSchema); - -compare_rows('empty batch', rows(schema(int_schema('id')))); -compare('no frames', [], json_encode(schema(int_schema('id'))->normalize(), JSON_THROW_ON_ERROR), schema(int_schema('id'))); - -$narrow = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a']), row(['id' => 2, 'name' => 'b'])); -compare_rows('read schema declares a nullable column the frames lack', $narrow, schema(int_schema('id'), str_schema('name'), str_schema('extra', nullable: true))); -compare_rows('read schema declares a NOT NULL column the frames lack', $narrow, schema(int_schema('id'), str_schema('name'), str_schema('extra'))); -compare_rows('read schema drops a decoded column', $narrow, schema(int_schema('id'))); -compare_rows('read schema reorders columns', $narrow, schema(str_schema('name'), int_schema('id'))); -compare_rows('read schema refuses a decoded value', $narrow, schema(int_schema('id'), int_schema('name'))); -compare_rows('read schema refuses a decoded null', rows(schema(int_schema('id'), str_schema('name', nullable: true)), row(['id' => 1, 'name' => null])), schema(int_schema('id'), str_schema('name'))); - -$narrowSchemaBody = json_encode($narrow->schema()->normalize(), JSON_THROW_ON_ERROR); -$narrowBodies = bodies($narrow, $narrow->schema()); -compare('trailing bytes', [$narrowBodies[0] . "\xEF"], $narrowSchemaBody, $narrow->schema()); -compare('truncated body', [substr($narrowBodies[1], 0, -1)], $narrowSchemaBody, $narrow->schema()); -compare('unknown value flag', ["\x09" . substr($narrowBodies[0], 1)], $narrowSchemaBody, $narrow->schema()); - -$duplicatedSchemaBody = json_encode([...$narrow->schema()->normalize(), ...schema(int_schema('id'))->normalize()], JSON_THROW_ON_ERROR); -compare('duplicated decoded name', [$narrowBodies[0] . "\x01" . pack('q', 9)], $duplicatedSchemaBody, $narrow->schema()); - -// the two-step path decodes every body before it casts; the fused path casts each row as it decodes it - a cast -// refusal in row 1 is reported ahead of a corrupt frame in row 2 only by the fused path -$precedence = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => '1']), row(['id' => 2, 'name' => 'x'])); -$precedenceBody = json_encode($precedence->schema()->normalize(), JSON_THROW_ON_ERROR); -$precedenceBodies = bodies($precedence, $precedence->schema()); -$precedenceInput = [$precedenceBodies[0], $precedenceBodies[1], $precedenceBodies[0] . "\xEF"]; -$castsName = schema(int_schema('id'), int_schema('name')); -echo 'precedence two-step: ', outcome(static fn(): Rows => (new RustRowHydratorNative())->hydrate((new RustFloeEncoderNative())->decode($precedenceInput, $precedenceBody), $castsName)), "\n"; -echo 'precedence fused: ', outcome(static fn(): Rows => (new RustFloeEncoderNative())->decodeRows($precedenceInput, $precedenceBody, $castsName)), "\n"; - -$encoder = new RustFloeEncoderNative(); -$first = $encoder->decodeRows($narrowBodies, $narrowSchemaBody, $narrow->schema()); -$second = $encoder->decodeRows(bodies($containers, $containers->schema()), json_encode($containers->schema()->normalize(), JSON_THROW_ON_ERROR), $containers->schema()); -$third = $encoder->decodeRows($narrowBodies, $narrowSchemaBody, $narrow->schema()); -echo 'plans rebind across schemas: ', $first->count(), ' ', $second->count(), ' ', serialize($first) === serialize($third) ? 'identical' : 'FAIL', "\n"; -?> ---EXPECT-- -017 rows: identical -021 rows: identical -nullable / datetime / list / map / structure / numeric name: identical -per-value metadata: identical -empty batch: identical -no frames: identical -read schema declares a nullable column the frames lack: identical -read schema declares a NOT NULL column the frames lack: identical - Flow\ETL\Exception\SchemaMismatchException: Rows do not match their schema: column "extra" (row 0) declared by the schema is missing from the row <- Flow\ETL\Exception\ColumnMismatchException: Row does not match its schema: column "extra" declared by the schema is missing from the row -read schema drops a decoded column: identical -read schema reorders columns: identical -read schema refuses a decoded value: identical - Flow\ETL\Exception\SchemaMismatchException: Rows do not match their schema: column "name" (row 0): could not convert 'a' (string) to integer <- Flow\ETL\Exception\ColumnMismatchException: Row does not match its schema: column "name": could not convert 'a' (string) to integer -read schema refuses a decoded null: identical - Flow\ETL\Exception\SchemaMismatchException: Rows do not match their schema: column "name" (row 0): could not convert null to string, column is not nullable <- Flow\ETL\Exception\ColumnMismatchException: Row does not match its schema: column "name": could not convert null to string, column is not nullable -trailing bytes: identical - Flow\Floe\Exception\ExtensionException: flow_php row frame length does not match its content -truncated body: identical - Flow\Floe\Exception\ExtensionException: flow_php frame body is truncated, string value is incomplete -unknown value flag: identical - Flow\Floe\Exception\ExtensionException: flow_php found unknown value flag 0x09 -duplicated decoded name: identical - Flow\Floe\Exception\ExtensionException: flow_php found duplicated entry name "id" in a row frame -precedence two-step: Flow\Floe\Exception\ExtensionException: flow_php row frame length does not match its content -precedence fused: Flow\ETL\Exception\SchemaMismatchException: Rows do not match their schema: column "name" (row 1): could not convert 'x' (string) to integer <- Flow\ETL\Exception\ColumnMismatchException: Row does not match its schema: column "name": could not convert 'x' (string) to integer -plans rebind across schemas: 2 3 identical diff --git a/src/extension/flow-php-ext/tests/phpt/057_decode_rows_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/057_decode_rows_no_leaks.phpt deleted file mode 100644 index e25fe89d01..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/057_decode_rows_no_leaks.phpt +++ /dev/null @@ -1,98 +0,0 @@ ---TEST-- -repeated fused decodeRows, refusals included, does not leak memory ---SKIPIF-- - ---FILE-- - type_integer(), 'tags' => type_list(type_string())])), - json_schema('json'), -); - -$batch = []; - -for ($i = 1; $i <= 100; $i++) { - $batch[] = new RawRowValues( - [ - 'id' => $i, - 'name' => $i % 10 === 0 ? null : 'user_' . $i, // null values under a nullable declaration - 'price' => (float) $i / 100, - 'active' => $i % 3 === 0, - 'created_at' => new DateTimeImmutable('2025-01-01 00:00:00.123456', new DateTimeZone('Europe/Warsaw')), - 'duration' => new DateInterval('PT1H2M3S'), - 'uuid' => new Flow\Types\Value\Uuid('01234567-89ab-4def-8123-456789abcdef'), - 'tags' => ['x', 'user_' . $i], - 'metrics' => ['cpu' => 0.5, 'mem' => 0.25], - 'nested' => ['a' => $i, 'tags' => ['x']], - 'json' => Flow\Types\Value\Json::fromArray([$i, ['a' => true]]), - ], - $i % 5 === 0 ? ['id' => Metadata::fromArray(['batch' => $i])] : [], // exercises the clone + setMetadata path - ); -} - -$schemaBody = json_encode($schema->normalize(), JSON_THROW_ON_ERROR); -// the per-row metadata diverges from the file schema, so the bodies carry VALUE_*_WITH_META flags -$bodies = (new RustFloeEncoderNative())->encode((new RustRowHydratorNative())->dehydrate((new PhpRowHydrator())->hydrate($batch, $schema)), $schemaBody, $schema); -$refusing = schema(int_schema('id'), int_schema('name', nullable: true)); - -$cycle = static function () use ($bodies, $schemaBody, $schema, $refusing): void { - $native = new RustFloeEncoderNative(); - $native->decodeRows($bodies, $schemaBody, $schema); - - try { - $native->decodeRows($bodies, $schemaBody, $refusing); - } catch (Flow\ETL\Exception\SchemaMismatchException) { - } -}; - -for ($i = 0; $i < 10; $i++) { - $cycle(); -} -gc_collect_cycles(); -$baseline = memory_get_usage(false); - -for ($i = 0; $i < 100; $i++) { - $cycle(); -} -gc_collect_cycles(); - -var_dump(memory_get_usage(false) <= $baseline); -?> ---EXPECT-- -bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/058_datetime_from_timestamp_parity.phpt b/src/extension/flow-php-ext/tests/phpt/058_datetime_from_timestamp_parity.phpt deleted file mode 100644 index e2fa8082a6..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/058_datetime_from_timestamp_parity.phpt +++ /dev/null @@ -1,133 +0,0 @@ ---TEST-- -native datetime decode builds the same DateTimeImmutable as createFromFormat('U.u')->setTimezone(), state and behaviour ---SKIPIF-- - ---FILE-- -format('Y-m-d H:i:s.u T e P p O U I Z L N z t'), - $value->getTimestamp(), - $value->getOffset(), - $value->getTimezone()->getName(), - $value->modify('+1 month')->format('Y-m-d H:i:s.u T e'), - $value->modify('midnight')->format('Y-m-d H:i:s.u T e U'), - $value->modify('last day of next month noon')->format('Y-m-d H:i:s.u T e'), - $value->setTime(1, 2, 3, 4)->format('Y-m-d H:i:s.u T e U'), - $value->setDate(2024, 2, 29)->format('Y-m-d H:i:s.u T e U'), - $value->add(new DateInterval('P1DT25H'))->format('Y-m-d H:i:s.u T e U'), - $value->sub(new DateInterval('P1M'))->format('Y-m-d H:i:s.u T e U'), - $value->diff($fixed)->format('%R %y %m %d %h %i %s %f %a'), - $value->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s.u T e'), - $value->setTimestamp(86400)->format('Y-m-d H:i:s.u T e'), - $value == $fixed, - $value < $fixed, - ]; -} - -$timezones = ['UTC', 'Z', 'Europe/Warsaw', 'America/New_York', 'Australia/Lord_Howe', '+00:00', '+02:00', '-05:30', 'CEST', 'EST']; -$instants = [ - '1970-01-01 00:00:00.000000 UTC', - '1969-12-31 23:59:59.999999 UTC', - '1969-07-20 20:17:00.5 UTC', - '2026-03-29 00:59:59.999999 UTC', - '2026-03-29 01:00:00.000001 UTC', - '2026-10-25 00:30:00 UTC', - '2026-10-25 01:30:00 UTC', - '2038-01-19 03:14:08.000001 UTC', - '0001-01-01 00:00:00 UTC', - '9999-12-31 23:59:59.999999 UTC', - '-0044-03-15 12:00:00 UTC', -]; - -$values = []; - -foreach ($timezones as $timezone) { - foreach ($instants as $instant) { - $values[] = (new DateTimeImmutable($instant))->setTimezone(new DateTimeZone($timezone)); - } -} - -$bodies = (new PhpFloeEncoder(schema(datetime_schema('at'))))->encode( - array_map(static fn(DateTimeImmutable $at): TypedRowValues => new TypedRowValues(['at' => $at], ['at' => type_datetime()]), $values), -); - -foreach (['UTC', 'Europe/Warsaw', '+05:30'] as $zone) { - $schema = schema(datetime_schema('at', zone: $zone)); - $php = (new PhpFloeEncoder($schema))->decode($bodies); - $native = (new RustFloeEncoderNative())->decode($bodies, json_encode($schema->normalize(), JSON_THROW_ON_ERROR)); - $differences = 0; - $inZone = 0; - - foreach ($php as $index => $expected) { - if (observe($expected->values['at']) !== observe($native[$index]->values['at'])) { - $differences++; - echo 'FAIL: ', $values[$index]->format('Y-m-d H:i:s.u e'), "\n"; - var_dump(array_diff_assoc(observe($expected->values['at']), observe($native[$index]->values['at']))); - } - - $inZone += $native[$index]->values['at']->getTimezone()->getName() === $zone ? 1 : 0; - } - - printf("datetime %s: %d values, %d differences, %d in the column zone\n", $zone, count($php), $differences, $inZone); -} - -$dates = array_map(static fn(DateTimeImmutable $at): DateTimeImmutable => $at->setTime(0, 0), $values); -$dateSchema = schema(date_schema('on')); -$dateBodies = (new PhpFloeEncoder($dateSchema))->encode( - array_map(static fn(DateTimeImmutable $on): TypedRowValues => new TypedRowValues(['on' => $on], ['on' => type_date()]), $dates), -); -$php = (new PhpFloeEncoder($dateSchema))->decode($dateBodies); -$native = (new RustFloeEncoderNative())->decode($dateBodies, json_encode($dateSchema->normalize(), JSON_THROW_ON_ERROR)); -$differences = 0; -$own = 0; - -foreach ($php as $index => $expected) { - $differences += observe($expected->values['on']) === observe($native[$index]->values['on']) ? 0 : 1; - $own += $native[$index]->values['on']->getTimezone()->getName() === $dates[$index]->getTimezone()->getName() ? 1 : 0; -} - -printf("date: %d values, %d differences, %d kept their own zone\n", count($php), $differences, $own); - -$schemaBody = json_encode(schema(datetime_schema('at'))->normalize(), JSON_THROW_ON_ERROR); - -$overlong = pack('P', 0) . pack('V', 1_000_000) . pack('V', 3) . 'UTC'; - -try { - (new RustFloeEncoderNative())->decode(["\x01" . $overlong], $schemaBody); - echo "FAIL: no exception\n"; -} catch (Flow\Floe\Exception\ExtensionException $e) { - echo $e->getMessage(), "\n"; -} - -try { - (new PhpFloeEncoder(schema(datetime_schema('at'))))->decode(["\x01" . $overlong]); - echo "FAIL: no exception\n"; -} catch (Flow\Floe\Exception\FloeException $e) { - echo $e->getMessage(), "\n"; -} -?> ---EXPECT-- -datetime UTC: 110 values, 0 differences, 110 in the column zone -datetime Europe/Warsaw: 110 values, 0 differences, 110 in the column zone -datetime +05:30: 110 values, 0 differences, 110 in the column zone -date: 110 values, 0 differences, 110 kept their own zone -flow_php failed to restore datetime from timestamp "0" -Floe failed to restore datetime from timestamp "0" diff --git a/src/extension/flow-php-ext/tests/phpt/059_encode_frames.phpt b/src/extension/flow-php-ext/tests/phpt/059_encode_frames.phpt deleted file mode 100644 index 270386d375..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/059_encode_frames.phpt +++ /dev/null @@ -1,137 +0,0 @@ ---TEST-- -RustFloeEncoderNative::encodeFrames() writes the bytes, and refuses with the message, of framing encode(dehydrate()) ---SKIPIF-- - ---FILE-- -getMessage(); - } -} - -function compare(string $label, Rows $rows, ?Schema $sessionSchema = null): void -{ - $sessionSchema ??= $rows->schema(); - $schemaBody = json_encode($sessionSchema->normalize(), JSON_THROW_ON_ERROR); - - $twoStep = outcome(static fn(): string => Format::rowFrames( - (new RustFloeEncoderNative())->encode((new RustRowHydratorNative())->dehydrate($rows), $schemaBody, $sessionSchema), - )); - $fused = outcome(static fn(): string => (new RustFloeEncoderNative())->encodeFrames($rows, $schemaBody, $sessionSchema)); - - echo $label, ': ', $twoStep === $fused ? 'identical' : "FAIL\n two-step: {$twoStep}\n fused: {$fused}", "\n"; - - if ($fused !== '' && !ctype_xdigit($fused)) { - echo ' ', $fused, "\n"; - } -} - -compare('017 rows', rows( - schema(int_schema('id'), str_schema('name', nullable: true), float_schema('price', nullable: true), datetime_schema('at', nullable: true)), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => null]), - row(['id' => 3, 'price' => 1.5]), - row(['id' => 4, 'at' => new DateTimeImmutable('2025-01-01 00:00:00.123456', new DateTimeZone('Europe/Warsaw'))]), -)); - -compare('021 rows', rows( - schema(int_schema('id'), str_schema('name', nullable: true), float_schema('price')), - ...array_map(static fn(int $i) => row(['id' => $i, 'name' => $i % 7 === 0 ? null : 'user_' . $i, 'price' => $i / 4.0]), range(1, 500)), -)); - -compare('034 nullable note', rows( - schema(int_schema('id'), str_schema('name'), str_schema('note', nullable: true)), - row(['id' => 1, 'name' => 'a', 'note' => null]), -)); - -compare('nullable / datetime / list / map / structure / numeric name', rows( - schema( - int_schema('id'), - datetime_schema('zoned', nullable: true), - list_schema('tags', type_list(type_string()), nullable: true), - map_schema('scores', type_map(type_string(), type_integer())), - structure_schema('address', type_structure(['street' => type_string(), 'zip' => type_integer()]), nullable: true), - bool_schema('active'), - int_schema('1', nullable: true), - ), - row(['id' => 1, 'zoned' => new DateTimeImmutable('2026-03-01 10:11:12', new DateTimeZone('+02:00')), 'tags' => ['a', 'b'], 'scores' => ['x' => 1], 'address' => ['street' => 'Main', 'zip' => 12345], 'active' => true, '1' => 7]), - row(['id' => 2, 'zoned' => null, 'tags' => null, 'scores' => [], 'address' => null, 'active' => false, '1' => null]), -)); - -$sessionSchema = schema(int_schema('id'), str_schema('name', nullable: true), int_schema('7', nullable: true)); -compare('batch metadata diverging from the session schema', rows( - schema(int_schema('id'), str_schema('name', nullable: true, metadata: Metadata::fromArray(['source' => 'crm'])), int_schema('7', nullable: true, metadata: Metadata::fromArray(['n' => 1]))), - row(['id' => 1, 'name' => 'a', '7' => 1]), - row(['id' => 2, 'name' => null, '7' => null]), -), $sessionSchema); - -compare('session schema carrying metadata', rows( - schema(int_schema('id', metadata: Metadata::fromArray(['k' => 'v']))), - row(['id' => 1]), -)); - -compare('empty Rows', rows(schema(int_schema('id')))); - -$schema = schema(int_schema('id'), str_schema('name')); -compare('null under NOT NULL', Rows::trusted($schema, [row(['id' => 1, 'name' => 'a']), row(['id' => 2, 'name' => null])])); -compare('row without a declared column', Rows::trusted($schema, [row(['id' => 1])])); - -// the two-step path dehydrates every row before it encodes; the fused path encodes each row as it reads it - a null -// under NOT NULL in row 1 is reported ahead of a missing column in row 2 only by the fused path -$precedence = Rows::trusted($schema, [row(['id' => 1, 'name' => 'a']), row(['id' => 2, 'name' => null]), row(['id' => 3])]); -$precedenceBody = json_encode($schema->normalize(), JSON_THROW_ON_ERROR); -echo 'precedence two-step: ', outcome(static fn(): string => Format::rowFrames((new RustFloeEncoderNative())->encode((new RustRowHydratorNative())->dehydrate($precedence), $precedenceBody, $schema))), "\n"; -echo 'precedence fused: ', outcome(static fn(): string => (new RustFloeEncoderNative())->encodeFrames($precedence, $precedenceBody, $schema)), "\n"; - -$encoder = new RustFloeEncoderNative(); -$small = rows($schema, row(['id' => 1, 'name' => 'a'])); -$first = $encoder->encodeFrames($small, json_encode($schema->normalize(), JSON_THROW_ON_ERROR), $schema); -$other = schema(int_schema('id')); -$encoder->encodeFrames(rows($other, row(['id' => 9])), json_encode($other->normalize(), JSON_THROW_ON_ERROR), $other); -echo 'plans rebind across schemas: ', $first === $encoder->encodeFrames($small, json_encode($schema->normalize(), JSON_THROW_ON_ERROR), $schema) ? 'identical' : 'FAIL', "\n"; -?> ---EXPECT-- -017 rows: identical -021 rows: identical -034 nullable note: identical -nullable / datetime / list / map / structure / numeric name: identical -batch metadata diverging from the session schema: identical -session schema carrying metadata: identical -empty Rows: identical -null under NOT NULL: identical - Flow\ETL\Exception\SchemaMismatchException: Rows do not match their schema: column "name" (row 1): could not convert null to string, column is not nullable -row without a declared column: identical - Flow\Floe\Exception\ExtensionException: flow_php found a row that does not carry the declared column "name" -precedence two-step: Flow\Floe\Exception\ExtensionException: flow_php found a row that does not carry the declared column "name" -precedence fused: Flow\ETL\Exception\SchemaMismatchException: Rows do not match their schema: column "name" (row 1): could not convert null to string, column is not nullable -plans rebind across schemas: identical diff --git a/src/extension/flow-php-ext/tests/phpt/060_encode_frames_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/060_encode_frames_no_leaks.phpt deleted file mode 100644 index 5a97dc7de5..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/060_encode_frames_no_leaks.phpt +++ /dev/null @@ -1,98 +0,0 @@ ---TEST-- -repeated fused encodeFrames, refusals included, does not leak memory ---SKIPIF-- - ---FILE-- - type_integer(), 'tags' => type_list(type_string())])), - json_schema('json'), -); - -$batch = []; - -for ($i = 1; $i <= 100; $i++) { - $batch[] = new RawRowValues( - [ - 'id' => $i, - 'name' => $i % 10 === 0 ? null : 'user_' . $i, // null values under a nullable declaration - 'price' => (float) $i / 100, - 'active' => $i % 3 === 0, - 'created_at' => new DateTimeImmutable('2025-01-01 00:00:00.123456', new DateTimeZone('Europe/Warsaw')), - 'duration' => new DateInterval('PT1H2M3S'), - 'uuid' => new Flow\Types\Value\Uuid('01234567-89ab-4def-8123-456789abcdef'), - 'tags' => ['x', 'user_' . $i], - 'metrics' => ['cpu' => 0.5, 'mem' => 0.25], - 'nested' => ['a' => $i, 'tags' => ['x']], - 'json' => Flow\Types\Value\Json::fromArray([$i, ['a' => true]]), - ], - $i % 5 === 0 ? ['id' => Metadata::fromArray(['batch' => $i])] : [], // exercises the clone + setMetadata path - ); -} - -$schemaBody = json_encode($schema->normalize(), JSON_THROW_ON_ERROR); -// the hydrated batch schema carries id's folded metadata, which the session schema does not - VALUE_*_WITH_META frames -$rows = (new PhpRowHydrator())->hydrate($batch, $schema); -$refused = Flow\ETL\Rows::trusted($rows->schema(), [...$rows->all(), row(['id' => 101, 'name' => 'x'])]); - -$cycle = static function () use ($rows, $refused, $schemaBody, $schema): void { - $native = new RustFloeEncoderNative(); - $native->encodeFrames($rows, $schemaBody, $schema); - - try { - $native->encodeFrames($refused, $schemaBody, $schema); - } catch (Flow\Floe\Exception\ExtensionException) { - } -}; - -for ($i = 0; $i < 10; $i++) { - $cycle(); -} -gc_collect_cycles(); -$baseline = memory_get_usage(false); - -for ($i = 0; $i < 100; $i++) { - $cycle(); -} -gc_collect_cycles(); - -var_dump(memory_get_usage(false) <= $baseline); -?> ---EXPECT-- -bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/061_date_iso_fast_path.phpt b/src/extension/flow-php-ext/tests/phpt/061_date_iso_fast_path.phpt deleted file mode 100644 index b29f1556e9..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/061_date_iso_fast_path.phpt +++ /dev/null @@ -1,114 +0,0 @@ ---TEST-- -ISO date strings: both hydrators read them in the column zone - midnight UTC for date, the declared zone for datetime - whatever date.timezone says ---SKIPIF-- - ---FILE-- - $value, 'at' => $value, 'at_scl' => $value])]; - $expected = serialize(new DateTimeImmutable($value, new DateTimeZone('UTC'))); - $expectedScl = serialize(new DateTimeImmutable($value, new DateTimeZone('America/Santiago'))); - $phpRow = $php->hydrate($batch, $schema)->first(); - $nativeRow = $native->hydrate($batch, $schema)->first(); - - printf( - "%-14s %s %s date php:%s native:%s datetime php:%s native:%s scl %s php:%s native:%s\n", - json_encode($value), - $nativeRow->get('on')->format('Y-m-d H:i:s'), - $nativeRow->get('on')->getTimezone()->getName(), - serialize($phpRow->get('on')) === $expected ? 'yes' : 'NO', - serialize($nativeRow->get('on')) === $expected ? 'yes' : 'NO', - serialize($phpRow->get('at')) === $expected ? 'yes' : 'NO', - serialize($nativeRow->get('at')) === $expected ? 'yes' : 'NO', - $nativeRow->get('at_scl')->format('Y-m-d H:i:s'), - serialize($phpRow->get('at_scl')) === $expectedScl ? 'yes' : 'NO', - serialize($nativeRow->get('at_scl')) === $expectedScl ? 'yes' : 'NO', - ); - } -} - -foreach (['2026-02-30', '2026-13-01', '0000-01-01'] as $value) { - foreach (['on' => date_schema('on'), 'at' => datetime_schema('at')] as $column => $definition) { - $batch = [new RawRowValues([$column => $value])]; - - foreach (['php' => $php, 'native' => $native] as $label => $hydrator) { - try { - $hydrator->hydrate($batch, schema($definition)); - echo "{$label} {$column} {$value}: FAIL no exception\n"; - } catch (Throwable $e) { - echo "{$label} {$column} {$value}: ", $e::class, "\n"; - } - } - } -} - -$halfPastMidnight = new DateTimeImmutable('2026-01-02 00:00:00.5', new DateTimeZone('UTC')); - -foreach (['php' => $php, 'native' => $native] as $label => $hydrator) { - echo $label, ' on 00:00:00.5: ', $hydrator->hydrate([new RawRowValues(['on' => $halfPastMidnight])], schema(date_schema('on')))->first()->get('on')->format('Y-m-d H:i:s.u e'), "\n"; -} -?> ---EXPECT-- -date.timezone UTC -"2026-01-02" 2026-01-02 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-01-02 00:00:00 php:yes native:yes -"2024-02-29" 2024-02-29 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2024-02-29 00:00:00 php:yes native:yes -"2026-01-02\n" 2026-01-02 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-01-02 00:00:00 php:yes native:yes -"0001-01-01" 0001-01-01 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 0001-01-01 00:00:00 php:yes native:yes -"9999-12-31" 9999-12-31 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 9999-12-31 00:00:00 php:yes native:yes -"2026-09-06" 2026-09-06 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-09-06 01:00:00 php:yes native:yes -date.timezone Europe/Warsaw -"2026-01-02" 2026-01-02 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-01-02 00:00:00 php:yes native:yes -"2024-02-29" 2024-02-29 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2024-02-29 00:00:00 php:yes native:yes -"2026-01-02\n" 2026-01-02 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-01-02 00:00:00 php:yes native:yes -"0001-01-01" 0001-01-01 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 0001-01-01 00:00:00 php:yes native:yes -"9999-12-31" 9999-12-31 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 9999-12-31 00:00:00 php:yes native:yes -"2026-09-06" 2026-09-06 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-09-06 01:00:00 php:yes native:yes -date.timezone America/Santiago -"2026-01-02" 2026-01-02 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-01-02 00:00:00 php:yes native:yes -"2024-02-29" 2024-02-29 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2024-02-29 00:00:00 php:yes native:yes -"2026-01-02\n" 2026-01-02 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-01-02 00:00:00 php:yes native:yes -"0001-01-01" 0001-01-01 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 0001-01-01 00:00:00 php:yes native:yes -"9999-12-31" 9999-12-31 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 9999-12-31 00:00:00 php:yes native:yes -"2026-09-06" 2026-09-06 00:00:00 UTC date php:yes native:yes datetime php:yes native:yes scl 2026-09-06 01:00:00 php:yes native:yes -php on 2026-02-30: Flow\ETL\Exception\SchemaMismatchException -native on 2026-02-30: Flow\ETL\Exception\SchemaMismatchException -php at 2026-02-30: Flow\ETL\Exception\SchemaMismatchException -native at 2026-02-30: Flow\ETL\Exception\SchemaMismatchException -php on 2026-13-01: Flow\ETL\Exception\SchemaMismatchException -native on 2026-13-01: Flow\ETL\Exception\SchemaMismatchException -php at 2026-13-01: Flow\ETL\Exception\SchemaMismatchException -native at 2026-13-01: Flow\ETL\Exception\SchemaMismatchException -php on 0000-01-01: Flow\ETL\Exception\SchemaMismatchException -native on 0000-01-01: Flow\ETL\Exception\SchemaMismatchException -php at 0000-01-01: Flow\ETL\Exception\SchemaMismatchException -native at 0000-01-01: Flow\ETL\Exception\SchemaMismatchException -php on 00:00:00.5: 2026-01-02 00:00:00.000000 UTC -native on 00:00:00.5: 2026-01-02 00:00:00.000000 UTC diff --git a/src/extension/flow-php-ext/tests/phpt/062_datetime_zone_version_skew.phpt b/src/extension/flow-php-ext/tests/phpt/062_datetime_zone_version_skew.phpt deleted file mode 100644 index 8eab94d441..0000000000 --- a/src/extension/flow-php-ext/tests/phpt/062_datetime_zone_version_skew.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -datetime column zones: the capability marker, and a zone-less datetime from an older flow-php/etl keeps each stored zone ---SKIPIF-- - ---FILE-- -datetimeZones()); -var_dump((new RustRowHydratorNative())->datetimeZones()); - -$bodies = (new PhpFloeEncoder(schema(datetime_schema('at'))))->encode([ - new TypedRowValues(['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('Europe/Warsaw'))], ['at' => type_datetime()]), -]); -$zoneless = '[{"ref":"at","type":{"type":"datetime"},"nullable":false,"metadata":[]}]'; -$zoned = json_encode(schema(datetime_schema('at'))->normalize(), JSON_THROW_ON_ERROR); - -echo 'zone-less datetime: ', (new RustFloeEncoderNative())->decode($bodies, $zoneless)[0]->values['at']->format('Y-m-d H:i:s e'), "\n"; -echo 'datetime: ', (new RustFloeEncoderNative())->decode($bodies, $zoned)[0]->values['at']->format('Y-m-d H:i:s e'), "\n"; -?> ---EXPECT-- -bool(true) -bool(true) -zone-less datetime: 2026-01-02 03:04:05 Europe/Warsaw -datetime: 2026-01-02 02:04:05 UTC diff --git a/src/extension/flow-php-ext/tests/phpt/bootstrap.php b/src/extension/flow-php-ext/tests/phpt/bootstrap.php index 59fa05318c..4ca412d665 100644 --- a/src/extension/flow-php-ext/tests/phpt/bootstrap.php +++ b/src/extension/flow-php-ext/tests/phpt/bootstrap.php @@ -5,147 +5,12 @@ require __DIR__ . '/../../../../../vendor/autoload.php'; use Flow\ETL\Row; -use Flow\ETL\Row\NativeRowHydrator; -use Flow\ETL\Row\PhpRowHydrator; -use Flow\ETL\Rows; -use Flow\Floe\Format; -use Flow\Floe\NativeFloeEncoder; -use Flow\Floe\PhpFloeEncoder; - -/** - * In-memory marker for the schema-carrying entry in the reference frame lists - * below. The Floe format stores the schema in the footer, not in a frame; this - * scaffold threads the schema through the frame list to drive the encoders. - */ -const SCHEMA_ENTRY = 0x01; - -/** - * Pure-PHP reference framing built from the Floe encoder primitives: a write - * session carries one schema, so the whole Rows is framed as a single schema - * entry (its union) followed by one ROW frame per row. - * - * @return array - */ -function php_frames(Rows $rows): array -{ - if ($rows->count() === 0) { - return []; - } - - $hydrator = new PhpRowHydrator(); - $schemaBody = json_encode($rows->schema()->normalize(), JSON_THROW_ON_ERROR); - $encoder = new PhpFloeEncoder(Flow\ETL\DSL\schema_from_json($schemaBody)); - - $frames = [['type' => SCHEMA_ENTRY, 'body' => $schemaBody]]; - - foreach ($rows->all() as $row) { - $frames[] = [ - 'type' => Format::FRAME_ROW, - 'body' => $encoder->encode($hydrator->dehydrate(new Rows($rows->schema(), $row)))[0], - ]; - } - - return $frames; -} - -/** - * Native counterpart of php_frames(): identical single-schema framing (PHP owns - * it), ROW bodies produced by NativeFloeEncoder. Compared against php_frames() - * to prove the native encode is byte-identical to the pure-PHP encode. - * - * @return array - */ -function ext_frames(Rows $rows): array -{ - if ($rows->count() === 0) { - return []; - } - - $hydrator = new NativeRowHydrator(); - $schemaBody = json_encode($rows->schema()->normalize(), JSON_THROW_ON_ERROR); - $encoder = new NativeFloeEncoder(Flow\ETL\DSL\schema_from_json($schemaBody)); - - $frames = [['type' => SCHEMA_ENTRY, 'body' => $schemaBody]]; - - foreach ($rows->all() as $row) { - $frames[] = [ - 'type' => Format::FRAME_ROW, - 'body' => $encoder->encode($hydrator->dehydrate(new Rows($rows->schema(), $row)))[0], - ]; - } - - return $frames; -} - -/** - * Pure-PHP reference decode of frame bodies via the Floe encoder and the row - * hydrator - the byte-for-byte oracle the extension is compared against. - * - * @param array $frames - * - * @return array - */ -function php_decode_frames(array $frames): array -{ - $hydrator = new PhpRowHydrator(); - $encoder = null; - $schema = null; - $rows = []; - - foreach ($frames as $frame) { - if ($frame['type'] === SCHEMA_ENTRY) { - $schema = Flow\ETL\DSL\schema_from_json($frame['body']); - $encoder = new PhpFloeEncoder($schema); - } elseif ($schema === null || $encoder === null) { - throw new RuntimeException('row frame before any schema entry'); - } else { - foreach ($hydrator->hydrate($encoder->decode([$frame['body']]), $schema)->all() as $row) { - $rows[] = $row; - } - } - } - - return $rows; -} - -/** - * Drives the native two-layer pipeline over frame bodies, rebinding the schema - * per schema entry (mirrors how FloeStreamReader sources the schema). - * - * @param array $frames - * - * @return array - */ -function ext_decode_frames(array $frames): array -{ - $hydrator = new NativeRowHydrator(); - $encoder = null; - $schema = null; - $rows = []; - - foreach ($frames as $frame) { - if ($frame['type'] === SCHEMA_ENTRY) { - $schema = Flow\ETL\DSL\schema_from_json($frame['body']); - $encoder = new NativeFloeEncoder($schema); - } elseif ($schema === null || $encoder === null) { - throw new RuntimeException('row frame before any schema entry'); - } else { - foreach ($hydrator->hydrate($encoder->decode([$frame['body']]), $schema)->all() as $row) { - $rows[] = $row; - } - } - } - - return $rows; -} /** * Byte-identical comparison against the pure-PHP decoder on fresh objects. - * Row::isEqual is intentionally avoided before serialize() - it memoizes - * schema state asymmetrically and breaks byte-level comparison. * - * @param array $expected - * @param array $actual + * @param list $expected + * @param list $actual */ function assert_rows_identical(array $expected, array $actual): void { @@ -156,7 +21,7 @@ function assert_rows_identical(array $expected, array $actual): void } foreach ($expected as $i => $row) { - if (serialize($row) !== serialize($actual[$i])) { + if (serialize($row->values()) !== serialize($actual[$i]->values())) { echo "FAIL: row {$i} differs from the PHP decoder output\n"; return; diff --git a/src/lib/types/src/Flow/Types/Type/Comparator.php b/src/lib/types/src/Flow/Types/Type/Comparator.php index f544e9e58f..e5bec56122 100644 --- a/src/lib/types/src/Flow/Types/Type/Comparator.php +++ b/src/lib/types/src/Flow/Types/Type/Comparator.php @@ -24,12 +24,8 @@ use function Flow\Types\DSL\type_instance_of; use function in_array; -final class Comparator +final readonly class Comparator { - public function __construct( - private StructureComparison $structures = new StructureComparison(), - ) {} - /** * @param Type $left * @param Type $right @@ -125,7 +121,7 @@ public function equals(Type $left, Type $right): bool } if ($left instanceof StructureType && $right instanceof StructureType) { - return $this->structures->identical($left, $right, $this); + return (new StructureComparison())->identical($left, $right, $this); } return $left->toString() === $right->toString(); diff --git a/src/lib/types/src/Flow/Types/Type/Logical/DateType.php b/src/lib/types/src/Flow/Types/Type/Logical/DateType.php index 6bc4afc991..682f8fa2d2 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/DateType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/DateType.php @@ -98,7 +98,11 @@ public function cast(mixed $value): DateTimeInterface public function isValid(mixed $value): bool { - return $value instanceof DateTimeInterface && $value->format('H:i:s.u') === '00:00:00.000000'; + return ( + $value instanceof DateTimeInterface + && $value->getOffset() === 0 + && $value->format('H:i:s.u') === '00:00:00.000000' + ); } public function normalize(): array diff --git a/src/lib/types/src/Flow/Types/Type/Logical/StructureType.php b/src/lib/types/src/Flow/Types/Type/Logical/StructureType.php index 760b4dd1d0..8148d5ab21 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/StructureType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/StructureType.php @@ -44,7 +44,7 @@ final readonly class StructureType implements Type { /** - * @var list>> + * @var non-empty-list>> */ private array $elements; @@ -220,7 +220,7 @@ public function element(int|string $name): ?StructureElement } /** - * @return list>> + * @return non-empty-list>> */ public function elements(): array { diff --git a/src/lib/types/src/Flow/Types/Value/Uuid.php b/src/lib/types/src/Flow/Types/Value/Uuid.php index ca29283897..18fe95cf63 100644 --- a/src/lib/types/src/Flow/Types/Value/Uuid.php +++ b/src/lib/types/src/Flow/Types/Value/Uuid.php @@ -7,12 +7,16 @@ use Flow\Types\Exception\InvalidArgumentException; use Flow\Types\Exception\RuntimeException; use Ramsey\Uuid\UuidInterface; +use ReflectionClass; use Stringable; use Symfony\Component\Uid\Uuid as SymfonyUuid; +use function bin2hex; use function is_string; use function preg_match; +use function sprintf; use function strlen; +use function substr; final readonly class Uuid implements Stringable { @@ -42,6 +46,30 @@ public function __construct(string|UuidInterface|SymfonyUuid $value) } } + /** + * @throws InvalidArgumentException + */ + public static function fromBytes(string $bytes): self + { + if (strlen($bytes) !== 16) { + throw new InvalidArgumentException('Uuid::fromBytes() expects 16 bytes, got ' . strlen($bytes)); + } + + $hex = bin2hex($bytes); + $uuid = (new ReflectionClass(self::class))->newInstanceWithoutConstructor(); + // @mago-ignore analysis:invalid-property-write + $uuid->value = sprintf( + '%s-%s-%s-%s-%s', + substr($hex, 0, 8), + substr($hex, 8, 4), + substr($hex, 12, 4), + substr($hex, 16, 4), + substr($hex, 20), + ); + + return $uuid; + } + public static function fromString(string $value): self { return new self($value); diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTypeTest.php index 39a77a6301..6984c2523a 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTypeTest.php @@ -123,6 +123,16 @@ public static function is_valid_data_provider(): Generator 'expected' => true, ]; + yield 'midnight outside UTC is not a date' => [ + 'value' => new DateTimeImmutable('2026-01-01 00:00:00', new DateTimeZone('Europe/Warsaw')), + 'expected' => false, + ]; + + yield 'midnight in UTC is a date' => [ + 'value' => new DateTimeImmutable('2026-01-01 00:00:00', new DateTimeZone('UTC')), + 'expected' => true, + ]; + yield 'invalid DateTimeImmutable with time' => [ 'value' => new DateTimeImmutable(), 'expected' => false, diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Value/UuidTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Value/UuidTest.php index 376e9c03dd..2ec7fc6ed6 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Value/UuidTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Value/UuidTest.php @@ -10,8 +10,35 @@ use Ramsey\Uuid\Uuid as RamseyUuid; use Symfony\Component\Uid\Uuid as SymfonyUuid; +use function hex2bin; +use function str_repeat; + final class UuidTest extends TestCase { + public function test_from_bytes_builds_canonical_lowercase_text(): void + { + $uuid = Uuid::fromBytes((string) hex2bin('6C2F1D4E8B3A4C5D9E6F0A1B2C3D4E5F')); + + static::assertSame('6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f', $uuid->toString()); + static::assertEquals(new Uuid('6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f'), $uuid); + } + + public function test_from_bytes_refuses_fifteen_bytes(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Uuid::fromBytes() expects 16 bytes, got 15'); + + Uuid::fromBytes(str_repeat('a', 15)); + } + + public function test_from_bytes_refuses_seventeen_bytes(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Uuid::fromBytes() expects 16 bytes, got 17'); + + Uuid::fromBytes(str_repeat('a', 17)); + } + public function test_construct_with_invalid_string_uuid_throws_exception(): void { $this->expectException(InvalidArgumentException::class); diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json index 2c3197ee47..d16f2abc5c 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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":576,"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":582,"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":591,"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":601,"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":608,"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":614,"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":626,"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":632,"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":638,"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":644,"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":650,"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":656,"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":665,"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":671,"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":680,"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":686,"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":693,"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":699,"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":705,"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":714,"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":720,"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":731,"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":740,"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":749,"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":755,"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":764,"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":774,"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":783,"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":789,"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":795,"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":803,"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":816,"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":822,"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":828,"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":838,"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":847,"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":856,"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":862,"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":875,"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":884,"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":893,"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":899,"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":908,"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":914,"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":920,"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":926,"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":932,"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":944,"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":971,"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":1001,"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":1007,"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":1013,"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":1019,"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":1025,"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":1031,"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":1037,"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":1043,"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":1049,"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":1055,"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":1061,"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":1067,"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":"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":1073,"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":1079,"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":1085,"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":1091,"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":1101,"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":1111,"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":1121,"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":1131,"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":1141,"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":1147,"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":1156,"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":1165,"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":1179,"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":1205,"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":1242,"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":1248,"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":1254,"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":1260,"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":1266,"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":1272,"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":1278,"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":1284,"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":1290,"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":1296,"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":1302,"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":1308,"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":1314,"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":1320,"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":1326,"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":1332,"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":1338,"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":1344,"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":1350,"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":1356,"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":1362,"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":1373,"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":1382,"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":1391,"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":1403,"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":1413,"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":1422,"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":1428,"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":1434,"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":1443,"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":1456,"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":1465,"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":1471,"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":1480,"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":1486,"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":1492,"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":1498,"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":1512,"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":1526,"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":1544,"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":1550,"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":1556,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1566,"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":1572,"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":1578,"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":1584,"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":1590,"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":1596,"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":1602,"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":1615,"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":1626,"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":1632,"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":1645,"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":1678,"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":1730,"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":1736,"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":1742,"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":1748,"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":1754,"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":1760,"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":1766,"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":1772,"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":1778,"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":1784,"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":1793,"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":1803,"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":1809,"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":1818,"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":1828,"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":1834,"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":1843,"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":1849,"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":1858,"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":1864,"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":1873,"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":1879,"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":1885,"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":1891,"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":1897,"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":1903,"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":1909,"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":1920,"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":1926,"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":1935,"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":1946,"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":1957,"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":1967,"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":2001,"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":2009,"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":2018,"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":2026,"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":2043,"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":2060,"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":2077,"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":2083,"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":2089,"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":2099,"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":2108,"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":2114,"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":2120,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":576,"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":582,"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":591,"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":601,"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":608,"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":614,"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":626,"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":632,"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":638,"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":644,"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":650,"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":656,"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":665,"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":671,"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":680,"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":686,"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":693,"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":699,"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":705,"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":714,"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":720,"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":731,"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":740,"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":749,"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":755,"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":764,"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":774,"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":783,"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":789,"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":795,"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":803,"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":816,"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":822,"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":828,"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":838,"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":847,"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":856,"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":862,"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":875,"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":884,"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":893,"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":899,"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":908,"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":914,"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":920,"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":926,"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":932,"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":944,"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":971,"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":1001,"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":1007,"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":1013,"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":1019,"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":1025,"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":1031,"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":1037,"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":1043,"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":1049,"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":1055,"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":1061,"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":1067,"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":"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":1073,"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":1079,"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":1085,"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":1091,"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":1101,"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":1111,"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":1121,"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":1131,"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":1141,"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":1147,"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":1156,"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":1165,"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":1179,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."},{"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":1205,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."}],"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":1242,"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":1248,"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":1254,"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":1260,"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":1266,"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":1272,"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":1278,"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":1284,"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":1290,"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":1296,"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":1302,"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":1308,"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":1314,"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":1320,"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":1326,"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":1332,"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":1338,"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":1344,"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":1350,"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":1356,"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":1362,"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":1373,"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":1382,"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":1391,"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":1403,"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":1413,"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":1422,"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":1428,"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":1434,"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":1443,"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":1456,"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":1465,"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":1471,"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":1480,"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":1486,"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":1492,"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":1498,"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":1512,"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":1526,"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":1544,"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":1550,"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":1556,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1566,"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":1572,"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":1578,"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":1584,"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":1590,"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":1596,"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":1602,"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":1615,"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":1626,"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":1632,"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":1645,"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":1678,"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":1730,"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":1736,"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":1742,"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":1748,"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":1754,"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":1760,"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":1766,"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":1772,"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":1778,"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":1784,"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":1793,"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":1803,"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":1809,"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":1818,"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":1828,"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":1834,"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":1843,"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":1849,"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":1858,"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":1864,"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":1873,"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":1879,"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":1885,"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":1891,"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":1897,"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":1903,"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":1909,"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":1920,"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":1926,"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":1935,"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":1946,"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":1957,"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":1967,"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":2001,"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":2009,"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":2018,"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":2026,"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":2043,"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":2060,"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":2077,"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":2083,"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":2089,"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":2099,"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":2108,"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":2114,"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":2120,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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 From f62db322e86242ae1ce645640707a1a5f697ac7e Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sun, 27 Sep 2026 15:05:41 +0200 Subject: [PATCH 02/21] feat(flow-php/etl): remove row(), InferredBatch and DataFrame::getEach() - array_to_row(s) refuse keys the schema does not declare - extractors project declared columns through DeclaredColumns - every row() call moves to a declared schema - docs, upgrading entry, completers and playground phar updated --- benchmarks/src/Schema/RowsSchemaScenario.php | 7 +- documentation/components/adapters/csv.md | 6 +- documentation/components/adapters/logger.md | 4 +- documentation/components/adapters/text.md | 8 +- .../components/core/building-blocks.md | 24 +- documentation/components/core/core.md | 4 +- .../components/core/data-retrieval.md | 11 - documentation/upgrading.md | 18 +- .../CSVExtractorBatchContractTest.php | 8 +- .../Adapter/CSV/Tests/Integration/CSVTest.php | 8 +- .../Integration/DbalDataFrameFactoryTest.php | 19 +- .../Dialects/MySQLTransactionSinkTest.php | 20 +- .../PostgreSQLTransactionSinkTest.php | 20 +- .../Dialects/SqliteTransactionSinkTest.php | 20 +- .../Tests/Integration/ExcelExtractorTest.php | 18 +- .../Tests/Integration/ExcelLoaderTest.php | 133 +++-- .../Function/IsValidExcelSheetNameTest.php | 9 +- .../Tests/Unit/GoogleSheetExtractorTest.php | 12 +- .../JSON/Tests/Integration/JsonTest.php | 6 +- .../Logger/Tests/Unit/PsrLoggerLoaderTest.php | 5 +- .../Integration/ParquetExtractorTest.php | 23 +- .../Parquet/Tests/Integration/ParquetTest.php | 37 +- ...ostgreSqlLoaderAllTypesIntegrationTest.php | 83 ++- .../Tests/Unit/PostgreSqlLoaderTest.php | 10 +- .../Seal/Tests/Integration/SealLoaderTest.php | 36 +- .../Seal/Tests/Unit/SealLoaderTest.php | 14 +- .../TextExtractorBatchContractTest.php | 10 +- .../Text/Tests/Integration/TextTest.php | 14 +- .../Response/FlowBufferedResponseTest.php | 8 +- .../Unit/Loader/ProgressBarLoaderTest.php | 15 +- .../etl/src/Flow/ETL/Bucketing/Bucket.php | 6 +- .../etl/src/Flow/ETL/Cache/CacheIndex.php | 9 +- src/core/etl/src/Flow/ETL/DSL/functions.php | 38 +- src/core/etl/src/Flow/ETL/DataFrame.php | 22 - .../Flow/ETL/Extractor/DataFrameExtractor.php | 7 +- .../src/Flow/ETL/Extractor/InferredRows.php | 3 +- .../ETL/Filesystem/ScalarFunctionFilter.php | 8 +- .../Flow/ETL/Processor/CountingProcessor.php | 5 +- .../etl/src/Flow/ETL/Row/DeclaredColumns.php | 38 ++ .../etl/src/Flow/ETL/Row/InferredBatch.php | 68 --- .../Flow/ETL/Tests/Context/RankingContext.php | 31 +- .../Flow/ETL/Tests/Context/ScoredRows.php | 7 +- .../AddStampToStringEntryTransformer.php | 9 +- .../Flow/ETL/Tests/Double/FakeExtractor.php | 47 +- .../ThrowingAfterFirstBatchExtractor.php | 5 +- .../ETL/Tests/Fixtures/with-dataframe.php | 13 +- .../Storage/FilesystemBucketsTest.php | 85 +-- .../Bucketing/Storage/PSRCacheBucketsTest.php | 7 +- .../Tests/Integration/Cache/CacheTestCase.php | 24 +- .../Integration/Cache/FilesystemCacheTest.php | 20 +- .../Cache/PSRSimpleFilesystemCacheTest.php | 9 +- .../Bucketing/BucketingConfigBuilderTest.php | 5 +- .../DataFrame/AlgorithmOverrideTest.php | 7 +- .../DataFrame/ConfigBuilderTest.php | 5 +- .../Integration/DataFrame/DisplayTest.php | 112 ++-- .../Integration/DataFrame/GroupByTest.php | 235 ++++---- .../Integration/DataFrame/JoinCrossTest.php | 20 +- .../Integration/DataFrame/JoinEachTest.php | 56 +- .../DataFrame/JoinEmptySideTest.php | 8 +- .../Tests/Integration/DataFrame/JoinTest.php | 254 ++++---- .../Tests/Integration/DataFrame/LimitTest.php | 40 +- .../Tests/Integration/DataFrame/MathTest.php | 50 +- .../Integration/DataFrame/OffsetTest.php | 32 +- .../DataFrame/PartitioningTest.php | 17 +- .../Integration/DataFrame/PlanBindTest.php | 11 +- .../Integration/DataFrame/RenameTest.php | 147 ++--- .../Integration/DataFrame/SinglePlanTest.php | 5 +- .../SinkRootBlockingOperationsTest.php | 8 +- .../Integration/DataFrame/SinkRootTest.php | 5 +- .../Function/ArrayKeysStyleConvertTest.php | 8 +- .../Function/DOMElementAttributeValueTest.php | 24 +- .../Function/DOMElementNextSiblingTest.php | 31 +- .../Function/DOMElementParentTest.php | 16 +- .../DOMElementPreviousSiblingTest.php | 31 +- .../Function/DOMElementValueTest.php | 28 +- .../Integration/Function/EnumNameTest.php | 28 +- .../Integration/Function/EnumValueTest.php | 35 +- .../Function/HTMLQuerySelectorAllTest.php | 7 +- .../Function/HTMLQuerySelectorTest.php | 7 +- .../Integration/Function/MatchCasesTest.php | 18 +- .../Integration/Pipeline/PipelineTest.php | 7 +- .../ETL/Tests/Mother/ListColumnsMother.php | 6 +- .../Tests/Mother/PartitionedSourceMother.php | 8 +- .../Flow/ETL/Tests/Mother/RowsMother.php | 47 +- .../Flow/ETL/Tests/Mother/SinkFeedMother.php | 5 +- .../Tests/Unit/Bucketing/BucketRunTest.php | 11 +- .../ETL/Tests/Unit/Bucketing/BucketsTest.php | 13 +- .../Unit/Bucketing/HashBucketingTest.php | 34 +- .../Tests/Unit/Bucketing/KeyGroupingTest.php | 49 +- .../Tests/Unit/Bucketing/KeyValuesTest.php | 23 +- .../Unit/Bucketing/SortedRunBucketingTest.php | 25 +- .../Bucketing/Storage/MemoryBucketsTest.php | 13 +- .../Bucketing/Storage/PSRCacheBucketsTest.php | 28 +- .../ETL/Tests/Unit/Cache/CacheIndexTest.php | 18 +- .../Cache/Implementation/ApcuCacheTest.php | 26 +- .../Implementation/TraceableCacheTest.php | 10 +- .../Unit/Comparator/RowComparatorTest.php | 24 +- .../Unit/Comparator/RowsComparatorTest.php | 30 +- .../Config/Telemetry/TelemetryContextTest.php | 22 +- .../Unit/Constraint/SortedConstraintTest.php | 137 +++-- .../Unit/Constraint/UniqueConstraintTest.php | 29 +- .../Flow/ETL/Tests/Unit/DataFrameTest.php | 346 +++++------ .../ETL/Tests/Unit/ETLErrorHandlingTest.php | 27 +- .../Unit/Executor/OffsetPipelineTest.php | 112 ++-- .../Tests/Unit/Executor/SourceRowsTest.php | 5 +- .../Unit/Executor/StatisticsCollectorTest.php | 29 +- .../Executor/WindowFunctionPipelineTest.php | 31 +- .../Flow/ETL/Tests/Unit/ExecutorTest.php | 12 +- .../Unit/Extractor/BatchByExtractorTest.php | 70 +-- .../Unit/Extractor/BatchExtractorTest.php | 12 +- .../Unit/Extractor/ChainExtractorTest.php | 20 +- .../Extractor/CollectingExtractorTest.php | 13 +- .../Unit/Extractor/DataFrameExtractorTest.php | 65 +- .../Unit/Extractor/FeedExtractorTest.php | 15 +- .../Unit/Extractor/FileConstantsTest.php | 22 +- .../Tests/Unit/Extractor/InferredRowsTest.php | 12 + .../Unit/Extractor/MemoryExtractorTest.php | 21 +- .../Unit/Extractor/PartitionColumnsTest.php | 35 +- .../Unit/Extractor/RowsExtractorTest.php | 27 +- .../Unit/Extractor/SequenceExtractorTest.php | 72 ++- .../Filesystem/ScalarFunctionFilterTest.php | 10 + .../Unit/Formatter/ASCII/ASCIIBodyTest.php | 8 +- .../Unit/Formatter/ASCII/ASCIIHeadersTest.php | 8 +- .../Tests/Unit/Formatter/ASCIITableTest.php | 64 +- .../Flow/ETL/Tests/Unit/Function/AllTest.php | 22 +- .../Flow/ETL/Tests/Unit/Function/AnyTest.php | 20 +- .../ETL/Tests/Unit/Function/AppendTest.php | 39 +- .../Tests/Unit/Function/ArrayExpandTest.php | 35 +- .../Tests/Unit/Function/ArrayFilterTest.php | 44 +- .../Unit/Function/ArrayGetCollectionTest.php | 68 ++- .../ETL/Tests/Unit/Function/ArrayGetTest.php | 47 +- .../ETL/Tests/Unit/Function/ArrayKeepTest.php | 42 +- .../Unit/Function/ArrayKeyRenameTest.php | 61 +- .../Function/ArrayKeysStyleConverterTest.php | 25 +- .../ETL/Tests/Unit/Function/ArrayKeysTest.php | 16 +- .../Function/ArrayMergeCollectionTest.php | 20 +- .../Tests/Unit/Function/ArrayMergeTest.php | 53 +- .../Tests/Unit/Function/ArrayReverseTest.php | 21 +- .../ETL/Tests/Unit/Function/ArraySortTest.php | 26 +- .../Tests/Unit/Function/ArrayUnpackTest.php | 47 +- .../Tests/Unit/Function/ArrayValuesTest.php | 17 +- .../ETL/Tests/Unit/Function/AsciiTest.php | 12 +- .../ETL/Tests/Unit/Function/AverageTest.php | 57 +- .../ETL/Tests/Unit/Function/BetweenTest.php | 68 ++- .../Unit/Function/BinaryComparisonsTest.php | 140 +++-- .../Tests/Unit/Function/BinaryLengthTest.php | 24 +- .../Tests/Unit/Function/CallUserFuncTest.php | 30 +- .../Tests/Unit/Function/CapitalizeTest.php | 6 +- .../Flow/ETL/Tests/Unit/Function/CastTest.php | 103 +++- .../ETL/Tests/Unit/Function/ChunkTest.php | 50 +- .../ETL/Tests/Unit/Function/CoalesceTest.php | 41 +- .../Unit/Function/CodePointLengthTest.php | 16 +- .../Unit/Function/CollapseWhitespaceTest.php | 40 +- .../ETL/Tests/Unit/Function/CollectTest.php | 11 +- .../Tests/Unit/Function/CollectUniqueTest.php | 12 +- .../ETL/Tests/Unit/Function/CombineTest.php | 12 +- .../ETL/Tests/Unit/Function/ConcatTest.php | 30 +- .../Unit/Function/ConcatWithSeparatorTest.php | 33 +- .../ETL/Tests/Unit/Function/CountTest.php | 68 ++- .../Function/DOMElementAttributeValueTest.php | 21 +- .../DOMElementAttributesCountTest.php | 29 +- .../Unit/Function/DOMElementNamespaceTest.php | 16 +- .../Unit/Function/DOMElementParentTest.php | 36 +- .../Unit/Function/DOMElementValueTest.php | 21 +- .../Unit/Function/DateTimeFormatTest.php | 22 +- .../ETL/Tests/Unit/Function/DenseRankTest.php | 5 +- .../ETL/Tests/Unit/Function/EnsureEndTest.php | 42 +- .../Tests/Unit/Function/EnsureStartTest.php | 40 +- .../ETL/Tests/Unit/Function/EnumNameTest.php | 17 +- .../ETL/Tests/Unit/Function/EnumValueTest.php | 15 +- .../ETL/Tests/Unit/Function/EqualsTest.php | 35 +- .../ETL/Tests/Unit/Function/ExistsTest.php | 25 +- .../ETL/Tests/Unit/Function/FirstTest.php | 15 +- .../Unit/Function/GreaterThanEqualTest.php | 123 +++- .../Tests/Unit/Function/GreaterThanTest.php | 129 +++- .../ETL/Tests/Unit/Function/GreatestTest.php | 16 +- .../Function/HTMLQuerySelectorAllTest.php | 21 +- .../Unit/Function/HTMLQuerySelectorTest.php | 21 +- .../Flow/ETL/Tests/Unit/Function/HashTest.php | 28 +- .../Tests/Unit/Function/IndexOfLastTest.php | 37 +- .../ETL/Tests/Unit/Function/IndexOfTest.php | 34 +- .../ETL/Tests/Unit/Function/IsEmptyTest.php | 22 +- .../Flow/ETL/Tests/Unit/Function/IsInTest.php | 30 +- .../ETL/Tests/Unit/Function/IsUtf8Test.php | 20 +- .../Tests/Unit/Function/JsonDecodeTest.php | 17 +- .../Tests/Unit/Function/JsonEncodeTest.php | 28 +- .../Flow/ETL/Tests/Unit/Function/LastTest.php | 15 +- .../ETL/Tests/Unit/Function/LeastTest.php | 12 +- .../Tests/Unit/Function/LessThanEqualTest.php | 125 +++- .../ETL/Tests/Unit/Function/LessThanTest.php | 129 +++- .../Tests/Unit/Function/ListSelectTest.php | 19 +- .../Unit/Function/LogicalFunctionsTest.php | 12 +- .../Tests/Unit/Function/MatchCasesTest.php | 20 +- .../Flow/ETL/Tests/Unit/Function/MathTest.php | 21 +- .../Flow/ETL/Tests/Unit/Function/MaxTest.php | 59 +- .../Flow/ETL/Tests/Unit/Function/MinTest.php | 61 +- .../Unit/Function/ModifyDateTimeTest.php | 15 +- .../Flow/ETL/Tests/Unit/Function/NotTest.php | 28 +- .../Flow/ETL/Tests/Unit/Function/NowTest.php | 18 +- .../Tests/Unit/Function/NumberFormatTest.php | 79 ++- .../ETL/Tests/Unit/Function/OnEachTest.php | 55 +- .../ETL/Tests/Unit/Function/OptionalTest.php | 9 +- .../ETL/Tests/Unit/Function/ParameterTest.php | 139 +++-- .../ETL/Tests/Unit/Function/PowerTest.php | 15 +- .../Tests/Unit/Function/PregReplaceTest.php | 11 +- .../ETL/Tests/Unit/Function/PrependTest.php | 35 +- .../Flow/ETL/Tests/Unit/Function/RankTest.php | 5 +- .../ETL/Tests/Unit/Function/RegexAllTest.php | 11 +- .../Tests/Unit/Function/RegexMatchAllTest.php | 13 +- .../Tests/Unit/Function/RegexMatchTest.php | 11 +- .../Tests/Unit/Function/RegexReplaceTest.php | 12 +- .../ETL/Tests/Unit/Function/RegexTest.php | 11 +- .../ETL/Tests/Unit/Function/RepeatTest.php | 36 +- .../ETL/Tests/Unit/Function/ReverseTest.php | 16 +- .../ETL/Tests/Unit/Function/RoundTest.php | 22 +- .../ETL/Tests/Unit/Function/RowNumberTest.php | 16 +- .../Flow/ETL/Tests/Unit/Function/SameTest.php | 16 +- .../ETL/Tests/Unit/Function/SanitizeTest.php | 19 +- .../Flow/ETL/Tests/Unit/Function/SizeTest.php | 9 +- .../Flow/ETL/Tests/Unit/Function/SlugTest.php | 20 +- .../ETL/Tests/Unit/Function/SplitTest.php | 15 +- .../ETL/Tests/Unit/Function/SprintfTest.php | 7 +- .../ETL/Tests/Unit/Function/StrPadTest.php | 6 +- .../Tests/Unit/Function/StrReplaceTest.php | 10 +- .../Unit/Function/StringAfterLastTest.php | 24 +- .../Tests/Unit/Function/StringAfterTest.php | 32 +- .../Unit/Function/StringAggregateTest.php | 37 +- .../Unit/Function/StringBeforeLastTest.php | 35 +- .../Tests/Unit/Function/StringBeforeTest.php | 43 +- .../Unit/Function/StringContainsAnyTest.php | 45 +- .../Unit/Function/StringEqualsToTest.php | 44 +- .../Tests/Unit/Function/StringFoldTest.php | 10 +- .../Unit/Function/StringMatchAllTest.php | 36 +- .../Tests/Unit/Function/StringMatchTest.php | 32 +- .../Unit/Function/StringNormalizeTest.php | 35 +- .../Tests/Unit/Function/StringStyleTest.php | 24 +- .../Tests/Unit/Function/StringTitleTest.php | 14 +- .../Tests/Unit/Function/StringWidthTest.php | 20 +- .../Unit/Function/StructureSelectTest.php | 24 +- .../ETL/Tests/Unit/Function/StructureTest.php | 66 +- .../Flow/ETL/Tests/Unit/Function/SumTest.php | 143 +++-- .../ETL/Tests/Unit/Function/ToDateTest.php | 18 +- .../Tests/Unit/Function/ToDateTimeTest.php | 46 +- .../ETL/Tests/Unit/Function/ToLowerTest.php | 5 +- .../Tests/Unit/Function/ToTimeZoneTest.php | 14 +- .../ETL/Tests/Unit/Function/ToUpperTest.php | 5 +- .../Flow/ETL/Tests/Unit/Function/TrimTest.php | 12 +- .../ETL/Tests/Unit/Function/TruncateTest.php | 62 +- .../Flow/ETL/Tests/Unit/Function/UlidTest.php | 17 +- .../Tests/Unit/Function/UnicodeLengthTest.php | 16 +- .../Flow/ETL/Tests/Unit/Function/UuidTest.php | 23 +- .../Flow/ETL/Tests/Unit/Function/WhenTest.php | 45 +- .../ETL/Tests/Unit/Function/WordwrapTest.php | 55 +- .../ETL/Tests/Unit/Function/XPathTest.php | 36 +- .../Unit/GroupBy/AggregatedGroupsTest.php | 38 +- .../Unit/GroupBy/BucketAggregationTest.php | 40 +- .../Tests/Unit/GroupBy/GroupByStepsTest.php | 56 +- .../Unit/GroupBy/PivotAggregationTest.php | 18 +- .../Tests/Unit/GroupBy/PivotedTableTest.php | 80 +-- .../tests/Flow/ETL/Tests/Unit/GroupByTest.php | 106 ++-- .../Tests/Unit/Join/Comparison/AllTest.php | 14 +- .../Tests/Unit/Join/Comparison/AnyTest.php | 14 +- .../Tests/Unit/Join/Comparison/EqualTest.php | 47 +- .../Unit/Join/Comparison/IdenticalTest.php | 30 +- .../ETL/Tests/Unit/Join/ExpressionTest.php | 9 +- .../Unit/Join/HashJoin/HashTableTest.php | 48 +- .../Tests/Unit/Join/HashJoin/JoinerTest.php | 195 +++--- .../Unit/Join/HashJoin/RowMergerTest.php | 77 ++- .../ETL/Tests/Unit/Join/JoinShapeTest.php | 10 +- .../ETL/Tests/Unit/Join/JoinStepsTest.php | 4 +- .../ETL/Tests/Unit/Loader/ArrayLoaderTest.php | 13 +- .../Tests/Unit/Loader/MemoryLoaderTest.php | 8 +- .../Tests/Unit/Loader/PartitionRouterTest.php | 26 +- .../Tests/Unit/Loader/RowPartitionsTest.php | 18 +- .../Loader/SchemaValidationLoaderTest.php | 11 +- .../Tests/Unit/Loader/StreamLoaderTest.php | 45 +- .../Rule/CountFromStatisticsTest.php | 11 +- .../Rule/PushFilterIntoSourceTest.php | 5 +- .../Tests/Unit/Planner/NodeTranslatorTest.php | 7 +- .../Unit/Planner/SinkFeedFactoryTest.php | 9 +- .../tests/Flow/ETL/Tests/Unit/PlannerTest.php | 8 +- .../Processor/BatchingByProcessorTest.php | 32 +- .../Unit/Processor/BatchingProcessorTest.php | 40 +- .../Unit/Processor/BucketingProcessorTest.php | 13 +- .../Unit/Processor/CachingProcessorTest.php | 11 +- .../Processor/CollectingProcessorTest.php | 11 +- .../Processor/ConstrainedProcessorTest.php | 9 +- .../Unit/Processor/CountingProcessorTest.php | 10 +- .../GroupByAggregationProcessorTest.php | 36 +- .../Unit/Processor/HashJoinProcessorTest.php | 143 +++-- .../Processor/MemorySortProcessorTest.php | 15 +- .../Unit/Processor/MergeSortProcessorTest.php | 33 +- .../Unit/Processor/OffsetProcessorTest.php | 13 +- .../Unit/Processor/PivotProcessorTest.php | 24 +- .../Processor/RepartitionProcessorTest.php | 8 +- .../Unit/Processor/VoidProcessorTest.php | 7 +- .../Unit/Processor/WindowProcessorTest.php | 125 ++-- .../ETL/Tests/Unit/Row/ArrayToRowTest.php | 39 +- .../Row/Comparator/NativeComparatorTest.php | 14 +- .../Tests/Unit/Row/DeclaredColumnsTest.php | 55 ++ .../ETL/Tests/Unit/Row/InferredBatchTest.php | 112 ---- .../ETL/Tests/Unit/Row/RowsBufferTest.php | 19 +- .../Unit/Row/UnresolvedReferenceTest.php | 19 +- .../etl/tests/Flow/ETL/Tests/Unit/RowTest.php | 64 +- .../ETL/Tests/Unit/Rows/ArrayToRowsTest.php | 72 ++- .../ETL/Tests/Unit/Rows/RowsBuilderTest.php | 35 +- .../Flow/ETL/Tests/Unit/RowsJoinTest.php | 394 ++++++------ .../ETL/Tests/Unit/RowsSerializationTest.php | 62 +- .../tests/Flow/ETL/Tests/Unit/RowsTest.php | 562 +++++++++--------- .../Unit/Sort/Merge/BucketCursorTest.php | 14 +- .../Tests/Unit/Sort/Merge/KWayMergeTest.php | 100 ++-- .../Tests/Unit/Sort/Merge/RowsMinHeapTest.php | 53 +- .../ETL/Tests/Unit/Sort/SortStepsTest.php | 12 +- .../AddRowIndexTransformerTest.php | 20 +- .../CollectReferencesTransformerTest.php | 5 +- .../CrossJoinRowsTransformerTest.php | 22 +- .../Unit/Transformer/DerivedColumnsTest.php | 7 +- .../DropDuplicatesTransformerTest.php | 71 +-- .../DropEntriesTransformerTest.php | 11 +- .../DuplicateRowTransformerTest.php | 83 +-- .../JoinEachRowsTransformerTest.php | 51 +- .../NestedExpandTransformerTest.php | 38 +- .../Unit/Transformer/NestedExpansionTest.php | Bin 6590 -> 6869 bytes .../PruneEntriesTransformerTest.php | 14 +- .../RenameEntryTransformerTest.php | 54 +- .../ScalarFunctionFilterTransformerTest.php | 42 +- .../ScalarFunctionTransformer/MathTest.php | 13 +- .../ScalarFunctionTransformerTest.php | 79 +-- .../SelectEntriesTransformerTest.php | 25 +- .../Transformer/SerializeTransformerTest.php | 44 +- .../SerializedPayloadDecoderTest.php | 30 +- .../UnserializeTransformerTest.php | 136 +++-- .../Unit/Transformer/UntilTransformerTest.php | 44 +- .../Accumulator/AverageAccumulatorTest.php | 33 +- .../Accumulator/CountAccumulatorTest.php | 23 +- .../Window/Accumulator/SumAccumulatorTest.php | 44 +- .../ETL/Tests/Unit/Window/PeerFrameTest.php | 25 +- .../Floe/Tests/Context/FloeFilesContext.php | 7 +- .../Tests/Integration/FloeDataFrameTest.php | 20 +- .../Tests/Integration/FloeExtractorTest.php | 65 +- .../Tests/Integration/FloeMergeDSLTest.php | 15 +- .../Tests/Integration/FloeStatisticsTest.php | 39 +- .../Integration/FloeStreamReaderTest.php | 22 +- .../Integration/FloeWriteContractTest.php | 27 +- .../Flow/Floe/Tests/Mother/RowsMother.php | 85 ++- .../Floe/Tests/Unit/FloeExtractorTest.php | 67 +-- .../Flow/Floe/Tests/Unit/FloeLoaderTest.php | 26 +- .../Flow/Floe/Tests/Unit/FloeMergerTest.php | 152 +++-- .../Flow/Floe/Tests/Unit/FloeReaderTest.php | 178 +++--- .../Floe/Tests/Unit/FloeSerializerTest.php | 29 +- .../Floe/Tests/Unit/FloeStreamReaderTest.php | 5 +- .../Floe/Tests/Unit/FloeStreamWriterTest.php | 76 ++- .../Tests/Unit/FloeValueRoundTripTest.php | 197 +++--- .../Flow/Floe/Tests/Unit/FloeWriterTest.php | 67 +-- .../Flow/Floe/Tests/Unit/FooterReaderTest.php | 7 +- .../tests/Flow/Floe/Tests/Unit/FooterTest.php | 4 +- .../Floe/Tests/Unit/PhpFloeEncoderTest.php | 26 +- .../Tests/Unit/Base64SerializerTest.php | 30 +- .../Tests/Unit/CompressingSerializerTest.php | 30 +- .../Tests/Unit/NativePHPSerializerTest.php | 30 +- .../Integration/DocumentationFencesTest.php | 11 +- .../codemirror/completions/dataframe.js | 22 +- .../assets/codemirror/completions/dsl.js | 36 +- web/landing/assets/wasm/tools/flow.phar | Bin 3960456 -> 4003673 bytes .../examples/topics/joins/join_each/code.php | 6 +- web/landing/resources/api.json | 2 +- web/landing/resources/dsl.json | 2 +- 367 files changed, 7865 insertions(+), 5728 deletions(-) create mode 100644 src/core/etl/src/Flow/ETL/Row/DeclaredColumns.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/InferredBatch.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/DeclaredColumnsTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/InferredBatchTest.php diff --git a/benchmarks/src/Schema/RowsSchemaScenario.php b/benchmarks/src/Schema/RowsSchemaScenario.php index 653c323748..52104ebcc3 100644 --- a/benchmarks/src/Schema/RowsSchemaScenario.php +++ b/benchmarks/src/Schema/RowsSchemaScenario.php @@ -7,8 +7,7 @@ use Flow\ETL\Rows; use function array_key_exists; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -60,9 +59,9 @@ public function rows(): Rows $list = []; for ($index = 0; $index < $this->batch; $index++) { - $list[] = row(['a' => 'x' . $index]); + $list[] = ['a' => 'x' . $index]; } - return self::$batches[$this->batch] = rows(schema(str_schema('a')), ...$list); + return self::$batches[$this->batch] = array_to_rows($list, schema(str_schema('a'))); } } diff --git a/documentation/components/adapters/csv.md b/documentation/components/adapters/csv.md index e18e9aefb3..66cd8267e5 100644 --- a/documentation/components/adapters/csv.md +++ b/documentation/components/adapters/csv.md @@ -40,11 +40,9 @@ $rows = data_frame() data_frame() ->read(from_rows( - rows( + array_to_rows( + [['id' => 1, 'name' => 'Norbert'], ['id' => 2, 'name' => 'Tomek'], ['id' => 3, 'name' => 'Dawid']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'Norbert']), - row(['id' => 2, 'name' => 'Tomek']), - row(['id' => 3, 'name' => 'Dawid']), ) )) ->load(to_csv($path, true, true)) diff --git a/documentation/components/adapters/logger.md b/documentation/components/adapters/logger.md index 193207b119..a9302795ee 100644 --- a/documentation/components/adapters/logger.md +++ b/documentation/components/adapters/logger.md @@ -29,9 +29,9 @@ $logger = new TestLogger(); $loader = new PsrLoggerLoader($logger, 'row log', LogLevel::ERROR); -$loader->load(rows( +$loader->load(array_to_rows( + [['id' => 12345, 'name' => 'norbert']], schema(int_schema('id'), str_schema('name')), - row(['id' => 12345, 'name' => 'norbert']), )); $this->assertTrue($logger->hasErrorRecords()); diff --git a/documentation/components/adapters/text.md b/documentation/components/adapters/text.md index 4ca17f568a..d0c73148bb 100644 --- a/documentation/components/adapters/text.md +++ b/documentation/components/adapters/text.md @@ -44,15 +44,13 @@ $rows = (new Flow()) ```php process( - rows( + array_to_rows( + [['name' => 'Norbert'], ['name' => 'Tomek'], ['name' => 'Dawid']], schema(str_schema('name')), - row(['name' => 'Norbert']), - row(['name' => 'Tomek']), - row(['name' => 'Dawid']), ) ) ->load(to_text($path)) diff --git a/documentation/components/core/building-blocks.md b/documentation/components/core/building-blocks.md index 4c1be61c0a..512fd0136b 100644 --- a/documentation/components/core/building-blocks.md +++ b/documentation/components/core/building-blocks.md @@ -15,27 +15,6 @@ Let's look at the following example: declare(strict_types=1); -use function Flow\ETL\DSL\{bool_schema, int_schema, row, rows, schema, str_schema}; - -$rows = rows( - schema(int_schema('id'), str_schema('name'), bool_schema('active')), - row(['id' => 1, 'name' => 'user_01', 'active' => true]), - row(['id' => 2, 'name' => 'user_02', 'active' => false]), - row(['id' => 3, 'name' => 'user_03', 'active' => true]), - row(['id' => 4, 'name' => 'user_04', 'active' => false]), -); -``` - -Rows are the main data structure in Flow ETL, they're used to represent data in the data frame. -Extractors are yielding Rows and Loaders are saving Rows. - -The same can be achieved using the following code: - -```php -withSchema($schema)` to skip the spill entirely; a declared schema streams the source directly and can therefore be read only once. -### getEach() - Retrieve individual Rows - -```php -getEach() as $row) { - echo "ID: " . $row->get('id')->value() . "\n"; - echo "Name: " . $row->get('name')->value() . "\n"; -} -``` - ### getAsArray() - Retrieve as array batches ```php diff --git a/documentation/upgrading.md b/documentation/upgrading.md index 84ef20a0a1..db89d242a5 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -492,7 +492,7 @@ document written by 0.45.x that has a structure column. Clear APCu and natively |------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------| | `new Rows($schema, ...$rows)` | `Rows::of($schema, ...$rows)` / `rows($schema, ...$rows)` | | `Rows::trusted($schema, $rows)` / `Rows::conformed($schema, $rows)` | `Rows::of($schema, ...$rows)` (views) / `Rows::fromColumns($schema, $columns, $count)` (columns) | -| `new Row(array $values)` | `row($values)` / `array_to_row($values, $schema)` | +| `new Row(array $values)` | `array_to_row($values, $schema)` | | - | `new Row(Rows $rows, int $index)` - a view over row `$index` of `$rows` | | `Row::matchTo()` / `Row::conformTo()` / `Row::project()` | removed - `Rows::matchTo()` / `Rows::project()` | | `Rows::empty(): bool` | `Rows::isEmpty(): bool` | @@ -503,13 +503,17 @@ document written by 0.45.x that has a structure column. Clear APCu and natively | `serialize(Rows)` payload `{schema, rows}` | `{schema, count, columns}` - payloads of 0.44.x cannot be unserialized | | `Rows::drop()` / `dropRight()` / `take()` / `takeRight()` with a negative size - `array_slice()` semantics | `InvalidArgumentException` | -### 50) `flow-php/etl` - `row()` infers through a batch +### 50) `flow-php/etl` - `row()`, `InferredBatch` and `DataFrame::getEach()` removed -| Before | After | -|------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| -| `row(['a' => [1, 'x']])` - an `array` value | a `Json` value (`json` column) | -| `row(['a' => new stdClass()])` / a closure - refused later by `rows()` | refused by `row()` (`RuntimeException` / `InvalidArgumentException`) | -| `row(['at' => $datetimeInWarsaw])` - the instance with its zone | a `datetime` (UTC) column - the instant reads back in UTC; declare the zone with `datetime_schema(zone: ...)` | +| Before | After | +|-----------------------------------|--------------------------------------------------------------------------------| +| `row($values)` | `array_to_row($values, $schema)` | +| `rows($schema, row($a), row($b))` | `array_to_rows([$a, $b], $schema)` | +| `Flow\ETL\Row\InferredBatch` | removed - `array_to_rows($data, $schema)`, or `from_array($data)` to infer one | +| `DataFrame::getEach()` | `getEachAsArray()` (values) / `get()` (batches with their schema) | + +`array_to_row()` / `array_to_rows()` cast values to the declared type and refuse keys the schema does not declare +(`SchemaMismatchException` naming the row and the column; before, those keys were silently dropped). ### 51) `flow-php/etl` - date and time columns store days and microseconds diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorBatchContractTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorBatchContractTest.php index d02c9094e8..0df9767804 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorBatchContractTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorBatchContractTest.php @@ -9,9 +9,8 @@ use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\CSV\from_csv; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -21,10 +20,9 @@ public function test_csv_extractor_honours_the_batch_contract(): void { self::assertExtractorHonoursBatchContract( static fn(): CSVExtractor => from_csv(CSVFixtureContext::path('two_columns.csv'))->withHeader(false), - rows( + array_to_rows( + [['e00' => 1, 'e01' => 'a'], ['e00' => 2, 'e01' => 'b']], schema(int_schema('e00'), str_schema('e01')), - row(['e00' => 1, 'e01' => 'a']), - row(['e00' => 2, 'e01' => 'b']), ), ); } 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 b0cb478ccd..5b04af80f1 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 @@ -13,6 +13,7 @@ use function file_get_contents; use function Flow\ETL\Adapter\CSV\from_csv; use function Flow\ETL\Adapter\CSV\to_csv; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\from_rows; @@ -22,8 +23,6 @@ use function Flow\ETL\DSL\overwrite; use function Flow\ETL\DSL\partition_by; use function Flow\ETL\DSL\ref; -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; @@ -49,10 +48,9 @@ public function test_header_and_body_follow_the_schema_order_not_the_row_key_ord // R10: the Schema owns column order and rows are never rekeyed, so the writer reads the order // off the Schema - the first row's key order must not decide the header df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['name' => 'a', 'id' => 1], ['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')), - row(['name' => 'a', 'id' => 1]), - row(['id' => 2, 'name' => 'b']), ))) ->load(to_csv($path = __DIR__ . '/var/test_schema_order.csv')->saveMode(overwrite())) ->run(); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalDataFrameFactoryTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalDataFrameFactoryTest.php index 7560eb4f4f..437fdc9e72 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalDataFrameFactoryTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalDataFrameFactoryTest.php @@ -14,11 +14,10 @@ use Flow\ETL\Adapter\Doctrine\Tests\IntegrationTestCase; use function Flow\ETL\Adapter\Doctrine\dbal_dataframe_factory; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_integer; @@ -69,13 +68,7 @@ public function test_dataframe_factory(): void Parameter::ints('ids', ref('id')), new LiteralParameter('name', 'Name 1'), ) - ->from(rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 55]), - )) + ->from(array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 55]], schema(int_schema('id')))) ->select('id') ->fetch(); @@ -134,13 +127,7 @@ public function test_dataframe_factory_with_schema(): void str_schema('name'), map_schema('tags', type_map(type_string(), type_integer())), )) - ->from(rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 55]), - )) + ->from(array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 55]], schema(int_schema('id')))) ->schema(); static::assertSame( diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php index b5d7764ce9..b179583fda 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php @@ -19,11 +19,10 @@ 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\array_to_rows; 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; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; use function getenv; @@ -48,8 +47,8 @@ public function test_multiple_batches_in_separate_transactions(): void 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])), + array_to_rows([['id' => 1, 'value' => 100]], schema(integer_schema('id'), integer_schema('value'))), + array_to_rows([['id' => 2, 'value' => 200]], schema(integer_schema('id'), integer_schema('value'))), )) ->write(to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table'))) ->run(); @@ -88,9 +87,9 @@ public function test_rollback_on_failure(): void try { df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Should fail']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Should fail']), ))) ->write(to_dbal_transaction( $connection, @@ -130,10 +129,9 @@ public function test_transactional_delete_and_insert(): void $connection = $this->mysqlDatabaseContext->connection(); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Updated'], ['id' => 2, 'name' => 'Updated']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Updated']), - row(['id' => 2, 'name' => 'Updated']), ))) ->write(to_dbal_transaction( $connection, @@ -168,9 +166,9 @@ public function test_with_isolation_level(): void $connection = $this->mysqlDatabaseContext->connection(); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Test']), ))) ->write( new Transactional( diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php index 95ce25b075..93e40ef4f7 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php @@ -19,11 +19,10 @@ 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\array_to_rows; 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; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; use function getenv; @@ -48,8 +47,8 @@ public function test_multiple_batches_in_separate_transactions(): void 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])), + array_to_rows([['id' => 1, 'value' => 100]], schema(integer_schema('id'), integer_schema('value'))), + array_to_rows([['id' => 2, 'value' => 200]], schema(integer_schema('id'), integer_schema('value'))), )) ->write(to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table'))) ->run(); @@ -88,9 +87,9 @@ public function test_rollback_on_failure(): void try { df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Should fail']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Should fail']), ))) ->write(to_dbal_transaction( $connection, @@ -130,10 +129,9 @@ public function test_transactional_delete_and_insert(): void $connection = $this->pgsqlDatabaseContext->connection(); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Updated'], ['id' => 2, 'name' => 'Updated']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Updated']), - row(['id' => 2, 'name' => 'Updated']), ))) ->write(to_dbal_transaction( $connection, @@ -168,9 +166,9 @@ public function test_with_isolation_level(): void $connection = $this->pgsqlDatabaseContext->connection(); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Test']), ))) ->write( new Transactional( diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php index 082d2e69e7..1bfec52afc 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php @@ -19,11 +19,10 @@ 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\array_to_rows; 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; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; use function getenv; @@ -48,8 +47,8 @@ public function test_multiple_batches_in_separate_transactions(): void 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])), + array_to_rows([['id' => 1, 'value' => 100]], schema(integer_schema('id'), integer_schema('value'))), + array_to_rows([['id' => 2, 'value' => 200]], schema(integer_schema('id'), integer_schema('value'))), )) ->write(to_dbal_transaction($connection, to_dbal_table_insert($connection, 'test_table'))) ->run(); @@ -88,9 +87,9 @@ public function test_rollback_on_failure(): void try { df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Should fail']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Should fail']), ))) ->write(to_dbal_transaction( $connection, @@ -130,10 +129,9 @@ public function test_transactional_delete_and_insert(): void $connection = $this->sqliteDatabaseContext->connection(); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Updated'], ['id' => 2, 'name' => 'Updated']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Updated']), - row(['id' => 2, 'name' => 'Updated']), ))) ->write(to_dbal_transaction( $connection, @@ -168,9 +166,9 @@ public function test_with_isolation_level(): void $connection = $this->sqliteDatabaseContext->connection(); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], schema(integer_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Test']), ))) ->write( new Transactional( 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 0eeb7ffb20..d8fb8be3b5 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 @@ -28,6 +28,7 @@ use function array_keys; use function Flow\ETL\Adapter\Excel\DSL\from_excel; use function Flow\ETL\Adapter\Excel\DSL\is_valid_excel_sheet_name; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; @@ -37,8 +38,6 @@ use function Flow\ETL\DSL\infer_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_schema; @@ -272,14 +271,13 @@ public function test_extract_with_wrongly_selected_reader(): void public function test_is_valid_excel_sheet_name_function(): void { $result = df() - ->read(from_rows(rows( - schema(string_schema('sheet')), - row(['sheet' => 'ValidSheet']), - row(['sheet' => 'Invalid/Sheet']), - row(['sheet' => 'Sheet*Name']), - row(['sheet' => 'This is a very long sheet name that exceeds the 31 character limit']), - row(['sheet' => 'Normal']), - ))) + ->read(from_rows(array_to_rows([ + ['sheet' => 'ValidSheet'], + ['sheet' => 'Invalid/Sheet'], + ['sheet' => 'Sheet*Name'], + ['sheet' => 'This is a very long sheet name that exceeds the 31 character limit'], + ['sheet' => 'Normal'], + ], schema(string_schema('sheet'))))) ->withEntry('is_valid', is_valid_excel_sheet_name(ref('sheet'))) ->fetch() ->toArray(); diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelLoaderTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelLoaderTest.php index 748e687d94..51f0d454c6 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelLoaderTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelLoaderTest.php @@ -21,6 +21,7 @@ use function Flow\ETL\Adapter\Excel\DSL\from_excel; use function Flow\ETL\Adapter\Excel\DSL\to_excel; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; @@ -34,8 +35,6 @@ use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\overwrite; use function Flow\ETL\DSL\partition_by; -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\string_schema; @@ -64,7 +63,10 @@ public function test_auto_detects_ods_writer_from_extension(): void $outputPath = __DIR__ . '/var/output_auto.ods'; df() - ->read(from_rows(rows(schema(int_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])))) + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], + schema(int_schema('id'), string_schema('name')), + ))) ->write(to_excel($outputPath)->saveMode(overwrite())) ->run(); @@ -83,7 +85,10 @@ public function test_auto_detects_xlsx_writer_from_extension(): void $outputPath = __DIR__ . '/var/output_auto.xlsx'; df() - ->read(from_rows(rows(schema(int_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])))) + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], + schema(int_schema('id'), string_schema('name')), + ))) ->write(to_excel($outputPath)->saveMode(overwrite())) ->run(); @@ -102,11 +107,9 @@ public function test_multiple_rows_in_single_batch(): void $outputPath = __DIR__ . '/var/output_batches.xlsx'; df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'First'], ['id' => 2, 'name' => 'Second'], ['id' => 3, 'name' => 'Third']], schema(int_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'First']), - row(['id' => 2, 'name' => 'Second']), - row(['id' => 3, 'name' => 'Third']), ))) ->batchSize(2) ->write(to_excel($outputPath)->saveMode(overwrite())) @@ -130,11 +133,13 @@ public function test_round_trip_with_basic_data(ExcelWriter $writer, string $ext $outputPath = __DIR__ . '/var/output.' . $extension; df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com'], + ['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com'], + ['id' => 3, 'name' => 'Charlie', 'email' => 'charlie@example.com'], + ], schema(int_schema('id'), string_schema('name'), string_schema('email')), - row(['id' => 1, 'name' => 'Alice', 'email' => 'alice@example.com']), - row(['id' => 2, 'name' => 'Bob', 'email' => 'bob@example.com']), - row(['id' => 3, 'name' => 'Charlie', 'email' => 'charlie@example.com']), ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withWriter($writer)) ->run(); @@ -159,9 +164,9 @@ public function test_round_trip_with_custom_datetime_and_time_formats(): void $time = new DateInterval('PT14H30M45S'); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['date_val' => $date, 'datetime_val' => $datetime, 'time_val' => $time]], schema(date_schema('date_val'), datetime_schema('datetime_val'), time_schema('time_val')), - row(['date_val' => $date, 'datetime_val' => $datetime, 'time_val' => $time]), ))) ->write( to_excel($outputPath) @@ -184,7 +189,10 @@ public function test_round_trip_with_custom_sheet_name(ExcelWriter $writer, stri $outputPath = __DIR__ . '/var/output_custom_sheet.' . $extension; df() - ->read(from_rows(rows(schema(int_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])))) + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], + schema(int_schema('id'), string_schema('name')), + ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withSheetName('MySheet')->withWriter($writer)) ->run(); @@ -204,7 +212,16 @@ public function test_round_trip_preserves_every_type_a_workbook_can_carry(): voi $uuid = 'f47ac10b-58cc-4372-a567-0e02b2c3d479'; df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [[ + 'i' => 1, + 'f' => 1.5, + 'b' => true, + 'd' => new DateTimeImmutable('2024-06-15'), + 'dt' => new DateTimeImmutable('2024-06-15 14:30:00'), + 'u' => type_uuid()->cast($uuid), + 'j' => type_json()->cast(['key' => 'value']), + ]], schema( int_schema('i'), float_schema('f'), @@ -214,15 +231,6 @@ public function test_round_trip_preserves_every_type_a_workbook_can_carry(): voi uuid_schema('u'), json_schema('j'), ), - row([ - 'i' => 1, - 'f' => 1.5, - 'b' => true, - 'd' => new DateTimeImmutable('2024-06-15'), - 'dt' => new DateTimeImmutable('2024-06-15 14:30:00'), - 'u' => type_uuid()->cast($uuid), - 'j' => type_json()->cast(['key' => 'value']), - ]), ))) ->write(to_excel($outputPath)->saveMode(overwrite())) ->run(); @@ -248,9 +256,9 @@ public function test_round_trip_with_datetime_xlsx(): void $datetime = new DateTimeImmutable('2024-06-15 14:30:00'); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['date_val' => $date, 'datetime_val' => $datetime]], schema(date_schema('date_val'), datetime_schema('datetime_val')), - row(['date_val' => $date, 'datetime_val' => $datetime]), ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withWriter(ExcelWriter::XLSX)) ->run(); @@ -269,11 +277,13 @@ public function test_temporal_cells_share_one_cell_format_per_format(): void $outputPath = __DIR__ . '/var/output_shared_formats.xlsx'; df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['d' => new DateTimeImmutable('2024-06-15'), 'dt' => new DateTimeImmutable('2024-06-15 14:30:00')], + ['d' => new DateTimeImmutable('2024-06-16'), 'dt' => new DateTimeImmutable('2024-06-16 14:30:00')], + ['d' => new DateTimeImmutable('2024-06-17'), 'dt' => new DateTimeImmutable('2024-06-17 14:30:00')], + ], schema(date_schema('d'), datetime_schema('dt')), - row(['d' => new DateTimeImmutable('2024-06-15'), 'dt' => new DateTimeImmutable('2024-06-15 14:30:00')]), - row(['d' => new DateTimeImmutable('2024-06-16'), 'dt' => new DateTimeImmutable('2024-06-16 14:30:00')]), - row(['d' => new DateTimeImmutable('2024-06-17'), 'dt' => new DateTimeImmutable('2024-06-17 14:30:00')]), ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withWriter(ExcelWriter::XLSX)) ->run(); @@ -293,11 +303,13 @@ public function test_round_trip_with_dynamic_sheet_names(): void $loader = $loader->withSheetNameFromEntry('category'); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'name' => 'Alice', 'category' => 'Users'], + ['id' => 2, 'name' => 'Bob', 'category' => 'Users'], + ['id' => 3, 'name' => 'Product A', 'category' => 'Products'], + ], schema(int_schema('id'), string_schema('name'), string_schema('category')), - row(['id' => 1, 'name' => 'Alice', 'category' => 'Users']), - row(['id' => 2, 'name' => 'Bob', 'category' => 'Users']), - row(['id' => 3, 'name' => 'Product A', 'category' => 'Products']), ))) ->write($loader->saveMode(overwrite())) ->run(); @@ -328,10 +340,12 @@ public function test_round_trip_with_null_values(ExcelWriter $writer, string $ex $outputPath = __DIR__ . '/var/output_nulls.' . $extension; df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'name' => 'Alice', 'email' => null], + ['id' => 2, 'name' => null, 'email' => 'bob@example.com'], + ], schema(int_schema('id'), string_schema('name', nullable: true), string_schema('email', nullable: true)), - row(['id' => 1, 'name' => 'Alice', 'email' => null]), - row(['id' => 2, 'name' => null, 'email' => 'bob@example.com']), ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withWriter($writer)) ->run(); @@ -354,7 +368,15 @@ public function test_round_trip_with_various_data_types(ExcelWriter $writer, str $uuidString = 'f47ac10b-58cc-4372-a567-0e02b2c3d479'; df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [[ + 'int_val' => 42, + 'float_val' => 3.14, + 'bool_val' => true, + 'string_val' => 'hello', + 'uuid_val' => type_uuid()->cast($uuidString), + 'json_val' => type_json()->cast(['key' => 'value']), + ]], schema( int_schema('int_val'), float_schema('float_val'), @@ -363,14 +385,6 @@ public function test_round_trip_with_various_data_types(ExcelWriter $writer, str uuid_schema('uuid_val'), json_schema('json_val'), ), - row([ - 'int_val' => 42, - 'float_val' => 3.14, - 'bool_val' => true, - 'string_val' => 'hello', - 'uuid_val' => type_uuid()->cast($uuidString), - 'json_val' => type_json()->cast(['key' => 'value']), - ]), ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withWriter($writer)) ->run(); @@ -398,10 +412,9 @@ public function test_round_trip_without_header(ExcelWriter $writer, string $exte $outputPath = __DIR__ . '/var/output_no_header.' . $extension; df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']], schema(int_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Alice']), - row(['id' => 2, 'name' => 'Bob']), ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withHeader(false)->withWriter($writer)) ->run(); @@ -474,10 +487,9 @@ public function style( $loader = $loader->withCellStyler($cellStyler); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']], schema(int_schema('id'), string_schema('name')), - row(['id' => 1, 'name' => 'Alice']), - row(['id' => 2, 'name' => 'Bob']), ))) ->write($loader->saveMode(overwrite())) ->run(); @@ -503,7 +515,10 @@ public function test_with_header_style(): void $loader = $loader->withHeaderStyle($headerStyle); df() - ->read(from_rows(rows(schema(int_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])))) + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], + schema(int_schema('id'), string_schema('name')), + ))) ->write($loader->saveMode(overwrite())) ->run(); @@ -524,7 +539,10 @@ public function test_with_ods_options(): void $options = new OdsOptions(DEFAULT_COLUMN_WIDTH: 15.0, DEFAULT_ROW_HEIGHT: 20.0); df() - ->read(from_rows(rows(schema(int_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])))) + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], + schema(int_schema('id'), string_schema('name')), + ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withWriterOptions($options)) ->run(); @@ -545,7 +563,10 @@ public function test_with_xlsx_options(): void $options = new XlsxOptions(SHOULD_USE_INLINE_STRINGS: false, DEFAULT_COLUMN_WIDTH: 15.0); df() - ->read(from_rows(rows(schema(int_schema('id'), string_schema('name')), row(['id' => 1, 'name' => 'Test'])))) + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Test']], + schema(int_schema('id'), string_schema('name')), + ))) ->write(to_excel($outputPath)->saveMode(overwrite())->withWriterOptions($options)) ->run(); diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/Function/IsValidExcelSheetNameTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/Function/IsValidExcelSheetNameTest.php index c8348d755e..bb8ec8747f 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/Function/IsValidExcelSheetNameTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/Function/IsValidExcelSheetNameTest.php @@ -8,9 +8,11 @@ use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\Adapter\Excel\DSL\is_valid_excel_sheet_name; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class IsValidExcelSheetNameTest extends FlowTestCase { @@ -21,7 +23,7 @@ final class IsValidExcelSheetNameTest extends FlowTestCase #[TestWith(['Sheet?Name'])] public function test_invalid_excel_sheet_name(string $invalidNames): void { - static::assertFalse(is_valid_excel_sheet_name($invalidNames)->eval(row([]), flow_context())); + static::assertFalse(is_valid_excel_sheet_name($invalidNames)->eval(array_to_row([], schema()), flow_context())); } #[TestWith(['Sheet1'])] @@ -29,7 +31,8 @@ public function test_invalid_excel_sheet_name(string $invalidNames): void public function test_valid_excel_sheet_name(string $sheetName): void { static::assertTrue( - is_valid_excel_sheet_name(ref('sheet_name'))->eval(row(['sheet_name' => $sheetName]), flow_context()), + is_valid_excel_sheet_name(ref('sheet_name')) + ->eval(array_to_row(['sheet_name' => $sheetName], schema(str_schema('sheet_name'))), flow_context()), ); } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php index ce25c15aae..3b9cb0e933 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php @@ -21,10 +21,10 @@ use PHPUnit\Framework\Attributes\DataProvider; use function array_sum; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\infer_schema; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -121,11 +121,17 @@ public function test_its_stop_fetching_data_if_processed_row_count_is_less_then_ static::assertCount(2, $rows); static::assertEquals( - row(['header' => 'row1', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet']), + array_to_row( + ['header' => 'row1', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet'], + schema(str_schema('header'), str_schema('_spread_sheet_id'), str_schema('_sheet_name')), + ), $rows->all()[0], ); static::assertEquals( - row(['header' => 'row2', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet']), + array_to_row( + ['header' => 'row2', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet'], + schema(str_schema('header'), str_schema('_spread_sheet_id'), str_schema('_sheet_name')), + ), $rows->all()[1], ); } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonTest.php index 60bb1af054..1c736f6dfe 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonTest.php @@ -15,6 +15,7 @@ use function file_get_contents; use function Flow\ETL\Adapter\JSON\from_json; use function Flow\ETL\Adapter\Json\to_json; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\df; @@ -28,7 +29,6 @@ use function Flow\ETL\DSL\overwrite; use function Flow\ETL\DSL\partition_by; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\select; @@ -136,9 +136,9 @@ public function test_jsonentry_json_file(): void { $jsonObject = ['short' => 'short_description', 'long' => 'long_description']; df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['id' => 1, 'nested' => type_json()->cast($jsonObject)]], schema(int_schema('id'), json_schema('nested')), - row(['id' => 1, 'nested' => type_json()->cast($jsonObject)]), ))) ->write(to_json($path = __DIR__ . '/var/test_jsonentry.json')->saveMode(overwrite())) ->run(); diff --git a/src/adapter/etl-adapter-logger/tests/Flow/ETL/Adapter/Logger/Tests/Unit/PsrLoggerLoaderTest.php b/src/adapter/etl-adapter-logger/tests/Flow/ETL/Adapter/Logger/Tests/Unit/PsrLoggerLoaderTest.php index 8f30206d3f..add7d3e199 100644 --- a/src/adapter/etl-adapter-logger/tests/Flow/ETL/Adapter/Logger/Tests/Unit/PsrLoggerLoaderTest.php +++ b/src/adapter/etl-adapter-logger/tests/Flow/ETL/Adapter/Logger/Tests/Unit/PsrLoggerLoaderTest.php @@ -9,11 +9,10 @@ use Psr\Log\LogLevel; use Psr\Log\Test\TestLogger; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; @@ -26,7 +25,7 @@ public function test_psr_logger_loader(): void $loader = new PsrLoggerLoader($logger, 'row log', LogLevel::ERROR); $loader->load( - rows(schema(int_schema('id'), string_schema('name')), row(['id' => 12345, 'name' => 'Norbert'])), + array_to_rows([['id' => 12345, 'name' => 'Norbert']], schema(int_schema('id'), string_schema('name'))), flow_context(config()), ); 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 8cb86d2065..a17343d8c6 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 @@ -24,14 +24,13 @@ use function Flow\ETL\Adapter\Parquet\from_parquet; use function Flow\ETL\Adapter\Parquet\to_parquet; use function Flow\ETL\DSL\analyze; +use function Flow\ETL\DSL\array_to_rows; 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_sequence_number; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\partition_types; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\memory_filesystem; @@ -455,13 +454,13 @@ public function test_a_later_file_with_other_columns_throws_naming_both_files(): { $memory = memory_filesystem(); ParquetFilesContext::write($memory, [ - 'memory://glob/a.parquet' => rows(schema(int_schema('id')), row(['id' => 1])), - 'memory://glob/b.parquet' => rows( - schema(int_schema('id'), str_schema('extra')), - row([ + 'memory://glob/a.parquet' => array_to_rows([['id' => 1]], schema(int_schema('id'))), + 'memory://glob/b.parquet' => array_to_rows( + [[ 'id' => 2, 'extra' => 'x', - ]), + ]], + schema(int_schema('id'), str_schema('extra')), ), ]); @@ -477,13 +476,13 @@ public function test_union_by_name_reads_every_file_under_one_schema(): void { $memory = memory_filesystem(); ParquetFilesContext::write($memory, [ - 'memory://glob/a.parquet' => rows(schema(int_schema('id')), row(['id' => 1])), - 'memory://glob/b.parquet' => rows( - schema(int_schema('id'), str_schema('extra')), - row([ + 'memory://glob/a.parquet' => array_to_rows([['id' => 1]], schema(int_schema('id'))), + 'memory://glob/b.parquet' => array_to_rows( + [[ 'id' => 2, 'extra' => 'x', - ]), + ]], + schema(int_schema('id'), str_schema('extra')), ), ]); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php index 62611a9154..ad173c1d5d 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php @@ -27,6 +27,7 @@ use function file_exists; use function Flow\ETL\Adapter\Parquet\from_parquet; use function Flow\ETL\Adapter\Parquet\to_parquet; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\datetime_schema; @@ -42,8 +43,6 @@ use function Flow\ETL\DSL\partition_by; use function Flow\ETL\DSL\partition_types; use function Flow\ETL\DSL\ref; -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; @@ -162,7 +161,12 @@ public function test_round_trip_of_nested_json_values(): void $config = config(); data_frame($config) - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [[ + 'body' => ['data' => Json::fromArray(['a' => 1]), 'n' => 1], + 'json_list' => [Json::fromArray(['c' => 3])], + 'outer' => ['inner' => ['deep' => Json::fromArray(['e' => 5])]], + ]], schema( structure_schema('body', type_structure([ 'data' => type_json(), @@ -173,11 +177,6 @@ public function test_round_trip_of_nested_json_values(): void 'inner' => type_structure(['deep' => type_json()]), ])), ), - row([ - 'body' => ['data' => Json::fromArray(['a' => 1]), 'n' => 1], - 'json_list' => [Json::fromArray(['c' => 3])], - 'outer' => ['inner' => ['deep' => Json::fromArray(['e' => 5])]], - ]), ))) ->write(to_parquet($path, filesystem: $memory)) ->run(); @@ -212,7 +211,12 @@ public function test_round_trip_of_nested_uuid_values(): void $uuid = 'f6d6e0e8-4b7e-4b0e-8d7a-ff0a0c9c9a5a'; data_frame($config) - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [[ + 'body' => ['id' => FlowUuid::fromString($uuid), 'n' => 1], + 'uuid_list' => [FlowUuid::fromString($uuid)], + 'outer' => ['inner' => ['id' => FlowUuid::fromString($uuid)]], + ]], schema( structure_schema('body', type_structure([ 'id' => type_uuid(), @@ -223,11 +227,6 @@ public function test_round_trip_of_nested_uuid_values(): void 'inner' => type_structure(['id' => type_uuid()]), ])), ), - row([ - 'body' => ['id' => FlowUuid::fromString($uuid), 'n' => 1], - 'uuid_list' => [FlowUuid::fromString($uuid)], - 'outer' => ['inner' => ['id' => FlowUuid::fromString($uuid)]], - ]), ))) ->write(to_parquet($path, filesystem: $memory)) ->run(); @@ -260,15 +259,15 @@ public function test_round_trip_of_json_and_uuid_map_values(): void $uuid = 'f6d6e0e8-4b7e-4b0e-8d7a-ff0a0c9c9a5a'; data_frame($config) - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [[ + 'uuid_map' => ['k' => FlowUuid::fromString($uuid)], + 'json_map' => ['k' => Json::fromArray(['d' => 4])], + ]], schema( map_schema('uuid_map', type_map(type_string(), type_uuid())), map_schema('json_map', type_map(type_string(), type_json())), ), - row([ - 'uuid_map' => ['k' => FlowUuid::fromString($uuid)], - 'json_map' => ['k' => Json::fromArray(['d' => 4])], - ]), ))) ->write(to_parquet($path, filesystem: $memory)) ->run(); diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLoaderAllTypesIntegrationTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLoaderAllTypesIntegrationTest.php index 1e239884b9..b70b081632 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLoaderAllTypesIntegrationTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLoaderAllTypesIntegrationTest.php @@ -14,6 +14,7 @@ use function Flow\ETL\Adapter\PostgreSql\from_pgsql_limit_offset; use function Flow\ETL\Adapter\PostgreSql\to_pgsql_table; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; @@ -25,8 +26,6 @@ use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; @@ -110,7 +109,26 @@ public function test_inserts_all_entry_types(): void $xmlElement = $xmlElementDoc->getElementsByTagName('item')->item(0); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [[ + 'col_string' => 'test string', + 'col_integer' => 42, + 'col_float' => 3.14159, + 'col_boolean' => true, + 'col_date' => $date, + 'col_datetime' => $dateTime, + 'col_time' => $time, + 'col_uuid' => $uuid, + 'col_json' => type_json()->cast(['key' => 'value', 'number' => 123]), + 'col_xml' => $xmlDoc, + 'col_xml_element' => $xmlElement, + 'col_html' => '

HTML content

', + 'col_html_element' => 'element', + 'col_enum' => BackedStringEnum::one, + 'col_list' => [1, 2, 3], + 'col_map' => ['a' => 1, 'b' => 2], + 'col_structure' => ['name' => 'John', 'age' => 30], + ]], schema( str_schema('col_string'), int_schema('col_integer'), @@ -133,25 +151,6 @@ enum_schema('col_enum', BackedStringEnum::class), 'age' => type_integer(), ])), ), - row([ - 'col_string' => 'test string', - 'col_integer' => 42, - 'col_float' => 3.14159, - 'col_boolean' => true, - 'col_date' => $date, - 'col_datetime' => $dateTime, - 'col_time' => $time, - 'col_uuid' => $uuid, - 'col_json' => type_json()->cast(['key' => 'value', 'number' => 123]), - 'col_xml' => $xmlDoc, - 'col_xml_element' => $xmlElement, - 'col_html' => '

HTML content

', - 'col_html_element' => 'element', - 'col_enum' => BackedStringEnum::one, - 'col_list' => [1, 2, 3], - 'col_map' => ['a' => 1, 'b' => 2], - 'col_structure' => ['name' => 'John', 'age' => 30], - ]), ))) ->write(to_pgsql_table($this->client, $this->tableName)) ->run(); @@ -225,7 +224,26 @@ enum_schema('col_enum', BackedStringEnum::class), public function test_inserts_null_values_for_all_entry_types(): void { df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [[ + 'col_string' => null, + 'col_integer' => null, + 'col_float' => null, + 'col_boolean' => null, + 'col_date' => null, + 'col_datetime' => null, + 'col_time' => null, + 'col_uuid' => null, + 'col_json' => null, + 'col_xml' => null, + 'col_xml_element' => null, + 'col_html' => null, + 'col_html_element' => null, + 'col_enum' => null, + 'col_list' => null, + 'col_map' => null, + 'col_structure' => null, + ]], schema( str_schema('col_string', nullable: true), int_schema('col_integer', nullable: true), @@ -252,25 +270,6 @@ public function test_inserts_null_values_for_all_entry_types(): void nullable: true, ), ), - row([ - 'col_string' => null, - 'col_integer' => null, - 'col_float' => null, - 'col_boolean' => null, - 'col_date' => null, - 'col_datetime' => null, - 'col_time' => null, - 'col_uuid' => null, - 'col_json' => null, - 'col_xml' => null, - 'col_xml_element' => null, - 'col_html' => null, - 'col_html_element' => null, - 'col_enum' => null, - 'col_list' => null, - 'col_map' => null, - 'col_structure' => null, - ]), ))) ->write(to_pgsql_table($this->client, $this->tableName)) ->run(); diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlLoaderTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlLoaderTest.php index 46614585a9..cf1773228c 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlLoaderTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlLoaderTest.php @@ -17,9 +17,9 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; @@ -36,7 +36,7 @@ public function test_load_delete_requires_delete_options(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('DeleteOptions must be set for DELETE operation'); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context()); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context()); } public function test_load_delete_requires_primary_keys(): void @@ -51,7 +51,7 @@ public function test_load_delete_requires_primary_keys(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Primary keys must be specified for DELETE operation'); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context()); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context()); } public function test_load_update_requires_primary_keys(): void @@ -66,7 +66,7 @@ public function test_load_update_requires_primary_keys(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Primary keys must be specified for UPDATE operation'); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context()); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context()); } public function test_load_update_requires_update_options(): void @@ -80,7 +80,7 @@ public function test_load_update_requires_update_options(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('UpdateOptions must be set for UPDATE operation'); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context()); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context()); } public function test_a_chunked_insert_joins_a_callers_transaction(): void diff --git a/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Integration/SealLoaderTest.php b/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Integration/SealLoaderTest.php index c07fee7e47..124bab1ac1 100644 --- a/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Integration/SealLoaderTest.php +++ b/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Integration/SealLoaderTest.php @@ -9,11 +9,10 @@ use function Flow\ETL\Adapter\Seal\to_seal_delete; use function Flow\ETL\Adapter\Seal\to_seal_schema; use function Flow\ETL\Adapter\Seal\to_seal_upsert; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\integer_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_schema; @@ -29,16 +28,17 @@ public function test_deleting_documents_by_identifier(): void )); to_seal_upsert($engine, 'users')->load( - rows( + array_to_rows( + [['id' => '1', 'name' => 'Alice'], ['id' => '2', 'name' => 'Bob']], schema(string_schema('id'), string_schema('name')), - row(['id' => '1', 'name' => 'Alice']), - row(['id' => '2', 'name' => 'Bob']), ), flow_context(), ); $this->sealContext()->refresh(); - to_seal_delete($engine, 'users')->load(rows(schema(string_schema('id')), row(['id' => '1'])), flow_context()); + to_seal_delete($engine, 'users')->load(array_to_rows([[ + 'id' => '1', + ]], schema(string_schema('id'))), flow_context()); $this->sealContext()->refresh(); static::assertSame(1, $engine->countDocuments('users')); @@ -54,14 +54,17 @@ public function test_deleting_documents_using_a_custom_identifier_entry(): void )); to_seal_upsert($engine, 'products')->load( - rows(schema(string_schema('sku'), string_schema('name')), row(['sku' => 'SKU_0001', 'name' => 'Keyboard'])), + array_to_rows( + [['sku' => 'SKU_0001', 'name' => 'Keyboard']], + schema(string_schema('sku'), string_schema('name')), + ), flow_context(), ); $this->sealContext()->refresh(); to_seal_delete($engine, 'products') ->withIdentifierEntry('sku') - ->load(rows(schema(string_schema('sku')), row(['sku' => 'SKU_0001'])), flow_context()); + ->load(array_to_rows([['sku' => 'SKU_0001']], schema(string_schema('sku'))), flow_context()); $this->sealContext()->refresh(); static::assertSame(0, $engine->countDocuments('products')); @@ -78,13 +81,13 @@ public function test_loading_respects_a_custom_bulk_size(): void $documents = []; for ($i = 1; $i <= 10; $i++) { - $documents[] = row(['id' => (string) $i, 'name' => 'User ' . $i, 'age' => 20 + $i]); + $documents[] = ['id' => (string) $i, 'name' => 'User ' . $i, 'age' => 20 + $i]; } to_seal_upsert($engine, 'users') ->withBulkSize(3) ->load( - rows(schema(str_schema('id'), str_schema('name'), int_schema('age')), ...$documents), + array_to_rows($documents, schema(str_schema('id'), str_schema('name'), int_schema('age'))), flow_context(), ); $this->sealContext()->refresh(); @@ -101,10 +104,9 @@ public function test_loading_rows_into_a_seal_index(): void )); to_seal_upsert($engine, 'users')->load( - rows( + array_to_rows( + [['id' => '1', 'name' => 'Alice', 'age' => 30], ['id' => '2', 'name' => 'Bob', 'age' => 25]], schema(string_schema('id'), string_schema('name'), integer_schema('age')), - row(['id' => '1', 'name' => 'Alice', 'age' => 30]), - row(['id' => '2', 'name' => 'Bob', 'age' => 25]), ), flow_context(), ); @@ -124,16 +126,16 @@ public function test_loading_updates_a_document_with_the_same_identifier(): void $loader = to_seal_upsert($engine, 'users'); $loader->load( - rows( + array_to_rows( + [['id' => '1', 'name' => 'Alice', 'age' => 30]], schema(string_schema('id'), string_schema('name'), integer_schema('age')), - row(['id' => '1', 'name' => 'Alice', 'age' => 30]), ), flow_context(), ); $loader->load( - rows( + array_to_rows( + [['id' => '1', 'name' => 'Alice Updated', 'age' => 31]], schema(string_schema('id'), string_schema('name'), integer_schema('age')), - row(['id' => '1', 'name' => 'Alice Updated', 'age' => 31]), ), flow_context(), ); diff --git a/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealLoaderTest.php b/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealLoaderTest.php index c77a663d17..67819e1d9e 100644 --- a/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealLoaderTest.php +++ b/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealLoaderTest.php @@ -10,9 +10,9 @@ use function Flow\ETL\Adapter\Seal\to_seal_delete; use function Flow\ETL\Adapter\Seal\to_seal_schema; use function Flow\ETL\Adapter\Seal\to_seal_upsert; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -29,17 +29,19 @@ public function test_deleting_with_a_non_scalar_identifier_entry_throws(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Entry "id" cannot be used as a document identifier for DELETE operation'); - to_seal_delete($engine, 'users')->load( - rows(schema(list_schema('id', type_list(type_string()))), row(['id' => ['1', '2']])), - flow_context(), - ); + to_seal_delete($engine, 'users')->load(array_to_rows([['id' => [ + '1', + '2', + ]]], schema(list_schema('id', type_list(type_string())))), flow_context()); } public function test_deleting_empty_rows_removes_no_documents(): void { $engine = $this->sealContext()->engine(to_seal_schema(schema(str_schema('id')), 'users', 'id')); - to_seal_upsert($engine, 'users')->load(rows(schema(string_schema('id')), row(['id' => '1'])), flow_context()); + to_seal_upsert($engine, 'users')->load(array_to_rows([[ + 'id' => '1', + ]], schema(string_schema('id'))), flow_context()); to_seal_delete($engine, 'users')->load(rows(schema()), flow_context()); static::assertSame(1, $engine->countDocuments('users')); diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorBatchContractTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorBatchContractTest.php index da54154c10..fd4d76d7da 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorBatchContractTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorBatchContractTest.php @@ -8,8 +8,7 @@ use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\Text\from_text; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -19,12 +18,7 @@ public function test_text_extractor_honours_the_batch_contract(): void { self::assertExtractorHonoursBatchContract( static fn(): TextExtractor => from_text(__DIR__ . '/../Fixtures/parity_lines.txt'), - rows( - schema(str_schema('text')), - row(['text' => 'alpha']), - row(['text' => 'beta']), - row(['text' => 'gamma']), - ), + array_to_rows([['text' => 'alpha'], ['text' => 'beta'], ['text' => 'gamma']], schema(str_schema('text'))), ); } } diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextTest.php index c72321d43a..f78a1ba0a2 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextTest.php @@ -11,13 +11,12 @@ use function file_get_contents; use function Flow\ETL\Adapter\Text\from_text; use function Flow\ETL\Adapter\Text\to_text; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\from_sequence_number; use function Flow\ETL\DSL\generate_random_string; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\overwrite; -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\string_schema; @@ -37,12 +36,11 @@ public function test_loading_text_files(): void $path = __DIR__ . '/var/flow_php_etl_csv_loader' . generate_random_string() . '.csv'; data_frame() - ->process(rows( - schema(string_schema('name')), - row(['name' => 'Norbert']), - row(['name' => 'Tomek']), - row(['name' => 'Dawid']), - )) + ->process(array_to_rows([ + ['name' => 'Norbert'], + ['name' => 'Tomek'], + ['name' => 'Dawid'], + ], schema(string_schema('name')))) ->write(to_text($path)) ->run(); diff --git a/src/bridge/symfony/http-foundation/tests/Flow/Bridge/Symfony/HttpFoundation/Tests/Unit/Response/FlowBufferedResponseTest.php b/src/bridge/symfony/http-foundation/tests/Flow/Bridge/Symfony/HttpFoundation/Tests/Unit/Response/FlowBufferedResponseTest.php index 461adee731..18a3230f87 100644 --- a/src/bridge/symfony/http-foundation/tests/Flow/Bridge/Symfony/HttpFoundation/Tests/Unit/Response/FlowBufferedResponseTest.php +++ b/src/bridge/symfony/http-foundation/tests/Flow/Bridge/Symfony/HttpFoundation/Tests/Unit/Response/FlowBufferedResponseTest.php @@ -9,10 +9,9 @@ use function Flow\Bridge\Symfony\HttpFoundation\http_json_output; use function Flow\Bridge\Symfony\HttpFoundation\http_stream_open; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\from_array; 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; final class FlowBufferedResponseTest extends FlowTestCase @@ -27,7 +26,10 @@ public function test_response_from_empty_dataset(): void public function test_response_is_buffered_only_once(): void { - $extractor = new CountingExtractor(schema(int_schema('id')), rows(schema(int_schema('id')), row(['id' => 1]))); + $extractor = new CountingExtractor( + schema(int_schema('id')), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); $response = http_stream_open($extractor)->response(http_json_output()); diff --git a/src/cli/tests/Flow/CLI/Tests/Unit/Loader/ProgressBarLoaderTest.php b/src/cli/tests/Flow/CLI/Tests/Unit/Loader/ProgressBarLoaderTest.php index 78211be901..7b49c27c51 100644 --- a/src/cli/tests/Flow/CLI/Tests/Unit/Loader/ProgressBarLoaderTest.php +++ b/src/cli/tests/Flow/CLI/Tests/Unit/Loader/ProgressBarLoaderTest.php @@ -9,9 +9,9 @@ use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Output\BufferedOutput; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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,10 +21,11 @@ public function test_it_advances_the_bar_by_the_batch_size(): void { $progressBar = new ProgressBar(new BufferedOutput()); - (new ProgressBarLoader($progressBar))->load( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), - flow_context(), - ); + (new ProgressBarLoader($progressBar))->load(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id'))), flow_context()); static::assertSame(3, $progressBar->getProgress()); } @@ -35,8 +36,8 @@ public function test_every_batch_adds_to_the_progress_so_far(): void $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); + $loader->load(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), $context); + $loader->load(array_to_rows([['id' => 3]], schema(int_schema('id'))), $context); static::assertSame(3, $progressBar->getProgress()); } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Bucket.php b/src/core/etl/src/Flow/ETL/Bucketing/Bucket.php index 4e86901e04..2b548d2f44 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/Bucket.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/Bucket.php @@ -7,8 +7,8 @@ use Flow\ETL\Row; use Flow\ETL\Schema; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -27,9 +27,9 @@ public static function schema(): Schema public function toRow(): Row { - return row([ + return array_to_row([ BucketShape::id->value => $this->id, BucketShape::totalRows->value => $this->totalRows, - ]); + ], self::schema()); } } diff --git a/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php b/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php index 81c5aa46f2..88f58b1eac 100644 --- a/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php +++ b/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php @@ -6,13 +6,11 @@ use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Row; use Flow\ETL\Rows; use function array_map; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; use function get_debug_type; @@ -86,10 +84,7 @@ public function rows(): Cardinality public function toRows(): Rows { - return rows( - schema(str_schema('key'), int_schema('rows', nullable: true)), - ...array_map(static fn(array $chunk): Row => row($chunk), $this->chunks), - ); + return array_to_rows($this->chunks, schema(str_schema('key'), int_schema('rows', nullable: true))); } /** diff --git a/src/core/etl/src/Flow/ETL/DSL/functions.php b/src/core/etl/src/Flow/ETL/DSL/functions.php index 97f70f09ea..9359bc3db2 100644 --- a/src/core/etl/src/Flow/ETL/DSL/functions.php +++ b/src/core/etl/src/Flow/ETL/DSL/functions.php @@ -33,8 +33,10 @@ use Flow\ETL\ErrorHandler\IgnoreError; use Flow\ETL\ErrorHandler\SkipRows; use Flow\ETL\ErrorHandler\ThrowError; +use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Exception\UnsupportedUnionTypeException; use Flow\ETL\Extractor; use Flow\ETL\Extractor\ArrayExtractor; @@ -150,7 +152,6 @@ use Flow\ETL\Row; use Flow\ETL\Row\ColumnName; use Flow\ETL\Row\Formatter\ASCIISchemaFormatter; -use Flow\ETL\Row\InferredBatch; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; use Flow\ETL\Row\SortOrder; @@ -255,6 +256,7 @@ use function array_is_list; use function array_key_exists; use function array_map; +use function array_values; use function class_exists; use function enum_exists; use function Flow\Filesystem\DSL\path; @@ -570,15 +572,6 @@ function rename_map(array $renames): RenameMapEntryStrategy return new RenameMapEntryStrategy($renames); } -/** - * @param array $values - */ -#[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] -function row(array $values): Row -{ - return (new InferredBatch())->of([$values])->first(); -} - #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] function rows(Schema $schema, Row ...$row): Rows { @@ -1183,23 +1176,13 @@ function array_to_row( Backend $backend = new DefaultBackend(), array|Partitions $partitions = [], ): Row { - $map = []; - - // @mago-ignore analysis:mixed-assignment - foreach ($data as $key => $value) { - $map[(new ColumnName())->of($key)] = $value; - } - foreach ($partitions as $partition) { - if (!array_key_exists($partition->name, $map)) { - $map[$partition->name] = $partition->value; + if (!array_key_exists($partition->name, $data)) { + $data[$partition->name] = $partition->value; } } - return (new RowsBuilder($schema, $backend)) - ->appendRows([$map]) - ->finish() - ->first(); + return array_to_rows([$data], $schema, $backend)->first(); } /** @@ -1223,7 +1206,7 @@ function array_to_rows(array $data, Schema $schema, Backend $backend = new Defau $maps = []; // @mago-ignore analysis:mixed-assignment - foreach ($rawRows as $row) { + foreach (array_values($rawRows) as $index => $row) { $row = type_array()->assert($row); $map = []; @@ -1232,8 +1215,13 @@ function array_to_rows(array $data, Schema $schema, Backend $backend = new Defau // PHP gives back a numeric-string column name as an int key, which the positional rule // would rename to eNN. A declared schema naming that column settles which one it is. $declared = $schema->findDefinition((string) $key); + $name = $declared === null ? (new ColumnName())->of($key) : (string) $key; + + if ($declared === null && $schema->findDefinition($name) === null) { + throw new SchemaMismatchException($index, ColumnMismatchException::unexpectedColumn($name)); + } - $map[$declared === null ? (new ColumnName())->of($key) : (string) $key] = $value; + $map[$name] = $value; } $maps[] = $map; diff --git a/src/core/etl/src/Flow/ETL/DataFrame.php b/src/core/etl/src/Flow/ETL/DataFrame.php index 168075b601..a5a3ffb931 100644 --- a/src/core/etl/src/Flow/ETL/DataFrame.php +++ b/src/core/etl/src/Flow/ETL/DataFrame.php @@ -299,7 +299,6 @@ public function duplicateRow(mixed $condition, WithEntry ...$entries): self * * DataFrame::get() : \Generator * DataFrame::getAsArray() : \Generator - * DataFrame::getEach() : \Generator * DataFrame::getEachAsArray() : \Generator * * @trigger @@ -401,27 +400,6 @@ public function getAsArray(): Generator } } - /** - * Yield each row as an instance of Row. - * - * @trigger - * - * @return \Generator - */ - public function getEach(): Generator - { - 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; - } - } - } - /** * Yield each row as an array. * diff --git a/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php index 83b6c66dd5..58ccb5b394 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php @@ -10,6 +10,7 @@ use Flow\ETL\Plan; use Flow\ETL\Plan\Node\Limit; use Flow\ETL\Plan\Trigger; +use Flow\ETL\Row\DeclaredColumns; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; @@ -46,7 +47,11 @@ public function extract(FlowContext $context, ?int $limit = null): Generator 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->backend()); + $rows = array_to_rows( + (new DeclaredColumns())->project($rows->toArray(), $this->schema), + $this->schema, + $context->backend(), + ); } $signal = yield $rows; diff --git a/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php b/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php index b64724d7a1..08faa59cf4 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php +++ b/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php @@ -7,6 +7,7 @@ use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\SchemaMismatchException; +use Flow\ETL\Row\DeclaredColumns; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; @@ -38,7 +39,7 @@ public function __construct( public function of(array $rows, Schema $schema, Backend $backend): Rows { try { - $batch = array_to_rows($rows, $schema, $backend); + $batch = array_to_rows((new DeclaredColumns())->project($rows, $schema), $schema, $backend); } catch (SchemaMismatchException $mismatch) { $row = $this->offset + $mismatch->rowIndex; diff --git a/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php b/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php index 6288a731be..aecfb01c54 100644 --- a/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php +++ b/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php @@ -13,7 +13,9 @@ use Flow\Filesystem\Path\Filter; use Throwable; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function sprintf; final readonly class ScalarFunctionFilter implements Filter @@ -39,11 +41,13 @@ public function __construct( public function accept(FileStatus $status): bool { $values = []; + $definitions = []; foreach ($status->path->partitions()->toArray() as $partition) { // 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); + $definitions[] = $definition ?? str_schema($partition->name, nullable: true); if ($definition === null || $definition->matches($partition->value)) { $values[$partition->name] = $partition->value; @@ -69,6 +73,6 @@ public function accept(FileStatus $status): bool } // @mago-ignore analysis:mixed-operand - return (bool) $this->resolved->eval(row($values), $this->context); + return (bool) $this->resolved->eval(array_to_row($values, schema(...$definitions)), $this->context); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/CountingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/CountingProcessor.php index 485304d5c5..dcf1b0b76d 100644 --- a/src/core/etl/src/Flow/ETL/Processor/CountingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/CountingProcessor.php @@ -11,9 +11,8 @@ use Flow\ETL\Schema; use Generator; +use function Flow\ETL\DSL\array_to_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; final readonly class CountingProcessor implements Processor @@ -39,7 +38,7 @@ public function process(Generator $rows, FlowContext $context): Generator */ public function rows(int $count): Rows { - return rows($this->schema(), row(['count' => $count])); + return array_to_rows([['count' => $count]], $this->schema()); } public function schema(): Schema diff --git a/src/core/etl/src/Flow/ETL/Row/DeclaredColumns.php b/src/core/etl/src/Flow/ETL/Row/DeclaredColumns.php new file mode 100644 index 0000000000..5085fead9e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Row/DeclaredColumns.php @@ -0,0 +1,38 @@ +> $rows + * + * @return list> + */ + public function project(array $rows, Schema $schema): array + { + $declared = array_flip($schema->references()->names()); + $projected = []; + + foreach ($rows as $row) { + foreach (array_keys(array_diff_key($row, $declared)) as $key) { + if (!is_int($key) || $schema->findDefinition((new ColumnName())->of($key)) === null) { + unset($row[$key]); + } + } + + $projected[] = $row; + } + + return $projected; + } +} diff --git a/src/core/etl/src/Flow/ETL/Row/InferredBatch.php b/src/core/etl/src/Flow/ETL/Row/InferredBatch.php deleted file mode 100644 index 98eb658091..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/InferredBatch.php +++ /dev/null @@ -1,68 +0,0 @@ -> $batch - */ - public function of(array $batch): Rows - { - $schema = new Schema(); - - foreach ($batch as $values) { - $definitions = []; - - /** @var mixed $value */ - foreach ($values as $name => $value) { - // PHP hands a numeric column name back as an INT key - a pivot names its columns by their own values - $definitions[] = definition_from_type( - (string) $name, - $this->typeDetector->detectType($value), - $value === null, - ); - } - - $schema = $schema->merge(new Schema(...$definitions)); - } - - $backend = new DefaultBackend(); - - // one row's schema is typed from its own values, so every value already fits: one constant per column spares - // the builders a single-row batch does not need - if (count($batch) === 1) { - $columns = []; - - foreach ($schema->definitions() as $name => $definition) { - $columns[$name] = $backend->constant($definition, $batch[0][$name], 1); - } - - return Rows::fromColumns($schema, $columns, 1); - } - - // the fold widens a column typed from one row's value to cover every row's, so the builder casts each value - // to the schema this method just derived - return (new RowsBuilder($schema, $backend)) - ->appendRows($batch) - ->finish(); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/RankingContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/RankingContext.php index f134ea4f4b..88f8f3b553 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/RankingContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/RankingContext.php @@ -6,9 +6,8 @@ use Flow\ETL\Rows; +use function Flow\ETL\DSL\array_to_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; /** @@ -22,25 +21,29 @@ final class RankingContext { public static function salariesAscending(): Rows { - return rows( + return array_to_rows( + [ + ['id' => 4, 'salary' => 2000], + ['id' => 5, 'salary' => 4000], + ['id' => 1, 'salary' => 6000], + ['id' => 2, 'salary' => 6000], + ['id' => 3, 'salary' => 6000], + ], schema(int_schema('id'), int_schema('salary')), - row(['id' => 4, 'salary' => 2000]), - row(['id' => 5, 'salary' => 4000]), - row(['id' => 1, 'salary' => 6000]), - row(['id' => 2, 'salary' => 6000]), - row(['id' => 3, 'salary' => 6000]), ); } public static function salariesDescending(): Rows { - return rows( + return array_to_rows( + [ + ['id' => 1, 'salary' => 6000], + ['id' => 2, 'salary' => 6000], + ['id' => 3, 'salary' => 6000], + ['id' => 5, 'salary' => 4000], + ['id' => 4, 'salary' => 2000], + ], schema(int_schema('id'), int_schema('salary')), - row(['id' => 1, 'salary' => 6000]), - row(['id' => 2, 'salary' => 6000]), - row(['id' => 3, 'salary' => 6000]), - row(['id' => 5, 'salary' => 4000]), - row(['id' => 4, 'salary' => 2000]), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/ScoredRows.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ScoredRows.php index 5ec471442b..117cc04509 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/ScoredRows.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ScoredRows.php @@ -8,9 +8,8 @@ use Generator; use function array_merge; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -30,10 +29,10 @@ public static function batches(array ...$batches): Generator $rows = []; foreach ($batch as [$score, $name]) { - $rows[] = row(['score' => $score, 'name' => $name]); + $rows[] = ['score' => $score, 'name' => $name]; } - yield rows(schema(int_schema('score'), str_schema('name')), ...$rows); + yield array_to_rows($rows, schema(int_schema('score'), str_schema('name'))); } } 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 fe8606f745..10bfefb505 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php @@ -10,8 +10,7 @@ use Flow\ETL\Schema; use Flow\ETL\Transformer; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; +use function Flow\ETL\DSL\array_to_rows; use function Flow\Types\DSL\type_string; use function sprintf; @@ -38,7 +37,7 @@ public function transform(Rows $rows, FlowContext $context): Rows $stamped = []; foreach ($rows->all() as $row) { - $stamped[] = row([ + $stamped[] = [ ...$row->values(), $this->entryName => sprintf( '%s%s%s', @@ -46,9 +45,9 @@ public function transform(Rows $rows, FlowContext $context): Rows $this->divider, $this->stamp, ), - ]); + ]; } - return rows($rows->schema(), ...$stamped); + return array_to_rows($stamped, $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 d6e616ac4e..52e2008edc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeExtractor.php @@ -16,6 +16,7 @@ use Generator; use Ramsey\Uuid\Uuid; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\enum_schema; @@ -26,8 +27,6 @@ use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\null_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; use function Flow\ETL\DSL\structure_schema; @@ -91,7 +90,28 @@ public function extract(FlowContext $context, ?int $limit = null): Generator for ($i = 0; $i < $this->total; $i++) { $id = $i; - yield rows( + yield array_to_rows( + [[ + 'int' => $id, + 'float' => type_float()->cast(generate_random_int(100, 100000) / 100), + 'bool' => random_int(0, 1) === 1, + 'datetime' => new DateTimeImmutable('now'), + 'null' => null, + 'uuid' => new FlowUuid(Uuid::uuid4()), + 'json' => type_json()->cast(['id' => $id, 'status' => 'NEW']), + 'list' => [1, 2, 3], + 'list_of_datetimes' => [new DateTimeImmutable(), new DateTimeImmutable(), new DateTimeImmutable()], + 'map' => ['NEW', 'PENDING'], + 'struct' => [ + 'street' => 'street_' . $id, + 'city' => 'city_' . $id, + 'zip' => 'zip_' . $id, + 'country' => 'country_' . $id, + 'location' => ['lat' => 1.5, 'lon' => 1.5], + ], + 'enum' => BackedStringEnum::three, + 'xml' => type_xml()->cast('node-' . $id . ''), + ]], schema( int_schema('int'), float_schema('float'), @@ -116,27 +136,6 @@ public function extract(FlowContext $context, ?int $limit = null): Generator enum_schema('enum', BackedStringEnum::class), xml_schema('xml'), ), - row([ - 'int' => $id, - 'float' => type_float()->cast(generate_random_int(100, 100000) / 100), - 'bool' => random_int(0, 1) === 1, - 'datetime' => new DateTimeImmutable('now'), - 'null' => null, - 'uuid' => new FlowUuid(Uuid::uuid4()), - 'json' => type_json()->cast(['id' => $id, 'status' => 'NEW']), - 'list' => [1, 2, 3], - 'list_of_datetimes' => [new DateTimeImmutable(), new DateTimeImmutable(), new DateTimeImmutable()], - 'map' => ['NEW', 'PENDING'], - 'struct' => [ - 'street' => 'street_' . $id, - 'city' => 'city_' . $id, - 'zip' => 'zip_' . $id, - 'country' => 'country_' . $id, - 'location' => ['lat' => 1.5, 'lon' => 1.5], - ], - 'enum' => BackedStringEnum::three, - 'xml' => type_xml()->cast('node-' . $id . ''), - ]), ); } } 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 b600a182b0..4223d92e8b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingAfterFirstBatchExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowingAfterFirstBatchExtractor.php @@ -11,16 +11,15 @@ use Generator; use RuntimeException; +use function Flow\ETL\DSL\array_to_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; final class ThrowingAfterFirstBatchExtractor implements Extractor { public function extract(FlowContext $context, ?int $limit = null): Generator { - yield rows($this->schema(), row(['id' => 1])); + yield array_to_rows([['id' => 1]], $this->schema()); throw new RuntimeException('source failed after its first batch'); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Fixtures/with-dataframe.php b/src/core/etl/tests/Flow/ETL/Tests/Fixtures/with-dataframe.php index b8e3660c37..9ba4c9f09f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Fixtures/with-dataframe.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Fixtures/with-dataframe.php @@ -2,15 +2,16 @@ declare(strict_types=1); +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\data_frame; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; -return data_frame()->process(rows( +return data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), )); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php index f2a28f159f..d812528ee9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php @@ -13,10 +13,11 @@ use Flow\Floe\FloeWriter; use function array_map; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; 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; use function Flow\ETL\DSL\str_schema; @@ -35,11 +36,11 @@ public function test_append_after_get_does_not_truncate_the_bucket(): void $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]))); + $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); static::assertCount(1, BucketsStorageContext::rows($storage->get('bucket'))); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 2]))); + $storage->append('bucket', array_to_rows([['id' => 2]], schema(int_schema('id')))); static::assertCount(2, BucketsStorageContext::rows($storage->get('bucket'))); @@ -52,14 +53,14 @@ public function test_append_with_a_column_absent_from_the_bucket_schema_fails(): $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]))); + $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessageMatches('/new column "name"/'); - $storage->append('bucket', rows( + $storage->append('bucket', array_to_rows( + [['id' => 2, 'name' => 'John']], schema(int_schema('id'), str_schema('name')), - row(['id' => 2, 'name' => 'John']), )); } @@ -69,12 +70,12 @@ public function test_append_widening_a_column_type_fails(): void $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); - $storage->append('bucket', rows(schema(int_schema('amount')), row(['amount' => 1]))); + $storage->append('bucket', array_to_rows([['amount' => 1]], schema(int_schema('amount')))); $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessageMatches('/expected: amount, given: amount/'); - $storage->append('bucket', rows(schema(float_schema('amount')), row(['amount' => 1.5]))); + $storage->append('bucket', array_to_rows([['amount' => 1.5]], schema(float_schema('amount')))); } public function test_appends_accumulate_into_one_bucket_in_order(): void @@ -83,9 +84,9 @@ public function test_appends_accumulate_into_one_bucket_in_order(): void $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, batchSize: 2); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 3]))); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 4]), row(['id' => 5]))); + $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); + $storage->append('bucket', array_to_rows([['id' => 4], ['id' => 5]], schema(int_schema('id')))); static::assertSame( [1, 2, 3, 4, 5], @@ -101,12 +102,7 @@ public function test_custom_batch_size_round_trips_all_rows(): void $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, batchSize: 2); - $storage->append('bucket', rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - )); + $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id')))); static::assertCount(3, BucketsStorageContext::rows($storage->get('bucket'))); @@ -130,7 +126,7 @@ public function test_remove_closes_an_open_append_session(): void $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]))); + $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $storage->remove('bucket'); static::assertSame([], BucketsStorageContext::rows($storage->get('bucket'))); @@ -144,7 +140,7 @@ public function test_remove_deletes_the_bucket(): void $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]))); + $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $storage->remove('bucket'); static::assertSame([], BucketsStorageContext::rows($storage->get('bucket'))); @@ -162,12 +158,15 @@ public function test_round_trips_rows_across_the_read_batch_boundary(): void $input = []; for ($i = 0; $i < 1500; $i++) { - $input[] = row(['id' => $i]); + $input[] = ['id' => $i]; } - $storage->append('bucket', rows(schema(int_schema('id')), ...$input)); + $storage->append('bucket', array_to_rows($input, schema(int_schema('id')))); - static::assertEquals($input, BucketsStorageContext::rows($storage->get('bucket'))); + static::assertSame($input, array_map( + static fn(Row $r): array => $r->toArray(), + BucketsStorageContext::rows($storage->get('bucket')), + )); $this->fs()->rm($cacheDir); } @@ -178,8 +177,8 @@ public function test_set_replaces_a_bucket_written_with_append(): void $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); - $storage->set('bucket', rows(schema(int_schema('id')), row(['id' => 3]))); + $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $storage->set('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); static::assertSame( [3], @@ -210,9 +209,9 @@ public function test_round_trips_schema_changing_rows(): void $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); $input = [ - row(['id' => 1]), - row(['id' => 2, 'name' => 'John']), - row(['name' => 'Jane']), + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2, 'name' => 'John'], schema(int_schema('id'), str_schema('name'))), + array_to_row(['name' => 'Jane'], schema(str_schema('name'))), ]; $storage->append('bucket', rows( @@ -240,7 +239,8 @@ public function test_append_with_reordered_structure_keys_matches_and_keeps_ever $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); - $storage->append('bucket', rows( + $storage->append('bucket', array_to_rows( + [['id' => 1, 's' => ['a' => 1, 'b' => 'x']]], schema( int_schema('id'), structure_schema('s', type_structure([ @@ -248,9 +248,9 @@ public function test_append_with_reordered_structure_keys_matches_and_keeps_ever 'b' => type_string(), ])), ), - row(['id' => 1, 's' => ['a' => 1, 'b' => 'x']]), )); - $storage->append('bucket', rows( + $storage->append('bucket', array_to_rows( + [['id' => 2, 's' => ['b' => 'y', 'a' => 2]]], schema( int_schema('id'), structure_schema('s', type_structure([ @@ -258,7 +258,6 @@ public function test_append_with_reordered_structure_keys_matches_and_keeps_ever 'a' => type_integer(), ])), ), - row(['id' => 2, 's' => ['b' => 'y', 'a' => 2]]), )); $read = BucketsStorageContext::rows($storage->get('bucket')); @@ -276,8 +275,14 @@ public function test_append_with_reordered_columns_matches_and_keeps_every_row() $this->fs()->rm($cacheDir); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); - $storage->append('bucket', rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'x']))); - $storage->append('bucket', rows(schema(str_schema('name'), int_schema('id')), row(['name' => 'y', 'id' => 2]))); + $storage->append('bucket', array_to_rows( + [['id' => 1, 'name' => 'x']], + schema(int_schema('id'), str_schema('name')), + )); + $storage->append('bucket', array_to_rows( + [['name' => 'y', 'id' => 2]], + schema(str_schema('name'), int_schema('id')), + )); $read = BucketsStorageContext::rows($storage->get('bucket')); @@ -296,7 +301,10 @@ public function test_append_resume_with_a_genuinely_different_column_set_still_t $writer = new FloeWriter( $this->fs(), - ($first = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'x'])))->schema(), + ($first = array_to_rows( + [['id' => 1, 'name' => 'x']], + schema(int_schema('id'), str_schema('name')), + ))->schema(), ); $writer->create($path); $writer->write($first); @@ -304,7 +312,7 @@ public function test_append_resume_with_a_genuinely_different_column_set_still_t $writer = new FloeWriter( $this->fs(), - rows(schema(int_schema('id'), str_schema('city')), row(['id' => 2, 'city' => 'y']))->schema(), + array_to_rows([['id' => 2, 'city' => 'y']], schema(int_schema('id'), str_schema('city')))->schema(), ); $this->expectException(IncompatibleSchemaException::class); @@ -317,10 +325,9 @@ public function test_datetime_values_read_back_as_admitted(): void $cacheDir = path(__DIR__ . '/var/buckets_datetime_zone'); $this->fs()->rm($cacheDir); - $rows = rows( - schema(datetime_schema('at', zone: 'Europe/Warsaw')), - row(['at' => new DateTimeImmutable('2026-01-02 03:04:05+05:00')]), - ); + $rows = array_to_rows([[ + 'at' => new DateTimeImmutable('2026-01-02 03:04:05+05:00'), + ]], schema(datetime_schema('at', zone: 'Europe/Warsaw'))); $admitted = type_datetime()->assert($rows->first()->get('at'))->format('c'); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php index 06a477f1ff..38192652c2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php @@ -14,9 +14,8 @@ use Symfony\Component\Cache\Psr16Cache; use function array_map; +use function Flow\ETL\DSL\array_to_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; use function getenv; @@ -48,8 +47,8 @@ public function test_round_trips_rows_across_chunks_and_removes_the_bucket(): vo ]))); $storage = new PSRCacheBuckets($cache, prefix: 'flow:buckets:test:round_trip'); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 3]))); + $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); static::assertSame( [1, 2, 3], diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/CacheTestCase.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/CacheTestCase.php index 5a6f440e1a..c5dac661c1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/CacheTestCase.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/CacheTestCase.php @@ -11,9 +11,8 @@ use Flow\ETL\Tests\FlowIntegrationTestCase; use Override; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -61,7 +60,10 @@ public function test_caching_rows(): void static::assertFalse($cache->has('rows')); - $cache->set('rows', $rows = rows(schema(str_schema('name')), row(['name' => 'John']), row(['name' => 'Jane']))); + $cache->set( + 'rows', + $rows = array_to_rows([['name' => 'John'], ['name' => 'Jane']], schema(str_schema('name'))), + ); static::assertTrue($cache->has('rows')); @@ -74,7 +76,7 @@ public function test_caching_schema(): void $cache->set( 'rows', - $rows = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'John'])), + $rows = array_to_rows([['id' => 1, 'name' => 'John']], schema(int_schema('id'), str_schema('name'))), ); static::assertEquals($rows->schema(), $cache->schema('rows')); @@ -92,8 +94,8 @@ public function test_clearing_cache(): void $cache = $this->cache(); $cache->set('index', (new CacheIndex('index'))->toRows()); - $cache->set('row', rows(schema(str_schema('name')), row(['name' => 'John']))); - $cache->set('rows', rows(schema(str_schema('name')), row(['name' => 'John']), row(['name' => 'Jane']))); + $cache->set('row', array_to_rows([['name' => 'John']], schema(str_schema('name')))); + $cache->set('rows', array_to_rows([['name' => 'John'], ['name' => 'Jane']], schema(str_schema('name')))); $cache->clear(); @@ -106,7 +108,7 @@ public function test_clearing_cache_removes_schemas(): void { $cache = $this->cache(); - $cache->set('rows', rows(schema(str_schema('name')), row(['name' => 'John']))); + $cache->set('rows', array_to_rows([['name' => 'John']], schema(str_schema('name')))); $cache->clear(); @@ -138,8 +140,8 @@ public function test_removing_from_cache(): void $cache = $this->cache(); $cache->set('index', (new CacheIndex('index'))->toRows()); - $cache->set('row', rows(schema(str_schema('name')), row(['name' => 'John']))); - $cache->set('rows', rows(schema(str_schema('name')), row(['name' => 'John']), row(['name' => 'Jane']))); + $cache->set('row', array_to_rows([['name' => 'John']], schema(str_schema('name')))); + $cache->set('rows', array_to_rows([['name' => 'John'], ['name' => 'Jane']], schema(str_schema('name')))); $cache->delete('row'); @@ -152,8 +154,8 @@ public function test_removing_from_cache_removes_its_schema(): void { $cache = $this->cache(); - $cache->set('row', rows(schema(str_schema('name')), row(['name' => 'John']))); - $cache->set('rows', $rows = rows(schema(int_schema('id')), row(['id' => 1]))); + $cache->set('row', array_to_rows([['name' => 'John']], schema(str_schema('name')))); + $cache->set('rows', $rows = array_to_rows([['id' => 1]], schema(int_schema('id')))); $cache->delete('row'); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/FilesystemCacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/FilesystemCacheTest.php index 50c4a80e98..d17089a94e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/FilesystemCacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/FilesystemCacheTest.php @@ -12,9 +12,8 @@ use function file_get_contents; use function file_put_contents; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\structure_schema; use function Flow\Filesystem\DSL\path; @@ -31,7 +30,7 @@ final class FilesystemCacheTest extends CacheTestCase public function test_torn_entry_is_treated_as_a_cache_miss(): void { $cache = $this->cache(); - $cache->set('torn', rows(schema(int_schema('id')), row(['id' => 1]))); + $cache->set('torn', array_to_rows([['id' => 1]], schema(int_schema('id')))); // simulate a crash mid-write / bit rot: overwrite the closed cache file with garbage $files = glob(__DIR__ . '/var/filesystem-cache/*/*/*/*/torn') ?: []; @@ -46,7 +45,7 @@ public function test_torn_entry_is_treated_as_a_cache_miss(): void public function test_corrupted_frame_with_intact_footer_is_treated_as_a_cache_miss(): void { $cache = $this->cache(); - $cache->set('corrupt', rows(schema(int_schema('id')), row(['id' => 1]))); + $cache->set('corrupt', array_to_rows([['id' => 1]], schema(int_schema('id')))); $files = glob(__DIR__ . '/var/filesystem-cache/*/*/*/*/corrupt') ?: []; static::assertNotEmpty($files); @@ -68,7 +67,7 @@ public function test_custom_serializer_is_used_for_set_and_get(): void $cache = new FilesystemCache($this->fs(), path(__DIR__ . '/var/filesystem-cache-spy'), $spy); $cache->clear(); - $cache->set('spy', $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); + $cache->set('spy', $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); static::assertEquals($rows, $cache->get('spy')); static::assertCount(1, $spy->serialized); @@ -80,7 +79,7 @@ public function test_custom_serializer_is_used_for_set_and_get(): void public function test_schema_of_an_entry_without_a_stored_schema_is_a_cache_miss(): void { $cache = $this->cache(); - $cache->set('orphan', rows(schema(int_schema('id')), row(['id' => 1]))); + $cache->set('orphan', array_to_rows([['id' => 1]], schema(int_schema('id')))); $files = glob(__DIR__ . '/var/filesystem-cache/*/*/*/*/orphan.schema') ?: []; static::assertNotEmpty($files); @@ -94,7 +93,7 @@ public function test_schema_of_an_entry_without_a_stored_schema_is_a_cache_miss( public function test_torn_schema_is_treated_as_a_cache_miss(): void { $cache = $this->cache(); - $cache->set('torn-schema', rows(schema(int_schema('id')), row(['id' => 1]))); + $cache->set('torn-schema', array_to_rows([['id' => 1]], schema(int_schema('id')))); $files = glob(__DIR__ . '/var/filesystem-cache/*/*/*/*/torn-schema.schema') ?: []; static::assertNotEmpty($files); @@ -112,10 +111,9 @@ public function test_legacy_structure_schema_payload_is_rejected_loudly(): void // this single test pins the contract for all three $cache = $this->cache(); - $cache->set('legacy', rows( - schema(structure_schema('s', type_structure(['a' => type_integer()]))), - row(['s' => ['a' => 1]]), - )); + $cache->set('legacy', array_to_rows([['s' => [ + 'a' => 1, + ]]], schema(structure_schema('s', type_structure(['a' => type_integer()]))))); $files = glob(__DIR__ . '/var/filesystem-cache/*/*/*/*/legacy.schema') ?: []; static::assertNotEmpty($files); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleFilesystemCacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleFilesystemCacheTest.php index 228abdff07..8c7c651a8b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleFilesystemCacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleFilesystemCacheTest.php @@ -10,9 +10,8 @@ use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Psr16Cache; +use function Flow\ETL\DSL\array_to_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; final class PSRSimpleFilesystemCacheTest extends CacheTestCase @@ -21,7 +20,7 @@ public function test_torn_entry_is_treated_as_a_cache_miss(): void { $psr = new Psr16Cache(new FilesystemAdapter(directory: __DIR__ . '/var/psr-simple-file-cache')); $cache = new PSRSimpleCache($psr); - $cache->set('torn', rows(schema(int_schema('id')), row(['id' => 1]))); + $cache->set('torn', array_to_rows([['id' => 1]], schema(int_schema('id')))); $psr->set('torn', 'not a valid floe payload'); @@ -34,7 +33,7 @@ public function test_schema_of_an_entry_without_a_stored_schema_is_a_cache_miss( { $psr = new Psr16Cache(new FilesystemAdapter(directory: __DIR__ . '/var/psr-simple-file-cache')); $cache = new PSRSimpleCache($psr); - $cache->set('orphan', rows(schema(int_schema('id')), row(['id' => 1]))); + $cache->set('orphan', array_to_rows([['id' => 1]], schema(int_schema('id')))); $psr->delete('orphan.schema'); @@ -47,7 +46,7 @@ public function test_torn_schema_is_treated_as_a_cache_miss(): void { $psr = new Psr16Cache(new FilesystemAdapter(directory: __DIR__ . '/var/psr-simple-file-cache')); $cache = new PSRSimpleCache($psr); - $cache->set('torn-schema', rows(schema(int_schema('id')), row(['id' => 1]))); + $cache->set('torn-schema', array_to_rows([['id' => 1]], schema(int_schema('id')))); $psr->set('torn-schema.schema', 'not a valid schema payload'); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/Bucketing/BucketingConfigBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/Bucketing/BucketingConfigBuilderTest.php index 3eb3e44377..cb80faa776 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/Bucketing/BucketingConfigBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/Bucketing/BucketingConfigBuilderTest.php @@ -7,9 +7,8 @@ use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; use Flow\ETL\Tests\FlowIntegrationTestCase; +use function Flow\ETL\DSL\array_to_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; use function Flow\Filesystem\DSL\path; use function iterator_to_array; @@ -22,7 +21,7 @@ public function test_build_uses_the_given_spill_root_for_the_default_storage(): (new BucketingConfigBuilder('/flow-php-sort/', 64)) ->build($spillRoot) - ->storage->set('bucket-1', rows(schema(int_schema('id')), row(['id' => 1]))); + ->storage->set('bucket-1', array_to_rows([['id' => 1]], schema(int_schema('id')))); static::assertNotSame( [], diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AlgorithmOverrideTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AlgorithmOverrideTest.php index 0902ace357..4bdef1fa70 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AlgorithmOverrideTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AlgorithmOverrideTest.php @@ -15,6 +15,7 @@ use Flow\Filesystem\Path\Filter\KeepAll; use function array_column; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\count as count_agg; use function Flow\ETL\DSL\df; @@ -26,8 +27,6 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\join_on; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; @@ -116,9 +115,9 @@ public function test_join_each_is_not_governed_by_the_join_algorithm(): void new class implements DataFrameFactory { public function from(Rows $rows): DataFrame { - return df()->process(rows( + return df()->process(array_to_rows( + [['id' => 1, 'n' => 'a']], schema(int_schema('id'), str_schema('n')), - row(['id' => 1, 'n' => 'a']), )); } }, 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 3e4ee98133..0839d6b593 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 @@ -21,12 +21,11 @@ use Override; use function Flow\ETL\DSL\analyze; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\external_sort; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\memory_sort; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function str_replace; @@ -55,7 +54,7 @@ public function test_config_serializer_reaches_the_default_cache(): void $config->cache->cache->set( 'key', - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), ); static::assertEquals($rows, $config->cache->cache->get('key')); 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 e362c2e8d8..1b861afc56 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 @@ -19,6 +19,7 @@ use Generator; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\df; @@ -31,8 +32,6 @@ use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_schema; @@ -73,7 +72,24 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 20; $i++) { - yield rows( + yield array_to_rows( + [[ + 'id' => 1234, + 'price' => 123.45, + '100' => 100, + 'deleted' => false, + 'created-at' => new DateTimeImmutable('2020-07-13 15:00'), + 'phase' => null, + 'array' => type_json()->cast([ + ['id' => 1, 'status' => 'NEW'], + ['id' => 2, 'status' => 'PENDING'], + ]), + 'list' => [1, 2, 3], + 'map' => ['NEW', 'PENDING'], + 'items' => ['item-id' => '1', 'name' => 'one'], + 'enum' => BackedStringEnum::three, + 'xml' => type_xml()->cast('testbar'), + ]], schema( int_schema('id'), float_schema('price'), @@ -91,24 +107,6 @@ public function extract(FlowContext $context, ?int $limit = null): Generator enum_schema('enum', BackedStringEnum::class), xml_schema('xml'), ), - // PHP casts the numeric column name "100" to an int array key - row([ - 'id' => 1234, - 'price' => 123.45, - '100' => 100, - 'deleted' => false, - 'created-at' => new DateTimeImmutable('2020-07-13 15:00'), - 'phase' => null, - 'array' => type_json()->cast([ - ['id' => 1, 'status' => 'NEW'], - ['id' => 2, 'status' => 'PENDING'], - ]), - 'list' => [1, 2, 3], - 'map' => ['NEW', 'PENDING'], - 'items' => ['item-id' => '1', 'name' => 'one'], - 'enum' => BackedStringEnum::three, - 'xml' => type_xml()->cast('testbar'), - ]), ); } } @@ -154,7 +152,15 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 5; $i++) { - yield rows( + yield array_to_rows( + [[ + 'id' => 1234, + 'price' => 123.45, + '100' => 100, + 'deleted' => false, + 'created-at' => new DateTimeImmutable('2020-07-13 15:00'), + 'group' => 'A', + ]], schema( int_schema('id'), float_schema('price'), @@ -163,20 +169,19 @@ public function extract(FlowContext $context, ?int $limit = null): Generator datetime_schema('created-at'), string_schema('group'), ), - // PHP casts the numeric column name "100" to an int array key - row([ + ); + } + + for ($i = 0; $i < 5; $i++) { + yield array_to_rows( + [[ 'id' => 1234, 'price' => 123.45, '100' => 100, 'deleted' => false, 'created-at' => new DateTimeImmutable('2020-07-13 15:00'), - 'group' => 'A', - ]), - ); - } - - for ($i = 0; $i < 5; $i++) { - yield rows( + 'group' => 'B', + ]], schema( int_schema('id'), float_schema('price'), @@ -185,15 +190,6 @@ public function extract(FlowContext $context, ?int $limit = null): Generator datetime_schema('created-at'), string_schema('group'), ), - // PHP casts the numeric column name "100" to an int array key - row([ - 'id' => 1234, - 'price' => 123.45, - '100' => 100, - 'deleted' => false, - 'created-at' => new DateTimeImmutable('2020-07-13 15:00'), - 'group' => 'B', - ]), ); } } @@ -288,21 +284,25 @@ public function test_print_rows(): void ob_start(); df() ->read(from_rows( - rows( + array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), ), - rows( + array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20, 'salary' => 5000], + ['id' => 1, 'country' => 'PL', 'age' => 20, 'salary' => null], + ], schema( int_schema('id'), str_schema('country'), int_schema('age'), int_schema('salary', nullable: true), ), - row(['id' => 1, 'country' => 'PL', 'age' => 20, 'salary' => 5000]), - row(['id' => 1, 'country' => 'PL', 'age' => 20, 'salary' => null]), ), )) ->printRows(); @@ -342,21 +342,25 @@ public function test_print_schema(): void ob_start(); df() ->read(from_rows( - rows( + array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), ), - rows( + array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20, 'salary' => 5000], + ['id' => 1, 'country' => 'PL', 'age' => 20, 'salary' => null], + ], schema( int_schema('id'), str_schema('country'), int_schema('age'), int_schema('salary', nullable: true), ), - row(['id' => 1, 'country' => 'PL', 'age' => 20, 'salary' => 5000]), - row(['id' => 1, 'country' => 'PL', 'age' => 20, 'salary' => null]), ), )) ->printSchema(); 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 e125ce1977..74905ee6c7 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 @@ -11,6 +11,7 @@ use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Types\Value\Uuid; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\collect; use function Flow\ETL\DSL\collect_unique; @@ -32,8 +33,6 @@ use function Flow\ETL\DSL\pivot_values; use function Flow\ETL\DSL\rank; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_agg; @@ -82,16 +81,18 @@ public function test_a_bare_reference_groups_like_a_one_element_array(): void public function test_group_by_array(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'score' => 20, 'array' => type_json()->cast(['a', 'b', 'c', 'd'])], + ['id' => 2, 'score' => 20, 'array' => type_json()->cast(['a', 'b', 'c', 'd'])], + ['id' => 3, 'score' => 25, 'array' => type_json()->cast(['a', 'b', 'c'])], + ['id' => 4, 'score' => 30, 'array' => type_json()->cast(['a', 'b', 'c'])], + ['id' => 5, 'score' => 40, 'array' => type_json()->cast(['a', 'b'])], + ['id' => 6, 'score' => 40, 'array' => type_json()->cast(['a', 'b'])], + ['id' => 7, 'score' => 45, 'array' => type_json()->cast(['a', 'b'])], + ['id' => 9, 'score' => 50, 'array' => type_json()->cast(['a'])], + ], schema(int_schema('id'), int_schema('score'), json_schema('array')), - row(['id' => 1, 'score' => 20, 'array' => type_json()->cast(['a', 'b', 'c', 'd'])]), - row(['id' => 2, 'score' => 20, 'array' => type_json()->cast(['a', 'b', 'c', 'd'])]), - row(['id' => 3, 'score' => 25, 'array' => type_json()->cast(['a', 'b', 'c'])]), - row(['id' => 4, 'score' => 30, 'array' => type_json()->cast(['a', 'b', 'c'])]), - row(['id' => 5, 'score' => 40, 'array' => type_json()->cast(['a', 'b'])]), - row(['id' => 6, 'score' => 40, 'array' => type_json()->cast(['a', 'b'])]), - row(['id' => 7, 'score' => 45, 'array' => type_json()->cast(['a', 'b'])]), - row(['id' => 9, 'score' => 50, 'array' => type_json()->cast(['a'])]), ))) ->groupBy(['array']) ->aggregate(sum('score'), average('score')) @@ -115,16 +116,18 @@ public function test_group_by_array(): void public function test_group_by_date_time(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'score' => 20, 'date' => type_datetime()->cast('2024-01-01 10:00:00')], + ['id' => 2, 'score' => 20, 'date' => type_datetime()->cast('2024-01-01 10:00:00')], + ['id' => 3, 'score' => 25, 'date' => type_datetime()->cast('2024-01-02 10:00:00')], + ['id' => 4, 'score' => 30, 'date' => type_datetime()->cast('2024-01-02 10:00:00')], + ['id' => 5, 'score' => 40, 'date' => type_datetime()->cast('2024-01-03 10:00:00')], + ['id' => 6, 'score' => 40, 'date' => type_datetime()->cast('2024-01-03 10:00:00')], + ['id' => 7, 'score' => 45, 'date' => type_datetime()->cast('2024-01-03 10:00:00')], + ['id' => 9, 'score' => 50, 'date' => type_datetime()->cast('2024-01-04 10:00:00')], + ], schema(int_schema('id'), int_schema('score'), datetime_schema('date')), - row(['id' => 1, 'score' => 20, 'date' => type_datetime()->cast('2024-01-01 10:00:00')]), - row(['id' => 2, 'score' => 20, 'date' => type_datetime()->cast('2024-01-01 10:00:00')]), - row(['id' => 3, 'score' => 25, 'date' => type_datetime()->cast('2024-01-02 10:00:00')]), - row(['id' => 4, 'score' => 30, 'date' => type_datetime()->cast('2024-01-02 10:00:00')]), - row(['id' => 5, 'score' => 40, 'date' => type_datetime()->cast('2024-01-03 10:00:00')]), - row(['id' => 6, 'score' => 40, 'date' => type_datetime()->cast('2024-01-03 10:00:00')]), - row(['id' => 7, 'score' => 45, 'date' => type_datetime()->cast('2024-01-03 10:00:00')]), - row(['id' => 9, 'score' => 50, 'date' => type_datetime()->cast('2024-01-04 10:00:00')]), ))) ->groupBy(['date']) ->aggregate(sum('score'), average('score')) @@ -156,16 +159,18 @@ public function test_group_by_multiple_columns_and_batch_size(): void $loader->expects(self::exactly(4))->method('load'); $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20, 'gender' => 'male'], + ['id' => 2, 'country' => 'PL', 'age' => 20, 'gender' => 'male'], + ['id' => 3, 'country' => 'PL', 'age' => 25, 'gender' => 'male'], + ['id' => 4, 'country' => 'PL', 'age' => 30, 'gender' => 'female'], + ['id' => 5, 'country' => 'US', 'age' => 40, 'gender' => 'female'], + ['id' => 6, 'country' => 'US', 'age' => 40, 'gender' => 'male'], + ['id' => 7, 'country' => 'US', 'age' => 45, 'gender' => 'female'], + ['id' => 9, 'country' => 'US', 'age' => 50, 'gender' => 'male'], + ], schema(int_schema('id'), str_schema('country'), int_schema('age'), str_schema('gender')), - row(['id' => 1, 'country' => 'PL', 'age' => 20, 'gender' => 'male']), - row(['id' => 2, 'country' => 'PL', 'age' => 20, 'gender' => 'male']), - row(['id' => 3, 'country' => 'PL', 'age' => 25, 'gender' => 'male']), - row(['id' => 4, 'country' => 'PL', 'age' => 30, 'gender' => 'female']), - row(['id' => 5, 'country' => 'US', 'age' => 40, 'gender' => 'female']), - row(['id' => 6, 'country' => 'US', 'age' => 40, 'gender' => 'male']), - row(['id' => 7, 'country' => 'US', 'age' => 45, 'gender' => 'female']), - row(['id' => 9, 'country' => 'US', 'age' => 50, 'gender' => 'male']), ))) ->groupBy(['country', 'gender']) ->aggregate(average(ref('age'))) @@ -188,16 +193,18 @@ public function test_group_by_multiple_columns_and_batch_size(): void public function test_group_by_multiples_columns_with_avg_aggregation(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20, 'gender' => 'male'], + ['id' => 2, 'country' => 'PL', 'age' => 20, 'gender' => 'male'], + ['id' => 3, 'country' => 'PL', 'age' => 25, 'gender' => 'male'], + ['id' => 4, 'country' => 'PL', 'age' => 30, 'gender' => 'female'], + ['id' => 5, 'country' => 'US', 'age' => 40, 'gender' => 'female'], + ['id' => 6, 'country' => 'US', 'age' => 40, 'gender' => 'male'], + ['id' => 7, 'country' => 'US', 'age' => 45, 'gender' => 'female'], + ['id' => 9, 'country' => 'US', 'age' => 50, 'gender' => 'male'], + ], schema(int_schema('id'), str_schema('country'), int_schema('age'), str_schema('gender')), - row(['id' => 1, 'country' => 'PL', 'age' => 20, 'gender' => 'male']), - row(['id' => 2, 'country' => 'PL', 'age' => 20, 'gender' => 'male']), - row(['id' => 3, 'country' => 'PL', 'age' => 25, 'gender' => 'male']), - row(['id' => 4, 'country' => 'PL', 'age' => 30, 'gender' => 'female']), - row(['id' => 5, 'country' => 'US', 'age' => 40, 'gender' => 'female']), - row(['id' => 6, 'country' => 'US', 'age' => 40, 'gender' => 'male']), - row(['id' => 7, 'country' => 'US', 'age' => 45, 'gender' => 'female']), - row(['id' => 9, 'country' => 'US', 'age' => 50, 'gender' => 'male']), ))) ->groupBy(['country', 'gender']) ->aggregate(average(ref('age'))) @@ -221,21 +228,23 @@ public function test_group_by_multiples_columns_with_avg_aggregation(): void public function test_group_by_multiples_columns_with_avg_aggregation_with_null(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20, 'gender' => 'male'], + ['id' => 2, 'country' => 'PL', 'age' => 20, 'gender' => 'male'], + ['id' => 3, 'country' => 'PL', 'age' => 25, 'gender' => 'male'], + ['id' => 4, 'country' => 'PL', 'age' => 30, 'gender' => 'female'], + ['id' => 5, 'country' => 'US', 'age' => 40, 'gender' => 'female'], + ['id' => 6, 'country' => 'US', 'age' => 40, 'gender' => 'male'], + ['id' => 7, 'country' => 'US', 'age' => 45, 'gender' => null], + ['id' => 9, 'country' => 'US', 'age' => 50, 'gender' => 'male'], + ], schema( int_schema('id'), str_schema('country'), int_schema('age'), str_schema('gender', nullable: true), ), - row(['id' => 1, 'country' => 'PL', 'age' => 20, 'gender' => 'male']), - row(['id' => 2, 'country' => 'PL', 'age' => 20, 'gender' => 'male']), - row(['id' => 3, 'country' => 'PL', 'age' => 25, 'gender' => 'male']), - row(['id' => 4, 'country' => 'PL', 'age' => 30, 'gender' => 'female']), - row(['id' => 5, 'country' => 'US', 'age' => 40, 'gender' => 'female']), - row(['id' => 6, 'country' => 'US', 'age' => 40, 'gender' => 'male']), - row(['id' => 7, 'country' => 'US', 'age' => 45, 'gender' => null]), - row(['id' => 9, 'country' => 'US', 'age' => 50, 'gender' => 'male']), ))) ->groupBy(['country', 'gender']) ->aggregate(average(ref('age'))) @@ -260,16 +269,18 @@ public function test_group_by_multiples_columns_with_avg_aggregation_with_null() public function test_group_by_single_column(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ['id' => 4, 'country' => 'PL', 'age' => 30], + ['id' => 5, 'country' => 'US', 'age' => 40], + ['id' => 6, 'country' => 'US', 'age' => 40], + ['id' => 7, 'country' => 'US', 'age' => 45], + ['id' => 9, 'country' => 'US', 'age' => 50], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), - row(['id' => 4, 'country' => 'PL', 'age' => 30]), - row(['id' => 5, 'country' => 'US', 'age' => 40]), - row(['id' => 6, 'country' => 'US', 'age' => 40]), - row(['id' => 7, 'country' => 'US', 'age' => 45]), - row(['id' => 9, 'country' => 'US', 'age' => 50]), ))) ->groupBy(['country']) ->aggregate(sum(ref('age'))) @@ -287,16 +298,18 @@ public function test_group_by_single_column(): void public function test_group_by_single_column_with_an_alias(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ['id' => 4, 'country' => 'PL', 'age' => 30], + ['id' => 5, 'country' => 'US', 'age' => 40], + ['id' => 6, 'country' => 'US', 'age' => 40], + ['id' => 7, 'country' => 'US', 'age' => 45], + ['id' => 9, 'country' => 'US', 'age' => 50], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), - row(['id' => 4, 'country' => 'PL', 'age' => 30]), - row(['id' => 5, 'country' => 'US', 'age' => 40]), - row(['id' => 6, 'country' => 'US', 'age' => 40]), - row(['id' => 7, 'country' => 'US', 'age' => 45]), - row(['id' => 9, 'country' => 'US', 'age' => 50]), ))) ->groupBy(['country']) ->aggregate(sum(ref('age')->as('total_age'))) @@ -314,16 +327,18 @@ public function test_group_by_single_column_with_an_alias(): void public function test_group_by_single_column_with_avg_aggregation(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ['id' => 4, 'country' => 'PL', 'age' => 30], + ['id' => 5, 'country' => 'US', 'age' => 40], + ['id' => 6, 'country' => 'US', 'age' => 40], + ['id' => 7, 'country' => 'US', 'age' => 45], + ['id' => 9, 'country' => 'US', 'age' => 50], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), - row(['id' => 4, 'country' => 'PL', 'age' => 30]), - row(['id' => 5, 'country' => 'US', 'age' => 40]), - row(['id' => 6, 'country' => 'US', 'age' => 40]), - row(['id' => 7, 'country' => 'US', 'age' => 45]), - row(['id' => 9, 'country' => 'US', 'age' => 50]), ))) ->groupBy(['country']) ->aggregate(average(ref('age'))) @@ -380,16 +395,18 @@ public function test_group_by_twice(): void public function test_group_by_uuid(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'score' => 20, 'uuid' => type_uuid()->cast('b97a23ab-ba84-4d8f-9d9a-abd32cc58110')], + ['id' => 2, 'score' => 20, 'uuid' => type_uuid()->cast('b97a23ab-ba84-4d8f-9d9a-abd32cc58110')], + ['id' => 3, 'score' => 25, 'uuid' => type_uuid()->cast('28fc1a5f-25eb-40e2-88b8-7a0cdc5d18ae')], + ['id' => 4, 'score' => 30, 'uuid' => type_uuid()->cast('28fc1a5f-25eb-40e2-88b8-7a0cdc5d18ae')], + ['id' => 5, 'score' => 40, 'uuid' => type_uuid()->cast('5085fabf-15f7-4467-9076-61547afbbdc9')], + ['id' => 6, 'score' => 40, 'uuid' => type_uuid()->cast('5085fabf-15f7-4467-9076-61547afbbdc9')], + ['id' => 7, 'score' => 45, 'uuid' => type_uuid()->cast('5085fabf-15f7-4467-9076-61547afbbdc9')], + ['id' => 9, 'score' => 50, 'uuid' => type_uuid()->cast('c7c22b40-45ad-46d1-a47b-0d1dd389ae41')], + ], schema(int_schema('id'), int_schema('score'), uuid_schema('uuid')), - row(['id' => 1, 'score' => 20, 'uuid' => type_uuid()->cast('b97a23ab-ba84-4d8f-9d9a-abd32cc58110')]), - row(['id' => 2, 'score' => 20, 'uuid' => type_uuid()->cast('b97a23ab-ba84-4d8f-9d9a-abd32cc58110')]), - row(['id' => 3, 'score' => 25, 'uuid' => type_uuid()->cast('28fc1a5f-25eb-40e2-88b8-7a0cdc5d18ae')]), - row(['id' => 4, 'score' => 30, 'uuid' => type_uuid()->cast('28fc1a5f-25eb-40e2-88b8-7a0cdc5d18ae')]), - row(['id' => 5, 'score' => 40, 'uuid' => type_uuid()->cast('5085fabf-15f7-4467-9076-61547afbbdc9')]), - row(['id' => 6, 'score' => 40, 'uuid' => type_uuid()->cast('5085fabf-15f7-4467-9076-61547afbbdc9')]), - row(['id' => 7, 'score' => 45, 'uuid' => type_uuid()->cast('5085fabf-15f7-4467-9076-61547afbbdc9')]), - row(['id' => 9, 'score' => 50, 'uuid' => type_uuid()->cast('c7c22b40-45ad-46d1-a47b-0d1dd389ae41')]), ))) ->groupBy(['uuid']) ->aggregate(sum('score'), average('score')) @@ -668,23 +685,25 @@ public function test_a_global_aggregate_emptied_by_a_filter_emits_one_row_of_typ public function test_standalone_avg_aggregation(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ['id' => 4, 'country' => 'PL', 'age' => 30], + ['id' => 5, 'country' => 'US', 'age' => 40], + ['id' => 6, 'country' => 'US', 'age' => 40], + ['id' => 7, 'country' => 'US', 'age' => 45], + ['id' => 9, 'country' => 'US', 'age' => 50], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), - row(['id' => 4, 'country' => 'PL', 'age' => 30]), - row(['id' => 5, 'country' => 'US', 'age' => 40]), - row(['id' => 6, 'country' => 'US', 'age' => 40]), - row(['id' => 7, 'country' => 'US', 'age' => 45]), - row(['id' => 9, 'country' => 'US', 'age' => 50]), ))) ->aggregate([average(ref('age'))]) ->rename('age_avg', 'average_age') ->fetch(); static::assertEquals( - rows(schema(float_schema('average_age', nullable: true)), row(['average_age' => 33.75])), + array_to_rows([['average_age' => 33.75]], schema(float_schema('average_age', nullable: true))), $rows, ); } @@ -692,16 +711,18 @@ public function test_standalone_avg_aggregation(): void public function test_standalone_avg_and_max_aggregation(): void { df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ['id' => 4, 'country' => 'PL', 'age' => 30], + ['id' => 5, 'country' => 'US', 'age' => 40], + ['id' => 6, 'country' => 'US', 'age' => 40], + ['id' => 7, 'country' => 'US', 'age' => 45], + ['id' => 9, 'country' => 'US', 'age' => 50], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), - row(['id' => 4, 'country' => 'PL', 'age' => 30]), - row(['id' => 5, 'country' => 'US', 'age' => 40]), - row(['id' => 6, 'country' => 'US', 'age' => 40]), - row(['id' => 7, 'country' => 'US', 'age' => 45]), - row(['id' => 9, 'country' => 'US', 'age' => 50]), ))) ->aggregate([average(ref('age')), max(ref('age'))]) ->forEach(function (Rows $rows): void { @@ -723,11 +744,13 @@ public function test_standalone_avg_and_max_aggregation(): void public function test_the_output_definition_does_not_vary_between_groups(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['group' => 'a', 'value' => 10.0], + ['group' => 'a', 'value' => 20.0], + ['group' => 'b', 'value' => 0.5], + ], schema(str_schema('group'), float_schema('value')), - row(['group' => 'a', 'value' => 10.0]), - row(['group' => 'a', 'value' => 20.0]), - row(['group' => 'b', 'value' => 0.5]), ))) ->groupBy(['group']) ->aggregate(min(ref('value'))) diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinCrossTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinCrossTest.php index dd1bc7b85b..78d2389ba7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinCrossTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinCrossTest.php @@ -7,13 +7,12 @@ use Flow\ETL\Loader; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\data_frame; 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; use function Flow\ETL\DSL\str_schema; @@ -25,18 +24,19 @@ public function test_cross_join(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'PL'], + ['id' => 4, 'country' => 'PL'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'PL']), - row(['id' => 4, 'country' => 'PL']), ))) ->batchSize(2) - ->crossJoin(data_frame()->process(rows( + ->crossJoin(data_frame()->process(array_to_rows( + [['num' => 1, 'active' => true], ['num' => 2, 'active' => false]], schema(int_schema('num'), bool_schema('active')), - row(['num' => 1, 'active' => true]), - row(['num' => 2, 'active' => false]), ))) ->write($loader) ->fetch(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinEachTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinEachTest.php index a2af8a1219..4b6c734cda 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinEachTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinEachTest.php @@ -11,13 +11,12 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\data_frame; 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\join_on; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -29,26 +28,27 @@ public function test_join_each(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'PL'], + ['id' => 4, 'country' => 'PL'], + ['id' => 5, 'country' => 'US'], + ['id' => 6, 'country' => 'US'], + ['id' => 7, 'country' => 'US'], + ['id' => 9, 'country' => 'US'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'PL']), - row(['id' => 4, 'country' => 'PL']), - row(['id' => 5, 'country' => 'US']), - row(['id' => 6, 'country' => 'US']), - row(['id' => 7, 'country' => 'US']), - row(['id' => 9, 'country' => 'US']), ))) ->batchSize(4) ->joinEach( new class implements DataFrameFactory { public function from(Rows $rows): DataFrame { - return data_frame()->process(rows( + return data_frame()->process(array_to_rows( + [['code' => 'PL', 'name' => 'Poland'], ['code' => 'US', 'name' => 'United States']], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), )); } }, @@ -78,26 +78,30 @@ public function test_join_each_without_prefix(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'PL'], + ['id' => 3, 'country_code' => 'PL'], + ['id' => 4, 'country_code' => 'PL'], + ['id' => 5, 'country_code' => 'US'], + ['id' => 6, 'country_code' => 'US'], + ['id' => 7, 'country_code' => 'US'], + ['id' => 9, 'country_code' => 'US'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'PL']), - row(['id' => 3, 'country_code' => 'PL']), - row(['id' => 4, 'country_code' => 'PL']), - row(['id' => 5, 'country_code' => 'US']), - row(['id' => 6, 'country_code' => 'US']), - row(['id' => 7, 'country_code' => 'US']), - row(['id' => 9, 'country_code' => 'US']), ))) ->batchSize(4) ->joinEach( new class implements DataFrameFactory { public function from(Rows $rows): DataFrame { - return data_frame()->process(rows( + return data_frame()->process(array_to_rows( + [ + ['country_code' => 'PL', 'name' => 'Poland'], + ['country_code' => 'US', 'name' => 'United States'], + ], schema(str_schema('country_code'), str_schema('name')), - row(['country_code' => 'PL', 'name' => 'Poland']), - row(['country_code' => 'US', 'name' => 'United States']), )); } }, diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinEmptySideTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinEmptySideTest.php index 3306190b8f..1f398bc59c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinEmptySideTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinEmptySideTest.php @@ -8,12 +8,12 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\hash_join; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\join_on; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -23,7 +23,7 @@ final class JoinEmptySideTest extends FlowTestCase public function test_cross_join_against_an_empty_side_yields_no_rows_under_the_cross_schema(): void { $joined = df() - ->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1])))) + ->read(from_rows(array_to_rows([['id' => 1]], schema(int_schema('id'))))) ->crossJoin(df()->process(rows(schema(str_schema('code'))))) ->fetch(); @@ -57,7 +57,7 @@ public function test_right_join_against_an_empty_left_side_keeps_the_left_column public function leftJoinedAgainstNothing(int $buckets): Rows { return df() - ->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])))) + ->read(from_rows(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))))) ->join( df()->process(rows(schema(int_schema('id'), str_schema('r')))), join_on(['id' => 'id']), @@ -75,7 +75,7 @@ public function rightJoinedAgainstNothing(int $buckets): Rows return df() ->read(from_rows(rows(schema(int_schema('id'), str_schema('l'))))) ->join( - df()->process(rows(schema(int_schema('id')), row(['id' => 1]))), + df()->process(array_to_rows([['id' => 1]], schema(int_schema('id')))), join_on(['id' => 'id']), Join::right, hash_join()->bucketsCount($buckets), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinTest.php index 21fd98233e..79b67e7601 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinTest.php @@ -14,6 +14,7 @@ use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\datetime_schema; @@ -22,8 +23,6 @@ use function Flow\ETL\DSL\hash_join; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\join_on; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function usort; @@ -36,21 +35,25 @@ public function test_join_inner(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'US'], + ['id' => 3, 'country' => 'FR'], + ['id' => 4, 'country' => 'UK'], + ['id' => 5, 'country' => 'GB'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), - row(['id' => 4, 'country' => 'UK']), - row(['id' => 5, 'country' => 'GB']), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'FR', 'name' => 'France'], + ['code' => 'CN', 'name' => 'Canada'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'FR', 'name' => 'France']), - row(['code' => 'CN', 'name' => 'Canada']), )), join_on(['country' => 'code'], 'joined_'), Join::inner, @@ -93,19 +96,23 @@ public function test_a_limit_after_a_resident_join_closes_the_loaders_before_it( public function test_join_inner_with_on_disk_buckets_cache(): void { $rows = df(config_builder()->join(hash_join()->bucketsCount(4))) - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'US'], + ['id' => 3, 'country' => 'FR'], + ['id' => 4, 'country' => 'UK'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), - row(['id' => 4, 'country' => 'UK']), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'FR', 'name' => 'France'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'FR', 'name' => 'France']), )), join_on(['country' => 'code'], 'joined_'), Join::inner, @@ -128,19 +135,23 @@ public function test_join_inner_with_on_disk_buckets_cache(): void public function test_join_inner_with_on_disk_buckets_preserves_a_nullable_column_present_and_null(): void { $rows = df(config_builder()->join(hash_join()->bucketsCount(2))) - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'note' => 'has-note'], + ['id' => 2, 'country' => 'US', 'note' => null], + ['id' => 3, 'country' => 'FR', 'note' => 'third'], + ['id' => 4, 'country' => 'PL', 'note' => null], + ], schema(int_schema('id'), str_schema('country'), str_schema('note', nullable: true)), - row(['id' => 1, 'country' => 'PL', 'note' => 'has-note']), - row(['id' => 2, 'country' => 'US', 'note' => null]), - row(['id' => 3, 'country' => 'FR', 'note' => 'third']), - row(['id' => 4, 'country' => 'PL', 'note' => null]), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'FR', 'name' => 'France'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'FR', 'name' => 'France']), )), join_on(['country' => 'code'], 'joined_'), Join::inner, @@ -167,22 +178,23 @@ public function test_join_left(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'PL'], + ['id' => 4, 'country' => 'PL'], + ['id' => 5, 'country' => 'US'], + ['id' => 6, 'country' => 'US'], + ['id' => 7, 'country' => 'US'], + ['id' => 9, 'country' => 'US'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'PL']), - row(['id' => 4, 'country' => 'PL']), - row(['id' => 5, 'country' => 'US']), - row(['id' => 6, 'country' => 'US']), - row(['id' => 7, 'country' => 'US']), - row(['id' => 9, 'country' => 'US']), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [['code' => 'PL', 'name' => 'Poland'], ['code' => 'US', 'name' => 'United States']], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), )), Expression::on(['country' => 'code'], 'joined_'), ) @@ -211,21 +223,25 @@ public function test_join_left_anti(): void $loader->expects(self::exactly(1))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'US'], + ['id' => 3, 'country' => 'FR'], + ['id' => 5, 'country' => 'GB'], + ['id' => 7, 'country' => 'CN'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), - row(['id' => 5, 'country' => 'GB']), - row(['id' => 7, 'country' => 'CN']), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'FR', 'name' => 'France'], + ['code' => 'CA', 'name' => 'Canada'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'FR', 'name' => 'France']), - row(['code' => 'CA', 'name' => 'Canada']), )), Expression::on(['country' => 'code'], 'joined_'), Join::left_anti, @@ -249,22 +265,26 @@ public function test_join_left_on_date_time_entry(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'date' => new DateTimeImmutable('2024-01-01 00:00:00')], + ['id' => 2, 'date' => new DateTimeImmutable('2024-01-01 00:00:00')], + ['id' => 3, 'date' => new DateTimeImmutable('2024-01-02 00:00:00')], + ['id' => 4, 'date' => new DateTimeImmutable('2024-01-03 00:00:00')], + ['id' => 5, 'date' => new DateTimeImmutable('2024-01-04 00:00:00')], + ['id' => 6, 'date' => new DateTimeImmutable('2024-01-04 00:00:00')], + ['id' => 7, 'date' => new DateTimeImmutable('2024-01-05 00:00:00')], + ['id' => 9, 'date' => new DateTimeImmutable('2024-01-05 00:00:00')], + ], schema(int_schema('id'), datetime_schema('date')), - row(['id' => 1, 'date' => new DateTimeImmutable('2024-01-01 00:00:00')]), - row(['id' => 2, 'date' => new DateTimeImmutable('2024-01-01 00:00:00')]), - row(['id' => 3, 'date' => new DateTimeImmutable('2024-01-02 00:00:00')]), - row(['id' => 4, 'date' => new DateTimeImmutable('2024-01-03 00:00:00')]), - row(['id' => 5, 'date' => new DateTimeImmutable('2024-01-04 00:00:00')]), - row(['id' => 6, 'date' => new DateTimeImmutable('2024-01-04 00:00:00')]), - row(['id' => 7, 'date' => new DateTimeImmutable('2024-01-05 00:00:00')]), - row(['id' => 9, 'date' => new DateTimeImmutable('2024-01-05 00:00:00')]), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [ + ['date' => new DateTimeImmutable('2024-01-01 00:00:00'), 'events' => 1], + ['date' => new DateTimeImmutable('2024-01-05 00:00:00'), 'events' => 5], + ], schema(datetime_schema('date'), int_schema('events')), - row(['date' => new DateTimeImmutable('2024-01-01 00:00:00'), 'events' => 1]), - row(['date' => new DateTimeImmutable('2024-01-05 00:00:00'), 'events' => 5]), )), Expression::on(['date' => 'date'], 'joined_'), Join::left, @@ -334,22 +354,23 @@ public function test_join_left_with_empty_prefix(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'PL'], + ['id' => 3, 'country_code' => 'PL'], + ['id' => 4, 'country_code' => 'PL'], + ['id' => 5, 'country_code' => 'US'], + ['id' => 6, 'country_code' => 'US'], + ['id' => 7, 'country_code' => 'US'], + ['id' => 9, 'country_code' => 'US'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'PL']), - row(['id' => 3, 'country_code' => 'PL']), - row(['id' => 4, 'country_code' => 'PL']), - row(['id' => 5, 'country_code' => 'US']), - row(['id' => 6, 'country_code' => 'US']), - row(['id' => 7, 'country_code' => 'US']), - row(['id' => 9, 'country_code' => 'US']), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [['country_code' => 'PL', 'name' => 'Poland'], ['country_code' => 'US', 'name' => 'United States']], schema(str_schema('country_code'), str_schema('name')), - row(['country_code' => 'PL', 'name' => 'Poland']), - row(['country_code' => 'US', 'name' => 'United States']), )), join_on(['country_code' => 'country_code']), ) @@ -378,22 +399,23 @@ public function test_join_on_same_column_name(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'code' => 'PL'], + ['id' => 2, 'code' => 'PL'], + ['id' => 3, 'code' => 'PL'], + ['id' => 4, 'code' => 'PL'], + ['id' => 5, 'code' => 'US'], + ['id' => 6, 'code' => 'US'], + ['id' => 7, 'code' => 'US'], + ['id' => 9, 'code' => 'US'], + ], schema(int_schema('id'), str_schema('code')), - row(['id' => 1, 'code' => 'PL']), - row(['id' => 2, 'code' => 'PL']), - row(['id' => 3, 'code' => 'PL']), - row(['id' => 4, 'code' => 'PL']), - row(['id' => 5, 'code' => 'US']), - row(['id' => 6, 'code' => 'US']), - row(['id' => 7, 'code' => 'US']), - row(['id' => 9, 'code' => 'US']), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [['code' => 'PL', 'name' => 'Poland'], ['code' => 'US', 'name' => 'United States']], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), )), Expression::on(['code' => 'code'], 'joined_'), ) @@ -422,21 +444,25 @@ public function test_join_right(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'US'], + ['id' => 3, 'country' => 'FR'], + ['id' => 4, 'country' => 'UK'], + ['id' => 5, 'country' => 'GB'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), - row(['id' => 4, 'country' => 'UK']), - row(['id' => 5, 'country' => 'GB']), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'FR', 'name' => 'France'], + ['code' => 'CA', 'name' => 'Canada'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'FR', 'name' => 'France']), - row(['code' => 'CA', 'name' => 'Canada']), )), Expression::on(['country' => 'code'], 'joined_'), Join::right, @@ -462,21 +488,25 @@ public function test_join_right_without_prefix(): void $loader->expects(self::exactly(2))->method('load'); $rows = df() - ->from(from_rows(rows( + ->from(from_rows(array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'US'], + ['id' => 3, 'country_code' => 'FR'], + ['id' => 4, 'country_code' => 'UK'], + ['id' => 5, 'country_code' => 'GB'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'US']), - row(['id' => 3, 'country_code' => 'FR']), - row(['id' => 4, 'country_code' => 'UK']), - row(['id' => 5, 'country_code' => 'GB']), ))) ->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [ + ['country_code' => 'PL', 'name' => 'Poland'], + ['country_code' => 'US', 'name' => 'United States'], + ['country_code' => 'FR', 'name' => 'France'], + ['country_code' => 'CA', 'name' => 'Canada'], + ], schema(str_schema('country_code'), str_schema('name')), - row(['country_code' => 'PL', 'name' => 'Poland']), - row(['country_code' => 'US', 'name' => 'United States']), - row(['country_code' => 'FR', 'name' => 'France']), - row(['country_code' => 'CA', 'name' => 'Canada']), )), Expression::on(['country_code' => 'country_code']), Join::right, 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 4d3a548d51..9e9e1003c1 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 @@ -23,6 +23,7 @@ use function array_column; use function array_map; use function array_slice; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\from_data_frame; @@ -32,7 +33,6 @@ use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\Types\DSL\type_integer; @@ -103,7 +103,7 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 20; $i++) { - yield rows(schema(integer_schema('id')), row(['id' => $i])); + yield array_to_rows([['id' => $i]], schema(integer_schema('id'))); } } @@ -138,7 +138,7 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => $i + 1], ['id' => $i + 2]], schema(integer_schema('id'))); } } @@ -199,22 +199,16 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 1000; $i++) { - yield rows( - schema(list_schema( - 'ids', - type_list(type_structure([ - 'id' => type_integer(), - 'more_ids' => type_list(type_map(type_string(), type_integer())), - ])), - )), - row([ - 'ids' => [ - ['id' => $i + 1, 'more_ids' => [['more_id' => $i + 4], ['more_id' => $i + 7]]], - ['id' => $i + 2, 'more_ids' => [['more_id' => $i + 5], ['more_id' => $i + 8]]], - ['id' => $i + 3, 'more_ids' => [['more_id' => $i + 6], ['more_id' => $i + 9]]], - ], - ]), - ); + yield array_to_rows([[ + 'ids' => [ + ['id' => $i + 1, 'more_ids' => [['more_id' => $i + 4], ['more_id' => $i + 7]]], + ['id' => $i + 2, 'more_ids' => [['more_id' => $i + 5], ['more_id' => $i + 8]]], + ['id' => $i + 3, 'more_ids' => [['more_id' => $i + 6], ['more_id' => $i + 9]]], + ], + ]], schema(list_schema('ids', type_list(type_structure([ + 'id' => type_integer(), + 'more_ids' => type_list(type_map(type_string(), type_integer())), + ]))))); } } @@ -261,7 +255,7 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => $i + 1], ['id' => $i + 2]], schema(integer_schema('id'))); } } @@ -299,7 +293,7 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => $i + 1], ['id' => $i + 2]], schema(integer_schema('id'))); } } @@ -337,7 +331,7 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 5; $i++) { - yield rows(schema(integer_schema('id')), row(['id' => $i])); + yield array_to_rows([['id' => $i]], schema(integer_schema('id'))); } } @@ -443,7 +437,7 @@ public function test_a_limit_over_a_read_frame_reaches_that_frames_source(bool $ { $source = new RecordingFileExtractor( schema(int_schema('id')), - rows(schema(int_schema('id')), ...array_map(static fn(int $id) => row(['id' => $id]), range(1, 6))), + array_to_rows(array_map(static fn(int $id) => ['id' => $id], range(1, 6)), schema(int_schema('id'))), ); $nested = from_data_frame(df()->read($source)); 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 c345d249d8..72d1520269 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,12 +7,12 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\sum; @@ -23,18 +23,20 @@ public function test_aggregations_on_floats(): void { $rows = rows(schema()); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'price' => 29.39, 'quantity' => 2, 'weight' => 1.5], + ['id' => 2, 'price' => 19.3, 'quantity' => 1, 'weight' => 0.5], + ['id' => 3, 'price' => 39.1, 'quantity' => 3, 'weight' => 2.0], + ['id' => 4, 'price' => 49.9, 'quantity' => 4, 'weight' => 2.1284], + ['id' => 5, 'price' => 15.0, 'quantity' => 1, 'weight' => 0.3], + ['id' => 6, 'price' => 30.0, 'quantity' => 2, 'weight' => 1.0], + ['id' => 7, 'price' => 25.0, 'quantity' => 3, 'weight' => 1.8], + ['id' => 8, 'price' => 20.0, 'quantity' => 1, 'weight' => 0.8], + ['id' => 9, 'price' => 35.0, 'quantity' => 4, 'weight' => 2.2], + ['id' => 10, 'price' => 45.0, 'quantity' => 5, 'weight' => 3.0], + ], schema(integer_schema('id'), float_schema('price'), integer_schema('quantity'), float_schema('weight')), - row(['id' => 1, 'price' => 29.39, 'quantity' => 2, 'weight' => 1.5]), - row(['id' => 2, 'price' => 19.3, 'quantity' => 1, 'weight' => 0.5]), - row(['id' => 3, 'price' => 39.1, 'quantity' => 3, 'weight' => 2.0]), - row(['id' => 4, 'price' => 49.9, 'quantity' => 4, 'weight' => 2.1284]), - row(['id' => 5, 'price' => 15.0, 'quantity' => 1, 'weight' => 0.3]), - row(['id' => 6, 'price' => 30.0, 'quantity' => 2, 'weight' => 1.0]), - row(['id' => 7, 'price' => 25.0, 'quantity' => 3, 'weight' => 1.8]), - row(['id' => 8, 'price' => 20.0, 'quantity' => 1, 'weight' => 0.8]), - row(['id' => 9, 'price' => 35.0, 'quantity' => 4, 'weight' => 2.2]), - row(['id' => 10, 'price' => 45.0, 'quantity' => 5, 'weight' => 3.0]), ))) ->aggregate([sum(ref('price')), sum(ref('weight'))]) ->forEach(static function (Rows $r) use (&$rows): void { @@ -53,18 +55,20 @@ public function test_mathematical_operations_on_floats(): void { $rows = rows(schema()); df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'price' => 29.39, 'quantity' => 2, 'weight' => 1.5], + ['id' => 2, 'price' => 19.3, 'quantity' => 1, 'weight' => 0.5], + ['id' => 3, 'price' => 39.1, 'quantity' => 3, 'weight' => 2.0], + ['id' => 4, 'price' => 49.9, 'quantity' => 4, 'weight' => 2.1284], + ['id' => 5, 'price' => 15.0, 'quantity' => 1, 'weight' => 0.3], + ['id' => 6, 'price' => 30.0, 'quantity' => 2, 'weight' => 1.0], + ['id' => 7, 'price' => 25.0, 'quantity' => 3, 'weight' => 1.8], + ['id' => 8, 'price' => 20.0, 'quantity' => 1, 'weight' => 0.8], + ['id' => 9, 'price' => 35.0, 'quantity' => 4, 'weight' => 2.2], + ['id' => 10, 'price' => 45.0, 'quantity' => 5, 'weight' => 3.0], + ], schema(integer_schema('id'), float_schema('price'), integer_schema('quantity'), float_schema('weight')), - row(['id' => 1, 'price' => 29.39, 'quantity' => 2, 'weight' => 1.5]), - row(['id' => 2, 'price' => 19.3, 'quantity' => 1, 'weight' => 0.5]), - row(['id' => 3, 'price' => 39.1, 'quantity' => 3, 'weight' => 2.0]), - row(['id' => 4, 'price' => 49.9, 'quantity' => 4, 'weight' => 2.1284]), - row(['id' => 5, 'price' => 15.0, 'quantity' => 1, 'weight' => 0.3]), - row(['id' => 6, 'price' => 30.0, 'quantity' => 2, 'weight' => 1.0]), - row(['id' => 7, 'price' => 25.0, 'quantity' => 3, 'weight' => 1.8]), - row(['id' => 8, 'price' => 20.0, 'quantity' => 1, 'weight' => 0.8]), - row(['id' => 9, 'price' => 35.0, 'quantity' => 4, 'weight' => 2.2]), - row(['id' => 10, 'price' => 45.0, 'quantity' => 5, 'weight' => 3.0]), ))) ->withEntry('discount', ref('price')->multiply(-0.1)) ->withEntry('total_weight', ref('weight')->multiply(ref('quantity'))) 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 e9fb7349ff..ee39ed6925 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 @@ -15,6 +15,7 @@ use Generator; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\from_rows; @@ -22,7 +23,6 @@ use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\Types\DSL\type_integer; @@ -139,7 +139,7 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => $i + 1]], schema(integer_schema('id'))); } } @@ -187,7 +187,7 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => $i + 1]], schema(integer_schema('id'))); } } @@ -237,21 +237,15 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 0; $i < 100; $i++) { - yield rows( - schema(list_schema( - 'ids', - type_list(type_structure([ - 'id' => type_integer(), - ])), - )), - row([ - 'ids' => [ - ['id' => $i + 1], - ['id' => $i + 2], - ['id' => $i + 3], - ], - ]), - ); + yield array_to_rows([[ + 'ids' => [ + ['id' => $i + 1], + ['id' => $i + 2], + ['id' => $i + 3], + ], + ]], schema(list_schema('ids', type_list(type_structure([ + 'id' => type_integer(), + ]))))); } } @@ -319,7 +313,7 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => $i + 1]], schema(integer_schema('id'))); } } 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 a563a6cdf9..94b13ff657 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 @@ -19,6 +19,7 @@ use function file_exists; use function Flow\ETL\Adapter\Text\from_text; use function Flow\ETL\Adapter\Text\to_text; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\collect; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\files; @@ -31,8 +32,6 @@ use function Flow\ETL\DSL\partition_by; use function Flow\ETL\DSL\partition_types; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_integer; @@ -215,13 +214,15 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void public function test_repartition_groups_every_row_sharing_a_key_into_one_batch(): void { $batches = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 5, 'country' => 'US', 'age' => 40], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 6, 'country' => 'US', 'age' => 40], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 5, 'country' => 'US', 'age' => 40]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 6, 'country' => 'US', 'age' => 40]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), ))) ->repartition(ref('country')) ->get(); 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 79dd806e45..bab5167d63 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 @@ -19,6 +19,7 @@ use Throwable; use function Flow\ETL\DSL\array_get; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\discover_pivot_values; @@ -32,7 +33,6 @@ use function Flow\ETL\DSL\rank; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\rename_replace; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -330,11 +330,10 @@ public function test_discovered_pivot_values_scan_the_source_once_at_build(): vo { $extractor = new CountingExtractor( $input = schema(str_schema('product'), str_schema('country'), int_schema('amount')), - rows( - $input, - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 1000]), - row(['product' => 'Banana', 'country' => 'China', 'amount' => 400]), - ), + array_to_rows([ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 1000], + ['product' => 'Banana', 'country' => 'China', 'amount' => 400], + ], $input), ); $schema = df() diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/RenameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/RenameTest.php index 0d5f4465f2..452c86520d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/RenameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/RenameTest.php @@ -8,6 +8,7 @@ use Flow\ETL\String\StringStyles; use Flow\ETL\Tests\FlowIntegrationTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; @@ -18,8 +19,6 @@ use function Flow\ETL\DSL\rename_map; use function Flow\ETL\DSL\rename_replace; use function Flow\ETL\DSL\rename_style; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_json; @@ -30,21 +29,25 @@ final class RenameTest extends FlowIntegrationTestCase public function test_rename(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'active' => false], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'active' => false]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), ))) ->rename('name', 'new_name') ->fetch(); static::assertEquals( - rows( + array_to_rows( + [ + ['id' => 1, 'new_name' => 'foo', 'active' => true], + ['id' => 2, 'new_name' => null, 'active' => false], + ['id' => 2, 'new_name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('new_name', nullable: true), bool_schema('active')), - row(['id' => 1, 'new_name' => 'foo', 'active' => true]), - row(['id' => 2, 'new_name' => null, 'active' => false]), - row(['id' => 2, 'new_name' => 'bar', 'active' => false]), ), $rows, ); @@ -53,17 +56,17 @@ public function test_rename(): void public function test_rename_each_with_numeric_entry_names(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [['broker' => 'acme', '2023' => 1, '2024' => 2]], schema(str_schema('broker'), int_schema('2023'), int_schema('2024')), - row(['broker' => 'acme', '2023' => 1, '2024' => 2]), ))) ->renameEach(rename_map(['2023' => 'y_2023', '2024' => 'y_2024'])) ->fetch(); static::assertEquals( - rows( + array_to_rows( + [['broker' => 'acme', 'y_2023' => 1, 'y_2024' => 2]], schema(str_schema('broker'), int_schema('y_2023'), int_schema('y_2024')), - row(['broker' => 'acme', 'y_2023' => 1, 'y_2024' => 2]), ), $rows, ); @@ -71,11 +74,10 @@ public function test_rename_each_with_numeric_entry_names(): void public function test_rename_all(): void { - $rows = rows( - schema(json_schema('array')), - row(['array' => type_json()->cast(['id' => 1, 'name' => 'name', 'active' => true])]), - row(['array' => type_json()->cast(['id' => 2, 'name' => 'name', 'active' => false])]), - ); + $rows = array_to_rows([ + ['array' => type_json()->cast(['id' => 1, 'name' => 'name', 'active' => true])], + ['array' => type_json()->cast(['id' => 2, 'name' => 'name', 'active' => false])], + ], schema(json_schema('array'))); $ds = df() ->read(from_rows($rows)) @@ -98,10 +100,9 @@ public function test_rename_all(): void public function test_rename_all_lower_case(): void { - $rows = rows( + $rows = array_to_rows( + [['ID' => 1, 'NAME' => 'name', 'ACTIVE' => true], ['ID' => 2, 'NAME' => 'name', 'ACTIVE' => false]], schema(int_schema('ID'), str_schema('NAME'), bool_schema('ACTIVE')), - row(['ID' => 1, 'NAME' => 'name', 'ACTIVE' => true]), - row(['ID' => 2, 'NAME' => 'name', 'ACTIVE' => false]), ); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::LOWER))->getEachAsArray(); @@ -117,11 +118,10 @@ public function test_rename_all_lower_case(): void public function test_rename_all_lower_case_i18n(): void { - $rows = rows( - schema(int_schema('ILOŚĆ PRZEDMIOTÓW')), - row(['ILOŚĆ PRZEDMIOTÓW' => 0]), - row(['ILOŚĆ PRZEDMIOTÓW' => 10]), - ); + $rows = array_to_rows([ + ['ILOŚĆ PRZEDMIOTÓW' => 0], + ['ILOŚĆ PRZEDMIOTÓW' => 10], + ], schema(int_schema('ILOŚĆ PRZEDMIOTÓW'))); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::LOWER))->getEachAsArray(); @@ -136,11 +136,10 @@ public function test_rename_all_lower_case_i18n(): void public function test_rename_all_multiple(): void { - $rows = rows( - schema(json_schema('array')), - row(['array' => type_json()->cast(['id' => 1, 'name' => 'name', 'isActive' => true])]), - row(['array' => type_json()->cast(['id' => 2, 'name' => 'name', 'isActive' => false])]), - ); + $rows = array_to_rows([ + ['array' => type_json()->cast(['id' => 1, 'name' => 'name', 'isActive' => true])], + ['array' => type_json()->cast(['id' => 2, 'name' => 'name', 'isActive' => false])], + ], schema(json_schema('array'))); $ds = df() ->read(from_rows($rows)) @@ -163,10 +162,9 @@ public function test_rename_all_multiple(): void public function test_rename_all_to_ascii(): void { - $rows = rows( + $rows = array_to_rows( + [['ÓSMY' => 8], ['DZIEWIĄTY' => 9]], schema(int_schema('ÓSMY', nullable: true), int_schema('DZIEWIĄTY', nullable: true)), - row(['ÓSMY' => 8]), - row(['DZIEWIĄTY' => 9]), ); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::ASCII))->getEachAsArray(); @@ -182,7 +180,7 @@ public function test_rename_all_to_ascii(): void public function test_rename_all_to_camel(): void { - $rows = rows(schema(int_schema('ósmy i dziewiąty')), row(['ósmy i dziewiąty' => 89])); + $rows = array_to_rows([['ósmy i dziewiąty' => 89]], schema(int_schema('ósmy i dziewiąty'))); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::CAMEL))->getEachAsArray(); @@ -196,7 +194,7 @@ public function test_rename_all_to_camel(): void public function test_rename_all_to_slug(): void { - $rows = rows(schema(int_schema('ÓSMY I DZIEWIĄTY')), row(['ÓSMY I DZIEWIĄTY' => 89])); + $rows = array_to_rows([['ÓSMY I DZIEWIĄTY' => 89]], schema(int_schema('ÓSMY I DZIEWIĄTY'))); $ds = df() ->read(from_rows($rows)) @@ -214,10 +212,12 @@ public function test_rename_all_to_slug(): void public function test_rename_all_to_snake_case(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'UserName' => 'name', 'isActive' => true], + ['id' => 2, 'UserName' => 'name', 'isActive' => false], + ], schema(int_schema('id'), str_schema('UserName'), bool_schema('isActive')), - row(['id' => 1, 'UserName' => 'name', 'isActive' => true]), - row(['id' => 2, 'UserName' => 'name', 'isActive' => false]), ); $ds = df() @@ -237,7 +237,7 @@ public function test_rename_all_to_snake_case(): void public function test_rename_all_to_title(): void { - $rows = rows(schema(int_schema('ósmy i dziewiąty')), row(['ósmy i dziewiąty' => 89])); + $rows = array_to_rows([['ósmy i dziewiąty' => 89]], schema(int_schema('ósmy i dziewiąty'))); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::TITLE))->getEachAsArray(); @@ -251,10 +251,9 @@ public function test_rename_all_to_title(): void public function test_rename_all_upper_case(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'name', 'active' => true], ['id' => 2, 'name' => 'name', 'active' => false]], schema(int_schema('id'), str_schema('name'), bool_schema('active')), - row(['id' => 1, 'name' => 'name', 'active' => true]), - row(['id' => 2, 'name' => 'name', 'active' => false]), ); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::UPPER))->getEachAsArray(); @@ -270,10 +269,9 @@ public function test_rename_all_upper_case(): void public function test_rename_all_upper_case_first(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'name', 'active' => true], ['id' => 2, 'name' => 'name', 'active' => false]], schema(int_schema('id'), str_schema('name'), bool_schema('active')), - row(['id' => 1, 'name' => 'name', 'active' => true]), - row(['id' => 2, 'name' => 'name', 'active' => false]), ); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::UCFIRST))->getEachAsArray(); @@ -289,10 +287,9 @@ public function test_rename_all_upper_case_first(): void public function test_rename_all_upper_case_word(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'name', 'active' => true], ['id' => 2, 'name' => 'name', 'active' => false]], schema(int_schema('id'), str_schema('name'), bool_schema('active')), - row(['id' => 1, 'name' => 'name', 'active' => true]), - row(['id' => 2, 'name' => 'name', 'active' => false]), ); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::UCWORDS))->getEachAsArray(); @@ -308,10 +305,9 @@ public function test_rename_all_upper_case_word(): void public function test_rename_all_upper_case_word_i18n(): void { - $rows = rows( + $rows = array_to_rows( + [['ósmy' => 8], ['dziewiąty' => 9]], schema(int_schema('ósmy', nullable: true), int_schema('dziewiąty', nullable: true)), - row(['ósmy' => 8]), - row(['dziewiąty' => 9]), ); $ds = df()->read(from_rows($rows))->renameEach(rename_style(StringStyles::UCWORDS))->getEachAsArray(); @@ -328,12 +324,15 @@ public function test_rename_all_upper_case_word_i18n(): void public function test_rename_each_with_empty_map(): void { $rows = df() - ->read(from_rows(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'foo'])))) + ->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'foo']], + schema(int_schema('id'), str_schema('name')), + ))) ->renameEach(rename_map([])) ->fetch(); static::assertEquals( - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'foo'])), + array_to_rows([['id' => 1, 'name' => 'foo']], schema(int_schema('id'), str_schema('name'))), $rows, ); } @@ -341,10 +340,12 @@ public function test_rename_each_with_empty_map(): void public function test_rename_each_with_map_chained_with_other_operations(): void { $ds = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['user_id' => 1, 'user_name' => 'John', 'is_active' => true], + ['user_id' => 2, 'user_name' => 'Jane', 'is_active' => false], + ], schema(int_schema('user_id'), str_schema('user_name'), bool_schema('is_active')), - row(['user_id' => 1, 'user_name' => 'John', 'is_active' => true]), - row(['user_id' => 2, 'user_name' => 'Jane', 'is_active' => false]), ))) ->renameEach(rename_map(['user_id' => 'id', 'user_name' => 'name'])) ->filter(ref('is_active')->equals(lit(true))) @@ -362,10 +363,12 @@ public function test_rename_each_with_map_chained_with_other_operations(): void public function test_rename_each_with_map_multiple_entries(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'first_name' => 'John', 'last_name' => 'Doe'], + ['id' => 2, 'first_name' => 'Jane', 'last_name' => 'Smith'], + ], schema(int_schema('id'), str_schema('first_name'), str_schema('last_name')), - row(['id' => 1, 'first_name' => 'John', 'last_name' => 'Doe']), - row(['id' => 2, 'first_name' => 'Jane', 'last_name' => 'Smith']), ))) ->renameEach(rename_map([ 'first_name' => 'name', @@ -374,10 +377,12 @@ public function test_rename_each_with_map_multiple_entries(): void ->fetch(); static::assertEquals( - rows( + array_to_rows( + [ + ['id' => 1, 'name' => 'John', 'surname' => 'Doe'], + ['id' => 2, 'name' => 'Jane', 'surname' => 'Smith'], + ], schema(int_schema('id'), str_schema('name'), str_schema('surname')), - row(['id' => 1, 'name' => 'John', 'surname' => 'Doe']), - row(['id' => 2, 'name' => 'Jane', 'surname' => 'Smith']), ), $rows, ); @@ -388,7 +393,9 @@ public function test_rename_each_with_map_preserves_metadata(): void $metadata = Metadata::fromArray(['description' => 'test metadata']); $rows = df() - ->read(from_rows(rows(schema(str_schema('old_name', metadata: $metadata)), row(['old_name' => 'value'])))) + ->read(from_rows(array_to_rows([[ + 'old_name' => 'value', + ]], schema(str_schema('old_name', metadata: $metadata))))) ->renameEach(rename_map(['old_name' => 'new_name'])) ->fetch(); @@ -397,15 +404,13 @@ public function test_rename_each_with_map_preserves_metadata(): void public function test_rename_each_with_multiple_strategies(): void { - $rows = rows( + $rows = array_to_rows( + [['ÓSMY' => 8], ['DZIEWIĄTY' => 9], ['ÓSMY I DZIEWIĄTY' => 89]], schema( int_schema('ÓSMY', nullable: true), int_schema('DZIEWIĄTY', nullable: true), int_schema('ÓSMY I DZIEWIĄTY', nullable: true), ), - row(['ÓSMY' => 8]), - row(['DZIEWIĄTY' => 9]), - row(['ÓSMY I DZIEWIĄTY' => 89]), ); $ds = df() @@ -432,7 +437,9 @@ public function test_rename_preserves_metadata(): void $metadata = Metadata::fromArray(['description' => 'test metadata']); $rows = df() - ->read(from_rows(rows(schema(str_schema('old_name', metadata: $metadata)), row(['old_name' => 'value'])))) + ->read(from_rows(array_to_rows([[ + 'old_name' => 'value', + ]], schema(str_schema('old_name', metadata: $metadata))))) ->rename('old_name', 'new_name') ->fetch(); 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 index e67ca3cf52..e2f12340e5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinglePlanTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinglePlanTest.php @@ -17,6 +17,7 @@ use RuntimeException; use function array_filter; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_all; @@ -26,8 +27,6 @@ use function Flow\ETL\DSL\join_on; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\to_memory; @@ -89,7 +88,7 @@ public function test_a_joined_frame_is_optimized_with_the_outer_frames_optimizer { $source = new RecordingFileExtractor( schema(int_schema('id')), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); $right = df(config_builder()->optimizer(new Optimizer()))->read($source)->limit(1); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php index 42c2a85056..ac7433fe7b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php @@ -15,6 +15,7 @@ use RuntimeException; use function array_column; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\constraint_unique; use function Flow\ETL\DSL\data_frame; @@ -26,9 +27,7 @@ use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\pivot_values; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; 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; @@ -196,10 +195,9 @@ public function test_join_inside_a_transformation_matches_every_row(): void // grouped by join key in 2 chunks of 3 - byte for byte what the same join gives on the outer frame. $spy = new SpyLoader(); $joinNames = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->join( - data_frame()->process(rows( + data_frame()->process(array_to_rows( + [['code' => 'a', 'n' => 'Alpha'], ['code' => 'b', 'n' => 'Bravo']], schema(str_schema('code'), str_schema('n')), - row(['code' => 'a', 'n' => 'Alpha']), - row(['code' => 'b', 'n' => 'Bravo']), )), join_on(['g' => 'code'], 'j_'), Join::inner, 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 index eca4b01a2c..6c3b61c2a4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootTest.php @@ -45,6 +45,7 @@ use function file_get_contents; use function Flow\ETL\Adapter\Text\from_text; use function Flow\ETL\DSL\add_row_index; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\batch_size; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\drop; @@ -58,8 +59,6 @@ use function Flow\ETL\DSL\mask_columns; use function Flow\ETL\DSL\partition_types; use function Flow\ETL\DSL\ref; -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\to_branch; @@ -409,7 +408,7 @@ 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])), + array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), ); $rows = df()->read($extractor)->write($spy)->limit(2)->fetch(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayKeysStyleConvertTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayKeysStyleConvertTest.php index 53fa8734b7..800d22a5bd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayKeysStyleConvertTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayKeysStyleConvertTest.php @@ -9,12 +9,14 @@ use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_keys_style_convert; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_memory; final class ArrayKeysStyleConvertTest extends FlowTestCase @@ -43,6 +45,8 @@ public function test_array_keys_style_convert_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - array_keys_style_convert(ref('string'), 'camel')->eval(row(['string' => 'test']), $context); + array_keys_style_convert(ref('string'), 'camel')->eval(array_to_row([ + 'string' => 'test', + ], schema(str_schema('string'))), $context); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementAttributeValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementAttributeValueTest.php index c369fa98cc..f84c06239c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementAttributeValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementAttributeValueTest.php @@ -6,11 +6,10 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\xml_element_schema; use function Flow\ETL\DSL\xml_schema; @@ -22,10 +21,9 @@ final class DOMElementAttributeValueTest extends FlowTestCase public function test_dom_element_attribute_value(): void { $rows = df() - ->read(from_rows(rows( - schema(xml_element_schema('node')), - row(['node' => type_xml_element()->cast('User Name 01')]), - ))) + ->read(from_rows(array_to_rows([[ + 'node' => type_xml_element()->cast('User Name 01'), + ]], schema(xml_element_schema('node'))))) ->withEntry('user_id', ref('node')->domElementAttributeValue('id')) ->drop('node') ->fetch(); @@ -41,10 +39,9 @@ public function test_dom_element_attribute_value(): void public function test_dom_element_attribute_value_from_dom_document(): void { $rows = df() - ->read(from_rows(rows( - schema(xml_schema('node')), - row(['node' => type_xml()->cast('User Name 01')]), - ))) + ->read(from_rows(array_to_rows([[ + 'node' => type_xml()->cast('User Name 01'), + ]], schema(xml_schema('node'))))) ->withEntry('user_id', ref('node')->domElementAttributeValue('id')) ->drop('node') ->fetch(); @@ -60,10 +57,9 @@ public function test_dom_element_attribute_value_from_dom_document(): void public function test_dom_element_attribute_value_on_xpath_result(): void { $rows = df() - ->read(from_rows(rows( - schema(xml_schema('node')), - row(['node' => type_xml()->cast('User Name 01')]), - ))) + ->read(from_rows(array_to_rows([[ + 'node' => type_xml()->cast('User Name 01'), + ]], schema(xml_schema('node'))))) ->withEntry('user_id', ref('node')->xpath('name')->domElementAttributeValue('id')) ->drop('node') ->fetch(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php index 733ee81945..5870506006 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php @@ -8,13 +8,12 @@ use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\RequiresPhp; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\optional; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_html_element; @@ -25,14 +24,11 @@ final class DOMElementNextSiblingTest extends FlowTestCase public function test_dom_element_sibling_text_value(): void { $rows = df() - ->read(from_rows(rows( - schema(html_element_schema('html_element')), - row([ - 'html_element' => type_html_element()->cast( - '

User Name

01
', - ), - ]), - ))) + ->read(from_rows(array_to_rows([[ + 'html_element' => type_html_element()->cast( + '

User Name

01
', + ), + ]], schema(html_element_schema('html_element'))))) ->withEntry('user_details', ref('html_element')->htmlQuerySelector('section')) ->withEntry('user_name', ref('user_details')->htmlQuerySelector('h1')->domElementValue()) ->withEntry('user_id', optional(ref('user_details')->domElementNextSibling()->domElementValue())) @@ -54,14 +50,11 @@ public function test_dom_element_sibling_text_value(): void public function test_dom_element_sibling_text_value_when_only_element_is_allowed(): void { $rows = df() - ->read(from_rows(rows( - schema(html_element_schema('html_element')), - row([ - 'html_element' => type_html_element()->cast( - '

User Name

01
', - ), - ]), - ))) + ->read(from_rows(array_to_rows([[ + 'html_element' => type_html_element()->cast( + '

User Name

01
', + ), + ]], schema(html_element_schema('html_element'))))) ->withEntry('user_details', ref('html_element')->htmlQuerySelector('section')) ->withEntry('user_name', ref('user_details')->htmlQuerySelector('h1')->domElementValue()) ->withEntry('user_id', optional(ref('user_details')->domElementNextSibling()->domElementValue())) @@ -86,7 +79,7 @@ public function test_xml_sibling_element_value(): void // a batch stores an element's own markup, so siblings are reached from the document it belongs to $rows = df() - ->read(from_rows(rows(schema(xml_schema('xml')), row(['xml' => $dom])))) + ->read(from_rows(array_to_rows([['xml' => $dom]], schema(xml_schema('xml'))))) ->withEntry('user_name', ref('xml')->xpath('/user/name')->arrayGet('0')->domElementValue()) ->withEntry( 'user_id', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementParentTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementParentTest.php index 49f514a1d6..7b7d485e04 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementParentTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementParentTest.php @@ -7,12 +7,11 @@ use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\RequiresPhp; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\Types\DSL\type_html_element; @@ -22,14 +21,11 @@ final class DOMElementParentTest extends FlowTestCase public function test_dom_element_value_from_dom_document(): void { $rows = df() - ->read(from_rows(rows( - schema(html_element_schema('html_element')), - row([ - 'html_element' => type_html_element()->cast( - '

User Name

01
', - ), - ]), - ))) + ->read(from_rows(array_to_rows([[ + 'html_element' => type_html_element()->cast( + '

User Name

01
', + ), + ]], schema(html_element_schema('html_element'))))) ->withEntry('user_details', ref('html_element')->htmlQuerySelector('section')) ->withEntry('user_name', ref('user_details')->htmlQuerySelector('h1')->domElementValue()) ->withEntry( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementPreviousSiblingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementPreviousSiblingTest.php index ae4499122c..ff56b6555c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementPreviousSiblingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementPreviousSiblingTest.php @@ -8,13 +8,12 @@ use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\RequiresPhp; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\optional; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_html_element; @@ -25,14 +24,11 @@ final class DOMElementPreviousSiblingTest extends FlowTestCase public function test_dom_element_sibling_text_value(): void { $rows = df() - ->read(from_rows(rows( - schema(html_element_schema('html_element')), - row([ - 'html_element' => type_html_element()->cast( - '
01

User Name

', - ), - ]), - ))) + ->read(from_rows(array_to_rows([[ + 'html_element' => type_html_element()->cast( + '
01

User Name

', + ), + ]], schema(html_element_schema('html_element'))))) ->withEntry('user_details', ref('html_element')->htmlQuerySelector('section')) ->withEntry('user_name', ref('user_details')->htmlQuerySelector('h1')->domElementValue()) ->withEntry('user_id', optional(ref('user_details')->domElementPreviousSibling()->domElementValue())) @@ -54,14 +50,11 @@ public function test_dom_element_sibling_text_value(): void public function test_dom_element_sibling_text_value_when_only_element_is_allowed(): void { $rows = df() - ->read(from_rows(rows( - schema(html_element_schema('html_element')), - row([ - 'html_element' => type_html_element()->cast( - '
01

User Name

', - ), - ]), - ))) + ->read(from_rows(array_to_rows([[ + 'html_element' => type_html_element()->cast( + '
01

User Name

', + ), + ]], schema(html_element_schema('html_element'))))) ->withEntry('user_details', ref('html_element')->htmlQuerySelector('section')) ->withEntry('user_name', ref('user_details')->htmlQuerySelector('h1')->domElementValue()) ->withEntry('user_id', optional(ref('user_details')->domElementPreviousSibling()->domElementValue())) @@ -86,7 +79,7 @@ public function test_xml_sibling_element_value(): void // a batch stores an element's own markup, so siblings are reached from the document it belongs to $rows = df() - ->read(from_rows(rows(schema(xml_schema('xml')), row(['xml' => $dom])))) + ->read(from_rows(array_to_rows([['xml' => $dom]], schema(xml_schema('xml'))))) ->withEntry('user_id', ref('xml')->xpath('/user/number')->arrayGet('0')->domElementValue()) ->withEntry( 'user_name', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementValueTest.php index 9181b147a2..789bd65d75 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementValueTest.php @@ -7,11 +7,10 @@ use DOMDocument; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\xml_element_schema; use function Flow\ETL\DSL\xml_schema; @@ -27,7 +26,7 @@ public function test_dom_element_cast_as_string(): void $document->loadXml('User Name 01'); $rows = df() - ->read(from_rows(rows(schema(xml_schema('html_raw')), row(['html_raw' => $document])))) + ->read(from_rows(array_to_rows([['html_raw' => $document]], schema(xml_schema('html_raw'))))) ->withEntry('html', ref('html_raw')->cast(type_string())) ->drop('html_raw') ->fetch(); @@ -43,10 +42,9 @@ public function test_dom_element_cast_as_string(): void public function test_dom_element_value(): void { $rows = df() - ->read(from_rows(rows( - schema(xml_element_schema('node')), - row(['node' => type_xml_element()->cast('User Name 01')]), - ))) + ->read(from_rows(array_to_rows([[ + 'node' => type_xml_element()->cast('User Name 01'), + ]], schema(xml_element_schema('node'))))) ->withEntry('user_name', ref('node')->domElementValue()) ->drop('node') ->fetch(); @@ -62,10 +60,9 @@ public function test_dom_element_value(): void public function test_dom_element_value_from_dom_document(): void { $rows = df() - ->read(from_rows(rows( - schema(xml_schema('node')), - row(['node' => type_xml()->cast('User Name 01')]), - ))) + ->read(from_rows(array_to_rows([[ + 'node' => type_xml()->cast('User Name 01'), + ]], schema(xml_schema('node'))))) ->withEntry('user_name', ref('node')->domElementValue()) ->drop('node') ->fetch(); @@ -84,7 +81,7 @@ public function test_dom_element_value_on_dom_document(): void $document->loadXml('User Name 01'); $rows = df() - ->read(from_rows(rows(schema(xml_schema('html_raw')), row(['html_raw' => $document])))) + ->read(from_rows(array_to_rows([['html_raw' => $document]], schema(xml_schema('html_raw'))))) ->withEntry('html', ref('html_raw')->domElementValue()) ->drop('html_raw') ->fetch(); @@ -100,10 +97,9 @@ public function test_dom_element_value_on_dom_document(): void public function test_dom_element_value_on_xpath_result(): void { $rows = df() - ->read(from_rows(rows( - schema(xml_schema('node')), - row(['node' => type_xml()->cast('User Name 01')]), - ))) + ->read(from_rows(array_to_rows([[ + 'node' => type_xml()->cast('User Name 01'), + ]], schema(xml_schema('node'))))) ->withEntry('user_name', ref('node')->xpath('name')->domElementValue()) ->drop('node') ->fetch(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/EnumNameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/EnumNameTest.php index c8b19104ed..08510199fb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/EnumNameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/EnumNameTest.php @@ -8,14 +8,13 @@ use Flow\ETL\Tests\Fixtures\Enum\BackedIntEnum; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\enum_name; use function Flow\ETL\DSL\enum_schema; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\optional; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\to_memory; use function Flow\Types\DSL\type_equals; @@ -28,10 +27,9 @@ public function test_enum_name_produces_string_entry_for_int_backed_enum(): void static::assertTrue(type_equals( type_string(), data_frame() - ->read(from_rows(rows( - schema(enum_schema('e', BackedIntEnum::class)), - row(['e' => BackedIntEnum::one]), - ))) + ->read(from_rows(array_to_rows([[ + 'e' => BackedIntEnum::one, + ]], schema(enum_schema('e', BackedIntEnum::class))))) ->withEntry('code', enum_name(ref('e'))) ->schema() ->get('code') @@ -42,11 +40,10 @@ public function test_enum_name_produces_string_entry_for_int_backed_enum(): void public function test_enum_name_writes_null_for_null_enum_in_permissive_mode(): void { data_frame() - ->read(from_rows(rows( - schema(enum_schema('e', BackedIntEnum::class, nullable: true)), - row(['e' => BackedIntEnum::one]), - row(['e' => null]), - ))) + ->read(from_rows(array_to_rows([ + ['e' => BackedIntEnum::one], + ['e' => null], + ], schema(enum_schema('e', BackedIntEnum::class, nullable: true))))) ->withEntry('code', optional(enum_name(ref('e')))) ->select('code') ->write(to_memory($memory = new ArrayMemory())) @@ -58,11 +55,10 @@ public function test_enum_name_writes_null_for_null_enum_in_permissive_mode(): v public function test_enum_name_writes_case_names(): void { data_frame() - ->read(from_rows(rows( - schema(enum_schema('e', BackedIntEnum::class)), - row(['e' => BackedIntEnum::one]), - row(['e' => BackedIntEnum::two]), - ))) + ->read(from_rows(array_to_rows([ + ['e' => BackedIntEnum::one], + ['e' => BackedIntEnum::two], + ], schema(enum_schema('e', BackedIntEnum::class))))) ->withEntry('code', enum_name(ref('e'))) ->select('code') ->write(to_memory($memory = new ArrayMemory())) diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/EnumValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/EnumValueTest.php index 5069f9b152..8c00152044 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/EnumValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/EnumValueTest.php @@ -9,14 +9,13 @@ use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\enum_schema; use function Flow\ETL\DSL\enum_value; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\optional; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\to_memory; use function Flow\Types\DSL\type_equals; @@ -30,10 +29,9 @@ public function test_enum_value_produces_integer_entry_for_int_backed_enum(): vo static::assertTrue(type_equals( type_integer(), data_frame() - ->read(from_rows(rows( - schema(enum_schema('e', BackedIntEnum::class)), - row(['e' => BackedIntEnum::one]), - ))) + ->read(from_rows(array_to_rows([[ + 'e' => BackedIntEnum::one, + ]], schema(enum_schema('e', BackedIntEnum::class))))) ->withEntry('code', enum_value(ref('e'))) ->schema() ->get('code') @@ -46,10 +44,9 @@ public function test_enum_value_produces_string_entry_for_string_backed_enum(): static::assertTrue(type_equals( type_string(), data_frame() - ->read(from_rows(rows( - schema(enum_schema('e', BackedStringEnum::class)), - row(['e' => BackedStringEnum::one]), - ))) + ->read(from_rows(array_to_rows([[ + 'e' => BackedStringEnum::one, + ]], schema(enum_schema('e', BackedStringEnum::class))))) ->withEntry('code', enum_value(ref('e'))) ->schema() ->get('code') @@ -60,11 +57,10 @@ public function test_enum_value_produces_string_entry_for_string_backed_enum(): public function test_enum_value_writes_null_for_null_enum_in_permissive_mode(): void { data_frame() - ->read(from_rows(rows( - schema(enum_schema('e', BackedIntEnum::class, nullable: true)), - row(['e' => BackedIntEnum::one]), - row(['e' => null]), - ))) + ->read(from_rows(array_to_rows([ + ['e' => BackedIntEnum::one], + ['e' => null], + ], schema(enum_schema('e', BackedIntEnum::class, nullable: true))))) ->withEntry('code', optional(enum_value(ref('e')))) ->select('code') ->write(to_memory($memory = new ArrayMemory())) @@ -76,11 +72,10 @@ public function test_enum_value_writes_null_for_null_enum_in_permissive_mode(): public function test_enum_value_writes_backing_values(): void { data_frame() - ->read(from_rows(rows( - schema(enum_schema('e', BackedIntEnum::class)), - row(['e' => BackedIntEnum::one]), - row(['e' => BackedIntEnum::two]), - ))) + ->read(from_rows(array_to_rows([ + ['e' => BackedIntEnum::one], + ['e' => BackedIntEnum::two], + ], schema(enum_schema('e', BackedIntEnum::class))))) ->withEntry('code', enum_value(ref('e'))) ->select('code') ->write(to_memory($memory = new ArrayMemory())) diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/HTMLQuerySelectorAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/HTMLQuerySelectorAllTest.php index 609146818c..c436fe7d1b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/HTMLQuerySelectorAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/HTMLQuerySelectorAllTest.php @@ -8,12 +8,11 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use const LIBXML_HTML_NOIMPLIED; @@ -36,7 +35,7 @@ public function test_invalid_query_all_on_html_document(): void ], ], df() - ->read(from_rows(rows(schema(html_schema('html_raw')), row(['html_raw' => $html])))) + ->read(from_rows(array_to_rows([['html_raw' => $html]], schema(html_schema('html_raw'))))) ->withEntry('html', ref('html_raw')->htmlQuerySelectorAll('body div p')) ->drop('html_raw') ->fetch() @@ -63,7 +62,7 @@ public function test_valid_query_all_on_html_document(): void ], ], df() - ->read(from_rows(rows(schema(html_schema('html_raw')), row(['html_raw' => $html])))) + ->read(from_rows(array_to_rows([['html_raw' => $html]], schema(html_schema('html_raw'))))) ->withEntry('html', ref('html_raw')->htmlQuerySelectorAll('body div span')) ->drop('html_raw') ->fetch() diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/HTMLQuerySelectorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/HTMLQuerySelectorTest.php index 005156d6b2..c33e3ef190 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/HTMLQuerySelectorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/HTMLQuerySelectorTest.php @@ -8,12 +8,11 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; // @mago-ignore analysis:unavailable-method @@ -33,7 +32,7 @@ public function test_invalid_query_on_html_document(): void ], ], df() - ->read(from_rows(rows(schema(html_schema('html_raw')), row(['html_raw' => $html])))) + ->read(from_rows(array_to_rows([['html_raw' => $html]], schema(html_schema('html_raw'))))) ->withEntry('html_element', ref('html_raw')->htmlQuerySelector('body div p')) ->drop('html_raw') ->fetch() @@ -71,7 +70,7 @@ public function test_valid_query_on_html_document(): void ], ], df() - ->read(from_rows(rows(schema(html_schema('html_raw')), row(['html_raw' => $html])))) + ->read(from_rows(array_to_rows([['html_raw' => $html]], schema(html_schema('html_raw'))))) ->withEntry('containers', ref('html_raw')->htmlQuerySelectorAll('body div')->expand()) ->withEntry('span_element', ref('containers')->htmlQuerySelector('body span')->domElementValue()) ->withEntry('p_element', ref('containers')->htmlQuerySelector('p')->domElementValue()) diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/MatchCasesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/MatchCasesTest.php index d4d825af8b..c209b0698a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/MatchCasesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/MatchCasesTest.php @@ -6,14 +6,13 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\match_cases; use function Flow\ETL\DSL\match_condition; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; use function Flow\Types\DSL\type_boolean; @@ -23,14 +22,13 @@ final class MatchCasesTest extends FlowTestCase { public function test_case_match(): void { - $rows = rows( - schema(string_schema('string')), - row(['string' => 'string-with-dashes']), - row(['string' => '123']), - row(['string' => '14%']), - row(['string' => '+14']), - row(['string' => '']), - ); + $rows = array_to_rows([ + ['string' => 'string-with-dashes'], + ['string' => '123'], + ['string' => '14%'], + ['string' => '+14'], + ['string' => ''], + ], schema(string_schema('string'))); $output = df() ->read(from_rows($rows)) 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 a4620c18ae..4165e08787 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 @@ -10,14 +10,13 @@ use Flow\ETL\Tests\Double\StaticDataFrameFactory; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; 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\join_on; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; final class PipelineTest extends FlowTestCase @@ -47,8 +46,8 @@ public function test_a_cycle_closed_on_a_later_batch_is_refused_when_run(): void { $frame = df() ->read(from_rows( - rows(schema(int_schema('id')), row(['id' => 1])), - rows(schema(int_schema('id')), row(['id' => 2])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), )) ->transform($transformer = new ReadsBackOnSecondBatch()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/ListColumnsMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/ListColumnsMother.php index 5ee05ab780..cf28f32ae3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/ListColumnsMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/ListColumnsMother.php @@ -7,9 +7,9 @@ use Flow\ETL\Row; use Flow\ETL\Schema; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_boolean; @@ -35,14 +35,14 @@ public static function schema(): Schema */ public static function row(array $override = []): Row { - return row([ + return array_to_row([ 'id' => 'a', 'tags' => ['x', 'y'], 'nums' => [1, 2, 3], 'lists' => [['q', 'r'], ['s']], 'flags' => [true, false], ...$override, - ]); + ], self::schema()->makeNullable()); } public static function tagsSchema(): Schema diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/PartitionedSourceMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/PartitionedSourceMother.php index 0c9a9470be..a6d27a9281 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/PartitionedSourceMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/PartitionedSourceMother.php @@ -8,9 +8,8 @@ use Flow\ETL\Tests\Double\RecordingFileExtractor; use Flow\Filesystem\FileStatus; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\path; @@ -30,10 +29,9 @@ public static function yearMonth(): RecordingFileExtractor { return (new RecordingFileExtractor( schema(int_schema('year'), str_schema('month'), str_schema('value')), - rows( + array_to_rows( + [['year' => 2023, 'month' => '07', 'value' => 'a'], ['year' => 2024, 'month' => '08', 'value' => 'b']], schema(int_schema('year'), str_schema('month'), str_schema('value')), - row(['year' => 2023, 'month' => '07', 'value' => 'a']), - row(['year' => 2024, 'month' => '08', 'value' => 'b']), ), ))->withPartitionSchema(self::partitions()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/RowsMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/RowsMother.php index f3fa16b5cb..6a3d4e30a5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/RowsMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/RowsMother.php @@ -4,13 +4,19 @@ namespace Flow\ETL\Tests\Mother; +use Flow\ETL\Row; use Flow\ETL\Rows; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\Types\DSL\type_boolean; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; final class RowsMother { @@ -22,9 +28,9 @@ final class RowsMother public static function descendingIdBatches(): array { return [ - rows(schema(int_schema('id')), row(['id' => 5]), row(['id' => 4])), - rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 2])), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 0])), + array_to_rows([['id' => 5], ['id' => 4]], schema(int_schema('id'))), + array_to_rows([['id' => 3], ['id' => 2]], schema(int_schema('id'))), + array_to_rows([['id' => 1], ['id' => 0]], schema(int_schema('id'))), ]; } @@ -36,9 +42,9 @@ public static function descendingIdBatches(): array public static function interleavedGroupBatches(): array { return [ - rows(schema(str_schema('g'), int_schema('v')), row(['g' => 'a', 'v' => 1]), row(['g' => 'b', 'v' => 10])), - rows(schema(str_schema('g'), int_schema('v')), row(['g' => 'a', 'v' => 2]), row(['g' => 'b', 'v' => 20])), - rows(schema(str_schema('g'), int_schema('v')), row(['g' => 'a', 'v' => 3]), row(['g' => 'b', 'v' => 30])), + array_to_rows([['g' => 'a', 'v' => 1], ['g' => 'b', 'v' => 10]], schema(str_schema('g'), int_schema('v'))), + array_to_rows([['g' => 'a', 'v' => 2], ['g' => 'b', 'v' => 20]], schema(str_schema('g'), int_schema('v'))), + array_to_rows([['g' => 'a', 'v' => 3], ['g' => 'b', 'v' => 30]], schema(str_schema('g'), int_schema('v'))), ]; } @@ -51,9 +57,9 @@ public static function interleavedGroupBatches(): array public static function sortedGroupBatches(): array { return [ - rows(schema(str_schema('g'), int_schema('v')), row(['g' => 'a', 'v' => 1]), row(['g' => 'a', 'v' => 2])), - rows(schema(str_schema('g'), int_schema('v')), row(['g' => 'a', 'v' => 3]), row(['g' => 'b', 'v' => 10])), - rows(schema(str_schema('g'), int_schema('v')), row(['g' => 'b', 'v' => 20]), row(['g' => 'b', 'v' => 30])), + array_to_rows([['g' => 'a', 'v' => 1], ['g' => 'a', 'v' => 2]], schema(str_schema('g'), int_schema('v'))), + array_to_rows([['g' => 'a', 'v' => 3], ['g' => 'b', 'v' => 10]], schema(str_schema('g'), int_schema('v'))), + array_to_rows([['g' => 'b', 'v' => 20], ['g' => 'b', 'v' => 30]], schema(str_schema('g'), int_schema('v'))), ]; } @@ -62,9 +68,24 @@ public static function sequentialIds(int $count): Rows $sequence = []; for ($id = 1; $id <= $count; $id++) { - $sequence[] = row(['id' => $id]); + $sequence[] = ['id' => $id]; } - return rows(schema(int_schema('id')), ...$sequence); + return array_to_rows($sequence, schema(int_schema('id'))); + } + + /** + * One row whose "array_entry" structure nests a structure: {id, status, enabled, array: {foo}}. + */ + public static function arrayEntry(): Row + { + return array_to_row([ + 'array_entry' => ['id' => 1, 'status' => 'PENDING', 'enabled' => true, 'array' => ['foo' => 'bar']], + ], schema(structure_schema('array_entry', type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ])))); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkFeedMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkFeedMother.php index 5ce17b6999..6989c9a899 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkFeedMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/SinkFeedMother.php @@ -17,16 +17,15 @@ use Flow\ETL\Rows; use Flow\ETL\Transformer; +use function Flow\ETL\DSL\array_to_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; final class SinkFeedMother { public static function batch(int $id = 1): Rows { - return rows(schema(int_schema('id')), row(['id' => $id])); + return array_to_rows([['id' => $id]], schema(int_schema('id'))); } public static function feed(): FeedExtractor diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketRunTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketRunTest.php index 46493fe4c6..b686f2265d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketRunTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketRunTest.php @@ -12,9 +12,8 @@ use Flow\ETL\Tests\Mother\BucketMother; use function array_map; +use function Flow\ETL\DSL\array_to_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; final class BucketRunTest extends FlowTestCase @@ -24,9 +23,9 @@ public function test_remove_removes_through_its_own_buckets(): void $a = new Buckets($storageA = new MemoryBuckets()); $b = new Buckets($storageB = new MemoryBuckets()); - $storageA->append('shared-id', rows(schema(int_schema('id')), row(['id' => 1]))); + $storageA->append('shared-id', array_to_rows([['id' => 1]], schema(int_schema('id')))); $a->add(BucketMother::withTotalRows('shared-id', 1)); - $storageB->append('shared-id', rows(schema(int_schema('id')), row(['id' => 2]))); + $storageB->append('shared-id', array_to_rows([['id' => 2]], schema(int_schema('id')))); $b->add(BucketMother::withTotalRows('shared-id', 1)); (new BucketRun('shared-id', $a))->remove(); @@ -40,8 +39,8 @@ public function test_rows_are_read_through_the_buckets_that_wrote_them(): void $a = new Buckets($storageA = new MemoryBuckets()); $b = new Buckets($storageB = new MemoryBuckets()); - $storageA->append('shared-id', rows(schema(int_schema('id')), row(['id' => 1]))); - $storageB->append('shared-id', rows(schema(int_schema('id')), row(['id' => 2]))); + $storageA->append('shared-id', array_to_rows([['id' => 1]], schema(int_schema('id')))); + $storageB->append('shared-id', array_to_rows([['id' => 2]], schema(int_schema('id')))); static::assertSame( [1], diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketsTest.php index af27129993..bf0f792a8d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketsTest.php @@ -9,9 +9,8 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\BucketMother; +use function Flow\ETL\DSL\array_to_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; use function iterator_to_array; @@ -29,8 +28,8 @@ public function test_all_returns_every_registered_bucket(): void public function test_clear_empties_manifest_and_storage(): void { $storage = new MemoryBuckets(); - $storage->append('a', rows(schema(int_schema('id')), row(['id' => 1]))); - $storage->append('b', rows(schema(int_schema('id')), row(['id' => 2]))); + $storage->append('a', array_to_rows([['id' => 1]], schema(int_schema('id')))); + $storage->append('b', array_to_rows([['id' => 2]], schema(int_schema('id')))); $buckets = new Buckets($storage); $buckets->add(BucketMother::withTotalRows('a', 1)); @@ -46,7 +45,7 @@ public function test_clear_empties_manifest_and_storage(): void public function test_remove_drops_manifest_entry_and_storage(): void { $storage = new MemoryBuckets(); - $storage->append('a', rows(schema(int_schema('id')), row(['id' => 1]))); + $storage->append('a', array_to_rows([['id' => 1]], schema(int_schema('id')))); $buckets = new Buckets($storage); $buckets->add(BucketMother::withTotalRows('a', 1)); @@ -60,8 +59,8 @@ public function test_remove_drops_manifest_entry_and_storage(): void public function test_rows_yields_storage_batches(): void { $storage = new MemoryBuckets(); - $storage->append('a', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); - $storage->append('a', rows(schema(int_schema('id')), row(['id' => 3]))); + $storage->append('a', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $storage->append('a', array_to_rows([['id' => 3]], schema(int_schema('id')))); $batches = iterator_to_array((new Buckets($storage))->rows('a'), false); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/HashBucketingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/HashBucketingTest.php index 70b133bc89..9467c23934 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/HashBucketingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/HashBucketingTest.php @@ -14,10 +14,9 @@ use Flow\ETL\Tests\Double\CountingHasher; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function iterator_to_array; use function sort; @@ -35,7 +34,7 @@ public function test_bucket_ids_carry_namespace_and_run_id(): void ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); })(); foreach ($strategy->bucketize($generator, new MemoryBuckets()) as $bucket) { @@ -49,8 +48,8 @@ public function test_buckets_are_yielded_after_the_whole_input_is_spilled(): voi $storage = new MemoryBuckets(); $generator = (static function () { - 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 array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); })(); $totalRows = 0; @@ -73,7 +72,7 @@ public function test_custom_hasher_overrides_assignment(): void ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + yield array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); })(); $buckets = iterator_to_array($strategy->bucketize($generator, new MemoryBuckets())); @@ -89,11 +88,11 @@ public function test_distributes_rows_within_buckets_count(): void $rows = []; for ($i = 0; $i < 100; $i++) { - $rows[] = row(['id' => $i]); + $rows[] = ['id' => $i]; } $generator = (static function () use ($rows) { - yield rows(schema(int_schema('id')), ...$rows); + yield array_to_rows($rows, schema(int_schema('id'))); })(); $total = 0; @@ -113,11 +112,11 @@ public function test_index_is_the_partition_number(): void $rows = []; for ($i = 0; $i < 100; $i++) { - $rows[] = row(['id' => $i]); + $rows[] = ['id' => $i]; } $generator = (static function () use ($rows) { - yield rows(schema(int_schema('id')), ...$rows); + yield array_to_rows($rows, schema(int_schema('id'))); })(); $indexes = []; @@ -137,8 +136,8 @@ public function test_hashes_each_row_exactly_once(): void $strategy = new HashBucketing([ref('id')], 4, $spy, new NativePHPRandomValueGenerator()); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); - yield rows(schema(int_schema('id')), row(['id' => 3])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); })(); iterator_to_array($strategy->bucketize($generator, new MemoryBuckets())); @@ -152,8 +151,8 @@ public function test_same_key_lands_in_the_same_bucket(): void $storage = new MemoryBuckets(); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 1])); - yield rows(schema(int_schema('id')), row(['id' => 1])); + yield array_to_rows([['id' => 1], ['id' => 1]], schema(int_schema('id'))); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); })(); $buckets = iterator_to_array($strategy->bucketize($generator, $storage)); @@ -169,10 +168,9 @@ public function test_missing_key_column_is_bucketed_as_null_when_the_schema_allo $storage = new MemoryBuckets(); $generator = (static function () { - yield rows( + yield array_to_rows( + [['id' => null], ['other' => 1]], schema(int_schema('id', nullable: true), int_schema('other', nullable: true)), - row(['id' => null]), - row(['other' => 1]), ); })(); @@ -187,7 +185,7 @@ public function test_rows_missing_the_key_column_throw_by_default(): void $strategy = new HashBucketing([ref('id')], 4, new NativeHasher(), new NativePHPRandomValueGenerator()); $generator = (static function () { - yield rows(schema(int_schema('other')), row(['other' => 1])); + yield array_to_rows([['other' => 1]], schema(int_schema('other'))); })(); $this->expectException(InvalidArgumentException::class); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyGroupingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyGroupingTest.php index 20c7223554..7c085f3c80 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyGroupingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyGroupingTest.php @@ -9,12 +9,12 @@ use Flow\ETL\Tests\FlowTestCase; use Generator; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -32,8 +32,8 @@ public function test_a_key_spanning_several_input_batches_lands_in_one_group(): KeyGroupingContext::groupedValuesOf( [ref('k')], (static function () use ($schema): Generator { - yield rows($schema, row(['k' => 'a', 'v' => 1]), row(['k' => 'b', 'v' => 2])); - yield rows($schema, row(['k' => 'a', 'v' => 3])); + yield array_to_rows([['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 2]], $schema); + yield array_to_rows([['k' => 'a', 'v' => 3]], $schema); })(), 'v', ), @@ -50,12 +50,11 @@ public function test_a_list_column_is_a_usable_key(): void KeyGroupingContext::groupedValuesOf( [ref('tags')], (static function () use ($schema): Generator { - yield rows( - $schema, - row(['tags' => [1, 2], 'v' => 1]), - row(['tags' => [3], 'v' => 2]), - row(['tags' => [1, 2], 'v' => 3]), - ); + yield array_to_rows([ + ['tags' => [1, 2], 'v' => 1], + ['tags' => [3], 'v' => 2], + ['tags' => [1, 2], 'v' => 3], + ], $schema); })(), 'v', ), @@ -73,13 +72,12 @@ public function test_datetime_keys_keep_full_precision(): void KeyGroupingContext::groupedValuesOf( [ref('at')], (static function () use ($schema): Generator { - yield rows( - $schema, - row(['at' => new DateTimeImmutable('2024-01-01 09:00:00'), 'v' => 1]), - row(['at' => new DateTimeImmutable('2024-01-01 21:00:00'), 'v' => 2]), - row(['at' => new DateTimeImmutable('2024-01-01 09:00:00'), 'v' => 3]), - row(['at' => new DateTimeImmutable('2024-01-01 21:00:00'), 'v' => 4]), - ); + yield array_to_rows([ + ['at' => new DateTimeImmutable('2024-01-01 09:00:00'), 'v' => 1], + ['at' => new DateTimeImmutable('2024-01-01 21:00:00'), 'v' => 2], + ['at' => new DateTimeImmutable('2024-01-01 09:00:00'), 'v' => 3], + ['at' => new DateTimeImmutable('2024-01-01 21:00:00'), 'v' => 4], + ], $schema); })(), 'v', ), @@ -96,7 +94,7 @@ public function test_empty_batches_are_skipped(): void [ref('k')], (static function () use ($schema): Generator { yield rows($schema); - yield rows($schema, row(['k' => 'a', 'v' => 1])); + yield array_to_rows([['k' => 'a', 'v' => 1]], $schema); })(), 'v', ), @@ -127,7 +125,7 @@ public function test_numerically_equal_keys_of_different_types_collapse(): void KeyGroupingContext::groupedValuesOf( [ref('k')], (static function () use ($schema): Generator { - yield rows($schema, row(['k' => 1.0, 'v' => 1]), row(['k' => 1.0, 'v' => 2])); + yield array_to_rows([['k' => 1.0, 'v' => 1], ['k' => 1.0, 'v' => 2]], $schema); })(), 'v', ), @@ -143,12 +141,11 @@ public function test_null_key_values_group_together(): void KeyGroupingContext::groupedValuesOf( [ref('k')], (static function () use ($schema): Generator { - yield rows( - $schema, - row(['k' => null, 'v' => 1]), - row(['k' => 'a', 'v' => 2]), - row(['k' => null, 'v' => 3]), - ); + yield array_to_rows([ + ['k' => null, 'v' => 1], + ['k' => 'a', 'v' => 2], + ['k' => null, 'v' => 3], + ], $schema); })(), 'v', ), @@ -164,7 +161,7 @@ public function test_one_key_yields_one_group(): void KeyGroupingContext::groupedValuesOf( [ref('k')], (static function () use ($schema): Generator { - yield rows($schema, row(['k' => 'a', 'v' => 1]), row(['k' => 'a', 'v' => 2])); + yield array_to_rows([['k' => 'a', 'v' => 1], ['k' => 'a', 'v' => 2]], $schema); })(), 'v', ), @@ -180,7 +177,7 @@ public function test_the_group_keeps_the_schema_of_the_first_non_empty_batch(): KeyGroupingContext::groups( [ref('k')], (static function () use ($schema): Generator { - yield rows($schema, row(['k' => 'a', 'v' => 1])); + yield array_to_rows([['k' => 'a', 'v' => 1]], $schema); })(), )[0]->schema(), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyValuesTest.php index ac7da009f4..1578c743a2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyValuesTest.php @@ -8,10 +8,10 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -21,7 +21,7 @@ public function test_of_projects_each_row(): void { static::assertSame( [[1], [2]], - (new KeyValues([ref('id')]))->of(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))), + (new KeyValues([ref('id')]))->of(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))), ); } @@ -29,7 +29,9 @@ public function test_of_row_preserves_null(): void { static::assertSame( [null], - (new KeyValues([ref('id')]))->ofRow(row(['id' => null]), schema(int_schema('id', nullable: true))), + (new KeyValues([ref('id')]))->ofRow(array_to_row([ + 'id' => null, + ], schema(str_schema('id', nullable: true))), schema(int_schema('id', nullable: true))), ); } @@ -38,7 +40,7 @@ public function test_of_row_projects_refs_in_order(): void static::assertSame( [1, 'PL'], (new KeyValues([ref('id'), ref('country')]))->ofRow( - row(['id' => 1, 'country' => 'PL']), + array_to_row(['id' => 1, 'country' => 'PL'], schema(int_schema('id'), str_schema('country'))), schema(int_schema('id'), str_schema('country')), ), ); @@ -48,7 +50,9 @@ public function test_duplicated_refs_are_extracted_per_position(): void { static::assertSame( [1, 1], - (new KeyValues([ref('id'), ref('id')]))->ofRow(row(['id' => 1]), schema(int_schema('id'))), + (new KeyValues([ref('id'), ref('id')]))->ofRow(array_to_row([ + 'id' => 1, + ], schema(int_schema('id'))), schema(int_schema('id'))), ); } @@ -57,7 +61,10 @@ public function test_a_missing_not_null_ref_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Column "id" does not exist'); - (new KeyValues([ref('id')]))->ofRow(row(['name' => 'flow']), schema(int_schema('id'), str_schema('name'))); + (new KeyValues([ref('id')]))->ofRow( + array_to_row(['name' => 'flow'], schema(str_schema('name'))), + schema(int_schema('id'), str_schema('name')), + ); } public function test_a_missing_nullable_ref_is_null_when_the_schema_allows_it(): void @@ -65,7 +72,7 @@ public function test_a_missing_nullable_ref_is_null_when_the_schema_allows_it(): static::assertSame( [null, 'flow'], (new KeyValues([ref('id'), ref('name')]))->ofRow( - row(['name' => 'flow']), + array_to_row(['name' => 'flow'], schema(str_schema('name'))), schema(int_schema('id', nullable: true), str_schema('name')), ), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/SortedRunBucketingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/SortedRunBucketingTest.php index c9da5f21ad..8b870d4e00 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/SortedRunBucketingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/SortedRunBucketingTest.php @@ -14,10 +14,9 @@ use function array_map; use function array_unique; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function iterator_to_array; @@ -28,8 +27,8 @@ public function test_bucket_ids_are_namespaced_per_run(): void $strategy = new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()); $generator = (static function () { - 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 array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); })(); $ids = []; @@ -48,7 +47,7 @@ public function test_emits_final_partial_run(): void $strategy = new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); $sizes = []; @@ -66,7 +65,7 @@ public function test_runs_are_spilled_sorted_by_refs(): void $storage = new MemoryBuckets(); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); $buckets = iterator_to_array($strategy->bucketize($generator, $storage)); @@ -86,8 +85,8 @@ public function test_runs_are_yielded_as_soon_as_they_are_complete(): void $storage = new MemoryBuckets(); $generator = (static function () { - 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 array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); })(); $firstRun = $strategy->bucketize($generator, $storage)->current(); @@ -102,8 +101,8 @@ public function test_splits_buffer_into_runs_of_run_size(): void $strategy = new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()); $generator = (static function () { - 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 array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); })(); $sizes = []; @@ -120,9 +119,9 @@ public function test_runs_are_numbered_sequentially(): void $strategy = new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()); $generator = (static function () { - 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])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); + yield array_to_rows([['id' => 5]], schema(int_schema('id'))); })(); $indexes = []; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/MemoryBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/MemoryBucketsTest.php index a302fc339e..0abd2cbeb5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/MemoryBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/MemoryBucketsTest.php @@ -11,9 +11,8 @@ use Flow\ETL\Tests\FlowTestCase; use function array_map; +use function Flow\ETL\DSL\array_to_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; final class MemoryBucketsTest extends FlowTestCase @@ -21,8 +20,8 @@ final class MemoryBucketsTest extends FlowTestCase public function test_append_accumulates_rows_in_order(): void { $storage = new MemoryBuckets(); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 3]))); + $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); static::assertSame( [1, 2, 3], @@ -43,7 +42,7 @@ public function test_is_resident_storage(): void public function test_remove_drops_the_bucket(): void { $storage = new MemoryBuckets(); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]))); + $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $storage->remove('bucket'); static::assertSame([], BucketsStorageContext::rows($storage->get('bucket'))); @@ -52,8 +51,8 @@ public function test_remove_drops_the_bucket(): void public function test_set_replaces_previous_rows(): void { $storage = new MemoryBuckets(); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]))); - $storage->set('bucket', rows(schema(int_schema('id')), row(['id' => 42]))); + $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); + $storage->set('bucket', array_to_rows([['id' => 42]], schema(int_schema('id')))); static::assertSame( [42], diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php index 9a02f0086e..6c303f72c4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php @@ -11,9 +11,8 @@ use Flow\ETL\Tests\FlowTestCase; use function array_map; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -23,8 +22,8 @@ final class PSRCacheBucketsTest extends FlowTestCase public function test_append_then_get_returns_rows_in_order_across_chunks(): void { $storage = new PSRCacheBuckets(new ArrayCache()); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 3]))); + $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); static::assertSame( [1, 2, 3], @@ -35,10 +34,9 @@ public function test_append_then_get_returns_rows_in_order_across_chunks(): void public function test_custom_prefix_is_used_in_keys(): void { $cache = new ArrayCache(); - (new PSRCacheBuckets($cache, prefix: 'custom:pfx'))->append('bucket', rows( - schema(int_schema('id')), - row(['id' => 1]), - )); + (new PSRCacheBuckets($cache, prefix: 'custom:pfx'))->append('bucket', array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id')))); static::assertTrue($cache->has('custom:pfx:bucket:chunks')); static::assertTrue($cache->has('custom:pfx:bucket:chunk:0')); @@ -70,8 +68,8 @@ public function test_remove_deletes_all_chunk_keys_and_the_counter(): void { $cache = new ArrayCache(); $storage = new PSRCacheBuckets($cache); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]))); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 2]))); + $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); + $storage->append('bucket', array_to_rows([['id' => 2]], schema(int_schema('id')))); $storage->remove('bucket'); @@ -84,11 +82,9 @@ public function test_remove_deletes_all_chunk_keys_and_the_counter(): void public function test_round_trips_schema_changing_rows(): void { $storage = new PSRCacheBuckets(new ArrayCache()); - $input = rows( + $input = array_to_rows( + [['id' => 1], ['id' => 2, 'name' => 'John'], ['name' => 'Jane']], schema(int_schema('id', nullable: true), str_schema('name', nullable: true)), - row(['id' => 1]), - row(['id' => 2, 'name' => 'John']), - row(['name' => 'Jane']), ); $storage->append('bucket', $input); @@ -101,8 +97,8 @@ public function test_round_trips_schema_changing_rows(): void public function test_set_replaces_previous_content(): void { $storage = new PSRCacheBuckets(new ArrayCache()); - $storage->append('bucket', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); - $storage->set('bucket', rows(schema(int_schema('id')), row(['id' => 42]))); + $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $storage->set('bucket', array_to_rows([['id' => 42]], schema(int_schema('id')))); static::assertSame( [42], diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/CacheIndexTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/CacheIndexTest.php index 7f36e3845c..97b23f9896 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/CacheIndexTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/CacheIndexTest.php @@ -9,9 +9,8 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -34,7 +33,7 @@ public function test_an_empty_index_declares_zero_rows_exactly(): void public function test_an_index_without_a_rows_column_declares_unknown_rows(): void { - $index = CacheIndex::fromRows('dataset-id', rows(schema(str_schema('key')), row(['key' => 'chunk-1']))); + $index = CacheIndex::fromRows('dataset-id', array_to_rows([['key' => 'chunk-1']], schema(str_schema('key')))); static::assertSame(['chunk-1'], $index->values()); static::assertEquals(Cardinality::unknown(), $index->rows()); @@ -64,7 +63,7 @@ public function test_from_rows_with_missing_key_entry_throws(): void { $this->expectException(InvalidArgumentException::class); - CacheIndex::fromRows('dataset-id', rows(schema(int_schema('id')), row(['id' => 1]))); + CacheIndex::fromRows('dataset-id', array_to_rows([['id' => 1]], schema(int_schema('id')))); } public function test_from_rows_with_non_string_key_entry_throws(): void @@ -72,7 +71,7 @@ public function test_from_rows_with_non_string_key_entry_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('CacheIndex expects rows with a string "key" entry, got: null'); - CacheIndex::fromRows('dataset-id', rows(schema(str_schema('key', nullable: true)), row(['key' => null]))); + CacheIndex::fromRows('dataset-id', array_to_rows([['key' => null]], schema(str_schema('key', nullable: true)))); } public function test_from_rows_with_non_integer_rows_entry_throws(): void @@ -80,9 +79,9 @@ public function test_from_rows_with_non_integer_rows_entry_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('CacheIndex expects rows with an integer "rows" entry, got: string'); - CacheIndex::fromRows('dataset-id', rows( + CacheIndex::fromRows('dataset-id', array_to_rows( + [['key' => 'chunk-1', 'rows' => 'three']], schema(str_schema('key'), str_schema('rows')), - row(['key' => 'chunk-1', 'rows' => 'three']), )); } @@ -116,10 +115,9 @@ public function test_to_rows_stores_one_key_and_rows_entry_per_chunk(): void $index->add('chunk-2'); static::assertEquals( - rows( + array_to_rows( + [['key' => 'chunk-1', 'rows' => 2], ['key' => 'chunk-2', 'rows' => null]], schema(str_schema('key'), int_schema('rows', nullable: true)), - row(['key' => 'chunk-1', 'rows' => 2]), - row(['key' => 'chunk-2', 'rows' => null]), ), $index->toRows(), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/ApcuCacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/ApcuCacheTest.php index 27564fd095..ae54535208 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/ApcuCacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/ApcuCacheTest.php @@ -14,9 +14,8 @@ use function apcu_enabled; use function apcu_store; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -59,10 +58,9 @@ public function test_caching_rows(): void $this->cache->set( 'rows', - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'John'], ['id' => 2, 'name' => 'Jane']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'John']), - row(['id' => 2, 'name' => 'Jane']), ), ); @@ -74,7 +72,7 @@ public function test_caching_schema(): void { $this->cache->set( 'rows', - $rows = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'John'])), + $rows = array_to_rows([['id' => 1, 'name' => 'John']], schema(int_schema('id'), str_schema('name'))), ); static::assertEquals($rows->schema(), $this->cache->schema('rows')); @@ -87,8 +85,8 @@ public function test_checking_on_non_existing_cache_key(): void public function test_clearing_cache_removes_only_its_own_namespace(): void { - $this->cache->set('rows', rows(schema(int_schema('id')), row(['id' => 1]))); - $this->otherCache->set('rows', rows(schema(int_schema('id')), row(['id' => 2]))); + $this->cache->set('rows', array_to_rows([['id' => 1]], schema(int_schema('id')))); + $this->otherCache->set('rows', array_to_rows([['id' => 2]], schema(int_schema('id')))); $this->cache->clear(); @@ -98,7 +96,7 @@ public function test_clearing_cache_removes_only_its_own_namespace(): void public function test_clearing_cache_removes_schemas(): void { - $this->cache->set('rows', rows(schema(int_schema('id')), row(['id' => 1]))); + $this->cache->set('rows', array_to_rows([['id' => 1]], schema(int_schema('id')))); $this->cache->clear(); @@ -133,8 +131,8 @@ public function test_getting_schema_of_non_existing_cache_key(): void public function test_removing_from_cache(): void { - $this->cache->set('first', rows(schema(int_schema('id')), row(['id' => 1]))); - $this->cache->set('second', rows(schema(int_schema('id')), row(['id' => 2]))); + $this->cache->set('first', array_to_rows([['id' => 1]], schema(int_schema('id')))); + $this->cache->set('second', array_to_rows([['id' => 2]], schema(int_schema('id')))); $this->cache->delete('second'); @@ -144,8 +142,8 @@ public function test_removing_from_cache(): void public function test_removing_from_cache_removes_its_schema(): void { - $this->cache->set('first', $rows = rows(schema(int_schema('id')), row(['id' => 1]))); - $this->cache->set('second', rows(schema(int_schema('id')), row(['id' => 2]))); + $this->cache->set('first', $rows = array_to_rows([['id' => 1]], schema(int_schema('id')))); + $this->cache->set('second', array_to_rows([['id' => 2]], schema(int_schema('id')))); $this->cache->delete('second'); @@ -165,7 +163,7 @@ public function test_removing_non_existing_cache_key(): void public function test_schema_of_an_entry_without_a_stored_schema_is_a_cache_miss(): void { - apcu_store('flow_php_cache_test:orphan', rows(schema(int_schema('id')), row(['id' => 1]))); + apcu_store('flow_php_cache_test:orphan', array_to_rows([['id' => 1]], schema(int_schema('id')))); static::assertTrue($this->cache->has('orphan')); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/TraceableCacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/TraceableCacheTest.php index f40857fe16..44316996fd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/TraceableCacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/TraceableCacheTest.php @@ -24,8 +24,8 @@ use PHPUnit\Framework\Attributes\CoversClass; use RuntimeException; +use function Flow\ETL\DSL\array_to_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; @@ -101,7 +101,7 @@ public function test_get_increments_hit_counter_on_existing_key(): void $innerCache = new InMemoryCache(); $cache = new TraceableCache($innerCache, $this->telemetry, 'test_dataframe'); - $innerCache->set('existing-key', rows(schema(), row([]))); + $innerCache->set('existing-key', array_to_rows([[]], schema())); $cache->get('existing-key'); $this->telemetry->flush(); @@ -141,7 +141,7 @@ public function test_has_increments_hit_counter_when_key_exists(): void $innerCache = new InMemoryCache(); $cache = new TraceableCache($innerCache, $this->telemetry, 'test_dataframe'); - $innerCache->set('existing-key', rows(schema(), row([]))); + $innerCache->set('existing-key', array_to_rows([[]], schema())); $exists = $cache->has('existing-key'); static::assertTrue($exists); @@ -181,7 +181,7 @@ public function test_schema_increments_hit_counter_on_existing_key(): void $innerCache = new InMemoryCache(); $cache = new TraceableCache($innerCache, $this->telemetry, 'test_dataframe'); - $innerCache->set('existing-key', $rows = rows(schema(int_schema('id')), row(['id' => 1]))); + $innerCache->set('existing-key', $rows = array_to_rows([['id' => 1]], schema(int_schema('id')))); static::assertEquals($rows->schema(), $cache->schema('existing-key')); @@ -290,7 +290,7 @@ public function test_set_records_exception_on_error(): void $this->expectExceptionMessage('Test error'); try { - $cache->set('test-key', rows(schema(), row([]))); + $cache->set('test-key', array_to_rows([[]], schema())); } finally { $this->telemetry->flush(); $spans = $this->spanProcessor->endedSpans(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php index 72b29df04c..5684d1e7a9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php @@ -9,17 +9,19 @@ use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Comparator\Factory; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_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; +use function Flow\ETL\DSL\str_schema; final class RowComparatorTest extends TestCase { public function test_accepts_only_two_rows(): void { $comparator = new RowComparator(); - $row = row(['id' => 1]); + $row = array_to_row(['id' => 1], schema(int_schema('id'))); static::assertTrue($comparator->accepts($row, $row)); static::assertFalse($comparator->accepts($row, rows(schema(int_schema('id')), $row))); @@ -32,8 +34,8 @@ public function test_rows_of_different_batches_with_equal_values_pass(): void $comparator->setFactory(Factory::getInstance()); $comparator->assertEquals( - rows(schema(int_schema('id')), row(['id' => 1]))->first(), - rows(schema(int_schema('id')), row(['id' => 0]), row(['id' => 1]))->last(), + array_to_rows([['id' => 1]], schema(int_schema('id')))->first(), + array_to_rows([['id' => 0], ['id' => 1]], schema(int_schema('id')))->last(), ); $this->addToAssertionCount(1); @@ -44,9 +46,9 @@ public function test_the_schema_is_not_compared(): void $comparator = new RowComparator(); $comparator->setFactory(Factory::getInstance()); - $comparator->assertEquals(row([ + $comparator->assertEquals(array_to_row([ 'phase' => null, - ]), rows(schema(int_schema('phase', nullable: true)), row(['phase' => null]))->first()); + ], schema(str_schema('phase', nullable: true))), array_to_rows([['phase' => null]], schema(int_schema('phase', nullable: true)))->first()); $this->addToAssertionCount(1); } @@ -59,7 +61,10 @@ public function test_a_name_order_difference_fails(): void $this->expectException(ComparisonFailure::class); $this->expectExceptionMessage('Failed asserting that two Row objects have the same names.'); - $comparator->assertEquals(row(['a' => 1, 'b' => 2]), row(['b' => 2, 'a' => 1])); + $comparator->assertEquals( + array_to_row(['a' => 1, 'b' => 2], schema(int_schema('a'), int_schema('b'))), + array_to_row(['b' => 2, 'a' => 1], schema(int_schema('b'), int_schema('a'))), + ); } public function test_a_value_difference_fails(): void @@ -68,7 +73,10 @@ public function test_a_value_difference_fails(): void $comparator->setFactory(Factory::getInstance()); try { - $comparator->assertEquals(row(['id' => 1]), row(['id' => 2])); + $comparator->assertEquals( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + ); } catch (ComparisonFailure $failure) { static::assertSame('Failed asserting that two Row objects are equal.', $failure->getMessage()); static::assertStringContainsString('1', $failure->getExpectedAsString()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php index 12a197ecfb..b3aad4f832 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php @@ -11,9 +11,9 @@ use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Comparator\Factory; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -22,10 +22,10 @@ final class RowsComparatorTest extends TestCase public function test_accepts_only_two_rows(): void { $comparator = new RowsComparator(); - $rows = rows(schema(int_schema('id')), row(['id' => 1])); + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); static::assertTrue($comparator->accepts($rows, $rows)); - static::assertFalse($comparator->accepts($rows, row(['id' => 1]))); + static::assertFalse($comparator->accepts($rows, array_to_row(['id' => 1], schema(int_schema('id'))))); static::assertFalse($comparator->accepts([], $rows)); } @@ -35,8 +35,8 @@ public function test_equal_rows_of_two_batches_pass(): void $comparator->setFactory(Factory::getInstance()); $comparator->assertEquals( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); $this->addToAssertionCount(1); @@ -53,7 +53,7 @@ public function test_equal_across_column_classes(): void ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], 2, ), - rows(schema(int_schema('id')), row(['id' => 7]), row(['id' => 7])), + array_to_rows([['id' => 7], ['id' => 7]], schema(int_schema('id'))), ); $this->addToAssertionCount(1); @@ -68,8 +68,8 @@ public function test_a_schema_difference_fails(): void $this->expectExceptionMessage('Failed asserting that two Rows have the same schema.'); $comparator->assertEquals( - rows(schema(int_schema('id')), row(['id' => 1])), - rows(schema(int_schema('id', nullable: true)), row(['id' => 1])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 1]], schema(int_schema('id', nullable: true))), ); } @@ -80,8 +80,8 @@ public function test_a_value_difference_fails(): void try { $comparator->assertEquals( - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])), - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'b'])), + array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))), + array_to_rows([['id' => 1, 'name' => 'b']], schema(int_schema('id'), str_schema('name'))), ); } catch (ComparisonFailure $failure) { static::assertSame('Failed asserting that two Rows are equal.', $failure->getMessage()); @@ -97,12 +97,12 @@ public function test_a_value_difference_fails(): void public function test_assert_equals_uses_the_registered_comparator(): void { static::assertEquals( - rows(schema(int_schema('id')), row(['id' => 1])), - rows(schema(int_schema('id')), row(['id' => 1])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 1]], schema(int_schema('id'))), ); static::assertNotEquals( - rows(schema(int_schema('id')), row(['id' => 1])), - rows(schema(int_schema('id')), row(['id' => 2])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), ); } } 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 64da37b0d7..80fc48a450 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 @@ -34,13 +34,12 @@ use function array_map; use function count; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\telemetry_options; use function Flow\ETL\DSL\to_array; @@ -61,10 +60,9 @@ public function test_dataframe_batch_processed_drains_abandoned_spans(): void $context->telemetryContext->transformationStarted($inner); $context->telemetryContext->transformationCompleted($inner); - $context->telemetryContext->dataFrameBatchProcessed( - rows(schema(int_schema('id')), row(['id' => 1])), - $context->flowContext, - ); + $context->telemetryContext->dataFrameBatchProcessed(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))), $context->flowContext); $endedSpans = $context->spans->endedSpans(); @@ -108,7 +106,7 @@ public function test_dataframe_batch_processed_tracks_rows_and_memory(): void $telemetryContext->dataFrameStarted($context); - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $telemetryContext->dataFrameBatchProcessed($rows, $context); @@ -180,7 +178,7 @@ public function test_dataframe_completed_finalizes_span_with_statistics(): void $telemetryContext->dataFrameStarted($context); - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $telemetryContext->dataFrameBatchProcessed($rows, $context); $telemetryContext->dataFrameCompleted($context); @@ -256,7 +254,7 @@ public function test_dataframe_failed_logs_error_and_sets_span_status(): void $telemetryContext->dataFrameStarted($context); - $rows = rows(schema(int_schema('id')), row(['id' => 1])); + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); $telemetryContext->dataFrameBatchProcessed($rows, $context); $exception = new RuntimeException('Processing failed due to invalid data'); @@ -577,7 +575,7 @@ public function test_metrics_collected_when_collect_metrics_enabled(): void $telemetryContext->dataFrameStarted($context); - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $telemetryContext->dataFrameBatchProcessed($rows, $context); $telemetryContext->dataFrameCompleted($context); $telemetry->flush(); @@ -620,7 +618,7 @@ public function test_metrics_include_dataframe_name_attribute(): void $telemetryContext->dataFrameStarted($context); - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $telemetryContext->dataFrameBatchProcessed($rows, $context); $telemetryContext->dataFrameCompleted($context); $telemetry->flush(); @@ -666,7 +664,7 @@ public function test_metrics_not_collected_when_collect_metrics_disabled(): void $telemetryContext->dataFrameStarted($context); - $rows = rows(schema(int_schema('id')), row(['id' => 1])); + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); $telemetryContext->dataFrameBatchProcessed($rows, $context); $telemetryContext->dataFrameCompleted($context); $telemetry->flush(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/SortedConstraintTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/SortedConstraintTest.php index 7548605d0c..a9fe5a2a70 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/SortedConstraintTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/SortedConstraintTest.php @@ -8,11 +8,12 @@ use Flow\ETL\Constraint\SortedByConstraint; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -29,52 +30,96 @@ public function test_sorted_constraint_ascending_integers(): void { $constraint = new SortedByConstraint(ref('id')->asc()); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 1]), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 2]), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 3]), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 3]), schema(int_schema('id')))); - static::assertFalse($constraint->isSatisfiedBy(row(['id' => 2]), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 1, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 2, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 3, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 3, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertFalse($constraint->isSatisfiedBy(array_to_row([ + 'id' => 2, + ], schema(int_schema('id'))), schema(int_schema('id')))); } public function test_sorted_constraint_ascending_strings(): void { $constraint = new SortedByConstraint(ref('name')->asc()); - static::assertTrue($constraint->isSatisfiedBy(row(['name' => 'Alice']), schema(str_schema('name')))); - static::assertTrue($constraint->isSatisfiedBy(row(['name' => 'Bob']), schema(str_schema('name')))); - static::assertTrue($constraint->isSatisfiedBy(row(['name' => 'Charlie']), schema(str_schema('name')))); - static::assertFalse($constraint->isSatisfiedBy(row(['name' => 'Alice']), schema(str_schema('name')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'name' => 'Alice', + ], schema(str_schema('name'))), schema(str_schema('name')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'name' => 'Bob', + ], schema(str_schema('name'))), schema(str_schema('name')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'name' => 'Charlie', + ], schema(str_schema('name'))), schema(str_schema('name')))); + static::assertFalse($constraint->isSatisfiedBy(array_to_row([ + 'name' => 'Alice', + ], schema(str_schema('name'))), schema(str_schema('name')))); } public function test_sorted_constraint_default_order_is_ascending(): void { $constraint = new SortedByConstraint(ref('id')); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 1]), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 2]), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 3]), schema(int_schema('id')))); - static::assertFalse($constraint->isSatisfiedBy(row(['id' => 1]), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 1, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 2, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 3, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertFalse($constraint->isSatisfiedBy(array_to_row([ + 'id' => 1, + ], schema(int_schema('id'))), schema(int_schema('id')))); } public function test_sorted_constraint_descending_floats(): void { $constraint = new SortedByConstraint(ref('price')->desc()); - static::assertTrue($constraint->isSatisfiedBy(row(['price' => 99.99]), schema(float_schema('price')))); - static::assertTrue($constraint->isSatisfiedBy(row(['price' => 49.99]), schema(float_schema('price')))); - static::assertTrue($constraint->isSatisfiedBy(row(['price' => 19.99]), schema(float_schema('price')))); - static::assertTrue($constraint->isSatisfiedBy(row(['price' => 19.99]), schema(float_schema('price')))); - static::assertFalse($constraint->isSatisfiedBy(row(['price' => 29.99]), schema(float_schema('price')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'price' => 99.99, + ], schema(float_schema('price'))), schema(float_schema('price')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'price' => 49.99, + ], schema(float_schema('price'))), schema(float_schema('price')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'price' => 19.99, + ], schema(float_schema('price'))), schema(float_schema('price')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'price' => 19.99, + ], schema(float_schema('price'))), schema(float_schema('price')))); + static::assertFalse($constraint->isSatisfiedBy(array_to_row([ + 'price' => 29.99, + ], schema(float_schema('price'))), schema(float_schema('price')))); } public function test_sorted_constraint_descending_integers(): void { $constraint = new SortedByConstraint(ref('id')->desc()); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 10]), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 5]), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 1]), schema(int_schema('id')))); - static::assertFalse($constraint->isSatisfiedBy(row(['id' => 3]), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 10, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 5, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 1, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertFalse($constraint->isSatisfiedBy(array_to_row([ + 'id' => 3, + ], schema(int_schema('id'))), schema(int_schema('id')))); } public function test_sorted_constraint_multiple_columns(): void @@ -82,23 +127,23 @@ public function test_sorted_constraint_multiple_columns(): void $constraint = new SortedByConstraint(ref('category')->asc(), ref('price')->desc()); static::assertTrue($constraint->isSatisfiedBy( - row(['category' => 'A', 'price' => 100.0]), + array_to_row(['category' => 'A', 'price' => 100.0], schema(str_schema('category'), float_schema('price'))), schema(str_schema('category'), float_schema('price')), )); static::assertTrue($constraint->isSatisfiedBy( - row(['category' => 'A', 'price' => 50.0]), + array_to_row(['category' => 'A', 'price' => 50.0], schema(str_schema('category'), float_schema('price'))), schema(str_schema('category'), float_schema('price')), )); static::assertTrue($constraint->isSatisfiedBy( - row(['category' => 'B', 'price' => 200.0]), + array_to_row(['category' => 'B', 'price' => 200.0], schema(str_schema('category'), float_schema('price'))), schema(str_schema('category'), float_schema('price')), )); static::assertTrue($constraint->isSatisfiedBy( - row(['category' => 'B', 'price' => 150.0]), + array_to_row(['category' => 'B', 'price' => 150.0], schema(str_schema('category'), float_schema('price'))), schema(str_schema('category'), float_schema('price')), )); static::assertFalse($constraint->isSatisfiedBy( - row(['category' => 'B', 'price' => 250.0]), + array_to_row(['category' => 'B', 'price' => 250.0], schema(str_schema('category'), float_schema('price'))), schema(str_schema('category'), float_schema('price')), )); } @@ -113,10 +158,12 @@ public function test_sorted_constraint_multiple_columns_as_a_string(): void public function test_sorted_constraint_violation_ascending(): void { $constraint = new SortedByConstraint(ref('id')->asc()); - $constraint->isSatisfiedBy(row(['id' => 5]), schema(int_schema('id'))); - $constraint->isSatisfiedBy(row(['id' => 10]), schema(int_schema('id'))); + $constraint->isSatisfiedBy(array_to_row(['id' => 5], schema(int_schema('id'))), schema(int_schema('id'))); + $constraint->isSatisfiedBy(array_to_row(['id' => 10], schema(int_schema('id'))), schema(int_schema('id'))); - $violation = $constraint->violation(row(['id' => 3]), schema(int_schema('id'))); + $violation = $constraint->violation(array_to_row([ + 'id' => 3, + ], schema(int_schema('id'))), schema(int_schema('id'))); static::assertStringContainsString('expected ASC order', $violation); static::assertStringContainsString('id', $violation); @@ -127,10 +174,12 @@ public function test_sorted_constraint_violation_ascending(): void public function test_sorted_constraint_violation_descending(): void { $constraint = new SortedByConstraint(ref('id')->desc()); - $constraint->isSatisfiedBy(row(['id' => 10]), schema(int_schema('id'))); - $constraint->isSatisfiedBy(row(['id' => 5]), schema(int_schema('id'))); + $constraint->isSatisfiedBy(array_to_row(['id' => 10], schema(int_schema('id'))), schema(int_schema('id'))); + $constraint->isSatisfiedBy(array_to_row(['id' => 5], schema(int_schema('id'))), schema(int_schema('id'))); - $violation = $constraint->violation(row(['id' => 8]), schema(int_schema('id'))); + $violation = $constraint->violation(array_to_row([ + 'id' => 8, + ], schema(int_schema('id'))), schema(int_schema('id'))); static::assertStringContainsString('expected DESC order', $violation); static::assertStringContainsString('id', $violation); @@ -142,24 +191,26 @@ public function test_sorted_constraint_with_dates(): void { $constraint = new SortedByConstraint(ref('date')->asc()); - static::assertTrue($constraint->isSatisfiedBy(row([ + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ 'date' => new DateTimeImmutable('2025-01-01'), - ]), schema(date_schema('date')))); - static::assertTrue($constraint->isSatisfiedBy(row([ + ], schema(datetime_schema('date'))), schema(date_schema('date')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ 'date' => new DateTimeImmutable('2025-01-02'), - ]), schema(date_schema('date')))); - static::assertTrue($constraint->isSatisfiedBy(row([ + ], schema(datetime_schema('date'))), schema(date_schema('date')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ 'date' => new DateTimeImmutable('2025-01-03'), - ]), schema(date_schema('date')))); - static::assertFalse($constraint->isSatisfiedBy(row([ + ], schema(datetime_schema('date'))), schema(date_schema('date')))); + static::assertFalse($constraint->isSatisfiedBy(array_to_row([ 'date' => new DateTimeImmutable('2025-01-01'), - ]), schema(date_schema('date')))); + ], schema(datetime_schema('date'))), schema(date_schema('date')))); } public function test_sorted_constraint_with_single_row(): void { $constraint = new SortedByConstraint(ref('id')->asc()); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 42]), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 42, + ], schema(int_schema('id'))), schema(int_schema('id')))); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/UniqueConstraintTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/UniqueConstraintTest.php index b9fef7efe1..f866a371be 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/UniqueConstraintTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/UniqueConstraintTest.php @@ -8,9 +8,10 @@ use Flow\ETL\Constraint\UniqueConstraint; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; final class UniqueConstraintTest extends FlowTestCase @@ -27,19 +28,19 @@ public function test_unique_constraint_on_multiple_columns(): void $constraint = new UniqueConstraint('id', 'sub_id'); static::assertTrue($constraint->isSatisfiedBy( - row(['id' => 1, 'sub_id' => 1]), + array_to_row(['id' => 1, 'sub_id' => 1], schema(int_schema('id'), int_schema('sub_id'))), schema(int_schema('id'), int_schema('sub_id')), )); static::assertTrue($constraint->isSatisfiedBy( - row(['id' => 1, 'sub_id' => 2]), + array_to_row(['id' => 1, 'sub_id' => 2], schema(int_schema('id'), int_schema('sub_id'))), schema(int_schema('id'), int_schema('sub_id')), )); static::assertTrue($constraint->isSatisfiedBy( - row(['id' => 2, 'sub_id' => 1]), + array_to_row(['id' => 2, 'sub_id' => 1], schema(int_schema('id'), int_schema('sub_id'))), schema(int_schema('id'), int_schema('sub_id')), )); static::assertFalse($constraint->isSatisfiedBy( - row(['id' => 1, 'sub_id' => 1]), + array_to_row(['id' => 1, 'sub_id' => 1], schema(int_schema('id'), int_schema('sub_id'))), schema(int_schema('id'), int_schema('sub_id')), )); } @@ -48,9 +49,15 @@ public function test_unique_constraint_on_single_column(): void { $constraint = new UniqueConstraint('id'); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 1]), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(row(['id' => 2]), schema(int_schema('id')))); - static::assertFalse($constraint->isSatisfiedBy(row(['id' => 1]), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 1, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + 'id' => 2, + ], schema(int_schema('id'))), schema(int_schema('id')))); + static::assertFalse($constraint->isSatisfiedBy(array_to_row([ + 'id' => 1, + ], schema(int_schema('id'))), schema(int_schema('id')))); } public function test_unique_constraint_violation(): void @@ -58,7 +65,7 @@ public function test_unique_constraint_violation(): void $constraint = new UniqueConstraint('id', 'sub_id'); static::assertSame('Values: [id = 1, sub_id = 1]', $constraint->violation( - row(['id' => 1, 'sub_id' => 1]), + array_to_row(['id' => 1, 'sub_id' => 1], schema(int_schema('id'), int_schema('sub_id'))), schema(int_schema('id'), int_schema('sub_id')), )); } @@ -67,8 +74,8 @@ public function test_unique_constraint_violation_on_dates(): void { $constraint = new UniqueConstraint('date'); - static::assertSame('Values: [date = 2025-01-01]', $constraint->violation(row([ + static::assertSame('Values: [date = 2025-01-01]', $constraint->violation(array_to_row([ 'date' => new DateTimeImmutable('2025-01-01'), - ]), schema(date_schema('date')))); + ], schema(datetime_schema('date'))), schema(date_schema('date')))); } } 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 ca235f6b8e..eaade52973 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php @@ -55,6 +55,7 @@ use function array_column; use function array_merge; use function Flow\ETL\DSL\add_row_index; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config_builder; @@ -75,8 +76,6 @@ use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -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; @@ -185,21 +184,25 @@ public function test_count_still_writes_the_frames_sinks(): void public function test_drop(): void { $rows = df() - ->process(rows( + ->process(array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'active' => false], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'active' => false]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), )) ->drop('id') ->fetch(); static::assertEquals( - rows( + array_to_rows( + [ + ['name' => 'foo', 'active' => true], + ['name' => null, 'active' => false], + ['name' => 'bar', 'active' => false], + ], schema(str_schema('name', nullable: true), bool_schema('active')), - row(['name' => 'foo', 'active' => true]), - row(['name' => null, 'active' => false]), - row(['name' => 'bar', 'active' => false]), ), $rows, ); @@ -208,20 +211,21 @@ public function test_drop(): void public function test_drop_duplicates(): void { $rows = df() - ->process(rows( + ->process(array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => 'bar', 'active' => false], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('name'), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), )) ->dropDuplicates(ref('id')) ->fetch(); static::assertEquals( - rows( + array_to_rows( + [['id' => 1, 'name' => 'foo', 'active' => true], ['id' => 2, 'name' => 'bar', 'active' => false]], schema(int_schema('id'), str_schema('name'), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), ), $rows, ); @@ -230,16 +234,18 @@ public function test_drop_duplicates(): void public function test_encapsulate_transformations(): void { $rows = df() - ->process(rows( + ->process(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20, 'gender' => 'male'], + ['id' => 2, 'country' => 'PL', 'age' => 20, 'gender' => 'male'], + ['id' => 3, 'country' => 'PL', 'age' => 25, 'gender' => 'male'], + ['id' => 4, 'country' => 'PL', 'age' => 30, 'gender' => 'female'], + ['id' => 5, 'country' => 'US', 'age' => 40, 'gender' => 'female'], + ['id' => 6, 'country' => 'US', 'age' => 40, 'gender' => 'male'], + ['id' => 7, 'country' => 'US', 'age' => 45, 'gender' => 'female'], + ['id' => 9, 'country' => 'US', 'age' => 50, 'gender' => 'male'], + ], schema(int_schema('id'), str_schema('country'), int_schema('age'), str_schema('gender')), - row(['id' => 1, 'country' => 'PL', 'age' => 20, 'gender' => 'male']), - row(['id' => 2, 'country' => 'PL', 'age' => 20, 'gender' => 'male']), - row(['id' => 3, 'country' => 'PL', 'age' => 25, 'gender' => 'male']), - row(['id' => 4, 'country' => 'PL', 'age' => 30, 'gender' => 'female']), - row(['id' => 5, 'country' => 'US', 'age' => 40, 'gender' => 'female']), - row(['id' => 6, 'country' => 'US', 'age' => 40, 'gender' => 'male']), - row(['id' => 7, 'country' => 'US', 'age' => 45, 'gender' => 'female']), - row(['id' => 9, 'country' => 'US', 'age' => 50, 'gender' => 'male']), )) ->rows(new class implements Transformation { public function transform(DataFrame $dataFrame): DataFrame @@ -258,16 +264,18 @@ public function transform(DataFrame $dataFrame): DataFrame ->fetch(); static::assertEquals( - rows( + array_to_rows( + [ + ['country' => 'pl', 'age' => 2.0], + ['country' => 'pl', 'age' => 2.0], + ['country' => 'pl', 'age' => 2.5], + ['country' => 'pl', 'age' => 3.0], + ['country' => 'us', 'age' => 4.0], + ['country' => 'us', 'age' => 4.0], + ['country' => 'us', 'age' => 4.5], + ['country' => 'us', 'age' => 5.0], + ], schema(str_schema('country'), float_schema('age')), - row(['country' => 'pl', 'age' => 2.0]), - row(['country' => 'pl', 'age' => 2.0]), - row(['country' => 'pl', 'age' => 2.5]), - row(['country' => 'pl', 'age' => 3.0]), - row(['country' => 'us', 'age' => 4.0]), - row(['country' => 'us', 'age' => 4.0]), - row(['country' => 'us', 'age' => 4.5]), - row(['country' => 'us', 'age' => 5.0]), ), $rows, ); @@ -295,7 +303,7 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 1; $i <= 10; $i++) { - yield rows(schema(integer_schema('id')), row(['id' => $i])); + yield array_to_rows([['id' => $i]], schema(integer_schema('id'))); } } @@ -314,19 +322,23 @@ public function statistics(): Statistics public function test_foreach(): void { df() - ->process(rows( + ->process(array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'active' => false], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'active' => false]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), )) ->foreach(function (Rows $rows): void { $this->assertEquals( - rows( + array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'active' => false], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'active' => false]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), ), $rows, ); @@ -336,14 +348,16 @@ public function test_foreach(): void public function test_get(): void { $rows = df()->read(from_rows( - $extractedRows = rows( + $extractedRows = array_to_rows( + [ + ['id' => 1, 'name' => 'foo'], + ['id' => 2, 'name' => 'bar'], + ['id' => 3, 'name' => 'baz'], + ['id' => 4, 'name' => 'foo'], + ['id' => 5, 'name' => 'bar'], + ['id' => 6, 'name' => 'baz'], + ], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'foo']), - row(['id' => 2, 'name' => 'bar']), - row(['id' => 3, 'name' => 'baz']), - row(['id' => 4, 'name' => 'foo']), - row(['id' => 5, 'name' => 'bar']), - row(['id' => 6, 'name' => 'baz']), ), ))->get(); @@ -354,14 +368,16 @@ public function test_get_as_array(): void { $rows = df() ->read(from_rows( - $extractedRows = rows( + $extractedRows = array_to_rows( + [ + ['id' => 1, 'name' => 'foo'], + ['id' => 2, 'name' => 'bar'], + ['id' => 3, 'name' => 'baz'], + ['id' => 4, 'name' => 'foo'], + ['id' => 5, 'name' => 'bar'], + ['id' => 6, 'name' => 'baz'], + ], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'foo']), - row(['id' => 2, 'name' => 'bar']), - row(['id' => 3, 'name' => 'baz']), - row(['id' => 4, 'name' => 'foo']), - row(['id' => 5, 'name' => 'bar']), - row(['id' => 6, 'name' => 'baz']), ), )) ->getAsArray(); @@ -374,44 +390,19 @@ public function test_get_as_array(): void ); } - public function test_get_each(): void - { - $rows = df() - ->read(from_rows(rows( - schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'foo']), - row(['id' => 2, 'name' => 'bar']), - row(['id' => 3, 'name' => 'baz']), - row(['id' => 4, 'name' => 'foo']), - row(['id' => 5, 'name' => 'bar']), - row(['id' => 6, 'name' => 'baz']), - ))) - ->getEach(); - - static::assertEquals( - [ - row(['id' => 1, 'name' => 'foo']), - row(['id' => 2, 'name' => 'bar']), - row(['id' => 3, 'name' => 'baz']), - row(['id' => 4, 'name' => 'foo']), - row(['id' => 5, 'name' => 'bar']), - row(['id' => 6, 'name' => 'baz']), - ], - iterator_to_array($rows), - ); - } - public function test_get_each_as_array(): void { $rows = df() - ->read(from_rows(rows( + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'name' => 'foo'], + ['id' => 2, 'name' => 'bar'], + ['id' => 3, 'name' => 'baz'], + ['id' => 4, 'name' => 'foo'], + ['id' => 5, 'name' => 'bar'], + ['id' => 6, 'name' => 'baz'], + ], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'foo']), - row(['id' => 2, 'name' => 'bar']), - row(['id' => 3, 'name' => 'baz']), - row(['id' => 4, 'name' => 'foo']), - row(['id' => 5, 'name' => 'bar']), - row(['id' => 6, 'name' => 'baz']), ))) ->getEachAsArray(); @@ -450,7 +441,7 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { for ($i = 1; $i <= 10; $i++) { - yield rows(schema(integer_schema('id')), row(['id' => $i])); + yield array_to_rows([['id' => $i]], schema(integer_schema('id'))); } } @@ -505,34 +496,34 @@ public function schema(): Schema */ public function extract(FlowContext $context, ?int $limit = null): Generator { - yield rows( - schema( - int_schema('id'), - bool_schema('deleted'), - datetime_schema('expiration-date'), - str_schema('phase', nullable: true), - ), - row([ + yield array_to_rows( + [[ 'id' => 101, 'deleted' => false, 'expiration-date' => new DateTimeImmutable('2020-08-24'), 'phase' => null, - ]), - ); - - yield rows( + ]], schema( int_schema('id'), bool_schema('deleted'), datetime_schema('expiration-date'), str_schema('phase', nullable: true), ), - row([ + ); + + yield array_to_rows( + [[ 'id' => 102, 'deleted' => true, 'expiration-date' => new DateTimeImmutable('2020-08-25'), 'phase' => null, - ]), + ]], + schema( + int_schema('id'), + bool_schema('deleted'), + datetime_schema('expiration-date'), + str_schema('phase', nullable: true), + ), ); } @@ -553,10 +544,10 @@ public function transform(Rows $rows, FlowContext $context): Rows $stamped = []; foreach ($rows->all() as $row) { - $stamped[] = row([...$row->values(), 'stamp' => 'zero']); + $stamped[] = [...$row->values(), 'stamp' => 'zero']; } - return rows($rows->schema()->add(str_schema('stamp')), ...$stamped); + return array_to_rows($stamped, $rows->schema()->add(str_schema('stamp'))); } }; @@ -599,19 +590,19 @@ public function test_process_constructor(): void { $collectedRows = data_frame() ->process( - $rows = rows( + $rows = array_to_rows( + [[ + 'id' => 101, + 'deleted' => false, + 'expiration-date' => new DateTimeImmutable('2020-08-24'), + 'phase' => null, + ]], schema( int_schema('id'), bool_schema('deleted'), datetime_schema('expiration-date'), str_schema('phase', nullable: true), ), - row([ - 'id' => 101, - 'deleted' => false, - 'expiration-date' => new DateTimeImmutable('2020-08-24'), - 'phase' => null, - ]), ), ) ->fetch(); @@ -622,21 +613,21 @@ public function test_process_constructor(): void public function test_select(): void { $rows = data_frame() - ->process(rows( + ->process(array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'active' => false], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'active' => false]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), )) ->select('name', 'id') ->fetch(); static::assertEquals( - rows( + array_to_rows( + [['name' => 'foo', 'id' => 1], ['name' => null, 'id' => 2], ['name' => 'bar', 'id' => 2]], schema(str_schema('name', nullable: true), int_schema('id')), - row(['name' => 'foo', 'id' => 1]), - row(['name' => null, 'id' => 2]), - row(['name' => 'bar', 'id' => 2]), ), $rows, ); @@ -645,31 +636,35 @@ public function test_select(): void public function test_selective_validation_against_schema(): void { $rows = data_frame() - ->process(rows( + ->process(array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'tags' => type_json()->cast(['foo', 'bar'])], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema( int_schema('id'), str_schema('name', nullable: true), bool_schema('active', nullable: true), json_schema('tags', nullable: true), ), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'tags' => type_json()->cast(['foo', 'bar'])]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), )) ->match(schema(integer_schema('id', false)), new SelectiveValidator()) ->fetch(); static::assertSame( - rows( + array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'tags' => type_json()->cast(['foo', 'bar'])], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema( int_schema('id'), str_schema('name', nullable: true), bool_schema('active', nullable: true), json_schema('tags', nullable: true), ), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'tags' => type_json()->cast(['foo', 'bar'])]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), )->toArray(), $rows->toArray(), ); @@ -706,21 +701,25 @@ public function test_sort_by_accepts_column_name_strings_inside_the_array_form() public function test_strict_validation_against_schema(): void { $rows = data_frame() - ->process(rows( + ->process(array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'active' => false], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'active' => false]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), )) ->match(schema(integer_schema('id', false), string_schema('name', true), bool_schema('active', false))) ->fetch(); static::assertSame( - rows( + array_to_rows( + [ + ['id' => 1, 'name' => 'foo', 'active' => true], + ['id' => 2, 'name' => null, 'active' => false], + ['id' => 2, 'name' => 'bar', 'active' => false], + ], schema(int_schema('id'), str_schema('name', nullable: true), bool_schema('active')), - row(['id' => 1, 'name' => 'foo', 'active' => true]), - row(['id' => 2, 'name' => null, 'active' => false]), - row(['id' => 2, 'name' => 'bar', 'active' => false]), )->toArray(), $rows->toArray(), ); @@ -762,16 +761,18 @@ public function test_until(): void public function test_void(): void { $rows = data_frame() - ->process(rows( + ->process(array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'age' => 20], + ['id' => 2, 'country' => 'PL', 'age' => 20], + ['id' => 3, 'country' => 'PL', 'age' => 25], + ['id' => 4, 'country' => 'PL', 'age' => 30], + ['id' => 5, 'country' => 'US', 'age' => 40], + ['id' => 6, 'country' => 'US', 'age' => 40], + ['id' => 7, 'country' => 'US', 'age' => 45], + ['id' => 9, 'country' => 'US', 'age' => 50], + ], schema(int_schema('id'), str_schema('country'), int_schema('age')), - row(['id' => 1, 'country' => 'PL', 'age' => 20]), - row(['id' => 2, 'country' => 'PL', 'age' => 20]), - row(['id' => 3, 'country' => 'PL', 'age' => 25]), - row(['id' => 4, 'country' => 'PL', 'age' => 30]), - row(['id' => 5, 'country' => 'US', 'age' => 40]), - row(['id' => 6, 'country' => 'US', 'age' => 40]), - row(['id' => 7, 'country' => 'US', 'age' => 45]), - row(['id' => 9, 'country' => 'US', 'age' => 50]), )) ->rename('country', 'country_code') ->void() @@ -782,7 +783,7 @@ public function test_void(): void // void() drops rows, not columns - the batch it yields carries the plan's declared schema, and // the global aggregate that follows it reads zero rows, so it emits its initial accumulators static::assertEquals( - rows(schema(float_schema('average_age', nullable: true)), row(['average_age' => null])), + array_to_rows([['average_age' => null]], schema(float_schema('average_age', nullable: true))), $rows, ); } @@ -808,19 +809,18 @@ public function schema(): Schema */ public function extract(FlowContext $context, ?int $limit = null): Generator { - yield rows( - schema(integer_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - row(['id' => 6]), - row(['id' => 7]), - row(['id' => 8]), - row(['id' => 9]), - row(['id' => 10]), - ); + yield array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ['id' => 6], + ['id' => 7], + ['id' => 8], + ['id' => 9], + ['id' => 10], + ], schema(integer_schema('id'))); } public function statistics(): Statistics @@ -870,9 +870,9 @@ public function schema(): Schema */ 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])); - yield rows(schema(integer_schema('id')), row(['id' => 3])); + yield array_to_rows([['id' => 1]], schema(integer_schema('id'))); + yield array_to_rows([['id' => 2]], schema(integer_schema('id'))); + yield array_to_rows([['id' => 3]], schema(integer_schema('id'))); } public function statistics(): Statistics @@ -947,7 +947,7 @@ public function test_a_pushed_limit_reaches_extract_and_leaves_the_users_extract { $extractor = new RecordingFileExtractor( schema(int_schema('id')), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); $frame = df() ->read($extractor) @@ -976,7 +976,7 @@ public function test_a_limit_inside_a_joins_right_side_is_pushed_into_that_sourc { $extractor = new RecordingFileExtractor( schema(int_schema('id')), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); $right = df()->read($extractor)->limit(1); @@ -1002,17 +1002,17 @@ public function test_an_empty_fetch_plans_once(): void static::assertCount(1, $log); } - public function test_an_abandoned_get_each_leaves_no_consumed_step_for_the_next_run(): void + public function test_an_abandoned_get_each_as_array_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])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), + array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))), )) ->limit(3); // the reference keeps the generator parked, so its steps stay consumed - $parked = $dataFrame->getEach(); + $parked = $dataFrame->getEachAsArray(); $parked->current(); static::assertCount(3, $dataFrame->fetch()); @@ -1107,7 +1107,7 @@ public function test_a_limit_inside_a_read_frame_is_pushed_into_its_source(): vo { $extractor = new RecordingFileExtractor( schema(int_schema('id')), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); $inner = df()->read($extractor)->limit(1); 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 f5ae242a1b..7f8964d39e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/ETLErrorHandlingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/ETLErrorHandlingTest.php @@ -20,6 +20,7 @@ use RuntimeException; use function array_merge; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\datetime_schema; @@ -29,8 +30,6 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -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; @@ -75,19 +74,19 @@ public function extract(FlowContext $context, ?int $limit = null): Generator str_schema('phase', true), ); - yield rows($schema, row([ + yield array_to_rows([[ 'id' => 101, 'deleted' => false, 'expiration-date' => new DateTimeImmutable('2020-08-24'), 'phase' => null, - ])); + ]], $schema); - yield rows($schema, row([ + yield array_to_rows([[ 'id' => 102, 'deleted' => true, 'expiration-date' => new DateTimeImmutable('2020-08-25'), 'phase' => null, - ])); + ]], $schema); } public function statistics(): Statistics @@ -156,19 +155,19 @@ public function extract(FlowContext $context, ?int $limit = null): Generator str_schema('phase', true), ); - yield rows($schema, row([ + yield array_to_rows([[ 'id' => 101, 'deleted' => false, 'expiration-date' => new DateTimeImmutable('2020-08-24'), 'phase' => null, - ])); + ]], $schema); - yield rows($schema, row([ + yield array_to_rows([[ 'id' => 102, 'deleted' => true, 'expiration-date' => new DateTimeImmutable('2020-08-25'), 'phase' => null, - ])); + ]], $schema); } public function statistics(): Statistics @@ -259,19 +258,19 @@ public function extract(FlowContext $context, ?int $limit = null): Generator str_schema('phase', true), ); - yield rows($schema, row([ + yield array_to_rows([[ 'id' => 101, 'deleted' => false, 'expiration-date' => new DateTimeImmutable('2020-08-24'), 'phase' => null, - ])); + ]], $schema); - yield rows($schema, row([ + yield array_to_rows([[ 'id' => 102, 'deleted' => true, 'expiration-date' => new DateTimeImmutable('2020-08-25'), 'phase' => null, - ])); + ]], $schema); } public function statistics(): Statistics diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php index 6e3e8cafac..a8f5eafec4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php @@ -19,6 +19,7 @@ use function array_map; use function array_sum; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; @@ -26,7 +27,6 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function iterator_to_array; @@ -52,23 +52,23 @@ public function test_constructor_with_negative_offset_throws_exception(): void public function test_process_maintains_row_structure_with_mixed_entry_types(): void { - $segments = new Segments(from_rows(rows( + $segments = new Segments(from_rows(array_to_rows( + [ + ['id' => 1, 'active' => true], + ['id' => 2, 'active' => false], + ['id' => 3, 'active' => true], + ['id' => 4, 'active' => false], + ], 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]), ))); $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( - rows( + array_to_rows( + [['id' => 2, 'active' => false], ['id' => 3, 'active' => true], ['id' => 4, 'active' => false]], schema(int_schema('id'), bool_schema('active')), - row(['id' => 2, 'active' => false]), - row(['id' => 3, 'active' => true]), - row(['id' => 4, 'active' => false]), ), $result[0], ); @@ -97,9 +97,9 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); + yield array_to_rows([['id' => 5], ['id' => 6]], schema(int_schema('id'))); } public function statistics(): Statistics @@ -110,7 +110,7 @@ public function statistics(): Statistics $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]); + static::assertEquals(array_to_rows([['id' => 5], ['id' => 6]], schema(int_schema('id'))), $result[0]); } public function test_process_with_multiple_batches_offset_spanning_batches(): void @@ -128,9 +128,9 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4], ['id' => 5]], schema(int_schema('id'))); + yield array_to_rows([['id' => 6]], schema(int_schema('id'))); } public function statistics(): Statistics @@ -141,8 +141,8 @@ public function statistics(): Statistics $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]); + static::assertEquals(array_to_rows([['id' => 4], ['id' => 5]], schema(int_schema('id'))), $result[0]); + static::assertEquals(array_to_rows([['id' => 6]], schema(int_schema('id'))), $result[1]); } public function test_process_with_multiple_batches_offset_within_first_batch(): void @@ -160,8 +160,8 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); + yield array_to_rows([['id' => 4], ['id' => 5]], schema(int_schema('id'))); } public function statistics(): Statistics @@ -172,18 +172,17 @@ public function statistics(): Statistics $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]); + static::assertEquals(array_to_rows([['id' => 2], ['id' => 3]], schema(int_schema('id'))), $result[0]); + static::assertEquals(array_to_rows([['id' => 4], ['id' => 5]], schema(int_schema('id'))), $result[1]); } public function test_process_with_offset_equal_to_batch_size(): void { - $segments = new Segments(from_rows(rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - ))); + $segments = new Segments(from_rows(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id'))))); $segments->add(new OffsetProcessor(3)); $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(0, $result); @@ -191,7 +190,7 @@ public function test_process_with_offset_equal_to_batch_size(): void public function test_process_with_offset_larger_than_batch_size(): void { - $segments = new Segments(from_rows(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])))); + $segments = new Segments(from_rows(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))))); $segments->add(new OffsetProcessor(5)); $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); static::assertCount(0, $result); @@ -212,9 +211,9 @@ public function schema(): Schema public function extract(FlowContext $context, ?int $limit = null): Generator { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); yield rows(schema()); - yield rows(schema(int_schema('id')), row(['id' => 3])); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); } public function statistics(): Statistics @@ -225,38 +224,36 @@ public function statistics(): Statistics $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]); + static::assertEquals(array_to_rows([['id' => 3]], schema(int_schema('id'))), $result[0]); } public function test_process_with_offset_smaller_than_batch_size(): void { - $segments = new Segments(from_rows(rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - ))); + $segments = new Segments(from_rows(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))))); $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( - rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 4]), row(['id' => 5])), + array_to_rows([['id' => 3], ['id' => 4], ['id' => 5]], schema(int_schema('id'))), $result[0], ); } public function test_process_with_transformer_before_offset(): void { - $segments = new Segments(from_rows(rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - ))); + $segments = new Segments(from_rows(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ], schema(int_schema('id'))))); $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()))); @@ -274,9 +271,9 @@ public function test_process_with_various_offset_values(int $offset): void { $rowsData = []; for ($i = 1; $i <= 20; $i++) { - $rowsData[] = row(['id' => $i]); + $rowsData[] = ['id' => $i]; } - $segments = new Segments(from_rows(rows(schema(int_schema('id')), ...$rowsData))); + $segments = new Segments(from_rows(array_to_rows($rowsData, schema(int_schema('id'))))); $segments->add(new OffsetProcessor($offset >= 0 ? $offset : 0)); $result = iterator_to_array(ExecutedSegments::of($segments, flow_context(config()))); $expectedCount = max(0, 20 - $offset); @@ -290,18 +287,17 @@ public function test_process_with_various_offset_values(int $offset): void public function test_process_with_zero_offset_returns_all_data(): void { - $segments = new Segments(from_rows(rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - ))); + $segments = new Segments(from_rows(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id'))))); $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( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), + array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), $result[0], ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SourceRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SourceRowsTest.php index 59bc66e0d8..1fbcd00b14 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SourceRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/SourceRowsTest.php @@ -12,11 +12,10 @@ use Flow\ETL\Tests\Double\CountingExtractor; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_array; 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; use function iterator_to_array; @@ -40,7 +39,7 @@ public function test_a_stop_reaches_the_source_and_ends_the_count(): void { $extractor = new CountingExtractor( schema(int_schema('id')), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), + array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), ); $extractor->withBatchSize(1); $sources = new SourceRows(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/StatisticsCollectorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/StatisticsCollectorTest.php index 9c466dac8a..5beb8b28cd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/StatisticsCollectorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/StatisticsCollectorTest.php @@ -17,11 +17,10 @@ use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\analyze; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_array; 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; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -32,10 +31,9 @@ public function test_capture_collects_column_statistics_when_enabled(): void { $collector = new StatisticsCollector(analyze()->withColumnStatistics(), flow_context()); - $collector->capture(rows( + $collector->capture(array_to_rows( + [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'Alice']), - row(['id' => 2, 'name' => 'Bob']), )); $report = $collector->report(); @@ -51,7 +49,10 @@ public function test_capture_collects_schema_when_enabled(): void { $collector = new StatisticsCollector(analyze()->withSchema(), flow_context()); - $collector->capture(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'Alice']))); + $collector->capture(array_to_rows( + [['id' => 1, 'name' => 'Alice']], + schema(int_schema('id'), str_schema('name')), + )); $report = $collector->report(); @@ -67,8 +68,8 @@ public function test_capture_increments_row_count_correctly(): void { $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->capture(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); + $collector->capture(array_to_rows([['id' => 3]], schema(int_schema('id')))); $report = $collector->report(); @@ -80,7 +81,7 @@ public function test_capture_is_noop_when_analyze_is_false(): void { $collector = new StatisticsCollector(false, flow_context()); - $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); + $collector->capture(array_to_rows([['id' => 1]], schema(int_schema('id')))); static::assertNull($collector->report()); } @@ -89,7 +90,7 @@ public function test_column_statistics_is_null_when_not_enabled(): void { $collector = new StatisticsCollector(analyze(), flow_context()); - $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); + $collector->capture(array_to_rows([['id' => 1]], schema(int_schema('id')))); $report = $collector->report(); @@ -135,7 +136,7 @@ public function test_report_returns_report_with_correct_execution_time(): void $collector = new StatisticsCollector(true, $context); $clock->modify('+5 minutes'); - $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); + $collector->capture(array_to_rows([['id' => 1]], schema(int_schema('id')))); $clock->modify('+5 minutes'); $report = $collector->report(); @@ -156,7 +157,7 @@ public function test_report_returns_report_with_high_resolution_time(): void { $collector = new StatisticsCollector(true, flow_context()); - $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); + $collector->capture(array_to_rows([['id' => 1]], schema(int_schema('id')))); $report = $collector->report(); @@ -168,7 +169,7 @@ public function test_report_returns_report_with_memory_consumption(): void { $collector = new StatisticsCollector(true, flow_context()); - $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); + $collector->capture(array_to_rows([['id' => 1]], schema(int_schema('id')))); $report = $collector->report(); @@ -208,7 +209,7 @@ public function test_schema_is_null_when_not_enabled(): void { $collector = new StatisticsCollector(analyze(), flow_context()); - $collector->capture(rows(schema(int_schema('id')), row(['id' => 1]))); + $collector->capture(array_to_rows([['id' => 1]], schema(int_schema('id')))); $report = $collector->report(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php index eef87678f6..09adab5564 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php @@ -9,12 +9,12 @@ use Flow\ETL\Tests\Context\ExecutedSegments; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; 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\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\row_number; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; @@ -39,10 +39,9 @@ public function test_handles_empty_input(): void public function test_handles_no_order_by(): void { - $segments = new Segments(from_rows(rows( + $segments = new Segments(from_rows(array_to_rows( + [['dept' => 'IT', 'value' => 100], ['dept' => 'IT', 'value' => 150]], schema(str_schema('dept'), int_schema('value')), - row(['dept' => 'IT', 'value' => 100]), - row(['dept' => 'IT', 'value' => 150]), ))); $window = window()->partitionBy(ref('dept')); @@ -65,8 +64,8 @@ public function test_handles_single_row_partition(): void // one Rows per partition key $schema = schema(str_schema('dept'), int_schema('salary')); $segments = new Segments(from_rows( - rows($schema, row(['dept' => 'IT', 'salary' => 5000])), - rows($schema, row(['dept' => 'HR', 'salary' => 4000])), + array_to_rows([['dept' => 'IT', 'salary' => 5000]], $schema), + array_to_rows([['dept' => 'HR', 'salary' => 4000]], $schema), )); $window = window()->partitionBy(ref('dept'))->orderBy(ref('salary')); @@ -85,8 +84,8 @@ public function test_processes_multiple_partitions_separately(): void { $schema = schema(str_schema('dept'), int_schema('salary')); $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])), + array_to_rows([['dept' => 'IT', 'salary' => 5000], ['dept' => 'IT', 'salary' => 6000]], $schema), + array_to_rows([['dept' => 'HR', 'salary' => 4000], ['dept' => 'HR', 'salary' => 4500]], $schema), )); $window = window()->partitionBy(ref('dept'))->orderBy(ref('salary')); @@ -109,11 +108,9 @@ public function test_processes_multiple_partitions_separately(): void public function test_processes_single_partition_without_partition_by(): void { - $segments = new Segments(from_rows(rows( + $segments = new Segments(from_rows(array_to_rows( + [['id' => 1, 'value' => 100], ['id' => 2, 'value' => 150], ['id' => 3, 'value' => 200]], schema(int_schema('id'), int_schema('value')), - row(['id' => 1, 'value' => 100]), - row(['id' => 2, 'value' => 150]), - row(['id' => 3, 'value' => 200]), ))); $window = window()->orderBy(ref('id')); @@ -132,11 +129,13 @@ public function test_processes_single_partition_without_partition_by(): void public function test_sorts_partition_by_order_by(): void { - $segments = new Segments(from_rows(rows( + $segments = new Segments(from_rows(array_to_rows( + [ + ['dept' => 'IT', 'salary' => 6000], + ['dept' => 'IT', 'salary' => 5000], + ['dept' => 'IT', 'salary' => 7000], + ], schema(str_schema('dept'), int_schema('salary')), - row(['dept' => 'IT', 'salary' => 6000]), - row(['dept' => 'IT', 'salary' => 5000]), - row(['dept' => 'IT', 'salary' => 7000]), ))); $window = window()->partitionBy(ref('dept'))->orderBy(ref('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 index ccdab6b92e..c7ffc00d3c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php @@ -35,12 +35,12 @@ use function array_map; use function array_sum; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\from_array; 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; use function iterator_to_array; @@ -241,7 +241,7 @@ public function test_merge_merges_every_batch_into_one_rows(): void ); $batches = (static function () { yield RowsMother::sequentialIds(1); - yield rows(schema(int_schema('id')), row(['id' => 2])); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); })(); static::assertSame( @@ -351,8 +351,8 @@ public function test_an_abandoned_run_leaves_no_consumed_step_for_the_next_run() { $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])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), + array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))), )), 3, )); @@ -449,8 +449,8 @@ 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])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), ))), $telemetry->flowContext, ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php index e927239705..b1c4edf867 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php @@ -13,6 +13,7 @@ use Flow\ETL\Tests\Double\VaryingBatchesExtractor; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\batched_by; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; @@ -20,7 +21,6 @@ use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -31,8 +31,8 @@ final class BatchByExtractorTest extends TestCase public function test_a_group_spanning_child_batches_answers_to_the_first_batch_schema(): void { $child = new VaryingBatchesExtractor( - rows(schema(int_schema('g'), str_schema('name', nullable: true)), row(['g' => 1, 'name' => 'a'])), - rows(schema(int_schema('g')), row(['g' => 1])), + array_to_rows([['g' => 1, 'name' => 'a']], schema(int_schema('g'), str_schema('name', nullable: true))), + array_to_rows([['g' => 1]], schema(int_schema('g'))), ); $batches = iterator_to_array(batched_by($child, ref('g'))->extract(flow_context(config())), false); @@ -44,8 +44,8 @@ public function test_a_group_spanning_child_batches_answers_to_the_first_batch_s public function test_a_later_child_batch_that_widens_the_shape_is_refused(): void { $child = new VaryingBatchesExtractor( - rows(schema(int_schema('g')), row(['g' => 1])), - rows(schema(int_schema('g'), str_schema('extra')), row(['g' => 1, 'extra' => 'x'])), + array_to_rows([['g' => 1]], schema(int_schema('g'))), + array_to_rows([['g' => 1, 'extra' => 'x']], schema(int_schema('g'), str_schema('extra'))), ); $this->expectException(SchemaMismatchException::class); @@ -57,13 +57,15 @@ public function test_a_later_child_batch_that_widens_the_shape_is_refused(): voi public function test_grouping_by_column_with_min_size(): void { $extractor = batched_by( - from_rows(rows( + from_rows(array_to_rows( + [ + ['order_id' => 1, 'item' => 1], + ['order_id' => 2, 'item' => 2], + ['order_id' => 3, 'item' => 3], + ['order_id' => 4, 'item' => 4], + ['order_id' => 5, 'item' => 5], + ], schema(int_schema('order_id'), int_schema('item')), - row(['order_id' => 1, 'item' => 1]), - row(['order_id' => 2, 'item' => 2]), - row(['order_id' => 3, 'item' => 3]), - row(['order_id' => 4, 'item' => 4]), - row(['order_id' => 5, 'item' => 5]), )), ref('order_id'), 3, @@ -77,13 +79,15 @@ public function test_grouping_by_column_with_min_size(): void public function test_grouping_by_column_without_min_size(): void { $extractor = batched_by( - from_rows(rows( + from_rows(array_to_rows( + [ + ['order_id' => 1, 'item' => 1], + ['order_id' => 1, 'item' => 2], + ['order_id' => 2, 'item' => 3], + ['order_id' => 2, 'item' => 4], + ['order_id' => 3, 'item' => 5], + ], schema(int_schema('order_id'), int_schema('item')), - row(['order_id' => 1, 'item' => 1]), - row(['order_id' => 1, 'item' => 2]), - row(['order_id' => 2, 'item' => 3]), - row(['order_id' => 2, 'item' => 4]), - row(['order_id' => 3, 'item' => 5]), )), ref('order_id'), null, @@ -98,11 +102,9 @@ public function test_grouping_by_column_without_min_size(): void public function test_grouping_with_all_unique_values(): void { $extractor = batched_by( - from_rows(rows( + from_rows(array_to_rows( + [['order_id' => 1, 'item' => 1], ['order_id' => 2, 'item' => 2], ['order_id' => 3, 'item' => 3]], schema(int_schema('order_id'), int_schema('item')), - row(['order_id' => 1, 'item' => 1]), - row(['order_id' => 2, 'item' => 2]), - row(['order_id' => 3, 'item' => 3]), )), ref('order_id'), null, @@ -124,14 +126,16 @@ public function test_grouping_with_empty_data(): void public function test_grouping_with_large_group_exceeding_min_size(): void { $extractor = batched_by( - from_rows(rows( + from_rows(array_to_rows( + [ + ['order_id' => 1, 'item' => 1], + ['order_id' => 1, 'item' => 2], + ['order_id' => 1, 'item' => 3], + ['order_id' => 1, 'item' => 4], + ['order_id' => 1, 'item' => 5], + ['order_id' => 2, 'item' => 6], + ], schema(int_schema('order_id'), int_schema('item')), - row(['order_id' => 1, 'item' => 1]), - row(['order_id' => 1, 'item' => 2]), - row(['order_id' => 1, 'item' => 3]), - row(['order_id' => 1, 'item' => 4]), - row(['order_id' => 1, 'item' => 5]), - row(['order_id' => 2, 'item' => 6]), )), ref('order_id'), 2, @@ -145,11 +149,9 @@ public function test_grouping_with_large_group_exceeding_min_size(): void public function test_grouping_with_single_group(): void { $extractor = batched_by( - from_rows(rows( + from_rows(array_to_rows( + [['order_id' => 1, 'item' => 1], ['order_id' => 1, 'item' => 2], ['order_id' => 1, 'item' => 3]], schema(int_schema('order_id'), int_schema('item')), - row(['order_id' => 1, 'item' => 1]), - row(['order_id' => 1, 'item' => 2]), - row(['order_id' => 1, 'item' => 3]), )), ref('order_id'), null, @@ -169,7 +171,7 @@ public function test_min_size_validation(): void public function test_with_schema_does_not_leak_into_a_second_pipeline(): void { - $child = from_rows(rows(schema(int_schema('id')), row(['id' => 1]))); + $child = from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')))); iterator_to_array( batched_by($child, ref('id')) @@ -188,7 +190,7 @@ public function test_with_schema_does_not_leak_into_a_second_pipeline(): void public function test_is_repeatable(): void { static::assertTrue( - batched_by(from_rows(rows(schema(int_schema('id')), row(['id' => 1]))), ref('id'))->isRepeatable(), + batched_by(from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')))), ref('id'))->isRepeatable(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchExtractorTest.php index 6088e5a998..2086810667 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchExtractorTest.php @@ -25,8 +25,6 @@ use function Flow\ETL\DSL\from_memory; 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; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -62,8 +60,8 @@ public function test_a_buffer_spanning_child_batches_answers_to_the_first_batch_ // the second child batch omits a column the first declares nullable - the buffer that spans // both must carry one schema, and the later rows are matched to it rather than mislabelled $child = new VaryingBatchesExtractor( - rows(schema(int_schema('id'), str_schema('name', nullable: true)), row(['id' => 1, 'name' => 'a'])), - rows(schema(int_schema('id')), row(['id' => 2])), + array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name', nullable: true))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), ); $batches = iterator_to_array(batches($child, 2)->extract(flow_context()), false); @@ -76,8 +74,8 @@ public function test_a_buffer_spanning_child_batches_answers_to_the_first_batch_ public function test_a_later_child_batch_that_widens_the_shape_is_refused(): void { $child = new VaryingBatchesExtractor( - rows(schema(int_schema('id')), row(['id' => 1])), - rows(schema(int_schema('id'), str_schema('extra')), row(['id' => 2, 'extra' => 'x'])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2, 'extra' => 'x']], schema(int_schema('id'), str_schema('extra'))), ); $this->expectException(SchemaMismatchException::class); @@ -126,7 +124,7 @@ public function test_throws_when_constructed_with_zero_batch_size(): void public function test_with_schema_does_not_leak_into_a_second_pipeline(): void { - $child = from_rows(rows(schema(int_schema('id')), row(['id' => 1]))); + $child = from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')))); iterator_to_array( batches($child, 1) 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 92768cfdb4..80658384f0 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 @@ -15,6 +15,7 @@ use Flow\ETL\Tests\FlowTestCase; use Generator; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_all; @@ -23,7 +24,6 @@ use function Flow\ETL\DSL\from_memory; 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; use function Flow\ETL\DSL\str_schema; @@ -36,8 +36,8 @@ public function test_a_chain_containing_a_data_frame_source_folds_its_schema(): static::assertEquals( schema(int_schema('id', true), str_schema('name', true)), from_all( - from_rows(rows(schema(int_schema('id')), row(['id' => 1]))), - from_data_frame(df()->read(from_rows(rows(schema(str_schema('name')), row(['name' => 'a']))))), + from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')))), + from_data_frame(df()->read(from_rows(array_to_rows([['name' => 'a']], schema(str_schema('name')))))), )->schema(), ); } @@ -63,8 +63,8 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); } public function statistics(): Statistics @@ -84,8 +84,8 @@ public function schema(): Schema 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])); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); + yield array_to_rows([['id' => 4]], schema(int_schema('id'))); } public function statistics(): Statistics @@ -95,14 +95,14 @@ public function statistics(): Statistics }); self::assertExtractedRowsEquals( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), row(['id' => 4])), + array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))), $extractor, ); } public function test_with_schema_does_not_leak_into_a_second_pipeline(): void { - $child = from_rows(rows(schema(int_schema('id')), row(['id' => 1]))); + $child = from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')))); iterator_to_array( from_all($child) @@ -120,7 +120,7 @@ public function test_with_schema_does_not_leak_into_a_second_pipeline(): void public function test_is_repeatable(): void { - static::assertTrue(from_all(from_rows(rows(schema(int_schema('id')), row(['id' => 1]))))->isRepeatable()); + static::assertTrue(from_all(from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')))))->isRepeatable()); } public function test_it_sums_the_statistics_of_its_children(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/CollectingExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/CollectingExtractorTest.php index 8c4877f1fb..69f3b49bf5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/CollectingExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/CollectingExtractorTest.php @@ -11,12 +11,11 @@ use Flow\ETL\Tests\Double\DeclaringExtractor; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_memory; 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; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -27,8 +26,8 @@ public function test_collecting_every_batch_into_one(): void { $collected = iterator_to_array( (new CollectingExtractor(from_rows( - rows(schema(int_schema('id')), row(['id' => 1])), - rows(schema(int_schema('id')), row(['id' => 2])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), )))->extract(flow_context()), false, ); @@ -39,7 +38,7 @@ public function test_collecting_every_batch_into_one(): void public function test_with_schema_does_not_leak_into_a_second_pipeline(): void { - $child = from_rows(rows(schema(int_schema('id')), row(['id' => 1]))); + $child = from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')))); iterator_to_array( (new CollectingExtractor($child)) @@ -57,7 +56,9 @@ public function test_with_schema_does_not_leak_into_a_second_pipeline(): void public function test_is_repeatable(): void { static::assertTrue( - (new CollectingExtractor(from_rows(rows(schema(int_schema('id')), row(['id' => 1])))))->isRepeatable(), + (new CollectingExtractor(from_rows(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))))))->isRepeatable(), ); } 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 dcb1388227..dc607111f5 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 @@ -25,6 +25,7 @@ use function array_map; use function array_merge; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; @@ -35,8 +36,6 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -46,7 +45,7 @@ final class DataFrameExtractorTest extends FlowTestCase public function test_a_build_error_in_the_wrapped_frame_is_not_a_schema_refusal(): void { $extractor = from_data_frame( - df()->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1]))))->select('nope'), + df()->read(from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')))))->select('nope'), ); try { @@ -61,11 +60,10 @@ public function test_a_build_error_in_the_wrapped_frame_is_not_a_schema_refusal( public function test_a_declared_schema_wins_over_the_wrapped_frame(): void { - $extractor = from_data_frame(df()->read(from_rows(rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - )))) + $extractor = from_data_frame(df()->read(from_rows(array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id')))))) ->withSchema(schema(str_schema('id'))); $batches = iterator_to_array($extractor->extract(flow_context(config()))); @@ -75,6 +73,19 @@ 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_narrower_than_the_frame_projects_its_columns(): void + { + $extractor = from_data_frame(df()->read(from_rows(array_to_rows( + [['id' => 1, 'name' => 'one'], ['id' => 2, 'name' => 'two']], + schema(int_schema('id'), str_schema('name')), + )))) + ->withSchema(schema(int_schema('id'))); + + $batches = iterator_to_array($extractor->extract(flow_context(config()))); + + 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')); @@ -146,7 +157,7 @@ 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])), + array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), ); $batches = iterator_to_array(from_data_frame(df()->read($source))->extract(flow_context(config()), 2), false); @@ -174,7 +185,7 @@ public function test_a_refusal_from_the_wrapped_frame_is_re_raised_unchanged(): public function test_the_frame_is_frozen_at_construction(): void { - $inner = df()->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1])))); + $inner = df()->read(from_rows(array_to_rows([['id' => 1]], schema(int_schema('id'))))); $extractor = from_data_frame($inner); $inner->withEntry('doubled', ref('id')->multiply(lit(2))); @@ -187,7 +198,9 @@ 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])))))) + ->read(new DataFrameExtractor(df()->read(from_rows(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))))))) ->fetch() ->toArray(), ); @@ -209,7 +222,7 @@ public function test_an_error_handler_set_after_embedding_does_not_reach_the_fra 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); + $inner = df()->read(from_rows(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))))->limit(1); static::assertSame( [['id' => 1], ['id' => 3]], @@ -224,8 +237,8 @@ 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])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), ); $counting->withBatchSize(1); $generator = from_data_frame(df()->read($counting))->extract(flow_context(config())); @@ -239,7 +252,10 @@ public function test_extract_stops_on_signal_stop(): void 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]))); + $counting = new CountingExtractor( + schema(int_schema('id')), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); $extractor = from_data_frame(df()->read($counting)->limit(1)); $extractor->schema(); @@ -254,7 +270,7 @@ public function test_extract_opens_and_closes_one_dataframe_span_for_the_wrapped { $telemetry = new MemoryTelemetryContext(); $extractor = from_data_frame( - df($telemetry->config)->read(from_rows(rows(schema(int_schema('id')), row(['id' => 1])))), + df($telemetry->config)->read(from_rows(array_to_rows([['id' => 1]], schema(int_schema('id'))))), ) ->withSchema(schema(int_schema('id'))); @@ -267,18 +283,17 @@ public function test_extract_opens_and_closes_one_dataframe_span_for_the_wrapped public function test_extracting_from_another_data_frame(): void { $extractor = from_data_frame(df()->read(from_rows( - rows(schema(str_schema('value')), row(['value' => 'test']), row(['value' => 'test'])), - rows(schema(str_schema('value')), row(['value' => 'test']), row(['value' => 'test'])), + array_to_rows([['value' => 'test'], ['value' => 'test']], schema(str_schema('value'))), + array_to_rows([['value' => 'test'], ['value' => 'test']], schema(str_schema('value'))), ))); self::assertExtractedRowsEquals( - rows( - schema(str_schema('value')), - row(['value' => 'test']), - row(['value' => 'test']), - row(['value' => 'test']), - row(['value' => 'test']), - ), + array_to_rows([ + ['value' => 'test'], + ['value' => 'test'], + ['value' => 'test'], + ['value' => 'test'], + ], schema(str_schema('value'))), $extractor, ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FeedExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FeedExtractorTest.php index 9e09913886..0aeb21e637 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FeedExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FeedExtractorTest.php @@ -12,11 +12,10 @@ use Flow\ETL\Tests\FlowTestCase; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -38,7 +37,7 @@ public function test_finish_ends_the_stream(): void $collected = []; $completed = false; - $extractor->feed(rows(schema(int_schema('id')), row(['id' => 1]))); + $extractor->feed(array_to_rows([['id' => 1]], schema(int_schema('id')))); $fiber = new Fiber(static function () use ($extractor, $context, &$collected, &$completed): void { foreach ($extractor->extract($context) as $rows) { @@ -71,7 +70,7 @@ public function test_resumes_with_the_next_fed_batch(): void $context = flow_context(config()); $collected = []; - $extractor->feed(rows(schema(int_schema('id')), row(['id' => 1]))); + $extractor->feed(array_to_rows([['id' => 1]], schema(int_schema('id')))); $fiber = new Fiber(static function () use ($extractor, $context, &$collected): void { foreach ($extractor->extract($context) as $rows) { @@ -80,7 +79,7 @@ public function test_resumes_with_the_next_fed_batch(): void }); $fiber->start(); - $extractor->feed(rows(schema(int_schema('id')), row(['id' => 2]))); + $extractor->feed(array_to_rows([['id' => 2]], schema(int_schema('id')))); $fiber->resume(); static::assertTrue($fiber->isSuspended()); @@ -97,7 +96,7 @@ public function test_stop_signal_at_a_batch_yield_ends_the_stream(): void $batch = null; $valid = null; - $extractor->feed(rows(schema(int_schema('id')), row(['id' => 1]))); + $extractor->feed(array_to_rows([['id' => 1]], schema(int_schema('id')))); $fiber = new Fiber(static function () use ($extractor, $context, &$batch, &$valid): void { $generator = $extractor->extract($context); @@ -120,7 +119,7 @@ public function test_stop_signal_at_the_trailing_yield_ends_the_stream(): void $trailing = null; $valid = null; - $extractor->feed(rows(schema(int_schema('id')), row(['id' => 1]))); + $extractor->feed(array_to_rows([['id' => 1]], schema(int_schema('id')))); $fiber = new Fiber(static function () use ($extractor, $context, &$trailing, &$valid): void { $generator = $extractor->extract($context); @@ -153,7 +152,7 @@ public function test_yields_the_fed_batch_and_a_trailing_empty_rows_then_suspend $context = flow_context(config()); $collected = []; - $extractor->feed(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); + $extractor->feed(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $fiber = new Fiber(static function () use ($extractor, $context, &$collected): void { foreach ($extractor->extract($context) as $rows) { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php index 4b204a152d..ae52a5ba8c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php @@ -8,9 +8,8 @@ use Flow\ETL\Extractor\PartitionColumns; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\memory_filesystem; @@ -61,7 +60,7 @@ public function test_the_uri_joins_the_body_when_metadata_columns_are_on(): void public function test_fill_rows_returns_a_batch_with_nothing_to_add_as_it_is(): void { - $rows = rows(schema(str_schema('name')), row(['name' => 'Norbert'])); + $rows = array_to_rows([['name' => 'Norbert']], schema(str_schema('name'))); static::assertSame($rows, (new FileConstants( new PartitionColumns(memory_filesystem()), @@ -76,20 +75,19 @@ public function test_fill_rows_adds_the_constants_to_every_row_under_the_declare $declared = schema(str_schema('name'), str_schema('_input_file_uri'), int_schema('year')); static::assertEquals( - rows( - $declared, - row(['name' => 'Norbert', '_input_file_uri' => 'memory://orders/data.csv', 'year' => 2024]), - row(['name' => 'Flow', '_input_file_uri' => 'memory://orders/data.csv', 'year' => 2024]), - ), + array_to_rows([ + ['name' => 'Norbert', '_input_file_uri' => 'memory://orders/data.csv', 'year' => 2024], + ['name' => 'Flow', '_input_file_uri' => 'memory://orders/data.csv', 'year' => 2024], + ], $declared), (new FileConstants( new PartitionColumns(memory_filesystem()), 'memory://orders/data.csv', ['year' => false], ['year' => 2024], - ))->fillRows( - rows(schema(str_schema('name')), row(['name' => 'Norbert']), row(['name' => 'Flow'])), - $declared, - ), + ))->fillRows(array_to_rows([ + ['name' => 'Norbert'], + ['name' => 'Flow'], + ], schema(str_schema('name'))), $declared), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php index c22b9e0dce..921ce8c475 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php @@ -63,4 +63,16 @@ public function test_a_refusal_the_sample_does_not_explain_stays_the_gate_s_own( $sampleSize === null ? null : new SchemaInference(sampleSize: $sampleSize), ))->of([['code' => 1], ['code' => 'x']], schema(int_schema('code', true)), new PhpBackend()); } + + public function test_a_declared_schema_narrower_than_the_rows_projects_its_columns(): void + { + static::assertSame( + [['code' => 1], ['code' => 2]], + (new InferredRows('from_array()', null))->of( + [['code' => 1, 'name' => 'one'], ['code' => 2, 'name' => 'two']], + schema(int_schema('code')), + new PhpBackend(), + )->toArray(), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/MemoryExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/MemoryExtractorTest.php index c8300a73a2..c79d2a680f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/MemoryExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/MemoryExtractorTest.php @@ -13,13 +13,12 @@ use Flow\ETL\Tests\Mother\RowsMother; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_memory; use function Flow\ETL\DSL\infer_schema; 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; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_memory; @@ -33,25 +32,27 @@ public function test_declared_schema_is_used_to_hydrate_extracted_rows(): void $memory = new ArrayMemory(); to_memory($memory)->load( - rows(schema(int_schema('number'), str_schema('name')), row(['number' => 1, 'name' => 'one'])), + array_to_rows([['number' => 1, 'name' => 'one']], schema(int_schema('number'), str_schema('name'))), flow_context(config()), ); self::assertExtractedRowsEquals( - rows(schema(str_schema('number'), str_schema('name')), row(['number' => '1', 'name' => 'one'])), + array_to_rows([['number' => '1', 'name' => 'one']], schema(str_schema('number'), str_schema('name'))), from_memory($memory)->withSchema(schema(str_schema('number'), str_schema('name'))), ); } public function test_memory_extractor(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['number' => 1, 'name' => 'one'], + ['number' => 2, 'name' => 'two'], + ['number' => 3, 'name' => 'tree'], + ['number' => 4, 'name' => 'four'], + ['number' => 5, 'name' => 'five'], + ], schema(int_schema('number'), str_schema('name')), - row(['number' => 1, 'name' => 'one']), - row(['number' => 2, 'name' => 'two']), - row(['number' => 3, 'name' => 'tree']), - row(['number' => 4, 'name' => 'four']), - row(['number' => 5, 'name' => 'five']), ); $memory = new ArrayMemory(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php index 932d726021..12f77eab9c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php @@ -10,9 +10,10 @@ use Flow\Filesystem\Path\Filter\OnlyFiles; use function array_keys; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; 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; use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\path; @@ -33,7 +34,7 @@ public function test_apply_adds_a_column_the_inferred_schema_is_missing(): void static::assertEquals( schema(int_schema('id'), str_schema('date', nullable: true)), (new PartitionColumns(new MemoryFilesystem())) - ->apply(rows(schema(int_schema('id')), row(['id' => 1])), ['date' => true]) + ->apply(array_to_rows([['id' => 1]], schema(int_schema('id'))), ['date' => true]) ->schema(), ); } @@ -41,9 +42,12 @@ public function test_apply_adds_a_column_the_inferred_schema_is_missing(): void public function test_apply_keeps_the_rows_it_was_given(): void { static::assertEquals( - [row(['id' => 1, 'date' => null])], + [array_to_row(['id' => 1, 'date' => null], schema(int_schema('id'), bool_schema('date', nullable: true)))], (new PartitionColumns(new MemoryFilesystem()))->apply( - rows(schema(int_schema('id'), str_schema('date', nullable: true)), row(['id' => 1, 'date' => null])), + array_to_rows( + [['id' => 1, 'date' => null]], + schema(int_schema('id'), str_schema('date', nullable: true)), + ), ['date' => true], )->all(), ); @@ -54,9 +58,12 @@ public function test_apply_replaces_the_definition_inference_guessed(): void static::assertEquals( schema(int_schema('id'), str_schema('date', nullable: true)), (new PartitionColumns(new MemoryFilesystem())) - ->apply(rows(schema(int_schema('id'), str_schema('date')), row(['id' => 1, 'date' => '2026-01-01'])), [ - 'date' => true, - ]) + ->apply( + array_to_rows([['id' => 1, 'date' => '2026-01-01']], schema(int_schema('id'), str_schema('date'))), + [ + 'date' => true, + ], + ) ->schema(), ); } @@ -66,7 +73,7 @@ public function test_apply_takes_nullability_from_the_names_map(): void static::assertEquals( schema(str_schema('date'), str_schema('region', nullable: true)), (new PartitionColumns(new MemoryFilesystem())) - ->apply(rows(schema(str_schema('date', nullable: true)), row(['date' => '2026-01-01'])), [ + ->apply(array_to_rows([['date' => '2026-01-01']], schema(str_schema('date', nullable: true))), [ 'date' => false, 'region' => true, ]) @@ -104,9 +111,9 @@ public function test_apply_moves_a_partition_column_out_of_its_body_position(): schema(int_schema('id'), str_schema('value'), str_schema('group')), (new PartitionColumns(new MemoryFilesystem())) ->apply( - rows( + array_to_rows( + [['group' => '1', 'id' => 1, 'value' => 'a']], schema(str_schema('group'), int_schema('id'), str_schema('value')), - row(['group' => '1', 'id' => 1, 'value' => 'a']), ), ['group' => false], ) @@ -125,8 +132,10 @@ public function test_declare_leaves_a_schema_alone_when_nothing_was_discovered() public function test_apply_leaves_rows_alone_when_nothing_was_discovered(): void { static::assertEquals( - rows(schema(int_schema('id')), row(['id' => 1])), - (new PartitionColumns(new MemoryFilesystem()))->apply(rows(schema(int_schema('id')), row(['id' => 1])), []), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + (new PartitionColumns(new MemoryFilesystem()))->apply(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))), []), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/RowsExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/RowsExtractorTest.php index dad9e64077..64e3a5fef4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/RowsExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/RowsExtractorTest.php @@ -8,11 +8,10 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; 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; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -20,13 +19,15 @@ final class RowsExtractorTest extends FlowTestCase { public function test_process_extractor(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['number' => 1, 'name' => 'one'], + ['number' => 2, 'name' => 'two'], + ['number' => 3, 'name' => 'tree'], + ['number' => 4, 'name' => 'four'], + ['number' => 5, 'name' => 'five'], + ], schema(int_schema('number'), str_schema('name')), - row(['number' => 1, 'name' => 'one']), - row(['number' => 2, 'name' => 'two']), - row(['number' => 3, 'name' => 'tree']), - row(['number' => 4, 'name' => 'four']), - row(['number' => 5, 'name' => 'five']), ); $extractor = from_rows($rows); @@ -46,8 +47,8 @@ public function test_process_extractor(): void public function test_extract_yields_batches_matching_schema(): void { $extractor = from_rows( - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number'), str_schema('name')), row(['number' => 2, 'name' => 'two'])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 2, 'name' => 'two']], schema(int_schema('number'), str_schema('name'))), ); foreach ($extractor->extract(flow_context()) as $batch) { @@ -57,14 +58,14 @@ public function test_extract_yields_batches_matching_schema(): void public function test_is_repeatable(): void { - static::assertTrue(from_rows(rows(schema(int_schema('number')), row(['number' => 1])))->isRepeatable()); + static::assertTrue(from_rows(array_to_rows([['number' => 1]], schema(int_schema('number'))))->isRepeatable()); } public function test_it_declares_an_exact_row_count(): void { $extractor = from_rows( - rows(schema(int_schema('number')), row(['number' => 1]), row(['number' => 2])), - rows(schema(int_schema('number')), row(['number' => 3])), + array_to_rows([['number' => 1], ['number' => 2]], schema(int_schema('number'))), + array_to_rows([['number' => 3]], schema(int_schema('number'))), ); static::assertEquals(new Statistics(rows: Cardinality::exact(3)), $extractor->statistics()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SequenceExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SequenceExtractorTest.php index 9ae9fb4bc6..a487cb4a25 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SequenceExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SequenceExtractorTest.php @@ -15,6 +15,7 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\float_schema; @@ -23,8 +24,6 @@ use function Flow\ETL\DSL\from_sequence_date_period_recurrences; use function Flow\ETL\DSL\from_sequence_number; use function Flow\ETL\DSL\infer_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -34,7 +33,7 @@ final class SequenceExtractorTest extends FlowTestCase public function test_declared_schema_is_used_to_hydrate_extracted_rows(): void { self::assertExtractedRowsEquals( - rows(schema(str_schema('num')), row(['num' => '1']), row(['num' => '2']), row(['num' => '3'])), + array_to_rows([['num' => '1'], ['num' => '2'], ['num' => '3']], schema(str_schema('num'))), from_sequence_number('num', 1, 3)->withSchema(schema(str_schema('num'))), ); } @@ -50,18 +49,17 @@ public function test_extracting_from_date_period(): void ); self::assertExtractedRowsEquals( - rows( - schema(date_schema('day', true)), - row(['day' => new DateTimeImmutable('2023-01-02')]), - row(['day' => new DateTimeImmutable('2023-01-03')]), - row(['day' => new DateTimeImmutable('2023-01-04')]), - row(['day' => new DateTimeImmutable('2023-01-05')]), - row(['day' => new DateTimeImmutable('2023-01-06')]), - row(['day' => new DateTimeImmutable('2023-01-07')]), - row(['day' => new DateTimeImmutable('2023-01-08')]), - row(['day' => new DateTimeImmutable('2023-01-09')]), - row(['day' => new DateTimeImmutable('2023-01-10')]), - ), + array_to_rows([ + ['day' => new DateTimeImmutable('2023-01-02')], + ['day' => new DateTimeImmutable('2023-01-03')], + ['day' => new DateTimeImmutable('2023-01-04')], + ['day' => new DateTimeImmutable('2023-01-05')], + ['day' => new DateTimeImmutable('2023-01-06')], + ['day' => new DateTimeImmutable('2023-01-07')], + ['day' => new DateTimeImmutable('2023-01-08')], + ['day' => new DateTimeImmutable('2023-01-09')], + ['day' => new DateTimeImmutable('2023-01-10')], + ], schema(date_schema('day', true))), $extractor, ); } @@ -77,19 +75,18 @@ public function test_extracting_from_date_period_recurrences(): void ); self::assertExtractedRowsEquals( - rows( - schema(date_schema('day', true)), - row(['day' => new DateTimeImmutable('2023-01-02')]), - row(['day' => new DateTimeImmutable('2023-01-03')]), - row(['day' => new DateTimeImmutable('2023-01-04')]), - row(['day' => new DateTimeImmutable('2023-01-05')]), - row(['day' => new DateTimeImmutable('2023-01-06')]), - row(['day' => new DateTimeImmutable('2023-01-07')]), - row(['day' => new DateTimeImmutable('2023-01-08')]), - row(['day' => new DateTimeImmutable('2023-01-09')]), - row(['day' => new DateTimeImmutable('2023-01-10')]), - row(['day' => new DateTimeImmutable('2023-01-11')]), - ), + array_to_rows([ + ['day' => new DateTimeImmutable('2023-01-02')], + ['day' => new DateTimeImmutable('2023-01-03')], + ['day' => new DateTimeImmutable('2023-01-04')], + ['day' => new DateTimeImmutable('2023-01-05')], + ['day' => new DateTimeImmutable('2023-01-06')], + ['day' => new DateTimeImmutable('2023-01-07')], + ['day' => new DateTimeImmutable('2023-01-08')], + ['day' => new DateTimeImmutable('2023-01-09')], + ['day' => new DateTimeImmutable('2023-01-10')], + ['day' => new DateTimeImmutable('2023-01-11')], + ], schema(date_schema('day', true))), $extractor, ); } @@ -99,16 +96,15 @@ public function test_extracting_from_numbers_range(): void $extractor = from_sequence_number('num', 0, 10, 1.5); self::assertExtractedRowsEquals( - rows( - schema(float_schema('num', true)), - row(['num' => 0.0]), - row(['num' => 1.5]), - row(['num' => 3.0]), - row(['num' => 4.5]), - row(['num' => 6.0]), - row(['num' => 7.5]), - row(['num' => 9.0]), - ), + array_to_rows([ + ['num' => 0.0], + ['num' => 1.5], + ['num' => 3.0], + ['num' => 4.5], + ['num' => 6.0], + ['num' => 7.5], + ['num' => 9.0], + ], schema(float_schema('num', true))), $extractor, ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Filesystem/ScalarFunctionFilterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Filesystem/ScalarFunctionFilterTest.php index 6200d30f80..d4b6a6d869 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Filesystem/ScalarFunctionFilterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Filesystem/ScalarFunctionFilterTest.php @@ -107,4 +107,14 @@ public function test_partition_filter_with_cast_rejects_non_matching_files(): vo static::assertTrue($filter->accept(new FileStatus(path('flow-file://data/year=2024/file.csv'), true))); static::assertFalse($filter->accept(new FileStatus(path('flow-file://data/year=2025/file.csv'), true))); } + + public function test_an_undeclared_null_partition_value_reads_as_null(): void + { + $filter = new ScalarFunctionFilter(ref('year')->isNull(), schema(), flow_context(config())); + + static::assertTrue($filter->accept( + new FileStatus(path('flow-file://data/year=__HIVE_DEFAULT_PARTITION__/f.csv'), true), + )); + static::assertFalse($filter->accept(new FileStatus(path('flow-file://data/year=2024/f.csv'), true))); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCII/ASCIIBodyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCII/ASCIIBodyTest.php index 089c6382d1..89ccbea5d3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCII/ASCIIBodyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCII/ASCIIBodyTest.php @@ -10,10 +10,9 @@ use Flow\ETL\Tests\CommandOutputNormalizer; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\float_schema; 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; final class ASCIIBodyTest extends FlowTestCase @@ -22,10 +21,9 @@ final class ASCIIBodyTest extends FlowTestCase public function test_printing_ascii_body(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'value' => 1.4], ['id' => 2, 'value' => 3.4]], schema(int_schema('id'), float_schema('value')), - row(['id' => 1, 'value' => 1.4]), - row(['id' => 2, 'value' => 3.4]), ); $headers = new ASCIIBody(new Headers($rows), new Body($rows)); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCII/ASCIIHeadersTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCII/ASCIIHeadersTest.php index 6177a6e6ae..0f7355de51 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCII/ASCIIHeadersTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCII/ASCIIHeadersTest.php @@ -10,10 +10,9 @@ use Flow\ETL\Tests\CommandOutputNormalizer; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\float_schema; 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; final class ASCIIHeadersTest extends FlowTestCase @@ -22,10 +21,9 @@ final class ASCIIHeadersTest extends FlowTestCase public function test_printing_ascii_headers(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'value' => 1.4], ['id' => 2, 'value' => 3.4]], schema(int_schema('id'), float_schema('value')), - row(['id' => 1, 'value' => 1.4]), - row(['id' => 2, 'value' => 3.4]), ); $headers = new ASCIIHeaders(new Headers($rows), new Body($rows)); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCIITableTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCIITableTest.php index 76ecf94220..82a83b4598 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCIITableTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Formatter/ASCIITableTest.php @@ -8,9 +8,8 @@ use Flow\ETL\Tests\CommandOutputNormalizer; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -20,16 +19,15 @@ final class ASCIITableTest extends FlowTestCase public function test_ascii_table_with_mb_strings(): void { - $rows = rows( - schema(str_schema('row')), - row(['row' => '[498][534]/Wiele z tego,|/co niegdyś było, przepadło.']), - row(['row' => '[540][572]/A nie żyje już nikt z tych,|/którzy by o tym pamiętali.']), - row(['row' => '[572][647]WŁADCA PIERŚCIENI']), - row(['row' => '[701][741]/Wszystko zaczęło się|/od wykucia Pierścieni Władzy.']), - row(['row' => '[742][762]/Trzy zostały dane elfom...']), - row(['row' => '[763][805]/nieśmiertelnym, najmędrszym|/i najbliższym magii spośród wszystkich ras.']), - row(['row' => '[816][853]/Siedem - władcom krasnoludów,|/wspaniałym górnikom']), - ); + $rows = array_to_rows([ + ['row' => '[498][534]/Wiele z tego,|/co niegdyś było, przepadło.'], + ['row' => '[540][572]/A nie żyje już nikt z tych,|/którzy by o tym pamiętali.'], + ['row' => '[572][647]WŁADCA PIERŚCIENI'], + ['row' => '[701][741]/Wszystko zaczęło się|/od wykucia Pierścieni Władzy.'], + ['row' => '[742][762]/Trzy zostały dane elfom...'], + ['row' => '[763][805]/nieśmiertelnym, najmędrszym|/i najbliższym magii spośród wszystkich ras.'], + ['row' => '[816][853]/Siedem - władcom krasnoludów,|/wspaniałym górnikom'], + ], schema(str_schema('row'))); self::assertCommandOutputContains(<<<'TABLE' +-------------------------------------------------------------------------------------+ @@ -48,16 +46,15 @@ public function test_ascii_table_with_mb_strings(): void public function test_ascii_table_with_mb_strings_truncate(): void { - $rows = rows( - schema(str_schema('row')), - row(['row' => '[498][534]/Wiele z tego,|/co niegdyś było, przepadło.']), - row(['row' => '[540][572]/A nie żyje już nikt z tych,|/którzy by o tym pamiętali.']), - row(['row' => '[572][647]WŁADCA PIERŚCIENI']), - row(['row' => '[701][741]/Wszystko zaczęło się|/od wykucia Pierścieni Władzy.']), - row(['row' => '[742][762]/Trzy zostały dane elfom...']), - row(['row' => '[763][805]/nieśmiertelnym, najmędrszym|/i najbliższym magii spośród wszystkich ras.']), - row(['row' => '[816][853]/Siedem - władcom krasnoludów,|/wspaniałym górnikom']), - ); + $rows = array_to_rows([ + ['row' => '[498][534]/Wiele z tego,|/co niegdyś było, przepadło.'], + ['row' => '[540][572]/A nie żyje już nikt z tych,|/którzy by o tym pamiętali.'], + ['row' => '[572][647]WŁADCA PIERŚCIENI'], + ['row' => '[701][741]/Wszystko zaczęło się|/od wykucia Pierścieni Władzy.'], + ['row' => '[742][762]/Trzy zostały dane elfom...'], + ['row' => '[763][805]/nieśmiertelnym, najmędrszym|/i najbliższym magii spośród wszystkich ras.'], + ['row' => '[816][853]/Siedem - władcom krasnoludów,|/wspaniałym górnikom'], + ], schema(str_schema('row'))); self::assertCommandOutputContains(<<<'TABLE' +----------------------+ @@ -76,15 +73,17 @@ public function test_ascii_table_with_mb_strings_truncate(): void public function test_ascii_table_with_non_symmetric_entries(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['row' => '[498][534]/Wiele z tego,|/co niegdyś było, przepadło.'], + ['row' => '[540][572]/A nie żyje już nikt z tych,|/którzy by o tym pamiętali.'], + ['row' => '[572][647]WŁADCA PIERŚCIENI'], + ['row' => '[701][741]/Wszystko zaczęło się|/od wykucia Pierścieni Władzy.'], + ['row' => '[742][762]/Trzy zostały dane elfom...'], + ['row' => '[763][805]/nieśmiertelnym, najmędrszym|/i najbliższym magii spośród wszystkich ras.'], + ['test' => '[816][853]/Siedem - władcom krasnoludów,|/wspaniałym górnikom'], + ], schema(str_schema('row', nullable: true), str_schema('test', nullable: true)), - row(['row' => '[498][534]/Wiele z tego,|/co niegdyś było, przepadło.']), - row(['row' => '[540][572]/A nie żyje już nikt z tych,|/którzy by o tym pamiętali.']), - row(['row' => '[572][647]WŁADCA PIERŚCIENI']), - row(['row' => '[701][741]/Wszystko zaczęło się|/od wykucia Pierścieni Władzy.']), - row(['row' => '[742][762]/Trzy zostały dane elfom...']), - row(['row' => '[763][805]/nieśmiertelnym, najmędrszym|/i najbliższym magii spośród wszystkich ras.']), - row(['test' => '[816][853]/Siedem - władcom krasnoludów,|/wspaniałym górnikom']), ); self::assertCommandOutputContains(<<<'TABLE' @@ -111,10 +110,9 @@ public function test_ascii_table_with_single_row(): void | 1 | EN | | 2 | PL | +----+------+ - TABLE, (new ASCIITable(rows( + TABLE, (new ASCIITable(array_to_rows( + [['id' => 1, 'name' => 'EN'], ['id' => 2, 'name' => 'PL']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'EN']), - row(['id' => 2, 'name' => 'PL']), )))->print(false)); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllTest.php index 6b166b23d8..18a9496040 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllTest.php @@ -10,10 +10,12 @@ use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\all; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class AllTest extends FlowTestCase { @@ -41,31 +43,37 @@ public static function three_valued_and(): Generator #[DataProvider('three_valued_and')] public function test_three_valued_truth_table(?bool $left, ?bool $right, ?bool $expected): void { - static::assertSame($expected, (new All(lit($left), lit($right)))->eval(row([]), flow_context())); + static::assertSame($expected, (new All(lit($left), lit($right)))->eval( + array_to_row([], schema()), + flow_context(), + )); } public function test_all_expression_on_is_null_expression(): void { - static::assertTrue(all(ref('value')->isNull())->eval(row(['value' => null]), flow_context())); + static::assertTrue( + all(ref('value')->isNull()) + ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), + ); } public function test_all_expression_on_multiple_boolean_values(): void { - static::assertTrue(all(lit(true), lit(true), lit(true))->eval(row([]), flow_context())); + static::assertTrue(all(lit(true), lit(true), lit(true))->eval(array_to_row([], schema()), flow_context())); } public function test_all_expression_on_multiple_random_boolean_values(): void { - static::assertFalse(all(lit(true), lit(false), lit(true))->eval(row([]), flow_context())); + static::assertFalse(all(lit(true), lit(false), lit(true))->eval(array_to_row([], schema()), flow_context())); } public function test_all_function_on_boolean_false_value(): void { - static::assertFalse(all(lit(false))->eval(row([]), flow_context())); + static::assertFalse(all(lit(false))->eval(array_to_row([], schema()), flow_context())); } public function test_all_function_on_boolean_true_value(): void { - static::assertTrue(all(lit(true))->eval(row([]), flow_context())); + static::assertTrue(all(lit(true))->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AnyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AnyTest.php index 9075da0381..534be7e28b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AnyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AnyTest.php @@ -10,10 +10,12 @@ use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\any; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class AnyTest extends FlowTestCase { @@ -41,26 +43,32 @@ public static function three_valued_or(): Generator #[DataProvider('three_valued_or')] public function test_three_valued_truth_table(?bool $left, ?bool $right, ?bool $expected): void { - static::assertSame($expected, (new Any(lit($left), lit($right)))->eval(row([]), flow_context())); + static::assertSame($expected, (new Any(lit($left), lit($right)))->eval( + array_to_row([], schema()), + flow_context(), + )); } public function test_any_expression_on_boolean_false_value(): void { - static::assertFalse(any(lit(false))->eval(row([]), flow_context())); + static::assertFalse(any(lit(false))->eval(array_to_row([], schema()), flow_context())); } public function test_any_expression_on_boolean_true_value(): void { - static::assertTrue(any(lit(true))->eval(row([]), flow_context())); + static::assertTrue(any(lit(true))->eval(array_to_row([], schema()), flow_context())); } public function test_any_expression_on_is_null_expression(): void { - static::assertTrue(any(ref('value')->isNull())->eval(row(['value' => null]), flow_context())); + static::assertTrue( + any(ref('value')->isNull()) + ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), + ); } public function test_any_expression_on_multiple_boolean_values(): void { - static::assertTrue(any(lit(false), lit(true), lit(false))->eval(row([]), flow_context())); + static::assertTrue(any(lit(false), lit(true), lit(false))->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AppendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AppendTest.php index bb48210e92..0459709f97 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AppendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AppendTest.php @@ -7,37 +7,53 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class AppendTest extends FlowTestCase { public function test_append_empty_string_to_content(): void { - $result = ref('str')->append('')->eval(row(['str' => 'hello']), flow_context()); + $result = ref('str') + ->append('') + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); static::assertEquals('hello', $result); } public function test_append_to_empty_string(): void { - $result = ref('str')->append('hello')->eval(row(['str' => '']), flow_context()); + $result = ref('str') + ->append('hello') + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); static::assertEquals('hello', $result); } public function test_append_to_non_empty_string(): void { - $result = ref('str')->append(' world')->eval(row(['str' => 'hello']), flow_context()); + $result = ref('str') + ->append(' world') + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); static::assertEquals('hello world', $result); } public function test_append_with_null_suffix(): void { - $result = ref('str')->append(ref('suffix'))->eval(row(['str' => 'hello', 'suffix' => null]), flow_context()); + $result = ref('str') + ->append(ref('suffix')) + ->eval( + array_to_row( + ['str' => 'hello', 'suffix' => null], + schema(str_schema('str'), str_schema('suffix', nullable: true)), + ), + flow_context(), + ); static::assertEquals('hello', $result); } @@ -47,7 +63,9 @@ public function test_append_with_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Append function requires non-null value'); - $result = ref('str')->append(' world')->eval(row(['str' => null]), flow_context()); + $result = ref('str') + ->append(' world') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); static::assertNull($result); } @@ -58,14 +76,19 @@ public function test_append_with_null_value_in_strict_mode(): void $this->expectExceptionMessage('Append function requires non-null value'); $context = flow_context(config()); - ref('str')->append(' world')->eval(row(['str' => null]), $context); + ref('str') + ->append(' world') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), $context); } public function test_append_with_scalar_function_parameter(): void { $result = ref('str') ->append(ref('suffix')) - ->eval(row(['str' => 'hello', 'suffix' => ' world']), flow_context()); + ->eval( + array_to_row(['str' => 'hello', 'suffix' => ' world'], schema(str_schema('str'), str_schema('suffix'))), + flow_context(), + ); static::assertEquals('hello world', $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayExpandTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayExpandTest.php index d0856661d1..ed000a591e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayExpandTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayExpandTest.php @@ -12,13 +12,15 @@ use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\DSL\array_expand; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_integer; @@ -31,7 +33,11 @@ final class ArrayExpandTest extends FlowTestCase { public function test_expand_both(): void { - $row = row(['array' => ['a' => 1, 'b' => 2, 'c' => 3]]); + $row = array_to_row(['array' => [ + 'a' => 1, + 'b' => 2, + 'c' => 3, + ]], schema(map_schema('array', type_map(type_string(), type_integer())))); static::assertSame( [ @@ -45,14 +51,22 @@ public function test_expand_both(): void public function test_expand_keys(): void { - $row = row(['array' => ['a' => 1, 'b' => 2, 'c' => 3]]); + $row = array_to_row(['array' => [ + 'a' => 1, + 'b' => 2, + 'c' => 3, + ]], schema(map_schema('array', type_map(type_string(), type_integer())))); static::assertSame(['a', 'b', 'c'], array_expand(ref('array'), ArrayExpand::KEYS)->eval($row, flow_context())); } public function test_expand_values(): void { - $row = row(['array' => ['a' => 1, 'b' => 2, 'c' => 3]]); + $row = array_to_row(['array' => [ + 'a' => 1, + 'b' => 2, + 'c' => 3, + ]], schema(map_schema('array', type_map(type_string(), type_integer())))); static::assertSame(['a' => 1, 'b' => 2, 'c' => 3], array_expand(ref('array'))->eval($row, flow_context())); } @@ -62,7 +76,8 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - array_expand(ref('integer_entry'))->eval(row(['integer_entry' => 1]), flow_context()); + array_expand(ref('integer_entry')) + ->eval(array_to_row(['integer_entry' => 1], schema(int_schema('integer_entry'))), flow_context()); } public function test_for_not_array_entry_in_strict_mode(): void @@ -71,7 +86,8 @@ public function test_for_not_array_entry_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - array_expand(ref('integer_entry'))->eval(row(['integer_entry' => 1]), $context); + array_expand(ref('integer_entry')) + ->eval(array_to_row(['integer_entry' => 1], schema(int_schema('integer_entry'))), $context); } public function test_values_over_a_structure_declare_the_unified_field_type(): void @@ -177,6 +193,11 @@ public function test_values_over_a_structure_with_non_unifying_fields_refuse_to_ #[TestWith([ArrayExpand::BOTH])] public function test_a_null_array_expands_to_nothing(ArrayExpand $expand): void { - static::assertSame([], array_expand(ref('list'), $expand)->eval(row(['list' => null]), flow_context())); + static::assertSame( + [], + array_expand(ref('list'), $expand)->eval(array_to_row([ + 'list' => null, + ], schema(str_schema('list', nullable: true))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayFilterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayFilterTest.php index 1a9afe3324..e8f317660d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayFilterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayFilterTest.php @@ -7,24 +7,46 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; final class ArrayFilterTest extends FlowTestCase { public function test_array_filter(): void { - static::assertSame([1], ref('list')->arrayFilter(lit(2))->eval(row(['list' => [1, 2]]), flow_context())); + static::assertSame( + [1], + ref('list') + ->arrayFilter(lit(2)) + ->eval(array_to_row(['list' => [ + 1, + 2, + ]], schema(list_schema('list', type_list(type_integer())))), flow_context()), + ); } public function test_array_filter_by_entry_reference(): void { static::assertSame( [1], - ref('list')->arrayFilter(ref('int'))->eval(row(['list' => [1, 2], 'int' => 2]), flow_context()), + ref('list') + ->arrayFilter(ref('int')) + ->eval( + array_to_row( + ['list' => [1, 2], 'int' => 2], + schema(list_schema('list', type_list(type_integer())), int_schema('int')), + ), + flow_context(), + ), ); } @@ -34,12 +56,20 @@ public function test_array_filter_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('map')->arrayFilter(lit(1))->eval(row(['map' => 'test']), $context); + ref('map')->arrayFilter(lit(1))->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), $context); } public function test_array_filter_not_existing_value(): void { - static::assertSame([1, 2], ref('list')->arrayFilter(lit(5))->eval(row(['list' => [1, 2]]), flow_context())); + static::assertSame( + [1, 2], + ref('list') + ->arrayFilter(lit(5)) + ->eval(array_to_row(['list' => [ + 1, + 2, + ]], schema(list_schema('list', type_list(type_integer())))), flow_context()), + ); } public function test_array_filter_on_non_array(): void @@ -47,6 +77,8 @@ public function test_array_filter_on_non_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('map')->arrayFilter(lit(1))->eval(row(['map' => 'test']), flow_context()); + ref('map') + ->arrayFilter(lit(1)) + ->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetCollectionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetCollectionTest.php index 42aa8ddd64..d2b9640c4a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetCollectionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetCollectionTest.php @@ -6,16 +6,28 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\RowsMother; use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\DSL\array_get_collection; use function Flow\ETL\DSL\array_get_collection_first; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\structure_get_collection; use function Flow\ETL\DSL\structure_get_collection_first; +use function Flow\Types\DSL\type_boolean; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; final class ArrayGetCollectionTest extends FlowTestCase { @@ -25,7 +37,7 @@ public function test_array_get_collection_in_strict_mode(): void $this->expectExceptionMessage('ArrayGetCollection function failed to evaluate parameters'); $context = flow_context(config()); - $row = row(['invalid_entry' => 1]); + $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); array_get_collection(ref('invalid_entry'), ['id'])->eval($row, $context); } @@ -35,7 +47,7 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGetCollection function failed to evaluate parameters.'); - $row = row(['invalid_entry' => 1]); + $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); array_get_collection(ref('invalid_entry'), ['id'])->eval($row, flow_context()); } @@ -45,21 +57,14 @@ public function test_getting_keys_from_simple_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGetCollection function failed to evaluate parameters.'); - $row = row([ - 'array_entry' => [ - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - ]); + $row = RowsMother::arrayEntry(); array_get_collection(ref('array_entry'), ['id'])->eval($row, flow_context()); } public function test_getting_specific_keys_from_collection_of_array(): void { - $row = row([ + $row = array_to_row([ 'array_entry' => [ [ 'id' => 1, @@ -74,7 +79,12 @@ public function test_getting_specific_keys_from_collection_of_array(): void 'array' => ['foo' => 'bar'], ], ], - ]); + ], schema(list_schema('array_entry', type_list(type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ]))))); static::assertEquals( [ @@ -87,7 +97,7 @@ public function test_getting_specific_keys_from_collection_of_array(): void public function test_getting_specific_keys_from_first_element_in_collection_of_array(): void { - $row = row([ + $row = array_to_row([ 'array_entry' => [ [ 'parent_id' => 1, @@ -104,7 +114,13 @@ public function test_getting_specific_keys_from_first_element_in_collection_of_a 'array' => ['foo' => 'bar'], ], ], - ]); + ], schema(list_schema('array_entry', type_list(type_structure([ + 'parent_id' => type_integer(), + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ]))))); static::assertEquals( [ @@ -116,7 +132,7 @@ public function test_getting_specific_keys_from_first_element_in_collection_of_a public function test_getting_specific_keys_from_first_element_in_collection_of_array_when_first_index_does_not_exists(): void { - $row = row([ + $row = array_to_row([ 'array_entry' => [ 2 => [ 'parent_id' => 1, @@ -133,7 +149,13 @@ public function test_getting_specific_keys_from_first_element_in_collection_of_a 'array' => ['foo' => 'bar'], ], ], - ]); + ], schema(map_schema('array_entry', type_map(type_integer(), type_structure([ + 'parent_id' => type_integer(), + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ]))))); static::assertEquals( [ @@ -153,9 +175,9 @@ public function test_getting_specific_keys_from_first_element_in_collection_of_a #[TestWith([['a.b'], [['a' => ['b' => 1]]], [['a.b' => null]]])] public function test_keys_are_literal_keys(array $keys, array $collection, array $expected): void { - static::assertSame($expected, array_get_collection(ref('array_entry'), $keys)->eval(row([ + static::assertSame($expected, array_get_collection(ref('array_entry'), $keys)->eval(array_to_row([ 'array_entry' => $collection, - ]), flow_context())); + ], schema(json_schema('array_entry'))), flow_context())); } public function test_a_non_scalar_key_fails(): void @@ -163,16 +185,18 @@ public function test_a_non_scalar_key_fails(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGetCollection function failed to evaluate parameters.'); - array_get_collection(ref('array_entry'), [['x']])->eval(row(['array_entry' => [['x' => 1]]]), flow_context()); + array_get_collection(ref('array_entry'), [[ + 'x', + ]])->eval(array_to_row(['array_entry' => [['x' => 1]]], schema(list_schema('array_entry', type_list(type_structure(['x' => type_integer()]))))), flow_context()); } public function test_an_empty_element_reads_null_keys(): void { static::assertSame( [['id' => null], ['id' => null]], - array_get_collection(ref('array_entry'), ['id'])->eval(row([ + array_get_collection(ref('array_entry'), ['id'])->eval(array_to_row([ 'array_entry' => [['name' => 'a'], []], - ]), flow_context()), + ], schema(json_schema('array_entry'))), flow_context()), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetTest.php index 7435e91ca3..e3fda29a01 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetTest.php @@ -12,19 +12,23 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\RowsMother; use Flow\Types\Type\Logical\StructureType; use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\array_exists; use function Flow\ETL\DSL\array_get; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\structure_get; use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\structure_element; +use function Flow\Types\DSL\type_boolean; +use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_mixed; @@ -108,8 +112,12 @@ public function test_array_access_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGet function failed to get value from array.'); - array_get(ref('integer_entry'), 'invalid_path')->eval(row(['integer_entry' => 1]), flow_context()); - array_exists(ref('integer_entry'), 'invalid_path')->eval(row(['integer_entry' => 1]), flow_context()); + array_get(ref('integer_entry'), 'invalid_path')->eval(array_to_row([ + 'integer_entry' => 1, + ], schema(int_schema('integer_entry'))), flow_context()); + array_exists(ref('integer_entry'), 'invalid_path')->eval(array_to_row([ + 'integer_entry' => 1, + ], schema(int_schema('integer_entry'))), flow_context()); } public function test_array_access_for_not_array_entry_strict_mode(): void @@ -118,26 +126,21 @@ public function test_array_access_for_not_array_entry_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGet function failed to get value from array'); - array_get(ref('integer_entry'), 'invalid_path')->eval(row(['integer_entry' => 1]), $context); + array_get(ref('integer_entry'), 'invalid_path')->eval(array_to_row([ + 'integer_entry' => 1, + ], schema(int_schema('integer_entry'))), $context); } public function test_array_accessor_transformer(): void { - $row = row([ - 'array_entry' => [ - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - ]); + $row = RowsMother::arrayEntry(); static::assertEquals('bar', array_get(ref('array_entry'), 'array.foo')->eval($row, flow_context())); static::assertTrue(array_exists(ref('array_entry'), 'array.foo')->eval($row, flow_context())); } public function test_array_accessor_transformer_with_invalid_and_without_strict_path(): void { - $row = row([ + $row = array_to_row([ 'array_entry' => [ 'id' => 1, 'status' => 'PENDING', @@ -145,7 +148,13 @@ public function test_array_accessor_transformer_with_invalid_and_without_strict_ 'datetime' => new DateTimeImmutable('2020-01-01 00:00:00 UTC'), 'array' => ['foo' => 'bar'], ], - ]); + ], schema(structure_schema('array_entry', type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'datetime' => type_datetime(), + 'array' => type_structure(['foo' => type_string()]), + ])))); static::assertNull(array_get(ref('array_entry'), '?invalid_path')->eval($row, flow_context())); static::assertTrue(array_exists(ref('array_entry'), '?invalid_path')->eval($row, flow_context())); static::assertFalse(array_exists(ref('array_entry'), 'invalid_path')->eval($row, flow_context())); @@ -156,7 +165,7 @@ public function test_array_accessor_transformer_with_invalid_but_strict_path(): $this->expectException(InvalidPathException::class); $this->expectExceptionMessage('Path "invalid_path" does not exists in array '); - array_get(ref('array_entry'), 'invalid_path')->eval(row([ + array_get(ref('array_entry'), 'invalid_path')->eval(array_to_row([ 'array_entry' => [ 'id' => 1, 'status' => 'PENDING', @@ -164,7 +173,13 @@ public function test_array_accessor_transformer_with_invalid_but_strict_path(): 'datetime' => new DateTimeImmutable('2020-01-01 00:00:00 UTC'), 'array' => ['foo' => 'bar'], ], - ]), flow_context()); + ], schema(structure_schema('array_entry', type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'datetime' => type_datetime(), + 'array' => type_structure(['foo' => type_string()]), + ])))), flow_context()); } public function test_returns_rejects_a_non_structure_input(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeepTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeepTest.php index 50dce04302..60efbb1b77 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeepTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeepTest.php @@ -7,24 +7,46 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; final class ArrayKeepTest extends FlowTestCase { public function test_array_keep(): void { - static::assertSame([1 => 2], ref('list')->arrayKeep(lit(2))->eval(row(['list' => [1, 2]]), flow_context())); + static::assertSame( + [1 => 2], + ref('list') + ->arrayKeep(lit(2)) + ->eval(array_to_row(['list' => [ + 1, + 2, + ]], schema(list_schema('list', type_list(type_integer())))), flow_context()), + ); } public function test_array_keep_by_entry_reference(): void { static::assertSame( [1 => 2], - ref('list')->arrayKeep(ref('int'))->eval(row(['list' => [1, 2], 'int' => 2]), flow_context()), + ref('list') + ->arrayKeep(ref('int')) + ->eval( + array_to_row( + ['list' => [1, 2], 'int' => 2], + schema(list_schema('list', type_list(type_integer())), int_schema('int')), + ), + flow_context(), + ), ); } @@ -34,12 +56,20 @@ public function test_array_keep_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('map')->arrayKeep(lit(1))->eval(row(['map' => 'test']), $context); + ref('map')->arrayKeep(lit(1))->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), $context); } public function test_array_keep_not_existing_value(): void { - static::assertSame([], ref('list')->arrayKeep(lit(5))->eval(row(['list' => [1, 2]]), flow_context())); + static::assertSame( + [], + ref('list') + ->arrayKeep(lit(5)) + ->eval(array_to_row(['list' => [ + 1, + 2, + ]], schema(list_schema('list', type_list(type_integer())))), flow_context()), + ); } public function test_array_keep_on_non_array(): void @@ -47,6 +77,6 @@ public function test_array_keep_on_non_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('map')->arrayKeep(lit(1))->eval(row(['map' => 'test']), flow_context()); + ref('map')->arrayKeep(lit(1))->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeyRenameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeyRenameTest.php index b746fba6e3..de09dc376b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeyRenameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeyRenameTest.php @@ -7,12 +7,18 @@ use Flow\ArrayDot\Exception\InvalidPathException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\RowsMother; use function Flow\ETL\DSL\array_key_rename; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; final class ArrayKeyRenameTest extends FlowTestCase { @@ -22,7 +28,7 @@ public function test_array_key_rename_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - $row = row(['integer_entry' => 1]); + $row = array_to_row(['integer_entry' => 1], schema(int_schema('integer_entry'))); array_key_rename(ref('integer_entry'), 'invalid_path', 'new_name')->eval($row, $context); } @@ -32,26 +38,35 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - $row = row(['integer_entry' => 1]); + $row = array_to_row(['integer_entry' => 1], schema(int_schema('integer_entry'))); array_key_rename(ref('integer_entry'), 'invalid_path', 'new_name')->eval($row, flow_context()); } public function test_renames_array_entry_keys_in_multiple_array_entry(): void { - $row = row([ - 'customer' => [ - 'first' => 'John', - 'last' => 'Snow', - ], - 'shipping' => [ - 'address' => [ - 'line' => '3644 Clement Street', - 'city' => 'Atalanta', + $row = array_to_row( + [ + 'customer' => [ + 'first' => 'John', + 'last' => 'Snow', + ], + 'shipping' => [ + 'address' => [ + 'line' => '3644 Clement Street', + 'city' => 'Atalanta', + ], + 'estimated_delivery_date' => '2023-04-01T10:00:00+00:00', ], - 'estimated_delivery_date' => '2023-04-01T10:00:00+00:00', ], - ]); + schema( + structure_schema('customer', type_structure(['first' => type_string(), 'last' => type_string()])), + structure_schema('shipping', type_structure([ + 'address' => type_structure(['line' => type_string(), 'city' => type_string()]), + 'estimated_delivery_date' => type_string(), + ])), + ), + ); static::assertEquals( [ @@ -75,14 +90,7 @@ public function test_renames_array_entry_keys_in_multiple_array_entry(): void public function test_renames_array_entry_keys_in_single_array_entry(): void { - $row = row([ - 'array_entry' => [ - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - ]); + $row = RowsMother::arrayEntry(); static::assertEquals( [ @@ -97,14 +105,7 @@ public function test_renames_array_entry_keys_in_single_array_entry(): void public function test_throws_exception_for_invalid_path(): void { - $row = row([ - 'array_entry' => [ - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - ]); + $row = RowsMother::arrayEntry(); $this->expectException(InvalidPathException::class); $this->expectExceptionMessage('Path "invalid_path" does not exists in array '); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysStyleConverterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysStyleConverterTest.php index 90061098df..087b95404e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysStyleConverterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysStyleConverterTest.php @@ -11,12 +11,16 @@ use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_keys_style_convert; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\structure_schema; +use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; @@ -27,7 +31,7 @@ public function test_for_invalid_style(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Unrecognized style invalid, please use one of following:'); - $row = row(['invalid_entry' => []]); + $row = array_to_row(['invalid_entry' => []], schema(json_schema('invalid_entry'))); array_keys_style_convert(ref('invalid_entry'), 'invalid')->eval($row, flow_context()); } @@ -37,14 +41,14 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - $row = row(['invalid_entry' => 1]); + $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); array_keys_style_convert(ref('invalid_entry'), 'snake')->eval($row, flow_context()); } public function test_transforms_case_style_for_all_keys_in_array_entry(): void { - $row = row([ + $row = array_to_row([ 'arrayEntry' => [ 'itemId' => 1, 'itemStatus' => 'PENDING', @@ -63,7 +67,18 @@ public function test_transforms_case_style_for_all_keys_in_array_entry(): void 'variantName' => 'Variant Name', ], ], - ]); + ], schema(structure_schema('arrayEntry', type_structure([ + 'itemId' => type_integer(), + 'itemStatus' => type_string(), + 'itemEnabled' => type_boolean(), + 'itemVariants' => type_structure([ + 'variantStatuses' => type_list(type_structure([ + 'statusId' => type_integer(), + 'statusName' => type_string(), + ])), + 'variantName' => type_string(), + ]), + ])))); static::assertEquals( [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysTest.php index 34732fc2ad..1cee206571 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysTest.php @@ -10,16 +10,19 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; @@ -62,7 +65,12 @@ public function test_array_keys(): void { static::assertSame( ['a', 'b'], - ref('map')->arrayKeys()->eval(row(['map' => ['a' => 1, 'b' => 2]]), flow_context()), + ref('map') + ->arrayKeys() + ->eval(array_to_row(['map' => [ + 'a' => 1, + 'b' => 2, + ]], schema(map_schema('map', type_map(type_string(), type_integer())))), flow_context()), ); } @@ -72,7 +80,7 @@ public function test_array_keys_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('map')->arrayKeys()->eval(row(['map' => 'test']), $context); + ref('map')->arrayKeys()->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), $context); } public function test_array_keys_on_non_array(): void @@ -80,6 +88,6 @@ public function test_array_keys_on_non_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('map')->arrayKeys()->eval(row(['map' => 'test']), flow_context()); + ref('map')->arrayKeys()->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeCollectionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeCollectionTest.php index 446937d0cc..2587afa983 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeCollectionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeCollectionTest.php @@ -9,11 +9,13 @@ use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_merge_collection; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_integer; @@ -29,7 +31,7 @@ public function test_array_merge_collection_in_strict_mode_with_non_array(): voi $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - $row = row(['invalid_entry' => 1]); + $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); array_merge_collection(ref('invalid_entry'))->eval($row, $context); } @@ -40,12 +42,12 @@ public function test_array_merge_collection_in_strict_mode_with_non_array_elemen $this->expectExceptionMessage('ArrayMergeCollection function requires array elements to be arrays'); $context = flow_context(config()); - $row = row([ + $row = array_to_row([ 'array_entry' => [ ['foo' => 'bar'], 1, ], - ]); + ], schema(json_schema('array_entry'))); array_merge_collection(ref('array_entry'))->eval($row, $context); } @@ -55,12 +57,12 @@ public function test_attempt_of_merging_collection_where_not_every_element_is_ar $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayMergeCollection function requires array elements to be arrays'); - $row = row([ + $row = array_to_row([ 'array_entry' => [ ['foo' => 'bar'], 1, ], - ]); + ], schema(json_schema('array_entry'))); array_merge_collection(ref('array_entry'))->eval($row, flow_context()); } @@ -70,14 +72,14 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - $row = row(['invalid_entry' => 1]); + $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); array_merge_collection(ref('invalid_entry'))->eval($row, flow_context()); } public function test_merging_collection_of_arrays(): void { - $row = row([ + $row = array_to_row([ 'array_entry' => [ [ 1, @@ -87,7 +89,7 @@ public function test_merging_collection_of_arrays(): void ], [], ], - ]); + ], schema(list_schema('array_entry', type_list(type_list(type_integer()))))); static::assertEquals([1, 2], array_merge_collection(ref('array_entry'))->eval($row, flow_context())); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeTest.php index ea8c656b17..8940ac05c3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeTest.php @@ -8,11 +8,17 @@ use Flow\ETL\Function\ArrayMerge; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; final class ArrayMergeTest extends FlowTestCase { @@ -22,14 +28,33 @@ public function test_array_merge_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - ref('a')->arrayMerge(ref('b'))->eval(row(['a' => 1, 'b' => ['b' => 2]]), $context); + ref('a') + ->arrayMerge(ref('b')) + ->eval( + array_to_row( + ['a' => 1, 'b' => ['b' => 2]], + schema(int_schema('a'), map_schema('b', type_map(type_string(), type_integer()))), + ), + $context, + ); } public function test_array_merge_two_array_row_entries(): void { static::assertSame( ['a' => 1, 'b' => 2], - ref('a')->arrayMerge(ref('b'))->eval(row(['a' => ['a' => 1], 'b' => ['b' => 2]]), flow_context()), + ref('a') + ->arrayMerge(ref('b')) + ->eval( + array_to_row( + ['a' => ['a' => 1], 'b' => ['b' => 2]], + schema( + map_schema('a', type_map(type_string(), type_integer())), + map_schema('b', type_map(type_string(), type_integer())), + ), + ), + flow_context(), + ), ); } @@ -37,7 +62,7 @@ public function test_array_merge_two_lit_functions(): void { $function = new ArrayMerge(lit(['a' => 1]), lit(['b' => 2])); - static::assertSame(['a' => 1, 'b' => 2], $function->eval(row([]), flow_context())); + static::assertSame(['a' => 1, 'b' => 2], $function->eval(array_to_row([], schema()), flow_context())); } public function test_array_merge_when_left_side_is_not_an_array(): void @@ -45,7 +70,15 @@ public function test_array_merge_when_left_side_is_not_an_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - ref('a')->arrayMerge(ref('b'))->eval(row(['a' => 1, 'b' => ['b' => 2]]), flow_context()); + ref('a') + ->arrayMerge(ref('b')) + ->eval( + array_to_row( + ['a' => 1, 'b' => ['b' => 2]], + schema(int_schema('a'), map_schema('b', type_map(type_string(), type_integer()))), + ), + flow_context(), + ); } public function test_array_merge_when_right_side_is_not_an_array(): void @@ -53,6 +86,14 @@ public function test_array_merge_when_right_side_is_not_an_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - ref('a')->arrayMerge(ref('b'))->eval(row(['a' => ['a' => 1], 'b' => 2]), flow_context()); + ref('a') + ->arrayMerge(ref('b')) + ->eval( + array_to_row( + ['a' => ['a' => 1], 'b' => 2], + schema(map_schema('a', type_map(type_string(), type_integer())), int_schema('b')), + ), + flow_context(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayReverseTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayReverseTest.php index 58bb9cd3a4..0dcbf1f38c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayReverseTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayReverseTest.php @@ -8,14 +8,17 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; @@ -23,7 +26,17 @@ final class ArrayReverseTest extends FlowTestCase { public function test_array_reverse_array_entry(): void { - static::assertSame([5, 3, 10, 4], ref('a')->arrayReverse()->eval(row(['a' => [4, 10, 3, 5]]), flow_context())); + static::assertSame( + [5, 3, 10, 4], + ref('a') + ->arrayReverse() + ->eval(array_to_row(['a' => [ + 4, + 10, + 3, + 5, + ]], schema(list_schema('a', type_list(type_integer())))), flow_context()), + ); } public function test_array_reverse_in_strict_mode(): void @@ -32,7 +45,7 @@ public function test_array_reverse_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - ref('a')->arrayReverse()->eval(row(['a' => 123]), $context); + ref('a')->arrayReverse()->eval(array_to_row(['a' => 123], schema(int_schema('a'))), $context); } public function test_array_reverse_non_array_entry(): void @@ -40,7 +53,7 @@ public function test_array_reverse_non_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - ref('a')->arrayReverse()->eval(row(['a' => 123]), flow_context()); + ref('a')->arrayReverse()->eval(array_to_row(['a' => 123], schema(int_schema('a'))), flow_context()); } public function test_a_structure_operand_declares_reversed_fields(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArraySortTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArraySortTest.php index 624c2c2d47..2d2b0f9c58 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArraySortTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArraySortTest.php @@ -9,11 +9,13 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_array; @@ -29,7 +31,7 @@ public function test_array_sort_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('array')->arraySort()->eval(row(['array' => 'string']), $context); + ref('array')->arraySort()->eval(array_to_row(['array' => 'string'], schema(str_schema('array'))), $context); } public function test_sorting_big_arrays(): void @@ -37,20 +39,20 @@ public function test_sorting_big_arrays(): void static::assertSame( ref('array') ->arraySort() - ->eval(row(['array' => type_array()->assert(json_decode( + ->eval(array_to_row(['array' => type_array()->assert(json_decode( $this->jsonDifferentOrder(), true, 512, JSON_THROW_ON_ERROR, - ))]), flow_context()), + ))], schema(json_schema('array'))), flow_context()), ref('array') ->arraySort() - ->eval(row(['array' => type_array()->assert(json_decode( + ->eval(array_to_row(['array' => type_array()->assert(json_decode( $this->json(), true, 512, JSON_THROW_ON_ERROR, - ))]), flow_context()), + ))], schema(json_schema('array'))), flow_context()), ); } @@ -68,7 +70,7 @@ public function test_sorting_nested_array_using_asort_algo(): void ], ref('array') ->arraySort(Sort::asort) - ->eval(row([ + ->eval(array_to_row([ 'array' => [ 'a' => [ 'b' => [ @@ -78,7 +80,7 @@ public function test_sorting_nested_array_using_asort_algo(): void 'g' => 'h', ], ], - ]), flow_context()), + ], schema(json_schema('array'))), flow_context()), ); } @@ -96,7 +98,7 @@ public function test_sorting_nested_associative_array(): void ], ref('array') ->arraySort(Sort::ksort) - ->eval(row([ + ->eval(array_to_row([ 'array' => [ 'a' => [ 'g' => 'h', @@ -106,7 +108,7 @@ public function test_sorting_nested_associative_array(): void ], ], ], - ]), flow_context()), + ], schema(json_schema('array'))), flow_context()), ); } @@ -115,7 +117,9 @@ public function test_sorting_non_array_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('array')->arraySort()->eval(row(['array' => 'string']), flow_context()); + ref('array') + ->arraySort() + ->eval(array_to_row(['array' => 'string'], schema(str_schema('array'))), flow_context()); } private function json(): string diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayUnpackTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayUnpackTest.php index 5d45c9d16b..44910e4583 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayUnpackTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayUnpackTest.php @@ -8,14 +8,16 @@ use Flow\ETL\Function\ArrayUnpack; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_json; @@ -33,14 +35,27 @@ public function test_array_unpack(): void 'enabled' => true, 'array' => ['foo' => 'bar'], ], - (new ArrayUnpack(ref('array_entry'), schema(str_schema('status'), bool_schema('enabled'))))->eval(row([ - 'id' => 1, - 'array_entry' => [ - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - ]), flow_context()), + (new ArrayUnpack(ref('array_entry'), schema(str_schema('status'), bool_schema('enabled'))))->eval( + array_to_row( + [ + 'id' => 1, + 'array_entry' => [ + 'status' => 'PENDING', + 'enabled' => true, + 'array' => ['foo' => 'bar'], + ], + ], + schema( + int_schema('id'), + structure_schema('array_entry', type_structure([ + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ])), + ), + ), + flow_context(), + ), ); } @@ -49,10 +64,16 @@ public function test_array_unpack_with_null_in_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('array_unpack() requires a non-null array'); - (new ArrayUnpack(ref('array_entry'), schema(str_schema('status'))))->eval(row([ - 'id' => 1, - 'array_entry' => null, - ]), flow_context(config())); + (new ArrayUnpack(ref('array_entry'), schema(str_schema('status'))))->eval( + array_to_row( + [ + 'id' => 1, + 'array_entry' => null, + ], + schema(int_schema('id'), str_schema('array_entry', nullable: true)), + ), + flow_context(config()), + ); } public function test_it_refuses_an_empty_schema(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayValuesTest.php index 14fc364ea1..8386a40915 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayValuesTest.php @@ -9,15 +9,19 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; final class ArrayValuesTest extends FlowTestCase @@ -26,7 +30,12 @@ public function test_array_values(): void { static::assertSame( [1, 2], - ref('map')->arrayValues()->eval(row(['map' => ['a' => 1, 'b' => 2]]), flow_context()), + ref('map') + ->arrayValues() + ->eval(array_to_row(['map' => [ + 'a' => 1, + 'b' => 2, + ]], schema(map_schema('map', type_map(type_string(), type_integer())))), flow_context()), ); } @@ -36,7 +45,7 @@ public function test_array_values_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('map')->arrayValues()->eval(row(['map' => 'test']), $context); + ref('map')->arrayValues()->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), $context); } public function test_array_values_on_non_array(): void @@ -44,7 +53,7 @@ public function test_array_values_on_non_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('map')->arrayValues()->eval(row(['map' => 'test']), flow_context()); + ref('map')->arrayValues()->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), flow_context()); } public function test_a_structure_operand_declares_the_unified_field_type(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AsciiTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AsciiTest.php index 47dc3345e7..221087a214 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AsciiTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AsciiTest.php @@ -7,15 +7,19 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class AsciiTest extends FlowTestCase { public function test_ascii(): void { - static::assertSame('azcz', ref('str')->ascii()->eval(row(['str' => 'ąźćż']), flow_context())); + static::assertSame('azcz', ref('str') + ->ascii() + ->eval(array_to_row(['str' => 'ąźćż'], schema(str_schema('str'))), flow_context())); } public function test_ascii_on_null(): void @@ -23,6 +27,8 @@ public function test_ascii_on_null(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Ascii function requires non-null value'); - ref('str')->ascii()->eval(row(['str' => null]), flow_context()); + ref('str') + ->ascii() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AverageTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AverageTest.php index 31f1d300c4..2ce16fb56a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AverageTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AverageTest.php @@ -8,14 +8,15 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\window; final class AverageTest extends FlowTestCase @@ -29,11 +30,13 @@ public function test_aggregation_average_from_numeric_values(): void { $aggregator = average(ref('int')); - $aggregator->aggregate(row(['int' => '10']), flow_context()); - $aggregator->aggregate(row(['int' => '20']), flow_context()); - $aggregator->aggregate(row(['int' => '30']), flow_context()); - $aggregator->aggregate(row(['int' => '25']), flow_context()); - $aggregator->aggregate(row(['not_int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '30'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'not_int' => null, + ], schema(str_schema('not_int', nullable: true))), flow_context()); static::assertSame(21.25, $aggregator->value()); } @@ -42,10 +45,12 @@ public function test_aggregation_average_including_null_value(): void { $aggregator = average(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'int' => null, + ], schema(int_schema('int', nullable: true))), flow_context()); static::assertSame(20.0, $aggregator->value()); } @@ -54,10 +59,10 @@ public function test_aggregation_average_with_float_result(): void { $aggregator = average(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => 25]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); static::assertSame(21.25, $aggregator->value()); } @@ -66,10 +71,10 @@ public function test_aggregation_average_with_integer_result(): void { $aggregator = average(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => 40]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 40], schema(int_schema('int'))), flow_context()); static::assertSame(25.0, $aggregator->value()); } @@ -85,11 +90,11 @@ public function test_window_function_average_on_partitioned_rows(): void { $rows = rows( schema(int_schema('id'), int_schema('value')), - $row1 = row(['id' => 1, 'value' => 1]), - row(['id' => 2, 'value' => 100]), - row(['id' => 3, 'value' => 25]), - row(['id' => 4, 'value' => 64]), - row(['id' => 5, 'value' => 23]), + $row1 = array_to_row(['id' => 1, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 2, 'value' => 100], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 3, 'value' => 25], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 4, 'value' => 64], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 5, 'value' => 23], schema(int_schema('id'), int_schema('value'))), ); $avg = average(ref('value'))->over(window()->orderBy(ref('value'))); @@ -102,7 +107,11 @@ public function test_window_function_average_with_missing_reference_in_strict_mo $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Average window function error:'); - $rows = rows(schema(int_schema('id')), $row1 = row(['id' => 1]), row(['id' => 2])); + $rows = rows( + schema(int_schema('id')), + $row1 = array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + ); $avg = average(ref('missing_column'))->over(window()->orderBy(ref('id'))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BetweenTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BetweenTest.php index 6fc53681a4..2ee76fd186 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BetweenTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BetweenTest.php @@ -8,70 +8,84 @@ use Flow\ETL\Function\Between\Boundary; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\between; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class BetweenTest extends FlowTestCase { public function test_a_definite_false_short_circuits_past_a_null(): void { - static::assertFalse(ref('value')->between(lit(10), lit(null))->eval(row(['value' => 5]), flow_context())); + static::assertFalse( + ref('value') + ->between(lit(10), lit(null)) + ->eval(array_to_row(['value' => 5], schema(int_schema('value'))), flow_context()), + ); } public function test_a_null_bound_that_could_change_the_answer_is_null(): void { - static::assertNull(ref('value')->between(lit(10), lit(null))->eval(row(['value' => 50]), flow_context())); + static::assertNull( + ref('value') + ->between(lit(10), lit(null)) + ->eval(array_to_row(['value' => 50], schema(int_schema('value'))), flow_context()), + ); } public function test_between_exclusive(): void { - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(row([ + static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(array_to_row([ 'value' => 11, - ]), flow_context())); - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(row([ + ], schema(int_schema('value'))), flow_context())); + static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(array_to_row([ 'value' => 49, - ]), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(row([ + ], schema(int_schema('value'))), flow_context())); + static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(array_to_row([ 'value' => 10, - ]), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(row([ + ], schema(int_schema('value'))), flow_context())); + static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(array_to_row([ 'value' => 50, - ]), flow_context())); + ], schema(int_schema('value'))), flow_context())); } public function test_between_inclusive(): void { - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(row([ + static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(array_to_row([ 'value' => 10, - ]), flow_context())); - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(row([ + ], schema(int_schema('value'))), flow_context())); + static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(array_to_row([ 'value' => 50, - ]), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(row([ + ], schema(int_schema('value'))), flow_context())); + static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(array_to_row([ 'value' => 9, - ]), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(row([ + ], schema(int_schema('value'))), flow_context())); + static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(array_to_row([ 'value' => 51, - ]), flow_context())); + ], schema(int_schema('value'))), flow_context())); } public function test_between_left_inclusive(): void { - static::assertTrue(between(ref('value'), lit(10), lit(50))->eval(row(['value' => 10]), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50))->eval(row(['value' => 9]), flow_context())); + static::assertTrue(between(ref('value'), lit(10), lit(50))->eval(array_to_row([ + 'value' => 10, + ], schema(int_schema('value'))), flow_context())); + static::assertFalse(between(ref('value'), lit(10), lit(50))->eval(array_to_row([ + 'value' => 9, + ], schema(int_schema('value'))), flow_context())); } public function test_between_right_inclusive(): void { - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::RIGHT_INCLUSIVE)->eval(row([ + static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::RIGHT_INCLUSIVE)->eval(array_to_row([ 'value' => 50, - ]), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::RIGHT_INCLUSIVE)->eval(row([ + ], schema(int_schema('value'))), flow_context())); + static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::RIGHT_INCLUSIVE)->eval(array_to_row([ 'value' => 51, - ]), flow_context())); + ], schema(int_schema('value'))), flow_context())); } public function test_between_with_invalid_boundary_in_strict_mode(): void @@ -80,6 +94,8 @@ public function test_between_with_invalid_boundary_in_strict_mode(): void $this->expectExceptionMessage('Expected type "object", got "string".'); $context = flow_context(); - between(ref('value'), lit(10), lit(50), lit('invalid'))->eval(row(['value' => 20]), $context); + between(ref('value'), lit(10), lit(50), lit('invalid'))->eval(array_to_row([ + 'value' => 20, + ], schema(int_schema('value'))), $context); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryComparisonsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryComparisonsTest.php index d0eaa9db2d..4454781cd5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryComparisonsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryComparisonsTest.php @@ -24,24 +24,34 @@ use Flow\ETL\Function\StartsWith; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_datetime; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_string; final class BinaryComparisonsTest extends FlowTestCase { public function test_equals(): void { - $row = row([ - 'a' => 100, - 'b' => 100, - 'c' => 10, - 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), - 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), - ]); + $row = array_to_row( + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + ], + schema(int_schema('a'), int_schema('b'), int_schema('c'), datetime_schema('d'), datetime_schema('e')), + ); static::assertTrue((new Equals(ref('a'), ref('b')))->eval($row, flow_context())); static::assertTrue((new Equals(ref('d'), ref('e')))->eval($row, flow_context())); @@ -50,14 +60,24 @@ public function test_equals(): void public function test_greater_than(): void { - $row = row([ - 'a' => 100, - 'b' => 100, - 'c' => 10, - 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), - 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), - 'f' => null, - ]); + $row = array_to_row( + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + ); static::assertTrue((new GreaterThan(ref('a'), ref('c')))->eval($row, flow_context())); static::assertNull((new GreaterThan(ref('a'), ref('f')))->eval($row, flow_context())); @@ -83,26 +103,35 @@ public function test_greater_than(): void public function test_greater_than_equal_with_null_in_strict_mode(): void { $context = flow_context(); - $row = row(['a' => 100, 'f' => null]); + $row = array_to_row(['a' => 100, 'f' => null], schema(int_schema('a'), str_schema('f', nullable: true))); static::assertNull((new GreaterThanEqual(ref('a'), ref('f')))->eval($row, $context)); } public function test_greater_than_with_null_in_strict_mode(): void { $context = flow_context(); - $row = row(['a' => 100, 'f' => null]); + $row = array_to_row(['a' => 100, 'f' => null], schema(int_schema('a'), str_schema('f', nullable: true))); static::assertNull((new GreaterThan(ref('a'), ref('f')))->eval($row, $context)); } public function test_is_in(): void { - $row = row([ - 'a' => [1, 2, 3, 4, 5], - 'b' => ['a', 'b', 'c'], - 'c' => 'another', - 'd' => 4, - 'e' => 'b', - ]); + $row = array_to_row( + [ + 'a' => [1, 2, 3, 4, 5], + 'b' => ['a', 'b', 'c'], + 'c' => 'another', + 'd' => 4, + 'e' => 'b', + ], + schema( + list_schema('a', type_list(type_integer())), + list_schema('b', type_list(type_string())), + str_schema('c'), + int_schema('d'), + str_schema('e'), + ), + ); static::assertTrue((new IsIn(ref('a'), lit(1)))->eval($row, flow_context())); static::assertFalse((new IsIn(ref('a'), lit(10)))->eval($row, flow_context())); @@ -113,13 +142,13 @@ public function test_is_in(): void public function test_is_in_with_null_array_in_strict_mode(): void { $context = flow_context(); - $row = row(['a' => null, 'd' => 1]); + $row = array_to_row(['a' => null, 'd' => 1], schema(str_schema('a', nullable: true), int_schema('d'))); static::assertNull((new IsIn(ref('a'), ref('d')))->eval($row, $context)); } public function test_is_numeric(): void { - $row = row(['a' => 100, 'b' => null]); + $row = array_to_row(['a' => 100, 'b' => null], schema(int_schema('a'), str_schema('b', nullable: true))); static::assertTrue((new IsNumeric(ref('a')))->eval($row, flow_context())); static::assertNull((new IsNumeric(ref('b')))->eval($row, flow_context())); static::assertFalse((new IsNotNumeric(ref('a')))->eval($row, flow_context())); @@ -130,7 +159,7 @@ public function test_is_numeric(): void public function test_is_type(): void { - $row = row(['a' => 100, 'b' => null]); + $row = array_to_row(['a' => 100, 'b' => null], schema(int_schema('a'), str_schema('b', nullable: true))); static::assertTrue((new IsType(ref('a'), 'integer', 'string'))->eval($row, flow_context())); static::assertFalse((new IsType(ref('a'), type_string()))->eval($row, flow_context())); @@ -140,14 +169,17 @@ public function test_is_type_with_non_existing_type_class(): void { $this->expectExceptionMessage('Unknown type \'aaa\''); - $row = row(['a' => 100, 'b' => null]); + $row = array_to_row(['a' => 100, 'b' => null], schema(int_schema('a'), str_schema('b', nullable: true))); static::assertFalse((new IsType(ref('a'), 'aaa'))->eval($row, flow_context())); } public function test_less_than(): void { - $row = row(['a' => 100, 'b' => 100, 'c' => 10, 'd' => null]); + $row = array_to_row( + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + ); static::assertFalse((new LessThan(ref('a'), ref('c')))->eval($row, flow_context())); static::assertNull((new LessThan(ref('a'), ref('d')))->eval($row, flow_context())); @@ -164,20 +196,23 @@ public function test_less_than(): void public function test_less_than_equal_with_null_in_strict_mode(): void { $context = flow_context(); - $row = row(['a' => 100, 'd' => null]); + $row = array_to_row(['a' => 100, 'd' => null], schema(int_schema('a'), str_schema('d', nullable: true))); static::assertNull((new LessThanEqual(ref('a'), ref('d')))->eval($row, $context)); } public function test_less_than_with_null_in_strict_mode(): void { $context = flow_context(); - $row = row(['a' => 100, 'd' => null]); + $row = array_to_row(['a' => 100, 'd' => null], schema(int_schema('a'), str_schema('d', nullable: true))); static::assertNull((new LessThan(ref('a'), ref('d')))->eval($row, $context)); } public function test_not_equals(): void { - $row = row(['a' => 100, 'b' => 100, 'c' => 10]); + $row = array_to_row( + ['a' => 100, 'b' => 100, 'c' => 10], + schema(int_schema('a'), int_schema('b'), int_schema('c')), + ); static::assertFalse((new NotEquals(ref('a'), ref('b')))->eval($row, flow_context())); static::assertTrue((new NotEquals(ref('a'), ref('c')))->eval($row, flow_context())); @@ -185,7 +220,10 @@ public function test_not_equals(): void public function test_not_same(): void { - $row = row(['a' => 100, 'b' => 100, 'c' => 10]); + $row = array_to_row( + ['a' => 100, 'b' => 100, 'c' => 10], + schema(int_schema('a'), int_schema('b'), int_schema('c')), + ); static::assertTrue((new NotSame(ref('a'), ref('c')))->eval($row, flow_context())); static::assertFalse((new NotSame(ref('a'), ref('b')))->eval($row, flow_context())); @@ -193,7 +231,7 @@ public function test_not_same(): void public function test_null(): void { - $row = row(['a' => 100, 'b' => null]); + $row = array_to_row(['a' => 100, 'b' => null], schema(int_schema('a'), str_schema('b', nullable: true))); static::assertFalse((new IsNull(ref('a')))->eval($row, flow_context())); static::assertTrue((new IsNull(ref('b')))->eval($row, flow_context())); @@ -205,13 +243,16 @@ public function test_null(): void public function test_same(): void { - $row = row([ - 'a' => 100, - 'b' => 100, - 'c' => 10, - 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), - 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), - ]); + $row = array_to_row( + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + ], + schema(int_schema('a'), int_schema('b'), int_schema('c'), datetime_schema('d'), datetime_schema('e')), + ); static::assertTrue((new Same(ref('a'), ref('b')))->eval($row, flow_context())); static::assertFalse((new Same(ref('d'), ref('e')))->eval($row, flow_context())); @@ -220,12 +261,15 @@ public function test_same(): void public function test_starts_ends_with(): void { - $row = row([ - 'a' => 'some not too long string', - 'b' => 'another not too long text', - 'c' => 'another', - 'd' => 'text', - ]); + $row = array_to_row( + [ + 'a' => 'some not too long string', + 'b' => 'another not too long text', + 'c' => 'another', + 'd' => 'text', + ], + schema(str_schema('a'), str_schema('b'), str_schema('c'), str_schema('d')), + ); static::assertTrue((new StartsWith(ref('a'), lit('some not')))->eval($row, flow_context())); static::assertTrue((new EndsWith(ref('a'), lit('long string')))->eval($row, flow_context())); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryLengthTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryLengthTest.php index 4ee9b58dd8..f6f20133d4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryLengthTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryLengthTest.php @@ -7,27 +7,35 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class BinaryLengthTest extends FlowTestCase { public function test_binary_length_ascii_string(): void { - static::assertSame(5, ref('str')->binaryLength()->eval(row(['str' => 'hello']), flow_context())); + static::assertSame(5, ref('str') + ->binaryLength() + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_binary_length_binary_data(): void { $binaryData = "\x00\x01\x02\x03\xFF"; - static::assertSame(5, ref('str')->binaryLength()->eval(row(['str' => $binaryData]), flow_context())); + static::assertSame(5, ref('str') + ->binaryLength() + ->eval(array_to_row(['str' => $binaryData], schema(str_schema('str'))), flow_context())); } public function test_binary_length_empty_string(): void { - static::assertSame(0, ref('str')->binaryLength()->eval(row(['str' => '']), flow_context())); + static::assertSame(0, ref('str') + ->binaryLength() + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); } public function test_binary_length_throws_on_null_input(): void @@ -35,11 +43,15 @@ public function test_binary_length_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('BinaryLength function requires non-null value'); - ref('str')->binaryLength()->eval(row(['str' => null]), flow_context()); + ref('str') + ->binaryLength() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_binary_length_string_with_newlines_and_tabs(): void { - static::assertSame(12, ref('str')->binaryLength()->eval(row(['str' => "hello\nworld\t"]), flow_context())); + static::assertSame(12, ref('str') + ->binaryLength() + ->eval(array_to_row(['str' => "hello\nworld\t"], schema(str_schema('str'))), flow_context())); } } 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 16f5711bc1..8984971496 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 @@ -10,13 +10,14 @@ use Flow\ETL\Tests\Unit\Function\Fixtures\CallUserFunc\StaticCalculator; use Flow\ETL\Transformer\ScalarFunctionTransformer; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\call; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\row_number; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_integer; @@ -38,13 +39,16 @@ public function test_named_parameters_survive_a_rebuild(): void ]); $rebuilt = $function->withChildren($function->children()); - static::assertEquals($function->eval(row([]), flow_context()), $rebuilt->eval(row([]), flow_context())); - static::assertEquals(['1', '2', '3'], $rebuilt->eval(row([]), flow_context())); + static::assertEquals( + $function->eval(array_to_row([], schema()), flow_context()), + $rebuilt->eval(array_to_row([], schema()), flow_context()), + ); + static::assertEquals(['1', '2', '3'], $rebuilt->eval(array_to_row([], schema()), flow_context())); } public function test_call_user_func_as_dsl(): void { - static::assertIsInt(call(lit('time'), type_integer())->eval(row([]), flow_context())); + static::assertIsInt(call(lit('time'), type_integer())->eval(array_to_row([], schema()), flow_context())); } public function test_a_non_scalar_function_cannot_replace_the_callable_child(): void @@ -61,19 +65,23 @@ public function test_call_user_func_with_array_callable(): void { static::assertSame(3, ref('list') ->call(lit([new StaticCalculator(), 'count']), type_integer()) - ->eval(row(['list' => [1, 2, 3]]), flow_context())); + ->eval(array_to_row(['list' => [ + 1, + 2, + 3, + ]], schema(list_schema('list', type_list(type_integer())))), flow_context())); } public function test_call_user_func_with_native_function(): void { - $row = row(['list' => [1, 2, 3]]); + $row = array_to_row(['list' => [1, 2, 3]], schema(list_schema('list', type_list(type_integer())))); static::assertSame(3, ref('list')->call(lit('count'), type_integer())->eval($row, flow_context())); } public function test_call_user_func_with_ref_alias_and_optional_arguments(): void { - $row = row(['item_ids' => '1,2,3']); + $row = array_to_row(['item_ids' => '1,2,3'], schema(str_schema('item_ids'))); static::assertEquals( ['1', '2', '3'], @@ -85,7 +93,7 @@ public function test_call_user_func_with_ref_alias_and_optional_arguments(): voi public function test_call_user_func_with_ref_alias_and_optional_arguments_and_return_type(): void { - $row = row(['item_ids' => '1,2,3']); + $row = array_to_row(['item_ids' => '1,2,3'], schema(str_schema('item_ids'))); static::assertEquals( [1, 2, 3], @@ -97,7 +105,7 @@ public function test_call_user_func_with_ref_alias_and_optional_arguments_and_re public function test_call_user_func_with_static_method(): void { - $row = row(['list' => [1, 2, 3]]); + $row = array_to_row(['list' => [1, 2, 3]], schema(list_schema('list', type_list(type_integer())))); static::assertSame(3, ref('list') ->call(lit(StaticCalculator::class . '::count'), type_integer()) @@ -116,7 +124,7 @@ public function test_a_null_return_lands_in_a_nullable_column(): void $result = (new ScalarFunctionTransformer( 'out', new CallUserFunc(lit([StaticCalculator::class, 'alwaysNull']), type_string(), []), - ))->transform(rows(schema(str_schema('name')), row(['name' => 'a'])), flow_context()); + ))->transform(array_to_rows([['name' => 'a']], schema(str_schema('name'))), flow_context()); static::assertTrue($result->schema()->get('out')->isNullable()); static::assertNull($result->first()->get('out')); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CapitalizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CapitalizeTest.php index 7acc24a0c1..e21bf2f2aa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CapitalizeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CapitalizeTest.php @@ -6,9 +6,11 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class CapitalizeTest extends FlowTestCase { @@ -16,6 +18,6 @@ public function test_capitalize_valid_string(): void { static::assertSame('This Is A Value', ref('string') ->capitalize() - ->eval(row(['string' => 'this is a value']), flow_context())); + ->eval(array_to_row(['string' => 'this is a value'], schema(str_schema('string'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php index 077987dff8..70570ea667 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php @@ -8,6 +8,7 @@ use DateTimeZone; use DOMDocument; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Schema\Definition; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Type; use Flow\Types\Value\Json; @@ -15,10 +16,18 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\cast; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\uuid_schema; +use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; @@ -34,14 +43,16 @@ public function test_cast_of_a_null_value_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function requires non-null value'); - cast(ref('value'), 'int')->eval(row(['value' => null]), flow_context()); + cast(ref('value'), 'int')->eval(array_to_row([ + 'value' => null, + ], schema(str_schema('value', nullable: true))), flow_context()); } public function test_cast_of_a_null_value_to_an_optional_target_is_null(): void { - static::assertNull(cast(ref('value'), type_optional(type_integer()))->eval(row([ + static::assertNull(cast(ref('value'), type_optional(type_integer()))->eval(array_to_row([ 'value' => null, - ]), flow_context())); + ], schema(str_schema('value', nullable: true))), flow_context())); } public function test_casting_an_unconvertible_value_to_an_optional_target_throws(): void @@ -49,7 +60,9 @@ public function test_casting_an_unconvertible_value_to_an_optional_target_throws $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "string" into "datetime" type'); - cast(ref('value'), type_optional(type_datetime()))->eval(row(['value' => 'abc']), flow_context()); + cast(ref('value'), type_optional(type_datetime()))->eval(array_to_row([ + 'value' => 'abc', + ], schema(str_schema('value'))), flow_context()); } public function test_constructor_rejects_a_non_representable_target(): void @@ -62,8 +75,12 @@ public function test_constructor_rejects_a_non_representable_target(): void public function test_double_and_real_resolve_to_float(): void { - static::assertSame(1.0, cast(ref('value'), 'double')->eval(row(['value' => '1']), flow_context())); - static::assertSame(1.0, cast(ref('value'), 'real')->eval(row(['value' => '1']), flow_context())); + static::assertSame(1.0, cast(ref('value'), 'double')->eval(array_to_row([ + 'value' => '1', + ], schema(str_schema('value'))), flow_context())); + static::assertSame(1.0, cast(ref('value'), 'real')->eval(array_to_row([ + 'value' => '1', + ], schema(str_schema('value'))), flow_context())); } public function test_constructor_rejects_json_pretty(): void @@ -113,53 +130,71 @@ public static function cast_provider(): array XML; return [ - 'int' => ['1', 'int', 1], - 'integer' => ['1', 'integer', 1], - 'float' => ['1', 'float', 1.0], - 'double' => ['1', 'double', 1.0], - 'real' => ['1', 'real', 1.0], - 'string' => [1, 'string', '1'], - 'bool' => ['1', 'bool', true], - 'boolean' => ['1', 'boolean', true], - 'json' => [[1], 'json', new Json('[1]')], + 'int' => ['1', str_schema('value'), 'int', 1], + 'integer' => ['1', str_schema('value'), 'integer', 1], + 'float' => ['1', str_schema('value'), 'float', 1.0], + 'double' => ['1', str_schema('value'), 'double', 1.0], + 'real' => ['1', str_schema('value'), 'real', 1.0], + 'string' => [1, int_schema('value'), 'string', '1'], + 'bool' => ['1', str_schema('value'), 'bool', true], + 'boolean' => ['1', str_schema('value'), 'boolean', true], + 'json' => [[1], list_schema('value', type_list(type_integer())), 'json', new Json('[1]')], 'xml_to_array' => [ $xml, + xml_schema('value'), 'array', ['root' => ['foo' => ['@attributes' => ['baz' => 'buz'], '@value' => 'bar']]], ], - 'string_to_xml' => [$xmlString, 'xml', $xml], - 'xml_to_string' => [$xml, 'string', 'bar'], - 'full_xml_to_string' => [$fullXMLString, 'string', $fullXMLString], - 'datetime' => [new DateTimeImmutable('2023-01-01 00:00:00 UTC'), 'string', '2023-01-01T00:00:00+00:00'], + 'string_to_xml' => [$xmlString, str_schema('value'), 'xml', $xml], + 'xml_to_string' => [$xml, xml_schema('value'), 'string', 'bar'], + 'full_xml_to_string' => [$fullXMLString, str_schema('value'), 'string', $fullXMLString], + 'datetime' => [ + new DateTimeImmutable('2023-01-01 00:00:00 UTC'), + datetime_schema('value'), + 'string', + '2023-01-01T00:00:00+00:00', + ], 'datetime_to_date' => [ new DateTimeImmutable('2023-01-01 00:01:00 UTC'), + datetime_schema('value'), 'date', new DateTimeImmutable('2023-01-01T00:00:00+00:00'), ], - 'string_to_timezone' => ['UTC', 'timezone', new DateTimeZone('UTC')], - 'string_to_timezone_america' => ['America/New_York', 'timezone', new DateTimeZone('America/New_York')], - // row() infers a UTC datetime column, so the value reads back under the column zone + 'string_to_timezone' => ['UTC', str_schema('value'), 'timezone', new DateTimeZone('UTC')], + 'string_to_timezone_america' => [ + 'America/New_York', + str_schema('value'), + 'timezone', + new DateTimeZone('America/New_York'), + ], + // a UTC datetime column, so the value reads back under the column zone 'datetime_to_timezone' => [ new DateTimeImmutable('2023-01-01 00:00:00', new DateTimeZone('Europe/London')), + datetime_schema('value'), 'timezone', new DateTimeZone('UTC'), ], 'uuid' => [ Uuid::fromString('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'), + uuid_schema('value'), 'string', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11', ], - 'bool_to_string' => [true, 'string', 'true'], + 'bool_to_string' => [true, bool_schema('value'), 'string', 'true'], ]; } + /** + * @param Definition $definition + */ #[DataProvider('cast_provider')] - public function test_cast(mixed $from, string $to, mixed $expected): void + public function test_cast(mixed $from, Definition $definition, string $to, mixed $expected): void { + $row = array_to_row(['value' => $from], schema($definition)); // @mago-ignore analysis:mixed-assignment - $resultRefCast = ref('value')->cast($to)->eval(row(['value' => $from]), flow_context()); + $resultRefCast = ref('value')->cast($to)->eval($row, flow_context()); // @mago-ignore analysis:mixed-assignment - $resultCastRef = cast(ref('value'), $to)->eval(row(['value' => $from]), flow_context()); + $resultCastRef = cast(ref('value'), $to)->eval($row, flow_context()); if (is_object($expected) || is_object($from)) { static::assertEquals($expected, $resultRefCast); @@ -177,7 +212,7 @@ public function test_casting_a_scalar_to_array_names_the_remedy(): void 'Cast function failed: Can\'t cast "string" into "array" type: wrap the value first, e.g. type_list(type_string())', ); - ref('value')->cast('array')->eval(row(['value' => '1']), flow_context()); + ref('value')->cast('array')->eval(array_to_row(['value' => '1'], schema(str_schema('value'))), flow_context()); } public function test_casting_integer_to_timezone(): void @@ -185,7 +220,9 @@ public function test_casting_integer_to_timezone(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "int" into "timezone" type'); - ref('value')->cast('timezone')->eval(row(['value' => 123]), flow_context()); + ref('value') + ->cast('timezone') + ->eval(array_to_row(['value' => 123], schema(int_schema('value'))), flow_context()); } public function test_casting_integer_to_xml(): void @@ -193,7 +230,7 @@ public function test_casting_integer_to_xml(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "int" into "xml" type'); - ref('value')->cast('xml')->eval(row(['value' => 1]), flow_context()); + ref('value')->cast('xml')->eval(array_to_row(['value' => 1], schema(int_schema('value'))), flow_context()); } public function test_casting_invalid_string_to_timezone(): void @@ -201,7 +238,9 @@ public function test_casting_invalid_string_to_timezone(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "string" into "timezone" type'); - ref('value')->cast('timezone')->eval(row(['value' => 'invalid-timezone']), flow_context()); + ref('value') + ->cast('timezone') + ->eval(array_to_row(['value' => 'invalid-timezone'], schema(str_schema('value'))), flow_context()); } public function test_casting_non_xml_string_to_xml(): void @@ -209,6 +248,6 @@ public function test_casting_non_xml_string_to_xml(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "string" into "xml" type'); - ref('value')->cast('xml')->eval(row(['value' => 'foo']), flow_context()); + ref('value')->cast('xml')->eval(array_to_row(['value' => 'foo'], schema(str_schema('value'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ChunkTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ChunkTest.php index ab3bb5790f..36c530c7a4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ChunkTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ChunkTest.php @@ -7,25 +7,37 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class ChunkTest extends FlowTestCase { public function test_chunk_empty_string(): void { - static::assertSame([], ref('str')->chunk(3)->eval(row(['str' => '']), flow_context())); + static::assertSame( + [], + ref('str')->chunk(3)->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()), + ); } public function test_chunk_equal_to_string_length(): void { - static::assertSame(['hello'], ref('str')->chunk(5)->eval(row(['str' => 'hello']), flow_context())); + static::assertSame( + ['hello'], + ref('str')->chunk(5)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), + ); } public function test_chunk_larger_than_string_length(): void { - static::assertSame(['hello'], ref('str')->chunk(10)->eval(row(['str' => 'hello']), flow_context())); + static::assertSame( + ['hello'], + ref('str')->chunk(10)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), + ); } public function test_chunk_negative_size(): void @@ -33,7 +45,7 @@ public function test_chunk_negative_size(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Chunk function requires non-null, positive size'); - ref('str')->chunk(-1)->eval(row(['str' => 'hello']), flow_context()); + ref('str')->chunk(-1)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); } public function test_chunk_null_input(): void @@ -41,12 +53,17 @@ public function test_chunk_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Chunk function requires non-null value'); - ref('str')->chunk(3)->eval(row(['str' => null]), flow_context()); + ref('str') + ->chunk(3) + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_chunk_string_basic_functionality(): void { - static::assertSame(['hel', 'lo '], ref('str')->chunk(3)->eval(row(['str' => 'hello ']), flow_context())); + static::assertSame( + ['hel', 'lo '], + ref('str')->chunk(3)->eval(array_to_row(['str' => 'hello '], schema(str_schema('str'))), flow_context()), + ); } public function test_chunk_with_null_size(): void @@ -54,14 +71,27 @@ public function test_chunk_with_null_size(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Chunk function requires non-null, positive size'); - ref('str')->chunk(ref('size'))->eval(row(['str' => 'hello', 'size' => null]), flow_context()); + ref('str') + ->chunk(ref('size')) + ->eval( + array_to_row( + ['str' => 'hello', 'size' => null], + schema(str_schema('str'), str_schema('size', nullable: true)), + ), + flow_context(), + ); } public function test_chunk_with_scalar_function_size(): void { static::assertSame( ['he', 'll', 'o'], - ref('str')->chunk(ref('size'))->eval(row(['str' => 'hello', 'size' => 2]), flow_context()), + ref('str') + ->chunk(ref('size')) + ->eval( + array_to_row(['str' => 'hello', 'size' => 2], schema(str_schema('str'), int_schema('size'))), + flow_context(), + ), ); } @@ -70,6 +100,6 @@ public function test_chunk_zero_size(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Chunk function requires non-null, positive size'); - ref('str')->chunk(0)->eval(row(['str' => 'hello']), flow_context()); + ref('str')->chunk(0)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CoalesceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CoalesceTest.php index 9f6198fe5b..97701a6ea4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CoalesceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CoalesceTest.php @@ -9,11 +9,12 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\coalesce; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -32,31 +33,49 @@ public function test_a_non_nullable_branch_makes_the_result_not_nullable(): void public function test_coalesce_entries(): void { - static::assertSame(1, coalesce(ref('name'), ref('id'), lit('N/A'))->eval(row([ - 'name' => null, - 'id' => 1, - ]), flow_context())); + static::assertSame(1, coalesce(ref('name'), ref('id'), lit('N/A'))->eval( + array_to_row( + [ + 'name' => null, + 'id' => 1, + ], + schema(str_schema('name', nullable: true), int_schema('id')), + ), + flow_context(), + )); } public function test_coalesce_on_null_entries_falls_through_to_lit(): void { - static::assertSame('N/A', coalesce(ref('name'), ref('string'), lit('N/A'))->eval(row([ - 'name' => null, - 'string' => null, - ]), flow_context())); + static::assertSame('N/A', coalesce(ref('name'), ref('string'), lit('N/A'))->eval( + array_to_row( + [ + 'name' => null, + 'string' => null, + ], + schema(str_schema('name', nullable: true), str_schema('string', nullable: true)), + ), + flow_context(), + )); } public function test_coalesce_on_ref(): void { static::assertSame(1, ref('name') ->coalesce(ref('id'), lit('N/A')) - ->eval(row(['name' => null, 'id' => 1]), flow_context())); + ->eval( + array_to_row(['name' => null, 'id' => 1], schema(str_schema('name', nullable: true), int_schema('id'))), + flow_context(), + )); } public function test_a_throwing_branch_is_not_swallowed(): void { $this->expectException(InvalidArgumentException::class); - coalesce(ref('a')->upper(), ref('b')->upper())->eval(row(['a' => 1, 'b' => 2]), flow_context()); + coalesce(ref('a')->upper(), ref('b')->upper())->eval( + array_to_row(['a' => 1, 'b' => 2], schema(int_schema('a'), int_schema('b'))), + flow_context(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CodePointLengthTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CodePointLengthTest.php index 290321d443..3e153abf45 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CodePointLengthTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CodePointLengthTest.php @@ -7,20 +7,26 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class CodePointLengthTest extends FlowTestCase { public function test_code_point_length_ascii_string(): void { - static::assertSame(5, ref('str')->codePointLength()->eval(row(['str' => 'hello']), flow_context())); + static::assertSame(5, ref('str') + ->codePointLength() + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_code_point_length_empty_string(): void { - static::assertSame(0, ref('str')->codePointLength()->eval(row(['str' => '']), flow_context())); + static::assertSame(0, ref('str') + ->codePointLength() + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); } public function test_code_point_length_throws_on_null_input(): void @@ -28,6 +34,8 @@ public function test_code_point_length_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('CodePointLength function requires non-null value'); - ref('str')->codePointLength()->eval(row(['str' => null]), flow_context()); + ref('str') + ->codePointLength() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollapseWhitespaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollapseWhitespaceTest.php index 6a46f796c3..40e75fc2ae 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollapseWhitespaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollapseWhitespaceTest.php @@ -7,43 +7,55 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class CollapseWhitespaceTest extends FlowTestCase { public function test_empty_string(): void { - $result = ref('str')->collapseWhitespace()->eval(row(['str' => '']), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); static::assertEquals('', $result); } public function test_leading_and_trailing_whitespace(): void { - $result = ref('str')->collapseWhitespace()->eval(row(['str' => ' Hello world ']), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => ' Hello world '], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello world', $result); } public function test_leading_whitespace(): void { - $result = ref('str')->collapseWhitespace()->eval(row(['str' => ' Hello world']), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => ' Hello world'], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello world', $result); } public function test_mixed_whitespace_types(): void { - $result = ref('str')->collapseWhitespace()->eval(row(['str' => "Hello\t\tworld\n\ntest"]), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => "Hello\t\tworld\n\ntest"], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello world test', $result); } public function test_multiple_spaces_between_words(): void { - $result = ref('str')->collapseWhitespace()->eval(row(['str' => 'Hello world test']), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => 'Hello world test'], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello world test', $result); } @@ -53,28 +65,36 @@ public function test_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('CollapseWhitespace function requires non-null value'); - $result = ref('str')->collapseWhitespace()->eval(row(['str' => null]), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); static::assertNull($result); } public function test_single_spaces(): void { - $result = ref('str')->collapseWhitespace()->eval(row(['str' => 'Hello world test']), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => 'Hello world test'], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello world test', $result); } public function test_single_word(): void { - $result = ref('str')->collapseWhitespace()->eval(row(['str' => 'Hello']), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => 'Hello'], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello', $result); } public function test_trailing_whitespace(): void { - $result = ref('str')->collapseWhitespace()->eval(row(['str' => 'Hello world ']), flow_context()); + $result = ref('str') + ->collapseWhitespace() + ->eval(array_to_row(['str' => 'Hello world '], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello world', $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectTest.php index 77516fe010..133f8b4e01 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectTest.php @@ -7,12 +7,13 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\collect; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class CollectTest extends FlowTestCase { @@ -25,10 +26,10 @@ public function test_aggregation_collect_entry_values(): void { $aggregator = collect(ref('data')); - $aggregator->aggregate(row(['data' => 'a']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'c']), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); static::assertSame( [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectUniqueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectUniqueTest.php index 9132bdd1f9..189e2873bc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectUniqueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectUniqueTest.php @@ -6,10 +6,12 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\collect_unique; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class CollectUniqueTest extends FlowTestCase { @@ -22,10 +24,10 @@ public function test_aggregation_collect_unique_values(): void { $aggregator = collect_unique(ref('data')); - $aggregator->aggregate(row(['data' => 'a']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'c']), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); static::assertSame( [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CombineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CombineTest.php index 5362ead779..37d750464a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CombineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CombineTest.php @@ -10,12 +10,12 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\combine; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_list; @@ -41,13 +41,13 @@ public function test_array_combine(): void { static::assertSame( ['a' => 1, 'b' => 2, 'c' => 3], - combine(lit(['a', 'b', 'c']), lit([1, 2, 3]))->eval(row([]), flow_context()), + combine(lit(['a', 'b', 'c']), lit([1, 2, 3]))->eval(array_to_row([], schema()), flow_context()), ); } public function test_array_combine_when_arrays_are_empty(): void { - static::assertSame([], combine(lit([]), lit([]))->eval(row([]), flow_context())); + static::assertSame([], combine(lit([]), lit([]))->eval(array_to_row([], schema()), flow_context())); } public function test_array_combine_when_keys_are_not_array(): void @@ -55,14 +55,14 @@ public function test_array_combine_when_keys_are_not_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - combine(lit('a'), lit([1, 2, 3]))->eval(row([]), flow_context()); + combine(lit('a'), lit([1, 2, 3]))->eval(array_to_row([], schema()), flow_context()); } public function test_array_combine_when_keys_are_not_unique(): void { static::assertSame( ['a' => 4, 'b' => 2, 'c' => 3], - combine(lit(['a', 'b', 'c', 'a']), lit([1, 2, 3, 4]))->eval(row([]), flow_context()), + combine(lit(['a', 'b', 'c', 'a']), lit([1, 2, 3, 4]))->eval(array_to_row([], schema()), flow_context()), ); } @@ -71,6 +71,6 @@ public function test_array_combine_when_one_of_arrays_is_empty(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Combine function requires keys and values arrays to have the same length'); - combine(lit(['a', 'b', 'c']), lit([]))->eval(row([]), flow_context()); + combine(lit(['a', 'b', 'c']), lit([]))->eval(array_to_row([], schema()), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatTest.php index c7c3bf40bb..f736c68e43 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatTest.php @@ -6,32 +6,48 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\concat; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_string; final class ConcatTest extends FlowTestCase { public function test_concat_arrays(): void { - static::assertSame('["a"]["b","c"]', concat(ref('array_1'), ref('array_2'))->eval(row([ - 'array_1' => ['a'], - 'array_2' => ['b', 'c'], - ]), flow_context())); + static::assertSame('["a"]["b","c"]', concat(ref('array_1'), ref('array_2'))->eval( + array_to_row( + [ + 'array_1' => ['a'], + 'array_2' => ['b', 'c'], + ], + schema( + list_schema('array_1', type_list(type_string())), + list_schema('array_2', type_list(type_string())), + ), + ), + flow_context(), + )); } public function test_concat_different_types_of_values(): void { static::assertSame('1abc["a","b"]', concat(lit(1), lit('a'), lit('b'), lit('c'), lit(['a', 'b']))->eval( - row([]), + array_to_row([], schema()), flow_context(), )); } public function test_concat_string_values(): void { - static::assertSame('abc', concat(lit('a'), lit('b'), lit('c'))->eval(row([]), flow_context())); + static::assertSame('abc', concat(lit('a'), lit('b'), lit('c'))->eval( + array_to_row([], schema()), + flow_context(), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatWithSeparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatWithSeparatorTest.php index 8a536b2036..ab26a5dd04 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatWithSeparatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatWithSeparatorTest.php @@ -6,27 +6,42 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\concat_ws; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class ConcatWithSeparatorTest extends FlowTestCase { public function test_concat_with_separator(): void { - static::assertSame('a,1', concat_ws(lit(','), ref('string'), ref('integer'))->eval(row([ - 'string' => 'a', - 'integer' => 1, - ]), flow_context())); + static::assertSame('a,1', concat_ws(lit(','), ref('string'), ref('integer'))->eval( + array_to_row( + [ + 'string' => 'a', + 'integer' => 1, + ], + schema(str_schema('string'), int_schema('integer')), + ), + flow_context(), + )); } public function test_a_null_value_is_skipped(): void { - static::assertSame('a', concat_ws(lit(','), ref('string'), ref('missing_value'))->eval(row([ - 'string' => 'a', - 'missing_value' => null, - ]), flow_context())); + static::assertSame('a', concat_ws(lit(','), ref('string'), ref('missing_value'))->eval( + array_to_row( + [ + 'string' => 'a', + 'missing_value' => null, + ], + schema(str_schema('string'), str_schema('missing_value', nullable: true)), + ), + flow_context(), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CountTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CountTest.php index a17be7e289..7f15d8d91e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CountTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CountTest.php @@ -8,14 +8,16 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\count; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\window; final class CountTest extends FlowTestCase @@ -34,11 +36,13 @@ public function test_aggregation_count_from_numeric_values(): void { $aggregator = count(ref('int')); - $aggregator->aggregate(row(['int' => '10']), flow_context()); - $aggregator->aggregate(row(['int' => '20']), flow_context()); - $aggregator->aggregate(row(['int' => '55']), flow_context()); - $aggregator->aggregate(row(['int' => '25']), flow_context()); - $aggregator->aggregate(row(['not_int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'not_int' => null, + ], schema(str_schema('not_int', nullable: true))), flow_context()); static::assertSame(4, $aggregator->value()); } @@ -47,10 +51,10 @@ public function test_aggregation_count_with_float_result(): void { $aggregator = count(ref('int')); - $aggregator->aggregate(row(['int' => 10.25]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 305]), flow_context()); - $aggregator->aggregate(row(['int' => 25]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10.25], schema(float_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 305], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); static::assertSame(4, $aggregator->value()); } @@ -59,11 +63,13 @@ public function test_aggregation_count_without_reference(): void { $aggregator = count(); - $aggregator->aggregate(row(['int' => '10']), flow_context()); - $aggregator->aggregate(row(['int' => '20']), flow_context()); - $aggregator->aggregate(row(['int' => '55']), flow_context()); - $aggregator->aggregate(row(['int' => '25']), flow_context()); - $aggregator->aggregate(row(['not_int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'not_int' => null, + ], schema(str_schema('not_int', nullable: true))), flow_context()); static::assertSame(5, $aggregator->value()); } @@ -72,11 +78,15 @@ public function test_aggregation_when_row_does_not_have_entry(): void { $aggregator = count(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => null]), flow_context()); - $aggregator->aggregate(row(['test' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'int' => null, + ], schema(int_schema('int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'test' => null, + ], schema(str_schema('test', nullable: true))), flow_context()); static::assertSame(4, $aggregator->value()); } @@ -85,9 +95,9 @@ public function test_window_function_count_of_a_reference_skips_nulls(): void { $rows = rows( schema(int_schema('id'), int_schema('value', nullable: true)), - $row1 = row(['id' => 1, 'value' => 10]), - row(['id' => 2, 'value' => null]), - row(['id' => 3, 'value' => 30]), + $row1 = array_to_row(['id' => 1, 'value' => 10], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 2, 'value' => null], schema(int_schema('id'), int_schema('value', nullable: true))), + array_to_row(['id' => 3, 'value' => 30], schema(int_schema('id'), int_schema('value'))), ); $count = count(ref('value'))->over(window()->orderBy(ref('id'))); @@ -99,9 +109,9 @@ public function test_window_function_count_without_a_reference_counts_every_row_ { $rows = rows( schema(int_schema('id'), int_schema('value', nullable: true)), - $row1 = row(['id' => 1, 'value' => 10]), - row(['id' => 2, 'value' => null]), - row(['id' => 3, 'value' => 30]), + $row1 = array_to_row(['id' => 1, 'value' => 10], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 2, 'value' => null], schema(int_schema('id'), int_schema('value', nullable: true))), + array_to_row(['id' => 3, 'value' => 30], schema(int_schema('id'), int_schema('value'))), ); $count = count()->over(window()->orderBy(ref('id'))); @@ -114,7 +124,11 @@ public function test_window_function_count_with_missing_reference_in_strict_mode $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Count window function error:'); - $rows = rows(schema(int_schema('id')), $row1 = row(['id' => 1]), row(['id' => 2])); + $rows = rows( + schema(int_schema('id')), + $row1 = array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + ); $count = count(ref('missing_column'))->over(window()->orderBy(ref('id'))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributeValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributeValueTest.php index 312063f7c6..75c6a7c369 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributeValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributeValueTest.php @@ -11,9 +11,12 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\xml_element_schema; use const LIBXML_HTML_NOIMPLIED; use const LIBXML_NOERROR; @@ -32,7 +35,9 @@ public function test_html_extracting_attribute_from_dom_element_entry(): void static::assertInstanceOf(HTMLElement::class, $element->documentElement); static::assertEquals('foobar', ref('value') ->domElementAttributeValue('id') - ->eval(row(['value' => $element->documentElement]), flow_context())); + ->eval(array_to_row([ + 'value' => $element->documentElement, + ], schema(html_element_schema('value'))), flow_context())); } #[RequiresPhp('>= 8.4.0')] @@ -45,7 +50,9 @@ public function test_html_extracting_non_existing_attribute_from_dom_element_ent static::assertNull( ref('value') ->domElementAttributeValue('id') - ->eval(row(['value' => $element->documentElement]), flow_context()), + ->eval(array_to_row([ + 'value' => $element->documentElement, + ], schema(html_element_schema('value'))), flow_context()), ); } @@ -57,7 +64,9 @@ public function test_xml_extracting_attribute_from_dom_element_entry(): void static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertEquals('buz', ref('value') ->domElementAttributeValue('baz') - ->eval(row(['value' => $xml->documentElement->firstChild]), flow_context())); + ->eval(array_to_row([ + 'value' => $xml->documentElement->firstChild, + ], schema(xml_element_schema('value'))), flow_context())); } public function test_xml_extracting_non_existing_attribute_from_dom_element_entry(): void @@ -69,7 +78,9 @@ public function test_xml_extracting_non_existing_attribute_from_dom_element_entr static::assertNull( ref('value') ->domElementAttributeValue('bar') - ->eval(row(['value' => $xml->documentElement->firstChild]), flow_context()), + ->eval(array_to_row([ + 'value' => $xml->documentElement->firstChild, + ], schema(xml_element_schema('value'))), flow_context()), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributesCountTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributesCountTest.php index e43c5b6960..aa2b0dd904 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributesCountTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributesCountTest.php @@ -11,9 +11,12 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\xml_element_schema; use const LIBXML_HTML_NOIMPLIED; use const LIBXML_NOERROR; @@ -32,7 +35,9 @@ public function test_html_attributes_count_on_element_with_multiple_attributes() static::assertInstanceOf(HTMLElement::class, $element->documentElement); static::assertSame(3, ref('value') ->domElementAttributesCount() - ->eval(row(['value' => $element->documentElement]), flow_context())); + ->eval(array_to_row([ + 'value' => $element->documentElement, + ], schema(html_element_schema('value'))), flow_context())); } #[RequiresPhp('>= 8.4.0')] @@ -47,7 +52,9 @@ public function test_html_attributes_count_on_element_with_one_attribute(): void static::assertInstanceOf(HTMLElement::class, $element->documentElement); static::assertSame(1, ref('value') ->domElementAttributesCount() - ->eval(row(['value' => $element->documentElement]), flow_context())); + ->eval(array_to_row([ + 'value' => $element->documentElement, + ], schema(html_element_schema('value'))), flow_context())); } #[RequiresPhp('>= 8.4.0')] @@ -59,7 +66,9 @@ public function test_html_attributes_count_on_element_with_zero_attributes(): vo static::assertInstanceOf(HTMLElement::class, $element->documentElement); static::assertSame(0, ref('value') ->domElementAttributesCount() - ->eval(row(['value' => $element->documentElement]), flow_context())); + ->eval(array_to_row([ + 'value' => $element->documentElement, + ], schema(html_element_schema('value'))), flow_context())); } public function test_xml_attributes_count_on_element_with_multiple_attributes(): void @@ -70,7 +79,9 @@ public function test_xml_attributes_count_on_element_with_multiple_attributes(): static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertSame(3, ref('value') ->domElementAttributesCount() - ->eval(row(['value' => $xml->documentElement->firstChild]), flow_context())); + ->eval(array_to_row([ + 'value' => $xml->documentElement->firstChild, + ], schema(xml_element_schema('value'))), flow_context())); } public function test_xml_attributes_count_on_element_with_one_attribute(): void @@ -81,7 +92,9 @@ public function test_xml_attributes_count_on_element_with_one_attribute(): void static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertSame(1, ref('value') ->domElementAttributesCount() - ->eval(row(['value' => $xml->documentElement->firstChild]), flow_context())); + ->eval(array_to_row([ + 'value' => $xml->documentElement->firstChild, + ], schema(xml_element_schema('value'))), flow_context())); } public function test_xml_attributes_count_on_element_with_zero_attributes(): void @@ -92,6 +105,8 @@ public function test_xml_attributes_count_on_element_with_zero_attributes(): voi static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertSame(0, ref('value') ->domElementAttributesCount() - ->eval(row(['value' => $xml->documentElement->firstChild]), flow_context())); + ->eval(array_to_row([ + 'value' => $xml->documentElement->firstChild, + ], schema(xml_element_schema('value'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementNamespaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementNamespaceTest.php index 51c2f23568..6c47661dc6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementNamespaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementNamespaceTest.php @@ -11,9 +11,11 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\xml_element_schema; use const LIBXML_HTML_NOIMPLIED; use const LIBXML_NOERROR; @@ -39,7 +41,9 @@ public function test_html_getting_element_namespace(): void static::assertInstanceOf(Element::class, $element->documentElement); static::assertSame('urn:oasis:names:specification:ubl:schema:xsd:Invoice-2', ref('node') ->domElementNamespace() - ->eval(row(['node' => $element->documentElement]), flow_context())); + ->eval(array_to_row([ + 'node' => $element->documentElement, + ], schema(xml_element_schema('node'))), flow_context())); } public function test_xml_getting_element_namespace(): void @@ -50,7 +54,9 @@ public function test_xml_getting_element_namespace(): void static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertSame('urn:oasis:names:specification:ubl:schema:xsd:Invoice-2', ref('node') ->domElementNamespace() - ->eval(row(['node' => $xml->documentElement]), flow_context())); + ->eval(array_to_row([ + 'node' => $xml->documentElement, + ], schema(xml_element_schema('node'))), flow_context())); } public function test_xml_getting_element_non_default_namespace(): void @@ -61,6 +67,8 @@ public function test_xml_getting_element_non_default_namespace(): void static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertSame('http://www.unece.org/cefact/nodes/StandardBusinessDocumentHeader', ref('node') ->domElementNamespace('xmlns:sh') - ->eval(row(['node' => $xml->documentElement]), flow_context())); + ->eval(array_to_row([ + 'node' => $xml->documentElement, + ], schema(xml_element_schema('node'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php index 45e4a67e17..410f534b0c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php @@ -10,11 +10,15 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\xml_element_schema; +use function Flow\ETL\DSL\xml_schema; use const LIBXML_HTML_NOIMPLIED; use const LIBXML_NOERROR; @@ -32,7 +36,9 @@ public function test_html_fails_when_parent_not_available_in_strict_mode(): void ref('value') ->domElementParent() // @mago-ignore analysis:possibly-null-property-access - ->eval(row(['value' => $element->documentElement->parentElement]), $context); + ->eval(array_to_row([ + 'value' => $element->documentElement->parentElement, + ], schema(html_element_schema('value', nullable: true))), $context); } #[RequiresPhp('>= 8.4.0')] @@ -45,7 +51,7 @@ public function test_html_getting_parent_element(): void ); static::assertEquals( $element->documentElement, - lit($element->querySelector('span'))->domElementParent()->eval(row([]), flow_context()), + lit($element->querySelector('span'))->domElementParent()->eval(array_to_row([], schema()), flow_context()), ); } @@ -54,7 +60,9 @@ public function test_html_getting_parent_element_when_not_available(): void { // @mago-ignore analysis:unavailable-method $element = HTMLDocument::createFromString('bar', LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); - static::assertNull(lit($element->documentElement)->domElementParent()->eval(row([]), flow_context())); + static::assertNull( + lit($element->documentElement)->domElementParent()->eval(array_to_row([], schema()), flow_context()), + ); } public function test_xml_fails_when_parent_not_available_in_strict_mode(): void @@ -66,7 +74,9 @@ public function test_xml_fails_when_parent_not_available_in_strict_mode(): void $this->expectExceptionMessage('DOMElementParent requires non-null DOMNode or HTMLElement.'); static::assertEquals($xml, ref('value') ->domElementParent() - ->eval(row(['value' => $xml->parentNode]), $context)); + ->eval(array_to_row([ + 'value' => $xml->parentNode, + ], schema(xml_element_schema('value', nullable: true))), $context)); } public function test_xml_getting_parent_element(): void @@ -77,7 +87,9 @@ public function test_xml_getting_parent_element(): void $xml->documentElement, // a batch stores the element's markup, so the parent is only reachable on the live node // @mago-ignore analysis:possibly-null-property-access - lit($xml->documentElement->firstChild)->domElementParent()->eval(row([]), flow_context()), + lit($xml->documentElement->firstChild) + ->domElementParent() + ->eval(array_to_row([], schema()), flow_context()), ); } @@ -86,7 +98,11 @@ public function test_xml_getting_parent_element_when_not_available(): void $xml = new DOMDocument(); $xml->loadXML('foobar'); static::assertNull( - ref('value')->domElementParent()->eval(row(['value' => $xml->documentElement]), flow_context()), + ref('value') + ->domElementParent() + ->eval(array_to_row([ + 'value' => $xml->documentElement, + ], schema(xml_element_schema('value'))), flow_context()), ); } @@ -94,6 +110,10 @@ public function test_xml_getting_parent_element_when_passing_document(): void { $xml = new DOMDocument(); $xml->loadXML('foobar'); - static::assertNull(ref('value')->domElementParent()->eval(row(['value' => $xml]), flow_context())); + static::assertNull( + ref('value') + ->domElementParent() + ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementValueTest.php index 04367e4640..078c588a24 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementValueTest.php @@ -11,9 +11,12 @@ use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\RequiresPhp; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\xml_element_schema; use const LIBXML_HTML_NOIMPLIED; use const LIBXML_NOERROR; @@ -29,7 +32,9 @@ public function test_html_getting_element_value_with_children(): void static::assertInstanceOf(HTMLElement::class, $element->documentElement); static::assertEquals('foobar', ref('value') ->domElementValue() - ->eval(row(['value' => $element->documentElement]), flow_context())); + ->eval(array_to_row([ + 'value' => $element->documentElement, + ], schema(html_element_schema('value'))), flow_context())); } #[RequiresPhp('>= 8.4.0')] @@ -41,7 +46,9 @@ public function test_html_getting_simple_element_value(): void static::assertInstanceOf(HTMLElement::class, $element->documentElement); static::assertEquals('bar', ref('value') ->domElementValue() - ->eval(row(['value' => $element->documentElement]), flow_context())); + ->eval(array_to_row([ + 'value' => $element->documentElement, + ], schema(html_element_schema('value'))), flow_context())); } public function test_xml_getting_element_value_with_children(): void @@ -52,7 +59,9 @@ public function test_xml_getting_element_value_with_children(): void static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertEquals('baz', ref('value') ->domElementValue() - ->eval(row(['value' => $xml->documentElement->firstChild]), flow_context())); + ->eval(array_to_row([ + 'value' => $xml->documentElement->firstChild, + ], schema(xml_element_schema('value'))), flow_context())); } public function test_xml_getting_simple_element_value(): void @@ -63,6 +72,8 @@ public function test_xml_getting_simple_element_value(): void static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertEquals('bar', ref('value') ->domElementValue() - ->eval(row(['value' => $xml->documentElement->firstChild]), flow_context())); + ->eval(array_to_row([ + 'value' => $xml->documentElement->firstChild, + ], schema(xml_element_schema('value'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DateTimeFormatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DateTimeFormatTest.php index 11db787d5d..97295adc0c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DateTimeFormatTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DateTimeFormatTest.php @@ -9,28 +9,34 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\date_time_format; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\now; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class DateTimeFormatTest extends FlowTestCase { public function test_date_time_format(): void { static::assertEquals('2020-01-01 00:00:00', date_time_format(ref('date_time'), 'Y-m-d H:i:s')->eval( - row(['date_time' => new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC'))]), + array_to_row(['date_time' => new DateTimeImmutable( + '2020-01-01 00:00:00', + new DateTimeZone('UTC'), + )], schema(datetime_schema('date_time'))), flow_context(), )); } public function test_formatting_now(): void { - static::assertInstanceOf(DateTimeImmutable::class, now()->eval(row(['date_time' => new DateTimeImmutable( - '2020-01-01 00:00:00', - new DateTimeZone('UTC'), - )]), flow_context())); + static::assertInstanceOf(DateTimeImmutable::class, now()->eval(array_to_row( + ['date_time' => new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC'))], + schema(datetime_schema('date_time')), + ), flow_context())); } public function test_invalid_date_time_format(): void @@ -38,8 +44,8 @@ public function test_invalid_date_time_format(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "object", got "string".'); - date_time_format(ref('date_time'), 'Y-m-d H:i:s')->eval(row([ + date_time_format(ref('date_time'), 'Y-m-d H:i:s')->eval(array_to_row([ 'date_time' => '2020-01-01 00:00:00', - ]), flow_context()); + ], schema(str_schema('date_time'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DenseRankTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DenseRankTest.php index 052b8afa6f..97288077e8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DenseRankTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DenseRankTest.php @@ -8,11 +8,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\dense_rank; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\window; @@ -71,7 +70,7 @@ public function test_dense_rank_requires_an_order_by(): void { $this->expectExceptionMessage('Dens Rank window function requires to be ordered by one column'); - dense_rank()->over(window())->rankPartition(rows(schema(int_schema('salary')), row(['salary' => 6000]))); + dense_rank()->over(window())->rankPartition(array_to_rows([['salary' => 6000]], schema(int_schema('salary')))); } public function test_dense_rank_without_over_clause(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureEndTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureEndTest.php index 25cc5732a4..1470a863d5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureEndTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureEndTest.php @@ -7,22 +7,34 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class EnsureEndTest extends FlowTestCase { public function test_empty_string_with_suffix(): void { - $result = ref('str')->ensureEnd('_suffix')->eval(row(['str' => '']), flow_context()); + $result = ref('str') + ->ensureEnd('_suffix') + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); static::assertEquals('_suffix', $result); } public function test_null_suffix(): void { - $result = ref('str')->ensureEnd(ref('suffix'))->eval(row(['str' => 'hello', 'suffix' => null]), flow_context()); + $result = ref('str') + ->ensureEnd(ref('suffix')) + ->eval( + array_to_row( + ['str' => 'hello', 'suffix' => null], + schema(str_schema('str'), str_schema('suffix', nullable: true)), + ), + flow_context(), + ); static::assertEquals('hello', $result); } @@ -32,28 +44,36 @@ public function test_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('EnsureEnd function requires non-null value'); - $result = ref('str')->ensureEnd('_suffix')->eval(row(['str' => null]), flow_context()); + $result = ref('str') + ->ensureEnd('_suffix') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); static::assertNull($result); } public function test_string_already_ends_with_suffix(): void { - $result = ref('str')->ensureEnd('.txt')->eval(row(['str' => 'document.txt']), flow_context()); + $result = ref('str') + ->ensureEnd('.txt') + ->eval(array_to_row(['str' => 'document.txt'], schema(str_schema('str'))), flow_context()); static::assertEquals('document.txt', $result); } public function test_string_doesnt_end_with_suffix(): void { - $result = ref('str')->ensureEnd('.txt')->eval(row(['str' => 'document']), flow_context()); + $result = ref('str') + ->ensureEnd('.txt') + ->eval(array_to_row(['str' => 'document'], schema(str_schema('str'))), flow_context()); static::assertEquals('document.txt', $result); } public function test_string_with_empty_suffix(): void { - $result = ref('str')->ensureEnd('')->eval(row(['str' => 'hello']), flow_context()); + $result = ref('str') + ->ensureEnd('') + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); static::assertEquals('hello', $result); } @@ -62,7 +82,13 @@ public function test_with_scalar_function_parameter(): void { $result = ref('str') ->ensureEnd(ref('suffix')) - ->eval(row(['str' => 'document', 'suffix' => '.pdf']), flow_context()); + ->eval( + array_to_row( + ['str' => 'document', 'suffix' => '.pdf'], + schema(str_schema('str'), str_schema('suffix')), + ), + flow_context(), + ); static::assertEquals('document.pdf', $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureStartTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureStartTest.php index 441a442018..7e18ba2ca6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureStartTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureStartTest.php @@ -7,15 +7,19 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class EnsureStartTest extends FlowTestCase { public function test_empty_string_with_prefix(): void { - $result = ref('str')->ensureStart('prefix_')->eval(row(['str' => '']), flow_context()); + $result = ref('str') + ->ensureStart('prefix_') + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); static::assertEquals('prefix_', $result); } @@ -24,7 +28,13 @@ public function test_null_prefix(): void { $result = ref('str') ->ensureStart(ref('prefix')) - ->eval(row(['str' => 'hello', 'prefix' => null]), flow_context()); + ->eval( + array_to_row( + ['str' => 'hello', 'prefix' => null], + schema(str_schema('str'), str_schema('prefix', nullable: true)), + ), + flow_context(), + ); static::assertEquals('hello', $result); } @@ -34,28 +44,36 @@ public function test_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('EnsureStart function requires non-null value'); - $result = ref('str')->ensureStart('prefix_')->eval(row(['str' => null]), flow_context()); + $result = ref('str') + ->ensureStart('prefix_') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); static::assertNull($result); } public function test_string_already_starts_with_prefix(): void { - $result = ref('str')->ensureStart('https://')->eval(row(['str' => 'https://example.com']), flow_context()); + $result = ref('str') + ->ensureStart('https://') + ->eval(array_to_row(['str' => 'https://example.com'], schema(str_schema('str'))), flow_context()); static::assertEquals('https://example.com', $result); } public function test_string_doesnt_start_with_prefix(): void { - $result = ref('str')->ensureStart('https://')->eval(row(['str' => 'example.com']), flow_context()); + $result = ref('str') + ->ensureStart('https://') + ->eval(array_to_row(['str' => 'example.com'], schema(str_schema('str'))), flow_context()); static::assertEquals('https://example.com', $result); } public function test_string_with_empty_prefix(): void { - $result = ref('str')->ensureStart('')->eval(row(['str' => 'hello']), flow_context()); + $result = ref('str') + ->ensureStart('') + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); static::assertEquals('hello', $result); } @@ -64,7 +82,13 @@ public function test_with_scalar_function_parameter(): void { $result = ref('str') ->ensureStart(ref('prefix')) - ->eval(row(['str' => 'example.com', 'prefix' => 'https://']), flow_context()); + ->eval( + array_to_row( + ['str' => 'example.com', 'prefix' => 'https://'], + schema(str_schema('str'), str_schema('prefix')), + ), + flow_context(), + ); static::assertEquals('https://example.com', $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumNameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumNameTest.php index dd23cceaea..466a5ac3bf 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumNameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumNameTest.php @@ -12,11 +12,13 @@ use PHPUnit\Framework\Attributes\TestWith; use UnitEnum; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\enum_name; +use function Flow\ETL\DSL\enum_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\Types\DSL\type_equals; use function Flow\Types\DSL\type_string; @@ -24,7 +26,7 @@ final class EnumNameTest extends FlowTestCase { public function test_enum_name_accepts_literal_enum(): void { - static::assertSame('one', enum_name(BackedStringEnum::one)->eval(row([]), flow_context())); + static::assertSame('one', enum_name(BackedStringEnum::one)->eval(array_to_row([], schema()), flow_context())); } public function test_enum_name_carries_string_type(): void @@ -34,7 +36,11 @@ public function test_enum_name_carries_string_type(): void public function test_enum_name_from_scalar_function_chain(): void { - static::assertSame('one', ref('e')->enumName()->eval(row(['e' => BackedIntEnum::one]), flow_context())); + static::assertSame('one', ref('e') + ->enumName() + ->eval(array_to_row([ + 'e' => BackedIntEnum::one, + ], schema(enum_schema('e', BackedIntEnum::class))), flow_context())); } #[TestWith([BackedStringEnum::one])] @@ -42,7 +48,8 @@ public function test_enum_name_from_scalar_function_chain(): void #[TestWith([BasicEnum::one])] public function test_enum_name_returns_case_name(UnitEnum $enum): void { - static::assertSame('one', enum_name(ref('e'))->eval(row(['e' => $enum]), flow_context())); + static::assertSame('one', enum_name(ref('e')) + ->eval(array_to_row(['e' => $enum], schema(enum_schema('e', $enum::class))), flow_context())); } #[TestWith([null])] @@ -54,6 +61,6 @@ public function test_enum_name_throws_in_strict_mode(mixed $input): void $this->expectExceptionMessage('EnumName function requires a UnitEnum value'); $context = flow_context(config()); - enum_name($input)->eval(row([]), $context); + enum_name($input)->eval(array_to_row([], schema()), $context); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumValueTest.php index e87467bc9f..d27f331555 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumValueTest.php @@ -15,12 +15,12 @@ use PHPUnit\Framework\Attributes\TestWith; use UnitEnum; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\enum_schema; use function Flow\ETL\DSL\enum_value; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_equals; @@ -31,19 +31,24 @@ final class EnumValueTest extends FlowTestCase { public function test_enum_value_accepts_literal_enum(): void { - static::assertSame(1, enum_value(BackedIntEnum::one)->eval(row([]), flow_context())); + static::assertSame(1, enum_value(BackedIntEnum::one)->eval(array_to_row([], schema()), flow_context())); } public function test_enum_value_from_scalar_function_chain(): void { - static::assertSame(1, ref('e')->enumValue()->eval(row(['e' => BackedIntEnum::one]), flow_context())); + static::assertSame(1, ref('e') + ->enumValue() + ->eval(array_to_row([ + 'e' => BackedIntEnum::one, + ], schema(enum_schema('e', BackedIntEnum::class))), flow_context())); } #[TestWith([BackedStringEnum::one, 'one'])] #[TestWith([BackedIntEnum::one, 1])] public function test_enum_value_returns_backing_value(UnitEnum $enum, int|string $expected): void { - static::assertSame($expected, enum_value(ref('e'))->eval(row(['e' => $enum]), flow_context())); + static::assertSame($expected, enum_value(ref('e')) + ->eval(array_to_row(['e' => $enum], schema(enum_schema('e', $enum::class))), flow_context())); } #[TestWith([BasicEnum::one])] @@ -56,7 +61,7 @@ public function test_enum_value_throws_in_strict_mode(mixed $input): void $this->expectExceptionMessage('EnumValue function requires a BackedEnum value'); $context = flow_context(config()); - enum_value($input)->eval(row([]), $context); + enum_value($input)->eval(array_to_row([], schema()), $context); } public function test_a_non_enum_operand_is_refused_at_bind(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php index 58070c9e70..c340e3c6f8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php @@ -6,23 +6,46 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class EqualsTest extends FlowTestCase { public function test_null_operand_yields_null(): void { - static::assertNull(ref('a')->equals(lit(1))->eval(row(['a' => null]), flow_context())); - static::assertNull(ref('a')->equals(ref('b'))->eval(row(['a' => null, 'b' => null]), flow_context())); + static::assertNull( + ref('a') + ->equals(lit(1)) + ->eval(array_to_row(['a' => null], schema(str_schema('a', nullable: true))), flow_context()), + ); + static::assertNull( + ref('a') + ->equals(ref('b')) + ->eval( + array_to_row( + ['a' => null, 'b' => null], + schema(str_schema('a', nullable: true), str_schema('b', nullable: true)), + ), + flow_context(), + ), + ); } public function test_equal_values(): void { - static::assertTrue(ref('a')->equals(lit(1))->eval(row(['a' => 1]), flow_context())); - static::assertTrue(ref('a')->equals(lit('x'))->eval(row(['a' => 'x']), flow_context())); - static::assertFalse(ref('a')->equals(lit(2))->eval(row(['a' => 1]), flow_context())); + static::assertTrue( + ref('a')->equals(lit(1))->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context()), + ); + static::assertTrue( + ref('a')->equals(lit('x'))->eval(array_to_row(['a' => 'x'], schema(str_schema('a'))), flow_context()), + ); + static::assertFalse( + ref('a')->equals(lit(2))->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ExistsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ExistsTest.php index cc38baec29..adf2e082e4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ExistsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ExistsTest.php @@ -7,35 +7,48 @@ use Flow\ETL\Function\Exists; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class ExistsTest extends FlowTestCase { public function test_a_throwing_operand_means_the_reference_does_not_exist(): void { - static::assertFalse((new Exists(ref('value')->upper()))->eval(row(['value' => 1]), flow_context())); + static::assertFalse((new Exists(ref('value')->upper()))->eval(array_to_row([ + 'value' => 1, + ], schema(int_schema('value'))), flow_context())); } public function test_if_reference_exists(): void { - static::assertTrue(ref('value')->exists()->eval(row(['value' => 'test']), flow_context())); + static::assertTrue( + ref('value') + ->exists() + ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context()), + ); } public function test_that_lit_function_exists(): void { - static::assertTrue((new Exists(lit('val')))->eval(row([]), flow_context())); + static::assertTrue((new Exists(lit('val')))->eval(array_to_row([], schema()), flow_context())); } public function test_that_null_reference_to_null_entry_exists(): void { - static::assertTrue(ref('value')->exists()->eval(row(['value' => null]), flow_context())); + static::assertTrue( + ref('value') + ->exists() + ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), + ); } public function test_that_reference_does_not_exists(): void { - static::assertFalse(ref('value')->exists()->eval(row([]), flow_context())); + static::assertFalse(ref('value')->exists()->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/FirstTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/FirstTest.php index 3c10bb7fd7..85a638cb40 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/FirstTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/FirstTest.php @@ -7,12 +7,13 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\first; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class FirstTest extends FlowTestCase { @@ -25,11 +26,13 @@ public function test_aggregation_firs_value(): void { $aggregator = first(ref('int')); - $aggregator->aggregate(row(['not_int' => null]), flow_context()); - $aggregator->aggregate(row(['int' => '10']), flow_context()); - $aggregator->aggregate(row(['int' => '20']), flow_context()); - $aggregator->aggregate(row(['int' => '55']), flow_context()); - $aggregator->aggregate(row(['int' => '25']), flow_context()); + $aggregator->aggregate(array_to_row([ + 'not_int' => null, + ], schema(str_schema('not_int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); static::assertSame('10', $aggregator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanEqualTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanEqualTest.php index d956455de8..02923961e9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanEqualTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanEqualTest.php @@ -9,10 +9,19 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; final class GreaterThanEqualTest extends FlowTestCase { @@ -20,9 +29,21 @@ public function test_greater_than_equal_arrays(): void { $context = flow_context(); - static::assertTrue(ref('v')->greaterThanEqual(lit([1, 0]))->eval(row(['v' => [1, 9]]), $context)); - static::assertTrue(ref('v')->greaterThanEqual(lit([1, 0]))->eval(row(['v' => [1, 0]]), $context)); - static::assertFalse(ref('v')->greaterThanEqual(lit([1, 9]))->eval(row(['v' => [1, 0]]), $context)); + static::assertTrue( + ref('v') + ->greaterThanEqual(lit([1, 0])) + ->eval(array_to_row(['v' => [1, 9]], schema(list_schema('v', type_list(type_integer())))), $context), + ); + static::assertTrue( + ref('v') + ->greaterThanEqual(lit([1, 0])) + ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), + ); + static::assertFalse( + ref('v') + ->greaterThanEqual(lit([1, 9])) + ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), + ); } public function test_greater_than_equal_datetimes(): void @@ -32,17 +53,23 @@ public function test_greater_than_equal_datetimes(): void static::assertTrue( ref('v') ->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-06-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-06-01'), + ], schema(datetime_schema('v'))), $context), ); static::assertTrue( ref('v') ->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-01-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-01-01'), + ], schema(datetime_schema('v'))), $context), ); static::assertFalse( ref('v') ->greaterThanEqual(lit(new DateTimeImmutable('2024-06-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-01-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-01-01'), + ], schema(datetime_schema('v'))), $context), ); } @@ -50,23 +77,39 @@ public function test_greater_than_equal_floats(): void { $context = flow_context(); - static::assertTrue(ref('v')->greaterThanEqual(lit(1.5))->eval(row(['v' => 2.5]), $context)); - static::assertTrue(ref('v')->greaterThanEqual(lit(1.5))->eval(row(['v' => 1.5]), $context)); - static::assertFalse(ref('v')->greaterThanEqual(lit(2.5))->eval(row(['v' => 1.5]), $context)); + static::assertTrue( + ref('v')->greaterThanEqual(lit(1.5))->eval(array_to_row(['v' => 2.5], schema(float_schema('v'))), $context), + ); + static::assertTrue( + ref('v')->greaterThanEqual(lit(1.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->greaterThanEqual(lit(2.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), + ); } public function test_greater_than_equal_integers(): void { $context = flow_context(); - static::assertTrue(ref('v')->greaterThanEqual(lit(10))->eval(row(['v' => 20]), $context)); - static::assertTrue(ref('v')->greaterThanEqual(lit(10))->eval(row(['v' => 10]), $context)); - static::assertFalse(ref('v')->greaterThanEqual(lit(20))->eval(row(['v' => 10]), $context)); + static::assertTrue( + ref('v')->greaterThanEqual(lit(10))->eval(array_to_row(['v' => 20], schema(int_schema('v'))), $context), + ); + static::assertTrue( + ref('v')->greaterThanEqual(lit(10))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->greaterThanEqual(lit(20))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), + ); } public function test_greater_than_equal_returns_null_for_null_array(): void { - static::assertNull(ref('v')->greaterThanEqual(lit([1, 0]))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->greaterThanEqual(lit([1, 0])) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_greater_than_equal_returns_null_for_null_datetime(): void @@ -74,31 +117,49 @@ public function test_greater_than_equal_returns_null_for_null_datetime(): void static::assertNull( ref('v') ->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => null]), flow_context()), + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), ); } public function test_greater_than_equal_returns_null_for_null_left(): void { - static::assertNull(ref('v')->greaterThanEqual(lit(10))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->greaterThanEqual(lit(10)) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_greater_than_equal_returns_null_for_null_right(): void { static::assertNull( - ref('v')->greaterThanEqual(ref('other'))->eval(row(['v' => 10, 'other' => null]), flow_context()), + ref('v') + ->greaterThanEqual(ref('other')) + ->eval( + array_to_row( + ['v' => 10, 'other' => null], + schema(int_schema('v'), str_schema('other', nullable: true)), + ), + flow_context(), + ), ); } public function test_greater_than_equal_returns_null_for_null_string(): void { - static::assertNull(ref('v')->greaterThanEqual(lit('a'))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->greaterThanEqual(lit('a')) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_greater_than_equal_returns_null_for_null_time_interval(): void { static::assertNull( - ref('v')->greaterThanEqual(lit(new DateInterval('PT1H')))->eval(row(['v' => null]), flow_context()), + ref('v') + ->greaterThanEqual(lit(new DateInterval('PT1H'))) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), ); } @@ -106,9 +167,21 @@ public function test_greater_than_equal_strings(): void { $context = flow_context(); - static::assertTrue(ref('v')->greaterThanEqual(lit('apple'))->eval(row(['v' => 'banana']), $context)); - static::assertTrue(ref('v')->greaterThanEqual(lit('apple'))->eval(row(['v' => 'apple']), $context)); - static::assertFalse(ref('v')->greaterThanEqual(lit('banana'))->eval(row(['v' => 'apple']), $context)); + static::assertTrue( + ref('v') + ->greaterThanEqual(lit('apple')) + ->eval(array_to_row(['v' => 'banana'], schema(str_schema('v'))), $context), + ); + static::assertTrue( + ref('v') + ->greaterThanEqual(lit('apple')) + ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), + ); + static::assertFalse( + ref('v') + ->greaterThanEqual(lit('banana')) + ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), + ); } public function test_greater_than_equal_throws_on_incompatible_types(): void @@ -125,17 +198,17 @@ public function test_greater_than_equal_time_intervals(): void static::assertTrue( ref('v') ->greaterThanEqual(lit(new DateInterval('PT1H'))) - ->eval(row(['v' => new DateInterval('PT5H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT5H')], schema(time_schema('v'))), $context), ); static::assertTrue( ref('v') ->greaterThanEqual(lit(new DateInterval('PT1H'))) - ->eval(row(['v' => new DateInterval('PT1H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), ); static::assertFalse( ref('v') ->greaterThanEqual(lit(new DateInterval('PT5H'))) - ->eval(row(['v' => new DateInterval('PT1H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanTest.php index f5578aa376..b9d7b0bb76 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanTest.php @@ -9,26 +9,49 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; final class GreaterThanTest extends FlowTestCase { public function test_an_integer_column_compared_to_a_string_literal_still_works(): void { // Comparator::comparable(integer, string) stays deliberately loose - 5 > '3' keeps working. - static::assertTrue(ref('a')->greaterThan(lit('3'))->eval(row(['a' => 5]), flow_context())); + static::assertTrue( + ref('a')->greaterThan(lit('3'))->eval(array_to_row(['a' => 5], schema(int_schema('a'))), flow_context()), + ); } public function test_greater_than_arrays(): void { $context = flow_context(); - static::assertTrue(ref('v')->greaterThan(lit([1, 0]))->eval(row(['v' => [1, 9]]), $context)); - static::assertFalse(ref('v')->greaterThan(lit([1, 9]))->eval(row(['v' => [1, 0]]), $context)); - static::assertFalse(ref('v')->greaterThan(lit([1, 0]))->eval(row(['v' => [1, 0]]), $context)); + static::assertTrue( + ref('v') + ->greaterThan(lit([1, 0])) + ->eval(array_to_row(['v' => [1, 9]], schema(list_schema('v', type_list(type_integer())))), $context), + ); + static::assertFalse( + ref('v') + ->greaterThan(lit([1, 9])) + ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), + ); + static::assertFalse( + ref('v') + ->greaterThan(lit([1, 0])) + ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), + ); } public function test_greater_than_datetimes(): void @@ -38,17 +61,23 @@ public function test_greater_than_datetimes(): void static::assertTrue( ref('v') ->greaterThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-06-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-06-01'), + ], schema(datetime_schema('v'))), $context), ); static::assertFalse( ref('v') ->greaterThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2023-06-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2023-06-01'), + ], schema(datetime_schema('v'))), $context), ); static::assertFalse( ref('v') ->greaterThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-01-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-01-01'), + ], schema(datetime_schema('v'))), $context), ); } @@ -56,63 +85,111 @@ public function test_greater_than_floats(): void { $context = flow_context(); - static::assertTrue(ref('v')->greaterThan(lit(1.5))->eval(row(['v' => 2.5]), $context)); - static::assertFalse(ref('v')->greaterThan(lit(2.5))->eval(row(['v' => 1.5]), $context)); - static::assertFalse(ref('v')->greaterThan(lit(1.5))->eval(row(['v' => 1.5]), $context)); + static::assertTrue( + ref('v')->greaterThan(lit(1.5))->eval(array_to_row(['v' => 2.5], schema(float_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->greaterThan(lit(2.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->greaterThan(lit(1.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), + ); } public function test_greater_than_integers(): void { $context = flow_context(); - static::assertTrue(ref('v')->greaterThan(lit(10))->eval(row(['v' => 20]), $context)); - static::assertFalse(ref('v')->greaterThan(lit(20))->eval(row(['v' => 10]), $context)); - static::assertFalse(ref('v')->greaterThan(lit(10))->eval(row(['v' => 10]), $context)); + static::assertTrue( + ref('v')->greaterThan(lit(10))->eval(array_to_row(['v' => 20], schema(int_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->greaterThan(lit(20))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->greaterThan(lit(10))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), + ); } public function test_greater_than_returns_null_for_null_left(): void { - static::assertNull(ref('v')->greaterThan(lit(10))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->greaterThan(lit(10)) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_greater_than_returns_null_for_null_right(): void { static::assertNull( - ref('v')->greaterThan(ref('other'))->eval(row(['v' => 10, 'other' => null]), flow_context()), + ref('v') + ->greaterThan(ref('other')) + ->eval( + array_to_row( + ['v' => 10, 'other' => null], + schema(int_schema('v'), str_schema('other', nullable: true)), + ), + flow_context(), + ), ); } public function test_greater_than_returns_null_for_null_string(): void { - static::assertNull(ref('v')->greaterThan(lit('a'))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->greaterThan(lit('a')) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_greater_than_returns_null_for_null_datetime(): void { static::assertNull( - ref('v')->greaterThan(lit(new DateTimeImmutable('2024-01-01')))->eval(row(['v' => null]), flow_context()), + ref('v') + ->greaterThan(lit(new DateTimeImmutable('2024-01-01'))) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), ); } public function test_greater_than_returns_null_for_null_time_interval(): void { static::assertNull( - ref('v')->greaterThan(lit(new DateInterval('PT1H')))->eval(row(['v' => null]), flow_context()), + ref('v') + ->greaterThan(lit(new DateInterval('PT1H'))) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), ); } public function test_greater_than_returns_null_for_null_array(): void { - static::assertNull(ref('v')->greaterThan(lit([1, 0]))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->greaterThan(lit([1, 0])) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_greater_than_strings(): void { $context = flow_context(); - static::assertTrue(ref('v')->greaterThan(lit('apple'))->eval(row(['v' => 'banana']), $context)); - static::assertFalse(ref('v')->greaterThan(lit('banana'))->eval(row(['v' => 'apple']), $context)); - static::assertFalse(ref('v')->greaterThan(lit('apple'))->eval(row(['v' => 'apple']), $context)); + static::assertTrue( + ref('v') + ->greaterThan(lit('apple')) + ->eval(array_to_row(['v' => 'banana'], schema(str_schema('v'))), $context), + ); + static::assertFalse( + ref('v') + ->greaterThan(lit('banana')) + ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), + ); + static::assertFalse( + ref('v') + ->greaterThan(lit('apple')) + ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), + ); } public function test_greater_than_throws_on_incompatible_types(): void @@ -129,17 +206,17 @@ public function test_greater_than_time_intervals(): void static::assertTrue( ref('v') ->greaterThan(lit(new DateInterval('PT1H'))) - ->eval(row(['v' => new DateInterval('PT5H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT5H')], schema(time_schema('v'))), $context), ); static::assertFalse( ref('v') ->greaterThan(lit(new DateInterval('PT5H'))) - ->eval(row(['v' => new DateInterval('PT1H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), ); static::assertFalse( ref('v') ->greaterThan(lit(new DateInterval('PT1H'))) - ->eval(row(['v' => new DateInterval('PT1H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreatestTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreatestTest.php index 0caf622fa9..4fd1c94590 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreatestTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreatestTest.php @@ -9,12 +9,12 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\greatest; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; final class GreatestTest extends FlowTestCase @@ -34,7 +34,7 @@ public function test_greatest_value(): void { $greatest = greatest(10, 20, ref('int'), 40); - static::assertSame(55, $greatest->eval(row(['int' => 55]), flow_context())); + static::assertSame(55, $greatest->eval(array_to_row(['int' => 55], schema(int_schema('int'))), flow_context())); } public function test_greatest_with_non_comparable_values(): void @@ -53,18 +53,24 @@ public function test_an_integer_and_a_string_column_have_no_common_type(): void public function test_nulls_are_skipped(): void { - static::assertSame(20, greatest(null, 20, ref('int'))->eval(row(['int' => 4]), flow_context())); + static::assertSame(20, greatest(null, 20, ref('int'))->eval(array_to_row([ + 'int' => 4, + ], schema(int_schema('int'))), flow_context())); } public function test_null_only_when_every_argument_is_null(): void { - static::assertNull(greatest(null, null)->eval(row(['int' => 4]), flow_context())); + static::assertNull(greatest(null, null)->eval(array_to_row([ + 'int' => 4, + ], schema(int_schema('int'))), flow_context())); } public function test_greatest_with_null(): void { $greatest = greatest(null, 20, ref('int'), 1257); - static::assertSame(1257, $greatest->eval(row(['int' => 55]), flow_context())); + static::assertSame(1257, $greatest->eval(array_to_row([ + 'int' => 55, + ], schema(int_schema('int'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorAllTest.php index 2bd4bd6988..d356e00b66 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorAllTest.php @@ -11,9 +11,12 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class HTMLQuerySelectorAllTest extends TestCase { @@ -21,7 +24,9 @@ final class HTMLQuerySelectorAllTest extends TestCase public function test_getting_element_for_older_versions(): void { $this->expectException(RequiredPHPVersionException::class); - ref('value')->htmlQuerySelectorAll('body div p')->eval(row(['value' => '']), flow_context()); + ref('value') + ->htmlQuerySelectorAll('body div p') + ->eval(array_to_row(['value' => ''], schema(str_schema('value'))), flow_context()); } #[RequiresPhp('>= 8.4.0')] @@ -32,7 +37,9 @@ public function test_getting_elements_for_given_path(): void '
foobar
', ); /** @var array $result */ - $result = ref('value')->htmlQuerySelectorAll('body div span')->eval(row(['value' => $html]), flow_context()); + $result = ref('value') + ->htmlQuerySelectorAll('body div span') + ->eval(array_to_row(['value' => $html], schema(html_schema('value'))), flow_context()); static::assertCount(1, $result); static::assertInstanceOf(Element::class, $result[0]); } @@ -44,7 +51,9 @@ public function test_getting_null_when_nothing_found(): void $html = HTMLDocument::createFromString( '
foobar
', ); - $result = ref('value')->htmlQuerySelectorAll('body div p')->eval(row(['value' => $html]), flow_context()); + $result = ref('value') + ->htmlQuerySelectorAll('body div p') + ->eval(array_to_row(['value' => $html], schema(html_schema('value'))), flow_context()); static::assertNull($result); } @@ -54,6 +63,8 @@ public function test_invalid_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected one of'); - ref('value')->htmlQuerySelectorAll('body div span')->eval(row(['value' => '']), flow_context()); + ref('value') + ->htmlQuerySelectorAll('body div span') + ->eval(array_to_row(['value' => ''], schema(str_schema('value'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorTest.php index fba9e741fe..d56e88559b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorTest.php @@ -11,9 +11,12 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class HTMLQuerySelectorTest extends TestCase { @@ -21,7 +24,9 @@ final class HTMLQuerySelectorTest extends TestCase public function test_getting_element_for_older_versions(): void { $this->expectException(RequiredPHPVersionException::class); - ref('value')->htmlQuerySelector('body div p')->eval(row(['value' => '']), flow_context()); + ref('value') + ->htmlQuerySelector('body div p') + ->eval(array_to_row(['value' => ''], schema(str_schema('value'))), flow_context()); } #[RequiresPhp('>= 8.4.0')] @@ -31,7 +36,9 @@ public function test_getting_elements_for_given_path(): void $html = HTMLDocument::createFromString( '
foobar
', ); - $result = ref('value')->htmlQuerySelector('body div span')->eval(row(['value' => $html]), flow_context()); + $result = ref('value') + ->htmlQuerySelector('body div span') + ->eval(array_to_row(['value' => $html], schema(html_schema('value'))), flow_context()); static::assertInstanceOf(Element::class, $result); } @@ -42,7 +49,9 @@ public function test_getting_null_when_nothing_found(): void $html = HTMLDocument::createFromString( '
foobar
', ); - $result = ref('value')->htmlQuerySelector('body div p')->eval(row(['value' => $html]), flow_context()); + $result = ref('value') + ->htmlQuerySelector('body div p') + ->eval(array_to_row(['value' => $html], schema(html_schema('value'))), flow_context()); static::assertNull($result); } @@ -52,6 +61,8 @@ public function test_invalid_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected one of'); - ref('value')->htmlQuerySelector('body div span')->eval(row(['value' => '']), flow_context()); + ref('value') + ->htmlQuerySelector('body div span') + ->eval(array_to_row(['value' => ''], schema(str_schema('value'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HashTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HashTest.php index 12dade91f1..34ff8482c9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HashTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HashTest.php @@ -8,12 +8,18 @@ use Flow\ETL\Hash\NativePHPHash; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\concat; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\hash; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_string; final class HashTest extends FlowTestCase { @@ -21,16 +27,18 @@ public function test_hashing_array_value(): void { static::assertSame('4450cf82dc53848e2bbe9798b70b0a6a', ref('value') ->hash() - ->eval(row(['value' => ['test']]), flow_context())); + ->eval(array_to_row(['value' => [ + 'test', + ]], schema(list_schema('value', type_list(type_string())))), flow_context())); } public function test_hashing_concat(): void { static::assertSame( NativePHPHash::xxh128('test_test'), - hash(concat(ref('value'), lit('_'), ref('value')), new NativePHPHash('xxh128'))->eval(row([ + hash(concat(ref('value'), lit('_'), ref('value')), new NativePHPHash('xxh128'))->eval(array_to_row([ 'value' => 'test', - ]), flow_context()), + ], schema(str_schema('value'))), flow_context()), ); } @@ -38,18 +46,24 @@ public function test_hashing_datetime(): void { static::assertSame('5347d10de38eb5570c044eb710a5120a', ref('value') ->hash() - ->eval(row(['value' => new DateTimeImmutable('2021-01-01')]), flow_context())); + ->eval(array_to_row([ + 'value' => new DateTimeImmutable('2021-01-01'), + ], schema(datetime_schema('value'))), flow_context())); } public function test_hashing_null_value(): void { - static::assertNull(ref('value')->hash()->eval(row(['value' => null]), flow_context())); + static::assertNull( + ref('value') + ->hash() + ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), + ); } public function test_hashing_string_value(): void { static::assertSame('6c78e0e3bd51d358d01e758642b85fb8', ref('value') ->hash() - ->eval(row(['value' => 'test']), flow_context())); + ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfLastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfLastTest.php index 78ce5d3b5a..ed766cc772 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfLastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfLastTest.php @@ -7,20 +7,29 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class IndexOfLastTest extends FlowTestCase { public function test_index_of_last_basic(): void { - static::assertSame(9, ref('str')->indexOfLast('l')->eval(row(['str' => 'hello world']), flow_context())); + static::assertSame(9, ref('str') + ->indexOfLast('l') + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context())); } public function test_index_of_last_not_found(): void { - static::assertNull(ref('str')->indexOfLast('x')->eval(row(['str' => 'hello world']), flow_context())); + static::assertNull( + ref('str') + ->indexOfLast('x') + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()), + ); } public function test_index_of_last_throws_on_null_needle(): void @@ -28,7 +37,15 @@ public function test_index_of_last_throws_on_null_needle(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('IndexOfLast function requires non-null string and needle'); - ref('str')->indexOfLast(ref('needle'))->eval(row(['str' => 'hello', 'needle' => null]), flow_context()); + ref('str') + ->indexOfLast(ref('needle')) + ->eval( + array_to_row( + ['str' => 'hello', 'needle' => null], + schema(str_schema('str'), str_schema('needle', nullable: true)), + ), + flow_context(), + ); } public function test_index_of_last_throws_on_null_string(): void @@ -36,13 +53,21 @@ public function test_index_of_last_throws_on_null_string(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('IndexOfLast function requires non-null string and needle'); - ref('str')->indexOfLast('l')->eval(row(['str' => null]), flow_context()); + ref('str') + ->indexOfLast('l') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_index_of_last_with_scalar_function_parameters(): void { static::assertSame(9, ref('str') ->indexOfLast(ref('needle'), ref('ignore_case')) - ->eval(row(['str' => 'hello world', 'needle' => 'L', 'ignore_case' => true]), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'L', 'ignore_case' => true], + schema(str_schema('str'), str_schema('needle'), bool_schema('ignore_case')), + ), + flow_context(), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfTest.php index ac82553fde..c416db60be 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfTest.php @@ -7,23 +7,33 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class IndexOfTest extends FlowTestCase { public function test_index_of(): void { - static::assertSame(5, ref('str')->indexOf('x', offset: 5)->eval(row(['str' => 'AbBAsxa']), flow_context())); + static::assertSame(5, ref('str') + ->indexOf('x', offset: 5) + ->eval(array_to_row(['str' => 'AbBAsxa'], schema(str_schema('str'))), flow_context())); static::assertSame(0, ref('str') ->indexOf('A', ignoreCase: true) - ->eval(row(['str' => 'abbbbb']), flow_context())); + ->eval(array_to_row(['str' => 'abbbbb'], schema(str_schema('str'))), flow_context())); - static::assertSame(5, ref('str')->indexOf('x', offset: 5)->eval(row(['str' => 'AbBAsxa']), flow_context())); + static::assertSame(5, ref('str') + ->indexOf('x', offset: 5) + ->eval(array_to_row(['str' => 'AbBAsxa'], schema(str_schema('str'))), flow_context())); - static::assertNull(ref('str')->indexOf('x', offset: 2)->eval(row(['str' => 'Abba']), flow_context())); + static::assertNull( + ref('str') + ->indexOf('x', offset: 2) + ->eval(array_to_row(['str' => 'Abba'], schema(str_schema('str'))), flow_context()), + ); } public function test_index_of_throws_on_null_needle(): void @@ -31,7 +41,15 @@ public function test_index_of_throws_on_null_needle(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('IndexOf function requires non-null string and needle'); - ref('str')->indexOf(ref('needle'))->eval(row(['str' => 'x', 'needle' => null]), flow_context()); + ref('str') + ->indexOf(ref('needle')) + ->eval( + array_to_row( + ['str' => 'x', 'needle' => null], + schema(str_schema('str'), str_schema('needle', nullable: true)), + ), + flow_context(), + ); } public function test_index_of_throws_on_null_string(): void @@ -39,6 +57,8 @@ public function test_index_of_throws_on_null_string(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('IndexOf function requires non-null string and needle'); - ref('str')->indexOf('x')->eval(row(['str' => null]), flow_context()); + ref('str') + ->indexOf('x') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsEmptyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsEmptyTest.php index a5f2299c82..dd336c3153 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsEmptyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsEmptyTest.php @@ -6,29 +6,41 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class IsEmptyTest extends FlowTestCase { public function test_is_empty_empty_string(): void { - static::assertTrue(ref('str')->isEmpty()->eval(row(['str' => '']), flow_context())); + static::assertTrue( + ref('str')->isEmpty()->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()), + ); } public function test_is_empty_non_empty_string(): void { - static::assertFalse(ref('str')->isEmpty()->eval(row(['str' => 'hello']), flow_context())); + static::assertFalse( + ref('str')->isEmpty()->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), + ); } public function test_is_empty_returns_null_for_null_input(): void { - static::assertNull(ref('str')->isEmpty()->eval(row(['str' => null]), flow_context())); + static::assertNull( + ref('str') + ->isEmpty() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()), + ); } public function test_is_empty_single_character_string(): void { - static::assertFalse(ref('str')->isEmpty()->eval(row(['str' => 'a']), flow_context())); + static::assertFalse( + ref('str')->isEmpty()->eval(array_to_row(['str' => 'a'], schema(str_schema('str'))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php index 18de9f64d1..9bb68873b0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php @@ -9,10 +9,12 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class IsInTest extends FlowTestCase { @@ -27,7 +29,7 @@ public function test_is_in_accepts_a_container_haystack_without_a_single_element ->returns() ->toString(), ); - static::assertTrue(lit('a')->isIn(lit([1, 'a']))->eval(row([]), flow_context())); + static::assertTrue(lit('a')->isIn(lit([1, 'a']))->eval(array_to_row([], schema()), flow_context())); } public function test_is_in_matches_two_equal_datetimes(): void @@ -36,7 +38,7 @@ public function test_is_in_matches_two_equal_datetimes(): void static::assertTrue( lit(new DateTimeImmutable('2024-01-01 10:00:00')) ->isIn(lit([new DateTimeImmutable('2024-01-01 10:00:00')])) - ->eval(row([]), flow_context()), + ->eval(array_to_row([], schema()), flow_context()), ); } @@ -44,22 +46,26 @@ public function test_is_in_does_not_match_two_equal_date_intervals(): void { // Equals::eval() has a DateInterval arm and IsIn deliberately does not static::assertTrue( - lit(new DateInterval('PT1H'))->equals(lit(new DateInterval('PT60M')))->eval(row([]), flow_context()), + lit(new DateInterval('PT1H')) + ->equals(lit(new DateInterval('PT60M'))) + ->eval(array_to_row([], schema()), flow_context()), ); static::assertFalse( - lit(new DateInterval('PT1H'))->isIn(lit([new DateInterval('PT60M')]))->eval(row([]), flow_context()), + lit(new DateInterval('PT1H')) + ->isIn(lit([new DateInterval('PT60M')])) + ->eval(array_to_row([], schema()), flow_context()), ); } public function test_is_in_over_an_empty_haystack(): void { static::assertSame('boolean', lit('a')->isIn(lit([]))->returns()->toString()); - static::assertFalse(lit('a')->isIn(lit([]))->eval(row([]), flow_context())); + static::assertFalse(lit('a')->isIn(lit([]))->eval(array_to_row([], schema()), flow_context())); } public function test_is_in_agrees_with_equals_on_numeric_operands(): void { - $row = row(['a' => '1']); + $row = array_to_row(['a' => '1'], schema(str_schema('a'))); static::assertTrue(ref('a')->equals(lit(1))->eval($row, flow_context())); static::assertTrue(ref('a')->isIn(lit([1]))->eval($row, flow_context())); @@ -77,26 +83,26 @@ public function test_is_in_refuses_an_incomparable_element_type(): void public function test_a_match_beats_a_null_element(): void { - static::assertTrue(lit(5)->isIn(lit([1, null, 5]))->eval(row([]), flow_context())); + static::assertTrue(lit(5)->isIn(lit([1, null, 5]))->eval(array_to_row([], schema()), flow_context())); } public function test_no_match_with_a_null_element_is_null(): void { - static::assertNull(lit(7)->isIn(lit([1, null, 5]))->eval(row([]), flow_context())); + static::assertNull(lit(7)->isIn(lit([1, null, 5]))->eval(array_to_row([], schema()), flow_context())); } public function test_no_match_without_a_null_element_is_false(): void { - static::assertFalse(lit(7)->isIn(lit([1, 3, 5]))->eval(row([]), flow_context())); + static::assertFalse(lit(7)->isIn(lit([1, 3, 5]))->eval(array_to_row([], schema()), flow_context())); } public function test_a_null_needle_is_null(): void { - static::assertNull(lit(null)->isIn(lit([1, 3, 5]))->eval(row([]), flow_context())); + static::assertNull(lit(null)->isIn(lit([1, 3, 5]))->eval(array_to_row([], schema()), flow_context())); } public function test_a_null_haystack_is_null(): void { - static::assertNull(lit(5)->isIn(lit(null))->eval(row(['x' => []]), flow_context())); + static::assertNull(lit(5)->isIn(lit(null))->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsUtf8Test.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsUtf8Test.php index 85052e04ae..bd806a53a4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsUtf8Test.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsUtf8Test.php @@ -6,21 +6,33 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class IsUtf8Test extends FlowTestCase { public function test_is_utf8_returns_null(): void { - static::assertNull(ref('str')->isUtf8()->eval(row(['str' => null]), flow_context())); + static::assertNull( + ref('str') + ->isUtf8() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()), + ); } public function test_is_utf_8(): void { - static::assertTrue(ref('str')->isUtf8()->eval(row(['str' => 'Lorem Ipsum']), flow_context())); + static::assertTrue( + ref('str') + ->isUtf8() + ->eval(array_to_row(['str' => 'Lorem Ipsum'], schema(str_schema('str'))), flow_context()), + ); - static::assertFalse(ref('str')->isUtf8()->eval(row(['str' => "\xc3\x28"]), flow_context())); + static::assertFalse( + ref('str')->isUtf8()->eval(array_to_row(['str' => "\xc3\x28"], schema(str_schema('str'))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonDecodeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonDecodeTest.php index eaa65948a9..95490ccbca 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonDecodeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonDecodeTest.php @@ -7,9 +7,12 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class JsonDecodeTest extends FlowTestCase { @@ -17,7 +20,9 @@ public function test_json_decode_expression(): void { static::assertSame( ['value' => 1], - ref('value')->jsonDecode()->eval(row(['value' => '{"value": 1}']), flow_context()), + ref('value') + ->jsonDecode() + ->eval(array_to_row(['value' => '{"value": 1}'], schema(str_schema('value'))), flow_context()), ); } @@ -26,7 +31,9 @@ public function test_json_decode_expression_with_invalid_json(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('JsonDecode error: Syntax error'); - ref('value')->jsonDecode()->eval(row(['value' => '{"value": 1']), flow_context()); + ref('value') + ->jsonDecode() + ->eval(array_to_row(['value' => '{"value": 1'], schema(str_schema('value'))), flow_context()); } public function test_json_decode_on_non_json_value(): void @@ -34,7 +41,7 @@ public function test_json_decode_on_non_json_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('JsonDecode function requires string, array, or Json value'); - ref('value')->jsonDecode()->eval(row(['value' => 125]), flow_context()); + ref('value')->jsonDecode()->eval(array_to_row(['value' => 125], schema(int_schema('value'))), flow_context()); } public function test_json_decode_on_scalar_json_throws(): void @@ -44,6 +51,6 @@ public function test_json_decode_on_scalar_json_throws(): void 'JsonDecode function requires JSON that decodes to an array, cast scalar JSON instead', ); - ref('value')->jsonDecode()->eval(row(['value' => '5']), flow_context()); + ref('value')->jsonDecode()->eval(array_to_row(['value' => '5'], schema(str_schema('value'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonEncodeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonEncodeTest.php index 83460a5dd2..a398cb67ae 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonEncodeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonEncodeTest.php @@ -8,9 +8,17 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Value\Json; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; final class JsonEncodeTest extends FlowTestCase { @@ -18,7 +26,9 @@ public function test_json_encode_on_datetime(): void { $result = ref('value') ->jsonEncode() - ->eval(row(['value' => new DateTimeImmutable('2021-01-01')]), flow_context()); + ->eval(array_to_row([ + 'value' => new DateTimeImmutable('2021-01-01'), + ], schema(datetime_schema('value'))), flow_context()); static::assertInstanceOf(Json::class, $result); static::assertSame( @@ -29,17 +39,25 @@ public function test_json_encode_on_datetime(): void public function test_json_encode_on_integer(): void { - static::assertSame('125', ref('value')->jsonEncode()->eval(row(['value' => 125]), flow_context())); + static::assertSame('125', ref('value') + ->jsonEncode() + ->eval(array_to_row(['value' => 125], schema(int_schema('value'))), flow_context())); } public function test_json_encode_on_string(): void { - static::assertSame('"test"', ref('value')->jsonEncode()->eval(row(['value' => 'test']), flow_context())); + static::assertSame('"test"', ref('value') + ->jsonEncode() + ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); } public function test_json_encode_on_valid_associative_array(): void { - $result = ref('value')->jsonEncode()->eval(row(['value' => ['value' => 1]]), flow_context()); + $result = ref('value') + ->jsonEncode() + ->eval(array_to_row(['value' => [ + 'value' => 1, + ]], schema(map_schema('value', type_map(type_string(), type_integer())))), flow_context()); static::assertInstanceOf(Json::class, $result); static::assertSame('{"value":1}', $result->toString()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LastTest.php index bc3496b9a5..2d17099a91 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LastTest.php @@ -7,12 +7,13 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\last; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class LastTest extends FlowTestCase { @@ -25,11 +26,13 @@ public function test_aggregation_last_value(): void { $aggregator = last(ref('int')); - $aggregator->aggregate(row(['int' => '10']), flow_context()); - $aggregator->aggregate(row(['int' => '20']), flow_context()); - $aggregator->aggregate(row(['int' => '55']), flow_context()); - $aggregator->aggregate(row(['int' => '25']), flow_context()); - $aggregator->aggregate(row(['not_int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'not_int' => null, + ], schema(str_schema('not_int', nullable: true))), flow_context()); static::assertSame('25', $aggregator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LeastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LeastTest.php index e05ff3df7c..70f0c7ee62 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LeastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LeastTest.php @@ -9,12 +9,12 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\least; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; final class LeastTest extends FlowTestCase @@ -46,18 +46,22 @@ public function test_an_integer_and_a_string_column_have_no_common_type(): void public function test_null_only_when_every_argument_is_null(): void { - static::assertNull(least(null, null)->eval(row(['int' => 4]), flow_context())); + static::assertNull(least(null, null)->eval(array_to_row([ + 'int' => 4, + ], schema(int_schema('int'))), flow_context())); } public function test_least_value(): void { $lest = least(10, 20, ref('int'), 40); - static::assertSame(10, $lest->eval(row(['int' => 55]), flow_context())); + static::assertSame(10, $lest->eval(array_to_row(['int' => 55], schema(int_schema('int'))), flow_context())); } public function test_least_with_null(): void { - static::assertSame(4, least(null, 20, ref('int'), 1257)->eval(row(['int' => 4]), flow_context())); + static::assertSame(4, least(null, 20, ref('int'), 1257)->eval(array_to_row([ + 'int' => 4, + ], schema(int_schema('int'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanEqualTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanEqualTest.php index 7cdd3e2696..948d63f315 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanEqualTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanEqualTest.php @@ -9,10 +9,19 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; final class LessThanEqualTest extends FlowTestCase { @@ -20,9 +29,21 @@ public function test_less_than_equal_arrays(): void { $context = flow_context(); - static::assertTrue(ref('v')->lessThanEqual(lit([1, 9]))->eval(row(['v' => [1, 0]]), $context)); - static::assertTrue(ref('v')->lessThanEqual(lit([1, 0]))->eval(row(['v' => [1, 0]]), $context)); - static::assertFalse(ref('v')->lessThanEqual(lit([1, 0]))->eval(row(['v' => [1, 9]]), $context)); + static::assertTrue( + ref('v') + ->lessThanEqual(lit([1, 9])) + ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), + ); + static::assertTrue( + ref('v') + ->lessThanEqual(lit([1, 0])) + ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), + ); + static::assertFalse( + ref('v') + ->lessThanEqual(lit([1, 0])) + ->eval(array_to_row(['v' => [1, 9]], schema(list_schema('v', type_list(type_integer())))), $context), + ); } public function test_less_than_equal_datetimes(): void @@ -32,17 +53,23 @@ public function test_less_than_equal_datetimes(): void static::assertTrue( ref('v') ->lessThanEqual(lit(new DateTimeImmutable('2024-06-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-01-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-01-01'), + ], schema(datetime_schema('v'))), $context), ); static::assertTrue( ref('v') ->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-01-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-01-01'), + ], schema(datetime_schema('v'))), $context), ); static::assertFalse( ref('v') ->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-06-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-06-01'), + ], schema(datetime_schema('v'))), $context), ); } @@ -50,53 +77,89 @@ public function test_less_than_equal_floats(): void { $context = flow_context(); - static::assertTrue(ref('v')->lessThanEqual(lit(2.5))->eval(row(['v' => 1.5]), $context)); - static::assertTrue(ref('v')->lessThanEqual(lit(1.5))->eval(row(['v' => 1.5]), $context)); - static::assertFalse(ref('v')->lessThanEqual(lit(1.5))->eval(row(['v' => 2.5]), $context)); + static::assertTrue( + ref('v')->lessThanEqual(lit(2.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), + ); + static::assertTrue( + ref('v')->lessThanEqual(lit(1.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->lessThanEqual(lit(1.5))->eval(array_to_row(['v' => 2.5], schema(float_schema('v'))), $context), + ); } public function test_less_than_equal_integers(): void { $context = flow_context(); - static::assertTrue(ref('v')->lessThanEqual(lit(20))->eval(row(['v' => 10]), $context)); - static::assertTrue(ref('v')->lessThanEqual(lit(10))->eval(row(['v' => 10]), $context)); - static::assertFalse(ref('v')->lessThanEqual(lit(10))->eval(row(['v' => 20]), $context)); + static::assertTrue( + ref('v')->lessThanEqual(lit(20))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), + ); + static::assertTrue( + ref('v')->lessThanEqual(lit(10))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->lessThanEqual(lit(10))->eval(array_to_row(['v' => 20], schema(int_schema('v'))), $context), + ); } public function test_less_than_equal_returns_null_for_null_array(): void { - static::assertNull(ref('v')->lessThanEqual(lit([1, 0]))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->lessThanEqual(lit([1, 0])) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_less_than_equal_returns_null_for_null_datetime(): void { static::assertNull( - ref('v')->lessThanEqual(lit(new DateTimeImmutable('2024-01-01')))->eval(row(['v' => null]), flow_context()), + ref('v') + ->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), ); } public function test_less_than_equal_returns_null_for_null_left(): void { - static::assertNull(ref('v')->lessThanEqual(lit(10))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->lessThanEqual(lit(10)) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_less_than_equal_returns_null_for_null_right(): void { static::assertNull( - ref('v')->lessThanEqual(ref('other'))->eval(row(['v' => 10, 'other' => null]), flow_context()), + ref('v') + ->lessThanEqual(ref('other')) + ->eval( + array_to_row( + ['v' => 10, 'other' => null], + schema(int_schema('v'), str_schema('other', nullable: true)), + ), + flow_context(), + ), ); } public function test_less_than_equal_returns_null_for_null_string(): void { - static::assertNull(ref('v')->lessThanEqual(lit('a'))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->lessThanEqual(lit('a')) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_less_than_equal_returns_null_for_null_time_interval(): void { static::assertNull( - ref('v')->lessThanEqual(lit(new DateInterval('PT1H')))->eval(row(['v' => null]), flow_context()), + ref('v') + ->lessThanEqual(lit(new DateInterval('PT1H'))) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), ); } @@ -104,9 +167,21 @@ public function test_less_than_equal_strings(): void { $context = flow_context(); - static::assertTrue(ref('v')->lessThanEqual(lit('banana'))->eval(row(['v' => 'apple']), $context)); - static::assertTrue(ref('v')->lessThanEqual(lit('apple'))->eval(row(['v' => 'apple']), $context)); - static::assertFalse(ref('v')->lessThanEqual(lit('apple'))->eval(row(['v' => 'banana']), $context)); + static::assertTrue( + ref('v') + ->lessThanEqual(lit('banana')) + ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), + ); + static::assertTrue( + ref('v') + ->lessThanEqual(lit('apple')) + ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), + ); + static::assertFalse( + ref('v') + ->lessThanEqual(lit('apple')) + ->eval(array_to_row(['v' => 'banana'], schema(str_schema('v'))), $context), + ); } public function test_less_than_equal_throws_on_incompatible_types(): void @@ -123,17 +198,17 @@ public function test_less_than_equal_time_intervals(): void static::assertTrue( ref('v') ->lessThanEqual(lit(new DateInterval('PT5H'))) - ->eval(row(['v' => new DateInterval('PT1H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), ); static::assertTrue( ref('v') ->lessThanEqual(lit(new DateInterval('PT1H'))) - ->eval(row(['v' => new DateInterval('PT1H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), ); static::assertFalse( ref('v') ->lessThanEqual(lit(new DateInterval('PT1H'))) - ->eval(row(['v' => new DateInterval('PT5H')]), $context), + ->eval(array_to_row(['v' => new DateInterval('PT5H')], schema(time_schema('v'))), $context), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanTest.php index ea78658511..36a07c51fd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanTest.php @@ -9,10 +9,19 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; final class LessThanTest extends FlowTestCase { @@ -20,9 +29,21 @@ public function test_less_than_arrays(): void { $context = flow_context(); - static::assertTrue(ref('v')->lessThan(lit([1, 9]))->eval(row(['v' => [1, 0]]), $context)); - static::assertFalse(ref('v')->lessThan(lit([1, 0]))->eval(row(['v' => [1, 9]]), $context)); - static::assertFalse(ref('v')->lessThan(lit([1, 0]))->eval(row(['v' => [1, 0]]), $context)); + static::assertTrue( + ref('v') + ->lessThan(lit([1, 9])) + ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), + ); + static::assertFalse( + ref('v') + ->lessThan(lit([1, 0])) + ->eval(array_to_row(['v' => [1, 9]], schema(list_schema('v', type_list(type_integer())))), $context), + ); + static::assertFalse( + ref('v') + ->lessThan(lit([1, 0])) + ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), + ); } public function test_less_than_datetimes(): void @@ -32,17 +53,23 @@ public function test_less_than_datetimes(): void static::assertTrue( ref('v') ->lessThan(lit(new DateTimeImmutable('2024-06-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-01-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-01-01'), + ], schema(datetime_schema('v'))), $context), ); static::assertFalse( ref('v') ->lessThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-06-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-06-01'), + ], schema(datetime_schema('v'))), $context), ); static::assertFalse( ref('v') ->lessThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(row(['v' => new DateTimeImmutable('2024-01-01')]), $context), + ->eval(array_to_row([ + 'v' => new DateTimeImmutable('2024-01-01'), + ], schema(datetime_schema('v'))), $context), ); } @@ -50,59 +77,105 @@ public function test_less_than_floats(): void { $context = flow_context(); - static::assertTrue(ref('v')->lessThan(lit(2.5))->eval(row(['v' => 1.5]), $context)); - static::assertFalse(ref('v')->lessThan(lit(1.5))->eval(row(['v' => 2.5]), $context)); - static::assertFalse(ref('v')->lessThan(lit(1.5))->eval(row(['v' => 1.5]), $context)); + static::assertTrue( + ref('v')->lessThan(lit(2.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->lessThan(lit(1.5))->eval(array_to_row(['v' => 2.5], schema(float_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->lessThan(lit(1.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), + ); } public function test_less_than_integers(): void { $context = flow_context(); - static::assertTrue(ref('v')->lessThan(lit(20))->eval(row(['v' => 10]), $context)); - static::assertFalse(ref('v')->lessThan(lit(10))->eval(row(['v' => 20]), $context)); - static::assertFalse(ref('v')->lessThan(lit(10))->eval(row(['v' => 10]), $context)); + static::assertTrue( + ref('v')->lessThan(lit(20))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->lessThan(lit(10))->eval(array_to_row(['v' => 20], schema(int_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->lessThan(lit(10))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), + ); } public function test_less_than_returns_null_for_null_array(): void { - static::assertNull(ref('v')->lessThan(lit([1, 0]))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->lessThan(lit([1, 0])) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_less_than_returns_null_for_null_datetime(): void { static::assertNull( - ref('v')->lessThan(lit(new DateTimeImmutable('2024-01-01')))->eval(row(['v' => null]), flow_context()), + ref('v') + ->lessThan(lit(new DateTimeImmutable('2024-01-01'))) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), ); } public function test_less_than_returns_null_for_null_left(): void { - static::assertNull(ref('v')->lessThan(lit(10))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->lessThan(lit(10)) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_less_than_returns_null_for_null_right(): void { - static::assertNull(ref('v')->lessThan(ref('other'))->eval(row(['v' => 10, 'other' => null]), flow_context())); + static::assertNull( + ref('v') + ->lessThan(ref('other')) + ->eval( + array_to_row( + ['v' => 10, 'other' => null], + schema(int_schema('v'), str_schema('other', nullable: true)), + ), + flow_context(), + ), + ); } public function test_less_than_returns_null_for_null_string(): void { - static::assertNull(ref('v')->lessThan(lit('a'))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->lessThan(lit('a')) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_less_than_returns_null_for_null_time_interval(): void { - static::assertNull(ref('v')->lessThan(lit(new DateInterval('PT1H')))->eval(row(['v' => null]), flow_context())); + static::assertNull( + ref('v') + ->lessThan(lit(new DateInterval('PT1H'))) + ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), + ); } public function test_less_than_strings(): void { $context = flow_context(); - static::assertTrue(ref('v')->lessThan(lit('banana'))->eval(row(['v' => 'apple']), $context)); - static::assertFalse(ref('v')->lessThan(lit('apple'))->eval(row(['v' => 'banana']), $context)); - static::assertFalse(ref('v')->lessThan(lit('apple'))->eval(row(['v' => 'apple']), $context)); + static::assertTrue( + ref('v')->lessThan(lit('banana'))->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->lessThan(lit('apple'))->eval(array_to_row(['v' => 'banana'], schema(str_schema('v'))), $context), + ); + static::assertFalse( + ref('v')->lessThan(lit('apple'))->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), + ); } public function test_less_than_throws_on_incompatible_types(): void @@ -117,13 +190,19 @@ public function test_less_than_time_intervals(): void $context = flow_context(); static::assertTrue( - ref('v')->lessThan(lit(new DateInterval('PT5H')))->eval(row(['v' => new DateInterval('PT1H')]), $context), + ref('v') + ->lessThan(lit(new DateInterval('PT5H'))) + ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), ); static::assertFalse( - ref('v')->lessThan(lit(new DateInterval('PT1H')))->eval(row(['v' => new DateInterval('PT5H')]), $context), + ref('v') + ->lessThan(lit(new DateInterval('PT1H'))) + ->eval(array_to_row(['v' => new DateInterval('PT5H')], schema(time_schema('v'))), $context), ); static::assertFalse( - ref('v')->lessThan(lit(new DateInterval('PT1H')))->eval(row(['v' => new DateInterval('PT1H')]), $context), + ref('v') + ->lessThan(lit(new DateInterval('PT1H'))) + ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ListSelectTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ListSelectTest.php index c60de58b36..8be1555b0c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ListSelectTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ListSelectTest.php @@ -9,16 +9,17 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_mixed; use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; final class ListSelectTest extends FlowTestCase { @@ -57,13 +58,13 @@ public function test_selecting_from_a_list_of_scalars_declares_null_element_type public function test_selecting_non_existing_value_from_list_using_alias(): void { - $list = row([ + $list = array_to_row([ 'list' => [ ['id' => 1, 'name' => 'test'], ['id' => 2, 'name' => 'test2'], ['id' => 3, 'name' => 'test3'], ], - ]); + ], schema(list_schema('list', type_list(type_structure(['id' => type_integer(), 'name' => type_string()]))))); static::assertEquals( [ @@ -77,13 +78,13 @@ public function test_selecting_non_existing_value_from_list_using_alias(): void public function test_selecting_value_from_list(): void { - $list = row([ + $list = array_to_row([ 'list' => [ ['id' => 1, 'name' => 'test'], ['id' => 2, 'name' => 'test2'], ['id' => 3, 'name' => 'test3'], ], - ]); + ], schema(list_schema('list', type_list(type_structure(['id' => type_integer(), 'name' => type_string()]))))); static::assertEquals( [ @@ -97,13 +98,13 @@ public function test_selecting_value_from_list(): void public function test_selecting_value_from_list_using_alias(): void { - $list = row([ + $list = array_to_row([ 'list' => [ ['id' => 1, 'name' => 'test'], ['id' => 2, 'name' => 'test2'], ['id' => 3, 'name' => 'test3'], ], - ]); + ], schema(list_schema('list', type_list(type_structure(['id' => type_integer(), 'name' => type_string()]))))); static::assertEquals( [ @@ -117,12 +118,12 @@ public function test_selecting_value_from_list_using_alias(): void public function test_selecting_value_from_simple_list(): void { - $list = row(['list' => [ + $list = array_to_row(['list' => [ 'a', 'b', 'c', 'd', - ]]); + ]], schema(list_schema('list', type_list(type_string())))); static::assertEquals( [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LogicalFunctionsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LogicalFunctionsTest.php index e4dccbead4..cdb7696491 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LogicalFunctionsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LogicalFunctionsTest.php @@ -6,10 +6,12 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class LogicalFunctionsTest extends FlowTestCase { @@ -19,25 +21,25 @@ public function test_logical_operations(): void ref('id') ->isEven() ->andNot(ref('id')->equals(lit(1))) - ->eval(row(['id' => 1]), flow_context()), + ->eval(array_to_row(['id' => 1], schema(int_schema('id'))), flow_context()), ); static::assertTrue( ref('id') ->isOdd() ->and(ref('id')->equals(lit(1))) - ->eval(row(['id' => 1]), flow_context()), + ->eval(array_to_row(['id' => 1], schema(int_schema('id'))), flow_context()), ); static::assertTrue( ref('id') ->isEven() ->or(ref('id')->equals(lit(1))) - ->eval(row(['id' => 1]), flow_context()), + ->eval(array_to_row(['id' => 1], schema(int_schema('id'))), flow_context()), ); static::assertFalse( ref('id') ->isOdd() ->andNot(ref('id')->equals(lit(1))) - ->eval(row(['id' => 1]), flow_context()), + ->eval(array_to_row(['id' => 1], schema(int_schema('id'))), flow_context()), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MatchCasesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MatchCasesTest.php index 44724e3b76..f99f30ac27 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MatchCasesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MatchCasesTest.php @@ -7,13 +7,15 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\match_cases; use function Flow\ETL\DSL\match_condition; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class MatchCasesTest extends FlowTestCase { @@ -24,7 +26,7 @@ public function test_no_matching_case_without_a_default_still_throws(): void match_cases([ match_condition(ref('string')->contains('_'), ref('string')->strReplace('_', ' ')), - ])->eval(row(['string' => 'weirdstring']), flow_context()); + ])->eval(array_to_row(['string' => 'weirdstring'], schema(str_schema('string'))), flow_context()); } public function test_case_match(): void @@ -34,8 +36,12 @@ public function test_case_match(): void match_condition(ref('string')->contains('-'), ref('string')->strReplace('-', ' ')), ]); - static::assertSame('this is slug', $match->eval(row(['string' => 'this-is-slug']), flow_context())); - static::assertSame('this is slug', $match->eval(row(['string' => 'this_is_slug']), flow_context())); + static::assertSame('this is slug', $match->eval(array_to_row([ + 'string' => 'this-is-slug', + ], schema(str_schema('string'))), flow_context())); + static::assertSame('this is slug', $match->eval(array_to_row([ + 'string' => 'this_is_slug', + ], schema(str_schema('string'))), flow_context())); } public function test_not_matching_anything_in_strict_mode(): void @@ -51,7 +57,7 @@ public function test_not_matching_anything_in_strict_mode(): void ]); $context = flow_context(config()); - $match->eval(row(['string' => 'weirdstring']), $context); + $match->eval(array_to_row(['string' => 'weirdstring'], schema(str_schema('string'))), $context); } public function test_not_matching_anything_with_default(): void @@ -61,6 +67,8 @@ public function test_not_matching_anything_with_default(): void match_condition(ref('string')->contains('-'), ref('string')->strReplace('-', ' ')), ], default: lit('normal string')); - static::assertEquals('normal string', $match->eval(row(['string' => 'weirdstring']), flow_context())); + static::assertEquals('normal string', $match->eval(array_to_row([ + 'string' => 'weirdstring', + ], schema(str_schema('string'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MathTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MathTest.php index a2396cde0c..0f72c2871f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MathTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MathTest.php @@ -13,30 +13,33 @@ use Flow\ETL\Function\Round; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class MathTest extends FlowTestCase { public function test_divide(): void { - $row = row(['a' => 100, 'b' => 10]); + $row = array_to_row(['a' => 100, 'b' => 10], schema(int_schema('a'), int_schema('b'))); static::assertSame(10.0, (new Divide(ref('a'), ref('b')))->eval($row, flow_context())); } public function test_minus(): void { - $row = row(['a' => 100, 'b' => 100]); + $row = array_to_row(['a' => 100, 'b' => 100], schema(int_schema('a'), int_schema('b'))); static::assertSame(0, (new Minus(ref('a'), ref('b')))->eval($row, flow_context())); } public function test_modulo(): void { - $row = row(['a' => 110, 'b' => 100]); + $row = array_to_row(['a' => 110, 'b' => 100], schema(int_schema('a'), int_schema('b'))); static::assertSame(10, (new Mod(ref('a'), ref('b')))->eval($row, flow_context())); } @@ -47,33 +50,33 @@ public function test_multiple_operations(): void ->plus(lit(100)) ->plus(lit(100)) ->minus(ref('b')) - ->eval(row(['a' => 100, 'b' => 100]), flow_context())); + ->eval(array_to_row(['a' => 100, 'b' => 100], schema(int_schema('a'), int_schema('b'))), flow_context())); } public function test_multiply(): void { - $row = row(['a' => 100, 'b' => 100]); + $row = array_to_row(['a' => 100, 'b' => 100], schema(int_schema('a'), int_schema('b'))); static::assertSame(10_000, (new Multiply(ref('a'), ref('b')))->eval($row, flow_context())); } public function test_plus(): void { - $row = row(['a' => 100, 'b' => 100]); + $row = array_to_row(['a' => 100, 'b' => 100], schema(int_schema('a'), int_schema('b'))); static::assertSame(200, (new Plus(ref('a'), ref('b')))->eval($row, flow_context())); } public function test_power(): void { - $row = row(['a' => 1, 'b' => 2]); + $row = array_to_row(['a' => 1, 'b' => 2], schema(int_schema('a'), int_schema('b'))); static::assertSame(1, (new Power(ref('a'), ref('b')))->eval($row, flow_context())); } public function test_round(): void { - $row = row(['a' => 1.009, 'b' => 2]); + $row = array_to_row(['a' => 1.009, 'b' => 2], schema(float_schema('a'), int_schema('b'))); static::assertSame(1.01, (new Round(ref('a'), ref('b')))->eval($row, flow_context())); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MaxTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MaxTest.php index 1402e0b125..f45a939752 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MaxTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MaxTest.php @@ -8,12 +8,15 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\max; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_datetime; final class MaxTest extends FlowTestCase @@ -27,11 +30,13 @@ public function test_aggregation_max_from_numeric_values(): void { $aggregator = max(ref('int')); - $aggregator->aggregate(row(['int' => '10']), flow_context()); - $aggregator->aggregate(row(['int' => '20']), flow_context()); - $aggregator->aggregate(row(['int' => '55']), flow_context()); - $aggregator->aggregate(row(['int' => '25']), flow_context()); - $aggregator->aggregate(row(['not_int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'not_int' => null, + ], schema(str_schema('not_int', nullable: true))), flow_context()); static::assertSame(55.0, $aggregator->value()); } @@ -40,10 +45,12 @@ public function test_aggregation_max_including_null_value(): void { $aggregator = max(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'int' => null, + ], schema(int_schema('int', nullable: true))), flow_context()); static::assertSame(30.0, $aggregator->value()); } @@ -52,10 +59,18 @@ public function test_aggregation_max_with_datetime_values(): void { $aggregator = max(ref('datetime')); - $aggregator->aggregate(row(['datetime' => type_datetime()->cast('2021-01-01 00:00:00')]), flow_context()); - $aggregator->aggregate(row(['datetime' => type_datetime()->cast('2021-01-02 00:00:00')]), flow_context()); - $aggregator->aggregate(row(['datetime' => type_datetime()->cast('2021-01-03 00:00:00')]), flow_context()); - $aggregator->aggregate(row(['datetime' => type_datetime()->cast('2021-01-04 00:00:00')]), flow_context()); + $aggregator->aggregate(array_to_row([ + 'datetime' => type_datetime()->cast('2021-01-01 00:00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'datetime' => type_datetime()->cast('2021-01-02 00:00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'datetime' => type_datetime()->cast('2021-01-03 00:00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'datetime' => type_datetime()->cast('2021-01-04 00:00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); static::assertEquals(new DateTimeImmutable('2021-01-04 00:00:00'), $aggregator->value()); } @@ -64,10 +79,10 @@ public function test_aggregation_max_with_float_result(): void { $aggregator = max(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30.5]), flow_context()); - $aggregator->aggregate(row(['int' => 25]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30.5], schema(float_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); static::assertSame(30.5, $aggregator->value()); } @@ -76,10 +91,10 @@ public function test_aggregation_max_with_integer_result(): void { $aggregator = max(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => 40]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 40], schema(int_schema('int'))), flow_context()); static::assertSame(40.0, $aggregator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinTest.php index 3898729388..1739f021c3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinTest.php @@ -8,12 +8,15 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_datetime; final class MinTest extends FlowTestCase @@ -27,7 +30,7 @@ public function test_the_output_suffix_survives_an_immutable_reference(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); static::assertSame('int_min', $aggregator->outputName()); } @@ -36,11 +39,13 @@ public function test_aggregation_min_from_numeric_values(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(row(['int' => '10']), flow_context()); - $aggregator->aggregate(row(['int' => '20']), flow_context()); - $aggregator->aggregate(row(['int' => '55']), flow_context()); - $aggregator->aggregate(row(['int' => '25']), flow_context()); - $aggregator->aggregate(row(['not_int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'not_int' => null, + ], schema(str_schema('not_int', nullable: true))), flow_context()); static::assertSame(10.0, $aggregator->value()); } @@ -49,10 +54,12 @@ public function test_aggregation_min_including_null_value(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'int' => null, + ], schema(int_schema('int', nullable: true))), flow_context()); static::assertSame(10.0, $aggregator->value()); } @@ -61,10 +68,18 @@ public function test_aggregation_min_with_datetime_values(): void { $aggregator = min(ref('datetime')); - $aggregator->aggregate(row(['datetime' => type_datetime()->cast('2021-01-01 00:00:00')]), flow_context()); - $aggregator->aggregate(row(['datetime' => type_datetime()->cast('2021-01-02 00:00:00')]), flow_context()); - $aggregator->aggregate(row(['datetime' => type_datetime()->cast('2021-01-03 00:00:00')]), flow_context()); - $aggregator->aggregate(row(['datetime' => type_datetime()->cast('2021-01-04 00:00:00')]), flow_context()); + $aggregator->aggregate(array_to_row([ + 'datetime' => type_datetime()->cast('2021-01-01 00:00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'datetime' => type_datetime()->cast('2021-01-02 00:00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'datetime' => type_datetime()->cast('2021-01-03 00:00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'datetime' => type_datetime()->cast('2021-01-04 00:00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); static::assertEquals(new DateTimeImmutable('2021-01-01 00:00:00'), $aggregator->value()); } @@ -73,10 +88,10 @@ public function test_aggregation_min_with_float_result(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(row(['int' => 10.25]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 305]), flow_context()); - $aggregator->aggregate(row(['int' => 25]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10.25], schema(float_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 305], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); static::assertSame(10.25, $aggregator->value()); } @@ -85,10 +100,10 @@ public function test_aggregation_min_with_integer_result(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => 40]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 40], schema(int_schema('int'))), flow_context()); static::assertSame(10.0, $aggregator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ModifyDateTimeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ModifyDateTimeTest.php index 6b29d26ff5..c0c055459c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ModifyDateTimeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ModifyDateTimeTest.php @@ -9,11 +9,12 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_date; @@ -27,7 +28,9 @@ public function test_modify_date(): void new DateTimeImmutable('2025-01-01 12:00:00 +00:00'), ref('datetime') ->modifyDateTime('noon') - ->eval(row(['datetime' => type_date()->cast('2025-01-01')]), flow_context()), + ->eval(array_to_row([ + 'datetime' => type_date()->cast('2025-01-01'), + ], schema(date_schema('datetime'))), flow_context()), ); } @@ -37,7 +40,9 @@ public function test_modify_datetime(): void new DateTimeImmutable('2025-01-01 00:00:00 +00:00'), ref('datetime') ->modifyDateTime('midnight') - ->eval(row(['datetime' => type_datetime()->cast('2025-01-01 10:00:23 +00:00')]), flow_context()), + ->eval(array_to_row([ + 'datetime' => type_datetime()->cast('2025-01-01 10:00:23 +00:00'), + ], schema(datetime_schema('datetime'))), flow_context()), ); } @@ -48,7 +53,9 @@ public function test_modify_using_invalid_modifier(): void ref('datetime') ->modifyDateTime(lit(1)) - ->eval(row(['datetime' => type_datetime()->cast('2025-01-01 10:00:23 +00:00')]), flow_context()); + ->eval(array_to_row([ + 'datetime' => type_datetime()->cast('2025-01-01 10:00:23 +00:00'), + ], schema(datetime_schema('datetime'))), flow_context()); } public function test_zone_of_the_reference_is_kept(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NotTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NotTest.php index 9f0810d1d8..ef2e95181f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NotTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NotTest.php @@ -6,14 +6,19 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_array; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\not; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; final class NotTest extends FlowTestCase { @@ -47,18 +52,25 @@ public function test_not_over_a_null_predicate_drops_the_row(): void public function test_not_expression_on_array_true_value(): void { - static::assertFalse(not(lit([1, 2, 3]))->eval(row([]), flow_context())); + static::assertFalse(not(lit([1, 2, 3]))->eval(array_to_row([], schema()), flow_context())); } public function test_not_expression_on_boolean_true_value(): void { - static::assertFalse(not(lit(true))->eval(row([]), flow_context())); + static::assertFalse(not(lit(true))->eval(array_to_row([], schema()), flow_context())); } public function test_not_expression_on_is_in_expression(): void { static::assertTrue( - not(ref('value')->isIn(ref('array')))->eval(row(['array' => [1, 2, 3], 'value' => 10]), flow_context()), + not(ref('value')->isIn(ref('array'))) + ->eval( + array_to_row( + ['array' => [1, 2, 3], 'value' => 10], + schema(list_schema('array', type_list(type_integer())), int_schema('value')), + ), + flow_context(), + ), ); } @@ -66,19 +78,19 @@ public function test_not_expression_with_and_operator(): void { static::assertTrue( not(ref('value')->isNull()->or(ref('value')->isType(type_integer()))) - ->eval(row(['value' => '10']), flow_context()), + ->eval(array_to_row(['value' => '10'], schema(str_schema('value'))), flow_context()), ); static::assertFalse( not(ref('value')->isNull()->or(ref('value')->isType(type_integer()))) - ->eval(row(['value' => null]), flow_context()), + ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), ); static::assertTrue( not(ref('value')->isNull()->and(ref('value')->size()->between(1, 10))) - ->eval(row(['value' => 'abcd']), flow_context()), + ->eval(array_to_row(['value' => 'abcd'], schema(str_schema('value'))), flow_context()), ); static::assertTrue( not(ref('value')->isNull()->or(ref('value')->size()->equals(1))) - ->eval(row(['value' => 'abcd']), flow_context()), + ->eval(array_to_row(['value' => 'abcd'], schema(str_schema('value'))), flow_context()), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NowTest.php index 42a169cd74..89e3303c87 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NowTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NowTest.php @@ -8,10 +8,13 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\now; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\time_zone_schema; use function Flow\Types\DSL\type_datetime; final class NowTest extends FlowTestCase @@ -31,7 +34,7 @@ public function test_value_is_in_the_zone(): void static::assertSame( 'Europe/Warsaw', type_datetime() - ->assert(now(new DateTimeZone('Europe/Warsaw'))->eval(row([]), flow_context())) + ->assert(now(new DateTimeZone('Europe/Warsaw'))->eval(array_to_row([], schema()), flow_context())) ->getTimezone() ->getName(), ); @@ -42,7 +45,12 @@ public function test_function_zone_value_is_in_the_declared_zone(): void static::assertSame( 'UTC', type_datetime() - ->assert(now(ref('tz'))->eval(row(['tz' => new DateTimeZone('Europe/Warsaw')]), flow_context())) + ->assert( + now(ref('tz')) + ->eval(array_to_row([ + 'tz' => new DateTimeZone('Europe/Warsaw'), + ], schema(time_zone_schema('tz'))), flow_context()), + ) ->getTimezone() ->getName(), ); @@ -53,7 +61,7 @@ public function test_function_zone_null_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Now function requires valid DateTimeZone'); - now(ref('tz'))->eval(row(['tz' => null]), flow_context()); + now(ref('tz'))->eval(array_to_row(['tz' => null], schema(str_schema('tz', nullable: true))), flow_context()); } public function test_utc_alias_zone_lands_in_utc(): void @@ -61,7 +69,7 @@ public function test_utc_alias_zone_lands_in_utc(): void static::assertSame( 'UTC', type_datetime() - ->assert(now(new DateTimeZone('GMT'))->eval(row([]), flow_context())) + ->assert(now(new DateTimeZone('GMT'))->eval(array_to_row([], schema()), flow_context())) ->getTimezone() ->getName(), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NumberFormatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NumberFormatTest.php index 81f083c847..1782f51f10 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NumberFormatTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NumberFormatTest.php @@ -8,11 +8,15 @@ use Flow\ETL\Function\NumberFormat; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\number_format; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class NumberFormatTest extends FlowTestCase { @@ -25,19 +29,32 @@ public function test_number_format(): void ref('thousands_separator'), ); - static::assertSame('1,234.57', $expression->eval(row([ - 'value' => 1234.5678, - 'decimals' => 2, - 'decimal_separator' => '.', - 'thousands_separator' => ',', - ]), flow_context())); + static::assertSame('1,234.57', $expression->eval( + array_to_row( + [ + 'value' => 1234.5678, + 'decimals' => 2, + 'decimal_separator' => '.', + 'thousands_separator' => ',', + ], + schema( + float_schema('value'), + int_schema('decimals'), + str_schema('decimal_separator'), + str_schema('thousands_separator'), + ), + ), + flow_context(), + )); } public function test_number_format_dsl(): void { $expression = number_format(ref('value'), lit(2), lit('.'), lit(',')); - static::assertSame('1,234.57', $expression->eval(row(['value' => 1234.5678]), flow_context())); + static::assertSame('1,234.57', $expression->eval(array_to_row([ + 'value' => 1234.5678, + ], schema(float_schema('value'))), flow_context())); } public function test_number_format_on_decimals_that_are_not_integer(): void @@ -52,12 +69,23 @@ public function test_number_format_on_decimals_that_are_not_integer(): void ref('thousands_separator'), ); - $expression->eval(row([ - 'value' => 1234.5678, - 'decimals' => 2.5, - 'decimal_separator' => '.', - 'thousands_separator' => ',', - ]), flow_context()); + $expression->eval( + array_to_row( + [ + 'value' => 1234.5678, + 'decimals' => 2.5, + 'decimal_separator' => '.', + 'thousands_separator' => ',', + ], + schema( + float_schema('value'), + float_schema('decimals'), + str_schema('decimal_separator'), + str_schema('thousands_separator'), + ), + ), + flow_context(), + ); } public function test_number_format_on_non_int_entry(): void @@ -72,11 +100,22 @@ public function test_number_format_on_non_int_entry(): void ref('thousands_separator'), ); - $expression->eval(row([ - 'value' => 'test', - 'decimals' => 2, - 'decimal_separator' => '.', - 'thousands_separator' => ',', - ]), flow_context()); + $expression->eval( + array_to_row( + [ + 'value' => 'test', + 'decimals' => 2, + 'decimal_separator' => '.', + 'thousands_separator' => ',', + ], + schema( + str_schema('value'), + int_schema('decimals'), + str_schema('decimal_separator'), + str_schema('thousands_separator'), + ), + ), + flow_context(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php index 379afb4b76..ac04ca6a66 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php @@ -16,14 +16,15 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\definition_from_type; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_array; @@ -32,6 +33,7 @@ use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_optional; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; use function serialize; @@ -49,7 +51,11 @@ public function test_a_throwing_body_is_not_swallowed(): void ref('array')->onEach(ref('element')->upper()), schema(list_schema('array', type_list(type_integer()))), ) - ->eval(row(['array' => [1, 2, 3]]), flow_context()); + ->eval(array_to_row(['array' => [ + 1, + 2, + 3, + ]], schema(list_schema('array', type_list(type_integer())))), flow_context()); } public function test_an_element_the_declared_type_refuses_is_not_swallowed(): void @@ -61,7 +67,10 @@ public function test_an_element_the_declared_type_refuses_is_not_swallowed(): vo ref('array')->onEach(ref('element')->upper()), schema(list_schema('array', type_list(type_string()))), ) - ->eval(row(['array' => ['a', null]]), flow_context()); + ->eval(array_to_row(['array' => [ + 'a', + null, + ]], schema(list_schema('array', type_list(type_optional(type_string()))))), flow_context()); } public function test_executing_function_on_each_value_from_array(): void @@ -73,7 +82,13 @@ public function test_executing_function_on_each_value_from_array(): void ref('array')->onEach(ref('element')->cast(type_string())), schema(list_schema('array', type_list(type_integer()))), ) - ->eval(row(['array' => [1, 2, 3, 4, 5]]), flow_context()), + ->eval(array_to_row(['array' => [ + 1, + 2, + 3, + 4, + 5, + ]], schema(list_schema('array', type_list(type_integer())))), flow_context()), ); } @@ -86,7 +101,10 @@ public function test_executing_function_on_each_value_from_empty_array(): void ref('array')->onEach(ref('element')->cast(type_string())), schema(list_schema('array', type_list(type_integer()))), ) - ->eval(row(['array' => []]), flow_context()), + ->eval(array_to_row( + ['array' => []], + schema(list_schema('array', type_list(type_integer()))), + ), flow_context()), ); } @@ -99,7 +117,13 @@ public function test_executing_function_on_each_value_with_preserving_keys(): vo ref('array')->onEach(ref('element')->cast(type_string()), true), schema(map_schema('array', type_map(type_string(), type_integer()))), ) - ->eval(row(['array' => ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5]]), flow_context()), + ->eval(array_to_row(['array' => [ + 'a' => 1, + 'b' => 2, + 'c' => 3, + 'd' => 4, + 'e' => 5, + ]], schema(map_schema('array', type_map(type_string(), type_integer())))), flow_context()), ); } @@ -112,7 +136,13 @@ public function test_executing_function_on_each_value_without_preserving_keys(): ref('array')->onEach(ref('element')->cast(type_string()), false), schema(map_schema('array', type_map(type_string(), type_integer()))), ) - ->eval(row(['array' => ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5]]), flow_context()), + ->eval(array_to_row(['array' => [ + 'a' => 1, + 'b' => 2, + 'c' => 3, + 'd' => 4, + 'e' => 5, + ]], schema(map_schema('array', type_map(type_string(), type_integer())))), flow_context()), ); } @@ -128,14 +158,17 @@ public function test_on_each_over_an_untyped_array_operand_is_refused(): void ref('array')->onEach(ref('element')->cast(type_string())), schema(definition_from_type('array', type_array())), ) - ->eval(row(['array' => [1, 2]]), flow_context()); + ->eval(array_to_row(['array' => [ + 1, + 2, + ]], schema(list_schema('array', type_list(type_integer())))), flow_context()); } public function test_the_element_schema_is_built_once_per_eval_not_once_per_element(): void { $operand = new CountingReturnsFunction(lit([1, 2, 3, 4, 5]), type_list(type_integer())); - (new OnEach($operand, ref('element')->cast(type_string())))->eval(row([]), flow_context()); + (new OnEach($operand, ref('element')->cast(type_string())))->eval(array_to_row([], schema()), flow_context()); static::assertSame(1, $operand->returnsCalls); } @@ -224,7 +257,9 @@ public function test_a_null_array_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('OnEach requires non-null array'); - ref('tags')->onEach(ref('element'))->eval(row(['tags' => null]), flow_context()); + ref('tags') + ->onEach(ref('element')) + ->eval(array_to_row(['tags' => null], schema(str_schema('tags', nullable: true))), flow_context()); } public function test_with_children_keeps_the_element_schema(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OptionalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OptionalTest.php index 5201813d9c..35aa11c8c4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OptionalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OptionalTest.php @@ -6,10 +6,12 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\optional; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class OptionalTest extends FlowTestCase { @@ -20,6 +22,9 @@ public function test_optional_declares_the_inner_type_widened_to_optional(): voi public function test_optional_returns_null_when_the_inner_function_throws(): void { - static::assertNull(optional(ref('name')->upper())->eval(row(['other' => 'flow']), flow_context())); + static::assertNull( + optional(ref('name')->upper()) + ->eval(array_to_row(['other' => 'flow'], schema(str_schema('other'))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php index df1677d7b5..db878709a3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php @@ -15,10 +15,12 @@ use PHPUnit\Framework\Attributes\DataProvider; use stdClass; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_string; @@ -86,31 +88,31 @@ public static function string_data_provider(): Generator public function test_as_array_with_empty_array(): void { $parameter = new Parameter(lit([])); - static::assertSame([], $parameter->asArray(row([]), flow_context())); + static::assertSame([], $parameter->asArray(array_to_row([], schema()), flow_context())); } public function test_as_boolean_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit(['value'])))->asBoolean(row([]), flow_context()); + (new Parameter(lit(['value'])))->asBoolean(array_to_row([], schema()), flow_context()); } public function test_as_boolean_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asBoolean(row([]), flow_context())); + static::assertNull((new Parameter(lit(null)))->asBoolean(array_to_row([], schema()), flow_context())); } public function test_as_float_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('3.14')))->asFloat(row([]), flow_context()); + (new Parameter(lit('3.14')))->asFloat(array_to_row([], schema()), flow_context()); } public function test_as_float_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asFloat(row([]), flow_context())); + static::assertNull((new Parameter(lit(null)))->asFloat(array_to_row([], schema()), flow_context())); } public function test_as_int_throws_on_a_malformed_value(): void @@ -118,54 +120,54 @@ public function test_as_int_throws_on_a_malformed_value(): void // A default never applies to a malformed value - only to a NULL input. $this->expectException(InvalidArgumentException::class); - (new Parameter(lit(3.14)))->asInt(row([]), flow_context(), 99); + (new Parameter(lit(3.14)))->asInt(array_to_row([], schema()), flow_context(), 99); } public function test_as_int_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asInt(row([]), flow_context())); + static::assertNull((new Parameter(lit(null)))->asInt(array_to_row([], schema()), flow_context())); } public function test_as_number_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not numeric')))->asNumber(row([]), flow_context(), 99); + (new Parameter(lit('not numeric')))->asNumber(array_to_row([], schema()), flow_context(), 99); } public function test_as_number_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asNumber(row([]), flow_context())); + static::assertNull((new Parameter(lit(null)))->asNumber(array_to_row([], schema()), flow_context())); } public function test_as_string_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit(42)))->asString(row([]), flow_context(), 'default'); + (new Parameter(lit(42)))->asString(array_to_row([], schema()), flow_context(), 'default'); } public function test_as_string_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asString(row([]), flow_context())); + static::assertNull((new Parameter(lit(null)))->asString(array_to_row([], schema()), flow_context())); } public function test_as_array_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an array')))->asArray(row([]), flow_context()); + (new Parameter(lit('not an array')))->asArray(array_to_row([], schema()), flow_context()); } public function test_as_array_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asArray(row([]), flow_context())); + static::assertNull((new Parameter(lit(null)))->asArray(array_to_row([], schema()), flow_context())); } public function test_as_array_with_valid_array(): void { $parameter = new Parameter(lit(['key' => 'value', 'number' => 42])); - $result = $parameter->asArray(row([]), flow_context()); + $result = $parameter->asArray(array_to_row([], schema()), flow_context()); static::assertSame(['key' => 'value', 'number' => 42], $result); } @@ -174,24 +176,28 @@ public function test_as_array_with_valid_array(): void public function test_as_boolean(mixed $input, ?bool $expected): void { $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asBoolean(row([]), flow_context())); + static::assertSame($expected, $parameter->asBoolean(array_to_row([], schema()), flow_context())); } public function test_as_value_with_literal(): void { - static::assertNull((new Parameter(lit('literal_value')))->asValue(row([]))); + static::assertNull((new Parameter(lit('literal_value')))->asValue(array_to_row([], schema()))); } public function test_as_value_with_missing_reference(): void { - static::assertNull((new Parameter(ref('missing_column')))->asValue(row(['other_column' => 'test_value']))); + static::assertNull((new Parameter(ref('missing_column')))->asValue(array_to_row([ + 'other_column' => 'test_value', + ], schema(str_schema('other_column'))))); } public function test_as_value_with_reference(): void { static::assertSame( 'test_value', - (new Parameter(ref('test_column')))->asValue(row(['test_column' => 'test_value'])), + (new Parameter(ref('test_column')))->asValue(array_to_row([ + 'test_column' => 'test_value', + ], schema(str_schema('test_column')))), ); } @@ -199,18 +205,26 @@ public function test_as_enum_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an enum')))->asEnum(row([]), flow_context(), SQLParametersStyle::class); + (new Parameter(lit('not an enum')))->asEnum( + array_to_row([], schema()), + flow_context(), + SQLParametersStyle::class, + ); } public function test_as_enum_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asEnum(row([]), flow_context(), SQLParametersStyle::class)); + static::assertNull((new Parameter(lit(null)))->asEnum( + array_to_row([], schema()), + flow_context(), + SQLParametersStyle::class, + )); } public function test_as_enum_with_valid_enum(): void { $parameter = new Parameter(lit(SQLParametersStyle::NAMED)); - $result = $parameter->asEnum(row([]), flow_context(), SQLParametersStyle::class); + $result = $parameter->asEnum(array_to_row([], schema()), flow_context(), SQLParametersStyle::class); static::assertSame(SQLParametersStyle::NAMED, $result); } @@ -219,26 +233,38 @@ public function test_as_enum_with_wrong_enum_class(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit(SQLParametersStyle::NAMED)))->asEnum(row([]), flow_context(), StringStyles::class); + (new Parameter(lit(SQLParametersStyle::NAMED)))->asEnum( + array_to_row([], schema()), + flow_context(), + StringStyles::class, + ); } #[DataProvider('float_data_provider')] public function test_as_float(mixed $input, ?float $expected): void { $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asFloat(row([]), flow_context())); + static::assertSame($expected, $parameter->asFloat(array_to_row([], schema()), flow_context())); } public function test_as_instance_of_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an object')))->asInstanceOf(row([]), flow_context(), DateTimeImmutable::class); + (new Parameter(lit('not an object')))->asInstanceOf( + array_to_row([], schema()), + flow_context(), + DateTimeImmutable::class, + ); } public function test_as_instance_of_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asInstanceOf(row([]), flow_context(), DateTimeImmutable::class)); + static::assertNull((new Parameter(lit(null)))->asInstanceOf( + array_to_row([], schema()), + flow_context(), + DateTimeImmutable::class, + )); } public function test_as_instance_of_with_valid_object(): void @@ -246,10 +272,10 @@ public function test_as_instance_of_with_valid_object(): void $dateTime = new DateTimeImmutable('2023-01-01'); $parameter = new Parameter(lit($dateTime)); - $result = $parameter->asInstanceOf(row([]), flow_context(), DateTimeImmutable::class); + $result = $parameter->asInstanceOf(array_to_row([], schema()), flow_context(), DateTimeImmutable::class); static::assertSame($dateTime, $result); - $result = $parameter->asInstanceOf(row([]), flow_context(), DateTimeInterface::class); + $result = $parameter->asInstanceOf(array_to_row([], schema()), flow_context(), DateTimeInterface::class); static::assertSame($dateTime, $result); } @@ -257,13 +283,13 @@ public function test_as_instance_of_with_valid_object(): void public function test_as_int(mixed $input, ?int $default, ?int $expected): void { $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asInt(row([]), flow_context(), $default)); + static::assertSame($expected, $parameter->asInt(array_to_row([], schema()), flow_context(), $default)); } public function test_as_list_of_objects_with_empty_array(): void { $parameter = new Parameter(lit([])); - $result = $parameter->asListOfObjects(row([]), flow_context(), DateTimeImmutable::class); + $result = $parameter->asListOfObjects(array_to_row([], schema()), flow_context(), DateTimeImmutable::class); static::assertSame([], $result); } @@ -273,7 +299,7 @@ public function test_as_list_of_objects_throws_on_a_malformed_element(): void $this->expectException(InvalidArgumentException::class); (new Parameter(lit([new DateTimeImmutable('2023-01-01'), 'not an object'])))->asListOfObjects( - row([]), + array_to_row([], schema()), flow_context(), DateTimeImmutable::class, ); @@ -283,13 +309,17 @@ public function test_as_list_of_objects_throws_on_a_non_array(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an array')))->asListOfObjects(row([]), flow_context(), DateTimeImmutable::class); + (new Parameter(lit('not an array')))->asListOfObjects( + array_to_row([], schema()), + flow_context(), + DateTimeImmutable::class, + ); } public function test_as_list_of_objects_propagates_null(): void { static::assertNull((new Parameter(lit(null)))->asListOfObjects( - row([]), + array_to_row([], schema()), flow_context(), DateTimeImmutable::class, )); @@ -301,7 +331,7 @@ public function test_as_list_of_objects_with_valid_array(): void $date2 = new DateTimeImmutable('2023-01-02'); $parameter = new Parameter(lit([$date1, $date2])); - $result = $parameter->asListOfObjects(row([]), flow_context(), DateTimeImmutable::class); + $result = $parameter->asListOfObjects(array_to_row([], schema()), flow_context(), DateTimeImmutable::class); static::assertSame([$date1, $date2], $result); } @@ -310,7 +340,7 @@ public function test_as_list_of_objects_with_wrong_object_type(): void $this->expectException(InvalidArgumentException::class); (new Parameter(lit([new DateTimeImmutable('2023-01-01'), new stdClass()])))->asListOfObjects( - row([]), + array_to_row([], schema()), flow_context(), DateTimeImmutable::class, ); @@ -320,19 +350,19 @@ public function test_as_list_of_objects_with_wrong_object_type(): void public function test_as_number(mixed $input, int|float|null $default, int|float|null $expected): void { $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asNumber(row([]), flow_context(), $default)); + static::assertSame($expected, $parameter->asNumber(array_to_row([], schema()), flow_context(), $default)); } public function test_as_object_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an object')))->asObject(row([]), flow_context()); + (new Parameter(lit('not an object')))->asObject(array_to_row([], schema()), flow_context()); } public function test_as_object_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asObject(row([]), flow_context())); + static::assertNull((new Parameter(lit(null)))->asObject(array_to_row([], schema()), flow_context())); } public function test_as_object_with_valid_object(): void @@ -341,13 +371,13 @@ public function test_as_object_with_valid_object(): void $object->property = 'value'; $parameter = new Parameter(lit($object)); - static::assertSame($object, $parameter->asObject(row([]), flow_context())); + static::assertSame($object, $parameter->asObject(array_to_row([], schema()), flow_context())); } public function test_as_one_of(): void { static::assertSame('42', (new Parameter(ref('value')))->as( - row(['value' => '42']), + array_to_row(['value' => '42'], schema(str_schema('value'))), flow_context(), type_string(), type_integer(), @@ -358,18 +388,23 @@ public function test_as_throws_when_no_type_matches(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(ref('value')))->as(row(['value' => '42']), flow_context(), type_integer(), type_boolean()); + (new Parameter(ref('value')))->as( + array_to_row(['value' => '42'], schema(str_schema('value'))), + flow_context(), + type_integer(), + type_boolean(), + ); } public function test_as_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->as(row([]), flow_context(), type_integer())); + static::assertNull((new Parameter(lit(null)))->as(array_to_row([], schema()), flow_context(), type_integer())); } public function test_as_scalar(): void { static::assertSame('42', (new Parameter(ref('value')))->as( - row(['value' => '42']), + array_to_row(['value' => '42'], schema(str_schema('value'))), flow_context(), type_string(), )); @@ -379,19 +414,19 @@ public function test_as_scalar(): void public function test_as_string(mixed $input, ?string $default, ?string $expected): void { $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asString(row([]), flow_context(), $default)); + static::assertSame($expected, $parameter->asString(array_to_row([], schema()), flow_context(), $default)); } public function test_constructor_with_mixed_value(): void { $parameter = new Parameter('direct_string'); - static::assertSame('direct_string', $parameter->eval(row([]), flow_context())); + static::assertSame('direct_string', $parameter->eval(array_to_row([], schema()), flow_context())); $parameter = new Parameter(123); - static::assertSame(123, $parameter->eval(row([]), flow_context())); + static::assertSame(123, $parameter->eval(array_to_row([], schema()), flow_context())); $parameter = new Parameter(true); - static::assertTrue($parameter->eval(row([]), flow_context())); + static::assertTrue($parameter->eval(array_to_row([], schema()), flow_context())); } public function test_constructor_with_scalar_function(): void @@ -399,22 +434,24 @@ public function test_constructor_with_scalar_function(): void $scalarFunction = lit('test'); $parameter = new Parameter($scalarFunction); - static::assertSame('test', $parameter->eval(row([]), flow_context())); + static::assertSame('test', $parameter->eval(array_to_row([], schema()), flow_context())); } public function test_eval_with_direct_value(): void { $parameter = new Parameter(lit('direct_value')); - static::assertSame('direct_value', $parameter->eval(row([]), flow_context())); + static::assertSame('direct_value', $parameter->eval(array_to_row([], schema()), flow_context())); $parameter = new Parameter(lit(42)); - static::assertSame(42, $parameter->eval(row([]), flow_context())); + static::assertSame(42, $parameter->eval(array_to_row([], schema()), flow_context())); } public function test_eval_with_reference(): void { $parameter = new Parameter(ref('column')); - $result = $parameter->eval(row(['column' => 'ref_value']), flow_context()); + $result = $parameter->eval(array_to_row([ + 'column' => 'ref_value', + ], schema(str_schema('column'))), flow_context()); static::assertSame('ref_value', $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PowerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PowerTest.php index dac7637e58..84282d0d50 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PowerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PowerTest.php @@ -7,10 +7,13 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class PowerTest extends FlowTestCase { @@ -19,12 +22,16 @@ public function test_power_non_numeric_values(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "integer", got "string".'); - ref('int')->power(lit('non numeric'))->eval(row(['int' => 10]), flow_context()); - ref('str')->power(lit(2))->eval(row(['str' => 'abc']), flow_context()); + ref('int') + ->power(lit('non numeric')) + ->eval(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + ref('str')->power(lit(2))->eval(array_to_row(['str' => 'abc'], schema(str_schema('str'))), flow_context()); } public function test_power_two_numeric_values(): void { - static::assertSame(100, ref('int')->power(lit(2))->eval(row(['int' => 10]), flow_context())); + static::assertSame(100, ref('int') + ->power(lit(2)) + ->eval(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PregReplaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PregReplaceTest.php index 246d0c81f1..a7a669e5d8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PregReplaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PregReplaceTest.php @@ -7,10 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex_replace; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class PregReplaceTest extends FlowTestCase { @@ -21,7 +22,7 @@ public function test_preg_replace_expression_on_invalid_pattern(): void $pregReplace = regex_replace(lit(1), lit('bar'), lit('foo is awesome')); - $pregReplace->eval(row([]), flow_context()); + $pregReplace->eval(array_to_row([], schema()), flow_context()); } public function test_preg_replace_expression_on_invalid_replacement(): void @@ -31,7 +32,7 @@ public function test_preg_replace_expression_on_invalid_replacement(): void $pregReplace = regex_replace(lit('/(foo)/'), lit(2), lit('foo is awesome')); - $pregReplace->eval(row([]), flow_context()); + $pregReplace->eval(array_to_row([], schema()), flow_context()); } public function test_preg_replace_expression_on_invalid_subject(): void @@ -41,13 +42,13 @@ public function test_preg_replace_expression_on_invalid_subject(): void $pregReplace = regex_replace(lit('/(foo)/'), lit('bar'), lit(3)); - $pregReplace->eval(row([]), flow_context()); + $pregReplace->eval(array_to_row([], schema()), flow_context()); } public function test_preg_replace_expression_on_valid_strings(): void { $pregReplace = regex_replace(lit('/(foo)/'), lit('bar'), lit('foo is awesome')); - static::assertSame('bar is awesome', $pregReplace->eval(row([]), flow_context())); + static::assertSame('bar is awesome', $pregReplace->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PrependTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PrependTest.php index bb5f455498..42a111c115 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PrependTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PrependTest.php @@ -7,36 +7,52 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class PrependTest extends FlowTestCase { public function test_prepend_empty_string_to_content(): void { - $result = ref('str')->prepend('')->eval(row(['str' => 'hello']), flow_context()); + $result = ref('str') + ->prepend('') + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); static::assertEquals('hello', $result); } public function test_prepend_to_empty_string(): void { - $result = ref('str')->prepend('hello')->eval(row(['str' => '']), flow_context()); + $result = ref('str') + ->prepend('hello') + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); static::assertEquals('hello', $result); } public function test_prepend_to_non_empty_string(): void { - $result = ref('str')->prepend('Hello ')->eval(row(['str' => 'world']), flow_context()); + $result = ref('str') + ->prepend('Hello ') + ->eval(array_to_row(['str' => 'world'], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello world', $result); } public function test_prepend_with_null_prefix(): void { - $result = ref('str')->prepend(ref('prefix'))->eval(row(['str' => 'world', 'prefix' => null]), flow_context()); + $result = ref('str') + ->prepend(ref('prefix')) + ->eval( + array_to_row( + ['str' => 'world', 'prefix' => null], + schema(str_schema('str'), str_schema('prefix', nullable: true)), + ), + flow_context(), + ); static::assertEquals('world', $result); } @@ -46,7 +62,9 @@ public function test_prepend_with_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Prepend function requires non-null value'); - $result = ref('str')->prepend('Hello ')->eval(row(['str' => null]), flow_context()); + $result = ref('str') + ->prepend('Hello ') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); static::assertNull($result); } @@ -55,7 +73,10 @@ public function test_prepend_with_scalar_function_parameter(): void { $result = ref('str') ->prepend(ref('prefix')) - ->eval(row(['str' => 'world', 'prefix' => 'Hello ']), flow_context()); + ->eval( + array_to_row(['str' => 'world', 'prefix' => 'Hello '], schema(str_schema('str'), str_schema('prefix'))), + flow_context(), + ); static::assertEquals('Hello world', $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RankTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RankTest.php index e9e638519d..1146da01bd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RankTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RankTest.php @@ -8,11 +8,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\rank; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\window; @@ -69,7 +68,7 @@ public function test_rank_requires_an_order_by(): void { $this->expectExceptionMessage('Rank window function requires to be ordered by one column'); - rank()->over(window())->rankPartition(rows(schema(int_schema('salary')), row(['salary' => 6000]))); + rank()->over(window())->rankPartition(array_to_rows([['salary' => 6000]], schema(int_schema('salary')))); } public function test_rank_without_over_clause(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexAllTest.php index 0399de8a8b..c8e19adb21 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexAllTest.php @@ -7,10 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex_all; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class RegexAllTest extends FlowTestCase { @@ -21,14 +22,14 @@ public function test_regex_all_expression_on_invalid_subject(): void $pregMatch = regex_all(lit('/\d+/'), lit(2)); - $pregMatch->eval(row([]), flow_context()); + $pregMatch->eval(array_to_row([], schema()), flow_context()); } public function test_regex_all_expression_on_no_match(): void { $pregMatch = regex_all(lit('/\d+/'), lit('apples and oranges')); - static::assertNull($pregMatch->eval(row([]), flow_context())); + static::assertNull($pregMatch->eval(array_to_row([], schema()), flow_context())); } public function test_regex_all_expression_on_valid_strings(): void @@ -41,7 +42,7 @@ public function test_regex_all_expression_on_valid_strings(): void ['124.23', '12', '45'], ['EUR', 'USD', 'PLN'], ], - $pregMatch->eval(row([]), flow_context()), + $pregMatch->eval(array_to_row([], schema()), flow_context()), ); } @@ -52,6 +53,6 @@ public function test_regex_expression_on_invalid_pattern(): void $pregMatch = regex_all(lit(1), lit('12 apples and 45 oranges')); - $pregMatch->eval(row([]), flow_context()); + $pregMatch->eval(array_to_row([], schema()), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchAllTest.php index 393b2f5f84..f031055579 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchAllTest.php @@ -7,10 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex_match_all; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class RegexMatchAllTest extends FlowTestCase { @@ -21,7 +22,7 @@ public function test_regex_match_all_expression_on_invalid_flags(): void $pregMatchAll = regex_match_all(lit('/\d+/'), lit('12 apples and 45 oranges'), lit('invalid')); - $pregMatchAll->eval(row([]), flow_context()); + $pregMatchAll->eval(array_to_row([], schema()), flow_context()); } public function test_regex_match_all_expression_on_invalid_pattern(): void @@ -31,7 +32,7 @@ public function test_regex_match_all_expression_on_invalid_pattern(): void $pregMatchAll = regex_match_all(lit(1), lit('12 apples and 45 oranges')); - $pregMatchAll->eval(row([]), flow_context()); + $pregMatchAll->eval(array_to_row([], schema()), flow_context()); } public function test_regex_match_all_expression_on_invalid_subject(): void @@ -41,14 +42,14 @@ public function test_regex_match_all_expression_on_invalid_subject(): void $pregMatchAll = regex_match_all(lit('/\d+/'), lit(2)); - $pregMatchAll->eval(row([]), flow_context()); + $pregMatchAll->eval(array_to_row([], schema()), flow_context()); } public function test_regex_match_all_expression_on_valid_strings(): void { $pregMatchAll = regex_match_all(lit('/\d+/'), lit('12 apples and 45 oranges')); - static::assertTrue($pregMatchAll->eval(row([]), flow_context())); + static::assertTrue($pregMatchAll->eval(array_to_row([], schema()), flow_context())); } public function test_regex_match_all_expression_on_valid_strings_with_flags(): void @@ -59,6 +60,6 @@ public function test_regex_match_all_expression_on_valid_strings_with_flags(): v lit(PREG_PATTERN_ORDER), ); - static::assertTrue($pregMatchAll->eval(row([]), flow_context())); + static::assertTrue($pregMatchAll->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchTest.php index 54c248e09d..f83c99d74f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchTest.php @@ -7,10 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex_match; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class RegexMatchTest extends FlowTestCase { @@ -21,7 +22,7 @@ public function test_regex_match_expression_on_invalid_pattern(): void $pregMatch = regex_match(lit(1), lit('12 apples and 45 oranges')); - $pregMatch->eval(row([]), flow_context()); + $pregMatch->eval(array_to_row([], schema()), flow_context()); } public function test_regex_match_expression_on_invalid_subject(): void @@ -31,20 +32,20 @@ public function test_regex_match_expression_on_invalid_subject(): void $pregMatch = regex_match(lit('/\d+/'), lit(2)); - $pregMatch->eval(row([]), flow_context()); + $pregMatch->eval(array_to_row([], schema()), flow_context()); } public function test_regex_match_expression_on_no_match(): void { $pregMatch = regex_match(lit('/\d+/'), lit('apples and oranges')); - static::assertFalse($pregMatch->eval(row([]), flow_context())); + static::assertFalse($pregMatch->eval(array_to_row([], schema()), flow_context())); } public function test_regex_match_expression_on_valid_strings(): void { $pregMatch = regex_match(lit('/\d+/'), lit('12 apples and 45 oranges')); - static::assertTrue($pregMatch->eval(row([]), flow_context())); + static::assertTrue($pregMatch->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexReplaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexReplaceTest.php index 70d5ab9566..8961a7d4ba 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexReplaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexReplaceTest.php @@ -6,25 +6,27 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\regex_replace; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class RegexReplaceTest extends FlowTestCase { public function test_a_null_limit_still_means_unlimited(): void { - static::assertSame('x x x', regex_replace(lit('/a/'), lit('x'), ref('text'))->eval(row([ + static::assertSame('x x x', regex_replace(lit('/a/'), lit('x'), ref('text'))->eval(array_to_row([ 'text' => 'a a a', - ]), flow_context())); + ], schema(str_schema('text'))), flow_context())); } public function test_a_limit_caps_the_replacements(): void { - static::assertSame('x a a', regex_replace(lit('/a/'), lit('x'), ref('text'), lit(1))->eval(row([ + static::assertSame('x a a', regex_replace(lit('/a/'), lit('x'), ref('text'), lit(1))->eval(array_to_row([ 'text' => 'a a a', - ]), flow_context())); + ], schema(str_schema('text'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexTest.php index f5917e1f24..ace87e4da6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexTest.php @@ -7,11 +7,12 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex; use function Flow\ETL\DSL\regex_match_all; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class RegexTest extends FlowTestCase { @@ -22,7 +23,7 @@ public function test_regex_expression_on_invalid_pattern(): void $pregMatch = regex(lit(1), lit('12 apples and 45 oranges')); - $pregMatch->eval(row([]), flow_context()); + $pregMatch->eval(array_to_row([], schema()), flow_context()); } public function test_regex_expression_on_invalid_subject(): void @@ -32,20 +33,20 @@ public function test_regex_expression_on_invalid_subject(): void $pregMatch = regex(lit('/\d+/'), lit(2)); - $pregMatch->eval(row([]), flow_context()); + $pregMatch->eval(array_to_row([], schema()), flow_context()); } public function test_regex_expression_on_no_match(): void { $pregMatch = regex(lit('/\d+/'), lit('apples and oranges')); - static::assertNull($pregMatch->eval(row([]), flow_context())); + static::assertNull($pregMatch->eval(array_to_row([], schema()), flow_context())); } public function test_regex_expression_on_valid_strings(): void { $pregMatch = regex_match_all(lit('/\d+/'), lit('12 apples and 45 oranges')); - static::assertTrue($pregMatch->eval(row([]), flow_context())); + static::assertTrue($pregMatch->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RepeatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RepeatTest.php index e2d83a7f45..8971595212 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RepeatTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RepeatTest.php @@ -7,15 +7,20 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class RepeatTest extends FlowTestCase { public function test_repeat_empty_string(): void { - static::assertSame('', ref('str')->repeat(3)->eval(row(['str' => '']), flow_context())); + static::assertSame('', ref('str') + ->repeat(3) + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); } public function test_repeat_negative_times(): void @@ -23,7 +28,7 @@ public function test_repeat_negative_times(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Repeat function requires non-null, positive times'); - ref('str')->repeat(-1)->eval(row(['str' => 'hello']), flow_context()); + ref('str')->repeat(-1)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); } public function test_repeat_null_input(): void @@ -31,12 +36,16 @@ public function test_repeat_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Repeat function requires non-null value'); - ref('str')->repeat(3)->eval(row(['str' => null]), flow_context()); + ref('str') + ->repeat(3) + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_repeat_string_multiple_times(): void { - static::assertSame('hellohellohello', ref('str')->repeat(3)->eval(row(['str' => 'hello']), flow_context())); + static::assertSame('hellohellohello', ref('str') + ->repeat(3) + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_repeat_with_null_times(): void @@ -44,14 +53,25 @@ public function test_repeat_with_null_times(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Repeat function requires non-null, positive times'); - ref('str')->repeat(ref('times'))->eval(row(['str' => 'hello', 'times' => null]), flow_context()); + ref('str') + ->repeat(ref('times')) + ->eval( + array_to_row( + ['str' => 'hello', 'times' => null], + schema(str_schema('str'), str_schema('times', nullable: true)), + ), + flow_context(), + ); } public function test_repeat_with_scalar_function_times(): void { static::assertSame('hellohello', ref('str') ->repeat(ref('times')) - ->eval(row(['str' => 'hello', 'times' => 2]), flow_context())); + ->eval( + array_to_row(['str' => 'hello', 'times' => 2], schema(str_schema('str'), int_schema('times'))), + flow_context(), + )); } public function test_repeat_zero_times(): void @@ -59,6 +79,6 @@ public function test_repeat_zero_times(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Repeat function requires non-null, positive times'); - ref('str')->repeat(0)->eval(row(['str' => 'hello']), flow_context()); + ref('str')->repeat(0)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReverseTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReverseTest.php index daffef3795..f004f48caa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReverseTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReverseTest.php @@ -7,20 +7,26 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class ReverseTest extends FlowTestCase { public function test_reverse_ascii_string(): void { - static::assertSame('olleh', ref('str')->reverse()->eval(row(['str' => 'hello']), flow_context())); + static::assertSame('olleh', ref('str') + ->reverse() + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_reverse_empty_string(): void { - static::assertSame('', ref('str')->reverse()->eval(row(['str' => '']), flow_context())); + static::assertSame('', ref('str') + ->reverse() + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); } public function test_reverse_throws_on_null_input(): void @@ -28,6 +34,8 @@ public function test_reverse_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Reverse function requires non-null value'); - ref('str')->reverse()->eval(row(['str' => null]), flow_context()); + ref('str') + ->reverse() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RoundTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RoundTest.php index 7b62ca6668..a154ba5e83 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RoundTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RoundTest.php @@ -7,28 +7,38 @@ use Flow\ETL\Function\Round; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class RoundTest extends FlowTestCase { public function test_round_float(): void { - static::assertEquals(10.12, ref('float')->round(lit(2))->eval(row(['float' => 10.123]), flow_context())); - - static::assertIsFloat(ref('float')->round(lit(2))->eval(row(['float' => 10.123]), flow_context())); + static::assertEquals(10.12, ref('float') + ->round(lit(2)) + ->eval(array_to_row(['float' => 10.123], schema(float_schema('float'))), flow_context())); + + static::assertIsFloat( + ref('float') + ->round(lit(2)) + ->eval(array_to_row(['float' => 10.123], schema(float_schema('float'))), flow_context()), + ); } public function test_round_with_precision_0(): void { - static::assertSame(10.0, ref('float')->round(lit(0))->eval(row(['float' => 10.123]), flow_context())); + static::assertSame(10.0, ref('float') + ->round(lit(0)) + ->eval(array_to_row(['float' => 10.123], schema(float_schema('float'))), flow_context())); } public function test_constructor_default_matches_the_dsl_default(): void { - $row = row(['float' => 10.12345]); + $row = array_to_row(['float' => 10.12345], schema(float_schema('float'))); static::assertSame(round(10.12345, 2), (new Round(ref('float')))->eval($row, flow_context())); static::assertSame(round(10.12345, 2), ref('float')->round()->eval($row, flow_context())); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RowNumberTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RowNumberTest.php index 6a96fa357b..20eb566ab2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RowNumberTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RowNumberTest.php @@ -7,9 +7,9 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\row_number; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; @@ -21,11 +21,11 @@ public function test_row_number_is_the_position_in_the_ordered_partition(): void { $rows = rows( schema(int_schema('id'), int_schema('value')), - row(['id' => 5, 'value' => 1]), - row(['id' => 4, 'value' => 1]), - row(['id' => 3, 'value' => 1]), - row(['id' => 2, 'value' => 1]), - $row1 = row(['id' => 1, 'value' => 1]), + array_to_row(['id' => 5, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 4, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 3, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 2, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + $row1 = array_to_row(['id' => 1, 'value' => 1], schema(int_schema('id'), int_schema('value'))), ); $rowNumber = row_number()->over(window()->partitionBy(ref('value'))->orderBy(ref('id')->desc())); @@ -37,8 +37,8 @@ public function test_row_number_numbers_duplicated_rows_separately(): void { $rows = rows( schema(int_schema('id'), int_schema('value')), - $row1 = row(['id' => 1, 'value' => 100]), - $row2 = row(['id' => 1, 'value' => 100]), + $row1 = array_to_row(['id' => 1, 'value' => 100], schema(int_schema('id'), int_schema('value'))), + $row2 = array_to_row(['id' => 1, 'value' => 100], schema(int_schema('id'), int_schema('value'))), ); $rowNumber = row_number()->over(window()->orderBy(ref('value'))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SameTest.php index b586dfe240..389e3aea16 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SameTest.php @@ -6,17 +6,27 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class SameTest extends FlowTestCase { public function test_null_is_identical_to_null(): void { // PHP identity, not SQL equality - ->same() is the migration path for both-null checks. - static::assertTrue(ref('a')->same(lit(null))->eval(row(['a' => null]), flow_context())); - static::assertFalse(ref('a')->same(lit(1))->eval(row(['a' => null]), flow_context())); + static::assertTrue( + ref('a') + ->same(lit(null)) + ->eval(array_to_row(['a' => null], schema(str_schema('a', nullable: true))), flow_context()), + ); + static::assertFalse( + ref('a') + ->same(lit(1)) + ->eval(array_to_row(['a' => null], schema(str_schema('a', nullable: true))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SanitizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SanitizeTest.php index 76e81a8ca7..4b2157a839 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SanitizeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SanitizeTest.php @@ -7,10 +7,13 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class SanitizeTest extends FlowTestCase { @@ -19,30 +22,34 @@ public function test_sanitize_on_non_string_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "string", got "integer".'); - ref('value')->sanitize()->eval(row(['value' => 1000]), flow_context()); + ref('value')->sanitize()->eval(array_to_row(['value' => 1000], schema(int_schema('value'))), flow_context()); } public function test_sanitize_on_valid_string(): void { - static::assertSame('****', ref('value')->sanitize()->eval(row(['value' => 'test']), flow_context())); + static::assertSame('****', ref('value') + ->sanitize() + ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); } public function test_sanitize_on_valid_string_with_left_characters(): void { static::assertSame('te**', ref('value') ->sanitize(skipCharacters: lit(2)) - ->eval(row(['value' => 'test']), flow_context())); + ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); } public function test_sanitize_on_valid_string_with_left_characters_longer_than_string(): void { static::assertSame('****', ref('value') ->sanitize(skipCharacters: lit(5)) - ->eval(row(['value' => 'test']), flow_context())); + ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); } public function test_sanitize_on_valid_string_with_placeholder(): void { - static::assertSame('----', ref('value')->sanitize(lit('-'))->eval(row(['value' => 'test']), flow_context())); + static::assertSame('----', ref('value') + ->sanitize(lit('-')) + ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SizeTest.php index 396a294d4c..3730982cfc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SizeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SizeTest.php @@ -6,25 +6,26 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\size; final class SizeTest extends FlowTestCase { public function test_size_expression_on_array_value(): void { - static::assertSame(3, size(lit(['foo', 'bar', 'baz']))->eval(row([]), flow_context())); + static::assertSame(3, size(lit(['foo', 'bar', 'baz']))->eval(array_to_row([], schema()), flow_context())); } public function test_size_expression_on_integer_value(): void { - static::assertNull(size(lit(1))->eval(row([]), flow_context())); + static::assertNull(size(lit(1))->eval(array_to_row([], schema()), flow_context())); } public function test_size_expression_on_string_value(): void { - static::assertSame(3, size(lit('foo'))->eval(row([]), flow_context())); + static::assertSame(3, size(lit('foo'))->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SlugTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SlugTest.php index 4a08d27b13..636fb9ebd9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SlugTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SlugTest.php @@ -7,10 +7,12 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class SlugTest extends FlowTestCase { @@ -18,7 +20,9 @@ public function test_a_malformed_separator_operand_throws(): void { $this->expectException(InvalidArgumentException::class); - ref('value')->slug(lit(123))->eval(row(['value' => 'hello world']), flow_context()); + ref('value') + ->slug(lit(123)) + ->eval(array_to_row(['value' => 'hello world'], schema(str_schema('value'))), flow_context()); } public function test_ascii_on_null(): void @@ -26,16 +30,22 @@ public function test_ascii_on_null(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Slug function requires non-null value'); - ref('str')->slug()->eval(row(['str' => null]), flow_context()); + ref('str') + ->slug() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_slug(): void { - static::assertSame('azcz', ref('str')->slug()->eval(row(['str' => 'ąźćż']), flow_context())); + static::assertSame('azcz', ref('str') + ->slug() + ->eval(array_to_row(['str' => 'ąźćż'], schema(str_schema('str'))), flow_context())); } public function test_slug_separator(): void { - static::assertSame('Some_Text', ref('str')->slug('_')->eval(row(['str' => 'Some Text']), flow_context())); + static::assertSame('Some_Text', ref('str') + ->slug('_') + ->eval(array_to_row(['str' => 'Some Text'], schema(str_schema('str'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SplitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SplitTest.php index 3e025ae451..819d7fa8b1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SplitTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SplitTest.php @@ -7,9 +7,10 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\split; final class SplitTest extends FlowTestCase @@ -19,16 +20,22 @@ public function test_split_not_string(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "string", got "integer".'); - split(lit(123), ',')->eval(row([]), flow_context()); + split(lit(123), ',')->eval(array_to_row([], schema()), flow_context()); } public function test_split_string(): void { - static::assertSame(['foo', 'bar', 'baz'], split(lit('foo,bar,baz'), ',')->eval(row([]), flow_context())); + static::assertSame( + ['foo', 'bar', 'baz'], + split(lit('foo,bar,baz'), ',')->eval(array_to_row([], schema()), flow_context()), + ); } public function test_split_string_with_limit(): void { - static::assertSame(['foo', 'bar,baz'], split(lit('foo,bar,baz'), ',', 2)->eval(row([]), flow_context())); + static::assertSame( + ['foo', 'bar,baz'], + split(lit('foo,bar,baz'), ',', 2)->eval(array_to_row([], schema()), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SprintfTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SprintfTest.php index d73c7b7e25..3f37938833 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SprintfTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SprintfTest.php @@ -7,9 +7,10 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\sprintf; final class SprintfTest extends FlowTestCase @@ -21,13 +22,13 @@ public function test_sprintf_expression_on_invalid_format(): void $sprintf = sprintf(lit(1), lit('John'), lit(25)); - $sprintf->eval(row([]), flow_context()); + $sprintf->eval(array_to_row([], schema()), flow_context()); } public function test_sprintf_expression_on_valid_format_and_args(): void { $sprintf = sprintf(lit('Hello, %s! Your age is %d.'), lit('John'), lit(25)); - static::assertSame('Hello, John! Your age is 25.', $sprintf->eval(row([]), flow_context())); + static::assertSame('Hello, John! Your age is 25.', $sprintf->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrPadTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrPadTest.php index 30e39558a7..5936b0f3f3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrPadTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrPadTest.php @@ -6,9 +6,11 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use const STR_PAD_LEFT; @@ -18,6 +20,6 @@ public function test_str_pad_on_valid_string(): void { static::assertSame('----N', ref('value') ->strPad(5, '-', STR_PAD_LEFT) - ->eval(row(['value' => 'N']), flow_context())); + ->eval(array_to_row(['value' => 'N'], schema(str_schema('value'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrReplaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrReplaceTest.php index 406f437022..f09abe2864 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrReplaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrReplaceTest.php @@ -6,21 +6,25 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StrReplaceTest extends FlowTestCase { public function test_str_replace_on_valid_string(): void { - static::assertSame('1', ref('value')->strReplace('test', '1')->eval(row(['value' => 'test']), flow_context())); + static::assertSame('1', ref('value') + ->strReplace('test', '1') + ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); } public function test_str_replace_on_valid_string_with_array_of_replacements(): void { static::assertSame('test was successful', ref('value') ->strReplace(['is', 'broken'], ['was', 'successful']) - ->eval(row(['value' => 'test is broken']), flow_context())); + ->eval(array_to_row(['value' => 'test is broken'], schema(str_schema('value'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterLastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterLastTest.php index 302593965c..12bc1be420 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterLastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterLastTest.php @@ -7,9 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringAfterLastTest extends FlowTestCase { @@ -17,14 +19,26 @@ public function test_string_after_last(): void { static::assertSame('rld', ref('str') ->stringAfterLast(ref('needle')) - ->eval(row(['str' => 'hello world', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); } public function test_string_after_last_including_needle(): void { static::assertSame('orld', ref('str') ->stringAfterLast(ref('needle'), includeNeedle: true) - ->eval(row(['str' => 'hello world', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); } public function test_string_after_last_throws_on_null_input(): void @@ -32,6 +46,8 @@ public function test_string_after_last_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringAfterLast function requires non-null value'); - ref('str')->stringAfterLast('x')->eval(row(['str' => null]), flow_context()); + ref('str') + ->stringAfterLast('x') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterTest.php index 83b7711ede..9bfb7c84e0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterTest.php @@ -7,9 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringAfterTest extends FlowTestCase { @@ -17,18 +19,36 @@ public function test_string_after(): void { static::assertSame(' world', ref('str') ->stringAfter(ref('needle')) - ->eval(row(['str' => 'hello world', 'needle' => 'hello']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'hello'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); static::assertSame(' world', ref('str') ->stringAfter(ref('needle')) - ->eval(row(['str' => 'hello world', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); } public function test_string_after_including_needle(): void { static::assertSame('o world', ref('str') ->stringAfter(ref('needle'), includeNeedle: true) - ->eval(row(['str' => 'hello world', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); } public function test_string_after_throws_on_null_input(): void @@ -36,6 +56,8 @@ public function test_string_after_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringAfter function requires non-null value'); - ref('str')->stringAfter('x')->eval(row(['str' => null]), flow_context()); + ref('str') + ->stringAfter('x') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAggregateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAggregateTest.php index 25feab7dae..41619fd5ff 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAggregateTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAggregateTest.php @@ -7,9 +7,12 @@ use Flow\ETL\Row\SortOrder; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_agg; final class StringAggregateTest extends FlowTestCase @@ -23,10 +26,10 @@ public function test_string_agg(): void { $aggregator = string_agg(ref('data')); - $aggregator->aggregate(row(['data' => 'a']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'c']), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); static::assertSame('a, b, b, c', $aggregator->value()); static::assertSame('data_str_agg', $aggregator->outputName()); @@ -43,10 +46,10 @@ public function test_string_agg_on_non_string(): void { $aggregator = string_agg(ref('data'), sort: SortOrder::DESC); - $aggregator->aggregate(row(['data' => 'a']), flow_context()); - $aggregator->aggregate(row(['data' => 1]), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'c']), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 1], schema(int_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); static::assertSame('c, b, a', $aggregator->value()); } @@ -55,10 +58,10 @@ public function test_string_agg_with_alias(): void { $aggregator = string_agg(ref('data')->as('string')); - $aggregator->aggregate(row(['data' => 'a']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'c']), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); static::assertSame('a, b, b, c', $aggregator->value()); static::assertSame('string', $aggregator->outputName()); @@ -68,10 +71,10 @@ public function test_string_agg_with_order(): void { $aggregator = string_agg(ref('data'), sort: SortOrder::DESC); - $aggregator->aggregate(row(['data' => 'a']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'b']), flow_context()); - $aggregator->aggregate(row(['data' => 'c']), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); static::assertSame('c, b, b, a', $aggregator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeLastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeLastTest.php index 2a815400fb..bb8499a34a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeLastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeLastTest.php @@ -7,9 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringBeforeLastTest extends FlowTestCase { @@ -17,21 +19,36 @@ public function test_string_before_last(): void { static::assertSame('hello w', ref('str') ->stringBeforeLast(ref('needle')) - ->eval(row(['str' => 'hello world', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); } public function test_string_before_last_including_needle(): void { static::assertSame('hello wo', ref('str') ->stringBeforeLast(ref('needle'), includeNeedle: true) - ->eval(row(['str' => 'hello world', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); } public function test_string_before_last_returns_empty_string(): void { static::assertSame('', ref('str') ->stringBeforeLast(ref('needle')) - ->eval(row(['str' => '', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row(['str' => '', 'needle' => 'o'], schema(str_schema('str'), str_schema('needle'))), + flow_context(), + )); } public function test_string_before_last_throws_on_null_input(): void @@ -39,6 +56,14 @@ public function test_string_before_last_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringBeforeLast function requires non-null value'); - ref('str')->stringBeforeLast(ref('needle'))->eval(row(['str' => null, 'needle' => 'o']), flow_context()); + ref('str') + ->stringBeforeLast(ref('needle')) + ->eval( + array_to_row( + ['str' => null, 'needle' => 'o'], + schema(str_schema('str', nullable: true), str_schema('needle')), + ), + flow_context(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeTest.php index 8f6a31ef23..6d8d98ab80 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeTest.php @@ -7,9 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringBeforeTest extends FlowTestCase { @@ -17,25 +19,46 @@ public function test_string_before(): void { static::assertSame('hello ', ref('str') ->stringBefore(ref('needle')) - ->eval(row(['str' => 'hello world', 'needle' => 'world']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'world'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); static::assertSame('hell', ref('str') ->stringBefore(ref('needle')) - ->eval(row(['str' => 'hello world', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); } public function test_string_before_including_needle(): void { static::assertSame('hello', ref('str') ->stringBefore(ref('needle'), includeNeedle: true) - ->eval(row(['str' => 'hello world', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + ), + flow_context(), + )); } public function test_string_before_returns_empty_string(): void { static::assertSame('', ref('str') ->stringBefore(ref('needle')) - ->eval(row(['str' => '', 'needle' => 'o']), flow_context())); + ->eval( + array_to_row(['str' => '', 'needle' => 'o'], schema(str_schema('str'), str_schema('needle'))), + flow_context(), + )); } public function test_string_before_throws_on_null_input(): void @@ -43,6 +66,14 @@ public function test_string_before_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringBefore function requires non-null value'); - ref('str')->stringBefore(ref('needle'))->eval(row(['str' => null, 'needle' => 'o']), flow_context()); + ref('str') + ->stringBefore(ref('needle')) + ->eval( + array_to_row( + ['str' => null, 'needle' => 'o'], + schema(str_schema('str', nullable: true), str_schema('needle')), + ), + flow_context(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringContainsAnyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringContainsAnyTest.php index 22eff5b9aa..a27f2c9433 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringContainsAnyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringContainsAnyTest.php @@ -7,10 +7,15 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_string; final class StringContainsAnyTest extends FlowTestCase { @@ -19,20 +24,26 @@ public function test_contains_any_empty_needles_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringContainsAny function requires a non-empty needles array'); - ref('str')->stringContainsAny([])->eval(row(['str' => 'hello world']), flow_context()); + ref('str') + ->stringContainsAny([]) + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()); } public function test_contains_any_multiple_needles_one_found(): void { static::assertTrue( - ref('str')->stringContainsAny(['foo', 'world', 'bar'])->eval(row(['str' => 'hello world']), flow_context()), + ref('str') + ->stringContainsAny(['foo', 'world', 'bar']) + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()), ); } public function test_contains_any_no_needles_found(): void { static::assertFalse( - ref('str')->stringContainsAny(['foo', 'bar', 'baz'])->eval(row(['str' => 'hello world']), flow_context()), + ref('str') + ->stringContainsAny(['foo', 'bar', 'baz']) + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()), ); } @@ -41,21 +52,33 @@ public function test_contains_any_null_needles(): void static::assertNull( ref('str') ->stringContainsAny(ref('needles')) - ->eval(row(['str' => 'hello world', 'needles' => null]), flow_context()), + ->eval( + array_to_row( + ['str' => 'hello world', 'needles' => null], + schema(str_schema('str'), str_schema('needles', nullable: true)), + ), + flow_context(), + ), ); } public function test_contains_any_null_string(): void { static::assertNull( - ref('str')->stringContainsAny(['hello', 'world'])->eval(row(['str' => null]), flow_context()), + ref('str') + ->stringContainsAny(['hello', 'world']) + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()), ); } public function test_contains_any_null_string_in_strict_mode(): void { $context = flow_context(config()); - static::assertNull(ref('str')->stringContainsAny(['hello', 'world'])->eval(row(['str' => null]), $context)); + static::assertNull( + ref('str') + ->stringContainsAny(['hello', 'world']) + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), $context), + ); } public function test_contains_any_with_scalar_function_parameter(): void @@ -63,7 +86,13 @@ public function test_contains_any_with_scalar_function_parameter(): void static::assertTrue( ref('str') ->stringContainsAny(ref('needles')) - ->eval(row(['str' => 'hello world', 'needles' => ['world', 'foo']]), flow_context()), + ->eval( + array_to_row( + ['str' => 'hello world', 'needles' => ['world', 'foo']], + schema(str_schema('str'), list_schema('needles', type_list(type_string()))), + ), + flow_context(), + ), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringEqualsToTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringEqualsToTest.php index 55cb9d7bfb..df8b9d0991 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringEqualsToTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringEqualsToTest.php @@ -6,25 +6,39 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringEqualsToTest extends FlowTestCase { public function test_equals_to_empty_strings(): void { - static::assertTrue(ref('str')->stringEqualsTo('')->eval(row(['str' => '']), flow_context())); + static::assertTrue( + ref('str') + ->stringEqualsTo('') + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()), + ); } public function test_equals_to_exact_match(): void { - static::assertTrue(ref('str')->stringEqualsTo('hello')->eval(row(['str' => 'hello']), flow_context())); + static::assertTrue( + ref('str') + ->stringEqualsTo('hello') + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), + ); } public function test_equals_to_no_match(): void { - static::assertFalse(ref('str')->stringEqualsTo('world')->eval(row(['str' => 'hello']), flow_context())); + static::assertFalse( + ref('str') + ->stringEqualsTo('world') + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), + ); } public function test_equals_to_null_comparison_string_returns_null(): void @@ -32,13 +46,23 @@ public function test_equals_to_null_comparison_string_returns_null(): void static::assertNull( ref('str') ->stringEqualsTo(ref('compare')) - ->eval(row(['str' => 'hello', 'compare' => null]), flow_context()), + ->eval( + array_to_row( + ['str' => 'hello', 'compare' => null], + schema(str_schema('str'), str_schema('compare', nullable: true)), + ), + flow_context(), + ), ); } public function test_equals_to_null_string_returns_null(): void { - static::assertNull(ref('str')->stringEqualsTo('hello')->eval(row(['str' => null]), flow_context())); + static::assertNull( + ref('str') + ->stringEqualsTo('hello') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()), + ); } public function test_equals_to_with_scalar_function_parameter(): void @@ -46,7 +70,13 @@ public function test_equals_to_with_scalar_function_parameter(): void static::assertTrue( ref('str') ->stringEqualsTo(ref('compare')) - ->eval(row(['str' => 'hello', 'compare' => 'hello']), flow_context()), + ->eval( + array_to_row( + ['str' => 'hello', 'compare' => 'hello'], + schema(str_schema('str'), str_schema('compare')), + ), + flow_context(), + ), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringFoldTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringFoldTest.php index f90d574f09..75affd5b85 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringFoldTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringFoldTest.php @@ -7,9 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringFoldTest extends FlowTestCase { @@ -17,7 +19,7 @@ public function test_string_folded(): void { static::assertSame("die o'brian strasse", ref('str') ->stringFold() - ->eval(row(['str' => "Die O'Brian Straße"]), flow_context())); + ->eval(array_to_row(['str' => "Die O'Brian Straße"], schema(str_schema('str'))), flow_context())); } public function test_string_fold_throws_on_null_input(): void @@ -25,6 +27,8 @@ public function test_string_fold_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringFold function requires non-null value'); - ref('str')->stringFold()->eval(row(['str' => null]), flow_context()); + ref('str') + ->stringFold() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchAllTest.php index 6f37097796..a56e7b0f9f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchAllTest.php @@ -7,29 +7,37 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringMatchAllTest extends FlowTestCase { public function test_empty_haystack_string(): void { - $result = ref('str')->stringMatchAll('/hello/')->eval(row(['str' => '']), flow_context()); + $result = ref('str') + ->stringMatchAll('/hello/') + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); static::assertEquals([], $result); } public function test_multiple_successful_pattern_matches(): void { - $result = ref('str')->stringMatchAll('/\d+/')->eval(row(['str' => 'test 123 and 456 and 789']), flow_context()); + $result = ref('str') + ->stringMatchAll('/\d+/') + ->eval(array_to_row(['str' => 'test 123 and 456 and 789'], schema(str_schema('str'))), flow_context()); static::assertEquals([['123'], ['456'], ['789']], $result); } public function test_no_matches_found(): void { - $result = ref('str')->stringMatchAll('/foo/')->eval(row(['str' => 'hello world']), flow_context()); + $result = ref('str') + ->stringMatchAll('/foo/') + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()); static::assertEquals([], $result); } @@ -39,7 +47,9 @@ public function test_null_haystack(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringMatchAll function requires non-null haystack'); - ref('str')->stringMatchAll('/hello/')->eval(row(['str' => null]), flow_context()); + ref('str') + ->stringMatchAll('/hello/') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_null_pattern(): void @@ -49,14 +59,26 @@ public function test_null_pattern(): void ref('str') ->stringMatchAll(ref('pattern')) - ->eval(row(['str' => 'hello world', 'pattern' => null]), flow_context()); + ->eval( + array_to_row( + ['str' => 'hello world', 'pattern' => null], + schema(str_schema('str'), str_schema('pattern', nullable: true)), + ), + flow_context(), + ); } public function test_with_scalar_function_parameter(): void { $result = ref('str') ->stringMatchAll(ref('pattern')) - ->eval(row(['str' => 'test 123 and 456', 'pattern' => '/\d+/']), flow_context()); + ->eval( + array_to_row( + ['str' => 'test 123 and 456', 'pattern' => '/\d+/'], + schema(str_schema('str'), str_schema('pattern')), + ), + flow_context(), + ); static::assertEquals([['123'], ['456']], $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchTest.php index 5fdfef9484..567952e402 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchTest.php @@ -7,15 +7,19 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringMatchTest extends FlowTestCase { public function test_no_matches_found(): void { - $result = ref('str')->stringMatch('/foo/')->eval(row(['str' => 'hello world']), flow_context()); + $result = ref('str') + ->stringMatch('/foo/') + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()); static::assertNull($result); } @@ -25,7 +29,9 @@ public function test_null_haystack(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringMatch function requires non-null haystack'); - $result = ref('str')->stringMatch('/hello/')->eval(row(['str' => null]), flow_context()); + $result = ref('str') + ->stringMatch('/hello/') + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); static::assertNull($result); } @@ -37,14 +43,22 @@ public function test_null_pattern(): void $result = ref('str') ->stringMatch(ref('pattern')) - ->eval(row(['str' => 'hello world', 'pattern' => null]), flow_context()); + ->eval( + array_to_row( + ['str' => 'hello world', 'pattern' => null], + schema(str_schema('str'), str_schema('pattern', nullable: true)), + ), + flow_context(), + ); static::assertNull($result); } public function test_successful_pattern_match(): void { - $result = ref('str')->stringMatch('/hello/')->eval(row(['str' => 'hello world']), flow_context()); + $result = ref('str') + ->stringMatch('/hello/') + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()); static::assertEquals(['hello'], $result); } @@ -53,7 +67,13 @@ public function test_with_scalar_function_parameter(): void { $result = ref('str') ->stringMatch(ref('pattern')) - ->eval(row(['str' => 'hello world', 'pattern' => '/world/']), flow_context()); + ->eval( + array_to_row( + ['str' => 'hello world', 'pattern' => '/world/'], + schema(str_schema('str'), str_schema('pattern')), + ), + flow_context(), + ); static::assertEquals(['world'], $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringNormalizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringNormalizeTest.php index 7164b7fbab..4b0e0266aa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringNormalizeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringNormalizeTest.php @@ -8,10 +8,13 @@ use Flow\ETL\Tests\FlowTestCase; use Normalizer; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringNormalizeTest extends FlowTestCase { @@ -19,38 +22,44 @@ public function test_a_malformed_form_operand_throws(): void { $this->expectException(InvalidArgumentException::class); - ref('value')->stringNormalize(lit('not-a-form'))->eval(row(['value' => 'abc']), flow_context()); + ref('value') + ->stringNormalize(lit('not-a-form')) + ->eval(array_to_row(['value' => 'abc'], schema(str_schema('value'))), flow_context()); } public function test_normalize_already_normalized(): void { static::assertSame('hello', ref('str') ->stringNormalize(Normalizer::NFC) - ->eval(row(['str' => 'hello']), flow_context())); + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_normalize_empty_string(): void { - static::assertSame('', ref('str')->stringNormalize()->eval(row(['str' => '']), flow_context())); + static::assertSame('', ref('str') + ->stringNormalize() + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); } public function test_normalize_nfc_default(): void { - static::assertSame('é', ref('str')->stringNormalize()->eval(row(['str' => "e\u{0301}"]), flow_context())); + static::assertSame('é', ref('str') + ->stringNormalize() + ->eval(array_to_row(['str' => "e\u{0301}"], schema(str_schema('str'))), flow_context())); } public function test_normalize_nfc_explicit(): void { static::assertSame('é', ref('str') ->stringNormalize(Normalizer::NFC) - ->eval(row(['str' => "e\u{0301}"]), flow_context())); + ->eval(array_to_row(['str' => "e\u{0301}"], schema(str_schema('str'))), flow_context())); } public function test_normalize_nfd(): void { static::assertSame("e\u{0301}", ref('str') ->stringNormalize(Normalizer::NFD) - ->eval(row(['str' => 'é']), flow_context())); + ->eval(array_to_row(['str' => 'é'], schema(str_schema('str'))), flow_context())); } public function test_normalize_throws_on_null_input(): void @@ -58,14 +67,22 @@ public function test_normalize_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringNormalize function requires non-null value'); - ref('str')->stringNormalize()->eval(row(['str' => null]), flow_context()); + ref('str') + ->stringNormalize() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_normalize_with_scalar_function_form(): void { $normalized = ref('str') ->stringNormalize(ref('form')) - ->eval(row(['str' => "e\u{0301}", 'form' => Normalizer::NFC]), flow_context()); + ->eval( + array_to_row( + ['str' => "e\u{0301}", 'form' => Normalizer::NFC], + schema(str_schema('str'), int_schema('form')), + ), + flow_context(), + ); static::assertSame('é', $normalized); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringStyleTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringStyleTest.php index 6c5420a708..5a8437b86f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringStyleTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringStyleTest.php @@ -9,9 +9,11 @@ use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringStyleTest extends FlowTestCase { @@ -20,7 +22,9 @@ public function test_a_null_value_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringStyle function requires non-null value'); - ref('value')->stringStyle(StringStyles::LOWER)->eval(row(['value' => null]), flow_context()); + ref('value') + ->stringStyle(StringStyles::LOWER) + ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()); } /** @@ -57,26 +61,34 @@ public function test_string_style_camel(): void { static::assertSame('fooBarBaz', ref('str') ->stringStyle(ref('style')) - ->eval(row(['str' => 'Foo: Bar-baz.', 'style' => 'camel']), flow_context())); + ->eval( + array_to_row( + ['str' => 'Foo: Bar-baz.', 'style' => 'camel'], + schema(str_schema('str'), str_schema('style')), + ), + flow_context(), + )); } public function test_string_style_kebab(): void { static::assertSame('foo-bar-baz', ref('str') ->stringStyle('kebab') - ->eval(row(['str' => 'Foo: Bar-baz.']), flow_context())); + ->eval(array_to_row(['str' => 'Foo: Bar-baz.'], schema(str_schema('str'))), flow_context())); } public function test_string_style_lower(): void { static::assertSame('foo bar bri̇an', ref('str') ->stringStyle('lower') - ->eval(row(['str' => 'FOO Bar Brİan']), flow_context())); + ->eval(array_to_row(['str' => 'FOO Bar Brİan'], schema(str_schema('str'))), flow_context())); } #[DataProvider('provideStringStyles')] public function test_string_styles(StringStyles $style, ?string $value, ?string $expected): void { - static::assertSame($expected, ref('str')->stringStyle($style)->eval(row(['str' => $value]), flow_context())); + static::assertSame($expected, ref('str') + ->stringStyle($style) + ->eval(array_to_row(['str' => $value], schema(str_schema('str', nullable: true))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringTitleTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringTitleTest.php index ae59f88bba..b168baa153 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringTitleTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringTitleTest.php @@ -7,22 +7,26 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringTitleTest extends FlowTestCase { public function test_string_title(): void { - static::assertSame('Foo ijssel', ref('str')->stringTitle()->eval(row(['str' => 'foo ijssel']), flow_context())); + static::assertSame('Foo ijssel', ref('str') + ->stringTitle() + ->eval(array_to_row(['str' => 'foo ijssel'], schema(str_schema('str'))), flow_context())); } public function test_string_title_allwords(): void { static::assertSame('Foo Ijssel', ref('str') ->stringTitle(allWords: true) - ->eval(row(['str' => 'foo ijssel']), flow_context())); + ->eval(array_to_row(['str' => 'foo ijssel'], schema(str_schema('str'))), flow_context())); } public function test_string_title_throws_on_null_input(): void @@ -30,6 +34,8 @@ public function test_string_title_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringTitle function requires non-null value'); - ref('str')->stringTitle()->eval(row(['str' => null]), flow_context()); + ref('str') + ->stringTitle() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringWidthTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringWidthTest.php index bd3d4dedf3..6e505d4d65 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringWidthTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringWidthTest.php @@ -7,20 +7,26 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class StringWidthTest extends FlowTestCase { public function test_width_ascii_string(): void { - static::assertSame(5, ref('str')->stringWidth()->eval(row(['str' => 'hello']), flow_context())); + static::assertSame(5, ref('str') + ->stringWidth() + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_width_empty_string(): void { - static::assertSame(0, ref('str')->stringWidth()->eval(row(['str' => '']), flow_context())); + static::assertSame(0, ref('str') + ->stringWidth() + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); } public function test_width_throws_on_null_input(): void @@ -28,11 +34,15 @@ public function test_width_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringWidth function requires non-null value'); - ref('str')->stringWidth()->eval(row(['str' => null]), flow_context()); + ref('str') + ->stringWidth() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_width_single_character(): void { - static::assertSame(1, ref('str')->stringWidth()->eval(row(['str' => 'a']), flow_context())); + static::assertSame(1, ref('str') + ->stringWidth() + ->eval(array_to_row(['str' => 'a'], schema(str_schema('str'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureSelectTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureSelectTest.php index 1d39ea81f9..763ef9c88d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureSelectTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureSelectTest.php @@ -10,13 +10,15 @@ use Flow\ETL\Function\StructureSelect; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_optional; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; @@ -26,10 +28,10 @@ public function test_selecting_multiple_values_from_structure(): void { static::assertEquals( ['id' => 1, 'name' => 'test'], - (new StructureSelect(ref('struct'), ref('id'), ref('name')))->eval(row(['struct' => [ + (new StructureSelect(ref('struct'), ref('id'), ref('name')))->eval(array_to_row(['struct' => [ 'id' => 1, 'name' => 'test', - ]]), flow_context()), + ]], schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()])))), flow_context()), ); } @@ -37,10 +39,10 @@ public function test_selecting_single_value_from_structure(): void { static::assertEquals( ['id' => 1], - (new StructureSelect(ref('struct'), 'id'))->eval(row(['struct' => [ + (new StructureSelect(ref('struct'), 'id'))->eval(array_to_row(['struct' => [ 'id' => 1, 'name' => 'test', - ]]), flow_context()), + ]], schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()])))), flow_context()), ); } @@ -48,10 +50,10 @@ public function test_selecting_single_value_from_structure_with_alias(): void { static::assertEquals( ['new_id' => 1], - (new StructureSelect(ref('struct'), ref('id')->as('new_id')))->eval(row(['struct' => [ + (new StructureSelect(ref('struct'), ref('id')->as('new_id')))->eval(array_to_row(['struct' => [ 'id' => 1, 'name' => 'test', - ]]), flow_context()), + ]], schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()])))), flow_context()), ); } @@ -59,11 +61,15 @@ public function test_selecting_values_from_empty_structure(): void { static::assertEquals( ['new_id' => null], - (new StructureSelect(ref('struct'), ref('id')->as('new_id')))->eval(row(['struct' => [ + (new StructureSelect(ref('struct'), ref('id')->as('new_id')))->eval(array_to_row(['struct' => [ 'id' => null, 'email' => 'email@email.com', 'name' => null, - ]]), flow_context()), + ]], schema(structure_schema('struct', type_structure([ + 'id' => type_optional(type_integer()), + 'email' => type_string(), + 'name' => type_optional(type_string()), + ])))), flow_context()), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureTest.php index 1bd6fc9edd..45e5be0682 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureTest.php @@ -9,11 +9,11 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure; @@ -25,11 +25,17 @@ public function test_eval_preserves_key_order(): void { static::assertSame( ['second' => 'x', 'first' => 1], - structure(['second' => ref('b'), 'first' => ref('a')])->eval(row([ - 'a' => 1, - 'b' => 'x', - 'q' => null, - ]), flow_context()), + structure(['second' => ref('b'), 'first' => ref('a')])->eval( + array_to_row( + [ + 'a' => 1, + 'b' => 'x', + 'q' => null, + ], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), + ), + flow_context(), + ), ); } @@ -37,11 +43,17 @@ public function test_eval_keeps_null_under_its_key(): void { static::assertSame( ['id' => 'x', 'quantity' => null], - structure(['id' => ref('b'), 'quantity' => ref('q')])->eval(row([ - 'a' => 1, - 'b' => 'x', - 'q' => null, - ]), flow_context()), + structure(['id' => ref('b'), 'quantity' => ref('q')])->eval( + array_to_row( + [ + 'a' => 1, + 'b' => 'x', + 'q' => null, + ], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), + ), + flow_context(), + ), ); } @@ -49,7 +61,13 @@ public function test_eval_with_numeric_keys(): void { static::assertSame( [5 => 1, 7 => 'x'], - structure([5 => ref('a'), 7 => ref('b')])->eval(row(['a' => 1, 'b' => 'x', 'q' => null]), flow_context()), + structure([5 => ref('a'), 7 => ref('b')])->eval( + array_to_row( + ['a' => 1, 'b' => 'x', 'q' => null], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), + ), + flow_context(), + ), ); } @@ -67,11 +85,17 @@ public function test_eval_nested_structure(): void { static::assertSame( ['user' => ['id' => 1]], - structure(['user' => structure(['id' => ref('a')])])->eval(row([ - 'a' => 1, - 'b' => 'x', - 'q' => null, - ]), flow_context()), + structure(['user' => structure(['id' => ref('a')])])->eval( + array_to_row( + [ + 'a' => 1, + 'b' => 'x', + 'q' => null, + ], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), + ), + flow_context(), + ), ); } @@ -127,7 +151,13 @@ public function test_with_children_keeps_keys(): void ['id' => 1, 'name' => 'x'], structure(['id' => ref('a'), 'name' => ref('b')]) ->withChildren([lit(1), lit('x')]) - ->eval(row(['a' => 1, 'b' => 'x', 'q' => null]), flow_context()), + ->eval( + array_to_row( + ['a' => 1, 'b' => 'x', 'q' => null], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), + ), + flow_context(), + ), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SumTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SumTest.php index d111edbe5f..e59ecb5fc8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SumTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SumTest.php @@ -8,18 +8,22 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; use function Flow\ETL\DSL\window; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; final class SumTest extends FlowTestCase { @@ -38,11 +42,13 @@ public function test_aggregation_sum_from_numeric_values(): void { $aggregator = sum(ref('int')); - $aggregator->aggregate(row(['int' => '10']), flow_context()); - $aggregator->aggregate(row(['int' => '20']), flow_context()); - $aggregator->aggregate(row(['int' => '55']), flow_context()); - $aggregator->aggregate(row(['int' => '25']), flow_context()); - $aggregator->aggregate(row(['not_int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'not_int' => null, + ], schema(str_schema('not_int', nullable: true))), flow_context()); static::assertSame(110.0, $aggregator->value()); } @@ -51,10 +57,12 @@ public function test_aggregation_sum_including_null_value(): void { $aggregator = sum(ref('int')); - $aggregator->aggregate(row(['int' => 10]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 30]), flow_context()); - $aggregator->aggregate(row(['int' => null]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row([ + 'int' => null, + ], schema(int_schema('int', nullable: true))), flow_context()); static::assertSame(60.0, $aggregator->value()); } @@ -63,10 +71,10 @@ public function test_aggregation_sum_with_float_result(): void { $aggregator = sum(ref('int')); - $aggregator->aggregate(row(['int' => 10.25]), flow_context()); - $aggregator->aggregate(row(['int' => 20]), flow_context()); - $aggregator->aggregate(row(['int' => 305]), flow_context()); - $aggregator->aggregate(row(['int' => 25]), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 10.25], schema(float_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 305], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); static::assertSame(360.25, $aggregator->value()); } @@ -75,18 +83,25 @@ public function test_aggregation_sum_of_decimal_fractions(): void { $aggregator = sum(ref('value')); - $aggregator->aggregate(row(['value' => 0.1]), flow_context()); - $aggregator->aggregate(row(['value' => 0.2]), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 0.1], schema(float_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 0.2], schema(float_schema('value'))), flow_context()); static::assertSame(0.30000000000000004, $aggregator->value()); } public function test_window_function_sum_of_decimal_fractions_uses_float_arithmetic_by_default(): void { - $rows = rows(schema(int_schema('id'), float_schema('value')), $row1 = row(['id' => 1, 'value' => 0.1]), row([ - 'id' => 2, - 'value' => 0.2, - ])); + $rows = rows( + schema(int_schema('id'), float_schema('value')), + $row1 = array_to_row(['id' => 1, 'value' => 0.1], schema(int_schema('id'), float_schema('value'))), + array_to_row( + [ + 'id' => 2, + 'value' => 0.2, + ], + schema(int_schema('id'), float_schema('value')), + ), + ); $sum = sum(ref('value'))->over(window()->orderBy(ref('id')->desc())); @@ -97,8 +112,8 @@ public function test_aggregation_sum_of_floats_stays_float_when_sum_is_whole(): { $aggregator = sum(ref('value')); - $aggregator->aggregate(row(['value' => 2.5]), flow_context()); - $aggregator->aggregate(row(['value' => 2.5]), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 2.5], schema(float_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 2.5], schema(float_schema('value'))), flow_context()); static::assertSame(5.0, $aggregator->value()); static::assertSame('?float', $aggregator->returns()->toString()); @@ -108,10 +123,10 @@ public function test_sum_over_an_int_column_declares_float(): void { $aggregator = sum(ref('value')); - $aggregator->aggregate(row(['value' => 1]), flow_context()); - $aggregator->aggregate(row(['value' => 2]), flow_context()); - $aggregator->aggregate(row(['value' => 3]), flow_context()); - $aggregator->aggregate(row(['value' => 4]), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 1], schema(int_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 2], schema(int_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 3], schema(int_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 4], schema(int_schema('value'))), flow_context()); static::assertSame(10.0, $aggregator->value()); static::assertSame('?float', $aggregator->returns()->toString()); @@ -124,15 +139,21 @@ public function test_a_malformed_exact_operand_throws_wrapped_as_a_sum_error(): $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Sum error:'); - $aggregator->aggregate(row(['value' => 0.1, 'exact' => ['not' => 'a boolean']]), flow_context()); + $aggregator->aggregate( + array_to_row( + ['value' => 0.1, 'exact' => ['not' => 'a boolean']], + schema(float_schema('value'), map_schema('exact', type_map(type_string(), type_string()))), + ), + flow_context(), + ); } public function test_exact_aggregation_sum_of_decimal_fractions(): void { $aggregator = sum(ref('value'), exact: true); - $aggregator->aggregate(row(['value' => 0.1]), flow_context()); - $aggregator->aggregate(row(['value' => 0.2]), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 0.1], schema(float_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_row(['value' => 0.2], schema(float_schema('value'))), flow_context()); static::assertSame(0.3, $aggregator->value()); } @@ -141,11 +162,11 @@ public function test_window_function_sum_on_partitioned_rows(): void { $rows = rows( schema(int_schema('id'), int_schema('value')), - $row1 = row(['id' => 1, 'value' => 1]), - row(['id' => 2, 'value' => 1]), - row(['id' => 3, 'value' => 1]), - row(['id' => 4, 'value' => 1]), - row(['id' => 5, 'value' => 1]), + $row1 = array_to_row(['id' => 1, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 2, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 3, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 4, 'value' => 1], schema(int_schema('id'), int_schema('value'))), + array_to_row(['id' => 5, 'value' => 1], schema(int_schema('id'), int_schema('value'))), ); $sum = sum(ref('id'))->over(window()->orderBy(ref('id')->desc())); @@ -155,10 +176,17 @@ public function test_window_function_sum_on_partitioned_rows(): void public function test_window_function_sum_of_decimal_fractions_in_exact_mode(): void { - $rows = rows(schema(int_schema('id'), float_schema('value')), $row1 = row(['id' => 1, 'value' => 0.1]), row([ - 'id' => 2, - 'value' => 0.2, - ])); + $rows = rows( + schema(int_schema('id'), float_schema('value')), + $row1 = array_to_row(['id' => 1, 'value' => 0.1], schema(int_schema('id'), float_schema('value'))), + array_to_row( + [ + 'id' => 2, + 'value' => 0.2, + ], + schema(int_schema('id'), float_schema('value')), + ), + ); $sum = sum(ref('value'), exact: true)->over(window()->orderBy(ref('id')->desc())); @@ -169,12 +197,18 @@ public function test_window_function_sum_with_exact_mode_from_column(): void { $rows = rows( schema(int_schema('id'), float_schema('value'), bool_schema('is_exact')), - $row1 = row(['id' => 1, 'value' => 0.1, 'is_exact' => true]), - row([ - 'id' => 2, - 'value' => 0.2, - 'is_exact' => true, - ]), + $row1 = array_to_row( + ['id' => 1, 'value' => 0.1, 'is_exact' => true], + schema(int_schema('id'), float_schema('value'), bool_schema('is_exact')), + ), + array_to_row( + [ + 'id' => 2, + 'value' => 0.2, + 'is_exact' => true, + ], + schema(int_schema('id'), float_schema('value'), bool_schema('is_exact')), + ), ); $sum = sum(ref('value'), exact: ref('is_exact'))->over(window()->orderBy(ref('id')->desc())); @@ -184,10 +218,17 @@ public function test_window_function_sum_with_exact_mode_from_column(): void public function test_window_function_sum_with_exact_mode_from_literal(): void { - $rows = rows(schema(int_schema('id'), float_schema('value')), $row1 = row(['id' => 1, 'value' => 0.1]), row([ - 'id' => 2, - 'value' => 0.2, - ])); + $rows = rows( + schema(int_schema('id'), float_schema('value')), + $row1 = array_to_row(['id' => 1, 'value' => 0.1], schema(int_schema('id'), float_schema('value'))), + array_to_row( + [ + 'id' => 2, + 'value' => 0.2, + ], + schema(int_schema('id'), float_schema('value')), + ), + ); $sum = sum(ref('value'), exact: lit(true))->over(window()->orderBy(ref('id')->desc())); @@ -199,7 +240,11 @@ public function test_window_function_sum_with_missing_reference_in_strict_mode() $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Sum window function error:'); - $rows = rows(schema(int_schema('id')), $row1 = row(['id' => 1]), row(['id' => 2])); + $rows = rows( + schema(int_schema('id')), + $row1 = array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + ); $sum = sum(ref('missing_column'))->over(window()->orderBy(ref('id'))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTest.php index 71aede9daa..360cedc703 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTest.php @@ -8,9 +8,13 @@ use DateTimeZone; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_date; final class ToDateTest extends FlowTestCase @@ -20,10 +24,10 @@ public function test_date_time_to_date(): void static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), to_date(ref('date_time')) - ->eval(row(['date_time' => new DateTimeImmutable( + ->eval(array_to_row(['date_time' => new DateTimeImmutable( '2020-01-01 12:43:23', new DateTimeZone('UTC'), - )]), flow_context()), + )], schema(datetime_schema('date_time'))), flow_context()), ); } @@ -32,9 +36,9 @@ public function test_int_to_date_time(): void static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), to_date(ref('int')) - ->eval(row([ + ->eval(array_to_row([ 'int' => (int) (new DateTimeImmutable('2020-01-01 10:11:11', new DateTimeZone('UTC')))->format('U'), - ]), flow_context()), + ], schema(int_schema('int'))), flow_context()), ); } @@ -42,7 +46,9 @@ public function test_string_to_date_time(): void { static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), - to_date(ref('string'), 'Y-m-d H:i:s')->eval(row(['string' => '2020-01-01 10:08:00']), flow_context()), + to_date(ref('string'), 'Y-m-d H:i:s')->eval(array_to_row([ + 'string' => '2020-01-01 10:08:00', + ], schema(str_schema('string'))), flow_context()), ); } } 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 956a4e35a8..040f492977 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 @@ -7,16 +7,20 @@ use DateTime; use DateTimeImmutable; use DateTimeZone; -use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; use stdClass; use function array_slice; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; 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\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_date_time; use function Flow\Types\DSL\type_datetime; @@ -69,10 +73,10 @@ public function test_date_time_to_date_time(): void static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), to_date_time(ref('date_time')) - ->eval(row(['date_time' => new DateTimeImmutable( + ->eval(array_to_row(['date_time' => new DateTimeImmutable( '2020-01-01 00:00:00', new DateTimeZone('UTC'), - )]), flow_context()), + )], schema(datetime_schema('date_time'))), flow_context()), ); } @@ -81,9 +85,9 @@ public function test_int_to_date_time(): void static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), to_date_time(ref('int')) - ->eval(row([ + ->eval(array_to_row([ 'int' => (int) (new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')))->format('U'), - ]), flow_context()), + ], schema(int_schema('int'))), flow_context()), ); } @@ -91,15 +95,17 @@ public function test_string_to_date_time(): void { static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), - to_date_time(ref('string'), 'Y-m-d H:i:s')->eval(row(['string' => '2020-01-01 00:00:00']), flow_context()), + to_date_time(ref('string'), 'Y-m-d H:i:s')->eval(array_to_row([ + 'string' => '2020-01-01 00:00:00', + ], schema(str_schema('string'))), flow_context()), ); } public function test_unparseable_string_to_date_time_is_null(): void { - static::assertNull(to_date_time(ref('string'), 'Y-m-d H:i:s')->eval(row([ + static::assertNull(to_date_time(ref('string'), 'Y-m-d H:i:s')->eval(array_to_row([ 'string' => 'not a datetime', - ]), flow_context())); + ], schema(str_schema('string'))), flow_context())); } public function test_constant_zone_returns_a_zoned_type(): void @@ -117,10 +123,10 @@ public function test_object_keeps_its_time(): void type_datetime() ->assert( to_date_time(ref('at')) - ->eval(row(['at' => new DateTimeImmutable( + ->eval(array_to_row(['at' => new DateTimeImmutable( '2020-01-01 10:30:00', new DateTimeZone('UTC'), - )]), flow_context()), + )], schema(datetime_schema('at'))), flow_context()), ) ->format('H:i:s'), ); @@ -131,9 +137,9 @@ public function test_int_lands_in_the_constant_zone(): void static::assertSame( '2020-01-01 11:30:00 Europe/Warsaw', type_datetime() - ->assert(to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('Europe/Warsaw'))->eval(row([ + ->assert(to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('Europe/Warsaw'))->eval(array_to_row([ 'at' => 1577874600, - ]), flow_context())) + ], schema(int_schema('at'))), flow_context())) ->format('Y-m-d H:i:s e'), ); } @@ -144,19 +150,19 @@ public function test_mutable_datetime_is_converted_without_mutation(): void static::assertEquals( new DateTimeImmutable('2020-01-01 11:30:00', new DateTimeZone('Europe/Warsaw')), - to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('Europe/Warsaw'))->eval(row([ + to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('Europe/Warsaw'))->eval(array_to_row([ 'at' => $value, - ]), flow_context()), + ], schema(datetime_schema('at'))), flow_context()), ); static::assertSame('2020-01-01 10:30:00 UTC', $value->format('Y-m-d H:i:s e')); } public function test_non_datetime_object_is_refused(): void { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Cannot create Definition from type'); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('ToDateTime function requires DateTimeInterface object'); - to_date_time(ref('at'))->eval(row(['at' => new stdClass()]), flow_context()); + to_date_time(lit(new stdClass()))->eval(array_to_row([], schema()), flow_context()); } public function test_string_in_a_utc_alias_zone_lands_in_utc(): void @@ -164,9 +170,9 @@ public function test_string_in_a_utc_alias_zone_lands_in_utc(): void static::assertSame( '2020-01-01 10:30:00 UTC', type_datetime() - ->assert(to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('GMT'))->eval(row([ + ->assert(to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('GMT'))->eval(array_to_row([ 'at' => '2020-01-01 10:30:00', - ]), flow_context())) + ], schema(str_schema('at'))), flow_context())) ->format('Y-m-d H:i:s e'), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToLowerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToLowerTest.php index 48f645394c..6dd194f27f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToLowerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToLowerTest.php @@ -6,15 +6,16 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\lower; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class ToLowerTest extends FlowTestCase { public function test_string_to_lower(): void { - static::assertSame('lower', lower(lit('LOWER'))->eval(row([]), flow_context())); + static::assertSame('lower', lower(lit('LOWER'))->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToTimeZoneTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToTimeZoneTest.php index 3f5f95d00e..be1d4fd7c0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToTimeZoneTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToTimeZoneTest.php @@ -12,10 +12,12 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException as TypesInvalidArgumentException; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_timezone; final class ToTimeZoneTest extends FlowTestCase @@ -36,7 +38,7 @@ public function test_casting_date_time_pst_to_utc_time_zone(): void $result = to_timezone( lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('PST'))), new DateTimeZone('UTC'), - )->eval(row([]), flow_context()); + )->eval(array_to_row([], schema()), flow_context()); static::assertInstanceOf(DateTimeInterface::class, $result); static::assertSame('2020-01-01 08:00:00.000000', $result->format('Y-m-d H:i:s.u')); } @@ -45,7 +47,7 @@ public function test_casting_date_time_pst_to_utc_time_zone_from_string_tz(): vo { // @mago-ignore analysis:mixed-assignment $result = to_timezone(lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('PST'))), 'UTC')->eval( - row([]), + array_to_row([], schema()), flow_context(), ); static::assertInstanceOf(DateTimeInterface::class, $result); @@ -56,7 +58,7 @@ public function test_does_not_mutate_a_datetime(): void { $value = new DateTime('2020-01-01 00:00:00 UTC'); - to_timezone(lit($value), 'Europe/Warsaw')->eval(row([]), flow_context()); + to_timezone(lit($value), 'Europe/Warsaw')->eval(array_to_row([], schema()), flow_context()); static::assertSame('UTC', $value->getTimezone()->getName()); } @@ -76,6 +78,8 @@ public function test_null_value_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ToTimeZone function requires non-null values'); - to_timezone(ref('at'), 'UTC')->eval(row(['at' => null]), flow_context()); + to_timezone(ref('at'), 'UTC')->eval(array_to_row([ + 'at' => null, + ], schema(str_schema('at', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToUpperTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToUpperTest.php index f733e5298a..af38dc4178 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToUpperTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToUpperTest.php @@ -6,15 +6,16 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\upper; final class ToUpperTest extends FlowTestCase { public function test_string_to_upper(): void { - static::assertSame('UPPER', upper(lit('upper'))->eval(row([]), flow_context())); + static::assertSame('UPPER', upper(lit('upper'))->eval(array_to_row([], schema()), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TrimTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TrimTest.php index c5fbf7ed16..1a9175c287 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TrimTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TrimTest.php @@ -7,28 +7,32 @@ use Flow\ETL\Function\Trim\Type; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class TrimTest extends FlowTestCase { public function test_trim_both_valid_string(): void { - static::assertSame('value', ref('string')->trim()->eval(row(['string' => ' value']), flow_context())); + static::assertSame('value', ref('string') + ->trim() + ->eval(array_to_row(['string' => ' value'], schema(str_schema('string'))), flow_context())); } public function test_trim_left_valid_string(): void { static::assertSame('value ', ref('string') ->trim(Type::LEFT) - ->eval(row(['string' => ' value ']), flow_context())); + ->eval(array_to_row(['string' => ' value '], schema(str_schema('string'))), flow_context())); } public function test_trim_right_valid_string(): void { static::assertSame(' value', ref('string') ->trim(Type::RIGHT) - ->eval(row(['string' => ' value ']), flow_context())); + ->eval(array_to_row(['string' => ' value '], schema(str_schema('string'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TruncateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TruncateTest.php index 226fd77964..290dfcf1e4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TruncateTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TruncateTest.php @@ -7,9 +7,12 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class TruncateTest extends FlowTestCase { @@ -17,17 +20,21 @@ public function test_truncate_ellipsis_longer_than_limit(): void { static::assertSame('hello', ref('str') ->truncate(5, 'verylongellipsis') - ->eval(row(['str' => 'hello world']), flow_context())); + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context())); } public function test_truncate_empty_string(): void { - static::assertSame('', ref('str')->truncate(10)->eval(row(['str' => '']), flow_context())); + static::assertSame('', ref('str') + ->truncate(10) + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); } public function test_truncate_exact_length(): void { - static::assertSame('hello', ref('str')->truncate(5)->eval(row(['str' => 'hello']), flow_context())); + static::assertSame('hello', ref('str') + ->truncate(5) + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_truncate_throws_on_null_input(): void @@ -35,59 +42,86 @@ public function test_truncate_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Truncate function requires non-null value'); - ref('str')->truncate(10)->eval(row(['str' => null]), flow_context()); + ref('str') + ->truncate(10) + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } public function test_truncate_string_longer_than_limit(): void { - static::assertSame('he...', ref('str')->truncate(5)->eval(row(['str' => 'hello world']), flow_context())); + static::assertSame('he...', ref('str') + ->truncate(5) + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context())); } public function test_truncate_string_shorter_than_limit(): void { - static::assertSame('hello', ref('str')->truncate(10)->eval(row(['str' => 'hello']), flow_context())); + static::assertSame('hello', ref('str') + ->truncate(10) + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_truncate_with_custom_ellipsis(): void { static::assertSame('he***', ref('str') ->truncate(5, '***') - ->eval(row(['str' => 'hello world']), flow_context())); + ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context())); } public function test_truncate_with_length_one(): void { - static::assertSame('h', ref('str')->truncate(1)->eval(row(['str' => 'hello']), flow_context())); + static::assertSame('h', ref('str') + ->truncate(1) + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_truncate_with_length_zero(): void { - static::assertSame('', ref('str')->truncate(0)->eval(row(['str' => 'hello']), flow_context())); + static::assertSame('', ref('str') + ->truncate(0) + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_truncate_with_negative_length(): void { - static::assertSame('hell', ref('str')->truncate(-1)->eval(row(['str' => 'hello']), flow_context())); + static::assertSame('hell', ref('str') + ->truncate(-1) + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_truncate_with_null_length(): void { static::assertSame('hello world', ref('str') ->truncate(ref('length')) - ->eval(row(['str' => 'hello world', 'length' => null]), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'length' => null], + schema(str_schema('str'), str_schema('length', nullable: true)), + ), + flow_context(), + )); } public function test_truncate_with_scalar_function_ellipsis(): void { static::assertSame('hel>>', ref('str') ->truncate(5, ref('ellipsis')) - ->eval(row(['str' => 'hello world', 'ellipsis' => '>>']), flow_context())); + ->eval( + array_to_row( + ['str' => 'hello world', 'ellipsis' => '>>'], + schema(str_schema('str'), str_schema('ellipsis')), + ), + flow_context(), + )); } public function test_truncate_with_scalar_function_length(): void { static::assertSame('he...', ref('str') ->truncate(ref('length')) - ->eval(row(['str' => 'hello world', 'length' => 5]), flow_context())); + ->eval( + array_to_row(['str' => 'hello world', 'length' => 5], schema(str_schema('str'), int_schema('length'))), + flow_context(), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UlidTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UlidTest.php index 6d8d1e4def..8c2df9e97a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UlidTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UlidTest.php @@ -8,9 +8,10 @@ use Flow\ETL\Tests\FlowTestCase; use Symfony\Component\Uid\Ulid; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\ulid; final class UlidTest extends FlowTestCase @@ -18,18 +19,24 @@ final class UlidTest extends FlowTestCase public function test_ulid_produces_a_string_column(): void { $expression = ulid(); - $result = $expression->eval(row([]), flow_context()); + $result = $expression->eval(array_to_row([], schema()), flow_context()); static::assertIsString($result); static::assertTrue(Ulid::isValid($result)); - static::assertNotSame($expression->eval(row([]), flow_context()), $expression->eval(row([]), flow_context())); + static::assertNotSame( + $expression->eval(array_to_row([], schema()), flow_context()), + $expression->eval(array_to_row([], schema()), flow_context()), + ); } public function test_ulid_is_unique(): void { $expression = ulid(); - static::assertNotEquals($expression->eval(row([]), flow_context()), $expression->eval(row([]), flow_context())); + static::assertNotEquals( + $expression->eval(array_to_row([], schema()), flow_context()), + $expression->eval(array_to_row([], schema()), flow_context()), + ); } public function test_ulid_with_invalid_value_throws(): void @@ -37,6 +44,6 @@ public function test_ulid_with_invalid_value_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Ulid requires valid ULID string: Invalid ULID'); - ulid(lit(''))->eval(row([]), flow_context()); + ulid(lit(''))->eval(array_to_row([], schema()), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UnicodeLengthTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UnicodeLengthTest.php index cb4d41d372..87ea1c4b7b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UnicodeLengthTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UnicodeLengthTest.php @@ -7,20 +7,26 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class UnicodeLengthTest extends FlowTestCase { public function test_unicode_length_ascii_string(): void { - static::assertSame(5, ref('str')->unicodeLength()->eval(row(['str' => 'hello']), flow_context())); + static::assertSame(5, ref('str') + ->unicodeLength() + ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); } public function test_unicode_length_empty_string(): void { - static::assertSame(0, ref('str')->unicodeLength()->eval(row(['str' => '']), flow_context())); + static::assertSame(0, ref('str') + ->unicodeLength() + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); } public function test_unicode_length_throws_on_null_input(): void @@ -28,6 +34,8 @@ public function test_unicode_length_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('UnicodeLength function requires non-null value'); - ref('str')->unicodeLength()->eval(row(['str' => null]), flow_context()); + ref('str') + ->unicodeLength() + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UuidTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UuidTest.php index 51b1e8e845..b47b91d186 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UuidTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UuidTest.php @@ -13,9 +13,10 @@ use Symfony\Component\Uid\Uuid as SymfonyUuid; use function class_exists; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\uuid_v4; use function Flow\ETL\DSL\uuid_v7; @@ -35,17 +36,23 @@ public function test_uuid4(): void } $expression = uuid_v4(); - $result = $expression->eval(row([]), flow_context()); + $result = $expression->eval(array_to_row([], schema()), flow_context()); static::assertInstanceOf(FlowUuid::class, $result); static::assertTrue(Uuid::isValid($result->toString())); - static::assertNotSame($expression->eval(row([]), flow_context()), $expression->eval(row([]), flow_context())); + static::assertNotSame( + $expression->eval(array_to_row([], schema()), flow_context()), + $expression->eval(array_to_row([], schema()), flow_context()), + ); } public function test_uuid4_is_unique(): void { $expression = uuid_v4(); - static::assertNotEquals($expression->eval(row([]), flow_context()), $expression->eval(row([]), flow_context())); + static::assertNotEquals( + $expression->eval(array_to_row([], schema()), flow_context()), + $expression->eval(array_to_row([], schema()), flow_context()), + ); } public function test_uuid7(): void @@ -55,7 +62,7 @@ public function test_uuid7(): void } $result = uuid_v7(lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')))) - ->eval(row([]), flow_context()); + ->eval(array_to_row([], schema()), flow_context()); static::assertInstanceOf(FlowUuid::class, $result); static::assertTrue(Uuid::isValid($result->toString())); } @@ -64,8 +71,8 @@ public function test_uuid7_is_unique(): void { $dateTime = lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC'))); static::assertNotEquals( - uuid_v7($dateTime)->eval(row([]), flow_context()), - uuid_v7($dateTime)->eval(row([]), flow_context()), + uuid_v7($dateTime)->eval(array_to_row([], schema()), flow_context()), + uuid_v7($dateTime)->eval(array_to_row([], schema()), flow_context()), ); } @@ -74,6 +81,6 @@ public function test_uuid_v7_requires_a_date_time(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Uuid uuid7 function requires a DateTimeInterface value'); - uuid_v7(lit(''))->eval(row([]), flow_context()); + uuid_v7(lit(''))->eval(array_to_row([], schema()), flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WhenTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WhenTest.php index 8e9fe97a25..8c36ad989c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WhenTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WhenTest.php @@ -8,41 +8,60 @@ use Flow\ETL\Function\When; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\when; final class WhenTest extends FlowTestCase { public function test_a_falsy_else_branch_is_returned(): void { - static::assertFalse(when(ref('active'), lit('yes'), false)->eval(row(['active' => false]), flow_context())); - static::assertSame(0, when(ref('active'), lit('yes'), 0)->eval(row(['active' => false]), flow_context())); - static::assertSame('', when(ref('active'), lit('yes'), '')->eval(row(['active' => false]), flow_context())); - static::assertSame([], when(ref('active'), lit('yes'), [])->eval(row(['active' => false]), flow_context())); - static::assertNull(when(ref('active'), lit('yes'))->eval(row(['active' => false]), flow_context())); + static::assertFalse(when(ref('active'), lit('yes'), false)->eval(array_to_row([ + 'active' => false, + ], schema(bool_schema('active'))), flow_context())); + static::assertSame(0, when(ref('active'), lit('yes'), 0)->eval(array_to_row([ + 'active' => false, + ], schema(bool_schema('active'))), flow_context())); + static::assertSame('', when(ref('active'), lit('yes'), '')->eval(array_to_row([ + 'active' => false, + ], schema(bool_schema('active'))), flow_context())); + static::assertSame( + [], + when(ref('active'), lit('yes'), [])->eval(array_to_row([ + 'active' => false, + ], schema(bool_schema('active'))), flow_context()), + ); + static::assertNull(when(ref('active'), lit('yes'))->eval(array_to_row([ + 'active' => false, + ], schema(bool_schema('active'))), flow_context())); } public function test_condition_not_satisfied_without_else(): void { - static::assertSame(1, (new When(ref('id')->equals(lit(2)), new Literal('then'), ref('id')))->eval(row([ + static::assertSame(1, (new When(ref('id')->equals(lit(2)), new Literal('then'), ref('id')))->eval(array_to_row([ 'id' => 1, - ]), flow_context())); + ], schema(int_schema('id'))), flow_context())); } public function test_else(): void { - static::assertSame('else', (new When(new Literal(false), new Literal('then'), new Literal('else')))->eval(row([ - 'id' => 1, - ]), flow_context())); + static::assertSame('else', (new When(new Literal(false), new Literal('then'), new Literal('else')))->eval( + array_to_row([ + 'id' => 1, + ], schema(int_schema('id'))), + flow_context(), + )); } public function test_when(): void { - static::assertSame('then', (new When(new Literal(true), new Literal('then')))->eval(row([ + static::assertSame('then', (new When(new Literal(true), new Literal('then')))->eval(array_to_row([ 'id' => 1, - ]), flow_context())); + ], schema(int_schema('id'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WordwrapTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WordwrapTest.php index b892f22fdd..8b69a21797 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WordwrapTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WordwrapTest.php @@ -7,22 +7,30 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class WordwrapTest extends FlowTestCase { public function test_empty_string(): void { - $result = ref('str')->wordwrap(10)->eval(row(['str' => '']), flow_context()); + $result = ref('str') + ->wordwrap(10) + ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); static::assertEquals('', $result); } public function test_normal_word_wrapping(): void { - $result = ref('str')->wordwrap(10)->eval(row(['str' => 'The quick brown fox jumps']), flow_context()); + $result = ref('str') + ->wordwrap(10) + ->eval(array_to_row(['str' => 'The quick brown fox jumps'], schema(str_schema('str'))), flow_context()); static::assertEquals("The quick\nbrown fox\njumps", $result); } @@ -31,7 +39,13 @@ public function test_null_break_character(): void { $result = ref('str') ->wordwrap(10, ref('break')) - ->eval(row(['str' => 'Hello World Test', 'break' => null]), flow_context()); + ->eval( + array_to_row( + ['str' => 'Hello World Test', 'break' => null], + schema(str_schema('str'), str_schema('break', nullable: true)), + ), + flow_context(), + ); static::assertEquals("Hello\nWorld Test", $result); } @@ -41,21 +55,27 @@ public function test_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Wordwrap function requires non-null value'); - $result = ref('str')->wordwrap(10)->eval(row(['str' => null]), flow_context()); + $result = ref('str') + ->wordwrap(10) + ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); static::assertNull($result); } public function test_text_shorter_than_width(): void { - $result = ref('str')->wordwrap(20)->eval(row(['str' => 'Hello']), flow_context()); + $result = ref('str') + ->wordwrap(20) + ->eval(array_to_row(['str' => 'Hello'], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello', $result); } public function test_width_zero(): void { - $result = ref('str')->wordwrap(0)->eval(row(['str' => 'Hello World']), flow_context()); + $result = ref('str') + ->wordwrap(0) + ->eval(array_to_row(['str' => 'Hello World'], schema(str_schema('str'))), flow_context()); static::assertEquals('Hello World', $result); } @@ -64,7 +84,13 @@ public function test_with_scalar_function_break(): void { $result = ref('str') ->wordwrap(10, ref('break')) - ->eval(row(['str' => 'Hello World Test', 'break' => ' | ']), flow_context()); + ->eval( + array_to_row( + ['str' => 'Hello World Test', 'break' => ' | '], + schema(str_schema('str'), str_schema('break')), + ), + flow_context(), + ); static::assertEquals('Hello | World Test', $result); } @@ -73,7 +99,10 @@ public function test_with_scalar_function_cut(): void { $result = ref('str') ->wordwrap(3, "\n", ref('cut')) - ->eval(row(['str' => 'Hello', 'cut' => true]), flow_context()); + ->eval( + array_to_row(['str' => 'Hello', 'cut' => true], schema(str_schema('str'), bool_schema('cut'))), + flow_context(), + ); static::assertEquals("Hel\nlo", $result); } @@ -82,7 +111,13 @@ public function test_with_scalar_function_width(): void { $result = ref('str') ->wordwrap(ref('width')) - ->eval(row(['str' => 'Hello World Test', 'width' => 8]), flow_context()); + ->eval( + array_to_row( + ['str' => 'Hello World Test', 'width' => 8], + schema(str_schema('str'), int_schema('width')), + ), + flow_context(), + ); static::assertEquals("Hello\nWorld\nTest", $result); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/XPathTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/XPathTest.php index 2ef26aa17f..f40c11543c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/XPathTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/XPathTest.php @@ -8,9 +8,11 @@ use DOMElement; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\xml_schema; final class XPathTest extends FlowTestCase { @@ -22,7 +24,9 @@ public function test_xpath_on_simple_xml_with_only_one_node_returned(): void static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertEquals( [$xml->documentElement->firstChild], - ref('value')->xpath('/root/foo')->eval(row(['value' => $xml]), flow_context()), + ref('value') + ->xpath('/root/foo') + ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), ); } @@ -37,7 +41,9 @@ public function test_xpath_when_there_are_more_than_one_elements_under_given_pat $xml->documentElement->firstChild, $xml->documentElement->lastChild, ], - ref('value')->xpath('/root/foo')->eval(row(['value' => $xml]), flow_context()), + ref('value') + ->xpath('/root/foo') + ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), ); } @@ -46,7 +52,11 @@ public function test_xpath_with_invalid_path_syntax(): void $xml = new DOMDocument(); $xml->loadXML('bar'); - static::assertNull(ref('value')->xpath('/root/foo/asa')->eval(row(['value' => $xml]), flow_context())); + static::assertNull( + ref('value') + ->xpath('/root/foo/asa') + ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), + ); } public function test_xpath_with_non_existing_path(): void @@ -54,7 +64,11 @@ public function test_xpath_with_non_existing_path(): void $xml = new DOMDocument(); $xml->loadXML('bar'); - static::assertNull(ref('value')->xpath('/root/bar')->eval(row(['value' => $xml]), flow_context())); + static::assertNull( + ref('value') + ->xpath('/root/bar') + ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), + ); } public function test_xpath_selecting_non_element_nodes_returns_null(): void @@ -62,7 +76,15 @@ public function test_xpath_selecting_non_element_nodes_returns_null(): void $xml = new DOMDocument(); $xml->loadXML('bar'); - static::assertNull(ref('value')->xpath('/root/foo/text()')->eval(row(['value' => $xml]), flow_context())); - static::assertNull(ref('value')->xpath('/root/foo/@baz')->eval(row(['value' => $xml]), flow_context())); + static::assertNull( + ref('value') + ->xpath('/root/foo/text()') + ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), + ); + static::assertNull( + ref('value') + ->xpath('/root/foo/@baz') + ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatedGroupsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatedGroupsTest.php index 20563bbfb4..5596db3603 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatedGroupsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatedGroupsTest.php @@ -11,13 +11,12 @@ use Flow\ETL\Tests\FlowTestCase; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; @@ -32,11 +31,11 @@ public function test_it_accumulates_rows_of_the_same_key_into_one_group(): void $input = schema(str_schema('country'), int_schema('amount')); $groups = new AggregatedGroups($groupBy, GroupByShape::of($groupBy, $input)); - $groups->accumulate( - rows($input, row(['country' => 'PL', 'amount' => 10]), row(['country' => 'DE', 'amount' => 20])), - flow_context(config()), - ); - $groups->accumulate(rows($input, row(['country' => 'PL', 'amount' => 30])), flow_context(config())); + $groups->accumulate(array_to_rows([ + ['country' => 'PL', 'amount' => 10], + ['country' => 'DE', 'amount' => 20], + ], $input), flow_context(config())); + $groups->accumulate(array_to_rows([['country' => 'PL', 'amount' => 30]], $input), flow_context(config())); /** @var list $batches */ $batches = iterator_to_array($groups->flush(1000)); @@ -60,7 +59,7 @@ public function test_the_flushed_batch_carries_the_shape_output_schema(): void $shape = GroupByShape::of($groupBy, $input); $groups = new AggregatedGroups($groupBy, $shape); - $groups->accumulate(rows($input, row(['country' => 'PL', 'amount' => 10])), flow_context(config())); + $groups->accumulate(array_to_rows([['country' => 'PL', 'amount' => 10]], $input), flow_context(config())); /** @var list $batches */ $batches = iterator_to_array($groups->flush(1000)); @@ -77,15 +76,11 @@ public function test_it_splits_the_flushed_groups_into_batches_of_the_requested_ $input = schema(str_schema('country'), int_schema('amount')); $groups = new AggregatedGroups($groupBy, GroupByShape::of($groupBy, $input)); - $groups->accumulate( - rows( - $input, - row(['country' => 'PL', 'amount' => 10]), - row(['country' => 'DE', 'amount' => 20]), - row(['country' => 'FR', 'amount' => 30]), - ), - flow_context(config()), - ); + $groups->accumulate(array_to_rows([ + ['country' => 'PL', 'amount' => 10], + ['country' => 'DE', 'amount' => 20], + ['country' => 'FR', 'amount' => 30], + ], $input), flow_context(config())); static::assertSame( [2, 1], @@ -114,10 +109,11 @@ public function test_a_row_missing_a_nullable_group_key_lands_in_the_null_group( $input = schema(str_schema('country', nullable: true), int_schema('amount')); $groups = new AggregatedGroups($groupBy, GroupByShape::of($groupBy, $input)); - $groups->accumulate( - rows($input, row(['amount' => 10]), row(['country' => 'PL', 'amount' => 20]), row(['amount' => 5])), - flow_context(config()), - ); + $groups->accumulate(array_to_rows([ + ['amount' => 10], + ['country' => 'PL', 'amount' => 20], + ['amount' => 5], + ], $input), flow_context(config())); /** @var list $batches */ $batches = iterator_to_array($groups->flush(1000)); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/BucketAggregationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/BucketAggregationTest.php index ae0474f3b2..da725d6cab 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/BucketAggregationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/BucketAggregationTest.php @@ -9,6 +9,7 @@ use Flow\ETL\GroupBy\BucketAggregation; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\first; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; @@ -16,7 +17,6 @@ use function Flow\ETL\DSL\last; use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -30,10 +30,9 @@ public function test_batch_size_bounds_result_batches(): void $groupBy->aggregate(sum(ref('v'))); $batches = (static function () { - yield rows( + yield array_to_rows( + [['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 10]], schema(str_schema('k'), int_schema('v')), - row(['k' => 'a', 'v' => 1]), - row(['k' => 'b', 'v' => 10]), ); })(); @@ -66,15 +65,13 @@ public function test_folds_groups_across_multiple_batches(): void $groupBy->aggregate(sum(ref('v'))); $batches = (static function () { - yield rows( + yield array_to_rows( + [['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 10]], schema(str_schema('k'), int_schema('v')), - row(['k' => 'a', 'v' => 1]), - row(['k' => 'b', 'v' => 10]), ); - yield rows( + yield array_to_rows( + [['k' => 'a', 'v' => 2], ['k' => 'b', 'v' => 20]], schema(str_schema('k'), int_schema('v')), - row(['k' => 'a', 'v' => 2]), - row(['k' => 'b', 'v' => 20]), ); })(); @@ -100,8 +97,8 @@ public function test_first_preserves_input_order_across_batches(): void $groupBy->aggregate(first(ref('v'))); $batches = (static function () { - yield rows(schema(str_schema('k'), int_schema('v')), row(['k' => 'a', 'v' => 100])); - yield rows(schema(str_schema('k'), int_schema('v')), row(['k' => 'a', 'v' => 200])); + yield array_to_rows([['k' => 'a', 'v' => 100]], schema(str_schema('k'), int_schema('v'))); + yield array_to_rows([['k' => 'a', 'v' => 200]], schema(str_schema('k'), int_schema('v'))); })(); $firsts = []; @@ -126,8 +123,8 @@ public function test_last_keeps_the_latest_across_batches(): void $groupBy->aggregate(last(ref('v'))); $batches = (static function () { - yield rows(schema(str_schema('k'), int_schema('v')), row(['k' => 'a', 'v' => 100])); - yield rows(schema(str_schema('k'), int_schema('v')), row(['k' => 'a', 'v' => 200])); + yield array_to_rows([['k' => 'a', 'v' => 100]], schema(str_schema('k'), int_schema('v'))); + yield array_to_rows([['k' => 'a', 'v' => 200]], schema(str_schema('k'), int_schema('v'))); })(); $lasts = []; @@ -151,10 +148,9 @@ public function test_a_leading_empty_batch_defers_the_bind_to_the_first_data_bat $batches = (static function () { yield rows(schema()); - yield rows( + yield array_to_rows( + [['k' => 'a', 'v' => 1], ['k' => 'a', 'v' => 2]], schema(str_schema('k'), int_schema('v')), - row(['k' => 'a', 'v' => 1]), - row(['k' => 'a', 'v' => 2]), ); })(); @@ -173,10 +169,9 @@ public function test_groups_in_one_run_share_one_output_definition(): void $groupBy->aggregate(min(ref('v'))); $batches = (static function () { - yield rows( + yield array_to_rows( + [['k' => 'a', 'v' => 10.0], ['k' => 'b', 'v' => 0.5]], schema(str_schema('k'), float_schema('v')), - row(['k' => 'a', 'v' => 10.0]), - row(['k' => 'b', 'v' => 0.5]), ); })(); @@ -206,10 +201,9 @@ public function test_a_group_whose_aggregated_column_is_absent_emits_null_under_ $groupBy->aggregate(min(ref('v'))); $batches = (static function () { - yield rows( + yield array_to_rows( + [['k' => 'a'], ['k' => 'a']], schema(str_schema('k'), float_schema('v', nullable: true)), - row(['k' => 'a']), - row(['k' => 'a']), ); })(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/GroupByStepsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/GroupByStepsTest.php index e2d1f0da4d..0ec2ff9e39 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/GroupByStepsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/GroupByStepsTest.php @@ -15,6 +15,7 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\PruneEntriesTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\config_builder; @@ -25,8 +26,6 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\pivot_values; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; @@ -78,9 +77,9 @@ public function test_groups_across_multiple_batches(): void $result = GroupByContext::aggregate( $groupBy, flow_context(config_builder()->groupBy(hash_group_by()->storage(new MemoryBuckets()))->build()), - rows(schema(str_schema('category'), int_schema('amount')), row(['category' => 'a', 'amount' => 10])), - rows(schema(str_schema('category'), int_schema('amount')), row(['category' => 'a', 'amount' => 20])), - rows(schema(str_schema('category'), int_schema('amount')), row(['category' => 'b', 'amount' => 15])), + array_to_rows([['category' => 'a', 'amount' => 10]], schema(str_schema('category'), int_schema('amount'))), + array_to_rows([['category' => 'a', 'amount' => 20]], schema(str_schema('category'), int_schema('amount'))), + array_to_rows([['category' => 'b', 'amount' => 15]], schema(str_schema('category'), int_schema('amount'))), ); $aggregated = []; @@ -106,11 +105,13 @@ public function test_aggregates_each_bucket_separately_with_single_bucket(): voi flow_context( config_builder()->groupBy(hash_group_by()->storage(new MemoryBuckets())->bucketsCount(1))->build(), ), - rows( + array_to_rows( + [ + ['category' => 'a', 'amount' => 10], + ['category' => 'b', 'amount' => 15], + ['category' => 'a', 'amount' => 20], + ], schema(str_schema('category'), int_schema('amount')), - row(['category' => 'a', 'amount' => 10]), - row(['category' => 'b', 'amount' => 15]), - row(['category' => 'a', 'amount' => 20]), ), ); @@ -136,10 +137,9 @@ public function test_aggregates_many_buckets_and_flushes_per_bucket(): void $batches = []; for ($id = 0; $id < 20; $id++) { - $batches[] = rows( + $batches[] = array_to_rows( + [['id' => $id, 'amount' => 1], ['id' => $id, 'amount' => 2]], schema(int_schema('id'), int_schema('amount')), - row(['id' => $id, 'amount' => 1]), - row(['id' => $id, 'amount' => 2]), ); } @@ -176,10 +176,9 @@ public function test_removes_storage_buckets_after_last_bucket(): void GroupByContext::aggregate( $groupBy, flow_context(config_builder()->groupBy(hash_group_by()->storage($storage))->build()), - rows( + array_to_rows( + [['category' => 'a', 'amount' => 10], ['category' => 'b', 'amount' => 15]], schema(str_schema('category'), int_schema('amount')), - row(['category' => 'a', 'amount' => 10]), - row(['category' => 'b', 'amount' => 15]), ), ); @@ -195,11 +194,9 @@ public function test_groups_rows_missing_group_column_under_null(): void $result = GroupByContext::aggregate( $groupBy, flow_context(config_builder()->groupBy(hash_group_by()->storage(new MemoryBuckets()))->build()), - rows( + array_to_rows( + [['category' => 'a', 'amount' => 10], ['amount' => 15], ['amount' => 20]], schema(str_schema('category', nullable: true), int_schema('amount')), - row(['category' => 'a', 'amount' => 10]), - row(['amount' => 15]), - row(['amount' => 20]), ), ); @@ -226,10 +223,12 @@ public function test_spills_only_grouping_and_aggregation_columns(): void GroupByContext::aggregate( $groupBy, flow_context(config_builder()->groupBy(hash_group_by()->storage($storage))->build()), - rows( + array_to_rows( + [ + ['category' => 'a', 'amount' => 10, 'noise' => 'x', 'id' => 1], + ['category' => 'b', 'amount' => 15, 'noise' => 'y', 'id' => 2], + ], schema(str_schema('category'), int_schema('amount'), str_schema('noise'), int_schema('id')), - row(['category' => 'a', 'amount' => 10, 'noise' => 'x', 'id' => 1]), - row(['category' => 'b', 'amount' => 15, 'noise' => 'y', 'id' => 2]), ), ); @@ -252,10 +251,12 @@ public function test_spills_all_columns_when_aggregator_references_cannot_be_enu $result = GroupByContext::aggregate( $groupBy, flow_context(config_builder()->groupBy(hash_group_by()->storage($storage))->build()), - rows( + array_to_rows( + [ + ['category' => 'a', 'amount' => 0.1, 'flag' => true], + ['category' => 'a', 'amount' => 0.2, 'flag' => true], + ], schema(str_schema('category'), float_schema('amount'), bool_schema('flag')), - row(['category' => 'a', 'amount' => 0.1, 'flag' => true]), - row(['category' => 'a', 'amount' => 0.2, 'flag' => true]), ), ); @@ -279,10 +280,9 @@ public function test_missing_aggregated_column_is_treated_as_null_in_strict_mode $result = GroupByContext::aggregate( $groupBy, $context, - rows( + array_to_rows( + [['category' => 'a', 'amount' => 10], ['category' => 'a']], schema(str_schema('category'), int_schema('amount', nullable: true)), - row(['category' => 'a', 'amount' => 10]), - row(['category' => 'a']), ), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/PivotAggregationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/PivotAggregationTest.php index cb68d9f35b..993fa70c54 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/PivotAggregationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/PivotAggregationTest.php @@ -12,14 +12,13 @@ use Flow\ETL\Tests\FlowTestCase; use Generator; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\pivot_values; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; @@ -46,8 +45,8 @@ public function test_a_bound_aggregation_pivots_without_reading_a_schema_from_th /** @var list $batches */ $batches = iterator_to_array((new PivotAggregation())->aggregateBound( (static function () use ($input): Generator { - yield rows($input, row(['product' => 'Banana', 'country' => 'USA', 'amount' => 30])); - yield rows($input, row(['product' => 'Banana', 'country' => 'USA', 'amount' => 10])); + yield array_to_rows([['product' => 'Banana', 'country' => 'USA', 'amount' => 30]], $input); + yield array_to_rows([['product' => 'Banana', 'country' => 'USA', 'amount' => 10]], $input); })(), flow_context(config()), $groupBy, @@ -86,12 +85,11 @@ public function test_it_splits_the_result_into_batches_of_the_requested_size(): 2, iterator_to_array((new PivotAggregation(2))->aggregateBound( (static function () use ($input): Generator { - yield rows( - $input, - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 1]), - row(['product' => 'Apple', 'country' => 'USA', 'amount' => 2]), - row(['product' => 'Cherry', 'country' => 'USA', 'amount' => 3]), - ); + yield array_to_rows([ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 1], + ['product' => 'Apple', 'country' => 'USA', 'amount' => 2], + ['product' => 'Cherry', 'country' => 'USA', 'amount' => 3], + ], $input); })(), flow_context(config()), $groupBy, diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/PivotedTableTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/PivotedTableTest.php index 17e1213942..a363c59075 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/PivotedTableTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/PivotedTableTest.php @@ -10,12 +10,11 @@ use Flow\ETL\Tests\Mother\PivotedTableMother; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\sum; final class PivotedTableTest extends FlowTestCase @@ -24,18 +23,15 @@ public function test_it_accumulates_rows_of_the_same_key_across_batches(): void { $table = PivotedTableMother::of(sum(ref('amount')), 'USA', 'PL'); - $table->accumulate( - rows( - PivotedTableMother::schema(), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 10]), - row(['product' => 'Banana', 'country' => 'PL', 'amount' => 20]), - ), - flow_context(config()), - ); - $table->accumulate( - rows(PivotedTableMother::schema(), row(['product' => 'Banana', 'country' => 'USA', 'amount' => 5])), - flow_context(config()), - ); + $table->accumulate(array_to_rows([ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 10], + ['product' => 'Banana', 'country' => 'PL', 'amount' => 20], + ], PivotedTableMother::schema()), flow_context(config())); + $table->accumulate(array_to_rows([[ + 'product' => 'Banana', + 'country' => 'USA', + 'amount' => 5, + ]], PivotedTableMother::schema()), flow_context(config())); /** @var list $batches */ $batches = iterator_to_array($table->flush(1000, flow_context(config()))); @@ -48,10 +44,11 @@ public function test_a_pivot_value_never_seen_becomes_null(): void { $table = PivotedTableMother::of(sum(ref('amount')), 'USA', 'PL'); - $table->accumulate( - rows(PivotedTableMother::schema(), row(['product' => 'Banana', 'country' => 'USA', 'amount' => 10])), - flow_context(config()), - ); + $table->accumulate(array_to_rows([[ + 'product' => 'Banana', + 'country' => 'USA', + 'amount' => 10, + ]], PivotedTableMother::schema()), flow_context(config())); /** @var list $batches */ $batches = iterator_to_array($table->flush(1000, flow_context(config()))); @@ -64,10 +61,11 @@ public function test_a_null_pivot_value_keeps_the_group_row_and_feeds_no_column( $input = PivotedTableMother::schema(nullableCountry: true); $table = PivotedTableMother::boundTo($input, sum(ref('amount')), 'USA'); - $table->accumulate( - rows($input, row(['product' => 'Banana', 'country' => null, 'amount' => 10])), - flow_context(config()), - ); + $table->accumulate(array_to_rows([[ + 'product' => 'Banana', + 'country' => null, + 'amount' => 10, + ]], $input), flow_context(config())); /** @var list $batches */ $batches = iterator_to_array($table->flush(1000, flow_context(config()))); @@ -79,14 +77,10 @@ public function test_a_pivot_value_outside_the_declared_values_is_discarded(): v { $table = PivotedTableMother::of(sum(ref('amount')), 'USA'); - $table->accumulate( - rows( - PivotedTableMother::schema(), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 30]), - row(['product' => 'Banana', 'country' => 'DE', 'amount' => 99]), - ), - flow_context(config()), - ); + $table->accumulate(array_to_rows([ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 30], + ['product' => 'Banana', 'country' => 'DE', 'amount' => 99], + ], PivotedTableMother::schema()), flow_context(config())); /** @var list $batches */ $batches = iterator_to_array($table->flush(1000, flow_context(config()))); @@ -99,15 +93,11 @@ public function test_it_splits_the_flushed_rows_into_batches_of_the_requested_si { $table = PivotedTableMother::of(sum(ref('amount')), 'USA'); - $table->accumulate( - rows( - PivotedTableMother::schema(), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 10]), - row(['product' => 'Apple', 'country' => 'USA', 'amount' => 20]), - row(['product' => 'Cherry', 'country' => 'USA', 'amount' => 30]), - ), - flow_context(config()), - ); + $table->accumulate(array_to_rows([ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 10], + ['product' => 'Apple', 'country' => 'USA', 'amount' => 20], + ['product' => 'Cherry', 'country' => 'USA', 'amount' => 30], + ], PivotedTableMother::schema()), flow_context(config())); static::assertSame( [2, 1], @@ -139,14 +129,10 @@ public function test_an_argument_typed_aggregate_keeps_its_resolved_column_type( { $table = PivotedTableMother::of(min(ref('amount')), 'USA'); - $table->accumulate( - rows( - PivotedTableMother::schema(), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 30]), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 10]), - ), - flow_context(config()), - ); + $table->accumulate(array_to_rows([ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 30], + ['product' => 'Banana', 'country' => 'USA', 'amount' => 10], + ], PivotedTableMother::schema()), flow_context(config())); /** @var list $batches */ $batches = iterator_to_array($table->flush(1000, flow_context(config()))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php index 28b472bb46..081963cd5b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php @@ -14,6 +14,8 @@ use Flow\ETL\Tests\FlowTestCase; use Generator; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\count; use function Flow\ETL\DSL\float_schema; @@ -22,8 +24,6 @@ use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\pivot_values; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; @@ -38,11 +38,9 @@ public function test_group_by_missing_entry(): void $result = GroupByContext::aggregated( $groupBy, flow_context(config()), - rows( + array_to_rows( + [['type' => 'a'], ['not-type' => 'b'], ['type' => 'c']], schema(str_schema('type', nullable: true), str_schema('not-type', nullable: true)), - row(['type' => 'a']), - row(['not-type' => 'b']), - row(['type' => 'c']), ), ); @@ -65,13 +63,15 @@ public function test_group_by_with_aggregation(): void $result = GroupByContext::aggregated( $group, flow_context(config()), - rows( + array_to_rows( + [ + ['id' => 1, 'type' => 'a'], + ['id' => 2, 'type' => 'b'], + ['id' => 3, 'type' => 'c'], + ['id' => 4, 'type' => 'a'], + ['id' => 5, 'type' => 'd'], + ], schema(int_schema('id'), str_schema('type')), - row(['id' => 1, 'type' => 'a']), - row(['id' => 2, 'type' => 'b']), - row(['id' => 3, 'type' => 'c']), - row(['id' => 4, 'type' => 'a']), - row(['id' => 5, 'type' => 'd']), ), ); @@ -116,9 +116,9 @@ public function test_a_pivot_declares_its_output_schema(): void $schema = iterator_to_array((new PivotAggregation())->aggregate( (static function (): Generator { - yield rows( + yield array_to_rows( + [['product' => 'Banana', 'country' => 'USA', 'amount' => 1000]], schema(str_schema('product'), str_schema('country'), int_schema('amount')), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 1000]), ); })(), flow_context(config()), @@ -198,10 +198,12 @@ public function test_an_unbound_pivot_resolves_an_argument_typed_aggregate(): vo $result = iterator_to_array((new PivotAggregation())->aggregate( (static function (): Generator { - yield rows( + yield array_to_rows( + [ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 30], + ['product' => 'Banana', 'country' => 'USA', 'amount' => 10], + ], schema(str_schema('product'), str_schema('country'), int_schema('amount')), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 30]), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 10]), ); })(), flow_context(config()), @@ -230,10 +232,12 @@ public function test_a_falsy_pivot_value_keeps_its_column(): void $result = iterator_to_array((new PivotAggregation())->aggregate( (static function (): Generator { - yield rows( + yield array_to_rows( + [ + ['product' => 'Banana', 'country' => '0', 'amount' => 7], + ['product' => 'Banana', 'country' => 'USA', 'amount' => 3], + ], schema(str_schema('product'), str_schema('country'), int_schema('amount')), - row(['product' => 'Banana', 'country' => '0', 'amount' => 7]), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 3]), ); })(), flow_context(config()), @@ -251,7 +255,13 @@ public function test_group_by_with_pivoting(): void $group->pivot(ref('country'), pivot_values('Canada', 'China', 'Mexico', 'USA')); static::assertEquals( - rows( + array_to_rows( + [ + ['product' => 'Banana', 'Canada' => 2000.0, 'China' => 400.0, 'Mexico' => null, 'USA' => 1000.0], + ['product' => 'Beans', 'Canada' => null, 'China' => 1500.0, 'Mexico' => 2000.0, 'USA' => 1600.0], + ['product' => 'Carrots', 'Canada' => 2000.0, 'China' => 1200.0, 'Mexico' => null, 'USA' => 1500.0], + ['product' => 'Orange', 'Canada' => null, 'China' => 4000.0, 'Mexico' => null, 'USA' => 4000.0], + ], schema( str_schema('product'), // PivotSchema declares every pivot column optional: the yield loop writes null @@ -261,28 +271,26 @@ public function test_group_by_with_pivoting(): void float_schema('Mexico', nullable: true), float_schema('USA', nullable: true), ), - row(['product' => 'Banana', 'Canada' => 2000.0, 'China' => 400.0, 'Mexico' => null, 'USA' => 1000.0]), - row(['product' => 'Beans', 'Canada' => null, 'China' => 1500.0, 'Mexico' => 2000.0, 'USA' => 1600.0]), - row(['product' => 'Carrots', 'Canada' => 2000.0, 'China' => 1200.0, 'Mexico' => null, 'USA' => 1500.0]), - row(['product' => 'Orange', 'Canada' => null, 'China' => 4000.0, 'Mexico' => null, 'USA' => 4000.0]), ), GroupByContext::aggregated( $group, flow_context(config()), - rows( + array_to_rows( + [ + ['product' => 'Banana', 'amount' => 1000, 'country' => 'USA'], + ['product' => 'Carrots', 'amount' => 1500, 'country' => 'USA'], + ['product' => 'Beans', 'amount' => 1600, 'country' => 'USA'], + ['product' => 'Orange', 'amount' => 2000, 'country' => 'USA'], + ['product' => 'Orange', 'amount' => 2000, 'country' => 'USA'], + ['product' => 'Banana', 'amount' => 400, 'country' => 'China'], + ['product' => 'Carrots', 'amount' => 1200, 'country' => 'China'], + ['product' => 'Beans', 'amount' => 1500, 'country' => 'China'], + ['product' => 'Orange', 'amount' => 4000, 'country' => 'China'], + ['product' => 'Banana', 'amount' => 2000, 'country' => 'Canada'], + ['product' => 'Carrots', 'amount' => 2000, 'country' => 'Canada'], + ['product' => 'Beans', 'amount' => 2000, 'country' => 'Mexico'], + ], schema(str_schema('product'), int_schema('amount'), str_schema('country')), - row(['product' => 'Banana', 'amount' => 1000, 'country' => 'USA']), - row(['product' => 'Carrots', 'amount' => 1500, 'country' => 'USA']), - row(['product' => 'Beans', 'amount' => 1600, 'country' => 'USA']), - row(['product' => 'Orange', 'amount' => 2000, 'country' => 'USA']), - row(['product' => 'Orange', 'amount' => 2000, 'country' => 'USA']), - row(['product' => 'Banana', 'amount' => 400, 'country' => 'China']), - row(['product' => 'Carrots', 'amount' => 1200, 'country' => 'China']), - row(['product' => 'Beans', 'amount' => 1500, 'country' => 'China']), - row(['product' => 'Orange', 'amount' => 4000, 'country' => 'China']), - row(['product' => 'Banana', 'amount' => 2000, 'country' => 'Canada']), - row(['product' => 'Carrots', 'amount' => 2000, 'country' => 'Canada']), - row(['product' => 'Beans', 'amount' => 2000, 'country' => 'Mexico']), ), )->sortBy(ref('product')), ); @@ -295,18 +303,19 @@ public function test_group_by_with_pivoting_with_null_pivot_column(): void $group->pivot(ref('country'), pivot_values('USA')); static::assertEquals( - rows( + array_to_rows( + [['product' => 'Apple', 'USA' => null], ['product' => 'Banana', 'USA' => 1000.0]], schema(str_schema('product'), float_schema('USA', nullable: true)), - row(['product' => 'Apple', 'USA' => null]), - row(['product' => 'Banana', 'USA' => 1000.0]), ), GroupByContext::aggregated( $group, flow_context(config()), - rows( + array_to_rows( + [ + ['product' => 'Banana', 'country' => 'USA', 'amount' => 1000], + ['product' => 'Apple', 'country' => null, 'amount' => 400], + ], schema(str_schema('product'), str_schema('country', nullable: true), int_schema('amount')), - row(['product' => 'Banana', 'country' => 'USA', 'amount' => 1000]), - row(['product' => 'Apple', 'country' => null, 'amount' => 400]), ), )->sortBy(ref('product')), ); @@ -327,7 +336,7 @@ public function test_a_group_column_absent_from_the_schema_is_refused_at_bind(): GroupByContext::aggregated( $groupBy, flow_context(config()), - rows(schema(str_schema('type')), row(['type' => 'a']), row(['type' => 'b'])), + array_to_rows([['type' => 'a'], ['type' => 'b']], schema(str_schema('type'))), ); } @@ -362,7 +371,10 @@ public function test_key_values_throws_when_a_row_lacks_a_not_null_key(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Column "country" does not exist.'); - (new GroupBy('country'))->keyValues(row(['age' => 20]), schema(str_schema('country'), int_schema('age'))); + (new GroupBy('country'))->keyValues( + array_to_row(['age' => 20], schema(int_schema('age'))), + schema(str_schema('country'), int_schema('age')), + ); } public function test_key_values_substitutes_null_when_a_row_lacks_a_nullable_key(): void @@ -370,7 +382,7 @@ public function test_key_values_substitutes_null_when_a_row_lacks_a_nullable_key static::assertSame( ['country' => null], iterator_to_array((new GroupBy('country'))->keyValues( - row(['age' => 20]), + array_to_row(['age' => 20], schema(int_schema('age'))), schema(str_schema('country', nullable: true), int_schema('age')), )), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AllTest.php index 20cd70e31d..8200d42885 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AllTest.php @@ -8,7 +8,9 @@ use Flow\ETL\Join\Comparison\All; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; final class AllTest extends FlowTestCase { @@ -20,7 +22,10 @@ public function test_failure(): void $comparison2 = self::createStub(Comparison::class); $comparison2->method('compare')->willReturn(false); - static::assertFalse((new All($comparison1, $comparison2))->compare(row(['id' => 1]), row(['id' => 2]))); + static::assertFalse((new All($comparison1, $comparison2))->compare( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + )); } public function test_success(): void @@ -31,6 +36,9 @@ public function test_success(): void $comparison2 = self::createStub(Comparison::class); $comparison2->method('compare')->willReturn(true); - static::assertTrue((new All($comparison1, $comparison2))->compare(row(['id' => 1]), row(['id' => 2]))); + static::assertTrue((new All($comparison1, $comparison2))->compare( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AnyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AnyTest.php index 1808dd0a2f..25920a3021 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AnyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AnyTest.php @@ -8,7 +8,9 @@ use Flow\ETL\Join\Comparison\Any; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; final class AnyTest extends FlowTestCase { @@ -20,7 +22,10 @@ public function test_failure(): void $comparison2 = self::createStub(Comparison::class); $comparison2->method('compare')->willReturn(false); - static::assertFalse((new Any($comparison1, $comparison2))->compare(row(['id' => 1]), row(['id' => 2]))); + static::assertFalse((new Any($comparison1, $comparison2))->compare( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + )); } public function test_success(): void @@ -31,6 +36,9 @@ public function test_success(): void $comparison2 = self::createStub(Comparison::class); $comparison2->method('compare')->willReturn(false); - static::assertTrue((new Any($comparison1, $comparison2))->compare(row(['id' => 1]), row(['id' => 2]))); + static::assertTrue((new Any($comparison1, $comparison2))->compare( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/EqualTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/EqualTest.php index d0a32ae599..ff9989029d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/EqualTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/EqualTest.php @@ -8,58 +8,77 @@ use Flow\ETL\Join\Comparison\Equal; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class EqualTest extends FlowTestCase { public function test_failure(): void { static::assertFalse((new Equal('datetime', 'datetime'))->compare( - row(['datetime' => new DateTimeImmutable('2022-10-01 00:00:00')]), - row(['datetime' => new DateTimeImmutable('2022-10-01 01:00:00')]), + array_to_row([ + 'datetime' => new DateTimeImmutable('2022-10-01 00:00:00'), + ], schema(datetime_schema('datetime'))), + array_to_row([ + 'datetime' => new DateTimeImmutable('2022-10-01 01:00:00'), + ], schema(datetime_schema('datetime'))), )); } public function test_null_is_not_equal_to_null(): void { - static::assertFalse((new Equal('id', 'id'))->compare(row(['id' => null]), row(['id' => null]))); + static::assertFalse((new Equal('id', 'id'))->compare( + array_to_row(['id' => null], schema(str_schema('id', nullable: true))), + array_to_row(['id' => null], schema(str_schema('id', nullable: true))), + )); } public function test_null_is_not_equal_to_value(): void { - static::assertFalse((new Equal('id', 'id'))->compare(row(['id' => null]), row(['id' => 1]))); - static::assertFalse((new Equal('id', 'id'))->compare(row(['id' => 1]), row(['id' => null]))); + static::assertFalse((new Equal('id', 'id'))->compare( + array_to_row(['id' => null], schema(int_schema('id', nullable: true))), + array_to_row(['id' => 1], schema(int_schema('id'))), + )); + static::assertFalse((new Equal('id', 'id'))->compare( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => null], schema(int_schema('id', nullable: true))), + )); } public function test_object_and_scalar_are_not_equal(): void { static::assertFalse((new Equal('id', 'id'))->compare( - row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']), - row(['id' => 1]), + array_to_row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479'], schema(str_schema('id'))), + array_to_row(['id' => 1], schema(int_schema('id'))), )); } public function test_uuid_objects_with_different_values_are_not_equal(): void { static::assertFalse((new Equal('id', 'id'))->compare( - row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']), - row(['id' => '00000000-0000-4000-8000-000000000000']), + array_to_row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479'], schema(str_schema('id'))), + array_to_row(['id' => '00000000-0000-4000-8000-000000000000'], schema(str_schema('id'))), )); } public function test_uuid_objects_with_same_value_are_equal(): void { static::assertTrue((new Equal('id', 'id'))->compare( - row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']), - row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']), + array_to_row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479'], schema(str_schema('id'))), + array_to_row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479'], schema(str_schema('id'))), )); } public function test_success(): void { static::assertTrue((new Equal('datetime', 'datetime'))->compare( - row(['datetime' => $datetime = new DateTimeImmutable('2022-10-01 00:00:00')]), - row(['datetime' => $datetime]), + array_to_row([ + 'datetime' => $datetime = new DateTimeImmutable('2022-10-01 00:00:00'), + ], schema(datetime_schema('datetime'))), + array_to_row(['datetime' => $datetime], schema(datetime_schema('datetime'))), )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/IdenticalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/IdenticalTest.php index dc06266645..527cf9ec02 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/IdenticalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/IdenticalTest.php @@ -7,28 +7,46 @@ use Flow\ETL\Join\Comparison\Identical; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class IdenticalTest extends FlowTestCase { public function test_failure(): void { - static::assertFalse((new Identical('id', 'id'))->compare(row(['id' => 1]), row(['id' => 2]))); + static::assertFalse((new Identical('id', 'id'))->compare( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 2], schema(int_schema('id'))), + )); } public function test_null_is_not_identical_to_null(): void { - static::assertFalse((new Identical('id', 'id'))->compare(row(['id' => null]), row(['id' => null]))); + static::assertFalse((new Identical('id', 'id'))->compare( + array_to_row(['id' => null], schema(str_schema('id', nullable: true))), + array_to_row(['id' => null], schema(str_schema('id', nullable: true))), + )); } public function test_null_is_not_identical_to_value(): void { - static::assertFalse((new Identical('id', 'id'))->compare(row(['id' => null]), row(['id' => 1]))); - static::assertFalse((new Identical('id', 'id'))->compare(row(['id' => 1]), row(['id' => null]))); + static::assertFalse((new Identical('id', 'id'))->compare( + array_to_row(['id' => null], schema(int_schema('id', nullable: true))), + array_to_row(['id' => 1], schema(int_schema('id'))), + )); + static::assertFalse((new Identical('id', 'id'))->compare( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => null], schema(int_schema('id', nullable: true))), + )); } public function test_success(): void { - static::assertTrue((new Identical('id', 'id'))->compare(row(['id' => 1]), row(['id' => 1]))); + static::assertTrue((new Identical('id', 'id'))->compare( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 1], schema(int_schema('id'))), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/ExpressionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/ExpressionTest.php index cb675c6b74..6a9e0111e7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/ExpressionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/ExpressionTest.php @@ -8,8 +8,10 @@ use Flow\ETL\Join\Expression; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\col; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; final class ExpressionTest extends FlowTestCase { @@ -26,6 +28,9 @@ public function test_expression_comparison(): void { $expression = Expression::on(new Equal('id', 'id'), '_'); - static::assertTrue($expression->meet(row(['id' => 1]), row(['id' => 1]))); + static::assertTrue($expression->meet( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 1], schema(int_schema('id'))), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/HashTableTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/HashTableTest.php index 64c6b168b3..c6ef239f9e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/HashTableTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/HashTableTest.php @@ -7,7 +7,10 @@ use Flow\ETL\Join\HashJoin\HashTable; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function iterator_to_array; final class HashTableTest extends FlowTestCase @@ -15,8 +18,14 @@ final class HashTableTest extends FlowTestCase public function test_candidates_for_matching_hash(): void { $hashTable = new HashTable(); - $hashTable->add('hash-a', row(['user_id' => 1, 'name' => 'Alice'])); - $hashTable->add('hash-b', row(['user_id' => 2, 'name' => 'Bob'])); + $hashTable->add('hash-a', array_to_row( + ['user_id' => 1, 'name' => 'Alice'], + schema(int_schema('user_id'), str_schema('name')), + )); + $hashTable->add('hash-b', array_to_row( + ['user_id' => 2, 'name' => 'Bob'], + schema(int_schema('user_id'), str_schema('name')), + )); $candidates = $hashTable->candidatesFor('hash-a'); @@ -27,8 +36,8 @@ public function test_candidates_for_matching_hash(): void public function test_constant_hash_makes_every_row_a_candidate(): void { $hashTable = new HashTable(); - $hashTable->add('0', row(['user_id' => 1])); - $hashTable->add('0', row(['user_id' => 2])); + $hashTable->add('0', array_to_row(['user_id' => 1], schema(int_schema('user_id')))); + $hashTable->add('0', array_to_row(['user_id' => 2], schema(int_schema('user_id')))); static::assertCount(2, $hashTable->candidatesFor('0')); } @@ -36,8 +45,14 @@ public function test_constant_hash_makes_every_row_a_candidate(): void public function test_duplicated_rows_are_preserved(): void { $hashTable = new HashTable(); - $hashTable->add('hash-a', row(['user_id' => 1, 'name' => 'Alice'])); - $hashTable->add('hash-a', row(['user_id' => 1, 'name' => 'Alice'])); + $hashTable->add('hash-a', array_to_row( + ['user_id' => 1, 'name' => 'Alice'], + schema(int_schema('user_id'), str_schema('name')), + )); + $hashTable->add('hash-a', array_to_row( + ['user_id' => 1, 'name' => 'Alice'], + schema(int_schema('user_id'), str_schema('name')), + )); static::assertSame(2, $hashTable->count()); static::assertCount(2, $hashTable->candidatesFor('hash-a')); @@ -46,7 +61,7 @@ public function test_duplicated_rows_are_preserved(): void public function test_no_candidates_for_unknown_hash(): void { $hashTable = new HashTable(); - $hashTable->add('hash-a', row(['user_id' => 1])); + $hashTable->add('hash-a', array_to_row(['user_id' => 1], schema(int_schema('user_id')))); static::assertSame([], $hashTable->candidatesFor('hash-404')); } @@ -54,9 +69,18 @@ public function test_no_candidates_for_unknown_hash(): void public function test_unmatched_rows_tracking(): void { $hashTable = new HashTable(trackUnmatched: true); - $hashTable->add('hash-a', row(['user_id' => 1, 'name' => 'Alice'])); - $hashTable->add('hash-b', row(['user_id' => 2, 'name' => 'Bob'])); - $hashTable->add('hash-c', row(['user_id' => 3, 'name' => 'Cid'])); + $hashTable->add('hash-a', array_to_row( + ['user_id' => 1, 'name' => 'Alice'], + schema(int_schema('user_id'), str_schema('name')), + )); + $hashTable->add('hash-b', array_to_row( + ['user_id' => 2, 'name' => 'Bob'], + schema(int_schema('user_id'), str_schema('name')), + )); + $hashTable->add('hash-c', array_to_row( + ['user_id' => 3, 'name' => 'Cid'], + schema(int_schema('user_id'), str_schema('name')), + )); $hashTable->matched(1); @@ -70,7 +94,7 @@ public function test_unmatched_rows_tracking(): void public function test_unmatched_rows_without_tracking_are_empty(): void { $hashTable = new HashTable(); - $hashTable->add('hash-a', row(['user_id' => 1])); + $hashTable->add('hash-a', array_to_row(['user_id' => 1], schema(int_schema('user_id')))); static::assertSame([], iterator_to_array($hashTable->unmatchedRows(), false)); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php index 575ac1af13..d31f8ee0d1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php @@ -17,10 +17,9 @@ use Flow\ETL\Tests\FlowTestCase; use Generator; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\join_on; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -40,15 +39,16 @@ public function test_any_comparison_falls_back_to_verifying_every_pair(): void ); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'email' => 'alice@flow.php'], ['id' => 2, 'email' => 'bob@flow.php']], schema(int_schema('id'), str_schema('email')), - row(['id' => 1, 'email' => 'alice@flow.php']), - row(['id' => 2, 'email' => 'bob@flow.php']), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [ + ['user_id' => 5, 'contact' => 'alice@flow.php', 'name' => 'Alice'], + ['user_id' => 2, 'contact' => 'other@flow.php', 'name' => 'Bob'], + ], schema(int_schema('user_id'), str_schema('contact'), str_schema('name')), - row(['user_id' => 5, 'contact' => 'alice@flow.php', 'name' => 'Alice']), - row(['user_id' => 2, 'contact' => 'other@flow.php', 'name' => 'Bob']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -90,15 +90,19 @@ public function test_all_with_any_hashes_by_the_equality_and_verifies_the_rest() ); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [ + ['id' => 1, 'email' => 'alice@flow.php', 'phone' => '111'], + ['id' => 2, 'email' => 'bob@flow.php', 'phone' => '222'], + ], schema(int_schema('id'), str_schema('email'), str_schema('phone')), - row(['id' => 1, 'email' => 'alice@flow.php', 'phone' => '111']), - row(['id' => 2, 'email' => 'bob@flow.php', 'phone' => '222']), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [ + ['user_id' => 1, 'contact' => 'alice@flow.php', 'phone' => '999'], + ['user_id' => 2, 'contact' => 'other@flow.php', 'phone' => '999'], + ], schema(int_schema('user_id'), str_schema('contact'), str_schema('phone')), - row(['user_id' => 1, 'contact' => 'alice@flow.php', 'phone' => '999']), - row(['user_id' => 2, 'contact' => 'other@flow.php', 'phone' => '999']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -132,11 +136,10 @@ public function test_duplicated_right_rows_are_all_joined(): void $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); foreach ($joiner->join( - JoinSide::of($batches(rows(schema(int_schema('id')), row(['id' => 1])))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows([['id' => 1]], schema(int_schema('id'))))), + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 1, 'name' => 'Alice']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -158,15 +161,17 @@ public function test_inner_join_emits_every_matching_right_row(): void $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [ + ['user_id' => 1, 'role' => 'admin'], + ['user_id' => 1, 'role' => 'writer'], + ['user_id' => 2, 'role' => 'reader'], + ], schema(int_schema('user_id'), str_schema('role')), - row(['user_id' => 1, 'role' => 'admin']), - row(['user_id' => 1, 'role' => 'writer']), - row(['user_id' => 2, 'role' => 'reader']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -194,13 +199,13 @@ public function test_inner_join_drops_duplicated_right_join_columns(): void $joiner = new Joiner(join_on(['id' => 'id']), Join::inner); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'name' => 'Alice']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'Alice']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -223,12 +228,12 @@ public function test_left_anti_join_keeps_left_row_on_hash_hit_without_match(): $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left_anti); $right = static function (): Generator { - yield rows(schema(str_schema('user_id')), row(['user_id' => '2'])); - yield rows(schema(str_schema('user_id')), row(['user_id' => '9'])); + yield array_to_rows([['user_id' => '2']], schema(str_schema('user_id'))); + yield array_to_rows([['user_id' => '9']], schema(str_schema('user_id'))); }; foreach ($joiner->join( - JoinSide::of($batches(rows(schema(str_schema('id')), row(['id' => '1']), row(['id' => '2'])))), + JoinSide::of($batches(array_to_rows([['id' => '1'], ['id' => '2']], schema(str_schema('id'))))), JoinSide::of($right()), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -252,13 +257,13 @@ public function test_left_join_keeps_left_row_on_hash_hit_without_match(): void $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => '1', 'name' => 'Alice']], schema(str_schema('user_id'), str_schema('name')), - row(['user_id' => '1', 'name' => 'Alice']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -280,14 +285,13 @@ public function test_left_join_pads_unmatched_left_rows_with_nulls(): void $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100], ['id' => 404, 'amount' => 200]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), - row(['id' => 404, 'amount' => 200]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -316,13 +320,13 @@ public function test_prefix_collision_with_left_column_throws(): void $joiner = new Joiner(join_on(['id' => 'user_id'], join_prefix: 'left_'), Join::inner); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'left_name' => 'collision']], schema(int_schema('id'), str_schema('left_name')), - row(['id' => 1, 'left_name' => 'collision']), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), ) as $batch) { $batch->count(); @@ -340,15 +344,17 @@ public function test_swapped_inner_join_emits_the_same_rows(): void $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [ + ['user_id' => 1, 'role' => 'admin'], + ['user_id' => 1, 'role' => 'writer'], + ['user_id' => 2, 'role' => 'reader'], + ], schema(int_schema('user_id'), str_schema('role')), - row(['user_id' => 1, 'role' => 'admin']), - row(['user_id' => 1, 'role' => 'writer']), - row(['user_id' => 2, 'role' => 'reader']), ))), buildLeft: true, ) as $batch) { @@ -377,8 +383,8 @@ public function test_swapped_left_anti_join_emits_unmatched_left_rows_at_the_end $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left_anti); foreach ($joiner->join( - JoinSide::of($batches(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])))), - JoinSide::of($batches(rows(schema(int_schema('user_id')), row(['user_id' => 1])))), + JoinSide::of($batches(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))))), + JoinSide::of($batches(array_to_rows([['user_id' => 1]], schema(int_schema('user_id'))))), buildLeft: true, ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -400,14 +406,13 @@ public function test_swapped_left_join_pads_unmatched_left_rows_at_the_end(): vo $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100], ['id' => 404, 'amount' => 200]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), - row(['id' => 404, 'amount' => 200]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), buildLeft: true, ) as $batch) { @@ -440,9 +445,9 @@ public function test_swapped_left_join_with_empty_right_side_pads_every_left_row $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), ))), JoinSide::of($empty()), buildLeft: true, @@ -466,14 +471,13 @@ public function test_swapped_right_join_pads_unmatched_right_rows_inline(): void $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 2, 'name' => 'Bob']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 2, 'name' => 'Bob']), ))), buildLeft: true, ) as $batch) { @@ -502,14 +506,13 @@ public function test_right_join_emits_unmatched_right_rows_with_null_left_entrie $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 2, 'name' => 'Bob']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 2, 'name' => 'Bob']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -536,14 +539,13 @@ public function test_left_join_emits_a_schema_declaring_the_right_side_nullable( $emitted = iterator_to_array( $joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100], ['id' => 404, 'amount' => 200]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), - row(['id' => 404, 'amount' => 200]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), ), preserve_keys: false, @@ -570,14 +572,13 @@ public function test_right_join_emits_a_schema_declaring_the_left_side_nullable( $emitted = iterator_to_array( $joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 404, 'name' => 'Bob']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 404, 'name' => 'Bob']), ))), ), preserve_keys: false, @@ -602,15 +603,21 @@ public function test_every_batch_of_a_multi_batch_left_side_shares_one_output_sc $joiner->join( JoinSide::of( (static function (): Generator { - yield rows(schema(int_schema('id'), int_schema('amount')), row(['id' => 1, 'amount' => 100])); - yield rows(schema(int_schema('id'), int_schema('amount')), row(['id' => 404, 'amount' => 200])); + yield array_to_rows( + [['id' => 1, 'amount' => 100]], + schema(int_schema('id'), int_schema('amount')), + ); + yield array_to_rows( + [['id' => 404, 'amount' => 200]], + schema(int_schema('id'), int_schema('amount')), + ); })(), ), JoinSide::of( (static function (): Generator { - yield rows( + yield array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ); })(), ), @@ -633,10 +640,10 @@ public function test_a_padded_row_covers_a_right_column_no_source_row_carried(): $joined = []; foreach ($joiner->join( - JoinSide::of($batches(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 404])))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows([['id' => 1], ['id' => 404]], schema(int_schema('id'))))), + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name'), str_schema('nickname', nullable: true)), - row(['user_id' => 1, 'name' => 'Alice']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -668,14 +675,13 @@ public function test_a_row_omitting_a_nullable_join_key_is_unmatched_rather_than $joined = []; foreach ($joiner->join( - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['id' => 1, 'l' => 'has-key'], ['l' => 'no-key']], schema(int_schema('id', nullable: true), str_schema('l')), - row(['id' => 1, 'l' => 'has-key']), - row(['l' => 'no-key']), ))), - JoinSide::of($batches(rows( + JoinSide::of($batches(array_to_rows( + [['user_id' => 1, 'r' => 'Alice']], schema(int_schema('user_id'), str_schema('r')), - row(['user_id' => 1, 'r' => 'Alice']), ))), ) as $batch) { foreach ($batch->toArray() as $rowData) { @@ -704,11 +710,14 @@ public function test_a_left_batch_wider_than_the_output_schema_is_projected_not_ foreach ($joiner->join( JoinSide::of( - $batches(rows(schema(int_schema('id'), str_schema('extra')), row(['id' => 404, 'extra' => 'drop-me']))), + $batches(array_to_rows( + [['id' => 404, 'extra' => 'drop-me']], + schema(int_schema('id'), str_schema('extra')), + )), null, schema(int_schema('id')), ), - JoinSide::of($batches(rows(schema(int_schema('user_id')), row(['user_id' => 1])))), + JoinSide::of($batches(array_to_rows([['user_id' => 1]], schema(int_schema('user_id'))))), ) as $batch) { foreach ($batch->toArray() as $rowData) { $joined[] = $rowData; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php index 17757d3dac..3baba11e2a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php @@ -8,7 +8,10 @@ use Flow\ETL\Join\HashJoin\RowMerger; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class RowMergerTest extends FlowTestCase { @@ -17,7 +20,10 @@ public function test_collision_between_left_and_right_names_throws(): void $this->expectException(DuplicatedEntriesException::class); $this->expectExceptionMessage('Merged entries names must be unique'); - (new RowMerger())->merge(row(['id' => 1, 'name' => 'left']), row(['name' => 'right'])); + (new RowMerger())->merge( + array_to_row(['id' => 1, 'name' => 'left'], schema(int_schema('id'), str_schema('name'))), + array_to_row(['name' => 'right'], schema(str_schema('name'))), + ); } public function test_drop_left_skips_duplicated_join_columns(): void @@ -26,7 +32,10 @@ public function test_drop_left_skips_duplicated_join_columns(): void static::assertSame( ['amount' => 100, 'id' => 1, 'name' => 'Alice'], - $merger->merge(row(['id' => 1, 'amount' => 100]), row(['id' => 1, 'name' => 'Alice'])), + $merger->merge( + array_to_row(['id' => 1, 'amount' => 100], schema(int_schema('id'), int_schema('amount'))), + array_to_row(['id' => 1, 'name' => 'Alice'], schema(int_schema('id'), str_schema('name'))), + ), ); } @@ -36,7 +45,10 @@ public function test_drop_right_skips_duplicated_join_columns(): void static::assertSame( ['id' => 1, 'amount' => 100, 'name' => 'Alice'], - $merger->merge(row(['id' => 1, 'amount' => 100]), row(['id' => 1, 'name' => 'Alice'])), + $merger->merge( + array_to_row(['id' => 1, 'amount' => 100], schema(int_schema('id'), int_schema('amount'))), + array_to_row(['id' => 1, 'name' => 'Alice'], schema(int_schema('id'), str_schema('name'))), + ), ); } @@ -44,7 +56,10 @@ public function test_merge_without_prefix_keeps_right_names(): void { static::assertSame( ['id' => 1, 'name' => 'Alice'], - (new RowMerger())->merge(row(['id' => 1]), row(['name' => 'Alice'])), + (new RowMerger())->merge( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['name' => 'Alice'], schema(str_schema('name'))), + ), ); } @@ -52,20 +67,29 @@ public function test_prefix_collision_with_left_name_throws(): void { $this->expectException(DuplicatedEntriesException::class); - (new RowMerger('left_'))->merge(row(['left_name' => 'left']), row(['name' => 'right'])); + (new RowMerger('left_'))->merge( + array_to_row(['left_name' => 'left'], schema(str_schema('left_name'))), + array_to_row(['name' => 'right'], schema(str_schema('name'))), + ); } public function test_prefix_renames_every_right_entry(): void { static::assertSame( ['id' => 1, 'right_id' => 1, 'right_name' => 'Alice'], - (new RowMerger('right_'))->merge(row(['id' => 1]), row(['id' => 1, 'name' => 'Alice'])), + (new RowMerger('right_'))->merge( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['id' => 1, 'name' => 'Alice'], schema(int_schema('id'), str_schema('name'))), + ), ); } public function test_renamed_entries_carry_renamed_names(): void { - $merged = (new RowMerger('r_'))->merge(row(['id' => 1]), row(['name' => 'Alice'])); + $merged = (new RowMerger('r_'))->merge( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['name' => 'Alice'], schema(str_schema('name'))), + ); static::assertSame(['id' => 1, 'r_name' => 'Alice'], $merged); } @@ -74,19 +98,46 @@ public function test_reused_plan_renames_rows_with_identical_name_sets(): void { $merger = new RowMerger('r_'); - static::assertSame(['id' => 1, 'r_x' => 'a'], $merger->merge(row(['id' => 1]), row(['x' => 'a']))); - static::assertSame(['id' => 2, 'r_x' => 5], $merger->merge(row(['id' => 2]), row(['x' => 5]))); + static::assertSame( + ['id' => 1, 'r_x' => 'a'], + $merger->merge( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['x' => 'a'], schema(str_schema('x'))), + ), + ); + static::assertSame( + ['id' => 2, 'r_x' => 5], + $merger->merge( + array_to_row(['id' => 2], schema(int_schema('id'))), + array_to_row(['x' => 5], schema(int_schema('x'))), + ), + ); } public function test_reused_merger_handles_rows_with_different_entry_sets(): void { $merger = new RowMerger(); - static::assertSame(['id' => 1, 'name' => 'Alice'], $merger->merge(row(['id' => 1]), row(['name' => 'Alice']))); + static::assertSame( + ['id' => 1, 'name' => 'Alice'], + $merger->merge( + array_to_row(['id' => 1], schema(int_schema('id'))), + array_to_row(['name' => 'Alice'], schema(str_schema('name'))), + ), + ); static::assertSame( ['id' => 2, 'name' => 'Bob', 'age' => 30], - $merger->merge(row(['id' => 2]), row(['name' => 'Bob', 'age' => 30])), + $merger->merge( + array_to_row(['id' => 2], schema(int_schema('id'))), + array_to_row(['name' => 'Bob', 'age' => 30], schema(str_schema('name'), int_schema('age'))), + ), + ); + static::assertSame( + ['id' => 3, 'name' => 'Cid'], + $merger->merge( + array_to_row(['id' => 3], schema(int_schema('id'))), + array_to_row(['name' => 'Cid'], schema(str_schema('name'))), + ), ); - static::assertSame(['id' => 3, 'name' => 'Cid'], $merger->merge(row(['id' => 3]), row(['name' => 'Cid']))); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php index 341f0962ed..4af6037423 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php @@ -8,9 +8,9 @@ use Flow\ETL\Join\JoinShape; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\join_on; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -106,8 +106,8 @@ public function test_the_merger_drops_the_same_column_the_schema_does(): void static::assertSame( ['id' => 1, 'country' => 'PL', 'name' => 'Norbert'], JoinShape::of(join_on(['id' => 'id']), Join::inner)->merger()->merge( - row(['id' => 1, 'country' => 'PL']), - row(['id' => 1, 'name' => 'Norbert']), + array_to_row(['id' => 1, 'country' => 'PL'], schema(int_schema('id'), str_schema('country'))), + array_to_row(['id' => 1, 'name' => 'Norbert'], schema(int_schema('id'), str_schema('name'))), ), ); } @@ -117,8 +117,8 @@ public function test_the_merger_of_a_right_join_keeps_the_right_side_value(): vo static::assertSame( ['country' => 'PL', 'id' => 2, 'name' => 'Norbert'], JoinShape::of(join_on(['id' => 'id']), Join::right)->merger()->merge( - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'name' => 'Norbert']), + array_to_row(['id' => 1, 'country' => 'PL'], schema(int_schema('id'), str_schema('country'))), + array_to_row(['id' => 2, 'name' => 'Norbert'], schema(int_schema('id'), str_schema('name'))), ), ); } 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 8cf0433d2d..3cf2a3e7e9 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 @@ -11,10 +11,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\PhysicalPlanMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; 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; @@ -35,7 +35,7 @@ public function test_builds_a_hash_join_processor(): void 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])))); + $right = PhysicalPlanMother::reading(from_rows(array_to_rows([['id' => 1]], schema(int_schema('id'))))); $steps = JoinSteps::of($right, Expression::on(['id' => 'id'], 'r_'), Join::inner, config_builder()->build()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/ArrayLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/ArrayLoaderTest.php index 81bda654ac..a04b2823dd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/ArrayLoaderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/ArrayLoaderTest.php @@ -6,10 +6,9 @@ use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_array; @@ -18,16 +17,14 @@ final class ArrayLoaderTest extends FlowTestCase { public function test_loads_rows_data_into_memory(): void { - $rows1 = rows( + $rows1 = array_to_rows( + [['number' => 1, 'name' => 'one'], ['number' => 2, 'name' => 'two']], schema(int_schema('number'), str_schema('name')), - row(['number' => 1, 'name' => 'one']), - row(['number' => 2, 'name' => 'two']), ); - $rows2 = rows( + $rows2 = array_to_rows( + [['number' => 3, 'name' => 'three'], ['number' => 4, 'name' => 'four']], schema(int_schema('number'), str_schema('name')), - row(['number' => 3, 'name' => 'three']), - row(['number' => 4, 'name' => 'four']), ); $array = []; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/MemoryLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/MemoryLoaderTest.php index d4646c0ab6..f2502e8a01 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/MemoryLoaderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/MemoryLoaderTest.php @@ -7,11 +7,10 @@ use Flow\ETL\Memory\ArrayMemory; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_memory; @@ -20,10 +19,9 @@ final class MemoryLoaderTest extends FlowTestCase { public function test_loads_rows_data_into_memory(): void { - $rows = rows( + $rows = array_to_rows( + [['number' => 1, 'name' => 'one'], ['number' => 2, 'name' => 'two']], schema(int_schema('number'), str_schema('name')), - row(['number' => 1, 'name' => 'one']), - row(['number' => 2, 'name' => 'two']), ); $memory = new ArrayMemory(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/PartitionRouterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/PartitionRouterTest.php index 0fc1227884..9662f1da99 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/PartitionRouterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/PartitionRouterTest.php @@ -10,10 +10,9 @@ use Flow\ETL\Tests\FlowTestCase; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -23,11 +22,9 @@ public function test_a_batch_carrying_two_combinations_yields_two_groups(): void { $groups = PartitionRoutingContext::route( Partitioning::by(ref('region')), - rows( + array_to_rows( + [['id' => 1, 'region' => 'eu'], ['id' => 2, 'region' => 'us'], ['id' => 3, 'region' => 'eu']], schema(int_schema('id'), str_schema('region')), - row(['id' => 1, 'region' => 'eu']), - row(['id' => 2, 'region' => 'us']), - row(['id' => 3, 'region' => 'eu']), ), ); @@ -44,7 +41,7 @@ public function test_partition_columns_are_stripped_from_the_body_by_default(): { $groups = PartitionRoutingContext::route( Partitioning::by(ref('region')), - rows(schema(int_schema('id'), str_schema('region')), row(['id' => 1, 'region' => 'eu'])), + array_to_rows([['id' => 1, 'region' => 'eu']], schema(int_schema('id'), str_schema('region'))), ); static::assertSame(['id'], $groups[0][1]->schema()->references()->names()); @@ -55,7 +52,7 @@ public function test_write_columns_keeps_the_partition_column_in_the_body(): voi { $groups = PartitionRoutingContext::route( Partitioning::by(ref('region'))->writeColumns(), - rows(schema(int_schema('id'), str_schema('region')), row(['id' => 1, 'region' => 'eu'])), + array_to_rows([['id' => 1, 'region' => 'eu']], schema(int_schema('id'), str_schema('region'))), ); static::assertSame(['id', 'region'], $groups[0][1]->schema()->references()->names()); @@ -65,7 +62,10 @@ public function test_a_null_partition_value_becomes_the_hive_sentinel_on_the_pat { $groups = PartitionRoutingContext::route( Partitioning::by(ref('region')), - rows(schema(int_schema('id'), str_schema('region', nullable: true)), row(['id' => 1, 'region' => null])), + array_to_rows( + [['id' => 1, 'region' => null]], + schema(int_schema('id'), str_schema('region', nullable: true)), + ), ); static::assertNull($groups[0][0]->get('region')->value); @@ -76,9 +76,9 @@ public function test_partitions_keep_declaration_order_not_name_order(): void { $groups = PartitionRoutingContext::route( Partitioning::by(ref('year'), ref('day'), ref('month')), - rows( + array_to_rows( + [['id' => 1, 'year' => '2024', 'month' => '03', 'day' => '01']], schema(int_schema('id'), str_schema('year'), str_schema('month'), str_schema('day')), - row(['id' => 1, 'year' => '2024', 'month' => '03', 'day' => '01']), ), ); @@ -95,7 +95,7 @@ public function test_partitioning_by_every_column_leaves_nothing_to_write(): voi PartitionRoutingContext::route( Partitioning::by('region'), - rows(schema(str_schema('region')), row(['region' => 'eu'])), + array_to_rows([['region' => 'eu']], schema(str_schema('region'))), ); } @@ -105,7 +105,7 @@ public function test_partitioning_by_every_column_is_allowed_with_write_columns( [['region' => 'eu']], PartitionRoutingContext::route( Partitioning::by('region')->writeColumns(), - rows(schema(str_schema('region')), row(['region' => 'eu'])), + array_to_rows([['region' => 'eu']], schema(str_schema('region'))), )[0][1]->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RowPartitionsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RowPartitionsTest.php index 55c95d55a0..34eaaea451 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RowPartitionsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RowPartitionsTest.php @@ -11,6 +11,7 @@ use Flow\Filesystem\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; @@ -18,7 +19,6 @@ use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; @@ -55,15 +55,17 @@ public function test_a_scalar_column_becomes_its_formatted_value( ): void { static::assertSame( $expected, - (new RowPartitions(refs(ref('v'))))->of(row(['v' => $value]), schema($definition))->get('v')->value, + (new RowPartitions(refs(ref('v'))))->of(array_to_row([ + 'v' => $value, + ], schema($definition)), schema($definition))->get('v')->value, ); } public function test_a_null_value_stays_null(): void { - static::assertNull((new RowPartitions(refs(ref('v'))))->of(row([ + static::assertNull((new RowPartitions(refs(ref('v'))))->of(array_to_row([ 'v' => null, - ]), schema(str_schema('v', nullable: true)))->get('v')->value); + ], schema(str_schema('v', nullable: true))), schema(str_schema('v', nullable: true)))->get('v')->value); } public function test_a_list_column_is_refused(): void @@ -71,10 +73,10 @@ public function test_a_list_column_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('can\'t be used as a partition'); - (new RowPartitions(refs(ref('v'))))->of(row(['v' => [ + (new RowPartitions(refs(ref('v'))))->of(array_to_row(['v' => [ 1, 2, - ]]), schema(list_schema('v', type_list(type_integer())))); + ]], schema(list_schema('v', type_list(type_integer())))), schema(list_schema('v', type_list(type_integer())))); } public function test_a_structure_column_is_refused(): void @@ -84,8 +86,8 @@ public function test_a_structure_column_is_refused(): void $structure = type_structure(['a' => type_string()]); - (new RowPartitions(refs(ref('v'))))->of(row(['v' => $structure->cast([ + (new RowPartitions(refs(ref('v'))))->of(array_to_row(['v' => $structure->cast([ 'a' => 'x', - ])]), schema(structure_schema('v', $structure))); + ])], schema(structure_schema('v', $structure))), schema(structure_schema('v', $structure))); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/SchemaValidationLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/SchemaValidationLoaderTest.php index cc6e3569ce..a3acbfcbf8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/SchemaValidationLoaderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/SchemaValidationLoaderTest.php @@ -9,14 +9,13 @@ use Flow\ETL\Schema\Validator\StrictValidator; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\null_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_schema; @@ -34,7 +33,7 @@ public function test_schema_validation_failed_by_mismatching(): void $loader = new SchemaValidationLoader(schema(integer_schema('id')), new StrictValidator()); - $loader->load(rows(schema(str_schema('id')), row(['id' => '1'])), flow_context(config())); + $loader->load(array_to_rows([['id' => '1']], schema(str_schema('id'))), flow_context(config())); } public function test_schema_validation_failed_by_unexpected(): void @@ -50,7 +49,7 @@ public function test_schema_validation_failed_by_unexpected(): void $loader = new SchemaValidationLoader(schema(integer_schema('id')), new StrictValidator()); - $loader->load(rows(schema(str_schema('name')), row(['name' => '1'])), flow_context(config())); + $loader->load(array_to_rows([['name' => '1']], schema(str_schema('name'))), flow_context(config())); } public function test_schema_validation_failure_message_lists_only_definitions_rejected_by_validator(): void @@ -62,7 +61,7 @@ public function test_schema_validation_failure_message_lists_only_definitions_re try { $loader->load( - rows(schema(int_schema('id'), null_schema('deleted_at')), row(['id' => 1, 'deleted_at' => null])), + array_to_rows([['id' => 1, 'deleted_at' => null]], schema(int_schema('id'), null_schema('deleted_at'))), flow_context(config()), ); static::fail('SchemaValidationException was not thrown'); @@ -76,7 +75,7 @@ public function test_schema_validation_succeed(): void { $loader = new SchemaValidationLoader(schema(integer_schema('id')), new StrictValidator()); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), flow_context(config())); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context(config())); // validate that error wasn't thrown $this->addToAssertionCount(1); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/StreamLoaderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/StreamLoaderTest.php index d8e712b7ac..14fead110e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/StreamLoaderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/StreamLoaderTest.php @@ -11,11 +11,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Stream\Mode; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_output; @@ -35,11 +34,9 @@ public function test_columns_count_to_php_output_stream(): void ob_start(); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'name' => 'id_1'], ['id' => 2, 'name' => 'id_2'], ['id' => 3, 'name' => 'id_3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'id_1']), - row(['id' => 2, 'name' => 'id_2']), - row(['id' => 3, 'name' => 'id_3']), ), flow_context(config()), ); @@ -60,11 +57,9 @@ public function test_loading_data_into_invalid_stream(): void $loader = to_stream('php://qweqweqw', 0); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'name' => 'id_1'], ['id' => 2, 'name' => 'id_2'], ['id' => 3, 'name' => 'id_3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'id_1']), - row(['id' => 2, 'name' => 'id_2']), - row(['id' => 3, 'name' => 'id_3']), ), flow_context(config()), ); @@ -77,11 +72,9 @@ public function test_loading_rows_and_schema_into_output_stream(): void ob_start(); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'name' => 'id_1'], ['id' => 2, 'name' => 'id_2'], ['id' => 3, 'name' => 'id_3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'id_1']), - row(['id' => 2, 'name' => 'id_2']), - row(['id' => 3, 'name' => 'id_3']), ), flow_context(config()), ); @@ -112,11 +105,9 @@ public function test_loading_rows_into_php_output_stream(): void ob_start(); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'name' => 'id_1'], ['id' => 2, 'name' => 'id_2'], ['id' => 3, 'name' => 'id_3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'id_1']), - row(['id' => 2, 'name' => 'id_2']), - row(['id' => 3, 'name' => 'id_3']), ), flow_context(config()), ); @@ -142,11 +133,9 @@ public function test_loading_schema_into_php_output_stream(): void ob_start(); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'name' => 'id_1'], ['id' => 2, 'name' => 'id_2'], ['id' => 3, 'name' => 'id_3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'id_1']), - row(['id' => 2, 'name' => 'id_2']), - row(['id' => 3, 'name' => 'id_3']), ), flow_context(config()), ); @@ -168,11 +157,9 @@ public function test_rows_and_columns_count_to_php_output_stream(): void ob_start(); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'name' => 'id_1'], ['id' => 2, 'name' => 'id_2'], ['id' => 3, 'name' => 'id_3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'id_1']), - row(['id' => 2, 'name' => 'id_2']), - row(['id' => 3, 'name' => 'id_3']), ), flow_context(config()), ); @@ -192,11 +179,9 @@ public function test_rows_count_to_php_output_stream(): void ob_start(); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'name' => 'id_1'], ['id' => 2, 'name' => 'id_2'], ['id' => 3, 'name' => 'id_3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'id_1']), - row(['id' => 2, 'name' => 'id_2']), - row(['id' => 3, 'name' => 'id_3']), ), flow_context(config()), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CountFromStatisticsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CountFromStatisticsTest.php index de5434b921..1c8079b83b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CountFromStatisticsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/Rule/CountFromStatisticsTest.php @@ -19,6 +19,7 @@ use function Flow\ETL\Adapter\Parquet\from_parquet; use function Flow\ETL\Adapter\Parquet\to_parquet; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\from_rows; @@ -27,8 +28,6 @@ use function Flow\ETL\DSL\join_on; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\to_memory; use function Flow\Filesystem\DSL\memory_filesystem; @@ -46,7 +45,7 @@ public function test_a_count_over_a_plain_array_read_reads_the_number_instead(): ); static::assertEquals( - from_rows(rows(schema(int_schema('count')), row(['count' => 3]))), + from_rows(array_to_rows([['count' => 3]], schema(int_schema('count')))), $plan->source()->extractor(), ); } @@ -59,7 +58,7 @@ public function test_a_count_over_a_plain_sequence_read_reads_the_number_instead ); static::assertEquals( - from_rows(rows(schema(int_schema('count')), row(['count' => 10]))), + from_rows(array_to_rows([['count' => 10]], schema(int_schema('count')))), $plan->source()->extractor(), ); } @@ -81,7 +80,7 @@ public function test_a_count_over_a_plain_parquet_read_reads_the_number_instead( ); static::assertEquals( - from_rows(rows(schema(int_schema('count')), row(['count' => 25]))), + from_rows(array_to_rows([['count' => 25]], schema(int_schema('count')))), $plan->source()->extractor(), ); } @@ -103,7 +102,7 @@ public function test_a_count_over_a_plain_floe_read_reads_the_number_instead(): ); static::assertEquals( - from_rows(rows(schema(int_schema('count')), row(['count' => 25]))), + from_rows(array_to_rows([['count' => 25]], schema(int_schema('count')))), $plan->source()->extractor(), ); } 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 index 193b22f18d..9cdf73e140 100644 --- 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 @@ -23,6 +23,7 @@ use Flow\Filesystem\Path\Filter\OnlyFiles; use Flow\Types\Exception\InvalidArgumentException; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\int_schema; @@ -30,8 +31,6 @@ 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\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\to_memory; use function Flow\Types\DSL\type_boolean; @@ -300,7 +299,7 @@ public function test_a_source_without_partition_columns_is_never_pushed_into(): { $extractor = new RecordingFileExtractor( schema(int_schema('year')), - rows(schema(int_schema('year')), row(['year' => 2023])), + array_to_rows([['year' => 2023]], schema(int_schema('year'))), ); df() diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php index be3b1624e9..998fdbace3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php @@ -85,6 +85,7 @@ use PHPUnit\Framework\Attributes\TestWith; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_array; @@ -97,8 +98,6 @@ use function Flow\ETL\DSL\rank; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\to_memory; use function Flow\ETL\DSL\window; @@ -438,7 +437,7 @@ public function test_transform_the_instance_the_node_holds_is_the_step(): void 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()); + $transformer->transform(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context()); $steps = NodeTranslator::toSteps(new Transform(NodeMother::read(), $transformer), NodeMother::context(), []); @@ -447,7 +446,7 @@ public function test_transform_a_stateful_transformer_runs_as_its_fresh_instance 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(), + $steps[0]->transform(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context())->toArray(), ); } 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 index a0c2081d13..d3fce7bd52 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkFeedFactoryTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/SinkFeedFactoryTest.php @@ -19,10 +19,9 @@ use Flow\ETL\Tests\Mother\NodeMother; use RuntimeException; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\from_array; 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; final class SinkFeedFactoryTest extends FlowTestCase @@ -43,7 +42,7 @@ public function test_rows_fed_to_the_pipeline_reach_the_tail_loader(): void new SinkOffers($context->errorHandler()), 7, ); - $feed->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), $context); + $feed->load(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), $context); $feed->closure($context); static::assertSame([2], $spy->loadedRowCounts()); @@ -65,7 +64,7 @@ public function test_a_host_without_a_schema_feeds_an_empty_schema(): void new SinkOffers($context->errorHandler()), 0, ); - $feed->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); + $feed->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); $feed->closure($context); static::assertNotNull($planned->refusal()); @@ -90,6 +89,6 @@ public function test_a_throw_only_handler_surfaces_a_failing_step(): void $this->expectException(SinkFailure::class); - $feed->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); + $feed->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $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 index 95c21713d2..191d1d00aa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/PlannerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/PlannerTest.php @@ -54,6 +54,7 @@ use function array_map; use function Flow\ETL\Adapter\CSV\from_csv; use function Flow\ETL\Adapter\CSV\to_csv; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_array; @@ -63,8 +64,6 @@ use function Flow\ETL\DSL\memory_sort; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\to_array; @@ -535,7 +534,10 @@ public function test_a_planned_node_with_a_null_schema_is_distinct_from_a_node_n public function test_planning_reads_no_row(): void { - $extractor = new CountingExtractor(schema(int_schema('id')), rows(schema(int_schema('id')), row(['id' => 1]))); + $extractor = new CountingExtractor( + schema(int_schema('id')), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); $planned = new PlannedNodes(); (new Planner())->node(NodeMother::select(new Read($extractor)), NodeMother::context(), $planned); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingByProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingByProcessorTest.php index 7f353db7ec..393e9d8a99 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingByProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingByProcessorTest.php @@ -12,11 +12,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -47,12 +46,14 @@ public function test_groups_rows_by_column_value(): void { $processor = new BatchingByProcessor(ref('group')); $generator = (static function () { - yield rows( + yield array_to_rows( + [ + ['group' => 'a', 'id' => 1], + ['group' => 'a', 'id' => 2], + ['group' => 'b', 'id' => 3], + ['group' => 'b', 'id' => 4], + ], schema(str_schema('group'), int_schema('id')), - row(['group' => 'a', 'id' => 1]), - row(['group' => 'a', 'id' => 2]), - row(['group' => 'b', 'id' => 3]), - row(['group' => 'b', 'id' => 4]), ); })(); $result = iterator_to_array($processor->process($generator, flow_context())); @@ -79,10 +80,9 @@ public function test_handles_single_group(): void { $processor = new BatchingByProcessor(ref('group')); $generator = (static function () { - yield rows( + yield array_to_rows( + [['group' => 'a', 'id' => 1], ['group' => 'a', 'id' => 2]], schema(str_schema('group'), int_schema('id')), - row(['group' => 'a', 'id' => 1]), - row(['group' => 'a', 'id' => 2]), ); })(); $result = iterator_to_array($processor->process($generator, flow_context())); @@ -94,12 +94,14 @@ public function test_respects_min_size(): void { $processor = new BatchingByProcessor(ref('group'), minSize: 3); $generator = (static function () { - yield rows( + yield array_to_rows( + [ + ['group' => 'a', 'id' => 1], + ['group' => 'a', 'id' => 2], + ['group' => 'b', 'id' => 3], + ['group' => 'b', 'id' => 4], + ], schema(str_schema('group'), int_schema('id')), - row(['group' => 'a', 'id' => 1]), - row(['group' => 'a', 'id' => 2]), - row(['group' => 'b', 'id' => 3]), - row(['group' => 'b', 'id' => 4]), ); })(); $result = iterator_to_array($processor->process($generator, flow_context())); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingProcessorTest.php index 58785a6e58..d4440f604b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingProcessorTest.php @@ -13,10 +13,9 @@ use Flow\ETL\Tests\Mother\RowsMother; use PHPUnit\Framework\Attributes\TestWith; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; use function Flow\ETL\DSL\str_schema; @@ -30,8 +29,8 @@ final class BatchingProcessorTest extends FlowTestCase public function test_a_batch_under_another_schema_is_conformed_to_the_first(int $size): void { $generator = (static function () { - yield rows(schema(int_schema('id'), str_schema('name', true)), row(['id' => 1, 'name' => 'a'])); - yield rows(schema(int_schema('id')), row(['id' => 2])); + yield array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name', true))); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); })(); /** @var list $result */ @@ -74,13 +73,7 @@ public function test_handles_exact_batch_size_multiple(): void { $processor = new BatchingProcessor(2); $generator = (static function () { - yield rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - ); + yield array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); })(); /** @var list $result */ $result = iterator_to_array($processor->process($generator, flow_context())); @@ -93,14 +86,13 @@ public function test_handles_single_large_batch(): void { $processor = new BatchingProcessor(3); $generator = (static function () { - yield rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - ); + yield array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))); })(); /** @var list $result */ $result = iterator_to_array($processor->process($generator, flow_context())); @@ -113,11 +105,11 @@ public function test_rebatches_rows_into_fixed_size(): void { $processor = new BatchingProcessor(2); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1])); - yield rows(schema(int_schema('id')), row(['id' => 2])); - yield rows(schema(int_schema('id')), row(['id' => 3])); - yield rows(schema(int_schema('id')), row(['id' => 4])); - yield rows(schema(int_schema('id')), row(['id' => 5])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); + yield array_to_rows([['id' => 4]], schema(int_schema('id'))); + yield array_to_rows([['id' => 5]], schema(int_schema('id'))); })(); /** @var list $result */ $result = iterator_to_array($processor->process($generator, flow_context())); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BucketingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BucketingProcessorTest.php index defe41df25..35177c4f7f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BucketingProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BucketingProcessorTest.php @@ -18,12 +18,11 @@ use function array_map; use function count; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -66,13 +65,7 @@ public function test_registers_every_yielded_bucket_in_the_repository(): void ); $generator = (static function () { - yield rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - ); + yield array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); })(); /** @var list $result */ @@ -96,7 +89,7 @@ public function test_yields_one_metadata_rows_batch_per_bucket(): void ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); /** @var list $result */ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CachingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CachingProcessorTest.php index 9208c0412d..731db0db31 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CachingProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CachingProcessorTest.php @@ -14,11 +14,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; 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; use function Flow\ETL\DSL\str_schema; @@ -62,8 +61,8 @@ public function test_caches_batches_and_yields_them(): void $processor = new CachingProcessor('test-cache'); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1])); - yield rows(schema(int_schema('id')), row(['id' => 2])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); })(); $result = iterator_to_array($processor->process($generator, $context)); @@ -111,7 +110,7 @@ public function test_passes_through_when_cache_exists(): void $processor = new CachingProcessor('test-cache'); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); })(); $result = iterator_to_array($processor->process($generator, $context)); @@ -127,7 +126,7 @@ public function test_uses_config_id_when_no_id_provided(): void $processor = new CachingProcessor(); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); })(); iterator_to_array($processor->process($generator, $context)); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CollectingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CollectingProcessorTest.php index c36ad1324b..0e0f60e4aa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CollectingProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CollectingProcessorTest.php @@ -8,10 +8,9 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; use function Flow\ETL\DSL\str_schema; @@ -46,9 +45,9 @@ public function test_collects_all_rows_into_single_batch(): void $processor = new CollectingProcessor(); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); - yield rows(schema(int_schema('id')), row(['id' => 3])); - yield rows(schema(int_schema('id')), row(['id' => 4]), row(['id' => 5])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); + yield array_to_rows([['id' => 4], ['id' => 5]], schema(int_schema('id'))); })(); /** @var list $result */ @@ -88,7 +87,7 @@ public function test_handles_single_batch(): void $processor = new CollectingProcessor(); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); /** @var list $result */ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ConstrainedProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ConstrainedProcessorTest.php index e0e7095c3e..0e68eba4f9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ConstrainedProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ConstrainedProcessorTest.php @@ -16,10 +16,9 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; final class ConstrainedProcessorTest extends FlowTestCase @@ -48,7 +47,7 @@ public function test_handles_empty_constraints(): void { $processor = new ConstrainedProcessor([]); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); })(); $result = iterator_to_array($processor->process($generator, flow_context())); static::assertCount(1, $result); @@ -101,7 +100,7 @@ public function violation(Row $row, Schema $schema): string }; $processor = new ConstrainedProcessor([$constraint]); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); /** @var list $result */ $result = iterator_to_array($processor->process($generator, flow_context())); @@ -138,7 +137,7 @@ public function violation(Row $row, Schema $schema): string }; $processor = new ConstrainedProcessor([$constraint]); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => -1])); + yield array_to_rows([['id' => 1], ['id' => -1]], schema(int_schema('id'))); })(); $this->expectException(ConstraintViolationException::class); iterator_to_array($processor->process($generator, flow_context())); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CountingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CountingProcessorTest.php index 0c33f90c24..1f96fb1caa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CountingProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CountingProcessorTest.php @@ -7,9 +7,9 @@ use Flow\ETL\Processor\CountingProcessor; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; use function Flow\ETL\DSL\str_schema; @@ -20,13 +20,13 @@ final class CountingProcessorTest extends FlowTestCase public function test_every_batch_is_counted_into_one_row(): void { $batches = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); yield rows(schema(int_schema('id'))); - yield rows(schema(int_schema('id')), row(['id' => 3])); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); })(); static::assertEquals( - [rows(schema(int_schema('count')), row(['count' => 3]))], + [array_to_rows([['count' => 3]], schema(int_schema('count')))], iterator_to_array((new CountingProcessor())->process($batches, flow_context())), ); } @@ -38,7 +38,7 @@ public function test_no_batch_counts_to_zero(): void })(); static::assertEquals( - [rows(schema(int_schema('count')), row(['count' => 0]))], + [array_to_rows([['count' => 0]], schema(int_schema('count')))], iterator_to_array((new CountingProcessor())->process($batches, flow_context())), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php index 21d9f4249c..59138350f6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php @@ -19,12 +19,12 @@ use Flow\ETL\Tests\FlowTestCase; use Generator; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\count; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -47,11 +47,13 @@ public function test_aggregates_every_bucket_from_the_metadata_stream(): void ); $input = (static function (): Generator { - yield rows( + yield array_to_rows( + [ + ['category' => 'a', 'amount' => 10], + ['category' => 'b', 'amount' => 15], + ['category' => 'a', 'amount' => 20], + ], schema(str_schema('category'), int_schema('amount')), - row(['category' => 'a', 'amount' => 10]), - row(['category' => 'b', 'amount' => 15]), - row(['category' => 'a', 'amount' => 20]), ); })(); @@ -100,11 +102,13 @@ public function test_aggregates_every_bucket_when_metadata_rows_arrive_in_one_ba ); $input = (static function (): Generator { - yield rows( + yield array_to_rows( + [ + ['category' => 'a', 'amount' => 10], + ['category' => 'b', 'amount' => 15], + ['category' => 'a', 'amount' => 20], + ], schema(str_schema('category'), int_schema('amount')), - row(['category' => 'a', 'amount' => 10]), - row(['category' => 'b', 'amount' => 15]), - row(['category' => 'a', 'amount' => 20]), ); })(); @@ -181,10 +185,9 @@ public function test_clears_storage_after_the_last_bucket(): void ); $input = (static function (): Generator { - yield rows( + yield array_to_rows( + [['category' => 'a', 'amount' => 10], ['category' => 'b', 'amount' => 15]], schema(str_schema('category'), int_schema('amount')), - row(['category' => 'a', 'amount' => 10]), - row(['category' => 'b', 'amount' => 15]), ); })(); @@ -313,11 +316,10 @@ public function test_a_bound_global_aggregate_with_input_emits_no_extra_row(): v $groupBy->aggregate(sum(ref('amount')), count(ref('amount'))); $buckets = new Buckets(new MemoryBuckets()); - $metadata = GroupByContext::bucketMetadata( - $buckets, - [], - rows(schema(int_schema('amount')), row(['amount' => 10]), row(['amount' => 20])), - ); + $metadata = GroupByContext::bucketMetadata($buckets, [], array_to_rows([ + ['amount' => 10], + ['amount' => 20], + ], schema(int_schema('amount')))); $bound = (new GroupByAggregationProcessor($groupBy, $buckets))->bind(schema(int_schema('amount'))); 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 216cb51983..9094e7fcb4 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 @@ -18,10 +18,10 @@ use Flow\ETL\Tests\Mother\PhysicalPlanMother; use Flow\ETL\Tests\Mother\RowsMother; +use function Flow\ETL\DSL\array_to_rows; 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; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -34,9 +34,9 @@ final class HashJoinProcessorTest extends FlowTestCase public function test_bind_derives_the_joined_schema_from_both_sides(): void { $processor = HashJoinProcessorMother::resident( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Alice']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'Alice']), ))), Expression::on(['id' => 'id']), Join::inner, @@ -50,14 +50,19 @@ public function test_bind_derives_the_joined_schema_from_both_sides(): void public function test_builds_hash_table_from_the_smaller_side_without_changing_results(): void { - $bigger = rows( + $bigger = array_to_rows( + [ + ['id' => 1, 'amount' => 100], + ['id' => 1, 'amount' => 150], + ['id' => 2, 'amount' => 200], + ['id' => 3, 'amount' => 300], + ], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), - row(['id' => 1, 'amount' => 150]), - row(['id' => 2, 'amount' => 200]), - row(['id' => 3, 'amount' => 300]), ); - $smaller = rows(schema(int_schema('user_id'), str_schema('name')), row(['user_id' => 1, 'name' => 'Alice'])); + $smaller = array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], + schema(int_schema('user_id'), str_schema('name')), + ); $leftBiggerJoined = []; @@ -95,17 +100,13 @@ public function test_builds_hash_table_from_the_smaller_side_without_changing_re public function test_grace_and_resident_storages_produce_the_same_rows(): void { - $leftRows = rows( + $leftRows = array_to_rows( + [['id' => 1, 'amount' => 100], ['id' => 2, 'amount' => 200], ['id' => 404, 'amount' => 300]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), - row(['id' => 2, 'amount' => 200]), - row(['id' => 404, 'amount' => 300]), ); - $rightRows = rows( + $rightRows = array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 2, 'name' => 'Bob'], ['user_id' => 3, 'name' => 'Cid']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 2, 'name' => 'Bob']), - row(['user_id' => 3, 'name' => 'Cid']), ); $results = []; @@ -155,9 +156,9 @@ public function test_grace_and_resident_storages_produce_the_same_rows(): void public function test_handles_empty_left_side(): void { $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), Expression::on(['id' => 'user_id']), Join::inner, @@ -179,7 +180,7 @@ public function test_handles_empty_right_side(): void ); $generator = (static function () { - yield rows(schema(int_schema('id'), int_schema('amount')), row(['id' => 1, 'amount' => 100])); + yield array_to_rows([['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount'))); })(); $result = iterator_to_array($processor->process($generator, flow_context()), false); @@ -197,21 +198,18 @@ public function test_handles_empty_right_side(): void public function test_inner_join(): void { $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 2, 'name' => 'Bob']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 2, 'name' => 'Bob']), ))), Expression::on(['id' => 'user_id']), Join::inner, ); $generator = (static function () { - yield rows( + yield array_to_rows( + [['id' => 1, 'amount' => 100], ['id' => 2, 'amount' => 200], ['id' => 3, 'amount' => 300]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), - row(['id' => 2, 'amount' => 200]), - row(['id' => 3, 'amount' => 300]), ); })(); @@ -239,9 +237,9 @@ public function test_inner_join_drops_null_key_rows_without_touching_storage(): $storage = new SpyBucketsStorage(new MemoryBuckets()); $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), Expression::on(['id' => 'user_id']), Join::inner, @@ -249,7 +247,7 @@ public function test_inner_join_drops_null_key_rows_without_touching_storage(): ); $generator = (static function () { - yield rows(schema(int_schema('id', nullable: true)), row(['id' => null]), row(['id' => null])); + yield array_to_rows([['id' => null], ['id' => null]], schema(int_schema('id', nullable: true))); })(); static::assertCount(0, iterator_to_array($processor->process($generator, flow_context()), false)); @@ -259,17 +257,16 @@ 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( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'role' => 'admin'], ['user_id' => 1, 'role' => 'writer']], schema(int_schema('user_id'), str_schema('role')), - row(['user_id' => 1, 'role' => 'admin']), - row(['user_id' => 1, 'role' => 'writer']), ))), Expression::on(['id' => 'user_id']), Join::inner, ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); })(); $joined = []; @@ -294,13 +291,13 @@ public function test_inner_join_emits_every_matching_right_row(): void public function test_left_anti_join(): void { $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows(schema(int_schema('user_id')), row(['user_id' => 1])))), + PhysicalPlanMother::reading(from_rows(array_to_rows([['user_id' => 1]], schema(int_schema('user_id'))))), Expression::on(['id' => 'user_id']), Join::left_anti, ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); $joined = []; @@ -319,13 +316,13 @@ public function test_left_anti_join(): void public function test_left_anti_join_keeps_null_key_left_rows(): void { $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows(schema(int_schema('user_id')), row(['user_id' => 1])))), + PhysicalPlanMother::reading(from_rows(array_to_rows([['user_id' => 1]], schema(int_schema('user_id'))))), Expression::on(['id' => 'user_id']), Join::left_anti, ); $generator = (static function () { - yield rows(schema(int_schema('id', nullable: true)), row(['id' => 1]), row(['id' => null])); + yield array_to_rows([['id' => 1], ['id' => null]], schema(int_schema('id', nullable: true))); })(); $joined = []; @@ -344,19 +341,18 @@ public function test_left_anti_join_keeps_null_key_left_rows(): void public function test_left_join(): void { $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), Expression::on(['id' => 'user_id']), Join::left, ); $generator = (static function () { - yield rows( + yield array_to_rows( + [['id' => 1, 'amount' => 100], ['id' => 2, 'amount' => 200]], schema(int_schema('id'), int_schema('amount')), - row(['id' => 1, 'amount' => 100]), - row(['id' => 2, 'amount' => 200]), ); })(); @@ -380,16 +376,16 @@ public function test_left_join(): void public function test_left_join_pads_null_key_left_rows(): void { $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), Expression::on(['id' => 'user_id']), Join::left, ); $generator = (static function () { - yield rows(schema(int_schema('id', nullable: true)), row(['id' => 1]), row(['id' => null])); + yield array_to_rows([['id' => 1], ['id' => null]], schema(int_schema('id', nullable: true))); })(); $joined = []; @@ -416,17 +412,16 @@ 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( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 2, 'name' => 'Bob']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 2, 'name' => 'Bob']), ))), Expression::on(new Any(new Equal('id', 'user_id'))), Join::inner, ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 3])); + yield array_to_rows([['id' => 1], ['id' => 3]], schema(int_schema('id'))); })(); $joined = []; @@ -445,19 +440,21 @@ 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( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [ + ['user_id' => 1, 'name' => 'Alice'], + ['user_id' => 2, 'name' => 'Bob'], + ['user_id' => 3, 'name' => 'Cid'], + ], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 2, 'name' => 'Bob']), - row(['user_id' => 3, 'name' => 'Cid']), ))), Expression::on(['id' => 'user_id']), Join::inner, ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 1])); - yield rows(schema(int_schema('id')), row(['id' => 2])); + yield array_to_rows([['id' => 3], ['id' => 1]], schema(int_schema('id'))); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); })(); $joined = []; @@ -483,17 +480,16 @@ public function test_resident_storage_preserves_left_row_order(): void public function test_right_join(): void { $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 2, 'name' => 'Bob']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => 2, 'name' => 'Bob']), ))), Expression::on(['id' => 'user_id']), Join::right, ); $generator = (static function () { - yield rows(schema(int_schema('id'), int_schema('amount')), row(['id' => 1, 'amount' => 100])); + yield array_to_rows([['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount'))); })(); $joined = []; @@ -520,17 +516,16 @@ public function test_right_join(): void public function test_right_join_pads_null_key_right_rows(): void { $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => null, 'name' => 'Bob']], schema(int_schema('user_id', nullable: true), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), - row(['user_id' => null, 'name' => 'Bob']), ))), Expression::on(['id' => 'user_id']), Join::right, ); $generator = (static function () { - yield rows(schema(int_schema('id', nullable: true)), row(['id' => 1]), row(['id' => null])); + yield array_to_rows([['id' => 1], ['id' => null]], schema(int_schema('id', nullable: true))); })(); $joined = []; @@ -559,9 +554,9 @@ public function test_storages_are_cleared_after_the_join(): void $storage = new SpyBucketsStorage(new MemoryBuckets()); $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), Expression::on(['id' => 'user_id']), Join::left, @@ -569,7 +564,7 @@ public function test_storages_are_cleared_after_the_join(): void ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); iterator_to_array($processor->process($generator, flow_context()), false); @@ -589,7 +584,7 @@ public function test_pairs_with_a_missing_right_side_read_only_left_buckets(): v ); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); iterator_to_array($processor->process($generator, flow_context()), false); @@ -625,16 +620,16 @@ 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( - PhysicalPlanMother::reading(from_rows(rows( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name')), - row(['user_id' => 1, 'name' => 'Alice']), ))), Expression::on(['id' => 'user_id']), Join::inner, ); $generator = (static function () { - yield rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'Norbert'])); + yield array_to_rows([['id' => 1, 'name' => 'Norbert']], schema(int_schema('id'), str_schema('name'))); })(); $this->expectException(JoinException::class); @@ -647,14 +642,14 @@ public function test_duplicated_entries_outside_join_columns_throw_join_exceptio public function test_the_right_side_is_pulled_through_a_frame_output(): void { - $right = PhysicalPlanMother::reading(from_rows(rows( + $right = PhysicalPlanMother::reading(from_rows(array_to_rows( + [['id' => 1, 'name' => 'Alice']], 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])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); $batches = iterator_to_array($processor->process($generator, flow_context()), false); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MemorySortProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MemorySortProcessorTest.php index dee0c9e0ac..97271be500 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MemorySortProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MemorySortProcessorTest.php @@ -8,12 +8,11 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; final class MemorySortProcessorTest extends FlowTestCase @@ -37,7 +36,7 @@ public function test_the_declared_schema_wins_over_the_batch_schema(): void $declared = schema(int_schema('id', nullable: true)); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 2]), row(['id' => 1])); + yield array_to_rows([['id' => 2], ['id' => 1]], schema(int_schema('id'))); })(); /** @var list $result */ @@ -66,9 +65,9 @@ public function test_sorts_across_multiple_batches(): void $processor = new MemorySortProcessor(refs(ref('id'))); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 3])); - yield rows(schema(int_schema('id')), row(['id' => 1])); - yield rows(schema(int_schema('id')), row(['id' => 2])); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); })(); /** @var list $result */ @@ -89,7 +88,7 @@ public function test_sorts_rows_ascending(): void $processor = new MemorySortProcessor(refs(ref('id'))); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); /** @var list $result */ @@ -110,7 +109,7 @@ public function test_sorts_rows_descending(): void $processor = new MemorySortProcessor(refs(ref('id')->desc())); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 3]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 3], ['id' => 2]], schema(int_schema('id'))); })(); /** @var list $result */ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php index 7c4b935896..98d4e1a7a2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php @@ -13,7 +13,6 @@ use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\MergeSortProcessor; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Tests\Double\SpyBucketsStorage; use Flow\ETL\Tests\Double\ThrowingRemoveBucketsStorage; @@ -22,13 +21,12 @@ use function array_map; use function array_merge; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function iterator_to_array; use function range; @@ -69,13 +67,7 @@ public function test_descending_single_column(): void ); $input = (static function () { - yield rows( - schema(int_schema('id')), - row(['id' => 3]), - row(['id' => 1]), - row(['id' => 4]), - row(['id' => 2]), - ); + yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]], schema(int_schema('id'))); })(); $result = iterator_to_array($merge->process($bucketing->process($input, $context), $context), false); @@ -137,7 +129,7 @@ public function test_heap_merges_overlapping_runs_without_reduction(): void ); $input = (static function () { - yield rows(schema(int_schema('id')), ...array_map(static fn(int $i): Row => row(['id' => $i]), [ + yield array_to_rows(array_map(static fn(int $i): array => ['id' => $i], [ 0, 10, 1, @@ -146,7 +138,7 @@ public function test_heap_merges_overlapping_runs_without_reduction(): void 12, 3, 13, - ])); + ]), schema(int_schema('id'))); })(); $result = iterator_to_array($merge->process($bucketing->process($input, $context), $context), false); @@ -178,12 +170,9 @@ public function test_sorts_by_multiple_columns(): void ); $input = (static function () { - yield rows( + yield array_to_rows( + [['a' => 1, 'b' => 2], ['a' => 1, 'b' => 1], ['a' => 0, 'b' => 5], ['a' => 0, 'b' => 3]], schema(int_schema('a'), int_schema('b')), - row(['a' => 1, 'b' => 2]), - row(['a' => 1, 'b' => 1]), - row(['a' => 0, 'b' => 5]), - row(['a' => 0, 'b' => 3]), ); })(); @@ -221,9 +210,9 @@ public function test_multi_pass_reduction_produces_sorted_output(): void ); $input = (static function () { - yield rows( + yield array_to_rows( + array_map(static fn(int $i): array => ['id' => $i], range(19, 0)), schema(int_schema('id')), - ...array_map(static fn(int $i): Row => row(['id' => $i]), range(19, 0)), ); })(); @@ -246,7 +235,7 @@ public function test_both_storages_are_cleared_when_the_first_clear_throws(): vo // the upstream throws during the drain, so reduce() never writes a merged run - seed one, or the // merge-side assertion is true whether or not the nested finally ran - $mergeStorage->append('pre-existing', rows(schema(int_schema('id')), row(['id' => 1]))); + $mergeStorage->append('pre-existing', array_to_rows([['id' => 1]], schema(int_schema('id')))); $merge->add(new Bucket('pre-existing', 1, 0)); $bucketing = new BucketingProcessor( @@ -256,9 +245,9 @@ public function test_both_storages_are_cleared_when_the_first_clear_throws(): vo $processor = new MergeSortProcessor(refs('id'), $spill, $merge, new NativePHPRandomValueGenerator(), 2, 1000); $upstream = (static function (): Generator { - yield rows( + yield array_to_rows( + array_map(static fn(int $i): array => ['id' => $i], range(9, 0)), schema(int_schema('id')), - ...array_map(static fn(int $i): Row => row(['id' => $i]), range(9, 0)), ); throw new RuntimeException('upstream failed'); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/OffsetProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/OffsetProcessorTest.php index 93660215cc..46c7279427 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/OffsetProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/OffsetProcessorTest.php @@ -11,10 +11,9 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; final class OffsetProcessorTest extends FlowTestCase @@ -43,7 +42,7 @@ public function test_offset_greater_than_total_rows_yields_nothing(): void { $processor = new OffsetProcessor(10); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); $result = iterator_to_array($processor->process($generator, flow_context())); $totalRows = 0; @@ -59,7 +58,7 @@ public function test_offset_within_single_batch(): void { $processor = new OffsetProcessor(1); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + yield array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); })(); $result = iterator_to_array($processor->process($generator, flow_context())); $allRows = []; @@ -83,7 +82,7 @@ public function test_offset_zero_yields_all_rows(): void { $processor = new OffsetProcessor(0); $generator = (static function () { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); })(); $result = iterator_to_array($processor->process($generator, flow_context())); $totalRows = 0; @@ -99,8 +98,8 @@ public function test_skips_first_n_rows(): void { $processor = new OffsetProcessor(2); $generator = (static function () { - 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 array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); })(); $result = iterator_to_array($processor->process($generator, flow_context())); $allRows = []; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/PivotProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/PivotProcessorTest.php index 904603a91a..ee0ae3c829 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/PivotProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/PivotProcessorTest.php @@ -12,6 +12,7 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\collect; use function Flow\ETL\DSL\collect_unique; @@ -25,8 +26,6 @@ use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\pivot_values; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_agg; @@ -144,12 +143,11 @@ public function test_a_bound_processor_pivots_grouped_rows(): void $result = iterator_to_array( $bound->step->process( (static function () use ($input): Generator { - yield rows( - $input, - row(['date' => '2024-01-01', 'user' => 'norbert', 'contributions' => 2]), - row(['date' => '2024-01-01', 'user' => 'stloyd', 'contributions' => 3]), - row(['date' => '2024-01-02', 'user' => 'norbert', 'contributions' => 5]), - ); + yield array_to_rows([ + ['date' => '2024-01-01', 'user' => 'norbert', 'contributions' => 2], + ['date' => '2024-01-01', 'user' => 'stloyd', 'contributions' => 3], + ['date' => '2024-01-02', 'user' => 'norbert', 'contributions' => 5], + ], $input); })(), flow_context(), ), @@ -174,11 +172,13 @@ public function test_pivots_grouped_rows(): void $groupBy->aggregate(sum(ref('contributions'))); $input = (static function (): Generator { - yield rows( + yield array_to_rows( + [ + ['date' => '2024-01-01', 'user' => 'norbert', 'contributions' => 2], + ['date' => '2024-01-01', 'user' => 'stloyd', 'contributions' => 3], + ['date' => '2024-01-02', 'user' => 'norbert', 'contributions' => 5], + ], schema(str_schema('date'), str_schema('user'), int_schema('contributions')), - row(['date' => '2024-01-01', 'user' => 'norbert', 'contributions' => 2]), - row(['date' => '2024-01-01', 'user' => 'stloyd', 'contributions' => 3]), - row(['date' => '2024-01-02', 'user' => 'norbert', 'contributions' => 5]), ); })(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/RepartitionProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/RepartitionProcessorTest.php index 5979beed99..00acb474f9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/RepartitionProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/RepartitionProcessorTest.php @@ -17,11 +17,11 @@ use PHPUnit\Framework\Attributes\TestWith; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -59,8 +59,8 @@ public function test_every_row_sharing_a_key_arrives_in_one_batch(int $bucketsCo ); $input = (static function () use ($schema): Generator { - yield rows($schema, row(['k' => 'a', 'v' => 1]), row(['k' => 'b', 'v' => 2])); - yield rows($schema, row(['k' => 'a', 'v' => 3]), row(['k' => 'b', 'v' => 4])); + yield array_to_rows([['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 2]], $schema); + yield array_to_rows([['k' => 'a', 'v' => 3], ['k' => 'b', 'v' => 4]], $schema); })(); $metadata = []; @@ -107,7 +107,7 @@ public function test_buckets_are_cleared_when_the_stream_is_done(): void foreach ($strategy->bucketize( (static function () use ($schema): Generator { - yield rows($schema, row(['k' => 'a', 'v' => 1])); + yield array_to_rows([['k' => 'a', 'v' => 1]], $schema); })(), $buckets->storage(), ) as $bucket) { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/VoidProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/VoidProcessorTest.php index 79396bfb79..e4da3a8279 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/VoidProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/VoidProcessorTest.php @@ -8,10 +8,9 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; use function Flow\ETL\DSL\str_schema; @@ -46,8 +45,8 @@ public function test_discards_all_rows_and_yields_empty_batch(): void $processor = new VoidProcessor(); $generator = (static function () { - 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 array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); })(); /** @var list $result */ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/WindowProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/WindowProcessorTest.php index a84b7c23e3..18376822cd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/WindowProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/WindowProcessorTest.php @@ -17,6 +17,7 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\count; use function Flow\ETL\DSL\current_row; @@ -28,7 +29,6 @@ use function Flow\ETL\DSL\preceding; use function Flow\ETL\DSL\rank; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\row_number; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; @@ -80,12 +80,14 @@ public function test_constant_frame_accumulates_once_per_partition(): void WindowProcessorContext::values( 'total', $function->over(window()->partitionBy(ref('group'))), - rows( + array_to_rows( + [ + ['group' => 'a', 'value' => 10], + ['group' => 'a', 'value' => 20], + ['group' => 'a', 'value' => 30], + ['group' => 'a', 'value' => 40], + ], schema(str_schema('group'), int_schema('value')), - row(['group' => 'a', 'value' => 10]), - row(['group' => 'a', 'value' => 20]), - row(['group' => 'a', 'value' => 30]), - row(['group' => 'a', 'value' => 40]), ), ), ); @@ -106,13 +108,12 @@ public function test_growing_frame_accumulates_each_row_once(): void WindowProcessorContext::values( 'total', $function->over(window()->orderBy(ref('value'))), - rows( - schema(int_schema('value')), - row(['value' => 10]), - row(['value' => 20]), - row(['value' => 30]), - row(['value' => 40]), - ), + array_to_rows([ + ['value' => 10], + ['value' => 20], + ['value' => 30], + ['value' => 40], + ], schema(int_schema('value'))), ), ); static::assertSame(1, $function->accumulatorCalls); @@ -131,13 +132,12 @@ public function test_peer_group_reuses_the_value_within_a_group(): void WindowProcessorContext::values( 'total', $function->over(window()->orderBy(ref('value'))), - rows( - schema(int_schema('value')), - row(['value' => 10]), - row(['value' => 10]), - row(['value' => 20]), - row(['value' => 30]), - ), + array_to_rows([ + ['value' => 10], + ['value' => 10], + ['value' => 20], + ['value' => 30], + ], schema(int_schema('value'))), ), ); static::assertSame(1, $function->accumulatorCalls); @@ -156,13 +156,12 @@ public function test_sliding_frame_recomputes_per_row(): void WindowProcessorContext::values( 'total', $function->over(window()->orderBy(ref('value'))->rowsBetween(preceding(1), current_row())), - rows( - schema(int_schema('value')), - row(['value' => 10]), - row(['value' => 20]), - row(['value' => 30]), - row(['value' => 40]), - ), + array_to_rows([ + ['value' => 10], + ['value' => 20], + ['value' => 30], + ['value' => 40], + ], schema(int_schema('value'))), ), ); static::assertSame(3, $function->accumulatorCalls); @@ -178,10 +177,9 @@ public function test_definition_entry_keeps_its_type_and_metadata(): void $batches = WindowProcessorContext::batches( int_schema('total')->addMetadata('origin', 'window'), sum(ref('value'))->over(window()->partitionBy(ref('group'))), - rows( + array_to_rows( + [['group' => 'a', 'value' => 40], ['group' => 'a', 'value' => 60]], schema(str_schema('group'), int_schema('value')), - row(['group' => 'a', 'value' => 40]), - row(['group' => 'a', 'value' => 60]), ), ); @@ -201,7 +199,7 @@ public function test_an_unknown_partition_reference_is_refused_at_bind(): void WindowProcessorContext::values( 'row_number', row_number()->over(window()->partitionBy(ref('missing'))->orderBy(ref('value'))), - rows(schema(int_schema('value')), row(['value' => 10]), row(['value' => 20]), row(['value' => 30])), + array_to_rows([['value' => 10], ['value' => 20], ['value' => 30]], schema(int_schema('value'))), ); } @@ -213,7 +211,7 @@ public function test_an_unknown_order_reference_is_refused_at_bind(): void WindowProcessorContext::values( 'row_number', row_number()->over(window()->orderBy(ref('missing'))), - rows(schema(int_schema('value')), row(['value' => 10]), row(['value' => 20]), row(['value' => 30])), + array_to_rows([['value' => 10], ['value' => 20], ['value' => 30]], schema(int_schema('value'))), ); } @@ -224,7 +222,7 @@ public function test_empty_frame_yields_the_accumulator_empty_value(): void WindowProcessorContext::values( 'total', sum(ref('value'))->over(window()->orderBy(ref('value'))->rowsBetween(following(10), following(20))), - rows(schema(int_schema('value')), row(['value' => 10]), row(['value' => 20]), row(['value' => 30])), + array_to_rows([['value' => 10], ['value' => 20], ['value' => 30]], schema(int_schema('value'))), ), ); } @@ -236,12 +234,14 @@ public function test_empty_frame_yields_the_accumulator_empty_value(): void */ public function test_row_number_is_not_memoised_by_a_constant_frame(): void { - $partition = rows( + $partition = array_to_rows( + [ + ['group' => 'a', 'value' => 10], + ['group' => 'a', 'value' => 20], + ['group' => 'a', 'value' => 30], + ['group' => 'a', 'value' => 40], + ], schema(str_schema('group'), int_schema('value')), - row(['group' => 'a', 'value' => 10]), - row(['group' => 'a', 'value' => 20]), - row(['group' => 'a', 'value' => 30]), - row(['group' => 'a', 'value' => 40]), ); $frame = window()->partitionBy(ref('group'))->frame(); @@ -263,12 +263,14 @@ public function test_whole_partition_frame_gives_every_row_the_partition_total() WindowProcessorContext::values( 'total', sum(ref('value'))->over(window()->partitionBy(ref('group'))), - rows( + array_to_rows( + [ + ['group' => 'a', 'value' => 10], + ['group' => 'a', 'value' => 20], + ['group' => 'a', 'value' => 30], + ['group' => 'a', 'value' => 40], + ], schema(str_schema('group'), int_schema('value')), - row(['group' => 'a', 'value' => 10]), - row(['group' => 'a', 'value' => 20]), - row(['group' => 'a', 'value' => 30]), - row(['group' => 'a', 'value' => 40]), ), ), ); @@ -281,11 +283,13 @@ public function test_applies_window_function(): void $processor = new WindowProcessor('rank', $windowFunction); $generator = (static function () { - yield rows( + yield array_to_rows( + [ + ['category' => 'a', 'amount' => 100], + ['category' => 'a', 'amount' => 200], + ['category' => 'b', 'amount' => 150], + ], schema(str_schema('category'), int_schema('amount')), - row(['category' => 'a', 'amount' => 100]), - row(['category' => 'a', 'amount' => 200]), - row(['category' => 'b', 'amount' => 150]), ); })(); @@ -326,12 +330,11 @@ public function test_handles_single_partition(): void $processor = new WindowProcessor('rank', $windowFunction); $generator = (static function () { - yield rows( - schema(int_schema('amount')), - row(['amount' => 300]), - row(['amount' => 100]), - row(['amount' => 200]), - ); + yield array_to_rows([ + ['amount' => 300], + ['amount' => 100], + ['amount' => 200], + ], schema(int_schema('amount'))); })(); /** @var list $result */ @@ -391,7 +394,7 @@ public function test_a_running_sum_over_mixed_numerics_yields_one_definition(): $batches = WindowProcessorContext::batches( 'total', sum(ref('value'))->over(window()->orderBy(ref('value'))), - rows(schema(float_schema('value')), row(['value' => 1.0]), row(['value' => 2.5]), row(['value' => 3.0])), + array_to_rows([['value' => 1.0], ['value' => 2.5], ['value' => 3.0]], schema(float_schema('value'))), ); $definitions = []; @@ -416,12 +419,14 @@ public function test_processes_multiple_partitions(): void $processor = new WindowProcessor('rank', $windowFunction); $generator = (static function () { - yield rows( + yield array_to_rows( + [ + ['group' => 'a', 'value' => 10], + ['group' => 'a', 'value' => 20], + ['group' => 'b', 'value' => 5], + ['group' => 'b', 'value' => 15], + ], schema(str_schema('group'), int_schema('value')), - row(['group' => 'a', 'value' => 10]), - row(['group' => 'a', 'value' => 20]), - row(['group' => 'b', 'value' => 5]), - row(['group' => 'b', 'value' => 15]), ); })(); @@ -450,7 +455,7 @@ public function test_a_leading_empty_batch_is_yielded_under_the_bound_schema(): $generator = (static function () { yield rows(schema(int_schema('value'))); - yield rows(schema(int_schema('value')), row(['value' => 10]), row(['value' => 20])); + yield array_to_rows([['value' => 10], ['value' => 20]], schema(int_schema('value'))); })(); $batches = iterator_to_array($processor->process($generator, flow_context()), preserve_keys: false); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php index 1330f9c77a..88583bea0e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Row; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_to_row; @@ -13,9 +14,9 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\Filesystem\DSL\partition; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_string; @@ -29,7 +30,7 @@ public function test_building_array_to_row_with_entry_that_is_list_of_strings(): flow_context(config())->backend(), ); - static::assertEquals(row(['data' => ['a', 'b', 'c', 'd']]), $row); + static::assertSame(['data' => ['a', 'b', 'c', 'd']], $row->toArray()); } public function test_building_single_row_from_array_with_rows_fails(): void @@ -43,24 +44,40 @@ public function test_building_single_row_from_array_with_rows_fails(): void flow_context(config())->backend(), ); - static::assertEquals( - row([ + static::assertSame( + [ 'e00' => ['id' => 1234, 'deleted' => false, 'phase' => null], 'e01' => ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], - ]), - $row, + ], + $row->toArray(), ); } - public function test_building_single_row_from_array_with_schema_and_additional_fields_not_covered_by_schema(): void + public function test_refuses_an_undeclared_key(): void { - $row = array_to_row( + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "phase" (row 0) is not declared by the schema', + ); + + array_to_row( ['id' => 1234, 'deleted' => false, 'phase' => null], schema(int_schema('id'), bool_schema('deleted')), flow_context(config())->backend(), ); + } + + public function test_refuses_an_undeclared_partition(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "year" (row 0) is not declared by the schema', + ); - static::assertEquals(row(['id' => 1234, 'deleted' => false]), $row); + array_to_row(['id' => 1234], schema(int_schema('id')), flow_context(config())->backend(), [partition( + 'year', + '2024', + )]); } public function test_building_single_row_from_array_with_schema_but_entries_not_available_in_rows(): void @@ -71,7 +88,7 @@ public function test_building_single_row_from_array_with_schema_but_entries_not_ flow_context(config())->backend(), ); - static::assertEquals(row(['id' => 1234, 'deleted' => false, 'phase' => null]), $row); + static::assertSame(['id' => 1234, 'deleted' => false, 'phase' => null], $row->toArray()); } public function test_building_single_row_from_flat_array(): void @@ -86,6 +103,6 @@ public function test_building_single_row_from_flat_array(): void flow_context(config())->backend(), ); - static::assertEquals(row(['id' => 1234, 'deleted' => false, 'phase' => null]), $row); + static::assertSame(['id' => 1234, 'deleted' => false, 'phase' => null], $row->toArray()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Comparator/NativeComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Comparator/NativeComparatorTest.php index e206d1502d..d715eb6960 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Comparator/NativeComparatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Comparator/NativeComparatorTest.php @@ -7,7 +7,7 @@ use Flow\ETL\Row\Comparator\NativeComparator; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -16,8 +16,8 @@ final class NativeComparatorTest extends FlowTestCase public function test_row_comparison(): void { static::assertTrue((new NativeComparator())->equals( - row(['test' => 'test']), - row(['test' => 'test']), + array_to_row(['test' => 'test'], schema(str_schema('test'))), + array_to_row(['test' => 'test'], schema(str_schema('test'))), schema(str_schema('test')), )); } @@ -25,8 +25,8 @@ public function test_row_comparison(): void public function test_row_comparison_for_different_rows(): void { static::assertFalse((new NativeComparator())->equals( - row(['test' => 'test']), - row(['test' => 'other']), + array_to_row(['test' => 'test'], schema(str_schema('test'))), + array_to_row(['test' => 'other'], schema(str_schema('test'))), schema(str_schema('test')), )); } @@ -34,8 +34,8 @@ public function test_row_comparison_for_different_rows(): void public function test_row_comparison_for_rows_with_different_columns(): void { static::assertFalse((new NativeComparator())->equals( - row(['test' => 'test']), - row(['other' => 'test']), + array_to_row(['test' => 'test'], schema(str_schema('test'))), + array_to_row(['other' => 'test'], schema(str_schema('other'))), schema(str_schema('test')), )); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/DeclaredColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/DeclaredColumnsTest.php new file mode 100644 index 0000000000..ccc3c89555 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/DeclaredColumnsTest.php @@ -0,0 +1,55 @@ + 1, 'name' => 'one'], ['id' => 2]], + (new DeclaredColumns())->project( + [['id' => 1, 'name' => 'one'], ['id' => 2]], + schema(int_schema('id'), str_schema('name', nullable: true)), + ), + ); + } + + public function test_drops_a_column_the_schema_does_not_declare(): void + { + static::assertSame( + [['id' => 1], ['id' => 2]], + (new DeclaredColumns())->project([ + ['id' => 1, 'name' => 'one'], + ['id' => 2, 'nmae' => 'two'], + ], schema(int_schema('id'))), + ); + } + + public function test_keeps_a_numeric_column_name_declared_as_is(): void + { + static::assertSame( + [[2024 => 1]], + (new DeclaredColumns())->project([['2024' => 1, 'other' => 2]], schema(int_schema('2024'))), + ); + } + + public function test_keeps_a_position_declared_by_its_positional_name(): void + { + static::assertSame([[0 => 'a']], (new DeclaredColumns())->project([['a', 'b']], schema(str_schema('e00')))); + } + + public function test_an_empty_batch_projects_to_nothing(): void + { + static::assertSame([], (new DeclaredColumns())->project([], schema(int_schema('id')))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/InferredBatchTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/InferredBatchTest.php deleted file mode 100644 index 46ffab9a81..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/InferredBatchTest.php +++ /dev/null @@ -1,112 +0,0 @@ -of([ - ['id' => 1, 'name' => 'a'], - ['id' => 2], - ])->schema(), - ); - } - - public function test_an_empty_batch_infers_an_empty_schema(): void - { - static::assertEquals(rows(schema()), (new InferredBatch())->of([])); - } - - public function test_an_explicit_null_makes_the_column_nullable(): void - { - static::assertEquals( - schema(int_schema('id'), str_schema('name', nullable: true)), - (new InferredBatch())->of([ - ['id' => 1, 'name' => 'a'], - ['id' => 2, 'name' => null], - ])->schema(), - ); - } - - public function test_a_numeric_column_name_is_a_string_column(): void - { - // PHP hands a numeric array key back as an int, and definition_from_type() takes - // Reference|string - a pivot names its columns by their own values, so this is reachable - $values = []; - - foreach ([0, 7] as $pivotValue) { - $values[(string) $pivotValue] = $pivotValue + 1; - } - - // PHP cannot hold '0' as a string key, which is precisely the shape under test - $inferred = (new InferredBatch())->of([$values]); - - static::assertSame(['0', '7'], $inferred->schema()->references()->names()); - static::assertSame([['0' => 1, '7' => 8]], $inferred->toArray()); - } - - public function test_rows_keep_their_values_verbatim(): void - { - static::assertEquals( - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])), - (new InferredBatch())->of([['id' => 1, 'name' => 'a']]), - ); - } - - /** - * Widening derives one column type from values of two, so the values follow the schema it just - * derived - otherwise the batch would contradict its own declaration at the door. - */ - public function test_widening_folds_int_and_string_into_one_column_and_converts_the_values(): void - { - $rows = (new InferredBatch())->of([ - ['v' => 1], - ['v' => 'text'], - ]); - - static::assertSame('string', $rows->schema()->get('v')->type()->toString()); - static::assertSame([['v' => '1'], ['v' => 'text']], $rows->toArray()); - } - - public function test_a_midnight_outside_utc_infers_datetime(): void - { - static::assertSame( - 'datetime', - (new InferredBatch()) - ->of([['at' => new DateTimeImmutable('2026-01-01 00:00:00', new DateTimeZone('Europe/Warsaw'))]]) - ->schema() - ->get('at') - ->type() - ->toString(), - ); - } - - public function test_a_midnight_in_utc_infers_date(): void - { - static::assertSame( - 'date', - (new InferredBatch()) - ->of([['at' => new DateTimeImmutable('2026-01-01 00:00:00', new DateTimeZone('UTC'))]]) - ->schema() - ->get('at') - ->type() - ->toString(), - ); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php index e91ad83952..d9c087a726 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php @@ -11,10 +11,11 @@ use Flow\ETL\Schema; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; 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; +use function Flow\ETL\DSL\str_schema; final class RowsBufferTest extends FlowTestCase { @@ -27,7 +28,7 @@ public function test_a_batch_factory_builds_each_released_batch(): void static::assertTrue( $buffer - ->add(row(['id' => 1])) + ->add(array_to_row(['id' => 1], schema(int_schema('id')))) ?->schema() ->get('id') ->isNullable(), @@ -38,28 +39,28 @@ public function test_the_default_batch_checks_every_row(): void { $this->expectException(SchemaMismatchException::class); - (new RowsBuffer(schema(int_schema('id')), 1))->add(row(['id' => 'x'])); + (new RowsBuffer(schema(int_schema('id')), 1))->add(array_to_row(['id' => 'x'], schema(str_schema('id')))); } public function test_add_returns_a_full_batch_and_resets(): void { $buffer = new RowsBuffer(schema(int_schema('id')), 2); - static::assertNull($buffer->add(row(['id' => 1]))); + static::assertNull($buffer->add(array_to_row(['id' => 1], schema(int_schema('id'))))); - $batch = $buffer->add(row(['id' => 2])); + $batch = $buffer->add(array_to_row(['id' => 2], schema(int_schema('id')))); static::assertNotNull($batch); static::assertSame([1, 2], $batch->reduceToArray('id')); - static::assertNull($buffer->add(row(['id' => 3]))); + static::assertNull($buffer->add(array_to_row(['id' => 3], schema(int_schema('id'))))); } public function test_add_returns_null_until_size_is_reached(): void { $buffer = new RowsBuffer(schema(int_schema('id')), 3); - static::assertNull($buffer->add(row(['id' => 1]))); - static::assertNull($buffer->add(row(['id' => 2]))); + static::assertNull($buffer->add(array_to_row(['id' => 1], schema(int_schema('id'))))); + static::assertNull($buffer->add(array_to_row(['id' => 2], schema(int_schema('id'))))); } public function test_flush_returns_null_when_empty(): void @@ -70,7 +71,7 @@ public function test_flush_returns_null_when_empty(): void public function test_flush_returns_the_remainder(): void { $buffer = new RowsBuffer(schema(int_schema('id')), 3); - $buffer->add(row(['id' => 1])); + $buffer->add(array_to_row(['id' => 1], schema(int_schema('id')))); $batch = $buffer->flush(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/UnresolvedReferenceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/UnresolvedReferenceTest.php index 602e86b337..2db60cebf9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/UnresolvedReferenceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/UnresolvedReferenceTest.php @@ -7,9 +7,11 @@ use Flow\ETL\Row\SortOrder; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; final class UnresolvedReferenceTest extends FlowTestCase { @@ -40,31 +42,34 @@ public function test_executing_equals_expression(): void { $ref = ref('a')->equals(ref('b')); - static::assertTrue($ref->eval(row(['a' => 1, 'b' => 1]), flow_context())); + static::assertTrue($ref->eval( + array_to_row(['a' => 1, 'b' => 1], schema(int_schema('a'), int_schema('b'))), + flow_context(), + )); } public function test_executing_expression(): void { $ref = ref('b')->literal(100); - static::assertSame(100, $ref->eval(row(['a' => 1]), flow_context())); + static::assertSame(100, $ref->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context())); } public function test_is_even(): void { $ref = ref('a')->isEven(); - static::assertFalse($ref->eval(row(['a' => 1]), flow_context())); + static::assertFalse($ref->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context())); - static::assertTrue($ref->eval(row(['a' => 2]), flow_context())); + static::assertTrue($ref->eval(array_to_row(['a' => 2], schema(int_schema('a'))), flow_context())); } public function test_is_odd(): void { $ref = ref('a')->isOdd(); - static::assertTrue($ref->eval(row(['a' => 1]), flow_context())); + static::assertTrue($ref->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context())); - static::assertFalse($ref->eval(row(['a' => 2]), flow_context())); + static::assertFalse($ref->eval(array_to_row(['a' => 2], schema(int_schema('a'))), flow_context())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php index cc3483d06a..36a09b0b3e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php @@ -9,12 +9,12 @@ use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\TestWith; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; @@ -31,7 +31,7 @@ public function test_get_throws_when_the_column_is_absent(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Column "missing" does not exist'); - row(['id' => 1])->get('missing'); + array_to_row(['id' => 1], schema(int_schema('id')))->get('missing'); } #[TestWith([-1])] @@ -41,12 +41,12 @@ public function test_a_view_outside_its_batch_is_refused(int $index): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage("Row {$index} does not exist in a batch of 1 rows"); - row(['id' => 1])->rows->row($index); + array_to_row(['id' => 1], schema(int_schema('id')))->rows->row($index); } public function test_has(): void { - $row = row(['id' => 1, 'name' => 'one']); + $row = array_to_row(['id' => 1, 'name' => 'one'], schema(int_schema('id'), str_schema('name'))); static::assertTrue($row->has('id')); static::assertTrue($row->has('id', 'name')); @@ -63,26 +63,35 @@ public function test_hash_ignores_column_order(): void $schema = schema(int_schema('id'), bool_schema('bool'), str_schema('string')); static::assertSame( - row(['id' => 1, 'string' => 'string', 'bool' => false])->hash($schema), - row(['bool' => false, 'id' => 1, 'string' => 'string'])->hash($schema), + array_to_row( + ['id' => 1, 'string' => 'string', 'bool' => false], + schema(int_schema('id'), str_schema('string'), bool_schema('bool')), + )->hash($schema), + array_to_row( + ['bool' => false, 'id' => 1, 'string' => 'string'], + schema(bool_schema('bool'), int_schema('id'), str_schema('string')), + )->hash($schema), ); } public function test_hash_of_an_empty_row(): void { - static::assertSame(row([])->hash(schema()), row([])->hash(schema())); + static::assertSame(array_to_row([], schema())->hash(schema()), array_to_row([], schema())->hash(schema())); } public function test_hash_of_different_rows(): void { $schema = schema(list_schema('list', type_list(type_integer()))); - static::assertNotSame(row(['list' => [1, 2, 3]])->hash($schema), row(['list' => [3, 2, 1]])->hash($schema)); + static::assertNotSame( + array_to_row(['list' => [1, 2, 3]], schema(list_schema('list', type_list(type_integer()))))->hash($schema), + array_to_row(['list' => [3, 2, 1]], schema(list_schema('list', type_list(type_integer()))))->hash($schema), + ); } public function test_names_and_values_keep_storage_order(): void { - $row = row(['b' => 2, 'a' => 1]); + $row = array_to_row(['b' => 2, 'a' => 1], schema(int_schema('b'), int_schema('a'))); static::assertSame(['b', 'a'], $row->names()); static::assertSame(['b' => 2, 'a' => 1], $row->values()); @@ -90,14 +99,24 @@ public function test_names_and_values_keep_storage_order(): void public function test_transforms_row_to_array(): void { - $row = row([ - 'id' => 1234, - 'deleted' => false, - 'created-at' => $createdAt = new DateTimeImmutable('2020-07-13 15:00'), - 'phase' => null, - 'items' => ['item-id' => 1, 'name' => 'one'], - 'statuses' => ['NEW', 'PENDING'], - ]); + $row = array_to_row( + [ + 'id' => 1234, + 'deleted' => false, + 'created-at' => $createdAt = new DateTimeImmutable('2020-07-13 15:00'), + 'phase' => null, + 'items' => ['item-id' => 1, 'name' => 'one'], + 'statuses' => ['NEW', 'PENDING'], + ], + schema( + int_schema('id'), + bool_schema('deleted'), + datetime_schema('created-at'), + str_schema('phase', nullable: true), + structure_schema('items', type_structure(['item-id' => type_integer(), 'name' => type_string()])), + list_schema('statuses', type_list(type_string())), + ), + ); static::assertEquals( [ @@ -114,7 +133,12 @@ public function test_transforms_row_to_array(): void public function test_transforms_row_to_array_without_keys(): void { - static::assertSame([1, 'one'], row(['id' => 1, 'name' => 'one'])->toArray(withKeys: false)); + static::assertSame( + [1, 'one'], + array_to_row(['id' => 1, 'name' => 'one'], schema(int_schema('id'), str_schema('name')))->toArray( + withKeys: false, + ), + ); } /** @@ -130,13 +154,13 @@ public function test_values_are_read_by_the_schema(): void map_schema('statuses', type_map(type_integer(), type_string())), ); $createdAt = new DateTimeImmutable('2020-07-13 15:00'); - $row = row([ + $row = array_to_row([ 'id' => 1, 'name' => 'one', 'created-at' => $createdAt, 'items' => ['a' => 1], 'statuses' => ['NEW'], - ]); + ], $schema); $values = []; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php index aa85ae8c34..38af1722fc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Rows; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_to_rows; @@ -12,8 +13,6 @@ use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_list; @@ -33,11 +32,10 @@ public function test_building_array_to_rows_with_entry_that_is_list_of_strings() ); static::assertEquals( - rows( - schema(list_schema('data', type_list(type_string()))), - row(['data' => ['a', 'b', 'c', 'd']]), - row(['data' => ['e', 'f', 'g', 'd']]), - ), + array_to_rows([ + ['data' => ['a', 'b', 'c', 'd']], + ['data' => ['e', 'f', 'g', 'd']], + ], schema(list_schema('data', type_list(type_string())))), $rows, ); } @@ -53,23 +51,23 @@ public function test_building_array_to_rows_with_entry_that_is_list_of_strings_w ); static::assertEquals( - rows(schema(list_schema('data', type_list(type_string()))), row(['data' => ['e', 'f', 'g', 'd']])), + array_to_rows([['data' => ['e', 'f', 'g', 'd']]], schema(list_schema('data', type_list(type_string())))), $rows, ); } - public function test_building_row_from_array_with_schema_and_additional_fields_not_covered_by_schema(): void + public function test_refuses_an_undeclared_key_of_a_single_flat_row(): void { - $rows = array_to_rows( + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "phase" (row 0) is not declared by the schema', + ); + + array_to_rows( ['id' => 1234, 'deleted' => false, 'phase' => null], schema(int_schema('id'), bool_schema('deleted')), flow_context(config())->backend(), ); - - static::assertEquals( - rows(schema(int_schema('id'), bool_schema('deleted')), row(['id' => 1234, 'deleted' => false])), - $rows, - ); } public function test_building_row_from_array_with_schema_but_entries_not_available_in_rows(): void @@ -81,9 +79,9 @@ public function test_building_row_from_array_with_schema_but_entries_not_availab ); static::assertEquals( - rows( + array_to_rows( + [['id' => 1234, 'deleted' => false, 'phase' => null]], schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', nullable: true)), - row(['id' => 1234, 'deleted' => false, 'phase' => null]), ), $rows, ); @@ -101,34 +99,32 @@ public function test_building_rows_from_array(): void ); static::assertEquals( - rows( + array_to_rows( + [ + ['id' => 1234, 'deleted' => false, 'phase' => null], + ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], + ], schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', nullable: true)), - row(['id' => 1234, 'deleted' => false, 'phase' => null]), - row(['id' => 4321, 'deleted' => true, 'phase' => 'launch']), ), $rows, ); } - public function test_building_rows_from_array_with_schema_and_additional_fields_not_covered_by_schema(): void + public function test_refuses_an_undeclared_key(): void { - $rows = array_to_rows( + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "nmae" (row 1) is not declared by the schema', + ); + + array_to_rows( [ - ['id' => 1234, 'deleted' => false, 'phase' => null], - ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], + ['id' => 1234, 'name' => 'launch'], + ['id' => 4321, 'nmae' => 'landing'], ], - schema(int_schema('id'), bool_schema('deleted')), + schema(int_schema('id'), str_schema('name', nullable: true)), flow_context(config())->backend(), ); - - static::assertEquals( - rows( - schema(int_schema('id'), bool_schema('deleted')), - row(['id' => 1234, 'deleted' => false]), - row(['id' => 4321, 'deleted' => true]), - ), - $rows, - ); } public function test_building_rows_from_array_with_schema_but_entries_not_available_in_rows(): void @@ -143,10 +139,12 @@ public function test_building_rows_from_array_with_schema_but_entries_not_availa ); static::assertEquals( - rows( + array_to_rows( + [ + ['id' => 1234, 'deleted' => false, 'phase' => null], + ['id' => 4321, 'deleted' => true, 'phase' => null], + ], schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', nullable: true)), - row(['id' => 1234, 'deleted' => false, 'phase' => null]), - row(['id' => 4321, 'deleted' => true, 'phase' => null]), ), $rows, ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php index 7d43717f3e..73dd36c4de 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php @@ -14,9 +14,8 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -28,22 +27,22 @@ final class RowsBuilderTest extends FlowTestCase public static function refused_views(): Generator { yield 'a not null column the source lacks' => [ - rows(schema(int_schema('id')), row(['id' => 1])), + array_to_rows([['id' => 1]], schema(int_schema('id'))), schema(int_schema('id'), str_schema('name')), 'column "name" (row 0) declared by the schema is missing from the row', ]; yield 'null under not null' => [ - rows(schema(int_schema('id', nullable: true)), row(['id' => null])), + array_to_rows([['id' => null]], schema(int_schema('id', nullable: true))), schema(int_schema('id')), 'column "id" (row 0): could not convert null to integer, column is not nullable', ]; yield 'a value that matches only after a cast' => [ - rows(schema(str_schema('id')), row(['id' => '2'])), + array_to_rows([['id' => '2']], schema(str_schema('id'))), schema(int_schema('id')), 'column "id" (row 0): could not convert \'2\' (string) to integer', ]; yield 'a column the target does not declare' => [ - rows(schema(int_schema('id'), int_schema('extra')), row(['id' => 1, 'extra' => 2])), + array_to_rows([['id' => 1, 'extra' => 2]], schema(int_schema('id'), int_schema('extra'))), schema(int_schema('id')), 'column "extra" (row 0) is not declared by the schema', ]; @@ -87,7 +86,7 @@ public function test_a_view_of_another_definition_keeps_a_value_that_matches_the static::assertSame( [['id' => 5, 'name' => null]], (new RowsBuilder(schema(int_schema('id'), str_schema('name', nullable: true)), new PhpBackend())) - ->appendFrom(rows(schema(int_schema('id', nullable: true)), row(['id' => 5])), 0) + ->appendFrom(array_to_rows([['id' => 5]], schema(int_schema('id', nullable: true))), 0) ->finish() ->toArray(), ); @@ -99,8 +98,8 @@ public function test_a_refused_view_is_placed_at_its_output_row(): void $this->expectExceptionMessage('column "id" (row 1): could not convert \'x\' (string) to integer'); (new RowsBuilder(schema(int_schema('id')), new PhpBackend())) - ->appendFrom(rows(schema(int_schema('id')), row(['id' => 1])), 0) - ->appendFrom(rows(schema(str_schema('id')), row(['id' => 'x'])), 0); + ->appendFrom(array_to_rows([['id' => 1]], schema(int_schema('id'))), 0) + ->appendFrom(array_to_rows([['id' => 'x']], schema(str_schema('id'))), 0); } #[DataProvider('refused_views')] @@ -118,7 +117,7 @@ public function test_refuses_a_view_that_does_not_fit_the_target( public function test_a_missing_nullable_column_is_padded_with_null(): void { static::assertEquals( - rows(schema(int_schema('id'), str_schema('name', nullable: true)), row(['id' => 1, 'name' => null])), + array_to_rows([['id' => 1, 'name' => null]], schema(int_schema('id'), str_schema('name', nullable: true))), (new RowsBuilder( schema(int_schema('id'), str_schema('name', nullable: true)), new PhpBackend(), @@ -210,7 +209,7 @@ public function test_rows_follow_the_schema_column_order(): void public function test_every_value_is_cast_against_its_own_column(): void { static::assertEquals( - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => '2'])), + array_to_rows([['id' => 1, 'name' => '2']], schema(int_schema('id'), str_schema('name'))), (new RowsBuilder(schema(int_schema('id'), str_schema('name')), new PhpBackend()))->append([ 'id' => '1', 'name' => 2, @@ -236,13 +235,15 @@ public function test_appending_no_rows_changes_nothing(): void public function test_copies_physical_cells_from_another_batch(): void { - $source = rows( + $source = array_to_rows( + [ + ['id' => 1, 'name' => 'a'], + [ + 'id' => 2, + 'name' => 'b', + ], + ], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'a']), - row([ - 'id' => 2, - 'name' => 'b', - ]), ); static::assertSame( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsJoinTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsJoinTest.php index c48b138ed8..e1ac1d9f4c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsJoinTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsJoinTest.php @@ -8,10 +8,10 @@ use Flow\ETL\Join\Expression; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\join_on; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -20,18 +20,19 @@ final class RowsJoinTest extends FlowTestCase { public function test_cross_join(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), ); - $joined = $left->joinCross(rows( + $joined = $left->joinCross(array_to_rows( + [['num' => 1, 'active' => true], ['num' => 2, 'active' => false]], schema(int_schema('num'), bool_schema('active')), - row(['num' => 1, 'active' => true]), - row(['num' => 2, 'active' => false]), )); static::assertEquals( @@ -51,12 +52,14 @@ public function test_cross_join(): void public function test_cross_join_empty(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), ); // n x 0 = 0, and a zero-row batch fits the cross schema vacuously @@ -67,15 +70,16 @@ public function test_cross_join_with_an_empty_side_yields_no_rows_under_the_cros { // a cross join with an empty side produces zero rows, and the batch still declares both // sides' columns - the schema describes the plan, not the cardinality - $emptyRight = rows( + $emptyRight = array_to_rows( + [['id' => 1, 'country' => 'PL']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), )->joinCross(rows(schema(str_schema('code')))); static::assertSame(['id', 'country', 'joined_code'], $emptyRight->schema()->references()->names()); static::assertSame([], $emptyRight->toArray()); - $emptyLeft = rows(schema(int_schema('id')))->joinCross(rows(schema(str_schema('code')), row(['code' => 'PL']))); + $emptyLeft = rows(schema(int_schema('id'))) + ->joinCross(array_to_rows([['code' => 'PL']], schema(str_schema('code')))); static::assertSame(['id', 'joined_code'], $emptyLeft->schema()->references()->names()); static::assertSame([], $emptyLeft->toArray()); @@ -85,12 +89,14 @@ public function test_cross_join_left_empty(): void { $left = rows(schema()); - $joined = $left->joinCross(rows( + $joined = $left->joinCross(array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), )); static::assertSame([], $joined->toArray()); @@ -103,28 +109,32 @@ public function test_cross_join_left_with_name_conflict(): void 'Entry definitions must be unique, duplicated entries: [active], all: [id, country, active, active]', ); - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'active' => false], + ['id' => 2, 'country' => 'PL', 'active' => false], + ['id' => 3, 'country' => 'US', 'active' => false], + ['id' => 4, 'country' => 'FR', 'active' => false], + ], schema(int_schema('id'), str_schema('country'), bool_schema('active')), - row(['id' => 1, 'country' => 'PL', 'active' => false]), - row(['id' => 2, 'country' => 'PL', 'active' => false]), - row(['id' => 3, 'country' => 'US', 'active' => false]), - row(['id' => 4, 'country' => 'FR', 'active' => false]), ); - $left->joinCross(rows(schema(bool_schema('active')), row(['active' => true])), ''); + $left->joinCross(array_to_rows([['active' => true]], schema(bool_schema('active'))), ''); } public function test_cross_join_left_with_name_conflict_with_prefix(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL', 'active' => false], + ['id' => 2, 'country' => 'PL', 'active' => false], + ['id' => 3, 'country' => 'US', 'active' => false], + ['id' => 4, 'country' => 'FR', 'active' => false], + ], schema(int_schema('id'), str_schema('country'), bool_schema('active')), - row(['id' => 1, 'country' => 'PL', 'active' => false]), - row(['id' => 2, 'country' => 'PL', 'active' => false]), - row(['id' => 3, 'country' => 'US', 'active' => false]), - row(['id' => 4, 'country' => 'FR', 'active' => false]), ); - $joined = $left->joinCross(rows(schema(bool_schema('active')), row(['active' => true])), '_'); + $joined = $left->joinCross(array_to_rows([['active' => true]], schema(bool_schema('active'))), '_'); static::assertEquals( [ @@ -139,12 +149,14 @@ public function test_cross_join_left_with_name_conflict_with_prefix(): void public function test_inner_empty(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), ); $joined = $left->joinInner(rows(schema()), Expression::on(['country' => 'code'])); @@ -154,20 +166,24 @@ public function test_inner_empty(): void public function test_inner_join(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), ); $joined = $left->joinInner( - rows( + array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), ), join_on(['country' => 'code'], 'joined_'), ); @@ -184,11 +200,13 @@ public function test_inner_join(): void public function test_inner_join_emits_every_matching_right_row(): void { - $joined = rows(schema(int_schema('id'), str_schema('country')), row(['id' => 1, 'country' => 'PL']))->joinInner( - rows( + $joined = array_to_rows( + [['id' => 1, 'country' => 'PL']], + schema(int_schema('id'), str_schema('country')), + )->joinInner( + array_to_rows( + [['code' => 1, 'city' => 'Warsaw'], ['code' => 1, 'city' => 'Cracow']], schema(int_schema('code'), str_schema('city')), - row(['code' => 1, 'city' => 'Warsaw']), - row(['code' => 1, 'city' => 'Cracow']), ), join_on(['id' => 'code']), ); @@ -207,11 +225,13 @@ public function test_inner_join_into_empty(): void $left = rows(schema()); $joined = $left->joinInner( - rows( + array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country' => 'code']), ); @@ -226,20 +246,24 @@ public function test_inner_join_with_duplicated_entries(): void 'Entry definitions must be unique, duplicated entries: [id], all: [id, country, id, code, name]', ); - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), ); $left->joinInner( - rows( + array_to_rows( + [ + ['id' => 101, 'code' => 'PL', 'name' => 'Poland'], + ['id' => 102, 'code' => 'US', 'name' => 'United States'], + ['id' => 103, 'code' => 'GB', 'name' => 'Great Britain'], + ], schema(int_schema('id'), str_schema('code'), str_schema('name')), - row(['id' => 101, 'code' => 'PL', 'name' => 'Poland']), - row(['id' => 102, 'code' => 'US', 'name' => 'United States']), - row(['id' => 103, 'code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country' => 'code'], joinPrefix: ''), ); @@ -247,20 +271,24 @@ public function test_inner_join_with_duplicated_entries(): void public function test_inner_join_without_prefix(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'PL'], + ['id' => 3, 'country_code' => 'US'], + ['id' => 4, 'country_code' => 'FR'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'PL']), - row(['id' => 3, 'country_code' => 'US']), - row(['id' => 4, 'country_code' => 'FR']), ); $joined = $left->joinInner( - rows( + array_to_rows( + [ + ['country_code' => 'PL', 'name' => 'Poland'], + ['country_code' => 'US', 'name' => 'United States'], + ['country_code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('country_code'), str_schema('name')), - row(['country_code' => 'PL', 'name' => 'Poland']), - row(['country_code' => 'US', 'name' => 'United States']), - row(['country_code' => 'GB', 'name' => 'Great Britain']), ), join_on(['country_code' => 'country_code']), ); @@ -277,35 +305,30 @@ public function test_inner_join_without_prefix(): void public function test_left_anti_join(): void { - $left = rows( + $left = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ); $joined = $left->joinLeftAnti( - rows( + array_to_rows( + [['code' => 'US', 'name' => 'United States'], ['code' => 'FR', 'name' => 'France']], schema(str_schema('code'), str_schema('name')), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'FR', 'name' => 'France']), ), Expression::on(['country' => 'code']), ); static::assertEquals( - rows(schema(int_schema('id'), str_schema('country')), row(['id' => 1, 'country' => 'PL'])), + array_to_rows([['id' => 1, 'country' => 'PL']], schema(int_schema('id'), str_schema('country'))), $joined, ); } public function test_left_anti_join_on_empty(): void { - $left = rows( + $left = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ); $joined = $left->joinLeftAnti(rows(schema()), Expression::on(['country' => 'code'])); @@ -315,43 +338,44 @@ public function test_left_anti_join_on_empty(): void public function test_left_anti_join_without_prefix(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'US'], + ['id' => 3, 'country_code' => 'FR'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'US']), - row(['id' => 3, 'country_code' => 'FR']), ); $joined = $left->joinLeftAnti( - rows( + array_to_rows( + [['country_code' => 'US', 'name' => 'United States'], ['country_code' => 'FR', 'name' => 'France']], schema(str_schema('country_code'), str_schema('name')), - row(['country_code' => 'US', 'name' => 'United States']), - row(['country_code' => 'FR', 'name' => 'France']), ), Expression::on(['country_code' => 'country_code']), ); static::assertEquals( - rows(schema(int_schema('id'), str_schema('country_code')), row(['id' => 1, 'country_code' => 'PL'])), + array_to_rows([['id' => 1, 'country_code' => 'PL']], schema(int_schema('id'), str_schema('country_code'))), $joined, ); } public function test_left_join(): void { - $left = rows( + $left = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ); $joined = $left->joinLeft( - rows( + array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country' => 'code'], 'joined_'), ); @@ -368,21 +392,17 @@ public function test_left_join(): void public function test_left_join_empty(): void { - $left = rows( + $left = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ); $joined = $left->joinLeft(rows(schema()), Expression::on(['country' => 'code'])); static::assertEquals( - rows( + array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ), $joined, ); @@ -390,21 +410,25 @@ public function test_left_join_empty(): void public function test_left_join_empty_without_prefix(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'US'], + ['id' => 3, 'country_code' => 'FR'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'US']), - row(['id' => 3, 'country_code' => 'FR']), ); $joined = $left->joinLeft(rows(schema()), Expression::on(['country_code' => 'country_code'])); static::assertEquals( - rows( + array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'US'], + ['id' => 3, 'country_code' => 'FR'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'US']), - row(['id' => 3, 'country_code' => 'FR']), ), $joined, ); @@ -415,11 +439,13 @@ public function test_left_join_to_empty(): void $left = rows(schema()); $joined = $left->joinLeft( - rows( + array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country' => 'code']), ); @@ -437,19 +463,19 @@ public function test_left_join_with_the_duplicated_columns(): void 'Entry definitions must be unique, duplicated entries: [id], all: [id, country, id, code, name]', ); - $left = rows( + $left = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ); $left->joinLeft( - rows( + array_to_rows( + [ + ['id' => 100, 'code' => 'PL', 'name' => 'Poland'], + ['id' => 101, 'code' => 'US', 'name' => 'United States'], + ['id' => 102, 'code' => 'GB', 'name' => 'Great Britain'], + ], schema(int_schema('id'), str_schema('code'), str_schema('name')), - row(['id' => 100, 'code' => 'PL', 'name' => 'Poland']), - row(['id' => 101, 'code' => 'US', 'name' => 'United States']), - row(['id' => 102, 'code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country' => 'code'], ''), ); @@ -457,19 +483,23 @@ public function test_left_join_with_the_duplicated_columns(): void public function test_left_join_without_prefix(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'US'], + ['id' => 3, 'country_code' => 'FR'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'US']), - row(['id' => 3, 'country_code' => 'FR']), ); $joined = $left->joinLeft( - rows( + array_to_rows( + [ + ['country_code' => 'PL', 'name' => 'Poland'], + ['country_code' => 'US', 'name' => 'United States'], + ['country_code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('country_code'), str_schema('name')), - row(['country_code' => 'PL', 'name' => 'Poland']), - row(['country_code' => 'US', 'name' => 'United States']), - row(['country_code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country_code' => 'country_code']), ); @@ -486,20 +516,24 @@ public function test_left_join_without_prefix(): void public function test_right_join(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), ); $joined = $left->joinRight( - rows( + array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country' => 'code'], 'joined_'), ); @@ -517,12 +551,14 @@ public function test_right_join(): void public function test_right_join_empty(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), ); $joined = $left->joinRight(rows(schema()), Expression::on(['country' => 'code'])); @@ -538,11 +574,13 @@ public function test_right_join_to_empty(): void $left = rows(schema()); $joined = $left->joinRight( - rows( + array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country' => 'code'], 'joined_'), ); @@ -564,20 +602,24 @@ public function test_right_join_with_duplicated_entry_names(): void 'Entry definitions must be unique, duplicated entries: [id], all: [id, country, id, code, name]', ); - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country' => 'PL'], + ['id' => 2, 'country' => 'PL'], + ['id' => 3, 'country' => 'US'], + ['id' => 4, 'country' => 'FR'], + ], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), - row(['id' => 3, 'country' => 'US']), - row(['id' => 4, 'country' => 'FR']), ); $left->joinRight( - rows( + array_to_rows( + [ + ['id' => 101, 'code' => 'PL', 'name' => 'Poland'], + ['id' => 102, 'code' => 'US', 'name' => 'United States'], + ['id' => 103, 'code' => 'GB', 'name' => 'Great Britain'], + ], schema(int_schema('id'), str_schema('code'), str_schema('name')), - row(['id' => 101, 'code' => 'PL', 'name' => 'Poland']), - row(['id' => 102, 'code' => 'US', 'name' => 'United States']), - row(['id' => 103, 'code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country' => 'code'], ''), ); @@ -585,20 +627,24 @@ public function test_right_join_with_duplicated_entry_names(): void public function test_right_join_without_prefix(): void { - $left = rows( + $left = array_to_rows( + [ + ['id' => 1, 'country_code' => 'PL'], + ['id' => 2, 'country_code' => 'PL'], + ['id' => 3, 'country_code' => 'US'], + ['id' => 4, 'country_code' => 'FR'], + ], schema(int_schema('id'), str_schema('country_code')), - row(['id' => 1, 'country_code' => 'PL']), - row(['id' => 2, 'country_code' => 'PL']), - row(['id' => 3, 'country_code' => 'US']), - row(['id' => 4, 'country_code' => 'FR']), ); $joined = $left->joinRight( - rows( + array_to_rows( + [ + ['country_code' => 'PL', 'name' => 'Poland'], + ['country_code' => 'US', 'name' => 'United States'], + ['country_code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('country_code'), str_schema('name')), - row(['country_code' => 'PL', 'name' => 'Poland']), - row(['country_code' => 'US', 'name' => 'United States']), - row(['country_code' => 'GB', 'name' => 'Great Britain']), ), Expression::on(['country_code' => 'country_code']), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php index 4aa407aeb8..b185243e90 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php @@ -16,13 +16,12 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use function assert; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; @@ -43,10 +42,9 @@ final class RowsSerializationTest extends FlowTestCase { public function test_native_columns_survive_a_serialize_round_trip(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null]], schema(int_schema('id'), str_schema('name', nullable: true)), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => null]), ); /** @var Rows $restored */ @@ -61,10 +59,9 @@ public function test_xml_column_metadata_survives_a_serialize_round_trip(): void $document = new DOMDocument(); $document->loadXML('1'); - $rows = rows( - schema(xml_schema('x', metadata: Metadata::empty()->add('src', 'file.xml'))), - row(['x' => $document]), - ); + $rows = array_to_rows([[ + 'x' => $document, + ]], schema(xml_schema('x', metadata: Metadata::empty()->add('src', 'file.xml')))); /** @var Rows $restored */ $restored = unserialize(serialize($rows)); @@ -81,10 +78,9 @@ public function test_xml_document_survives_a_round_trip(): void $document = new DOMDocument(); $document->loadXML('1'); - $restored = type_instance_of(DOMDocument::class)->assert(RowsSerializationContext::roundTrip(rows( - schema(xml_schema('x')), - row(['x' => $document]), - ))->first()->get('x')); + $restored = type_instance_of(DOMDocument::class)->assert(RowsSerializationContext::roundTrip(array_to_rows([[ + 'x' => $document, + ]], schema(xml_schema('x'))))->first()->get('x')); static::assertSame($document->C14N(), $restored->C14N()); } @@ -94,10 +90,9 @@ public function test_xml_element_survives_a_round_trip(): void $document = new DOMDocument(); $document->loadXML('1'); - $restored = type_instance_of(DOMElement::class)->assert(RowsSerializationContext::roundTrip(rows( - schema(xml_element_schema('x')), - row(['x' => $document->documentElement]), - ))->first()->get('x')); + $restored = type_instance_of(DOMElement::class)->assert(RowsSerializationContext::roundTrip(array_to_rows([[ + 'x' => $document->documentElement, + ]], schema(xml_element_schema('x'))))->first()->get('x')); static::assertSame('1', $restored->C14N()); } @@ -109,11 +104,10 @@ public function test_restored_xml_elements_do_not_canonicalize_to_an_empty_strin $right = new DOMDocument(); $right->loadXML('999'); - $restored = RowsSerializationContext::roundTrip(rows( - schema(xml_element_schema('x')), - row(['x' => $left->documentElement]), - row(['x' => $right->documentElement]), - )); + $restored = RowsSerializationContext::roundTrip(array_to_rows([ + ['x' => $left->documentElement], + ['x' => $right->documentElement], + ], schema(xml_element_schema('x')))); $restoredLeft = type_instance_of(DOMElement::class)->assert($restored->first()->get('x')); $restoredRight = type_instance_of(DOMElement::class)->assert($restored->row(1)->get('x')); @@ -128,10 +122,9 @@ public function test_html_document_survives_a_round_trip(): void static::assertSame( type_string()->cast($document), - type_string()->cast(RowsSerializationContext::roundTrip(rows( - schema(html_schema('x')), - row(['x' => $document]), - ))->first()->get('x')), + type_string()->cast(RowsSerializationContext::roundTrip(array_to_rows([[ + 'x' => $document, + ]], schema(html_schema('x'))))->first()->get('x')), ); } @@ -142,16 +135,19 @@ public function test_html_element_survives_a_round_trip(): void static::assertSame( type_string()->cast($element), - type_string()->cast(RowsSerializationContext::roundTrip(rows( - schema(html_element_schema('x')), - row(['x' => $element]), - ))->first()->get('x')), + type_string()->cast(RowsSerializationContext::roundTrip(array_to_rows([[ + 'x' => $element, + ]], schema(html_element_schema('x'))))->first()->get('x')), ); } public function test_container_columns_survive_a_round_trip(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['l' => [1, null], 'm' => ['a' => 1], 's' => ['id' => 1, 'note' => 'x']], + ['l' => null, 'm' => [], 's' => ['id' => 2]], + ], schema( list_schema('l', type_list(type_optional(type_integer())), nullable: true), map_schema('m', type_map(type_string(), type_integer())), @@ -160,8 +156,6 @@ public function test_container_columns_survive_a_round_trip(): void 'note' => structure_element('note', type_string(), optional: true), ])), ), - row(['l' => [1, null], 'm' => ['a' => 1], 's' => ['id' => 1, 'note' => 'x']]), - row(['l' => null, 'm' => [], 's' => ['id' => 2]]), ); static::assertEquals($rows, RowsSerializationContext::roundTrip($rows)); @@ -188,7 +182,7 @@ public function test_constant_columns_survive_a_round_trip(): void public function test_a_batch_without_columns_keeps_its_row_count(): void { - $rows = rows(schema(), row([]), row([]), row([])); + $rows = array_to_rows([[], [], []], schema()); static::assertSame(3, RowsSerializationContext::roundTrip($rows)->count()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php index cf61feba44..628faf99fb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php @@ -22,13 +22,14 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -67,39 +68,39 @@ public function test_a_negative_size_is_refused(Closure $call): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Size must be greater than or equal to 0'); - $call(rows(schema(int_schema('id')), row(['id' => 1]))); + $call(array_to_rows([['id' => 1]], schema(int_schema('id')))); } public static function rows_diff_left_provider(): Generator { yield 'one entry identical row' => [ rows(schema()), - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 1]], schema(int_schema('number'))), ]; yield 'one entry right different - missing entry' => [ - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 1]], schema(int_schema('number'))), rows(schema()), ]; yield 'one entry left different - missing entry' => [ rows(schema()), rows(schema()), - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), ]; yield 'one entry right different - different entry' => [ - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number')), row(['number' => 2])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 2]], schema(int_schema('number'))), ]; yield 'one entry left different - different entry' => [ - rows(schema(int_schema('number')), row(['number' => 2])), - rows(schema(int_schema('number')), row(['number' => 2])), - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 2]], schema(int_schema('number'))), + array_to_rows([['number' => 2]], schema(int_schema('number'))), + array_to_rows([['number' => 1]], schema(int_schema('number'))), ]; } @@ -107,40 +108,40 @@ public static function rows_diff_right_provider(): Generator { yield 'one entry identical row' => [ rows(schema()), - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 1]], schema(int_schema('number'))), ]; yield 'one entry right different - missing entry' => [ rows(schema()), - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), rows(schema()), ]; yield 'one entry left different - missing entry' => [ - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), rows(schema()), - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), ]; yield 'one entry right different - different entry' => [ - rows(schema(int_schema('number')), row(['number' => 2])), - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number')), row(['number' => 2])), + array_to_rows([['number' => 2]], schema(int_schema('number'))), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 2]], schema(int_schema('number'))), ]; yield 'one entry left different - different entry' => [ - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number')), row(['number' => 2])), - rows(schema(int_schema('number')), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 2]], schema(int_schema('number'))), + array_to_rows([['number' => 1]], schema(int_schema('number'))), ]; } public static function unique_rows_provider(): Generator { yield 'simple identical rows' => [ - rows(schema(int_schema('number')), row(['number' => 1])), - rows(schema(int_schema('number')), row(['number' => 1]), row(['number' => 1])), + array_to_rows([['number' => 1]], schema(int_schema('number'))), + array_to_rows([['number' => 1], ['number' => 1]], schema(int_schema('number'))), new NativeComparator(), ]; } @@ -150,13 +151,15 @@ public function test_add_reports_the_violating_row_at_its_position_in_the_batch( $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "number" (row 1): could not convert \'x\' (string) to integer'); - rows(schema(int_schema('number')), row(['number' => 1]))->add(row(['number' => 'x'])); + array_to_rows([['number' => 1]], schema(int_schema('number')))->add(array_to_row([ + 'number' => 'x', + ], schema(str_schema('number')))); } public function test_adding_multiple_rows(): void { - $one = row(['number' => 1, 'name' => 'one']); - $two = row(['number' => 2, 'name' => 'two']); + $one = array_to_row(['number' => 1, 'name' => 'one'], schema(int_schema('number'), str_schema('name'))); + $two = array_to_row(['number' => 2, 'name' => 'two'], schema(int_schema('number'), str_schema('name'))); $schema = schema(int_schema('number'), str_schema('name')); static::assertEquals(rows($schema, $one, $two), rows($schema)->add($one, $two)); @@ -166,7 +169,7 @@ public function test_match_to_adopts_a_wider_schema_and_pads_the_new_nullable_co { static::assertSame( [['id' => 1, 'name' => null]], - rows(schema(int_schema('id')), row(['id' => 1])) + array_to_rows([['id' => 1]], schema(int_schema('id'))) ->matchTo(schema(int_schema('id'), str_schema('name', true))) ->toArray(), ); @@ -177,24 +180,23 @@ public function test_match_to_reports_the_violating_row_at_its_position_in_the_b $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "id" (row 0): could not convert 1 (integer) to string'); - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))->matchTo(schema(str_schema('id'))); + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))->matchTo(schema(str_schema('id'))); } public function test_project_drops_the_columns_the_schema_does_not_declare(): void { static::assertSame( [['id' => 1], ['id' => 2]], - rows( + array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => 'b']), ) ->project(schema(int_schema('id'))) ->toArray(), ); static::assertSame( ['name', 'id'], - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])) + array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))) ->project(schema(str_schema('name'), int_schema('id'))) ->first() ->names(), @@ -207,7 +209,7 @@ public function test_project_rejects_a_schema_that_widens_the_batch(): void $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "name" (row 0) declared by the schema is missing from the row'); - rows(schema(int_schema('id')), row(['id' => 1]))->project(schema(int_schema('id'), str_schema('name'))); + array_to_rows([['id' => 1]], schema(int_schema('id')))->project(schema(int_schema('id'), str_schema('name'))); } public function test_project_rejects_a_schema_that_retypes_a_column(): void @@ -215,16 +217,17 @@ public function test_project_rejects_a_schema_that_retypes_a_column(): void $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "id" (row 0): could not convert 1 (integer) to string'); - rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a']))->project(schema(str_schema( - 'id', - ))); + array_to_rows( + [['id' => 1, 'name' => 'a']], + schema(int_schema('id'), str_schema('name')), + )->project(schema(str_schema('id'))); } public function test_construct_reorders_row_storage_into_schema_order(): void { static::assertSame( ['c', 'a', 'b'], - rows(schema(int_schema('c'), int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 2, 'c' => 3])) + array_to_rows([['a' => 1, 'b' => 2, 'c' => 3]], schema(int_schema('c'), int_schema('a'), int_schema('b'))) ->first() ->names(), ); @@ -235,7 +238,7 @@ public function test_construct_rejects_a_row_that_contradicts_the_schema(): void $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "number" (row 0): could not convert \'x\' (string) to integer'); - rows(schema(int_schema('number')), row(['number' => 'x'])); + array_to_rows([['number' => 'x']], schema(int_schema('number'))); } public function test_the_epic_repro_is_unconstructible(): void @@ -245,12 +248,16 @@ public function test_the_epic_repro_is_unconstructible(): void 'Rows do not match their schema: column "code" (row 1): could not convert 1000 (integer) to string', ); - rows(schema(str_schema('code')), row(['code' => 'AB-01']), row(['code' => 1000])); + rows( + schema(str_schema('code')), + array_to_row(['code' => 'AB-01'], schema(str_schema('code'))), + array_to_row(['code' => 1000], schema(int_schema('code'))), + ); } public function test_array_access_exists(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); static::assertTrue(isset($rows[0])); static::assertFalse(isset($rows[3])); @@ -258,7 +265,7 @@ public function test_array_access_exists(): void public function test_array_access_get(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); static::assertSame(1, $rows[0]->get('id')); static::assertSame(2, $rows[1]->get('id')); @@ -270,29 +277,28 @@ public function test_array_access_set(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('In order to add new rows use Rows::add(Row $row) : self'); $rows = rows(schema()); - $rows[0] = row(['id' => 1]); + $rows[0] = array_to_row(['id' => 1], schema(int_schema('id'))); } public function test_array_access_unset(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessage('In order to remove rows use Rows::remove(int $offset) : self'); - $rows = rows(schema(int_schema('id')), row(['id' => 1])); + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); unset($rows[0]); } public function test_chunks_with_less(): void { - $rows = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - row(['id' => 6]), - row(['id' => 7]), - ); + $rows = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ['id' => 6], + ['id' => 7], + ], schema(int_schema('id'))); $chunk = iterator_to_array($rows->chunks(10)); @@ -302,19 +308,18 @@ public function test_chunks_with_less(): void public function test_chunks_with_more_than_expected_in_chunk_rows(): void { - $rows = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - row(['id' => 6]), - row(['id' => 7]), - row(['id' => 8]), - row(['id' => 9]), - row(['id' => 10]), - ); + $rows = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ['id' => 6], + ['id' => 7], + ['id' => 8], + ['id' => 9], + ['id' => 10], + ], schema(int_schema('id'))); $chunk = iterator_to_array($rows->chunks(5)); @@ -325,7 +330,7 @@ public function test_chunks_with_more_than_expected_in_chunk_rows(): void public function test_drop(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->drop(1); @@ -336,7 +341,7 @@ public function test_drop(): void public function test_drop_all(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->drop(3); @@ -345,7 +350,7 @@ public function test_drop_all(): void public function test_drop_more_than_exists(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->drop(4); @@ -354,7 +359,7 @@ public function test_drop_more_than_exists(): void public function test_drop_right(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->dropRight(1); @@ -365,7 +370,7 @@ public function test_drop_right(): void public function test_drop_right_all(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->dropRight(3); @@ -374,7 +379,7 @@ public function test_drop_right_all(): void public function test_drop_right_more_than_available(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->dropRight(5); @@ -383,7 +388,7 @@ public function test_drop_right_more_than_available(): void public function test_drop_right_more_than_exists(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->dropRight(4); @@ -393,7 +398,7 @@ public function test_drop_right_more_than_exists(): void public function test_empty_rows(): void { static::assertTrue(rows(schema())->isEmpty()); - static::assertFalse(rows(schema(int_schema('id')), row(['id' => 1]))->isEmpty()); + static::assertFalse(array_to_rows([['id' => 1]], schema(int_schema('id')))->isEmpty()); } public function test_first_on_empty_rows(): void @@ -405,22 +410,26 @@ public function test_first_on_empty_rows(): void public function test_hash(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'bool' => false], + ['id' => 2, 'bool' => false], + ['id' => 3, 'bool' => false], + ['id' => 4, 'bool' => false], + ], schema(int_schema('id'), bool_schema('bool')), - row(['id' => 1, 'bool' => false]), - row(['id' => 2, 'bool' => false]), - row(['id' => 3, 'bool' => false]), - row(['id' => 4, 'bool' => false]), ); static::assertSame( $rows->hash(), - rows( + array_to_rows( + [ + ['bool' => false, 'id' => 1], + ['bool' => false, 'id' => 2], + ['bool' => false, 'id' => 3], + ['bool' => false, 'id' => 4], + ], schema(bool_schema('bool'), int_schema('id')), - row(['bool' => false, 'id' => 1]), - row(['bool' => false, 'id' => 2]), - row(['bool' => false, 'id' => 3]), - row(['bool' => false, 'id' => 4]), )->hash(), ); } @@ -432,58 +441,62 @@ public function test_hash_empty_rows(): void public function test_hash_rows_with_different_columns(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'bool' => false], + ['id' => 3, 'bool' => false], + ['id' => 2, 'bool' => false], + ['id' => 4, 'bool' => false], + ], schema(int_schema('id'), bool_schema('bool')), - row(['id' => 1, 'bool' => false]), - row(['id' => 3, 'bool' => false]), - row(['id' => 2, 'bool' => false]), - row(['id' => 4, 'bool' => false]), ); static::assertNotSame( $rows->hash(), - rows( - schema(bool_schema('bool')), - row(['bool' => false]), - row(['bool' => false]), - row(['bool' => false]), - row(['bool' => false]), - )->hash(), + array_to_rows([ + ['bool' => false], + ['bool' => false], + ['bool' => false], + ['bool' => false], + ], schema(bool_schema('bool')))->hash(), ); } public function test_hash_rows_with_different_order(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'bool' => false], + ['id' => 3, 'bool' => false], + ['id' => 2, 'bool' => false], + ['id' => 4, 'bool' => false], + ], schema(int_schema('id'), bool_schema('bool')), - row(['id' => 1, 'bool' => false]), - row(['id' => 3, 'bool' => false]), - row(['id' => 2, 'bool' => false]), - row(['id' => 4, 'bool' => false]), ); static::assertNotSame( $rows->hash(), - rows( + array_to_rows( + [ + ['bool' => false, 'id' => 1], + ['bool' => false, 'id' => 2], + ['bool' => false, 'id' => 3], + ['bool' => false, 'id' => 4], + ], schema(bool_schema('bool'), int_schema('id')), - row(['bool' => false, 'id' => 1]), - row(['bool' => false, 'id' => 2]), - row(['bool' => false, 'id' => 3]), - row(['bool' => false, 'id' => 4]), )->hash(), ); } public function test_head(): void { - $rows = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - ); + $rows = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))); $head = $rows->head(3); @@ -502,7 +515,7 @@ public function test_head_on_empty_rows(): void public function test_head_with_count_larger_than_available(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $head = $rows->head(10); @@ -517,14 +530,14 @@ public function test_head_with_negative_count(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Count must be greater than or equal to 0'); - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows->head(-1); } public function test_head_with_zero_count(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $head = $rows->head(0); @@ -533,7 +546,7 @@ public function test_head_with_zero_count(): void public function test_last(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $lastRow = $rows->last(); @@ -550,7 +563,7 @@ public function test_last_on_empty_rows(): void public function test_last_on_single_row(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 42])); + $rows = array_to_rows([['id' => 42]], schema(int_schema('id'))); $lastRow = $rows->last(); @@ -560,7 +573,7 @@ public function test_last_on_single_row(): void public function test_merge_accepts_an_empty_side_with_any_schema(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1])); + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); // an empty batch has nothing to disagree about, so it short-circuits before the schema check static::assertEquals($rows, $rows->merge(rows(schema(str_schema('unrelated'))))); @@ -574,32 +587,31 @@ public function test_merge_throws_when_schemas_disagree(): void 'Cannot merge Rows with different schemas: [id: integer] and [id: integer, name: string]', ); - rows(schema(int_schema('id')), row(['id' => 1]))->merge(rows( + array_to_rows([['id' => 1]], schema(int_schema('id')))->merge(array_to_rows( + [['id' => 2, 'name' => 'x']], schema(int_schema('id'), str_schema('name')), - row(['id' => 2, 'name' => 'x']), )); } public function test_merges_collection_together(): void { - $rowsOne = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); - $rowsTwo = rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 4]), row(['id' => 5])); + $rowsOne = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + $rowsTwo = array_to_rows([['id' => 3], ['id' => 4], ['id' => 5]], schema(int_schema('id'))); - $rowsThree = rows(schema(int_schema('id')), row(['id' => 6]), row(['id' => 7])); + $rowsThree = array_to_rows([['id' => 6], ['id' => 7]], schema(int_schema('id'))); $merged = $rowsOne->merge($rowsTwo)->merge($rowsThree); static::assertEquals( - rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - row(['id' => 6]), - row(['id' => 7]), - ), + array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ['id' => 6], + ['id' => 7], + ], schema(int_schema('id'))), $merged, ); } @@ -621,7 +633,7 @@ public function test_offset_get_on_empty_rows(): void public function test_remove(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->remove(1); @@ -641,9 +653,9 @@ public function test_returns_first_row(): void { $rows = rows( schema(int_schema('number'), str_schema('name')), - $first = row(['number' => 3, 'name' => 'three']), - row(['number' => 1, 'name' => 'one']), - row(['number' => 2, 'name' => 'two']), + $first = array_to_row(['number' => 3, 'name' => 'three'], schema(int_schema('number'), str_schema('name'))), + array_to_row(['number' => 1, 'name' => 'one'], schema(int_schema('number'), str_schema('name'))), + array_to_row(['number' => 2, 'name' => 'two'], schema(int_schema('number'), str_schema('name'))), ); static::assertEquals($first, $rows->first()); @@ -651,7 +663,7 @@ public function test_returns_first_row(): void public function test_reverse(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->reverse(); @@ -676,25 +688,27 @@ public function test_rows_diff_right(Rows $expected, Rows $left, Rows $right): v public function test_rows_diff_right_carries_the_right_sides_schema(): void { // the surviving rows come from the right side, so the left side's schema cannot describe them - $left = rows(schema(int_schema('number')), row(['number' => 1])); - $right = rows(schema(int_schema('number'), str_schema('name')), row(['number' => 2, 'name' => 'two'])); + $left = array_to_rows([['number' => 1]], schema(int_schema('number'))); + $right = array_to_rows([['number' => 2, 'name' => 'two']], schema(int_schema('number'), str_schema('name'))); static::assertTrue($left->diffRight($right)->schema()->isSame($right->schema())); } public function test_rows_schema(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'name' => 'foo'], + ['id' => 1, 'name' => null, 'list' => [1, 2]], + ['id' => 1, 'name' => 'bar', 'tags' => ['a', 'b']], + ['id' => 1, 'name' => 'baz'], + ], schema( int_schema('id'), str_schema('name', nullable: true), list_schema('list', type_list(type_integer()), nullable: true), list_schema('tags', type_list(type_string()), nullable: true), ), - row(['id' => 1, 'name' => 'foo']), - row(['id' => 1, 'name' => null, 'list' => [1, 2]]), - row(['id' => 1, 'name' => 'bar', 'tags' => ['a', 'b']]), - row(['id' => 1, 'name' => 'baz']), ); static::assertEquals( @@ -717,14 +731,14 @@ public function test_rows_reject_a_row_whose_list_contradicts_the_declared_eleme rows( schema(list_schema('list', type_list(type_string()))), - row(['list' => ['one', 'two']]), - row(['list' => [1, 2]]), + array_to_row(['list' => ['one', 'two']], schema(list_schema('list', type_list(type_string())))), + array_to_row(['list' => [1, 2]], schema(list_schema('list', type_list(type_integer())))), ); } public function test_rows_serialization(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $serialized = serialize($rows); @@ -749,14 +763,16 @@ public function test_sort_rows_by_not_existing_column(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Column "c" does not exist'); - $rows = rows( + $rows = array_to_rows( + [ + ['a' => 3, 'b' => 2], + ['a' => 1, 'b' => 5], + ['a' => 1, 'b' => 4], + ['a' => 2, 'b' => 7], + ['a' => 3, 'b' => 10], + ['a' => 2, 'b' => 4], + ], schema(int_schema('a'), int_schema('b')), - row(['a' => 3, 'b' => 2]), - row(['a' => 1, 'b' => 5]), - row(['a' => 1, 'b' => 4]), - row(['a' => 2, 'b' => 7]), - row(['a' => 3, 'b' => 10]), - row(['a' => 2, 'b' => 4]), ); $rows->sortBy(ref('c'), ref('b')->desc()); @@ -764,14 +780,16 @@ public function test_sort_rows_by_not_existing_column(): void public function test_sort_rows_by_two_columns(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['a' => 3, 'b' => 2], + ['a' => 1, 'b' => 5], + ['a' => 1, 'b' => 4], + ['a' => 2, 'b' => 7], + ['a' => 3, 'b' => 10], + ['a' => 2, 'b' => 4], + ], schema(int_schema('a'), int_schema('b')), - row(['a' => 3, 'b' => 2]), - row(['a' => 1, 'b' => 5]), - row(['a' => 1, 'b' => 4]), - row(['a' => 2, 'b' => 7]), - row(['a' => 3, 'b' => 10]), - row(['a' => 2, 'b' => 4]), ); $ascending = $rows->sortBy(ref('a'), ref('b')->desc()); @@ -805,11 +823,11 @@ public function test_sort_rows_without_changing_original_collection(): void { $rows = rows( schema(int_schema('number'), str_schema('name')), - $three = row(['number' => 3, 'name' => 'three']), - $one = row(['number' => 1, 'name' => 'one']), - $five = row(['number' => 5, 'name' => 'five']), - $two = row(['number' => 2, 'name' => 'two']), - $four = row(['number' => 4, 'name' => 'four']), + $three = array_to_row(['number' => 3, 'name' => 'three'], schema(int_schema('number'), str_schema('name'))), + $one = array_to_row(['number' => 1, 'name' => 'one'], schema(int_schema('number'), str_schema('name'))), + $five = array_to_row(['number' => 5, 'name' => 'five'], schema(int_schema('number'), str_schema('name'))), + $two = array_to_row(['number' => 2, 'name' => 'two'], schema(int_schema('number'), str_schema('name'))), + $four = array_to_row(['number' => 4, 'name' => 'four'], schema(int_schema('number'), str_schema('name'))), ); $ascending = $rows->sortAscending(ref('number')); @@ -829,14 +847,13 @@ public function test_sort_rows_without_changing_original_collection(): void public function test_tail(): void { - $rows = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - ); + $rows = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))); $tail = $rows->tail(3); @@ -848,14 +865,13 @@ public function test_tail(): void public function test_tail_maintains_correct_order(): void { - $rows = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - ); + $rows = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))); $tail = $rows->tail(2); @@ -873,7 +889,7 @@ public function test_tail_on_empty_rows(): void public function test_tail_with_count_larger_than_available(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $tail = $rows->tail(10); @@ -888,14 +904,14 @@ public function test_tail_with_negative_count(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Count must be greater than or equal to 0'); - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows->tail(-1); } public function test_tail_with_zero_count(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $tail = $rows->tail(0); @@ -904,7 +920,7 @@ public function test_tail_with_zero_count(): void public function test_take(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->take(1); @@ -914,7 +930,7 @@ public function test_take(): void public function test_take_all(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->take(3); @@ -926,7 +942,7 @@ public function test_take_all(): void public function test_take_more_than_exists(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->take(4); @@ -938,7 +954,7 @@ public function test_take_more_than_exists(): void public function test_take_right(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->takeRight(1); @@ -948,7 +964,7 @@ public function test_take_right(): void public function test_take_right_all(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->takeRight(3); @@ -960,7 +976,7 @@ public function test_take_right_all(): void public function test_take_right_more_than_exists(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $rows = $rows->takeRight(4); @@ -972,10 +988,12 @@ public function test_take_right_more_than_exists(): void public function test_transforms_rows_to_array(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1234, 'deleted' => false, 'phase' => null], + ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], + ], schema(int_schema('id'), bool_schema('deleted'), string_schema('phase', nullable: true)), - row(['id' => 1234, 'deleted' => false, 'phase' => null]), - row(['id' => 4321, 'deleted' => true, 'phase' => 'launch']), ); static::assertEquals( @@ -989,10 +1007,12 @@ public function test_transforms_rows_to_array(): void public function test_transforms_rows_to_array_without_keys(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1234, 'deleted' => false, 'phase' => null], + ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], + ], schema(int_schema('id'), bool_schema('deleted'), string_schema('phase', nullable: true)), - row(['id' => 1234, 'deleted' => false, 'phase' => null]), - row(['id' => 4321, 'deleted' => true, 'phase' => 'launch']), ); static::assertEquals( @@ -1006,20 +1026,20 @@ public function test_transforms_rows_to_array_without_keys(): void public function test_structure_field_order_is_a_schema_difference_not_a_value_difference(): void { - $left = rows( - schema(structure_schema('s', type_structure([ - 'a' => type_integer(), - 'b' => type_string(), - ]))), - row(['s' => ['a' => 1, 'b' => 'x']]), - ); - $right = rows( - schema(structure_schema('s', type_structure([ - 'b' => type_string(), - 'a' => type_integer(), - ]))), - row(['s' => ['b' => 'x', 'a' => 1]]), - ); + $left = array_to_rows([['s' => [ + 'a' => 1, + 'b' => 'x', + ]]], schema(structure_schema('s', type_structure([ + 'a' => type_integer(), + 'b' => type_string(), + ])))); + $right = array_to_rows([['s' => [ + 'b' => 'x', + 'a' => 1, + ]]], schema(structure_schema('s', type_structure([ + 'b' => type_string(), + 'a' => type_integer(), + ])))); // Values are compared by content (ArrayComparison), so the two rows are equal ... static::assertCount(0, $left->diffLeft($right)); @@ -1038,10 +1058,9 @@ public function test_rows_hop_a_foreign_zone_at_ingest(): void static::assertSame( '2026-01-01 22:04:05 UTC', type_datetime() - ->assert(rows( - schema(datetime_schema('at')), - row(['at' => new DateTimeImmutable('2026-01-02 03:04:05+05:00')]), - )->first()->get('at')) + ->assert(array_to_rows([[ + 'at' => new DateTimeImmutable('2026-01-02 03:04:05+05:00'), + ]], schema(datetime_schema('at')))->first()->get('at')) ->format('Y-m-d H:i:s e'), ); } @@ -1051,10 +1070,12 @@ public function test_rows_hop_nested_datetimes(): void static::assertSame( '2026-01-02 04:04:05 Europe/Warsaw', type_list(type_datetime()) - ->assert(rows( - schema(list_schema('l', type_list(type_datetime('Europe/Warsaw')))), - row(['l' => [new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC'))]]), - )->first()->get('l'))[0]->format('Y-m-d H:i:s e'), + ->assert(array_to_rows([['l' => [new DateTimeImmutable( + '2026-01-02 03:04:05', + new DateTimeZone('UTC'), + )]]], schema(list_schema('l', type_list(type_datetime('Europe/Warsaw')))))->first()->get( + 'l', + ))[0]->format('Y-m-d H:i:s e'), ); } @@ -1063,10 +1084,12 @@ public function test_rows_hop_nested_optional_datetimes(): void static::assertSame( '2026-01-02 04:04:05 Europe/Warsaw', type_list(type_optional(type_datetime())) - ->assert(rows( - schema(list_schema('l', type_list(type_optional(type_datetime('Europe/Warsaw'))))), - row(['l' => [new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), null]]), - )->first()->get('l'))[0]?->format('Y-m-d H:i:s e'), + ->assert(array_to_rows([['l' => [ + new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), + null, + ]]], schema(list_schema('l', type_list(type_optional(type_datetime('Europe/Warsaw'))))))->first()->get( + 'l', + ))[0]?->format('Y-m-d H:i:s e'), ); } @@ -1077,47 +1100,47 @@ public static function from_rows_refusals(): Generator { yield 'other column, same count' => [ schema(int_schema('a'), int_schema('b')), - row(['a' => 1, 'z' => 2]), + array_to_row(['a' => 1, 'z' => 2], schema(int_schema('a'), int_schema('z'))), 'Rows do not match their schema: column "b" (row 0) declared by the schema is missing from the row', ]; yield 'null under not-null' => [ schema(str_schema('a')), - row(['a' => null]), + array_to_row(['a' => null], schema(int_schema('a', nullable: true))), 'column "a" (row 0): could not convert null to string, column is not nullable', ]; yield 'missing not-null column' => [ schema(int_schema('a'), int_schema('b')), - row(['a' => 1]), + array_to_row(['a' => 1], schema(int_schema('a'))), 'Rows do not match their schema: column "b" (row 0) declared by the schema is missing from the row', ]; yield 'unknown column' => [ schema(int_schema('a')), - row(['a' => 1, 'b' => 2]), + array_to_row(['a' => 1, 'b' => 2], schema(int_schema('a'), int_schema('b'))), 'Rows do not match their schema: column "b" (row 0) is not declared by the schema', ]; yield 'any column against schema()' => [ schema(), - row(['a' => 1]), + array_to_row(['a' => 1], schema(int_schema('a'))), 'Rows do not match their schema: column "a" (row 0) is not declared by the schema', ]; yield 'same names, third value wrong' => [ schema(int_schema('a'), str_schema('b'), str_schema('c')), - row(['a' => 1, 'b' => 'x', 'c' => 3]), + array_to_row(['a' => 1, 'b' => 'x', 'c' => 3], schema(int_schema('a'), str_schema('b'), int_schema('c'))), 'Rows do not match their schema: column "c" (row 0): could not convert 3 (integer) to string', ]; yield 'reordered, wrong type' => [ schema(int_schema('a'), int_schema('b')), - row(['b' => 'x', 'a' => 1]), + array_to_row(['b' => 'x', 'a' => 1], schema(str_schema('b'), int_schema('a'))), 'Rows do not match their schema: column "b" (row 0): could not convert \'x\' (string) to integer', ]; yield 'null under not-null datetime' => [ schema(datetime_schema('at')), - row(['at' => null]), + array_to_row(['at' => null], schema(str_schema('at', nullable: true))), 'column "at" (row 0): could not convert null to datetime, column is not nullable', ]; yield 'string in a datetime column' => [ schema(datetime_schema('at')), - row(['at' => '2026-01-02 03:04:05']), + array_to_row(['at' => '2026-01-02 03:04:05'], schema(str_schema('at'))), 'column "at" (row 0): could not convert \'2026-01-02 03:04:05\' (string) to datetime', ]; } @@ -1136,13 +1159,13 @@ public function test_from_rows_refuses_null_under_not_null_in_row_1(): void $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "id" (row 1)'); - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => null])); + array_to_rows([['id' => 1], ['id' => null]], schema(int_schema('id'))); } public function test_from_rows_gathers_views_of_one_batch_whose_schema_is_same(): void { $schema = schema(int_schema('id')); - $batch = rows($schema, row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $batch = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], $schema); static::assertSame([['id' => 3], ['id' => 1]], rows($schema, $batch->row(2), $batch->row(0))->toArray()); } @@ -1151,7 +1174,7 @@ public function test_from_rows_copies_views_of_two_batches_with_the_same_schema( { $schema = schema(int_schema('id')); $constant = Rows::fromColumns($schema, ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], 2); - $scalar = rows($schema, row(['id' => 1]), row(['id' => 2])); + $scalar = array_to_rows([['id' => 1], ['id' => 2]], $schema); $copied = rows($schema, $scalar->row(1), $constant->row(0), $scalar->row(0)); @@ -1164,9 +1187,9 @@ public function test_from_rows_reorders_and_hops_into_the_column_zone(): void static::assertSame( '2026-01-02 04:04:05 Europe/Warsaw', type_datetime() - ->assert(rows( + ->assert(array_to_rows( + [['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), 'id' => 1]], schema(int_schema('id'), datetime_schema('at', zone: 'Europe/Warsaw')), - row(['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), 'id' => 1]), )->first()->get('at')) ->format('Y-m-d H:i:s e'), ); @@ -1216,7 +1239,7 @@ public function test_of_refuses_a_column_of_another_count(): void public function test_project_shares_kept_columns(): void { - $rows = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])); + $rows = array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))); static::assertSame($rows->column('id'), $rows->project(schema(int_schema('id')))->column('id')); } @@ -1225,7 +1248,7 @@ public function test_concat_of_a_constant_and_a_scalar_column_yields_php_columns { $schema = schema(int_schema('id')); $constant = Rows::fromColumns($schema, ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], 2); - $concatenated = $constant->concat(rows($schema, row(['id' => 1]))); + $concatenated = $constant->concat(array_to_rows([['id' => 1]], $schema)); static::assertSame([['id' => 7], ['id' => 7], ['id' => 1]], $concatenated->toArray()); static::assertInstanceOf(ScalarColumn::class, $concatenated->column('id')); @@ -1236,7 +1259,7 @@ public function test_concat_refuses_a_zero_row_input_with_another_schema(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cannot merge Rows with different schemas'); - rows(schema(int_schema('id')), row(['id' => 1]))->concat(rows(schema(str_schema('id')))); + array_to_rows([['id' => 1]], schema(int_schema('id')))->concat(rows(schema(str_schema('id')))); } public function test_concat_of_empty_inputs_is_an_empty_batch(): void @@ -1273,7 +1296,7 @@ public function test_with_columns_refuses_a_column_of_another_count(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Column "n" holds 1 rows, the batch 2'); - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))->withColumns( + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))->withColumns( schema(int_schema('id'), int_schema('n')), ['n' => (new PhpBackend())->constant(int_schema('n'), 1, 1)], ); @@ -1281,7 +1304,7 @@ public function test_with_columns_refuses_a_column_of_another_count(): void public function test_with_schema_renames_and_retypes_positionally(): void { - $renamed = rows(schema(int_schema('id', nullable: true)), row(['id' => 1]))->withSchema(schema(int_schema( + $renamed = array_to_rows([['id' => 1]], schema(int_schema('id', nullable: true)))->withSchema(schema(int_schema( 'key', ))); @@ -1293,7 +1316,7 @@ public function test_with_schema_refuses_another_definition_count(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Rows::withSchema() expects 1 definitions, got 2'); - rows(schema(int_schema('id')), row(['id' => 1]))->withSchema(schema(int_schema('a'), int_schema('b'))); + array_to_rows([['id' => 1]], schema(int_schema('id')))->withSchema(schema(int_schema('a'), int_schema('b'))); } public function test_with_schema_refuses_nulls_under_not_null(): void @@ -1301,7 +1324,9 @@ public function test_with_schema_refuses_nulls_under_not_null(): void $this->expectException(ColumnMismatchException::class); $this->expectExceptionMessage('column "key": could not convert null to integer, column is not nullable'); - rows(schema(int_schema('id', nullable: true)), row(['id' => null]))->withSchema(schema(int_schema('key'))); + array_to_rows([['id' => null]], schema(int_schema('id', nullable: true)))->withSchema(schema(int_schema( + 'key', + ))); } public function test_with_schema_refuses_another_column_kind(): void @@ -1311,7 +1336,7 @@ public function test_with_schema_refuses_another_column_kind(): void 'column "id": cannot retype the column to string, integer and string are different column kinds', ); - rows(schema(int_schema('id')), row(['id' => 1]))->withSchema(schema(str_schema('id'))); + array_to_rows([['id' => 1]], schema(int_schema('id')))->withSchema(schema(str_schema('id'))); } /** @@ -1319,12 +1344,12 @@ public function test_with_schema_refuses_another_column_kind(): void */ public static function slices_out_of_range(): Generator { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); yield 'negative offset' => [$rows, -1, 1]; yield 'negative length' => [$rows, 0, -1]; yield 'past the end' => [$rows, 2, 2]; - yield 'past the end of a batch without columns' => [rows(schema(), row([]), row([]), row([])), 1, 3]; + yield 'past the end of a batch without columns' => [array_to_rows([[], [], []], schema()), 1, 3]; } #[DataProvider('slices_out_of_range')] @@ -1346,11 +1371,11 @@ public function test_slice_refuses_out_of_range(Rows $rows, int $offset, int $le */ public static function gathers_out_of_range(): Generator { - $rows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); yield 'negative' => [$rows, -1]; yield 'the count' => [$rows, 3]; - yield 'the count of a batch without columns' => [rows(schema(), row([]), row([]), row([])), 3]; + yield 'the count of a batch without columns' => [array_to_rows([[], [], []], schema()), 3]; } #[DataProvider('gathers_out_of_range')] @@ -1368,12 +1393,12 @@ public function test_gather_refuses_out_of_range(Rows $rows, int $index): void public function test_gather_nothing_is_an_empty_batch(): void { - static::assertSame(0, rows(schema(int_schema('id')), row(['id' => 1]))->gather([])->count()); + static::assertSame(0, array_to_rows([['id' => 1]], schema(int_schema('id')))->gather([])->count()); } public function test_a_batch_without_columns_keeps_its_rows(): void { - $rows = rows(schema(), row([]), row([]), row([])); + $rows = array_to_rows([[], [], []], schema()); static::assertSame(3, $rows->count()); static::assertSame(2, $rows->slice(1, 2)->count()); @@ -1382,7 +1407,7 @@ public function test_a_batch_without_columns_keeps_its_rows(): void public function test_dropping_nothing_keeps_the_batch(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1])); + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); static::assertSame($rows, $rows->drop(0)); static::assertSame($rows, $rows->dropRight(0)); @@ -1401,11 +1426,14 @@ public function test_match_to_rebuilds_a_column_its_type_cannot_restamp(): void { // the child of a nullable structure carries null under the null parent row, so narrowing ?int to int cannot be a // restamp - the matching values are rebuilt under the new type instead - $matched = rows( - schema(structure_schema('s', type_structure(['a' => type_optional(type_integer())]), nullable: true)), - row(['s' => ['a' => 1]]), - row(['s' => null]), - )->matchTo(schema(structure_schema('s', type_structure(['a' => type_integer()]), nullable: true))); + $matched = array_to_rows([ + ['s' => ['a' => 1]], + ['s' => null], + ], schema(structure_schema('s', type_structure(['a' => type_optional(type_integer())]), nullable: true)))->matchTo(schema(structure_schema( + 's', + type_structure(['a' => type_integer()]), + nullable: true, + ))); static::assertSame([['s' => ['a' => 1]], ['s' => null]], $matched->toArray()); static::assertSame('structure{a: integer}', $matched->column('s')->type()->toString()); @@ -1426,9 +1454,9 @@ public function test_match_to_refuses_a_midnight_outside_utc_in_a_date_column(): 'column "at" (row 0): could not convert 2026-01-01T00:00:00.000000+01:00 (datetime) to date', ); - rows( - schema(datetime_schema('at', zone: 'Europe/Warsaw')), - row(['at' => new DateTimeImmutable('2026-01-01 00:00:00', new DateTimeZone('Europe/Warsaw'))]), - )->matchTo(schema(date_schema('at'))); + array_to_rows([['at' => new DateTimeImmutable( + '2026-01-01 00:00:00', + new DateTimeZone('Europe/Warsaw'), + )]], schema(datetime_schema('at', zone: 'Europe/Warsaw')))->matchTo(schema(date_schema('at'))); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php index 5ac8878263..303b2e8c7d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php @@ -8,8 +8,8 @@ use Flow\ETL\Tests\FlowTestCase; use Generator; +use function Flow\ETL\DSL\array_to_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; @@ -18,8 +18,8 @@ final class BucketCursorTest extends FlowTestCase public function test_iterates_rows_across_batch_boundaries(): void { $batches = static function (): Generator { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); - yield rows(schema(int_schema('id')), row(['id' => 3])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); }; $cursor = new BucketCursor($batches()); @@ -47,9 +47,9 @@ public function test_skips_empty_batches(): void { $batches = static function (): Generator { yield rows(schema()); - yield rows(schema(int_schema('id')), row(['id' => 1])); + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); yield rows(schema()); - yield rows(schema(int_schema('id')), row(['id' => 2])); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); }; $cursor = new BucketCursor($batches()); @@ -67,8 +67,8 @@ public function test_skips_empty_batches(): void public function test_next_batch_is_not_decoded_until_the_current_one_is_exhausted(): void { $batches = static function (): Generator { - yield rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); - yield rows(schema(int_schema('id')), row(['id' => 3])); + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); }; $generator = $batches(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php index 6d16554b74..33a3d9953b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php @@ -14,11 +14,10 @@ use Flow\ETL\Tests\FlowTestCase; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -27,24 +26,21 @@ final class KWayMergeTest extends FlowTestCase public function test_merges_multiple_sorted_runs_ascending(): void { $buckets = new Buckets(new MemoryBuckets()); - $buckets->storage()->append('a', rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 4]), - row(['id' => 7]), - )); - $buckets->storage()->append('b', rows( - schema(int_schema('id')), - row(['id' => 2]), - row(['id' => 5]), - row(['id' => 8]), - )); - $buckets->storage()->append('c', rows( - schema(int_schema('id')), - row(['id' => 3]), - row(['id' => 6]), - row(['id' => 9]), - )); + $buckets->storage()->append('a', array_to_rows([ + ['id' => 1], + ['id' => 4], + ['id' => 7], + ], schema(int_schema('id')))); + $buckets->storage()->append('b', array_to_rows([ + ['id' => 2], + ['id' => 5], + ['id' => 8], + ], schema(int_schema('id')))); + $buckets->storage()->append('c', array_to_rows([ + ['id' => 3], + ['id' => 6], + ['id' => 9], + ], schema(int_schema('id')))); $merge = new KWayMerge(refs(ref('id')->asc())); @@ -61,8 +57,8 @@ public function test_merge_reads_each_run_through_its_own_storage(): void $spill = new Buckets(new MemoryBuckets()); $merged = new Buckets(new MemoryBuckets()); - $spill->storage()->append('sort-run-0', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 3]))); - $merged->storage()->append('sort-merge-0', rows(schema(int_schema('id')), row(['id' => 2]), row(['id' => 4]))); + $spill->storage()->append('sort-run-0', array_to_rows([['id' => 1], ['id' => 3]], schema(int_schema('id')))); + $merged->storage()->append('sort-merge-0', array_to_rows([['id' => 2], ['id' => 4]], schema(int_schema('id')))); // neither storage holds the other's id, so a routing miss reads 0 batches instead of throwing static::assertSame([], BucketsStorageContext::rows($spill->storage()->get('sort-merge-0'))); @@ -84,18 +80,16 @@ public function test_merge_reads_each_run_through_its_own_storage(): void public function test_merges_multiple_sorted_runs_descending(): void { $buckets = new Buckets(new MemoryBuckets()); - $buckets->storage()->append('a', rows( - schema(int_schema('id')), - row(['id' => 7]), - row(['id' => 4]), - row(['id' => 1]), - )); - $buckets->storage()->append('b', rows( - schema(int_schema('id')), - row(['id' => 8]), - row(['id' => 5]), - row(['id' => 2]), - )); + $buckets->storage()->append('a', array_to_rows([ + ['id' => 7], + ['id' => 4], + ['id' => 1], + ], schema(int_schema('id')))); + $buckets->storage()->append('b', array_to_rows([ + ['id' => 8], + ['id' => 5], + ['id' => 2], + ], schema(int_schema('id')))); $merge = new KWayMerge(refs(ref('id')->desc())); @@ -110,13 +104,12 @@ public function test_merges_multiple_sorted_runs_descending(): void public function test_merges_runs_of_uneven_length(): void { $buckets = new Buckets(new MemoryBuckets()); - $buckets->storage()->append('a', rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - )); - $buckets->storage()->append('b', rows(schema(int_schema('id')), row(['id' => 4]))); + $buckets->storage()->append('a', array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id')))); + $buckets->storage()->append('b', array_to_rows([['id' => 4]], schema(int_schema('id')))); $merge = new KWayMerge(refs(ref('id')->asc())); @@ -131,8 +124,8 @@ public function test_merges_runs_of_uneven_length(): void public function test_merges_non_numeric_values(): void { $buckets = new Buckets(new MemoryBuckets()); - $buckets->storage()->append('a', rows(schema(str_schema('id')), row(['id' => 'a']), row(['id' => 'c']))); - $buckets->storage()->append('b', rows(schema(str_schema('id')), row(['id' => 'b']), row(['id' => 'd']))); + $buckets->storage()->append('a', array_to_rows([['id' => 'a'], ['id' => 'c']], schema(str_schema('id')))); + $buckets->storage()->append('b', array_to_rows([['id' => 'b'], ['id' => 'd']], schema(str_schema('id')))); $merge = new KWayMerge(refs(ref('id')->asc())); @@ -147,11 +140,11 @@ public function test_merges_non_numeric_values(): void public function test_runs_under_different_schemas_are_conformed_to_the_first(): void { $buckets = new Buckets(new MemoryBuckets()); - $buckets->storage()->append('a', rows( + $buckets->storage()->append('a', array_to_rows( + [['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name', true)), - row(['id' => 1, 'name' => 'a']), )); - $buckets->storage()->append('b', rows(schema(int_schema('id')), row(['id' => 2]))); + $buckets->storage()->append('b', array_to_rows([['id' => 2]], schema(int_schema('id')))); $merge = new KWayMerge(refs(ref('id')->asc())); @@ -170,7 +163,7 @@ public function test_runs_under_different_schemas_are_conformed_to_the_first(): public function test_single_run_passthrough(): void { $buckets = new Buckets(new MemoryBuckets()); - $buckets->storage()->append('a', rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); + $buckets->storage()->append('a', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $merge = new KWayMerge(refs(ref('id')->asc())); @@ -192,13 +185,12 @@ public function test_empty_bucket_set_yields_nothing(): void public function test_merged_rows_are_yielded_in_batches_of_batch_size(): void { $buckets = new Buckets(new MemoryBuckets()); - $buckets->storage()->append('a', rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 3]), - row(['id' => 5]), - )); - $buckets->storage()->append('b', rows(schema(int_schema('id')), row(['id' => 2]), row(['id' => 4]))); + $buckets->storage()->append('a', array_to_rows([ + ['id' => 1], + ['id' => 3], + ['id' => 5], + ], schema(int_schema('id')))); + $buckets->storage()->append('b', array_to_rows([['id' => 2], ['id' => 4]], schema(int_schema('id')))); $merge = new KWayMerge(refs(ref('id')->asc()), batchSize: 2); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/RowsMinHeapTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/RowsMinHeapTest.php index f330d50a47..1f1f0d7b55 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/RowsMinHeapTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/RowsMinHeapTest.php @@ -9,8 +9,11 @@ use function array_map; use function count; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function range; final class RowsMinHeapTest extends FlowTestCase @@ -19,12 +22,12 @@ public function test_min_heap(): void { $minHeap = new RowsMinHeap(ref('id')->asc()); - $minHeap->push(row(['id' => 1]), 'cache_id'); - $minHeap->push(row(['id' => 2]), 'cache_id'); - $minHeap->push(row(['id' => 3]), 'cache_id'); - $minHeap->push(row(['id' => 4]), 'cache_id'); - $minHeap->push(row(['id' => 5]), 'cache_id'); - $minHeap->push(row(['id' => 6]), 'cache_id'); + $minHeap->push(array_to_row(['id' => 1], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 2], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 3], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 4], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 5], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 6], schema(int_schema('id'))), 'cache_id'); static::assertEquals( [ @@ -43,12 +46,12 @@ public function test_min_heap_desc(): void { $minHeap = new RowsMinHeap(ref('id')->desc()); - $minHeap->push(row(['id' => 1]), 'cache_id'); - $minHeap->push(row(['id' => 2]), 'cache_id'); - $minHeap->push(row(['id' => 3]), 'cache_id'); - $minHeap->push(row(['id' => 4]), 'cache_id'); - $minHeap->push(row(['id' => 5]), 'cache_id'); - $minHeap->push(row(['id' => 6]), 'cache_id'); + $minHeap->push(array_to_row(['id' => 1], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 2], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 3], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 4], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 5], schema(int_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 6], schema(int_schema('id'))), 'cache_id'); static::assertEquals( [ @@ -67,12 +70,12 @@ public function test_min_heap_on_non_numeric_values(): void { $minHeap = new RowsMinHeap(ref('id')->asc()); - $minHeap->push(row(['id' => 'a']), 'cache_id'); - $minHeap->push(row(['id' => 'b']), 'cache_id'); - $minHeap->push(row(['id' => 'c']), 'cache_id'); - $minHeap->push(row(['id' => 'd']), 'cache_id'); - $minHeap->push(row(['id' => 'e']), 'cache_id'); - $minHeap->push(row(['id' => 'f']), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'a'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'b'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'c'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'd'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'e'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'f'], schema(str_schema('id'))), 'cache_id'); static::assertEquals( [ @@ -91,12 +94,12 @@ public function test_min_heap_on_non_numeric_values_desc(): void { $minHeap = new RowsMinHeap(ref('id')->desc()); - $minHeap->push(row(['id' => 'a']), 'cache_id'); - $minHeap->push(row(['id' => 'b']), 'cache_id'); - $minHeap->push(row(['id' => 'c']), 'cache_id'); - $minHeap->push(row(['id' => 'd']), 'cache_id'); - $minHeap->push(row(['id' => 'e']), 'cache_id'); - $minHeap->push(row(['id' => 'f']), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'a'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'b'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'c'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'd'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'e'], schema(str_schema('id'))), 'cache_id'); + $minHeap->push(array_to_row(['id' => 'f'], schema(str_schema('id'))), 'cache_id'); static::assertEquals( [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/SortStepsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/SortStepsTest.php index 6a06ff227b..db9f2dd4dc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/SortStepsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/SortStepsTest.php @@ -8,7 +8,6 @@ use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\MemorySortProcessor; use Flow\ETL\Processor\MergeSortProcessor; -use Flow\ETL\Row; use Flow\ETL\Sort\SortSteps; use Flow\ETL\Tests\Double\RecordingBucketsStorage; use Flow\ETL\Tests\FlowTestCase; @@ -16,6 +15,7 @@ use function array_filter; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\external_sort; @@ -24,8 +24,6 @@ use function Flow\ETL\DSL\memory_sort; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function iterator_to_array; use function range; @@ -57,9 +55,9 @@ public function test_external_sort_resolves_both_phases_over_the_same_storage_by $context = flow_context(config()); $input = (static function (): Generator { - yield rows( + yield array_to_rows( + array_map(static fn(int $i): array => ['id' => $i], range(9, 0)), schema(int_schema('id')), - ...array_map(static fn(int $i): Row => row(['id' => $i]), range(9, 0)), ); })(); @@ -88,9 +86,9 @@ public function test_external_sort_routes_merged_runs_to_the_merge_storage_when_ $context = flow_context(config()); $input = (static function (): Generator { - yield rows( + yield array_to_rows( + array_map(static fn(int $i): array => ['id' => $i], range(9, 0)), schema(int_schema('id')), - ...array_map(static fn(int $i): Row => row(['id' => $i]), range(9, 0)), ); })(); 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 c56320d8a3..64925a9ba5 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 @@ -10,10 +10,9 @@ use Flow\ETL\Transformer\AddRowIndexTransformer; use PHPUnit\Framework\Attributes\TestWith; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; 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; final class AddRowIndexTransformerTest extends FlowTestCase @@ -23,10 +22,9 @@ public function test_an_index_column_colliding_with_an_existing_column_is_reject $this->expectException(SchemaDefinitionNotUniqueException::class); $this->expectExceptionMessage('Entry definitions must be unique, duplicated entries: [id]'); - (new AddRowIndexTransformer('id', StartFrom::ZERO))->transform( - rows(schema(int_schema('id')), row(['id' => 1])), - flow_context(), - ); + (new AddRowIndexTransformer('id', StartFrom::ZERO))->transform(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))), flow_context()); } public function test_bind_adds_an_int_index_column(): void @@ -45,11 +43,11 @@ public function test_index_keeps_incrementing_across_batches(): void static::assertSame( [['id' => 1, 'idx' => 0], ['id' => 2, 'idx' => 1]], - $transformer->transform(rows($schema, row(['id' => 1]), row(['id' => 2])), $context)->toArray(), + $transformer->transform(array_to_rows([['id' => 1], ['id' => 2]], $schema), $context)->toArray(), ); static::assertSame( [['id' => 3, 'idx' => 2]], - $transformer->transform(rows($schema, row(['id' => 3])), $context)->toArray(), + $transformer->transform(array_to_rows([['id' => 3]], $schema), $context)->toArray(), ); } @@ -59,14 +57,14 @@ public function test_a_fresh_instance_starts_counting_again(StartFrom $startFrom { $transformer = new AddRowIndexTransformer('idx', $startFrom); $schema = schema(int_schema('id')); - $transformer->transform(rows($schema, row(['id' => 1]), row(['id' => 2])), flow_context()); + $transformer->transform(array_to_rows([['id' => 1], ['id' => 2]], $schema), 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(), + $fresh->transform(array_to_rows([['id' => 1]], $schema), flow_context())->toArray(), ); } @@ -75,7 +73,7 @@ public function test_index_starting_from_one(): void static::assertSame( [['id' => 1, 'idx' => 1]], (new AddRowIndexTransformer('idx', StartFrom::ONE)) - ->transform(rows(schema(int_schema('id')), row(['id' => 1])), flow_context()) + ->transform(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context()) ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/CollectReferencesTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/CollectReferencesTransformerTest.php index 22735c8b82..597efd0498 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/CollectReferencesTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/CollectReferencesTransformerTest.php @@ -8,11 +8,10 @@ use Flow\ETL\Transformer\CollectReferencesTransformer; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -28,7 +27,7 @@ public function test_bind_returns_the_input_schema(): void public function test_collecting_references_from_the_batch_schema(): void { $references = refs(); - $batch = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'John'])); + $batch = array_to_rows([['id' => 1, 'name' => 'John']], schema(int_schema('id'), str_schema('name'))); static::assertSame($batch, (new CollectReferencesTransformer($references))->transform($batch, flow_context())); 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 c80bc24eeb..ae117d0a34 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 @@ -9,11 +9,10 @@ use Flow\ETL\Tests\Mother\PhysicalPlanMother; use Flow\ETL\Transformer\CrossJoinRowsTransformer; +use function Flow\ETL\DSL\array_to_rows; 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; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -24,7 +23,9 @@ public function test_bind_concatenates_the_left_and_the_right_schema(): void static::assertEquals( schema(int_schema('id'), str_schema('name')), (new CrossJoinRowsTransformer( - PhysicalPlanMother::reading(from_rows(rows(schema(str_schema('name')), row(['name' => 'Alice'])))), + PhysicalPlanMother::reading(from_rows(array_to_rows([[ + 'name' => 'Alice', + ]], schema(str_schema('name'))))), new Executor(), ))->bind(schema(int_schema('id')))->output, ); @@ -35,7 +36,9 @@ public function test_bind_prefixes_every_right_side_column(): void static::assertEquals( schema(int_schema('id'), str_schema('right_name')), (new CrossJoinRowsTransformer( - PhysicalPlanMother::reading(from_rows(rows(schema(str_schema('name')), row(['name' => 'Alice'])))), + PhysicalPlanMother::reading(from_rows(array_to_rows([[ + 'name' => 'Alice', + ]], schema(str_schema('name'))))), new Executor(), 'right_', ))->bind(schema(int_schema('id')))->output, @@ -45,18 +48,17 @@ public function test_bind_prefixes_every_right_side_column(): void 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']), - ))), + PhysicalPlanMother::reading(from_rows(array_to_rows([ + ['name' => 'Alice'], + ['name' => 'Bob'], + ], schema(str_schema('name'))))), 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(), + $transformer->transform(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context())->toArray(), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php index 33cdad3d5d..64aee63237 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php @@ -9,9 +9,8 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\DerivedColumns; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -61,7 +60,7 @@ public function test_rows_adds_the_derived_column_under_the_output_schema(): voi [['a' => 1, 'note' => 'x']], (new DerivedColumns()) ->rows( - rows(schema(int_schema('a')), row(['a' => 1])), + array_to_rows([['a' => 1]], schema(int_schema('a'))), $output, $output, 'note', @@ -79,7 +78,7 @@ public function test_rows_matches_a_batch_declared_under_another_schema(): void [['a' => 1, 'note' => 'x', 'extra' => null]], (new DerivedColumns()) ->rows( - rows(schema(int_schema('a')), row(['a' => 1])), + array_to_rows([['a' => 1]], schema(int_schema('a'))), $declared, $declared->add(str_schema('extra', nullable: true)), 'note', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DropDuplicatesTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DropDuplicatesTransformerTest.php index af47667367..779f3c10be 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DropDuplicatesTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DropDuplicatesTransformerTest.php @@ -8,11 +8,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\DropDuplicatesTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -37,21 +36,21 @@ public function test_dropping_duplicated_entries_from_rows(): void { $transformer = new DropDuplicatesTransformer('id'); - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'name' => 'name1'], + ['id' => 1, 'name' => 'name1'], + ['id' => 2, 'name' => 'name2'], + ['id' => 2, 'name' => 'name2'], + ['id' => 3, 'name' => 'name3'], + ], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 2, 'name' => 'name2']), - row(['id' => 2, 'name' => 'name2']), - row(['id' => 3, 'name' => 'name3']), ); static::assertEquals( - rows( + array_to_rows( + [['id' => 1, 'name' => 'name1'], ['id' => 2, 'name' => 'name2'], ['id' => 3, 'name' => 'name3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 2, 'name' => 'name2']), - row(['id' => 3, 'name' => 'name3']), ), $transformer->transform($rows, flow_context(config())), ); @@ -61,23 +60,27 @@ public function test_dropping_duplicates_when_not_all_rows_has_expected_entry(): { $transformer = new DropDuplicatesTransformer('id'); - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'name' => 'name1'], + ['id' => 1, 'name' => 'name1'], + ['id' => 2, 'name' => 'name2'], + ['id' => 2, 'name' => 'name2'], + ['name' => 'name3'], + ['id' => 4, 'name' => 'name4'], + ], schema(int_schema('id', nullable: true), str_schema('name')), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 2, 'name' => 'name2']), - row(['id' => 2, 'name' => 'name2']), - row(['name' => 'name3']), - row(['id' => 4, 'name' => 'name4']), ); static::assertEquals( - rows( + array_to_rows( + [ + ['id' => 1, 'name' => 'name1'], + ['id' => 2, 'name' => 'name2'], + ['name' => 'name3'], + ['id' => 4, 'name' => 'name4'], + ], schema(int_schema('id', nullable: true), str_schema('name')), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 2, 'name' => 'name2']), - row(['name' => 'name3']), - row(['id' => 4, 'name' => 'name4']), ), $transformer->transform($rows, flow_context(config())), ); @@ -87,21 +90,21 @@ public function test_dropping_duplications_based_on_two_entries(): void { $transformer = new DropDuplicatesTransformer('id', 'name'); - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'name' => 'name1'], + ['id' => 1, 'name' => 'name1'], + ['id' => 2, 'name' => 'name2'], + ['id' => 2, 'name' => 'name2'], + ['id' => 3, 'name' => 'name3'], + ], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 2, 'name' => 'name2']), - row(['id' => 2, 'name' => 'name2']), - row(['id' => 3, 'name' => 'name3']), ); static::assertEquals( - rows( + array_to_rows( + [['id' => 1, 'name' => 'name1'], ['id' => 2, 'name' => 'name2'], ['id' => 3, 'name' => 'name3']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'name1']), - row(['id' => 2, 'name' => 'name2']), - row(['id' => 3, 'name' => 'name3']), ), $transformer->transform($rows, flow_context(config())), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DropEntriesTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DropEntriesTransformerTest.php index 97fb86d64f..b55dfc5fa3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DropEntriesTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DropEntriesTransformerTest.php @@ -7,12 +7,11 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\DropEntriesTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\json_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; use function Flow\Types\DSL\type_json; @@ -40,9 +39,9 @@ public function test_bind_removes_the_dropped_columns(): void public function test_dropping_entries(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]], schema(int_schema('id'), string_schema('name'), json_schema('array')), - row(['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]), ); $transformer = new DropEntriesTransformer('id', 'array'); @@ -56,9 +55,9 @@ public function test_dropping_entries(): void public function test_removing_not_existing_entries(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]], schema(int_schema('id'), string_schema('name'), json_schema('array')), - row(['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]), ); $transformer = new DropEntriesTransformer('not_existing'); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php index f8e53e1db0..d4b74ede62 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php @@ -13,6 +13,7 @@ use Flow\ETL\WithEntry; use Flow\Types\Exception\InvalidTypeException; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\date_schema; @@ -21,7 +22,6 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; @@ -60,7 +60,7 @@ public function test_a_literal_condition_duplicates_every_row(): void ['id' => 2, 'flag' => true], ], (new DuplicateRowTransformer(true, with_entry('flag', lit(true)))) - ->transform(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), flow_context(config())) + ->transform(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), flow_context(config())) ->toArray(), ); } @@ -71,10 +71,9 @@ public function test_a_transformation_that_adds_a_column_conforms_the_untouched_ ref('status')->equals(lit('inactive')), with_entry('flag', lit(true)), ))->transform( - rows( + array_to_rows( + [['id' => 1, 'status' => 'active'], ['id' => 2, 'status' => 'inactive']], schema(int_schema('id'), string_schema('status')), - row(['id' => 1, 'status' => 'active']), - row(['id' => 2, 'status' => 'inactive']), ), flow_context(config()), ); @@ -96,10 +95,12 @@ public function test_a_transformation_that_narrows_a_column_widens_it_back(): vo ref('status')->equals(lit('inactive')), with_entry('amount', ref('amount')->multiply(lit(-1))), ))->transform( - rows( + array_to_rows( + [ + ['id' => 1, 'status' => 'active', 'amount' => 100], + ['id' => 2, 'status' => 'inactive', 'amount' => 100], + ], schema(int_schema('id'), string_schema('status'), int_schema('amount', nullable: true)), - row(['id' => 1, 'status' => 'active', 'amount' => 100]), - row(['id' => 2, 'status' => 'inactive', 'amount' => 100]), ), flow_context(config()), ); @@ -111,7 +112,30 @@ public function test_a_transformation_that_narrows_a_column_widens_it_back(): vo public function test_applying_two_transformations(): void { - $rows = rows( + $rows = array_to_rows( + [ + [ + 'id' => 1, + 'status' => 'active', + 'amount' => 100, + 'date_created' => type_date()->cast('2025-01-01'), + 'date_deactivated' => null, + ], + [ + 'id' => 2, + 'status' => 'inactive', + 'amount' => 100, + 'date_created' => type_date()->cast('2025-01-01'), + 'date_deactivated' => type_date()->cast('2025-01-03'), + ], + [ + 'id' => 3, + 'status' => 'active', + 'amount' => 100, + 'date_created' => type_date()->cast('2025-01-01'), + 'date_deactivated' => null, + ], + ], schema( int_schema('id'), string_schema('status'), @@ -120,27 +144,6 @@ public function test_applying_two_transformations(): void date_schema('date_deactivated', nullable: true), date_schema('date_updated', nullable: true), ), - row([ - 'id' => 1, - 'status' => 'active', - 'amount' => 100, - 'date_created' => type_date()->cast('2025-01-01'), - 'date_deactivated' => null, - ]), - row([ - 'id' => 2, - 'status' => 'inactive', - 'amount' => 100, - 'date_created' => type_date()->cast('2025-01-01'), - 'date_deactivated' => type_date()->cast('2025-01-03'), - ]), - row([ - 'id' => 3, - 'status' => 'active', - 'amount' => 100, - 'date_created' => type_date()->cast('2025-01-01'), - 'date_deactivated' => null, - ]), ); $transformedRows = (new DuplicateRowTransformer( @@ -213,11 +216,13 @@ public function test_bind_refuses_a_condition_referencing_a_column_missing_from_ public function test_doing_nothing_when_condition_is_not_satisfied(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'status' => 'active', 'amount' => 100], + ['id' => 2, 'status' => 'active', 'amount' => 100], + ['id' => 3, 'status' => 'active', 'amount' => 100], + ], schema(int_schema('id'), string_schema('status'), int_schema('amount')), - row(['id' => 1, 'status' => 'active', 'amount' => 100]), - row(['id' => 2, 'status' => 'active', 'amount' => 100]), - row(['id' => 3, 'status' => 'active', 'amount' => 100]), ); $transformedRows = (new DuplicateRowTransformer( @@ -239,11 +244,13 @@ public function test_doing_nothing_when_condition_is_not_satisfied(): void public function test_duplicating_row(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'status' => 'active', 'amount' => 100], + ['id' => 2, 'status' => 'inactive', 'amount' => 100], + ['id' => 3, 'status' => 'active', 'amount' => 100], + ], schema(int_schema('id'), string_schema('status'), int_schema('amount')), - row(['id' => 1, 'status' => 'active', 'amount' => 100]), - row(['id' => 2, 'status' => 'inactive', 'amount' => 100]), - row(['id' => 3, 'status' => 'active', 'amount' => 100]), ); $transformedRows = (new DuplicateRowTransformer( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/JoinEachRowsTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/JoinEachRowsTransformerTest.php index 49821aa428..9f55aabf13 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/JoinEachRowsTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/JoinEachRowsTransformerTest.php @@ -12,12 +12,11 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\JoinEachRowsTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\flow_context; 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; use function Flow\ETL\DSL\str_schema; @@ -42,21 +41,21 @@ public function from(Rows $rows): DataFrame public function test_inner_join_rows(): void { - $left = rows( + $left = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ); $right = new class implements DataFrameFactory { public function from(Rows $rows): DataFrame { - return data_frame()->process(rows( + return data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), )); } }; @@ -74,20 +73,20 @@ public function from(Rows $rows): DataFrame public function test_left_join_rows(): void { - $left = rows( + $left = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ); $right = new class implements DataFrameFactory { public function from(Rows $rows): DataFrame { - return data_frame()->process(rows( + return data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), )); } }; @@ -106,20 +105,20 @@ public function from(Rows $rows): DataFrame public function test_right_join_rows(): void { - $left = rows( + $left = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US'], ['id' => 3, 'country' => 'FR']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), - row(['id' => 3, 'country' => 'FR']), ); $right = new class implements DataFrameFactory { public function from(Rows $rows): DataFrame { - return data_frame()->process(rows( + return data_frame()->process(array_to_rows( + [ + ['code' => 'PL', 'name' => 'Poland'], + ['code' => 'US', 'name' => 'United States'], + ['code' => 'GB', 'name' => 'Great Britain'], + ], schema(str_schema('code'), str_schema('name')), - row(['code' => 'PL', 'name' => 'Poland']), - row(['code' => 'US', 'name' => 'United States']), - row(['code' => 'GB', 'name' => 'Great Britain']), )); } }; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php index 0dd9b9b297..85eca30f2e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpandTransformerTest.php @@ -16,8 +16,6 @@ use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure; @@ -42,14 +40,10 @@ public function test_emits_one_row_per_element_and_none_for_an_empty_list(): voi ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'x']], ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'y']], ], - $step->transform( - rows( - ListColumnsMother::tagsSchema(), - row(['id' => 'a', 'tags' => ['x', 'y']]), - row(['id' => 'b', 'tags' => []]), - ), - flow_context(config()), - )->toArray(), + $step->transform(array_to_rows([ + ['id' => 'a', 'tags' => ['x', 'y']], + ['id' => 'b', 'tags' => []], + ], ListColumnsMother::tagsSchema()), flow_context(config()))->toArray(), ); } @@ -66,10 +60,10 @@ public function test_unpack_emits_one_row_per_element(): void ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'x'], ['id' => 'a', 'tags' => ['x', 'y'], 'u.tag' => 'y'], ], - $step->transform( - rows(ListColumnsMother::tagsSchema(), row(['id' => 'a', 'tags' => ['x', 'y']])), - flow_context(config()), - )->toArray(), + $step->transform(array_to_rows([[ + 'id' => 'a', + 'tags' => ['x', 'y'], + ]], ListColumnsMother::tagsSchema()), flow_context(config()))->toArray(), ); } @@ -111,10 +105,10 @@ public function test_a_definition_entry_is_declared_as_given(): void ['id' => 'a', 'tags' => ['x', 'y'], 's' => 'ax'], ['id' => 'a', 'tags' => ['x', 'y'], 's' => 'ay'], ], - $step->transform( - rows(ListColumnsMother::tagsSchema(), row(['id' => 'a', 'tags' => ['x', 'y']])), - flow_context(config()), - )->toArray(), + $step->transform(array_to_rows([[ + 'id' => 'a', + 'tags' => ['x', 'y'], + ]], ListColumnsMother::tagsSchema()), flow_context(config()))->toArray(), ); } @@ -128,10 +122,10 @@ public function test_a_batch_under_another_schema_than_the_bound_one_is_conforme static::assertInstanceOf(NestedExpandTransformer::class, $step); - $result = $step->transform( - rows(ListColumnsMother::tagsSchema(), row(['id' => 'a', 'tags' => ['x']])), - flow_context(config()), - ); + $result = $step->transform(array_to_rows([[ + 'id' => 'a', + 'tags' => ['x'], + ]], ListColumnsMother::tagsSchema()), flow_context(config())); static::assertEquals( schema( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php index c57df979d3a485e708484cec293372a5ecfee710..a7be86f8b1d9ab0f75a5c918f6c5cfb55aebb4a3 100644 GIT binary patch delta 207 zcmdmIeARTrMMj>)qN2pg_>%niqWtp7icB(-FEW1L{G2IGgcB|^*;hPZGPAhz82r%7tE>42pszm-tpR%b}9C`impu`*DfEG=m-22!I5 akq0rMVDdysaTQciBt@FmVDoCZYPkT^b~4%k delta 53 zcmca=y3csSMaIcL8NV|Z<(E%ZWRltZfhkR7a=duJ=8xh>8Cig$8k1j2YEIrFEH#;1 JLYS$R3jkxP6fgh) diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/PruneEntriesTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/PruneEntriesTransformerTest.php index 84252f39fb..b18cc603cd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/PruneEntriesTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/PruneEntriesTransformerTest.php @@ -7,11 +7,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\PruneEntriesTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -43,9 +42,9 @@ public function test_keeping_only_the_given_entries(): void [['id' => 1, 'name' => 'a']], (new PruneEntriesTransformer(ref('id'), ref('name'))) ->transform( - rows( + array_to_rows( + [['id' => 1, 'name' => 'a', 'dropped' => 9]], schema(int_schema('id'), str_schema('name'), int_schema('dropped')), - row(['id' => 1, 'name' => 'a', 'dropped' => 9]), ), flow_context(), ) @@ -59,10 +58,9 @@ public function test_entry_missing_from_a_row_is_padded_from_its_nullable_declar [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null]], (new PruneEntriesTransformer(ref('id'), ref('name'))) ->transform( - rows( + array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2]], schema(int_schema('id'), str_schema('name', nullable: true)), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2]), ), flow_context(), ) @@ -75,7 +73,7 @@ public function test_row_without_any_of_the_given_entries_becomes_empty(): void static::assertSame( [[]], (new PruneEntriesTransformer(ref('missing'))) - ->transform(rows(schema(int_schema('id')), row(['id' => 1])), flow_context()) + ->transform(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context()) ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/RenameEntryTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/RenameEntryTransformerTest.php index 714f63b51a..2d22f25e8d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/RenameEntryTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/RenameEntryTransformerTest.php @@ -7,14 +7,13 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\RenameEntryTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\json_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\schema_metadata; use function Flow\ETL\DSL\string_schema; @@ -26,7 +25,7 @@ final class RenameEntryTransformerTest extends FlowTestCase public function test_renaming_keeps_the_column_position_and_its_values(): void { $renamed = (new RenameEntryTransformer('a', 'x'))->transform( - rows(schema(integer_schema('a'), integer_schema('b')), row(['a' => 1, 'b' => 2])), + array_to_rows([['a' => 1, 'b' => 2]], schema(integer_schema('a'), integer_schema('b'))), flow_context(config()), ); @@ -57,7 +56,16 @@ public function test_renaming_entries(): void $context = flow_context(config()); $rows = (new RenameEntryTransformer('old_int', 'new_int'))->transform( - rows( + array_to_rows( + [[ + 'old_int' => 1000, + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'datetime' => type_datetime()->cast('2020-01-01 00:00:00 UTC'), + 'json' => type_json()->cast(['foo', 'bar']), + 'null' => null, + ]], schema( integer_schema('old_int'), integer_schema('id'), @@ -67,21 +75,21 @@ public function test_renaming_entries(): void json_schema('json'), string_schema('null', nullable: true), ), - row([ - 'old_int' => 1000, - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'datetime' => type_datetime()->cast('2020-01-01 00:00:00 UTC'), - 'json' => type_json()->cast(['foo', 'bar']), - 'null' => null, - ]), ), $context, ); static::assertEquals( - rows( + array_to_rows( + [[ + 'new_int' => 1000, + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'datetime' => type_datetime()->cast('2020-01-01 00:00:00 UTC'), + 'json' => type_json()->cast(['foo', 'bar']), + 'nothing' => null, + ]], schema( integer_schema('new_int'), integer_schema('id'), @@ -91,15 +99,6 @@ public function test_renaming_entries(): void json_schema('json'), string_schema('nothing', nullable: true), ), - row([ - 'new_int' => 1000, - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'datetime' => type_datetime()->cast('2020-01-01 00:00:00 UTC'), - 'json' => type_json()->cast(['foo', 'bar']), - 'nothing' => null, - ]), ), (new RenameEntryTransformer('null', 'nothing'))->transform($rows, $context), ); @@ -109,10 +108,9 @@ public function test_renaming_entry_preserves_metadata(): void { $metadata = schema_metadata(['description' => 'test metadata', 'priority' => 1]); - $outputRows = (new RenameEntryTransformer('old_name', 'new_name'))->transform( - rows(schema(string_schema('old_name', metadata: $metadata)), row(['old_name' => 'test value'])), - flow_context(config()), - ); + $outputRows = (new RenameEntryTransformer('old_name', 'new_name'))->transform(array_to_rows([[ + 'old_name' => 'test value', + ]], schema(string_schema('old_name', metadata: $metadata))), flow_context(config())); static::assertSame('test value', $outputRows->first()->get('new_name')); static::assertTrue($outputRows->schema()->get('new_name')->metadata()->isEqual($metadata)); @@ -120,7 +118,7 @@ public function test_renaming_entry_preserves_metadata(): void public function test_renaming_to_same_name_returns_same_rows_instance(): void { - $inputRows = rows(schema(string_schema('name')), row(['name' => 'value'])); + $inputRows = array_to_rows([['name' => 'value']], schema(string_schema('name'))); static::assertSame($inputRows, (new RenameEntryTransformer('name', 'name'))->transform( $inputRows, diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionFilterTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionFilterTransformerTest.php index b98eb38f12..313fda2876 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionFilterTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionFilterTransformerTest.php @@ -10,12 +10,12 @@ use Flow\ETL\Tests\Mother\ListColumnsMother; use Flow\ETL\Transformer\ScalarFunctionFilterTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; @@ -47,7 +47,7 @@ public function test_bind_returns_the_input_schema(): void public function test_equal(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 1]), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -61,7 +61,7 @@ public function test_equal(): void public function test_equal_on_literal(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 1]), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -75,7 +75,7 @@ public function test_equal_on_literal(): void public function test_greater_than(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -89,7 +89,7 @@ public function test_greater_than(): void public function test_greater_than_or_equal(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 1]), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -104,7 +104,7 @@ public function test_greater_than_or_equal(): void public function test_less_than(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 1]), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -118,7 +118,7 @@ public function test_less_than(): void public function test_less_than_equal(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 1]), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -133,7 +133,7 @@ public function test_less_than_equal(): void public function test_not_equal(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 1]), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -147,7 +147,7 @@ public function test_not_equal(): void public function test_not_same(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 1]), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -161,7 +161,7 @@ public function test_not_same(): void public function test_same(): void { - $rows = rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 1]), row(['a' => 1, 'b' => 2])); + $rows = array_to_rows([['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))); static::assertSame( [ @@ -178,10 +178,10 @@ public function test_a_non_boolean_predicate_is_rejected_at_bind(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('filter() requires a predicate returning boolean'); - (new ScalarFunctionFilterTransformer(ref('score')))->transform( - rows(schema(int_schema('score', nullable: true)), row(['score' => 1]), row(['score' => null])), - flow_context(config()), - ); + (new ScalarFunctionFilterTransformer(ref('score')))->transform(array_to_rows([ + ['score' => 1], + ['score' => null], + ], schema(int_schema('score', nullable: true))), flow_context(config())); } public function test_a_null_propagating_predicate_over_a_nullable_column_is_accepted(): void @@ -191,15 +191,11 @@ public function test_a_null_propagating_predicate_over_a_nullable_column_is_acce ['score' => 11], ], (new ScalarFunctionFilterTransformer(ref('score')->greaterThan(lit(10)))) - ->transform( - rows( - schema(int_schema('score', nullable: true)), - row(['score' => 11]), - row(['score' => 2]), - row(['score' => null]), - ), - flow_context(config()), - ) + ->transform(array_to_rows([ + ['score' => 11], + ['score' => 2], + ['score' => null], + ], schema(int_schema('score', nullable: true))), flow_context(config())) ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformer/MathTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformer/MathTest.php index 3fed78a1b6..3c4a0a435b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformer/MathTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformer/MathTest.php @@ -11,13 +11,12 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\integer_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; final class MathTest extends FlowTestCase @@ -146,7 +145,7 @@ public function test_divide( ): void { $rows = (new ScalarFunctionTransformer('result', ref($a->entry()->name()) ->divide(ref($b->entry()->name()), $scale, $rounding)))->transform( - rows(schema($a, $b), row([$a->entry()->name() => $aValue, $b->entry()->name() => $bValue])), + array_to_rows([[$a->entry()->name() => $aValue, $b->entry()->name() => $bValue]], schema($a, $b)), flow_context(), ); @@ -165,7 +164,7 @@ public function test_minus(Definition $a, mixed $aValue, Definition $b, mixed $b 'result', ref($a->entry()->name())->minus(ref($b->entry()->name())), ))->transform( - rows(schema($a, $b), row([$a->entry()->name() => $aValue, $b->entry()->name() => $bValue])), + array_to_rows([[$a->entry()->name() => $aValue, $b->entry()->name() => $bValue]], schema($a, $b)), flow_context(), ); @@ -184,7 +183,7 @@ public function test_multiply(Definition $a, mixed $aValue, Definition $b, mixed 'result', ref($a->entry()->name())->multiply(ref($b->entry()->name())), ))->transform( - rows(schema($a, $b), row([$a->entry()->name() => $aValue, $b->entry()->name() => $bValue])), + array_to_rows([[$a->entry()->name() => $aValue, $b->entry()->name() => $bValue]], schema($a, $b)), flow_context(), ); @@ -203,7 +202,7 @@ public function test_plus(Definition $a, mixed $aValue, Definition $b, mixed $bV 'result', ref($a->entry()->name())->plus(ref($b->entry()->name())), ))->transform( - rows(schema($a, $b), row([$a->entry()->name() => $aValue, $b->entry()->name() => $bValue])), + array_to_rows([[$a->entry()->name() => $aValue, $b->entry()->name() => $bValue]], schema($a, $b)), flow_context(), ); @@ -222,7 +221,7 @@ public function test_power(Definition $a, mixed $aValue, Definition $b, mixed $b 'result', ref($a->entry()->name())->power(ref($b->entry()->name())), ))->transform( - rows(schema($a, $b), row([$a->entry()->name() => $aValue, $b->entry()->name() => $bValue])), + array_to_rows([[$a->entry()->name() => $aValue, $b->entry()->name() => $bValue]], schema($a, $b)), flow_context(), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php index d4387a0bb4..aeebde0603 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php @@ -22,6 +22,7 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\concat; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; @@ -29,7 +30,6 @@ use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -83,7 +83,7 @@ public function test_expand_results(): void ['array' => 3], ], (new ScalarFunctionTransformer('array', new ArrayExpand(lit([1, 2, 3]), ArrayExpand\ArrayExpand::VALUES))) - ->transform(rows(schema(), row([])), flow_context(config())) + ->transform(array_to_rows([[]], schema()), flow_context(config())) ->toArray(), ); } @@ -105,7 +105,7 @@ public function test_lit_expression_on_non_empty_rows(): void ['name' => 'Norbert', 'number' => 1], ], (new ScalarFunctionTransformer('number', lit(1))) - ->transform(rows(schema(str_schema('name')), row(['name' => 'Norbert'])), flow_context(config())) + ->transform(array_to_rows([['name' => 'Norbert']], schema(str_schema('name'))), flow_context(config())) ->toArray(), ); } @@ -128,7 +128,7 @@ public function test_plus_expression_on_non_empty_rows(): void ], (new ScalarFunctionTransformer('c', ref('a')->plus(ref('b')))) ->transform( - rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 2])), + array_to_rows([['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))), flow_context(config()), ) ->toArray(), @@ -145,7 +145,7 @@ public function test_plus_expression_on_non_existing_rows(): void ['a' => 1, 'number' => 0], ], (new ScalarFunctionTransformer('number', ref('num')->plus(ref('num1')))) - ->transform(rows(schema(int_schema('a')), row(['a' => 1])), flow_context(config())) + ->transform(array_to_rows([['a' => 1]], schema(int_schema('a'))), flow_context(config())) ->toArray(), ); } @@ -160,7 +160,7 @@ public function test_an_undeclared_payload_key_is_dropped(): void 'array', new ArrayUnpack(lit(['id' => 1, 'secret' => 'dropped']), schema(int_schema('id'))), )) - ->transform(rows(schema(), row([])), flow_context(config())) + ->transform(array_to_rows([[]], schema()), flow_context(config())) ->toArray(), ); } @@ -172,7 +172,7 @@ public function test_unpack_results_ignores_a_definition_passed_to_with_entry(): $result = (new ScalarFunctionTransformer( str_schema('array'), new ArrayUnpack(lit(['id' => 1, 'name' => 'Norbert']), schema(int_schema('id'), str_schema('name'))), - ))->transform(rows(schema(), row([])), flow_context(config())); + ))->transform(array_to_rows([[]], schema()), flow_context(config())); static::assertEquals([['array.id' => 1, 'array.name' => 'Norbert']], $result->toArray()); static::assertEquals( @@ -191,10 +191,9 @@ public function test_xml_xpath_expression_when_there_is_more_than_one_node_under $nodes = type_instance_of(DOMNodeList::class)->assert($xpath->query('/root/foo')); $expected = [$nodes->item(0), $nodes->item(1)]; - $result = (new ScalarFunctionTransformer('xpath', ref('xml')->xpath('/root/foo')))->transform( - rows(schema(xml_schema('xml')), row(['xml' => type_xml()->cast($xml)])), - flow_context(config()), - ); + $result = (new ScalarFunctionTransformer('xpath', ref('xml')->xpath('/root/foo')))->transform(array_to_rows([[ + 'xml' => type_xml()->cast($xml), + ]], schema(xml_schema('xml'))), flow_context(config())); static::assertEquals($expected, $result->first()->get('xpath')); static::assertEquals(type_list(type_xml_element()), $result->schema()->get('xpath')->type()); @@ -203,10 +202,10 @@ public function test_xml_xpath_expression_when_there_is_more_than_one_node_under public function test_a_declared_output_definition_coerces_the_produced_value(): void { - $result = (new ScalarFunctionTransformer(str_schema('out'), ref('v')))->transform( - rows(schema(int_schema('v')), row(['v' => 1]), row(['v' => 2])), - flow_context(config()), - ); + $result = (new ScalarFunctionTransformer(str_schema('out'), ref('v')))->transform(array_to_rows([ + ['v' => 1], + ['v' => 2], + ], schema(int_schema('v'))), flow_context(config())); static::assertSame( [ @@ -219,25 +218,27 @@ public function test_a_declared_output_definition_coerces_the_produced_value(): public function test_the_produced_column_takes_the_declared_definition(): void { - $result = (new ScalarFunctionTransformer(str_schema('out'), ref('v')))->transform( - rows(schema(int_schema('v')), row(['v' => 1]), row(['v' => 2])), - flow_context(config()), - ); + $result = (new ScalarFunctionTransformer(str_schema('out'), ref('v')))->transform(array_to_rows([ + ['v' => 1], + ['v' => 2], + ], schema(int_schema('v'))), flow_context(config())); static::assertEquals(type_string(), $result->schema()->get('out')->type()); } public function test_the_produced_definition_does_not_depend_on_batch_size(): void { - $wholeBatch = (new ScalarFunctionTransformer('out', ref('v')->plus(lit(1))))->transform( - rows(schema(int_schema('v')), row(['v' => 1]), row(['v' => 2])), - flow_context(config()), - ); + $wholeBatch = (new ScalarFunctionTransformer('out', ref('v')->plus(lit(1))))->transform(array_to_rows([ + ['v' => 1], + ['v' => 2], + ], schema(int_schema('v'))), flow_context(config())); $transformer = new ScalarFunctionTransformer('out', ref('v')->plus(lit(1))); $single = $transformer - ->transform(rows(schema(int_schema('v')), row(['v' => 1])), flow_context(config())) - ->merge($transformer->transform(rows(schema(int_schema('v')), row(['v' => 2])), flow_context(config()))); + ->transform(array_to_rows([['v' => 1]], schema(int_schema('v'))), flow_context(config())) + ->merge($transformer->transform(array_to_rows([[ + 'v' => 2, + ]], schema(int_schema('v'))), flow_context(config()))); static::assertEquals($wholeBatch->schema()->get('out'), $single->schema()->get('out')); static::assertEquals($wholeBatch->toArray(), $single->toArray()); @@ -248,10 +249,10 @@ public function test_a_null_produced_under_a_not_null_declaration_names_its_row( $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "out" (row 1)'); - (new ScalarFunctionTransformer(int_schema('out'), ref('v')))->transform( - rows(schema(int_schema('v', nullable: true)), row(['v' => 1]), row(['v' => null])), - flow_context(config()), - ); + (new ScalarFunctionTransformer(int_schema('out'), ref('v')))->transform(array_to_rows([ + ['v' => 1], + ['v' => null], + ], schema(int_schema('v', nullable: true))), flow_context(config())); } public function test_a_batch_arriving_under_another_schema_than_the_bound_one_is_conformed_to_the_bound_output(): void @@ -263,7 +264,7 @@ public function test_a_batch_arriving_under_another_schema_than_the_bound_one_is static::assertSame( [['id' => 1, 'name' => null, 'out' => 'x']], - $step->transform(rows(schema(int_schema('id')), row(['id' => 1])), flow_context(config()))->toArray(), + $step->transform(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context(config()))->toArray(), ); } @@ -275,7 +276,7 @@ public function test_an_expanded_null_under_a_not_null_declaration_names_its_row (new ScalarFunctionTransformer( int_schema('out'), new ArrayExpand(lit([1, null]), ArrayExpand\ArrayExpand::VALUES), - ))->transform(rows(schema(), row([])), flow_context(config())); + ))->transform(array_to_rows([[]], schema()), flow_context(config())); } public function test_an_empty_batch_is_bound_against_its_own_schema(): void @@ -365,10 +366,10 @@ public function test_an_unbound_nested_expand_is_expanded(): void ['id' => 'a', 'tags' => ['x', 'y'], 's' => ['tag' => 'y']], ], (new ScalarFunctionTransformer('s', structure(['tag' => ref('tags')->expand()]))) - ->transform( - rows(ListColumnsMother::tagsSchema(), row(['id' => 'a', 'tags' => ['x', 'y']])), - flow_context(config()), - ) + ->transform(array_to_rows([[ + 'id' => 'a', + 'tags' => ['x', 'y'], + ]], ListColumnsMother::tagsSchema()), flow_context(config())) ->toArray(), ); } @@ -384,10 +385,10 @@ public function test_an_unbound_unpack_over_a_nested_expand_is_expanded(): void 'u', structure(['tag' => ref('tags')->expand()])->unpack(schema(str_schema('tag'))), )) - ->transform( - rows(ListColumnsMother::tagsSchema(), row(['id' => 'a', 'tags' => ['x', 'y']])), - flow_context(config()), - ) + ->transform(array_to_rows([[ + 'id' => 'a', + 'tags' => ['x', 'y'], + ]], ListColumnsMother::tagsSchema()), flow_context(config())) ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SelectEntriesTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SelectEntriesTransformerTest.php index ba07261d74..cb0c616818 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SelectEntriesTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SelectEntriesTransformerTest.php @@ -8,12 +8,11 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\SelectEntriesTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\json_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\string_schema; @@ -43,9 +42,9 @@ public function test_bind_refuses_a_column_missing_from_the_input(): void public function test_selecting_entries(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]], schema(int_schema('id'), str_schema('name'), json_schema('array')), - row(['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]), ); $transformer = new SelectEntriesTransformer('name'); @@ -59,9 +58,9 @@ public function test_selecting_entries(): void public function test_selecting_not_existing_entries(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]], schema(int_schema('id'), string_schema('name'), json_schema('array')), - row(['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]), ); $this->expectException(SchemaDefinitionNotFoundException::class); @@ -78,10 +77,9 @@ public function test_selecting_an_entry_missing_from_some_rows_widens_to_a_nulla schema(int_schema('id', nullable: true)), $transformer ->transform( - rows( + array_to_rows( + [['id' => 1], ['name' => 'no id here']], schema(int_schema('id', nullable: true), str_schema('name', nullable: true)), - row(['id' => 1]), - row(['name' => 'no id here']), ), flow_context(config()), ) @@ -91,9 +89,9 @@ public function test_selecting_an_entry_missing_from_some_rows_widens_to_a_nulla public function test_using_select_entries_in_order_to_change_entries_order(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]], schema(int_schema('id'), str_schema('name'), json_schema('array')), - row(['id' => 1, 'name' => 'Row Name', 'array' => type_json()->cast(['test'])]), ); $result = (new SelectEntriesTransformer('name', 'id', 'array'))->transform($rows, flow_context(config())); @@ -113,10 +111,9 @@ public function test_select_carries_a_not_null_definition_through_unchanged(): v schema(int_schema('id')), (new SelectEntriesTransformer('id')) ->transform( - rows( + array_to_rows( + [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'Alice']), - row(['id' => 2, 'name' => 'Bob']), ), flow_context(config()), ) diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php index 8886a35717..8c1ac29a63 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php @@ -9,11 +9,11 @@ use Flow\Floe\FloeSerializer; use Flow\Serializer\Base64Serializer; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -52,7 +52,7 @@ public function test_bind_replaces_the_target_column_with_a_string_column(): voi public function test_serializing_empty_row_under_one_entry(): void { - $rows = rows($rowSchema = schema(), $row1 = row([])); + $rows = rows($rowSchema = schema(), $row1 = array_to_row([], schema())); $transformer = new SerializeTransformer('serialized'); $transformedRows = $transformer->transform($rows, flow_context()); @@ -80,8 +80,24 @@ public function test_serializing_row_under_one_entry(): void ); $rows = rows( $rowSchema, - $row1 = row(['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']]), - $row2 = row(['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']]), + $row1 = array_to_row( + ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + list_schema('tags', type_list(type_string())), + ), + ), + $row2 = array_to_row( + ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + list_schema('tags', type_list(type_string())), + ), + ), ); $transformer = new SerializeTransformer('serialized'); @@ -125,8 +141,24 @@ public function test_serializing_row_under_standalone_entry(): void ); $rows = rows( $rowSchema, - $row1 = row(['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']]), - $row2 = row(['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']]), + $row1 = array_to_row( + ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + list_schema('tags', type_list(type_string())), + ), + ), + $row2 = array_to_row( + ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + list_schema('tags', type_list(type_string())), + ), + ), ); $transformer = new SerializeTransformer('serialized', true); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php index b94006e735..c95ea41611 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php @@ -9,26 +9,27 @@ use Flow\Floe\FloeSerializer; use Flow\Serializer\Base64Serializer; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Serializer\DSL\serialize_to_string; final class SerializedPayloadDecoderTest extends FlowTestCase { public function test_a_multi_row_payload_gives_up(): void { - $payload = serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), - ); + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id')))); static::assertSame( [], SerializedPayloadDecoderTest::decoder() - ->decode(row(['serialized' => $payload])) + ->decode(array_to_row(['serialized' => $payload], schema(str_schema('serialized')))) ->values(), ); } @@ -38,7 +39,7 @@ public function test_a_non_string_value_gives_up(): void static::assertSame( [], SerializedPayloadDecoderTest::decoder() - ->decode(row(['serialized' => 123])) + ->decode(array_to_row(['serialized' => 123], schema(int_schema('serialized')))) ->values(), ); } @@ -48,7 +49,7 @@ public function test_a_payload_that_does_not_deserialize_gives_up(): void static::assertSame( [], SerializedPayloadDecoderTest::decoder() - ->decode(row(['serialized' => 'not-serialized'])) + ->decode(array_to_row(['serialized' => 'not-serialized'], schema(str_schema('serialized')))) ->values(), ); } @@ -58,22 +59,21 @@ public function test_a_row_without_the_source_column_gives_up(): void static::assertSame( [], SerializedPayloadDecoderTest::decoder() - ->decode(row(['other' => 1])) + ->decode(array_to_row(['other' => 1], schema(int_schema('other')))) ->values(), ); } public function test_it_reads_the_declared_columns_out_of_the_payload(): void { - $payload = serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows(schema(int_schema('id')), row(['id' => 7])), - ); + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + 'id' => 7, + ]], schema(int_schema('id')))); static::assertSame( ['id' => 7], SerializedPayloadDecoderTest::decoder() - ->decode(row(['serialized' => $payload])) + ->decode(array_to_row(['serialized' => $payload], schema(str_schema('serialized')))) ->values(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php index 92d5113ab6..c0ec0a81fa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php @@ -10,11 +10,12 @@ use Flow\Floe\FloeSerializer; use Flow\Serializer\Base64Serializer; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -26,18 +27,16 @@ final class UnserializeTransformerTest extends FlowTestCase { public function test_a_payload_written_with_another_type_is_refused(): void { - $payload = serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows(schema(str_schema('id')), row(['id' => '12'])), - ); + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + 'id' => '12', + ]], schema(str_schema('id')))); $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "id" (row 0): could not convert \'12\' (string) to integer'); - (new UnserializeTransformer('serialized', schema(int_schema('id'))))->transform( - rows(schema(str_schema('serialized')), row(['serialized' => $payload])), - flow_context(), - ); + (new UnserializeTransformer('serialized', schema(int_schema('id'))))->transform(array_to_rows([[ + 'serialized' => $payload, + ]], schema(str_schema('serialized'))), flow_context()); } public function test_bind_expands_the_declared_target_into_nullable_columns(): void @@ -82,27 +81,36 @@ public function test_bind_without_merging_keeps_only_the_declared_target(): void public function test_unserializing_row_from_entry(): void { - $row1 = row(['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']]); + $row1 = array_to_row( + ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + list_schema('tags', type_list(type_string())), + ), + ); $rowSchema = schema( int_schema('id'), str_schema('name'), bool_schema('active'), list_schema('tags', type_list(type_string())), ); - $row2 = row(['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']]); - - $rows = rows( - schema(str_schema('serialized')), - row(['serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row1), - )]), - row(['serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row2), - )]), + $row2 = array_to_row( + ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + list_schema('tags', type_list(type_string())), + ), ); + $rows = array_to_rows([ + ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), rows($rowSchema, $row1))], + ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), rows($rowSchema, $row2))], + ], schema(str_schema('serialized'))); + $transformer = new UnserializeTransformer('serialized', $rowSchema); $transformedRows = $transformer->transform($rows, flow_context()); @@ -136,7 +144,7 @@ public function test_unserializing_row_from_entry(): void public function test_unserializing_something_that_is_not_serialized_row(): void { - $rows = rows(schema(str_schema('serialized')), row(['serialized' => 'not-serialized'])); + $rows = array_to_rows([['serialized' => 'not-serialized']], schema(str_schema('serialized'))); $transformer = new UnserializeTransformer('serialized', schema(int_schema('id'))); @@ -148,7 +156,7 @@ public function test_unserializing_something_that_is_not_serialized_row(): void public function test_unserializing_row_without_source_column_emits_the_declared_shape(): void { - $rows = rows(schema(int_schema('id')), row(['id' => 1])); + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); $transformer = new UnserializeTransformer('serialized', schema(str_schema('name'))); @@ -157,7 +165,7 @@ public function test_unserializing_row_without_source_column_emits_the_declared_ public function test_unserializing_non_string_value_emits_the_declared_shape(): void { - $rows = rows(schema(int_schema('serialized')), row(['serialized' => 123])); + $rows = array_to_rows([['serialized' => 123]], schema(int_schema('serialized'))); $transformer = new UnserializeTransformer('serialized', schema(str_schema('name'))); @@ -169,11 +177,11 @@ public function test_unserializing_non_string_value_emits_the_declared_shape(): public function test_unserializing_multi_row_payload_emits_the_declared_shape(): void { - $payload = serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), - ); - $rows = rows(schema(str_schema('serialized')), row(['serialized' => $payload])); + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id')))); + $rows = array_to_rows([['serialized' => $payload]], schema(str_schema('serialized'))); $transformer = new UnserializeTransformer('serialized', schema(int_schema('id'))); @@ -185,44 +193,54 @@ public function test_unserializing_multi_row_payload_emits_the_declared_shape(): public function test_the_declared_columns_land_under_the_merge_prefix(): void { - $payload = serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows(schema(int_schema('id')), row(['id' => 7])), - ); + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + 'id' => 7, + ]], schema(int_schema('id')))); $transformer = new UnserializeTransformer('serialized', schema(int_schema('id')), mergePrefix: 'payload_'); static::assertSame( [['serialized' => $payload, 'payload_id' => 7]], $transformer - ->transform(rows(schema(str_schema('serialized')), row(['serialized' => $payload])), flow_context()) + ->transform(array_to_rows([[ + 'serialized' => $payload, + ]], schema(str_schema('serialized'))), flow_context()) ->toArray(), ); } public function test_unserializing_without_merge(): void { - $row1 = row(['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']]); + $row1 = array_to_row( + ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + list_schema('tags', type_list(type_string())), + ), + ); $rowSchema = schema( int_schema('id'), str_schema('name'), bool_schema('active'), list_schema('tags', type_list(type_string())), ); - $row2 = row(['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']]); - - $rows = rows( - schema(str_schema('serialized')), - row(['serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row1), - )]), - row(['serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row2), - )]), + $row2 = array_to_row( + ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + list_schema('tags', type_list(type_string())), + ), ); + $rows = array_to_rows([ + ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), rows($rowSchema, $row1))], + ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), rows($rowSchema, $row2))], + ], schema(str_schema('serialized'))); + $transformer = new UnserializeTransformer('serialized', $rowSchema, false); $transformedRows = $transformer->transform($rows, flow_context()); @@ -248,18 +266,17 @@ public function test_unserializing_without_merge(): void public function test_a_declared_column_replaces_an_input_column_of_the_same_name(): void { - $payload = serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows(schema(int_schema('id')), row(['id' => 7])), - ); + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + 'id' => 7, + ]], schema(int_schema('id')))); static::assertSame( [['serialized' => $payload, 'id' => 7]], (new UnserializeTransformer('serialized', schema(int_schema('id')))) ->transform( - rows( + array_to_rows( + [['serialized' => $payload, 'id' => 1]], schema(str_schema('serialized'), int_schema('id')), - row(['serialized' => $payload, 'id' => 1]), ), flow_context(), ) @@ -269,15 +286,16 @@ public function test_a_declared_column_replaces_an_input_column_of_the_same_name public function test_a_declared_column_the_payload_does_not_carry_is_null(): void { - $payload = serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows(schema(int_schema('id')), row(['id' => 7])), - ); + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + 'id' => 7, + ]], schema(int_schema('id')))); static::assertSame( [['serialized' => $payload, 'id' => 7, 'absent' => null]], (new UnserializeTransformer('serialized', schema(int_schema('id'), str_schema('absent')))) - ->transform(rows(schema(str_schema('serialized')), row(['serialized' => $payload])), flow_context()) + ->transform(array_to_rows([[ + 'serialized' => $payload, + ]], schema(str_schema('serialized'))), flow_context()) ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UntilTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UntilTransformerTest.php index 13a7d21969..1a7740e582 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UntilTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UntilTransformerTest.php @@ -11,12 +11,12 @@ use Flow\ETL\Tests\Mother\ListColumnsMother; use Flow\ETL\Transformer\UntilTransformer; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; @@ -27,7 +27,7 @@ public function test_a_batch_that_holds_the_predicate_throughout_passes_through( static::assertSame( [['id' => 1], ['id' => 2]], (new UntilTransformer(ref('id')->lessThan(lit(3)))) - ->transform(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), flow_context(config())) + ->transform(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), flow_context(config())) ->toArray(), ); } @@ -51,10 +51,11 @@ public function test_passes_rows_until_the_predicate_stops_holding(): void $thrown = null; try { - (new UntilTransformer(ref('id')->lessThan(lit(3))))->transform( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), - flow_context(config()), - ); + (new UntilTransformer(ref('id')->lessThan(lit(3))))->transform(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id'))), flow_context(config())); } catch (LimitReachedException $e) { $thrown = $e; } @@ -68,17 +69,13 @@ public function test_it_stops_at_the_first_row_failing_the_predicate(): void $thrown = null; try { - (new UntilTransformer(ref('id')->lessThan(lit(3))))->transform( - rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 5]), - row(['id' => 1]), - row(['id' => 2]), - ), - flow_context(config()), - ); + (new UntilTransformer(ref('id')->lessThan(lit(3))))->transform(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 5], + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id'))), flow_context(config())); } catch (LimitReachedException $e) { $thrown = $e; } @@ -92,14 +89,14 @@ public function test_a_reached_limit_stops_the_next_batch(): void $transformer = new UntilTransformer(ref('id')->lessThan(lit(1))); try { - $transformer->transform(rows(schema(int_schema('id')), row(['id' => 5])), flow_context(config())); + $transformer->transform(array_to_rows([['id' => 5]], schema(int_schema('id'))), flow_context(config())); } catch (LimitReachedException) { } $thrown = null; try { - $transformer->transform(rows(schema(int_schema('id')), row(['id' => 0])), flow_context(config())); + $transformer->transform(array_to_rows([['id' => 0]], schema(int_schema('id'))), flow_context(config())); } catch (LimitReachedException $e) { $thrown = $e; } @@ -113,10 +110,9 @@ public function test_a_non_boolean_predicate_is_rejected_at_bind(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('until() requires a predicate returning boolean'); - (new UntilTransformer(ref('id')))->transform( - rows(schema(int_schema('id')), row(['id' => 1])), - flow_context(config()), - ); + (new UntilTransformer(ref('id')))->transform(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))), flow_context(config())); } public function test_an_empty_batch_is_bound_against_its_own_schema(): void @@ -131,7 +127,7 @@ public function test_a_reached_limit_stops_an_empty_next_batch(): void $transformer = new UntilTransformer(ref('id')->lessThan(lit(1))); try { - $transformer->transform(rows(schema(int_schema('id')), row(['id' => 5])), flow_context(config())); + $transformer->transform(array_to_rows([['id' => 5]], schema(int_schema('id'))), flow_context(config())); } catch (LimitReachedException) { } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/AverageAccumulatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/AverageAccumulatorTest.php index d4d8637727..69ae0029bc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/AverageAccumulatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/AverageAccumulatorTest.php @@ -9,9 +9,12 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Window\Accumulator\AverageAccumulator; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class AverageAccumulatorTest extends FlowTestCase { @@ -19,8 +22,8 @@ public function test_averages_accumulated_values(): void { $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()); - $accumulator->accumulate(row(['value' => 10])); - $accumulator->accumulate(row(['value' => 20])); + $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 20], schema(int_schema('value')))); static::assertSame(15.0, $accumulator->value()); } @@ -36,17 +39,19 @@ public function test_missing_entry_throws_in_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessageMatches('/^Average window function error: /'); - (new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, $context))->accumulate(row(['other' => 'x'])); + (new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, $context))->accumulate(array_to_row([ + 'other' => 'x', + ], schema(str_schema('other')))); } public function test_non_numeric_values_are_skipped(): void { $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()); - $accumulator->accumulate(row(['value' => 10])); - $accumulator->accumulate(row(['value' => 'not a number'])); - $accumulator->accumulate(row(['value' => null])); - $accumulator->accumulate(row(['value' => 20])); + $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 'not a number'], schema(str_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => null], schema(str_schema('value', nullable: true)))); + $accumulator->accumulate(array_to_row(['value' => 20], schema(int_schema('value')))); static::assertSame(15.0, $accumulator->value()); } @@ -55,7 +60,7 @@ public function test_only_null_values_still_average_to_null(): void { $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()); - $accumulator->accumulate(row(['value' => null])); + $accumulator->accumulate(array_to_row(['value' => null], schema(str_schema('value', nullable: true)))); static::assertNull($accumulator->value()); } @@ -64,9 +69,9 @@ public function test_scale_and_rounding_are_applied(): void { $accumulator = new AverageAccumulator(ref('value'), 3, Rounding::HALF_UP, flow_context()); - $accumulator->accumulate(row(['value' => 10])); - $accumulator->accumulate(row(['value' => 20])); - $accumulator->accumulate(row(['value' => 25])); + $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 20], schema(int_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 25], schema(int_schema('value')))); static::assertSame(18.333, $accumulator->value()); } @@ -74,12 +79,12 @@ public function test_scale_and_rounding_are_applied(): void public function test_value_is_idempotent(): void { $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()); - $accumulator->accumulate(row(['value' => 10])); + $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); static::assertSame(10.0, $accumulator->value()); static::assertSame(10.0, $accumulator->value()); - $accumulator->accumulate(row(['value' => 20])); + $accumulator->accumulate(array_to_row(['value' => 20], schema(int_schema('value')))); static::assertSame(15.0, $accumulator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/CountAccumulatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/CountAccumulatorTest.php index a458b45118..1d377f3d26 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/CountAccumulatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/CountAccumulatorTest.php @@ -8,9 +8,12 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Window\Accumulator\CountAccumulator; +use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class CountAccumulatorTest extends FlowTestCase { @@ -18,8 +21,8 @@ public function test_counts_every_row_when_reference_is_null(): void { $accumulator = new CountAccumulator(null, flow_context()); - $accumulator->accumulate(row(['value' => 1])); - $accumulator->accumulate(row(['other' => 'x'])); + $accumulator->accumulate(array_to_row(['value' => 1], schema(int_schema('value')))); + $accumulator->accumulate(array_to_row(['other' => 'x'], schema(str_schema('other')))); static::assertSame(2, $accumulator->value()); } @@ -28,9 +31,9 @@ public function test_counts_only_non_null_values(): void { $accumulator = new CountAccumulator(ref('value'), flow_context()); - $accumulator->accumulate(row(['value' => 1])); - $accumulator->accumulate(row(['value' => null])); - $accumulator->accumulate(row(['value' => 3])); + $accumulator->accumulate(array_to_row(['value' => 1], schema(int_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => null], schema(int_schema('value', nullable: true)))); + $accumulator->accumulate(array_to_row(['value' => 3], schema(int_schema('value')))); static::assertSame(2, $accumulator->value()); } @@ -51,18 +54,20 @@ public function test_missing_entry_throws_in_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessageMatches('/^Count window function error: /'); - (new CountAccumulator(ref('value'), $context))->accumulate(row(['other' => 'x'])); + (new CountAccumulator(ref('value'), $context))->accumulate(array_to_row([ + 'other' => 'x', + ], schema(str_schema('other')))); } public function test_value_is_idempotent(): void { $accumulator = new CountAccumulator(ref('value'), flow_context()); - $accumulator->accumulate(row(['value' => 1])); + $accumulator->accumulate(array_to_row(['value' => 1], schema(int_schema('value')))); static::assertSame(1, $accumulator->value()); static::assertSame(1, $accumulator->value()); - $accumulator->accumulate(row(['value' => 2])); + $accumulator->accumulate(array_to_row(['value' => 2], schema(int_schema('value')))); static::assertSame(2, $accumulator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/SumAccumulatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/SumAccumulatorTest.php index 12c299def2..2b66e26b8c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/SumAccumulatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/SumAccumulatorTest.php @@ -8,10 +8,14 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Window\Accumulator\SumAccumulator; +use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class SumAccumulatorTest extends FlowTestCase { @@ -24,8 +28,8 @@ public function test_exact_as_scalar_function_is_resolved_per_row(): void { $accumulator = new SumAccumulator(ref('value'), lit(true), flow_context()); - $accumulator->accumulate(row(['value' => 0.1])); - $accumulator->accumulate(row(['value' => 0.2])); + $accumulator->accumulate(array_to_row(['value' => 0.1], schema(float_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 0.2], schema(float_schema('value')))); static::assertSame(0.3, $accumulator->value()); } @@ -34,8 +38,8 @@ public function test_exact_sum_avoids_floating_point_drift(): void { $accumulator = new SumAccumulator(ref('value'), true, flow_context()); - $accumulator->accumulate(row(['value' => 0.1])); - $accumulator->accumulate(row(['value' => 0.2])); + $accumulator->accumulate(array_to_row(['value' => 0.1], schema(float_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 0.2], schema(float_schema('value')))); static::assertSame(0.3, $accumulator->value()); } @@ -44,8 +48,8 @@ public function test_inexact_sum_keeps_native_addition(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(row(['value' => 0.1])); - $accumulator->accumulate(row(['value' => 0.2])); + $accumulator->accumulate(array_to_row(['value' => 0.1], schema(float_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 0.2], schema(float_schema('value')))); static::assertSame(0.1 + 0.2, $accumulator->value()); } @@ -56,17 +60,19 @@ public function test_missing_entry_throws_in_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessageMatches('/^Sum window function error: /'); - (new SumAccumulator(ref('value'), false, $context))->accumulate(row(['other' => 'x'])); + (new SumAccumulator(ref('value'), false, $context))->accumulate(array_to_row([ + 'other' => 'x', + ], schema(str_schema('other')))); } public function test_non_numeric_values_are_skipped(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(row(['value' => 10])); - $accumulator->accumulate(row(['value' => 'not a number'])); - $accumulator->accumulate(row(['value' => null])); - $accumulator->accumulate(row(['value' => 5])); + $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 'not a number'], schema(str_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => null], schema(str_schema('value', nullable: true)))); + $accumulator->accumulate(array_to_row(['value' => 5], schema(int_schema('value')))); static::assertSame(15, $accumulator->value()); } @@ -75,8 +81,8 @@ public function test_numeric_strings_are_summed(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(row(['value' => '10'])); - $accumulator->accumulate(row(['value' => '2.5'])); + $accumulator->accumulate(array_to_row(['value' => '10'], schema(str_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => '2.5'], schema(str_schema('value')))); static::assertSame(12.5, $accumulator->value()); } @@ -85,7 +91,7 @@ public function test_only_non_numeric_values_still_sums_to_null(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(row(['value' => null])); + $accumulator->accumulate(array_to_row(['value' => null], schema(str_schema('value', nullable: true)))); static::assertNull($accumulator->value()); } @@ -93,12 +99,12 @@ public function test_only_non_numeric_values_still_sums_to_null(): void public function test_value_is_idempotent(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(row(['value' => 10])); + $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); static::assertSame(10, $accumulator->value()); static::assertSame(10, $accumulator->value()); - $accumulator->accumulate(row(['value' => 5])); + $accumulator->accumulate(array_to_row(['value' => 5], schema(int_schema('value')))); static::assertSame(15, $accumulator->value()); } @@ -107,8 +113,8 @@ public function test_whole_float_result_stays_float(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(row(['value' => 1.5])); - $accumulator->accumulate(row(['value' => 2.5])); + $accumulator->accumulate(array_to_row(['value' => 1.5], schema(float_schema('value')))); + $accumulator->accumulate(array_to_row(['value' => 2.5], schema(float_schema('value')))); static::assertSame(4.0, $accumulator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerFrameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerFrameTest.php index 72b0c5418d..65ebcd9851 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerFrameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerFrameTest.php @@ -8,10 +8,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Window\PeerFrame; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -20,7 +20,7 @@ final class PeerFrameTest extends FlowTestCase { public function test_all_rows_tied_covers_the_whole_partition(): void { - $partition = rows(schema(int_schema('d')), row(['d' => 1]), row(['d' => 1]), row(['d' => 1])); + $partition = array_to_rows([['d' => 1], ['d' => 1], ['d' => 1]], schema(int_schema('d'))); $frame = new PeerFrame([ref('d')]); @@ -31,12 +31,11 @@ public function test_all_rows_tied_covers_the_whole_partition(): void public function test_datetime_peers_are_matched_by_value_not_identity(): void { - $partition = rows( - schema(datetime_schema('d')), - row(['d' => new DateTimeImmutable('2024-01-01 00:00:00')]), - row(['d' => new DateTimeImmutable('2024-01-01 00:00:00')]), - row(['d' => new DateTimeImmutable('2024-01-02 00:00:00')]), - ); + $partition = array_to_rows([ + ['d' => new DateTimeImmutable('2024-01-01 00:00:00')], + ['d' => new DateTimeImmutable('2024-01-01 00:00:00')], + ['d' => new DateTimeImmutable('2024-01-02 00:00:00')], + ], schema(datetime_schema('d'))); $frame = new PeerFrame([ref('d')]); @@ -52,11 +51,9 @@ public function test_index_past_the_partition_end_is_empty(): void public function test_multiple_order_by_references_must_all_match(): void { - $partition = rows( + $partition = array_to_rows( + [['a' => 'x', 'b' => 1], ['a' => 'x', 'b' => 1], ['a' => 'x', 'b' => 2]], schema(str_schema('a'), int_schema('b')), - row(['a' => 'x', 'b' => 1]), - row(['a' => 'x', 'b' => 1]), - row(['a' => 'x', 'b' => 2]), ); $frame = new PeerFrame([ref('a'), ref('b')]); @@ -67,7 +64,7 @@ public function test_multiple_order_by_references_must_all_match(): void public function test_ties_extend_the_frame_to_the_last_peer(): void { - $partition = rows(schema(int_schema('d')), row(['d' => 1]), row(['d' => 1]), row(['d' => 2]), row(['d' => 3])); + $partition = array_to_rows([['d' => 1], ['d' => 1], ['d' => 2], ['d' => 3]], schema(int_schema('d'))); $frame = new PeerFrame([ref('d')]); @@ -79,7 +76,7 @@ public function test_ties_extend_the_frame_to_the_last_peer(): void public function test_without_ties_the_frame_ends_at_the_current_row(): void { - $partition = rows(schema(int_schema('d')), row(['d' => 1]), row(['d' => 2]), row(['d' => 3])); + $partition = array_to_rows([['d' => 1], ['d' => 2], ['d' => 3]], schema(int_schema('d'))); $frame = new PeerFrame([ref('d')]); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php index 3eb0614f35..d77917053c 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php @@ -16,9 +16,8 @@ use Flow\Floe\FloeWriter; use Flow\Floe\Options; +use function Flow\ETL\DSL\array_to_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; use function Flow\Filesystem\DSL\path; @@ -64,7 +63,7 @@ public static function writePartitionedFiles(Filesystem $filesystem, string $roo self::writeAll( self::phpWriter($filesystem, $schema), path($root . '/country=' . $country . '/data.floe'), - [rows($schema, row(['id' => $id]))], + [array_to_rows([['id' => $id]], $schema)], ); } } @@ -81,7 +80,7 @@ public static function writeYearPartitionedFiles(Filesystem $filesystem, string self::writeAll( self::phpWriter($filesystem, $schema), path($root . '/year=' . $year . '/data.floe'), - [rows($schema, row(['id' => $id]))], + [array_to_rows([['id' => $id]], $schema)], ); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php index efa1973663..d055fea43b 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php @@ -13,6 +13,7 @@ use function array_keys; use function Flow\ETL\DSL\append; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\from_array; @@ -22,8 +23,6 @@ use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\overwrite; use function Flow\ETL\DSL\partition_by; -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\time_zone_schema; @@ -74,11 +73,10 @@ public function test_a_timezone_column_round_trips_through_floe(): void $path = $this->cacheDir->suffix('timezones.floe'); data_frame() - ->read(from_rows(rows( - schema(time_zone_schema('tz')), - row(['tz' => type_time_zone()->cast('Europe/Warsaw')]), - row(['tz' => type_time_zone()->cast('UTC')]), - ))) + ->read(from_rows(array_to_rows([ + ['tz' => type_time_zone()->cast('Europe/Warsaw')], + ['tz' => type_time_zone()->cast('UTC')], + ], schema(time_zone_schema('tz'))))) ->write(to_floe($path)->saveMode(overwrite())) ->run(); @@ -131,10 +129,10 @@ public function test_list_of_json_round_trip(): void $path = $this->cacheDir->suffix('list-json.floe'); data_frame() - ->read(from_rows(rows( - schema(list_schema('json_list', type_list(type_json()))), - row(['json_list' => [Json::fromArray(['a' => 1]), Json::fromArray([1, 'b'])]]), - ))) + ->read(from_rows(array_to_rows([['json_list' => [ + Json::fromArray(['a' => 1]), + Json::fromArray([1, 'b']), + ]]], schema(list_schema('json_list', type_list(type_json())))))) ->write(to_floe($path)->saveMode(overwrite())) ->run(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php index 0ec907453d..789ed43f41 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php @@ -11,11 +11,10 @@ use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\Tests\Context\FloeStreamReaderContext; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\df; 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; use function Flow\Floe\DSL\from_floe; use function Flow\Types\DSL\type_datetime; @@ -27,12 +26,12 @@ public function test_a_glob_declares_an_approximate_row_count(): void FloeStreamReaderContext::write( $this->fs(), $this->cacheDir->suffix('glob/a.floe'), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); FloeStreamReaderContext::write( $this->fs(), $this->cacheDir->suffix('glob/b.floe'), - rows(schema(int_schema('id')), row(['id' => 3])), + array_to_rows([['id' => 3]], schema(int_schema('id'))), ); $firstBytes = FloeStreamReaderContext::dataBytes($this->fs(), $this->cacheDir->suffix('glob/a.floe')); @@ -48,11 +47,10 @@ public function test_a_glob_declares_an_approximate_row_count(): void public function test_a_single_file_declares_exact_rows_and_byte_size(): void { $path = $this->cacheDir->suffix('single.floe'); - FloeStreamReaderContext::write( - $this->fs(), - $path, - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), - ); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id')))); $statistics = from_floe($path, filesystem: $this->fs())->statistics(); @@ -66,11 +64,10 @@ public function test_a_single_file_declares_exact_rows_and_byte_size(): void public function test_an_offset_is_subtracted_from_the_row_count(): void { $path = $this->cacheDir->suffix('offset.floe'); - FloeStreamReaderContext::write( - $this->fs(), - $path, - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), - ); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id')))); $extractor = from_floe($path, filesystem: $this->fs()); @@ -82,7 +79,7 @@ public function test_an_offset_is_subtracted_from_the_row_count(): void public function test_statistics_are_computed_at_most_once(): void { $path = $this->cacheDir->suffix('memo.floe'); - FloeStreamReaderContext::write($this->fs(), $path, rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); $filesystem = new CountingFilesystem($this->fs()); $extractor = from_floe($path, filesystem: $filesystem); @@ -94,7 +91,7 @@ public function test_statistics_are_computed_at_most_once(): void public function test_schema_then_statistics_reads_the_footer_once(): void { $path = $this->cacheDir->suffix('schema-first.floe'); - FloeStreamReaderContext::write($this->fs(), $path, rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); $filesystem = new CountingFilesystem($this->fs()); $extractor = from_floe($path, filesystem: $filesystem); @@ -107,7 +104,7 @@ public function test_schema_then_statistics_reads_the_footer_once(): void public function test_a_declared_schema_still_reads_the_footer_for_statistics(): void { $path = $this->cacheDir->suffix('declared.floe'); - FloeStreamReaderContext::write($this->fs(), $path, rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); static::assertEquals( Cardinality::exact(1), @@ -120,12 +117,12 @@ public function test_union_by_name_sums_every_footer_exactly(): void FloeStreamReaderContext::write( $this->fs(), $this->cacheDir->suffix('union/a.floe'), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); FloeStreamReaderContext::write( $this->fs(), $this->cacheDir->suffix('union/b.floe'), - rows(schema(int_schema('id')), row(['id' => 3])), + array_to_rows([['id' => 3]], schema(int_schema('id'))), ); $statistics = from_floe($this->cacheDir->suffix('union/*.floe'), filesystem: $this->fs()) @@ -145,7 +142,7 @@ public function test_union_by_name_sums_every_footer_exactly(): void public function test_union_by_name_invalidates_the_memo(): void { $path = $this->cacheDir->suffix('union-memo.floe'); - FloeStreamReaderContext::write($this->fs(), $path, rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); $filesystem = new CountingFilesystem($this->fs()); $extractor = from_floe($path, filesystem: $filesystem); @@ -158,14 +155,10 @@ public function test_union_by_name_invalidates_the_memo(): void public function test_declared_zone_rezones_a_utc_file(): void { $path = $this->cacheDir->suffix('utc.floe'); - FloeStreamReaderContext::write( - $this->fs(), - $path, - rows( - schema(datetime_schema('at')), - row(['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC'))]), - ), - ); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['at' => new DateTimeImmutable( + '2026-01-02 03:04:05', + new DateTimeZone('UTC'), + )]], schema(datetime_schema('at')))); static::assertSame( '2026-01-02 04:04:05 Europe/Warsaw', @@ -189,18 +182,18 @@ public function test_two_files_read_in_the_first_footer_zone(): void FloeStreamReaderContext::write( $this->fs(), $this->cacheDir->suffix('zones/a.floe'), - rows( - schema(datetime_schema('at', zone: 'Europe/Warsaw')), - row(['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('Europe/Warsaw'))]), - ), + array_to_rows([['at' => new DateTimeImmutable( + '2026-01-02 03:04:05', + new DateTimeZone('Europe/Warsaw'), + )]], schema(datetime_schema('at', zone: 'Europe/Warsaw'))), ); FloeStreamReaderContext::write( $this->fs(), $this->cacheDir->suffix('zones/b.floe'), - rows( - schema(datetime_schema('at')), - row(['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC'))]), - ), + array_to_rows([['at' => new DateTimeImmutable( + '2026-01-02 03:04:05', + new DateTimeZone('UTC'), + )]], schema(datetime_schema('at'))), ); $zones = []; diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeMergeDSLTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeMergeDSLTest.php index 85710a10cf..464013871c 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeMergeDSLTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeMergeDSLTest.php @@ -7,9 +7,8 @@ use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\Tests\Context\FloeStreamReaderContext; +use function Flow\ETL\DSL\array_to_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; use function Flow\Floe\DSL\merge_floe; @@ -21,13 +20,13 @@ public function test_merge_floe_compact_over_path_objects(): void $b = $this->cacheDir->suffix('mc-b.floe'); $out = $this->cacheDir->suffix('mc-out.floe'); - FloeStreamReaderContext::write($this->fs(), $a, rows(schema(int_schema('id')), row(['id' => 1]))); - FloeStreamReaderContext::write($this->fs(), $b, rows(schema(int_schema('id')), row(['id' => 2]))); + FloeStreamReaderContext::write($this->fs(), $a, array_to_rows([['id' => 1]], schema(int_schema('id')))); + FloeStreamReaderContext::write($this->fs(), $b, array_to_rows([['id' => 2]], schema(int_schema('id')))); merge_floe([$a, $b], $out, compact: true); static::assertEquals( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), FloeStreamReaderContext::readAll($this->fs(), $out), ); } @@ -38,13 +37,13 @@ public function test_merge_floe_splices_local_files_from_string_paths(): void $b = $this->cacheDir->suffix('ms-b.floe'); $out = $this->cacheDir->suffix('ms-out.floe'); - FloeStreamReaderContext::write($this->fs(), $a, rows(schema(int_schema('id')), row(['id' => 1]))); - FloeStreamReaderContext::write($this->fs(), $b, rows(schema(int_schema('id')), row(['id' => 2]))); + FloeStreamReaderContext::write($this->fs(), $a, array_to_rows([['id' => 1]], schema(int_schema('id')))); + FloeStreamReaderContext::write($this->fs(), $b, array_to_rows([['id' => 2]], schema(int_schema('id')))); merge_floe([$a->path(), $b->path()], $out->path()); static::assertEquals( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), FloeStreamReaderContext::readAll($this->fs(), $out), ); } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStatisticsTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStatisticsTest.php index a7c0cbeedb..917d4b250e 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStatisticsTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStatisticsTest.php @@ -8,9 +8,8 @@ use Flow\Floe\FloeWriter; use Flow\Floe\Tests\Context\FloeStreamReaderContext; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; use function Flow\Floe\DSL\merge_floe; @@ -23,12 +22,11 @@ public function test_a_compacted_merge_reports_the_same_rows_as_a_spliced_one(): $b = $this->cacheDir->suffix('compact-b.floe'); $spliced = $this->cacheDir->suffix('compact-spliced.floe'); $compacted = $this->cacheDir->suffix('compact-compacted.floe'); - FloeStreamReaderContext::write( - $this->fs(), - $a, - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), - ); - FloeStreamReaderContext::write($this->fs(), $b, rows(schema(int_schema('id')), row(['id' => 3]))); + FloeStreamReaderContext::write($this->fs(), $a, array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id')))); + FloeStreamReaderContext::write($this->fs(), $b, array_to_rows([['id' => 3]], schema(int_schema('id')))); merge_floe([$a, $b], $spliced); merge_floe([$a, $b], $compacted, compact: true); @@ -46,8 +44,12 @@ public function test_a_merged_file_reports_the_output_byte_size_not_the_inputs() $a = $this->cacheDir->suffix('splice-a.floe'); $b = $this->cacheDir->suffix('splice-b.floe'); $out = $this->cacheDir->suffix('splice-out.floe'); - FloeStreamReaderContext::write($this->fs(), $a, rows(schema(str_schema('name')), row(['name' => 'first']))); - FloeStreamReaderContext::write($this->fs(), $b, rows(schema(str_schema('name')), row(['name' => 'second']))); + FloeStreamReaderContext::write($this->fs(), $a, array_to_rows([[ + 'name' => 'first', + ]], schema(str_schema('name')))); + FloeStreamReaderContext::write($this->fs(), $b, array_to_rows([[ + 'name' => 'second', + ]], schema(str_schema('name')))); merge_floe([$a, $b], $out); @@ -68,14 +70,14 @@ public function test_a_merged_file_reports_the_output_byte_size_not_the_inputs() public function test_a_multi_section_file_sums_its_sections(): void { $path = $this->cacheDir->suffix('sections.floe'); - FloeStreamReaderContext::write($this->fs(), $path, rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); foreach ([[2, 3], [4, 5, 6]] as $ids) { $writer = new FloeWriter($this->fs(), schema(int_schema('id'))); $writer->append($path); foreach ($ids as $id) { - $writer->write(rows(schema(int_schema('id')), row(['id' => $id]))); + $writer->write(array_to_rows([['id' => $id]], schema(int_schema('id')))); } $writer->close(); @@ -97,11 +99,10 @@ public function test_a_multi_section_file_sums_its_sections(): void public function test_a_written_file_reports_its_rows_and_byte_size(): void { $path = $this->cacheDir->suffix('written.floe'); - FloeStreamReaderContext::write( - $this->fs(), - $path, - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), - ); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id')))); $statistics = FloeStreamReaderContext::footer($this->fs(), $path)->statistics; @@ -113,12 +114,12 @@ public function test_a_written_file_reports_its_rows_and_byte_size(): void public function test_an_appended_file_reports_the_combined_totals(): void { $path = $this->cacheDir->suffix('appended.floe'); - FloeStreamReaderContext::write($this->fs(), $path, rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); $before = FloeStreamReaderContext::footer($this->fs(), $path)->statistics->byteSize; $writer = new FloeWriter($this->fs(), schema(int_schema('id'))); $writer->append($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 2]), row(['id' => 3]))); + $writer->write(array_to_rows([['id' => 2], ['id' => 3]], schema(int_schema('id')))); $writer->close(); $statistics = FloeStreamReaderContext::footer($this->fs(), $path)->statistics; diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php index 118c2846ed..540e5d4823 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php @@ -10,9 +10,8 @@ use Flow\Floe\FloeWriter; use Flow\Floe\Tests\Mother\RowsMother; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; @@ -28,22 +27,25 @@ public function test_merged_multi_schema_file_reads_seamlessly(): void $fileTwo = $this->cacheDir->suffix('evolving-2.floe'); $fileThree = $this->cacheDir->suffix('evolving-3.floe'); - $rowsOne = rows(schema(int_schema('id')), row(['id' => 1])); + $rowsOne = array_to_rows([['id' => 1]], schema(int_schema('id'))); $writer = new FloeWriter($this->fs(), $rowsOne->schema()); $writer->create($fileOne); $writer->write($rowsOne); $writer->close(); - $rowsTwo = rows( + $rowsTwo = array_to_rows( + [['id' => 2, 'email' => null]], schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 2, 'email' => null]), ); $writer = new FloeWriter($this->fs(), $rowsTwo->schema()); $writer->create($fileTwo); $writer->write($rowsTwo); $writer->close(); - $rowsThree = rows(schema(int_schema('id'), str_schema('email')), row(['id' => 3, 'email' => 'third@flow.php'])); + $rowsThree = array_to_rows( + [['id' => 3, 'email' => 'third@flow.php']], + schema(int_schema('id'), str_schema('email')), + ); $writer = new FloeWriter($this->fs(), $rowsThree->schema()); $writer->create($fileThree); $writer->write($rowsThree); @@ -71,18 +73,18 @@ public function test_file_larger_than_compaction_threshold_round_trips(): void { $path = $this->cacheDir->suffix('large.floe'); - $schema = rows( + $schema = array_to_rows( + [['id' => 0, 'payload' => str_pad('row_0', 300, 'x')]], schema(int_schema('id'), str_schema('payload')), - row(['id' => 0, 'payload' => str_pad('row_0', 300, 'x')]), )->schema(); $writer = new FloeWriter($this->fs(), $schema); $writer->create($path); $written = 0; for ($i = 0; $i < 4000; $i++) { - $writer->write(rows( + $writer->write(array_to_rows( + [['id' => $i, 'payload' => str_pad('row_' . $i, 300, 'x')]], schema(int_schema('id'), str_schema('payload')), - row(['id' => $i, 'payload' => str_pad('row_' . $i, 300, 'x')]), )); $written++; } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php index 0a6f4e12e3..85c5b55d25 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php @@ -13,10 +13,9 @@ use Flow\Floe\Tests\Context\FloeStreamReaderContext; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\float_schema; 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; use function Flow\ETL\DSL\str_schema; @@ -27,27 +26,27 @@ public static function rejected_values(): array return [ 'string into int' => [ schema(int_schema('id')), - rows(schema(str_schema('id')), row(['id' => 'AB-1'])), + array_to_rows([['id' => 'AB-1']], schema(str_schema('id'))), 'expected: id, given: id', ], 'float into int' => [ schema(int_schema('id')), - rows(schema(float_schema('id')), row(['id' => 1.5])), + array_to_rows([['id' => 1.5]], schema(float_schema('id'))), 'expected: id, given: id', ], 'int into string' => [ schema(str_schema('name')), - rows(schema(int_schema('name')), row(['name' => 1000])), + array_to_rows([['name' => 1000]], schema(int_schema('name'))), 'expected: name, given: name', ], 'null into non nullable' => [ schema(str_schema('name')), - rows(schema(str_schema('name', nullable: true)), row(['name' => null])), + array_to_rows([['name' => null]], schema(str_schema('name', nullable: true))), 'expected: name, given: name', ], 'undeclared column' => [ schema(int_schema('id')), - rows(schema(int_schema('id'), int_schema('extra')), row(['id' => 1, 'extra' => 2])), + array_to_rows([['id' => 1, 'extra' => 2]], schema(int_schema('id'), int_schema('extra'))), 'new column "extra"', ], ]; @@ -84,10 +83,10 @@ public function test_a_rejected_batch_leaves_previously_written_rows_readable(): $path = $this->cacheDir->suffix('contract-survivor.floe'); $writer = new FloeWriter($this->fs(), schema(int_schema('id')), new Options()); $writer->create($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))); + $writer->write(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); try { - $writer->write(rows(schema(str_schema('id')), row(['id' => 'AB-1']))); + $writer->write(array_to_rows([['id' => 'AB-1']], schema(str_schema('id')))); static::fail('rejected batch was accepted'); } catch (IncompatibleSchemaException) { } @@ -111,11 +110,11 @@ public function test_a_batch_omitting_a_nullable_column_still_writes(): void new Options(), ); $writer->create($path); - $writer->write(rows( + $writer->write(array_to_rows( + [['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name', nullable: true)), - row(['id' => 1, 'name' => 'a']), )); - $writer->write(rows(schema(int_schema('id')), row(['id' => 2]))); + $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); $writer->close(); static::assertSame( @@ -133,11 +132,11 @@ public function test_a_batch_omitting_a_not_null_column_is_refused(): void $path = $this->cacheDir->suffix('contract-absent-not-null.floe'); $writer = new FloeWriter($this->fs(), schema(int_schema('id'), str_schema('name')), new Options()); $writer->create($path); - $writer->write(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a']))); + $writer->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('Missing Definitions'); - $writer->write(rows(schema(int_schema('id')), row(['id' => 2]))); + $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Mother/RowsMother.php b/src/core/etl/tests/Flow/Floe/Tests/Mother/RowsMother.php index 36889fb1a2..d49761e8bc 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Mother/RowsMother.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Mother/RowsMother.php @@ -13,6 +13,7 @@ use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; @@ -23,7 +24,6 @@ use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\null_schema; -use function Flow\ETL\DSL\row; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -56,9 +56,9 @@ public static function empty(): Rows public static function ids(int $from, int $to): Rows { - return rows( + return array_to_rows( + array_map(static fn(int $id) => ['id' => $id], range($from, $to)), schema(int_schema('id')), - ...array_map(static fn(int $id) => row(['id' => $id]), range($from, $to)), ); } @@ -67,27 +67,24 @@ public static function ids(int $from, int $to): Rows */ public static function numbered(int $count): Rows { - return rows( - schema(int_schema('id'), str_schema('name', nullable: true), datetime_schema('at')), - ...array_map( - static fn(int $id) => row([ + return array_to_rows( + array_map( + static fn(int $id) => [ 'id' => $id, 'name' => ($id % 4) === 0 ? null : 'user_' . $id, 'at' => (new DateTimeImmutable('2026-01-01 00:00:00.000001 +00:00'))->modify("+{$id} hours"), - ]), + ], range(1, $count), ), + schema(int_schema('id'), str_schema('name', nullable: true), datetime_schema('at')), ); } public static function heterogeneous(): Rows { - return rows( + return array_to_rows( + [['a' => 1, 'b' => 'x'], ['a' => 2, 'b' => 'y'], ['a' => 3, 'c' => 1.5], ['b' => 'z', 'a' => 4]], schema(int_schema('a'), str_schema('b', nullable: true), float_schema('c', nullable: true)), - row(['a' => 1, 'b' => 'x']), - row(['a' => 2, 'b' => 'y']), - row(['a' => 3, 'c' => 1.5]), - row(['b' => 'z', 'a' => 4]), ); } @@ -106,36 +103,8 @@ public static function withAllEntryTypes(): Rows 'b' => type_string(), ]); - return rows( - schema( - int_schema('int'), - int_schema('int_min'), - int_schema('int_max'), - float_schema('float'), - bool_schema('bool'), - str_schema('string'), - str_schema('string_binary'), - str_schema('string_unicode'), - str_schema('string_null', nullable: true), - null_schema('string_from_null'), - datetime_schema('datetime_immutable', zone: 'Europe/Warsaw'), - datetime_schema('datetime_mutable', zone: 'America/New_York'), - datetime_schema('datetime_before_epoch'), - date_schema('date'), - time_schema('time'), - uuid_schema('uuid'), - json_schema('json'), - json_schema('json_object'), - enum_schema('enum_backed', BackedStringEnum::class), - enum_schema('enum_basic', BasicEnum::class), - list_schema('list', type_list(type_integer())), - map_schema('map', type_map(type_string(), type_integer())), - structure_schema('structure', $structure), - structure_schema('structure_interleaved', $interleaved), - xml_schema('xml'), - xml_element_schema('xml_element'), - ), - row([ + return array_to_rows( + [[ 'int' => 42, 'int_min' => PHP_INT_MIN, 'int_max' => PHP_INT_MAX, @@ -165,7 +134,35 @@ enum_schema('enum_basic', BasicEnum::class), 'structure_interleaved' => $interleaved->cast(['z' => 1, 'b' => 'x']), 'xml' => type_xml()->cast('text & entity'), 'xml_element' => type_xml_element()->cast('value'), - ]), + ]], + schema( + int_schema('int'), + int_schema('int_min'), + int_schema('int_max'), + float_schema('float'), + bool_schema('bool'), + str_schema('string'), + str_schema('string_binary'), + str_schema('string_unicode'), + str_schema('string_null', nullable: true), + null_schema('string_from_null'), + datetime_schema('datetime_immutable', zone: 'Europe/Warsaw'), + datetime_schema('datetime_mutable', zone: 'America/New_York'), + datetime_schema('datetime_before_epoch'), + date_schema('date'), + time_schema('time'), + uuid_schema('uuid'), + json_schema('json'), + json_schema('json_object'), + enum_schema('enum_backed', BackedStringEnum::class), + enum_schema('enum_basic', BasicEnum::class), + list_schema('list', type_list(type_integer())), + map_schema('map', type_map(type_string(), type_integer())), + structure_schema('structure', $structure), + structure_schema('structure_interleaved', $interleaved), + xml_schema('xml'), + xml_element_schema('xml_element'), + ), ); } } 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 a7c83cbb20..9e5cafa093 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php @@ -15,14 +15,13 @@ use Flow\Floe\Tests\Context\FloeFilesContext; use function array_sum; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\partition_types; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\memory_filesystem; @@ -39,13 +38,13 @@ public function test_a_later_file_with_other_columns_throws_naming_both_files(): { $memory = memory_filesystem(); FloeFilesContext::writeFiles($memory, [ - 'memory://glob/a.floe' => rows(schema(int_schema('id')), row(['id' => 1])), - 'memory://glob/b.floe' => rows( - schema(int_schema('id'), str_schema('extra')), - row([ + 'memory://glob/a.floe' => array_to_rows([['id' => 1]], schema(int_schema('id'))), + 'memory://glob/b.floe' => array_to_rows( + [[ 'id' => 2, 'extra' => 'x', - ]), + ]], + schema(int_schema('id'), str_schema('extra')), ), ]); @@ -65,8 +64,8 @@ public function test_a_later_file_with_another_column_type_throws(): void { $memory = memory_filesystem(); FloeFilesContext::writeFiles($memory, [ - 'memory://glob/a.floe' => rows(schema(int_schema('id')), row(['id' => 1])), - 'memory://glob/b.floe' => rows(schema(str_schema('id')), row(['id' => 'x'])), + 'memory://glob/a.floe' => array_to_rows([['id' => 1]], schema(int_schema('id'))), + 'memory://glob/b.floe' => array_to_rows([['id' => 'x']], schema(str_schema('id'))), ]); $this->expectException(InferredSchemaException::class); @@ -81,19 +80,19 @@ public function test_a_later_file_with_the_columns_in_another_order_follows_the_ { $memory = memory_filesystem(); FloeFilesContext::writeFiles($memory, [ - 'memory://glob/a.floe' => rows( - schema(int_schema('id'), str_schema('name')), - row([ + 'memory://glob/a.floe' => array_to_rows( + [[ 'id' => 1, 'name' => 'a', - ]), + ]], + schema(int_schema('id'), str_schema('name')), ), - 'memory://glob/b.floe' => rows( - schema(str_schema('name'), int_schema('id')), - row([ + 'memory://glob/b.floe' => array_to_rows( + [[ 'name' => 'b', 'id' => 2, - ]), + ]], + schema(str_schema('name'), int_schema('id')), ), ]); @@ -110,13 +109,13 @@ public function test_union_by_name_reads_every_file_under_one_schema(): void { $memory = memory_filesystem(); FloeFilesContext::writeFiles($memory, [ - 'memory://glob/a.floe' => rows(schema(int_schema('id')), row(['id' => 1])), - 'memory://glob/b.floe' => rows( - schema(int_schema('id'), str_schema('extra')), - row([ + 'memory://glob/a.floe' => array_to_rows([['id' => 1]], schema(int_schema('id'))), + 'memory://glob/b.floe' => array_to_rows( + [[ 'id' => 2, 'extra' => 'x', - ]), + ]], + schema(int_schema('id'), str_schema('extra')), ), ]); @@ -136,7 +135,7 @@ public function test_extract_adds_input_file_uri_when_configured(): void $path = path('memory://input-uri.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); $loader->closure($context); $extractor = from_floe($path, filesystem: $memory)->withMetadataColumns(true); @@ -152,7 +151,7 @@ public function test_extract_applies_offset_within_a_file(): void $path = path('memory://offset-within.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), $context); + $loader->load(array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), $context); $loader->closure($context); $ids = []; @@ -173,7 +172,7 @@ public function test_extract_honors_limit(): void $path = path('memory://limited.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), $context); + $loader->load(array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), $context); $loader->closure($context); $extractor = from_floe($path, filesystem: $memory); @@ -196,7 +195,7 @@ public function test_extract_omits_input_file_uri_by_default(): void $path = path('memory://no-input-uri.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); $loader->closure($context); $batches = iterator_to_array(from_floe($path, filesystem: $memory)->extract($context)); @@ -211,7 +210,7 @@ public function test_extract_reads_rows(): void $path = path('memory://read.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), $context); + $loader->load(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), $context); $loader->closure($context); $ids = []; @@ -232,10 +231,10 @@ public function test_extract_skips_whole_files_with_offset(): void foreach (['a' => [1, 2], 'b' => [10, 11]] as $name => $values) { $loader = to_floe(path('memory://skip-files/' . $name . '.floe'), filesystem: $memory); - $loader->load( - rows(schema(int_schema('id')), row(['id' => $values[0]]), row(['id' => $values[1]])), - $context, - ); + $loader->load(array_to_rows([ + ['id' => $values[0]], + ['id' => $values[1]], + ], schema(int_schema('id'))), $context); $loader->closure($context); } @@ -259,7 +258,7 @@ public function test_extract_stops_on_stop_signal(): void $path = path('memory://stop.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), $context); + $loader->load(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), $context); $loader->closure($context); $generator = from_floe($path, filesystem: $memory)->extract($context); @@ -280,7 +279,7 @@ public function test_extract_yields_the_metadata_column_schema_promises(): void $path = path('memory://declared-with-metadata.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); $loader->closure($context); $extractor = from_floe($path, filesystem: $memory) @@ -307,7 +306,7 @@ public function test_schema_reads_footer_only(): void $path = path('memory://schema.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1])), $context); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); $loader->closure($context); $schema = from_floe($path, filesystem: $memory)->schema(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php index 021a4441fa..7979226c90 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php @@ -8,14 +8,13 @@ use Flow\Floe\Exception\IncompatibleSchemaException; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\partition_by; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\memory_filesystem; @@ -33,7 +32,7 @@ public function test_closure_writes_a_readable_non_torn_file(): void $path = path('memory://closed.floe'); $loader = to_floe($path, filesystem: $memory); - $loader->load(rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), $context); + $loader->load(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), $context); $loader->closure($context); $ids = []; @@ -64,10 +63,9 @@ public function test_inferred_schema_preserves_nullability(): void $loader = to_floe($path, filesystem: $memory); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'note' => 'a'], ['id' => 2, 'note' => null]], schema(int_schema('id'), str_schema('note', nullable: true)), - row(['id' => 1, 'note' => 'a']), - row(['id' => 2, 'note' => null]), ), $context, ); @@ -83,10 +81,9 @@ public function test_load_to_path_without_extension_reports_failure(): void { $this->expectException(RuntimeException::class); - to_floe(path('memory://no-extension'), filesystem: memory_filesystem())->load( - rows(schema(int_schema('id')), row(['id' => 1])), - flow_context(config()), - ); + to_floe(path('memory://no-extension'), filesystem: memory_filesystem())->load(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))), flow_context(config())); } public function test_partitioned_batches_write_one_file_per_partition(): void @@ -98,10 +95,9 @@ public function test_partitioned_batches_write_one_file_per_partition(): void // one batch carrying both combinations: the loader routes it, B39 $loader = to_floe($base, filesystem: $memory)->partitionBy(partition_by('country')); $loader->load( - rows( + array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'US']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'US']), ), $context, ); @@ -130,8 +126,8 @@ public function test_repeated_loads_write_a_single_file(): void $path = path('memory://repeated.floe'); $loader = to_floe($path, filesystem: $memory); - $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); + $loader->load(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), $context); + $loader->load(array_to_rows([['id' => 3]], schema(int_schema('id'))), $context); $loader->closure($context); $ids = []; diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php index 95c7818a84..45bff3fe4d 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php @@ -17,9 +17,9 @@ use PHPUnit\Framework\TestCase; use function chr; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; 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; use function Flow\ETL\DSL\str_schema; @@ -37,9 +37,13 @@ public function test_compact_reads_identically_to_splice(): void FloeStreamReaderContext::write( $fs, path('memory://a.floe'), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), + ); + FloeStreamReaderContext::write( + $fs, + path('memory://b.floe'), + array_to_rows([['id' => 3]], schema(int_schema('id'))), ); - FloeStreamReaderContext::write($fs, path('memory://b.floe'), rows(schema(int_schema('id')), row(['id' => 3]))); (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://splice.floe')); (new FloeMerger($fs))->merge( @@ -57,8 +61,16 @@ public function test_compact_reads_identically_to_splice(): void public function test_compact_coalesces_same_schema_sources_into_one_section(): void { $fs = memory_filesystem(); - FloeStreamReaderContext::write($fs, path('memory://a.floe'), rows(schema(int_schema('id')), row(['id' => 1]))); - FloeStreamReaderContext::write($fs, path('memory://b.floe'), rows(schema(int_schema('id')), row(['id' => 2]))); + FloeStreamReaderContext::write( + $fs, + path('memory://a.floe'), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); + FloeStreamReaderContext::write( + $fs, + path('memory://b.floe'), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + ); (new FloeMerger($fs))->merge( [path('memory://a.floe'), path('memory://b.floe')], @@ -75,12 +87,12 @@ public function test_merge_of_same_columns_in_different_order_re_encodes_instead FloeStreamReaderContext::write( $fs, path('memory://a.floe'), - rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 100])), + array_to_rows([['a' => 1, 'b' => 100]], schema(int_schema('a'), int_schema('b'))), ); FloeStreamReaderContext::write( $fs, path('memory://b.floe'), - rows(schema(int_schema('b'), int_schema('a')), row(['b' => 200, 'a' => 2])), + array_to_rows([['b' => 200, 'a' => 2]], schema(int_schema('b'), int_schema('a'))), ); (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); @@ -102,12 +114,12 @@ public function test_merge_of_same_columns_in_different_order_with_mixed_types_r FloeStreamReaderContext::write( $fs, path('memory://a.floe'), - rows(schema(int_schema('a'), str_schema('b')), row(['a' => 1, 'b' => 'one'])), + array_to_rows([['a' => 1, 'b' => 'one']], schema(int_schema('a'), str_schema('b'))), ); FloeStreamReaderContext::write( $fs, path('memory://b.floe'), - rows(schema(str_schema('b'), int_schema('a')), row(['b' => 'two', 'a' => 2])), + array_to_rows([['b' => 'two', 'a' => 2]], schema(str_schema('b'), int_schema('a'))), ); (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); @@ -124,9 +136,17 @@ public function test_merge_of_same_columns_in_different_order_with_mixed_types_r public function test_empty_source_contributes_no_rows(): void { $fs = memory_filesystem(); - FloeStreamReaderContext::write($fs, path('memory://a.floe'), rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write( + $fs, + path('memory://a.floe'), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); FloeStreamReaderContext::write($fs, path('memory://empty.floe'), rows(schema())); - FloeStreamReaderContext::write($fs, path('memory://b.floe'), rows(schema(int_schema('id')), row(['id' => 2]))); + FloeStreamReaderContext::write( + $fs, + path('memory://b.floe'), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + ); (new FloeMerger($fs))->merge([ path('memory://a.floe'), @@ -135,7 +155,7 @@ public function test_empty_source_contributes_no_rows(): void ], path('memory://out.floe')); static::assertEquals( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), FloeStreamReaderContext::readAll($fs, path('memory://out.floe')), ); } @@ -151,11 +171,15 @@ public function test_empty_sources_list_throws(): void public function test_merging_a_source_that_adds_a_non_nullable_column_throws(): void { $fs = memory_filesystem(); - FloeStreamReaderContext::write($fs, path('memory://a.floe'), rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write( + $fs, + path('memory://a.floe'), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); FloeStreamReaderContext::write( $fs, path('memory://b.floe'), - rows(schema(int_schema('id'), str_schema('email')), row(['id' => 2, 'email' => 'x@y'])), + array_to_rows([['id' => 2, 'email' => 'x@y']], schema(int_schema('id'), str_schema('email'))), ); // "email" is non-nullable in B but absent from A - padding A's rows with null would @@ -172,9 +196,13 @@ public function test_merging_a_source_that_drops_a_non_nullable_column_throws(): FloeStreamReaderContext::write( $fs, path('memory://a.floe'), - rows(schema(int_schema('id'), str_schema('email')), row(['id' => 1, 'email' => 'x@y'])), + array_to_rows([['id' => 1, 'email' => 'x@y']], schema(int_schema('id'), str_schema('email'))), + ); + FloeStreamReaderContext::write( + $fs, + path('memory://b.floe'), + array_to_rows([['id' => 2]], schema(int_schema('id'))), ); - FloeStreamReaderContext::write($fs, path('memory://b.floe'), rows(schema(int_schema('id')), row(['id' => 2]))); $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('Floe merge cannot reconcile the schema of'); @@ -188,9 +216,16 @@ public function test_merging_sources_with_a_nullable_column_pads_missing_rows(): FloeStreamReaderContext::write( $fs, path('memory://a.floe'), - rows(schema(int_schema('id'), str_schema('email', nullable: true)), row(['id' => 1, 'email' => null])), + array_to_rows( + [['id' => 1, 'email' => null]], + schema(int_schema('id'), str_schema('email', nullable: true)), + ), + ); + FloeStreamReaderContext::write( + $fs, + path('memory://b.floe'), + array_to_rows([['id' => 2]], schema(int_schema('id'))), ); - FloeStreamReaderContext::write($fs, path('memory://b.floe'), rows(schema(int_schema('id')), row(['id' => 2]))); (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); @@ -198,10 +233,9 @@ public function test_merging_sources_with_a_nullable_column_pads_missing_rows(): FloeStreamReaderContext::write( $fs, path('memory://reference.floe'), - rows( + array_to_rows( + [['id' => 1, 'email' => null], ['id' => 2]], schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 1, 'email' => null]), - row(['id' => 2]), ), ); @@ -214,14 +248,24 @@ public function test_merging_sources_with_a_nullable_column_pads_missing_rows(): public function test_metadata_is_merged_with_new_keys_winning(): void { $fs = memory_filesystem(); - FloeStreamReaderContext::write($fs, path('memory://a.floe'), rows(schema(int_schema('id')), row(['id' => 1])), [ - 'a' => '1', - 'shared' => 'from-a', - ]); - FloeStreamReaderContext::write($fs, path('memory://b.floe'), rows(schema(int_schema('id')), row(['id' => 2])), [ - 'b' => '2', - 'shared' => 'from-b', - ]); + FloeStreamReaderContext::write( + $fs, + path('memory://a.floe'), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + [ + 'a' => '1', + 'shared' => 'from-a', + ], + ); + FloeStreamReaderContext::write( + $fs, + path('memory://b.floe'), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + [ + 'b' => '2', + 'shared' => 'from-b', + ], + ); (new FloeMerger($fs))->merge( [path('memory://a.floe'), path('memory://b.floe')], @@ -252,12 +296,12 @@ public function test_offset_read_after_merge_seeks_across_sources(): void FloeStreamReaderContext::write( $fs, path('memory://a.floe'), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); FloeStreamReaderContext::write( $fs, path('memory://b.floe'), - rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 4])), + array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))), ); (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); @@ -278,7 +322,7 @@ public function test_offset_read_after_merge_seeks_across_sources(): void public function test_single_source_is_a_copy(): void { $fs = memory_filesystem(); - $value = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $value = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); FloeStreamReaderContext::write($fs, path('memory://a.floe'), $value); (new FloeMerger($fs))->merge([path('memory://a.floe')], path('memory://out.floe')); @@ -289,9 +333,21 @@ public function test_single_source_is_a_copy(): void public function test_splices_three_files(): void { $fs = memory_filesystem(); - FloeStreamReaderContext::write($fs, path('memory://a.floe'), rows(schema(int_schema('id')), row(['id' => 1]))); - FloeStreamReaderContext::write($fs, path('memory://b.floe'), rows(schema(int_schema('id')), row(['id' => 2]))); - FloeStreamReaderContext::write($fs, path('memory://c.floe'), rows(schema(int_schema('id')), row(['id' => 3]))); + FloeStreamReaderContext::write( + $fs, + path('memory://a.floe'), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); + FloeStreamReaderContext::write( + $fs, + path('memory://b.floe'), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + ); + FloeStreamReaderContext::write( + $fs, + path('memory://c.floe'), + array_to_rows([['id' => 3]], schema(int_schema('id'))), + ); (new FloeMerger($fs))->merge([ path('memory://a.floe'), @@ -300,7 +356,7 @@ public function test_splices_three_files(): void ], path('memory://out.floe')); static::assertEquals( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])), + array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), FloeStreamReaderContext::readAll($fs, path('memory://out.floe')), ); } @@ -311,18 +367,18 @@ public function test_splices_two_files_with_the_same_schema(): void FloeStreamReaderContext::write( $fs, path('memory://a.floe'), - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])), + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), ); FloeStreamReaderContext::write( $fs, path('memory://b.floe'), - rows(schema(int_schema('id')), row(['id' => 3]), row(['id' => 4])), + array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))), ); (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); static::assertEquals( - rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), row(['id' => 4])), + array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))), FloeStreamReaderContext::readAll($fs, path('memory://out.floe')), ); } @@ -330,11 +386,15 @@ public function test_splices_two_files_with_the_same_schema(): void public function test_type_conflict_throws(): void { $fs = memory_filesystem(); - FloeStreamReaderContext::write($fs, path('memory://a.floe'), rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write( + $fs, + path('memory://a.floe'), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); FloeStreamReaderContext::write( $fs, path('memory://b.floe'), - rows(schema(str_schema('id')), row(['id' => 'x'])), + array_to_rows([['id' => 'x']], schema(str_schema('id'))), ); $this->expectException(IncompatibleSchemaException::class); @@ -346,7 +406,11 @@ public function test_type_conflict_throws(): void public function test_unsized_source_throws(): void { $fs = memory_filesystem(); - FloeStreamReaderContext::write($fs, path('memory://a.floe'), rows(schema(int_schema('id')), row(['id' => 1]))); + FloeStreamReaderContext::write( + $fs, + path('memory://a.floe'), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ); $this->expectException(FloeException::class); $this->expectExceptionMessage('does not report its size'); @@ -404,12 +468,12 @@ public function test_merge_of_different_datetime_zones_widens_to_utc(): void FloeStreamReaderContext::write( $fs, path('memory://warsaw.floe'), - rows(schema(datetime_schema('at', zone: 'Europe/Warsaw')), row(['at' => $warsaw])), + array_to_rows([['at' => $warsaw]], schema(datetime_schema('at', zone: 'Europe/Warsaw'))), ); FloeStreamReaderContext::write( $fs, path('memory://utc.floe'), - rows(schema(datetime_schema('at')), row(['at' => $utc])), + array_to_rows([['at' => $utc]], schema(datetime_schema('at'))), ); (new FloeMerger($fs))->merge([ diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php index 5380981b21..74703144e7 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php @@ -25,9 +25,8 @@ use function array_map; use function array_slice; use function count; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\schema_from_json; use function Flow\ETL\DSL\str_schema; @@ -65,14 +64,13 @@ public function test_batches_follow_requested_size(): void $filesystem = memory_filesystem(); $path = path('memory://batches.floe'); - $data = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - ); + $data = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -102,7 +100,7 @@ public function test_limit_caps_returned_rows(): void $filesystem = memory_filesystem(); $path = path('memory://limit.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), row(['id' => 4])); + $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -126,7 +124,7 @@ public function test_limit_stops_within_a_batch(): void $filesystem = memory_filesystem(); $path = path('memory://limit-batch.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -183,7 +181,7 @@ public function test_offset_skips_leading_rows_within_a_single_section(): void $filesystem = memory_filesystem(); $path = path('memory://offset-single.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), row(['id' => 4])); + $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -207,15 +205,17 @@ public function test_offset_skips_whole_sections(): void $filesystem = memory_filesystem(); $path = path('memory://offset-sections.floe'); - $data = rows( + $data = array_to_rows( + [ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4, 'email' => 'a'], + ['id' => 5, 'email' => 'b'], + ['id' => 6], + ['id' => 7], + ], schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4, 'email' => 'a']), - row(['id' => 5, 'email' => 'b']), - row(['id' => 6]), - row(['id' => 7]), ); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); @@ -247,7 +247,7 @@ public function test_offset_beyond_total_rows_yields_nothing(): void $filesystem = memory_filesystem(); $path = path('memory://offset-past-end.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -276,7 +276,7 @@ public function test_offset_respects_batch_size(): void $filesystem = memory_filesystem(); $path = path('memory://offset-batches.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), row(['id' => 4])); + $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -299,14 +299,13 @@ public function test_offset_and_limit_combined(): void $filesystem = memory_filesystem(); $path = path('memory://offset-limit.floe'); - $data = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - ); + $data = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -330,15 +329,17 @@ public function test_offset_matches_tail_of_full_read(): void $filesystem = memory_filesystem(); $path = path('memory://offset-tail.floe'); - $data = rows( + $data = array_to_rows( + [ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4, 'email' => 'a'], + ['id' => 5, 'email' => 'b'], + ['id' => 6], + ['id' => 7], + ], schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4, 'email' => 'a']), - row(['id' => 5, 'email' => 'b']), - row(['id' => 6]), - row(['id' => 7]), ); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); @@ -372,7 +373,7 @@ public function test_offset_reads_through_a_custom_identity_codec(): void $filesystem = memory_filesystem(); $path = path('memory://offset-codec.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema(), new Options(codec: new CodecStub(0x00))); $writer->create($path); $writer->write($data); @@ -440,13 +441,13 @@ public function test_dead_footers_of_appended_files_are_skipped(): void $filesystem = memory_filesystem(); $path = path('memory://appended.floe'); - $created = rows(schema(int_schema('id')), row(['id' => 1])); + $created = array_to_rows([['id' => 1]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $created->schema()); $writer->create($path); $writer->write($created); $writer->close(); - $appended = rows(schema(int_schema('id')), row(['id' => 2])); + $appended = array_to_rows([['id' => 2]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $appended->schema()); $writer->append($path); $writer->write($appended); @@ -487,16 +488,15 @@ public function test_evolved_file_rows_match_merged_schema(): void $baseFile = path('memory://evolved-base.floe'); $evolvedFile = path('memory://evolved-new.floe'); - $baseRows = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $baseRows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $baseRows->schema()); $writer->create($baseFile); $writer->write($baseRows); $writer->close(); - $evolvedRows = rows( + $evolvedRows = array_to_rows( + [['id' => 3, 'email' => null], ['id' => 4, 'email' => 'x@flow.php']], schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 3, 'email' => null]), - row(['id' => 4, 'email' => 'x@flow.php']), ); $writer = new FloeWriter($filesystem, $evolvedRows->schema()); $writer->create($evolvedFile); @@ -581,7 +581,7 @@ public function test_footer_accessors(): void $filesystem = memory_filesystem(); $path = path('memory://accessors.floe'); - $data = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'x'])); + $data = array_to_rows([['id' => 1, 'name' => 'x']], schema(int_schema('id'), str_schema('name'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path, Metadata::fromArray(['source' => 'unit'])); $writer->write($data); @@ -631,7 +631,7 @@ public function test_rows_through_a_custom_identity_codec(): void $filesystem = memory_filesystem(); $path = path('memory://custom-codec.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema(), new Options(codec: new CodecStub(0x00))); $writer->create($path); $writer->write($data); @@ -652,10 +652,9 @@ public function test_rows_through_a_custom_identity_codec_with_long_row_body_thr $filesystem = memory_filesystem(); $path = path('memory://custom-codec-long-row.floe'); $schemaBody = FloeSchemaContext::schemaBody(schema(int_schema('id'))); - $rowBody = (new PhpFloeEncoder(schema_from_json($schemaBody)))->encode((new PhpRowHydrator())->dehydrate(rows( - schema(int_schema('id')), - row(['id' => 1]), - )))[0]; + $rowBody = (new PhpFloeEncoder(schema_from_json( + $schemaBody, + )))->encode((new PhpRowHydrator())->dehydrate(array_to_rows([['id' => 1]], schema(int_schema('id')))))[0]; $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); $stream = $filesystem->writeTo($path); $stream->append( @@ -701,10 +700,9 @@ public function test_row_body_longer_than_hydrated_content_throws(): void $filesystem = memory_filesystem(); $path = path('memory://long-row.floe'); $schemaBody = FloeSchemaContext::schemaBody(schema(int_schema('id'))); - $rowBody = (new PhpFloeEncoder(schema_from_json($schemaBody)))->encode((new PhpRowHydrator())->dehydrate(rows( - schema(int_schema('id')), - row(['id' => 1]), - )))[0]; + $rowBody = (new PhpFloeEncoder(schema_from_json( + $schemaBody, + )))->encode((new PhpRowHydrator())->dehydrate(array_to_rows([['id' => 1]], schema(int_schema('id')))))[0]; $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); $stream = $filesystem->writeTo($path); $stream->append( @@ -728,11 +726,9 @@ public function test_torn_file_without_footer_throws_in_strict_mode(): void $filesystem = memory_filesystem(); $path = path('memory://strict-torn.floe'); - FloeStreamReaderContext::writeWithoutFooter( - $filesystem, - $path, - rows(schema(int_schema('id')), row(['id' => 1])), - ); + FloeStreamReaderContext::writeWithoutFooter($filesystem, $path, array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id')))); $this->expectException(FloeException::class); $this->expectExceptionMessage('magic'); @@ -771,14 +767,13 @@ public function test_head_returns_first_rows(): void $filesystem = memory_filesystem(); $path = path('memory://head.floe'); - $data = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - ); + $data = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -802,7 +797,7 @@ public function test_head_count_beyond_total_returns_all_rows(): void $filesystem = memory_filesystem(); $path = path('memory://head-all.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -826,7 +821,7 @@ public function test_head_respects_batch_size(): void $filesystem = memory_filesystem(); $path = path('memory://head-batches.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), row(['id' => 4])); + $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -867,15 +862,17 @@ public function test_tail_returns_last_rows_across_sections(): void $filesystem = memory_filesystem(); $path = path('memory://tail-sections.floe'); - $data = rows( + $data = array_to_rows( + [ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4, 'email' => 'a'], + ['id' => 5, 'email' => 'b'], + ['id' => 6], + ['id' => 7], + ], schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4, 'email' => 'a']), - row(['id' => 5, 'email' => 'b']), - row(['id' => 6]), - row(['id' => 7]), ); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); @@ -903,7 +900,7 @@ public function test_tail_count_beyond_total_returns_all_rows(): void $filesystem = memory_filesystem(); $path = path('memory://tail-all.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -927,7 +924,7 @@ public function test_tail_respects_batch_size(): void $filesystem = memory_filesystem(); $path = path('memory://tail-batches.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3]), row(['id' => 4])); + $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); @@ -950,16 +947,15 @@ public function test_tail_matches_slice_of_full_read(): void $filesystem = memory_filesystem(); $path = path('memory://tail-slice.floe'); - $data = rows( - schema(int_schema('id')), - row(['id' => 1]), - row(['id' => 2]), - row(['id' => 3]), - row(['id' => 4]), - row(['id' => 5]), - row(['id' => 6]), - row(['id' => 7]), - ); + $data = array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ['id' => 6], + ['id' => 7], + ], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php index 04da98eedc..c95f9f3abf 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php @@ -4,7 +4,6 @@ namespace Flow\Floe\Tests\Unit; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\Floe\Exception\FloeException; use Flow\Floe\FloeSerializer; @@ -15,8 +14,8 @@ use PHPUnit\Framework\TestCase; use function array_map; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -33,8 +32,11 @@ final class FloeSerializerTest extends TestCase public static function values(): array { return [ - 'single row' => [rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'John']))], - 'rows' => [rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]))], + 'single row' => [array_to_rows( + [['id' => 1, 'name' => 'John']], + schema(int_schema('id'), str_schema('name')), + )], + 'rows' => [array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))], 'heterogeneous rows' => [RowsMother::heterogeneous()], 'all entry types' => [RowsMother::withAllEntryTypes()], 'empty rows' => [rows(schema())], @@ -75,10 +77,9 @@ public function test_streaming_mode_round_trip(): void public function test_cache_round_trip_preserves_rows_without_a_partition_table(): void { - $value = rows( + $value = array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'PL']], schema(int_schema('id'), str_schema('country')), - row(['id' => 1, 'country' => 'PL']), - row(['id' => 2, 'country' => 'PL']), ); static::assertEquals($value, unserialize_from_string( @@ -93,11 +94,9 @@ public function test_heterogeneous_rows_round_trip_unpadded_but_union_widened(): // one write session = one schema: rows keep their own columns (unpadded) but // entry types widen to the batch union - id and name become nullable because // each is absent from some row. Values are unchanged; only nullability widens. - $value = rows( + $value = array_to_rows( + [['id' => 1], ['id' => 2, 'name' => 'John'], ['name' => 'Jane']], schema(int_schema('id', nullable: true), str_schema('name', nullable: true)), - row(['id' => 1]), - row(['id' => 2, 'name' => 'John']), - row(['name' => 'Jane']), ); $result = unserialize_from_string($serializer, serialize_to_string($serializer, $value)); @@ -131,9 +130,9 @@ public function test_batch_sizes_decode_each_others_bytes(Rows $value): void public function test_batch_size_smaller_than_row_count(): void { $serializer = new FloeSerializer(3); - $value = rows( + $value = array_to_rows( + array_map(static fn(int $id): array => ['id' => $id], range(1, 10)), schema(int_schema('id')), - ...array_map(static fn(int $id): Row => row(['id' => $id]), range(1, 10)), ); static::assertEquals($value, unserialize_from_string($serializer, serialize_to_string( @@ -145,7 +144,7 @@ public function test_batch_size_smaller_than_row_count(): void public function test_batch_size_larger_than_row_count(): void { $serializer = new FloeSerializer(100); - $value = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $value = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); static::assertEquals($value, unserialize_from_string($serializer, serialize_to_string($serializer, $value))); } @@ -176,7 +175,7 @@ public function test_unserialize_rejects_empty_payload(): void public function test_unserialize_rejects_row_count_mismatch(): void { - $bytes = serialize_to_string(new FloeSerializer(), rows(schema(int_schema('id')), row(['id' => 1]))); + $bytes = serialize_to_string(new FloeSerializer(), array_to_rows([['id' => 1]], schema(int_schema('id')))); // inflate the footer's row count while the body still holds a single row; the JSON // byte-length is unchanged (1 -> 2) so the trailer stays valid and the read reaches // the whole-value row-count guard diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php index e5e931fa98..4d23d57bfa 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php @@ -18,9 +18,8 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_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; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; @@ -34,7 +33,7 @@ public function test_close_closes_the_source_stream(): void $filesystem = memory_filesystem(); $path = path('memory://close.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1])); + $data = array_to_rows([['id' => 1]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $data->schema()); $writer->create($path); $writer->write($data); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php index 5b5f9eee36..91ca24a710 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php @@ -15,8 +15,8 @@ use Flow\Floe\Tests\Double\CodecStub; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -30,10 +30,9 @@ public function test_create_on_stream_is_byte_identical_to_path_create(): void $filesystem = memory_filesystem(); $viaCreate = path('memory://via-create.floe'); $viaStream = path('memory://via-stream.floe'); - $data = rows( + $data = array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => 'b']), ); $schema = $data->schema(); @@ -55,11 +54,9 @@ public function test_small_buffer_size_produces_byte_identical_output(): void $filesystem = memory_filesystem(); $default = path('memory://default-buffer.floe'); $tiny = path('memory://tiny-buffer.floe'); - $data = rows( + $data = array_to_rows( + [['id' => 1, 'name' => 'alpha'], ['id' => 2, 'name' => 'beta'], ['id' => 3, 'name' => 'gamma']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'alpha']), - row(['id' => 2, 'name' => 'beta']), - row(['id' => 3, 'name' => 'gamma']), ); $schema = $data->schema(); @@ -82,7 +79,7 @@ public function test_create_on_stream_round_trips(): void $filesystem = memory_filesystem(); $path = path('memory://on-stream.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2]), row(['id' => 3])); + $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); $writer = new FloeStreamWriter($data->schema()); $writer->create($filesystem->writeTo($path), Metadata::fromArray(['source' => 'stream'])); @@ -125,7 +122,7 @@ public function test_write_before_create_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('Floe writer session is not open'); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); } public function test_aligned_multi_batch_session_is_byte_identical_to_a_single_batch(): void @@ -134,17 +131,16 @@ public function test_aligned_multi_batch_session_is_byte_identical_to_a_single_b $multi = path('memory://multi-batch.floe'); $single = path('memory://single-batch.floe'); - $data = rows( + $data = array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => 'b']), ); $schema = $data->schema(); $multiWriter = new FloeStreamWriter($schema); $multiWriter->create($filesystem->writeTo($multi)); - $multiWriter->write(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a']))); - $multiWriter->write(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 2, 'name' => 'b']))); + $multiWriter->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); + $multiWriter->write(array_to_rows([['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')))); $multiWriter->close(); $singleWriter = new FloeStreamWriter($schema); @@ -164,12 +160,15 @@ public function test_batch_omitting_a_nullable_session_column_is_accepted_and_ro $filesystem = memory_filesystem(); $path = path('memory://subset.floe'); - $first = rows(schema(int_schema('id'), str_schema('name', nullable: true)), row(['id' => 1, 'name' => 'a'])); + $first = array_to_rows( + [['id' => 1, 'name' => 'a']], + schema(int_schema('id'), str_schema('name', nullable: true)), + ); $writer = new FloeStreamWriter($first->schema()); $writer->create($filesystem->writeTo($path)); $writer->write($first); - $writer->write(rows(schema(int_schema('id')), row(['id' => 2]))); + $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); $writer->close(); $footer = FloeStreamReaderContext::footer($filesystem, $path); @@ -184,7 +183,7 @@ public function test_batch_omitting_a_nullable_session_column_is_accepted_and_ro */ public function test_batch_omitting_a_not_null_session_column_is_refused(): void { - $first = rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a'])); + $first = array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))); $writer = new FloeStreamWriter($first->schema()); $writer->create(memory_filesystem()->writeTo(path('memory://subset-not-null.floe'))); @@ -193,45 +192,45 @@ public function test_batch_omitting_a_not_null_session_column_is_refused(): void $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('Missing Definitions'); - $writer->write(rows(schema(int_schema('id')), row(['id' => 2]))); + $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); } public function test_batch_introducing_a_new_column_throws_naming_the_column(): void { $writer = new FloeStreamWriter(schema(int_schema('id'))); $writer->create(memory_filesystem()->writeTo(path('memory://new-column.floe'))); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('new column "email"'); - $writer->write(rows(schema(int_schema('id'), str_schema('email')), row(['id' => 2, 'email' => 'x']))); + $writer->write(array_to_rows([['id' => 2, 'email' => 'x']], schema(int_schema('id'), str_schema('email')))); } public function test_batch_with_an_incompatible_type_throws_naming_the_column(): void { $writer = new FloeStreamWriter(schema(int_schema('id'))); $writer->create(memory_filesystem()->writeTo(path('memory://type-drift.floe'))); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('expected: id, given: id'); - $writer->write(rows(schema(str_schema('id')), row(['id' => 'x']))); + $writer->write(array_to_rows([['id' => 'x']], schema(str_schema('id')))); } public function test_new_column_message_names_the_session_schema_and_the_column(): void { $writer = new FloeStreamWriter(schema(int_schema('id'))); $writer->create(memory_filesystem()->writeTo(path('memory://hint.floe'))); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage( 'Floe write session schema is fixed and this batch does not fit it: new column "email".', ); - $writer->write(rows(schema(int_schema('id'), str_schema('email')), row(['id' => 2, 'email' => 'x']))); + $writer->write(array_to_rows([['id' => 2, 'email' => 'x']], schema(int_schema('id'), str_schema('email')))); } public function test_explicit_session_schema_is_used_for_the_footer(): void @@ -241,7 +240,7 @@ public function test_explicit_session_schema_is_used_for_the_footer(): void $writer = new FloeStreamWriter(schema(int_schema('id'), str_schema('name'))); $writer->create($filesystem->writeTo($path)); - $writer->write(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a']))); + $writer->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); $writer->close(); $fileSchema = FloeStreamReaderContext::footer($filesystem, $path)->schema(); @@ -269,7 +268,7 @@ public function test_empty_batch_writes_no_schema_or_section(): void public function test_writing_a_column_name_with_invalid_utf8_throws(): void { - $badRows = rows(schema(str_schema('badÿname')), row(['badÿname' => 'x'])); + $badRows = array_to_rows([['badÿname' => 'x']], schema(str_schema('badÿname'))); $writer = new FloeStreamWriter($badRows->schema()); $writer->create(memory_filesystem()->writeTo(path('memory://bad-name.floe'))); @@ -288,17 +287,16 @@ public function test_multi_batch_is_byte_identical_to_single_batch(): void $filesystem = memory_filesystem(); $multi = path('memory://off-multi.floe'); $single = path('memory://off-single.floe'); - $data = rows( + $data = array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => 'b']), ); $schema = $data->schema(); $multiWriter = new FloeStreamWriter($schema); $multiWriter->create($filesystem->writeTo($multi)); - $multiWriter->write(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 1, 'name' => 'a']))); - $multiWriter->write(rows(schema(int_schema('id'), str_schema('name')), row(['id' => 2, 'name' => 'b']))); + $multiWriter->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); + $multiWriter->write(array_to_rows([['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')))); $multiWriter->close(); $singleWriter = new FloeStreamWriter($schema); @@ -311,7 +309,7 @@ public function test_multi_batch_is_byte_identical_to_single_batch(): void public function test_a_later_null_into_a_non_nullable_session_column_is_rejected(): void { - $first = rows(schema(int_schema('id'), str_schema('opt')), row(['id' => 1, 'opt' => 'present'])); + $first = array_to_rows([['id' => 1, 'opt' => 'present']], schema(int_schema('id'), str_schema('opt'))); $writer = new FloeStreamWriter($first->schema()); $writer->create(memory_filesystem()->writeTo(path('memory://off-present-then-null.floe'))); @@ -320,15 +318,15 @@ public function test_a_later_null_into_a_non_nullable_session_column_is_rejected $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('expected: opt, given: opt'); - $writer->write(rows( + $writer->write(array_to_rows( + [['id' => 2, 'opt' => null]], schema(int_schema('id'), str_schema('opt', nullable: true)), - row(['id' => 2, 'opt' => null]), )); } public function test_validation_on_rejects_a_later_null_into_a_non_nullable_session_column(): void { - $first = rows(schema(int_schema('id'), str_schema('opt')), row(['id' => 1, 'opt' => 'present'])); + $first = array_to_rows([['id' => 1, 'opt' => 'present']], schema(int_schema('id'), str_schema('opt'))); $writer = new FloeStreamWriter($first->schema()); $writer->create(memory_filesystem()->writeTo(path('memory://on-present-then-null.floe'))); @@ -336,9 +334,9 @@ public function test_validation_on_rejects_a_later_null_into_a_non_nullable_sess $this->expectException(IncompatibleSchemaException::class); - $writer->write(rows( + $writer->write(array_to_rows( + [['id' => 2, 'opt' => null]], schema(int_schema('id'), str_schema('opt', nullable: true)), - row(['id' => 2, 'opt' => null]), )); } @@ -355,6 +353,6 @@ public function test_column_absent_from_the_session_schema_throws(): void $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('new column "b"'); - $writer->write(rows(schema(int_schema('a'), int_schema('b')), row(['a' => 1, 'b' => 2]))); + $writer->write(array_to_rows([['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b')))); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php index 63c186c721..e616ba4255 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; @@ -25,8 +26,6 @@ use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\null_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; @@ -62,15 +61,8 @@ final class FloeValueRoundTripTest extends TestCase public function test_datetime_entries(): void { static::assertEquals( - $rows = rows( - schema( - datetime_schema('immutable', zone: 'Europe/Warsaw'), - datetime_schema('mutable', zone: 'America/New_York'), - datetime_schema('offset_timezone', zone: '+02:30'), - datetime_schema('before_epoch'), - date_schema('date'), - ), - row([ + $rows = array_to_rows( + [[ 'immutable' => new DateTimeImmutable( '2025-06-15 12:30:45.123456', new DateTimeZone('Europe/Warsaw'), @@ -79,7 +71,14 @@ public function test_datetime_entries(): void 'offset_timezone' => new DateTimeImmutable('2025-06-15 12:30:45', new DateTimeZone('+02:30')), 'before_epoch' => new DateTimeImmutable('1969-07-20 20:17:00 UTC'), 'date' => new DateTimeImmutable('2025-06-15 00:00:00', new DateTimeZone('UTC')), - ]), + ]], + schema( + datetime_schema('immutable', zone: 'Europe/Warsaw'), + datetime_schema('mutable', zone: 'America/New_York'), + datetime_schema('offset_timezone', zone: '+02:30'), + datetime_schema('before_epoch'), + date_schema('date'), + ), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -87,7 +86,22 @@ public function test_datetime_entries(): void public function test_entries_with_null_values(): void { - $rows = rows( + $rows = array_to_rows( + [[ + 'int' => null, + 'float' => null, + 'bool' => null, + 'str' => null, + 'from_null' => null, + 'list' => null, + 'map' => null, + 'json' => null, + 'uuid' => null, + 'datetime' => null, + 'time' => null, + 'enum' => null, + 'xml' => null, + ]], schema( int_schema('int', nullable: true), float_schema('float', nullable: true), @@ -103,21 +117,6 @@ public function test_entries_with_null_values(): void enum_schema('enum', BackedStringEnum::class, nullable: true), xml_schema('xml', nullable: true), ), - row([ - 'int' => null, - 'float' => null, - 'bool' => null, - 'str' => null, - 'from_null' => null, - 'list' => null, - 'map' => null, - 'json' => null, - 'uuid' => null, - 'datetime' => null, - 'time' => null, - 'enum' => null, - 'xml' => null, - ]), ); static::assertEquals($rows, FloeStreamReaderContext::roundTrip($rows)); @@ -126,9 +125,9 @@ enum_schema('enum', BackedStringEnum::class, nullable: true), public function test_enum_entries(): void { static::assertEquals( - $rows = rows( + $rows = array_to_rows( + [['backed' => BackedStringEnum::two, 'basic' => BasicEnum::three]], schema(enum_schema('backed', BackedStringEnum::class), enum_schema('basic', BasicEnum::class)), - row(['backed' => BackedStringEnum::two, 'basic' => BasicEnum::three]), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -137,10 +136,9 @@ public function test_enum_entries(): void #[RequiresPhp('>= 8.4.0')] public function test_html_entries(): void { - $rows = rows( - schema(html_schema('html')), - row(['html' => type_html()->cast('

hello

')]), - ); + $rows = array_to_rows([[ + 'html' => type_html()->cast('

hello

'), + ]], schema(html_schema('html'))); static::assertSame( type_string()->cast($rows->first()->get('html')), @@ -159,14 +157,14 @@ public function test_interval_entries(): void $fractional->f = 0.123456; static::assertEquals( - $rows = rows( - schema(time_schema('time'), time_schema('negative'), time_schema('fractional'), time_schema('days')), - row([ + $rows = array_to_rows( + [[ 'time' => new DateInterval('PT2H30M15S'), 'negative' => $negative, 'fractional' => $fractional, 'days' => new DateInterval('P3D'), - ]), + ]], + schema(time_schema('time'), time_schema('negative'), time_schema('fractional'), time_schema('days')), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -175,19 +173,19 @@ public function test_interval_entries(): void public function test_json_entries(): void { static::assertEquals( - $rows = rows( + $rows = array_to_rows( + [[ + 'list' => type_json()->cast('[1,2,3]'), + 'object' => type_json()->cast('{"a":1,"b":[true,null]}'), + 'empty_object' => type_json()->cast('{}'), + 'empty_list' => type_json()->cast('[]'), + ]], schema( json_schema('list'), json_schema('object'), json_schema('empty_object'), json_schema('empty_list'), ), - row([ - 'list' => type_json()->cast('[1,2,3]'), - 'object' => type_json()->cast('{"a":1,"b":[true,null]}'), - 'empty_object' => type_json()->cast('{}'), - 'empty_list' => type_json()->cast('[]'), - ]), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -196,7 +194,17 @@ public function test_json_entries(): void public function test_list_entries(): void { static::assertEquals( - $rows = rows( + $rows = array_to_rows( + [[ + 'int' => [1, -2, PHP_INT_MAX], + 'int_empty' => [], + 'float' => [1.5, -2.25], + 'float_empty' => [], + 'string' => ['a', 'b', ''], + 'bool' => [true, false], + 'nullable_int' => [1, null, 3], + 'list_of_lists' => [[1, 2], [3]], + ]], schema( list_schema('int', type_list(type_integer())), list_schema('int_empty', type_list(type_integer())), @@ -207,16 +215,6 @@ public function test_list_entries(): void list_schema('nullable_int', type_list(type_optional(type_integer()))), list_schema('list_of_lists', type_list(type_list(type_integer()))), ), - row([ - 'int' => [1, -2, PHP_INT_MAX], - 'int_empty' => [], - 'float' => [1.5, -2.25], - 'float_empty' => [], - 'string' => ['a', 'b', ''], - 'bool' => [true, false], - 'nullable_int' => [1, null, 3], - 'list_of_lists' => [[1, 2], [3]], - ]), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -225,13 +223,13 @@ public function test_list_entries(): void public function test_map_entries(): void { static::assertEquals( - $rows = rows( + $rows = array_to_rows( + [['string_keys' => ['a' => 1, 'b' => 2], 'int_keys' => [10 => 'x', 20 => 'y'], 'empty' => []]], schema( map_schema('string_keys', type_map(type_string(), type_integer())), map_schema('int_keys', type_map(type_integer(), type_string())), map_schema('empty', type_map(type_string(), type_integer())), ), - row(['string_keys' => ['a' => 1, 'b' => 2], 'int_keys' => [10 => 'x', 20 => 'y'], 'empty' => []]), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -240,13 +238,13 @@ public function test_map_entries(): void public function test_uuid_entries_round_trip_under_format_v2(): void { static::assertEquals( - $rows = rows( - schema(uuid_schema('uuid'), uuid_schema('uuid_max'), str_schema('after')), - row([ + $rows = array_to_rows( + [[ 'uuid' => type_uuid()->cast('0196aecb-b568-7e57-a381-8ec8d3e4a531'), 'uuid_max' => type_uuid()->cast('ffffffff-ffff-ffff-ffff-ffffffffffff'), 'after' => 'not desynchronised', - ]), + ]], + schema(uuid_schema('uuid'), uuid_schema('uuid_max'), str_schema('after')), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -255,7 +253,20 @@ public function test_uuid_entries_round_trip_under_format_v2(): void public function test_scalar_entries(): void { static::assertEquals( - $rows = rows( + $rows = array_to_rows( + [[ + 'int' => 42, + 'int_min' => PHP_INT_MIN, + 'int_max' => PHP_INT_MAX, + 'float' => 3.14159, + 'float_negative' => -1.0E-10, + 'bool_true' => true, + 'bool_false' => false, + 'string' => 'hello', + 'string_empty' => '', + 'string_binary' => "line\nbreak\x00null\xFFbyte", + 'string_unicode' => 'zażółć gęślą jaźń 🚀', + ]], schema( int_schema('int'), int_schema('int_min'), @@ -269,19 +280,6 @@ public function test_scalar_entries(): void str_schema('string_binary'), str_schema('string_unicode'), ), - row([ - 'int' => 42, - 'int_min' => PHP_INT_MIN, - 'int_max' => PHP_INT_MAX, - 'float' => 3.14159, - 'float_negative' => -1.0E-10, - 'bool_true' => true, - 'bool_false' => false, - 'string' => 'hello', - 'string_empty' => '', - 'string_binary' => "line\nbreak\x00null\xFFbyte", - 'string_unicode' => 'zażółć gęślą jaźń 🚀', - ]), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -296,7 +294,18 @@ public function test_structure_entries(): void ]); static::assertEquals( - $rows = rows( + $rows = array_to_rows( + [[ + 'full' => [ + 'street' => 'Main', + 'nested' => ['count' => 5, 'tags' => ['a']], + 'optional_zip' => '00-001', + ], + 'without_optional' => ['street' => 'Side', 'nested' => ['count' => 0, 'tags' => []]], + 'nullable_element' => ['street' => null, 'nested' => ['count' => 1, 'tags' => []]], + 'with_timezone' => ['tz' => new DateTimeZone('Europe/Warsaw')], + 'with_null_type' => ['nothing' => null], + ]], schema( structure_schema('full', $type), structure_schema('without_optional', $type), @@ -309,17 +318,6 @@ public function test_structure_entries(): void ])), structure_schema('with_null_type', type_structure(['nothing' => type_null()])), ), - row([ - 'full' => [ - 'street' => 'Main', - 'nested' => ['count' => 5, 'tags' => ['a']], - 'optional_zip' => '00-001', - ], - 'without_optional' => ['street' => 'Side', 'nested' => ['count' => 0, 'tags' => []]], - 'nullable_element' => ['street' => null, 'nested' => ['count' => 1, 'tags' => []]], - 'with_timezone' => ['tz' => new DateTimeZone('Europe/Warsaw')], - 'with_null_type' => ['nothing' => null], - ]), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -334,9 +332,9 @@ public function test_interleaved_structure_entries(): void ]); static::assertEquals( - $rows = rows( + $rows = array_to_rows( + [['full' => ['z' => 1, 'a' => 'present', 'b' => 'x'], 'without_optional' => ['z' => 2, 'b' => 'y']]], schema(structure_schema('full', $type), structure_schema('without_optional', $type)), - row(['full' => ['z' => 1, 'a' => 'present', 'b' => 'x'], 'without_optional' => ['z' => 2, 'b' => 'y']]), ), FloeStreamReaderContext::roundTrip($rows), ); @@ -346,14 +344,14 @@ public function test_round_trip_rewrites_value_key_order_into_schema_order(): vo { $type = type_structure(['a' => type_integer(), 'b' => type_string()]); - $inOrder = rows(schema(structure_schema('s', $type)), row(['s' => ['a' => 1, 'b' => 'x']])); + $inOrder = array_to_rows([['s' => ['a' => 1, 'b' => 'x']]], schema(structure_schema('s', $type))); static::assertSame( $inOrder->first()->values(), FloeStreamReaderContext::roundTrip($inOrder)->first()->values(), ); - $outOfOrder = rows(schema(structure_schema('s', $type)), row(['s' => ['b' => 'x', 'a' => 1]])); + $outOfOrder = array_to_rows([['s' => ['b' => 'x', 'a' => 1]]], schema(structure_schema('s', $type))); $decoded = FloeStreamReaderContext::roundTrip($outOfOrder)->first(); static::assertSame(['a' => 1, 'b' => 'x'], $decoded->get('s')); @@ -362,10 +360,9 @@ public function test_round_trip_rewrites_value_key_order_into_schema_order(): vo public function test_uuid_entries(): void { static::assertEquals( - $rows = rows( - schema(uuid_schema('uuid')), - row(['uuid' => type_uuid()->cast('0196aecb-b568-7e57-a381-8ec8d3e4a531')]), - ), + $rows = array_to_rows([[ + 'uuid' => type_uuid()->cast('0196aecb-b568-7e57-a381-8ec8d3e4a531'), + ]], schema(uuid_schema('uuid'))), FloeStreamReaderContext::roundTrip($rows), ); } @@ -373,12 +370,12 @@ public function test_uuid_entries(): void public function test_xml_entries(): void { static::assertEquals( - $rows = rows( - schema(xml_schema('xml'), xml_element_schema('element')), - row([ + $rows = array_to_rows( + [[ 'xml' => type_xml()->cast('text & entity'), 'element' => type_xml_element()->cast('value'), - ]), + ]], + schema(xml_schema('xml'), xml_element_schema('element')), ), FloeStreamReaderContext::roundTrip($rows), ); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php index 849ae08380..27c054fdd6 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php @@ -16,10 +16,9 @@ use Flow\Floe\Tests\Double\UnsizedFilesystem; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; 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; use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\memory_filesystem; @@ -34,10 +33,9 @@ public function test_create_for_stream_is_byte_identical_to_create_by_path(): vo $filesystem = memory_filesystem(); $viaPath = path('memory://via-path.floe'); $viaStream = path('memory://via-stream.floe'); - $data = rows( + $data = array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'a']), - row(['id' => 2, 'name' => 'b']), ); $schema = $data->schema(); @@ -59,10 +57,9 @@ public function test_buffer_size_only_changes_flush_cadence_not_bytes(): void $filesystem = memory_filesystem(); $default = path('memory://default-buffer.floe'); $tiny = path('memory://tiny-buffer.floe'); - $data = rows( + $data = array_to_rows( + [['id' => 1, 'name' => 'alpha'], ['id' => 2, 'name' => 'beta']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'alpha']), - row(['id' => 2, 'name' => 'beta']), ); $schema = $data->schema(); @@ -87,7 +84,7 @@ public function test_append_on_missing_file_behaves_like_create(): void $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->append($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); static::assertSame(1, FloeStreamReaderContext::footer($filesystem, $path)->statistics->rows); @@ -101,7 +98,7 @@ public function test_append_on_empty_file_behaves_like_create(): void $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->append($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); static::assertSame(1, FloeStreamReaderContext::footer($filesystem, $path)->statistics->rows); @@ -118,7 +115,7 @@ public function test_append_to_a_closed_zero_row_file_derives_the_schema_from_th $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->append($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); static::assertSame([['id' => 1]], FloeStreamReaderContext::readAll($filesystem, $path)->toArray()); @@ -139,7 +136,7 @@ public function test_append_to_a_zero_row_file_with_an_explicit_schema_validates $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('new column "name"'); - $writer->write(rows(schema(str_schema('name')), row(['name' => 'flow']))); + $writer->write(array_to_rows([['name' => 'flow']], schema(str_schema('name')))); } public function test_create_with_an_explicit_schema_and_no_writes_records_the_schema_in_the_footer(): void @@ -253,14 +250,14 @@ public function test_append_with_incompatible_schema_keeps_previous_rows_readabl $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->create($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->append($path); try { - $writer->write(rows(schema(str_schema('id')), row(['id' => 'no longer an int']))); + $writer->write(array_to_rows([['id' => 'no longer an int']], schema(str_schema('id')))); static::fail('expected ' . IncompatibleSchemaException::class); } catch (IncompatibleSchemaException) { } @@ -280,7 +277,7 @@ public function test_append_with_new_non_nullable_column_throws(): void $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->create($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); $this->expectException(IncompatibleSchemaException::class); @@ -288,7 +285,7 @@ public function test_append_with_new_non_nullable_column_throws(): void $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->append($path); - $writer->write(rows(schema(int_schema('id'), str_schema('email')), row(['id' => 2, 'email' => 'x']))); + $writer->write(array_to_rows([['id' => 2, 'email' => 'x']], schema(int_schema('id'), str_schema('email')))); } public function test_append_with_new_nullable_column_throws(): void @@ -298,7 +295,7 @@ public function test_append_with_new_nullable_column_throws(): void $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->create($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); $writer = new FloeWriter($filesystem, schema(int_schema('id'))); @@ -307,9 +304,9 @@ public function test_append_with_new_nullable_column_throws(): void $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('new column "email"'); - $writer->write(rows( + $writer->write(array_to_rows( + [['id' => 2, 'email' => null]], schema(int_schema('id'), str_schema('email', nullable: true)), - row(['id' => 2, 'email' => null]), )); } @@ -320,12 +317,12 @@ public function test_append_with_same_schema_adds_a_section_reusing_the_footer_s $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->create($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->append($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 2]))); + $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); $writer->close(); static::assertSame( @@ -398,8 +395,8 @@ public function test_two_writes_with_the_same_schema_in_one_session_share_one_se $writer = new FloeWriter($filesystem, schema(int_schema('id'))); $writer->create($path); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); - $writer->write(rows(schema(int_schema('id')), row(['id' => 2]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); + $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); $writer->close(); $footer = FloeStreamReaderContext::footer($filesystem, $path); @@ -419,11 +416,11 @@ public function test_nothing_reaches_the_stream_before_buffer_fills_or_close(): $writer = new FloeWriter($filesystem, schema(str_schema('data'))); $writer->create($path); - $writer->write(rows(schema(str_schema('data')), row(['data' => 'x']))); + $writer->write(array_to_rows([['data' => 'x']], schema(str_schema('data')))); static::assertSame(0, $filesystem->readFrom($path)->size()); - $writer->write(rows(schema(str_schema('data')), row(['data' => str_repeat('x', 70_000)]))); + $writer->write(array_to_rows([['data' => str_repeat('x', 70_000)]], schema(str_schema('data')))); static::assertGreaterThan(0, $filesystem->readFrom($path)->size()); } @@ -433,11 +430,9 @@ public function test_within_batch_heterogeneous_rows_encode_under_one_union_sche $filesystem = memory_filesystem(); $path = path('memory://sections.floe'); - $data = rows( + $data = array_to_rows( + [['a' => 1, 'b' => 'x'], ['a' => 2, 'c' => 'y'], ['a' => 3, 'b' => 'z']], schema(int_schema('a'), str_schema('b', nullable: true), str_schema('c', nullable: true)), - row(['a' => 1, 'b' => 'x']), - row(['a' => 2, 'c' => 'y']), - row(['a' => 3, 'b' => 'z']), ); $writer = new FloeWriter($filesystem, $data->schema()); @@ -464,10 +459,9 @@ public function test_section_offsets_point_at_frames(): void $filesystem = memory_filesystem(); $path = path('memory://offsets.floe'); - $data = rows( + $data = array_to_rows( + [['a' => 1], ['b' => 'x']], schema(int_schema('a', nullable: true), str_schema('b', nullable: true)), - row(['a' => 1]), - row(['b' => 'x']), ); $writer = new FloeWriter($filesystem, $data->schema()); @@ -494,7 +488,7 @@ public function test_write_after_close_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('Floe writer session is not open'); - $writer->write(rows(schema(int_schema('id')), row(['id' => 1]))); + $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); } public function test_append_refuses_a_different_datetime_zone(): void @@ -504,10 +498,9 @@ public function test_append_refuses_a_different_datetime_zone(): void $writer = new FloeWriter($filesystem, schema(datetime_schema('at'))); $writer->create($path); - $writer->write(rows( - schema(datetime_schema('at')), - row(['at' => new DateTimeImmutable('2026-01-02 03:04:05')]), - )); + $writer->write(array_to_rows([[ + 'at' => new DateTimeImmutable('2026-01-02 03:04:05'), + ]], schema(datetime_schema('at')))); $writer->close(); $this->expectException(IncompatibleSchemaException::class); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterReaderTest.php index 28e5f7e642..02de026a60 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterReaderTest.php @@ -15,9 +15,8 @@ use PHPUnit\Framework\TestCase; use function chr; +use function Flow\ETL\DSL\array_to_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; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; @@ -30,7 +29,7 @@ public function test_reads_footer_location_of_a_written_file(): void { $fs = memory_filesystem(); $path = path('memory://footer.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $writer = new FloeWriter($fs, $data->schema()); $writer->create($path); $writer->write($data); @@ -95,7 +94,7 @@ public function test_leaves_the_source_open_on_success(): void { $fs = memory_filesystem(); $path = path('memory://close-ok.floe'); - $data = rows(schema(int_schema('id')), row(['id' => 1])); + $data = array_to_rows([['id' => 1]], schema(int_schema('id'))); $writer = new FloeWriter($fs, $data->schema()); $writer->create($path); $writer->write($data); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterTest.php index ecd34de58e..731684e409 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterTest.php @@ -12,8 +12,8 @@ use Flow\Floe\Tests\Mother\FooterMother; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_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; use function Flow\ETL\DSL\str_schema; @@ -193,7 +193,7 @@ public function test_reconstruct_rows_round_trips_unpartitioned_rows(): void { $filesystem = memory_filesystem(); $path = path('memory://footer-rows.floe'); - $value = rows(schema(int_schema('id')), row(['id' => 1]), row(['id' => 2])); + $value = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $writer = new FloeWriter($filesystem, $value->schema()); $writer->create($path); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php index 77d8d97210..4bf5418326 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php @@ -15,11 +15,10 @@ use Flow\Floe\Tests\Mother\RowsMother; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\null_schema; -use function Flow\ETL\DSL\row; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\schema_from_json; use function Flow\ETL\DSL\str_schema; @@ -30,10 +29,9 @@ final class PhpFloeEncoderTest extends TestCase { public function test_decode_produces_row_values(): void { - $original = rows( + $original = array_to_rows( + [['id' => 1, 'name' => 'flow', 'price' => 1.5], ['id' => 2, 'name' => null, 'price' => 0.5]], schema(int_schema('id'), str_schema('name', nullable: true), float_schema('price')), - row(['id' => 1, 'name' => 'flow', 'price' => 1.5]), - row(['id' => 2, 'name' => null, 'price' => 0.5]), ); $encoder = new PhpFloeEncoder(schema_from_json(FloeSchemaContext::schemaBody($original->schema()))); @@ -47,10 +45,9 @@ public function test_decode_produces_row_values(): void public function test_encode_from_dehydrated_rows_round_trips(): void { - $original = rows( + $original = array_to_rows( + [['id' => 1, 'name' => 'flow'], ['id' => 2, 'name' => null]], schema(int_schema('id'), str_schema('name', nullable: true)), - row(['id' => 1, 'name' => 'flow']), - row(['id' => 2, 'name' => null]), ); $encoder = new PhpFloeEncoder(schema_from_json(FloeSchemaContext::schemaBody($original->schema()))); @@ -142,9 +139,9 @@ public function test_null_entry_in_a_typed_column_encodes_as_a_plain_null(): voi ))); $encoder = new PhpFloeEncoder($schema); - $body = $encoder->encode((new PhpRowHydrator())->dehydrate(rows( + $body = $encoder->encode((new PhpRowHydrator())->dehydrate(array_to_rows( + [['id' => 2, 'name' => null]], schema(int_schema('id'), null_schema('name')), - row(['id' => 2, 'name' => null]), )))[0]; $decoded = $encoder->decode([$body]); @@ -158,9 +155,9 @@ public function test_row_body_with_trailing_garbage_throws(): void $schema = schema_from_json(FloeSchemaContext::schemaBody(schema(int_schema('id'), str_schema('name')))); $encoder = new PhpFloeEncoder($schema); - $body = $encoder->encode((new PhpRowHydrator())->dehydrate(rows( + $body = $encoder->encode((new PhpRowHydrator())->dehydrate(array_to_rows( + [['id' => 1, 'name' => 'flow']], schema(int_schema('id'), str_schema('name')), - row(['id' => 1, 'name' => 'flow']), )))[0]; $this->expectException(FloeException::class); @@ -181,10 +178,9 @@ public function test_unknown_value_flag_throws(): void public function test_decode_rows_hydrates_the_decoded_values(): void { - $data = rows( + $data = array_to_rows( + [['id' => 1, 'name' => 'flow'], ['id' => 2, 'name' => null]], schema(int_schema('id'), str_schema('name', nullable: true)), - row(['id' => 1, 'name' => 'flow']), - row(['id' => 2, 'name' => null]), ); $schema = schema_from_json(FloeSchemaContext::schemaBody($data->schema())); $encoder = new PhpFloeEncoder($schema); diff --git a/src/core/etl/tests/Flow/Serializer/Tests/Unit/Base64SerializerTest.php b/src/core/etl/tests/Flow/Serializer/Tests/Unit/Base64SerializerTest.php index 4ae3bec8e1..ddbdb8ec6e 100644 --- a/src/core/etl/tests/Flow/Serializer/Tests/Unit/Base64SerializerTest.php +++ b/src/core/etl/tests/Flow/Serializer/Tests/Unit/Base64SerializerTest.php @@ -5,19 +5,17 @@ namespace Flow\Serializer\Tests\Unit; use DateTimeImmutable; -use Flow\ETL\Row; use Flow\Serializer\Base64Serializer; use Flow\Serializer\Exception\SerializationException; use Flow\Serializer\NativePHPSerializer; use PHPUnit\Framework\TestCase; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; 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; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; @@ -32,18 +30,9 @@ final class Base64SerializerTest extends TestCase { public function test_serializing_rows(): void { - $rows = rows( - schema( - int_schema('integer'), - str_schema('string'), - bool_schema('boolean'), - datetime_schema('datetime'), - str_schema('null', nullable: true), - float_schema('float'), - structure_schema('struct', type_structure(['integer' => type_integer(), 'string' => type_string()])), - ), - ...array_map( - static fn(): Row => row([ + $rows = array_to_rows( + array_map( + static fn(): array => [ 'integer' => 1, 'string' => 'string', 'boolean' => true, @@ -51,9 +40,18 @@ public function test_serializing_rows(): void 'null' => null, 'float' => 0.12, 'struct' => ['integer' => 1, 'string' => 'string'], - ]), + ], range(0, 100), ), + schema( + int_schema('integer'), + str_schema('string'), + bool_schema('boolean'), + datetime_schema('datetime'), + str_schema('null', nullable: true), + float_schema('float'), + structure_schema('struct', type_structure(['integer' => type_integer(), 'string' => type_string()])), + ), ); $serializer = new Base64Serializer(new NativePHPSerializer()); diff --git a/src/core/etl/tests/Flow/Serializer/Tests/Unit/CompressingSerializerTest.php b/src/core/etl/tests/Flow/Serializer/Tests/Unit/CompressingSerializerTest.php index 66aa108c29..7e7833093b 100644 --- a/src/core/etl/tests/Flow/Serializer/Tests/Unit/CompressingSerializerTest.php +++ b/src/core/etl/tests/Flow/Serializer/Tests/Unit/CompressingSerializerTest.php @@ -5,18 +5,16 @@ namespace Flow\Serializer\Tests\Unit; use DateTimeImmutable; -use Flow\ETL\Row; use Flow\Serializer\CompressingSerializer; use Flow\Serializer\NativePHPSerializer; use PHPUnit\Framework\TestCase; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; 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; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; @@ -39,18 +37,9 @@ protected function setUp(): void public function test_serializing_rows(): void { - $rows = rows( - schema( - int_schema('integer'), - str_schema('string'), - bool_schema('boolean'), - datetime_schema('datetime'), - str_schema('null', nullable: true), - float_schema('float'), - structure_schema('struct', type_structure(['integer' => type_integer(), 'string' => type_string()])), - ), - ...array_map( - static fn(): Row => row([ + $rows = array_to_rows( + array_map( + static fn(): array => [ 'integer' => 1, 'string' => 'string', 'boolean' => true, @@ -58,9 +47,18 @@ public function test_serializing_rows(): void 'null' => null, 'float' => 0.12, 'struct' => ['integer' => 1, 'string' => 'string'], - ]), + ], range(0, 100), ), + schema( + int_schema('integer'), + str_schema('string'), + bool_schema('boolean'), + datetime_schema('datetime'), + str_schema('null', nullable: true), + float_schema('float'), + structure_schema('struct', type_structure(['integer' => type_integer(), 'string' => type_string()])), + ), ); $serializer = new CompressingSerializer(new NativePHPSerializer()); diff --git a/src/core/etl/tests/Flow/Serializer/Tests/Unit/NativePHPSerializerTest.php b/src/core/etl/tests/Flow/Serializer/Tests/Unit/NativePHPSerializerTest.php index 67ca850ebd..89179c306a 100644 --- a/src/core/etl/tests/Flow/Serializer/Tests/Unit/NativePHPSerializerTest.php +++ b/src/core/etl/tests/Flow/Serializer/Tests/Unit/NativePHPSerializerTest.php @@ -5,18 +5,16 @@ namespace Flow\Serializer\Tests\Unit; use DateTimeImmutable; -use Flow\ETL\Row; use Flow\Serializer\Exception\SerializationException; use Flow\Serializer\NativePHPSerializer; use PHPUnit\Framework\TestCase; use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; 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; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; @@ -32,18 +30,9 @@ final class NativePHPSerializerTest extends TestCase { public function test_serializing_rows(): void { - $rows = rows( - schema( - int_schema('integer'), - str_schema('string'), - bool_schema('boolean'), - datetime_schema('datetime'), - str_schema('null', nullable: true), - float_schema('float'), - structure_schema('struct', type_structure(['integer' => type_integer(), 'string' => type_string()])), - ), - ...array_map( - static fn(): Row => row([ + $rows = array_to_rows( + array_map( + static fn(): array => [ 'integer' => 1, 'string' => 'string', 'boolean' => true, @@ -51,9 +40,18 @@ public function test_serializing_rows(): void 'null' => null, 'float' => 0.12, 'struct' => ['integer' => 1, 'string' => 'string'], - ]), + ], range(0, 100), ), + schema( + int_schema('integer'), + str_schema('string'), + bool_schema('boolean'), + datetime_schema('datetime'), + str_schema('null', nullable: true), + float_schema('float'), + structure_schema('struct', type_structure(['integer' => type_integer(), 'string' => type_string()])), + ), ); $serializer = new NativePHPSerializer(); diff --git a/src/tools/documentation/tests/Flow/Documentation/Tests/Integration/DocumentationFencesTest.php b/src/tools/documentation/tests/Flow/Documentation/Tests/Integration/DocumentationFencesTest.php index 5514c4d0fc..d2d650e3ad 100644 --- a/src/tools/documentation/tests/Flow/Documentation/Tests/Integration/DocumentationFencesTest.php +++ b/src/tools/documentation/tests/Flow/Documentation/Tests/Integration/DocumentationFencesTest.php @@ -18,16 +18,17 @@ use function array_filter; use function array_values; +use function fnmatch; use function implode; use function sprintf; final class DocumentationFencesTest extends TestCase { /** - * documentation/upgrading.md is append-only history. Its "Before:" fences are deliberately - * written against APIs that no longer exist, so the whole file is excluded by name. + * documentation/upgrading*.md is append-only history. Its "Before:" fences are deliberately + * written against APIs that no longer exist, so every such file is excluded by pattern. */ - private const EXCLUDED = 'documentation/upgrading.md'; + private const EXCLUDED = 'documentation/upgrading*.md'; public static function documentation_links(): Generator { @@ -43,7 +44,7 @@ public static function documentation_links(): Generator public static function documentation_pages(): Generator { foreach ((new MarkdownCorpusContext())->filesIn(['documentation']) as $file) { - if ($file === self::EXCLUDED) { + if (fnmatch(self::EXCLUDED, $file)) { continue; } @@ -56,7 +57,7 @@ public static function php_fences(): Generator $fences = new MarkdownFences(); foreach ((new MarkdownCorpusContext())->filesIn(['documentation']) as $file) { - if ($file === self::EXCLUDED) { + if (fnmatch(self::EXCLUDED, $file)) { continue; } diff --git a/web/landing/assets/codemirror/completions/dataframe.js b/web/landing/assets/codemirror/completions/dataframe.js index 2ebb22f397..5bcea27607 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: 47 + * DataFrame methods: 46 * DataFrame-returning methods from classes: 3 * * This completer triggers after DataFrame-returning methods @@ -253,7 +253,7 @@ const dataframeMethods = [ fetch(int $limit = null) : Rows
- Be aware that fetch is not memory safe and will load all rows into memory.
If you want to safely iterate over Rows use oe of the following methods:.
DataFrame::get() : \\Generator
DataFrame::getAsArray() : \\Generator
DataFrame::getEach() : \\Generator
DataFrame::getEachAsArray() : \\Generator
@trigger
@throws InvalidArgumentException + Be aware that fetch is not memory safe and will load all rows into memory.
If you want to safely iterate over Rows use oe of the following methods:.
DataFrame::get() : \\Generator
DataFrame::getAsArray() : \\Generator
DataFrame::getEachAsArray() : \\Generator
@trigger
@throws InvalidArgumentException
` return div @@ -350,24 +350,6 @@ const dataframeMethods = [ }, apply: snippet("getAsArray()"), boost: 10 - }, { - label: "getEach", - type: "method", - detail: "Flow\\\\ETL\\\\DataFrame", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- getEach() : Generator -
-
- Yield each row as an instance of Row.
@trigger
@return \\Generator -
- ` - return div - }, - apply: snippet("getEach()"), - boost: 10 }, { label: "getEachAsArray", type: "method", diff --git a/web/landing/assets/codemirror/completions/dsl.js b/web/landing/assets/codemirror/completions/dsl.js index 17a9645e32..1808c5606f 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: 814 + * Total functions: 813 * * This completer provides autocompletion for all Flow PHP DSL functions: * - Extractors (flow-extractors) @@ -700,7 +700,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- array_to_row(array $data, Schema $schema, Hydrator $hydrator = Flow\\ETL\\Row\\AdaptiveRowHydrator::..., Partitions|array $partitions = []) : Row + array_to_row(array $data, Schema $schema, Backend $backend = Flow\\ETL\\Column\\DefaultBackend::..., Partitions|array $partitions = []) : Row
@param array>|array $data
@param array|Partitions $partitions @@ -708,7 +708,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\ETL\\DSL\\array_to_row(" + "$" + "{" + "1:data" + "}" + ", " + "$" + "{" + "2:schema" + "}" + ", " + "$" + "{" + "3:hydrator" + "}" + ", " + "$" + "{" + "4:partitions" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\DSL\\array_to_row(" + "$" + "{" + "1:data" + "}" + ", " + "$" + "{" + "2:schema" + "}" + ", " + "$" + "{" + "3:backend" + "}" + ", " + "$" + "{" + "4:partitions" + "}" + ")"), boost: 10 }, { label: "array_to_rows", @@ -718,7 +718,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- array_to_rows(array $data, Schema $schema, Hydrator $hydrator = Flow\\ETL\\Row\\AdaptiveRowHydrator::...) : Rows + array_to_rows(array $data, Schema $schema, Backend $backend = Flow\\ETL\\Column\\DefaultBackend::...) : Rows
@param array>|array $data @@ -726,7 +726,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\ETL\\DSL\\array_to_rows(" + "$" + "{" + "1:data" + "}" + ", " + "$" + "{" + "2:schema" + "}" + ", " + "$" + "{" + "3:hydrator" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\DSL\\array_to_rows(" + "$" + "{" + "1:data" + "}" + ", " + "$" + "{" + "2:schema" + "}" + ", " + "$" + "{" + "3:backend" + "}" + ")"), boost: 10 }, { label: "array_unpack", @@ -4336,7 +4336,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- from_floe(Path|string $path, Codec $codec = Flow\\Floe\\Codec\\NoopCodec::..., int $chunk_size = 65536, FloeEngine $engine = Flow\\Floe\\FloeEngine::..., Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : FloeExtractor + from_floe(Path|string $path, Codec $codec = Flow\\Floe\\Codec\\NoopCodec::..., int $chunk_size = 65536, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : FloeExtractor
@param Path|string $path @@ -4344,7 +4344,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\Floe\\DSL\\from_floe(" + "$" + "{" + "1:path" + "}" + ", " + "$" + "{" + "2:codec" + "}" + ", " + "$" + "{" + "3:chunk_size" + "}" + ", " + "$" + "{" + "4:engine" + "}" + ", " + "$" + "{" + "5:filesystem" + "}" + ")"), + apply: snippet("\\Flow\\Floe\\DSL\\from_floe(" + "$" + "{" + "1:path" + "}" + ", " + "$" + "{" + "2:codec" + "}" + ", " + "$" + "{" + "3:chunk_size" + "}" + ", " + "$" + "{" + "4:filesystem" + "}" + ")"), boost: 10 }, { label: "from_google_sheet", @@ -8513,24 +8513,6 @@ const dslFunctions = [ }, apply: snippet("\\Flow\\ETL\\DSL\\round(" + "$" + "{" + "1:value" + "}" + ", " + "$" + "{" + "2:precision" + "}" + ", " + "$" + "{" + "3:mode" + "}" + ")"), boost: 10 - }, { - label: "row", - type: "function", - detail: "flow\u002Ddsl\u002Ddata\u002Dframe", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
- row(array $values) : Row -
-
- @param array $values -
- ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\row(" + "$" + "{" + "1:values" + "}" + ")"), - boost: 10 }, { label: "rows", type: "function", @@ -11257,7 +11239,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
- to_floe(Path|string $path, Metadata $metadata = null, Options $options = Flow\\Floe\\Options::..., FloeEngine $engine = Flow\\Floe\\FloeEngine::..., Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : FloeLoader + to_floe(Path|string $path, Metadata $metadata = null, Options $options = Flow\\Floe\\Options::..., Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : FloeLoader
@param Path|string $path @@ -11265,7 +11247,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\Floe\\DSL\\to_floe(" + "$" + "{" + "1:path" + "}" + ", " + "$" + "{" + "2:metadata" + "}" + ", " + "$" + "{" + "3:options" + "}" + ", " + "$" + "{" + "4:engine" + "}" + ", " + "$" + "{" + "5:filesystem" + "}" + ")"), + apply: snippet("\\Flow\\Floe\\DSL\\to_floe(" + "$" + "{" + "1:path" + "}" + ", " + "$" + "{" + "2:metadata" + "}" + ", " + "$" + "{" + "3:options" + "}" + ", " + "$" + "{" + "4:filesystem" + "}" + ")"), boost: 10 }, { label: "to_json", diff --git a/web/landing/assets/wasm/tools/flow.phar b/web/landing/assets/wasm/tools/flow.phar index d0c4b09847ed6b7addcd4883122e4769d92e6b2b..37cfbabd6d74678695b38c8e6f372292969af35a 100755 GIT binary patch delta 585238 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%0AK%pi&yOg*7-;vAxd@Jp)b`f zK5x}MHk&xY@&Gx<5Z|}fll*O)OQz@ifiM&x__V0WYvRHCMU?^@U)C zuyCNMl#IZkxy>GRl7-r&9`OYFOe{iB$LZ?R)%FLPtgczCGTe8KRsWO%tWE55k6WW@7Jc&0phV4J z5A=S~mFALFe{2)rjAnK0n)5Cgx6+bvsgF{qn@EANNf4lwILn8^Df~lWJw^!?@CtRWH zoN<3s7L(upq}{$h(;3&1lbAn9a_%t&=$ycEma=nBUSE69yu}mE|wbS z*XO5lf1-7buE-q|6{4KVTI84WrvrvkI|~EyC2wxZdBabg>K9#nS6!WCW7_9art%+y z{I}Oh*t@@PGLI}qu64piG+Rfl5PKB5S#0sfC(NESXX1jB7oJ=@0TZH5UcRS%h%+AL zBP+e~9!pN;_Q)(maDyP=1IvX-!G17r3{{7=e;=tuZ+Zx1kMM;ZtliP?9xuz8_wcZ# zJL!qf=KRkcv2{qucs>ewAkzB~0ESr)lqs!<6LDGicT$ng?{I+l@N*WKH+Sxw`Qsc; zDZp_}gN|D57Dg(B!Fp}+E>`CJ#KEJa3gHn9u9Zk>Qd-M+mF*zf+)0svagzjCex}t# ze=3#-(`RbbQlkMeI({TOOww=nS!}W&Y`U00Vrbp@lA)WyX*TlKJxI%RkDNv^n67+h z;8U=nK@K2J?z62IAIVKHro|G8!BNhtpKmwHjLoiLF2Nt^*C)1j1{G{{57!3BJL=5T zRlgAUMu<6bjDb9gM7p}Ohb@|dy+<@(e-u+>gz-db-e9&Au$P`3ZxD0-Vy7h55TXpR z$xZh!y+_GanH_3O*B(5a62s*Y$to;XDiPeG-6pz9LzdH6Ia)k^>$VV)Tn>KWo#HRW zUz?rcY%9nXb%O|J2|xN3M4{_6!*NTgZLLVA%O@@vf3jg+)wD3og$lY!8R`r&l z@T!Ymq+8{aoJ~v)*J{BH;|uE+t*Zr3fiQ_K0~2W(l~mkAEE6J7jb6vv5r?}0wG%%G z4=;T2ogLX449l#68x#u_mVu7`e~Cgfd{Xs8z7lz+aYA-uIBpUryKDNS(-!hdOjejl z8OcVYP}a+UtOQT^LrdG+Bf2kKvcREotFt`YZ4u#{Q?6~Ac}Ku;cErAzp;_Zsg~u~7 zI~XH#)8pd|9BQk4cAtyp=-Gv3GR&1z=rav&fz&-&C9oPf^2mNR>vNsVrbA?tkA;N>@nM49p$^pESy%rF?^iiwT=nb1|CHJYg z<2;zR?!!W+na>qJ-F5lwe>{AHin`bGOO?$?M)W7?21F-L^F(iPYboBe;UZJE#W&$Rcjaa$dR^nfzCR`-3qx?8M;sasvFVnqE>aL=qrt^V_& z*dTNLmCX(vtBG3e8j<{dJ;FI$~*`nZBi_6J_v@i(|H-v*qR|kMwvy&ujF3 z1?d|wAIJIRi2%>TQ_+Y#3U_h?fBs~viQ6buyK$j=p{SxqN`}BoC zz{7KqRT%pkhX3K1R)a7AAIpDFSfi5Q)o96>6hdoh{a&INUbprtZ>^QQ&j*z(9i}RV zBe|p2FlUh@j3^95C;$EwXh<1e@jS<;21LbT626LL5s=^mI-f@h%2)j3MSuJ!i@rVi zKey_25-$mVR%>tDHWdA?UvXDtuoPHP>;^?9&so|m8}e;Pn{L277_>r31SnD^sW@8V z|6Y=!Vo9~#R50}5J-pAOBmeqanU|h-j}wXn_N5XeQA<^qSk5QG%<~v3uq;u6;Sb8! zi%-U~_>5?UwXu@D&0C~ z?(OM@DJ)W*jx*zw;>5tOD3Y>S{HTjy8Cp>X`dAk!XZ7NW7bRypoyDE=21vG6^XMu{ zD`s87im+*pA7}klBA3!e7_659XUhVqBp(=LsnIGOt|~z>8!lEWy{_{}2}2YFM)#c2 z8WK}~9oUpfQBrK0Dm#UGPafzaIzF~nIEGI-k$QiIA4{DvASk&|z*A5;ZX8jv5=hkJ zcE>s=Np7$SFKa=vT)_v-+yusODKUmzsZz#Klo6FztCNHmk+Alt(k@S&tH@q;)elHv z?T$$WP0Qf!?&kO9?e(A6|NI4W7)6Ws|DJ|_zo0Pv@9BIKzTBU^;(jvSEdGxQInwRw z#&eO59vn#rjk#30;A;u{DEd4kV!xJ4eL!;@DLwq~!UA-c+fH;L8^BZ(@7uk$JHYUIZ-e}Q zH_l>*8N=wQ39uQx2?jyDemGM^g9W0ShFF3%A$$EAmb0^z@Ivv1`+g_l&XV@-zfF^~ z$#mLt;5FwTWy~&u=;~CLC#m4YhgxCjxAa_@ryvG1)g6pzS~F;|HK6L2IVe{=j-4L&g=1-~{@AL3^!vxjoW~s5|MjvBhqoM@9)Wz&B|P^Z;T& zoxj;p*s56&gclleTtM+Z;qC1)>g3AJBJR}+80t3?OSW6;f($pQ6f|ppR zI$R5)a6g&t_?;5_y(W%+mSN{N8uzS?BKxN5F`SO!JUC!KAH&%p`(*k(z`O4Nrl%ci ze=ysQMPOA4))YMJ68Qij-8Z zb~k39b6cL>_v(;8SV-s7vGF$ESG8ALx2}N_lL>!ca}zfZfA^=*Of!=+;{zytkC4Bd4_3w0+&gVcxd2np)YWKIRm9$!k_*tS&PbY8oy4(mII^YqwhX!R1nGz(@4&Cj1RZpcN=NV{F&?(K3+ z7j;UuU<79%Tp=zNzFIw`n>riM4{2855;I!*=@WXH%yD{tnBuBB)jm!`Q4^CKEdGb^XFxWZ+f|YrZgpZLkugvL!74gBHduEViZBQo$jN&&U$~D zcr)JM5yjOTTozwhkvRl!FY|HoiEJ1+#dT7r8)kuGI=%SFmG-i|Ar-C5dB2zYrm13k zn{T$WhCxlzgx&ZV;Nt~h9D3I#03R!RGsY>|eHgryC1 z?(!v0D`I!sQ`i zw+0Q7^ryhBohz}bUj`p{tHGB@juH-kGJRlP(vsl$3Pn;JB)2WpB39SP4wMmpq9wx3s*d=|!f=wqzOEDT;XayDhSM=;JUN}Bled$J zFd8M5vWYAZ_r?n6mt?W8UH>&xD|FOdK*6guK5n>q$47MRoK+TVw3CvhvyEw5nOv?| z5X;CvHP5k>Z2&>g}qk3MJc ze%v3t!)*QNBFLg2XSjmDn#J~+s=2A-Acz|&Z9&|Z;X-*&L)O!yLC77dP`Un8gvjb{ z_w=Pmx|A8imk>66Z@3(|^Q)S41`0otYG*c6gQhPcFY5&|;cu?gc!BKr!#oFo5* z9quXGeLFqe<#yTlT-$7FB)WDR`F#zHH1=-Xonz7-4*~V+o6qxJq+%Fgo$U0m@opzl zU9N4M3oW70&R~!=WUbl{TT}heRkfF+Zf==wtt+Sy27Jm=fUZ=3yQmeR6R=gv7P!^# zTlF^(WK-^u&@B*N3oN?d5M8;C;Y*Ox36~3CwIUa$ruYF`b?-O{);E zL_b#R@Ez{Z-5jbx(76Pac3^gOA_<}N6f-Uw2W5t3op8g-r;jG=W*S#uRD0_;`E&=PBDXxcFznpG(U3t zCM_=2j}UORYyfO4bs^hSKWKAps*V}*6dnS#EM#%WMx~2?*O2^R?Hl2Eu6~5Ts$~OQ zTd9lKrusqa8c_`Os4zv}G?k^^w4?5+DSm+F&iP)dO8&DY2nLKsm*@PbNq&@`Hyx0E z#E(WO!=HjgY@t-z`G^OGYl?@dBQ~5DGjUGyJpyeZuL)>A6FTgR0tbpGjvOApS?vcI za%K7aC4?n^(h9S*v=zGswCNkO2K@%$EAj^Y$Rte0K)7@#RnRIuCM$|JJ!qTk-EY?_ zTdJnxl=sX#vM@%cQbFW}s4$6YpTXfP_!(lPdia7@zu1fI$C)8)S}}Rx)e2q2n&O{j zYwr+a>vt%)_F;ETy&rw|ad+FR5C6<-b}PkssODjRh-)kBHe`f!$Qh+u-y7)rtC8LL zd-$ZET^IXB4-(3cGo0US_N8fB19S%;Kj%6eH;){F-g@1A9UhC-e-hy|#{RF$ZY8kq&n~!w?xd=+NoQ zv(|Qh2=6#J@Sy|DlfAbYT6^R@j{bsXdgYuks!iQ`nmXydXOHJ(2J&6xt@N2wlB=jt&A`Y|-9&z9ZG(q9FO=aFwKswlu9qzw!~>6}}?xjwg})wNQRL zvaS#R1Gfg062bz1S6ffpFcf~zukfS_r6>jM6=*jEo5aM}1MG>S%1xctTAE~u15|_m zKF7D%sdF78553smIsVS)N>=KksKaNiwCxTm)CD2FU zYZyPx?}{1rN$2v+GHMx|U&m|g!*G5H3A)2u)DhW=`j*9iQ9J4yXQUnV9VYFd9|^&6 z1jBaZElG2qnesh5d}M+*Sq)^2je_*YTIP*YhGv7dXlYjC{0+gHscYqXjIKpk4w@_Y9;6uHq=% z0h;Ss1}@@%Z30tB;?()$0Qwvs9eNma%rE|>wD)t?7nDS9M!rz)Opc1U&^ z2J+_Q1VnN3z_p~W>OUzw=&$x`*x_u%@>s+NTw?tuH9O!pm+}FmX zA)*&H|GjM#6o$2o;uL`o(WZbBJ^xM6OFn_qekr-H7r9j|Me?>V*7x1OwANO(w0xpO--T!S*lW_vb&|-`-RwU za&&Z5TA{X6dminYB~e2azjmocKA#0saIgEQ7(bkrsZt&VXK7J z(;GChg_2?eltE+QrIMC$iTbnTOA6U}Prgrpo`d~;|Au{dQ8LX6aM;fa{tXv%*b}(4 zyX=~;)_sSN{iNeK?aoS%;3NVm8Q0g`;6rihLj4e^TCgAZcUfHu zo^QpjNUx12P)kv-AHtqC47U+(N+g`*Jq5N0PYhvOZ(K(%fWlG{(Z-(HeBhS|(# zs~@3zI>|hajJGjb@T&oTcQEz#BZ#`Grjc&(JJ_R%Yc?-<{CGs1#yUt?*fgS?g%ku+ zl1^JO+o8U2O{gtgkdMOiuMnNvc#_8HFMT7p!|pOJve~R+0$q2 z$>AZCs0(fl$!>9l8h-uw2}_}v1q$1MRrPM={`lc3T(5b)2D?UJTC+{&bhKEMf?4b@ zlQSum1^iZOq!T0a)1=o}pr5&_m|g(8R9DnV#@jU=jl4iu5g-i^m4aD|+C1sQzbM#B zWrU8o1xC%aG29$~HDt0}Q7vgYqHK1>m8cJ>dqD_dn;9B&2U{l5SX^XGuPRsGnQgY* zp771t>Pu!C^8Odi5ZxHYTOx89G=>9wUH71I^%k|eNz%9~YV@vuyczfjgF5s#mn2#$ zg-2AC!4QEytZ#5j?d(gB%2Ls7gz7M60?bgCDZ~9aJDW#;l8kYQ=(Z9xaAz%6fB7hf z!9AP18?4tNf~m*HR^O?{h$5b`tFqx{(yryq(>?(=*iU8~LJhcMU->7RP4dpZ5ZS?9 zc6fd8lLl%I?+2|0e=tQ5&7r%!@C-~tnDjnpzdJ0VW^7MCGv4t70dFU_lizKPy$-@K z41{+-g$IVWVxAHd5Pwd?Fc97S6*nN1NM&H9v|SJq5@G?iNR{heT1&1IoHM9u`|sFp z+Bzhm6~aT5_};yH&v(xKq+FJa%~2?BFsaB$K~q|nSdDJeA!C}auqwGgcvQt#_U0qu z>0-9(*zMTNo{NPPTxAcO@J+7pLS!%Mg_Hcm%x!Zzi+a+83x70caW7V>$XIT*AX(@b z{_y&o`LmhMojh_zhUcO9VY#X<0OsC}E1pZu6&U36LaQ~n##9x&xq=S&1!e+-h3t1;+ zop=jyr7))f?0?^lTr4TQgNgqPnVX{ynL`qtNm3`)IcbFS%OF{!_w2)Cq?U7_3sI2H zGS>o&91dOVW22?4ZpM-MoAJy~el4QEP>BCaB`>+ZP=l-OFPdi9ZlM)F-ifq9bbZ}r z;U`%O(81PY_cX%EpS>L}eW$Vb-*Jhz23dEs#n$6(#WzVT-RK(IYPMg$O7-e~FAt+J zG=3_F%XfJV$FRRkt-Lwr+$su)prQ%cb+)Ru?MHVX-?1J02ABS?62^a}RLO4JFc7`# zE9MZuQeY?O)rp-JXaf{TlSABI;=rIKIw3%l0!i6%i~M_MNZDEWk# zP5zokQN~lr43DidB6Tyj$+;bUO0J?vu_d=TOF7(1y`E0!i+@h<^ovNDL`-2DU%$Pj zJa36kaQe%TlM!rewS*R7!;E z(65hoQ%Zg&h2w^jJBnPg{1g=BZ~~4Bpk7V`7O5)?rW;+JpGR;GpB-Q3k~t0&{OfN7 zUhpMX&H~wAPsVtC87+ij5)5aVR&oPadu!prmxoCLLd!7v69Io7ABYaRUNKYo^mmv3 zH#cJCIgp#PIkUvDWqe;q$>st@-hi+mG9<1YM(cysur@5uQ3YTMm?V~)fiB4bB@d}a z``mI1PJ>n)Bwum4^)8fkXasrz?$ziuxf%ers^rGPLYtIsRE>i|bAwNw0fU!hAp=VhrEB<5FgA!SJO8YD&|t8Re5K#RI5+mxa;GDqJ6YLsRh>5SxrisskDK`VH^6 zM7FQ*(cx@%Bm9rqoJO8OLH+~BZdPaRRoKDU^BTbiewKgB1>A)DfQl0sZkxR3t3D^8 zahNe|a~-C;6c4*7V~(}E$Z(u$)tJWXfbVJ|<9{mNa8U1tG zIQIAa6}k+!wi^hf+uNCQn`CL5oiLZAnG4&UY2X-Pi{Op17)ykvZT|OrPqK|H+m!6q zKLCGvdS80qGH*_o^X1-N$by)r%oQ??0y&Y7OD2wwyw`hs30*L;qyZzp#e6*);*R

B%sT7)QI8XUn8%V8Zt0X{4gr+HdoCJI^jdG({d-v>d!aheLXJu_K=+c4* za~9l(U~3C*sQ&)uVgymK3gjwf6K1-g2_2(n5=Y?BJQTKK3T27i5VaZ>Zj?;a0d0S< zm`pjhH2`P=9)~cmZq#bBOxYcnP6l&pLo5MX&TObmB?skMYHzHjum?`|A9Xnd>i@Nrf$aN3*Y7jtp9kk)^)XRQxx zK&J$N04yyNNaE(TZsv3waY z>5$_S;+(BgzGU6E=}HI|i;{nq7EWKzSyILj8Ae|vKJ8vpXlv9&ndd0iG>B$V&^_k~ zk1cyFcF<-~ku~Qmi9VY+Ym3iCB&IyE4csMJR}RUP&3MX4>kG6)A~-od1}iR>uqOzd zmIO562{vP*+BKO)DVjJ5Ny5O@SS6s;Yh1In5uQ?U74#^CatHo{ z@J6y#9B0bm6U~U52|dom8Y1y&$$2C?C;8EH?Orz_0RpOM2*D?1(4~?M(bHzTq~Yo5 zak;CzB{oIZb~jDMJv@Ir^xC9F;}~R{Hu3!!I{#q9-YxI;FD@p342I{Ex9>c!T|N+S z+dvGnwi0awZM6uzNt1v;|Yl6%N>?kjoL=?kY;!A%ypMFWk?_;vs_ z7}X4RWk?fH$9I1-Yq>CjWRrq1Cj30ciK3Vk)QHg52l7->AE6YtQZ6)xXGCaOZpdbI z70Vy(YY6CsOQ_!9VVtrhZU@j-7Ky^r?xP7A^soA=bc6TqfjH|6e?Xwn^?sY|LmclD zo+54*B>M;F=l6M+wdDh zSi|VgQt5x{V;Jt$jYt_AkLFhLG#92R(LMO%R)fdjC$rH$)%W>KxbgvMLC%1Be)VE+ z*;O@T?ej={#6)v5TD#t7htRvVO;zV?-Syn}6;;N%ts`^$aRMru50k&Vs5^{8u4|G7 z)z*`#;)LjEd)KU0Du3*pI?c#1Av1bm&>QGpt<8V7tK6Vz7 z$LLeM^{Gs18uz$3eZoWbu{lK2M|+F_fyJG_DfW~k%woKjjIA**=TZUUW3)2eSxa~9 zHYp+!xo6F*meEf?ZC=y3ZiJRlG`BCuZDOu}w$?{uufnkIeEBh4P4;RGb188gt&{Vq zG9!PR4_s2PzQxfLLPYTRA-iPkf7&mPF)-{1Y==0yL{gCToX4z;qM`@t9!tI_F1z$_ zxZ^;K;5dbB^%x}NYxPUDqB&fFAde%Ezl!2e)9D!m8=MX_*(h$uOGqPqD-&Q57und?SSJdk{s1Sb*!{-b_TD#&GM3s8|QT!KVE3#|c*3Vkcq;43L z^ReBUmC?P{cwCxuYbWH*zkh~6^VXNKP#2i5cr}7dEN)kA)$RT4&E-?w4Y1HU;pqa@ z{sP6!*X-(*ZMxtYQX8&xR#P@^YFo`I`Av4&%Ma3E#VtL5qZ~2p^G4;aMRpuWoD*lO zLi!%!mu8;ts`Oos`bzVxBj!Ax_WlpI{kIY;0)JO+kJC61{+?ekNGqJ|wcCRDl+qq2 zSj0-eB2kdwdbjc>PS?7`j%;Vc0{h$={u^7uEf??N|qH`_ns6YvX+4Bi%Ti% zNbOQZkul7{;f8iLP|xi6*n?wuX3$)Uaesm}$OJYAkwhlP$C1qiPJ?y*>3W6anU`=u zQ&5b?QlvM4`PaINJ2F8>$ou92uDrNRc?6LZ+Cb$HoV`E4c=5;j6qZ0{fBT#G+mqX1 zYVVKl?ng6%p6{q=k)c(ljGyr@EQTY@Nx_2fuq>Qx<%C^40sqKcaXnpe{m~}UuYYBO z9WJ{RGldeh=0&@8>$Q)@<_P-gAq<^Vt$G5^Vo)i$?S~U#1^z4;ZLpXkI4VqpK@_aq zD}SGSSU)Gh!uuuQoi4Wx9Fs~##ITs|4qI1a&AY50rYj+1_Hj72>ZYS$z+ksK!1wPk z%+~d42kU{RFpRLs4ST6%)@Gmy*nf1TnX&Btd;;|qEcSHoplSSXPvcPB8^)f#5Qbb! z>*Sd14xZg|XffSYB-TvF-yWY`;&N*p6W8lgg28DVS{w>nEDtITw&tAs0X%#N9iofm zAfnl$B+ zn!GSjDsBuDU`mb?tdvC>L#||8;F~EW#5_ru!a4_sUH7W28iY+mcfRa*hKcQ_8ruet zx^guLX@Fu^NSTPKf*A3W`z35N|NdB61X$LIR2els`83U@F$sDrrN6T40W?;gwQB=T zkY@x=n(i0$MzlS4Uu}bPu78d5{p|6yv-Q6s@VRY&|09n6{?~kD{ToBsr! zo;$?;Yap;(0dZ|^((e8>YR$-MBw1tCSnan~X>C;9dOx=^y%KW{e_L_MqxAS(K7T%!yu3(P zspEt^h?wF;8zllWH(AQ{Way0@N3xjflm#5#MahOv?N0urpOU2rScE!j&EX9*{G&8n z{j{Q;WGdo9xh@fiAf1+WxnHKI;fK@k z@-)11&km}U*IXjH9?p(deR90&(*vqDbvrjK+e|5z&42K0&ToY_nmnsB_vq1``)4zF zfJD0Pe<3FA`j@h(uj*DBWm1FU0~rpW*DL!wsqM8(b+@+NEbPijR73Iz!_w$LCusrL z-c=EHO@s-gns#k6ixzGDwnuH%o2v;(>L)#_J??P+Mb!NoE@14-ZFAoj}D;nFHYjD*fMNg zw*pDfeMkbAk?BOMOt~TzH%s#0cSq`#qGUG>CZw)y-W`wk^4#%!aJ0Hv4F+=_#w_K& zRB05dnYvqXdH6cm9}EOra=Bt5hhO7leQ`!B`t{;{avg;%Mw(1ER*%1ie5Im9T>Q*` zq>99K`Ne)W>F?r}#nJq2dYvt~P~X5pUvESHXCx&l6LZ>NqiXc({PN;$nzFk;_+4xD zBa1VB@lF=f&Ti6V&8}je+h~!AkoE#b5@z#gvDkMlL~<5KQaRT?^Sc@UimS3~*t;ISFd=F-Q4bJ_7^7zDZcLGJP>RUY{os~zbDS)2^IL}siZgh#vSIVVDf{_y5Ky@Bqvb2JIG%|vJ4VoqAcuJLR zWHe}5#nR)v$#sc(p-K3DgQs?^@@N|wYfPkW?yYL)r}(RNl9~exH|er&+- z>$Y87sX~lJS2US~2~R_AB$>Dm-~~d_(7bK4KQ*p5#5e3vJlE8Jz)#)|%oB8{NE9rY zLIaUw(LXtHN#>25+XefrudTc5uQ!9fSM|Gpw{JWP%RG$>vd$%y-@A=wBWF}h#(aLzjv`AZY&-oX2ULxwZv(9s zP(V;6B=529?JjM0kHy%6VkuN9)7-7b-*1qNZ1E-hO>`ZriN6fSQ|#RkWPRhc{bprr z6=G{6!vrs1ns?`o<;!QTf;%at=Bgn7Dz;AhaSKO75!UDxnpGSOVQ=#golzVnPBHt5@&P+@R8x&hM!)!G4? zZaBMTLwT6L8BbMWkUZ!uakNQ!do65ADBxQ+)Y2&4y%)g4gMEXo*3Z4b-Om>qR^to5 z0iZjRS7O1djf+-~JA@$nIT+KRVKO z51zq)1OJ=#U0waNTD`PNZ(0}S#3XFdU|EXPt0n?I-D>=D_KZ4pcTfF@L-uP_rNkH%{Kx5IFARw!U83**O>B&5R4W2+*bs@q2lNBuvcFLs1MTnN*&HPsVho zTH2?=4)v!R33ap`eZwI;mud#xG!klmgOxQF>Wi_i0h$#{O{&_+EO$n2Fw|RHRC1cn zy^1Kbh3Cd8Isssr>{wX)uQ`!|+CEfViN zdWF3n2mb-3Q(a5LFcf{yuQnTol}@X_78Qp^dhz;vaY2XmpQgyA&PO4jf>Sc@U@N*5(H!fHi62)r%l z^RQ!%n~WyGPo^=E?We-q#FnePvoF;2zT63^h}rDMGNfZdrpm^ zb-ONJc%7gS?>t+rFq1rYe+)HZv+ZM-VK1v^DcDzEM5xNQFWTd5RTCV5fiFSZChD}o zj1A}b6wg}AAk%iQF_9w*&5r`*V#Osdyrzxf7)NP}&Kaopyzz*oF~fa-A__T`){nPG zcVsx`+Rv43F;xP!nDtXb>O0f<4mD=l&(a{pG@plo;PH&?1vMr1go{=4d_!R^R|_2K z{9MmLO;i5ip^Y_q@ZUN|qk;PBUn?Iq5^sLfWKeCsCS&?d@*DB)x_@ik?H$>XPqkP} zZ`(K!zWZ0qAt>a)Zm?H>$9DQ$AiHS_G{Np630y{|Vr}(Wl8S4j`R^T4q(thC6!jqp zIUk4f;_#!EXW1^BOt#dI2%{bsEcC@j95TvRe@ss&lZ3>SXT+!QXO!-5ucbu&MOn^U zW?Lq2FVct5C(-Q(BItD((~-zQ)L%SJhEW$G7sIGeBpU{O&P14hCL|h0UI~`_B4<5b zToMsJ(%ZL;k;5SBW1NY@I4Dk&9)~sRJQ4JPvO(OZ@H^cOqAv3&vZ^A;6JJKkhJU!a zxaB4)8yeA=CgQXgF6(f!#ZnMhG$Wva^n3*FKdhS(um}rh1S}@m2vn*|X9QH9!sMX_ z43iC!>Bk5MA?g8tM#(l!q66U3=@oiP^@CQjO77X!%;*7 z(I;o&!_ELo9HZ!1Vgt44q}8##OrR&x#eOp={#UxE3pG*;pGvpG0K6ly3;BFqc{^Xz z|8o*?PixT%rq(+7)7B}_X(`d+D3wbomLC@+@o5@>IqO~83S$yPk^6{xdhc%iO8zSw zNCSKH*X_4|n>hUV0ZjvJMBRv^dxFPuWvnPN<{%WRchj>%K3_{+-V_!(+f6mSrb#^t zU@KA+uBPefq&1GplOEklz5u6vd1|&h+RjGJ*ju-b3VmH(-d$5i(W_T&by8Q>0JLc9 zsHy7u@Luej;Vi9=+0f9Rb{rrj$C(%*a3sW0*MHap%bb62(-WTYc(kO7P zE3|Ng5r`aR!^sIq1_rw{+HxStK~fY!LZmLhcLWXDhhmrJ0)mJLK@(&{5DE|}2>KnB z^HdIh??igbWi+mC_z^B+VR=Yr@}tNGJw-4SS%`TG=t)pU?i#)%9Wud zeT_wW+tF7r7UxMo8O30OPm&}>KX)wMD=!K1KE^19#}CzI2N?-jK@+%&2YMf;NbfSr z;*fLX;%ZBkKqQD&5Nvyjco~bD^yjOhDqmrLM>r%YnBEUT%3_$y*po=o&jXNc9AXmW zU5o;>c+W_d>3r?eJlYoCK)})%h}j^fm|rO(0^*!YeS30{wZQk3y{@yU7Pch}6M8w> zDhWivv82X6ie;kO#Uko}^5N8Za@2dNr6%lDRrjv4uPbA31dX#u(%PS%Pg?E zyb0r~O@emaI+;gsv@3nJvoy-!; z3a}p{hHWkw@r5TA3Fhv()3q#$BFq!yWB3@x&!d5w(a+ImB*+|(9%TrfN@U7+G57J5 z_$VCpk-!6g5@9vi{XJ5nG;ESmUyzuBKg0fyKu&gx<7&uD5aZ~)l5fYpy-kunMt zKWjRBfjxkRQwc$}BXq4d%-$*!IUk{?I>M%wj6Z78@#{pH-t!#Y|R1N=0MrKo8Ce(XX$NBNrI4#u!}J&9bb*MKKk#Lx2HV zyalUm`p>py{!Uq-3B_SeS02ogb~fC9Up>0$!7Z?C+?>U!^62_{%>cEk)onr|LQ{c{ z4B}Y!Z*XMLgdyFF`@>2#RLj-LnzdX5%%s$#ZKq$@r&2L8QgkKKj;_JEDe@EExPc0}c|G!yz>B>9A0GdWvenEX=ahj;xA(JnD zFxZXuD0tUyf&c5Qgvm6|51!a^SXTkNN5r+ZG6rwuiQ-bs*3(9kZoKL8M}P7y0iy z{E$hBip2uWApyx}X2{WS_~zE7aYHL^4NabJ*1QNfqD{1G#{eqTQ{CE@CSxNzAwv5p2Nmv`cU7MLynW?0H^ zur2;D4u8Oke5WNDCvUk_m>1;hW}LmFQl(Ie)R>KfpK&z~eKq+?aR<3+3f0sn4*dly z`bd@^c~g!;w;YZkNuk4!!aw+tGT5f!#t`AU#)teDIpkyy*^`&u<-pyCZ+A;wZn-f@ z;8sF^FoJmk3E5$I#Yh6WhQdj}NLi^v@=iBQV3ojaRml>uoG_wqR02-nLq3o?f&3{& zN;*rrC+h@`3+@sn&9zN2X;?}IpneJTr*yw!^%E*N1$5Uf0j-3jy7+%1!8MVhsf&~f zlTfrc#bV|g z0BA}Z3Lg~}`VB!k?k8L*Q6DD%O%VLNK0h~q(K-67!Zj{!-@3B7T_98OH|Pwy19sq% zuL<;AZk%3O&Mmz*f2(H2XaU=VMp^icZE8`z*D*2^$-16j7&pewZcP99rkKrN-oOEW zNUbuzQz5!k=V-lD$}nYvfVTeyh`wCDGKT$_&`)^D2LpuZBCw$Ge5X=ftT6pH6ub@ia& zk@ILU85=-fHe@R>E-rkX+Y;=b7W#c~LKsC(ZR_@s9S?kKtK)L9F>F`Yjc&wrhA`zl zxjE{fZS8)e?M$>)-C;eZM}vs&!ClO><%rdi#dCTzh#aGa+IaL>S`v8YdK5W-*N=cl z^e94@mBfY$-)yQR2!NIBh-3%T_e!k8h1(M@5gC2XB^7K`F6>DxB?`z~hF08>S4K@J#;Tzqr`BhjBJVuTbZCgYk4W4MIHG2h%;4 zq5d$@SbOI+KKLY%R56jWTQf zyqV93B}7*XbcCR_jl%2O0E(yc`1|O#lHF&~OGj?e)^Z-N-S_Ls$`3F;S&K%$xC{LN zxa)H&*wHQuWmlp=!Bsfr*I`4B-BRRP>lAGe3Yb$NT5c#tyVeg9T%r@M&3C*Xx*SiF z{{gpxIunFof0i=Y*|0aIme+MnF(6xuIB#)aFcKXTkVS!{?0Q}P`*=u+qHIY{vP};L zb$ITVkCflf@^wBKBqUBTC!Ua;#&Rk5IT6#J{L8^0!y6)U920bvvfbj-?e*eAf^$ju z;+A}qilY$D-luOd$t7jk;`eNeQ<{9>kHv;$(r#QHe+o#BW65|Ieeo-n@fts*J$CY3Qz1zLoZZ&`AQC57;*TsXHkmkW_=fCgmOL-iIepA<+Py8Y zR4&r^&^=guWSP{pYwX;x-68W_Wpjfaq7HbkLf<&c_Wf%X<8<+-a$`&M`jo&|EZ5yT z@UEKfe=eWxQO+R>Tbg&_HwVBy%>8ZhYy`y~GVoA`< zR2dCTC}@hZB2}HGnIJ4XRTZHzAPrqyQJE?Lf2xavhAXG=P0P*{p<$|Dn&$K3A*FGh z*yS>2nM!*ROHVVj8i#g3!(9CamZ{w#uts*MwM#wUNc-r!)k0Uud*jHDBT?iz<5GCq zp6@clBiEemw2dx2^vY)O8glTA9G~9`BnaQCJe|E2;l;%n0&^ljkIL~Z1nSvD1+Lmm zf38(0){=6KC0gSwfh3QPj7-o-uBp-v#U}wGlg9~Kakg0kM3|@oM_-8WPAtXG%bMg( zCKKPEjDjQOPNu?84?!=_INHEadj2@dIg>1AX$wDiG>!^Rs{&Pz?_b*Yr-5A#A--|c zD0-tO9sa|9qvD3-L=BgkAI}fb17oRXf2^y_i7a@AR8NwIs*Ce;!*h;)DS0dwy;lVf z5CCp~43Pf~O&_2wqe)bXU9@^c%oKYLj-z3076FP*s{Kp=&lXeT=;tn!OQtJn|blp!_9X)=C_rchodN#ihsG@!F!Mt8^Sy zH!8>7Mygn{Ka$x|xn_mD#WeLwy{^|QrVuV(qslqK3LXAzTer z-U!|_b5ac_;Omt_2Co#hxo9FDf8QS{)rvK4V|CgcMXkbu7%Hs+Y6;z{;dpmVGXh%f z0Fgj$zwTQY>KvI!jMrMkGl8dSeHiwU`n!8@6Ifepzyk+?zCn0a#z)cAnSm}F+Kw3? zJppxQbhcAKh2yiJMVj$y3{~#R+0lKc7LHeeX*T~DNgFy%&byh~s$qpsRmCz^gMa_S zw9dgeGKuW9AT&xU{aQmU+#>@evU1aD3AAB2zy0#HuQ>1+z`pF{c{*X%An=>1!C>_6 zT^)KfEdl!9`|vz!i?7;8TQqR5q}L6`m`!j8i5WXLVE0Q-9xOsXTAhUBaAq?H8q&AGXe6`ux-0@4eUMm`e() z`Typ#H6f1OhWkxrx!+N9CW3$PQPb;PuD_rAblLv|biDTM@WN-*m7im?*%UdSX<^7# zFTZ~@E?=eBItR5!LLHf5)3&-j?xli^-k{*lRHm}|9jijr0mtp()z`M_3kbe7t(EPk z!9TaLMICPfw}+w=40L}~%Z}496y4`5E>fi?RofBU&NLvwut38IbzntN<#BErLt+Qp znNC&p-??^@z8{cH?Btwt&wbc;@5-zUf&_WaG=|1%!R^d0OElxR(QOb&R-h>vNBESh z#q|E$!}PNflKxa?=iB`&$I=QVr%yb?f_=nPNZ~#_D*IiEKNWv&Ah-L}nm~fYU^!@H ziIVve$dNJNg4Kv%6#zXqy`FzV58jtdvjUjbYR`SOXnMix*}QYAxuLnv#8mF?75ABajcfHASc&KQE%ZsU27Z zt95YF9M{U2ur7ZNbaGPfL%Y*XB^ot*PhV}KYP6M>(6N~?gIJ}ZEAnV0q(t3sl^Tg# z&pP9vp^_2}%r^LcSn=2=ksxL4*MoSjY1+~%pJ1V0FdPntjnTG-jVDj{;w|5At_Vz; ztTqxNg|PYGH1f^ZwKCdq>7G>4Wb%x_o0x-`2&hqVG+}=P%#a044~b`dwgT>eg^t&U zeH%lsHi$hS+DW=@$ab|^TD?4o-E_KO);o7?I%Ti!zbpTYNh@F+ZyVFUfZhWRVwNPn z+B^9b>^DAEdCs15N`hLjxfiHn(K&5hpMgE`L!}eJ{!QGE`E}=)#Mawptby0Xy?*aO z=cxEL(`rZo5*Kit9v)8>*_@;Og2u2p6@^BoJA|(}GP+;g#YKr|sEoU%ez|knOqTL` z-Qxmgxp8a{=$Vu!vRs07LpK z5Nmg15wza){=zFY24oeGi)5M=9HWb1*^&gPMOQm`2v}qg53OWmcPy}O!JA;b_myUC zY^od?%}*c*PGCARc^Z7ht`auQaGA&yt~8sKM%Uei?cjED5e`)C0J-ZaPye4GK$2M? zz1h0q&Kot7KGU3{U$<%-6kP#-?Hb#b+qmuBUxDoL*~mF^F0anmPLpQ4Z8v>LwtY!* zayS-kbE8{HX=dDH{=EQ5Nt7&UJdAN3=+0zdMDUG-Jyxe?$l!Z!n3?cQ? zq3yrQ!#_k^N;3%YH&Lhyc>|g^_z_F{-V6F7i_0W^_eZ%EWn4TL2$)74n3q=@nHMTU zuriO;Mier7nW8MDska7?{5ic4v5NkncV!~eV(0)%?d4Ujr7;7$R-XOqZ#H|Gh{4^x z$Yp2qb#{5Y(v>zX@yGLjQpM4c@O-L&lBv|9$h1@WwoEs4PuOH-THxYVr6LA2Bx8V> zl6vxK0{G-wU7$!oOA%#hd;qH`nC_jz`k|U@!}J$V1pUx!0!O1VF#U+1LtwSp!8DfJ zqB6mLU=++NsdvO`!rv!g)oQnIqkZ(?0e`~-c$Nz-5>RPz_9TRVL|m<4dM=91{*C&V zggF@c%C?Y|MP3%bTZmL9sz8&3ZKk126JCvgDdCX_89@y?8jmc80%;66Nr zE>(=V6|w6{{nJ5_VWa#iOJ6LuI!j*E*9knO%~#DegW2qV>BJXXiu>}PC0?L70J)Zd zy||FLj&#x;6d90f!ucTtc_H<|F2^W+gX#o<*Q2lt8(dKlX**V?=(20w8yWW5zqedM zTE;P~S&n{?4`#67#p9qJcye*r8uvvCbgFj3z@xXefUo7&Ao}$h-o8IZ<@xLlxEQj7 ztifg|3_AsXaY$Y)vaPR`&^pU82R6Krs2E4J&~xo35_-^v7b@uMp}2FNWih%Uh5DaR zC>U_~H`=AN3NHjY4Ukpw8cEIu7}PUh_>jVG*wB-u5`&mbGL24dXd^`u=w%q3&JS%2 zj+2@p_9O$t`L=sN%c9h2lZDPGYpq6u9*HVoUC|0>3 z*-|YW)9C{w1SE{cpe#z`Qf&>$7}}5ysqwQi!;&Ta%!Xur>Bs6lC^VK|f3FhQqLL4} z1T2?-)^8SzN-7=VZNd#N9%;;vQef~6D(2Y6gmLMotEm>^^?K>Ry6)7v7)OX!e6!!d zaVVLu$oVbhu96#0d7pVyu*7lzS?==Lmg;;Zq9}08yq&7|p*_@Q_PW=8x) z9d>jR_ZWQJ+z4&Jk=6xXRG{1hM`X)Y-!>yX4WLXj+M1A5jz-*mzbwcw!hehmtGsJDo+<8J2=~T zJ$tRI1oK0teaoF$x|lGotnE7^>LX4M+2uVa0l(Bqq;x?Q4~HI}Aw=|GX^0(UDWCR# zLR=r;ts?>~ru!sN@j2{2AFv2jW1O9%3_sqAtzm*Tn2r$h73D4$Se49fCmCyOZ{IhD z%QZ}|UXC&MV71z=1pfW^1L>kKBvlWVK=ABBXzJuTamv*Uce#d-=c`|3)H+(+Ifmw| z3tOr7vNFOL8;uJQRFz{f+d~%H1%Z`+KeaD5RG>FgPjiVO*>yBj=y8>3qb0w)4)ziq z9O1CUwtKHCAkmfcKl^fFiovH%F%G{BUUc z#tu0uf>S)wyP4mMyH1v@<#RoMwB(VF=pZ3M+x2N?_P`CFUwa-YfKX; z36ff5wTyz3o02)5gU(`14CYegVU;_$6NoaB=mNatUQ?^E3pd<@OmmihF+d8D8k1Sr z%wgv=66DU7tTo9lC=q3-ONG0b=v-=41&_{%PoA*4Ch-HDI`5=rJXy$gyC^j z3)Ni)38O{Sx1J=7Ofl$x`QI2MoD#u)h0edrDwew}gi9jyGTOr#mnZ@yI>8`t)9s(tcZpEl@%MeoSz_ulsR-u9?_5n7AG z8Gp{PoeUvSS2DVxi?Qa%lUm!g@XxAYVPu_VrO=0t=-LgY{UdsR%dk5wC0_$JT)G6q ze~gCdk-awm3Nm~wIQB_&kA#$&8 zP$ZSs;@#1wiDEHde@>H-`9#s+j-y&C%cWU;%eVM3*RoB2xvvF)2tiJp2YTAjBa=$b zdX}3DEK0&SppCaO5sa%X8rd>VLcmz11T^~x6+0?MPb0wJ&Gogp!Zmz45Rn=AX#S^Y z$^#`*y2wRt%oX(>FhCHL1Tha!*&Y}NB2K>2twM|cgXV8+w;xum)5v#T_VmXhB3VFzW?TXJz>Z1;+4`35*bW8SF@0+Wfz`Gv2y!&s_d-j-!?{nNBliFl?@_ctV`Wi(NwcC68ET0 z6J=J)okw-6#;uEHGv^2G7K)x@SnZjdE-cJ!&u3k71$s48ndG_6V6_+VqlEsZmP?i! z1XZcv?P7}9kp_!F4n?{xIoO|ItP8^fb8Cp}-ewxjJ}cW=?r##NRF|N6nl29J*>SDt zjgCrx&OF+Jm834`-{}dZ@}BBkt&i{DUwKyZbu6>43-3USe7M4!p*@xlu5EHPexTH3 z%mZ_4a)S4QnjwVwuTvyTrRh7X!ryyXF6Z`=)8p>*d>S7LtZGcYxq(j+*~L?~<49^C zI8{!P$y<}$DNYw$h_JnMaNo*QL4KGoa!bvBGGJS9nzPU`dvc64TyArh<#|;)*^60C z@Z42OFA2`(*Yl$LWiUKLfzJ4_%PPj(0o5r|fRIzDKx4UtUR*2{c?suQdRs#_azb>z zs`Euwgnw$Qmjn%Hw&d$Ho!6WDonyc3R#lZ*F?+?Fs)FllT?LKvA}il#W7ur%pCqM! z!QM$SSVHxw@dBb1LG+EPW<<{!X=MR4k;&QIdaY&uYN1xHUx6YLr{tA`#YH>tK<>J84aV=`5G)%4l)I^gtipxrt7mz>jzc49u| zg7Qe86-bmy1wSdIoc)_3XghYG{1#Sk@G$Y#T&!bv>1KX*nRqa%pAxEpdudk-pvDf@ z9U3?nPeR2gI*SP zi5=Mvr9=Gp9Xn}~UKrc@P)GK;eHVLrktez5g&3qvp|6eNfq68W9QAC{J@-7pGSoQ> z5I&`Hy}bVZZMl%jEN@Z8Nauxaom>^cPc&S_)z@7i&UYiOp99Pdmtuc;Bc52w!w)Jh zG8Cph*h{#h^$sIcC<4^S4&_>36%j=o9`464f&?>GZhl6AiWy01Uc?1UK_LsJNH;)S zXboR~u#H3My?8*sQLpD#=)q;q6w81MGoADyW6yKwte6Rs1^?jL^|t~%P?5<5zfrmaR1IfIcNzJmfxJ52k!R#ht`?I~Oy!60zE2x{Au zse`%m1I6r>Zcle{F@rk3-1A$4@31w1^0d-5Gk&)Z=W$a9Wj$vBzq6xiDTeP<^DCs5`GNbI}s`|i7o$JfQGh@uR+ zWEx{*wcvJPcLkcs=j1Ai6kDSy7)Q95`6j)aKcx4i;#TB}PD_Ju%Ph{t8fVI)UQ*;$ zYx`%e>YY8n-G7#2;Skc9dSy~%U-e75MrHR0odoxAlN0{dc20ien_y?|bo<|vo9RRT zA~=(2qpgbcq073c1N80VLn=j0*gmcxU4V0HkrA9FID%RV#UzlK#=typ>IbndB)SR> zJdyyW8xNzu5zulJ?Sq>Y6V73GT4?b~6rho1xstn1D1Y?G#1iY^%YNVgLm$4pG7Vv^ znO_G*g%jJzM$ZBg@PjXl1OajR!n!VITA6(%(X2qI;QW4`RVa@~ZCfZ7;WFEr8}JXaIJwHg^8L{#zb$KGnR zrB(!O?0>k;+_AJ{6kiFMX;g7C0;V!8-zpzM8C4r61B8%Ah8N8!#xB@jmG3)AJx~#Bl0NkCXq}?x%Sz zwwRrFy9zhXY?pG{>p(z@w+n{UjF@g5=;?ejfPdgtqOz+8;_<4wvzyhEPLmcp8@{`~ zA$<>V*ykh}PMMk2BmIqx@8g2VB}FmR3=rDj$;J*_vKI&O(~Lr#qz-y&dixJ7Y=#z zXH`_A(H66kDNM9cJTn_}tWeMYNUujD!FH%CmLYsAIQrG{+LH z&NC{5YW-O$cKm_Iu+y>oM;8v5$2cW-C8$L8!VABdS0E%w|TVnv|e*ASP8beT0@fw9cKvm zuBt(QH7qS}rkX^KUPoXTd1?!83&yGXB(3(3CC^S&Hk(X}ns4G1oDvn)ASh&8DavC9 z55@}f=^5>)5HQyCU2CWC`c~8UczIddU&1GaHdO*jo7bDRqlMS`*h@Vtc)3+5lJu&s zkJEY$ygcq|YznSt3(NW8+6j9&R7|m5O`&mrey4DadILY1H!h=y1Rg+RnI}PM_4~sVe4H-d>0qQDgSzi#$6s)JKFPJZrW}(= zCx&qy>l{K0C#P)Fhc`}r_tD}xB)@q>Zd;Fu3}p_jsf@MUs|=g%u%AnN*sQyxq0`t~I!p(+ZW_lvaNJtJ zxLsxoFG<{$BA(KKF7=~&kZWzS&{4mD5E*r*ql%@dB8jL&x8bTWc>q%eKu(aOVebART>aA7| z+6bZ7SETvws%&>rz@Y&X|Cg>$SlNG`qCwf3D@kzP9+2IshxR>`*oTI_>EvO53eh9R zWs!c^f#}BP&_qng`QLP{pnbzcV=+x<3#Q%Op49LGvNI(ctoabcr?n`&_ z73n&1p>l7de*v{sO;6)65WVNOV}umu2!FIla*G3lkw!7G5~-3@5@R?2y~BrONtT@e z)xnm?;mq)xZyx7g%1t>MrI_SgBQsWu#IEhOM6>v9dNvwKUZ5#?g77U@FRQD&>(#eP zCRQj(yOn9JU%e(+x{cKz@|ou%{i>g;0;O#>&bkNO%cYVQUu|#aM!mFF?wmXRcYknk zb*-L6!t>Q%ynJ8i*6J#;mByis|y_pq6;{G#IWPbCK-syj~|t2AEk8q^GOqr`Hmd%^IP1uTa}Ka^z8|9LA+a zgZdf&#I1n^kTZDXOu#=f_BPpI!C{P@&jm<)84_gEpm+*D8UxJ9UcHuFrhh^{)$SWM zoz9mUGm0bIT?Hn}Yn@DEY}_-p8)4?l0MjA@1%hDZGC`H~k@-@Kdqv%?Z^c*DfaPiFb;MI4>Ym==zITjksGu8;*|N1bixqr1IU|eYDOtaX@ zf`f#rqvI;wc_U<^+Xv6vY->BBg^E3D8<$e%?GCB%8xa8i-nwr~Ok}_Y zf(M^IwJ~g0jds6nSAVP?YdUg)sIG0Xj=XyUV9VVN4O1KW)X<;NtR@5@d1mv#s?L^7-=*CyZF|AYdblDlPjBouB3sIs#N6E3}{O5EzyKYLzwVI zxIv~!j*7?DwSQnBqR>vU^QJ$d94ve97tuEG$_9Z@_L_p-Bt>U}ebG!|W->)or))9Oo4iV5ufB5v_lSgtr9LfCN=d5rRJffd|8M4cAM` zv42EpEfjwRB%&Biaw*oHD>+guWr|5G%Rl*N$c{7B;Fk-*<87Yvd7Mk=r7|{Q#@|@t zMCcK0GWoLEhZ$MODlL4D%#!Q=xCJ012aRxuLt&ApKFLehZ9t$J;dUds@bR1Q2;Z&` zqPJc(c$+|l{a$Hvc6wTcIwe<%nNmsc)_-Q$#T(Z?XFK(bms}*kJB$W|Dn-|xL^bZS zFICS^Znl?NK^4s^W(}u_Vr)!~n&1Z+uDDrVH!Lm1?Li<7DjFVptRXzPdZlWo9^2zh zNGDOrRzx$AhON`{*I93Sl9RB#TAJHrsh+6SaFX2Py8ezpvTZwM0sp`p{PW0rtv`*GiYD?IT=xzky{ zORktEGM9ZD&&JXxPNwf&j$djzJBm(@kI4aZ`#=6K8MLNceT+!*#V;0{J!v(~Y?;@E zTkjaA@4;WUlg<<|;eW+fTW=ya6n^JdoJvT{L}b(LBMD(Eb|XcK)M~@NG(?dz7;rOV zQ`-YcH~H^9zRZlr3^Y<#Di6Te$KUzR)n_gyoAsvGThJ^gk|s(^mgxumvY~4HF+K0~ zI4P*wkc`4rE_U-Tvzz%<$urFa$K6s<_)IjNv4UO~MXAYSPJhqa%Un~rM1c14AAqLB%oiY=976)XQL zcEQTbIKX~)F3xYnie)69SKv<4iY~qC2Kw{u%{*tGVtd;`8Uf?-hXulEgnNgmunr-4 zB+AqSP-BDOm`fzeJ+Y$1s;@?Ym@`LKZ~7Q&`t2X64ULPV6t7z^5&d5XS9d zzL%<(UihqAS$G;%x!6Z)W@~h`Weh~Yift)}-5S4`hJPKd5ZL7CDDVM*C(LjlnH0+G zN%~l_d;xlm=W|N7RN?;`FeL4#=z;W)eVxtx7l=%I-nH3*MNP!X6p3PvcYqX z7BFN@cz;I4G7kQv5*Y!OUE&_n^BB+ja$H$(9MQ{oNcXgl8JO3YdK9;o^2pV5fPHob zp9-=Pr)UmNSllo*+OYY%;?QOlFu7rv6jnkhNs~Try*NnK=|k?%u%BysB}H*%wPVIFS)MCw)0kjEw_OPA zzFcU)c$w=HPuT4&7unM}c55$Z?}jHXb{z0YmK;n9KtWzU9F60GqA3OA7!j74%zG3f zkK$&X7gY$l&lCZ?zCvOm6Ad_#e43)0jemW{;;EsYq_M-j=awW_w9~a{DJ9vu=F-%Q zxs6&ewED*tl;kJMyszji+AmBj^CCM=CE~>j7D}Q-D@P?{-6eGW5TtDlwXZA zPOnk9ZES~LI+8&!4+lB&SIMMp4E)rpvy9Xr?JOL_xgNu-k)*3q_NSY@>GVj^1ZjxH zNmR%56A}9%KG>rO&d}q|z!#N6o=oU3DrMvS_e)HPxOES{4Tg}oaUrb+R|toxu09uN z!R)XN2S*GW%u$ysEAgXNRWr+vF|1z?75|G(|2Z=-#vr7B%W)+#s2k*4?;p2Gv=v)f ze^p&?+AtJ-&#&+U5>8db_DTzMqOF94wrOQAD;07R2P`>uW;;#k*8je1=gSF{`2iC9 z`rLcYJ$A0=***(`m`0o^inUQJGFx-VsGfcfuYy33lp&3!H+!=!-K zTvK#Q3|+I7F4HtOJ+LJC7) zO>gCgEWDYut=s*coZPJBjzxrT>e|Xk7n)S0TIkz{)rPYwVRyNNv;kJBZ47V*-~cLN zf^Y<4YK^|i0O}5DbgmU0Cc1v(nntOtBZhMv9VH3V!H?f1-hD z1a|S`iwpOUF3`;jQOM_c-LPJQkSc+e&Z^+?>16(HNL6a(BJ*d?qE?gbHj)CYlSc-3 zEBx!bpe+|ok)TD#B6#?7y%>g}OHgWK$H45F9?iUsEeM00L_}03eO=~W)C55jaq|wI zuCd2sbd!>u9I>5{iXsB7J7}gSe<^#V@d#Q73$}M{HE(qd-KxAwRt&@i3(WgLqZwE| zr#OU)M9%ru5l1WYw94Tjb|jpmj^nV4wvgTFisk#UEfh7m5}=7T*Im_mZs_$m+A|(2 zDsVVKL@9FUHLAjW?6H386w(KcDTtLa0mZP$B0o#XPXi}}Yx*Ipj3|uC%y}BTMdB{#l*>0~>dQ`0SHRTCzf*wCT{kLQ83_E9@ zZ&Vqst(tbrX*E5|oox^W&tkY^(Ll-K5_$J9Ff1P+&-~~UaCC~_z}eUm|86^F+m3rq z3B%Eh=w;>mZ=jA#S*N+|Oq_$s#9gsrbs^co5`C~OC(93U!*#n-_{-ci$9@-n* z6Y_V?6xGN@chV2NTjV`BBkpJx5pA%4*)HofyY$vu!O2;1N2U*hnbYH*I>G~#L=TVd*m&{;noe|t6?j=V%{xlp#kzyIz zoN2LGdf0NzJ!>w?5_s_G1 z&qSgMDL(+yAuQI13Y!GG{jGiSs?liuhx0{XnJu3)-m z!YAKL^I|Cl-y2I3t`)IZa2E$a02#4i4#6NxwURH8i7louAYKYQ3$P)7yzby)1@XYG zg*~4H1PIc|6i2;k$Zo^^=hjA-ps<8vY{wnE|4!~2ZNQmQ+QAZiv?(wP3}l_3;KCK; zB1b6{f?ob2ZY^Ymb>L5}wM+rG#HV9Ri9o(Oyf``Q7^G5erf*Rv(uST+$isesRjyzR zZPY00U=CGRTqikr)g~%`t~rp%R>LdUXp#0z?x^sP4{-1=T>KYK4sf&QsI%&@SB>F! zd3st2PT|&|D~uu+t-J2tmr0GeJa}XHTFBI(iiw55U_k9tTkHM)V|2`N&J4>c!;Q(g zL7c##(fzIirEu$M<3#Xae~^5t3a953nTOjAGY7-nA8$;y;t2JBdo+|9&Tmh$ob9FGcB7| zVtZ)hBTGy4;T1+?&f*^RF2~gDU4GZoL#}qIl;!bmQA(zdx4Ag6Y2g$5*}kf2Qy24H z-IOTin;#!lEr# zIG7vTi4ss)7S7C&e}mdI0t7y~({QA)+z>L&a~Lf*wiClBh5&rG=8!&vKA^{h2-w8{ zMI$SBL`4XunV*T?2z;uki!k>IOd0TvfqS}8jJ$s>-04t*?_LawjC%Y`72=+@#AEgE zRK<7s&{1{;#8W0L4sARR0#8;g;Znu)7sL~ti5r&$dC~HVil5g4TIuIQNfzr&Xvik>=-jTGzM!^Eq$zWEW6%@ufQ@!~U6c5h@pp}&W3%py)P3|OJ z|9SJTD4Zksc>SZ!=+@M6M6YkyGtXC_Djk0Wgn9r=aL;plzTD72c85x_J$ZVy@urWM zA8O{!(}OOhV(fX-%Y|6jqQFl6D zOwn%ra2mdt$WRu?GyM?Ga#P5LKnsJvmen%9-~N{HM6Jvp!K{WvCuT}*HK(KZaZ9{( z)qPp~4Y%t#7Q_U9-BV3(+b|5h`&SS~i`YSuV%N6IHf$L%VAzH(y%`7;nT|Eclwr#G zz}Ej>N%ovIhao$31Ezy%h~(oV^?3WLF6$`DQEJg(!nRS;uI!;ke)%H3i6RmeaxEmn zdu?{vV)-#!>?PJ#8FKEHe{tM7dxr%!ND^<3zNLo?-|Ulruxg9hJ-Kv$(L)q1NskCz zH;QcGt_wv%gQLX^_rz^oo5o^3WDYC<_ZBH<_&{5sRsN>gv=x#a0;2B`xN|ig2Mc3( zU5iFkFkszQYLEE@f|M8-mCbPm{6XD|i$8X@8u1auri z5W4{hY4rgNVThW5pd8phZqRwR*c@Q=q~HujJv1m{l_MxSI}M35ichmXldBU`tM!j% z42m6<@F>vwVZan@DQtJ|gTz|n&nC{o|6-VxPb%DhQ}OjVDPwrosoT{?*turdy7^R< zmrmbgHx-<1X5n|`_kcD@`e*px*wBh)iIqsQ(Isc26m}(2D9ojB@8de(Ahn9n%_%>) z?NV|yc>>w%XFB(*m!v07Pj5Q6=4;RJ%-q!NvbPV>GwwpC(!ak7>rU1=2tIECo=wVK z)qkNAWZ#yXs%=gL_}?h_x6Y%yAEHOMb3hh#7=PbO!!QuX-}6_Tu!nX`hOh3I2vY=o znZ9j9vh>;p+ax4uN0I&SrcGDo?9@CYko(^EK6lAP17kI3_T5$r&Fm(e z5F%)fMp1_FkjedK`S!fIFW3iKE|Sfwm6|5#WQFM!tkCcXh4nY4(|?n%no;#53=Fd&DC4d7HtZ&K!1TE z=*2N?h8jymXj0(fL=E!q9g^}|^PpwcH*X#%w{=x#S%F+KgSmA^aJO_#jdps|9cP(h z8?-g!2;ZcBdHnkD^YOFi&*+3I$?fftrkWcYNtL`pIPYBS8% zLNN)1tk8_ZJYZ`65g>mFX5 zq6|ak`;1h#J37>eS#Nv%gbePs%p_S%g8Ee12Pv$ZJRZwxMi^spyK5cJ&NPMjVtlY# zUg3t3Re34L+1|0%Cdwm^uz(SrQB&O`MB#`v5Ze3SECVUN0~lR<+;vG;RF6SJLtLQu;v=t&#%pAdX*ax^w4+ z8iBHaa0^DGKv3%2hrwWQlyuxEJ>Ro`x6fP_-UEM)k}+?CFc5`z{|XNoKuU+Mq)DZ! z?Ubo>D;09h5v)2kvd>LXl>c56f`ODu^@7Cv?)lw=yZgGT2`PX}W+1X?1jihk8tnQu zUJ;_$9&F7x&}XR++0*MbdvN>{P^g`kogE1;`mmb5NqGf(cHv5=I0~%>`7zyQ%ox_> zsB?eQPtS8gVQw#We^dV;&;%b+3dJNfzzVHoLwyO>(r!O;B-EeUeMrFvuRP~kc@M`i zIs+r9ZBOm!LKMqu$)~3a)X1bS$YJ29x z(e=hxR|%hBT!hQ(nd0A<)PgLNq;E3pbs|5v)nOKy1Al=Ol9pcfP};&Gu`8rK z(bb-ikef_X3&)9UhZ0c#`;L>;O~VGQ4|O`8d2c?RJ-f*_x#z_g38v83M)Alzn=(f| zpA4@(PqGws&LV^#BHKRQ|NixKS41ypxJ>A{(5-{}w+M5?Gx_u&UzyN&%kc0&T7uoN;Lg6O+>W@PO9%;-cE&0&a7rSPFt`GjrK3V6ZAX9z;Hy z1dy^fI#q>S@^@@p#?_t|E5V~f!q3l9CTR>sWc=FEI)5qtN|}H{7H3kFz?5R8r3?Cf zh}uzp;r6c?P+VoL!-nwT!pCE{O<9tKJdv3~VARx7b3Ntt#KSB{8~YytX`X4#R{}$- zIOewcKw(_Sm`Ovnlsd?DCLI)CgFi4EuERxB7R+GM&dx5gQP~zGZlOxC0o9= z_7-1CWL4|)9sTye2t8<|tCwVA3Bo|vAH(T^qJliM%qrv|hPkV=8hp60FM&+_$+uR; zgH^F6t&_7XglO5hjPZ@kSJ$31u4&pV+R(^sYJb2qg)N7vcb9*b8=~Hw;{NgQkf= z(}>HUG=@-FIe;I1XM<7?2Mo$On6b_OR7nCtsAH>E%9*4bZUe>HuI-#;X+ zr&QMBS+Q3Ly zBgjY~ccniXjhe2k%3)hp%>}j3NuAkeh(=`{?wz;u{sNafXcoSI-*4MC5PtVxaStvm zWpdoS42A7D*@kW_wx_n(OA-XMbe4!pq(D+})FS`;j-;$#QH%*k@mn=s3GndEvk6-`2|GkR8q2VH>V+M3l=qGvyg)EUGui+o89Ss`h-%gKoi1l56U0k?3T)=I~6e}R-+H6}2 zb}--9BM(Y^dlf;!p6#kjLjPfbH-0OhMYYd)++llsjHMuSRcr$9NEcIz)%J*}HNDE7 zjvF3x#@BL%3g(%+pK+WL2h5eTp4nz4OhuS?!o7xt&u!tih47=@zFNU;!BV;8sgMeR zQBiBn^_qKs1utcZ_Q;>uP?S<@zRz(L*IqDVC>$fW|RkhOa~3tyE%V|tolEMA-tOs{$?Vsl|l0n2o~@3(*BY~blTnyn5a=r)Z`LQ z1oMC?kL2O*!BVg6cWoLAdOz#s-iLlKqZ+J#fHf@uoT~0VQ1mPh*6t{z);GX%J0WW* z>3f9<*=RJ-V2FU`lN%2RngD^0Gc4E}C27j$YLd93IE(G*$T*Z*Jgy2*3CN81w>-37nv^!`L)w52Le8VXQe6 z=7}4He$aS)oqsee=wP_||CibSw}@;O%m;r{+b|Hv@BS2f@Jy3TDbs5x(2`O@rw<00 zo-)HIvJ$JvvPY6BDdoF&Wyz0VM&2Ytw0bz(gpglzE-S4yLc(iS z5M{XGxzl%^LvA;@GK=#^!;~b#KD;Xa&azx>UX$K3!7^slrnLs;*Z4c%BmjYu5lzMpd6ajt;#UF^l#R(!M663-dxF|bZEzEu<@DY!dWKe(a8N{i# zyx`FB%BA2GR;8rX-0$viVVGehH6thN1httb*AVmM?ancqi@Qf3n9>-gFK7=BV%^w% z-S$yJOzm@D_OmcNbF{oR`>OLtM$2k%n78_x{{D3|Zu2_njuWyEJ;}>l_}9-QTsPYN z37mdH*#@s&Oq|h!zepU2P5pnOC+!szh}XW*3~JkA0`YIO2SvRK0}q~B8A}&vy+8O*BM6RDQvZh%BOz~shBC1blcXI zjrIzXxFy*jnu*mg+m1}9&3q0{DswnML-rTdlIz<$O!s@{^+D#c-uY>LL_y@T?$QAy z?Oe5K=i&vywDT7t#I|**!fq9;FxpCk)VfSra9zBD$l76x+HDeEKHsM|)CJH+-*NzN zK#;%K6+LbGbzn`rI#bsmf;1j~K26(r_9R(pkkw?X1vb4T$ZTAKU|$_9)|ZALv}x`E z3+$LYy(_*Q z&yk+23J>Eh2;-dai}9tseH{LCA!;FEhy`y_7`>(RL7FD%yC5D%BE8t3#z`tD zsR``tV>mxeZpwszTQKKWX>#MlbUPB%ZYg1hVKxi$(UnfGh2M{1UJ1v$>68Xidx6tM zoWrcr4tNG*V-_q=$@@54%;(fO!1g4@fm>e+`eT$k_#o3ScGEPtYX^IUw7psuupNwM zgeAbPK$_aYw0yOL(xlW5#^b6T?nDi2?1hR<8esXA23?|mdKB<>s51eBE*>q>Y6baL z#3BtO%jDu%$$J2nqs8n}q-_|Ah2Y{WxE8QFl_vuH;z)uCB^S5l+2l=^cph9vq84@$k9aMNqS~zZt~QHD%^c<%Tt1DT3S^0r=J!VMx1z#=az0FFk!Y{@ zuj1}h#MOy^xB``(<#!QI=+`1`uKZA>(`Ix8u_S>wPzJYQmY2tp4R$JkuB^FQT)$cY zE?S}9$Dnb3tOWr&g8KHq68Vh~wM~}U7q3vk4ANS016?$FpNSL`>S5+#4og%;Uo#-G z+NSO$0gTa6eOd0lmTXo7>VamLVcd`%kAj98F!#rQFuyuOZOS#v6rhWW2BI^Sw$Bqo zEtH5eaT>(6{XU2nv!jM_g!w-NQ9U!7h5SvJ*7w!hR6rx@^HJrj%R6Y0fdkQ$3FN9D zwPYWJFw+LL6Y3%A1|Wr%h0*~bzb3HpYML|-gWKAyu(s4uQrpg>>O!QmXt8S+9M-Dq zSpYJBHBM${u>Xq7TNe|iR_;#4RMfVZG8+~&$|t_IL$slRJxvtU&lj|1uFt$-Ue*De z1u^t`{Y-W?3ZfuwTWZgmFwCQ{wiD0h&^`I2Hk*2HcREeQ6b51g*kY6~(sqE>adozs z)n%P0uN!FKT%7OfAr6w8`kpvX9Hx;H#QXVwydJ@O*fiDVE$Z`rys9jla+3~|GZ~1+ zC*gIH(hV5lIa>IeLn2Ic`3jIM6R5$;e$ZAXz0B?4hAoSj)I&Db^5M~j7 z%$jhR5EsXbe7-0TK&C_fDdp)-;2D&2df_V)LA+g`W7 zzyhaY0-_gJCP^!=ERL9oI_Ys*WhCakk3j&E=vs^$&^wT3^x-xVaZ{X$Xo3r4*AiUG z2Q4;L0&W0Embj2&LE+GAa*bt zP0P!a8wm7^`BiW!XkC9;Nx5krKdh8$=fg^2A3weX{WwWORHQdUY9)}vAp6L=TQfJLtkl6&hP;t;!FE&m2Tc@%I8X0thD&WhSUVq8 zPHwlG%KjLF)?3zUIq`xHM_xJhHO!yQ5^5U+TxVERPd4Mkck9cIeO>?BL2FAsf| zT!R2xjtr45MiXhA@&aV#FwBNgs4V8CypQ5;C=3&SDSH;oo$1$xg-U0Qq9DuM*aQ&g z&MD7*ug?xH=6Ysq1slRl8M$DYnFxlCSwkXw2{_PPi!Z>Q- zSKe+Ef_e-Ky@y)*aDvOPzvcCbA7eH!)B4JT ztKWaUd%in-bGmzfIN18Rj6`~n`FS!AM}2P-IvM@iHhZ4n97rn&+H6N~gF1Z)0UBH} zoyu!2j3++(BHdfQS@+o6-qR7Kc`rQtxy5XF@~o6MgOkCjNoTIy$c72~k@-|R4oB}P`iqEvA&f!f8c;b2qD=HE0J)`` zXZ3(1bQW@DkNDVmh?ImQ0|W4+?C9oI_)~`PZNhssboMN=dKD^GWA)&}`RVT7`SIx& zC6*J|?hVuACiBsX>^*z->?!^NHd~%bRT;FheO>Nzv1o3bTUgDcHBRSd)y9?pSiEs- zanB2b_Y@(2SQv}-(|bB8zP}(2I5$527RhLhTUb?8YXE({PWeR6miN-bzv@?CQfZRK zyqD|HpV5_K=FzeJWhB0*RrdQ?cq_&`JKj_JX~5xhbI;}u?`g(=x4l1)#XJ=wSmDPW zu6#G>q(Pamq`{!LO2%FoL*2o+j0@WZnC4*=ohC_t4#;kd?U5?S z!c(Dt6BxY><1&3D%6+HxhNh)rR3K7hu?aA_4q=mum?oAV-QMlrwj2dsyT+eiO!FcIB#R zJwwfwcA}7_z33V#lFdvu<=$+&rIoxSw`Rza3X7I$+ugZNrfn!6Nt3uN`E^jYj4W5X z*MZ3vajK5m*@W2cNeREiP+5QXLUa6r%cyPW8c|oVy~(S}ikS_N>=VmabFb}v@Gsp;st3w6gx z>RZHB6rZ*17j4cEc5`Ym)I_ym!^|PjwWjs6Fh#>6SA2h=_I-veTdJC+%UD$vvjpH< zE2+VK-4w-rG8I|reWSrWlR%g5Nef(m80X)A-ScL_EohyyFdk+AzWz1f63?W>czAhd zOcTWz@5x2sUc1)N=58^Id)`YRu^_G3dY3Q8NJ0Mn@4Y|If@!iH(yb=YCxhrN3$uR6 z_lUNWIVfB4xEIdmNtT76c5RQ8vuiIEV{{0Qb4XK;VMb!ahGfQp1&Ya96R1{y1n;-M zHOT({h4R#bDf=UG2&^_ z!1b>^hP6pwp@QjCrvmBKt5sEh@~beuiKHXqGkNQXY|Fzr-DR>>JAsFmLp(m^S+jBh z7`Tgv*+s6pKn!Z3{8n31#8Ppjj+Rz1m=~VYbX&QaRh@7vAif@!lBsnUw0t|?m#r{} zX7V&yTXNZ8?XAR>&)Gk)R*V)YJ3e;RSJWRyJzsJ!nPh$;y%m#Zeskx4$Yl~5a!*Gs zR^L=J&7o2h5Oe5Ru=-Pa|1c+#TCv)^-_7SFl1 z3NP0)c?Zu!yD3xyngpK}l8GwIQMt&k1TJ`>jb*sw=j>}x8_=4Ar%A@T$QC~O-2Ny) zLuO-NVe2bkx06L~!dLBof{$NNH3uJIqSmG`llyGP;->$W2~@Tui}kgNS)pEylhGv} z25%$HT<9y{2{5#Q8_0}O*BX^e`&0)~myjd9uZNd9H(B6yIn-0XdCp^xJ?>$W;lD3r zLcfoKCHEuB^AWZq`l~dzRd3Yly@>5KsVs$W$`~9@^Kx%u-VCsRN4}ZU@5{F8*7a0t zdIrJ03IQE(J3#7J6X84g81Rh5bJ2R6e!JROWPN7D=*Gi-e+ci?mWRiX7`s75Cu?_U6fK9m=9p z8tlVx-*8yHw|#AY>6BdM^*pBW9^IR9PaA*4Bl^P4xvCf$nZAvRi?6?Fm*kP{+m}np z*+QCSoQ+U^+>Twn%<)YWYakv}_@lEo$ESyO3sQ0vhT(b#`jhD(j`}bB#lw2H^RnaE z-VNwWOb&Ys>qI=9ck~%~CW3Ty)e4rfck@abWiwY~4a$grEl-x2JZ<)qsS;N6%jJ7r z$1)eJuj|pMYZ+)L=8{QRhytH^hr!%SCSDSaX$#}M*ujeFdxxBx1#@3Bh6vG&DLb>* zF{KRWYfK%OyRh}rj(dMk#pLg6bk!@| zJ(I|{Hr_ygvBMl%Wwryzml(Qi#o6BO!S3ns&HJOh^Znza_B|aNa5HO9HzG^2wW%Y@ zyWzx_)>P<(FTJ6rJ1e{54_#DOV;a~*V;Kp&y`xe2mVlD4W99`#RqQd5(ZZ}9YqP$W z#KIHocJIwWVWW97jPb9R;05YuQs5O(n9-pKdAX2(V?>x|rq}OxXiG8bg=`T`fYsN4 zJMBsNu9#o}| zwu@swI{JtDL%G_i%lfVrPUZP#p)M4>j4rRW5zANH9DUBEyC!m+Ci6BD@y?&)6bVaq zOyzXH zVfW{jHC&*ROFBCBE60?0WwYjl60`g@97xts72!ospAXvUJ53Vsw@MBr`x2^FnFdUT z8ZFo2F8DbMvX4WFU(LkwCkV|?Klchd2SB2KoP9Lz!*ev%TTz;zG^supV(6|qr>O1m6zkKfw=SX^I%7D}VLku8 z+(F}gnM%m(UOg_+>SmRlsH{OqpTW2yj%iJ&o7G5G5{hL^KEDEsoOG|BJ*I^1wKJ$i z)`k;|kNKHqf=a!O0}U0}6+}kXz$i6;uFmI<&e~Yb=d+PFMl)9)AAqIX;o)4F3v+RG zaJXjOBD8VM&?o?E=imo2CK8kUG5idtS9!M_oncJq8ipd(b<+)zrZ`H0rE8c;dA`IY zi><)P)jeL8V@dritTb<+WqUGxDQtj$zDC1 zc7iFka2J8QxvKPte($TV?(^vo0rNHV;{ zkY85%0)si5>7}k#PZfAiFV(jfo=WWZ4+d|}hx~-v4gTw#VMPe%Q}8okdJxVNv>9qa<-43mwDT z5yC>}shOUs=@rNxcIxua!i$aOX=K@7v!ZH(tBoL6m(e7jlQ9rB*z0z-v1fSlZ(9 z&|)0EtE(k=#Gzno7GET}Zr8+g;SFd;;kf!NaZ5C+MCl^J2*z%I09q91KJ)e`-d(cr zZUX4OJOKj9yD`Rr$RKpn-_u<~m;V`RcvBp_cV@@os>%#AtQgvtfOvzzF4hnd8@!P* zrB-*`yx~p7GEp6LHN(=)1M8KYI)+$4zFC!nQynz^D#)&^6P%u>UvYq4vi@q`rj~Cw z(EW4#Qf(V$>p4Y#V{y$T7p35W@~(qNU?vHMPQ|ik@JwZlv2| z40aE#FU}=#nni~#x_9o;uoO9L97{)0#^^-73u_+A(P^*n3Z}r+-2jfN2ke-Lu4z4w zN3lU_Pu}V?NF&bz8sx>}aIV2#GL7X6 z63iwOdC#+*z?I>NMY_iB#F<4jF&+1-7!v$mryLSAv+^L2;vY^>)bU~|{6FK{xiDIA z11neD*&@orc_jEouZq>hE-GVoSXBcjBP@JVb=>2CbW+8{42tiCdN-A&Rv=EoaU?Q~ zwiN<@!{P)fDyB`}@Vo6P9eIoNwk?dRm*q$k&Z!yEjUhtNyH<|>XWkiF=Yj~U5t17r zH&N*KsffT|!ugy@#Ni($@f4^ckI?VXz4r;9Hw`tlklBCl}@Yc1O_jWw3FCo3D&po^I##twuA1(NKq?<+~) zRFnQtgR9d+TI%ZBg9G!GUX0X2e_xoX{r(TT2k!@GMG!*sMcn+Qzl_YvgV?p(Q{?D5fgcC8_$jrm#7!<@CjUeUi21 zp-9st9fImTj!=E;d;63=z~m~CM&^p^lbfjQV>qYy=_W;IkXXHnO6#@E>4X-4iuqUN z&p9U7u&2oD@*>t$-0FMUO-D&{3W5+f9ydumNMZA_)PkP>XmJ`*CsR6}ulWRa^<>J- z^)>J(|^@KMU9AcQo* zn>#L434?S>w`duyV`-N4Y0SD%XDtlyh2LMA*Ti-Q3|e}w5`0C7E+D#nZ;CY!RhGT0 zfF2}BGjs7flLR?jG8Cy=(=%%Am2q}AfY4XW$u1)RWj)7e6ySRWVaDfwSKriw%{Xoq zx~!ZYzdw3Ce7Ae>X88VuhYr%=7&k;-!6H>tkI{9v9id>E${%Sp_Kbn%SrBEl+)-jD z0f&VT2ngRZxA5tm#Z|J%(5!5i>TMENIp!xjKvkJ*<`z6wGykf?u(~?eCXs&e(xZb3|mHF&j7X*yI6rM(J99|c-T zFXb2MdnYErBFbg13cAL2YrH27OPRB%v$?%SwP9OzCNu(eq&JGB2MjsSUVFZQc&D3^Mqj#}W>ti^Sr(A`a>~ zNEqMM9@jLGySXGn{ksJ0A8UI0X&T(fq6*1NW{=nRWRG*vr?X(rqPRM0wa7;5GwP3@fAFcdqMpznE)b(aewKu2L-Ispg^Wc<-;kpdjxAn+VDglDPu!b ziT_XmEQazt4}}N413-e)aI`JwcNuMiVweHGASTt64wU&(Bs?sfCmD^-Ao5a>^KuK7tix^_Coyv27HWQC}kKv`~v)2n!L*7GM(1RFy4AFq7S$IqG zOK&_>apD^fHB=HMTNcqUI(ZP6`&moB{Y=qm) zo5%;LR?@Q{ij>HN%iNQEz#GvP#iyd#u5KbGG{SLMQh7au0x~4~*Aw0wF6j z9@fDK9xyvl>?``-_tfn@thrZI*4Yk$-*eHfrPe{pTbWmFi^}o4K2M26;HK?BI2~On zc|BCM`#;j{TDJg^?_=Z+%Ox|G5QJ_Uz?Bb!>9lSTRGi9bPlo@|ZOmhgx5rl=i!*D! zJi4oY+-aPV=uChm$AhtT!}>l;*A5qP_|HYn6jAi>dxEO%XU^`tx83^x4J_m6;MDhi zq;HPUJQAXV$`>(R;S=K_8axEfV@L_T8$|a99Z$gNJiqwLb-X`%h31yQ>*2}iU~ljm zI!C?3^lPubQP4p7fm^)^z5u#s!EG(shk+v|CM5p)M2B%b(V@fB6B2)=H5+|@ zHRO|AY;0o#w`1q1vYe*J!Xlt9xu60))~T8D^jD9O(Dr#nhuwFB!(D6s;n%baTFOM= z9K#h?rx`9=F5qaYZOUA!3GW66C#4v?gcNP4|Hvprk8L*9aWC@x&X_n^ZtO;p$>J}7 zr2G(xERI$oc~s-NhVXeCJHMK%1EcDHX#w3bGag;Jwtutb*alK(2UxRFGPizmK?_8_ z(jrG}m7gc?PAcrQ$?279`J&hy;L|o0p?X<)*2a1ghj&^|5iFddaIL`9&L_Mx7)0h^I_*ac%+cPwnh%17arCy^1*9u$0_XU*j4>jw|Ea#?UvZ7RErs^XkElqd|!4d z(jnKpa+K7v76<4hYAu6&1kcKkeqTeXKd^qOR#>f;>()LKTj+!~1MIec__8KlNzW^B zW3A0JYwo_OW10|D`FnqwWXnYvc*rf9qIcwd8YlzFl$W?JO+e59#^!H5Z$- z#>T#aLL!KpT3Z46oXw@le~s;ZgZP?STLM^mQ2#j>vw4JfyU+iMPZ~`;efhqW%|Sq{ z+xmyW92p?}jSxXk!tLyT+}GylxHYCm1E>rGf>mJ6v&$@)yE{g<#)xn8$j-9bqO>LT zzH<}LxK_tI&lX1Aw@l(gy4dbMd>)Bt!RzwhpQ}DoznuMqWz3FRckj?!PO^K53sxUd ziXz+WD9WhmEXu3zFxrjT&GJfpR$)|aN7;B*=qVhD7w-WL2HCNHyKNMKiYq;xfEZ^t zVW}>=iQ)x0N0Awu>XGBeCf*%)=n+g_U+b|7ck3J5bp(H!+GXeKc6HSXG$~N{$mZep z*inV~&Rd-_v@J!}q`{}4Dg)3Fm9oko+Wo1v_=J7y^N4}Tyfv)xcJmxpB%RIw91TV8 zuCbxmmrV_|^FL>QL&+$yzJ{Xhy{Vyg{^xAyRX$s%I{xnb@Sv%ocK&B?sNgt1Yi{s> zv9`6l0`@tZf4kOh{?OdZAAYS)zU`!sKP=V7E~v-szHA*&Kc8ys6^y88=l1@}&T%S) z8ex}OVezO@vr1vLZk=kpqm^Y{zMZqR%Dn^oub_NV45IaaNjZiiYLag||8tIN{f@z! zbu3gy+w?3OX6f;~$6@jU!x@4fme$cMQ$deRNbW56pq*#J< zY?0;ORd6kT_^EG{o(({`fmeYxx2$U(HRK|PYUmBr!BIgjL9d5im9&94T?C^$5a0hP zu}j?;Q!}1@aHT{F(Z0s9A?LXwp@fs$^j!f20OTS6b^OVW)9CV%S3Lo zOXUK~@PZNW6bE%Z%uBB(%j;Wr@oJiGUW;r!qqBH_VN)VVQMcUE?aC`M_)r7W&Cd34@8Ov2oq`9An_=qG&ik^ zReP7P%aa%3VR_n*lkEwVyW9TfB8b9CD8}20jQ^E->UhPC-ZMSZdE zlWy|eQ*YzHvkh+)#Bq{iWM!;rOc#w2`@cSadE2;t3#?BCF~<<|GE@W>3e;U;Ec(pb zv}%FhulWKl$26Bg(OGW9v*|OodE#M&Pv4~Gw6&$8UZ{WXV^B7e=vs{RT{5SNctvT3L?z#w=7wG*|36}|BA)iO63~xGea*he7GT5 z$nk;AWEWHpoPn;YJoewm* zEa$6U?iU?y1KAAjKeWwl&66*?G)OX@)R{tDKDjI8cYBA9H6K1$(8Ow1Q8qO{YThvH zwq@K7W8b5y_+XR$VGUG&a1!k{P(G>xJfJjDmk%r%=`xtic>uAs?N+vTE`yAJV&#_x zg=-M3RgD;PJepn)CqO?KHl&jNf`U`vAe&(_gbn-0NqhE zO_RlZczLI&dW*kb-8B+s!*oYmDs)gdMc!$V)JS3#&b}KWw~VaE&%^6~M8%`Rt>={6 zhng{Efet)Rp$#LE(Q7zVCJOM40~t08Qf9EXozT?|dY}hqxokCG@9NzJqDBQMD-5xA z@Du*^~nX?4pC zfyLdO`V19vewV`rwy!*N&5K72#1XnG$@(rv?2KF@Og(NUKRAlAC zqM6h0Llp|6iNJCD$Fy!EC~Y(gVy%dCs4CKye2#aK$S{QI@Fksp5|37k!#VhHe!9DN zeq6&g-U5?itqC<*f;m~)E7?9MF&ZoP?wR8_+{Wn3n%p-=vfx?_p><-2vUHP%`0&+g zBfve&8t5^M@U;LOrC2#CwckHhz+Jq@;A-(hNowFD-@5CDi3)c+x%{d{r|f$aF%66p zYST6hC+e8D6D~S`D{60r-c;^S22`k1?yi-{2Cj2F#BLa^aJQ4aOOTy1^a~({Oc5M` zmtxFfSk;U|49ciGdAguy)D5SZ^<4eO-~#7popIm%XF7ECtEmoq$A>4or~7Ai+?8+) zh{912IijybVv_efM^u(@dWC_Z_ElNOtx1hmVv&V9Xn{a~o75wyA7DAhW{}WzPW336 zfeIq%O^H4F9%lF$)kuHG*seMqHIpKXpXgS7^R|W0M6~w1!7`9UlIE}r;wR&c z0GLV2FKp-}SWC|KaK(WHXyjR*!t6SAy-F9&uYyZKGns<&8DG6n+4s$itpP15_?CGZ zCZMvy&Z(1VPMQzJd7yf!Tvv?TAYepwqLVQm;{Ne}>Hhit;7qz6x3Q7^h;2qzuOneK znt_GI+^*d>2*lH}|Cjg-6Wy2v@5^8~jO)uV7GuqHeL%Bfcl0boO#_4>J09ygh=-c5 z$PaiegI~F?740J2ZDJ`+Ev7)4KeVr(DrG(w+{NBB<9PsK)NAZ)Z7ID|jH<5Tid=O( z!L#dsibLKD?K2s zkQfV@k#C}r$*77OU3C%IgqZ_N$xtJz82oG~Lte28lzub-;|_sf>6rk01i*aQ#{y00 z;Vy-ke>GsH&Q;LrHI6!9bcS-mqBkzPbwdt+xlGj}F^+m=@6eR2UxX>T{QjPAKv!~H zJ%|7Bth#v7!W2VY*6l4q`?HqA=gs%}Z3H=nHoa$tgjO+svXef!$d)q)zq4XN>tCNd zfz(xnTi1;~KNQPKas9D1nWIs{OONlhZ=a_k7C1xV>jC3rrp6f0Bxp{LL_E!}V5<0k zgM66klmN*d{+0`49Js0e%5mV10*vf+^6tb1-Vk=MK(xK1#ygYH#W7X6^*B`&O$V{1 z;OqDr+5XY_@Noagc>0fD@zHs^AJ)wttfiJWG^r7RJtC!(SgB5txGz7!%-yr@)^paG zLqz1e9y(VENYAKf-O=voQaHKOz{tjb(2}z-g85a9l6ai?=>EJfGx4n<{>EKsuF5KB zd*{yk4J;ndac(tIXPoN3QL`UYguPvPtWwN~)-1AdDk9>pXA$M2i=a14;`}Q6{hbKX zYzxonHtCoS8gVUBnotwZY}hmJEe2lPs7zwd`0}`jIij6vfjf|$;c#o;=?N}>vm{#N z;*4tp;V@Y=1}*EGZ{g!l&*@{!`<<14Ri72=R3kC7uZ)=B)O=0lOK%%b61P0xuaNka z_cb0Umg<|R^uh!nv*P{FHD7F7zU{TmcB8;l?W+9zaMRciB-Os0^H2HUwOtWGC z;o@047dA|X51duoFs)gPQ3{5C@)h_$5zjO`$yZqH*hF37PMz=$>KLE{RaRpcp1!aC@o~bW8Fp5o`KYZe1HRIujA2 zSoaW(lF>&!;poU0Doh$1o*yCvEw+|V$9vQ1eVt2NwxLLo8Z-YRxlADSp9KICl`1JYv{nHmwaMKve zOWd!GxAXZW;guCiKK&=3Ss@M|bbnTtT-tu)_WS_dd{ol%7dzgmW#T+N@RVyV6aK)B zDxSH%X1Gll=5Tr(S#6V?m&{unl5n?M%WQ3?_rEcl)3ZHcf6ui#vVFn3{L>C|fcvz) ze_~p*W@pt7jc@;AXS~p^SXjNAv@(?z(xwKJQ!dZ6PTM1fqz2+du4MF5^_4X00wDWS*(7N3z^}{12zKPHh`wMb7Tz& zVhhQ#04qxd>){T4d2OGFg6_IhZhO1ep#7aBF-u6EqCp5CH10oM zVYgM`4h@(gYFmv}Tf^he0UH}#8b=`QS z8K;ZwM4-c`9xjUKNPhwg8MhHe%&_;hPKe~po>*cgY2r9c?FU{~I4|u4jM3V`A&#`; zx>`9TpC`-nh76^^N_6cRa$Rgj@ejE!HuS>r`ZliY<4^MF`MwosCS9{{Bl5z{ z8*@XtL{iy4^jxRh;0>zazP2c*258*CC5FqGi==tk z)&hs~y7g2)tbf{CQrW*A9JgyA?j6j&{ zEtgAQLt@m+&P(?>(FOe)yas;&eU3j1!axkg_k4;B4!1e87JUSNj@vd6efL*P7cNXK zWCwZmuC=`&NrNsn#pcon+c3BiWwW70fu!sR8~=NU5_Pq;Y4swJL(ZHzXNJ`6UAjw0 zqlkrqDn_(XJTx1Vr%W$idpDy|LibFkG-U8r$m8nGr~B2tq!CkS%XDk@w=De13{SSJ zKd9bW`+)gRmVcptB4c`R#RE0`z%IIZ^DShl;WAmhPYzV@=vTGP_AD{Ap|{~t9?xg` zp+AN@wx_Mhw_GrtYs2=dzo;_YI(D1hv4kmVWJN%nC80F~Rf^`DSn%}blHn`M^+m&> zMMiDn`&7t?^=5Udcw%CV9P@+e=05jkMqO)fB2 z?IC)!dtO~%7jL+RUk+520B>zkBwN26O)-zaEqZl1P_Yiik&ng>htjc&U#x7%Xge(mmvl4xA)LBNZVMmJ4S&9+Q=eYOsB9qb%PG2aq#2|gG4fe@76A>(}xGiNpzl^qaCEI0xqfz03Uk0rKbxC7EY=ZGV!L2uF7IweNBU{!aFq1#3S3w10%E9Y*4hO=g+CEs7BtF&2gb!<$j3YS@Zfbi3r%X z)O>FFDRKE=fwZ=Iz1nx3(hW6~bs1&uJ}@o%n=VyiQ}xf)+;m-4!< z)t$pZ^60|3a2e?L?~N+%e1HJ{?-BCCpE_0o zjq*4o_B!V+ztl*pPorg)S+z&1RgQ3P++nl+^>g!0u_9!-4AeVb|7Ndpc7F57iZ!v$ zsnwLh=B%9swd;<5a%YL*$HTqsOKp__kE(FiynvKK1dlHG9M4wSYXFH}Iua zUhN^)Y@c9&U4GySfl~NK0;-(n)-yilB6{bXfkE!}wLwO}XY? zE#RQJ0_(u&y=IV{;>J3?vDAi94gytJfVL^B%{ohK9d<^4=VvP0ZKB~r&cjA{7G1q= ze5p7ifkw1B(PIMs~M>#2Q%ll2M)Txpuz zc3qj=#_-8)r&wmEC|$y^7r9!2jr88$;6rQD@f-Cxa>dUh2XB*ndAc}WI5!pvL-d~i z!{mJhbGU=~bPkK=ckmbQHcb8=z2Ya(OE-d9f7`emvt#xLx1b0Yv>ty=kJB&^z2{d9 zh(oeUS#hPi1tdU1THvs7qNsAy2{AZvWIJ7|)&6(JcH)iOZqoxfL{a9=c)s3CuHLj& zn5fy!lpn%b-K5I zv!3ogKlXBYBY*LN337kdhLP{ravFQXwV6hJX6-cSYiqb{n3zW18r2o1Q}{IW3p0F+ z%Xdn#-6ZNm-J0Eb(9irYZYEJ*I&q?m9`wDTay`ny%C0GF2gdmKw>L{YRJ%ffH8y5` z5^ncn^;^s4449zlodK&^dj?AO^E(4-SGoB`b(fqRKq1@6M(lrp7F}zwVDgeGxle$u zwp$BcJVsot3fcIsqz>Rfif@@gaGS6Ej5NG(Y{?xegZqcXJzZX0c)tsH+cL#!cjQ%V zXS?t|y*SQ5wb@RL^s`t2i~nZGz1cDk(Plbf$y;_$=vRw&+=s zW@FsI$S9h<-oU6Y2iDgRc#=lV+&^owrM(2&JO@qW>F3oZ{7Jth`hi62O6mc}M zpdCj?b`WOh(gZC2Kui@rDCPt%$YFjkg`sC&HqyN+p7pgls?Qcokl^UP-U-(YmaG#d zEYG9$VeTHE6pS%L{-cKkcEk+-9UHJ* zhbS*8q0k`c(}v2XLn(Arp$!adEw{ulhgcwKhL^R<^>JN=jKo0f}0&w^b?tb zRL-E?uO%(qZ!C0h+6jQ3DMwPys_at9q9Ow`~$^RO-~y!5WVlO zm`b-RD;F>ae{FBuHW2>qU%?p;BnNi7esyBE*pi?dlAvhPAs7T0j7-Pc^ahd2ON0FP z9wkvCDN&O1vUEWG!M4P^hsV2zcSjz4h&Sfr(`mkirN^DpeDU8<*q;T2{Elk=Y@2yPY4z8haUC(*U%V&6H$ zj9h@jdP;UmeY!Y3Ir2$BLe@{XTk205h22so9_=yXDUQ2^&RLSWEKPbWx1Z~{)ZbCq zL-K3tf33QuF1PUUWt)r7F!OGR^IH`81h+W3kUI*~pi>B5;}*LLsXszSu1V4<2eI(N z>q_hkS^LE0oAfvh-F&lV1MA`uxe=s*ef6CLet3T3@MN>}LdtOHl4Z2kq-hLuvf5jg zEE5tF4B!LE6xc@z!K*0r?-8UjN)c>sZ9^h2e~9xyQKStG9tH?LaeC!@ZZ*qt=|*4} zC!n1PWI~B|1G^8Y2?LF8)aN-0$*m@2k0&)4C1arxQyy~=MMPkX(Zk~)`}b~lH%Hw? zA7h;0pjaIm(d@SveAl?db%txJ8siyvFoZf&c_?ijC1t=1)9MVchfbLod3bZgA+IF@ ze{7L;aB80DQd_|aa+`+f1bSF zifvk6ak%Zv?(AZs8aHBw;JL81jeM_6xIFZ^6>m(%SLE7Sv?AM*?J4BQCVK`u-i!-x z9PxV8R6OwqjRe?>hAj`+QeY2jwNH$2=Nttw14kN)o``T3R0x_OP|fA92_p-ASA(K9 zfg&8T-64PDd*ArnUAqk?Kll~se~0g2pZVm5_#InJZjaQKZoB2euKz(L;^d!VTkz2L0H6v8Qy8;FkzmZKiP9}EnwxvJZ1t*UH2b-eD`yAFXf9sRs-M!j7GUxscG(aj~2-zM-)S=$~P z>M5Mt7hg5EG^t(-2yw9iTr5=@O~sf9uNRN&J9aSzE_uFMD&;Y20a3GW498}`9g*U- z!v#Ty`hOp42lx|BxQwFbqrS5yb|H=ei^&$j8tO0RsbQ^yag<6Pi!tw=WMV^T^wL)t zDuSfpo)4cq?0!xkKAU6SdP*NXkr!cMGdcBZ^GYPh`!oUao*ljwpQA&hH&>8}GV2$E zoOY`Y(m3}Geo_igEId9PTD|!yqgC~=Naep}s~~b?ZxT3#o_{CzA6rOk5@pZhALZA} zcyyM9m_%BMcnSy>Vmb1^#6lB@FTuT`K%+wlS&#UM=CBn8`h+UQ^=ndzKyMDzmDjJN z(UN1n3I`p)EJB)e0m8*6(&%a>SO{kpof4d3=ywy%u7hfl@t0(o=VWeDq;lDxjDujU(Xvbd4`QU0Ekk&q`*BUmmXAgPr83zB!s$uioH7V&eM zO3Tj_=%h3lx($Cw21LGzO$%)MtFX@l>b{QOB8X&_C-E#THe0o2G8P+>bvqj9Od3#= z4cZ530h4fcVQKU>Ne0sfc7Np``G@}YmWyQFE+=GF?j_yn965_`J$~?Mme?;YPsX&)qUmpE(D0uKFanU~&rE^$h7OezpJ~b%x zb%^xcy4f_hdZOg5r1v&QOr}z${W&FXd{*Lu27+TN?%^O zI-=PjeKoX$-yU^+-%%%ihn-lQ&b4S?D}4KE^V2LoRnue0SBsU8>vztJ(Bc{n+aK+P zvB{e#IGYvbBAPMQViW9c*`#UMi-bWku2;ZWK3k%u8MR)e>|9_b&0Ya>!3?+N`*B2EQg(dh(S6FxP*iVW16saBBNT5gJO^3cX9Sv|wCS+}Y(@V!oW zCYi-atJl*MY+dgGAw?vx4YPVmX-0l+AbRZdJb!A2VZ~Hfsmtjkr%#wsWL@v*5?k@j|Wra zBcBv3qu%v+63!XneVJAe9_Y`M0F1_q;uWW(&xx7i(&qxrLA==F5P*%MtX1znH-!#R zLLiRy=Upx2Xb}b&Rx9ayT@v~?7J6K9Om@2DA2sW&e-X#5d3nYW)wfmPjwo7g#yoE% zAe?W0%a z4A4(Wa!NE#Xi7KiLuVZOYUdouoAk0ndl3T>ETAJOHNu|0*V!bax7~Yr8$ej$%-cm7 z>`&h=Y}O+GtC+h8?=Amfy4L(jl(Jyy^#|xONl}bT@#-7AQ8O_C2KN%OhhDSfa}Lc2 zs}$`*!k|eaC@EujYNwu-Fp|;BNk!kN39F<%SlQ2NXrO`bbQVcRD94WNurM4}J%}gH z4$3>>%La4r>xXk5 z(imL_0aXZYThSSPR>i_W)0`G5^@E1iP9zqjDq7*75ts{e>?^x=%FI@Rs(^K44S&j? zl4y?c3JtsdDm_ z8zU65PL2JmshYScCiLG#-kcl9Ly13=3dfv=K5Bn2Ugr9`D34d^rWvl2VJv#uZPl(M z#M(+GC6u0Mf$1x%D2qN{FQbn=fNaaG=3pjWf}u#q>X(`1UnXqdcgPpV8d^K;s$1R8 zu=JCD(-1Mxekf;nDxm-vC8A>#Tr6a<6Tp`+Wc?IxSH~JG2F7)AS}kS#9;~ey^9>J+ z?Bx%IMn!7hT0wssDfhL`{w2$r%Uj7oBbioxm%AU{Wa^7L;$|<4%7^LzgYoQZQ_5HL zHD!!!*=o(vyqWSP^lP-Jya1~ytg}VS+rZ(}rB9%hqVVZODw!A?|#J zp?z8+mq5VQ3EB48+ZyB3G+MguUfM{FU5(tkMlb(CX^p0&Dil+y4d{A~bbm9dga@?6 zyjt|q@zFQqd-3+Wei*f6$d&G6v!@^SS*3AwVd~aP8Nv)i6?d(off5&H+~<%Np-0P~ zvTpS~7w+@T>U$!A4Jf~9h!u!Y&hXf~)Og44_eQ<%df*UJiF}#dJUMjhG4IHGrKh~z zV{P7|D?*#6152lA+{>%Xtk*))HuL)vCi5Jv9TZcf&OOjyr%pqHkN4b8fN3P_tLP)P zesjfJzvMldTjJQ|iDH*kKyCbd(Z2O7i;pT{5WD+qZO0zaUTib}n0yz;=hDC zR{9!__h<~bI&F!#p?ZL?R0Bn{oG2Z~YBj!E(|(aTYE-UR=Jmm1%OY{B(mIe4qHNX_ zUnxop*4o~^gA+uR)*aZnIcqsHJg)Z~IQhE<&##F?%u`T=YE}G$j=r5b(Qw#dn+bJG zeKnC24ttZS`@On58ocV_F0WkYC2us4YKRM6FYF0?OcoGHI}Tb^?ZK2T^>&zJ{psJO z_U}tj@j42XsBtBjPf|`u=Y336N{Xu3r`0jZl{P*$0!S)Ntm;jfVqx>njCtqZ&l9<( z6>B}^6NmDqv%gSUxzEY$`8!~Wq)f-hf5^-cP*0;`E!39UiQ}GEZ>sUZ>!yt(7LrN; zE{&setd&SRPAU|uqc_xiH~f5&MHN+8{7p-DiwyK}C0K;EEhlqkkcqvC!4DCv?DuXh zdV_VvSxh(?u*2E|gBaeIm%nTiw~?x}+qA(u_Cns@(6~o66 z!7Zt8KPZ9`U+Qeo$kCf~Ejmlpwjn_RQf^9YJLc#N5h0PptdjRv#oAhGFskQSM`sD$ z+$>G?lT{^buG&Xjb~ssi7?a%@J~u>6Bn=B1sNGglP=$%&^cIbyWO7|$IR1H@N56~#R5g8o zNrow-mi@Z)AhZLXqQldAm+wF@T&%AQ;lKJa)kVj zy|M{&BB+`hIeW5dS^}#2bTRC86o2MoY^T@~mWU{q`63PX?xxjRe5(3FRPj4&hc#Qc zk{R3PHJ)u=zSR`v*{tcc|DV();8XvyQ}{F&m5lCDjBM=eh%(gIAveqEvl~V8-{U+h z0lz)rBK@^A4W~!6op9$6=Qc+vUKQL>ey<++B z&X$}|t3HCQ)Xa~+5Nz@)Q>bIqE;MijY4Z-=HU9Gube?ct_#GJ_F?s^lo)h<4j93BC zJx<`w&?V4m4p?NBEE2oEZ&n=-ZIF<0G+sO|a)KJ2B(Fq~$|D{hGF6{pS_Ar)16(*+ zJ(`M5%=hD!Ko7w}L-ieCYr&&$@Ko##(o$o4A&V?8Kv(!S@-Wyx{v%`1W3D)4Y(MeOD zMdrOH=4<*}w=XV=T6Zp!uY9jp+4C6>MO8-~B%Kl8pxO%MatUp7m$EmW++xj%|6Xry4dbuK%@GqGU&Dl zFs_%IF2%?k|7m(&P}mIVNhyaQ=Tu~R2uADUz4c-vX3LG^yO&y=jkmfhTGg!x@ubho zU2}Qj+&*@{6BC{otBjPCL;nc*j#VeUdE)~=Cw?T(khyA1Odiqni;K&xeMcK|wuSh& zWL7!#U-21!3q{P3Rs6vX01AA0JL0yK_%hL$bq~*jmxPg~5|+~VQguavYF6h&iTrRt zf3uGWS11hCz)?VmqEA)Tbul^l;n5F_t>>DFab}dbJL$0K_4p8G&AC5)_*iiCk;hkW zo|ug}^A4$IaknhdKbh%S1N+k6I!G*bVZMo_ejyC#0=*5W+(H8OKpN)fO$@#l(Prvs z)X&m&ncjI?W{(_kw$v|_fZT>!n&JR$0T*9#+5WGIh9o@(p%-UJG;%Qt3dON0dVkU~ z8c0@4ot;L`CuZS`4+q$Oxl+h@W;S_re(bO2+EXpM39(_&_FXY(vxmn*v{3Rk&0oPH zF|P^op*~Bon|~`^0tPsuEzpksRLmQU>Fe1DM0oYOD28WGnp4^|&VRe=~zG%?vvEt7FS8gZvvZnT#X_hJlw#Vg>=87C*$ef=Ri zfhlW5Hd87k^IRx(IYaTi3DQ};r&MR@rKP9)jg|!2sU!Ynf;CUbN$Qqq94-W<+rX$k z+C?5h&!6D8EE+)eBFB?T9}kEBwcZ4g^^4U^Hx;dpnlj>eBb2*%$+J_7u}U{{ht#?- zm6Hshg=C4!<8IRV4>k%`ge?sHt6z4L7q4Pfu;SJPbD4m9vv%~m+?tPvc>W9W>WmXb zVGJhl_c}B+t($#8NYDomY2SVGQf0JWONXWGHW3#&ta5*cn@B%jC2U^$4gRtcj%6>( zvPQ<(^Bw7Yxyi$kIk>P4P?1hWNTt`@6=7w~M+Kc^9{gyIwp=|aiI7cZ3USNs{`|=T z?~*Y6-oFnpibido@6w`sJ2tgjX|DC=Zy!CUr%IAdKydDA1l(ddeCma%zDC8xa1m=iOw2~YQ@7-9UPeNf#PD@8C`g(izMiU&d}l@7M<@#L|~fy&i<9y zAvgvwWT)c%TA#sJ0+GX}+f121a&jmi`R>8Pg`8FPL=kE*n-OB=z=l??*q9m&Euou~ zj4Krn>})bLzH+|Rn5PM@QJUATEc;XDZOKZpvE%3xJW?JOMRmPUAyO5UjJ3`8X9sBb zozV)LQv!o`^xp*@E-H4TGmeAd`>o?w)p&vTUTJ6nI{89^x1&*5snyKANWY#sHM>KM zm}<}oZICx|n&!q>eO3!e<;`=BJFJmSzZn%=hf{9|LNwqmqgO_3I-we(_q$kcjkA$@ zv;Ep3iGO_Hli}s;;^Y&%zAuC_`Gv&auoM!0wsL7-#deKu%-=UYVK^fY<2Bhhx*Zrv zzi&Uj$SN|vkNTe`X@m&WB>g%o+W_@Qot#$S)f?xSk)=7j1$YxEIoKp%qgZ@1Jl zdN?HID>uN@X7ZZ)@~_oY6$dy!ZvJ;Dv85bRKmXu2B7qdpX2Eth#e88!}i(?7;doeI&aO*2B5!C#Y*fgzzFGu-%ckG^evLD zw%s(6a&Q^r0#_(7Y!nboa*zPGNm*1uJUv6KgXI3P8NT>(`Ufz{=%YESQPMfT?p*WJ zs|p@@Z0w}1+q9zArR_7hQG}DaqY{#?cI$o77z|XB!MBy~Rh`qXXoV-xkxkH}{UmbC zc}O|MB16P!eC8w^w9_;nLi4y~w9lD;Wa6&3Txu`sROBj&)=uEKYQq6#a6PES(UMc- z15wK+nQl4_Ch5OsvA}5y>)YjRJWy8nO#Nf21EAq&0+kH7@=nb}C|*xV&50avpYeLRhHu?>ktYFeIr@FSgNh}IK?3qM!iwJ9p?W@g5uWS>%Xa?X zMcy`N4@2M=Tb*<~&v>Lt9s|-rIE=I?++t+VR%0xoVEq z5ysIbR@p0Rr@*66`NeepaSQv4+}x|q6?6X0H0fvP*v3Z$8}_oXD>E&NL$?d)WJfFP z6JXhP>kEqaxS9+_fh-NmlA7j0mC85G(2kPi;v!*6nXvXTv8HJ(m*;aUswf9=NOeN$ z$nn%a8C-0P(IJJrZfp_*t1L8I9 zTR)OGyPT9qbK{LnwLwJ;EzQUHpHn~|V`xCA#yv#GkX6!L#V6!E#E`HG5;sBMH0ti&tdIOSp7zp_vS(`l8Ww*Uy0@ICMxMJZ>R=A zl|q)1Nzz%mQtET=wYsf$1{c4!3Hn!{_~i1_&=j1{g*YQrhs; zlv7jvEFk>2dRb23WoTZn)<&jfl#Q}LXmmQ!OY%M1-tXlw{)6t96A09rhUO@bKlKGa z%SzZ|dCf4O6kwSlT7^r*n>_*InEuFa?nstt6B=!S&u$HI6GW|Bi?q(VCgS;=+sZ7Y zkvMxNzD>mRik~pGkgU=cvPQ%=^_vHpNOt?XHC70z5T)PNCHWad_feKwI#B4cS>Slp%u{YockS6^=iWz(>KKH zFkuh&E`pYcujzG=(<$>jxrwU0*;MRlX7G~pe4<%*`+CTeI#YGbu9`WAS@5uQ65$;U zGgD!`aNhe2U8yE*2Wl%ikJaqK++?BI{dF@JKG#T1iqr*@pB6G8h~rfTB~q&v#JS8r zue(V~k>A#Bv2s83M_&UEd)xNkJrYlu$Kku9HIP&Wd9QZAow1;l>zQF^{nh{{HR6w1 z-@Y+%x^{2(xNwW98D$GZjW$kj48#NO^r(tiykMjAe&=)meYC+vY<6<~oapbU^f6Oo3{AEb=`^vhE5cLia@bLy_>?kb#W zbry%rXN=UrIFk-Qfww=_4s<^CH6b4hUTmCa*BR z3ds;Q@bLB{(=g&7Mkbc4RedT)?9hI^SKa`Q(DMK>j6rGMThsml6*4RX>w% zE;eVZsJ{&kaNa8$50$rCI4Xdvwpk2$+m@KBAq*X#MdMo)fwJc&baCdk^HdU;jLmDA zys4X|`%+YqLs%p)7 zZkIt`kJarIHuRe^xXs2a%WEH}ya_HHY@R|hmsEwopF3NMj!U@;mB->7=-aydR(rr)gcd8U{C+cS#~aQpgg^S8wO_L4o1#{K)y zbHr42c)=&pq$hzTMVBOC{j0RV&+JOIWm}N$z32a{`%dm!W&L=53N2!(aHzSU9?5*f zTC~D2XEe8t_can15|`-dgB}h-&}25tr>Jqpso%iNHTVTt5?CV5cIQ%=H=N_`@yVZS z$Z(;eKhRfR3A}byXVn~TZ)APePOv1{+Lxll)>H)Dv*F04x(h33fm=)}0vWS@%@02C zB*w(w57eKPjfvwAVEy@3pp&a^@fGOw!??=txy7$FCy?EK&4Xk<(taF?Wd#3zqE0?O z;0G`|Gz7sIqLle1SquchO)eh}g-XZ`+VRRc6_B(0UXSh)ai~3>2alSd*@ZD$f!GsC zgcvyl7CGq>x=eb)&d8_>Se>h6vCDa|#Dx%zybRc97n1lErIL>&&Q$RTzYHfY=8*?3 z`k3=5aPn+&irLyd;ZsYrz3XedLR#!*mjK&WQGKqn?_y5y4+mEm>qst2*OslUZ!zSk zsUbQTwZSlhVSy<;H7((;3oug;pIFEQXih}=99z}%i2|KxwjE0o3)5f-lLr`nx7|8B zC=PXM3ulz^*__V|Z&aB|B@SkviWblrF&StK-0knVToT+lp^%x~=E5tq38fYObc$fQmS-BO z`7Cdq@y!`oW9V+jrGbPm4Xi4hzA+-UPiiq~I;-L^WtHzSodDQ%b`Y4mD`lr`p3@p? z(Hd9Q4OU2U4Jm}?h}GGLRFtB5j&Hy9uW84?ijb-OG<_)yjX~IkweeMM} z5MNje*ud#ohA0OK9}P{%?AvhG6XS7zrL-}zkZQB?G33tSart|`$C2Ziftu>GZ%fB7 zHRxmel4I>mAgMF68m=)l+o-pb#qGu1zX4MA;CXnHee0bH*7Th%uVoa{?v)eu-Xppy z0{cJ8zv-$F@9qI9fA_EQX*V8clI4wd2RS%rL&?K6`rg^@s~1;Cx2l9fM4Xl`iiMw-IP>Cy6_0;Z&uDSb*ggum#Xh2T|-!i88p*B0pLTMYalj=F-P z0sT>moiA_h{T`M$z>oP%sNkS>_d-wA{jit@SQwQhWBp>*+*=g`pts= zErSiMVxip?d{w*MnxkNj$vIjsbpj8&L7aV`47hb12WMF=ic@*@*tW9$GPXjpp4saZ{*|e#L4(aqB9;cmNyRVVfko)eWxbhYjppX%gzO_^qnY=n{ zk$_I$bk$WwwKb{H-5JICZI!Df5Iex0Dd(H=#X$~j9GxlZ`+NksshdD_7e4bSlbuuD zqMYkwYv;O7!CREVabr+*+}YXTIn4D}bZpD|e|qL`7vPfsiOMy<=`*|!aF?jJRb2dd zxn!U2b#HU(vc{10yC7wBZZFcMfjc~T@z<36xxn9q3^W|vajizoVhQO{aCuXv?pPe^ z_0_RvRkth(nlhP*l6(+6hk$Ju7zcm(@bGzr4Y^K?&UL-hTfKsT;X0TXh7<;!(vODT zqvZUC9~x+Ubh%`Jfs_{7rGvbZh~qo0vK2V9{RJ%v5`CYx{V0o{Y0woyRcBC4deEv1 z39Edr$7Pj`J1EK~`3OrI=+`I^1er(?jS{JWsE@1p4w)tpg|`Mz5a7{evc1`v8Y56Ufel0vY>(XN2>4rt?sMHAy2hSXJB&kFG;FN#_-$@J7|Hc9TE z#R8i|6T&Q%mBJP{(k5-SDqb*PMd~Zysai9$h>{}VJR&I5n0bk=MIg!i!b^D*317G5 zDAplcZUg1K2|wOzwtGyj)N|}Oq`8U|Q5 zf~cWO-#+3R57m5u^h)~Z9%gENBUfm1GFGvhTuU1>$uenqax^BjiC(T$`~25hvaS>R zXu@M7bJn$?u%*A_11+{CufI#?GHAK>3<~;#2%v2g}PfWXHYT_nm&h<%835eJlBO^+GHfdN9&Ih$RKK%52A+u zG4@#K`5g@ki<;<^1x4VhlEBc=yEAa(NZU>zkw?U3d+C-z#o=#6-?6D^xT zzTVsD{2?ET8N*ptFBz!|^om{X`Ns`^!?AY@;EFr{ z<~k-JU~uV;H(kZ-aisF*hU@_rB=ooQd8!!FADvWehPPy&~x8eDe7kKZwA~3ixM4od#Aqd83 zd_py_v%R1k91R0L#c=GXaxMRn?l8FZq7mBd@np|1H@-GdfGd1w(l%!-r^OD;B#cot z#19D>iPurE^O7@?_+u`4?MgKKHWw)p-}fQXI52oL0JRckPU5Sh(T6$zo2Sb+4@e?} zr#_4r%WGqlc?}ys9}QZ~Q;wh)`D-H%yfytzH)}SgZGA-rJ=I*`WV!gSE;D^hOpAO{c5Li%obBFJaYm1^`U z@CJ~y=AQK^NQ24pO-kHe73bzEjpxk-S$ND-&7(g#iTQDGH%p`L!^~LdNha1V*8Eh_ zHF)tUU4mcqj;$+tsSPY6+cdG)1~)>*xLB>GX~5w9!>B7OB8-j)Tx>~`eI%4CFhK@B z%7&dq!Q;OMe)Ozm$wRftfhRN`;QCwEnZL47*t}8SAUN?f#{Dhp)-JzyEzpWvK9fsi zDzm{Hy)z}rNzx)9!>-l~Q93b{8nLD(i%L|Teex0S_(np}(X_95_WWG1nK@GK7}_Zy z3~RrH=Yqj)3mOYJh{|iR_N)hW?v3RH{B{>x9&WNrq08x`{7j(i8#o_cmiRjtpq+IL znhQ`JX@|q8mjHb~dswg#BjDP?L3peKvhc(ISojgsRRw~#;vYJe$}99gXfjgRo^gVz`eI}h@NZeq zpBxC--~?Itf6Mw@s_gE^S2a%umrw-qlBd7vci#8(oAvQ}`t^_45+mN{$LMvscD5uP zNp`!|k#4Zf%&Bum19M1Lzj=R`^XMd882+TLdbMm?;N}nc$C9Us+f_V!yjT{PgnTB9 zTl`+k9^7WtCiw~w&*@}mbNRQYwq?1EeYTLc<5-Pai_b*D*Ft_<{GrVz9K38 za)xWs&b~r6P2eYBX6l6>zcrAamJOygtMMXC&D-Jm4x(4fwxG!#(3~fEMq2e;s#Qr$H%)kiw9}* zm}t7SoXtbXd371`nlG4_QTnk7q|GV6T4UGra8i=&G{W{c(AiXQ3KhNxGr|j}4sGc6cQ}%@GLMaF_?2(@?u-$~dtO zZKy8!=@c0;!rv$SAL}Slu|8(3in&#r8=t_Zb3JM-%iTh#jUes`#S_+6e)}P3>ARs} z?%^@1QxqPac03CgCv$E-Km8>@w^5fSUQcIxZpqUu<9cSe5eO5P;H%=+*CQ#>oITHk)RU&L8tN#)e$+Giimvazk%+K?No zEBycFarggM9+&ywJWj0pKY5(Wzj+*m;taqimk+(}&gr!G#~w7@CrKDT)CbLI{8^z? z>8#YNQC_eL$jp|d^cN#W-vfK(i^z6Mc2jHDI!7gKS{CkxQsc#f86l6c`E=T;t!HDz z7%o`Ca-F~G^0+0GH`$&pLrv)SnhW-`=N=!17;01K_fj?~6mGEm#yx2I-L+CLz!2d7 z+oMnWrO%TV5u;}{Z7|r`Rl92DdOc7X@>=zA%O@<`{GRbYHKN&AI3#Fbrj;%rhFo)FL zvtMbY*-&{|BXy!~ho}3461^M!sTIAJ*8aBXCWwh4*{6`?bS9_<7Q=V@z@Ez^!5uu> zCH4geG<`n_j8PGix=XOOAhWlj!N=P^)*G`ta)3IpcuLEvp@XkAcHmNxkk4u-;t6-;_z;6r(p~>8AP)? z28VZRA;nI37HYI?FxoGdk=)K}361hEI+JE@>dIPg<^janv-hbQs}9V3F|{Dn?M3!z zgRU4K{1WPYcANRx^szQinQgOt9Vg+u{uV(i_t!uCOeBVh@f7^XGU>_%SHY8Sq_F7x zougRv5DbcZ$CDn=MFHL%p8V&0Fj1&K`D#3CaDRhMx_pybRDL(vsl9j_kxxZFTlA326bFHgTW$H;k7@`}1Zc z`cD|INOyKcXcPHAkz8H=`bNJR;`aY1lH-h2AN*gD9PZv<@q;3{>A#U2u#T$fVY4w( z(C*bX0(`UF5(a%9+VKp3~c&7FL%T{vBTyY2ZUL^5R~15$g36@#``2c7@j7iZx06+50PIuN)FNAZea-J7{c%p7 zri*_%{~kV*a7UFgW4`T-f+-K;ZF9d4E-({KED@4JKlF;tN%+u8Qdpvie1!lZu~?Rdr|a z2h-UPjmIsdd3E@RL5?~iV|e?V-W>)0@~Ufl{JFU<)0UW~5wt&qgkZA4Z**o)LN)FV zEU~2n&g$ueM4F_~zGtJbN-*_>h`7y(5`>U@3$ci=Bb+Mm0!sWkzG#A5Lq&@+-0U%$ z!gcemTq~6Y^(@=BiwIjv)&YBR7C0wxI3D6tGhJ6FM0xt~72?~M&OOqC;7~vIZaPK* z#OT7CAkpy5Kx=F&Tr3{ROr1?A*6+WDik3q;!@gSiJ0=@iFSh(iG#+*1g|IUc66s$M z&O)yVCb8hA0;EoGcpWyGkPGvvTo#JqCm5(_CP~X5W+MFtM|<#D(p`LJE5tKTs0GHS z*wkT$q2vs3#P{X>CfJB$&Y}5ZLX&`XiIQ}s#fJ-I;`nLd~w6$9FFeiX3Q8Wo3f`JK?5Ho{8)iGDhLLE8 z^g)QHuQS^YR^J*BWSI}>66l8%2Ey?RuABt}Q^)WR6n1vUdR|xRY{1ezn=M^pm?Y_V@rB9z6g`fA#p;-=k7auERDNW>)GRq7@mbdF~yD ze4}&TcPoiHMSCh@6~m_c%RJO@DI1?^S%Lry^!eDDrJdoYsxw8+cs0AwumIUn&vSX>MC&f z)lTF$2++{O-z>EAf3i>-Ek`rM`-C0+cD{xqbA3l#BVm6!uqDO3mwSe8=kni=>dPkB+u`mOj&9!lR&1blm>x=+m87YKldE65z!**?MRp9;c6dX=@fwgW&5{M9p%x4Aso05D9JldRUeuMot zCFzKo{F!vqtNpO#-~QeE-l4dEp|=Z^lJv7G1h>BfSuo}XCTR}2!Z$8Hu6wa8SNPG> zARhV^P5Rx@Z4_fAKelUP0LyQmu&Or1xZ7V;6xu&EE=~odJ@E$b#>X9!=;kf(hZF^5 zYJVd+q98qMstHO`_>VfDm^<{5kf_$)nTl+V2#ZgtrNTz_F#@71&1EO|KBP4Vj(U^7 z!1>z%nEqs=_@O%8st5scDN$3>Xwo|ru*Db@7Dz0&*+@(wJUxA^9f`=yQV9k%t($p1P281Px(vAc`f~4o1CtYb3tct6%^Gs1 z_m4eyB~V;H6o1X2N}s9^N}9_5K3^`DAwBCx-kJ0>L%MEbnpA0CT8&5W{Nxaq z1^m5jy@$xIjIG?%Y2(mg20DXX!-y%U;ZlYTTU0CQJ!4fq8LIwgks>VeSGlIr^oX?+ zZWVsn>U*g{_6_I=rB0%F#D1Gc#BDSmO+ebi%`5hyyJn&_DGR_^I=jD{TvUI_oG z$+0E!;a$pq5eTKWW$Dopkn8iF%(vP$p>_CYm*S=R7|i}=tKO-_XqMpVt2@&z=CnH7 z-&G3IAw#Uo^M6(;JYH5~ETTNp<40ZVO#a-O?2+EO1!`8)e@}FFlLsEhX=SxbMm?*; z0r7hORi$7B#AYDnZ*$duuN9h2sPo&Z_tbb*fXa^LYgdF6Q%J=qQN!dB-CH|mk`E|g znN`;U{fvU)GheL_)?5S*VxEZ$gcAkbz75DyOUWKEIH6xdz9xt(Np-ZncLcY^&Wt)t zfTa_j4Du#NueV-&*-w9Ay8jvS0~QrSnnJzgY=)uO5x7kU_B=8QRQAXV4n*Sk>=^B; zn>aSfWQXqj|D6yv3~GR6=n7(;hhIMSr%jr=3uaNf!0W8Gkb&AIAy9w*^LKYjG@q#y zj85b~yHlDSvtD!p&1#Df@KSXh#9?dT+OI|(#Vs4T>{iFxE7~?}B5wMzN2i$tSU@3w zO&&`ilnOtficlpdFURZb?_*|>HId**5xY3$0e^yART4siV->@HE9gruseop}yGR0) z3)!JLcaSeszUGG91A&qy2*HMstFh#`3)6rq2->9btnI5L>V6Z2ti%2ELkBLKJIRKE zRT=Y9=a>tXoX@;V$*lw99u^+)5O8xd7$6xBSJ?cDLYR5~VsL)uFv)O_nuob{vj{?6 zisntO*(R`Qm!wjI-g$|JgW#4s?A}X_CNb5<-)}k+LGJ=(vek!=q!5Xyklc0ZWWm2q z&1X}rTzSHitRRf)Eu2VU%+tyVsz%>%!jV9WRbwOLyJ~G(ISJnRlb+QYz`}1S@fpG^ zZ@t(^Q+e{wMMh$IB|X0Ql~XlLM)-_;^RBNS{J&zrOZWZ|6H+B{$K{oZ$HD)G&8~JT zjovPnT(OHcu?Z)4I<;Hej$0xC_UU6$+>cyb(fGZT@7aZ1C!ht0@&z-+XO4%d6XzAs zUKPi{kmD$MQ$o@)UWpx5HV{-TV-PRG_Ooi2eSf_}B+7+SU{?CU9T`!qNl0~$umG|T zUvkuN=kEWZ>mArDUAuML*tTt(72CFLn^#>+SCMjSLcEnn>+N0*4=;@f}p$L=pL1$;G7Y1H2DCxf!AOio%0nZXL2ht87N+ z0@EgjUD{1>mdvQunq$YZd_nYA2p@6Hwb%^C1QuGlz!XRB4MiW`I5s2TQKhPH>5qm( z@%_eQqD_zbH~HdpkKU)`a}A3+B8f+RwAI{0XMtX0DMO*Vr?5MD4P%vozm0pe=I?(T zw`Ik>A&l-Mrh^dGLHakBgyk}*)EE7#Pjw2(BO zhhlcEbNE`NW`0!&i8$r~7Sg$4i5+rI$b_eqzu`0}Ca+%&`)!mz%C(;t_clzNitQUi zb;g-xFMn}L<@!ayFJg7lTK&SFUBwK*{Pjincz%csu9tOlTD#LabhhN=aRdI*b3@z= z{<^W4F&hos;Jh*~G8S%TJk*I$lg ztk@P=@V*$~7HRcZ>)*t5;AxOhSb#Qo=fuV2*}TWfl7ka}L+|YI=BYS{?+lTrjtM|` zsLTB7`>@7Y5-uftG76b$seIvZj+H;`X>h{v&yVD%N5<7zcLnBEq4)QZ44wD?2G`FzSKF}NiN%tbGCBThe zQsc9ki=JhQT$3|L^KRjOl7%~rcknhgM*-vk0QI3d-~bZS$5&~OG-cR(`xTo`MxMe& zvkrsy)h$4gqND7L-O%#X3-UGQb|E_p*kYBKgp9FmFfT<_%wt=}V=812Xh^?QSCLka z|EMH0SNpAj7AGAR&)M6VB^dl!Y|cIzO=eeC2g(QRY)D>z86^UyGKai3$+h~19)ds- za7`#vkWVq?^9q4OBO0XJ;(QI4`JMwJXuZ(IR#1RZnn~IU$-)$BBa-Z^k|!=;eJVhk zzq_GbzKo<7f`=eq@~EgZ6M;cdrP!!UI_+fV!lLn>R~g>2e@kVNXz}{WH^zI(K#r>} z>`y1N{>XZ0+1^ka!khJ)ko`@`WNe%RK*>!TPDycWZ|g!Gz=T?SjcG|7h{qsDQvci7 zshuMcFCvv)$UjJcT9)v+n_foXwswR#XdW6z_98#7&v+>;#}%y8k9iApnv%k2bZ?bF zpHfP4_-^2xH`Pm?L34zZCfP5VFoJFhOrnuIf9qhzl$MW|RRkv@1NWBp_-bJZ!1RZr zXj~F9kO+=O6=VNI8^9DeQ^sq4o;Xxh<9fs;<3`pxGSLDHvR_wRWFq;ujg`mR)8>z6 zEWN&6?ZIUvjVlcu$)@~ZloL-K+E zs-$dibtKp7$D>XY6mMPPPX?j`z(Nkw3`T`R5f#q+aeD^OWE0};4+h|rmos$eq+aH~ zs8TxTHvQAH!88NlnLJmAduCzkP*RJq_3lEMtr}9Xl{7Wr(}mG#D2C{ar@BKi+gT&i z1?MRqY4;<&ro}Ex?IOV^ntY-vV2)C8anfiw=W(*i+po&a7j}FgQ*{*y&}iwC9?Etb znq~I%8{@IxNW%+?ev0XhV#XQ;EIDvxTD<$cRn=J2bFSj*wL*ZqK=7c}R*Fg}^Z@RbubA*X|hyOsbnt@UJK~DLd z_FFz=&o6gAv+c%o^ZI-F5Nd-j&YhWgB)#8!W`~V>Oc!&W{LOzG0OfK;d)8{QzCoVV zk7mu2lfAxWpI$XwkhbrTV104xRe`*no0s@z|GrH2UE6@lanwii42WgUL+GOTtyE(J?xhM3z@ zT_Fx~gaz$r1+CLJPv52D@xIdFr@foo6iNXSUp=+vf$QH`xnFydr&KB%*g5W;!NClCzYjy#R3 zxBGy?xXT1?m%FAmIzk6w1iv)EJVDS?Q?jyje0N{Vde1@epSeL-6CS%CRmnM{jFtQZ6SxK_EX)y~f2~?pj4LF|EMcjYYTr>*5rV@pd@#%-%R-9)h~uNSJ6)eXmP4O&?gtm$ z)=*5tXR2tjX{QCt?WlAEhO27sRl=5=?FT=1!7Fr*ZrvJy+L$s(&Y>h>0MqF|(^4^w zBS)_N;&)X`PSZOi<`Q7;oZ@oR_ag$BI|s(j?Y__R0j)8cbdSW;aWlx66|Z`m)>oRA zy=B77Er6K-7I0kB0gg+RhjVqnaS5~}XyM3D-l2|hi z!asuOsuY!Y^{sLAH2C}>M#Z~H%N3EI%zB!EO@b-ls^?DqEIP*8!J30H}t4 z5Ei5^Lv=I!?kLmyY)V4M*45~m9~27J_~TfiMiZ%5{b=?6`S-1+H$J|${~t5_4KTVM zJIDN;f>>PhuxB-&@2wc-gw$4U%hQ|C6goMO;jgEv95lyL`#EwZQep z&6x`iHc7dilvJYU_TIw71JLywKF?Yd7&o^Jp-qEBS(laCIhB*<_63-DbYR9%Hv770 zVt0o3v~rZR0@sn@6r-W5V?!XR>V1ar*0| zx2Sh(@#pgZ8J)GJGP;vQxtES{y4P}5xoB5h69;Q^p3lD9qHkoH_B@~kc&|Qx!(6@` z=REgkPV5ZqtHi81pg+3s_%mic3=Yz15-jxTFkC#X)eUJXFTHS_Qu-%wckP^_f>si8 zg|Z)&BHd*EL|WG}+lm?j%_3k2LHS{wqaIuitG+9-7dtdq=prr@^pa^_j-Z5JiON@F z!w^2pWA&@VMT{-U{dA&rk<*Eo2cB{7%p(JiCc~lJnF%Hyz(jJ>R`Z~Tm>V~RrxozDhNXjv}dr34L$_qzDgrl?NK5B*jL~VM?{K_KGl*WGLUz;-SNK3 zd#R<=Gjr$yE;;qyGRnj+NS~f~pRC{IpIe07DPm-$oZH7~T5R^*UbM(nDa!cWmMnIyF=Y_h6+zOpuQC7hhK?H12cwA?yx1Ol?+S%6H?p^4q&rj_u zG=v%1k-GlIQ|AJun_mgLvkr%Hm{o8`TtxsOx?QeWqaARssc~TE zKjRQ6~m)g$|<16?9kP4$+~%9j+_N*7_lTbpvmOyI_;o|)y3pg#^@t(ewF0t zcimFwo6fL45j4fGFx{ZgxH`JUfc51;?=}_PCK!;l`IqyfO)-^FABEMSaqD5+;v35l z+HIz$W9yX2@4i6)drzcIQfs(cRJ3ffNC5z}J9Q%OyZ?eI@x5ksJbwwASv%gvho{Zs zO0waUOGmDGUDm)Ut(*};;^cRHrc3OHz=FI{KQi%3*LoV$2Hr55vh|==AsKOT2ms!u zn9#-HQQ}ShlN|IP(&TARKh{!!|&O}LBgsUgcN!Q36XVGIB`R(Zb%iXJ&}M7 zu8Kv}uC}Tyj)2*(GrKY6y=#ez*_Fq)SFYL9_aC{?F3Skd4d1ph?>>wNIC&Lj_nrw0 z`yK9tBw@ubQB*fBA?7(`1_J~^=?)~ET-PRqL+LK2tFle5w0|uFq^kUO=?CucjRMi> z>-@U7`4TN*ch9RbFD+Y%hx0hIs89f{u(}M;ely}$o%ET+&4g8mFKow`M1WT%Sw(#n ze2=>59^WFc3#|@iLwnLS?(2`86P*!aABPJij8>%wiARWCUYk2QeR?_`iAhX4 zyig>+sj7^jrpZA&zYIpoGoRPG))xM&-1O4F`$3Yz{1bEw_zPx^CnWkG1`PNF{SO5G z5jX1(gupp(KnVPP`TC*w-39*ZkRi=#z84t(vfVYOBC8d>2Rb)@6VZXO8=!O3n@W-P z+P>N$(OVJO(~tpUEHbwDj{{%v!D?|+yd3j1N&cKaE>#+&o|vqoYBvM2FqV`VRIktR z?IBd3IFp2LB6x zj{GIas<5#Lf)p7{*8K0VOS&hvojj&mq7#B1D`dI8bKh>Xbd;Fwpn+zvmX2Nvr@liX z3L{R6VOCP}i&-Xoil+m7OWqGkR$Hbdr+JG0f5I+P3k>C7QbxK7Y1uRs_o*I@fHlb^ zzHH6)q~ktD{>VI9Lp>6pD|hgF&8UY8@htIOn+dpCPXQ?_QYjPuCn!$Mmk8Xf1FvZn ztE&KW;zRsL$2ra6z?}HID3JWd&0UlL$#1gs{}}Ko_0#_t@Wm_f|6{;EHT+)&JOHS` zAO9}}{%>G$Va|Ay-ao3%sYtOB@R}Bc__#?B*Y#^=k3~*dC5c=J4Tpmw>KSs;hXUFV zIPlc#zvOpC^8btcM*RPhU+aI!FW~<|zXVzTLBCD^px>4HuYI^n5qZnwp4r}uZlN;p z(s%0AHm>=prZ8)DTIfD!hr3O)2!UmluExc*_`GZo8}XvlY7pp>=EodkYC5=LAfS zcOPlVqw3{2>i$+$YMwE;@GOxP@OaWxHb)aHgrasOAOh}w2!%kXl^y$DFcu(c9kU z4S2iZ;E-fP4wv-aW;tMEV2#EVuy}yRQY9G9WWyb@*H`$J@}s{QA+dM26fI8)|IH#e z+cm^jKBY6rgHCRS(tDp(&({vw*@Kzs9-C?BE(dO8PIb#hV5!c25j+$?7^GSX-8t6C z9kz*3t)>NFUC5EO9Ek8tQGfpxCfFIv(#cgmq=R=c8g7!}7FJ6pgD|%x&4PFIO>cE( zMv^F)>(->}21$Ed+$HqMw^(r@jD|9mDK~n=s?sM4A8i4t8M7^(uin0pbcw(FLj5Gl z#rC{L`GbAX4N+pjPH1mq!aGsYs8xR2(f zw}H)O{_jq`U$c?!DPqHseyw1h)6JiWvOL;WAKfh>cWylFUW>e+#F(mhGF%p>^g}|J zHhFzU*kk&r_U}9`gGdAqghsIxe8kcJ!^PZTy_W8Ty5>oNE)+8lG(=jwT8 zz;G9iuk@zpX2WBnDqpd$!2Q8XNb)wuRQ<vU}T#Qpk@Qsoz^_>;{&sQ$> zrkP)$2H5lU?A$;Zv=Rl73dOOnN8htMTS^xMIm zDC?p^{CXR;F;^s~O>KT#QGe4*(>HaJrkwjC?rG=^vh{EcI}HsmUJERF*gT?#qSdF? zxB_0+(Sudj#14Zvr_<=J5M$KmzYT54Z;Z$@9z?D;oi5v8{^L0}AVa*tkTl|Ec{q`I z^DPf!oGb>5!c02}_~*(lu)H2pKI_02OBSakj>$uQ9TWXv|N80pm}VlF?Fbh^+X_}R^D-X}>SJqG}J1?)X)xMiq8Un82Hs&@~LDk<9p1mlLc&9&t zxkQ+a5y5Olp}6LUO(+ochoZz${oR~%?u0OMUfwt*s>st z1ev4k$3WUTQAd|<_r*9NP^2R!x-XLqXR7g41`aF)e~|)QX`wkIPm;nqr<>6(Jt{0h ze@1`jR8nng3&IkeWiAev4)wlF6vsbVFtyjl_f%PEpk}1rM*|O`k9tU2!f^ z#OQ7oDZS#9Z|bNryuz3T)O>7Jlm+DedT*JPtYq1Th?NPBmg{GP7Hj~&rm949oCebJ z6^Jg1A9=gt8l7CfboWFlzhbmrj=g?*(N&Qkye<*;z7YAO3ln-?2n6Vl<#}u8!hxa z!CLX_UkdA_x}{W8gc!%GV+$eLjp583)Tbtg2;>&HiOZH%C{~F)MtS}ay6l^gqR=A!#|(S>b}KVT053gi`$EV2MsOF+LRUXri_Hy6jB3;aD-HQd*j z4YhnJK9de{U4ET+#UHoEE6LN zpDZ)52e-%$~v-Ddm1ddf&;2r5Kw7SIXK!lWh(-zPP`*bM>uB2K+{Hj zqpb)&LVBWnIWKvj!ecajwi9cGqf}>nK!sU+S2v?giJzql`2*=BlG~qqxthva^UC}r zR!XPum{3W(U!^qAM+&FKgP-T9n|%vY#163JW@zC2G`Z8%YFFE{ZIpwV=#!u}%kC{F zX~lzAEQxN(blEDZsT8GGBn{npRA*wghi^>dtUf`?y=qkD^3-z)=7sk(x9c_oG)AZ0 zYq+hI^#3Y~md8f&+J*ms!sh7?+2v=`okMRJFL8SMBl1)X@nFLwepbSbIp`=ws?S<{ z&*OM3)g*Has;~*}%S!C)Em}gG3Wh$HWzf;9}Ol7(P*mk!yr9;+nu8t1c=Yu#eDt{kx`2 zEZBos^ElxY!ck5;%k*@W0w*43Lb|?~Wi?iNSJNBZ#42;LRZ-%;9t-AlutA!wm)p%H zCeu=>PgnbMj+jMw5;tJX&oJh1s_yr1H2^_=s(@T42ykhZEzol)b94R z^B*HVJ{q@sY=t4J(mc z+$%2KixID{SEA>#*vp(zl}U&N`nt%b)W4K)#xp6y83!?{LvyrRz|Kfv7hu0MQby$&VE>^ zUi_?wzqgz=bRB2r44L5CU=gYGWIN4eE5eC~>NlN%f^6as?%YYE_4n}10l$PXw;#Pz zvM*UoyBBTuMdOeN@7Z!A6no5J@dlty>KgQuMG1KHV7d&H!Zf+?p-WD|E{v=0E9hTc z&KT{x<*wWRrSOLk!|1W-v>^E{45(RTr!v9jG|!-yiTEp|*G##-l>|Jg6Mwj_tNQMV zui=Z6nIMS~)DVs(oe|TB_!u2sPXMuu#)*h8FWU_6DjW^oK=J-)54-ON(E+G42(9^L zKex-9G`=d48XMom3&6^N?yCw&O-We#?sWrLIa< z+q{_}YJP&Q)rj6g2P2cmb+3`?v_(NCT=KD5MgxbEC`3_dR{6G6+1NRB&^i^a-$Fwy zl*a#Xnp-d7!=6nq40#}vf)Sv}aE5NxqFj{<>UX1qW7k;j%w`iF@kub(FFbwpA}9qy zGvP#$RIRWOIjb@i7&YWL8z38H1$~so$dFPGS@q;zPUd>Q=IT&jz2T6HX5rUehtbHm zUEB{HD4x=&cua-xhZw!)jTB}Ev(LF}aBje@rrx(wx5KvuTN%sEybF+j{`VC<=DgmW z^bx|4uZ7ur0_4@OjgQM5a=g8*Y#(OdgdlaNX+21YR0xrhp8oEin9jGx(uG8d%Vx0o!GM z*5|Wg^DZ82FObK6_4k6q4|Rx}Xe(vP9d4*vxy4G7$WG8pD3dP>N`DYKsY zljtTh2nL&F*8sttctQ$OA9HhI{AFQwuu;5RjkLSZp%Z&3#=9H7l>4Zb3hu zeM=Nj2*;F&g%^BHP`5XE#8J0or+wi;QeMG;lzjiXM(xa35oI= zv*K14(CrYw#xuS@MUE!=`;RX?+HfCiYKwF3V4!Q@=YtOm(W?Mhovq)+g5@q&mIsno z63+de(%>kd+0XeZoF?mlOJMj+U2ZDr%DbpR{n|zFRKJfuX1d6mPZP_&q`?QTCf$^N z?Fw^i{o@y5;;D76km1=r$#W@YK#wy|pVX+?gCz}1L}z))g=CL~x9>A)1@7|_ujFl5 zz)N2s4vac}+I=3OK~4YQuZoMGTk5L@NcYnlFcIbeTQ_X0iizn56A$a=D~U)%UjCF3mUp6D+)>mx|0!>4$w|bH#oihOl1M1V@0`vIEX#JPzpL^Vz~_Y^mRUu zuVC)CS%{B5@etU1T55iHXrXU3?)^SS{sUFi7puM3$q(Y|)@_#FICW8c_S}DLa?gB0 zVBj|2TI-Lqi3AvT1U_pz&*&fXL&MgDT|I1}Yw^KBliKPrF{}+>I3y&*DP>72_#}4# z)2dDtE%@rxF&mkyxdyj)4p;+`P;M6i%qCwkF2?Au?Q0+O!9bezRtB1W?oHb-n$^*v5I{6h za;oP)SiHr^(-QtzCR5LT!(8`4A-Oe#IQQt76+bPJPe%JI!M2%fFj48-r>`7p)86e! z)S_=~G(&HUq~3J=yoIWs9MgIr$yg5u`F`5)lda zd#FFQ+Zv$qMNk2fi>_>q7VNk6sB}WiGe~Lj-x5>ZVway$voFU($n_ds4E+Y)cE&An zZFtjgvKgMDCVaUq1j(cE9S?AhyKq#_0cySRWp=QXYKeP_!VNqOWV)QA?o5y{EzF9! zwZ0n4xhly~eku-;+GPZoX7Xuv>W-3+o&M;mhb(}~-aTAcu(I43bll&U2eIw~cyYM4 z^)3jB-R!T%^RB^}SqUOZ4=3KGXYdDY&-2;ug{%xT^KMlYY{ZgYZFGXkEjEt*o#gl2 zVtWZ*>32NFw?>>^6cfW@&M{*{>@kYA!{NC4?cgVI-|(_6XkMfT{?IaMDOoNM4=Aya z5cdN-9Q@)tp|g;bKc3Bc!0?AT;yF3;1(sEGYAWTb-kpUwFv*{NSbHQEBXsOw1(`NB zQdN+j?W`XosZ0~ItjaT^)mC%7^Qn{Dk7@#(1ORIcT4%%UUOm3IS9#q6exJS%0cyqT z>>l@D%~e))(|YbZ2zN$I>glbbzq$m#D6@zqcQ}{@SL}JBi5s0|yf$P=@j%g8pGafzey_53^i)SV*w)jyS7!U;0t zhq;oUCXijkVkaZa4bomXI3UXaVqqfyn`nK>Gd| zHZ)Kvv;l^-URVQ!5b)y=+In*&QleMg0fT5lnYv%DIS_Bd6#!GyB!x+ku!_OzJ<9NG-;88Y<~ z*otv4hKWIUcXw!miSh+hr(|0D2mlr-axYOq zFfw!`mN0O(USyF~5UYBNMU0|ZkCKr1I7=98`go9uaWQ6w48sDhj^)}s+`iqhtF82% z#SG53Q&8EB6zGn`>9EN-^u#~Jea3le{b}cI2Q5RKgGHvs2?^*(x_%JVAINYdlcuXB z<1j+$7CFbnhNed(}n_4PPe|b;> zkF=gaZIbDfH|gzHEmkFTE98_CPKjj0Wh=nX7tC!(*Q08-ZMGsX-xNlQfU7phUFCTamGDd)P>E9IN&zwF#)~0E(J2;fI zk)XosTe^!Ok+lFx7JGLOI%8h5ffr4{Z{cCts}0@mhy!V+b=wYjo6I8_KL7ar3da!T z!;u{7AnBn;OBWmxLqYEMvpRe18)->er}MnjX#P)9rFeIIc7uo79njZAkjf<)O*^{S zc%Isx+RNprjmDyl*XsZ|Ngr!Mg+dCk@-~bC-OH{= z7=K46#|7?o(meL8`LKlpfB8aeEXBZdkEHI)h8d*RQ-1mu7mNiPCoYk(U`Pp)+&PpV zx5wD2vDIL3sE2Dyij79sj4fMsFC<0JKko~I-kU+#ekoLsK_1Rn9X2@Vr7u@jIoLDI ziCTs;JQ)CPUzg4p0`PBUSea0vk-fy}MCsF)Por{1$s*McNYO&0YXezSSex&(agBK7 z@vaHX8Bf5Q!lW3ck^_|mh0(0%c(%`xsOD%!U3Md3**Rzh{1Zn220b)$l107A2B7A$|bZrx5PIL-c5?nhTU97)EoWt+S-a zj0q1w<-9cGr~Pm4MxQA;+&HYE;OcPa9opkhMU9I;{Dnd^CKk)5Rn^ZWHooxv0K5j( zhsfi^YGHwQ0XI)YJvxH#O{xaH?$GF*js(kZclF5epFaAFsql$;*)%wp>4tl@S3e-s zp`ZbO)kD#W&$)1&5yRZ@1~~&!iW7qez>PQg*0I(x)li3_E(zcOjiyzV=-r@l*j`7=QIdG0zFMw6FiftJ1 z$nzt(lCP!gHi+6r8V{~^WkH)s&v-j7Em9Wuci%738;N>eyi+!1kiW)P+?PG2jrS0N zM*2VOKKU#JDvvkk##|H5|N# zTUa-CjotrKf1#VoE3I+XgLO3F$?`I)eTWd*AH!U`%xSan_&qL@9;dUiX)nAS%W+uK zcwnCNv~{be6+Hvz4+KDUFfORMPI;%eEEGF~fwB+R~*T6^{ zOI6|kbmc+6yFFlUn`-d)u{&BUI~A+4?yWZSeXTI(D<^>`UxN|Ga5L-Q=u_wPX4%RPR%imL6eA8Q}=l^B@H;|GxOd@_o6@Wa~ggax&SP@lLB{qF&KicfC%XOzr0jaZ^V-?SiRHDt@3S z!!*13U-YDBuTcQo0c@qHYk?YAit8V?gpnkDbN>7(6*#0j=YIAdbFlEwr7W1(y1{On zK4%~SOw3H@%=*2{Au=tXDweB4kzBj-n!lul>rmmMVdFC;t?O1}Tnd^4IyrJ-D#y6A z^W~V5NFc()g3s1=OFkIKEQa<1>c30KPZn6!$z`p>>@k%ZYm2a`Z?Qcy$$nlL! zQ2W;Xjws;Z+iY=o_6lh{c!E3!s>k%s)C-wPK!WT15_@wnENz@im-Qcp7&Xh8ZN)_# z1kbtRB9^Y9d)?Lk^t$s5N^BcAL!nIlJw*oPA|qNlv~jA&CxQ{>MiGNRsrKsQ=3Y;1&OSsR}HGgh*pA&EpbLB$P5NN=odTYM$Aq^a=j`sUF? z$~e~Ne3MKV0g+6n7m`wBqFTt<#DJqL7tVe~UL}C({w?5)^gijXA|`Mg5w@B0qHi9x z7v0Z27Wm$LbnwWKdHVH9D$9=R>!#(0TYDRyH?^?2`5<}L&ui%`s zRLNRr>|3A`Nft}Dnr?LMtB)=AX1g8~-n%Cwy2!gQLyCb6eXY5y1D|`^6&(H&s zZ|`}#)<|bQW9jIxrk&GP_JiLU3um2j14#hkNt_|5SV?ke8vwa8q}?eL)Kk2dmoZ+b zBbuv<@to5S+@Y7z)we%H0r(Zso6RkwV%QtYu)nYI+fPN3hvR+e%Z;c)ibQJAWqp#v zB9Z|iSGB&Oedc9|U*prKashSc1;|HImM51gxJXbNSj}T?5g8*4hEp4{_ z*Wa?B8kEnJ2yaKj>T`$YEcH%;U!=R{KMr~FP#>aFmB=nXU0_xV(Cn&Khp%!0pskM$lj>17>HMy6Dxl}f@or8nLj+K#JP|CtyDx4C616 zMoc&TJSfR0+xy#Kcyd!t+oJ~QiKEV=$YMcXnjyWKVv{L!LER}w>s=X$SYCR|tG>%* z(1eJH#ZPp8{=RSdArWNM`G6}49;={ZqVY`i(|U?s-x14i|JmzP>>AU`Hc;&l_=kF% zlYP-Vv1;=7O4hL$v`!N~&bLMLHk0Y5KEOzWh(w+Cx52yVI;7w3n))O3dcN~$U(L|* zwAb=oY)#uvTeo&F7#Ae+Y}L@>W`GrnDoG^dTSqZ33Q`dNB&>P+(!QGxuuLsNq_a~Q zrJI(8K74jSkLaBU<+;o6Zs?O5;4~6RT`7$;)a}&gp>omH^aVed7bKt(YpJ@gcLeDQ zR*fko6h>fWC#eeCZjY$K1kEl=OpCpS0uEdaF%~-T{eao;GVr*%9^sr-_A0J450G^f zah?Q>N~9q~TN>jLtmmxumpIGA+b%hyq*&tZ_sW58X{#pJDiwJ;Ji}W9yylL56d}yD zEi@I}PgL`AM&>X|V57z;!}5P@nt~pJzot~k@I&4p%fBGekIr;Lc97~scW><;sRQVNL>sn=r@3V{0*U{$;uhfElY=~i(frN z*hTkp@p2P>bQ;s5D?^6~c$LCy)q=K-bwc8x#$Yc&(;OU%8)(3VJV)vnTF^))K@$z> z-A27h*cd`0?zNCc^Bu3`lDJjXUQ7h%gEvGsI>?%S?pw&E!0nT(0g(u}M9_$^m^%2h znMl^GtQqv$?~f21V+CNSvX(PvIdLwdXS>D5}uAeq!(nAT>Ti(q7WndcbJp9}fg5ZG`0rQ!qOk zbVgXl7=QR&ZmNFC2%V^8mNJx=u=Cp-Z&}k773L6$V50Oqnr=O5H4dYF27us>J8K8O<;kzQ$N%F9aUo~Ysu8k2nD;s&?k zVPRfotas5+yy#X&DUN9=zSW0_l#1R6)!~X3Wh0Pavj>noe?f|hR&|=j&zUAh+*!>@ z<8fNEY)~@*m}VePwtjzJtVi<9oyWzrx<<#6{*Va-N&#!YuAU5 z)!z2W-A4#t*2P7|po!mx=^F@x$t%G@cU{U+%~g;L z$#y=7_LKQrQz~G)zBp@uDRB0s6L;h^nv_6m(~l>>0}5K|?Bu=9WwX%hEAA%=3w=vS zhaQ^gV^rr<=lJSbXwl@?C6Z^-Q-_X#+Y719=KPe^o54I=ze`Q`+$kKm3TAfMg(mYa zh8UApfM6YE$Xx#M(V?{IOW27yblT%}dxzr%t~Sci*>gKQ-4qND1I;o?d2le)X;8ae zsh8d#R>-Y8S8`|iA;L0uRF;!2;?TR*}IWjSuQP z2EA(*8}=D$bO6!GG)G)p>v`$zPE#CXKibb$tr_M*My6+b2o(PS!o0v&q&4>4hnywq z=4DXmIM&{5`LM95=3rAPD5;22`k|}1jxB-b0qEdOlDO)JTqbc%KO=-7%=r@y@2lYs zKu7`0sF;tt2!ni)ZcUH~K`~vI`on0!lfir*>jyH=q{!9pwKvt-uceuvA@po&rD)(5 zI(Kn7e5I_-!+wMX*mYSgaVw73$hjKZPHVu%sA(e?u7T9HRU(Nz6YzrZ3{<#1AuxR;R|dJ+d zS&0}ET=<+zdtfxHR!Y+<<9b3Ym01Jb(ulg-4o^mST+y`zFEx6%$84EPjNM;*01<}g zsX3QOzs$pL%ij?dXyUuJR=I`h*Ni&m<)b>Pl58l_Xj6@Z)=4E{W61+HC!2jxzo!tH z3ADIoy%66Gz;A?9?{rh_Lu$ z+D|ue#A>xx8KvP2LEzhE2v5Pl3a}43ERciw`O}1lphYa45&n**AC+aJui_BO$_x@0 zts;mWLPyF7+t(`iH(hrDEL9hK%^cq2qFq|IY{hxpBW>?>{bO3!cyCA}MLis7USp>+ z@QTBnC)}e?L34O8vjX%Rf%}uP7j8)FD9WmNliTQO$0F8dA`L!iD4ni07=QuNsNcER z?tm#GIn!W~MTGar9#c0;5tfDL8Xz!KA*=zT*-~TDzqC{#76zcyT+Bk6kPfMn$T!dn zg%7mH&T=;U>uQkeDOK4m6rv2w3`a+^X^7Lv+nbtH5w5M7jHUyhTG=s|$}d9BBgan# zi@$j&Q#^!SNfJ&JRN$Iz0Vwurg+VOBWNf;*HZ@cdv7^yU0BM3Rj3~xk1F#BP^4|ON zlkdbc2z)psZhA96Cd1hv4ZNQpK^lmpbo9JxqAL9kurK##K^WsMPQmHEsTURvq3P!{ zu>Eq{Nvm8?bnGAKb@7RhsBLSH!pHR3IZ-f_>Ndv4-lNHyC>nis1o*lMy|BhPUR@ow zdI4X+{;pqcx-ET&xMwdaA}cR|mABzzlveY<5VuX^qMT!?T4zv;0-BP#lUfM=?!WGs z;GAG4AKz_IsKMW0uNwmV*0;5;kV`cGQ#=t`+lbyt=I+}!#X*<#uWK1 zTv)CsgGK?CLIdE$H3`@*ppnC{z!uSh)+3tgeDN3i3N*MnU9IlbX9-W_iaDZUSK>U~ zckt)UmT8ePXd>8ERF9k-zQ3c=kUwoy^;0jNvA#MESR65RsP85iccRz19ae||d$L}b zzxFg6IcQ-m2S2 z6^IX^NWWQe+S>xwF)%K97@_3~@>&1csiJN8dEOR(bKm|5CRk*m?rAtaUZ^4XIU%3A z3Na2~YE5nUHKHkJmuk6hJZGkY^U7{HZ6j>> zhiUxq*Pfvg_D1Einv~}*Ub2LIjyW`?#8TRpUDXwSQ1DvnJwnBV97WkHMp<~3a1IgH z6n6kV%RFu;<8>yY=Ll`P<95BENrE+X4*FTXeMnI$3e&Q`(y57<%8C)zek(Wr+#o3N zockAeju=>b#ouZMCS~eB3Jctu|jAc|xNFe{3-3l9N;1ns8q7{QBvs+m23cTh#W5e*b;QMruvWCN=9E4#_0bQCpLZuBEn*xK~K{I-(S~ zd)*)H4Lhe+j&EYfi|6UUkX};x*y>QZKTBK>`HqQ!msI7#=SgzU6!T?BU?or{VP_2> zQ=HH#bJ?+c>iJN3ea-Ul(p$yvGV!G=o3&YFqY5CUU!jh-oT1U4_xMy0v zP0$Y$3;ghW33}!+H+_NB==__?2LwLV?LaxD!toCp=2F_EQ3(f65t?HAS%ZZpTI*%V z!;&oySl?}Xd1K0`cw$W;M~e~td^;e&dz0v@kt)hDr*xF=^HwwWAAI68vFa%)D?%OQ z@3YN8byw4j_gWrT@*0OyYpKm5vr_n5qFw6b4`pS2zZ+O)D<~U^LpZ>V1 zOW@kAl*H{1F#|u zeF~vZpoCS~A-A06APg?icp-N&X?_qILpZkrm)hTB3>Z&CTqAN00JBf1A=4eLP6tl+ zSY354pSn5bmn!)(OMwAjJ@LA?6e!2Ny9^XWDFiHtB9;udiRcZoM`IQzVvj z8g(s{1KE_&Bxs_90rV5WCHHAXZJry&Me66Gb-0hoMC0E@pz~zL$*A>jhD<^Sg3a`Q zV*~(*Byz8nXTGsg!^1((<2H8b61_M|booW>pG3=ZV3Bx^v<>-`uwQOqKxQh(Ng5T)|iz{ zmg02PFD!0WeT(0dCPN|2iZj{C+{ucbBY9DdQ(>!C){6NMw{}fz*|1BJ4X}-pJ_LAR zT}fmGxrl*(0V-jxQ|f^a)&obPY^KHf)U~Wj9D3vSp5DE^25cSBPXzQE`<{3{& znVvmacarty^XRDL#xPCUl3eM^pX8u&#tjwuW|}Djd}isTd@RSyMjBlAtQ8YcArT6k z5<-7g>z+)IA)kY{0R2C{%g+G0K#h+f^#KQ3v{8CWZRFBzYg#saEVj7Kj~RW z7>#d#15oYUWB%NCeve1`fhg6v^uR>G(V9Zx(PnJ25V9BXy;2?bX)&3&eRIMxef;3U z*2UxH<0A2%UkT%zuSrT(;BBH048 zXItF!!txd6R%a!|HR1h{Ngk6E^U?S0=~jRt93Z_`aO&%|QGYY=(~q>P>Q`ckF?e;k57CpcDE2w`&xC<9a*%-I(p zRELYjtQJ&w=OqZ047BnNGWF$p5Y=+9I9H3)e+&7BxkH^{CTPFjJ8P=SnO?T*&`k*z z?O3aU%Mt>KnMm54JgLSXwr2^yVpG?9ehW{D4*I&C2Lpw)mi&U{w(z;a9@*EwJBg@>i#r*T5zSw&^z2z*O=TL9zO0AtanmdTX$pFziezN3Fh`p!nuu>J46YV}~ ze^sL2pZjk+Z+ezJyX2L`HD=?2JW6e|H6Jgc@ue0F}C*ZFri}r zyjBZ2eZy2r2THL6aEF?<;ZF1`x^CY3&mOLJn942^MTv=m38`hHYGC60E$HHUJC7+U zQ<9UD6IX6}7#HXp*(=`_%#Gc<{y8nhf4Ok~kLaMA?%~U63=R13rT1$3vZ-$ysC-=u z5ybFQt5Mb!Qv>EKo;oqTb3IyV>_AEy2?F8RpzE|0X(S=Vs+XCDu^Mh#r4w}|ULZBz zmle+c1ElEz8OtL!Qdy$aaNKrex*jYEt&aF-fC={Tc_gn2&VL&dO*K9LhmcyAXr=mMn0cNV-kZn6W4mvosKTX!{&MYe|fW(l&h_f4N3#()Fkym)Lp~oJn zWF*h`U52*jKljT*E_UEr9IGm^Rt+0J7{D8%8Y8094q^Y5_zwK8JoU3r-C@gJd*i_L z-W%9z;n&tiy`RaX;WuxkaUH+kGSBcJEtq<>4)YTx)-cnC*~M3{+*$P`$e78-QesE;q!gk3_u2^wAp!|i z^#R#4^Jd<>neh2bnU$WmN1ii{fgvq8C3Gy&%sz!v&y%b`Q!TXI(sngPUJER66E4Lp%L41+g3 z!-5TrS3I33&a^tPU5=J^DkRH6Bik#PAHlY73`FSKeU_G24-BFx9a~8TdS>tBfjwol z%LRwDlAMH+kR)75t7F9}r~~RCEq*gXaQe!3@Kddd(Ooa8#uvir!@F5zC*(e8ng(Bg z$g-kv0-g9Zb02 zx|X-kWz-{b&U>e0YK0Hn_`$c6w3&NL0zPjpRtXpKA4I5&-0ZfkWx?$t2cdnmB$?y9 zA*KoUOKv#XGVi_;r=T zof}{5WU`3kD2b!RYO`EN-xu-AdX>Dae!Rv>wEnq)*}UzC+nt~w9Q}LR^=o{cw^r;< z=C`2=-9&3tZ>GQ*@eG3QzX5z4uERqTE}6(L`q?A{2ILA@dw-vr-w*FEomJm|Z`v>r ze$QWVlXyrfpxP@8HrBOLrL9zuY7cFNOmcwN;8^x$9qRbscTPeG=?~HQ0UZ18zVGfk z+n+w`mG-wTKWdlJxQJJp6ta8lmhWHET3%klEVS z*ECb{lu-8%*UwV5kjuLe6I>&InazGSB8Hr2gtp=0ChSJ|hZ;K*{-59i4XOy=+G~d7 z&F0cHTH#tW77r41JK@Ttk7AxMns<6~;=u{rs6;*>Jbkfk zW*gy>h*%pVBIZui%T(Op)KPGQ_;pI6NI9ta zyCD~BmIHN$T<`cBE*xFv;uq#01_Mx8k~AIb1a9w{f-~jl+6@4$sF-kxok_F0%EFqs=0(Z!{SUkX785o2ni2mY)F~=7x=kzgU^vF z9s)82nN3S;u!^te1jIO2^meaIN^@Anyj`#7q-yQY) zhaxXVqZAXtG{(kip4g3jF3`+>8J~?tlI_qGEJ3&uYX9)(`t!qDGifrVcc@9BG(FLU zDrLH|Sey;_FO|&rf78Pn1@6%5=kD#?lFMyr(F8}_3mvog%?6SsJ(rlFMw#HDEHvb{ z{NF{%Me1T6h*wFDI~HsXQfwtF)SLQ-DxSf%)zH(Smqt_v}GB!o#sf$NClLW zrGDJ!Jjpu)+O<*QM_j2f4U+1#<`tQO(GhnzRyHX9PB`vkR;R(BV9!Fa6l~5cWQ+^r zT9~G|fAVp2As}aduh1$j2_Ksy)KfkMld}RRU=-k2q&hT$&{5)KJyNYZAnN=t;VTdpmv??cZw%C+tS*F0W%Shc8V+WT#d5uEnd z7ahKTJUbTHbx%By6MvCWjpIRUO&2LSlH3uSfBGE=;;7ph2Yl`VxPNr;XSu`bK4A1 zowQ!u5NWO>YKUe#K=Mta`%<~jj&^uY;Qj!uBcE}z+4*|C+^m=9*Q=|W&^1!?-k4!O*#o(t2VspC%a0+S>Knd3)s^BE5@sFG+V44t zFyz;pAiSc{+~F5t7=d*TXus#XzOi3N{{gjETTkOg6n@XII9;W}Moyrwp$Vm1kdRoY z5~Ds46iw`tWVH6!^^6IK^51)Ae96Ri5bf@cv`aib=R5a{e?3n(X|ESz5U~s$f2lGa zsD*k-QI3Cc&w4$RTjwzfRlhjMaKmG+rpST~hKH#2 z57J8EvueJ{MPOhqpHn76F4omee^bSpa*8X=Py{$dnM6<8FWrQ*fRUf8#|G6j*)}E2 z$b^_RF8BPe-}sv>*|KGXWjIzPJ_Hnw(!Bc4!1y}A^FL-ca~f8`Yf_2?{?ExKvcw!1cf2#uh$O<%! zVMQ{v4>aM)@v->}$M9RqG8Ti#qv)Ug06;%00v3YWAc14Z0}Wqavo+&FD)V}&lN)3a z5=cb!0!uDJ#|4R`ELWw#lS0#c8S!9e{bCVN2B|C$lv5B|=48l11K8BBV)t4s=Lbz0 z8&eAo7hd0bo%$Hni~NEg`~nswU&O^iaVvEoG)y zrZ6m2cgvj7ho~(qefSD03+;S!8)P3A{W;MIUJLi&p@pMQM~57Ze=dA~y6~qLx3jCe z>6Z)t`tEjdef#IVznI?rHG}b_aMxgBD&KLvZ-c(O_igOcHr%7_yV{4kADLw7?8MHg zXW}**C6qgbzC~3zu3P3tb>8;TPfkoF=Ax*@l&KADm;{kP8ZpY91U5-jRC8Sqby<5L z6Dm{S5@L)KF6rfle;PLonnH5jlyqUMB$WnjOSnkSRH?B?@)R`yY6(mQn?2_J)DPkO zeB3IBhRORD_XQ=8$^0=qJT|;bNu-?#1qQI9Ji1a*XYEf7Wd;+ZNosh#T@iJ0Tb49> zEHyCf2)SYSj@hrz53GRy1mCEF0=N#-0STRjq0cuIhX=#qe{d(bkvRIiwPn`y504Z+ zjreYbeXk(?py2)ApuLCN3ROAn4A0J4ZxHBe2d6V`(8p#W6_M^^2SmNGb+COX0#}Sj zJNFYv!-Njm_RO`nBSR|T(3ZWw)RfCdJ*=yq)?6g^my_m%F1a$js!$=c)@R2`ZF{e& z8Lej8+CA(Qe`8PDU_$#QW~!7z-m9QHxXgCb{sN$Ot!1xhv9;Nc%)mIZqo7AswOi99 z`HEOhlC{}iBU-=oxYDZ{Tk?pj7Z?CD&x15eQrbKfNw${K@*_>!BF@X5+yhdS{(KA7w{xw8c1~^mr=R7g@?M&UAsn?(>F%EF)?Ru}Y3HO>AfQgh zGA?!I;BY;J!Gvb}W#It|igW6^!=rW|s$DV~na`MaC@iN@6(=+5TVmbpL3T5@I&$5K zN~~&ee}3!z3$0bnZ`v>vzvr)bm5}OGK-X(2Y}4AEdYIbY03p|L8cV^BY^Rh}{onT- zC&m!ip<6Bq@ALP5?}MAKRZ%5L##u=LeB@ftQvBw6aree}WrdPK zNZqd>KJK;qY{BNWWX`;2dHZ<3sHN!yt6Zz~$}u8eCi|Yk1bLDRNlVb2W=fV@Kpu^O z5HbqU^TPETSiu)889%a){GB(COb~hCVcnpsMd7bqU~#aH87|& z&&69`kKIRKWec?O+7#YDlK(@{5IAK8lvHL8L@hH{jE4eaaQ^!o*3YG2h#5zU?U+GO4ppM5?K>W3+upQqPgc$qgD-vc3G(6(*KSCE_}Yn! z;1`IbLzpjzaFvc`T5ZUe6nEL>>ht>@UIqH8Jf`#9KzkB)%z6&dNN7;Ct!mrQXeK~I z7i>W-Fed+JdV-hx#}>)N2|M8AITqulud8jFbsz8{uM-#gB{one|Al3r@%f= z!**DAN{fNDVa;y?V*h##!HEs$EMSw?0$7a z%T4|v*+h}Tnwu6&4qs&R=l=8E*ZVt-%2bW6xu%5P%(i}%2VNsZE1^(==Exc)2OxE0 z;HM&?BWE8Q+1JWMe~MF~}} zN}p22{-jH!tcSn=SI)t2@Ket_rrtjLmgWL7? z?HPo(Es;Lcsj)Ae#ok^`>`N}Q z;~S3bJV*Zkw+q)84+4LsSl@5kHV}UIUvVo8Ols_;eRX2HK-)ca8_)#ULmU{iM8{lZ zQV^-wZqfgJ$6pdfNn5x1A-0ak<9FX3?@qZ}mxppP$!S)QiY8K3EK^%`DXCn(O>ZX? zPL5QTB%|<4Ax@i*51%#<72$F(sw1sXp_ajt{_$RLMbGLsTB(0|rkLQHkLQx`obhKb zkz<#(b9*dm$=_?RJ|XNLAIDN+zBLuhqSC_B%Ge0U-OeRov#>gA*Dd1k4224Ipu$`QxFob{)DHy--9TP?=8}$#`SvwO<@IZTP(pjwu-K=;pgW|9vL<+Lr@7WopZ-ye*GNvQLa#*g$0+fqLV9e{$ z0gZpZ+Pty57O&viA9{6l+u86PP6t*{Jk?x<`3gY?&=X@Ug`Y5Xn!7XrY|hf{L}!7a zat$Wyg3f5tO>ZQ-g8ICfuWZnDGQtA-(k{dx0FOwAPC9)`Z#1x2XBJazqZgA$qpgh% zb;x9x)mdL`2neoqI5;37W_`Ze5lIu{tbTv)oADGa01I=pKI}^1z~5a#Y{&5Kg;ax; zy=|pTVw=W<46NRo*v`}T7~f2W+6MUC#fzR?UtfpgQqtE?Q^%;IDV$gw3>`ez;k(V$wwiyY z$21wcFk7Mq;*3qzfl176bf}l(;}8lg0zU$QqMr$l%9{Dp41yN{m}d3|qBE34@TU3* zIod!RY+vJaEwY7Wv>I81ZC(z=0S#)v7Hk7B9d2?3<A_qML(<9U0I?eg$Kz_l-ifCc^`dF6Jgv0vE>60RWnU=IH9)sK z3d-d{T)i?{6g_YbAc8A}G}}#cg!b{yhbjE-rf6Tb7{@Z->+Y-0AlAGib_dhc&3=Aj zHyK~ivLLu=@U*Xm)`rt=QydwP z!zpOU$kTA9WjNjCxJ`#t>&;hQ66WUAx~+^}TWCEwJfg#xh@97Tq}%kPyQ24W2b;j9 zcEMzngE%lCgh-dmz`wQiPnT2cr@2tx*LGXec)w5n0u9Nr4nQyv0MM7!-56kh1XK#- z277hmq?dI?fo>g=yv0F4OGh?Qi4;gGuGi(i@9-j7QWSSZg&-EmkLU88o6axmZ9SXi zn3YUntc~KCxi|Y7_42pm^=u|sg}P=L!XKsFtv=j*UVZpx6w8cMblm9agTcOic`t>* zZ)SAzCstDJ!_VmKI@@B!CO21qpG1KQMTTLcTmK~dUBk;9$Mzn(r3UC5OO*S+`Ybm* zV*5OBQnFKfJ`=mxS17Puo5U1T7xI0;}m#Rmsp`N z8s0IJZP~iS?lgtot20!4qf@xT9T)ikJ^MZbdaMaf6l&6KcWT8Sm_fLI^p_zba`*%0 zVYvj+l;sFJq7)*22*$KfJteJKmpnT#a(|ymVp27ki5;LXNg>OnDEEOQh${D+I$#3d zy9<%oay`H3EV4RrH#Rw@M7QY2X;Zkq!Wx;e6voK{)>4)Zc+jKJG)e%Oivv+-r>7os z3U30Y%Ykz)ObV+m>#pQ~PN#6qHNPSG9=qV9I#&O{336Esya@9X^5yQ`-##s z`u5IxM&~_&_TdG@u1@0sOyImn+E|)>Y#_L3bE177hjJtBLQYEe9Lv08X?`J#R#n=P zo_5i-!O6a&$m1lLu(Xp(#QB_BEUs_9{5@r+&&=aSP6o6GaykR(#nQsYnts8%gT9{D zCuM3A!dG@Y-R7--7w(0sfSR=7*|-Frwu|-(8Dw7uN$$}{TI7LT4?fyv+A3Ov_B681 z5j?1g7ojG`ME5ne;OApD<;4G!Jh(HdpdBB?N<8YjG)Lnx-DzkGQv;OpAPLZTVAJhg zI#|bEhMx?swM;evD@`*yQuPx%+7nmS2kHGXJ3E87)P1Xe+U%*@P+n`c*Ki^v)qL4h z0(R77y2AF4RX2;ETQ1Wdj`9XyrCRke@Kd#r_EdSkq zE<2vKTx=FF#Xa%J>^4m`wLupF3M5cE`|mx-C=46Btav_Gjd*o*)H{DPxuji>=vLF8 zBCgzeH(FO7Xa50xkwH%!F${(8`4v9&z^-5yt}IZuE#ep#5Pz*zU2obj6n)RHxRX$u zR8X{6D0ExbK26iKO?zpp$RrN2aO}u-N>SJUzUvP{8lcsteJw0?}~(+d>yh7&MBx16Y?-Kt&D7i6M}= z_BB?fAd8}x!S!?DQw(7tC7;6pO@`TazgiAoji}fo&40TgzX)$AR^t}X224r84#j<0R?Kn%*%rc>x%*5W&Iw|%*425so!dC(3u9a{y+>5#F zP_}P%0Q)4o?dE}dzXYD1qa!o({JHlCb+DsQ$#rmTBNR1_630SbC9Pnb$Dv2eoJ@Qc z=lj%x8GnzV=7eDht=UpkRG1+&g0q#MSc|Te(SoADF&SzF$LmkQ-nAT3ChEqdSed5C zY`4gY(pm#E8fvM1LLzct8sr02YsHK~&0-(eO-9>DRzN&3CDWt1RrkBu%qcwSAh3@G zczfC_e|iry*ac79h%g!Z1b%~8UpS+=Bhh9b?tl4sRqP#m6(qjez6M;v#DTUH5|fpV zXM0)fQMfggH6Wu#I;(|rsy*ZW>I?z5MQxmj+gmkq&fZ~L(C-lkXENC?%LEn;s7LcGEdBUJtc%~0HJUG}iTCm(!~Kx9s{=NR($;IRST8m?h`x}hPSizwm{XL) zz%Bxq;WA5)pm!esh}gv*K-vFK^^QmHCVyNWv22^0xbgiD#=3$U&Fy^(cQNiL-!s#$ zjOXYNeN@42;~)^d`zvN8AFz}j_UdlxL)G2ON-L$kZC4S&;~EKr1-NMx<=+<@?AX)| z7hrh2_httBN72@8l9b2<)kuuhoY}oSwP?2Av->2Gv_aEShVWCU1}XE44HR6ut>6u}!B>`FD>V?F zCmYuUQd@I#_h3SKuL$OgiDlo6Wv2b8lt#*GAc0`YVp@{XTL#oXsvS)>v(OJ-x%4~V;^t8_O zH*Vv{ zySjv2oP`Z4E!JJy8n7$p?hXneC1!Bc>J0XT;9HZ`nMfqJbQIcH;3tu1P?x%N%S43S zy+BTXs%pOu!oa!qF9WN97_5MSb6ZvYoYdgb^Z}7nFv_7`;9OENmghh*6(JLlk_f^0 z10Iz|A4w+&sBTUKB>iQbOKq0~zf5TIj>HXl^2Rje!q^9A!xrWRO4q85?ln@gmcsMP zX0-fCmD0(4--CAi7-^A&+-;Y&k4fX!0+@k+xu)#>9_v@I+oe9BsUcZxhJk^}^9!_* zwFOTq2_V1N;kp0b?&9vdgC9g!WD-&>gH793*sk-V0)o@dIg(khj5^qR1qGSvdxBO9 zfd*>5hy{gn+)&FDOz27&>~HC{3skDiv#ERevc@ z=EQJ$liSOOv&j2T_W@VyRh`30+CJ0dulZ3oX$Y4Nt@7<)A?{$&zQg2<{0(9_(vm;sjUsqgz`=dXe*}^x7q_W%4gRi;Kx;AkiokDaxL+bgL;7g+PWUqn?9IvHsQVRP zOP7?fg4a6i+i%liOeE>;e>ai4?7bw(@K*?>twDH{awt>Ugm0!RZ*pH}{{f}9%J~>9 z7k^euPvbBUzUNoWp$7+23cI(KmR&6%t%O!9;8sv&QkO>LCEIDKp#Ocxk35>X-AXLm zLz;M={^pyp&oAXNd-EpFZL`5e+CRtrwAT zi7BEx8Utr^nx*jyuo^2m;2Sr(5VFB1Yq3mA?dE#jCy z#mrjwoC#_U5mgiD8q*A~T#*c$~wG7!_SDuyf>AbVoHLzJK2x#V8~;#WFXb0y;ucSqQ(8TpjZGxDjw8s5R@3 zl%9H8^aL?ptA)1X#_q?pR(GU;e8er1-NK6tIQ8Ke&RR*SUo->Kv{=x%Kp2NZT}D?D z8-P1gLE5pwmfhNOf33Yn9Th8V5w{Cg7GL31lFh7bRY5x%cgl>67Mz!icz=K2>UpA- zgL-TJz?GtIPNOUQMv}HejKEkr`Ut_IiL;H2;og=h2eO%;NI?A`7Ie$Gz^E_S=b%}uv z$L9yTO*#6%y~g$Z%K`mA@3eL|9Kza9V(XzS-OEXZTz8aE8P4xBVn3}<|3g$gjH~+D zMR!iR?$k}9S2jgueUJ;s^-K!_Rbw^SKplvnEO#(P%@noCq38C0M3b>R3`a`ysv>jX2p;S(1#x`@A?T-+jJW zzI#-HWU3JQxRTz%8zMH0lbosJRe195F{7no1z-NgA2h*#=4WwV?I~C8;Do{H2=;OD zrr?S`s?NzG+tEGoHs7B0dadSGH(|*OCkh0u2iuS#X$}cu8SgH zNiUZDWZyu4p+vtNSqjG0R=cppWC5LdQiAc)-8!&+nNv&<3BM4P?Z`T(?lb{!iHzRs zCwgFf6OfO-j6gqH?E_I1u5G5k*jfiO;8mV$b3!7eFI#6!CN*KZ4v5h$V;$a4vr*^S zMJAoMmm$R;x^Zi&CP>RAdNxMPll}xYWOiBkEU! zj?e@2W^@!=?iju}DQpYTGmn2VmsMF7LdnSJi+y5z)J|ub(Q&TgqdF0yfDfMw&*m2r zBoz--!t)n0y}W!5s7@wuuMOuZ?mnMt$8`#+ozAkBQ|*X?9pM|j0~aSsrf{KlOiRZs zpb5}_>HXBQTaOY?Rtn@GSMtYIyA@5R(>R`9BqxHsD5a@M?m?Q#e2>K&#glm{3RPr9 z-b0TTP3Dzg&E+&t9ACNjuOqh{qi>UWaN$9gdGy^}WAYO%DN$HNQJexof+1{gSWs07 z4muxcAnNkfD@*eVeyV94X1&&zoxsw8#3zk^Li^=q%*VQ>3EF=zF>b+jG&FG+lsv4 zo9MnN@@mgzOX_V#CwG!GRHlMFQ4X2vbNe1>TUXnyapm^T+dVRxZ|FvEe}B~`!?w_W z2$Ag|iqLPb8J?OH>om;uVdPns_`!>TNb4&iWF@GQXw4s@I}LGfZ>)aiStTw-d>;6&17?v62dA*YSt?Hw{YqfIRG==KzoP~HX1 z=6zc5w_BK&sjld=jP-dhGm@`x{yN8hjXQYW%e^LYm>UVsax-bL?v$5Fb7^OIHca%f zyk&x7CqDM^U0#~Lm8RZZ0papMg@i51adyxX0WrmI33Rqf1J73m^fQxT8n>X}v`;?H zvkAz;P?NRxThFtI{UyzFT`q_epsRnUD@wNw4#a>S)hmWCI2QB!TF>;7R# z*{pWq+A2xC(=Zfw-2}y!Yv#JBPSqG*dvMe(JbVxc8E-JTdA@cMzX6HwW)RBnR){p% ztn0&YKrll#Os+5!hr^g!*&mc|qPWi|CsxPCqJNq$K7aVw=aB6o!|nt~c&g2IgJ(0_ z58&m?HURTk-7LOcb&nB7OKk*ys=2-Eiu*6&3ss-#*kvub|Z8_n_HXdw;kqkUNNgVvSi3u;K#u&@6^KMt=r@Vd#T?o~HF1dXrxx(-D2 z&uxSJwa0(K?zh>`~@61(?aZWO`){R-1Su#zF?Y|zgx>IR));TrJmR{=} zLQ4wX|6#DJ;=EiNJDD5A*W(mURVldb^-)ndoRVGbgAqS4wW}c^{M^>@HzKlbxd!Dm zYsjzq?Pzp=9sLb$jKK=G#~c~I0~Qo#!`|fBUYDiAfM6}+yv2dR$h1vNmz*FO8h_<1 z-{ynCip2>Pj7TMTtd{DKGdcMw7!L+1-7%Tdn8Bwc+b^!~ZWhT1uyE{Zii`p~MkAcL-)9hp_I+LZ1{iLJbxx$W@u%WnT(pu77u^wNCvS zdjNDpNeNgjiv?*>4Sbg;3>!eguT;fb`j{}g8iF&#`Z}MtY|qn`CqDQ(0R3qDPgF6O zm7M^?G9@s9v`7-|moKC=m~}_QQVTX?PZ;Af-XR9+iK>s9pjw&*qpM8g5*p0HaP729 zDP24!JZ`eL)HzLc(u-ITBY)7V60-@zT)#sr)Ncj@VSDK9SQ3=G1NdsS@HLQk&i?bM zEb=@PN)lr)aE0+vTa9jG<26Pj6(WeY51&)V=l2pM6HiRS$$J@HT$})!lOb%h<7tGm zCnFuW#**4USfsHmJSc`18M1KSNRoAZ!FmzN$ zK=*Pfe_l3IWHcHD!RR#X*m05;MF#XoWzMHNY#tJvPjiu}EY6Z1dGzRfS_od(s(ylC zY`@BN-VLW3gVF zQ0^a`*#l?EimmkYkK+am>zA)187B)9FDKecCeXHVVxE`bBN-JD|A5x4X%kUG?z=>T z`cGjpg_j2;876;zKE=DGaZZno#;!LHVV~;`dFcYG>?8W2aUHbcc?cX>;Da=84sTLr zGJs15^X=;5gWbl{y7BAh#n)?*_`?Kz{VfNE(hz_ypVhYx>E0;ZFSk-pt@j}yj9CjLj=Hil7|zpAFwnfF6uJ=7ZVHP? zW4eyV`ah7qUt%xn8c*#~*D-kPTK}i&mQd7UHsH2=xyJ zasDAR$AVb*>5|l2rL`AxQxf}iw8+kFem0wUjvG)lIQ%%*hhQJ(JVfV=TRhCh9+kT!XH9C-G9CP>;CJr)hw|}({^E68wuu?D|!E? zJTSr2-}J7?P};CD?;Z%ATI=rPcYh@HranU27th`T%gOvKv_XBFpQ!aOn#T$I$GG!Zq zVKMp<0X@0q2WAmg9v6&^e=k55LJ$OJbaio2zTpBs=S;J#+$3#iezesHC4I6+@Jd7|TdS(@bfl;DFk;!wD z6{Qj2S9yD@G5iSDS6A>kV>>nFJE=4RBVmq)n;G|+O;t`(%5*}iC}TKLJtg!hcbQBy zrUmgYEv;q5AUCZ=p>{lB!hicX(LxX3LOim2Zl=o`;k$*$2=CuRXX|bQ5v3LYqW)yK*Hm^>8e?Vl}+fNYf_QwoN8?XYk$&+iI-AHI4GVj z-z>ALeBwrnyJ{&vCRKR|o^e|h2Z0V@JIJX@axNvNu+=If(h&R{D^&%h%cU*XL~gR@ zBK4F{+%f^7);)qK`Swz9L)}FmN4)nnh=r(NCN zHDwb;IinR(EY?PGYSw1oFr8f|^C%LeX1XDi!H-IAR}U{wtB0LYgc_-EyVbpo@3LxZ zvHC{n8x#3_xcRW7tT9}Q)uSkwQhzL8(vsDri;vmyvrR`Xk~p zrgtLZd?DZG>nUWsAQ zROqh;0*V!wB?rU-7r>2%jjeeOQdD~|_<@$K!ozqImh77i{ACb5K#)ZCST0xaRSl+}qgg)KLw50gE})_lgy zS5d(QsQ|s#8cwHc-HzTPz||=J+t$g2fr%^%%?xDl1)Z?F&JDY!@UfQ3L}$s7@45| znjnkV5qrWEd=Av^o+*SWhsnnONp9fzr0l&j!>E1l&8~^>)C>kw5r4;mZQ){m<0P3a z8YO=*JcuA8@F(e6NvB}m5goA`EK596IZWyhN-pKup~+xkO0H*%(5#=%_}Kyhk2pxX z(7va|3y8y4p;NOg^Nn~oz+mU}T=G92HM@2gOMN>Iy_D+wwFiGzHy;3wLxmnY(jzxF z_NKrqY3ca7Qo`I@Z6E1STG}(Q=lq%T!o$p8l>Q)-o_mU!R*BFUKGQKeMz`5G87l#Q zS#R4o5PtWsm=*>i2TFr|b>p~b(cLZ3O@laZaS+hb*d{8GT9S(6cJtqNc<8j^wx|Fb zJm&o7;9Sg$Z7~|9m}E?0q>bWgVAEYq&WO_F@a;JMoi)4#A8$4Wo5^GdeQ#h#i zzexVRuaI|ET>S&y~{DvWs(j$xtth_v~_FvGRsi6+8k-6bwp z8BZDjA084(z^gJbkt1kJRLD%719xU^xTIs-wr$(CJGO1TvD0zKw$-uSv2EM-%lh8ShNh{L&{!0pEzZ-j6q%r>p%9PXz~ zwt|0~*F!rlN}@CUu2V=7I()`YRBxk@iafabvQq>-3jp|0Z7lE*WT(*wAw)W&c!&?! z9!-Y78WELl)yD?{+ju_zLp%6@Rvq&R_5#oQTuOANS`|SvT^!Y595papb7^iYJ6zxF zdSsBYEZ!+TZg*HU5$q28*OWwcqqtK5?qv}9X^YiXc31Y6)8Ra_Mh>^yaGX}mK5UWd ztXCdY84nn8vtOB^FiS~-zpZ|vE)lOvP6%QK-b6Bxwf#m*JSzqOv>a&A~3vD+2Bq)O80a{ z(W^Wh5A%FONG|8*zh)_K5sy?ZFDpe0HZSD;gI8&^?VE3e&CM8eiJ*W~Dpsb_F?8jW zDWhsn{wS1h7cm>^r|~!0jK7%IxgwtPodM(t*?J{DAyC3CoGqP;r#PUClquz}uJ)${ z?pSb2N#mk1^V0G49|O_WO6U4Ld@LGHY zuya8HvWmFONZr@9j>ReM(TN&e6i8(OPeD4#jxlK1*JMuTE41sf5jtN!BToX8LG7tr z_a8@@*zX?=8>!MNK&Wb>=2b@%_7~+~F1O^ll#xY{Oyp)l-Oz5j+X5Ta4!PAO6Ev}B zV-IMY3v&)Q_(!6zm#o2a&g9Fq&EcS*`4{j2%P%oP@W1WoP2w@^Q(Fn;F*f zinx^=Ym&0fx+=m<)yzfY)x{|{qSQM;b2tqlq^aUW6&jQPlpupssJ}uCpm>QHH$K7u zQ*tnhQ(UXO(8N74JWMir{?NVxZ?r78R!-a!vfsi(wo4+URkyDl8_l zs)zeLIA3A>c$K+7hs)5u6nAZE{Kx(3PeqsblfpK5l^~pZ^Y1dpkxU4mTv+T^cV)Z< zCuIoAZo6EJy4mz`Au+>12-c$anM?qn4<{B@qV=!-;sIO59Gt)+0QXc~nmNnj)}b7( zmn&RbRb06 z9qWwZxRJqb10&x(Yd2o+ftO8hVb99~>tF2US=Cp-nYY%)NDEn|vTtjd(*p`XaujkB zv5ys6a_^bV2CfuV)frk_pd9ugTw~G? z{!d#gan<(m=H5T1qt4K2ZTHmdgJs_wntUfEpVA|Vc0=$KCx@~Ri zof=y^pVOg%w&Quz|G3)c83T&m*-gF3!UvI6~(=|LStY%C&%N-w}FYELZ@!DZX zdZ$dVz0&!wi`eW-zhkoynQJ^Oj>OrDuA9L2>MyZXa)yV?`wN6B)^^*|_DgG< z)vrgsj2XsJ!4!=?`=4U|pCkjg&<4^yMnAiqy3X>sVF)7=s0;1qK5yzIng9|Wg=>0$ z%_}{3`h*NZ~@GWt;xRV9_-hLI`u-`g4H6kkaOHv_4=Njo@d7Do4=o^XKaPae^ZpgB)b zyqq+(!1`ymQ32ZW;q0WQ*ifY76j-E4_Pj)dtY1krXi7NKKn}SGwa}66C#I-7^tU&@ zK0`CvmhQU$9%YB5h1Yb;4x|2?rWao!K?{u2%>iK@7Tvj#+d*N1Ex-jn{CsRT@#ny- zTMQ{z!_bNrv+9(@4lKuw76IvVa=Bvz_Q#o`bu*y+T?%OXgl}Ea!H^X+KJN;(%E4^u z3RKbV7gg$Lk`P_x!G~}0_9*3_=Krhf26IAcX4RiOcTAE!y?e?nN**}o0!#=p%+ZSZ z+0DwpkcfwYKmRRV4C{GQ;P7kZ^z#l+&LR+JCSXnMM8cZD6lw_G-AV=Hu zRbKKGyfj*A^B3?kMufCDe$OD%R?c}vC9{K z;|)@ZS{^N;(qv>Ou(S8^TvVD)FVLRP5SlioA+-xVcjw!20JA}ptxrfA0CmN1eJ!$W zKp%i?`^#jN#Y4s)OTP~Roz%mx>*+9mn%xmL*F0U~*YGPGr zFa=_Zxs`P@lq-DA>IhF~I(aC0YR?P=oN@gIsNQ7*wRw8)Qof31?qXq?8}wT?LLzQC zD>x)bG;tPZ>Y3!FibK9UcfaK}2k**<*%%Om{pNKiSgf_~{9``(NnfWxk|9fQmS!B`o(;_iUeuevA8og^VB zsoKez3x#^@5;)M+6L>b5FvnhZN@rd)PW7;h5;(&>cJq zy}wfq8T=uMeVHjyt&GZfz)f&=Q_8r`T0VXCU@<-2M4#UaTz|f%f9ZAIo7l*BS?%#y znq9fDD`5-vyEb9<9f}gU!oC06!v-*FVa~Kph@fJ?n58e)*pGy?j~ItRO&g=yf;cA^ z2u^6>a-nqa9rET_i8H1npf*c;@pcd$FM7+U>;IZz-;Sm`lb-ILfQn=8w;w`R%S`A* zLX`W-2aUG+{qy>jKkpM8SmYraz%3Fc=0M%13cW5oTPXR3fF{Mmv#n4ULI775in(jw z56LxK+Z+v?6Rl-XP=QK0h&?J4?0o|~yJP`(BoLQV=f%?yZ_WuNeC@+JR4Hb_=L&?L zc1$4JjW;?n{5*jW8_5{?t93qt?upwj8g=;4X;uYpM$At2sBwHc)krWU>3bPk67Iuz zjC(Y6gJF_f_=nU8&mi}Z*?e6!a&q4B@zZ$l@tq%6`p?k8JC^e zUTc@4T2R1>Fr5;M-%iwDSEqViySDE7+Ln$FMP*NaL5828QX|R4_jjcrM{#Uxhou#6 z80r1aCB0}3cbpsw9ACwx$iDlI#R08lg-pUEe0%N4AF(CIFJFhig6?l8u!L zF5gbVu_kTzBtL7VVkl%FB)DD8ot=qR+8h&_?32*H~@ z!$hPVtprGYwk_(@yM{Y5ey_PDf?AAn#e;e8n9kn7&d{#?)V9&K-vB|oFI`4WHyZtx^+lMh z;(9Q@fsjsX#F7hhhSDrg-w)Gd!>!d`J`#%QC5>8)htvMP0Y}bzteD8EK%aZx^J`vB zj7cSLB)-@+M>$uq9=!VIlp7CO416VJ$U96F-D=f%tMKf z+&<|KV9LnGiR&N!k~o8Bb)juPcIy~{#T%P&-7c}H!C`E_=TjvM949=qcZ+TGT#P~u zY3g6xoe5@{v}_lCBWr`UePzR6>1#r)P8=$(3Klinwt(3h+86FFz8-7DS<+;8~Szb*l zrLlfF4~C1T38`0{T7yJBr@WDk}cY+Apv})5p^ukkVf=NQ)$b-I&b-mKb5Yk_(ziD_29hbRrV9CQ@b z766p;gmxU~`2}W%I`eb{IcOsbyDY9z)8B7+y6wojhCa~@!-RAMjg;`IW#{$bGmSb& zv%}WnE%Sf^4Vp7LZX5ok&j%r*xIslNk!0JBo0=Z%jKpm%aKjinP5r3{_8j@;!1H*k=W06)FX9yTAkd_TBVziS!FYQEbjbzkV2 zu5X0O`K~jJQNLm2mgEY}t%9f`(Kb$}8*#3gC9GY9KGg484z?@Ugg_p{N{l~DO#%Ej zfz5(cHDQk%&5>5(;N|ZH=q!Z|nwx!vE>LUO*v{C)vlv#}56@n%l9kxhYo*Pk`NcSxgEsx@F&Nrbcr2%YQk%>^zC?dWSU-fo@uj^j zt$|W@M@1n9M5091j3=D*6*#c%E>fXVSv4bLD2z?ri}otw>uTj0vr?HmKLCe@YE>?o z?vlMu+Q*js$lxL?WHjlToFR%9fC+~F1qzuk3N8`@eG3}ws&G2I+p?ofBCc#Dr#Hjr ztx;>;7%HgRzUIjKJLpnihV7)XvHB^WLFCc1gAVvpq9kLU=- z%dAvLQo*A~E$Td$vXBn2a$j#gNd8xj3pIOQRW`8#^ym!DxdS;sN8D%jH^%Co#`kq| zSdB4%1nbrn!xI|dPZ(*R%f4^%2)$|1KO0|9bY^q1ItVb{>0NOl_d)Lsq9>}-iE1B+fq86A zIAO^|{zIm?;U9gfOwDzuJf>5o{`I+XxK=ARaPQnpmda*Qsrdv+&h|FeLPIW>gO7ns z8#alKbX*4IRz+gG1aLns>fxnGa2Ye*Xp+f6T4JWr*v(F3Nd}^%8q-n*j0bNb@RQ>@{D9(s%p*`*_~AI0*1twBO76!V;~h(J*#o;+1&7X}({ zGIwIx-snw5vuh;YY=}V>%EK!{Zi?v}rR}*`;Lj%?OxVuJi-`*9^n{yeM z!0%fmxhykg2iToBO~nD`l^AD=-c<$56hYA==RN?FMZr$WNqjwVEf8$=tQ>e}$*b9& zd(PRs-@-3BRYpe$w4bzVAuKhj-4^ErTT;H%4xV&#tIV{}oQyhFE7Xii7GY|Mx^QOJ zt)zdRm zX&l=xa-mVY)`-d)f2d5(+Q(Zv&zrG=GNA1>5B4&1@A3-hb-VrC2-1J0pHvcdxU@k! z2EdF5EA&{m<r^ zk0yM8{8*$E*MBTh*R`#A8uHB&c93VHvLh6RYh)Dpvz$>hoIfa$Nc>fVVw{g>J<3T7 zO)4nZqPI6)gYA8ntj2q;h+p(^?ZgQS02Lh;O~wa`5^J8nl+_rN$m+~a)E`ho-u~uj zU5I$fV#BaU`=D53hMIaR1S_#Njrb8Az^?#Og+IhD<9bd1fHejQ$|3Dc>GGej=BzT3 z%rX+(9L%sTB(3`OXg+YZkAB~Q9SvYy`fm2ly25~ZdI#~LnGtuW^uysx)k7#O&vX)1 zhOv^aSG1rqGW0cgU?%XAzhM3T2F%1;J}F_sY1x#3Mu05`o;gq@j6tN{)P#|P7l(@F zU|9oCeC?F%@z!Vxquk|AljGZo>-F)2tJYNoVId0irK;izV0MCWgegb_2SQ_Th4szm zMX8#l_!B}^Sh>RN1hs0P8sx)iT6w=y~8@dKv|4^@u`84g~MM1kW>B2#P-se7rN%1E6%$68H z#s*RvY0WNdi58xPs@P)B-Pv|^WiPOKClm50KjAL4q8rHDhPJko%tm>kaps*+Xhy|= z#fQ{V<=I$+oP8OvB%X=g0rrNmN7fga#Mj{xv__N!I0h|7*9S|+{iq8{ruQ#D%qovN z(M~El);-~~PQiS#GFloyXnm|2H#Fvx2P@{QE(%$eXw-IWE!YtsgiYZtfd&{TfIcCt`Kj1 zXnsM4M!_DLXqvu2k=g?l6WpS!p^tLn<@guFfW)*+B+ZMd|Mv7ioIh$zM*PbqfC8Pp zppkRlE4q=g#5-uz1mNXgF*EPn`J0^D(q^YPHvW4(>F=_e`AY23woM3*)3wtMBnDtI zvgvOW4DN3>lkMfg7YV+WFW{6!`TxuSVL$domohP(gzDCkq5zExD?~hZMKtwcHyqio z#F4OSm~TIPUMmr5DCc@U!fQUSkyOnRX68KkkD z)S2nZb-^A@!KNFP>MI=7I|A$v^^Hv$#txfHbT?gEqKJw1p>?7~7<}asqu=N5t!oeo z8MGw5EDf_V7esl)BD^~_tHh0A)uWq3Y#?CGWF4wG|BQFEPB}qLtCCkq5M=+Er=tQlBZ^JAf@{5+w;= z<{zZmdJ6znLd>`-{Ea1+S-Sw&rhN%x^MqF=PoMEBgDr9rVcvqqxCz$$rr7Tx@pf3LQ7PN>PrC(BVR5_kQdi!gIIKpC@ZNQSLY+0K_y2uJQf6WK4l zo9ekgz|f3zP)68*7N`K?S%ET9N&GP=JHr=EIDwcGNzoDB^Lr(AbSg%$&dy%Qsn~bk zoA>Yle~|+k{6mjTeD05{dc&T8Z|3NdG(`t~>DvgJNZYDQZYUq@Q^IyOt zv5W%1=(vBI@xsnFe|PT>#v`4)fq1bxe3&1-zUyA9Ar+-Tl`yku+z-~+70(PNod`gY zjn7j3A?l1W?(u#7Z2nM=U`ZV};1$1}b0uL62TM5&)%{8ar0tw0ZT;bv@qzJ_&=?!^ z17U?|>Jo(Xsu4>tCS$^}UL!B9~X z3TB4Te+8bmh&r)m@iS3ZUelpyzk*|vy5R)ksn~$Z`J19lu^|8NuQ@v0LJiB0q(+Rj zEI(tOX%l;9M}`e)z*yY+_su0e-;wRFm{$!9oWKMr8dLK&RSt?+G)H5Fn3y@OhTu9t zSK{y{OaxDA`+QZwWEj_P;Xfk1?>@XA90Upc?Y@k@^(3cu39p@vQ8(sZ9;`v5e?>nn zeHMQFRz|zegb3knEI6xf3=Q?9MRB<C)xfUzfwdt+0Q z4iodH2^qIB9@h>pXlLX|BKh$P<01le*A6i%YFtcvAR%?d^KYi5TuI49FL-mj6i#1pdh<41I|K=2jt*z-Od1NqX6$P>|8Ci+POa@rB+ha={ zuprYi7!hRuTi*`Px6g)`beE*aq4SbDfLEbTdMW;pNTV)Y&Jgb|-7CW~g=l^pbevRd z-W6&@a*=Oi6U5>Jn_1@9Wr!Ma`ivE41-axbG>-Cqa58kiFp0EtpKP5A4fwPO;PXyo zY{Sw}yKgo@O-V8c0KB4_hHmk<4Hb5T?+4d+y$HV4`mkj6+K zE$YbAv~4wn)J3eQIc5evL|&Gtf*7eOqZwy9wfV6g z%AB<|o8bHjo;Y$%3fQGoV+DZ!5Y9vp_enn6F#PgXL$buKkU&TwudE|e`8JJok(ejx zLi&Kzsh@&hW2Fv?Zv+@R5#CV%ge%K({}Iu0;CWC--WX&K**4tC6xXAFkU08<)Ea8z z57$-PkDA5%IYzp(e1d&M?JHxbZv9tvuSTeX*@?J={Mlr^{OjhT2I2ZX$UN+Rqu3Ko zPq$>gj3InQ#$|nRzwY8t{K1qdV8nwYkhS=lR#f0`3_`GUV?6~2 zj1>0#5rvC2moHKUtt>nf6_~F=`=_Kr_jnGA+uf8`NbG&vse7IV9SSkh*W-HArS{rF zJCR!um zms@}|1(^mw$B8LlBQxBV7bXq-1OFZtL}ckodiN+Iy-ifbvrSF=c@D&pMLXat^nb%J zlkT`j&_cB-Ld_Tc)Uj2P;;g0JUk31NcOS<*UB=qNZY28|fpG!|$zKP9&vdM;&AhCg zTTI+C&*nOsCGtm80`h@#QXk@N+A5x`n*59TxC=e&6Hmzvmo@-q3zJz2j_{3M1FRFF z*`4jSHx^5hQ+fqx)ZV&wUX?T84tBv|KpgA9+du#Rq64DR3!)+sqNh_k(o1z-#mhe& z%0cc?D}RtPgr)(N)!3jt5TcM0ZeCD9Kw?wecyW$H-TB?X+qU#?Qc2pM_g`kWy+?f} z?5OLST-<^wf9!15nUF@d-&IeiocONJjw#9Y3U?ON139qlC?DAja+44 zX|g9uPvJ}3O-~0JSlsFH#}C*CQb@9jJubkhMg^lo8JJan4LBY%wMd`YT$}P7!X^UC zJ5Wiz4$#HWf81ayc`C@@NqLvo-e1o{54j^6)#biXaNn!4PEnW@FXiLrrn_)7!46%Y zTLV2NA?gB9#Px6RRXqbkw}~%a=pU0Bf$o%(HWc|kC9`v$Qmi1{TTa=J(FSrvnl?gC z=U~&VRvK&m+~qiqx3Sl>i8N09K^+~_QZp)nHI9k~3(I0{mq_;upFvyFt^CDMu#L>J zZ^~45Z5bf&gN_vAI5CsfcM_0*)Bx9cm-efDU?m5vGGv1rpU>5eif87BWum#`@daxi zlm#LgsQ`~NF~+ZloK(~k#?j+bo)ma-_?+%RRsA(A152S-t_m5BOfpLy9o@k@o%L@h zo#ZE|S@4|kpZGnC#oXC&&iB58r=R5+WS3d)QbQTE$-C*I0`Md}IqyWv_TfdxGF)ya zxN!iy-g9>@3L<_VRiY^MDpd1XQeG2O&BG%u$)w~u4^D%67?cBDCPSGJ5lMs69oS2PoU;^fpl)jNachA8nlsIbK!(VGs{(>%k`TL=HJOyB8BvD- znk2ah@{!-R7QjvK+a6h9C?GG!cYK5nIl1YA=-Rtp(8EDi53!4U&49~%AyoO`nfssK z42@3Wg?hpM@$T5|Q8bbzwQ^fq__+8qtMkHyj!x70QMQ}8FX`I**Adm_Y2K)mEC9Ph zF@hC8hg5ehq~}qnIEla*Mn1ucut_J+CeisnoOfj69uQkL^G#K<5QV|2a0-T}K9uVL z+(N|jG^mbv8#150O+k!$kidKfzM+ySbuY(sbEB$!hzyy7c zy9jX<$qx(MUv2ya0H&HYP1~@mJ<;Kz?8#PPQBYw}n_5-;iq~fIT!|p;S$LnWk(!aM z+9o1XNZ%B47&!;ZmyI={!+=k7-fpW}TO-=zD>2nT=Pszn?!}u<*26TU9_2R~g)wiD(az$&$TJ28c1lh8cx7~^V zEwXKNFA{(v%QmB={!%4 zJx;Mk7`9zeot3?T>bF4xEOR-{Hb*QMFzc%ubvrUELUa*cGUN{49~@k>qL{SkcE))e zGi@9p<6J2{nBZyFfv-S&&hphRxSp}B!a3au$d2AOI&Vo zz{oo#)h3F?!^D!H?NX*XbaZU@xVI!Or>yWNkL@-Ib1enw{Gec}r5j5dyp2ILT~=T@ z%rQL4JBJbDnaeH@;?uhrohIXc=rA~=!Z2F_>wQ?QlxO+2aD@oQDSKM^br4~V2gw0G zYM+DH`0CI0w!46(+VV-hz9cpuatu-WBL4|m#eci53g%5!crXo7pM9bRe;E4!ZyBnV zbM)!(HfH>7?0~$Yie*-%-X~^}n%Z3-@tngTe%Ny42-ZR6$vF=lE<4D-5Ft^8g~&Q0 z+apck3!5-#Hd6Jhv~eXJwmo*`arO~Ej4S1UGVXBsXB~iuwX8XYO>MW9q(0cIx{_dA zrsdxz4CUJ2kC8)?^p)kKqKBG(2p=nF{xQ*H7AEe66_ukUw^D*!(|fujlXr}a7-}S% z8_r*r4Z0rb-)saXM{5xwuav7Ndhjn;5ziiJ&u=6;n;XA!%Mo!f7oJup2pPWz{QOXs zcY7B5jt>Bg)#`Q*^GrxzTLw;2*%`ec*&#^QryPS}X@lcnsDycCcPK4Q$twv4?I~8@ z*^T!{MZZoVG=8xk-@jh99p`j%kEMFmrp|DYCql@`Vw|VzAFIhD^gGp#NK2?I7{gqv zIR(aswCZ>zOsz?6;fp($unw6OgBteI;R8XoYp7UQ(WL?IlhrP|F-_ae408v zb(3@XS#5Qb%CL5q!5`|m44Aw_9jL_eVicDx;1^=PAFPj*SKIzEgur1vX=SNFZ9cm@!aRXRh+=tLt`(=EG#)>|w96st_#;R{j(vr74IKf9 zHe7|Cj1)+*pbF7tErHRaitGkR*GmW!tx4N1UF!W1 zmyc9T^_mY4@7?>=ftI!eaOnmw>w^cNI|;h~hFBMFGM+WL(hYY)w_VRVZV0Fmg<4o! ztk`sR$yL}^pgI_mf(q_5MiQD0R89ccqt<*{F5j=nt9DJrwX8$A#>(`giuBZ(yKu(W zkgjH_B*rY?2ymBTtW%V@z67z=s;E&T5zrTNaa1&@!t4i1j2`Ju&dF70^FMo1Vgj?v zW5$3|2gm>rjtMvXcFZ>d1QCMbpQ?<}A zbhF@zo6QFK4!2ZH8rAr`1$6){6A3=oAZ!Ny(Th_D^;qn&oCC-Y7ETME&hKj-8+;?- zH=g^`yCitbv33xYS-D>p*tlQj+2JcyXo?5Qk^@@01gq7ye^$}|H`Y02PtLSg1GwO? z2@R3_9K9TTwl+)Y-pfj41~fL380QUF!7*CQI)p_fqyw zN59Nmaw71p(%?_cIt?@R`pCMUjxIA*x}ZgzIw?Adew>J|nK$fcC%Gv}IluV4?v+of zLu7zRAxB2$e-0QDnFC`hg(XjdH$;u0hVA@i7h{NpYW3$PS=Pqz`RMZzNU>xHl?1t) znNz1&^_C0;i|!^Wy(2<{8P0j!{q}=@9;oxH4Xwn!uu3LFShW~w_> zdrY{{K2Bmo{=3Gpz*xkQNmw3B!MIq}I`VrS5n<;t-dFHp9Z^>X8MNGzk>~>rA5pPz zclG$h)Dwb{(M=fD5wtY0u#wBXc(MJ$YCEUt3)GTNvW~&^kMbR!Z^|!H3_MgvA(9z2 z25!S7Dl~wW;i1Co6k3bjZpOOqcy`kh9D@Y!gJkOB^XGgeN6=r(7AJN=r>=zyo?Ax0 z7pTk98{jF0g56nVB(U8<$6vkQXiGM+ZQFpFm|AI(vZa+DiG5!3U3m}5AsCG6rXbfM zAwj>HOezhUY&jcb6m4AOgxBhCB;0^NBMHA0T2%DaiN0gI`~!knvd%@!27!O@7@Ny=TEv!vDUT28W+~rl)-M2 zH;G!F6(J(brd=^kX+KShv}IvNrykV@#f7x_wF@| zj#~GSgsMC-PeS>R}d4g#SPMxGRQKg zCGKw7}z$z#at40knZcWL)G;79=1`QTQnEyESXutG|>P#s0Z2!zj$1>b~wJ z8YS1HHM(rt|A^^Pi1Ci=DM0Xst&dkQn9tPf2o*g?m~6)Y>WTR^OA;6HWsEjPV^aAq z8o9(5|Er^)q`NZI{$n_niq6YA{8HO8%BdK3`3%B^L}Zyqp;%pqGT-oK9(dn8nHeCw zSwQzDXgpKs*9)cgAEOJ2E!45#9qe+MT@I?GVR$=_6CUvmsRV5Mg)ved4f($MfPUt7 zPHv|H11{kPSuW+N0i{;22T*oTv3xOXx1h6x$Moee5#E2h93%Nq)JVGyOyfI7YJPI6 z_EXJxla(+r!eKjMJ1;;Y%GAA|UqXP;0SD=&*Hz$;f!k@mbzvzcGa;3r%+pI-=3i3+ z^aQ!}H;ZLRvBu)XqkVmdYIIK>GLw)d&{DCQE_xEQQz7IFWql0p0b zalo__zR8@L?q&K3)1!)N8OTpC_v=N3fAofke);#AyZ+^vW|C1#J*uVb8x&Rjf@Sku zJz7%*Ya7?QE@;ZmvXvgh?<)ZSx@#a>f>1=>a;-%Bcq{Dbb|0&y<6YPy7UjceJ6;he z2###!O=nP6^rpat8uAI+*`SBi&HFy3nrFH!%N=0kJW0;yDUpIs<_eh%VRnd8I{o% z)zS}kVyF>LHYW6HA$cz|JAhpYY7-L@zJIV9~QN#g|xg%|E|Q8 zoXXDlV{VX$d5ny@^+wO|MCB^oIBct3Zx`~TrezIjUr~{^%B88wEqpkN$G_|e-R{;= zaTkIYCGNBAZNATiwKW-{F>wkUKBl{lYB%?MZp@YEH55k!6#4)HI&SMeoi;P;t39J^ zeY+G4S+4X)JE^27CmYT`m<&dnB+$0EpnBOC@!bj*T<3ljsJ>A zWc|L~)+&uFBWxj5kktpFT4(q!jPA3+&huO&hN|D z(kZktBqFh-;Xh=j9?hVUi3P_|oXHkHhkBu|;smeLEC*ew8_0Nai5 zfk;G)3jZLL94Fq`dyM1>4XL%tO`8&f zB#+4Yy?(b;hOls4qnK*_EYN@MfAAV8F!ss{j&xk>BtoLpuJo;QX*Q{d1?i?_q`J6~ ztG7A)VABT=3pFQbdeT|@aOpD)EN^0a;5gV!vaf?R4O*-?i_BFT2~NqF2~XL^)uwdZ zs1|m!dhO~E>}-jLJ)r2gBJ|&p+D?|?&ao00kd!bp_m#`oR7>6JC4GR2^k$uD-eB%o z@hResGKVm$Cc0r(mK6xJPzaymLN$7+b84vR{XimuBcwKC91w%skq$f-SnTXeuiI?$N z^IrotfM9Fm1NbJ}gMk5|(bl#2mw_htx*BUu#|mBA#U5ca2f?p7N0lwlIv6{mt)gXg z!r}grK$LMDNGxf`p!5 zMw2yCK?9S%AvJUyEvy0a_FFXw&9>4hP)9a+T8CP(WW3YsQlkYun9uu(F!2K|<3x(% zLim8|KT*^qb5xF6hI!AXCC~a{m?#6(fxT5eT>}eHdq33n$=}-3Ei=y)28eOs4F8AUA)Yne$ECzTcAQYCe-m2GXK3-^^EK2E5JDW;|nskRU{MY*&V+L_r$>R)7 zv%&H0Ibch^fsB+)grZDh`XHmxH!~GGW5=C|LTnCAUIM#cw`|(6+51PsK&67skT`J! z8_eYAl|!RZM0M|kUnYAAJD^DelSQJ6d=}l7ZtLR4!az3OmM9b}yy?yh-nOa{;A~N8 z!cYzr%ci1|YYJ1l z=eo%kSjv#l=7-N;UI0p^C{4_d(&MB7?eLEE$|r9XegEo))Gs&V|Fu3VL%W!uD;C=% zGi}uP^uc>QDq4%FJ7D|#1nOe%pr6C}!g?NzM6j6ghrg!2)9oatrM^!H=sb3S6Q|El z2H;`+&qKuu%o+f?{_o{+LX@{yUM-JO+;*HwHt(2y32ub(SjD4Wk06K$NE-?`98|Y{ zda-5aJXXAC#&pj21E77eazR(wRlnY!;0v0qDsS^6iue&2{tyy*cfvyX>8?twR*Nq3 z%|PL0^BKew4z<+&#E_LjuYW!NwjH|V0noqaiyBWJXFf|9l&UL(3lEnOWrPk}D_jP!K-nZZHDAYPgQN4Kg5%{T(Je) z;j*zb|7Fh9t!1uz9hLDEFk`s+ZXJt*quJdgn;3#P3E-F=l(}>o)ouL#p=WSk0QV=J z5gk?~+qhv9s6BkLnBXG1R&l^TI5yJsK=gdY6K>$(wLlK(TP>+6U!*oq!@X02N?DTZTN1H_FNw6(sQVFI$EuK?f-@4Q;div$U8v`zU$uF^^Eq{jlK*-yU<9;bdolKtA$%*t$C*%07cIe1eu;qP_h3+uaL^ZB6mbqieu1?*$aaCSbhCQOW4TO;-*jqfqT06XqFmWQ zWnAI9G(=y_fWj&}3{(MspULUe?GVsDxvaQG*X$hCo;0>BFT1S#l+ zeCqM`H1$KWtVG2m%n&l}I%};NRjIrXgSG~`2_i)|haL27{zV|ofl=%<`6uy=-?vrn zvb~`BQ;Ze_Kcl(%LwIW}bGUlcP?Y&p4b84+n@1NTzZ3UxFq|9UmAMsb-*2E9cMO>2R25P2@~2GcfIuT5!bU1-n=2-Ko1Y9|lU6dZjB*Ia{{{la{&d7d?7zWRql51mgb zR>*{srbcz)-yQo+S!Hvj)kpTFqwRA&QA~4e0M;skA6)1jC7%8(f16b}5l^QK?QH9N z%-Z=^&T^Ui9LrjKarkF(eAC(xZ=k=Ax!1sm-~K<<2$0lpWNe)|G76m;A>fL|N(-zJt< z0FLXV!&0M9d=x}FImpvT{iXf?!_+ypSJH4{wqx72opd_3ot)UV?LM(>8y(xWZL4G3 zoyqfln3?}jRoAY)?|ZF-Fn!Li%va!ytRYUcJCW+U)oSrA)T3uF{{C6<_=CHi_hZw_ z`rx#SMAjoWbPryJszJ7NzJN&xHve?#2~u>7f()1t{LuA1jT7=FqwuZOxqzqwq1TC{ z(7a^|!RRz%x~wZoPshRP`cU96V5*?r_IuZ%?MVQOc72qvs*0nUz6(5h4U;*XG4B&P zm{tH4p8zN@hd=2|D-C|k{WeSS!XUjX03RdlmMvxq$S zsBkMmpOMOHR33ppL*FsVayk$s$Bld!?VjI4&rK4~4Rif(ReN6`B9s$5kYcjB+rRA~ z*R_A!hqgL7{|kZF9d{oX1dw*Q zOnuqusU7!jV>YkUnmZt|#w8rR5M!?!yjD2c2p$? z-3F4lT=v9qiUaN{?WRfU8XUN*yTByJ1pguv5|3txzt!kIQp!NFCfFR%Ue`6d4T5!t zR5YpOIF@1wk41)`K}fD3sctiop2GC|G>AoSJsZ6RfGN-FH0~GnW4`8d^-IwKuX8-5%i&IW z*50=5h8!Fn>#ieYZueB%e6+-vHWW?-XN;BW#4=gK9XePlA+WR@Qab6v5^Pi;e?I3cS^L{ZbvpxEsh7dR}n(;yg^b+zM2#S@?M?*|o5Zd2&BmlsAh6y667DGH{0rFm#XQrEQXb_Y-|!jqBd{JD8evjxhSxZ!i$@cBY4hj{oY38g{ zSkdXdSPc(jYh$t=wE0osz)>{#4kl3L)QJKElq5~�TkWb6tK?jO?b;F=PFuJa5`J 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

  • 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

    x>)RY$l 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 delta 545287 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

      WY`4?^D2l^>=$dL;f>h)NE!s4ml zwbHsF$vI9tBcSxX`>5Ok*WhTfDl-U3+V?X_dHK8eSYD_lB5Prjz85|OQ z64c&5;poD^-k5z`Yoi0aBC;4#cIo@jN*UfCQ)q_U#i}U_@U=fHl8qWj?JzAw{D2U$ zz~hxG?_@P5-he1lX@^8}pRXF+GD;#LzWzKK4ZGMX(irH;Pu?hO&u14LF-``KU*nPb zhYJL{XMv35IB-dD`aSvsXIWm5L?EN_{k|Bk1xh)7)^}uha*rtFQ&;Zoia~S4PZct& zh8><<1q_-_>e$NcV-Rz1!WcuhUx3>_LcL?Al8^URrhR#9J@P3sPxK%2*Lc|X_g1b0 z;amC^;T0*#D%Vxe#p8%x3p)D;QI*`or~;i~%%SEk)LUVh<=p+5--ZxV@h9LMoGre; zgQs|kg@fCuT!bCQ?gAV+;}AIIS0!7I;xW-P-f>X02Lt7^;TbAv3+o7JrvMJlO$bqK zAMF!=jvlV4Wg3!~p)uLIm*6!9k%STZ+oxrL6%|pMmO{d4sSRPEDmdpB;R!FXg#0aY zYh?&EF{yM=SBM1m+J3bGz5jhVf&WC@^#`CCV%G|05`M)(uA)T`a)vSigys5CY9GB3 z6(+O%>mE5ZN##6FbdC-xLX#I?$m9UjNG-d=DU|P5eIg^e{W-mi*qkAooo_~dk34|6 zoy+6H2`Ai04#QA~9k`T$=JN(OyoeHj=*w|sn_Fg}VrnVpKb}1l{Y8==#VC4xcQjAR zXP{R19B`>OjT)AR+XXP_KuR}*Q9IWv!3r8Ht6AMG2yUll$=w*YGrgELlJ5Np9`G1E zHdcsh;UxJNJVV~AZ0Mqv(In=g5ESE&y`vWNR?eM&DcwBv$GAda(exJp%KE_PNM9t- zOL+$!-xs#-!wUCR%O6|CJu-2vcc)iy+znQ3n8)B2yWhC+G zv9s1XXc^`LvoXhurlQRd$)6GrMIP1%b7QpoBkyxJ2iEH92AfDcWT7g*@Z_Zww1`EL zwSTkmG9mD~9|$lYjDSZj%^0oVjj}JLofeDwSICL>`~cRUkfHqWj_q6AoAthla-q+k zTyGpXA`1+#H@RQtbthn*#aU;W4-Eeht^5uR$fgP{l?kCNv99;`a1gG$O^%nLBjfO3e~>zo7*3(NN%V9CJC`FncS zm-g)ht&`~D_gA%jq>;SLg>6}?@gy!TeoDpvv3DnwkHW5s~2Bv~WbKgTXhc})| z(g{#lhuJ!$g`dE&$6J$pOHpGoyC414==Uq$_w!;{+pkP^i9x-oN5$qc#rHTQP1QHD z-Y0pVFT*|Ad<s?jw6nfNZaz;QEc zH;hU#!5+iH3CV7TH!nfO@5a#Ya66A%AQup6JV}L>5IxH8X#*Gh8|sQaMLPEJp9%tT zm-g)!>)FD_f>~h+f)-ELgNU!yePOXd#XQ}K8XPo%OYUJ3*dNj;ty6$6FZ`36$+O0b zybN#d7{bTZ6`e*4{>*3t5iIKh`?9*}*!@_PPruTo`#TWm%)hP43T7y`btbO2B(MNx zQhON_SKFrW;15)3L*mz;rHIf1(V^q>zm04tF3cnt=ua@RV6iQrtQHCOU}!B`Iwa{& zY;D(8KGla>;le(Ykx)Fn>9MA~j{k%sY8`nZp^XXQo_GLkEM<_X8^+j={1VC%a=H7< z*ueFU))kBGY!q&WGdUgx_gXssg*ADx~ZaM8E_NS!>CX_qT7r6 zxc=XwGrOzRteOyw5YiH|7wImkVBMgIa_X(NQkS9cl5lIKhZzJj~2@k(^^B9i~4#Y=0H7 zeIzbAxqaLljYiVz=JuS^6_)}Go+Fm4O)VME@N*V-;cz<~1b0lZS`bgu9yb;yX2z6h zCW1Xs;11(pF*nLmSJ%H`p;w^Edd1-Nt@F-o#dO|?0ri;Ip+FZc5u5HP3+0npU=n=z zs;s(HmLiA?@AX!%syqTvqID4QqZJxmWs$#XFGdv@cfve&nTf+s+4ulUm}nGT`-K@% zj)y=8MH}NO`5T@6xSM05-eXwPMUv!<%%Y!zff)Gub!?0!znWH-!M85hT!Gs*WkMEr zoZd*z=t_SnKLxL3$#|QWx5Ri!{DI$FF~1lvCR7tItB6~J6S}x!d){Y7n>k~D-k%5U zwza>!1Yyx8+L5E}66?|GUWe}9NkO*mZ(unNM+JJi1>@HdaI@G+@Y}@vVWzWTnV3GJ zUPPy-IcuqhYrjo+wf=H5M=yLYjekTK-H-e2|B`ZY_fciL(h@m2(gH=FuZdW+^8P(Ui{@CHy_sc?f2MWx6w+Z{(3y4+Dqc? z^9Z?P!>PN5pj3U?xTSu2NQ$l=V>x2S&*2i6b(nVq;GDeY_|{5vj10AFD_&S<*G*y3 zQitMz=ify~aWy#vPQ$kxP}Am!p4ym)Nh>F6FRywCZ=c%4kR-hH0`$Y1xw3d?5`FWy z=u2m6L%X|our^F-5<`& z!M)W6ER>y{dt$JWrX@-e&xk#?-ehK*NC23(ZJ?zA%6kV^5=8P4!Db5T2Mj&}(k{N< z{4AeYnOz)v1tO^QY8|Au$aWzCrWa6A(A^j!Q7Me)sj!&(r=fo~s23F|fE0tv0)PUN z0`?0DN3>woDW~;>U!I5dZ+cJG(g&{vQLF#?!N7pw=+qUp&mhR`m%ZP_V%?7tTB~JA zr7=8sL$(7{*B;w3lPQS#1KRdm;z558Cw%e)m|nQH7Tg-Bp-4K^O7wKBZ=Za_q&=PT z-nIJ(o8iYh8gG8IKddx-?IWZ|D+tB5GW3Mz6 zPS>KeKL!%DMPuQ_Gny`_uc*EDkh5gSEB-<{Y2I5#{L=K{Qmmf7~P z1zKB;>Mh8 z(~5~!)bIYWl7?xH#x**VA$u_EXl@L$m7k0wKo<1HiJn^MqE{jNW86XluR3OuSEc3r zmlV8n_=QZ^NRfeDzz3$yH{d2=++^RviDqedwN601Up z89#D7FpiIjsWeg&lE6mKAcmO+SchC}$Lqp9ZG~>DZaV<>lCRMRmtm9%vSk1Z;6suO zT!T6gjCXUPdVaZ*xy~-w6Q$p-YV#m6Lt0^9BHNj)iz#z_o5Q+G?(XfWe?Fl0Sj+sb zxd6DX+2HJJ7}}F`i3FaMJ|zdpEa$DlqOg37FuVup&I5yeE@%wn-iBoYFzotr4lDD) z+YE~Np12hjSjR);eNX4@hXS`@fNU#~3euvHq*1CaMV$?v(pUGTW~I3m#d)rn{0u5B zVV8kxK4XTpQazCbH|p#xzi2i~D1Xa+(-mEPluXL=JrwF=fSo@=U-I9z?@{lRorCcFLKRH4B(i`yfah2d=FlJxhF-A zzvX#o{$0dfQg6FA8nBD!QtRP0#Cu>wqLGJ ztQg*{z)3n#r{PB4r+$WtHE`S9)px3mLD+5I0_%!j$klVYxz5-~a@FTM#Q16r1LPnE zLofgxx|_fw2|C~U8~;TZnMN)zO05(n9V44E(^15oYYL^^M%$D;+FXjuOae%bdG4Qh;!`;zKi+_RY!^+JqT(P2-yNp%XI0HSfKYQHp1}2J)^3+Zd zM1_bm)1Fa(h|Xgj>-r3qvPFXicbNK;X(S6sKJW&WPe}6rt&=f`5r5>%Hrc=ZV#wG#JW+ex}rRP;&e~Y_r zHi@Pcs%|_VXujv7($#ze_atujLham2-zRhbT(sDIKKr_V((6X!2hPanj{Xg`w z&!f8efCs^hnMo2Y-35!F=T85iP(BG!YfA)uJNZhRk zGR4H*Emx=8I*@MG71}+NQSCKbu_5F-`A?i{G2T5iRF>+Yhsj2Fg5!s<)LHdCc6-5v zxofbBD&GgAbMw#1ve6NBjju9r$I#EfhIu~&oFtIc*{xB)F8giGy`&89l2e_tY?2T` zGgLm6*ZR1H{Uf~SYGh<_M{(l}C!tYOvAheEQkH{&NhovJi;qIL@(|bbf;sA+sx35wN0xN$o48HqUXh5*o zMT%lqcWw3_cI(jH+9FVGr7@=1o+NL}n*R6cZM~cZ!+dEg@*^qoBdNY#_M1M-YE)rJ zP)-?XDz;*~9?^?e#d(&saEoXUD+E5_?$_;AN7(~G*FW&>b+tiT$W;a!3$Gxdh}?es z-4jG<)3xg0JgNM3KxBXSZfJ1rL7ZQYz^QO<-*aZ<=l25q2uB z1xAJI4dj2XNw;+lC-gs{H5@RDAo`r6B+x-9)e8U#fxAbM#uAA1whs#+)XFfD1!xD1 z;XUS}`>w+aP%Goh5-j5=7NDW4rbaDm*luYc=3w=JT0|h@xf6eIe7iwTnBQU*it4Jx}RgS>KOg?*($2PS5k`UkQKo-svPkQN97!cp!~BB-e1tyfB=6-|JNKsA3kXXTI5 zkGU+xQW(>fM-~>!eGxbsYaI%rnnp-l%RrKcmBP?#j47pTx*z6ncoFv7&osm zt`9;7nuVoW>#Of*$9HB!8O`TfG+*fJftN3hH6yx9k3sP*Q+)CQw?>KxTn4=g+b(WG>~m-`BdKn(7Lso# zWhxFKXgX^od|##TMQXX(25acY9|Od>oVT-%Z4fEc^Df<9dV`A=l9NqA^ns|Kl54Zq z@&PvR{|~h3V`3RW#|9P5Zxw=QR~txf;*^urQy+sKce8sjeHdbbrZZ~N8_l)F+D>q7 z&Fp`oi3r^N?Zhx1PvH`4+{H)YN&n84_X4oz6Ug-DcTA)dj@TW#!p`zYtqn_|@$FaW z>62#6jdu;T5x~WzOK-me)%15%6ulgOfxg`XuG!?1!Omw#)BFQ>$b&nS9q81%AUOhE zTtpJ?{U^jj7_K+_JjWByiiuh0K%aki#G`-Cflt0k?hLPi<4}V-u(}Ef<3Qp8bAbkB3cLwMnu^C58;8 zT(G(ng*dl}=U=k>Bq6XtyoDtKKQKML{GwbO8QQ+#mu*?021-cB5jb?D6g4FPG6sLo zMFU&8ad&&0fLriY9S5FReLNzzt)P6#4ep{&UjcP1IWB;JuNW1BwYrhd{vEv|BKQgr zN|vZ;#d(QqE*{MGdf|l(jyX_PAXrufqo);kr4%o~sY0YEDcRSGumT$c{*apQl0!`( z1`NSHCHM?vdN_A6B$ouppAJv`WQcz)WUv{EvhYVGc@1Vpx~1IdXWPBvy6m%8C_Pd} zSBlgCdyr8FW-747)TU11&oP7*^Q7}Bf%?C0mo9y1r%Y14~#b7RFJ6+RS|zP*(eAf zH1FbNG9)@i06{0c+ZROrOnYhe^IW~mcZ&$%E8$UndtYH~lSegLt(4Z(k@ebqm&Hss z4u0%X7cfa(dNn5Vr|WhE`8s-cml^EBNjAq{-5S>4hZjxWFv7kadVDaFLwM8?o)Hi1 zdN^T&U;4&qc*6U?Zn5X+1ij8{Ic_)JtaU#?YjAkTAqfLVxu zH#ZLJdmtkC)d`lBxz#q%NmsT~|1HX%{$JsmzKiwir3vw-V~M3EseO0&27~k?+unZ015M`qbYEWevpjACzWxX2(nM94R;cqDD?O=)rhkLURd# zBcB6K=*GR4pIg3*MIW58W_-!3>ik z#BaW@X%yA^XJY>-Pd;O*X45HxDg1V0K@{}Zi;CEA21F^c-Ia&JYjE2TFPGqUa1D8Q z-P=|(WJQF7qNJ39Z^3R)>(ka~hrpgjv46x+I70|Y;}e$DtJ`PJ3fQ!w@Y(gc@D1C- zU@sVm0um%W_2pMd-f7$vc1+QKavnq}><;3@R7_vZ1Bg{&LEqqvWifYb4NlWE*5d(= zy+W@2K8)s#aL1ZqrKCRRMp6<(qI8Ci1}0{>oQ;z8oih%5`$A!At)qP7>-rHDHLVih z;9V9Eo%Ur?6V5&; zws_vualWTRz@4FWkj*>#vH!x$y`2N0d+#NyZmvE01eH_4Zlf>|z4H}wh#H7eMZIR1 zuvOKS_Ess!CW@xS6syL6rnXU=M)~*JV6c<0(ynie-;Cdz_xPFBWgSI(k~5SfR$9_r z@ARQ2D!og7L=ne|s2XzuznS>hJPD;=C0W0-%{nhhg_{S#O&3zG4Z2a+xF?i~$j#$t zEs0W8@UCFci`guK8T_)(!9z*%H$QA$qA8|;QsUuAhUO($j{J3h4wl&xvf)$gC@+bm zdI>K=u#*|RhziP)fh4#WoE^ZZRO<4n=oo=Hb@Re#?#9E!KWUf-_eH~VZK|-_N!9Jjzh|H^Cm(RR z?>I?rS6s*n8T}%Ealp{nY$u&MnXM`I7-MRbSdBX~*`r1WT%7L@b-1QNit65)7`Ik- zjft_5u%hkrS|rhpj(sbKLz+Kso=@zoA+b9gn^N1lL)9tzFOK+)q zd~cA&mIh3OHcd$vt8vQCh0f75buF%NbJO3uvFkQ8jrre7+~|Md;+y`HR2YqbT2S@` zgTRF<`s!bU;$9p}%2-AQZ9b1iNt=&xDbGW}o-hTFuC9g7&*5z{0-*iAg!pKLz+SjV zZ~GmbqHnjskqAKwe~nbjZrd;ryz48rfDlW8ji6U2w%Y^EIlIG~Re36-=s+_@Bu$i-d8YUJTvE08oL)x}Ck0g{$tZkh z;%R#;lzxzO^T@WF>_iJZ;4b?Zr9JHq)O$2`+z}Te_dWia0y@R8SsN2==0`8 z%;y4#l;r$k51fN7gg;Cn6Raw@ngbVnMvGFPXDnCx#^;w)sCfQZ8N$5~YzhU{Cvj-$ zrOXQ=&vn`qbI3EI4SwYzucnr(=$LcDKvHrLoSngFp_H#JdWpcSvbtw^R+AuZHZm8o zd3Pzh%*9F~e@QV?FT{8uL|=uwA1j_|BNgoTnc#*|WjgV|7F1VYWt#SrPQm7kLE4G{ zu~*FKeI!f`_i)$#>2!qH>uIn-bUy#~``3CsvO6k1+?ATF? z;;R)u!4_CzYUYr#qvN%glT=rdgRR_V+Xma^hu^X9CiZ8tn|1(=9}t88eOT=ZMET!7 zs5Xl$dH;u=_w?D!s!Aq4GnwK&jMAO{+uJ6%H9~h*-1mmWiC4Q3x%l6&D{yH8#K>d^ zt5q;He{OO*{p@=wSL?@$u*7N&vCtcpn`9p7x_}1YxY1z;QNeAwA9@6AMt@b6{Y?PTozEN7SB#jEN}w)(3OmDfyX#-If4?? z70A*BFclI~7YX2TwgxIRK$X1stjK4UhbbgL6-S61Db}?9SwMe1ey||e1xiM$k2DS~ z=Lp%-!Gea?Y}+}FkQxc-2Ya9uf=(}2NIDYsi=luD#qM6vp*+Wd|5Ag8ZTj(>QlIVjY8MGaJln>? zS*eM!f)a&CNP}tD>|CIHXyaHQ3A&!Yx3p6=*}KrBxCwvKth!JSmO^PAy;7}f1gtG; z2njXx1)(DCD0J@1ux+RJdo-R89|nV)eoeB6YKI%|m@HqZvCFsFuskBuT?PpfE{f7{ zDBB6zEZZuoDdcLCLdM6*YBlQ_Ved4B1Vb@Yx4qU(@u9F@-8oKkB(2+Q)^)yyqNPbr zchsfv0!e>(kyV2G3CZr*5{AJ%h+gP4oS0dO=wQu9ki&I&ogJ!oh(v099@AMWkA__p zBad$4Nw64T`efh)g2l78O=kVO4sBXxWZb69)eg>4YKKRLi|zzJo*#)bwC$V8{CeDT zroG9urX{YmRYP^-uXLy!cYsXiW-;4iwlS+~3_O3jtd7Gu+?wr`LXU5vXQE!x03}zK zK{wqG3XBhKFCRJEfPH>lNieQg^bOZ)KF}x1HWZ-Dl51t4e*-mR{aD-Q_(e5E#c7wF zK;mjL)1#dCf-zF^-0^8!C0m>KG)g$Kj|I%zTNU;l3-!~&l~risTuX#IzSMpxbioJJ z`aBYL%QJ7@%zNYZLy;9xlwd5F#)h$)$987d1)95?i`yuY zEJstY7~!)}tLcj}cA;_nCZ?V7gzig&@I|SG!0C%tR?W+F`Y0`G$;9-38I55Jq_FE| zGlC}go7ADDN&_K)R0+b88*Y_0R}|yIUc(uP6KGs;Lur`!BvW9_Qyy2Do+&VyfRbWO zu`%)``a1(E1)DMJgB&z`BeFI_FqYYX&=t%WG>r?$(PkCC<1=G|Gx8ol8w8>q}mRoNNDE zlygChVx+`$b^davRLbG59x_Kl=k<-o0hg85QR zYqma9Yt(-pzV>H>VXsdGJ{}erTUB^?LgO^F&>RzIK*y8eOWiD#fhpo{&n}D3HLlET3@uvfsX$$ez7pO(ku;M~M!f7ik z*@N2})43BVX6>^;IM*hSk#qN}f6~4=AJX>CT)NGZi+0$U`+JzwO~sW%ciW=ByL)kL z*umy$DPzl(-1U2ZtCIe3@LeVZVXiXrB|2LZFJKjyFzl_;VYhbMBX6-B)ciZf7T)>H zO*@Fme@ja#&C#EOK6+db5f>mJ2M2WP#L@ejhO{}&e%rRq2u5_!$ zIQT9-TnoC2Y%I$yAD>A%zKE?;Ykmf4cOzQWR_$-pF^xBW;(DnX+cPJLA80)16&6T? z`7iK^l&#mVRX?SFp3&+F{imurdGNTZzoOrTRZVZ&KoGtASInVO4GM|UW4>BM(l%1_ zA)q}WMH_nz+bp}z?m7fD{qLQfwSkz>_yT5U-prf#W;yv>&dMaoF;l`~>b#Yizw^ry z-RWWHI7zgBn4>F2hVWIH#pKpFKeae|RFnQ_Oy`wD_-4#h;pEmDZ|M3|Do+wbLkPAPxk`D+^(n)V9JzdOXHUr`Y7De8FGg>VnGfH6=&O3YS+8l(>C7oan z-as}JdWzs@7&;B`2Z>w}xTbEJHj_UI(8DCd(}i=RKl-LOBq*tJiyBP9cv)rX%`>I_ zI_H2t%j#aqj9S#r!}-ni_-;Jx|GF5CF75{3FMpg5FRtMf4r!#ViX(4I#wJ`zOg87T z3x70!zPWAi`#%Wx(>Cr9ePy*{=%P|IzQ;jX_&E|>>qlSZZ%$@Vde^5 z(@g{4Uq{TvvW}wP0t0#hqc<>*xkNKn3k#_fuMIwc)5WPBh0ZpHi}WkY#j#T;HwKmIXt~E+cQ{(ll^UyTef1kwSaFAf-Esg@J{C z6=fMN4O5~OK?v7r8=@3e%)#9Mrh5QBFu-^{Cel%7xS>cI3|i|EZC|@hwnXl*;aA5m$VzGNjCz z9Lx7$4m7~pPWj3(o%ivn7f9cB$X-h}{!Z+}8U+RY+q{n*IUbQAqV}(JUr0Zz&5Y50 zZ*AskC8MC}rt*9LRf)P?&-o>c@i_UL`~$a{=nJe?e~nbZj@mF3yyq+4fkQx0#I?ID ztyb!(l~CbUDrB4&aO>Eq{md4j{r5gQSvG){Z7ztHneog#EBCW{S7%v)QVWN z=}@DePWpFQW<-U)782o$woj|M^|W=k_@h^!7fXI0{Pml;vt&1+jF8n_IFH}a2Td)! z3`UZ&e+HxtCJx7gK?Vb0+Fljtd2R^*5-3wzSBZozf>UM-tO%7YRHT)9l}e#=+f5cnj%}>ar&(T ze-|%b@6US8G`_MyQr-X~$f1YG)29ICH+VoBmJU z^8Uw$mSD$|n^v($e7i>vC-_|gv<@ysQ=llw@ovf`;7uvzm$v?jd(=^HW37H)5T?^9 zOm50H*D*@YnwI`A^^f$q$S=oz7{TNxf6QiJ_+Gtt@XH?K>75b zj~OYJ7|s4jKA+64=<^M!J~?}eP+r7Y`uQWo1Y!OC&`bUiXGM0uSul>DFS9vnK*kwQ z5!ob#RARA7BPIhtjN$WLp5^qx4{zS=fH#05z!ioMh-m{B83u~)uNNR^tU!SgBKwq> z(JNX4iWTB$n9e~2lY{__mN6+1e@1ig5R56ruP5@#g}95uER3Y4QxR9AU_8Az&C~NrJdxyHpHJo=HqboYi|R(B}0R7b_5D zX@Q;!&Un2kI5&eYXYiJ)od~=(iTkGXt!B;q@VLqn1pe3{OjS%HvS;SOXK(mUF()Bz4*#Y!JqXPc^0I>+w&)NO&)WRc%Vo!4%KTuxcAs9d^ ziBOl#3K)F>V{mgz<7(2yX#ob&24gDxl;+ur68$J?c>LMN63DgMW4WF#cja#^@03T6 zjwHxdhy{qpM{1@c?kIF@e>!lG8(+pC-6V-aexGFt7*G>)=_l&9F<8KapiWlE6l-XN z%3-C{=02fWs|VBF9nB;vV-poagZZDPyTJbb{$M4OX~fxxIJ1uyAVa5rFUN}!Q}$sg z1)~)hYMuZRpuUU@-d^g112zmM%sGe*M;xnvanbA(FG?^?CYs1Jf8(+RFirH~Y%6X` zA-6ZT)F#F9umb#Rr4jihSD4r21_G_RW$(6 ztTg*}wmNB8NX#%av_=QuA&cj3@(KL{W6PoP6&i=6T4fvpd$5}d9-6L|*35Lxq{MWL zA@3+~e0*cL;NXB4e}P+Yd`#8lslE;P-66p3W|JT&#(1u1%zb4$c0i;0*@hBvpn z;KyCt>!U+Emw6s5N#n6Kh7Jy9S06s!T}@A}&!)4J3tvKGRBUj1=%i;05vLz6uatq5;07(TMEel2}t{HJR5q;vI}$4WBOLWXXHwE7(Jx3QT2 zgOwbkJfSOXW*%cN^ih^G-wQ@QDMqwP9?nD(k}G5@TZpv9(?qEU=kKvFut^DTi`^wO0-&enW&oy+YF4;6UC zFsG|^H7n}npYW5taQ3eA^wf!j>~~BwV@>!vPOOROtjRgK)27%+IO{SN*5N>yFcvf- z^AX#ii2NS~lU(o=>k`i6Ff`VEGTxwpM*)4 zY}V-%E&3C2PSbZn_uKtRI5~UDd-TySbXV7}gnwpn+OGs!->x90fAl9}mf_-;=l=L# zJ?CfwNsksxGMFF|p?*U_ZFmIXAR)cJvr*x+I0`UZ+zw8zGqXJNl;CW50vq z3jIpuO*jojpiqK*{_s;tzT%FBX>4}*ypIYy~&+Gz@Ve*-b!vE=ZSM6~Z-(;Dxz15WCi?@Pwp&aHDypqnqXR$k ze|0;;O`-e6T<7t`!YP zaP@8vyD7>MHFtgr}OObB{*HfWP=EEH~Bh77g_WrPM3yGHm}DO!bm)2IqDizKCQe; z<>_j|>)xh%U!59Y$3$md9<1PlHo~LkTjQ}`Pm4ioMNRY;O_O*X7atZ2I$wAcy(pjh z^)%tF)il6Ow47v{G^iwhSfir=e|J-nW4CEY>y0X$u731UKr;oZ)r(Qd{jS(jSLY^9 zBi_81wOX_H0ldai`YmSSu$j}KnYfXexPh72XC`iGCf;r)I{_OmGWubl#+2X|`R0_x zl8Jb2P@rmI^&h*7^_%YC3vhQ5Hz2`DT+mEWB2EI2O+oTqpLpbViUY6De*{Uzmpt1t z!l31up(~0y z(P!MuT2nf91y+`hNwe*1%wRZO4y^{hqwP07@HhJSN$^yPJMaxiaNr9XbKsY#1_R%L zzsA6~MZWUDcbwCCAL8(FfA&TG5LL=ZB~lH_h@V;ag!b}lQAPy*lfCYD4BNWyuQF*} zNh&N_l@eFsZ@ZMt^(nL9;WM|C7?5Bo5j18gDNzkdi35L)QeumIMa{&4QU-Ih1?P#MmF{76yD8hNGF}9&2;*80~1nFivJqcN`N}4#i3tO zsw_3#Lgg`ZK*T{i|KYnzlUWi6Q;Vo`ZhX5gs1-|f0M6&N64%;m8rofP7MwTz+sr$fDeAjMG-tFCyf{Sx^ zc-i*dgNka*(vehF;tdJS#le|K1!sZaa^3f9lj36gwZ zIXfelk!B{S+c(u2Y+Iwbs>n2~2=1l`_A27@@4dW?5xAk@dRdcq%WDPq=e4O<5)-?~ zh)#p64=3xU3xkRVa)H)iMIw2DKZc91hWP?{65vUAA;lY<1bpBn^l z>mFuNo{O+Fe>zo9Li-j4?66;v&}Or!UoeXSqOCa86E3~-~+6!MZ-;O3ZXvL+9QLsCeSf7RD|lTA=-lMQeqlL^0f=e>$o z*}e(V@Xm!lmz_HKO(c!%*m?FVC8Yh1MPr+9-P8rAx~os#jhhB`8+jHFy_n|zfhjot z?#rt>;VV486^jA|RW*oYVj92H=cWT~9W)!?EO6pBk^hEKC0LTUW0(Ybdu@d3{!#E+ zQf0xee-YhO(|9rICgOiz1Qm?S%S$!4nyLo~N>t4W0!<{d$M~f_dmLzox4wVW#x<{+`(KrL+k}PZZi7nA-^Nc{=5Pnxejc|O zG%6cU>*`KV-%)d&poqIgNus;9FHE?Kl^bTme>(G@z~$`1DA)MUxImaS;P}6OI|73R zV=f5;{}IHm&#~epdDNU!=Ffw7%W94&mq*kE3-!O*To!HqgG_^eW8_aRdj+9<{nyTa z0i9V}Q{zS!e)q39Q{^p7Glm&<^JE6H#+V8j1{2#m*%VMNS#E)+aG^SAJa}}MZ!2>#N&cRp;(BQl<<=y|G3jhf(_wm5E8hE>9@NZ z%EbdCvp?dy;cR|4XF@!_O>nIFFM3WIs1bG(6t>A0ABAS4(b`(l} zLZRCrUm_j}%J|()z=F+`tVcACNr;b{e`&_gAxWi*NbnFPO55UDGYN9$Wc5o%*h>q5 zQ9+m4S}8PKpz*xL^a^tPoVKXh09<^ElGPsQGfLw<8RyVBrotX@bZxdt(8qgVFEIfg z+5+bwucA#PCfodPqh;dk0n4*tKPV?t!n1gvpxvC!uzZq-J)kop6LBUs`|zDneG1<%%T2)Tkm`XGtgn1tHB6 zV^;Bur|1}gF7Ld5`?dpbVVI_IL^%9TUN{lpg&E_N9V`PZCm+(H{y?W zI36u;Thag!&kftPA6;ViI?DLOQ z2AWHjf%G8y6OkS{d^qewv^I<$0}fiHeon3Y*ZmJZ`=Jj+goi%zc;8uLcw)fu!nuiA z*e1COha3MWiib_!Fku;HT4+9=B7Q86@ z_d+luB4Y{MT0LbjP;Ti%*$&L3`(s7-+HBZHy645C%dbcUT`9Z|e+@HM86iKQO6a>k zHNl@r7RMFkFs`2Bqw+jRLV|g2Y3f^8`Qs(z8(70n6Z`(bsq~DFq=)}Wk1#PsUr*52 z+Dy+k@v3-6s&!nvcr7v5GT^^Y0khnsjh5+UTks~g_uw?*bDCa}ClY&pRry`=BrDa# zysmhR_`#`81^HJFe>v{M$q8m%m92QhegN7rwe`X4)%z90;*YQi%Q}lmfIWgH1hkNz z->TXhqZO9mgkha_Q$%de?VeRY|Y+aJY_mmwXrh6 zG;;;rnjBRgyHmpqN3TXEe|jUW;!_Z3m?}y%c>ls7xsg)^JAU|Ra>jn!>o;<9joFH6 zwysX%`)(9o-Qs@#9)dLn60Cgk`@ks#dK$t*^h6TCc@mW4NzQVm2aaMv>7FT~U+B^I zIe1n{cCFK;f9Qn&Fl9=kO!u(I)L?Kvxt=fP)8Uu#bT(d$e!9FmpN_AcCaxAA`SVtf z`N{NrJcYC0Oa|4$_E!d7!dU+)e-`y>0 zDO0V5e?8MhXXz;4n9F)x%A><4_pP%7bn_)u$x{X@10IY9#sa@OR$Q{S9^S=8R~~ju zH1cz8Eg}Y{{3by(_3Se+X2j0G{=EFi@joF}ayvPOcZD$^WkB zmO2&sku%U#8~GxqsncCd4~r#%zoSG{Mvv$QM^MD&B*#do@O5Ld7DbEdTL%_BhH&nw z8v^Lklwbo_r$b3ubwFzFC`>}+R~B|s6d2tp&6u-C~PkXwSV8pyU*q6yhCj ze>A;DNx9bMKEz?C5xP6!PUDrHsDZX=RU$MiEyz4}R0^!(*SBR3qoAl=d57j%_i0%1 zvfMGrn(wKtgMr2y}d=e5q= zoU!@vuOA8Y3p;jfRNkx9cMI(7kv!G+ej=N?e!VYtlH)obM=w3jtua|?Dn@Ew>h}(g`p`S+RhU-R z?Z2UC)TU=qlIqxH!?$crz0)4_D0%XyF0X<%p3{&Y<|=jLObuYe793SFpb{55xI zJgLU3_QPDm&HiAJ$}2w4=B>5~e|fp5j(PHP{g5ZvmJJ|>SSx_yQb+7OLkU(}0PtBA zrtLN-C&Ao|wKFNqeQJc3KDI+zpp@JT#oRMO+&i)yxGg~(km6Wt)s-D9&lQJqpOh(g zUU?T>+`vIsT`e^yjXGzk_j}#m<+>?~gHu6=T-fH?-j4LQfW|TAJ3+@ce+Hqva;XwU zYwB!w>KoN!y;J{rw>@+~+=G+Tf{AnF(wE0A5lM<2N;5MennIB5^nBx8)b5-5hUH3s zaa}nN6kljN7Kr?-af2?tD)&l8jd+Zh`RJ85>1p{bfakX)qUNbi>=j#goTRKf?1rP^ z5?f})6-KC;CB;2~b(QvA(|*N-rdxd`<4Vlj;3b60YV#f3B!h2+mY9?30Mu zoJB-4!Fz&h`m8T@f`=lePJqg0RR1}mso}c6B@4zaZSkyG3184jfA*+oLZgEOsG1VFpod^5mUN<5hk-E^RFd7%uyyh=V@XUUR$D5m zQm))2wu3eyw{r80M}`F=k#SVrI{)yY1s@u?O}{sVugGV9Y5^pU;b!n@Fg+h# zUr+i|NQ)9aLs28$P1a)%ep z6Xd7Xr429zYe~|S#=tlb!=$oDcZSYVt};n6I#ObKP{E3D%_7w{z&tjndp!CC!P(iF zkj%s)apd?Qe}wJ?W@UtChTKH}p0^%uknFrQw}O(ASny8hTjs2{>JYH;0{Y7@l@a zWL!=H{AD5{^%yfb!c00h19KJmWO-zaSr^5@_Y#AR2){fL>4nKTZED5$;N8~W(+*Qp zk>1cJf0_hg-T1fk*UFJQKR`Bn<)t4{d;)lJ(f66J{FGGROqD?Yj8n&b*lx( zd9|;ZUW!bY?VL&xXAw3y7yL9f!)e91nH3QlZStUw!?#Rk%Abil?8`%til7 zO1pE4M!h)!PK{*KAW<)Vzf0TgtI=>en~u9*f6Ppp^?n`PT#fs~YUStcS(JWVlV1`F z|6-*-2^QDN+a6(UQte%yf%m=Lwu5Lkx}D;job^VZhf~kvntadP5Zic1IHxqlft^v~ zUh&wDkJCn$wNiT4kagJ1LA8nXI5p`k>x5Hy2L{Fw}DqUZFm%-KF`n3 zf#5chhx1rL9%}`EbFt=N@748^a_|0^e;LQCNC{xt?LfG!n0*CYIlZ#7spcB92`?`@ z&>i^UZ9nrt+tBF^j_1Zju0vgc~nCc^uV(v?wqcmtrE~4ID zUV^Wn-NxHsbUPc4hJAC*?8M-F>W{m2M13A!^{)rR{?&d@-Wcr-o;7qU7CWbMf4HZ( z3xKWglGUZ4+F9o1Y1>%ldxglJx;8Q2%o}TPT;CdxD}=K0GLkb_-%u(ls(5E`zUKy| zBX3AJ%bmGefCvAf0njXT^?4$zkSi%*1`67HT2u3mh_9c0xG(iDfcGR z2e~{Jn#;oqFK&KRPW+fR@>D-7s?_RTV$%6T6mTmCwMthT_{R`!Cm~Mw65Pl+9Dr(K8m@4Nm;^9`jF+xkLl zpL@=^_r}-Z!%2Fddft+RF&4y^O3+ZL^>3E)h&!@lq(jc9*}73J)lGev%?aVPkSFNqBxq8)WDxZ;Z}GVqTi zx`;`#2lC=)8e__)D(O(KpfADZYA*-c@E)-1vnf=Ut@eOUNlZdzjd~GfI7WitC1>## zL8GKZE|&Y;&>sC)x3AVGiESdp9> z`V`R>>V@X-z`z3Z_~extrGlQ8h#6>~YlB4k!3bd?@YdiTcQS&gOfWPnavY6JPV=$B zR0Vd-iOy*2^TiK{LOm@sKrPReF|5CU{E0=^4A2Pq?{d^|LgfulKa(|y{U9j8N?utO z$K&0GGgwe*FNi`tF$)QgP?3MxYx&%MPu){FoNNS6zf*PZ8sZzFpjsu@vt5}&cuo{? zXX1?W*c@pFebfgTYNDTxT0weC3rEL@kqvUeelTtzh7(B?>}xLHGL8%Pwh)#?%TyTj zULJ1fbIvkDoy)*S<#6+&!U4M`{t|zz_|8u)`l?p5 zS)W>>K02Nl#JtPZsaW|r#edNUJKt)p$bbEfZh)5K$cJr(1hx&qw4)ucUvEb({3@@W zW7liXw#UW%tM=4KNHLmpI*ID&2Ptk!XS8&8`juoJG9tFmRc!~bb=w*6t$}f?s=}NR9xk3U93;QN z@!`r4+$!24|01EA(0%>i30BRf+I2XujccGjhrU`RKbNe41(8|YxW&t3tw0#I@+2)w zwGH?pG#~R%-fy=kXAB|>e^za8<2DTb?q9(H1?m*n7W>-ny0uvY9MCqmINM=pgFlAK(y>wh05*^ZPtFUyC(mL5KQNRgC(`E~v}Pm(d_1yh)6qj+wf&1#PN^Us~j zBoSKhKdP2k!prY6S&mvuzNY?e-oZF!=>m-Veq@T z+zNh>WAp~7+EHJb(m4L3M77!iP}0bka^m=|pEJX@F-5?FGkpNAD~oa_1~@qY+bc!h zWkqoS)W&@P%mqI{T^3t%7^818I#Mw`06Jh|idp%hvB3NgZW1wMYKn(oGe?@48G)1Y zlamBapeY^=+3nqJe|HFPbfg?LaA72L`+q*Hmk0-QHs!(<(HYrWif@X|HJDcfskq%N zoWY71E^1Q8lb&>-H|XC(dUkf!f$I#Ob6E=Wtjm`-%XA6@oXG`w>JNUu9l*`skP2x) zAdYeD+&crxWhchpeYyWKJn#2<+3gV0CBl*k14bGW<4i36e>|Bubqd*7ied%SZ(2jw z?$^Z*d^Rs|hQeqFn;`i&0s76$mxAY@4P_vQ2^E&j1PDTQEg9;xa{){#wsLrHWq%4y zsRTR*rE_uN1bl+^!Bk75OK10KZ!yEh% zWl?O1;}b|7e-Gg(Hj$&8K%le}VC^pzxP)K=c;imz^vY(&r!S>9n-OIOlvuG>qV7zWWTMeDz|DiN43^X^-?({oe?=Fu)`zY5f>O9X?VQThpu_j7 zH9O2~o!J82ILRYs2Q7RCdqRHdrlD-NZS5+EeQXENS)#di1b#6LiZWfz--@T1#}QeB za%4S@#aO40YagR_&RzN2$Xt8c0gjCRrIkY4QP0A(@sG}>x#t)@2RQQCH(r&D+0MwRVC_k~_# z8nG^%W~;3+LbKhi@Uh#%k)Y|HnqndOc(W<&*6CGVAXCoTcVDP|6H)Q+>CJdX{4X)K zGNdweYtX%&K92Tyiswd)r?y$Zg}|N7-T=Iwe}*;ntYHB#`(akk75f}d4ZGqi$UeCW zJq~X7H?J>Y(fQ z*iXIc=>MW&RNWq1?}BzGJ7Wn!K8!}odNbmcr9qX2XBJdU$Q=M3v*)_w+R!A59FKOH zAoY}-)&0?u`_X35^r5mR;tKJh+5^vR6KZW)H|cxwAGa=b49Eq4QXw}Pf>mRu_IR@t z@!xA3$OaY;^(mQ;cit!Cyepbj!&rr-5*E25D@$6?ra?D(n~xdOVvVj5CBnTj?fk(w zsx8j`sQH7i4s9s$?sf8uN4xpprK-@*@19F+NE$u=q@RS6)q6)>EC?*6778qi%4oHL zV8uCjw6d!>JW5&xg|*X%|X=OK%CI4U1c}4LxfMH1iRS+l?j=*RHcjU@? zFuNCfgEB0hFs?gdM8Gtl1LJv-o^Ma;cz%v}uJiw_ULO%Yn+hMpPr$R&sS(rb-`ceL z8cy5Yl8ADDYASK`uF)%oe)ARo7Rg(ESn>q}hy2ycrj1<(^uHJx`x6g5JGNv00G*OQ zYr`-Q#dm#*3m9TS0?kyY>vTv{3S9ynx&(|OUt&>NRwcP<8uHyM|A}LV4y7LN-uu1N zo$nuXrU^-rOJ*>%&Is-jchG3#8I1^0EJv#uM|hHd#eTgitlJrU{gCSwGZu}PlonxI zD(*y~Kzc$R4Qmxu7xubZZhXW0w?Z)q23cAtc>q6&wXn#LzdxeyiAvpsks|^B>2f0l zzmSrI7s|6r?!sD7i;VbW4q^GF4O-hVAi%52r1nrap2)9wU8(BTs2v1pHxs>srdYd< zU9v%cR~iL@%Y>cIuhXV;RhXPf@r_|CsrU0{nAT{*etu1n0{U^7TH9uDmc{_pWtlQ^_`~Y>5J#WG=e-MUu|B4$T1c(ZCr44kT-6|n< zMMB2D5KG23wxbe7`R{cMNt&j3IqB|s-}^{jHzqfPaAcBNoH}m>^9NrVbm{Z#g%Cy0 z=nQ2DA5wqsciQ=r#jlIp@2GWX1Cj|vC0L|fD_KHtat>mZzh9XwIBqd8!V9fPMIgN8 zd>$jrf8otgOV1#M^RLueT2^>97M%<93Yvk`X#v`xrC!@MQ?DUGiDy*a-JO;(n&K!0 zgRD@j=?8}c(<*2R=BGEXhi+DoP{u;PPxQIwi@#8usc$x_Z(5fyG#89|93e-oB_td( z3|>e12#6=5QkL6D;(eAGR5kf`H@p;7x~W5%e?g*sj&`<+UXiZ4E*5=Z74-WzFY&o> zPwU^iLz<>{qhVnnoJ?A6dy|1~_*F)l?n(numwlk>Z#R(j=?A*eNeA*#wQ~u7eiLd^ zlOL^D+iv1W5Pjz>dL%S9QL>YnM;ORv5@t10HpvF|B83P!b`h*?Y)`u#!bbf2R$tt1 zf8T&e;R(9ydg@eF^YtuQCY??IKJ^&5DQBV2=X{euI{e%lbUKl@f;91bAm3@cp54YN ze_}BCNoThnOM#(CmNs0nn8%OVVs<{6&Mx8z4SQk42ZstzF@ghxujAklF&XL|q#13A z;ExR0=35rh0N8B&;zPp2IGX*4o;?}{f9EMTXFA_S7Wv{Q@#8E{%bZa}aaB1J$R=@G zKjksTB5_=Vkw*ywFNh<$Ay|<#CFq!D0bBy!hC)Zd-g)g1{3O{U4gJF2eC|v5GM~Fr zKnk(&+2eqw5(a5%Y>+NgPL8EckGyU>jph>}B}o!Jk#1mO>h*~<5Y(cTW?oGwe_esh z3IZ}zAi1`YLC4623*u_T++63FIOBgVuKv6nJ3aDYI3%Y%%W}nfE=nBoi#Z<{>22Yv zE0YpBUA_#{lTj6vlaZ8|aKvy05qF)7yYcySOs41GuEq%Y0t+|?mH9l1*^0QfSN!Vq zoL=F)>zjVCz2b?_i&k-UU?(Hyf34k~jSd5zv4}*lZiC$|;o|u|CiFY-WgPS^&bd}3 zC!;6e=awM4JT6%QD$`HhlNBpX~xB0~mWn>62<~>rOT?zQo+_@Dk z34}-KMu|XBSN?$_fxflXb*b_m(A{I2pk66!yl6V9AJ`U!RJ9XQzT&By3<L&e!nncwG2xpFuy3H^bILyQ69Ni3Sxg? zqZ*4Mvn={Iiq}y~28$SlfBj`C4jJ-P&}&RZO^BD`(8R)42T!@9L08hEh@EVaaG~`< zCrmzmtnn1hh=uH`vKRZY-@mxIo=orNa@I|L++0`V5+6M*ETe;x%(e-PH&Ll%&fz&+ zPPrjV#VFrIG0DfZ1<3*#A7CGoVnsM@P5SBRNZlNfUv*{U4J~%ObXjfoe0Cx`?jHt?q$}54PIM8mVO@S8*j?ja z;)P5y&z6#gt`LT1_9>l~M%zPzre+hKTH36_u2KkU6ytEgOixB?%&GnU<&8n@VWy#5 zD4bO|Xf9P2&39%rf5Hn=0iS4Jh_oe0YLF))sRj$X;V=xje-Iq0X*&gn9Wor{YZQ-S z`V5+t#RIPi+IX=@f&T{FJ*}>G=^^ik2KzVqYPZ?XRkII`gEk*XdBz8A+v1_n+IVNG zk*lq@UIGKr8sXDb_D`y1WC zKsgrj6-2_6z$)RJwkFem=!c{sN_%VQ*Srv}J+c*$?&sWSt07-@IrcVpFn-(4g_1FDp`tfniuPv zt3v68#PPTM=88#$l0+)Cy?HX8+)N}BYF@|{N_8_K$ahTXF{FJ7e=cU#+#0_qGJJ-Z#k)pT<@y=Y*K9r3t7l1~nlQP*=g5vR$5cNPc#Qgz(#JF} z#BOn$y}v4+XDDw*_bHY}_U267v7BcoN;hkD?dFw8%`2ouC2AjB;%o$rz3y zx{nC+aoO=dr>AG1j4+T+1Orf*&xgYn=rM@#=zR2UGQGMU)gW#GHtjmc;jr`^x0}^0 z=V_aT>C|G&D%G(S2oW~<4u{JBbqoU6TLN*?vmgolXuuBjlB@n3=S8jOT#KnUjl@sq zf7;6zFPzc~xS)okLVrhK0j4(ZhY!#Z;?1Vt*my2*o1jY8efO z5*L)(IbZa^%%9;<7@ivg*9 z{CjjgGK1L+@UqHts!xshj<7UNsE5qilMLYGuHc#N0S{Z}=B32G{R1Q&5n12F>uBpJ zYR#@W?az>g6lP?Eh`%UENcwK|n2tLA88cJ~f(8^?K0sLzW1q=Qlatscf9BA1p1DZp_9O{NX4Nv zpF?af6|vJx;Q06$j>03(JccA|*l|G_4!K)A<(Ow5SYBZqStOd`QE+!NuM`BDmH?t< zj%Gp^0!UC zJ|I(ObLzw$Rr5rx`KY(G8@Op3C4sj?h$?X_inZ7!zg^M~M0fJW-%b3pCzaaXc+a_V zNostvP?KhJA4OXA-@=m?&aflQ)IP2_jeSIs{z`9~s{!|vX>R=6e?$m0e+v(y#+Hf2 z7j%!?1Zf;@d~kJT`L>%@^4A?)ahe=ragE<9P8SSYf;b{U<6P_MZuk7SB=M)G;Mn(a zGY-|aoaSIK(Kp6ncN%wRp;hi0t?%yP$Is^Y?poe?+|)+hN0K$ut3RW5&0jj~`<>lz z@;>2T=iKU?gTZXve>@>V9-H&9L)>jCI>cyx(4{5b{LtDjZs_GadA+NFtf$Vn8%(=^ z%#H&!9e=lHT&fet;;eFKfz5gCzn^#i_44A);alDoPOVe z1`Y@Iy2*3@dhj)KZ{5tfH3#URY8xG(vSmhiA#yA6*0sm2AG@m7hrz2qj*gE0cudmW z1U`G0zU;an1v;MOKM(!|hv|t7hv|t8hv|t9hv|tAhv|tBx9N!yW0-%zZo)7Oz2_@3 z35gVe(5_?cHci`cVgqriRGHvHq>z*(g(1YhuL*^AgZYvud47I=_Ty8rDhOF1mtc@t zX9Rbd+ZSl#`)EXnf;HL#IMR2icj;JLw=_7}$n@>o8Q@METfs_u4S1PM(+|Bsn@(Xa zar7@}Camy0=@+Oa&cJ`XYAMlE-_99>vAFmw(d_Hed8xP)T2U|t_E|2Z!#erT*BXkO z?^}>1`c878KvILS&`R!U<%_j6G+@br&?<^@E(LE0vW#n0IahMW0w92l*n&ga(n>oU zfAj+;qK6|1w_&e$%IeW)gRV5Sq{mP+ssDyIOM{dwdN|<&;BbEt(BWqjX-pOF=#{yw zn(qbeR>BUFAaIaWgWY1Kn>8eU7tY|e%Gx;AHokGe$Hn(*yTEz%iggU;5si}|EcAJL z>bGPMk|nycXv?Cg|BJRo<~%{5J6#8f-&z*YyEvxZZj%?)9UsY&`~a0y(MrQG6n*bk zN^&+Pm$@tZ;7iXvH&u=ta6%_;Ne?~ZRuPD!pik5}k z9rkBlf5_NI7Ik%XQr&?-{(|2&YgWm2Vz5ARn#r1vjbFW_GF#D`l08zCiP8C=i^pg| zsdGlb!`o4rlWNJhxPaZ(bX4d~AtcLD-MC4=F-dbO>8rYI)|GhJx^uQIs{C>BxF~Mn zl*Xqem0)6#`R3unf2+EZ?1S`X&f)u- zqRg2ehkdJfPg)((4i0PWJcj4r)EOhWt?U&9J&in^T_ z8(vg$3CosP^#l+_2=c3_t2UQNvEGyn3tdbIe1=7vsB!OSuORi1TUmN!tVHx|pdKcl z)C~I2B7z<06}K7%=kBOv#LFo%ExK&%2_7SsR<~rjsUa+klOs|!W$8)X)OFd4T-L8E z$#vVJBsz{n0#ur6iX64 zan{ckqSpvlxv{#9v zFC}ylX{wx_NcOsRh3PkqG%ogh!(maZ1iw&=3oz-PP9xa+J8eZ4~ zvY$9UY=7TR+Q%vSH(T@$y_b`oU{`=TIXsw%%r5ug3@yYt+b{qxz^5oq6)GsfE-yHf z4X+4fG3%*vkl{xo(<1l}kRl1eZkrI@ZlTR!!w3z2F=lG(IVRa{fZMec5$Nd zf8X5=p{k84qPFc)jQ4S1xKD3dEv@;Q$~66{&J?mFAqA!_?VEF2mM3On(~ZW5U3noS z+5qV`^5jS-l8=RO+QK<#VR)jQz9$T#JvYFN$U``w$%CB})4xJQ z6M!H#qQeGeKkwcTVcZW%SR&-7$)1+jSPku%L8$)H`$;$#9kiG&+oe`V@x zuy5Z=zgs5D8V)#HL84fsp~6;{pDK{_AdYT8R%2f1rvCQD`Q^#w$=NB%8SwG~(H+{s zc2$60MSSe;G09+=giU6~(?YAbsdF#U6`!KO;s>r+6O56G^*Q#kzw^wd@Qvo+&dL_l zW92rdTgB6ZHKJs}ns@KLjl9i_e-5SaPQ9Ck)O9M~y*Fj&zRpHn02Io?xocgsh0z&E z!TX_IrswH|w5`rIJ(Uh%!DtAT2HWDkIqI~{7MW&5p#?(m0N7Bi>=p%N6+&5g04Pl% z()8l;?Cn_8GzEE-_e#Cy5ElH&*I#!oEshMu`24-XzwY-^FhnDbX;Jvze*iKN6T zABIa;MHq4a2PW`%7Vszr@OakeB*Yl=!_UL)&ruX)fW!Gw7O33(_tdy$!`{1_2U`CX zQ`*Cl{x60!#*W6Bk?+&ze>0-{A*zJy@?m%(Q5U?9F6YJl1<6ezk`)jW0GgW}@UR&G%M5RV8lY_nY(_NZ za7O;B>TRXz+jhk&g=_lQhBtz=#N6L0PH1;zcZ~1g)k)pOl6q+de=uI&Eursm+iKLQ zw7)#xU4-wN(?cllFW7f8V=n%VkB^9RA(*E1@(bXl_fFrtSkT)*`^EzqX<@d6_IszY zs*4^TWlEfXk)>%oC#WL2 zCf-H2H#>U6Ju|7xe;eq@=8k*|WSZPCyo1k?qcfBy_&-P_@%B~<=J2L}Z=xdXywzGG z&%ortTX$r5tXziq-G9W`Jc;hV2G-6ok-q%_ufBv0V)%M&xP1%RPky^MT;bE5(BAix ze*nc<-EZ4A5P$by!4~c+b+WTzZ%X5|E7~DLmJ~^_Jv4>Ef5>#KRi+G)isyCt-*?9k ziJ~Yc?J(32wnQH9i+8^}(l3uUtIcS%U|B&c771D9nVierhKZveiXBq^E37J8_iZZXFy#Ghwcrn7CEOyE_a9BnYVvsY$NlMU!U+h zAXvPvZtFGUf3lhAEszz>WLXW3U;j*HwxTx$dn73ngY)n5$8bTa3r4}h+d-NWzGRiS z1ZitJNOYPD$ri|NSf$^XqzfwPo3g0aTs*AZ1>5F)@i>26=C`m*!_$&VP%+PZ_3+_M z$tC+sdNUXBdqKDG^E)l-o?S5R4+VXs2elU&&zKo#f8M{4{O39^7R>jvgR^Oo3ZH|haa3Lw! zdcMTrGg?*U*0TSFaaK_kFY0|+^9(bRgPo2YT`wUd>4$W1RjGL$EJHjosf&uRt@X<)$)bTV9x zf`xZfGU5dm8Ruq14IpS0Ac$aB(A{GB}6Z2Bb$tuPS$i;JD^F%g?jP$);C3-wb41B zXC*{^RcA8NE(i(7T!Ni|@1!9LD}>V6mIPBgiuLN4d~UepOAyAatn&{6i1&f#y5!Bm-*l5YvcZAs6)8R8PtBn zh##C$+(lC=S_aNw)Z6>SQmLGESc$T(GKOq=b<%RtB-;M{j1$*)aiXh$D-8jw@hW1s ztyQe*qCsCyXId>St2LErs;YDne_CxS)4n;UYI$VFG3{u4*ya|ZqVVj7N%dc)Axjdi@Y@l2ZWLWu{j~U)CCiOVZ$o9OUX8utFo3?G%uoT5XRw$7Q4T}?OZiXNNu@wRfSyuY+bb4ngQG7cBqvLniT`qe``;wiY%O6 z*A*M0Nyh`Y#SVB-WM?ohT$t;t+?#Utx?={Y5qaHR1iiw;ywW^O!Le-2cXrfceQu%~dv-%XQc2^*ZP zAW$sKP+>F64;2V{AV)JGf2uJqbX|Y{`r_*3>g4>4EEx3XIYK+sg6%2?zN+`J(qodr zG6_N^#?oA~xG5K2psSXOLL=WZ#j0SGOsvhZ7yYeeHiU0<8}6)Z5It6AS9Ggd^uISW`<`Ve+2LQdYOW!1Jc$x zTk%vlfChsuR2*!5`~IlqHkoC*9SSWFstEvrYGu19K&ueS(gQ&0{vk~-ug>2Oc}@2p zkFs8|*A0XPfAZaTtx2;Z(_ehKtnl0Y-u?^GNMl+QzCVD7&=1hUs8dbm_b>fE&@O@S z#)nR862?}2l<|oCe>0gsJ#fZqoun!EHlRAlu=Uis_{RPBp6M&9ztuhrmoAGi;(mip z;PG9+qdI`cw|q`O47Gjud7$-kxCGn3{`_DIsBHZ2O>xr)d#5%JvHq_%X-|vvt=glZ z)@Zmb@@@L^cIdtjDdD7ixHsB=5Z=&AsxIYnKOnil_C-L1e?LZq@L=fp*g3gJ4=Ac5 z81=*3qrKW~)Ge>W%Q>>+*_>qMnyEV!g;07A`qz83z(C%q?(Wc{m%8ACRXYOiCpG`X z%Pmg;nG6?b;yAkl1i@8S=%2Na*cRc!wRbh>o7of>wH3{qXRwRuZ8>@f*Zl?iE@I4W z-|_Jgac%+Af3#eF1*UY4@SS@EEd~nqPU59-&_J6v`>j)<)OrsKMoOGN$I{g7Rs;}- zN~Bts{aF_(`CUO>U6jPWEFo%Bz>o_I9@ud^h>;t17); z-7=V&f7$B~V5>`|QmIrbm8#Tlx2Ct#Cr?InIL<2CubV0#HkZwOO6!eRt8bn>DY6Nz zr`eE_599L7`OfLy`SvKAHnckb`^n(}gP7Hn{Fn`YqobW-HhF`;gRtj+ugl_OcuObQ z`Oe*tPMf?e&fn$LaK;)xrq{Hh#gM8;3#0m2f7G+-w5%FB`kBtZl+|caT>9%iZL(3; zWQi3O^~ba>$De8C)YC-n7N4_mKH9EsW)oU8F$#5s<5|(= zKqo)sV_MJahEC3pvgX!!atcC$e}jeRd*w|&%*N;Mvxc5Bf)gP-p?*5u-`g2eU{)G% ze>W5iTsPESUMIA;pG~`g4sqnNaW~{iQ_Y6WtV&=^8j}I)f6F2P^5ZNYbwhnxU^G6p z4aPy%_a}SjBc;UkY227&iWL!!uvb8oJ(!XQ6Eq%N5`TaH||)XXq+i>3@ib1k&wuq^6^ zfMs`i`qS~@FPH4g&hhc#F?-H*e@-?g%t)?l!i}eQWx>omrbnOr`w3wmhUzn$astct z!NK9__USG|@$=3psUe?m6M8A8IRH=^~h%29ZFWMh-~mgoBV`<;__$Gb;>WuR*| zc{8TbI;Xp*dpiTOo$G8iZd%&-u>EoG)Tlx4vdNSgfzc{EpSJgp_I6Ipe>!ZfiNha! z+&5sSS;M#%@Ac94>FLg~+2aXQ_>-0f_ID3<_pLT2*D}JPlih#pT>8ywBpvM=NIXhdZ}(_%)7-Z8_i}IN;BTit*cOhl8xZ`z2D%Y`$p4_+;6JQm@Skb1UKsz!gOiU(M~BC!JMSa&w;Mw%=y>YhI>j;eCX)JjgRhqHo$wZsSe_JYGN{bOQS2(xB z&yMN8W_d+N=EIfIoNfQ}A=})Binoj5ZCP1;;Iz#Tz-iD64`4;JQCW=V#M?5Hl}c@% zd6n4}vn#c_zP!ZIfyJ@E)l!{}6s+E>h~(djyp`rQuh%vWC|zS~ixl*WPg8&O4c7n0 zDSG+ccO2b!MCgB#f8mND76sD3ZJKGl{_-WPLu=fqd{I_6t7KFTal_A6%BEzsU|AKl zUI?5L^$*jm$|l@Oe#=+60YSTE^DAu1zw$D&@~fIcgfDp`)y#lY*%wZlYPqafyG+h* z2~xnRBWyQ7MawUPY;Q`SwU6Y8rjZP@{nd5R7nkQ(SxrAye>r1zuP25TKKV82o8+^} z&}5A7rLk`TYDyKHDAIu62ux)l zUfCa3+b-QrHFru-ie8c*CfQB7mfsX*MM=hNi+P>b>o~@1%*J33fM&0z*&D;sF=-gE zMrU+D{^!-}e?iEYarpC%46|llB`g-E7+aeiU}=Dl$aN*@6~}%&zvH9BGiOw zQG$q&(sj}!FIdxSn>V!Cr*)m((EjQmh?1=)pYw87uQPZb!tLY}>nDugQ)!v@6;Hj< zOYCyEcas@gNBHpIbSp@C^(!4VJ&!g$6d+u#T5oyZTLvnr@L3`}C4 zBl@Z=8$GS^Vw@LLvt&TbuVOk3$l1lJGnZZOLBE%c$A@g$;4OHpb=sZK>V|GZjXpkM zi!=N)dG*b1@TuP->`YXH zd#ivhR>>Ce3duSXK|=ypv{R@CGtGRqxU#)wU>T^y0P9IslNC4<0Sk6T+B-t~JEJ1i zj9e$6nmf2I2F8o0Vsq?0d^C-$JIICNigAfdf3hiItFfek;6V^*GGR7wX*Z2Y`Ds_a ztxD=Ebll~uDO>JnpIvArB5UbW55Mm?2tLUIgK)y}W?lXdc;&!)Bz+%zhzEKC@U_^f z5uRWbZDv&=nA?Bx;)U7E1S8ZiC#8j%VwVocsLHMz^7{MN->%*EZo{-?ex(iDy{bm?9d< zsW~iW`)>lalGS)#!&ydlHD)b`RFYx@f1jH`LDb?g7;9_>%#AjDdV+K4Ht0np`6UYS zOCiWFMGbrEaZ>=X2t&YmZm4=w!L#2Q@WL^Dgrv$|`=*ZWnYD&(Xil|h1kdR6wSYJr z6M|f`NkxTKUFU31#i#h%_kZQ;h-5>U6b!7G6Fh@q-$r1K12wDwOhj(6@<~!Jf4oWM zTD;a9!u#kE;V)2%#8%FHH)=LCAaYv_Tih1iBH+meGYGFUW^&&{oe0mdzra`v>oY|E zjARYpc0YSwKV##H3nyU)GG~8{{2y}tbOjy~wz;WUb4-`yh1BgqfkycP)XowUH$lzL zT?~(@*#a_Ix5{ISXvnH;e^|%kIpO;aCa1HjR%wCbhqoz0BGfw+ zmaggedVM|U00d3_8xJfA*?OL>D}e`U!D~0+TH;qsT-b>OmD;f{i;$!QB(yh^{B&vf z7Fh1idQ8D!Q@ygF>$&~9OTe;70I+(Xj^ z#=Q@OPRkaK2Pucs`y_sMY=+z0RHv~0IC8yNsl_73H`HnUfT;$7H0gaYc1#@&E>BNG z1CE;3J0YPwzUV>b)ZvP@r^8S)hw9k34aVnpw7>ouX1e=AzGd)CBQTcG#! zl0^sd(Fe10KqG_d4y-e{I9~1Q%H*4;wfIArXxbE1s>rN4kYP0a-t+p!^ZM-h=%Odo zlxuC_@UDh@3}$=AVW13~3_2PN@rA97gB3n-(4H4F&jFFzycxHfMuG=n^HKler;D!h z#vzSQL+(h?RpYjke^72%t99W7x+Ci**4AT=kz*3&8{c+O9N3aIWC=H68f4u%NBhSw zJ7`xgY_BY?_*TT$K6C`)?i#kVX@HOLd_xuS?ZbuZb~5xIZ^~NUMA74|Xh3MH8hntA z{Ch4^a?oHU!mpu)hd)6F3PzbMtQLYn1iZN*GOh!991Q1v>(2+`L{JW`6k9jaWDYHEK~1M*iq#L2O2dU@w9}PxUYxv-OzmB|$`l z|1V|~q^|k;+wZg**v6c||KGnh9HNc3yxpvMvfsMhY(3mxX)=Fw$l6H)*94HuW#t-#_rGXuVl3;zd+I9RNWY-q&L-5%; z@iL7RZm2XMGV5fWx6rzWFcrPR+gJTq#CevDMmcZze<)qK1uHG=S_@(EG+z+NaJ+>{ zY4O9c8Pm6nt$`tAM|EV$U8JQ7uy1-5ud^B48F z?Ju_u3!GpZW!pkM+qQK8ne}#M!U;Rofs!_-0#i1phi*L9P~5gWUFTMCFMM@9db?rAyNp>R3_6w+Iz8{2Z!8t&~HNj?)R&p<6B z7qO#!V*_txJNJ#i0ocHTk$gd}nK4hb-su8Y2$r6`tsmIkZ_ZM@jr7IWP$^rMCy zf7t=UP<8B)Js~>2S?L!YpBd4B(cMjG@+x%85px}Oxoa+rpsmT&up|JxUau@VN1phZGr@Zb97$nm|eaCeko_; z5vggFv&HxSFb@rsG=X@KfefhSLBV;=R%=S?DIEgaC$M_LN{X?<5Gu@ukttQvf6S81 z)q@R-%LRA=9yWR9N?@Iw1j43d!yWok-U;+p-iotn`d*e0nGBwPYfi})c{`C%WPL(t zr4d}=Rcb%ZcQNHpSbq93N2OxTO%p1Jnowre%)$A{%-)hs=1eBL z)F7iUQ<%`!1g>9VT@ZQhV9t#(kEP}Bm9hZ)x=4ddI=f99mfWOX)h z;-}7OmA0ZvZ50rbo|ZHM-#rSoe0QiD%!*LH|5M&Y5KM9x-&`bSPOeU44y@kVMJ-!l zi#S~SkT>&z?yYcGw{PX*7dHCjok1d-#vW+>qALI;7k^zeXwmtYAxs`GpfFr}f z2iSj`y|T4P0=S+Z;XDx|3BWszdsqfV@Qgu%`LhZ>_rGqzJ6lu@+2@M&>?(ewC_86R zt-xdONOt>yh(Z!NACn)CZZ9KH4Y)+tIpY4J%m=@{q}{$hQ*qgme>0jtNOB%91jf@1 ze;fjqjVEGD8>24X+i~|QLnxfT^Z#f1>R99drumCh|5+yR(((a2jJbNdn0u!!0XLH& z)FJ^YD$N5T<1l4}U(g8!MHVXst zC2wxaS%are^@}dPf6Jy$vTNGMA(N4jLH^tGB)q$SXqb;kS*}$mMl_B`&Jep7s#`5g`rmp^8aadXGc89(H3N@|X48gyiIw=hy73}$unXR&1HCk`GdRR$i; z;9825BBeFiSK1D|&b<^F7&l3P!z(`_@Qo02L>~ij6p3_o#}!*N1zV43z9^FSQn9536o)R+?Cz4fIEQunx zM7vc~{)R}jv0}8)f9uxZo?HaK@J{g;;;+q4ezp~4i@aw9S%OEuoG9bc&G2FbpR}uQ zw1JagpJ3~j56wAA3|Jsg=OG&@`z|AO9G>FYP~k7Gb3<-f9b3VSqtR#SXtsvWYx#9X zq1O?(e?qan1%Nhs(F%9`d<$*Vfe>Lm+gZ z%RqZtMkVF96^nofBYUr7?(oCifZB;4goh_Se`}AZ4Tfdbz&(qFbjv_P|1exLIH;-+ zXCg)#Cqy@f{U&j;yM|9}+CsY$9TlcSMzYZ;e-!mHAS=NW{?OF+)`;$FnJjR~>FP|} zc56iV<|K0KYTglWoE@?EYADwD`Qq_N%nrtg*z|Zm1Bco&p55o7K6-XxnGBLH5;Ae ze~p`%A(y6wVm)M~rEQ*ND4SO|~v zx#Gv@E*?^7UI-(v?EF$?Q<4$&R=xpIf6?9;oz5?0H7yOeqm@6y;}~#0!UX0{v&iH$ za#&i!7n5^ctN?T?S}~I1&Li)Qpgz^(worcK{+NLo+~1u6sgeyiU5{;{yNvY0?AzHH zxP9DAL{OeVdGNtgoz<qdL7%^yj2R)J373cMMyrmGotZZHQdqf81bv zcj((LM$+^~uQ`fekm4=BsWKN!ih_^!@Ntsx#tOJUI|E58C5(*e_5>I27C>|>fajrS19WGp_f1$UsY zqW84oH9Ft7E{LuQ2l#=k`ieW8_>zyWfE7Rk^13rYJ#{@>+`jZuTslMX?IhjMwb-o+ z(8w-RX)dvB8&fB)I=Qi4Bl>;7(1dB4%FCcS5E$<;b}^_+pE^*emnFLhe?-E3SAFBn z%`OIYfl~(xsStb$z@F=C-G3`1DrFi*vI$EBp-GzHGyh$kKd%e?8 zVj6e~mGY(H_Y_U}ruISjk@1f4G`cZ2y{pkr(KbKbqshC37F8;c))8L15LZndh~zu# z9n#L!n=DlFUl&PuzeK2)f1-Xzbx4fYJwkORFR8IIDAjw>J+mS;WzmOXoy^q>L_2h> zB5Jj(NBh~-8KMa*S$Kp_e3Aa@N-|7jBW8 zLd3wog%c%WO9#lAEh!VQIt$eMd4 z#P*f7io?)01_N@#2I+Y)tj(aENlba-UHE}A)#iak1n4h~XqebbO#Ju#v>Lks_*gOW_cZ)VC-90k>0)5-$mVR9$b=Fcf{yueeN; z+D_|2$AqAzV*?7>8!GFBL{R0rPGiZjjqR)pTmL(b<7`Q2(C|az zq*8E;94&kxAYECDPhWhTaa@1_)l2PiO`89uBAaE33{F}G>&=KQGKeWh3=~0Y!C4NL zN3Fpj(o`~1w6AM*2KNEj6&@YAHypurLbZ+GkUMG100dHhC<7t}laMkIqbr3}eq2Rt z6N;0<7Ymsyx=9RtAl!3x3>TUZNQ{ws9EKZel5BN?MH(t+4>Ozc#HR|~TPk{s46*6B zHc;{ai^bKa<$U&K_WdhNp%+G%KVA;sqG9~={>^UqxIcTwessEveut^NXn_PxxT1;D7pNr-aZKz$Hu!3{v$vIh;kgmz?DuPkdt2&^pU3!Ybb8uI z5R}il(6&lb*E?1s_0Wwu8;qflrzNc-CR5z8Sy(I0CeHw>WNxFZgkXCHsJu8T0C+K- z!mHP9GJQEQvOLw>Zr3}4sf~ZSr2OR7&h9b%qm|m>c+zR?&*grGyi9FbJMvOJ`;{T) z%Ceys_R8N+OjmN(o{M`nU7yJRY_?Z%x34d*K+cpyZu3v$fY9>@hcH3_q zg>jm*ooTPKovD>xu60KPOOVALN$^O}FIVTk7mGK70!Ye<(aQ%}!Y+27T`Yjb0*T)g z+hR0YlU0gK5>>2BR&2>03R1oPcJgX8%5g@j0qm(shd1yHU|F6W$7R|K8V?CLZn z8Ohlz(|_>8;%t6GSGC*fuzqwnFV38XRxbfVvtX9c{OT>^u&--I+U)}6V3#wxu2ZrH zBbbhGg}7MwYW0v#>1@0@rdfeY%xLMS&*@FF!s*p&tJtg=yv!%*Z0i$ex^o zT-NaH$2`pSV_q?wugJw_nD?I*&4;<>Nwo*Md4Ix4iPK@mGh7Taozwg@E7-%n19Q%! zhtHyY*)Ix+vwhIMr&Yp|Tk>Ph$PFonJ6!S)ybm8M>lLd@;!d8e4X}Ks~APl?Wg-Rud_iW z-hYgHJfgS;gUjM8E3$&%9b`UB?n%$UDX#N6?U@CN>Eikiu5^&?XHwC+Tn&49Xqqav z4|%_xH4JK!ChWn_03RoWap+x}0DQc|K<^PzIiz23S`)E)c93AsND{Y!L8S1l`|Fo4 zN9ZN`o{_9b`SySo{HJJvjVePJ!Y&q{2Y>$|4^y|d{q^Xp-*&g{C=;9V49U%THe3Ar{psZtF)nAOH(=R1`F*sha}kDuysWg+ zNT_PSq1WiQ->2xB&r>w!laSsm$vrDEZ{OgwB9mDg@aWGG;{SZM%x0UCX37;+WPeml zTY`D|^r^$u_D{V5Ai5FY+9RQyjK*M`-EO*#sruICeKTa!rq>sG{)f}~`_rFo-y63t zl{2CwXOESbU1$th#~^@+`yW3Vq@zDuR;+$GL1dkc&bHXDba$ zsUhNCbWpgMN-uIzv#4@&ZN09gHdPL5+fsY)moA*53{rnL zZsZy>ykn#=PST%yHxVYn9=jB1^i~caxRtJTR`MkGW|22XvcqSM=JT7AR6IUq?%y6X zvFW$WiDX=woHCkB4vvz_GiDIA1tRy{_VfYqLljEMEfKjy-t?cMyKS=Ca!Lslwk3$& zQB)NqP5CHSXvH0z@RcDEt7~Kj$`pUm65(c5M|@>rILTpO*BSfd5G^Rf>5Ma;Uo6o1 zhxuF>jgm^)MAnFVV~g_}vOd(V|D356I_j>W4%QkUH{87ABRY1@DhoCmr)1-7W13bb zH(M6OGV7~oipU49&8s^}(Ll&n@ zpEGzr?hoE!xqEaGWYLc^+`?bYV*5-L=hV3o#7&j9Anwa>p}eOd>*>)Td+BN3bRGdYIxWOwD0y5vR3FArtwyoZU zZc}^U|Gm%+>~6@NaNC|1P;bBZr0zwk9o+5Qe#hDs+s3)j5(@3|e_XhRtX2DAYpNf* zD)@5L%|+9rbqf{3fcq>3=t{MVS`j({Th(lVTm61ie*-}_g&Yap0^xtPz@qyN(Z%~1 zz62?XaJc|hD{^6KiXWg=`i_$@ZcU_$NS*JMHW#Qx^kcP-)!~lQ%`v*~{M>nPRy^k3 zA>P2Z5I}`sz-e^3Fb&C%(z?EhArB4#^IGZvpq4rpszvOqML-`4L7f14hue!gLAu7hIfjUcraAsL3PQRk_y z7+S}aHMg-Mz#c`=J~mbIATwC#6f@Xp_sn2J^CPz})8bP72mx2i2Eevb7qU(DgElv( z>Hs0n*C9~L5*3GRRJwQ#$q&}P6pmNwM+mH1Ho&!&x`=J6AGCk2{=`se3RBKaQ(44K zJ1Ux*;svu)qay9SC&6Ng|I|gVV0J*V%LB+y*F#n z&j3CnZ_w{d!eoC8giCi)1+CI!vZ8p?gSN@u{dT8jrK&Yf;m$lI3uAOD6+~W$3X`bg z863V+o*_o6hc9^bqrKREpBciYEt3actoUIRK|=X)iSvhkUzz}k zKz6^T9Y9a;@msFLar4v>=&jd1R}SQQ;D*TO;*k*FELiT$iS*@)eg`M)T8kf@OV{v$ z7m~!sy>>6PQNW!fbV6^?&V%dN7ITDVy>z(6nS{vDL5EIX-n6zuc%i|8PaI&L?7hv< z+9RKF^w%`gE9a7bQH@%FY3h{bK58lm^5xftmKkPCTC<{N`uUg5Q1HVbDQ`)+yxa2q zZ7Kf~f??!NklG$agL=#|UelF&$70oYqZi*Ee)D3AUVK=*JNWK}ddC912S*aeg@)0_ zWix6#{{l3Z3XC76dUi8TvVxY3tk3CMFbg@d5t_`+8+UX&DFR<~OEx@G+g)Gl=W*7X z9W~gZz4b6hs=-A;^7ZjHN!M*@T8)0cBe*MkOFo{>Bl&Bs{B~+x4E_bTT&xnp0)JRt zPunmQeebXEqzWY{1??4RHw2r+#MlGuiK5C)oz_~KWU&KOz<;0P*p8h#pF`xKYVC8c z&pr3rzUkSQWRr|WE98eTMGm1U_UVG|5=5q--P6%1f?Grq=p*nwjGyLr`3(PLa~ZLW zS_bFW@f!OuoL@qU?(i0MM7E-SkbgL8M_pq=+fhGZ(hmBSP#i}vY)9VGH1lbec8H=` zksCjq`Rut64qx{4@TqqG%wlZ6eU2oTc*N9$JD?+DAZa#)Z> zelEL?zr4Mk=T*AE5uq^h(IO5`O*D=cFjs#3+2XIh|A6ZEPmDa)yW(5ewL=F-#1rd6(p&Zxa&Rp>FHsaro4-X6X zhu~|@XbbYt&bIg&t!7{xqJTEdr+B@QfMaVQei7+1L{4s5xb#5rotwKSU>V0Dw|-Hv z;s7`t3#7Pl08~=I!9n3^GJnHF-w%%KYEJSeMN9*x58YrgnQ3$kRQ^;`$qApF@Qk^W z8T&*jb;Pp#baL2midLDABnLhe;FM6t#M@hhpihkk0po$XucqtTSyfRWOGsEQJXz#+zU7J4xqk$PbMjQh6x<3< z)tK8U)mb!$Si_YaQazT^ZUQTLb)VEJvq!J$aSxze+NbsFq;n3tFIpEzHSjJpsy2Ef zWK~o4Kb^(g^Jqu(VyXP86VEm~q`C|Pc~KVx#Npvpq|&2%@kXsWw`jh1=vJ#9+e5_8u* zE~B=lPXuY5tGotSqA)KG^f$}zYva-o(SKCiC@2hT8O1IFpQck_Y`*vD3Z&H514&Fa z-^{weli44%D;ovz)8*c6=tmf4NXLtT9!-=gBx?k6woeEsM1NZpQJt0=>OssXR69EZ z(oC^@BVs-BigC$bbj_;v3ap)?z7JVj8yDxcya`R!`D+`BPYn^n-rTc=lZv;V{ zBIs{`Tt&UMz<)4gIfev`BlK+D35~i*qekr-H7r9jfAu@M_5mMQn&OWNtu{4@22`mk zjY@V)yN?U8-Q?)#sI)?DyY@WVHA|v~Dt_%!js0R4Ou@bGqhkDUT9!(=6{Kxm{ni`P zD0_8C__ak|Ti|b9YxZsQ53N?sZqzyy-p^AUqzWa~gnv?rRm)6~xZG8_7pbsnQRQaN z%vd;fWIJs~v@gJ#C*(;ucAQL{glVBGZjQhze8Z@9sy;?#-yAx3LKHByKq$V!O2 z&bA;w@b9v^5^$+LmS=MZl%#MJOdrDRZHuKTyTj-unFpneQeT)|LYQP;#z5EEGYN~0ZTl^08XyBUW1<#+4IH!>g z0v4J^6tfV5AWG6{>&$kk@3_X)7B0At%=52coohTvqx2ibg`PWZTM!OR`+^&1R$L2> zaU|>-=08WX!J{wmUob8ft1`jl+hyJn)ou|Rl1mu*-W5K7bqw}#wqafKRweESYdp_m0S+kjPdw{m~{@)T~?JYR!dBQUMm zCUbtYSd@ZU>>raeDU}7hEj7}_$ow|xeJs%LTvbdjfL*C;swCs(nnoip5LN_83x7nV zVAi5GFZ%Fr3bs-ip<`}=QE_byH%ASbELW6Ennsk(uDKHRfO-^!AhwyIH8IySpDOp7zXuh?ryN&7ZFUoK6d&}Z;W`vGj>@vY$oklPCV@saEtw5wkFhoJNn8W z(QJZu{+Y-Q?y|${gWojp=J0;d`rsF$2%;If+Y8S?G=xbXGyC1Jh>EeDejH}n6dn_F zt2Xa$sRz+TrKQjlj5mmZzwamalb^SOwh|!_e{RAs5Z(P1Hz1TqFmx>i7F4McVu5av zB4aLK$vCO)fFj`EYlj3(NeZf(A&ULpy}Ng3=WU#AGD23!1XUPlqc}6MDKgZ|nHp zxorwnpOPoGJx+og2-qjfmx8maa2&H#+9~GD1SO#)DZaA>gL6oiTyRrBM|z7PNZk8y z5cbOG5Dq8Om?*cU6oIn<9f67I!TDS9fAz+MuP}DYGV*Y#gC`JpJqfD7Dkk)p?onuR zCC}=E3sRL+%atf_Yne)hX#({W+tkd4>;A|y-ybdA$*+oNPgLUnlF60ap6EvF-k*1x z;dq2Q{BkG48=-Eu$-+;uJ3@n6i{0xH4*u+|zVwa8{C~$Y-fqO2(L1%@ywz8}3&mbV zb>lwcCvqa+msiLV#(&LKO;6iE5WV|X%mK+Z3ZPy?5?ZN6szl*H+6zI^#@@h6n_X*n z9Y_)Xy)(N`{DA|hdZ`b_*`1H~X5I{=i{i0}qMT=v8J<{YMCRshQ*b-}l%7YCVk>S7 zmT|b0`e`<$8~>hN=?9T9i8iHe-F|z{c;SRrv+runq{!)bcYk=^HK%v);q00@vF5WM z;+f|kTK!ZQe7_aFE?MTZ*;I&^rOF6U)AZ}@)r`o`rEuI3xeqN@tT@DqI2>R{4Nwn< z8J3wV4bqLyj*lZahR=?#3dtOYDgN{)0uT6#D`$cHN7D%&pG8Zdm;}RFu9e&X_TE~! z@$F%f458x~y?;c2k55DohF&vM$Mk1s{%>K#+GC(FM+;^NVaNHpl#(q37I_20g2)lL zc9?AdR>PBFMS)cSrhrL8xjE4lI3V(nY4k5Fx8O8r#X<5lm)qz5|33uf4AOMf`<>YDgu7Wzcru28v8^^0D$1E-T@@LQQ>|LlI12WC zB0_AgsU>3ig>of6V@Qz>J@k&C+G`}aYgIh~kzB@VZ}!rNNZ`m3uFVt&Y~ZxwgA1;q}-MsJgO z3*g_%m@)fb6w%}8D`6M#HhTy2LTlLv+26x>Jof)b_F%=?Ivi<-{zv8a6eOoOPTxb5PA7OkE z!)ZHP?YhnI8vOyKR$p)1HV}W;r?>$@C8bV0XM34a$1TT{4>>o(L3r(Xl4acF zEavbbRomHwcHDRNn_7vOrN~nl4)2-eV`;hG5NSu5h>Rbu##vTacAqxMbaaU@75U@c zZOSt)ZMlAeefuruxfM#zer3iAxvB{#SjQ5tB@!YZXQyu`arQg2V#8;j&^mHe{eLDr z%avy7A52?Q9-FMS+LpSx^|FvLAwj(6@z(@Zy*{K1v$$6(ZBu2Dar8uc!#L~)J=c7- z$e4}S2;4tE_uw4fTD)J1kT3zYgjvhb$mIA0vN=l|AYI=~ZjjvfmO`==G-rvD=>uSR z7*l(T7@={{`|be_2T$W1-T|rH1Al=W33~vO^EBlNsKWMu$pjc!6cz#BaE;qeHLz=8 zz$wEGY=vDT8(t#?j5RJ3rkyP0QIhYFIy?efRip?JlebGayXFupi8w`Ul}4#wc#NDx z*W6h6Qs9RfyzuVy5{-rX%$6>^tN{D&pKGxp13Q_!>yJNuT)clbxm`@gcYn7q1i$}R zFiXDw{1{%)|7!oAPGIh4k^2UtsGiI&aW?4v@)(Z75w8FIXZreLUbBr#0l0V8_tE9< zGR1u=;(bh@ySTPNCcdG?&oKH69!BkSb7xD>(GW`r&d387H^O|TlnJV{;S(+zn%hFl zO7eBR_2|`8OW6QjnHNRwRDUJ92M#eTg*F~>}36{44Gc3SWe zc`e*1iZQM&|DaWNSCV$dehF$_DVw+z@35L&+(?!1&&S<`DR?M=0PB)-EDjtJQ=qgh8jESFiR3HV6b+!hfBaUd?;(bp2Cf zJ(!0rfnEC1sJtlow(ZHb+dAx98!LC^Y1mb?qG*Z1uou^9%pXb#l%aH!AS44ch;+T6 z(^oY5{k9HN0ad!en(O;L@TJ=Nu4wwN2Uj>-F^V}?Dz_}fVw|e@YY&Vf(lHQ&ZwHLk zyuf;@g|%FQ-3ok4lz-JV*D5J+Ww#0vv0QSEQ4CIZ(>pv_dJ!%*R>kRl+ zz8H`SOZ(FvV!8i3hrQhM4Ixz?RXzPwBAtZt-}-O~F94*c#s5UBvgMhW-8FIdDm-z8 z;Mg60^uzGth9$`{L)SBOEmjf;>Ni*u?zzF!U3_17`bZbs^+(i3BO^yOde=b{>TF;8 z2lEL)sdR>je`7I-fN9Mhx^bolrt<0i@5As0e99Agr1`y?V}26Rsc9k>>d-*EdSlysS%QkuhX^d&Bq`=;!q4D1alluozAtSug{Y z!hDN2RPuU%9MwE=1|0PB*%Za6LCPf+pcze+6f3}N8&i>wO3*P1{sw?6FKz^nA7P;h z(>Bcb9ZTQ<2`$(l+RmW2tvtBJQwR_2lAGfxH&-qTVQo8D({f8QTWDE(9=BT$LHlSO z!O)k?DDqad>mm4vgUU(mpnIGc%jbU{#{2Tyz@@Q&RK^T5`&jv1kG1ZkemI^=m9VSb zThNB_WpTT&;W({S7t1bCme0m0Q*K5c?PX|U( zs#VrlkAp2^7v)vu!6na~Cmg`xA#{WudT)5QPEUIX)66Jw%M1`Q1R_;QfXW2O>$5lb zw4jcEMyy>1B^3gDPsP87V3ZT>3Sw~VBK>(`q14=3Cc%~*r*NqXkwC6hQsA2{6(l@O znZ|+ve|FRBvg#bkO6X3_&6XLu8DX%WfYc>mKq?Cq+eI*$Pz?#5pL8AA0D_9Gw{1Ww?^INWT1DTt7NyN-Vul>V-5Zsq478xeMx)4oPDXx_y%?qQA^0DhOc7A6>8c;v&kc5o`yWSOG6mwBcG&Lz+8fOf zs%pTxVAWLak5+kYTs;K;xAEE%a}Ix9Z`v>veb2ABtJ=juFv{BP0Sc|Oc3P!Yn^sh5 z0)|ZDfVISlY*U(5{P$faAr0X}^l5%TaD9C5@$voO;xeAamgO-wppp@#C3p2$Coxmq zmea8;K|`iu>N5BmM2lhH?4+N=yJ*T?8X#t_7+h1$ZiQy@$(UA_J`dS#7|wq+odm36 zHeeqe=jQMCHvtQo(An=&w3}y_#hOQA_=PIX#k4T&f!+!v!aZZ&4L6^eu|Jd1A|sjp z_UFPiN6P5yhr6LsW~`BZXC21X*k~uF6+0ROhJmeSt!6kx7e9Dcy-s`y0^SJL5!4`j;bwXAUKawHU z#QxO?8=mbrbvxHnM#4L|Go~=sVAQcT z_Kl-hvgtU*5xe=D4850D{cP#9$>6l{X*Bdo-^gWq_#s1lUOLX@anr6tkvMrQ2fE!Z zw6@VnDe*i@kkjf3R*8Q@RE#&$KG}NGEc-|Q#QS#Q-Jf_5c6}#|aHIN)(V#Ut82a&W z=-Cda<7`pdETcA+k|yInEE%(BuCyZOW#!(#e|3L8f_EsSZSPXjtY#CgLOP8ad@3Tz zfMTCY6jyDYm3kwVQH*UTX)GkyY^R^%RWS4MVJbI8Dor4*Q>cH{@~%osdrqk;%4@k@ zg;g!`VqzU|Fh8`BFnR8;`&hnK5%wyi38a`YRWY;1X#7?OT+tDWxkH>c)qjcS8=`L3 za7JU(Zd&T58Hbd@t`0{(8O}QXwEp)1$b#z`gptrQ)l3+bm~}1{wuT8y8$0L-%w><( zU2nhn0qPwvPgYJ-p)yh?QB)lzYkho|*l88zoi$0D(P`NfW~RN2gz5eP|BFxFhO}h2 z6B(>&WSdN}q1(f6s9>o-jrK;<(L>hBF<92qw@1sou3Rmxf49Eu5y!zZh(qY3a0S+ROlxelQ;Akk6o2mK>dgp}>Fd?%nC_bdm*Ssv*Sa_V)Jm z*}e7A@#cCn7%aITvV^-LO#(k%q<0%GChxq%!60I5E;h{P@N*b%FV1O2{=WDWUj;r3 zktP$h)stJFZ_*%+E`DTxA`POe;>BS*>95fZ3xnl{+A7Zzsx;-kp9onI&MmR*Ki+h~V6rwDAvtbg zNh%iGAidTR=f{yq;p5roKNjb|oPPdufgeszPd}gH`oZ4b0QTUAl%r%U<@|SdBoMYKnX0Hqu9Ck^r*6(K)Rg3|2wJLP$7U#!+|&2rELsS#A@e z1Y_smegODLap*zbCdrYEjm~kcAj=C%0+B zU;--^3a%(UxG#1DD{#Mq$z-B3-z}JWRVsR<77+1mt0JybSP0e`hEl?P9^9anQ$P^F z7jeWv9{_H`zhyzfmk=iqO9m|T-a1%E@*^Jy#mAxGJVG^Q^KyB(%rH|!F6c#g8BO{oAS?t`OQdJu%2^v;0F6zI52mUEa}RfmmIPv_?Gc8IPf;dDAySQ{*)D^F4d@ZNQ-mR>p<*J3s+65 z8CjvN=4B2sy`2bH5h?} z0r2sx08JGjlXx2yAq}gLU70c_92p=E^Kf<4ko3d^D}@ON*l86Ss9W&j;fL6wdQCw6IF+j_XUWV zEM+ZOQELF2>7h9EP7xVYd4ABTEg3*dgu1nVw#=Q?tm)9IL&0BdFI}ggU);QR49IgN ze2D5Uk-DA7$Zh1Aa+5Nj>or5lkO>=Ex4r|)*3~ufSTe|ws$`mpLLh=t22?|#25#Lb12|AMXOgUg~F_>|G zT`4w5N7y#x1cjmJeX3$3^Ga~n2B}(qUQa`_kCdcB=BtYdKrS*8Kp&@Tahcw&*{wI6 zclNK^=`#9YC@Uo%FYRWWuPTQ;JP=<9zFkdkdO4R=u3Al}DuM0FKOW0nn)OJj+m2wp zbo8;c?W19u+}Wz7Y9A`)l4b(dK2uSDPV|TUX&NhV^Eyia9a3BobDP4OH{crAz``ib zz2m{dgLzFX*JqAr?}T#+%Nc=NW`5;9TCk!fcLd+Rdq1*WJiXnTy~;1eZP8N317(sq z$*~4P%W*?;G+&mTf`M1`l$d4ov>n%vA`*%#Kye*v>2##xyKgM*2FV|L57DB3e@#}& zyLoHD9xckkkizR#xv2W5JgteKQ>xNk-D5b(X$19iMl!CE%!9ggmcFY)Nz>Vu3!15) z!~wfuJWK!9ZGVecWcN11A0JD*doSRD|IPZguJ=W)URb3wt&PH`yA(r^YKca`r>@^E zCblS3`|Z0MamaqP@?R0qQiw=@n}^OhRA;5q=5d24eNb-FH>xoln_P|J^&DWUgPOWG zc3t9fPv|YC*DU_4m}OTDfAWaXZad+&RQGxqS?3of%RC*8-oetG^{RAQ0(s4E9USQr zO_ynGk`W|o-y%Gl^?whKuA0|xKv#A)t-#lU&TUX=SKFd~{`9(&KdE|uQy=yc>a?q3 zO)M#6<1Wy+Z~Yy`+XydDjk_B?&+UauuCqGelXkl;%h#J!U-;#>W^Q#fsf;?RoMG=| zpJ*;kUXERlSVOCSfvO_=P~5d6Sd7YQ5h8jM+G2{_@;6{)Gs>` zE{c;ihSfj34dT>2w&R|E-rvufm2_}(_;Ij@vTqrN6_eKjtv~DoL)45?e#H|tpWDV+ zxK!VC@rZ5~bST4uu)ahR7A?_*K?tXrNF4!Rl{L>Kx39S!s!us~Y3XCS1~6utRt&mp z?9#+RWAxHBB4`^@8R1o@s*I(yGj_~&8fZ`%?{t>AG(OX_s63E=&A1}iq><}O1eWGy zfev_Ut2b~A&M|$Xf&cKwqY&p}q7K%%Ct% z231rEpiaTB1(>3?K&Eg7(g6v1Fd0aH*hsWW7v#bmcFuc$hSp+L&$Aa%C6LQ^kuDZ6 zQX=zz47GB#Zex$)T9nU9@@-vY%!o}H|MV2y~Xha4(9VlaNwErqQkI)4xk}J<>*>l>xS(h;{CQDp+rt;xu6v= zjkAIEyuU_&WrkXZuVJ4A=wQ?~2F$7Wjc>>p8EO{`+vK+z51qi{DccE(RctoS7U2u2 z>ld|Z!;tfRK7*Y0^}Al~Gg{-nIS0L-q3mBvit53`pCIX|;cf4lenNf$Z?;oAH@i1% z!#)AESX)mUITU`+uQ(5=nxLd;UqcewZCQz3N~MB-b{_zxX5t~Uo!iogh$#-`* zQlkE%Y|9&F8z%2A^T#+O$=ydH=uMo`fyiFepFGd{QI|0n{isi*=m&i+M4V?N=|^4* zwhhI9mUVb>MMV5W@7^;;_Pwa{v=IAYP@Ew&y|_>DGhO$huC__yR7JGS zLK!I+{_*~gXhKt(iPKKFti#nBOF>}K41h+`^8vVjv2F&y5-gknu#^-7P`NIh z0Z@4gv&RZB&Q?UGA0r&as0SD&>pV;LfJc{qbC5dziPtovZ1ge${1q&I!q`EWXI#LC z&sR6^FRsqNT*Crx6+r%MNzG3q8w0R7M$xg%1!~brqhmXnz(AtQ{U%WUuXK-RYNQsvShwQ{f+Mks z`E+^kcDkhhZArodtwk#sJL}|6Tc<#$R-(gUl}jm>9~UGGX&!+&>uuUfV=_dMhlB=t z?{@u4{wo_u13UCr?RPJ6`2HR02DpfSsu4#I1drvySW#xoLnu_|re~#mx|F(tG0b$f z>uNeplX?`uRiq|-P2tdmGhb?{pm%`l{UauCb@+&6}n= zsVb`h8nm_4)S-O@ulCJwmPW^1>NCVQPg%3Hrmf32(?vVntJ&;b%+k)fAs(cE`@E`? zV)50hX}DFUzcd?Uqyub`(AS%xyIHdpS~$Q6L=LjyP_FbX=_*+1ZA-CYEH1K$GK#^5kYrhoer{O4Q(h9} zN{mqqPZ+BP0R@R!*;=`Z2YR38NQnx{(wKAPuWCz`KqOU%Ah`CF@iG?GDZ^LQ-oL_z zaL95n_a#I*OJOQwPZCMl_CVHYj7gCF3k7KLj*+6!`P${%WLf4dMtOdTK>}{2KG%yrl*u(1yify_jFOeF%Xo-nxTj#9;>|>+#MM0F1I^Oe`%t0Wnj%cGnbEqxl*ufCW#fK(z)#6i~gE2F9Vok zd8642QeP{Fv7wP>rjj#%H->WKz~eZYvgn5!(q~IP?9_N@tpB2Wz;vs-V)~8lTVQ{a zWJ}xfGC+sIxk@Uj(bx1`>6jbKCeG$9Ijt--_DtL@`*Q5-ux?CXaJp6RFnvfT+YU{x z^+ZRi@%`#ko1W*ybctrV`B%g7fz_(9A&%zWoHT9WRo0V?nyXiTPdH2epR??dn0h|C z4tL+uL8rY($>4f$$dymsbZt~7O@(;Vl{zUwzwfU|Djz+!_s&xSI~yh8#;{j=4{%IA zHo+r3tUaI{mA3|j&p904%XgLiGGrDwx4aSZc3Zq#s?U@hxq$pM&}q}znQD8d-qLNx zsR+8(RbO4!_FLtDrrvt7P|9mBzcZ+PD+~M$CU6+blQyxOV^*@On$B5+&Kk%yRd3Xc z@lJ5XlG3|!G;UdMmsqMK8G&AC=IU#kDPg4+b-{L}-pj@>$GVG?$nQ?x8MDff8S8pQ z7M}0;`LkdIOV+;mDgt}`{TTfO%~x%2+cpsX?q6{Qf?7_u_Z<_}5r3^#ZExE)5dQ98 zaRIW*%IwB*+O3Q0q{Ffm8-{g2@@aKu(9+2wLXiSV#c|W@x9>>3SXS&I0p<_3aeD6U z;qf`WzsS?P*NZU{Ok>|z%_BRv>m1GWB%Jhml4WRe79sp1)M|F^p7`(CAI$PQoL!NN zToSS{2uUF$%aw#E#ee8FW)>&gc4wOBOq=e5R`koO-)F9ZIhPifs5?k*=1gn0?wE6p z%X!9Zl`jSk8Js7;tDJ-{_Y`qU+d4E>9hw$*&^Z$;Ij!N_q ze3IDWvmZjDGxz=mA+ zX%9p{9G=sep?|jhGTP?=seVldQ%D=!gm4a{E$^>ip+>He>EH&Y(%n#mfx6UXXlzqN>)u=}k zN2BmU){fJqmo6QAxMLc;>-%!b2axf5jL+e)4pHBbhTP`C6rQG=Y-4vEM0pssNBcZR zWvio-kqx3v|2|Bc?HaRlHo8Mal1Ibj{+^ws%>29&u=)ZI$~LM|d#YGlY87L`3PDo9 zh)83cZhz41gH>=sSri20(fG}9bP~{+0hcj1mM{f3DO(8idedM$Y_TSRGvJA?Gcut_ zC7Fy}7I)!>v<@O}{Ekwh$Rw;(A!1mdmzdbs2rEu1%4ixEv=7PP%1ouaRix_5Pw zkJ}=!V9{-zP!-k*swE_sd124!uSNt}WJs}Ksee_Gn*oqi+m(V`6pjFslg?s1bl$#9 z=m(?m@V7z^sl#y)))HK&`AKE8lr8*v^@*U4h0*EgZ4f%HT*p35)i>2hLSC&T-`}KE z>o72zMNKENbgkba<_3b3@#&kl-+lisXqco}iRKiz z^?zm1M#`SGJv#H$-6L)vcK1ld=toZ|-LO(Ix3_&iIG)Ad9tQ*1y<$2+&Zls?M_S$R z@4O{D!nj><;>2cC3>EVCEPi6ooV3L+Id8}h&Jc%)29R3Z*o z9ukoJ+#Pv39>2MIU+?SLY|Dz0HY`)R;f2oiQ_a-%yXECyM(XCZSsa$55;= z;V0p5;zS{~YXuq-+BEbj|G}Pec7*Jy%l>lU?)R^EYg0rynj~-=DN9C00twlFDe0zU z3FwyUR7~?K1!YyOpOO!?D<#zl++J5@B9^m~nJblmbNJ>DtVtlhE18n{iXYiFffG`= zL@B(tDJE^1k^v}n1`R6RuiSixqE7+c%}hXRskpf({~^H*Q?hM}lnPT&-!#Q%at;zp z+hFyc9Ld)i9_RoyK&)f5J{7cTsuQhFGWn0{p&FzX{#ov%K=n&L_C%$3Oo&`F+vYcCb zi+}5OQ}P0~2|cy&8{0Lq`e0&Y7|FU`UZ5Mavl}x%zJF%RH#cwq*67TC@^G+@;yaT4 zG;GY-!Wb`B&iyj*ik|n4JP^SSKZ`7Bj?dzGB$v|jAW-p zE-rkX+Y%g}7W#c~LKsC(ZR_@s9glo#EBSJ{L$)sgCpUtfAx!x|Z%#VsTD#w9Hxq5u zbXbp>(I{eia390A9I-~Wc+QMQk$%)}CPIw{@R%7zi0S$sF{227DXm;aDv-{TSuCMz zIU}peCoL*kqk+@ilf3E#b^iDZ8uk?SqBz$2)Co2e$Estcea+guqeekKkt^yam~S{TU*Y1b)Wc3D^Y-MYn*p=xw`0o0=7VKmfg|aJApx`RJ z=GS3kj@?q^*$5M35Gt0}LUi0%jBafhB)CMcxW?~zKXy5uXa54XepeHOV1JP^+1ao+ zr)1Ul{!63yOA~GBibeXW-;?vF5;zNuxN%-Q1e3ihF3+LIVuMx>4 zW$EINbc+)jf8Y=KhNRLyxPNF0NRA`Pco%)~E0)n3-zVgWtVDD^zobvmqPVUJj%oVP z$#X@8B(dV`w)Q8HIK~oxWJ$hB#c{*eWJlBZX`#;PLyD8`#}Z3$kw#7T)ZrsbrLJA= z$u<1H#yj};H%{_{xPaay%^}$v>=1Q6_K=y4b8LTp#Uh+6{sJ$zM1P-;34FnF-Tg$} zLr)%MSbR>Cy;HW|NlG}@iPrb4JdISBqKM^bks(X7f&VtYS_mij4i3qetz07GG?gnb zxuQ@+1hXduQsZO`i0CFuh#DL*KyV!nL7?f4+ggJgQdbw6r!6fv_@|QJN>vc$!ItWq*gRB-G}ori%lWK><)z95h@xg|Az7h71i8eN#7|<@X7Vs>Cjr z5lbQMc_cl}&}v+@0~%)VH?U0Y4k>G7hg!ST^NqBRzF94Fg}gV8{3sN8mN71cr|tPJ zv%2J(vz@ll1(#mYEM84cU8j!EZv_&BZy`@7Z^h*N`~)d;B7Z;+;CMPw)RQp;4s9ma z(213#Tw{sWIE_`3PY;ZY(WzWh(5{M40z}3SW3=LIvs4ITq6!>+6NGnSDSlp7ByT(( z`~LVeI8g3nYBJG7(91IlH)<$7e-vh%NfxoBgwb~br3a#rD7-hNSEKewk}+RuG`)RC1}>EV96 z{eP54q`$V3)^}F<3W*XXYRgDn&tu;ZnQ>S@x3{lO_B2*I+?K5 z^Ov&Pc3F6>b5MCCV2_y8ZNqxJmw-OKK^yI;ToVewX%p(q(D+> z4a5K5B_-LiYu6|*6v>&{*@y1GG*uHt1#-y@#?~3Z-O6nmw2RNlT@)!+qiq;Rc$E6r z+rzi#w*6uvghuo{># zY;*79t91^O!szB1OLrZ$6zgh$-G;qs-=*MCwu(EU6|7cVE8?`=#U0RtjQC&0h7__F#%o-+%lQ6-4=VxtDhi~G!*`ai4UJ6M z$|ctN1LN6j)*Bsa*n0}}AU^QJ;flbr&uT9rN{IXSzLB36zLm+yrC+6{$>bG*_c61a z2xw4ov~dE=k_9YJi5Gkh0{$6>zDrt7pX z^ol7bV38kMkX}F@fwG(xMX2d0i<y9r8?S^^ZMSlRdzcmyV0)LQCOT;h`#qaqPbJ#-y+k;nED+r2+cuq-Mh3L>YO(;2%HL;EJh{$4xOHJ_ zZeAXm`(S-@r+L^O*^>B&_!OqY@5!?n@Tfn1eex#S;6W4Vx$UiU?HkUV<$vCK?SN2s z!Mho9A!c|?&Sm6vvaUlCi-3H_^y;knX0@#eK37jB%3>%cvhO+~oZ?}}<=z)v!Lo{f zQ4}Vr&LKw@dHKQ-#zY=GPMawI)R((BSgz_*NL3T|Nazi+R8?JeDAgW({*B68-GHlD z#Rr{IOHacv48G@A_%MlWLbo|N6ixwugH{Ub0p)UwhC};C&5uWp0q-za-!Lvt0 z+duKcZ!9jj8ie?nD}6RU~-JOXPb)|)2U`}gkYPq+t9 zwk%@_h%|rv(1(OwoWk^s<>BU)_=Ce76n)4Q$RghsIp{4!$`g^J?ZHZaW>BPwUX4Ig z!Xptff?BdP?i&t^Gc;IO6=_ID2k+j6GDR0H!rU`}eb=b%5T?BP?hhXznZuNPegp__ z>)vt!4<9^uVBlx)p*nZ}K0Ha-TF%8fl^F+y)^t!p1;TjJTyD|S(&&f-$yOrgXEC4S zts_Aa@G~A2X~fbT*Ai5JgHST9P>B_I(|jY;{Iq8DF+6nnqbJ{>q#@;d7;sc|E+^Gj3q^*F@+&Pp2v(U)zOJt0 zIZB(K*4OlAvquwGY$@*Z-wV7zegJYU1sk^GxQ=wvHRKY=HR0@k-~-?B>|mB-l)gfB z0>kT3?1T_kL`2$-h05FP8uvzqUH0!R7LXQk3`;FXH&S~u2=rn%GJB3(EVkNxkpi8n zoX~UVEe+sHzEX&OxrEnmyQmzWy#kkpY$2<$DT=pNK|1yZfn2#-@r|=|IWXacM5S?* z3q9AaBcTJW^g;=LeK{0&&ZLad6$=qZ&rv8CaP)VyOKudNGjtjttI}&EITK(|&w$~B zGqYhrk4!lRF`mc_om|mIiX_m>FgTqZniwo66+_yS6bvWU_JNG&MV8hH=P_lb)6t+u zqVlvZ=n6XC`%u5@OZXk3EMUcA#b-fHOJo1gj26{_c8oZG2#zAvGIUh-l)%xf>4axl zF&wxSM31>>e;6RgAq;qT(mtV?pVFev>J6}$+ENXirqc&V2uK*UK^c_FrrHWnV`xHJ zq{_|88kQ{S7i~z!m%cCGy*y*#`LAUH3rhKrOTc1b{3ZxWskDeU3D>+hq%l8ohQZe> znbS7LlubW>ZA~>0FP94o)^?}H#dL&d#5eQlbwkPgl$_sCZY#OwRPSpZ1uU=}K$hEl zHl;d0Wl`i=W?oOlTi+aNGJDx;KkWg3n5vIZt%2V?O9^VHGy7n|_XYlCIwX+vZSXA`euuT_j0wtfr{__rtP%*~Y z8Orc~{90@c6EwkegqW)+dpXajWOhBt7-M_=wl-W{!}RKXL zQ_)rnYdLa;8;#LH8=WnK%W14>U&}Y+l7W36C3K~GI8AZCEMJH$!xUi>049ik6)WN# z1;@ieb2^7i#u%#9o^AayZ|K@Tk|fapoOE7ME3q>>&I6fIo%|74#tL zRU}SDV&wpcda7+aI3wr%FlXtGk#;1)63}Z*IdSurslBZ<(lU&Ftamc zX$B{7S6>5LGx}F029Y31Q+uboZ7c#-;zAEI1Ng%EXAHMKFhB;|7kB**RZpatJ1p(5 zWrT#gKvUjaYy92I{Jxxj{0X&JOLN*V5We#(wi!CuscG74D9}UG>GV0%c6xyfqu2t} z*s?3h1SZ3O?@E5j#)fo~<`7%fY9HTzyDQ#IlXcST1=J6TppI06`D&qd36ey~>uqX-RfHuC$L@=(FXk^Ja2?1l3 z642}yDppkV?t6fL7w6~Z3Fq*3Lqulejrl)BQywUh(n&6IVV%035F2rhhzZ-nsEi>ElUy_0OO$66yj7RsRAb`Nd>==ec;Do8gc2Kwq#I4Q^Gu- zz*dezdV@k0*A@#u=4d$em6Hj!Wi#^(K@)Vzwustb;FZ!15*bWee|NKxs%;nUOR@6! z531~}=)Yx*j`(YEDjP&XUzfVAqN!$PB(71LCd#Ok+xO~Ljaw(pX3ihATPS*nVYOy* zII%FZJs-8n73kGWWs>_t2CKD*?<90LwWF+vbfa;w<3L|i-2?M#sOVnmg*jzqPfPtG zVM=vLnbmNzF>A-Qf1)uODmk;X1uIEio}cIrrScx>oXxkdUY&VXGj%Mpt_v?gi@ZL= zmt$uvA6(nytba?X$$$su)nJV8f|{X%`K+frOO5Fxv%=qNm`=y`meb+x!+h#*3ao0( zytsh35n07Uw&F-qAUGvt@j!2#=VjBX z%FT+|D+W*%e;jr&^R3y#3O?u6R({Xst2x>|B1(guBjRW+)yKgj7*_<*HG`TFJ!Dpu zmC!^cr}e>SE&J^NwQ?UXCdfUVvN0@4C}}IARl*(%>0_(7jK2xifip$p&#y^ieNk%d zj#UP93(#5{E&xSbPM@sVd)cPRPL$P+D>X-BZ%4Q~f9%!B)IJI9bRUwj33iQ})uMyR zO{&d0gR|_IOqE_WeKx($G~MoY=j1=poP%fw<~LeU-qo`LiBhTHhC<5OpAs2D~2-e0X%O>d(x5WVv& zMpX__x7kJ%WEy`}+fLg+5PkPo3{nIRvbns5TqqU2sO5!J>H|S&V^880_O7+NPH++b z-r2QdnFLdYTs)!!ZaIvi4ZVPeo+T!{t!rXswDP~{AilsdMpq533!Za6K z4!88Y#RV!95$b)Ha;>k51zGG~Zre|z1T$70enx?c8A)#5f(w>{LKaJrmO#DG8ovEx zr9}d?WIWti*<-f2tI(5&yn5R5~MIj;!4jvvN zDX7auWc+{1&>AVeVg{kb2|a}i9qd?8#!e;}!TH(QS!LFT=f?c>6fQHilp$XVsSp^! zD>c^xUNt?GIbj#^UpQpB)SAyz45{##TM&W5xDYWDhR!l-1=mtEq4)y)o=Lb4$8DiQ zIPcbHKPFLf4FcEjmJ+=?l1d4_g`#WH{j&c{M&sR&WzUi79? zmvMh{HiEnRwpTsvro@&~q-p285PTt3Mi-=C>{LLf$cQN4VFacf*loh=bT!0odCrgU z5$e~_8a-96;n)dvo%brX|(AZaJen$y=&@``yhr6EPnCmI+K);T^FO+329Os2j z+Dhq3qipz9t$yK{{zR3(u2kp|mg$Z5G@ zOany2WOvFsL1BNDu%_+fwjj(|^ax?4-xz4v-NYeCfl&9^dFX`xH3DGWgl_(bV~jNj z2^#I<0CI{RTP@Aq#_q_yTH$`nqPv;aECf5l9kjGfT!6uVRH+Tdc4GQ4aO&-fX`N;8 z6v02J>Eil2%T2i}rk;^@4r?>wMX|_nvm;BJ0S-nZ5@-c_v;jtA8ppnkXJ$FO&HNOAfnR!pSud@8Be)lT!y}m6{Tg-05_BU&@*I&Hfw;W^? zt0aGoRZVZ=Fc7`xSNMQbrvi0*rG<9Y4+*K#uC|;OD&!_kv6MJj+bM0A{`Va_w&SG0 zk^@RSZ|2Rs84s6N)w+tJlqNY56iX#oqE_m?qH=N`Uqlfn1(g*^D7w$f&GK&ku)ME% zqFBknT1$#&>2@$WPrTr9RDu4J@J15?%onw=?Kdie%F&q2T3 zlo0<-^(?>2O>i>Td7EFGTV_*j9c~{VmN~Owy5`1P19bhX6bevKz!6Z!r6N3`t1>$R ztwrW9Js^|*Jjxg+If9NziRPsf5wW7msg_Bi$Amz?TqB~t5rRj@>l$v>gy}YEYbAf! zD^!F8C27g?_Z}1tpc6F|dlXjd@?jd=;Opm{C2cXQRZ@Z^qD~a|!f zXV`-l-=2o8%i{d$zYWlr^s-=YG(D_)1D9HM?Xp|-&H}+*?tVZDt--Lz&_I8bn;{Bz z9Td>K0GG+EKlQ1-BQT#>Yw%Myjl#vkVb|k$G$nFo$My%PWQbhw;nxj59-HOUxeyuo!W?!xU^-9Bu}eY3mZ(ounU@AsmP_nIK;0IofWUdhB-` zNNNbzkhGbpeSc5*Bv{MAWc)^{nV=H!l8+3Lkzbw!I(|kyN&VgjH9ullA(}U=usI)V zcu<+YD@%vn`nOq8)QUXkG#HStcgEXBQ%Tj__Rz4oas7<`0k<@Z6oL|eZi_SpiUx~f zoi{r$7_mUJvQ;K9@Q9k&>nK^Uj!Xa-yl|?xkZ82j+VxqL9ncnDQ ziE92=dOaF(vO`sp4B;CS`}N(!{rX$QGff3I(n>}9cZUp1D_DQ$FND$U7x`T6kn140 z9x_;F1@6e-LVra`U&s@G!yy~{<5qBu2i=u;TI;1gGBi3bC^gFU7b(f{2Oh&t$L=4o z@9Zp17WlLOa%d{jc(BQFpS_#wd+|&&!mN3f=}Ka)>U49@5r`$V`4^8HJW!=Qeh^2P zUzhi5)j(~Kq0Q)dbz8p8lc}fino~{~nCdD8O(s;FA)vdm234?sG`xvy5;=Mufmzm5 zTX0(tYO8OhW%a~pcA~P`WP;ax6Q|&mY*96WM6wl}9Xoh1mY7e^Xh(&Bv9jN_b_%a= zHI0v#m$m&Re3ocZ#etc;-n1Ppyw1m7>RCbARw7T*tGYf;>oxH5xT~=)sG2Pd=f`U& z?BP%nNp>}b#`%MPL|nkQ@p6{Rp6cSZq2sum3=KP_iKbbHo^cPKUx@4t{AAv^j3VN= z2Zbz8g3{{G$0_(YUB1)7NIiz_zMCCA;P!lyYjtIFY)v{bjO$qE5L!4nW!rvuk*!z$f0%o(#VHhx{zWIXQs~8Rl_)G8QL{}35Qp0Tykv7+oLp@zSq?S z*3AT>L`nD-{H#@QF@X<0;@Lury33Q)Y)&qwurFv<09C++1_EIObe#CYM8$D=#O6rP zVfA=Y87ooA44dt+p9^!?jJu?v)7Tq2Lt^U#mrVL!7SYiE zucCJ3alvQSM?DfJ1H-E+m^ATOzwcgfNzVOTfw4KW?nZR~=8J(bkc3LyCG@b^=rfTOx-u!*9NMoPR0O zVls&_%D6^mtQL{o+FgNW_1pYxGLbw-Q}77kTc%z%S9jN&Z>5Z^P?B~_(^8#v2cl__@f8yp^J&A~Co4Sb^}qEdI*E?>B))zhZDFcxaK+d-E;rD{0Dan$i*wh>z|`q!r9Zx zaQT>tsJ-)c8!1`A%ql^8`f7f9EkW6$5qkFuwT&Z39+k>qT4*$=pYc!J8CU^1gGbI( z_y@+`Mk(eTrr7&jfy9?FK{l@x&*4X7fH~Q#*MiGff5@lWeZ%JSLpbTKu2Pt&A-u6O%mm*|5e~dZ774HD4 zo|J@$0sh3D5#V5U(xzyH!5EapWu&q)mq6*a0HX-Igv|m(v$^w3#0bLHCWMUf)hUEn zBnfH~f1|acw6Fxy3#zoJNsCe0Gri;`8I{U{Ri(=W`%6&Nuv8-@tpt~2=l#pCkFqgJ zMHZ8JHvbGQciUJ6z4u+j9}WQ*a>YAQo4?bDYnaw{jym%qYqf}sQBV<_@&|>KM5fiK^UJkLSgX31Z9WTDRo>p9r)z{a zft(?2{Ri6z&)e*3JEDb(J!%`4V&?6Rsqh;C0RP^(Z%0fdz(#@xpFVXl>{g9#zwK76 ze*tTHaurcs+hRR=_f(99M6zMyZwe^IcyDjDhP^(#uiPUMc9&~6DlNukYP1e)H!74L zlX$i-H{V}s5p0NL*g&pJzPJAomoQo#h)6v(u&ztgqsg20?&F?xHMsi0hVnsnn4qpB zFd7qK>I;5nl%$GNy--|zrVo?X^%AU;f9bocmq?|)m%UXge08s^GSDa;vO8#7QU5Ko zYzUA|>9l9;p_!P?!f>VW-%?O8sLRNu(^YkY**I=f>QAm&t>FHlo0sV>*4!#zV}i@e zb-lxBEPU^m(Ju7l{YB27)KWZ2rI8%u*^Xv`&pzTyDr2C^LJICp8ltRXiE@^0SBPeKU(R7G0<7;jn1KHrm+4!SLWhQ{DKiC-_Dr5umC5@ae-RkEDAzTxa;( zu8Tzx1PR2PN(hyfEY@?qE{44CI05tJ(eZarRJ(ShHMUv{XRusD>%a zVA%O@l4Yf)uiW1j8f1!af7N!2dH)_mVL)dSv80?OU*ubvfzWNhD=;6oIikI5FY+T_ zIXhF+iv3&5O>6bLg1e{38D}+2H(XVl1Y^lO!7j9IHAtDDoS_~yFTahI2U;CWvs)Dy+h(K^oh9;;%##XGqR9XTV|c;1ykqa7J!T#G{TUF;zyqP zBCp-F0m0JBViM(n{PF zqG)tcv)EIO^yFqqJw+^U<1_$a#>~mOTfy~f877j81UVk7~tp&{bP@! z^D$ME`tE*1n=Dg<-v2l`2Ln5G+*jeehy8Tzb+>F!_ECFGQ9U2bVkrq7(9wv9l5?`z zv~AT}k<+nRdV!es$PbP2@XVW*&f)zknFK{dF3v5V9@G2r{qYu z{dxK?9kiib7k*?U`Rh-J^?|nPOIj(f4{p6@UTuRvx1sA4G2wr;S8Z?GHW2>qUvUEr zSPGoJ>|+uq9oz;8P+-I2epws@j7-N|DAFS-J6V(ez9U6Z6fL_2+6jSUk;mtrd*%7; zV!c`q1`AqnqG+a#VuiUg&ugkD@AK2aK#-E^H7O`ua=D#+}ds{Bv6jaFvXZujYJTYA9uz{l&)bI!ct?sk3J3RwT$Es%i; zemN*AotcCuqDu^@d1CMtTnXW0amU#wa(UXT@cKH z#)X5g1Hi}PbvLFf!ffd6?pm=8B7vf0Aq9US7k`2}P zJs=hBpP^S+DiUB+fyiw@_Q$L9F~l8jSUPFEb2oGiG4{(0~jyc@$rP)F1RcnPqB}AIoCTMh1?3jH&qF+ zDF7vTeseI63yP+cOkhMy5Okj{0(g0W%tj`;d=vRRM>kvhti@AH zJ7uH`;^~KI~mk@s$ zHg|=OJ~k8U-7IcSHtJ4Ytt!AreK*_?{V={X5r^n&-;eiVMK?n~T4?+Z@5!Fmcx4XZVdh} zc7IP8qWgb`avzhZl;X)XeqNL6|G7a6EHUHM(*EeGBXc-<_=8|y=!T0%*`zmW>3uW$ zG8#ix&p3HAheA9X^)=^63#PN{k~kN+>^o^U51G(RRX@jyVHkV97NUamGaSvwh~gcO)Gm@sgQ9l!;)iX zwnJcB|NE}<0ZE{pA5gIGJ@=e*?K_&L+cXGb;F1}j))~Rw${kX$L5hy>a?DoNI%Y-+~pQc9a5Stiau~zcX2_-#u zw5^QK)>7~j+0}}FYlWT4xTEdVzfIFmIAlx|G!joB z0&6nGL2tT*r;Vr~L3io#KVBh^`&ufw?)S@5eR6BSWkzANb)z=kq>8z|sGe_yj14Fn z4GA-b9Xb*!+~wyiyA{!&Zj}!!*BZ`sdVJ;x4VBKrfw$sl`D^eGx3?`8;|hN=Ym+4-$w^At z|GtxKC$@1*VGr|zEa`r_uixo(eN$vb6s5=|GZ^T-5wfd~KOp5f*{48@+?jYzL@RPY#4)?An z`KouVou&6JjDwqDxJQ47+-XyLxTzfmW(<2tc1-?G4D!-gv8}ZnAT4$G&x@7MM50P5 zKLFDqEY^n#n*_V$%tnwHDAm@&LO3+E5_uufC&t1vXT(C2-sm*~`n;~LV4gAIlkcTP zxt4+-jU@@!idZbUivu8ljMy@VV34I+$rs4Q9#a?*FD0G@*cg9a4{))8c;qr+&u0Mv zf;2M4QEwWu+i?H6%;+5`+`(IH#~r-?PVO3Qz?o9o!5V$EDKHBRWSyVj!W9&vKq(Z0 zUjHI)E##$j;7?^*rht3m)3LQgAYUC`oSbzGQYkmnKT#*rhMrEy<9>iuu3!pn)FkR) zhN>&BlN`Ki6BU2g97trF@fB>fNP8v^RCve-IQSPX{tG7q+#EUTtUByfWB6U3o>qcW zxHafXqsT?;uDkbTR%0#)Zw$|bObx1-SO^RT)G@WS-tRvqZ&@ywVR>b^F}XB|GZ;0x z-*sRoTsCi<2p${{l229P^qeB|aJyw@Fx=zu#$+pwP``g~hEjukW4jIo`hM;zxb>;? zNBT})`html_Z(9fr26sGP!E0rT+1?7a880XJwEV6n_dm1BZbmPvT z^@0%v)r1Z*6Y@A*RNZD$S^5+G1-B_X7Q7jMwN=S(+b|Hl>njF90!e}5bh#<9)1pa% z0!K_#NnPrW;vrpQ&gQqcnVNE`;ZUJxyMkIPQY_ zf7KQ;g&L$X;Hm;{G-x;C7%EIS@nO;=K)?Lze+5MBvC&^V_jP%GUICuNHv(ii9B6W# z^Brb0>)42D+e@!gkT%TFSKFkVYfXh!y$=rIx^co7G>WAQbEvpLQx*~=Zk;xN=r~-= zs29aP2rp)q`au|h5B2rPAlZXiW8DQ}QjAiCGIwK2QaG(=#TS* ziPy8I9CP9_td2+){MY?$a6%)W44sG7w$;M?r1zrSQcqd)K@R<(0) zU&U^ydc}lw%zglx3oC`OcKt_q$fcKN4lmw6x0qNK!~}npQ&DT%Kn#BOuMnoiPDonz zns(X7*1=$Gqf6fm<#Lwe8)uz4otuQM|GhdpIBUj6rw0r4NuNIHtm`*z-6lzi+A5DZ z2XAz^5BnDR^{dHMl8|bUTcr^`TDL83R-cQToyIm8M*?^J8*nTB7Ay2f8n2GnD$@1e z;)@FA0gHb-lJXchP*ff1$OzneL!pvzWk^{NSl-vXdXl72?&3;J(?fp&&Pyl+0X>ib521kA{Std z5Lru5+{YK7VCW3Bv$74`DIM${91WQl*)z@yNDE3&LfKc6ij+EQf2~q5ETsKTp^L-7 z973(a5RXY}ZSm0cMfBesvxzm8ESeWDDVf5D;op?j2wPJk2Wio&dLNUlw&3e^E=rFc8Pz^C?c)LpvtJS2s5iR0MsQ zzHLLY^x6j7G$iRpk$rcsO;_gZ)I21R```b5cgb|FQ_Wa}BI5=F>x>lc-BlXx%~d#I zOz|A8<^tg%D|V~9bi%?U%e-Esrm7+y{57F9BWOjoaCaOkJZZat#E|qYyP{6fD6$Re-knt3apmv9Wp*_5Y zZ6Tv3-NV&O#t>XI@yi+J+Eqaq9);^Qe{iX!XiKr|%-72`AvL*^E@997-bYJUXr$GQ=kP3e-uG4 zj$t#@SRz7`0v9`Kkbm!xl-HUEEwjFP^Eke%t2)aH*LR-&z`@a6RIS)w?~fOdTU3~^neNtbK0~aE3dc{S^+bLHH!_C9w{^% z_Ierg;ER?LxwBxX0@#WfstycZf3N|eoCd8Bo|)rSAFL)vp|^^#B3py5Qzx*97Lf5O zrr|5&PBxUuF|=T+0Iro2rPtodW&n>Bg3@Nqr1*;kRLoW&EI2Y#fm`x{^R>i&%w66r z`}7!mT&CZvo2wWDGil%=Z5a_)gf-K&OiDH?izGj9v z+plLFRyKuB;JuC6hZ=O=sPov?J-j$Y8HUXF8L4jf_D~~cz3uT6GPvI`lVmXt>QiMO zq_A%MbS$eWVT{G?u5~y&f71kJ^U=X-d4+36R^_D}WqZd;n<$Sw!U9HgMoo2(5QQUF zkbg+7>nYb>xx9NG6Hb(q@;Ey2yk{rB!y!CVi6ROyjP`<%F3_j4G+44g+%4b+O_L-J z+B?vzr1=;bZv<_hK^pC(!EW5Uy9w+-CsW=%MV90d=<2vi*z0MMe@lAjtt|-bda74> z%T0H5I?tZOt2AtjyjdV%4vs{Otv zY2)X;l8#50(hrJgl@x#nar|1*ojWho2$TgV+(NhsyS{xG3#dhQaw+@FcjSVD?D^aq%yFkv`7e;IuSO4BICR^7Orji zgHlEP@4PgvlawI5Sn{3k-JN}RZ)!tG1za)sP7vqzh*RW$}-X&?9S0H7HJ5@Wx|IPyw@sAt`%wo?voQ?Kx#`R@dlP-X zNBc+e1Gn6O7MTNop(!LSz3id1g+*dlNPD8IJs}}CnWh$w6WILEP^>|xE&uF+z z=(y0WgS*!VbHg+FcrRa=;PH2r6e&vM4z4~1JTMt&=^rM43jB!@6*HOYy3qcB8&oJG z{CuWsQ!BdqzbRy7`9SB2OS2*KhD#=Z%G4TGnKBqZ6w;LfJk15#Ts1i3$`B?drT6Xu zt;zX$wZl2w*?1lMNnvRlGnU3NT(d_D~zWv_Iq3c2EM*tkrpJulXRN5_Ppo}x_B z7>daFwWD=^Qv8K70fj8iq$q(Y#Y#&T^!pICqx{0{Uo)V%%36nw;N68!CUBFoBnx>W zGljsYsio$6#_NfPS&laLKLXM`)0(dZhE#FPZS{e|xR5cEhHNQykn2o3D82!IV76R` z%cd-t!?c~9U1qDY9Z1|kp9uXSO&+w3PYZ2ejgU}(I}9ocW)dy~NcaoN84O_z9~tRN z9EkQ_{oA7r*UY(+=o$_P_`|Xr!xGWMT=zK-V9m z*^#1xJhsd#xU?^UO#JD$R>gyLu_3LKvn+&Y*}07ImCTn{o-=M}+AP}A z$ZTqVz%+$36K%WmI)b{dMNI(LO$f{mXW=qMm7w21wdm~HZMi@qJorXgA&ozR<)S;q zP7ZdJ97TNa(>WL72xQnZcBD57Tz7+}i9yqdi;Gszddm!#vC8r;>c_x+OKcynL4$U3 zXw}&noH$@ib5r`GZk7EN_Se#<_ro*NdT1?Do|Srq&@06NYGpZ|>Y1v!W=&96qP5^F zl{W9WKh*Suho?F`jfY?4d|;(|(fAIijvym}+?M`$JZ`$OE=O%qHP_QVCUs_?AsUT! zxcA=P`wN#uhZeqnO>f&c5WV|X%t3{vth{b6#lm)+>=x~Av3qKZUXmc7rLja*A_bC) z<1O;vJ0xX&MKLNEmNXm==e>C|+FVz8HJhcF6ii{LjpB)UFvkk@)n&Av%>*k^S1dvJ zSjfZOhp+$L{Z%L5(QuK`a;Pm58_G4?k zBa$fSo(on0(WW*0!*t%V0=%pWw6Ha_#xI7F!R$EuF$20N^dr54LY7KV9N}L)IvO+t z-%pQpi1l56UR=04T)<7m6f2?N+H6`1wh-)&BM(Y^a~VU)p6seiLch1b8^5K`qTUre z>99RKBvKH%Ix(Slq>CxVj`oPSHND85jvF3x#@BL%3WD6-&p1wr0|Mo&XSP`hQxSqr zxK}Xuxy}8y2!6ENmrJ-QStb`e6H*~CD(X>lz2aVf!3$ZTJ@OYel$F$)?+RQHiz&B^ z#tPF~q)ZsHl~fw8rD#L(J%oYDxn6Ah+`$Ge`zhMXS%U8zoyx?gd5wV zq)GyRq#K{sRiUYs==pj~+q0_m`SbrV?8}6r$4&d`FJxjFLZJOawCav}IRf|t4 z0cU-?-Sc@Abds|R_IgGoGNscVZNmCX)Fd8L0W|DlYCEt0v!{|GI(ci;ytruIl51T-J>}N9f<4GR2lz*mV zT@BKADKzF0f*}fbrh~!Z$_r);rK5vFg~V9YjPlTr>9E0i8}R$ss{fBDf;UsbUr)rf zGH5;m;rxwW*k3x2Putr86E~`fn_QxaU>-2#k>20lTk4hlu1#Y>?`OT-`_S)sRD&gd zu%-ooQ`OxEik{`(+8u?|`UY5GC*%<-`d(p5HX02y7-FFLFMi?f-KLNLoix$iW ze@`1R5XbNPDdw@2l!&WNC; zASPEG^Qaw1`C^vK6<^~xO_}?4Jv(I8f6rOTMZ$KFE>vC?T&@>$qSLBzwh1A>+E42Zc8|zL}BG*VDD~t}@ywgw+?U{B3 zGsm%*!)V2Eb3rkZv``sNbe+(0(q-NxVouD>xF-}h<2J98?l>Xa=t*AZ!oPkd z;kwc8PvG|>DZp))ud_g$}vO!DkE5hc4|csb~V2m@~k6_;kk(vo0RK= z6Q5R|;bkSKvqEDQs2z%BKyfm?@QXtMAH2dj(0@ij>0G zAexEQFx!qyr_Fp0PAYRae?UX__sx>)OE^sTd*<~)ChZ*Wv~$=&Fzvj$A-1gr6?Usg zgwa+Sq}HXug6o12MAi;l)NWz+^7%gXxGp+2`j*44=xOst2G+!r>bg`#IY{G4kYkJe zo+K*`vYOPgz@~l&nT<;j>{HodeI5s)&4U_14iy~BA1X4zU_+o_f8_RUwDH{&C*(K)t#qzC`~4?S1=qKz@B3Ge@XU{@5ii3># zd67k zD&>S_Q5x#s=h2iyjRB3F{I@g_DTIA5h)44{DAMfmG@U15luXRrI30buJiE^eHl^=I z-rICEpR%L~iYQGkcME98)x2PKIuX8Hk-=RsoyBZ{Vuxuse_sgj9GL3`xd+tXSEB?n zcQ*;*`(Mhbd%@`1nRdC4)Fe*;D&+nFAr4w;z)u4U$DFKXn&Vx)1W9Sx=5v8?&hN?IuEX5Rtq~% zMtrJ?f8*M$ig<_#-I`P`DhZ>n4dbHqWtzMvIpedaCaWgWm-kU+23YqGOZ04wme zsrIZ1!z_+!JMnA=-BXNfv#IxXCzFg#e_$XsfXzq6JZlGN9am@bXJePPBB(ZRUZ3~lb!FNVi)c{JwEq&GL^o+cO18{61sUa| z6lUlqSk#ta1y0fo=9V&>Df1{Oq8oPd;l!a>Y0(Z78%#-2UJ=Do?&aX0^NMOHf5YsD zuw0BrZa6R&GnVI7p+882>f)Ryax8MAk^BWsG8(P?lCf1FZF*=!7=f1Om6u$AX3h&JzWR_!RvyGTI5()fmj4d}~Ac`KcX zFj~h^;+n%N`Cta8F$hK07a0fKS6qlvz@U6KW|bnKt@RJwAbVU%Qh>`8U5L#6M5s5BpnkhIx<#o&Rs>;C)abf}Dn{)K z5(;7m+GtXq=iESGpvKf_|K25n5sq%W-3km$K8{ zi2sVa?X)L3xPj>l>QE_de+AAM?M&UU#Y@o1-@@SH8w@h{h9)mii!Q1x2QlgLO%^0j zuxvq7-Z|vuW01pYHmOJPhc@}j3{_;Ywg{vvk%BaS%-_YrPW4VUT~~W?eHkgsjxTREE5fbICVef5ji%;}|4Gc3(4G zY74^L`KWSYz1~#z#|X^kvRTX%FX?pUjbl+?$#)#n;;tQ4Y@{1!0{W{v{~!gWCl&zo zy{&*+t+Zt4b@|1$JBKe}E=va(@WJTgjAaq+z?x#96EB_lbZ~T8;+jr`)=yCBE8BHJ z$W|!Blw1tB9STi^e|9J|7Tcjf&f9_HZd*H~GVDnRDl52~47hvT_*Z!#I*#?xnm>?0(3Me=~wo_B5E4(noQS=k6j5 zC~)VL72MmigUgvxf309cP=~P#mU9fj&^u~KG%o;`%;PdT;E}5|BwvB-R#V3)S=D6a zGh!yDSN~9xxtX3D+w&^@AE4ZZAsZ>(Z|A_up_&7TiZtf?tIxjr^2=x5m)>q1fnf_% zw1@WfaEueDf4}ARi6Jil;;U!>^;6js%b$|NRNv!{Q~mzl@#&!FA=CQOH>%%%yL-Mn ze0REgIN18Rj70cm`9(U5MtyG+dJa9tHhUi9Igq9a+H6N~i`IAv0q(V8I+a&k2**Bm z6MC@RrXH}jz2_rJ^Im!QbBnX#*}tB7@GoPau@jR|e*${zyJx>X`?q70ZstntO4u!> zu7_D41_vjDQ}?&9TB?Km90=jbZJhA;+^Ye3~Vh;!Df02G#0o!0}7&`-#f zJ>nkWgj%J!k;pPZxi0Dp|fX^)vHjk8mk8%&rf&v&W}$&E3q8ILT#9( zx4DlSf4|;~7cZXUFJQCfq*RqbE8AD)o{B{?Z;_1Fc!X6&wFb~v^OR5IYz%`)Z%UXmu;RK1`Areu%cppx5bXbljJ zX(7u;S#-t1?+BwO4lZ)9NU^foe+EakcP6ahPSWSo+1n@sveBn2P2zhGb=`GP5L;K8 zf0tJr*u;bd#&o+*AUMut`*o?i`JA(g+!NMv$4j&@C~Rj`F&3UPmB7*4 zP`)79q@!oxN56b(;@IF5(ziQddMFh&G?b z;43m7g?MyL^F0h05Zo)~2~4aqOf)y1f5QY9Uj?I2L(PzFPk$#_mH1#V;$UHktUC7? zuHkCN>^p&4bG2dkiU}ANjz|Fi%WDb7AV-oUlrwj2dsyT+c^4&7e(kDhJwwfwcA}6= zyY3nxlFdvu<=$+&WtF@pk7mdc28)tu+tayDrfn!6NfWp%`E^jYh%8sT*MZ3ve{rgg z+S!EI?nwc^z))F#_d;`g&1JMURE=n>*pB2?W5v$*OXWMFc}k8BKKFORZHB44<{E z7j4cEc2l(&W};lMVdfC%TGRZge>ag~lGEQ`$#tKx3oT5|(lw{5iCF^ht(nx|zG{l( zKJEWl>3yTYJ(EC}?MV|{loa28-Seiw9ax>yC>iDezWzDj3Qv<*IJ~+y)Px@6JuxXf zD6bb<+|8#+&wC9dYSQ%5yL=}`2=Z57d4HY;lXN?x3rAp22Jw9!<^70Xe+k-7XJBk4 zVK17_(mapA?AjhlKi6KyLi7bs3P_VaVMb!iw}3egETEOOB2dl<-WOjOWPkt4dugij z0`D+U_t#xj@;47buTSSw&ODFMOy_xl2F8S(kjd&uyq7(10uq~m!RfuwbvkDPtg*~F z-|Ps72U5R}P71#0k*%Ipe?@gkV@gz)(v;VT63GiuCxoOy*V*|NBcAI9u7B<^cAM1g zDNvs(6-ck%s;ZJ-h4D=!9TA_43rE-rHk{ElCfl@Qc-%O|gHNtCD_3iQyLb$(bLG`s zFbl=E+LA00h9h;f*aZW<@RHPR+WXxcD^rKe_;^K$x~!)iD`pd zZzZlgW&gljF`8%GC$X!(qW&=I`J8*nB=a-rt%RKNn>$BLlhBX{I%=`{rkZIE6~=aYO!(@);NvG$#lc5xQLC*mlly!hi#PoXPN3XNvRGehm}&DWOh;FEjJu6A^Fm(& zPk^Bf+(2fOy4I*%>`!$dbt(DK`)YW}bCWsVltVl9o0oj-e{pAfP%`}QE0NIeqhN{k zi1b;6<%s$!w%e+gY1LZ9_IH#!h40E39G>uEZDL*uut&a`)9;J6s@C;nYkCI3y$S&x za6K=8pzJ?`>!Pin2iMd86j>K-{VceSblC>MJd1j3=>~}q$itGGx0|19_mB}{Rm*tul={)tNd;bgE9!ovYJI&Cog4bt>M6BUqcK({&h&PHC_Y!+pcm z^uhL$rBia5*Yh}y59pYTYue-!9?@$D<*H$1WcoHLUVQycyCPp|-@aE$&K6=@#@Ptz zf$dn;iyYrXu?FJ7gg-iacYJziw;&@IUl^|UU_Y6zf8A*R!e2bBce@=sj_uumzQE+z zZ{ao(AI>}Kj67!mlt630K{mQ>1(Uujx9L zxnO-&k3wC`K*KN>Ou|AGQp`IHW?nk>(m13gjQ45>E2i%qa&8*Te8m_dL@}o9hF-^% zGMuk4Ey4%6K!3TRE0F8+jnfTHZ)FR49o((O>CECwkPZ$L$iK!uZtr28(%nXQ+qj)< zd{sh1o4nnHMWb>#{Cmd6e_x}Mq4qvaW8c~`0E!(Oxzz?ZfP8_W%T}E2?H=r&4&PlI z?Vax*AGNPW`POr8twu+*2W~A#iSlkZ@wqh>I^lC~sDJ5*%iaHnE~=}67;K`ki~!!= zQK)=NK*>up_X1rN_w~rhq);xwdEZMD<}vQ-@6Eu}Buy73_}5GER`v@a@DeD>={Se{ zbI7G5Dst0b`8(VNGU|nF7LS3|H-J6L+jfC$qX)FDsCPAeyGUn9)hjDByP_&KD$Cae zx{?=k%YS!@iWLT@K}ryT-x+yOl{%Ey2bSct0QE;=o|X{+TywL`^UXqCn5H>hm}?`J zU#oNUIWOHckztn3+DOEEhK}*ef`P-D_#?=Ia|dne+@^eHB`lT zxzy(_0`#4f1pKX%L&?5?sx^NBld%90b8#2^oCf))p};RSvG@r>^V82gy+Z?#C}&^N zzfC;Y(D!8>=NdXw3J@M~A(qZGVk&L|R+jJ*0*IEk1*;Ux9AATfmL^vW@yVN4eT#KG8mR#H%kRG$~(&|P(o zuI=#@t8=#ZE}|PcV>nW=NdLar5$QvjN`J`f-aIbR>SmRlDEG0DK7(;O_-ak3o7D(b z5{kt)X`YltPP*669#g{h+8NX$Yr`=H^?V{tP^q_ZprHY~g2;#(I7)@9bKTKd8>{*J zROg-1%$3InVCi;vIA>Hd!8BMN>ZaF%|K!4UX z3`MHz)D4j)IZDy6YnVxSzQ84lt-#6EeRURNNxc@99I%{nO7Xy(cwuVYHMr5VHV30F z@B@l=!$kiAnvb~4tQ};%re!MM95FqOrt>D|{G<@Njr_}eae!WJ?=x}Gtj-hl=^p;1 zy#<{Kl^^Z?WuR~JmE*`)Pt~1Zl7B6{4!ji>BqNrNt;)RD5};oq0yXuSxUs;`EIa0C zp4RbD0?PZ800>mW=TMm20j|J4ICf#z*L=3RYvKxj{DSxl{Nj8dS z2WrN($hDYhV(Ux{ll0a%ABn2)86TDz{(=V&uaxVu1ok&C&i6L)TGo;4;PVI%K2`b7 znsCKmLg2&5+~Vk&DHKX&c!goctn@iXpf=M>T`k{N@Sb1EZ?8O=*zX?<-klHkkM<5O z&i4Px^_O^=p*m(nhS*l=*?%>gH#$=MUX{@_*q3RLJ@8aQ7qk zCdBF;ZiGaYQXaYjukBo5;T@M{i><-ArlA`~Jp63U81TKAn5F0d!xH0)gb0nczU=AQYp(Q(Z%03pmv9Rv)}~wvWTB zDl^R3#ZbNk#2W;5v44h;*x-$fDYd%e<_&KvI}_DGS2HZ#Jg}Yys$+-+&BI>G6A>gfqsC9ALIJ#g{x1l^p+FV(hDw$dpIi%XYWmI4}zt1OE7{N77PJs;#n zsqx~>9gFh1DPTtK5@;-}+DM>Xb<#+@g;k#YP(%!+#DQFrCVz?>@SUB$VPr?zN+=x* z%J-=pXKx~>^MgSojjC|bMls#p#8K8-sM~%2{&etu_k928eN9Ktlfr*(T=_38%c-9M z#?{GKv~*l7RVye}^aO)>Bijx!z&^BIpG%^eMTafAG4Ii^WCbi7OGi=0=tR2>xxP_@jod(M@t?og zmwPN2T`MQLbgZvWg5j28oH3}0{Iz<}RjB>2S2zUv;srS+5QK+gOm@&42Bs_PUjnPK`55GR}yl)^c+~|MX z+h800KlV1p8~s21+J=)(r!Y2?O?2(2Bp(QVaYdga`s68$KF1GB;DRP01HPfpKXA5K zpR#e~oNwv#kM#Mc#cTXLH_PWFm`z*cJJMcRG)YXcjYm7gg5tOcb5m;?(TrX6@;`9Ti7ummPXL`fcnOf^@Y+#!7;6k$Z6hWIr# z4df^<_lDKriy9tmN$Oq~02gdSLu?z>$>;9HQeR++F$ZJ$#tz{e3SYugR zS%2A}23?#dvGy0 z)8P}%XNYT5h7DxxSo1o%+m=Ch%#uOq_TJ=H>VViNKV8A3?tD z&Xt=}@IU2A!4U&Ra;u5Z|LL4zaa5L8JAd36pInsrjL$zhZh#<`jwz*m`MNy@$xHG2 zrQ-@J&*+-Sk$SYbjZ*!*v&&poSi0_hJl<$$D!mBmVk%{HO{8O$Qrw?1MzHxJ5H*s93gv6)VQUFV&G9AgDJxU!*VMy${NAdDGC__AfTvSn3HV>@>Qh&AG zB~MgPYGtlVaMkIJ-hx`oVT}7WB{!ajEX&et2$pylqczv}_9=aU$yFka%oV3AH&OYg zXhwnHO^VJS(S0*j=5#^}1uv}f=Nyx3*rW5hyq7g$ck04<)5+3|qB$gur%wV8QrLV- zHK%t>T6{?4L6r(jY(C>%J*YBseSbx+O_Z+MI=$+Qu~WJMgz9}&*0!)rd)&ON2T8}{ zoE0jdob_~i4L@bJ$xzKg=~}}PKLsy8Z$36L@weyTdU>}BvugPC+p}o>Lvs zF=*usfCJ1tPXh>3(rDxRIE92~L0HN!clU+t6 z&3cZ}D8PpoqMRRReNzuM69UcCAkJ&KBY(wC01mZF2ngQ`xA3Wz#dSK*ahKUH)!QVl^5CW1AF9e+ zGgtFilG}3-)N@wY;!GsNSUwoP9@NcajN)7=rye5OdC+eX(LtQ}-a%*?zEKKGKn&JH ztP&?CNTC`0O-0V3v=8?o=lb(&`Avj?3xgT@Rlwpz!pI6qM~wtfaWcrh#Jx~{`$Nnke2tOeu9|4!e85I2Z4?Dh@?0w!v<%z}!B5x}4Az$PK%~X{EMFaWG3nJvdE5QD#rt_a?)V)|#B6-cZ z>oW7NqSv6&b(%N%ZaeE5pGS2PwR3_~o_?SB-Cuw{z9NzL*Um8gQ6 z8&!d*0H$kk0Ey4|pgRKyY!;2S#SA3EgHX6Qz!xNBJktp{e}4*3H)m;112c%d48*!z z$89=~LlF%Q4@B9~(FCLtmwzMcj zujCNGah!y2(SK=%2=hg_lPzM%R!N|^%F$Tl!xyi;CRGUnWnnF=PD3h{y#4gE7>HFZ z29P>2&_FdgjOdqqoODy6wgw`Gi|xr|{Pi_=j@4syk#!K9mH!g&(X+1;Q`^ z)FmCPjSzB7msu;)(&lIupzFbe`O4GG*y9_^_d>vqq<;vyJ#Jj{Z29e#O6>QAd5-4< z9IxZ7KvZZv-h;6=U|>*`D*E2{&WB1$g8$R=By|FV$+Es z3*59FFsDl@C9j97c27mR2kRCf@=}c50klNM0)o(O19;`bU^1y21QqvhS}x&#bZ_z) zBjfSQiGTWZnP2nVm5wjYm~ke+g5$whRbhQk(zU~R68&>tqat(t z-VRSr2YZ9J(0N@Dtw}X@Egw&{qIFGMmNlVX>3`Xpf|lctr*-e*^mK4^K0H1Cv6I*N zU_7L^Yvb&@{f35mZw(NR)QbmZ{K zgnz`}XwF7A3i0e0-%a9s&(1*OM*_~V#ikeR@;V9{(4k7rrBA+m@Prn@E4tQx7#!|e z`iH;Rt!XI}fjWj)Tvao?Y`K7=srHuLN=^7MI5;Uq%O#|^SNM;dg6Y`XgDOHrQQRAf zlgo|WDB1w|0g#j*I}yckLqwdSxGoGlZGU5D*E4yRQ{Bj?y%ytPmmB*x-d$f6r_-EfCqz*T`E%Cy+0Ohks6^jBUu<-#exzETU&QK0~YfPabK zQ2$<<6zr~a2B@*nfe9x}6C)^CZ91ss1iMM&8(gd3XrlYxK%}acIPPwiK~`Mn)l!%f zPi^{2e0J{ySRK(3ZH(fT-LMjQGP#Mu3QTFLUEkbUOFq2^N>h*8j*<7!teJDU0}kAw zPhnXj2GA=HYZ&rG{dfsQtn&W&^?x@#?}xMFqv81nSQ`%E%i#3%_*87OS5Uc+Xe=ms zYGCn?#|hiz2U%tC#wU)%t=8{xGOjq`>^!)W@lntsSowglw&NsrdAulp%lo#6vUW@C zWU9psS+p*;DZXJlVcC$^ymCC#vK0sD1!^UO{Lq;jKk6k6VgA7UC0k*&T7S%2`0+v1CwR3$yH#ErE!)2zAsrjmZvr`wsCnwYCJX@Sy&4!KSkqZ(*PR z1s@+8d+M5eDVvAuuHV~`=Yt}B)VCL=^ z(HbKX%_BR@YKyd%h*BikW=By*O=nSFeTUI%%x;!f>az-?YCFotvwuQQ;Yhr^05lj5 z$L_XK3?{B{@d09--GrsO>?Vrr;~Yh16sbp!ADei0grG+-d3~+ND%`DaY}XO|X=<09 zuiDjBD{xDJ0zIy8nvxeRn_5|gdCG}-%?)mA>~Ggl?AO%1j4pS+=rN6}exg9jXITe~Y@PucvtwRZEz=3f5zTXphX zCw=^Jp)PhoJ!ZvZ+hyu;Qp3JCVve2LYa%ajl%l3CW zXKM{|2ll0{@=7qq2QbXjL?`H1%FSL38Txi%a5OKFKJj>kFn{;RPbI!5pLn8sn*t2$ zQ)j*jk6Hc}y?()hup}Iny(Fz7$~oC2X~&{_NQP?>r+@5x2Z{0 z+4)ayDPy>mHJi&AFs038wqX`l&3inaU|`A+y}+%)er7l(bIF~>UjFk8caSF@gk_oM zhg|adn98(9jep>%`yStB#>SgHtE~6%;Qh|d1G*d$^a;S#hK%U!aatV4p^va|S#OWd! zy|M7pP=#IcMw*~lkNqIipALrhsZp@fsS={pSs0Dt7L0#iteFP9j{b`pm??KFpH zl;^Cl*(Gywk794JG4YF>zc(6usK1J3-e%|8QedE4mmNI|ui5tldL9)-M&cr8eA6Ujtc-c))NQc_B*VpU!}+||sB z(McieC+YSW%H41Oa~{OeIAY=UBu=k_cv~ufdVjhG(^+wE5!Wy&U&=r@)+OIfevQ}L z`0sqf8wE*{78rXPYYORRGh+YOudt4SiJM`4GR!*$;TO>}u#j4aVbK@frd134e#`F> z^QiA4Y&=)j?8W2-_cX#oAfLVolWA*91_F`)E)uXZ)A)vkO6&Fe*bm&9o5w})4YqGJ zb$=|b0nC0auL&M4*Jx&!WxH&8KMJ`#Fq4SO$6~GXU;}P(fGSa!jz(9(Y;7|bim$qX zutY5|p!P@Xie;0{oG#ddeX)T>HhSLq&nTcMYq%2-vq=#1bvKXtU3gQNesb^ixfI@f zKIM|zAS`lCPLTsJcY7zwk7;xT@i}cNSbwtmx?$=z|LIxVO64`+XO7-?__Rej7vlq) z$z6YWU=DN<=41aN$>*~fhEWd{!Ac2$jg@A6#8=5!V0cxjRFqb;9MG~u`{D)7a=z^4 zzV2`v$YyYV**3Q|PrQB8Ajx<_Y6@}r#8k`g_6{8NzfR>iy`PBD{AM0u zB)PgPNM*QAE=#jJHkwn%kNEuq|9|yfnvA1~_k6_vn$Bmp;*x^X@l0m=vLvW^j;r4n z-RQ6Q0CUX^U#NQp@~bQmWjnbtO_+WDRvmn^NvW`_GYW=RQm7;)wbE#1cS6#XP18)g zo=qO=_!C1t)Y4P|>1c3Z98ip|Cny_;ghtvNK%G#BF9;6*kw%Fxo&)>=zJJ$JRRZXa zqDhv{XTz&|N!5G&{pP-rFdL>j+A^jB&`I)6by6dVRXF=jj#x5sJAM}3q%r^&E-JAY}?`+c90Kp(l(`%jK*2*jMk25H6glm%gxPq6qIL0e%(kL;y$CtCkt4H!KPa$qTh zF~M^FVwDQ^C7*LWrI(a|-&jeW&a)8{k;v3m0hk4V@irQ^~>SQmoJg20=|u{E-+uCTy3Zv9Php@34|1K9KqEsTk%R*C4U2Z8uKC&7!@|N za#7UG>Gz=uiP1#ReCkf1w9wSVS|RSxRHP;O4DW!^#t^2%mux~jS}io`;N$t}?%w%v z4cqtYz3~-cU6o1Loe*ahkckx7ptHsNb)WAo6+p!xaO5E+_@`pY;W#6NSXjaM4*&dn?qUa(_IaLY;DVtwc6(J($fHz9ZNLqb2TkvUdrxQ-*#9#L!j* zkMK)DWigIxPN5w|w4)-M(?j!yx6FD%E?`iHbKISAM_k}^sDJ8LGadGh4^MVa_s{Hj zH&F&e3r3sbcazrH)&I4CLZ0jyG5t>`?$Sr;WH7f{Z6(B;E`qptb&Gg zNNWThO*8)Jh)ROFcoSAUE&nS}B=zIvgu@A(-^1DaCs zwf8Ja!DNM%Qzuch6d&|?pnS_+RgByqU_^DIk}(eD{_*Ml`TpQcxR1B7k^6$%jI2J3 zfz>Dm>K${tcHbZnPs{#a;xj0^kPF`D!EhMYS5d-3#dLK*vtoDjEJRHMghO^b)>ZHn zsjtWZcz-Q}U;3@-b`kD2u@qY^ra+oMl#`zoGi-6-fEX1cVd*fB;*h{C(hhc>K2s zkQjrSBj3bLCZj6e=&FmrCTI>UB|^N&V(_z}41c-9N>KXI0E{aHf~D6E@Yw_Nts@IG zrMJu^V*aZEGj*^bVN)&}XVv-%4O0wNS+}^^_9opI|?wO+R29#7kERsM~!HEM~-(+LKnwW<<_IB&`k%i zrJ(otK->P&`S5W6$aoErC83$O`*Gdu!GBt6c|%H#2<#Cloy4ehio`?tk!s#O>ux>I zI&+AKcuz&;N&)E^6|FnUV2DCO?lds6F{I}-ib21!QJRFgkABblBGY>=!FU&%v$D+D z-nsXF2b0H3)U8J9l&89{((ES`*>G1Jt7wgAX_1Xn787?pizpvm1ifjR6xaDz_kS$N z@+~~4+oWSUXv7W6NTH^l*{~PhdklEFQBh(qcmM#F@JNEP1?~WXhQqCWnJ2i)(|BI6 zGhQ1AhsmN4tgLUog^xeIq>nA{_g4OOeO9DWjl|r(D`J9E^A(k^y=^>6-12-t6{U;XWgAJBpf`Go>j4&VJ<}ty)a7ecZq0-P&w$_n zkIuyVN5*Rj{LDq|BIAaUXFjWt>Tfg-U&vo!mw$C^!%LXjO}9hbe*l_8a1sBbZAMWk7#l{dr>0ue2GRP=`@eP!!n~*piXt&6;-qduL?FRvf2r z^x%u;(_Ft9{rk4ct0+1MUN9qK>x|@X=bB2`^_%1_iWDn_tr!>ZxzNYQPv7nzKg&Yc z#yU}=ytaYl(=!*9lUhCgr=D0L5ARJ@mw!UJUT}AQfIdEG<;1faOKQcvrU#J9D?wlTgO~&r{!On%jw^pY=6s*KC*owy7<%1=3wsQ z_WltucjsbT8L3=~r&6g{0Yd~)XV;Ti;U7{|wmxXiR^FoOk!-I z3FI{FwaY;&$m!ey7^H1xG5b81Du2VB2P_1tZ2+MtIkE<%_1>T*t(T$7Q-b3JvYHvR zE8U883X5B0BQ?6*RY;oMkR}v$JqAiczmM@3b%|L7t3xB`h9nO=>Vpzb-eYgtdMie_ z+IYoBT^E!QBpgrzC>Wh0$Q}g}E*spRxm?=C<`e>~Ay(oD7cCYiNso#LI)8+9Pdb9p zk}1R^)x#I+3d%m=1$}j)-1WGZsC`b7m~omW@zA$0v;Li|u-dxthX$K797Q!|Z4Ezu z241JyGXPz04=*-UGkOk1TWp+uZwzawv^I!;923?Id;0KE;L`)*K?G7SB+mox6w-l0Ld7kw{?;B>KtHBWKVl(o8 zh;^}{OCT(GU-VGtdJU>B3i$myw6)lj%%O+&OrfvH1u=qR{TQ47NluS7j9j8c14k+n zg}X23Kxdl&YdVaGu1DeqXVy)GH8KsH5&&_3YrsrQMcy_r_2ae6Gk?A~L#w-0riHZT zUq=*!n^*RRMg&c*_NQkg#Rji%Anj|1lg$D(1^B>l8)H$#>OD?w3?7FgVwUsUtG36v z{0s8D3u_~>g|4Hg>f!X((ZKub!Ew0;;=YCXm+$xYb6COrW)8~csp4krm2`*4qky##mKt2 zqdv~84%6M+ol7s#OY{e~xzZMj1b=SZI1qjJSIh=pm zv_#oNWKkd~r$Xv~-yua^EvH?*NaAqr=L~ssm+i9AC}LqkB_m2p9_qC&GNx|dc-Ny* zO7~1b8`45$v z8^ccNJxiIST2uvy^E5PKpiX>fb@-1W*MCfoUPgcqZaq-VKr$MMG${a!(j*FF+5Sa~M(67C(!Svm zemhWE26$r-lWzU;Z;E*YZqwDUBfAgAkrY|RB4;|wHwh1$RMzVd{c4$qnv~{-Ow|!$ z05Hy4fBt!;5>+tXmG4_f*)y~ON4!$ogO}RMSns%+2A!%n)lT6^Cx41*uqlv2JtHo2 zRPSwmmRz$xMUwB)_#G@(FmJ);)bup4+$5g!aXf94WIC5=r&GQ5^a}5SdngS%|8{3n zjJ8n=T++?#hvC!=y0JE1n)>;soa*>`jM4y^n2i>v3d5`|_Cn<`kY8MMr{xPpo@y*# zOTjz^XGsJL)7(~PJ%7LSwsMf|R-@_iu@R4z9V@2OMspgJ|Kt=CNK_{EC$VSvpKd>> zdlu`@;$MRZ;>>t0$0d3V1f78r&E=aA6M8*m$=UpAl3@1UG!QWLY%dOs%x1H*O=~#cbm|Hy*oc8E{8afyF%2Td?+w*hWWA#rXkvz70hvKt zgli18I2y5~X@3M|+-8tU8-ucPh0fY;LN}daDfYm%0@E(5Z&$2}P00r(a6EEtW^Bq> zqyX2$C*y!_DNj#vP~ildzG!BhajLN4-B`oHPOBaRy4knJ;h zGunGK?w=`?i^K1Ri4$ZC3;o?_yF@s6%7{9;Z zov+@w-Zm6wT6o>t1EyQKF`PuIruc8z8RNay!0VYM$!y|RH%Zb-d~)H##l-I-`3Li; z+3hv=k>lt;x82$n{z`vS%Z?f`5WLS<)M2Cr#4A?_u#v(lk)pk9j!38(dce|PkL-2` zLi~F?PiEO9zF2lwS5=p1KCkj)9z}ajGP2xrVpSqrx#a8?pZfDC(sW{%Q^I)3%z3l^ z`D62ygd9sKde^yL{}xM$7`u5B66HiCuEwNZC!&l7?V78^XeWR8{`wNmsnV3eGVP7d zE(lhf!<+Fo;X74yjS$vkFerBn@SKyS6AI7zfS4P7$dTd7_9q8-G*)WPVwk#nQtr9m zWh%M*+ipu=)+f@dfOpUbo#7+mZWeK!=>7vpX+dnw*;SQ3uD9rMvTx>$l&V1*B5+_n zkuc8WVA6CL63c&r;4g-l5?Zk0#N>RykMZiW3}+=r;{~K!f?09!dCnF)F~HpI6P~xJpOO^1=HGE zV|)D>R%vEPO5C-LFm9SDRvm>3E7+^|}9ryKW1AN5|+09l1Ux-DAaai*C^$w+|>6 zv>t!UZrer_-RmoE120HJve9j1D=m-|DBvUooUSZG7*SW|q(crdGn672{`cH@QG6(( z7S%$aH0QqWIm5dTRbEXd8_Wb#m}sMTW>)4g#qK`@ppsM}211IOuC-^JQWj`Dj#~nOfnmpMTr9voC-ZthxXtL%T14+C?p2sBVAS zF(yDE+sINJfYw-Ruwb&1YVtY(`c(B=@a*VuwaR4ayOKD711Y{^2EpyM@-xzK<+v~% zpt>s!SJmdyr11JSaZk6`*WT$h1luG9SA)X6;)Y@~rPx7(kzl7W1uenk z2$Z{FyhKHSLcu0TeaUiXB#`Y;--M7c@*fpbtZ=#B6?QQf zzTiGgA+1l@#)YHXll|S=-X|9A-KFoHsl&cDt#n7!tt*prJzE?**gPlRdOm4vLLvn- zR98Y1#I)t{=#>Y-kXvYz815G_TwJygW7=_Ydkas`z{(Ac3)a%)Knf{0XnTM9^z0^K zH~+3Anl6BAc&BC2n#{W?>~l^jx`Ep1K`zBcpU*TZm(P+OW{W^rT8$PiibKbn{d|Ci zyGc4YeGd&~lh6b|sD7-p*Ns71hCe|Vr>hg1G{Ow@RR_l}mfCf3N<$&n4* z#4e4%x>w6s;ZeLtaE&rg2UCBDJ@X2d^s4wR)aq1cwqSy|twX&drW@R{T9{^ej;C*P z_c#=uK>s#F{!bZbDAu9i8AS;GJD0)9Rb4afHff}=&L-VCIrZN&TGJ``63*9pnTxY+ zIPPtCvtuJV|MoR9kW!OQK0UXDa4WsG_sFYBDVT1|`r=5s_9v;7s0)9Z&RV0|;l^te z8Cfy&((UdXzhzDYN#N)Xv9e1NXklzE5Y~rq9XWTZ7TAw91KgoH5HtLh8nIkAUT!F% zra=(WhTNt@Db!SH$T!JpoemrYNnP)U0pPP@u1vdxC>1}liQn>@|-cf1c z>^0-614T@u2(Tw7O~O)JC5xLb*JG#Yg1Cplt5q@}d^DIX?7Q?(5RT`+Qn0A&4JA4% zkdm->Inr^Mo{Jbgb}@lgEo#|MAcTFl>1=EhPfz2m^Vo6lM7H-Ps&cJFBhjL z3y=6D;QffZss3PL&`othS&tJ>anwz8&f~=8N!;VQ{ZuEY{tkm4lz%34)lGGOxrL4| z+f;mpIlUpyZ(-;W+@j>1ZV@DYClM^;7P)e&-vdsrN!&>XwxGdvN%oDbJ>rTWJx&5Q z3)XaFoxdVCgcPu^uPNY1=O>OxHcJ{Xjsur0!*zw4MQ|pst@3yolZapdA3&zS9*PNG zg@JdEAeAwOAh;_5iKriChGM9HvNd=ZAb6tW%A;<1%5v$3AeeAKJ0(boVtND7hxCMj zMmPHVAqvQCg~%RHYA{;HLL;udW*{1g#2BN8$3gn*!|rZ|x{E$XIL3Z{J2YbHcfR?d z@rvsd*VZ}4GofHGb;|Nk$UKS*gXf~vJ-{A1MPd}@%@Bv8mPnYGKs*sHh8(6vv`VbRBH|yK7R81CMK!X)HeC7mYQ)63VQ>Zf)NHw$Ku?%>IPB2t< z;f4ge8)Og;VWy>jl!~Yt_THf?-5zL}r@-|}C97ElO+01CD9cEVL}@;aG)hlwq>&?$ zkwA_IMglq87zyM+(0YWNEsR8R&}t=6MhYX{We3h>KNxlDG!lvDa4y4`rLA;YtWtG4Pw_Gh>1J8#;er>?9GuVrx;%RgBk_oA*R)4+C~ z2O^-)H#nAm>E!^&F}}|}r~i_BuwN?2JonN3bk%7aT=AKn2v>P`#Q&`$DrNaOGvwBt zUaiX$1OI+)upVTAcJj0@rrBW0W;U3@rRePHvsLfMP?8&s5 z?WgF>ifg_1XaA9FJ`R2Wy;yB;qc{-$o?kJl5(TPcyZ1G1v-h&C_D96RTc;|7tCPL8E`}*l?@dc-3T!XJ9jrxCFH|Wjc zJLZ$n`$z=6Vr$wG*@*gd^?7y{(lw1lJ8(09>JJ`A&8QjUEfhbKq#5)j5iE{K*o?ds zY37S8ZDE*pMwY0*;;04k&x|dbQP+ET<9e4fE{I?c)cYk($#Wy>*EkL-+2J&e`;CMl zS%f>@Rs(UE?05r>`aKf#j;4*ci!9vXTMha~d7Pzw^V%>5Sai36eWO80eHlULS)}fN zdOV8+diU(fr%67lh64=(wobx$sYy1Ye9j_a4e|sfMSu(e!#D*@Ae@6-LXiu4|Mmc{ zqr*dWheP-|At_la)XADX(d88SGTG?oN9vwri;(#nr9kmHa#D^S!2+EN{V2;_2d5B_ zkW+U8Tp2>q{b zc_`0k%Q$*hIu)~THp&OsP8n;*IRoy{JYP>>z+HC;6P#v^4o6jq&FhS(cT`+p*?``x zV(Q$kIUTnIZt|Sok0(SP1o{8*J$)X*-cB?-Ti<`E3)dvs--DG=dA0JWbRHT=)pgQ) zBX}TTMvL$0<5$Gm=R2ppRS=+mNF@Na0+s$=vC?qV)Q3eWt8@(uWb;=#O-?52khHU6 zQP1e-a5~*Tn$#{BS~lF21zo7~x3sxSg-#c8mebhmrRuE<`y!{Y*^5%H3wIz%Z02$+ z(}jGAJhD=&<$nWioA)i&T({nG1>1!?)jT%8DWkh^%MESwn$D&RZ-yLyb#^wrRaaZj zzax6=E<~NOS7w*52!{#+@co*K4Sif?l^;EPw!4XQyOk5tCEP zdN0Qf-GkZBTRI0*9I4WO1j~;tCCASG!Eo$Z6)VL}E!-%+wIZo>T5nLpRy()Kw;x*1 za-&?SYWo4B;Sz%uZf;A%xO7U2!l-Bi(5^r@^z~Oe3XYC2!2Zc%L6>mw{s121EL_6H zmn-mNil+lCh<^_v#)uN|UNVu5wMcrGNzxHyQONEo5IKf+2ei9?Rc)gqamD%X9*$Yf zcq+$T3>PQ2p9|GT7#l@^9t`+_43X;Gk_Ae}xw%EL4bp^MO|4(s9GGi3P`RPbL4|Kj z5^!WSFaM0#ByYT}ioRlz{U23J_~Hen%iY&g+?pPwuxI{m11@c<6nC@NXMnzm0U3`4 zwTZn6+zj|F3g}-x!5sW3<#H#vZe8vgPw||LANkpnND1zJD_~24?@lF|LeHs0=N2Ef zNmX6Cd6}##UHt#-+ln`->AhZh{{gmK7e)iOVqh1~7JuDXO>f&c5WV|Xuz6$pQ;BJtXN~){B6VMvYL3(vnnCZ{7diAtjO2r{gr2T^*cQd^7X-X2>CZcAh`v zlSv3c!URyML>#C)waY=Sf1SUZOgKwH<}3j6dy+kEFK<6=Z-NI%+4cgWn8zy4IKm3) z0WQA=kbmoe?RCLboPvGvt_i%xzt<3f03JZk*e5PPX2~OjL#Q4uedAZ4SjZIfMsM{T z&1XeFDtMqh_`?@BAGTVIJ2b9BkHX-ef+eyAl(~qxiZIOS$;pJAkl*4oPap-ZByr5o zwig)W7UlYbD-aQCzCrZq1OY4|0$7;wWJfSl5`XOw>ugD{$H}(|!3V=XBAV19kZEe= zXaKCpWGW!41`TKZAn!*eh@NpjRRcP0c+_ArRi(&gptw)sz-e=L7i1i(t_Tz@J>a9O zkbmAc=`8GU?fgE=5;EmQlCb*($eKi`JviKXcfttL_!2WG-z;{j9%8xNU>t<>l-+8j zHGid=2(F5jmFL|>IzP99uU3%eYDc@4S{bymC00YeceT%%U@2iju-%#YTz-Mwf~4_R z2seAJ#Xd?hruJBC`%*zNePl@i&CIkCz{0SmNoyl`3f_|R2&$`PD=r* z5S(y$A`+5_I&ByAyz8Vb+7d1|NQjmUs(&a=N!t9ed)v#*r9x7t8lqn&YI9 z9QD@MG_?O?EGNzGp7HkaYLp*sAZ8g`{kakdz$ za$+Le&0{<+h|ePx3ib%_il zDBGPnE1*o@Q2igxQ#$M-V$h%^nvw} z?_e&qT3zt#YUl6TKc^p-%1tYA`UmbsC?<%7QHFt0H zy!w}v3SQn)%G*PIMH#(?@JysEiT^d{MPuF1%AfV9)HaWc6U96`Z9*u{)pe7eIBduhp$@Wwc&T(?mhZ-u71yB zQm)UH`7L3zI?JCKN>AS>KLFKNO>^5e5WVwPATw$Nd8G05DqC`A68F%FbFiIWs*VRH z!59q*vH)mDiSpmO07(G+wj5uogKQBGyKmnv7R&RC{2>p5h=vIf6n{%4Sg7vQKBsc? z>*6d3I7z9@Nl4M}N%pk6y#27d2_I-mcJFD-I8!X+04t;ixcnN@Trcdd3$9p7?Sr!> z@EZPJ)0hg%L)x?Ui3=*TsM5fh$!N%-s%|5cjw`sBq`|b4{0Nd3m$6Y zKIr|;hn?2xj{aMaM1P)51OJgVJqwe$U|hxE=JezwKqu%omgWgfDOVD?pw2ayEv%mg z@Q5TxP!eT4*&|4slt?c-H0rexd=C(Oz~LiN6xE8LS!%Uu0IcF@CTLtO8kYJ4Odp9r zI>MTqd3@Tip_kE28I8+@;yz)ai~sH}%s3QX5h`3-fR8Rh{(t$QG*E}T=!OU&jW00^^xa}->Ve7C7W@FDr|Q;gts>S$;83)7dDfk$iwi69 zdQH<@?QwUfRt9$2>Zl<8%hgxT=g8&$fAt`=#RZNJV*9XSc3i zbk@~_$bX)UcI~+cSAzg<;Pq$zj&Po-k}Qf?Y}%Yc&L2eki$sJ+@Mpg481RYeVGb{P zFg@)1(Tm04LGX;g?E%#T%{YsZt}`d)K>gSC;@2fGkW|^*sdEC#^bOVj(L8lI53sY< zJ|ga*@b+LG4o#iyX&Ku2tWeweIX3JYbH`66NPkPvhQ6*Gek1-lNg(?_Dat3#8Ur<4 zx2ETq=T|hnr$U;p1JkP_u+cYEb-$rjZ|%HT$nLfBKTz9m-7sUN8NV%WL~Fci++Gi! z=-##ewVkv_#|-zL<5~4b>2*_B2u9r(YDt zYs0@cx^IE6^WyS6Cgu5Dn>XRn>MUQ9OG`h3{{Xice;0rOf7MuDQ{y%ef6u4T&7>EF zNsj4jAfYn{eJRimaP33W$tboA?%A>{D{$%MzI#`aZArH5B+x$84*^^I_qVIvmCi5n zr+hF7X^;?3aUpmdh?Uspw3vTCJ{t@eNokRjfTACh>}7fNaJ{?_o@h#zmo$o5EaHp- z*`}}vuD%2`f0ql(yA2a@O6w12F5w;gy`vH3lm*nY_K9&?WXUrPyQn<2_||WzAR!UN zT78f{s^8^x_812wS>BLbzV{RTtQ;XpH>LdfEexcJ;^R0!rQf?CxFYSYEVMhu@{+`%v@M01i@%tok|gv7Vq(-U*+mtCRP zZ0hU>xKAjM70flONX_c&xPrcCp%QmYE$vQv*r_q|hi6WuuAhMLCcz;ov>GF7pC&l8 z{*Yeoe$}2zJiH`81sPvI&AsSor!elo9!7_%wS9t? z2$E_1@IzAVTYr;q1q5RJFlok~Hm{Lu;0Xc{hb))7f{`+0WZk|b`^8f=39SKCvYqoT z+HRV>%X3a-sjeQzN=LWS4QzwT{xbr~`kw7Q z+=$^rNc@1$#dwOgZ;^4bRy%j2ZEgkP(I3YSuZy>@;>v$i>8r9){^4YEc_YgkZ@rE~>CMehGSBZ);sh4Qoe`?Sk?PFx;AG zSp#tAzpoB%WHmOd=4TIHa1xD${cOH(Z%?9IH_%|*6^s?4%s=7iuenmePHaP=&NUkq znuE&eL#T#fXQ%a`PRxSWFx-&&kz;e$9hK=l{u&B5yB0IGPNqSU+45B@7(%ltr$VzCE~VN-;F>Zh z&VLw-JBXJIaP%8eR&cBow>bTc{v}%Mp2N_oI@c0KWa`QcAZ_*!(Td$T25GZ{-$s9l zR;{rrkgB79sY37|O5!AR#-aRhyBSPzZI7>w8-kQE4!uhU!(B#A4bCSD)N?3X%XK7; zPF43oxv*TFM;-MhWnE)&i=WC zs5VyETqoGFTL%3)L8V!gH6@5|O_Ey@%*H=b=j#PF|EG9`+SV;tQo%~SI?iZqScvFC z&atL*0RzzMev5Wl`?m32?40Z@W0ghWFNck}7@}$tp`_1lHyuxM5ArFEP8=)595@j? zz~~pg&w0p{A=dZBVQbY2RbUiR$1E;_W4NA{{<}kN7G4eEa%h8MW=k%#<#bTeIYJ+0 zlX3YS(>*pkX3`uGwDjQM($Ulnvr?LOVG}p4ohM8tY2=6~CgnM;Dc3Ov zLYNh0#*m`X0uORPcezZRW^MJLJ1;d3fI+L~lUvoW#a8>lw>LpsZL4cH&d~S=74UA$ zaKQkk?7Ulg0aZ-lEW_3;$%>||dLKysnHf$Sj0eXiAMt$!hq#@ymcgTH3@YZ9u~LvW ztAHrkqi?bCdZKCGU1U7(vk=6J4K~mwJPLprlN!b*qxiRA6-wfg zQT&b@_)y3C-P6uD&Igd3gQY7z;&b-ZfTDT|uRQ0TKd#Bu!dPC{e1o-rt|6Gzwi$97 zBbvdl!*5#*q3-lL100lBiiQ!rrmm`={xYq+hOs86fbYbD;x`J#6ehrX=3HFnI?3=R zQr5o88t;ldHNma^B1nh5gLxS0J%W7goHtAMI^L^-+T$LkH@q5zQ$@b8Cpz$jH^g@% z|E%)MIh-&ThsS5B2kb{Kob+@_kPK_-fRC?i>ZV9f3xpB|PyGaPZded|PP8r)LI^o% zJQda2L{@XzFtxir0S1`O5z~YxFGggc$0Ws(Jq=5AS2^Z z4gTHEtxHT6b4vI!3w|F`m8B>Bh6?A|p}UzrZZdG zr6nBpm7?jmQofHU44sGVpVv5DvF*xZ6C)d)=yc7*Zcf46w^90QexhAiPicYiX_s>- zC0a;fD9W6Q166A6dPTaog=snaVP!fq3=g>rTMjtpqDL@~sN)_)BG!z= zZC2N5Mz&e;g3NXa%&f|{WBcyT&{NC=Y();H+Nmx!)-(A`hAMJTsoyq;t(wQ|gnC0O z-Nt06X4Q_T;TMCluyJm_e#3*~-&bXK#2?v&*B>~_XIeb$m#BZc9mhCUl0(#MPhWk{$dRsHasOFC(_CAIE`#OMW4))K7^yEmKQ$SI97jzx%Knu4b0<%QSFD$Sg z{j}nltS=9)QsH>EJ`Q6LUWM`H;m(VY+hz8wAZ)MaYCM}ed0cDo8(c7>91DZ0Ock4A zrJ@H7s)2u|AvAapULmvs>SOp#+v9y8(I%x|O5Y>QnOc&jjS_BkDT4D<#m;l(iD~y_ z{v6bfH;_APi+e|eJ@7RjS{Y);WY0k3m#jv5Imr{G<`I2VZyKclVxePGAzw_$8x@0e zBznDpB6?nHY;T9&uzFd$D6Yj9bkyYc#^lslWU2sUL{7z_JkZg!VDh=${KzCC23*(t*=5j4<mUkRy?fc-s zXs3^WbdBN5CKEnRKYxH?wqD;jX=`mKKi#tUbxiB{3I7*bTg;j4j7B|___ReYUcY8a zzbyeUnj49uQ4Y5|IrDI$(Id)iAH#-y` zgQbD16(!^(6a21B`rVqef>Zd^5G9Pd?QQkL!ZoT)>P$sdsrG9A$I*MW1$Zw`>072& zcA{>tcsvxI(@1N0{;+vmujBHtdqAel>`)k+jSvWwg=r#tsI_sUNkp?wIU7-=W-juq zaR?0VK6!j$e}ruTdDb9t2|CBY^0^D-S&P;w?KCe7rKK??u&Pl2r zRA`d2JP!tgS@RUy95C9eWpuT?;9`$)#P_g{0Kw(geaC<$$u29A2kb*nCN*M*rD@{%Y zn{PN?5)DYucJ)TRG_rCC0I^M~(rQ^mwxoWxE*1Hd0@x(vwPx=|0cF~4esFOkCCy^6 zOX}yIrnxzAKFQvC`&_k&UWv)F=$L?#D?+GAn9I0gkV$nQuueV#O`9lszNe}(wzUe@ z2dm%+;!cH7NKIKe;UbE>_y}1k(J*CiV84*i%J;`jbG{-}Ci2<=G}RU}(@DQ(%4xtB z3*)&tRD%{DPJJ|b>e3e_62`?%xs>I$J2-zqsSA`axSD7)73GKvVkP!#q6&3>d%UR~ z?JqWTr_!gPER+23%b8Vp1u*=c%&4<#7bvP%_u<9Pifw09(nXaa4H~ukx7^M&HAH zV4AS7=Q!gf!^-Xw^}9)(Aff>Zq+V8T8eSTy|4xj;0f=wSxf?l7LTNSBF4X< zWi@xdw(0llYjImLVQ{JOc;eEn+Tz+%^2pwKzV4}}6KAF#Z3X(G?UBQQE#);%Ce?@xt}uL7)NVYOfHBMtiz6-1;+0e^Juo_x2N{XT-AVEa%izO@k^ zX4BY*@Zre>yTkb`1uyI0ZQz`ufo=P$P=<*(#Lk#ma{0TEC zSR*&TF>JZsI$T!^gEZldzD_-jWh5_rDh}nyWIhGCKzRO4anVb z@CpPfz>~9~xaJAfcKNA|p$61zDFhsa#vR9;jS-iBz{H7lPA5*w43U?&=gt|gwpUl2 z2)oq!lK08PC?Bbc*VcM1JhMJ`&3auSSArn%0%NBh)C<$AolbgG07v)wfS31TzQk}m zzhLHOK5m`y#~jp%^6P`thnWSNIg|buGi<3#V0mV_%p1C6bRnJoI8$xF@ zcEOV{Hstu+_89O%sQA0Vq4x8SPpB@BaE2t61AVo31PSA2Njg;zbk46jKlZHFH1JP< zk9D2Inp%I@WXFzba@kUn+QzomMbxLT`CbygucWL*=qmPxTu32}peE@IIHGk)Emefj zGf>d7Fz;{Y8NY>+Vpk?n=HllXA@{*f2(!T#Q-mmxi_0S!k5DCJzL=^$R}tNn&MPYq8g>1lL#G08Aw zB9q(8Yo)|ur&*xOMStp24D46KMoTNT2Wo|JHjRa;RWBjC??hc(F9$M4A+cAViSD;iSm#=Qo%4kOzeuoYK7-*!fLaXw*t7d3vgMmV@CpFFoh9n`Kybt0+B6i-QGy7@hH z{kUu?&8W4*uk9{_8-2=7)PuPyOCDHPv3N6r?outpWz3>Wu^ub+L0k>HJrR-Ap|V2UT+;+)|M!l;c`7Ig9u_sl4m<$Qb5eM8NdztU2W z@8r9?_hxL~gfDk+36wHQHL?9rgR*+AhWhNB&u!-328MZ=q#)))r*J3FJ52EVmKX!&+Grm!W+K$@g8EnOzU`ubtr-+*2C0 z6^SDmoozE3iB!|LVY35_8EanJtC6K>!H?fdg93Y-!te1$ znBjHwd1X!Z8)B?~x7L zAxmMNJpNAb@(r8>9hJ#FCIB6NgvJ}H4rQUQ#Lgcw%143K?pCR8#()3zRlR*BSkT|c zuV=yZbZavO`r4lGkr0L-juff@AF#%w)~6xq$<52**$aK?8{iR_Q)Arn_xrQB5BfWn z45hZY-kXMa%aHrEMbM26DS`$2>SbkxoNC=vEF#=>y#jflNQ$pVFcZXZ*x=>EY(J}c zvB`d)f<*#exA2K|#G0YRn~`ptEwz-%Fj6a=U}m2`cctof?55w3F&zJO1eVhrH&5zTkmS zLf-W<Ss2@5=?chFQY>aVS2@G%gsWmXTgzg zMasbW>&gl+ry2cl+)xLhgcyfef?tLF>|T5!CCz2y&pk&jtVmHe{lG8%xHw^ZP_|Gp{^Fg<%=O0>PVU#p+Plq48v}BH_q_RPw?C{Tg~NU$ z;F@H`npu-4Ag72A9Wz_8O!w|9W)*&ePqg&H466;ogJX-Y_-_UKxY@IoKASTPrn=@a z-z2O7GjN1uZkqIUx-#ulqqe^wflClJ++JLorZHF|>{Rag-WKj~tFF)3`7;)G%Hj(5 z{=?{EP)wr|u;6LfV_R1hLE+1`!bw1#<%QB5zBqLYi9xQ0r?ca-nZhec2ehwjQke7) z)E#wOe5b1H`UfQHFQld{dkFg2g3DknQLuMMsQISoX#K8xM{xL=6N8{M@|0?b62j`3 z-{bcy<~kw_GS47)?h%X}s|N~d-8%H1EWcS-OaPCBU8j0(L-8;&^3$Q;Y6v~a-Z*7h zo_cA1QU@_t_kSL)so>pzh3WT`DX!pK`au_t;UMmFcS3(xlB@M$SqS76*{+rl_*Ju@ zdo4$5<4=8P(+H8S^x6h=xYj}(q&%P-t5+C3k*9o5s~;HgPy2{w}iM)~4cBoH~sdxjTJ9AHOQ$A4*|3aNzf5L(f>LDMGw?KD$@9c1Mp{HFd!>2Fi>)+UD-4 zYJ0E4ehl6`CLuyFwMG2;?tOZ~ zSl;~`_#VN8_z();hkRq@0+X$T5nU%%T0O0|`wFB3OmK7qRRN?H#_h^#0iZE?hnC9e z%}vT)vrC>t4q=J%-SOS* zZA9Q`uIX0jt{d#-i|ki9`STNk9(mE4jd3Lb<$7H8pZ=s5MSCu8fv+xZzcC@}L%$?G}BECrs@1 z$&o@0nT}H5Q$}kZ+BQSktp6foEJ|KT)OScDDP-PCFL2bn^Lh;@ba)+PLpr!JO2MR2 z4ld^~Dj}AEqMNrbT8pB9-ZY+*7vQJQZXz`*VP(1!bms8mRqk^(fiPNzfu7OaID`;D zwfbZI+c{u}j5FkvOhJy(5KHb!0IrjWDh`fyUfm-Gh36lhnP^1mS$NT*TRnp!#y4x% z!9lJj4%O7lI@Vz5!^cmL1)@kwcX6#&_!iD-*<{eiUV0ZPve+0@l&iTbQ-j<~6SCug zNc{!@@4ZP1OON!YX9Wp1ALAM9<37OV$7g8Kz7*`H>g}H~c5A+qXOn5T45b}TNLsFP z(|WXDK1&ypBG^z~bZh&fwfTG+9K?s8i4g@cVcBHi(hdoibd7$`rV1IvtleV=^s;su z3h7)yPWYeiGwEo>+u;$R-zsw$e(9@P&6?(7sFQEY<5lD; zhT{)krs&~%qXaKVyx$yCo`!;eUEPUarhx8QmKA9h35+$8Q{Istl|&(XBgIw$qg$5x zn{x|5+b{7MD7{GoPcP?fpV5IW4GG}(z05) za9{pQkUkh0y^)O16}zEyv8}@XIK%q3ru`gXaNyc@JK;a8mVL$Rz6@L_8j-}tt9}jg z*I`{_d$9^OK7Ch7qW3%XNup9beAh~uf-vG~L02YiMO=NrLEQ{iZ$;hBG-S^?#Q#Yk zX7oURCZIRsS@w!je&)$8;5ii8K8Xxpa@C#A>tIt{fc2LC`_=4nPs8Aiu}>p-WArR6|U&{?gXJL3AnjeDbKacTNlg zM_00EZg8=$+_;NNp2krN_e}ZmbriOmP&m*Fe-f!Jwe@0%*)81i zg3i;~>xchVRC;qkvBq_drwl8lWq%O@81qGAnJp)yQ>BxozWeoh!Cy>VoEJBzuL&#s zV|#qqNeDT@>flcRC{GK8PZmi{6PR!FO%Kt1W%VNfJv{Q&6&vDDhIxE;bhdK#$tAH` z>mM*y9Q_-GugjV~FgU_uBNN~EZRt6b3j(iNZM?%awNOK#(8Q*eaL7b0Mj<7{0Zl>e zry*w1rY|=8u^SnjD^uu!-B<-zTPQ<QjTq+J=P=MD?wZE&OI1gDRtVsyv8nC4xj0 z1V}{f+2n~Jh|%wS&(CDBBNRru#FGC4g>6B;jHVE;wr3F3uSnYC7@QB@2Wuw8f>f+4 zkXg)$gcOpc&z6Xq9)ex&gL(=;CjVe)>bEk==km`mVVi-@^)&WNznoTe_9L)_xNAY; zWE9vkyQTVeo(;Bt=lpvuloF#s5#2K#OeYbS7RJhJ!+;zg@44SnD)3h;M!?j9X{^h1 zv9$46iAf?pY5DsvhN-S-_dvr>-TGo#Cq!qH9OGLIMhdA5bxhm5$qbZ$f?O+qQ+~8l zeRgun`)BJO?wbdfB-S2j4bYja(Y+u_J!`76R7h+|EH&MU#<*O9&5l_8r(8x>9fg}| zK2P`mg^0+CA}>S6o}a7T6Fa7{pRI$w#>^HM$C7w3C9aixvKPjOHJvBYx@h7UmL%gj zcBqt9e;?8gPXIJ=i7}pjLhDp_6mAp`c0%#pgdJ=*U3;L@Znp?7`T{rM9Nlhr9fXC$ z(lkijx{`vCli7*m^uDCDLVt5K*$PdM?+2WD{L%--ifdI1$IzKg9lTL(2UKNE%I%#j zWZC3Z;V6_e7MouUJiW3{x516b)M>na#;%x0c8Ac$a9Kl&k6 z8$Il;p8$G&;CF7Gfq~#Z2qCC@zG8sNxC*{f&pmZ3h(SIFt&M)Ql*X&5FQ9*BCzs`n33Vi2_P)F8?b^l*M@a0aCkfd;h&8~6V*P~Fe}^OE{?N55W}PQ?vr~u! zbPx8n{l$d-?<-n=F#$uutUO3N{Fjr+Ur4A4WaV9%qI+paEoj(c2D+b{+0EAmdZFd# z2VK6JsQ90NX~Z#m#KcWbO+vUzZQT6rKNn!RG#I62w|(J3xupCbK)|R50m3B28Zw(T z^&=jt|MU^YoXGLsC0UMeqkCU%u@ zIo;q4kXS-6ViuH^K>N!@M|i@GS$1%}C0M{`Mv}`ei9?u+n=-)itZ4|#f*3=jPC`DC zXDLaCt^19dyw^dW#lN9ps z$w_C-X9vgpr|A^Gg-KV45eXuAMl*!I)*_d1viX_Hf}gFp%Y82_M^5?GRc&H5#O)}k z<%wfgjWs9G98Q#t?oI}ccBz0#!Rm3!bTWR@$k;_u+lq_I__4gZnf7QXUMzj&Y(>_S z2OsB0F>kGqIbahfYvMf5uhCTgha><`jL*?q;gI0KyybV4Z?@(t-E>$TKeJGkVOauQ zckOSf^NWqdG>=*#E&1EKzXir$?rtI0l+@tA}0mI*bUs>juFOWgy}2Me4>=ns}n ze`3d%SGuFxK1I**Q|lWLq&p-oj142CG+s;>ub&hz0SU_dYemCP+8p@I7LpFkZW9*z z-1F`4W8WReHOH|HG^DBzN_`Zbq5n9DsczgYFD}Sh83_M8U3Oh03bE!yoyOh}xIt0) zqLAK~^kukp!e-~iq}2(_guGw)#$xI-NqOe_p(z+U>MM(H1Fj%k9vX;43ogYpW#H!W z(n;SM0Vjitlu}(6qXLMJh%iP1V4kWXRf<+Egid zY}j32a=Cv_y^ou95BjOerhBwcL4v$n$Y@7>^^o$juF!4B~RR2Q)dvE z{E@jKDwwo`HCi0moLd8Tu%3uS@d(3rznU`FsE5zOJkG@8yvOV9eO#%$9HySNad`!EqMcf|gc;@>Uf(4HMojdGR>9tIV)czF-@l8=QZ;=^CKIJRR!MD~e0)i?aiFQYja_hh}Gax z1quDI!~Ms@k&n`Q4k_lW6yH-RIB(`Act2gDXps_YcS~(GM3^y9L1-sjd&{%PswEM) zt15r&8S2g_?t>K+{;H}rs7w{9Q3ziDloa{7o)F-0zY9qr$spyMN0w&~Tw^J9F)u{0 znGgxYkq)dGIjhNct!`PFY_x~0`@UxG zz|_2>0SRSKtA*Zaol$c5olGE2#Njrv+~=kq)iR+2Mdc@~^<>O+#X8-IVs+KC2A^1@ z!>yd=FuxYvp0BP{+^|RYYkTg$WGR@N$1D>y2AYa=S{@FSRJN?}{1OWD!Tvnj5 zgQgRxx-8!Etc>qjQD)kFSjhou)J&MIF@LE8jU8^M9YH*xrphl-2>)zlm`s-#>F?O# zh=0hZ5}}deix_C^p!Pgq{hkzh1@^9R04iy!280(i{T(|5-r94uqY{4nck7@eUU*WS z=KA%m%Gc!t9Zv>OY329O1TlevC*h1TrUP)#))na=M3@^))$6qtO$L970H!U!a71_w zipwNu>|hU>4Lga}(z%tsFuC6Ht{}{iDy)9Fl9QB2Ay4r1j`jQFFpiSJcF^GI%Kj@Q zg%@e@a@*BQ9j=l)QtGQ&xsERX6n5ik#yg~K*93}k1t9y=DT+Oe)38;jEc)ySNPREq zsfr<=KGa?Em^OFTc^c2Ignnk>RB92pQ$$XS|n3XXC1$XeR~%7Vztk+HO2A zKo6ze0U*I(8o)H+1YfkE^D?fY{q*}41~hf}8^M4|HlPS5?e9D)7c`HW%-dl~D2|4> zBR4Kq{it5pOp*HIA8sIv`PWpaMt(yju_E3?j2O6yz9sV@BKwLLKz*?%1l{ly z;JMEeGeoL(4E~2*F3&T)O{Y9+bt}() za=jd)Uf{Kemu!N#FA3=#ySa!82D>jhyhJ@DN-^{CF`yhd*kD&LVZJO$x2Vl_`>9F$ zQv$29PJIM7w-$fNG|@};j7&}}Wd3e>5IQYNCgSwi(P*T&(g=x3j?`CojADR1@Z0K3 z3nR3k_D-$KWJL%IJ{t18vUW2yt~l8jF+9lPx$2t%vPaSgX}X{ku>@IriVEKOJJLVWKO=Q-P>qlTYnC-WjY#afo&=o=A@s(f~nNJ4Qd znx$FvT!Vrbb0d(;@O#5yO8w_nHCu$-k10+_dgbE=CJCLMQY!=Jso<;zStF6B+Y%_7 zc6i90Z&e_hp}@HY1RkR9mejd}%4LqJ#L%DvSIH+Ao5@*sD*g=NYrBG&U{yOEn!X^5 zb)Mdff(GEqR%$sGrPbmzy@3G*F=n%v=j*n2;XjX-2uoJ&LO?-GLAyHBiL54aJTy(| z=68lJ4XFnFUPreF#}igAP!O|y{IAd8lKR|>WncA=&tM|q$2DlS#C%x?iD!{pde-f` zV3>{~;4{0z$xqQ{jkAVtC^(0b(jc)9m`9SpbdJla{TWzzqk^*#3RFB`gyd3PIO%9Y zR)BqWytV(;g~ssF+t>Ksm{kd)@VYvwk@|hizu^WQ4=!Qf-S+IWfPcUrfI~TTQt(uv z73Iq+{XapB!QUX}ACL8~#YzzH*J73Ze=XK<;9rlmmiOrud&h4}OpD0gka94xwV?3n zF4foUU_q=kKJ`6l#q(&0m|khgA&?w@S8}`6_EP4K>6KZrNN~wgU5jL_a@`c?vU_;a zZ?mzF__RQ$-wZ!&)1$4(%IoG)E!ifjFE?qyw^>A4BgUclDSrB=9i$P=dfuFYJy2Rg z#nl|;TNVw#6a`x)>x%iLezyjGyfdFuA-p_Fn(%O+x)lY$`)5awjb-dTyHzmvgRF(k zL^pZiTu@l6Jpo!gVD=u=p|T$hnV@GFLc%-f_y*@9*PjKk;0>mU8t6^RAtX570~g8m z@{NrAP^}UB2|s?#JwNs+AKlsmckRb_UymuaJR!2 zuCl`9So(8zCw4w8GmLz|Qp-_KCsHDDVmd(Bf&SAuB%7;J&11m^b3YsrA?W@kFpWfnBJANQOawdVQ_V<)E2ST9reG7EJ?}X zv?`%@E5KzH;+p;_;I}J8mWUE6!z*+OZ)GN_z?~9-C%rPCGcP100B9J=mhHL-&oyV4 zGq0Y^AzWy=McvBS5Ivz|1U_0ElL$O#TQ3D~I}2b?A_j$jU3%}CutO3qxeb$Os)4X2 zpvFtnlgV(16Fe5)HeWyEBa|#b677&@Z?)Io*LCgl;sGZylNFy>f|!6`8c1N%PM|<$ zxcrENd85+lr4H*S06?Av>*tD@W94_UqSg`mvov(6nOABt3`;xN* zn;8rKli}C-TDFNWgGe!aDnV)sdVfFkx_cu>SBau+y zcX*o5E#Q7{|*QS|+)9C|i8?h&aaJW*1RGw{p=IM2^c z8RqJDVD0fGPQM`TatVB$t}u41X81TrHgT&SlH7?Xt~-*o54|E?Dl{!iVPQv|R^5EkU+m_wJ#T?pIJbjC zz|5|SZEPG_ql`Dd>9gBQ3AJMqD ztF6xjT7&)g6?;CuZcr%m$_coXP_pf}U^YVv!x|UdU{CX-b1rnMk z?j3}u860XaVYp2MpDM2}p391Uby%m{q9gl~PbU`;Ev$sd#Fqkejr1)V@g#p#?AppmGur-g^$c-d_ooF?MKk_ugM>82a;mgZ272U3hEy?lAtx!UfSo=9yBt!C& z{c`??RNo!;ukic89VFT zz}ny|c}1|akogqy7XY`UH4Q=k+DZ*>PX6{)1pvAA%pdEsN8QDT{aB%hGxsjBa-~j^ zk*+OgyVqw@@P{6Zlqp2e?GqR!Q9h~LXZj>2cpN^Nd5K7qqOtPw3WxO{mp<$X6O(ts zBC8H?EFPtJT@%^0CWg(BWsMhy@Fg#i9dt)I=BMkK0}DMcv?EmyzJDlX4g_JxyrVFl z;sN6FTgP5vFRTohtu^qhNzb&`pz8+t%=qTGdHjGQcdz)~B}6#|eYF#hx-ZX4bt1!` zs8SXMw;TjFzj+$d9zJxBA0cD5adKYVzJ+8{_3Gxy`0d8pPkif!Qm9R1FW*2OumH#d-f_Vf zMHHh~n-SjBXG8L`-ZN@$klLyMi9m96?SwDZ$}DPfi4bavl({fHBp?mgBV1^r1}948 zLMw};f}jXcq4)bwt8t;s2AU^jaJFTvT+L;%hJ3`xwXuiwd_a4k*J#xP#YOJ?|HMU9 z@Pp~%xue~LOfj3(vJzCLIFhGA5RK$yQgC!@l72OCY>$ZSABE*kC4`+@w2MeW-Obls zZT5=8;T)re7>0d+gSKSzz8#@F3w|qkHYt5Nz}*j8XW`YAGKIzr7TV>vwLqqC{eeoR zZ%Dy+eQ>UDMWIKKr7L8~iJ+{!ImFi+U)5Mt#kpjV!LFTc7r!mft*ePLJlf`5Zy@z6 z`mGWIC@QDIAq;kYsH^50Q8Ewkzd=(hO3Jg(h0{Rb@*fH10R1t35RJo*FZzeZ{q58IT>eYrm_d0FVKIou%@{7Cu=zBu zaAtqZdVp&V2bsY{800f}I_Q_vAT#)HR4$BZLjL`qsGQQ4kMD1v=08z6>;FXM6ckkd ziOKnD{3u_XF{`5g8DVt0i94i?LSfZrx4)Zth{ygZ&rTdQr-D~XXO-Z zmT2#epcBts*~4X73ZD?qQ>uRzLHpX8o{~=hp_+ySkK~8vIp?PAj2tcn8uR=H{=_l= zn8AY@5Jj)x@4{W#BUigPVcToYQ?d6NmmW+^Q)WqLQzbpfD3(^9pMXh**V{nw_5W6U z|CWnEX7E1_(f`LFn#ZY_qBykBf~Dr#92fY8=PFfZwH&bT1OCX0AyR^#Sm(GP1li%! z#B(JuiJpLW6ZAq<7T*<}{m^CiPK@5lAHlMd7^N0h51NAm(HBDIz9wF&ZdjBm@6J0A zb(a@dp`@Rmr}oR8NhCHO5PfKd z0{*W_1b8d6=%Js<*@HHIJ-)(%!6<6pA|KQuMJ;6+qan)&so23yI;_1;Y8S!jydlbZjSEq_q=TE}!2&JO=k-X-%*J{gf4RHgA4vJ`z49s;e~`z6Q<>as|y z94IO*npe^!a6EtOyePbKajMPQ`PF`SyR+Nzj^B%LjT90VgRggFvt2lxjV%TWF=QK- zZ!3ROm8>j;PTASZPfg0|wQFThkf=`rd;2>7&fC#PKM>6_Hrj&b?eNbqcdh(hw1%V1 z{A(e@zEQFLX^a&eV_9Ps?T+Qh@3I3-Ewty@;;Bjsdr#N6@gH_hWF&Pan)S4p`A&`v zi{qub?h_=&OoI5lU&l9DCqHQ

      R!r^L$(LK2A(gIET8EkTd20B!(=4g&zY+pr?61T6x+-i z@E*OT3!Hswf(Pv{9(vpo&N=a*V5*S2UMdLY$ODE+UGcL5hFs~>oa$AyPAj_f;q@UW6$v0I|Z>tYvcNvoDztqX@1KFo`WbzNB4nhoXF!>{| zwxb@zTc!WUK0K=?jGIiVMTR7T0sXXuP(UA&0|)Z)2!Mb+6@R^!pPotutQrQ*Hz!q9 zBu_PB`sCYTW+Hf_78&w?k*Q8%yJ@a(5G*N7CPEDWV5uM@0g9|U__{w+oCm2r7rR#l zvE1i*m5Q?L`d4^R#;PC`d6+x0s9A&<^q}_gD#8olHFKo~wboOp@x|O4#7Gy4qlX#z zaYnjO9OS~vH4500O56PL@%;9>%g;f0qKN^Pa3j~~??a_mG?Jfxqs!v-{rA;kc4Vjn z%}A+N?@HBsu`BIUc_?K`N;eT_KL+GW%TK)p6E@%j^Q*-c46 z{p8Wmz%>)gu7(iQd$r_VcAP7!r#_pem&vAhu~;h(G@7Ou=7Y0qtFAT#njd(4JPiu zxceI;+`9UIYy0l>{UqJzO$+iKe38BnAqHlR4;w}GY$(ahkrM7}`FOG3hCHf&JBVc^t!(+%qZdng7j|;WH z1-fh&mhpk*BARdu+AD~%ktL_QRibEW0P>R$lMEk!ImFNq9v5xG0J>BfL03OnQeh&6 z1n^CPu@cB${?C#*6@p7`1>-@;YHwA%H!R0E+iY`e=V=Sj3q`#S(z=Sb-#M(M4&1tb z+YkOCTj~=Chav&TBRe`!Kv{AILyqV(a!5G>2ypXND9G}Tt4%mL)}5>m4p02raI3;y z$DOKwh!L4EtbfvcNq7 zXVjOs`RjkywqnH2H#X5&XTiA?{WHBQPU<3tEFGAdH(KpOJ+hP#_GNtlty@?#?{uKn zO@2e(&LdALux8fOf%ElKq}?_;?3#m~sjSw2KbKXqMHc>@*H~rM)z^>UBy$VoRFyTy zXz>7*1!M2HM$6|lIIYj+n`{f+Mr{>gq=!MdcoW-N-eM04rJx#tSZWxI&&mEpEkogB znM%$8T@*!Le2%jnU>{=J)eH#`S1r$WCgBO_gyeaFSKqVPtFJ-sm-{R)gs-!I zp#pN1GbEF2@15Y54#wFx!ln$!ck?|tLe?=acyL;Y9F?CD@1Pyr`S3}yK`h$xNYCPLFN^~G;(|;D>)t|vx4g^dapcxuFKonPB_h-m1k1N8)i{-mPz)b zp_`Izs1;Fp+D^GGlBf0Eo!$CTAAZ&8?&ZB~S|{>+a+mx*C?J1XpgZHxhK9OeyNO0N zvt2}kk1UJ?IkR=aK|W303b47tf|C{id7&5gSw{0K`wSN~fy3JWb+5kX{7jbH zkfp$LrcR>a_h0t@@i`1C_KFpucu99tE{`8 z%6j0bzwcNF=*)lPi*?m?O%7*E3FwZUw>7eyoup;>w7nUgF|<_xt}k%{-wS%y)lvbt z>M~3B6nI)srPlrX*&g2ZQzd}A*rstI%DZlsudJ<-GniX#okBkDy`yi506ddakfsC} zj)Mf$FDt8Z+-2(Z<&z{#8>a#>sjiKWYE405qImYlia>GH$k%FsB1W+*8T5>MMhqiV6201 z_NrfC>lJ_Ue6;3lQab# zT|evAD*)a6>ehw?z|XtMvf5Y~c7AE!%Z^c;+aMA33IMlF{3@;iyVK5^bpjBtZJfr% zr#e%;zq*1z_jQQPF*I+HKFym2G1AIMBjB90nvjN1lrGqs?BnCf=IrvaeSw_!Ib#$l zfvA6%!5QmQOOZE|)4Nr|*+0k{5`($Y!C9-_@))d@4%piNLZhxR%jJb%*>amC>QeaL zJ&{9d&c7{n8vFge5c^p6Cv;yT?b}e1LuuVTMOGvRw{)%&VW?-=Y}2b}v)N@(Kgt=8 zR09=w-9rz}9b>xDpn!2>w#H+S9JBO}*L%@ijnXTPTM3xo2EEwaHrvcEICnVd?Kyn?BDjC) zm+Xk1>|+~h1(+LUPiWh1aZ_l+P1d)lJ~HgOLz9QldvgpPI`pc`si=MkLA|%z&`_6l z`~MibMaS4L>SWf9ldSpKmB{wh3)Rz*SoJ%L)AUOzRMVd5XG#G4j!6}#3HFc%!>tnl zc$L(GLk3;ff2q;^M!kUyyY7(3sVINf&)A$ZX@diNcH%BivdSytjZ^@xX&N6(@$Dt4 zMA?*?^mvYiK;F%x-NUd64Rz70V*I?c2Eg&~gr070c&X3;muwr;6Hf*PdVEW&myO)x z5kHhLGPIN+?p2&%N1#nh6&&DGW9QWyCiU#B`oZD+_PRYCv)=}f(lgeX&dGmKI7*+` z&*~vaZki^WDld3a#FoQwh_`B!Jf-Ma04|6@3qf!f7w82Z4s$Jo@h!w_lGi0y>_>VC z5}qsoyz+4+x>yv6~iL85ytQ7Y#xyI6mUw2Ag6Z9BYZ=(XQdR%0?QkLjMmo7NK zr>qNcLGD-V!vmc*RZMQ}8VY{^xB75H@Ac|}gM57MtUmm@({FX0QlHm4@VbXj=MJz> zM|V6M0~2(=vCyjbr=%b^nN-+y2RZ-$WV@{obsFQ(NE+P6I_u8uyN5zhGovZ7>i2UY zngY6bc)>0-?d=Q&jGM~K{+3Dx=u6HtUGP<(&kxsE|ENXrz7dqQfW3d=LLYZQHhO+qRmdVZVL9U%S^ea|X|uGxO-a z$A|hPG7NPSD5IAod|YteBCISAv3EpJrwn!M z!4ggHgBU~qiXPO%?Uh6sDMGIn%gKWD@3l7ZIeLeMa$^ zw9oo#dK`5a>^w)iu0P|LD|w7J+_iFNIcy4ij=#I7L8)&Hxev zJ0(qq?gxm2wx)p)8p7~Lv`h?s+3W?gl=##GJDuzgvhssHOn(b`A?zlDYbl=jK5d`w zLWCw0ntduEV*wCoSCv z&%2cWvw0pfMJZ zb8~y)oEU-QJ9ow$m2ml`3##1dY+#yqw4rRN7-OVWR{pXIAR!}RlnZA}I}|t99~_R# zVaszjXxj|(_$i&rE7Gi=&LhIrxfxa&UjkBlO?zUG7{+rL5l^IUAJw#%*p)&{vkP$# ztQSvnWl&>*v7lz^~pF7r2lh{%epX zX~9D>Y6IP>o5I2p71ewAf^K@s>6hr`B9xAOav}rAx&gfMst63Z_pTO2Z< z(S(o$`r3W2N%R?;Kev)LJoA41`6bFRSI4x<9i4*n&I}Fv8`zbL>ce^p3dTc9DFI4e z)N5s0IWme{-)ufLDfR!_RLWk$9f}9+ft4AQ?q= z-(6Bi;d}NEjq6Kyc#t0B;g)J?NQ)ZixJ+46o{8gk>VOSs%`_FH$VzR`Ov-UKoStD; z;Qi&|d}#EyIqLuf9l;E;TtrWt(i`$L{C;BB~?jYVmKppA*gG!^98U` zR!fXtOiEld&A=Cs<0(1^ZJrM&)mAa_)Y~&rIsQ1OX2{4ah8!s`E1ev-%|9;T+u4RE z5)LhJDUeEp$>Hlx?*;`+U?QgIT3UEo_QY<%twu7nB{rpj?a8#x$Vy#lk&KbCoc}ytsd$^6*Ee^CUSW$0PS( zDp%7gc9%;1(K18t<+b6q!dln4gTS}nYiKj6Uq#&Y;eRqmf3}3@K{h01`~g~)iJ8qM z){FVy>ux5C+Wa{30(M!ei)=TXjSMd2f%HnkXCv^NoVa?l)V@9sP21VT+75a@ddHp zn*+Ok@k=O}EU9#@&AqNCZjk%kQf`J*H56rhYa0`IE(DdQho61%vC=)Uv=Jp1L8yDf zo-h@F=TWz`4xI$zzGx*<^Q*Y^Et_p@OSV0XchqPf#{Pb5Xfy3x`X+$;5H{c5aY=D> zOL_s3xlu65H(Bxx{a>@G`XxR@u^#&GV#+?Oe{r+z?j62kI(ElOb>wZ+3sXOzi&NpN zye`fh>Zd^GSJ$z>|KfS|nTcrWxvvNrZZA`%x&CN!n%-E}(sk$Zbm{E+u6F@lf6%|N z{-1rDPWu^@NnL+kwz0QeO_fIQ<6m1@D1F(mYl|>CZajWoLEU_&fSatj@B5))x4_zv z3?Ea=%k7Jgj9lCC5=H%CS%<=HiI02*#by0~zY9pR#qG4epSYcGUJ#6qvqjh!&*G7~ zwSi)`0cSU7?kjKXeD8<^B)|We#Ok_R25bA@YAjBBhB}_bs8Y5u!>0#KWK!iRqN;W; zgcIK(+a{PBEY+|Nb#(etyj_AH8ANC>6@1-UWLP)^-s2a1-V1<5w$kK2ld}=bTWrwK z5g=wd*&NIe;mi7f_AYlrHUc@u*CUZdRdP>^bSFZ{8jr-1#|Mt0LxO&0zR~bkJ28gt zw_JtS`rR$y;SYiL@`Ts48IIYa`omZ1ukR085@y?2IiW~nTJi1Ik$xQWiJEH>5p`AO zL90jth@Dmxw6!9%1jeI=Au++bMr3Wc6d)C;%sO2eEHP-sgas7T-xk9t@|)@L$NbES4`~0Lsrpd&NIsj~0cAjh{pPIA8qYG2VqKx zjxyQ)rL*ON4&L_4LNlujk(eV2X_$|s#t`j9leiD4-JnXx8`2uwtA=5rZyo_gr-oXc&E2c1P&4=?+tW{oy-u_ z&osD^e_MVn`0G(~r11+z`Z0Baw9r0Kp_sD@a9ukYc-f#x&g-p*Pc0n$b~y3KIWB-Gm8Dk|17-~>|7Gc+x~|1E3T@i ze?4ZObEoI{%%SGKL$0`Pw~&O>N<(hqT#^Rdv}93ZL{n@Lz;SxV}k_bwv&A1I`UiTVtPPDR&CKPR$P@3!fAW(^M{a)Xk|;ObvLP>`NL#_H^HN^$;NFyQ~?D z!8+B~XU4juT@8XVV)V^Uce9q*H^uFe#$hlX!$pbbKlQ2p9VxYDMic!JTVkG>dKX(V z)qb~-q8bPyi5NBvyt0j`1(nkp(`ka!NzzO*lVRCeL^zd7$~Kxl+x} zes9`}B)X&CLabc-N<-@+L*w=V{Ws2n2pJ^*qc9f|G6~fv^E;!fY7L5AgL(8`FdXF| zUx4+ygUWdPqjun(?U&M8!E&~KU5{z{eyjCr6Poxk!f+FJyq*$ZrvP4HQh&;pIvoqB z1U573KlPHczh&c9wZxPB>`)W?&Jce`jhKqcn=@$;qHM~Y*KznaeyWnsu4LVjmZ&n( zHHi?Gr1W1L+NPaG2f-0abd?}kclEwL;lEOTST#XQpsbxNbQsq;`wL42hf3N%Z*H3Q0PINr2(QoxtL5d`PTXUMz<-!>>OA?4{c}>Z*XO7>65(~nt8y%woV!z zHHIaa{Foqkm=ttA*Ae7ekqGoBvJRN5PN-L`|EPK$jXYk4E!djq`nS4ZQweI1EI=L6 zqK##|8L2aI7_EF8!xif?XoFj|PIBe>*j`cU32GOr%nnCw_Wnf{YyWC^q(lUc5}j~@ z;%U39Iq|hJlXN(({3{=i!vxE!z6^)MBhUJe!-uX(Bx@tQlj)+OjuuoD&3SQ@p=GWN z(<4EyYjkY1@0$^PrDSc_UIy_8%i&C&LJ=IPxU%GI!{^4r@WXA86F;_3D6Uj^UDxRR z=y2cW5weeQx{&4r2XZH43|nq;apdS*?_596HSLLpzaiRh_N*i!)RYu_VN3oF+YXi0 z-mve>1GmcPV_}a9shaJLz9zqltn9IF$Ff+k1 zj?Z{ZEQk}-H!4FyG)NxIbuvMVHD#U%N8x^5Zl>~l>-z6VZV7Oq{{4k((5uaAt{<+E zo<19^#<509mgxp+bk^4Z0NwNz1vD5!xsAw2KBOmz9QyF;F}Qa#X*=-aPSxNj1cK>M(Ina~|*7w|%SXq83Kp(DM zo1VgRDC(|Dnn&+AIk}ceK;~Yl%1NTv zf-&=9vzaaBS{beqdP-dhVYW%GE7jjltOeqApObI|R8%BPwrZ-DfO_lTP^U%E^ujs? z%!9)NML<_o<8}49Yj$@r?5LXN`MZ)5SijV*d-(I;49vKCK?^gnI?w7hEnSzeL9RUD zl12`2NxOVj$q86m?xpiUewD!GF4v~%g%wPH&riy2U0XPk*oJDQR{?#nuk8EL^nwSV z;reR@FgyD{X_OxU3DXHLqI>Fv^h)H(-Lv5?B(0XcbQAzReoO!-{AZgGMjXEj^MMi- zF~uOz_UTHFv6yqTtg+=AK!VXpqgtX@>a3+)^+A&E{QD|(K!xD2WeUY^eB*j<5@i(> zv)m36WfN*EK*)AoF_sLHMXz)Zldn*`?i33Aw+`QlJ*{uWt{Vs8=gdZ26l%Ab1h-Dy zwDa#u#70K?lOl9PN`c#Yn5%h0v6G`C=5&yiF@cp2CJ17)1I@R~D?Rfps zNBQE!a&`dSj8sWV8we4TjdRl`6T2`P&6@(`#QAZa~U(v*+jR->)EUMjR+lYG~#%$Ba(w?e3T&5mdc ze{@~y@{6V2WADoZWW(IAO4e5jDKjNE@NPjilR}Xr%d?)$kRBcEz5=U67o**+GtJ8D z=dJ@!O$Biz{-(HlKUFQ4zkMu8Ij5X&-o1R3$%<xxvr#j>7?tvo92*LFjyca;3P}6C(Pv@-X3fq+eMBki3;^SOuMdAmE_Aj5~Y~g zlC-oqsN{hMFF}DQY^AYY3%7~FBM~1{bjeSgI#!(+qV$K#_&4J0<>~E|NqstUNHBZb zHTV}qyCSG7#4#_4BFg$__Ydv$+*dO~)7Z#lZcf+S(LMc}uOg!mg2pnQ)w;~YM|?L{ zxOJ2GaS{X}ZrO=W6cf=zw)q`?MKVw!N$gi-5Cstpg8a6J8iBFcQl9}Brj#LOu?2?0 z-$_xU#W2VBR|&L=Sl||2a#pnnQCFf7JeCJQOr>=IVrlm~=lV!&47y=LuI`H?RT%QE zF5;K#@;dzSoU>>r1ZGF%1zwksj?Q#ykAzKNx-ZR0Bx7V);{h84V)sg2#CdbIea;f> z6*W?w3Z`~fB0Qcqu2e#Pk?-4o> zacAV_f}sJoa1dcJ9fxlP5q1!r!mB37A*DKseC`{|v{njT0ECA7P?}fYeSO!;!?u6z zXXB54RgSxV@3d_U0DL{prrVOF2U`)p)%v@<&x;?zf$PQx5+9)VM~PArZnK|lf>gwn zMamY)8M%UIbhJq!rj3h^krE$CXp{4x!M#o44|Us$5Q7?5qy0LmJkc!;*I+nX7MRED z;=RB6?((W99Ud%`sGK0kGJJo22TQR-ubjLif=n@7IM?h_IndqsaMZ6%F?6{5wyb=> zLXuEaqmG%4^R3T^x@><9h?4zjgPbu*R>W+0XOWI$e)C5YjUG(Ggf4r z90Zhl*g^+Kpf@~`0xdkOf7N0D1ta73#g-34Zw1$;{Z+i0?(=g5%})?7WY=s&glL67 zf*Gy<3L!>BuPPM!Xfl(;JsLYwHX4i6y}?)k$^6I&mfB~hP^RY4ipYE>O4BI%z{^A0 zK$gmapu-GEQ0^HRr@=Der4~SEP!3IL+L@FzHcPGQ6RofxUq?VpFS~c!s(vi1>K>I| zjEQ$c`W2N4RULIw^%z9ZwQsW4BCl$BlTEciysUe8&$1n($qdJG8i0<9u7D%+pK(Hj z7m7LX;#>m5gp+!WAc1_ngJ)0Lpll1TkD6%+c6C9iZ zr9|$Y`+4vqt$KnS_E8&$dm7RW0Dqz*a!zn6;@sP?@qA-@71u+xL8WxJH`iy!4_?xi ze5gZMC&~zypi6;B^R$5B8peMYe@73t5dD1;?BW~-xo6x4?R6$LRRgdJt@~wJOT`fE z_aj*lklAWMS?uPW$_VG)V6KVq@UkqsP_Ykl>&+!zb39>*R}}yoqd^SeySj8RgdG#& zQ_hZ!OST^^o*TH+9y#-34x?{rN1OK0R~#ArjV*_uUgWWxes{Xb-?e{wvBBgv?vXP_ z^)SZc{sht1-^!@^2{z(U)mYI^H2Z#FaJgomL=!jWUOTa-jC82?^Dc}OjZA-qn#Z!_ zVhUo}?;=k1A0a#|<=)2>D6T%Pqf9)UNSScX{_8GpWa-N5cbSGeD73}sE`cI{dqFf~ zl)J18a<$_bUDI-xGCbPI*<4uua8VgNDfEXfbbcr$cVD&@e;vk2tk7 zN3+lg3!)OoyEw-*$HC#DP3JYse^zi08iep8>dLzEI+i{0>&cKF?pZFxYZiqtzsUGO zCe!!)50!K>SX>bPgcuu~T=Gq&Eke?3@ADC(*x|(c9->Rlh=V+H(g#ZC?Z&crcC)j_ z_}a1e_3L;h4;h)%-QWzc-4|w{@*i^lPXD0|`3()E#2$hYG?aX`0s=n37jm8#<0KMSwKaFj^GioJu@k@)@J* zP7wQU-3TsS+8R?Qz2;~?N>%%7{gSnxZf5rd#x!dvl@DfNC*N-jy?xG3yt)sN?_@$H zA{<{+ZeB5v;M!#4T(Y+v88{L7XdU|^){OwiH%}{0x&wtt2(B;Ac{A{3{T?vrJco_q zw64Od7y^UgnlUUTtE`^`pBA2LZ9TStp5R1;*YPWo%7@U5G@9jE^6R}RFRyxLp!*$7 zvuiIS?=rZ-qg-uKS^XU77m%FBMv75rGe5%Z2_@>^z~&`6zZ5vWJ97Lz+3a9CTCxzT z#>FtdBKWl6WP+-K`{Ou46tZd- zou&GZ#_NPJ>aq7oXPfykZn^%EvSTm-2~DzKp*e@-JTm@j23~z+^3RH94C}^e+-Tn= zz^~+7x=}!um=Lk*+5ss|WQBjUro7AW@`I;bVv#eV@AKQ7Ts{R3qj~zbTaYrcZ0e8t z8{JPT1J7u1mmup^t-V3NVBls@=PnfxbAQD{eeJp(xqvG>-{} zS1FcALbV-hOtT7(LX`n8ld$L0=#TY~cB`^+W`K_9LFo#bmN+Yd?CSjWiE{>a&yTv< zLbP86TqxQY%^9>~v5Bk;)_gH;lqA9|-7;Y;5V6XxLHj;lk?wv9=gqe?C{A%FinEPk z>WczQP$iTSuVY)d5H>AwMqLc)GR$4V5fk$E0>1>=O{0d4UG5uy;i5A^v)Y|NJ|}qJ z3^_kYa~pk}5W26=X%I@$&^nKwnY|lfnPabfHy8{dN8nbIcHA0SGxUx^@~sBn)Le0a z&!=&+4=QylF&oa{=vCu}89(!a;MI3eJ7ZJ|%x+2XXeMbCe}m+lYEUfgMoB`GYHI(B z7`z(`1NBn_W9w4#}*)YcbRaI8ZJ~H1d}7@ z7SLdbcB6`Jg4GYzhx5SITaac=7icdOf4alp2Pw7M#51TZ*^QJd z#_GXsXX<%E(-VISO_exSytQQMgrG@KciRocOwGaNhwwj)Qa?w6UHTA;X3<1cD9$26 zTF|U!J3IbaCPL&ByBG6*J;S-3Cf>c@b=T{|R(IPK*g?93^J25V#joy810TofZ(7hqypA zis4HCAwTS1(7fAr%NhTSQ2{!JRxBymi<))$awd&nJ%O%!1k1`Pf#qL&)DGz{9=160p0$9CQgmMw36m+1t$ymh++|;z_S}+u}KBV!S<>)rdXOSgjZ1cH=lPfME2q z?EQ$Xy=omb_YG`A*E6P;XG8^uoivthO7cZhkMA0xh_RppPKS1n zj}8vx)CO;~ov12#%`Zl^{=e#$QKYav19*y-K_jqhU!~Qt$P6$n^Nf{{*w4MF_j7ZT zzu-JDuHjJ7Gx;za0u91qW0OI`IQI#gSzLd+4u9Q2qE4Sj0n@^A6O)BW*x!qCJUn{C zyWl-HVwk*DBUX4(rhWodjgQoV`<(k02jO@)%Xki5v%_-FtchaTE*j+#`IH#wE*66j zz17Ji<7_47qnS!eU%g9X3#s53P9+wE5q$rtD2=v`QCQhG{qZ4J04jqtt-fsx5V_?02KHPvpR>>r?0H8H)xCDJ6BQ>8=llyzDp zOtOKKxwv;QeWGo;4BT0_iX4}HOoG^hLzg3rO^7hU)-ADJ2&; z?e>cidWZ9lmf_dW&_4L}X7uwDB19XgmENuov6%e~(V}ycO>;bxkU|Y1+)fXXE zX?}~Lqwe)Agnj`*to=OXU&AY(F7%R1Z+H0ap^`x&Nu_`lJG_ zHr63)U8=#bDO)Noqc5a4t{ocCbVSG#gGt@LX!w}Pmrkg*M*xHD*avG4sWtX1GY5Qm zFUcv7l*w0Q0Y2W|E~~|(Xu6x27}^@g`0;iocWd5MNp&=4t!jfF_=r{n#r4m(Jq2IA z5QN{{Dhr?zkGCwOilhLjQL50Og6Sz&-K5XP^QhKbraU!ht{mMnTWij>+Y`S?XPRGn z!D=1>h@AJ=wIXr}sb3w^;;qoH5$|-8Q45=yH;zJP_OAkT3UnoMbZiG5nnue3$|4Me z57EMRre#3*| zfc+@Md*?m^LBM>EH5$Ay-i%ywDGg2n@Nf}^vh3QE&#X^|BRiH1Nd#7Ku z0kW?6&Q3edTmA2wy1cpaE)^kX93ul}B(Xf&SZ^kFphm3N=S2!&gUysq2>`|lC^Y*P zI8w!H#r5{F5+56VK?zs#;MSZ>Qz#^k1~cP&Xaj1zvAY1#W<5K^3xRjdc3^H!r917g zt{<*;$n!r`A(% zzXXgb*hO~t#IFYISErpky3_q=iZk>jBGcIvs62+}y z{F;y|0jgu39uRcu>7vV1x7w!7x;W%Hd`yC}P?+7D5Js>W(yx;sjU z6`gF+Rb@tG2ur$yHv62Y(hgnxN^jRlE^yQZ4+Y3#iZ1DxSzv8) zkVuuqfejmM!05RdLGHcJuR`au-vZ=LkM2Y;JL zUxih+Q#Z$LiET1xw4wtZAiQdqWVzAxPVt@7Dte)CUSPY{@lQB!w4jP^LID;)tu|S- zm@fTTEOFcGtD+UZ8fTPIXPLebV!+|aacnwWazjW&!*kUpp>VZA_l4<%Nm%tkaiQYk zq_8rj1g=6OhGU)2o(ce@jyF;mZS!PUYw>`bZiTyC;z1i)NCzZ~%py-0-wwP4WPv-` zh}ivl%`ZkAlqu_(LQCLKlfe{0CI9ek^GFJZ!_q(>Z%iWv#~H3QFU*whQip7%iZq%c zMqQ0v+f7Lg5LHPoa_C8(9XFEr2xd~)H2s3~3k)Z{vcdeZ%?{$AR}w^;xxc1IbMbjb zP7q9pAdwBHv_3>;d}7EglixG$zVlLIRPY&{CMbb;3WtvNa*Ouj9N8mpB|8kDNvEFC zsKIwOtaGVT9BJLXdgtJrV{{U$H@f-AprdL#yoWsooC6R5l?uF}Hax*b)X%4XGzb-F z+-19GKpIN-?4TVhQ)|FloO@{*)}R`8KCm|P7S$p>ADXZY4G58~oGiXbwn6fH0+V(Y zCbd}rmqxWtWwXhgUQ(?1n!l0WR;+lCzY)Q9Gr@#O6H%qsx{l-3Mf!8@dy8NY>)_&6 z8K?i{(<*1j_3Fe(-fzI`fNRk*Eq5WZ1nd|8rsxHPeY$houe8k%YK_0G5Vsqxzp+VzL@STw}I;3?KY1`a_>N`N)Z~`&3^E^^CfG*5}inm6y zM$X)Li@?1w!lYf0_#yxNnCTWxeCqU#z5e)#z=zlrjOeQDa_XYY4tPd%3zvvKjF1t#xVB zRv4I4hC@AzedmQmWkJX!Ux47YCB4td?>eZgI#>slp5T+&i%q?7n~X$d%n3@0>+T#n z*4PM%5}K1dPOLgK8RASm#PHYPgJO~i0ds)o{PKv%x4ShkOE&igZ`8|IQE(5X8!!=M;~LV= zWe6~pg7R_0c`Y)#C3EeSV0xszO1_#oNb5<+e zCvp#ETq5twaDbOpxy69tx5si$(kHK4ZK((Eulomabur7cl6Bzu&yoS_OiAWAIMo=n z$0*AF6wli-f|pxSCG^c;nHZ)_{77eloPZc$=&9q{dq*Q^^eHkXs*E!|lFz4+Jbgb; zc>HRE;3Qk8+$!6_@!Q!@TP1kx>7~GQRy0K2a=L6AwM&=>M05$P87C6$4ZP*wtI0!H zb=z89l>P<6yA2Ku-%iI+Mj!cCsM!HU;V z=^B$b0{Xa0i9$R}N9c;hta0IOh#a^y-|CV<&5Y5fqY6%gSe@bdvWEbO=#11~?$+F5O;#;}LxM!ERC@xP(m%y?!z zg?pe*Yk^c~LyPE!y67@+v1nyW!pzGsUlIkUE^J5m6FHKK;~Ytyt;6T7bhL?d!0)fg zcpGT2^raNm?g#g^*G`d&DRRQmSz8xyc_?Z1!Bt5m(a|6%w&U?Zcolc=_3j1<$t$w!rr~sQeV`Tm}td%v@M8a)Q0%&C@nMDj)347vW0LF%X?cA8)TGCNg zzD?k-`BSFz{OUL_v+k@r()3HJqNZTX=2Wn|Gon7ON};{z@*KJTa=3__V6UYJMZyyKTs@Tl3bgLav+QPc#LoSp9%8uMk-$*w3;I$KhyBdGVK z^H>c=hTN~?XElcI7AJ{jTz}JrPl;47HnKjsE$ggCggZ{}YY@s5<06)SXGtv~S4^xk zAb5z~CJ&hjA0o(m-t^8=WrBwKcq(+x z>Phq{XnzUiqoa(^pH}(0i^|25kKJ+1(Q?^HBm6N1+JlaZD%x_xE$U_!GR8)Byaeew z$sLJ~QC<}x=2kJKqfeOy$l$#lw6KScceA;qpq?~Mg;qVoaEA-e_;bkzLWJ6y8u6Hk z)mDC?AMWuwv4_IS9~D+OwNqWzR{Wh2^V8U2J=C2nyos|3d|+sgx%a(alAO(_rh0kF zw0qD9S&&f{DVhUPh+lWJFpRABb#%P2Z@UoAB^Ofv`Mt(fqhVdp`AZOi#*#0e^Htdq zZnC(wq@B2^37)NUi|L|^>A%gG3_r5}r-d_4Mwnhdah>^$t7ZV0wC)}cuN zVSwi*gRQQEs`s{|xWFZa&^NEb2+RHHg)Bh$;flmKfBDwA8a_VUhnEy%NOy9jCXxcq z#DW9DWY|K4xOKG@4v*_v>x=zNOJKQrl-`^<;bX!AznnWL-)g?3lJx%Aiws?z?Hrm7 z{XhCCB$x$krJDRw%o%%mB)JKhX8vFmJh-Wg0T`mh8x-w)!;D96k5of2od0slqcj#)3|0suZ8QwbN{blm#ralB#4yB2KfzV2Z`fq( z$yoynqCCew!*KXp|Z8NKj?bNc8V49FcS3|NVTwvG1OHsEdSM;;w@LsJ3rf_T z!ym^lo{d;2D`ND)ko=EKuojg}M zzlRg-Xe8D*z3fY!rHX$V^t1(eO2z_s8^zJMPvIScow@;H`Og*mp!84clFsnPZ!kluh5GdQFGw%;_YhKxj z-^#B=$nt9w3kYBakl!u7W*ATR`27(rRlIH=H8qaum&)Vi|Kd>^wIhj{eLJsm4yEz- zp?b62eA!~LVuRLwKcW7TSor=a2bp|+*=x!o1MLn1CP`SW zJHC60C*7ThbIw5bY+)V$<+o$lNV?rzHbzxMNGOY!$99ZGT9;QJ`=fSB(c8$L zq(D-;#@X@rRT#O^FjIczI)J2lwE?*_@qj61fO4iI?&WKbx|@YuMbm&AZt8i-&LLUA zuO_fhF8aIO@v0Hg=46A97YKvk!P_CgUX}LY5ot4x2n1Dd|RurQnKgqu=ySupSOB=OOC8@=T zZHnKnHIPL_QHy2Xo7yXWR0jG9k^jaCZMRpFx;nXc>57`h-2PMhc6@e@cRd{$wwP{Q z)S<3$g(emc_j5{&K)G=i^r=QrJMW6H;x zRvjwK;LxoI#bkamUEnXhdYPjD=9x%(KK`G{)i1(_)M~JEgAr)Lms0o#aIzn0r7cmW zeHx}25#u8uL(FEqbpZcf4&y=Vt)TjP=&92|!1Zkz0nCpWN!V4?IvCQ61p+WZ6cfKK z-e+%8k|qXinxLjSsX426AKE&-3>EEV~0aIUkhUB7r;RCqzLV zlyN22z8csDZry6C=CdKQF`3?dJ!W$1LvQH!bvOv1?^D`@=fh7YqAJ8204L9T85*4+ z3pRd3uJj}LpmU&JWQ@wrf|Cp6lQ7fpXv06bh_Y{og~UF{p8pz2<0j$+DE)6pEH&`2 zGn-NEyx~Do`DH|w(BhL+2GP)tCVP64!juY9%p%jWf}!9Wp3=u>;G_rd55pBpURXv= zotG0qrDJKRDvoO-6>r3+%{PZsCE&+@Z!vMG-L~r=Q)1jAh+v`2SiYfS@Hu}LuqO82h2emF+7-Lzt}*> z#6T*{T6=yXoEgG$3o)393p6qQ`yanij6|I}#=f13sT#XQf`Dq@f zS$Sxso>1oV0AEH!@uP_`URntUBFSt3!pGOgRh*HWBIlpS)!dO9BG;(yy0214nIE#< zY%hFAX2N(@e>a_!1wN<0e04{B&n>A1zqwDS`OTwaGJmwMG~X>E|B^X>X$2w47HCzZ z3-|4gNDHq1c;Kv#=PdjCgq{UOR{1`Aq`Ya(Ft7B^2x+pxjeVFCp~L(~mBs&BsfZ*E zwL7=(S{!QWVwuA@%^f=o7Q~ z%6s|(T>W$Br`6zp9e&6qHmm4Mb|tFG|b>b)uDl;#Nv!TH=J!~^_qSo@~*iy_CKW=Bm*&aHbwdrN*zT745LGgV4!#uYd!-wnt zkU~XD44i1a>;FXr+nu_S?>YA3CY59I6AEq8D^ADZ_wnU2Recx!8Pv%sMvu0=mOy(l z%b40u?EL|=>i)CV+-evINl>R8KdvHp;iR>MdG-8N_!I|jx3K^>h_QZRz9SC+tHC_&Z zl^Gdi@zcpTM6Yl~FQbvsH5oK{9M6M6P`tL^1iX23p{A>ejJ-h0Ek%I5W z0~V2CNF*Muiej>GKui<6!%cnz+|m#O{WtU97`MRK^NrBwOhY@OJwwjO&XbzqWmYq<3dDiR|N$f@8D1u?Cj>i z7rb$mzl*4vYM6jf?|nnd8Ih$+7wP@BDulVDec)FN?SEt%D&G2s2hg|4r0w>i0!>yE zx1Mur+u)(UZd>HXeVl*lk5yIWr`>)Y??*(J0#S{F%89}1t2 zCFVT`Qsy(z~V{!y~q-26*QJjtKDtLCXjW zdTwGNK&;j zW`AASZeWWIbQqZjC&x$&3(kI-h`?z6VSVR&d3<4D_9*6yyjp3sSU|u+^H&vUE`FV$ zTfDmGGy$DS(Q(S(uj^~&7hhaY&SIvCGp7DMj1>pOND!f^y$l~TDf{47sRo}>mW=FE zaEIaEun>myP8Fa15qu3@vriir+#OS5(f#+?vH4%FzPs&E@F&KL#n0hjvihj2P(KH( z4V)mQ4-FXp&2b!F>-Sx2KhR_15+-jhIa6I3jW@L5b;aUxpXm&k>oc`>tseZM*Ebe|ZN)=Ry@+2(?E? zUiG}*vm;Lgm=F52vkD(A9{>u;m|5#orLb~;oUPeqrI**|LQpc+yLvDZZnv(3-A0pVZ7 zGY1TxDZ}+p@WeBCwQQk6LirVi&$IE&XfIoZ|wB9h}xqI>4ki5A1&$>T^kJt=E zG{X=)wxJ72SbSMZO+bu4tYle_ws-j=Qn9Tb&a7eG!idIq1_F|DGqz%?XpR zQ>XJ?C5ME0V=xo2m-isdx8H+aX2XC^dHeiaihv0@=zB00&6gqXYQum|+5R64a?tl- ztZsjgqKNrB3v5!`h0Ysbmp2oXwz->4m^4T~0wVVMG{)gd@beAYD7N1iSIYf{S`nva zw#c!gByK8`>JuA^Qj1J!0@-;}6@LvwW=a#t~y#uJUfzV8YrKWYW7r9OI&?gA8AW%)0Y-oG}QSsh58Y z$+5W4)AT9ceh-=WBM)!Zu*p1e@#YO(emH!{%$xXC9Glib&q#yersSQXNB(;C}?nPA>8TZhX1!-B(NjJdSz0#*Kl=)} zj?tF)AqrnOvjOd59LE#>;>O6uo0qGC-I#pQBnHPtc|6aD#Nqm>t zPQ0C^BF<|56g0(2baH}Ls4Qq`li9*$K1-dMxF@mvb0Fcc~) ztD?D-mCPw(`+fL=g{%{cM&fw7i??lB??foRi9DXLNqUj&vtPtJFWP^gi)Xqkl0#g) zvoj64c&0B|@>?D3LXOp8eC^%yOOovva11q|ee(SL_;^z4?K8x&F&EkP{a%!L`pQyB zNQY?F07Kap`f|haxQMHqjcy`LppqY$dE|Q($&1{Rc;nY+V{vqXC<^^h;7pEQ5y#Qp zhygN;LmR`^-3RKX;DUd$M9DN|5S$Xl!R35(0#Q!K7>*AR>v+|&b;t)-nJ=?P0RHi11MVDg_;;rJ&JPv6BS%A{p zuk3EZB-<*?{pNqt#;~c`U;H=SNES`RnbCVeG)0r3^|orBJAo3&p^sqbLNL>dx2-sKtJY+H&`n-_%Ij>`|A7Ih*NSF5(5(8aFpMK@G@H6p!X~5J z0!*6Lr6N7a-uq8?d75lFO8H(fn#!XIFS1=J$A?2=&Uk;|S>NJqrE0Z7Y3E!Bydf$5 z*zVMjXBHCCZGk4$U)?_a({pdX37;wKMddpYagl6&CZdxrKZ;$*i|cg2b5?Ot1uuVQ zUC_MWUh<}n);+$00ngh&iN&^7tK8)FVvG$8w=fi{?Zju{XtiM0!+e0D`l@2UfHJEM zM60tc2StA)12>dc@T=M`Ku%m^vbRNHFqd+it@-uOB4gMqtc9710%7C`1&6=XL0Ddk z>LurxL}94G?62djj#K`rZcbe&l0AyRLSswPK=@0J6$cpRO>URT3|wPL7|31oj7{{u zi)@dZi6#)G8yw(3=(J$g`jx>~zW`0!ep?RPRtkS+?7iVu>k8Oj%d%`2?{hh~azKD0 z+3#8IvsMXZd(k*@w1P}I6u?7rNHUI@;g%i@f$4bwe+Gmp_d#X-rh7CLkB_HuDgOGG z;hRMUQ5oh#m}o4rY$>~+n~0Qho`IjQQ)$`U?1pT=R@FFISKl0n(f{ZaU1qvze*7x# zKHq(I$(J$M^1aQNC0^F&y+~{j#RqWr3Bkl0}a}W6kYcY#IDam8s){ zNX0=^gv#|vR%dZjigEaj zgqBV7tP*dPEDHDgc)widSa#J)Q7Z&NfRsn)V}QRKzvINPONT`w<_N|;}Juox zJl9PXr76Bv$Dr^`hBAWdrcToUS8XhdAlg)gh!4CtmL`Vfy-f4{r+B;G^NxVAMA0<*IAVu1S`Z?bA{!Y z7nSZB(C>T@v_k)8(fL!7D&LcIdDnmLMN2IbH5xFl%p?1EUfFVP@4dPTgZ{$b*Ve-^ ztj~c*A`t9oeLlE~~3GT}fXG~mga*sZh*00fkdJP$p!*x(w^uK?UE3Rv~ zbD%zz&aVT(rM76_)Z_Ou`pxS_)_g;^)=E()1a-Ymc1=y^N4zo`3$z~8p#EwAceO7V zXy1!L-S5RVFFZOk25YT^^VL1beC}Eg%CJeY?;PGz2kN;tG7GeH4$ICuf@aRZo#!Xa zI0%LtVp5q)vOVwpH%N`^d1HSoH2OtWB-@ve#BK*PXxEkupTx^fAn?Apk^?7I7kj=E zu~&**@>s;auP_j!Qy&X?7nkM3OOe<6mq3^^4rtKiDAFVgm6$Gh5Tbt%Ps;-8)wveB zfwkWkVy~)952DEhMeNu8req_xDun0at@(W#dt4Ar(CJ`2)hV?5OzeL?CuNoIi}-L_ zZ@-JG`}@5pMe&*^Y;Y0K4;zUe@q2mu{M>!z+k-KIcIuNLv#^Yr4`LuR4kZ4Z=$Yp> zN%N+u^1O-NCiz{2<6JYsVXFa2Isa=H=wixXwpnO9hj44 zXx^+^A=RF{>56MA%$r69>=ToP%=&6^AU%XXK zMXd5kgOSjp>0P}29`D6hQLL`&UG%hdmMx3?80!{yQydgU{C*Y}MdI`DF(e~X5zfJi zfOqe1sP0>z%WsiPh2d1j2k*(#Ce&0H&%~8LlyuqDM^Wt4{7Ej4Wz05HT{zRXKc9I| zt2bE&Jrsj#M6!QomXYWhjjDLcGXwMOcQqfa5(o9ci$QCR%1jXq&=LpYea(}d{+}_wNx8_>M8h!WvmS_$#|9|={MB>O^45UHov(T@c%G6w zkNVA%?G!*ZM#qz0F%~D8DEjaGDTdyrXey6KJQv3_f0zBoVHh3yc*xIr83@l(#)I9K zVXzEcJXC*sUxXnWi{tS&qIgZVA`ISG9FO;P8z|*WVIbDIsD$iU(+la7Y~Ovs0MmR#v~g{ zE|P4-p{ZlOa%?&f3kUd`JHMI*&!j%2U8NA;`U5W3cg z1}TKIPpX@?%c(s|W_9GObDBT8FOk>tSD9||z5b7qDQ%lVW)a^IkfUQn67A9e3fv7SX zl(nW@=45WV83P>VU0gK9mYRsm4LFs?p>gxjAymV7oA}LHanTsUG_0l~SEv4uurZXD zMIzP5e%DU!D>sqGp|$&Z-ODllAX$CR0EU0r6v+N0jR@Gyd&-1i3YjTkdh^t|dL^*$ zFG=RHsM@fVLSR?lslSFVVCJvw?6Z{G@?BX=ZMyQ+T?o~bCWPEWujWZ_EroPG^V)@D z;(oTa6-P&)U%j363&PQVCcovpFqgk+x0d$NcyU=Z4+P*AQ!=<=uRa<_;El8({w#mS zD96j}HBOV=NwKeGr!EV?oF;-t{(+Ol(t~hZC#q_2A+uCgapsFJ4>$&%+}3)nqt!F+!zwc>u2@0%aW`JZWAmh$}JY){X%Q7adX)SwXO zaV6xU2?hdF3T4k^jj;XvaDCO5Yz*!rH4FrkJH}Qnn2fWnxP4|Yx5a1(H*rzqKh`Qz zNR&<#iuCuU{9s6rP6ldwm6RMgu#7+e83_exOn>-flE+^RrLZ}NZa;&4>w z&-0YGQ$a9FQ{60*Eg#8P4+^4ZL9=87QwnN-Cx;J`S8>@?gyh*q{uB;HD9on$KjvT< zguvF_DfaC%#1~*BhsNMY1XBwNz*G&vRzc+N|1;0HtUD>F{g+xd`#h~X8K~{AoE4y7 zN%fy!S*kz3;%Yz5&((i&R)l|8pH>gCk4(804t=0i+n)1?z1E3(8KCWHo~I)Aspz!E zh7i#DEKb$-um0Yq63|>dshQH;)`9|L^?|{@7A@K0owXM&s$^oW8AbZ zN}*0y=J7YxfDqSmBPxIQUIu6@&;0Or?NorKdIto5+d&6t+)d;2w>E#3facy+_tqL* zWw(ucfOZ>2dGPPbzz>Wha_G{?-o2akPOx`y!@lGClCcy8z08_zEuT$*<7(y&2Za?c z-O}*y!<^`>`F552q34zAJXKopmj8S9zMB#Nw@+$o7wXkC6aZeHw+!O;kpHVI?q$|0 z0KC2>J2_Rd&Qcb@i16gD*!5Ic#oHjRAxQZ?{p_M-bn>kJ=1IYvJ-)- zFT)dG}>^~(U-Cf6}b4C=_zZXLQG=El2W)A;O3t_JsacWt|xhS_q za-6wau_&ExG{_>T^ifj_lM%5vmLLX1Rl!&YloG;P_Li1ad^mEr_hJ};nPvgnd(nb*E+7dlj}T1*}(@x>Al#v}G@&db&^@dVv+6_ezw0M!mwa6QK+m zKLXsv&4SZilL-E9Qf0+4ub)!km5heOiWl~w3VD!DTx5SM)j@_`SNG2kw#vGr*Y)WI zfId9Y8%ZsDt11fBO$7$%`^Re}1Mo!E;Xw5^w~yMQb(eo+vxmNb4I@JcWIVS}0q!_n zq2RERqZwW|!Jx40gs%8PD!Z=w?VtbT6`w(2)#5J5r;2V zxrEVRoY%?}1cO+mIvb5k)eA{JNw#V1*W6#`iwu7UPu8!Z=!eneI#z~4!bv>wfpUKm zu^e#U2>)l!AcZ$S7te8>x@WBrAv#GqjQL&rNN@iX05h8N!t={g)H@HU1QqJDM6&qH-^e%_p%_IXy&{a2ilZ zzf{kE`zlw~^Hd)UL|d7{_BAOJJ?|z!o}GxZ5X#D!dPr^F4^MeI{5>doG-C>m5>J=? zz>4X+pT*#5kGMpAfF2*O;wRzX!{*YCl(c^z9ZwCy1&69fNCB=klPN|4czitLOO>vH zaYjv!zE_Q{>TF^WtI8H%SJc!;c?b$GpRG;f`}>Cfa%xQ)kA8D6zOmrq~WmiLW~tLD11eDitX$&g6IrL6^nt}ycI%Aa#3bf*QjmkU~CGgpquUp6gse~7Un8AVRL$nuJ(**sB?25}Zbbznl= z)F8G&S)^^_y97*XGhJt;L%P?Sb!ceg5_;``c9EX4c>4Xr* zUQ-86W56`RsqtmyUcf{$mttT5-T&(Et#y#L%o8D;sz@ZRTA?imhp1k1_I@I#Dh`P+ zSqwE2Li2~6T%+DJ8n^FP;+3I(X6Z*`c_`&=Ch}*-Hs45(h{2PCT%sr-p5lLXkV2Vr zWnNPZ3UD9);G9cp%Yh-xAr+Qq%|sE3(wi4E1|j#( zn%`c+11IWq!Cc&9PSo+Feyt(P)O1S?itr^%477+U^xi6g-i&r zs1si%l>4H3tyt&XfogxEL$5d_ZwdJltH8_pau*1%lzgYqu4f&x{GYb zhqEd>%l0YW#yc_F-9CS3Z3LT_PEv99QfJ?twUAlmKGdvm)4V^RG*y6QxrO@DqN<~g zWQofUdbGJvi$~PtQFU!FR)$JsiNJi-Pu1=$`k+hsE!Ezo1*CYZjL&3$O9kfKmfiD* zbV7_R5uk6ALp-BvNWeVX6NYO~-;oT=TUT^%v-I85eIf+&|LT8#mA?Y6ansZjV1zmQ$%Dn?m_WMHYn-*PD zcYJg9jm%;W> zXqQo0)lX$K$XO=uFL`=s?!U754^q?!~cu=RlW>r!(H_(|#o#X9!6Qq##j!`BD?FDI65g5gW8pf0if5xxy#lNhkK`ka+fP;>ojKYHfd+(Xo2n(>))dL`?o?s|NHz0 z-LeS`v{AbZ$g;nfY0|Y`!R&Stc!bH`5m1J2 z$*y|gVNg;y23b6uq{%+>yWus3C5GqtDvC-TJjcp25k+$4sk?6##UVv-zAQPDkSE&` zvr9D=4438_)iB1PKStWffcv2 z&DUe^Q(YbEK&ty> z^}Nv)phmH)4NdhhG#gRLGc-$loos(fVrxMt=yexq3#+>*BXZqE`he;#+QzHyqP)O$ z7iCDTyGScY-DNQGj2EWvqF+hPmDX{ju;w?UxtFO!X2n^jiif8y0CHo9sapu*E@v!V zi(;>akV|id896A)u#l65#38pr(jLaBo>bl9MK#JyFOOTvXhsnML@qN81W>k;Wh{qg=_aBuGr43zY<*MHtTdKqY7XOG z9!;m-G+#F+`}c)ud=TKSDeCfy+*aWt;ZtZ)V*@SODAD@R_^?Jq_KV8J_`6O$NDL+} z9O#$XwKy~vHYoYngaceFsx5!%gD@NV9=P<*uX#dPC)k9lsim;d3|dGEIZDk%VQA4Q z_zE4DD30q}UVMMb^Y8Z}Rr{QjFUgTB2Q6uXDCuo=#Q|%qYb$ciQ#m2(oPO{dwk{?hIte%vLEk0mqSi+%7@3q87Cmn2TA|8CZ;Gx1%LnKB6A3lz=k}F z zRE@ta9HBVzmw}=o48rZ$2#aj{ewqEVYqg#1cI^+^n8>N6FpP;>2zNM^Z1|=xkX4k!+(1u!|>MA7gba{0q~`>Nup1JCZ>WNnB;#Q7vFdJ4?4qCfW&bx zHdRq?tGW<7c^D9xXI_ZJ<;B9_|LY+o+goA5?&`TB8xum!MN#{0b{`=CR`|#Yj$`OQ zpQLedP+x)lqe)PrcU$7p+|9s5f0ceT_aP|Nn`Z0bs2g%LUw zaE4(yYMWm`>xd^P{rb~66$%k-($YN3@|-0o1!jnDo&_{cha=Km{C+$m4GPUwzE8G9 z3Og*t{W?+S2dMrAB7{?d!XlUNm&YcXdEP_wIut5-#;(38KgCJ9vd(-SYF38GR3$4r zC@i8_p}_?GwtvxjLV|9iFK$jfhUkABIRuzEW_LJ2!A$ltff9M83PXyFBv57lEC~Jy zFi%9dK7p={(&0%UTZ)TqQ^oG1;&5C_hQg%w&zF7TJeg`$4$RoEu$CP^z0UkP;xSXV zp4t(dz|b|*2>y0Zymx&-I;sF@A9@n|rY_ph%LkRQEq_CL9@eiL_r`~do*MygsdR3t znx>{hqEmJp6z#2V`}R-{gs~M4?b@D_g^sQjj^es6n&77~(z6RicD&4XvWFMe<23T^ z!=l~)QR|@-bTZok(Z21E$o9_gXo?5yHGkmyTESz@Z{4z5%c;^@1?5gJcW2>df=2t@L`$(PqD zJKSUtk{9}7c45G7D)rUu>{syg67|EV4}$k9;&-%J7Y6HwG@^T8Cb%13=o#*o=jw`> zCFj|tF<}35@tkA{w7bag9s-hlsZsWeEqv0qVSkC7_1*gEb$zmErp9+pfk4vr#G=f* zKnTBfReu`>WEXAo ziALZMAaIbp(SCZKNw=+I_xU<@?$9>2wSNOgeOOQTrF|KAK@hfl5O4C%a~HtB^$hQ7@J%H}zHyQ#{weE8lW-N|8ed4S%Lz z!Ryaj2qV;*qujTp+mh?#a2!4^*_m5$S%FY)<$Jb07u#HQ^R7nG@|*_6IJd|D;^R6A zNN|08{8WhYB@@dl9~`z(9}s2xQfJ@W^(gW!*i`;F>Vpw1)l6H0=Mauy`Y9>OieNf~ zBbZ)h&v{!>i&KL6G&}*~Dkep|4}V6m)LV;fsc%(vcauvOh~@U@g%`?1 z0|SG95YS5h;XSIr7zM*RE*yw4=jJ#B1LBm{dweqXfiP~WPpGK~s|M+5zI*@r7pP|! zH0ne88UGKm@&6zj>n}G|Tz?5##4Q093{o;!0%VMCkt{7KhS2^1q(m4(lL6#Tm+31t z1%}Z60HhQcLel`w;w)b7!go6BU_{Fy=i+^butf8wmFfjxho?a_ZA01MSnh#!+V>%e z##yOaIe6bTAkDUYR()%pz*l*`IA-N^ABCqu+{AJ(P@ii*QJ{g`)_>JLPqIB=pBN{` zC_D|~t}b81uG_C4&0q(|AQ-*Co85R6lI$8=AA^#NY> z=t4wRXnz23)x!yZs(*SI0CJcKFcZ=3Zv^(R#}LQ%)uUF|KkRQ1eY( z$fKf0hpj;Yq(n38Hdz+$?F_u;uGbt5 zCuQl+OO~bjMSo-mz}kGtl5M^dXg4by)b#Ydf;$aAhRUBcKzDhP!P9OO0%}CwQLeT1 z*-*~GKpAMBkWj~%9Xy!5xF#Ift++b>%j~(E=5vwl)1-XqzXAC7zm3L$3I3l7k!^|g zqp$?`{w*d)4gk~O1cuEq&d66_92n{^PpJUk`NNN)@_(DO)~hT}%59Rgp8!tnFC#M; z+OvIwxul)%I4IQnp{TQM^9Wm8JJ{NpKZjaiA3msuj;f2NaXVouuHrP`*Wy}K@viv* zUwU2*I?;*@4QY57-!`qf)nzA6o@gRLWw{o`UU-1m;i(k80R0k0Qw=K3L)^s4=jx0E za2&=_E`Qy(S51}WZ2dqN3uZXf#i8O&bXTXTKarurK%`F3@Fwb2yopx(6joS3oe6G= zU(@9I*(2AC!=osy`O)29mMaA&!%T2Gg7r7>Oz>HxXig1B=$e~76ZN%;+7_x~qV|HU zKeOCLqIo>?(K-eFInAr4wt)2IbPBR^Uc9Miynla^&S~<|@-c=Wt6oY@yjBj!sIo}& z_wrTt(5-JpOL5#pZXG%mzDIkGi`K2ZLMA6igO|N6l1-GTWbji{ z+&s9GQ|2hzqfg`v(nN0M1wT>7O|`5?rR>&WGF--4DJt7tk-sK8;94{{(?o)e#iPuc z*P_y4#+lqq*ukbbk}p|VALYCcvD<84gnt*)ycUwKZPyLm%ktUPe+>s~14K?4D%06Z zoMav_c6cg9|CW%iJCdmem8Pj!o|KhGqKpKn9AA?%u`*8k1s$Iy!G_IxywN67 z-f-#%*P?pKciwbUEgrn)2Xb;uyNG}X)2WHVHO|>-Zl)A;Vw4FsoU3C6XJJ5>5Pvf; zv{J&LYSY&vamETXV@@lH(*ko&yr4^U_Q>&OU6 za&Ef)pT`y1eH@(1(DnpU8LZ$m2HhD*12Dsq+`GO&lD!?6y0D< z*nyG$+c*`QA4%1;P7%IlD5T+N{1@&y3W&08t0es-9;oX$oR=xOP@5G%V))FGW0)M* zbrub6(C!<+DhQLM3l`1j5UI{faL-Op(1annHFs*0h)q`RzCwFX6o@2pvwwavgc+E@ zpPCaK8bq3r3i?Lrk>-Rvx%`2ANsO<%FWZSnh`!ODYEdl&AvKFZL~*>OsCT(~h$g?Q z@9>YqB@GnJy@VE+<6IMaFB?v4WDa4mDost&@&41cu3pSqyC0WCZE@DA7 z1Urov*O$1xnm}|rbSdNxjRN>mC289Ud6s9dqNw0yvJ4y9K?&ZfVJqK)=T<7;AsEW@ zTai?wM}YncYOa4BO~Ug~ptHan4mdY_Np{B4-ehr_f1T_i>W>;P*Oq*b>@!4Z_`UDLg5qW5K19-HbRA==ZBG-rIIry)Vkp7XpU zf&cujF$sM3lrpGBi!IM18-AWoaQ!j53<3X5~UZ}Lcf zp!&N*;|S#T*i?U4SbvR~Xc7Qqa~;3QR9F*le+HJU zVUjga@+L_kl1-(!A#YVOUF4% z*zK@>+IC`*9UkL6e+rBT&g{W3zKHUyqFs{hc_HUjiI}{2Y*_MZUNpBN5zlq}3Jc|; zFcEfiJ_`%yoF)-*d~^#7MVhS=Nf`>p24=->)2Z^UBP0kXqJ9KJqhXq@|eH$X`f`S}x)*p&vp!5T1YdE!ek$87 z54(3DzkfsfRX7i+gw}lINy^D!US! zoP0Vn-{BZ8Bkl;EMaoG+7M0(`9V_g_QaryQ` zMNXAvW7&79r(JnDyJeQG|Gv4s@%43RESvfoqRjN3v7hQ}OSPLQEF1ROj_NlSaM^W9 z@c1ZGUze;4=N`HII*CXsM1}ywPo9$L(Iu$j*q{HcXTP(GYqQHtSE+ymJ${PGA(>^n&Au1Z>D#XPz=_C3f#FV zbLuTeye*++|Iwoh?K%pNGCSFBMXDxJIjfl%UqfmIVf4Vn8;=B5?9AsR-pdTVVsu@n zRnlaDH?gDpIYd@$>0U?!ISN?J%_4?5^?wp8mcyMykKI(mWx5eX(zQ<896fvmH621k z6O9?uS7rDqFTOXG9Q_&L_9~sMz>7AU&6R$?$+zDHxM1syM!}b@NKt{r!6yPZ`o1Pe z^XY>xTdC|xOfDm=)1#I9W`fW3p9f!!`$1zlEA3UJ@T5H6Cz)})tua8~49-G4YP z3!|+;a4|x=j7CNJwn*U#@W%DXtv#L0h39F``+p|~v zwLf|N>dDKeFHhdYjGeqrUh!0oPflKN-xtfdMwThRu8X?QG;hUMXZ#!aZ~w*rZIq}< z{QT8x9-ZXLi}jQBix*E{ZQeY;dlElmuYX^~uih-%vO4Px-``x!XU}J^lO#EL^7P3Q z{u(AvH!qXd>o`7n&P#N}hUng&P5&AlbpS*g>3-gz+8GFj!Jbn6f*yYujTm*z1q$EVZt2`{>nXV0I$;xGK0ySoj0 z!3)^r)#mj{^77=)Aw6~Lsy^I}EPvvsPoKPe_2hN@^!44VlQ&PEKRVD*H53_y@->9Hzr=cc=h7tizBpO4ferHRGjM|i`5B>pYm4u-OD#`-aO&u z(B>)6tS7vI{Pd1@rGGZ-S1^{E{hR=~5&tsXK;Z8RFM01?ui44-m#^M1UOm4_;#ViH z*RP&GNr3Op&)q~`{qu4zm%e=d;ssm3dd=H?&o;bA7H^(CeZhMSG5_}2Q-{1!>=|z_ zq`y{smZY1s>8#w9>3XZZ$M4kdpZOoZy*iIp`X4Veqc*%PdVdo0Jj>thm#b}~D^5xkxhjt?GKiAumRexy-bfvyq{iWXGBuiO7YNEb+!h5K9Z=OGSnY`lZ^fXT5 zH=+;sH_vXdR*{i2wASvO!BnwF2Xli{=FU}`j{{4Ub%{CCVFWDyj zdBO5+eP3NwOCT(d0RmC3YL?&2*^UzR2ZYesOrJ z+MmOs(*;`@&-SH52wZGBwZ}hi${^<+rUu8w|z5R>fV^V*i$L)zdwLUMW zmT17N_Qj!IkovSN_381x$aegdtIAic+B3V_@5^ex^Je*_>XI*r{kAOjTTyI9-nuG_ zx_`JkY^I*jZ&&XwS$}d)s#VZg1ZmvhE=d-x2k<^50(C z4bPShd#kg4;JunEHMGBe_x8e)KXvza%kI35EHd$BT;I21Pe)?2wdz?~PFJZ~eL2hV zWU2+SkCX5GyqE+Zr~=KV^PFZPYoPi9Jw-PVdWoNL z94MW5&7%&)Ug4*P2THH;)7=B5Hy)Gt!wkCocFitN7|JbY_^A~aL#5?xKYzE5WT>{B z`4{rR)8&lbtQwmVaLVA5p_eoDcn#uEV>vHdR=*BKmb3AAweV15IRl%koF~fdxxq?Y zmD1&JZP{@(Q}5dbKz*Hg9X8`Q8Y0En-3gg!$5rfJ6N9XqILq$h!f8;tPe%R zAMUUBhh3b@b)3ETgrVF5aDN%^ZR5E{QoKvIXS~+h#o6Tiu^H#64>6n=9txl5HQTZh zAl!sl68?19-GOvffF;>$nQuWU(FU277HhutYSiT{eMl?*>D}Xhva;y@!PT(~5KRcV zax@A3`GJ+9?C=1YQgSDGh_iJ4w%i_eyd&#HVpnn{5np)N8^K*YKYy_;&p{7NWl#_I z2_a{Wf~OuUE9QeR(r|W{&>zJ3zfT6R%D6II$N9S0t>g-54+g7@GedF6*J-}}#1b)@ zR6hEEOlrB(e95cBeqWR|TVG{yz2WKV!84~eOC$=Ik{7XJpeIWXJZ#}y^tWN7J}B7h znr+jHx5_*`TM4i?uYZ;j@vkH?kA_+ZoZohP8Wuwc0rE+fb~G$QEk~TD74(s1d-ujj z=Wm2|bX>)o>0O6YMk3Ixep^yp7Hem9JAy^96mzl~bJPB0&NZ;GBqsG@LwKUDRn;s-rZBaDK&O!Grc z`=&`IrHex<^7=jik&s0Jt(e#{MNg!3QApny`%VueR8ctpH;V(jX+qTrM-AYRww?x( z01V!oEO{4aW;hs(5jBb!3Ni1WW^2k+X>p=P8Hcs1#eV@s+eg_1+{851{Qz*}0Ybel z_*eWFR+2tUUDk=GJ77Uey))Lvje@K{!l6yMULTG4J`ao7>*Eotz=)MM;)gOUVy}-z zJYR=J?Dg@8bzsEW8}U;X7O~eyBVGkg#Vc4UswLs1)&4*dfFWjr#koGK!)BBIq+^M6 zSr|{r;(zb^BF#zqhAmAe3S#+K@3NcnkS8%sXQQFfWnnzcSClNx7a)#H#y=$Fc}AB7 z@vQEPvgUs5sw~9(-^>IFoN6o%ViRYZ1js|WER3fKMB0FDp@!NZvTsGX4)XS!!cI)> z<{>#LN!JtUWv6=~%?YQs=Xq7fS;p31St-`ORDUx7DoivAGE^5m)%RsN^L|VmDAw0{ z^0bbq6S6ui&YMGArl!r+K)hT8^LfwISstX$lj1WZVi@2*i<~wIrnGGwmvJT*8?bdd zN1@&UQl2G`S*|Nqro}oWmDOREDI|>p$LG6$u%sq?FEu%v+jX38=?Z~fZR9mr^(v1# zyBs2oE(WiwN-R~1MP62PPXSLo>Ler?F~Le)k8L`pzgL0>6uw zAI~VD0q?iK&nU?O0V|h^(I`LxueZz5D6j(o*SCDtC{zP~Pxc{;x1ijvSsNN4ckr%g z-PUbOwBd(Y5Tjc5WK284BWni%uUD z;)QxjUC1RTaO20V!DIHG)dgW{cZfP9p+fbb_1^M-tR@Vv8Q1mb+UsBwYA7W67^#Q` zVnCp>*wa418ATWx(R1^AU^Gw4>k*0DV7&=U5hnn-2N3F~0s-`K$1U|%?k6wVO+`_; zJ!Em&w>_cTCT%d0T@}RmHRY{yEJ+i1(NMmr{dR-573}H|6+SY8Lp|ly3E*pI2F{uY z)L+ei`NdiGNJ3(jgEFb#FXKGk!rnoX#gK7j5HrPUEUiMmoeDzJ0lcNN5VyA~Ip1cy znXrCT`yh$PB8xN)Eph{{11w}uu9a2EtT6Aq&eh4_Ai6i^Oa9j(&g3Q!?d9>uTQ)#} z2g0R*JnV39EDr~BIZHPitdj@}b9=vrR*AZQp9<~nh?wx|{9LEG#%}7$1RqbO;Ocz# z?wMzGGgNSPRy`QhcxG!olt6p)M{p=hme*&nfy610NR#u25@*>ELJ2t4dtx%F z3B)rpApFW~6U!#%%A-~Ps?_mptn_uhMGg(+*CrVf* z9{;Y_$v$iok{Gx=QDwe3iGxdc<*tz!3TVxKlI8aR%Rn^0u^JYMDqD@jus|Y#o88ym zJen2?$2b;qljbR|yEl2#W-Ez@voC8QM4dOlgP*T?jV9i3M5Ag1*^7Aq$qY=HbOS{^ zns>3<%itld%5)c(kKuCKya67(X|WV*oG@jW~;qG(GW%N|8`ceBmJf{_W@TmBELNw%iVRIZyvw*w?tyFS=FmDlKdfsJL(y%I zv$xRwEpvDyT~|z>5efJJ1oV!S*2v{fe-y(5`?hF-L4MaPN0pvhV31$)1DC;N(5Mr@ z7_&8YPFXW=Mce`EvZ(fITHN?G->SbsYys@BH0@|c8VRdy%}ZES6%$(lRf3HE*f%~S zL2D^8VNMrg`P7dV#W^>+IN1j9juu6LIbDp~p3M>BH)%x|n_(mWXwS~km@cMbfB5AH z@v_>u#-a^)+uf1aesf*?fU~xNBa0dwX}QewgLKk|V_V8WKTf+K9L!_m{tyYeV}A@Y zU6lGI)~qfZvzdY+d5$A31kRv<_5>QM!I9*M5@mL`3nIY?k-T8$Yac(lMQu2)Ua9!O z4V0Ww#Q9sz3xi!2Io5D>#|_Ove@5ZN-`?K-#&TAs3EnQ!6kygq0};|0J{qBn`^Dg% zE4n1bgc=M9zST-2aNKfbG4$Hqp?Sl1cT7;o;{{*!RpW4;Tve6>YNYi*1&&bg5~qJJJ`~wH%@Mm#IvA@S1Pi?b6S3ctXz!=j zo=slW*EgPgee$960Y z;n#$OI-zru5#H4mdX->f=5$e@;h|pRLy27BJk|iY;|hc>D98)@0JXrbe#0R`xam*< z>x_-GUB{I|j6%XaMJR{^Hg0{`MK{@yXf6uH6mhoji>8Q^Rh>^$f4wP+tdgfWR)x5< zK%89~=j+?s>qEZ!D{FoQI7`8((Tke!k)Z}>YEL(A?_2la8A{<{5YK-K#x*M}!|?3F z`^Xm z7em_Mjj!df1+Ig}z(szv!55Vhy!(>!(EpSzp$~DIfwq1QQ7me3B=JqN!|$4H(~4IJ zUQkv&Bv!dSh%VSE?`G7{Q&p{8BS9P(rWa+waqdA)L6AK#LkovfVK<%Hcq-7I(+MDa zdvE{)Z4^%Jf8q2jc}7}roUd_q5D&Y#cPNDoi4K7*YK}-BvLeRyu)2_rPQM+HC4L*w z(MPnTx2!~2X<;4Rey@sLO%kIF&ENn}v>U>w$yI2(COp9P&NE5xP-%+mlXoEcnJ1}{lvwq4e09QJ&=VR z#6k~X0SB*e9x#2?bpS1s=zZG206%!|LjK>;;cHydjB!p0!8v^G7hKuCWa{v=%J|K} zQVS}rf3?uAhF2f2zT|1mBh1Ql^QiwL0-#Zg#$rPrUf%w=y_F@sI{7@UL>FoB#U#Rp z2mh5zMyyt;F7%>7=;7}WhE-A4@5K5)3WQE%?hp-@6%r^ zUF_F8>D6;8@2Ihk3}^SZ5fFpsJ!(f+|5Xv1!tjpY^&#iEjQy+PHMGaYr}=*Q#&XI? ze+*5%(A!u=c0^J`ArOKrWq5(d;67zw1e$1xJcA#L_-NTW6{7{d$=0m zXDqwLZSDCOaw+EpZ@^ElbF+K5>)NJ-z!2>kdIAhX$^}F`w6}SjJ^qtn0mc%p#?8y+ zV{A&e8eg+`?c=J2ceX5kRC4mp%Xc8+e`@ZR!$t}&wpZz%WxSums{pL;Si;3vk*b+? ztg}VK#rmdf=nwWqnM0`XTb$ayZ0;!Kz)hg}WCQ}eb@Ri{bii!u~~e^C5+ zdEsf_E6n&do3dm%^Zuv2?X;NL?`1b`{yws3I9gv6@p^8b*`lu@;9@G@Q|}mCRov{o zo#Ccpw$$6$CgN)D_n1ctF1CJ_V7sOm^iJgo9RPw~#BCxj=Dg7Hj=M#}(b_N0LxDL{ z{;}D9DsJJf1JnO{e!z<8zP!ea>J18n|$0&ff-Yk`r-hAVk_>m zd>5DMD`!*n=g~-D#AIMSe$eDf;CZV)D9i{Mv!Q^isTjWTu~?2J|W=0eM~LAV)*RsATo0E%zqM`sK9f7ekLZo(qY zl0znLQ`SEN=kof1+Q(%--0Z@Xv-6a}1VS?||NiH`$YIk1%S2P!7{FB$XOKaDXF5|D zg!ZY(KOJ`BkS|%6kkURs=g}OJ}%ihNCV1h;Kug% z11lewPA)_s>AG+df7QS`23s^Va)aeX#71CG_*s9djeM<6ZS>+Zxu z`W_Co-H3vfs}3dU`BD9tjh#PJL5-8(#k?u z+GTmv$6 zIlLG}((6KKL@GMhMi3lL7{-$n<@%i%PmWz0T`(kF8$?z701nN&L+R2GCRHY^Me#uV z=yYWSkyx=De*{Pf!+CD4*GY$^FS` z0}ZEfUMrp1b>3LSeyqV}!{ zCV-T%`UxlbeT8bGI1{z{a5CO~jmw~^6}1K!IME&qe@oXnVDPTez;vyF3!HYc!Cjn* z+1C$Zq{n%fOGoTZHn1{w0~9tRI4Y_O3?KybhE1?P*yBoD0~`!+-~$J}NOx)dd9$gG zL2ENZAR`Jy2&8j)XkxkV?nQ#lZ{?jslVi!@AFpWx$Gm3MA*&beyYhw9P2h;yg#f__ zH4h*lf2)!*y<_q@gu&AtU~un$?z1?}yAPO7p(ADE5E)KL+RMk)U)k}H$972WcKZC7 z@DrY}7?}5L@VAv0CBV*sBevBE1}iT0E90!27z@HVG=U*rK30Ea=~Wgd?7qm>b633j zK#pxNn5uAgUPy=LG<-0i@`SR>*x`&LG-GQ4f5TH<^5BnqY=gm^KMT*F&w6U!JlN+l zRNGQ2BVgWzsmdE|7|>O`4fMdIG8iV!n-g|iPnkntH6GIkggNr@e%cWbxeJ~$T;|sx z5${3R`W0ERYO7&_Jz32G2)8cOYC2WNiA%Wyy|)%4AnKM2gs=F=HVDk1)xO~XgzGC} zf7FT@SHh7E8uOa{DAQnX^wW0~nedDF|DB zn-(xUy+8;8ryD@gM9!_5xHdHqT5kYD>#louJ&6%PH}C)g$|~u3=*n+wgTV|w>^Zi< zV210gY5Fj*`76 zq;k{?18GDgKE-8O{0PFN%LB;N8C94$&P6I+8cc+nNpfU@%pd7g>ZB9g(seg9(*eqd zS$^xr<-Q14=fO;)y79Qrpz1v6Wv6aXz{RISvM?#-zF=AB`G)8@x$%5+?khDse;*Ec z(wsq3eN_jU@b6dmjMbt&M9kQ_MOHHawhW`r<(40bIi+UQsl&nK4^eSYzY2=1mq((B zi`G*Gpl~ekMOBkM?k{?0Qjvazuy(b_b`b! zP)BeDDUwZb1eIC{9tx{b$8ZHGf8z{oEE8sP6pYM$o7Bg;-piu|Yo@N1!!;%Exs07o z7(^C*ceu01Jl>^A*F?U({ltFO*X*wYt7_D0%>~+_VKnx0rx*W6b!HYIHC-Ug&*VPN zx4``8LemJl-YNY4dOc8yxF-E-s8c&+8%-X77L_f4oTZ@2Z1z z6_*up*3&qLJ~&!24K7bh2!+`hp!u55D_$hjY)f0-n4kkEFJj_id<+UH$92AImdUj$ zUrMnmsmLC}Wl@V2mRZ&S>W;pUX*)9V;>GN31GBnsbF*=($)ZCJ?%zW=H4_}?sxJ25 z?pd&;Z1w%<_#b82=S^tHe@MD`qvnstKou^&sPA|C`qAwgNl)C)i3GWA>AWk}!D=lN zU3c`2!iOy0eu%Sh?ZFPcbD}`LDG$dX7Dm3nm+?=;3P%KRYeWF7iu0o&H&(vTpBQg= zh+l&@q71rBtIG96WFKhF%NP5msKth-IJsvIH^zE$>t+_GCD^-UCGF^*%W9`MeeK3eYYn|FdQ!!Tde|v}q98eZ8V0inC)! zW9;b_g;iZ1lKR+@u(^6gE(8$TF2f3TD1&+gRsyJ0_T^?y|TT=Rf- zL?IbzxCLZ+d# zGZX(Gf2zourRhZ>9O5AZi}xi8DG6avtN4-S<`T_79Kxk$asqJ;#35XmP033*?%R<~ zird?>&zJ2B5DqLFxnNLN;uwu>&=iaY9&?y^oIU>2tpFc5tB^C=@|vYp&D<9Lnd)8G zIsHTOoz*;|?MIAHtI>Rd*j*po20P~+xeCN|e{~-_*0=MvQU_wpKZ5oE&D(2g5D2$g zV%~bLS{NIyc)1um?ipP0ZKT}nKgQL4_p6t?q2zAvSTxPK&Xzoy-5>1nx3W0wePgQW zI2+48pI^4>RNPF}S;YiNtP8nWU$ZJ*^V*9rZ`&o^a8~^P8B<>nq{mp!5kpQT@p72v ze|;OvIbx`!yS+3s8{y%3GsX1VX%eRA-MVPq;sogkd0&$XmP16erNd9HFV zDU~4#XX5#Hm5T33p-fdc)eY}kGO-MSf0W8pouw+*DetPJHKy6Bg`V>$@=c1VG*rMv zWqWJf)791_C*XN^NHf_Dd%qrR!66{pUrGxqmRl@SIYHHZj+wrxwi`SkAb zZMH4Sw7%bYqqNe|gffUuv=kd1Icq-vC+Qp2Gg`6yS68x?=zeMbbg`+pY{vg^VKP5 z3>;WRmr|_1tXat$BjPu2I3W^Q6j3z3&vOLh{1g?7YBtlQ%SaDFLXsv!IcE;>f4ZD3 zS!|LHJU2|V+w1a?L+#^yl@zG)f9r;%Q;Rw=1VbGs-^mz+7>uF&*ewpg3}B3CEV4*0 z-@I#Ka?ZaKJYq2jHIUFm5BE7iN)Q4Aqbj{TL8_7=4B+8mOZw!_X~Lb+^4EoV&0t`jCTACv29_1UBvdw3nds zC=`Er+s&AQ3pS06$dChaREM4W=AR{sRt&U+|fn$!<+T8 zZxdt@tP4g%Jp_pSo{mF)?Tm50&5M$eAZSv~_F`plnr~^Ig&_t-AV~sU%NbzxJ>5H> zZ7^fr>Np$U+?T}3e@&xzNST{qC-SAE$oISYN0c>XSrBcrS?eDpv?(8q8;{Gn#gm*^14jL zIWr_+ld^7DG!#J7^L)d~lC3G9(1fNd(1W-o>utG}OVp`|?4lqfvD`)-p+pL0kp*F0 z6kBnk93hdZ=msNZ0BIl$B{%aw*yDevqCU^%$^se+yQCYAJfyNYRF;Ous^|vOoXXpl zn8_mz(X=cGOH7yL6mtk8`WJ2e z`)fC8o{L@54M#iPi@%daF0^Q$n-GdzKibIqtn{O&bj-!|V8mj~5T_WV2#h=Nl#}096@-sMuea%xtXt6 zwrNJNc|LMJ7k`RiEa!^x*FoKwLXi$5H5kNiEN5lh_TShQf5nRR=pRW4JGE%W2~DrA z^9)Ts;ew_P&5I>Xw|SiTu}BF=JJ>}Pla?-bQRue&G|NOM!_&5te*xGMbQLrmM`N1K znNzo{KLo4!EC#9(w!Kc&$vE1s;s|2seDo-FJENQn*(XeG|sWzmTVh~ zQJD5i3`Y|*vdFn%WSBNjZ=21vcQl(EmB%`pd^T_OHhZxM*vm;OxS6RL+kNcm*vmj| zLoncY@U^~yuw2!fw!fhcsW&};n?0p|Y}if~dcLnCHFtc_0TzKX8?SH&VwkS0`9m=*mg%#=H-a?h ze|o|4ZGG=$uIV@#pT=4CrDAf3#K&0IaWvkib)2QBD~>eVR>je@@+y)Rz;k#%JJgvDYr($(QwVKiZrkNv+F?0(LT%Ke|^Qi-KRCHcp2>(^P!qE1aE-& zI&%q#o!SXUV5)>1t#^00-5{E&lyJ1mlh`v|g#y6rTUy_*#3{hYDWrk3A?J!w$0=%+ zgYGRg91RbsjWC+qVRjo#Z*}(hvbl)6JNpzpO4+(kX<~sY@AQ}y1tNXoy;)fZ5vGx; z2?b(5f9q9xm*Ezn*l2n|Aj(x-;Fk(i2y8D zb?i4jpvgGe9(JER2Oe7uXG8Bdv=ec&{Ob^Be_jmm>L{sw!+N6}H@leeP z;zL^cbs(jHo0ZtT^EOEiyF(TuuRiQ;hhlCB&8M4^d1YZ;$I1A&lJT0MytzkheeZlV z8K|v%3y8d>768C6hqW3`h97S(FaCaD<>QK>_ZfH2BQYF;=RC4a&kZE5ylPz$-pNQ_ zfByJ+?eWS_!_sO2yHXHw!%z zSxGqAU5c|HPUFgNX1Z4anzo+{-q{lWMgtLze?4w^D z*=jf$Ud3X3%yZdsC*o?UwnB?(2+z^Ip_Us!=2wA;@NP!M56^@Z0&Z3%^If&yNI2Q? z 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, row(['id' => 1, 'sku' => 'PRODUCT01']), row(['id' => 2, 'sku' => 'PRODUCT02'])); + yield array_to_rows([['id' => 1, 'sku' => 'PRODUCT01'], ['id' => 2, 'sku' => 'PRODUCT02']], $this->schema); - yield rows($this->schema, row(['id' => 10_001, 'sku' => 'PRODUCT10_001'])); + yield array_to_rows([['id' => 10_001, 'sku' => 'PRODUCT10_001']], $this->schema); } public function schema(): Schema diff --git a/web/landing/resources/api.json b/web/landing/resources/api.json index 41752dda5e..c2e0a73e83 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\/Function\/ResolvesFromChildren.php","start_line_in_file":23,"slug":"deterministic","name":"deterministic","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":23,"slug":"setup","name":"setUp","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"config","type":[{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","is_nullable":false,"is_variadic":false},{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":28,"slug":"extract","name":"extract","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":33,"slug":"from","name":"from","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":38,"slug":"process","name":"process","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"rows","type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":46,"slug":"read","name":"read","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRmxvdzo6ZXh0cmFjdCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":74,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"aggregations","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBBZ2dyZWdhdGlvbnMgJGFnZ3JlZ2F0aW9ucwogICAgICogQHBhcmFtIG51bGx8R3JvdXBCeUFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUKICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGdvcml0aG0gZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":98,"slug":"batchby","name":"batchBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"column","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"minSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBidXQga2VlcCB0aG9zZSB3aXRoIGNvbW1vbiB2YWx1ZSBpbiBnaXZlbiBjb2x1bW4gdG9nZXRoZXIuCiAgICAgKiBUaGlzIHdvcmtzIHByb3Blcmx5IG9ubHkgb24gc29ydGVkIGRhdGFzZXRzLgogICAgICoKICAgICAqIFdoZW4gbWluU2l6ZSBpcyBub3QgcHJvdmlkZWQsIGJhdGNoZXMgd2lsbCBiZSBjcmVhdGVkIG9ubHkgd2hlbiB0aGVyZSBpcyBhIGNoYW5nZSBpbiB2YWx1ZSBvZiB0aGUgY29sdW1uLgogICAgICogV2hlbiBtaW5TaXplIGlzIHByb3ZpZGVkLCBiYXRjaGVzIHdpbGwgYmUgY3JlYXRlZCBvbmx5IHdoZW4gdGhlcmUgaXMgYSBjaGFuZ2UgaW4gdmFsdWUgb2YgdGhlIGNvbHVtbiBvcgogICAgICogd2hlbiB0aGVyZSBhcmUgYXQgbGVhc3QgbWluU2l6ZSByb3dzIGluIHRoZSBiYXRjaC4KICAgICAqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAkY29sdW1uIC0gY29sdW1uIHRvIGdyb3VwIGJ5IChhbGwgcm93cyB3aXRoIHNhbWUgdmFsdWUgc3RheSB0b2dldGhlcikKICAgICAqIEBwYXJhbSBudWxsfGludDwxLCBtYXg+ICRtaW5TaXplIC0gb3B0aW9uYWwgbWluaW11bSByb3dzIHBlciBiYXRjaCBmb3IgZWZmaWNpZW5jeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":118,"slug":"batchsize","name":"batchSize","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplLgogICAgICogRm9yIGV4YW1wbGUsIHdoZW4gRXh0cmFjdG9yIGlzIHlpZWxkaW5nIG9uZSByb3cgYXQgdGltZSwgdGhpcyBtZXRob2Qgd2lsbCBtZXJnZSB0aGVtIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplCiAgICAgKiBiZWZvcmUgcGFzc2luZyB0aGVtIHRvIHRoZSBuZXh0IHBpcGVsaW5lIGVsZW1lbnQuCiAgICAgKiBTaW1pbGFybHkgd2hlbiBFeHRyYWN0b3IgaXMgeWllbGRpbmcgYmF0Y2hlcyBvZiByb3dzLCB0aGlzIG1ldGhvZCB3aWxsIHNwbGl0IHRoZW0gaW50byBzbWFsbGVyIGJhdGNoZXMgb2YgZ2l2ZW4KICAgICAqIHNpemUuCiAgICAgKgogICAgICogSW4gb3JkZXIgdG8gbWVyZ2UgYWxsIFJvd3MgaW50byBhIHNpbmdsZSBiYXRjaCB1c2UgRGF0YUZyYW1lOjpjb2xsZWN0KCkgbWV0aG9kIG9yIHNldCBzaXplIHRvIC0xIG9yIDAuCiAgICAgKgogICAgICogQHBhcmFtIGludDwtMSwgbWF4PiAkc2l6ZQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":150,"slug":"cache","name":"cache","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"id","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cacheBatchSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cache","type":[{"name":"Cache","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTdGFydCBwcm9jZXNzaW5nIHJvd3MgdXAgdG8gdGhpcyBtb21lbnQgYW5kIHB1dCBlYWNoIGluc3RhbmNlIG9mIFJvd3MKICAgICAqIGludG8gcHJldmlvdXNseSBkZWZpbmVkIGNhY2hlLgogICAgICogQ2FjaGUgdHlwZSBjYW4gYmUgc2V0IHRocm91Z2ggQ29uZmlnQnVpbGRlci4KICAgICAqIEJ5IGRlZmF1bHQgZXZlcnl0aGluZyBpcyBjYWNoZWQgaW4gc3lzdGVtIHRtcCBkaXIuCiAgICAgKgogICAgICogSW1wb3J0YW50OiBjYWNoZSBiYXRjaCBzaXplIG1pZ2h0IHNpZ25pZmljYW50bHkgaW1wcm92ZSBwZXJmb3JtYW5jZSB3aGVuIHByb2Nlc3NpbmcgbGFyZ2UgYW1vdW50IG9mIHJvd3MuCiAgICAgKiBMYXJnZXIgYmF0Y2ggc2l6ZSB3aWxsIGluY3JlYXNlIG1lbW9yeSBjb25zdW1wdGlvbiBidXQgd2lsbCByZWR1Y2UgbnVtYmVyIG9mIElPIG9wZXJhdGlvbnMuCiAgICAgKiBXaGVuIG5vdCBzZXQsIHRoZSBiYXRjaCBzaXplIGlzIHRha2VuIGZyb20gdGhlIGxhc3QgRGF0YUZyYW1lOjpiYXRjaFNpemUoKSBjYWxsLgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHBhcmFtIG51bGx8c3RyaW5nICRpZAogICAgICogQHBhcmFtIG51bGx8Q2FjaGUgJGNhY2hlIHJlYWRzIG9mIHRoaXMgY2FjaGUgbXVzdCBwYXNzIHRoZSBzYW1lIGluc3RhbmNlIHRvIGZyb21fY2FjaGUoKQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":167,"slug":"collect","name":"collect","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZWZvcmUgdHJhbnNmb3JtaW5nIHJvd3MsIGNvbGxlY3QgdGhlbSBhbmQgbWVyZ2UgaW50byBzaW5nbGUgUm93cyBpbnN0YW5jZS4KICAgICAqIFRoaXMgbWlnaHQgbGVhZCB0byBtZW1vcnkgaXNzdWVzIHdoZW4gcHJvY2Vzc2luZyBsYXJnZSBhbW91bnQgb2Ygcm93cywgdXNlIHdpdGggY2F1dGlvbi4KICAgICAqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":186,"slug":"collectrefs","name":"collectRefs","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"References","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGlzIG1ldGhvZCBhbGxvd3MgdG8gY29sbGVjdCByZWZlcmVuY2VzIHRvIGFsbCBlbnRyaWVzIHVzZWQgaW4gdGhpcyBwaXBlbGluZS4KICAgICAqCiAgICAgKiBgYGBwaHAKICAgICAqIChuZXcgRmxvdygpKQogICAgICogICAtPnJlYWQoRnJvbTo6Y2hhaW4oKSkKICAgICAqICAgLT5jb2xsZWN0UmVmcygkcmVmcyA9IHJlZnMoKSkKICAgICAqICAgLT5ydW4oKTsKICAgICAqIGBgYAogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":193,"slug":"constrain","name":"constrain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"constraint","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"constraints","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":204,"slug":"count","name":"count","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICogUmV0dXJuIHRvdGFsIGNvdW50IG9mIHJvd3MgcHJvY2Vzc2VkIGJ5IHRoaXMgcGlwZWxpbmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":224,"slug":"crossjoin","name":"crossJoin","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"prefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"''"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":241,"slug":"display","name":"display","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gaW50ICRsaW1pdCBtYXhpbXVtIG51bWJlcnMgb2Ygcm93cyB0byBkaXNwbGF5CiAgICAgKiBAcGFyYW0gYm9vbHxpbnQgJHRydW5jYXRlIGZhbHNlIG9yIGlmIHNldCB0byAwIGNvbHVtbnMgYXJlIG5vdCB0cnVuY2F0ZWQsIG90aGVyd2lzZSBkZWZhdWx0IHRydW5jYXRlIHRvIDIwCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJhY3RlcnMKICAgICAqIEBwYXJhbSBGb3JtYXR0ZXIgJGZvcm1hdHRlcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":268,"slug":"drop","name":"drop","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBEcm9wIGdpdmVuIGVudHJpZXMuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":282,"slug":"dropduplicates","name":"dropDuplicates","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAuLi4kZW50cmllcwogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHJldHVybiAkdGhpcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":289,"slug":"duplicaterow","name":"duplicateRow","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"condition","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":309,"slug":"fetch","name":"fetch","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZSBhd2FyZSB0aGF0IGZldGNoIGlzIG5vdCBtZW1vcnkgc2FmZSBhbmQgd2lsbCBsb2FkIGFsbCByb3dzIGludG8gbWVtb3J5LgogICAgICogSWYgeW91IHdhbnQgdG8gc2FmZWx5IGl0ZXJhdGUgb3ZlciBSb3dzIHVzZSBvZSBvZiB0aGUgZm9sbG93aW5nIG1ldGhvZHM6LgogICAgICoKICAgICAqIERhdGFGcmFtZTo6Z2V0KCkgOiBcR2VuZXJhdG9yCiAgICAgKiBEYXRhRnJhbWU6OmdldEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqIERhdGFGcmFtZTo6Z2V0RWFjaCgpIDogXEdlbmVyYXRvcgogICAgICogRGF0YUZyYW1lOjpnZXRFYWNoQXNBcnJheSgpIDogXEdlbmVyYXRvcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":326,"slug":"filter","name":"filter","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":338,"slug":"filters","name":"filters","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"functions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxTY2FsYXJGdW5jdGlvbj4gJGZ1bmN0aW9ucwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":352,"slug":"foreach","name":"forEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"callback","type":[{"name":"callable","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEBwYXJhbSBudWxsfGNhbGxhYmxlKFJvd3MgJHJvd3MsIEZsb3dDb250ZXh0ICRjb250ZXh0KSA6IHZvaWQgJGNhbGxiYWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":373,"slug":"get","name":"get","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gaW5zdGFuY2Ugb2YgUm93cy4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxSb3dzPgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":392,"slug":"getasarray","name":"getAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gYXJyYXkuCiAgICAgKgogICAgICogQHRyaWdnZXIKICAgICAqCiAgICAgKiBAcmV0dXJuIFxHZW5lcmF0b3I8YXJyYXk8YXJyYXk8bWl4ZWQ+Pj4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":411,"slug":"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":432,"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":453,"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":472,"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":500,"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":516,"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":530,"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":576,"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":597,"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":611,"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":623,"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":635,"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":655,"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":665,"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":673,"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":680,"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":691,"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":708,"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":736,"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":749,"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":763,"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":777,"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":788,"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":802,"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":812,"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":840,"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":858,"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":871,"slug":"write","name":"write","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6bG9hZCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":21,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"aggregations","type":[{"name":"AggregatingFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":28,"slug":"pivot","name":"pivot","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"ref","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"values","type":[{"name":"PivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null}] \ No newline at end of file +[{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":31,"slug":"and","name":"and","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":36,"slug":"andnot","name":"andNot","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":41,"slug":"append","name":"append","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"suffix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Append","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":54,"slug":"arrayfilter","name":"arrayFilter","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayFilter","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBGaWx0ZXJzIGFuIGFycmF5IGJ5IHJlbW92aW5nIGFsbCBlbGVtZW50cyB0aGF0IG1hdGNoZXMgcGFzc2VkIHZhbHVlLgogICAgICogQXBwbGljYWJsZSB0byBhbGwgZGF0YSBzdHJ1Y3R1cmVzIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhbiBhcnJheToKICAgICAqICAgIC0ganNvbgogICAgICogICAgLSBsaXN0CiAgICAgKiAgICAtIG1hcAogICAgICogICAgLSBzdHJ1Y3R1cmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":59,"slug":"arrayget","name":"arrayGet","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayGet","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":67,"slug":"arraygetcollection","name":"arrayGetCollection","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"keys","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayGetCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGtleXMKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":72,"slug":"arraygetcollectionfirst","name":"arrayGetCollectionFirst","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"keys","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ArrayGetCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":85,"slug":"arraykeep","name":"arrayKeep","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayKeep","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBGaWx0ZXJzIGFuIGFycmF5IGJ5IGtlZXBpbmcgb25seSBlbGVtZW50cyB0aGF0IG1hdGNoZXMgcGFzc2VkIHZhbHVlLgogICAgICogQXBwbGljYWJsZSB0byBhbGwgZGF0YSBzdHJ1Y3R1cmVzIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhbiBhcnJheToKICAgICAqICAgLSBqc29uCiAgICAgKiAgIC0gbGlzdAogICAgICogICAtIG1hcAogICAgICogICAtIHN0cnVjdHVyZS4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":98,"slug":"arraykeys","name":"arrayKeys","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayKeys","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGFsbCBrZXlzIGZyb20gYW4gYXJyYXksIGlnbm9yaW5nIHRoZSB2YWx1ZXMuCiAgICAgKiBBcHBsaWNhYmxlIHRvIGFsbCBkYXRhIHN0cnVjdHVyZXMgdGhhdCBjYW4gYmUgY29udmVydGVkIHRvIGFuIGFycmF5OgogICAgICogICAtIGpzb24KICAgICAqICAgLSBsaXN0CiAgICAgKiAgIC0gbWFwCiAgICAgKiAgIC0gc3RydWN0dXJlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":106,"slug":"arraymerge","name":"arrayMerge","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayMerge","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHJlZgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":111,"slug":"arraymergecollection","name":"arrayMergeCollection","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayMergeCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":116,"slug":"arraypathexists","name":"arrayPathExists","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayPathExists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":121,"slug":"arrayreverse","name":"arrayReverse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"preserveKeys","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"ArrayReverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":126,"slug":"arraysort","name":"arraySort","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"sortFunction","type":[{"name":"Sort","namespace":"Flow\\ETL\\Function\\ArraySort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"recursive","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"}],"return_type":[{"name":"ArraySort","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":142,"slug":"arrayvalues","name":"arrayValues","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayValues","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGFsbCB2YWx1ZXMgZnJvbSBhbiBhcnJheSwgaWdub3JpbmcgdGhlIGtleXMuCiAgICAgKiBBcHBsaWNhYmxlIHRvIGFsbCBkYXRhIHN0cnVjdHVyZXMgdGhhdCBjYW4gYmUgY29udmVydGVkIHRvIGFuIGFycmF5OgogICAgICogICAtIGpzb24KICAgICAqICAgLSBsaXN0CiAgICAgKiAgIC0gbWFwCiAgICAgKiAgIC0gc3RydWN0dXJlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":147,"slug":"ascii","name":"ascii","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Ascii","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":157,"slug":"between","name":"between","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"lowerBoundRef","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"upperBoundRef","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"boundary","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Boundary","namespace":"Flow\\ETL\\Function\\Between","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\Between\\Boundary::..."}],"return_type":[{"name":"Between","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gbWl4ZWR8U2NhbGFyRnVuY3Rpb24gJGxvd2VyQm91bmRSZWYKICAgICAqIEBwYXJhbSBtaXhlZHxTY2FsYXJGdW5jdGlvbiAkdXBwZXJCb3VuZFJlZgogICAgICogQHBhcmFtIEJvdW5kYXJ5fFNjYWxhckZ1bmN0aW9uICRib3VuZGFyeQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":165,"slug":"binarylength","name":"binaryLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"BinaryLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":174,"slug":"call","name":"call","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"callable","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"returnType","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"arguments","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"refAlias","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"CallUserFunc","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGFyZ3VtZW50cwogICAgICogQHBhcmFtIFR5cGU8bWl4ZWQ+ICRyZXR1cm5UeXBlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":183,"slug":"capitalize","name":"capitalize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Capitalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":191,"slug":"cast","name":"cast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Cast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gc3RyaW5nfFR5cGU8bWl4ZWQ+ICR0eXBlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":196,"slug":"chunk","name":"chunk","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"size","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Chunk","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":201,"slug":"coalesce","name":"coalesce","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Coalesce","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":206,"slug":"codepointlength","name":"codePointLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"CodePointLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":211,"slug":"collapsewhitespace","name":"collapseWhitespace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"CollapseWhitespace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":216,"slug":"concat","name":"concat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Concat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":221,"slug":"concatwithseparator","name":"concatWithSeparator","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ConcatWithSeparator","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":228,"slug":"contains","name":"contains","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Contains","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":233,"slug":"dateformat","name":"dateFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d'"}],"return_type":[{"name":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":238,"slug":"datetimeformat","name":"dateTimeFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d H:i:s'"}],"return_type":[{"name":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":243,"slug":"divide","name":"divide","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"scale","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"rounding","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Rounding","namespace":"Flow\\Calculator","is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Divide","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":251,"slug":"domelementattributescount","name":"domElementAttributesCount","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementAttributesCount","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":256,"slug":"domelementattributevalue","name":"domElementAttributeValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"attribute","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DOMElementAttributeValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":261,"slug":"domelementnamespace","name":"domElementNamespace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"attribute","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DOMElementNamespaceValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":266,"slug":"domelementnextsibling","name":"domElementNextSibling","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementNextSibling","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":271,"slug":"domelementparent","name":"domElementParent","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementParent","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":276,"slug":"domelementprevioussibling","name":"domElementPreviousSibling","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementPreviousSibling","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":281,"slug":"domelementvalue","name":"domElementValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":286,"slug":"endswith","name":"endsWith","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EndsWith","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":291,"slug":"ensureend","name":"ensureEnd","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"suffix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EnsureEnd","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":296,"slug":"ensurestart","name":"ensureStart","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"prefix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EnsureStart","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":301,"slug":"enumname","name":"enumName","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"EnumName","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":306,"slug":"enumvalue","name":"enumValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"EnumValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":311,"slug":"equals","name":"equals","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Equals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":316,"slug":"exists","name":"exists","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Exists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":345,"slug":"expand","name":"expand","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"expand","type":[{"name":"ArrayExpand","namespace":"Flow\\ETL\\Function\\ArrayExpand","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\ArrayExpand\\ArrayExpand::..."}],"return_type":[{"name":"ArrayExpand","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBFeHBhbmRzIGVhY2ggdmFsdWUgaW50byBlbnRyeSwgaWYgdGhlcmUgYXJlIG1vcmUgdGhhbiBvbmUgdmFsdWUsIG11bHRpcGxlIHJvd3Mgd2lsbCBiZSBjcmVhdGVkLgogICAgICogQXJyYXkga2V5cyBhcmUgaWdub3JlZCwgb25seSB2YWx1ZXMgYXJlIHVzZWQgdG8gY3JlYXRlIG5ldyByb3dzLgogICAgICogTmVzdGVkIGluIGFub3RoZXIgZnVuY3Rpb24gKHN0cnVjdHVyZSgpLCBjb25jYXQoKSwgLi4uKSBpdCBzdGlsbCBnaXZlcyBvbmUgcm93IHBlciBlbGVtZW50LiBTZXZlcmFsCiAgICAgKiBleHBhbmRzIGluIG9uZSBleHByZXNzaW9uIGFyZSB6aXBwZWQgdG8gdGhlIGxvbmdlc3QgbGlzdDsgYSBzaG9ydGVyIG9uZSBnaXZlcyBudWxsLCBzbyBpdHMgZWxlbWVudAogICAgICogdHlwZSBiZWNvbWVzIG51bGxhYmxlLiBJdCBpcyByZWZ1c2VkIGluc2lkZSBhbm90aGVyIGFycmF5X2V4cGFuZCgpIGFuZCBpbiBmaWx0ZXIoKSwgdW50aWwoKSwKICAgICAqIGR1cGxpY2F0ZVJvdygpLCBhZ2dyZWdhdGUoKSwgb3ZlcigpIGFuZCBvbkVhY2goKS4KICAgICAqCiAgICAgKiBCZWZvcmU6CiAgICAgKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgICogICB8aWR8ICAgICAgICAgICAgICBhcnJheXwKICAgICAqICAgKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAgICAgKiAgIHwgMXx7ImEiOjEsImIiOjIsImMiOjN9fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqCiAgICAgKiBBZnRlcjoKICAgICAqICAgKy0tKy0tLS0tLS0tKwogICAgICogICB8aWR8ZXhwYW5kZWR8CiAgICAgKiAgICstLSstLS0tLS0tLSsKICAgICAqICAgfCAxfCAgICAgICAxfAogICAgICogICB8IDF8ICAgICAgIDJ8CiAgICAgKiAgIHwgMXwgICAgICAgM3wKICAgICAqICAgKy0tKy0tLS0tLS0tKwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":350,"slug":"greaterthan","name":"greaterThan","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"GreaterThan","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":355,"slug":"greaterthanequal","name":"greaterThanEqual","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"GreaterThanEqual","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":360,"slug":"hash","name":"hash","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"algorithm","type":[{"name":"Algorithm","namespace":"Flow\\ETL\\Hash","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Hash\\NativePHPHash::..."}],"return_type":[{"name":"Hash","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":365,"slug":"htmlqueryselector","name":"htmlQuerySelector","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HTMLQuerySelector","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":370,"slug":"htmlqueryselectorall","name":"htmlQuerySelectorAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HTMLQuerySelectorAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":378,"slug":"indexof","name":"indexOf","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ignoreCase","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"IndexOf","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBpbmRleCBvZiBnaXZlbiAkbmVlZGxlIGluIHN0cmluZy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":389,"slug":"indexoflast","name":"indexOfLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ignoreCase","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"IndexOfLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBsYXN0IGluZGV4IG9mIGdpdmVuICRuZWVkbGUgaW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":397,"slug":"isempty","name":"isEmpty","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsEmpty","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":402,"slug":"iseven","name":"isEven","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Equals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":407,"slug":"isfalse","name":"isFalse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":415,"slug":"isin","name":"isIn","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"haystack","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"IsIn","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGhheXN0YWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":420,"slug":"isnotnull","name":"isNotNull","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNotNull","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":425,"slug":"isnotnumeric","name":"isNotNumeric","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNotNumeric","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":430,"slug":"isnull","name":"isNull","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNull","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":435,"slug":"isnumeric","name":"isNumeric","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNumeric","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":440,"slug":"isodd","name":"isOdd","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"NotEquals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":445,"slug":"istrue","name":"isTrue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":453,"slug":"istype","name":"isType","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"IsType","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gc3RyaW5nfFR5cGU8bWl4ZWQ+ICR0eXBlcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":465,"slug":"isutf8","name":"isUtf8","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsUtf8","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDaGVjayBzdHJpbmcgaXMgdXRmOCBhbmQgcmV0dXJucyB0cnVlIG9yIGZhbHNlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":470,"slug":"jsondecode","name":"jsonDecode","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"4194304"}],"return_type":[{"name":"JsonDecode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":475,"slug":"jsonencode","name":"jsonEncode","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"4194304"}],"return_type":[{"name":"JsonEncode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":480,"slug":"lessthan","name":"lessThan","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LessThan","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":485,"slug":"lessthanequal","name":"lessThanEqual","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LessThanEqual","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":490,"slug":"literal","name":"literal","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Literal","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":495,"slug":"lower","name":"lower","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ToLower","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":500,"slug":"minus","name":"minus","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"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":74,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"aggregations","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBBZ2dyZWdhdGlvbnMgJGFnZ3JlZ2F0aW9ucwogICAgICogQHBhcmFtIG51bGx8R3JvdXBCeUFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUKICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGdvcml0aG0gZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":98,"slug":"batchby","name":"batchBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"column","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"minSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBidXQga2VlcCB0aG9zZSB3aXRoIGNvbW1vbiB2YWx1ZSBpbiBnaXZlbiBjb2x1bW4gdG9nZXRoZXIuCiAgICAgKiBUaGlzIHdvcmtzIHByb3Blcmx5IG9ubHkgb24gc29ydGVkIGRhdGFzZXRzLgogICAgICoKICAgICAqIFdoZW4gbWluU2l6ZSBpcyBub3QgcHJvdmlkZWQsIGJhdGNoZXMgd2lsbCBiZSBjcmVhdGVkIG9ubHkgd2hlbiB0aGVyZSBpcyBhIGNoYW5nZSBpbiB2YWx1ZSBvZiB0aGUgY29sdW1uLgogICAgICogV2hlbiBtaW5TaXplIGlzIHByb3ZpZGVkLCBiYXRjaGVzIHdpbGwgYmUgY3JlYXRlZCBvbmx5IHdoZW4gdGhlcmUgaXMgYSBjaGFuZ2UgaW4gdmFsdWUgb2YgdGhlIGNvbHVtbiBvcgogICAgICogd2hlbiB0aGVyZSBhcmUgYXQgbGVhc3QgbWluU2l6ZSByb3dzIGluIHRoZSBiYXRjaC4KICAgICAqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAkY29sdW1uIC0gY29sdW1uIHRvIGdyb3VwIGJ5IChhbGwgcm93cyB3aXRoIHNhbWUgdmFsdWUgc3RheSB0b2dldGhlcikKICAgICAqIEBwYXJhbSBudWxsfGludDwxLCBtYXg+ICRtaW5TaXplIC0gb3B0aW9uYWwgbWluaW11bSByb3dzIHBlciBiYXRjaCBmb3IgZWZmaWNpZW5jeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":118,"slug":"batchsize","name":"batchSize","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplLgogICAgICogRm9yIGV4YW1wbGUsIHdoZW4gRXh0cmFjdG9yIGlzIHlpZWxkaW5nIG9uZSByb3cgYXQgdGltZSwgdGhpcyBtZXRob2Qgd2lsbCBtZXJnZSB0aGVtIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplCiAgICAgKiBiZWZvcmUgcGFzc2luZyB0aGVtIHRvIHRoZSBuZXh0IHBpcGVsaW5lIGVsZW1lbnQuCiAgICAgKiBTaW1pbGFybHkgd2hlbiBFeHRyYWN0b3IgaXMgeWllbGRpbmcgYmF0Y2hlcyBvZiByb3dzLCB0aGlzIG1ldGhvZCB3aWxsIHNwbGl0IHRoZW0gaW50byBzbWFsbGVyIGJhdGNoZXMgb2YgZ2l2ZW4KICAgICAqIHNpemUuCiAgICAgKgogICAgICogSW4gb3JkZXIgdG8gbWVyZ2UgYWxsIFJvd3MgaW50byBhIHNpbmdsZSBiYXRjaCB1c2UgRGF0YUZyYW1lOjpjb2xsZWN0KCkgbWV0aG9kIG9yIHNldCBzaXplIHRvIC0xIG9yIDAuCiAgICAgKgogICAgICogQHBhcmFtIGludDwtMSwgbWF4PiAkc2l6ZQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":150,"slug":"cache","name":"cache","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"id","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cacheBatchSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cache","type":[{"name":"Cache","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTdGFydCBwcm9jZXNzaW5nIHJvd3MgdXAgdG8gdGhpcyBtb21lbnQgYW5kIHB1dCBlYWNoIGluc3RhbmNlIG9mIFJvd3MKICAgICAqIGludG8gcHJldmlvdXNseSBkZWZpbmVkIGNhY2hlLgogICAgICogQ2FjaGUgdHlwZSBjYW4gYmUgc2V0IHRocm91Z2ggQ29uZmlnQnVpbGRlci4KICAgICAqIEJ5IGRlZmF1bHQgZXZlcnl0aGluZyBpcyBjYWNoZWQgaW4gc3lzdGVtIHRtcCBkaXIuCiAgICAgKgogICAgICogSW1wb3J0YW50OiBjYWNoZSBiYXRjaCBzaXplIG1pZ2h0IHNpZ25pZmljYW50bHkgaW1wcm92ZSBwZXJmb3JtYW5jZSB3aGVuIHByb2Nlc3NpbmcgbGFyZ2UgYW1vdW50IG9mIHJvd3MuCiAgICAgKiBMYXJnZXIgYmF0Y2ggc2l6ZSB3aWxsIGluY3JlYXNlIG1lbW9yeSBjb25zdW1wdGlvbiBidXQgd2lsbCByZWR1Y2UgbnVtYmVyIG9mIElPIG9wZXJhdGlvbnMuCiAgICAgKiBXaGVuIG5vdCBzZXQsIHRoZSBiYXRjaCBzaXplIGlzIHRha2VuIGZyb20gdGhlIGxhc3QgRGF0YUZyYW1lOjpiYXRjaFNpemUoKSBjYWxsLgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHBhcmFtIG51bGx8c3RyaW5nICRpZAogICAgICogQHBhcmFtIG51bGx8Q2FjaGUgJGNhY2hlIHJlYWRzIG9mIHRoaXMgY2FjaGUgbXVzdCBwYXNzIHRoZSBzYW1lIGluc3RhbmNlIHRvIGZyb21fY2FjaGUoKQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":167,"slug":"collect","name":"collect","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZWZvcmUgdHJhbnNmb3JtaW5nIHJvd3MsIGNvbGxlY3QgdGhlbSBhbmQgbWVyZ2UgaW50byBzaW5nbGUgUm93cyBpbnN0YW5jZS4KICAgICAqIFRoaXMgbWlnaHQgbGVhZCB0byBtZW1vcnkgaXNzdWVzIHdoZW4gcHJvY2Vzc2luZyBsYXJnZSBhbW91bnQgb2Ygcm93cywgdXNlIHdpdGggY2F1dGlvbi4KICAgICAqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":186,"slug":"collectrefs","name":"collectRefs","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"References","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGlzIG1ldGhvZCBhbGxvd3MgdG8gY29sbGVjdCByZWZlcmVuY2VzIHRvIGFsbCBlbnRyaWVzIHVzZWQgaW4gdGhpcyBwaXBlbGluZS4KICAgICAqCiAgICAgKiBgYGBwaHAKICAgICAqIChuZXcgRmxvdygpKQogICAgICogICAtPnJlYWQoRnJvbTo6Y2hhaW4oKSkKICAgICAqICAgLT5jb2xsZWN0UmVmcygkcmVmcyA9IHJlZnMoKSkKICAgICAqICAgLT5ydW4oKTsKICAgICAqIGBgYAogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":193,"slug":"constrain","name":"constrain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"constraint","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"constraints","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":204,"slug":"count","name":"count","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICogUmV0dXJuIHRvdGFsIGNvdW50IG9mIHJvd3MgcHJvY2Vzc2VkIGJ5IHRoaXMgcGlwZWxpbmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":224,"slug":"crossjoin","name":"crossJoin","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"prefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"''"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":241,"slug":"display","name":"display","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gaW50ICRsaW1pdCBtYXhpbXVtIG51bWJlcnMgb2Ygcm93cyB0byBkaXNwbGF5CiAgICAgKiBAcGFyYW0gYm9vbHxpbnQgJHRydW5jYXRlIGZhbHNlIG9yIGlmIHNldCB0byAwIGNvbHVtbnMgYXJlIG5vdCB0cnVuY2F0ZWQsIG90aGVyd2lzZSBkZWZhdWx0IHRydW5jYXRlIHRvIDIwCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJhY3RlcnMKICAgICAqIEBwYXJhbSBGb3JtYXR0ZXIgJGZvcm1hdHRlcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":268,"slug":"drop","name":"drop","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBEcm9wIGdpdmVuIGVudHJpZXMuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":282,"slug":"dropduplicates","name":"dropDuplicates","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAuLi4kZW50cmllcwogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHJldHVybiAkdGhpcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":289,"slug":"duplicaterow","name":"duplicateRow","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"condition","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":308,"slug":"fetch","name":"fetch","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZSBhd2FyZSB0aGF0IGZldGNoIGlzIG5vdCBtZW1vcnkgc2FmZSBhbmQgd2lsbCBsb2FkIGFsbCByb3dzIGludG8gbWVtb3J5LgogICAgICogSWYgeW91IHdhbnQgdG8gc2FmZWx5IGl0ZXJhdGUgb3ZlciBSb3dzIHVzZSBvZSBvZiB0aGUgZm9sbG93aW5nIG1ldGhvZHM6LgogICAgICoKICAgICAqIERhdGFGcmFtZTo6Z2V0KCkgOiBcR2VuZXJhdG9yCiAgICAgKiBEYXRhRnJhbWU6OmdldEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqIERhdGFGcmFtZTo6Z2V0RWFjaEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":325,"slug":"filter","name":"filter","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":337,"slug":"filters","name":"filters","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"functions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxTY2FsYXJGdW5jdGlvbj4gJGZ1bmN0aW9ucwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":351,"slug":"foreach","name":"forEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"callback","type":[{"name":"callable","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEBwYXJhbSBudWxsfGNhbGxhYmxlKFJvd3MgJHJvd3MsIEZsb3dDb250ZXh0ICRjb250ZXh0KSA6IHZvaWQgJGNhbGxiYWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":372,"slug":"get","name":"get","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gaW5zdGFuY2Ugb2YgUm93cy4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxSb3dzPgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":391,"slug":"getasarray","name":"getAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gYXJyYXkuCiAgICAgKgogICAgICogQHRyaWdnZXIKICAgICAqCiAgICAgKiBAcmV0dXJuIFxHZW5lcmF0b3I8YXJyYXk8YXJyYXk8bWl4ZWQ+Pj4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":410,"slug":"geteachasarray","name":"getEachAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZCBlYWNoIHJvdyBhcyBhbiBhcnJheS4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxhcnJheTxtaXhlZD4+CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":431,"slug":"groupby","name":"groupBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"GroupedDataFrame","namespace":"Flow\\ETL\\DataFrame","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBHcm91cEJ5UmVmZXJlbmNlc3xSZWZlcmVuY2V8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBncm91cGVkIGJ5IG9uIGl0cyBvd24KICAgICAqIEBwYXJhbSBudWxsfEdyb3VwQnlBbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxnb3JpdGhtIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":450,"slug":"join","name":"join","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."},{"name":"algorithm","type":[{"name":"JoinAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Join","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfEpvaW5BbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlIGFsZ29yaXRobQogICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":478,"slug":"joineach","name":"joinEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"factory","type":[{"name":"DataFrameFactory","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBKb2lucyBpbiBtZW1vcnkgcGVyIGJhdGNoOyBpdCBpcyBub3QgZ292ZXJuZWQgYnkgdGhlIGpvaW4gYWxnb3JpdGhtIGFuZCB0YWtlcyBubyBhbGdvcml0aG0gb3ZlcnJpZGUuCiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAcGFyYW0gc3RyaW5nfEpvaW4gJHR5cGUKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":494,"slug":"limit","name":"limit","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":508,"slug":"load","name":"load","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":554,"slug":"match","name":"match","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"validator","type":[{"name":"SchemaValidator","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfFNjaGVtYVZhbGlkYXRvciAkdmFsaWRhdG9yIC0gd2hlbiBudWxsLCBTdHJpY3RWYWxpZGF0b3IgZ2V0cyBpbml0aWFsaXplZAogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":575,"slug":"offset","name":"offset","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"offset","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTa2lwIGdpdmVuIG51bWJlciBvZiByb3dzIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF0YXNldC4KICAgICAqIFdoZW4gJG9mZnNldCBpcyBudWxsLCBub3RoaW5nIGhhcHBlbnMgKG5vIHJvd3MgYXJlIHNraXBwZWQpLgogICAgICoKICAgICAqIFBlcmZvcm1hbmNlIE5vdGU6IERhdGFGcmFtZSBtdXN0IGl0ZXJhdGUgdGhyb3VnaCBhbmQgcHJvY2VzcyBhbGwgc2tpcHBlZCByb3dzCiAgICAgKiB0byByZWFjaCB0aGUgb2Zmc2V0IHBvc2l0aW9uLiBGb3IgbGFyZ2Ugb2Zmc2V0cywgdGhpcyBjYW4gaW1wYWN0IHBlcmZvcm1hbmNlCiAgICAgKiBhcyB0aGUgZGF0YSBzb3VyY2Ugc3RpbGwgbmVlZHMgdG8gYmUgcmVhZCBhbmQgcHJvY2Vzc2VkIHVwIHRvIHRoZSBvZmZzZXQgcG9pbnQuCiAgICAgKgogICAgICogQHBhcmFtID9pbnQ8MCwgbWF4PiAkb2Zmc2V0CiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":589,"slug":"onerror","name":"onError","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"handler","type":[{"name":"ErrorHandler","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":601,"slug":"repartition","name":"repartition","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogU2h1ZmZsZXMgdGhlIHN0cmVhbSBzbyBldmVyeSByb3cgc2hhcmluZyB0aGUgZ2l2ZW4gY29sdW1ucyBhcnJpdmVzIGluIG9uZSBiYXRjaC4gSXQgZG9lcyBub3QKICAgICAqIHdyaXRlIGRpcmVjdG9yaWVzIC0gdGhhdCBpcyBkZWNsYXJlZCBvbiB0aGUgbG9hZGVyLCBgdG9fY3N2KC4uLiktPnBhcnRpdGlvbkJ5KCdyZWdpb24nKWAuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":613,"slug":"printrows","name":"printRows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":633,"slug":"explain","name":"explain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"trigger","type":[{"name":"Trigger","namespace":"Flow\\ETL\\Plan","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Plan\\Trigger::..."}],"return_type":[{"name":"Plan","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgcGxhbiAkdHJpZ2dlciB3b3VsZCBydW4gb3ZlciB0aGlzIGZyYW1lLCBmcm96ZW46IGxhdGVyIHZlcmJzIG9uIHRoaXMgZnJhbWUgZG8gbm90IHJlYWNoIGl0LiBUaGUgZGVmYXVsdAogICAgICogYWRkcyBubyBjb25zdW1lciBvZiBpdHMgb3duIC0gaXQgZHJhd3MgdGhlIGZyYW1lIGFzIGJ1aWx0LCBpdHMgY2hhaW4gYW5kIGl0cyBzaW5rcy4gdG9TdHJpbmcoKSBwcmludHMgaXQgYXMgYQogICAgICogdHJlZS4gQW5zd2VycyBmcm9tIHRoZSBwbGFuIHdpdGhvdXQgcmVhZGluZyBhIHJvdy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":643,"slug":"printschema","name":"printSchema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"formatter","type":[{"name":"SchemaFormatter","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\Formatter\\ASCIISchemaFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":651,"slug":"rename","name":"rename","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"from","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"to","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":658,"slug":"renameeach","name":"renameEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"strategies","type":[{"name":"RenameEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":669,"slug":"rows","name":"rows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6dHJhbnNmb3JtIG1ldGhvZC4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":686,"slug":"run","name":"run","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"analyze","type":[{"name":"Analyze","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Report","namespace":"Flow\\ETL\\Dataset","is_nullable":true,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIFdoZW4gYW5hbHl6aW5nIHBpcGVsaW5lIGV4ZWN1dGlvbiB3ZSBjYW4gY2hvc2UgdG8gY29sbGVjdCB2YXJpb3VzIG1ldHJpY3MgdGhyb3VnaCBhbmFseXplKCktPndpdGgqKCkgbWV0aG9kCiAgICAgKgogICAgICogLSBjb2x1bW4gc3RhdGlzdGljcyAtIGFuYWx5emUoKS0+d2l0aENvbHVtblN0YXRpc3RpY3MoKQogICAgICogLSBzY2hlbWEgLSBhbmFseXplKCktPndpdGhTY2hlbWEoKQogICAgICoKICAgICAqIEBwYXJhbSBBbmFseXplfGJvb2wgJGFuYWx5emUgLSB3aGVuIHNldCBydW4gd2lsbCByZXR1cm4gUmVwb3J0CiAgICAgKgogICAgICogQHJldHVybiAoJGFuYWx5emUgaXMgQW5hbHl6ZXx0cnVlID8gUmVwb3J0IDogbnVsbCkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":714,"slug":"schema","name":"schema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":727,"slug":"select","name":"select","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogS2VlcCBvbmx5IGdpdmVuIGVudHJpZXMuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":741,"slug":"sortby","name":"sortBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"SortAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBSZWZlcmVuY2V8U29ydFJlZmVyZW5jZXN8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBzb3J0ZWQgYnkgb24gaXRzIG93bgogICAgICogQHBhcmFtIG51bGx8U29ydEFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUgYWxnb3JpdGhtCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":755,"slug":"transform","name":"transform","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRGF0YUZyYW1lOjp3aXRoKCkuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":766,"slug":"until","name":"until","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGZpbHRlciBhbmQgdW50aWwgaXMgdGhhdCBmaWx0ZXIgd2lsbCBrZWVwIGZpbHRlcmluZyByb3dzIHVudGlsIGV4dHJhY3RvcnMgZmluaXNoIHlpZWxkaW5nCiAgICAgKiByb3dzLiBVbnRpbCB3aWxsIHNlbmQgYSBTVE9QIHNpZ25hbCB0byB0aGUgRXh0cmFjdG9yIHdoZW4gdGhlIGNvbmRpdGlvbiBpcyBub3QgbWV0LgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":780,"slug":"void","name":"void","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogVGhpcyBtZXRob2QgaXMgdXNlZnVsIG1vc3RseSBpbiBkZXZlbG9wbWVudCB3aGVuCiAgICAgKiB5b3Ugd2FudCB0byBwYXVzZSBwcm9jZXNzaW5nIGF0IGNlcnRhaW4gbW9tZW50IHdpdGhvdXQKICAgICAqIHJlbW92aW5nIGNvZGUuIEFsbCBvcGVyYXRpb25zIHdpbGwgZ2V0IHByb2Nlc3NlZCB1cCB0byB0aGlzIHBvaW50LAogICAgICogZnJvbSBoZXJlIG5vIHJvd3MgYXJlIHBhc3NlZCBmb3J3YXJkLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":790,"slug":"with","name":"with","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":818,"slug":"withentries","name":"withEntries","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxpbnQsIFdpdGhFbnRyeT58YXJyYXk8c3RyaW5nLCBTY2FsYXJGdW5jdGlvbnxXaW5kb3dGdW5jdGlvbnxXaXRoRW50cnk+ICRyZWZlcmVuY2VzCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":836,"slug":"withentry","name":"withEntry","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"reference","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"WindowFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gRGVmaW5pdGlvbjxtaXhlZD58c3RyaW5nICRlbnRyeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":849,"slug":"write","name":"write","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6bG9hZCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":21,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"aggregations","type":[{"name":"AggregatingFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":28,"slug":"pivot","name":"pivot","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"ref","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"values","type":[{"name":"PivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null}] \ No newline at end of file diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json index d16f2abc5c..2f2cf816ad 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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":576,"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":582,"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":591,"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":601,"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":608,"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":614,"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":626,"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":632,"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":638,"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":644,"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":650,"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":656,"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":665,"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":671,"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":680,"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":686,"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":693,"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":699,"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":705,"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":714,"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":720,"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":731,"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":740,"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":749,"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":755,"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":764,"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":774,"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":783,"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":789,"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":795,"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":803,"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":816,"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":822,"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":828,"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":838,"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":847,"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":856,"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":862,"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":875,"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":884,"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":893,"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":899,"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":908,"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":914,"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":920,"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":926,"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":932,"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":944,"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":971,"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":1001,"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":1007,"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":1013,"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":1019,"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":1025,"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":1031,"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":1037,"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":1043,"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":1049,"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":1055,"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":1061,"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":1067,"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":"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":1073,"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":1079,"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":1085,"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":1091,"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":1101,"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":1111,"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":1121,"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":1131,"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":1141,"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":1147,"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":1156,"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":1165,"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":1179,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."},{"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":1205,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."}],"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":1242,"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":1248,"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":1254,"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":1260,"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":1266,"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":1272,"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":1278,"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":1284,"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":1290,"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":1296,"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":1302,"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":1308,"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":1314,"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":1320,"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":1326,"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":1332,"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":1338,"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":1344,"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":1350,"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":1356,"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":1362,"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":1373,"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":1382,"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":1391,"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":1403,"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":1413,"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":1422,"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":1428,"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":1434,"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":1443,"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":1456,"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":1465,"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":1471,"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":1480,"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":1486,"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":1492,"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":1498,"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":1512,"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":1526,"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":1544,"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":1550,"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":1556,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1566,"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":1572,"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":1578,"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":1584,"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":1590,"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":1596,"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":1602,"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":1615,"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":1626,"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":1632,"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":1645,"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":1678,"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":1730,"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":1736,"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":1742,"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":1748,"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":1754,"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":1760,"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":1766,"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":1772,"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":1778,"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":1784,"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":1793,"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":1803,"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":1809,"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":1818,"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":1828,"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":1834,"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":1843,"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":1849,"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":1858,"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":1864,"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":1873,"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":1879,"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":1885,"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":1891,"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":1897,"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":1903,"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":1909,"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":1920,"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":1926,"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":1935,"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":1946,"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":1957,"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":1967,"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":2001,"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":2009,"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":2018,"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":2026,"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":2043,"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":2060,"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":2077,"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":2083,"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":2089,"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":2099,"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":2108,"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":2114,"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":2120,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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":283,"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":291,"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":297,"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":309,"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":316,"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":332,"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":353,"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":373,"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":379,"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":385,"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":391,"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":403,"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":417,"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":423,"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":429,"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":443,"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":457,"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":467,"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":481,"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":489,"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":499,"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":509,"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":519,"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":539,"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":545,"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":551,"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":561,"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":570,"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":576,"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":585,"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":595,"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":602,"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":608,"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":620,"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":626,"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":632,"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":638,"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":644,"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":650,"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":659,"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":665,"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":674,"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":680,"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":687,"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":693,"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":699,"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":708,"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":714,"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":725,"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":734,"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":743,"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":749,"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":758,"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":768,"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":777,"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":783,"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":789,"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":797,"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":810,"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":816,"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":822,"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":832,"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":841,"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":850,"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":856,"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":869,"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":878,"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":887,"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":893,"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":902,"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":908,"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":914,"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":920,"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":926,"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":938,"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":965,"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":995,"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":1001,"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":1007,"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":1013,"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":1019,"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":1025,"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":1031,"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":1037,"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":1043,"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":1049,"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":1055,"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":1061,"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":"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":1067,"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":1073,"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":1079,"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":1085,"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":1095,"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":1105,"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":1115,"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":1125,"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":1135,"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":1141,"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":1150,"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":1159,"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":1173,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."},{"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":1192,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."}],"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":1236,"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":1242,"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":1248,"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":1254,"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":1260,"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":1266,"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":1272,"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":1278,"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":1284,"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":1290,"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":1296,"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":1302,"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":1308,"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":1314,"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":1320,"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":1326,"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":1332,"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":1338,"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":1344,"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":1350,"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":1356,"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":1367,"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":1376,"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":1385,"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":1397,"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":1407,"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":1416,"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":1422,"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":1428,"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":1437,"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":1450,"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":1459,"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":1465,"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":1474,"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":1480,"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":1486,"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":1492,"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":1506,"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":1520,"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":1538,"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":1544,"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":1550,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1560,"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":1566,"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":1572,"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":1578,"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":1584,"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":1590,"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":1596,"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":1609,"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":1620,"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":1626,"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":1639,"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":1672,"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":1724,"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":1730,"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":1736,"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":1742,"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":1748,"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":1754,"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":1760,"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":1766,"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":1772,"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":1778,"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":1787,"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":1797,"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":1803,"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":1812,"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":1822,"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":1828,"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":1837,"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":1843,"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":1852,"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":1858,"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":1867,"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":1873,"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":1879,"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":1885,"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":1891,"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":1897,"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":1903,"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":1914,"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":1920,"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":1929,"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":1940,"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":1951,"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":1961,"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":1995,"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":2003,"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":2012,"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":2020,"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":2037,"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":2054,"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":2071,"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":2077,"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":2083,"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":2093,"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":2102,"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":2108,"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":2114,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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 From 4525c4adca73a99c41ae7f375c7b102b46d5abb3 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sun, 27 Sep 2026 20:33:30 +0200 Subject: [PATCH 03/21] feat(flow-php/etl): every reader and writer speaks columns - remove Hydrator, TypedRowValues, Row\Encoder and Row\RowsBuffer; add Rows\RowsBuffer - extractors build through RowsBuilder with the context backend, encoders take Rows - split adapter encoders into decoders and encoders - Floe takes a Backend instead of a hydrator - parquet reads column chunks via readColumns() / ParquetFile::columns() - Parquet and Floe refuse withSchema(), the footer is the schema --- benchmarks/src/Pipeline/SourceExtractor.php | 3 +- .../Unit/Pipeline/SourceExtractorTest.php | 11 +- documentation/components/adapters/http.md | 5 +- documentation/components/adapters/parquet.md | 20 + documentation/components/core/floe.md | 18 +- documentation/components/libs/parquet.md | 14 + documentation/upgrading.md | 98 ++- .../ETL/Adapter/ChartJS/Chart/BarChart.php | 29 +- .../ETL/Adapter/ChartJS/Chart/LineChart.php | 29 +- .../ETL/Adapter/ChartJS/Chart/PieChart.php | 27 +- .../ChartJS/Tests/Unit/Chart/BarChartTest.php | 17 + .../Tests/Unit/Chart/LineChartTest.php | 29 + .../ChartJS/Tests/Unit/Chart/PieChartTest.php | 45 ++ .../src/Flow/ETL/Adapter/CSV/CSVDecoder.php | 119 ++++ .../src/Flow/ETL/Adapter/CSV/CSVEncoder.php | 121 +--- .../src/Flow/ETL/Adapter/CSV/CSVExtractor.php | 22 +- .../Flow/ETL/Adapter/CSV/CSVFileReader.php | 7 +- .../src/Flow/ETL/Adapter/CSV/CSVLoader.php | 12 +- .../Flow/ETL/Adapter/CSV/CSVOpenSource.php | 7 + .../Flow/ETL/Adapter/CSV/CSVSourceOpener.php | 2 +- .../ETL/Adapter/CSV/NativeCSVOpenSource.php | 5 + .../Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php | 13 +- .../CSV/Tests/Context/CSVFixtureContext.php | 4 +- ...t.php => CSVExtractorTypedColumnsTest.php} | 2 +- .../Tests/Integration/CSVFileReaderTest.php | 8 + .../Integration/NativeCSVOpenSourceTest.php | 17 + .../Integration/PhpCSVOpenSourceTest.php | 13 + .../Adapter/CSV/Tests/Unit/CSVDecoderTest.php | 114 ++++ .../Adapter/CSV/Tests/Unit/CSVEncoderTest.php | 183 ++---- .../CSV/Tests/Unit/CSVExtractorTest.php | 26 + .../Flow/ETL/Adapter/Doctrine/DbalEncoder.php | 32 +- .../Adapter/Doctrine/DbalKeySetExtractor.php | 10 +- .../Doctrine/DbalLimitOffsetExtractor.php | 10 +- .../Flow/ETL/Adapter/Doctrine/DbalLoader.php | 5 +- .../Adapter/Doctrine/DbalQueryExtractor.php | 39 +- .../Doctrine/Tests/Unit/DbalEncoderTest.php | 44 +- .../Tests/Unit/DbalKeySetExtractorTest.php | 20 + .../Unit/DbalLimitOffsetExtractorTest.php | 19 + .../Tests/Unit/DbalQueryExtractorTest.php | 36 ++ .../Flow/ETL/Adapter/Excel/ExcelDecoder.php | 96 +++ .../Flow/ETL/Adapter/Excel/ExcelEncoder.php | 106 +--- .../Flow/ETL/Adapter/Excel/ExcelExtractor.php | 29 +- .../Flow/ETL/Adapter/Excel/ExcelLoader.php | 84 +-- .../ETL/Adapter/Excel/Sheet/OpenSheet.php | 4 +- .../ETL/Adapter/Excel/WorkbookManager.php | 3 +- .../Flow/ETL/Adapter/Excel/WorkbookReader.php | 2 +- .../Flow/ETL/Adapter/Excel/WorkbookSheet.php | 8 +- .../Tests/Double/RecordingCellStyler.php | 34 ++ .../Tests/Integration/ExcelExtractorTest.php | 17 + ...php => ExcelExtractorTypedColumnsTest.php} | 2 +- .../Tests/Integration/ExcelLoaderTest.php | 28 + .../Tests/Integration/Sheet/OpenSheetTest.php | 10 +- .../Excel/Tests/Unit/ExcelDecoderTest.php | 80 +++ .../Excel/Tests/Unit/ExcelEncoderTest.php | 214 ++----- ...heetEncoder.php => GoogleSheetDecoder.php} | 19 +- .../GoogleSheet/GoogleSheetExtractor.php | 11 +- .../GoogleSheet/GoogleSheetReadOptions.php | 6 +- .../Adapter/GoogleSheet/GoogleSheetReader.php | 10 +- ... GoogleSheetExtractorTypedColumnsTest.php} | 2 +- ...derTest.php => GoogleSheetDecoderTest.php} | 90 ++- .../Tests/Unit/GoogleSheetExtractorTest.php | 19 + .../Tests/Unit/GoogleSheetReadOptionsTest.php | 26 +- .../Tests/Unit/GoogleSheetReaderTest.php | 2 +- .../Http/{HttpEncoder.php => HttpDecoder.php} | 23 +- .../Http/PsrHttpClientDynamicExtractor.php | 14 +- .../Http/PsrHttpClientPaginatedExtractor.php | 15 +- .../Http/PsrHttpClientStaticExtractor.php | 11 +- .../PsrHttpClientDynamicExtractorTest.php | 24 +- .../PsrHttpClientPaginatedExtractorTest.php | 20 + .../PsrHttpClientStaticExtractorTest.php | 20 + ...ttpEncoderTest.php => HttpDecoderTest.php} | 24 +- .../src/Flow/ETL/Adapter/JSON/JSONEncoder.php | 34 +- .../JSON/JSONMachine/JsonExtractor.php | 17 +- .../JSON/JSONMachine/JsonLinesExtractor.php | 17 +- .../Flow/ETL/Adapter/JSON/JsonLinesLoader.php | 6 +- .../src/Flow/ETL/Adapter/JSON/JsonLoader.php | 9 +- .../JSONMachine/JsonExtractorTest.php | 16 + ....php => JsonExtractorTypedColumnsTest.php} | 2 +- .../JSONMachine/JsonLinesExtractorTest.php | 16 + ...=> JsonLinesExtractorTypedColumnsTest.php} | 2 +- .../JSON/Tests/Unit/JSONEncoderTest.php | 180 +++--- .../ETL/Adapter/Logger/PsrLoggerLoader.php | 4 +- .../Logger/Tests/Unit/PsrLoggerLoaderTest.php | 13 + .../ETL/Adapter/Parquet/ParquetEncoder.php | 53 +- .../ETL/Adapter/Parquet/ParquetExtractor.php | 99 ++- .../ETL/Adapter/Parquet/ParquetLoader.php | 4 +- .../ValueConverter/ElementsValueConverter.php | 16 - .../ValueConverter/JsonValueConverter.php | 6 - .../ValueConverter/StructValueConverter.php | 15 - .../ValueConverter/UuidValueConverter.php | 6 - .../Parquet/ValueConverter/ValueConverter.php | 2 - .../Integration/ParquetExtractorTest.php | 56 +- .../Integration/ParquetHydratorParityTest.php | 66 -- .../Parquet/Tests/Unit/ParquetEncoderTest.php | 179 +----- .../Tests/Unit/ParquetExtractorTest.php | 32 +- .../ElementsValueConverterTest.php | 25 - .../ValueConverter/JsonValueConverterTest.php | 14 - .../StructValueConverterTest.php | 22 - .../ValueConverter/UuidValueConverterTest.php | 14 - .../PostgreSql/PostgreSqlCursorExtractor.php | 10 +- .../Adapter/PostgreSql/PostgreSqlEncoder.php | 34 +- .../PostgreSql/PostgreSqlKeySetExtractor.php | 10 +- .../PostgreSqlLimitOffsetExtractor.php | 10 +- .../Adapter/PostgreSql/PostgreSqlLoader.php | 20 +- .../QueryBuilder/DeleteQueryBuilder.php | 2 +- .../QueryBuilder/InsertQueryBuilder.php | 2 +- .../QueryBuilder/UpdateQueryBuilder.php | 2 +- .../Unit/PostgreSqlCursorExtractorTest.php | 19 + .../Tests/Unit/PostgreSqlEncoderTest.php | 55 +- .../Unit/PostgreSqlKeySetExtractorTest.php | 21 + .../PostgreSqlLimitOffsetExtractorTest.php | 20 + .../src/Flow/ETL/Adapter/Seal/SealEncoder.php | 34 +- .../src/Flow/ETL/Adapter/Seal/SealLoader.php | 10 +- .../Seal/Tests/Unit/SealEncoderTest.php | 30 +- .../src/Flow/ETL/Adapter/Text/TextEncoder.php | 39 +- .../Flow/ETL/Adapter/Text/TextExtractor.php | 30 +- .../src/Flow/ETL/Adapter/Text/TextLoader.php | 2 +- .../Tests/Integration/TextExtractorTest.php | 15 + ....php => TextExtractorTypedColumnsTest.php} | 2 +- .../Text/Tests/Unit/TextEncoderTest.php | 44 +- .../Flow/ETL/Adapter/XML/Loader/XMLLoader.php | 6 +- .../src/Flow/ETL/Adapter/XML/XMLEncoder.php | 46 +- .../ETL/Adapter/XML/XMLParserExtractor.php | 30 +- .../ETL/Adapter/XML/XMLReaderExtractor.php | 29 +- ...t.php => XMLExtractorTypedColumnsTest.php} | 2 +- .../Integration/XMLParserExtractorTest.php | 17 + .../Integration/XMLReaderExtractorTest.php | 14 + .../Adapter/XML/Tests/Unit/XMLEncoderTest.php | 124 ++-- src/core/etl/src/Flow/ETL/Config.php | 13 - .../etl/src/Flow/ETL/Config/ConfigBuilder.php | 6 +- .../ETL/Exception/InferredSchemaException.php | 2 +- .../Flow/ETL/Extractor/BatchByExtractor.php | 41 +- .../src/Flow/ETL/Extractor/FileConstants.php | 3 +- .../src/Flow/ETL/Extractor/InMemoryRows.php | 2 +- .../src/Flow/ETL/Extractor/PathFiltering.php | 26 - src/core/etl/src/Flow/ETL/FlowContext.php | 9 - .../src/Flow/ETL/Loader/PartitionRouter.php | 14 +- .../etl/src/Flow/ETL/Loader/RowPartitions.php | 10 +- src/core/etl/src/Flow/ETL/Row/Encoder.php | 25 - src/core/etl/src/Flow/ETL/Row/Hydrator.php | 24 - .../etl/src/Flow/ETL/Row/PhpRowHydrator.php | 71 --- src/core/etl/src/Flow/ETL/Row/RowsBuffer.php | 75 --- .../etl/src/Flow/ETL/Row/TypedRowValues.php | 22 - src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php | 79 +++ .../Flow/ETL/Schema/Inference/ColumnTypes.php | 2 +- .../etl/src/Flow/ETL/Sort/Merge/KWayMerge.php | 7 +- src/core/etl/src/Flow/Floe/FloeEncoder.php | 16 +- src/core/etl/src/Flow/Floe/FloeExtractor.php | 53 +- src/core/etl/src/Flow/Floe/FloeLoader.php | 5 +- src/core/etl/src/Flow/Floe/FloeMerger.php | 17 +- src/core/etl/src/Flow/Floe/FloeReader.php | 15 +- src/core/etl/src/Flow/Floe/FloeSerializer.php | 10 +- .../etl/src/Flow/Floe/FloeStreamReader.php | 17 +- .../etl/src/Flow/Floe/FloeStreamWriter.php | 22 +- src/core/etl/src/Flow/Floe/FloeWriter.php | 5 +- src/core/etl/src/Flow/Floe/PhpFloeEncoder.php | 83 ++- .../Flow/ETL/Tests/Double/SpyBackend.php | 45 ++ .../DataFrame/ConfigBuilderTest.php | 6 - .../Exception/InferredSchemaExceptionTest.php | 4 +- .../Unit/Extractor/BatchByExtractorTest.php | 32 + .../Unit/Extractor/FileConstantsTest.php | 15 +- .../Flow/ETL/Tests/Unit/FlowContextTest.php | 3 +- .../Tests/Unit/Loader/RowPartitionsTest.php | 31 +- .../ETL/Tests/Unit/Row/PhpRowHydratorTest.php | 571 ------------------ .../ETL/Tests/Unit/Row/RowsBufferTest.php | 91 --- .../ETL/Tests/Unit/Row/TypedRowValuesTest.php | 33 - .../ETL/Tests/Unit/Rows/RowsBufferTest.php | 118 ++++ .../ETL/Tests/Unit/Rows/RowsBuilderTest.php | 426 +++++++++++++ .../Floe/Tests/Context/FloeFilesContext.php | 5 +- .../Tests/Context/FloeStreamReaderContext.php | 4 +- .../Flow/Floe/Tests/Double/SpyHydrator.php | 31 - .../Tests/Integration/FloeDataFrameTest.php | 2 +- .../Tests/Integration/FloeExtractorTest.php | 21 +- .../Floe/Tests/Unit/FloeExtractorTest.php | 53 +- .../Flow/Floe/Tests/Unit/FloeReaderTest.php | 13 +- .../Floe/Tests/Unit/FloeSerializerTest.php | 11 + .../Floe/Tests/Unit/FloeStreamReaderTest.php | 30 +- .../Floe/Tests/Unit/PhpFloeEncoderTest.php | 151 ++++- .../Flow/ETL/Row/RustRowHydratorNative.php | 2 +- .../php/Flow/Floe/RustFloeEncoderNative.php | 3 +- .../tests/phpt/054_csv_consumed_bytes.phpt | 4 +- .../flow-php-ext/tests/phpt/bootstrap.php | 8 +- .../Parquet/Engine/AdaptiveParquetEngine.php | 11 +- .../Parquet/Engine/ArrowParquetEngine.php | 69 ++- .../Flow/Parquet/Engine/PhpParquetEngine.php | 77 +-- .../src/Flow/Parquet/ParquetEngine.php | 14 +- .../parquet/src/Flow/Parquet/ParquetFile.php | 46 +- .../Engine/ArrowParquetEngineReadTest.php | 225 ++++--- .../Integration/Engine/CrossEngineTest.php | 46 +- .../Integration/Engine/ReadColumnsTest.php | 90 +++ .../Tests/Integration/IO/PaginationTest.php | 71 +++ 191 files changed, 3706 insertions(+), 3222 deletions(-) create mode 100644 src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/LineChartTest.php create mode 100644 src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/PieChartTest.php create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php rename src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/{CSVHydratorParityTest.php => CSVExtractorTypedColumnsTest.php} (98%) create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVDecoderTest.php create mode 100644 src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php create mode 100644 src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Double/RecordingCellStyler.php rename src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/{ExcelHydratorParityTest.php => ExcelExtractorTypedColumnsTest.php} (96%) create mode 100644 src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php rename src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/{GoogleSheetEncoder.php => GoogleSheetDecoder.php} (89%) rename src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/{GoogleSheetHydratorParityTest.php => GoogleSheetExtractorTypedColumnsTest.php} (97%) rename src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/{GoogleSheetEncoderTest.php => GoogleSheetDecoderTest.php} (65%) rename src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/{HttpEncoder.php => HttpDecoder.php} (87%) rename src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Unit/{HttpEncoderTest.php => HttpDecoderTest.php} (86%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/{JsonHydratorParityTest.php => JsonExtractorTypedColumnsTest.php} (97%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/{JsonLinesHydratorParityTest.php => JsonLinesExtractorTypedColumnsTest.php} (94%) delete mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetHydratorParityTest.php rename src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/{TextHydratorParityTest.php => TextExtractorTypedColumnsTest.php} (96%) rename src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/{XMLHydratorParityTest.php => XMLExtractorTypedColumnsTest.php} (95%) delete mode 100644 src/core/etl/src/Flow/ETL/Row/Encoder.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/Hydrator.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/PhpRowHydrator.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/RowsBuffer.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/TypedRowValues.php create mode 100644 src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/PhpRowHydratorTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/TypedRowValuesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBufferTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Double/SpyHydrator.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php diff --git a/benchmarks/src/Pipeline/SourceExtractor.php b/benchmarks/src/Pipeline/SourceExtractor.php index 7dd863d43c..15bfccd716 100644 --- a/benchmarks/src/Pipeline/SourceExtractor.php +++ b/benchmarks/src/Pipeline/SourceExtractor.php @@ -16,6 +16,7 @@ use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\from_memory; use function Flow\Floe\DSL\from_floe; +use function in_array; final readonly class SourceExtractor { @@ -40,7 +41,7 @@ public function extractor(): Extractor Source::parquet => from_parquet($orders->parquet()), }; - return $this->mode === SchemaMode::declared + return $this->mode === SchemaMode::declared && !in_array($this->source, [Source::floe, Source::parquet], true) ? $extractor->withSchema(OrdersSchema::of($this->source)) : $extractor; } diff --git a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/SourceExtractorTest.php b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/SourceExtractorTest.php index a482e9b097..b2354f6ca3 100644 --- a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/SourceExtractorTest.php +++ b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/SourceExtractorTest.php @@ -24,6 +24,15 @@ public static function sources(): Generator } } + public static function sources_taking_a_schema(): Generator + { + foreach (Source::cases() as $source) { + if ($source !== Source::floe && $source !== Source::parquet) { + yield $source->value => [$source]; + } + } + } + #[DataProvider('sources')] public function test_declared_mode_attaches_the_frozen_schema(Source $source): void { @@ -40,7 +49,7 @@ public function test_declared_mode_attaches_the_frozen_schema(Source $source): v * comparing schemas passes whether or not withSchema() was applied. Comparing the extractors * themselves does distinguish them - withSchema() returns a clone carrying the schema. */ - #[DataProvider('sources')] + #[DataProvider('sources_taking_a_schema')] public function test_inferred_mode_attaches_no_schema(Source $source): void { (new SourceFixture($source, self::ROWS))->warm(); diff --git a/documentation/components/adapters/http.md b/documentation/components/adapters/http.md index 217e025340..3efc01a358 100644 --- a/documentation/components/adapters/http.md +++ b/documentation/components/adapters/http.md @@ -218,9 +218,8 @@ data_frame() ## Typing the row with a schema All three extractors expose `withSchema(Schema)` (also the optional last argument of the `from_*` DSL functions). The -schema is passed straight to the DataFrame Hydrator's `cast()` - it describes the **row**, so to type the body you -declare `response_body` as a `structure`. As with every extractor, `cast()` keeps only the columns the schema mentions, -so include any envelope columns you want to keep. +schema describes the **row**, so to type the body you declare `response_body` as a `structure`. As with every +extractor, only the columns the schema mentions are kept, so include any envelope columns you want to keep. ```php withSchema()` throws. Project with `columns:`, change types after +reading: + +```php +read(from_parquet(__DIR__ . '/orders.parquet', columns: ['id', 'payload', 'created_at'])) + ->withEntry('payload', ref('payload')->cast(type_json())) + ->withEntry('created_at', to_timezone(ref('created_at'), 'Europe/Warsaw')) + ->write(to_output()) + ->run(); +``` diff --git a/documentation/components/core/floe.md b/documentation/components/core/floe.md index 4db4d062c9..6aeaf4c932 100644 --- a/documentation/components/core/floe.md +++ b/documentation/components/core/floe.md @@ -38,10 +38,20 @@ data_frame() ->run(); ``` -When the [`flow_php` extension](/documentation/components/extensions/flow-php-ext.md) is loaded, the -strict read and the write fuse frame-split + value decode/encode + hydrate/dehydrate into one native -call per batch. It is transparent - the on-disk format is unchanged and the rows are byte-for-byte -identical to the pure-PHP engine. +The footer is the schema: `from_floe(...)->withSchema()` throws. Change a column's type or zone after reading: + +```php +read(from_floe(__DIR__ . '/output.floe')) + ->withEntry('at', to_timezone(ref('at'), 'Europe/Warsaw')) + ->write(to_output()) + ->run(); +``` ## Save Modes diff --git a/documentation/components/libs/parquet.md b/documentation/components/libs/parquet.md index cd7fed2030..9d09c1ac52 100644 --- a/documentation/components/libs/parquet.md +++ b/documentation/components/libs/parquet.md @@ -225,6 +225,20 @@ foreach ($file->values(["column_1", "column_2"], limit: 100, offset: 1000) as $r } ``` +### Reading columns in batches + +```php +use Flow\Parquet\Reader; + +$file = (new Reader())->read('path/to/file.parquet'); + +foreach ($file->columns(batchSize: 1000, columns: ["column_1", "column_2"]) as $chunk) { + // $chunk = ['column_1' => [...up to 1000 values], 'column_2' => [...]] +} +``` + +`limit` and `offset` work as in `values()`. + ## Writing Parquet Files Since parquet is a binary format, we need to provide a schema for the writer so it can know how diff --git a/documentation/upgrading.md b/documentation/upgrading.md index db89d242a5..b4d2956504 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -536,12 +536,12 @@ document written by 0.45.x that has a structure column. Clear APCu and natively ### 53) `flow-php/etl` - the column backend replaces the adaptive hydrator -| Before | After | -|------------------------------------------------------------------------------------|---------------------------------------------------------------------| -| `AdaptiveRowHydrator`, `NativeRowHydrator` | removed - `PhpRowHydrator(Backend $backend = new DefaultBackend())` | -| `array_to_row(..., Hydrator $hydrator)` / `array_to_rows(..., Hydrator $hydrator)` | `Backend $backend` | -| `ConfigBuilder::hydrator(Hydrator)` | removed - `ConfigBuilder::backend(Backend)` | -| - | `Config::backend()`, `FlowContext::backend()` | +| Before | After | +|------------------------------------------------------------------------------------|-----------------------------------------------| +| `AdaptiveRowHydrator`, `NativeRowHydrator` | removed | +| `array_to_row(..., Hydrator $hydrator)` / `array_to_rows(..., Hydrator $hydrator)` | `Backend $backend` | +| `ConfigBuilder::hydrator(Hydrator)` | removed - `ConfigBuilder::backend(Backend)` | +| - | `Config::backend()`, `FlowContext::backend()` | ### 54) `flow-php/etl` - `FloeEngine` and `NativeFloeEncoder` removed @@ -552,16 +552,16 @@ document written by 0.45.x that has a structure column. Clear APCu and natively ### 55) `flow-php/etl` - engine classes follow the batch -| Before | After | -|------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------| -| `Schema::zonedDefinitions()`, `ZoneAlignment`, `HydratedBatch`, `RowRenaming`, `DomValueCodec` | removed | -| `GroupBy::aggregatedRow(): Row` | `GroupBy::aggregatedValues(): array` | -| `RowMerger::merge(): Row` | `RowMerger::merge(): array` | -| `DerivedColumns::rows(Schema, Schema, list)` | `DerivedColumns::rows(Rows, Schema, Schema, string, Column)` | -| `UnpackedColumns::values(array, string, Schema, array)` | `UnpackedColumns::values(string, Schema, array)` | -| `InferredBatch::of(list)` | `InferredBatch::of(list)` | -| `InferredRows::of(..., Hydrator)` | `InferredRows::of(..., Backend)` | -| `FileConstants::fillRows(Rows, Schema)` | `FileConstants::fillRows(Rows, Schema, Backend $backend = new DefaultBackend())` | +| Before | After | +|------------------------------------------------------------------------------------------------|--------------------------------------------------------------| +| `Schema::zonedDefinitions()`, `ZoneAlignment`, `HydratedBatch`, `RowRenaming`, `DomValueCodec` | removed | +| `GroupBy::aggregatedRow(): Row` | `GroupBy::aggregatedValues(): array` | +| `RowMerger::merge(): Row` | `RowMerger::merge(): array` | +| `DerivedColumns::rows(Schema, Schema, list)` | `DerivedColumns::rows(Rows, Schema, Schema, string, Column)` | +| `UnpackedColumns::values(array, string, Schema, array)` | `UnpackedColumns::values(string, Schema, array)` | +| `InferredBatch::of(list)` | `InferredBatch::of(list)` | +| `InferredRows::of(..., Hydrator)` | `InferredRows::of(..., Backend)` | +| `FileConstants::fillRows(Rows, Schema)` | `FileConstants::fillRows(Rows, Schema, Backend $backend)` | ### 56) `flow-php/etl-adapter-json` - untyped JSON Schema arrays and objects become `json` @@ -598,6 +598,72 @@ different instant; it now stays a `datetime` unless it is cast to a date explici |---------------------------------------------------|--------------------| | `new Comparator(StructureComparison $structures)` | `new Comparator()` | + +### 60) `flow-php/etl` - the row-shaped reader/writer API is removed + +| Before | After | +|---------------------------------------------------------------|-------------------------------------------------------------------------------------------------------| +| `Hydrator`, `PhpRowHydrator`, `TypedRowValues`, `Row\Encoder` | removed - readers build with `RowsBuilder`, encoders take `encode(Rows)` | +| `Row\RowsBuffer(Schema, int $size, ?Closure $batch)` | `Rows\RowsBuffer(Schema, Backend, int $size)` - `append()`, `appendFrom()`, `appendTake()`, `flush()` | +| `Config::hydrator()`, `FlowContext::hydrator()` | removed - `Config::backend()`, `FlowContext::backend()` | + +### 61) `flow-php/etl` - Floe takes a `Backend` + +| Before | After | +|-------------------------------------------------------------------------------------------|-----------------------------------------------------------------------| +| `?Hydrator $hydrator` on `FloeReader`, `FloeStreamReader`, `FloeSerializer`, `FloeMerger` | `Backend $backend = new DefaultBackend()` | +| `?Hydrator $hydrator` on `FloeWriter`, `FloeStreamWriter` | removed | +| `new PhpFloeEncoder(Schema)` | `new PhpFloeEncoder(Schema, Backend $backend = new DefaultBackend())` | +| `FloeEncoder::decodeRows(array, Schema, Hydrator)`, `encodeFrames(Rows, Hydrator)` | `decodeRows(array, Schema)`, `encodeFrames(Rows)` | +| `PhpFloeEncoder::encode(list)` | `PhpFloeEncoder::encode(Rows)` | +| `FloeMerger(Filesystem, ?Hydrator, Codec)` | `FloeMerger(Filesystem, Backend, Codec)` | + +### 62) adapters - encoders split into decoders and encoders + +| Before | After | +|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| +| `CSVEncoder::decode()`, `CSVEncoder::headers()` | `CSVDecoder::decode()`, `CSVDecoder::headers()` | +| `new CSVEncoder(withHeader:, emptyToNull:, ...)` | `new CSVDecoder(withHeader:, emptyToNull:, ...)` - `CSVEncoder` keeps only the write options | +| `PhpCSVOpenSource(..., CSVEncoder $encoder, ...)` | `PhpCSVOpenSource(..., CSVDecoder $decoder, ...)` | +| `TextEncoder::decode()` | removed - `TextExtractor` builds `['text' => $line]` rows itself | +| `XMLEncoder::decode()` | removed - `XMLReaderExtractor` builds `['node' => $xml]` rows itself | +| `ExcelEncoder(withHeader:, convertEmptyToNull:, timeFormat:)`, `decode()`, `headers()` | `ExcelDecoder(withHeader:, convertEmptyToNull:)` with `decode()`, `headers()`; `ExcelEncoder(timeFormat:)` | +| `OpenSheet::$encoder` (`ExcelEncoder`) | `OpenSheet::$decoder` (`ExcelDecoder`) | +| `GoogleSheetEncoder` | `GoogleSheetDecoder` - its throwing `encode()` is removed | +| `GoogleSheetReadOptions::encoder(): GoogleSheetEncoder` | `GoogleSheetReadOptions::decoder(): GoogleSheetDecoder` | +| `HttpEncoder` | `HttpDecoder` - `decode()` returns `list`, its throwing `encode()` is removed, `structuredBody()` stays | +| `JSONEncoder::decode()`, `DbalEncoder::decode()`, `PostgreSqlEncoder::decode()`, `SealEncoder::decode()`, `ParquetEncoder::decode()` | removed | +| `*Encoder::encode(list)` | `*Encoder::encode(Rows)`; no encoder implements `Row\Encoder` | +| `CSVLoader::write(Rows, array, FlowContext, array)` | `CSVLoader::write(Rows, array $headers, array $partitions)` | +| `JsonLoader::write(Rows, array, FlowContext)`, `JsonLinesLoader::write(...)`, `XMLLoader::write(...)` | `write(Rows, array $partitions)` | +| `XMLEncoder` refusing a structure value with more values than elements | removed - a structure cast drops undeclared keys, so the case cannot occur | +| `CSVOpenSource` implementations | must implement `headers(): list` - the header `records()` resolved | + +### 63) `flow-php/parquet` - `readColumns()` replaces `readValues()` + +| Before | After | +|-----------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------| +| `ParquetEngine::readValues(SourceStream, Schema, array $columns = [], ?int $limit = null, ?int $offset = null)` | `ParquetEngine::readColumns(SourceStream, Schema, list $columns, int $batchSize, ?int $limit, ?int $offset)` - chunks keyed by column | +| - | `ParquetFile::columns(int $batchSize, array $columns = [], ?int $limit = null, ?int $offset = null)` | +| `ParquetFile::values(offset: -1)` without a limit - read from row 0 | `InvalidArgumentException` | + +### 64) `flow-php/etl-adapter-parquet`, `flow-php/etl` - self-describing formats take no schema + +| Before | After | +|-------------------------------------------------------------------------|------------------------------------------------------------| +| `from_parquet(...)->withSchema(...)`, `from_floe(...)->withSchema(...)` | `InvalidArgumentException` - the file footer is the schema | +| `InferredSchemaException::filesDiverge` suggesting `->withSchema(...)` | suggests only `->unionByName()` | +| `ValueConverter::decode()` | removed - values are cast by the batch builder | + +Project with `from_parquet(..., columns: [...])`. Change a type after reading, e.g. a JSON column another tool wrote as +`string`: `->withEntry('payload', ref('payload')->cast(type_json()))`. Re-zone a datetime after reading: +`->withEntry('at', to_timezone(ref('at'), 'Europe/Warsaw'))`. + +### 65) `flow-php/etl` - `RowPartitions` reads a batch + +| Before | After | +|-----------------------------------------------|---------------------------------------------| +| `RowPartitions::of(Row $row, Schema $schema)` | `RowPartitions::of(Rows $rows, int $index)` | --- ## Upgrading from 0.43.x to 0.44.x diff --git a/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/BarChart.php b/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/BarChart.php index e917d087d7..285ca57551 100644 --- a/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/BarChart.php +++ b/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/BarChart.php @@ -12,6 +12,7 @@ use function array_key_exists; use function array_map; use function array_merge; +use function array_push; use function array_values; use function is_scalar; @@ -45,19 +46,25 @@ public function __construct( public function collect(Rows $rows): void { - foreach ($rows as $row) { - $labelValue = $row->get($this->label); + if ($rows->count() === 0) { + return; + } + + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->label->base())->values() as $labelValue) { $this->data['labels'][] = is_scalar($labelValue) ? (string) $labelValue : ''; + } + + foreach ($this->datasets as $dataset) { + $values = $rows->column($dataset->base())->values(); - foreach ($this->datasets as $dataset) { - if (!array_key_exists($dataset->name(), $this->data['datasets'])) { - $this->data['datasets'][$dataset->name()] = [ - 'label' => $dataset->name(), - 'data' => [$row->get($dataset)], - ]; - } else { - $this->data['datasets'][$dataset->name()]['data'][] = $row->get($dataset); - } + if (!array_key_exists($dataset->name(), $this->data['datasets'])) { + $this->data['datasets'][$dataset->name()] = [ + 'label' => $dataset->name(), + 'data' => $values, + ]; + } else { + array_push($this->data['datasets'][$dataset->name()]['data'], ...$values); } } } diff --git a/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/LineChart.php b/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/LineChart.php index 2da11f6af6..18b312f62c 100644 --- a/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/LineChart.php +++ b/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/LineChart.php @@ -12,6 +12,7 @@ use function array_key_exists; use function array_map; use function array_merge; +use function array_push; use function array_values; use function is_scalar; @@ -45,19 +46,25 @@ public function __construct( public function collect(Rows $rows): void { - foreach ($rows as $row) { - $labelValue = $row->get($this->label); + if ($rows->count() === 0) { + return; + } + + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->label->base())->values() as $labelValue) { $this->data['labels'][] = is_scalar($labelValue) ? (string) $labelValue : ''; + } + + foreach ($this->datasets as $dataset) { + $values = $rows->column($dataset->base())->values(); - foreach ($this->datasets as $dataset) { - if (!array_key_exists($dataset->name(), $this->data['datasets'])) { - $this->data['datasets'][$dataset->name()] = [ - 'label' => $dataset->name(), - 'data' => [$row->get($dataset)], - ]; - } else { - $this->data['datasets'][$dataset->name()]['data'][] = $row->get($dataset); - } + if (!array_key_exists($dataset->name(), $this->data['datasets'])) { + $this->data['datasets'][$dataset->name()] = [ + 'label' => $dataset->name(), + 'data' => $values, + ]; + } else { + array_push($this->data['datasets'][$dataset->name()]['data'], ...$values); } } } diff --git a/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/PieChart.php b/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/PieChart.php index bab1942775..a654705f75 100644 --- a/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/PieChart.php +++ b/src/adapter/etl-adapter-chartjs/src/Flow/ETL/Adapter/ChartJS/Chart/PieChart.php @@ -9,7 +9,6 @@ use Flow\ETL\Row\References; use Flow\ETL\Rows; -use function array_key_exists; use function array_map; use function array_merge; use function array_values; @@ -43,19 +42,21 @@ public function __construct( public function collect(Rows $rows): void { - foreach ($rows as $row) { + if ($rows->count() === 0) { + return; + } + + $label = $rows->column($this->label->base())->values(); + $columns = []; + + foreach ($this->datasets as $dataset) { + $columns[$dataset->name()] = $rows->column($dataset->base())->values(); + } + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { foreach ($this->datasets as $dataset) { - $labelValue = $row->get($this->label); - - if (!array_key_exists('pie', $this->data['datasets'])) { - $this->data['datasets']['pie'] = [ - 'data' => [$row->get($dataset)], - 'label' => is_scalar($labelValue) ? (string) $labelValue : '', - ]; - } else { - $this->data['datasets']['pie']['data'][] = $row->get($dataset); - $this->data['datasets']['pie']['label'] = is_scalar($labelValue) ? (string) $labelValue : ''; - } + $this->data['datasets']['pie']['data'][] = $columns[$dataset->name()][$i]; + $this->data['datasets']['pie']['label'] = is_scalar($label[$i]) ? (string) $label[$i] : ''; } } } diff --git a/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/BarChartTest.php b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/BarChartTest.php index 659d4a1a3f..dac7f6db87 100644 --- a/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/BarChartTest.php +++ b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/BarChartTest.php @@ -8,10 +8,14 @@ use Flow\ETL\Memory\ArrayMemory; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\Adapter\ChartJS\bar_chart; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_memory; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; +use function Flow\ETL\DSL\schema; final class BarChartTest extends FlowTestCase { @@ -118,4 +122,17 @@ public function test_collecting_data_from_rows(): void $chart->data(), ); } + + public function test_an_int_label_is_rendered_as_a_string_across_batches(): void + { + $chart = bar_chart(ref('l'), refs(ref('v'))); + + $chart->collect(array_to_rows([['l' => 1, 'v' => 5]], schema(int_schema('l'), int_schema('v')))); + $chart->collect(array_to_rows([['l' => 2, 'v' => 6]], schema(int_schema('l'), int_schema('v')))); + + static::assertSame( + ['type' => 'bar', 'data' => ['labels' => ['1', '2'], 'datasets' => [['label' => 'v', 'data' => [5, 6]]]]], + $chart->data(), + ); + } } diff --git a/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/LineChartTest.php b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/LineChartTest.php new file mode 100644 index 0000000000..7b89645845 --- /dev/null +++ b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/LineChartTest.php @@ -0,0 +1,29 @@ +collect(array_to_rows([['l' => 1, 'v' => 5]], schema(int_schema('l'), int_schema('v')))); + + static::assertSame( + ['type' => 'line', 'data' => ['labels' => ['1'], 'datasets' => [['label' => 'v', 'data' => [5]]]]], + $chart->data(), + ); + } +} diff --git a/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/PieChartTest.php b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/PieChartTest.php new file mode 100644 index 0000000000..4f4a75820c --- /dev/null +++ b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Unit/Chart/PieChartTest.php @@ -0,0 +1,45 @@ +collect(array_to_rows( + [['l' => 'x', 'a' => 1, 'b' => 10], ['l' => 'y', 'a' => 2, 'b' => 20]], + schema(str_schema('l'), int_schema('a'), int_schema('b')), + )); + + static::assertSame( + [ + 'type' => 'pie', + 'data' => ['labels' => ['a', 'b'], 'datasets' => [['data' => [1, 10, 2, 20], 'label' => 'y']]], + ], + $chart->data(), + ); + } + + public function test_an_empty_batch_adds_no_dataset(): void + { + $chart = pie_chart(ref('l'), refs(ref('a'))); + + $chart->collect(array_to_rows([], schema(str_schema('l'), int_schema('a')))); + + static::assertSame(['type' => 'pie', 'data' => ['labels' => ['a'], 'datasets' => []]], $chart->data()); + } +} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php new file mode 100644 index 0000000000..b44e96259c --- /dev/null +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php @@ -0,0 +1,119 @@ + + */ + private ?array $headers = null; + + public function __construct( + private readonly bool $withHeader = true, + private readonly string $separator = ',', + private readonly string $enclosure = '"', + private readonly string $escape = '\\', + bool $emptyToNull = true, + ) { + $this->rowNormalizer = new CSVRowNormalizer($emptyToNull); + } + + /** + * @param list $batch + * + * @return list + */ + public function decode(array $batch): array + { + $maps = []; + + foreach ($batch as $line) { + /** @var list $fields */ + $fields = str_getcsv($line, $this->separator, $this->enclosure, $this->escape); + + if ($this->headers === null) { + if ($this->withHeader) { + $this->headers = $this->mapHeaders($fields); + + continue; + } + + $this->headers = $this->generateAutoHeaders(count($fields)); + } + + $maps[] = new RawRowValues(array_combine( + $this->headers, + $this->rowNormalizer->normalize($fields, count($this->headers)), + )); + } + + return $maps; + } + + /** + * Null before the first decoded line: a 0-byte source resolves no header, which is not the same as a + * header of zero columns. + * + * @return null|list + */ + public function headers(): ?array + { + return $this->headers; + } + + /** + * @return list + */ + private function generateAutoHeaders(int $count): array + { + $headers = []; + + for ($i = 0; $i < $count; $i++) { + $headers[] = 'e' . str_pad((string) $i, 2, '0', STR_PAD_LEFT); + } + + return $headers; + } + + /** + * @param array $headers + * + * @return list + */ + private function mapHeaders(array $headers): array + { + $headers = array_map(static fn(mixed $header): string => trim(match (true) { + is_string($header) => $header, + is_numeric($header) => (string) $header, + $header === null => '', + default => is_scalar($header) ? (string) $header : '', + }), $headers); + + return array_values(array_map( + static fn(string $header, int|string $index): string => $header !== '' + ? $header + : 'e' . str_pad((string) $index, 2, '0', STR_PAD_LEFT), + $headers, + array_keys($headers), + )); + } +} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php index 8dc8f6d79b..ff7477417f 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php @@ -12,8 +12,7 @@ use DOMDocument; use DOMElement; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; @@ -33,94 +32,54 @@ use Stringable; use UnitEnum; -use function array_combine; -use function array_keys; -use function array_map; -use function array_values; -use function count; use function Flow\ETL\DSL\date_interval_to_microseconds; use function is_array; use function is_bool; use function is_float; use function is_int; -use function is_numeric; use function is_resource; -use function is_scalar; use function is_string; use function json_encode; -use function str_getcsv; -use function str_pad; -use function trim; use const JSON_THROW_ON_ERROR; -/** - * @implements Encoder - */ -final class CSVEncoder implements Encoder +final class CSVEncoder { /** * @var null|resource */ private $buffer = null; - private readonly CSVRowNormalizer $rowNormalizer; - - /** - * @var null|list - */ - private ?array $headers = null; - public function __construct( - private readonly bool $withHeader = true, private readonly string $separator = ',', private readonly string $enclosure = '"', private readonly string $escape = '\\', - bool $emptyToNull = true, private readonly string $dateTimeFormat = DateTimeInterface::ATOM, private readonly string $dateFormat = 'Y-m-d', private readonly string $newLineSeparator = PHP_EOL, - ) { - $this->rowNormalizer = new CSVRowNormalizer($emptyToNull); - } + ) {} - public function decode(array $batch): array + /** + * @return list + */ + public function encode(Rows $rows): array { - $maps = []; - - foreach ($batch as $line) { - /** @var list $fields */ - $fields = str_getcsv($line, $this->separator, $this->enclosure, $this->escape); - - if ($this->headers === null) { - if ($this->withHeader) { - $this->headers = $this->mapHeaders($fields); + $columns = []; + $types = []; - continue; - } - - $this->headers = $this->generateAutoHeaders(count($fields)); - } - - $maps[] = new RawRowValues(array_combine( - $this->headers, - $this->rowNormalizer->normalize($fields, count($this->headers)), - )); + foreach ($rows->schema()->definitions() as $definition) { + $name = $definition->entry()->name(); + $columns[$name] = $rows->column($name)->values(); + $types[$name] = $definition->type(); } - return $maps; - } - - public function encode(array $batch): array - { $lines = []; - foreach ($batch as $rowValues) { + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { $fields = []; - /** @var mixed $value */ - foreach ($rowValues->values as $name => $value) { - $fields[] = $this->renderValue($rowValues->types[$name], $value); + foreach ($columns as $name => $column) { + $fields[] = $this->renderValue($types[$name], $column[$i]); } $lines[] = $this->line($fields); @@ -137,54 +96,6 @@ public function encodeHeader(array $headers): string return $this->line($headers); } - /** - * Null before the first decoded line: a 0-byte source resolves no header, which is not the same as a - * header of zero columns. - * - * @return null|list - */ - public function headers(): ?array - { - return $this->headers; - } - - /** - * @return list - */ - private function generateAutoHeaders(int $count): array - { - $headers = []; - - for ($i = 0; $i < $count; $i++) { - $headers[] = 'e' . str_pad((string) $i, 2, '0', STR_PAD_LEFT); - } - - return $headers; - } - - /** - * @param array $headers - * - * @return list - */ - private function mapHeaders(array $headers): array - { - $headers = array_map(static fn(mixed $header): string => trim(match (true) { - is_string($header) => $header, - is_numeric($header) => (string) $header, - $header === null => '', - default => is_scalar($header) ? (string) $header : '', - }), $headers); - - return array_values(array_map( - static fn(string $header, int|string $index): string => $header !== '' - ? $header - : 'e' . str_pad((string) $index, 2, '0', STR_PAD_LEFT), - $headers, - array_keys($headers), - )); - } - /** * @param list $fields */ 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 d47cd226c4..1efea7a15a 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 @@ -19,7 +19,9 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; +use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -96,7 +98,7 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $hydrator = $context->hydrator(); + $backend = $context->backend(); $batchSize = $this->batchSize(); $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); @@ -132,7 +134,9 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $constants = $fileColumns->forFile($source, $schema); $columns = null; - foreach ($reader->batches($source, $batchSize) as $rawBatch) { + $batches = $reader->batches($source, $batchSize); + + foreach ($batches as $rawBatch) { if ($columns === null) { $columns = array_map( strval(...), @@ -154,11 +158,17 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } } - $hydrated = $constants->fillRows($hydrator->hydrate($rawBatch, $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $rawBatch)) + ->finish(), + $schema, + $backend, + ); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; @@ -170,7 +180,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } if ($columns === null && $this->schema === null && !$this->inference->unionByName) { - $columns = array_values(array_diff($reader->columns($source), $tail)); + $columns = array_values(array_diff($batches->getReturn(), $tail)); if ( $columns !== [] diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php index 2d90dc60a4..306788cff5 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php @@ -22,11 +22,12 @@ public function __construct( ) {} /** - * Abandoning the generator closes the source. + * Abandoning the generator closes the source. Returns the header the read resolved, so a source without data rows + * needs no second open to name its columns. * * @param int<1, max> $batchSize * - * @return Generator> + * @return Generator, mixed, list> */ public function batches(SourceFile $source, int $batchSize): Generator { @@ -46,6 +47,8 @@ public function batches(SourceFile $source, int $batchSize): Generator if ($batch !== []) { yield $batch; } + + return $open->headers(); } finally { $open->close(); } diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php index a0ac4d7895..09fab85789 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php @@ -111,12 +111,7 @@ public function load(Rows $rows, FlowContext $context): void try { foreach ($this->router->route($rows) as [$partitions, $group]) { - $this->write( - $group, - array_values($group->schema()->references()->names()), - $context, - $partitions->toArray(), - ); + $this->write($group, array_values($group->schema()->references()->names()), $partitions->toArray()); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); @@ -187,7 +182,7 @@ public function withSeparator(string $separator): self * @param list $headers * @param array $partitions */ - public function write(Rows $nextRows, array $headers, FlowContext $context, array $partitions): void + public function write(Rows $nextRows, array $headers, array $partitions): void { $files = $this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode); @@ -200,13 +195,12 @@ public function write(Rows $nextRows, array $headers, FlowContext $context, arra $stream->append($encoder->encodeHeader($headers)); } - $stream->append(implode('', $encoder->encode($context->hydrator()->dehydrate($nextRows)))); + $stream->append(implode('', $encoder->encode($nextRows))); } private function encoder(): CSVEncoder { return $this->encoder ??= new CSVEncoder( - withHeader: $this->header, separator: $this->separator, enclosure: $this->enclosure, escape: $this->escape, diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php index 49b35a7200..874bdc825f 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php @@ -35,6 +35,13 @@ public function producedRows(): int; */ public function columns(): array; + /** + * The header records() resolved; [] before it ran or for a 0-byte source. + * + * @return list + */ + public function headers(): array; + /** * This instance is consumed afterwards. * diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSourceOpener.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSourceOpener.php index 5e27c6390b..72ac2f9ae1 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSourceOpener.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSourceOpener.php @@ -45,7 +45,7 @@ public function open(SourceFile $source): CSVOpenSource return new PhpCSVOpenSource( $stream, - new CSVEncoder( + new CSVDecoder( withHeader: $this->options->withHeader, separator: $dialect->separator, enclosure: $dialect->enclosure, diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php index 12b826a463..119275b59d 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php @@ -106,6 +106,11 @@ public function producedRows(): int return $this->producedRows; } + public function headers(): array + { + return $this->reader->headers(); + } + public function records(): Generator { foreach ($this->stream->iterate($this->chunkSize) as $chunk) { diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php index f352def658..2e1b373701 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php @@ -26,7 +26,7 @@ final class PhpCSVOpenSource implements CSVOpenSource public function __construct( private readonly SourceStream $stream, - private readonly CSVEncoder $encoder, + private readonly CSVDecoder $decoder, private readonly CSVLineReader $lineReader, ) {} @@ -43,12 +43,17 @@ public function close(): void public function columns(): array { foreach ($this->lineReader->readLines($this->stream) as $line) { - $this->encoder->decode([$line]); + $this->decoder->decode([$line]); break; } - return $this->encoder->headers() ?? []; + return $this->decoder->headers() ?? []; + } + + public function headers(): array + { + return $this->decoder->headers() ?? []; } /** @@ -60,7 +65,7 @@ public function columns(): array public function records(): Generator { foreach ($this->lineReader->readLines($this->stream) as $line) { - foreach ($this->encoder->decode([$line]) as $values) { + foreach ($this->decoder->decode([$line]) as $values) { $this->producedBytes += $this->lineReader->lastRecordBytes(); $this->producedRows++; diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php index 6f73770427..9f4fbfca54 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Adapter\CSV\Tests\Context; +use Flow\ETL\Adapter\CSV\CSVDecoder; use Flow\ETL\Adapter\CSV\CSVDialect; -use Flow\ETL\Adapter\CSV\CSVEncoder; use Flow\ETL\Adapter\CSV\CSVFileReader; use Flow\ETL\Adapter\CSV\CSVFileSample; use Flow\ETL\Adapter\CSV\CSVLineReader; @@ -155,7 +155,7 @@ public static function openPhp( return new PhpCSVOpenSource( $stream, - new CSVEncoder( + new CSVDecoder( withHeader: $options->withHeader, separator: $dialect->separator, enclosure: $dialect->enclosure, diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVHydratorParityTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTypedColumnsTest.php similarity index 98% rename from src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVHydratorParityTest.php rename to src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTypedColumnsTest.php index 11ad67c833..1463b761af 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVHydratorParityTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTypedColumnsTest.php @@ -16,7 +16,7 @@ use function Flow\Filesystem\DSL\path_real; use function usort; -final class CSVHydratorParityTest extends FlowTestCase +final class CSVExtractorTypedColumnsTest extends FlowTestCase { public function test_hydrates_typed_columns_with_empty_to_null_and_input_uri(): void { diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileReaderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileReaderTest.php index 6041f355ce..3e328337cf 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileReaderTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileReaderTest.php @@ -47,6 +47,14 @@ public function test_batches_never_yields_an_empty_batch(string $fixture): void ); } + public function test_batches_return_the_header_of_a_source_without_rows(): void + { + $batches = CSVFixtureContext::reader()->batches(CSVFixtureContext::source('header_only.csv'), 10); + + static::assertSame([], iterator_to_array($batches, false)); + static::assertSame(['id', 'name'], $batches->getReturn()); + } + public function test_columns_of_one_source(): void { static::assertSame( diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php index 6cae0ede10..6a6cd992c7 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php @@ -75,6 +75,23 @@ public function test_columns_reads_a_quoted_multiline_header_as_one_record(): vo } } + public function test_headers_are_the_header_records_resolved(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + $open = CSVFixtureContext::openNative('header_only.csv'); + + try { + static::assertSame([], $open->headers()); + static::assertSame([], iterator_to_array($open->records(), false)); + static::assertSame(['id', 'name'], $open->headers()); + } finally { + $open->close(); + } + } + public function test_columns_reports_the_resolved_header(): void { if (!NativeCSVOpenSource::isSupported()) { diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/PhpCSVOpenSourceTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/PhpCSVOpenSourceTest.php index 79f52fcd22..2426f3dc43 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/PhpCSVOpenSourceTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/PhpCSVOpenSourceTest.php @@ -49,6 +49,19 @@ public function test_columns_reads_a_quoted_multiline_header_as_one_record(): vo } } + public function test_headers_are_the_header_records_resolved(): void + { + $open = CSVFixtureContext::openPhp('header_only.csv'); + + try { + static::assertSame([], $open->headers()); + static::assertSame([], iterator_to_array($open->records(), false)); + static::assertSame(['id', 'name'], $open->headers()); + } finally { + $open->close(); + } + } + public function test_columns_reports_the_resolved_header(): void { $open = CSVFixtureContext::openPhp('header_only.csv'); diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVDecoderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVDecoderTest.php new file mode 100644 index 0000000000..90de6bb463 --- /dev/null +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVDecoderTest.php @@ -0,0 +1,114 @@ +decode(['id,name'])); + static::assertSame(['id' => '1', 'name' => 'Norbert'], $decoder->decode(['1,Norbert'])[0]->values); + } + + public function test_decode_generates_auto_headers_when_header_is_disabled(): void + { + static::assertSame( + ['e00' => '1', 'e01' => 'Norbert'], + (new CSVDecoder(withHeader: false))->decode(['1,Norbert'])[0]->values, + ); + } + + public function test_decode_keeps_empty_fields_when_empty_to_null_is_disabled(): void + { + static::assertSame( + ['id' => '1', 'name' => ''], + (new CSVDecoder(emptyToNull: false))->decode(['id,name', '1,'])[0]->values, + ); + } + + public function test_decode_maps_fields_to_headers(): void + { + static::assertSame( + ['id' => '1', 'name' => 'Norbert'], + (new CSVDecoder())->decode(['id,name', '1,Norbert'])[0]->values, + ); + } + + public function test_decode_pads_short_rows_with_null(): void + { + static::assertSame(['id' => '1', 'name' => null], (new CSVDecoder())->decode(['id,name', '1'])[0]->values); + } + + public function test_decode_truncates_rows_longer_than_the_headers(): void + { + static::assertSame( + ['id' => '1', 'name' => 'Norbert'], + (new CSVDecoder())->decode(['id,name', '1,Norbert,extra'])[0]->values, + ); + } + + public function test_decode_turns_empty_fields_into_null_by_default(): void + { + static::assertSame(['id' => '1', 'name' => null], (new CSVDecoder())->decode(['id,name', '1,'])[0]->values); + } + + public function test_decoding_a_blank_line_yields_a_single_null_field(): void + { + static::assertSame( + ['e00' => null], + (new CSVDecoder(withHeader: false, emptyToNull: false))->decode([''])[0]->values, + ); + } + + public function test_decoding_a_line_with_a_custom_separator_enclosure_and_escape_yields_strings(): void + { + static::assertSame( + ['id' => '1', 'name' => 'a;b'], + (new CSVDecoder(separator: ';', enclosure: "'", escape: '|'))->decode(['id;name', "1;'a;b'"])[0]->values, + ); + } + + public function test_decoding_a_line_with_empty_quoted_fields_yields_empty_strings(): void + { + static::assertSame( + ['id' => '', 'name' => ''], + (new CSVDecoder(emptyToNull: false))->decode(['id,name', '"",""'])[0]->values, + ); + } + + public function test_headers_are_null_before_any_line_is_decoded(): void + { + static::assertNull((new CSVDecoder())->headers()); + } + + public function test_the_generated_headers_are_exposed_without_a_header_line(): void + { + $decoder = new CSVDecoder(withHeader: false); + $decoder->decode(['1,a']); + + static::assertSame(['e00', 'e01'], $decoder->headers()); + } + + public function test_the_resolved_headers_are_exposed(): void + { + $decoder = new CSVDecoder(); + + static::assertSame([], $decoder->decode(['id,name'])); + static::assertSame(['id', 'name'], $decoder->headers()); + } + + public function test_an_empty_header_cell_is_named_by_position(): void + { + $decoder = new CSVDecoder(); + $decoder->decode([',name']); + + static::assertSame(['e00', 'name'], $decoder->headers()); + } +} diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVEncoderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVEncoderTest.php index 36d7a16fa2..5327720543 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVEncoderTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVEncoderTest.php @@ -8,103 +8,34 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Adapter\CSV\CSVEncoder; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Value\Uuid; -use function Flow\Types\DSL\type_array; -use function Flow\Types\DSL\type_date; -use function Flow\Types\DSL\type_datetime; -use function Flow\Types\DSL\type_float; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\ETL\DSL\time_zone_schema; +use function Flow\ETL\DSL\uuid_schema; use function Flow\Types\DSL\type_integer; -use function Flow\Types\DSL\type_string; -use function Flow\Types\DSL\type_time; -use function Flow\Types\DSL\type_time_zone; -use function Flow\Types\DSL\type_uuid; +use function Flow\Types\DSL\type_list; final class CSVEncoderTest extends FlowTestCase { - public function test_decode_captures_headers_from_the_first_row_and_emits_no_row_for_it(): void - { - $encoder = new CSVEncoder(); - - static::assertSame([], $encoder->decode(['id,name'])); - static::assertSame(['id' => '1', 'name' => 'Norbert'], $encoder->decode(['1,Norbert'])[0]->values); - } - - public function test_decode_generates_auto_headers_when_header_is_disabled(): void - { - static::assertSame( - ['e00' => '1', 'e01' => 'Norbert'], - (new CSVEncoder(withHeader: false))->decode(['1,Norbert'])[0]->values, - ); - } - - public function test_decode_keeps_empty_fields_when_empty_to_null_is_disabled(): void - { - static::assertSame( - ['id' => '1', 'name' => ''], - (new CSVEncoder(emptyToNull: false))->decode(['id,name', '1,'])[0]->values, - ); - } - - public function test_decode_maps_fields_to_headers(): void - { - static::assertSame( - ['id' => '1', 'name' => 'Norbert'], - (new CSVEncoder())->decode(['id,name', '1,Norbert'])[0]->values, - ); - } - - public function test_decode_pads_short_rows_with_null(): void - { - static::assertSame(['id' => '1', 'name' => null], (new CSVEncoder())->decode(['id,name', '1'])[0]->values); - } - - public function test_decode_truncates_rows_longer_than_the_headers(): void - { - static::assertSame( - ['id' => '1', 'name' => 'Norbert'], - (new CSVEncoder())->decode(['id,name', '1,Norbert,extra'])[0]->values, - ); - } - - public function test_decode_turns_empty_fields_into_null_by_default(): void - { - static::assertSame(['id' => '1', 'name' => null], (new CSVEncoder())->decode(['id,name', '1,'])[0]->values); - } - - public function test_decoding_a_blank_line_yields_a_single_null_field(): void - { - static::assertSame( - ['e00' => null], - (new CSVEncoder(withHeader: false, emptyToNull: false))->decode([''])[0]->values, - ); - } - - public function test_decoding_a_line_with_a_custom_separator_enclosure_and_escape_yields_strings(): void - { - static::assertSame( - ['id' => '1', 'name' => 'a;b'], - (new CSVEncoder(separator: ';', enclosure: "'", escape: '|'))->decode(['id;name', "1;'a;b'"])[0]->values, - ); - } - - public function test_decoding_a_line_with_empty_quoted_fields_yields_empty_strings(): void - { - static::assertSame( - ['id' => '', 'name' => ''], - (new CSVEncoder(emptyToNull: false))->decode(['id,name', '"",""'])[0]->values, - ); - } - - public function test_encode_renders_array_values_as_json(): void + public function test_encode_renders_list_values_as_json(): void { static::assertSame( ["\"[1,2,3]\"\n"], - (new CSVEncoder(newLineSeparator: "\n"))->encode([ - new TypedRowValues(['tags' => [1, 2, 3]], ['tags' => type_array()]), - ]), + (new CSVEncoder(newLineSeparator: "\n"))->encode(array_to_rows([['tags' => [ + 1, + 2, + 3, + ]]], schema(list_schema('tags', type_list(type_integer()))))), ); } @@ -112,9 +43,9 @@ public function test_encode_renders_date_with_the_date_format(): void { static::assertSame( ["2023-10-01\n"], - (new CSVEncoder(newLineSeparator: "\n"))->encode([ - new TypedRowValues(['at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC')], ['at' => type_date()]), - ]), + (new CSVEncoder(newLineSeparator: "\n"))->encode(array_to_rows([[ + 'at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC'), + ]], schema(date_schema('at')))), ); } @@ -122,11 +53,9 @@ public function test_encode_renders_datetime_with_the_datetime_format(): void { static::assertSame( ["2023-10-01T12:02:01+00:00\n"], - (new CSVEncoder(newLineSeparator: "\n"))->encode([ - new TypedRowValues(['at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC')], [ - 'at' => type_datetime(), - ]), - ]), + (new CSVEncoder(newLineSeparator: "\n"))->encode(array_to_rows([[ + 'at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC'), + ]], schema(datetime_schema('at')))), ); } @@ -134,9 +63,9 @@ public function test_encode_renders_null_as_an_empty_field(): void { static::assertSame( ["\n"], - (new CSVEncoder(newLineSeparator: "\n"))->encode([ - new TypedRowValues(['name' => null], ['name' => type_string()]), - ]), + (new CSVEncoder(newLineSeparator: "\n"))->encode(array_to_rows([[ + 'name' => null, + ]], schema(str_schema('name', nullable: true)))), ); } @@ -144,13 +73,10 @@ public function test_encode_renders_scalars_verbatim_in_value_order(): void { static::assertSame( ["9.99,1,Norbert\n"], - (new CSVEncoder(newLineSeparator: "\n"))->encode([ - new TypedRowValues(['price' => 9.99, 'id' => 1, 'name' => 'Norbert'], [ - 'price' => type_float(), - 'id' => type_integer(), - 'name' => type_string(), - ]), - ]), + (new CSVEncoder(newLineSeparator: "\n"))->encode(array_to_rows( + [['price' => 9.99, 'id' => 1, 'name' => 'Norbert']], + schema(float_schema('price'), int_schema('id'), str_schema('name')), + )), ); } @@ -158,9 +84,9 @@ public function test_encode_renders_time_as_microseconds(): void { static::assertSame( ["3600000000\n"], - (new CSVEncoder(newLineSeparator: "\n"))->encode([ - new TypedRowValues(['duration' => new DateInterval('PT1H')], ['duration' => type_time()]), - ]), + (new CSVEncoder(newLineSeparator: "\n"))->encode(array_to_rows([[ + 'duration' => new DateInterval('PT1H'), + ]], schema(time_schema('duration')))), ); } @@ -168,9 +94,9 @@ public function test_encode_renders_a_timezone_as_its_iana_name(): void { static::assertSame( ["Europe/Warsaw\n"], - (new CSVEncoder(newLineSeparator: "\n"))->encode([ - new TypedRowValues(['tz' => new DateTimeZone('Europe/Warsaw')], ['tz' => type_time_zone()]), - ]), + (new CSVEncoder(newLineSeparator: "\n"))->encode(array_to_rows([[ + 'tz' => new DateTimeZone('Europe/Warsaw'), + ]], schema(time_zone_schema('tz')))), ); } @@ -178,38 +104,9 @@ public function test_encode_renders_uuid_as_string(): void { static::assertSame( ["f47ac10b-58cc-4372-a567-0e02b2c3d479\n"], - (new CSVEncoder(newLineSeparator: "\n"))->encode([ - new TypedRowValues(['id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')], ['id' => type_uuid()]), - ]), + (new CSVEncoder(newLineSeparator: "\n"))->encode(array_to_rows([[ + 'id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), + ]], schema(uuid_schema('id')))), ); } - - public function test_headers_are_null_before_any_line_is_decoded(): void - { - static::assertNull((new CSVEncoder())->headers()); - } - - public function test_the_generated_headers_are_exposed_without_a_header_line(): void - { - $encoder = new CSVEncoder(withHeader: false); - $encoder->decode(['1,a']); - - static::assertSame(['e00', 'e01'], $encoder->headers()); - } - - public function test_the_resolved_headers_are_exposed(): void - { - $encoder = new CSVEncoder(); - - static::assertSame([], $encoder->decode(['id,name'])); - static::assertSame(['id', 'name'], $encoder->headers()); - } - - public function test_an_empty_header_cell_is_named_by_position(): void - { - $encoder = new CSVEncoder(); - $encoder->decode([',name']); - - static::assertSame(['e00', 'name'], $encoder->headers()); - } } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVExtractorTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVExtractorTest.php index 2f0bc0eca4..ce5c248d65 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVExtractorTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVExtractorTest.php @@ -9,6 +9,7 @@ use Flow\ETL\Adapter\CSV\Tests\Context\CSVFixtureContext; use Flow\ETL\Cardinality; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Generator; @@ -16,6 +17,7 @@ use function abs; use function Flow\ETL\Adapter\CSV\from_csv; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\infer_schema; use function Flow\ETL\DSL\int_schema; @@ -83,6 +85,17 @@ public function test_a_header_only_file_declares_zero_rows_exactly(): void static::assertEquals(Cardinality::exact(8), $extractor->statistics()->size); } + public function test_a_header_only_file_is_opened_once_by_extract(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + $extractor = from_csv(CSVFixtureContext::path('header_only.csv'), filesystem: $filesystem); + $extractor->schema(); + $opened = $filesystem->readFromCalls; + + static::assertSame([], iterator_to_array($extractor->extract(flow_context()), false)); + static::assertSame($opened + 1, $filesystem->readFromCalls); + } + public function test_a_member_without_a_size_makes_both_facts_unknown(): void { $extractor = from_csv(CSVFixtureContext::path('glob_with_empty/*.csv')) @@ -181,4 +194,17 @@ public function test_statistics_before_a_sample_list_the_source_once(): void static::assertSame(1, $filesystem->listCalls); } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + iterator_to_array( + from_csv(CSVFixtureContext::path('five_rows.csv')) + ->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalEncoder.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalEncoder.php index d2ca457feb..542118b54b 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalEncoder.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalEncoder.php @@ -9,36 +9,28 @@ use DOMDocument; use DOMElement; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; -/** - * @implements Encoder> - */ -final class DbalEncoder implements Encoder +final class DbalEncoder { - public function decode(array $batch): array + /** + * @return list> + */ + public function encode(Rows $rows): array { - $decoded = []; + $columns = []; - foreach ($batch as $values) { - $decoded[] = new RawRowValues($values); + foreach ($rows->schema()->definitions() as $definition) { + $columns[$definition->entry()->name()] = $rows->column($definition->entry()->name())->values(); } - return $decoded; - } - - public function encode(array $batch): array - { $normalized = []; - foreach ($batch as $rowValues) { - $values = $rowValues->values; + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { $row = []; - /** @var mixed $value */ - foreach ($values as $name => $value) { - $row[$name] = $this->renderValue($value); + foreach ($columns as $name => $column) { + $row[$name] = $this->renderValue($column[$i]); } $normalized[] = $row; 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 2b5638b6b3..7b3624f2fc 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 @@ -20,6 +20,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; @@ -88,7 +89,6 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $schema = $this->schema(); $yielded = 0; $lastRow = null; - $encoder = new DbalEncoder(); $maximum = match (true) { $this->maximum !== null && $limit !== null => min($this->maximum, $limit), $this->maximum !== null => $this->maximum, @@ -180,11 +180,13 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $rawBatch[$index] = $row; } - $hydrated = $context->hydrator()->hydrate($encoder->decode($rawBatch), $schema); + $rows = (new RowsBuilder($schema, $context->backend())) + ->appendRows($rawBatch) + ->finish(); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; 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 0394ed3701..ba8dd4c3b7 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 @@ -17,6 +17,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; @@ -125,7 +126,6 @@ public function extract(FlowContext $context, ?int $limit = null): Generator } $yielded = 0; - $encoder = new DbalEncoder(); for ($page = 0; $page < (new Pages($total, $this->batchSize))->pages(); $page++) { // the request asks only for what is still wanted, while the offset keeps striding by the batch size @@ -148,11 +148,13 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $rawBatch[] = $row; } - $hydrated = $context->hydrator()->hydrate($encoder->decode($rawBatch), $schema); + $rows = (new RowsBuilder($schema, $context->backend())) + ->appendRows($rawBatch) + ->finish(); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalLoader.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalLoader.php index 741ba8b4a3..5d3368c76e 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalLoader.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalLoader.php @@ -85,10 +85,7 @@ public function load(Rows $rows, FlowContext $context): void $this->bulk()->{$this->operation}( $this->connection(), $this->tableName, - new BulkData( - $this->encoder()->encode($context->hydrator()->dehydrate($rows)), - $this->typesMap()->flowSchemaTypes($rows->schema()), - ), + new BulkData($this->encoder()->encode($rows), $this->typesMap()->flowSchemaTypes($rows->schema())), $this->operationOptions, ); 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 f1de450992..50189166ba 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 @@ -19,6 +19,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; @@ -96,8 +97,6 @@ public static function single( public function extract(FlowContext $context, ?int $limit = null): Generator { $schema = $this->schema(); - $hydrator = $context->hydrator(); - $encoder = new DbalEncoder(); $yielded = 0; foreach ($this->parametersSet->all() as $parameters) { @@ -105,38 +104,20 @@ public function extract(FlowContext $context, ?int $limit = null): Generator return; } - $rawBatch = []; + $all = (new RowsBuilder($schema, $context->backend())) + ->appendRows($this->connection->fetchAllAssociative($this->query, $parameters, $this->types)) + ->finish(); - foreach ($this->connection->fetchAllAssociative($this->query, $parameters, $this->types) as $row) { - $rawBatch[] = $row; - } - - $hydrated = $hydrator->hydrate($encoder->decode($rawBatch), $schema); - $buffer = []; - - foreach ($hydrated as $hydratedRow) { - $buffer[] = $hydratedRow; - $yielded++; - - if (count($buffer) === $this->batchSize) { - $signal = yield Rows::of($hydrated->schema(), ...$buffer); - - if ($signal === Signal::STOP) { - return; - } + foreach ($all->chunks($this->batchSize) as $batch) { + $yielded += $batch->count(); - $buffer = []; + $signal = yield $batch; - if ($limit !== null && $yielded >= $limit) { - return; - } + if ($signal === Signal::STOP) { + return; } - } - if ($buffer !== []) { - $signal = yield Rows::of($hydrated->schema(), ...$buffer); - - if ($signal === Signal::STOP) { + if ($batch->count() === $this->batchSize && $limit !== null && $yielded >= $limit) { return; } } diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalEncoderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalEncoderTest.php index c92dc3bb48..30a1fffe6b 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalEncoderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalEncoderTest.php @@ -6,25 +6,25 @@ use DOMDocument; use Flow\ETL\Adapter\Doctrine\DbalEncoder; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\FlowTestCase; use function array_keys; -use function Flow\Types\DSL\type_boolean; -use function Flow\Types\DSL\type_integer; -use function Flow\Types\DSL\type_string; -use function Flow\Types\DSL\type_xml; -use function Flow\Types\DSL\type_xml_element; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\xml_element_schema; +use function Flow\ETL\DSL\xml_schema; final class DbalEncoderTest extends FlowTestCase { public function test_passes_scalar_values_through_unchanged_preserving_column_order(): void { - $encoded = (new DbalEncoder())->encode([new TypedRowValues(['id' => 1, 'name' => 'Norbert', 'active' => true], [ - 'id' => type_integer(), - 'name' => type_string(), - 'active' => type_boolean(), - ])]); + $encoded = (new DbalEncoder())->encode(array_to_rows( + [['id' => 1, 'name' => 'Norbert', 'active' => true]], + schema(int_schema('id'), str_schema('name'), bool_schema('active')), + )); static::assertSame([['id' => 1, 'name' => 'Norbert', 'active' => true]], $encoded); static::assertSame(['id', 'name', 'active'], array_keys($encoded[0])); @@ -35,10 +35,10 @@ public function test_renders_a_dom_document_value_to_an_xml_string(): void $doc = new DOMDocument(); $doc->loadXML('Software Engineer'); - $encoded = (new DbalEncoder())->encode([new TypedRowValues(['id' => 1, 'profile' => $doc], [ - 'id' => type_integer(), - 'profile' => type_xml(), - ])]); + $encoded = (new DbalEncoder())->encode(array_to_rows( + [['id' => 1, 'profile' => $doc]], + schema(int_schema('id'), xml_schema('profile')), + )); static::assertSame(1, $encoded[0]['id']); static::assertIsString($encoded[0]['profile']); @@ -51,9 +51,9 @@ public function test_renders_a_dom_element_value_to_an_xml_string(): void $doc->loadXML('John Doe'); $element = $doc->getElementsByTagName('user')->item(0); - $encoded = (new DbalEncoder())->encode([new TypedRowValues(['user_element' => $element], [ - 'user_element' => type_xml_element(), - ])]); + $encoded = (new DbalEncoder())->encode(array_to_rows([[ + 'user_element' => $element, + ]], schema(xml_element_schema('user_element')))); static::assertIsString($encoded[0]['user_element']); static::assertStringContainsString('John Doe', $encoded[0]['user_element']); @@ -63,10 +63,10 @@ public function test_passes_null_through_unchanged(): void { static::assertSame( [['id' => 1, 'body' => null]], - (new DbalEncoder())->encode([new TypedRowValues(['id' => 1, 'body' => null], [ - 'id' => type_integer(), - 'body' => type_string(), - ])]), + (new DbalEncoder())->encode(array_to_rows( + [['id' => 1, 'body' => null]], + schema(int_schema('id'), str_schema('body', nullable: true)), + )), ); } } 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 ef3b1fb4b3..a0609284ca 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 @@ -11,15 +11,18 @@ use Flow\ETL\Adapter\Doctrine\Tests\Double\NativeHandleStub; use Flow\ETL\Cardinality; use Flow\ETL\Exception\SchemaNotDerivableException; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use stdClass; use function Flow\ETL\Adapter\Doctrine\pagination_key_asc; use function Flow\ETL\Adapter\Doctrine\pagination_key_set; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function iterator_to_array; final class DbalKeySetExtractorTest extends FlowTestCase { @@ -140,4 +143,21 @@ public function test_a_new_maximum_drops_the_statistics(): void static::assertEquals(Cardinality::atMost(5), $extractor->statistics()->rows); } + + public function test_extract_builds_through_the_config_backend(): void + { + $connection = InMemorySqlite::withUsers(InMemorySqlite::connection(), 1); + $backend = new SpyBackend(); + + iterator_to_array( + (new DbalKeySetExtractor( + $connection, + $connection->createQueryBuilder()->select('*')->from('users'), + pagination_key_set(pagination_key_asc('id')), + ))->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } 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 86de2399b0..00746005eb 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 @@ -12,15 +12,18 @@ use Flow\ETL\Cardinality; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use stdClass; use function array_map; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function implode; +use function iterator_to_array; final class DbalLimitOffsetExtractorTest extends FlowTestCase { @@ -287,4 +290,20 @@ public function test_the_query_builder_limit_bounds_the_rows(): void ))->statistics()->rows, ); } + + public function test_extract_builds_through_the_config_backend(): void + { + $connection = InMemorySqlite::withUsers(InMemorySqlite::connection(), 1); + $backend = new SpyBackend(); + + iterator_to_array( + (new DbalLimitOffsetExtractor( + $connection, + $connection->createQueryBuilder()->select('*')->from('users')->orderBy('id'), + ))->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } 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 965efeaee6..624a5144e9 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 @@ -12,10 +12,14 @@ use Flow\ETL\Adapter\Doctrine\Tests\Double\NativeHandleStub; use Flow\ETL\Cardinality; use Flow\ETL\Exception\SchemaNotDerivableException; +use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\TestWith; use stdClass; +use function array_map; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -23,6 +27,7 @@ use function Flow\ETL\DSL\str_schema; use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_string; +use function iterator_to_array; final class DbalQueryExtractorTest extends FlowTestCase { @@ -186,4 +191,35 @@ public function test_naive_datetime_text_reads_as_utc_under_non_utc_default(): v date_default_timezone_set($previous); } } + + public function test_batches_split_at_the_batch_size(): void + { + $extractor = (new DbalQueryExtractor( + InMemorySqlite::withUsers(InMemorySqlite::connection(), 5), + 'SELECT * FROM users', + ))->withBatchSize(2); + + static::assertSame( + [2, 2, 1], + array_map( + static fn(Rows $rows): int => $rows->count(), + iterator_to_array($extractor->extract(flow_context()), false), + ), + ); + } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + iterator_to_array( + (new DbalQueryExtractor( + InMemorySqlite::withUsers(InMemorySqlite::connection(), 1), + 'SELECT * FROM users', + ))->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php new file mode 100644 index 0000000000..0200e0db04 --- /dev/null +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php @@ -0,0 +1,96 @@ + + */ + private ?array $headers = null; + + public function __construct( + private readonly bool $withHeader = true, + private readonly bool $convertEmptyToNull = true, + ) {} + + /** + * @param list> $batch + * + * @return list + */ + public function decode(array $batch): array + { + $decoded = []; + + foreach ($batch as $cells) { + if ($this->headers === null) { + if ($this->withHeader) { + $this->headers = $this->mapHeaders($cells); + + continue; + } + + $this->headers = $this->generateAutoHeaders(count($cells)); + } + + $values = []; + + foreach ($this->headers as $index => $name) { + // @mago-ignore analysis:mixed-assignment + $cell = $cells[$index] ?? null; + $values[$name] = $this->convertEmptyToNull && '' === $cell ? null : $cell; + } + + $decoded[] = new RawRowValues($values); + } + + return $decoded; + } + + /** + * The names decode() resolved from the first row it saw; null before the first decode(). + * + * @return null|list + */ + public function headers(): ?array + { + return $this->headers; + } + + /** + * @return list + */ + private function generateAutoHeaders(int $count): array + { + $headers = []; + + for ($i = 0; $i < $count; $i++) { + $headers[] = 'e' . str_pad((string) $i, 2, '0', STR_PAD_LEFT); + } + + return $headers; + } + + /** + * @param array $cells + * + * @return list + */ + private function mapHeaders(array $cells): array + { + return array_values(array_map(static fn(mixed $header): string => is_scalar($header) + ? (string) $header + : '', $cells)); + } +} diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelEncoder.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelEncoder.php index 836a0d4800..ce926bc4a2 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelEncoder.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelEncoder.php @@ -11,8 +11,7 @@ use Dom\XMLDocument; use DOMDocument; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; @@ -28,80 +27,48 @@ use Flow\Types\Type\Native\EnumType; use Flow\Types\Value\Json; use Flow\Types\Value\Uuid; -use Stringable; use UnitEnum; -use function array_map; use function array_values; -use function count; use function is_array; use function is_scalar; use function json_encode; -use function str_pad; use const JSON_THROW_ON_ERROR; -/** - * @implements Encoder> - */ -final class ExcelEncoder implements Encoder +final class ExcelEncoder { - /** - * @var null|list - */ - private ?array $headers = null; - public function __construct( - private readonly bool $withHeader = true, - private readonly bool $convertEmptyToNull = true, private readonly string $timeFormat = '%H:%I:%S', ) {} - public function decode(array $batch): array + /** + * @return list> + */ + public function encode(Rows $rows): array { - $decoded = []; - - foreach ($batch as $cells) { - if ($this->headers === null) { - if ($this->withHeader) { - $this->headers = $this->mapHeaders($cells); - - continue; - } - - $this->headers = $this->generateAutoHeaders(count($cells)); - } - - $values = []; + $columns = []; + $types = []; - foreach ($this->headers as $index => $name) { - // @mago-ignore analysis:mixed-assignment - $cell = $cells[$index] ?? null; - $values[$name] = $this->convertEmptyToNull && '' === $cell ? null : $cell; - } - - $decoded[] = new RawRowValues($values); + foreach ($rows->schema()->definitions() as $definition) { + $name = $definition->entry()->name(); + $columns[$name] = $rows->column($name)->values(); + $types[$name] = $definition->type(); } - return $decoded; - } - - public function encode(array $batch): array - { - $rows = []; + $encoded = []; - foreach ($batch as $rowValues) { + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { $cells = []; - /** @var mixed $value */ - foreach ($rowValues->values as $name => $value) { - $cells[] = $this->renderValue($rowValues->types[$name], $value); + foreach ($columns as $name => $column) { + $cells[] = $this->renderValue($types[$name], $column[$i]); } - $rows[] = $cells; + $encoded[] = $cells; } - return $rows; + return $encoded; } /** @@ -114,42 +81,6 @@ public function encodeHeader(array $headers): array return array_values($headers); } - /** - * The names decode() resolved from the first row it saw; null before the first decode(). - * - * @return null|list - */ - public function headers(): ?array - { - return $this->headers; - } - - /** - * @return list - */ - private function generateAutoHeaders(int $count): array - { - $headers = []; - - for ($i = 0; $i < $count; $i++) { - $headers[] = 'e' . str_pad((string) $i, 2, '0', STR_PAD_LEFT); - } - - return $headers; - } - - /** - * @param array $cells - * - * @return list - */ - private function mapHeaders(array $cells): array - { - return array_values(array_map(static fn(mixed $header): string => is_scalar($header) - ? (string) $header - : '', $cells)); - } - private function renderValue(Type $type, mixed $value): bool|DateTimeInterface|float|int|string|null { if ($value === null) { @@ -183,7 +114,6 @@ private function scalar(mixed $value): bool|float|int|string|null { return match (true) { is_scalar($value) => $value, - $value instanceof Stringable => (string) $value, default => null, }; } 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 53ac1e39a8..3a263ee74a 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 @@ -19,7 +19,9 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; +use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -33,6 +35,7 @@ use Throwable; use function array_diff; +use function array_map; use function array_values; use function count; use function iterator_to_array; @@ -123,7 +126,7 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $hydrator = $context->hydrator(); + $backend = $context->backend(); $batchSize = $this->batchSize(); $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); @@ -205,12 +208,18 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi continue; } - $hydrated = $constants->fillRows($hydrator->hydrate($batch, $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $batch)) + ->finish(), + $schema, + $backend, + ); $batch = []; - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; @@ -225,11 +234,17 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi continue; } - $hydrated = $constants->fillRows($hydrator->hydrate($batch, $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $batch)) + ->finish(), + $schema, + $backend, + ); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelLoader.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelLoader.php index aeded6bd14..2563bf312b 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelLoader.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelLoader.php @@ -17,8 +17,6 @@ use Flow\ETL\Loader\Partitioning; use Flow\ETL\Loader\PartitioningLoader; use Flow\ETL\Loader\PartitionRouter; -use Flow\ETL\Row; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; @@ -32,7 +30,7 @@ use OpenSpout\Writer\XLSX\Options as XlsxOptions; use Throwable; -use function array_keys; +use function array_values; use function is_string; use function sprintf; @@ -148,8 +146,6 @@ public function load(Rows $rows, FlowContext $context): void $encoder = $this->encoder(); foreach ($this->router->route($rows) as [$partitions, $group]) { - $dehydrated = $context->hydrator()->dehydrate($group); - $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( $partitions->toArray(), ); @@ -161,38 +157,50 @@ public function load(Rows $rows, FlowContext $context): void ); $manager->open($stream->path()->path()); - foreach ($group as $rowIndex => $row) { - $sheetName = $this->resolveSheetName($row); - - $rowSchema = $this->sheetNameEntryName !== null && $row->has($this->sheetNameEntryName) - ? $group->schema()->gracefulRemove($this->sheetNameEntryName) - : $group->schema(); - - $typed = $dehydrated[$rowIndex]; - $values = $typed->values; - $types = $typed->types; - $metadata = $typed->metadata; + $sheetColumn = + $this->sheetNameEntryName !== null + && $group->schema()->findDefinition($this->sheetNameEntryName) !== null + ? $this->sheetNameEntryName + : null; + $written = $sheetColumn === null + ? $group + : $group->project($group->schema()->gracefulRemove($sheetColumn)); + $sheetValues = $sheetColumn === null ? null : $group->column($sheetColumn)->values(); + + /** @var array> $sheets */ + $sheets = []; + + for ($i = 0; $i < $group->count(); $i++) { + $sheets[$this->resolveSheetName($sheetValues === null ? null : $sheetValues[$i])][] = $i; + } - if ($this->sheetNameEntryName !== null) { - unset( - $values[$this->sheetNameEntryName], - $types[$this->sheetNameEntryName], - $metadata[$this->sheetNameEntryName], - ); - } + foreach ($sheets as $sheetName => $indices) { + $sheetName = (string) $sheetName; + $sheetRows = $written->gather($indices); if ($this->withHeader && !$manager->isHeaderWritten($sheetName)) { $manager->writeHeader( $sheetName, - $encoder->encodeHeader(array_keys($values)), + $encoder->encodeHeader(array_values($sheetRows->schema()->references()->names())), $this->headerStyle, ); } - $styles = $this->resolveCellStyles($row, $rowSchema, $rowIndex, $sheetName); - /** @var array $cells */ - $cells = $encoder->encode([new TypedRowValues($values, $types, $metadata)])[0]; - $manager->writeRow($sheetName, $cells, $styles); + $values = []; + + foreach ($sheetRows->schema()->definitions() as $definition) { + $values[$definition->entry()->name()] = $sheetRows + ->column($definition->entry()->name()) + ->values(); + } + + foreach ($encoder->encode($sheetRows) as $k => $cells) { + $manager->writeRow( + $sheetName, + $cells, + $this->resolveCellStyles($sheetRows->schema(), $values, $k, $indices[$k] + 1, $sheetName), + ); + } } } @@ -319,18 +327,20 @@ private function encoder(): ExcelEncoder } /** + * @param array> $values + * * @return null|array */ - private function resolveCellStyles(Row $row, Schema $schema, int $rowIndex, string $sheetName): ?array + private function resolveCellStyles(Schema $schema, array $values, int $i, int $rowNumber, string $sheetName): ?array { $styles = []; $columnIndex = 0; foreach ($schema->definitions() as $definition) { $styles[$columnIndex] = $this->cellStyler?->style( - $row->get($definition->entry()->name()), + $values[$definition->entry()->name()][$i], $definition, - $rowIndex + 1, + $rowNumber, $columnIndex, $sheetName, ) ?? $this->temporalStyle($definition); @@ -340,16 +350,12 @@ private function resolveCellStyles(Row $row, Schema $schema, int $rowIndex, stri return $styles; } - private function resolveSheetName(Row $row): string + private function resolveSheetName(mixed $value): string { - if ($this->sheetNameEntryName !== null && $row->has($this->sheetNameEntryName)) { - $value = $row->get($this->sheetNameEntryName); - - if (is_string($value) && $value !== '') { - SheetNameAssertion::assert($value); + if (is_string($value) && $value !== '') { + SheetNameAssertion::assert($value); - return $value; - } + return $value; } return $this->sheetName ?? 'Sheet1'; diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Sheet/OpenSheet.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Sheet/OpenSheet.php index 8c20cce0c1..fcbe7bdd6a 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Sheet/OpenSheet.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Sheet/OpenSheet.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\Excel\Sheet; -use Flow\ETL\Adapter\Excel\ExcelEncoder; +use Flow\ETL\Adapter\Excel\ExcelDecoder; use Generator; use OpenSpout\Reader\ODS\Reader as OdsReader; use OpenSpout\Reader\XLSX\Reader as XlsxReader; @@ -20,7 +20,7 @@ public function __construct( private XlsxReader|OdsReader $reader, public Generator $cells, - public ExcelEncoder $encoder, + public ExcelDecoder $decoder, ) {} public function close(): void diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookManager.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookManager.php index 67bafade6e..03724c2008 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookManager.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookManager.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Excel; +use DateTimeInterface; use LogicException; use OpenSpout\Common\Entity\Row as OpenSpoutRow; use OpenSpout\Common\Entity\Style\Style; @@ -100,7 +101,7 @@ public function writeHeader(string $sheetName, array $headers, ?Style $style = n } /** - * @param array $values + * @param array $values * @param null|array $styles */ public function writeRow(string $sheetName, array $values, ?array $styles = null): void diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookReader.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookReader.php index c5561fb890..0295f7f424 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookReader.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookReader.php @@ -41,7 +41,7 @@ public function open(Path $path): OpenSheet return new OpenSheet( $reader, (new SheetCells($sheet, $this->options->withHeader, $this->options->offset))->rows(), - new ExcelEncoder( + new ExcelDecoder( withHeader: $this->options->withHeader, convertEmptyToNull: $this->options->convertEmptyToNull, ), diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheet.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheet.php index 735cf6ae03..d05c47bea5 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheet.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheet.php @@ -45,12 +45,12 @@ public function columns(): array $row = $sheet->cells->current(); if ($row !== null) { - $this->buffered = $sheet->encoder->decode([$row]); + $this->buffered = $sheet->decoder->decode([$row]); $sheet->cells->next(); } } - return $sheet->encoder->headers() ?? []; + return $sheet->decoder->headers() ?? []; } /** @@ -74,7 +74,7 @@ public function sample(): Generator // buffered, so rows() neither repeats nor skips a row $sheet->cells->next(); - foreach ($sheet->encoder->decode([$row]) as $rowValues) { + foreach ($sheet->decoder->decode([$row]) as $rowValues) { $this->buffered[] = $rowValues; yield $rowValues; @@ -101,7 +101,7 @@ public function rows(): Generator $this->buffered = []; while (($row = $sheet->cells->current()) !== null) { - foreach ($sheet->encoder->decode([$row]) as $rowValues) { + foreach ($sheet->decoder->decode([$row]) as $rowValues) { yield $rowValues; } diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Double/RecordingCellStyler.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Double/RecordingCellStyler.php new file mode 100644 index 0000000000..aae1e6623d --- /dev/null +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Double/RecordingCellStyler.php @@ -0,0 +1,34 @@ + "sheet:value@rowNumber" of every first-column cell + */ + public array $firstColumnCells = []; + + public function style( + mixed $value, + Definition $definition, + int $rowNumber, + int $columnIndex, + string $sheetName, + ): ?Style { + if ($columnIndex === 0) { + $this->firstColumnCells[] = + $sheetName . ':' . (is_scalar($value) ? (string) $value : '') . '@' . $rowNumber; + } + + return null; + } +} 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 d8fb8be3b5..4f8f6fc9a9 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 @@ -19,6 +19,7 @@ use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\Double\KeepPaths; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\UnsizedFilesystem; use Flow\ETL\Tests\FlowTestCase; use Generator; @@ -30,6 +31,7 @@ use function Flow\ETL\Adapter\Excel\DSL\is_valid_excel_sheet_name; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\df; @@ -44,6 +46,7 @@ use function Flow\Filesystem\DSL\native_local_filesystem; use function Flow\Filesystem\DSL\path_real; use function Flow\Types\DSL\type_datetime; +use function iterator_to_array; use function max; final class ExcelExtractorTest extends FlowTestCase @@ -920,4 +923,18 @@ public function test_date_cells_read_as_utc_wall_clock_under_non_utc_default(): date_default_timezone_set($previous); } } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + iterator_to_array( + from_excel(__DIR__ . '/../Fixtures/fixture.xlsx')->extract( + flow_context(config_builder()->backend($backend)->build()), + ), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelHydratorParityTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTypedColumnsTest.php similarity index 96% rename from src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelHydratorParityTest.php rename to src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTypedColumnsTest.php index 4f0b66a8d5..cac412bb80 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelHydratorParityTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTypedColumnsTest.php @@ -15,7 +15,7 @@ use function Flow\Filesystem\DSL\path_real; use function Flow\Types\DSL\type_integer; -final class ExcelHydratorParityTest extends FlowTestCase +final class ExcelExtractorTypedColumnsTest extends FlowTestCase { public function test_reads_typed_columns_with_a_schema(): void { diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelLoaderTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelLoaderTest.php index 51f0d454c6..1d6b2e0976 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelLoaderTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelLoaderTest.php @@ -8,6 +8,7 @@ use DateTimeImmutable; use Flow\ETL\Adapter\Excel\CellStyler; use Flow\ETL\Adapter\Excel\ExcelWriter; +use Flow\ETL\Adapter\Excel\Tests\Double\RecordingCellStyler; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Schema\Definition; use Flow\ETL\Tests\FlowTestCase; @@ -505,6 +506,33 @@ public function style( ); } + public function test_cell_styler_receives_the_row_index_within_the_batch(): void + { + $styler = new RecordingCellStyler(); + + df() + ->read(from_rows(array_to_rows( + [ + ['id' => 1, 'sheet' => 'A'], + ['id' => 2, 'sheet' => 'B'], + ['id' => 3, 'sheet' => 'A'], + ['id' => 4, 'sheet' => 'A'], + ['id' => 5, 'sheet' => 'B'], + ], + schema(int_schema('id'), string_schema('sheet')), + ))) + ->batchSize(2) + ->write( + to_excel(__DIR__ . '/var/output_row_number.xlsx') + ->withSheetNameFromEntry('sheet') + ->withCellStyler($styler) + ->saveMode(overwrite()), + ) + ->run(); + + static::assertSame(['A:1@1', 'B:2@2', 'A:3@1', 'A:4@2', 'B:5@1'], $styler->firstColumnCells); + } + public function test_with_header_style(): void { $outputPath = __DIR__ . '/var/output_header_style.xlsx'; diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/Sheet/OpenSheetTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/Sheet/OpenSheetTest.php index c30e89c81e..ef688d1abd 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/Sheet/OpenSheetTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/Sheet/OpenSheetTest.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\Excel\Tests\Integration\Sheet; -use Flow\ETL\Adapter\Excel\ExcelEncoder; +use Flow\ETL\Adapter\Excel\ExcelDecoder; use Flow\ETL\Adapter\Excel\Sheet\OpenSheet; use Flow\ETL\Adapter\Excel\Sheet\SheetCells; use Flow\ETL\Adapter\Excel\Sheet\SheetsManager; @@ -15,7 +15,7 @@ final class OpenSheetTest extends FlowTestCase { - public function test_it_carries_the_cells_and_the_encoder_of_one_handle(): void + public function test_it_carries_the_cells_and_the_decoder_of_one_handle(): void { $reader = new XlsxReader(); $reader->open(ExcelFixtureContext::path('fixture.xlsx')->path()); @@ -23,11 +23,11 @@ public function test_it_carries_the_cells_and_the_encoder_of_one_handle(): void $open = new OpenSheet( $reader, (new SheetCells((new SheetsManager($reader->getSheetIterator()))->first(), true, 1))->rows(), - $encoder = new ExcelEncoder(), + $decoder = new ExcelDecoder(), ); static::assertSame(['id', 'name', 'email'], $open->cells->current()); - static::assertSame($encoder, $open->encoder); + static::assertSame($decoder, $open->decoder); $open->close(); } @@ -40,7 +40,7 @@ public function test_closing_it_closes_the_reader_it_was_given(): void (new OpenSheet( $reader, (new SheetCells((new SheetsManager($reader->getSheetIterator()))->first(), true, 1))->rows(), - new ExcelEncoder(), + new ExcelDecoder(), ))->close(); $this->expectException(ReaderNotOpenedException::class); diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php new file mode 100644 index 0000000000..7964f84fdd --- /dev/null +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php @@ -0,0 +1,80 @@ +decode([['id', 'name']])); + static::assertSame(['id' => 1, 'name' => 'Norbert'], $decoder->decode([[1, 'Norbert']])[0]->values); + } + + public function test_decode_generates_auto_headers_when_header_is_disabled(): void + { + static::assertSame( + ['e00' => 1, 'e01' => 'Norbert'], + (new ExcelDecoder(withHeader: false))->decode([[1, 'Norbert']])[0]->values, + ); + } + + public function test_headers_are_generated_when_header_is_disabled(): void + { + $decoder = new ExcelDecoder(withHeader: false); + + static::assertCount(1, $decoder->decode([[1, 2, 3]])); + static::assertSame(['e00', 'e01', 'e02'], $decoder->headers()); + } + + public function test_headers_are_null_before_the_first_decode(): void + { + static::assertNull((new ExcelDecoder())->headers()); + } + + public function test_headers_are_stringified_and_blank_for_non_scalar_cells(): void + { + $decoder = new ExcelDecoder(); + $decoder->decode([[1, null, 'x']]); + + static::assertSame(['1', '', 'x'], $decoder->headers()); + } + + public function test_headers_are_the_header_row_after_decode(): void + { + $decoder = new ExcelDecoder(); + + static::assertSame([], $decoder->decode([['id', 'name']])); + static::assertSame(['id', 'name'], $decoder->headers()); + } + + public function test_decode_keeps_empty_cells_when_convert_empty_to_null_is_disabled(): void + { + static::assertSame( + ['id' => 1, 'name' => ''], + (new ExcelDecoder(convertEmptyToNull: false))->decode([['id', 'name'], [1, '']])[0]->values, + ); + } + + public function test_decode_maps_cells_to_headers(): void + { + static::assertSame( + ['id' => 1, 'name' => 'Norbert'], + (new ExcelDecoder())->decode([['id', 'name'], [1, 'Norbert']])[0]->values, + ); + } + + public function test_decode_turns_empty_cells_into_null_by_default(): void + { + static::assertSame( + ['id' => 1, 'name' => null], + (new ExcelDecoder())->decode([['id', 'name'], [1, '']])[0]->values, + ); + } +} diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelEncoderTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelEncoderTest.php index 02dd2be240..cf0bc3f9bf 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelEncoderTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelEncoderTest.php @@ -9,109 +9,43 @@ use DateTimeZone; use DOMDocument; use Flow\ETL\Adapter\Excel\ExcelEncoder; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\Fixtures\Enum\BackedIntEnum; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Value\Uuid; -use Stringable; - -use function Flow\Types\DSL\type_array; -use function Flow\Types\DSL\type_boolean; -use function Flow\Types\DSL\type_date; -use function Flow\Types\DSL\type_datetime; -use function Flow\Types\DSL\type_enum; -use function Flow\Types\DSL\type_float; + +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\enum_schema; +use function Flow\ETL\DSL\float_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\ETL\DSL\time_zone_schema; +use function Flow\ETL\DSL\uuid_schema; +use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_integer; -use function Flow\Types\DSL\type_json; -use function Flow\Types\DSL\type_object; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_string; -use function Flow\Types\DSL\type_time; -use function Flow\Types\DSL\type_time_zone; -use function Flow\Types\DSL\type_uuid; -use function Flow\Types\DSL\type_xml; +use function Flow\Types\DSL\type_structure; final class ExcelEncoderTest extends FlowTestCase { - public function test_decode_captures_headers_from_the_first_row_and_emits_no_row_for_it(): void - { - $encoder = new ExcelEncoder(); - - static::assertSame([], $encoder->decode([['id', 'name']])); - static::assertSame(['id' => 1, 'name' => 'Norbert'], $encoder->decode([[1, 'Norbert']])[0]->values); - } - - public function test_decode_generates_auto_headers_when_header_is_disabled(): void - { - static::assertSame( - ['e00' => 1, 'e01' => 'Norbert'], - (new ExcelEncoder(withHeader: false))->decode([[1, 'Norbert']])[0]->values, - ); - } - - public function test_headers_are_generated_when_header_is_disabled(): void - { - $encoder = new ExcelEncoder(withHeader: false); - - static::assertCount(1, $encoder->decode([[1, 2, 3]])); - static::assertSame(['e00', 'e01', 'e02'], $encoder->headers()); - } - - public function test_headers_are_null_before_the_first_decode(): void - { - static::assertNull((new ExcelEncoder())->headers()); - } - - public function test_headers_are_stringified_and_blank_for_non_scalar_cells(): void - { - $encoder = new ExcelEncoder(); - $encoder->decode([[1, null, 'x']]); - - static::assertSame(['1', '', 'x'], $encoder->headers()); - } - - public function test_headers_are_the_header_row_after_decode(): void - { - $encoder = new ExcelEncoder(); - - static::assertSame([], $encoder->decode([['id', 'name']])); - static::assertSame(['id', 'name'], $encoder->headers()); - } - - public function test_decode_keeps_empty_cells_when_convert_empty_to_null_is_disabled(): void - { - static::assertSame( - ['id' => 1, 'name' => ''], - (new ExcelEncoder(convertEmptyToNull: false))->decode([['id', 'name'], [1, '']])[0]->values, - ); - } - - public function test_decode_maps_cells_to_headers(): void - { - static::assertSame( - ['id' => 1, 'name' => 'Norbert'], - (new ExcelEncoder())->decode([['id', 'name'], [1, 'Norbert']])[0]->values, - ); - } - - public function test_decode_turns_empty_cells_into_null_by_default(): void - { - static::assertSame( - ['id' => 1, 'name' => null], - (new ExcelEncoder())->decode([['id', 'name'], [1, '']])[0]->values, - ); - } - public function test_encodes_scalars_as_a_flat_cell_list_in_value_order(): void { static::assertSame( [[1, 'Norbert', 1.5, true]], - (new ExcelEncoder())->encode([new TypedRowValues([ - 'id' => 1, - 'name' => 'Norbert', - 'p' => 1.5, - 'a' => true, - ], ['id' => type_integer(), 'name' => type_string(), 'p' => type_float(), 'a' => type_boolean()])]), + (new ExcelEncoder())->encode(array_to_rows( + [['id' => 1, 'name' => 'Norbert', 'p' => 1.5, 'a' => true]], + schema(int_schema('id'), str_schema('name'), float_schema('p'), bool_schema('a')), + )), ); } @@ -120,13 +54,12 @@ public function test_encodes_dates_and_datetimes_as_cell_values_and_intervals_wi $date = new DateTimeImmutable('2024-08-01'); $dateTime = new DateTimeImmutable('2024-08-01 10:30:00'); - static::assertSame( + static::assertEquals( [[$date, $dateTime, '01:30']], - (new ExcelEncoder(timeFormat: '%H:%I'))->encode([new TypedRowValues([ - 'd' => $date, - 'dt' => $dateTime, - 't' => new DateInterval('PT1H30M'), - ], ['d' => type_date(), 'dt' => type_datetime(), 't' => type_time()])]), + (new ExcelEncoder(timeFormat: '%H:%I'))->encode(array_to_rows( + [['d' => $date, 'dt' => $dateTime, 't' => new DateInterval('PT1H30M')]], + schema(date_schema('d'), datetime_schema('dt'), time_schema('t')), + )), ); } @@ -134,9 +67,9 @@ public function test_encodes_time_with_the_default_time_format(): void { static::assertSame( [['14:30:45']], - (new ExcelEncoder())->encode([ - new TypedRowValues(['t' => new DateInterval('PT14H30M45S')], ['t' => type_time()]), - ]), + (new ExcelEncoder())->encode(array_to_rows([[ + 't' => new DateInterval('PT14H30M45S'), + ]], schema(time_schema('t')))), ); } @@ -144,9 +77,9 @@ public function test_encodes_backed_enum_as_its_backing_value(): void { static::assertSame( [['1']], - (new ExcelEncoder())->encode([ - new TypedRowValues(['e' => BackedIntEnum::one], ['e' => type_enum(BackedIntEnum::class)]), - ]), + (new ExcelEncoder())->encode(array_to_rows([[ + 'e' => BackedIntEnum::one, + ]], schema(enum_schema('e', BackedIntEnum::class)))), ); } @@ -154,24 +87,9 @@ public function test_encodes_a_pure_enum_as_its_case_name(): void { static::assertSame( [['three']], - (new ExcelEncoder())->encode([ - new TypedRowValues(['e' => BasicEnum::three], ['e' => type_enum(BasicEnum::class)]), - ]), - ); - } - - public function test_encodes_a_stringable_as_its_string(): void - { - static::assertSame( - [['Krakow']], - (new ExcelEncoder())->encode([ - new TypedRowValues(['s' => new class implements Stringable { - public function __toString(): string - { - return 'Krakow'; - } - }], ['s' => type_object()]), - ]), + (new ExcelEncoder())->encode(array_to_rows([[ + 'e' => BasicEnum::three, + ]], schema(enum_schema('e', BasicEnum::class)))), ); } @@ -182,43 +100,22 @@ public function test_encodes_an_xml_document_as_its_serialized_root(): void static::assertSame( [['1']], - (new ExcelEncoder())->encode([new TypedRowValues(['x' => $document], ['x' => type_xml()])]), - ); - } - - public function test_encodes_a_value_that_does_not_match_its_declared_type_as_null(): void - { - static::assertSame( - [[null, null, null, null, null, null, null]], - (new ExcelEncoder())->encode([new TypedRowValues([ - 'datetime' => 'not a datetime', - 'date' => 'not a date', - 'time' => 'not an interval', - 'enum' => 'not an enum', - 'json' => 'not a json value', - 'uuid' => 'not a uuid', - 'xml' => 'not a document', - ], [ - 'datetime' => type_datetime(), - 'date' => type_date(), - 'time' => type_time(), - 'enum' => type_enum(BasicEnum::class), - 'json' => type_json(), - 'uuid' => type_uuid(), - 'xml' => type_xml(), - ])]), + (new ExcelEncoder())->encode(array_to_rows([['x' => $document]], schema(xml_schema('x')))), ); } - public function test_encodes_arrays_as_json(): void + public function test_encodes_containers_as_json(): void { static::assertSame( [['["a","b"]', '{"x":1}', '{"city":"Krakow"}']], - (new ExcelEncoder())->encode([new TypedRowValues([ - 'tags' => ['a', 'b'], - 'm' => ['x' => 1], - 'addr' => ['city' => 'Krakow'], - ], ['tags' => type_array(), 'm' => type_array(), 'addr' => type_array()])]), + (new ExcelEncoder())->encode(array_to_rows( + [['tags' => ['a', 'b'], 'm' => ['x' => 1], 'addr' => ['city' => 'Krakow']]], + schema( + list_schema('tags', type_list(type_string())), + map_schema('m', type_map(type_string(), type_integer())), + structure_schema('addr', type_structure(['city' => type_string()])), + ), + )), ); } @@ -226,9 +123,9 @@ public function test_encodes_a_timezone_as_its_iana_name(): void { static::assertSame( [['Europe/Warsaw']], - (new ExcelEncoder())->encode([new TypedRowValues([ + (new ExcelEncoder())->encode(array_to_rows([[ 'tz' => new DateTimeZone('Europe/Warsaw'), - ], ['tz' => type_time_zone()])]), + ]], schema(time_zone_schema('tz')))), ); } @@ -236,9 +133,9 @@ public function test_encodes_uuid_as_string(): void { static::assertSame( [['f47ac10b-58cc-4372-a567-0e02b2c3d479']], - (new ExcelEncoder())->encode([new TypedRowValues([ + (new ExcelEncoder())->encode(array_to_rows([[ 'id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), - ], ['id' => type_uuid()])]), + ]], schema(uuid_schema('id')))), ); } @@ -246,9 +143,10 @@ public function test_encodes_null_values_as_null_cells(): void { static::assertSame( [[null, null]], - (new ExcelEncoder())->encode([ - new TypedRowValues(['id' => null, 'd' => null], ['id' => type_integer(), 'd' => type_date()]), - ]), + (new ExcelEncoder())->encode(array_to_rows( + [['id' => null, 'd' => null]], + schema(int_schema('id', nullable: true), date_schema('d', nullable: true)), + )), ); } } diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetEncoder.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php similarity index 89% rename from src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetEncoder.php rename to src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php index 09224a9d46..1db2cf5fc4 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetEncoder.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php @@ -5,8 +5,6 @@ namespace Flow\ETL\Adapter\GoogleSheet; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; use Flow\ETL\Row\RawRowValues; use function array_combine; @@ -16,10 +14,7 @@ use function count; use function str_pad; -/** - * @implements Encoder> - */ -final class GoogleSheetEncoder implements Encoder +final class GoogleSheetDecoder { /** * @var list @@ -34,6 +29,11 @@ public function __construct( private readonly bool $emptyToNull = true, ) {} + /** + * @param list> $batch + * + * @return list + */ public function decode(array $batch): array { $maps = []; @@ -93,13 +93,6 @@ public function decode(array $batch): array return $maps; } - public function encode(array $batch): array - { - throw new RuntimeException( - 'Google Sheet adapter is read-only, encoding rows back to sheet values is not supported', - ); - } - /** * The header the first decoded row consumed, or the generated `e00`... names under withHeader(false); * [] before any row. 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 2472e454e5..b10f57838e 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 @@ -19,6 +19,7 @@ use Flow\ETL\FlowContext; use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -104,7 +105,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $schema = $this->addMetadataColumns ? $base->add(str_schema('_spread_sheet_id'), str_schema('_sheet_name')) : $base; - $hydrator = $context->hydrator(); + $backend = $context->backend(); $checked = $this->schema !== null || $this->inference->unionByName; $batchSize = $this->batchSize(); @@ -157,11 +158,13 @@ function (RawRowValues $rowValues): RawRowValues { ); } - $hydrated = $hydrator->hydrate($batch, $schema); + $rows = (new RowsBuilder($schema, $backend)) + ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $batch)) + ->finish(); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReadOptions.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReadOptions.php index 8c780886c9..9d32fa7a43 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReadOptions.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReadOptions.php @@ -25,11 +25,11 @@ public function __construct( ) {} /** - * A fresh encoder per pass - the sample and the read each consume their own header row. + * A fresh decoder per pass - the sample and the read each consume their own header row. */ - public function encoder(): GoogleSheetEncoder + public function decoder(): GoogleSheetDecoder { - return new GoogleSheetEncoder($this->withHeader, $this->dropExtraColumns, $this->emptyToNull); + return new GoogleSheetDecoder($this->withHeader, $this->dropExtraColumns, $this->emptyToNull); } /** diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php index c4eae47aac..4270123f1f 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php @@ -36,14 +36,14 @@ public function batches(int $rowsPerPage, int $batchSize): Generator /** @var Sheets\Resource\SpreadsheetsValues $values */ $values = $this->service->spreadsheets_values; - $encoder = $this->readOptions->encoder(); + $decoder = $this->readOptions->decoder(); $batch = []; foreach ($values->batchGet($this->spreadsheetId, array_merge($this->readOptions->options, [ 'ranges' => $ranges, ]))->getValueRanges() as $valueRange) { // @mago-ignore analysis:redundant-null-coalesce - foreach ($encoder->decode(array_values($valueRange->getValues() ?? [])) as $rowValues) { + foreach ($decoder->decode(array_values($valueRange->getValues() ?? [])) as $rowValues) { $batch[] = $rowValues; if (count($batch) >= $batchSize) { @@ -89,12 +89,12 @@ public function sample(int $rows): GoogleSheetSample /** @var Sheets\Resource\SpreadsheetsValues $values */ $values = $this->service->spreadsheets_values; - $encoder = $this->readOptions->encoder(); + $decoder = $this->readOptions->decoder(); // @mago-ignore analysis:redundant-null-coalesce - $decoded = $encoder->decode(array_values( + $decoded = $decoder->decode(array_values( $values->get($this->spreadsheetId, $range->toString(), $this->readOptions->options)->getValues() ?? [], )); - return new GoogleSheetSample($encoder->headers(), $decoded, $range->endRow >= $rowCount, $rowCount); + return new GoogleSheetSample($decoder->headers(), $decoded, $range->endRow >= $rowCount, $rowCount); } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetHydratorParityTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTypedColumnsTest.php similarity index 97% rename from src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetHydratorParityTest.php rename to src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTypedColumnsTest.php index 107a93381b..27ef7789e9 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetHydratorParityTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTypedColumnsTest.php @@ -19,7 +19,7 @@ use function Flow\ETL\DSL\string_schema; use function reset; -final class GoogleSheetHydratorParityTest extends FlowTestCase +final class GoogleSheetExtractorTypedColumnsTest extends FlowTestCase { public function test_appends_spread_sheet_id_and_sheet_name_to_the_schema_when_metadata_columns_are_enabled(): void { diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetEncoderTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php similarity index 65% rename from src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetEncoderTest.php rename to src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php index 7da527a0bf..5005fdf6fa 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetEncoderTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php @@ -4,21 +4,19 @@ namespace Flow\ETL\Adapter\GoogleSheet\Tests\Unit; -use Flow\ETL\Adapter\GoogleSheet\GoogleSheetEncoder; +use Flow\ETL\Adapter\GoogleSheet\GoogleSheetDecoder; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\FlowTestCase; use function array_map; -final class GoogleSheetEncoderTest extends FlowTestCase +final class GoogleSheetDecoderTest extends FlowTestCase { public function test_decodes_rows_with_first_row_as_headers(): void { - $encoder = new GoogleSheetEncoder(); + $decoder = new GoogleSheetDecoder(); - $decoded = $encoder->decode([ + $decoded = $decoder->decode([ ['id', 'name'], ['1', 'Norbert'], ['2', 'Tomek'], @@ -35,9 +33,9 @@ public function test_decodes_rows_with_first_row_as_headers(): void public function test_skips_empty_rows_before_headers(): void { - $encoder = new GoogleSheetEncoder(); + $decoder = new GoogleSheetDecoder(); - $decoded = $encoder->decode([ + $decoded = $decoder->decode([ [], ['id', 'name'], ['1', 'Norbert'], @@ -51,21 +49,21 @@ public function test_skips_empty_rows_before_headers(): void public function test_keeps_headers_between_decode_calls(): void { - $encoder = new GoogleSheetEncoder(); + $decoder = new GoogleSheetDecoder(); - $encoder->decode([['id', 'name'], ['1', 'Norbert']]); + $decoder->decode([['id', 'name'], ['1', 'Norbert']]); static::assertSame( [['id' => '2', 'name' => 'Tomek']], - array_map(static fn($rowValues): array => $rowValues->values, $encoder->decode([['2', 'Tomek']])), + array_map(static fn($rowValues): array => $rowValues->values, $decoder->decode([['2', 'Tomek']])), ); } public function test_pads_shorter_rows_with_nulls(): void { - $encoder = new GoogleSheetEncoder(); + $decoder = new GoogleSheetDecoder(); - $decoded = $encoder->decode([ + $decoded = $decoder->decode([ ['id', 'name'], ['1'], ]); @@ -78,9 +76,9 @@ public function test_pads_shorter_rows_with_nulls(): void public function test_drops_extra_columns(): void { - $encoder = new GoogleSheetEncoder(); + $decoder = new GoogleSheetDecoder(); - $decoded = $encoder->decode([ + $decoded = $decoder->decode([ ['id', 'name'], ['1', 'Norbert', 'extra'], ]); @@ -93,12 +91,12 @@ public function test_drops_extra_columns(): void public function test_throws_on_extra_columns_when_drop_is_disabled(): void { - $encoder = new GoogleSheetEncoder(dropExtraColumns: false); + $decoder = new GoogleSheetDecoder(dropExtraColumns: false); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Row has more columns (3) than headers (2)'); - $encoder->decode([ + $decoder->decode([ ['id', 'name'], ['1', 'Norbert', 'extra'], ]); @@ -106,9 +104,9 @@ public function test_throws_on_extra_columns_when_drop_is_disabled(): void public function test_generates_auto_headers_without_header_row(): void { - $encoder = new GoogleSheetEncoder(withHeader: false); + $decoder = new GoogleSheetDecoder(withHeader: false); - $decoded = $encoder->decode([ + $decoded = $decoder->decode([ ['1', 'Norbert'], ['2', 'Tomek'], ]); @@ -122,33 +120,23 @@ public function test_generates_auto_headers_without_header_row(): void ); } - public function test_encode_is_not_supported(): void - { - $encoder = new GoogleSheetEncoder(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Google Sheet adapter is read-only'); - - $encoder->encode([new TypedRowValues([], [])]); - } - public function test_empty_cells_become_null_by_default(): void { - $encoder = new GoogleSheetEncoder(); + $decoder = new GoogleSheetDecoder(); static::assertSame( [['a' => null, 'b' => 'x']], - array_map(static fn($rowValues): array => $rowValues->values, $encoder->decode([['a', 'b'], ['', 'x']])), + array_map(static fn($rowValues): array => $rowValues->values, $decoder->decode([['a', 'b'], ['', 'x']])), ); } public function test_empty_cells_stay_strings_when_asked(): void { - $encoder = new GoogleSheetEncoder(emptyToNull: false); + $decoder = new GoogleSheetDecoder(emptyToNull: false); static::assertSame( [['a' => '', 'b' => 'x']], - array_map(static fn($rowValues): array => $rowValues->values, $encoder->decode([['a', 'b'], ['', 'x']])), + array_map(static fn($rowValues): array => $rowValues->values, $decoder->decode([['a', 'b'], ['', 'x']])), ); } @@ -156,14 +144,14 @@ public function test_omitted_trailing_cells_are_null_regardless_of_empty_to_null { static::assertSame( [['a' => 'x', 'b' => null]], - array_map(static fn($rowValues): array => $rowValues->values, (new GoogleSheetEncoder())->decode([ + array_map(static fn($rowValues): array => $rowValues->values, (new GoogleSheetDecoder())->decode([ ['a', 'b'], ['x'], ])), ); static::assertSame( [['a' => 'x', 'b' => null]], - array_map(static fn($rowValues): array => $rowValues->values, (new GoogleSheetEncoder( + array_map(static fn($rowValues): array => $rowValues->values, (new GoogleSheetDecoder( emptyToNull: false, ))->decode([['a', 'b'], ['x']])), ); @@ -171,39 +159,39 @@ public function test_omitted_trailing_cells_are_null_regardless_of_empty_to_null public function test_headers_are_empty_before_the_first_row(): void { - static::assertSame([], (new GoogleSheetEncoder())->headers()); + static::assertSame([], (new GoogleSheetDecoder())->headers()); } public function test_headers_are_the_consumed_header_row(): void { - $encoder = new GoogleSheetEncoder(); - $encoder->decode([['a', 'b'], ['1', '2']]); + $decoder = new GoogleSheetDecoder(); + $decoder->decode([['a', 'b'], ['1', '2']]); - static::assertSame(['a', 'b'], $encoder->headers()); + static::assertSame(['a', 'b'], $decoder->headers()); } public function test_headers_skip_a_leading_empty_row(): void { - $encoder = new GoogleSheetEncoder(); - $encoder->decode([[], ['a', 'b']]); + $decoder = new GoogleSheetDecoder(); + $decoder->decode([[], ['a', 'b']]); - static::assertSame(['a', 'b'], $encoder->headers()); + static::assertSame(['a', 'b'], $decoder->headers()); } public function test_headers_are_generated_without_a_header_row(): void { - $encoder = new GoogleSheetEncoder(withHeader: false); - $encoder->decode([['1', '2', '3']]); + $decoder = new GoogleSheetDecoder(withHeader: false); + $decoder->decode([['1', '2', '3']]); - static::assertSame(['e00', 'e01', 'e02'], $encoder->headers()); + static::assertSame(['e00', 'e01', 'e02'], $decoder->headers()); } public function test_headers_are_strings_even_when_the_api_typed_them(): void { - $encoder = new GoogleSheetEncoder(); - $encoder->decode([[1, '2'], ['x', 'y']]); + $decoder = new GoogleSheetDecoder(); + $decoder->decode([[1, '2'], ['x', 'y']]); - static::assertSame(['1', '2'], $encoder->headers()); + static::assertSame(['1', '2'], $decoder->headers()); } /** @@ -213,10 +201,10 @@ public function test_headers_are_strings_even_when_the_api_typed_them(): void */ public function test_two_header_cells_with_the_same_name_collapse_the_row_to_one_column(): void { - $encoder = new GoogleSheetEncoder(); - $decoded = $encoder->decode([[1, true], ['x', 'y']]); + $decoder = new GoogleSheetDecoder(); + $decoded = $decoder->decode([[1, true], ['x', 'y']]); - static::assertSame(['1', '1'], $encoder->headers()); + static::assertSame(['1', '1'], $decoder->headers()); static::assertSame(['1' => 'y'], $decoded[0]->values); } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php index 3b9cb0e933..f245c58339 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php @@ -16,12 +16,14 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\Rows; use Flow\ETL\Tests\Context\ExtractedRows; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Google\Service\Sheets; use PHPUnit\Framework\Attributes\DataProvider; use function array_sum; use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\infer_schema; use function Flow\ETL\DSL\int_schema; @@ -623,4 +625,21 @@ public function test_shape_changing_setters_drop_the_sampled_statistics(Closure static::assertEquals(new Statistics(), $extractor->statistics()); } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + iterator_to_array( + GoogleSheetFixtureContext::extractor(GoogleSheetFixtureContext::service(100, GoogleSheetFixtureContext::valuesAndBatches([], [SheetValuesMother::batch([[ + ['header'], + ['row1'], + ]])]))) + ->withSchema(schema(str_schema('header'))) + ->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReadOptionsTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReadOptionsTest.php index 798534c511..e98e45ff6d 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReadOptionsTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReadOptionsTest.php @@ -65,34 +65,34 @@ public function test_with_options_changes_only_the_options(): void static::assertSame(['valueRenderOption' => 'UNFORMATTED_VALUE'], $options->options); } - public function test_encoder_is_a_fresh_instance_per_call(): void + public function test_decoder_is_a_fresh_instance_per_call(): void { $options = new GoogleSheetReadOptions(); - static::assertNotSame($options->encoder(), $options->encoder()); + static::assertNotSame($options->decoder(), $options->decoder()); } - public function test_encoder_carries_the_empty_to_null_flag(): void + public function test_decoder_carries_the_empty_to_null_flag(): void { static::assertSame( [['a' => '']], array_map(static fn($rowValues): array => $rowValues->values, (new GoogleSheetReadOptions()) ->withEmptyToNull(false) - ->encoder() + ->decoder() ->decode([['a'], ['']])), ); } - public function test_encoder_carries_the_drop_extra_columns_flag(): void + public function test_decoder_carries_the_drop_extra_columns_flag(): void { - $encoder = (new GoogleSheetReadOptions()) + $decoder = (new GoogleSheetReadOptions()) ->withDropExtraColumns(false) - ->encoder(); + ->decoder(); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Row has more columns (2) than headers (1)'); - $encoder->decode([['a'], ['x', 'y']]); + $decoder->decode([['a'], ['x', 'y']]); } public function test_typer_runs_the_string_ladder_under_the_default_render_option(): void @@ -113,13 +113,13 @@ public function test_typer_uses_the_value_type_under_any_other_render_option(): ); } - public function test_encoder_carries_the_header_flag(): void + public function test_decoder_carries_the_header_flag(): void { - $encoder = (new GoogleSheetReadOptions()) + $decoder = (new GoogleSheetReadOptions()) ->withHeader(false) - ->encoder(); - $encoder->decode([['1']]); + ->decoder(); + $decoder->decode([['1']]); - static::assertSame(['e00'], $encoder->headers()); + static::assertSame(['e00'], $decoder->headers()); } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReaderTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReaderTest.php index 835b6aeff1..5e3857bf5b 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReaderTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReaderTest.php @@ -108,7 +108,7 @@ public function test_sample_forwards_the_render_options(): void static::assertSame($options, $values->getCalls[0][2]); } - public function test_sample_decodes_names_and_rows_through_its_own_encoder(): void + public function test_sample_decodes_names_and_rows_through_its_own_decoder(): void { $sample = GoogleSheetFixtureContext::reader(GoogleSheetFixtureContext::service( 100, diff --git a/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/HttpEncoder.php b/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/HttpDecoder.php similarity index 87% rename from src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/HttpEncoder.php rename to src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/HttpDecoder.php index 2ff523f72a..7c518f1a03 100644 --- a/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/HttpEncoder.php +++ b/src/adapter/etl-adapter-http/src/Flow/ETL/Adapter/Http/HttpDecoder.php @@ -6,9 +6,6 @@ use DOMDocument; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; -use Flow\ETL\Row\TypedRowValues; use Flow\Types\Type\Logical\XML\XMLConverter; use JsonException; use Psr\Http\Message\MessageInterface; @@ -22,17 +19,15 @@ /** * A row carries the body as raw text, so response_body holds one type whatever the content type is. * Pagination, which needs to navigate into a structured body, calls structuredBody() instead. - * - * @implements Encoder */ -final class HttpEncoder implements Encoder +final class HttpDecoder { /** * @param list $batch * * @throws RuntimeException * - * @return list + * @return list> */ public function decode(array $batch): array { @@ -42,7 +37,7 @@ public function decode(array $batch): array $response = $exchange->response; $request = $exchange->request; - $rows[] = new RawRowValues([ + $rows[] = [ 'response_body' => $this->body($response), 'response_headers' => $response->getHeaders(), 'response_status_code' => $response->getStatusCode(), @@ -53,22 +48,12 @@ public function decode(array $batch): array 'request_headers' => $request->getHeaders(), 'request_protocol_version' => $request->getProtocolVersion(), 'request_method' => $request->getMethod(), - ]); + ]; } return $rows; } - /** - * @param list $batch - */ - public function encode(array $batch): array - { - throw new RuntimeException( - 'HTTP adapter is read-only, encoding Rows back to an HTTP exchange is not supported.', - ); - } - /** * @return array */ 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 863b36448a..ae0c9c9021 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 @@ -10,6 +10,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; use Psr\Http\Client\ClientInterface; @@ -48,8 +49,8 @@ public function __construct( */ public function extract(FlowContext $context, ?int $limit = null): Generator { - $encoder = new HttpEncoder(); - $hydrator = $context->hydrator(); + $decoder = new HttpDecoder(); + $backend = $context->backend(); $nextRequest = $this->requestFactory->create(); @@ -64,12 +65,11 @@ public function extract(FlowContext $context, ?int $limit = null): Generator ($this->postRequest)($nextRequest, $response); } - $hydrated = $hydrator->hydrate($encoder->decode([new HttpExchange( - $nextRequest, - $response, - )]), $this->schema()); + $rows = (new RowsBuilder($this->schema(), $backend)) + ->appendRows($decoder->decode([new HttpExchange($nextRequest, $response)])) + ->finish(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; 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 481cc8dac3..8816df8763 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 @@ -11,6 +11,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; use Psr\Http\Client\ClientInterface; @@ -50,8 +51,8 @@ public function __construct( */ public function extract(FlowContext $context, ?int $limit = null): Generator { - $encoder = new HttpEncoder(); - $hydrator = $context->hydrator(); + $decoder = new HttpDecoder(); + $backend = $context->backend(); $request = $this->paginator->initialRequest($this->request); @@ -66,11 +67,11 @@ public function extract(FlowContext $context, ?int $limit = null): Generator ($this->postRequest)($request, $response); } - $raw = $encoder->decode([new HttpExchange($request, $response)]); + $rows = (new RowsBuilder($this->schema(), $backend)) + ->appendRows($decoder->decode([new HttpExchange($request, $response)])) + ->finish(); - $hydrated = $hydrator->hydrate($raw, $this->schema()); - - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; @@ -78,7 +79,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $request = $this->paginator->nextRequest( $this->request, - new DecodedResponse($encoder->structuredBody($response), $response), + new DecodedResponse($decoder->structuredBody($response), $response), ); } } 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 97210c3fc3..acb15cdd02 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 @@ -9,6 +9,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; use Psr\Http\Client\ClientInterface; @@ -50,8 +51,8 @@ public function __construct( */ public function extract(FlowContext $context, ?int $limit = null): Generator { - $encoder = new HttpEncoder(); - $hydrator = $context->hydrator(); + $decoder = new HttpDecoder(); + $backend = $context->backend(); foreach ($this->requests as $request) { if ($this->preRequest) { @@ -64,9 +65,11 @@ public function extract(FlowContext $context, ?int $limit = null): Generator ($this->postRequest)($request, $response); } - $hydrated = $hydrator->hydrate($encoder->decode([new HttpExchange($request, $response)]), $this->schema()); + $rows = (new RowsBuilder($this->schema(), $backend)) + ->appendRows($decoder->decode([new HttpExchange($request, $response)])) + ->finish(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientDynamicExtractorTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientDynamicExtractorTest.php index a727297615..b4eaa8f1a1 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientDynamicExtractorTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientDynamicExtractorTest.php @@ -5,7 +5,10 @@ namespace Flow\ETL\Adapter\HTTP\Tests\Integration; use Flow\ETL\Adapter\Http\DynamicExtractor\NextRequestFactory; +use Flow\ETL\Adapter\HTTP\Tests\Double\NumberedRequestFactory; +use Flow\ETL\Adapter\HTTP\Tests\Mother\PaginationMother; use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Http\Mock\Client; use Nyholm\Psr7\Factory\Psr17Factory; @@ -17,6 +20,7 @@ use function file_get_contents; use function Flow\ETL\Adapter\Http\from_dynamic_http_requests; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\map_schema; @@ -29,6 +33,7 @@ use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; +use function iterator_to_array; use function json_encode; final class PsrHttpClientDynamicExtractorTest extends FlowTestCase @@ -80,7 +85,7 @@ public function create(?ResponseInterface $previousResponse = null): ?RequestInt } // The row carries the body as raw text, so response_body holds one type whatever the - // content type is; pagination reads the structured map through HttpEncoder::structuredBody(). + // content type is; pagination reads the structured map through HttpDecoder::structuredBody(). $body = type_array()->assert(json_decode( type_string()->assert($currentRows->first()->get('response_body')), true, @@ -175,4 +180,21 @@ public function create(?ResponseInterface $previousResponse = null): ?RequestInt ); static::assertSame(['login' => 'flow-php', 'id' => 73_495_297], $rows->first()->get('response_body')); } + + public function test_extract_builds_through_the_config_backend(): void + { + $client = new Client(new Psr17Factory()); + $client->addResponse(PaginationMother::jsonResponse(['id' => 1])); + $backend = new SpyBackend(); + + iterator_to_array( + from_dynamic_http_requests( + $client, + new NumberedRequestFactory('https://api.example.com/items/', 1), + )->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientPaginatedExtractorTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientPaginatedExtractorTest.php index 9eef4358d8..b5d38dc282 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientPaginatedExtractorTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientPaginatedExtractorTest.php @@ -7,6 +7,7 @@ use Flow\ETL\Adapter\HTTP\Tests\Mother\PaginationMother; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaMismatchException; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Http\Mock\Client; use Nyholm\Psr7\Factory\Psr17Factory; @@ -25,6 +26,7 @@ use function Flow\ETL\Adapter\Http\http_request_option_query; use function Flow\ETL\Adapter\Http\http_stop_when_max_pages; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\map_schema; @@ -444,4 +446,22 @@ public function test_stops_on_client_error_but_yields_its_row(): void static::assertCount(2, $rows); static::assertSame(500, $rows[1]->first()->get('response_status_code')); } + + public function test_extract_builds_through_the_config_backend(): void + { + $client = new Client(new Psr17Factory()); + $client->addResponse(PaginationMother::jsonResponse(['meta' => ['next_cursor' => null]])); + $backend = new SpyBackend(); + + iterator_to_array( + from_http_paginated( + $client, + PaginationMother::request(), + http_pagination_cursor('meta.next_cursor', http_request_option_query('cursor')), + )->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientStaticExtractorTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientStaticExtractorTest.php index 55b7226d35..dfb53f99b8 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientStaticExtractorTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientStaticExtractorTest.php @@ -4,8 +4,10 @@ namespace Flow\ETL\Adapter\HTTP\Tests\Integration; +use Flow\ETL\Adapter\HTTP\Tests\Mother\PaginationMother; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Http\Mock\Client; use Nyholm\Psr7\Factory\Psr17Factory; @@ -16,6 +18,7 @@ use function file_get_contents; use function Flow\ETL\Adapter\Http\from_static_http_requests; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\map_schema; @@ -29,6 +32,7 @@ use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; use function is_scalar; +use function iterator_to_array; use function json_decode; use function json_encode; @@ -203,4 +207,20 @@ public function test_schema_typed_response_body(): void ); static::assertSame(['login' => 'norberttech', 'id' => 1], $rows->first()->get('response_body')); } + + public function test_extract_builds_through_the_config_backend(): void + { + $client = new Client(new Psr17Factory()); + $client->addResponse(PaginationMother::jsonResponse(['id' => 1])); + $backend = new SpyBackend(); + + iterator_to_array( + from_static_http_requests($client, [PaginationMother::request()])->extract( + flow_context(config_builder()->backend($backend)->build()), + ), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Unit/HttpEncoderTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Unit/HttpDecoderTest.php similarity index 86% rename from src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Unit/HttpEncoderTest.php rename to src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Unit/HttpDecoderTest.php index 1c2e3cfbf8..1784a9e3bc 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Unit/HttpEncoderTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Unit/HttpDecoderTest.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\HTTP\Tests\Unit; -use Flow\ETL\Adapter\Http\HttpEncoder; +use Flow\ETL\Adapter\Http\HttpDecoder; use Flow\ETL\Adapter\Http\HttpExchange; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\FlowTestCase; @@ -16,7 +16,7 @@ use function json_encode; -final class HttpEncoderTest extends FlowTestCase +final class HttpDecoderTest extends FlowTestCase { public static function structured_bodies(): Generator { @@ -81,7 +81,7 @@ public function test_a_row_carries_the_response_body_as_raw_text( ): void { $exchange = new HttpExchange((new Psr17Factory())->createRequest('GET', 'https://api.example.com'), $response); - static::assertSame($expected, (new HttpEncoder())->decode([$exchange])[0]->values['response_body']); + static::assertSame($expected, (new HttpDecoder())->decode([$exchange])[0]['response_body']); } public function test_decodes_full_row_values(): void @@ -93,7 +93,7 @@ public function test_decodes_full_row_values(): void body: json_encode(['id' => 1], JSON_THROW_ON_ERROR), ); - $values = (new HttpEncoder())->decode([new HttpExchange($request, $response)])[0]->values; + $values = (new HttpDecoder())->decode([new HttpExchange($request, $response)])[0]; static::assertSame('{"id":1}', $values['response_body']); static::assertSame( @@ -108,31 +108,23 @@ public function test_decodes_full_row_values(): void static::assertSame('1.1', $values['request_protocol_version']); } - public function test_encode_is_unsupported(): void - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('read-only'); - - (new HttpEncoder())->encode([]); - } - /** * @param array $expected */ #[DataProvider('structured_bodies')] public function test_pagination_reads_a_structured_body(ResponseInterface $response, array $expected): void { - static::assertSame($expected, (new HttpEncoder())->structuredBody($response)); + static::assertSame($expected, (new HttpDecoder())->structuredBody($response)); } public function test_a_row_carries_an_undecodable_body_as_text(): void { static::assertSame( 'not json {', - (new HttpEncoder())->decode([new HttpExchange( + (new HttpDecoder())->decode([new HttpExchange( (new Psr17Factory())->createRequest('GET', 'https://api.example.com'), new Response(503, ['Content-Type' => 'application/json'], 'not json {'), - )])[0]->values['response_body'], + )])[0]['response_body'], ); } @@ -141,6 +133,6 @@ public function test_invalid_json_body_throws_runtime_exception(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('status 503'); - (new HttpEncoder())->structuredBody(new Response(503, ['Content-Type' => 'application/json'], 'not json {')); + (new HttpDecoder())->structuredBody(new Response(503, ['Content-Type' => 'application/json'], 'not json {')); } } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php index c37e0c2a8d..cd531192da 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php @@ -12,8 +12,7 @@ use DOMDocument; use DOMElement; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; @@ -44,37 +43,34 @@ use function is_int; use function is_string; -/** - * @implements Encoder> - */ -final class JSONEncoder implements Encoder +final class JSONEncoder { public function __construct( private readonly string $dateTimeFormat = DateTimeInterface::ATOM, private readonly string $dateFormat = 'Y-m-d', ) {} - public function decode(array $batch): array + /** + * @return list> + */ + public function encode(Rows $rows): array { - $decoded = []; + $columns = []; + $types = []; - foreach ($batch as $values) { - $decoded[] = new RawRowValues($values); + foreach ($rows->schema()->definitions() as $definition) { + $name = $definition->entry()->name(); + $columns[$name] = $rows->column($name)->values(); + $types[$name] = $definition->type(); } - return $decoded; - } - - public function encode(array $batch): array - { $encoded = []; - foreach ($batch as $rowValues) { + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { $row = []; - /** @var mixed $value */ - foreach ($rowValues->values as $name => $value) { - $row[$name] = $this->renderValue($rowValues->types[$name], $value); + foreach ($columns as $name => $column) { + $row[$name] = $this->renderValue($types[$name], $column[$i]); } $encoded[] = $row; 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 ce7ec0ce4c..6a4748c335 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 @@ -18,7 +18,9 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; +use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -31,6 +33,7 @@ use Flow\Types\Type\Logical\InstanceOfTypeNarrower; use Generator; +use function array_map; use function iterator_to_array; use function sprintf; @@ -92,7 +95,7 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $hydrator = $context->hydrator(); + $backend = $context->backend(); $batchSize = $this->batchSize(); $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); @@ -132,11 +135,17 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $constants = $fileColumns->forFile($source, $schema); foreach ($reader->batches($source, $batchSize) as $rawBatch) { - $hydrated = $constants->fillRows($hydrator->hydrate($rawBatch, $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $rawBatch)) + ->finish(), + $schema, + $backend, + ); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; 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 2d55db2a2f..58f83b7242 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 @@ -18,7 +18,9 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; +use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -31,6 +33,7 @@ use Flow\Types\Type\Logical\InstanceOfTypeNarrower; use Generator; +use function array_map; use function iterator_to_array; use function sprintf; @@ -92,7 +95,7 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $hydrator = $context->hydrator(); + $backend = $context->backend(); $batchSize = $this->batchSize(); $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); @@ -132,11 +135,17 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $constants = $fileColumns->forFile($source, $schema); foreach ($reader->batches($source, $batchSize) as $rawBatch) { - $hydrated = $constants->fillRows($hydrator->hydrate($rawBatch, $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $rawBatch)) + ->finish(), + $schema, + $backend, + ); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php index b8a0ff8bfe..f3ebbe1c6c 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php @@ -99,7 +99,7 @@ public function load(Rows $rows, FlowContext $context): void try { foreach ($this->router->route($rows) as [$partitions, $group]) { - $this->write($group, $partitions->toArray(), $context); + $this->write($group, $partitions->toArray()); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); @@ -141,13 +141,13 @@ public function withFlags(int $flags): self /** * @param array $partitions */ - public function write(Rows $nextRows, array $partitions, FlowContext $context): void + public function write(Rows $nextRows, array $partitions): void { $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( $partitions, ); - foreach ($this->encoder()->encode($context->hydrator()->dehydrate($nextRows)) as $normalizedRow) { + foreach ($this->encoder()->encode($nextRows) as $normalizedRow) { try { $json = json_encode($normalizedRow, $this->flags); diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php index ee4f1a5b58..a8efed803b 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php @@ -101,7 +101,7 @@ public function load(Rows $rows, FlowContext $context): void try { foreach ($this->router->route($rows) as [$partitions, $group]) { - $this->write($group, $partitions->toArray(), $context); + $this->write($group, $partitions->toArray()); } $context->telemetry()->loadingCompleted($this, [ @@ -152,15 +152,12 @@ public function withRowsInNewLines(bool $putRowsInNewLines): self /** * @param array $partitions */ - public function write(Rows $nextRows, array $partitions, FlowContext $context): void + public function write(Rows $nextRows, array $partitions): void { ($this->documents ??= new JsonDocuments( new FilesSink($this->filesystem, $this->path, $this->saveMode), $this->putRowsInNewLines, - ))->append( - $this->encodeJSON($this->encoder()->encode($context->hydrator()->dehydrate($nextRows))), - $partitions, - ); + ))->append($this->encodeJSON($this->encoder()->encode($nextRows)), $partitions); } /** 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 fe1ed868bf..a97f73a997 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 @@ -16,6 +16,7 @@ use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Generator; @@ -26,6 +27,7 @@ use function array_sum; use function Flow\ETL\Adapter\JSON\from_json; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; @@ -687,4 +689,18 @@ public function test_the_listing_is_read_once(): void static::assertSame(1, $filesystem->listCalls); } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + iterator_to_array( + from_json(__DIR__ . '/../../Fixtures/timezones.json')->extract( + flow_context(config_builder()->backend($backend)->build()), + ), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonHydratorParityTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTypedColumnsTest.php similarity index 97% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonHydratorParityTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTypedColumnsTest.php index 9f9610b69c..fe5041f278 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonHydratorParityTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTypedColumnsTest.php @@ -16,7 +16,7 @@ use function Flow\Filesystem\DSL\path_real; use function usort; -final class JsonHydratorParityTest extends FlowTestCase +final class JsonExtractorTypedColumnsTest extends FlowTestCase { public function test_fast_path_hydrates_typed_columns_with_missing_column_null_and_input_uri(): void { 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 dc9a26c557..02fd3fec38 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 @@ -16,6 +16,7 @@ use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Generator; @@ -27,6 +28,7 @@ use function array_sum; use function Flow\ETL\Adapter\JSON\from_json_lines; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; @@ -739,4 +741,18 @@ public function test_the_listing_is_read_once(): void static::assertSame(1, $filesystem->listCalls); } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + iterator_to_array( + from_json_lines(__DIR__ . '/../../Fixtures/timezones.jsonl')->extract( + flow_context(config_builder()->backend($backend)->build()), + ), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesHydratorParityTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTypedColumnsTest.php similarity index 94% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesHydratorParityTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTypedColumnsTest.php index a3711c8435..b26e96e826 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesHydratorParityTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTypedColumnsTest.php @@ -15,7 +15,7 @@ use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\path_real; -final class JsonLinesHydratorParityTest extends FlowTestCase +final class JsonLinesExtractorTypedColumnsTest extends FlowTestCase { public function test_hydrates_typed_columns_with_missing_column_null(): void { diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JSONEncoderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JSONEncoderTest.php index 6dd721bffa..d9798c6a59 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JSONEncoderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JSONEncoderTest.php @@ -8,16 +8,27 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Adapter\JSON\JSONEncoder; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Value\Json; use Flow\Types\Value\Uuid; -use stdClass; -use function Flow\Types\DSL\type_array; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\ETL\DSL\time_zone_schema; +use function Flow\ETL\DSL\uuid_schema; use function Flow\Types\DSL\type_boolean; -use function Flow\Types\DSL\type_date; use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_enum; use function Flow\Types\DSL\type_float; @@ -28,26 +39,18 @@ use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; use function Flow\Types\DSL\type_time; -use function Flow\Types\DSL\type_time_zone; use function Flow\Types\DSL\type_uuid; final class JSONEncoderTest extends FlowTestCase { - public function test_decode_passes_parsed_maps_through_unchanged(): void - { - static::assertSame( - ['id' => 1, 'name' => 'Alice'], - (new JSONEncoder())->decode([['id' => 1, 'name' => 'Alice']])[0]->values, - ); - } - public function test_encode_keeps_json_values_as_nested_structures(): void { static::assertSame( [['data' => ['a' => 1, 'b' => 2]]], - (new JSONEncoder())->encode([ - new TypedRowValues(['data' => Json::fromArray(['a' => 1, 'b' => 2])], ['data' => type_json()]), - ]), + (new JSONEncoder())->encode(array_to_rows([['data' => Json::fromArray([ + 'a' => 1, + 'b' => 2, + ])]], schema(json_schema('data')))), ); } @@ -55,21 +58,16 @@ public function test_encode_passes_scalars_through(): void { static::assertSame( [['id' => 1, 'name' => 'Alice', 'active' => true, 'score' => 9.5, 'missing' => null]], - (new JSONEncoder())->encode([ - new TypedRowValues([ - 'id' => 1, - 'name' => 'Alice', - 'active' => true, - 'score' => 9.5, - 'missing' => null, - ], [ - 'id' => type_integer(), - 'name' => type_string(), - 'active' => type_boolean(), - 'score' => type_float(), - 'missing' => type_string(), - ]), - ]), + (new JSONEncoder())->encode(array_to_rows( + [['id' => 1, 'name' => 'Alice', 'active' => true, 'score' => 9.5, 'missing' => null]], + schema( + int_schema('id'), + str_schema('name'), + bool_schema('active'), + float_schema('score'), + str_schema('missing', nullable: true), + ), + )), ); } @@ -77,9 +75,9 @@ public function test_encode_renders_date_with_the_date_format(): void { static::assertSame( [['at' => '2023-10-01']], - (new JSONEncoder())->encode([ - new TypedRowValues(['at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC')], ['at' => type_date()]), - ]), + (new JSONEncoder())->encode(array_to_rows([[ + 'at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC'), + ]], schema(date_schema('at')))), ); } @@ -87,21 +85,21 @@ public function test_encode_renders_datetime_with_the_datetime_format(): void { static::assertSame( [['at' => '2023-10-01T12:02:01+00:00']], - (new JSONEncoder())->encode([ - new TypedRowValues(['at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC')], [ - 'at' => type_datetime(), - ]), - ]), + (new JSONEncoder())->encode(array_to_rows([[ + 'at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC'), + ]], schema(datetime_schema('at')))), ); } - public function test_encode_renders_array_values_as_nested_arrays(): void + public function test_encode_renders_list_values_as_nested_arrays(): void { static::assertSame( [['tags' => [1, 2, 3]]], - (new JSONEncoder())->encode([ - new TypedRowValues(['tags' => [1, 2, 3]], ['tags' => type_array()]), - ]), + (new JSONEncoder())->encode(array_to_rows([['tags' => [ + 1, + 2, + 3, + ]]], schema(list_schema('tags', type_list(type_integer()))))), ); } @@ -109,11 +107,9 @@ public function test_encode_renders_list_of_structures_as_nested_arrays(): void { static::assertSame( [['tags' => [['t' => 'a'], ['t' => 'b']]]], - (new JSONEncoder())->encode([ - new TypedRowValues(['tags' => [['t' => 'a'], ['t' => 'b']]], ['tags' => type_list(type_structure([ - 't' => type_string(), - ]))]), - ]), + (new JSONEncoder())->encode(array_to_rows([[ + 'tags' => [['t' => 'a'], ['t' => 'b']], + ]], schema(list_schema('tags', type_list(type_structure(['t' => type_string()])))))), ); } @@ -121,12 +117,10 @@ public function test_encode_renders_map_values_as_nested_arrays(): void { static::assertSame( [['translations' => ['en' => 'red', 'pl' => 'czerwony']]], - (new JSONEncoder())->encode([ - new TypedRowValues(['translations' => ['en' => 'red', 'pl' => 'czerwony']], ['translations' => type_map( - type_string(), - type_string(), - )]), - ]), + (new JSONEncoder())->encode(array_to_rows([['translations' => [ + 'en' => 'red', + 'pl' => 'czerwony', + ]]], schema(map_schema('translations', type_map(type_string(), type_string()))))), ); } @@ -141,19 +135,19 @@ public function test_encode_renders_nested_datetime_uuid_json_and_enum_leaves(): 'level' => 'one', ], ]], - (new JSONEncoder())->encode([ - new TypedRowValues(['event' => [ + (new JSONEncoder())->encode(array_to_rows([[ + 'event' => [ 'at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC'), 'id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), 'payload' => Json::fromArray(['a' => 1]), 'level' => BackedStringEnum::one, - ]], ['event' => type_structure([ - 'at' => type_datetime(), - 'id' => type_uuid(), - 'payload' => type_json(), - 'level' => type_enum(BackedStringEnum::class), - ])]), - ]), + ], + ]], schema(structure_schema('event', type_structure([ + 'at' => type_datetime(), + 'id' => type_uuid(), + 'payload' => type_json(), + 'level' => type_enum(BackedStringEnum::class), + ]))))), ); } @@ -161,39 +155,15 @@ public function test_encode_renders_nested_interval_float_and_bool_leaves(): voi { static::assertSame( [['event' => ['took' => 3600000000, 'score' => 9.5, 'active' => true]]], - (new JSONEncoder())->encode([ - new TypedRowValues(['event' => [ - 'took' => new DateInterval('PT1H'), - 'score' => 9.5, - 'active' => true, - ]], ['event' => type_structure([ - 'took' => type_time(), - 'score' => type_float(), - 'active' => type_boolean(), - ])]), - ]), - ); - } - - public function test_encode_renders_non_array_container_values_as_null(): void - { - static::assertSame( - [['x' => null]], - (new JSONEncoder())->encode([ - new TypedRowValues(['x' => new stdClass()], ['x' => type_list(type_string())]), - ]), - ); - } - - public function test_encode_renders_unrenderable_nested_values_as_null(): void - { - static::assertSame( - [['event' => ['stream' => null]]], - (new JSONEncoder())->encode([ - new TypedRowValues(['event' => ['stream' => new stdClass()]], ['event' => type_structure([ - 'stream' => type_string(), - ])]), - ]), + (new JSONEncoder())->encode(array_to_rows([['event' => [ + 'took' => new DateInterval('PT1H'), + 'score' => 9.5, + 'active' => true, + ]]], schema(structure_schema('event', type_structure([ + 'took' => type_time(), + 'score' => type_float(), + 'active' => type_boolean(), + ]))))), ); } @@ -201,9 +171,9 @@ public function test_encode_renders_time_as_microseconds(): void { static::assertSame( [['duration' => 3600000000]], - (new JSONEncoder())->encode([ - new TypedRowValues(['duration' => new DateInterval('PT1H')], ['duration' => type_time()]), - ]), + (new JSONEncoder())->encode(array_to_rows([[ + 'duration' => new DateInterval('PT1H'), + ]], schema(time_schema('duration')))), ); } @@ -211,9 +181,9 @@ public function test_encode_renders_a_timezone_as_its_iana_name(): void { static::assertSame( [['tz' => 'Europe/Warsaw']], - (new JSONEncoder())->encode([ - new TypedRowValues(['tz' => new DateTimeZone('Europe/Warsaw')], ['tz' => type_time_zone()]), - ]), + (new JSONEncoder())->encode(array_to_rows([[ + 'tz' => new DateTimeZone('Europe/Warsaw'), + ]], schema(time_zone_schema('tz')))), ); } @@ -221,9 +191,9 @@ public function test_encode_renders_uuid_as_string(): void { static::assertSame( [['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']], - (new JSONEncoder())->encode([ - new TypedRowValues(['id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')], ['id' => type_uuid()]), - ]), + (new JSONEncoder())->encode(array_to_rows([[ + 'id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), + ]], schema(uuid_schema('id')))), ); } } diff --git a/src/adapter/etl-adapter-logger/src/Flow/ETL/Adapter/Logger/PsrLoggerLoader.php b/src/adapter/etl-adapter-logger/src/Flow/ETL/Adapter/Logger/PsrLoggerLoader.php index f3212e705f..eae90ad3df 100644 --- a/src/adapter/etl-adapter-logger/src/Flow/ETL/Adapter/Logger/PsrLoggerLoader.php +++ b/src/adapter/etl-adapter-logger/src/Flow/ETL/Adapter/Logger/PsrLoggerLoader.php @@ -29,8 +29,8 @@ public function load(Rows $rows, FlowContext $context): void $context->telemetry()->loadingStarted($this); try { - foreach ($rows->all() as $row) { - $this->logger->log($this->logLevel, $this->message, $row->toArray()); + foreach ($rows->toArray() as $values) { + $this->logger->log($this->logLevel, $this->message, $values); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); diff --git a/src/adapter/etl-adapter-logger/tests/Flow/ETL/Adapter/Logger/Tests/Unit/PsrLoggerLoaderTest.php b/src/adapter/etl-adapter-logger/tests/Flow/ETL/Adapter/Logger/Tests/Unit/PsrLoggerLoaderTest.php index add7d3e199..868635bb0d 100644 --- a/src/adapter/etl-adapter-logger/tests/Flow/ETL/Adapter/Logger/Tests/Unit/PsrLoggerLoaderTest.php +++ b/src/adapter/etl-adapter-logger/tests/Flow/ETL/Adapter/Logger/Tests/Unit/PsrLoggerLoaderTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Adapter\Logger\PsrLoggerLoader; use Flow\ETL\Tests\FlowTestCase; +use Flow\Types\Value\Json; use Psr\Log\LogLevel; use Psr\Log\Test\TestLogger; @@ -13,6 +14,7 @@ use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\string_schema; @@ -32,4 +34,15 @@ public function test_psr_logger_loader(): void static::assertTrue($logger->hasErrorRecords()); static::assertTrue($logger->hasError('row log')); } + + public function test_a_json_column_is_logged_as_an_array(): void + { + $logger = new TestLogger(); + + (new PsrLoggerLoader($logger, 'row log'))->load(array_to_rows([['payload' => Json::fromArray([ + 'a' => 1, + ])]], schema(json_schema('payload'))), flow_context(config())); + + static::assertSame(['payload' => ['a' => 1]], $logger->records[0]['context']); + } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetEncoder.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetEncoder.php index 5758c90db3..f5956dd057 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetEncoder.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetEncoder.php @@ -6,23 +6,14 @@ use Flow\ETL\Adapter\Parquet\ValueConverter\ValueConverter; use Flow\ETL\Adapter\Parquet\ValueConverter\ValueConverters; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; use Flow\Parquet\ParquetFile\Schema as ParquetSchema; use Flow\Types\Type; use function array_key_exists; -/** - * @implements Encoder> - */ -final class ParquetEncoder implements Encoder +final class ParquetEncoder { - /** - * @var array - */ - private array $decodePlan; - /** * @var array, ?ValueConverter}> */ @@ -31,46 +22,34 @@ final class ParquetEncoder implements Encoder public function __construct(ParquetSchema $schema) { $converter = new SchemaConverter(); - $decodePlan = []; $encodePlan = []; foreach ($schema->columns() as $column) { - $valueConverter = ValueConverters::for($column); - - $encodePlan[$column->name()] = [$converter->parquetToFlowType($column), $valueConverter]; - - if ($valueConverter !== null) { - $decodePlan[$column->name()] = $valueConverter; - } + $encodePlan[$column->name()] = [$converter->parquetToFlowType($column), ValueConverters::for($column)]; } - $this->decodePlan = $decodePlan; $this->encodePlan = $encodePlan; } - public function decode(array $batch): array + /** + * @return list> + */ + public function encode(Rows $rows): array { - $decoded = []; + $columns = []; - foreach ($batch as $values) { - foreach ($this->decodePlan as $name => $valueConverter) { - if (array_key_exists($name, $values) && $values[$name] !== null) { - $values[$name] = $valueConverter->decode($values[$name]); - } - } - - $decoded[] = new RawRowValues($values); + foreach ($rows->schema()->definitions() as $definition) { + $columns[$definition->entry()->name()] = $rows->column($definition->entry()->name())->values(); } - return $decoded; - } - - public function encode(array $batch): array - { $encoded = []; - foreach ($batch as $rowValues) { - $values = $rowValues->values; + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $values = []; + + foreach ($columns as $name => $column) { + $values[$name] = $column[$i]; + } foreach ($this->encodePlan as $name => [$type, $valueConverter]) { if (array_key_exists($name, $values) && $values[$name] !== null) { 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 fddc59157e..e2eec51e67 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 @@ -17,6 +17,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Validator\StrictValidator; use Flow\Filesystem\Filesystem; @@ -31,7 +32,6 @@ use Generator; use function array_values; -use function count; use function iterator_count; use function max; use function sprintf; @@ -43,8 +43,6 @@ final class ParquetExtractor implements MetadataColumnsExtractor, RewindableExtractor { - private ?Schema $schema = null; - use Batches; use FileReading; @@ -101,15 +99,14 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $hydrator = $context->hydrator(); + $backend = $context->backend(); $batchSize = $this->batchSize(); $yielded = 0; $fileOffset = $this->offset ?? 0; - $promisedSchema = $this->schema === null ? null : $this->schema(); - // undeclared, every file is read under the first file's schema, or the union of all of them - $expected = $this->schema === null ? $this->derivedSchema($this->files(), $this->unionByName) : null; - $target = $promisedSchema ?? $this->schema(); + // every file is read under the first file's schema, or the union of all of them + $expected = $this->derivedSchema($this->files(), $this->unionByName); + $target = $this->schema(); $fileColumns = $this->fileColumns($this->filesystem, $this->path); @@ -125,7 +122,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi continue; } - if ($expected !== null && !$this->unionByName) { + if (!$this->unionByName) { $validation = (new StrictValidator())->validate($expected, $file->schema()); if (!$validation->isValid()) { @@ -137,63 +134,35 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } } + $body = $fileColumns->withoutTail($file->schema()); // R6: over the FILE's schema, never over schema()'s output - $fileSchema = $fileColumns->declare($this->schema ?? $file->schema()); - $constants = $fileColumns->forFile($file->source(), $fileSchema); - $rowsSchema = $promisedSchema ?? $fileSchema; - $body = $fileColumns->withoutTail($rowsSchema); - $matchTo = $promisedSchema === null && !$fileSchema->isSame($target) ? $target : null; - - $encoder = new ParquetEncoder($file->file->schema()); - - $rawBatch = []; + $rowsSchema = $fileColumns->declare($file->schema()); + $constants = $fileColumns->forFile($file->source(), $rowsSchema); + $matchTo = !$rowsSchema->isSame($target) ? $target : null; - foreach ($file->file->values( + foreach ($file->file->columns( + $batchSize, $this->columns, $limit === null ? null : $limit - $yielded, $fileOffset, - ) as $row) { - $rawBatch[] = $row; - - if (count($rawBatch) >= $batchSize) { - $hydrated = $constants->fillRows( - $hydrator->hydrate($encoder->decode($rawBatch), $body), - $rowsSchema, - ); - - if ($matchTo !== null) { - $hydrated = $hydrated->matchTo($matchTo); - } - - $yielded += $hydrated->count(); - - $signal = yield $hydrated; - - if ($signal === Signal::STOP) { - return; - } + ) as $chunk) { + $builder = new RowsBuilder($body, $backend); - if ($limit !== null && $yielded >= $limit) { - return; - } - - $rawBatch = []; + foreach ($body->definitions() as $definition) { + $builder + ->column($definition->entry()->name()) + ->appendMany($chunk[$definition->entry()->name()]); } - } - if ($rawBatch !== []) { - $hydrated = $constants->fillRows( - $hydrator->hydrate($encoder->decode($rawBatch), $body), - $rowsSchema, - ); + $rows = $constants->fillRows($builder->finish(), $rowsSchema, $backend); if ($matchTo !== null) { - $hydrated = $hydrated->matchTo($matchTo); + $rows = $rows->matchTo($matchTo); } - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; @@ -213,9 +182,10 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi public function schema(): Schema { - return $this->fileColumns($this->filesystem, $this->path)->declare( - $this->schema ?? $this->derivedSchema($this->files(), $this->unionByName), - ); + return $this->fileColumns($this->filesystem, $this->path)->declare($this->derivedSchema( + $this->files(), + $this->unionByName, + )); } public function statistics(): Statistics @@ -237,7 +207,7 @@ public function unionByName(bool $union = true): self public function partitionSchema(): Schema { - return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + return $this->fileColumns($this->filesystem, $this->path)->partitions(new Schema()); } public function source(): Path @@ -302,11 +272,10 @@ public function withOptions(Options $options): self */ private function declare(): Statistics { - $footers = $this->schema === null - ? $this->derivedFooters($this->files(), $this->unionByName) - : $this->footers($this->files(), $this->unionByName); - - return $footers->of(iterator_count($this->sourceFiles($this->filesystem, $this->path)), $this->offset ?? 0); + return $this->derivedFooters($this->files(), $this->unionByName)->of( + iterator_count($this->sourceFiles($this->filesystem, $this->path)), + $this->offset ?? 0, + ); } /** @@ -331,8 +300,8 @@ private function files(Filter $pathFilter = new OnlyFiles()): Generator public function withSchema(Schema $schema): static { - $this->schema = $schema; - - return $this; + throw new InvalidArgumentException( + 'Parquet is a self-describing format and does not accept a schema; declaring one is not supported yet.', + ); } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php index dcc56906b1..905f75614c 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php @@ -132,9 +132,7 @@ public function load(Rows $rows, FlowContext $context): void ); ($this->writers[$stream->path()->uri()] ??= - $this->openWriter($stream))->writeBatch($this->encoder()->encode( - $context->hydrator()->dehydrate($group), - )); + $this->openWriter($stream))->writeBatch($this->encoder()->encode($group)); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/ElementsValueConverter.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/ElementsValueConverter.php index 09eb8790b6..bdbf7f9ae2 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/ElementsValueConverter.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/ElementsValueConverter.php @@ -12,22 +12,6 @@ public function __construct( private ValueConverter $element, ) {} - public function decode(mixed $value): mixed - { - if (!is_array($value)) { - return $value; - } - - // @mago-ignore analysis:mixed-assignment - foreach ($value as $key => $element) { - if ($element !== null) { - $value[$key] = $this->element->decode($element); - } - } - - return $value; - } - public function encode(mixed $value): mixed { if (!is_array($value)) { diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/JsonValueConverter.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/JsonValueConverter.php index cefa9d9e72..a075795f21 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/JsonValueConverter.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/JsonValueConverter.php @@ -4,17 +4,11 @@ namespace Flow\ETL\Adapter\Parquet\ValueConverter; -use function Flow\Types\DSL\type_json; use function Flow\Types\DSL\type_string; use function is_object; final readonly class JsonValueConverter implements ValueConverter { - public function decode(mixed $value): mixed - { - return $value === null ? null : type_json()->cast($value); - } - public function encode(mixed $value): mixed { return is_object($value) ? type_string()->cast($value) : $value; diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/StructValueConverter.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/StructValueConverter.php index e2501ac84e..c224273302 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/StructValueConverter.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/StructValueConverter.php @@ -16,21 +16,6 @@ public function __construct( private array $children, ) {} - public function decode(mixed $value): mixed - { - if (!is_array($value)) { - return $value; - } - - foreach ($this->children as $name => $converter) { - if (array_key_exists($name, $value) && $value[$name] !== null) { - $value[$name] = $converter->decode($value[$name]); - } - } - - return $value; - } - public function encode(mixed $value): mixed { if (!is_array($value)) { diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/UuidValueConverter.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/UuidValueConverter.php index 2a422c220e..97fb3543ff 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/UuidValueConverter.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/UuidValueConverter.php @@ -5,16 +5,10 @@ namespace Flow\ETL\Adapter\Parquet\ValueConverter; use function Flow\Types\DSL\type_string; -use function Flow\Types\DSL\type_uuid; use function is_object; final readonly class UuidValueConverter implements ValueConverter { - public function decode(mixed $value): mixed - { - return $value === null ? null : type_uuid()->cast($value); - } - public function encode(mixed $value): mixed { return is_object($value) ? type_string()->cast($value) : $value; diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/ValueConverter.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/ValueConverter.php index be102ce115..fa6792aa1e 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/ValueConverter.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ValueConverter/ValueConverter.php @@ -6,7 +6,5 @@ interface ValueConverter { - public function decode(mixed $value): mixed; - public function encode(mixed $value): mixed; } 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 a17343d8c6..5f86c0ffc9 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 @@ -19,6 +19,8 @@ use Flow\Parquet\Engine\PhpParquetEngine; use Flow\Parquet\Options; use Flow\Parquet\Reader; +use Flow\Types\Value\Json; +use Flow\Types\Value\Uuid; use function array_keys; use function Flow\ETL\Adapter\Parquet\from_parquet; @@ -28,15 +30,25 @@ 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_rows; use function Flow\ETL\DSL\from_sequence_number; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\partition_types; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; use function Flow\Filesystem\DSL\path_real; use function Flow\Types\DSL\type_datetime; +use function Flow\Types\DSL\type_json; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; +use function Flow\Types\DSL\type_uuid; use function iterator_to_array; final class ParquetExtractorTest extends FlowTestCase @@ -88,17 +100,53 @@ public function test_calling_schema_does_not_change_extraction(): void public function test_extract_yields_the_metadata_column_schema_promises(): void { - $extractor = from_parquet(path(__DIR__ . '/Fixtures/orders_1k.parquet'), columns: ['email']) - ->withMetadataColumns(true) - ->withSchema(schema(str_schema('email'))); + $extractor = from_parquet( + path(__DIR__ . '/Fixtures/orders_1k.parquet'), + columns: ['email'], + )->withMetadataColumns(true); foreach ($extractor->extract(flow_context(config())) as $batch) { - static::assertSame($extractor->schema()->references()->names(), $batch->first()->names()); + static::assertSame($extractor->schema()->references()->names(), $batch->schema()->references()->names()); break; } } + public function test_nested_uuid_and_json_read_as_value_objects(): void + { + $memory = memory_filesystem(); + $uuid = '5f0e3a0e-0b8a-4b7a-9d6e-1f2a3b4c5d6e'; + + df() + ->read(from_rows(array_to_rows( + [['lu' => [$uuid], 's' => ['j' => ['b' => 2], 'u' => $uuid], 'm' => ['k' => $uuid]]], + schema( + list_schema('lu', type_list(type_uuid())), + structure_schema('s', type_structure(['j' => type_json(), 'u' => type_uuid()])), + map_schema('m', type_map(type_string(), type_uuid())), + ), + ))) + ->write(to_parquet(path('memory://nested.parquet'), filesystem: $memory)) + ->run(); + + $rows = df()->read(from_parquet(path('memory://nested.parquet'), filesystem: $memory))->fetch(); + + // @mago-ignore analysis:mixed-assignment + $list = $rows->column('lu')->value(0); + // @mago-ignore analysis:mixed-assignment + $structure = $rows->column('s')->value(0); + // @mago-ignore analysis:mixed-assignment + $map = $rows->column('m')->value(0); + + static::assertIsArray($list); + static::assertInstanceOf(Uuid::class, $list[0]); + static::assertIsArray($structure); + static::assertInstanceOf(Json::class, $structure['j']); + static::assertInstanceOf(Uuid::class, $structure['u']); + static::assertIsArray($map); + static::assertInstanceOf(Uuid::class, $map['k']); + } + public function test_schema_appends_the_metadata_column(): void { static::assertSame( diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetHydratorParityTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetHydratorParityTest.php deleted file mode 100644 index aacb11ffcf..0000000000 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetHydratorParityTest.php +++ /dev/null @@ -1,66 +0,0 @@ -path)) { - unlink($this->path); - } - } - - public function test_trusted_read_is_identical_to_a_casting_read(): void - { - data_frame(config()) - ->read(new FakeExtractor(50)) - ->drop('null', 'enum') - ->write(to_parquet(path($this->path))->saveMode(overwrite())) - ->run(); - - $file = (new Reader())->read($this->path); - $flowSchema = (new SchemaConverter())->toFlow($file->schema()); - $rawRows = iterator_to_array($file->values(), false); - - $encoder = new ParquetEncoder($file->schema()); - $decodedRows = $encoder->decode($rawRows); - - $trusted = (new PhpRowHydrator())->hydrate($decodedRows, $flowSchema); - $cast = (new PhpRowHydrator())->hydrate( - array_map(static fn(array $values): RawRowValues => new RawRowValues($values), $rawRows), - $flowSchema, - ); - - static::assertSame(serialize($cast), serialize($trusted)); - } -} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetEncoderTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetEncoderTest.php index b643b39875..1d869da1aa 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetEncoderTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetEncoderTest.php @@ -6,7 +6,6 @@ use DateTimeImmutable; use Flow\ETL\Adapter\Parquet\ParquetEncoder; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\FlowTestCase; use Flow\Parquet\ParquetFile\Schema as ParquetSchema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; @@ -17,7 +16,15 @@ use Flow\Types\Value\Json; use Flow\Types\Value\Uuid; -use function Flow\Types\DSL\type_datetime; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\ETL\DSL\uuid_schema; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_json; use function Flow\Types\DSL\type_list; @@ -28,48 +35,6 @@ final class ParquetEncoderTest extends FlowTestCase { - public function test_decode_leaves_null_logical_values_untouched(): void - { - static::assertSame( - ['id' => null, 'payload' => null], - (new ParquetEncoder(ParquetSchema::with(FlatColumn::uuid('id'), FlatColumn::json('payload'))))->decode([[ - 'id' => null, - 'payload' => null, - ]])[0]->values, - ); - } - - public function test_decode_normalizes_json_columns_to_flow_native(): void - { - $decoded = (new ParquetEncoder(ParquetSchema::with(FlatColumn::json('payload'))))->decode([[ - 'payload' => '{"id":1,"status":"NEW"}', - ]]); - - static::assertInstanceOf(Json::class, $decoded[0]->values['payload']); - static::assertSame(['id' => 1, 'status' => 'NEW'], $decoded[0]->values['payload']->toArray()); - } - - public function test_decode_normalizes_uuid_columns_to_flow_native(): void - { - $decoded = (new ParquetEncoder(ParquetSchema::with(FlatColumn::uuid('id'))))->decode([[ - 'id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479', - ]]); - - static::assertInstanceOf(Uuid::class, $decoded[0]->values['id']); - static::assertSame('f47ac10b-58cc-4372-a567-0e02b2c3d479', $decoded[0]->values['id']->toString()); - } - - public function test_decode_passes_scalar_value_maps_through_unchanged(): void - { - static::assertSame( - ['id' => 1, 'name' => 'Alice'], - (new ParquetEncoder(ParquetSchema::with(FlatColumn::int64('id'), FlatColumn::string('name'))))->decode([[ - 'id' => 1, - 'name' => 'Alice', - ]])[0]->values, - ); - } - public function test_encode_coerces_values_to_the_column_type(): void { static::assertSame( @@ -77,10 +42,7 @@ public function test_encode_coerces_values_to_the_column_type(): void (new ParquetEncoder(ParquetSchema::with( FlatColumn::string('id'), FlatColumn::string('name'), - )))->encode([new TypedRowValues(['id' => 1, 'name' => 'test'], [ - 'id' => type_integer(), - 'name' => type_string(), - ])]), + )))->encode(array_to_rows([['id' => 1, 'name' => 'test']], schema(int_schema('id'), str_schema('name')))), ); } @@ -88,15 +50,12 @@ public function test_encode_keeps_datetime_and_scalar_values(): void { $at = new DateTimeImmutable('2024-01-01 12:00:00 UTC'); - static::assertSame( + static::assertEquals( [['id' => 1, 'at' => $at]], (new ParquetEncoder(ParquetSchema::with( FlatColumn::int64('id'), FlatColumn::datetime('at'), - )))->encode([new TypedRowValues(['id' => 1, 'at' => $at], [ - 'id' => type_integer(), - 'at' => type_datetime(), - ])]), + )))->encode(array_to_rows([['id' => 1, 'at' => $at]], schema(int_schema('id'), datetime_schema('at')))), ); } @@ -107,10 +66,10 @@ public function test_encode_leaves_null_values_untouched(): void (new ParquetEncoder(ParquetSchema::with( FlatColumn::int64('id'), FlatColumn::string('name'), - )))->encode([new TypedRowValues(['id' => null, 'name' => null], [ - 'id' => type_integer(), - 'name' => type_string(), - ])]), + )))->encode(array_to_rows( + [['id' => null, 'name' => null]], + schema(int_schema('id', nullable: true), str_schema('name', nullable: true)), + )), ); } @@ -118,88 +77,12 @@ public function test_encode_renders_uuid_values_back_to_strings(): void { static::assertSame( [['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']], - (new ParquetEncoder(ParquetSchema::with(FlatColumn::uuid('id'))))->encode([new TypedRowValues([ + (new ParquetEncoder(ParquetSchema::with(FlatColumn::uuid('id'))))->encode(array_to_rows([[ 'id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), - ], ['id' => type_uuid()])]), + ]], schema(uuid_schema('id')))), ); } - public function test_decode_normalizes_json_and_uuid_nested_in_struct(): void - { - $decoded = (new ParquetEncoder(ParquetSchema::with(NestedColumn::struct('body', [ - FlatColumn::json('data'), - FlatColumn::uuid('id'), - FlatColumn::int64('n'), - ]))))->decode([[ - 'body' => ['data' => '{"a":1}', 'id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479', 'n' => 1], - ]]); - - // @mago-ignore analysis:mixed-assignment - $body = $decoded[0]->values['body']; - - static::assertIsArray($body); - static::assertInstanceOf(Json::class, $body['data']); - static::assertInstanceOf(Uuid::class, $body['id']); - static::assertSame(1, $body['n']); - } - - public function test_decode_normalizes_json_in_deep_struct(): void - { - $decoded = (new ParquetEncoder(ParquetSchema::with(NestedColumn::struct('outer', [NestedColumn::struct('inner', [FlatColumn::json( - 'deep', - )])]))))->decode([['outer' => ['inner' => ['deep' => '{"e":5}']]]]); - - // @mago-ignore analysis:mixed-assignment - $outer = $decoded[0]->values['outer']; - - static::assertIsArray($outer); - // @mago-ignore analysis:mixed-assignment - $inner = $outer['inner']; - static::assertIsArray($inner); - static::assertInstanceOf(Json::class, $inner['deep']); - } - - public function test_decode_normalizes_json_list_elements(): void - { - $decoded = (new ParquetEncoder(ParquetSchema::with(NestedColumn::list( - 'items', - ListElement::json(), - ))))->decode([['items' => ['{"c":3}', '{"d":4}']]]); - - // @mago-ignore analysis:mixed-assignment - $items = $decoded[0]->values['items']; - - static::assertIsArray($items); - static::assertContainsOnlyInstancesOf(Json::class, $items); - } - - public function test_decode_normalizes_nested_null_leaves_untouched(): void - { - static::assertSame( - ['body' => ['data' => null, 'n' => 1]], - (new ParquetEncoder(ParquetSchema::with(NestedColumn::struct('body', [ - FlatColumn::json('data'), - FlatColumn::int64('n'), - ]))))->decode([['body' => ['data' => null, 'n' => 1]]])[0]->values, - ); - } - - public function test_decode_normalizes_uuid_map_values_keeping_keys(): void - { - $decoded = (new ParquetEncoder(ParquetSchema::with(NestedColumn::map( - 'ids', - MapKey::string(), - MapValue::uuid(), - ))))->decode([['ids' => ['a' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']]]); - - // @mago-ignore analysis:mixed-assignment - $ids = $decoded[0]->values['ids']; - - static::assertIsArray($ids); - static::assertSame(['a'], array_keys($ids)); - static::assertInstanceOf(Uuid::class, $ids['a']); - } - public function test_encode_stringifies_json_and_uuid_nested_in_struct(): void { static::assertSame( @@ -208,17 +91,17 @@ public function test_encode_stringifies_json_and_uuid_nested_in_struct(): void FlatColumn::json('data'), FlatColumn::uuid('id'), FlatColumn::int64('n'), - ]))))->encode([new TypedRowValues([ + ]))))->encode(array_to_rows([[ 'body' => [ 'data' => Json::fromArray(['a' => 1]), 'id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), 'n' => 1, ], - ], ['body' => type_structure([ + ]], schema(structure_schema('body', type_structure([ 'data' => type_json(), 'id' => type_uuid(), 'n' => type_integer(), - ])])]), + ]))))), ); } @@ -228,9 +111,9 @@ public function test_encode_stringifies_json_in_deep_struct(): void [['outer' => ['inner' => ['deep' => '{"e":5}']]]], (new ParquetEncoder(ParquetSchema::with(NestedColumn::struct('outer', [NestedColumn::struct('inner', [FlatColumn::json( 'deep', - )])]))))->encode([new TypedRowValues([ + )])]))))->encode(array_to_rows([[ 'outer' => ['inner' => ['deep' => Json::fromArray(['e' => 5])]], - ], ['outer' => type_structure(['inner' => type_structure(['deep' => type_json()])])])]), + ]], schema(structure_schema('outer', type_structure(['inner' => type_structure(['deep' => type_json()])]))))), ); } @@ -241,9 +124,9 @@ public function test_encode_stringifies_uuid_list_elements(): void (new ParquetEncoder(ParquetSchema::with(NestedColumn::list( 'ids', ListElement::uuid(), - ))))->encode([new TypedRowValues([ - 'ids' => [new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')], - ], ['ids' => type_list(type_uuid())])]), + ))))->encode(array_to_rows([['ids' => [new Uuid( + 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + )]]], schema(list_schema('ids', type_list(type_uuid()))))), ); } @@ -255,9 +138,9 @@ public function test_encode_stringifies_uuid_map_values_keeping_keys(): void 'ids', MapKey::string(), MapValue::uuid(), - ))))->encode([new TypedRowValues([ - 'ids' => ['a' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')], - ], ['ids' => type_map(type_string(), type_uuid())])]), + ))))->encode(array_to_rows([['ids' => [ + 'a' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), + ]]], schema(map_schema('ids', type_map(type_string(), type_uuid()))))), ); } @@ -267,9 +150,9 @@ public function test_encode_stringifies_uuids_in_list_of_structs(): void [['items' => [['x' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']]]], (new ParquetEncoder(ParquetSchema::with(NestedColumn::list('items', ListElement::structure([FlatColumn::uuid( 'x', - )])))))->encode([new TypedRowValues([ + )])))))->encode(array_to_rows([[ 'items' => [['x' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')]], - ], ['items' => type_list(type_structure(['x' => type_uuid()]))])]), + ]], schema(list_schema('items', type_list(type_structure(['x' => type_uuid()])))))), ); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php index 928019bc73..006680015e 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php @@ -7,7 +7,9 @@ use Closure; use Flow\ETL\Adapter\Parquet\ParquetExtractor; use Flow\ETL\Cardinality; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Parquet\Binary\ByteOrder; @@ -16,6 +18,8 @@ use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\Adapter\Parquet\from_parquet; +use function Flow\ETL\DSL\config_builder; +use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -161,14 +165,28 @@ public function test_schema_then_statistics_reads_the_footer_once(): void static::assertSame(1, $filesystem->readFromCalls); } - public function test_a_declared_schema_still_reads_the_footer_for_statistics(): void + public function test_with_schema_is_refused(): void { - static::assertEquals( - Cardinality::exact(1000), - from_parquet(__DIR__ . '/../Integration/Fixtures/Pagination/01_1000.parquet') - ->withSchema(schema(int_schema('id'))) - ->statistics() - ->rows, + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Parquet is a self-describing format and does not accept a schema; declaring one is not supported yet.', ); + + from_parquet(__DIR__ . '/../Integration/Fixtures/Pagination/01_1000.parquet')->withSchema(schema(int_schema( + 'id', + ))); + } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + foreach (from_parquet(__DIR__ . '/../Integration/Fixtures/Pagination/01_1000.parquet')->extract( + flow_context(config_builder()->backend($backend)->build()), + ) as $rows) { + break; + } + + static::assertGreaterThanOrEqual(1, $backend->builders()); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/ElementsValueConverterTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/ElementsValueConverterTest.php index 21676372e4..2c387da1ee 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/ElementsValueConverterTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/ElementsValueConverterTest.php @@ -13,30 +13,6 @@ final class ElementsValueConverterTest extends FlowTestCase { - public function test_decode_converts_each_list_element(): void - { - // @mago-ignore analysis:mixed-assignment - $decoded = (new ElementsValueConverter(new UuidValueConverter()))->decode([ - 'f6d6e0e8-4b7e-4b0e-8d7a-ff0a0c9c9a5a', - null, - ]); - - static::assertIsArray($decoded); - static::assertInstanceOf(Uuid::class, $decoded[0]); - static::assertNull($decoded[1]); - } - - public function test_decode_converts_keyed_values_keeping_keys(): void - { - // @mago-ignore analysis:mixed-assignment - $decoded = (new ElementsValueConverter(new JsonValueConverter()))->decode(['a' => '{"x":1}', 'b' => null]); - - static::assertIsArray($decoded); - static::assertSame(['a', 'b'], array_keys($decoded)); - static::assertInstanceOf(Json::class, $decoded['a']); - static::assertNull($decoded['b']); - } - public function test_encode_stringifies_each_list_element(): void { static::assertSame( @@ -60,7 +36,6 @@ public function test_non_array_values_pass_through(): void { $converter = new ElementsValueConverter(new UuidValueConverter()); - static::assertNull($converter->decode(null)); static::assertSame('scalar', $converter->encode('scalar')); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/JsonValueConverterTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/JsonValueConverterTest.php index ef549eee68..1ec807098c 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/JsonValueConverterTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/JsonValueConverterTest.php @@ -10,20 +10,6 @@ final class JsonValueConverterTest extends FlowTestCase { - public function test_decode_casts_string_to_json(): void - { - // @mago-ignore analysis:mixed-assignment - $decoded = (new JsonValueConverter())->decode('{"a":1}'); - - static::assertInstanceOf(Json::class, $decoded); - static::assertSame(['a' => 1], $decoded->toArray()); - } - - public function test_decode_passes_null_through(): void - { - static::assertNull((new JsonValueConverter())->decode(null)); - } - public function test_encode_passes_scalar_through(): void { static::assertSame('{"a":1}', (new JsonValueConverter())->encode('{"a":1}')); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/StructValueConverterTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/StructValueConverterTest.php index e738069a1f..795375531c 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/StructValueConverterTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/StructValueConverterTest.php @@ -11,27 +11,6 @@ final class StructValueConverterTest extends FlowTestCase { - public function test_decode_converts_only_declared_children(): void - { - // @mago-ignore analysis:mixed-assignment - $decoded = (new StructValueConverter(['data' => new JsonValueConverter()]))->decode([ - 'data' => '{"a":1}', - 'n' => 1, - ]); - - static::assertIsArray($decoded); - static::assertInstanceOf(Json::class, $decoded['data']); - static::assertSame(1, $decoded['n']); - } - - public function test_decode_passes_missing_and_null_children_through(): void - { - $converter = new StructValueConverter(['data' => new JsonValueConverter()]); - - static::assertSame([], $converter->decode([])); - static::assertSame(['data' => null], $converter->decode(['data' => null])); - } - public function test_encode_stringifies_child_objects(): void { static::assertSame( @@ -47,7 +26,6 @@ public function test_non_array_values_pass_through(): void { $converter = new StructValueConverter(['data' => new JsonValueConverter()]); - static::assertNull($converter->decode(null)); static::assertSame('scalar', $converter->encode('scalar')); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/UuidValueConverterTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/UuidValueConverterTest.php index 617a064c19..568eaafabe 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/UuidValueConverterTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ValueConverter/UuidValueConverterTest.php @@ -10,20 +10,6 @@ final class UuidValueConverterTest extends FlowTestCase { - public function test_decode_casts_canonical_string_to_uuid(): void - { - // @mago-ignore analysis:mixed-assignment - $decoded = (new UuidValueConverter())->decode('f6d6e0e8-4b7e-4b0e-8d7a-ff0a0c9c9a5a'); - - static::assertInstanceOf(Uuid::class, $decoded); - static::assertSame('f6d6e0e8-4b7e-4b0e-8d7a-ff0a0c9c9a5a', $decoded->toString()); - } - - public function test_decode_passes_null_through(): void - { - static::assertNull((new UuidValueConverter())->decode(null)); - } - public function test_encode_passes_scalar_through(): void { static::assertSame( 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 6575ba692a..afe288c2d1 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 @@ -14,6 +14,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\PostgreSql\Client\Client; use Flow\PostgreSql\QueryBuilder\Sql; @@ -72,7 +73,6 @@ public function extract(FlowContext $context, ?int $limit = null): Generator { $read = $this->read ??= ReadQuery::of($this->query, self::class); - $encoder = new PostgreSqlEncoder(); $cursorName = $this->cursorName ?? 'flow_cursor_' . bin2hex(random_bytes(8)); $schema = $this->schema(); @@ -119,11 +119,13 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $cursor->free(); - $hydrated = $context->hydrator()->hydrate($encoder->decode($rawBatch), $schema); + $rows = (new RowsBuilder($schema, $context->backend())) + ->appendRows($rawBatch) + ->finish(); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlEncoder.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlEncoder.php index fa6b5df279..93bdab880d 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlEncoder.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlEncoder.php @@ -4,31 +4,31 @@ namespace Flow\ETL\Adapter\PostgreSql; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; -/** - * @implements Encoder> - */ -final class PostgreSqlEncoder implements Encoder +final class PostgreSqlEncoder { - public function decode(array $batch): array + /** + * @return list> + */ + public function encode(Rows $rows): array { - $decoded = []; + $columns = []; - foreach ($batch as $values) { - $decoded[] = new RawRowValues($values); + foreach ($rows->schema()->definitions() as $definition) { + $columns[$definition->entry()->name()] = $rows->column($definition->entry()->name())->values(); } - return $decoded; - } - - public function encode(array $batch): array - { $encoded = []; - foreach ($batch as $rowValues) { - $encoded[] = $rowValues->values; + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $row = []; + + foreach ($columns as $name => $column) { + $row[$name] = $column[$i]; + } + + $encoded[] = $row; } return $encoded; 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 037cb6b9d2..eef53f2c94 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 @@ -17,6 +17,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\PostgreSql\Client\Client; use Flow\PostgreSql\QueryBuilder\Sql; @@ -72,7 +73,6 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $schema = $this->schema(); - $encoder = new PostgreSqlEncoder(); $yielded = 0; $cursorValues = null; $maximum = match (true) { @@ -114,11 +114,13 @@ public function extract(FlowContext $context, ?int $limit = null): Generator break; } - $hydrated = $context->hydrator()->hydrate($encoder->decode($rawBatch), $schema); + $rows = (new RowsBuilder($schema, $context->backend())) + ->appendRows($rawBatch) + ->finish(); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; 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 8d3ea01930..a65551ebbf 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 @@ -14,6 +14,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\PostgreSql\Client\Client; use Flow\PostgreSql\QueryBuilder\Sql; @@ -77,7 +78,6 @@ public function extract(FlowContext $context, ?int $limit = null): Generator return; } - $encoder = new PostgreSqlEncoder(); $yielded = 0; $pages = (int) ceil($total / $this->batchSize); $pageSql = $read->page(count($this->parameters) + 1); @@ -100,11 +100,13 @@ public function extract(FlowContext $context, ?int $limit = null): Generator return; } - $hydrated = $context->hydrator()->hydrate($encoder->decode($rawBatch), $schema); + $rows = (new RowsBuilder($schema, $context->backend())) + ->appendRows($rawBatch) + ->finish(); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLoader.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLoader.php index 8b2c036de3..412d949e0b 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLoader.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLoader.php @@ -60,9 +60,9 @@ public function load(Rows $rows, FlowContext $context): void try { match ($this->operation) { - Operation::INSERT => $this->insertRows($rows, $context), - Operation::UPDATE => $this->updateRows($rows, $context), - Operation::DELETE => $this->deleteRows($rows, $context), + Operation::INSERT => $this->insertRows($rows), + Operation::UPDATE => $this->updateRows($rows), + Operation::DELETE => $this->deleteRows($rows), }; $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); @@ -113,7 +113,7 @@ private function encoder(): PostgreSqlEncoder return $this->encoder ??= new PostgreSqlEncoder(); } - private function deleteRows(Rows $rows, FlowContext $context): void + private function deleteRows(Rows $rows): void { $deleteOptions = $this->deleteOptions; @@ -124,13 +124,13 @@ private function deleteRows(Rows $rows, FlowContext $context): void $builder = new DeleteQueryBuilder($this->table, $this->typesMap); $schema = $rows->schema(); - foreach ($this->encoder()->encode($context->hydrator()->dehydrate($rows)) as $values) { + foreach ($this->encoder()->encode($rows) as $values) { [$query, $params] = $builder->build($values, $schema, $deleteOptions); $this->client->execute($query, $params); } } - private function insertRows(Rows $rows, FlowContext $context): void + private function insertRows(Rows $rows): void { // PQ_QUERY_PARAM_MAX_LIMIT: an INSERT binds one parameter per column per row $maxRows = max(1, intdiv(65_535, $rows->schema()->count())); @@ -138,7 +138,7 @@ private function insertRows(Rows $rows, FlowContext $context): void if ($rows->count() <= $maxRows) { $builder = new InsertQueryBuilder($this->table, $this->typesMap); [$query, $params] = $builder->build( - $this->encoder()->encode($context->hydrator()->dehydrate($rows)), + $this->encoder()->encode($rows), $rows->schema(), $this->client->converters(), $this->insertOptions, @@ -159,7 +159,7 @@ private function insertRows(Rows $rows, FlowContext $context): void foreach ($rows->chunks($maxRows) as $chunk) { $builder = new InsertQueryBuilder($this->table, $this->typesMap); [$query, $params] = $builder->build( - $this->encoder()->encode($context->hydrator()->dehydrate($chunk)), + $this->encoder()->encode($chunk), $chunk->schema(), $this->client->converters(), $this->insertOptions, @@ -179,7 +179,7 @@ private function insertRows(Rows $rows, FlowContext $context): void } } - private function updateRows(Rows $rows, FlowContext $context): void + private function updateRows(Rows $rows): void { $updateOptions = $this->updateOptions; @@ -190,7 +190,7 @@ private function updateRows(Rows $rows, FlowContext $context): void $builder = new UpdateQueryBuilder($this->table, $this->typesMap); $schema = $rows->schema(); - foreach ($this->encoder()->encode($context->hydrator()->dehydrate($rows)) as $values) { + foreach ($this->encoder()->encode($rows) as $values) { [$query, $params] = $builder->build($values, $schema, $updateOptions); if ($query !== null) { diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/DeleteQueryBuilder.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/DeleteQueryBuilder.php index f8ee1a6064..7f061ec346 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/DeleteQueryBuilder.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/DeleteQueryBuilder.php @@ -28,7 +28,7 @@ public function __construct( ) {} /** - * @param array $value dehydrated value map for a single row + * @param array $value encoded value map for a single row * * @return array{Sql, list} */ diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/InsertQueryBuilder.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/InsertQueryBuilder.php index 1854361c94..7071f82d38 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/InsertQueryBuilder.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/InsertQueryBuilder.php @@ -31,7 +31,7 @@ public function __construct( * Every value already in PostgreSQL's text form. A column's converter is resolved once, on its first non-null * value - so a column of an unmapped type holding only nulls passes. * - * @param list> $values pre-sorted dehydrated value maps + * @param list> $values pre-sorted encoded value maps * * @return array{Sql, ConvertedParameters} */ diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/UpdateQueryBuilder.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/UpdateQueryBuilder.php index 93f5c241db..b33488c9ff 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/UpdateQueryBuilder.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/UpdateQueryBuilder.php @@ -29,7 +29,7 @@ public function __construct( ) {} /** - * @param array $value dehydrated value map for a single row + * @param array $value encoded value map for a single row * * @return array{null|Sql, list} */ 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 90d4cc7ec9..061d8b31e6 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 @@ -11,6 +11,7 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Exception\SchemaNotDerivableException; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\PostgreSql\AST\Transformers\ExplainConfig; use Flow\PostgreSql\Client\Exception\PostgreSqlError; @@ -19,6 +20,7 @@ use function array_map; use function Flow\ETL\Adapter\PostgreSql\from_pgsql_cursor; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -454,4 +456,21 @@ public function test_a_maximum_bounds_and_caps_the_estimate_and_a_new_one_drops_ $extractor->statistics()->rows, ); } + + public function test_extract_builds_through_the_config_backend(): void + { + $client = (new SpyClient()) + ->willDescribe(ColumnMother::of(['id' => 'int8'])) + ->willReturnCursors(new StubCursor([['id' => '1']]), new StubCursor()); + $backend = new SpyBackend(); + + iterator_to_array( + from_pgsql_cursor($client, 'SELECT id FROM t')->extract( + flow_context(config_builder()->backend($backend)->build()), + ), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlEncoderTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlEncoderTest.php index 850314c656..dbe0167223 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlEncoderTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlEncoderTest.php @@ -5,59 +5,40 @@ namespace Flow\ETL\Adapter\PostgreSql\Tests\Unit; use Flow\ETL\Adapter\PostgreSql\PostgreSqlEncoder; -use Flow\ETL\Row\RawRowValues; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\FlowTestCase; -use function Flow\Types\DSL\type_boolean; -use function Flow\Types\DSL\type_integer; -use function Flow\Types\DSL\type_string; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class PostgreSqlEncoderTest extends FlowTestCase { - public function test_decode_wraps_each_value_map_in_row_values(): void + public function test_encode_returns_each_row_as_its_value_map(): void { - $decoded = (new PostgreSqlEncoder())->decode([ - ['id' => 1, 'name' => 'Norbert'], - ['id' => 2, 'name' => null], - ]); - - static::assertEquals( - [new RawRowValues(['id' => 1, 'name' => 'Norbert']), new RawRowValues(['id' => 2, 'name' => null])], - $decoded, + static::assertSame( + [['id' => 1, 'name' => 'Norbert'], ['id' => 2, 'name' => null]], + (new PostgreSqlEncoder())->encode(array_to_rows( + [['id' => 1, 'name' => 'Norbert'], ['id' => 2, 'name' => null]], + schema(int_schema('id'), str_schema('name', nullable: true)), + )), ); } - public function test_encode_unwraps_each_typed_row_values_to_its_value_map(): void - { - $types = ['id' => type_integer(), 'name' => type_string()]; - - $encoded = (new PostgreSqlEncoder())->encode([ - new TypedRowValues(['id' => 1, 'name' => 'Norbert'], $types), - new TypedRowValues(['id' => 2, 'name' => null], $types), - ]); - - static::assertSame([['id' => 1, 'name' => 'Norbert'], ['id' => 2, 'name' => null]], $encoded); - } - public function test_encode_returns_the_original_value_maps(): void { - $types = ['id' => type_integer(), 'active' => type_boolean()]; - static::assertSame( [['id' => 1, 'active' => true], ['id' => 2, 'active' => false]], - (new PostgreSqlEncoder())->encode([ - new TypedRowValues(['id' => 1, 'active' => true], $types), - new TypedRowValues(['id' => 2, 'active' => false], $types), - ]), + (new PostgreSqlEncoder())->encode(array_to_rows( + [['id' => 1, 'active' => true], ['id' => 2, 'active' => false]], + schema(int_schema('id'), bool_schema('active')), + )), ); } - public function test_encode_and_decode_of_an_empty_batch_return_empty(): void + public function test_encode_of_an_empty_batch_returns_empty(): void { - $encoder = new PostgreSqlEncoder(); - - static::assertSame([], $encoder->decode([])); - static::assertSame([], $encoder->encode([])); + static::assertSame([], (new PostgreSqlEncoder())->encode(array_to_rows([], schema(int_schema('id'))))); } } 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 9876dd9593..a88aa17eb2 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 @@ -10,6 +10,7 @@ use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\PostgreSql\AST\Transformers\ExplainConfig; use Flow\PostgreSql\Client\Exception\PostgreSqlError; @@ -20,6 +21,7 @@ use function Flow\ETL\Adapter\PostgreSql\from_pgsql_key_set; use function Flow\ETL\Adapter\PostgreSql\pgsql_pagination_key_asc; use function Flow\ETL\Adapter\PostgreSql\pgsql_pagination_key_set; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -395,4 +397,23 @@ public function test_a_maximum_bounds_and_caps_the_estimate_and_a_new_one_drops_ $extractor->statistics()->rows, ); } + + public function test_extract_builds_through_the_config_backend(): void + { + $client = (new SpyClient()) + ->willDescribe(ColumnMother::of(['id' => 'int8'])) + ->willReturnCursors(new StubCursor([['id' => '1']]), new StubCursor()); + $backend = new SpyBackend(); + + iterator_to_array( + from_pgsql_key_set( + $client, + 'SELECT id FROM t', + pgsql_pagination_key_set(pgsql_pagination_key_asc('id')), + )->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } 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 7d1909e5ae..bf30b95332 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 @@ -11,6 +11,7 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\PostgreSql\AST\Transformers\ExplainConfig; use Flow\PostgreSql\Client\Exception\PostgreSqlError; @@ -19,6 +20,7 @@ use function array_map; use function extension_loaded; use function Flow\ETL\Adapter\PostgreSql\from_pgsql_limit_offset; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -365,4 +367,22 @@ public function test_a_maximum_bounds_and_caps_the_estimate_and_a_new_one_drops_ $extractor->statistics()->rows, ); } + + public function test_extract_builds_through_the_config_backend(): void + { + $client = (new SpyClient()) + ->willDescribe(ColumnMother::of(['id' => 'int8'])) + ->willCountTotal(1) + ->willReturnCursors(new StubCursor([['id' => '1']])); + $backend = new SpyBackend(); + + iterator_to_array( + from_pgsql_limit_offset($client, 'SELECT id FROM t ORDER BY id')->extract( + flow_context(config_builder()->backend($backend)->build()), + ), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealEncoder.php b/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealEncoder.php index 92c7c58b0a..5550f25832 100644 --- a/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealEncoder.php +++ b/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealEncoder.php @@ -12,8 +12,7 @@ use DOMDocument; use DOMElement; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; @@ -40,37 +39,34 @@ use function is_int; use function is_string; -/** - * @implements Encoder> - */ -final class SealEncoder implements Encoder +final class SealEncoder { public function __construct( private readonly string $dateTimeFormat = DateTimeInterface::ATOM, private readonly string $dateFormat = 'Y-m-d', ) {} - public function decode(array $batch): array + /** + * @return list> + */ + public function encode(Rows $rows): array { - $decoded = []; + $columns = []; + $types = []; - foreach ($batch as $values) { - $decoded[] = new RawRowValues($values); + foreach ($rows->schema()->definitions() as $definition) { + $name = $definition->entry()->name(); + $columns[$name] = $rows->column($name)->values(); + $types[$name] = $definition->type(); } - return $decoded; - } - - public function encode(array $batch): array - { $documents = []; - foreach ($batch as $rowValues) { + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { $document = []; - /** @var mixed $value */ - foreach ($rowValues->values as $name => $value) { - $document[$name] = $this->renderValue($rowValues->types[$name], $value); + foreach ($columns as $name => $column) { + $document[$name] = $this->renderValue($types[$name], $column[$i]); } $documents[] = $document; diff --git a/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealLoader.php b/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealLoader.php index 6498324d39..960f2bb508 100644 --- a/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealLoader.php +++ b/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealLoader.php @@ -47,10 +47,8 @@ public function load(Rows $rows, FlowContext $context): void try { $this->engine->bulk( $this->index, - $this->operation === Operation::UPSERT - ? $this->encoder()->encode($context->hydrator()->dehydrate($rows)) - : [], - $this->operation === Operation::DELETE ? $this->deleteIdentifiers($rows, $context) : [], + $this->operation === Operation::UPSERT ? $this->encoder()->encode($rows) : [], + $this->operation === Operation::DELETE ? $this->deleteIdentifiers($rows) : [], $this->bulkSize, ); @@ -98,9 +96,9 @@ private function encoder(): SealEncoder /** * @return Generator */ - private function deleteIdentifiers(Rows $rows, FlowContext $context): Generator + private function deleteIdentifiers(Rows $rows): Generator { - foreach ($this->encoder()->encode($context->hydrator()->dehydrate($rows)) as $document) { + foreach ($this->encoder()->encode($rows) as $document) { // @mago-ignore analysis:mixed-assignment $identifier = array_key_exists($this->identifierEntry, $document) ? $document[$this->identifierEntry] diff --git a/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealEncoderTest.php b/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealEncoderTest.php index 1110731338..a609c77ed4 100644 --- a/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealEncoderTest.php +++ b/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealEncoderTest.php @@ -9,7 +9,6 @@ use DateTimeZone; use DOMDocument; use Flow\ETL\Adapter\Seal\SealEncoder; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Type; @@ -18,8 +17,14 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\definition_from_type; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_boolean; -use function Flow\Types\DSL\type_date; use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_enum; use function Flow\Types\DSL\type_float; @@ -32,7 +37,6 @@ use function Flow\Types\DSL\type_time; use function Flow\Types\DSL\type_time_zone; use function Flow\Types\DSL\type_uuid; -use function Flow\Types\DSL\type_xml; final class SealEncoderTest extends FlowTestCase { @@ -84,7 +88,9 @@ public function test_encodes_values_into_documents(mixed $value, mixed $expected { static::assertSame( $expected, - (new SealEncoder())->encode([new TypedRowValues(['field' => $value], ['field' => $type])])[0]['field'], + (new SealEncoder())->encode(array_to_rows([[ + 'field' => $value, + ]], schema(definition_from_type('field', $type, nullable: $value === null))))[0]['field'], ); } @@ -95,7 +101,7 @@ public function test_encodes_xml_document_to_string(): void static::assertSame( '1', - (new SealEncoder())->encode([new TypedRowValues(['xml' => $doc], ['xml' => type_xml()])])[0]['xml'], + (new SealEncoder())->encode(array_to_rows([['xml' => $doc]], schema(xml_schema('xml'))))[0]['xml'], ); } @@ -103,9 +109,9 @@ public function test_renders_date_with_the_date_format(): void { static::assertSame( '2023-10-01', - (new SealEncoder())->encode([ - new TypedRowValues(['date' => new DateTimeImmutable('2023-10-01 00:00:00')], ['date' => type_date()]), - ])[0]['date'], + (new SealEncoder())->encode(array_to_rows([[ + 'date' => new DateTimeImmutable('2023-10-01 00:00:00'), + ]], schema(date_schema('date'))))[0]['date'], ); } @@ -113,10 +119,10 @@ public function test_produces_documents_keyed_by_column_name(): void { static::assertSame( [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']], - (new SealEncoder())->encode([ - new TypedRowValues(['id' => 1, 'name' => 'Alice'], ['id' => type_integer(), 'name' => type_string()]), - new TypedRowValues(['id' => 2, 'name' => 'Bob'], ['id' => type_integer(), 'name' => type_string()]), - ]), + (new SealEncoder())->encode(array_to_rows( + [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']], + schema(int_schema('id'), str_schema('name')), + )), ); } } diff --git a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextEncoder.php b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextEncoder.php index a5ab22f982..baa304d989 100644 --- a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextEncoder.php +++ b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextEncoder.php @@ -5,56 +5,43 @@ namespace Flow\ETL\Adapter\Text; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; use Stringable; -use function array_values; use function count; use function get_debug_type; use function is_bool; use function is_scalar; -use function rtrim; use function sprintf; -/** - * @implements Encoder - */ -final class TextEncoder implements Encoder +final class TextEncoder { public function __construct( private readonly string $newLineSeparator = PHP_EOL, ) {} - public function decode(array $batch): array + /** + * @return list + */ + public function encode(Rows $rows): array { - $maps = []; + $columns = []; - foreach ($batch as $line) { - $maps[] = new RawRowValues(['text' => rtrim($line)]); + foreach ($rows->schema()->definitions() as $definition) { + $columns[] = $rows->column($definition->entry()->name())->values(); } - return $maps; - } - - public function encode(array $batch): array - { $lines = []; - foreach ($batch as $rowValues) { - $values = $rowValues->values; - - if (count($values) > 1) { + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + if (count($columns) > 1) { throw new RuntimeException(sprintf( 'Text data loader supports only a single entry rows, and you have %d rows.', - count($values), + count($columns), )); } - /** @var mixed $value */ - $value = array_values($values)[0] ?? null; - - $lines[] = $this->renderValue($value) . $this->newLineSeparator; + $lines[] = $this->renderValue($columns[0][$i] ?? null) . $this->newLineSeparator; } return $lines; 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 555626b1ef..7bf318c408 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 @@ -17,6 +17,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -28,6 +29,7 @@ use function count; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function rtrim; use function sprintf; final class TextExtractor implements @@ -73,10 +75,9 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $hydrator = $context->hydrator(); + $backend = $context->backend(); $batchSize = $this->batchSize(); $yielded = 0; - $encoder = new TextEncoder(); $baseSchema = $this->schema ?? schema(str_schema('text')); @@ -93,19 +94,22 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $rawLines = []; foreach ($stream->readLines() as $line) { - $rawLines[] = $line; + $rawLines[] = ['text' => rtrim($line)]; if (count($rawLines) >= $batchSize) { - $hydrated = $constants->fillRows( - $hydrator->hydrate($encoder->decode($rawLines), $body), + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows($rawLines) + ->finish(), $schema, + $backend, ); $rawLines = []; - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; @@ -118,11 +122,17 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } if ($rawLines !== []) { - $hydrated = $constants->fillRows($hydrator->hydrate($encoder->decode($rawLines), $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows($rawLines) + ->finish(), + $schema, + $backend, + ); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextLoader.php b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextLoader.php index 96e0ea18de..dfddb537d8 100644 --- a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextLoader.php +++ b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextLoader.php @@ -98,7 +98,7 @@ public function load(Rows $rows, FlowContext $context): void foreach ($this->router->route($rows) as [$partitions, $group]) { ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode)) ->writeTo($partitions->toArray()) - ->append(implode('', $this->encoder()->encode($context->hydrator()->dehydrate($group)))); + ->append(implode('', $this->encoder()->encode($group))); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); 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 f350ac449f..3a57daea28 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 @@ -11,11 +11,13 @@ use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\Double\RecordingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\UnsizedFilesystem; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\Text\from_text; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\schema; @@ -186,4 +188,17 @@ public function test_the_listing_is_read_once(): void static::assertSame(1, $filesystem->listCalls); } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + iterator_to_array( + from_text(path_real(__DIR__ . '/../Fixtures/orders_flow.csv')) + ->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextHydratorParityTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTypedColumnsTest.php similarity index 96% rename from src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextHydratorParityTest.php rename to src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTypedColumnsTest.php index b3fe83c723..1f0b88313d 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextHydratorParityTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTypedColumnsTest.php @@ -12,7 +12,7 @@ use function Flow\Filesystem\DSL\path_real; use function Flow\Types\DSL\type_string; -final class TextHydratorParityTest extends FlowTestCase +final class TextExtractorTypedColumnsTest extends FlowTestCase { public function test_reads_each_line_into_a_string_text_column(): void { diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextEncoderTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextEncoderTest.php index d68cae6cf5..a12e9dfa3d 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextEncoderTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextEncoderTest.php @@ -6,35 +6,23 @@ use Flow\ETL\Adapter\Text\TextEncoder; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\RawRowValues; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\FlowTestCase; -use function array_map; -use function Flow\Types\DSL\type_integer; -use function Flow\Types\DSL\type_string; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; final class TextEncoderTest extends FlowTestCase { - public function test_decode_trims_trailing_new_lines_into_a_single_text_column(): void - { - static::assertSame( - [['text' => 'first'], ['text' => 'second']], - array_map( - static fn(RawRowValues $rowValues): array => $rowValues->values, - (new TextEncoder())->decode(["first\n", "second\r\n"]), - ), - ); - } - public function test_encode_appends_the_new_line_separator_to_the_single_value(): void { static::assertSame( ["first\n", "second\n"], - (new TextEncoder("\n"))->encode([ - new TypedRowValues(['text' => 'first'], ['text' => type_string()]), - new TypedRowValues(['text' => 'second'], ['text' => type_string()]), - ]), + (new TextEncoder("\n"))->encode(array_to_rows([ + ['text' => 'first'], + ['text' => 'second'], + ], schema(str_schema('text')))), ); } @@ -42,7 +30,9 @@ public function test_encode_renders_null_as_an_empty_line(): void { static::assertSame( ["\n"], - (new TextEncoder("\n"))->encode([new TypedRowValues(['text' => null], ['text' => type_string()])]), + (new TextEncoder("\n"))->encode(array_to_rows([[ + 'text' => null, + ]], schema(str_schema('text', nullable: true)))), ); } @@ -51,8 +41,14 @@ public function test_encode_throws_when_a_row_has_more_than_one_column(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Text data loader supports only a single entry rows, and you have 2 rows.'); - (new TextEncoder())->encode([ - new TypedRowValues(['a' => 1, 'b' => 2], ['a' => type_integer(), 'b' => type_integer()]), - ]); + (new TextEncoder())->encode(array_to_rows([['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b')))); + } + + public function test_encode_of_an_empty_batch_with_more_than_one_column_returns_no_lines(): void + { + static::assertSame( + [], + (new TextEncoder())->encode(array_to_rows([], schema(int_schema('a'), int_schema('b')))), + ); } } diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/Loader/XMLLoader.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/Loader/XMLLoader.php index 7f18345cc2..414d96ac36 100644 --- a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/Loader/XMLLoader.php +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/Loader/XMLLoader.php @@ -127,7 +127,7 @@ public function load(Rows $rows, FlowContext $context): void try { foreach ($this->router->route($rows) as [$partitions, $group]) { - $this->write($group, $partitions->toArray(), $context); + $this->write($group, $partitions->toArray()); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); @@ -221,7 +221,7 @@ public function withXMLAttributes(array $xmlAttributes): self /** * @param array $partitions */ - public function write(Rows $nextRows, array $partitions, FlowContext $context): void + public function write(Rows $nextRows, array $partitions): void { $files = $this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode); $opening = !$files->touched($partitions); @@ -237,7 +237,7 @@ public function write(Rows $nextRows, array $partitions, FlowContext $context): $stream->append('\n<" . $this->rootElementName . ">\n"); } - foreach ($this->encoder()->encode($context->hydrator()->dehydrate($nextRows)) as $node) { + foreach ($this->encoder()->encode($nextRows) as $node) { $stream->append($node . "\n"); } } diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLEncoder.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLEncoder.php index f069782601..1f227b92a6 100644 --- a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLEncoder.php +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLEncoder.php @@ -15,8 +15,7 @@ use Flow\ETL\Adapter\XML\Abstraction\XMLNode; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; @@ -52,10 +51,7 @@ use const JSON_THROW_ON_ERROR; -/** - * @implements Encoder - */ -final class XMLEncoder implements Encoder +final class XMLEncoder { public function __construct( private readonly ?XMLWriter $xmlWriter = null, @@ -69,28 +65,29 @@ public function __construct( private readonly string $rowElementName = 'row', ) {} - public function decode(array $batch): array + /** + * @return list + */ + public function encode(Rows $rows): array { - $maps = []; - - foreach ($batch as $xml) { - $maps[] = new RawRowValues(['node' => $xml]); - } + $xmlWriter = $this->xmlWriter ?? throw new RuntimeException('XMLEncoder requires an XMLWriter to encode rows'); - return $maps; - } + $columns = []; + $types = []; - public function encode(array $batch): array - { - $xmlWriter = $this->xmlWriter ?? throw new RuntimeException('XMLEncoder requires an XMLWriter to encode rows'); + foreach ($rows->schema()->definitions() as $definition) { + $name = $definition->entry()->name(); + $columns[$name] = $rows->column($name)->values(); + $types[$name] = $definition->type(); + } $lines = []; - foreach ($batch as $rowValues) { + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { $elements = []; - foreach ($rowValues->types as $name => $type) { - $elements[] = $this->normalize($name, $type, $rowValues->values[$name]); + foreach ($columns as $name => $column) { + $elements[] = $this->normalize($name, $types[$name], $column[$i]); } $lines[] = $xmlWriter->write(XMLNode::nested($this->rowElementName, ...$elements)); @@ -162,15 +159,6 @@ private function normalize(string $name, Type $type, mixed $value): XMLNode|XMLA if ($type instanceof StructureType) { $values = is_array($value) ? array_values($value) : []; - if (count($values) > count($type->elements())) { - throw new RuntimeException(sprintf( - 'XML encoder received %d values for structure "%s" which declares %d elements - extra values would be silently lost', - count($values), - $type->toString(), - count($type->elements()), - )); - } - $elements = []; foreach ($type->elements() as $position => $element) { 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 4d64eee9b0..e3fa8a9404 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 @@ -16,8 +16,8 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -96,7 +96,7 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $hydrator = $context->hydrator(); + $backend = $context->backend(); $batchSize = $this->batchSize(); $yielded = 0; $nodes = new XMLNodes($this->xmlNodePath); @@ -116,16 +116,22 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $batch = []; foreach ($nodes->of($stream, $this->bufferSize) as $node) { - $batch[] = new RawRowValues(['node' => $node]); + $batch[] = ['node' => $node]; if (count($batch) >= $batchSize) { - $hydrated = $constants->fillRows($hydrator->hydrate($batch, $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows($batch) + ->finish(), + $schema, + $backend, + ); $batch = []; - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; @@ -138,11 +144,17 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } if ($batch !== []) { - $hydrated = $constants->fillRows($hydrator->hydrate($batch, $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows($batch) + ->finish(), + $schema, + $backend, + ); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; 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 a6541813b4..d9112e87f0 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 @@ -18,6 +18,7 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -102,10 +103,9 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $hydrator = $context->hydrator(); + $backend = $context->backend(); $batchSize = $this->batchSize(); $yielded = 0; - $encoder = new XMLEncoder(); $baseSchema = $this->schema ?? schema(xml_schema('node')); @@ -149,19 +149,22 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi ) { $dom = new DOMDocument('1.0', ''); $node = $xmlReader->expand($dom); - $rawNodes[] = $node === false ? '' : (string) $dom->saveXML($node); + $rawNodes[] = ['node' => $node === false ? '' : (string) $dom->saveXML($node)]; if (count($rawNodes) >= $batchSize) { - $hydrated = $constants->fillRows( - $hydrator->hydrate($encoder->decode($rawNodes), $body), + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows($rawNodes) + ->finish(), $schema, + $backend, ); $rawNodes = []; - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; @@ -178,11 +181,17 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } if ($rawNodes !== []) { - $hydrated = $constants->fillRows($hydrator->hydrate($encoder->decode($rawNodes), $body), $schema); + $rows = $constants->fillRows( + (new RowsBuilder($body, $backend)) + ->appendRows($rawNodes) + ->finish(), + $schema, + $backend, + ); - $yielded += $hydrated->count(); + $yielded += $rows->count(); - $signal = yield $hydrated; + $signal = yield $rows; if ($signal === Signal::STOP) { return; diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLHydratorParityTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php similarity index 95% rename from src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLHydratorParityTest.php rename to src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php index 9441f6575e..04b4e1a1ca 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLHydratorParityTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php @@ -12,7 +12,7 @@ use function Flow\Filesystem\DSL\path_real; use function Flow\Types\DSL\type_xml; -final class XMLHydratorParityTest extends FlowTestCase +final class XMLExtractorTypedColumnsTest extends FlowTestCase { public function test_reads_each_node_into_a_typed_xml_column(): void { 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 262d9ad7c7..833e8a247e 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 @@ -14,6 +14,7 @@ use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\Double\RecordingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\UnsizedFilesystem; use Flow\ETL\Tests\FlowIntegrationTestCase; @@ -21,6 +22,7 @@ use function file_get_contents; use function Flow\ETL\Adapter\XML\from_xml; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; @@ -32,6 +34,7 @@ use function Flow\Filesystem\DSL\path; use function Flow\Filesystem\DSL\path_real; use function Flow\Types\DSL\type_string; +use function iterator_to_array; final class XMLParserExtractorTest extends FlowIntegrationTestCase { @@ -442,4 +445,18 @@ public function test_the_listing_is_read_once(): void static::assertSame(1, $filesystem->listCalls); } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + + iterator_to_array( + from_xml(path_real(__DIR__ . '/../Fixtures/one_line_items.xml')) + ->withXMLNodePath('root/item') + ->extract(flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } 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 ee4304e0ee..945e11a2b8 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 @@ -10,11 +10,13 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\UnsizedFilesystem; use Flow\ETL\Tests\FlowIntegrationTestCase; use function array_keys; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\schema; @@ -24,6 +26,7 @@ use function Flow\Filesystem\DSL\path; use function Flow\Filesystem\DSL\path_real; use function Flow\Types\DSL\type_string; +use function iterator_to_array; final class XMLReaderExtractorTest extends FlowIntegrationTestCase { @@ -230,4 +233,15 @@ public function test_the_listing_is_read_once(): void static::assertSame(1, $filesystem->listCalls); } + + public function test_extract_builds_through_the_config_backend(): void + { + $backend = new SpyBackend(); + // @mago-ignore analysis:deprecated-class + $extractor = new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/one_line_items.xml'), 'root/item'); + + iterator_to_array($extractor->extract(flow_context(config_builder()->backend($backend)->build())), false); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLEncoderTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLEncoderTest.php index ac02a45af8..87a2556dbe 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLEncoderTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLEncoderTest.php @@ -10,46 +10,42 @@ use Flow\ETL\Adapter\XML\XMLEncoder; use Flow\ETL\Adapter\XML\XMLWriter\DOMDocumentWriter; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Tests\Fixtures\Enum\BackedIntEnum; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Value\Uuid; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\enum_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\ETL\DSL\time_zone_schema; +use function Flow\ETL\DSL\uuid_schema; use function Flow\Types\DSL\structure_element; -use function Flow\Types\DSL\type_date; -use function Flow\Types\DSL\type_datetime; -use function Flow\Types\DSL\type_enum; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; -use function Flow\Types\DSL\type_time; -use function Flow\Types\DSL\type_time_zone; -use function Flow\Types\DSL\type_uuid; final class XMLEncoderTest extends FlowTestCase { - public function test_decode_wraps_raw_xml_into_a_node_column(): void - { - $encoder = new XMLEncoder(new DOMDocumentWriter()); - - static::assertSame( - ['node' => '1'], - $encoder->decode(['1'])[0]->values, - ); - } - public function test_encodes_scalars_into_flat_nodes(): void { $encoder = new XMLEncoder(new DOMDocumentWriter()); static::assertXmlStringEqualsXmlString( '1Norbert', - $encoder->encode([new TypedRowValues(['id' => 1, 'name' => 'Norbert'], [ - 'id' => type_integer(), - 'name' => type_string(), - ])])[0], + $encoder->encode(array_to_rows( + [['id' => 1, 'name' => 'Norbert']], + schema(int_schema('id'), str_schema('name')), + ))[0], ); } @@ -59,10 +55,10 @@ public function test_encodes_prefixed_columns_as_attributes(): void static::assertXmlStringEqualsXmlString( 'Norbert', - $encoder->encode([new TypedRowValues(['_id' => 1, 'name' => 'Norbert'], [ - '_id' => type_integer(), - 'name' => type_string(), - ])])[0], + $encoder->encode(array_to_rows( + [['_id' => 1, 'name' => 'Norbert']], + schema(int_schema('_id'), str_schema('name')), + ))[0], ); } @@ -72,9 +68,9 @@ public function test_encodes_date_with_the_date_format(): void static::assertXmlStringEqualsXmlString( '2024-08-01', - $encoder->encode([new TypedRowValues(['at' => new DateTimeImmutable('2024-08-01 10:00:00')], [ - 'at' => type_date(), - ])])[0], + $encoder->encode(array_to_rows([[ + 'at' => new DateTimeImmutable('2024-08-01 10:00:00'), + ]], schema(date_schema('at'))))[0], ); } @@ -84,9 +80,9 @@ public function test_encodes_datetime_with_the_configured_format(): void static::assertXmlStringEqualsXmlString( '2024-08-01', - $encoder->encode([new TypedRowValues(['at' => new DateTimeImmutable('2024-08-01 10:00:00')], [ - 'at' => type_datetime(), - ])])[0], + $encoder->encode(array_to_rows([[ + 'at' => new DateTimeImmutable('2024-08-01 10:00:00'), + ]], schema(datetime_schema('at'))))[0], ); } @@ -96,7 +92,7 @@ public function test_encodes_time_as_microseconds(): void static::assertXmlStringEqualsXmlString( '3600000000', - $encoder->encode([new TypedRowValues(['d' => new DateInterval('PT1H')], ['d' => type_time()])])[0], + $encoder->encode(array_to_rows([['d' => new DateInterval('PT1H')]], schema(time_schema('d'))))[0], ); } @@ -106,9 +102,9 @@ public function test_encodes_enum_as_its_name(): void static::assertXmlStringEqualsXmlString( 'one', - $encoder->encode([new TypedRowValues(['e' => BackedIntEnum::one], [ - 'e' => type_enum(BackedIntEnum::class), - ])])[0], + $encoder->encode(array_to_rows([[ + 'e' => BackedIntEnum::one, + ]], schema(enum_schema('e', BackedIntEnum::class))))[0], ); } @@ -116,9 +112,9 @@ public function test_encodes_a_timezone_as_its_iana_name(): void { static::assertXmlStringEqualsXmlString( 'Europe/Warsaw', - (new XMLEncoder(new DOMDocumentWriter()))->encode([new TypedRowValues([ + (new XMLEncoder(new DOMDocumentWriter()))->encode(array_to_rows([[ 'tz' => new DateTimeZone('Europe/Warsaw'), - ], ['tz' => type_time_zone()])])[0], + ]], schema(time_zone_schema('tz'))))[0], ); } @@ -128,9 +124,9 @@ public function test_encodes_uuid_as_string(): void static::assertXmlStringEqualsXmlString( 'f47ac10b-58cc-4372-a567-0e02b2c3d479', - $encoder->encode([new TypedRowValues(['id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')], [ - 'id' => type_uuid(), - ])])[0], + $encoder->encode(array_to_rows([[ + 'id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), + ]], schema(uuid_schema('id'))))[0], ); } @@ -140,7 +136,10 @@ public function test_encodes_list_into_element_nodes(): void static::assertXmlStringEqualsXmlString( 'ab', - $encoder->encode([new TypedRowValues(['tags' => ['a', 'b']], ['tags' => type_list(type_string())])])[0], + $encoder->encode(array_to_rows([['tags' => [ + 'a', + 'b', + ]]], schema(list_schema('tags', type_list(type_string())))))[0], ); } @@ -150,10 +149,9 @@ public function test_encodes_map_into_key_value_element_nodes(): void static::assertXmlStringEqualsXmlString( 'x1', - $encoder->encode([new TypedRowValues(['m' => ['x' => 1]], ['m' => type_map( - type_string(), - type_integer(), - )])])[0], + $encoder->encode(array_to_rows([['m' => [ + 'x' => 1, + ]]], schema(map_schema('m', type_map(type_string(), type_integer())))))[0], ); } @@ -163,10 +161,10 @@ public function test_encodes_structure_into_nested_nodes(): void static::assertXmlStringEqualsXmlString( '

      Krakow31-021
      ', - $encoder->encode([new TypedRowValues(['address' => [ + $encoder->encode(array_to_rows([['address' => [ 'city' => 'Krakow', 'zip' => '31-021', - ]], ['address' => type_structure(['city' => type_string(), 'zip' => type_string()])])])[0], + ]]], schema(structure_schema('address', type_structure(['city' => type_string(), 'zip' => type_string()])))))[0], ); } @@ -179,10 +177,12 @@ public function test_encoding_structure_with_optional_elements_throws(): void 'XML encoder does not support structure optional elements, given: structure{city: string, zip?: string}', ); - $encoder->encode([new TypedRowValues(['address' => ['city' => 'Krakow']], ['address' => type_structure([ + $encoder->encode(array_to_rows([['address' => [ + 'city' => 'Krakow', + ]]], schema(structure_schema('address', type_structure([ 'city' => type_string(), 'zip' => structure_element('zip', type_string(), optional: true), - ])])]); + ]))))); } public function test_encoding_structure_with_an_interleaved_optional_element_throws(): void @@ -194,26 +194,12 @@ public function test_encoding_structure_with_an_interleaved_optional_element_thr 'XML encoder does not support structure optional elements, given: structure{zip?: string, city: string}', ); - $encoder->encode([new TypedRowValues(['address' => ['city' => 'Krakow']], ['address' => type_structure([ + $encoder->encode(array_to_rows([['address' => [ + 'city' => 'Krakow', + ]]], schema(structure_schema('address', type_structure([ 'zip' => structure_element('zip', type_string(), optional: true), 'city' => type_string(), - ])])]); - } - - public function test_encoding_structure_with_more_values_than_declared_elements_throws(): void - { - $encoder = new XMLEncoder(new DOMDocumentWriter()); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'XML encoder received 3 values for structure "structure{city: string, zip: string}" which declares 2 elements', - ); - - $encoder->encode([new TypedRowValues(['address' => [ - 'city' => 'Krakow', - 'zip' => '31-021', - 'extra' => 'lost', - ]], ['address' => type_structure(['city' => type_string(), 'zip' => type_string()])])]); + ]))))); } public function test_encodes_null_scalar_as_an_empty_node(): void @@ -222,7 +208,7 @@ public function test_encodes_null_scalar_as_an_empty_node(): void static::assertXmlStringEqualsXmlString( '', - $encoder->encode([new TypedRowValues(['name' => null], ['name' => type_string()])])[0], + $encoder->encode(array_to_rows([['name' => null]], schema(str_schema('name', nullable: true))))[0], ); } @@ -232,7 +218,7 @@ public function test_uses_the_configured_row_element_name(): void static::assertXmlStringEqualsXmlString( '1', - $encoder->encode([new TypedRowValues(['id' => 1], ['id' => type_integer()])])[0], + $encoder->encode(array_to_rows([['id' => 1]], schema(int_schema('id'))))[0], ); } } diff --git a/src/core/etl/src/Flow/ETL/Config.php b/src/core/etl/src/Flow/ETL/Config.php index 252e96e60b..d58a9aafaf 100644 --- a/src/core/etl/src/Flow/ETL/Config.php +++ b/src/core/etl/src/Flow/ETL/Config.php @@ -15,7 +15,6 @@ use Flow\ETL\Config\Sort\ExternalSortConfig; use Flow\ETL\Config\Sort\MemorySortConfig; use Flow\ETL\Config\Telemetry\TelemetryConfig; -use Flow\ETL\Row\Hydrator; use Flow\Serializer\Serializer; use Psr\Clock\ClockInterface; @@ -27,9 +26,6 @@ { private Planner $planner; - /** - * @param Hydrator $hydrator - */ public function __construct( private string $id, private string $name, @@ -38,7 +34,6 @@ public function __construct( private ClockInterface $clock, private Optimizer $optimizer, private Executor $executor, - private Hydrator $hydrator, public CacheConfig $cache, public MemorySortConfig|ExternalSortConfig $sort, private ?Analyze $analyze, @@ -88,14 +83,6 @@ public function executor(): Executor return $this->executor; } - /** - * @return Hydrator - */ - public function hydrator(): Hydrator - { - return $this->hydrator; - } - public function id(): string { return $this->id; diff --git a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php index 76788fabb6..2571467a1a 100644 --- a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php @@ -25,7 +25,6 @@ use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\Optimizer; use Flow\ETL\RandomValueGenerator; -use Flow\ETL\Row\PhpRowHydrator; use Flow\Filesystem\Path; use Flow\Floe\FloeSerializer; use Flow\Serializer\Serializer; @@ -108,9 +107,7 @@ public function build(): Config $id = $this->id ??= 'flow-php-' . $this->randomValueGenerator->string(32); $this->optimizer ??= Optimizer::default(); $this->executor ??= new Executor(); - $hydrator = new PhpRowHydrator($this->backend); - // the default serializer shares the context hydrator - one source of Row objects - $this->serializer ??= new FloeSerializer(hydrator: $hydrator); + $this->serializer ??= new FloeSerializer(backend: $this->backend); $serializer = $this->serializer; $optimizer = $this->optimizer; @@ -127,7 +124,6 @@ public function build(): Config $this->getClock(), $optimizer, $executor, - $hydrator, $cacheConfig, ($this->sort ?? new ExternalSortBuilder())->build($cacheConfig->localFilesystemCacheDir), $this->analyze, diff --git a/src/core/etl/src/Flow/ETL/Exception/InferredSchemaException.php b/src/core/etl/src/Flow/ETL/Exception/InferredSchemaException.php index 2603d00223..743bf6c26d 100644 --- a/src/core/etl/src/Flow/ETL/Exception/InferredSchemaException.php +++ b/src/core/etl/src/Flow/ETL/Exception/InferredSchemaException.php @@ -46,7 +46,7 @@ public static function filesDiverge(string $source, string $readFrom, Validation { return new self(sprintf( "Columns of %s do not match the schema read from %s:\n%sRead the files as one wider schema with " - . '->unionByName(), or declare the schema with ->withSchema(...).', + . '->unionByName().', $source, $readFrom, $validation->toString(), diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php index 4bba4d0e2e..8a0ff089b6 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php @@ -12,7 +12,7 @@ use Flow\ETL\Schema; use Generator; -use function count; +use function array_shift; final class BatchByExtractor implements Extractor, OverridingExtractor, RewindableExtractor { @@ -48,38 +48,57 @@ public function extract(FlowContext $context, ?int $limit = null): Generator // it - a buffer spans child batches, so its rows must all answer to one schema before trusted() $schema = $this->schema; - $buffer = []; + /** @var list $pending */ + $pending = []; + $pendingCount = 0; $currentGroupValue = null; foreach ($this->extractor->extract($context) as $rows) { $schema ??= $rows->schema(); $rows = $rows->matchTo($schema); - foreach ($rows->all() as $row) { - $groupValue = $row->get($this->column); + if ($rows->count() === 0) { + continue; + } + + $column = $rows->column($this->column->base()); + $start = 0; + + for ($i = 0; $i < $rows->count(); $i++) { + // @mago-ignore analysis:mixed-assignment + $groupValue = $column->value($i); if ($currentGroupValue === null) { + // @mago-ignore analysis:mixed-assignment $currentGroupValue = $groupValue; } elseif ($currentGroupValue !== $groupValue) { - if ($this->minSize === null || count($buffer) >= $this->minSize) { - $signal = yield Rows::of($schema, ...$buffer); + if ($this->minSize === null || ($pendingCount + $i - $start) >= $this->minSize) { + $pending[] = $rows->slice($start, $i - $start); + $first = array_shift($pending); + $signal = yield $first->concat(...$pending); if ($signal === Signal::STOP) { return; } - $buffer = []; + $pending = []; + $pendingCount = 0; + $start = $i; } + // @mago-ignore analysis:mixed-assignment $currentGroupValue = $groupValue; } - - $buffer[] = $row; } + + $pending[] = $rows->slice($start, $rows->count() - $start); + $pendingCount += $rows->count() - $start; } - if (count($buffer) > 0) { - yield Rows::of($schema ?? $this->schema(), ...$buffer); + $first = array_shift($pending); + + if ($first !== null && $pendingCount > 0) { + yield $first->concat(...$pending); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/FileConstants.php b/src/core/etl/src/Flow/ETL/Extractor/FileConstants.php index 51170cfa61..629f57301e 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FileConstants.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FileConstants.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Extractor; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -45,7 +44,7 @@ public function fill(array $row): array * fill() over a batch the reader already matched to the file's body schema, adopting $declared - the schema * FileColumns::declare() built over that body schema. A batch with nothing to add is returned as it is. */ - public function fillRows(Rows $rows, Schema $declared, Backend $backend = new DefaultBackend()): Rows + public function fillRows(Rows $rows, Schema $declared, Backend $backend): Rows { if ($this->uri === null && $this->partitionNames === []) { return $rows; diff --git a/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php b/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php index a917981dc5..035ff4b353 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php +++ b/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php @@ -36,7 +36,7 @@ public function samples(int $rowBudget): iterable /** * The same ColumnName normalisation array_to_rows() applies, so the fold's names are the - * hydrator's names. + * batch builder's names. * * @return Generator */ diff --git a/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php b/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php index 27772816f5..866d872cf0 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php +++ b/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php @@ -83,32 +83,6 @@ private function derivedFooters(Generator $files, bool $unionByName): FooterStat return $this->derivedFooters ?? new FooterStatistics(new Statistics(), 0); } - /** - * The same footers without deriving a schema, for a read whose schema was declared: nothing else opens them. - * - * @param Generator $files an unstarted generator - */ - private function footers(Generator $files, bool $unionByName): FooterStatistics - { - $statistics = new Statistics(rows: Cardinality::exact(0), size: Cardinality::exact(0)); - $read = 0; - - foreach ($files as $file) { - try { - $statistics = $statistics->merge($file->statistics()); - $read++; - } finally { - $file->close(); - } - - if (!$unionByName) { - break; - } - } - - return new FooterStatistics($statistics, $read); - } - /** * @return array */ diff --git a/src/core/etl/src/Flow/ETL/FlowContext.php b/src/core/etl/src/Flow/ETL/FlowContext.php index a81c12f6fc..cf5ca9d0f3 100644 --- a/src/core/etl/src/Flow/ETL/FlowContext.php +++ b/src/core/etl/src/Flow/ETL/FlowContext.php @@ -8,7 +8,6 @@ use Flow\ETL\Column\Backend; use Flow\ETL\Config\Telemetry\TelemetryContext; use Flow\ETL\ErrorHandler\ThrowError; -use Flow\ETL\Row\Hydrator; /** * Mutable Flow execution context. @@ -46,14 +45,6 @@ public function backend(): Backend return $this->config->backend(); } - /** - * @return Hydrator - */ - public function hydrator(): Hydrator - { - return $this->config->hydrator(); - } - public function setErrorHandler(ErrorHandler $handler): self { $this->errorHandler = $handler; diff --git a/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php b/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php index bfbe0c831e..6657b445f1 100644 --- a/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php +++ b/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php @@ -8,7 +8,6 @@ use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Filesystem\Partitions; @@ -16,7 +15,6 @@ use function array_flip; use function array_keys; -use function array_values; use function implode; use function sprintf; @@ -61,18 +59,18 @@ public function route(Rows $rows): Generator $hashes = $this->hasher->hash((new KeyValues($this->partitioning->by->all()))->of($rows)); - /** @var array}> $groups */ + /** @var array}> $groups */ $groups = []; - foreach (array_values($rows->all()) as $index => $row) { - $groups[$hashes[$index]] ??= [$this->rowPartitions->of($row, $schema), []]; - $groups[$hashes[$index]][1][] = $row; + foreach ($hashes as $index => $hash) { + $groups[$hash] ??= [$this->rowPartitions->of($rows, $index), []]; + $groups[$hash][1][] = $index; } $stripped = $this->dropped === [] ? $schema : $schema->gracefulRemove(...$this->partitioning->by->names()); - foreach ($groups as [$partitions, $rowsOfGroup]) { - $group = Rows::of($schema, ...$rowsOfGroup); + foreach ($groups as [$partitions, $indices]) { + $group = $rows->gather($indices); yield [$partitions, $this->dropped === [] ? $group : $group->project($stripped)]; } diff --git a/src/core/etl/src/Flow/ETL/Loader/RowPartitions.php b/src/core/etl/src/Flow/ETL/Loader/RowPartitions.php index 73a39e6d4b..c8f827c4bc 100644 --- a/src/core/etl/src/Flow/ETL/Loader/RowPartitions.php +++ b/src/core/etl/src/Flow/ETL/Loader/RowPartitions.php @@ -4,9 +4,8 @@ namespace Flow\ETL\Loader; -use Flow\ETL\Row; use Flow\ETL\Row\References; -use Flow\ETL\Schema; +use Flow\ETL\Rows; use Flow\Filesystem\Partition; use Flow\Filesystem\Partitions; @@ -16,18 +15,19 @@ public function __construct( private References $by, ) {} - public function of(Row $row, Schema $schema): Partitions + public function of(Rows $rows, int $index): Partitions { $partitions = []; foreach ($this->by as $reference) { - $value = $row->get($reference); + // @mago-ignore analysis:mixed-assignment + $value = $rows->column($reference->base())->value($index); $partitions[] = new Partition( $reference->name(), $value === null ? null - : Partition::fromValue($reference->name(), $schema->get($reference)->type(), $value), + : Partition::fromValue($reference->name(), $rows->schema()->get($reference)->type(), $value), ); } diff --git a/src/core/etl/src/Flow/ETL/Row/Encoder.php b/src/core/etl/src/Flow/ETL/Row/Encoder.php deleted file mode 100644 index 0cab32540f..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/Encoder.php +++ /dev/null @@ -1,25 +0,0 @@ - $batch - * - * @return list - */ - public function encode(array $batch): array; - - /** - * @param list $batch - * - * @return list - */ - public function decode(array $batch): array; -} diff --git a/src/core/etl/src/Flow/ETL/Row/Hydrator.php b/src/core/etl/src/Flow/ETL/Row/Hydrator.php deleted file mode 100644 index 9c1861d866..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/Hydrator.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ - public function dehydrate(Rows $rows): array; - - /** - * @param list $batch - * - * @throws SchemaMismatchException - */ - public function hydrate(array $batch, Schema $schema): Rows; -} diff --git a/src/core/etl/src/Flow/ETL/Row/PhpRowHydrator.php b/src/core/etl/src/Flow/ETL/Row/PhpRowHydrator.php deleted file mode 100644 index 664868c543..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/PhpRowHydrator.php +++ /dev/null @@ -1,71 +0,0 @@ -schema()->definitions() as $definition) { - $name = $definition->entry()->name(); - $values[$name] = $rows->column($name)->values(); - $types[$name] = $definition->type(); - - if (!$definition->metadata()->isEmpty()) { - $metadata[$name] = $definition->metadata(); - } - } - - $batch = []; - - for ($i = 0, $count = $rows->count(); $i < $count; $i++) { - $row = []; - - foreach ($values as $name => $column) { - $row[$name] = $column[$i]; - } - - $batch[] = new TypedRowValues($row, $types, $metadata); - } - - return $batch; - } - - public function hydrate(array $batch, Schema $schema): Rows - { - // metadata belongs to the column, so it is folded into the schema once - a per-row divergent Metadata is - // no longer representable - foreach ($batch as $rowValues) { - foreach ($rowValues->metadata as $name => $metadata) { - // PHP casts a numeric array key to int, column names are always strings - $name = (string) $name; - - if ($schema->findDefinition($name) !== null) { - $schema = $schema->setMetadata($name, $metadata); - } - } - } - - return (new RowsBuilder($schema, $this->backend)) - ->appendRows(array_map(static fn(RawRowValues $row): array => $row->values, $batch)) - ->finish(); - } -} diff --git a/src/core/etl/src/Flow/ETL/Row/RowsBuffer.php b/src/core/etl/src/Flow/ETL/Row/RowsBuffer.php deleted file mode 100644 index f9487800de..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/RowsBuffer.php +++ /dev/null @@ -1,75 +0,0 @@ -): Rows - */ - private readonly Closure $batch; - - /** - * @var list - */ - private array $rows = []; - - /** - * @param int<1, max> $size - * @param null|Closure(Schema, list): Rows $batch builds each released batch; null uses Rows::of() - */ - public function __construct( - private readonly Schema $schema, - private readonly int $size, - ?Closure $batch = null, - ) { - // @mago-ignore analysis:invalid-operand - // @mago-ignore analysis:impossible-condition,redundant-comparison - if ($this->size < 1) { - throw new InvalidArgumentException('Buffer size must be greater than 0, given: ' . $this->size); - } - - $this->batch = - $batch ?? - /** - * @param list $rows - */ - static fn(Schema $schema, array $rows): Rows => Rows::of($schema, ...$rows); - } - - public function add(Row $row): ?Rows - { - $this->rows[] = $row; - - if (count($this->rows) < $this->size) { - return null; - } - - return $this->flush(); - } - - public function flush(): ?Rows - { - if ($this->rows === []) { - return null; - } - - $batch = ($this->batch)($this->schema, $this->rows); - $this->rows = []; - - return $batch; - } -} diff --git a/src/core/etl/src/Flow/ETL/Row/TypedRowValues.php b/src/core/etl/src/Flow/ETL/Row/TypedRowValues.php deleted file mode 100644 index 88cd6db06b..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/TypedRowValues.php +++ /dev/null @@ -1,22 +0,0 @@ - $values - * @param array> $types - * @param array $metadata - */ - public function __construct( - public array $values, - public array $types, - public array $metadata = [], - ) {} -} diff --git a/src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php b/src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php new file mode 100644 index 0000000000..eb29710ffa --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php @@ -0,0 +1,79 @@ + $size + */ + public function __construct( + private readonly Schema $schema, + private readonly Backend $backend, + private readonly int $size, + ) { + // @mago-ignore analysis:invalid-operand + // @mago-ignore analysis:impossible-condition,redundant-comparison + if ($this->size < 1) { + throw new InvalidArgumentException('Buffer size must be greater than 0, given: ' . $this->size); + } + + $this->builder = new RowsBuilder($this->schema, $this->backend); + } + + /** + * @param array $row + * + * @throws SchemaMismatchException + */ + public function append(array $row): ?Rows + { + $this->builder->append($row); + + return $this->builder->count() >= $this->size ? $this->flush() : null; + } + + /** + * @throws SchemaMismatchException + */ + public function appendFrom(Rows $rows, int $i): ?Rows + { + $this->builder->appendFrom($rows, $i); + + return $this->builder->count() >= $this->size ? $this->flush() : null; + } + + /** + * A take that overshoots the size is released whole. + * + * @param list $indices + */ + public function appendTake(Rows $rows, array $indices): ?Rows + { + $this->builder->appendTake($rows, $indices); + + return $this->builder->count() >= $this->size ? $this->flush() : null; + } + + public function flush(): ?Rows + { + if ($this->builder->count() === 0) { + return null; + } + + $batch = $this->builder->finish(); + $this->builder = new RowsBuilder($this->schema, $this->backend); + + return $batch; + } +} diff --git a/src/core/etl/src/Flow/ETL/Schema/Inference/ColumnTypes.php b/src/core/etl/src/Flow/ETL/Schema/Inference/ColumnTypes.php index fee2112843..d35acbe5da 100644 --- a/src/core/etl/src/Flow/ETL/Schema/Inference/ColumnTypes.php +++ b/src/core/etl/src/Flow/ETL/Schema/Inference/ColumnTypes.php @@ -92,7 +92,7 @@ public function merge(self $other, bool $unionByName): self } /** - * RawRowValues::$metadata is not read: the fold types columns, metadata is folded by the hydrator per batch. + * RawRowValues::$metadata is not read: the fold types columns. */ public function observe(RawRowValues $row): void { diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php index 75c4052912..c21860c42e 100644 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php +++ b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php @@ -5,10 +5,11 @@ namespace Flow\ETL\Sort\Merge; use Flow\ETL\Bucketing\BucketRun; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Row\References; -use Flow\ETL\Row\RowsBuffer; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuffer; use Flow\ETL\Schema; use Generator; @@ -52,12 +53,12 @@ public function merge(array $runs): Generator } } - $buffer = new RowsBuffer($schema ?? new Schema(), $this->batchSize); + $buffer = new RowsBuffer($schema ?? new Schema(), new PhpBackend(), $this->batchSize); while (!$heap->isEmpty()) { $top = $heap->extract(); - if (null !== ($batch = $buffer->add($top->row))) { + if (null !== ($batch = $buffer->appendFrom($top->row->rows, $top->row->index))) { yield $batch; } diff --git a/src/core/etl/src/Flow/Floe/FloeEncoder.php b/src/core/etl/src/Flow/Floe/FloeEncoder.php index 01fcea9d23..01cdb2c022 100644 --- a/src/core/etl/src/Flow/Floe/FloeEncoder.php +++ b/src/core/etl/src/Flow/Floe/FloeEncoder.php @@ -5,33 +5,27 @@ namespace Flow\Floe; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Row\Encoder; -use Flow\ETL\Row\Hydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Floe\Exception\FloeException; -/** - * @extends Encoder - */ -interface FloeEncoder extends Encoder +interface FloeEncoder { /** - * `$hydrator->hydrate($this->decode($bodies), $schema)`, in one native pass where the hydrator is native too. + * `RowsBuilder` over `decode()`. * * @param list $bodies * * @throws FloeException * @throws SchemaMismatchException */ - public function decodeRows(array $bodies, Schema $schema, Hydrator $hydrator): Rows; + public function decodeRows(array $bodies, Schema $schema): Rows; /** - * `Format::rowFrames($this->encode($hydrator->dehydrate($rows)))`, in one native pass where the hydrator is native - * too - complete ROW frames for a writer whose codec leaves bodies as they are. + * `Format::rowFrames($this->encode($rows))`. * * @throws FloeException * @throws SchemaMismatchException */ - public function encodeFrames(Rows $rows, Hydrator $hydrator): string; + public function encodeFrames(Rows $rows): string; } diff --git a/src/core/etl/src/Flow/Floe/FloeExtractor.php b/src/core/etl/src/Flow/Floe/FloeExtractor.php index 1147b82d9d..0519eaf794 100644 --- a/src/core/etl/src/Flow/Floe/FloeExtractor.php +++ b/src/core/etl/src/Flow/Floe/FloeExtractor.php @@ -4,6 +4,8 @@ namespace Flow\Floe; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; @@ -16,7 +18,6 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; -use Flow\ETL\Row\Hydrator; use Flow\ETL\Schema; use Flow\ETL\Schema\Validator\StrictValidator; use Flow\Filesystem\Filesystem; @@ -37,8 +38,6 @@ final class FloeExtractor implements MetadataColumnsExtractor, RewindableExtractor { - private ?Schema $schema = null; - use Batches; use FileReading; @@ -81,14 +80,13 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi { $fileOffset = $this->offset ?? 0; $yielded = 0; - $promisedSchema = $this->schema === null ? null : $this->schema(); - // undeclared, every file is read under the first file's schema, or the union of all of them - $expected = $this->schema === null ? $this->derivedSchema($this->files(), $this->unionByName) : null; - $target = $promisedSchema ?? $this->schema(); + // every file is read under the first file's schema, or the union of all of them + $expected = $this->derivedSchema($this->files(), $this->unionByName); + $target = $this->schema(); $fileColumns = $this->fileColumns($this->filesystem, $this->path); - foreach ($this->files($context->hydrator(), $pathFilter) as $file) { + foreach ($this->files($context->backend(), $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 { @@ -100,7 +98,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi continue; } - if ($expected !== null && !$this->unionByName) { + if (!$this->unionByName) { $validation = (new StrictValidator())->validate($expected, $file->schema()); if (!$validation->isValid()) { @@ -113,15 +111,14 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi } // R6: over the FILE's schema, never over schema()'s output - $fileSchema = $fileColumns->declare($this->schema ?? $file->schema()); + $fileSchema = $fileColumns->declare($file->schema()); $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); + $matchTo = !$fileSchema->isSame($target) ? $target : null; $remaining = $limit === null ? null : $limit - $yielded; foreach ($file->reader->rows($this->batchSize(), $fileOffset, $remaining) as $rows) { - // R7: the stamp stays post-hydration - FloeStreamReader::rows() yields hydrated Rows and - // must not learn about paths - but the constants are the shared ones, already typed + // R7: the stamp stays after decoding - FloeStreamReader::rows() yields built Rows and must not + // learn about paths - but the constants are the shared ones, already typed $rows = $constants->fillRows($rows, $fileSchema, $context->backend()); if ($matchTo !== null) { @@ -154,9 +151,10 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi */ public function schema(): Schema { - return $this->fileColumns($this->filesystem, $this->path)->declare( - $this->schema ?? $this->derivedSchema($this->files(), $this->unionByName), - ); + return $this->fileColumns($this->filesystem, $this->path)->declare($this->derivedSchema( + $this->files(), + $this->unionByName, + )); } public function statistics(): Statistics @@ -178,7 +176,7 @@ public function unionByName(bool $union = true): self public function partitionSchema(): Schema { - return $this->fileColumns($this->filesystem, $this->path)->partitions($this->schema ?? new Schema()); + return $this->fileColumns($this->filesystem, $this->path)->partitions(new Schema()); } public function source(): Path @@ -204,17 +202,16 @@ public function withOffset(int $offset): self */ private function declare(): Statistics { - $footers = $this->schema === null - ? $this->derivedFooters($this->files(), $this->unionByName) - : $this->footers($this->files(), $this->unionByName); - - return $footers->of(iterator_count($this->sourceFiles($this->filesystem, $this->path)), $this->offset ?? 0); + return $this->derivedFooters($this->files(), $this->unionByName)->of( + iterator_count($this->sourceFiles($this->filesystem, $this->path)), + $this->offset ?? 0, + ); } /** * @return Generator */ - private function files(?Hydrator $hydrator = null, Filter $pathFilter = new OnlyFiles()): Generator + private function files(Backend $backend = new DefaultBackend(), Filter $pathFilter = new OnlyFiles()): Generator { foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { yield new FloeSourceFile( @@ -222,7 +219,7 @@ private function files(?Hydrator $hydrator = null, Filter $pathFilter = new Only $this->filesystem, $this->codec, $this->chunkSize, - hydrator: $hydrator, + backend: $backend, ))->read($source->path), $source, ); @@ -231,8 +228,8 @@ private function files(?Hydrator $hydrator = null, Filter $pathFilter = new Only public function withSchema(Schema $schema): static { - $this->schema = $schema; - - return $this; + throw new InvalidArgumentException( + 'Floe is a self-describing format and does not accept a schema; declaring one is not supported yet.', + ); } } diff --git a/src/core/etl/src/Flow/Floe/FloeLoader.php b/src/core/etl/src/Flow/Floe/FloeLoader.php index 5fd2516052..735a301653 100644 --- a/src/core/etl/src/Flow/Floe/FloeLoader.php +++ b/src/core/etl/src/Flow/Floe/FloeLoader.php @@ -125,7 +125,7 @@ public function load(Rows $rows, FlowContext $context): void $partitions->toArray(), ); - ($this->writers[$stream->path()->uri()] ??= $this->openWriter($stream, $context))->write($group); + ($this->writers[$stream->path()->uri()] ??= $this->openWriter($stream))->write($group); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); @@ -155,7 +155,7 @@ private function closeWriters(): void } } - private function openWriter(DestinationStream $stream, FlowContext $context): FloeWriter + private function openWriter(DestinationStream $stream): FloeWriter { $declared = $this->schema @@ -170,7 +170,6 @@ private function openWriter(DestinationStream $stream, FlowContext $context): Fl $this->filesystem, $declared->gracefulRemove(...$this->router->droppedNames()), $this->options, - hydrator: $context->hydrator(), ); $writer->createForStream($stream, $this->metadata); diff --git a/src/core/etl/src/Flow/Floe/FloeMerger.php b/src/core/etl/src/Flow/Floe/FloeMerger.php index 29b46851b5..50ae228001 100644 --- a/src/core/etl/src/Flow/Floe/FloeMerger.php +++ b/src/core/etl/src/Flow/Floe/FloeMerger.php @@ -4,7 +4,8 @@ namespace Flow\Floe; -use Flow\ETL\Row\Hydrator; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; use Flow\ETL\Schema\Validator\EvolvingValidator; @@ -22,7 +23,7 @@ public function __construct( private Filesystem $filesystem, - private ?Hydrator $hydrator = null, + private Backend $backend = new DefaultBackend(), private Codec $codec = new NoopCodec(), ) { Format::validateCodecId($this->codec->id()); @@ -45,9 +46,6 @@ public function merge(array $sources, Path $dest, bool $compact = false, ?Metada $metadata ??= Metadata::empty(); - // a merged file carries exactly one schema; raw splicing is only valid when every - // source already shares it - differing (but compatible) schemas are re-encoded to - // the union, exactly as compaction does if ($compact || !$this->sourcesShareSchema($reconciled['layouts'], $reconciled['merged'])) { $this->mergeCompact($sources, $reconciled['layouts'], $reconciled['merged'], $dest, $metadata); @@ -144,15 +142,10 @@ private function mergeCompact(array $sources, array $layouts, ?Schema $merged, P $mergedMetadata = $mergedMetadata->merge($layout['footer']->metadata); } - $writer = new FloeWriter( - $this->filesystem, - $merged ?? new Schema(), - new Options(codec: $this->codec), - hydrator: $this->hydrator, - ); + $writer = new FloeWriter($this->filesystem, $merged ?? new Schema(), new Options(codec: $this->codec)); $writer->create($dest, $mergedMetadata->merge($metadata)); - $reader = new FloeReader($this->filesystem, $this->codec, hydrator: $this->hydrator); + $reader = new FloeReader($this->filesystem, $this->codec, backend: $this->backend); foreach ($sources as $source) { $streamReader = $reader->read($source); diff --git a/src/core/etl/src/Flow/Floe/FloeReader.php b/src/core/etl/src/Flow/Floe/FloeReader.php index aa47277a66..43c167f86b 100644 --- a/src/core/etl/src/Flow/Floe/FloeReader.php +++ b/src/core/etl/src/Flow/Floe/FloeReader.php @@ -4,7 +4,8 @@ namespace Flow\Floe; -use Flow\ETL\Row\Hydrator; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; use Flow\Floe\Codec\NoopCodec; @@ -12,14 +13,11 @@ final readonly class FloeReader { - /** - * @param null|Hydrator $hydrator null uses `new PhpRowHydrator()` - */ public function __construct( private Filesystem $filesystem, private Codec $codec = new NoopCodec(), private int $chunkSize = 65536, - private ?Hydrator $hydrator = null, + private Backend $backend = new DefaultBackend(), ) {} /** @@ -27,11 +25,6 @@ public function __construct( */ public function read(Path $path): FloeStreamReader { - return new FloeStreamReader( - $this->filesystem->readFrom($path), - $this->codec, - $this->chunkSize, - $this->hydrator, - ); + return new FloeStreamReader($this->filesystem->readFrom($path), $this->codec, $this->chunkSize, $this->backend); } } diff --git a/src/core/etl/src/Flow/Floe/FloeSerializer.php b/src/core/etl/src/Flow/Floe/FloeSerializer.php index d6ba72fa18..3bbfa3b1d4 100644 --- a/src/core/etl/src/Flow/Floe/FloeSerializer.php +++ b/src/core/etl/src/Flow/Floe/FloeSerializer.php @@ -4,7 +4,8 @@ namespace Flow\Floe; -use Flow\ETL\Row\Hydrator; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Rows; use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; @@ -22,11 +23,10 @@ final class FloeSerializer implements Serializer /** * @param int<1, max> $batchSize - * @param null|Hydrator $hydrator null uses `new PhpRowHydrator()` */ public function __construct( private readonly int $batchSize = 1000, - private readonly ?Hydrator $hydrator = null, + private readonly Backend $backend = new DefaultBackend(), ) { // @mago-ignore analysis:impossible-condition,redundant-comparison if ($this->batchSize < 1) { @@ -38,7 +38,7 @@ public function serialize(Rows $rows, DestinationStream $destination): void { try { // validation stays on until an upstream mechanism guarantees Rows match their schema - $writer = new FloeStreamWriter($rows->schema(), new Options(), hydrator: $this->hydrator); + $writer = new FloeStreamWriter($rows->schema(), new Options()); $writer->create($destination); $writer->write($rows); $writer->close(); @@ -50,7 +50,7 @@ public function serialize(Rows $rows, DestinationStream $destination): void public function unserialize(SourceStream $source): Rows { try { - $reader = new FloeStreamReader($source, new NoopCodec(), self::CHUNK_SIZE, $this->hydrator); + $reader = new FloeStreamReader($source, new NoopCodec(), self::CHUNK_SIZE, $this->backend); $footer = $reader->footer(); diff --git a/src/core/etl/src/Flow/Floe/FloeStreamReader.php b/src/core/etl/src/Flow/Floe/FloeStreamReader.php index c7d1d14174..de2e400a56 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamReader.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamReader.php @@ -4,8 +4,8 @@ namespace Flow\Floe; -use Flow\ETL\Row\Hydrator; -use Flow\ETL\Row\PhpRowHydrator; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -33,21 +33,16 @@ final class FloeStreamReader private ?Schema $schema = null; - private readonly Hydrator $hydrator; - /** - * @param null|Hydrator $hydrator null uses `new PhpRowHydrator()` - * * @throws FloeException */ public function __construct( private readonly SourceStream $source, private readonly Codec $codec, private readonly int $chunkSize, - ?Hydrator $hydrator = null, + private readonly Backend $backend = new DefaultBackend(), ) { Format::validateCodecId($this->codec->id()); - $this->hydrator = $hydrator ?? new PhpRowHydrator(); } public function close(): void @@ -57,7 +52,7 @@ public function close(): void private function encoder(Schema $schema): FloeEncoder { - return $this->encoder ??= new PhpFloeEncoder($schema); + return $this->encoder ??= new PhpFloeEncoder($schema, $this->backend); } /** @@ -261,13 +256,13 @@ private function walk( } /** - * A batch carries the file schema even when the hydrator folded per-value metadata into a schema of its own. + * A batch carries the file schema even when `decodeRows` folded per-value metadata into a schema of its own. * * @param list $pending */ private function decode(Schema $schema, array $pending): Rows { - $rows = $this->encoder($schema)->decodeRows($pending, $schema, $this->hydrator); + $rows = $this->encoder($schema)->decodeRows($pending, $schema); return $rows->schema() === $schema ? $rows : $rows->withSchema($schema); } diff --git a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php index 9620f7ec06..8a74030abc 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php @@ -5,8 +5,6 @@ namespace Flow\Floe; use Composer\InstalledVersions; -use Flow\ETL\Row\Hydrator; -use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -51,25 +49,21 @@ final class FloeStreamWriter private Schema $sessionSchema; - private ?FloeEncoder $sessionEncoder = null; + private ?PhpFloeEncoder $sessionEncoder = null; private ?FrameWriter $frameWriter = null; private int $totalRows = 0; - private readonly Hydrator $hydrator; - /** * @throws FloeException */ public function __construct( Schema $schema, private readonly Options $options = new Options(), - ?Hydrator $hydrator = null, ) { Format::validateCodecId($this->options->codec->id()); $this->sessionSchema = $schema; - $this->hydrator = $hydrator ?? new PhpRowHydrator(); } /** @@ -159,7 +153,7 @@ public function write(Rows $rows): void $matched = $rows->schema()->isSame($this->sessionSchema) ? $rows : $rows->matchTo($this->sessionSchema); if ($this->options->codec instanceof NoopCodec) { - $frames = $this->sessionEncoder()->encodeFrames($matched, $this->hydrator); + $frames = $this->sessionEncoder()->encodeFrames($matched); $this->startSectionWhenDue(); $this->frameWriter()->raw($frames); @@ -169,10 +163,8 @@ public function write(Rows $rows): void return; } - $typed = $this->hydrator->dehydrate($matched); - $this->startSectionWhenDue(); - $this->emitBatch($typed); + $this->emitBatch($this->sessionEncoder()->encode($matched)); } public static function writerVersion(): string @@ -217,13 +209,13 @@ private function assertBatchFitsSession(Schema $batch): void } /** - * @param list<\Flow\ETL\Row\TypedRowValues> $typed + * @param list $bodies * * @throws FloeException */ - private function emitBatch(array $typed): void + private function emitBatch(array $bodies): void { - foreach ($this->sessionEncoder()->encode($typed) as $encoded) { + foreach ($bodies as $encoded) { $this->frameWriter()->row($this->options->codec->encode($encoded)); $this->sectionRowCount++; $this->totalRows++; @@ -284,7 +276,7 @@ private function startSection(): void /** * @throws FloeException */ - private function sessionEncoder(): FloeEncoder + private function sessionEncoder(): PhpFloeEncoder { return $this->sessionEncoder ?? throw new FloeException('Floe writer has no active session encoder'); } diff --git a/src/core/etl/src/Flow/Floe/FloeWriter.php b/src/core/etl/src/Flow/Floe/FloeWriter.php index da3e8cc51b..38bcb7d211 100644 --- a/src/core/etl/src/Flow/Floe/FloeWriter.php +++ b/src/core/etl/src/Flow/Floe/FloeWriter.php @@ -4,7 +4,6 @@ namespace Flow\Floe; -use Flow\ETL\Row\Hydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -21,7 +20,6 @@ final class FloeWriter /** * @param Schema $schema fixes the session schema for the writer's life - * @param null|Hydrator $hydrator null uses `new PhpRowHydrator()` * * @throws FloeException */ @@ -29,9 +27,8 @@ public function __construct( private readonly Filesystem $filesystem, Schema $schema, private readonly Options $options = new Options(), - ?Hydrator $hydrator = null, ) { - $this->inner = new FloeStreamWriter($schema, $this->options, $hydrator); + $this->inner = new FloeStreamWriter($schema, $this->options); } /** diff --git a/src/core/etl/src/Flow/Floe/PhpFloeEncoder.php b/src/core/etl/src/Flow/Floe/PhpFloeEncoder.php index 94bf44aed0..1866df68f0 100644 --- a/src/core/etl/src/Flow/Floe/PhpFloeEncoder.php +++ b/src/core/etl/src/Flow/Floe/PhpFloeEncoder.php @@ -4,17 +4,19 @@ namespace Flow\Floe; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Row\Hydrator; use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; use JsonException; -use function array_key_exists; +use function array_map; use function json_encode; use function ord; use function sprintf; @@ -40,10 +42,18 @@ final class PhpFloeEncoder implements FloeEncoder public function __construct( private readonly Schema $schema, + private readonly Backend $backend = new DefaultBackend(), ) { $this->schemaDecoder = new SchemaDecoder(new ValueDecoder()); } + /** + * @param list $batch + * + * @throws FloeException + * + * @return list + */ public function decode(array $batch): array { $decodePlan = $this->decodePlan ??= $this->schemaDecoder->decode($this->schemaBody()); @@ -83,40 +93,83 @@ public function decode(array $batch): array return $decoded; } - public function decodeRows(array $bodies, Schema $schema, Hydrator $hydrator): Rows + public function decodeRows(array $bodies, Schema $schema): Rows { - return $hydrator->hydrate($this->decode($bodies), $schema); + $batch = $this->decode($bodies); + + // metadata belongs to the column, so it is folded into the schema once - a per-row divergent Metadata is + // no longer representable + foreach ($batch as $rowValues) { + foreach ($rowValues->metadata as $name => $metadata) { + // PHP casts a numeric array key to int, column names are always strings + $name = (string) $name; + + if ($schema->findDefinition($name) !== null) { + $schema = $schema->setMetadata($name, $metadata); + } + } + } + + return (new RowsBuilder($schema, $this->backend)) + ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $batch)) + ->finish(); } - public function encodeFrames(Rows $rows, Hydrator $hydrator): string + public function encodeFrames(Rows $rows): string { - return Format::rowFrames($this->encode($hydrator->dehydrate($rows))); + return Format::rowFrames($this->encode($rows)); } - public function encode(array $batch): array + /** + * @throws FloeException + * @throws SchemaMismatchException + * + * @return list + */ + public function encode(Rows $rows): array { $encoders = $this->encoders ??= $this->buildEncoders(); + /** @var array, bool, Metadata}> $columns */ + $columns = []; + + foreach ($this->schema->definitions() as $name => $definition) { + $own = $rows->schema()->findDefinition($definition->entry()->name()); + + if ($own === null) { + $columns[$name] = null; + + continue; + } + + $metadata = $own->metadata(); + $columnMetadata = $definition->metadata(); + + $columns[$name] = [ + $rows->column($definition->entry()->name())->values(), + $metadata->isEmpty() && $columnMetadata->isEmpty() ? false : !$metadata->isEqual($columnMetadata), + $metadata, + ]; + } + $bodies = []; - foreach ($batch as $rowIndex => $rowValues) { + for ($rowIndex = 0, $count = $rows->count(); $rowIndex < $count; $rowIndex++) { $body = ''; foreach ($this->schema->definitions() as $name => $definition) { - if (!array_key_exists($name, $rowValues->values)) { + $column = $columns[$name]; + + if ($column === null) { throw new FloeException(sprintf( 'Floe found a row that does not carry the declared column "%s"', $name, )); } + [$values, $diverges, $metadata] = $column; // @mago-ignore analysis:mixed-assignment - $value = $rowValues->values[$name]; - $metadata = $rowValues->metadata[$name] ?? Metadata::empty(); - $columnMetadata = $definition->metadata(); - $diverges = $metadata->isEmpty() && $columnMetadata->isEmpty() - ? false - : !$metadata->isEqual($columnMetadata); + $value = $values[$rowIndex]; if ($value === null) { if (!$definition->isNullable()) { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php new file mode 100644 index 0000000000..f2aea2438f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php @@ -0,0 +1,45 @@ +php = new PhpBackend(); + } + + public function builder(Definition $definition): ColumnBuilder + { + $this->builders++; + + return $this->php->builder($definition); + } + + public function builders(): int + { + return $this->builders; + } + + public function constant(Definition $definition, mixed $value, int $count): Column + { + return $this->php->constant($definition, $value, $count); + } + + public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column + { + return $this->php->decode($definition, $buffers, $count, $nullCount); + } +} 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 0839d6b593..f157fed091 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 @@ -15,7 +15,6 @@ use Flow\ETL\Optimizer; use Flow\ETL\Optimizer\Rule\PushLimitIntoSource; use Flow\ETL\Planner; -use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Tests\Double\SpySerializer; use Flow\ETL\Tests\FlowIntegrationTestCase; use Override; @@ -147,11 +146,6 @@ public function test_default_external_sort_builds_filesystem_storage(): void static::assertInstanceOf(FilesystemBuckets::class, $config->sort->bucketing->storage); } - public function test_default_hydrator_is_the_php_hydrator(): void - { - static::assertInstanceOf(PhpRowHydrator::class, config_builder()->build()->hydrator()); - } - public function test_default_sorting_algorithm_is_external_sort(): void { static::assertInstanceOf(ExternalSortConfig::class, config_builder()->build()->sort); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/InferredSchemaExceptionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/InferredSchemaExceptionTest.php index 240db3cc00..6b024e7166 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/InferredSchemaExceptionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/InferredSchemaExceptionTest.php @@ -34,13 +34,13 @@ public function test_columns_diverge_names_the_source_both_diffs_the_knobs_and_b static::assertStringContainsString('infer_schema()->unionByName()', $exception->getMessage()); } - public function test_files_diverge_names_both_files_the_difference_and_both_remedies(): void + public function test_files_diverge_names_both_files_the_difference_and_the_remedy(): void { static::assertSame( "Columns of file:///orders/part-02.parquet do not match the schema read from file:///orders/part-01.parquet:\n" . " Unexpected Definitions: \n" . " |-- extra\n" - . 'Read the files as one wider schema with ->unionByName(), or declare the schema with ->withSchema(...).', + . 'Read the files as one wider schema with ->unionByName().', InferredSchemaException::filesDiverge( 'file:///orders/part-02.parquet', 'file:///orders/part-01.parquet', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php index b1c4edf867..da8e299ace 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php @@ -9,10 +9,12 @@ use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Extractor\Statistics; use Flow\ETL\Memory\ArrayMemory; +use Flow\ETL\Rows; use Flow\ETL\Tests\Double\DeclaringExtractor; use Flow\ETL\Tests\Double\VaryingBatchesExtractor; use PHPUnit\Framework\TestCase; +use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\batched_by; use function Flow\ETL\DSL\config; @@ -41,6 +43,36 @@ public function test_a_group_spanning_child_batches_answers_to_the_first_batch_s static::assertSame([['g' => 1, 'name' => 'a'], ['g' => 1, 'name' => null]], $batches[0]->toArray()); } + public function test_a_group_spanning_two_child_batches_is_one_batch(): void + { + $child = new VaryingBatchesExtractor( + array_to_rows([['g' => 1], ['g' => 1]], schema(int_schema('g'))), + array_to_rows([['g' => 1], ['g' => 2]], schema(int_schema('g'))), + ); + + $batches = iterator_to_array(batched_by($child, ref('g'))->extract(flow_context(config())), false); + + static::assertSame( + [[1, 1, 1], [2]], + array_map(static fn(Rows $rows): array => $rows->reduceToArray('g'), $batches), + ); + } + + public function test_a_group_spanning_two_child_batches_counts_toward_the_min_size(): void + { + $child = new VaryingBatchesExtractor( + array_to_rows([['g' => 1], ['g' => 1]], schema(int_schema('g'))), + array_to_rows([['g' => 1], ['g' => 2]], schema(int_schema('g'))), + ); + + $batches = iterator_to_array(batched_by($child, ref('g'), 3)->extract(flow_context(config())), false); + + static::assertSame( + [[1, 1, 1], [2]], + array_map(static fn(Rows $rows): array => $rows->reduceToArray('g'), $batches), + ); + } + public function test_a_later_child_batch_that_widens_the_shape_is_refused(): void { $child = new VaryingBatchesExtractor( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php index ae52a5ba8c..b70abe3596 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Extractor; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Extractor\FileConstants; use Flow\ETL\Extractor\PartitionColumns; use Flow\ETL\Tests\FlowTestCase; @@ -67,7 +68,7 @@ public function test_fill_rows_returns_a_batch_with_nothing_to_add_as_it_is(): v null, [], [], - ))->fillRows($rows, $rows->schema())); + ))->fillRows($rows, $rows->schema(), new PhpBackend())); } public function test_fill_rows_adds_the_constants_to_every_row_under_the_declared_schema(): void @@ -84,10 +85,14 @@ public function test_fill_rows_adds_the_constants_to_every_row_under_the_declare 'memory://orders/data.csv', ['year' => false], ['year' => 2024], - ))->fillRows(array_to_rows([ - ['name' => 'Norbert'], - ['name' => 'Flow'], - ], schema(str_schema('name'))), $declared), + ))->fillRows( + array_to_rows([ + ['name' => 'Norbert'], + ['name' => 'Flow'], + ], schema(str_schema('name'))), + $declared, + new PhpBackend(), + ), ); } } 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 4065cffa72..95cf322b0e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowContextTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowContextTest.php @@ -58,7 +58,7 @@ public function test_config_constructor_takes_no_filesystem_table(): void $constructor = (new ReflectionClass(Config::class))->getConstructor(); static::assertNotNull($constructor); - static::assertCount(18, $constructor->getParameters()); + static::assertCount(17, $constructor->getParameters()); static::assertSame( [], array_filter( @@ -78,7 +78,6 @@ public function test_flow_context_exposes_no_filesystem_and_no_streams(): void 'calculator', 'errorHandler', 'backend', - 'hydrator', 'setErrorHandler', 'withErrorHandler', 'telemetry', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RowPartitionsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RowPartitionsTest.php index 34eaaea451..368ae9965f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RowPartitionsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/RowPartitionsTest.php @@ -11,7 +11,7 @@ use Flow\Filesystem\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; @@ -55,17 +55,28 @@ public function test_a_scalar_column_becomes_its_formatted_value( ): void { static::assertSame( $expected, - (new RowPartitions(refs(ref('v'))))->of(array_to_row([ - 'v' => $value, - ], schema($definition)), schema($definition))->get('v')->value, + (new RowPartitions(refs(ref('v'))))->of(array_to_rows([['v' => $value]], schema($definition)), 0)->get( + 'v', + )->value, + ); + } + + public function test_an_aliased_partition_reference_reads_its_base_column(): void + { + static::assertSame( + '7', + (new RowPartitions(refs(ref('v')->as('alias'))))->of( + array_to_rows([['v' => 7, 'alias' => 9]], schema(int_schema('v'), int_schema('alias'))), + 0, + )->get('alias')->value, ); } public function test_a_null_value_stays_null(): void { - static::assertNull((new RowPartitions(refs(ref('v'))))->of(array_to_row([ + static::assertNull((new RowPartitions(refs(ref('v'))))->of(array_to_rows([[ 'v' => null, - ], schema(str_schema('v', nullable: true))), schema(str_schema('v', nullable: true)))->get('v')->value); + ]], schema(str_schema('v', nullable: true))), 0)->get('v')->value); } public function test_a_list_column_is_refused(): void @@ -73,10 +84,10 @@ public function test_a_list_column_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('can\'t be used as a partition'); - (new RowPartitions(refs(ref('v'))))->of(array_to_row(['v' => [ + (new RowPartitions(refs(ref('v'))))->of(array_to_rows([['v' => [ 1, 2, - ]], schema(list_schema('v', type_list(type_integer())))), schema(list_schema('v', type_list(type_integer())))); + ]]], schema(list_schema('v', type_list(type_integer())))), 0); } public function test_a_structure_column_is_refused(): void @@ -86,8 +97,8 @@ public function test_a_structure_column_is_refused(): void $structure = type_structure(['a' => type_string()]); - (new RowPartitions(refs(ref('v'))))->of(array_to_row(['v' => $structure->cast([ + (new RowPartitions(refs(ref('v'))))->of(array_to_rows([['v' => $structure->cast([ 'a' => 'x', - ])], schema(structure_schema('v', $structure))), schema(structure_schema('v', $structure))); + ])]], schema(structure_schema('v', $structure))), 0); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/PhpRowHydratorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/PhpRowHydratorTest.php deleted file mode 100644 index a974e8b264..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/PhpRowHydratorTest.php +++ /dev/null @@ -1,571 +0,0 @@ -, class-string<\Throwable>, string}> - */ - public static function refusing_datasets(): Generator - { - yield 'null in a not null column' => [ - schema(int_schema('id'), str_schema('name')), - [new RawRowValues(['id' => 1, 'name' => null])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "name" (row 0): could not convert null to string, column is not nullable', - ]; - - yield 'non numeric string in an integer column' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => 'abc'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 0): could not convert \'abc\' (string) to integer', - ]; - - yield 'trailing garbage after digits in an integer column' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => '12abc'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 0): could not convert \'12abc\' (string) to integer', - ]; - - yield 'hex string in a float column' => [ - schema(float_schema('price')), - [new RawRowValues(['price' => '0x1A'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "price" (row 0): could not convert \'0x1A\' (string) to float', - ]; - - yield 'unrecognised word in a boolean column' => [ - schema(bool_schema('active')), - [new RawRowValues(['active' => 'weird'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "active" (row 0): could not convert \'weird\' (string) to boolean', - ]; - - yield 'array in an integer column' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => [1, 2, 3]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 0): could not convert array (list) to integer', - ]; - - yield 'invalid uuid string' => [ - schema(uuid_schema('u')), - [new RawRowValues(['u' => 'not-a-uuid'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "u" (row 0): could not convert \'not-a-uuid\' (string) to uuid', - ]; - - yield 'uppercase uuid string' => [ - schema(uuid_schema('u')), - [new RawRowValues(['u' => '01234567-89AB-4DEF-8123-456789ABCDEF'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "u" (row 0): could not convert \'01234567-89AB-4DEF-8123-456789AB...\' (string) to uuid', - ]; - - yield 'json from a scalar' => [ - schema(json_schema('j')), - [new RawRowValues(['j' => 5])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "j" (row 0): could not convert 5 (integer) to json', - ]; - - yield 'json from an invalid json string' => [ - schema(json_schema('j')), - [new RawRowValues(['j' => '{oops'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "j" (row 0): could not convert \'{oops\' (string) to json', - ]; - - yield 'json from a plain string' => [ - schema(json_schema('j')), - [new RawRowValues(['j' => 'plain'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "j" (row 0): could not convert \'plain\' (string) to json', - ]; - - yield 'datetime from garbage' => [ - schema(datetime_schema('at')), - [new RawRowValues(['at' => 'not-a-date'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "at" (row 0): could not convert \'not-a-date\' (string) to datetime', - ]; - - yield 'datetime from an array' => [ - schema(datetime_schema('at')), - [new RawRowValues(['at' => ['nope']])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "at" (row 0): could not convert array (list) to datetime', - ]; - - yield 'date from garbage' => [ - schema(date_schema('d')), - [new RawRowValues(['d' => 'not-a-date'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "d" (row 0): could not convert \'not-a-date\' (string) to date', - ]; - - yield 'string map with integer keys' => [ - schema(map_schema('m', type_map(type_string(), type_integer()))), - [new RawRowValues(['m' => [5 => 1]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "m" (row 0): could not convert array (map) to map', - ]; - - yield 'list with non-sequential keys' => [ - schema(list_schema('l', type_list(type_integer()))), - [new RawRowValues(['l' => [1 => 'x']])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert array (map) to list', - ]; - - yield 'positive integer list from a non-numeric string' => [ - schema(list_schema('l', type_list(type_positive_integer()))), - [new RawRowValues(['l' => ['abc']])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', - ]; - - yield 'positive integer list from a negative int' => [ - schema(list_schema('l', type_list(type_positive_integer()))), - [new RawRowValues(['l' => [-3]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', - ]; - - yield 'structure missing required element' => [ - schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), - [new RawRowValues(['data' => ['id' => 1]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer}) to structure{id: integer, name: string}', - ]; - - yield 'structure present-null required element' => [ - schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), - [new RawRowValues(['data' => ['id' => 1, 'name' => null]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer, name: null}) to structure{id: integer, name: string}', - ]; - - yield 'structure present-null optional element' => [ - schema(structure_schema('data', type_structure([ - 'id' => type_integer(), - 'name' => structure_element('name', type_string(), optional: true), - ]))), - [new RawRowValues(['data' => ['id' => 1, 'name' => null]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer, name: null}) to structure{id: integer, name?: string}', - ]; - - // the refusal is placed at the batch position, so a constant row index would diverge here - yield 'non numeric string in the second row of an integer column' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => '1']), new RawRowValues(['id' => 'x'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 1): could not convert \'x\' (string) to integer', - ]; - - yield 'a not null column the row does not carry' => [ - schema(int_schema('id'), str_schema('name')), - [new RawRowValues(['id' => 1])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "name" (row 0) declared by the schema is missing from the row', - ]; - - yield 'integer overflow' => [ - schema(int_schema('id')), - [new RawRowValues(['id' => '9223372036854775808'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "id" (row 0): could not convert \'9223372036854775808\' (string) to integer', - ]; - - yield 'date from an empty string' => [ - schema(date_schema('d')), - [new RawRowValues(['d' => ''])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "d" (row 0): could not convert \'\' (string) to date', - ]; - - yield 'datetime from a relative word' => [ - schema(datetime_schema('at')), - [new RawRowValues(['at' => 'now'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "at" (row 0): could not convert \'now\' (string) to datetime', - ]; - - yield 'string from a null element inside a list' => [ - schema(list_schema('l', type_list(type_string()))), - [new RawRowValues(['l' => ['a', null]])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', - ]; - - yield 'list from a scalar' => [ - schema(list_schema('l', type_list(type_integer()))), - [new RawRowValues(['l' => 5])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "l" (row 0): could not convert 5 (integer) to list', - ]; - - // ordering: an absence must not pre-empt a refusal that PHP reports first, or the two - // hydrators name different columns - and different ROWS - for the same batch - yield 'an absent column before a cast refusal in the same row' => [ - schema(int_schema('a'), int_schema('b')), - [new RawRowValues(['b' => 'abc'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "b" (row 0): could not convert \'abc\' (string) to integer', - ]; - - yield 'an absent column in row 0 before a cast refusal in row 1' => [ - schema(int_schema('a'), int_schema('b')), - [new RawRowValues(['a' => 1]), new RawRowValues(['a' => 1, 'b' => 'abc'])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "b" (row 1): could not convert \'abc\' (string) to integer', - ]; - - yield 'an absent column in row 0 before a present null in row 1' => [ - schema(int_schema('a'), int_schema('b')), - [new RawRowValues(['a' => 1]), new RawRowValues(['a' => 1, 'b' => null])], - SchemaMismatchException::class, - 'Rows do not match their schema: column "b" (row 1): could not convert null to integer, column is not nullable', - ]; - } - - /** - * @param list $batch - * @param class-string<\Throwable> $exception - */ - #[DataProvider('refusing_datasets')] - public function test_refuses(Schema $schema, array $batch, string $exception, string $message): void - { - $this->expectException($exception); - $this->expectExceptionMessage($message); - - (new PhpRowHydrator())->hydrate($batch, $schema); - } - - public function test_absent_schema_column_is_filled_with_typed_null(): void - { - $rows = (new PhpRowHydrator())->hydrate( - [new RawRowValues(['id' => '1'])], - schema(int_schema('id'), str_schema('name', nullable: true)), - ); - - static::assertTrue($rows->first()->has('name')); - static::assertNull($rows->first()->get('name')); - static::assertTrue($rows->schema()->get('name')->isNullable()); - static::assertSame(['id' => 1, 'name' => null], $rows->first()->toArray()); - } - - public function test_refuses_a_definition_outside_the_nineteen(): void - { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage( - 'Row does not match its schema: column "a": throwing cannot be a batch column, only the 19 Flow definitions have a column kind', - ); - - (new PhpRowHydrator())->hydrate([new RawRowValues(['a' => [ - 1, - 2, - ]])], schema(new ForeignTypeDefinition('a', new ThrowingType(new LogicException('stub type refuses everything'))))); - } - - public function test_hydrate_throws_on_missing_required_structure_element(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('Rows do not match their schema: column "data" (row 0)'); - - (new PhpRowHydrator())->hydrate([new RawRowValues(['data' => [ - 'id' => 1, - ]])], schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()])))); - } - - public function test_casts_datetime_and_uuid_strings(): void - { - $rows = (new PhpRowHydrator())->hydrate( - [new RawRowValues([ - 'created_at' => '2024-01-01 12:00:00 UTC', - 'uuid' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479', - ])], - schema(datetime_schema('created_at'), uuid_schema('uuid')), - ); - - $uuid = $rows->first()->get('uuid'); - - static::assertInstanceOf(DateTimeImmutable::class, $rows->first()->get('created_at')); - static::assertInstanceOf(Uuid::class, $uuid); - static::assertSame('f47ac10b-58cc-4372-a567-0e02b2c3d479', $uuid->toString()); - } - - public function test_casts_raw_scalar_strings_to_schema_types(): void - { - $rows = (new PhpRowHydrator())->hydrate( - [new RawRowValues(['id' => '1', 'price' => '9.99', 'active' => 'true', 'name' => 'Alice'])], - schema(int_schema('id'), float_schema('price'), bool_schema('active'), str_schema('name')), - ); - - static::assertSame( - ['id' => 1, 'price' => 9.99, 'active' => true, 'name' => 'Alice'], - $rows->first()->toArray(), - ); - } - - public function test_columns_absent_from_the_schema_are_dropped(): void - { - $rows = (new PhpRowHydrator())->hydrate([new RawRowValues([ - 'id' => '1', - 'extra' => 'raw', - ])], schema(int_schema('id'))); - - static::assertFalse($rows->first()->has('extra')); - static::assertSame(['id' => 1], $rows->first()->toArray()); - } - - public function test_dehydrate_returns_typed_values_keyed_by_entry_name(): void - { - $hydrator = new PhpRowHydrator(); - $schema = schema(int_schema('id'), str_schema('name', nullable: true)); - - $batch = [ - new RawRowValues(['id' => 1, 'name' => 'Alice']), - new RawRowValues(['id' => 2, 'name' => null]), - ]; - - static::assertEquals( - [ - new TypedRowValues(['id' => 1, 'name' => 'Alice'], ['id' => type_integer(), 'name' => type_string()]), - new TypedRowValues(['id' => 2, 'name' => null], ['id' => type_integer(), 'name' => type_string()]), - ], - $hydrator->dehydrate($hydrator->hydrate($batch, $schema)), - ); - } - - public function test_empty_batch_produces_empty_rows(): void - { - static::assertCount(0, (new PhpRowHydrator())->hydrate([], schema(int_schema('id')))); - } - - public function test_hydrate_keeps_native_typed_values(): void - { - $rows = (new PhpRowHydrator())->hydrate( - [ - new RawRowValues(['id' => 1, 'name' => 'Alice']), - new RawRowValues(['id' => 2, 'name' => 'Bob']), - ], - schema(int_schema('id'), str_schema('name')), - ); - - static::assertSame( - [ - ['id' => 1, 'name' => 'Alice'], - ['id' => 2, 'name' => 'Bob'], - ], - $rows->toArray(), - ); - } - - public function test_hydrate_keeps_native_uuid_value_objects(): void - { - $rows = (new PhpRowHydrator())->hydrate([new RawRowValues([ - 'id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), - ])], schema(uuid_schema('id'))); - - $value = $rows->first()->get('id'); - - static::assertInstanceOf(Uuid::class, $value); - static::assertSame('f47ac10b-58cc-4372-a567-0e02b2c3d479', $value->toString()); - } - - public function test_null_value_in_a_non_nullable_column_is_refused(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('Rows do not match their schema: column "name" (row 0): could not convert null to string, ' - . 'column is not nullable'); - - (new PhpRowHydrator())->hydrate( - [new RawRowValues(['id' => 1, 'name' => null])], - schema(int_schema('id'), str_schema('name')), - ); - } - - public function test_null_value_keeps_the_schema_definition(): void - { - $rows = (new PhpRowHydrator())->hydrate( - [new RawRowValues(['id' => 1, 'name' => null])], - schema(int_schema('id'), str_schema('name', nullable: true)), - ); - - static::assertNull($rows->first()->get('name')); - static::assertTrue($rows->schema()->get('name')->isNullable()); - } - - public function test_plan_is_rebuilt_when_the_schema_changes(): void - { - $hydrator = new PhpRowHydrator(); - - $ids = $hydrator->hydrate([new RawRowValues(['id' => '1'])], schema(int_schema('id'))); - $prices = $hydrator->hydrate([new RawRowValues(['id' => '1'])], schema(float_schema('id'))); - - static::assertSame(['id' => 1], $ids->first()->toArray()); - static::assertSame(['id' => 1.0], $prices->first()->toArray()); - } - - public function test_metadata_is_folded_onto_the_column_with_last_write_winning(): void - { - static::assertSame( - ['k' => 'v2'], - (new PhpRowHydrator()) - ->hydrate([ - new RawRowValues(['id' => 1], ['id' => Metadata::fromArray(['k' => 'v1'])]), - new RawRowValues(['id' => 2], ['id' => Metadata::fromArray(['k' => 'v2'])]), - ], schema(int_schema('id'))) - ->schema() - ->get('id') - ->metadata() - ->normalize(), - ); - } - - public function test_metadata_is_folded_onto_a_numeric_column_name(): void - { - static::assertSame( - ['k' => 'v'], - (new PhpRowHydrator()) - ->hydrate([new RawRowValues([], ['0' => Metadata::fromArray([ - 'k' => 'v', - ])])], schema(int_schema('0', nullable: true))) - ->schema() - ->get('0') - ->metadata() - ->normalize(), - ); - } - - public function test_metadata_for_an_undeclared_column_is_ignored(): void - { - static::assertEquals( - schema(int_schema('id')), - (new PhpRowHydrator()) - ->hydrate([new RawRowValues(['id' => 1], ['nope' => Metadata::fromArray([ - 'k' => 'v', - ])])], schema(int_schema('id'))) - ->schema(), - ); - } - - public function test_rows_share_the_declared_schema_instance(): void - { - $schema = schema(int_schema('id')); - - $rows = (new PhpRowHydrator())->hydrate([ - new RawRowValues(['id' => 1]), - new RawRowValues(['id' => 2]), - ], $schema); - - static::assertSame($schema, $rows->schema()); - } - - public function test_hydrate_does_not_cast_native_values(): void - { - $createdAt = new DateTimeImmutable('2024-01-01 12:00:00 UTC'); - - $rows = (new PhpRowHydrator())->hydrate( - [new RawRowValues(['id' => 1, 'created_at' => $createdAt])], - schema(int_schema('id'), datetime_schema('created_at')), - ); - - static::assertSame(1, $rows->first()->get('id')); - static::assertEquals($createdAt, $rows->first()->get('created_at')); - } - - public function test_hydrate_does_not_cast_nested_list_map_and_structure(): void - { - $rows = (new PhpRowHydrator())->hydrate( - [new RawRowValues([ - 'tags' => ['a', 'b'], - 'counts' => ['x' => 1, 'y' => 2], - 'address' => ['city' => 'NYC', 'zip' => 10001], - ])], - schema( - list_schema('tags', type_list(type_string())), - map_schema('counts', type_map(type_string(), type_integer())), - structure_schema('address', type_structure(['city' => type_string(), 'zip' => type_integer()])), - ), - ); - - static::assertInstanceOf(ListType::class, $rows->schema()->get('tags')->type()); - static::assertInstanceOf(MapType::class, $rows->schema()->get('counts')->type()); - static::assertInstanceOf(StructureType::class, $rows->schema()->get('address')->type()); - static::assertSame(['a', 'b'], $rows->first()->get('tags')); - static::assertSame(['x' => 1, 'y' => 2], $rows->first()->get('counts')); - static::assertSame(['city' => 'NYC', 'zip' => 10001], $rows->first()->get('address')); - } - - public function test_hydrate_pads_a_nullable_column_absent_from_the_values(): void - { - $rows = (new PhpRowHydrator())->hydrate( - [new RawRowValues(['id' => 1])], - schema(int_schema('id'), str_schema('name', nullable: true)), - ); - - static::assertTrue($rows->first()->has('id')); - static::assertTrue($rows->first()->has('name')); - static::assertNull($rows->first()->get('name')); - } - - public function test_hydrating_already_typed_values_is_idempotent(): void - { - $schema = schema(int_schema('id'), str_schema('name'), datetime_schema('created_at')); - $hydrator = new PhpRowHydrator(); - $rows = $hydrator->hydrate([new RawRowValues([ - 'id' => 1, - 'name' => 'Alice', - 'created_at' => new DateTimeImmutable('2024-01-01 00:00:00 UTC'), - ])], $schema); - - static::assertEquals($rows, $hydrator->hydrate([new RawRowValues($rows->first()->values())], $schema)); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php deleted file mode 100644 index d9c087a726..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RowsBufferTest.php +++ /dev/null @@ -1,91 +0,0 @@ - rows( - schema(int_schema('id', nullable: true)), - ...$rows, - )); - - static::assertTrue( - $buffer - ->add(array_to_row(['id' => 1], schema(int_schema('id')))) - ?->schema() - ->get('id') - ->isNullable(), - ); - } - - public function test_the_default_batch_checks_every_row(): void - { - $this->expectException(SchemaMismatchException::class); - - (new RowsBuffer(schema(int_schema('id')), 1))->add(array_to_row(['id' => 'x'], schema(str_schema('id')))); - } - - public function test_add_returns_a_full_batch_and_resets(): void - { - $buffer = new RowsBuffer(schema(int_schema('id')), 2); - - static::assertNull($buffer->add(array_to_row(['id' => 1], schema(int_schema('id'))))); - - $batch = $buffer->add(array_to_row(['id' => 2], schema(int_schema('id')))); - - static::assertNotNull($batch); - static::assertSame([1, 2], $batch->reduceToArray('id')); - static::assertNull($buffer->add(array_to_row(['id' => 3], schema(int_schema('id'))))); - } - - public function test_add_returns_null_until_size_is_reached(): void - { - $buffer = new RowsBuffer(schema(int_schema('id')), 3); - - static::assertNull($buffer->add(array_to_row(['id' => 1], schema(int_schema('id'))))); - static::assertNull($buffer->add(array_to_row(['id' => 2], schema(int_schema('id'))))); - } - - public function test_flush_returns_null_when_empty(): void - { - static::assertNull((new RowsBuffer(schema(int_schema('id')), 2))->flush()); - } - - public function test_flush_returns_the_remainder(): void - { - $buffer = new RowsBuffer(schema(int_schema('id')), 3); - $buffer->add(array_to_row(['id' => 1], schema(int_schema('id')))); - - $batch = $buffer->flush(); - - static::assertNotNull($batch); - static::assertSame([1], $batch->reduceToArray('id')); - static::assertNull($buffer->flush()); - } - - public function test_throws_when_size_below_one(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Buffer size must be greater than 0, given: 0'); - - // @mago-ignore analysis:invalid-argument - new RowsBuffer(schema(int_schema('id')), 0); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/TypedRowValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/TypedRowValuesTest.php deleted file mode 100644 index 9ae895ab45..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/TypedRowValuesTest.php +++ /dev/null @@ -1,33 +0,0 @@ - 1], ['id' => type_integer()]); - - static::assertSame(['id' => 1], $rowValues->values); - static::assertEquals(['id' => type_integer()], $rowValues->types); - static::assertSame([], $rowValues->metadata); - } - - public function test_carries_per_value_types_and_metadata(): void - { - $metadata = Metadata::with('source', 'decoder'); - $rowValues = new TypedRowValues(['id' => null], ['id' => type_integer()], ['id' => $metadata]); - - static::assertSame(['id' => null], $rowValues->values); - static::assertEquals(['id' => type_integer()], $rowValues->types); - static::assertSame(['id' => $metadata], $rowValues->metadata); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBufferTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBufferTest.php new file mode 100644 index 0000000000..be98f8b8f6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBufferTest.php @@ -0,0 +1,118 @@ +appendFrom(array_to_rows([['id' => 1]], schema(int_schema('id'))), 0); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } + + public function test_a_released_batch_carries_the_buffer_schema(): void + { + $schema = schema(int_schema('id', nullable: true)); + $buffer = new RowsBuffer($schema, new PhpBackend(), 1); + + static::assertTrue( + $buffer + ->appendFrom(array_to_rows([['id' => 1]], $schema), 0) + ?->schema() + ->isSame($schema), + ); + } + + public function test_append_from_checks_every_row(): void + { + $this->expectException(SchemaMismatchException::class); + + (new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 1))->appendFrom(array_to_rows([[ + 'id' => 'x', + ]], schema(str_schema('id'))), 0); + } + + public function test_append_from_returns_a_full_batch_and_resets(): void + { + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); + $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 2); + + static::assertNull($buffer->appendFrom($rows, 0)); + + $batch = $buffer->appendFrom($rows, 1); + + static::assertNotNull($batch); + static::assertSame([1, 2], $batch->reduceToArray('id')); + static::assertNull($buffer->appendFrom($rows, 2)); + } + + public function test_append_from_returns_null_until_size_is_reached(): void + { + $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 3); + + static::assertNull($buffer->appendFrom($rows, 0)); + static::assertNull($buffer->appendFrom($rows, 1)); + } + + public function test_append_returns_a_full_batch(): void + { + $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 2); + + static::assertNull($buffer->append(['id' => 1])); + static::assertSame([1, 2], $buffer->append(['id' => 2])?->reduceToArray('id')); + } + + public function test_append_take_overshooting_the_size_is_released_whole(): void + { + $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); + $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 2); + + static::assertSame([3, 1, 2], $buffer->appendTake($rows, [2, 0, 1])?->reduceToArray('id')); + static::assertNull($buffer->flush()); + } + + public function test_flush_returns_null_when_empty(): void + { + static::assertNull((new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 2))->flush()); + } + + public function test_flush_returns_the_remainder(): void + { + $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 3); + $buffer->append(['id' => 1]); + + $batch = $buffer->flush(); + + static::assertNotNull($batch); + static::assertSame([1], $batch->reduceToArray('id')); + static::assertNull($buffer->flush()); + } + + public function test_throws_when_size_below_one(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Buffer size must be greater than 0, given: 0'); + + // @mago-ignore analysis:invalid-argument + new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 0); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php index 73dd36c4de..befb6de646 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php @@ -4,20 +4,45 @@ namespace Flow\ETL\Tests\Unit\Rows; +use DateTimeImmutable; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; +use Flow\ETL\Tests\Double\ForeignTypeDefinition; +use Flow\ETL\Tests\Double\ThrowingType; use Flow\ETL\Tests\FlowTestCase; +use Flow\Types\Type\Logical\ListType; +use Flow\Types\Type\Logical\MapType; +use Flow\Types\Type\Logical\StructureType; +use Flow\Types\Value\Uuid; use Generator; +use LogicException; use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\ETL\DSL\uuid_schema; +use function Flow\Types\DSL\structure_element; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_positive_integer; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; final class RowsBuilderTest extends FlowTestCase { @@ -48,6 +73,235 @@ public static function refused_views(): Generator ]; } + /** + * @return \Generator>, class-string<\Throwable>, string}> + */ + public static function refused_rows(): Generator + { + yield 'null in a not null column' => [ + schema(int_schema('id'), str_schema('name')), + [['id' => 1, 'name' => null]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "name" (row 0): could not convert null to string, column is not nullable', + ]; + + yield 'non numeric string in an integer column' => [ + schema(int_schema('id')), + [['id' => 'abc']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 0): could not convert \'abc\' (string) to integer', + ]; + + yield 'trailing garbage after digits in an integer column' => [ + schema(int_schema('id')), + [['id' => '12abc']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 0): could not convert \'12abc\' (string) to integer', + ]; + + yield 'hex string in a float column' => [ + schema(float_schema('price')), + [['price' => '0x1A']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "price" (row 0): could not convert \'0x1A\' (string) to float', + ]; + + yield 'unrecognised word in a boolean column' => [ + schema(bool_schema('active')), + [['active' => 'weird']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "active" (row 0): could not convert \'weird\' (string) to boolean', + ]; + + yield 'array in an integer column' => [ + schema(int_schema('id')), + [['id' => [1, 2, 3]]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 0): could not convert array (list) to integer', + ]; + + yield 'invalid uuid string' => [ + schema(uuid_schema('u')), + [['u' => 'not-a-uuid']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "u" (row 0): could not convert \'not-a-uuid\' (string) to uuid', + ]; + + yield 'uppercase uuid string' => [ + schema(uuid_schema('u')), + [['u' => '01234567-89AB-4DEF-8123-456789ABCDEF']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "u" (row 0): could not convert \'01234567-89AB-4DEF-8123-456789AB...\' (string) to uuid', + ]; + + yield 'json from a scalar' => [ + schema(json_schema('j')), + [['j' => 5]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "j" (row 0): could not convert 5 (integer) to json', + ]; + + yield 'json from an invalid json string' => [ + schema(json_schema('j')), + [['j' => '{oops']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "j" (row 0): could not convert \'{oops\' (string) to json', + ]; + + yield 'json from a plain string' => [ + schema(json_schema('j')), + [['j' => 'plain']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "j" (row 0): could not convert \'plain\' (string) to json', + ]; + + yield 'datetime from garbage' => [ + schema(datetime_schema('at')), + [['at' => 'not-a-date']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "at" (row 0): could not convert \'not-a-date\' (string) to datetime', + ]; + + yield 'datetime from an array' => [ + schema(datetime_schema('at')), + [['at' => ['nope']]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "at" (row 0): could not convert array (list) to datetime', + ]; + + yield 'date from garbage' => [ + schema(date_schema('d')), + [['d' => 'not-a-date']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "d" (row 0): could not convert \'not-a-date\' (string) to date', + ]; + + yield 'string map with integer keys' => [ + schema(map_schema('m', type_map(type_string(), type_integer()))), + [['m' => [5 => 1]]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "m" (row 0): could not convert array (map) to map', + ]; + + yield 'list with non-sequential keys' => [ + schema(list_schema('l', type_list(type_integer()))), + [['l' => [1 => 'x']]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert array (map) to list', + ]; + + yield 'positive integer list from a non-numeric string' => [ + schema(list_schema('l', type_list(type_positive_integer()))), + [['l' => ['abc']]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', + ]; + + yield 'positive integer list from a negative int' => [ + schema(list_schema('l', type_list(type_positive_integer()))), + [['l' => [-3]]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', + ]; + + yield 'structure missing required element' => [ + schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), + [['data' => ['id' => 1]]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer}) to structure{id: integer, name: string}', + ]; + + yield 'structure present-null required element' => [ + schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), + [['data' => ['id' => 1, 'name' => null]]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer, name: null}) to structure{id: integer, name: string}', + ]; + + yield 'structure present-null optional element' => [ + schema(structure_schema('data', type_structure([ + 'id' => type_integer(), + 'name' => structure_element('name', type_string(), optional: true), + ]))), + [['data' => ['id' => 1, 'name' => null]]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "data" (row 0): could not convert array (structure{id: integer, name: null}) to structure{id: integer, name?: string}', + ]; + + // the refusal is placed at the batch position, so a constant row index would diverge here + yield 'non numeric string in the second row of an integer column' => [ + schema(int_schema('id')), + [['id' => '1'], ['id' => 'x']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 1): could not convert \'x\' (string) to integer', + ]; + + yield 'a not null column the row does not carry' => [ + schema(int_schema('id'), str_schema('name')), + [['id' => 1]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "name" (row 0) declared by the schema is missing from the row', + ]; + + yield 'integer overflow' => [ + schema(int_schema('id')), + [['id' => '9223372036854775808']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "id" (row 0): could not convert \'9223372036854775808\' (string) to integer', + ]; + + yield 'date from an empty string' => [ + schema(date_schema('d')), + [['d' => '']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "d" (row 0): could not convert \'\' (string) to date', + ]; + + yield 'datetime from a relative word' => [ + schema(datetime_schema('at')), + [['at' => 'now']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "at" (row 0): could not convert \'now\' (string) to datetime', + ]; + + yield 'string from a null element inside a list' => [ + schema(list_schema('l', type_list(type_string()))), + [['l' => ['a', null]]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert array (list) to list', + ]; + + yield 'list from a scalar' => [ + schema(list_schema('l', type_list(type_integer()))), + [['l' => 5]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "l" (row 0): could not convert 5 (integer) to list', + ]; + + // ordering: an absence must not pre-empt a refusal that PHP reports first, or the two + // hydrators name different columns - and different ROWS - for the same batch + yield 'an absent column before a cast refusal in the same row' => [ + schema(int_schema('a'), int_schema('b')), + [['b' => 'abc']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "b" (row 0): could not convert \'abc\' (string) to integer', + ]; + + yield 'an absent column in row 0 before a cast refusal in row 1' => [ + schema(int_schema('a'), int_schema('b')), + [['a' => 1], ['a' => 1, 'b' => 'abc']], + SchemaMismatchException::class, + 'Rows do not match their schema: column "b" (row 1): could not convert \'abc\' (string) to integer', + ]; + + yield 'an absent column in row 0 before a present null in row 1' => [ + schema(int_schema('a'), int_schema('b')), + [['a' => 1], ['a' => 1, 'b' => null]], + SchemaMismatchException::class, + 'Rows do not match their schema: column "b" (row 1): could not convert null to integer, column is not nullable', + ]; + } + public function test_a_refused_value_wins_over_an_earlier_absence(): void { $this->expectException(SchemaMismatchException::class); @@ -284,4 +538,176 @@ public function test_ragged_columns_are_refused_at_finish(): void $builder->finish(); } + + /** + * @param list> $rows + * @param class-string<\Throwable> $exception + */ + #[DataProvider('refused_rows')] + public function test_append_rows_refuses(Schema $schema, array $rows, string $exception, string $message): void + { + $this->expectException($exception); + $this->expectExceptionMessage($message); + + (new RowsBuilder($schema, new PhpBackend())) + ->appendRows($rows) + ->finish(); + } + + public function test_append_rows_refuses_a_definition_outside_the_nineteen(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage( + 'Row does not match its schema: column "a": throwing cannot be a batch column, only the 19 Flow definitions have a column kind', + ); + + (new RowsBuilder( + schema( + new ForeignTypeDefinition('a', new ThrowingType(new LogicException('stub type refuses everything'))), + ), + new PhpBackend(), + ))->appendRows([['a' => [1, 2]]]); + } + + public function test_append_rows_refuses_a_structure_missing_a_required_element(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('Rows do not match their schema: column "data" (row 0)'); + + (new RowsBuilder( + schema(structure_schema('data', type_structure(['id' => type_integer(), 'name' => type_string()]))), + new PhpBackend(), + ))->appendRows([['data' => ['id' => 1]]]); + } + + public function test_append_rows_casts_datetime_and_uuid_strings(): void + { + $rows = (new RowsBuilder( + schema(datetime_schema('created_at'), uuid_schema('uuid')), + new PhpBackend(), + ))->appendRows([[ + 'created_at' => '2024-01-01 12:00:00 UTC', + 'uuid' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + ]])->finish(); + + // @mago-ignore analysis:mixed-assignment + $uuid = $rows->column('uuid')->value(0); + + static::assertInstanceOf(DateTimeImmutable::class, $rows->column('created_at')->value(0)); + static::assertInstanceOf(Uuid::class, $uuid); + static::assertSame('f47ac10b-58cc-4372-a567-0e02b2c3d479', $uuid->toString()); + } + + public function test_append_rows_casts_raw_scalar_strings_to_schema_types(): void + { + static::assertSame( + [['id' => 1, 'price' => 9.99, 'active' => true, 'name' => 'Alice']], + (new RowsBuilder( + schema(int_schema('id'), float_schema('price'), bool_schema('active'), str_schema('name')), + new PhpBackend(), + )) + ->appendRows([['id' => '1', 'price' => '9.99', 'active' => 'true', 'name' => 'Alice']]) + ->finish() + ->toArray(), + ); + } + + public function test_append_rows_keeps_native_typed_values(): void + { + static::assertSame( + [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']], + (new RowsBuilder(schema(int_schema('id'), str_schema('name')), new PhpBackend())) + ->appendRows([['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']]) + ->finish() + ->toArray(), + ); + } + + public function test_append_rows_keeps_native_uuid_value_objects(): void + { + // @mago-ignore analysis:mixed-assignment + $value = (new RowsBuilder(schema(uuid_schema('id')), new PhpBackend())) + ->appendRows([['id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')]]) + ->finish() + ->column('id') + ->value(0); + + static::assertInstanceOf(Uuid::class, $value); + static::assertSame('f47ac10b-58cc-4372-a567-0e02b2c3d479', $value->toString()); + } + + public function test_append_rows_keeps_the_schema_definition_of_a_null_value(): void + { + $rows = (new RowsBuilder( + schema(int_schema('id'), str_schema('name', nullable: true)), + new PhpBackend(), + ))->appendRows([['id' => 1, 'name' => null]])->finish(); + + static::assertNull($rows->column('name')->value(0)); + static::assertTrue($rows->schema()->get('name')->isNullable()); + } + + public function test_append_rows_shares_the_declared_schema_instance(): void + { + $schema = schema(int_schema('id')); + + static::assertSame( + $schema, + (new RowsBuilder($schema, new PhpBackend())) + ->appendRows([['id' => 1], ['id' => 2]]) + ->finish() + ->schema(), + ); + } + + public function test_append_rows_does_not_cast_native_values(): void + { + $createdAt = new DateTimeImmutable('2024-01-01 12:00:00 UTC'); + + $rows = (new RowsBuilder( + schema(int_schema('id'), datetime_schema('created_at')), + new PhpBackend(), + ))->appendRows([['id' => 1, 'created_at' => $createdAt]])->finish(); + + static::assertSame(1, $rows->column('id')->value(0)); + static::assertEquals($createdAt, $rows->column('created_at')->value(0)); + } + + public function test_append_rows_does_not_cast_nested_list_map_and_structure(): void + { + $rows = (new RowsBuilder( + schema( + list_schema('tags', type_list(type_string())), + map_schema('counts', type_map(type_string(), type_integer())), + structure_schema('address', type_structure(['city' => type_string(), 'zip' => type_integer()])), + ), + new PhpBackend(), + ))->appendRows([[ + 'tags' => ['a', 'b'], + 'counts' => ['x' => 1, 'y' => 2], + 'address' => ['city' => 'NYC', 'zip' => 10001], + ]])->finish(); + + static::assertInstanceOf(ListType::class, $rows->schema()->get('tags')->type()); + static::assertInstanceOf(MapType::class, $rows->schema()->get('counts')->type()); + static::assertInstanceOf(StructureType::class, $rows->schema()->get('address')->type()); + static::assertSame(['a', 'b'], $rows->column('tags')->value(0)); + static::assertSame(['x' => 1, 'y' => 2], $rows->column('counts')->value(0)); + static::assertSame(['city' => 'NYC', 'zip' => 10001], $rows->column('address')->value(0)); + } + + public function test_append_rows_of_already_typed_values_is_idempotent(): void + { + $schema = schema(int_schema('id'), str_schema('name'), datetime_schema('created_at')); + $rows = (new RowsBuilder($schema, new PhpBackend()))->appendRows([[ + 'id' => 1, + 'name' => 'Alice', + 'created_at' => new DateTimeImmutable('2024-01-01 00:00:00 UTC'), + ]])->finish(); + + static::assertEquals( + $rows, + (new RowsBuilder($schema, new PhpBackend()))->appendRows([$rows->values(0)])->finish(), + ); + } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php index d77917053c..dcbd468535 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php @@ -5,7 +5,6 @@ namespace Flow\Floe\Tests\Context; use Flow\ETL\Row; -use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; @@ -25,12 +24,12 @@ final class FloeFilesContext { public static function phpWriter(Filesystem $filesystem, Schema $schema, Codec $codec = new NoopCodec()): FloeWriter { - return new FloeWriter($filesystem, $schema, new Options(codec: $codec), new PhpRowHydrator()); + return new FloeWriter($filesystem, $schema, new Options(codec: $codec)); } public static function phpReader(Filesystem $filesystem, Codec $codec = new NoopCodec()): FloeReader { - return new FloeReader($filesystem, $codec, hydrator: new PhpRowHydrator()); + return new FloeReader($filesystem, $codec); } /** diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php index 3c937c5ad1..c7189f50bf 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php @@ -4,7 +4,6 @@ namespace Flow\Floe\Tests\Context; -use Flow\ETL\Row\Hydrator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -187,9 +186,8 @@ public static function writeBatches( Schema $schema, array $batches, Options $options = new Options(), - ?Hydrator $hydrator = null, ): string { - $writer = new FloeWriter($filesystem, $schema, $options, $hydrator); + $writer = new FloeWriter($filesystem, $schema, $options); $writer->create($path); foreach ($batches as $batch) { diff --git a/src/core/etl/tests/Flow/Floe/Tests/Double/SpyHydrator.php b/src/core/etl/tests/Flow/Floe/Tests/Double/SpyHydrator.php deleted file mode 100644 index cbc7bcb184..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Double/SpyHydrator.php +++ /dev/null @@ -1,31 +0,0 @@ -dehydrateCalls++; - - return (new PhpRowHydrator())->dehydrate($rows); - } - - public function hydrate(array $batch, Schema $schema): Rows - { - $this->hydrateCalls++; - - return (new PhpRowHydrator())->hydrate($batch, $schema); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php index d055fea43b..4ded8fe3e9 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php @@ -56,7 +56,7 @@ public function test_append_writes_sibling_files_read_as_union(): void static::assertSame(2, data_frame()->read(from_floe($dir . '/*.floe'))->count()); } - public function test_writing_and_reading_with_the_php_hydrator(): void + public function test_writing_and_reading_with_the_default_backend(): void { $path = $this->cacheDir->suffix('php-engine.floe'); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php index 789ed43f41..d5f83e844a 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php @@ -15,7 +15,9 @@ use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\to_timezone; use function Flow\Floe\DSL\from_floe; use function Flow\Types\DSL\type_datetime; @@ -101,17 +103,6 @@ public function test_schema_then_statistics_reads_the_footer_once(): void static::assertSame(1, $filesystem->readFromCalls); } - public function test_a_declared_schema_still_reads_the_footer_for_statistics(): void - { - $path = $this->cacheDir->suffix('declared.floe'); - FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); - - static::assertEquals( - Cardinality::exact(1), - from_floe($path, filesystem: $this->fs())->withSchema(schema(int_schema('id')))->statistics()->rows, - ); - } - public function test_union_by_name_sums_every_footer_exactly(): void { FloeStreamReaderContext::write( @@ -152,7 +143,7 @@ public function test_union_by_name_invalidates_the_memo(): void static::assertSame(2, $filesystem->readFromCalls); } - public function test_declared_zone_rezones_a_utc_file(): void + public function test_a_utc_file_is_rezoned_after_reading(): void { $path = $this->cacheDir->suffix('utc.floe'); FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['at' => new DateTimeImmutable( @@ -165,10 +156,8 @@ public function test_declared_zone_rezones_a_utc_file(): void type_datetime() ->assert( df() - ->read(from_floe($path, filesystem: $this->fs())->withSchema(schema(datetime_schema( - 'at', - zone: 'Europe/Warsaw', - )))) + ->read(from_floe($path, filesystem: $this->fs())) + ->withEntry('at', to_timezone(ref('at'), 'Europe/Warsaw')) ->fetch() ->first() ->get('at'), 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 9e5cafa093..a507440e8e 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php @@ -8,6 +8,7 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; use Flow\Filesystem\Tests\Double\RejectingFilter; @@ -282,9 +283,7 @@ public function test_extract_yields_the_metadata_column_schema_promises(): void $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); $loader->closure($context); - $extractor = from_floe($path, filesystem: $memory) - ->withMetadataColumns(true) - ->withSchema(schema(int_schema('id'))); + $extractor = from_floe($path, filesystem: $memory)->withMetadataColumns(true); $batches = iterator_to_array($extractor->extract($context)); @@ -292,6 +291,35 @@ 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_with_schema_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Floe is a self-describing format and does not accept a schema; declaring one is not supported yet.', + ); + + from_floe(path('memory://x.floe'), filesystem: memory_filesystem())->withSchema(schema(int_schema('id'))); + } + + public function test_extract_builds_through_the_config_backend(): void + { + $memory = memory_filesystem(); + $path = path('memory://backend.floe'); + $context = flow_context(config()); + + $loader = to_floe($path, filesystem: $memory); + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); + $loader->closure($context); + + $backend = new SpyBackend(); + + iterator_to_array(from_floe($path, filesystem: $memory)->extract( + flow_context(config_builder()->backend($backend)->build()), + )); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } + public function test_negative_offset_throws(): void { $this->expectException(InvalidArgumentException::class); @@ -402,25 +430,6 @@ public function test_declared_partition_types_reach_the_rows(): void static::fail('extractor yielded nothing'); } - public function test_a_declared_schema_may_name_the_partition_column(): void - { - $memory = memory_filesystem(); - FloeFilesContext::writeYearPartitionedFiles($memory); - - $extractor = from_floe(path('memory://years/*/*.floe'), filesystem: $memory)->withSchema(schema( - int_schema('id'), - int_schema('year'), - )); - - foreach ($extractor->extract(flow_context(config())) as $rows) { - static::assertSame(2024, $rows->first()->get('year')); - - return; - } - - static::fail('extractor yielded nothing'); - } - public function test_extract_closes_the_reader_when_the_generator_is_abandoned(): void { $counting = new CountingFilesystem($memory = memory_filesystem()); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php index 74703144e7..7d4c79cdd5 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php @@ -4,7 +4,6 @@ namespace Flow\Floe\Tests\Unit; -use Flow\ETL\Row\PhpRowHydrator; use Flow\ETL\Rows; use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; @@ -652,9 +651,9 @@ public function test_rows_through_a_custom_identity_codec_with_long_row_body_thr $filesystem = memory_filesystem(); $path = path('memory://custom-codec-long-row.floe'); $schemaBody = FloeSchemaContext::schemaBody(schema(int_schema('id'))); - $rowBody = (new PhpFloeEncoder(schema_from_json( - $schemaBody, - )))->encode((new PhpRowHydrator())->dehydrate(array_to_rows([['id' => 1]], schema(int_schema('id')))))[0]; + $rowBody = (new PhpFloeEncoder(schema_from_json($schemaBody)))->encode(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))))[0]; $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); $stream = $filesystem->writeTo($path); $stream->append( @@ -700,9 +699,9 @@ public function test_row_body_longer_than_hydrated_content_throws(): void $filesystem = memory_filesystem(); $path = path('memory://long-row.floe'); $schemaBody = FloeSchemaContext::schemaBody(schema(int_schema('id'))); - $rowBody = (new PhpFloeEncoder(schema_from_json( - $schemaBody, - )))->encode((new PhpRowHydrator())->dehydrate(array_to_rows([['id' => 1]], schema(int_schema('id')))))[0]; + $rowBody = (new PhpFloeEncoder(schema_from_json($schemaBody)))->encode(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))))[0]; $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); $stream = $filesystem->writeTo($path); $stream->append( diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php index c95f9f3abf..bc2b3cbd72 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php @@ -5,6 +5,7 @@ namespace Flow\Floe\Tests\Unit; use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\Floe\Exception\FloeException; use Flow\Floe\FloeSerializer; use Flow\Floe\Format; @@ -202,4 +203,14 @@ public function test_unserialize_rejects_footer_that_does_not_fit(): void unserialize_from_string(new FloeSerializer(), Format::header(0x00) . Format::trailer(1000)); } + + public function test_unserialize_builds_through_the_given_backend(): void + { + $backend = new SpyBackend(); + $serializer = new FloeSerializer(backend: $backend); + + unserialize_from_string($serializer, serialize_to_string($serializer, RowsMother::numbered(3))); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php index 4d23d57bfa..e3ba846c7a 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php @@ -4,9 +4,6 @@ namespace Flow\Floe\Tests\Unit; -use Flow\ETL\Row\Hydrator; -use Flow\ETL\Row\PhpRowHydrator; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Schema\Metadata; use Flow\Floe\Codec\NoopCodec; use Flow\Floe\FloeReader; @@ -15,7 +12,6 @@ use Flow\Floe\PhpFloeEncoder; use Flow\Floe\Tests\Context\FloeStreamReaderContext; use Flow\Floe\Tests\Double\ClosingSpySourceStream; -use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use function Flow\ETL\DSL\array_to_rows; @@ -23,7 +19,6 @@ use function Flow\ETL\DSL\schema; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; -use function Flow\Types\DSL\type_integer; use function iterator_to_array; final class FloeStreamReaderTest extends TestCase @@ -46,26 +41,23 @@ public function test_close_closes_the_source_stream(): void static::assertSame(1, $source->closeCount); } - /** - * @return array - */ - public static function hydrators(): array - { - return ['default' => [null], 'php' => [new PhpRowHydrator()]]; - } - - #[DataProvider('hydrators')] - public function test_batches_carry_the_file_schema_when_frames_carry_per_value_metadata(?Hydrator $hydrator): void + public function test_batches_carry_the_file_schema_when_frames_carry_per_value_metadata(): void { $filesystem = memory_filesystem(); $path = path('memory://per-value-metadata.floe'); $schema = schema(int_schema('id')); - FloeStreamReaderContext::writeFrames($filesystem, $path, $schema, (new PhpFloeEncoder($schema))->encode([ - new TypedRowValues(['id' => 1], ['id' => type_integer()], ['id' => Metadata::fromArray(['k' => 'v'])]), - ])); + FloeStreamReaderContext::writeFrames( + $filesystem, + $path, + $schema, + (new PhpFloeEncoder($schema))->encode(array_to_rows( + [['id' => 1]], + $schema->setMetadata('id', Metadata::fromArray(['k' => 'v'])), + )), + ); $batches = iterator_to_array( - (new FloeReader($filesystem, hydrator: $hydrator)) + (new FloeReader($filesystem)) ->read($path) ->rows(), ); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php index 4bf5418326..d0301183be 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php @@ -4,10 +4,12 @@ namespace Flow\Floe\Tests\Unit; -use Flow\ETL\Row\PhpRowHydrator; +use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Row\RawRowValues; -use Flow\ETL\Row\TypedRowValues; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema\Metadata; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\Floe\Exception\FloeException; use Flow\Floe\Format; use Flow\Floe\PhpFloeEncoder; @@ -15,6 +17,7 @@ use Flow\Floe\Tests\Mother\RowsMother; use PHPUnit\Framework\TestCase; +use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; @@ -22,8 +25,6 @@ use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\schema_from_json; use function Flow\ETL\DSL\str_schema; -use function Flow\Types\DSL\type_integer; -use function Flow\Types\DSL\type_string; final class PhpFloeEncoderTest extends TestCase { @@ -36,14 +37,14 @@ public function test_decode_produces_row_values(): void $encoder = new PhpFloeEncoder(schema_from_json(FloeSchemaContext::schemaBody($original->schema()))); - $decoded = $encoder->decode($encoder->encode((new PhpRowHydrator())->dehydrate($original))); + $decoded = $encoder->decode($encoder->encode($original)); static::assertSame(['id' => 1, 'name' => 'flow', 'price' => 1.5], $decoded[0]->values); static::assertSame([], $decoded[0]->metadata); static::assertSame(['id' => 2, 'name' => null, 'price' => 0.5], $decoded[1]->values); } - public function test_encode_from_dehydrated_rows_round_trips(): void + public function test_encode_round_trips(): void { $original = array_to_rows( [['id' => 1, 'name' => 'flow'], ['id' => 2, 'name' => null]], @@ -52,7 +53,7 @@ public function test_encode_from_dehydrated_rows_round_trips(): void $encoder = new PhpFloeEncoder(schema_from_json(FloeSchemaContext::schemaBody($original->schema()))); - $decoded = $encoder->decode($encoder->encode((new PhpRowHydrator())->dehydrate($original))); + $decoded = $encoder->decode($encoder->encode($original)); static::assertEquals( [ @@ -75,7 +76,7 @@ public function test_encode_refuses_a_row_that_does_not_carry_a_declared_column( $this->expectException(FloeException::class); $this->expectExceptionMessage('Floe found a row that does not carry the declared column "name"'); - $encoder->encode([new TypedRowValues(['id' => 4], ['id' => type_integer()])]); + $encoder->encode(array_to_rows([['id' => 4]], schema(int_schema('id')))); } public function test_encode_decode_round_trip_preserves_flags(): void @@ -89,14 +90,15 @@ public function test_encode_decode_round_trip_preserves_flags(): void $encoder = new PhpFloeEncoder($schema); - $types = ['id' => type_integer(), 'name' => type_string()]; $encoded = [ - new TypedRowValues(['id' => 1, 'name' => 'flow'], $types), - new TypedRowValues(['id' => 2, 'name' => null], $types), - new TypedRowValues(['id' => 3, 'name' => null], $types, ['name' => Metadata::fromArray(['tag' => 'x'])]), + ...$encoder->encode(array_to_rows([['id' => 1, 'name' => 'flow'], ['id' => 2, 'name' => null]], $schema)), + ...$encoder->encode(array_to_rows( + [['id' => 3, 'name' => null]], + $schema->setMetadata('name', Metadata::fromArray(['tag' => 'x'])), + )), ]; - $decoded = $encoder->decode($encoder->encode($encoded)); + $decoded = $encoder->decode($encoded); static::assertEquals( [ @@ -116,15 +118,11 @@ public function test_encode_decode_round_trip_preserves_arbitrary_metadata(): vo $encoder = new PhpFloeEncoder($schema); $metadata = ['name' => Metadata::fromArray(['source' => 'trusted', 'weight' => 3])]; - $encoded = [ - new TypedRowValues( - ['id' => 1, 'name' => 'flow'], - ['id' => type_integer(), 'name' => type_string()], - $metadata, - ), - ]; - $decoded = $encoder->decode($encoder->encode($encoded)); + $decoded = $encoder->decode($encoder->encode(array_to_rows( + [['id' => 1, 'name' => 'flow']], + $schema->setMetadata('name', $metadata['name']), + ))); static::assertEquals([new RawRowValues(['id' => 1, 'name' => 'flow'], $metadata)], $decoded); static::assertSame('trusted', $decoded[0]->metadata['name']->get('source')); @@ -139,10 +137,10 @@ public function test_null_entry_in_a_typed_column_encodes_as_a_plain_null(): voi ))); $encoder = new PhpFloeEncoder($schema); - $body = $encoder->encode((new PhpRowHydrator())->dehydrate(array_to_rows( + $body = $encoder->encode(array_to_rows( [['id' => 2, 'name' => null]], schema(int_schema('id'), null_schema('name')), - )))[0]; + ))[0]; $decoded = $encoder->decode([$body]); @@ -155,10 +153,10 @@ public function test_row_body_with_trailing_garbage_throws(): void $schema = schema_from_json(FloeSchemaContext::schemaBody(schema(int_schema('id'), str_schema('name')))); $encoder = new PhpFloeEncoder($schema); - $body = $encoder->encode((new PhpRowHydrator())->dehydrate(array_to_rows( + $body = $encoder->encode(array_to_rows( [['id' => 1, 'name' => 'flow']], schema(int_schema('id'), str_schema('name')), - )))[0]; + ))[0]; $this->expectException(FloeException::class); $this->expectExceptionMessage('Floe row frame length does not match its content'); @@ -176,7 +174,7 @@ public function test_unknown_value_flag_throws(): void (new PhpFloeEncoder($schema))->decode(["\xEF"]); } - public function test_decode_rows_hydrates_the_decoded_values(): void + public function test_decode_rows_builds_the_decoded_values(): void { $data = array_to_rows( [['id' => 1, 'name' => 'flow'], ['id' => 2, 'name' => null]], @@ -184,22 +182,109 @@ public function test_decode_rows_hydrates_the_decoded_values(): void ); $schema = schema_from_json(FloeSchemaContext::schemaBody($data->schema())); $encoder = new PhpFloeEncoder($schema); - $bodies = $encoder->encode((new PhpRowHydrator())->dehydrate($data)); + $bodies = $encoder->encode($data); static::assertEquals( - (new PhpRowHydrator())->hydrate($encoder->decode($bodies), $schema), - $encoder->decodeRows($bodies, $schema, new PhpRowHydrator()), + (new RowsBuilder($schema, new DefaultBackend())) + ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $encoder->decode($bodies))) + ->finish(), + $encoder->decodeRows($bodies, $schema), ); } - public function test_encode_frames_frames_the_encoded_dehydrated_rows(): void + public function test_decode_rows_builds_through_the_given_backend(): void { $data = RowsMother::numbered(3); - $encoder = new PhpFloeEncoder($data->schema()); + $backend = new SpyBackend(); + + (new PhpFloeEncoder($data->schema(), $backend))->decodeRows( + (new PhpFloeEncoder($data->schema()))->encode($data), + $data->schema(), + ); + + static::assertGreaterThanOrEqual(1, $backend->builders()); + } + + public function test_decode_rows_folds_metadata_onto_the_column_with_last_write_winning(): void + { + $plain = schema(int_schema('id', nullable: true)); + $encoder = new PhpFloeEncoder($plain); + + $bodies = [ + ...$encoder->encode(array_to_rows( + [['id' => 1]], + $plain->setMetadata('id', Metadata::fromArray(['k' => 'v1'])), + )), + ...$encoder->encode(array_to_rows( + [['id' => 2]], + $plain->setMetadata('id', Metadata::fromArray(['k' => 'v2'])), + )), + ]; + + static::assertSame( + ['k' => 'v2'], + $encoder->decodeRows($bodies, $plain)->schema()->get('id')->metadata()->normalize(), + ); + } + + public function test_decode_rows_folds_metadata_onto_a_numeric_column_name(): void + { + $plain = schema(int_schema('0', nullable: true)); + $encoder = new PhpFloeEncoder($plain); + + $bodies = $encoder->encode(array_to_rows( + [['0' => 1]], + $plain->setMetadata('0', Metadata::fromArray(['k' => 'v'])), + )); static::assertSame( - Format::rowFrames($encoder->encode((new PhpRowHydrator())->dehydrate($data))), - $encoder->encodeFrames($data, new PhpRowHydrator()), + ['k' => 'v'], + $encoder->decodeRows($bodies, $plain)->schema()->get('0')->metadata()->normalize(), ); } + + public function test_decode_rows_ignores_metadata_of_an_undeclared_column(): void + { + $written = schema(int_schema('id'), int_schema('nope')); + $encoder = new PhpFloeEncoder($written); + + $bodies = $encoder->encode(array_to_rows( + [['id' => 1, 'nope' => 2]], + $written->setMetadata('nope', Metadata::fromArray(['k' => 'v'])), + )); + + static::assertEquals( + schema(int_schema('id')), + $encoder->decodeRows($bodies, schema(int_schema('id')))->schema(), + ); + } + + public function test_encode_of_an_empty_batch_returns_no_bodies(): void + { + static::assertSame( + [], + (new PhpFloeEncoder(schema(int_schema('id'), str_schema('name'))))->encode(array_to_rows( + [], + schema(int_schema('id')), + )), + ); + } + + public function test_a_not_null_refusal_on_an_earlier_column_wins_over_a_missing_later_column(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "id" (row 0)'); + + (new PhpFloeEncoder(schema(int_schema('id'), str_schema('name'))))->encode(array_to_rows([[ + 'id' => null, + ]], schema(int_schema('id', nullable: true)))); + } + + public function test_encode_frames_frames_the_encoded_rows(): void + { + $data = RowsMother::numbered(3); + $encoder = new PhpFloeEncoder($data->schema()); + + static::assertSame(Format::rowFrames($encoder->encode($data)), $encoder->encodeFrames($data)); + } } diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Row/RustRowHydratorNative.php b/src/extension/flow-php-ext/php/Flow/ETL/Row/RustRowHydratorNative.php index 1e619fec6f..cd642b126c 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Row/RustRowHydratorNative.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Row/RustRowHydratorNative.php @@ -30,7 +30,7 @@ public function hydrate(array $batch, Schema $schema): Rows } /** - * @return list + * @return list */ public function dehydrate(Rows $rows): array { diff --git a/src/extension/flow-php-ext/php/Flow/Floe/RustFloeEncoderNative.php b/src/extension/flow-php-ext/php/Flow/Floe/RustFloeEncoderNative.php index 2e2362914d..37504fe5e8 100644 --- a/src/extension/flow-php-ext/php/Flow/Floe/RustFloeEncoderNative.php +++ b/src/extension/flow-php-ext/php/Flow/Floe/RustFloeEncoderNative.php @@ -5,7 +5,6 @@ namespace Flow\Floe; use Flow\ETL\Row\RawRowValues; -use Flow\ETL\Row\TypedRowValues; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Floe\Exception\ExtensionException; @@ -25,7 +24,7 @@ public function __construct() } /** - * @param list $batch + * @param list $batch * @param string $schemaBody SCHEMA frame body (JSON list of normalized definitions) * @param Schema $schema the same definitions as objects, so a refusal is raised through the PHP factory * diff --git a/src/extension/flow-php-ext/tests/phpt/054_csv_consumed_bytes.phpt b/src/extension/flow-php-ext/tests/phpt/054_csv_consumed_bytes.phpt index 5f2ac050a5..b54d75cbf4 100644 --- a/src/extension/flow-php-ext/tests/phpt/054_csv_consumed_bytes.phpt +++ b/src/extension/flow-php-ext/tests/phpt/054_csv_consumed_bytes.phpt @@ -6,7 +6,7 @@ native CSV consumedBytes() counts the bytes of the rows it produced exactly like , list>} */ @@ -55,7 +55,7 @@ function csv_php_rows( bool $emptyToNull = true, bool $removeBOM = true, ): array { - $encoder = new Flow\ETL\Adapter\CSV\CSVEncoder( + $decoder = new Flow\ETL\Adapter\CSV\CSVDecoder( withHeader: $withHeader, separator: $separator, enclosure: $enclosure, @@ -68,12 +68,12 @@ function csv_php_rows( foreach ($lines->readLines( new Flow\Filesystem\Stream\StringSourceStream(Flow\Filesystem\DSL\path('memory://phpt.csv'), $raw), ) as $line) { - foreach ($encoder->decode([$line]) as $values) { + foreach ($decoder->decode([$line]) as $values) { $rows[] = $values->values; } } - return [$encoder->headers() ?? [], $rows]; + return [$decoder->headers() ?? [], $rows]; } /** diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php index 5ddf84a895..3835c8b85b 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php @@ -36,14 +36,15 @@ public function openForWrite( return $this->delegate->openForWrite($stream, $schema, $compression, $options); } - public function readValues( + public function readColumns( SourceStream $stream, Schema $schema, - array $columns = [], - ?int $limit = null, - ?int $offset = null, + array $columns, + int $batchSize, + ?int $limit, + ?int $offset, ): Generator { - return $this->delegate->readValues($stream, $schema, $columns, $limit, $offset); + return $this->delegate->readColumns($stream, $schema, $columns, $batchSize, $limit, $offset); } public function writeRows( diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php index 404945ec1a..665bdb2dbf 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php @@ -23,8 +23,11 @@ use function array_column; use function array_keys; +use function array_push; +use function array_slice; use function count; use function extension_loaded; +use function min; final class ArrowParquetEngine implements ParquetEngine { @@ -77,56 +80,68 @@ public function openForWrite( ); } - /** - * @param array $columns - * - * @return \Generator> - */ - public function readValues( + public function readColumns( SourceStream $stream, Schema $schema, - array $columns = [], - ?int $limit = null, - ?int $offset = null, + array $columns, + int $batchSize, + ?int $limit, + ?int $offset, ): Generator { $adapter = new SourceStreamAdapter($stream); $extensionOptions = OptionsConverter::toExtension($this->options); $reader = new Reader($adapter, $extensionOptions); try { - $skipped = 0; - $yielded = 0; + $toSkip = $offset ?? 0; + $remaining = $limit; + /** @var array> $carry */ + $carry = []; + $carryCount = 0; - while (null !== ($batch = $reader->readRowGroup($columns ?: null))) { - $colNames = array_keys($batch); + while (($remaining === null || $remaining > 0) && null !== ($got = $reader->readRowGroup($columns))) { + $names = array_keys($got); - if ($colNames === []) { + if ($names === []) { continue; } - $rowCount = count($batch[$colNames[0]]); + $available = count($got[$names[0]]); + $cursor = min($toSkip, $available); + $toSkip -= $cursor; - for ($i = 0; $i < $rowCount; $i++) { - if ($offset !== null && $skipped < $offset) { - $skipped++; + while ($cursor < $available && ($remaining === null || $remaining > 0)) { + $take = min($batchSize - $carryCount, $available - $cursor, $remaining ?? $available); - continue; - } + foreach ($names as $name) { + /** @var list $slice */ + $slice = array_slice($got[$name], $cursor, $take); - if ($limit !== null && $yielded >= $limit) { - return; + if ($carryCount === 0) { + $carry[$name] = $slice; + } else { + array_push($carry[$name], ...$slice); + } } - $row = []; + $carryCount += $take; + $cursor += $take; - foreach ($colNames as $name) { - $row[$name] = $batch[$name][$i]; + if ($remaining !== null) { + $remaining -= $take; } - yield $row; - $yielded++; + if ($carryCount === $batchSize) { + yield $carry; + $carry = []; + $carryCount = 0; + } } } + + if ($carryCount > 0) { + yield $carry; + } } finally { $reader->close(); } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php index 9d0d2eb58b..caa82d06d5 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php @@ -29,13 +29,12 @@ use Flow\Parquet\Thrift\MemoryBuffer; use Flow\Parquet\ThriftModel\FileMetaData; use Generator; -use MultipleIterator; -use function array_map; use function array_push; use function count; use function is_array; use function iterator_to_array; +use function min; use function unpack; final class PhpParquetEngine implements ParquetEngine @@ -60,12 +59,13 @@ public function openForWrite( ); } - public function readValues( + public function readColumns( SourceStream $stream, Schema $schema, - array $columns = [], - ?int $limit = null, - ?int $offset = null, + array $columns, + int $batchSize, + ?int $limit, + ?int $offset, ): Generator { $dataConverter = DataConverter::initialize($this->options); $dremelAssembler = new DremelAssembler($dataConverter); @@ -73,10 +73,6 @@ public function readValues( $metadata = $this->readMetadata($stream); - if (!count($columns)) { - $columns = array_map(static fn(Column $c) => $c->name(), $schema->columns()); - } - $totalRows = $metadata->rowsNumber(); if ($offset !== null && $offset > $totalRows) { @@ -97,45 +93,54 @@ public function readValues( return; } - $multipleIterator = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC); + $generators = []; foreach ($columns as $columnName) { - $multipleIterator->attachIterator( - $this->readColumn( - $schema->get($columnName), - $metadata, - $stream, - $chunkReader, - $dremelAssembler, - $limit, - $offset, - ), - $columnName, + $generators[$columnName] = $this->readColumn( + $schema->get($columnName), + $metadata, + $stream, + $chunkReader, + $dremelAssembler, + $limit, + $offset, ); } - $rowCount = 0; + $remaining = $totalRows; - foreach ($multipleIterator as $rowData) { - if ($limit !== null && $rowCount >= $limit) { - break; - } + while ($remaining > 0) { + $take = min($batchSize, $remaining); + $chunk = []; + $read = 0; - $row = []; + foreach ($generators as $name => $generator) { + $values = []; - // Row payload assembled from per-column generators; values are user data (mixed). - // @mago-ignore analysis:mixed-assignment - foreach ($rowData as $columnData) { - if (is_array($columnData)) { + while (count($values) < $take && $generator->valid()) { // @mago-ignore analysis:mixed-assignment - foreach ($columnData as $key => $value) { - $row[(string) $key] = $value; + $entry = $generator->current(); + + if (is_array($entry)) { + // @mago-ignore analysis:mixed-assignment + foreach ($entry as $value) { + $values[] = $value; + } } + + $generator->next(); } + + $chunk[$name] = $values; + $read = count($values); + } + + if ($read === 0) { + return; } - yield $row; - $rowCount++; + yield $chunk; + $remaining -= $read; } } diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php index ed591d514e..d414293567 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php @@ -20,16 +20,18 @@ public function openForWrite( ): ParquetFileWriter; /** - * @param array $columns + * @param list $columns resolved names, never empty + * @param int<1, max> $batchSize upper bound of rows per chunk * - * @return \Generator> + * @return Generator>> chunks keyed by column, every list the same length (>0) */ - public function readValues( + public function readColumns( SourceStream $stream, Schema $schema, - array $columns = [], - ?int $limit = null, - ?int $offset = null, + array $columns, + int $batchSize, + ?int $limit, + ?int $offset, ): Generator; /** diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile.php index 7cb2bcfd11..cbd16e2599 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFile.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile.php @@ -18,7 +18,9 @@ use Flow\Parquet\ThriftModel\FileMetaData; use Generator; +use function array_keys; use function array_map; +use function array_values; use function count; use function unpack; @@ -26,6 +28,8 @@ final class ParquetFile { public const string PARQUET_MAGIC_NUMBER = 'PAR1'; + private const int VALUES_BATCH_SIZE = 1024; + private ?Metadata $metadata = null; public function __construct( @@ -98,15 +102,19 @@ public function schema(): Schema /** * @param array $columns * - * @return \Generator> + * @return Generator>> */ - public function values(array $columns = [], ?int $limit = null, ?int $offset = null): Generator + public function columns(int $batchSize, array $columns = [], ?int $limit = null, ?int $offset = null): Generator { + if ($batchSize < 1) { + throw new InvalidArgumentException('Batch size must be greater than 0'); + } + if ($limit !== null && $limit <= 0) { throw new InvalidArgumentException('Limit must be greater than 0'); } - if ($limit !== null && $offset !== null && $offset < 0) { + if ($offset !== null && $offset < 0) { throw new InvalidArgumentException('Offset must be greater than or equal to 0'); } @@ -120,7 +128,37 @@ public function values(array $columns = [], ?int $limit = null, ?int $offset = n } } - yield from $this->engine->readValues($this->stream, $this->schema(), $columns, $limit, $offset); + yield from $this->engine->readColumns( + $this->stream, + $this->schema(), + array_values($columns), + $batchSize, + $limit, + $offset, + ); + } + + /** + * @param array $columns + * + * @return Generator> + */ + public function values(array $columns = [], ?int $limit = null, ?int $offset = null): Generator + { + foreach ($this->columns(self::VALUES_BATCH_SIZE, $columns, $limit, $offset) as $chunk) { + $names = array_keys($chunk); + $count = count($chunk[$names[0]]); + + for ($i = 0; $i < $count; $i++) { + $row = []; + + foreach ($names as $name) { + $row[$name] = $chunk[$name][$i]; + } + + yield $row; + } + } } /** diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php index dcb8c23108..12fa023e43 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php @@ -61,16 +61,25 @@ public function test_read_flat_columns(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - )); - - static::assertCount(3, $result); - static::assertSame(1, $result[0]['id']); - static::assertSame('Alice', $result[0]['name']); - static::assertTrue($result[0]['active']); - static::assertEqualsWithDelta(99.5, $result[0]['score'], 0.001); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id', 'name', 'active', 'score'], + batchSize: 2, + limit: null, + offset: null, + ), + false, + ); + + static::assertSame( + [ + ['id' => [1, 2], 'name' => ['Alice', 'Bob'], 'active' => [true, false], 'score' => [99.5, 87.3]], + ['id' => [3], 'name' => ['Charlie'], 'active' => [true], 'score' => [92.1]], + ], + $chunks, + ); } public function test_read_nested_lists(): void @@ -91,14 +100,19 @@ public function test_read_nested_lists(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - )); - - static::assertCount(2, $result); - static::assertSame(['php', 'rust'], $result[0]['tags']); - static::assertSame(['python'], $result[1]['tags']); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id', 'tags'], + batchSize: 2, + limit: null, + offset: null, + ), + false, + ); + + static::assertSame([['id' => [1, 2], 'tags' => [['php', 'rust'], ['python']]]], $chunks); } public function test_read_nested_maps(): void @@ -119,17 +133,22 @@ public function test_read_nested_maps(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - )); - - static::assertCount(2, $result); - /** @var array $metadata */ - $metadata = $result[0]['metadata']; - static::assertIsArray($metadata); - static::assertSame(100, $metadata['score']); - static::assertSame(5, $metadata['level']); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id', 'metadata'], + batchSize: 2, + limit: null, + offset: null, + ), + false, + ); + + static::assertSame( + [['id' => [1, 2], 'metadata' => [['score' => 100, 'level' => 5], ['score' => 200]]]], + $chunks, + ); } public function test_read_nested_structs(): void @@ -153,17 +172,22 @@ public function test_read_nested_structs(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - )); - - static::assertCount(2, $result); - /** @var array $address */ - $address = $result[0]['address']; - static::assertIsArray($address); - static::assertSame('Berlin', $address['city']); - static::assertSame(10115, $address['zip']); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id', 'address'], + batchSize: 2, + limit: null, + offset: null, + ), + false, + ); + + static::assertSame( + [['id' => [1, 2], 'address' => [['city' => 'Berlin', 'zip' => 10115], ['city' => 'Warsaw', 'zip' => 1]]]], + $chunks, + ); } public function test_read_nested_uuid_as_canonical_strings(): void @@ -185,14 +209,26 @@ public function test_read_nested_uuid_as_canonical_strings(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - )); - - static::assertSame($uuid, $result[0]['top_uuid']); - static::assertSame(['id' => $uuid, 'data' => '{"a":1}'], $result[0]['body']); - static::assertSame([$uuid, $uuid], $result[0]['uuid_list']); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['top_uuid', 'body', 'uuid_list'], + batchSize: 2, + limit: null, + offset: null, + ), + false, + ); + + static::assertSame( + [[ + 'top_uuid' => [$uuid], + 'body' => [['id' => $uuid, 'data' => '{"a":1}']], + 'uuid_list' => [[$uuid, $uuid]], + ]], + $chunks, + ); } public function test_read_with_column_projection(): void @@ -214,16 +250,19 @@ public function test_read_with_column_projection(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - ['id', 'name'], - )); - - static::assertCount(2, $result); - static::assertArrayHasKey('id', $result[0]); - static::assertArrayHasKey('name', $result[0]); - static::assertArrayNotHasKey('email', $result[0]); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id', 'name'], + batchSize: 2, + limit: null, + offset: null, + ), + false, + ); + + static::assertSame([['id' => [1, 2], 'name' => ['Alice', 'Bob']]], $chunks); } public function test_read_with_limit(): void @@ -238,16 +277,19 @@ public function test_read_with_limit(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - [], - 10, - )); - - static::assertCount(10, $result); - static::assertSame(1, $result[0]['id']); - static::assertSame(10, $result[9]['id']); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id'], + batchSize: 2, + limit: 5, + offset: null, + ), + false, + ); + + static::assertSame([['id' => [1, 2]], ['id' => [3, 4]], ['id' => [5]]], $chunks); } public function test_read_with_limit_and_offset(): void @@ -262,17 +304,19 @@ public function test_read_with_limit_and_offset(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - [], - 5, - 10, - )); - - static::assertCount(5, $result); - static::assertSame(11, $result[0]['id']); - static::assertSame(15, $result[4]['id']); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id'], + batchSize: 2, + limit: 5, + offset: 10, + ), + false, + ); + + static::assertSame([['id' => [11, 12]], ['id' => [13, 14]], ['id' => [15]]], $chunks); } public function test_read_with_offset(): void @@ -287,15 +331,18 @@ public function test_read_with_offset(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - [], - null, - 50, - )); - - static::assertCount(50, $result); - static::assertSame(51, $result[0]['id']); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id'], + batchSize: 2, + limit: null, + offset: 96, + ), + false, + ); + + static::assertSame([['id' => [97, 98]], ['id' => [99, 100]]], $chunks); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php index a019a73770..335322461b 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php @@ -61,12 +61,22 @@ public function test_arrow_write_arrow_read_roundtrip(): void $parquetFile = (new Reader())->read($path); $readStream = NativeLocalSourceStream::open(path_real($path)); - $result = iterator_to_array($engine->readValues($readStream, $parquetFile->schema())); + $chunks = iterator_to_array( + $engine->readColumns( + $readStream, + $parquetFile->schema(), + ['id', 'label', 'big_number'], + batchSize: 2, + limit: null, + offset: null, + ), + false, + ); - static::assertCount(2, $result); - static::assertSame(1, $result[0]['id']); - static::assertSame('first', $result[0]['label']); - static::assertSame(1_000_000_000_000, $result[0]['big_number']); + static::assertSame( + [['id' => [1, 2], 'label' => ['first', 'second'], 'big_number' => [1_000_000_000_000, 2_000_000_000_000]]], + $chunks, + ); } public function test_arrow_write_php_read(): void @@ -147,14 +157,24 @@ public function test_php_write_arrow_read(): void $engine = new ArrowParquetEngine(); $parquetFile = (new Reader())->read($path); - $result = iterator_to_array($engine->readValues( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), - )); + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + $parquetFile->schema(), + ['id', 'name', 'value'], + batchSize: 2, + limit: null, + offset: null, + ), + false, + ); - static::assertCount(3, $result); - static::assertSame(1, $result[0]['id']); - static::assertSame('one', $result[0]['name']); - static::assertEqualsWithDelta(1.1, $result[0]['value'], 0.001); + static::assertSame( + [ + ['id' => [1, 2], 'name' => ['one', 'two'], 'value' => [1.1, 2.2]], + ['id' => [3], 'name' => ['three'], 'value' => [3.3]], + ], + $chunks, + ); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php new file mode 100644 index 0000000000..a1ab6d3ef3 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php @@ -0,0 +1,90 @@ +, list>}> + */ + public static function chunkings(): Generator + { + foreach (self::engine_provider() as $name => [$engine]) { + yield "{$name}: batch size 2" => [$engine, 2, null, null, [2, 2, 1], [[1, 2], [3, 4], [5]]]; + yield "{$name}: offset 3" => [$engine, 2, null, 3, [2], [[4, 5]]]; + yield "{$name}: limit 3" => [$engine, 2, 3, null, [2, 1], [[1, 2], [3]]]; + yield "{$name}: offset 1, limit 3" => [$engine, 2, 3, 1, [2, 1], [[2, 3], [4]]]; + yield "{$name}: batch size above the row count" => [$engine, 10, null, null, [5], [[1, 2, 3, 4, 5]]]; + } + } + + /** + * @param int<1, max> $batchSize + * @param list $sizes + * @param list> $ids + */ + #[DataProvider('chunkings')] + public function test_chunks_follow_batch_size_limit_and_offset( + ParquetEngine $engine, + int $batchSize, + ?int $limit, + ?int $offset, + array $sizes, + array $ids, + ): void { + $path = TestParquetFile::path($this); + + (new Writer())->write( + $path, + Schema::with( + FlatColumn::int32('id', Repetition::REQUIRED), + NestedColumn::list('tags', ListElement::string()), + ), + array_map(static fn(int $i): array => ['id' => $i, 'tags' => ['t' . $i]], [1, 2, 3, 4, 5]), + ); + + $chunks = iterator_to_array( + $engine->readColumns( + NativeLocalSourceStream::open(path_real($path)), + (new Reader()) + ->read($path) + ->schema(), + ['id', 'tags'], + $batchSize, + $limit, + $offset, + ), + false, + ); + + static::assertSame($sizes, array_map(static fn(array $chunk): int => count($chunk['id']), $chunks)); + static::assertSame($ids, array_map(static fn(array $chunk): array => $chunk['id'], $chunks)); + static::assertSame( + array_map(static fn(array $chunk): array => array_map(static fn(int $i): array => [ + 't' . $i, + ], $chunk), $ids), + array_map(static fn(array $chunk): array => $chunk['tags'], $chunks), + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/PaginationTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/PaginationTest.php index 60f123b5aa..7c92bda586 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/PaginationTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/PaginationTest.php @@ -149,6 +149,77 @@ public function test_setting_setting_offset_to_negative(ParquetEngine $engine): ); } + #[DataProvider('engine_provider')] + public function test_columns_refuses_a_batch_size_below_one(ParquetEngine $engine): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Batch size must be greater than 0'); + + iterator_to_array( + (new Reader(engine: $engine)) + ->read(__DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet') + ->columns(0, ['id']), + ); + } + + #[DataProvider('engine_provider')] + public function test_columns_refuses_a_limit_of_zero(ParquetEngine $engine): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Limit must be greater than 0'); + + iterator_to_array( + (new Reader(engine: $engine)) + ->read(__DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet') + ->columns(2, ['id'], limit: 0), + ); + } + + #[DataProvider('engine_provider')] + public function test_columns_refuses_a_negative_offset_without_a_limit(ParquetEngine $engine): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Offset must be greater than or equal to 0'); + + iterator_to_array( + (new Reader(engine: $engine)) + ->read(__DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet') + ->columns(2, ['id'], offset: -1), + ); + } + + #[DataProvider('engine_provider')] + public function test_columns_refuses_an_unknown_column(ParquetEngine $engine): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column "nope" does not exist'); + + iterator_to_array( + (new Reader(engine: $engine)) + ->read(__DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet') + ->columns(2, ['nope']), + ); + } + + #[DataProvider('engine_provider')] + public function test_values_equal_the_zip_of_columns(ParquetEngine $engine): void + { + $file = (new Reader(engine: $engine))->read(__DIR__ + . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'); + + $zipped = []; + + foreach ($file->columns(3, ['id', 'name'], limit: 7, offset: 1020) as $chunk) { + // @mago-ignore analysis:mixed-assignment + foreach ($chunk['id'] as $i => $id) { + $zipped[] = ['id' => $id, 'name' => $chunk['name'][$i]]; + } + } + + static::assertSame($zipped, iterator_to_array($file->values(['id', 'name'], limit: 7, offset: 1020), false)); + static::assertCount(7, $zipped); + } + #[DataProvider('engine_provider')] public function test_simple_pagination_on_small_row_group_size(ParquetEngine $engine): void { From 14d47e93ef8777792bd5060b7d4dbd85cecbb22b Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Mon, 28 Sep 2026 10:31:06 +0200 Subject: [PATCH 04/21] feat(flow-php/etl): Floe writes one BATCH frame per batch - columnar BATCH frame (FrameEncoder/FrameDecoder, BufferLayout), codec per buffer - row format removed: PhpFloeEncoder, Encoding/Decoding, ROW frames - read batches are frame-sized, batchSize an upper bound; bucket reads coalesce - NOT NULL refusal moves to Rows::fromColumns, nested nulls refused on decode - oversized batches split in halves on OffsetOverflow/FrameTooLarge - Rows serialize as a BATCH frame; golden fixtures and docs regenerated --- documentation/components/core/floe.md | 168 ++++------ documentation/contributing/wasm.md | 4 +- documentation/upgrading.md | 64 ++-- .../Bucketing/Storage/FilesystemBuckets.php | 20 +- .../etl/src/Flow/ETL/Column/BufferLayout.php | 171 ++++++++++ .../src/Flow/ETL/Column/Php/ColumnDecoder.php | 78 ++++- .../ETL/Column/Php/HtmlDocumentPhysical.php | 16 +- .../ETL/Column/Php/HtmlElementPhysical.php | 38 ++- .../etl/src/Flow/ETL/Column/Php/Offsets.php | 3 +- .../Flow/ETL/Column/Php/TimeZonePhysical.php | 1 - .../Decoding => ETL/Column/Php}/TimeZones.php | 2 +- .../ETL/Column/Php/XmlDocumentPhysical.php | 23 +- .../ETL/Column/Php/XmlElementPhysical.php | 31 +- .../src/Flow/ETL/Exception/OffsetOverflow.php | 7 + src/core/etl/src/Flow/ETL/Rows.php | 55 ++-- src/core/etl/src/Flow/Floe/Codec.php | 4 +- .../etl/src/Flow/Floe/ColumnBlueprint.php | 19 -- .../src/Flow/Floe/Decoding/BooleanDecoder.php | 13 - .../Flow/Floe/Decoding/DateTimeDecoder.php | 54 ---- .../src/Flow/Floe/Decoding/EnumDecoder.php | 39 --- .../src/Flow/Floe/Decoding/Float64Decoder.php | 18 -- .../Floe/Decoding/HtmlDocumentDecoder.php | 22 -- .../Flow/Floe/Decoding/HtmlElementDecoder.php | 22 -- .../src/Flow/Floe/Decoding/Int64Decoder.php | 18 -- .../Flow/Floe/Decoding/IntervalDecoder.php | 42 --- .../src/Flow/Floe/Decoding/JsonDecoder.php | 27 -- .../src/Flow/Floe/Decoding/ListDecoder.php | 30 -- .../etl/src/Flow/Floe/Decoding/MapDecoder.php | 33 -- .../src/Flow/Floe/Decoding/NullDecoder.php | 13 - .../Flow/Floe/Decoding/OptionalDecoder.php | 25 -- .../Flow/Floe/Decoding/PackedListDecoder.php | 37 --- .../src/Flow/Floe/Decoding/StringDecoder.php | 20 -- .../Flow/Floe/Decoding/StructureDecoder.php | 43 --- .../Flow/Floe/Decoding/TimeZoneDecoder.php | 26 -- .../src/Flow/Floe/Decoding/UuidDecoder.php | 48 --- .../src/Flow/Floe/Decoding/ValueDecoder.php | 13 - .../Flow/Floe/Decoding/XmlDocumentDecoder.php | 23 -- .../Flow/Floe/Decoding/XmlElementDecoder.php | 23 -- .../src/Flow/Floe/Encoding/BooleanEncoder.php | 16 - .../Flow/Floe/Encoding/DateTimeEncoder.php | 41 --- .../src/Flow/Floe/Encoding/EnumEncoder.php | 21 -- .../src/Flow/Floe/Encoding/Float64Encoder.php | 18 -- .../Floe/Encoding/HtmlDocumentEncoder.php | 19 -- .../Flow/Floe/Encoding/HtmlElementEncoder.php | 18 -- .../src/Flow/Floe/Encoding/Int64Encoder.php | 18 -- .../Flow/Floe/Encoding/IntervalEncoder.php | 23 -- .../src/Flow/Floe/Encoding/JsonEncoder.php | 21 -- .../src/Flow/Floe/Encoding/ListEncoder.php | 30 -- .../etl/src/Flow/Floe/Encoding/MapEncoder.php | 31 -- .../src/Flow/Floe/Encoding/NullEncoder.php | 16 - .../Flow/Floe/Encoding/OptionalEncoder.php | 22 -- .../Flow/Floe/Encoding/PackedListEncoder.php | 29 -- .../src/Flow/Floe/Encoding/StringEncoder.php | 19 -- .../Flow/Floe/Encoding/StringKeyEncoder.php | 22 -- .../Flow/Floe/Encoding/StructureEncoder.php | 39 --- .../Flow/Floe/Encoding/TimeZoneEncoder.php | 21 -- .../src/Flow/Floe/Encoding/UuidEncoder.php | 18 -- .../src/Flow/Floe/Encoding/ValueEncoder.php | 19 -- .../Flow/Floe/Encoding/XmlDocumentEncoder.php | 18 -- .../Flow/Floe/Encoding/XmlElementEncoder.php | 18 -- .../src/Flow/Floe/Exception/FrameTooLarge.php | 7 + src/core/etl/src/Flow/Floe/FloeEncoder.php | 31 -- src/core/etl/src/Flow/Floe/FloeSerializer.php | 6 +- .../etl/src/Flow/Floe/FloeStreamReader.php | 87 +++--- .../etl/src/Flow/Floe/FloeStreamWriter.php | 95 +++--- src/core/etl/src/Flow/Floe/Format.php | 77 +---- src/core/etl/src/Flow/Floe/FrameDecoder.php | 200 ++++++++++++ src/core/etl/src/Flow/Floe/FrameEncoder.php | 80 +++++ src/core/etl/src/Flow/Floe/FrameWriter.php | 6 +- src/core/etl/src/Flow/Floe/PhpFloeEncoder.php | 229 -------------- src/core/etl/src/Flow/Floe/SchemaDecoder.php | 66 ---- src/core/etl/src/Flow/Floe/ValueDecoder.php | 295 ------------------ src/core/etl/src/Flow/Floe/ValueEncoder.php | 265 ---------------- .../Context/RowsSerializationContext.php | 2 +- .../Flow/ETL/Tests/Double/SpyBackend.php | 9 + .../Storage/FilesystemBucketsTest.php | 24 ++ .../Tests/Unit/Column/BufferLayoutTest.php | 137 ++++++++ .../Unit/Column/Php/ColumnDecoderTest.php | 81 ++++- .../Column/Php/HtmlDocumentPhysicalTest.php | 12 +- .../Column/Php/HtmlElementPhysicalTest.php | 21 +- .../ETL/Tests/Unit/Column/Php/OffsetsTest.php | 3 +- .../Tests/Unit/Column/Php}/TimeZonesTest.php | 4 +- .../Column/Php/XmlDocumentPhysicalTest.php | 9 + .../Column/Php/XmlElementPhysicalTest.php | 20 ++ .../ETL/Tests/Unit/Column/PhpBackendTest.php | 2 +- .../ETL/Tests/Unit/RowsSerializationTest.php | 37 ++- .../tests/Flow/ETL/Tests/Unit/RowsTest.php | 18 ++ .../Floe/Tests/Context/FloeFilesContext.php | 20 -- .../Floe/Tests/Context/FloeGoldenContext.php | 4 +- .../Tests/Context/FloeStreamReaderContext.php | 20 +- .../Flow/Floe/Tests/Context/FrameContext.php | 37 +++ .../Tests/Double/OverflowingColumnStub.php | 94 ++++++ .../Tests/Double/TrailingZerosCodecStub.php | 37 +++ .../all-entry-types.floe | Bin 3597 -> 0 bytes .../Tests/Fixtures/v2/all-entry-types.floe | Bin 3527 -> 4829 bytes .../Floe/Tests/Fixtures/v2/heterogeneous.floe | Bin 442 -> 617 bytes .../Floe/Tests/Integration/FloeGoldenTest.php | 30 +- .../FloePreAllowExtraRemovalTest.php | 39 --- .../Tests/Mother/DateTimeDecoderMother.php | 22 -- .../Flow/Floe/Tests/Mother/RowsMother.php | 8 + .../Unit/Decoding/BooleanDecoderTest.php | 21 -- .../Unit/Decoding/DateTimeDecoderTest.php | 104 ------ .../Tests/Unit/Decoding/EnumDecoderTest.php | 50 --- .../Unit/Decoding/Float64DecoderTest.php | 21 -- .../Unit/Decoding/HtmlDocumentDecoderTest.php | 37 --- .../Unit/Decoding/HtmlElementDecoderTest.php | 34 -- .../Tests/Unit/Decoding/Int64DecoderTest.php | 28 -- .../Unit/Decoding/IntervalDecoderTest.php | 34 -- .../Tests/Unit/Decoding/JsonDecoderTest.php | 26 -- .../Tests/Unit/Decoding/ListDecoderTest.php | 25 -- .../Tests/Unit/Decoding/MapDecoderTest.php | 42 --- .../Tests/Unit/Decoding/NullDecoderTest.php | 19 -- .../Unit/Decoding/OptionalDecoderTest.php | 26 -- .../Unit/Decoding/PackedListDecoderTest.php | 43 --- .../Tests/Unit/Decoding/StringDecoderTest.php | 26 -- .../Unit/Decoding/StructureDecoderTest.php | 49 --- .../Unit/Decoding/TimeZoneDecoderTest.php | 26 -- .../Tests/Unit/Decoding/UuidDecoderTest.php | 28 -- .../Unit/Decoding/XmlDocumentDecoderTest.php | 37 --- .../Unit/Decoding/XmlElementDecoderTest.php | 28 -- .../Unit/Encoding/BooleanEncoderTest.php | 19 -- .../Unit/Encoding/DateTimeEncoderTest.php | 44 --- .../Tests/Unit/Encoding/EnumEncoderTest.php | 25 -- .../Unit/Encoding/Float64EncoderTest.php | 21 -- .../Unit/Encoding/HtmlDocumentEncoderTest.php | 34 -- .../Unit/Encoding/HtmlElementEncoderTest.php | 31 -- .../Tests/Unit/Encoding/Int64EncoderTest.php | 26 -- .../Unit/Encoding/IntervalEncoderTest.php | 28 -- .../Tests/Unit/Encoding/JsonEncoderTest.php | 22 -- .../Tests/Unit/Encoding/ListEncoderTest.php | 22 -- .../Tests/Unit/Encoding/MapEncoderTest.php | 30 -- .../Tests/Unit/Encoding/NullEncoderTest.php | 16 - .../Unit/Encoding/OptionalEncoderTest.php | 23 -- .../Unit/Encoding/PackedListEncoderTest.php | 28 -- .../Tests/Unit/Encoding/StringEncoderTest.php | 21 -- .../Unit/Encoding/StringKeyEncoderTest.php | 24 -- .../Unit/Encoding/StructureEncoderTest.php | 37 --- .../Unit/Encoding/TimeZoneEncoderTest.php | 22 -- .../Tests/Unit/Encoding/UuidEncoderTest.php | 22 -- .../Unit/Encoding/XmlDocumentEncoderTest.php | 26 -- .../Unit/Encoding/XmlElementEncoderTest.php | 29 -- .../Floe/Tests/Unit/FloeExtractorTest.php | 2 +- .../Flow/Floe/Tests/Unit/FloeReaderTest.php | 112 ++----- .../Floe/Tests/Unit/FloeSerializerTest.php | 11 +- .../Floe/Tests/Unit/FloeStreamReaderTest.php | 152 ++++++++- .../Floe/Tests/Unit/FloeStreamWriterTest.php | 142 +++++++-- .../Flow/Floe/Tests/Unit/FloeWriterTest.php | 8 +- .../tests/Flow/Floe/Tests/Unit/FormatTest.php | 11 +- .../Flow/Floe/Tests/Unit/FrameDecoderTest.php | 280 +++++++++++++++++ .../Flow/Floe/Tests/Unit/FrameEncoderTest.php | 104 ++++++ .../Flow/Floe/Tests/Unit/FrameReaderTest.php | 14 +- .../Flow/Floe/Tests/Unit/FrameWriterTest.php | 12 +- .../Floe/Tests/Unit/PhpFloeEncoderTest.php | 290 ----------------- .../Floe/Tests/Unit/SchemaDecoderTest.php | 69 ---- .../Flow/Floe/Tests/Unit/ValueDecoderTest.php | 253 --------------- .../Flow/Floe/Tests/Unit/ValueEncoderTest.php | 103 ------ 156 files changed, 2103 insertions(+), 4638 deletions(-) create mode 100644 src/core/etl/src/Flow/ETL/Column/BufferLayout.php rename src/core/etl/src/Flow/{Floe/Decoding => ETL/Column/Php}/TimeZones.php (90%) create mode 100644 src/core/etl/src/Flow/ETL/Exception/OffsetOverflow.php delete mode 100644 src/core/etl/src/Flow/Floe/ColumnBlueprint.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/BooleanDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/DateTimeDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/EnumDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/Float64Decoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/HtmlDocumentDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/HtmlElementDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/Int64Decoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/IntervalDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/JsonDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/ListDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/MapDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/NullDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/OptionalDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/PackedListDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/StringDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/StructureDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/TimeZoneDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/UuidDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/ValueDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/XmlDocumentDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Decoding/XmlElementDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/BooleanEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/DateTimeEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/EnumEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/Float64Encoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/HtmlDocumentEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/HtmlElementEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/Int64Encoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/IntervalEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/JsonEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/ListEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/MapEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/NullEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/OptionalEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/PackedListEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/StringEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/StringKeyEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/StructureEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/TimeZoneEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/UuidEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/ValueEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/XmlDocumentEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/Encoding/XmlElementEncoder.php create mode 100644 src/core/etl/src/Flow/Floe/Exception/FrameTooLarge.php delete mode 100644 src/core/etl/src/Flow/Floe/FloeEncoder.php create mode 100644 src/core/etl/src/Flow/Floe/FrameDecoder.php create mode 100644 src/core/etl/src/Flow/Floe/FrameEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/PhpFloeEncoder.php delete mode 100644 src/core/etl/src/Flow/Floe/SchemaDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/ValueDecoder.php delete mode 100644 src/core/etl/src/Flow/Floe/ValueEncoder.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/BufferLayoutTest.php rename src/core/etl/tests/Flow/{Floe/Tests/Unit/Decoding => ETL/Tests/Unit/Column/Php}/TimeZonesTest.php (83%) create mode 100644 src/core/etl/tests/Flow/Floe/Tests/Context/FrameContext.php create mode 100644 src/core/etl/tests/Flow/Floe/Tests/Double/OverflowingColumnStub.php create mode 100644 src/core/etl/tests/Flow/Floe/Tests/Double/TrailingZerosCodecStub.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Fixtures/pre-allow-extra-removal/all-entry-types.floe delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Integration/FloePreAllowExtraRemovalTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Mother/DateTimeDecoderMother.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/BooleanDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/DateTimeDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/EnumDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/Float64DecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/HtmlDocumentDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/HtmlElementDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/Int64DecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/IntervalDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/JsonDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/ListDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/MapDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/NullDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/OptionalDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/PackedListDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/StringDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/StructureDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/TimeZoneDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/UuidDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/XmlDocumentDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/XmlElementDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/BooleanEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/DateTimeEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/EnumEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/Float64EncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/HtmlDocumentEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/HtmlElementEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/Int64EncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/IntervalEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/JsonEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/ListEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/MapEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/NullEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/OptionalEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/PackedListEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StringEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StringKeyEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StructureEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/TimeZoneEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/UuidEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/XmlDocumentEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/XmlElementEncoderTest.php create mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/FrameDecoderTest.php create mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/FrameEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/SchemaDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/ValueDecoderTest.php delete mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/ValueEncoderTest.php diff --git a/documentation/components/core/floe.md b/documentation/components/core/floe.md index 6aeaf4c932..5910e05b87 100644 --- a/documentation/components/core/floe.md +++ b/documentation/components/core/floe.md @@ -38,6 +38,8 @@ data_frame() ->run(); ``` +Batches hold at most `withBatchSize()` rows, never spanning two BATCH frames. + The footer is the schema: `from_floe(...)->withSchema()` throws. Change a column's type or zone after reading: ```php @@ -119,7 +121,8 @@ data_frame() ## Limit & Offset Pushdown `limit()` stops reading early, and `withOffset()` skips whole file sections using the footer before -reading, so neither scans the full file: +reading, then passes over every BATCH frame whose row count lies inside the offset without decoding it, so +neither scans the full file: ```php tail(300) as $rows) { } ``` -Both yield `Rows` in batches (default 1000, override with the second argument) and return every row when +Both yield `Rows` in batches of at most 1000 rows (override with the second argument) and return every row when the file holds fewer than the requested count. For the first N through the DataFrame API use `->limit(N)` (pushed into the extractor); `tail()` is a reader-level convenience because it needs the file's total from the footer. @@ -179,7 +182,7 @@ from the footer. `merge_floe()` combines several `.floe` files (same or append-compatible evolving schema) into one. The default byte-splices frame regions without re-encoding a single row - O(bytes); `compact: true` -re-encodes every row, coalescing same-schema runs into fewer sections: +re-reads and re-writes every batch, coalescing same-schema runs into fewer sections: ```php bytes ``` -### Header (6 bytes) +Any other frame type is refused with `Floe found unknown frame type 0x%02X`. + +### BATCH body + +One batch in columnar form: a plaintext directory, then the buffer area. ``` - byte 0 1 2 3 4 5 - ┌────┬────┬────┬────┬────────┬────────┐ - │ 'F'│ 'L'│ 'O'│ 'E'│ version│ flags │ - └────┴────┴────┴────┴────────┴────────┘ - magic "FLOE" 0x02 codec id - (0x00 = no compression) +rowCount u32 +nodeCount u32 +bufferCount u32 +nodes nodeCount × {length u32, nullCount u32} pre-order, every column's type tree +extents bufferCount × {offset u32, length u32} into the buffer area +padding to 8 bytes +buffer area per non-empty buffer: i64 uncompressed length (-1 = stored raw) + bytes, padded to 8 ``` -### Frame envelope +- Nodes per type: scalar and null 1, list 1 + element, map 2 (map, entries) + key + value, structure 1 + children. +- Buffers per node: validity (`''` when the node holds no nulls), then offsets for list, map and string kinds, + then values/data; a null column has none. +- An empty buffer is extent `{0, 0}` with no prefix. +- A codec compresses each buffer on its own; the buffer is stored raw (`-1`) whenever the codec output is not + smaller. The directory is never compressed. -Every frame - `ROW`, `PARTITIONS`, `FOOTER` - shares the same envelope: a 1-byte type, a -4-byte little-endian body length, then the body. +`[['id' => 1, 'name' => 'ab'], ['id' => 2, 'name' => null]]` under `int_schema('id')`, +`str_schema('name', nullable: true)` - 72-byte directory, 80-byte buffer area: ``` - ┌────────┬───────────────┬───────────────────────┐ - │ type │ body length │ body │ - │ 1 byte │ 4 bytes (LE) │ bytes │ - └────────┴───────────────┴───────────────────────┘ - 0x02 ROW 0x03 PARTITIONS 0x06 FOOTER +02000000 02000000 05000000 rows 2, nodes 2, buffers 5 +02000000 00000000 02000000 01000000 id {2,0}, name {2,1} +00000000 00000000 00000000 18000000 18000000 09000000 id validity {0,0}, id values {0,24}, name validity {24,9} +28000000 14000000 40000000 0a000000 00000000 name offsets {40,20}, name data {64,10}, padding +ffffffffffffffff 0100000000000000 0200000000000000 id values +ffffffffffffffff 01 00000000000000 name validity +ffffffffffffffff 000000000200000002000000 00000000 name offsets +ffffffffffffffff 6162 000000000000 name data ``` -The file's schema is not a frame - it carries **exactly one schema**, fixed at session start (explicit, -or the first batch's union) and stored only in the footer (see `schema` below). A row narrower than the -schema rides it (see the ROW absent flag). A later batch that introduces a new column or an incompatible -type throws `IncompatibleSchemaException` - schema evolution lives only in `merge_floe()`. - -- **ROW (`0x02`)** - one row encoded **by column** against the file schema: for each schema - column, in order, a one-byte presence flag - - - `0x01` **present** - followed by the value encoded per the column's schema type, no per-value tag. - - `0x00` **null** - the value is null. - - `0x02` **null with metadata** - a null value carrying per-value metadata that diverges from the - column's schema metadata: a metadata block (4-byte little-endian JSON length + JSON), no value. - - `0x03` **absent** - the row has no such column. - - `0x04` **present with metadata** - a divergent-metadata block (4-byte length + JSON) followed by - the encoded value. - - The two metadata flags (`0x02`, `0x04`) appear only when a row's per-value metadata differs from the - column's schema metadata; otherwise every value uses `0x00`/`0x01`. Every value is encoded positionally - against its column type, so no value carries a type tag. A row whose columns exactly match the section, - with no divergent metadata, produces the same bytes as a plain positional encode. One frame per row. - - A **structure** value nests the same idea one level down: one flag byte per declared element, in the - structure type's declared field order, with no element names on the wire - - - - `0x01` **present** - followed by the element value encoded per its declared type. - - `0x00` **null** - the element key is present in the value, holding null. - - `0x03` **absent** - the value has no such key (an `optional` element that was omitted). - - Because the bytes carry no names, the declared field order binds each flag byte to its element. The - writer looks each element up **by name** in the value and emits in declared order, so a value whose - keys arrive in a different order still produces the declared-order bytes; the reader rebuilds keys - in declared order. -- **PARTITIONS (`0x03`)** - the partition key/value pairs for the section that follows: a 4-byte count - followed by repeated `[nameLen(4), name, valueLen(4), value]`. Written at the start of every section - whose combination differs from the previous one; the reader starts at the empty combination, so an - unpartitioned first section emits none and a later change back to unpartitioned emits a `count=0` - frame. -- **FOOTER (`0x06`)** - the footer JSON followed by the trailer (below). - ### Footer -The `FOOTER` frame body is a JSON object carrying everything needed to read the file **without -scanning rows**: - ```json { "version": 2, "writer": "1.x-dev", - "schema": { /* the file's single schema */ }, - "sections": [ { "offset": 6, "partitionsId": 0, "rowCount": 2 } ], - "partitions": [ { "country": "PL" } ], - "statistics": { "rows": 2, "byteSize": 118 }, - "metadata": { /* typed key/value, Schema\Metadata */ } + "schema": [ /* the file's single schema */ ], + "sections": [ { "offset": 6, "rowCount": 2 } ], + "statistics": { "rows": 2, "byteSize": 157 }, + "metadata": { /* Schema\Metadata */ } } ``` -- **`statistics`** holds the file's row count and the uncompressed bytes of its data frames (header and - footer excluded), so a reader can size the file before reading a row. The footer and its sections - ignore keys they do not know, so a field added later does not break an older reader. - -- **`sections`** map a byte `offset` → `partitionsId` + `rowCount`, so a reader can skip whole sections - (offset/limit pushdown) and know each section's partition combination up front. Sections bound - partition combinations and appends only; every section shares the file's one schema. -- **`partitions`** is the deduplicated, order-preserving table of partition combinations, indexed by - `partitionsId`; the unpartitioned combination is an empty object at its own id. A file can hold many - combinations (one per section). -- **`schema`** is the file's single schema and the sole place it is stored, so every read decodes - against it without scanning the body. On a read, a row narrower than it (an absent column) is padded - with null entries so every yielded row conforms. `merge_floe()` re-encodes drifted sources to their - union, so a merged file is still one schema. +- `sections` - byte `offset` and `rowCount` of each section, for offset/limit pushdown without a scan. +- `statistics` - row count and the bytes of the data frames (header and footer excluded). +- Unknown keys are ignored, so a field added later does not break an older reader. ### Trailer (last 8 bytes) diff --git a/documentation/contributing/wasm.md b/documentation/contributing/wasm.md index 47475e22ab..b67d54f37c 100644 --- a/documentation/contributing/wasm.md +++ b/documentation/contributing/wasm.md @@ -274,7 +274,7 @@ What is now true: - `pack()`/`unpack()` 64-bit format codes (`q`, `Q`, `J`, `P`) work. `Flow\Floe` therefore works, and so does **`sortBy()`** and everything else that spills runs to disk through - `Flow\Floe\Encoding\Int64Encoder`. Before this, every Floe write in the browser died with + `Flow\ETL\Column\Php\Int64Layout` (`pack('P*')`). Before this, every Floe write in the browser died with `ValueError: 64-bit format codes are not available for 32-bit versions of PHP`. - Large integers from Thrift/Parquet metadata no longer overflow to float. On the 32-bit build, reading a parquet file emitted hundreds of @@ -282,7 +282,7 @@ What is now true: `Flow\Parquet\Thrift\CompactProtocol` and `Flow\ETL\Bucketing\HashBucketing`; the 64-bit build emits none. - Hex constants like `0x80000000` are plain integers and need no `(int)` cast. -- `DateTimeEncoder` packs `getTimestamp()`, which now represents dates past 2038-01-19. +- `DateTimePhysical` stores `getTimestamp() * 1_000_000 + µs`, which now represents dates past 2038-01-19. The `(int)` casts in the parquet library's `fromThrift()` methods are **left in place**. They are no longer load-bearing for the playground, but the library still supports 32-bit PHP builds generally, diff --git a/documentation/upgrading.md b/documentation/upgrading.md index b4d2956504..f9d22250e5 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -488,20 +488,20 @@ document written by 0.45.x that has a structure column. Clear APCu and natively ### 49) `flow-php/etl` - `Rows` is a columnar batch, `Row` is a view -| Before | After | -|------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------| -| `new Rows($schema, ...$rows)` | `Rows::of($schema, ...$rows)` / `rows($schema, ...$rows)` | -| `Rows::trusted($schema, $rows)` / `Rows::conformed($schema, $rows)` | `Rows::of($schema, ...$rows)` (views) / `Rows::fromColumns($schema, $columns, $count)` (columns) | -| `new Row(array $values)` | `array_to_row($values, $schema)` | -| - | `new Row(Rows $rows, int $index)` - a view over row `$index` of `$rows` | -| `Row::matchTo()` / `Row::conformTo()` / `Row::project()` | removed - `Rows::matchTo()` / `Rows::project()` | -| `Rows::empty(): bool` | `Rows::isEmpty(): bool` | -| `Row::get()` of a datetime / date / time / uuid / json / xml / html cell - the instance handed in | a new object per call - compare with `assertEquals`, not `assertSame` | -| a `DOMElement` / `HTMLElement` cell keeps its document (parent and siblings reachable) | the cell is the element's own markup - navigate from the document column (`xpath()`) | -| an optional and nullable structure element given `null` | reads back absent (the element's validity bit) | -| `$row == $other` - compares the rows' values | compares both views' whole batches and indices - compare `toArray()` | -| `serialize(Rows)` payload `{schema, rows}` | `{schema, count, columns}` - payloads of 0.44.x cannot be unserialized | -| `Rows::drop()` / `dropRight()` / `take()` / `takeRight()` with a negative size - `array_slice()` semantics | `InvalidArgumentException` | +| Before | After | +|------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| +| `new Rows($schema, ...$rows)` | `Rows::of($schema, ...$rows)` / `rows($schema, ...$rows)` | +| `Rows::trusted($schema, $rows)` / `Rows::conformed($schema, $rows)` | `Rows::of($schema, ...$rows)` (views) / `Rows::fromColumns($schema, $columns, $count)` (columns) | +| `new Row(array $values)` | `array_to_row($values, $schema)` | +| - | `new Row(Rows $rows, int $index)` - a view over row `$index` of `$rows` | +| `Row::matchTo()` / `Row::conformTo()` / `Row::project()` | removed - `Rows::matchTo()` / `Rows::project()` | +| `Rows::empty(): bool` | `Rows::isEmpty(): bool` | +| `Row::get()` of a datetime / date / time / uuid / json / xml / html cell - the instance handed in | a new object per call - compare with `assertEquals`, not `assertSame` | +| a `DOMElement` / `HTMLElement` cell keeps its document (parent and siblings reachable) | the cell is the element's own markup - navigate from the document column (`xpath()`) | +| an optional and nullable structure element given `null` | reads back absent (the element's validity bit) | +| `$row == $other` - compares the rows' values | compares both views' whole batches and indices - compare `toArray()` | +| `serialize(Rows)` payload `{schema, rows}` | `{schema, frame}` - the Floe BATCH body; payloads of 0.44.x cannot be unserialized, a corrupt payload throws `FloeException` | +| `Rows::drop()` / `dropRight()` / `take()` / `takeRight()` with a negative size - `array_slice()` semantics | `InvalidArgumentException` | ### 50) `flow-php/etl` - `row()`, `InferredBatch` and `DataFrame::getEach()` removed @@ -545,10 +545,10 @@ document written by 0.45.x that has a structure column. Clear APCu and natively ### 54) `flow-php/etl` - `FloeEngine` and `NativeFloeEncoder` removed -| Before | After | -|-----------------------------------------------------------------------------------------------------------------------------|--------------------------------------| -| `from_floe(..., engine: ...)` / `to_floe(..., engine: ...)` | removed - Floe runs `PhpFloeEncoder` | -| the `engine` parameter of `FloeReader`, `FloeWriter`, `FloeStreamReader`, `FloeStreamWriter`, `FloeExtractor`, `FloeLoader` | removed | +| Before | After | +|-----------------------------------------------------------------------------------------------------------------------------|---------| +| `from_floe(..., engine: ...)` / `to_floe(..., engine: ...)` | removed | +| the `engine` parameter of `FloeReader`, `FloeWriter`, `FloeStreamReader`, `FloeStreamWriter`, `FloeExtractor`, `FloeLoader` | removed | ### 55) `flow-php/etl` - engine classes follow the batch @@ -609,14 +609,11 @@ different instant; it now stays a `datetime` unless it is cast to a date explici ### 61) `flow-php/etl` - Floe takes a `Backend` -| Before | After | -|-------------------------------------------------------------------------------------------|-----------------------------------------------------------------------| -| `?Hydrator $hydrator` on `FloeReader`, `FloeStreamReader`, `FloeSerializer`, `FloeMerger` | `Backend $backend = new DefaultBackend()` | -| `?Hydrator $hydrator` on `FloeWriter`, `FloeStreamWriter` | removed | -| `new PhpFloeEncoder(Schema)` | `new PhpFloeEncoder(Schema, Backend $backend = new DefaultBackend())` | -| `FloeEncoder::decodeRows(array, Schema, Hydrator)`, `encodeFrames(Rows, Hydrator)` | `decodeRows(array, Schema)`, `encodeFrames(Rows)` | -| `PhpFloeEncoder::encode(list)` | `PhpFloeEncoder::encode(Rows)` | -| `FloeMerger(Filesystem, ?Hydrator, Codec)` | `FloeMerger(Filesystem, Backend, Codec)` | +| Before | After | +|-------------------------------------------------------------------------------------------|-------------------------------------------| +| `?Hydrator $hydrator` on `FloeReader`, `FloeStreamReader`, `FloeSerializer`, `FloeMerger` | `Backend $backend = new DefaultBackend()` | +| `?Hydrator $hydrator` on `FloeWriter`, `FloeStreamWriter` | removed | +| `FloeMerger(Filesystem, ?Hydrator, Codec)` | `FloeMerger(Filesystem, Backend, Codec)` | ### 62) adapters - encoders split into decoders and encoders @@ -664,6 +661,21 @@ Project with `from_parquet(..., columns: [...])`. Change a type after reading, e | Before | After | |-----------------------------------------------|---------------------------------------------| | `RowPartitions::of(Row $row, Schema $schema)` | `RowPartitions::of(Rows $rows, int $index)` | + +### 66) `flow-php/etl` - Floe writes one BATCH frame per batch + +| Before | After | +|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------| +| `FloeEncoder`, `PhpFloeEncoder`, `Format::rowFrames()`, `Format::metadataBytes()`, `Format::readMetadata()`, `Format::FRAME_ROW`, `Format::VALUE_*_BYTE`, `Flow\Floe\ValueEncoder`, `Flow\Floe\Encoding\*` | removed - `Rows::encodeFrame()` / `Flow\Floe\FrameEncoder` | +| `Flow\Floe\Decoding\*`, `Flow\Floe\ValueDecoder`, `Flow\Floe\SchemaDecoder`, `Flow\Floe\ColumnBlueprint` | removed - `Flow\Floe\FrameDecoder` | +| `FrameWriter::row(string $body)` | `FrameWriter::frame(int $type, string $body)` | +| `ValueEncoder::{xmlDocument,xmlElement,htmlElement}ToString()`, `ValueDecoder::{xmlDocument,xmlElement,htmlDocument,htmlElement}FromString()` | removed - `(new XmlDocumentPhysical())->toPhysical()` / `fromPhysical()` and the other `Flow\ETL\Column\Php\*Physical` | +| `Flow\Floe\Decoding\TimeZones` | `Flow\ETL\Column\Php\TimeZones` | +| `Offsets::pack()` throws `InvalidArgumentException` past 2³¹−1 | throws `Flow\ETL\Exception\OffsetOverflow` (extends `InvalidArgumentException`) | +| `from_floe()->withBatchSize($n)`, `FloeReader::rows($n)` - batches of exactly `$n` rows | at most `$n` rows, never spanning two BATCH frames - re-batch with `->batchSize($n)` | +| a codec wraps every frame body | a codec wraps each buffer of a BATCH frame behind an i64 uncompressed length (`-1` = stored raw); the directory stays plaintext | +| a null in a NOT NULL column refused by the Floe writer (`SchemaMismatchException`) | refused by `Rows::fromColumns()` / `withColumns()` with the same exception and message, whatever the sink | +| an XML/HTML value that cannot be converted to or from its string while building a column throws `FloeException` | throws `Flow\ETL\Exception\InvalidArgumentException`, same message | --- ## Upgrading from 0.43.x to 0.44.x diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php b/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php index 3d6a3cf72c..31b559b388 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php @@ -15,6 +15,8 @@ use Flow\Floe\Options; use Generator; +use function array_slice; + final class FilesystemBuckets implements BucketsStorage { private readonly Path $cacheDir; @@ -74,9 +76,25 @@ public function get(string $bucketId): Generator // finally, not a trailing close(): PHP runs it on generator destruction too, and a KWayMerge cursor is // destroyed rather than exhausted when a merge throws + // every append() is one Floe frame and a read never spans two, so small appends are coalesced back into + // batches of up to batchSize rows + $pending = []; + $pendingRows = 0; + try { foreach ($reader->rows($this->batchSize) as $batch) { - yield $batch; + if (($pendingRows + $batch->count()) > $this->batchSize) { + yield $pending[0]->concat(...array_slice($pending, 1)); + $pending = []; + $pendingRows = 0; + } + + $pending[] = $batch; + $pendingRows += $batch->count(); + } + + if ($pending !== []) { + yield $pending[0]->concat(...array_slice($pending, 1)); } } finally { $reader->close(); diff --git a/src/core/etl/src/Flow/ETL/Column/BufferLayout.php b/src/core/etl/src/Flow/ETL/Column/BufferLayout.php new file mode 100644 index 0000000000..9468dcd606 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/BufferLayout.php @@ -0,0 +1,171 @@ + $type + */ + public function nodeCount(Type $type): int + { + $base = $type instanceof OptionalType ? $type->base() : $type; + + if ($base instanceof ListType) { + return 1 + $this->nodeCount($base->element()); + } + + if ($base instanceof MapType) { + return 2 + $this->nodeCount($base->key()) + $this->nodeCount($base->value()); + } + + if ($base instanceof StructureType) { + $nodes = 1; + + foreach ($base->elements() as $element) { + $nodes += $this->nodeCount($element->type); + } + + return $nodes; + } + + return 1; + } + + /** + * @param Type $type + */ + public function bufferCount(Type $type): int + { + $base = $type instanceof OptionalType ? $type->base() : $type; + + if ($base instanceof NullType) { + return 0; + } + + if ($base instanceof ListType) { + return 2 + $this->bufferCount($base->element()); + } + + if ($base instanceof MapType) { + return 3 + $this->bufferCount($base->key()) + $this->bufferCount($base->value()); + } + + if ($base instanceof StructureType) { + $buffers = 1; + + foreach ($base->elements() as $element) { + $buffers += $this->bufferCount($element->type); + } + + return $buffers; + } + + return (new LayoutFor())->type($type) instanceof Utf8Layout ? 3 : 2; + } + + /** + * Pre-order {length, nullCount} of one column's tree: the first node as given, every child derived from the + * buffers - a null kind is {length, length}, list and map children span the last offset, a map entries node + * holds no nulls and structure children span their parent. + * + * @param Type $type + * @param list $buffers + * + * @throws InvalidArgumentException + * + * @return list + */ + public function nodes(Type $type, int $length, int $nullCount, array $buffers): array + { + if (count($buffers) !== $this->bufferCount($type)) { + throw new InvalidArgumentException(sprintf( + 'Column of type %s holds %d buffers, its layout needs %d', + $type->toString(), + count($buffers), + $this->bufferCount($type), + )); + } + + $base = $type instanceof OptionalType ? $type->base() : $type; + $nodes = [[$length, $nullCount]]; + $children = []; + $position = 1; + + if ($base instanceof ListType || $base instanceof MapType) { + if (strlen($buffers[1]) !== (($length + 1) * 4)) { + throw new InvalidArgumentException(sprintf( + '%s offsets buffer of %d bytes, expected %d for %d rows', + $base instanceof ListType ? 'List' : 'Map', + strlen($buffers[1]), + ($length + 1) * 4, + $length, + )); + } + + /** @var int $childLength */ + $childLength = unpack('V', $buffers[1], $length * 4)[1]; + + if ($base instanceof ListType) { + $children[] = [$base->element(), $childLength]; + $position = 2; + } else { + if ($buffers[2] !== '') { + throw new InvalidArgumentException(sprintf( + 'Map entries validity must be omitted, got %d bytes', + strlen($buffers[2]), + )); + } + + $nodes[] = [$childLength, 0]; + $children[] = [$base->key(), $childLength]; + $children[] = [$base->value(), $childLength]; + $position = 3; + } + } elseif ($base instanceof StructureType) { + foreach ($base->elements() as $element) { + $children[] = [$element->type, $length]; + } + } + + foreach ($children as [$childType, $childLength]) { + $childBuffers = array_slice($buffers, $position, $this->bufferCount($childType)); + $position += count($childBuffers); + $childBase = $childType instanceof OptionalType ? $childType->base() : $childType; + + array_push($nodes, ...$this->nodes( + $childType, + $childLength, + $childBase instanceof NullType + ? $childLength + : (new Validity())->nullCount($childBuffers[0], $childLength), + $childBuffers, + )); + } + + return $nodes; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php b/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php index bfcbfbb860..e239fa17c3 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Column\Php; +use Flow\ETL\Column\BufferLayout; use Flow\ETL\Column\Column; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; @@ -14,22 +15,41 @@ use Flow\Types\Type\Native\NullType; use function sprintf; -use function strlen; final readonly class ColumnDecoder { + public function __construct( + private BufferLayout $layout = new BufferLayout(), + ) {} + /** + * Nested nulls follow Arrow: a list element or map value holds nulls only when optional or of the null kind, a map + * key never, a structure child always may (its parent's nulls mask it). + * * @param Type $type - * @param int $nullCount -1 derives the null count from the validity buffer * * @throws InvalidArgumentException */ public function decode(Type $type, Buffers $buffers, int $count, int $nullCount): Column { $base = $type instanceof OptionalType ? $type->base() : $type; + $nodes = []; + $own = $buffers; + + // only a container has child nodes to derive; a flat column reads its buffers straight off the cursor + if ($base instanceof ListType || $base instanceof MapType || $base instanceof StructureType) { + $subtree = []; + + for ($i = $this->layout->bufferCount($type); $i > 0; $i--) { + $subtree[] = $buffers->next(); + } + + $nodes = $this->layout->nodes($type, $count, $nullCount, $subtree); + $own = new Buffers($subtree); + } if ($base instanceof NullType) { - if ($nullCount !== -1 && $nullCount !== $count) { + if ($nullCount !== $count) { throw new InvalidArgumentException(sprintf( 'Null column of %d rows carries a null count of %d', $count, @@ -41,11 +61,11 @@ public function decode(Type $type, Buffers $buffers, int $count, int $nullCount) } $validity = new Validity(); - $bitmap = $buffers->next(); + $bitmap = $own->next(); $valid = $validity->valid($bitmap, $count); $derived = $validity->nullCount($bitmap, $count); - if ($nullCount !== -1 && $nullCount !== $derived) { + if ($nullCount !== $derived) { throw new InvalidArgumentException(sprintf( 'Column null count %d disagrees with its validity bitmap (%d nulls in %d rows)', $nullCount, @@ -55,41 +75,67 @@ public function decode(Type $type, Buffers $buffers, int $count, int $nullCount) } if ($base instanceof ListType) { - $offsets = (new Offsets())->unpack($buffers->next(), $count, 'List'); + $offsets = (new Offsets())->unpack($own->next(), $count, 'List'); + $element = $base->element(); + [$length, $nulls] = $nodes[1]; + + if ($nulls > 0 && !$element instanceof OptionalType && !$element instanceof NullType) { + throw new InvalidArgumentException(sprintf( + 'List child holds %d nulls in a non-nullable %s', + $nulls, + $element->toString(), + )); + } return new ListColumn( $type, $offsets, - $this->decode($base->element(), $buffers, $offsets[$count], -1), + $this->decode($element, $own, $length, $nulls), $validity->nulls($valid), ); } if ($base instanceof MapType) { - $offsets = (new Offsets())->unpack($buffers->next(), $count, 'Map'); - $entries = $buffers->next(); + $offsets = (new Offsets())->unpack($own->next(), $count, 'Map'); + $own->next(); + $key = $base->key(); + $value = $base->value(); + [$length, $keyNulls] = $nodes[2]; + [, $valueNulls] = $nodes[2 + $this->layout->nodeCount($key)]; + + if ($keyNulls > 0) { + throw new InvalidArgumentException(sprintf( + 'Map key child holds %d nulls in a non-nullable %s', + $keyNulls, + $key->toString(), + )); + } - if ($entries !== '') { + if ($valueNulls > 0 && !$value instanceof OptionalType && !$value instanceof NullType) { throw new InvalidArgumentException(sprintf( - 'Map entries validity must be omitted, got %d bytes', - strlen($entries), + 'Map value child holds %d nulls in a non-nullable %s', + $valueNulls, + $value->toString(), )); } return new MapColumn( $type, $offsets, - $this->decode($base->key(), $buffers, $offsets[$count], -1), - $this->decode($base->value(), $buffers, $offsets[$count], -1), + $this->decode($key, $own, $length, $keyNulls), + $this->decode($value, $own, $length, $valueNulls), $validity->nulls($valid), ); } if ($base instanceof StructureType) { $children = []; + $node = 1; foreach ($base->elements() as $element) { - $children[$element->name] = $this->decode($element->type, $buffers, $count, -1); + [$length, $nulls] = $nodes[$node]; + $node += $this->layout->nodeCount($element->type); + $children[$element->name] = $this->decode($element->type, $own, $length, $nulls); } return new StructColumn($type, $children, $validity->nulls($valid)); @@ -100,7 +146,7 @@ public function decode(Type $type, Buffers $buffers, int $count, int $nullCount) (new PhysicalFor())->type($type), (new LayoutFor()) ->type($type) - ->decode($buffers, $count, $valid), + ->decode($own, $count, $valid), $derived, ); } diff --git a/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php index 828a2d8e23..f26feda04b 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php @@ -4,12 +4,16 @@ namespace Flow\ETL\Column\Php; -use Flow\Floe\ValueDecoder; +use Dom\HTMLDocument; +use Flow\ETL\Exception\InvalidArgumentException; use function assert; +use function class_exists; use function is_object; use function is_string; +use const LIBXML_NOERROR; + final readonly class HtmlDocumentPhysical implements Physical { public function toPhysical(mixed $value): mixed @@ -25,7 +29,12 @@ public function fromPhysical(mixed $physical): mixed { assert(is_string($physical)); - return ValueDecoder::htmlDocumentFromString($physical); + if (!class_exists('\Dom\HTMLDocument')) { + throw new InvalidArgumentException('Floe cannot restore HTML values, \Dom\HTMLDocument requires PHP 8.4+'); + } + + // @mago-expect analysis:unavailable-method + return HTMLDocument::createFromString($physical, LIBXML_NOERROR); } public function fromPhysicalAll(array $physicals): array @@ -34,8 +43,7 @@ public function fromPhysicalAll(array $physicals): array // @mago-ignore analysis:mixed-assignment foreach ($physicals as $physical) { - assert($physical === null || is_string($physical)); - $values[] = $physical === null ? null : ValueDecoder::htmlDocumentFromString($physical); + $values[] = $physical === null ? null : $this->fromPhysical($physical); } return $values; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php index ec76bad956..30c58a2e6d 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php @@ -4,12 +4,16 @@ namespace Flow\ETL\Column\Php; -use Flow\Floe\ValueDecoder; -use Flow\Floe\ValueEncoder; +use Dom\HTMLDocument; +use Flow\ETL\Exception\InvalidArgumentException; use function assert; +use function class_exists; use function is_object; use function is_string; +use function sprintf; + +use const LIBXML_NOERROR; final readonly class HtmlElementPhysical implements Physical { @@ -17,14 +21,37 @@ public function toPhysical(mixed $value): mixed { assert(is_object($value)); - return ValueEncoder::htmlElementToString($value); + /** @var \Dom\HTMLElement $value */ + // @mago-ignore analysis:non-existent-method + // @mago-ignore analysis:mixed-assignment + $html = $value->ownerDocument?->saveHtml($value); + + if (!is_string($html)) { + throw new InvalidArgumentException('Floe failed to convert HTMLElement to HTML string'); + } + + return $html; } public function fromPhysical(mixed $physical): mixed { assert(is_string($physical)); - return ValueDecoder::htmlElementFromString($physical); + if (!class_exists('\Dom\HTMLDocument')) { + throw new InvalidArgumentException('Floe cannot restore HTML values, \Dom\HTMLDocument requires PHP 8.4+'); + } + + // @mago-expect analysis:unavailable-method + $element = HTMLDocument::createFromString( + '' . $physical . '', + LIBXML_NOERROR, + )->body?->firstElementChild; + + if ($element === null) { + throw new InvalidArgumentException(sprintf('Floe failed to restore HTMLElement from "%s"', $physical)); + } + + return $element; } public function fromPhysicalAll(array $physicals): array @@ -33,8 +60,7 @@ public function fromPhysicalAll(array $physicals): array // @mago-ignore analysis:mixed-assignment foreach ($physicals as $physical) { - assert($physical === null || is_string($physical)); - $values[] = $physical === null ? null : ValueDecoder::htmlElementFromString($physical); + $values[] = $physical === null ? null : $this->fromPhysical($physical); } return $values; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Offsets.php b/src/core/etl/src/Flow/ETL/Column/Php/Offsets.php index 8a6cc5ed28..2d60f9e5fa 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Offsets.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/Offsets.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Column\Php; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\OffsetOverflow; use function array_values; use function count; @@ -23,7 +24,7 @@ public function pack(array $offsets): string $last = $offsets[count($offsets) - 1]; if ($last > 2_147_483_647) { - throw new InvalidArgumentException(sprintf( + throw new OffsetOverflow(sprintf( 'Offsets exceed the i32 range of a batch buffer: the last offset is %d', $last, )); diff --git a/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php index e25daf6e8f..f3c8d67722 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Column\Php; use DateTimeZone; -use Flow\Floe\Decoding\TimeZones; use function assert; use function is_string; diff --git a/src/core/etl/src/Flow/Floe/Decoding/TimeZones.php b/src/core/etl/src/Flow/ETL/Column/Php/TimeZones.php similarity index 90% rename from src/core/etl/src/Flow/Floe/Decoding/TimeZones.php rename to src/core/etl/src/Flow/ETL/Column/Php/TimeZones.php index c247298c3c..fdb2a16ed0 100644 --- a/src/core/etl/src/Flow/Floe/Decoding/TimeZones.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/TimeZones.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\Floe\Decoding; +namespace Flow\ETL\Column\Php; use DateTimeZone; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php index 57c42045e7..7b2e6d6113 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php @@ -5,11 +5,11 @@ namespace Flow\ETL\Column\Php; use DOMDocument; -use Flow\Floe\ValueDecoder; -use Flow\Floe\ValueEncoder; +use Flow\ETL\Exception\InvalidArgumentException; use function assert; use function is_string; +use function sprintf; final readonly class XmlDocumentPhysical implements Physical { @@ -17,14 +17,26 @@ public function toPhysical(mixed $value): mixed { assert($value instanceof DOMDocument); - return ValueEncoder::xmlDocumentToString($value); + $xml = $value->saveXML(); + + if ($xml === false) { + throw new InvalidArgumentException('Floe failed to convert DOMDocument to XML string'); + } + + return $xml; } public function fromPhysical(mixed $physical): mixed { assert(is_string($physical)); - return ValueDecoder::xmlDocumentFromString($physical); + $document = new DOMDocument(); + + if (!@$document->loadXML($physical)) { + throw new InvalidArgumentException(sprintf('Floe failed to restore DOMDocument from "%s"', $physical)); + } + + return $document; } public function fromPhysicalAll(array $physicals): array @@ -33,8 +45,7 @@ public function fromPhysicalAll(array $physicals): array // @mago-ignore analysis:mixed-assignment foreach ($physicals as $physical) { - assert($physical === null || is_string($physical)); - $values[] = $physical === null ? null : ValueDecoder::xmlDocumentFromString($physical); + $values[] = $physical === null ? null : $this->fromPhysical($physical); } return $values; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php index b28931675c..49e16486e3 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php @@ -4,12 +4,14 @@ namespace Flow\ETL\Column\Php; +use DOMDocument; use DOMElement; -use Flow\Floe\ValueDecoder; -use Flow\Floe\ValueEncoder; +use Flow\ETL\Exception\InvalidArgumentException; use function assert; +use function Flow\Types\DSL\type_instance_of; use function is_string; +use function sprintf; /** * A \Dom\Element (PHP 8.4) is stored by its markup too and reads back as the DOMElement XMLElementType::cast() builds @@ -17,10 +19,20 @@ */ final readonly class XmlElementPhysical implements Physical { + public function __construct( + private XmlDocumentPhysical $document = new XmlDocumentPhysical(), + ) {} + public function toPhysical(mixed $value): mixed { if ($value instanceof DOMElement) { - return ValueEncoder::xmlElementToString($value); + $xml = $value->ownerDocument?->saveXML($value); + + if ($xml === null || $xml === false) { + throw new InvalidArgumentException('Floe failed to convert DOMElement to XML string'); + } + + return $xml; } /** @var \Dom\Element $value */ @@ -36,7 +48,15 @@ public function fromPhysical(mixed $physical): mixed { assert(is_string($physical)); - return ValueDecoder::xmlElementFromString($physical); + $element = type_instance_of(DOMDocument::class)->assert($this->document->fromPhysical( + $physical, + ))->documentElement; + + if ($element === null) { + throw new InvalidArgumentException(sprintf('Floe failed to restore DOMElement from "%s"', $physical)); + } + + return $element; } public function fromPhysicalAll(array $physicals): array @@ -45,8 +65,7 @@ public function fromPhysicalAll(array $physicals): array // @mago-ignore analysis:mixed-assignment foreach ($physicals as $physical) { - assert($physical === null || is_string($physical)); - $values[] = $physical === null ? null : ValueDecoder::xmlElementFromString($physical); + $values[] = $physical === null ? null : $this->fromPhysical($physical); } return $values; diff --git a/src/core/etl/src/Flow/ETL/Exception/OffsetOverflow.php b/src/core/etl/src/Flow/ETL/Exception/OffsetOverflow.php new file mode 100644 index 0000000000..26cb8bcca2 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Exception/OffsetOverflow.php @@ -0,0 +1,7 @@ +, nullCount: int}> - * } + * @type RowsPayload = array{schema: Schema, frame: string} * * @implements \ArrayAccess * @implements \IteratorAggregate @@ -75,13 +73,7 @@ private function __construct( */ public function __serialize(): array { - $columns = []; - - foreach ($this->columns as $name => $column) { - $columns[$name] = ['buffers' => $column->encode(), 'nullCount' => $column->nullCount()]; - } - - return ['schema' => $this->schema, 'count' => $this->count, 'columns' => $columns]; + return ['schema' => $this->schema, 'frame' => $this->encodeFrame()]; } /** @@ -89,23 +81,7 @@ public function __serialize(): array */ public function __unserialize(array $data): void { - if (array_keys($data['columns']) !== array_keys($data['schema']->definitions())) { - throw new InvalidArgumentException(sprintf( - 'Rows::fromColumns() expects columns [%s], got [%s]', - implode(', ', array_keys($data['schema']->definitions())), - implode(', ', array_keys($data['columns'])), - )); - } - - $backend = new PhpBackend(); - $columns = []; - - foreach ($data['schema']->definitions() as $name => $definition) { - $column = $data['columns'][$name]; - $columns[$name] = $backend->decode($definition, $column['buffers'], $data['count'], $column['nullCount']); - } - - $rows = self::fromColumns($data['schema'], $columns, $data['count']); + $rows = (new FrameDecoder())->decode($data['frame'], $data['schema'], new PhpBackend()); $this->schema = $rows->schema; $this->columns = $rows->columns; @@ -159,6 +135,7 @@ public static function of(Schema $schema, Row ...$rows): self * @param array $columns keyed and ordered by $schema, every one of $count rows * * @throws InvalidArgumentException + * @throws SchemaMismatchException a NOT NULL column holds a null */ public static function fromColumns(Schema $schema, array $columns, int $count): self { @@ -181,6 +158,21 @@ public static function fromColumns(Schema $schema, array $columns, int $count): } } + foreach ($schema->definitions() as $name => $definition) { + if (!$definition->isNullable() && $columns[$name]->nullCount() > 0) { + $index = 0; + + while (!$columns[$name]->isNull($index)) { + $index++; + } + + throw new SchemaMismatchException($index, ColumnMismatchException::valueDoesNotMatch( + $definition, + null, + )); + } + } + return new self($schema, $columns, $count); } @@ -252,6 +244,11 @@ public function columns(): array return $this->columns; } + public function encodeFrame(): string + { + return (new FrameEncoder())->encode($this); + } + /** * Every input carries this schema; zero-row inputs add no rows. * diff --git a/src/core/etl/src/Flow/Floe/Codec.php b/src/core/etl/src/Flow/Floe/Codec.php index 22198f50c2..4ea4fea019 100644 --- a/src/core/etl/src/Flow/Floe/Codec.php +++ b/src/core/etl/src/Flow/Floe/Codec.php @@ -5,8 +5,8 @@ namespace Flow\Floe; /** - * Compression codec contract for ROW frame bodies. Only the no-op codec (id 0x00) - * is supported; the codec id is stamped into the header flags byte. + * Compression codec contract, applied per buffer of a BATCH frame (behind an i64 uncompressed-length prefix, -1 = + * stored raw). Only the no-op codec (id 0x00) is supported; the codec id is stamped into the header flags byte. */ interface Codec { diff --git a/src/core/etl/src/Flow/Floe/ColumnBlueprint.php b/src/core/etl/src/Flow/Floe/ColumnBlueprint.php deleted file mode 100644 index 16464ec222..0000000000 --- a/src/core/etl/src/Flow/Floe/ColumnBlueprint.php +++ /dev/null @@ -1,19 +0,0 @@ - $definition - */ - public function __construct( - public string $name, - public Definition $definition, - public Decoding\ValueDecoder $decoder, - ) {} -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/BooleanDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/BooleanDecoder.php deleted file mode 100644 index 885ff07310..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/BooleanDecoder.php +++ /dev/null @@ -1,13 +0,0 @@ -setTimezone($this->columnZone ?? $this->timeZones->get($timezoneName)); - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/EnumDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/EnumDecoder.php deleted file mode 100644 index 3763a976b8..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/EnumDecoder.php +++ /dev/null @@ -1,39 +0,0 @@ -y = $fields['y']; - // @mago-ignore analysis:invalid-property-write - $value->m = $fields['m']; - // @mago-ignore analysis:invalid-property-write - $value->d = $fields['d']; - // @mago-ignore analysis:invalid-property-write - $value->h = $fields['h']; - // @mago-ignore analysis:invalid-property-write - $value->i = $fields['i']; - // @mago-ignore analysis:invalid-property-write - $value->s = $fields['s']; - // @mago-ignore analysis:invalid-property-write - $value->f = $fraction; - // @mago-ignore analysis:invalid-property-write - $value->invert = $invert; - - return $value; - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/JsonDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/JsonDecoder.php deleted file mode 100644 index fd0c7f831a..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/JsonDecoder.php +++ /dev/null @@ -1,27 +0,0 @@ -factory->create($json); - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/ListDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/ListDecoder.php deleted file mode 100644 index 7bb9f1d9ec..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/ListDecoder.php +++ /dev/null @@ -1,30 +0,0 @@ - - */ - public function decode(string $data, int &$position): array - { - $count = unpack('V', $data, $position)[1]; - $position += 4; - $values = []; - - for ($i = 0; $i < $count; $i++) { - $values[] = $this->element->decode($data, $position); - } - - return $values; - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/MapDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/MapDecoder.php deleted file mode 100644 index 4213c1852e..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/MapDecoder.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ - public function decode(string $data, int &$position): array - { - $count = unpack('V', $data, $position)[1]; - $position += 4; - $values = []; - - for ($i = 0; $i < $count; $i++) { - /** @var array-key $key */ - $key = $this->key->decode($data, $position); - $values[$key] = $this->value->decode($data, $position); - } - - return $values; - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/NullDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/NullDecoder.php deleted file mode 100644 index 99ffeef51a..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/NullDecoder.php +++ /dev/null @@ -1,13 +0,0 @@ -base->decode($data, $position); - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/PackedListDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/PackedListDecoder.php deleted file mode 100644 index 5596dc5f05..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/PackedListDecoder.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ - public function decode(string $data, int &$position): array - { - $count = unpack('V', $data, $position)[1]; - $position += 4; - - if ($count === 0) { - return []; - } - - $values = array_values(unpack($this->format . '*', substr($data, $position, $count * 8))); - $position += $count * 8; - - return $values; - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/StringDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/StringDecoder.php deleted file mode 100644 index b9bba92ae4..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/StringDecoder.php +++ /dev/null @@ -1,20 +0,0 @@ - $elements structure element name => decoder - */ - public function __construct( - private readonly array $elements, - ) {} - - /** - * @return array - */ - public function decode(string $data, int &$position): array - { - $structure = []; - - foreach ($this->elements as $name => $element) { - $flag = ord($data[$position++]); - - if ($flag === Format::VALUE_PRESENT) { - $structure[$name] = $element->decode($data, $position); - } elseif ($flag === Format::VALUE_NULL) { - $structure[$name] = null; - } elseif ($flag !== Format::VALUE_ABSENT) { - throw new FloeException(sprintf('Floe found unknown structure element flag 0x%02X', $flag)); - } - } - - return $structure; - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/TimeZoneDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/TimeZoneDecoder.php deleted file mode 100644 index 3c6e1aa1a4..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/TimeZoneDecoder.php +++ /dev/null @@ -1,26 +0,0 @@ -timeZones->get($name); - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/UuidDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/UuidDecoder.php deleted file mode 100644 index 2268b9dd5b..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/UuidDecoder.php +++ /dev/null @@ -1,48 +0,0 @@ -newInstanceWithoutConstructor(); - $uuid->value = $value; - - return $uuid; - }, - null, - Uuid::class, - ); - - $this->create = $create; - } - - public function decode(string $data, int &$position): Uuid - { - $length = unpack('V', $data, $position)[1]; - $value = ($this->create)(substr($data, $position + 4, $length)); - $position += 4 + $length; - - return $value; - } -} diff --git a/src/core/etl/src/Flow/Floe/Decoding/ValueDecoder.php b/src/core/etl/src/Flow/Floe/Decoding/ValueDecoder.php deleted file mode 100644 index 33016d4dd8..0000000000 --- a/src/core/etl/src/Flow/Floe/Decoding/ValueDecoder.php +++ /dev/null @@ -1,13 +0,0 @@ - - */ -final class BooleanEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return $value ? "\x01" : "\x00"; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/DateTimeEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/DateTimeEncoder.php deleted file mode 100644 index 122073cda6..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/DateTimeEncoder.php +++ /dev/null @@ -1,41 +0,0 @@ - - */ -final class DateTimeEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - // The class is not stored: a datetime column always hydrates to DateTimeImmutable, so a - // flag distinguishing the two would describe nothing a reader can observe. Custom - // subclasses are still refused - their extra state would be silently dropped. - if ($value::class !== DateTimeImmutable::class && $value::class !== DateTime::class) { - throw new FloeException(sprintf( - 'Floe supports only DateTime and DateTimeImmutable, got %s - convert custom datetime instances before writing', - $value::class, - )); - } - - $timezone = $value->getTimezone()->getName(); - - return ( - pack('P', $value->getTimestamp()) - . pack('V', (int) $value->format('u')) - . pack('V', strlen($timezone)) - . $timezone - ); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/EnumEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/EnumEncoder.php deleted file mode 100644 index 09b9ea1a2a..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/EnumEncoder.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -final class EnumEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - $class = $value::class; - - return pack('V', strlen($class)) . $class . pack('V', strlen($value->name)) . $value->name; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/Float64Encoder.php b/src/core/etl/src/Flow/Floe/Encoding/Float64Encoder.php deleted file mode 100644 index 23c68c9683..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/Float64Encoder.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class Float64Encoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return pack('e', $value); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/HtmlDocumentEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/HtmlDocumentEncoder.php deleted file mode 100644 index cb5e0d44c2..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/HtmlDocumentEncoder.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final class HtmlDocumentEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - // @mago-ignore analysis:unavailable-method - return ValueEncoderFactory::lengthPrefixed($value->saveHtml()); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/HtmlElementEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/HtmlElementEncoder.php deleted file mode 100644 index e7b997d12f..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/HtmlElementEncoder.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class HtmlElementEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return ValueEncoderFactory::lengthPrefixed(ValueEncoderFactory::htmlElementToString($value)); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/Int64Encoder.php b/src/core/etl/src/Flow/Floe/Encoding/Int64Encoder.php deleted file mode 100644 index 8855c53b50..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/Int64Encoder.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class Int64Encoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return pack('P', $value); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/IntervalEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/IntervalEncoder.php deleted file mode 100644 index d30eec1dba..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/IntervalEncoder.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -final class IntervalEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return ( - chr($value->invert) - . pack('VVVVVV', $value->y, $value->m, $value->d, $value->h, $value->i, $value->s) - . pack('e', $value->f) - ); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/JsonEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/JsonEncoder.php deleted file mode 100644 index f864064292..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/JsonEncoder.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -final class JsonEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - $json = $value->toString(); - - return pack('V', strlen($json)) . $json . ($value->isObject() ? "\x01" : "\x00"); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/ListEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/ListEncoder.php deleted file mode 100644 index 4b62d1cec4..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/ListEncoder.php +++ /dev/null @@ -1,30 +0,0 @@ -> - */ -final class ListEncoder implements ValueEncoder -{ - public function __construct( - private readonly ValueEncoder $element, - ) {} - - public function encode(mixed $value): string - { - $buffer = pack('V', count($value)); - - // @mago-ignore analysis:mixed-assignment - foreach ($value as $item) { - $buffer .= $this->element->encode($item); - } - - return $buffer; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/MapEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/MapEncoder.php deleted file mode 100644 index 8d5efeacfd..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/MapEncoder.php +++ /dev/null @@ -1,31 +0,0 @@ -> - */ -final class MapEncoder implements ValueEncoder -{ - public function __construct( - private readonly ValueEncoder $key, - private readonly ValueEncoder $value, - ) {} - - public function encode(mixed $value): string - { - $buffer = pack('V', count($value)); - - // @mago-ignore analysis:mixed-assignment - foreach ($value as $key => $item) { - $buffer .= $this->key->encode($key) . $this->value->encode($item); - } - - return $buffer; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/NullEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/NullEncoder.php deleted file mode 100644 index bf0ff74273..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/NullEncoder.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -final class NullEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return ''; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/OptionalEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/OptionalEncoder.php deleted file mode 100644 index efc3fceae6..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/OptionalEncoder.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final class OptionalEncoder implements ValueEncoder -{ - public function __construct( - private readonly ValueEncoder $base, - ) {} - - public function encode(mixed $value): string - { - return $value === null ? Format::VALUE_NULL_BYTE : Format::VALUE_PRESENT_BYTE . $this->base->encode($value); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/PackedListEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/PackedListEncoder.php deleted file mode 100644 index 47a5e74161..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/PackedListEncoder.php +++ /dev/null @@ -1,29 +0,0 @@ -> - */ -final class PackedListEncoder implements ValueEncoder -{ - /** - * @param 'e'|'P' $format - */ - public function __construct( - private readonly string $format, - ) {} - - public function encode(mixed $value): string - { - return count($value) === 0 ? pack('V', 0) : pack('V', count($value)) . pack($this->format . '*', ...$value); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/StringEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/StringEncoder.php deleted file mode 100644 index 4669e6ddf0..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/StringEncoder.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final class StringEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return pack('V', strlen($value)) . $value; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/StringKeyEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/StringKeyEncoder.php deleted file mode 100644 index 9cf0395ef2..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/StringKeyEncoder.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -final class StringKeyEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return pack('V', strlen((string) $value)) . $value; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/StructureEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/StructureEncoder.php deleted file mode 100644 index dff4e44673..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/StructureEncoder.php +++ /dev/null @@ -1,39 +0,0 @@ -> - */ -final class StructureEncoder implements ValueEncoder -{ - /** - * @param array> $elements structure element name => encoder - */ - public function __construct( - private readonly array $elements, - ) {} - - public function encode(mixed $value): string - { - $buffer = ''; - - foreach ($this->elements as $name => $element) { - if (!array_key_exists($name, $value)) { - $buffer .= Format::VALUE_ABSENT_BYTE; - } elseif ($value[$name] === null) { - $buffer .= Format::VALUE_NULL_BYTE; - } else { - $buffer .= Format::VALUE_PRESENT_BYTE . $element->encode($value[$name]); - } - } - - return $buffer; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/TimeZoneEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/TimeZoneEncoder.php deleted file mode 100644 index 589fef9d07..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/TimeZoneEncoder.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -final class TimeZoneEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - $name = $value->getName(); - - return pack('V', strlen($name)) . $name; - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/UuidEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/UuidEncoder.php deleted file mode 100644 index 7eb4e73381..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/UuidEncoder.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class UuidEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return ValueEncoderFactory::lengthPrefixed($value->toString()); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/ValueEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/ValueEncoder.php deleted file mode 100644 index 07365b0111..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/ValueEncoder.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final class XmlDocumentEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return ValueEncoderFactory::lengthPrefixed(ValueEncoderFactory::xmlDocumentToString($value)); - } -} diff --git a/src/core/etl/src/Flow/Floe/Encoding/XmlElementEncoder.php b/src/core/etl/src/Flow/Floe/Encoding/XmlElementEncoder.php deleted file mode 100644 index 32d4b7f2be..0000000000 --- a/src/core/etl/src/Flow/Floe/Encoding/XmlElementEncoder.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ -final class XmlElementEncoder implements ValueEncoder -{ - public function encode(mixed $value): string - { - return ValueEncoderFactory::lengthPrefixed(ValueEncoderFactory::xmlElementToString($value)); - } -} diff --git a/src/core/etl/src/Flow/Floe/Exception/FrameTooLarge.php b/src/core/etl/src/Flow/Floe/Exception/FrameTooLarge.php new file mode 100644 index 0000000000..3354119107 --- /dev/null +++ b/src/core/etl/src/Flow/Floe/Exception/FrameTooLarge.php @@ -0,0 +1,7 @@ + $bodies - * - * @throws FloeException - * @throws SchemaMismatchException - */ - public function decodeRows(array $bodies, Schema $schema): Rows; - - /** - * `Format::rowFrames($this->encode($rows))`. - * - * @throws FloeException - * @throws SchemaMismatchException - */ - public function encodeFrames(Rows $rows): string; -} diff --git a/src/core/etl/src/Flow/Floe/FloeSerializer.php b/src/core/etl/src/Flow/Floe/FloeSerializer.php index 3bbfa3b1d4..c21ed81af6 100644 --- a/src/core/etl/src/Flow/Floe/FloeSerializer.php +++ b/src/core/etl/src/Flow/Floe/FloeSerializer.php @@ -7,6 +7,7 @@ use Flow\ETL\Column\Backend; use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; use Flow\Floe\Codec\NoopCodec; @@ -15,6 +16,7 @@ use Flow\Serializer\Exception\SerializationException; use Flow\Serializer\Serializer; +use function array_slice; use function sprintf; final class FloeSerializer implements Serializer @@ -70,7 +72,9 @@ public function unserialize(SourceStream $source): Rows )); } - return Rows::of($reader->schema())->concat(...$batches); + return $batches === [] + ? (new RowsBuilder($reader->schema(), $this->backend))->finish() + : $batches[0]->concat(...array_slice($batches, 1)); } catch (FloeException|ExtensionException $e) { throw new SerializationException($e->getMessage(), 0, $e); } finally { diff --git a/src/core/etl/src/Flow/Floe/FloeStreamReader.php b/src/core/etl/src/Flow/Floe/FloeStreamReader.php index de2e400a56..ec7a2b1fa4 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamReader.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamReader.php @@ -10,15 +10,12 @@ use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; use Flow\Filesystem\SourceStream; -use Flow\Floe\Codec\NoopCodec; use Flow\Floe\Exception\ExtensionException; use Flow\Floe\Exception\FloeException; use Flow\Serializer\Exception\SerializationException; use Generator; -use function count; use function max; -use function min; use function ord; use function sprintf; use function strlen; @@ -27,12 +24,12 @@ final class FloeStreamReader { - private ?FloeEncoder $encoder = null; - private ?Footer $footer = null; private ?Schema $schema = null; + private readonly FrameDecoder $frameDecoder; + /** * @throws FloeException */ @@ -43,6 +40,7 @@ public function __construct( private readonly Backend $backend = new DefaultBackend(), ) { Format::validateCodecId($this->codec->id()); + $this->frameDecoder = new FrameDecoder($this->codec); } public function close(): void @@ -50,11 +48,6 @@ public function close(): void $this->source->close(); } - private function encoder(Schema $schema): FloeEncoder - { - return $this->encoder ??= new PhpFloeEncoder($schema, $this->backend); - } - /** * @throws FloeException */ @@ -74,7 +67,8 @@ public function metadata(): Metadata /** * Hot path: frames are walked in-buffer. offset skips whole leading sections * using the footer, then the remaining rows inside the start section; limit - * stops the read after that many rows. + * stops the read after that many rows. Batches are frame-sized: batchSize is + * an upper bound, a batch never spans two BATCH frames. * * @param int<1, max> $batchSize * @@ -167,6 +161,8 @@ public function tail(int $count, int $batchSize = 1000): Generator * The single strict frame-walk shared by rows() and rowsFromOffset(); they * differ only in how it is seeded - start position and skip. The * file carries exactly one schema, so decode state comes from the footer. + * Every BATCH frame yields at most batchSize rows per batch; a frame wholly + * inside skip is passed over without decoding. * * @param \Generator $chunks * @param int<1, max> $batchSize @@ -187,10 +183,6 @@ private function walk( $fill = FrameReader::chunkFiller($buffer, $position, $chunks); $yielded = 0; - /** @var list $pending */ - $pending = []; - $flushThreshold = $limit !== null && $limit < $batchSize ? $limit : $batchSize; - $transforms = !$this->codec instanceof NoopCodec; try { while (true) { @@ -212,29 +204,48 @@ private function walk( $frameEnd = $position + $frameLength; - if ($frameType === Format::FRAME_ROW) { - if ($skip > 0) { - $skip--; - } else { - $body = substr($buffer, $position, $frameLength); - $pending[] = $transforms ? $this->codec->decode($body) : $body; + if ($frameType === Format::FRAME_BATCH) { + if ($frameLength < 4) { + throw new FloeException('Floe BATCH frame is truncated, its directory is incomplete'); } - $position = $frameEnd; + /** @var int $rowCount */ + $rowCount = unpack('V', $buffer, $position)[1]; + + if ($skip >= $rowCount) { + $skip -= $rowCount; + } else { + $rows = $this->frameDecoder->decode( + substr($buffer, $position, $frameLength), + $schema, + $this->backend, + ); + + if ($skip > 0) { + $rows = $rows->slice($skip, $rows->count() - $skip); + $skip = 0; + } - if (count($pending) === $flushThreshold) { - yield $this->decode($schema, $pending); - $yielded += $flushThreshold; - $pending = []; + if ($limit !== null && $rows->count() > ($limit - $yielded)) { + $rows = $rows->slice(0, $limit - $yielded); + } - if ($limit !== null) { - if ($yielded === $limit) { - return; + if ($rows->count() <= $batchSize) { + yield $rows; + } else { + foreach ($rows->chunks($batchSize) as $chunk) { + yield $chunk; } + } - $flushThreshold = min($batchSize, $limit - $yielded); + $yielded += $rows->count(); + + if ($limit !== null && $yielded === $limit) { + return; } } + + $position = $frameEnd; } elseif ($frameType === Format::FRAME_FOOTER) { $position = $frameEnd; } else { @@ -246,27 +257,11 @@ private function walk( $position = 0; } } - - if ($pending !== []) { - yield $this->decode($schema, $pending); - } } catch (SerializationException|ExtensionException $e) { throw new FloeException($e->getMessage(), 0, $e); } } - /** - * A batch carries the file schema even when `decodeRows` folded per-value metadata into a schema of its own. - * - * @param list $pending - */ - private function decode(Schema $schema, array $pending): Rows - { - $rows = $this->encoder($schema)->decodeRows($pending, $schema); - - return $rows->schema() === $schema ? $rows : $rows->withSchema($schema); - } - /** * @throws FloeException */ diff --git a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php index 8a74030abc..b910b50f3d 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php @@ -5,16 +5,20 @@ namespace Flow\Floe; use Composer\InstalledVersions; +use Flow\ETL\Exception\OffsetOverflow; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; use Flow\ETL\Schema\Validator\EvolvingValidator; use Flow\Filesystem\DestinationStream; -use Flow\Floe\Codec\NoopCodec; use Flow\Floe\Exception\FloeException; +use Flow\Floe\Exception\FrameTooLarge; use Flow\Floe\Exception\IncompatibleSchemaException; use function array_key_exists; +use function array_shift; +use function array_unshift; +use function intdiv; use function sprintf; final class FloeStreamWriter @@ -49,12 +53,12 @@ final class FloeStreamWriter private Schema $sessionSchema; - private ?PhpFloeEncoder $sessionEncoder = null; - private ?FrameWriter $frameWriter = null; private int $totalRows = 0; + private readonly FrameEncoder $frameEncoder; + /** * @throws FloeException */ @@ -64,6 +68,7 @@ public function __construct( ) { Format::validateCodecId($this->options->codec->id()); $this->sessionSchema = $schema; + $this->frameEncoder = new FrameEncoder($this->options->codec); } /** @@ -147,24 +152,46 @@ public function write(Rows $rows): void return; } - $this->openSession(); - $this->assertBatchFitsSession($rows->schema()); - - $matched = $rows->schema()->isSame($this->sessionSchema) ? $rows : $rows->matchTo($this->sessionSchema); - - if ($this->options->codec instanceof NoopCodec) { - $frames = $this->sessionEncoder()->encodeFrames($matched); + $matched = $rows; - $this->startSectionWhenDue(); - $this->frameWriter()->raw($frames); - $this->sectionRowCount += $matched->count(); - $this->totalRows += $matched->count(); + if (!$rows->schema()->isSame($this->sessionSchema)) { + $this->assertBatchFitsSession($rows->schema()); + $matched = $rows->matchTo($this->sessionSchema); + } - return; + $bodies = []; + $parts = [[$matched, 0]]; + + while ($parts !== []) { + [$part, $start] = array_shift($parts); + + try { + $bodies[] = [$this->frameEncoder->encode($part), $part->count()]; + } catch (OffsetOverflow|FrameTooLarge $e) { + if ($part->count() === 1) { + $message = sprintf('%s (row %d)', $e->getMessage(), $start); + + throw $e instanceof OffsetOverflow + ? new OffsetOverflow($message, 0, $e) + : new FrameTooLarge($message, 0, $e); + } + + $half = intdiv($part->count(), 2); + array_unshift( + $parts, + [$part->slice(0, $half), $start], + [$part->slice($half, $part->count() - $half), $start + $half], + ); + } } $this->startSectionWhenDue(); - $this->emitBatch($this->sessionEncoder()->encode($matched)); + + foreach ($bodies as [$body, $count]) { + $this->frameWriter()->frame(Format::FRAME_BATCH, $body); + $this->sectionRowCount += $count; + $this->totalRows += $count; + } } public static function writerVersion(): string @@ -174,18 +201,6 @@ public static function writerVersion(): string : 'unknown'; } - /** - * @throws FloeException - */ - private function openSession(): void - { - if ($this->sessionEncoder !== null) { - return; - } - - $this->sessionEncoder = new PhpFloeEncoder($this->sessionSchema); - } - /** * @throws IncompatibleSchemaException */ @@ -194,7 +209,7 @@ private function assertBatchFitsSession(Schema $batch): void $definitions = $this->sessionSchema->definitions(); // unconditional, and before the validator: EvolvingValidator admits a nullable extra column, - // which the session encoder would then drop - silent column loss is not unlockable here + // which the session schema cannot carry foreach ($batch->definitions() as $name => $_) { if (!array_key_exists($name, $definitions)) { throw new IncompatibleSchemaException(sprintf(self::BATCH_MISMATCH, sprintf('new column "%s"', $name))); @@ -208,20 +223,6 @@ private function assertBatchFitsSession(Schema $batch): void } } - /** - * @param list $bodies - * - * @throws FloeException - */ - private function emitBatch(array $bodies): void - { - foreach ($bodies as $encoded) { - $this->frameWriter()->row($this->options->codec->encode($encoded)); - $this->sectionRowCount++; - $this->totalRows++; - } - } - private function closeSection(): void { if ($this->sectionOpen) { @@ -273,14 +274,6 @@ private function startSection(): void $this->sectionRowCount = 0; } - /** - * @throws FloeException - */ - private function sessionEncoder(): PhpFloeEncoder - { - return $this->sessionEncoder ?? throw new FloeException('Floe writer has no active session encoder'); - } - /** * @throws FloeException */ diff --git a/src/core/etl/src/Flow/Floe/Format.php b/src/core/etl/src/Flow/Floe/Format.php index bf4c32517f..814cb97f91 100644 --- a/src/core/etl/src/Flow/Floe/Format.php +++ b/src/core/etl/src/Flow/Floe/Format.php @@ -4,13 +4,9 @@ namespace Flow\Floe; -use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; -use JsonException; use function chr; -use function json_decode; -use function json_encode; use function ord; use function pack; use function sprintf; @@ -19,8 +15,6 @@ use function substr; use function unpack; -use const JSON_THROW_ON_ERROR; - final class Format { public const string MAGIC = 'FLOE'; @@ -33,84 +27,15 @@ final class Format public const int FRAME_HEADER_LENGTH = 5; - public const int FRAME_ROW = 0x02; + public const int FRAME_BATCH = 0x05; public const int FRAME_FOOTER = 0x06; - public const int VALUE_NULL = 0x00; - - public const int VALUE_PRESENT = 0x01; - - public const int VALUE_NULL_WITH_META = 0x02; - - public const int VALUE_ABSENT = 0x03; - - public const int VALUE_PRESENT_WITH_META = 0x04; - - public const string VALUE_NULL_BYTE = "\x00"; - - public const string VALUE_PRESENT_BYTE = "\x01"; - - public const string VALUE_NULL_WITH_META_BYTE = "\x02"; - - public const string VALUE_ABSENT_BYTE = "\x03"; - - public const string VALUE_PRESENT_WITH_META_BYTE = "\x04"; - public static function frame(int $type, string $body): string { return chr($type) . pack('V', strlen($body)) . $body; } - /** - * @param list $bodies - */ - public static function rowFrames(array $bodies): string - { - $frames = ''; - - foreach ($bodies as $body) { - $frames .= self::frame(self::FRAME_ROW, $body); - } - - return $frames; - } - - /** - * @throws FloeException - */ - public static function metadataBytes(Metadata $metadata): string - { - try { - $json = json_encode($metadata->normalize(), JSON_THROW_ON_ERROR); - } catch (JsonException $e) { - throw new FloeException('Floe failed to encode per-value metadata: ' . $e->getMessage(), 0, $e); - } - - return pack('V', strlen($json)) . $json; - } - - /** - * @throws FloeException - */ - public static function readMetadata(string $body, int &$position): Metadata - { - $length = unpack('V', substr($body, $position, 4))[1]; - $position += 4; - - $json = substr($body, $position, $length); - $position += $length; - - try { - /** @var array|bool|float|int|string> $map */ - $map = json_decode($json, true, 512, JSON_THROW_ON_ERROR); - } catch (JsonException $e) { - throw new FloeException('Floe failed to decode per-value metadata: ' . $e->getMessage(), 0, $e); - } - - return Metadata::fromArray($map); - } - public static function header(int $flags): string { return self::MAGIC . chr(self::VERSION) . chr($flags); diff --git a/src/core/etl/src/Flow/Floe/FrameDecoder.php b/src/core/etl/src/Flow/Floe/FrameDecoder.php new file mode 100644 index 0000000000..5e093fb37e --- /dev/null +++ b/src/core/etl/src/Flow/Floe/FrameDecoder.php @@ -0,0 +1,200 @@ + $rowCount, 2 => $nodeCount, 3 => $bufferCount] = $counts; + $nodeCounts = []; + $bufferCounts = []; + + foreach ($schema->definitions() as $name => $definition) { + $nodeCounts[$name] = $this->layout->nodeCount($definition->type()); + $bufferCounts[$name] = $this->layout->bufferCount($definition->type()); + } + + $expectedNodes = array_sum($nodeCounts); + $expectedBuffers = array_sum($bufferCounts); + + if ($nodeCount !== $expectedNodes) { + throw new FloeException(sprintf( + 'Floe BATCH frame holds %d nodes, the schema describes %d', + $nodeCount, + $expectedNodes, + )); + } + + if ($bufferCount !== $expectedBuffers) { + throw new FloeException(sprintf( + 'Floe BATCH frame holds %d buffers, the schema describes %d', + $bufferCount, + $expectedBuffers, + )); + } + + $areaStart = intdiv(12 + (8 * ($nodeCount + $bufferCount)) + 7, 8) * 8; + + if (strlen($body) < $areaStart) { + throw new FloeException('Floe BATCH frame is truncated, its directory is incomplete'); + } + + /** @var list $words */ + $words = ($nodeCount + $bufferCount) === 0 + ? [] + : array_values((array) unpack('V' . (2 * ($nodeCount + $bufferCount)), $body, 12)); + $area = substr($body, $areaStart); + $areaLength = strlen($area); + $node = 0; + $extent = 2 * $nodeCount; + $buffer = 0; + $columns = []; + + foreach ($schema->definitions() as $name => $definition) { + $type = $definition->type(); + $length = $words[2 * $node]; + $nullCount = $words[(2 * $node) + 1]; + + if ($length !== $rowCount) { + throw new FloeException(sprintf( + 'Floe BATCH frame column "%s" holds %d rows, the frame %d', + $name, + $length, + $rowCount, + )); + } + + if ($nullCount > $length) { + throw new FloeException(sprintf( + 'Floe BATCH frame column "%s" has %d nulls in %d rows', + $name, + $nullCount, + $length, + )); + } + + $buffers = []; + + for ($i = $bufferCounts[$name]; $i > 0; $i--, $buffer++, $extent += 2) { + $offset = $words[$extent]; + $stored = $words[$extent + 1]; + + if ($stored === 0) { + $buffers[] = ''; + + continue; + } + + if (($offset + $stored) > $areaLength) { + throw new FloeException(sprintf( + 'Floe BATCH frame buffer %d lies outside the %d-byte buffer area', + $buffer, + $areaLength, + )); + } + + if ($stored < 8) { + throw new FloeException(sprintf( + 'Floe BATCH frame buffer %d is shorter than its 8-byte length prefix', + $buffer, + )); + } + + /** @var array{1: int} $prefix */ + $prefix = unpack('P', $area, $offset); + $bytes = substr($area, $offset + 8, $stored - 8); + + if ($prefix[1] === -1) { + $buffers[] = $bytes; + + continue; + } + + $decoded = $this->codec->decode($bytes); + + if (strlen($decoded) !== $prefix[1]) { + throw new FloeException(sprintf( + 'Floe BATCH frame buffer %d decodes to %d bytes, its prefix declares %d', + $buffer, + strlen($decoded), + $prefix[1], + )); + } + + $buffers[] = $decoded; + } + + try { + // a flat column's only node is its top node, already checked above; the backend checks its buffers + if ($nodeCounts[$name] === 1) { + $node++; + $columns[$name] = $backend->decode($definition, $buffers, $rowCount, $nullCount); + + continue; + } + + foreach ($this->layout->nodes($type, $length, $nullCount, $buffers) as [ + $derivedLength, + $derivedNulls, + ]) { + if ($words[2 * $node] !== $derivedLength || $words[(2 * $node) + 1] !== $derivedNulls) { + throw new FloeException(sprintf( + 'Floe BATCH frame column "%s" declares nodes that disagree with its buffers', + $name, + )); + } + + $node++; + } + + $columns[$name] = $backend->decode($definition, $buffers, $rowCount, $nullCount); + } catch (InvalidArgumentException $e) { + throw new FloeException( + sprintf('Floe BATCH frame column "%s" is malformed: %s', $name, $e->getMessage()), + 0, + $e, + ); + } + } + + try { + return Rows::fromColumns($schema, $columns, $rowCount); + } catch (SchemaMismatchException $e) { + throw new FloeException(sprintf('Floe BATCH frame is malformed: %s', $e->getMessage()), 0, $e); + } + } +} diff --git a/src/core/etl/src/Flow/Floe/FrameEncoder.php b/src/core/etl/src/Flow/Floe/FrameEncoder.php new file mode 100644 index 0000000000..560d8778b4 --- /dev/null +++ b/src/core/etl/src/Flow/Floe/FrameEncoder.php @@ -0,0 +1,80 @@ +schema()->definitions() as $definition) { + $column = $rows->column($definition->entry()->name()); + $buffers = $column->encode(); + + $columnNodes = $this->layout->nodeCount($definition->type()) === 1 + ? [[$rows->count(), $column->nullCount()]] + : $this->layout->nodes($definition->type(), $rows->count(), $column->nullCount(), $buffers); + + foreach ($columnNodes as [$length, $nulls]) { + $nodes .= pack('VV', $length, $nulls); + $nodeCount++; + } + + foreach ($buffers as $buffer) { + $bufferCount++; + + if ($buffer === '') { + $extents .= pack('VV', 0, 0); + + continue; + } + + $encoded = $this->codec->encode($buffer); + $stored = strlen($encoded) < strlen($buffer) + ? pack('P', strlen($buffer)) . $encoded + : pack('P', -1) . $buffer; + $extents .= pack('VV', strlen($area), strlen($stored)); + $area .= $stored . str_repeat("\0", (8 - (strlen($stored) % 8)) % 8); + } + } + + $directory = pack('VVV', $rows->count(), $nodeCount, $bufferCount) . $nodes . $extents; + $body = $directory . str_repeat("\0", (8 - (strlen($directory) % 8)) % 8) . $area; + + if (strlen($body) > 0xFFFFFFFF) { + throw new FrameTooLarge(sprintf( + 'Floe BATCH frame body of %d bytes exceeds the 4 GiB frame length', + strlen($body), + )); + } + + return $body; + } +} diff --git a/src/core/etl/src/Flow/Floe/FrameWriter.php b/src/core/etl/src/Flow/Floe/FrameWriter.php index b47824cc54..ae21d7ce2a 100644 --- a/src/core/etl/src/Flow/Floe/FrameWriter.php +++ b/src/core/etl/src/Flow/Floe/FrameWriter.php @@ -6,8 +6,6 @@ use Flow\Filesystem\DestinationStream; -use function chr; -use function pack; use function strlen; final class FrameWriter @@ -31,9 +29,9 @@ public function header(): void $this->position += Format::HEADER_LENGTH; } - public function row(string $body): void + public function frame(int $type, string $body): void { - $this->buffer .= chr(Format::FRAME_ROW) . pack('V', strlen($body)) . $body; + $this->buffer .= Format::frame($type, $body); $this->position += Format::FRAME_HEADER_LENGTH + strlen($body); $this->flushIfFull(); } diff --git a/src/core/etl/src/Flow/Floe/PhpFloeEncoder.php b/src/core/etl/src/Flow/Floe/PhpFloeEncoder.php deleted file mode 100644 index 1866df68f0..0000000000 --- a/src/core/etl/src/Flow/Floe/PhpFloeEncoder.php +++ /dev/null @@ -1,229 +0,0 @@ - - */ - private ?array $decodePlan = null; - - /** - * @var null|array per-column value encoder, keyed by column name - */ - private ?array $encoders = null; - - private ?string $schemaBody = null; - - private readonly SchemaDecoder $schemaDecoder; - - public function __construct( - private readonly Schema $schema, - private readonly Backend $backend = new DefaultBackend(), - ) { - $this->schemaDecoder = new SchemaDecoder(new ValueDecoder()); - } - - /** - * @param list $batch - * - * @throws FloeException - * - * @return list - */ - public function decode(array $batch): array - { - $decodePlan = $this->decodePlan ??= $this->schemaDecoder->decode($this->schemaBody()); - - $decoded = []; - - foreach ($batch as $body) { - $position = 0; - $values = []; - $metadata = []; - - foreach ($decodePlan as $column) { - $flag = ord($body[$position++]); - - if ($flag === Format::VALUE_PRESENT) { - $values[$column->name] = $column->decoder->decode($body, $position); - } elseif ($flag === Format::VALUE_NULL) { - $values[$column->name] = null; - } elseif ($flag === Format::VALUE_PRESENT_WITH_META) { - $metadata[$column->name] = Format::readMetadata($body, $position); - $values[$column->name] = $column->decoder->decode($body, $position); - } elseif ($flag === Format::VALUE_NULL_WITH_META) { - $metadata[$column->name] = Format::readMetadata($body, $position); - $values[$column->name] = null; - } else { - throw new FloeException(sprintf('Floe found unknown value flag 0x%02X', $flag)); - } - } - - if ($position !== strlen($body)) { - throw new FloeException('Floe row frame length does not match its content'); - } - - $decoded[] = new RawRowValues($values, $metadata); - } - - return $decoded; - } - - public function decodeRows(array $bodies, Schema $schema): Rows - { - $batch = $this->decode($bodies); - - // metadata belongs to the column, so it is folded into the schema once - a per-row divergent Metadata is - // no longer representable - foreach ($batch as $rowValues) { - foreach ($rowValues->metadata as $name => $metadata) { - // PHP casts a numeric array key to int, column names are always strings - $name = (string) $name; - - if ($schema->findDefinition($name) !== null) { - $schema = $schema->setMetadata($name, $metadata); - } - } - } - - return (new RowsBuilder($schema, $this->backend)) - ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $batch)) - ->finish(); - } - - public function encodeFrames(Rows $rows): string - { - return Format::rowFrames($this->encode($rows)); - } - - /** - * @throws FloeException - * @throws SchemaMismatchException - * - * @return list - */ - public function encode(Rows $rows): array - { - $encoders = $this->encoders ??= $this->buildEncoders(); - - /** @var array, bool, Metadata}> $columns */ - $columns = []; - - foreach ($this->schema->definitions() as $name => $definition) { - $own = $rows->schema()->findDefinition($definition->entry()->name()); - - if ($own === null) { - $columns[$name] = null; - - continue; - } - - $metadata = $own->metadata(); - $columnMetadata = $definition->metadata(); - - $columns[$name] = [ - $rows->column($definition->entry()->name())->values(), - $metadata->isEmpty() && $columnMetadata->isEmpty() ? false : !$metadata->isEqual($columnMetadata), - $metadata, - ]; - } - - $bodies = []; - - for ($rowIndex = 0, $count = $rows->count(); $rowIndex < $count; $rowIndex++) { - $body = ''; - - foreach ($this->schema->definitions() as $name => $definition) { - $column = $columns[$name]; - - if ($column === null) { - throw new FloeException(sprintf( - 'Floe found a row that does not carry the declared column "%s"', - $name, - )); - } - - [$values, $diverges, $metadata] = $column; - // @mago-ignore analysis:mixed-assignment - $value = $values[$rowIndex]; - - if ($value === null) { - if (!$definition->isNullable()) { - throw new SchemaMismatchException($rowIndex, ColumnMismatchException::valueDoesNotMatch( - $definition, - null, - )); - } - - $body .= $diverges - ? Format::VALUE_NULL_WITH_META_BYTE . Format::metadataBytes($metadata) - : Format::VALUE_NULL_BYTE; - - continue; - } - - $body .= $diverges - ? Format::VALUE_PRESENT_WITH_META_BYTE - . Format::metadataBytes($metadata) - . $encoders[$name]->encode($value) - : Format::VALUE_PRESENT_BYTE . $encoders[$name]->encode($value); - } - - $bodies[] = $body; - } - - return $bodies; - } - - /** - * @return array - */ - private function buildEncoders(): array - { - $valueEncoder = new ValueEncoder(); - $encoders = []; - - foreach ($this->schema->definitions() as $name => $definition) { - $encoders[$name] = $valueEncoder->encoderFor($definition); - } - - return $encoders; - } - - private function schemaBody(): string - { - if ($this->schemaBody !== null) { - return $this->schemaBody; - } - - try { - return $this->schemaBody = json_encode($this->schema->normalize(), JSON_THROW_ON_ERROR); - } catch (JsonException $e) { - throw new FloeException('Floe failed to encode schema as JSON: ' . $e->getMessage(), 0, $e); - } - } -} diff --git a/src/core/etl/src/Flow/Floe/SchemaDecoder.php b/src/core/etl/src/Flow/Floe/SchemaDecoder.php deleted file mode 100644 index bc36b4b69b..0000000000 --- a/src/core/etl/src/Flow/Floe/SchemaDecoder.php +++ /dev/null @@ -1,66 +0,0 @@ - - */ - public function decode(string $schemaJson): array - { - try { - // @mago-ignore analysis:mixed-assignment - $definitions = json_decode($schemaJson, true, 512, JSON_THROW_ON_ERROR); - } catch (JsonException $e) { - throw new FloeException('Floe failed to decode schema JSON: ' . $e->getMessage(), 0, $e); - } - - try { - $definitions = type_list(type_array())->assert($definitions); - } catch (InvalidTypeException $e) { - throw new FloeException( - 'Floe expected schema JSON to be a list of definitions: ' . $e->getMessage(), - 0, - $e, - ); - } - - $plan = []; - - /** @var array{ref: string, type: array, nullable?: bool, metadata?: array|bool|float|int|string>} $normalized */ - foreach ($definitions as $normalized) { - $definition = definition_from_array([ - 'ref' => $normalized['ref'], - 'type' => $normalized['type'], - 'nullable' => $normalized['nullable'] ?? false, - 'metadata' => $normalized['metadata'] ?? [], - ]); - - $plan[] = new ColumnBlueprint( - $normalized['ref'], - $definition, - $this->valueDecoder->decoderFor($definition), - ); - } - - return $plan; - } -} diff --git a/src/core/etl/src/Flow/Floe/ValueDecoder.php b/src/core/etl/src/Flow/Floe/ValueDecoder.php deleted file mode 100644 index ba3deecb9f..0000000000 --- a/src/core/etl/src/Flow/Floe/ValueDecoder.php +++ /dev/null @@ -1,295 +0,0 @@ -timeZones = new TimeZones(); - $this->dateTimeDecoder = new DateTimeDecoder($this->timeZones); - $this->uuidDecoder = new UuidDecoder(); - $this->jsonDecoder = new JsonDecoder(); - } - - /** - * @throws FloeException - */ - public function decoderFor(Definition $definition): Decoding\ValueDecoder - { - return match ($definition::class) { - IntegerDefinition::class, - FloatDefinition::class, - BooleanDefinition::class, - StringDefinition::class, - DateTimeDefinition::class, - DateDefinition::class, - TimeDefinition::class, - UuidDefinition::class, - TimeZoneDefinition::class, - JsonDefinition::class, - EnumDefinition::class, - XMLDefinition::class, - XMLElementDefinition::class, - HTMLDefinition::class, - HTMLElementDefinition::class, - ListDefinition::class, - MapDefinition::class, - StructureDefinition::class, - NullDefinition::class, - => $this->elementDecoderFor($definition->type()), - default => throw new FloeException(sprintf( - 'Floe does not support columns of type "%s"', - $definition->type()->toString(), - )), - }; - } - - /** - * Types reachable only inside containers - list elements, map keys and values, - * structure elements - where no Definition exists. - * - * @param Type $type - * - * @throws FloeException - */ - private function elementDecoderFor(Type $type): Decoding\ValueDecoder - { - return match ($type::class) { - IntegerType::class, PositiveIntegerType::class => new Int64Decoder(), - FloatType::class => new Float64Decoder(), - BooleanType::class => new BooleanDecoder(), - StringType::class, - NonEmptyStringType::class, - NumericStringType::class, - ClassStringType::class, - => new StringDecoder(), - TimeZoneType::class => new TimeZoneDecoder($this->timeZones), - DateTimeType::class => $this->zonedDateTimeDecoder($type), - DateType::class => $this->dateTimeDecoder, - TimeType::class => new IntervalDecoder(), - UuidType::class => $this->uuidDecoder, - JsonType::class => $this->jsonDecoder, - EnumType::class => new EnumDecoder(), - XMLType::class => new XmlDocumentDecoder(), - XMLElementType::class => new XmlElementDecoder(), - HTMLType::class => new HtmlDocumentDecoder(), - HTMLElementType::class => new HtmlElementDecoder(), - ListType::class => $this->listDecoder($type), - MapType::class => $this->mapDecoder($type), - StructureType::class => $this->structureDecoder($type), - OptionalType::class => $this->optionalDecoder($type), - NullType::class => new NullDecoder(), - default => throw new FloeException(sprintf('Floe does not support values of type "%s"', $type->toString())), - }; - } - - public static function htmlDocumentFromString(string $html): object - { - if (!class_exists('\Dom\HTMLDocument')) { - throw new FloeException('Floe cannot restore HTML values, \Dom\HTMLDocument requires PHP 8.4+'); - } - - // @mago-expect analysis:unavailable-method - return HTMLDocument::createFromString($html, LIBXML_NOERROR); - } - - public static function htmlElementFromString(string $html): object - { - if (!class_exists('\Dom\HTMLDocument')) { - throw new FloeException('Floe cannot restore HTML values, \Dom\HTMLDocument requires PHP 8.4+'); - } - - // @mago-expect analysis:unavailable-method - $element = HTMLDocument::createFromString( - '' . $html . '', - LIBXML_NOERROR, - )->body?->firstElementChild; - - if ($element === null) { - throw new FloeException(sprintf('Floe failed to restore HTMLElement from "%s"', $html)); - } - - return $element; - } - - public static function xmlDocumentFromString(string $xml): DOMDocument - { - $document = new DOMDocument(); - - if (!@$document->loadXML($xml)) { - throw new FloeException(sprintf('Floe failed to restore DOMDocument from "%s"', $xml)); - } - - return $document; - } - - public static function xmlElementFromString(string $xml): DOMElement - { - $element = self::xmlDocumentFromString($xml)->documentElement; - - if ($element === null) { - throw new FloeException(sprintf('Floe failed to restore DOMElement from "%s"', $xml)); - } - - return $element; - } - - /** - * @param Type $type - */ - private function listDecoder(Type $type): Decoding\ValueDecoder - { - /** @var ListType> $type */ - $element = $type->element(); - - if ($element instanceof IntegerType) { - return new PackedListDecoder('P'); - } - - if ($element instanceof FloatType) { - return new PackedListDecoder('e'); - } - - return new ListDecoder($this->elementDecoderFor($element)); - } - - /** - * @param Type $type - */ - private function mapDecoder(Type $type): Decoding\ValueDecoder - { - /** @var MapType> $type */ - $key = $type->key(); - - $keyDecoder = match (true) { - $key instanceof IntegerType => new Int64Decoder(), - $key instanceof StringType => new StringDecoder(), - default => throw new FloeException(sprintf( - 'Floe does not support map keys of type "%s"', - $key->toString(), - )), - }; - - return new MapDecoder($keyDecoder, $this->elementDecoderFor($type->value())); - } - - /** - * @param Type $type - */ - private function optionalDecoder(Type $type): Decoding\ValueDecoder - { - /** @var OptionalType $type */ - return new OptionalDecoder($this->elementDecoderFor($type->base())); - } - - /** - * @param Type $type - */ - private function structureDecoder(Type $type): Decoding\ValueDecoder - { - /** @var StructureType> $type */ - $elements = []; - - foreach ($type->elements() as $element) { - $elements[$element->name] = $this->elementDecoderFor($element->type); - } - - return new StructureDecoder($elements); - } - - /** - * @param Type $type - */ - private function zonedDateTimeDecoder(Type $type): DateTimeDecoder - { - return new DateTimeDecoder($this->timeZones, type_instance_of(DateTimeType::class)->assert($type)->zone()); - } -} diff --git a/src/core/etl/src/Flow/Floe/ValueEncoder.php b/src/core/etl/src/Flow/Floe/ValueEncoder.php deleted file mode 100644 index 60841ea2f0..0000000000 --- a/src/core/etl/src/Flow/Floe/ValueEncoder.php +++ /dev/null @@ -1,265 +0,0 @@ -dateTimeEncoder = new DateTimeEncoder(); - $this->timeZoneEncoder = new TimeZoneEncoder(); - $this->uuidEncoder = new UuidEncoder(); - $this->jsonEncoder = new JsonEncoder(); - } - - /** - * @throws FloeException - */ - public function encoderFor(Definition $definition): Encoding\ValueEncoder - { - return match ($definition::class) { - IntegerDefinition::class, - FloatDefinition::class, - BooleanDefinition::class, - StringDefinition::class, - DateTimeDefinition::class, - DateDefinition::class, - TimeDefinition::class, - UuidDefinition::class, - TimeZoneDefinition::class, - JsonDefinition::class, - EnumDefinition::class, - XMLDefinition::class, - XMLElementDefinition::class, - HTMLDefinition::class, - HTMLElementDefinition::class, - ListDefinition::class, - MapDefinition::class, - StructureDefinition::class, - NullDefinition::class, - => $this->elementEncoderFor($definition->type()), - default => throw new FloeException(sprintf( - 'Floe does not support columns of type "%s"', - $definition->type()->toString(), - )), - }; - } - - /** - * Types reachable only inside containers - list elements, map keys and values, - * structure elements - where no Definition exists. - * - * @param Type $type - * - * @throws FloeException - */ - private function elementEncoderFor(Type $type): Encoding\ValueEncoder - { - return match ($type::class) { - IntegerType::class, PositiveIntegerType::class => new Int64Encoder(), - FloatType::class => new Float64Encoder(), - BooleanType::class => new BooleanEncoder(), - StringType::class, - NonEmptyStringType::class, - NumericStringType::class, - ClassStringType::class, - => new StringEncoder(), - TimeZoneType::class => $this->timeZoneEncoder, - DateTimeType::class, DateType::class => $this->dateTimeEncoder, - TimeType::class => new IntervalEncoder(), - UuidType::class => $this->uuidEncoder, - JsonType::class => $this->jsonEncoder, - EnumType::class => new EnumEncoder(), - XMLType::class => new XmlDocumentEncoder(), - XMLElementType::class => new XmlElementEncoder(), - HTMLType::class => new HtmlDocumentEncoder(), - HTMLElementType::class => new HtmlElementEncoder(), - ListType::class => $this->listEncoder($type), - MapType::class => $this->mapEncoder($type), - StructureType::class => $this->structureEncoder($type), - OptionalType::class => new OptionalEncoder($this->elementEncoderFor($type->base())), - NullType::class => new NullEncoder(), - default => throw new FloeException(sprintf('Floe does not support values of type "%s"', $type->toString())), - }; - } - - public static function lengthPrefixed(string $value): string - { - return pack('V', strlen($value)) . $value; - } - - public static function htmlElementToString(object $value): string - { - /** @var \Dom\HTMLElement $value */ - // @mago-ignore analysis:non-existent-method - // @mago-ignore analysis:mixed-assignment - $html = $value->ownerDocument?->saveHtml($value); - - if (!is_string($html)) { - throw new FloeException('Floe failed to convert HTMLElement to HTML string'); - } - - return $html; - } - - public static function xmlDocumentToString(DOMDocument $value): string - { - $xml = $value->saveXML(); - - if ($xml === false) { - throw new FloeException('Floe failed to convert DOMDocument to XML string'); - } - - return $xml; - } - - public static function xmlElementToString(DOMElement $value): string - { - $xml = $value->ownerDocument?->saveXML($value); - - if ($xml === null || $xml === false) { - throw new FloeException('Floe failed to convert DOMElement to XML string'); - } - - return $xml; - } - - /** - * @param Type $type - */ - private function listEncoder(Type $type): Encoding\ValueEncoder - { - /** @var ListType> $type */ - $element = $type->element(); - - if ($element instanceof IntegerType) { - return new PackedListEncoder('P'); - } - - if ($element instanceof FloatType) { - return new PackedListEncoder('e'); - } - - return new ListEncoder($this->elementEncoderFor($element)); - } - - /** - * @param Type $type - */ - private function mapEncoder(Type $type): Encoding\ValueEncoder - { - /** @var MapType> $type */ - $key = $type->key(); - - $keyEncoder = match (true) { - $key instanceof IntegerType => new Int64Encoder(), - $key instanceof StringType => new StringKeyEncoder(), - default => throw new FloeException(sprintf( - 'Floe does not support map keys of type "%s"', - $key->toString(), - )), - }; - - return new MapEncoder($keyEncoder, $this->elementEncoderFor($type->value())); - } - - /** - * @param Type $type - */ - private function structureEncoder(Type $type): Encoding\ValueEncoder - { - /** @var StructureType> $type */ - $elements = []; - - foreach ($type->elements() as $element) { - $elements[$element->name] = $this->elementEncoderFor($element->type); - } - - return new StructureEncoder($elements); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php index a54b8f4a83..fde8d461a2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/RowsSerializationContext.php @@ -19,7 +19,7 @@ public static function roundTrip(Rows $rows): Rows } /** - * @param array{schema: \Flow\ETL\Schema, count: int, columns: array, nullCount: int}>} $payload + * @param array{schema: \Flow\ETL\Schema, frame: string} $payload */ public static function unserialize(array $payload): Rows { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php index f2aea2438f..af0d305771 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php @@ -14,6 +14,8 @@ final class SpyBackend implements Backend { private int $builders = 0; + private int $decodes = 0; + private readonly PhpBackend $php; public function __construct() @@ -33,6 +35,11 @@ public function builders(): int return $this->builders; } + public function decodes(): int + { + return $this->decodes; + } + public function constant(Definition $definition, mixed $value, int $count): Column { return $this->php->constant($definition, $value, $count); @@ -40,6 +47,8 @@ public function constant(Definition $definition, mixed $value, int $count): Colu public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column { + $this->decodes++; + return $this->php->decode($definition, $buffers, $count, $nullCount); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php index d812528ee9..a9849e55ed 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php @@ -7,6 +7,7 @@ use DateTimeImmutable; use Flow\ETL\Bucketing\Storage\FilesystemBuckets; use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\ETL\Tests\Context\BucketsStorageContext; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\Exception\IncompatibleSchemaException; @@ -27,6 +28,7 @@ use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; +use function iterator_to_array; final class FilesystemBucketsTest extends FlowIntegrationTestCase { @@ -109,6 +111,28 @@ public function test_custom_batch_size_round_trips_all_rows(): void $this->fs()->rm($cacheDir); } + public function test_small_appends_read_back_coalesced_up_to_the_batch_size(): void + { + $cacheDir = path(__DIR__ . '/var/buckets_coalesced'); + $this->fs()->rm($cacheDir); + + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, batchSize: 3); + + foreach ([1, 2, 3, 4, 5] as $id) { + $storage->append('bucket', array_to_rows([['id' => $id]], schema(int_schema('id')))); + } + + static::assertSame( + [[1, 2, 3], [4, 5]], + array_map( + static fn(Rows $batch) => $batch->reduceToArray('id'), + iterator_to_array($storage->get('bucket'), false), + ), + ); + + $this->fs()->rm($cacheDir); + } + public function test_get_missing_bucket_yields_nothing(): void { $cacheDir = path(__DIR__ . '/var/buckets_missing'); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/BufferLayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/BufferLayoutTest.php new file mode 100644 index 0000000000..41a2bbae34 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/BufferLayoutTest.php @@ -0,0 +1,137 @@ +, int, int}> + */ + public static function counts(): Generator + { + yield 'int' => [type_integer(), 1, 2]; + yield 'float' => [type_float(), 1, 2]; + yield 'date' => [type_date(), 1, 2]; + yield 'bool' => [type_boolean(), 1, 2]; + yield 'string' => [type_string(), 1, 3]; + yield 'uuid' => [type_uuid(), 1, 2]; + yield 'null' => [type_null(), 1, 0]; + yield 'optional' => [type_optional(type_string()), 1, 3]; + yield 'list' => [type_list(type_string()), 2, 5]; + yield 'map' => [type_map(type_string(), type_integer()), 4, 8]; + yield 'structure' => [type_structure(['a' => type_integer(), 'b' => type_list(type_null())]), 4, 5]; + } + + /** + * @param Type $type + */ + #[DataProvider('counts')] + public function test_counts_nodes_and_buffers(Type $type, int $nodes, int $buffers): void + { + static::assertSame($nodes, (new BufferLayout())->nodeCount($type)); + static::assertSame($buffers, (new BufferLayout())->bufferCount($type)); + } + + public function test_the_first_node_is_given(): void + { + static::assertSame([[3, 3]], (new BufferLayout())->nodes(type_null(), 3, 3, [])); + static::assertSame([[2, 1]], (new BufferLayout())->nodes(type_integer(), 2, 1, ['', ''])); + } + + public function test_a_list_child_spans_the_last_offset(): void + { + $type = type_list(type_optional(type_integer())); + $column = ColumnMother::of(list_schema('a', $type, nullable: true), [[1, null], null, [2, 3, null]]); + + static::assertSame([[3, 1], [5, 2]], (new BufferLayout())->nodes($column->type(), 3, 1, $column->encode())); + } + + public function test_a_map_entries_node_holds_no_nulls(): void + { + $type = type_map(type_string(), type_optional(type_integer())); + $column = ColumnMother::of(map_schema('a', $type), [['a' => 1, 'b' => null], ['c' => null]]); + + static::assertSame( + [[2, 0], [3, 0], [3, 0], [3, 2]], + (new BufferLayout())->nodes($type, 2, 0, $column->encode()), + ); + } + + public function test_structure_children_span_their_parent(): void + { + $type = type_structure(['a' => type_integer(), 'n' => type_optional(type_null())]); + $column = ColumnMother::of(structure_schema('s', $type, nullable: true), [['a' => 1, 'n' => null], null]); + + static::assertSame( + [[2, 1], [2, 1], [2, 2]], + (new BufferLayout())->nodes($column->type(), 2, 1, $column->encode()), + ); + } + + public function test_refuses_a_buffer_count_other_than_the_layout(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column of type integer holds 1 buffers, its layout needs 2'); + + (new BufferLayout())->nodes(type_integer(), 1, 0, ['']); + } + + public function test_refuses_an_offsets_buffer_of_another_length(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('List offsets buffer of 4 bytes, expected 8 for 1 rows'); + + (new BufferLayout())->nodes(type_list(type_integer()), 1, 0, ['', pack('V', 0), '', '']); + } + + public function test_refuses_a_map_entries_validity(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Map entries validity must be omitted, got 1 bytes'); + + (new BufferLayout())->nodes(type_map(type_string(), type_integer()), 1, 0, [ + '', + pack('V2', 0, 0), + "\x01", + '', + pack('V', 0), + '', + '', + '', + ]); + } + + public function test_refuses_a_short_child_validity(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Validity bitmap of 1 bytes is too short for 9 rows'); + + (new BufferLayout())->nodes(type_list(type_optional(type_integer())), 1, 0, ['', pack('V2', 0, 9), "\x01", '']); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php index fe0006d346..47686e3b69 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php @@ -12,12 +12,16 @@ use PHPUnit\Framework\TestCase; use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_null; use function Flow\Types\DSL\type_optional; +use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; +use function pack; final class ColumnDecoderTest extends TestCase { @@ -49,12 +53,6 @@ public function test_a_top_level_null_column(): void 3, 3, )); - static::assertInstanceOf(ConstantColumn::class, (new ColumnDecoder())->decode( - type_null(), - new Buffers([]), - 3, - -1, - )); } public function test_refuses_a_null_count_other_than_the_bitmap(): void @@ -64,4 +62,75 @@ public function test_refuses_a_null_count_other_than_the_bitmap(): void (new ColumnDecoder())->decode(type_integer(), new Buffers(['', "\0\0\0\0\0\0\0\0"]), 1, 1); } + + public function test_refuses_nulls_in_a_non_optional_list_element(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('List child holds 1 nulls in a non-nullable integer'); + + (new ColumnDecoder())->decode( + type_list(type_integer()), + new Buffers(['', pack('V2', 0, 1), "\x00", "\0\0\0\0\0\0\0\0"]), + 1, + 0, + ); + } + + public function test_refuses_nulls_in_a_map_key(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Map key child holds 1 nulls in a non-nullable string'); + + (new ColumnDecoder())->decode( + type_map(type_string(), type_integer()), + new Buffers(['', pack('V2', 0, 1), '', "\x00", pack('V2', 0, 0), '', '', "\0\0\0\0\0\0\0\0"]), + 1, + 0, + ); + } + + public function test_refuses_nulls_in_a_non_optional_map_value(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Map value child holds 1 nulls in a non-nullable integer'); + + (new ColumnDecoder())->decode( + type_map(type_string(), type_integer()), + new Buffers(['', pack('V2', 0, 1), '', '', pack('V2', 0, 1), 'k', "\x00", "\0\0\0\0\0\0\0\0"]), + 1, + 0, + ); + } + + public function test_null_kind_children_hold_nulls(): void + { + $list = type_list(type_null()); + $map = type_map(type_string(), type_null()); + + static::assertSame( + [[null, null]], + (new ColumnDecoder()) + ->decode($list, new Buffers(ColumnMother::of(list_schema('a', $list), [[null, null]])->encode()), 1, 0) + ->values(), + ); + static::assertSame( + [['k' => null]], + (new ColumnDecoder()) + ->decode($map, new Buffers(ColumnMother::of(map_schema('a', $map), [['k' => null]])->encode()), 1, 0) + ->values(), + ); + } + + public function test_a_structure_child_under_a_null_parent_holds_nulls(): void + { + $type = type_structure(['a' => type_integer()]); + $column = ColumnMother::of(structure_schema('s', $type, nullable: true), [['a' => 1], null]); + + static::assertSame( + [['a' => 1], null], + (new ColumnDecoder()) + ->decode($column->type(), new Buffers($column->encode()), 2, 1) + ->values(), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php index d493650b4f..068ffad461 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php @@ -5,15 +5,16 @@ namespace Flow\ETL\Tests\Unit\Column\Php; use Flow\ETL\Column\Php\HtmlDocumentPhysical; +use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_html; use function Flow\Types\DSL\type_string; -#[RequiresPhp('>= 8.4.0')] final class HtmlDocumentPhysicalTest extends TestCase { + #[RequiresPhp('>= 8.4.0')] public function test_the_markup(): void { $document = type_html()->cast('

      a

      '); @@ -25,4 +26,13 @@ public function test_the_markup(): void static::assertEquals($markup, $physical->toPhysical($physical->fromPhysical($markup))); static::assertNull($physical->fromPhysicalAll([$markup, null])[1]); } + + #[RequiresPhp('< 8.4.0')] + public function test_restoring_below_php84_throws(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('requires PHP 8.4+'); + + (new HtmlDocumentPhysical())->fromPhysical('

      x

      '); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php index be5de3a483..87b36938ad 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php @@ -5,15 +5,16 @@ namespace Flow\ETL\Tests\Unit\Column\Php; use Flow\ETL\Column\Php\HtmlElementPhysical; +use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_html_element; use function Flow\Types\DSL\type_string; -#[RequiresPhp('>= 8.4.0')] final class HtmlElementPhysicalTest extends TestCase { + #[RequiresPhp('>= 8.4.0')] public function test_the_markup(): void { $physical = new HtmlElementPhysical(); @@ -23,4 +24,22 @@ public function test_the_markup(): void static::assertSame('

      a

      ', $physical->toPhysical($physical->fromPhysical('

      a

      '))); static::assertNull($physical->fromPhysicalAll(['

      a

      ', null])[1]); } + + #[RequiresPhp('>= 8.4.0')] + public function test_markup_without_an_element_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Floe failed to restore HTMLElement from "text"'); + + (new HtmlElementPhysical())->fromPhysical('text'); + } + + #[RequiresPhp('< 8.4.0')] + public function test_restoring_below_php84_throws(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('requires PHP 8.4+'); + + (new HtmlElementPhysical())->fromPhysical('

      x

      '); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php index e589b1fa12..29cc741e73 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Column\Php\Offsets; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\OffsetOverflow; use PHPUnit\Framework\TestCase; use function bin2hex; @@ -25,7 +26,7 @@ public function test_packs_the_last_i32_offset(): void public function test_refuses_an_offset_past_the_i32_range(): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException(OffsetOverflow::class); $this->expectExceptionMessage('Offsets exceed the i32 range of a batch buffer: the last offset is 2147483648'); (new Offsets())->pack([0, 2_147_483_648]); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/TimeZonesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonesTest.php similarity index 83% rename from src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/TimeZonesTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonesTest.php index 090a154f9a..389ffe15ed 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/TimeZonesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonesTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\Floe\Tests\Unit\Decoding; +namespace Flow\ETL\Tests\Unit\Column\Php; -use Flow\Floe\Decoding\TimeZones; +use Flow\ETL\Column\Php\TimeZones; use PHPUnit\Framework\TestCase; final class TimeZonesTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php index f822a8ada8..790e01e90f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php @@ -6,6 +6,7 @@ use DOMDocument; use Flow\ETL\Column\Php\XmlDocumentPhysical; +use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_string; @@ -24,4 +25,12 @@ public function test_the_markup(): void static::assertEquals($document, $physical->fromPhysical($markup)); static::assertEquals([$document, null], $physical->fromPhysicalAll([$markup, null])); } + + public function test_malformed_markup_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Floe failed to restore DOMDocument from ""'); + + (new XmlDocumentPhysical())->fromPhysical(''); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php index 9e84e260fb..fb23d176c5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php @@ -8,9 +8,11 @@ use DOMDocument; use DOMElement; use Flow\ETL\Column\Php\XmlElementPhysical; +use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; +use function Flow\Types\DSL\type_instance_of; use function Flow\Types\DSL\type_string; final class XmlElementPhysicalTest extends TestCase @@ -39,4 +41,22 @@ public function test_a_dom_element_of_the_new_api_reads_back_as_a_dom_element(): static::assertSame('1', $markup); static::assertInstanceOf(DOMElement::class, $physical->fromPhysical($markup)); } + + public function test_restoring_xml_element_from_string(): void + { + static::assertSame( + 'item', + type_instance_of(DOMElement::class)->assert((new XmlElementPhysical())->fromPhysical( + 'value', + ))->tagName, + ); + } + + public function test_a_detached_dom_element_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('failed to convert DOMElement to XML string'); + + (new XmlElementPhysical())->toPhysical(new DOMElement('detached')); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php index 99f86abc66..f0a41c8a27 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php @@ -513,7 +513,7 @@ public static function corrupt_buffers(): Generator ]; yield 'map entries validity present' => [ map_schema('a', type_map(type_string(), type_integer())), - ['', "\x00\x00\x00\x00\x00\x00\x00\x00", "\x01"], + ['', "\x00\x00\x00\x00\x00\x00\x00\x00", "\x01", '', "\x00\x00\x00\x00", '', '', ''], 1, 0, 'Map entries validity must be omitted, got 1 bytes', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php index b185243e90..e07155d2e4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php @@ -6,13 +6,14 @@ use DOMDocument; use DOMElement; +use Flow\ETL\Column\Php\HtmlDocumentPhysical; +use Flow\ETL\Column\Php\HtmlElementPhysical; use Flow\ETL\Column\PhpBackend; -use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Rows; use Flow\ETL\Schema\Metadata; use Flow\ETL\Tests\Context\RowsSerializationContext; use Flow\ETL\Tests\FlowTestCase; -use Flow\Floe\ValueDecoder; +use Flow\Floe\Exception\FloeException; use PHPUnit\Framework\Attributes\RequiresPhp; use function assert; @@ -32,9 +33,11 @@ use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_object; use function Flow\Types\DSL\type_optional; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; +use function pack; use function serialize; use function unserialize; @@ -118,7 +121,7 @@ public function test_restored_xml_elements_do_not_canonicalize_to_an_empty_strin #[RequiresPhp('>= 8.4.0')] public function test_html_document_survives_a_round_trip(): void { - $document = ValueDecoder::htmlDocumentFromString('

      x

      '); + $document = type_object()->assert((new HtmlDocumentPhysical())->fromPhysical('

      x

      ')); static::assertSame( type_string()->cast($document), @@ -131,7 +134,7 @@ public function test_html_document_survives_a_round_trip(): void #[RequiresPhp('>= 8.4.0')] public function test_html_element_survives_a_round_trip(): void { - $element = ValueDecoder::htmlElementFromString('

      x

      '); + $element = type_object()->assert((new HtmlElementPhysical())->fromPhysical('

      x

      ')); static::assertSame( type_string()->cast($element), @@ -187,27 +190,35 @@ public function test_a_batch_without_columns_keeps_its_row_count(): void static::assertSame(3, RowsSerializationContext::roundTrip($rows)->count()); } - public function test_unserialize_refuses_columns_that_disagree_with_the_schema(): void + public function test_unserialize_refuses_a_frame_that_disagrees_with_the_schema(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Rows::fromColumns() expects columns [id], got [other]'); + $this->expectException(FloeException::class); + $this->expectExceptionMessage('Floe BATCH frame holds 2 nodes, the schema describes 1'); RowsSerializationContext::unserialize([ 'schema' => schema(int_schema('id')), - 'count' => 1, - 'columns' => ['other' => ['buffers' => ['', "\x01\x00\x00\x00\x00\x00\x00\x00"], 'nullCount' => 0]], + 'frame' => array_to_rows( + [['id' => 1, 'other' => 2]], + schema(int_schema('id'), int_schema('other')), + )->encodeFrame(), ]); } public function test_unserialize_refuses_a_corrupt_buffer(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Int64 values buffer of 2 bytes, expected 8 for 1 rows'); + $this->expectException(FloeException::class); + $this->expectExceptionMessage('is malformed: Int64 values buffer of 2 bytes, expected 8 for 1 rows'); RowsSerializationContext::unserialize([ 'schema' => schema(int_schema('id')), - 'count' => 1, - 'columns' => ['id' => ['buffers' => ['', "\x01\x00"], 'nullCount' => 0]], + 'frame' => + pack('VVV', 1, 1, 2) + . pack('VV', 1, 0) + . pack('VV', 0, 0) + . pack('VV', 0, 10) + . "\0\0\0\0" + . pack('P', -1) + . "\x01\x00\0\0\0\0\0\0", ]); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php index 628faf99fb..70dd13a3d7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php @@ -1237,6 +1237,24 @@ public function test_of_refuses_a_column_of_another_count(): void Rows::fromColumns(schema(int_schema('id')), ['id' => (new PhpBackend())->constant(int_schema('id'), 1, 2)], 1); } + public function test_of_refuses_a_null_in_a_not_null_column(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "id" (row 1): could not convert null to integer, column is not nullable', + ); + + Rows::fromColumns( + schema(int_schema('id')), + [ + 'id' => array_to_rows([['id' => 1], ['id' => null]], schema(int_schema('id', nullable: true)))->column( + 'id', + ), + ], + 2, + ); + } + public function test_project_shares_kept_columns(): void { $rows = array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php index dcbd468535..62f6da714b 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php @@ -4,7 +4,6 @@ namespace Flow\Floe\Tests\Context; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; @@ -32,25 +31,6 @@ public static function phpReader(Filesystem $filesystem, Codec $codec = new Noop return new FloeReader($filesystem, $codec); } - /** - * @return list - */ - public static function readRows(FloeReader $reader, Path $path): array - { - $file = $reader->read($path); - $rows = []; - - foreach ($file->rows() as $batch) { - foreach ($batch as $row) { - $rows[] = $row; - } - } - - $file->close(); - - return $rows; - } - /** * A two-file Hive tree whose bodies carry only `id`, so `country` can only come from the path. */ diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeGoldenContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeGoldenContext.php index 13518c9b7d..dc060dbe2d 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeGoldenContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeGoldenContext.php @@ -40,8 +40,8 @@ public static function path(string $name, string $version = self::VERSION_DIRECT /** * Rewrites every golden file from the batches above. Committed on purpose: fixtures are only - * trustworthy when the thing that made them is reviewable, and phase 5 of the format bump has - * to be reproducible by someone who is not the author. + * trustworthy when the thing that made them is reviewable and reproducible by someone who is not + * the author. */ public static function regenerate(string $version = self::VERSION_DIRECTORY): void { diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php index c7189f50bf..90254104c4 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php @@ -21,7 +21,6 @@ use Flow\Floe\Section; use Flow\Floe\Statistics; -use function count; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\Filesystem\DSL\memory_filesystem; @@ -152,26 +151,29 @@ public static function write( } /** - * A file holding exactly these ROW frame bodies under `$schema` - frames no FloeWriter would produce. - * - * @param list $bodies + * A file holding exactly these complete frames under `$schema` - frames no FloeWriter would produce. */ - public static function writeFrames(Filesystem $filesystem, Path $path, Schema $schema, array $bodies): void - { + public static function writeFrames( + Filesystem $filesystem, + Path $path, + Schema $schema, + string $frames, + int $rowCount, + ): void { /** @var array> $normalized */ $normalized = $schema->normalize(); $footerJson = (new Footer( Format::VERSION, 'test', $normalized, - [new Section(Format::HEADER_LENGTH, count($bodies))], - new Statistics(count($bodies), strlen(Format::rowFrames($bodies))), + [new Section(Format::HEADER_LENGTH, $rowCount)], + new Statistics($rowCount, strlen($frames)), Metadata::empty(), ))->toJson(); $stream = $filesystem->writeTo($path); $stream->append( - Format::header(0x00) . Format::rowFrames($bodies) + Format::header(0x00) . $frames . Format::frame(Format::FRAME_FOOTER, $footerJson . Format::trailer(strlen($footerJson))), ); $stream->close(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FrameContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FrameContext.php new file mode 100644 index 0000000000..974b6356f3 --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FrameContext.php @@ -0,0 +1,37 @@ + the row, node and buffer counts, then every node and extent word + */ + public static function directory(string $body): array + { + /** @var array{1: int, 2: int, 3: int} $counts */ + $counts = unpack('V3', $body); + + /** @var list */ + return array_values((array) unpack('V' . (3 + (2 * ($counts[2] + $counts[3]))), $body)); + } + + /** + * @param array $words directory word index (0 = row count) => new value + */ + public static function patch(string $body, array $words): string + { + foreach ($words as $index => $word) { + $body = substr_replace($body, pack('V', $word), 4 * $index, 4); + } + + return $body; + } +} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Double/OverflowingColumnStub.php b/src/core/etl/tests/Flow/Floe/Tests/Double/OverflowingColumnStub.php new file mode 100644 index 0000000000..0f2b300011 --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Double/OverflowingColumnStub.php @@ -0,0 +1,94 @@ +column->at($i); + } + + public function concat(Column ...$others): Column + { + return $this->column->concat(...$others); + } + + public function count(): int + { + return $this->column->count(); + } + + public function encode(): array + { + $this->encodeCalls++; + + if ($this->count() > $this->maxRows) { + throw $this->failure; + } + + return $this->column->encode(); + } + + public function isNull(int $i): bool + { + return $this->column->isNull($i); + } + + public function nullCount(): int + { + return $this->column->nullCount(); + } + + public function physicals(): array + { + return $this->column->physicals(); + } + + public function slice(int $offset, int $length): Column + { + return new self($this->column->slice($offset, $length), $this->failure, $this->maxRows); + } + + public function take(array $indices): Column + { + return $this->column->take($indices); + } + + public function type(): Type + { + return $this->column->type(); + } + + public function value(int $i): mixed + { + return $this->column->value($i); + } + + public function values(): array + { + return $this->column->values(); + } + + public function withType(Type $type): Column + { + return $this->column->withType($type); + } +} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Double/TrailingZerosCodecStub.php b/src/core/etl/tests/Flow/Floe/Tests/Double/TrailingZerosCodecStub.php new file mode 100644 index 0000000000..d1d77a8795 --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Double/TrailingZerosCodecStub.php @@ -0,0 +1,37 @@ +0qc>A@^MmBzIWp9`vk_h3t@rU%wHZuJF@E;{q=DVCN3` z{d7Bm#McZ+O`Qx>*mwnhFHR_Uq}TD~dim`&298~{D{C9Yb*QWt+3H5QxB<>aa}{o| z%4(Th#D%+MbH!ZUGstCpIi`$O%Oh@*xb3>*nvO=jV<0+ zp@g8Z>4#q9J?3xqh-ym!qW6xy_iy67i4V2Ln#sm1 z^lWRY9)vuD|J#iFv5RAxX5f#Z-!%cph3KhIw(+@ktM9pmLy!R%{!Lnb>pHzvU#>|Z zRDmfakwoh?r_J4FT|r+Jt}(CsP62$y)u2|28MTsLUtcCyG$L2v6?pR|t?= zG^zgFC(mmmC$eaD#iTun97(G*^gF)j`P8I=(*_S6v3pDb5CAqvYN#;)@&xV$eU_n+z=m)++_c)8ZrZ=kqopL;wUeuTaC7Jdl+ E2c4&#*8l(j diff --git a/src/core/etl/tests/Flow/Floe/Tests/Fixtures/v2/all-entry-types.floe b/src/core/etl/tests/Flow/Floe/Tests/Fixtures/v2/all-entry-types.floe index 8211db1961bd477785f6aec9da66af3ae07398a9..5d3b93fda1d9b39e48d1c0f5c1a8deb5621aae5c 100644 GIT binary patch literal 4829 zcmb_gUuYaf7{63oZB*=oV1xg*16Gm4%SBrCyk4s%p%1MUnouPdu5){HxlML=j@{W@ z{&4mb{}cr2lUNlkh~Se1#24`)U=9Qk3cmQ*2OoS4^hFVj-?uljH@V$3cS#0@Z+^e; zo8SEVZf28-^B2btqz-<2Un(_}N~MlNoq~#OEPJuoSFd~3OX`0Ql2Ft<4|HIv*DC*B ztXhjcp3;-UhUSO{u&raG2aopPGk_06Rpkw6VE-#nAA+h%9U92Dpgs;&m7CB&eiiC7 zQ2&66dVfJhzPJ1hgwEd&3)1n?9{eoe2Q`tGdi>`AAJzO4_=jc4Xl2?D*l%A-1FKgSNAQ5d#9ED9qy2vy-4vu&0zWS^c#bG}zs$U0nack&{ z_Kg=0MgHuak>9@5uyO69^^rTO_vYr47dr}yS^IZt1db=_KlI6Wzy45r`|{WCeEiGr ze}0oyao7v4)hKQ{n;uKQFcV?)KdSjx2qn2}nv_XyT6h6VZW$8baS`RM)C`TeH?I`*o9sHd+JG4??Yi;AP=tyt;y#$nXGTE7d_a*u zctDXt-mF=6r6Aa%Fpg8F{))j|VTq-DrsK$GFus6yjy}$ahVzzSj$u_!krSk_K<$9# zGe{NW{0==0H{%MC6Ct^=G--Gc;E@~&+U>GU^VnNxtwbcQ&ph`Ti%==};vqE#lY;BxeM7(#siPnSut~&dOmFoaOz5`G{9i5 zI?S_7TFku88l|_mH@}W2yGBxK}!s5^gOEzul`;eOxHg6P* z|G7D|9$#CBoM%g#cK4J(>NF3SxnYrxYJMa+Mawz+1JLU4es! zSKFoVi^&lPU@T!*x)bDe0UspPmJc^R)v~V(DUy^_I}U2{V27`T?FSWf){n1q+e1|A zfZgoXgs+Z7uFo%(?ke%fJb1zvcC{JH@zq2*5T9Uo_i4PJTCCm;A299A%Kh~U@5v_a zP@lU2->z|GBnOfxsb6929R;b#xufI^e4oPA32EEObzZIdkmR|OY2xw5*)aQZ*(Qbw uD&SVIObCQeP~HHGe|!K6wJh>wc`RG@DPr2l52`W9xq<*6E%A delta 614 zcmah{&r2Io5PlPFgFlKr6hu-qE?S}8C0*mjC@NM-PR1TgDdLK}-3(^QX1Bb3YZM9T zssBLmZqGeRZ{Gb2JbLjjXb(LUL7nFsd+fk_GxL2jkDdAUYWgCxUEcUuO0iTo#TdM0 ziNT})3U`ThAo!N~^>=b$6#$+QTSwmy;T1)`7vP{HkT+Nm`~IDCBoQWv=>F)>b{Jfq zZr0UvtJlC@kT1m|{DQg9TtvJD)}Ms^eKWvb68oWv!gG0U6I*-Rp=iMQ$;`tiWWT3b z9~FG6uG2e76Q%z!mGq2eVdHd0Iz5CuOwsk;TqtmK9mBB-MPnYVd4uPRrcp$Wsc^^CXZ8FpgHcM3HLfk1y5?w$J5t1`t4Vj;00xm|KWy2h>V{p#NJe(qJCw1& z$SwtOvtzGuw}G`SDZF4`A!-KM3gOLvI;k=8T-Bl0E$adiRBun3+ec-d1X43AlJ_c< zUv?C%44|Lx3ipCUzywnS9Zsq$fUNH!I)n`4&uqDT+vnr#=ii6pab+hzZ^H+@qZr55qQ z+xdRUEE(S1Uhk>{wWHL&Qfd!80>u}IMd`aHxr8$~!ej6PJOv-X6L1Pjehx~H;A0KZ z6YPGO)tTa^GgF`F2vRJ*%*vcl?kY(2`C_>d|JGX-w?6NeDRuY=^_Jdjh^2Rw^)xl1 zWE&`>+Pyg6IMNjJsht_ho>~gFK*=DCnp|B~W?Z3Km?~OLGt1`L zuqcc=okYglB9TMsCYu@@>OUp&ZHc1thW}L0WP*r61S=Vsgh2|Jp@IxhEkEobCa@qY mu3}(|*v!l5$S7rDUaO;&n_7~Xl30?cWK~^T8vxV@vKjyd3J-Ds diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeGoldenTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeGoldenTest.php index bc6f45a67c..51666fa52b 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeGoldenTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeGoldenTest.php @@ -11,6 +11,9 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use function array_map; +use function array_merge; +use function iterator_to_array; use function ord; /** @@ -61,18 +64,14 @@ public function test_golden_bytes_are_unchanged(string $name, array $batches): v #[DataProvider('golden_fixtures')] public function test_golden_files_read_back_to_the_rows_that_wrote_them(string $name, array $batches): void { - $expected = []; + $file = FloeFilesContext::phpReader($this->fs())->read(FloeGoldenContext::path($name)); + $read = iterator_to_array($file->rows(), false); + $file->close(); - foreach ($batches as $batch) { - foreach ($batch as $row) { - $expected[] = $row; - } - } - - static::assertEquals($expected, FloeFilesContext::readRows( - FloeFilesContext::phpReader($this->fs()), - FloeGoldenContext::path($name), - )); + static::assertEquals( + array_merge(...array_map(static fn(Rows $batch) => $batch->toArray(), $batches)), + array_merge(...array_map(static fn(Rows $batch) => $batch->toArray(), $read)), + ); } #[DataProvider('golden_fixture_names')] @@ -80,4 +79,13 @@ public function test_golden_header_is_the_current_format_version(string $name): { static::assertSame(0x02, ord($this->fs()->readFrom(FloeGoldenContext::path($name))->content()[4])); } + + #[DataProvider('golden_fixture_names')] + public function test_golden_fixtures_hold_batch_frames(string $name): void + { + static::assertSame( + $name === 'empty' ? 0x06 : 0x05, + ord($this->fs()->readFrom(FloeGoldenContext::path($name))->content()[6]), + ); + } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloePreAllowExtraRemovalTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloePreAllowExtraRemovalTest.php deleted file mode 100644 index 54a93e3b74..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloePreAllowExtraRemovalTest.php +++ /dev/null @@ -1,39 +0,0 @@ -fs()->readFrom(path(__DIR__ - . '/../Fixtures/pre-allow-extra-removal/all-entry-types.floe'))->content(), - ); - } - - public function test_php_reader_reads_a_footer_that_carries_allow_extra(): void - { - static::assertEquals( - array_values(RowsMother::withAllEntryTypes()->all()), - FloeFilesContext::readRows( - FloeFilesContext::phpReader($this->fs()), - path(__DIR__ . '/../Fixtures/pre-allow-extra-removal/all-entry-types.floe'), - ), - ); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Mother/DateTimeDecoderMother.php b/src/core/etl/tests/Flow/Floe/Tests/Mother/DateTimeDecoderMother.php deleted file mode 100644 index 48864658b8..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Mother/DateTimeDecoderMother.php +++ /dev/null @@ -1,22 +0,0 @@ - 1, 'name' => 'ab'], ['id' => 2, 'name' => null]], + schema(int_schema('id'), str_schema('name', nullable: true)), + ); + } + public static function ids(int $from, int $to): Rows { return array_to_rows( diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/BooleanDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/BooleanDecoderTest.php deleted file mode 100644 index a324590d1f..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/BooleanDecoderTest.php +++ /dev/null @@ -1,21 +0,0 @@ -decode("\x01\x00", $position)); - static::assertFalse($decoder->decode("\x01\x00", $position)); - static::assertSame(2, $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/DateTimeDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/DateTimeDecoderTest.php deleted file mode 100644 index 3355942a60..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/DateTimeDecoderTest.php +++ /dev/null @@ -1,104 +0,0 @@ -encode($value); - $position = 0; - - $decoded = DateTimeDecoderMother::create()->decode($encoded, $position); - - static::assertInstanceOf(DateTimeImmutable::class, $decoded); - static::assertEquals($value, $decoded); - static::assertSame('Australia/Eucla', $decoded->getTimezone()->getName()); - static::assertSame('987654', $decoded->format('u')); - static::assertSame(strlen($encoded), $position); - } - - public function test_a_mutable_datetime_decodes_as_immutable(): void - { - $value = new DateTime('2025-01-01 00:00:00 UTC'); - $position = 0; - - $decoded = DateTimeDecoderMother::create()->decode((new DateTimeEncoder())->encode($value), $position); - - static::assertInstanceOf(DateTimeImmutable::class, $decoded); - static::assertSame($value->format('Y-m-d H:i:s.u e'), $decoded->format('Y-m-d H:i:s.u e')); - } - - public function test_round_trip_before_epoch(): void - { - $value = new DateTimeImmutable('1969-07-20 20:17:00.500000 UTC'); - $position = 0; - - static::assertEquals($value, DateTimeDecoderMother::create()->decode( - (new DateTimeEncoder())->encode($value), - $position, - )); - } - - public function test_a_truncated_datetime_value_throws(): void - { - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('Floe found a truncated datetime value'); - - DateTimeDecoderMother::create()->decode("\xEE", $position); - } - - public function test_column_zone_decoder_advances_the_position(): void - { - $value = new DateTimeImmutable('2025-06-15 12:30:45', new DateTimeZone('Australia/Eucla')); - $encoded = (new DateTimeEncoder())->encode($value) . (new DateTimeEncoder())->encode($value); - $position = 0; - - DateTimeDecoderMother::inColumnZone('Europe/Warsaw')->decode($encoded, $position); - - static::assertSame(strlen($encoded) / 2, $position); - } - - public function test_column_zone_decoder_ignores_an_unknown_stored_zone(): void - { - $position = 0; - - static::assertSame( - '2025-06-15 12:30:45.000000 Europe/Warsaw', - DateTimeDecoderMother::inColumnZone('Europe/Warsaw') - ->decode(pack('P', 1749983445) . pack('V', 0) . pack('V', 13) . 'Europe/Xarsaw', $position) - ->format('Y-m-d H:i:s.u e'), - ); - } - - public function test_decodes_into_the_column_zone(): void - { - $value = new DateTimeImmutable('2025-06-15 12:30:45.987654', new DateTimeZone('Australia/Eucla')); - $position = 0; - - $decoded = DateTimeDecoderMother::inColumnZone('Europe/Warsaw')->decode( - (new DateTimeEncoder())->encode($value), - $position, - ); - - static::assertSame('Europe/Warsaw', $decoded->getTimezone()->getName()); - static::assertSame($value->getTimestamp(), $decoded->getTimestamp()); - static::assertSame('987654', $decoded->format('u')); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/EnumDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/EnumDecoderTest.php deleted file mode 100644 index 29f645da80..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/EnumDecoderTest.php +++ /dev/null @@ -1,50 +0,0 @@ -decode( - (new EnumEncoder())->encode(BackedStringEnum::one), - $position, - )); - } - - public function test_unknown_case_throws(): void - { - $class = BackedStringEnum::class; - $encoded = pack('V', strlen($class)) . $class . pack('V', 4) . 'nope'; - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('cannot restore enum case'); - - (new EnumDecoder())->decode($encoded, $position); - } - - public function test_unknown_class_throws(): void - { - $encoded = pack('V', 10) . 'NoSuchEnum' . pack('V', 3) . 'one'; - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('enum not found'); - - (new EnumDecoder())->decode($encoded, $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/Float64DecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/Float64DecoderTest.php deleted file mode 100644 index 947ac6de25..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/Float64DecoderTest.php +++ /dev/null @@ -1,21 +0,0 @@ -decode(pack('e', 3.5), $position)); - static::assertSame(8, $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/HtmlDocumentDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/HtmlDocumentDecoderTest.php deleted file mode 100644 index d65240d33a..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/HtmlDocumentDecoderTest.php +++ /dev/null @@ -1,37 +0,0 @@ -x

      '); - static::assertInstanceOf(HTMLDocument::class, $document); - - $encoder = new HtmlDocumentEncoder(); - $encoded = $encoder->encode($document); - $position = 0; - - $decoded = (new HtmlDocumentDecoder())->decode($encoded, $position); - static::assertInstanceOf(HTMLDocument::class, $decoded); - - static::assertSame($encoded, $encoder->encode($decoded)); - static::assertSame(strlen($encoded), $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/HtmlElementDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/HtmlElementDecoderTest.php deleted file mode 100644 index 2b8451545d..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/HtmlElementDecoderTest.php +++ /dev/null @@ -1,34 +0,0 @@ -x

      '); - static::assertInstanceOf(HTMLElement::class, $element); - - $position = 0; - - $decoded = (new HtmlElementDecoder())->decode((new HtmlElementEncoder())->encode($element), $position); - static::assertInstanceOf(HTMLElement::class, $decoded); - - static::assertSame(ValueEncoder::htmlElementToString($element), ValueEncoder::htmlElementToString($decoded)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/Int64DecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/Int64DecoderTest.php deleted file mode 100644 index d69cfc92ab..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/Int64DecoderTest.php +++ /dev/null @@ -1,28 +0,0 @@ -decode(pack('P', $value), $position)); - static::assertSame(8, $position); - } - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/IntervalDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/IntervalDecoderTest.php deleted file mode 100644 index 9daad8038b..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/IntervalDecoderTest.php +++ /dev/null @@ -1,34 +0,0 @@ -invert = 1; - // @mago-ignore analysis:invalid-property-write - $value->f = 0.5; - - $position = 0; - $decoded = (new IntervalDecoder())->decode((new IntervalEncoder())->encode($value), $position); - - static::assertSame([1, 2, 3, 4, 0.5, 1], [ - $decoded->d, - $decoded->h, - $decoded->i, - $decoded->s, - $decoded->f, - $decoded->invert, - ]); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/JsonDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/JsonDecoderTest.php deleted file mode 100644 index ad9c3f63f1..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/JsonDecoderTest.php +++ /dev/null @@ -1,26 +0,0 @@ -decode((new JsonEncoder())->encode($value), $position); - - static::assertSame($value->toString(), $decoded->toString()); - static::assertSame($value->isObject(), $decoded->isObject()); - } - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/ListDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/ListDecoderTest.php deleted file mode 100644 index e06d8b8501..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/ListDecoderTest.php +++ /dev/null @@ -1,25 +0,0 @@ -decode((new ListEncoder(new StringEncoder()))->encode(['a', 'bc']), $position), - ); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/MapDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/MapDecoderTest.php deleted file mode 100644 index d192171d5e..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/MapDecoderTest.php +++ /dev/null @@ -1,42 +0,0 @@ - 1, 'b' => 2], - $decoder->decode((new MapEncoder(new StringKeyEncoder(), new Int64Encoder()))->encode([ - 'a' => 1, - 'b' => 2, - ]), $position), - ); - } - - public function test_round_trip_of_integer_keyed_map(): void - { - $decoder = new MapDecoder(new Int64Decoder(), new StringDecoder()); - $position = 0; - - static::assertSame( - [7 => 'x'], - $decoder->decode((new MapEncoder(new Int64Encoder(), new StringEncoder()))->encode([7 => 'x']), $position), - ); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/NullDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/NullDecoderTest.php deleted file mode 100644 index 2ce8d77948..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/NullDecoderTest.php +++ /dev/null @@ -1,19 +0,0 @@ -decode('', $position)); - static::assertSame(0, $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/OptionalDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/OptionalDecoderTest.php deleted file mode 100644 index 66e7405167..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/OptionalDecoderTest.php +++ /dev/null @@ -1,26 +0,0 @@ -decode($encoder->encode($value), $position)); - } - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/PackedListDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/PackedListDecoderTest.php deleted file mode 100644 index bd1ffcaad2..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/PackedListDecoderTest.php +++ /dev/null @@ -1,43 +0,0 @@ -decode((new PackedListEncoder('P'))->encode([10, -20, 30]), $position), - ); - } - - public function test_round_trip_of_float64_list(): void - { - $position = 0; - - static::assertSame( - [1.5, -2.5], - (new PackedListDecoder('e'))->decode((new PackedListEncoder('e'))->encode([1.5, -2.5]), $position), - ); - } - - public function test_empty_list(): void - { - $position = 0; - - static::assertSame( - [], - (new PackedListDecoder('P'))->decode((new PackedListEncoder('P'))->encode([]), $position), - ); - static::assertSame(4, $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/StringDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/StringDecoderTest.php deleted file mode 100644 index a8cf3c0b22..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/StringDecoderTest.php +++ /dev/null @@ -1,26 +0,0 @@ -decode(pack('V', 3) . 'abc', $position)); - static::assertSame(7, $position); - - $position = 0; - static::assertSame('', $decoder->decode(pack('V', 0), $position)); - static::assertSame(4, $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/StructureDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/StructureDecoderTest.php deleted file mode 100644 index c0005d5ee7..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/StructureDecoderTest.php +++ /dev/null @@ -1,49 +0,0 @@ - new Int64Encoder(), - 'name' => new StringEncoder(), - 'missing' => new Int64Encoder(), - ]); - $decoder = new StructureDecoder([ - 'id' => new Int64Decoder(), - 'name' => new StringDecoder(), - 'missing' => new Int64Decoder(), - ]); - - $position = 0; - - static::assertSame( - ['id' => 1, 'name' => null], - $decoder->decode($encoder->encode(['id' => 1, 'name' => null]), $position), - ); - } - - public function test_unknown_element_flag_throws(): void - { - $decoder = new StructureDecoder(['name' => new StringDecoder()]); - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('unknown structure element flag'); - - $decoder->decode("\xEE", $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/TimeZoneDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/TimeZoneDecoderTest.php deleted file mode 100644 index 96b264e4a1..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/TimeZoneDecoderTest.php +++ /dev/null @@ -1,26 +0,0 @@ -decode(pack('V', 15) . 'Australia/Eucla', $position)->getName(), - ); - static::assertSame(19, $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/UuidDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/UuidDecoderTest.php deleted file mode 100644 index de4d30a91a..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/UuidDecoderTest.php +++ /dev/null @@ -1,28 +0,0 @@ -decode(pack('V', strlen($uuid)) . $uuid, $position); - - static::assertInstanceOf(Uuid::class, $decoded); - static::assertSame($uuid, $decoded->toString()); - static::assertSame(4 + strlen($uuid), $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/XmlDocumentDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/XmlDocumentDecoderTest.php deleted file mode 100644 index 59fa09db07..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/XmlDocumentDecoderTest.php +++ /dev/null @@ -1,37 +0,0 @@ -loadXML('value'); - - $position = 0; - $decoded = (new XmlDocumentDecoder())->decode((new XmlDocumentEncoder())->encode($document), $position); - - static::assertSame('item', $decoded->documentElement?->tagName); - } - - public function test_invalid_xml_throws(): void - { - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('failed to restore DOMDocument'); - - (new XmlDocumentDecoder())->decode(pack('V', 9) . 'not < xml', $position); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/XmlElementDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/XmlElementDecoderTest.php deleted file mode 100644 index 1b34b528da..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Decoding/XmlElementDecoderTest.php +++ /dev/null @@ -1,28 +0,0 @@ -loadXML('value'); - $element = $document->documentElement; - static::assertInstanceOf(DOMElement::class, $element); - - $position = 0; - $decoded = (new XmlElementDecoder())->decode((new XmlElementEncoder())->encode($element), $position); - - static::assertSame('item', $decoded->tagName); - static::assertSame('5', $decoded->getAttribute('id')); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/BooleanEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/BooleanEncoderTest.php deleted file mode 100644 index 81adc6792a..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/BooleanEncoderTest.php +++ /dev/null @@ -1,19 +0,0 @@ -encode(true)); - static::assertSame("\x00", $encoder->encode(false)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/DateTimeEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/DateTimeEncoderTest.php deleted file mode 100644 index 86341512f4..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/DateTimeEncoderTest.php +++ /dev/null @@ -1,44 +0,0 @@ -encode($value), $encoder->encode(DateTime::createFromImmutable($value))); - } - - public function test_encodes_timestamp_microseconds_and_timezone(): void - { - $value = new DateTimeImmutable('2025-01-01 00:00:00.123456 UTC'); - - static::assertSame( - pack('P', $value->getTimestamp()) . pack('V', 123456) . pack('V', 3) . 'UTC', - (new DateTimeEncoder())->encode($value), - ); - } - - public function test_custom_datetime_class_throws(): void - { - $this->expectException(FloeException::class); - $this->expectExceptionMessage('Floe supports only DateTime and DateTimeImmutable, got ' - . CustomDateTime::class); - - (new DateTimeEncoder())->encode(new CustomDateTime('2025-01-01 00:00:00 UTC')); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/EnumEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/EnumEncoderTest.php deleted file mode 100644 index c7c8b9d4e9..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/EnumEncoderTest.php +++ /dev/null @@ -1,25 +0,0 @@ -encode(BackedStringEnum::one), - ); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/Float64EncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/Float64EncoderTest.php deleted file mode 100644 index 2ce9f18af0..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/Float64EncoderTest.php +++ /dev/null @@ -1,21 +0,0 @@ -encode(3.5)); - static::assertSame(pack('e', -0.25), $encoder->encode(-0.25)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/HtmlDocumentEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/HtmlDocumentEncoderTest.php deleted file mode 100644 index 08b7ca0f3a..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/HtmlDocumentEncoderTest.php +++ /dev/null @@ -1,34 +0,0 @@ -x

      '); - static::assertInstanceOf(HTMLDocument::class, $document); - - $encoded = (new HtmlDocumentEncoder())->encode($document); - - static::assertSame(pack('V', strlen($encoded) - 4), substr($encoded, 0, 4)); - static::assertTrue(str_contains($encoded, '

      x

      ')); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/HtmlElementEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/HtmlElementEncoderTest.php deleted file mode 100644 index 179275acac..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/HtmlElementEncoderTest.php +++ /dev/null @@ -1,31 +0,0 @@ -x

      '); - static::assertInstanceOf(HTMLElement::class, $element); - $html = ValueEncoder::htmlElementToString($element); - - static::assertSame(pack('V', strlen($html)) . $html, (new HtmlElementEncoder())->encode($element)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/Int64EncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/Int64EncoderTest.php deleted file mode 100644 index 432d9efa56..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/Int64EncoderTest.php +++ /dev/null @@ -1,26 +0,0 @@ -encode(PHP_INT_MIN)); - static::assertSame(pack('P', PHP_INT_MAX), $encoder->encode(PHP_INT_MAX)); - static::assertSame("\xFB\xFF\xFF\xFF\xFF\xFF\xFF\xFF", $encoder->encode(-5)); - static::assertSame("\x2A\x00\x00\x00\x00\x00\x00\x00", $encoder->encode(42)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/IntervalEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/IntervalEncoderTest.php deleted file mode 100644 index dccd16a929..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/IntervalEncoderTest.php +++ /dev/null @@ -1,28 +0,0 @@ -invert = 1; - // @mago-ignore analysis:invalid-property-write - $value->f = 0.5; - - static::assertSame( - "\x01" . pack('VVVVVV', 1, 2, 3, 4, 5, 6) . pack('e', 0.5), - (new IntervalEncoder())->encode($value), - ); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/JsonEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/JsonEncoderTest.php deleted file mode 100644 index 785328de95..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/JsonEncoderTest.php +++ /dev/null @@ -1,22 +0,0 @@ -encode(new Json('[1,2,3]'))); - static::assertSame(pack('V', 10) . '{"a":true}' . "\x01", $encoder->encode(new Json('{"a":true}'))); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/ListEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/ListEncoderTest.php deleted file mode 100644 index 8fc99e6262..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/ListEncoderTest.php +++ /dev/null @@ -1,22 +0,0 @@ -encode(['a', 'bc'])); - static::assertSame(pack('V', 0), $encoder->encode([])); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/MapEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/MapEncoderTest.php deleted file mode 100644 index 1fae624359..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/MapEncoderTest.php +++ /dev/null @@ -1,30 +0,0 @@ -encode(['a' => 42])); - } - - public function test_encodes_integer_keys(): void - { - $encoder = new MapEncoder(new Int64Encoder(), new StringEncoder()); - - static::assertSame(pack('V', 1) . pack('P', 7) . pack('V', 1) . 'x', $encoder->encode([7 => 'x'])); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/NullEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/NullEncoderTest.php deleted file mode 100644 index 6a143bab36..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/NullEncoderTest.php +++ /dev/null @@ -1,16 +0,0 @@ -encode(null)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/OptionalEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/OptionalEncoderTest.php deleted file mode 100644 index 25fe70185c..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/OptionalEncoderTest.php +++ /dev/null @@ -1,23 +0,0 @@ -encode(null)); - static::assertSame(Format::VALUE_PRESENT_BYTE . pack('P', 42), $encoder->encode(42)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/PackedListEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/PackedListEncoderTest.php deleted file mode 100644 index 81fafd3499..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/PackedListEncoderTest.php +++ /dev/null @@ -1,28 +0,0 @@ -encode([10, -20, 30])); - static::assertSame(pack('V', 0), $encoder->encode([])); - } - - public function test_encodes_float64_list_in_bulk(): void - { - $encoder = new PackedListEncoder('e'); - - static::assertSame(pack('V', 2) . pack('e*', 1.5, -2.5), $encoder->encode([1.5, -2.5])); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StringEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StringEncoderTest.php deleted file mode 100644 index adfacbf642..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StringEncoderTest.php +++ /dev/null @@ -1,21 +0,0 @@ -encode('abc')); - static::assertSame(pack('V', 0), $encoder->encode('')); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StringKeyEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StringKeyEncoderTest.php deleted file mode 100644 index 6734fc8437..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StringKeyEncoderTest.php +++ /dev/null @@ -1,24 +0,0 @@ -encode('abc')); - } - - public function test_encodes_numeric_string_key_arriving_as_integer(): void - { - // PHP turns numeric-string array keys into integers - static::assertSame(pack('V', 3) . '123', (new StringKeyEncoder())->encode(123)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StructureEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StructureEncoderTest.php deleted file mode 100644 index 151fc7cbf4..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/StructureEncoderTest.php +++ /dev/null @@ -1,37 +0,0 @@ - new Int64Encoder(), - 'name' => new StringEncoder(), - 'missing' => new Int64Encoder(), - ]); - - static::assertSame( - Format::VALUE_PRESENT_BYTE . pack('P', 1) . Format::VALUE_NULL_BYTE . Format::VALUE_ABSENT_BYTE, - $encoder->encode(['id' => 1, 'name' => null]), - ); - } - - public function test_undeclared_keys_are_not_encoded(): void - { - $encoder = new StructureEncoder(['id' => new Int64Encoder()]); - - static::assertSame(Format::VALUE_PRESENT_BYTE . pack('P', 1), $encoder->encode(['id' => 1, 'extra' => 2])); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/TimeZoneEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/TimeZoneEncoderTest.php deleted file mode 100644 index c96516c443..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/TimeZoneEncoderTest.php +++ /dev/null @@ -1,22 +0,0 @@ -encode(new DateTimeZone('Australia/Eucla')), - ); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/UuidEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/UuidEncoderTest.php deleted file mode 100644 index 5d8a0a8514..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/UuidEncoderTest.php +++ /dev/null @@ -1,22 +0,0 @@ -encode(new Uuid($uuid))); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/XmlDocumentEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/XmlDocumentEncoderTest.php deleted file mode 100644 index 300eaccc22..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/XmlDocumentEncoderTest.php +++ /dev/null @@ -1,26 +0,0 @@ -loadXML('value'); - - $xml = ValueEncoder::xmlDocumentToString($document); - - static::assertSame(pack('V', strlen($xml)) . $xml, (new XmlDocumentEncoder())->encode($document)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/XmlElementEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/XmlElementEncoderTest.php deleted file mode 100644 index 8e8b763163..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/Encoding/XmlElementEncoderTest.php +++ /dev/null @@ -1,29 +0,0 @@ -loadXML('value'); - $element = $document->documentElement; - static::assertInstanceOf(DOMElement::class, $element); - - static::assertSame( - pack('V', strlen('value')) . 'value', - (new XmlElementEncoder())->encode($element), - ); - } -} 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 a507440e8e..3488e2906f 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php @@ -317,7 +317,7 @@ public function test_extract_builds_through_the_config_backend(): void flow_context(config_builder()->backend($backend)->build()), )); - static::assertGreaterThanOrEqual(1, $backend->builders()); + static::assertGreaterThanOrEqual(1, $backend->decodes()); } public function test_negative_offset_throws(): void diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php index 7d4c79cdd5..12d2e28173 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php @@ -12,8 +12,6 @@ use Flow\Floe\FloeWriter; use Flow\Floe\Format; use Flow\Floe\Options; -use Flow\Floe\PhpFloeEncoder; -use Flow\Floe\Tests\Context\FloeSchemaContext; use Flow\Floe\Tests\Context\FloeStreamReaderContext; use Flow\Floe\Tests\Double\CodecStub; use Flow\Floe\Tests\Double\UnsizedFilesystem; @@ -22,12 +20,12 @@ use PHPUnit\Framework\TestCase; use function array_map; +use function array_merge; use function array_slice; use function count; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; -use function Flow\ETL\DSL\schema_from_json; use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; @@ -85,7 +83,7 @@ public function test_batches_follow_requested_size(): void */ static fn(int $batchSize): array => array_map( static fn(Rows $batch): int => $batch->count(), - iterator_to_array($reader->rows($batchSize)), + iterator_to_array($reader->rows($batchSize), false), ); static::assertSame([2, 2, 1], $sizes(2)); @@ -398,13 +396,13 @@ public function test_corrupt_row_body_throws_wrapped_exception(): void $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); $stream = $filesystem->writeTo($path); $stream->append( - Format::header(0x00) . Format::frame(Format::FRAME_ROW, "\xEE") + Format::header(0x00) . Format::frame(Format::FRAME_BATCH, "\xEE") . Format::frame(Format::FRAME_FOOTER, $footerJson . Format::trailer(strlen($footerJson))), ); $stream->close(); $this->expectException(FloeException::class); - $this->expectExceptionMessage('unknown value flag'); + $this->expectExceptionMessage('Floe BATCH frame is truncated, its directory is incomplete'); iterator_to_array( (new FloeReader($filesystem)) @@ -456,10 +454,13 @@ public function test_dead_footers_of_appended_files_are_skipped(): void (new FloeReader($filesystem)) ->read($path) ->rows(), + false, ); - static::assertCount(1, $batches); - static::assertSame([1, 2], array_map(static fn($row) => $row->get('id'), $batches[0]->all())); + static::assertSame( + [[['id' => 1]], [['id' => 2]]], + array_map(static fn(Rows $batch) => $batch->toArray(), $batches), + ); } public function test_empty_file_yields_no_batches(): void @@ -473,7 +474,7 @@ public function test_empty_file_yields_no_batches(): void $reader = (new FloeReader($filesystem))->read($path); - static::assertSame([], iterator_to_array($reader->rows())); + static::assertSame([], iterator_to_array($reader->rows(), false)); static::assertSame(0, $reader->totalRows()); static::assertCount(0, $reader->schema()->definitions()); } @@ -508,17 +509,18 @@ public function test_evolved_file_rows_match_merged_schema(): void (new FloeReader($filesystem)) ->read($path) ->rows(), + false, ); - $rows = $batches[0]->all(); - static::assertCount(4, $rows); - - foreach ($rows as $row) { - static::assertSame(['id', 'email'], $row->names()); - } - - static::assertNull($rows[0]->get('email')); - static::assertSame('x@flow.php', $rows[3]->get('email')); + static::assertSame( + [ + ['id' => 1, 'email' => null], + ['id' => 2, 'email' => null], + ['id' => 3, 'email' => null], + ['id' => 4, 'email' => 'x@flow.php'], + ], + array_merge(...array_map(static fn(Rows $batch) => $batch->toArray(), $batches)), + ); // the merged schema is what carries nullability now, not a per-cell definition $merged = $batches[0]->schema(); @@ -646,80 +648,6 @@ public function test_rows_through_a_custom_identity_codec(): void static::assertCount(2, $batches[0]->all()); } - public function test_rows_through_a_custom_identity_codec_with_long_row_body_throws(): void - { - $filesystem = memory_filesystem(); - $path = path('memory://custom-codec-long-row.floe'); - $schemaBody = FloeSchemaContext::schemaBody(schema(int_schema('id'))); - $rowBody = (new PhpFloeEncoder(schema_from_json($schemaBody)))->encode(array_to_rows([[ - 'id' => 1, - ]], schema(int_schema('id'))))[0]; - $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); - $stream = $filesystem->writeTo($path); - $stream->append( - Format::header(0x00) . Format::frame(Format::FRAME_ROW, $rowBody . 'extra-bytes') - . Format::frame(Format::FRAME_FOOTER, $footerJson . Format::trailer(strlen($footerJson))), - ); - $stream->close(); - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('row frame length does not match its content'); - - iterator_to_array( - (new FloeReader($filesystem, new CodecStub(0x00))) - ->read($path) - ->rows(), - ); - } - - public function test_row_frame_not_described_by_the_footer_schema_throws(): void - { - $filesystem = memory_filesystem(); - $path = path('memory://row-first.floe'); - $footerJson = FooterMother::footer()->toJson(); - $stream = $filesystem->writeTo($path); - $stream->append( - Format::header(0x00) . Format::frame(Format::FRAME_ROW, 'row-bytes') - . Format::frame(Format::FRAME_FOOTER, $footerJson . Format::trailer(strlen($footerJson))), - ); - $stream->close(); - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('row frame length does not match its content'); - - iterator_to_array( - (new FloeReader($filesystem)) - ->read($path) - ->rows(), - ); - } - - public function test_row_body_longer_than_hydrated_content_throws(): void - { - $filesystem = memory_filesystem(); - $path = path('memory://long-row.floe'); - $schemaBody = FloeSchemaContext::schemaBody(schema(int_schema('id'))); - $rowBody = (new PhpFloeEncoder(schema_from_json($schemaBody)))->encode(array_to_rows([[ - 'id' => 1, - ]], schema(int_schema('id'))))[0]; - $footerJson = FooterMother::footer(schema: schema(int_schema('id'))->normalize())->toJson(); - $stream = $filesystem->writeTo($path); - $stream->append( - Format::header(0x00) . Format::frame(Format::FRAME_ROW, $rowBody . 'extra-bytes') - . Format::frame(Format::FRAME_FOOTER, $footerJson . Format::trailer(strlen($footerJson))), - ); - $stream->close(); - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('row frame length does not match its content'); - - iterator_to_array( - (new FloeReader($filesystem)) - ->read($path) - ->rows(), - ); - } - public function test_torn_file_without_footer_throws_in_strict_mode(): void { $filesystem = memory_filesystem(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php index bc2b3cbd72..894daabc75 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php @@ -211,6 +211,15 @@ public function test_unserialize_builds_through_the_given_backend(): void unserialize_from_string($serializer, serialize_to_string($serializer, RowsMother::numbered(3))); - static::assertGreaterThanOrEqual(1, $backend->builders()); + static::assertGreaterThanOrEqual(1, $backend->decodes()); + } + + public function test_an_empty_payload_unserializes_to_an_empty_batch_of_its_schema(): void + { + $serializer = new FloeSerializer(); + $rows = unserialize_from_string($serializer, serialize_to_string($serializer, rows(schema(int_schema('id'))))); + + static::assertSame(0, $rows->count()); + static::assertSame(schema(int_schema('id'))->normalize(), $rows->schema()->normalize()); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php index e3ba846c7a..defdb53193 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php @@ -4,16 +4,20 @@ namespace Flow\Floe\Tests\Unit; -use Flow\ETL\Schema\Metadata; +use Flow\ETL\Rows; use Flow\Floe\Codec\NoopCodec; +use Flow\Floe\Exception\FloeException; use Flow\Floe\FloeReader; use Flow\Floe\FloeStreamReader; use Flow\Floe\FloeWriter; -use Flow\Floe\PhpFloeEncoder; +use Flow\Floe\Format; use Flow\Floe\Tests\Context\FloeStreamReaderContext; use Flow\Floe\Tests\Double\ClosingSpySourceStream; +use Flow\Floe\Tests\Mother\RowsMother; use PHPUnit\Framework\TestCase; +use function array_keys; +use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -41,29 +45,149 @@ public function test_close_closes_the_source_stream(): void static::assertSame(1, $source->closeCount); } - public function test_batches_carry_the_file_schema_when_frames_carry_per_value_metadata(): void + public function test_a_row_frame_is_an_unknown_frame_type(): void { $filesystem = memory_filesystem(); - $path = path('memory://per-value-metadata.floe'); - $schema = schema(int_schema('id')); + $path = path('memory://row-frame.floe'); FloeStreamReaderContext::writeFrames( $filesystem, $path, - $schema, - (new PhpFloeEncoder($schema))->encode(array_to_rows( - [['id' => 1]], - $schema->setMetadata('id', Metadata::fromArray(['k' => 'v'])), - )), + schema(int_schema('id')), + Format::frame(0x02, "\x01"), + 1, ); - $batches = iterator_to_array( + $this->expectException(FloeException::class); + $this->expectExceptionMessage('Floe found unknown frame type 0x02'); + + iterator_to_array( (new FloeReader($filesystem)) ->read($path) ->rows(), + false, + ); + } + + public function test_offset_skips_a_whole_batch_frame_and_slices_the_next(): void + { + $filesystem = memory_filesystem(); + $path = path('memory://offset.floe'); + FloeStreamReaderContext::writeFrames( + $filesystem, + $path, + schema(int_schema('id')), + Format::frame(Format::FRAME_BATCH, RowsMother::ids(1, 3)->encodeFrame()) + . Format::frame(Format::FRAME_BATCH, RowsMother::ids(4, 6)->encodeFrame()), + 6, + ); + + static::assertSame( + [[['id' => 5], ['id' => 6]]], + array_map( + static fn(Rows $batch) => $batch->toArray(), + iterator_to_array( + (new FloeReader($filesystem)) + ->read($path) + ->rows(offset: 4), + false, + ), + ), ); + } + + public function test_limit_slices_a_batch_frame(): void + { + $filesystem = memory_filesystem(); + $path = path('memory://limit.floe'); + FloeStreamReaderContext::writeFrames( + $filesystem, + $path, + schema(int_schema('id')), + Format::frame(Format::FRAME_BATCH, RowsMother::ids(1, 5)->encodeFrame()), + 5, + ); + + static::assertSame( + [[['id' => 1], ['id' => 2]]], + array_map( + static fn(Rows $batch) => $batch->toArray(), + iterator_to_array( + (new FloeReader($filesystem)) + ->read($path) + ->rows(limit: 2), + false, + ), + ), + ); + } - static::assertCount(1, $batches); - static::assertSame($schema->normalize(), $batches[0]->schema()->normalize()); - static::assertSame([1], $batches[0]->reduceToArray('id')); + public function test_batch_size_is_an_upper_bound(): void + { + $filesystem = memory_filesystem(); + $one = path('memory://one-frame.floe'); + $two = path('memory://two-frames.floe'); + FloeStreamReaderContext::writeFrames( + $filesystem, + $one, + schema(int_schema('id')), + Format::frame(Format::FRAME_BATCH, RowsMother::ids(1, 5)->encodeFrame()), + 5, + ); + FloeStreamReaderContext::writeFrames( + $filesystem, + $two, + schema(int_schema('id')), + Format::frame(Format::FRAME_BATCH, RowsMother::ids(1, 2)->encodeFrame()) + . Format::frame(Format::FRAME_BATCH, RowsMother::ids(3, 4)->encodeFrame()), + 4, + ); + + static::assertSame( + [2, 2, 1], + array_map( + static fn(Rows $batch) => $batch->count(), + iterator_to_array( + (new FloeReader($filesystem)) + ->read($one) + ->rows(2), + false, + ), + ), + ); + static::assertSame( + [2, 2], + array_map( + static fn(Rows $batch) => $batch->count(), + iterator_to_array( + (new FloeReader($filesystem)) + ->read($two) + ->rows(10), + false, + ), + ), + ); + } + + public function test_chunked_frames_yield_unique_keys(): void + { + $filesystem = memory_filesystem(); + $path = path('memory://keys.floe'); + FloeStreamReaderContext::writeFrames( + $filesystem, + $path, + schema(int_schema('id')), + Format::frame(Format::FRAME_BATCH, RowsMother::ids(1, 3)->encodeFrame()) + . Format::frame(Format::FRAME_BATCH, RowsMother::ids(4, 6)->encodeFrame()), + 6, + ); + + static::assertSame( + [0, 1, 2, 3], + array_keys(iterator_to_array( + (new FloeReader($filesystem)) + ->read($path) + ->rows(2), + )), + ); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php index 91ca24a710..3d24e8dbae 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php @@ -4,17 +4,24 @@ namespace Flow\Floe\Tests\Unit; +use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\OffsetOverflow; +use Flow\ETL\Rows; use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; use Flow\Floe\Exception\IncompatibleSchemaException; +use Flow\Floe\FloeReader; use Flow\Floe\FloeStreamWriter; use Flow\Floe\FloeWriter; use Flow\Floe\Format; use Flow\Floe\Options; use Flow\Floe\Tests\Context\FloeStreamReaderContext; use Flow\Floe\Tests\Double\CodecStub; +use Flow\Floe\Tests\Double\OverflowingColumnStub; use PHPUnit\Framework\TestCase; +use function array_map; +use function array_merge; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\rows; @@ -22,6 +29,7 @@ use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; +use function iterator_to_array; final class FloeStreamWriterTest extends TestCase { @@ -91,7 +99,7 @@ public function test_create_on_stream_round_trips(): void static::assertSame(3, $footer->statistics->rows); static::assertSame(['source' => 'stream'], $footer->metadata->normalize()); static::assertSame( - [Format::FRAME_ROW, Format::FRAME_ROW, Format::FRAME_ROW, Format::FRAME_FOOTER], + [Format::FRAME_BATCH, Format::FRAME_FOOTER], FloeStreamReaderContext::frameTypes($filesystem, $path), ); } @@ -125,7 +133,7 @@ public function test_write_before_create_throws(): void $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); } - public function test_aligned_multi_batch_session_is_byte_identical_to_a_single_batch(): void + public function test_a_multi_batch_session_reads_back_the_rows_of_a_single_batch(): void { $filesystem = memory_filesystem(); $multi = path('memory://multi-batch.floe'); @@ -148,7 +156,26 @@ public function test_aligned_multi_batch_session_is_byte_identical_to_a_single_b $singleWriter->write($data); $singleWriter->close(); - static::assertSame($filesystem->readFrom($single)->content(), $filesystem->readFrom($multi)->content()); + static::assertSame( + [Format::FRAME_BATCH, Format::FRAME_BATCH, Format::FRAME_FOOTER], + FloeStreamReaderContext::frameTypes($filesystem, $multi), + ); + static::assertSame( + (new FloeReader($filesystem)) + ->read($single) + ->rows() + ->current() + ->toArray(), + array_merge(...array_map( + static fn(Rows $batch) => $batch->toArray(), + iterator_to_array( + (new FloeReader($filesystem)) + ->read($multi) + ->rows(), + false, + ), + )), + ); $footer = FloeStreamReaderContext::footer($filesystem, $multi); static::assertNotSame([], $footer->schema); @@ -282,31 +309,6 @@ public function test_writing_a_column_name_with_invalid_utf8_throws(): void $writer->close(); } - public function test_multi_batch_is_byte_identical_to_single_batch(): void - { - $filesystem = memory_filesystem(); - $multi = path('memory://off-multi.floe'); - $single = path('memory://off-single.floe'); - $data = array_to_rows( - [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], - schema(int_schema('id'), str_schema('name')), - ); - $schema = $data->schema(); - - $multiWriter = new FloeStreamWriter($schema); - $multiWriter->create($filesystem->writeTo($multi)); - $multiWriter->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); - $multiWriter->write(array_to_rows([['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')))); - $multiWriter->close(); - - $singleWriter = new FloeStreamWriter($schema); - $singleWriter->create($filesystem->writeTo($single)); - $singleWriter->write($data); - $singleWriter->close(); - - static::assertSame($filesystem->readFrom($single)->content(), $filesystem->readFrom($multi)->content()); - } - public function test_a_later_null_into_a_non_nullable_session_column_is_rejected(): void { $first = array_to_rows([['id' => 1, 'opt' => 'present']], schema(int_schema('id'), str_schema('opt'))); @@ -355,4 +357,88 @@ public function test_column_absent_from_the_session_schema_throws(): void $writer->write(array_to_rows([['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b')))); } + + public function test_an_overflowing_batch_is_split_in_halves(): void + { + $filesystem = memory_filesystem(); + $path = path('memory://split.floe'); + $schema = schema(int_schema('id'), str_schema('name')); + $data = array_to_rows([ + ['id' => 1, 'name' => 'a'], + ['id' => 2, 'name' => 'b'], + ['id' => 3, 'name' => 'c'], + ['id' => 4, 'name' => 'd'], + ], $schema); + $rows = Rows::fromColumns( + $schema, + [ + 'id' => $data->column('id'), + 'name' => new OverflowingColumnStub($data->column('name'), new OffsetOverflow('overflow'), maxRows: 2), + ], + 4, + ); + + $writer = new FloeStreamWriter($schema); + $writer->create($filesystem->writeTo($path)); + $writer->write($rows); + $writer->close(); + + static::assertSame( + [Format::FRAME_BATCH, Format::FRAME_BATCH, Format::FRAME_FOOTER], + FloeStreamReaderContext::frameTypes($filesystem, $path), + ); + static::assertSame( + [[1, 2], [3, 4]], + array_map( + static fn(Rows $batch) => $batch->reduceToArray('id'), + iterator_to_array( + (new FloeReader($filesystem)) + ->read($path) + ->rows(), + false, + ), + ), + ); + } + + public function test_a_corrupt_column_fails_on_the_first_encode(): void + { + $filesystem = memory_filesystem(); + $schema = schema(str_schema('name')); + $name = new OverflowingColumnStub( + array_to_rows([['name' => 'a'], ['name' => 'b']], $schema)->column('name'), + new InvalidArgumentException('corrupt offsets'), + maxRows: 0, + ); + + $writer = new FloeStreamWriter($schema); + $writer->create($filesystem->writeTo(path('memory://corrupt.floe'))); + + try { + $writer->write(Rows::fromColumns($schema, ['name' => $name], 2)); + static::fail('A corrupt column must fail the write'); + } catch (InvalidArgumentException $e) { + static::assertSame('corrupt offsets', $e->getMessage()); + static::assertSame(1, $name->encodeCalls); + } + } + + public function test_a_single_overflowing_row_rethrows_offset_overflow(): void + { + $filesystem = memory_filesystem(); + $schema = schema(str_schema('name')); + $name = new OverflowingColumnStub( + array_to_rows([['name' => 'a']], $schema)->column('name'), + new OffsetOverflow('overflow'), + maxRows: 0, + ); + + $writer = new FloeStreamWriter($schema); + $writer->create($filesystem->writeTo(path('memory://single.floe'))); + + $this->expectException(OffsetOverflow::class); + $this->expectExceptionMessage('overflow (row 0)'); + + $writer->write(Rows::fromColumns($schema, ['name' => $name], 1)); + } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php index 27c054fdd6..760ed8c741 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php @@ -220,7 +220,7 @@ public function test_append_to_torn_file_throws(): void $filesystem = memory_filesystem(); $path = path('memory://torn.floe'); $stream = $filesystem->writeTo($path); - $stream->append(Format::header(0x00) . Format::frame(Format::FRAME_ROW, 'not closed')); + $stream->append(Format::header(0x00) . Format::frame(Format::FRAME_BATCH, 'not closed')); $stream->close(); $this->expectException(FloeException::class); @@ -326,7 +326,7 @@ public function test_append_with_same_schema_adds_a_section_reusing_the_footer_s $writer->close(); static::assertSame( - [Format::FRAME_ROW, Format::FRAME_FOOTER, Format::FRAME_ROW, Format::FRAME_FOOTER], + [Format::FRAME_BATCH, Format::FRAME_FOOTER, Format::FRAME_BATCH, Format::FRAME_FOOTER], FloeStreamReaderContext::frameTypes($filesystem, $path), ); @@ -404,7 +404,7 @@ public function test_two_writes_with_the_same_schema_in_one_session_share_one_se static::assertSame(2, $footer->statistics->rows); static::assertCount(1, $footer->sections); static::assertSame( - [Format::FRAME_ROW, Format::FRAME_ROW, Format::FRAME_FOOTER], + [Format::FRAME_BATCH, Format::FRAME_BATCH, Format::FRAME_FOOTER], FloeStreamReaderContext::frameTypes($filesystem, $path), ); } @@ -475,7 +475,7 @@ public function test_section_offsets_point_at_frames(): void static::assertSame(Format::HEADER_LENGTH, $footer->sections[0]->offset); foreach ($footer->sections as $section) { - static::assertSame(Format::FRAME_ROW, ord($source->read(1, $section->offset))); + static::assertSame(Format::FRAME_BATCH, ord($source->read(1, $section->offset))); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FormatTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FormatTest.php index 63390952cf..3cbc74c9f5 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FormatTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FormatTest.php @@ -16,16 +16,7 @@ final class FormatTest extends TestCase { public function test_frame_prefixes_type_and_length(): void { - static::assertSame(chr(Format::FRAME_ROW) . pack('V', 3) . 'abc', Format::frame(Format::FRAME_ROW, 'abc')); - } - - public function test_row_frames_frames_every_body_in_order(): void - { - static::assertSame( - chr(Format::FRAME_ROW) . pack('V', 1) . 'a' . chr(Format::FRAME_ROW) . pack('V', 0), - Format::rowFrames(['a', '']), - ); - static::assertSame('', Format::rowFrames([])); + static::assertSame(chr(Format::FRAME_BATCH) . pack('V', 3) . 'abc', Format::frame(Format::FRAME_BATCH, 'abc')); } public function test_header_starts_with_magic_version_and_flags(): void diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameDecoderTest.php new file mode 100644 index 0000000000..e749253715 --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameDecoderTest.php @@ -0,0 +1,280 @@ + + */ + public static function round_trips(): Generator + { + $cases = [ + 'all entry types' => RowsMother::withAllEntryTypes(), + 'worked example' => RowsMother::workedExample(), + 'list with a null slot' => array_to_rows([ + ['l' => [1, 2]], + ['l' => null], + ['l' => []], + ], schema(list_schema('l', type_list(type_integer()), nullable: true))), + 'map' => array_to_rows([ + ['m' => ['a' => 1]], + ['m' => ['b' => 2, 'c' => 3]], + ], schema(map_schema('m', type_map(type_string(), type_integer())))), + 'structure with a null parent' => array_to_rows([ + ['s' => ['a' => 1]], + ['s' => null], + ], schema(structure_schema('s', type_structure(['a' => type_integer()]), nullable: true))), + 'null column' => array_to_rows([['n' => null], ['n' => null]], schema(null_schema('n'))), + 'list of nulls' => array_to_rows([ + ['l' => [null, null]], + ['l' => [null]], + ], schema(list_schema('l', type_list(type_null())))), + 'map of null values' => array_to_rows([['m' => [ + 'a' => null, + ]]], schema(map_schema('m', type_map(type_string(), type_null())))), + 'no columns' => array_to_rows([[], [], []], schema()), + ]; + + foreach ($cases as $name => $rows) { + yield $name . ' / noop' => [$rows, new NoopCodec()]; + yield $name . ' / trailing zeros' => [$rows, new TrailingZerosCodecStub()]; + yield $name . ' / prefixing' => [$rows, new PrefixingCodecStub()]; + } + } + + #[DataProvider('round_trips')] + public function test_round_trips(Rows $rows, Codec $codec): void + { + $decoded = (new FrameDecoder($codec))->decode( + (new FrameEncoder($codec))->encode($rows), + $rows->schema(), + new PhpBackend(), + ); + + static::assertSame($rows->count(), $decoded->count()); + static::assertEquals($rows->toArray(), $decoded->toArray()); + } + + public function test_a_numeric_column_name_round_trips(): void + { + $rows = array_to_rows([['0' => 1], ['0' => null]], schema(int_schema('0', nullable: true))); + + static::assertSame( + $rows->toArray(), + (new FrameDecoder()) + ->decode($rows->encodeFrame(), $rows->schema(), new PhpBackend()) + ->toArray(), + ); + } + + public function test_a_null_struct_child_under_a_null_parent_is_accepted(): void + { + $rows = array_to_rows([ + ['s' => ['a' => 1, 'b' => 'x']], + ['s' => null], + ], schema(structure_schema('s', type_structure(['a' => type_integer(), 'b' => type_string()]), nullable: true))); + + static::assertSame( + $rows->toArray(), + (new FrameDecoder()) + ->decode($rows->encodeFrame(), $rows->schema(), new PhpBackend()) + ->toArray(), + ); + } + + /** + * @return Generator + */ + public static function refusals(): Generator + { + $body = RowsMother::workedExample()->encodeFrame(); + + yield 'a body shorter than the directory counts' => [ + substr($body, 0, 11), + 'Floe BATCH frame is truncated, its directory is incomplete', + ]; + yield 'a directory cut short' => [ + substr($body, 0, 40), + 'Floe BATCH frame is truncated, its directory is incomplete', + ]; + yield 'a node count other than the schema' => [ + FrameContext::patch($body, [1 => 3]), + 'Floe BATCH frame holds 3 nodes, the schema describes 2', + ]; + yield 'a buffer count other than the schema' => [ + FrameContext::patch($body, [2 => 4]), + 'Floe BATCH frame holds 4 buffers, the schema describes 5', + ]; + yield 'a column of another row count' => [ + FrameContext::patch($body, [3 => 3]), + 'Floe BATCH frame column "id" holds 3 rows, the frame 2', + ]; + yield 'more nulls than rows' => [ + FrameContext::patch($body, [4 => 3]), + 'Floe BATCH frame column "id" has 3 nulls in 2 rows', + ]; + yield 'a buffer past the area' => [ + FrameContext::patch($body, [10 => 200]), + 'Floe BATCH frame buffer 1 lies outside the 80-byte buffer area', + ]; + yield 'a buffer shorter than its prefix' => [ + FrameContext::patch($body, [10 => 4]), + 'Floe BATCH frame buffer 1 is shorter than its 8-byte length prefix', + ]; + yield 'a null count other than the bitmap' => [ + FrameContext::patch($body, [6 => 0]), + 'Floe BATCH frame column "name" is malformed: Column null count 0 disagrees with its validity bitmap (1 nulls in 2 rows)', + ]; + } + + #[DataProvider('refusals')] + public function test_refuses(string $body, string $message): void + { + $this->expectException(FloeException::class); + $this->expectExceptionMessage($message); + + (new FrameDecoder())->decode($body, RowsMother::workedExample()->schema(), new PhpBackend()); + } + + public function test_refuses_a_buffer_that_decodes_to_another_length_than_its_prefix(): void + { + $body = (new FrameEncoder(new TrailingZerosCodecStub()))->encode(RowsMother::workedExample()); + + $this->expectException(FloeException::class); + $this->expectExceptionMessage('Floe BATCH frame buffer 1 decodes to 16 bytes, its prefix declares 15'); + + (new FrameDecoder(new TrailingZerosCodecStub()))->decode( + substr_replace($body, pack('P', 15), 72, 8), + RowsMother::workedExample()->schema(), + new PhpBackend(), + ); + } + + public function test_refuses_child_nodes_that_disagree_with_the_buffers(): void + { + $rows = array_to_rows([ + ['l' => [1, 2]], + ['l' => null], + ], schema(list_schema('l', type_list(type_integer()), nullable: true))); + + $this->expectException(FloeException::class); + $this->expectExceptionMessage('Floe BATCH frame column "l" declares nodes that disagree with its buffers'); + + (new FrameDecoder())->decode( + FrameContext::patch($rows->encodeFrame(), [5 => 3]), + $rows->schema(), + new PhpBackend(), + ); + } + + public function test_refuses_a_backend_refusal_as_malformed(): void + { + $body = FrameContext::patch(RowsMother::workedExample()->encodeFrame(), [10 => 10]); + + try { + (new FrameDecoder())->decode($body, RowsMother::workedExample()->schema(), new PhpBackend()); + static::fail('A cut values buffer must be refused'); + } catch (FloeException $e) { + static::assertSame( + 'Floe BATCH frame column "id" is malformed: Int64 values buffer of 2 bytes, expected 16 for 2 rows', + $e->getMessage(), + ); + static::assertInstanceOf(InvalidArgumentException::class, $e->getPrevious()); + } + } + + public function test_a_not_null_column_with_a_null_node_is_refused(): void + { + $body = array_to_rows([['id' => 1], ['id' => null]], schema(int_schema('id', nullable: true)))->encodeFrame(); + + $this->expectException(FloeException::class); + $this->expectExceptionMessage( + 'Floe BATCH frame is malformed: Rows do not match their schema: column "id" (row 1): could not convert null to integer, column is not nullable', + ); + + (new FrameDecoder())->decode($body, schema(int_schema('id')), new PhpBackend()); + } + + public function test_a_null_in_a_non_optional_list_element_is_refused(): void + { + $body = array_to_rows([['l' => [ + 1, + null, + ]]], schema(list_schema('l', type_list(type_optional(type_integer())))))->encodeFrame(); + + try { + (new FrameDecoder())->decode($body, schema(list_schema('l', type_list(type_integer()))), new PhpBackend()); + static::fail('A null list element must be refused'); + } catch (FloeException $e) { + static::assertSame( + 'Floe BATCH frame column "l" is malformed: List child holds 1 nulls in a non-nullable integer', + $e->getMessage(), + ); + static::assertInstanceOf(InvalidArgumentException::class, $e->getPrevious()); + } + } + + public function test_a_null_map_key_is_refused(): void + { + $rows = array_to_rows([['m' => [ + 1 => null, + ]]], schema(map_schema('m', type_map(type_integer(), type_optional(type_integer()))))); + $words = FrameContext::directory($rows->encodeFrame()); + $body = FrameContext::patch($rows->encodeFrame(), [ + 8 => 1, + 10 => 0, + 17 => $words[21], + 18 => $words[22], + 21 => $words[17], + 22 => $words[18], + ]); + + try { + (new FrameDecoder())->decode($body, $rows->schema(), new PhpBackend()); + static::fail('A null map key must be refused'); + } catch (FloeException $e) { + static::assertSame( + 'Floe BATCH frame column "m" is malformed: Map key child holds 1 nulls in a non-nullable integer', + $e->getMessage(), + ); + static::assertInstanceOf(InvalidArgumentException::class, $e->getPrevious()); + } + } +} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameEncoderTest.php new file mode 100644 index 0000000000..0ea366bad1 --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameEncoderTest.php @@ -0,0 +1,104 @@ +encode(RowsMother::workedExample())), + ); + } + + public function test_a_codec_wraps_each_buffer_behind_its_length(): void + { + static::assertSame( + '020000000200000005000000020000000000000002000000010000000000000000000000000000001200000018000000090000002800000012000000400000000a00000000000000100000000000000001000000000000000207000000000000ffffffffffffffff01000000000000000c0000000000000000000000020000000203000000000000ffffffffffffffff6162000000000000', + bin2hex((new FrameEncoder(new TrailingZerosCodecStub()))->encode(RowsMother::workedExample())), + ); + } + + public function test_a_codec_whose_output_is_not_smaller_stores_raw(): void + { + static::assertSame( + (new FrameEncoder())->encode(RowsMother::workedExample()), + (new FrameEncoder(new PrefixingCodecStub()))->encode(RowsMother::workedExample()), + ); + } + + public function test_a_list_with_a_null_slot(): void + { + $body = (new FrameEncoder())->encode(array_to_rows([ + ['l' => [1, 2]], + ['l' => null], + ], schema(list_schema('l', type_list(type_integer()), nullable: true)))); + + static::assertSame([2, 2, 4, 2, 1, 2, 0, 0, 9, 16, 20, 0, 0, 40, 24], FrameContext::directory($body)); + } + + public function test_a_map_entries_node_and_extent(): void + { + $body = (new FrameEncoder())->encode(array_to_rows([ + ['m' => ['a' => 1]], + ['m' => ['b' => 2, 'c' => 3]], + ], schema(map_schema('m', type_map(type_string(), type_integer()))))); + + static::assertSame( + [2, 4, 8, 2, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 20, 0, 0, 0, 0, 24, 24, 48, 11, 0, 0, 64, 32], + FrameContext::directory($body), + ); + } + + public function test_a_structure_with_a_null_parent(): void + { + $body = (new FrameEncoder())->encode(array_to_rows([ + ['s' => ['a' => 1]], + ['s' => null], + ], schema(structure_schema('s', type_structure(['a' => type_integer()]), nullable: true)))); + + static::assertSame([2, 2, 3, 2, 1, 2, 1, 0, 9, 16, 9, 32, 24], FrameContext::directory($body)); + } + + public function test_a_null_column_has_a_full_null_node_and_no_extent(): void + { + static::assertSame( + '020000000100000000000000020000000200000000000000', + bin2hex((new FrameEncoder())->encode(array_to_rows([ + ['n' => null], + ['n' => null], + ], schema(null_schema('n'))))), + ); + } + + public function test_a_batch_without_columns_keeps_its_row_count(): void + { + static::assertSame( + '03000000000000000000000000000000', + bin2hex((new FrameEncoder())->encode(array_to_rows([[], [], []], schema()))), + ); + } +} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameReaderTest.php index d1ae478866..b6788bd735 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameReaderTest.php @@ -38,13 +38,13 @@ public function test_frames_crossing_compaction_threshold_are_streamed(): void $bytes = Format::header(0x00); for ($i = 0; $i < 200; $i++) { - $bytes .= Format::frame(Format::FRAME_ROW, $body); + $bytes .= Format::frame(Format::FRAME_BATCH, $body); } $read = 0; foreach (FrameReaderMother::overBytes($bytes, chunkSize: 4096)->frames() as [$type, $frameBody]) { - static::assertSame(Format::FRAME_ROW, $type); + static::assertSame(Format::FRAME_BATCH, $type); static::assertSame($body, $frameBody); $read++; } @@ -56,12 +56,12 @@ public function test_frames_are_yielded_in_order_with_bodies(): void { $bytes = Format::header(0x00) - . Format::frame(Format::FRAME_ROW, 'row-1') + . Format::frame(Format::FRAME_BATCH, 'row-1') . Format::frame(Format::FRAME_FOOTER, 'footer'); static::assertSame( [ - [Format::FRAME_ROW, 'row-1'], + [Format::FRAME_BATCH, 'row-1'], [Format::FRAME_FOOTER, 'footer'], ], iterator_to_array(FrameReaderMother::overBytes($bytes)->frames()), @@ -70,14 +70,14 @@ public function test_frames_are_yielded_in_order_with_bodies(): void public function test_stream_ending_at_frame_boundary_ends_cleanly(): void { - $bytes = Format::header(0x00) . Format::frame(Format::FRAME_ROW, 'row'); + $bytes = Format::header(0x00) . Format::frame(Format::FRAME_BATCH, 'row'); static::assertCount(1, iterator_to_array(FrameReaderMother::overBytes($bytes)->frames())); } public function test_truncated_frame_body_throws(): void { - $bytes = Format::header(0x00) . chr(Format::FRAME_ROW) . pack('V', 100) . 'short'; + $bytes = Format::header(0x00) . chr(Format::FRAME_BATCH) . pack('V', 100) . 'short'; $this->expectException(FloeException::class); $this->expectExceptionMessage('frame body is incomplete'); @@ -87,7 +87,7 @@ public function test_truncated_frame_body_throws(): void public function test_truncated_frame_header_throws(): void { - $bytes = Format::header(0x00) . chr(Format::FRAME_ROW) . 'xy'; + $bytes = Format::header(0x00) . chr(Format::FRAME_BATCH) . 'xy'; $this->expectException(FloeException::class); $this->expectExceptionMessage('frame header is incomplete'); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameWriterTest.php index 5f11627997..4b90e47e0a 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FrameWriterTest.php @@ -28,15 +28,15 @@ public function test_header_emits_magic_version_and_codec(): void static::assertSame(Format::HEADER_LENGTH, $writer->position()); } - public function test_row_frame_is_type_length_prefixed_body(): void + public function test_frame_is_type_length_prefixed_body(): void { $sink = new StringDestinationStream(path('memory://frame.floe')); $writer = new FrameWriter($sink, 0x00); - $writer->row('abc'); + $writer->frame(Format::FRAME_BATCH, 'abc'); $writer->flush(); - static::assertSame(chr(Format::FRAME_ROW) . pack('V', 3) . 'abc', $sink->content()); + static::assertSame(chr(Format::FRAME_BATCH) . pack('V', 3) . 'abc', $sink->content()); static::assertSame(Format::FRAME_HEADER_LENGTH + 3, $writer->position()); } @@ -71,7 +71,7 @@ public function test_start_position_seeds_the_logical_position(): void static::assertSame(128, $writer->position()); - $writer->row('x'); + $writer->frame(Format::FRAME_BATCH, 'x'); static::assertSame(128 + Format::FRAME_HEADER_LENGTH + 1, $writer->position()); } @@ -93,9 +93,9 @@ public function test_close_flushes_pending_bytes(): void $sink = new StringDestinationStream(path('memory://frame.floe')); $writer = new FrameWriter($sink, 0x00); - $writer->row('pending'); + $writer->frame(Format::FRAME_BATCH, 'pending'); $writer->close(); - static::assertSame(chr(Format::FRAME_ROW) . pack('V', 7) . 'pending', $sink->content()); + static::assertSame(chr(Format::FRAME_BATCH) . pack('V', 7) . 'pending', $sink->content()); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php deleted file mode 100644 index d0301183be..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/PhpFloeEncoderTest.php +++ /dev/null @@ -1,290 +0,0 @@ - 1, 'name' => 'flow', 'price' => 1.5], ['id' => 2, 'name' => null, 'price' => 0.5]], - schema(int_schema('id'), str_schema('name', nullable: true), float_schema('price')), - ); - - $encoder = new PhpFloeEncoder(schema_from_json(FloeSchemaContext::schemaBody($original->schema()))); - - $decoded = $encoder->decode($encoder->encode($original)); - - static::assertSame(['id' => 1, 'name' => 'flow', 'price' => 1.5], $decoded[0]->values); - static::assertSame([], $decoded[0]->metadata); - static::assertSame(['id' => 2, 'name' => null, 'price' => 0.5], $decoded[1]->values); - } - - public function test_encode_round_trips(): void - { - $original = array_to_rows( - [['id' => 1, 'name' => 'flow'], ['id' => 2, 'name' => null]], - schema(int_schema('id'), str_schema('name', nullable: true)), - ); - - $encoder = new PhpFloeEncoder(schema_from_json(FloeSchemaContext::schemaBody($original->schema()))); - - $decoded = $encoder->decode($encoder->encode($original)); - - static::assertEquals( - [ - new RawRowValues(['id' => 1, 'name' => 'flow']), - new RawRowValues(['id' => 2, 'name' => null]), - ], - $decoded, - ); - } - - public function test_encode_refuses_a_row_that_does_not_carry_a_declared_column(): void - { - // a row always carries every column its schema declares, so absence is a broken contract, - // not a value the format can express - VALUE_ABSENT is a structure-element flag only - $encoder = new PhpFloeEncoder(schema_from_json(FloeSchemaContext::schemaBody(schema( - int_schema('id'), - str_schema('name'), - )))); - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('Floe found a row that does not carry the declared column "name"'); - - $encoder->encode(array_to_rows([['id' => 4]], schema(int_schema('id')))); - } - - public function test_encode_decode_round_trip_preserves_flags(): void - { - // the column carries nulls, so the declaration admits them - a null on a NOT NULL column is - // refused by the encoder - $schema = schema_from_json(FloeSchemaContext::schemaBody(schema( - int_schema('id'), - str_schema('name', nullable: true), - ))); - - $encoder = new PhpFloeEncoder($schema); - - $encoded = [ - ...$encoder->encode(array_to_rows([['id' => 1, 'name' => 'flow'], ['id' => 2, 'name' => null]], $schema)), - ...$encoder->encode(array_to_rows( - [['id' => 3, 'name' => null]], - $schema->setMetadata('name', Metadata::fromArray(['tag' => 'x'])), - )), - ]; - - $decoded = $encoder->decode($encoded); - - static::assertEquals( - [ - new RawRowValues(['id' => 1, 'name' => 'flow']), - new RawRowValues(['id' => 2, 'name' => null]), - new RawRowValues(['id' => 3, 'name' => null], ['name' => Metadata::fromArray(['tag' => 'x'])]), - ], - $decoded, - ); - static::assertSame('x', $decoded[2]->metadata['name']->get('tag')); - } - - public function test_encode_decode_round_trip_preserves_arbitrary_metadata(): void - { - $schema = schema_from_json(FloeSchemaContext::schemaBody(schema(int_schema('id'), str_schema('name')))); - - $encoder = new PhpFloeEncoder($schema); - - $metadata = ['name' => Metadata::fromArray(['source' => 'trusted', 'weight' => 3])]; - - $decoded = $encoder->decode($encoder->encode(array_to_rows( - [['id' => 1, 'name' => 'flow']], - $schema->setMetadata('name', $metadata['name']), - ))); - - static::assertEquals([new RawRowValues(['id' => 1, 'name' => 'flow'], $metadata)], $decoded); - static::assertSame('trusted', $decoded[0]->metadata['name']->get('source')); - static::assertSame(3, $decoded[0]->metadata['name']->get('weight')); - } - - public function test_null_entry_in_a_typed_column_encodes_as_a_plain_null(): void - { - $schema = schema_from_json(FloeSchemaContext::schemaBody(schema( - int_schema('id'), - str_schema('name', nullable: true), - ))); - - $encoder = new PhpFloeEncoder($schema); - $body = $encoder->encode(array_to_rows( - [['id' => 2, 'name' => null]], - schema(int_schema('id'), null_schema('name')), - ))[0]; - - $decoded = $encoder->decode([$body]); - - static::assertNull($decoded[0]->values['name']); - static::assertArrayNotHasKey('name', $decoded[0]->metadata); - } - - public function test_row_body_with_trailing_garbage_throws(): void - { - $schema = schema_from_json(FloeSchemaContext::schemaBody(schema(int_schema('id'), str_schema('name')))); - - $encoder = new PhpFloeEncoder($schema); - $body = $encoder->encode(array_to_rows( - [['id' => 1, 'name' => 'flow']], - schema(int_schema('id'), str_schema('name')), - ))[0]; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('Floe row frame length does not match its content'); - - $encoder->decode([$body . "\x00"]); - } - - public function test_unknown_value_flag_throws(): void - { - $schema = schema_from_json(FloeSchemaContext::schemaBody(schema(int_schema('id'), str_schema('name')))); - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('unknown value flag'); - - (new PhpFloeEncoder($schema))->decode(["\xEF"]); - } - - public function test_decode_rows_builds_the_decoded_values(): void - { - $data = array_to_rows( - [['id' => 1, 'name' => 'flow'], ['id' => 2, 'name' => null]], - schema(int_schema('id'), str_schema('name', nullable: true)), - ); - $schema = schema_from_json(FloeSchemaContext::schemaBody($data->schema())); - $encoder = new PhpFloeEncoder($schema); - $bodies = $encoder->encode($data); - - static::assertEquals( - (new RowsBuilder($schema, new DefaultBackend())) - ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $encoder->decode($bodies))) - ->finish(), - $encoder->decodeRows($bodies, $schema), - ); - } - - public function test_decode_rows_builds_through_the_given_backend(): void - { - $data = RowsMother::numbered(3); - $backend = new SpyBackend(); - - (new PhpFloeEncoder($data->schema(), $backend))->decodeRows( - (new PhpFloeEncoder($data->schema()))->encode($data), - $data->schema(), - ); - - static::assertGreaterThanOrEqual(1, $backend->builders()); - } - - public function test_decode_rows_folds_metadata_onto_the_column_with_last_write_winning(): void - { - $plain = schema(int_schema('id', nullable: true)); - $encoder = new PhpFloeEncoder($plain); - - $bodies = [ - ...$encoder->encode(array_to_rows( - [['id' => 1]], - $plain->setMetadata('id', Metadata::fromArray(['k' => 'v1'])), - )), - ...$encoder->encode(array_to_rows( - [['id' => 2]], - $plain->setMetadata('id', Metadata::fromArray(['k' => 'v2'])), - )), - ]; - - static::assertSame( - ['k' => 'v2'], - $encoder->decodeRows($bodies, $plain)->schema()->get('id')->metadata()->normalize(), - ); - } - - public function test_decode_rows_folds_metadata_onto_a_numeric_column_name(): void - { - $plain = schema(int_schema('0', nullable: true)); - $encoder = new PhpFloeEncoder($plain); - - $bodies = $encoder->encode(array_to_rows( - [['0' => 1]], - $plain->setMetadata('0', Metadata::fromArray(['k' => 'v'])), - )); - - static::assertSame( - ['k' => 'v'], - $encoder->decodeRows($bodies, $plain)->schema()->get('0')->metadata()->normalize(), - ); - } - - public function test_decode_rows_ignores_metadata_of_an_undeclared_column(): void - { - $written = schema(int_schema('id'), int_schema('nope')); - $encoder = new PhpFloeEncoder($written); - - $bodies = $encoder->encode(array_to_rows( - [['id' => 1, 'nope' => 2]], - $written->setMetadata('nope', Metadata::fromArray(['k' => 'v'])), - )); - - static::assertEquals( - schema(int_schema('id')), - $encoder->decodeRows($bodies, schema(int_schema('id')))->schema(), - ); - } - - public function test_encode_of_an_empty_batch_returns_no_bodies(): void - { - static::assertSame( - [], - (new PhpFloeEncoder(schema(int_schema('id'), str_schema('name'))))->encode(array_to_rows( - [], - schema(int_schema('id')), - )), - ); - } - - public function test_a_not_null_refusal_on_an_earlier_column_wins_over_a_missing_later_column(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('column "id" (row 0)'); - - (new PhpFloeEncoder(schema(int_schema('id'), str_schema('name'))))->encode(array_to_rows([[ - 'id' => null, - ]], schema(int_schema('id', nullable: true)))); - } - - public function test_encode_frames_frames_the_encoded_rows(): void - { - $data = RowsMother::numbered(3); - $encoder = new PhpFloeEncoder($data->schema()); - - static::assertSame(Format::rowFrames($encoder->encode($data)), $encoder->encodeFrames($data)); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/SchemaDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/SchemaDecoderTest.php deleted file mode 100644 index 185e5ab4f5..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/SchemaDecoderTest.php +++ /dev/null @@ -1,69 +0,0 @@ -decode($schemaJson); - - static::assertCount(1, $plan); - static::assertSame('name', $plan[0]->name); - static::assertFalse($plan[0]->definition->isNullable()); - } - - public function test_decoded_plan_maps_a_null_column_to_a_null_definition(): void - { - $schemaJson = FloeSchemaContext::schemaBody(schema(null_schema('name'))); - - $plan = (new SchemaDecoder(new ValueDecoder()))->decode($schemaJson); - - static::assertInstanceOf(NullDefinition::class, $plan[0]->definition); - static::assertTrue($plan[0]->definition->isNullable()); - } - - public function test_decoded_plan_preserves_custom_metadata(): void - { - $schemaJson = FloeSchemaContext::schemaBody(schema(int_schema('id', metadata: Metadata::fromArray([ - 'custom' => 'meta', - ])))); - - $plan = (new SchemaDecoder(new ValueDecoder()))->decode($schemaJson); - - static::assertSame('meta', $plan[0]->definition->metadata()->get('custom')); - } - - public function test_decoding_invalid_json_throws(): void - { - $this->expectException(FloeException::class); - $this->expectExceptionMessage('failed to decode schema JSON'); - - (new SchemaDecoder(new ValueDecoder()))->decode('{invalid'); - } - - public function test_decoding_non_list_json_throws(): void - { - $this->expectException(FloeException::class); - $this->expectExceptionMessage('expected schema JSON to be a list'); - - (new SchemaDecoder(new ValueDecoder()))->decode('"scalar"'); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/ValueDecoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/ValueDecoderTest.php deleted file mode 100644 index 7156cb49e7..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/ValueDecoderTest.php +++ /dev/null @@ -1,253 +0,0 @@ -decoderFor(enum_schema('c', BackedStringEnum::class)); - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('cannot restore enum case'); - - $decoder->decode($encoded, $position); - } - - public function test_decoding_enum_of_unknown_class_throws(): void - { - $encoded = pack('V', 10) . 'NoSuchEnum' . pack('V', 3) . 'one'; - $decoder = (new ValueDecoder())->decoderFor(enum_schema('c', BackedStringEnum::class)); - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('enum not found'); - - $decoder->decode($encoded, $position); - } - - public function test_decoding_html_document_below_php84_throws(): void - { - if (class_exists('\Dom\HTMLDocument')) { - static::markTestSkipped('requires PHP < 8.4'); - } - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('requires PHP 8.4+'); - - ValueDecoder::htmlDocumentFromString('

      x

      '); - } - - public function test_decoding_html_element_below_php84_throws(): void - { - if (class_exists('\Dom\HTMLDocument')) { - static::markTestSkipped('requires PHP < 8.4'); - } - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('requires PHP 8.4+'); - - ValueDecoder::htmlElementFromString('

      x

      '); - } - - public function test_decoding_structure_with_unknown_element_flag_throws(): void - { - $decoder = (new ValueDecoder())->decoderFor(structure_schema('c', type_structure(['name' => type_string()]))); - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('unknown structure element flag'); - - $decoder->decode("\xEE", $position); - } - - public function test_decoding_invalid_xml_throws(): void - { - $encoded = pack('V', 9) . 'not < xml'; - $decoder = (new ValueDecoder())->decoderFor(xml_schema('c')); - $position = 0; - - $this->expectException(FloeException::class); - $this->expectExceptionMessage('failed to restore DOMDocument'); - - $decoder->decode($encoded, $position); - } - - public function test_decoding_value_of_unsupported_type_throws(): void - { - $this->expectException(FloeException::class); - $this->expectExceptionMessage('Floe does not support columns of type "mixed"'); - - (new ValueDecoder())->decoderFor(new ForeignTypeDefinition('c', type_mixed())); - } - - public function test_round_trip_of_datetime_reads_the_column_zone(): void - { - $value = new DateTimeImmutable('2025-06-15 12:30:45.987654', new DateTimeZone('Australia/Eucla')); - $encoded = (new ValueEncoder()) - ->encoderFor(datetime_schema('c')) - ->encode($value); - $position = 0; - - // @mago-ignore analysis:mixed-assignment - $decoded = (new ValueDecoder()) - ->decoderFor(datetime_schema('c')) - ->decode($encoded, $position); - - static::assertInstanceOf(DateTimeImmutable::class, $decoded); - static::assertEquals($value, $decoded); - static::assertSame('UTC', $decoded->getTimezone()->getName()); - static::assertSame('987654', $decoded->format('u')); - static::assertSame(strlen($encoded), $position); - } - - public function test_round_trip_of_date_keeps_the_stored_zone(): void - { - $value = new DateTimeImmutable('2025-06-15 00:00:00', new DateTimeZone('Australia/Eucla')); - $encoded = (new ValueEncoder()) - ->encoderFor(date_schema('c')) - ->encode($value); - $position = 0; - - // @mago-ignore analysis:mixed-assignment - $decoded = (new ValueDecoder()) - ->decoderFor(date_schema('c')) - ->decode($encoded, $position); - - static::assertInstanceOf(DateTimeImmutable::class, $decoded); - static::assertEquals($value, $decoded); - static::assertSame('Australia/Eucla', $decoded->getTimezone()->getName()); - static::assertSame(strlen($encoded), $position); - } - - public function test_round_trip_of_datetime_before_epoch(): void - { - $value = new DateTimeImmutable('1969-07-20 20:17:00.500000 UTC'); - $encoded = (new ValueEncoder()) - ->encoderFor(datetime_schema('c')) - ->encode($value); - $position = 0; - - static::assertEquals($value, (new ValueDecoder()) - ->decoderFor(datetime_schema('c')) - ->decode($encoded, $position)); - } - - public function test_round_trip_of_integer_signed_edges(): void - { - $encoder = (new ValueEncoder())->encoderFor(int_schema('c')); - $decoder = (new ValueDecoder())->decoderFor(int_schema('c')); - - foreach ([PHP_INT_MIN, PHP_INT_MAX, -1, 0, 42] as $value) { - $position = 0; - - static::assertSame($value, $decoder->decode($encoder->encode($value), $position)); - } - } - - public function test_round_trip_of_interval_preserves_all_fields(): void - { - $value = new DateInterval('P1DT2H3M4S'); - // @mago-ignore analysis:invalid-property-write - $value->invert = 1; - // @mago-ignore analysis:invalid-property-write - $value->f = 0.5; - - $encoded = (new ValueEncoder()) - ->encoderFor(time_schema('c')) - ->encode($value); - $position = 0; - - // @mago-ignore analysis:mixed-assignment - $decoded = (new ValueDecoder()) - ->decoderFor(time_schema('c')) - ->decode($encoded, $position); - - static::assertInstanceOf(DateInterval::class, $decoded); - static::assertSame([1, 2, 3, 4, 0.5, 1], [ - $decoded->d, - $decoded->h, - $decoded->i, - $decoded->s, - $decoded->f, - $decoded->invert, - ]); - } - - public function test_restoring_xml_element_from_string(): void - { - static::assertSame('item', ValueDecoder::xmlElementFromString('value')->tagName); - } - - public function test_round_trip_of_uuid_skips_validation(): void - { - $uuid = new Uuid('0196aecb-b568-7e57-a381-8ec8d3e4a531'); - $encoded = (new ValueEncoder()) - ->encoderFor(uuid_schema('c')) - ->encode($uuid); - $position = 0; - - // @mago-ignore analysis:mixed-assignment - $decoded = (new ValueDecoder()) - ->decoderFor(uuid_schema('c')) - ->decode($encoded, $position); - - static::assertInstanceOf(Uuid::class, $decoded); - static::assertSame($uuid->toString(), $decoded->toString()); - } - - public function test_round_trip_of_a_list_with_null_or_t_elements(): void - { - $definition = list_schema('c', type_list(type_union(type_integer(), type_null()))); - $encoded = (new ValueEncoder()) - ->encoderFor($definition) - ->encode([1, null]); - $position = 0; - - static::assertSame( - [1, null], - (new ValueDecoder()) - ->decoderFor($definition) - ->decode($encoded, $position), - ); - } -} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/ValueEncoderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/ValueEncoderTest.php deleted file mode 100644 index 355ba4216e..0000000000 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/ValueEncoderTest.php +++ /dev/null @@ -1,103 +0,0 @@ -expectException(FloeException::class); - $this->expectExceptionMessage('Floe supports only DateTime and DateTimeImmutable, got ' - . CustomDateTime::class); - - (new DateTimeEncoder())->encode(new CustomDateTime('2025-01-01 00:00:00 UTC')); - } - - public function test_encoding_a_column_of_an_unsupported_type_throws(): void - { - $this->expectException(FloeException::class); - $this->expectExceptionMessage('Floe does not support columns of type "mixed"'); - - (new ValueEncoder())->encoderFor(new ForeignTypeDefinition('c', type_mixed())); - } - - public function test_encoding_list_of_mixed_elements_throws(): void - { - $this->expectException(FloeException::class); - $this->expectExceptionMessage('Floe does not support values of type "mixed"'); - - (new ValueEncoder())->encoderFor(list_schema('c', type_list(type_mixed()))); - } - - public function test_encoding_map_with_unsupported_key_type_throws(): void - { - $this->expectException(FloeException::class); - $this->expectExceptionMessage('Floe does not support map keys of type "non_empty_string"'); - - (new ValueEncoder())->encoderFor(map_schema('c', type_map(type_non_empty_string(), type_string()))); - } - - public function test_encoding_xml_element_without_owner_document_throws(): void - { - $this->expectException(FloeException::class); - $this->expectExceptionMessage('failed to convert DOMElement to XML string'); - - ValueEncoder::xmlElementToString(new DOMElement('detached')); - } - - public function test_integer_encoding_is_little_endian_for_signed_edges(): void - { - $encoder = (new ValueEncoder())->encoderFor(int_schema('c')); - - static::assertSame(pack('P', PHP_INT_MIN), $encoder->encode(PHP_INT_MIN)); - static::assertSame(pack('P', PHP_INT_MAX), $encoder->encode(PHP_INT_MAX)); - static::assertSame("\xFB\xFF\xFF\xFF\xFF\xFF\xFF\xFF", $encoder->encode(-5)); - static::assertSame("\x2A\x00\x00\x00\x00\x00\x00\x00", $encoder->encode(42)); - } - - public function test_integer_list_fast_path_is_bulk_packed(): void - { - $encoder = (new ValueEncoder())->encoderFor(list_schema('c', type_list(type_integer()))); - - static::assertSame(pack('V', 3) . pack('P*', 10, -20, 30), $encoder->encode([10, -20, 30])); - static::assertSame(pack('V', 0), $encoder->encode([])); - } - - public function test_stateful_encoders_are_shared_across_calls(): void - { - $factory = new ValueEncoder(); - - static::assertSame($factory->encoderFor(datetime_schema('c')), $factory->encoderFor(datetime_schema('c'))); - static::assertSame($factory->encoderFor(datetime_schema('c')), $factory->encoderFor(date_schema('c'))); - static::assertSame($factory->encoderFor(uuid_schema('c')), $factory->encoderFor(uuid_schema('c'))); - static::assertSame($factory->encoderFor(json_schema('c')), $factory->encoderFor(json_schema('c'))); - } -} From 88e226c938a15c363a9bbc69d01da54091be5055 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Mon, 28 Sep 2026 17:02:28 +0200 Subject: [PATCH 05/21] feat(flow-php/flow-php-ext): native Arrow column backend - DefaultBackend, NativeColumn, NativeColumnBuilder over Arrow arrays - flow-batch-frame crate for column buffers and BATCH bodies - CSV reads straight into native columns via nextColumns() - Backend gains adopt() and allocatedBytes(); pipelines build with the configured backend - RawRowValues, row hydrator and ROW-frame encoder removed - untagged builds report the next minor as -dev; Composer conflict on older extensions --- .github/workflows/job-arrow-extension.yml | 8 +- .github/workflows/job-flow-php-extension.yml | 29 +- .github/workflows/test-suite.yml | 2 + .nix/pkgs/php-arrow-ext/package.nix | 2 +- .nix/pkgs/php-flow-php-ext/package.nix | 4 +- bootstrap.php | 1 + .../components/extensions/flow-php-ext.md | 27 +- documentation/contributing/rust.md | 43 +- documentation/upgrading.md | 43 +- src/adapter/etl-adapter-csv/composer.json | 3 + .../src/Flow/ETL/Adapter/CSV/CSVDecoder.php | 9 +- .../src/Flow/ETL/Adapter/CSV/CSVExtractor.php | 66 +- .../Flow/ETL/Adapter/CSV/CSVFileReader.php | 29 +- .../Flow/ETL/Adapter/CSV/CSVFileSample.php | 5 +- .../Flow/ETL/Adapter/CSV/CSVOpenSource.php | 19 +- .../ETL/Adapter/CSV/NativeCSVOpenSource.php | 34 + .../Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php | 30 +- .../CSV/Tests/Context/CSVFixtureContext.php | 83 +- .../Fixtures/columns_diverge_refused/a.csv | 2 + .../Fixtures/columns_diverge_refused/b.csv | 2 + .../Tests/Integration/CSVExtractorTest.php | 16 +- .../Tests/Integration/CSVFileReaderTest.php | 38 +- .../Tests/Integration/CSVFileSampleTest.php | 2 +- .../Integration/NativeCSVOpenSourceTest.php | 280 +++++- .../Integration/PhpCSVOpenSourceTest.php | 131 ++- .../Adapter/CSV/Tests/Unit/CSVDecoderTest.php | 26 +- .../CSV/Tests/Unit/CSVExtractorTest.php | 6 +- .../Flow/ETL/Adapter/Excel/ExcelDecoder.php | 6 +- .../Flow/ETL/Adapter/Excel/ExcelExtractor.php | 6 +- .../Flow/ETL/Adapter/Excel/WorkbookSheet.php | 7 +- .../ETL/Adapter/Excel/WorkbookSheetSample.php | 7 +- .../Tests/Integration/WorkbookReaderTest.php | 4 +- .../Tests/Integration/WorkbookSheetTest.php | 4 +- .../Excel/Tests/Unit/ExcelDecoderTest.php | 13 +- .../Tests/Unit/WorkbookSheetSampleTest.php | 11 +- .../GoogleSheet/GoogleSheetDecoder.php | 7 +- .../GoogleSheet/GoogleSheetExtractor.php | 13 +- .../Adapter/GoogleSheet/GoogleSheetReader.php | 3 +- .../Adapter/GoogleSheet/GoogleSheetSample.php | 4 +- .../GoogleSheet/GoogleSheetSampler.php | 5 +- .../Tests/Unit/GoogleSheetDecoderTest.php | 46 +- .../Tests/Unit/GoogleSheetReadOptionsTest.php | 6 +- .../Tests/Unit/GoogleSheetReaderTest.php | 2 +- .../Tests/Unit/GoogleSheetSampleTest.php | 5 +- .../Tests/Unit/GoogleSheetSamplerTest.php | 6 +- .../JSON/JSONMachine/JsonExtractor.php | 4 +- .../JSON/JSONMachine/JsonFileReader.php | 7 +- .../JSON/JSONMachine/JsonFileSample.php | 5 +- .../JSON/JSONMachine/JsonLinesExtractor.php | 4 +- .../JSONMachine/JsonFileReaderTest.php | 24 +- src/core/etl/composer.json | 3 + .../Bucketing/Storage/FilesystemBuckets.php | 4 +- src/core/etl/src/Flow/ETL/Column/Backend.php | 17 + .../src/Flow/ETL/Column/DefaultBackend.php | 16 + .../etl/src/Flow/ETL/Column/PhpBackend.php | 31 + .../Bucketing/BucketingConfigBuilder.php | 4 +- .../etl/src/Flow/ETL/Config/ConfigBuilder.php | 11 +- .../Grouping/GroupByAlgorithmBuilder.php | 3 +- .../Config/Grouping/HashGroupByBuilder.php | 5 +- .../Flow/ETL/Config/Join/HashJoinBuilder.php | 5 +- .../ETL/Config/Join/JoinAlgorithmBuilder.php | 3 +- .../Repartition/HashRepartitionBuilder.php | 5 +- .../RepartitionAlgorithmBuilder.php | 3 +- .../ETL/Config/Sort/ExternalSortBuilder.php | 9 +- .../ETL/Config/Sort/MemorySortBuilder.php | 3 +- .../ETL/Config/Sort/SortAlgorithmBuilder.php | 3 +- .../ETL/Config/Telemetry/TelemetryContext.php | 8 +- .../Flow/ETL/Dataset/Memory/Consumption.php | 7 +- .../Flow/ETL/Executor/StatisticsCollector.php | 2 +- .../src/Flow/ETL/Extractor/InMemoryRows.php | 7 +- .../src/Flow/ETL/Extractor/SpilledRows.php | 7 +- .../ETL/Filesystem/ScalarFunctionFilter.php | 5 +- src/core/etl/src/Flow/ETL/FlowContext.php | 1 + .../src/Flow/ETL/GroupBy/AggregatedGroups.php | 7 +- .../Flow/ETL/GroupBy/BucketAggregation.php | 4 +- .../etl/src/Flow/ETL/GroupBy/GroupBySteps.php | 3 +- .../etl/src/Flow/ETL/Join/HashJoin/Joiner.php | 15 +- src/core/etl/src/Flow/ETL/Join/JoinSteps.php | 2 +- .../Optimizer/Rule/CountFromStatistics.php | 5 +- .../src/Flow/ETL/Optimizer/TopNRewrite.php | 3 +- .../Flow/ETL/Processor/CountingProcessor.php | 7 +- .../Processor/GroupByAggregationProcessor.php | 3 +- .../Flow/ETL/Processor/HashJoinProcessor.php | 2 +- .../Flow/ETL/Processor/MergeSortProcessor.php | 2 +- .../Flow/ETL/Repartition/RepartitionSteps.php | 3 +- .../etl/src/Flow/ETL/Row/RawRowValues.php | 19 - src/core/etl/src/Flow/ETL/Rows.php | 13 +- .../Flow/ETL/Schema/Inference/ColumnTypes.php | 7 +- .../ETL/Schema/Inference/SchemaInferrer.php | 5 +- .../ETL/Schema/Inference/SchemaSampler.php | 4 +- .../Schema/Inference/SniffsColumnTypes.php | 3 +- .../etl/src/Flow/ETL/Sort/Merge/KWayMerge.php | 5 +- src/core/etl/src/Flow/ETL/Sort/SortSteps.php | 2 +- .../ETL/Tests/Comparator/ColumnComparator.php | 63 ++ .../Tests/Context/MemoryTelemetryContext.php | 1 + .../ETL/Tests/Double/AcceptingBackend.php | 10 + .../ETL/Tests/Double/FakeSchemaSampler.php | 5 +- .../ETL/Tests/Double/ForeignColumnStub.php | 83 ++ .../ETL/Tests/Double/RecordingSources.php | 7 +- .../Flow/ETL/Tests/Double/SpyBackend.php | 24 +- .../ETL/Tests/Double/SpySniffingSample.php | 5 +- .../Storage/FilesystemBucketsTest.php | 53 +- .../Bucketing/BucketingConfigBuilderTest.php | 3 +- .../Extractor/FileSourceFilesystemTest.php | 4 +- .../Tests/Unit/Column/DefaultBackendTest.php | 26 + .../ETL/Tests/Unit/Column/PhpBackendTest.php | 44 + .../Unit/Comparator/ColumnComparatorTest.php | 65 ++ .../Bucketing/BucketingConfigBuilderTest.php | 12 +- .../Grouping/HashGroupByBuilderTest.php | 7 +- .../Unit/Config/Join/HashJoinBuilderTest.php | 7 +- .../Config/Sort/ExternalSortBuilderTest.php | 21 +- .../Config/Sort/MemorySortBuilderTest.php | 6 +- .../Config/Telemetry/TelemetryContextTest.php | 17 + .../Unit/Dataset/Memory/ConsumptionTest.php | 13 +- .../Tests/Unit/Extractor/InMemoryRowsTest.php | 13 +- .../Unit/GroupBy/AggregatedGroupsTest.php | 13 +- .../Tests/Unit/Join/HashJoin/JoinerTest.php | 41 +- .../Unit/Processor/CountingProcessorTest.php | 17 + .../GroupByAggregationProcessorTest.php | 41 + .../Unit/Processor/HashJoinProcessorTest.php | 25 + .../Unit/Processor/MergeSortProcessorTest.php | 27 + .../ETL/Tests/Unit/Row/RawRowValuesTest.php | 29 - .../tests/Flow/ETL/Tests/Unit/RowsTest.php | 18 +- .../Unit/Schema/Inference/ColumnTypesTest.php | 120 +-- .../Schema/Inference/SchemaInferrerTest.php | 25 +- .../Tests/Unit/Sort/Merge/KWayMergeTest.php | 21 +- src/extension/arrow-ext/build.rs | 13 +- .../tests/phpt/038_extension_version.phpt | 4 +- src/extension/flow-php-ext/Cargo.lock | 326 +++++++ src/extension/flow-php-ext/Cargo.toml | 9 + src/extension/flow-php-ext/build.rs | 13 +- src/extension/flow-php-ext/composer.json | 3 +- .../crates/flow-batch-frame/.gitattributes | 5 + .../crates/flow-batch-frame/.gitignore | 1 + .../crates/flow-batch-frame/Cargo.lock | 629 ++++++++++++ .../crates/flow-batch-frame/Cargo.toml | 15 + .../crates/flow-batch-frame/src/body.rs | 209 ++++ .../crates/flow-batch-frame/src/column.rs | 572 +++++++++++ .../crates/flow-batch-frame/src/error.rs | 168 ++++ .../crates/flow-batch-frame/src/format.rs | 67 ++ .../crates/flow-batch-frame/src/kind.rs | 213 ++++ .../crates/flow-batch-frame/src/layout.rs | 158 +++ .../crates/flow-batch-frame/src/lib.rs | 18 + .../crates/flow-batch-frame/tests/body.rs | 236 +++++ .../crates/flow-batch-frame/tests/column.rs | 468 +++++++++ .../flow-batch-frame/tests/common/mod.rs | 10 + .../crates/flow-batch-frame/tests/kind.rs | 143 +++ .../ETL/Adapter/CSV/RustCSVReaderNative.php | 21 +- .../Flow/ETL/Row/RustRowHydratorNative.php | 47 - .../php/Flow/Floe/RustFloeEncoderNative.php | 85 -- src/extension/flow-php-ext/src/alloc.rs | 53 + src/extension/flow-php-ext/src/backend.rs | 135 +++ src/extension/flow-php-ext/src/builder.rs | 444 +++++++++ src/extension/flow-php-ext/src/cast.rs | 560 +++-------- src/extension/flow-php-ext/src/column.rs | 320 ++++++ src/extension/flow-php-ext/src/csv/columns.rs | 321 ++++++ src/extension/flow-php-ext/src/csv/fold.rs | 12 +- src/extension/flow-php-ext/src/csv/mod.rs | 59 +- src/extension/flow-php-ext/src/ctx.rs | 913 ++++++++---------- src/extension/flow-php-ext/src/date_check.rs | 79 ++ src/extension/flow-php-ext/src/encode.rs | 795 --------------- src/extension/flow-php-ext/src/exception.rs | 23 + src/extension/flow-php-ext/src/format.rs | 81 -- src/extension/flow-php-ext/src/globals.rs | 43 + src/extension/flow-php-ext/src/hydrate.rs | 576 ----------- src/extension/flow-php-ext/src/interfaces.rs | 143 +++ .../flow-php-ext/src/kind_builder.rs | 324 +++++++ src/extension/flow-php-ext/src/lib.rs | 338 +------ src/extension/flow-php-ext/src/physical.rs | 275 ++++++ src/extension/flow-php-ext/src/plan.rs | 306 +++--- src/extension/flow-php-ext/src/render.rs | 168 ++++ src/extension/flow-php-ext/src/values.rs | 535 +++++----- .../tests/phpt/001_extension_loaded.phpt | 17 +- ...xtension_version_is_release_or_commit.phpt | 4 +- .../tests/phpt/040_csv_tokenizer_parity.phpt | 2 +- .../tests/phpt/051_csv_guards.phpt | 18 + .../phpt/055_column_interfaces_skew.phpt | 20 + .../phpt/056_native_constructors_refused.phpt | 32 + .../tests/phpt/057_native_encode_parity.phpt | 47 + .../tests/phpt/058_native_values_parity.phpt | 94 ++ .../tests/phpt/059_native_cast_parity.phpt | 99 ++ .../phpt/060_native_decode_refusals.phpt | 63 ++ .../phpt/061_native_mixed_class_building.phpt | 70 ++ .../tests/phpt/062_native_no_leaks.phpt | 48 + .../phpt/063_csv_next_columns_parity.phpt | 78 ++ .../phpt/064_csv_next_columns_no_leaks.phpt | 59 ++ .../tests/phpt/065_type_plan_by_object.phpt | 32 + .../066_iso_datetime_fast_path_parity.phpt | 133 +++ .../flow-php-ext/tests/phpt/bootstrap.php | 321 +++++- 189 files changed, 9367 insertions(+), 3987 deletions(-) create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Fixtures/columns_diverge_refused/a.csv create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Fixtures/columns_diverge_refused/b.csv delete mode 100644 src/core/etl/src/Flow/ETL/Row/RawRowValues.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Comparator/ColumnComparator.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/ForeignColumnStub.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ColumnComparatorTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RawRowValuesTest.php create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/.gitattributes create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/.gitignore create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/Cargo.lock create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/Cargo.toml create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/error.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/format.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/layout.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/lib.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/tests/common/mod.rs create mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/tests/kind.rs delete mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Row/RustRowHydratorNative.php delete mode 100644 src/extension/flow-php-ext/php/Flow/Floe/RustFloeEncoderNative.php create mode 100644 src/extension/flow-php-ext/src/alloc.rs create mode 100644 src/extension/flow-php-ext/src/backend.rs create mode 100644 src/extension/flow-php-ext/src/builder.rs create mode 100644 src/extension/flow-php-ext/src/column.rs create mode 100644 src/extension/flow-php-ext/src/csv/columns.rs delete mode 100644 src/extension/flow-php-ext/src/encode.rs delete mode 100644 src/extension/flow-php-ext/src/format.rs create mode 100644 src/extension/flow-php-ext/src/globals.rs delete mode 100644 src/extension/flow-php-ext/src/hydrate.rs create mode 100644 src/extension/flow-php-ext/src/interfaces.rs create mode 100644 src/extension/flow-php-ext/src/kind_builder.rs create mode 100644 src/extension/flow-php-ext/src/physical.rs create mode 100644 src/extension/flow-php-ext/src/render.rs create mode 100644 src/extension/flow-php-ext/tests/phpt/055_column_interfaces_skew.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/056_native_constructors_refused.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/058_native_values_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/060_native_decode_refusals.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/062_native_no_leaks.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/063_csv_next_columns_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/064_csv_next_columns_no_leaks.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/065_type_plan_by_object.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/066_iso_datetime_fast_path_parity.phpt diff --git a/.github/workflows/job-arrow-extension.yml b/.github/workflows/job-arrow-extension.yml index d5296a92ba..31bea22951 100644 --- a/.github/workflows/job-arrow-extension.yml +++ b/.github/workflows/job-arrow-extension.yml @@ -202,7 +202,13 @@ jobs: - name: Verify extension version run: | - expected="$(git describe --tags --match '[0-9]*' | sed -E 's/-([0-9]+)-(g[0-9a-f]+)$/+\1.\2/')" + describe="$(git describe --tags --match '[0-9]*')" + if git describe --exact-match --tags --match '[0-9]*' HEAD >/dev/null 2>&1; then + expected="$describe" + else + # commits past a tag are a pre-release of the next minor: 0.44.1-65-g4525c4adc -> 0.45.0-dev+65.g4525c4adc + expected="$(echo "$describe" | awk -F- '{split($1, v, "."); printf "%d.%d.0-dev+%s.%s", v[1], v[2] + 1, $2, $3}')" + fi actual="$(php -r 'echo phpversion("arrow");')" echo "expected: $expected, actual: $actual" test "$actual" = "$expected" diff --git a/.github/workflows/job-flow-php-extension.yml b/.github/workflows/job-flow-php-extension.yml index 21023c8d85..a0a3530b45 100644 --- a/.github/workflows/job-flow-php-extension.yml +++ b/.github/workflows/job-flow-php-extension.yml @@ -76,10 +76,25 @@ jobs: echo "LIBCLANG_PATH=$(dirname "$LIBCLANG_SO")" >> "$GITHUB_ENV" echo "Detected libclang at: $LIBCLANG_SO" + - name: Verify the nix development version literals + run: | + if git describe --exact-match --tags --match '[0-9]*' HEAD >/dev/null 2>&1; then + exit 0 + fi + tag="$(git describe --tags --abbrev=0 --match '[0-9]*')" + expected="$(echo "$tag" | awk -F. '{printf "%d.%d.0-dev", $1, $2 + 1}')" + for f in .nix/pkgs/php-flow-php-ext/package.nix .nix/pkgs/php-arrow-ext/package.nix; do + grep -q "version ? \"$expected\"" "$f" || { echo "$f: version literal must be $expected"; exit 1; } + done + - name: Build extension working-directory: src/extension/flow-php-ext run: make build + - name: Test flow-batch-frame crate + working-directory: src/extension/flow-php-ext/crates/flow-batch-frame + run: cargo test --locked + - name: Install Composer Dependencies uses: ./.github/actions/composer-install with: @@ -104,6 +119,12 @@ jobs: - name: Run ETL Integration Tests with Flow PHP Extension run: just test --testsuite=etl-integration + - name: Run CSV Adapter Unit Tests with Flow PHP Extension + run: just test --testsuite=adapter-csv-unit + + - name: Run CSV Adapter Integration Tests with Flow PHP Extension + run: just test --testsuite=adapter-csv-integration + - name: Upload to Codecov if: ${{ !cancelled() && matrix.php == '8.3' && runner.os == 'Linux' }} uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 @@ -203,7 +224,13 @@ jobs: - name: Verify extension version run: | - expected="$(git describe --tags --match '[0-9]*' | sed -E 's/-([0-9]+)-(g[0-9a-f]+)$/+\1.\2/')" + describe="$(git describe --tags --match '[0-9]*')" + if git describe --exact-match --tags --match '[0-9]*' HEAD >/dev/null 2>&1; then + expected="$describe" + else + # commits past a tag are a pre-release of the next minor: 0.44.1-65-g4525c4adc -> 0.45.0-dev+65.g4525c4adc + expected="$(echo "$describe" | awk -F- '{split($1, v, "."); printf "%d.%d.0-dev+%s.%s", v[1], v[2] + 1, $2, $3}')" + fi actual="$(php -r 'echo phpversion("flow_php");')" echo "expected: $expected, actual: $actual" test "$actual" = "$expected" diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 6264d3f797..56167f8d6a 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -11,6 +11,7 @@ on: - 'composer.lock' - 'composer.json' - 'phpunit.xml.dist' + - '.nix/pkgs/**' push: branches: [ 1.x ] paths: @@ -22,6 +23,7 @@ on: - 'composer.lock' - 'composer.json' - 'phpunit.xml.dist' + - '.nix/pkgs/**' schedule: - cron: '0 4 * * *' workflow_dispatch: diff --git a/.nix/pkgs/php-arrow-ext/package.nix b/.nix/pkgs/php-arrow-ext/package.nix index 1a36e7224c..0272a006de 100644 --- a/.nix/pkgs/php-arrow-ext/package.nix +++ b/.nix/pkgs/php-arrow-ext/package.nix @@ -5,7 +5,7 @@ rustPlatform, clang, llvmPackages, - arrow-ext-version ? "dev", + arrow-ext-version ? "0.45.0-dev", }: let diff --git a/.nix/pkgs/php-flow-php-ext/package.nix b/.nix/pkgs/php-flow-php-ext/package.nix index 50e21c59d3..2f11a72ac8 100644 --- a/.nix/pkgs/php-flow-php-ext/package.nix +++ b/.nix/pkgs/php-flow-php-ext/package.nix @@ -5,7 +5,7 @@ rustPlatform, clang, llvmPackages, - flow-php-ext-version ? "dev", + flow-php-ext-version ? "0.45.0-dev", }: let @@ -58,7 +58,7 @@ let doCheck = false; meta = with lib; { - description = "Flow PHP native extension (Rust) - Floe frame-body encoder/decoder for DataFrame Rows"; + description = "Flow PHP native extension (Rust) - native column backend and CSV reader"; license = licenses.mit; }; }; diff --git a/bootstrap.php b/bootstrap.php index 43202e1a42..ade6286e0f 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -37,4 +37,5 @@ } SebastianBergmann\Comparator\Factory::getInstance()->register(new Flow\ETL\Tests\Comparator\RowsComparator()); +SebastianBergmann\Comparator\Factory::getInstance()->register(new Flow\ETL\Tests\Comparator\ColumnComparator()); SebastianBergmann\Comparator\Factory::getInstance()->register(new Flow\ETL\Tests\Comparator\RowComparator()); diff --git a/documentation/components/extensions/flow-php-ext.md b/documentation/components/extensions/flow-php-ext.md index 41ed20abaf..855f4ba9e1 100644 --- a/documentation/components/extensions/flow-php-ext.md +++ b/documentation/components/extensions/flow-php-ext.md @@ -8,7 +8,7 @@ package: flow-php/flow-php-ext [TOC] -This extension reads CSV and narrows string columns to their types natively in Rust via +This extension is Flow's native column backend and reads CSV natively in Rust via [ext-php-rs](https://github.com/extphprs/ext-php-rs). The pure-PHP implementations in `flow-php/etl` are the canonical behaviour reference and work without the extension - loading it is purely an optimization. @@ -42,6 +42,25 @@ df() ->run(); ``` -The extension registers `Flow\ETL\Adapter\CSV\RustCSVReaderNative` and -`Flow\ETL\Adapter\CSV\RustColumnFoldNative`, used by `Flow\ETL\Adapter\CSV\NativeCSVOpenSource` for CSV reading and -string-type narrowing. The Floe codec and the row hydrator run in PHP until the native column backend lands. +With the extension loaded, `Flow\ETL\Column\DefaultBackend` - the default of `config_builder()->backend()` - is the +extension's class and every batch column is a `Flow\ETL\Column\NativeColumn` over an Apache Arrow array: + +```php +builder(int_schema('id')); +$builder->appendMany([1, '2', 3.0]); + +$column = $builder->finish(); // Flow\ETL\Column\NativeColumn +$column->values(); // [1, 2, 3] +(new DefaultBackend())->allocatedBytes(); // bytes held outside PHP's memory manager +``` + +The extension registers the interfaces `Flow\ETL\Column\{Backend, Column, ColumnBuilder}`, the classes +`Flow\ETL\Column\{DefaultBackend, NativeColumn, NativeColumnBuilder}`, and `Flow\ETL\Adapter\CSV\RustCSVReaderNative` +and `Flow\ETL\Adapter\CSV\RustColumnFoldNative`, which read CSV straight into native columns and narrow string +columns to their types. diff --git a/documentation/contributing/rust.md b/documentation/contributing/rust.md index 6b1283773c..8e4a04815c 100644 --- a/documentation/contributing/rust.md +++ b/documentation/contributing/rust.md @@ -8,7 +8,7 @@ This document describes how to develop the two Rust PHP extensions in this monor | Extension | Package | What it provides | |---|---|---| | `arrow-ext` | `flow-php/arrow-ext` | Parquet reader and writer powered by the [Apache Arrow](https://arrow.apache.org/) Rust ecosystem, exposed as `Flow\Arrow\Parquet\Reader` and `Flow\Arrow\Parquet\Writer` | -| `flow-php-ext` | `flow-php/flow-php-ext` | Native Floe binary frame encoding/decoding and row hydration/casting against a schema | +| `flow-php-ext` | `flow-php/flow-php-ext` | The native column backend (`Flow\ETL\Column\DefaultBackend`, `NativeColumn`, `NativeColumnBuilder` over Apache Arrow arrays) and the native CSV reader | Both are optional. The pure-PHP implementations in `flow-php/etl` remain the canonical behaviour reference, and Flow routes to the native code automatically when the extension is loaded. @@ -58,16 +58,24 @@ src/extension/flow-php-ext/ ├── Makefile # Build orchestration ├── src/ # Rust source code │ ├── lib.rs # Extension entry point, module registration -│ ├── encode.rs # Floe frame body encoder -│ ├── format.rs # Floe binary format primitives -│ ├── hydrate.rs # Row hydration against a schema +│ ├── interfaces.rs # Flow\ETL\Column\{Backend, Column, ColumnBuilder}, registered at MINIT +│ ├── backend.rs # DefaultBackend +│ ├── column.rs # NativeColumn +│ ├── builder.rs # NativeColumnBuilder: native cast lanes, PHP lane for the rest +│ ├── kind_builder.rs # Arrow storage appended row by row +│ ├── physical.rs # Arrow rows as physical and logical zvals +│ ├── plan.rs # Per-type plan, cached by Type object and type JSON +│ ├── render.rs # flow-batch-frame refusals as the PHP messages │ ├── cast.rs # Value casting │ ├── json_check.rs # JSON validation shared by casting and CSV inference -│ ├── csv/ # CSV tokenizer, reader and schema-inference fold -│ ├── plan.rs # Per-column plan resolved once per schema -│ ├── ctx.rs # Shared module context +│ ├── csv/ # CSV tokenizer, reader, native columns and schema-inference fold +│ ├── ctx.rs # Request-scoped context and engine helpers +│ ├── globals.rs # Module globals, RINIT/RSHUTDOWN +│ ├── alloc.rs # Counting global allocator (allocatedBytes()) │ ├── values.rs # Zval <-> PHP value helpers │ └── exception.rs # Exception mapping +├── crates/ +│ └── flow-batch-frame/ # Pure-Rust column buffers and BATCH frame bodies (no PHP types) ├── php/ # PHP stubs for static analysis │ └── Flow/ ├── tests/ @@ -133,3 +141,24 @@ Re-enter `nix-shell` to rebuild the derivation, or build and test the extension ```bash nix-shell --arg with-rust true --run "cd src/extension/flow-php-ext && make build && make test" ``` + +This covers `crates/flow-batch-frame`, which the flow-php-ext build compiles from the same directory. + +## The flow-batch-frame crate + +`src/extension/flow-php-ext/crates/flow-batch-frame` holds Flow's batch layout in pure Rust: one column's buffers in the +canonical form of `Column::encode()` and back, and the BATCH frame body around them. It returns every refusal as a data +`Error` variant; `flow_php` renders each into the PHP message. flow-php-ext depends on it by `path`: + +```bash +nix-shell --arg with-rust true --run "cd src/extension/flow-php-ext/crates/flow-batch-frame && cargo test" +``` + +arrow-ext will hold a copy of the crate; the two copies stay identical, and each is pinned to the PHP reference by its own +tests. + +## Releasing + +Cutting a minor tag `X.Y.0` includes bumping `flow-php-ext-version` and `arrow-ext-version` in +`.nix/pkgs/php-{flow-php,arrow}-ext/package.nix` to `X.(Y+1).0-dev` in the commit right after the tag. Untagged builds +report `X.(Y+1).0-dev+.g`; the CI literal check backstops a missed bump. diff --git a/documentation/upgrading.md b/documentation/upgrading.md index f9d22250e5..f7a203b564 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -360,10 +360,10 @@ final class MyExtractor implements Extractor ### 35) `flow-php/etl` - `AdaptiveFloeEncoder` removed, Floe engines build a `FloeEncoder` -| Before | After | -|------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| -| `Flow\Floe\AdaptiveFloeEncoder` | removed - `FloeEngine::adaptive->encoder($schema)` returns `NativeFloeEncoder` when the extension supports it, else `PhpFloeEncoder` | -| `FloeEngine::encoder(): Encoder` | `FloeEngine::encoder(): Flow\Floe\FloeEncoder` (`Encoder` plus `decodeRows()` / `encodeFrames()`) | +| Before | After | +|------------------------------------------|-----------------------------------------------------------------------------------------------------------| +| `Flow\Floe\AdaptiveFloeEncoder` | removed | +| `FloeEngine::encoder(): Encoder` | `FloeEngine::encoder(): Flow\Floe\FloeEncoder` (`Encoder` plus `decodeRows()` / `encodeFrames()`) | ### 36) `flow-php/etl` - `UnionDefinition` and `union_schema()` removed @@ -419,7 +419,7 @@ The same applies to map values and structure elements. | `type_time()->cast(new DateTimeImmutable('10:00+05:00'))` = `05:00:00` | `10:00:00` - the value's wall clock | | Excel date cells in the host zone | UTC wall clock | | `new DateTimeDefinition('at', true)` | `new DateTimeDefinition('at', type_datetime(), true)` or `datetime_schema('at', nullable: true, zone: 'Europe/Warsaw')` | -| a `flow_php` extension older than this release | ignored - the PHP engine runs; a current extension with an older `flow-php/etl` keeps that library's behaviour | +| a `flow_php` extension older than this release | Composer refuses it (`conflict`) - see 67) | ### 41) `flow-php/parquet` - `Converter::isFor()` replaced by `static Converter::forColumn()`, `Int32DateTimeConverter` removed @@ -676,6 +676,39 @@ Project with `from_parquet(..., columns: [...])`. Change a type after reading, e | a codec wraps every frame body | a codec wraps each buffer of a BATCH frame behind an i64 uncompressed length (`-1` = stored raw); the directory stays plaintext | | a null in a NOT NULL column refused by the Floe writer (`SchemaMismatchException`) | refused by `Rows::fromColumns()` / `withColumns()` with the same exception and message, whatever the sink | | an XML/HTML value that cannot be converted to or from its string while building a column throws `FloeException` | throws `Flow\ETL\Exception\InvalidArgumentException`, same message | +### 67) `flow-php/flow-php-ext`, `flow-php/etl`, `flow-php/etl-adapter-csv` - the extension is the column backend + +| Before | After | +|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| +| `Flow\Floe\RustFloeEncoderNative`, `Flow\ETL\Row\RustRowHydratorNative` | removed | +| - | `flow_php` registers `Flow\ETL\Column\{Backend, Column, ColumnBuilder, DefaultBackend, NativeColumn, NativeColumnBuilder}` | +| any `flow_php` installs beside `flow-php/etl` | Composer refuses `ext-flow_php` < 0.45 (`conflict`); forced past it: `Class "Flow\ETL\Column\DefaultBackend" not found` | +| untagged builds report `0.44.1+65.g…` | `0.45.0-dev+65.g…` (next minor, pre-release) | +| `Backend` has `builder`, `constant`, `decode` | also `adopt(Definition, Column): Column` and `allocatedBytes(): int`; custom backends implement both | +| `Consumption` / `analyze()` / telemetry memory = `memory_get_usage()` | plus the configured backend's `allocatedBytes()` (native columns are not bound by `memory_limit`) | +| `new Consumption()` | `new Consumption(Backend)` | +| `new TelemetryContext(Logger, Tracer, Meter, TelemetryOptions)` | `new TelemetryContext(Backend, Logger, Tracer, Meter, TelemetryOptions)` | +| `new KWayMerge(References, int)` | `new KWayMerge(References, Backend, int)` | +| `new Joiner(Expression, Join, int)` | `new Joiner(Expression, Join, Backend, int)` | +| `AggregatedGroups::flush(int)` | `flush(int, FlowContext)` | +| `CountingProcessor::rows(int)` | `rows(int, Backend)` | +| `BucketingConfigBuilder::build(Path)`, `SortAlgorithmBuilder`, `GroupByAlgorithmBuilder`, `JoinAlgorithmBuilder`, `RepartitionAlgorithmBuilder` and their implementations `build(Path)` | `build(Path, Backend)` - custom algorithm builders implement the new signature | +| `new FilesystemBuckets(Filesystem, Path, int)` | `new FilesystemBuckets(Filesystem, Path, Backend, int)` (required) | +| sort merges, joins, group-by, `count()`, spilled bucket reads and partition filters build with `DefaultBackend` or `PhpBackend` | the configured backend | +| `Rows` rebuilds (`of`, the `concat` mixed lane, `matchTo` null fills, `unserialize()`), `Rows::join()`, `Rows::joinCross()` build with `PhpBackend` | `DefaultBackend`: native columns with the extension loaded, even under a configured `PhpBackend`, and `Consumption` does not count them | +| a CSV read with the extension and a configured `PhpBackend` | PHP columns (`Backend::adopt()`) | +| a native string/list column past 2 GiB of offsets | `OffsetOverflow` at `concat()` / `appendMany()`, as at `encode()` | + +### 68) `flow-php/etl`, adapters - `RawRowValues` removed, CSV sources yield batches + +| Before | After | +|---------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------| +| `RawRowValues`; `SchemaSampler`, `SniffsColumnTypes`, `SchemaInferrer::infer()/sniff()`, `ColumnTypes::observe()` over it | plain `array` rows | +| `CSVOpenSource::records(): Generator` | `Generator>` | +| - | `CSVOpenSource::batches(Schema, int, Backend): Generator` | +| `CSVFileReader::batches(SourceFile, int): Generator>` returning the header | `batches(SourceFile, Schema, int, Backend): Generator`, no return value | +| `RustCSVReaderNative::next(): list` | `list>` | +| - | `RustCSVReaderNative::nextColumns(Schema, int): ?Rows` | --- ## Upgrading from 0.43.x to 0.44.x diff --git a/src/adapter/etl-adapter-csv/composer.json b/src/adapter/etl-adapter-csv/composer.json index 190efa72d6..7750290e3f 100644 --- a/src/adapter/etl-adapter-csv/composer.json +++ b/src/adapter/etl-adapter-csv/composer.json @@ -15,6 +15,9 @@ "flow-php/etl": "self.version", "symfony/polyfill-mbstring": "^1.33" }, + "conflict": { + "ext-flow_php": "<0.45" + }, "config": { "optimize-autoloader": true, "sort-packages": true diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php index b44e96259c..89ad51cd55 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php @@ -4,8 +4,6 @@ namespace Flow\ETL\Adapter\CSV; -use Flow\ETL\Row\RawRowValues; - use function array_combine; use function array_keys; use function array_map; @@ -40,7 +38,7 @@ public function __construct( /** * @param list $batch * - * @return list + * @return list> */ public function decode(array $batch): array { @@ -60,10 +58,7 @@ public function decode(array $batch): array $this->headers = $this->generateAutoHeaders(count($fields)); } - $maps[] = new RawRowValues(array_combine( - $this->headers, - $this->rowNormalizer->normalize($fields, count($this->headers)), - )); + $maps[] = array_combine($this->headers, $this->rowNormalizer->normalize($fields, count($this->headers))); } return $maps; 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 1efea7a15a..9b0c1bdcde 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 @@ -19,9 +19,7 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -35,8 +33,7 @@ use Generator; use function array_diff; -use function array_keys; -use function array_map; +use function array_unique; use function array_values; use function iterator_to_array; use function sprintf; @@ -132,39 +129,27 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi foreach ($sources as $source) { // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body $constants = $fileColumns->forFile($source, $schema); - $columns = null; - $batches = $reader->batches($source, $batchSize); + // before any batch is built: a cell the inferred types refuse must not hide a file whose columns diverge + if ($this->schema === null && !$this->inference->unionByName) { + $columns = array_values(array_diff(array_unique($reader->columns($source)), $tail)); - foreach ($batches as $rawBatch) { - if ($columns === null) { - $columns = array_map( - strval(...), - array_values(array_diff(array_keys($rawBatch[0]->values), $tail)), + if ( + $columns !== [] + && (array_diff($columns, $expected) !== [] || array_diff($expected, $columns) !== []) + ) { + throw InferredSchemaException::columnsDiverge( + $source->uri(), + $reader->header()->source ?? '', + $base, + $columns, + $this->inference, ); - - if ( - $this->schema === null - && !$this->inference->unionByName - && (array_diff($columns, $expected) !== [] || array_diff($expected, $columns) !== []) - ) { - throw InferredSchemaException::columnsDiverge( - $source->uri(), - $reader->header()->source ?? '', - $base, - $columns, - $this->inference, - ); - } } + } - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $rawBatch)) - ->finish(), - $schema, - $backend, - ); + foreach ($reader->batches($source, $body, $batchSize, $backend) as $batch) { + $rows = $constants->fillRows($batch, $schema, $backend); $yielded += $rows->count(); @@ -178,23 +163,6 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi return; } } - - if ($columns === null && $this->schema === null && !$this->inference->unionByName) { - $columns = array_values(array_diff($batches->getReturn(), $tail)); - - if ( - $columns !== [] - && (array_diff($columns, $expected) !== [] || array_diff($expected, $columns) !== []) - ) { - throw InferredSchemaException::columnsDiverge( - $source->uri(), - $reader->header()->source ?? '', - $base, - $columns, - $this->inference, - ); - } - } } } diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php index 306788cff5..d76a06a250 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php @@ -4,13 +4,13 @@ namespace Flow\ETL\Adapter\CSV; +use Flow\ETL\Column\Backend; use Flow\ETL\Extractor\SourceFile; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Rows; +use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaSampler; use Generator; -use function count; - final readonly class CSVFileReader implements SchemaSampler { /** @@ -22,33 +22,18 @@ public function __construct( ) {} /** - * Abandoning the generator closes the source. Returns the header the read resolved, so a source without data rows - * needs no second open to name its columns. + * Abandoning the generator closes the source. * * @param int<1, max> $batchSize * - * @return Generator, mixed, list> + * @return Generator */ - public function batches(SourceFile $source, int $batchSize): Generator + public function batches(SourceFile $source, Schema $schema, int $batchSize, Backend $backend): Generator { $open = $this->opener->open($source); - $batch = []; try { - foreach ($open->records() as $values) { - $batch[] = $values; - - if (count($batch) >= $batchSize) { - yield $batch; - $batch = []; - } - } - - if ($batch !== []) { - yield $batch; - } - - return $open->headers(); + yield from $open->batches($schema, $batchSize, $backend); } finally { $open->close(); } diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php index 719409c244..593d89554e 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\CSV; use Flow\ETL\Extractor\SourceFile; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SniffsColumnTypes; @@ -14,7 +13,7 @@ use IteratorAggregate; /** - * @implements IteratorAggregate + * @implements IteratorAggregate> */ final class CSVFileSample implements IteratorAggregate, SniffsColumnTypes { @@ -28,7 +27,7 @@ public function __construct( /** * The source is opened on the first advance; abandoning the generator closes it. * - * @return Generator + * @return Generator> */ public function getIterator(): Generator { diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php index 874bdc825f..e8420fe20d 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php @@ -4,7 +4,10 @@ namespace Flow\ETL\Adapter\CSV; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Column\Backend; +use Flow\ETL\Exception\SchemaMismatchException; +use Flow\ETL\Rows; +use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\Types\Type\TypeNarrower; @@ -35,6 +38,18 @@ public function producedRows(): int; */ public function columns(): array; + /** + * Batches of exactly $batchSize rows (the last may be shorter), keyed and ordered by $schema; row indexes in + * refusals are relative to the batch. This instance is consumed afterwards. + * + * @param int<1, max> $batchSize + * + * @throws SchemaMismatchException + * + * @return Generator + */ + public function batches(Schema $schema, int $batchSize, Backend $backend): Generator; + /** * The header records() resolved; [] before it ran or for a 0-byte source. * @@ -45,7 +60,7 @@ public function headers(): array; /** * This instance is consumed afterwards. * - * @return Generator + * @return Generator> */ public function records(): Generator; diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php index 119275b59d..3a26316592 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php @@ -4,6 +4,9 @@ namespace Flow\ETL\Adapter\CSV; +use Flow\ETL\Column\Backend; +use Flow\ETL\Rows; +use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferrer; @@ -74,6 +77,37 @@ public static function isSupported(): bool return extension_loaded('flow_php') && class_exists(RustCSVReaderNative::class, false); } + public function batches(Schema $schema, int $batchSize, Backend $backend): Generator + { + // every batch goes through the configured backend, which keeps its own columns and copies the native ones + $adopted = function (Rows $batch) use ($schema, $backend): Rows { + $columns = []; + $native = $batch->columns(); + + foreach ($schema->definitions() as $name => $definition) { + $columns[$name] = $backend->adopt($definition, $native[$name]); + } + + $this->producedRows += count($batch); + + return Rows::fromColumns($schema, $columns, $batch->count()); + }; + + foreach ($this->stream->iterate($this->chunkSize) as $chunk) { + $this->reader->feed($chunk); + + while (($batch = $this->reader->nextColumns($schema, $batchSize)) !== null) { + yield $adopted($batch); + } + } + + $this->reader->finish(); + + while (($batch = $this->reader->nextColumns($schema, $batchSize)) !== null) { + yield $adopted($batch); + } + } + public function close(): void { $this->stream->close(); diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php index 2e1b373701..65ecd866ad 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php @@ -4,7 +4,9 @@ namespace Flow\ETL\Adapter\CSV; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Column\Backend; +use Flow\ETL\Rows\RowsBuilder; +use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferrer; @@ -12,6 +14,8 @@ use Flow\Types\Type\TypeNarrower; use Generator; +use function count; + final class PhpCSVOpenSource implements CSVOpenSource { /** @@ -30,6 +34,28 @@ public function __construct( private readonly CSVLineReader $lineReader, ) {} + public function batches(Schema $schema, int $batchSize, Backend $backend): Generator + { + $rows = []; + + foreach ($this->records() as $values) { + $rows[] = $values; + + if (count($rows) >= $batchSize) { + yield (new RowsBuilder($schema, $backend)) + ->appendRows($rows) + ->finish(); + $rows = []; + } + } + + if ($rows !== []) { + yield (new RowsBuilder($schema, $backend)) + ->appendRows($rows) + ->finish(); + } + } + public function close(): void { $this->stream->close(); @@ -60,7 +86,7 @@ public function headers(): array * CSVLineReader::readLines() already joins a quoted multi-line record, so never re-split or re-join here. * This instance is consumed afterwards. * - * @return Generator + * @return Generator> */ public function records(): Generator { diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php index 9f4fbfca54..abce114d30 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php @@ -15,8 +15,10 @@ use Flow\ETL\Adapter\CSV\NativeCSVOpenSource; use Flow\ETL\Adapter\CSV\PhpCSVOpenSource; use Flow\ETL\Adapter\CSV\RustCSVReaderNative; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Extractor\SourceFile; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; @@ -39,6 +41,7 @@ use function Flow\Filesystem\DSL\path; use function Flow\Filesystem\DSL\path_real; use function range; +use function serialize; use function sprintf; use function str_ends_with; use function str_repeat; @@ -150,7 +153,13 @@ public static function openPhp( Filesystem $filesystem = new NativeLocalFilesystem(), CSVReadOptions $options = new CSVReadOptions(), ): PhpCSVOpenSource { - $stream = $filesystem->readFrom(path_real(self::path($fixture))); + return self::openPhpStream($filesystem->readFrom(path_real(self::path($fixture))), $options); + } + + public static function openPhpStream( + SourceStream $stream, + CSVReadOptions $options = new CSVReadOptions(), + ): PhpCSVOpenSource { $dialect = self::dialect($stream, $options); return new PhpCSVOpenSource( @@ -173,16 +182,78 @@ public static function openPhp( } /** - * Every record's values and metadata, for strict comparison across paths - consumes the source. + * An open stream over `$content`. + */ + public static function content(string $content): SourceStream + { + return self::memory($content)->readFrom(self::memorySource()->path); + } + + /** + * Every batch's rows, or the refusal that stopped them - consumes and closes the source. + * + * @param int<1, max> $batchSize + * + * @return list>|SchemaMismatchException + */ + public static function batches( + CSVOpenSource $open, + Schema $schema, + int $batchSize, + Backend $backend = new PhpBackend(), + ): array|SchemaMismatchException { + $batches = []; + + try { + foreach ($open->batches($schema, $batchSize, $backend) as $batch) { + $batches[] = $batch->toArray(); + } + + return $batches; + } catch (SchemaMismatchException $e) { + return $e; + } finally { + $open->close(); + } + } + + /** + * `batches()` as one string: the serialized rows, or the refusal's class, message, row and previous. + * + * @param int<1, max> $batchSize + */ + public static function batchesOutcome( + CSVOpenSource $open, + Schema $schema, + int $batchSize, + Backend $backend = new PhpBackend(), + ): string { + $batches = self::batches($open, $schema, $batchSize, $backend); + + return $batches instanceof SchemaMismatchException + ? $batches::class + . ': ' + . $batches->getMessage() + . ' @' + . $batches->rowIndex + . ' <- ' + . $batches->cause::class + . ': ' + . $batches->cause->getMessage() + : serialize($batches); + } + + /** + * Every record, for strict comparison across paths - consumes the source. * - * @return list, array}> + * @return list> */ public static function records(CSVOpenSource $open): array { $records = []; foreach ($open->records() as $record) { - $records[] = [$record->values, $record->metadata]; + $records[] = $record; } return $records; @@ -233,7 +304,7 @@ public static function inferPhp(SchemaInference $inference, string ...$fixtures) /** * The PHP open source's records, opened on the first advance and closed when abandoned - a SchemaSampler unit. * - * @return Generator + * @return Generator> */ public static function phpRecords(string $fixture): Generator { diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Fixtures/columns_diverge_refused/a.csv b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Fixtures/columns_diverge_refused/a.csv new file mode 100644 index 0000000000..3ff3deb87e --- /dev/null +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Fixtures/columns_diverge_refused/a.csv @@ -0,0 +1,2 @@ +id +1 diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Fixtures/columns_diverge_refused/b.csv b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Fixtures/columns_diverge_refused/b.csv new file mode 100644 index 0000000000..894a557c91 --- /dev/null +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Fixtures/columns_diverge_refused/b.csv @@ -0,0 +1,2 @@ +id,label +x,c 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 b9a4404a74..9003926a92 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 @@ -235,8 +235,8 @@ public function test_the_inferred_schema_is_memoised_across_schema_and_extract() $extractor->schema(); iterator_to_array($extractor->extract(flow_context(config()))); - static::assertSame(3, $counting->readFromCalls, 'header() + sample + read'); - static::assertSame(3, $counting->closedStreams()); + static::assertSame(4, $counting->readFromCalls, 'header() + sample + divergence check + read'); + static::assertSame(4, $counting->closedStreams()); static::assertSame(3, $counting->listCalls); } @@ -440,6 +440,18 @@ public function test_the_divergence_message_names_both_sources(): void } } + public function test_divergence_is_reported_before_a_refused_cell(): void + { + $this->expectException(InferredSchemaException::class); + $this->expectExceptionMessageMatches('/unexpected \[label\]/'); + + iterator_to_array( + from_csv(CSVFixtureContext::path('columns_diverge_refused/*.csv')) + ->inferSchema(infer_schema()->filesToSniff(1)) + ->extract(flow_context(config())), + ); + } + public function test_a_header_only_file_with_a_divergent_header_is_rejected(): void { try { diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileReaderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileReaderTest.php index 3e328337cf..06d273d3e2 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileReaderTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileReaderTest.php @@ -5,12 +5,16 @@ namespace Flow\ETL\Adapter\CSV\Tests\Integration; use Flow\ETL\Adapter\CSV\Tests\Context\CSVFixtureContext; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use PHPUnit\Framework\Attributes\TestWith; use function count; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function iterator_to_array; final class CSVFileReaderTest extends FlowTestCase @@ -19,7 +23,12 @@ public function test_batches_are_sized_and_the_tail_is_shorter(): void { $sizes = []; - foreach (CSVFixtureContext::reader()->batches(CSVFixtureContext::source('five_rows.csv'), 2) as $batch) { + foreach (CSVFixtureContext::reader()->batches( + CSVFixtureContext::source('five_rows.csv'), + schema(int_schema('id'), str_schema('name')), + 2, + new PhpBackend(), + ) as $batch) { $sizes[] = count($batch); } @@ -29,7 +38,12 @@ public function test_batches_are_sized_and_the_tail_is_shorter(): void public function test_batches_closes_its_stream_when_abandoned(): void { $counting = new CountingFilesystem(new NativeLocalFilesystem()); - $batches = CSVFixtureContext::reader($counting)->batches(CSVFixtureContext::source('five_rows.csv'), 2); + $batches = CSVFixtureContext::reader($counting)->batches( + CSVFixtureContext::source('five_rows.csv'), + schema(int_schema('id'), str_schema('name')), + 2, + new PhpBackend(), + ); $batches->current(); unset($batches); @@ -43,18 +57,18 @@ public function test_batches_never_yields_an_empty_batch(string $fixture): void { static::assertSame( [], - iterator_to_array(CSVFixtureContext::reader()->batches(CSVFixtureContext::source($fixture), 10), false), + iterator_to_array( + CSVFixtureContext::reader()->batches( + CSVFixtureContext::source($fixture), + schema(int_schema('id'), str_schema('name')), + 10, + new PhpBackend(), + ), + false, + ), ); } - public function test_batches_return_the_header_of_a_source_without_rows(): void - { - $batches = CSVFixtureContext::reader()->batches(CSVFixtureContext::source('header_only.csv'), 10); - - static::assertSame([], iterator_to_array($batches, false)); - static::assertSame(['id', 'name'], $batches->getReturn()); - } - public function test_columns_of_one_source(): void { static::assertSame( @@ -133,7 +147,7 @@ public function test_samples_walks_the_sources_in_listing_order(): void foreach (CSVFixtureContext::globReader('columns_diverge/*.csv')->samples(10) as $unit) { foreach ($unit as $values) { - $first[] = $values->values; + $first[] = $values; break; } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileSampleTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileSampleTest.php index 6208c55566..541ac8625b 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileSampleTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVFileSampleTest.php @@ -35,7 +35,7 @@ public function test_iterating_yields_every_row_with_the_full_key_set(): void static::assertCount(3, $records); foreach ($records as $record) { - static::assertSame(['id', 'name', 'v'], array_keys($record->values)); + static::assertSame(['id', 'name', 'v'], array_keys($record)); } } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php index 6a6cd992c7..2888e1ed6f 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php @@ -9,22 +9,32 @@ use Flow\ETL\Adapter\CSV\RustCSVReaderNative; use Flow\ETL\Adapter\CSV\Tests\Context\CSVFixtureContext; use Flow\ETL\Adapter\CSV\Tests\Double\LengthCapturingSourceStream; +use Flow\ETL\Exception\ColumnMismatchException; +use Flow\ETL\Exception\SchemaMismatchException; +use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\InferredTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferrer; use Flow\ETL\Schema\Inference\TypeFloor; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Types\Type\Native\String\StringTypeNarrower; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProviderExternal; use PHPUnit\Framework\Attributes\TestWith; use function array_keys; use function array_map; use function class_exists; +use function count; use function file_get_contents; use function Flow\ETL\DSL\infer_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\path; use function implode; use function iterator_to_array; @@ -136,7 +146,7 @@ public function test_records_yields_every_row_with_the_full_key_set(): void static::assertCount(3, $records); foreach ($records as $record) { - static::assertSame(['id', 'name', 'v'], array_keys($record->values)); + static::assertSame(['id', 'name', 'v'], array_keys($record)); } } finally { $open->close(); @@ -155,7 +165,7 @@ public function test_records_yields_one_logical_record_per_iteration(): void $records = iterator_to_array($open->records(), false); static::assertNotSame([], $records); - static::assertStringContainsString("\n", implode('', array_map('strval', $records[0]->values))); + static::assertStringContainsString("\n", implode('', array_map('strval', $records[0]))); } finally { $open->close(); } @@ -402,4 +412,270 @@ public function test_php_and_native_paths_agree_on_bytes_per_row(string $fixture $native->close(); } } + + public function test_batches_are_batch_size_rows(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + $batches = CSVFixtureContext::batches( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content("id,name\n1,a\n2,b\n3,c\n4,d\n5,e\n")), + schema(int_schema('id'), str_schema('name')), + 2, + ); + + static::assertIsArray($batches); + static::assertSame([2, 2, 1], array_map(count(...), $batches)); + } + + public function test_batches_skip_undeclared_header_columns(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + static::assertSame( + [[['id' => 1, 'name' => 'a']]], + CSVFixtureContext::batches( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content("id,name,extra\n1,a,x\n")), + schema(int_schema('id'), str_schema('name')), + 10, + ), + ); + } + + public function test_batches_pad_a_missing_nullable_column(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + static::assertSame( + [[['id' => 1, 'name' => null]]], + CSVFixtureContext::batches( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content("id\n1\n")), + schema(int_schema('id'), str_schema('name', nullable: true)), + 10, + ), + ); + } + + public function test_batches_refuse_a_missing_not_null_column(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + $refusal = CSVFixtureContext::batches( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content("id\n1\n")), + schema(int_schema('id'), str_schema('name')), + 10, + ); + + static::assertInstanceOf(SchemaMismatchException::class, $refusal); + static::assertSame( + (new SchemaMismatchException(0, ColumnMismatchException::missingColumn(str_schema('name'))))->getMessage(), + $refusal->getMessage(), + ); + static::assertSame(0, $refusal->rowIndex); + } + + public function test_batches_refused_value_wins_over_absence(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + $refusal = CSVFixtureContext::batches( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content("id\n1\nx\n")), + schema(int_schema('id'), str_schema('name')), + 10, + ); + + static::assertInstanceOf(SchemaMismatchException::class, $refusal); + static::assertSame( + (new SchemaMismatchException(1, ColumnMismatchException::valueDoesNotMatch( + int_schema('id'), + 'x', + )))->getMessage(), + $refusal->getMessage(), + ); + static::assertSame(1, $refusal->rowIndex); + } + + public function test_batches_refusal_tie_goes_to_the_first_definition(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + $refusal = CSVFixtureContext::batches( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content("a,b\nx,y\n")), + schema(int_schema('b'), int_schema('a')), + 10, + ); + + static::assertInstanceOf(SchemaMismatchException::class, $refusal); + static::assertSame( + (new SchemaMismatchException(0, ColumnMismatchException::valueDoesNotMatch( + int_schema('b'), + 'y', + )))->getMessage(), + $refusal->getMessage(), + ); + static::assertSame(0, $refusal->rowIndex); + } + + public function test_batches_refuse_an_empty_to_null_null_under_not_null(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + $refusal = CSVFixtureContext::batches( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content("id,name\n1,a\n2,\n")), + schema(int_schema('id'), str_schema('name')), + 10, + ); + + static::assertInstanceOf(SchemaMismatchException::class, $refusal); + static::assertSame( + (new SchemaMismatchException(1, ColumnMismatchException::valueDoesNotMatch( + str_schema('name'), + null, + )))->getMessage(), + $refusal->getMessage(), + ); + static::assertSame(1, $refusal->rowIndex); + } + + public function test_batches_of_a_header_only_source_are_empty(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + static::assertSame( + [], + CSVFixtureContext::batches( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content("id\n")), + schema(int_schema('id'), str_schema('absent')), + 10, + ), + ); + } + + /** + * @return Generator + */ + public static function batch_parity_cases(): Generator + { + foreach (CSVFixtureContext::fixtures() as $label => [$fixture]) { + // the first 1000 records (orders_flow.csv has 10000, one per line) in about five batches: batch + // boundaries without the cost of typing every record twice + $content = implode("\n", array_slice( + explode("\n", (string) file_get_contents(CSVFixtureContext::path($fixture))), + 0, + 1001, + )); + + yield $label => [ + $content, + CSVFixtureContext::inferPhp(new SchemaInference(), $fixture), + max(2, intdiv(substr_count($content, "\n"), 5)), + ]; + } + + $idName = schema(int_schema('id'), str_schema('name')); + + yield 'missing not null column' => ["id\n1\n", $idName, 2]; + yield 'refused value over absence' => ["id\n1\nx\n", $idName, 2]; + yield 'refusal tie' => ["a,b\nx,y\n", schema(int_schema('b'), int_schema('a')), 2]; + yield 'empty to null under not null' => ["id,name\n1,a\n2,\n", $idName, 2]; + yield 'duplicate header' => ["id,name,name\n1,a,b\n2,c,d\n", $idName, 2]; + yield 'ragged row' => [ + "id,name\n1\n2,b,extra\n", + schema(int_schema('id'), str_schema('name', nullable: true)), + 2, + ]; + yield 'numeric header' => ["1,2\na,3\n", schema(str_schema('1'), int_schema('2')), 2]; + yield 'refusal in the second batch' => ["id,name\n1,a\n2,b\n3,c\nx,d\n", $idName, 2]; + } + + /** + * @param positive-int $batchSize + */ + #[DataProvider('batch_parity_cases')] + public function test_native_and_php_batches_are_identical(string $content, Schema $schema, int $batchSize): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + static::assertSame( + CSVFixtureContext::batchesOutcome( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content($content)), + $schema, + $batchSize, + ), + CSVFixtureContext::batchesOutcome( + CSVFixtureContext::openNativeStream(CSVFixtureContext::content($content)), + $schema, + $batchSize, + ), + ); + } + + /** + * @param positive-int $chunkSize + */ + #[TestWith([1, "id,note\n1,\"a\nb\"\n2,\"c\nd\"\n3,e\n"])] + #[TestWith([7, "id,note\n1,\"a\nb\"\n2,\"c\nd\"\n3,e\n"])] + #[TestWith([4096, "id,note\n1,\"a\nb\"\n2,\"c\nd\"\n3,e\n"])] + #[TestWith([7, "id,note\n1,\"a\nb\"\nx,\"a record that crosses\nthe chunk boundary\"\n"])] + public function test_batches_are_identical_across_chunk_sizes(int $chunkSize, string $content): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + $schema = schema(int_schema('id'), str_schema('note')); + + static::assertSame( + CSVFixtureContext::batchesOutcome( + CSVFixtureContext::openNativeStream( + new LengthCapturingSourceStream($content, path('s3://bucket/a.csv')), + ), + $schema, + 2, + ), + CSVFixtureContext::batchesOutcome( + CSVFixtureContext::openNativeStream( + new LengthCapturingSourceStream($content, path('s3://bucket/a.csv')), + (new CSVReadOptions())->withCharactersReadInLine($chunkSize), + ), + $schema, + 2, + ), + ); + } + + public function test_batches_hand_every_column_to_the_backend(): void + { + if (!NativeCSVOpenSource::isSupported()) { + static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + } + + $backend = new SpyBackend(); + + CSVFixtureContext::batches( + CSVFixtureContext::openNative('five_rows.csv'), + schema(int_schema('id'), str_schema('name')), + 2, + $backend, + ); + + static::assertSame(2 * 3, $backend->adopts()); + } } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/PhpCSVOpenSourceTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/PhpCSVOpenSourceTest.php index 2426f3dc43..8977e08c12 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/PhpCSVOpenSourceTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/PhpCSVOpenSourceTest.php @@ -6,12 +6,18 @@ use Flow\ETL\Adapter\CSV\CSVReadOptions; use Flow\ETL\Adapter\CSV\Tests\Context\CSVFixtureContext; +use Flow\ETL\Exception\ColumnMismatchException; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use function array_keys; use function array_map; +use function count; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function implode; use function iterator_to_array; @@ -94,7 +100,7 @@ public function test_records_yields_every_row_with_the_full_key_set(): void static::assertCount(3, $records); foreach ($records as $record) { - static::assertSame(['id', 'name', 'v'], array_keys($record->values)); + static::assertSame(['id', 'name', 'v'], array_keys($record)); } } finally { $open->close(); @@ -109,7 +115,7 @@ public function test_records_yields_one_logical_record_per_iteration(): void $records = iterator_to_array($open->records(), false); static::assertNotSame([], $records); - static::assertStringContainsString("\n", implode('', array_map('strval', $records[0]->values))); + static::assertStringContainsString("\n", implode('', array_map('strval', $records[0]))); } finally { $open->close(); } @@ -128,4 +134,125 @@ public function test_produced_rows_and_bytes_exclude_the_header(): void $open->close(); } } + + public function test_batches_are_batch_size_rows(): void + { + $batches = CSVFixtureContext::batches( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content("id,name\n1,a\n2,b\n3,c\n4,d\n5,e\n")), + schema(int_schema('id'), str_schema('name')), + 2, + ); + + static::assertIsArray($batches); + static::assertSame([2, 2, 1], array_map(count(...), $batches)); + } + + public function test_batches_skip_undeclared_header_columns(): void + { + static::assertSame( + [[['id' => 1, 'name' => 'a']]], + CSVFixtureContext::batches( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content("id,name,extra\n1,a,x\n")), + schema(int_schema('id'), str_schema('name')), + 10, + ), + ); + } + + public function test_batches_pad_a_missing_nullable_column(): void + { + static::assertSame( + [[['id' => 1, 'name' => null]]], + CSVFixtureContext::batches( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content("id\n1\n")), + schema(int_schema('id'), str_schema('name', nullable: true)), + 10, + ), + ); + } + + public function test_batches_refuse_a_missing_not_null_column(): void + { + $refusal = CSVFixtureContext::batches( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content("id\n1\n")), + schema(int_schema('id'), str_schema('name')), + 10, + ); + + static::assertInstanceOf(SchemaMismatchException::class, $refusal); + static::assertSame( + (new SchemaMismatchException(0, ColumnMismatchException::missingColumn(str_schema('name'))))->getMessage(), + $refusal->getMessage(), + ); + static::assertSame(0, $refusal->rowIndex); + } + + public function test_batches_refused_value_wins_over_absence(): void + { + $refusal = CSVFixtureContext::batches( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content("id\n1\nx\n")), + schema(int_schema('id'), str_schema('name')), + 10, + ); + + static::assertInstanceOf(SchemaMismatchException::class, $refusal); + static::assertSame( + (new SchemaMismatchException(1, ColumnMismatchException::valueDoesNotMatch( + int_schema('id'), + 'x', + )))->getMessage(), + $refusal->getMessage(), + ); + static::assertSame(1, $refusal->rowIndex); + } + + public function test_batches_refusal_tie_goes_to_the_first_definition(): void + { + $refusal = CSVFixtureContext::batches( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content("a,b\nx,y\n")), + schema(int_schema('b'), int_schema('a')), + 10, + ); + + static::assertInstanceOf(SchemaMismatchException::class, $refusal); + static::assertSame( + (new SchemaMismatchException(0, ColumnMismatchException::valueDoesNotMatch( + int_schema('b'), + 'y', + )))->getMessage(), + $refusal->getMessage(), + ); + static::assertSame(0, $refusal->rowIndex); + } + + public function test_batches_refuse_an_empty_to_null_null_under_not_null(): void + { + $refusal = CSVFixtureContext::batches( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content("id,name\n1,a\n2,\n")), + schema(int_schema('id'), str_schema('name')), + 10, + ); + + static::assertInstanceOf(SchemaMismatchException::class, $refusal); + static::assertSame( + (new SchemaMismatchException(1, ColumnMismatchException::valueDoesNotMatch( + str_schema('name'), + null, + )))->getMessage(), + $refusal->getMessage(), + ); + static::assertSame(1, $refusal->rowIndex); + } + + public function test_batches_of_a_header_only_source_are_empty(): void + { + static::assertSame( + [], + CSVFixtureContext::batches( + CSVFixtureContext::openPhpStream(CSVFixtureContext::content("id\n")), + schema(int_schema('id'), str_schema('absent')), + 10, + ), + ); + } } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVDecoderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVDecoderTest.php index 90de6bb463..53231f09f8 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVDecoderTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVDecoderTest.php @@ -14,14 +14,14 @@ public function test_decode_captures_headers_from_the_first_row_and_emits_no_row $decoder = new CSVDecoder(); static::assertSame([], $decoder->decode(['id,name'])); - static::assertSame(['id' => '1', 'name' => 'Norbert'], $decoder->decode(['1,Norbert'])[0]->values); + static::assertSame(['id' => '1', 'name' => 'Norbert'], $decoder->decode(['1,Norbert'])[0]); } public function test_decode_generates_auto_headers_when_header_is_disabled(): void { static::assertSame( ['e00' => '1', 'e01' => 'Norbert'], - (new CSVDecoder(withHeader: false))->decode(['1,Norbert'])[0]->values, + (new CSVDecoder(withHeader: false))->decode(['1,Norbert'])[0], ); } @@ -29,49 +29,43 @@ public function test_decode_keeps_empty_fields_when_empty_to_null_is_disabled(): { static::assertSame( ['id' => '1', 'name' => ''], - (new CSVDecoder(emptyToNull: false))->decode(['id,name', '1,'])[0]->values, + (new CSVDecoder(emptyToNull: false))->decode(['id,name', '1,'])[0], ); } public function test_decode_maps_fields_to_headers(): void { - static::assertSame( - ['id' => '1', 'name' => 'Norbert'], - (new CSVDecoder())->decode(['id,name', '1,Norbert'])[0]->values, - ); + static::assertSame(['id' => '1', 'name' => 'Norbert'], (new CSVDecoder())->decode(['id,name', '1,Norbert'])[0]); } public function test_decode_pads_short_rows_with_null(): void { - static::assertSame(['id' => '1', 'name' => null], (new CSVDecoder())->decode(['id,name', '1'])[0]->values); + static::assertSame(['id' => '1', 'name' => null], (new CSVDecoder())->decode(['id,name', '1'])[0]); } public function test_decode_truncates_rows_longer_than_the_headers(): void { static::assertSame( ['id' => '1', 'name' => 'Norbert'], - (new CSVDecoder())->decode(['id,name', '1,Norbert,extra'])[0]->values, + (new CSVDecoder())->decode(['id,name', '1,Norbert,extra'])[0], ); } public function test_decode_turns_empty_fields_into_null_by_default(): void { - static::assertSame(['id' => '1', 'name' => null], (new CSVDecoder())->decode(['id,name', '1,'])[0]->values); + static::assertSame(['id' => '1', 'name' => null], (new CSVDecoder())->decode(['id,name', '1,'])[0]); } public function test_decoding_a_blank_line_yields_a_single_null_field(): void { - static::assertSame( - ['e00' => null], - (new CSVDecoder(withHeader: false, emptyToNull: false))->decode([''])[0]->values, - ); + static::assertSame(['e00' => null], (new CSVDecoder(withHeader: false, emptyToNull: false))->decode([''])[0]); } public function test_decoding_a_line_with_a_custom_separator_enclosure_and_escape_yields_strings(): void { static::assertSame( ['id' => '1', 'name' => 'a;b'], - (new CSVDecoder(separator: ';', enclosure: "'", escape: '|'))->decode(['id;name', "1;'a;b'"])[0]->values, + (new CSVDecoder(separator: ';', enclosure: "'", escape: '|'))->decode(['id;name', "1;'a;b'"])[0], ); } @@ -79,7 +73,7 @@ public function test_decoding_a_line_with_empty_quoted_fields_yields_empty_strin { static::assertSame( ['id' => '', 'name' => ''], - (new CSVDecoder(emptyToNull: false))->decode(['id,name', '"",""'])[0]->values, + (new CSVDecoder(emptyToNull: false))->decode(['id,name', '"",""'])[0], ); } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVExtractorTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVExtractorTest.php index ce5c248d65..47f52924f7 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVExtractorTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVExtractorTest.php @@ -85,7 +85,7 @@ public function test_a_header_only_file_declares_zero_rows_exactly(): void static::assertEquals(Cardinality::exact(8), $extractor->statistics()->size); } - public function test_a_header_only_file_is_opened_once_by_extract(): void + public function test_extract_opens_an_inferred_file_for_its_header_and_its_rows(): void { $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); $extractor = from_csv(CSVFixtureContext::path('header_only.csv'), filesystem: $filesystem); @@ -93,7 +93,7 @@ public function test_a_header_only_file_is_opened_once_by_extract(): void $opened = $filesystem->readFromCalls; static::assertSame([], iterator_to_array($extractor->extract(flow_context()), false)); - static::assertSame($opened + 1, $filesystem->readFromCalls); + static::assertSame($opened + 2, $filesystem->readFromCalls); } public function test_a_member_without_a_size_makes_both_facts_unknown(): void @@ -205,6 +205,6 @@ public function test_extract_builds_through_the_config_backend(): void false, ); - static::assertGreaterThanOrEqual(1, $backend->builders()); + static::assertGreaterThanOrEqual(1, $backend->builders() + $backend->adopts()); } } diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php index 0200e0db04..f89b0937c3 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php @@ -4,8 +4,6 @@ namespace Flow\ETL\Adapter\Excel; -use Flow\ETL\Row\RawRowValues; - use function array_map; use function array_values; use function count; @@ -27,7 +25,7 @@ public function __construct( /** * @param list> $batch * - * @return list + * @return list> */ public function decode(array $batch): array { @@ -52,7 +50,7 @@ public function decode(array $batch): array $values[$name] = $this->convertEmptyToNull && '' === $cell ? null : $cell; } - $decoded[] = new RawRowValues($values); + $decoded[] = $values; } return $decoded; 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 3a263ee74a..6a6847d4be 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 @@ -19,7 +19,6 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; @@ -35,7 +34,6 @@ use Throwable; use function array_diff; -use function array_map; use function array_values; use function count; use function iterator_to_array; @@ -210,7 +208,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $rows = $constants->fillRows( (new RowsBuilder($body, $backend)) - ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $batch)) + ->appendRows($batch) ->finish(), $schema, $backend, @@ -236,7 +234,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $rows = $constants->fillRows( (new RowsBuilder($body, $backend)) - ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $batch)) + ->appendRows($batch) ->finish(), $schema, $backend, diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheet.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheet.php index d05c47bea5..e7775f2125 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheet.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheet.php @@ -5,14 +5,13 @@ namespace Flow\ETL\Adapter\Excel; use Flow\ETL\Adapter\Excel\Sheet\OpenSheet; -use Flow\ETL\Row\RawRowValues; use Flow\Filesystem\Path; use Generator; final class WorkbookSheet { /** - * @var list + * @var list> */ private array $buffered = []; @@ -58,7 +57,7 @@ public function columns(): array * rows() that follows replays the sample and parses on from where the sample stopped, instead of parsing the * sample a second time. Closing the sheet stays with its owner. * - * @return Generator + * @return Generator> */ public function sample(): Generator { @@ -83,7 +82,7 @@ public function sample(): Generator } /** - * @return Generator + * @return Generator> */ public function rows(): Generator { diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheetSample.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheetSample.php index e176188f72..4eaa823e00 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheetSample.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSheetSample.php @@ -4,12 +4,11 @@ namespace Flow\ETL\Adapter\Excel; -use Flow\ETL\Row\RawRowValues; use Generator; use IteratorAggregate; /** - * @implements IteratorAggregate + * @implements IteratorAggregate> */ final class WorkbookSheetSample implements IteratorAggregate { @@ -21,14 +20,14 @@ final class WorkbookSheetSample implements IteratorAggregate private bool $wholeSheet = false; /** - * @param Generator $sheetRows + * @param Generator> $sheetRows */ public function __construct( private readonly Generator $sheetRows, ) {} /** - * @return Generator + * @return Generator> */ public function getIterator(): Generator { diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/WorkbookReaderTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/WorkbookReaderTest.php index 17668b048a..7aa5461142 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/WorkbookReaderTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/WorkbookReaderTest.php @@ -24,8 +24,8 @@ public function test_options_reach_the_sheet(): void ); static::assertCount(3, $rows); - static::assertSame(['e00', 'e01', 'e02'], array_keys($rows[0]->values)); - static::assertSame('', $rows[0]->values['e01']); + static::assertSame(['e00', 'e01', 'e02'], array_keys($rows[0])); + static::assertSame('', $rows[0]['e01']); } public function test_sheet_is_a_new_object_every_time(): void diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/WorkbookSheetTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/WorkbookSheetTest.php index 5b2b1585f9..4bfd777869 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/WorkbookSheetTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/WorkbookSheetTest.php @@ -166,7 +166,7 @@ public function test_rows_re_emit_the_row_the_header_was_resolved_from(): void ); static::assertCount(11, $rows); - static::assertSame(['e00' => 'id', 'e01' => 'name', 'e02' => 'email'], $rows[0]->values); + static::assertSame(['e00' => 'id', 'e01' => 'name', 'e02' => 'email'], $rows[0]); } public function test_rows_resolve_the_columns_without_a_columns_call_first(): void @@ -174,7 +174,7 @@ public function test_rows_resolve_the_columns_without_a_columns_call_first(): vo $rows = iterator_to_array(ExcelFixtureContext::sheet('fixture.xlsx')->rows(), false); static::assertCount(10, $rows); - static::assertSame(['id', 'name', 'email'], array_keys($rows[0]->values)); + static::assertSame(['id', 'name', 'email'], array_keys($rows[0])); } public function test_an_unknown_sheet_name_names_the_sheet_it_looked_for(): void diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php index 7964f84fdd..8317e50140 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php @@ -14,14 +14,14 @@ public function test_decode_captures_headers_from_the_first_row_and_emits_no_row $decoder = new ExcelDecoder(); static::assertSame([], $decoder->decode([['id', 'name']])); - static::assertSame(['id' => 1, 'name' => 'Norbert'], $decoder->decode([[1, 'Norbert']])[0]->values); + static::assertSame(['id' => 1, 'name' => 'Norbert'], $decoder->decode([[1, 'Norbert']])[0]); } public function test_decode_generates_auto_headers_when_header_is_disabled(): void { static::assertSame( ['e00' => 1, 'e01' => 'Norbert'], - (new ExcelDecoder(withHeader: false))->decode([[1, 'Norbert']])[0]->values, + (new ExcelDecoder(withHeader: false))->decode([[1, 'Norbert']])[0], ); } @@ -58,7 +58,7 @@ public function test_decode_keeps_empty_cells_when_convert_empty_to_null_is_disa { static::assertSame( ['id' => 1, 'name' => ''], - (new ExcelDecoder(convertEmptyToNull: false))->decode([['id', 'name'], [1, '']])[0]->values, + (new ExcelDecoder(convertEmptyToNull: false))->decode([['id', 'name'], [1, '']])[0], ); } @@ -66,15 +66,12 @@ public function test_decode_maps_cells_to_headers(): void { static::assertSame( ['id' => 1, 'name' => 'Norbert'], - (new ExcelDecoder())->decode([['id', 'name'], [1, 'Norbert']])[0]->values, + (new ExcelDecoder())->decode([['id', 'name'], [1, 'Norbert']])[0], ); } public function test_decode_turns_empty_cells_into_null_by_default(): void { - static::assertSame( - ['id' => 1, 'name' => null], - (new ExcelDecoder())->decode([['id', 'name'], [1, '']])[0]->values, - ); + static::assertSame(['id' => 1, 'name' => null], (new ExcelDecoder())->decode([['id', 'name'], [1, '']])[0]); } } diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/WorkbookSheetSampleTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/WorkbookSheetSampleTest.php index 45d87eb0a2..7cf74b0991 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/WorkbookSheetSampleTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/WorkbookSheetSampleTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\Excel\Tests\Unit; use Flow\ETL\Adapter\Excel\WorkbookSheetSample; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Tests\FlowTestCase; use function iterator_to_array; @@ -16,8 +15,8 @@ public function test_a_sample_stopped_early_is_not_whole(): void { $sample = new WorkbookSheetSample( (static function () { - yield new RawRowValues(['id' => 1]); - yield new RawRowValues(['id' => 2]); + yield ['id' => 1]; + yield ['id' => 2]; })(), ); @@ -33,8 +32,8 @@ public function test_a_sample_read_to_the_end_is_whole(): void { $sample = new WorkbookSheetSample( (static function () { - yield new RawRowValues(['id' => 1]); - yield new RawRowValues(['id' => 2]); + yield ['id' => 1]; + yield ['id' => 2]; })(), ); @@ -48,7 +47,7 @@ public function test_nothing_is_counted_before_iteration(): void { $sample = new WorkbookSheetSample( (static function () { - yield new RawRowValues(['id' => 1]); + yield ['id' => 1]; })(), ); diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php index 1db2cf5fc4..2622644769 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\GoogleSheet; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Row\RawRowValues; use function array_combine; use function array_keys; @@ -32,7 +31,7 @@ public function __construct( /** * @param list> $batch * - * @return list + * @return list> */ public function decode(array $batch): array { @@ -84,10 +83,10 @@ public function decode(array $batch): array } } - $maps[] = new RawRowValues(array_combine( + $maps[] = array_combine( $this->withHeader ? $this->headers : $this->generateAutoHeaders(count($rowData)), $rowData, - )); + ); } return $maps; 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 b10f57838e..6a73897499 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 @@ -17,7 +17,6 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; @@ -119,10 +118,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator foreach ($batches as $batch) { if (!$checked) { - $columns = array_map( - static fn(int|string $name): string => (string) $name, - array_keys($batch[0]->values), - ); + $columns = array_map(static fn(int|string $name): string => (string) $name, array_keys($batch[0])); // a row that carries no columns is not a divergence: withHeader(false) decodes a leading blank // row to one, and the names come from the row after it @@ -146,20 +142,19 @@ public function extract(FlowContext $context, ?int $limit = null): Generator if ($this->addMetadataColumns) { $batch = array_map( - function (RawRowValues $rowValues): RawRowValues { + function (array $values): array { // assigned, never unpacked: a numeric column name is an int array key and ... renumbers it - $values = $rowValues->values; $values['_spread_sheet_id'] = $this->spreadsheetId; $values['_sheet_name'] = $this->columnRange->sheetName; - return new RawRowValues($values); + return $values; }, $batch, ); } $rows = (new RowsBuilder($schema, $backend)) - ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $batch)) + ->appendRows($batch) ->finish(); $yielded += $rows->count(); diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php index 4270123f1f..49eaa1a3b9 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Adapter\GoogleSheet; -use Flow\ETL\Row\RawRowValues; use Generator; use Google\Service\Sheets; @@ -22,7 +21,7 @@ public function __construct( ) {} /** - * @return Generator> + * @return Generator>> */ public function batches(int $rowsPerPage, int $batchSize): Generator { diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetSample.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetSample.php index 77a7380ed4..29adb379d6 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetSample.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetSample.php @@ -4,13 +4,11 @@ namespace Flow\ETL\Adapter\GoogleSheet; -use Flow\ETL\Row\RawRowValues; - final readonly class GoogleSheetSample { /** * @param list $names the header (or generated names) - known even when no data row follows - * @param list $rows + * @param list> $rows * @param bool $wholeSheet the range reached the last row of the grid, so $rows IS the sheet and a read can be * served from it instead of fetching the same rows again * @param int $gridRowCount the rows the grid allocates - an upper bound on the rows it holds diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetSampler.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetSampler.php index 362ad86c77..1812aadbc9 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetSampler.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetSampler.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Adapter\GoogleSheet; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema\Inference\SchemaSampler; use Generator; @@ -28,7 +27,7 @@ public function __construct( * * @param int<1, max> $batchSize * - * @return null|Generator> + * @return null|Generator>> */ public function batches(int $batchSize): ?Generator { @@ -77,7 +76,7 @@ public function sample(): GoogleSheetSample * $rowBudget is deliberately unused: the budget sized the single range when this sampler was constructed, * and sample() is memoised, so advancing further cannot fetch more. * - * @return Generator> + * @return Generator>> */ public function samples(int $rowBudget): iterable { diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php index 5005fdf6fa..9a38cb4e37 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php @@ -8,8 +8,6 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; -use function array_map; - final class GoogleSheetDecoderTest extends FlowTestCase { public function test_decodes_rows_with_first_row_as_headers(): void @@ -27,7 +25,7 @@ public function test_decodes_rows_with_first_row_as_headers(): void ['id' => '1', 'name' => 'Norbert'], ['id' => '2', 'name' => 'Tomek'], ], - array_map(static fn($rowValues): array => $rowValues->values, $decoded), + $decoded, ); } @@ -41,10 +39,7 @@ public function test_skips_empty_rows_before_headers(): void ['1', 'Norbert'], ]); - static::assertSame( - [['id' => '1', 'name' => 'Norbert']], - array_map(static fn($rowValues): array => $rowValues->values, $decoded), - ); + static::assertSame([['id' => '1', 'name' => 'Norbert']], $decoded); } public function test_keeps_headers_between_decode_calls(): void @@ -53,10 +48,7 @@ public function test_keeps_headers_between_decode_calls(): void $decoder->decode([['id', 'name'], ['1', 'Norbert']]); - static::assertSame( - [['id' => '2', 'name' => 'Tomek']], - array_map(static fn($rowValues): array => $rowValues->values, $decoder->decode([['2', 'Tomek']])), - ); + static::assertSame([['id' => '2', 'name' => 'Tomek']], $decoder->decode([['2', 'Tomek']])); } public function test_pads_shorter_rows_with_nulls(): void @@ -68,10 +60,7 @@ public function test_pads_shorter_rows_with_nulls(): void ['1'], ]); - static::assertSame( - [['id' => '1', 'name' => null]], - array_map(static fn($rowValues): array => $rowValues->values, $decoded), - ); + static::assertSame([['id' => '1', 'name' => null]], $decoded); } public function test_drops_extra_columns(): void @@ -83,10 +72,7 @@ public function test_drops_extra_columns(): void ['1', 'Norbert', 'extra'], ]); - static::assertSame( - [['id' => '1', 'name' => 'Norbert']], - array_map(static fn($rowValues): array => $rowValues->values, $decoded), - ); + static::assertSame([['id' => '1', 'name' => 'Norbert']], $decoded); } public function test_throws_on_extra_columns_when_drop_is_disabled(): void @@ -116,7 +102,7 @@ public function test_generates_auto_headers_without_header_row(): void ['e00' => '1', 'e01' => 'Norbert'], ['e00' => '2', 'e01' => 'Tomek'], ], - array_map(static fn($rowValues): array => $rowValues->values, $decoded), + $decoded, ); } @@ -124,36 +110,28 @@ public function test_empty_cells_become_null_by_default(): void { $decoder = new GoogleSheetDecoder(); - static::assertSame( - [['a' => null, 'b' => 'x']], - array_map(static fn($rowValues): array => $rowValues->values, $decoder->decode([['a', 'b'], ['', 'x']])), - ); + static::assertSame([['a' => null, 'b' => 'x']], $decoder->decode([['a', 'b'], ['', 'x']])); } public function test_empty_cells_stay_strings_when_asked(): void { $decoder = new GoogleSheetDecoder(emptyToNull: false); - static::assertSame( - [['a' => '', 'b' => 'x']], - array_map(static fn($rowValues): array => $rowValues->values, $decoder->decode([['a', 'b'], ['', 'x']])), - ); + static::assertSame([['a' => '', 'b' => 'x']], $decoder->decode([['a', 'b'], ['', 'x']])); } public function test_omitted_trailing_cells_are_null_regardless_of_empty_to_null(): void { static::assertSame( [['a' => 'x', 'b' => null]], - array_map(static fn($rowValues): array => $rowValues->values, (new GoogleSheetDecoder())->decode([ + (new GoogleSheetDecoder())->decode([ ['a', 'b'], ['x'], - ])), + ]), ); static::assertSame( [['a' => 'x', 'b' => null]], - array_map(static fn($rowValues): array => $rowValues->values, (new GoogleSheetDecoder( - emptyToNull: false, - ))->decode([['a', 'b'], ['x']])), + (new GoogleSheetDecoder(emptyToNull: false))->decode([['a', 'b'], ['x']]), ); } @@ -205,6 +183,6 @@ public function test_two_header_cells_with_the_same_name_collapse_the_row_to_one $decoded = $decoder->decode([[1, true], ['x', 'y']]); static::assertSame(['1', '1'], $decoder->headers()); - static::assertSame(['1' => 'y'], $decoded[0]->values); + static::assertSame(['1' => 'y'], $decoded[0]); } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReadOptionsTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReadOptionsTest.php index e98e45ff6d..e691c07cb7 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReadOptionsTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReadOptionsTest.php @@ -11,8 +11,6 @@ use Flow\Types\Type\Logical\InstanceOfTypeNarrower; use Flow\Types\Type\Native\String\StringTypeNarrower; -use function array_map; - final class GoogleSheetReadOptionsTest extends FlowTestCase { public function test_defaults(): void @@ -76,10 +74,10 @@ public function test_decoder_carries_the_empty_to_null_flag(): void { static::assertSame( [['a' => '']], - array_map(static fn($rowValues): array => $rowValues->values, (new GoogleSheetReadOptions()) + (new GoogleSheetReadOptions()) ->withEmptyToNull(false) ->decoder() - ->decode([['a'], ['']])), + ->decode([['a'], ['']]), ); } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReaderTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReaderTest.php index 5e3857bf5b..53588826b5 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReaderTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetReaderTest.php @@ -116,7 +116,7 @@ public function test_sample_decodes_names_and_rows_through_its_own_decoder(): vo ))->sample(2); static::assertSame(['id', 'note'], $sample->names); - static::assertSame(['id' => '1', 'note' => null], $sample->rows[0]->values); + static::assertSame(['id' => '1', 'note' => null], $sample->rows[0]); static::assertCount(2, $sample->rows); } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetSampleTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetSampleTest.php index 3cabc1ae69..d9384889bb 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetSampleTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetSampleTest.php @@ -5,17 +5,16 @@ namespace Flow\ETL\Adapter\GoogleSheet\Tests\Unit; use Flow\ETL\Adapter\GoogleSheet\GoogleSheetSample; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Tests\FlowTestCase; final class GoogleSheetSampleTest extends FlowTestCase { public function test_carries_names_and_rows(): void { - $sample = new GoogleSheetSample(['a'], [new RawRowValues(['a' => 1])], wholeSheet: true, gridRowCount: 1000); + $sample = new GoogleSheetSample(['a'], [['a' => 1]], wholeSheet: true, gridRowCount: 1000); static::assertSame(['a'], $sample->names); - static::assertSame([['a' => 1]], [$sample->rows[0]->values]); + static::assertSame([['a' => 1]], [$sample->rows[0]]); static::assertTrue($sample->wholeSheet); static::assertSame(1000, $sample->gridRowCount); } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetSamplerTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetSamplerTest.php index 32780a6304..21388653bf 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetSamplerTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetSamplerTest.php @@ -8,7 +8,6 @@ use Flow\ETL\Adapter\GoogleSheet\Tests\Mother\SheetValuesMother; use Flow\ETL\Tests\FlowTestCase; -use function array_map; use function iterator_to_array; final class GoogleSheetSamplerTest extends FlowTestCase @@ -34,10 +33,7 @@ public function test_samples_unit_holds_the_rows(): void $rows = iterator_to_array(GoogleSheetFixtureContext::sampler($values, 2)->samples(2)->current(), false); - static::assertSame( - [['id' => '1'], ['id' => '2']], - array_map(static fn($rowValues): array => $rowValues->values, $rows), - ); + static::assertSame([['id' => '1'], ['id' => '2']], $rows); static::assertSame('sheet!A1:B3', $values->getCalls[0][1]); } 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 6a4748c335..0e23bdbf34 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 @@ -18,7 +18,6 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; @@ -33,7 +32,6 @@ use Flow\Types\Type\Logical\InstanceOfTypeNarrower; use Generator; -use function array_map; use function iterator_to_array; use function sprintf; @@ -137,7 +135,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi foreach ($reader->batches($source, $batchSize) as $rawBatch) { $rows = $constants->fillRows( (new RowsBuilder($body, $backend)) - ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $rawBatch)) + ->appendRows($rawBatch) ->finish(), $schema, $backend, diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php index 89cfbbf2c9..42b8ec827e 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; use Flow\ETL\Extractor\SourceFile; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema\Inference\SchemaSampler; use Flow\Filesystem\Filesystem; use Flow\Filesystem\SourceStream; @@ -57,7 +56,7 @@ public function __construct( * * @param int<1, max> $batchSize * - * @return Generator> + * @return Generator>> */ public function batches(SourceFile $source, int $batchSize): Generator { @@ -157,7 +156,7 @@ public function lineItems(SourceStream $stream, JsonReadBytes $read = new JsonRe * The pointer wrap and the empty-record skip live here and nowhere else, so the sample and the read see the * same rows. * - * @return Generator + * @return Generator> */ public function sample(SourceFile $source, JsonReadBytes $read = new JsonReadBytes()): Generator { @@ -180,7 +179,7 @@ public function sample(SourceFile $source, JsonReadBytes $read = new JsonReadByt continue; } - yield new RawRowValues($row); + yield $row; } } finally { $stream->close(); diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileSample.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileSample.php index 817cda9469..76e628a2c2 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileSample.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileSample.php @@ -5,12 +5,11 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; use Flow\ETL\Extractor\SourceFile; -use Flow\ETL\Row\RawRowValues; use Generator; use IteratorAggregate; /** - * @implements IteratorAggregate + * @implements IteratorAggregate> */ final class JsonFileSample implements IteratorAggregate { @@ -24,7 +23,7 @@ public function __construct( /** * Records what it read when the consumer stops or the file ends, whichever comes first. * - * @return Generator + * @return Generator> */ public function getIterator(): Generator { 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 58f83b7242..96c11dcb86 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 @@ -18,7 +18,6 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; @@ -33,7 +32,6 @@ use Flow\Types\Type\Logical\InstanceOfTypeNarrower; use Generator; -use function array_map; use function iterator_to_array; use function sprintf; @@ -137,7 +135,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi foreach ($reader->batches($source, $batchSize) as $rawBatch) { $rows = $constants->fillRows( (new RowsBuilder($body, $backend)) - ->appendRows(array_map(static fn(RawRowValues $r): array => $r->values, $rawBatch)) + ->appendRows($rawBatch) ->finish(), $schema, $backend, diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php index 443fef7467..3220d7ee11 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php @@ -7,7 +7,6 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFileSample; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -94,7 +93,7 @@ public function test_a_document_is_read_across_chunk_boundaries(): void static::assertCount(247, $rows); static::assertSame(iterator_to_array(Items::fromFile($source->path->path(), [ 'decoder' => new ExtJsonDecoder(true), - ]), false), array_map(static fn(RawRowValues $values): array => $values->values, $rows)); + ]), false), array_map(static fn(array $values): array => $values, $rows)); } #[TestWith([JsonFormat::Document, 'empty_record.json'])] @@ -105,10 +104,7 @@ public function test_an_empty_record_is_skipped(JsonFormat $format, string $fixt $rows = iterator_to_array($reader->sample(JsonFixtureContext::source($fixture)), false); - static::assertSame( - [['id' => 1], ['id' => 2]], - array_map(static fn(RawRowValues $v): array => $v->values, $rows), - ); + static::assertSame([['id' => 1], ['id' => 2]], array_map(static fn(array $v): array => $v, $rows)); } public function test_a_zero_byte_document_yields_nothing(): void @@ -183,7 +179,7 @@ public function test_the_pointer_selects_the_rows( $reader = JsonFixtureContext::reader($format, pointer: $pointer); $rows = iterator_to_array($reader->sample(JsonFixtureContext::source($fixture)), false); - $values = array_map(static fn(RawRowValues $v): mixed => $v->values[$expectedKey], $rows); + $values = array_map(static fn(array $v): mixed => $v[$expectedKey], $rows); static::assertCount($expectedRows, $rows); static::assertSame($expectedHead, array_slice($values, 0, count($expectedHead))); @@ -204,8 +200,8 @@ public function test_the_pointer_can_name_the_column( static::assertCount($expectedRows, $rows); foreach ($rows as $row) { - static::assertSame([$pointer], array_keys($row->values)); - static::assertIsArray($row->values[$pointer]); + static::assertSame([$pointer], array_keys($row)); + static::assertIsArray($row[$pointer]); } } @@ -221,7 +217,7 @@ public function test_sample_closes_its_stream_when_abandoned(JsonFormat $format, unset($rows); static::assertNotNull($first); - static::assertSame(['id' => 1], $first->values); + static::assertSame(['id' => 1], $first); static::assertSame(1, $counting->readFromCalls); static::assertSame(1, $counting->closedStreams()); @@ -235,7 +231,7 @@ public function test_sample_yields_every_row_of_a_source(JsonFormat $format, str $rows = iterator_to_array($reader->sample(JsonFixtureContext::source($fixture)), false); - static::assertSame([1, 2, 3, 4, 5], array_map(static fn(RawRowValues $v): mixed => $v->values['id'], $rows)); + static::assertSame([1, 2, 3, 4, 5], array_map(static fn(array $v): mixed => $v['id'], $rows)); } #[TestWith([JsonFormat::Document, 'five_rows.json'])] @@ -259,7 +255,7 @@ public function test_a_glob_reader_samples_every_listed_file_in_listing_order(): foreach ($reader->samples(100) as $sample) { foreach ($sample as $values) { - $ids[] = $values->values['id']; + $ids[] = $values['id']; } } @@ -288,7 +284,7 @@ public function test_samples_yields_one_unopened_sample_per_source_in_listing_or static::assertSame(0, $beforeAdvance, 'samples() opens nothing until a sample is iterated'); static::assertSame(1, $afterAdvance, 'advancing the first sample opens exactly the first source'); static::assertNotNull($first); - static::assertSame(['id' => 1], $first->values); + static::assertSame(['id' => 1], $first); } #[TestWith(['blank_line.jsonl'])] @@ -315,7 +311,7 @@ public function test_a_whitespace_only_line_is_skipped_under_a_pointer(): void $rows = iterator_to_array($reader->sample(JsonFixtureContext::source('pointer_blank_line.jsonl')), false); - static::assertSame([1, 2], array_map(static fn(RawRowValues $v): mixed => $v->values['a'], $rows)); + static::assertSame([1, 2], array_map(static fn(array $v): mixed => $v['a'], $rows)); } public function test_a_nul_only_line_is_refused(): void diff --git a/src/core/etl/composer.json b/src/core/etl/composer.json index 8ad3b01d4f..cf1598b099 100644 --- a/src/core/etl/composer.json +++ b/src/core/etl/composer.json @@ -21,6 +21,9 @@ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", "symfony/string": "^6.4 || ^7.4 || ^8.0" }, + "conflict": { + "ext-flow_php": "<0.45" + }, "suggest": { "ext-apcu": "Allows using ApcuCache as a pipeline cache implementation", "ext-bcmath": "BCMath extension for PHP for more precise calculations" diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php b/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php index 31b559b388..986ecbfb89 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Bucketing\Storage; use Flow\ETL\Bucketing\BucketsStorage; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Hash\NativePHPHash; use Flow\ETL\Rows; @@ -34,6 +35,7 @@ final class FilesystemBuckets implements BucketsStorage public function __construct( private readonly Filesystem $filesystem, Path $cacheDir, + Backend $backend, private readonly int $batchSize = 1000, ) { // @mago-ignore analysis:impossible-condition,redundant-comparison @@ -42,7 +44,7 @@ public function __construct( } $this->cacheDir = $cacheDir->suffix('/flow-php-buckets/'); - $this->reader = new FloeReader($this->filesystem); + $this->reader = new FloeReader($this->filesystem, backend: $backend); } /** diff --git a/src/core/etl/src/Flow/ETL/Column/Backend.php b/src/core/etl/src/Flow/ETL/Column/Backend.php index 8cb947c07b..20b2f02a13 100644 --- a/src/core/etl/src/Flow/ETL/Column/Backend.php +++ b/src/core/etl/src/Flow/ETL/Column/Backend.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Column; +use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Schema\Definition; interface Backend @@ -27,4 +28,20 @@ public function constant(Definition $definition, mixed $value, int $count): Colu * @param list $buffers the column's subtree buffers as Column::encode() produced them ('' = omitted validity) */ public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column; + + /** + * The same values in this backend's storage: $column itself when this backend owns it, otherwise one copy through + * builder($definition)->appendTake(). For producers that build columns outside the configured backend. + * + * @param Definition $definition + * + * @throws ColumnMismatchException a null under NOT NULL on the copy path (an own column passes through unchecked; + * Rows::fromColumns checks NOT NULL) + */ + public function adopt(Definition $definition, Column $column): Column; + + /** + * Bytes this backend holds outside PHP's memory manager (invisible to memory_get_usage() and memory_limit). + */ + public function allocatedBytes(): int; } diff --git a/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php b/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php index a75a75bb10..7c1e2e6b1a 100644 --- a/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php +++ b/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php @@ -6,6 +6,12 @@ use Flow\ETL\Schema\Definition; +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} + final readonly class DefaultBackend implements Backend { private PhpBackend $php; @@ -29,4 +35,14 @@ public function decode(Definition $definition, array $buffers, int $count, int $ { return $this->php->decode($definition, $buffers, $count, $nullCount); } + + public function adopt(Definition $definition, Column $column): Column + { + return $this->php->adopt($definition, $column); + } + + public function allocatedBytes(): int + { + return $this->php->allocatedBytes(); + } } diff --git a/src/core/etl/src/Flow/ETL/Column/PhpBackend.php b/src/core/etl/src/Flow/ETL/Column/PhpBackend.php index 13e2a74a20..c5be05a249 100644 --- a/src/core/etl/src/Flow/ETL/Column/PhpBackend.php +++ b/src/core/etl/src/Flow/ETL/Column/PhpBackend.php @@ -8,13 +8,18 @@ use Flow\ETL\Column\Php\CastingColumnBuilder; use Flow\ETL\Column\Php\ColumnDecoder; use Flow\ETL\Column\Php\ConstantColumn; +use Flow\ETL\Column\Php\ListColumn; +use Flow\ETL\Column\Php\MapColumn; use Flow\ETL\Column\Php\PhysicalBuilderFor; use Flow\ETL\Column\Php\PhysicalFor; +use Flow\ETL\Column\Php\ScalarColumn; +use Flow\ETL\Column\Php\StructColumn; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Schema\Definition; use Flow\ETL\Schema\Definition\NullDefinition; +use function range; use function sprintf; final readonly class PhpBackend implements Backend @@ -63,4 +68,30 @@ public function decode(Definition $definition, array $buffers, int $count, int $ return $column; } + + public function adopt(Definition $definition, Column $column): Column + { + if ( + $column instanceof ScalarColumn + || $column instanceof ConstantColumn + || $column instanceof ListColumn + || $column instanceof MapColumn + || $column instanceof StructColumn + ) { + return $column; + } + + $builder = $this->builder($definition); + + if ($column->count() > 0) { + $builder->appendTake($column, range(0, $column->count() - 1)); + } + + return $builder->finish(); + } + + public function allocatedBytes(): int + { + return 0; + } } diff --git a/src/core/etl/src/Flow/ETL/Config/Bucketing/BucketingConfigBuilder.php b/src/core/etl/src/Flow/ETL/Config/Bucketing/BucketingConfigBuilder.php index b1df735e32..500d2aa490 100644 --- a/src/core/etl/src/Flow/ETL/Config/Bucketing/BucketingConfigBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Bucketing/BucketingConfigBuilder.php @@ -6,6 +6,7 @@ use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Bucketing\Storage\FilesystemBuckets; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; @@ -49,12 +50,13 @@ public function batchSize(int $batchSize): self return $this; } - public function build(Path $spillRoot): BucketingConfig + public function build(Path $spillRoot, Backend $backend): BucketingConfig { return new BucketingConfig( $this->storage ?? new FilesystemBuckets( new NativeLocalFilesystem(), $spillRoot->suffix($this->spillDirectory), + $backend, $this->batchSize, ), $this->bucketsCount, diff --git a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php index 2571467a1a..77d1c90692 100644 --- a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php @@ -125,12 +125,15 @@ public function build(): Config $optimizer, $executor, $cacheConfig, - ($this->sort ?? new ExternalSortBuilder())->build($cacheConfig->localFilesystemCacheDir), + ($this->sort ?? new ExternalSortBuilder())->build($cacheConfig->localFilesystemCacheDir, $this->backend), $this->analyze, $this->telemetryConfig ?? TelemetryConfig::default($this->getClock()), - ($this->groupBy ?? new HashGroupByBuilder())->build($cacheConfig->localFilesystemCacheDir), - ($this->join ?? new HashJoinBuilder())->build($cacheConfig->localFilesystemCacheDir), - ($this->repartition ?? new HashRepartitionBuilder())->build($cacheConfig->localFilesystemCacheDir), + ($this->groupBy ?? new HashGroupByBuilder())->build($cacheConfig->localFilesystemCacheDir, $this->backend), + ($this->join ?? new HashJoinBuilder())->build($cacheConfig->localFilesystemCacheDir, $this->backend), + ($this->repartition ?? new HashRepartitionBuilder())->build( + $cacheConfig->localFilesystemCacheDir, + $this->backend, + ), randomValueGenerator: $this->randomValueGenerator, backend: $this->backend, ); diff --git a/src/core/etl/src/Flow/ETL/Config/Grouping/GroupByAlgorithmBuilder.php b/src/core/etl/src/Flow/ETL/Config/Grouping/GroupByAlgorithmBuilder.php index 0b7453a799..8bcc145f44 100644 --- a/src/core/etl/src/Flow/ETL/Config/Grouping/GroupByAlgorithmBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Grouping/GroupByAlgorithmBuilder.php @@ -4,9 +4,10 @@ namespace Flow\ETL\Config\Grouping; +use Flow\ETL\Column\Backend; use Flow\Filesystem\Path; interface GroupByAlgorithmBuilder { - public function build(Path $spillRoot): HashGroupByConfig; + public function build(Path $spillRoot, Backend $backend): HashGroupByConfig; } diff --git a/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByBuilder.php b/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByBuilder.php index 193f180cef..f308caf003 100644 --- a/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByBuilder.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Config\Grouping; use Flow\ETL\Bucketing\BucketsStorage; +use Flow\ETL\Column\Backend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; use Flow\Filesystem\Path; @@ -27,9 +28,9 @@ public function batchSize(int $batchSize): self return $this; } - public function build(Path $spillRoot): HashGroupByConfig + public function build(Path $spillRoot, Backend $backend): HashGroupByConfig { - return new HashGroupByConfig($this->bucketing->build($spillRoot)); + return new HashGroupByConfig($this->bucketing->build($spillRoot, $backend)); } /** diff --git a/src/core/etl/src/Flow/ETL/Config/Join/HashJoinBuilder.php b/src/core/etl/src/Flow/ETL/Config/Join/HashJoinBuilder.php index a8e4f238c5..e009e6f8d6 100644 --- a/src/core/etl/src/Flow/ETL/Config/Join/HashJoinBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Join/HashJoinBuilder.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Config\Join; use Flow\ETL\Bucketing\BucketsStorage; +use Flow\ETL\Column\Backend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; use Flow\Filesystem\Path; @@ -27,9 +28,9 @@ public function batchSize(int $batchSize): self return $this; } - public function build(Path $spillRoot): HashJoinConfig + public function build(Path $spillRoot, Backend $backend): HashJoinConfig { - return new HashJoinConfig($this->bucketing->build($spillRoot)); + return new HashJoinConfig($this->bucketing->build($spillRoot, $backend)); } /** diff --git a/src/core/etl/src/Flow/ETL/Config/Join/JoinAlgorithmBuilder.php b/src/core/etl/src/Flow/ETL/Config/Join/JoinAlgorithmBuilder.php index 84d653d62d..66e79241ca 100644 --- a/src/core/etl/src/Flow/ETL/Config/Join/JoinAlgorithmBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Join/JoinAlgorithmBuilder.php @@ -4,9 +4,10 @@ namespace Flow\ETL\Config\Join; +use Flow\ETL\Column\Backend; use Flow\Filesystem\Path; interface JoinAlgorithmBuilder { - public function build(Path $spillRoot): HashJoinConfig; + public function build(Path $spillRoot, Backend $backend): HashJoinConfig; } diff --git a/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionBuilder.php b/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionBuilder.php index 3639363cea..a46f2073fb 100644 --- a/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionBuilder.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Config\Repartition; use Flow\ETL\Bucketing\BucketsStorage; +use Flow\ETL\Column\Backend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; use Flow\Filesystem\Path; @@ -27,9 +28,9 @@ public function batchSize(int $batchSize): self return $this; } - public function build(Path $spillRoot): HashRepartitionConfig + public function build(Path $spillRoot, Backend $backend): HashRepartitionConfig { - return new HashRepartitionConfig($this->bucketing->build($spillRoot)); + return new HashRepartitionConfig($this->bucketing->build($spillRoot, $backend)); } /** diff --git a/src/core/etl/src/Flow/ETL/Config/Repartition/RepartitionAlgorithmBuilder.php b/src/core/etl/src/Flow/ETL/Config/Repartition/RepartitionAlgorithmBuilder.php index e9f8364ac6..c4d185a9fe 100644 --- a/src/core/etl/src/Flow/ETL/Config/Repartition/RepartitionAlgorithmBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Repartition/RepartitionAlgorithmBuilder.php @@ -4,9 +4,10 @@ namespace Flow\ETL\Config\Repartition; +use Flow\ETL\Column\Backend; use Flow\Filesystem\Path; interface RepartitionAlgorithmBuilder { - public function build(Path $spillRoot): HashRepartitionConfig; + public function build(Path $spillRoot, Backend $backend): HashRepartitionConfig; } diff --git a/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortBuilder.php b/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortBuilder.php index 63b3d4a5b3..b6fed07d07 100644 --- a/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortBuilder.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Config\Sort; use Flow\ETL\Bucketing\BucketsStorage; +use Flow\ETL\Column\Backend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Filesystem\Path; @@ -35,9 +36,13 @@ public function batchSize(int $batchSize): self return $this; } - public function build(Path $spillRoot): ExternalSortConfig + public function build(Path $spillRoot, Backend $backend): ExternalSortConfig { - return new ExternalSortConfig($this->bucketing->build($spillRoot), $this->mergeStorage, $this->runSize); + return new ExternalSortConfig( + $this->bucketing->build($spillRoot, $backend), + $this->mergeStorage, + $this->runSize, + ); } /** diff --git a/src/core/etl/src/Flow/ETL/Config/Sort/MemorySortBuilder.php b/src/core/etl/src/Flow/ETL/Config/Sort/MemorySortBuilder.php index 33c8469131..47704f62dc 100644 --- a/src/core/etl/src/Flow/ETL/Config/Sort/MemorySortBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Sort/MemorySortBuilder.php @@ -4,11 +4,12 @@ namespace Flow\ETL\Config\Sort; +use Flow\ETL\Column\Backend; use Flow\Filesystem\Path; final class MemorySortBuilder implements SortAlgorithmBuilder { - public function build(Path $spillRoot): MemorySortConfig + public function build(Path $spillRoot, Backend $backend): MemorySortConfig { return new MemorySortConfig(); } diff --git a/src/core/etl/src/Flow/ETL/Config/Sort/SortAlgorithmBuilder.php b/src/core/etl/src/Flow/ETL/Config/Sort/SortAlgorithmBuilder.php index abd8a96484..e6d72e80f2 100644 --- a/src/core/etl/src/Flow/ETL/Config/Sort/SortAlgorithmBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Sort/SortAlgorithmBuilder.php @@ -4,9 +4,10 @@ namespace Flow\ETL\Config\Sort; +use Flow\ETL\Column\Backend; use Flow\Filesystem\Path; interface SortAlgorithmBuilder { - public function build(Path $spillRoot): MemorySortConfig|ExternalSortConfig; + public function build(Path $spillRoot, Backend $backend): MemorySortConfig|ExternalSortConfig; } 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 34dc7e072b..915656131d 100644 --- a/src/core/etl/src/Flow/ETL/Config/Telemetry/TelemetryContext.php +++ b/src/core/etl/src/Flow/ETL/Config/Telemetry/TelemetryContext.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Config\Telemetry; +use Flow\ETL\Column\Backend; use Flow\ETL\Config\Sort\ExternalSortConfig; use Flow\ETL\Config\Sort\MemorySortConfig; use Flow\ETL\Dataset\Memory\Consumption; @@ -60,12 +61,13 @@ final class TelemetryContext private readonly SpanStack $transformationSpans; public function __construct( + private readonly Backend $backend, private readonly Logger $logger, private readonly Tracer $tracer, private readonly Meter $meter, public readonly TelemetryOptions $options, ) { - $this->memory = new Consumption(); + $this->memory = new Consumption($this->backend); $this->loadingSpans = new SpanStack(); $this->transformationSpans = new SpanStack(); } @@ -141,7 +143,7 @@ public function dataFrameCompleted(FlowContext $context, array $attributes = []) $this->dataFrameExecutionTime = null; $this->totalRowsProcessed = 0; $this->dataFrameSpan = null; - $this->memory = new Consumption(); + $this->memory = new Consumption($this->backend); } /** @@ -200,7 +202,7 @@ public function dataFrameFailed(FlowContext $context, Throwable $exception, arra $this->dataFrameExecutionTime = null; $this->totalRowsProcessed = 0; $this->dataFrameSpan = null; - $this->memory = new Consumption(); + $this->memory = new Consumption($this->backend); } public function dataFrameStarted(FlowContext $context): void diff --git a/src/core/etl/src/Flow/ETL/Dataset/Memory/Consumption.php b/src/core/etl/src/Flow/ETL/Dataset/Memory/Consumption.php index 8c2a3b8136..88d1cb0e6d 100644 --- a/src/core/etl/src/Flow/ETL/Dataset/Memory/Consumption.php +++ b/src/core/etl/src/Flow/ETL/Dataset/Memory/Consumption.php @@ -4,6 +4,8 @@ namespace Flow\ETL\Dataset\Memory; +use Flow\ETL\Column\Backend; + use function memory_get_usage; final class Consumption @@ -15,16 +17,17 @@ final class Consumption private Unit $min; public function __construct( + private readonly Backend $backend, private readonly bool $realMemory = true, ) { - $this->initial = Unit::fromBytes(memory_get_usage($this->realMemory)); + $this->initial = Unit::fromBytes(memory_get_usage($this->realMemory) + $this->backend->allocatedBytes()); $this->min = $this->initial; $this->max = $this->initial; } public function capture(): Unit { - $current = Unit::fromBytes(memory_get_usage($this->realMemory)); + $current = Unit::fromBytes(memory_get_usage($this->realMemory) + $this->backend->allocatedBytes()); if ($current->isGreaterThan($this->max)) { $this->max = $current; diff --git a/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php b/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php index ea9d8ad556..8ac3d1f8d8 100644 --- a/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php +++ b/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php @@ -61,7 +61,7 @@ public function __construct( } gc_collect_cycles(); - $this->memory = new Consumption(); + $this->memory = new Consumption($this->context->backend()); $this->startedAt = $this->context->config->clock()->now(); $this->startTime = HighResolutionTime::now(); } diff --git a/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php b/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php index 035ff4b353..8c442232a9 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php +++ b/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Extractor; use Flow\ETL\Row\ColumnName; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema\Inference\SchemaSampler; use Generator; @@ -25,7 +24,7 @@ public function __construct( * $rowBudget is never rationed: the inner generator is lazy and SchemaInferrer stops advancing it * when the budget is spent. * - * @return iterable> + * @return iterable>> */ public function samples(int $rowBudget): iterable { @@ -38,7 +37,7 @@ public function samples(int $rowBudget): iterable * The same ColumnName normalisation array_to_rows() applies, so the fold's names are the * batch builder's names. * - * @return Generator + * @return Generator> */ public function values(): Generator { @@ -52,7 +51,7 @@ public function values(): Generator $values[$columnName->of($key)] = $value; } - yield new RawRowValues($values); + yield $values; } } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/SpilledRows.php b/src/core/etl/src/Flow/ETL/Extractor/SpilledRows.php index d5a0caa454..4a5c9bba22 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/SpilledRows.php +++ b/src/core/etl/src/Flow/ETL/Extractor/SpilledRows.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Extractor; use Flow\ETL\Exception\InvalidLogicException; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema\Inference\SchemaSampler; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; @@ -143,7 +142,7 @@ public function rows(): Generator * $rowBudget is IGNORED: every row is written regardless, which is what makes a partially written * spill unreachable by construction rather than merely unlikely. * - * @return iterable> + * @return iterable>> * * @throws InvalidLogicException when the source was already read */ @@ -192,8 +191,8 @@ public function samples(int $rowBudget): iterable } }; - // InMemoryRows owns the raw-row to RawRowValues naming; keeping a second copy here would put the - // "same names array_to_rows() gives" invariant in two places. + // InMemoryRows owns the raw-row naming; keeping a second copy here would put the "same names array_to_rows() + // gives" invariant in two places. return (new InMemoryRows($spilling()))->samples($rowBudget); } diff --git a/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php b/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php index aecfb01c54..214d0e680c 100644 --- a/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php +++ b/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php @@ -73,6 +73,9 @@ public function accept(FileStatus $status): bool } // @mago-ignore analysis:mixed-operand - return (bool) $this->resolved->eval(array_to_row($values, schema(...$definitions)), $this->context); + return (bool) $this->resolved->eval( + array_to_row($values, schema(...$definitions), $this->context->backend()), + $this->context, + ); } } diff --git a/src/core/etl/src/Flow/ETL/FlowContext.php b/src/core/etl/src/Flow/ETL/FlowContext.php index cf5ca9d0f3..53bef1f5bd 100644 --- a/src/core/etl/src/Flow/ETL/FlowContext.php +++ b/src/core/etl/src/Flow/ETL/FlowContext.php @@ -63,6 +63,7 @@ public function withErrorHandler(ErrorHandler $handler): self public function telemetry(): TelemetryContext { return $this->telemetryContext ??= new TelemetryContext( + $this->config->backend(), $this->config->telemetry->telemetry->logger('flow_php_dataframe', $this->config->version()), $this->config->telemetry->telemetry->tracer('flow_php_dataframe', $this->config->version()), $this->config->telemetry->telemetry->meter('flow_php_dataframe', $this->config->version()), diff --git a/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php b/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php index 6b6c14dadf..130d802c37 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php @@ -4,7 +4,6 @@ namespace Flow\ETL\GroupBy; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\FlowContext; use Flow\ETL\GroupBy; use Flow\ETL\Rows; @@ -39,7 +38,7 @@ public function accumulate(Rows $batch, FlowContext $context): void * * @return Generator */ - public function flush(int $batchSize): Generator + public function flush(int $batchSize, FlowContext $context): Generator { $pending = []; @@ -47,7 +46,7 @@ public function flush(int $batchSize): Generator $pending[] = $this->groupBy->aggregatedValues($group->key, $group->aggregators, $this->shape->output); if (count($pending) >= $batchSize) { - yield (new RowsBuilder($this->shape->output, new DefaultBackend())) + yield (new RowsBuilder($this->shape->output, $context->backend())) ->appendRows($pending) ->finish(); $pending = []; @@ -55,7 +54,7 @@ public function flush(int $batchSize): Generator } if ($pending !== []) { - yield (new RowsBuilder($this->shape->output, new DefaultBackend())) + yield (new RowsBuilder($this->shape->output, $context->backend())) ->appendRows($pending) ->finish(); } diff --git a/src/core/etl/src/Flow/ETL/GroupBy/BucketAggregation.php b/src/core/etl/src/Flow/ETL/GroupBy/BucketAggregation.php index 8240c13744..c49e95130e 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/BucketAggregation.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/BucketAggregation.php @@ -49,7 +49,7 @@ public function aggregate(Generator $rows, FlowContext $context, GroupBy $groupB } if ($groups !== null) { - yield from $groups->flush($this->batchSize); + yield from $groups->flush($this->batchSize, $context); } } @@ -70,6 +70,6 @@ public function aggregateBound( $groups->accumulate($batch, $context); } - yield from $groups->flush($this->batchSize); + yield from $groups->flush($this->batchSize, $context); } } diff --git a/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php b/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php index 8913b23e28..2f7d420da8 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php @@ -29,7 +29,8 @@ */ public static function of(GroupBy $groupBy, Config $config, ?GroupByAlgorithmBuilder $algorithm = null): array { - $grouping = $algorithm?->build($config->cache->localFilesystemCacheDir) ?? $config->grouping; + $grouping = + $algorithm?->build($config->cache->localFilesystemCacheDir, $config->backend()) ?? $config->grouping; if ($groupBy->isPivot()) { return [new PivotProcessor($groupBy, $grouping->bucketing->batchSize)]; } diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php index d504f5361f..554a36bc84 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php @@ -8,7 +8,7 @@ use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\SingleBucketHasher; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\DuplicatedEntriesException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Join\Expression; @@ -43,6 +43,7 @@ final class Joiner public function __construct( private readonly Expression $expression, private readonly Join $type, + private readonly Backend $backend, private readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand @@ -145,7 +146,7 @@ public function join(JoinSide $left, JoinSide $right, bool $buildLeft = false): // a later batch can be wider than the side schema the output was derived from, and every arm answers // for the same declared output - the builder ignores the undeclared keys and pads the nulls the join // introduced - yield (new RowsBuilder($outputSchema, new DefaultBackend())) + yield (new RowsBuilder($outputSchema, $this->backend)) ->appendRows($joined) ->finish(); } @@ -161,7 +162,7 @@ public function join(JoinSide $left, JoinSide $right, bool $buildLeft = false): $pending[] = $this->merge($nullLeftRow, $rightRow); if (count($pending) >= $this->batchSize) { - yield (new RowsBuilder($outputSchema, new DefaultBackend())) + yield (new RowsBuilder($outputSchema, $this->backend)) ->appendRows($pending) ->finish(); $pending = []; @@ -169,7 +170,7 @@ public function join(JoinSide $left, JoinSide $right, bool $buildLeft = false): } if ($pending !== []) { - yield (new RowsBuilder($outputSchema, new DefaultBackend())) + yield (new RowsBuilder($outputSchema, $this->backend)) ->appendRows($pending) ->finish(); } @@ -252,7 +253,7 @@ private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator } if ($joined !== []) { - yield (new RowsBuilder($outputSchema, new DefaultBackend())) + yield (new RowsBuilder($outputSchema, $this->backend)) ->appendRows($joined) ->finish(); } @@ -269,7 +270,7 @@ private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator $pending[] = $this->type === Join::left ? $this->merge($leftRow, $nullRightRow) : $leftRow->values(); if (count($pending) >= $this->batchSize) { - yield (new RowsBuilder($outputSchema, new DefaultBackend())) + yield (new RowsBuilder($outputSchema, $this->backend)) ->appendRows($pending) ->finish(); $pending = []; @@ -277,7 +278,7 @@ private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator } if ($pending !== []) { - yield (new RowsBuilder($outputSchema, new DefaultBackend())) + yield (new RowsBuilder($outputSchema, $this->backend)) ->appendRows($pending) ->finish(); } diff --git a/src/core/etl/src/Flow/ETL/Join/JoinSteps.php b/src/core/etl/src/Flow/ETL/Join/JoinSteps.php index 8ab7bf631c..5c6dff210e 100644 --- a/src/core/etl/src/Flow/ETL/Join/JoinSteps.php +++ b/src/core/etl/src/Flow/ETL/Join/JoinSteps.php @@ -26,7 +26,7 @@ public static function of( Config $config, ?JoinAlgorithmBuilder $algorithm = null, ): array { - $join = $algorithm?->build($config->cache->localFilesystemCacheDir) ?? $config->join; + $join = $algorithm?->build($config->cache->localFilesystemCacheDir, $config->backend()) ?? $config->join; return [ new HashJoinProcessor( diff --git a/src/core/etl/src/Flow/ETL/Optimizer/Rule/CountFromStatistics.php b/src/core/etl/src/Flow/ETL/Optimizer/Rule/CountFromStatistics.php index 0122ea91c6..6ab5bce034 100644 --- a/src/core/etl/src/Flow/ETL/Optimizer/Rule/CountFromStatistics.php +++ b/src/core/etl/src/Flow/ETL/Optimizer/Rule/CountFromStatistics.php @@ -30,6 +30,9 @@ public function apply(LogicalPlan $plan, FlowContext $context): LogicalPlan return $rows === null ? $plan - : new LogicalPlan(new Result(new Read(from_rows((new CountingProcessor())->rows($rows))))); + : new LogicalPlan(new Result(new Read(from_rows((new CountingProcessor())->rows( + $rows, + $context->backend(), + ))))); } } diff --git a/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php b/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php index b276930834..f6778ad354 100644 --- a/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php +++ b/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php @@ -34,7 +34,8 @@ public function of(Node $node): Node } $config = $this->context->config; - $algorithm = $sort->algorithm?->build($config->cache->localFilesystemCacheDir) ?? $config->sort; + $algorithm = + $sort->algorithm?->build($config->cache->localFilesystemCacheDir, $config->backend()) ?? $config->sort; if ($algorithm instanceof ExternalSortConfig && $node->limit > $algorithm->runSize) { return $node; diff --git a/src/core/etl/src/Flow/ETL/Processor/CountingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/CountingProcessor.php index dcf1b0b76d..86cd9d9ef1 100644 --- a/src/core/etl/src/Flow/ETL/Processor/CountingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/CountingProcessor.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Processor; use Flow\ETL\BoundStep; +use Flow\ETL\Column\Backend; use Flow\ETL\FlowContext; use Flow\ETL\Processor; use Flow\ETL\Rows; @@ -30,15 +31,15 @@ public function process(Generator $rows, FlowContext $context): Generator $count += $batch->count(); } - yield $this->rows($count); + yield $this->rows($count, $context->backend()); } /** * The one row a count hands out, whether it was counted or known upfront. */ - public function rows(int $count): Rows + public function rows(int $count, Backend $backend): Rows { - return array_to_rows([['count' => $count]], $this->schema()); + return array_to_rows([['count' => $count]], $this->schema(), $backend); } public function schema(): Schema diff --git a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php index 61f2ac6ee5..0dd23bc0b7 100644 --- a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php @@ -7,7 +7,6 @@ use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\BucketShape; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\FlowContext; @@ -91,7 +90,7 @@ public function process(Generator $rows, FlowContext $context): Generator // SQL's scalar aggregate: no input and no grouping key is one row of the initial accumulators, // not no row. Only reachable bound - an unbound plan has no schema to type the defaults with. if (!$emitted && $this->shape !== null && $this->groupBy->isGlobal()) { - yield (new RowsBuilder($this->shape->output, new DefaultBackend()))->appendRows([ + yield (new RowsBuilder($this->shape->output, $context->backend()))->appendRows([ $this->groupBy->aggregatedValues( new GroupKey([]), $this->shape->aggregators->cloned(), diff --git a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php index 20c4edd9a7..3026cc11e1 100644 --- a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php @@ -119,7 +119,7 @@ public function process(Generator $rows, FlowContext $context): Generator } } - $joiner = new Joiner($this->expression, $this->type, $this->batchSize); + $joiner = new Joiner($this->expression, $this->type, $context->backend(), $this->batchSize); $equalityKeys = $joiner->keys(); $resident = $this->rightBuckets->storage() instanceof ResidentBucketsStorage; diff --git a/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php b/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php index 13931e45ae..d7c53b4f4f 100644 --- a/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php @@ -69,7 +69,7 @@ public function process(Generator $rows, FlowContext $context): Generator } } - $merger = new KWayMerge($this->refs, $this->batchSize); + $merger = new KWayMerge($this->refs, $context->backend(), $this->batchSize); $mergedIndex = 0; while (count($runs) > $this->mergeFanIn) { diff --git a/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php b/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php index 1458a6ab3c..4e38044d69 100644 --- a/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php +++ b/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php @@ -24,7 +24,8 @@ */ public static function of(References $by, Config $config, ?RepartitionAlgorithmBuilder $algorithm = null): array { - $repartition = $algorithm?->build($config->cache->localFilesystemCacheDir) ?? $config->repartition; + $repartition = + $algorithm?->build($config->cache->localFilesystemCacheDir, $config->backend()) ?? $config->repartition; $buckets = new Buckets($repartition->bucketing->storage); return [ diff --git a/src/core/etl/src/Flow/ETL/Row/RawRowValues.php b/src/core/etl/src/Flow/ETL/Row/RawRowValues.php deleted file mode 100644 index 17398caaad..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/RawRowValues.php +++ /dev/null @@ -1,19 +0,0 @@ - $values - * @param array $metadata - */ - public function __construct( - public array $values, - public array $metadata = [], - ) {} -} diff --git a/src/core/etl/src/Flow/ETL/Rows.php b/src/core/etl/src/Flow/ETL/Rows.php index e9914ae999..17bd56750c 100644 --- a/src/core/etl/src/Flow/ETL/Rows.php +++ b/src/core/etl/src/Flow/ETL/Rows.php @@ -9,7 +9,6 @@ use Countable; use Flow\ETL\Column\Column; use Flow\ETL\Column\DefaultBackend; -use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; @@ -81,7 +80,7 @@ public function __serialize(): array */ public function __unserialize(array $data): void { - $rows = (new FrameDecoder())->decode($data['frame'], $data['schema'], new PhpBackend()); + $rows = (new FrameDecoder())->decode($data['frame'], $data['schema'], new DefaultBackend()); $this->schema = $rows->schema; $this->columns = $rows->columns; @@ -94,7 +93,7 @@ public function __unserialize(array $data): void public static function of(Schema $schema, Row ...$rows): self { if ($rows === []) { - $backend = new PhpBackend(); + $backend = new DefaultBackend(); $columns = []; foreach ($schema->definitions() as $name => $definition) { @@ -122,7 +121,7 @@ public static function of(Schema $schema, Row ...$rows): self return new self($schema, $gathered->columns, $gathered->count); } - $builder = new RowsBuilder($schema, new PhpBackend()); + $builder = new RowsBuilder($schema, new DefaultBackend()); foreach ($rows as $row) { $builder->appendFrom($row->rows, $row->index); @@ -280,7 +279,7 @@ public function concat(self ...$others): self return self::of($this->schema); } - $backend = new PhpBackend(); + $backend = new DefaultBackend(); $columns = []; foreach ($this->schema->definitions() as $name => $definition) { @@ -543,7 +542,7 @@ public function matchTo(Schema $schema): self } } - $backend = new PhpBackend(); + $backend = new DefaultBackend(); $columns = []; $changed = []; @@ -976,7 +975,7 @@ private function joinUsing(self $right, Expression $expression, Join $type): sel yield $rows; }; - $joiner = new Joiner($expression, $type); + $joiner = new Joiner($expression, $type, new DefaultBackend()); $joined = []; foreach ($joiner->join(JoinSide::of($single($this)), JoinSide::of($single($right))) as $batch) { diff --git a/src/core/etl/src/Flow/ETL/Schema/Inference/ColumnTypes.php b/src/core/etl/src/Flow/ETL/Schema/Inference/ColumnTypes.php index d35acbe5da..7f4f51fe62 100644 --- a/src/core/etl/src/Flow/ETL/Schema/Inference/ColumnTypes.php +++ b/src/core/etl/src/Flow/ETL/Schema/Inference/ColumnTypes.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Schema\Inference; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema; use Flow\Types\Type; use Flow\Types\Type\Logical\OptionalType; @@ -92,12 +91,12 @@ public function merge(self $other, bool $unionByName): self } /** - * RawRowValues::$metadata is not read: the fold types columns. + * @param array $row */ - public function observe(RawRowValues $row): void + public function observe(array $row): void { /** @var mixed $value */ - foreach ($row->values as $name => $value) { + foreach ($row as $name => $value) { $current = array_key_exists($name, $this->types) ? $this->types[$name] : null; if ( diff --git a/src/core/etl/src/Flow/ETL/Schema/Inference/SchemaInferrer.php b/src/core/etl/src/Flow/ETL/Schema/Inference/SchemaInferrer.php index 9bc005ea82..c081916691 100644 --- a/src/core/etl/src/Flow/ETL/Schema/Inference/SchemaInferrer.php +++ b/src/core/etl/src/Flow/ETL/Schema/Inference/SchemaInferrer.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Schema\Inference; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema; use Flow\Types\Type\TypeNarrower; @@ -22,7 +21,7 @@ public function __construct( * a source abandoned mid-way is closed by its producer, not here. * * @param list $names - columns known before any row; [] when the format carries none (JSON) - * @param iterable> $sources - one inner iterable per source, in listing order. + * @param iterable>> $sources - one inner iterable per source, in listing order. * A source that lists no files yields exactly one. * An empty outer iterable yields every name as ?string. */ @@ -62,7 +61,7 @@ public function infer(array $names, iterable $sources): Schema /** * @param list $names - columns known before any row; [] when the format carries none (JSON) - * @param iterable $source - one source's rows, unstarted + * @param iterable> $source - one source's rows, unstarted * @param int<0, max>|-1 $rowBudget - rows to observe, 0 for none, -1 for all of them */ public function sniff(array $names, iterable $source, int $rowBudget): ColumnTypes diff --git a/src/core/etl/src/Flow/ETL/Schema/Inference/SchemaSampler.php b/src/core/etl/src/Flow/ETL/Schema/Inference/SchemaSampler.php index d7224f93c1..8a8e1d3140 100644 --- a/src/core/etl/src/Flow/ETL/Schema/Inference/SchemaSampler.php +++ b/src/core/etl/src/Flow/ETL/Schema/Inference/SchemaSampler.php @@ -4,8 +4,6 @@ namespace Flow\ETL\Schema\Inference; -use Flow\ETL\Row\RawRowValues; - interface SchemaSampler { /** @@ -13,7 +11,7 @@ interface SchemaSampler * The outer iterable is exactly what SchemaInferrer::infer() consumes; a unit that implements * SniffsColumnTypes folds itself into its partial instead of being iterated row by row. * - * @return iterable> + * @return iterable>> */ public function samples(int $rowBudget): iterable; } diff --git a/src/core/etl/src/Flow/ETL/Schema/Inference/SniffsColumnTypes.php b/src/core/etl/src/Flow/ETL/Schema/Inference/SniffsColumnTypes.php index 97b55c0a3d..46a120e4c5 100644 --- a/src/core/etl/src/Flow/ETL/Schema/Inference/SniffsColumnTypes.php +++ b/src/core/etl/src/Flow/ETL/Schema/Inference/SniffsColumnTypes.php @@ -4,12 +4,11 @@ namespace Flow\ETL\Schema\Inference; -use Flow\ETL\Row\RawRowValues; use Flow\Types\Type\TypeNarrower; use Traversable; /** - * @extends Traversable + * @extends Traversable> */ interface SniffsColumnTypes extends Traversable { diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php index c21860c42e..10924cbb78 100644 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php +++ b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Sort\Merge; use Flow\ETL\Bucketing\BucketRun; -use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Row\References; use Flow\ETL\Rows; @@ -20,6 +20,7 @@ */ public function __construct( private References $refs, + private Backend $backend, private int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand @@ -53,7 +54,7 @@ public function merge(array $runs): Generator } } - $buffer = new RowsBuffer($schema ?? new Schema(), new PhpBackend(), $this->batchSize); + $buffer = new RowsBuffer($schema ?? new Schema(), $this->backend, $this->batchSize); while (!$heap->isEmpty()) { $top = $heap->extract(); diff --git a/src/core/etl/src/Flow/ETL/Sort/SortSteps.php b/src/core/etl/src/Flow/ETL/Sort/SortSteps.php index a9a6b0731c..adefd0ddd9 100644 --- a/src/core/etl/src/Flow/ETL/Sort/SortSteps.php +++ b/src/core/etl/src/Flow/ETL/Sort/SortSteps.php @@ -25,7 +25,7 @@ */ public static function of(References $refs, Config $config, ?SortAlgorithmBuilder $algorithm = null): array { - $sort = $algorithm?->build($config->cache->localFilesystemCacheDir) ?? $config->sort; + $sort = $algorithm?->build($config->cache->localFilesystemCacheDir, $config->backend()) ?? $config->sort; if ($sort instanceof MemorySortConfig) { return [new MemorySortProcessor($refs)]; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Comparator/ColumnComparator.php b/src/core/etl/tests/Flow/ETL/Tests/Comparator/ColumnComparator.php new file mode 100644 index 0000000000..bae3aff649 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Comparator/ColumnComparator.php @@ -0,0 +1,63 @@ +type()->toString() !== $actual->type()->toString()) { + throw new ComparisonFailure( + $expected, + $actual, + $expected->type()->toString(), + $actual->type()->toString(), + 'Failed asserting that two columns have the same type.', + ); + } + + $expectedPhysicals = $expected->physicals(); + $actualPhysicals = $actual->physicals(); + + try { + $this + ->factory() + ->getComparatorFor($expectedPhysicals, $actualPhysicals) + ->assertEquals($expectedPhysicals, $actualPhysicals, $delta, $canonicalize, $ignoreCase); + } catch (ComparisonFailure) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expectedPhysicals), + $exporter->export($actualPhysicals), + 'Failed asserting that two columns are equal.', + ); + } + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/MemoryTelemetryContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/MemoryTelemetryContext.php index b56ceb02e6..ca5ffc2a2a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/MemoryTelemetryContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/MemoryTelemetryContext.php @@ -67,6 +67,7 @@ public function __construct( $this->config = $configBuilder->build(); $this->flowContext = flow_context($this->config); $this->telemetryContext = new TelemetryContext( + $this->config->backend(), $this->telemetry->logger('flow-php'), $this->telemetry->tracer('flow-php'), $this->telemetry->meter('flow-php'), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingBackend.php b/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingBackend.php index f289e8078a..e457c4bef1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingBackend.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingBackend.php @@ -29,4 +29,14 @@ public function decode(Definition $definition, array $buffers, int $count, int $ { return (new PhpBackend())->decode($definition, $buffers, $count, $nullCount); } + + public function adopt(Definition $definition, Column $column): Column + { + return $column; + } + + public function allocatedBytes(): int + { + return 0; + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeSchemaSampler.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeSchemaSampler.php index 7ef84fa86a..e6e89ea073 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeSchemaSampler.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeSchemaSampler.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Tests\Double; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema\Inference\SchemaSampler; final class FakeSchemaSampler implements SchemaSampler @@ -15,14 +14,14 @@ final class FakeSchemaSampler implements SchemaSampler public array $askedBudgets = []; /** - * @param list> $units + * @param list>> $units */ public function __construct( private readonly array $units, ) {} /** - * @return list> + * @return list>> */ public function samples(int $rowBudget): iterable { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ForeignColumnStub.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ForeignColumnStub.php new file mode 100644 index 0000000000..f6c284c11e --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ForeignColumnStub.php @@ -0,0 +1,83 @@ +column->at($i); + } + + public function concat(Column ...$others): Column + { + return $this->column->concat(...$others); + } + + public function count(): int + { + return $this->column->count(); + } + + public function encode(): array + { + return $this->column->encode(); + } + + public function isNull(int $i): bool + { + return $this->column->isNull($i); + } + + public function nullCount(): int + { + return $this->column->nullCount(); + } + + public function physicals(): array + { + return $this->column->physicals(); + } + + public function slice(int $offset, int $length): Column + { + return new self($this->column->slice($offset, $length)); + } + + public function take(array $indices): Column + { + return $this->column->take($indices); + } + + public function type(): Type + { + return $this->column->type(); + } + + public function value(int $i): mixed + { + return $this->column->value($i); + } + + public function values(): array + { + return $this->column->values(); + } + + public function withType(Type $type): Column + { + return $this->column->withType($type); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingSources.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingSources.php index b1959ca661..82db2e8081 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingSources.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingSources.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Tests\Double; -use Flow\ETL\Row\RawRowValues; use Generator; use function array_keys; @@ -24,14 +23,14 @@ final class RecordingSources public array $rowsRead = []; /** - * @param list> $sources + * @param list>> $sources */ public function __construct( private readonly array $sources, ) {} /** - * @return Generator + * @return Generator> */ public function source(int $index): Generator { @@ -46,7 +45,7 @@ public function source(int $index): Generator } /** - * @return Generator> + * @return Generator>> */ public function sources(): Generator { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php index af0d305771..813e3942b1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php @@ -12,17 +12,37 @@ final class SpyBackend implements Backend { + private int $adopts = 0; + private int $builders = 0; private int $decodes = 0; private readonly PhpBackend $php; - public function __construct() - { + public function __construct( + private readonly int $allocatedBytes = 0, + ) { $this->php = new PhpBackend(); } + public function adopt(Definition $definition, Column $column): Column + { + $this->adopts++; + + return $this->php->adopt($definition, $column); + } + + public function adopts(): int + { + return $this->adopts; + } + + public function allocatedBytes(): int + { + return $this->allocatedBytes; + } + public function builder(Definition $definition): ColumnBuilder { $this->builders++; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpySniffingSample.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpySniffingSample.php index f63085dfce..b869bed1f7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/SpySniffingSample.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpySniffingSample.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Tests\Double; use ArrayIterator; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SniffsColumnTypes; @@ -17,7 +16,7 @@ * A sample that sniffs itself: records what SchemaInferrer hands it and answers with a canned fold. Iterating it * fails - infer() must never fall back to row-by-row observe() for a unit that sniffs itself. * - * @implements IteratorAggregate + * @implements IteratorAggregate> */ final class SpySniffingSample implements IteratorAggregate, SniffsColumnTypes { @@ -31,7 +30,7 @@ public function __construct( ) {} /** - * @return ArrayIterator + * @return ArrayIterator> */ public function getIterator(): ArrayIterator { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php index a9849e55ed..c1b2883bd7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php @@ -6,9 +6,11 @@ use DateTimeImmutable; use Flow\ETL\Bucketing\Storage\FilesystemBuckets; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Tests\Context\BucketsStorageContext; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\Exception\IncompatibleSchemaException; use Flow\Floe\FloeWriter; @@ -37,7 +39,7 @@ public function test_append_after_get_does_not_truncate_the_bucket(): void $cacheDir = path(__DIR__ . '/var/buckets_append_reopen'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); static::assertCount(1, BucketsStorageContext::rows($storage->get('bucket'))); @@ -54,7 +56,7 @@ public function test_append_with_a_column_absent_from_the_bucket_schema_fails(): $cacheDir = path(__DIR__ . '/var/buckets_append_new_column'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $this->expectException(IncompatibleSchemaException::class); @@ -71,7 +73,7 @@ public function test_append_widening_a_column_type_fails(): void $cacheDir = path(__DIR__ . '/var/buckets_append_widen'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->append('bucket', array_to_rows([['amount' => 1]], schema(int_schema('amount')))); $this->expectException(IncompatibleSchemaException::class); @@ -85,7 +87,7 @@ public function test_appends_accumulate_into_one_bucket_in_order(): void $cacheDir = path(__DIR__ . '/var/buckets_append'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, batchSize: 2); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend(), batchSize: 2); $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 4], ['id' => 5]], schema(int_schema('id')))); @@ -103,7 +105,7 @@ public function test_custom_batch_size_round_trips_all_rows(): void $cacheDir = path(__DIR__ . '/var/buckets_batch_size'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, batchSize: 2); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend(), batchSize: 2); $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id')))); static::assertCount(3, BucketsStorageContext::rows($storage->get('bucket'))); @@ -116,7 +118,7 @@ public function test_small_appends_read_back_coalesced_up_to_the_batch_size(): v $cacheDir = path(__DIR__ . '/var/buckets_coalesced'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, batchSize: 3); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend(), batchSize: 3); foreach ([1, 2, 3, 4, 5] as $id) { $storage->append('bucket', array_to_rows([['id' => $id]], schema(int_schema('id')))); @@ -140,7 +142,11 @@ public function test_get_missing_bucket_yields_nothing(): void static::assertSame( [], - BucketsStorageContext::rows((new FilesystemBuckets($this->fs(), cacheDir: $cacheDir))->get('nope')), + BucketsStorageContext::rows((new FilesystemBuckets( + $this->fs(), + cacheDir: $cacheDir, + backend: new PhpBackend(), + ))->get('nope')), ); } @@ -149,7 +155,7 @@ public function test_remove_closes_an_open_append_session(): void $cacheDir = path(__DIR__ . '/var/buckets_append_remove'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $storage->remove('bucket'); @@ -163,7 +169,7 @@ public function test_remove_deletes_the_bucket(): void $cacheDir = path(__DIR__ . '/var/buckets_remove'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $storage->remove('bucket'); @@ -177,7 +183,7 @@ public function test_round_trips_rows_across_the_read_batch_boundary(): void $cacheDir = path(__DIR__ . '/var/buckets_batch'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $input = []; @@ -200,7 +206,7 @@ public function test_set_replaces_a_bucket_written_with_append(): void $cacheDir = path(__DIR__ . '/var/buckets_append_set'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->set('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); @@ -217,7 +223,7 @@ public function test_set_with_empty_rows_creates_a_readable_empty_bucket(): void $cacheDir = path(__DIR__ . '/var/buckets_empty'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->set('bucket', rows(schema())); static::assertSame([], BucketsStorageContext::rows($storage->get('bucket'))); @@ -230,7 +236,7 @@ public function test_round_trips_schema_changing_rows(): void $cacheDir = path(__DIR__ . '/var/buckets_heterogeneous'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $input = [ array_to_row(['id' => 1], schema(int_schema('id'))), @@ -262,7 +268,7 @@ public function test_append_with_reordered_structure_keys_matches_and_keeps_ever $cacheDir = path(__DIR__ . '/var/buckets_append_struct_order'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->append('bucket', array_to_rows( [['id' => 1, 's' => ['a' => 1, 'b' => 'x']]], schema( @@ -298,7 +304,7 @@ public function test_append_with_reordered_columns_matches_and_keeps_every_row() $cacheDir = path(__DIR__ . '/var/buckets_append_col_order'); $this->fs()->rm($cacheDir); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->append('bucket', array_to_rows( [['id' => 1, 'name' => 'x']], schema(int_schema('id'), str_schema('name')), @@ -354,7 +360,7 @@ public function test_datetime_values_read_back_as_admitted(): void ]], schema(datetime_schema('at', zone: 'Europe/Warsaw'))); $admitted = type_datetime()->assert($rows->first()->get('at'))->format('c'); - $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->set('b', $rows); static::assertSame('2026-01-01T23:04:05+01:00', $admitted); @@ -365,4 +371,19 @@ public function test_datetime_values_read_back_as_admitted(): void $this->fs()->rm($cacheDir); } + + public function test_buckets_decode_with_the_given_backend(): void + { + $cacheDir = path(__DIR__ . '/var/buckets_backend'); + $this->fs()->rm($cacheDir); + $backend = new SpyBackend(); + $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: $backend); + $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); + + BucketsStorageContext::rows($storage->get('bucket')); + + static::assertGreaterThan(0, $backend->decodes()); + + $this->fs()->rm($cacheDir); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/Bucketing/BucketingConfigBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/Bucketing/BucketingConfigBuilderTest.php index cb80faa776..0ea0253f72 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/Bucketing/BucketingConfigBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/Bucketing/BucketingConfigBuilderTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Integration\Config\Bucketing; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; use Flow\ETL\Tests\FlowIntegrationTestCase; @@ -20,7 +21,7 @@ public function test_build_uses_the_given_spill_root_for_the_default_storage(): $spillRoot = $this->cacheDir->suffix('/spill-root'); (new BucketingConfigBuilder('/flow-php-sort/', 64)) - ->build($spillRoot) + ->build($spillRoot, new PhpBackend()) ->storage->set('bucket-1', array_to_rows([['id' => 1]], schema(int_schema('id')))); static::assertNotSame( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/FileSourceFilesystemTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/FileSourceFilesystemTest.php index a255d916da..1a00c0a944 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/FileSourceFilesystemTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/FileSourceFilesystemTest.php @@ -248,9 +248,9 @@ public function test_reads_through_the_given_filesystem(): void static::assertSame([1, 2], array_column($rows, 'id')); static::assertSame( - 3, + 4, $counting->readFromCalls, - 'header() + the sample pass + the read, all through the filesystem it was given', + 'header() + the sample pass + the divergence check + the read, all through the filesystem it was given', ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php index a16df60540..d05c388663 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php @@ -6,14 +6,40 @@ use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Tests\Double\ForeignColumnStub; use Flow\ETL\Tests\Mother\ColumnMother; use PHPUnit\Framework\TestCase; +use function extension_loaded; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\str_schema; final class DefaultBackendTest extends TestCase { + protected function setUp(): void + { + if (extension_loaded('flow_php')) { + static::markTestSkipped('flow_php registers its own DefaultBackend'); + } + } + + public function test_adopt_is_what_the_php_backend_adopts(): void + { + $column = ColumnMother::of(int_schema('a'), [1, 2]); + $foreign = new ForeignColumnStub($column); + + static::assertSame($column, (new DefaultBackend())->adopt(int_schema('a'), $column)); + static::assertEquals( + (new PhpBackend())->adopt(int_schema('a'), $foreign), + (new DefaultBackend())->adopt(int_schema('a'), $foreign), + ); + } + + public function test_allocated_bytes_is_what_the_php_backend_allocates(): void + { + static::assertSame((new PhpBackend())->allocatedBytes(), (new DefaultBackend())->allocatedBytes()); + } + public function test_builder_builds_what_the_php_backend_builds(): void { $default = (new DefaultBackend())->builder(str_schema('a')); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php index f0a41c8a27..9089e131b1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php @@ -16,6 +16,7 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Schema\Definition; +use Flow\ETL\Tests\Double\ForeignColumnStub; use Flow\ETL\Tests\Double\ForeignTypeDefinition; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\Mother\ColumnMother; @@ -565,4 +566,47 @@ public function test_decode_refuses( (new PhpBackend())->decode($definition, $buffers, $count, $nullCount); } + + public function test_adopt_returns_its_own_column(): void + { + $column = ColumnMother::of(int_schema('a'), [1, 2]); + + static::assertSame($column, (new PhpBackend())->adopt(int_schema('a'), $column)); + } + + public function test_adopt_copies_a_foreign_column(): void + { + $foreign = new ForeignColumnStub(ColumnMother::of(str_schema('a', nullable: true), ['x', null, 'z'])); + + $adopted = (new PhpBackend())->adopt(str_schema('a', nullable: true), $foreign); + + static::assertNotSame($foreign, $adopted); + static::assertSame(['x', null, 'z'], $adopted->values()); + static::assertSame(1, $adopted->nullCount()); + } + + public function test_adopt_copies_an_empty_foreign_column(): void + { + $foreign = new ForeignColumnStub(ColumnMother::of(int_schema('a'), [])); + + $adopted = (new PhpBackend())->adopt(int_schema('a'), $foreign); + + static::assertNotSame($foreign, $adopted); + static::assertSame(0, $adopted->count()); + } + + public function test_adopt_refuses_a_null_under_not_null(): void + { + $foreign = new ForeignColumnStub(ColumnMother::of(int_schema('a', nullable: true), [1, null])); + + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage(ColumnMismatchException::valueDoesNotMatch(int_schema('a'), null)->getMessage()); + + (new PhpBackend())->adopt(int_schema('a'), $foreign); + } + + public function test_allocated_bytes_is_zero(): void + { + static::assertSame(0, (new PhpBackend())->allocatedBytes()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ColumnComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ColumnComparatorTest.php new file mode 100644 index 0000000000..a539e814b5 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ColumnComparatorTest.php @@ -0,0 +1,65 @@ +accepts($column, $column)); + static::assertFalse((new ColumnComparator())->accepts($column, [1])); + static::assertFalse((new ColumnComparator())->accepts([1], $column)); + } + + public function test_columns_of_both_backends_with_equal_values_pass(): void + { + $comparator = new ColumnComparator(); + $comparator->setFactory(Factory::getInstance()); + $default = (new DefaultBackend())->builder(int_schema('a', nullable: true)); + $default->appendMany([1, null]); + + $comparator->assertEquals(ColumnMother::of(int_schema('a', nullable: true), [1, null]), $default->finish()); + + $this->addToAssertionCount(1); + } + + public function test_different_values_fail(): void + { + $comparator = new ColumnComparator(); + $comparator->setFactory(Factory::getInstance()); + + $this->expectException(ComparisonFailure::class); + $this->expectExceptionMessage('Failed asserting that two columns are equal.'); + + $comparator->assertEquals( + (new PhpBackend())->constant(int_schema('a'), 1, 2), + ColumnMother::of(int_schema('a'), [1, 3]), + ); + } + + public function test_different_types_fail(): void + { + $comparator = new ColumnComparator(); + $comparator->setFactory(Factory::getInstance()); + + $this->expectException(ComparisonFailure::class); + $this->expectExceptionMessage('Failed asserting that two columns have the same type.'); + + $comparator->assertEquals(ColumnMother::of(int_schema('a'), [1]), ColumnMother::of(str_schema('a'), ['1'])); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Bucketing/BucketingConfigBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Bucketing/BucketingConfigBuilderTest.php index 0159f8501f..d1a6f6c7f9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Bucketing/BucketingConfigBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Bucketing/BucketingConfigBuilderTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Bucketing\Storage\FilesystemBuckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; @@ -27,7 +28,7 @@ public function test_buckets_count_and_batch_size_are_set(): void $config = (new BucketingConfigBuilder('/flow-php-join/', 64)) ->bucketsCount(4) ->batchSize(250) - ->build(Path::realpath(__DIR__)); + ->build(Path::realpath(__DIR__), new PhpBackend()); static::assertSame(4, $config->bucketsCount); static::assertSame(250, $config->batchSize); @@ -44,7 +45,7 @@ public function test_buckets_count_below_one_is_rejected(): void public function test_default_builds_a_filesystem_buckets_storage(): void { - $config = (new BucketingConfigBuilder('/flow-php-join/', 64))->build(Path::realpath(__DIR__)); + $config = (new BucketingConfigBuilder('/flow-php-join/', 64))->build(Path::realpath(__DIR__), new PhpBackend()); static::assertInstanceOf(FilesystemBuckets::class, $config->storage); static::assertSame(64, $config->bucketsCount); @@ -53,7 +54,10 @@ public function test_default_builds_a_filesystem_buckets_storage(): void public function test_default_buckets_count_comes_from_the_constructor(): void { - $config = (new BucketingConfigBuilder('/flow-php-sort/', 100))->build(Path::realpath(__DIR__)); + $config = (new BucketingConfigBuilder('/flow-php-sort/', 100))->build( + Path::realpath(__DIR__), + new PhpBackend(), + ); static::assertSame(100, $config->bucketsCount); } @@ -64,7 +68,7 @@ public function test_injected_storage_wins_over_the_default(): void $config = (new BucketingConfigBuilder('/flow-php-join/', 64)) ->storage($storage) - ->build(Path::realpath(__DIR__)); + ->build(Path::realpath(__DIR__), new PhpBackend()); static::assertSame($storage, $config->storage); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Grouping/HashGroupByBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Grouping/HashGroupByBuilderTest.php index 134370e877..d5c0650659 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Grouping/HashGroupByBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Grouping/HashGroupByBuilderTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Bucketing\Storage\FilesystemBuckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Path; @@ -15,7 +16,7 @@ final class HashGroupByBuilderTest extends FlowTestCase { public function test_bucketing_options_are_set(): void { - $config = hash_group_by()->bucketsCount(4)->batchSize(250)->build(Path::realpath(__DIR__)); + $config = hash_group_by()->bucketsCount(4)->batchSize(250)->build(Path::realpath(__DIR__), new PhpBackend()); static::assertSame(4, $config->bucketing->bucketsCount); static::assertSame(250, $config->bucketing->batchSize); @@ -23,7 +24,7 @@ public function test_bucketing_options_are_set(): void public function test_default_builds_a_filesystem_buckets_storage(): void { - $config = hash_group_by()->build(Path::realpath(__DIR__)); + $config = hash_group_by()->build(Path::realpath(__DIR__), new PhpBackend()); static::assertInstanceOf(FilesystemBuckets::class, $config->bucketing->storage); static::assertSame(64, $config->bucketing->bucketsCount); @@ -36,7 +37,7 @@ public function test_injected_storage_wins_over_the_default(): void static::assertSame( $storage, - hash_group_by()->storage($storage)->build(Path::realpath(__DIR__))->bucketing->storage, + hash_group_by()->storage($storage)->build(Path::realpath(__DIR__), new PhpBackend())->bucketing->storage, ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Join/HashJoinBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Join/HashJoinBuilderTest.php index 311f034df7..024c865e0d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Join/HashJoinBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Join/HashJoinBuilderTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Bucketing\Storage\FilesystemBuckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Path; @@ -15,7 +16,7 @@ final class HashJoinBuilderTest extends FlowTestCase { public function test_bucketing_options_are_set(): void { - $config = hash_join()->bucketsCount(4)->batchSize(250)->build(Path::realpath(__DIR__)); + $config = hash_join()->bucketsCount(4)->batchSize(250)->build(Path::realpath(__DIR__), new PhpBackend()); static::assertSame(4, $config->bucketing->bucketsCount); static::assertSame(250, $config->bucketing->batchSize); @@ -23,7 +24,7 @@ public function test_bucketing_options_are_set(): void public function test_default_builds_a_filesystem_buckets_storage(): void { - $config = hash_join()->build(Path::realpath(__DIR__)); + $config = hash_join()->build(Path::realpath(__DIR__), new PhpBackend()); static::assertInstanceOf(FilesystemBuckets::class, $config->bucketing->storage); static::assertSame(64, $config->bucketing->bucketsCount); @@ -36,7 +37,7 @@ public function test_injected_storage_wins_over_the_default(): void static::assertSame( $storage, - hash_join()->storage($storage)->build(Path::realpath(__DIR__))->bucketing->storage, + hash_join()->storage($storage)->build(Path::realpath(__DIR__), new PhpBackend())->bucketing->storage, ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/ExternalSortBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/ExternalSortBuilderTest.php index 6af61444be..ccfc3a8cae 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/ExternalSortBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/ExternalSortBuilderTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Bucketing\Storage\FilesystemBuckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Path; @@ -16,7 +17,7 @@ final class ExternalSortBuilderTest extends FlowTestCase { public function test_bucketing_options_are_set(): void { - $config = external_sort()->bucketsCount(10)->batchSize(250)->build(Path::realpath(__DIR__)); + $config = external_sort()->bucketsCount(10)->batchSize(250)->build(Path::realpath(__DIR__), new PhpBackend()); static::assertSame(10, $config->bucketing->bucketsCount); static::assertSame(250, $config->bucketing->batchSize); @@ -24,7 +25,7 @@ public function test_bucketing_options_are_set(): void public function test_default_builds_a_filesystem_buckets_storage(): void { - $config = external_sort()->build(Path::realpath(__DIR__)); + $config = external_sort()->build(Path::realpath(__DIR__), new PhpBackend()); static::assertInstanceOf(FilesystemBuckets::class, $config->bucketing->storage); static::assertSame(100, $config->bucketing->bucketsCount); @@ -34,14 +35,19 @@ public function test_default_builds_a_filesystem_buckets_storage(): void public function test_merge_storage_defaults_to_null_so_the_spill_storage_is_reused(): void { - static::assertNull(external_sort()->storage(new MemoryBuckets())->build(Path::realpath(__DIR__))->merge); + static::assertNull( + external_sort()->storage(new MemoryBuckets())->build(Path::realpath(__DIR__), new PhpBackend())->merge, + ); } public function test_merge_storage_is_carried_into_the_config(): void { $merge = new MemoryBuckets(); - static::assertSame($merge, external_sort()->mergeStorage($merge)->build(Path::realpath(__DIR__))->merge); + static::assertSame( + $merge, + external_sort()->mergeStorage($merge)->build(Path::realpath(__DIR__), new PhpBackend())->merge, + ); } public function test_injected_storage_wins_over_the_default(): void @@ -50,7 +56,7 @@ public function test_injected_storage_wins_over_the_default(): void static::assertSame( $storage, - external_sort()->storage($storage)->build(Path::realpath(__DIR__))->bucketing->storage, + external_sort()->storage($storage)->build(Path::realpath(__DIR__), new PhpBackend())->bucketing->storage, ); } @@ -65,6 +71,9 @@ public function test_run_size_below_one_is_rejected(): void public function test_run_size_is_set(): void { - static::assertSame(500, external_sort()->runSize(500)->build(Path::realpath(__DIR__))->runSize); + static::assertSame( + 500, + external_sort()->runSize(500)->build(Path::realpath(__DIR__), new PhpBackend())->runSize, + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/MemorySortBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/MemorySortBuilderTest.php index 751df697b4..1343b647d9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/MemorySortBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/MemorySortBuilderTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Config\Sort; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Config\Sort\MemorySortConfig; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Path; @@ -14,6 +15,9 @@ final class MemorySortBuilderTest extends FlowTestCase { public function test_builds_a_memory_sort_config(): void { - static::assertInstanceOf(MemorySortConfig::class, memory_sort()->build(Path::realpath(__DIR__))); + static::assertInstanceOf(MemorySortConfig::class, memory_sort()->build( + Path::realpath(__DIR__), + new PhpBackend(), + )); } } 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 80fc48a450..1ce41a6ec2 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 @@ -5,6 +5,7 @@ namespace Flow\ETL\Tests\Unit\Config\Telemetry; use DateTimeImmutable; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Config\Telemetry\TelemetryContext; use Flow\ETL\Config\Telemetry\TelemetryOptions; use Flow\ETL\Loader\StreamLoader; @@ -94,6 +95,7 @@ public function test_dataframe_batch_processed_tracks_rows_and_memory(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -166,6 +168,7 @@ public function test_dataframe_completed_finalizes_span_with_statistics(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -242,6 +245,7 @@ public function test_dataframe_failed_logs_error_and_sets_span_status(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -293,6 +297,7 @@ public function test_dataframe_started_creates_span_and_logs_debug_message(): vo ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -352,6 +357,7 @@ public function test_loading_completed_finalizes_span_with_ok_status(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -418,6 +424,7 @@ public function test_loading_failed_logs_error_and_sets_span_status(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -490,6 +497,7 @@ public function test_loading_started_creates_span_when_trace_loading_enabled(): ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -527,6 +535,7 @@ public function test_loading_started_does_not_create_span_when_trace_loading_dis ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -563,6 +572,7 @@ public function test_metrics_collected_when_collect_metrics_enabled(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -603,6 +613,7 @@ public function test_metrics_include_dataframe_name_attribute(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -652,6 +663,7 @@ public function test_metrics_not_collected_when_collect_metrics_disabled(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -735,6 +747,7 @@ public function test_transformation_completed_finalizes_span(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -801,6 +814,7 @@ public function test_transformation_failed_logs_error_and_sets_span_status(): vo ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -872,6 +886,7 @@ public function test_transformation_started_creates_span_when_trace_transformati ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -909,6 +924,7 @@ public function test_transformation_started_does_not_create_span_when_trace_tran ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), @@ -957,6 +973,7 @@ public function test_optimizer_rules_are_logged(): void ); $telemetryContext = new TelemetryContext( + new PhpBackend(), $telemetry->logger('flow-php'), $telemetry->tracer('flow-php'), $telemetry->meter('flow-php'), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/ConsumptionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/ConsumptionTest.php index 66a0b872fd..9ddb9be2ad 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/ConsumptionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/ConsumptionTest.php @@ -4,18 +4,29 @@ namespace Flow\ETL\Tests\Unit\Dataset\Memory; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Dataset\Memory\Consumption; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; final class ConsumptionTest extends FlowTestCase { public function test_capturing_memory_consumption(): void { - $consumption = new Consumption(); + $consumption = new Consumption(new PhpBackend()); $consumption->capture(); static::assertGreaterThan(0, $consumption->max()->inBytes()); static::assertGreaterThan(0, $consumption->min()->inBytes()); } + + public function test_consumption_adds_the_backend_allocations(): void + { + $php = new Consumption(new PhpBackend()); + $native = new Consumption(new SpyBackend(1_048_576)); + + static::assertSame(1_048_576, $native->initial()->inBytes() - $php->initial()->inBytes()); + static::assertSame(1_048_576, $native->capture()->inBytes() - $php->capture()->inBytes()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InMemoryRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InMemoryRowsTest.php index 4aafa9a547..556b5bb14f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InMemoryRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InMemoryRowsTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Tests\Unit\Extractor; use Flow\ETL\Extractor\InMemoryRows; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Tests\FlowTestCase; use function array_keys; @@ -17,21 +16,15 @@ public function test_it_reads_the_source_again_on_every_call(): void { $rows = new InMemoryRows([['id' => 1], ['id' => 2]]); - static::assertEquals( - [new RawRowValues(['id' => 1]), new RawRowValues(['id' => 2])], - iterator_to_array($rows->values(), false), - ); - static::assertEquals( - [new RawRowValues(['id' => 1]), new RawRowValues(['id' => 2])], - iterator_to_array($rows->values(), false), - ); + static::assertEquals([['id' => 1], ['id' => 2]], iterator_to_array($rows->values(), false)); + static::assertEquals([['id' => 1], ['id' => 2]], iterator_to_array($rows->values(), false)); } public function test_positional_keys_are_named_like_the_hydrator_names_them(): void { static::assertSame( ['e00', 'e01'], - array_keys(iterator_to_array((new InMemoryRows([[1, 2]]))->values(), false)[0]->values), + array_keys(iterator_to_array((new InMemoryRows([[1, 2]]))->values(), false)[0]), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatedGroupsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatedGroupsTest.php index 5596db3603..2a498538e8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatedGroupsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatedGroupsTest.php @@ -38,7 +38,7 @@ public function test_it_accumulates_rows_of_the_same_key_into_one_group(): void $groups->accumulate(array_to_rows([['country' => 'PL', 'amount' => 30]], $input), flow_context(config())); /** @var list $batches */ - $batches = iterator_to_array($groups->flush(1000)); + $batches = iterator_to_array($groups->flush(1000, flow_context(config()))); static::assertCount(1, $batches); static::assertSame( @@ -62,7 +62,7 @@ public function test_the_flushed_batch_carries_the_shape_output_schema(): void $groups->accumulate(array_to_rows([['country' => 'PL', 'amount' => 10]], $input), flow_context(config())); /** @var list $batches */ - $batches = iterator_to_array($groups->flush(1000)); + $batches = iterator_to_array($groups->flush(1000, flow_context(config()))); static::assertEquals($shape->output, $batches[0]->schema()); static::assertEquals(schema(str_schema('country'), float_schema('amount_sum', nullable: true)), $shape->output); @@ -84,7 +84,10 @@ public function test_it_splits_the_flushed_groups_into_batches_of_the_requested_ static::assertSame( [2, 1], - array_map(static fn(Rows $batch): int => $batch->count(), iterator_to_array($groups->flush(2))), + array_map( + static fn(Rows $batch): int => $batch->count(), + iterator_to_array($groups->flush(2, flow_context(config()))), + ), ); } @@ -98,7 +101,7 @@ public function test_flushing_without_accumulating_yields_nothing(): void int_schema('amount'), ))); - static::assertSame([], iterator_to_array($groups->flush(1000))); + static::assertSame([], iterator_to_array($groups->flush(1000, flow_context(config())))); } public function test_a_row_missing_a_nullable_group_key_lands_in_the_null_group(): void @@ -116,7 +119,7 @@ public function test_a_row_missing_a_nullable_group_key_lands_in_the_null_group( ], $input), flow_context(config())); /** @var list $batches */ - $batches = iterator_to_array($groups->flush(1000)); + $batches = iterator_to_array($groups->flush(1000, flow_context(config()))); static::assertSame( [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php index d31f8ee0d1..5851f3fb0a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Join\HashJoin; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\SchemaDefinitionNotUniqueException; use Flow\ETL\Join\Comparison\All; use Flow\ETL\Join\Comparison\Any; @@ -36,6 +37,7 @@ public function test_any_comparison_falls_back_to_verifying_every_pair(): void $joiner = new Joiner( Expression::on(new Any(new Equal('id', 'user_id'), new Equal('email', 'contact'))), Join::inner, + new PhpBackend(), ); foreach ($joiner->join( @@ -87,6 +89,7 @@ public function test_all_with_any_hashes_by_the_equality_and_verifies_the_rest() ), ), Join::inner, + new PhpBackend(), ); foreach ($joiner->join( @@ -133,7 +136,7 @@ public function test_duplicated_right_rows_are_all_joined(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows([['id' => 1]], schema(int_schema('id'))))), @@ -158,7 +161,7 @@ public function test_inner_join_emits_every_matching_right_row(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -196,7 +199,7 @@ public function test_inner_join_drops_duplicated_right_join_columns(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'id']), Join::inner); + $joiner = new Joiner(join_on(['id' => 'id']), Join::inner, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -225,7 +228,7 @@ public function test_left_anti_join_keeps_left_row_on_hash_hit_without_match(): $joined = []; // int 1 and string "1" hash into the same bucket but are not identical - $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left_anti); + $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left_anti, new PhpBackend()); $right = static function (): Generator { yield array_to_rows([['user_id' => '2']], schema(str_schema('user_id'))); @@ -254,7 +257,7 @@ public function test_left_join_keeps_left_row_on_hash_hit_without_match(): void $joined = []; // int 1 and string "1" hash into the same bucket but are not identical - $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left); + $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -282,7 +285,7 @@ public function test_left_join_pads_unmatched_left_rows_with_nulls(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -317,7 +320,7 @@ public function test_prefix_collision_with_left_column_throws(): void $this->expectException(SchemaDefinitionNotUniqueException::class); $this->expectExceptionMessage('Entry definitions must be unique, duplicated entries: [left_name]'); - $joiner = new Joiner(join_on(['id' => 'user_id'], join_prefix: 'left_'), Join::inner); + $joiner = new Joiner(join_on(['id' => 'user_id'], join_prefix: 'left_'), Join::inner, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -341,7 +344,7 @@ public function test_swapped_inner_join_emits_the_same_rows(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -380,7 +383,7 @@ public function test_swapped_left_anti_join_emits_unmatched_left_rows_at_the_end $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left_anti); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left_anti, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))))), @@ -403,7 +406,7 @@ public function test_swapped_left_join_pads_unmatched_left_rows_at_the_end(): vo $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -442,7 +445,7 @@ public function test_swapped_left_join_with_empty_right_side_pads_every_left_row $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -468,7 +471,7 @@ public function test_swapped_right_join_pads_unmatched_right_rows_inline(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -503,7 +506,7 @@ public function test_right_join_emits_unmatched_right_rows_with_null_left_entrie $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new PhpBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -535,7 +538,7 @@ public function test_left_join_emits_a_schema_declaring_the_right_side_nullable( yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); $emitted = iterator_to_array( $joiner->join( @@ -568,7 +571,7 @@ public function test_right_join_emits_a_schema_declaring_the_left_side_nullable( yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new PhpBackend()); $emitted = iterator_to_array( $joiner->join( @@ -597,7 +600,7 @@ public function test_right_join_emits_a_schema_declaring_the_left_side_nullable( public function test_every_batch_of_a_multi_batch_left_side_shares_one_output_schema(): void { - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); $emitted = iterator_to_array( $joiner->join( @@ -635,7 +638,7 @@ public function test_a_padded_row_covers_a_right_column_no_source_row_carried(): yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); $joined = []; @@ -670,7 +673,7 @@ public function test_a_row_omitting_a_nullable_join_key_is_unmatched_rather_than yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); $joined = []; @@ -704,7 +707,7 @@ public function test_a_left_batch_wider_than_the_output_schema_is_projected_not_ yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); $joined = []; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CountingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CountingProcessorTest.php index 1f96fb1caa..9439d94826 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CountingProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CountingProcessorTest.php @@ -5,9 +5,11 @@ namespace Flow\ETL\Tests\Unit\Processor; use Flow\ETL\Processor\CountingProcessor; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\rows; @@ -50,4 +52,19 @@ public function test_bind_outputs_the_count_column_whatever_the_input(): void static::assertEquals(schema(int_schema('count')), $bound->output); static::assertEquals(new CountingProcessor(), $bound->step); } + + public function test_count_builds_with_the_configured_backend(): void + { + $backend = new SpyBackend(); + $batches = (static function () { + yield array_to_rows([['id' => 1]], schema(int_schema('id'))); + })(); + + iterator_to_array((new CountingProcessor())->process( + $batches, + flow_context(config_builder()->backend($backend)->build()), + )); + + static::assertGreaterThan(0, $backend->builders()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php index 59138350f6..8543ff5b67 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php @@ -15,11 +15,13 @@ use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\Processor\GroupByAggregationProcessor; use Flow\ETL\Tests\Context\GroupByContext; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\SpyBucketsStorage; use Flow\ETL\Tests\FlowTestCase; use Generator; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\count; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; @@ -338,4 +340,43 @@ public function test_a_bound_global_aggregate_with_input_emits_no_extra_row(): v static::assertCount(1, $result); static::assertSame([['amount_sum' => 30.0, 'amount_count' => 2]], $result[0]->toArray()); } + + public function test_output_builds_with_the_configured_backend(): void + { + $backend = new SpyBackend(); + $groupBy = new GroupBy(ref('category')); + $groupBy->aggregate(sum(ref('amount'))); + $buckets = new Buckets(new MemoryBuckets()); + $strategy = new HashBucketing( + [ref('category')], + 2, + new NativeHasher(), + new NativePHPRandomValueGenerator(), + 'group-by', + ); + $input = (static function (): Generator { + yield array_to_rows( + [['category' => 'a', 'amount' => 10], ['category' => 'b', 'amount' => 15]], + schema(str_schema('category'), int_schema('amount')), + ); + })(); + $metadata = []; + + foreach ($strategy->bucketize($input, $buckets->storage()) as $bucket) { + $buckets->add($bucket); + $metadata[] = rows(Bucket::schema(), $bucket->toRow()); + } + + iterator_to_array( + (new GroupByAggregationProcessor($groupBy, $buckets))->process( + (static function () use ($metadata): Generator { + yield from $metadata; + })(), + flow_context(config_builder()->backend($backend)->build()), + ), + preserve_keys: false, + ); + + static::assertGreaterThan(0, $backend->builders()); + } } 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 9094e7fcb4..1f2a72c1bd 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 @@ -12,6 +12,7 @@ use Flow\ETL\Join\Expression; use Flow\ETL\Join\Join; use Flow\ETL\Tests\Double\CountingExtractor; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\SpyBucketsStorage; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\HashJoinProcessorMother; @@ -19,6 +20,7 @@ use Flow\ETL\Tests\Mother\RowsMother; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\int_schema; @@ -656,4 +658,27 @@ public function test_the_right_side_is_pulled_through_a_frame_output(): void static::assertSame([['id' => 1, 'r_id' => 1, 'r_name' => 'Alice']], $batches[0]->toArray()); } + + public function test_join_output_builds_with_the_configured_backend(): void + { + $backend = new SpyBackend(); + $processor = HashJoinProcessorMother::grace( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], + schema(int_schema('user_id'), str_schema('name')), + ))), + Expression::on(['id' => 'user_id']), + Join::inner, + ); + $generator = (static function () { + yield array_to_rows([['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount'))); + })(); + + iterator_to_array( + $processor->process($generator, flow_context(config_builder()->backend($backend)->build())), + false, + ); + + static::assertGreaterThan(0, $backend->builders()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php index 98d4e1a7a2..c1f91e6c85 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php @@ -14,6 +14,7 @@ use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\MergeSortProcessor; use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\SpyBucketsStorage; use Flow\ETL\Tests\Double\ThrowingRemoveBucketsStorage; use Flow\ETL\Tests\FlowTestCase; @@ -23,6 +24,7 @@ use function array_merge; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -300,4 +302,29 @@ public function test_throws_when_merge_fan_in_below_one(): void 1000, ); } + + public function test_merge_builds_with_the_configured_backend(): void + { + $backend = new SpyBackend(); + $storage = new MemoryBuckets(); + $buckets = new Buckets($storage); + $context = flow_context(config_builder()->backend($backend)->build()); + $bucketing = new BucketingProcessor( + new SortedRunBucketing([ref('id')->asc()], 2, new NativePHPRandomValueGenerator()), + $buckets, + ); + $merge = new MergeSortProcessor( + refs(ref('id')->asc()), + $buckets, + new Buckets($storage), + new NativePHPRandomValueGenerator(), + ); + $input = (static function () { + yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); + })(); + + iterator_to_array($merge->process($bucketing->process($input, $context), $context), false); + + static::assertGreaterThan(0, $backend->builders()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RawRowValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RawRowValuesTest.php deleted file mode 100644 index 1b14ffeb16..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/RawRowValuesTest.php +++ /dev/null @@ -1,29 +0,0 @@ - 1]); - - static::assertSame(['id' => 1], $rowValues->values); - static::assertSame([], $rowValues->metadata); - } - - public function test_carries_per_value_metadata(): void - { - $metadata = Metadata::with('source', 'decoder'); - $rowValues = new RawRowValues(['id' => null], ['id' => $metadata]); - - static::assertSame(['id' => null], $rowValues->values); - static::assertSame(['id' => $metadata], $rowValues->metadata); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php index 70dd13a3d7..010107f1c5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php @@ -7,7 +7,7 @@ use Closure; use DateTimeImmutable; use DateTimeZone; -use Flow\ETL\Column\Php\ScalarColumn; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; @@ -1179,7 +1179,12 @@ public function test_from_rows_copies_views_of_two_batches_with_the_same_schema( $copied = rows($schema, $scalar->row(1), $constant->row(0), $scalar->row(0)); static::assertSame([['id' => 2], ['id' => 7], ['id' => 1]], $copied->toArray()); - static::assertInstanceOf(ScalarColumn::class, $copied->column('id')); + static::assertInstanceOf( + (new DefaultBackend()) + ->builder(int_schema('id')) + ->finish()::class, + $copied->column('id'), + ); } public function test_from_rows_reorders_and_hops_into_the_column_zone(): void @@ -1262,14 +1267,19 @@ public function test_project_shares_kept_columns(): void static::assertSame($rows->column('id'), $rows->project(schema(int_schema('id')))->column('id')); } - public function test_concat_of_a_constant_and_a_scalar_column_yields_php_columns(): void + public function test_concat_of_a_constant_and_a_scalar_column_yields_default_backend_columns(): void { $schema = schema(int_schema('id')); $constant = Rows::fromColumns($schema, ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], 2); $concatenated = $constant->concat(array_to_rows([['id' => 1]], $schema)); static::assertSame([['id' => 7], ['id' => 7], ['id' => 1]], $concatenated->toArray()); - static::assertInstanceOf(ScalarColumn::class, $concatenated->column('id')); + static::assertInstanceOf( + (new DefaultBackend()) + ->builder(int_schema('id')) + ->finish()::class, + $concatenated->column('id'), + ); } public function test_concat_refuses_a_zero_row_input_with_another_schema(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/ColumnTypesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/ColumnTypesTest.php index 1fe18e5146..485816cffd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/ColumnTypesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/ColumnTypesTest.php @@ -4,9 +4,7 @@ namespace Flow\ETL\Tests\Unit\Schema\Inference; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema; -use Flow\ETL\Schema\Metadata; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\ColumnTypesMother; use Flow\Types\Type; @@ -173,7 +171,7 @@ public function test_a_header_only_source_yields_every_name_as_nullable_string() public function test_a_name_met_only_in_a_row_is_appended_after_the_header_names(): void { $columns = ColumnTypesMother::fromStrings(['a', 'b']); - $columns->observe(new RawRowValues(['c' => '1'])); + $columns->observe(['c' => '1']); static::assertSame(['a', 'b', 'c'], array_keys($columns->schema(ColumnTypesMother::floor())->definitions())); } @@ -181,9 +179,9 @@ public function test_a_name_met_only_in_a_row_is_appended_after_the_header_names public function test_a_null_first_row_then_free_text_yields_optional_string(): void { $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['c' => null])); - $columns->observe(new RawRowValues(['c' => 'free text'])); - $columns->observe(new RawRowValues(['c' => '42'])); + $columns->observe(['c' => null]); + $columns->observe(['c' => 'free text']); + $columns->observe(['c' => '42']); static::assertEquals( new Schema(definition_from_type('c', type_optional(type_string()), nullable: true)), @@ -194,9 +192,8 @@ public function test_a_null_first_row_then_free_text_yields_optional_string(): v public function test_a_numeric_key_becomes_a_string_column_name(): void { $columns = ColumnTypesMother::fromStrings(); - // PHP re-keys a numeric column name to int; RawRowValues declares array, which cannot - // express that, so the fold has to survive an int key arriving through a documented-string array - $columns->observe(new RawRowValues(['1' => 'x'])); + // PHP re-keys a numeric column name to int, so the fold has to survive an int key + $columns->observe(['1' => 'x']); static::assertSame('1', $columns->schema(ColumnTypesMother::floor())->get('1')->entry()->name()); } @@ -204,9 +201,9 @@ public function test_a_numeric_key_becomes_a_string_column_name(): void public function test_a_saturated_string_column_widens_to_optional_string_on_a_later_null(): void { $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['c' => 'free text'])); - $columns->observe(new RawRowValues(['c' => null])); - $columns->observe(new RawRowValues(['c' => 'more text'])); + $columns->observe(['c' => 'free text']); + $columns->observe(['c' => null]); + $columns->observe(['c' => 'more text']); static::assertEquals( new Schema(definition_from_type('c', type_optional(type_string()), nullable: true)), @@ -222,7 +219,7 @@ public function test_a_source_with_no_names_and_no_rows_yields_an_empty_schema() public function test_all_strings_floors_every_scalar_column(): void { $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['a' => '1', 'b' => 'true', 'c' => '2024-01-01'])); + $columns->observe(['a' => '1', 'b' => 'true', 'c' => '2024-01-01']); static::assertEquals( new Schema( @@ -237,8 +234,8 @@ public function test_all_strings_floors_every_scalar_column(): void public function test_an_absent_key_is_read_as_null(): void { $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['a' => '1'])); - $columns->observe(new RawRowValues(['b' => 'x'])); + $columns->observe(['a' => '1']); + $columns->observe(['b' => 'x']); static::assertEquals( new Schema( @@ -252,8 +249,8 @@ public function test_an_absent_key_is_read_as_null(): void public function test_an_integer_column_is_declared_nullable(): void { $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['c' => '1'])); - $columns->observe(new RawRowValues(['c' => '2'])); + $columns->observe(['c' => '1']); + $columns->observe(['c' => '2']); $definition = $columns->schema(ColumnTypesMother::floor())->get('c'); @@ -264,9 +261,9 @@ public function test_an_integer_column_is_declared_nullable(): void public function test_an_optional_non_string_column_is_not_saturated(): void { $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['c' => '1'])); - $columns->observe(new RawRowValues(['c' => null])); - $columns->observe(new RawRowValues(['c' => '1.5'])); + $columns->observe(['c' => '1']); + $columns->observe(['c' => null]); + $columns->observe(['c' => '1.5']); static::assertEquals( new Schema(definition_from_type('c', type_optional(type_float()), nullable: true)), @@ -277,8 +274,8 @@ public function test_an_optional_non_string_column_is_not_saturated(): void public function test_from_column_types_reproduces_an_observed_fold(): void { $observed = ColumnTypesMother::fromStrings(['id', 'name']); - $observed->observe(new RawRowValues(['id' => '1', 'name' => 'a'])); - $observed->observe(new RawRowValues(['id' => '2', 'name' => null])); + $observed->observe(['id' => '1', 'name' => 'a']); + $observed->observe(['id' => '2', 'name' => null]); $computed = ColumnTypesMother::fromColumnTypes([ 'id' => type_optional(type_integer()), @@ -295,9 +292,9 @@ public function test_from_column_types_reproduces_an_observed_fold(): void public function test_from_column_types_merges_with_an_observed_fold(): void { $left = ColumnTypesMother::fromStrings(['a']); - $left->observe(new RawRowValues(['a' => '1'])); + $left->observe(['a' => '1']); $right = ColumnTypesMother::fromStrings(['a']); - $right->observe(new RawRowValues(['a' => '1.5', 'b' => 'x'])); + $right->observe(['a' => '1.5', 'b' => 'x']); static::assertEquals( $left->merge($right, true)->schema(ColumnTypesMother::floor()), @@ -311,7 +308,7 @@ public function test_from_column_types_merges_with_an_observed_fold(): void public function test_from_column_types_carries_the_row_count_into_merge(): void { $observed = ColumnTypesMother::fromStrings(); - $observed->observe(new RawRowValues(['a' => '1'])); + $observed->observe(['a' => '1']); static::assertSame( 8, @@ -322,11 +319,11 @@ public function test_from_column_types_carries_the_row_count_into_merge(): void public function test_merge_is_associative_over_three_partials(): void { $left = ColumnTypesMother::fromStrings(['a']); - $left->observe(new RawRowValues(['a' => '1'])); + $left->observe(['a' => '1']); $middle = ColumnTypesMother::fromStrings(['b']); - $middle->observe(new RawRowValues(['b' => 'x'])); + $middle->observe(['b' => 'x']); $right = ColumnTypesMother::fromStrings(['c']); - $right->observe(new RawRowValues(['a' => '1.5', 'c' => 'true'])); + $right->observe(['a' => '1.5', 'c' => 'true']); $leftAssociated = $left->merge($middle, true)->merge($right, true)->schema(ColumnTypesMother::floor()); $rightAssociated = $left->merge($middle->merge($right, true), true)->schema(ColumnTypesMother::floor()); @@ -362,10 +359,10 @@ public function test_merge_keeps_the_left_operands_name_order_then_appends_the_r public function test_merge_sums_the_row_counts_and_leaves_both_operands_alone(): void { $left = ColumnTypesMother::fromStrings(); - $left->observe(new RawRowValues(['a' => '1'])); - $left->observe(new RawRowValues(['a' => '2'])); + $left->observe(['a' => '1']); + $left->observe(['a' => '2']); $right = ColumnTypesMother::fromStrings(); - $right->observe(new RawRowValues(['a' => '3'])); + $right->observe(['a' => '3']); static::assertSame(3, $left->merge($right, true)->rows()); static::assertSame(2, $left->rows()); @@ -376,7 +373,7 @@ public function test_merge_takes_a_seeded_only_partial_as_the_identity_of_the_fo { $seeded = ColumnTypesMother::fromStrings(['a', 'b']); $observed = ColumnTypesMother::fromStrings(['a', 'b']); - $observed->observe(new RawRowValues(['a' => '1'])); + $observed->observe(['a' => '1']); $expected = new Schema( definition_from_type('a', type_integer(), nullable: true), @@ -390,9 +387,9 @@ public function test_merge_takes_a_seeded_only_partial_as_the_identity_of_the_fo public function test_merge_unions_disjoint_name_sets(): void { $left = ColumnTypesMother::fromStrings(); - $left->observe(new RawRowValues(['a' => '1'])); + $left->observe(['a' => '1']); $right = ColumnTypesMother::fromStrings(); - $right->observe(new RawRowValues(['b' => 'x'])); + $right->observe(['b' => 'x']); static::assertEquals( new Schema( @@ -413,9 +410,9 @@ public function test_merged_types_do_not_depend_on_the_order_of_the_two_partials Type $expected, ): void { $left = ColumnTypesMother::fromStrings(); - $left->observe(new RawRowValues(['c' => $leftValue])); + $left->observe(['c' => $leftValue]); $right = ColumnTypesMother::fromStrings(); - $right->observe(new RawRowValues(['c' => $rightValue])); + $right->observe(['c' => $rightValue]); $leftFirst = $left->merge($right, true)->schema(ColumnTypesMother::floor())->get('c')->type(); $rightFirst = $right->merge($left, true)->schema(ColumnTypesMother::floor())->get('c')->type(); @@ -433,9 +430,9 @@ public function test_merged_types_do_not_depend_on_the_order_of_the_two_partials public function test_merged_types_do_not_depend_on_the_order_for_container_partials(): void { $left = ColumnTypesMother::fromTypedValues(); - $left->observe(new RawRowValues(['c' => []])); + $left->observe(['c' => []]); $right = ColumnTypesMother::fromTypedValues(); - $right->observe(new RawRowValues(['c' => [1]])); + $right->observe(['c' => [1]]); static::assertTrue(type_equals( type_list(type_optional(type_integer())), @@ -447,23 +444,12 @@ public function test_merged_types_do_not_depend_on_the_order_for_container_parti )); } - public function test_metadata_never_reaches_the_schema(): void - { - $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['a' => '1'], ['a' => Metadata::empty()->add('k', 'v')])); - - static::assertEquals( - new Schema(definition_from_type('a', type_integer(), nullable: true)), - $columns->schema(ColumnTypesMother::floor()), - ); - } - public function test_null_never_reaches_the_ladder(): void { $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['c' => '1'])); - $columns->observe(new RawRowValues(['c' => null])); - $columns->observe(new RawRowValues(['c' => '2'])); + $columns->observe(['c' => '1']); + $columns->observe(['c' => null]); + $columns->observe(['c' => '2']); static::assertEquals( new Schema(definition_from_type('c', type_optional(type_integer()), nullable: true)), @@ -474,8 +460,8 @@ public function test_null_never_reaches_the_ladder(): void public function test_observing_a_column_name_absent_from_the_header_still_records_its_type(): void { $columns = ColumnTypesMother::fromStrings(['a']); - $columns->observe(new RawRowValues(['a' => 'free text', 'b' => '1'])); - $columns->observe(new RawRowValues(['a' => 'more text', 'b' => '2'])); + $columns->observe(['a' => 'free text', 'b' => '1']); + $columns->observe(['a' => 'more text', 'b' => '2']); static::assertEquals( new Schema( @@ -489,12 +475,12 @@ public function test_observing_a_column_name_absent_from_the_header_still_record public function test_padded_cells_are_read_as_text_because_cast_does_not_trim(): void { $padded = ColumnTypesMother::fromStrings(); - $padded->observe(new RawRowValues(['c' => ' 12 '])); - $padded->observe(new RawRowValues(['c' => '13'])); + $padded->observe(['c' => ' 12 ']); + $padded->observe(['c' => '13']); $clean = ColumnTypesMother::fromStrings(); - $clean->observe(new RawRowValues(['c' => '12'])); - $clean->observe(new RawRowValues(['c' => '13'])); + $clean->observe(['c' => '12']); + $clean->observe(['c' => '13']); static::assertEquals( new Schema(definition_from_type('c', type_string(), nullable: true)), @@ -512,9 +498,9 @@ public function test_rows_counts_observations_not_columns(): void static::assertSame(0, $columns->rows()); - $columns->observe(new RawRowValues(['a' => '1', 'b' => '2'])); - $columns->observe(new RawRowValues(['a' => '3'])); - $columns->observe(new RawRowValues([])); + $columns->observe(['a' => '1', 'b' => '2']); + $columns->observe(['a' => '3']); + $columns->observe([]); static::assertSame(3, $columns->rows()); } @@ -526,7 +512,7 @@ public function test_rows_counts_observations_not_columns(): void public function test_the_declared_type_fits_the_cell_that_produced_it(string $cell): void { $columns = ColumnTypesMother::fromStrings(); - $columns->observe(new RawRowValues(['c' => $cell])); + $columns->observe(['c' => $cell]); $definition = $columns->schema(ColumnTypesMother::floor())->get('c'); @@ -536,11 +522,11 @@ public function test_the_declared_type_fits_the_cell_that_produced_it(string $ce public function test_the_null_rung_is_read_as_text_because_the_cell_is_text(): void { $mixed = ColumnTypesMother::fromStrings(); - $mixed->observe(new RawRowValues(['c' => 'null'])); - $mixed->observe(new RawRowValues(['c' => '1'])); + $mixed->observe(['c' => 'null']); + $mixed->observe(['c' => '1']); $only = ColumnTypesMother::fromStrings(); - $only->observe(new RawRowValues(['c' => 'nil'])); + $only->observe(['c' => 'nil']); static::assertEquals( new Schema(definition_from_type('c', type_string(), nullable: true)), @@ -563,7 +549,7 @@ public function test_typed_values_fold_through_the_instance_of_narrower(array $v /** @var mixed $value */ foreach ($values as $value) { - $columns->observe(new RawRowValues(['c' => $value])); + $columns->observe(['c' => $value]); } static::assertEquals( @@ -582,7 +568,7 @@ public function test_widening_across_rows_of_one_column(array $values, Type $exp $columns = ColumnTypesMother::fromStrings(); foreach ($values as $value) { - $columns->observe(new RawRowValues(['c' => $value])); + $columns->observe(['c' => $value]); } static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/SchemaInferrerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/SchemaInferrerTest.php index b6b1a732b1..751059f34d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/SchemaInferrerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/SchemaInferrerTest.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Tests\Unit\Schema\Inference; -use Flow\ETL\Row\RawRowValues; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\InferredTypes; use Flow\ETL\Schema\Inference\SchemaInference; @@ -51,7 +50,7 @@ public static function budgets(): array * Heterogeneous on purpose: "a" widens integer -> float inside source 1, and source 2 introduces "c", so a * budget that stops early and a merge that drops a name are both observable. * - * @return list> + * @return list>> */ public static function threeSourcesOfTenRows(): array { @@ -71,7 +70,7 @@ public static function threeSourcesOfTenRows(): array $values['c'] = 'true'; } - $rows[] = new RawRowValues($values); + $rows[] = $values; } $sources[] = $rows; @@ -120,8 +119,8 @@ public function test_a_sample_that_sniffs_itself_is_not_asked_once_the_budget_is public function test_a_column_that_is_free_text_in_the_first_source_and_numeric_in_the_second_widens_to_string(): void { $fixture = [ - [new RawRowValues(['id' => '1', 'v' => 'free text']), new RawRowValues(['id' => '2', 'v' => 'more text'])], - [new RawRowValues(['id' => '3', 'v' => '42']), new RawRowValues(['id' => '4', 'v' => '43'])], + [['id' => '1', 'v' => 'free text'], ['id' => '2', 'v' => 'more text']], + [['id' => '3', 'v' => '42'], ['id' => '4', 'v' => '43']], ]; $inferrer = new SchemaInferrer( new SchemaInference(), @@ -148,8 +147,8 @@ public function test_a_row_less_source_does_not_spend_a_files_to_sniff_slot(): v { $sources = new RecordingSources([ [], - [new RawRowValues(['a' => '1', 'b' => 'x'])], - [new RawRowValues(['c' => '1'])], + [['a' => '1', 'b' => 'x']], + [['c' => '1']], ]); $schema = (new SchemaInferrer( @@ -163,7 +162,7 @@ public function test_a_row_less_source_does_not_spend_a_files_to_sniff_slot(): v public function test_a_single_generator_source_is_accepted(): void { - $sources = new RecordingSources([[new RawRowValues(['a' => '1'])]]); + $sources = new RecordingSources([[['a' => '1']]]); static::assertEquals( new Schema(definition_from_type('a', type_integer(), nullable: true)), @@ -332,7 +331,7 @@ public function test_sniff_seeds_the_names_it_is_handed_even_when_no_row_carries $partial = (new SchemaInferrer( new SchemaInference(), new StringTypeNarrower(InferredTypes::default()->toArray()), - ))->sniff(['ghost'], [new RawRowValues(['a' => '1'])], -1); + ))->sniff(['ghost'], [['a' => '1']], -1); static::assertSame(['ghost', 'a'], array_keys($partial->schema(ColumnTypesMother::floor())->definitions())); static::assertSame('string', $partial->schema(ColumnTypesMother::floor())->get('ghost')->type()->toString()); @@ -340,7 +339,7 @@ public function test_sniff_seeds_the_names_it_is_handed_even_when_no_row_carries public function test_sniff_observes_nothing_when_the_budget_is_already_spent(): void { - $sources = new RecordingSources([[new RawRowValues(['a' => '1'])]]); + $sources = new RecordingSources([[['a' => '1']]]); $partial = (new SchemaInferrer( new SchemaInference(), @@ -374,7 +373,7 @@ public function test_the_candidate_set_reaches_the_floor_through_infer(): void $schema = (new SchemaInferrer( new SchemaInference(types: new InferredTypes(type_integer(), type_string())), new StringTypeNarrower([type_integer(), type_string()]), - ))->infer([], [[new RawRowValues(['i' => '42', 'f' => '1.5', 'd' => '2024-01-01'])]]); + ))->infer([], [[['i' => '42', 'f' => '1.5', 'd' => '2024-01-01']]]); static::assertEquals( new Schema( @@ -389,8 +388,8 @@ public function test_the_candidate_set_reaches_the_floor_through_infer(): void public function test_union_by_name_over_sources_where_one_column_saturates_to_string(): void { $sources = new RecordingSources([ - [new RawRowValues(['id' => '1', 'v' => 'free text'])], - [new RawRowValues(['id' => '2', 'v' => '42', 'w' => '2024-01-01'])], + [['id' => '1', 'v' => 'free text']], + [['id' => '2', 'v' => '42', 'w' => '2024-01-01']], ]); static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php index 33a3d9953b..df3147f866 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php @@ -7,6 +7,7 @@ use Flow\ETL\Bucketing\BucketRun; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Row; use Flow\ETL\Sort\Merge\KWayMerge; @@ -42,7 +43,7 @@ public function test_merges_multiple_sorted_runs_ascending(): void ['id' => 9], ], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); static::assertSame( [1, 2, 3, 4, 5, 6, 7, 8, 9], @@ -64,7 +65,7 @@ public function test_merge_reads_each_run_through_its_own_storage(): void static::assertSame([], BucketsStorageContext::rows($spill->storage()->get('sort-merge-0'))); static::assertSame([], BucketsStorageContext::rows($merged->storage()->get('sort-run-0'))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); static::assertSame( [1, 2, 3, 4], @@ -91,7 +92,7 @@ public function test_merges_multiple_sorted_runs_descending(): void ['id' => 2], ], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->desc())); + $merge = new KWayMerge(refs(ref('id')->desc()), new PhpBackend()); static::assertSame( [8, 7, 5, 4, 2, 1], @@ -111,7 +112,7 @@ public function test_merges_runs_of_uneven_length(): void ], schema(int_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 4]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); static::assertSame( [1, 2, 3, 4], @@ -127,7 +128,7 @@ public function test_merges_non_numeric_values(): void $buckets->storage()->append('a', array_to_rows([['id' => 'a'], ['id' => 'c']], schema(str_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 'b'], ['id' => 'd']], schema(str_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); static::assertSame( ['a', 'b', 'c', 'd'], @@ -146,7 +147,7 @@ public function test_runs_under_different_schemas_are_conformed_to_the_first(): )); $buckets->storage()->append('b', array_to_rows([['id' => 2]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); static::assertSame( [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null]], @@ -165,7 +166,7 @@ public function test_single_run_passthrough(): void $buckets = new Buckets(new MemoryBuckets()); $buckets->storage()->append('a', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); static::assertSame( [1, 2], @@ -177,7 +178,7 @@ public function test_single_run_passthrough(): void public function test_empty_bucket_set_yields_nothing(): void { - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); static::assertSame([], BucketsStorageContext::rows($merge->merge([]))); } @@ -192,7 +193,7 @@ public function test_merged_rows_are_yielded_in_batches_of_batch_size(): void ], schema(int_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 2], ['id' => 4]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc()), batchSize: 2); + $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend(), batchSize: 2); $sizes = []; @@ -209,6 +210,6 @@ public function test_throws_when_batch_size_below_one(): void $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); // @mago-ignore analysis:invalid-argument - new KWayMerge(refs(ref('id')->asc()), batchSize: 0); + new KWayMerge(refs(ref('id')->asc()), new PhpBackend(), batchSize: 0); } } diff --git a/src/extension/arrow-ext/build.rs b/src/extension/arrow-ext/build.rs index 0f9cd4c10d..eb491f8fb4 100644 --- a/src/extension/arrow-ext/build.rs +++ b/src/extension/arrow-ext/build.rs @@ -67,7 +67,8 @@ fn git(args: &[&str]) -> Option { .filter(|stdout| !stdout.is_empty()) } -/// `0.43.0-107-gf998a45d0` (git describe) becomes `0.43.0+107.gf998a45d0`, semver build metadata Composer reads as 0.43.0. +/// `0.44.1-65-g4525c4adc` (git describe) becomes `0.45.0-dev+65.g4525c4adc`: commits past a tag are a pre-release of the +/// next minor, outside Composer's `<0.45` conflict of the libraries. A tag, or any other string, passes through. fn as_semver(describe: &str) -> String { let mut parts = describe.rsplitn(3, '-'); @@ -75,9 +76,15 @@ fn as_semver(describe: &str) -> String { (Some(hash), Some(distance), Some(tag)) if hash.starts_with('g') && !distance.is_empty() - && distance.bytes().all(|b| b.is_ascii_digit()) => + && distance.bytes().all(|b| b.is_ascii_digit()) + && distance != "0" => { - format!("{tag}+{distance}.{hash}") + let mut numbers = tag.split('.').map(|number| number.parse::().ok()); + + match (numbers.next().flatten(), numbers.next().flatten()) { + (Some(major), Some(minor)) => format!("{major}.{}.0-dev+{distance}.{hash}", minor + 1), + _ => describe.to_string(), + } } _ => describe.to_string(), } diff --git a/src/extension/arrow-ext/tests/phpt/038_extension_version.phpt b/src/extension/arrow-ext/tests/phpt/038_extension_version.phpt index 6f1f935c11..2bfd90d11c 100644 --- a/src/extension/arrow-ext/tests/phpt/038_extension_version.phpt +++ b/src/extension/arrow-ext/tests/phpt/038_extension_version.phpt @@ -1,8 +1,8 @@ --TEST-- -extension version is the release tag, or the last tag with commit distance and hash +extension version is the release tag, or the next minor's dev pre-release with commit distance and hash --FILE-- --EXPECT-- int(1) diff --git a/src/extension/flow-php-ext/Cargo.lock b/src/extension/flow-php-ext/Cargo.lock index cf93be0665..6c22e19ec1 100644 --- a/src/extension/flow-php-ext/Cargo.lock +++ b/src/extension/flow-php-ext/Cargo.lock @@ -19,6 +19,20 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "const-random", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -28,12 +42,90 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" +[[package]] +name = "arrow-array" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e5f6adeffdf587d7a31db5d2266189624b526730cd3627f9ff9fedae97ad584" +dependencies = [ + "ahash", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "chrono", + "half", + "hashbrown", + "num-complex", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrow-buffer" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "097d193003ce7995d5d087089069ec2a6e0187faf5a6f8c9f38af2645d987182" +dependencies = [ + "bytes", + "half", + "num-bigint", + "num-traits", +] + +[[package]] +name = "arrow-data" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba2f832eaeca24b8f26143dba750e42ee4ab51cf7d65e701ca9607cfda9f358" +dependencies = [ + "arrow-buffer", + "arrow-schema", + "half", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrow-schema" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10fab8d4563491417ba801fab29d205104d20d4bdf37bda6cd1cf425cff598cd" + +[[package]] +name = "arrow-select" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc58569193c2525915f3cc6310edba3792f1200f65d6e9ed330aa33e691493b8" +dependencies = [ + "ahash", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "num-traits", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + [[package]] name = "base64" version = "0.22.1" @@ -147,6 +239,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "num-traits", + "windows-link", +] + [[package]] name = "cipher" version = "0.5.2" @@ -180,6 +283,26 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + [[package]] name = "constant_time_eq" version = "0.4.2" @@ -235,6 +358,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.2.2" @@ -441,12 +570,30 @@ dependencies = [ "zlib-rs", ] +[[package]] +name = "flow-batch-frame" +version = "0.1.0" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "serde", + "serde_json", +] + [[package]] name = "flow_php" version = "0.0.0" dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", "ext-php-rs", "ext-php-rs-build", + "flow-batch-frame", "memchr", "serde", "serde_json", @@ -491,6 +638,17 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "getrandom" version = "0.3.4" @@ -522,6 +680,18 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -562,6 +732,30 @@ dependencies = [ "typenum", ] +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -654,6 +848,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -733,12 +933,50 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-bigint" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e7820bc0a80a0238e650327316f929ba18d5be054b647490a3a6a339f3e7c0" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1200,6 +1438,15 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "typed-path" version = "0.12.3" @@ -1288,6 +1535,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + [[package]] name = "wasip2" version = "1.0.4+wasi-0.2.12" @@ -1360,12 +1613,65 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -1381,6 +1687,26 @@ version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +[[package]] +name = "zerocopy" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" version = "1.9.0" diff --git a/src/extension/flow-php-ext/Cargo.toml b/src/extension/flow-php-ext/Cargo.toml index 26a2ef0c97..2288de06c5 100644 --- a/src/extension/flow-php-ext/Cargo.toml +++ b/src/extension/flow-php-ext/Cargo.toml @@ -7,10 +7,19 @@ publish = false crate-type = ["cdylib"] [dependencies] +arrow-array = "59" +arrow-buffer = "59" +arrow-data = "59" +arrow-schema = "59" +arrow-select = "59" ext-php-rs = "0.15" +flow-batch-frame = { path = "crates/flow-batch-frame" } memchr = "2" serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["raw_value"] } [build-dependencies] ext-php-rs-build = "0.1" + +[profile.release] +strip = true diff --git a/src/extension/flow-php-ext/build.rs b/src/extension/flow-php-ext/build.rs index 24b1b85636..1b7fbb4405 100644 --- a/src/extension/flow-php-ext/build.rs +++ b/src/extension/flow-php-ext/build.rs @@ -80,7 +80,8 @@ fn git(args: &[&str]) -> Option { .filter(|stdout| !stdout.is_empty()) } -/// `0.43.0-107-gf998a45d0` (git describe) becomes `0.43.0+107.gf998a45d0`, semver build metadata Composer reads as 0.43.0. +/// `0.44.1-65-g4525c4adc` (git describe) becomes `0.45.0-dev+65.g4525c4adc`: commits past a tag are a pre-release of the +/// next minor, outside Composer's `<0.45` conflict of the libraries. A tag, or any other string, passes through. fn as_semver(describe: &str) -> String { let mut parts = describe.rsplitn(3, '-'); @@ -88,9 +89,15 @@ fn as_semver(describe: &str) -> String { (Some(hash), Some(distance), Some(tag)) if hash.starts_with('g') && !distance.is_empty() - && distance.bytes().all(|b| b.is_ascii_digit()) => + && distance.bytes().all(|b| b.is_ascii_digit()) + && distance != "0" => { - format!("{tag}+{distance}.{hash}") + let mut numbers = tag.split('.').map(|number| number.parse::().ok()); + + match (numbers.next().flatten(), numbers.next().flatten()) { + (Some(major), Some(minor)) => format!("{major}.{}.0-dev+{distance}.{hash}", minor + 1), + _ => describe.to_string(), + } } _ => describe.to_string(), } diff --git a/src/extension/flow-php-ext/composer.json b/src/extension/flow-php-ext/composer.json index c21e562074..36039d089e 100644 --- a/src/extension/flow-php-ext/composer.json +++ b/src/extension/flow-php-ext/composer.json @@ -1,7 +1,7 @@ { "name": "flow-php/flow-php-ext", "type": "php-ext", - "description": "Flow PHP native extension (Rust) - Floe frame-body encoder/decoder for DataFrame Rows", + "description": "Flow PHP native extension (Rust) - native column backend and CSV reader", "keywords": ["serializer", "binary", "extension", "rust", "native", "dataframe"], "license": "MIT", "require": { @@ -10,7 +10,6 @@ "autoload": { "psr-4": { "Flow\\ETL\\Adapter\\CSV\\": "php/Flow/ETL/Adapter/CSV/", - "Flow\\ETL\\Row\\": "php/Flow/ETL/Row/", "Flow\\Floe\\": "php/Flow/Floe/" } }, diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/.gitattributes b/src/extension/flow-php-ext/crates/flow-batch-frame/.gitattributes new file mode 100644 index 0000000000..360f09ff9c --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/.gitattributes @@ -0,0 +1,5 @@ +# Exclude development files from distribution archives +/tests export-ignore +/target export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/.gitignore b/src/extension/flow-php-ext/crates/flow-batch-frame/.gitignore new file mode 100644 index 0000000000..b83d22266a --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/Cargo.lock b/src/extension/flow-php-ext/crates/flow-batch-frame/Cargo.lock new file mode 100644 index 0000000000..bddb682b52 --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/Cargo.lock @@ -0,0 +1,629 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "const-random", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + +[[package]] +name = "arrow-array" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e5f6adeffdf587d7a31db5d2266189624b526730cd3627f9ff9fedae97ad584" +dependencies = [ + "ahash", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "chrono", + "half", + "hashbrown", + "num-complex", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrow-buffer" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "097d193003ce7995d5d087089069ec2a6e0187faf5a6f8c9f38af2645d987182" +dependencies = [ + "bytes", + "half", + "num-bigint", + "num-traits", +] + +[[package]] +name = "arrow-data" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba2f832eaeca24b8f26143dba750e42ee4ab51cf7d65e701ca9607cfda9f358" +dependencies = [ + "arrow-buffer", + "arrow-schema", + "half", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrow-schema" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10fab8d4563491417ba801fab29d205104d20d4bdf37bda6cd1cf425cff598cd" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "cc" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "num-traits", + "windows-link", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "find-msvc-tools" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" + +[[package]] +name = "flow-batch-frame" +version = "0.1.0" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "serde", + "serde_json", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "num-bigint" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e7820bc0a80a0238e650327316f929ba18d5be054b647490a3a6a339f3e7c0" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "unicode-ident" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.6", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "zerocopy" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/Cargo.toml b/src/extension/flow-php-ext/crates/flow-batch-frame/Cargo.toml new file mode 100644 index 0000000000..492a33515e --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "flow-batch-frame" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] + +[dependencies] +arrow-array = "59" +arrow-buffer = "59" +arrow-data = "59" +arrow-schema = "59" +serde = { version = "1", features = ["derive"] } +serde_json = "1" diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs new file mode 100644 index 0000000000..14dc07c016 --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs @@ -0,0 +1,209 @@ +//! The Floe BATCH frame body (`FrameEncoder` / `FrameDecoder`), Noop codec only: every stored buffer is prefixed with +//! the i64 -1. +//! +//! ```text +//! V rowCount, V nodeCount, V bufferCount, nodeCount × (V length, V nullCount), bufferCount × (V offset, V stored), +//! zero padding to 8, buffer area: per non-empty buffer the i64 prefix and its bytes, each zero padded to 8 +//! ``` + +use arrow_data::ArrayData; + +use crate::column; +use crate::error::Error; +use crate::format::{write_u32, Reader}; +use crate::kind::Kind; +use crate::layout::{buffer_count, node_count, nodes, null_count_of}; + +const RAW: i64 = -1; + +pub fn encode_body(columns: &[(Kind, ArrayData)], row_count: u32) -> Result, Error> { + let mut node_words = Vec::new(); + let mut extents = Vec::new(); + let mut area: Vec = Vec::new(); + let mut node_total: u32 = 0; + let mut buffer_total: u32 = 0; + + for (index, (kind, data)) in columns.iter().enumerate() { + if data.len() as u64 != row_count as u64 { + return Err(Error::ColumnRows { + column: index, + rows: data.len() as u64, + frame_rows: row_count as u64, + }); + } + + let buffers = column::encode(data, kind)?; + let buffers: Vec<&[u8]> = buffers.iter().map(Vec::as_slice).collect(); + let null_count = match kind { + Kind::Null => row_count, + _ => null_count_of(buffers[0], row_count)?, + }; + let column_nodes = if node_count(kind) == 1 { + vec![(row_count, null_count)] + } else { + nodes(kind, row_count, null_count, &buffers)? + }; + + for (length, nulls) in column_nodes { + write_u32(&mut node_words, length); + write_u32(&mut node_words, nulls); + node_total += 1; + } + + for buffer in buffers { + buffer_total += 1; + + if buffer.is_empty() { + write_u32(&mut extents, 0); + write_u32(&mut extents, 0); + + continue; + } + + write_u32(&mut extents, area.len() as u32); + write_u32(&mut extents, (8 + buffer.len()) as u32); + area.extend_from_slice(&RAW.to_le_bytes()); + area.extend_from_slice(buffer); + pad8(&mut area); + } + } + + let mut body = Vec::with_capacity(12 + node_words.len() + extents.len() + 8 + area.len()); + write_u32(&mut body, row_count); + write_u32(&mut body, node_total); + write_u32(&mut body, buffer_total); + body.extend_from_slice(&node_words); + body.extend_from_slice(&extents); + pad8(&mut body); + body.extend_from_slice(&area); + + if body.len() as u64 > u32::MAX as u64 { + return Err(Error::FrameTooLarge { + bytes: body.len() as u64, + }); + } + + Ok(body) +} + +/// `FrameDecoder::decode()`'s checks in its order, columns by index. Returns the row count and one array per kind. +pub fn decode_body(body: &[u8], kinds: &[Kind]) -> Result<(u32, Vec), Error> { + let mut directory = Reader::new(body); + let row_count = directory.u32()?; + let node_total = directory.u32()?; + let buffer_total = directory.u32()?; + let expected_nodes: usize = kinds.iter().map(node_count).sum(); + let expected_buffers: usize = kinds.iter().map(buffer_count).sum(); + + if node_total as u64 != expected_nodes as u64 { + return Err(Error::FrameNodeCount { + frame: node_total as u64, + schema: expected_nodes as u64, + }); + } + + if buffer_total as u64 != expected_buffers as u64 { + return Err(Error::FrameBufferCount { + frame: buffer_total as u64, + schema: expected_buffers as u64, + }); + } + + let words_len = 2 * (expected_nodes + expected_buffers); + let area_start = (12 + 4 * words_len).div_ceil(8) * 8; + + if body.len() < area_start { + return Err(Error::DirectoryTruncated); + } + + let words: Vec = (0..words_len) + .map(|_| directory.u32()) + .collect::>()?; + let area = &body[area_start..]; + let mut node = 0; + let mut extent = 2 * expected_nodes; + let mut buffer = 0; + let mut columns = Vec::with_capacity(kinds.len()); + + for (index, kind) in kinds.iter().enumerate() { + let length = words[2 * node]; + let null_count = words[2 * node + 1]; + + if length != row_count { + return Err(Error::ColumnRows { + column: index, + rows: length as u64, + frame_rows: row_count as u64, + }); + } + + if null_count > length { + return Err(Error::ColumnNulls { + column: index, + nulls: null_count as u64, + rows: length as u64, + }); + } + + let mut buffers: Vec<&[u8]> = Vec::with_capacity(buffer_count(kind)); + + for _ in 0..buffer_count(kind) { + let offset = words[extent] as usize; + let stored = words[extent + 1] as usize; + + if stored != 0 { + if offset as u64 + stored as u64 > area.len() as u64 { + return Err(Error::BufferOutsideArea { + buffer, + area: area.len() as u64, + }); + } + + if stored < 8 { + return Err(Error::BufferShorterThanPrefix { buffer }); + } + + let prefix = + i64::from_le_bytes(area[offset..offset + 8].try_into().expect("8-byte slice")); + + if prefix != RAW { + return Err(Error::CompressedBuffer { buffer, prefix }); + } + + buffers.push(&area[offset + 8..offset + stored]); + } else { + buffers.push(&[]); + } + + buffer += 1; + extent += 2; + } + + let malformed = |error: Error| Error::MalformedColumn { + column: index, + error: Box::new(error), + }; + + if node_count(kind) == 1 { + node += 1; + } else { + for (derived_length, derived_nulls) in + nodes(kind, length, null_count, &buffers).map_err(malformed)? + { + if words[2 * node] != derived_length || words[2 * node + 1] != derived_nulls { + return Err(Error::NodesDisagree { column: index }); + } + + node += 1; + } + } + + columns.push(column::decode(kind, &buffers, row_count, null_count).map_err(malformed)?); + } + + Ok((row_count, columns)) +} + +fn pad8(bytes: &mut Vec) { + bytes.resize(bytes.len().div_ceil(8) * 8, 0); +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs new file mode 100644 index 0000000000..432eb24e5b --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs @@ -0,0 +1,572 @@ +//! One column's buffers in the canonical form of `Column::encode()`, and back (`Backend::decode()`). +//! +//! Canonical: validity '' when the rows hold no null, else packed LSB-first from bit 0 with zero padding; a null slot +//! zeroed (0, 0.0, bit 0, 16 zero bytes, offset not advanced, structure children null under a null parent); offsets +//! from 0 over exactly the rows' bytes and children, whatever slice or selection the array is. + +use arrow_array::cast::AsArray; +use arrow_array::types::{ + Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType, +}; +use arrow_array::{make_array, Array, ArrowPrimitiveType}; +use arrow_buffer::{Buffer, ToByteSlice}; +use arrow_data::ArrayData; +use arrow_schema::DataType; + +use crate::error::{Error, Of, Role, Values}; +use crate::kind::{data_type, Kind}; +use crate::layout::{buffer_count, node_count, nodes_at, null_count_of}; + +pub fn encode(data: &ArrayData, kind: &Kind) -> Result>, Error> { + let expected = data_type(kind); + + if data.data_type() != &expected { + return Err(Error::DataTypeMismatch { + expected, + actual: data.data_type().clone(), + }); + } + + let array = make_array(data.clone()); + let mut out = Vec::with_capacity(buffer_count(kind)); + encode_node( + array.as_ref(), + kind, + &Rows::Range { + start: 0, + len: array.len(), + }, + None, + &mut out, + ); + + Ok(out) +} + +/// `ColumnDecoder::decode()` + `PhpBackend::decode()`: the same refusals in the same order. The result's data type is +/// `data_type(kind)`. A top-level null under NOT NULL is not refused here (`Rows::fromColumns` does). +pub fn decode( + kind: &Kind, + buffers: &[&[u8]], + len: u32, + null_count: u32, +) -> Result { + let mut cursor = Cursor::new(buffers); + let data = decode_node(kind, 0, &mut cursor, len, null_count)?; + + if cursor.remaining() != 0 { + return Err(Error::LeftoverBuffers { + count: cursor.remaining(), + }); + } + + Ok(data) +} + +/// The rows of an array a node encodes, as logical indexes: the whole array or a slice, or the compacted children of +/// the valid list/map slots. +enum Rows { + Range { start: usize, len: usize }, + Indices(Vec), +} + +impl Rows { + fn len(&self) -> usize { + match self { + Rows::Range { len, .. } => *len, + Rows::Indices(indices) => indices.len(), + } + } + + fn at(&self, j: usize) -> usize { + match self { + Rows::Range { start, .. } => start + j, + Rows::Indices(indices) => indices[j], + } + } +} + +fn encode_node( + array: &dyn Array, + kind: &Kind, + rows: &Rows, + parent: Option<&[bool]>, + out: &mut Vec>, +) { + if let Kind::Null = kind { + return; + } + + let valid = effective_validity(array, rows, parent); + out.push(valid.as_deref().map_or_else(Vec::new, pack_bits)); + let valid = valid.as_deref(); + + match kind { + Kind::Null => unreachable!("returned above"), + Kind::Int64 => out.push(fixed::(array, rows, valid)), + Kind::Timestamp => out.push(fixed::(array, rows, valid)), + Kind::Duration => out.push(fixed::(array, rows, valid)), + Kind::Int32 => out.push(fixed::(array, rows, valid)), + Kind::Float64 => out.push(fixed::(array, rows, valid)), + Kind::Boolean => { + let values = array.as_boolean().values(); + let mut bits = vec![0u8; rows.len().div_ceil(8)]; + + for j in 0..rows.len() { + if is_valid(valid, j) && values.value(rows.at(j)) { + bits[j >> 3] |= 1 << (j & 7); + } + } + + out.push(bits); + } + Kind::Uuid => { + let values = array.as_fixed_size_binary(); + let mut bytes = Vec::with_capacity(rows.len() * 16); + + for j in 0..rows.len() { + if is_valid(valid, j) { + bytes.extend_from_slice(values.value(rows.at(j))); + } else { + bytes.extend_from_slice(&[0; 16]); + } + } + + out.push(bytes); + } + Kind::Bytes => { + let values = array.as_binary::(); + let offsets = values.value_offsets(); + let data = values.value_data(); + + if let (Rows::Range { start, len }, None) = (rows, valid) { + out.push(rebased(&offsets[*start..=start + len])); + out.push(data[offsets[*start] as usize..offsets[start + len] as usize].to_vec()); + } else { + let mut packed = Vec::with_capacity((rows.len() + 1) * 4); + let mut bytes = Vec::new(); + packed.extend_from_slice(&0u32.to_le_bytes()); + + for j in 0..rows.len() { + if is_valid(valid, j) { + let i = rows.at(j); + bytes + .extend_from_slice(&data[offsets[i] as usize..offsets[i + 1] as usize]); + } + + packed.extend_from_slice(&(bytes.len() as u32).to_le_bytes()); + } + + out.push(packed); + out.push(bytes); + } + } + Kind::List(element) => { + let list = array.as_list::(); + let (offsets, children) = compact(list.value_offsets(), rows, valid); + out.push(offsets); + encode_node(list.values().as_ref(), &element.kind, &children, None, out); + } + Kind::Map(key, value) => { + let map = array.as_map(); + let (offsets, children) = compact(map.value_offsets(), rows, valid); + out.push(offsets); + out.push(Vec::new()); + encode_node(map.keys().as_ref(), &key.kind, &children, None, out); + encode_node(map.values().as_ref(), &value.kind, &children, None, out); + } + Kind::Struct(fields) => { + let structure = array.as_struct(); + + for (i, field) in fields.iter().enumerate() { + encode_node(structure.column(i).as_ref(), &field.kind, rows, valid, out); + } + } + } +} + +/// The null of a row is its own or its parent structure's; `None` when every row is valid. +fn effective_validity( + array: &dyn Array, + rows: &Rows, + parent: Option<&[bool]>, +) -> Option> { + let nulls = array.nulls(); + + if nulls.is_none() && parent.is_none() { + return None; + } + + let valid: Vec = (0..rows.len()) + .map(|j| parent.is_none_or(|p| p[j]) && nulls.is_none_or(|n| n.is_valid(rows.at(j)))) + .collect(); + + if valid.iter().all(|v| *v) { + None + } else { + Some(valid) + } +} + +fn is_valid(valid: Option<&[bool]>, j: usize) -> bool { + valid.is_none_or(|v| v[j]) +} + +fn pack_bits(valid: &[bool]) -> Vec { + let mut bits = vec![0u8; valid.len().div_ceil(8)]; + + for (j, _) in valid.iter().enumerate().filter(|(_, v)| **v) { + bits[j >> 3] |= 1 << (j & 7); + } + + bits +} + +fn fixed(array: &dyn Array, rows: &Rows, valid: Option<&[bool]>) -> Vec { + let values = array.as_primitive::().values(); + + if let (Rows::Range { start, len }, None) = (rows, valid) { + return values[*start..start + len].to_byte_slice().to_vec(); + } + + let width = std::mem::size_of::(); + let mut bytes = Vec::with_capacity(rows.len() * width); + + for j in 0..rows.len() { + if is_valid(valid, j) { + bytes.extend_from_slice(values[rows.at(j)].to_byte_slice()); + } else { + bytes.resize(bytes.len() + width, 0); + } + } + + bytes +} + +/// Offsets from 0 over the valid rows' ranges (a null row's range is dropped), and the child rows those ranges select. +/// Compaction only shrinks an i32 array's ranges, so the offsets stay within i32. +fn compact(offsets: &[i32], rows: &Rows, valid: Option<&[bool]>) -> (Vec, Rows) { + if let (Rows::Range { start, len }, None) = (rows, valid) { + return ( + rebased(&offsets[*start..=start + len]), + Rows::Range { + start: offsets[*start] as usize, + len: (offsets[start + len] - offsets[*start]) as usize, + }, + ); + } + + let mut packed = Vec::with_capacity((rows.len() + 1) * 4); + let mut children = Vec::new(); + packed.extend_from_slice(&0u32.to_le_bytes()); + + for j in 0..rows.len() { + if is_valid(valid, j) { + let i = rows.at(j); + children.extend(offsets[i] as usize..offsets[i + 1] as usize); + } + + packed.extend_from_slice(&(children.len() as u32).to_le_bytes()); + } + + (packed, Rows::Indices(children)) +} + +fn rebased(offsets: &[i32]) -> Vec { + offsets + .iter() + .flat_map(|offset| ((offset - offsets[0]) as u32).to_le_bytes()) + .collect() +} + +struct Cursor<'b, 'a> { + buffers: &'b [&'a [u8]], + position: usize, +} + +impl<'b, 'a> Cursor<'b, 'a> { + fn new(buffers: &'b [&'a [u8]]) -> Self { + Self { + buffers, + position: 0, + } + } + + fn next(&mut self) -> Result<&'a [u8], Error> { + let buffer = self + .buffers + .get(self.position) + .ok_or(Error::BuffersExhausted)?; + self.position += 1; + + Ok(buffer) + } + + fn remaining(&self) -> usize { + self.buffers.len() - self.position + } +} + +fn decode_node( + kind: &Kind, + node: usize, + cursor: &mut Cursor<'_, '_>, + len: u32, + null_count: u32, +) -> Result { + if let Kind::List(_) | Kind::Map(_, _) | Kind::Struct(_) = kind { + let mut subtree = Vec::with_capacity(buffer_count(kind)); + + for _ in 0..buffer_count(kind) { + subtree.push(cursor.next()?); + } + + let nodes = nodes_at(kind, node, len, null_count, &subtree)?; + + return decode_nested( + kind, + node, + &mut Cursor::new(&subtree), + len, + null_count, + &nodes, + ); + } + + if let Kind::Null = kind { + if null_count != len { + return Err(Error::NullKindNullCount { + rows: len as u64, + null_count: null_count as u64, + }); + } + + return Ok(ArrayData::new_null(&DataType::Null, len as usize)); + } + + let nulls = validity(cursor.next()?, len, null_count)?; + let builder = ArrayData::builder(data_type(kind)) + .len(len as usize) + .null_bit_buffer(nulls); + let builder = match kind { + Kind::Int64 | Kind::Timestamp | Kind::Duration => { + builder.add_buffer(fixed_values(cursor.next()?, 8, len, Values::Int64)?) + } + Kind::Int32 => builder.add_buffer(fixed_values(cursor.next()?, 4, len, Values::Int32)?), + Kind::Float64 => builder.add_buffer(fixed_values(cursor.next()?, 8, len, Values::Float64)?), + Kind::Uuid => builder.add_buffer(fixed_values( + cursor.next()?, + 16, + len, + Values::FixedBinary16, + )?), + Kind::Boolean => { + let buffer = cursor.next()?; + let expected = (len as u64).div_ceil(8); + + if (buffer.len() as u64) < expected { + return Err(Error::ValuesLength { + values: Values::Boolean, + bytes: buffer.len() as u64, + expected, + rows: len as u64, + }); + } + + builder.add_buffer(Buffer::from_slice_ref(buffer)) + } + Kind::Bytes => { + let offsets = cursor.next()?; + let last = check_offsets(offsets, len, Of::Utf8)?; + let data = cursor.next()?; + + if last as u64 != data.len() as u64 { + return Err(Error::Utf8DataLength { + bytes: data.len() as u64, + last_offset: last as u64, + }); + } + + fits_i32(last)?; + + builder + .add_buffer(Buffer::from_slice_ref(offsets)) + .add_buffer(Buffer::from_slice_ref(data)) + } + Kind::Null | Kind::List(_) | Kind::Map(_, _) | Kind::Struct(_) => { + unreachable!("returned above") + } + }; + + builder.build().map_err(Error::Arrow) +} + +fn decode_nested( + kind: &Kind, + node: usize, + own: &mut Cursor<'_, '_>, + len: u32, + null_count: u32, + nodes: &[(u32, u32)], +) -> Result { + let nulls = validity(own.next()?, len, null_count)?; + let builder = ArrayData::builder(data_type(kind)) + .len(len as usize) + .null_bit_buffer(nulls); + + let builder = match kind { + Kind::List(element) => { + let offsets = own.next()?; + let last = check_offsets(offsets, len, Of::List)?; + let (length, nulls) = nodes[1]; + + if nulls > 0 && !element.optional && element.kind != Kind::Null { + return Err(Error::NestedNulls { + node: node + 1, + role: Role::ListElement, + nulls: nulls as u64, + }); + } + + let child = decode_node(&element.kind, node + 1, own, length, nulls)?; + fits_i32(last)?; + + builder + .add_buffer(Buffer::from_slice_ref(offsets)) + .add_child_data(child) + } + Kind::Map(key, value) => { + let offsets = own.next()?; + let last = check_offsets(offsets, len, Of::Map)?; + own.next()?; + let key_node = node + 2; + let value_node = key_node + node_count(&key.kind); + let (length, key_nulls) = nodes[key_node - node]; + let (_, value_nulls) = nodes[value_node - node]; + + if key_nulls > 0 { + return Err(Error::NestedNulls { + node: key_node, + role: Role::MapKey, + nulls: key_nulls as u64, + }); + } + + if value_nulls > 0 && !value.optional && value.kind != Kind::Null { + return Err(Error::NestedNulls { + node: value_node, + role: Role::MapValue, + nulls: value_nulls as u64, + }); + } + + let keys = decode_node(&key.kind, key_node, own, length, key_nulls)?; + let values = decode_node(&value.kind, value_node, own, length, value_nulls)?; + fits_i32(last)?; + let DataType::Map(entries, _) = data_type(kind) else { + unreachable!("a map kind has a map data type") + }; + let entries = ArrayData::builder(entries.data_type().clone()) + .len(length as usize) + .add_child_data(keys) + .add_child_data(values) + .build() + .map_err(Error::Arrow)?; + + builder + .add_buffer(Buffer::from_slice_ref(offsets)) + .add_child_data(entries) + } + Kind::Struct(fields) => { + let mut child_node = node + 1; + let mut children = Vec::with_capacity(fields.len()); + + for field in fields { + let (length, nulls) = nodes[child_node - node]; + children.push(decode_node(&field.kind, child_node, own, length, nulls)?); + child_node += node_count(&field.kind); + } + + builder.child_data(children) + } + _ => unreachable!("decode_nested takes a nested kind"), + }; + + builder.build().map_err(Error::Arrow) +} + +/// `Some` bitmap only when it holds a null: the canonical form omits it otherwise. +fn validity(bitmap: &[u8], len: u32, declared: u32) -> Result, Error> { + let derived = null_count_of(bitmap, len)?; + + if declared != derived { + return Err(Error::NullCountMismatch { + declared: declared as u64, + derived: derived as u64, + rows: len as u64, + }); + } + + Ok((derived > 0).then(|| Buffer::from_slice_ref(bitmap))) +} + +fn fixed_values(buffer: &[u8], width: u64, len: u32, values: Values) -> Result { + let expected = width * len as u64; + + if buffer.len() as u64 != expected { + return Err(Error::ValuesLength { + values, + bytes: buffer.len() as u64, + expected, + rows: len as u64, + }); + } + + Ok(Buffer::from_slice_ref(buffer)) +} + +/// `Offsets::unpack()`: exactly (len + 1) * 4 bytes, from 0, monotonic. Returns the last offset. +fn check_offsets(buffer: &[u8], len: u32, of: Of) -> Result { + let expected = (len as u64 + 1) * 4; + + if buffer.len() as u64 != expected { + return Err(Error::OffsetsLength { + of, + bytes: buffer.len() as u64, + expected, + rows: len as u64, + }); + } + + let offset = + |i: usize| u32::from_le_bytes(buffer[i * 4..i * 4 + 4].try_into().expect("4-byte slice")); + + if offset(0) != 0 { + return Err(Error::OffsetsStart { + of, + first: offset(0) as u64, + }); + } + + for i in 1..=len as usize { + if offset(i) < offset(i - 1) { + return Err(Error::OffsetsNotMonotonic { + of, + index: i as u64, + previous: offset(i - 1) as u64, + current: offset(i) as u64, + }); + } + } + + Ok(offset(len as usize)) +} + +/// Native offsets are i32 (D5): the PHP decoder takes them unsigned, so a last offset past i32::MAX is refused here. +fn fits_i32(last: u32) -> Result<(), Error> { + if last > i32::MAX as u32 { + return Err(Error::OffsetOverflow { last: last as u64 }); + } + + Ok(()) +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/error.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/error.rs new file mode 100644 index 0000000000..afc40edcc1 --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/error.rs @@ -0,0 +1,168 @@ +//! Every refusal the crate returns, as data. The wording belongs to the caller: flow_php renders each variant into the +//! message its pure-PHP twin throws, so a message change never moves this crate. + +use arrow_schema::{ArrowError, DataType}; + +/// The layout an offsets buffer belongs to. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Of { + List, + Map, + Utf8, +} + +/// The layout a fixed-width values buffer belongs to. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Values { + Int64, + Int32, + Float64, + Boolean, + FixedBinary16, +} + +/// The child of a list or map that holds nulls it may not. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Role { + ListElement, + MapKey, + MapValue, +} + +/// The part of a nested type JSON that is missing. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Part { + Element, + Key, + Value, + Base, +} + +/// `node` is a pre-order index in one column's node tree (the map entries node counts); `column` and `buffer` are +/// indexes in a frame body. +#[derive(Debug)] +pub enum Error { + SchemaJsonUtf8, + SchemaJson(serde_json::Error), + TypeJsonUtf8, + TypeJson(serde_json::Error), + MissingPart { + type_name: String, + part: Part, + }, + UnknownType { + type_name: String, + }, + BufferCount { + node: usize, + buffers: usize, + expected: usize, + }, + OffsetsLength { + of: Of, + bytes: u64, + expected: u64, + rows: u64, + }, + MapEntriesValidity { + bytes: u64, + }, + ValidityTooShort { + bytes: u64, + rows: u64, + }, + BuffersExhausted, + LeftoverBuffers { + count: usize, + }, + NullKindNullCount { + rows: u64, + null_count: u64, + }, + NullCountMismatch { + declared: u64, + derived: u64, + rows: u64, + }, + NestedNulls { + node: usize, + role: Role, + nulls: u64, + }, + OffsetsStart { + of: Of, + first: u64, + }, + OffsetsNotMonotonic { + of: Of, + index: u64, + previous: u64, + current: u64, + }, + ValuesLength { + values: Values, + bytes: u64, + expected: u64, + rows: u64, + }, + Utf8DataLength { + bytes: u64, + last_offset: u64, + }, + OffsetOverflow { + last: u64, + }, + DataTypeMismatch { + expected: DataType, + actual: DataType, + }, + Arrow(ArrowError), + FrameTooLarge { + bytes: u64, + }, + DirectoryTruncated, + FrameNodeCount { + frame: u64, + schema: u64, + }, + FrameBufferCount { + frame: u64, + schema: u64, + }, + ColumnRows { + column: usize, + rows: u64, + frame_rows: u64, + }, + ColumnNulls { + column: usize, + nulls: u64, + rows: u64, + }, + BufferOutsideArea { + buffer: usize, + area: u64, + }, + BufferShorterThanPrefix { + buffer: usize, + }, + CompressedBuffer { + buffer: usize, + prefix: i64, + }, + NodesDisagree { + column: usize, + }, + MalformedColumn { + column: usize, + error: Box, + }, +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Debug::fmt(self, f) + } +} + +impl std::error::Error for Error {} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/format.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/format.rs new file mode 100644 index 0000000000..27d2d475ff --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/format.rs @@ -0,0 +1,67 @@ +//! Floe wire constants and a bounds-checked little-endian reader. The canonical definitions live in the pure-PHP +//! `Flow\Floe\Format`; mirror any change there. + +use crate::error::Error; + +pub const MAGIC: &[u8; 4] = b"FLOE"; +pub const VERSION: u8 = 0x02; + +pub const FRAME_BATCH: u8 = 0x05; +pub const FRAME_FOOTER: u8 = 0x06; + +pub struct Reader<'a> { + data: &'a [u8], + pos: usize, +} + +impl<'a> Reader<'a> { + pub fn new(data: &'a [u8]) -> Self { + Self { data, pos: 0 } + } + + pub fn is_eof(&self) -> bool { + self.pos >= self.data.len() + } + + fn take(&mut self, len: usize) -> Result<&'a [u8], Error> { + let end = self + .pos + .checked_add(len) + .filter(|end| *end <= self.data.len()) + .ok_or(Error::DirectoryTruncated)?; + let slice = &self.data[self.pos..end]; + self.pos = end; + + Ok(slice) + } + + pub fn u8(&mut self) -> Result { + Ok(self.take(1)?[0]) + } + + pub fn u32(&mut self) -> Result { + let bytes = self.take(4)?; + + Ok(u32::from_le_bytes(bytes.try_into().expect("4-byte slice"))) + } + + pub fn i64(&mut self) -> Result { + let bytes = self.take(8)?; + + Ok(i64::from_le_bytes(bytes.try_into().expect("8-byte slice"))) + } + + pub fn f64(&mut self) -> Result { + let bytes = self.take(8)?; + + Ok(f64::from_le_bytes(bytes.try_into().expect("8-byte slice"))) + } + + pub fn bytes(&mut self, len: usize) -> Result<&'a [u8], Error> { + self.take(len) + } +} + +pub fn write_u32(out: &mut Vec, value: u32) { + out.extend_from_slice(&value.to_le_bytes()); +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs new file mode 100644 index 0000000000..bad14c5cb1 --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs @@ -0,0 +1,213 @@ +//! Flow schema and type JSON (`Schema::normalize()`, `Type::normalize()`) and the column kind a type is stored as. + +use std::sync::Arc; + +use arrow_schema::{DataType, Field as ArrowField, FieldRef, Fields, TimeUnit}; +use serde::Deserialize; + +use crate::error::{Error, Part}; + +#[derive(Deserialize, Default)] +pub struct TypeJson { + #[serde(rename = "type")] + pub type_: String, + element: Option>, + key: Option>, + value: Option>, + base: Option>, + #[serde(default)] + fields: Vec, + #[serde(default)] + zone: Option, + #[serde(default)] + class: Option, +} + +#[derive(Deserialize)] +pub struct StructureElementJson { + // ALWAYS a JSON string - PHP casts the name on normalize(). A JSON number here + // would fail parse_schema for the WHOLE schema, not just this field. + pub name: String, + #[serde(rename = "type")] + pub type_: TypeJson, + #[serde(default)] + pub optional: bool, +} + +impl TypeJson { + pub fn element(&self) -> Option<&TypeJson> { + self.element.as_deref() + } + + pub fn key(&self) -> Option<&TypeJson> { + self.key.as_deref() + } + + pub fn value(&self) -> Option<&TypeJson> { + self.value.as_deref() + } + + pub fn base(&self) -> Option<&TypeJson> { + self.base.as_deref() + } + + pub fn fields(&self) -> &[StructureElementJson] { + &self.fields + } + + pub fn zone(&self) -> Option<&[u8]> { + self.zone.as_deref().map(str::as_bytes) + } + + pub fn class(&self) -> Option<&[u8]> { + self.class.as_deref().map(str::as_bytes) + } + + fn is_optional(&self) -> bool { + self.type_ == "optional" + } +} + +#[derive(Deserialize)] +pub struct NormalizedDefinition { + #[serde(rename = "ref")] + pub name: String, + #[serde(rename = "type")] + pub type_: TypeJson, + pub nullable: bool, +} + +pub fn parse_schema(schema_json: &[u8]) -> Result, Error> { + let json = std::str::from_utf8(schema_json).map_err(|_| Error::SchemaJsonUtf8)?; + + serde_json::from_str(json).map_err(Error::SchemaJson) +} + +pub fn parse_type(type_json: &[u8]) -> Result { + let json = std::str::from_utf8(type_json).map_err(|_| Error::TypeJsonUtf8)?; + + serde_json::from_str(json).map_err(Error::TypeJson) +} + +/// How a column of a Flow type is stored. `Bytes` holds every string-like type (string, non-empty and numeric +/// strings, class strings, json, enum, timezone, xml, xml_element, html, html_element), `Timestamp` a datetime, +/// `Duration` a time and `Int32` a date. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Kind { + Null, + Boolean, + Int64, + Int32, + Float64, + Uuid, + Bytes, + Timestamp, + Duration, + List(Box), + Map(Box, Box), + Struct(Vec), +} + +/// A nested child. `optional` is the structure element's flag for a structure child, and whether the child type is +/// optional for a list element, map key or map value. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Field { + pub name: String, + pub kind: Kind, + pub optional: bool, +} + +pub fn kind(type_json: &[u8]) -> Result { + kind_of(&parse_type(type_json)?) +} + +pub fn kind_of(parsed: &TypeJson) -> Result { + let missing = |part: Part| Error::MissingPart { + type_name: parsed.type_.clone(), + part, + }; + let child = |name: &str, type_json: &TypeJson| -> Result, Error> { + Ok(Box::new(Field { + name: name.to_owned(), + kind: kind_of(type_json)?, + optional: type_json.is_optional(), + })) + }; + + Ok(match parsed.type_.as_str() { + "integer" | "positive_integer" => Kind::Int64, + "float" => Kind::Float64, + "boolean" => Kind::Boolean, + "string" | "non_empty_string" | "numeric-string" | "class_string" | "json" | "enum" + | "timezone" | "xml" | "xml_element" | "html" | "html_element" => Kind::Bytes, + "datetime" => Kind::Timestamp, + "date" => Kind::Int32, + "time" => Kind::Duration, + "uuid" => Kind::Uuid, + "null" => Kind::Null, + "list" => Kind::List(child( + "item", + parsed.element().ok_or_else(|| missing(Part::Element))?, + )?), + "map" => Kind::Map( + child("key", parsed.key().ok_or_else(|| missing(Part::Key))?)?, + child("value", parsed.value().ok_or_else(|| missing(Part::Value))?)?, + ), + "structure_v2" => Kind::Struct( + parsed + .fields() + .iter() + .map(|element| { + Ok(Field { + name: element.name.clone(), + kind: kind_of(&element.type_)?, + optional: element.optional, + }) + }) + .collect::>()?, + ), + "optional" => kind_of(parsed.base().ok_or_else(|| missing(Part::Base))?)?, + other => { + return Err(Error::UnknownType { + type_name: other.to_owned(), + }) + } + }) +} + +pub fn data_type(kind: &Kind) -> DataType { + match kind { + Kind::Null => DataType::Null, + Kind::Boolean => DataType::Boolean, + Kind::Int64 => DataType::Int64, + Kind::Int32 => DataType::Date32, + Kind::Float64 => DataType::Float64, + Kind::Uuid => DataType::FixedSizeBinary(16), + Kind::Bytes => DataType::Binary, + Kind::Timestamp => DataType::Timestamp(TimeUnit::Microsecond, Some("UTC".into())), + Kind::Duration => DataType::Duration(TimeUnit::Microsecond), + Kind::List(element) => DataType::List(field("item", &element.kind)), + Kind::Map(key, value) => DataType::Map( + Arc::new(ArrowField::new( + "entries", + DataType::Struct(Fields::from(vec![ + ArrowField::new("key", data_type(&key.kind), false), + ArrowField::new("value", data_type(&value.kind), true), + ])), + false, + )), + false, + ), + Kind::Struct(fields) => DataType::Struct( + fields + .iter() + .map(|child| field(&child.name, &child.kind)) + .collect(), + ), + } +} + +/// Nullable: only map entries and keys are not, and data_type() builds those itself. +pub fn field(name: &str, kind: &Kind) -> FieldRef { + Arc::new(ArrowField::new(name, data_type(kind), true)) +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/layout.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/layout.rs new file mode 100644 index 0000000000..a311f8dbd6 --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/layout.rs @@ -0,0 +1,158 @@ +//! The one node/buffer layout of a column (`Flow\ETL\Column\BufferLayout`): the pre-order nodes and buffers a kind +//! spans, and the child nodes derived from a column's buffers. + +use crate::error::{Error, Of}; +use crate::kind::Kind; + +pub fn node_count(kind: &Kind) -> usize { + match kind { + Kind::List(element) => 1 + node_count(&element.kind), + Kind::Map(key, value) => 2 + node_count(&key.kind) + node_count(&value.kind), + Kind::Struct(fields) => { + 1 + fields + .iter() + .map(|field| node_count(&field.kind)) + .sum::() + } + _ => 1, + } +} + +pub fn buffer_count(kind: &Kind) -> usize { + match kind { + Kind::Null => 0, + Kind::List(element) => 2 + buffer_count(&element.kind), + Kind::Map(key, value) => 3 + buffer_count(&key.kind) + buffer_count(&value.kind), + Kind::Struct(fields) => { + 1 + fields + .iter() + .map(|field| buffer_count(&field.kind)) + .sum::() + } + Kind::Bytes => 3, + _ => 2, + } +} + +/// Pre-order `(length, null count)` of one column's tree: the first node as given, every child derived from the +/// buffers - a null kind is `(length, length)`, list and map children span the last offset, a map entries node holds +/// no nulls and structure children span their parent. +pub fn nodes( + kind: &Kind, + len: u32, + null_count: u32, + buffers: &[&[u8]], +) -> Result, Error> { + nodes_at(kind, 0, len, null_count, buffers) +} + +pub(crate) fn nodes_at( + kind: &Kind, + node: usize, + len: u32, + null_count: u32, + buffers: &[&[u8]], +) -> Result, Error> { + let expected = buffer_count(kind); + + if buffers.len() != expected { + return Err(Error::BufferCount { + node, + buffers: buffers.len(), + expected, + }); + } + + let mut nodes = vec![(len, null_count)]; + let mut children: Vec<(&Kind, u32)> = Vec::new(); + let mut position = 1; + + match kind { + Kind::List(element) => { + children.push((&element.kind, last_offset(buffers[1], len, Of::List)?)); + position = 2; + } + Kind::Map(key, value) => { + let child_len = last_offset(buffers[1], len, Of::Map)?; + + if !buffers[2].is_empty() { + return Err(Error::MapEntriesValidity { + bytes: buffers[2].len() as u64, + }); + } + + nodes.push((child_len, 0)); + children.push((&key.kind, child_len)); + children.push((&value.kind, child_len)); + position = 3; + } + Kind::Struct(fields) => { + children.extend(fields.iter().map(|field| (&field.kind, len))); + } + _ => {} + } + + for (child, child_len) in children { + let child_buffers = &buffers[position..position + buffer_count(child)]; + position += child_buffers.len(); + let child_nulls = match child { + Kind::Null => child_len, + _ => null_count_of(child_buffers[0], child_len)?, + }; + + nodes.extend(nodes_at( + child, + node + nodes.len(), + child_len, + child_nulls, + child_buffers, + )?); + } + + Ok(nodes) +} + +/// `Validity::nullCount()`: '' holds no nulls; a bitmap may be longer than its rows. +pub fn null_count_of(bitmap: &[u8], len: u32) -> Result { + if bitmap.is_empty() { + return Ok(0); + } + + let needed = (len as usize).div_ceil(8); + + if bitmap.len() < needed { + return Err(Error::ValidityTooShort { + bytes: bitmap.len() as u64, + rows: len as u64, + }); + } + + let full = len as usize / 8; + let mut valid: u32 = bitmap[..full].iter().map(|byte| byte.count_ones()).sum(); + let tail = len % 8; + + if tail != 0 { + valid += (bitmap[full] & ((1u8 << tail) - 1)).count_ones(); + } + + Ok(len - valid) +} + +fn last_offset(offsets: &[u8], len: u32, of: Of) -> Result { + let expected = (len as u64 + 1) * 4; + + if offsets.len() as u64 != expected { + return Err(Error::OffsetsLength { + of, + bytes: offsets.len() as u64, + expected, + rows: len as u64, + }); + } + + let at = len as usize * 4; + + Ok(u32::from_le_bytes( + offsets[at..at + 4].try_into().expect("4-byte slice"), + )) +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/lib.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/lib.rs new file mode 100644 index 0000000000..e4f6facd54 --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/lib.rs @@ -0,0 +1,18 @@ +//! Flow's batch layout in Rust: one column's buffers in the canonical form of `Flow\ETL\Column\Column::encode()` and +//! back (`column`), and the Floe BATCH frame body around them (`body`). The pure-PHP classes in flow-php/etl are the +//! reference; this crate holds no PHP types and no message text. +//! +//! arrow-ext will hold a copy of this crate: keep both copies identical. + +// Floe is little-endian by construction; a big-endian host could never match its bytes. +#[cfg(target_endian = "big")] +compile_error!("flow-batch-frame only supports little-endian targets"); + +pub mod body; +pub mod column; +pub mod error; +pub mod format; +pub mod kind; +pub mod layout; + +pub use error::Error; diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs new file mode 100644 index 0000000000..0b25c6e1e5 --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs @@ -0,0 +1,236 @@ +mod common; + +use std::sync::Arc; + +use arrow_array::builder::{BinaryBuilder, Int64Builder, MapBuilder, MapFieldNames}; +use arrow_array::types::Int64Type; +use arrow_array::{Array, BinaryArray, Int64Array, ListArray, NullArray, StructArray}; +use arrow_buffer::NullBuffer; +use arrow_data::ArrayData; +use common::{hex, unhex}; +use flow_batch_frame::body::{decode_body, encode_body}; +use flow_batch_frame::error::Error; +use flow_batch_frame::kind::{kind, Kind}; + +fn kind_of(type_json: &str) -> Kind { + kind(type_json.as_bytes()).expect("a valid type JSON") +} + +/// FrameContext::directory(): the counts, then every node and extent word. +fn directory(body: &[u8]) -> Vec { + let word = + |i: usize| u32::from_le_bytes(body[i * 4..i * 4 + 4].try_into().expect("4-byte slice")); + + (0..3 + 2 * (word(1) + word(2)) as usize) + .map(word) + .collect() +} + +fn round_trips(body: &[u8], kinds: &[Kind]) { + let (row_count, arrays) = decode_body(body, kinds).expect("a decodable body"); + let columns: Vec<(Kind, ArrayData)> = kinds.iter().cloned().zip(arrays).collect(); + + assert_eq!( + body, + encode_body(&columns, row_count) + .expect("an encodable batch") + .as_slice() + ); +} + +fn worked_example() -> Vec<(Kind, ArrayData)> { + vec![ + ( + kind_of(r#"{"type":"integer"}"#), + Int64Array::from(vec![1, 2]).into_data(), + ), + ( + kind_of(r#"{"type":"string"}"#), + BinaryArray::from(vec![Some(b"ab".as_ref()), None]).into_data(), + ), + ] +} + +/// FrameEncoderTest.php:29-35. +#[test] +fn the_worked_example() { + let body = encode_body(&worked_example(), 2).expect("the worked example"); + + assert_eq!(152, body.len()); + assert_eq!( + "020000000200000005000000020000000000000002000000010000000000000000000000000000001800000018000000090000002800000014000000400000000a00000000000000ffffffffffffffff01000000000000000200000000000000ffffffffffffffff0100000000000000ffffffffffffffff00000000020000000200000000000000ffffffffffffffff6162000000000000", + hex(&body), + ); + round_trips( + &body, + &[worked_example()[0].0.clone(), worked_example()[1].0.clone()], + ); +} + +#[test] +fn a_list_with_a_null_slot() { + let kind = kind_of(r#"{"type":"list","element":{"type":"integer"}}"#); + let list = + ListArray::from_iter_primitive::(vec![Some(vec![Some(1), Some(2)]), None]); + let body = encode_body(&[(kind.clone(), list.into_data())], 2).expect("a list batch"); + + assert_eq!( + vec![2, 2, 4, 2, 1, 2, 0, 0, 9, 16, 20, 0, 0, 40, 24], + directory(&body) + ); + round_trips(&body, &[kind]); +} + +#[test] +fn a_map_entries_node_and_extent() { + let kind = kind_of(r#"{"type":"map","key":{"type":"string"},"value":{"type":"integer"}}"#); + let mut map = MapBuilder::new( + Some(MapFieldNames { + entry: "entries".into(), + key: "key".into(), + value: "value".into(), + }), + BinaryBuilder::new(), + Int64Builder::new(), + ); + + for row in [vec![("a", 1)], vec![("b", 2), ("c", 3)]] { + for (key, value) in row { + map.keys().append_value(key.as_bytes()); + map.values().append_value(value); + } + + map.append(true).expect("a map row"); + } + + let body = encode_body(&[(kind.clone(), map.finish().into_data())], 2).expect("a map batch"); + + assert_eq!( + vec![ + 2, 4, 8, 2, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 20, 0, 0, 0, 0, 24, 24, 48, 11, 0, 0, 64, 32 + ], + directory(&body), + ); + round_trips(&body, &[kind]); +} + +#[test] +fn a_structure_with_a_null_parent() { + let kind = + kind_of(r#"{"type":"structure_v2","fields":[{"name":"a","type":{"type":"integer"}}]}"#); + let structure = StructArray::try_new( + vec![Arc::new(arrow_schema::Field::new( + "a", + arrow_schema::DataType::Int64, + true, + ))] + .into(), + vec![Arc::new(Int64Array::from(vec![1, 5]))], + Some(NullBuffer::from(vec![true, false])), + ) + .expect("a valid struct"); + let body = encode_body(&[(kind.clone(), structure.into_data())], 2).expect("a structure batch"); + + assert_eq!( + vec![2, 2, 3, 2, 1, 2, 1, 0, 9, 16, 9, 32, 24], + directory(&body) + ); + round_trips(&body, &[kind]); +} + +#[test] +fn a_null_column_has_a_full_null_node_and_no_extent() { + let kind = kind_of(r#"{"type":"null"}"#); + let body = + encode_body(&[(kind.clone(), NullArray::new(2).into_data())], 2).expect("a null batch"); + + assert_eq!( + "020000000100000000000000020000000200000000000000", + hex(&body) + ); + round_trips(&body, &[kind]); +} + +#[test] +fn a_batch_without_columns_keeps_its_row_count() { + let body = encode_body(&[], 3).expect("a zero-column batch"); + + assert_eq!("03000000000000000000000000000000", hex(&body)); + round_trips(&body, &[]); +} + +#[test] +fn encode_refuses_a_column_of_another_length() { + assert!(matches!( + encode_body(&worked_example(), 3), + Err(Error::ColumnRows { + column: 0, + rows: 2, + frame_rows: 3 + }), + )); +} + +#[test] +fn decode_refuses_a_malformed_body() { + let kinds = [ + kind_of(r#"{"type":"integer"}"#), + kind_of(r#"{"type":"string"}"#), + ]; + let body = encode_body(&worked_example(), 2).expect("the worked example"); + let with = |at: usize, bytes: &[u8]| { + let mut corrupt = body.clone(); + corrupt[at..at + bytes.len()].copy_from_slice(bytes); + corrupt + }; + + assert!(matches!( + decode_body(&body[..11], &kinds), + Err(Error::DirectoryTruncated) + )); + assert!(matches!( + decode_body(&body[..40], &kinds), + Err(Error::DirectoryTruncated) + )); + assert!(matches!( + decode_body(&body, &kinds[..1]), + Err(Error::FrameNodeCount { + frame: 2, + schema: 1 + }), + )); + assert!(matches!( + decode_body(&with(12, &unhex("03000000")), &kinds), + Err(Error::ColumnRows { + column: 0, + rows: 3, + frame_rows: 2 + }), + )); + assert!(matches!( + decode_body(&with(24, &unhex("03000000")), &kinds), + Err(Error::ColumnNulls { + column: 1, + nulls: 3, + rows: 2 + }), + )); + assert!(matches!( + decode_body(&with(72, &unhex("0000000000000000")), &kinds), + Err(Error::CompressedBuffer { + buffer: 1, + prefix: 0 + }), + )); + assert!(matches!( + decode_body(&with(36, &unhex("ff000000")), &kinds), + Err(Error::BufferOutsideArea { + buffer: 1, + area: 80 + }), + )); + assert!(matches!( + decode_body(&with(24, &unhex("00000000")), &kinds), + Err(Error::MalformedColumn { column: 1, .. }), + )); +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs new file mode 100644 index 0000000000..222a768ad2 --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs @@ -0,0 +1,468 @@ +mod common; + +use std::sync::Arc; + +use arrow_array::builder::{BinaryBuilder, Int64Builder, MapBuilder, MapFieldNames}; +use arrow_array::types::Int64Type; +use arrow_array::{ + Array, ArrayRef, BinaryArray, BooleanArray, Date32Array, FixedSizeBinaryArray, Float64Array, + Int64Array, ListArray, NullArray, StructArray, TimestampMicrosecondArray, +}; +use arrow_buffer::NullBuffer; +use arrow_data::ArrayData; +use common::{hex, unhex}; +use flow_batch_frame::column::{decode, encode}; +use flow_batch_frame::error::{Error, Of, Role, Values}; +use flow_batch_frame::kind::{data_type, kind, Kind}; + +fn kind_of(type_json: &str) -> Kind { + kind(type_json.as_bytes()).expect("a valid type JSON") +} + +fn encoded_hex(data: &ArrayData, kind: &Kind) -> Vec { + encode(data, kind) + .expect("an encodable column") + .iter() + .map(|buffer| hex(buffer)) + .collect() +} + +fn decoded(kind: &Kind, buffers: &[&str], len: u32, null_count: u32) -> Result { + let buffers: Vec> = buffers.iter().map(|buffer| unhex(buffer)).collect(); + let buffers: Vec<&[u8]> = buffers.iter().map(Vec::as_slice).collect(); + + decode(kind, &buffers, len, null_count) +} + +fn raw(kind: &Kind, buffers: &[&[u8]], len: u32, null_count: u32) -> Error { + decode(kind, buffers, len, null_count).expect_err("a refused column") +} + +fn structure(fields: Vec<(&str, ArrayRef)>, nulls: Option>) -> ArrayData { + let arrow_fields = fields + .iter() + .map(|(name, array)| { + Arc::new(arrow_schema::Field::new( + *name, + array.data_type().clone(), + true, + )) + }) + .collect::>(); + + StructArray::try_new( + arrow_fields.into(), + fields.into_iter().map(|(_, array)| array).collect(), + nulls.map(NullBuffer::from), + ) + .expect("a valid struct") + .into_data() +} + +/// ColumnEncodeTest.php:40-105, and each case decodes back to itself. +fn cases() -> Vec<(&'static str, Kind, ArrayData, Vec<&'static str>)> { + let list = kind_of("{\"type\":\"list\",\"element\":{\"type\":\"integer\"}}"); + let list_rows = ListArray::from_iter_primitive::(vec![ + Some(vec![Some(1)]), + Some(vec![Some(2), Some(3)]), + None, + ]); + let mut map = MapBuilder::new( + Some(MapFieldNames { + entry: "entries".into(), + key: "key".into(), + value: "value".into(), + }), + BinaryBuilder::new(), + Int64Builder::new(), + ); + map.keys().append_value(b"a"); + map.values().append_value(1); + map.append(true).expect("a map row"); + + vec![ + ( + "integer", + kind_of("{\"type\":\"integer\"}"), + Int64Array::from(vec![1, 2]).into_data(), + vec!["", "01000000000000000200000000000000"], + ), + ( + "nullable string", + kind_of("{\"type\":\"string\"}"), + BinaryArray::from(vec![Some(b"ab".as_ref()), None]).into_data(), + vec!["01", "000000000200000002000000", "6162"], + ), + ( + "float", + kind_of("{\"type\":\"float\"}"), + Float64Array::from(vec![1.5]).into_data(), + vec!["", "000000000000f83f"], + ), + ( + "date before the epoch", + kind_of("{\"type\":\"date\"}"), + Date32Array::from(vec![-3]).into_data(), + vec!["", "fdffffff"], + ), + ( + "boolean", + kind_of("{\"type\":\"boolean\"}"), + BooleanArray::from(vec![true, false, true]).into_data(), + vec!["", "05"], + ), + ( + "nullable boolean with a null slot at 0", + kind_of("{\"type\":\"boolean\"}"), + BooleanArray::from(vec![Some(true), None, Some(true)]).into_data(), + vec!["05", "05"], + ), + ( + "uuid", + kind_of("{\"type\":\"uuid\"}"), + FixedSizeBinaryArray::try_from_iter(vec![unhex("6c2f1d4e8b3a4c5d9e6f0a1b2c3d4e5f")].into_iter()) + .expect("16 bytes") + .into_data(), + vec!["", "6c2f1d4e8b3a4c5d9e6f0a1b2c3d4e5f"], + ), + ( + "list with a null slot", + list.clone(), + ListArray::from_iter_primitive::(vec![ + Some(vec![Some(1)]), + None, + Some(vec![Some(2), Some(3)]), + ]) + .into_data(), + vec!["05", "00000000010000000100000003000000", "", "010000000000000002000000000000000300000000000000"], + ), + ( + "map", + kind_of("{\"type\":\"map\",\"key\":{\"type\":\"string\"},\"value\":{\"type\":\"integer\"}}"), + map.finish().into_data(), + vec!["", "0000000001000000", "", "", "0000000001000000", "61", "", "0100000000000000"], + ), + ( + "structure: the child bit is 0 under a null parent", + kind_of("{\"type\":\"structure_v2\",\"fields\":[{\"name\":\"x\",\"type\":{\"type\":\"integer\"}}]}"), + structure(vec![("x", Arc::new(Int64Array::from(vec![1, 7])))], Some(vec![true, false])), + vec!["01", "01", "01000000000000000000000000000000"], + ), + ( + "a null column has no buffers", + kind_of("{\"type\":\"null\"}"), + NullArray::new(3).into_data(), + vec![], + ), + ( + "a null element of a structure has no buffers", + kind_of( + "{\"type\":\"structure_v2\",\"fields\":[{\"name\":\"x\",\"type\":{\"type\":\"integer\"}},{\"name\":\"n\",\"type\":{\"type\":\"null\"}}]}", + ), + structure( + vec![("x", Arc::new(Int64Array::from(vec![1]))), ("n", Arc::new(NullArray::new(1)))], + None, + ), + vec!["", "", "0100000000000000"], + ), + ( + "an optional null element of a structure has no buffers", + kind_of( + "{\"type\":\"structure_v2\",\"fields\":[{\"name\":\"x\",\"type\":{\"type\":\"integer\"}},{\"name\":\"n\",\"type\":{\"type\":\"optional\",\"base\":{\"type\":\"null\"}}}]}", + ), + structure( + vec![("x", Arc::new(Int64Array::from(vec![1]))), ("n", Arc::new(NullArray::new(1)))], + None, + ), + vec!["", "", "0100000000000000"], + ), + ( + "a slice re-bases offsets and re-packs validity from bit 0", + list, + list_rows.slice(1, 2).into_data(), + vec!["01", "000000000200000002000000", "", "02000000000000000300000000000000"], + ), + ] +} + +#[test] +fn encodes_the_column_encode_test_cases() { + for (name, kind, data, expected) in cases() { + assert_eq!(expected, encoded_hex(&data, &kind), "{name}"); + } +} + +#[test] +fn decodes_the_column_encode_test_cases_back() { + for (name, kind, data, expected) in cases() { + let null_count = match kind { + Kind::Null => data.len() as u32, + _ => data.nulls().map_or(0, |nulls| nulls.null_count() as u32), + }; + let decoded = decoded(&kind, &expected, data.len() as u32, null_count).expect(name); + + assert_eq!(&data_type(&kind), decoded.data_type(), "{name}"); + assert_eq!(expected, encoded_hex(&decoded, &kind), "{name}"); + } +} + +#[test] +fn a_selection_under_a_null_list_slot_is_compacted() { + let kind = kind_of("{\"type\":\"list\",\"element\":{\"type\":\"string\"}}"); + let strings = BinaryArray::from(vec![b"a".as_ref(), b"bc", b"d"]); + let offsets = arrow_buffer::OffsetBuffer::new(vec![0, 1, 2, 3].into()); + let field = Arc::new(arrow_schema::Field::new( + "item", + arrow_schema::DataType::Binary, + true, + )); + let list = ListArray::new( + field, + offsets, + Arc::new(strings), + Some(NullBuffer::from(vec![true, false, true])), + ); + + assert_eq!( + vec![ + "05", + "00000000010000000100000002000000", + "", + "000000000100000002000000", + "6164" + ], + encoded_hex(&list.into_data(), &kind), + ); +} + +#[test] +fn bytes_that_are_not_utf8_round_trip() { + let kind = kind_of("{\"type\":\"string\"}"); + let data = BinaryArray::from(vec![b"a\xFFb".as_ref()]).into_data(); + let buffers = encoded_hex(&data, &kind); + let buffers: Vec<&str> = buffers.iter().map(String::as_str).collect(); + + assert_eq!(vec!["", "0000000003000000", "61ff62"], buffers); + assert_eq!( + b"a\xFFb", + decoded(&kind, &buffers, 1, 0) + .expect("a binary column") + .buffers()[1] + .as_slice(), + ); +} + +#[test] +fn encode_refuses_a_foreign_data_type() { + let kind = kind_of("{\"type\":\"datetime\",\"zone\":\"UTC\"}"); + + assert!(matches!( + encode(&TimestampMicrosecondArray::from(vec![1]).into_data(), &kind), + Err(Error::DataTypeMismatch { .. }), + )); +} + +/// PhpBackendTest.php:454-556. +#[test] +fn decode_refuses_corrupt_buffers() { + let int = kind_of("{\"type\":\"integer\"}"); + let string = kind_of("{\"type\":\"string\"}"); + let map = kind_of( + "{\"type\":\"map\",\"key\":{\"type\":\"string\"},\"value\":{\"type\":\"integer\"}}", + ); + let null = kind_of("{\"type\":\"null\"}"); + + assert!(matches!(raw(&int, &[b""], 1, 0), Error::BuffersExhausted)); + assert!(matches!( + raw(&int, &[b"", b"\x01\x00"], 1, 0), + Error::ValuesLength { + values: Values::Int64, + bytes: 2, + expected: 8, + rows: 1 + }, + )); + assert!(matches!( + raw( + &string, + &[b"", b"\x01\x00\x00\x00\x02\x00\x00\x00", b"ab"], + 1, + 0 + ), + Error::OffsetsStart { + of: Of::Utf8, + first: 1 + }, + )); + assert!(matches!( + raw( + &string, + &[ + b"", + b"\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00", + b"ab" + ], + 2, + 0 + ), + Error::OffsetsNotMonotonic { + of: Of::Utf8, + index: 2, + previous: 2, + current: 1 + }, + )); + assert!(matches!( + raw( + &string, + &[b"", b"\x00\x00\x00\x00\x03\x00\x00\x00", b"ab"], + 1, + 0 + ), + Error::Utf8DataLength { + bytes: 2, + last_offset: 3 + }, + )); + assert!(matches!( + raw( + &map, + &[ + b"", + b"\x00\x00\x00\x00\x00\x00\x00\x00", + b"\x01", + b"", + b"\x00\x00\x00\x00", + b"", + b"", + b"" + ], + 1, + 0 + ), + Error::MapEntriesValidity { bytes: 1 }, + )); + assert!(matches!( + raw(&int, &[b"\x01", &[0; 16]], 2, 0), + Error::NullCountMismatch { + declared: 0, + derived: 1, + rows: 2 + }, + )); + assert!(matches!( + raw(&int, &[b"", b""], 9, 0), + Error::ValuesLength { + values: Values::Int64, + bytes: 0, + expected: 72, + rows: 9 + }, + )); + assert!(matches!( + raw(&null, &[], 2, 1), + Error::NullKindNullCount { + rows: 2, + null_count: 1 + } + )); + assert!(matches!( + raw(&int, &[b"", b"\x01\x00\x00\x00\x00\x00\x00\x00", b""], 1, 0), + Error::LeftoverBuffers { count: 1 }, + )); + assert!(matches!( + raw(&int, &[b"\x01", &[0; 72]], 9, 0), + Error::ValidityTooShort { bytes: 1, rows: 9 }, + )); + assert!(matches!( + raw(&string, &[b"", b"\x00\x00", b""], 1, 0), + Error::OffsetsLength { + of: Of::Utf8, + bytes: 2, + expected: 8, + rows: 1 + }, + )); +} + +/// ColumnDecoderTest.php: a list element or map value holds nulls only when optional or of the null kind, a map key +/// never, a structure child always may. +#[test] +fn decode_refuses_nested_nulls_where_the_type_forbids_them() { + let one_null_child = [ + b"".as_ref(), + b"\x00\x00\x00\x00\x01\x00\x00\x00", + b"\x00", + &[0; 8], + ]; + + assert!(matches!( + raw( + &kind_of("{\"type\":\"list\",\"element\":{\"type\":\"integer\"}}"), + &one_null_child, + 1, + 0 + ), + Error::NestedNulls { + node: 1, + role: Role::ListElement, + nulls: 1 + }, + )); + assert!(decode( + &kind_of("{\"type\":\"list\",\"element\":{\"type\":\"optional\",\"base\":{\"type\":\"integer\"}}}"), + &one_null_child, + 1, + 0, + ) + .is_ok()); + assert!(decode( + &kind_of("{\"type\":\"list\",\"element\":{\"type\":\"null\"}}"), + &[b"".as_ref(), b"\x00\x00\x00\x00\x02\x00\x00\x00"], + 1, + 0, + ) + .is_ok()); + + let entries = + |key_validity: &'static [u8], value_validity: &'static [u8]| -> [&'static [u8]; 7] { + [ + b"", + b"\x00\x00\x00\x00\x01\x00\x00\x00", + b"", + key_validity, + &[0; 8], + value_validity, + &[0; 8], + ] + }; + let map = kind_of( + "{\"type\":\"map\",\"key\":{\"type\":\"integer\"},\"value\":{\"type\":\"integer\"}}", + ); + let optional_values = + kind_of("{\"type\":\"map\",\"key\":{\"type\":\"integer\"},\"value\":{\"type\":\"optional\",\"base\":{\"type\":\"integer\"}}}"); + + assert!(matches!( + raw(&map, &entries(b"\x00", b""), 1, 0), + Error::NestedNulls { + node: 2, + role: Role::MapKey, + nulls: 1 + }, + )); + assert!(matches!( + raw(&map, &entries(b"", b"\x00"), 1, 0), + Error::NestedNulls { + node: 3, + role: Role::MapValue, + nulls: 1 + }, + )); + assert!(decode(&optional_values, &entries(b"", b"\x00"), 1, 0).is_ok()); + + let structure = kind_of( + "{\"type\":\"structure_v2\",\"fields\":[{\"name\":\"x\",\"type\":{\"type\":\"integer\"}}]}", + ); + + assert!(decode(&structure, &[b"".as_ref(), b"\x00", &[0; 8]], 1, 0).is_ok()); +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/common/mod.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/common/mod.rs new file mode 100644 index 0000000000..a9dfa5a5ca --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/common/mod.rs @@ -0,0 +1,10 @@ +pub fn hex(bytes: &[u8]) -> String { + bytes.iter().map(|byte| format!("{byte:02x}")).collect() +} + +pub fn unhex(hex: &str) -> Vec { + (0..hex.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).expect("hex digit pair")) + .collect() +} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/kind.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/kind.rs new file mode 100644 index 0000000000..fa6e8ff0fe --- /dev/null +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/kind.rs @@ -0,0 +1,143 @@ +use arrow_data::ArrayData; +use flow_batch_frame::column::{decode, encode}; +use flow_batch_frame::error::{Error, Part}; +use flow_batch_frame::kind::{data_type, kind, kind_of, parse_schema, parse_type, Field, Kind}; + +/// The footer schema of FloeGoldenTest's `v2/all-entry-types.floe`. +const GOLDEN_SCHEMA: &str = r#"[{"ref":"int","type":{"type":"integer"},"nullable":false,"metadata":[]},{"ref":"int_min","type":{"type":"integer"},"nullable":false,"metadata":[]},{"ref":"int_max","type":{"type":"integer"},"nullable":false,"metadata":[]},{"ref":"float","type":{"type":"float"},"nullable":false,"metadata":[]},{"ref":"bool","type":{"type":"boolean"},"nullable":false,"metadata":[]},{"ref":"string","type":{"type":"string"},"nullable":false,"metadata":[]},{"ref":"string_binary","type":{"type":"string"},"nullable":false,"metadata":[]},{"ref":"string_unicode","type":{"type":"string"},"nullable":false,"metadata":[]},{"ref":"string_null","type":{"type":"string"},"nullable":true,"metadata":[]},{"ref":"string_from_null","type":{"type":"null"},"nullable":true,"metadata":[]},{"ref":"datetime_immutable","type":{"type":"datetime","zone":"Europe\/Warsaw"},"nullable":false,"metadata":[]},{"ref":"datetime_mutable","type":{"type":"datetime","zone":"America\/New_York"},"nullable":false,"metadata":[]},{"ref":"datetime_before_epoch","type":{"type":"datetime","zone":"UTC"},"nullable":false,"metadata":[]},{"ref":"date","type":{"type":"date"},"nullable":false,"metadata":[]},{"ref":"time","type":{"type":"time"},"nullable":false,"metadata":[]},{"ref":"uuid","type":{"type":"uuid"},"nullable":false,"metadata":[]},{"ref":"json","type":{"type":"json"},"nullable":false,"metadata":[]},{"ref":"json_object","type":{"type":"json"},"nullable":false,"metadata":[]},{"ref":"enum_backed","type":{"type":"enum","class":"Flow\\ETL\\Tests\\Fixtures\\Enum\\BackedStringEnum"},"nullable":false,"metadata":[]},{"ref":"enum_basic","type":{"type":"enum","class":"Flow\\ETL\\Tests\\Fixtures\\Enum\\BasicEnum"},"nullable":false,"metadata":[]},{"ref":"list","type":{"type":"list","element":{"type":"integer"}},"nullable":false,"metadata":[]},{"ref":"map","type":{"type":"map","key":{"type":"string"},"value":{"type":"integer"}},"nullable":false,"metadata":[]},{"ref":"structure","type":{"type":"structure_v2","fields":[{"name":"street","type":{"type":"string"},"optional":false},{"name":"nested","type":{"type":"structure_v2","fields":[{"name":"count","type":{"type":"integer"},"optional":false},{"name":"tags","type":{"type":"list","element":{"type":"string"}},"optional":false}]},"optional":false}]},"nullable":false,"metadata":[]},{"ref":"structure_interleaved","type":{"type":"structure_v2","fields":[{"name":"z","type":{"type":"integer"},"optional":false},{"name":"a","type":{"type":"string"},"optional":true},{"name":"b","type":{"type":"string"},"optional":false}]},"nullable":false,"metadata":[]},{"ref":"xml","type":{"type":"xml"},"nullable":false,"metadata":[]},{"ref":"xml_element","type":{"type":"xml_element"},"nullable":false,"metadata":[]}]"#; + +fn field(name: &str, kind: Kind, optional: bool) -> Field { + Field { + name: name.to_owned(), + kind, + optional, + } +} + +#[test] +fn parses_a_golden_footer_schema() { + let definitions = parse_schema(GOLDEN_SCHEMA.as_bytes()).expect("the golden schema"); + + assert_eq!(26, definitions.len()); + assert_eq!("string_null", definitions[8].name); + assert!(definitions[8].nullable); + assert_eq!( + Some(b"Europe/Warsaw".as_ref()), + definitions[10].type_.zone() + ); + assert_eq!( + Some(br"Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum".as_ref()), + definitions[18].type_.class() + ); + assert_eq!( + Kind::Struct(vec![ + field("z", Kind::Int64, false), + field("a", Kind::Bytes, true), + field("b", Kind::Bytes, false), + ]), + kind_of(&definitions[23].type_).expect("a structure"), + ); +} + +#[test] +fn refuses_schema_and_type_json_it_cannot_read() { + assert!(matches!( + parse_schema(b"[\xFF]"), + Err(Error::SchemaJsonUtf8) + )); + assert!(matches!(parse_schema(b"[{"), Err(Error::SchemaJson(_)))); + assert!(matches!(parse_type(b"\xFF"), Err(Error::TypeJsonUtf8))); + assert!(matches!(parse_type(b"{}"), Err(Error::TypeJson(_)))); +} + +#[test] +fn refuses_a_type_without_a_column_kind() { + assert!(matches!( + kind(br#"{"type":"mixed"}"#), + Err(Error::UnknownType { type_name }) if type_name == "mixed", + )); + assert!(matches!( + kind(br#"{"type":"list"}"#), + Err(Error::MissingPart { type_name, part: Part::Element }) if type_name == "list", + )); + assert!(matches!( + kind(br#"{"type":"map","key":{"type":"string"}}"#), + Err(Error::MissingPart { + part: Part::Value, + .. + }), + )); + assert!(matches!( + kind(br#"{"type":"optional"}"#), + Err(Error::MissingPart { + part: Part::Base, + .. + }) + )); +} + +/// Every Definition's `Schema::normalize()` type JSON. +fn definitions() -> Vec<(&'static str, Kind)> { + vec![ + (r#"{"type":"integer"}"#, Kind::Int64), + (r#"{"type":"float"}"#, Kind::Float64), + (r#"{"type":"boolean"}"#, Kind::Boolean), + (r#"{"type":"string"}"#, Kind::Bytes), + (r#"{"type":"datetime","zone":"UTC"}"#, Kind::Timestamp), + (r#"{"type":"date"}"#, Kind::Int32), + (r#"{"type":"time"}"#, Kind::Duration), + (r#"{"type":"uuid"}"#, Kind::Uuid), + (r#"{"type":"json"}"#, Kind::Bytes), + (r#"{"type":"enum","class":"E"}"#, Kind::Bytes), + (r#"{"type":"timezone"}"#, Kind::Bytes), + (r#"{"type":"xml"}"#, Kind::Bytes), + (r#"{"type":"xml_element"}"#, Kind::Bytes), + (r#"{"type":"html"}"#, Kind::Bytes), + (r#"{"type":"html_element"}"#, Kind::Bytes), + ( + r#"{"type":"list","element":{"type":"optional","base":{"type":"integer"}}}"#, + Kind::List(Box::new(field("item", Kind::Int64, true))), + ), + ( + r#"{"type":"map","key":{"type":"string"},"value":{"type":"optional","base":{"type":"integer"}}}"#, + Kind::Map( + Box::new(field("key", Kind::Bytes, false)), + Box::new(field("value", Kind::Int64, true)), + ), + ), + ( + r#"{"type":"structure_v2","fields":[{"name":"a","type":{"type":"integer"},"optional":false},{"name":"b","type":{"type":"optional","base":{"type":"string"}},"optional":false},{"name":"c","type":{"type":"string"},"optional":true}]}"#, + Kind::Struct(vec![ + field("a", Kind::Int64, false), + field("b", Kind::Bytes, false), + field("c", Kind::Bytes, true), + ]), + ), + (r#"{"type":"null"}"#, Kind::Null), + ] +} + +#[test] +fn every_definition_has_its_kind() { + for (type_json, expected) in definitions() { + assert_eq!( + expected, + kind(type_json.as_bytes()).expect(type_json), + "{type_json}" + ); + } +} + +#[test] +fn decode_builds_the_data_type_of_its_kind() { + for (type_json, kind) in definitions() { + let empty = encode(&ArrayData::new_empty(&data_type(&kind)), &kind).expect(type_json); + let buffers: Vec<&[u8]> = empty.iter().map(Vec::as_slice).collect(); + + assert_eq!( + &data_type(&kind), + decode(&kind, &buffers, 0, 0).expect(type_json).data_type(), + "{type_json}", + ); + } +} diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVReaderNative.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVReaderNative.php index 1a35add1bd..2193e94617 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVReaderNative.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVReaderNative.php @@ -4,7 +4,9 @@ namespace Flow\ETL\Adapter\CSV; -use Flow\ETL\Row\RawRowValues; +use Flow\ETL\Exception\SchemaMismatchException; +use Flow\ETL\Rows; +use Flow\ETL\Schema; use RuntimeException; use function extension_loaded; @@ -27,7 +29,7 @@ public function __construct( } /** - * The bytes, as read, of every row next() and fold() produced so far - line endings included, the header + * The bytes, as read, of every row next(), nextColumns() and fold() produced so far - line endings included, the header * record excluded. * * @return int<0, max> @@ -68,10 +70,23 @@ public function headers(): array /** * @param int<1, max> $batchSize * - * @return list + * @return list> */ public function next(int $batchSize): array { throw new RuntimeException('flow_php extension is not loaded'); } + + /** + * Exactly $batchSize rows keyed and ordered by $schema while that many are buffered, the remainder after finish(), + * else null; row indexes in refusals are relative to the batch. + * + * @param int<1, max> $batchSize + * + * @throws SchemaMismatchException + */ + public function nextColumns(Schema $schema, int $batchSize): ?Rows + { + throw new RuntimeException('flow_php extension is not loaded'); + } } diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Row/RustRowHydratorNative.php b/src/extension/flow-php-ext/php/Flow/ETL/Row/RustRowHydratorNative.php deleted file mode 100644 index cd642b126c..0000000000 --- a/src/extension/flow-php-ext/php/Flow/ETL/Row/RustRowHydratorNative.php +++ /dev/null @@ -1,47 +0,0 @@ - $batch - */ - public function hydrate(array $batch, Schema $schema): Rows - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * @return list - */ - public function dehydrate(Rows $rows): array - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * Present in every extension whose casts and decoders apply the datetime column zone. - */ - public function datetimeZones(): bool - { - throw new RuntimeException('flow_php extension is not loaded'); - } -} diff --git a/src/extension/flow-php-ext/php/Flow/Floe/RustFloeEncoderNative.php b/src/extension/flow-php-ext/php/Flow/Floe/RustFloeEncoderNative.php deleted file mode 100644 index 37504fe5e8..0000000000 --- a/src/extension/flow-php-ext/php/Flow/Floe/RustFloeEncoderNative.php +++ /dev/null @@ -1,85 +0,0 @@ - $batch - * @param string $schemaBody SCHEMA frame body (JSON list of normalized definitions) - * @param Schema $schema the same definitions as objects, so a refusal is raised through the PHP factory - * - * @throws ExtensionException - * - * @return list bare ROW frame bodies - */ - public function encode(array $batch, string $schemaBody, Schema $schema): array - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * @param list $frameBodies - * @param string $schemaBody SCHEMA frame body (JSON list of normalized definitions) - * - * @throws ExtensionException - * - * @return list - */ - public function decode(array $frameBodies, string $schemaBody): array - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * `RustRowHydratorNative::hydrate($this->decode($frameBodies, $schemaBody), $schema)` in one pass. - * - * @param list $frameBodies - * @param string $schemaBody SCHEMA frame body (JSON list of normalized definitions) - * - * @throws ExtensionException - */ - public function decodeRows(array $frameBodies, string $schemaBody, Schema $schema): Rows - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * `Format::frame(Format::FRAME_ROW, ...)` over `$this->encode(RustRowHydratorNative::dehydrate($rows), ...)`. - * - * @param string $schemaBody SCHEMA frame body (JSON list of normalized definitions) - * - * @throws ExtensionException - */ - public function encodeFrames(Rows $rows, string $schemaBody, Schema $schema): string - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * Present in every extension whose casts and decoders apply the datetime column zone. - */ - public function datetimeZones(): bool - { - throw new RuntimeException('flow_php extension is not loaded'); - } -} diff --git a/src/extension/flow-php-ext/src/alloc.rs b/src/extension/flow-php-ext/src/alloc.rs new file mode 100644 index 0000000000..d8226dae80 --- /dev/null +++ b/src/extension/flow-php-ext/src/alloc.rs @@ -0,0 +1,53 @@ +//! The global allocator: `System`, counting the bytes it holds for `DefaultBackend::allocatedBytes()`. + +use std::alloc::{GlobalAlloc, Layout, System}; +use std::sync::atomic::{AtomicI64, Ordering}; + +static ALLOCATED: AtomicI64 = AtomicI64::new(0); + +struct Counting; + +unsafe impl GlobalAlloc for Counting { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let ptr = System.alloc(layout); + + if !ptr.is_null() { + ALLOCATED.fetch_add(layout.size() as i64, Ordering::Relaxed); + } + + ptr + } + + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + let ptr = System.alloc_zeroed(layout); + + if !ptr.is_null() { + ALLOCATED.fetch_add(layout.size() as i64, Ordering::Relaxed); + } + + ptr + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + System.dealloc(ptr, layout); + ALLOCATED.fetch_sub(layout.size() as i64, Ordering::Relaxed); + } + + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let new = System.realloc(ptr, layout, new_size); + + if !new.is_null() { + ALLOCATED.fetch_add(new_size as i64 - layout.size() as i64, Ordering::Relaxed); + } + + new + } +} + +#[global_allocator] +static GLOBAL: Counting = Counting; + +/// Process-wide: on ZTS every thread's allocations. +pub fn allocated_bytes() -> i64 { + ALLOCATED.load(Ordering::Relaxed) +} diff --git a/src/extension/flow-php-ext/src/backend.rs b/src/extension/flow-php-ext/src/backend.rs new file mode 100644 index 0000000000..9643335dab --- /dev/null +++ b/src/extension/flow-php-ext/src/backend.rs @@ -0,0 +1,135 @@ +//! `Flow\ETL\Column\DefaultBackend` when flow_php is loaded: every column is a `NativeColumn`. + +// a parameter's Rust name is its PHP name, and `Backend::decode()` names it `$nullCount` +#![allow(non_snake_case)] + +use std::rc::Rc; + +use ext_php_rs::convert::IntoZval; +use ext_php_rs::error::Result as ZvalResult; +use ext_php_rs::flags::{ClassFlags, DataType}; +use ext_php_rs::prelude::*; +use ext_php_rs::types::{ZendHashTable, Zval}; +use flow_batch_frame::column::decode; +use flow_batch_frame::layout::buffer_count; + +use crate::builder::NativeColumnBuilder; +use crate::column::NativeColumn; +use crate::ctx::{call_method, zval_long}; +use crate::exception::ext_exception; +use crate::interfaces::backend_ce; +use crate::plan::{physical_for_definition, type_plan, TypePlan}; +use crate::render::{decode_exception, invalid_argument}; + +/// A return typed `Flow\ETL\Column\Column`: `adopt()` hands back its argument itself. +pub struct ColumnValue(Zval); + +impl IntoZval for ColumnValue { + const TYPE: DataType = DataType::Object(Some("Flow\\ETL\\Column\\Column")); + const NULLABLE: bool = false; + + fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { + *zv = self.0; + + Ok(()) + } +} + +fn definition_plan(definition: &Zval) -> PhpResult> { + type_plan(&call_method(definition, "type", &mut [])?) +} + +fn rows(count: i64, name: &str) -> PhpResult { + u32::try_from(count).map_err(|_| invalid_argument(format!("flow_php {name} must be between 0 and {}", u32::MAX))) +} + +#[php_class] +#[php( + name = "Flow\\ETL\\Column\\DefaultBackend", + flags = ClassFlags::Final, + implements(ce = backend_ce, stub = "Flow\\ETL\\Column\\Backend") +)] +pub struct DefaultBackend; + +#[php_impl] +impl DefaultBackend { + pub fn __construct() -> Self { + DefaultBackend + } + + pub fn builder(&self, definition: &Zval) -> PhpResult { + physical_for_definition(definition)?; + + NativeColumnBuilder::for_definition(definition, definition_plan(definition)?) + } + + pub fn constant(&self, definition: &Zval, value: &Zval, count: i64) -> PhpResult { + let mut builder = self.builder(definition)?; + let pending = builder.pending(value)?; + + builder.append_repeated(pending, rows(count, "constant count")?)?; + builder.finish_column() + } + + pub fn decode(&self, definition: &Zval, buffers: &ZendHashTable, count: i64, nullCount: i64) -> PhpResult { + let plan = definition_plan(definition)?; + let bytes = buffers + .values() + .map(|buffer| { + buffer + .zend_str() + .map(|buffer| buffer.as_bytes()) + .ok_or_else(|| invalid_argument("flow_php column buffers must be strings".to_string())) + }) + .collect::, _>>()?; + + let needed = buffer_count(&plan.kind).min(bytes.len()); + let data = decode(&plan.kind, &bytes[..needed], rows(count, "row count")?, rows(nullCount, "null count")?) + .map_err(|e| decode_exception(e, &plan.type_zv, &plan.kind))?; + + if bytes.len() > needed { + let entry = call_method(definition, "entry", &mut [])?; + let name = call_method(&entry, "name", &mut [])?; + + return Err(invalid_argument(format!( + "Column \"{}\": {} buffers left after decoding", + String::from_utf8_lossy(name.zend_str().map_or(&b""[..], |name| name.as_bytes())), + bytes.len() - needed + ))); + } + + Ok(NativeColumn::new(arrow_array::make_array(data), plan)) + } + + pub fn adopt(&self, definition: &Zval, column: &Zval) -> PhpResult { + if column.extract::<&NativeColumn>().is_some() { + return Ok(ColumnValue(column.shallow_clone())); + } + + let mut builder = self.builder(definition)?; + let count = call_method(column, "count", &mut [])? + .long() + .ok_or_else(|| ext_exception("flow_php expected Column::count() to return an int"))?; + + if count > 0 { + let mut indices = ZendHashTable::with_capacity(count as u32); + + for i in 0..count { + indices + .push(zval_long(i)) + .map_err(|e| ext_exception(format!("flow_php failed to collect row indices: {e:?}")))?; + } + + builder.append_take(column, &indices)?; + } + + let mut adopted = builder.finish_column()?.into_zval(false)?; + + Ok(ColumnValue(std::mem::take(&mut adopted))) + } + + #[php(name = "allocatedBytes")] + pub fn allocated_bytes(&self) -> i64 { + crate::alloc::allocated_bytes() + } +} diff --git a/src/extension/flow-php-ext/src/builder.rs b/src/extension/flow-php-ext/src/builder.rs new file mode 100644 index 0000000000..69bb9978e9 --- /dev/null +++ b/src/extension/flow-php-ext/src/builder.rs @@ -0,0 +1,444 @@ +//! `Flow\ETL\Column\NativeColumnBuilder`: `CastingColumnBuilder` over arrow storage. A value takes the native lane +//! where `cast.rs` casts it natively; every other value, and every value the native lane refuses, runs PHP's +//! `$type->cast()` then `$physical->toPhysical()`, so results and refusals are PHP's own. + +use std::rc::Rc; + +use arrow_array::Array; +use ext_php_rs::boxed::ZBox; +use ext_php_rs::exception::PhpException; +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::{ZendHashTable, ZendObject, Zval}; +use flow_batch_frame::kind::Kind; + +use crate::cast::{cast_value, CastKind}; +use crate::column::NativeColumn; +use crate::ctx::{ + self, call_handle_catching, call_method, call_static, construct_with_zvals, expect_object, find_class, + ht_for_each, null_zval, read_slot, transparent_exception, zval_long, +}; +use crate::date_check::iso_instant_micros; +use crate::exception::ext_exception; +use crate::interfaces::column_builder_ce; +use crate::kind_builder::KindBuilder; +use crate::physical::{append_physical, overflow}; +use crate::plan::TypePlan; +use crate::render::invalid_argument; +use crate::values::{datetime_days, datetime_micros, uuid_bytes}; + +const COLUMN_MISMATCH: &str = "Flow\\ETL\\Exception\\ColumnMismatchException"; +const SCHEMA_MISMATCH: &str = "Flow\\ETL\\Exception\\SchemaMismatchException"; +const TYPES_EXCEPTION: &str = "Flow\\Types\\Exception\\Exception"; +const NULL_DEFINITION: &str = "Flow\\ETL\\Schema\\Definition\\NullDefinition"; + +/// A value in its physical form, produced by the native lane without a PHP call. +pub enum Native { + Fixed([u8; 8]), + Days(i32), + Bool(bool), + Uuid([u8; 16]), + Bytes(Zval), +} + +/// One value ready to append: `appendMany()` builds all of them before appending any. +pub enum Pending { + Null, + Native(Native), + Physical(Zval), +} + +/// Why the PHP lane refused a value: its cast, or its `toPhysical()`. +pub enum Refusal { + Cast(ZBox), + Physical(ZBox), +} + +fn string_slot(object: &ZendObject, slot: u32) -> Option { + let value = read_slot(object, slot); + + value.is_string().then(|| value.shallow_clone()) +} + +/// The physical form of `value` for `plan`, when `cast.rs` casts it natively; `None` hands it to the PHP lane. +pub fn native_lane(plan: &TypePlan, value: &Zval) -> Result, PhpException> { + if let (Kind::Timestamp, CastKind::DateTime(_)) = (&plan.kind, &plan.cast) { + if let Some(micros) = value.zend_str().and_then(|string| iso_instant_micros(string.as_bytes())) { + return Ok(Some(Native::Fixed(micros.to_le_bytes()))); + } + } + + let Some(cast) = cast_value(&plan.cast, value)? else { + return Ok(None); + }; + + Ok(match (&plan.kind, &plan.cast) { + (Kind::Int64, CastKind::Integer | CastKind::PositiveInteger) => { + cast.long().map(|long| Native::Fixed(long.to_le_bytes())) + } + (Kind::Float64, CastKind::Float) => cast.double().map(|double| Native::Fixed(double.to_le_bytes())), + (Kind::Boolean, CastKind::Boolean) => cast.bool().map(Native::Bool), + (Kind::Bytes, CastKind::String | CastKind::NonEmptyString) => cast.is_string().then_some(Native::Bytes(cast)), + (Kind::Timestamp, CastKind::DateTime(_)) => cast + .object() + .and_then(datetime_micros) + .map(|micros| Native::Fixed(micros.to_le_bytes())), + (Kind::Int32, CastKind::Date) => cast + .object() + .and_then(datetime_days) + .map(|days| Native::Days(days as i32)), + (Kind::Uuid, CastKind::Uuid) => { + let (_, value_slot) = ctx::uuid()?; + + cast.object() + .and_then(|uuid| string_slot(uuid, value_slot)) + .and_then(|text| uuid_bytes(text.zend_str()?.as_bytes())) + .map(Native::Uuid) + } + (Kind::Bytes, CastKind::Json) => { + let (_, value_slot, _) = ctx::json()?; + + cast.object() + .and_then(|json| string_slot(json, value_slot)) + .map(Native::Bytes) + } + _ => None, + }) +} + +/// `$type->cast($value)`, then `$physical->toPhysical($cast)` unless the physical is the identity. +pub fn php_lane(plan: &TypePlan, value: &Zval) -> Result { + let type_obj = plan.type_zv.object().expect("a plan's type is an object"); + let cast = call_handle_catching(plan.cast_fn, Some(type_obj), &mut [value.shallow_clone()]).map_err(Refusal::Cast)?; + + if plan.identity { + return Ok(cast); + } + + let physical = plan.physical.object().expect("a plan's physical is an object"); + + call_handle_catching(plan.to_physical, Some(physical), &mut [cast]).map_err(Refusal::Physical) +} + +fn append_native(builder: &mut KindBuilder, native: Native) -> Result<(), PhpException> { + match native { + Native::Fixed(bytes) => builder.append_fixed(&bytes), + Native::Days(days) => builder.append_fixed(&days.to_le_bytes()), + Native::Bool(value) => builder.append_bool(value), + Native::Uuid(bytes) => builder.append_fixed(&bytes), + Native::Bytes(string) => builder + .append_bytes(string.zend_str().expect("a native string").as_bytes()) + .map_err(overflow)?, + } + + Ok(()) +} + +fn append_pending(builder: &mut KindBuilder, kind: &Kind, pending: Pending) -> Result<(), PhpException> { + match pending { + Pending::Null => { + builder.append_null(); + Ok(()) + } + Pending::Native(native) => append_native(builder, native), + Pending::Physical(physical) => append_physical(builder, kind, &physical), + } +} + +/// `ColumnMismatchException::valueDoesNotMatch($definition, $value[, $reason])`. +pub fn value_does_not_match(definition: &Zval, value: Zval, reason: Option) -> Result { + let mut args = vec![definition.shallow_clone(), value]; + args.extend(reason); + + call_static(COLUMN_MISMATCH, "valueDoesNotMatch", &mut args) +} + +pub fn throw(mut exception: Zval) -> PhpException { + match exception.object_mut() { + Some(object) => transparent_exception(object), + None => ext_exception("flow_php expected an exception object"), + } +} + +/// `new SchemaMismatchException($position, $cause)`. +pub fn schema_mismatch(position: Zval, cause: Zval) -> PhpException { + let built = find_class(SCHEMA_MISMATCH) + .and_then(|ce| construct_with_zvals(ce, &mut [position, cause], "a SchemaMismatchException")); + + match built { + Ok(mut exception) => transparent_exception(&mut exception), + Err(e) => e, + } +} + +/// Whether `definition` admits a null row: `isNullable()`, or a `NullDefinition`. +pub fn definition_nullable(definition: &Zval) -> Result { + Ok(call_method(definition, "isNullable", &mut [])?.bool().unwrap_or(false) + || expect_object(definition, "a Definition")?.instance_of(find_class(NULL_DEFINITION)?)) +} + +pub fn is_types_exception(exception: &ZendObject) -> Result { + Ok(exception.instance_of(find_class(TYPES_EXCEPTION)?)) +} + +#[php_class] +#[php( + name = "Flow\\ETL\\Column\\NativeColumnBuilder", + flags = ClassFlags::Final, + implements(ce = column_builder_ce, stub = "Flow\\ETL\\Column\\ColumnBuilder") +)] +pub struct NativeColumnBuilder { + definition: Zval, + nullable: bool, + plan: Rc, + values: KindBuilder, +} + +impl NativeColumnBuilder { + pub fn for_definition(definition: &Zval, plan: Rc) -> Result { + Ok(Self { + definition: definition.shallow_clone(), + nullable: definition_nullable(definition)?, + values: KindBuilder::new(&plan.kind), + plan, + }) + } + + /// One value for `append()`/`DefaultBackend::constant()`: refusals escape as PHP threw them. + pub fn pending(&self, value: &Zval) -> Result { + let value = value.dereference(); + + if value.is_null() { + if !self.nullable { + return Err(throw(value_does_not_match(&self.definition, null_zval(), None)?)); + } + + return Ok(Pending::Null); + } + + if let Some(native) = native_lane(&self.plan, value)? { + return Ok(Pending::Native(native)); + } + + match php_lane(&self.plan, value) { + Ok(physical) => Ok(Pending::Physical(physical)), + Err(Refusal::Cast(mut exception) | Refusal::Physical(mut exception)) => { + Err(transparent_exception(&mut exception)) + } + } + } + + pub fn append_pending(&mut self, pending: Pending) -> Result<(), PhpException> { + append_pending(&mut self.values, &self.plan.kind, pending) + } + + fn not_null(&self, is_null: bool) -> Result<(), PhpException> { + if is_null && !self.nullable { + return Err(throw(value_does_not_match(&self.definition, null_zval(), None)?)); + } + + Ok(()) + } + + fn same_kind<'a>(&self, column: &'a Zval) -> Option<&'a NativeColumn> { + column + .extract::<&NativeColumn>() + .filter(|native| native.data().data_type() == &flow_batch_frame::kind::data_type(&self.plan.kind)) + } + + /// `count` copies of one value, for `DefaultBackend::constant()`. + pub fn append_repeated(&mut self, pending: Pending, count: u32) -> Result<(), PhpException> { + match pending { + Pending::Null => (0..count).for_each(|_| self.values.append_null()), + Pending::Physical(physical) => { + for _ in 0..count { + append_physical(&mut self.values, &self.plan.kind, &physical)?; + } + } + Pending::Native(native) => { + let mut single = KindBuilder::new(&self.plan.kind); + append_native(&mut single, native)?; + let one = arrow_array::make_array( + single + .finish(&self.plan.kind) + .map_err(|e| invalid_argument(format!("flow_php built an invalid column: {e}")))?, + ); + + for _ in 0..count { + self.values.append_from(one.as_ref(), &self.plan.kind, 0).map_err(overflow)?; + } + } + } + + Ok(()) + } + + pub fn finish_column(&self) -> Result { + let data = self + .values + .finish(&self.plan.kind) + .map_err(|e| invalid_argument(format!("flow_php built an invalid column: {e}")))?; + + Ok(NativeColumn::new(arrow_array::make_array(data), Rc::clone(&self.plan))) + } +} + +fn index(i: i64, count: usize) -> Result { + usize::try_from(i) + .ok() + .filter(|i| *i < count) + .ok_or_else(|| invalid_argument(format!("flow_php column index {i} is outside [0, {count})"))) +} + +#[php_impl] +impl NativeColumnBuilder { + pub fn __construct() -> PhpResult { + Err(ext_exception("Flow\\ETL\\Column\\NativeColumnBuilder is built by DefaultBackend")) + } + + pub fn append(&mut self, value: &Zval) -> PhpResult<()> { + let pending = self.pending(value)?; + + self.append_pending(pending) + } + + #[php(name = "appendMany")] + pub fn append_many(&mut self, values: &ZendHashTable) -> PhpResult<()> { + let mut pendings = Vec::with_capacity(values.len()); + + ht_for_each(values, |string_key, index, value| { + let value = value.dereference(); + let position = || match string_key { + Some(name) => crate::ctx::zval_str(name.as_bytes()), + None => zval_long(index as i64), + }; + + if value.is_null() { + if !self.nullable { + return Err(schema_mismatch( + position(), + value_does_not_match(&self.definition, null_zval(), None)?, + )); + } + + pendings.push(Pending::Null); + + return Ok(()); + } + + if let Some(native) = native_lane(&self.plan, value)? { + pendings.push(Pending::Native(native)); + + return Ok(()); + } + + match php_lane(&self.plan, value) { + Ok(physical) => { + pendings.push(Pending::Physical(physical)); + + Ok(()) + } + Err(Refusal::Cast(mut exception)) => { + if !is_types_exception(&exception)? { + return Err(transparent_exception(&mut exception)); + } + + // the cast's own reason is dropped, as CastingColumnBuilder::appendMany drops it + Err(schema_mismatch( + position(), + value_does_not_match(&self.definition, value.shallow_clone(), None)?, + )) + } + Err(Refusal::Physical(mut exception)) => { + if !is_types_exception(&exception)? { + return Err(transparent_exception(&mut exception)); + } + + let mut reason = Zval::new(); + reason.set_object(&mut exception); + + // the value cast, so only the physical form's reason (a range) tells the user why it was refused + Err(schema_mismatch( + position(), + value_does_not_match(&self.definition, value.shallow_clone(), Some(reason))?, + )) + } + } + })?; + + for pending in pendings { + self.append_pending(pending)?; + } + + Ok(()) + } + + #[php(name = "appendFrom")] + pub fn append_from(&mut self, column: &Zval, i: i64) -> PhpResult<()> { + if let Some(native) = self.same_kind(column) { + let i = index(i, native.data().len())?; + self.not_null(matches!(self.plan.kind, Kind::Null) || native.data().is_null(i))?; + + return self + .values + .append_from(native.data().as_ref(), &self.plan.kind, i) + .map_err(overflow); + } + + self.not_null(call_method(column, "isNull", &mut [zval_long(i)])?.bool().unwrap_or(false))?; + let physical = call_method(column, "at", &mut [zval_long(i)])?; + + append_physical(&mut self.values, &self.plan.kind, &physical) + } + + #[php(name = "appendTake")] + pub fn append_take(&mut self, column: &Zval, indices: &ZendHashTable) -> PhpResult<()> { + if let Some(native) = self.same_kind(column) { + let data = native.data(); + let mut rows = Vec::with_capacity(indices.len()); + + ht_for_each(indices, |_, _, i| { + let row = index(i.long().ok_or_else(|| invalid_argument("flow_php column indices must be ints".into()))?, data.len())?; + self.not_null(matches!(self.plan.kind, Kind::Null) || data.is_null(row))?; + rows.push(row); + + Ok(()) + })?; + + for row in rows { + self.values.append_from(data.as_ref(), &self.plan.kind, row).map_err(overflow)?; + } + + return Ok(()); + } + + let all = call_method(column, "physicals", &mut [])?; + let all = all.array().ok_or_else(|| ext_exception("flow_php expected Column::physicals() to return an array"))?; + let mut physicals = Vec::with_capacity(indices.len()); + + ht_for_each(indices, |_, _, i| { + let physical = i + .long() + .and_then(|i| all.get_index(i)) + .map_or_else(null_zval, Zval::shallow_clone); + self.not_null(physical.is_null())?; + physicals.push(physical); + + Ok(()) + })?; + + for physical in physicals { + append_physical(&mut self.values, &self.plan.kind, &physical)?; + } + + Ok(()) + } + + pub fn count(&self) -> i64 { + self.values.len() as i64 + } + + pub fn finish(&self) -> PhpResult { + self.finish_column() + } +} diff --git a/src/extension/flow-php-ext/src/cast.rs b/src/extension/flow-php-ext/src/cast.rs index 119e589967..c22e728c24 100644 --- a/src/extension/flow-php-ext/src/cast.rs +++ b/src/extension/flow-php-ext/src/cast.rs @@ -4,25 +4,18 @@ use ext_php_rs::boxed::ZBox; use ext_php_rs::exception::PhpException; use ext_php_rs::flags::DataType; use ext_php_rs::types::{ZendHashTable, ZendObject, ZendStr, Zval}; -use ext_php_rs::zend::Function; +use ext_php_rs::zend::{ClassEntry, Function}; use crate::ctx::{ - array_key_index, call_handle, call_handle_catching, call_handle_on, call_handle_transparent, - ce_method_ref, construct_with_zvals, ht_find_key, ht_insert, ht_insert_key, null_zval, - schema_mismatch, transparent_exception, write_slot, zval_long, Ctx, HtKey, + self, array_key_index, call_handle_on, call_handle_transparent, expect_object, ht_insert, ht_insert_key, null_zval, + write_slot, zval_long, HtKey, HASH_FLAG_PACKED, }; use crate::date_check::{iso_date_gate, iso_date_time_gate, IsoSuffix}; -use crate::encode::{expect_object, ht_for_each, read_slot}; use crate::exception::ext_exception; -use crate::format::Reader; -use crate::hydrate::{ - build_hydrate_plan, fold_metadata_into_schema, fold_pending_metadata, read_cell, AssemblyClasses, - HydrateColumn, HydratePlan, RowValuesClass, -}; use crate::json_check::json_valid; -use crate::plan::{parse_schema_json, Plan, TypeJson}; use crate::uuid_check::is_uuid; use crate::values::date_from_free_form; +use flow_batch_frame::kind::TypeJson; extern "C" { fn zval_get_long_func(op: *const Zval, is_strict: bool) -> i64; @@ -39,18 +32,18 @@ extern "C" { ) -> u8; } -pub(crate) enum MapKeyKind { +pub enum MapKeyKind { Int, Str, } -pub(crate) struct StructureElement { +pub struct StructureElement { name: String, kind: CastKind, required: bool, } -pub(crate) enum CastKind { +pub enum CastKind { Integer, PositiveInteger, Float, @@ -92,7 +85,7 @@ fn build_structure_kind(type_json: &TypeJson) -> CastKind { CastKind::Structure(elements) } -fn build_cast_kind(type_json: &TypeJson) -> CastKind { +pub(crate) fn build_cast_kind(type_json: &TypeJson) -> CastKind { match type_json.type_.as_str() { "integer" => CastKind::Integer, "positive_integer" => CastKind::PositiveInteger, @@ -128,111 +121,6 @@ fn build_cast_kind(type_json: &TypeJson) -> CastKind { } } -struct CastColumn { - kind: CastKind, - /// The retained `$definition->type()` object - the fallback receiver. - type_zv: Zval, - /// `Type::cast` resolved on the concrete type class. - cast_fn: &'static Function, -} - -pub struct CastPlan { - hydrate: HydratePlan, - columns: Vec, -} - -fn build_cast_plan(schema: &Zval, ctx: &mut Ctx) -> Result { - let hydrate = build_hydrate_plan(schema)?; - - let schema_obj = expect_object(schema, "a Schema")?; - let schema_ce = unsafe { schema_obj.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve the Schema class"))?; - let normalize_fn = ce_method_ref(schema_ce, "normalize")?; - let normalized = call_handle_on(normalize_fn, schema_obj, &mut [], "normalize a schema")?; - - let json = { - let json_encode = ctx.json_encode()?; - call_handle( - json_encode, - None, - &mut [normalized.shallow_clone()], - "encode a schema as JSON", - )? - }; - let json_bytes = json - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected schema JSON to be a string"))? - .as_bytes(); - - let definitions = parse_schema_json(json_bytes)?; - - if definitions.len() != hydrate.columns.len() { - return Err(ext_exception( - "flow_php normalized schema JSON does not match the schema definitions", - )); - } - - let mut columns = Vec::with_capacity(definitions.len()); - - for (definition, column) in definitions.iter().zip(&hydrate.columns) { - if column.name_zv.zend_str().map(ZendStr::as_bytes) != Some(definition.name.as_bytes()) { - return Err(ext_exception( - "flow_php normalized schema JSON does not match the schema definitions", - )); - } - - let def_obj = column - .base_def - .object() - .ok_or_else(|| ext_exception("flow_php expected a Definition object"))?; - let def_ce = unsafe { def_obj.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve a Definition class"))?; - - let type_fn = ce_method_ref(def_ce, "type")?; - let type_zv = call_handle_on(type_fn, def_obj, &mut [], "read a definition type")?; - let type_obj = type_zv - .object() - .ok_or_else(|| ext_exception("flow_php expected a definition type to be an object"))?; - let type_ce = unsafe { type_obj.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve a Type class"))?; - - columns.push(CastColumn { - kind: build_cast_kind(&definition.type_), - cast_fn: ce_method_ref(type_ce, "cast")?, - type_zv, - }); - } - - Ok(CastPlan { hydrate, columns }) -} - -/// The Schema `definitions` array address identifies the definition set; -/// retaining it (refcount++) prevents address reuse. -fn ensure_cast_plan( - plan: &mut Option, - schema: &Zval, - ctx: &mut Ctx, -) -> Result<(), PhpException> { - let schema_obj = expect_object(schema, "a Schema")?; - - let current = plan.as_ref().and_then(|p| { - read_slot(schema_obj, p.hydrate.definitions_slot) - .array() - .zip(p.hydrate.definitions_retained.array()) - }); - - if current.is_some_and(|(definitions, retained)| std::ptr::eq(definitions, retained)) { - return Ok(()); - } - - *plan = Some(build_cast_plan(schema, ctx)?); - - Ok(()) -} - -/// `HASH_FLAG_PACKED` from zend_types.h. -const HASH_FLAG_PACKED: u8 = 1 << 2; - /// In-order hashtable walk yielding `(string key, numeric key, value)` - the /// early-exit sibling of `encode::ht_for_each` for the container cast checks. struct HtEntries<'a> { @@ -298,7 +186,7 @@ fn engine_string(value: &Zval) -> Result, PhpException> { /// `mb_strtolower` + table match from `BooleanType::cast`. ASCII lowering /// suffices: no non-ASCII uppercase code point lowercases onto these words. -fn bool_from_str(bytes: &[u8]) -> Option { +pub(crate) fn bool_from_str(bytes: &[u8]) -> Option { if bytes.is_empty() || bytes.len() > 5 { return None; } @@ -318,21 +206,21 @@ fn bool_from_str(bytes: &[u8]) -> Option { } /// The cheap prefix of `Json::isValid`: non-empty + matching `{}`/`[]` pair. -fn json_gate(bytes: &[u8]) -> bool { +pub(crate) fn json_gate(bytes: &[u8]) -> bool { bytes.len() >= 2 && ((bytes[0] == b'{' && bytes[bytes.len() - 1] == b'}') || (bytes[0] == b'[' && bytes[bytes.len() - 1] == b']')) } /// `source` is a gated JSON string; the Json shares its zend_string instead of copying the bytes. -fn json_object_from(source: &Zval, ctx: &mut Ctx) -> Result { +fn json_object_from(source: &Zval) -> Result { let bytes = source .zend_str() .ok_or_else(|| ext_exception("flow_php expected a JSON string"))? .as_bytes(); let is_object = bytes[0] == b'{' && bytes[bytes.len() - 1] == b'}'; - let (json_ce, value_slot, is_object_slot) = ctx.json()?; + let (json_ce, value_slot, is_object_slot) = ctx::json()?; let mut json = ZendObject::new(json_ce); write_slot(&mut json, value_slot, source.shallow_clone()); @@ -355,13 +243,27 @@ const IS_DOUBLE: u8 = 5; /// reproducing the grammar and drifting from it. Yields the type code together /// with the value `_is_numeric_string_ex` already computed, so the integer cast /// reads one parse instead of parsing the same bytes a second time. +/// +/// The engine scans past `length` until a non-digit (it expects a zend_string's +/// NUL terminator), so a CSV cell - a slice of the record buffer - is copied +/// NUL-terminated first; unterminated, `"1"` followed by the next field's +/// `"2..."` reads as trailing data and is refused. fn is_numeric_str(bytes: &[u8]) -> (u8, i64, f64) { let mut lval: i64 = 0; let mut dval: f64 = 0.0; + let mut short = [0u8; 64]; + let long; + let terminated: &[u8] = if bytes.len() < short.len() { + short[..bytes.len()].copy_from_slice(bytes); + &short + } else { + long = [bytes, &[0]].concat(); + &long + }; let code = unsafe { _is_numeric_string_ex( - bytes.as_ptr().cast::(), + terminated.as_ptr().cast::(), bytes.len(), &mut lval, &mut dval, @@ -410,12 +312,69 @@ fn numeric_scalar(value: &Zval) -> bool { } } +/// `IntegerType::cast` of a string: `None` for any string it refuses or that needs its round-trip branch. A form feed is +/// whitespace to `is_numeric()` but not to `trim()`, so PHP's round-trip refuses it: it bails. +pub(crate) fn integer_from_str(bytes: &[u8]) -> Option { + match is_numeric_str(bytes) { + (IS_LONG, long, _) if !bytes.contains(&0x0C) => Some(long), + (IS_DOUBLE, _, _) if integer_shaped(bytes) => None, + (IS_DOUBLE, _, double) if fits_i64(double) => Some(double as i64), + _ => None, + } +} + +/// `FloatType::cast` of a numeric string: the engine's `(float)` of it, which `is_numeric()` already computed; an integer +/// zero keeps the sign of its text, as `(float) '-0'` is `-0.0`. +pub(crate) fn float_from_str(bytes: &[u8]) -> Option { + match is_numeric_str(bytes) { + (IS_LONG, 0, _) if bytes.iter().find(|byte| !byte.is_ascii_whitespace() && **byte != 0x0B) == Some(&b'-') => { + Some(-0.0) + } + (IS_LONG, long, _) => Some(long as f64), + (IS_DOUBLE, _, double) => Some(double), + _ => None, + } +} + +/// The instant an ISO string names, parsed as `DateTimeType::cast` parses it (before moving it into the column zone); +/// any other string is gated on StringTemporalParts, a PHP class, so it bails. +pub(crate) fn parse_iso_datetime(bytes: &[u8], zone: &[u8]) -> Result, PhpException> { + Ok(match iso_date_time_gate(bytes).or_else(|| iso_date_gate(bytes).then_some(IsoSuffix::Naive)) { + Some(IsoSuffix::Zulu) => { + // mirrors DateTimeType::cast's Z branch + let local = bytes.strip_suffix(b"\n").unwrap_or(bytes); + let local = local.strip_suffix(b"Z").unwrap_or(local); + let mut utc = ctx::timezone(b"UTC")?; + + date_from_free_form(local, Some(&mut utc))?.map(|instant| (IsoSuffix::Zulu, instant)) + } + Some(IsoSuffix::Offset) => date_from_free_form(bytes, None)?.map(|instant| (IsoSuffix::Offset, instant)), + Some(IsoSuffix::Naive) => { + let mut column = ctx::timezone(zone)?; + + date_from_free_form(bytes, Some(&mut column))?.map(|instant| (IsoSuffix::Naive, instant)) + } + None => None, + }) +} + +/// `DateType::cast` of an ISO date string: midnight UTC. +pub(crate) fn parse_iso_date(bytes: &[u8]) -> Result, PhpException> { + if !iso_date_gate(bytes) { + return Ok(None); + } + + let mut utc = ctx::timezone(b"UTC")?; + + date_from_free_form(bytes, Some(&mut utc)) +} + /// Casts one value natively; `Ok(None)` bails the WHOLE column value to the /// PHP fallback (`Type::cast`), which reproduces results, exception classes, /// messages and `previous` chains by re-running the canonical implementation. /// PHP calls made inside a branch discard their own thrown exceptions and bail /// instead - mirroring the `catch (Throwable)` wrappers in the PHP casts. -fn cast_value(kind: &CastKind, value: &Zval, ctx: &mut Ctx) -> Result, PhpException> { +pub(crate) fn cast_value(kind: &CastKind, value: &Zval) -> Result, PhpException> { // Type::cast receives its argument by value; a branch that returns `value` itself must not hand // back the caller's reference let value = value.dereference(); @@ -433,14 +392,7 @@ fn cast_value(kind: &CastKind, value: &Zval, ctx: &mut Ctx) -> Result Some(zval_long(long)), - (IS_DOUBLE, _, _) if integer_shaped(bytes) => None, - (IS_DOUBLE, _, double) if fits_i64(double) => Some(zval_long(double as i64)), - _ => None, - } + integer_from_str(string.as_bytes()).map(zval_long) } else if value.is_bool() { Some(zval_long(engine_long(value))) } else { @@ -488,7 +440,7 @@ fn cast_value(kind: &CastKind, value: &Zval, ctx: &mut Ctx) -> Result Result { if let Some(object) = value.object() { - let immutable_ce = ctx.datetime_fns(false)?.ce; + let immutable_ce = ctx::datetime_immutable()?.ce; if !object.instance_of(immutable_ce) { None - } else if zone_name(object, ctx)? == zone.as_slice() { + } else if zone_name(object)? == zone.as_slice() { Some(value.shallow_clone()) } else { - Some(in_zone(value, zone, ctx)?) + Some(in_zone(value, zone)?) } } else if let Some(string) = value.zend_str() { - // any other string is gated on StringTemporalParts, a PHP class, so it bails - let bytes = string.as_bytes(); - - match iso_date_time_gate(bytes).or_else(|| iso_date_gate(bytes).then_some(IsoSuffix::Naive)) { - Some(IsoSuffix::Zulu) => { - // mirrors DateTimeType::cast's Z branch - let local = bytes.strip_suffix(b"\n").unwrap_or(bytes); - let local = local.strip_suffix(b"Z").unwrap_or(local); - let mut utc = ctx.timezone(b"UTC")?.shallow_clone(); - - match date_from_free_form(local, Some(&mut utc), ctx)? { - Some(instant) if zone.as_slice() != b"UTC" => Some(in_zone(&instant, zone, ctx)?), - instant => instant, - } - } - Some(IsoSuffix::Offset) => date_from_free_form(bytes, None, ctx)? - .map(|instant| in_zone(&instant, zone, ctx)) - .transpose()?, - Some(IsoSuffix::Naive) => { - let mut column = ctx.timezone(zone)?.shallow_clone(); - - date_from_free_form(bytes, Some(&mut column), ctx)? - } + match parse_iso_datetime(string.as_bytes(), zone)? { + Some((IsoSuffix::Zulu, instant)) if zone.as_slice() != b"UTC" => Some(in_zone(&instant, zone)?), + Some((IsoSuffix::Offset, instant)) => Some(in_zone(&instant, zone)?), + Some((_, instant)) => Some(instant), None => None, } } else if value.is_long() || value.is_double() { - date_from_free_form(×tamp_string(value)?, None, ctx)? - .map(|instant| in_zone(&instant, zone, ctx)) + date_from_free_form(×tamp_string(value)?, None)? + .map(|instant| in_zone(&instant, zone)) .transpose()? } else { None } } - CastKind::Date => cast_date(value, ctx)?, + CastKind::Date => cast_date(value)?, CastKind::Uuid => { if let Some(object) = value.object() { - let (uuid_ce, _) = ctx.uuid()?; + let (uuid_ce, _) = ctx::uuid()?; if object.instance_of(uuid_ce) { Some(value.shallow_clone()) @@ -564,7 +497,7 @@ fn cast_value(kind: &CastKind, value: &Zval, ctx: &mut Ctx) -> Result Result cast_json(value, ctx)?, + CastKind::Json => cast_json(value)?, CastKind::List(inner) => { let Some(values) = value.array() else { return Ok(None); @@ -591,7 +524,7 @@ fn cast_value(kind: &CastKind, value: &Zval, ctx: &mut Ctx) -> Result Result return Ok(None), }; - let Some(casted) = cast_value(value_kind, item, ctx)? else { + let Some(casted) = cast_value(value_kind, item)? else { return Ok(None); }; @@ -653,7 +586,7 @@ fn cast_value(kind: &CastKind, value: &Zval, ctx: &mut Ctx) -> Result Result None, }) } +fn object_ce(object: &ZendObject) -> Result<&'static ClassEntry, PhpException> { + unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php failed to resolve an object class")) +} + /// `"@" . $value` with the engine's number-to-string conversion. fn timestamp_string(value: &Zval) -> Result, PhpException> { let number = engine_string(value)?; @@ -692,12 +629,12 @@ fn timestamp_string(value: &Zval) -> Result, PhpException> { } /// `$datetime->getTimezone()->getName()` of a DateTimeImmutable. -fn zone_name(datetime: &ZendObject, ctx: &mut Ctx) -> Result, PhpException> { - let immutable_ce = ctx.datetime_fns(false)?.ce; - let get_timezone = ctx.datetime_encode_fns(std::ptr::from_ref(immutable_ce))?.get_timezone; +fn zone_name(datetime: &ZendObject) -> Result, PhpException> { + let immutable_ce = ctx::datetime_immutable()?.ce; + let get_timezone = ctx::datetime_get_timezone(immutable_ce)?; let timezone_zv = call_handle_on(get_timezone, datetime, &mut [], "read a timezone")?; let timezone = expect_object(&timezone_zv, "a timezone")?; - let name = call_handle_on(ctx.timezone_get_name()?, timezone, &mut [], "read a timezone name")?; + let name = call_handle_on(ctx::timezone_get_name()?, timezone, &mut [], "read a timezone name")?; Ok(name .zend_str() @@ -707,29 +644,29 @@ fn zone_name(datetime: &ZendObject, ctx: &mut Ctx) -> Result, PhpExcepti } /// `$datetime->setTimezone(new DateTimeZone($zone))` of a DateTimeImmutable. -fn in_zone(datetime: &Zval, zone: &[u8], ctx: &mut Ctx) -> Result { - let set_timezone = ctx.datetime_fns(false)?.set_timezone; - let timezone = ctx.timezone(zone)?.shallow_clone(); +fn in_zone(datetime: &Zval, zone: &[u8]) -> Result { + let set_timezone = ctx::datetime_immutable()?.set_timezone; + let timezone = ctx::timezone(zone)?; call_handle_on( - &set_timezone, + set_timezone, expect_object(datetime, "a datetime value")?, &mut [timezone], "move a datetime into its column zone", ) } -fn cast_date(value: &Zval, ctx: &mut Ctx) -> Result, PhpException> { +fn cast_date(value: &Zval) -> Result, PhpException> { if let Some(object) = value.object() { - let immutable_ce = ctx.datetime_fns(false)?.ce; + let immutable_ce = ctx::datetime_immutable()?.ce; if !object.instance_of(immutable_ce) { return Ok(None); } - let fns = ctx.datetime_cast_fns(object.ce.cast_const())?; + let fns = ctx::datetime_cast_fns(object_ce(object)?)?; let (set_time, format) = (fns.set_time, fns.format); - let his = ctx.format_his()?.shallow_clone(); + let his = ctx::string(b"H:i:s.u")?; // isValid passthrough: midnight keeps the SAME object (serialize // back-reference topology); a thrown format() bails like PHP's catch @@ -745,17 +682,11 @@ fn cast_date(value: &Zval, ctx: &mut Ctx) -> Result, PhpException> } if let Some(string) = value.zend_str() { - return if iso_date_gate(string.as_bytes()) { - let mut utc = ctx.timezone(b"UTC")?.shallow_clone(); - - date_from_free_form(string.as_bytes(), Some(&mut utc), ctx) - } else { - Ok(None) - }; + return parse_iso_date(string.as_bytes()); } let parsed = if value.is_long() || value.is_double() { - date_from_free_form(×tamp_string(value)?, None, ctx)? + date_from_free_form(×tamp_string(value)?, None)? } else { None }; @@ -763,11 +694,11 @@ fn cast_date(value: &Zval, ctx: &mut Ctx) -> Result, PhpException> let Some(instant) = parsed else { return Ok(None); }; - let datetime = in_zone(&instant, b"UTC", ctx)?; + let datetime = in_zone(&instant, b"UTC")?; let object = datetime .object() .ok_or_else(|| ext_exception("flow_php expected a datetime object"))?; - let set_time = ctx.datetime_cast_fns(object.ce.cast_const())?.set_time; + let set_time = ctx::datetime_cast_fns(object_ce(object)?)?.set_time; set_midnight(set_time, object) } @@ -789,9 +720,9 @@ fn set_midnight( Ok(Some(result)) } -fn cast_json(value: &Zval, ctx: &mut Ctx) -> Result, PhpException> { +fn cast_json(value: &Zval) -> Result, PhpException> { if let Some(object) = value.object() { - let (json_ce, _, _) = ctx.json()?; + let (json_ce, _, _) = ctx::json()?; if object.instance_of(json_ce) { return Ok(Some(value.shallow_clone())); @@ -810,14 +741,13 @@ fn cast_json(value: &Zval, ctx: &mut Ctx) -> Result, PhpException> return Ok(None); } - return Ok(Some(json_object_from(value, ctx)?)); + return Ok(Some(json_object_from(value)?)); } if value.is_array() { // Json::fromArray's json_encode, in its non-throwing flavor: `false` // (or a thrown JsonSerializable) bails to the PHP cast - let json_encode = ctx.json_encode()?; - let Ok(encoded) = call_handle_transparent(json_encode, None, &mut [value.shallow_clone()]) + let Ok(encoded) = call_handle_transparent(ctx::json_encode()?, None, &mut [value.shallow_clone()]) else { return Ok(None); }; @@ -830,238 +760,8 @@ fn cast_json(value: &Zval, ctx: &mut Ctx) -> Result, PhpException> return Ok(None); } - return Ok(Some(json_object_from(&encoded, ctx)?)); + return Ok(Some(json_object_from(&encoded)?)); } Ok(None) } - -/// One value of a row against its column: a present null under NOT NULL is refused, a null passes, anything else is -/// cast natively where proven identical and otherwise through the retained PHP `Type::cast`. -fn cast_cell( - column: &HydrateColumn, - cast_column: &CastColumn, - value: &Zval, - row_index: u64, - assembly: &AssemblyClasses, - ctx: &mut Ctx, -) -> Result { - // a present null is a DIFFERENT refusal from an absence: valueDoesNotMatch, not - // missingColumn, and 027 pins the two messages apart - if value.is_null() && !column.nullable { - return Err(schema_mismatch( - assembly.schema_mismatch_ce, - assembly.value_does_not_match, - row_index, - &mut [column.base_def.shallow_clone(), null_zval()], - )?); - } - - if value.is_null() { - return Ok(null_zval()); - } - - if let Some(casted) = cast_value(&cast_column.kind, value, ctx)? { - return Ok(casted); - } - - let type_obj = cast_column - .type_zv - .object() - .ok_or_else(|| ext_exception("flow_php expected a Type object"))?; - - match call_handle_catching(cast_column.cast_fn, Some(type_obj), &mut [value.shallow_clone()]) { - Ok(casted) => Ok(casted), - Err(mut refusal) => { - if !refusal.instance_of(assembly.types_exception_ce) { - return Err(transparent_exception(&mut refusal)); - } - - // The declared type refused the value. Its own exception is dropped rather than chained, exactly as - // HydratedBatch's guard drops it - 027 compares the two hydrators' class and message byte for byte. - Err(schema_mismatch( - assembly.schema_mismatch_ce, - assembly.value_does_not_match, - row_index, - &mut [column.base_def.shallow_clone(), value.shallow_clone()], - )?) - } - } -} - -/// Builds one `Row` through its PHP constructor and appends it to the batch. -fn push_row( - rows_ht: &mut ZendHashTable, - row_values: ZBox, - assembly: &AssemblyClasses, -) -> Result<(), PhpException> { - let mut values_zv = Zval::new(); - values_zv.set_hashtable(row_values); - - let mut row = construct_with_zvals(assembly.row_ce, &mut [values_zv], "a Row")?; - let mut row_zv = Zval::new(); - row_zv.set_object(&mut row); - - rows_ht - .push(row_zv) - .map_err(|e| ext_exception(format!("flow_php failed to collect hydrated rows: {e:?}"))) -} - -/// Every non-null value was cast to its column's type, so the batch takes the shape-only door - the one -/// HydratedBatch returns through. Row::conform() returns $this for a row holding exactly the Schema's keys, in -/// order, with no null under NOT NULL - which every cast row is once no column was absent. An absence keeps the -/// PHP door: padding, missingColumn and the failing row's index are conform()'s to decide. -fn assemble_rows( - rows_ht: ZBox, - schema_zv: Zval, - every_column_present: bool, - assembly: &AssemblyClasses, -) -> Result { - let mut rows_zv = Zval::new(); - rows_zv.set_hashtable(rows_ht); - - let door = if every_column_present { assembly.rows_trusted } else { assembly.rows_conformed }; - - // conform()'s refusal surfaces as the SchemaMismatchException PHP threw, like the cast refusals above - call_handle_transparent(door, None, &mut [schema_zv, rows_zv]) -} - -/// Native `PhpRowHydrator::hydrate`: raw scalars cast against a `Schema` and -/// assembled into `Flow\ETL\Rows` in one pass. Column values cast natively -/// where proven identical, otherwise per value through the retained PHP -/// `Type::cast`; a null under a nullable declaration passes through, and both an -/// absence and a present null under NOT NULL are refused - each with its own cause. -pub fn cast_rows( - batch: &Zval, - schema: &Zval, - plan_slot: &mut Option, - raw_class: &RowValuesClass, - assembly: &AssemblyClasses, - ctx: &mut Ctx, -) -> Result { - ensure_cast_plan(plan_slot, schema, ctx)?; - let plan = plan_slot.as_ref().expect("plan built above"); - - let batch_ht = batch - .array() - .ok_or_else(|| ext_exception("flow_php expected a list of raw row values"))?; - - let schema_zv = fold_metadata_into_schema(schema, batch_ht, raw_class, ctx)?; - let mut rows_ht = ZendHashTable::with_capacity(batch_ht.len() as u32); - let mut every_column_present = true; - - ht_for_each(batch_ht, |_, row_index, rv_zv| { - let rv = expect_object(rv_zv, "a RawRowValues")?; - let values_ht = read_slot(rv, raw_class.values_slot) - .array() - .ok_or_else(|| ext_exception("flow_php expected RawRowValues::values to be an array"))?; - - let mut row_values = ZendHashTable::with_capacity(plan.hydrate.columns.len() as u32); - - for (column, cast_column) in plan.hydrate.columns.iter().zip(&plan.columns) { - let key = column.key(); - - // An absent column is simply not inserted, mirroring HydratedBatch's `continue`: - // Rows::__construct runs Row::matchTo(), which pads a declared-nullable absence and - // raises missingColumn for a NOT-NULL one. Re-implementing that here instead would - // refuse the absence mid-row, so a later cast refusal in the same batch would be - // reported by PHP and pre-empted by native - the two paths would name different - // columns and different rows for the same input. - let Some(value) = ht_find_key(values_ht, &key).map(Zval::dereference) else { - every_column_present = false; - continue; - }; - - let casted = cast_cell(column, cast_column, value, row_index, assembly, ctx)?; - ht_insert_key(&mut row_values, &key, casted); - } - - push_row(&mut rows_ht, row_values, assembly) - })?; - - assemble_rows(rows_ht, schema_zv, every_column_present, assembly) -} - -/// `cast_rows(decode(...))` in one pass: each ROW frame body is decoded straight into the cast, so no -/// `RawRowValues` is built. A Schema column takes the decoded column of the same name - the lookup `cast_rows` does -/// in `RawRowValues::values` - and a Schema column the frames do not carry is an absence, exactly as there. -pub fn decode_rows( - frame_bodies: &Zval, - decode_plan: &Plan, - schema: &Zval, - plan_slot: &mut Option, - assembly: &AssemblyClasses, - ctx: &mut Ctx, -) -> Result { - ensure_cast_plan(plan_slot, schema, ctx)?; - let plan = plan_slot.as_ref().expect("plan built above"); - - let bodies_ht = frame_bodies - .array() - .ok_or_else(|| ext_exception("flow_php expected a list of row frame bodies"))?; - - let decoded_names: Vec<&[u8]> = decode_plan.columns.iter().map(|column| column.name.as_bytes()).collect(); - // RawRowValues::values refuses a name decoded twice at the second occurrence - let duplicated = (0..decoded_names.len()).find(|&index| decoded_names[..index].contains(&decoded_names[index])); - let sources: Vec> = plan - .hydrate - .columns - .iter() - .map(|column| { - let name = column.name_zv.zend_str().map(ZendStr::as_bytes); - decoded_names.iter().position(|decoded| Some(*decoded) == name) - }) - .collect(); - - let mut decoded: Vec = (0..decoded_names.len()).map(|_| Zval::new()).collect(); - let mut metadata: Vec<(Vec, Zval)> = Vec::new(); - let mut rows_ht = ZendHashTable::with_capacity(bodies_ht.len() as u32); - let every_column_present = sources.iter().all(Option::is_some); - - ht_for_each(bodies_ht, |_, row_index, body_zv| { - let bytes = body_zv - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected a row frame body to be a string"))? - .as_bytes(); - - let mut reader = Reader::new(bytes); - - for (index, column) in decode_plan.columns.iter().enumerate() { - let (value, value_metadata) = read_cell(&column.decoder, &mut reader, ctx)?; - - if let Some(value_metadata) = value_metadata { - metadata.push((column.name.as_bytes().to_vec(), value_metadata)); - } - - if duplicated == Some(index) { - return Err(ext_exception(format!( - "flow_php found duplicated entry name \"{}\" in a row frame", - column.name - ))); - } - - decoded[index] = value; - } - - if !reader.is_eof() { - return Err(ext_exception("flow_php row frame length does not match its content")); - } - - let mut row_values = ZendHashTable::with_capacity(plan.hydrate.columns.len() as u32); - - for ((column, cast_column), source) in plan.hydrate.columns.iter().zip(&plan.columns).zip(&sources) { - let Some(source) = source else { - continue; - }; - - let casted = cast_cell(column, cast_column, &decoded[*source], row_index, assembly, ctx)?; - ht_insert_key(&mut row_values, &column.key(), casted); - } - - push_row(&mut rows_ht, row_values, assembly) - })?; - - let schema_zv = fold_pending_metadata(schema, metadata, ctx)?; - - assemble_rows(rows_ht, schema_zv, every_column_present, assembly) -} diff --git a/src/extension/flow-php-ext/src/column.rs b/src/extension/flow-php-ext/src/column.rs new file mode 100644 index 0000000000..321b9f6cf9 --- /dev/null +++ b/src/extension/flow-php-ext/src/column.rs @@ -0,0 +1,320 @@ +//! `Flow\ETL\Column\NativeColumn`: one arrow array of the column's kind, read as the PHP columns read. + +use std::rc::Rc; + +use arrow_array::cast::AsArray; +use arrow_array::{Array, ArrayRef, UInt32Array}; +use arrow_schema::ArrowError; +use ext_php_rs::boxed::ZBox; +use ext_php_rs::convert::IntoZval; +use ext_php_rs::error::Result as ZvalResult; +use ext_php_rs::exception::PhpException; +use ext_php_rs::flags::{ClassFlags, DataType}; +use ext_php_rs::prelude::*; +use ext_php_rs::types::{ZendHashTable, Zval}; +use flow_batch_frame::column::encode; +use flow_batch_frame::kind::{data_type, Kind}; + +use crate::ctx::{call_method, expect_object, find_class, ht_for_each, instance, read_property, zval_long, zval_str}; +use crate::exception::ext_exception; +use crate::interfaces::column_ce; +use crate::physical::{physical_at, value_at}; +use crate::plan::{type_plan, TypePlan}; +use crate::render::{invalid_argument, offset_overflow}; + +/// A return typed `Flow\Types\Type`. +pub struct TypeObject(Zval); + +impl IntoZval for TypeObject { + const TYPE: DataType = DataType::Object(Some("Flow\\Types\\Type")); + const NULLABLE: bool = false; + + fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { + *zv = self.0; + + Ok(()) + } +} + +#[php_class] +#[php( + name = "Flow\\ETL\\Column\\NativeColumn", + flags = ClassFlags::Final, + implements(ce = column_ce, stub = "Flow\\ETL\\Column\\Column") +)] +pub struct NativeColumn { + data: ArrayRef, + plan: Rc, +} + +impl NativeColumn { + pub fn new(data: ArrayRef, plan: Rc) -> Self { + debug_assert_eq!(data.data_type(), &data_type(&plan.kind)); + + Self { data, plan } + } + + pub fn data(&self) -> &ArrayRef { + &self.data + } + + fn kind(&self) -> &Kind { + &self.plan.kind + } + + fn row(&self, i: i64) -> Result { + usize::try_from(i) + .ok() + .filter(|i| *i < self.data.len()) + .ok_or_else(|| invalid_argument(format!("flow_php column row {i} is outside [0, {})", self.data.len()))) + } + + fn rows(&self, read: impl Fn(usize) -> Result) -> Result, PhpException> { + let mut rows = ZendHashTable::with_capacity(self.data.len() as u32); + + for i in 0..self.data.len() { + rows.push(read(i)?) + .map_err(|e| ext_exception(format!("flow_php failed to collect column rows: {e:?}")))?; + } + + Ok(rows) + } +} + +fn null_count(array: &dyn Array, kind: &Kind) -> usize { + match kind { + Kind::Null => array.len(), + _ => array.null_count(), + } +} + +/// The child rows of a list or map slice, compacted as the PHP columns hold them. +fn entries(offsets: &[i32], child: &ArrayRef) -> ArrayRef { + let start = offsets[0] as usize; + + child.slice(start, offsets[offsets.len() - 1] as usize - start) +} + +fn base(type_zv: Zval) -> Result { + if expect_object(&type_zv, "a Type")?.instance_of(find_class("Flow\\Types\\Type\\Logical\\OptionalType")?) { + return call_method(&type_zv, "base", &mut []); + } + + Ok(type_zv) +} + +/// `Column::withType()` of the PHP columns over the same storage: `Retype::assert()` at every level, and a required +/// structure element refuses the rows its optional one left absent. +fn retype(from: Zval, to: Zval, array: &ArrayRef, kind: &Kind) -> Result<(), PhpException> { + call_method( + &instance("Flow\\ETL\\Column\\Php\\Retype")?, + "assert", + &mut [from.shallow_clone(), to.shallow_clone(), zval_long(null_count(array.as_ref(), kind) as i64)], + )?; + + match kind { + Kind::List(element) => { + let list = array.as_list::(); + + retype( + call_method(&base(from)?, "element", &mut [])?, + call_method(&base(to)?, "element", &mut [])?, + &entries(list.value_offsets(), list.values()), + &element.kind, + ) + } + Kind::Map(key, value) => { + let map = array.as_map(); + let (from, to) = (base(from)?, base(to)?); + + retype( + call_method(&from, "key", &mut [])?, + call_method(&to, "key", &mut [])?, + &entries(map.value_offsets(), map.keys()), + &key.kind, + )?; + retype( + call_method(&from, "value", &mut [])?, + call_method(&to, "value", &mut [])?, + &entries(map.value_offsets(), map.values()), + &value.kind, + ) + } + Kind::Struct(fields) => { + let structure = array.as_struct(); + let from_elements = call_method(&base(from)?, "elements", &mut [])?; + let to_elements = call_method(&base(to)?, "elements", &mut [])?; + let from_elements: Vec<&Zval> = from_elements.array().map(|a| a.values().collect()).unwrap_or_default(); + let to_elements: Vec<&Zval> = to_elements.array().map(|a| a.values().collect()).unwrap_or_default(); + + for (((field, child), from_element), to_element) in + fields.iter().zip(structure.columns()).zip(from_elements).zip(to_elements) + { + let from_element = expect_object(from_element, "a StructureElement")?; + let to_element = expect_object(to_element, "a StructureElement")?; + let optional = |element| -> Result { + Ok(read_property(element, "optional")?.bool().unwrap_or(false)) + }; + + if optional(from_element)? && !optional(to_element)? { + let absent = (0..child.len()) + .filter(|i| !array.is_null(*i) && (matches!(field.kind, Kind::Null) || child.is_null(*i))) + .count(); + + if absent > 0 { + return Err(invalid_argument(format!( + "{absent} absent values under the required element \"{}\"", + field.name + ))); + } + } + + retype( + read_property(from_element, "type")?, + read_property(to_element, "type")?, + child, + &field.kind, + )?; + } + + Ok(()) + } + _ => Ok(()), + } +} + +fn class_name(zv: &Zval) -> String { + zv.object() + .and_then(|object| object.get_class_name().ok()) + .unwrap_or_else(|| zv.get_type().to_string()) +} + +#[php_impl] +impl NativeColumn { + pub fn __construct() -> PhpResult { + Err(ext_exception("Flow\\ETL\\Column\\NativeColumn is built by DefaultBackend")) + } + + #[php(name = "type")] + pub fn column_type(&self) -> TypeObject { + TypeObject(self.plan.type_zv.shallow_clone()) + } + + pub fn count(&self) -> i64 { + self.data.len() as i64 + } + + #[php(name = "isNull")] + pub fn is_null(&self, i: i64) -> PhpResult { + let row = self.row(i)?; + + Ok(matches!(self.kind(), Kind::Null) || self.data.is_null(row)) + } + + #[php(name = "nullCount")] + pub fn null_count(&self) -> i64 { + null_count(self.data.as_ref(), self.kind()) as i64 + } + + pub fn at(&self, i: i64) -> PhpResult { + physical_at(self.data.as_ref(), self.kind(), self.row(i)?) + } + + pub fn physicals(&self) -> PhpResult> { + self.rows(|i| physical_at(self.data.as_ref(), self.kind(), i)) + } + + pub fn value(&self, i: i64) -> PhpResult { + value_at(self.data.as_ref(), self.kind(), &self.plan.values, self.row(i)?) + } + + pub fn values(&self) -> PhpResult> { + self.rows(|i| value_at(self.data.as_ref(), self.kind(), &self.plan.values, i)) + } + + pub fn slice(&self, offset: i64, length: i64) -> PhpResult { + let (Ok(offset), Ok(length)) = (usize::try_from(offset), usize::try_from(length)) else { + return Err(invalid_argument(format!("flow_php cannot slice {length} rows from row {offset}"))); + }; + + if offset.checked_add(length).is_none_or(|end| end > self.data.len()) { + return Err(invalid_argument(format!( + "flow_php cannot slice {length} rows from row {offset} of {}", + self.data.len() + ))); + } + + Ok(NativeColumn::new(self.data.slice(offset, length), Rc::clone(&self.plan))) + } + + pub fn take(&self, indices: &ZendHashTable) -> PhpResult { + let mut rows = Vec::with_capacity(indices.len()); + + ht_for_each(indices, |_, _, index| { + let row = index + .long() + .ok_or_else(|| invalid_argument("flow_php column indices must be ints".to_string()))?; + rows.push(self.row(row)? as u32); + + Ok(()) + })?; + + let data = arrow_select::take::take(self.data.as_ref(), &UInt32Array::from(rows), None) + .map_err(|e| invalid_argument(format!("flow_php failed to take column rows: {e}")))?; + + Ok(NativeColumn::new(data, Rc::clone(&self.plan))) + } + + #[php(name = "withType")] + pub fn with_type(&self, r#type: &Zval) -> PhpResult { + retype(self.plan.type_zv.shallow_clone(), r#type.shallow_clone(), &self.data, self.kind())?; + let plan = type_plan(r#type)?; + + if data_type(&plan.kind) != data_type(self.kind()) { + return Err(invalid_argument(format!( + "flow_php cannot store {:?} in a {:?} column", + plan.kind, + self.kind() + ))); + } + + Ok(NativeColumn::new(self.data.clone(), plan)) + } + + pub fn concat(&self, others: &[&Zval]) -> PhpResult { + let mut arrays: Vec<&dyn Array> = vec![self.data.as_ref()]; + + for other in others { + let native = other + .extract::<&NativeColumn>() + .filter(|native| native.data.data_type() == self.data.data_type()) + .ok_or_else(|| { + invalid_argument(format!( + "Flow\\ETL\\Column\\NativeColumn cannot concat {}", + class_name(other) + )) + })?; + arrays.push(native.data.as_ref()); + } + + let data = arrow_select::concat::concat(&arrays).map_err(|e| match e { + ArrowError::OffsetOverflowError(last) => offset_overflow(last as u64), + e => invalid_argument(format!("flow_php failed to concat columns: {e}")), + })?; + + Ok(NativeColumn::new(data, Rc::clone(&self.plan))) + } + + pub fn encode(&self) -> PhpResult> { + let buffers = encode(&self.data.to_data(), self.kind()) + .map_err(|e| invalid_argument(format!("flow_php failed to encode a column: {e}")))?; + let mut list = ZendHashTable::with_capacity(buffers.len() as u32); + + for buffer in buffers { + list.push(zval_str(&buffer)) + .map_err(|e| ext_exception(format!("flow_php failed to collect column buffers: {e:?}")))?; + } + + Ok(list) + } +} diff --git a/src/extension/flow-php-ext/src/csv/columns.rs b/src/extension/flow-php-ext/src/csv/columns.rs new file mode 100644 index 0000000000..102dc4dab7 --- /dev/null +++ b/src/extension/flow-php-ext/src/csv/columns.rs @@ -0,0 +1,321 @@ +//! `RustCSVReaderNative::nextColumns()`: CSV cells straight into native columns, one builder per schema definition, +//! with `RowsBuilder::appendRows()`'s refusals - each column keeps its first, the lowest row wins (then the earliest +//! definition), and a NOT NULL column absent from the header is refused only when nothing else was. + +use std::rc::Rc; + +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::{ZendHashTable, Zval}; +use flow_batch_frame::kind::Kind; + +use crate::builder::{ + definition_nullable, is_types_exception, php_lane, schema_mismatch, value_does_not_match, Refusal, +}; +use crate::cast::{bool_from_str, float_from_str, integer_from_str, json_gate, parse_iso_date, parse_iso_datetime, CastKind}; +use crate::column::NativeColumn; +use crate::csv::CsvReader; +use crate::ctx::{ + self, call_method, call_static, ht_for_each, ht_insert, ht_insert_long, null_zval, transparent_exception, zval_long, + zval_str, +}; +use crate::date_check::iso_instant_micros; +use crate::exception::ext_exception; +use crate::json_check::json_valid; +use crate::kind_builder::KindBuilder; +use crate::physical::{append_physical, overflow}; +use crate::plan::{type_plan, TypePlan}; +use crate::render::invalid_argument; +use crate::uuid_check::is_uuid; +use crate::values::{datetime_days, datetime_micros, uuid_bytes}; + +/// A `Schema::definitions()` key: an int for a numeric name, as PHP keys it. +enum Key { + Index(i64), + Name(Vec), +} + +impl Key { + fn name(&self) -> Vec { + match self { + Key::Index(index) => index.to_string().into_bytes(), + Key::Name(name) => name.clone(), + } + } +} + +struct Column { + key: Key, + definition: Zval, + nullable: bool, + plan: Rc, + /// `None`: the header has no column of this name. + field: Option, + values: KindBuilder, + /// The first refused row and its `ColumnMismatchException`. + refusal: Option<(usize, Zval)>, +} + +/// The batch being built, and the schema and batch size it is built for. +pub struct CsvColumns { + schema: Zval, + schema_json: Vec, + batch_size: usize, + columns: Vec, + rows: usize, +} + +fn schema_json(schema: &Zval) -> Result, PhpException> { + let normalized = call_method(schema, "normalize", &mut [])?; + let json = crate::ctx::call_handle(ctx::json_encode()?, None, &mut [normalized], "encode a schema as JSON")?; + + Ok(json + .zend_str() + .ok_or_else(|| ext_exception("flow_php expected schema JSON to be a string"))? + .as_bytes() + .to_vec()) +} + +impl CsvColumns { + fn new(reader: &mut CsvReader, schema: &Zval, schema_json: Vec, batch_size: usize) -> Result { + let definitions = call_method(schema, "definitions", &mut [])?; + let definitions = definitions + .array() + .ok_or_else(|| ext_exception("flow_php expected Schema::definitions() to return an array"))?; + let mut columns = Vec::with_capacity(definitions.len()); + + ht_for_each(definitions, |name, index, definition| { + let key = match name { + Some(name) => Key::Name(name.as_bytes().to_vec()), + None => Key::Index(index as i64), + }; + let plan = type_plan(&call_method(definition, "type", &mut [])?)?; + + columns.push(Column { + field: reader.field_of(&key.name()), + key, + definition: definition.shallow_clone(), + nullable: definition_nullable(definition)?, + values: KindBuilder::new(&plan.kind), + plan, + refusal: None, + }); + + Ok(()) + })?; + + Ok(Self { + schema: schema.shallow_clone(), + schema_json, + batch_size, + columns, + rows: 0, + }) + } + + fn reset(&mut self) { + self.rows = 0; + + for column in &mut self.columns { + column.values = KindBuilder::new(&column.plan.kind); + column.refusal = None; + } + } +} + +/// A cell `cast.rs` casts natively, appended in its physical form; `false` hands it to the PHP lane. +fn native_cell(values: &mut KindBuilder, plan: &TypePlan, bytes: &[u8]) -> Result { + match (&plan.kind, &plan.cast) { + (Kind::Int64, CastKind::Integer) => Ok(integer_from_str(bytes).map(|value| values.append_fixed(&value.to_le_bytes())).is_some()), + (Kind::Float64, CastKind::Float) => Ok(float_from_str(bytes).map(|value| values.append_fixed(&value.to_le_bytes())).is_some()), + (Kind::Boolean, CastKind::Boolean) => Ok(bool_from_str(bytes).map(|value| values.append_bool(value)).is_some()), + (Kind::Bytes, CastKind::String) => values.append_bytes(bytes).map(|()| true).map_err(overflow), + (Kind::Bytes, CastKind::NonEmptyString) if !bytes.is_empty() => values.append_bytes(bytes).map(|()| true).map_err(overflow), + (Kind::Bytes, CastKind::Json) if json_gate(bytes) && json_valid(bytes) => { + values.append_bytes(bytes).map(|()| true).map_err(overflow) + } + (Kind::Uuid, CastKind::Uuid) if is_uuid(bytes) => { + Ok(uuid_bytes(bytes).map(|uuid| values.append_fixed(&uuid)).is_some()) + } + (Kind::Timestamp, CastKind::DateTime(zone)) => Ok(match iso_instant_micros(bytes) { + Some(micros) => Some(micros), + None => parse_iso_datetime(bytes, zone)?.and_then(|(_, instant)| instant.object().and_then(datetime_micros)), + } + .map(|micros| values.append_fixed(µs.to_le_bytes())) + .is_some()), + (Kind::Int32, CastKind::Date) => Ok(parse_iso_date(bytes)? + .and_then(|instant| instant.object().and_then(datetime_days)) + .map(|days| values.append_fixed(&(days as i32).to_le_bytes())) + .is_some()), + _ => Ok(false), + } +} + +/// One cell into its column: a NOT NULL null or a PHP-lane `Flow\Types` refusal becomes the column's refusal, any +/// other exception escapes as thrown. +fn append_cell(column: &mut Column, row: usize, cell: Option<&[u8]>) -> Result<(), PhpException> { + let Some(bytes) = cell else { + if !column.nullable { + column.refusal = Some((row, value_does_not_match(&column.definition, null_zval(), None)?)); + + return Ok(()); + } + + column.values.append_null(); + + return Ok(()); + }; + + if native_cell(&mut column.values, &column.plan, bytes)? { + return Ok(()); + } + + let value = zval_str(bytes); + + match php_lane(&column.plan, &value) { + Ok(physical) => append_physical(&mut column.values, &column.plan.kind, &physical), + Err(Refusal::Cast(mut exception)) => { + if !is_types_exception(&exception)? { + return Err(transparent_exception(&mut exception)); + } + + column.refusal = Some((row, value_does_not_match(&column.definition, value, None)?)); + + Ok(()) + } + Err(Refusal::Physical(mut exception)) => { + if !is_types_exception(&exception)? { + return Err(transparent_exception(&mut exception)); + } + + let mut reason = Zval::new(); + reason.set_object(&mut exception); + column.refusal = Some((row, value_does_not_match(&column.definition, value, Some(reason))?)); + + Ok(()) + } + } +} + +fn finish_batch(state: &mut CsvColumns) -> Result { + let refusal = state + .columns + .iter() + .filter_map(|column| column.refusal.as_ref()) + .fold(None::<&(usize, Zval)>, |lowest, refusal| match lowest { + Some(lowest) if lowest.0 <= refusal.0 => Some(lowest), + _ => Some(refusal), + }); + + if let Some((row, cause)) = refusal { + return Err(schema_mismatch(zval_long(*row as i64), cause.shallow_clone())); + } + + if let Some(absent) = state.columns.iter().find(|column| column.field.is_none() && !column.nullable) { + let cause = call_static( + "Flow\\ETL\\Exception\\ColumnMismatchException", + "missingColumn", + &mut [absent.definition.shallow_clone()], + )?; + + return Err(schema_mismatch(zval_long(0), cause)); + } + + let mut columns = ZendHashTable::with_capacity(state.columns.len() as u32); + + for column in &state.columns { + let data = column + .values + .finish(&column.plan.kind) + .map_err(|e| invalid_argument(format!("flow_php built an invalid column: {e}")))?; + let mut native = Zval::new(); + ext_php_rs::convert::IntoZval::set_zval( + NativeColumn::new(arrow_array::make_array(data), Rc::clone(&column.plan)), + &mut native, + false, + )?; + + match &column.key { + Key::Index(index) => ht_insert_long(&mut columns, *index, native), + Key::Name(name) => ht_insert(&mut columns, name, native), + } + } + + let mut columns_zv = Zval::new(); + columns_zv.set_hashtable(columns); + + call_static( + "Flow\\ETL\\Rows", + "fromColumns", + &mut [state.schema.shallow_clone(), columns_zv, zval_long(state.rows as i64)], + ) +} + +pub fn next_columns( + reader: &mut CsvReader, + pending: &mut Option, + schema: &Zval, + batch_size: usize, +) -> Result { + if reader.headers().is_empty() { + return Ok(null_zval()); + } + + let same_object = pending.as_ref().is_some_and(|state| { + state.schema.object().map(|object| object.handle) == schema.object().map(|object| object.handle) + }); + + if !same_object { + let json = schema_json(schema)?; + + match pending { + Some(state) if state.schema_json == json => state.schema = schema.shallow_clone(), + Some(state) if state.rows > 0 => { + return Err(ext_exception("flow_php cannot change the schema of a pending CSV batch")); + } + _ => *pending = Some(CsvColumns::new(reader, schema, json, batch_size)?), + } + } + + let state = pending.as_mut().expect("built above"); + + if state.batch_size != batch_size { + if state.rows > 0 { + return Err(ext_exception("flow_php cannot change the batch size of a pending CSV batch")); + } + + state.batch_size = batch_size; + } + + while state.rows < state.batch_size && reader.next_record() { + let row = state.rows; + + for column in &mut state.columns { + if column.refusal.is_some() { + continue; + } + + let Some(field) = column.field else { + column.values.append_null(); + + continue; + }; + + if let Err(e) = append_cell(column, row, reader.cell(field)) { + state.reset(); + + return Err(e); + } + } + + state.rows += 1; + } + + if state.rows == 0 || (state.rows < state.batch_size && !reader.is_finished()) { + return Ok(null_zval()); + } + + let batch = finish_batch(state); + state.reset(); + + batch +} diff --git a/src/extension/flow-php-ext/src/csv/fold.rs b/src/extension/flow-php-ext/src/csv/fold.rs index 21131eb326..74a3800632 100644 --- a/src/extension/flow-php-ext/src/csv/fold.rs +++ b/src/extension/flow-php-ext/src/csv/fold.rs @@ -9,7 +9,7 @@ use std::collections::HashMap; use ext_php_rs::exception::PhpException; use ext_php_rs::types::{ZendHashTable, Zval}; -use crate::ctx::{call_handle, zval_str, Ctx}; +use crate::ctx::{self, call_handle, zval_str}; use crate::csv::php_trim; use crate::csv::tokenizer::is_space; use crate::date_check::{checkdate, iso_date_gate, iso_date_time_gate}; @@ -129,14 +129,12 @@ impl Candidates { /// `StringTypeNarrower::narrow()` for a string cell, without the HTML and XML rungs. pub struct Narrower { candidates: Candidates, - ctx: Ctx, } impl Narrower { fn new(candidates: Candidates) -> Result { Ok(Self { candidates, - ctx: Ctx::new()?, }) } @@ -192,7 +190,7 @@ impl Narrower { } // same one-sided rule as the cast: only PHP may say "not JSON" - let valid = call_handle(self.ctx.json_validate()?, None, &mut [zval_str(value)], "validate a JSON cell")?; + let valid = call_handle(ctx::json_validate()?, None, &mut [zval_str(value)], "validate a JSON cell")?; Ok(valid.bool().unwrap_or(false)) } @@ -208,7 +206,7 @@ impl Narrower { return Ok(Some(Leaf::Date)); } - let parts_zv = call_handle(self.ctx.date_parse()?, None, &mut [zval_str(value)], "parse a temporal cell")?; + let parts_zv = call_handle(ctx::date_parse()?, None, &mut [zval_str(value)], "parse a temporal cell")?; let parts = parts_zv .array() .ok_or_else(|| ext_exception("flow_php expected date_parse() to return an array"))?; @@ -242,11 +240,11 @@ impl Narrower { } fn is_timezone(&mut self, value: &[u8]) -> Result { - if self.ctx.timezone_identifiers()?.contains(value) { + if ctx::is_timezone_identifier(value)? { return Ok(true); } - Ok(is_offset(value) && self.ctx.timezone_accepts(value)?) + Ok(is_offset(value) && ctx::timezone_accepts(value)?) } } diff --git a/src/extension/flow-php-ext/src/csv/mod.rs b/src/extension/flow-php-ext/src/csv/mod.rs index 6b7fc4e6ae..c94def1f88 100644 --- a/src/extension/flow-php-ext/src/csv/mod.rs +++ b/src/extension/flow-php-ext/src/csv/mod.rs @@ -1,16 +1,16 @@ //! Native CSV reading: records and fields from `tokenizer`, rows shaped exactly like //! `CSVEncoder::decode()` + `CSVRowNormalizer::normalize()` shape them. +pub mod columns; pub mod fold; pub mod tokenizer; use ext_php_rs::boxed::ZBox; use ext_php_rs::exception::PhpException; -use ext_php_rs::types::{ZendHashTable, ZendObject, ZendStr, Zval}; +use ext_php_rs::types::{ZendHashTable, ZendStr, Zval}; -use crate::ctx::{array_key_index, ht_insert_key, null_zval, write_slot, zval_str, HtKey}; +use crate::ctx::{array_key_index, ht_insert_key, null_zval, zval_str, HtKey}; use crate::exception::ext_exception; -use crate::hydrate::RowValuesClass; use tokenizer::{Dialect, Field, Record, Tokenizer}; /// A header name resolved once into the array key `array_combine()` would use for it. @@ -42,7 +42,7 @@ impl Header { } } -/// One key of `RawRowValues::$values`: `array_combine()` keeps a duplicated header at its first position with the +/// One key of a row: `array_combine()` keeps a duplicated header at its first position with the /// value of its last one. struct Cell { header_index: usize, @@ -58,6 +58,7 @@ pub struct CsvReader { record: Record, first_row_pending: bool, consumed_bytes: u64, + finished: bool, } impl CsvReader { @@ -97,6 +98,7 @@ impl CsvReader { record: Record::default(), first_row_pending: false, consumed_bytes: 0, + finished: false, }) } @@ -106,6 +108,36 @@ impl CsvReader { pub fn finish(&mut self) { self.tokenizer.finish(); + self.finished = true; + } + + pub fn is_finished(&self) -> bool { + self.finished + } + + /// The field of the header named `name` (the last of duplicates, as `array_combine()` keeps it); `None` before the + /// header resolved or when no header has that name. + pub fn field_of(&mut self, name: &[u8]) -> Option { + self.resolve_headers(); + let headers = self.headers.as_ref()?; + + self.cells + .iter() + .find(|cell| headers[cell.header_index].name == name) + .map(|cell| cell.field_index) + } + + /// Advances to the next complete row, counting its bytes; `false` when none is buffered. + pub fn next_record(&mut self) -> bool { + self.resolve_headers(); + + self.headers.is_some() + && next_row(&mut self.first_row_pending, &mut self.tokenizer, &mut self.record, &mut self.consumed_bytes) + } + + /// The current row's cell of `field`, as `CSVRowNormalizer::normalize()` shapes it; `None` is null. + pub fn cell(&self, field: usize) -> Option<&[u8]> { + cell_value(&self.record, field, self.empty_to_null) } /// The bytes, as read, of every row `next` and `fold` produced so far: line endings included, the header @@ -124,8 +156,8 @@ impl CsvReader { .unwrap_or_default() } - /// Up to `batch_size` `RawRowValues`; an empty list when no complete record is buffered. - pub fn next(&mut self, batch_size: usize, class: &RowValuesClass) -> Result, PhpException> { + /// Up to `batch_size` rows keyed by header; an empty list when no complete record is buffered. + pub fn next(&mut self, batch_size: usize) -> Result, PhpException> { self.resolve_headers(); let mut batch = ZendHashTable::new(); @@ -140,7 +172,7 @@ impl CsvReader { } batch - .push(row_values(headers, &self.record, self.empty_to_null, class)) + .push(row_values(headers, &self.record, self.empty_to_null)) .map_err(|e| ext_exception(format!("flow_php failed to collect CSV row values: {e:?}")))?; } @@ -250,8 +282,8 @@ fn cell_value(record: &Record, index: usize, empty_to_null: bool) -> Option<&[u8 } } -/// `new RawRowValues(array_combine($headers, $normalizer->normalize($fields, count($headers))))`. -fn row_values(headers: &[Header], record: &Record, empty_to_null: bool, class: &RowValuesClass) -> ZBox { +/// `array_combine($headers, $normalizer->normalize($fields, count($headers)))`. +fn row_values(headers: &[Header], record: &Record, empty_to_null: bool) -> Zval { let mut values = ZendHashTable::with_capacity(headers.len() as u32); for (index, header) in headers.iter().enumerate() { @@ -260,17 +292,10 @@ fn row_values(headers: &[Header], record: &Record, empty_to_null: bool, class: & ht_insert_key(&mut values, &header.key(), value); } - let mut row_values = ZendObject::new(class.ce); - let mut values_zv = Zval::new(); values_zv.set_hashtable(values); - write_slot(&mut row_values, class.values_slot, values_zv); - - let mut metadata_zv = Zval::new(); - metadata_zv.set_hashtable(ZendHashTable::new()); - write_slot(&mut row_values, class.metadata_slot, metadata_zv); - row_values + values_zv } /// PHP's `trim()`: `" \t\n\r\0\x0B"`, nothing else. diff --git a/src/extension/flow-php-ext/src/ctx.rs b/src/extension/flow-php-ext/src/ctx.rs index ebca596f0d..fa004b19f2 100644 --- a/src/extension/flow-php-ext/src/ctx.rs +++ b/src/extension/flow-php-ext/src/ctx.rs @@ -1,13 +1,13 @@ //! PHP-engine plumbing: class-entry/slot lookups, hashtable helpers, calls and -//! per-instance caches (timezones, enums, callables). +//! request-scoped caches (timezones, enums, callables). use std::collections::{HashMap, HashSet}; +use std::rc::Rc; use ext_php_rs::boxed::ZBox; -use ext_php_rs::convert::IntoZvalDyn; use ext_php_rs::exception::PhpException; use ext_php_rs::ffi::{ - _zend_property_info, zend_call_known_function, zend_hash_find, zend_hash_index_update, + _zend_property_info, zend_call_known_function, zend_hash_index_update, zend_hash_str_find, zend_hash_str_update, zend_hash_update, zend_ulong, }; use ext_php_rs::flags::ClassFlags; @@ -15,19 +15,8 @@ use ext_php_rs::types::{ZendHashTable, ZendObject, ZendStr, Zval}; use ext_php_rs::zend::{ClassEntry, ExecutorGlobals, Function}; use crate::exception::ext_exception; - -// Not in ext-php-rs's allowed bindings; ZEND_API symbols with the same ABI as -// the bound zend_hash_*_update functions. -extern "C" { - fn zend_hash_str_add( - ht: *mut ZendHashTable, - key: *const std::ffi::c_char, - len: usize, - data: *mut Zval, - ) -> *mut Zval; - - fn zend_hash_index_add(ht: *mut ZendHashTable, h: zend_ulong, data: *mut Zval) -> *mut Zval; -} +use crate::globals::with_ctx; +use crate::plan::TypePlan; /// PHP array-key coercion (`_zend_handle_numeric_str`): parse + canonical /// re-format equality rejects "+5", "-0", leading zeros and whitespace exactly @@ -70,15 +59,6 @@ pub enum HtKey<'a> { Str(&'a ZendStr), } -pub fn ht_find_key<'a>(ht: &'a ZendHashTable, key: &HtKey<'_>) -> Option<&'a Zval> { - match key { - HtKey::Index(index) => ht.get_index(*index), - HtKey::Str(name) => unsafe { - zend_hash_find(ht, std::ptr::from_ref(*name).cast_mut()).as_ref() - }, - } -} - /// [`ht_insert`] for a pre-resolved key; ownership of `value` moves into the /// table. pub fn ht_insert_key(ht: &mut ZendHashTable, key: &HtKey<'_>, mut value: Zval) { @@ -100,7 +80,7 @@ pub fn ht_insert_key(ht: &mut ZendHashTable, key: &HtKey<'_>, mut value: Zval) { std::mem::forget(value); } -pub fn ht_insert_index(ht: &mut ZendHashTable, index: i64, mut value: Zval) { +pub fn ht_insert_long(ht: &mut ZendHashTable, index: i64, mut value: Zval) { unsafe { zend_hash_index_update(ht, index as u64, std::ptr::from_mut(&mut value)); } @@ -108,29 +88,12 @@ pub fn ht_insert_index(ht: &mut ZendHashTable, index: i64, mut value: Zval) { std::mem::forget(value); } -/// Inserts only when the key is absent (PHP array-key coercion applies) and -/// reports whether it did; on `false` the value is dropped, not inserted. -pub fn ht_add(ht: &mut ZendHashTable, key: &[u8], mut value: Zval) -> bool { - let added = unsafe { - match array_key_index(key) { - Some(index) => { - !zend_hash_index_add(ht, index as u64, std::ptr::from_mut(&mut value)).is_null() - } - None => !zend_hash_str_add( - ht, - key.as_ptr().cast(), - key.len(), - std::ptr::from_mut(&mut value), - ) - .is_null(), - } - }; - - if added { - std::mem::forget(value); +/// `$array[$key]` with PHP array-key coercion. +pub fn ht_get<'a>(ht: &'a ZendHashTable, key: &[u8]) -> Option<&'a Zval> { + match array_key_index(key) { + Some(index) => ht.get_index(index), + None => unsafe { zend_hash_str_find(ht, key.as_ptr().cast(), key.len()).as_ref() }, } - - added } pub fn zval_str(bytes: &[u8]) -> Zval { @@ -151,24 +114,6 @@ pub fn null_zval() -> Zval { zv } -/// `throw new SchemaMismatchException($rowIndex, )`, where the cause comes from a -/// `ColumnMismatchException` factory - the PHP side authors every schema-mismatch message. -pub fn schema_mismatch( - schema_mismatch_ce: &'static ClassEntry, - factory: &'static Function, - row_index: u64, - args: &mut [Zval], -) -> Result { - let cause = call_handle_transparent(factory, None, args)?; - let mut wrapped = construct_with_zvals( - schema_mismatch_ce, - &mut [zval_long(row_index as i64), cause], - "a SchemaMismatchException", - )?; - - Ok(transparent_exception(&mut wrapped)) -} - pub fn find_class(name: &str) -> Result<&'static ClassEntry, PhpException> { ClassEntry::try_find(name).ok_or_else(|| { ext_exception(format!( @@ -241,8 +186,8 @@ pub fn write_slot(obj: &mut ZendObject, offset: u32, value: Zval) { } } -/// Reads one property with `BP_VAR_R` semantics; `ZendObject::get_property` -/// passes `BP_VAR_W`, which trips the readonly-property guard on `HydratorColumn`. +/// Reads one property with `BP_VAR_R` semantics; `ZendObject::get_property` passes `BP_VAR_W`, which trips the +/// readonly-property guard. pub fn read_property(obj: &ZendObject, name: &str) -> Result { let handler = unsafe { obj.handlers.as_ref() } .and_then(|handlers| handlers.read_property) @@ -267,18 +212,17 @@ pub fn read_property(obj: &ZendObject, name: &str) -> Result Ok(value.shallow_clone()) } -pub fn construct_object( - ce: &'static ClassEntry, - args: Vec<&dyn IntoZvalDyn>, - context: &str, -) -> Result, PhpException> { - let obj = ZendObject::new(ce); +/// `$object->$method(...$args)`; an exception the method throws surfaces as itself. +pub fn call_method(object: &Zval, method: &str, args: &mut [Zval]) -> Result { + let object = expect_object(object, "a method receiver")?; + let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php failed to resolve an object class"))?; - obj.try_call_method("__construct", args) - .map_err(|e| ext_exception(format!("flow_php failed to construct {context}: {e:?}")))?; - ensure_no_pending_exception(&format!("construct {context}"))?; + call_handle_transparent(ce_method_ref(ce, method)?, Some(object), args) +} - Ok(obj) +/// `$class::$method(...$args)`; an exception the method throws surfaces as itself. +pub fn call_static(class: &str, method: &str, args: &mut [Zval]) -> Result { + call_handle_transparent(ce_method_ref(find_class(class)?, method)?, None, args) } /// Constructs a fresh object and calls its `__construct` with already-owned @@ -302,26 +246,6 @@ pub fn construct_with_zvals( Ok(obj) } -fn method_handle(class: &str, method: &str) -> Result { - Function::try_from_method(class, method).ok_or_else(|| { - ext_exception(format!( - "flow_php failed to resolve method {class}::{method}" - )) - }) -} - -fn function_handle(name: &str) -> Result { - Function::try_from_function(name) - .ok_or_else(|| ext_exception(format!("flow_php failed to resolve function {name}"))) -} - -/// Resolves a method to a reference into the class function table WITHOUT -/// copying the zend_function: the engine writes into userland op_arrays -/// (run-time cache), and a copy discards those writes on every call. -fn method_handle_ref(class: &str, method: &str) -> Result<&'static Function, PhpException> { - ce_method_ref(find_class(class)?, method) -} - pub fn ce_method_ref(ce: &ClassEntry, method: &str) -> Result<&'static Function, PhpException> { let function = unsafe { ext_php_rs::ffi::zend_hash_str_find_ptr_lc( @@ -459,513 +383,440 @@ pub fn call_handle( Ok(retval) } -pub struct DateTimeFns { - pub ce: &'static ClassEntry, - pub set_timezone: Function, -} - -pub struct IntervalFns { - pub ce: &'static ClassEntry, - pub construct: Function, - pub spec: Zval, - pub names: [ZBox; 8], -} - +/// Request-scoped caches of class entries, function handles and value zvals, reached only through [`with_ctx`]: +/// every function below reads and writes the cache inside the closure and calls PHP (autoload, constructors, +/// functions) outside it, so PHP code re-entering flow_php never meets a borrowed `Ctx`. +#[derive(Default)] pub struct Ctx { - uuid_ce: Option<(&'static ClassEntry, u32)>, - json_ce: Option<(&'static ClassEntry, u32, u32)>, + uuid: Option<(&'static ClassEntry, u32)>, + json: Option<(&'static ClassEntry, u32, u32)>, interval: Option, - timezone_ce: Option<&'static ClassEntry>, + timezone: Option, datetime_immutable: Option, - datetime_mutable: Option, + datetime_get_timezone: HashMap, + datetime_cast: HashMap, timezones: HashMap, Zval>, enums: HashMap, Zval>, - fn_defined: Option, - fn_constant: Option, - value_decoder_statics: HashMap<&'static str, &'static Function>, - value_encoder_statics: HashMap<&'static str, &'static Function>, - fn_json_encode: Option, - fn_json_decode: Option, - fn_json_validate: Option, - fn_date_parse: Option, + functions: HashMap<&'static str, &'static Function>, timezone_identifiers: Option>>, - timezone_construct: Option<&'static Function>, - metadata_from_array: Option<&'static Function>, - metadata_map_slot: Option, - typed_row_values_slots: Option<(u32, u32)>, - schema_set_metadata: Option<&'static Function>, - schema_find_definition: Option<&'static Function>, - timezone_get_name: Option<&'static Function>, - datetime_encode: HashMap, - datetime_cast: HashMap, - save_html: HashMap, - format_u: Option, - format_his: Option, - str_true: Option, - str_false: Option, + strings: HashMap<&'static [u8], Zval>, + instances: HashMap<&'static str, Zval>, + plans: HashMap, Rc>, + /// `plans` by Type object handle; each entry holds its object, so the handle is not reused while cached. + type_plans: HashMap)>, } -pub struct DateTimeEncFns { - pub get_timestamp: &'static Function, - pub format: &'static Function, - pub get_timezone: &'static Function, +/// Type objects `type_plans` holds before it starts over. +const TYPE_PLANS: usize = 1024; + +#[derive(Clone, Copy)] +pub struct DateTimeFns { + pub ce: &'static ClassEntry, + pub set_timezone: &'static Function, +} + +#[derive(Clone, Copy)] +pub struct IntervalFns { + pub ce: &'static ClassEntry, + pub construct: &'static Function, } +#[derive(Clone, Copy)] +pub struct TimezoneFns { + pub ce: &'static ClassEntry, + pub construct: &'static Function, + pub get_name: &'static Function, +} + +#[derive(Clone, Copy)] pub struct DateTimeCastFns { pub set_time: &'static Function, pub format: &'static Function, } -impl Ctx { - pub fn new() -> Result { - Ok(Self { - uuid_ce: None, - json_ce: None, - interval: None, - timezone_ce: None, - datetime_immutable: None, - datetime_mutable: None, - timezones: HashMap::new(), - enums: HashMap::new(), - fn_defined: None, - fn_constant: None, - value_decoder_statics: HashMap::new(), - value_encoder_statics: HashMap::new(), - fn_json_encode: None, - fn_json_decode: None, - fn_json_validate: None, - fn_date_parse: None, - timezone_identifiers: None, - timezone_construct: None, - metadata_from_array: None, - metadata_map_slot: None, - typed_row_values_slots: None, - schema_set_metadata: None, - schema_find_definition: None, - timezone_get_name: None, - datetime_encode: HashMap::new(), - datetime_cast: HashMap::new(), - save_html: HashMap::new(), - format_u: None, - format_his: None, - str_true: None, - str_false: None, - }) - } +/// One instance of a stateless PHP class (a `Physical`, `PhysicalFor`), constructed without arguments. +pub fn instance(class: &'static str) -> Result { + cached( + |ctx| ctx.instances.get(class).map(Zval::shallow_clone), + || { + let ce = find_class(class)?; + let mut object = ZendObject::new(ce); - /// Property-table slot offsets `(values, metadata)` on `Flow\ETL\Row\TypedRowValues`. - pub fn typed_row_values_slots(&mut self) -> Result<(u32, u32), PhpException> { - if self.typed_row_values_slots.is_none() { - let ce = find_class("Flow\\ETL\\Row\\TypedRowValues")?; - self.typed_row_values_slots = - Some((property_offset(ce, "values")?, property_offset(ce, "metadata")?)); - } - - Ok(self.typed_row_values_slots.expect("just initialized")) - } - - /// `Schema::setMetadata` / `Schema::findDefinition` - the native hydrate and cast paths fold - /// `RawRowValues::metadata` into the batch Schema exactly like `HydratedBatch` does in PHP. - pub fn schema_set_metadata(&mut self) -> Result<&'static Function, PhpException> { - if self.schema_set_metadata.is_none() { - self.schema_set_metadata = Some(method_handle_ref("Flow\\ETL\\Schema", "setMetadata")?); - } - - Ok(self.schema_set_metadata.expect("just initialized")) - } + if !ce.constructor.is_null() { + call_handle_transparent(ce_method_ref(ce, "__construct")?, Some(&object), &mut [])?; + } - pub fn schema_find_definition(&mut self) -> Result<&'static Function, PhpException> { - if self.schema_find_definition.is_none() { - self.schema_find_definition = - Some(method_handle_ref("Flow\\ETL\\Schema", "findDefinition")?); - } + let mut zv = Zval::new(); + zv.set_object(&mut object); - Ok(self.schema_find_definition.expect("just initialized")) - } + Ok(zv) + }, + |ctx, zv| { + ctx.instances.insert(class, zv.shallow_clone()); + }, + ) +} - pub fn metadata_map_slot(&mut self) -> Result { - if self.metadata_map_slot.is_none() { - self.metadata_map_slot = Some(property_offset( - find_class("Flow\\ETL\\Schema\\Metadata")?, - "map", - )?); - } +pub fn plan(json: &[u8]) -> Result>, PhpException> { + with_ctx(|ctx| Ok(ctx.plans.get(json).cloned())) +} - Ok(self.metadata_map_slot.expect("just initialized")) - } +pub fn store_plan(json: Vec, plan: &Rc) -> Result<(), PhpException> { + with_ctx(|ctx| { + ctx.plans.insert(json, Rc::clone(plan)); + Ok(()) + }) +} - pub fn timezone_get_name(&mut self) -> Result<&'static Function, PhpException> { - if self.timezone_get_name.is_none() { - self.timezone_get_name = Some(method_handle_ref("DateTimeZone", "getName")?); - } +/// The plan of a Type object seen before; Types are immutable, so the object names its plan. +pub fn type_plan_of(type_zv: &Zval) -> Result>, PhpException> { + let Some(handle) = type_zv.object().map(|object| object.handle) else { + return Ok(None); + }; - Ok(self.timezone_get_name.expect("just initialized")) - } + with_ctx(|ctx| Ok(ctx.type_plans.get(&handle).map(|(_, plan)| Rc::clone(plan)))) +} - /// Per-datetime-class encode handles (getTimestamp/format/getTimezone). - pub fn datetime_encode_fns( - &mut self, - ce: *const ClassEntry, - ) -> Result<&DateTimeEncFns, PhpException> { - let key = ce as usize; - - if let std::collections::hash_map::Entry::Vacant(entry) = self.datetime_encode.entry(key) { - let ce_ref = unsafe { ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve a datetime class"))?; - - entry.insert(DateTimeEncFns { - get_timestamp: ce_method_ref(ce_ref, "getTimestamp")?, - format: ce_method_ref(ce_ref, "format")?, - get_timezone: ce_method_ref(ce_ref, "getTimezone")?, - }); - } +pub fn store_type_plan(type_zv: &Zval, plan: &Rc) -> Result<(), PhpException> { + let Some(handle) = type_zv.object().map(|object| object.handle) else { + return Ok(()); + }; - Ok(self.datetime_encode.get(&key).expect("just inserted")) - } + // the evicted objects are released outside the context: freeing one may run PHP code + let _evicted = with_ctx(|ctx| { + let evicted = if ctx.type_plans.len() >= TYPE_PLANS { + std::mem::take(&mut ctx.type_plans) + } else { + HashMap::new() + }; + ctx.type_plans.insert(handle, (type_zv.shallow_clone(), Rc::clone(plan))); - pub fn save_html(&mut self, ce: *const ClassEntry) -> Result<&'static Function, PhpException> { - let key = ce as usize; + Ok(evicted) + })?; - if let std::collections::hash_map::Entry::Vacant(entry) = self.save_html.entry(key) { - let ce_ref = unsafe { ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve an HTML class"))?; - entry.insert(ce_method_ref(ce_ref, "saveHtml")?); - } + Ok(()) +} - Ok(self.save_html.get(&key).expect("just inserted")) +/// A cached handle: read inside the context, resolved outside it on a miss, then stored. +fn cached( + read: impl FnOnce(&Ctx) -> Option, + resolve: impl FnOnce() -> Result, + store: impl FnOnce(&mut Ctx, &T), +) -> Result { + if let Some(value) = with_ctx(|ctx| Ok(read(ctx)))? { + return Ok(value); } - /// Cached `"u"` format-string zval for microsecond reads. - pub fn format_u(&mut self) -> Result<&Zval, PhpException> { - if self.format_u.is_none() { - self.format_u = Some(zval_str(b"u")); - } + let value = resolve()?; + with_ctx(|ctx| { + store(ctx, &value); + Ok(()) + })?; - Ok(self.format_u.as_ref().expect("just initialized")) - } + Ok(value) +} - /// Cached `"H:i:s.u"` format-string zval for the date midnight check. - pub fn format_his(&mut self) -> Result<&Zval, PhpException> { - if self.format_his.is_none() { - self.format_his = Some(zval_str(b"H:i:s.u")); - } +/// An internal PHP function; the engine's function table outlives every request. +fn function(name: &'static str) -> Result<&'static Function, PhpException> { + cached( + |ctx| ctx.functions.get(name).copied(), + || { + let table = ExecutorGlobals::get().function_table; - Ok(self.format_his.as_ref().expect("just initialized")) - } + let found = unsafe { ext_php_rs::ffi::zend_hash_str_find_ptr_lc(table, name.as_ptr().cast(), name.len()) } + .cast::(); - /// Cached `"true"`/`"false"` string zvals for bool-to-string casts. - pub fn bool_str(&mut self, value: bool) -> Result<&Zval, PhpException> { - let slot = if value { - &mut self.str_true - } else { - &mut self.str_false - }; + unsafe { found.as_ref() } + .ok_or_else(|| ext_exception(format!("flow_php failed to resolve function {name}"))) + }, + |ctx, function| { + ctx.functions.insert(name, function); + }, + ) +} - if slot.is_none() { - *slot = Some(zval_str(if value { b"true" } else { b"false" })); - } +pub fn json_encode() -> Result<&'static Function, PhpException> { + function("json_encode") +} - Ok(slot.as_ref().expect("just initialized")) - } +pub fn json_validate() -> Result<&'static Function, PhpException> { + function("json_validate") +} - /// Per-datetime-class cast handles (setTime/format), subclass-safe. - pub fn datetime_cast_fns( - &mut self, - ce: *const ClassEntry, - ) -> Result<&DateTimeCastFns, PhpException> { - let key = ce as usize; - - if let std::collections::hash_map::Entry::Vacant(entry) = self.datetime_cast.entry(key) { - let ce_ref = unsafe { ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve a datetime class"))?; - - entry.insert(DateTimeCastFns { - set_time: ce_method_ref(ce_ref, "setTime")?, - format: ce_method_ref(ce_ref, "format")?, - }); - } +pub fn date_parse() -> Result<&'static Function, PhpException> { + function("date_parse") +} - Ok(self.datetime_cast.get(&key).expect("just inserted")) - } +/// A cached string zval, e.g. a format string. +pub fn string(bytes: &'static [u8]) -> Result { + cached( + |ctx| ctx.strings.get(bytes).map(Zval::shallow_clone), + || Ok(zval_str(bytes)), + |ctx, zv| { + ctx.strings.insert(bytes, zv.shallow_clone()); + }, + ) +} - /// Cached handles to `ValueEncoder`'s public static markup serializers. - pub fn value_encoder_static( - &mut self, - method: &'static str, - ) -> Result<&'static Function, PhpException> { - if !self.value_encoder_statics.contains_key(method) { - let handle = method_handle_ref("Flow\\Floe\\ValueEncoder", method)?; - self.value_encoder_statics.insert(method, handle); - } +/// `"true"`/`"false"` for bool-to-string casts. +pub fn bool_str(value: bool) -> Result { + string(if value { b"true" } else { b"false" }) +} - Ok(self - .value_encoder_statics - .get(method) - .expect("just inserted")) - } +pub fn uuid() -> Result<(&'static ClassEntry, u32), PhpException> { + cached( + |ctx| ctx.uuid, + || { + let ce = find_class("Flow\\Types\\Value\\Uuid")?; + Ok((ce, property_offset(ce, "value")?)) + }, + |ctx, uuid| ctx.uuid = Some(*uuid), + ) +} - pub fn json(&mut self) -> Result<(&'static ClassEntry, u32, u32), PhpException> { - if self.json_ce.is_none() { +pub fn json() -> Result<(&'static ClassEntry, u32, u32), PhpException> { + cached( + |ctx| ctx.json, + || { let ce = find_class("Flow\\Types\\Value\\Json")?; - self.json_ce = Some(( - ce, - property_offset(ce, "value")?, - property_offset(ce, "isObject")?, - )); - } - - Ok(self.json_ce.expect("just initialized")) - } - - /// Enum cases cached per `Class::Case`, resolved with the same validation - /// and errors as `ValueDecoder` (enum_exists + defined + constant). - pub fn enum_case(&mut self, class: &[u8], case: &[u8]) -> Result { - let mut cache_key = Vec::with_capacity(class.len() + case.len() + 2); - cache_key.extend_from_slice(class); - cache_key.extend_from_slice(b"::"); - cache_key.extend_from_slice(case); - - if let Some(cached) = self.enums.get(&cache_key) { - return Ok(cached.shallow_clone()); - } + Ok((ce, property_offset(ce, "value")?, property_offset(ce, "isObject")?)) + }, + |ctx, json| ctx.json = Some(*json), + ) +} - let constant_name = std::str::from_utf8(&cache_key) - .map_err(|_| ext_exception("flow_php expected an enum name to be UTF-8"))? - .to_string(); - let class_name = std::str::from_utf8(class) - .expect("validated above") - .to_string(); - let case_name = std::str::from_utf8(case) - .expect("validated above") - .to_string(); - - let is_enum = ClassEntry::try_find(&class_name) - .is_some_and(|ce| ce.flags().contains(ClassFlags::Enum)); - - if !is_enum { - return Err(ext_exception(format!( - "flow_php cannot restore enum of class \"{class_name}\", enum not found" - ))); - } +pub fn interval() -> Result { + cached( + |ctx| ctx.interval, + || { + let ce = find_class("DateInterval")?; + Ok(IntervalFns { + ce, + construct: ce_method_ref(ce, "__construct")?, + }) + }, + |ctx, interval| ctx.interval = Some(*interval), + ) +} - if self.fn_defined.is_none() { - self.fn_defined = Some(function_handle("defined")?); - self.fn_constant = Some(function_handle("constant")?); - } +pub fn datetime_immutable() -> Result { + cached( + |ctx| ctx.datetime_immutable, + || { + let ce = find_class("DateTimeImmutable")?; + Ok(DateTimeFns { + ce, + set_timezone: ce_method_ref(ce, "setTimezone")?, + }) + }, + |ctx, fns| ctx.datetime_immutable = Some(*fns), + ) +} - let constant_name_zv = zval_str(constant_name.as_bytes()); +fn timezone_fns() -> Result { + cached( + |ctx| ctx.timezone, + || { + let ce = find_class("DateTimeZone")?; + Ok(TimezoneFns { + ce, + construct: ce_method_ref(ce, "__construct")?, + get_name: ce_method_ref(ce, "getName")?, + }) + }, + |ctx, fns| ctx.timezone = Some(*fns), + ) +} - let defined = call_handle( - &self.fn_defined.expect("just initialized"), - None, - &mut [constant_name_zv.shallow_clone()], - "check an enum case", - )?; +pub fn timezone_get_name() -> Result<&'static Function, PhpException> { + Ok(timezone_fns()?.get_name) +} - if !defined.bool().unwrap_or(false) { - return Err(ext_exception(format!( - "flow_php cannot restore enum case \"{class_name}::{case_name}\"" - ))); - } +/// `getTimezone` of a datetime class, subclass-safe. +pub fn datetime_get_timezone(ce: &'static ClassEntry) -> Result<&'static Function, PhpException> { + let key = std::ptr::from_ref(ce) as usize; - let case_zv = call_handle( - &self.fn_constant.expect("just initialized"), - None, - &mut [constant_name_zv], - "restore an enum case", - )?; - - if !case_zv.is_object() { - return Err(ext_exception(format!( - "flow_php cannot restore enum case \"{class_name}::{case_name}\"" - ))); - } + cached( + |ctx| ctx.datetime_get_timezone.get(&key).copied(), + || ce_method_ref(ce, "getTimezone"), + |ctx, function| { + ctx.datetime_get_timezone.insert(key, function); + }, + ) +} - let result = case_zv.shallow_clone(); - self.enums.insert(cache_key, case_zv); +/// `setTime`/`format` of a datetime class, subclass-safe. +pub fn datetime_cast_fns(ce: &'static ClassEntry) -> Result { + let key = std::ptr::from_ref(ce) as usize; - Ok(result) - } + cached( + |ctx| ctx.datetime_cast.get(&key).copied(), + || { + Ok(DateTimeCastFns { + set_time: ce_method_ref(ce, "setTime")?, + format: ce_method_ref(ce, "format")?, + }) + }, + |ctx, fns| { + ctx.datetime_cast.insert(key, *fns); + }, + ) +} - /// Cached handles to `ValueDecoder`'s public static markup restorers. - pub fn value_decoder_static( - &mut self, - method: &'static str, - ) -> Result<&'static Function, PhpException> { - if !self.value_decoder_statics.contains_key(method) { - let handle = method_handle_ref("Flow\\Floe\\ValueDecoder", method)?; - self.value_decoder_statics.insert(method, handle); - } +/// `new DateTimeZone($name)`, one instance per name. +pub fn timezone(name: &[u8]) -> Result { + cached( + |ctx| ctx.timezones.get(name).map(Zval::shallow_clone), + || { + let fns = timezone_fns()?; + let mut timezone = ZendObject::new(fns.ce); + call_handle(fns.construct, Some(&mut timezone), &mut [zval_str(name)], "construct DateTimeZone")?; - Ok(self - .value_decoder_statics - .get(method) - .expect("just inserted")) - } + let mut zv = Zval::new(); + zv.set_object(&mut timezone); - pub fn uuid(&mut self) -> Result<(&'static ClassEntry, u32), PhpException> { - if self.uuid_ce.is_none() { - let ce = find_class("Flow\\Types\\Value\\Uuid")?; - self.uuid_ce = Some((ce, property_offset(ce, "value")?)); - } + Ok(zv) + }, + |ctx, zv| { + ctx.timezones.insert(name.to_vec(), zv.shallow_clone()); + }, + ) +} - Ok(self.uuid_ce.expect("just initialized")) - } +/// Whether `new DateTimeZone($name)` succeeds; the exception it throws otherwise is discarded. +pub fn timezone_accepts(name: &[u8]) -> Result { + let fns = timezone_fns()?; + let timezone = ZendObject::new(fns.ce); - pub fn interval(&mut self) -> Result<&mut IntervalFns, PhpException> { - if self.interval.is_none() { - self.interval = Some(IntervalFns { - ce: find_class("DateInterval")?, - construct: method_handle("DateInterval", "__construct")?, - spec: zval_str(b"PT0S"), - names: [ - ZendStr::new("y", false), - ZendStr::new("m", false), - ZendStr::new("d", false), - ZendStr::new("h", false), - ZendStr::new("i", false), - ZendStr::new("s", false), - ZendStr::new("invert", false), - ZendStr::new("f", false), - ], - }); - } + Ok(call_handle_catching(fns.construct, Some(&timezone), &mut [zval_str(name)]).is_ok()) +} - Ok(self.interval.as_mut().expect("just initialized")) +/// Whether `$name` is in `DateTimeZone::listIdentifiers()`, fetched once per request. +pub fn is_timezone_identifier(name: &[u8]) -> Result { + if let Some(known) = with_ctx(|ctx| Ok(ctx.timezone_identifiers.as_ref().map(|ids| ids.contains(name))))? { + return Ok(known); } - /// Datetime class entry + pre-resolved setTimezone handle per class. - pub fn datetime_fns(&mut self, mutable: bool) -> Result<&DateTimeFns, PhpException> { - let slot = if mutable { - &mut self.datetime_mutable - } else { - &mut self.datetime_immutable - }; + let list = call_handle( + ce_method_ref(timezone_fns()?.ce, "listIdentifiers")?, + None, + &mut [], + "list timezone identifiers", + )?; + let identifiers: HashSet> = list + .array() + .ok_or_else(|| ext_exception("flow_php expected DateTimeZone::listIdentifiers() to return an array"))? + .values() + .filter_map(|zv| zv.zend_str().map(|name| name.as_bytes().to_vec())) + .collect(); + let known = identifiers.contains(name); + + with_ctx(|ctx| { + ctx.timezone_identifiers = Some(identifiers); + Ok(()) + })?; + + Ok(known) +} + +/// An enum case, cached per `Class::Case`, resolved with `enum_exists` + `defined` + `constant`. +pub fn enum_case(class: &[u8], case: &[u8]) -> Result { + let mut constant_name = Vec::with_capacity(class.len() + case.len() + 2); + constant_name.extend_from_slice(class); + constant_name.extend_from_slice(b"::"); + constant_name.extend_from_slice(case); + + cached( + |ctx| ctx.enums.get(&constant_name).map(Zval::shallow_clone), + || { + let class_name = String::from_utf8_lossy(class); + let case_name = String::from_utf8_lossy(case); + let is_enum = std::str::from_utf8(class) + .ok() + .and_then(ClassEntry::try_find) + .is_some_and(|ce| ce.flags().contains(ClassFlags::Enum)); + + if !is_enum { + return Err(ext_exception(format!( + "flow_php cannot restore enum of class \"{class_name}\", enum not found" + ))); + } - if slot.is_none() { - let class = if mutable { - "DateTime" + let constant_name_zv = zval_str(&constant_name); + let defined = call_handle( + function("defined")?, + None, + &mut [constant_name_zv.shallow_clone()], + "check an enum case", + )?; + let case_zv = if defined.bool().unwrap_or(false) { + call_handle(function("constant")?, None, &mut [constant_name_zv], "restore an enum case")? } else { - "DateTimeImmutable" + null_zval() }; - *slot = Some(DateTimeFns { - ce: find_class(class)?, - set_timezone: method_handle(class, "setTimezone")?, - }); - } - Ok(slot.as_ref().expect("just initialized")) - } - - /// `DateTimeZone` instances cached per timezone name, mirroring - /// `ValueDecoder::$timezones`. - pub fn timezone(&mut self, name: &[u8]) -> Result<&Zval, PhpException> { - if !self.timezones.contains_key(name) { - if self.timezone_ce.is_none() { - self.timezone_ce = Some(find_class("DateTimeZone")?); + if !case_zv.is_object() { + return Err(ext_exception(format!( + "flow_php cannot restore enum case \"{class_name}::{case_name}\"" + ))); } - let name_string = std::str::from_utf8(name) - .map_err(|_| ext_exception("flow_php found a non UTF-8 timezone name"))? - .to_string(); - let mut timezone = construct_object( - self.timezone_ce.expect("just initialized"), - vec![&name_string as &dyn IntoZvalDyn], - "DateTimeZone", - )?; - - let mut zv = Zval::new(); - zv.set_object(&mut timezone); - self.timezones.insert(name.to_vec(), zv); - } - - Ok(self.timezones.get(name).expect("just inserted")) - } - - pub fn json_encode(&mut self) -> Result<&Function, PhpException> { - if self.fn_json_encode.is_none() { - self.fn_json_encode = Some(function_handle("json_encode")?); - } - - Ok(self.fn_json_encode.as_ref().expect("just initialized")) - } + Ok(case_zv) + }, + |ctx, zv| { + ctx.enums.insert(constant_name.clone(), zv.shallow_clone()); + }, + ) +} - pub fn json_decode(&mut self) -> Result<&Function, PhpException> { - if self.fn_json_decode.is_none() { - self.fn_json_decode = Some(function_handle("json_decode")?); - } +/// `HASH_FLAG_PACKED` from zend_types.h. +pub const HASH_FLAG_PACKED: u8 = 1 << 2; - Ok(self.fn_json_decode.as_ref().expect("just initialized")) - } +/// Raw order-preserving iteration over packed and bucket layouts, binary-safe +/// for arbitrary keys (ext-php-rs's `iter()` panics on non-UTF-8 string keys). +pub fn ht_for_each( + ht: &ZendHashTable, + mut f: impl FnMut(Option<&ZendStr>, zend_ulong, &Zval) -> Result<(), PhpException>, +) -> Result<(), PhpException> { + let packed = unsafe { ht.u.v.flags } & HASH_FLAG_PACKED != 0; - pub fn json_validate(&mut self) -> Result<&Function, PhpException> { - if self.fn_json_validate.is_none() { - self.fn_json_validate = Some(function_handle("json_validate")?); - } + for index in 0..ht.nNumUsed { + if packed { + let value = unsafe { &*ht.__bindgen_anon_1.arPacked.add(index as usize) }; - Ok(self.fn_json_validate.as_ref().expect("just initialized")) - } + if value.get_type() == ext_php_rs::flags::DataType::Undef { + continue; + } - pub fn date_parse(&mut self) -> Result<&Function, PhpException> { - if self.fn_date_parse.is_none() { - self.fn_date_parse = Some(function_handle("date_parse")?); - } + f(None, zend_ulong::from(index), value)?; + } else { + let bucket = unsafe { &*ht.__bindgen_anon_1.arData.add(index as usize) }; - Ok(self.fn_date_parse.as_ref().expect("just initialized")) - } + if bucket.val.get_type() == ext_php_rs::flags::DataType::Undef { + continue; + } - /// `DateTimeZone::listIdentifiers()`, fetched once per `Ctx`. - pub fn timezone_identifiers(&mut self) -> Result<&HashSet>, PhpException> { - if self.timezone_identifiers.is_none() { - let list = call_handle( - method_handle_ref("DateTimeZone", "listIdentifiers")?, - None, - &mut [], - "list timezone identifiers", - )?; - let identifiers = list - .array() - .ok_or_else(|| ext_exception("flow_php expected DateTimeZone::listIdentifiers() to return an array"))? - .values() - .filter_map(|zv| zv.zend_str().map(|name| name.as_bytes().to_vec())) - .collect(); - - self.timezone_identifiers = Some(identifiers); + let key = unsafe { bucket.key.as_ref() }; + f(key, bucket.h, &bucket.val)?; } - - Ok(self.timezone_identifiers.as_ref().expect("just initialized")) } - /// Whether `new DateTimeZone($name)` succeeds; the exception it throws otherwise is discarded. - pub fn timezone_accepts(&mut self, name: &[u8]) -> Result { - if self.timezone_ce.is_none() { - self.timezone_ce = Some(find_class("DateTimeZone")?); - } - - let ce = self.timezone_ce.expect("just initialized"); - - if self.timezone_construct.is_none() { - self.timezone_construct = Some(ce_method_ref(ce, "__construct")?); - } - - let timezone = ZendObject::new(ce); + Ok(()) +} - Ok(call_handle_catching( - self.timezone_construct.expect("just initialized"), - Some(&timezone), - &mut [zval_str(name)], - ) - .is_ok()) +pub fn read_slot(obj: &ZendObject, offset: u32) -> &Zval { + unsafe { + &*std::ptr::from_ref(obj) + .cast::() + .add(offset as usize) + .cast::() } +} - /// Static `Flow\ETL\Schema\Metadata::fromArray` handle - builds a Metadata - /// value object from a decoded per-value metadata map (the rare path). - pub fn metadata_from_array(&mut self) -> Result<&'static Function, PhpException> { - if self.metadata_from_array.is_none() { - self.metadata_from_array = - Some(method_handle_ref("Flow\\ETL\\Schema\\Metadata", "fromArray")?); - } - - Ok(self.metadata_from_array.expect("just initialized")) - } +pub fn expect_object<'a>( + zv: &'a Zval, + context: &str, +) -> Result<&'a ZendObject, PhpException> { + zv.object() + .ok_or_else(|| ext_exception(format!("flow_php expected {context} to be an object"))) } diff --git a/src/extension/flow-php-ext/src/date_check.rs b/src/extension/flow-php-ext/src/date_check.rs index eae53983e6..456ebb0e55 100644 --- a/src/extension/flow-php-ext/src/date_check.rs +++ b/src/extension/flow-php-ext/src/date_check.rs @@ -114,3 +114,82 @@ pub fn checkdate(month: i64, day: i64, year: i64) -> bool { day <= days } + +/// Epoch microseconds of `YYYY-MM-DDTHH:MM:SS[.f]` (1–6 fraction digits) + `Z` or `±HH:MM`, every field in range - the +/// instant `DateTimeType::cast` yields, computed without timelib. `None` for every other string, which timelib parses. +pub fn iso_instant_micros(bytes: &[u8]) -> Option { + let byte_at = |at: usize| bytes.get(at).copied(); + let number = |at: usize, count: usize| -> Option { + bytes + .get(at..at + count)? + .iter() + .try_fold(0i64, |value, digit| digit.is_ascii_digit().then(|| value * 10 + i64::from(digit - b'0'))) + }; + + if [(4, b'-'), (7, b'-'), (10, b'T'), (13, b':'), (16, b':')] + .iter() + .any(|(at, separator)| byte_at(*at) != Some(*separator)) + { + return None; + } + + let (year, month, day) = (number(0, 4)?, number(5, 2)?, number(8, 2)?); + let (hour, minute, second) = (number(11, 2)?, number(14, 2)?, number(17, 2)?); + + if year > 9999 || !checkdate(month, day, year) || hour > 23 || minute > 59 || second > 59 { + return None; + } + + let mut at = 19; + let mut fraction = 0; + + if byte_at(at) == Some(b'.') { + let digits = bytes[at + 1..].iter().take_while(|byte| byte.is_ascii_digit()).count(); + + if !(1..=6).contains(&digits) { + return None; + } + + fraction = number(at + 1, digits)? * 10i64.pow(6 - digits as u32); + at += 1 + digits; + } + + let offset = match byte_at(at) { + Some(b'Z') => { + at += 1; + + 0 + } + Some(sign @ (b'+' | b'-')) if byte_at(at + 3) == Some(b':') => { + let (hours, minutes) = (number(at + 1, 2)?, number(at + 4, 2)?); + + if hours > 23 || minutes > 59 { + return None; + } + + at += 6; + + (hours * 3600 + minutes * 60) * if sign == b'-' { -1 } else { 1 } + } + _ => return None, + }; + + if at != bytes.len() { + return None; + } + + let seconds = days_from_civil(year, month, day)? * 86_400 + hour * 3600 + minute * 60 + second - offset; + + Some(seconds * 1_000_000 + fraction) +} + +/// `DaysFromCivil::of()`: days since 1970-01-01 of a proleptic Gregorian date, `None` on i64 overflow. +pub(crate) fn days_from_civil(year: i64, month: i64, day: i64) -> Option { + let year = year - i64::from(month <= 2); + let era = (if year >= 0 { year } else { year.checked_sub(399)? }) / 400; + let year_of_era = year - era * 400; + let day_of_year = (153 * (if month > 2 { month - 3 } else { month + 9 }) + 2) / 5 + day - 1; + let day_of_era = year_of_era * 365 + year_of_era / 4 - year_of_era / 100 + day_of_year; + + era.checked_mul(146_097)?.checked_add(day_of_era - 719_468) +} diff --git a/src/extension/flow-php-ext/src/encode.rs b/src/extension/flow-php-ext/src/encode.rs deleted file mode 100644 index 1c4a5bea04..0000000000 --- a/src/extension/flow-php-ext/src/encode.rs +++ /dev/null @@ -1,795 +0,0 @@ -//! Floe ROW frame-body encoder mirroring `Flow\Floe\PhpFloeEncoder::encode` -//! byte-for-byte; values and per-value metadata are read from a `TypedRowValues`. - -use ext_php_rs::exception::PhpException; -use ext_php_rs::ffi::zend_ulong; -use ext_php_rs::types::{ZendHashTable, ZendObject, ZendStr, Zval}; -use ext_php_rs::zend::{ClassEntry, Function}; - -use crate::ctx::{ - call_handle, call_handle_on, ce_method_ref, find_class, null_zval, read_property, - schema_mismatch, zval_str, Ctx, -}; -use crate::exception::ext_exception; -use crate::format::{ - write_u32, FRAME_ROW, VALUE_ABSENT, VALUE_NULL, VALUE_NULL_WITH_META, VALUE_PRESENT, VALUE_PRESENT_WITH_META, -}; -use crate::plan::{parse_schema_json, TypeJson}; - -enum EncodeMapKey { - Integer, - String, -} - -/// Declared structure element key after PHP's array-key coercion, mirroring -/// `ValueEncoder::structureEncoder`. -enum DeclaredKey { - Index(i64), - Str(Vec), -} - -/// Recursive value encoder mirroring `ValueEncoder::encoderFor`. -enum Encoder { - Integer, - Float, - Boolean, - String, - Null, - DateTime, - Interval, - Uuid, - Json, - TimeZone, - Enum, - Xml, - XmlElement, - Html, - HtmlElement, - List(Box), - Map(EncodeMapKey, Box), - Structure(Vec<(DeclaredKey, Vec, Encoder)>), - Optional(Box), -} - -fn build_encoder(type_json: &TypeJson) -> Result { - let missing = |part: &str| { - ext_exception(format!( - "flow_php schema JSON for type \"{}\" is missing its {part}", - type_json.type_ - )) - }; - - Ok(match type_json.type_.as_str() { - "integer" | "positive_integer" => Encoder::Integer, - "float" => Encoder::Float, - "boolean" => Encoder::Boolean, - "string" | "non_empty_string" | "numeric-string" | "class_string" => Encoder::String, - "null" => Encoder::Null, - "datetime" | "date" => Encoder::DateTime, - "time" => Encoder::Interval, - "uuid" => Encoder::Uuid, - "json" => Encoder::Json, - "timezone" => Encoder::TimeZone, - "enum" => Encoder::Enum, - "xml" => Encoder::Xml, - "xml_element" => Encoder::XmlElement, - "html" => Encoder::Html, - "html_element" => Encoder::HtmlElement, - "list" => Encoder::List(Box::new(build_encoder( - type_json.element().ok_or_else(|| missing("element"))?, - )?)), - "map" => { - let key = match type_json - .key() - .ok_or_else(|| missing("key"))? - .type_ - .as_str() - { - "integer" => EncodeMapKey::Integer, - "string" => EncodeMapKey::String, - other => { - return Err(ext_exception(format!( - "flow_php does not support map keys of type \"{other}\"" - ))); - } - }; - - Encoder::Map( - key, - Box::new(build_encoder( - type_json.value().ok_or_else(|| missing("value"))?, - )?), - ) - } - "structure_v2" => { - if type_json.fields().is_empty() { - return Err(ext_exception( - "flow_php read a structure type with no fields; the loaded flow_php extension and the \ - flow-php/etl in use disagree on the structure schema format - reinstall one to match the \ - other, or set the Floe engine to FloeEngine::php", - )); - } - - let mut elements = Vec::new(); - - for field in type_json.fields() { - let bytes = field.name.clone().into_bytes(); - let declared = match crate::ctx::array_key_index(&bytes) { - Some(index) => DeclaredKey::Index(index), - None => DeclaredKey::Str(bytes.clone()), - }; - elements.push((declared, bytes, build_encoder(&field.type_)?)); - } - - Encoder::Structure(elements) - } - "optional" => Encoder::Optional(Box::new(build_encoder( - type_json.base().ok_or_else(|| missing("base"))?, - )?)), - other => { - return Err(ext_exception(format!( - "flow_php does not support values of type \"{other}\" in this build" - ))); - } - }) -} - -pub(crate) struct EncodeColumn { - pub(crate) name: Vec, - encoder: Encoder, - /// `Definition::isNullable()`, read once at plan build - never per row - nullable: bool, - /// retained (refcount++) so a refusal can be raised through the PHP factory, - /// which is the only place a schema-mismatch message is ever authored - base_def: Zval, - /// Canonical PHP `json_encode` of this column's section-schema metadata - the - /// divergence reference. An entry whose metadata JSON differs rides its own - /// metadata beside the value. - plan_metadata_json: Vec, - plan_metadata_empty: bool, -} - -pub struct EncodePlan { - pub(crate) columns: Vec, - schema_mismatch_ce: &'static ClassEntry, - value_does_not_match: &'static Function, -} - -/// `HASH_FLAG_PACKED` from zend_types.h. -const HASH_FLAG_PACKED: u8 = 1 << 2; - -/// Raw order-preserving iteration over packed and bucket layouts, binary-safe -/// for arbitrary keys (ext-php-rs's `iter()` panics on non-UTF-8 string keys). -pub fn ht_for_each( - ht: &ZendHashTable, - mut f: impl FnMut(Option<&ZendStr>, zend_ulong, &Zval) -> Result<(), PhpException>, -) -> Result<(), PhpException> { - let packed = unsafe { ht.u.v.flags } & HASH_FLAG_PACKED != 0; - - for index in 0..ht.nNumUsed { - if packed { - let value = unsafe { &*ht.__bindgen_anon_1.arPacked.add(index as usize) }; - - if value.get_type() == ext_php_rs::flags::DataType::Undef { - continue; - } - - f(None, zend_ulong::from(index), value)?; - } else { - let bucket = unsafe { &*ht.__bindgen_anon_1.arData.add(index as usize) }; - - if bucket.val.get_type() == ext_php_rs::flags::DataType::Undef { - continue; - } - - let key = unsafe { bucket.key.as_ref() }; - f(key, bucket.h, &bucket.val)?; - } - } - - Ok(()) -} - -pub(crate) fn read_slot(obj: &ZendObject, offset: u32) -> &Zval { - unsafe { - &*std::ptr::from_ref(obj) - .cast::() - .add(offset as usize) - .cast::() - } -} - -pub(crate) fn expect_object<'a>( - zv: &'a Zval, - context: &str, -) -> Result<&'a ZendObject, PhpException> { - zv.object() - .ok_or_else(|| ext_exception(format!("flow_php expected {context} to be an object"))) -} - -fn write_len_prefixed(out: &mut Vec, bytes: &[u8]) { - write_u32(out, bytes.len() as u32); - out.extend_from_slice(bytes); -} - -/// Builds the encode plan from a SCHEMA frame body (the JSON the PHP -/// `SchemaEncoder` emits). Each column's section-schema metadata is captured as -/// its canonical PHP `json_encode` so a diverging entry can be detected without -/// re-parsing the schema per row. -pub fn build_encode_plan( - schema_json: &[u8], - schema: &Zval, - ctx: &mut Ctx, -) -> Result { - let definitions = parse_schema_json(schema_json)?; - let base_defs = schema_definitions(schema)?; - - let mut assoc_zv = Zval::new(); - assoc_zv.set_bool(true); - let decoded = { - let json_decode = ctx.json_decode()?; - call_handle( - json_decode, - None, - &mut [zval_str(schema_json), assoc_zv], - "decode a schema frame for metadata", - )? - }; - let decoded_ht = decoded - .array() - .ok_or_else(|| ext_exception("flow_php expected a schema frame to decode to a list"))?; - - let mut columns = Vec::with_capacity(definitions.len()); - - for (index, definition) in definitions.iter().enumerate() { - let plan_metadata_json = column_metadata_json(decoded_ht, index, ctx)?; - - let base_def = base_defs - .get(index) - .ok_or_else(|| ext_exception("flow_php expected a Definition for every schema column"))? - .shallow_clone(); - - columns.push(EncodeColumn { - name: definition.name.clone().into_bytes(), - encoder: build_encoder(&definition.type_)?, - nullable: definition.nullable, - base_def, - plan_metadata_empty: plan_metadata_json == b"[]", - plan_metadata_json, - }); - } - - Ok(EncodePlan { - columns, - schema_mismatch_ce: find_class("Flow\\ETL\\Exception\\SchemaMismatchException")?, - value_does_not_match: ce_method_ref( - find_class("Flow\\ETL\\Exception\\ColumnMismatchException")?, - "valueDoesNotMatch", - )?, - }) -} - -/// Canonical PHP `json_encode` of the `metadata` map of the `index`th decoded -/// schema definition (`[]` when absent). -fn column_metadata_json( - decoded_ht: &ZendHashTable, - index: usize, - ctx: &mut Ctx, -) -> Result, PhpException> { - let definition_ht = decoded_ht - .get_index(index as i64) - .and_then(Zval::array) - .ok_or_else(|| ext_exception("flow_php expected a schema definition to be a map"))?; - - let metadata_zv = match definition_ht.get("metadata") { - Some(zv) => zv.shallow_clone(), - None => return Ok(b"[]".to_vec()), - }; - - let json_encode = ctx.json_encode()?; - let encoded = call_handle( - json_encode, - None, - &mut [metadata_zv], - "encode section-schema metadata", - )?; - - encoded - .zend_str() - .map(|s| s.as_bytes().to_vec()) - .ok_or_else(|| ext_exception("flow_php expected json_encode to return a string")) -} - -/// The `Schema`'s own `Definition` objects in declaration order - the same walk -/// `build_hydrate_plan` does, and the same order `parse_schema_json` yields. -/// Runs once per schema rebind, never per row. -fn schema_definitions(schema: &Zval) -> Result, PhpException> { - let schema_obj = expect_object(schema, "a Schema")?; - let schema_ce = unsafe { schema_obj.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve the Schema class"))?; - let definitions = call_handle_on( - ce_method_ref(schema_ce, "definitions")?, - schema_obj, - &mut [], - "read schema definitions", - )?; - let definitions_ht = definitions - .array() - .ok_or_else(|| ext_exception("flow_php expected Schema::definitions to return an array"))?; - - let mut base_defs = Vec::with_capacity(definitions_ht.len()); - - ht_for_each(definitions_ht, |_, _, def_zv| { - base_defs.push(def_zv.shallow_clone()); - - Ok(()) - })?; - - Ok(base_defs) -} - -/// Appends one `Flow\ETL\Row\TypedRowValues` (its `values` + `metadata` maps) to `out` -/// as a bare ROW frame body (no length prefix, no frame type). Byte-identical -/// to `Flow\Floe\PhpFloeEncoder::encode` for the same row. -pub fn encode_typed_row( - plan: &EncodePlan, - row_index: u64, - values_ht: &ZendHashTable, - metadata_ht: &ZendHashTable, - out: &mut Vec, - ctx: &mut Ctx, -) -> Result<(), PhpException> { - for column in &plan.columns { - let Some(value) = ht_find(values_ht, &column.name) else { - return Err(ext_exception(format!( - "flow_php found a row that does not carry the declared column \"{}\"", - String::from_utf8_lossy(&column.name) - ))); - }; - - let (diverges, entry_metadata_json) = typed_metadata(column, metadata_ht, ctx)?; - - if value.is_null() { - if !column.nullable { - return Err(schema_mismatch( - plan.schema_mismatch_ce, - plan.value_does_not_match, - row_index, - &mut [column.base_def.shallow_clone(), null_zval()], - )?); - } - - if diverges { - out.push(VALUE_NULL_WITH_META); - write_len_prefixed(out, &entry_metadata_json); - } else { - out.push(VALUE_NULL); - } - - continue; - } - - if diverges { - out.push(VALUE_PRESENT_WITH_META); - write_len_prefixed(out, &entry_metadata_json); - } else { - out.push(VALUE_PRESENT); - } - - encode_value(&column.encoder, value, out, ctx)?; - } - - Ok(()) -} - -/// `Format::frame(Format::FRAME_ROW, $body)` over `encode_typed_row` for every `Row` of a batch: the rows' own -/// values tables and the batch's one `TypedRowValues::metadata` map, complete ROW frames in one buffer. -pub fn encode_frames( - plan: &EncodePlan, - rows_ht: &ZendHashTable, - row_values_slot: u32, - metadata_ht: &ZendHashTable, - ctx: &mut Ctx, -) -> Result, PhpException> { - let mut out = Vec::with_capacity(rows_ht.len() * 256); - - ht_for_each(rows_ht, |_, row_index, row_zv| { - let values_ht = read_slot(expect_object(row_zv, "a Row")?, row_values_slot) - .array() - .ok_or_else(|| ext_exception("flow_php expected Row::values to be an array"))?; - - out.push(FRAME_ROW); - let length_at = out.len(); - out.extend_from_slice(&[0; 4]); - - encode_typed_row(plan, row_index, values_ht, metadata_ht, &mut out, ctx)?; - - let length = u32::try_from(out.len() - length_at - 4) - .map_err(|_| ext_exception("flow_php encoded a row frame longer than 4 GiB"))?; - out[length_at..length_at + 4].copy_from_slice(&length.to_le_bytes()); - - Ok(()) - })?; - - Ok(out) -} - -/// Whether a column's per-value metadata diverges from the section-schema -/// reference and, if so, its canonical JSON (the beside-value blob). `metadata_ht` -/// is the `TypedRowValues::metadata` map, which carries only non-empty entries -/// (mirroring `PhpRowHydrator::dehydrate`); an absent key is empty metadata. Fast -/// path: an empty entry against an empty-metadata column never diverges - no PHP call. -fn typed_metadata( - column: &EncodeColumn, - metadata_ht: &ZendHashTable, - ctx: &mut Ctx, -) -> Result<(bool, Vec), PhpException> { - let metadata_zv = ht_find(metadata_ht, &column.name); - - let entry_empty = match metadata_zv { - None => true, - Some(zv) => { - let metadata = expect_object(zv, "per-value metadata")?; - let map_slot = ctx.metadata_map_slot()?; - read_slot(metadata, map_slot) - .array() - .is_none_or(|map| map.is_empty()) - } - }; - - if entry_empty && column.plan_metadata_empty { - return Ok((false, Vec::new())); - } - - let entry_metadata_json = if entry_empty { - b"[]".to_vec() - } else { - let metadata = expect_object( - metadata_zv.expect("Some when the entry is not empty"), - "per-value metadata", - )?; - let map_slot = ctx.metadata_map_slot()?; - let map_owned = read_slot(metadata, map_slot).shallow_clone(); - let json_encode = ctx.json_encode()?; - let encoded = call_handle( - json_encode, - None, - &mut [map_owned], - "encode per-value metadata", - )?; - - encoded - .zend_str() - .map(|s| s.as_bytes().to_vec()) - .ok_or_else(|| ext_exception("flow_php expected json_encode to return a string"))? - }; - - let diverges = entry_metadata_json != column.plan_metadata_json; - - Ok((diverges, entry_metadata_json)) -} - -fn encode_value( - encoder: &Encoder, - value: &Zval, - out: &mut Vec, - ctx: &mut Ctx, -) -> Result<(), PhpException> { - match encoder { - Encoder::Integer => out.extend_from_slice( - &value - .long() - .ok_or_else(|| ext_exception("flow_php expected an integer value"))? - .to_le_bytes(), - ), - Encoder::Float => out.extend_from_slice( - &php_float(value) - .ok_or_else(|| ext_exception("flow_php expected a float value"))? - .to_le_bytes(), - ), - Encoder::Boolean => { - out.push(u8::from(value.bool().ok_or_else(|| { - ext_exception("flow_php expected a boolean value") - })?)) - } - Encoder::String => write_len_prefixed( - out, - value - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected a string value"))? - .as_bytes(), - ), - Encoder::Null => {} - Encoder::DateTime => encode_datetime(expect_object(value, "a datetime value")?, out, ctx)?, - Encoder::Interval => encode_interval(expect_object(value, "a time value")?, out, ctx)?, - Encoder::Uuid => { - let uuid = expect_object(value, "a uuid value")?; - let (uuid_ce, value_slot) = ctx.uuid()?; - - if !std::ptr::eq(uuid.ce.cast_const(), std::ptr::from_ref(uuid_ce)) { - return Err(ext_exception("flow_php expected a uuid value to be an object")); - } - - let bytes = read_slot(uuid, value_slot) - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected Uuid to hold a string"))?; - write_len_prefixed(out, bytes.as_bytes()); - } - Encoder::Json => encode_json(expect_object(value, "a json value")?, out, ctx)?, - Encoder::TimeZone => { - let timezone = expect_object(value, "a timezone value")?; - let name = call_handle_on( - ctx.timezone_get_name()?, - timezone, - &mut [], - "read a timezone name", - )?; - write_len_prefixed( - out, - name.zend_str() - .ok_or_else(|| ext_exception("flow_php expected a timezone name string"))? - .as_bytes(), - ); - } - Encoder::Enum => { - let case = expect_object(value, "an enum value")?; - let class = unsafe { case.ce.as_ref() } - .and_then(ClassEntry::name) - .ok_or_else(|| ext_exception("flow_php failed to resolve an enum class"))?; - write_len_prefixed(out, class.as_bytes()); - - let name = read_property(case, "name")?; - write_len_prefixed( - out, - name.zend_str() - .ok_or_else(|| ext_exception("flow_php expected an enum case name"))? - .as_bytes(), - ); - } - Encoder::Xml => encode_via_static(value, out, ctx, "xmlDocumentToString")?, - Encoder::XmlElement => encode_via_static(value, out, ctx, "xmlElementToString")?, - Encoder::HtmlElement => encode_via_static(value, out, ctx, "htmlElementToString")?, - Encoder::Html => { - let document = expect_object(value, "an html value")?; - let html = call_handle_on( - ctx.save_html(document.ce.cast_const())?, - document, - &mut [], - "convert an HTML document", - )?; - write_len_prefixed( - out, - html.zend_str() - .ok_or_else(|| ext_exception("flow_php expected saveHtml to return a string"))? - .as_bytes(), - ); - } - Encoder::List(element) => { - let values = value - .array() - .ok_or_else(|| ext_exception("flow_php expected a list value"))?; - write_u32(out, values.len() as u32); - ht_for_each(values, |_, _, item| encode_value(element, item, out, ctx))?; - } - Encoder::Map(key, element) => { - let values = value - .array() - .ok_or_else(|| ext_exception("flow_php expected a map value"))?; - write_u32(out, values.len() as u32); - ht_for_each(values, |map_key, index, item| { - match key { - EncodeMapKey::Integer => { - let int_key = match map_key { - None => index as i64, - Some(_) => { - return Err(ext_exception("flow_php expected an integer map key")); - } - }; - out.extend_from_slice(&int_key.to_le_bytes()); - } - EncodeMapKey::String => match map_key { - // numeric-string keys coerced to int by the PHP array - // are cast back, like ValueEncoder - None => write_len_prefixed(out, (index as i64).to_string().as_bytes()), - Some(key) => write_len_prefixed(out, key.as_bytes()), - }, - } - - encode_value(element, item, out, ctx) - })?; - } - Encoder::Structure(elements) => { - let values = value - .array() - .ok_or_else(|| ext_exception("flow_php expected a structure value"))?; - - for (declared, _, element) in elements { - let item = match declared { - DeclaredKey::Index(index) => values.get_index(*index), - DeclaredKey::Str(key) => ht_find(values, key), - }; - - match item { - None => out.push(VALUE_ABSENT), - Some(item) if item.is_null() => out.push(VALUE_NULL), - Some(item) => { - out.push(VALUE_PRESENT); - encode_value(element, item, out, ctx)?; - } - } - } - } - Encoder::Optional(base) => { - if value.is_null() { - out.push(VALUE_NULL); - } else { - out.push(VALUE_PRESENT); - encode_value(base, value, out, ctx)?; - } - } - } - - Ok(()) -} - -/// Accepts ints where FloatType is declared, permissive like `pack('e')`. -fn php_float(value: &Zval) -> Option { - value.double().or_else(|| value.long().map(|l| l as f64)) -} - -fn ht_find<'a>(ht: &'a ZendHashTable, key: &[u8]) -> Option<&'a Zval> { - match crate::ctx::array_key_index(key) { - Some(index) => ht.get_index(index), - None => unsafe { - ext_php_rs::ffi::zend_hash_str_find( - std::ptr::from_ref(ht).cast_mut(), - key.as_ptr().cast(), - key.len(), - ) - .as_ref() - }, - } -} - -/// Mirrors `ValueEncoder::encodeDateTime`. -fn encode_datetime( - value: &ZendObject, - out: &mut Vec, - ctx: &mut Ctx, -) -> Result<(), PhpException> { - let ce = value.ce.cast_const(); - let immutable_ce = std::ptr::from_ref(ctx.datetime_fns(false)?.ce); - let mutable_ce = std::ptr::from_ref(ctx.datetime_fns(true)?.ce); - - // the class is not stored - a datetime column always hydrates to DateTimeImmutable - but a - // custom subclass is still refused, because its extra state would be dropped silently - if !std::ptr::eq(ce, immutable_ce) && !std::ptr::eq(ce, mutable_ce) { - let class = unsafe { ce.as_ref() } - .and_then(ClassEntry::name) - .ok_or_else(|| ext_exception("flow_php failed to resolve a datetime class"))?; - - return Err(ext_exception(format!( - "Floe supports only DateTime and DateTimeImmutable, got {class} - convert custom datetime instances before writing" - ))); - } - - let enc = ctx.datetime_encode_fns(ce)?; - let get_timestamp = enc.get_timestamp; - let format = enc.format; - let get_timezone = enc.get_timezone; - - let timestamp = call_handle_on(get_timestamp, value, &mut [], "read a timestamp")? - .long() - .ok_or_else(|| ext_exception("flow_php expected getTimestamp to return an int"))?; - - let format_u = ctx.format_u()?.shallow_clone(); - let microseconds_zv = - call_handle_on(format, value, &mut [format_u], "read datetime microseconds")?; - let microseconds: u32 = microseconds_zv - .zend_str() - .and_then(|s| std::str::from_utf8(s.as_bytes()).ok()) - .and_then(|s| s.parse().ok()) - .ok_or_else(|| ext_exception("flow_php expected format('u') to return digits"))?; - - let timezone_zv = call_handle_on(get_timezone, value, &mut [], "read a timezone")?; - let timezone = expect_object(&timezone_zv, "a timezone")?; - let name = call_handle_on( - ctx.timezone_get_name()?, - timezone, - &mut [], - "read a timezone name", - )?; - - out.extend_from_slice(×tamp.to_le_bytes()); - write_u32(out, microseconds); - write_len_prefixed( - out, - name.zend_str() - .ok_or_else(|| ext_exception("flow_php expected a timezone name string"))? - .as_bytes(), - ); - - Ok(()) -} - -/// Mirrors `ValueEncoder::encodeInterval`. -fn encode_interval( - value: &ZendObject, - out: &mut Vec, - _ctx: &mut Ctx, -) -> Result<(), PhpException> { - let read = |name: &str| -> Result { read_property(value, name) }; - - let invert = read("invert")? - .long() - .ok_or_else(|| ext_exception("flow_php expected DateInterval::invert to be an int"))?; - out.push(invert as u8); - - for field in ["y", "m", "d", "h", "i", "s"] { - let field_value = read(field)? - .long() - .ok_or_else(|| ext_exception("flow_php expected DateInterval fields to be ints"))?; - write_u32(out, field_value as u32); - } - - let fraction = read("f")?; - let fraction = php_float(&fraction) - .ok_or_else(|| ext_exception("flow_php expected DateInterval::f to be a float"))?; - out.extend_from_slice(&fraction.to_le_bytes()); - - Ok(()) -} - -fn encode_json(value: &ZendObject, out: &mut Vec, ctx: &mut Ctx) -> Result<(), PhpException> { - let (json_ce, value_slot, is_object_slot) = ctx.json()?; - - if !std::ptr::eq(value.ce.cast_const(), std::ptr::from_ref(json_ce)) { - return Err(ext_exception("flow_php expected a json value to be an object")); - } - - write_len_prefixed( - out, - read_slot(value, value_slot) - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected Json to hold a string"))? - .as_bytes(), - ); - out.push(u8::from( - read_slot(value, is_object_slot) - .bool() - .ok_or_else(|| ext_exception("flow_php expected Json::isObject to be a bool"))?, - )); - - Ok(()) -} - -/// Markup serialization delegated to the pure-PHP `ValueEncoder` public -/// statics - the exact code its closures run. -fn encode_via_static( - value: &Zval, - out: &mut Vec, - ctx: &mut Ctx, - method: &'static str, -) -> Result<(), PhpException> { - let handle = ctx.value_encoder_static(method)?; - let string = call_handle( - handle, - None, - &mut [value.shallow_clone()], - "serialize a markup value", - )?; - - write_len_prefixed( - out, - string - .zend_str() - .ok_or_else(|| { - ext_exception(format!( - "flow_php expected ValueEncoder::{method} to return a string" - )) - })? - .as_bytes(), - ); - - Ok(()) -} diff --git a/src/extension/flow-php-ext/src/exception.rs b/src/extension/flow-php-ext/src/exception.rs index 29bbb12c3c..9c68c5ddda 100644 --- a/src/extension/flow-php-ext/src/exception.rs +++ b/src/extension/flow-php-ext/src/exception.rs @@ -3,6 +3,8 @@ use ext_php_rs::error::Result; use ext_php_rs::exception::PhpException; use ext_php_rs::flags::ClassFlags; use ext_php_rs::zend::{ce, ClassEntry}; +use flow_batch_frame::error::Part; +use flow_batch_frame::Error; const EXCEPTION_CLASS: &str = "Flow\\Floe\\Exception\\ExtensionException"; @@ -25,3 +27,24 @@ fn exception_ce() -> &'static ClassEntry { pub fn ext_exception(message: impl Into) -> PhpException { PhpException::new(message.into(), 0, exception_ce()) } + +/// A flow-batch-frame refusal of schema or type JSON, which only `kind` returns. +pub fn json_exception(error: Error) -> PhpException { + ext_exception(match error { + Error::SchemaJsonUtf8 => "flow_php failed to decode schema JSON: invalid UTF-8".to_string(), + Error::SchemaJson(e) => format!("flow_php failed to decode schema JSON: {e}"), + Error::TypeJsonUtf8 => "flow_php failed to decode type JSON: invalid UTF-8".to_string(), + Error::TypeJson(e) => format!("flow_php failed to decode type JSON: {e}"), + Error::MissingPart { type_name, part } => format!( + "flow_php schema JSON for type \"{type_name}\" is missing its {}", + match part { + Part::Element => "element", + Part::Key => "key", + Part::Value => "value", + Part::Base => "base", + } + ), + Error::UnknownType { type_name } => format!("flow_php cannot build a column for type \"{type_name}\""), + error => unreachable!("kind returns JSON refusals only, got {error}"), + }) +} diff --git a/src/extension/flow-php-ext/src/format.rs b/src/extension/flow-php-ext/src/format.rs deleted file mode 100644 index 5fbaa072c9..0000000000 --- a/src/extension/flow-php-ext/src/format.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Floe frame-body wire constants and a bounds-checked byte reader. The canonical -//! definitions live in the pure-PHP `Flow\Floe\Format`; mirror any change in the same PR. - -use ext_php_rs::exception::PhpException; - -use crate::exception::ext_exception; - -// Floe is little-endian by construction; a big-endian host could never match its bytes. -#[cfg(target_endian = "big")] -compile_error!("flow_php only supports little-endian targets"); - -pub const FRAME_ROW: u8 = 0x02; - -pub const VALUE_NULL: u8 = 0x00; -pub const VALUE_PRESENT: u8 = 0x01; -pub const VALUE_NULL_WITH_META: u8 = 0x02; -pub const VALUE_ABSENT: u8 = 0x03; -pub const VALUE_PRESENT_WITH_META: u8 = 0x04; - -pub struct Reader<'a> { - data: &'a [u8], - pos: usize, -} - -impl<'a> Reader<'a> { - pub fn new(data: &'a [u8]) -> Self { - Self { data, pos: 0 } - } - - pub fn is_eof(&self) -> bool { - self.pos >= self.data.len() - } - - fn take(&mut self, len: usize, context: &str) -> Result<&'a [u8], PhpException> { - let end = self - .pos - .checked_add(len) - .filter(|end| *end <= self.data.len()); - - match end { - Some(end) => { - let slice = &self.data[self.pos..end]; - self.pos = end; - Ok(slice) - } - None => Err(ext_exception(format!( - "flow_php frame body is truncated, {context} is incomplete" - ))), - } - } - - pub fn u8(&mut self, context: &str) -> Result { - Ok(self.take(1, context)?[0]) - } - - pub fn u32(&mut self, context: &str) -> Result { - let bytes = self.take(4, context)?; - - Ok(u32::from_le_bytes(bytes.try_into().expect("4-byte slice"))) - } - - pub fn i64(&mut self, context: &str) -> Result { - let bytes = self.take(8, context)?; - - Ok(i64::from_le_bytes(bytes.try_into().expect("8-byte slice"))) - } - - pub fn f64(&mut self, context: &str) -> Result { - let bytes = self.take(8, context)?; - - Ok(f64::from_le_bytes(bytes.try_into().expect("8-byte slice"))) - } - - pub fn bytes(&mut self, len: usize, context: &str) -> Result<&'a [u8], PhpException> { - self.take(len, context) - } -} - -pub fn write_u32(out: &mut Vec, value: u32) { - out.extend_from_slice(&value.to_le_bytes()); -} diff --git a/src/extension/flow-php-ext/src/globals.rs b/src/extension/flow-php-ext/src/globals.rs new file mode 100644 index 0000000000..aafa44dbad --- /dev/null +++ b/src/extension/flow-php-ext/src/globals.rs @@ -0,0 +1,43 @@ +//! Per-request state: the `Ctx` cache lives in module globals (per thread on ZTS), is built lazily and is dropped in +//! RSHUTDOWN, while the executor still runs; objects freed after RSHUTDOWN never touch it. + +use ext_php_rs::prelude::PhpResult; +use ext_php_rs::zend::{ModuleGlobal, ModuleGlobals}; + +use crate::ctx::Ctx; +use crate::exception::ext_exception; + +#[derive(Default)] +pub struct FlowGlobals { + ctx: Option, + closed: bool, +} + +impl ModuleGlobal for FlowGlobals {} + +pub static GLOBALS: ModuleGlobals = ModuleGlobals::new(); + +pub extern "C" fn request_startup(_type: i32, _module_number: i32) -> i32 { + unsafe { GLOBALS.get_mut() }.closed = false; + + 0 +} + +pub extern "C" fn request_shutdown(_type: i32, _module_number: i32) -> i32 { + let globals = unsafe { GLOBALS.get_mut() }; + globals.ctx = None; + globals.closed = true; + + 0 +} + +/// The only access to `Ctx`. `f` must not call PHP code: PHP re-entering flow_php would alias the `&mut Ctx`. +pub fn with_ctx(f: impl FnOnce(&mut Ctx) -> PhpResult) -> PhpResult { + let globals = unsafe { GLOBALS.get_mut() }; + + if globals.closed { + return Err(ext_exception("flow_php used after request shutdown")); + } + + f(globals.ctx.get_or_insert_with(Ctx::default)) +} diff --git a/src/extension/flow-php-ext/src/hydrate.rs b/src/extension/flow-php-ext/src/hydrate.rs deleted file mode 100644 index 767e9123cf..0000000000 --- a/src/extension/flow-php-ext/src/hydrate.rs +++ /dev/null @@ -1,576 +0,0 @@ -//! Object-graph assembly mirroring `Flow\ETL\Row\PhpRowHydrator` and -//! `EntryInstantiator`: constructor-less instantiation with direct -//! property-slot writes. - -use std::collections::HashMap; - -use ext_php_rs::boxed::ZBox; -use ext_php_rs::exception::PhpException; -use ext_php_rs::types::{ZendHashTable, ZendObject, Zval}; - -use ext_php_rs::zend::{ClassEntry, Function}; - -use crate::ctx::{ - array_key_index, call_handle, call_handle_on, ce_method_ref, - find_class, ht_add, ht_find_key, ht_insert, ht_insert_key, - property_offset, write_slot, zval_str, Ctx, HtKey, -}; -use crate::encode::{expect_object, ht_for_each, read_slot}; -use crate::exception::ext_exception; -use crate::format::{ - Reader, VALUE_NULL, VALUE_NULL_WITH_META, VALUE_PRESENT, VALUE_PRESENT_WITH_META, -}; -use crate::plan::{Decoder, Plan}; -use crate::values::decode_value; - -/// Resolved `Flow\ETL\Row\RawRowValues` class handles, shared by the binary decoder and the hydrator. -pub struct RowValuesClass { - pub ce: &'static ClassEntry, - pub values_slot: u32, - pub metadata_slot: u32, -} - -impl RowValuesClass { - pub fn resolve() -> Result { - let ce = find_class("Flow\\ETL\\Row\\RawRowValues")?; - - Ok(Self { - ce, - values_slot: property_offset(ce, "values")?, - metadata_slot: property_offset(ce, "metadata")?, - }) - } -} - -/// Reads one per-value metadata blob (`u32 len` + JSON) and rebuilds the -/// `Flow\ETL\Schema\Metadata` value object via the canonical PHP -/// `json_decode` + `Metadata::fromArray` - the rare diverging path only. -fn read_metadata(reader: &mut Reader, ctx: &mut Ctx) -> Result { - let length = reader.u32("per-value metadata length")? as usize; - let blob = reader.bytes(length, "per-value metadata")?; - - let json_zv = zval_str(blob); - let mut assoc_zv = Zval::new(); - assoc_zv.set_bool(true); - - let map = { - let json_decode = ctx.json_decode()?; - call_handle( - json_decode, - None, - &mut [json_zv.shallow_clone(), assoc_zv], - "decode per-value metadata", - )? - }; - - let from_array = ctx.metadata_from_array()?; - call_handle(from_array, None, &mut [map], "build per-value metadata") -} - -/// One column of a ROW frame body: its value, and the per-value metadata when the flag carries one. -pub(crate) fn read_cell( - decoder: &Decoder, - reader: &mut Reader, - ctx: &mut Ctx, -) -> Result<(Zval, Option), PhpException> { - Ok(match reader.u8("row value flag")? { - VALUE_PRESENT => (decode_value(decoder, reader, ctx)?, None), - VALUE_NULL => (Zval::new(), None), - VALUE_PRESENT_WITH_META => { - let metadata = read_metadata(reader, ctx)?; - - (decode_value(decoder, reader, ctx)?, Some(metadata)) - } - VALUE_NULL_WITH_META => (Zval::new(), Some(read_metadata(reader, ctx)?)), - other => { - return Err(ext_exception(format!( - "flow_php found unknown value flag 0x{other:02X}" - ))); - } - }) -} - -/// Decodes one ROW frame body into a `Flow\ETL\Row\RawRowValues` object - values keyed by -/// column name, absent columns omitted, diverging per-value metadata recorded in `metadata`. -pub fn decode_row_values( - plan: &Plan, - reader: &mut Reader, - ctx: &mut Ctx, - class: &RowValuesClass, -) -> Result, PhpException> { - let mut values_ht = ZendHashTable::with_capacity(plan.columns.len() as u32); - let mut metadata_ht = ZendHashTable::new(); - - for column in &plan.columns { - let (value, metadata) = read_cell(&column.decoder, reader, ctx)?; - - if let Some(metadata) = metadata { - ht_insert(&mut metadata_ht, column.name.as_bytes(), metadata); - } - - if !ht_add(&mut values_ht, column.name.as_bytes(), value) { - return Err(ext_exception(format!( - "flow_php found duplicated entry name \"{}\" in a row frame", - column.name - ))); - } - } - - let mut row_values = ZendObject::new(class.ce); - - let mut values_zv = Zval::new(); - values_zv.set_hashtable(values_ht); - write_slot(&mut row_values, class.values_slot, values_zv); - - let mut metadata_zv = Zval::new(); - metadata_zv.set_hashtable(metadata_ht); - write_slot(&mut row_values, class.metadata_slot, metadata_zv); - - Ok(row_values) -} - -/// Resolved property-table slot offsets for the `Rows -> Schema` / `Rows -> Row` -/// graph traversed by `dehydrate`. The Schema carries the column types now, so -/// they are read once per batch instead of once per cell. -pub struct RowsClasses { - pub rows_slot: u32, - pub schema_slot: u32, - pub row_values_slot: u32, - pub definitions_slot: u32, -} - -impl RowsClasses { - pub fn resolve() -> Result { - let rows_ce = find_class("Flow\\ETL\\Rows")?; - - Ok(Self { - rows_slot: property_offset(rows_ce, "rows")?, - schema_slot: property_offset(rows_ce, "schema")?, - row_values_slot: property_offset(find_class("Flow\\ETL\\Row")?, "values")?, - definitions_slot: property_offset(find_class("Flow\\ETL\\Schema")?, "definitions")?, - }) - } -} - -/// Resolved `Flow\ETL\Row\TypedRowValues` class handle + its three slot offsets. -pub struct TypedRowValuesClass { - pub ce: &'static ClassEntry, - pub values_slot: u32, - pub types_slot: u32, - pub metadata_slot: u32, -} - -impl TypedRowValuesClass { - pub fn resolve() -> Result { - let ce = find_class("Flow\\ETL\\Row\\TypedRowValues")?; - - Ok(Self { - ce, - values_slot: property_offset(ce, "values")?, - types_slot: property_offset(ce, "types")?, - metadata_slot: property_offset(ce, "metadata")?, - }) - } -} - -/// `(type(), metadata())` method handles cached per definition class. -pub type DefFnCache = HashMap; - -pub(crate) fn def_dehydrate_fns( - cache: &mut DefFnCache, - ce: &ClassEntry, -) -> Result<(&'static Function, &'static Function), PhpException> { - let key = std::ptr::from_ref(ce) as usize; - - if let Some(fns) = cache.get(&key) { - return Ok(*fns); - } - - let fns = (ce_method_ref(ce, "type")?, ce_method_ref(ce, "metadata")?); - cache.insert(key, fns); - - Ok(fns) -} - -/// One column of a batch's dehydrate plan: the key, and the `type()` / -/// `metadata()` zvals read once from the batch Schema. -pub(crate) struct DehydrateColumn { - numeric_key: Option, - name_zv: Zval, - type_zv: Zval, - metadata_zv: Option, -} - -impl DehydrateColumn { - fn key(&self) -> HtKey<'_> { - match self.numeric_key { - Some(index) => HtKey::Index(index), - None => HtKey::Str(self.name_zv.zend_str().expect("column names are strings")), - } - } -} - -/// Mirrors `PhpRowHydrator::dehydrate` for one row: values come from -/// `Row::values`, types and metadata from the batch Schema. -fn dehydrate_row( - values_ht: &ZendHashTable, - columns: &[DehydrateColumn], - class: &TypedRowValuesClass, -) -> Result, PhpException> { - let mut values_ht_out = ZendHashTable::with_capacity(columns.len() as u32); - let mut types_ht = ZendHashTable::with_capacity(columns.len() as u32); - let mut metadata_ht = ZendHashTable::new(); - - for column in columns { - let key = column.key(); - - let Some(value) = ht_find_key(values_ht, &key) else { - return Err(ext_exception(format!( - "flow_php found a row that does not carry the declared column \"{}\"", - column.name_zv.str().unwrap_or("?") - ))); - }; - - ht_insert_key(&mut values_ht_out, &key, value.shallow_clone()); - ht_insert_key(&mut types_ht, &key, column.type_zv.shallow_clone()); - - if let Some(metadata) = &column.metadata_zv { - ht_insert_key(&mut metadata_ht, &key, metadata.shallow_clone()); - } - } - - let mut row_values = ZendObject::new(class.ce); - - let mut values_zv = Zval::new(); - values_zv.set_hashtable(values_ht_out); - write_slot(&mut row_values, class.values_slot, values_zv); - - let mut types_zv = Zval::new(); - types_zv.set_hashtable(types_ht); - write_slot(&mut row_values, class.types_slot, types_zv); - - let mut metadata_zv = Zval::new(); - metadata_zv.set_hashtable(metadata_ht); - write_slot(&mut row_values, class.metadata_slot, metadata_zv); - - Ok(row_values) -} - -/// The batch behind a `Flow\ETL\Rows`: its `rows` table and one dehydrate column per Schema definition - the -/// `type()`/`metadata()` calls made once per batch, not once per cell. -pub(crate) fn dehydrate_batch<'a>( - rows: &'a Zval, - rows_classes: &RowsClasses, - def_fn_cache: &mut DefFnCache, - ctx: &mut Ctx, -) -> Result<(&'a ZendHashTable, Vec), PhpException> { - let rows_obj = expect_object(rows, "Rows")?; - let rows_ht = read_slot(rows_obj, rows_classes.rows_slot) - .array() - .ok_or_else(|| ext_exception("flow_php expected Rows::rows to be an array"))?; - - let schema = read_slot(rows_obj, rows_classes.schema_slot) - .object() - .ok_or_else(|| ext_exception("flow_php expected Rows::schema to be an object"))?; - let definitions_ht = read_slot(schema, rows_classes.definitions_slot) - .array() - .ok_or_else(|| ext_exception("flow_php expected Schema::definitions to be an array"))?; - - let metadata_map_slot = ctx.metadata_map_slot()?; - - let mut columns: Vec = Vec::with_capacity(definitions_ht.len()); - - ht_for_each(definitions_ht, |_, _, def_zv| { - let definition = expect_object(def_zv, "a Definition")?; - let definition_ce = unsafe { definition.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve a definition class"))?; - - let entry_fn = ce_method_ref(definition_ce, "entry")?; - let reference = call_handle_on(entry_fn, definition, &mut [], "read a definition reference")?; - let reference_obj = expect_object(&reference, "a definition reference")?; - let reference_ce = unsafe { reference_obj.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve a Reference class"))?; - let name_fn = ce_method_ref(reference_ce, "name")?; - let name_zv = call_handle_on(name_fn, reference_obj, &mut [], "read a definition name")?; - let numeric_key = array_key_index( - name_zv - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected a definition name to be a string"))? - .as_bytes(), - ); - - let (type_fn, metadata_fn) = def_dehydrate_fns(def_fn_cache, definition_ce)?; - - let type_zv = call_handle_on(type_fn, definition, &mut [], "read a definition type")?; - let metadata_zv = - call_handle_on(metadata_fn, definition, &mut [], "read definition metadata")?; - - let metadata = expect_object(&metadata_zv, "definition metadata")?; - let non_empty = read_slot(metadata, metadata_map_slot) - .array() - .is_some_and(|map| !map.is_empty()); - - columns.push(DehydrateColumn { - numeric_key, - name_zv, - type_zv, - metadata_zv: if non_empty { Some(metadata_zv) } else { None }, - }); - - Ok(()) - })?; - - Ok((rows_ht, columns)) -} - -/// `TypedRowValues::metadata` as `dehydrate_row` builds it - the batch's columns with non-empty metadata, the same -/// map for every row of the batch. -pub(crate) fn batch_metadata(columns: &[DehydrateColumn]) -> ZBox { - let mut metadata_ht = ZendHashTable::new(); - - for column in columns { - if let Some(metadata) = &column.metadata_zv { - ht_insert_key(&mut metadata_ht, &column.key(), metadata.shallow_clone()); - } - } - - metadata_ht -} - -/// Native `PhpRowHydrator::dehydrate`: turns a `Flow\ETL\Rows` into a list of -/// `Flow\ETL\Row\TypedRowValues`, value zvals moved verbatim (no casting). -pub fn dehydrate_rows( - rows: &Zval, - rows_classes: &RowsClasses, - class: &TypedRowValuesClass, - def_fn_cache: &mut DefFnCache, - ctx: &mut Ctx, -) -> Result { - let (rows_ht, columns) = dehydrate_batch(rows, rows_classes, def_fn_cache, ctx)?; - - let mut out = ZendHashTable::with_capacity(rows_ht.len() as u32); - - ht_for_each(rows_ht, |_, _, row_zv| { - let row = expect_object(row_zv, "a Row")?; - let values_ht = read_slot(row, rows_classes.row_values_slot) - .array() - .ok_or_else(|| ext_exception("flow_php expected Row::values to be an array"))?; - - let row_values = dehydrate_row(values_ht, &columns, class)?; - - out.push(row_values) - .map_err(|e| ext_exception(format!("flow_php failed to collect row values: {e:?}")))?; - - Ok(()) - })?; - - let mut zv = Zval::new(); - zv.set_hashtable(out); - - Ok(zv) -} - -/// The `Row`/`Rows` class entries used to assemble a hydrated `Rows` through -/// the canonical PHP `Row` constructor and `Rows::conformed()` door, plus the -/// handles the cast path re-raises a refused value through. -pub struct AssemblyClasses { - pub row_ce: &'static ClassEntry, - /// `Rows::conformed()` - the shape-only door `HydratedBatch` returns through, - /// so both hydrators assemble the batch by the same rule - pub rows_conformed: &'static Function, - /// `Rows::trusted()` - taken instead of `rows_conformed` when conform() would return every row unchanged - pub rows_trusted: &'static Function, - pub schema_mismatch_ce: &'static ClassEntry, - /// the base `PhpRowHydrator`'s guard catches, so a refusal is recognised on - /// both paths by the same rule and anything else stays the caller's exception - pub types_exception_ce: &'static ClassEntry, - pub value_does_not_match: &'static Function, -} - -impl AssemblyClasses { - pub fn resolve() -> Result { - Ok(Self { - row_ce: find_class("Flow\\ETL\\Row")?, - rows_conformed: ce_method_ref(find_class("Flow\\ETL\\Rows")?, "conformed")?, - rows_trusted: ce_method_ref(find_class("Flow\\ETL\\Rows")?, "trusted")?, - schema_mismatch_ce: find_class("Flow\\ETL\\Exception\\SchemaMismatchException")?, - types_exception_ce: find_class("Flow\\Types\\Exception\\Exception")?, - value_does_not_match: ce_method_ref( - find_class("Flow\\ETL\\Exception\\ColumnMismatchException")?, - "valueDoesNotMatch", - )?, - }) - } -} - -/// A per-column hydrate plan entry. Storage is name-keyed and the Schema owns -/// the column's type, so a column is just its key. -pub(crate) struct HydrateColumn { - numeric_key: Option, - pub(crate) name_zv: Zval, - /// retained (refcount++) so the cast plan can read `type()` once per column - pub(crate) base_def: Zval, - /// `Definition::isNullable()`, read once at plan build - never per row - pub(crate) nullable: bool, -} - -impl HydrateColumn { - pub(crate) fn key(&self) -> HtKey<'_> { - match self.numeric_key { - Some(index) => HtKey::Index(index), - None => HtKey::Str(self.name_zv.zend_str().expect("column names are strings")), - } - } -} - -/// `Schema` is immutable - `add()`/`keep()`/`makeNullable()` return a new -/// instance carrying a freshly built `definitions` array - so the array's -/// address identifies the definition set; retaining it (refcount++) prevents -/// address reuse. Keying on the array rather than on `Schema` identity also -/// survives a caller that hands the same definitions to a new `Schema`. -/// Per-value `setMetadata` returns a new `Definition` and leaves the retained -/// ones untouched, so it needs no rebuild. -pub struct HydratePlan { - pub(crate) definitions_slot: u32, - pub(crate) definitions_retained: Zval, - pub(crate) columns: Vec, -} - -/// Builds the per-column hydrate plan from a `Schema` object. Storage is -/// name-keyed and the Schema owns the column type, so a column is just its key. -/// Method calls are fine here - this runs once per schema, never per row. -pub(crate) fn build_hydrate_plan(schema: &Zval) -> Result { - let schema_obj = expect_object(schema, "a Schema")?; - let schema_ce = unsafe { schema_obj.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve the Schema class"))?; - - let definitions_slot = property_offset(schema_ce, "definitions")?; - let definitions_fn = ce_method_ref(schema_ce, "definitions")?; - let definitions = call_handle_on( - definitions_fn, - schema_obj, - &mut [], - "read schema definitions", - )?; - let definitions_ht = definitions - .array() - .ok_or_else(|| ext_exception("flow_php expected Schema::definitions to return an array"))?; - - let mut columns = Vec::with_capacity(definitions_ht.len()); - - ht_for_each(definitions_ht, |_, _, def_zv| { - let def_obj = expect_object(def_zv, "a Definition")?; - let def_ce = unsafe { def_obj.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve a Definition class"))?; - - let entry_fn = ce_method_ref(def_ce, "entry")?; - let reference = call_handle_on(entry_fn, def_obj, &mut [], "read a definition reference")?; - let reference_obj = expect_object(&reference, "a definition reference")?; - let reference_ce = unsafe { reference_obj.ce.as_ref() } - .ok_or_else(|| ext_exception("flow_php failed to resolve a Reference class"))?; - let name_fn = ce_method_ref(reference_ce, "name")?; - let name_zv = call_handle_on(name_fn, reference_obj, &mut [], "read a definition name")?; - let numeric_key = array_key_index( - name_zv - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected a definition name to be a string"))? - .as_bytes(), - ); - - let nullable = call_handle_on( - ce_method_ref(def_ce, "isNullable")?, - def_obj, - &mut [], - "read a definition nullability", - )? - .bool() - .ok_or_else(|| ext_exception("flow_php expected Definition::isNullable to return a bool"))?; - - columns.push(HydrateColumn { - numeric_key, - name_zv, - base_def: def_zv.shallow_clone(), - nullable, - }); - - Ok(()) - })?; - - Ok(HydratePlan { - definitions_slot, - definitions_retained: definitions, - columns, - }) -} - -/// `HydratedBatch` folds `RawRowValues::metadata` into the batch Schema before building rows, so a -/// column carries one Metadata rather than a per-row divergent one. The native hydrate and cast -/// paths have to fold identically or a natively hydrated batch silently loses column metadata that -/// the pure-PHP one keeps. Last write wins, matching the PHP loop order. -pub fn fold_metadata_into_schema( - schema: &Zval, - batch_ht: &ZendHashTable, - raw_class: &RowValuesClass, - ctx: &mut Ctx, -) -> Result { - let mut pending: Vec<(Vec, Zval)> = Vec::new(); - - ht_for_each(batch_ht, |_, _, rv_zv| { - let rv = expect_object(rv_zv, "a RawRowValues")?; - - let Some(metadata_ht) = read_slot(rv, raw_class.metadata_slot).array() else { - return Ok(()); - }; - - ht_for_each(metadata_ht, |key, index, metadata_zv| { - // PHP stores a numeric column name as an integer key; HydratedBatch casts it back to the name - let name = key.map_or_else(|| (index as i64).to_string().into_bytes(), |name| name.as_bytes().to_vec()); - pending.push((name, metadata_zv.shallow_clone())); - - Ok(()) - }) - })?; - - fold_pending_metadata(schema, pending, ctx) -} - -/// Folds `(column name, Metadata)` pairs, in the order the rows carried them, into the Schema. -pub fn fold_pending_metadata( - schema: &Zval, - pending: Vec<(Vec, Zval)>, - ctx: &mut Ctx, -) -> Result { - if pending.is_empty() { - return Ok(schema.shallow_clone()); - } - - let find_definition = ctx.schema_find_definition()?; - let set_metadata = ctx.schema_set_metadata()?; - let mut current = schema.shallow_clone(); - - for (name, metadata) in pending { - let object = current - .object() - .ok_or_else(|| ext_exception("flow_php expected a Schema object"))?; - - let found = call_handle_on( - find_definition, - object, - &mut [zval_str(&name)], - "Flow\\ETL\\Schema::findDefinition", - )?; - - if found.is_null() { - continue; - } - - current = call_handle_on( - set_metadata, - object, - &mut [zval_str(&name), metadata], - "Flow\\ETL\\Schema::setMetadata", - )?; - } - - Ok(current) -} diff --git a/src/extension/flow-php-ext/src/interfaces.rs b/src/extension/flow-php-ext/src/interfaces.rs new file mode 100644 index 0000000000..4557838403 --- /dev/null +++ b/src/extension/flow-php-ext/src/interfaces.rs @@ -0,0 +1,143 @@ +//! `Flow\ETL\Column\{Column, ColumnBuilder, Backend}`: registered at MINIT with the library files' exact signatures, so +//! the extension's classes implement them and the library files (autoloaded only without flow_php) stay unused. + +use std::sync::atomic::{AtomicPtr, Ordering}; + +use ext_php_rs::args::Arg; +use ext_php_rs::builders::{ClassBuilder, FunctionBuilder}; +use ext_php_rs::error::Result; +use ext_php_rs::flags::{ClassFlags, DataType, MethodFlags}; +use ext_php_rs::zend::ClassEntry; + +const DEFINITION: DataType = DataType::Object(Some("Flow\\ETL\\Schema\\Definition")); +const TYPE: DataType = DataType::Object(Some("Flow\\Types\\Type")); +const COLUMN: DataType = DataType::Object(Some("Flow\\ETL\\Column\\Column")); +const COLUMN_BUILDER: DataType = DataType::Object(Some("Flow\\ETL\\Column\\ColumnBuilder")); +const SELF: DataType = DataType::Object(Some("self")); + +// ClassEntry::try_find reads EG(class_table), which MINIT has not set, so each CE is kept from its registration +static COLUMN_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static COLUMN_BUILDER_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static BACKEND_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + +fn store_column(ce: &'static mut ClassEntry) { + COLUMN_CE.store(ce, Ordering::Release); +} + +fn store_column_builder(ce: &'static mut ClassEntry) { + COLUMN_BUILDER_CE.store(ce, Ordering::Release); +} + +fn store_backend(ce: &'static mut ClassEntry) { + BACKEND_CE.store(ce, Ordering::Release); +} + +fn load(ce: &AtomicPtr, name: &str) -> &'static ClassEntry { + unsafe { ce.load(Ordering::Acquire).as_ref() }.unwrap_or_else(|| panic!("{name} not registered")) +} + +pub fn column_ce() -> &'static ClassEntry { + load(&COLUMN_CE, "Flow\\ETL\\Column\\Column") +} + +pub fn column_builder_ce() -> &'static ClassEntry { + load(&COLUMN_BUILDER_CE, "Flow\\ETL\\Column\\ColumnBuilder") +} + +pub fn backend_ce() -> &'static ClassEntry { + load(&BACKEND_CE, "Flow\\ETL\\Column\\Backend") +} + +fn method(name: &str, args: Vec>, returns: DataType) -> FunctionBuilder<'static> { + args.into_iter() + .fold(FunctionBuilder::new_abstract(name), FunctionBuilder::arg) + .returns(returns, false, false) +} + +fn interface(name: &str, store: fn(&'static mut ClassEntry), methods: Vec>) -> Result<()> { + methods + .into_iter() + .fold( + ClassBuilder::new(name).flags(ClassFlags::Interface).registration(store), + |class, method| class.method(method, MethodFlags::Public | MethodFlags::Abstract), + ) + .register() +} + +pub fn register() -> Result<()> { + interface( + "Flow\\ETL\\Column\\Column", + store_column, + vec![ + method("type", vec![], TYPE), + method("count", vec![], DataType::Long), + method("isNull", vec![Arg::new("i", DataType::Long)], DataType::Bool), + method("nullCount", vec![], DataType::Long), + method("at", vec![Arg::new("i", DataType::Long)], DataType::Mixed), + method("physicals", vec![], DataType::Array), + method("value", vec![Arg::new("i", DataType::Long)], DataType::Mixed), + method("values", vec![], DataType::Array), + method( + "slice", + vec![Arg::new("offset", DataType::Long), Arg::new("length", DataType::Long)], + SELF, + ), + method("take", vec![Arg::new("indices", DataType::Array)], SELF), + method("withType", vec![Arg::new("type", TYPE)], SELF), + method("concat", vec![Arg::new("others", SELF).is_variadic()], SELF), + method("encode", vec![], DataType::Array), + ], + )?; + interface( + "Flow\\ETL\\Column\\ColumnBuilder", + store_column_builder, + vec![ + method("append", vec![Arg::new("value", DataType::Mixed)], DataType::Void), + method("appendMany", vec![Arg::new("values", DataType::Array)], DataType::Void), + method( + "appendFrom", + vec![Arg::new("column", COLUMN), Arg::new("i", DataType::Long)], + DataType::Void, + ), + method( + "appendTake", + vec![Arg::new("column", COLUMN), Arg::new("indices", DataType::Array)], + DataType::Void, + ), + method("count", vec![], DataType::Long), + method("finish", vec![], COLUMN), + ], + )?; + interface( + "Flow\\ETL\\Column\\Backend", + store_backend, + vec![ + method("builder", vec![Arg::new("definition", DEFINITION)], COLUMN_BUILDER), + method( + "constant", + vec![ + Arg::new("definition", DEFINITION), + Arg::new("value", DataType::Mixed), + Arg::new("count", DataType::Long), + ], + COLUMN, + ), + method( + "decode", + vec![ + Arg::new("definition", DEFINITION), + Arg::new("buffers", DataType::Array), + Arg::new("count", DataType::Long), + Arg::new("nullCount", DataType::Long), + ], + COLUMN, + ), + method( + "adopt", + vec![Arg::new("definition", DEFINITION), Arg::new("column", COLUMN)], + COLUMN, + ), + method("allocatedBytes", vec![], DataType::Long), + ], + ) +} diff --git a/src/extension/flow-php-ext/src/kind_builder.rs b/src/extension/flow-php-ext/src/kind_builder.rs new file mode 100644 index 0000000000..38d3a3af6e --- /dev/null +++ b/src/extension/flow-php-ext/src/kind_builder.rs @@ -0,0 +1,324 @@ +//! Arrow storage for one column kind, appended row by row and finished into the `ArrayData` whose data type is +//! `flow_batch_frame::kind::data_type(kind)`. A null row is stored the canonical way: zeroed slot, offset not advanced, +//! every structure child null. + +use arrow_array::cast::AsArray; +use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; +use arrow_array::Array; +use arrow_buffer::{BooleanBufferBuilder, Buffer, NullBufferBuilder}; +use arrow_data::ArrayData; +use arrow_schema::ArrowError; +use flow_batch_frame::kind::{data_type, Kind}; + +/// Offsets are i32 (D5): the last offset a row would reach past `i32::MAX`. +pub struct OffsetOverflow(pub u64); + +pub enum KindBuilder { + Null { + len: usize, + }, + Fixed { + width: usize, + values: Vec, + validity: NullBufferBuilder, + }, + Boolean { + values: BooleanBufferBuilder, + validity: NullBufferBuilder, + }, + Bytes { + offsets: Vec, + data: Vec, + validity: NullBufferBuilder, + }, + List { + offsets: Vec, + validity: NullBufferBuilder, + element: Box, + }, + Map { + offsets: Vec, + validity: NullBufferBuilder, + keys: Box, + values: Box, + }, + Struct { + len: usize, + validity: NullBufferBuilder, + children: Vec, + }, +} + +fn width(kind: &Kind) -> usize { + match kind { + Kind::Int32 => 4, + Kind::Uuid => 16, + _ => 8, + } +} + +fn offset(len: usize) -> Result { + i32::try_from(len).map_err(|_| OffsetOverflow(len as u64)) +} + +impl KindBuilder { + pub fn new(kind: &Kind) -> Self { + match kind { + Kind::Null => KindBuilder::Null { len: 0 }, + Kind::Boolean => KindBuilder::Boolean { + values: BooleanBufferBuilder::new(0), + validity: NullBufferBuilder::new(0), + }, + Kind::Bytes => KindBuilder::Bytes { + offsets: vec![0], + data: Vec::new(), + validity: NullBufferBuilder::new(0), + }, + Kind::List(element) => KindBuilder::List { + offsets: vec![0], + validity: NullBufferBuilder::new(0), + element: Box::new(KindBuilder::new(&element.kind)), + }, + Kind::Map(key, value) => KindBuilder::Map { + offsets: vec![0], + validity: NullBufferBuilder::new(0), + keys: Box::new(KindBuilder::new(&key.kind)), + values: Box::new(KindBuilder::new(&value.kind)), + }, + Kind::Struct(fields) => KindBuilder::Struct { + len: 0, + validity: NullBufferBuilder::new(0), + children: fields.iter().map(|field| KindBuilder::new(&field.kind)).collect(), + }, + _ => KindBuilder::Fixed { + width: width(kind), + values: Vec::new(), + validity: NullBufferBuilder::new(0), + }, + } + } + + pub fn len(&self) -> usize { + match self { + KindBuilder::Null { len } | KindBuilder::Struct { len, .. } => *len, + KindBuilder::Fixed { validity, .. } + | KindBuilder::Boolean { validity, .. } + | KindBuilder::Bytes { validity, .. } + | KindBuilder::List { validity, .. } + | KindBuilder::Map { validity, .. } => validity.len(), + } + } + + pub fn append_null(&mut self) { + match self { + KindBuilder::Null { len } => *len += 1, + KindBuilder::Fixed { width, values, validity } => { + values.resize(values.len() + *width, 0); + validity.append_null(); + } + KindBuilder::Boolean { values, validity } => { + values.append(false); + validity.append_null(); + } + KindBuilder::Bytes { offsets, validity, .. } + | KindBuilder::List { offsets, validity, .. } + | KindBuilder::Map { offsets, validity, .. } => { + offsets.push(*offsets.last().expect("offsets start at 0")); + validity.append_null(); + } + KindBuilder::Struct { len, validity, children } => { + *len += 1; + validity.append_null(); + + for child in children { + child.append_null(); + } + } + } + } + + /// A fixed-width value in its little-endian bytes (i64, i32 days, f64 bits, 16 uuid bytes). + pub fn append_fixed(&mut self, bytes: &[u8]) { + let KindBuilder::Fixed { values, validity, .. } = self else { + unreachable!("append_fixed on a non fixed-width kind"); + }; + + values.extend_from_slice(bytes); + validity.append_non_null(); + } + + pub fn append_bool(&mut self, value: bool) { + let KindBuilder::Boolean { values, validity } = self else { + unreachable!("append_bool on a non boolean kind"); + }; + + values.append(value); + validity.append_non_null(); + } + + pub fn append_bytes(&mut self, bytes: &[u8]) -> Result<(), OffsetOverflow> { + let KindBuilder::Bytes { offsets, data, validity } = self else { + unreachable!("append_bytes on a non bytes kind"); + }; + + let end = offset(data.len() + bytes.len())?; + data.extend_from_slice(bytes); + offsets.push(end); + validity.append_non_null(); + + Ok(()) + } + + /// The element builder of a list; call `end_entries` once the row's elements are appended. + pub fn list_element(&mut self) -> &mut KindBuilder { + let KindBuilder::List { element, .. } = self else { + unreachable!("list_element on a non list kind"); + }; + + element + } + + pub fn map_entries(&mut self) -> (&mut KindBuilder, &mut KindBuilder) { + let KindBuilder::Map { keys, values, .. } = self else { + unreachable!("map_entries on a non map kind"); + }; + + (keys, values) + } + + /// Closes a valid list or map row over the elements appended since the previous row. + pub fn end_entries(&mut self) -> Result<(), OffsetOverflow> { + let (offsets, validity, len) = match self { + KindBuilder::List { offsets, validity, element } => (offsets, validity, element.len()), + KindBuilder::Map { offsets, validity, keys, .. } => (offsets, validity, keys.len()), + _ => unreachable!("end_entries on a non list/map kind"), + }; + + offsets.push(offset(len)?); + validity.append_non_null(); + + Ok(()) + } + + pub fn struct_children(&mut self) -> &mut [KindBuilder] { + let KindBuilder::Struct { children, .. } = self else { + unreachable!("struct_children on a non structure kind"); + }; + + children + } + + /// Closes a valid structure row whose children were each appended once. + pub fn end_struct(&mut self) { + let KindBuilder::Struct { len, validity, .. } = self else { + unreachable!("end_struct on a non structure kind"); + }; + + *len += 1; + validity.append_non_null(); + } + + /// Row `i` of `array`, whose data type is `data_type(kind)`. + pub fn append_from(&mut self, array: &dyn Array, kind: &Kind, i: usize) -> Result<(), OffsetOverflow> { + if matches!(kind, Kind::Null) || array.is_null(i) { + self.append_null(); + + return Ok(()); + } + + match kind { + Kind::Null => unreachable!("appended above"), + Kind::Int64 => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), + Kind::Timestamp => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), + Kind::Duration => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), + Kind::Int32 => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), + Kind::Float64 => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), + Kind::Uuid => self.append_fixed(array.as_fixed_size_binary().value(i)), + Kind::Boolean => self.append_bool(array.as_boolean().value(i)), + Kind::Bytes => self.append_bytes(array.as_binary::().value(i))?, + Kind::List(element) => { + let list = array.as_list::(); + let offsets = list.value_offsets(); + + for j in offsets[i] as usize..offsets[i + 1] as usize { + self.list_element().append_from(list.values().as_ref(), &element.kind, j)?; + } + + self.end_entries()?; + } + Kind::Map(key, value) => { + let map = array.as_map(); + let offsets = map.value_offsets(); + + for j in offsets[i] as usize..offsets[i + 1] as usize { + let (keys, values) = self.map_entries(); + keys.append_from(map.keys().as_ref(), &key.kind, j)?; + values.append_from(map.values().as_ref(), &value.kind, j)?; + } + + self.end_entries()?; + } + Kind::Struct(fields) => { + let structure = array.as_struct(); + + for ((child, field), column) in self.struct_children().iter_mut().zip(fields).zip(structure.columns()) { + child.append_from(column.as_ref(), &field.kind, i)?; + } + + self.end_struct(); + } + } + + Ok(()) + } + + /// The rows appended so far; the builder keeps them and may be appended to again. + pub fn finish(&self, kind: &Kind) -> Result { + let builder = ArrayData::builder(data_type(kind)).len(self.len()); + + let builder = match (self, kind) { + (KindBuilder::Null { .. }, _) => builder, + (KindBuilder::Fixed { values, validity, .. }, _) => builder + .nulls(validity.finish_cloned()) + .add_buffer(Buffer::from_slice_ref(values)), + (KindBuilder::Boolean { values, validity }, _) => builder + .nulls(validity.finish_cloned()) + .add_buffer(values.finish_cloned().into_inner()), + (KindBuilder::Bytes { offsets, data, validity }, _) => builder + .nulls(validity.finish_cloned()) + .add_buffer(Buffer::from_slice_ref(offsets)) + .add_buffer(Buffer::from_slice_ref(data)), + (KindBuilder::List { offsets, validity, element }, Kind::List(field)) => builder + .nulls(validity.finish_cloned()) + .add_buffer(Buffer::from_slice_ref(offsets)) + .add_child_data(element.finish(&field.kind)?), + (KindBuilder::Map { offsets, validity, keys, values }, Kind::Map(key, value)) => { + let arrow_schema::DataType::Map(entries, _) = data_type(kind) else { + unreachable!("a map kind has a map data type") + }; + let entries = ArrayData::builder(entries.data_type().clone()) + .len(keys.len()) + .add_child_data(keys.finish(&key.kind)?) + .add_child_data(values.finish(&value.kind)?) + .build()?; + + builder + .nulls(validity.finish_cloned()) + .add_buffer(Buffer::from_slice_ref(offsets)) + .add_child_data(entries) + } + (KindBuilder::Struct { validity, children, .. }, Kind::Struct(fields)) => builder + .nulls(validity.finish_cloned()) + .child_data( + children + .iter() + .zip(fields) + .map(|(child, field)| child.finish(&field.kind)) + .collect::>()?, + ), + _ => unreachable!("a builder is finished with the kind it was built for"), + }; + + builder.build() + } +} diff --git a/src/extension/flow-php-ext/src/lib.rs b/src/extension/flow-php-ext/src/lib.rs index 651f0e1301..7dc1d014b5 100644 --- a/src/extension/flow-php-ext/src/lib.rs +++ b/src/extension/flow-php-ext/src/lib.rs @@ -1,34 +1,30 @@ +mod alloc; +mod backend; +mod builder; mod cast; +mod column; mod csv; mod ctx; mod date_check; -mod encode; mod exception; -mod format; -mod hydrate; +mod globals; +mod interfaces; mod json_check; +mod kind_builder; +mod physical; mod plan; +mod render; mod uuid_check; mod values; -use std::alloc::System; - use ext_php_rs::binary_slice::BinarySlice; use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, Zval}; use ext_php_rs::zend::ModuleEntry; use ext_php_rs::{info_table_end, info_table_row, info_table_start}; -use crate::ctx::{ht_insert, zval_str, Ctx}; -use crate::encode::{ - build_encode_plan, encode_frames, encode_typed_row, expect_object, ht_for_each, read_slot, EncodePlan, -}; +use crate::ctx::{ht_insert, zval_str}; use crate::exception::ext_exception; -use crate::format::Reader; -use crate::plan::Plan; - -#[global_allocator] -static GLOBAL: System = System; pub extern "C" fn php_module_info(_module: *mut ModuleEntry) { info_table_start!(); @@ -45,296 +41,28 @@ pub unsafe extern "C" fn module_startup(_type: i32, _module_number: i32) -> i32 eprintln!("flow_php: failed to register Flow\\Floe\\Exception\\ExtensionException: {e}"); return -1; } - 0 -} - -/// A built plan together with the schema JSON it was built from; the schema -/// bytes decide when a new schema requires a plan rebuild. Generic over the plan -/// kind so encode (`EncodePlan`) and decode (`Plan`) share one rebind path. -struct BoundPlan

      { - schema: Vec, - plan: P, -} - -/// Rebuilds the bound plan when the schema JSON changed, `Ctx` caches survive rebinds. -fn ensure_plan

      ( - bound: &mut Option>, - ctx: &mut Ctx, - schema: &[u8], - build: impl FnOnce(&[u8], &mut Ctx) -> PhpResult

      , -) -> PhpResult<()> { - if bound.as_ref().is_some_and(|b| b.schema == schema) { - return Ok(()); - } - - *bound = Some(BoundPlan { - schema: schema.to_vec(), - plan: build(schema, ctx)?, - }); - - Ok(()) -} - -/// Floe's consolidated binary codec, both directions: ROW frame bodies to/from -/// `Flow\ETL\Row\RawRowValues` (decode) and `Flow\ETL\Row\TypedRowValues` (encode), -/// plus `decode_rows` / `encode_frames`, which go straight between frames and `Flow\ETL\Rows`. -/// The PHP side keeps buffering/framing/sectioning and hands over bare frame -/// bodies; the extension owns value encode/decode against a primed schema. -#[php_class] -#[php(name = "Flow\\Floe\\RustFloeEncoderNative")] -pub struct RustFloeEncoderNative { - ctx: Ctx, - encode_bound: Option>, - decode_bound: Option>, - row_values_class: hydrate::RowValuesClass, - cast_plan: Option, - assembly: hydrate::AssemblyClasses, - rows_classes: hydrate::RowsClasses, - def_dehydrate_fns: hydrate::DefFnCache, -} - -#[php_impl] -impl RustFloeEncoderNative { - pub fn __construct() -> PhpResult { - Ok(Self { - ctx: Ctx::new()?, - encode_bound: None, - decode_bound: None, - row_values_class: hydrate::RowValuesClass::resolve()?, - cast_plan: None, - assembly: hydrate::AssemblyClasses::resolve()?, - rows_classes: hydrate::RowsClasses::resolve()?, - def_dehydrate_fns: hydrate::DefFnCache::new(), - }) - } - - /// Encodes a list of `Flow\ETL\Row\TypedRowValues` into a list of bare ROW - /// frame bodies against the plan bound to `schema_body`. - pub fn encode( - &mut self, - batch: &Zval, - schema_body: BinarySlice, - schema: &Zval, - ) -> PhpResult { - ensure_plan( - &mut self.encode_bound, - &mut self.ctx, - &schema_body, - |body, ctx| build_encode_plan(body, schema, ctx), - )?; - - let batch_ht = batch - .array() - .ok_or_else(|| ext_exception("flow_php expected a list of typed row values"))?; - - let (values_slot, metadata_slot) = self.ctx.typed_row_values_slots()?; - - let plan = &self.encode_bound.as_ref().expect("plan bound above").plan; - let ctx = &mut self.ctx; - - let mut encoded = ZendHashTable::with_capacity(batch_ht.len() as u32); - - ht_for_each(batch_ht, |_, row_index, item_zv| { - let typed = expect_object(item_zv, "a TypedRowValues")?; - - let values_ht = read_slot(typed, values_slot).array().ok_or_else(|| { - ext_exception("flow_php expected TypedRowValues::values to be an array") - })?; - let metadata_ht = read_slot(typed, metadata_slot).array().ok_or_else(|| { - ext_exception("flow_php expected TypedRowValues::metadata to be an array") - })?; - - let mut body = Vec::with_capacity(1024); - encode_typed_row(plan, row_index, values_ht, metadata_ht, &mut body, ctx)?; - - encoded.push(zval_str(&body)).map_err(|e| { - ext_exception(format!("flow_php failed to collect a row body: {e:?}")) - })?; - - Ok(()) - })?; - - let mut zv = Zval::new(); - zv.set_hashtable(encoded); - - Ok(zv) - } - - /// `Rows` straight to complete ROW frames (frame type + length + body per row) in one string - see - /// `encode::encode_frames`. - pub fn encode_frames( - &mut self, - rows: &Zval, - schema_body: BinarySlice, - schema: &Zval, - ) -> PhpResult { - ensure_plan( - &mut self.encode_bound, - &mut self.ctx, - &schema_body, - |body, ctx| build_encode_plan(body, schema, ctx), - )?; - - let (rows_ht, columns) = - hydrate::dehydrate_batch(rows, &self.rows_classes, &mut self.def_dehydrate_fns, &mut self.ctx)?; - - let frames = encode_frames( - &self.encode_bound.as_ref().expect("plan bound above").plan, - rows_ht, - self.rows_classes.row_values_slot, - &hydrate::batch_metadata(&columns), - &mut self.ctx, - )?; - - Ok(zval_str(&frames)) - } - - /// Decodes a list of ROW frame bodies written with the given SCHEMA frame - /// body into `Flow\ETL\Row\RawRowValues` objects. - pub fn decode(&mut self, frame_bodies: &Zval, schema_body: BinarySlice) -> PhpResult { - ensure_plan( - &mut self.decode_bound, - &mut self.ctx, - &schema_body, - plan::build_plan, - )?; - - let bodies_ht = frame_bodies - .array() - .ok_or_else(|| ext_exception("flow_php expected a list of row frame bodies"))?; - - let plan = &self.decode_bound.as_ref().expect("plan bound above").plan; - let class = &self.row_values_class; - let ctx = &mut self.ctx; - - let mut decoded = ZendHashTable::with_capacity(bodies_ht.len() as u32); - - ht_for_each(bodies_ht, |_, _, body_zv| { - let bytes = body_zv - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected a row frame body to be a string"))? - .as_bytes(); - - let mut reader = Reader::new(bytes); - let row_values = hydrate::decode_row_values(plan, &mut reader, ctx, class)?; - - if !reader.is_eof() { - return Err(ext_exception( - "flow_php row frame length does not match its content", - )); - } - - decoded.push(row_values).map_err(|e| { - ext_exception(format!("flow_php failed to collect row values: {e:?}")) - })?; - - Ok(()) - })?; - - let mut zv = Zval::new(); - zv.set_hashtable(decoded); - - Ok(zv) - } - - /// Frame bodies decoded and cast against `schema` straight into `Flow\ETL\Rows` - see `cast::decode_rows`. - pub fn decode_rows( - &mut self, - frame_bodies: &Zval, - schema_body: BinarySlice, - schema: &Zval, - ) -> PhpResult { - ensure_plan( - &mut self.decode_bound, - &mut self.ctx, - &schema_body, - plan::build_plan, - )?; - - cast::decode_rows( - frame_bodies, - &self.decode_bound.as_ref().expect("plan bound above").plan, - schema, - &mut self.cast_plan, - &self.assembly, - &mut self.ctx, - ) - } - - /// Present in every extension whose casts and decoders apply the datetime column zone. - #[php(name = "datetimeZones")] - pub fn datetime_zones(&self) -> bool { - true + if let Err(e) = interfaces::register() { + eprintln!("flow_php: failed to register the Flow\\ETL\\Column interfaces: {e}"); + return -1; } -} -/// Native counterpart of `PhpRowHydrator`: `hydrate` builds `Flow\ETL\Rows` from -/// a list of `RawRowValues` against a `Schema` object, casting each value against -/// the schema first; `dehydrate` turns `Rows` into a list of `TypedRowValues`. -#[php_class] -#[php(name = "Flow\\ETL\\Row\\RustRowHydratorNative")] -pub struct RustRowHydratorNative { - ctx: Ctx, - rows_classes: hydrate::RowsClasses, - typed_row_values_class: hydrate::TypedRowValuesClass, - raw_row_values_class: hydrate::RowValuesClass, - assembly: hydrate::AssemblyClasses, - def_dehydrate_fns: hydrate::DefFnCache, - cast_plan: Option, + 0 } -#[php_impl] -impl RustRowHydratorNative { - pub fn __construct() -> PhpResult { - Ok(Self { - ctx: Ctx::new()?, - rows_classes: hydrate::RowsClasses::resolve()?, - typed_row_values_class: hydrate::TypedRowValuesClass::resolve()?, - raw_row_values_class: hydrate::RowValuesClass::resolve()?, - assembly: hydrate::AssemblyClasses::resolve()?, - def_dehydrate_fns: hydrate::DefFnCache::new(), - cast_plan: None, - }) - } - - /// Casts a list of raw-scalar `RawRowValues` against a `Schema` and builds - /// a `Flow\ETL\Rows` in a single pass. - pub fn hydrate(&mut self, batch: &Zval, schema: &Zval) -> PhpResult { - cast::cast_rows( - batch, - schema, - &mut self.cast_plan, - &self.raw_row_values_class, - &self.assembly, - &mut self.ctx, - ) - } - - /// Turns a `Flow\ETL\Rows` into a list of `Flow\ETL\Row\TypedRowValues`. - pub fn dehydrate(&mut self, rows: &Zval) -> PhpResult { - hydrate::dehydrate_rows( - rows, - &self.rows_classes, - &self.typed_row_values_class, - &mut self.def_dehydrate_fns, - &mut self.ctx, - ) - } - - /// Present in every extension whose casts and decoders apply the datetime column zone. - #[php(name = "datetimeZones")] - pub fn datetime_zones(&self) -> bool { - true - } +fn csv_batch_size(batch_size: i64) -> PhpResult { + usize::try_from(batch_size) + .ok() + .filter(|size| *size > 0) + .ok_or_else(|| ext_exception("flow_php CSV batch size must be greater than 0")) } -/// Native counterpart of `CSVLineReader` + `CSVEncoder::decode()`: bytes in, `RawRowValues` out, +/// Native counterpart of `CSVLineReader` + `CSVEncoder::decode()`: bytes in, rows or native columns out, /// byte-identical to the PHP path. Resumable - `feed` any chunk size, `finish` at EOF. #[php_class] #[php(name = "Flow\\ETL\\Adapter\\CSV\\RustCSVReaderNative")] pub struct RustCSVReaderNative { reader: csv::CsvReader, - row_values_class: hydrate::RowValuesClass, + columns: Option, } #[php_impl] @@ -349,7 +77,7 @@ impl RustCSVReaderNative { ) -> PhpResult { Ok(Self { reader: csv::CsvReader::new(&separator, &enclosure, &escape, with_header, empty_to_null, remove_bom)?, - row_values_class: hydrate::RowValuesClass::resolve()?, + columns: None, }) } @@ -394,16 +122,18 @@ impl RustCSVReaderNative { } pub fn next(&mut self, batch_size: i64) -> PhpResult { - let batch_size = usize::try_from(batch_size) - .ok() - .filter(|size| *size > 0) - .ok_or_else(|| ext_exception("flow_php CSV batch size must be greater than 0"))?; - let mut zv = Zval::new(); - zv.set_hashtable(self.reader.next(batch_size, &self.row_values_class)?); + zv.set_hashtable(self.reader.next(csv_batch_size(batch_size)?)?); Ok(zv) } + + /// Exactly `$batchSize` rows keyed and ordered by `$schema` while that many are buffered, the remainder after + /// `finish()`, else null. Refusals are `RowsBuilder::appendRows()`'s, row indexes relative to the batch. + #[php(name = "nextColumns")] + pub fn next_columns(&mut self, schema: &Zval, batch_size: i64) -> PhpResult { + csv::columns::next_columns(&mut self.reader, &mut self.columns, schema, csv_batch_size(batch_size)?) + } } /// `ColumnTypes::observe()` over native CSV rows: a column fold seeded with the header names and gated by the @@ -453,8 +183,12 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { module .version(env!("FLOW_PHP_EXT_VERSION")) .info_function(php_module_info) - .class::() - .class::() + .globals(&globals::GLOBALS) + .request_startup_function(globals::request_startup) + .request_shutdown_function(globals::request_shutdown) + .class::() + .class::() + .class::() .class::() .class::() } diff --git a/src/extension/flow-php-ext/src/physical.rs b/src/extension/flow-php-ext/src/physical.rs new file mode 100644 index 0000000000..32b52532fd --- /dev/null +++ b/src/extension/flow-php-ext/src/physical.rs @@ -0,0 +1,275 @@ +//! Arrow rows as the zvals the PHP columns hold and return: `at()` (the physical form `PhysicalFor` produces), +//! `value()` (the logical form `Physical::fromPhysical()` builds), and a physical zval appended back into storage. + +use arrow_array::cast::AsArray; +use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; +use arrow_array::Array; +use ext_php_rs::boxed::ZBox; +use ext_php_rs::exception::PhpException; +use ext_php_rs::flags::DataType; +use ext_php_rs::types::{ZendHashTable, Zval}; +use flow_batch_frame::kind::Kind; + +use crate::ctx::{self, call_method, ht_for_each, ht_insert, null_zval, zval_long, zval_str}; +use crate::exception::ext_exception; +use crate::kind_builder::{KindBuilder, OffsetOverflow}; +use crate::plan::ValueNode; +use crate::render::{invalid_argument, offset_overflow}; +use crate::values::{date_from_days, datetime_from_micros, interval_from_micros, json_from_bytes, uuid_from_bytes}; + +fn long(array: &dyn Array, kind: &Kind, i: usize) -> i64 { + match kind { + Kind::Int64 => array.as_primitive::().value(i), + Kind::Timestamp => array.as_primitive::().value(i), + Kind::Duration => array.as_primitive::().value(i), + Kind::Int32 => i64::from(array.as_primitive::().value(i)), + _ => unreachable!("long() reads integer kinds only"), + } +} + +fn double(value: f64) -> Zval { + let mut zv = Zval::new(); + zv.set_double(value); + zv +} + +fn boolean(value: bool) -> Zval { + let mut zv = Zval::new(); + zv.set_bool(value); + zv +} + +fn array_zval(ht: ZBox) -> Zval { + let mut zv = Zval::new(); + zv.set_hashtable(ht); + zv +} + +fn push(ht: &mut ZendHashTable, value: Zval) -> Result<(), PhpException> { + ht.push(value) + .map_err(|e| ext_exception(format!("flow_php failed to collect column values: {e:?}"))) +} + +/// A map key as `array_keys()` returns it: the int or string key `array_combine()` coerces. +fn map_key(ht: &mut ZendHashTable, keys: &dyn Array, key: &Kind, j: usize, value: Zval) { + match key { + Kind::Bytes => ht_insert(ht, keys.as_binary::().value(j), value), + _ => { + let index = long(keys, key, j); + crate::ctx::ht_insert_long(ht, index, value); + } + } +} + +/// `Column::at($i)`: null, int (µs, days), float, bool, string (16 bytes for a uuid), or nested arrays. +pub fn physical_at(array: &dyn Array, kind: &Kind, i: usize) -> Result { + if matches!(kind, Kind::Null) || array.is_null(i) { + return Ok(null_zval()); + } + + Ok(match kind { + Kind::Null => unreachable!("returned above"), + Kind::Int64 | Kind::Timestamp | Kind::Duration | Kind::Int32 => zval_long(long(array, kind, i)), + Kind::Float64 => double(array.as_primitive::().value(i)), + Kind::Boolean => boolean(array.as_boolean().value(i)), + Kind::Uuid => zval_str(array.as_fixed_size_binary().value(i)), + Kind::Bytes => zval_str(array.as_binary::().value(i)), + Kind::List(element) => { + let list = array.as_list::(); + let offsets = list.value_offsets(); + let mut ht = ZendHashTable::with_capacity((offsets[i + 1] - offsets[i]) as u32); + + for j in offsets[i] as usize..offsets[i + 1] as usize { + push(&mut ht, physical_at(list.values().as_ref(), &element.kind, j)?)?; + } + + array_zval(ht) + } + Kind::Map(key, value) => { + let map = array.as_map(); + let offsets = map.value_offsets(); + let mut ht = ZendHashTable::with_capacity((offsets[i + 1] - offsets[i]) as u32); + + for j in offsets[i] as usize..offsets[i + 1] as usize { + let physical = physical_at(map.values().as_ref(), &value.kind, j)?; + map_key(&mut ht, map.keys().as_ref(), &key.kind, j, physical); + } + + array_zval(ht) + } + Kind::Struct(fields) => { + let structure = array.as_struct(); + let mut ht = ZendHashTable::with_capacity(fields.len() as u32); + + for (field, child) in fields.iter().zip(structure.columns()) { + if matches!(field.kind, Kind::Null) || child.is_null(i) { + if !field.optional { + ht_insert(&mut ht, field.name.as_bytes(), null_zval()); + } + + continue; + } + + ht_insert(&mut ht, field.name.as_bytes(), physical_at(child.as_ref(), &field.kind, i)?); + } + + array_zval(ht) + } + }) +} + +/// `Column::value($i)`: the logical value of row `i`, built natively except markup (D4). +pub fn value_at(array: &dyn Array, kind: &Kind, node: &ValueNode, i: usize) -> Result { + if matches!(kind, Kind::Null) || array.is_null(i) { + return Ok(null_zval()); + } + + match (node, kind) { + (ValueNode::DateTime(zone), _) => datetime_from_micros(long(array, kind, i), zone), + (ValueNode::Date, _) => date_from_days(long(array, kind, i)), + (ValueNode::Time, _) => interval_from_micros(long(array, kind, i)), + (ValueNode::Uuid, _) => uuid_from_bytes(array.as_fixed_size_binary().value(i)), + (ValueNode::Json, _) => json_from_bytes(array.as_binary::().value(i)), + (ValueNode::Enum(class), _) => ctx::enum_case(class, array.as_binary::().value(i)), + (ValueNode::TimeZone, _) => ctx::timezone(array.as_binary::().value(i)), + (ValueNode::Markup(physical), _) => call_method( + physical, + "fromPhysical", + &mut [zval_str(array.as_binary::().value(i))], + ), + (ValueNode::List(element_node), Kind::List(element)) => { + let list = array.as_list::(); + let offsets = list.value_offsets(); + let mut ht = ZendHashTable::with_capacity((offsets[i + 1] - offsets[i]) as u32); + + for j in offsets[i] as usize..offsets[i + 1] as usize { + push(&mut ht, value_at(list.values().as_ref(), &element.kind, element_node, j)?)?; + } + + Ok(array_zval(ht)) + } + (ValueNode::Map(value_node), Kind::Map(key, value)) => { + let map = array.as_map(); + let offsets = map.value_offsets(); + let mut ht = ZendHashTable::with_capacity((offsets[i + 1] - offsets[i]) as u32); + + for j in offsets[i] as usize..offsets[i + 1] as usize { + let logical = value_at(map.values().as_ref(), &value.kind, value_node, j)?; + map_key(&mut ht, map.keys().as_ref(), &key.kind, j, logical); + } + + Ok(array_zval(ht)) + } + (ValueNode::Struct(nodes), Kind::Struct(fields)) => { + let structure = array.as_struct(); + let mut ht = ZendHashTable::with_capacity(fields.len() as u32); + + for ((field, child), child_node) in fields.iter().zip(structure.columns()).zip(nodes) { + if matches!(field.kind, Kind::Null) || child.is_null(i) { + if !field.optional { + ht_insert(&mut ht, field.name.as_bytes(), null_zval()); + } + + continue; + } + + ht_insert(&mut ht, field.name.as_bytes(), value_at(child.as_ref(), &field.kind, child_node, i)?); + } + + Ok(array_zval(ht)) + } + _ => physical_at(array, kind, i), + } +} + +fn wrong_physical(kind: &Kind, physical: &Zval) -> PhpException { + invalid_argument(format!( + "flow_php cannot store a {} physical in a {kind:?} column", + physical.get_type() + )) +} + +pub fn overflow(OffsetOverflow(last): OffsetOverflow) -> PhpException { + offset_overflow(last) +} + +/// Appends one physical zval (what `Physical::toPhysical()` or `Column::at()` returns) to `builder`. +pub fn append_physical(builder: &mut KindBuilder, kind: &Kind, physical: &Zval) -> Result<(), PhpException> { + let physical = physical.dereference(); + + if physical.is_null() || matches!(kind, Kind::Null) { + builder.append_null(); + + return Ok(()); + } + + match kind { + Kind::Null => unreachable!("appended above"), + Kind::Int64 | Kind::Timestamp | Kind::Duration => { + let value = physical.long().ok_or_else(|| wrong_physical(kind, physical))?; + builder.append_fixed(&value.to_le_bytes()); + } + Kind::Int32 => { + let value = physical + .long() + .and_then(|value| i32::try_from(value).ok()) + .ok_or_else(|| wrong_physical(kind, physical))?; + builder.append_fixed(&value.to_le_bytes()); + } + Kind::Float64 => { + let value = physical.double().ok_or_else(|| wrong_physical(kind, physical))?; + builder.append_fixed(&value.to_le_bytes()); + } + Kind::Boolean => builder.append_bool(physical.bool().ok_or_else(|| wrong_physical(kind, physical))?), + Kind::Uuid => { + let bytes = physical + .zend_str() + .map(|string| string.as_bytes()) + .filter(|bytes| bytes.len() == 16) + .ok_or_else(|| wrong_physical(kind, physical))?; + builder.append_fixed(bytes); + } + Kind::Bytes => builder + .append_bytes(physical.zend_str().ok_or_else(|| wrong_physical(kind, physical))?.as_bytes()) + .map_err(overflow)?, + Kind::List(element) => { + let values = physical.array().ok_or_else(|| wrong_physical(kind, physical))?; + + ht_for_each(values, |_, _, value| append_physical(builder.list_element(), &element.kind, value))?; + builder.end_entries().map_err(overflow)?; + } + Kind::Map(key, value) => { + let entries = physical.array().ok_or_else(|| wrong_physical(kind, physical))?; + + ht_for_each(entries, |string_key, index, item| { + let (keys, values) = builder.map_entries(); + let key_zv = match string_key { + Some(name) => zval_str(name.as_bytes()), + None => zval_long(index as i64), + }; + // array keys are ints for numeric strings: a string-keyed map stores their decimal text + let key_zv = match (&key.kind, key_zv.get_type()) { + (Kind::Bytes, DataType::Long) => zval_str(index.to_string().as_bytes()), + _ => key_zv, + }; + + append_physical(keys, &key.kind, &key_zv)?; + append_physical(values, &value.kind, item) + })?; + builder.end_entries().map_err(overflow)?; + } + Kind::Struct(fields) => { + let elements = physical.array().ok_or_else(|| wrong_physical(kind, physical))?; + let null = null_zval(); + + for (child, field) in builder.struct_children().iter_mut().zip(fields) { + let element = crate::ctx::ht_get(elements, field.name.as_bytes()).unwrap_or(&null); + append_physical(child, &field.kind, element)?; + } + + builder.end_struct(); + } + } + + Ok(()) +} diff --git a/src/extension/flow-php-ext/src/plan.rs b/src/extension/flow-php-ext/src/plan.rs index fa08a5b0a4..385933c831 100644 --- a/src/extension/flow-php-ext/src/plan.rs +++ b/src/extension/flow-php-ext/src/plan.rs @@ -1,217 +1,139 @@ -//! Decode plan built from a SCHEMA frame body (a JSON list of normalized definitions): -//! per column a name and a recursive value `Decoder`, in schema order. +//! What a column of one Flow type needs beyond its `Kind`, derived once per type JSON (`Type::normalize()`) and shared +//! by every column and builder of that type: the Type object, its cast lane, its `Physical`, and how its logical +//! values are built. -use ext_php_rs::exception::PhpException; -use serde::Deserialize; - -use crate::ctx::Ctx; -use crate::exception::ext_exception; +use std::rc::Rc; -pub enum MapKey { - Integer, - String, +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::Zval; +use ext_php_rs::zend::Function; +use flow_batch_frame::kind::{kind_of, parse_type, Kind, TypeJson}; + +use crate::cast::{build_cast_kind, CastKind}; +use crate::ctx::{self, call_handle, call_method, ce_method_ref, expect_object, find_class, instance}; +use crate::exception::{ext_exception, json_exception}; + +const PHYSICAL_FOR: &str = "Flow\\ETL\\Column\\Php\\PhysicalFor"; +const IDENTITY: &str = "Flow\\ETL\\Column\\Php\\IdentityPhysical"; + +pub struct TypePlan { + pub kind: Kind, + pub type_zv: Zval, + pub values: ValueNode, + pub cast: CastKind, + /// `$type->cast()` of the concrete Type class. + pub cast_fn: &'static Function, + /// `PhysicalFor::type($type)` and its `toPhysical()`. + pub physical: Zval, + pub to_physical: &'static Function, + /// The physical is `IdentityPhysical`: the cast value is the physical one. + pub identity: bool, } -/// Recursive value decoder mirroring `ValueDecoder::decoderFor` dispatch. -pub enum Decoder { - Integer, - Float, - Boolean, - String, +/// How a logical value is built from its physical one. +pub enum ValueNode { + Plain, Null, - /// A `datetime` column: the stored instant, in the column zone. DateTime(Vec), - /// A `date`, or a zone-less `datetime` from an older flow-php/etl: each value's stored zone. - StoredZoneDateTime, - Interval, + Date, + Time, Uuid, Json, + Enum(Vec), TimeZone, - Enum, - Xml, - XmlElement, - Html, - HtmlElement, - List(Box), - Map(MapKey, Box), - Structure(Vec<(Vec, Decoder)>), - Optional(Box), -} - -pub struct Column { - pub name: String, - pub decoder: Decoder, -} - -pub struct Plan { - pub columns: Vec, + /// A markup `Physical` whose `fromPhysical()` builds the DOM value (D4). + Markup(Zval), + List(Box), + Map(Box), + Struct(Vec), } -#[derive(Deserialize, Default)] -pub struct TypeJson { - #[serde(rename = "type")] - pub type_: String, - element: Option>, - key: Option>, - value: Option>, - base: Option>, - #[serde(default)] - fields: Vec, - #[serde(default)] - zone: Option, -} - -#[derive(Deserialize)] -pub struct StructureElementJson { - // ALWAYS a JSON string - PHP casts the name on normalize(). A JSON number here - // would fail parse_schema_json for the WHOLE schema, not just this field. - pub name: String, - #[serde(rename = "type")] - pub type_: TypeJson, - #[serde(default)] - pub optional: bool, -} - -impl TypeJson { - pub fn element(&self) -> Option<&TypeJson> { - self.element.as_deref() - } - - pub fn key(&self) -> Option<&TypeJson> { - self.key.as_deref() +/// The plan of `$type`, built on first use of its type JSON. +pub fn type_plan(type_zv: &Zval) -> Result, PhpException> { + if let Some(plan) = ctx::type_plan_of(type_zv)? { + return Ok(plan); } - pub fn value(&self) -> Option<&TypeJson> { - self.value.as_deref() - } - - pub fn base(&self) -> Option<&TypeJson> { - self.base.as_deref() - } + let plan = json_plan(type_zv)?; + ctx::store_type_plan(type_zv, &plan)?; - pub fn fields(&self) -> &[StructureElementJson] { - &self.fields - } + Ok(plan) +} - pub fn zone(&self) -> Option<&[u8]> { - self.zone.as_deref().map(str::as_bytes) +fn json_plan(type_zv: &Zval) -> Result, PhpException> { + let normalized = call_method(type_zv, "normalize", &mut [])?; + let json = call_handle(ctx::json_encode()?, None, &mut [normalized], "encode a type as JSON")?; + let json = json + .zend_str() + .ok_or_else(|| ext_exception("flow_php expected type JSON to be a string"))? + .as_bytes() + .to_vec(); + + if let Some(plan) = ctx::plan(&json)? { + return Ok(plan); } -} -#[derive(Deserialize)] -pub struct NormalizedDefinition { - #[serde(rename = "ref")] - pub name: String, - #[serde(rename = "type")] - pub type_: TypeJson, - pub nullable: bool, + let parsed = parse_type(&json).map_err(json_exception)?; + let type_obj = expect_object(type_zv, "a Type")?; + let type_ce = unsafe { type_obj.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php failed to resolve a Type class"))?; + let physical = call_method(&instance(PHYSICAL_FOR)?, "type", &mut [type_zv.shallow_clone()])?; + let plan = Rc::new(TypePlan { + kind: kind_of(&parsed).map_err(json_exception)?, + type_zv: type_zv.shallow_clone(), + values: value_node(&parsed)?, + cast: build_cast_kind(&parsed), + cast_fn: ce_method_ref(type_ce, "cast")?, + to_physical: ce_method_ref( + unsafe { expect_object(&physical, "a Physical")?.ce.as_ref() } + .ok_or_else(|| ext_exception("flow_php failed to resolve a Physical class"))?, + "toPhysical", + )?, + physical: physical.shallow_clone(), + identity: expect_object(&physical, "a Physical")?.instance_of(find_class(IDENTITY)?), + }); + ctx::store_plan(json, &plan)?; + + Ok(plan) } -pub fn parse_schema_json(schema_json: &[u8]) -> Result, PhpException> { - let json = std::str::from_utf8(schema_json) - .map_err(|_| ext_exception("flow_php failed to decode schema JSON: invalid UTF-8"))?; - - serde_json::from_str(json) - .map_err(|e| ext_exception(format!("flow_php failed to decode schema JSON: {e}"))) +/// `PhysicalFor::definition($definition)`: its refusals (wildcard enum, mixed, a foreign definition) are PHP's. +pub fn physical_for_definition(definition: &Zval) -> Result { + call_method(&instance(PHYSICAL_FOR)?, "definition", &mut [definition.shallow_clone()]) } -fn build_decoder(type_json: &TypeJson) -> Result { - let missing = |part: &str| { - ext_exception(format!( - "flow_php schema JSON for type \"{}\" is missing its {part}", - type_json.type_ - )) +fn value_node(parsed: &TypeJson) -> Result { + let child = |part: Option<&TypeJson>| -> Result, PhpException> { + Ok(Box::new(value_node(part.ok_or_else(|| ext_exception("flow_php type JSON is missing a nested type"))?)?)) }; - Ok(match type_json.type_.as_str() { - "integer" | "positive_integer" => Decoder::Integer, - "float" => Decoder::Float, - "boolean" => Decoder::Boolean, - "string" | "non_empty_string" | "numeric-string" | "class_string" => Decoder::String, - "null" => Decoder::Null, - "datetime" => match type_json.zone() { - Some(zone) => Decoder::DateTime(zone.to_vec()), - None => Decoder::StoredZoneDateTime, - }, - "date" => Decoder::StoredZoneDateTime, - "time" => Decoder::Interval, - "uuid" => Decoder::Uuid, - "json" => Decoder::Json, - "timezone" => Decoder::TimeZone, - "enum" => Decoder::Enum, - "xml" => Decoder::Xml, - "xml_element" => Decoder::XmlElement, - "html" => Decoder::Html, - "html_element" => Decoder::HtmlElement, - "list" => Decoder::List(Box::new(build_decoder( - type_json - .element - .as_ref() - .ok_or_else(|| missing("element"))?, - )?)), - "map" => { - let key = match type_json - .key - .as_ref() - .ok_or_else(|| missing("key"))? - .type_ - .as_str() - { - "integer" => MapKey::Integer, - "string" => MapKey::String, - other => { - return Err(ext_exception(format!( - "flow_php does not support map keys of type \"{other}\"" - ))); - } - }; - - Decoder::Map( - key, - Box::new(build_decoder( - type_json.value.as_ref().ok_or_else(|| missing("value"))?, - )?), - ) - } - "structure_v2" => { - if type_json.fields.is_empty() { - return Err(ext_exception( - "flow_php read a structure type with no fields; the loaded flow_php extension and the \ - flow-php/etl in use disagree on the structure schema format - reinstall one to match the \ - other, or set the Floe engine to FloeEngine::php", - )); - } - - let mut elements = Vec::with_capacity(type_json.fields.len()); - - for field in &type_json.fields { - elements.push((field.name.clone().into_bytes(), build_decoder(&field.type_)?)); - } - - Decoder::Structure(elements) - } - "optional" => Decoder::Optional(Box::new(build_decoder( - type_json.base.as_ref().ok_or_else(|| missing("base"))?, - )?)), - other => { - return Err(ext_exception(format!( - "flow_php does not support values of type \"{other}\" in this build" - ))); - } + Ok(match parsed.type_.as_str() { + "datetime" => ValueNode::DateTime(parsed.zone().unwrap_or(b"UTC").to_vec()), + "date" => ValueNode::Date, + "time" => ValueNode::Time, + "uuid" => ValueNode::Uuid, + "json" => ValueNode::Json, + "enum" => ValueNode::Enum( + parsed + .class() + .ok_or_else(|| ext_exception("flow_php enum type JSON is missing its class"))? + .to_vec(), + ), + "timezone" => ValueNode::TimeZone, + "xml" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Php\\XmlDocumentPhysical")?), + "xml_element" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Php\\XmlElementPhysical")?), + "html" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Php\\HtmlDocumentPhysical")?), + "html_element" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Php\\HtmlElementPhysical")?), + "null" => ValueNode::Null, + "list" => ValueNode::List(child(parsed.element())?), + "map" => ValueNode::Map(child(parsed.value())?), + "structure_v2" => ValueNode::Struct( + parsed + .fields() + .iter() + .map(|field| value_node(&field.type_)) + .collect::>()?, + ), + "optional" => *child(parsed.base())?, + _ => ValueNode::Plain, }) } - -pub fn build_plan(schema_json: &[u8], _ctx: &mut Ctx) -> Result { - let definitions = parse_schema_json(schema_json)?; - - let mut columns = Vec::with_capacity(definitions.len()); - - for definition in &definitions { - columns.push(Column { - name: definition.name.clone(), - decoder: build_decoder(&definition.type_)?, - }); - } - - Ok(Plan { columns }) -} diff --git a/src/extension/flow-php-ext/src/render.rs b/src/extension/flow-php-ext/src/render.rs new file mode 100644 index 0000000000..1d27a46d3b --- /dev/null +++ b/src/extension/flow-php-ext/src/render.rs @@ -0,0 +1,168 @@ +//! flow-batch-frame refusals rendered as the exceptions `PhpBackend::decode()` throws for the same buffers: the +//! `Flow\ETL\Exception\InvalidArgumentException` (or `OffsetOverflow`) with its exact message, a nested type named by +//! its PHP `toString()`. + +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::Zval; +use flow_batch_frame::error::{Of, Role, Values}; +use flow_batch_frame::kind::Kind; +use flow_batch_frame::layout::node_count; +use flow_batch_frame::Error; + +use crate::ctx::{call_method, expect_object, find_class, read_property}; +use crate::exception::ext_exception; + +const INVALID_ARGUMENT: &str = "Flow\\ETL\\Exception\\InvalidArgumentException"; +const OFFSET_OVERFLOW: &str = "Flow\\ETL\\Exception\\OffsetOverflow"; + +pub fn exception(class: &str, message: String) -> PhpException { + match find_class(class) { + Ok(ce) => PhpException::new(message, 0, ce), + Err(e) => e, + } +} + +pub fn invalid_argument(message: String) -> PhpException { + exception(INVALID_ARGUMENT, message) +} + +pub fn offset_overflow(last: u64) -> PhpException { + exception(OFFSET_OVERFLOW, format!("Offsets exceed the i32 range of a batch buffer: the last offset is {last}")) +} + +fn of(of: Of) -> &'static str { + match of { + Of::List => "List", + Of::Map => "Map", + Of::Utf8 => "Utf8", + } +} + +fn values(values: Values) -> &'static str { + match values { + Values::Int64 => "Int64", + Values::Int32 => "Int32", + Values::Float64 => "Float64", + Values::Boolean => "Boolean", + Values::FixedBinary16 => "FixedBinary16", + } +} + +/// A `column::decode` refusal of the column typed `type_zv`, whose kind is `kind`. +pub fn decode_exception(error: Error, type_zv: &Zval, kind: &Kind) -> PhpException { + let message = match error { + Error::OffsetOverflow { last } => return offset_overflow(last), + Error::BuffersExhausted => "Column buffers exhausted: the column needs more buffers than given".to_string(), + Error::OffsetsLength { of: layout, bytes, expected, rows } => format!( + "{} offsets buffer of {bytes} bytes, expected {expected} for {rows} rows", + of(layout) + ), + Error::MapEntriesValidity { bytes } => format!("Map entries validity must be omitted, got {bytes} bytes"), + Error::ValidityTooShort { bytes, rows } => format!("Validity bitmap of {bytes} bytes is too short for {rows} rows"), + Error::NullKindNullCount { rows, null_count } => { + format!("Null column of {rows} rows carries a null count of {null_count}") + } + Error::NullCountMismatch { declared, derived, rows } => format!( + "Column null count {declared} disagrees with its validity bitmap ({derived} nulls in {rows} rows)" + ), + Error::NestedNulls { node, role, nulls } => { + let name = match type_name_at(type_zv, kind, node) { + Ok(name) => name, + Err(e) => return e, + }; + + format!( + "{} holds {nulls} nulls in a non-nullable {name}", + match role { + Role::ListElement => "List child", + Role::MapKey => "Map key child", + Role::MapValue => "Map value child", + } + ) + } + Error::BufferCount { node, buffers, expected } => { + let name = match type_name_at(type_zv, kind, node) { + Ok(name) => name, + Err(e) => return e, + }; + + format!("Column of type {name} holds {buffers} buffers, its layout needs {expected}") + } + Error::OffsetsStart { of: layout, first } => format!("{} offsets start at {first}, not 0", of(layout)), + Error::OffsetsNotMonotonic { of: layout, index, previous, current } => format!( + "{} offsets are not monotonic: offset {} is {previous}, offset {index} is {current}", + of(layout), + index - 1 + ), + Error::ValuesLength { values: layout, bytes, expected, rows } => format!( + "{} values buffer of {bytes} bytes, expected {expected} for {rows} rows", + values(layout) + ), + Error::Utf8DataLength { bytes, last_offset } => { + format!("Utf8 data buffer of {bytes} bytes, the last offset is {last_offset}") + } + error => format!("flow_php refused the column buffers: {error}"), + }; + + invalid_argument(message) +} + +/// `toString()` of the type at pre-order `node` of `type_zv`'s tree (the map entries node counts but has no type). +fn type_name_at(type_zv: &Zval, kind: &Kind, node: usize) -> Result { + let name = call_method(&type_at(type_zv.shallow_clone(), kind, node)?, "toString", &mut [])?; + + Ok(String::from_utf8_lossy( + name.zend_str() + .ok_or_else(|| ext_exception("flow_php expected Type::toString() to return a string"))? + .as_bytes(), + ) + .into_owned()) +} + +fn type_at(type_zv: Zval, kind: &Kind, node: usize) -> Result { + if node == 0 { + return Ok(type_zv); + } + + let optional = find_class("Flow\\Types\\Type\\Logical\\OptionalType")?; + let base = if expect_object(&type_zv, "a Type")?.instance_of(optional) { + call_method(&type_zv, "base", &mut [])? + } else { + type_zv + }; + + match kind { + Kind::List(element) => type_at(call_method(&base, "element", &mut [])?, &element.kind, node - 1), + Kind::Map(key, value) => { + let key_nodes = node_count(&key.kind); + + if node - 2 < key_nodes { + type_at(call_method(&base, "key", &mut [])?, &key.kind, node - 2) + } else { + type_at(call_method(&base, "value", &mut [])?, &value.kind, node - 2 - key_nodes) + } + } + Kind::Struct(fields) => { + let elements = call_method(&base, "elements", &mut [])?; + let elements = elements + .array() + .ok_or_else(|| ext_exception("flow_php expected StructureType::elements() to return an array"))?; + let mut first = 1; + + for (field, element) in fields.iter().zip(elements.values()) { + let nodes = node_count(&field.kind); + + if node < first + nodes { + let element_type = read_property(expect_object(element, "a StructureElement")?, "type")?; + + return type_at(element_type, &field.kind, node - first); + } + + first += nodes; + } + + Err(ext_exception("flow_php could not find a structure node")) + } + _ => Err(ext_exception("flow_php could not find a nested node")), + } +} diff --git a/src/extension/flow-php-ext/src/values.rs b/src/extension/flow-php-ext/src/values.rs index b7ee2cdcc5..33774e1466 100644 --- a/src/extension/flow-php-ext/src/values.rs +++ b/src/extension/flow-php-ext/src/values.rs @@ -1,18 +1,14 @@ -//! Wire-value decoding mirroring `Flow\Floe\ValueDecoder`. +//! PHP value construction through the engine's C date API. -use std::ffi::{c_char, c_int, c_void}; +use std::ffi::{c_char, c_int, c_uint, c_void}; use ext_php_rs::exception::PhpException; -use ext_php_rs::types::{ZendHashTable, ZendObject, ZendStr, Zval}; +use ext_php_rs::types::{ZendObject, ZendStr, Zval}; use ext_php_rs::zend::ExecutorGlobals; -use crate::ctx::{ - call_handle, ensure_no_pending_exception, ht_insert, ht_insert_index, write_property_raw, - write_slot, zval_long, zval_str, Ctx, -}; +use crate::ctx::{self, call_handle, ensure_no_pending_exception, write_property_raw, write_slot, zval_long, zval_str}; +use crate::date_check::days_from_civil; use crate::exception::ext_exception; -use crate::format::{Reader, VALUE_ABSENT, VALUE_NULL, VALUE_PRESENT}; -use crate::plan::{Decoder, MapKey}; extern "C" { fn php_date_instantiate(pce: *mut ext_php_rs::zend::ClassEntry, object: *mut Zval) @@ -41,294 +37,186 @@ fn php_date_obj(object: &mut ZendObject) -> *mut c_void { .cast::() } -/// `new DateTimeImmutable($str, $timezone)` through the same C-level timelib parser, in its -/// non-throwing `date_create()` flavor: `Ok(None)` on parse failure, no exception. -pub(crate) fn date_from_free_form( - bytes: &[u8], - timezone: Option<&mut Zval>, - ctx: &mut Ctx, -) -> Result, PhpException> { - let ce = ctx.datetime_fns(false)?.ce; - - let mut datetime = Zval::new(); - unsafe { - php_date_instantiate( - std::ptr::from_ref(ce).cast_mut(), - std::ptr::from_mut(&mut datetime), - ); - } - - let datetime_obj = datetime - .object_mut() - .ok_or_else(|| ext_exception("flow_php failed to instantiate a datetime object"))?; - - // timelib reads the byte AFTER the consumed input, so the buffer must be - // NUL-terminated like the zend_strings PHP hands it (length excludes the NUL) - let mut time_str = Vec::with_capacity(bytes.len() + 1); - time_str.extend_from_slice(bytes); - time_str.push(0); - - let initialized = unsafe { - php_date_initialize( - php_date_obj(datetime_obj), - time_str.as_mut_ptr().cast::(), - time_str.len() - 1, - std::ptr::null(), - timezone.map_or(std::ptr::null_mut(), std::ptr::from_mut), - 0, - ) - }; - - if !initialized { - // date_create() reports parse failures via `false`; discard any engine - // artifact so the caller can fall back to the PHP cast cleanly - drop(ExecutorGlobals::take_exception()); - - return Ok(None); - } - - ensure_no_pending_exception("parse a datetime value")?; - - Ok(Some(datetime)) +// `timelib_time` up to `tim_uptodate` (ext/date/lib/timelib.h, identical in the 2022.14-2022.17 timelib of PHP 8.3-8.5) +#[repr(C)] +struct TimelibSpecial { + kind: c_uint, + amount: i64, } -pub fn decode_value( - decoder: &Decoder, - reader: &mut Reader, - ctx: &mut Ctx, -) -> Result { - let mut zv = Zval::new(); - - match decoder { - Decoder::Integer => zv.set_long(reader.i64("integer value")?), - Decoder::Float => zv.set_double(reader.f64("float value")?), - Decoder::Boolean => zv.set_bool(reader.u8("boolean value")? == 0x01), - Decoder::String => { - let length = reader.u32("string value")? as usize; - zv.set_zend_string(ZendStr::new(reader.bytes(length, "string value")?, false)); - } - Decoder::Null => zv.set_null(), - Decoder::DateTime(zone) => zv = decode_datetime(reader, Some(zone), ctx)?, - Decoder::StoredZoneDateTime => zv = decode_datetime(reader, None, ctx)?, - Decoder::Interval => zv = decode_interval(reader, ctx)?, - Decoder::Uuid => zv = decode_uuid(reader, ctx)?, - Decoder::Json => zv = decode_json(reader, ctx)?, - Decoder::TimeZone => { - let length = reader.u32("timezone value")? as usize; - zv = ctx - .timezone(reader.bytes(length, "timezone value")?)? - .shallow_clone(); - } - Decoder::Enum => zv = decode_enum(reader, ctx)?, - Decoder::Xml => zv = decode_via_static(reader, ctx, "xmlDocumentFromString")?, - Decoder::XmlElement => zv = decode_via_static(reader, ctx, "xmlElementFromString")?, - Decoder::Html => zv = decode_via_static(reader, ctx, "htmlDocumentFromString")?, - Decoder::HtmlElement => zv = decode_via_static(reader, ctx, "htmlElementFromString")?, - Decoder::List(element) => { - let count = reader.u32("list value")?; - let mut values = ZendHashTable::with_capacity(count); - - for _ in 0..count { - let value = decode_value(element, reader, ctx)?; - values.push(value).map_err(|e| { - ext_exception(format!("flow_php failed to collect list values: {e:?}")) - })?; - } - - zv.set_hashtable(values); - } - Decoder::Map(key, value) => zv = decode_map(key, value, reader, ctx)?, - Decoder::Structure(elements) => zv = decode_structure(elements, reader, ctx)?, - Decoder::Optional(base) => { - if reader.u8("optional value")? == VALUE_NULL { - zv.set_null(); - } else { - zv = decode_value(base, reader, ctx)?; - } - } - } - - Ok(zv) +#[repr(C)] +struct TimelibRelTime { + y: i64, + m: i64, + d: i64, + h: i64, + i: i64, + s: i64, + us: i64, + weekday: c_int, + weekday_behavior: c_int, + first_last_day_of: c_int, + invert: c_int, + days: i64, + special: TimelibSpecial, + have_weekday_relative: c_uint, + have_special_relative: c_uint, } -fn decode_map( - key: &MapKey, - value: &Decoder, - reader: &mut Reader, - ctx: &mut Ctx, -) -> Result { - let count = reader.u32("map value")?; - let mut values = ZendHashTable::with_capacity(count); - - for _ in 0..count { - match key { - MapKey::Integer => { - let map_key = reader.i64("map key")?; - let map_value = decode_value(value, reader, ctx)?; - ht_insert_index(&mut values, map_key, map_value); - } - MapKey::String => { - let length = reader.u32("map key")? as usize; - let map_key = reader.bytes(length, "map key")?; - let map_value = decode_value(value, reader, ctx)?; - ht_insert(&mut values, map_key, map_value); - } - } - } - - let mut zv = Zval::new(); - zv.set_hashtable(values); - - Ok(zv) +#[repr(C)] +struct TimelibTime { + y: i64, + m: i64, + d: i64, + h: i64, + i: i64, + s: i64, + us: i64, + z: c_int, + tz_abbr: *mut c_char, + tz_info: *mut c_void, + dst: c_int, + relative: TimelibRelTime, + sse: i64, + have_time: c_uint, + have_date: c_uint, + have_zone: c_uint, + have_relative: c_uint, + have_weeknr_day: c_uint, + sse_uptodate: c_uint, + tim_uptodate: c_uint, } -fn decode_structure( - elements: &[(Vec, Decoder)], - reader: &mut Reader, - ctx: &mut Ctx, -) -> Result { - let mut structure = ZendHashTable::with_capacity(elements.len() as u32); - - for (name, element) in elements { - let flag = reader.u8("structure element flag")?; - - match flag { - VALUE_PRESENT => { - let value = decode_value(element, reader, ctx)?; - ht_insert(&mut structure, name, value); - } - VALUE_NULL => ht_insert(&mut structure, name, Zval::new()), - VALUE_ABSENT => {} - other => { - return Err(ext_exception(format!( - "flow_php found unknown structure element flag 0x{other:02X}" - ))); - } - } - } - - let mut zv = Zval::new(); - zv.set_hashtable(structure); +/// The up-to-date `timelib_time` of a `DateTimeImmutable` (or subclass) object. +fn timelib_time(datetime: &ZendObject) -> Option<&TimelibTime> { + let dateobj = std::ptr::from_ref(datetime) + .cast::() + .wrapping_sub(PHP_DATE_OBJ_STD_OFFSET) + .cast::<*const TimelibTime>(); + let time = unsafe { (*dateobj).as_ref() }?; - Ok(zv) + (time.sse_uptodate != 0 && time.tim_uptodate != 0).then_some(time) } -/// Mirrors `DateTimeDecoder`: `zone` is its column zone, `None` restores each value's stored zone. -fn decode_datetime(reader: &mut Reader, zone: Option<&[u8]>, ctx: &mut Ctx) -> Result { - let timestamp = reader.i64("datetime value")?; - let microseconds = reader.u32("datetime value")?; - let timezone_length = reader.u32("datetime value")? as usize; - let timezone_name = reader.bytes(timezone_length, "datetime value")?; - - let restore_failed = || ext_exception(format!("flow_php failed to restore datetime from timestamp \"{timestamp}\"")); +/// `DateTimePhysical::toPhysical()`: `getTimestamp() * 1_000_000 + format('u')`, `None` on i64 overflow. +pub fn datetime_micros(datetime: &ZendObject) -> Option { + let time = timelib_time(datetime)?; - // "U.u" refuses a fraction longer than six digits as trailing data - if microseconds > 999_999 { - return Err(restore_failed()); - } + time.sse.checked_mul(1_000_000)?.checked_add(time.us) +} - // the class is not stored: a datetime column always hydrates to DateTimeImmutable - let fns = ctx.datetime_fns(false)?; +/// `DatePhysical::toPhysical()`: days since the epoch of the value's own calendar day, `None` outside i32. +pub fn datetime_days(datetime: &ZendObject) -> Option { + let time = timelib_time(datetime)?; + let days = days_from_civil(time.y, time.m, time.d)?; - let ce = fns.ce; - let set_timezone = fns.set_timezone; + i32::try_from(days).is_ok().then_some(days) +} +/// A fresh `DateTimeImmutable` initialised by `init` over its `php_date_obj`, then moved into `zone`. +fn datetime_in(zone: &[u8], init: impl FnOnce(*mut c_void) -> bool, failure: impl FnOnce() -> PhpException) -> Result { + let fns = ctx::datetime_immutable()?; let mut datetime = Zval::new(); + unsafe { - php_date_instantiate( - std::ptr::from_ref(ce).cast_mut(), - std::ptr::from_mut(&mut datetime), - ); + php_date_instantiate(std::ptr::from_ref(fns.ce).cast_mut(), std::ptr::from_mut(&mut datetime)); } let datetime_obj = datetime .object_mut() .ok_or_else(|| ext_exception("flow_php failed to instantiate a datetime object"))?; - - let dateobj = php_date_obj(datetime_obj); - - // the createFromTimestamp() initializer, exported from PHP 8.4 - #[cfg(php84)] - let initialized = { - unsafe { php_date_initialize_from_ts_long(dateobj, timestamp, microseconds as c_int) }; - - true - }; - - #[cfg(not(php84))] - let initialized = { - // timelib reads the byte AFTER the consumed input, so the buffer must be - // NUL-terminated like the zend_strings PHP hands it (length excludes the NUL) - let mut time_str = format!("{timestamp}.{microseconds:06}\0"); - - unsafe { - php_date_initialize( - dateobj, - time_str.as_mut_ptr().cast::(), - time_str.len() - 1, - c"U.u".as_ptr(), - std::ptr::null_mut(), - // PHP_DATE_INIT_FORMAT - the flags createFromFormat passes. - 0x02, - ) - } - }; + let initialized = init(php_date_obj(datetime_obj)); ensure_no_pending_exception("restore a datetime value")?; if !initialized { - return Err(restore_failed()); + return Err(failure()); } - let timezone = ctx.timezone(zone.unwrap_or(timezone_name))?.shallow_clone(); - let datetime = call_handle( - &set_timezone, - Some(datetime_obj), - &mut [timezone], - "restore a datetime timezone", - )?; + let datetime = call_handle(fns.set_timezone, Some(datetime_obj), &mut [ctx::timezone(zone)?], "restore a datetime timezone")?; if !datetime.is_object() { - return Err(ext_exception( - "flow_php expected setTimezone to return a datetime object", - )); + return Err(ext_exception("flow_php expected setTimezone to return a datetime object")); } Ok(datetime) } -/// Mirrors `ValueDecoder::decodeInterval`; `days` is intentionally not -/// preserved (same as PHP). -fn decode_interval(reader: &mut Reader, ctx: &mut Ctx) -> Result { - let invert = i64::from(reader.u8("time value")?); - let mut fields = [0i64; 7]; +/// `DateTimePhysical::fromPhysical()`: the instant `micros` in `zone`. +pub fn datetime_from_micros(micros: i64, zone: &[u8]) -> Result { + let seconds = micros.div_euclid(1_000_000); + let fraction = micros.rem_euclid(1_000_000); - for field in &mut fields[..6] { - *field = i64::from(reader.u32("time value")?); - } + datetime_in( + zone, + |dateobj| { + // the createFromTimestamp() initializer, exported from PHP 8.4 + #[cfg(php84)] + { + unsafe { php_date_initialize_from_ts_long(dateobj, seconds, fraction as c_int) }; - fields[6] = invert; - let fraction = reader.f64("time value")?; - - let interval_fns = ctx.interval()?; - let mut interval = ZendObject::new(interval_fns.ce); - call_handle( - &interval_fns.construct, - Some(&mut interval), - &mut [interval_fns.spec.shallow_clone()], - "construct DateInterval", - )?; - - for (index, value) in fields.iter().enumerate() { - write_property_raw( - &mut interval, - &mut interval_fns.names[index], - zval_long(*value), - )?; - } + true + } + + #[cfg(not(php84))] + { + // timelib reads the byte AFTER the consumed input, so the buffer must be NUL-terminated like the + // zend_strings PHP hands it (length excludes the NUL) + let mut time_str = format!("{seconds}.{fraction:06}\0"); + + unsafe { + php_date_initialize( + dateobj, + time_str.as_mut_ptr().cast::(), + time_str.len() - 1, + c"U.u".as_ptr(), + std::ptr::null_mut(), + // PHP_DATE_INIT_FORMAT - the flags createFromFormat passes + 0x02, + ) + } + } + }, + || ext_exception(format!("flow_php failed to restore datetime from \"{micros}\" microseconds")), + ) +} - let mut fraction_zv = Zval::new(); - fraction_zv.set_double(fraction); - write_property_raw(&mut interval, &mut interval_fns.names[7], fraction_zv)?; +/// `DatePhysical::fromPhysical()`: `new DateTimeImmutable('@' . ($days * 86_400))` in UTC. +pub fn date_from_days(days: i64) -> Result { + let mut time_str = format!("@{}\0", days * 86_400); + + datetime_in( + b"UTC", + |dateobj| unsafe { + php_date_initialize( + dateobj, + time_str.as_mut_ptr().cast::(), + time_str.len() - 1, + std::ptr::null(), + std::ptr::null_mut(), + 0, + ) + }, + || ext_exception(format!("flow_php failed to restore date from \"{days}\" days")), + ) +} + +/// `TimePhysical::fromPhysical()`: `PT%dH%dM%dS`, then `f` and `invert`; `days` stays `false`. +pub fn interval_from_micros(micros: i64) -> Result { + let magnitude = micros.unsigned_abs(); + let spec = format!( + "PT{}H{}M{}S", + magnitude / 3_600_000_000, + magnitude / 60_000_000 % 60, + magnitude / 1_000_000 % 60 + ); + let fns = ctx::interval()?; + let mut interval = ZendObject::new(fns.ce); + call_handle(fns.construct, Some(&mut interval), &mut [zval_str(spec.as_bytes())], "construct DateInterval")?; + + let mut fraction = Zval::new(); + fraction.set_double((magnitude % 1_000_000) as f64 / 1_000_000.0); + write_property_raw(&mut interval, &mut ZendStr::new("f", false), fraction)?; + write_property_raw(&mut interval, &mut ZendStr::new("invert", false), zval_long(i64::from(micros < 0)))?; let mut zv = Zval::new(); zv.set_object(&mut interval); @@ -336,14 +224,24 @@ fn decode_interval(reader: &mut Reader, ctx: &mut Ctx) -> Result Result { - let length = reader.u32("uuid value")? as usize; - let value = reader.bytes(length, "uuid value")?; - let (uuid_ce, value_slot) = ctx.uuid()?; +/// `Uuid::fromBytes()`: the constructor-less instance holding the lowercase 36-char form. +pub fn uuid_from_bytes(bytes: &[u8]) -> Result { + const HEX: &[u8; 16] = b"0123456789abcdef"; + + let mut text = Vec::with_capacity(36); + + for (index, byte) in bytes.iter().enumerate() { + if matches!(index, 4 | 6 | 8 | 10) { + text.push(b'-'); + } + + text.push(HEX[usize::from(byte >> 4)]); + text.push(HEX[usize::from(byte & 0x0f)]); + } + + let (uuid_ce, value_slot) = ctx::uuid()?; let mut uuid = ZendObject::new(uuid_ce); - write_slot(&mut uuid, value_slot, zval_str(value)); + write_slot(&mut uuid, value_slot, zval_str(&text)); let mut zv = Zval::new(); zv.set_object(&mut uuid); @@ -351,19 +249,15 @@ fn decode_uuid(reader: &mut Reader, ctx: &mut Ctx) -> Result Ok(zv) } -/// Mirrors `ValueDecoder::$createJson`: constructor-less instantiation. -fn decode_json(reader: &mut Reader, ctx: &mut Ctx) -> Result { - let length = reader.u32("json value")? as usize; - let value = reader.bytes(length, "json value")?; - let is_object = reader.u8("json value")? == 0x01; - - let (json_ce, value_slot, is_object_slot) = ctx.json()?; +/// `JsonFactory::create()`: the constructor-less instance, `isObject` read from the first byte. +pub fn json_from_bytes(bytes: &[u8]) -> Result { + let (json_ce, value_slot, is_object_slot) = ctx::json()?; let mut json = ZendObject::new(json_ce); - write_slot(&mut json, value_slot, zval_str(value)); + write_slot(&mut json, value_slot, zval_str(bytes)); - let mut is_object_zv = Zval::new(); - is_object_zv.set_bool(is_object); - write_slot(&mut json, is_object_slot, is_object_zv); + let mut is_object = Zval::new(); + is_object.set_bool(bytes.first() == Some(&b'{')); + write_slot(&mut json, is_object_slot, is_object); let mut zv = Zval::new(); zv.set_object(&mut json); @@ -371,33 +265,66 @@ fn decode_json(reader: &mut Reader, ctx: &mut Ctx) -> Result Ok(zv) } -fn decode_enum(reader: &mut Reader, ctx: &mut Ctx) -> Result { - let class_length = reader.u32("enum value")? as usize; - let class = reader.bytes(class_length, "enum value")?.to_vec(); - let case_length = reader.u32("enum value")? as usize; - let case = reader.bytes(case_length, "enum value")?.to_vec(); +/// `hex2bin()` of a 36-char uuid with its dashes removed. +pub fn uuid_bytes(text: &[u8]) -> Option<[u8; 16]> { + let mut bytes = [0u8; 16]; + let mut digits = text.iter().filter(|byte| **byte != b'-').map(|byte| (*byte as char).to_digit(16)); - ctx.enum_case(&class, &case) + for byte in &mut bytes { + let high = digits.next()??; + let low = digits.next()??; + *byte = (high * 16 + low) as u8; + } + + digits.next().is_none().then_some(bytes) } -/// Markup DOM reconstruction delegated to the pure-PHP `ValueDecoder` public -/// statics - the exact code its decoders run. -fn decode_via_static( - reader: &mut Reader, - ctx: &mut Ctx, - method: &'static str, -) -> Result { - let length = reader.u32("markup value")? as usize; - let markup_zv = zval_str(reader.bytes(length, "markup value")?); - - let handle = ctx.value_decoder_static(method)?; - let value = call_handle(handle, None, &mut [markup_zv], "restore a markup value")?; - - if !value.is_object() { - return Err(ext_exception(format!( - "flow_php expected ValueDecoder::{method} to return an object" - ))); +/// `new DateTimeImmutable($str, $timezone)` through the same C-level timelib parser, in its +/// non-throwing `date_create()` flavor: `Ok(None)` on parse failure, no exception. +pub(crate) fn date_from_free_form( + bytes: &[u8], + timezone: Option<&mut Zval>, +) -> Result, PhpException> { + let ce = ctx::datetime_immutable()?.ce; + + let mut datetime = Zval::new(); + unsafe { + php_date_instantiate( + std::ptr::from_ref(ce).cast_mut(), + std::ptr::from_mut(&mut datetime), + ); + } + + let datetime_obj = datetime + .object_mut() + .ok_or_else(|| ext_exception("flow_php failed to instantiate a datetime object"))?; + + // timelib reads the byte AFTER the consumed input, so the buffer must be + // NUL-terminated like the zend_strings PHP hands it (length excludes the NUL) + let mut time_str = Vec::with_capacity(bytes.len() + 1); + time_str.extend_from_slice(bytes); + time_str.push(0); + + let initialized = unsafe { + php_date_initialize( + php_date_obj(datetime_obj), + time_str.as_mut_ptr().cast::(), + time_str.len() - 1, + std::ptr::null(), + timezone.map_or(std::ptr::null_mut(), std::ptr::from_mut), + 0, + ) + }; + + if !initialized { + // date_create() reports parse failures via `false`; discard any engine + // artifact so the caller can fall back to the PHP cast cleanly + drop(ExecutorGlobals::take_exception()); + + return Ok(None); } - Ok(value) + ensure_no_pending_exception("parse a datetime value")?; + + Ok(Some(datetime)) } diff --git a/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt b/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt index 4f5db9b9fc..2a2acae623 100644 --- a/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt +++ b/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt @@ -5,10 +5,23 @@ flow_php extension is loaded and symbols are registered --FILE-- --EXPECT-- bool(true) bool(true) bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/036_extension_version_is_release_or_commit.phpt b/src/extension/flow-php-ext/tests/phpt/036_extension_version_is_release_or_commit.phpt index 9f3df11cf2..2ea6d4ffd5 100644 --- a/src/extension/flow-php-ext/tests/phpt/036_extension_version_is_release_or_commit.phpt +++ b/src/extension/flow-php-ext/tests/phpt/036_extension_version_is_release_or_commit.phpt @@ -1,10 +1,10 @@ --TEST-- -extension version is the release tag, or the last tag with commit distance and hash +extension version is the release tag, or the next minor's dev pre-release with commit distance and hash --SKIPIF-- --FILE-- --EXPECT-- int(1) diff --git a/src/extension/flow-php-ext/tests/phpt/040_csv_tokenizer_parity.phpt b/src/extension/flow-php-ext/tests/phpt/040_csv_tokenizer_parity.phpt index a12bdbdb8a..b123216bde 100644 --- a/src/extension/flow-php-ext/tests/phpt/040_csv_tokenizer_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/040_csv_tokenizer_parity.phpt @@ -26,7 +26,7 @@ foreach ($cases as $case => $hex) { $reader->feed($input . "\n"); $reader->finish(); - $fields = array_values($reader->next(10)[0]->values); + $fields = array_values($reader->next(10)[0]); $expected = str_getcsv($input, ',', '"', '\\'); echo $case, ': ', $fields === $expected ? 'identical' : 'FAIL ' . json_encode(array_map(static fn(?string $f): ?string => $f === null ? null : bin2hex($f), $fields)), "\n"; diff --git a/src/extension/flow-php-ext/tests/phpt/051_csv_guards.phpt b/src/extension/flow-php-ext/tests/phpt/051_csv_guards.phpt index 9f97f6eb6e..217c737d3b 100644 --- a/src/extension/flow-php-ext/tests/phpt/051_csv_guards.phpt +++ b/src/extension/flow-php-ext/tests/phpt/051_csv_guards.phpt @@ -9,6 +9,8 @@ require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\CSV\RustColumnFoldNative; use Flow\ETL\Adapter\CSV\RustCSVReaderNative; +use function Flow\ETL\DSL\{int_schema, schema, str_schema}; + expect_exception(static fn() => new RustCSVReaderNative(',,', '"', '\\', true, true, true)); expect_exception(static fn() => new RustCSVReaderNative(',', '', '\\', true, true, true)); expect_exception(static fn() => new RustCSVReaderNative(',', '"', '\\\\', true, true, true)); @@ -18,6 +20,17 @@ $fold = new RustColumnFoldNative([], ['integer']); expect_exception(static fn() => (new RustCSVReaderNative(',', '"', '\\', true, true, true))->fold($fold, -2)); expect_exception(static fn() => new RustColumnFoldNative([], ['integer', 'html'])); expect_exception(static fn() => new RustColumnFoldNative([], ['xml'])); + +$pending = static function (): RustCSVReaderNative { + $reader = new RustCSVReaderNative(',', '"', '\\', true, true, true); + $reader->feed("id,name\n1,a\n"); + var_dump($reader->nextColumns(schema(int_schema('id'), str_schema('name')), 10)); + + return $reader; +}; +expect_exception(static fn() => $pending()->nextColumns(schema(int_schema('id')), 10)); +expect_exception(static fn() => $pending()->nextColumns(schema(int_schema('id'), str_schema('name')), 5)); +expect_exception(static fn() => (new RustCSVReaderNative(',', '"', '\\', true, true, true))->nextColumns(schema(int_schema('id')), 0)); ?> --EXPECT-- Flow\Floe\Exception\ExtensionException: flow_php CSV separator must be exactly one byte @@ -28,3 +41,8 @@ Flow\Floe\Exception\ExtensionException: flow_php CSV batch size must be greater Flow\Floe\Exception\ExtensionException: flow_php CSV fold limit must be -1 or at least 0 Flow\Floe\Exception\ExtensionException: flow_php cannot fold html or xml candidates natively Flow\Floe\Exception\ExtensionException: flow_php cannot fold html or xml candidates natively +NULL +Flow\Floe\Exception\ExtensionException: flow_php cannot change the schema of a pending CSV batch +NULL +Flow\Floe\Exception\ExtensionException: flow_php cannot change the batch size of a pending CSV batch +Flow\Floe\Exception\ExtensionException: flow_php CSV batch size must be greater than 0 diff --git a/src/extension/flow-php-ext/tests/phpt/055_column_interfaces_skew.phpt b/src/extension/flow-php-ext/tests/phpt/055_column_interfaces_skew.phpt new file mode 100644 index 0000000000..fec7f9f69c --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/055_column_interfaces_skew.phpt @@ -0,0 +1,20 @@ +--TEST-- +flow_php registers the column interfaces reflection-identical to the library files +--SKIPIF-- + +--FILE-- + +--EXPECT-- +library reflected +identical diff --git a/src/extension/flow-php-ext/tests/phpt/056_native_constructors_refused.phpt b/src/extension/flow-php-ext/tests/phpt/056_native_constructors_refused.phpt new file mode 100644 index 0000000000..64e1cbccd2 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/056_native_constructors_refused.phpt @@ -0,0 +1,32 @@ +--TEST-- +native columns and builders come only from DefaultBackend; a column is not serializable, a Rows of them is +--SKIPIF-- + +--FILE-- + new NativeColumn()); +expect_exception(static fn() => new NativeColumnBuilder()); + +foreach ([NativeColumn::class, NativeColumnBuilder::class] as $class) { + echo outcome(static fn() => (new ReflectionClass($class))->newInstanceWithoutConstructor()), "\n"; +} + +$rows = native_rows(all_types_schema(), all_types_values()); + +echo get_class($rows->column('int')), "\n"; +echo outcome(static fn() => $rows->column('int')), "\n"; +echo comparable(unserialize(serialize($rows))->toArray()) === comparable($rows->toArray()) ? 'round trip' : 'FAIL', "\n"; +?> +--EXPECT-- +Flow\Floe\Exception\ExtensionException: Flow\ETL\Column\NativeColumn is built by DefaultBackend +Flow\Floe\Exception\ExtensionException: Flow\ETL\Column\NativeColumnBuilder is built by DefaultBackend +ReflectionException: Class Flow\ETL\Column\NativeColumn is an internal class marked as final that cannot be instantiated without invoking its constructor +ReflectionException: Class Flow\ETL\Column\NativeColumnBuilder is an internal class marked as final that cannot be instantiated without invoking its constructor +Flow\ETL\Column\NativeColumn +Exception: Serialization of 'Flow\ETL\Column\NativeColumn' is not allowed +round trip diff --git a/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt b/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt new file mode 100644 index 0000000000..05ad3c9e67 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt @@ -0,0 +1,47 @@ +--TEST-- +native columns encode byte-identical frames to PHP columns, after every Rows reshaping, and decode PHP frames +--SKIPIF-- + +--FILE-- + print( + $label . ': ' . (bin2hex($expected->encodeFrame()) === bin2hex($actual->encodeFrame()) ? 'identical' : 'DIFF') . "\n" +); +$projection = schema($schema->get('uuid'), $schema->get('int'), $schema->get('structure')); + +$frame('all types', $php, $native); +$frame('slice', $php->slice(3, 3), $native->slice(3, 3)); +$frame('gather', $php->gather([5, 0, 3, 3]), $native->gather([5, 0, 3, 3])); +$frame('concat', $php->concat($php->slice(1, 2)), $native->concat($native->slice(1, 2))); +$frame('project', $php->project($projection), $native->project($projection)); +$frame('withSchema', $php->withSchema(all_types_schema('UTC')), $native->withSchema(all_types_schema('UTC'))); +$frame('mixed', $php, $php->concat($native)->slice(0, $php->count())); + +$body = $php->encodeFrame(); +$decodedPhp = (new FrameDecoder())->decode($body, $schema, new PhpBackend()); +$decodedNative = (new FrameDecoder())->decode($body, $schema, new DefaultBackend()); +echo get_class($decodedNative->column('int')), "\n"; +echo comparable($decodedPhp->toArray()) === comparable($decodedNative->toArray()) ? 'decoded rows identical' : 'DIFF', "\n"; +?> +--EXPECT-- +all types: identical +slice: identical +gather: identical +concat: identical +project: identical +withSchema: identical +mixed: identical +Flow\ETL\Column\NativeColumn +decoded rows identical diff --git a/src/extension/flow-php-ext/tests/phpt/058_native_values_parity.phpt b/src/extension/flow-php-ext/tests/phpt/058_native_values_parity.phpt new file mode 100644 index 0000000000..4c4b07cdfd --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/058_native_values_parity.phpt @@ -0,0 +1,94 @@ +--TEST-- +native columns read every row as the PHP columns read it: at(), value(), Rows::values(), physicals(), values() +--SKIPIF-- + +--FILE-- +definitions()) as $name) { + $expected = $php->column((string) $name); + $actual = $native->column((string) $name); + + foreach (['physicals', 'values'] as $read) { + if (comparable($expected->{$read}()) !== comparable($actual->{$read}())) { + $differences[] = "{$name} {$read}()"; + } + } + + for ($i = 0; $i < $php->count(); $i++) { + foreach (['at', 'value', 'isNull'] as $read) { + if (comparable($expected->{$read}($i)) !== comparable($actual->{$read}($i))) { + $differences[] = "{$name} {$read}({$i})"; + } + } + } +} + +for ($i = 0; $i < $php->count(); $i++) { + if (comparable($php->values($i)) !== comparable($native->values($i))) { + $differences[] = "Rows::values({$i})"; + } +} + +echo $differences === [] ? 'all types identical' : implode("\n", $differences), "\n"; + +$observe = static fn(DateTimeInterface $value): array => [ + serialize($value), + $value->format('Y-m-d H:i:s.u T e P U Z'), + $value->modify('+1 month')->format('Y-m-d H:i:s.u T e'), + $value->modify('midnight')->format('Y-m-d H:i:s.u T e U'), + $value->setTime(1, 2, 3, 4)->format('Y-m-d H:i:s.u T e U'), + $value->add(new DateInterval('P1DT25H'))->format('Y-m-d H:i:s.u T e U'), +]; +$instants = []; + +foreach (['UTC', 'Z', 'Europe/Warsaw', 'America/New_York', 'Australia/Lord_Howe', '+00:00', '+02:00', '-05:30', 'CEST', 'EST'] as $timezone) { + foreach ([ + '1970-01-01 00:00:00.000000 UTC', + '1969-12-31 23:59:59.999999 UTC', + '1969-07-20 20:17:00.5 UTC', + '2026-03-29 00:59:59.999999 UTC', + '2026-03-29 01:00:00.000001 UTC', + '2026-10-25 00:30:00 UTC', + '2026-10-25 01:30:00 UTC', + '2038-01-19 03:14:08.000001 UTC', + '0001-01-01 00:00:00 UTC', + '9999-12-31 23:59:59.999999 UTC', + '-0044-03-15 12:00:00 UTC', + ] as $instant) { + $instants[] = ['at' => (new DateTimeImmutable($instant))->setTimezone(new DateTimeZone($timezone))]; + } +} + +$frame = php_rows(schema(datetime_schema('at')), $instants)->encodeFrame(); + +foreach (['UTC', 'Europe/Warsaw', '+05:30'] as $zone) { + $zoned = schema(datetime_schema('at', zone: $zone)); + $expected = array_map($observe, (new FrameDecoder())->decode($frame, $zoned, new PhpBackend())->column('at')->values()); + $actual = array_map($observe, (new FrameDecoder())->decode($frame, $zoned, new DefaultBackend())->column('at')->values()); + + echo "zone {$zone}: ", serialize($expected) === serialize($actual) ? 'identical' : 'DIFF', "\n"; +} + +foreach (native_rows(schema(time_schema('t')), [['t' => new DateInterval('PT1H')]])->column('t')->values() as $interval) { + var_dump($interval->days); +} +?> +--EXPECT-- +all types identical +zone UTC: identical +zone Europe/Warsaw: identical +zone +05:30: identical +bool(false) diff --git a/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt b/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt new file mode 100644 index 0000000000..5d1167d522 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt @@ -0,0 +1,99 @@ +--TEST-- +NativeColumnBuilder casts and refuses exactly as the PHP builder through append() and appendMany(), in every default zone +--SKIPIF-- + +--FILE-- + 1]]], + [list_schema('l', type_list(type_integer())), [[1 => 'x']]], [list_schema('l', type_list(type_positive_integer())), [['abc']]], + [list_schema('l', type_list(type_positive_integer())), [[-3]]], [int_schema('i'), ['1', 'x']], + [int_schema('id'), ['9223372036854775808']], [date_schema('d'), ['']], [datetime_schema('at'), ['now']], + [list_schema('l', type_list(type_string())), [['a', null]]], [list_schema('l', type_list(type_integer())), [5]], + [new ForeignTypeDefinition('a', new ThrowingType(new LogicException('stub type refuses everything'))), [[1, 2]]], + [datetime_schema('at'), ['+292278994-08-17T07:12:55Z']], + [int_schema('id'), ["\f5"]], [int_schema('id'), ["5\f"]], [float_schema('p'), ['-0']], +] as $case) { + $cases[] = $case; +} + +$build = static fn(object $backend, object $definition, array $values, bool $many): Closure => static function () use ($backend, $definition, $values, $many): array { + $builder = $backend->builder($definition); + + if ($many) { + $builder->appendMany($values); + } else { + foreach ($values as $value) { + $builder->append($value); + } + } + + return $builder->finish()->values(); +}; + +foreach (['UTC', 'Europe/Warsaw', 'America/Santiago'] as $timezone) { + ini_set('date.timezone', $timezone); + $identical = 0; + + foreach ($cases as [$definition, $values]) { + foreach ([false, true] as $many) { + $php = outcome($build(new PhpBackend(), $definition, $values, $many)); + $native = outcome($build(new DefaultBackend(), $definition, $values, $many)); + + if ($php === $native) { + $identical++; + } else { + echo ($many ? 'appendMany ' : 'append ') . $definition->type()->toString() . ' ' . json_encode($values) . "\n php: {$php}\n native: {$native}\n"; + } + } + } + + echo "date.timezone {$timezone}: {$identical} of " . (2 * count($cases)) . " identical\n"; +} +?> +--EXPECT-- +date.timezone UTC: 434 of 434 identical +date.timezone Europe/Warsaw: 434 of 434 identical +date.timezone America/Santiago: 434 of 434 identical diff --git a/src/extension/flow-php-ext/tests/phpt/060_native_decode_refusals.phpt b/src/extension/flow-php-ext/tests/phpt/060_native_decode_refusals.phpt new file mode 100644 index 0000000000..f45d9be370 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/060_native_decode_refusals.phpt @@ -0,0 +1,63 @@ +--TEST-- +DefaultBackend::decode() refuses every corrupt buffer set PhpBackend::decode() refuses, with its class and message +--SKIPIF-- + +--FILE-- + [int_schema('a'), [''], 1, 0], + 'short fixed buffer' => [int_schema('a'), ['', "\x01\x00"], 1, 0], + 'offsets not from 0' => [str_schema('a'), ['', "\x01\x00\x00\x00\x02\x00\x00\x00", 'ab'], 1, 0], + 'offsets not monotonic' => [str_schema('a'), ['', "\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00", 'ab'], 2, 0], + 'offsets past the data' => [str_schema('a'), ['', "\x00\x00\x00\x00\x03\x00\x00\x00", 'ab'], 1, 0], + 'short offsets' => [str_schema('a'), ['', "\x00\x00", ''], 1, 0], + 'map entries validity present' => [map_schema('a', type_map(type_string(), type_integer())), ['', "\x00\x00\x00\x00\x00\x00\x00\x00", "\x01", '', "\x00\x00\x00\x00", '', '', ''], 1, 0], + 'null count disagreeing with the bitmap' => [int_schema('a', nullable: true), ["\x01", str_repeat("\x00", 16)], 2, 0], + 'values shorter than the rows' => [int_schema('a', nullable: true), ['', ''], 9, 0], + 'short validity bitmap' => [int_schema('a', nullable: true), ["\x01", str_repeat("\x00", 72)], 9, 0], + 'null column with a wrong null count' => [null_schema('a'), [], 2, 1], + 'leftover buffers' => [int_schema('a'), ['', "\x01\x00\x00\x00\x00\x00\x00\x00", ''], 1, 0], + 'list element nulls' => [list_schema('a', type_list(type_integer())), ['', "\x00\x00\x00\x00\x01\x00\x00\x00", "\x00", str_repeat("\x00", 8)], 1, 0], + 'list offsets too short' => [list_schema('a', type_list(type_integer())), ['', "\x00\x00\x00\x00", '', ''], 1, 0], + 'map key nulls' => [map_schema('a', type_map(type_integer(), type_integer())), ['', "\x00\x00\x00\x00\x01\x00\x00\x00", '', "\x00", str_repeat("\x00", 8), '', str_repeat("\x00", 8)], 1, 0], + 'map value nulls' => [map_schema('a', type_map(type_integer(), type_list(type_integer()))), ['', "\x00\x00\x00\x00\x01\x00\x00\x00", '', '', str_repeat("\x00", 8), "\x00", "\x00\x00\x00\x00\x00\x00\x00\x00", '', ''], 1, 0], + 'nested list of a structure' => [structure_schema('a', type_structure(['l' => type_list(type_string())])), ['', '', "\x00\x00\x00\x00\x01\x00\x00\x00", "\x00", "\x00\x00\x00\x00\x00\x00\x00\x00", ''], 1, 0], + 'optional list element nulls pass' => [list_schema('a', type_list(type_optional(type_integer()))), ['', "\x00\x00\x00\x00\x01\x00\x00\x00", "\x00", str_repeat("\x00", 8)], 1, 0], + 'null list element passes' => [list_schema('a', type_list(type_null())), ['', "\x00\x00\x00\x00\x02\x00\x00\x00"], 1, 0], +]; + +foreach ($cases as $label => [$definition, $buffers, $count, $nullCount]) { + $php = outcome(static fn() => (new PhpBackend())->decode($definition, $buffers, $count, $nullCount)->values()); + $native = outcome(static fn() => (new DefaultBackend())->decode($definition, $buffers, $count, $nullCount)->values()); + + echo $label, ': ', $php === $native ? $native : "DIFF\n php: {$php}\n native: {$native}", "\n"; +} +?> +--EXPECT-- +too few buffers: Flow\ETL\Exception\InvalidArgumentException: Column buffers exhausted: the column needs more buffers than given +short fixed buffer: Flow\ETL\Exception\InvalidArgumentException: Int64 values buffer of 2 bytes, expected 8 for 1 rows +offsets not from 0: Flow\ETL\Exception\InvalidArgumentException: Utf8 offsets start at 1, not 0 +offsets not monotonic: Flow\ETL\Exception\InvalidArgumentException: Utf8 offsets are not monotonic: offset 1 is 2, offset 2 is 1 +offsets past the data: Flow\ETL\Exception\InvalidArgumentException: Utf8 data buffer of 2 bytes, the last offset is 3 +short offsets: Flow\ETL\Exception\InvalidArgumentException: Utf8 offsets buffer of 2 bytes, expected 8 for 1 rows +map entries validity present: Flow\ETL\Exception\InvalidArgumentException: Map entries validity must be omitted, got 1 bytes +null count disagreeing with the bitmap: Flow\ETL\Exception\InvalidArgumentException: Column null count 0 disagrees with its validity bitmap (1 nulls in 2 rows) +values shorter than the rows: Flow\ETL\Exception\InvalidArgumentException: Int64 values buffer of 0 bytes, expected 72 for 9 rows +short validity bitmap: Flow\ETL\Exception\InvalidArgumentException: Validity bitmap of 1 bytes is too short for 9 rows +null column with a wrong null count: Flow\ETL\Exception\InvalidArgumentException: Null column of 2 rows carries a null count of 1 +leftover buffers: Flow\ETL\Exception\InvalidArgumentException: Column "a": 1 buffers left after decoding +list element nulls: Flow\ETL\Exception\InvalidArgumentException: List child holds 1 nulls in a non-nullable integer +list offsets too short: Flow\ETL\Exception\InvalidArgumentException: List offsets buffer of 4 bytes, expected 8 for 1 rows +map key nulls: Flow\ETL\Exception\InvalidArgumentException: Map key child holds 1 nulls in a non-nullable integer +map value nulls: Flow\ETL\Exception\InvalidArgumentException: Map value child holds 1 nulls in a non-nullable list +nested list of a structure: Flow\ETL\Exception\InvalidArgumentException: List child holds 1 nulls in a non-nullable string +optional list element nulls pass: a:1:{i:0;a:1:{i:0;N;}} +null list element passes: a:1:{i:0;a:2:{i:0;N;i:1;N;}} diff --git a/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt b/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt new file mode 100644 index 0000000000..c56d48474a --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt @@ -0,0 +1,70 @@ +--TEST-- +native and PHP columns build into each other: appendFrom/appendTake, Rows::concat, Rows::of, adopt() both ways +--SKIPIF-- + +--FILE-- + print( + $label . ': ' . ($expected->encodeFrame() === $actual->encodeFrame() && comparable($expected->toArray()) === comparable($actual->toArray()) ? 'identical' : 'DIFF') . "\n" +); +$rebuilt = static function (Rows $from, object $backend, bool $take) use ($schema): Rows { + $columns = []; + + foreach ($schema->definitions() as $name => $definition) { + $builder = $backend->builder($definition); + + if ($take) { + $builder->appendTake($from->column((string) $name), [5, 0, 3, 3]); + } else { + foreach ([5, 0, 3, 3] as $i) { + $builder->appendFrom($from->column((string) $name), $i); + } + } + + $columns[$name] = $builder->finish(); + } + + return Rows::fromColumns($schema, $columns, 4); +}; + +$same('native appendTake of a PHP column', $php->gather([5, 0, 3, 3]), $rebuilt($php, new DefaultBackend(), true)); +$same('native appendFrom of a PHP column', $php->gather([5, 0, 3, 3]), $rebuilt($php, new DefaultBackend(), false)); +$same('PHP appendTake of a native column', $php->gather([5, 0, 3, 3]), $rebuilt($native, new PhpBackend(), true)); +$same('Rows::concat PHP + native', $php->concat($php), $php->concat($native)); +$same('Rows::concat native + PHP', $php->concat($php), $native->concat($php)); +$same('Rows::of over both', Rows::of($schema, $php->row(1), $php->row(4)), Rows::of($schema, $native->row(1), $php->row(4))); + +foreach ($schema->definitions() as $name => $definition) { + $phpColumn = $php->column((string) $name); + $nativeColumn = $native->column((string) $name); + $adopted = (new DefaultBackend())->adopt($definition, $phpColumn); + $empty = (new DefaultBackend())->adopt($definition, $phpColumn->slice(0, 0)); + $back = (new PhpBackend())->adopt($definition, $nativeColumn); + + if (!$adopted instanceof NativeColumn || $adopted->encode() !== $phpColumn->encode() || $empty->count() !== 0 + || $back instanceof NativeColumn || $back->encode() !== $phpColumn->encode() + || (new DefaultBackend())->adopt($definition, $nativeColumn) !== $nativeColumn) { + echo "adopt DIFF {$name}\n"; + } +} + +echo "adopt identical\n"; +?> +--EXPECT-- +native appendTake of a PHP column: identical +native appendFrom of a PHP column: identical +PHP appendTake of a native column: identical +Rows::concat PHP + native: identical +Rows::concat native + PHP: identical +Rows::of over both: identical +adopt identical diff --git a/src/extension/flow-php-ext/tests/phpt/062_native_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/062_native_no_leaks.phpt new file mode 100644 index 0000000000..f8fa55f9aa --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/062_native_no_leaks.phpt @@ -0,0 +1,48 @@ +--TEST-- +decode, value reads, take, encode and a refused appendMany leak neither PHP memory nor native allocations +--SKIPIF-- + +--FILE-- +encodeFrame(); +$backend = new DefaultBackend(); + +$cycle = static function () use ($schema, $frame, $backend): void { + $rows = (new FrameDecoder())->decode($frame, $schema, $backend); + + foreach ($rows->columns() as $column) { + $column->value(1); + $column->take([2, 0])->encode(); + } + + try { + $backend->builder($schema->get('int'))->appendMany([1, 'not an int']); + throw new LogicException('a refused value was accepted'); + } catch (Flow\ETL\Exception\SchemaMismatchException) { + } +}; + +for ($i = 0; $i < 10; $i++) { + $cycle(); +} +gc_collect_cycles(); +$baseline = memory_get_usage(false); +$baselineRust = $backend->allocatedBytes(); + +for ($i = 0; $i < 100; $i++) { + $cycle(); +} +gc_collect_cycles(); + +var_dump(memory_get_usage(false) <= $baseline); +var_dump($backend->allocatedBytes() === $baselineRust); +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/063_csv_next_columns_parity.phpt b/src/extension/flow-php-ext/tests/phpt/063_csv_next_columns_parity.phpt new file mode 100644 index 0000000000..077ced72ee --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/063_csv_next_columns_parity.phpt @@ -0,0 +1,78 @@ +--TEST-- +NativeCSVOpenSource::batches() yields the frames or refusals of PhpCSVOpenSource::batches(), through either backend +--SKIPIF-- + +--FILE-- + new StringSourceStream(path('memory://phpt.csv'), $raw); +$batches = static fn(object $open, Schema $schema, object $backend): string => outcome(static function () use ($open, $schema, $backend): array { + $frames = []; + + foreach ($open->batches($schema, 2, $backend) as $batch) { + foreach ($batch->columns() as $column) { + if ($backend instanceof PhpBackend && $column instanceof NativeColumn) { + return ['a NativeColumn survived PhpBackend']; + } + } + + $frames[] = bin2hex($batch->encodeFrame()); + } + + return $frames; +}); +$cases = []; + +foreach (csv_narrow_corpus() as $cell) { + $raw = "v\n\"" . str_replace('"', '""', $cell) . "\"\n"; + + foreach ([int_schema('v'), float_schema('v'), bool_schema('v'), datetime_schema('v'), date_schema('v'), uuid_schema('v'), json_schema('v'), str_schema('v', nullable: true)] as $definition) { + $cases[] = [$raw, schema($definition)]; + } +} + +$idName = schema(int_schema('id'), str_schema('name')); + +foreach ([ + ["id\n1\n", $idName], + ["id\n1\nx\n", $idName], + ["a,b\nx,y\n", schema(int_schema('b'), int_schema('a'))], + ["id,name\n1,a\n2,\n", $idName], + ["id,name,name\n1,a,b\n2,c,d\n", $idName], + ["id,name\n1\n2,b,extra\n", schema(int_schema('id'), str_schema('name', nullable: true))], + ["1,2\na,3\n", schema(str_schema('1'), int_schema('2'))], + ["id,name\n1,a\n2,b\n3,c\nx,d\n", $idName], + ["id\n", schema(int_schema('id'), str_schema('absent'))], +] as $case) { + $cases[] = $case; +} + +$identical = 0; + +foreach ($cases as [$raw, $schema]) { + $php = $batches(new PhpCSVOpenSource($stream($raw), new CSVDecoder(), new CSVLineReader('"', ',', '\\')), $schema, new PhpBackend()); + + foreach ([new DefaultBackend(), new PhpBackend()] as $backend) { + $native = $batches(new NativeCSVOpenSource($stream($raw), new RustCSVReaderNative(',', '"', '\\', true, true, true)), $schema, $backend); + + if ($native === $php) { + $identical++; + } else { + echo json_encode($raw), ' ', get_class($backend), "\n php: {$php}\n native: {$native}\n"; + } + } +} + +echo "{$identical} of " . (2 * count($cases)) . " identical\n"; +?> +--EXPECT-- +6274 of 6274 identical diff --git a/src/extension/flow-php-ext/tests/phpt/064_csv_next_columns_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/064_csv_next_columns_no_leaks.phpt new file mode 100644 index 0000000000..662e22b970 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/064_csv_next_columns_no_leaks.phpt @@ -0,0 +1,59 @@ +--TEST-- +RustCSVReaderNative::nextColumns() leaks neither PHP memory nor native allocations +--SKIPIF-- + +--FILE-- +feed($chunk); + $reader->nextColumns($schema, 2); + } + + $reader->finish(); + + while ($reader->nextColumns($schema, 2) !== null) { + } + + $refused = new RustCSVReaderNative(',', '"', '\\', true, true, true); + $refused->feed("name\nx\n"); + $refused->finish(); + + try { + $refused->nextColumns($refusing, 2); + throw new LogicException('a refused cell was accepted'); + } catch (Flow\ETL\Exception\SchemaMismatchException) { + } +}; + +for ($i = 0; $i < 10; $i++) { + $cycle(); +} +gc_collect_cycles(); +$baseline = memory_get_usage(false); +$baselineRust = (new DefaultBackend())->allocatedBytes(); + +for ($i = 0; $i < 1000; $i++) { + $cycle(); +} +gc_collect_cycles(); + +var_dump(memory_get_usage(false) <= $baseline); +var_dump((new DefaultBackend())->allocatedBytes() === $baselineRust); +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/065_type_plan_by_object.phpt b/src/extension/flow-php-ext/tests/phpt/065_type_plan_by_object.phpt new file mode 100644 index 0000000000..36b307f03b --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/065_type_plan_by_object.phpt @@ -0,0 +1,32 @@ +--TEST-- +a column's plan follows its Type object across the plan cache's eviction and a freed Type's reused handle +--SKIPIF-- + +--FILE-- +builder($definition); + $builder->append($value); + $column = $builder->finish(); + + if ($column->type()->normalize() !== $definition->type()->normalize() || $column->value(0) !== $value) { + $wrong[] = $i; + } + + unset($definition, $builder, $column); +} + +echo $wrong === [] ? 'every column kept its type' : 'wrong at ' . implode(', ', array_slice($wrong, 0, 10)), "\n"; +?> +--EXPECT-- +every column kept its type diff --git a/src/extension/flow-php-ext/tests/phpt/066_iso_datetime_fast_path_parity.phpt b/src/extension/flow-php-ext/tests/phpt/066_iso_datetime_fast_path_parity.phpt new file mode 100644 index 0000000000..8543cfcdc5 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/066_iso_datetime_fast_path_parity.phpt @@ -0,0 +1,133 @@ +--TEST-- +ISO date-times with a Z or ±HH:MM suffix become the micros DateTimeType::cast() yields, through append() and nextColumns() +--SKIPIF-- + +--FILE-- + str_pad((string) $value, 2, '0', STR_PAD_LEFT); +$leap = static fn(int $year): bool => ($year % 4 === 0 && $year % 100 !== 0) || $year % 400 === 0; +$year = static fn(): int => match (mt_rand(0, 3)) { + 0 => mt_rand(1, 1969), + 1 => mt_rand(1970, 2038), + 2 => mt_rand(2039, 9999), + default => [1, 4, 1900, 1968, 1969, 1970, 2000, 2024, 2038, 2100, 2400, 9996, 9999][mt_rand(0, 12)], +}; +$fraction = static fn(): string => ($digits = mt_rand(0, 6)) === 0 + ? '' + : '.' . implode('', array_map(static fn(): int => mt_rand(0, 9), range(1, $digits))); +$suffix = static function () use ($two): string { + if (mt_rand(0, 3) === 0) { + return 'Z'; + } + + $minutes = mt_rand(-12 * 60, 14 * 60); + $minutes -= mt_rand(0, 1) === 0 ? $minutes % 15 : 0; + + return ($minutes < 0 ? '-' : '+') . $two(intdiv(abs($minutes), 60)) . ':' . $two(abs($minutes) % 60); +}; + +$strings = []; + +for ($i = 0; $i < 3000; $i++) { + $y = $year(); + $m = mt_rand(1, 12); + $days = match ($m) { + 2 => $leap($y) ? 29 : 28, + 4, 6, 9, 11 => 30, + default => 31, + }; + $d = match (mt_rand(0, 3)) { + 0 => $days, + 1 => 1, + default => mt_rand(1, $days), + }; + + if (mt_rand(0, 9) === 0) { + [$y, $m, $d] = [[4, 2000, 2024, 2400, 9996][mt_rand(0, 4)], 2, 29]; + } + + $strings[] = sprintf( + '%s-%s-%sT%s:%s:%s%s%s', + str_pad((string) $y, 4, '0', STR_PAD_LEFT), + $two($m), + $two($d), + $two(mt_rand(0, 23)), + $two(mt_rand(0, 59)), + $two(mt_rand(0, 59)), + $fraction(), + $suffix(), + ); +} + +$nearMisses = [ + '2026-01-02T03:04:05', '2026-01-02 03:04:05Z', '2026-01-02t03:04:05Z', '2026-01-02T03:04:05z', '2026-01-02T03:04Z', + '2026-01-02T03:04:05.1234567Z', '2026-01-02T03:04:05.123456789+01:00', '2026-01-02T03:04:05,5Z', '2026-01-02T03:04:05.Z', + '2026-01-02T03:04:05+01', '2026-01-02T03:04:05+0100', '2026-01-02T03:04:05+24:00', '2026-01-02T03:04:05+01:60', + '2026-01-02T24:00:00Z', '2026-12-31T23:59:60Z', '0000-01-01T00:00:00Z', '+2026-01-02T03:04:05Z', '-2026-01-02T03:04:05Z', + '12026-01-02T03:04:05Z', '2023-02-29T00:00:00Z', '2026-04-31T00:00:00Z', '2026-13-01T00:00:00Z', "2026-01-02T03:04:05Z\n", + ' 2026-01-02T03:04:05Z', '2026-01-02T03:04:05Z ', '2026-01-02T03:04:05ZZ', '2026-01-02T03:04:05+01:00Z', +]; + +$physicals = static function (object $backend, object $definition, array $values): array { + $builder = $backend->builder($definition); + $builder->appendMany($values); + + return $builder->finish()->physicals(); +}; +$csv = static function (object $definition, array $values): array { + $reader = new RustCSVReaderNative(',', '"', '', true, true, true); + $reader->feed("v\n" . implode("\n", $values) . "\n"); + $reader->finish(); + + return $reader->nextColumns(schema($definition), count($values) + 1)->column('v')->physicals(); +}; + +foreach (['UTC', 'Europe/Warsaw', 'Pacific/Kiritimati'] as $zone) { + $definition = datetime_schema('v', zone: $zone); + $expected = $physicals(new PhpBackend(), $definition, $strings); + $appended = $physicals(new DefaultBackend(), $definition, $strings); + $read = $csv($definition, $strings); + $differ = static fn(array $actual): array => array_keys(array_filter( + $expected, + static fn(int $micros, int $i): bool => $actual[$i] !== $micros, + ARRAY_FILTER_USE_BOTH, + )); + + foreach (['append()' => $appended, 'nextColumns()' => $read] as $lane => $actual) { + $wrong = $differ($actual); + echo "{$zone} {$lane}: ", $wrong === [] + ? count($strings) . ' strings, identical micros' + : implode("\n", array_map(static fn(int $i): string => "{$strings[$i]} php {$expected[$i]} native {$actual[$i]}", array_slice($wrong, 0, 10))), "\n"; + } + + $identical = 0; + + foreach ($nearMisses as $value) { + $php = outcome(static fn(): array => $physicals(new PhpBackend(), $definition, [$value])); + $native = outcome(static fn(): array => $physicals(new DefaultBackend(), $definition, [$value])); + + $php === $native ? $identical++ : print(json_encode($value) . "\n php: {$php}\n native: {$native}\n"); + } + + echo "{$zone} near misses: {$identical} of " . count($nearMisses) . " identical\n"; +} +?> +--EXPECT-- +UTC append(): 3000 strings, identical micros +UTC nextColumns(): 3000 strings, identical micros +UTC near misses: 27 of 27 identical +Europe/Warsaw append(): 3000 strings, identical micros +Europe/Warsaw nextColumns(): 3000 strings, identical micros +Europe/Warsaw near misses: 27 of 27 identical +Pacific/Kiritimati append(): 3000 strings, identical micros +Pacific/Kiritimati nextColumns(): 3000 strings, identical micros +Pacific/Kiritimati near misses: 27 of 27 identical diff --git a/src/extension/flow-php-ext/tests/phpt/bootstrap.php b/src/extension/flow-php-ext/tests/phpt/bootstrap.php index 58efa5b763..25ed7924b8 100644 --- a/src/extension/flow-php-ext/tests/phpt/bootstrap.php +++ b/src/extension/flow-php-ext/tests/phpt/bootstrap.php @@ -4,31 +4,300 @@ require __DIR__ . '/../../../../../vendor/autoload.php'; -use Flow\ETL\Row; +use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; +use Flow\ETL\Schema; +use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; + +use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\enum_schema; +use function Flow\ETL\DSL\float_schema; +use function Flow\ETL\DSL\html_schema; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; +use function Flow\ETL\DSL\null_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; +use function Flow\ETL\DSL\time_schema; +use function Flow\ETL\DSL\time_zone_schema; +use function Flow\ETL\DSL\uuid_schema; +use function Flow\ETL\DSL\xml_schema; +use function Flow\Types\DSL\structure_element; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_optional; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; /** - * Byte-identical comparison against the pure-PHP decoder on fresh objects. + * One column per Definition (html only where \Dom\HTMLDocument exists). + */ +function all_types_schema(string $zone = 'Europe/Warsaw'): Schema +{ + return schema( + int_schema('int'), + str_schema('string', nullable: true), + float_schema('float'), + bool_schema('bool'), + datetime_schema('datetime', zone: $zone), + date_schema('date'), + time_schema('time'), + uuid_schema('uuid'), + json_schema('json'), + enum_schema('enum', BasicEnum::class), + time_zone_schema('time_zone'), + xml_schema('xml'), + list_schema('list', type_list(type_optional(type_integer()))), + map_schema('map', type_map(type_string(), type_integer())), + structure_schema('structure', type_structure([ + 'a' => type_integer(), + 'b' => structure_element('b', type_optional(type_string()), true), + ])), + null_schema('null'), + ...class_exists('\Dom\HTMLDocument') ? [html_schema('html')] : [], + ); +} + +/** + * Six rows: bytes that are not UTF-8, a pre-1970 datetime with microseconds, a DST pair, a negative time. * - * @param list $expected - * @param list $actual + * @return list> */ -function assert_rows_identical(array $expected, array $actual): void +function all_types_values(): array { - if (count($expected) !== count($actual)) { - echo 'FAIL: row count ', count($expected), ' !== ', count($actual), "\n"; + $negative = (new DateTimeImmutable('2024-01-01 01:02:03'))->diff(new DateTimeImmutable('2024-01-01')); + $rows = [ + [ + 'int' => 1, + 'string' => "a\xFFb", + 'float' => 1.5, + 'bool' => true, + 'datetime' => '1969-07-20T20:17:40.123456Z', + 'date' => '1969-12-29', + 'time' => new DateInterval('PT1H2M3S'), + 'uuid' => '6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f', + 'json' => '{"a":1}', + 'enum' => BasicEnum::one, + 'time_zone' => new DateTimeZone('Europe/Warsaw'), + 'xml' => '1', + 'list' => [1, null, 3], + 'map' => ['a' => 1], + 'structure' => ['a' => 1, 'b' => 'x'], + 'null' => null, + ], + [ + 'int' => -2, + 'string' => null, + 'float' => -0.0, + 'bool' => false, + 'datetime' => '2024-10-27T00:30:00Z', + 'date' => '2024-02-29', + 'time' => $negative, + 'uuid' => '00000000-0000-0000-0000-000000000000', + 'json' => '[1,2]', + 'enum' => BasicEnum::two, + 'time_zone' => new DateTimeZone('UTC'), + 'xml' => '', + 'list' => [], + 'map' => [], + 'structure' => ['a' => 2], + 'null' => null, + ], + [ + 'int' => PHP_INT_MAX, + 'string' => '', + 'float' => 1e300, + 'bool' => true, + 'datetime' => '2024-10-27T01:30:00Z', + 'date' => '2000-01-01', + 'time' => new DateInterval('PT0S'), + 'uuid' => 'ffffffff-ffff-ffff-ffff-ffffffffffff', + 'json' => '{}', + 'enum' => BasicEnum::three, + 'time_zone' => new DateTimeZone('America/New_York'), + 'xml' => 't', + 'list' => [null], + 'map' => ['b' => 2, 'c' => 3], + 'structure' => ['a' => 3, 'b' => null], + 'null' => null, + ], + [ + 'int' => PHP_INT_MIN, + 'string' => 'zażółć', + 'float' => 0.1, + 'bool' => false, + 'datetime' => '1970-01-01T00:00:00Z', + 'date' => '1970-01-01', + 'time' => new DateInterval('PT49H'), + 'uuid' => '6c2f1d4e-8b3a-4c5d-9e6f-0a1b2c3d4e5f', + 'json' => '[true]', + 'enum' => BasicEnum::one, + 'time_zone' => new DateTimeZone('Europe/Warsaw'), + 'xml' => '', + 'list' => [4], + 'map' => ['a' => 4], + 'structure' => ['a' => 4, 'b' => 'y'], + 'null' => null, + ], + [ + 'int' => 0, + 'string' => 'e', + 'float' => 2.0, + 'bool' => true, + 'datetime' => '2038-01-19T03:14:08.000001Z', + 'date' => '1900-03-01', + 'time' => new DateInterval('PT59M59S'), + 'uuid' => '12345678-1234-1234-1234-123456789abc', + 'json' => '{"b":[1,{"c":null}]}', + 'enum' => BasicEnum::two, + 'time_zone' => new DateTimeZone('Asia/Tokyo'), + 'xml' => '5', + 'list' => [5, 6], + 'map' => ['z' => 0], + 'structure' => ['a' => 5], + 'null' => null, + ], + [ + 'int' => 7, + 'string' => 'last', + 'float' => -3.25, + 'bool' => false, + 'datetime' => '1900-01-01T12:00:00.5Z', + 'date' => '2100-12-31', + 'time' => new DateInterval('PT1S'), + 'uuid' => 'abcdefab-cdef-abcd-efab-cdefabcdefab', + 'json' => '[]', + 'enum' => BasicEnum::three, + 'time_zone' => new DateTimeZone('UTC'), + 'xml' => '', + 'list' => [7, null], + 'map' => ['q' => 7], + 'structure' => ['a' => 7, 'b' => 'z'], + 'null' => null, + ], + ]; - return; + if (class_exists('\\Dom\\HTMLDocument')) { + foreach ($rows as $index => $row) { + $rows[$index] = $row + ['html' => '

      html

      ']; + } } - foreach ($expected as $i => $row) { - if (serialize($row->values()) !== serialize($actual[$i]->values())) { - echo "FAIL: row {$i} differs from the PHP decoder output\n"; + return $rows; +} + +/** + * @param list> $values + */ +function php_rows(Schema $schema, array $values): Rows +{ + return (new RowsBuilder($schema, new PhpBackend())) + ->appendRows($values) + ->finish(); +} + +/** + * @param list> $values + */ +function native_rows(Schema $schema, array $values): Rows +{ + return (new RowsBuilder($schema, new DefaultBackend())) + ->appendRows($values) + ->finish(); +} + +/** + * `serialize()` with DOM values, which it refuses, replaced by their class and markup. + */ +function comparable(mixed $value): string +{ + $plain = static function (mixed $value) use (&$plain): mixed { + if (is_array($value)) { + return array_map($plain, $value); + } - return; + if ($value instanceof DOMDocument) { + return [$value::class, $value->saveXML()]; } + + if ($value instanceof DOMNode) { + return [$value::class, $value->ownerDocument?->saveXML($value)]; + } + + if (!is_object($value) || !str_starts_with($value::class, 'Dom\\')) { + return $value; + } + + // @mago-expect analysis:unavailable-method,mixed-method-access,ambiguous-object-property-access + return [ + $value::class, + $value instanceof Dom\HTMLDocument ? $value->saveHtml() : $value->ownerDocument->saveHtml($value), + ]; + }; + + return serialize($plain($value)); +} + +/** + * `comparable()` of the result, or `class: message <- previous class: message` of what it threw. + */ +function outcome(callable $fn): string +{ + try { + return comparable($fn()); + } catch (Throwable $e) { + $previous = $e->getPrevious(); + + return ( + get_class($e) + . ': ' + . $e->getMessage() + . ($previous === null ? '' : ' <- ' . get_class($previous) . ': ' . $previous->getMessage()) + ); + } +} + +function assert_same_outcome(callable $php, callable $native): void +{ + $expected = outcome($php); + $actual = outcome($native); + + echo $expected === $actual ? "identical\n" : "php: {$expected}\nnative: {$actual}\n"; +} + +/** + * JSON of the three column interfaces as reflection sees them: methods, parameters, types, variadics. + */ +function interfaces_reflection(): string +{ + $interfaces = []; + + foreach (['Backend', 'Column', 'ColumnBuilder'] as $name) { + $class = new ReflectionClass('Flow\\ETL\\Column\\' . $name); + $interfaces[$name] = [ + $class->isInterface(), + array_map(static fn(ReflectionMethod $method): array => [ + $method->getName(), + (string) $method->getReturnType(), + array_map(static fn(ReflectionParameter $parameter): array => [ + $parameter->getName(), + (string) $parameter->getType(), + $parameter->isVariadic(), + $parameter->isPassedByReference(), + ], $method->getParameters()), + ], $class->getMethods()), + ]; } - echo "identical\n"; + return (string) json_encode($interfaces); } function expect_exception(callable $fn): void @@ -42,7 +311,7 @@ function expect_exception(callable $fn): void } /** - * The PHP CSV path - CSVLineReader + CSVDecoder::decode() - as `[headers, list of RawRowValues::$values]`. + * The PHP CSV path - CSVLineReader + CSVDecoder::decode() - as `[headers, list of array::$values]`. * * @return array{list, list>} */ @@ -69,7 +338,7 @@ function csv_php_rows( new Flow\Filesystem\Stream\StringSourceStream(Flow\Filesystem\DSL\path('memory://phpt.csv'), $raw), ) as $line) { foreach ($decoder->decode([$line]) as $values) { - $rows[] = $values->values; + $rows[] = $values; } } @@ -77,7 +346,7 @@ function csv_php_rows( } /** - * RustCSVReaderNative fed `$raw` in `$chunk`-byte pieces, as `[headers, list of RawRowValues::$values]`. + * RustCSVReaderNative fed `$raw` in `$chunk`-byte pieces, as `[headers, list of array::$values]`. * * @param positive-int $chunk * @@ -105,7 +374,7 @@ function csv_native_rows( $drain = static function () use ($reader, &$rows): void { while (($batch = $reader->next(3)) !== []) { foreach ($batch as $values) { - $rows[] = $values->values; + $rows[] = $values; } } }; @@ -288,6 +557,24 @@ function csv_narrow_corpus(): array '12345678', '00000000', '2024-01-01 25:00', + '1969-12-31T23:59:59.5Z', + '2024-02-29T12:00:00+14:00', + '2024-02-29T12:00:00-12:00', + '2026-01-31T00:00:00+23:59', + '9999-12-31T23:59:59.999999-23:59', + '0001-01-01T00:00:00+23:59', + '2038-01-19T03:14:08Z', + '2026-01-02T03:04:05-00:00', + '2026-01-02t03:04:05Z', + '2026-01-02T03:04:05z', + '2026-01-02T03:04:05,5Z', + '2026-01-02T03:04:05+0100', + '2026-01-02T03:04:05.Z', + '2023-02-29T00:00:00Z', + '0000-01-01T00:00:00Z', + '2026-01-02T03:04:05+24:00', + '2026-01-02T03:04:05+01:60', + '2026-01-02T03:04:05.1234567+01:00', ]; mt_srand(46); From 97c7c7063cb0914d73fd57e840e44b71278ecf24 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Tue, 29 Sep 2026 12:58:20 +0200 Subject: [PATCH 06/21] feat(flow-php/etl): every consumer works on columns, Row removed - ScalarFunction evaluates a whole batch into one Column - sort, join, group-by, window, constraints and aggregates on columns - uuid/json/date-time values compare by value; one sort order - spilling steps stop at a process-wide memory limit - group-by and window stay in memory under the limit - BucketingProcessor and BucketingStrategy removed --- .nix/blackfire/.gitignore | 1 + .nix/blackfire/blackfire.env.dist | 2 + benchmarks/src/Datasets/SellersDataset.php | 5 +- benchmarks/src/Datasets/TextDataset.php | 9 +- benchmarks/src/Pipeline/InMemoryOrders.php | 10 +- .../Pipeline/PipelineCostScenariosTest.php | 2 +- .../Unit/Pipeline/PipelineScenarioTest.php | 9 +- .../Tests/Unit/Pipeline/StageScenarioTest.php | 2 +- .../Unit/Window/WindowPartitioningTest.php | 11 +- bootstrap.php | 1 - .../components/core/building-blocks.md | 5 +- documentation/components/core/constraints.md | 25 +- .../components/core/data-retrieval.md | 2 +- .../components/core/error-handling.md | 29 +- documentation/components/core/filter.md | 60 +- documentation/components/core/group-by.md | 14 +- documentation/components/core/join.md | 16 +- documentation/components/core/sort.md | 57 +- documentation/introduction.md | 2 +- documentation/upgrading.md | 149 ++++ shell.nix | 4 + .../Adapter/Avro/FlixTech/AvroExtractor.php | 2 +- .../Tests/Integration/ChartJSLoaderTest.php | 4 +- .../Tests/Integration/Output/pie_chart.html | 2 +- .../Tests/Integration/CSVExtractorTest.php | 49 +- .../CSVExtractorTypedColumnsTest.php | 12 +- .../Tests/Unit/DbalQueryExtractorTest.php | 4 +- .../Excel/Function/IsValidExcelSheetName.php | 14 +- .../Tests/Integration/ExcelExtractorTest.php | 43 +- .../ExcelExtractorTypedColumnsTest.php | 5 +- .../Function/IsValidExcelSheetNameTest.php | 17 +- .../Integration/GoogleSheetExtractorTest.php | 2 +- .../GoogleSheetExtractorTypedColumnsTest.php | 8 +- .../Tests/Unit/GoogleSheetExtractorTest.php | 24 +- .../PsrHttpClientDynamicExtractorTest.php | 16 +- ...srHttpClientExtractorBatchContractTest.php | 6 +- .../PsrHttpClientPaginatedExtractorTest.php | 6 +- .../PsrHttpClientStaticExtractorTest.php | 8 +- .../JSONMachine/JsonExtractorTest.php | 16 +- .../JsonExtractorTypedColumnsTest.php | 12 +- .../JSONMachine/JsonLinesExtractorTest.php | 16 +- .../JsonLinesExtractorTypedColumnsTest.php | 4 +- .../ConvertedTypeOnlyColumnsTest.php | 15 +- .../Integration/ParquetExtractorTest.php | 6 +- .../Parquet/Tests/Integration/ParquetTest.php | 36 +- .../Tests/Unit/ParquetExtractorTest.php | 8 +- ...stgreSqlCursorExtractorIntegrationTest.php | 2 +- ...stgreSqlKeySetExtractorIntegrationTest.php | 2 +- ...SqlLimitOffsetExtractorIntegrationTest.php | 2 +- .../Unit/PostgreSqlCursorExtractorTest.php | 10 +- .../Unit/PostgreSqlKeySetExtractorTest.php | 8 +- .../PostgreSqlLimitOffsetExtractorTest.php | 8 +- .../TextExtractorTypedColumnsTest.php | 8 +- .../XMLExtractorTypedColumnsTest.php | 9 +- .../Integration/XMLParserExtractorTest.php | 165 +++-- .../Integration/XMLReaderExtractorTest.php | 16 +- .../Tests/Integration/SFTPDataFrameTest.php | 21 +- .../etl/src/Flow/Calculator/RunningSum.php | 58 +- .../etl/src/Flow/ETL/Bucketing/Bucket.php | 21 - .../src/Flow/ETL/Bucketing/BucketShape.php | 14 - .../Flow/ETL/Bucketing/BucketingStrategy.php | 21 - .../src/Flow/ETL/Bucketing/HashBucketing.php | 32 +- .../src/Flow/ETL/Bucketing/KeyGrouping.php | 31 +- .../etl/src/Flow/ETL/Bucketing/KeyValues.php | 29 +- .../src/Flow/ETL/Bucketing/NativeHasher.php | 13 +- .../Flow/ETL/Bucketing/SortedRunBucketing.php | 65 -- .../ETL/Bucketing/Storage/SpillingBuckets.php | 161 +++++ .../etl/src/Flow/ETL/Cache/CacheIndex.php | 15 +- .../src/Flow/ETL/Column/ComparableValues.php | 79 +++ .../ETL/Column/Php/CastingColumnBuilder.php | 23 + .../src/Flow/ETL/Column/Php/ListColumn.php | 14 +- .../etl/src/Flow/ETL/Column/Php/MapColumn.php | 15 +- .../src/Flow/ETL/Column/Php/PhysicalFor.php | 78 +++ .../src/Flow/ETL/Column/Php/ValueColumn.php | 108 +++ .../etl/src/Flow/ETL/Column/PhpBackend.php | 5 + .../Config/Grouping/HashGroupByBuilder.php | 24 +- .../ETL/Config/Grouping/HashGroupByConfig.php | 2 + .../Flow/ETL/Config/Join/HashJoinBuilder.php | 25 +- .../Flow/ETL/Config/Join/HashJoinConfig.php | 2 + .../etl/src/Flow/ETL/Config/MemoryLimit.php | 39 ++ .../Repartition/HashRepartitionBuilder.php | 24 +- .../Repartition/HashRepartitionConfig.php | 2 + .../ETL/Config/Sort/ExternalSortBuilder.php | 20 +- .../ETL/Config/Sort/ExternalSortConfig.php | 5 +- src/core/etl/src/Flow/ETL/Constraint.php | 7 +- .../ETL/Constraint/SortedByConstraint.php | 108 +-- .../Flow/ETL/Constraint/UniqueConstraint.php | 37 +- src/core/etl/src/Flow/ETL/DSL/functions.php | 39 +- src/core/etl/src/Flow/ETL/DataFrame.php | 8 +- .../Flow/ETL/Dataset/Memory/BoundedRead.php | 59 ++ .../Flow/ETL/Dataset/Memory/MemoryBudget.php | 36 + .../Flow/ETL/Dataset/Statistics/Column.php | 205 ++++-- .../Flow/ETL/Dataset/Statistics/Columns.php | 10 +- .../ETL/Exception/ColumnMismatchException.php | 11 + .../ETL/Exception/EvaluationException.php | 30 + src/core/etl/src/Flow/ETL/Executor.php | 24 +- .../etl/src/Flow/ETL/Executor/Segment.php | 2 +- .../Flow/ETL/Executor/StatisticsCollector.php | 12 +- .../Flow/ETL/Extractor/BatchByExtractor.php | 75 +- .../src/Flow/ETL/Extractor/BatchExtractor.php | 4 +- .../ETL/Extractor/CollectingExtractor.php | 2 +- .../src/Flow/ETL/Extractor/FeedExtractor.php | 2 +- .../ETL/Filesystem/ScalarFunctionFilter.php | 13 +- .../Flow/ETL/Formatter/ASCII/ASCIIBody.php | 7 +- .../etl/src/Flow/ETL/Formatter/ASCII/Body.php | 36 +- .../Flow/ETL/Function/AggregatingFunction.php | 15 +- src/core/etl/src/Flow/ETL/Function/All.php | 60 +- src/core/etl/src/Flow/ETL/Function/Any.php | 60 +- src/core/etl/src/Flow/ETL/Function/Append.php | 38 +- .../etl/src/Flow/ETL/Function/ArrayExpand.php | 42 +- .../etl/src/Flow/ETL/Function/ArrayFilter.php | 34 +- .../etl/src/Flow/ETL/Function/ArrayGet.php | 40 +- .../Flow/ETL/Function/ArrayGetCollection.php | 119 ++-- .../etl/src/Flow/ETL/Function/ArrayKeep.php | 34 +- .../src/Flow/ETL/Function/ArrayKeyRename.php | 26 +- .../etl/src/Flow/ETL/Function/ArrayKeys.php | 29 +- .../ETL/Function/ArrayKeysStyleConvert.php | 70 +- .../etl/src/Flow/ETL/Function/ArrayMerge.php | 33 +- .../ETL/Function/ArrayMergeCollection.php | 45 +- .../src/Flow/ETL/Function/ArrayPathExists.php | 48 +- .../src/Flow/ETL/Function/ArrayReverse.php | 29 +- .../etl/src/Flow/ETL/Function/ArraySort.php | 42 +- .../etl/src/Flow/ETL/Function/ArrayUnpack.php | 28 +- .../etl/src/Flow/ETL/Function/ArrayValues.php | 29 +- src/core/etl/src/Flow/ETL/Function/Ascii.php | 26 +- .../etl/src/Flow/ETL/Function/Average.php | 60 +- .../etl/src/Flow/ETL/Function/Between.php | 44 +- .../src/Flow/ETL/Function/BinaryLength.php | 26 +- .../src/Flow/ETL/Function/CallUserFunc.php | 53 +- .../etl/src/Flow/ETL/Function/Capitalize.php | 35 +- src/core/etl/src/Flow/ETL/Function/Cast.php | 34 +- src/core/etl/src/Flow/ETL/Function/Chunk.php | 49 +- .../etl/src/Flow/ETL/Function/Coalesce.php | 39 +- .../src/Flow/ETL/Function/CodePointLength.php | 26 +- .../Flow/ETL/Function/CollapseWhitespace.php | 26 +- .../etl/src/Flow/ETL/Function/Collect.php | 24 +- .../src/Flow/ETL/Function/CollectUnique.php | 34 +- .../etl/src/Flow/ETL/Function/Combine.php | 75 +- src/core/etl/src/Flow/ETL/Function/Concat.php | 39 +- .../Flow/ETL/Function/ConcatWithSeparator.php | 59 +- .../etl/src/Flow/ETL/Function/Contains.php | 40 +- src/core/etl/src/Flow/ETL/Function/Count.php | 27 +- .../ETL/Function/DOMElementAttributeValue.php | 75 +- .../Function/DOMElementAttributesCount.php | 26 +- .../ETL/Function/DOMElementNamespaceValue.php | 32 +- .../ETL/Function/DOMElementNextSibling.php | 46 +- .../Flow/ETL/Function/DOMElementParent.php | 43 +- .../Function/DOMElementPreviousSibling.php | 46 +- .../src/Flow/ETL/Function/DOMElementValue.php | 48 +- .../src/Flow/ETL/Function/DateTimeFormat.php | 30 +- .../etl/src/Flow/ETL/Function/DenseRank.php | 7 +- src/core/etl/src/Flow/ETL/Function/Divide.php | 42 +- .../etl/src/Flow/ETL/Function/EndsWith.php | 32 +- .../etl/src/Flow/ETL/Function/EnsureEnd.php | 38 +- .../etl/src/Flow/ETL/Function/EnsureStart.php | 38 +- .../etl/src/Flow/ETL/Function/EnumName.php | 27 +- .../etl/src/Flow/ETL/Function/EnumValue.php | 29 +- src/core/etl/src/Flow/ETL/Function/Equals.php | 70 +- .../ETL/Function/Evaluation/ResultColumn.php | 161 +++++ .../ETL/Function/Evaluation/ReturnTypes.php | 42 ++ .../ETL/Function/Evaluation/Selection.php | 52 ++ .../Evaluation/TolerantEvaluation.php | 81 +++ src/core/etl/src/Flow/ETL/Function/Exists.php | 38 +- src/core/etl/src/Flow/ETL/Function/First.php | 27 +- .../etl/src/Flow/ETL/Function/GreaterThan.php | 60 +- .../Flow/ETL/Function/GreaterThanEqual.php | 60 +- .../etl/src/Flow/ETL/Function/Greatest.php | 34 +- .../Flow/ETL/Function/HTMLQuerySelector.php | 39 +- .../ETL/Function/HTMLQuerySelectorAll.php | 65 +- src/core/etl/src/Flow/ETL/Function/Hash.php | 39 +- .../etl/src/Flow/ETL/Function/IndexOf.php | 47 +- .../etl/src/Flow/ETL/Function/IndexOfLast.php | 47 +- .../etl/src/Flow/ETL/Function/IsEmpty.php | 28 +- src/core/etl/src/Flow/ETL/Function/IsIn.php | 103 ++- .../etl/src/Flow/ETL/Function/IsNotNull.php | 22 +- .../src/Flow/ETL/Function/IsNotNumeric.php | 29 +- src/core/etl/src/Flow/ETL/Function/IsNull.php | 22 +- .../etl/src/Flow/ETL/Function/IsNumeric.php | 29 +- src/core/etl/src/Flow/ETL/Function/IsType.php | 34 +- src/core/etl/src/Flow/ETL/Function/IsUtf8.php | 28 +- .../etl/src/Flow/ETL/Function/JsonDecode.php | 77 +- .../etl/src/Flow/ETL/Function/JsonEncode.php | 59 +- src/core/etl/src/Flow/ETL/Function/Last.php | 29 +- src/core/etl/src/Flow/ETL/Function/Least.php | 34 +- .../etl/src/Flow/ETL/Function/LessThan.php | 60 +- .../src/Flow/ETL/Function/LessThanEqual.php | 60 +- .../etl/src/Flow/ETL/Function/ListSelect.php | 52 +- .../etl/src/Flow/ETL/Function/Literal.php | 29 +- .../etl/src/Flow/ETL/Function/MatchCases.php | 70 +- .../Function/MatchCases/MatchCondition.php | 37 +- src/core/etl/src/Flow/ETL/Function/Max.php | 49 +- src/core/etl/src/Flow/ETL/Function/Min.php | 49 +- src/core/etl/src/Flow/ETL/Function/Minus.php | 54 +- src/core/etl/src/Flow/ETL/Function/Mod.php | 38 +- .../src/Flow/ETL/Function/ModifyDateTime.php | 38 +- .../etl/src/Flow/ETL/Function/Multiply.php | 54 +- src/core/etl/src/Flow/ETL/Function/Not.php | 17 +- .../etl/src/Flow/ETL/Function/NotEquals.php | 17 +- .../etl/src/Flow/ETL/Function/NotSame.php | 37 +- src/core/etl/src/Flow/ETL/Function/Now.php | 26 +- .../src/Flow/ETL/Function/NumberFormat.php | 41 +- src/core/etl/src/Flow/ETL/Function/OnEach.php | 106 ++- .../etl/src/Flow/ETL/Function/Optional.php | 20 +- .../etl/src/Flow/ETL/Function/Parameter.php | 398 ++++++----- src/core/etl/src/Flow/ETL/Function/Plus.php | 54 +- src/core/etl/src/Flow/ETL/Function/Power.php | 58 +- .../etl/src/Flow/ETL/Function/Prepend.php | 38 +- .../src/Flow/ETL/Function/RandomString.php | 26 +- src/core/etl/src/Flow/ETL/Function/Rank.php | 9 +- src/core/etl/src/Flow/ETL/Function/Regex.php | 70 +- .../etl/src/Flow/ETL/Function/RegexAll.php | 68 +- .../etl/src/Flow/ETL/Function/RegexMatch.php | 38 +- .../src/Flow/ETL/Function/RegexMatchAll.php | 39 +- .../src/Flow/ETL/Function/RegexReplace.php | 64 +- src/core/etl/src/Flow/ETL/Function/Repeat.php | 36 +- .../etl/src/Flow/ETL/Function/Reverse.php | 26 +- src/core/etl/src/Flow/ETL/Function/Round.php | 39 +- src/core/etl/src/Flow/ETL/Function/Same.php | 37 +- .../etl/src/Flow/ETL/Function/Sanitize.php | 58 +- .../src/Flow/ETL/Function/ScalarFunction.php | 8 +- .../Function/ScalarFunction/ExpandResults.php | 13 +- .../Function/ScalarFunction/UnpackResults.php | 13 +- .../Flow/ETL/Function/ScalarFunctionChain.php | 16 +- src/core/etl/src/Flow/ETL/Function/Size.php | 37 +- src/core/etl/src/Flow/ETL/Function/Slug.php | 40 +- src/core/etl/src/Flow/ETL/Function/Split.php | 50 +- .../etl/src/Flow/ETL/Function/Sprintf.php | 47 +- .../etl/src/Flow/ETL/Function/StartsWith.php | 32 +- src/core/etl/src/Flow/ETL/Function/StrPad.php | 42 +- .../etl/src/Flow/ETL/Function/StrReplace.php | 45 +- .../etl/src/Flow/ETL/Function/StringAfter.php | 36 +- .../src/Flow/ETL/Function/StringAfterLast.php | 36 +- .../src/Flow/ETL/Function/StringAggregate.php | 28 +- .../src/Flow/ETL/Function/StringBefore.php | 36 +- .../Flow/ETL/Function/StringBeforeLast.php | 36 +- .../Flow/ETL/Function/StringContainsAny.php | 42 +- .../src/Flow/ETL/Function/StringEqualsTo.php | 32 +- .../etl/src/Flow/ETL/Function/StringFold.php | 26 +- .../etl/src/Flow/ETL/Function/StringMatch.php | 52 +- .../src/Flow/ETL/Function/StringMatchAll.php | 58 +- .../src/Flow/ETL/Function/StringNormalize.php | 30 +- .../etl/src/Flow/ETL/Function/StringStyle.php | 47 +- .../etl/src/Flow/ETL/Function/StringTitle.php | 32 +- .../etl/src/Flow/ETL/Function/StringWidth.php | 26 +- .../etl/src/Flow/ETL/Function/Structure.php | 27 +- .../src/Flow/ETL/Function/StructureSelect.php | 45 +- src/core/etl/src/Flow/ETL/Function/Sum.php | 70 +- src/core/etl/src/Flow/ETL/Function/ToDate.php | 69 +- .../etl/src/Flow/ETL/Function/ToDateTime.php | 68 +- .../etl/src/Flow/ETL/Function/ToLower.php | 26 +- .../etl/src/Flow/ETL/Function/ToTimeZone.php | 45 +- .../etl/src/Flow/ETL/Function/ToUpper.php | 26 +- src/core/etl/src/Flow/ETL/Function/Trim.php | 51 +- .../etl/src/Flow/ETL/Function/Truncate.php | 41 +- src/core/etl/src/Flow/ETL/Function/Ulid.php | 44 +- .../src/Flow/ETL/Function/UnicodeLength.php | 26 +- src/core/etl/src/Flow/ETL/Function/Uuid.php | 37 +- src/core/etl/src/Flow/ETL/Function/When.php | 46 +- .../etl/src/Flow/ETL/Function/Wordwrap.php | 53 +- src/core/etl/src/Flow/ETL/Function/XPath.php | 85 ++- src/core/etl/src/Flow/ETL/GroupBy.php | 34 +- .../src/Flow/ETL/GroupBy/AggregatedGroups.php | 85 ++- .../etl/src/Flow/ETL/GroupBy/Aggregators.php | 22 +- .../Flow/ETL/GroupBy/BucketAggregation.php | 75 -- .../ETL/GroupBy/DiscoveredPivotValues.php | 17 +- .../etl/src/Flow/ETL/GroupBy/GroupBySteps.php | 14 +- .../etl/src/Flow/ETL/GroupBy/PivotedTable.php | 29 +- src/core/etl/src/Flow/ETL/Join/Comparison.php | 9 +- .../etl/src/Flow/ETL/Join/Comparison/All.php | 20 +- .../etl/src/Flow/ETL/Join/Comparison/Any.php | 20 +- .../src/Flow/ETL/Join/Comparison/Equal.php | 55 +- .../Flow/ETL/Join/Comparison/Identical.php | 25 +- src/core/etl/src/Flow/ETL/Join/Expression.php | 7 +- .../src/Flow/ETL/Join/HashJoin/HashTable.php | 38 +- .../src/Flow/ETL/Join/HashJoin/JoinSide.php | 7 +- .../etl/src/Flow/ETL/Join/HashJoin/Joiner.php | 275 +++++--- .../Flow/ETL/Join/HashJoin/NullRowBuilder.php | 13 +- .../src/Flow/ETL/Join/HashJoin/RowMerger.php | 42 +- src/core/etl/src/Flow/ETL/Join/JoinSteps.php | 6 +- .../Optimizer/Rule/CombineSortAndLimit.php | 2 +- .../src/Flow/ETL/Optimizer/TopNRewrite.php | 17 +- .../src/Flow/ETL/Plan/Explain/StepDetails.php | 52 +- src/core/etl/src/Flow/ETL/Plan/Node/TopN.php | 6 +- .../src/Flow/ETL/Planner/NodeTranslator.php | 6 +- .../ETL/Processor/BatchingByProcessor.php | 58 +- .../Flow/ETL/Processor/BatchingProcessor.php | 25 +- .../Flow/ETL/Processor/BucketingProcessor.php | 42 -- .../ETL/Processor/CollectingProcessor.php | 2 +- .../ETL/Processor/ConstrainedProcessor.php | 32 +- .../Processor/GroupByAggregationProcessor.php | 133 +++- .../Flow/ETL/Processor/HashJoinProcessor.php | 77 +- .../ETL/Processor/MemorySortProcessor.php | 17 +- .../Flow/ETL/Processor/MergeSortProcessor.php | 98 +-- .../ETL/Processor/RepartitionProcessor.php | 64 +- .../src/Flow/ETL/Processor/TopNProcessor.php | 61 +- .../src/Flow/ETL/Processor/VoidProcessor.php | 2 +- .../Flow/ETL/Processor/WindowProcessor.php | 54 +- .../Flow/ETL/Repartition/RepartitionSteps.php | 13 +- src/core/etl/src/Flow/ETL/Row.php | 108 --- src/core/etl/src/Flow/ETL/Row/Comparator.php | 13 - .../ETL/Row/Comparator/NativeComparator.php | 38 - src/core/etl/src/Flow/ETL/Row/NullsOrder.php | 19 + src/core/etl/src/Flow/ETL/Row/Reference.php | 2 + .../src/Flow/ETL/Row/ResolvedReference.php | 23 +- .../src/Flow/ETL/Row/UnresolvedReference.php | 24 +- src/core/etl/src/Flow/ETL/Rows.php | 347 +++------ .../etl/src/Flow/ETL/Rows/RowEquality.php | 161 +++++ src/core/etl/src/Flow/ETL/Rows/RowHashes.php | 44 ++ src/core/etl/src/Flow/ETL/Schema.php | 7 + .../etl/src/Flow/ETL/Schema/SameSchemas.php | 38 + .../etl/src/Flow/ETL/Sort/ExternalSort.php | 202 ++++++ .../src/Flow/ETL/Sort/Merge/BucketCursor.php | 51 +- .../ETL/Sort/Merge/ComparableBucketRow.php | 19 - .../etl/src/Flow/ETL/Sort/Merge/KWayMerge.php | 80 ++- .../src/Flow/ETL/Sort/Merge/RowsMinHeap.php | 83 --- src/core/etl/src/Flow/ETL/Sort/RowOrder.php | 191 +++++ src/core/etl/src/Flow/ETL/Sort/SortKey.php | 23 + src/core/etl/src/Flow/ETL/Sort/SortSteps.php | 43 +- .../etl/src/Flow/ETL/Sort/ValuesSorter.php | 129 ---- .../Flow/ETL/Transformer/DerivedColumns.php | 28 +- .../Transformer/DropDuplicatesTransformer.php | 24 +- .../Transformer/DuplicateRowTransformer.php | 32 +- .../Transformer/NestedExpandTransformer.php | 47 +- .../Flow/ETL/Transformer/NestedExpansion.php | 60 +- .../ScalarFunctionFilterTransformer.php | 12 +- .../Transformer/ScalarFunctionTransformer.php | 65 +- .../ETL/Transformer/SerializeTransformer.php | 5 +- .../Transformer/SerializedPayloadDecoder.php | 18 +- .../Transformer/UnserializeTransformer.php | 5 +- .../Flow/ETL/Transformer/UntilTransformer.php | 15 +- .../Window/Accumulator/AverageAccumulator.php | 15 +- .../Window/Accumulator/CountAccumulator.php | 6 +- .../ETL/Window/Accumulator/SumAccumulator.php | 30 +- .../src/Flow/ETL/Window/FrameAccumulator.php | 4 +- .../src/Flow/ETL/Window/PeerComparator.php | 71 +- .../etl/src/Flow/ETL/Window/PeerFrame.php | 47 +- .../etl/src/Flow/ETL/Window/WindowContext.php | 14 +- .../Calculator/Tests/Unit/RunningSumTest.php | 97 ++- .../ETL/Tests/Comparator/RowComparator.php | 60 -- .../Tests/Context/BucketsStorageContext.php | 5 +- .../ETL/Tests/Context/FunctionContext.php | 49 ++ .../Flow/ETL/Tests/Context/GroupByContext.php | 28 - .../Flow/ETL/Tests/Context/GroupedRows.php | 95 +++ .../tests/Flow/ETL/Tests/Context/IdRows.php | 50 ++ .../ETL/Tests/Context/WindowFrameContext.php | 5 +- .../Tests/Context/WindowProcessorContext.php | 4 +- .../AddStampToStringEntryTransformer.php | 6 +- .../ETL/Tests/Double/ConstantComparison.php | 36 + .../ETL/Tests/Double/CountingDOMDocument.php | 35 + .../ETL/Tests/Double/CountingExtractor.php | 17 +- .../Double/CountingFrameAccumulating.php | 6 +- .../Tests/Double/CountingFrameAccumulator.php | 7 +- .../Tests/Double/CountingReturnsFunction.php | 7 +- .../ETL/Tests/Double/DeclaringExtractor.php | 2 +- .../Tests/Double/FailingOnValuesFunction.php | 108 +++ .../ETL/Tests/Double/FixedValuesColumn.php | 98 +++ .../ETL/Tests/Double/HoldingExtractor.php | 57 ++ .../Tests/Double/NonStructureUnpackStub.php | 13 +- .../Tests/Double/OneRowBatchesExtractor.php | 6 +- .../ETL/Tests/Double/RepeatableExtractor.php | 2 +- .../Tests/Double/ReportedMemoryBackend.php | 48 ++ .../Tests/Double/ReportsResolvedOperand.php | 10 +- .../ETL/Tests/Double/ReturnsSpyFunction.php | 69 ++ .../ETL/Tests/Double/SpyBucketsStorage.php | 6 + .../tests/Flow/ETL/Tests/Double/SpyColumn.php | 109 +++ .../ETL/Tests/Double/ThrowWhenRowMatches.php | 4 +- .../Flow/ETL/Tests/Double/UnenumerableSum.php | 114 +++ .../Double/WindowFunctionOverOperand.php | 74 ++ .../ETL/Tests/Fixtures/Join/AlwaysMeets.php | 12 +- .../Bucketing/SpillingPathsTest.php | 113 +++ .../Storage/FilesystemBucketsTest.php | 41 +- .../Bucketing/Storage/PSRCacheBucketsTest.php | 7 +- .../Integration/Config/MemoryLimitTest.php | 41 ++ .../DataFrame/AlgorithmOverrideTest.php | 45 +- .../Integration/DataFrame/GroupByTest.php | 2 +- .../Tests/Integration/DataFrame/MathTest.php | 4 +- .../Integration/DataFrame/OffsetTest.php | 8 +- .../DataFrame/PartitioningTest.php | 2 +- .../Integration/DataFrame/PlanBindTest.php | 4 +- .../SinkRootBlockingOperationsTest.php | 16 +- .../Tests/Integration/DataFrame/SortTest.php | 9 +- .../Dataset/SharedMemoryLimitTest.php | 62 ++ .../Filesystem/ConfigIsolationTest.php | 6 +- .../Function/ArrayKeysStyleConvertTest.php | 30 +- .../Tests/Integration/Function/CastTest.php | 25 +- .../Function/DOMElementNextSiblingTest.php | 18 + .../Function/UntypedIntermediateTest.php | 58 ++ .../ExternalSortLifecycleTest.php | 7 +- .../ExternalSort/ExternalSortMergeTest.php | 46 +- .../ExternalSort/ExternalSortRunSizeTest.php | 68 ++ .../ETL/Tests/Mother/ExternalSortMother.php | 67 ++ .../GroupByAggregationProcessorMother.php | 54 ++ .../Tests/Mother/HashJoinProcessorMother.php | 6 +- .../ETL/Tests/Mother/ListColumnsMother.php | 10 +- .../Mother/RepartitionProcessorMother.php | 49 ++ .../Flow/ETL/Tests/Mother/RowsMother.php | 8 +- .../ETL/Tests/Mother/SortDatasetMother.php | 107 +++ .../ETL/Tests/Mother/WindowContextMother.php | 19 +- .../Tests/Unit/Bucketing/BucketRunTest.php | 9 +- .../Tests/Unit/Bucketing/BucketShapeTest.php | 17 - .../ETL/Tests/Unit/Bucketing/BucketTest.php | 10 - .../Unit/Bucketing/HashBucketingTest.php | 23 + .../Tests/Unit/Bucketing/KeyValuesTest.php | 70 +- .../Tests/Unit/Bucketing/NativeHasherTest.php | 7 + .../Unit/Bucketing/SortedRunBucketingTest.php | 144 ---- .../Bucketing/Storage/MemoryBucketsTest.php | 12 +- .../Bucketing/Storage/PSRCacheBucketsTest.php | 18 +- .../Bucketing/Storage/SpillingBucketsTest.php | 111 +++ .../Unit/Column/ComparableValuesTest.php | 131 ++++ .../Tests/Unit/Column/DefaultBackendTest.php | 10 + .../Tests/Unit/Column/Php/ListColumnTest.php | 19 + .../Tests/Unit/Column/Php/MapColumnTest.php | 23 + .../Tests/Unit/Column/Php/PhysicalForTest.php | 67 ++ .../Tests/Unit/Column/Php/ValueColumnTest.php | 72 ++ .../ETL/Tests/Unit/Column/PhpBackendTest.php | 11 + .../Unit/Comparator/RowComparatorTest.php | 90 --- .../Unit/Comparator/RowsComparatorTest.php | 3 +- .../Unit/Config/Join/HashJoinBuilderTest.php | 23 + .../Config/Sort/ExternalSortBuilderTest.php | 20 +- .../Unit/Constraint/SortedConstraintTest.php | 293 +++++--- .../Unit/Constraint/UniqueConstraintTest.php | 92 ++- .../Flow/ETL/Tests/Unit/DataFrameTest.php | 4 +- .../Unit/Dataset/Memory/BoundedReadTest.php | 44 ++ .../Unit/Dataset/Memory/MemoryBudgetTest.php | 48 ++ .../Unit/Dataset/Statistics/ColumnTest.php | 141 +++- .../Unit/Dataset/Statistics/ColumnsTest.php | 13 +- .../ETL/Tests/Unit/ETLErrorHandlingTest.php | 2 +- .../Exception/EvaluationExceptionTest.php | 44 ++ .../Unit/Executor/OffsetPipelineTest.php | 11 +- .../Executor/WindowFunctionPipelineTest.php | 30 +- .../Flow/ETL/Tests/Unit/ExecutorTest.php | 44 ++ .../Unit/Extractor/ArrayExtractorTest.php | 5 +- .../Unit/Extractor/BatchByExtractorTest.php | 69 ++ .../Unit/Extractor/FilesExtractorTest.php | 10 +- .../Unit/Extractor/PartitionColumnsTest.php | 22 +- .../Flow/ETL/Tests/Unit/Function/AllTest.php | 55 +- .../Flow/ETL/Tests/Unit/Function/AnyTest.php | 49 +- .../ETL/Tests/Unit/Function/AppendTest.php | 79 +-- .../Tests/Unit/Function/ArrayExpandTest.php | 81 ++- .../Tests/Unit/Function/ArrayFilterTest.php | 50 +- .../Unit/Function/ArrayGetCollectionTest.php | 211 +++--- .../ETL/Tests/Unit/Function/ArrayGetTest.php | 163 +++-- .../ETL/Tests/Unit/Function/ArrayKeepTest.php | 48 +- .../Unit/Function/ArrayKeyRenameTest.php | 116 +-- .../Function/ArrayKeysStyleConverterTest.php | 86 +-- .../ETL/Tests/Unit/Function/ArrayKeysTest.php | 20 +- .../Function/ArrayMergeCollectionTest.php | 77 +- .../Tests/Unit/Function/ArrayMergeTest.php | 64 +- .../Tests/Unit/Function/ArrayReverseTest.php | 16 +- .../ETL/Tests/Unit/Function/ArraySortTest.php | 302 ++++---- .../Tests/Unit/Function/ArrayUnpackTest.php | 54 +- .../Tests/Unit/Function/ArrayValuesTest.php | 20 +- .../ETL/Tests/Unit/Function/AsciiTest.php | 18 +- .../ETL/Tests/Unit/Function/AverageTest.php | 153 +++- .../ETL/Tests/Unit/Function/BetweenTest.php | 152 ++-- .../Unit/Function/BinaryComparisonsTest.php | 660 +++++++++++++++--- .../Tests/Unit/Function/BinaryLengthTest.php | 42 +- .../Tests/Unit/Function/CallUserFuncTest.php | 74 +- .../Tests/Unit/Function/CapitalizeTest.php | 10 +- .../Flow/ETL/Tests/Unit/Function/CastTest.php | 115 ++- .../ETL/Tests/Unit/Function/ChunkTest.php | 67 +- .../ETL/Tests/Unit/Function/CoalesceTest.php | 72 +- .../Unit/Function/CodePointLengthTest.php | 26 +- .../Unit/Function/CollapseWhitespaceTest.php | 92 +-- .../ETL/Tests/Unit/Function/CollectTest.php | 57 +- .../Tests/Unit/Function/CollectUniqueTest.php | 57 +- .../ETL/Tests/Unit/Function/CombineTest.php | 16 +- .../ETL/Tests/Unit/Function/ConcatTest.php | 35 +- .../Unit/Function/ConcatWithSeparatorTest.php | 34 +- .../ETL/Tests/Unit/Function/CountTest.php | 138 ++-- .../Function/DOMElementAttributeValueTest.php | 50 +- .../DOMElementAttributesCountTest.php | 62 +- .../Unit/Function/DOMElementNamespaceTest.php | 38 +- .../Unit/Function/DOMElementParentTest.php | 70 +- .../Unit/Function/DOMElementValueTest.php | 42 +- .../Unit/Function/DateTimeFormatTest.php | 27 +- .../ETL/Tests/Unit/Function/EnsureEndTest.php | 84 +-- .../Tests/Unit/Function/EnsureStartTest.php | 84 +-- .../ETL/Tests/Unit/Function/EnumNameTest.php | 27 +- .../ETL/Tests/Unit/Function/EnumValueTest.php | 27 +- .../ETL/Tests/Unit/Function/EqualsTest.php | 133 +++- .../Function/Evaluation/ResultColumnTest.php | 151 ++++ .../Function/Evaluation/ReturnTypesTest.php | 60 ++ .../Function/Evaluation/SelectionTest.php | 76 ++ .../Evaluation/TolerantEvaluationTest.php | 101 +++ .../ETL/Tests/Unit/Function/ExistsTest.php | 85 ++- .../ETL/Tests/Unit/Function/FirstTest.php | 74 +- .../Unit/Function/GreaterThanEqualTest.php | 248 +++---- .../Tests/Unit/Function/GreaterThanTest.php | 256 +++---- .../ETL/Tests/Unit/Function/GreatestTest.php | 38 +- .../Function/HTMLQuerySelectorAllTest.php | 35 +- .../Unit/Function/HTMLQuerySelectorTest.php | 36 +- .../Flow/ETL/Tests/Unit/Function/HashTest.php | 50 +- .../Tests/Unit/Function/IndexOfLastTest.php | 56 +- .../ETL/Tests/Unit/Function/IndexOfTest.php | 58 +- .../ETL/Tests/Unit/Function/IsEmptyTest.php | 36 +- .../Flow/ETL/Tests/Unit/Function/IsInTest.php | 142 +++- .../ETL/Tests/Unit/Function/IsUtf8Test.php | 30 +- .../Tests/Unit/Function/JsonDecodeTest.php | 46 +- .../Tests/Unit/Function/JsonEncodeTest.php | 48 +- .../Flow/ETL/Tests/Unit/Function/LastTest.php | 91 ++- .../ETL/Tests/Unit/Function/LeastTest.php | 28 +- .../Tests/Unit/Function/LessThanEqualTest.php | 248 +++---- .../ETL/Tests/Unit/Function/LessThanTest.php | 242 ++++--- .../Tests/Unit/Function/ListSelectTest.php | 89 ++- .../ETL/Tests/Unit/Function/LiteralTest.php | 38 + .../Unit/Function/LogicalFunctionsTest.php | 46 +- .../Tests/Unit/Function/MatchCasesTest.php | 68 +- .../Flow/ETL/Tests/Unit/Function/MathTest.php | 68 +- .../Flow/ETL/Tests/Unit/Function/MaxTest.php | 150 +++- .../Flow/ETL/Tests/Unit/Function/MinTest.php | 152 +++- .../ETL/Tests/Unit/Function/MinusTest.php | 57 ++ .../Unit/Function/ModifyDateTimeTest.php | 32 +- .../ETL/Tests/Unit/Function/MultiplyTest.php | 57 ++ .../Flow/ETL/Tests/Unit/Function/NotTest.php | 57 +- .../Flow/ETL/Tests/Unit/Function/NowTest.php | 29 +- .../Tests/Unit/Function/NumberFormatTest.php | 96 ++- .../ETL/Tests/Unit/Function/OnEachTest.php | 151 ++-- .../ETL/Tests/Unit/Function/OptionalTest.php | 72 +- .../ETL/Tests/Unit/Function/ParameterTest.php | 532 +++++++++----- .../Flow/ETL/Tests/Unit/Function/PlusTest.php | 57 ++ .../ETL/Tests/Unit/Function/PowerTest.php | 68 +- .../Tests/Unit/Function/PregReplaceTest.php | 10 +- .../ETL/Tests/Unit/Function/PrependTest.php | 71 +- .../ETL/Tests/Unit/Function/RegexAllTest.php | 10 +- .../Tests/Unit/Function/RegexMatchAllTest.php | 12 +- .../Tests/Unit/Function/RegexMatchTest.php | 10 +- .../Tests/Unit/Function/RegexReplaceTest.php | 22 +- .../ETL/Tests/Unit/Function/RegexTest.php | 10 +- .../ETL/Tests/Unit/Function/RepeatTest.php | 63 +- .../ETL/Tests/Unit/Function/ReverseTest.php | 26 +- .../ETL/Tests/Unit/Function/RoundTest.php | 50 +- .../ETL/Tests/Unit/Function/RowNumberTest.php | 28 +- .../Flow/ETL/Tests/Unit/Function/SameTest.php | 83 ++- .../ETL/Tests/Unit/Function/SanitizeTest.php | 40 +- .../Flow/ETL/Tests/Unit/Function/SizeTest.php | 12 +- .../Flow/ETL/Tests/Unit/Function/SlugTest.php | 34 +- .../ETL/Tests/Unit/Function/SplitTest.php | 8 +- .../ETL/Tests/Unit/Function/SprintfTest.php | 10 +- .../ETL/Tests/Unit/Function/StrPadTest.php | 10 +- .../Tests/Unit/Function/StrReplaceTest.php | 18 +- .../Unit/Function/StringAfterLastTest.php | 38 +- .../Tests/Unit/Function/StringAfterTest.php | 54 +- .../Unit/Function/StringAggregateTest.php | 101 ++- .../Unit/Function/StringBeforeLastTest.php | 55 +- .../Tests/Unit/Function/StringBeforeTest.php | 71 +- .../Unit/Function/StringContainsAnyTest.php | 82 +-- .../Unit/Function/StringEqualsToTest.php | 74 +- .../Tests/Unit/Function/StringFoldTest.php | 18 +- .../Unit/Function/StringMatchAllTest.php | 82 +-- .../Tests/Unit/Function/StringMatchTest.php | 85 ++- .../Unit/Function/StringNormalizeTest.php | 74 +- .../Tests/Unit/Function/StringStyleTest.php | 48 +- .../Tests/Unit/Function/StringTitleTest.php | 26 +- .../Tests/Unit/Function/StringWidthTest.php | 34 +- .../Unit/Function/StructureSelectTest.php | 60 +- .../ETL/Tests/Unit/Function/StructureTest.php | 80 +-- .../Flow/ETL/Tests/Unit/Function/SumTest.php | 270 +++---- .../ETL/Tests/Unit/Function/ToDateTest.php | 31 +- .../Tests/Unit/Function/ToDateTimeTest.php | 85 ++- .../ETL/Tests/Unit/Function/ToLowerTest.php | 4 +- .../Tests/Unit/Function/ToTimeZoneTest.php | 33 +- .../ETL/Tests/Unit/Function/ToUpperTest.php | 4 +- .../Flow/ETL/Tests/Unit/Function/TrimTest.php | 26 +- .../ETL/Tests/Unit/Function/TruncateTest.php | 121 ++-- .../Flow/ETL/Tests/Unit/Function/UlidTest.php | 15 +- .../Tests/Unit/Function/UnicodeLengthTest.php | 26 +- .../Flow/ETL/Tests/Unit/Function/UuidTest.php | 27 +- .../Flow/ETL/Tests/Unit/Function/WhenTest.php | 156 ++++- .../ETL/Tests/Unit/Function/WordwrapTest.php | 113 ++- .../ETL/Tests/Unit/Function/XPathTest.php | 58 +- .../Tests/Unit/GroupBy/AggregatorsTest.php | 5 +- .../Unit/GroupBy/BucketAggregationTest.php | 218 ------ .../GroupBy/DiscoveredPivotValuesTest.php | 31 + .../Tests/Unit/GroupBy/GroupByStepsTest.php | 79 ++- .../tests/Flow/ETL/Tests/Unit/GroupByTest.php | 49 +- .../Tests/Unit/Join/Comparison/AllTest.php | 56 +- .../Tests/Unit/Join/Comparison/AnyTest.php | 56 +- .../Tests/Unit/Join/Comparison/EqualTest.php | 119 ++-- .../Unit/Join/Comparison/IdenticalTest.php | 110 ++- .../ETL/Tests/Unit/Join/ExpressionTest.php | 13 +- .../Unit/Join/HashJoin/HashTableTest.php | 71 +- .../Tests/Unit/Join/HashJoin/JoinerTest.php | 136 +++- .../Unit/Join/HashJoin/NullRowBuilderTest.php | 25 +- .../Unit/Join/HashJoin/RowMergerTest.php | 140 ++-- .../ETL/Tests/Unit/Join/JoinShapeTest.php | 24 +- .../Rule/CombineSortAndLimitTest.php | 16 - .../Tests/Unit/Optimizer/TopNRewriteTest.php | 41 +- .../Unit/Plan/Explain/PhysicalOutlineTest.php | 4 + .../Unit/Plan/Explain/StepDetailsTest.php | 70 +- .../Tests/Unit/Planner/NodeTranslatorTest.php | 7 +- .../Processor/BatchingByProcessorTest.php | 79 ++- .../Unit/Processor/BucketingProcessorTest.php | 109 --- .../Processor/ConstrainedProcessorTest.php | 67 +- .../GroupByAggregationProcessorTest.php | 368 +++++----- .../Unit/Processor/HashJoinProcessorTest.php | 75 +- .../Unit/Processor/MergeSortProcessorTest.php | 307 +------- .../Processor/RepartitionProcessorTest.php | 163 +++-- .../Unit/Processor/TopNProcessorTest.php | 128 ++++ .../Unit/Processor/WindowProcessorTest.php | 17 +- .../Unit/Repartition/RepartitionStepsTest.php | 11 +- .../ETL/Tests/Unit/Row/ArrayToRowTest.php | 108 --- .../Row/Comparator/NativeComparatorTest.php | 42 -- .../ETL/Tests/Unit/Row/NullsOrderTest.php | 18 + .../Tests/Unit/Row/ResolvedReferenceTest.php | 13 + .../Unit/Row/UnresolvedReferenceTest.php | 30 +- .../etl/tests/Flow/ETL/Tests/Unit/RowTest.php | 182 ----- .../ETL/Tests/Unit/Rows/RowEqualityTest.php | 165 +++++ .../ETL/Tests/Unit/Rows/RowHashesTest.php | 150 ++++ .../ETL/Tests/Unit/Rows/RowsBuilderTest.php | 11 +- .../ETL/Tests/Unit/RowsSerializationTest.php | 47 +- .../tests/Flow/ETL/Tests/Unit/RowsTest.php | 497 +++++++------ .../ETL/Tests/Unit/Schema/SameSchemasTest.php | 28 + .../Flow/ETL/Tests/Unit/Schema/SchemaTest.php | 23 + .../ETL/Tests/Unit/Sort/ExternalSortTest.php | 307 ++++++++ .../Unit/Sort/Merge/BucketCursorTest.php | 59 +- .../Tests/Unit/Sort/Merge/KWayMergeTest.php | 168 ++++- .../Tests/Unit/Sort/Merge/RowsMinHeapTest.php | 116 --- .../Flow/ETL/Tests/Unit/Sort/RowOrderTest.php | 258 +++++++ .../ETL/Tests/Unit/Sort/SortStepsTest.php | 72 +- .../ETL/Tests/Unit/Sort/ValuesSorterTest.php | 105 --- .../Unit/Transformer/DerivedColumnsTest.php | 56 +- .../DuplicateRowTransformerTest.php | 2 +- .../Unit/Transformer/NestedExpansionTest.php | Bin 6869 -> 7406 bytes .../RenameEntryTransformerTest.php | 4 +- .../ScalarFunctionTransformer/MathTest.php | 8 +- .../ScalarFunctionTransformerTest.php | 36 +- .../Transformer/SerializeTransformerTest.php | 81 +-- .../SerializedPayloadDecoderTest.php | 34 +- .../UnserializeTransformerTest.php | 54 +- .../Accumulator/AverageAccumulatorTest.php | 44 +- .../Accumulator/CountAccumulatorTest.php | 20 +- .../Window/Accumulator/SumAccumulatorTest.php | 47 +- .../Tests/Unit/Window/PeerComparatorTest.php | 92 +++ .../ETL/Tests/Unit/Window/PeerFrameTest.php | 26 + .../Tests/Unit/Window/WindowContextTest.php | 17 +- .../Tests/Context/FloeStreamReaderContext.php | 8 +- .../Tests/Integration/FloeDataFrameTest.php | 19 +- .../Tests/Integration/FloeExtractorTest.php | 9 +- .../Integration/FloeStreamReaderTest.php | 12 +- .../Floe/Tests/Unit/FloeExtractorTest.php | 30 +- .../Flow/Floe/Tests/Unit/FloeLoaderTest.php | 12 +- .../Flow/Floe/Tests/Unit/FloeMergerTest.php | 8 +- .../Flow/Floe/Tests/Unit/FloeReaderTest.php | 69 +- .../Floe/Tests/Unit/FloeStreamWriterTest.php | 2 +- .../Tests/Unit/FloeValueRoundTripTest.php | 13 +- .../Flow/Floe/Tests/Unit/FloeWriterTest.php | 2 +- src/extension/flow-php-ext/src/backend.rs | 11 +- .../phpt/061_native_mixed_class_building.phpt | 6 +- .../067_adopt_refuses_untyped_column.phpt | 21 + .../examples/topics/inspecting/fetch/code.php | 6 +- web/landing/resources/api.json | 2 +- web/landing/resources/dsl.json | 2 +- 653 files changed, 22066 insertions(+), 11431 deletions(-) create mode 100644 .nix/blackfire/.gitignore create mode 100644 .nix/blackfire/blackfire.env.dist delete mode 100644 src/core/etl/src/Flow/ETL/Bucketing/BucketShape.php delete mode 100644 src/core/etl/src/Flow/ETL/Bucketing/BucketingStrategy.php delete mode 100644 src/core/etl/src/Flow/ETL/Bucketing/SortedRunBucketing.php create mode 100644 src/core/etl/src/Flow/ETL/Bucketing/Storage/SpillingBuckets.php create mode 100644 src/core/etl/src/Flow/ETL/Column/ComparableValues.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ValueColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Config/MemoryLimit.php create mode 100644 src/core/etl/src/Flow/ETL/Dataset/Memory/BoundedRead.php create mode 100644 src/core/etl/src/Flow/ETL/Dataset/Memory/MemoryBudget.php create mode 100644 src/core/etl/src/Flow/ETL/Exception/EvaluationException.php create mode 100644 src/core/etl/src/Flow/ETL/Function/Evaluation/ResultColumn.php create mode 100644 src/core/etl/src/Flow/ETL/Function/Evaluation/ReturnTypes.php create mode 100644 src/core/etl/src/Flow/ETL/Function/Evaluation/Selection.php create mode 100644 src/core/etl/src/Flow/ETL/Function/Evaluation/TolerantEvaluation.php delete mode 100644 src/core/etl/src/Flow/ETL/GroupBy/BucketAggregation.php delete mode 100644 src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php delete mode 100644 src/core/etl/src/Flow/ETL/Row.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/Comparator.php delete mode 100644 src/core/etl/src/Flow/ETL/Row/Comparator/NativeComparator.php create mode 100644 src/core/etl/src/Flow/ETL/Row/NullsOrder.php create mode 100644 src/core/etl/src/Flow/ETL/Rows/RowEquality.php create mode 100644 src/core/etl/src/Flow/ETL/Rows/RowHashes.php create mode 100644 src/core/etl/src/Flow/ETL/Schema/SameSchemas.php create mode 100644 src/core/etl/src/Flow/ETL/Sort/ExternalSort.php delete mode 100644 src/core/etl/src/Flow/ETL/Sort/Merge/ComparableBucketRow.php delete mode 100644 src/core/etl/src/Flow/ETL/Sort/Merge/RowsMinHeap.php create mode 100644 src/core/etl/src/Flow/ETL/Sort/RowOrder.php create mode 100644 src/core/etl/src/Flow/ETL/Sort/SortKey.php delete mode 100644 src/core/etl/src/Flow/ETL/Sort/ValuesSorter.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Comparator/RowComparator.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/FunctionContext.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/GroupedRows.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/IdRows.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/ConstantComparison.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/CountingDOMDocument.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/FailingOnValuesFunction.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/FixedValuesColumn.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/HoldingExtractor.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/ReportedMemoryBackend.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/ReturnsSpyFunction.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/SpyColumn.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/UnenumerableSum.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/WindowFunctionOverOperand.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/SpillingPathsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/Config/MemoryLimitTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/Dataset/SharedMemoryLimitTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/Function/UntypedIntermediateTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortRunSizeTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/ExternalSortMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/GroupByAggregationProcessorMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/RepartitionProcessorMother.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Mother/SortDatasetMother.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketShapeTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/SortedRunBucketingTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/SpillingBucketsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValueColumnTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/BoundedReadTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/MemoryBudgetTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/EvaluationExceptionTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ResultColumnTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ReturnTypesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/SelectionTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/TolerantEvaluationTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinusTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MultiplyTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PlusTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/BucketAggregationTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BucketingProcessorTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Comparator/NativeComparatorTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/NullsOrderTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowEqualityTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowHashesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/SameSchemasTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ExternalSortTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/RowsMinHeapTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/RowOrderTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ValuesSorterTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerComparatorTest.php create mode 100644 src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt diff --git a/.nix/blackfire/.gitignore b/.nix/blackfire/.gitignore new file mode 100644 index 0000000000..21b52734b0 --- /dev/null +++ b/.nix/blackfire/.gitignore @@ -0,0 +1 @@ +blackfire.env diff --git a/.nix/blackfire/blackfire.env.dist b/.nix/blackfire/blackfire.env.dist new file mode 100644 index 0000000000..19d9e5ec4d --- /dev/null +++ b/.nix/blackfire/blackfire.env.dist @@ -0,0 +1,2 @@ +# Copy to blackfire.env (gitignored) and fill in; nix-shell exports it for `blackfire run`. +BLACKFIRE_ENV= diff --git a/benchmarks/src/Datasets/SellersDataset.php b/benchmarks/src/Datasets/SellersDataset.php index dbbae23813..02e46047a2 100644 --- a/benchmarks/src/Datasets/SellersDataset.php +++ b/benchmarks/src/Datasets/SellersDataset.php @@ -31,9 +31,8 @@ public function parquet(): string $sellerIds = []; foreach (data_frame()->read(from_parquet($ordersPath)->withColumns(['seller_id']))->get() as $batch) { - foreach ($batch->all() as $row) { - $sellerId = $row->get('seller_id'); - + // @mago-ignore analysis:mixed-assignment + foreach ($batch->column('seller_id')->values() as $sellerId) { if (is_scalar($sellerId) || $sellerId instanceof Stringable) { $sellerIds[(string) $sellerId] = true; } diff --git a/benchmarks/src/Datasets/TextDataset.php b/benchmarks/src/Datasets/TextDataset.php index bdaa454e0c..a6ad0fbb97 100644 --- a/benchmarks/src/Datasets/TextDataset.php +++ b/benchmarks/src/Datasets/TextDataset.php @@ -31,9 +31,12 @@ public function path(): string $lines = []; foreach (data_frame()->read(from_parquet($parquetPath)->withColumns(['customer', 'notes']))->get() as $batch) { - foreach ($batch->all() as $row) { - $customer = $row->get('customer'); - $notes = $row->get('notes'); + $allNotes = $batch->column('notes')->values(); + + // @mago-ignore analysis:mixed-assignment + foreach ($batch->column('customer')->values() as $i => $customer) { + // @mago-ignore analysis:mixed-assignment + $notes = $allNotes[$i]; $customerText = is_scalar($customer) || $customer instanceof Stringable ? (string) $customer : ''; $notesText = is_array($notes) diff --git a/benchmarks/src/Pipeline/InMemoryOrders.php b/benchmarks/src/Pipeline/InMemoryOrders.php index 408be928d8..e35bf5bcc2 100644 --- a/benchmarks/src/Pipeline/InMemoryOrders.php +++ b/benchmarks/src/Pipeline/InMemoryOrders.php @@ -35,10 +35,12 @@ public static function of(int $rows): array $data = []; foreach (data_frame()->read(from_parquet(Datasets::orders($rows)->parquet()))->get() as $batch) { - foreach ($batch->all() as $row) { - // Row::toArray() is declared array; names() is list, so - // recombining them is what makes the string keys ArrayMemory requires provable. - $data[] = array_combine($row->names(), array_values($row->toArray())); + $names = $batch->schema()->references()->names(); + + // Rows::toArray() is declared array; names() is array, so + // recombining them is what makes the string keys ArrayMemory requires provable. + foreach ($batch->toArray(withKeys: false) as $values) { + $data[] = array_combine($names, $values); } } diff --git a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/PipelineCostScenariosTest.php b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/PipelineCostScenariosTest.php index 5a8ec7da22..438a7b1333 100644 --- a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/PipelineCostScenariosTest.php +++ b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/PipelineCostScenariosTest.php @@ -92,7 +92,7 @@ public function test_the_fetch_scenario_runs(): void $rows = (new FetchScenario(Source::csv, self::ROWS))->run(); static::assertCount(self::ROWS, $rows); - static::assertSame(['order_id', 'customer'], $rows->first()->names()); + static::assertSame(['order_id', 'customer'], array_keys($rows->values(0))); } #[DataProvider('limits')] diff --git a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/PipelineScenarioTest.php b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/PipelineScenarioTest.php index 74547de60a..def597cec1 100644 --- a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/PipelineScenarioTest.php +++ b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/PipelineScenarioTest.php @@ -40,7 +40,10 @@ public function test_it_writes_the_five_projected_columns_for_every_row(Source $ $written->remove(); static::assertCount(self::ROWS, $rows); - static::assertSame(['order_id', 'seller_id', 'created_at', 'customer', 'contact'], $rows->first()->names()); + static::assertSame( + ['order_id', 'seller_id', 'created_at', 'customer', 'contact'], + array_keys($rows->values(0)), + ); } #[DataProvider('sources')] @@ -50,12 +53,12 @@ public function test_the_inferred_and_declared_arms_produce_the_same_columns(Sou $declaredFile = new WrittenFile(Paths::var() . '/pipeline_' . $source->value . '_*.floe'); (new PipelineScenario($source, SchemaMode::declared, self::ROWS))->run(); - $declared = data_frame()->read(from_floe($declaredFile->path()))->fetch()->first()->names(); + $declared = array_keys(data_frame()->read(from_floe($declaredFile->path()))->fetch()->values(0)); $declaredFile->remove(); $inferredFile = new WrittenFile(Paths::var() . '/pipeline_' . $source->value . '_*.floe'); (new PipelineScenario($source, SchemaMode::inferred, self::ROWS))->run(); - $inferred = data_frame()->read(from_floe($inferredFile->path()))->fetch()->first()->names(); + $inferred = array_keys(data_frame()->read(from_floe($inferredFile->path()))->fetch()->values(0)); $inferredFile->remove(); static::assertSame($declared, $inferred); diff --git a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/StageScenarioTest.php b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/StageScenarioTest.php index 043c827ffe..689fbbabdd 100644 --- a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/StageScenarioTest.php +++ b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Pipeline/StageScenarioTest.php @@ -50,6 +50,6 @@ public function test_the_read_select_write_stage_writes_the_five_projected_colum $written->remove(); static::assertCount(self::ROWS, $rows); - static::assertSame(['order_id', 'seller_id', 'created_at', 'customer', 'email'], $rows->first()->names()); + static::assertSame(['order_id', 'seller_id', 'created_at', 'customer', 'email'], array_keys($rows->values(0))); } } diff --git a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Window/WindowPartitioningTest.php b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Window/WindowPartitioningTest.php index 1c168140d8..eaed8a293f 100644 --- a/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Window/WindowPartitioningTest.php +++ b/benchmarks/tests/Flow/Benchmarks/Tests/Unit/Window/WindowPartitioningTest.php @@ -25,11 +25,12 @@ public function test_both_arms_derive_the_key_so_only_the_partition_column_varie foreach (PartitionCardinality::cases() as $cardinality) { static::assertContains( 'day', - (new WindowPartitioning($cardinality)) - ->derive(data_frame()->read(from_floe(Datasets::orders(self::ROWS)->floe()))) - ->fetch() - ->first() - ->names(), + array_keys( + (new WindowPartitioning($cardinality)) + ->derive(data_frame()->read(from_floe(Datasets::orders(self::ROWS)->floe()))) + ->fetch() + ->values(0), + ), $cardinality->value, ); } diff --git a/bootstrap.php b/bootstrap.php index ade6286e0f..a69a0c0c6d 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -38,4 +38,3 @@ SebastianBergmann\Comparator\Factory::getInstance()->register(new Flow\ETL\Tests\Comparator\RowsComparator()); SebastianBergmann\Comparator\Factory::getInstance()->register(new Flow\ETL\Tests\Comparator\ColumnComparator()); -SebastianBergmann\Comparator\Factory::getInstance()->register(new Flow\ETL\Tests\Comparator\RowComparator()); diff --git a/documentation/components/core/building-blocks.md b/documentation/components/core/building-blocks.md index 512fd0136b..f796b33abb 100644 --- a/documentation/components/core/building-blocks.md +++ b/documentation/components/core/building-blocks.md @@ -4,9 +4,8 @@ Columns of the [Data Frame](/documentation/components/core/core.md) are described by the [Schema](/src/core/etl/src/Flow/ETL/Schema.php) - it owns their names, order, types and nullability. -A [Row](/src/core/etl/src/Flow/ETL/Row.php) carries the values for one record, keyed by column name. -A group of Rows is called `Rows`, represented by the [Rows](/src/core/etl/src/Flow/ETL/Rows.php) -class, and every `Rows` carries the one `Schema` that describes it. +A batch of records is represented by the [Rows](/src/core/etl/src/Flow/ETL/Rows.php) class: one column per +schema definition, and every `Rows` carries the one `Schema` that describes it. Let's look at the following example: diff --git a/documentation/components/core/constraints.md b/documentation/components/core/constraints.md index ad3a821c4f..25d3a9e998 100644 --- a/documentation/components/core/constraints.md +++ b/documentation/components/core/constraints.md @@ -49,26 +49,31 @@ You can implement custom constraints by creating classes that implement the `Con ```php get('age')->value(); - return $age >= $this->minAge && $age <= $this->maxAge; + foreach ($rows->column('age')->values() as $i => $age) { + if ($age < $this->minAge || $age > $this->maxAge) { + return $i; + } + } + + return null; } - + public function toString(): string { return "Age must be between {$this->minAge} and {$this->maxAge}"; } - - public function violation(Row $row): string + + public function violation(Rows $rows, int $index): string { - return "Age {$row->get('age')->value()} is outside allowed range"; + return "Age {$rows->column('age')->value($index)} is outside allowed range"; } } ``` \ No newline at end of file diff --git a/documentation/components/core/data-retrieval.md b/documentation/components/core/data-retrieval.md index 0a86fa49ff..f01f4a87f7 100644 --- a/documentation/components/core/data-retrieval.md +++ b/documentation/components/core/data-retrieval.md @@ -23,7 +23,7 @@ $dataFrame = data_frame()->read(from_array($largeDataset)); foreach ($dataFrame->get() as $rows) { echo "Processing batch of " . $rows->count() . " rows\n"; // Process each batch - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { // Process individual row } } diff --git a/documentation/components/core/error-handling.md b/documentation/components/core/error-handling.md index d4c405296d..3a3bec58d9 100644 --- a/documentation/components/core/error-handling.md +++ b/documentation/components/core/error-handling.md @@ -90,26 +90,29 @@ For fine-grained error handling during row processing operations: read($unreliableDataExtractor) - ->forEach(function(Row $row) use (&$successCount, &$errorCount) { - try { - validateAndProcess($row); - $successCount++; - } catch (InvalidArgumentException $e) { - logInvalidRow($row, $e->getMessage()); - $errorCount++; - } catch (Exception $e) { - logGeneralError($row, $e); - $errorCount++; + ->forEach(function(Rows $rows) use (&$successCount, &$errorCount) { + foreach ($rows->toArray() as $row) { + try { + validateAndProcess($row); + $successCount++; + } catch (InvalidArgumentException $e) { + logInvalidRow($row, $e->getMessage()); + $errorCount++; + } catch (Exception $e) { + logGeneralError($row, $e); + $errorCount++; + } } }); diff --git a/documentation/components/core/filter.md b/documentation/components/core/filter.md index 52df5d6767..1e6a3e82c1 100644 --- a/documentation/components/core/filter.md +++ b/documentation/components/core/filter.md @@ -20,27 +20,61 @@ data_frame() ->run(); ``` -## Complex Row-level Filtering +## Custom Filter Functions -For advanced filtering that requires custom business logic, you can use callback functions: +Business logic the built-in functions do not cover goes into a `ScalarFunction` that returns a boolean column: ```php amount, $this->type]; + } + + public function withChildren(array $children): static + { + return new self($children[0], $children[1]); + } + + public function returns(): Type + { + return type_boolean(); + } + + public function eval(Rows $rows, FlowContext $context): Column + { + $amounts = (new Parameter($this->amount))->asNumbers($rows, $context); + $types = (new Parameter($this->type))->asStrings($rows, $context); + $results = []; + + foreach ($amounts as $i => $amount) { + $results[] = $amount > 1000 && $types[$i] === 'purchase'; + } + + return (new ResultColumn())->of($this, $results); + } +} data_frame() ->read($transactionExtractor) - ->filter(function(Row $row): bool { - $amount = $row->get('amount')->value(); - $type = $row->get('type')->value(); - $date = $row->get('date')->value(); - - // Complex business logic - return $amount > 1000 - && $type === 'purchase' - && $date > new DateTime('-30 days'); - }) + ->filter(new HighValuePurchase(ref('amount'), ref('type'))) ->write($highValueTransactionLoader) ->run(); ``` diff --git a/documentation/components/core/group-by.md b/documentation/components/core/group-by.md index 3412d5681e..31ff4d67ef 100644 --- a/documentation/components/core/group-by.md +++ b/documentation/components/core/group-by.md @@ -60,7 +60,9 @@ algorithm: ``` The algorithm is configured through `config_builder()->groupBy(hash_group_by())` - all its options -live on the `hash_group_by()` builder: +live on the `hash_group_by()` builder. While the process is under `memoryLimit()` (the same default as the join and +the sort) the input aggregates in one pass and nothing is written; past it the rest of the stream is partitioned into +buckets of the storage, in frames of `batchSize` rows: ```php groupBy( hash_group_by() - ->bucketsCount(64) // number of buckets (default 64) - ->batchSize(1000) // rows per batch when reading buckets back (default 1000) - ->storage(new MemoryBuckets()) // keep buckets in memory instead of on disk + ->memoryLimit(Unit::fromMb(512)) // process memory past which buckets go to the storage + ->bucketsCount(64) // number of buckets (default 64) + ->batchSize(1000) // rows per bucket frame and per batch read back (default 1000) + ->storage(new MemoryBuckets()) // keep buckets in memory instead of on disk ) ) ->read(from_parquet('orders.parquet')) @@ -80,9 +83,6 @@ data_frame( ->run(); ``` -> While rows are partitioned, each spilled bucket is announced downstream as a single metadata row -> (`BucketShape`: `_bucket_id`, `_bucket_total_rows`). Those rows are an internal pipeline detail consumed -> by the aggregation processor - they never appear in the grouped output. ### Spill column pruning diff --git a/documentation/components/core/join.md b/documentation/components/core/join.md index 32cfd74263..77dd80e784 100644 --- a/documentation/components/core/join.md +++ b/documentation/components/core/join.md @@ -66,8 +66,10 @@ external sort - and the configured implementation decides how the join executes: rebuilt per row too. The join algorithm is configured through `config_builder()->join(hash_join())` - all its options live on the -`hash_join()` builder; any storage implementing `ResidentBucketsStorage` (like `MemoryBuckets`) -enables the streaming, order-preserving execution: +`hash_join()` builder. While the process stays under `memoryLimit()` the right side is held in memory and the left +side streams through in its own order; past it, both sides are partitioned into buckets of the storage. The limit +defaults to `FLOW_MAX_MEMORY`, otherwise 70% of PHP's `memory_limit` (1 GiB when it is `-1`), and is compared with the +whole process, so a join and a sort in one pipeline stay under it together: ```php join( hash_join() - ->storage(new MemoryBuckets()) // right side fits in memory, keep left row order - ->bucketsCount(64) // number of disk buckets - ->batchSize(1000) // rows per batch when reading buckets back + ->memoryLimit(Unit::fromMb(512)) // process memory past which rows go to the storage + ->storage(new MemoryBuckets()) // or FilesystemBuckets (default) + ->bucketsCount(64) // number of buckets + ->batchSize(1000) // rows per bucket frame and per batch read back ) ) ->read(from_parquet('orders.parquet')) @@ -89,9 +92,6 @@ data_frame( ->run(); ``` -> While rows are partitioned, each spilled bucket is announced downstream as a single metadata row -> (`BucketShape`: `_bucket_id`, `_bucket_total_rows`). Those rows are an internal pipeline detail consumed -> by the join processor - they never appear in the joined output. ## Example diff --git a/documentation/components/core/sort.md b/documentation/components/core/sort.md index c2934721b3..d9191bc21c 100644 --- a/documentation/components/core/sort.md +++ b/documentation/components/core/sort.md @@ -2,15 +2,49 @@ [DOC_LINK:/documentation/components/core/core.md] +## Order + +Nulls sort first ascending and last descending, NaN after every other number, strings by bytes; rows with equal keys +keep their input order. Both algorithms below produce the same order. + +```php +read(from_array([['code' => '9'], ['code' => null], ['code' => '10']])) + ->sortBy([ref('code')->asc()]) // null, '10', '9' + ->run(); +``` + +Each reference can move its nulls to the other end: + +```php +read(from_array([['code' => '9'], ['code' => null], ['code' => '10']])) + ->sortBy([ref('code')->asc(NullsOrder::LAST)]) // '10', '9', null + ->run(); + +data_frame() + ->read(from_array([['code' => '9'], ['code' => null], ['code' => '10']])) + ->sortBy([ref('code')->desc(NullsOrder::FIRST)]) // null, '9', '10' + ->run(); +``` + ## Sort Algorithm The sort algorithm is configured through `config_builder()->sort()` - all options live on the algorithm's own builder: -- `external_sort()` - **default**; buffers rows in memory, sorts them and spills each sorted run as a bucket through a - `BucketsStorage` (the same abstraction used by +- `external_sort()` - **default**; sorts in memory while the buffered rows stay under its memory limit. Past the limit + it spills each sorted run as a bucket through a `BucketsStorage` (the same abstraction used by [join](/documentation/components/core/join.md) and [group by](/documentation/components/core/group-by.md)), then k-way merges the runs back into one sorted stream. - Memory usage is bounded by one run. + The memory limit defaults to `FLOW_MAX_MEMORY` when set, otherwise 70% of PHP's `memory_limit` (1 GiB when + `memory_limit` is `-1`), and is compared with the whole process - a sort and a join in one pipeline stay under it + together. - `memory_sort()` - buffers the whole dataset and sorts it in one pass; fastest, but everything must fit in RAM. It has no options. @@ -29,7 +63,7 @@ data_frame( | Buckets storage | Behavior | |-----------------------------------|----------------------------------------------------------------------------------------------| -| `FilesystemBuckets` - **Default** | Sorted runs are spilled to disk (Floe files). Memory usage is bounded by one run. | +| `FilesystemBuckets` - **Default** | Sorted runs are spilled to disk (Floe files). | | `MemoryBuckets` | Runs are kept in memory - prefer `memory_sort()` instead, it sorts once and skips the merge. | | `PSRCacheBuckets` | Runs are spilled into any PSR-16 cache. | @@ -40,9 +74,9 @@ data_frame( config_builder() ->sort( external_sort() - ->runSize(10_000) // rows buffered and sorted in memory before spilled as one run - ->bucketsCount(100) // how many runs are merged at once (merge fan-in) - ->batchSize(1000) // rows per spill/output batch + ->memoryLimit(Unit::fromMb(256)) // process memory past which sorted runs are spilled + ->bucketsCount(100) // how many runs are merged at once (merge fan-in) + ->batchSize(1000) // rows per output batch ) ) ->read(from_parquet('orders.parquet')) @@ -51,7 +85,10 @@ data_frame( ``` The storage implementation is swapped with `external_sort()->storage(BucketsStorage $storage)`, which covers -both phases - the runs spilled during bucketing and the runs written while merging. +both phases - the sorted runs and the runs written while merging. + +`sortBy()` followed by `limit(n)` keeps only the top `n` rows while it reads. Past the same memory limit it hands +the rows it kept and the rest of the stream to the external sort, whose merge stops after `n` rows. ## Overriding the algorithm for one sort @@ -79,10 +116,6 @@ external_sort() ->mergeStorage(new FilesystemBuckets($fs, path('/tmp/merge'))); // merged runs only ``` -> While runs are spilled, each bucket is announced downstream as a single metadata row -> (`BucketShape`: `_bucket_id`, `_bucket_total_rows`). Those rows are an internal pipeline detail consumed -> by the merge processor - they never appear in the sorted output. - ## Example ```php diff --git a/documentation/introduction.md b/documentation/introduction.md index 0004128a0b..ab8b15453d 100644 --- a/documentation/introduction.md +++ b/documentation/introduction.md @@ -50,7 +50,7 @@ Every Flow pipeline has three stages: - **Load** - `->write(...)` streams the result into a sink; `->run()` executes the whole thing. -Data moves through the pipeline as **DataFrame → Rows → Row**. Every `Rows` +Data moves through the pipeline as **DataFrame → Rows** batches of columns. Every `Rows` batch carries the schema that types its columns. ## Where to go from here diff --git a/documentation/upgrading.md b/documentation/upgrading.md index f7a203b564..c788cf3a89 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -709,6 +709,155 @@ Project with `from_parquet(..., columns: [...])`. Change a type after reading, e | `CSVFileReader::batches(SourceFile, int): Generator>` returning the header | `batches(SourceFile, Schema, int, Backend): Generator`, no return value | | `RustCSVReaderNative::next(): list` | `list>` | | - | `RustCSVReaderNative::nextColumns(Schema, int): ?Rows` | + +### 69) `flow-php/etl` - `Row` removed, `Rows` is a columnar batch + +| Before | After | +|---------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------| +| `foreach ($df->fetch() as $row) { $row->get('x'); }` | `foreach ($df->fetch()->toArray() as $row) { $row['x']; }` | +| `$rows->first()->get('x')`, `$rows[0]->get('x')` | `$rows->column('x')->value(0)`, `$rows->values(0)['x']` | +| `$rows->first()->toArray()` | `$rows->toArray()[0]` | +| `Rows::of($schema)` | `Rows::empty($schema)` | +| `Rows::of($schema, ...$row)`, `rows($schema, ...$row)`, `$rows->add(...$row)` | `$rows->gather([...])`, `$rows->concat($other->matchTo($rows->schema()))` | +| `Rows` implements `ArrayAccess`, `IteratorAggregate` | `Countable` only | +| `Rows::all()`, `first()`, `last()`, `row()`, `offsetGet()` | removed - `toArray()`, `values(int)`, `column(string)`, `slice()`, `gather()` | +| `Rows::values(int)` outside the batch - a PHP warning and nulls, or the extension's `row N is outside [0, M)` | `InvalidArgumentException`: `Row N does not exist in a batch of M rows` | +| `Rows::unique(Comparator)`, `Row\Comparator`, `NativeComparator` | `Rows::unique()` - value equality per column | +| `array_to_row(array $data, Schema, Backend, $partitions)` | `array_to_rows([$data], Schema, Backend)` | +| `SerializedPayloadDecoder::decode(Row): Row` | `decode(Rows, int): Rows` - no payload is a one-row batch without columns | +| `Formatter\ASCII\Body::rows()` | `count()`, `value(string, int)` | + +### 70) `flow-php/etl` - `ScalarFunction` evaluates a batch + +| Before | After | +|-------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------| +| `ScalarFunction::eval(Row, FlowContext): mixed` | `eval(Rows, FlowContext): Column` - one value per row, built by `ResultColumn` | +| `ExpandResults::eval(Row): array`, `UnpackResults::eval(Row): array` | marker interfaces - `eval(Rows): Column` returns a list (expand) or structure (unpack) column | +| `Parameter::{as, asArray, asBoolean, asEnum, asFloat, asInstanceOf, asInt}(Row, …)` | `{asTypes, asArrays, asBooleans, asEnums, asFloats, asInstancesOf, asInts}(Rows, …)` - one list per batch | +| `Parameter::{asListOfObjects, asNumber, asObject, asString}(Row, …)` | `{asListsOfObjects, asNumbers, asObjects, asStrings}(Rows, …)` | +| `Parameter::eval(Row)`, `asValue(Row)` | `values(Rows, FlowContext)`, `column(Rows, FlowContext)` | +| `$function->eval($rows, $context)` on an unresolved tree | `InvalidLogicException` - `(new ReferenceResolver())->resolve($function, $rows->schema())->eval($rows, $context)` | + +Before: + +```php +public function eval(Row $row, FlowContext $context): ?string +{ + $value = (new Parameter($this->value))->asString($row, $context); + + return $value === null ? null : strtoupper($value); +} +``` + +After: + +```php +public function eval(Rows $rows, FlowContext $context): Column +{ + $results = []; + + foreach ((new Parameter($this->value))->asStrings($rows, $context) as $value) { + $results[] = $value === null ? null : strtoupper($value); + } + + return (new ResultColumn())->of($this, $results); +} +``` + +### 71) `flow-php/etl` - float arithmetic follows IEEE 754 + +| Before | After | +|------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------| +| `ref('a')->multiply(lit(3))` with `a = 0.1` - `0.3` | `0.30000000000000004`; `ref('a')->multiply(lit(3), exact: true)` - `0.3` | +| `plus()`, `minus()`, `power()` - decimal arithmetic | IEEE 754; `exact: true` keeps decimal arithmetic | +| an integer result past `PHP_INT_MAX` - `Brick\Math\Exception\IntegerOverflowException` | `EvaluationException`: `Plus function integer overflow (row N)` | +| `power()` of an integer with a negative exponent | `EvaluationException`: `Power function of an integer requires a non-negative exponent (row N)` | +| `average(ref('amount'))` - decimal sum (`Calculator` per value), then rounded to `scale` | IEEE sum with Neumaier compensation, then the same rounding; `average(ref('amount'), exact: true)` keeps the decimal sum | +| `sum(ref('amount'))` (default `exact: false`) - plain IEEE addition, `0.1` ten times: `0.9999999999999999` | compensated IEEE addition: `1.0` | +| `RunningSum::add(float\|int $sum, $value, bool $exact): float\|int` | stateful: `add($value, bool $exact): void`, `value(): float\|int`, `merge(RunningSum, bool $exact)` | + +### 72) `flow-php/etl` - function errors carry the batch row + +| Before | After | +|----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------| +| an exception thrown by a function reaches the caller as-is | `Flow\ETL\Exception\EvaluationException` (extends `InvalidArgumentException`), message `… (row N)`, the original as `getPrevious()` | +| `catch (SomeSpecificException $e)` around `withEntry()` / `filter()` | `catch (EvaluationException $e)` and read `$e->getPrevious()` | + +### 73) `flow-php/etl` - uuid, json, enum, xml, html and date/time values compare by value + +| Before | After | +|-------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------| +| `equals()`, `same()`, `isIn()`, join `Identical`, `batchBy()` over these types - always false / one batch per row | value equality | +| json values | compare by their stored text - `{"a":1,"b":2}` and `{"b":2,"a":1}` are not equal | + +### 74) `flow-php/etl` - `array_keys_style_convert()` declares the converted nested shape + +| Before | After | +|---------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------| +| `returns()` renames the top-level keys only; a nested conversion stored with `withEntry()` failed | `returns()` renames structure fields at every level (structures, lists, maps); key collisions are refused at every level | + +### 75) `flow-php/etl` - extension points take a batch + +| Before | After | +|-----------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------| +| `AggregatingFunction::aggregate(Row, FlowContext)` | `aggregate(Rows, list $indices, FlowContext)` + `merge(AggregatingFunction, FlowContext)` | +| `Join\Comparison::compare(Row, Row): bool` | `compare(Rows $left, Rows $right): list` - pairwise | +| `Constraint::isSatisfiedBy(Row, Schema)`, `violation(Row, Schema)` | `firstViolation(Rows): ?int`, `violation(Rows, int)` | +| `FrameAccumulator::accumulate(Row)` | `accumulate(Rows, int)` | +| `WindowContext::row()` | removed - `WindowContext(int, Rows, WindowFrame, FlowContext)` | +| `PeerComparator::arePeers(Row, Row, Schema)` | `arePeers(Rows, int, int)` | +| `Dataset\Statistics\Columns::add(Definition, mixed)` | `add(Definition, Column)` | +| `new KWayMerge(References, Backend, int)`, `new Joiner(Expression, Join, Backend, int)` | `new KWayMerge(References, int)`, `new Joiner(Expression, Join, int)` - output is gathered from the input columns | + +### 76) `flow-php/etl` - one sort order: nulls smallest, strings by bytes + +| Before | After | +|---------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------| +| `sortBy(ref('code')->asc())` over `'9', '10', '100'` - `'9', '10', '100'` (numeric when every value looked numeric) | `'10', '100', '9'` - strings always compare by bytes | +| `sortBy(ref('v')->asc())` over `3, null, 1` - unsorted (a null compared equal to every value) | `null, 1, 3` - nulls first ascending, last descending; descending is the exact reverse of ascending | +| NaN - no defined position | after every other value, equal to NaN; `-0.0` equals `0.0` | +| external sort (spilled runs) could order differently from the in-memory sort | both, `constraint_sorted_by()` and window peers use the same order | +| `Flow\ETL\Sort\ValuesSorter`, `Sort\Merge\RowsMinHeap`, `Sort\Merge\ComparableBucketRow` | removed - `Flow\ETL\Sort\RowOrder` | +| `new BucketCursor(Generator, References)`, `keys(): list`, `next()` | `new BucketCursor(Generator, RowOrder)`, `keys(): list`, `advance(int)` | +| - | `ref('x')->asc(NullsOrder::LAST)`, `ref('x')->desc(NullsOrder::FIRST)` move nulls to the other end | +| a custom `Reference` implementation | adds `nulls(): NullsOrder` | + +### 77) `flow-php/etl` - spilling steps stop at a memory limit, not a row count + +| Before | After | +|----------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `external_sort()->runSize(int)` - rows per sorted run, default `10000` | `external_sort()->memoryLimit(Unit)`; data under it sorts in memory without spilling | +| - | `hash_join()->memoryLimit(Unit)`, `hash_group_by()->memoryLimit(Unit)`, `hash_repartition()->memoryLimit(Unit)` | +| - | every limit defaults to `Config\MemoryLimit::default()`: `FLOW_MAX_MEMORY`, otherwise 70% of `memory_limit`, 1 GiB when `memory_limit` is `-1` | +| - | a limit is compared with the whole process (`memory_get_usage()` + the backend's native memory), not with the step's own buffer - a sort and a join in one pipeline stay under it together | +| `hash_join()` with a disk storage partitioned both sides into buckets | the right side stays in memory under the limit and the left side streams in its own order; past it both sides are partitioned | +| `groupBy()` / window partitions always hash-partitioned their input into buckets | under the limit a group-by aggregates in one pass and a window groups its partitions in memory - no bucket is written; past it the rest of the stream is partitioned (group-by merges the groups aggregated before the limit) | +| group-by / repartition / join wrote one bucket frame per bucket per input batch | buckets stay in memory under the limit; past it every frame holds `batchSize` rows | +| `GroupBySteps::of()` / `RepartitionSteps::of()` - `[BucketingProcessor, GroupByAggregationProcessor]` / `[BucketingProcessor, RepartitionProcessor]` | `[GroupByAggregationProcessor]` / `[RepartitionProcessor]`; both take `HashBucketing` and `Unit $memoryLimit`; `GroupBy\BucketAggregation` removed | +| `new ExternalSortConfig($bucketing, ?BucketsStorage $merge = null, int $runSize)` | `new ExternalSortConfig($bucketing, Unit $memoryLimit, ?BucketsStorage $merge = null)` | +| `new HashJoinConfig($bucketing)`, `new HashGroupByConfig($bucketing)`, `new HashRepartitionConfig($bucketing)` | `new …Config($bucketing, Unit $memoryLimit)` | +| `new HashJoinProcessor($right, $executor, $on, $type, $left, $right, $random, $bucketsCount, $batchSize)` | `new HashJoinProcessor($right, $executor, $on, $type, $left, $right, $random, Unit $memoryLimit, $bucketsCount, $batchSize)` | +| `new MergeSortProcessor(References, Buckets, Buckets, RandomValueGenerator, int, int)` | `new MergeSortProcessor(ExternalSort)` | +| `SortSteps::of()` - `[BucketingProcessor, MergeSortProcessor]` for the external sort | `[MergeSortProcessor]`; `SortSteps::external(): ?ExternalSort` | +| `Flow\ETL\Bucketing\SortedRunBucketing` | removed - `Flow\ETL\Sort\ExternalSort` | +| `Flow\ETL\Processor\BucketingProcessor`, `Flow\ETL\Bucketing\BucketingStrategy`, `Flow\ETL\Bucketing\BucketShape`, `Bucket::schema()`, `Bucket::toRow()` | removed - sort, join, group-by and repartition partition inside their own step | +| `sortBy()->limit(n)` over the external sort became a top-n only when `n <= runSize` | always a top-n; past the memory limit it hands its kept rows and the rest of the stream to the external sort, whose merge stops after `n` rows | +| `new TopNRewrite(FlowContext)` | `new TopNRewrite()` | +| `new TopNProcessor(References, int, ?Schema)` | `new TopNProcessor(References, int, ?ExternalSort $fallback = null, ?Schema)` | +| `new Plan\Node\TopN(Node, References, int)` | `new TopN(Node, References, int, ?SortAlgorithmBuilder $algorithm = null)` | +| explain: `Storage: FilesystemBuckets` | adds `Memory: N MB` under the storage of a sort, join, group-by and repartition step | + +### 78) `flow-php/etl` - `sum(exact:)` is a bool; `batched_by()`, `string_agg()` and `pivot()` follow the one order + +| Before | After | +|---------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------| +| `sum(ref('a'), exact: ref('is_exact'))` - exactness chosen per row | `sum(ref('a'), exact: true)` - one `bool` for the aggregate, as `average()` and `plus/minus/multiply/power` | +| `sum(…, exact: ScalarFunction)` disabled spill column pruning (`references()` was `null`) | `sum()` always enumerates its reference; a custom `AggregatingFunction` may still return `null` | +| `batched_by(from_…, 'at')` - equal datetimes / uuids split into one batch per row, a `null` value joined the next group | value equality, as `batchBy()`; nulls are a group of their own | +| `string_agg(ref('code'), ',', SortOrder::ASC)` over `'9', '10', '100'` - `9,10,100` (numeric-looking strings numerically) | `10,100,9` - strings by bytes, as `sortBy()` | +| `discover_pivot_values()` over `'9', '10', '100'` - columns `9, 10, 100` | `10, 100, 9`; integer pivot values stay numeric | +| `->stringMatch()` / `->stringMatchAll()` turned a PHP `\Error` into an exception `optional()` swallowed | an `\Error` propagates; `->jsonDecode()`, `cast()`, `->arrayPathExists()`, `->stringMatch*()` errors keep their cause as `getPrevious()` | + --- ## Upgrading from 0.43.x to 0.44.x diff --git a/shell.nix b/shell.nix index 67ef6dbc87..15c1abff0b 100644 --- a/shell.nix +++ b/shell.nix @@ -150,6 +150,10 @@ pkgs.mkShell { export PHPIZE="${php.unwrapped.dev}/bin/phpize" ''} + if [ -f "$PWD/.nix/blackfire/blackfire.env" ]; then + set -a; . "$PWD/.nix/blackfire/blackfire.env"; set +a + fi + eval "$(${pkgs.starship}/bin/starship init bash)" clear 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 f50bcc1f35..f4b7e8e0d6 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 @@ -37,7 +37,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - yield Rows::of(new Schema()); + yield Rows::empty(new Schema()); } public function schema(): Schema diff --git a/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Integration/ChartJSLoaderTest.php b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Integration/ChartJSLoaderTest.php index 8edec2bf82..b5972261e6 100644 --- a/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Integration/ChartJSLoaderTest.php +++ b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Integration/ChartJSLoaderTest.php @@ -519,8 +519,8 @@ public function test_loading_data_to_pie_chart(): void 'datasets' => [ [ 'data' => [ - 69876.76000000001, - 32555.319999999996, + 69876.76, + 32555.32, 13853.8, 7854.33, 10853.0, diff --git a/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Integration/Output/pie_chart.html b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Integration/Output/pie_chart.html index f0a5441382..d8b88e553b 100644 --- a/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Integration/Output/pie_chart.html +++ b/src/adapter/etl-adapter-chartjs/tests/Flow/ETL/Adapter/ChartJS/Tests/Integration/Output/pie_chart.html @@ -1 +1 @@ - Flow PHP - ChartJS
      \ No newline at end of file + Flow PHP - ChartJS
      \ No newline at end of file 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 9003926a92..b856293e3e 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 @@ -13,7 +13,7 @@ use Flow\ETL\Exception\SchemaDefinitionNotUniqueException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Extractor\Signal; -use Flow\ETL\Row; +use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Double\CountingFilesystem; @@ -79,7 +79,7 @@ public function test_a_hive_null_partition_value_reads_back_as_null(): void $rows = df()->read(from_csv($dir . '/*/*.csv')->withSchema(schema(int_schema('id'))))->fetch(); - $years = array_map(static fn(Row $row): mixed => $row->get('year'), $rows->all()); + $years = $rows->column('year')->values(); sort($years); static::assertSame([null, '2024'], $years); @@ -93,7 +93,7 @@ public function test_declared_partition_types_reach_the_rows(): void foreach ($extractor->extract(flow_context(config())) as $rows) { static::assertEquals($extractor->schema(), $rows->schema()); - static::assertSame(1, $rows->first()->get('group')); + static::assertSame(1, $rows->column('group')->value(0)); return; } @@ -108,7 +108,7 @@ public function test_partition_columns_are_typed_without_a_declared_schema(): vo ); foreach ($extractor->extract(flow_context(config())) as $rows) { - static::assertSame(1, $rows->first()->get('group')); + static::assertSame(1, $rows->column('group')->value(0)); return; } @@ -408,8 +408,8 @@ public function test_union_by_name_reads_diverging_columns_as_one_wider_schema() $rows = []; foreach ($extractor->extract(flow_context(config())) as $batch) { - foreach ($batch as $row) { - $rows[] = $row->toArray(); + foreach ($batch->toArray() as $row) { + $rows[] = $row; } } @@ -537,7 +537,7 @@ public function test_partition_columns_are_not_typed_by_the_sample(): void static::assertSame('string', $extractor->schema()->get('group')->type()->toString()); foreach ($extractor->extract(flow_context(config())) as $rows) { - static::assertSame('1', $rows->first()->toArray()['group']); + static::assertSame('1', $rows->toArray()[0]['group']); break; } @@ -601,7 +601,7 @@ public function test_without_a_declared_schema_the_metadata_column_still_overwri static::assertStringEndsWith( 'metadata_column_collision.csv', - type_string()->assert($rows->first()->get('_input_file_uri')), + type_string()->assert($rows->column('_input_file_uri')->value(0)), ); } @@ -824,7 +824,7 @@ public function test_extracting_csv_files_with_header(): void $rows = df()->read(from_csv($path))->fetch(); - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'Year', @@ -838,7 +838,7 @@ public function test_extracting_csv_files_with_header(): void 'Value', 'Industry_code_ANZSIC06', ], - array_keys($row->toArray()), + array_keys($row), ); } @@ -851,7 +851,7 @@ public function test_extracting_csv_files_with_schema(): void $rows = df()->read(from_csv($path, schema: $schema = df()->read(from_csv($path))->schema()))->fetch(); - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'Year', @@ -865,7 +865,7 @@ public function test_extracting_csv_files_with_schema(): void 'Value', 'Industry_code_ANZSIC06', ], - array_keys($row->toArray()), + array_keys($row), ); } @@ -898,10 +898,10 @@ public function test_extracting_csv_files_without_header(): void $total = 0; foreach ($extractor->extract(flow_context(config())) as $rows) { - foreach ($rows->all() as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( ['e00', 'e01', 'e02', 'e03', 'e04', 'e05', 'e06', 'e07', 'e08', 'e09'], - array_keys($row->toArray()), + array_keys($row), ); } $total += $rows->count(); @@ -924,8 +924,8 @@ public function test_extracting_csv_with_more_columns_than_headers(): void $total = 0; foreach ($extractor->extract(flow_context(config())) as $rows) { - foreach ($rows->all() as $row) { - static::assertSame(['id', 'name'], array_keys($row->toArray())); + foreach ($rows->toArray() as $row) { + static::assertSame(['id', 'name'], array_keys($row)); } $total += $rows->count(); } @@ -940,8 +940,8 @@ public function test_extracting_csv_with_more_headers_than_columns(): void $total = 0; foreach ($extractor->extract(flow_context(config())) as $rows) { - foreach ($rows->all() as $row) { - static::assertSame(['id', 'name', 'active'], array_keys($row->toArray())); + foreach ($rows->toArray() as $row) { + static::assertSame(['id', 'name', 'active'], array_keys($row)); } $total += $rows->count(); } @@ -986,14 +986,13 @@ public function test_extracting_csv_with_multiline_strings(): void static::assertSame(1, $rows->count()); - $row = $rows->first(); - static::assertSame('ABBA', $row->get('artist')); - static::assertSame("Ahe's My Kind Of Girl", $row->get('song')); - static::assertSame('/a/abba/ahes+my+kind+of+girl_20598417.html', $row->get('link')); + static::assertSame('ABBA', $rows->column('artist')->value(0)); + static::assertSame("Ahe's My Kind Of Girl", $rows->column('song')->value(0)); + static::assertSame('/a/abba/ahes+my+kind+of+girl_20598417.html', $rows->column('link')->value(0)); $expectedText = "Look at her face, it's a wonderful face \nAnd it means something special to me \nLook at the way that she smiles when she sees me \nHow lucky can one fellow be? \n \nShe's just my kind of girl, she makes me feel fine \nWho could ever believe that she could be mine? \nShe's just my kind of girl, without her I'm blue \nAnd if she ever leaves me what could I do, what could I do? \n \nAnd when we go for a walk in the park \nAnd she holds me and squeezes my hand \nWe'll go on walking for hours and talking \nAbout all the things that we plan \n \nShe's just my kind of girl, she makes me feel fine \nWho could ever believe that she could be mine? \nShe's just my kind of girl, without her I'm blue \nAnd if she ever leaves me what could I do, what could I do?\n\n"; - static::assertSame($expectedText, $row->get('text')); + static::assertSame($expectedText, $rows->column('text')->value(0)); } public function test_limit(): void @@ -1018,7 +1017,7 @@ public function test_schema_and_extract_agree_on_partition_columns(): void static::assertSame( ['id', 'value', 'group'], - array_map(static fn(Row\Reference $ref): string => $ref->name(), $extractor->schema()->references()->all()), + array_map(static fn(Reference $ref): string => $ref->name(), $extractor->schema()->references()->all()), ); foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { @@ -1036,7 +1035,7 @@ public function test_schema_lists_the_path_once_per_instance(): void static::assertEquals($extractor->schema(), $extractor->schema()); static::assertSame( ['id', 'value', 'group'], - array_map(static fn(Row\Reference $ref): string => $ref->name(), $extractor->schema()->references()->all()), + array_map(static fn(Reference $ref): string => $ref->name(), $extractor->schema()->references()->all()), ); } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTypedColumnsTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTypedColumnsTest.php index 1463b761af..39177429c5 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTypedColumnsTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVExtractorTypedColumnsTest.php @@ -31,8 +31,8 @@ public function test_hydrates_typed_columns_with_empty_to_null_and_input_uri(): $actual = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } @@ -56,8 +56,8 @@ public function test_reads_partitioned_files_with_schema_typed_partition_values( $actual = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } @@ -88,8 +88,8 @@ public function test_appends_partition_columns_absent_from_the_schema(): void $actual = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } 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 624a5144e9..23f43c874d 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 @@ -181,8 +181,8 @@ public function test_naive_datetime_text_reads_as_utc_under_non_utc_default(): v foreach ((new DbalQueryExtractor(InMemorySqlite::connection(), "SELECT '2026-01-01 14:30:00' AS at")) ->withSchema(schema(datetime_schema('at'))) ->extract(flow_context()) as $batch) { - foreach ($batch as $row) { - $values[] = type_datetime()->assert($row->get('at'))->format('Y-m-d H:i:s e'); + foreach ($batch->toArray() as $row) { + $values[] = type_datetime()->assert($row['at'])->format('Y-m-d H:i:s e'); } } diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Function/IsValidExcelSheetName.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Function/IsValidExcelSheetName.php index 48505032da..f5cb3fbf5b 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Function/IsValidExcelSheetName.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Function/IsValidExcelSheetName.php @@ -5,12 +5,14 @@ namespace Flow\ETL\Adapter\Excel\Function; use Flow\ETL\Adapter\Excel\Sheet\SheetNameAssertion; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Function\FunctionTree; use Flow\ETL\Function\Parameter; use Flow\ETL\Function\ResolvesFromChildren; use Flow\ETL\Function\ScalarFunction; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -53,14 +55,14 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->sheetName->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $sheetName = (new Parameter($this->sheetName))->asString($row, $context); + $results = []; - if ($sheetName === null) { - return null; + foreach ((new Parameter($this->sheetName))->asStrings($rows, $context) as $sheetName) { + $results[] = $sheetName === null ? null : SheetNameAssertion::isValid($sheetName); } - return SheetNameAssertion::isValid($sheetName); + return (new ResultColumn())->of($this, $results); } } 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 4f8f6fc9a9..c86d46c612 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 @@ -348,8 +348,8 @@ public function test_every_batch_carries_the_inferred_schema(string $fixtureName static::assertEquals($extractor->schema(), $rows->schema()); $sizes[] = $rows->count(); - foreach ($rows as $row) { - $emails[] = $row->get('email'); + foreach ($rows->toArray() as $row) { + $emails[] = $row['email']; } } @@ -884,13 +884,16 @@ public function test_date_cell_in_a_zoned_column_is_converted(): void static::assertSame( '2024-01-03 11:30:00 Europe/Warsaw', type_datetime() - ->assert(df() - ->extract( - from_excel(ExcelFixtureContext::file('dates_mixed.xlsx')) - ->withSchema(schema(datetime_schema('d', zone: 'Europe/Warsaw'))), - ) - ->fetch() - ->all()[2]->get('d')) + ->assert( + df() + ->extract( + from_excel(ExcelFixtureContext::file('dates_mixed.xlsx')) + ->withSchema(schema(datetime_schema('d', zone: 'Europe/Warsaw'))), + ) + ->fetch() + ->column('d') + ->value(2), + ) ->format('Y-m-d H:i:s e'), ); } @@ -904,19 +907,25 @@ public function test_date_cells_read_as_utc_wall_clock_under_non_utc_default(): static::assertSame( '2024-01-03 10:30:00 UTC', type_datetime() - ->assert(df() - ->extract(from_excel(ExcelFixtureContext::file('dates_mixed.xlsx'))) - ->fetch() - ->all()[2]->get('d')) + ->assert( + df() + ->extract(from_excel(ExcelFixtureContext::file('dates_mixed.xlsx'))) + ->fetch() + ->column('d') + ->value(2), + ) ->format('Y-m-d H:i:s e'), ); static::assertSame( '2024-01-03 10:30:00 UTC', type_datetime() - ->assert(df() - ->extract(from_excel(ExcelFixtureContext::file('dates_mixed.ods'))) - ->fetch() - ->all()[1]->get('d')) + ->assert( + df() + ->extract(from_excel(ExcelFixtureContext::file('dates_mixed.ods'))) + ->fetch() + ->column('d') + ->value(1), + ) ->format('Y-m-d H:i:s e'), ); } finally { diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTypedColumnsTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTypedColumnsTest.php index cac412bb80..8e98e152c0 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTypedColumnsTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/ExcelExtractorTypedColumnsTest.php @@ -40,10 +40,7 @@ public function test_appends_input_file_uri_when_metadata_columns_are_enabled(): ->withMetadataColumns(true); foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - static::assertTrue($row->has('_input_file_uri')); - static::assertSame($path->uri(), $row->get('_input_file_uri')); - } + static::assertSame([$path->uri()], array_values(array_unique($rows->column('_input_file_uri')->values()))); } } } diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/Function/IsValidExcelSheetNameTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/Function/IsValidExcelSheetNameTest.php index bb8ec8747f..b2a1418a46 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/Function/IsValidExcelSheetNameTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/Function/IsValidExcelSheetNameTest.php @@ -4,11 +4,11 @@ namespace Flow\ETL\Adapter\Excel\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\Adapter\Excel\DSL\is_valid_excel_sheet_name; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -23,16 +23,21 @@ final class IsValidExcelSheetNameTest extends FlowTestCase #[TestWith(['Sheet?Name'])] public function test_invalid_excel_sheet_name(string $invalidNames): void { - static::assertFalse(is_valid_excel_sheet_name($invalidNames)->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval( + is_valid_excel_sheet_name($invalidNames), + [], + schema(), + )); } #[TestWith(['Sheet1'])] #[TestWith(['Excel Sheet'])] public function test_valid_excel_sheet_name(string $sheetName): void { - static::assertTrue( - is_valid_excel_sheet_name(ref('sheet_name')) - ->eval(array_to_row(['sheet_name' => $sheetName], schema(str_schema('sheet_name'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + is_valid_excel_sheet_name(ref('sheet_name')), + ['sheet_name' => $sheetName], + schema(str_schema('sheet_name')), + )); } } 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 57fdafba71..c2be75e2cc 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 @@ -260,7 +260,7 @@ public function test_every_batch_carries_the_inferred_schema(): void static::assertTrue($rows->schema()->isSame($extractor->schema())); } - $first = $batches[0]->first()->toArray(); + $first = $batches[0]->toArray()[0]; static::assertSame(1, $first['id']); static::assertSame(1.5, $first['price']); static::assertTrue($first['active']); diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTypedColumnsTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTypedColumnsTest.php index 27ef7789e9..634e774a52 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTypedColumnsTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Integration/GoogleSheetExtractorTypedColumnsTest.php @@ -34,8 +34,8 @@ public function test_appends_spread_sheet_id_and_sheet_name_to_the_schema_when_m $rows = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $batch) { - foreach ($batch as $row) { - $rows[] = $row->toArray(); + foreach ($batch->toArray() as $row) { + $rows[] = $row; } } @@ -74,8 +74,8 @@ public function test_infers_typed_rows(): void )), ); - foreach ($batch as $row) { - $rows[] = $row->toArray(); + foreach ($batch->toArray() as $row) { + $rows[] = $row; } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php index f245c58339..82f8963689 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php @@ -22,7 +22,6 @@ use PHPUnit\Framework\Attributes\DataProvider; use function array_sum; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\infer_schema; @@ -122,19 +121,12 @@ public function test_its_stop_fetching_data_if_processed_row_count_is_less_then_ $rows = ExtractedRows::of($extractor); static::assertCount(2, $rows); - static::assertEquals( - array_to_row( + static::assertSame( + [ ['header' => 'row1', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet'], - schema(str_schema('header'), str_schema('_spread_sheet_id'), str_schema('_sheet_name')), - ), - $rows->all()[0], - ); - static::assertEquals( - array_to_row( ['header' => 'row2', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet'], - schema(str_schema('header'), str_schema('_spread_sheet_id'), str_schema('_sheet_name')), - ), - $rows->all()[1], + ], + $rows->toArray(), ); } @@ -317,7 +309,7 @@ public function test_extract_seeds_every_batch_with_the_inferred_schema(): void foreach ($extractor->withBatchSize(2)->extract(flow_context()) as $rows) { static::assertTrue($rows->schema()->isSame($extractor->schema())); $sizes[] = $rows->count(); - $first ??= $rows->first()->toArray(); + $first ??= $rows->toArray()[0]; } static::assertLessThanOrEqual(2, max($sizes)); @@ -417,7 +409,7 @@ public function test_metadata_columns_keep_a_numeric_column_name(): void static::assertSame( ['3' => 'a', '7' => 'b', '_spread_sheet_id' => 'spread-id', '_sheet_name' => 'sheet'], - $rowsArray[0]->first()->toArray(), + $rowsArray[0]->toArray()[0], ); } @@ -470,7 +462,7 @@ public function test_empty_cells_are_null_by_default(): void ->extract(flow_context()), ); - static::assertNull($rowsArray[0]->first()->toArray()['name']); + static::assertNull($rowsArray[0]->toArray()[0]['name']); } public function test_empty_cells_stay_strings_when_asked(): void @@ -488,7 +480,7 @@ public function test_empty_cells_stay_strings_when_asked(): void ->extract(flow_context()), ); - static::assertSame('', $rowsArray[0]->first()->toArray()['name']); + static::assertSame('', $rowsArray[0]->toArray()[0]['name']); } public function test_a_value_past_the_sample_that_does_not_fit_is_refused(): void diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientDynamicExtractorTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientDynamicExtractorTest.php index b4eaa8f1a1..02c6a9dc9f 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientDynamicExtractorTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientDynamicExtractorTest.php @@ -87,7 +87,7 @@ public function create(?ResponseInterface $previousResponse = null): ?RequestInt // The row carries the body as raw text, so response_body holds one type whatever the // content type is; pagination reads the structured map through HttpDecoder::structuredBody(). $body = type_array()->assert(json_decode( - type_string()->assert($currentRows->first()->get('response_body')), + type_string()->assert($currentRows->column('response_body')->value(0)), true, 512, JSON_THROW_ON_ERROR, @@ -97,13 +97,13 @@ public function create(?ResponseInterface $previousResponse = null): ?RequestInt static::assertSame('flow-php', $body['login']); static::assertSame(73_495_297, $body['id']); - $responseHeaders = type_array()->assert($currentRows->first()->get('response_headers')); + $responseHeaders = type_array()->assert($currentRows->column('response_headers')->value(0)); static::assertSame(['GitHub.com'], $responseHeaders['Server']); - static::assertSame(200, $currentRows->first()->get('response_status_code')); - static::assertSame('1.1', $currentRows->first()->get('response_protocol_version')); - static::assertSame('OK', $currentRows->first()->get('response_reason_phrase')); - static::assertSame('https://api.github.com/orgs/flow-php', $currentRows->first()->get('request_uri')); - static::assertSame('GET', $currentRows->first()->get('request_method')); + static::assertSame(200, $currentRows->column('response_status_code')->value(0)); + static::assertSame('1.1', $currentRows->column('response_protocol_version')->value(0)); + static::assertSame('OK', $currentRows->column('response_reason_phrase')->value(0)); + static::assertSame('https://api.github.com/orgs/flow-php', $currentRows->column('request_uri')->value(0)); + static::assertSame('GET', $currentRows->column('request_method')->value(0)); } public function test_schema_is_the_fixed_http_exchange_shape(): void @@ -178,7 +178,7 @@ public function create(?ResponseInterface $previousResponse = null): ?RequestInt type_structure(['login' => type_string(), 'id' => type_integer()]), $rows->schema()->get('response_body')->type(), ); - static::assertSame(['login' => 'flow-php', 'id' => 73_495_297], $rows->first()->get('response_body')); + static::assertSame(['login' => 'flow-php', 'id' => 73_495_297], $rows->column('response_body')->value(0)); } public function test_extract_builds_through_the_config_backend(): void diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientExtractorBatchContractTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientExtractorBatchContractTest.php index ec2c345e8e..546b40da2b 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientExtractorBatchContractTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientExtractorBatchContractTest.php @@ -95,7 +95,7 @@ public function test_dynamic_extractor_yields_one_row_per_batch_and_every_exchan static::assertSame([1, 1], array_map(static fn(Rows $rows): int => $rows->count(), $batches)); static::assertSame( ['https://api.example.com/1', 'https://api.example.com/2'], - array_map(static fn(Rows $rows): mixed => $rows->first()->get('request_uri'), $batches), + array_map(static fn(Rows $rows): mixed => $rows->column('request_uri')->value(0), $batches), ); } @@ -122,7 +122,7 @@ public function test_paginated_extractor_yields_one_row_per_page_and_every_page( 'https://api.example.com/items?cursor=c2', 'https://api.example.com/items?cursor=c3', ], - array_map(static fn(Rows $rows): mixed => $rows->first()->get('request_uri'), $batches), + array_map(static fn(Rows $rows): mixed => $rows->column('request_uri')->value(0), $batches), ); } @@ -144,7 +144,7 @@ public function test_static_extractor_yields_one_row_per_batch_and_every_exchang static::assertSame([1, 1], array_map(static fn(Rows $rows): int => $rows->count(), $batches)); static::assertSame( ['https://api.example.com/1', 'https://api.example.com/2'], - array_map(static fn(Rows $rows): mixed => $rows->first()->get('request_uri'), $batches), + array_map(static fn(Rows $rows): mixed => $rows->column('request_uri')->value(0), $batches), ); } } diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientPaginatedExtractorTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientPaginatedExtractorTest.php index b5d38dc282..24883fddef 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientPaginatedExtractorTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientPaginatedExtractorTest.php @@ -385,7 +385,7 @@ public function test_schema_typed_response_body(): void type_structure(['login' => type_string(), 'id' => type_integer()]), $rows[0]->schema()->get('response_body')->type(), ); - static::assertSame(['login' => 'flow-php', 'id' => 73_495_297], $rows[0]->first()->get('response_body')); + static::assertSame(['login' => 'flow-php', 'id' => 73_495_297], $rows[0]->column('response_body')->value(0)); } public function test_schema_typed_response_body_with_missing_field(): void @@ -427,7 +427,7 @@ public function test_schema_typed_response_body_via_with_schema(): void type_structure(['login' => type_string(), 'id' => type_integer()]), $rows[0]->schema()->get('response_body')->type(), ); - static::assertSame(['login' => 'flow-php', 'id' => 73_495_297], $rows[0]->first()->get('response_body')); + static::assertSame(['login' => 'flow-php', 'id' => 73_495_297], $rows[0]->column('response_body')->value(0)); } public function test_stops_on_client_error_but_yields_its_row(): void @@ -444,7 +444,7 @@ public function test_stops_on_client_error_but_yields_its_row(): void static::assertCount(2, $client->getRequests()); static::assertCount(2, $rows); - static::assertSame(500, $rows[1]->first()->get('response_status_code')); + static::assertSame(500, $rows[1]->column('response_status_code')->value(0)); } public function test_extract_builds_through_the_config_backend(): void diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientStaticExtractorTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientStaticExtractorTest.php index dfb53f99b8..765b662c37 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientStaticExtractorTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientStaticExtractorTest.php @@ -86,13 +86,15 @@ public function test_http_extractor(): void static::fail('Expected Rows instance for tomaszhanc'); } - $norbertResponseBodyValue = $norbertRows->first()->get('response_body'); + // @mago-ignore analysis:mixed-assignment + $norbertResponseBodyValue = $norbertRows->column('response_body')->value(0); $norbertBodyJson = is_scalar($norbertResponseBodyValue) || $norbertResponseBodyValue instanceof Stringable ? (string) $norbertResponseBodyValue : ''; $norbertResponseBody = type_array()->assert(json_decode($norbertBodyJson, true, 512, JSON_THROW_ON_ERROR)); - $tomekResponseBodyValue = $tomekRows->first()->get('response_body'); + // @mago-ignore analysis:mixed-assignment + $tomekResponseBodyValue = $tomekRows->column('response_body')->value(0); $tomekBodyJson = is_scalar($tomekResponseBodyValue) || $tomekResponseBodyValue instanceof Stringable ? (string) $tomekResponseBodyValue : ''; @@ -205,7 +207,7 @@ public function test_schema_typed_response_body(): void type_structure(['login' => type_string(), 'id' => type_integer()]), $rows->schema()->get('response_body')->type(), ); - static::assertSame(['login' => 'norberttech', 'id' => 1], $rows->first()->get('response_body')); + static::assertSame(['login' => 'norberttech', 'id' => 1], $rows->column('response_body')->value(0)); } public function test_extract_builds_through_the_config_backend(): void 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 a97f73a997..16995488c5 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 @@ -69,7 +69,7 @@ public function test_extracting_json_from_local_file_stream(): void ->read(from_json(__DIR__ . '/../../Fixtures/timezones.json')->withMetadataColumns(true)) ->fetch(); - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'timezones', @@ -79,7 +79,7 @@ public function test_extracting_json_from_local_file_stream(): void 'capital', '_input_file_uri', ], - array_keys($row->toArray()), + array_keys($row), ); } @@ -92,7 +92,7 @@ public function test_extracting_json_from_local_file_stream_using_pointer(): voi ->read(from_json(__DIR__ . '/../../Fixtures/nested_timezones.json')->withPointer('/timezones', true)) ->fetch(); - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'timezones', @@ -101,7 +101,7 @@ public function test_extracting_json_from_local_file_stream_using_pointer(): voi 'country_code', 'capital', ], - array_keys(type_array()->assert($row->get('/timezones'))), + array_keys(type_array()->assert($row['/timezones'])), ); } @@ -117,7 +117,7 @@ public function test_extracting_json_from_local_file_stream_with_schema(): void )) ->fetch(); - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'timezones', @@ -126,7 +126,7 @@ public function test_extracting_json_from_local_file_stream_with_schema(): void 'country_code', 'capital', ], - array_keys($row->toArray()), + array_keys($row), ); } @@ -150,7 +150,7 @@ public function test_extracting_json_from_local_file_string_uri(): void $total = 0; foreach ($extractor->extract(flow_context(config())) as $rows) { - foreach ($rows->all() as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'timezones', @@ -159,7 +159,7 @@ public function test_extracting_json_from_local_file_string_uri(): void 'country_code', 'capital', ], - array_keys($row->toArray()), + array_keys($row), ); } $total += $rows->count(); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTypedColumnsTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTypedColumnsTest.php index fe5041f278..4af30a5366 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTypedColumnsTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorTypedColumnsTest.php @@ -28,8 +28,8 @@ public function test_fast_path_hydrates_typed_columns_with_missing_column_null_a $actual = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } @@ -53,8 +53,8 @@ public function test_fast_path_reads_partitioned_files_with_partition_value_from $actual = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } @@ -79,8 +79,8 @@ public function test_appends_partition_columns_absent_from_the_schema(): void $actual = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } 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 02fd3fec38..c6bdcba131 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 @@ -56,7 +56,7 @@ public function test_extracting_jsonl_from_local_file_stream(): void ->read(from_json_lines(__DIR__ . '/../../Fixtures/timezones.jsonl')->withMetadataColumns(true)) ->fetch(); - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'timezones', @@ -66,7 +66,7 @@ public function test_extracting_jsonl_from_local_file_stream(): void 'capital', '_input_file_uri', ], - array_keys($row->toArray()), + array_keys($row), ); } @@ -94,7 +94,7 @@ public function test_extracting_jsonl_from_local_file_stream_using_pointer(): vo ->read(from_json_lines(__DIR__ . '/../../Fixtures/nested_timezones.jsonl')->withPointer('/timezones', true)) ->fetch(); - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'timezones', @@ -103,7 +103,7 @@ public function test_extracting_jsonl_from_local_file_stream_using_pointer(): vo 'country_code', 'capital', ], - array_keys(type_array()->assert($row->get('/timezones'))), + array_keys(type_array()->assert($row['/timezones'])), ); } @@ -116,7 +116,7 @@ public function test_extracting_jsonl_from_local_file_stream_with_schema(): void $rows = df()->read(from_json_lines(__DIR__ . '/../../Fixtures/timezones.jsonl')->withSchema($schema))->fetch(); - foreach ($rows as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'timezones', @@ -125,7 +125,7 @@ public function test_extracting_jsonl_from_local_file_stream_with_schema(): void 'country_code', 'capital', ], - array_keys($row->toArray()), + array_keys($row), ); } @@ -149,7 +149,7 @@ public function test_extracting_jsonl_from_local_file_string_uri(): void $total = 0; foreach ($extractor->extract(flow_context(config())) as $rows) { - foreach ($rows->all() as $row) { + foreach ($rows->toArray() as $row) { static::assertSame( [ 'timezones', @@ -158,7 +158,7 @@ public function test_extracting_jsonl_from_local_file_string_uri(): void 'country_code', 'capital', ], - array_keys($row->toArray()), + array_keys($row), ); } $total += $rows->count(); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTypedColumnsTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTypedColumnsTest.php index b26e96e826..6d4f1c1c78 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTypedColumnsTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonLinesExtractorTypedColumnsTest.php @@ -25,8 +25,8 @@ public function test_hydrates_typed_columns_with_missing_column_null(): void $actual = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ConvertedTypeOnlyColumnsTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ConvertedTypeOnlyColumnsTest.php index 1482b1da37..27e883d7aa 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ConvertedTypeOnlyColumnsTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ConvertedTypeOnlyColumnsTest.php @@ -76,11 +76,14 @@ public function test_converted_type_only_columns_read_as_temporal_and_float_entr $rows->schema(), ); - $row = $rows[0]; - $tsMs = $row->get('ts_ms'); - $tsUs = $row->get('ts_us'); - $tMs = $row->get('t_ms'); - $tUs = $row->get('t_us'); + // @mago-ignore analysis:mixed-assignment + $tsMs = $rows->column('ts_ms')->value(0); + // @mago-ignore analysis:mixed-assignment + $tsUs = $rows->column('ts_us')->value(0); + // @mago-ignore analysis:mixed-assignment + $tMs = $rows->column('t_ms')->value(0); + // @mago-ignore analysis:mixed-assignment + $tUs = $rows->column('t_us')->value(0); static::assertInstanceOf(DateTimeInterface::class, $tsMs); static::assertInstanceOf(DateTimeInterface::class, $tsUs); @@ -90,6 +93,6 @@ public function test_converted_type_only_columns_read_as_temporal_and_float_entr static::assertSame('2020-01-02 03:04:05.678901 +00:00', $tsUs->format('Y-m-d H:i:s.u P')); static::assertSame('03:04:05.678000', $tMs->format('%H:%I:%S.%F')); static::assertSame('03:04:05.678901', $tUs->format('%H:%I:%S.%F')); - static::assertSame(12345.67, $row->get('dec9')); + static::assertSame(12345.67, $rows->column('dec9')->value(0)); } } 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 5f86c0ffc9..493983f582 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 @@ -203,8 +203,8 @@ public function test_extract_fills_partition_columns_from_the_path(): void $extractor = from_parquet(path(__DIR__ . '/Fixtures/Pagination/partitioned/date=2024-01-01/*.parquet')); foreach ($extractor->extract(flow_context(config())) as $rows) { - static::assertSame(['id', 'name', 'date'], array_keys($rows->first()->toArray())); - static::assertSame('2024-01-01', $rows->first()->get('date')); + static::assertSame(['id', 'name', 'date'], array_keys($rows->toArray()[0])); + static::assertSame('2024-01-01', $rows->column('date')->value(0)); static::assertEquals($extractor->schema(), $rows->schema()); return; @@ -263,7 +263,7 @@ public function test_declared_partition_types_reach_the_rows(): void foreach ($extractor->extract(flow_context(config())) as $rows) { static::assertEquals($extractor->schema(), $rows->schema()); - static::assertEquals(new DateTimeImmutable('2024-01-01 00:00:00 UTC'), $rows->first()->get('date')); + static::assertEquals(new DateTimeImmutable('2024-01-01 00:00:00 UTC'), $rows->column('date')->value(0)); return; } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php index ad173c1d5d..5b88c7e569 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php @@ -143,12 +143,14 @@ public function test_round_trip_of_inferred_nested_arrays_projected_to_json(): v static::assertSame('structure{data: json, id: integer}', $rows->schema()->get('body')->type()->toString()); - $first = $rows[0]->get('body'); + // @mago-ignore analysis:mixed-assignment + $first = $rows->column('body')->value(0); static::assertIsArray($first); static::assertInstanceOf(Json::class, $first['data']); static::assertSame([1, 'a'], $first['data']->toArray()); - $second = $rows[1]->get('body'); + // @mago-ignore analysis:mixed-assignment + $second = $rows->column('body')->value(1); static::assertIsArray($second); static::assertInstanceOf(Json::class, $second['data']); static::assertSame([], $second['data']->toArray()); @@ -181,20 +183,23 @@ public function test_round_trip_of_nested_json_values(): void ->write(to_parquet($path, filesystem: $memory)) ->run(); - $row = data_frame($config)->read(from_parquet($path, filesystem: $memory))->fetch()[0]; + $rows = data_frame($config)->read(from_parquet($path, filesystem: $memory))->fetch(); - $body = $row->get('body'); + // @mago-ignore analysis:mixed-assignment + $body = $rows->column('body')->value(0); static::assertIsArray($body); static::assertInstanceOf(Json::class, $body['data']); static::assertSame(['a' => 1], $body['data']->toArray()); static::assertSame(1, $body['n']); - $jsonList = $row->get('json_list'); + // @mago-ignore analysis:mixed-assignment + $jsonList = $rows->column('json_list')->value(0); static::assertIsArray($jsonList); static::assertInstanceOf(Json::class, $jsonList[0]); static::assertSame(['c' => 3], $jsonList[0]->toArray()); - $outer = $row->get('outer'); + // @mago-ignore analysis:mixed-assignment + $outer = $rows->column('outer')->value(0); static::assertIsArray($outer); // @mago-ignore analysis:mixed-assignment $inner = $outer['inner']; @@ -231,18 +236,21 @@ public function test_round_trip_of_nested_uuid_values(): void ->write(to_parquet($path, filesystem: $memory)) ->run(); - $row = data_frame($config)->read(from_parquet($path, filesystem: $memory))->fetch()[0]; + $rows = data_frame($config)->read(from_parquet($path, filesystem: $memory))->fetch(); - $body = $row->get('body'); + // @mago-ignore analysis:mixed-assignment + $body = $rows->column('body')->value(0); static::assertIsArray($body); static::assertInstanceOf(FlowUuid::class, $body['id']); static::assertSame($uuid, $body['id']->toString()); - $uuidList = $row->get('uuid_list'); + // @mago-ignore analysis:mixed-assignment + $uuidList = $rows->column('uuid_list')->value(0); static::assertIsArray($uuidList); static::assertInstanceOf(FlowUuid::class, $uuidList[0]); - $outer = $row->get('outer'); + // @mago-ignore analysis:mixed-assignment + $outer = $rows->column('outer')->value(0); static::assertIsArray($outer); // @mago-ignore analysis:mixed-assignment $inner = $outer['inner']; @@ -272,15 +280,17 @@ public function test_round_trip_of_json_and_uuid_map_values(): void ->write(to_parquet($path, filesystem: $memory)) ->run(); - $row = data_frame($config)->read(from_parquet($path, filesystem: $memory))->fetch()[0]; + $rows = data_frame($config)->read(from_parquet($path, filesystem: $memory))->fetch(); - $uuidMap = $row->get('uuid_map'); + // @mago-ignore analysis:mixed-assignment + $uuidMap = $rows->column('uuid_map')->value(0); static::assertIsArray($uuidMap); static::assertSame(['k'], array_keys($uuidMap)); static::assertInstanceOf(FlowUuid::class, $uuidMap['k']); static::assertSame($uuid, $uuidMap['k']->toString()); - $jsonMap = $row->get('json_map'); + // @mago-ignore analysis:mixed-assignment + $jsonMap = $rows->column('json_map')->value(0); static::assertIsArray($jsonMap); static::assertSame(['k'], array_keys($jsonMap)); static::assertInstanceOf(Json::class, $jsonMap['k']); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php index 006680015e..62999b137b 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php @@ -181,11 +181,9 @@ public function test_extract_builds_through_the_config_backend(): void { $backend = new SpyBackend(); - foreach (from_parquet(__DIR__ . '/../Integration/Fixtures/Pagination/01_1000.parquet')->extract( - flow_context(config_builder()->backend($backend)->build()), - ) as $rows) { - break; - } + from_parquet(__DIR__ . '/../Integration/Fixtures/Pagination/01_1000.parquet') + ->extract(flow_context(config_builder()->backend($backend)->build())) + ->current(); static::assertGreaterThanOrEqual(1, $backend->builders()); } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlCursorExtractorIntegrationTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlCursorExtractorIntegrationTest.php index e19129d272..cfba0971a6 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlCursorExtractorIntegrationTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlCursorExtractorIntegrationTest.php @@ -361,7 +361,7 @@ public function test_schema_and_extract_agree(): void $extractor = from_pgsql_cursor($this->client, sprintf('SELECT id, name FROM %s ORDER BY id', $this->tableName)); $batch = df()->read($extractor)->fetch(); - static::assertSame($extractor->schema()->references()->names(), $batch->first()->names()); + static::assertSame($extractor->schema()->references()->names(), array_keys($batch->values(0))); static::assertTrue($batch->schema()->isSame($extractor->schema())); } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlKeySetExtractorIntegrationTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlKeySetExtractorIntegrationTest.php index 6a3be16c4c..e0389772a5 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlKeySetExtractorIntegrationTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlKeySetExtractorIntegrationTest.php @@ -312,7 +312,7 @@ public function test_schema_and_extract_agree(): void ); $batch = df()->read($extractor)->fetch(); - static::assertSame($extractor->schema()->references()->names(), $batch->first()->names()); + static::assertSame($extractor->schema()->references()->names(), array_keys($batch->values(0))); static::assertTrue($batch->schema()->isSame($extractor->schema())); } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLimitOffsetExtractorIntegrationTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLimitOffsetExtractorIntegrationTest.php index 6a03a59dc7..4a2785cb1a 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLimitOffsetExtractorIntegrationTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLimitOffsetExtractorIntegrationTest.php @@ -172,7 +172,7 @@ public function test_schema_and_extract_agree(): void ); $batch = df()->read($extractor)->fetch(); - static::assertSame($extractor->schema()->references()->names(), $batch->first()->names()); + static::assertSame($extractor->schema()->references()->names(), array_keys($batch->values(0))); static::assertTrue($batch->schema()->isSame($extractor->schema())); } 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 061d8b31e6..b1f9eb39c7 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 @@ -262,7 +262,7 @@ public function test_extract_casts_an_array_column_through_the_derived_schema(): $batches = iterator_to_array(from_pgsql_cursor($client, 'SELECT tags FROM t')->extract(flow_context())); - static::assertSame(['a', 'b'], $batches[0]->first()->get('tags')); + static::assertSame(['a', 'b'], $batches[0]->column('tags')->value(0)); } public function test_extract_casts_through_the_derived_schema(): void @@ -271,12 +271,10 @@ public function test_extract_casts_through_the_derived_schema(): void ->willDescribe(ColumnMother::of(['id' => 'int8', 'amount' => 'numeric'])) ->willReturnCursors(new StubCursor([['id' => '1', 'amount' => '10.5']])); - $row = iterator_to_array( - from_pgsql_cursor($client, 'SELECT id, amount FROM t')->extract(flow_context()), - )[0]->first(); + $rows = iterator_to_array(from_pgsql_cursor($client, 'SELECT id, amount FROM t')->extract(flow_context()))[0]; - static::assertSame(1, $row->get('id')); - static::assertSame(10.5, $row->get('amount')); + static::assertSame(1, $rows->column('id')->value(0)); + static::assertSame(10.5, $rows->column('amount')->value(0)); } public function test_extract_derives_the_schema_once_and_reuses_it_across_batches(): void 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 a88aa17eb2..53c65bde83 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 @@ -147,16 +147,16 @@ public function test_extract_casts_through_the_derived_schema(): void ->willDescribe(ColumnMother::of(['id' => 'int8', 'amount' => 'numeric'])) ->willReturnCursors(new StubCursor([['id' => '1', 'amount' => '10.5']]), new StubCursor()); - $row = iterator_to_array( + $rows = iterator_to_array( from_pgsql_key_set( $client, 'SELECT id, amount FROM t', pgsql_pagination_key_set(pgsql_pagination_key_asc('id')), )->extract(flow_context()), - )[0]->first(); + )[0]; - static::assertSame(1, $row->get('id')); - static::assertSame(10.5, $row->get('amount')); + static::assertSame(1, $rows->column('id')->value(0)); + static::assertSame(10.5, $rows->column('amount')->value(0)); } public function test_extract_derives_the_schema_once_and_reuses_it_across_batches(): void 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 bf30b95332..17b3e1d473 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 @@ -170,12 +170,12 @@ public function test_extract_casts_through_the_derived_schema(): void ->willCountTotal(1) ->willReturnCursors(new StubCursor([['id' => '1', 'amount' => '10.5']])); - $row = iterator_to_array( + $rows = iterator_to_array( from_pgsql_limit_offset($client, 'SELECT id, amount FROM t ORDER BY id')->extract(flow_context()), - )[0]->first(); + )[0]; - static::assertSame(1, $row->get('id')); - static::assertSame(10.5, $row->get('amount')); + static::assertSame(1, $rows->column('id')->value(0)); + static::assertSame(10.5, $rows->column('amount')->value(0)); } public function test_extract_derives_the_schema_once_and_reuses_it_across_batches(): void diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTypedColumnsTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTypedColumnsTest.php index 1f0b88313d..593956c1a6 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTypedColumnsTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextExtractorTypedColumnsTest.php @@ -23,8 +23,8 @@ public function test_reads_each_line_into_a_string_text_column(): void foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { static::assertEquals(type_string(), $rows->schema()->get('text')->type()); - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } @@ -38,8 +38,8 @@ public function test_appends_input_file_uri_when_metadata_columns_are_enabled(): $actual = []; foreach ($extractor->extract(flow_context(Config::builder()->build())) as $rows) { - foreach ($rows as $row) { - $actual[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $actual[] = $row; } } diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php index 04b4e1a1ca..5fcf6aaf1a 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php @@ -23,9 +23,7 @@ public function test_reads_each_node_into_a_typed_xml_column(): void foreach ($extractor->extract(flow_context(Config::builder()->build())) as $batch) { static::assertEquals(type_xml(), $batch->schema()->get('node')->type()); - foreach ($batch as $row) { - $rows[] = $row; - } + $rows = [...$rows, ...$batch->toArray()]; } static::assertCount(5, $rows); @@ -38,10 +36,7 @@ public function test_appends_input_file_uri_when_metadata_columns_are_enabled(): ->withMetadataColumns(true); foreach ($extractor->extract(flow_context(Config::builder()->build())) as $batch) { - foreach ($batch as $row) { - static::assertTrue($row->has('_input_file_uri')); - static::assertSame($path->uri(), $row->get('_input_file_uri')); - } + static::assertSame([$path->uri()], array_values(array_unique($batch->column('_input_file_uri')->values()))); } } } 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 833e8a247e..a922d041e4 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 @@ -100,46 +100,67 @@ public function test_reading_xml(): void public function test_reading_xml_each_collection_item(): void { - static::assertXmlStringEqualsXmlString(<<<'XML' - - 1 - - XML, type_string()->cast(df() - ->read(from_xml(__DIR__ . '/../Fixtures/simple_items_flat.xml', 'root/items/item')) - ->fetch()[0]->get('node'))); - - static::assertXmlStringEqualsXmlString(<<<'XML' - - 5 - - XML, type_string()->cast(df() - ->read(from_xml(__DIR__ . '/../Fixtures/simple_items_flat.xml', 'root/items/item')) - ->fetch()[4]->get('node'))); - } - - public function test_reading_xml_from_path(): void - { - static::assertXmlStringEqualsXmlString(<<<'XML' - + static::assertXmlStringEqualsXmlString( + <<<'XML' - 1 - - - 2 - - - 3 - - - 4 + 1 + XML, + type_string()->cast( + df() + ->read(from_xml(__DIR__ . '/../Fixtures/simple_items_flat.xml', 'root/items/item')) + ->fetch() + ->column('node') + ->value(0), + ), + ); + + static::assertXmlStringEqualsXmlString( + <<<'XML' - 5 + 5 - - XML, type_string()->cast(df() - ->read(from_xml(__DIR__ . '/../Fixtures/simple_items.xml', 'root/items')) - ->fetch()[0]->get('node'))); + XML, + type_string()->cast( + df() + ->read(from_xml(__DIR__ . '/../Fixtures/simple_items_flat.xml', 'root/items/item')) + ->fetch() + ->column('node') + ->value(4), + ), + ); + } + + public function test_reading_xml_from_path(): void + { + static::assertXmlStringEqualsXmlString( + <<<'XML' + + + 1 + + + 2 + + + 3 + + + 4 + + + 5 + + + XML, + type_string()->cast( + df() + ->read(from_xml(__DIR__ . '/../Fixtures/simple_items.xml', 'root/items')) + ->fetch() + ->column('node') + ->value(0), + ), + ); } public function test_reading_xml_with_ancestor_namespace_declaration(): void @@ -149,9 +170,12 @@ public function test_reading_xml_with_ancestor_namespace_declaration(): void ->withEntry('title', ref('node')->xpath('/entry/g:title')->domElementValue()) ->fetch(); - static::assertSame(['Product 1', 'Product 2'], [$rows[0]->get('title'), $rows[1]->get('title')]); + static::assertSame(['Product 1', 'Product 2'], [ + $rows->column('title')->value(0), + $rows->column('title')->value(1), + ]); - $node = type_string()->cast($rows[0]->get('node')); + $node = type_string()->cast($rows->column('node')->value(0)); static::assertStringContainsString('xmlns:g="http://base.google.com/ns/1.0"', $node); static::assertStringContainsString('xmlns:c="http://example.com/custom"', $node); @@ -159,18 +183,26 @@ public function test_reading_xml_with_ancestor_namespace_declaration(): void public function test_reading_xml_with_default_namespace_declaration(): void { - $node = type_string()->cast(df() - ->read(from_xml(__DIR__ . '/../Fixtures/namespaced_default.xml', 'feed/entry')) - ->fetch()[0]->get('node')); + $node = type_string()->cast( + df() + ->read(from_xml(__DIR__ . '/../Fixtures/namespaced_default.xml', 'feed/entry')) + ->fetch() + ->column('node') + ->value(0), + ); static::assertStringContainsString('xmlns="http://example.com/default"', $node); } public function test_reading_xml_with_multi_ancestor_namespace_merge(): void { - $node = type_string()->cast(df() - ->read(from_xml(__DIR__ . '/../Fixtures/namespaced_multi_ancestor.xml', 'feed/group/entry')) - ->fetch()[0]->get('node')); + $node = type_string()->cast( + df() + ->read(from_xml(__DIR__ . '/../Fixtures/namespaced_multi_ancestor.xml', 'feed/group/entry')) + ->fetch() + ->column('node') + ->value(0), + ); static::assertStringContainsString('xmlns:a="http://example.com/a"', $node); static::assertStringContainsString('xmlns:b="http://example.com/b"', $node); @@ -183,18 +215,22 @@ public function test_reading_xml_with_namespace_on_captured_root(): void ->withEntry('title', ref('node')->xpath('/entry/g:title')->domElementValue()) ->fetch(); - static::assertSame('Product 1', $rows[0]->get('title')); + static::assertSame('Product 1', $rows->column('title')->value(0)); static::assertStringContainsString( 'xmlns:g="http://base.google.com/ns/1.0"', - type_string()->cast($rows[0]->get('node')), + type_string()->cast($rows->column('node')->value(0)), ); } public function test_reading_xml_with_prefixed_attribute(): void { - $node = type_string()->cast(df() - ->read(from_xml(__DIR__ . '/../Fixtures/namespaced_prefixed_attribute.xml', 'feed/entry')) - ->fetch()[0]->get('node')); + $node = type_string()->cast( + df() + ->read(from_xml(__DIR__ . '/../Fixtures/namespaced_prefixed_attribute.xml', 'feed/entry')) + ->fetch() + ->column('node') + ->value(0), + ); static::assertStringContainsString('xmlns:g="http://base.google.com/ns/1.0"', $node); static::assertStringContainsString('xml:lang="en"', $node); @@ -237,9 +273,13 @@ public function test_reading_xml_refuses_a_not_null_column_the_document_lacks(): public function test_reading_xml_with_shadowed_namespace_declaration(): void { - $node = type_string()->cast(df() - ->read(from_xml(__DIR__ . '/../Fixtures/namespaced_nested.xml', 'feed/group/entry')) - ->fetch()[0]->get('node')); + $node = type_string()->cast( + df() + ->read(from_xml(__DIR__ . '/../Fixtures/namespaced_nested.xml', 'feed/group/entry')) + ->fetch() + ->column('node') + ->value(0), + ); static::assertStringContainsString('xmlns:g="http://example.com/override"', $node); static::assertStringContainsString('xmlns:x="http://example.com/extra"', $node); @@ -263,13 +303,20 @@ public function test_reading_xml_with_sibling_namespace_isolation(): void public function test_reading_xml_without_namespaces_is_unchanged(): void { - static::assertXmlStringEqualsXmlString(<<<'XML' - - 1 - - XML, type_string()->cast(df() - ->read(from_xml(__DIR__ . '/../Fixtures/simple_items_flat.xml', 'root/items/item')) - ->fetch()[0]->get('node'))); + static::assertXmlStringEqualsXmlString( + <<<'XML' + + 1 + + XML, + type_string()->cast( + df() + ->read(from_xml(__DIR__ . '/../Fixtures/simple_items_flat.xml', 'root/items/item')) + ->fetch() + ->column('node') + ->value(0), + ), + ); } public function test_schema_appends_the_metadata_column(): void 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 945e11a2b8..021a30d61c 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 @@ -95,7 +95,7 @@ public function test_reading_xml_each_collection_item(): void 1 - XML, type_string()->cast(data_frame()->read($extractor1)->fetch()[0]->get('node'))); + XML, type_string()->cast(data_frame()->read($extractor1)->fetch()->column('node')->value(0))); // @mago-ignore analysis:deprecated-class $extractor2 = new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/simple_items_flat.xml'), 'root/items/item'); @@ -103,7 +103,7 @@ public function test_reading_xml_each_collection_item(): void 5 - XML, type_string()->cast(data_frame()->read($extractor2)->fetch()[4]->get('node'))); + XML, type_string()->cast(data_frame()->read($extractor2)->fetch()->column('node')->value(4))); } public function test_reading_xml_from_path(): void @@ -128,10 +128,14 @@ public function test_reading_xml_from_path(): void XML, - type_string()->cast(data_frame() - // @mago-ignore analysis:deprecated-class - ->read(new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/simple_items.xml'), 'root/items')) - ->fetch()[0]->get('node')), + type_string()->cast( + data_frame() + // @mago-ignore analysis:deprecated-class + ->read(new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/simple_items.xml'), 'root/items')) + ->fetch() + ->column('node') + ->value(0), + ), ); } diff --git a/src/bridge/filesystem/sftp/tests/Flow/Filesystem/Bridge/SFTP/Tests/Integration/SFTPDataFrameTest.php b/src/bridge/filesystem/sftp/tests/Flow/Filesystem/Bridge/SFTP/Tests/Integration/SFTPDataFrameTest.php index dab8a20dbc..7e1bbe4a1f 100644 --- a/src/bridge/filesystem/sftp/tests/Flow/Filesystem/Bridge/SFTP/Tests/Integration/SFTPDataFrameTest.php +++ b/src/bridge/filesystem/sftp/tests/Flow/Filesystem/Bridge/SFTP/Tests/Integration/SFTPDataFrameTest.php @@ -34,8 +34,8 @@ public function test_orders_written_as_csv_are_read_back_from_sftp(): void $rows = data_frame()->read(from_csv(path('sftp:///upload/orders.csv'), filesystem: $filesystem))->fetch(); static::assertCount(1_000, $rows); - static::assertSame('user-0@example.com', $rows->first()->get('email')); - static::assertSame('user-999@example.com', $rows->last()?->get('email')); + static::assertSame('user-0@example.com', $rows->column('email')->value(0)); + static::assertSame('user-999@example.com', $rows->column('email')->value($rows->count() - 1)); } public function test_orders_written_as_parquet_survive_a_round_trip_with_every_entry_type(): void @@ -55,28 +55,29 @@ public function test_orders_written_as_parquet_survive_a_round_trip_with_every_e static::assertCount(1_000, $rows); - $first = $rows->first(); - - static::assertSame(0, $first->get('index')); + static::assertSame(0, $rows->column('index')->value(0)); static::assertSame( '254d61c5-22c8-4407-83a2-76f1cab53af2', - type_uuid()->assert($first->get('order_id'))->toString(), + type_uuid()->assert($rows->column('order_id')->value(0))->toString(), ); static::assertSame( '2025-01-01 12:00:00', - type_datetime()->assert($first->get('created_at'))->format('Y-m-d H:i:s'), + type_datetime()->assert($rows->column('created_at')->value(0))->format('Y-m-d H:i:s'), ); static::assertSame( ['street' => '123 Main St, Apt 0', 'city' => 'City ', 'zip' => '12345-0', 'country' => 'PL'], - $first->get('address'), + $rows->column('address')->value(0), + ); + static::assertSame( + ['Note 1 for order 0', 'Note 2 for order 0', 'Note 3 for order 0'], + $rows->column('notes')->value(0), ); - static::assertSame(['Note 1 for order 0', 'Note 2 for order 0', 'Note 3 for order 0'], $first->get('notes')); static::assertEqualsWithDelta( [ ['sku' => 'SKU_0001', 'quantity' => 1, 'price' => 0.14], ['sku' => 'SKU_0002', 'quantity' => 2, 'price' => 25.13], ], - $first->get('items'), + $rows->column('items')->value(0), 0.0001, ); } diff --git a/src/core/etl/src/Flow/Calculator/RunningSum.php b/src/core/etl/src/Flow/Calculator/RunningSum.php index 2545c63227..34a0291f19 100644 --- a/src/core/etl/src/Flow/Calculator/RunningSum.php +++ b/src/core/etl/src/Flow/Calculator/RunningSum.php @@ -4,23 +4,71 @@ namespace Flow\Calculator; +use function abs; +use function is_finite; +use function is_float; +use function is_int; use function is_string; -final readonly class RunningSum +/** + * IEEE addition with Neumaier compensation: the rounding error of every float addition is carried and added back once, + * so a long run of floats does not drift. An exact addition is decimal (Calculator) over the compensated total. + */ +final class RunningSum { + private float $compensation = 0.0; + + private float|int $sum = 0; + public function __construct( - private Calculator $calculator = new Calculator(), + private readonly Calculator $calculator = new Calculator(), ) {} /** * @param float|int|numeric-string $value */ - public function add(float|int $sum, float|int|string $value, bool $exact): float|int + public function add(float|int|string $value, bool $exact): void + { + if ($exact) { + $this->sum = $this->calculator->add($this->value(), $value); + $this->compensation = 0.0; + + return; + } + + $value = is_string($value) ? (float) $value : $value; + + if (is_int($this->sum) && is_int($value)) { + // an int overflow promotes to float, as PHP's + does + $this->sum += $value; + + return; + } + + $sum = (float) $this->sum; + $total = $sum + $value; + + if (is_finite($total)) { + $this->compensation += abs($sum) >= abs($value) ? $sum - $total + $value : $value - $total + $sum; + } + + $this->sum = $total; + } + + public function merge(self $other, bool $exact): void { if ($exact) { - return $this->calculator->add($sum, $value); + $this->add($other->value(), true); + + return; } - return $sum + (is_string($value) ? (float) $value : $value); + $this->add($other->sum, false); + $this->compensation += $other->compensation; + } + + public function value(): float|int + { + return is_float($this->sum) && is_finite($this->sum) ? $this->sum + $this->compensation : $this->sum; } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Bucket.php b/src/core/etl/src/Flow/ETL/Bucketing/Bucket.php index 2b548d2f44..2d3fec16fc 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/Bucket.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/Bucket.php @@ -4,14 +4,6 @@ namespace Flow\ETL\Bucketing; -use Flow\ETL\Row; -use Flow\ETL\Schema; - -use function Flow\ETL\DSL\array_to_row; -use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\schema; -use function Flow\ETL\DSL\str_schema; - final readonly class Bucket { public function __construct( @@ -19,17 +11,4 @@ public function __construct( public int $totalRows, public int $index, ) {} - - public static function schema(): Schema - { - return schema(str_schema(BucketShape::id->value), int_schema(BucketShape::totalRows->value)); - } - - public function toRow(): Row - { - return array_to_row([ - BucketShape::id->value => $this->id, - BucketShape::totalRows->value => $this->totalRows, - ], self::schema()); - } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/BucketShape.php b/src/core/etl/src/Flow/ETL/Bucketing/BucketShape.php deleted file mode 100644 index 72175df8dd..0000000000 --- a/src/core/etl/src/Flow/ETL/Bucketing/BucketShape.php +++ /dev/null @@ -1,14 +0,0 @@ - $rows - * - * @return Generator - */ - public function bucketize(Generator $rows, BucketsStorage $storage): Generator; -} diff --git a/src/core/etl/src/Flow/ETL/Bucketing/HashBucketing.php b/src/core/etl/src/Flow/ETL/Bucketing/HashBucketing.php index b09c63872b..09c5382001 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/HashBucketing.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/HashBucketing.php @@ -6,7 +6,6 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\RandomValueGenerator; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Generator; @@ -16,7 +15,7 @@ use function sprintf; use function substr; -final class HashBucketing implements BucketingStrategy +final class HashBucketing { private readonly KeyValues $keyValues; @@ -40,6 +39,21 @@ public function __construct( $this->keyValues = new KeyValues($by); } + public function index(string $hash): int + { + return (int) hexdec(substr($hash, 0, 8)) % $this->bucketsCount; + } + + /** + * The bucket a row with these key values lands in. + * + * @param list $values in the order of the bucketing references + */ + public function indexOf(array $values): int + { + return $this->index($this->hasher->hash([$values])[0]); + } + /** * @param Generator $rows * @@ -58,20 +72,20 @@ public function bucketize(Generator $rows, BucketsStorage $storage): Generator foreach ($rows as $batch) { $hashes = $this->hasher->hash($this->keyValues->of($batch)); - /** @var array> $groups */ + /** @var array> $groups */ $groups = []; - foreach ($batch as $i => $row) { - $index = (int) hexdec(substr($hashes[$i], 0, 8)) % $this->bucketsCount; + foreach ($hashes as $i => $hash) { + $index = $this->index($hash); $id = sprintf('%s-%s-%d', $this->namespace, $runId, $index); - $groups[$id][] = $row; + $groups[$id][] = $i; $indexes[$id] = $index; } // a bucket is a subset of a batch that already passed the gate, under the same schema - foreach ($groups as $id => $groupRows) { - $storage->append($id, Rows::of($batch->schema(), ...$groupRows)); - $totals[$id] = ($totals[$id] ?? 0) + count($groupRows); + foreach ($groups as $id => $indices) { + $storage->append($id, $batch->gather($indices)); + $totals[$id] = ($totals[$id] ?? 0) + count($indices); } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php b/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php index d93d4cf999..632d552db0 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php @@ -7,7 +7,7 @@ use Flow\ETL\Rows; use Generator; -use function array_values; +use function array_slice; /** * Collects rows sharing a key into one batch, so a downstream operator sees each key exactly once @@ -27,30 +27,33 @@ public function __construct( */ public function group(Generator $rows): Generator { - /** @var array> $groups */ + /** @var array> $groups each key's rows, one gathered part per batch, in batch order */ $groups = []; $schema = null; - foreach ($rows as $batch) { - if (!$batch->count()) { + foreach ($rows as $input) { + if (!$input->count()) { continue; } - // bound once, like BucketAggregation: every batch out of one bucket shares a schema - $schema ??= $batch->schema(); - $hashes = $this->hasher->hash($this->keys->of($batch)); + // bound once: every batch out of one bucket shares a schema + $schema ??= $input->schema(); + $batch = $input->matchTo($schema); - foreach (array_values($batch->all()) as $index => $row) { - $groups[$hashes[$index]][] = $row; + /** @var array> $indices */ + $indices = []; + + foreach ($this->hasher->hash($this->keys->of($batch)) as $i => $hash) { + $indices[$hash][] = $i; } - } - if ($schema === null) { - return; + foreach ($indices as $hash => $rowsOfKey) { + $groups[$hash][] = $batch->gather($rowsOfKey); + } } - foreach ($groups as $rowsOfKey) { - yield Rows::of($schema, ...$rowsOfKey); + foreach ($groups as $parts) { + yield $parts[0]->concat(...array_slice($parts, 1)); } } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/KeyValues.php b/src/core/etl/src/Flow/ETL/Bucketing/KeyValues.php index ad29bb53c6..4c0d1bbe9a 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/KeyValues.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/KeyValues.php @@ -4,10 +4,8 @@ namespace Flow\ETL\Bucketing; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; -use Flow\ETL\Schema; /** * Extracts bucket-key values positionally, in reference order - position, not column name, defines @@ -27,28 +25,21 @@ public function __construct( */ public function of(Rows $rows): array { - $values = []; - $schema = $rows->schema(); - - foreach ($rows as $row) { - $values[] = $this->ofRow($row, $schema); + if ($rows->isEmpty()) { + return []; } - return $values; - } - - /** - * @return list - */ - public function ofRow(Row $row, Schema $schema): array - { $values = []; + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $values[] = []; + } + foreach ($this->refs as $ref) { - // absent under a nullable declaration is a legitimate null - it keys into a bucket that - // no comparison will match, which is what SQL says an unknown key does. Absent under NOT - // NULL is a row-shape violation, and Row::get() names it and lists the available columns. - $values[] = !$row->has($ref) && $schema->get($ref)->isNullable() ? null : $row->get($ref); + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($rows->schema()->get($ref)->entry()->name())->values() as $i => $value) { + $values[$i][] = $value; + } } return $values; diff --git a/src/core/etl/src/Flow/ETL/Bucketing/NativeHasher.php b/src/core/etl/src/Flow/ETL/Bucketing/NativeHasher.php index 555f63c4ec..638f366ebf 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/NativeHasher.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/NativeHasher.php @@ -8,12 +8,12 @@ use Flow\ETL\Hash\NativePHPHash; use Stringable; -use function array_map; use function is_bool; use function is_numeric; use function is_object; use function is_string; use function serialize; +use function strlen; final readonly class NativeHasher implements Hasher { @@ -56,7 +56,16 @@ public function hash(array $values): array $hashes = []; foreach ($values as $rowValues) { - $hashes[] = NativePHPHash::xxh128(serialize(array_map(self::normalize(...), $rowValues))); + $key = ''; + + // @mago-ignore analysis:mixed-assignment + foreach ($rowValues as $value) { + $normalized = self::normalize($value); + // length-prefixed, so a value cannot run into the next one + $key .= strlen($normalized) . ':' . $normalized; + } + + $hashes[] = NativePHPHash::xxh128($key); } return $hashes; diff --git a/src/core/etl/src/Flow/ETL/Bucketing/SortedRunBucketing.php b/src/core/etl/src/Flow/ETL/Bucketing/SortedRunBucketing.php deleted file mode 100644 index 56829b45c9..0000000000 --- a/src/core/etl/src/Flow/ETL/Bucketing/SortedRunBucketing.php +++ /dev/null @@ -1,65 +0,0 @@ - $by - * @param int<1, max> $runSize - */ - public function __construct( - private readonly array $by, - private readonly int $runSize, - private readonly RandomValueGenerator $random, - ) { - // @mago-ignore analysis:invalid-operand - // @mago-ignore analysis:impossible-condition,redundant-comparison - if ($this->runSize < 1) { - throw new InvalidArgumentException('Run size must be greater than 0, given: ' . $this->runSize); - } - } - - /** - * @param Generator $rows - * - * @return Generator - */ - public function bucketize(Generator $rows, BucketsStorage $storage): Generator - { - $runId = $this->random->string(16); - $buffer = null; - $index = 0; - - foreach ($rows as $batch) { - $buffer = $buffer === null ? $batch : $buffer->merge($batch); - - while ($buffer->count() >= $this->runSize) { - yield $this->spill($buffer->take($this->runSize), $storage, $runId, $index++); - $buffer = $buffer->drop($this->runSize); - } - } - - if ($buffer !== null && !$buffer->isEmpty()) { - yield $this->spill($buffer, $storage, $runId, $index); - } - } - - private function spill(Rows $run, BucketsStorage $storage, string $runId, int $index): Bucket - { - $bucketId = sprintf('sort-%s-%d', $runId, $index); - $storage->set($bucketId, $run->sortBy(...$this->by)); - - return new Bucket($bucketId, $run->count(), $index); - } -} diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Storage/SpillingBuckets.php b/src/core/etl/src/Flow/ETL/Bucketing/Storage/SpillingBuckets.php new file mode 100644 index 0000000000..01474e6d6e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Bucketing/Storage/SpillingBuckets.php @@ -0,0 +1,161 @@ +> + */ + private array $buffers = []; + + /** + * @var array + */ + private array $buffered = []; + + private readonly MemoryBudget $budget; + + /** + * @var array + */ + private array $onDisk = []; + + private bool $spilling = false; + + /** + * @param int<1, max> $batchSize + */ + public function __construct( + public readonly BucketsStorage $disk, + public readonly Unit $memoryLimit, + Backend $backend, + private readonly int $batchSize = 1000, + ) { + // @mago-ignore analysis:invalid-operand + // @mago-ignore analysis:impossible-condition,redundant-comparison + if ($this->batchSize < 1) { + throw new InvalidArgumentException('Batch size must be greater than 0, given: ' . $this->batchSize); + } + + $this->budget = new MemoryBudget($backend, $this->memoryLimit); + } + + /** + * $bucketing's storage behind the memory limit - a resident storage already holds everything in memory. + */ + public static function around(BucketingConfig $bucketing, Unit $memoryLimit, Backend $backend): BucketsStorage + { + return $bucketing->storage instanceof ResidentBucketsStorage + ? $bucketing->storage + : new self($bucketing->storage, $memoryLimit, $backend, $bucketing->batchSize); + } + + public function append(string $bucketId, Rows $rows): void + { + if ($rows->isEmpty()) { + return; + } + + $this->buffers[$bucketId][] = $rows; + $this->buffered[$bucketId] = ($this->buffered[$bucketId] ?? 0) + $rows->count(); + + if (!$this->spilling && $this->budget->exceeded()) { + $this->spilling = true; + + foreach (array_keys($this->buffers) as $id) { + $this->writeFullBatches($id); + } + + return; + } + + if ($this->spilling) { + $this->writeFullBatches($bucketId); + } + } + + public function get(string $bucketId): Generator + { + if (array_key_exists($bucketId, $this->onDisk)) { + yield from $this->disk->get($bucketId); + } + + if (!array_key_exists($bucketId, $this->buffers)) { + return; + } + + $buffered = $this->buffers[$bucketId][0]->concat(...array_slice($this->buffers[$bucketId], 1)); + + for ($offset = 0, $count = $buffered->count(); $offset < $count; $offset += $this->batchSize) { + yield $buffered->slice($offset, min($this->batchSize, $count - $offset)); + } + } + + public function remove(string $bucketId): void + { + unset($this->buffers[$bucketId], $this->buffered[$bucketId]); + + if (array_key_exists($bucketId, $this->onDisk)) { + unset($this->onDisk[$bucketId]); + $this->disk->remove($bucketId); + } + } + + public function set(string $bucketId, Rows $rows): void + { + $this->remove($bucketId); + $this->append($bucketId, $rows); + } + + public function writeFullBatches(string $bucketId): void + { + $count = $this->buffered[$bucketId] ?? 0; + + if ($count < $this->batchSize) { + return; + } + + $buffered = $this->buffers[$bucketId][0]->concat(...array_slice($this->buffers[$bucketId], 1)); + $written = $count - ($count % $this->batchSize); + + for ($offset = 0; $offset < $written; $offset += $this->batchSize) { + $this->disk->append($bucketId, $buffered->slice($offset, $this->batchSize)); + } + + $this->onDisk[$bucketId] = true; + $this->budget->released(); + + if ($written === $count) { + unset($this->buffers[$bucketId], $this->buffered[$bucketId]); + + return; + } + + $this->buffers[$bucketId] = [$buffered->slice($written, $count - $written)]; + $this->buffered[$bucketId] = $count - $written; + } +} diff --git a/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php b/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php index 88f58b1eac..7a76f9c893 100644 --- a/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php +++ b/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php @@ -36,9 +36,16 @@ public static function fromRows(string $key, Rows $rows): self { $index = new self($key); - foreach ($rows->all() as $row) { - $value = $row->get('key'); + if ($rows->isEmpty()) { + return $index; + } + + $keys = $rows->column('key')->values(); + // an index written by 0.44.x has no "rows" column + $counts = $rows->schema()->findDefinition('rows') === null ? [] : $rows->column('rows')->values(); + // @mago-ignore analysis:mixed-assignment + foreach ($keys as $i => $value) { if (!is_string($value)) { throw new InvalidArgumentException(sprintf( 'CacheIndex expects rows with a string "key" entry, got: %s', @@ -46,8 +53,8 @@ public static function fromRows(string $key, Rows $rows): self )); } - // an index written by 0.44.x has no "rows" column - $chunkRows = $row->has('rows') ? $row->get('rows') : null; + // @mago-ignore analysis:mixed-assignment + $chunkRows = $counts[$i] ?? null; if ($chunkRows !== null && !is_int($chunkRows)) { throw new InvalidArgumentException(sprintf( diff --git a/src/core/etl/src/Flow/ETL/Column/ComparableValues.php b/src/core/etl/src/Flow/ETL/Column/ComparableValues.php new file mode 100644 index 0000000000..8e5b2a938e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/ComparableValues.php @@ -0,0 +1,79 @@ + $type + */ + public function equalByPhysical(Type $type): bool + { + $bare = type_bare($type); + + return ( + $this->orderedByPhysical($bare) + || $bare instanceof UuidType + || $bare instanceof JsonType + || $bare instanceof EnumType + || $bare instanceof XMLType + || $bare instanceof XMLElementType + || $bare instanceof HTMLType + || $bare instanceof HTMLElementType + ); + } + + /** + * @return list === on these is value equality + */ + public function equality(Column $column): array + { + return $this->equalByPhysical($column->type()) ? $column->physicals() : $column->values(); + } + + /** + * @param Type $type + */ + public function orderedByPhysical(Type $type): bool + { + $bare = type_bare($type); + + return ( + $bare instanceof IntegerType + || $bare instanceof FloatType + || $bare instanceof BooleanType + || $bare instanceof StringType + || $bare instanceof DateTimeType + || $bare instanceof DateType + || $bare instanceof TimeType + ); + } + + /** + * @return list PHP <, <=, <=> on these equal today's comparison of the values + */ + public function ordering(Column $column): array + { + return $this->orderedByPhysical($column->type()) ? $column->physicals() : $column->values(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php index 70666b1427..5e3635ac42 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php @@ -12,11 +12,19 @@ use Flow\ETL\Schema\Definition\NullDefinition; use Flow\Types\Exception\Exception as TypesException; use Flow\Types\Type; +use Flow\Types\Type\Native\BooleanType; +use Flow\Types\Type\Native\FloatType; +use Flow\Types\Type\Native\IntegerType; +use Flow\Types\Type\Native\StringType; + +use function get_debug_type; final class CastingColumnBuilder implements ColumnBuilder { private readonly bool $identity; + private readonly ?string $native; + private readonly bool $nullable; /** @@ -35,6 +43,15 @@ public function __construct( $this->identity = $physical instanceof IdentityPhysical; $this->nullable = $definition->isNullable() || $definition instanceof NullDefinition; $this->type = $definition->type(); + $this->native = $this->identity + ? match ($this->type::class) { + BooleanType::class => 'bool', + IntegerType::class => 'int', + FloatType::class => 'float', + StringType::class => 'string', + default => null, + } + : null; } public function append(mixed $value): void @@ -81,6 +98,12 @@ public function appendMany(array $values): void continue; } + if (get_debug_type($value) === $this->native) { + $physicals[] = $value; + + continue; + } + // @mago-ignore analysis:mixed-assignment $cast = $this->type->cast($value); diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php index 91d4e3abee..0cd3a655c9 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php @@ -37,11 +37,7 @@ public function at(int $i): mixed return null; } - return array_slice( - $this->element->physicals(), - $this->offsets[$i], - $this->offsets[$i + 1] - $this->offsets[$i], - ); + return $this->element->slice($this->offsets[$i], $this->offsets[$i + 1] - $this->offsets[$i])->physicals(); } public function concat(Column ...$others): Column @@ -148,13 +144,7 @@ public function value(int $i): mixed return null; } - $value = []; - - for ($j = $this->offsets[$i], $end = $this->offsets[$i + 1]; $j < $end; $j++) { - $value[] = $this->element->value($j); - } - - return $value; + return $this->element->slice($this->offsets[$i], $this->offsets[$i + 1] - $this->offsets[$i])->values(); } public function values(): array diff --git a/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php index 300890ec9b..e1bf624351 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php @@ -42,9 +42,9 @@ public function at(int $i): mixed $length = $this->offsets[$i + 1] - $this->offsets[$i]; /** @var list $keys */ - $keys = array_slice($this->keys->physicals(), $this->offsets[$i], $length); + $keys = $this->keys->slice($this->offsets[$i], $length)->physicals(); - return array_combine($keys, array_slice($this->values->physicals(), $this->offsets[$i], $length)); + return array_combine($keys, $this->values->slice($this->offsets[$i], $length)->physicals()); } public function concat(Column ...$others): Column @@ -176,15 +176,12 @@ public function value(int $i): mixed return null; } - $value = []; + $length = $this->offsets[$i + 1] - $this->offsets[$i]; - for ($j = $this->offsets[$i], $end = $this->offsets[$i + 1]; $j < $end; $j++) { - /** @var int|string $key */ - $key = $this->keys->value($j); - $value[$key] = $this->values->value($j); - } + /** @var list $keys */ + $keys = $this->keys->slice($this->offsets[$i], $length)->values(); - return $value; + return array_combine($keys, $this->values->slice($this->offsets[$i], $length)->values()); } public function values(): array diff --git a/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php b/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php index 970ce93cda..018e0c289c 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php @@ -46,7 +46,9 @@ use Flow\Types\Type\Logical\UuidType; use Flow\Types\Type\Logical\XMLElementType; use Flow\Types\Type\Logical\XMLType; +use Flow\Types\Type\Native\ArrayType; use Flow\Types\Type\Native\BooleanType; +use Flow\Types\Type\Native\EmptyArrayType; use Flow\Types\Type\Native\EnumType; use Flow\Types\Type\Native\FloatType; use Flow\Types\Type\Native\IntegerType; @@ -55,6 +57,7 @@ use Flow\Types\Type\Native\StringType; use UnitEnum; +use function Flow\Types\DSL\type_bare; use function in_array; use function sprintf; @@ -103,6 +106,81 @@ public function definition(Definition $definition): Physical } } + /** + * A column of $type exists: definition_from_type() accepts it and definition() gives it a Physical. + * + * @param Type $type + */ + public function supports(Type $type): bool + { + $base = type_bare($type); + + return match (true) { + $base instanceof ArrayType => true, + $base instanceof EmptyArrayType, + $base instanceof PositiveIntegerType, + $base instanceof NonEmptyStringType, + $base instanceof NumericStringType, + $base instanceof ClassStringType, + => false, + default => $this->supportsChild($base), + }; + } + + /** + * A child (list element, map value, structure element) of $type exists once TypeProjection stored it as json + * (an array) or as optional (a nullable union): type() gives it a Physical. + * + * @param Type $type + */ + public function supportsChild(Type $type): bool + { + $base = type_bare($type); + + return match (true) { + $base instanceof ArrayType, $base instanceof EmptyArrayType => true, + $base instanceof IntegerType, + $base instanceof PositiveIntegerType, + $base instanceof FloatType, + $base instanceof BooleanType, + $base instanceof StringType, + $base instanceof NonEmptyStringType, + $base instanceof NumericStringType, + $base instanceof ClassStringType, + $base instanceof DateTimeType, + $base instanceof DateType, + $base instanceof TimeType, + $base instanceof UuidType, + $base instanceof TimeZoneType, + $base instanceof JsonType, + $base instanceof XMLType, + $base instanceof XMLElementType, + $base instanceof HTMLType, + $base instanceof HTMLElementType, + $base instanceof NullType, + => true, + $base instanceof EnumType => $base->class !== UnitEnum::class && $base->class !== BackedEnum::class, + $base instanceof ListType => $this->supportsChild($base->element()), + $base instanceof MapType => $this->supportsChild($base->value()), + $base instanceof StructureType => $this->supportsElements($base), + default => false, + }; + } + + /** + * @param StructureType $type + */ + public function supportsElements(StructureType $type): bool + { + foreach ($type->elements() as $element) { + if (!$this->supportsChild($element->type)) { + return false; + } + } + + return true; + } + /** * @param Type $type * diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ValueColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/ValueColumn.php new file mode 100644 index 0000000000..d818aa39d4 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ValueColumn.php @@ -0,0 +1,108 @@ + $values logical PHP values, null = null + */ + public function __construct( + private array $values, + ) {} + + public function at(int $i): mixed + { + return $this->values[$i]; + } + + public function concat(Column ...$others): Column + { + throw new InvalidArgumentException( + 'An untyped function result (mixed) cannot be concatenated; it exists only inside function evaluation', + ); + } + + public function count(): int + { + return count($this->values); + } + + public function encode(): array + { + throw new RuntimeException( + 'An untyped function result (mixed) cannot be encoded; it exists only inside function evaluation', + ); + } + + public function isNull(int $i): bool + { + return $this->values[$i] === null; + } + + public function nullCount(): int + { + return count(array_filter($this->values, static fn(mixed $value): bool => $value === null)); + } + + public function physicals(): array + { + return $this->values; + } + + public function slice(int $offset, int $length): Column + { + return new self(array_slice($this->values, $offset, $length)); + } + + public function take(array $indices): Column + { + $values = []; + + foreach ($indices as $index) { + $values[] = $this->values[$index]; + } + + return new self($values); + } + + /** + * @return MixedType + */ + public function type(): Type + { + return type_mixed(); + } + + public function value(int $i): mixed + { + return $this->values[$i]; + } + + public function values(): array + { + return $this->values; + } + + public function withType(Type $type): Column + { + throw new InvalidArgumentException(sprintf( + 'An untyped function result (mixed) cannot be retyped to %s; it exists only inside function evaluation', + $type->toString(), + )); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/PhpBackend.php b/src/core/etl/src/Flow/ETL/Column/PhpBackend.php index c5be05a249..ebf5281a39 100644 --- a/src/core/etl/src/Flow/ETL/Column/PhpBackend.php +++ b/src/core/etl/src/Flow/ETL/Column/PhpBackend.php @@ -14,6 +14,7 @@ use Flow\ETL\Column\Php\PhysicalFor; use Flow\ETL\Column\Php\ScalarColumn; use Flow\ETL\Column\Php\StructColumn; +use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Schema\Definition; @@ -71,6 +72,10 @@ public function decode(Definition $definition, array $buffers, int $count, int $ public function adopt(Definition $definition, Column $column): Column { + if ($column instanceof ValueColumn) { + throw ColumnMismatchException::untypedColumn($definition); + } + if ( $column instanceof ScalarColumn || $column instanceof ConstantColumn diff --git a/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByBuilder.php b/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByBuilder.php index f308caf003..e0f2b09271 100644 --- a/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByBuilder.php @@ -7,12 +7,17 @@ use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Column\Backend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; +use Flow\ETL\Config\MemoryLimit; +use Flow\ETL\Dataset\Memory\Unit; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\Filesystem\Path; final class HashGroupByBuilder implements GroupByAlgorithmBuilder { private readonly BucketingConfigBuilder $bucketing; + private ?Unit $memoryLimit = null; + public function __construct() { $this->bucketing = new BucketingConfigBuilder('/flow-php-group-by/', 64); @@ -30,7 +35,10 @@ public function batchSize(int $batchSize): self public function build(Path $spillRoot, Backend $backend): HashGroupByConfig { - return new HashGroupByConfig($this->bucketing->build($spillRoot, $backend)); + return new HashGroupByConfig( + $this->bucketing->build($spillRoot, $backend), + $this->memoryLimit ?? MemoryLimit::default(), + ); } /** @@ -43,6 +51,20 @@ public function bucketsCount(int $bucketsCount): self return $this; } + /** + * The process memory past which buckets move to the storage; defaults to MemoryLimit::default(). + */ + public function memoryLimit(Unit $memoryLimit): self + { + if ($memoryLimit->inBytes() < 1) { + throw new InvalidArgumentException('Group by memory limit must be greater than 0 bytes'); + } + + $this->memoryLimit = $memoryLimit; + + return $this; + } + public function storage(BucketsStorage $storage): self { $this->bucketing->storage($storage); diff --git a/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByConfig.php b/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByConfig.php index e3726c3629..6442002dd7 100644 --- a/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByConfig.php +++ b/src/core/etl/src/Flow/ETL/Config/Grouping/HashGroupByConfig.php @@ -5,10 +5,12 @@ namespace Flow\ETL\Config\Grouping; use Flow\ETL\Config\Bucketing\BucketingConfig; +use Flow\ETL\Dataset\Memory\Unit; final readonly class HashGroupByConfig { public function __construct( public BucketingConfig $bucketing, + public Unit $memoryLimit, ) {} } diff --git a/src/core/etl/src/Flow/ETL/Config/Join/HashJoinBuilder.php b/src/core/etl/src/Flow/ETL/Config/Join/HashJoinBuilder.php index e009e6f8d6..77d9c775f4 100644 --- a/src/core/etl/src/Flow/ETL/Config/Join/HashJoinBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Join/HashJoinBuilder.php @@ -7,12 +7,17 @@ use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Column\Backend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; +use Flow\ETL\Config\MemoryLimit; +use Flow\ETL\Dataset\Memory\Unit; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\Filesystem\Path; final class HashJoinBuilder implements JoinAlgorithmBuilder { private readonly BucketingConfigBuilder $bucketing; + private ?Unit $memoryLimit = null; + public function __construct() { $this->bucketing = new BucketingConfigBuilder('/flow-php-join/', 64); @@ -30,7 +35,10 @@ public function batchSize(int $batchSize): self public function build(Path $spillRoot, Backend $backend): HashJoinConfig { - return new HashJoinConfig($this->bucketing->build($spillRoot, $backend)); + return new HashJoinConfig( + $this->bucketing->build($spillRoot, $backend), + $this->memoryLimit ?? MemoryLimit::default(), + ); } /** @@ -43,6 +51,21 @@ public function bucketsCount(int $bucketsCount): self return $this; } + /** + * The process memory past which the build side and the buckets move to the storage; defaults to + * MemoryLimit::default(). + */ + public function memoryLimit(Unit $memoryLimit): self + { + if ($memoryLimit->inBytes() < 1) { + throw new InvalidArgumentException('Join memory limit must be greater than 0 bytes'); + } + + $this->memoryLimit = $memoryLimit; + + return $this; + } + public function storage(BucketsStorage $storage): self { $this->bucketing->storage($storage); diff --git a/src/core/etl/src/Flow/ETL/Config/Join/HashJoinConfig.php b/src/core/etl/src/Flow/ETL/Config/Join/HashJoinConfig.php index 3f73c02318..9249a875d3 100644 --- a/src/core/etl/src/Flow/ETL/Config/Join/HashJoinConfig.php +++ b/src/core/etl/src/Flow/ETL/Config/Join/HashJoinConfig.php @@ -5,10 +5,12 @@ namespace Flow\ETL\Config\Join; use Flow\ETL\Config\Bucketing\BucketingConfig; +use Flow\ETL\Dataset\Memory\Unit; final readonly class HashJoinConfig { public function __construct( public BucketingConfig $bucketing, + public Unit $memoryLimit, ) {} } diff --git a/src/core/etl/src/Flow/ETL/Config/MemoryLimit.php b/src/core/etl/src/Flow/ETL/Config/MemoryLimit.php new file mode 100644 index 0000000000..fa6006a3f7 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Config/MemoryLimit.php @@ -0,0 +1,39 @@ +limit() ?? Unit::fromGb(self::WITHOUT_MEMORY_LIMIT_GB) + ); + } +} diff --git a/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionBuilder.php b/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionBuilder.php index a46f2073fb..fde31e314d 100644 --- a/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionBuilder.php @@ -7,12 +7,17 @@ use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Column\Backend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; +use Flow\ETL\Config\MemoryLimit; +use Flow\ETL\Dataset\Memory\Unit; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\Filesystem\Path; final class HashRepartitionBuilder implements RepartitionAlgorithmBuilder { private readonly BucketingConfigBuilder $bucketing; + private ?Unit $memoryLimit = null; + public function __construct() { $this->bucketing = new BucketingConfigBuilder('/flow-php-repartition/', 64); @@ -30,7 +35,10 @@ public function batchSize(int $batchSize): self public function build(Path $spillRoot, Backend $backend): HashRepartitionConfig { - return new HashRepartitionConfig($this->bucketing->build($spillRoot, $backend)); + return new HashRepartitionConfig( + $this->bucketing->build($spillRoot, $backend), + $this->memoryLimit ?? MemoryLimit::default(), + ); } /** @@ -43,6 +51,20 @@ public function bucketsCount(int $bucketsCount): self return $this; } + /** + * The process memory past which buckets move to the storage; defaults to MemoryLimit::default(). + */ + public function memoryLimit(Unit $memoryLimit): self + { + if ($memoryLimit->inBytes() < 1) { + throw new InvalidArgumentException('Repartition memory limit must be greater than 0 bytes'); + } + + $this->memoryLimit = $memoryLimit; + + return $this; + } + public function storage(BucketsStorage $storage): self { $this->bucketing->storage($storage); diff --git a/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionConfig.php b/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionConfig.php index 33a7009206..c5edeff752 100644 --- a/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionConfig.php +++ b/src/core/etl/src/Flow/ETL/Config/Repartition/HashRepartitionConfig.php @@ -5,10 +5,12 @@ namespace Flow\ETL\Config\Repartition; use Flow\ETL\Config\Bucketing\BucketingConfig; +use Flow\ETL\Dataset\Memory\Unit; final readonly class HashRepartitionConfig { public function __construct( public BucketingConfig $bucketing, + public Unit $memoryLimit, ) {} } diff --git a/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortBuilder.php b/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortBuilder.php index b6fed07d07..957c363118 100644 --- a/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortBuilder.php @@ -7,6 +7,8 @@ use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Column\Backend; use Flow\ETL\Config\Bucketing\BucketingConfigBuilder; +use Flow\ETL\Config\MemoryLimit; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Filesystem\Path; @@ -16,10 +18,7 @@ final class ExternalSortBuilder implements SortAlgorithmBuilder private ?BucketsStorage $mergeStorage = null; - /** - * @var int<1, max> - */ - private int $runSize = 10_000; + private ?Unit $memoryLimit = null; public function __construct() { @@ -40,8 +39,8 @@ public function build(Path $spillRoot, Backend $backend): ExternalSortConfig { return new ExternalSortConfig( $this->bucketing->build($spillRoot, $backend), + $this->memoryLimit ?? MemoryLimit::default(), $this->mergeStorage, - $this->runSize, ); } @@ -66,16 +65,15 @@ public function mergeStorage(BucketsStorage $storage): self } /** - * @param int<1, max> $runSize + * The process memory past which the sort spills sorted runs; defaults to MemoryLimit::default(). */ - public function runSize(int $runSize): self + public function memoryLimit(Unit $memoryLimit): self { - // @mago-ignore analysis:impossible-condition,redundant-comparison - if ($runSize < 1) { - throw new InvalidArgumentException('Run size must be greater than 0'); + if ($memoryLimit->inBytes() < 1) { + throw new InvalidArgumentException('Sort memory limit must be greater than 0 bytes'); } - $this->runSize = $runSize; + $this->memoryLimit = $memoryLimit; return $this; } diff --git a/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortConfig.php b/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortConfig.php index eb87958672..52a74737d6 100644 --- a/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortConfig.php +++ b/src/core/etl/src/Flow/ETL/Config/Sort/ExternalSortConfig.php @@ -6,17 +6,18 @@ use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Config\Bucketing\BucketingConfig; +use Flow\ETL\Dataset\Memory\Unit; final readonly class ExternalSortConfig { /** * @param BucketingConfig $bucketing - the spill side + * @param Unit $memoryLimit - memory the sort holds (sorting in memory) before it spills sorted runs * @param null|BucketsStorage $merge - null means the merged runs go to the same storage the spill uses - * @param int<1, max> $runSize - rows buffered and sorted in memory before they are spilled as one run */ public function __construct( public BucketingConfig $bucketing, + public Unit $memoryLimit, public ?BucketsStorage $merge = null, - public int $runSize = 10_000, ) {} } diff --git a/src/core/etl/src/Flow/ETL/Constraint.php b/src/core/etl/src/Flow/ETL/Constraint.php index a6a0c7cf34..12eca63381 100644 --- a/src/core/etl/src/Flow/ETL/Constraint.php +++ b/src/core/etl/src/Flow/ETL/Constraint.php @@ -6,9 +6,12 @@ interface Constraint { - public function isSatisfiedBy(Row $row, Schema $schema): bool; + /** + * Index of the first row that violates; state advances over the rows before it. + */ + public function firstViolation(Rows $rows): ?int; public function toString(): string; - public function violation(Row $row, Schema $schema): string; + public function violation(Rows $rows, int $index): string; } diff --git a/src/core/etl/src/Flow/ETL/Constraint/SortedByConstraint.php b/src/core/etl/src/Flow/ETL/Constraint/SortedByConstraint.php index 548564301f..8f90d265ee 100644 --- a/src/core/etl/src/Flow/ETL/Constraint/SortedByConstraint.php +++ b/src/core/etl/src/Flow/ETL/Constraint/SortedByConstraint.php @@ -4,30 +4,23 @@ namespace Flow\ETL\Constraint; -use DateInterval; -use DateTimeInterface; use Flow\ETL\Constraint; -use Flow\ETL\Row; +use Flow\ETL\Row\NullsOrder; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; -use Flow\ETL\Row\SortOrder; -use Flow\ETL\Schema; +use Flow\ETL\Rows; +use Flow\ETL\Sort\RowOrder; use Flow\Types\Type\TypedValueFormatter; use function implode; -use function is_array; -use function is_numeric; -use function is_string; use function var_export; final class SortedByConstraint implements Constraint { - private bool $firstRow = true; - /** - * @var array|bool|float|int|object|string> + * The last accepted row, one-row batch - the "previous" of the next batch's first row. */ - private array $previousValues = []; + private ?Rows $previous = null; private readonly References $references; @@ -36,71 +29,33 @@ public function __construct(Reference $column, Reference ...$columns) $this->references = new References($column, ...$columns); } - public function isSatisfiedBy(Row $row, Schema $schema): bool + public function firstViolation(Rows $rows): ?int { - if ($this->firstRow) { - foreach ($this->references->all() as $reference) { - $this->previousValues[$reference->name()] = $row->get($reference); - } - $this->firstRow = false; - - return true; + if ($rows->isEmpty()) { + return null; } - foreach ($this->references->all() as $reference) { - $currentValue = $row->get($reference); - $previousValue = $this->previousValues[$reference->name()]; - - $direction = $reference->sort(); - - if ($previousValue === null && $currentValue === null) { - $comparison = 0; - } elseif ($previousValue === null) { - $comparison = $direction === SortOrder::ASC ? -1 : 1; - } elseif ($currentValue === null) { - $comparison = $direction === SortOrder::ASC ? 1 : -1; - } elseif (is_numeric($previousValue) && is_numeric($currentValue)) { - $prev = (float) $previousValue; - $curr = (float) $currentValue; - $comparison = $direction === SortOrder::ASC ? $prev <=> $curr : $curr <=> $prev; - } elseif (is_string($previousValue) && is_string($currentValue)) { - $comparison = $direction === SortOrder::ASC - ? $previousValue <=> $currentValue - : $currentValue <=> $previousValue; - } elseif ($previousValue instanceof DateTimeInterface && $currentValue instanceof DateTimeInterface) { - $comparison = $direction === SortOrder::ASC - ? $previousValue <=> $currentValue - : $currentValue <=> $previousValue; - } elseif ($previousValue instanceof DateInterval && $currentValue instanceof DateInterval) { - $comparison = $direction === SortOrder::ASC - ? $previousValue <=> $currentValue - : $currentValue <=> $previousValue; - } elseif (is_array($previousValue) && is_array($currentValue)) { - $comparison = $direction === SortOrder::ASC - ? $previousValue <=> $currentValue - : $currentValue <=> $previousValue; - } else { - $comparison = 0; - } - - if ($comparison < 0) { - foreach ($this->references->all() as $ref) { - $this->previousValues[$ref->name()] = $row->get($ref); - } + $order = new RowOrder($this->references->all()); + $keys = $order->keys($rows); + $violation = null; - return true; - } + if ($this->previous !== null && $order->compare($order->keys($this->previous), 0, $keys, 0) > 0) { + $violation = 0; + } - if ($comparison > 0) { - return false; + for ($i = 1, $count = $rows->count(); $violation === null && $i < $count; $i++) { + if ($order->compare($keys, $i - 1, $keys, $i) > 0) { + $violation = $i; } } - foreach ($this->references->all() as $reference) { - $this->previousValues[$reference->name()] = $row->get($reference); + $last = ($violation ?? $rows->count()) - 1; + + if ($last >= 0) { + $this->previous = $rows->slice($last, 1); } - return true; + return $violation; } public function toString(): string @@ -108,27 +63,36 @@ public function toString(): string $columns = []; foreach ($this->references->all() as $reference) { - $columns[] = $reference->name() . ' ' . $reference->sort()->name; + $columns[] = + $reference->name() + . ' ' + . $reference->sort()->name + . ( + $reference->nulls() === NullsOrder::defaultFor($reference->sort()) + ? '' + : ' NULLS ' . $reference->nulls()->name + ); } return sprintf('Sorted constraint on [%s]', implode(', ', $columns)); } - public function violation(Row $row, Schema $schema): string + public function violation(Rows $rows, int $index): string { $formatter = new TypedValueFormatter(); $violations = []; foreach ($this->references->all() as $reference) { - $definition = $schema->get($reference); - $previousValue = $this->previousValues[$reference->name()] ?? null; + $definition = $rows->schema()->get($reference); + // @mago-ignore analysis:mixed-assignment + $previousValue = $this->previous?->column($reference->base())->value(0); $violations[] = sprintf( '%s<%s> expected %s order, current: %s, previous: %s', $reference->name(), $definition->type()->toString(), $reference->sort()->name, - $formatter->format($definition->type(), $row->get($reference)), + $formatter->format($definition->type(), $rows->column($reference->base())->value($index)), $previousValue === null ? 'null' : var_export($previousValue, true), ); } diff --git a/src/core/etl/src/Flow/ETL/Constraint/UniqueConstraint.php b/src/core/etl/src/Flow/ETL/Constraint/UniqueConstraint.php index e244eb41b6..073fc36e5f 100644 --- a/src/core/etl/src/Flow/ETL/Constraint/UniqueConstraint.php +++ b/src/core/etl/src/Flow/ETL/Constraint/UniqueConstraint.php @@ -7,10 +7,10 @@ use Flow\ETL\Constraint; use Flow\ETL\Constraint\UniqueConstraint\InMemoryStorage; use Flow\ETL\Constraint\UniqueConstraint\Storage; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; -use Flow\ETL\Schema; +use Flow\ETL\Rows; +use Flow\ETL\Rows\RowHashes; use Flow\Types\Type\TypedValueFormatter; use function Flow\ETL\DSL\refs; @@ -21,36 +21,27 @@ final class UniqueConstraint implements Constraint private Storage $storage; - /** - * Rows arrive batch by batch and Rows::schema() hands out the same instance for a whole batch, - * so the kept schema is folded once per batch instead of once per row. - */ - private ?Schema $keptSchema = null; - - private ?Schema $keptSchemaSource = null; - public function __construct(string|Reference $column, string|Reference ...$columns) { $this->reference = refs($column, ...$columns); $this->storage = new InMemoryStorage(); } - public function isSatisfiedBy(Row $row, Schema $schema): bool + public function firstViolation(Rows $rows): ?int { - if ($this->keptSchema === null || $this->keptSchemaSource !== $schema) { - $this->keptSchema = $schema->keep(...$this->reference); - $this->keptSchemaSource = $schema; + if ($rows->isEmpty()) { + return null; } - $key = $row->hash($this->keptSchema); + foreach ((new RowHashes())->of($rows->project($rows->schema()->keep(...$this->reference))) as $i => $key) { + if ($this->storage->has($key)) { + return $i; + } - if ($this->storage->has($key)) { - return false; + $this->storage->set($key); } - $this->storage->set($key); - - return true; + return null; } public function toString(): string @@ -61,19 +52,19 @@ public function toString(): string ))); } - public function violation(Row $row, Schema $schema): string + public function violation(Rows $rows, int $index): string { $formatter = new TypedValueFormatter(); $violations = []; - foreach ($schema->keep(...$this->reference)->definitions() as $definition) { + foreach ($rows->schema()->keep(...$this->reference)->definitions() as $definition) { $name = $definition->entry()->name(); $violations[] = $name . '<' . $definition->type()->toString() . '> = ' - . $formatter->format($definition->type(), $row->get($name)); + . $formatter->format($definition->type(), $rows->column($name)->value($index)); } return sprintf('Values: [%s]', implode(', ', $violations)); diff --git a/src/core/etl/src/Flow/ETL/DSL/functions.php b/src/core/etl/src/Flow/ETL/DSL/functions.php index 9359bc3db2..fa0f208ef3 100644 --- a/src/core/etl/src/Flow/ETL/DSL/functions.php +++ b/src/core/etl/src/Flow/ETL/DSL/functions.php @@ -149,7 +149,6 @@ use Flow\ETL\Memory\Memory; use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\RandomValueGenerator; -use Flow\ETL\Row; use Flow\ETL\Row\ColumnName; use Flow\ETL\Row\Formatter\ASCIISchemaFormatter; use Flow\ETL\Row\Reference; @@ -219,8 +218,6 @@ use Flow\ETL\WithEntry; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; -use Flow\Filesystem\Partition; -use Flow\Filesystem\Partitions; use Flow\Filesystem\Path; use Flow\Filesystem\Stream\Mode; use Flow\Floe\FloeSerializer; @@ -573,9 +570,9 @@ function rename_map(array $renames): RenameMapEntryStrategy } #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] -function rows(Schema $schema, Row ...$row): Rows +function rows(Schema $schema): Rows { - return Rows::of($schema, ...$row); + return Rows::empty($schema); } /** @@ -1165,26 +1162,6 @@ function number_format( return new NumberFormat($value, $decimals, $decimal_separator, $thousands_separator); } -/** - * @param array>|array $data - * @param array|Partitions $partitions - */ -#[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] -function array_to_row( - array $data, - Schema $schema, - Backend $backend = new DefaultBackend(), - array|Partitions $partitions = [], -): Row { - foreach ($partitions as $partition) { - if (!array_key_exists($partition->name, $data)) { - $data[$partition->name] = $partition->value; - } - } - - return array_to_rows([$data], $schema, $backend)->first(); -} - /** * @param array>|array $data */ @@ -1251,9 +1228,13 @@ function dense_rank(): DenseRank } #[DocumentationDSL(module: Module::CORE, type: DSLType::AGGREGATING_FUNCTION)] -function average(Reference|string $ref, int $scale = 2, Rounding $rounding = Rounding::HALF_UP): Average -{ - return new Average(is_string($ref) ? ref($ref) : $ref, $scale, $rounding); +function average( + Reference|string $ref, + int $scale = 2, + Rounding $rounding = Rounding::HALF_UP, + bool $exact = false, +): Average { + return new Average(is_string($ref) ? ref($ref) : $ref, $scale, $rounding, $exact); } #[DocumentationDSL(module: Module::CORE, type: DSLType::SCALAR_FUNCTION)] @@ -1323,7 +1304,7 @@ function unbounded_following(): FrameBound } #[DocumentationDSL(module: Module::CORE, type: DSLType::AGGREGATING_FUNCTION)] -function sum(Reference|string $ref, ScalarFunction|bool $exact = false): Sum +function sum(Reference|string $ref, bool $exact = false): Sum { return new Sum(is_string($ref) ? ref($ref) : $ref, $exact); } diff --git a/src/core/etl/src/Flow/ETL/DataFrame.php b/src/core/etl/src/Flow/ETL/DataFrame.php index a5a3ffb931..67a3e7de7b 100644 --- a/src/core/etl/src/Flow/ETL/DataFrame.php +++ b/src/core/etl/src/Flow/ETL/DataFrame.php @@ -213,8 +213,8 @@ public function count(): int ->planner() ->plan(Trigger::count->plan($this->root, $this->sinks), $this->context), ) - ->first() - ->get('count'), + ->column('count') + ->value(0), ); } @@ -415,8 +415,8 @@ public function getEachAsArray(): Generator ->execute( $this->context->config->planner()->plan(Trigger::rows->plan($this->root, $this->sinks), $this->context), ) as $rows) { - foreach ($rows as $row) { - yield $row->toArray(); + foreach ($rows->toArray() as $row) { + yield $row; } } } diff --git a/src/core/etl/src/Flow/ETL/Dataset/Memory/BoundedRead.php b/src/core/etl/src/Flow/ETL/Dataset/Memory/BoundedRead.php new file mode 100644 index 0000000000..cb2972cc34 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Dataset/Memory/BoundedRead.php @@ -0,0 +1,59 @@ + $read + * @param Generator $rest + * + * @return Generator the batches already read, then what is left of $rest + */ + public function followedBy(array $read, Generator $rest): Generator + { + yield from $read; + + // a started generator is never rewound, and PHP refuses to yield from one that already finished + if ($rest->valid()) { + yield from $rest; + } + } + + /** + * Reads $rows while the process stays under the limit; $rows is left at the first batch not read. + * + * @param Generator $rows + * + * @return array{list, bool} the batches read, and whether $rows ended within the limit + */ + public function read(Generator $rows): array + { + $budget = new MemoryBudget($this->backend, $this->limit); + $read = []; + + while ($rows->valid()) { + /** @var Rows $batch valid() holds, so current() is a batch */ + $batch = $rows->current(); + $read[] = $batch; + $rows->next(); + + if ($budget->exceeded()) { + return [$read, false]; + } + } + + return [$read, true]; + } +} diff --git a/src/core/etl/src/Flow/ETL/Dataset/Memory/MemoryBudget.php b/src/core/etl/src/Flow/ETL/Dataset/Memory/MemoryBudget.php new file mode 100644 index 0000000000..080154c23c --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Dataset/Memory/MemoryBudget.php @@ -0,0 +1,36 @@ +consumption = new Consumption($backend, realMemory: false); + } + + public function exceeded(): bool + { + return $this->consumption->capture()->isGreaterThan($this->limit); + } + + /** + * After a spill freed its buffer: hands the memory PHP keeps cached back to the OS. + */ + public function released(): void + { + gc_mem_caches(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Dataset/Statistics/Column.php b/src/core/etl/src/Flow/ETL/Dataset/Statistics/Column.php index 7afb82c907..7811d15af3 100644 --- a/src/core/etl/src/Flow/ETL/Dataset/Statistics/Column.php +++ b/src/core/etl/src/Flow/ETL/Dataset/Statistics/Column.php @@ -6,8 +6,10 @@ use DateTimeInterface; use DateTimeZone; +use Flow\ETL\Column\Column as ColumnData; use Flow\ETL\Row\Reference; use Flow\ETL\Schema\Definition; +use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; use Flow\Types\Type\Logical\ListType; @@ -23,11 +25,13 @@ use function count; use function Flow\Types\DSL\type_instance_of; +use function intdiv; use function is_bool; use function is_countable; use function is_float; use function is_int; use function is_scalar; +use function is_string; use function json_encode; use function max; use function mb_strlen; @@ -58,84 +62,41 @@ final class Column * * @throws \JsonException */ - public function __construct(Definition $definition, mixed $value) + public function __construct(Definition $definition, ColumnData $column) { $this->reference = $definition->entry(); $this->distinctCounter = new DistinctCounter(); - $this->add($definition, $value); + $this->add($definition, $column); } /** * @param Definition $definition + * + * @throws \JsonException */ - public function add(Definition $definition, mixed $value): void + public function add(Definition $definition, ColumnData $column): void { if ($this->reference->name() !== $definition->entry()->name()) { return; } - $type = $definition->type(); - - if ($value === null) { - $this->nullsCount++; - - return; - } - - if ($type instanceof UuidType) { - $this->distinctCounter->add(type_instance_of(Uuid::class)->assert($value)->toString()); + $this->nullsCount += $column->nullCount(); + if ($column->nullCount() === $column->count()) { return; } - if ($type instanceof TimeZoneType) { - $this->distinctCounter->add(type_instance_of(DateTimeZone::class)->assert($value)->getName()); - - return; - } - - if ($type instanceof StructureType) { - $this->distinctCounter->add(json_encode($value, JSON_THROW_ON_ERROR)); - - return; - } - - if ($type instanceof ListType || $type instanceof MapType) { - $this->distinctCounter->add(json_encode($value, JSON_THROW_ON_ERROR)); - $elementsCount = is_countable($value) ? count($value) : 0; - $this->maxElementsCount = max($this->maxElementsCount ?? $elementsCount, $elementsCount); - $this->minElementsCount = min($this->minElementsCount ?? $elementsCount, $elementsCount); - - return; - } - - if (is_scalar($value) || $value instanceof DateTimeInterface) { - $this->distinctCounter->add($value); - } - - if ($type instanceof StringType) { - $valueLength = mb_strlen(is_scalar($value) ? (string) $value : ''); - $this->maxLength = max($this->maxLength ?? $valueLength, $valueLength); - $this->minLength = min($this->minLength ?? $valueLength, $valueLength); - - return; - } - - if ($type instanceof DateType || $type instanceof DateTimeType) { - if ($value instanceof DateTimeInterface) { - $this->max = max($this->max ?? $value, $value); - $this->min = min($this->min ?? $value, $value); - } - - return; - } + $type = $definition->type(); - if ($type instanceof IntegerType || $type instanceof FloatType || $type instanceof BooleanType) { - if (is_int($value) || is_float($value) || is_bool($value)) { - $this->min = min($this->min ?? $value, $value); - $this->max = max($this->max ?? $value, $value); - } - } + match (true) { + $type instanceof StringType => $this->strings($column->physicals()), + $type instanceof IntegerType, $type instanceof FloatType, $type instanceof BooleanType => $this->scalars( + $column->physicals(), + ), + $type instanceof DateTimeType => $this->instants($column, 1_000_000), + $type instanceof DateType => $this->instants($column, 1), + default => $this->values($type, $column->values()), + }; } public function distinctCount(): int @@ -187,4 +148,128 @@ public function reference(): Reference { return $this->reference; } + + /** + * Date physicals are days, datetime physicals microseconds: the distinct key is the Unix second, as + * DateTimeInterface::getTimestamp() gives it, and only the two extremes are materialised. + * + * @param int $perSecond physical units per second, or 1 for days + */ + private function instants(ColumnData $column, int $perSecond): void + { + $min = null; + $max = null; + + // @mago-ignore analysis:mixed-assignment + foreach ($column->physicals() as $i => $physical) { + if (!is_int($physical)) { + continue; + } + + $seconds = $perSecond === 1 ? $physical * 86_400 : intdiv($physical, $perSecond); + + if ($perSecond !== 1 && ($physical % $perSecond) < 0) { + $seconds--; + } + + $this->distinctCounter->add($seconds); + + if ($min === null || $physical < $min[1]) { + $min = [$i, $physical]; + } + + if ($max === null || $physical > $max[1]) { + $max = [$i, $physical]; + } + } + + if ($min === null || $max === null) { + return; + } + + $minValue = type_instance_of(DateTimeInterface::class)->assert($column->value($min[0])); + $maxValue = type_instance_of(DateTimeInterface::class)->assert($column->value($max[0])); + $this->min = min($this->min ?? $minValue, $minValue); + $this->max = max($this->max ?? $maxValue, $maxValue); + } + + /** + * @param list $physicals + */ + private function scalars(array $physicals): void + { + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $value) { + if (is_int($value) || is_float($value) || is_bool($value)) { + $this->distinctCounter->add($value); + $this->min = min($this->min ?? $value, $value); + $this->max = max($this->max ?? $value, $value); + } + } + } + + /** + * @param list $physicals + */ + private function strings(array $physicals): void + { + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $value) { + if (!is_string($value)) { + continue; + } + + $this->distinctCounter->add($value); + $valueLength = mb_strlen($value); + $this->maxLength = max($this->maxLength ?? $valueLength, $valueLength); + $this->minLength = min($this->minLength ?? $valueLength, $valueLength); + } + } + + /** + * @param Type $type + * @param list $values + * + * @throws \JsonException + */ + private function values(Type $type, array $values): void + { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $value) { + if ($value === null) { + continue; + } + + if ($type instanceof UuidType) { + $this->distinctCounter->add(type_instance_of(Uuid::class)->assert($value)->toString()); + + continue; + } + + if ($type instanceof TimeZoneType) { + $this->distinctCounter->add(type_instance_of(DateTimeZone::class)->assert($value)->getName()); + + continue; + } + + if ($type instanceof StructureType) { + $this->distinctCounter->add(json_encode($value, JSON_THROW_ON_ERROR)); + + continue; + } + + if ($type instanceof ListType || $type instanceof MapType) { + $this->distinctCounter->add(json_encode($value, JSON_THROW_ON_ERROR)); + $elementsCount = is_countable($value) ? count($value) : 0; + $this->maxElementsCount = max($this->maxElementsCount ?? $elementsCount, $elementsCount); + $this->minElementsCount = min($this->minElementsCount ?? $elementsCount, $elementsCount); + + continue; + } + + if (is_scalar($value) || $value instanceof DateTimeInterface) { + $this->distinctCounter->add($value); + } + } + } } diff --git a/src/core/etl/src/Flow/ETL/Dataset/Statistics/Columns.php b/src/core/etl/src/Flow/ETL/Dataset/Statistics/Columns.php index 61a54bc116..3434db6223 100644 --- a/src/core/etl/src/Flow/ETL/Dataset/Statistics/Columns.php +++ b/src/core/etl/src/Flow/ETL/Dataset/Statistics/Columns.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Dataset\Statistics; +use Flow\ETL\Column\Column as ColumnData; use Flow\ETL\Row\Reference; use Flow\ETL\Schema\Definition; use InvalidArgumentException; @@ -21,23 +22,20 @@ final class Columns public function __construct() {} - /** - * @param Entry $entry - */ /** * @param Definition $definition */ - public function add(Definition $definition, mixed $value): void + public function add(Definition $definition, ColumnData $column): void { $name = $definition->entry()->name(); if (!array_key_exists($name, $this->columns)) { - $this->columns[$name] = new Column($definition, $value); + $this->columns[$name] = new Column($definition, $column); return; } - $this->columns[$name]->add($definition, $value); + $this->columns[$name]->add($definition, $column); } /** diff --git a/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php b/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php index fe66d77537..e112e792d2 100644 --- a/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php +++ b/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php @@ -66,6 +66,17 @@ public static function unsupportedType(Definition $definition, string $reason): )); } + /** + * @param Definition $definition + */ + public static function untypedColumn(Definition $definition): self + { + return new self( + $definition->entry()->name(), + ': mixed cannot be a batch column, an untyped function result exists only inside function evaluation', + ); + } + /** * @param Definition $definition */ diff --git a/src/core/etl/src/Flow/ETL/Exception/EvaluationException.php b/src/core/etl/src/Flow/ETL/Exception/EvaluationException.php new file mode 100644 index 0000000000..a31932763a --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Exception/EvaluationException.php @@ -0,0 +1,30 @@ +getMessage(), $rowIndex), 0, $cause); + } + + /** + * $cause at $rowIndex of the caller's batch; an EvaluationException cause is re-indexed, never nested. + */ + public static function at(int $rowIndex, BaseException $cause): self + { + return $cause instanceof self + ? new self($rowIndex, type_instance_of(BaseException::class)->assert($cause->getPrevious())) + : new self($rowIndex, $cause); + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor.php b/src/core/etl/src/Flow/ETL/Executor.php index 63e2543660..44ebdcc6af 100644 --- a/src/core/etl/src/Flow/ETL/Executor.php +++ b/src/core/etl/src/Flow/ETL/Executor.php @@ -15,6 +15,7 @@ use WeakMap; use function array_reverse; +use function array_slice; use function sprintf; final readonly class Executor @@ -94,20 +95,29 @@ public function fetch(PhysicalPlan $plan): Rows */ public function merge(Generator $batches, PhysicalPlan $plan): Rows { - $rows = null; + $last = null; + $parts = []; - foreach ($batches as $nextRows) { - $rows = $rows === null ? $nextRows : $rows->merge($nextRows); + foreach ($batches as $batch) { + $last = $batch; + + if (!$batch->isEmpty()) { + $parts[] = $batch; + } + } + + if ($parts !== []) { + return $parts[0]->concat(...array_slice($parts, 1)); } - if ($rows !== null) { - return $rows; + if ($last !== null) { + return $last; } try { - return Rows::of($plan->schema()); + return Rows::empty($plan->schema()); } catch (SchemaNotDerivableException) { - return Rows::of(new Schema()); + return Rows::empty(new Schema()); } } diff --git a/src/core/etl/src/Flow/ETL/Executor/Segment.php b/src/core/etl/src/Flow/ETL/Executor/Segment.php index 965693ff22..b504ba8901 100644 --- a/src/core/etl/src/Flow/ETL/Executor/Segment.php +++ b/src/core/etl/src/Flow/ETL/Executor/Segment.php @@ -130,7 +130,7 @@ public function execute(Generator $input, FlowContext $context): Generator } catch (LimitReachedException $limit) { $context->telemetry()->limitReached(['limit' => $limit->limit]); // the remaining steps still run, on the trimmed batch - $rows = $limit->rows ?? Rows::of($rows->schema()); + $rows = $limit->rows ?? Rows::empty($rows->schema()); $stop = true; } catch (Throwable $failure) { if ($failure instanceof SinkFailure) { diff --git a/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php b/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php index 8ac3d1f8d8..b94a1a9e7e 100644 --- a/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php +++ b/src/core/etl/src/Flow/ETL/Executor/StatisticsCollector.php @@ -82,15 +82,9 @@ public function capture(Rows $rows): void $this->schema = $this->schema->merge($rows->schema()); } - if ($this->columnStatistics !== null) { - foreach ($rows->all() as $row) { - foreach ($rows->schema()->definitions() as $definition) { - $name = $definition->entry()->name(); - - if ($row->has($name)) { - $this->columnStatistics->add($definition, $row->get($name)); - } - } + if ($this->columnStatistics !== null && !$rows->isEmpty()) { + foreach ($rows->schema()->definitions() as $name => $definition) { + $this->columnStatistics->add($definition, $rows->column($name)); } } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php index 8a0ff089b6..49649d73d0 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php @@ -7,13 +7,12 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; use Flow\ETL\FlowContext; +use Flow\ETL\Processor\BatchingByProcessor; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; -use function array_shift; - final class BatchByExtractor implements Extractor, OverridingExtractor, RewindableExtractor { private ?Schema $schema = null; @@ -44,61 +43,27 @@ public function isRepeatable(): bool */ 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() - $schema = $this->schema; - - /** @var list $pending */ - $pending = []; - $pendingCount = 0; - $currentGroupValue = null; - - foreach ($this->extractor->extract($context) as $rows) { - $schema ??= $rows->schema(); - $rows = $rows->matchTo($schema); - - if ($rows->count() === 0) { - continue; - } - - $column = $rows->column($this->column->base()); - $start = 0; - - for ($i = 0; $i < $rows->count(); $i++) { - // @mago-ignore analysis:mixed-assignment - $groupValue = $column->value($i); - - if ($currentGroupValue === null) { - // @mago-ignore analysis:mixed-assignment - $currentGroupValue = $groupValue; - } elseif ($currentGroupValue !== $groupValue) { - if ($this->minSize === null || ($pendingCount + $i - $start) >= $this->minSize) { - $pending[] = $rows->slice($start, $i - $start); - $first = array_shift($pending); - $signal = yield $first->concat(...$pending); - - if ($signal === Signal::STOP) { - return; - } - - $pending = []; - $pendingCount = 0; - $start = $i; - } - - // @mago-ignore analysis:mixed-assignment - $currentGroupValue = $groupValue; - } - } - - $pending[] = $rows->slice($start, $rows->count() - $start); - $pendingCount += $rows->count() - $start; - } + return (new BatchingByProcessor($this->column, $this->minSize))->process( + $this->declared($this->extractor->extract($context)), + $context, + ); + } - $first = array_shift($pending); + /** + * @param Generator $batches + * + * @return Generator + */ + public function declared(Generator $batches): Generator + { + if ($this->schema === null) { + yield from $batches; + + return; + } - if ($first !== null && $pendingCount > 0) { - yield $first->concat(...$pending); + foreach ($batches as $batch) { + yield $batch->matchTo($this->schema); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php index 57d9a5ae02..7f8031afc6 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php @@ -44,7 +44,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator while ($pendingCount >= $this->batchSize) { // one variadic concat per window copies each row once; a pairwise concat per child batch would // re-copy everything pending - $window = Rows::of($schema)->concat(...$pending); + $window = Rows::empty($schema)->concat(...$pending); $signal = yield $window->slice(0, $this->batchSize); if ($signal === Signal::STOP) { @@ -59,7 +59,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator } if ($pendingCount > 0) { - yield Rows::of($schema ?? $this->schema())->concat(...$pending); + yield Rows::empty($schema ?? $this->schema())->concat(...$pending); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php index bed4f53ad8..abfff21eda 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php @@ -32,7 +32,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $collectedRows = $collectedRows === null ? $rows : $collectedRows->merge($rows); } - yield $collectedRows ?? Rows::of($this->schema()); + yield $collectedRows ?? Rows::empty($this->schema()); } public function isRepeatable(): bool diff --git a/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php index 94139bf31a..8b022ee2cc 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php @@ -59,7 +59,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator // is parked, so both operands can change between the yield and this check. if ($this->batch === null && !$this->finished) { // a downstream projection still sees the columns it was built against - $signal = yield Rows::of($this->schema); + $signal = yield Rows::empty($this->schema); if ($signal === Signal::STOP) { return; diff --git a/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php b/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php index 214d0e680c..8f0f12f621 100644 --- a/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php +++ b/src/core/etl/src/Flow/ETL/Filesystem/ScalarFunctionFilter.php @@ -13,7 +13,7 @@ use Flow\Filesystem\Path\Filter; use Throwable; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function sprintf; @@ -72,10 +72,13 @@ public function accept(FileStatus $status): bool } } + $schema = schema(...$definitions); + + // an undeclared partition column resolves against the file's own path value (a str column) // @mago-ignore analysis:mixed-operand - return (bool) $this->resolved->eval( - array_to_row($values, schema(...$definitions), $this->context->backend()), - $this->context, - ); + return (bool) (new ReferenceResolver()) + ->resolve($this->resolved, $schema) + ->eval(array_to_rows([$values], $schema, $this->context->backend()), $this->context) + ->value(0); } } diff --git a/src/core/etl/src/Flow/ETL/Formatter/ASCII/ASCIIBody.php b/src/core/etl/src/Flow/ETL/Formatter/ASCII/ASCIIBody.php index 4a25f58abd..d811f30185 100644 --- a/src/core/etl/src/Flow/ETL/Formatter/ASCII/ASCIIBody.php +++ b/src/core/etl/src/Flow/ETL/Formatter/ASCII/ASCIIBody.php @@ -21,14 +21,17 @@ public function print(int|bool $truncate = 20): string { $buffer = ''; - foreach ($this->body->rows() as $row) { + for ($index = 0, $count = $this->body->count(); $index < $count; $index++) { $buffer .= '|'; foreach ($this->headers->names() as $name) { $header = new ASCIIValue(type_string(), $name); try { - $value = new ASCIIValue($this->body->schema()->get($name)->type(), $row->get($name)); + $value = new ASCIIValue( + $this->body->schema()->get($name)->type(), + $this->body->value($name, $index), + ); } catch (InvalidArgumentException) { $value = new ASCIIValue(type_string(), ''); } diff --git a/src/core/etl/src/Flow/ETL/Formatter/ASCII/Body.php b/src/core/etl/src/Flow/ETL/Formatter/ASCII/Body.php index b502bfbde0..03be77bc0f 100644 --- a/src/core/etl/src/Flow/ETL/Formatter/ASCII/Body.php +++ b/src/core/etl/src/Flow/ETL/Formatter/ASCII/Body.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Formatter\ASCII; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -25,33 +24,36 @@ public function schema(): Schema */ public function maximumLength(string $entry, int|bool $truncate = 20): int { + $definition = $this->schema()->findDefinition($entry); + + if ($definition === null) { + return 0; + } + $max = 0; - foreach ($this->rows as $row) { - try { - $value = new ASCIIValue($this->schema()->get($entry)->type(), $row->get($entry)); + // @mago-ignore analysis:mixed-assignment + foreach ($this->rows->column($definition->entry()->name())->values() as $cell) { + $value = new ASCIIValue($definition->type(), $cell); - if ($value->length($truncate) >= $max) { - $max = $value->length($truncate); - } - } catch (InvalidArgumentException) { + if ($value->length($truncate) >= $max) { + $max = $value->length($truncate); } } return $max; } + public function count(): int + { + return $this->rows->count(); + } + /** - * @return array + * @throws InvalidArgumentException the batch has no $entry column */ - public function rows(): array + public function value(string $entry, int $index): mixed { - $rows = []; - - foreach ($this->rows as $row) { - $rows[] = $row; - } - - return $rows; + return $this->rows->column($entry)->value($index); } } diff --git a/src/core/etl/src/Flow/ETL/Function/AggregatingFunction.php b/src/core/etl/src/Flow/ETL/Function/AggregatingFunction.php index b27b1e4061..41b313624d 100644 --- a/src/core/etl/src/Flow/ETL/Function/AggregatingFunction.php +++ b/src/core/etl/src/Flow/ETL/Function/AggregatingFunction.php @@ -4,14 +4,25 @@ namespace Flow\ETL\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Type; interface AggregatingFunction extends FunctionTree { - public function aggregate(Row $row, FlowContext $context): void; + /** + * @param list $indices the rows of $rows that belong to this aggregate, ascending + */ + public function aggregate(Rows $rows, array $indices, FlowContext $context): void; + + /** + * Folds $other's partial state into this one; $other aggregated rows that come after this one's. + * + * @throws InvalidArgumentException $other is not the same class + */ + public function merge(AggregatingFunction $other, FlowContext $context): void; /** * Decided in the constructor, never mutated. diff --git a/src/core/etl/src/Flow/ETL/Function/All.php b/src/core/etl/src/Flow/ETL/Function/All.php index 5715aaca43..bb7251ad8a 100644 --- a/src/core/etl/src/Flow/ETL/Function/All.php +++ b/src/core/etl/src/Flow/ETL/Function/All.php @@ -4,14 +4,19 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Function\Evaluation\Selection; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; +use function array_key_exists; use function array_map; use function array_values; use function Flow\Types\DSL\type_boolean; +use function range; final readonly class All implements ScalarFunction { @@ -65,25 +70,56 @@ public function returns(): Type )); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $sawNull = false; + $undecided = $rows->isEmpty() ? [] : range(0, $rows->count() - 1); + $results = []; - foreach ($this->functions as $ref) { - $value = (new Parameter($ref))->eval($row, $context); + /** @var array $sawNull */ + $sawNull = []; - if ($value === null) { - $sawNull = true; - - continue; + foreach ($this->functions as $function) { + if ($undecided === []) { + break; } - if (!$value) { - return false; + $column = (new Selection($undecided))->evaluate($function, $rows, $context); + $next = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $k => $value) { + $i = $undecided[$k]; + + if ($value === null) { + $sawNull[$i] = true; + $next[] = $i; + + continue; + } + + if (!$value) { + $results[$i] = false; + + continue; + } + + $next[] = $i; } + + $undecided = $next; + } + + foreach ($undecided as $i) { + $results[$i] = array_key_exists($i, $sawNull) ? null : true; + } + + $ordered = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $ordered[] = $results[$i]; } - return $sawNull ? null : true; + return (new ResultColumn())->of($this, $ordered); } public function or(ScalarFunction $scalarFunction): Any diff --git a/src/core/etl/src/Flow/ETL/Function/Any.php b/src/core/etl/src/Flow/ETL/Function/Any.php index d0941ca813..a772ee85f9 100644 --- a/src/core/etl/src/Flow/ETL/Function/Any.php +++ b/src/core/etl/src/Flow/ETL/Function/Any.php @@ -4,14 +4,19 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Function\Evaluation\Selection; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; +use function array_key_exists; use function array_map; use function array_values; use function Flow\Types\DSL\type_boolean; +use function range; final readonly class Any implements ScalarFunction { @@ -65,25 +70,56 @@ public function returns(): Type )); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $sawNull = false; + $undecided = $rows->isEmpty() ? [] : range(0, $rows->count() - 1); + $results = []; - foreach ($this->functions as $ref) { - $value = (new Parameter($ref))->eval($row, $context); + /** @var array $sawNull */ + $sawNull = []; - if ($value === null) { - $sawNull = true; - - continue; + foreach ($this->functions as $function) { + if ($undecided === []) { + break; } - if ($value) { - return true; + $column = (new Selection($undecided))->evaluate($function, $rows, $context); + $next = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $k => $value) { + $i = $undecided[$k]; + + if ($value === null) { + $sawNull[$i] = true; + $next[] = $i; + + continue; + } + + if ($value) { + $results[$i] = true; + + continue; + } + + $next[] = $i; } + + $undecided = $next; + } + + foreach ($undecided as $i) { + $results[$i] = array_key_exists($i, $sawNull) ? null : false; + } + + $ordered = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $ordered[] = $results[$i]; } - return $sawNull ? null : false; + return (new ResultColumn())->of($this, $ordered); } public function or(ScalarFunction $scalarFunction): self diff --git a/src/core/etl/src/Flow/ETL/Function/Append.php b/src/core/etl/src/Flow/ETL/Function/Append.php index 884139d90f..753806cce8 100644 --- a/src/core/etl/src/Flow/ETL/Function/Append.php +++ b/src/core/etl/src/Flow/ETL/Function/Append.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -51,19 +55,33 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $suffix = (new Parameter($this->suffix))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $suffixes = (new Parameter($this->suffix))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('Append function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $suffix = $suffixes[$i]; + + if ($value === null) { + throw new InvalidArgumentException('Append function requires non-null value'); + } + + if ($suffix === null) { + $results[] = $value; + + continue; + } - if ($suffix === null) { - return $value; + $results[] = s($value)->append($suffix)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->append($suffix)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayExpand.php b/src/core/etl/src/Flow/ETL/Function/ArrayExpand.php index f700854f1f..1a2c886150 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayExpand.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayExpand.php @@ -4,10 +4,12 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Function\ScalarFunction\ExpandResults; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; use Flow\Types\Type\Logical\MapType; @@ -15,6 +17,7 @@ use function array_keys; use function array_map; +use function array_values; use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_map; @@ -80,25 +83,28 @@ public function returns(): Type }; } - /** - * @return array - */ - public function eval(Row $row, FlowContext $context): array + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->ref))->asArray($row, $context); - - if ($array === null) { - return []; - } - - if ($this->expand === ArrayExpand\ArrayExpand::KEYS) { - return array_keys($array); - } - - if ($this->expand === ArrayExpand\ArrayExpand::BOTH) { - return array_map(static fn($key, $value) => [$key => $value], array_keys($array), $array); + $lists = []; + + foreach ((new Parameter($this->ref))->asArrays($rows, $context) as $array) { + if ($array === null) { + $lists[] = []; + + continue; + } + + $lists[] = match ($this->expand) { + ArrayExpand\ArrayExpand::KEYS => array_keys($array), + ArrayExpand\ArrayExpand::BOTH => array_map( + static fn($key, $value) => [$key => $value], + array_keys($array), + $array, + ), + default => array_values($array), + }; } - return $array; + return (new ResultColumn())->lists($this, $lists); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayFilter.php b/src/core/etl/src/Flow/ETL/Function/ArrayFilter.php index 8ab235a16e..f170e852ef 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayFilter.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayFilter.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; @@ -63,16 +67,28 @@ public function returns(): Type return $array; } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->array))->asArray($row, $context); - - if (null === $array) { - throw new InvalidArgumentException('ArrayFilter function requires non-null array'); + $arrays = (new Parameter($this->array))->asArrays($rows, $context); + $values = (new Parameter($this->value))->values($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($arrays as $i => $array) { + // @mago-ignore analysis:mixed-assignment + $value = $values[$i]; + + if (null === $array) { + throw new InvalidArgumentException('ArrayFilter function requires non-null array'); + } + + $results[] = array_filter($array, static fn($item) => $item !== $value); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - $value = (new Parameter($this->value))->eval($row, $context); - - return array_filter($array, static fn($item) => $item !== $value); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayGet.php b/src/core/etl/src/Flow/ETL/Function/ArrayGet.php index e69d5346bd..f972f2f63c 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayGet.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayGet.php @@ -4,13 +4,17 @@ namespace Flow\ETL\Function; +use Exception; use Flow\ArrayDot\Exception\InvalidPathException; use Flow\ArrayDot\Path; use Flow\ArrayDot\Step\Key; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\ArrayKey; use Flow\Types\Type\Logical\StructureType; @@ -100,18 +104,36 @@ public function returns(): Type return $nullable ? (new TypeWidener())->nullable($type) : $type; } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { try { - $value = (new Parameter($this->ref))->asArray($row, $context); + $values = (new Parameter($this->ref))->asArrays($rows, $context); + } catch (EvaluationException $e) { + throw new EvaluationException( + $e->rowIndex, + new InvalidArgumentException('ArrayGet function failed to get value from array.', 0, $e), + ); + } - if ($value === null) { - throw new InvalidArgumentException('ArrayGet function requires non-null array'); - } + $results = []; + $i = 0; - return array_dot_get($value, $this->path); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException('ArrayGet function failed to get value from array.', 0, $e); + try { + foreach ($values as $i => $value) { + try { + if ($value === null) { + throw new InvalidArgumentException('ArrayGet function requires non-null array'); + } + + $results[] = array_dot_get($value, $this->path); + } catch (InvalidArgumentException $e) { + throw new InvalidArgumentException('ArrayGet function failed to get value from array.', 0, $e); + } + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayGetCollection.php b/src/core/etl/src/Flow/ETL/Function/ArrayGetCollection.php index 87a4e5b075..a3a3ec4dcb 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayGetCollection.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayGetCollection.php @@ -4,13 +4,17 @@ namespace Flow\ETL\Function; +use Exception; use Flow\ArrayDot\Exception\InvalidPathException; use Flow\ArrayDot\Path; use Flow\ArrayDot\Step\Key; use Flow\ArrayDot\Step\Multimatch; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function array_map; @@ -76,54 +80,81 @@ public static function fromFirst(ScalarFunction $ref, ScalarFunction|array $keys return new self($ref, $keys, '0'); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { try { - $value = (new Parameter($this->ref))->asArray($row, $context); - $index = (new Parameter($this->index))->asString($row, $context); - $keys = (new Parameter($this->keys))->asArray($row, $context); - - if ($value === null || $index === null || $keys === null) { - throw new InvalidArgumentException( - 'ArrayGetCollection function requires non-null array, index, and keys', - ); - } - - // the keys are literal, so they become Key steps and are never parsed as a path - $keyPaths = array_map(static function (mixed $key): Path { - if (!is_scalar($key)) { - throw new InvalidArgumentException(sprintf( - 'ArrayGetCollection keys must be scalar, got "%s".', - get_debug_type($key), - )); - } + $values = (new Parameter($this->ref))->asArrays($rows, $context); + $indexes = (new Parameter($this->index))->asStrings($rows, $context); + $keysList = (new Parameter($this->keys))->asArrays($rows, $context); + } catch (EvaluationException $e) { + throw new EvaluationException( + $e->rowIndex, + new InvalidArgumentException('ArrayGetCollection function failed to evaluate parameters.', 0, $e), + ); + } - return new Path([new Key((string) $key, nullsafe: true)]); - }, array_values($keys)); - - try { - $array = $index === '0' ? array_values($value) : $value; - - // @mago-ignore analysis:mixed-assignment - $extractedValues = array_dot_get($array, new Path([ - ...Path::fromString($index)->steps, - new Multimatch($keyPaths), - ])); - } catch (InvalidPathException $e) { - throw new InvalidArgumentException( - 'ArrayGetCollection function failed to get values from array.', - 0, - $e, - ); - } + $results = []; + $i = 0; - if (!is_array($extractedValues)) { - throw new InvalidArgumentException('ArrayGetCollection function requires the result to be an array'); + try { + foreach ($values as $i => $value) { + $index = $indexes[$i]; + $keys = $keysList[$i]; + + try { + if ($value === null || $index === null || $keys === null) { + throw new InvalidArgumentException( + 'ArrayGetCollection function requires non-null array, index, and keys', + ); + } + + // the keys are literal, so they become Key steps and are never parsed as a path + $keyPaths = array_map(static function (mixed $key): Path { + if (!is_scalar($key)) { + throw new InvalidArgumentException(sprintf( + 'ArrayGetCollection keys must be scalar, got "%s".', + get_debug_type($key), + )); + } + + return new Path([new Key((string) $key, nullsafe: true)]); + }, array_values($keys)); + + try { + $array = $index === '0' ? array_values($value) : $value; + + // @mago-ignore analysis:mixed-assignment + $extractedValues = array_dot_get($array, new Path([ + ...Path::fromString($index)->steps, + new Multimatch($keyPaths), + ])); + } catch (InvalidPathException $e) { + throw new InvalidArgumentException( + 'ArrayGetCollection function failed to get values from array.', + 0, + $e, + ); + } + + if (!is_array($extractedValues)) { + throw new InvalidArgumentException( + 'ArrayGetCollection function requires the result to be an array', + ); + } + + $results[] = $extractedValues; + } catch (InvalidArgumentException $e) { + throw new InvalidArgumentException( + 'ArrayGetCollection function failed to evaluate parameters.', + 0, + $e, + ); + } } - - return $extractedValues; - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException('ArrayGetCollection function failed to evaluate parameters.', 0, $e); + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayKeep.php b/src/core/etl/src/Flow/ETL/Function/ArrayKeep.php index 140f1ad770..f88c035e51 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayKeep.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayKeep.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; @@ -63,16 +67,28 @@ public function returns(): Type return $array; } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->array))->asArray($row, $context); - - if (null === $array) { - throw new InvalidArgumentException('ArrayKeep function requires non-null array'); + $arrays = (new Parameter($this->array))->asArrays($rows, $context); + $values = (new Parameter($this->value))->values($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($arrays as $i => $array) { + // @mago-ignore analysis:mixed-assignment + $value = $values[$i]; + + if (null === $array) { + throw new InvalidArgumentException('ArrayKeep function requires non-null array'); + } + + $results[] = array_filter($array, static fn($item) => $item === $value); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - $value = (new Parameter($this->value))->eval($row, $context); - - return array_filter($array, static fn($item) => $item === $value); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayKeyRename.php b/src/core/etl/src/Flow/ETL/Function/ArrayKeyRename.php index 657ff8be3b..caa5c4ddfe 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayKeyRename.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayKeyRename.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ArrayDot\array_dot_rename; @@ -47,14 +51,24 @@ public function returns(): Type return type_array(); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->ref))->asArray($row, $context); + $values = (new Parameter($this->ref))->asArrays($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('ArrayKeyRename function requires non-null array'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('ArrayKeyRename function requires non-null array'); + } + + $results[] = array_dot_rename($value, $this->path, $this->newName); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return array_dot_rename($value, $this->path, $this->newName); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayKeys.php b/src/core/etl/src/Flow/ETL/Function/ArrayKeys.php index 0521acdc95..0563e6dcbb 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayKeys.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayKeys.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; use Flow\Types\Type\Logical\MapType; @@ -70,17 +74,24 @@ public function returns(): Type }; } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->array))->asArray($row, $context); + $arrays = (new Parameter($this->array))->asArrays($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($arrays as $i => $array) { + if (!is_array($array)) { + throw new InvalidArgumentException('ArrayKeys function requires non-null array'); + } - if (!is_array($array)) { - throw new InvalidArgumentException('ArrayKeys function requires non-null array'); + $results[] = array_keys($array); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return array_keys($array); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayKeysStyleConvert.php b/src/core/etl/src/Flow/ETL/Function/ArrayKeysStyleConvert.php index c2c14b3316..c3774d7427 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayKeysStyleConvert.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayKeysStyleConvert.php @@ -4,18 +4,28 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Function\StyleConverter\ArrayKeyConverter; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\ETL\String\StringStyles; use Flow\Types\Type; +use Flow\Types\Type\Logical\ListType; +use Flow\Types\Type\Logical\MapType; +use Flow\Types\Type\Logical\OptionalType; use Flow\Types\Type\Logical\StructureType; use function array_key_exists; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_bare; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_optional; final class ArrayKeysStyleConvert implements ScalarFunction { @@ -57,10 +67,39 @@ public function returns(): Type ); } + return $this->converted($array); + } + + /** + * $type with every structure field renamed the way eval() renames keys - at every depth, as ArrayKeyConverter + * recurses into nested arrays. + * + * @param Type $type + * + * @return Type + */ + public function converted(Type $type): Type + { + if ($type instanceof OptionalType) { + return type_optional($this->converted($type->base())); + } + + if ($type instanceof ListType) { + return type_list($this->converted($type->element())); + } + + if ($type instanceof MapType) { + return type_map($type->key(), $this->converted($type->value())); + } + + if (!$type instanceof StructureType) { + return $type; + } + $elements = []; $sources = []; - foreach ($array->elements() as $element) { + foreach ($type->elements() as $element) { $converted = $this->style->convert((string) $element->name); if (array_key_exists($converted, $sources)) { @@ -71,7 +110,7 @@ public function returns(): Type . '" and "' . $element->name . '" of "' - . $array->toString() + . $type->toString() . '" both convert to "' . $converted . '"', @@ -79,22 +118,31 @@ public function returns(): Type } $sources[$converted] = $element->name; - $elements[] = structure_element($converted, $element->type, $element->optional); + $elements[] = structure_element($converted, $this->converted($element->type), $element->optional); } return new StructureType($elements); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->ref))->asArray($row, $context); + $arrays = (new Parameter($this->ref))->asArrays($rows, $context); + $converter = new ArrayKeyConverter(fn(string $key): string => $this->style->convert($key)); + $results = []; + $i = 0; - if ($array === null) { - throw new InvalidArgumentException('ArrayKeysStyleConvert function requires non-null array'); - } + try { + foreach ($arrays as $i => $array) { + if ($array === null) { + throw new InvalidArgumentException('ArrayKeysStyleConvert function requires non-null array'); + } - $converter = new ArrayKeyConverter(fn(string $key): string => $this->style->convert($key)); + $results[] = $converter->convert($array); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } - return $converter->convert($array); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayMerge.php b/src/core/etl/src/Flow/ETL/Function/ArrayMerge.php index 6e7f97fb82..4d7950d0c2 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayMerge.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayMerge.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; @@ -75,18 +79,27 @@ public function returns(): Type return type_array(); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $left = (new Parameter($this->left))->asArray($row, $context); - $right = (new Parameter($this->right))->asArray($row, $context); + $lefts = (new Parameter($this->left))->asArrays($rows, $context); + $rights = (new Parameter($this->right))->asArrays($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($lefts as $i => $left) { + $right = $rights[$i]; + + if ($left === null || $right === null) { + throw new InvalidArgumentException('ArrayMerge function requires two non-null arrays'); + } - if ($left === null || $right === null) { - throw new InvalidArgumentException('ArrayMerge function requires two non-null arrays'); + $results[] = array_merge($left, $right); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return array_merge($left, $right); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayMergeCollection.php b/src/core/etl/src/Flow/ETL/Function/ArrayMergeCollection.php index 35d1b10144..08ef36d891 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayMergeCollection.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayMergeCollection.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; use Flow\Types\Type\Logical\StructureType; @@ -83,27 +87,34 @@ public function returns(): Type ); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->array))->asArray($row, $context); + $arrays = (new Parameter($this->array))->asArrays($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($arrays as $i => $array) { + if ($array === null) { + throw new InvalidArgumentException('ArrayMergeCollection function requires non-null array'); + } - if ($array === null) { - throw new InvalidArgumentException('ArrayMergeCollection function requires non-null array'); - } + // @mago-ignore analysis:mixed-assignment + foreach ($array as $element) { + if (!is_array($element)) { + throw new InvalidArgumentException( + 'ArrayMergeCollection function requires array elements to be arrays', + ); + } + } - // @mago-ignore analysis:mixed-assignment - foreach ($array as $element) { - if (!is_array($element)) { - throw new InvalidArgumentException( - 'ArrayMergeCollection function requires array elements to be arrays', - ); + /** @var array> $array */ + $results[] = array_merge(...array_values($array)); } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - /** @var array> $array */ - return array_merge(...array_values($array)); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayPathExists.php b/src/core/etl/src/Flow/ETL/Function/ArrayPathExists.php index 2b35289a8b..31d23ae164 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayPathExists.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayPathExists.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -55,19 +59,43 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->array->returns(), $this->path->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { try { - $array = (new Parameter($this->array))->asArray($row, $context); - $path = (new Parameter($this->path))->asString($row, $context); + $arrays = (new Parameter($this->array))->asArrays($rows, $context); + $paths = (new Parameter($this->path))->asStrings($rows, $context); + } catch (EvaluationException $e) { + throw new EvaluationException( + $e->rowIndex, + new InvalidArgumentException( + 'ArrayPathExists error: ' . ($e->getPrevious()?->getMessage() ?? $e->getMessage()), + ), + ); + } - if ($array === null || $path === null) { - return null; - } + $results = []; + $i = 0; + + try { + foreach ($arrays as $i => $array) { + $path = $paths[$i]; - return array_dot_exists($array, $path); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException('ArrayPathExists error: ' . $e->getMessage()); + try { + if ($array === null || $path === null) { + $results[] = null; + + continue; + } + + $results[] = array_dot_exists($array, $path); + } catch (InvalidArgumentException $e) { + throw new InvalidArgumentException('ArrayPathExists error: ' . $e->getMessage(), 0, $e); + } + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayReverse.php b/src/core/etl/src/Flow/ETL/Function/ArrayReverse.php index ce4d484d88..6fad2cf0c9 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayReverse.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayReverse.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\StructureType; @@ -62,17 +66,24 @@ public function returns(): Type return $array; } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->array))->asArray($row, $context); + $arrays = (new Parameter($this->array))->asArrays($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($arrays as $i => $array) { + if ($array === null) { + throw new InvalidArgumentException('ArrayReverse function requires non-null array'); + } - if ($array === null) { - throw new InvalidArgumentException('ArrayReverse function requires non-null array'); + $results[] = array_reverse($array, $this->preserveKeys); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return array_reverse($array, $this->preserveKeys); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArraySort.php b/src/core/etl/src/Flow/ETL/Function/ArraySort.php index 36daec8b2c..342bb4ca6c 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArraySort.php +++ b/src/core/etl/src/Flow/ETL/Function/ArraySort.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; use Flow\ETL\Function\ArraySort\Sort; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\StructureType; @@ -84,22 +88,34 @@ public function returns(): Type return $array; } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->ref))->asArray($row, $context); - $flags = (new Parameter($this->flags))->asInt($row, $context); - $recursive = (new Parameter($this->recursive))->asBoolean($row, $context) ?? false; + $arrays = (new Parameter($this->ref))->asArrays($rows, $context); + $flagsList = (new Parameter($this->flags))->asInts($rows, $context); + $recursives = (new Parameter($this->recursive))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($array === null) { - throw new InvalidArgumentException('ArraySort function requires non-null array'); - } + try { + foreach ($arrays as $i => $array) { + $flags = $flagsList[$i]; + $recursive = $recursives[$i]; - $this->recursiveSort($array, $this->sortFunction->value, $flags, $recursive); + $recursive ??= false; - return $array; + if ($array === null) { + throw new InvalidArgumentException('ArraySort function requires non-null array'); + } + + $this->recursiveSort($array, $this->sortFunction->value, $flags, $recursive); + + $results[] = $array; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } + + return (new ResultColumn())->of($this, $results); } /** diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayUnpack.php b/src/core/etl/src/Flow/ETL/Function/ArrayUnpack.php index 240d958210..0484074977 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayUnpack.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayUnpack.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Function\ScalarFunction\UnpackResults; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Types\Type; @@ -45,16 +49,20 @@ public function children(): array return [$this->array]; } - /** - * @return array - */ - public function eval(Row $row, FlowContext $context): array + public function eval(Rows $rows, FlowContext $context): Column { - return ( - (new Parameter($this->array))->asArray($row, $context) ?? throw new InvalidArgumentException( - 'array_unpack() requires a non-null array', - ) - ); + $results = []; + $i = 0; + + try { + foreach ((new Parameter($this->array))->asArrays($rows, $context) as $i => $array) { + $results[] = $array ?? throw new InvalidArgumentException('array_unpack() requires a non-null array'); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } + + return (new ResultColumn())->of($this, $results); } /** diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayValues.php b/src/core/etl/src/Flow/ETL/Function/ArrayValues.php index aff2c6a507..cee1daea1b 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayValues.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayValues.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; use Flow\Types\Type\Logical\MapType; @@ -67,17 +71,24 @@ public function returns(): Type }; } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $array = (new Parameter($this->array))->asArray($row, $context); + $arrays = (new Parameter($this->array))->asArrays($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($arrays as $i => $array) { + if (!is_array($array)) { + throw new InvalidArgumentException('ArrayValues function requires non-null array'); + } - if (!is_array($array)) { - throw new InvalidArgumentException('ArrayValues function requires non-null array'); + $results[] = array_values($array); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return array_values($array); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Ascii.php b/src/core/etl/src/Flow/ETL/Function/Ascii.php index 1b0abaf2ff..74ce671670 100644 --- a/src/core/etl/src/Flow/ETL/Function/Ascii.php +++ b/src/core/etl/src/Flow/ETL/Function/Ascii.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('Ascii function requires non-null value'); + try { + foreach ($strings as $i => $string) { + if ($string === null) { + throw new InvalidArgumentException('Ascii function requires non-null value'); + } + + $results[] = u($string)->ascii()->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return u($string)->ascii()->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Average.php b/src/core/etl/src/Flow/ETL/Function/Average.php index c4ccc35118..585e45529e 100644 --- a/src/core/etl/src/Flow/ETL/Function/Average.php +++ b/src/core/etl/src/Flow/ETL/Function/Average.php @@ -6,10 +6,12 @@ use Flow\Calculator\Calculator; use Flow\Calculator\Rounding; +use Flow\Calculator\RunningSum; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\ETL\Window; use Flow\ETL\Window\Accumulator\AverageAccumulator; use Flow\ETL\Window\FrameAccumulator; @@ -19,26 +21,26 @@ use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_optional; use function is_numeric; +use function sprintf; final class Average implements AggregatingFunction, FrameAccumulating, WindowFunction { use ResolvesFromChildren; - private int $count; + private int $count = 0; private readonly string $outputName; - private float $sum; + private ?RunningSum $runningSum = null; public function __construct( private readonly Reference $ref, private readonly int $scale = 2, private readonly Rounding $rounding = Rounding::HALF_UP, + private readonly bool $exact = false, private readonly ?Window $window = null, ) { $this->outputName = $ref->hasAlias() ? $ref->name() : $ref->to() . '_avg'; - $this->count = 0; - $this->sum = 0; } /** @@ -55,36 +57,54 @@ public function children(): array public function withChildren(array $children): static { /** @var list $children */ - return new self($children[0], $this->scale, $this->rounding, $this->window); + return new self($children[0], $this->scale, $this->rounding, $this->exact, $this->window); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref)) { + if ($rows->schema()->findDefinition($this->ref->base()) === null) { return; } - /** @var mixed $value */ - $value = $row->get($this->ref); + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->take($indices)->values() as $value) { + if (is_numeric($value)) { + $this->runningSum ??= new RunningSum($context->calculator()); + // @mago-ignore analysis:possibly-invalid-argument + $this->runningSum->add($value, $this->exact); + $this->count++; + } + } + } + + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); + } - if (is_numeric($value)) { - // @mago-ignore analysis:possibly-invalid-argument - $this->sum = $context->calculator()->add($this->sum, $value); - $this->count++; + if ($other->runningSum === null) { + return; } + + $this->runningSum ??= new RunningSum($context->calculator()); + $this->runningSum->merge($other->runningSum, $this->exact); + $this->count += $other->count; } public function accumulator(FlowContext $context): FrameAccumulator { - return new AverageAccumulator($this->ref, $this->scale, $this->rounding, $context); + return new AverageAccumulator($this->ref, $this->scale, $this->rounding, $this->exact, $context); } public function apply(WindowContext $window): mixed { $accumulator = $this->accumulator($window->flowContext()); - foreach ($window->frame() as $frameRow) { - $accumulator->accumulate($frameRow); + $frame = $window->frame(); + + for ($index = 0, $count = $frame->count(); $index < $count; $index++) { + $accumulator->accumulate($frame, $index); } return $accumulator->value(); @@ -92,7 +112,7 @@ public function apply(WindowContext $window): mixed public function over(Window $window): static { - return new self($this->ref, $this->scale, $this->rounding, $window); + return new self($this->ref, $this->scale, $this->rounding, $this->exact, $window); } public function outputName(): string @@ -118,11 +138,11 @@ public function returns(): Type public function value(): ?float { - if (0 === $this->count) { + if (0 === $this->count || $this->runningSum === null) { return null; } - return (new Calculator())->divide($this->sum, $this->count, $this->scale, $this->rounding); + return (new Calculator())->divide($this->runningSum->value(), $this->count, $this->scale, $this->rounding); } public function toString(): string diff --git a/src/core/etl/src/Flow/ETL/Function/Between.php b/src/core/etl/src/Flow/ETL/Function/Between.php index e390334434..d2c01dadc1 100644 --- a/src/core/etl/src/Flow/ETL/Function/Between.php +++ b/src/core/etl/src/Flow/ETL/Function/Between.php @@ -4,14 +4,21 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; use Flow\ETL\Function\Between\Boundary; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; +use function array_map; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; final class Between implements ScalarFunction @@ -66,18 +73,35 @@ public function returns(): Type ); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $boundary = (new Parameter($this->boundary))->asEnum($row, $context, Boundary::class); + $boundaries = (new Parameter($this->boundary))->asEnums($rows, $context, Boundary::class); + $columns = array_map( + static fn(ScalarFunction $function): Column => (new Parameter($function))->column($rows, $context), + [$this->value, $this->lowerBoundRef, $this->upperBoundRef], + ); + $comparable = new ComparableValues(); + $sameType = + type_bare($columns[0]->type())::class === type_bare($columns[1]->type())::class + && type_bare($columns[0]->type())::class === type_bare($columns[2]->type())::class; + [$values, $lowerBounds, $upperBounds] = array_map(static fn(Column $column): array => $sameType + ? $comparable->ordering($column) + : $column->values(), $columns); + $results = []; + $i = 0; + + try { + foreach ($boundaries as $i => $boundary) { + if (!$boundary instanceof Boundary) { + throw new InvalidArgumentException('Between function requires valid boundary'); + } - if (!$boundary instanceof Boundary) { - throw new InvalidArgumentException('Between function requires valid boundary'); + $results[] = $boundary->compare($values[$i], $lowerBounds[$i], $upperBounds[$i]); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $boundary->compare( - (new Parameter($this->value))->eval($row, $context), - (new Parameter($this->lowerBoundRef))->eval($row, $context), - (new Parameter($this->upperBoundRef))->eval($row, $context), - ); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/BinaryLength.php b/src/core/etl/src/Flow/ETL/Function/BinaryLength.php index c46e29f925..e63adf64fb 100644 --- a/src/core/etl/src/Flow/ETL/Function/BinaryLength.php +++ b/src/core/etl/src/Flow/ETL/Function/BinaryLength.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_integer(); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('BinaryLength function requires non-null value'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('BinaryLength function requires non-null value'); + } + + $results[] = b($value)->length(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return b($value)->length(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php b/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php index 3404632072..5dd7075ce4 100644 --- a/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php +++ b/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function array_combine; @@ -85,24 +89,39 @@ public function returns(): Type return type_optional($this->returnType); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $callable = (new Parameter($this->callable))->eval($row, $context); - - if (!is_callable($callable)) { - throw new InvalidArgumentException('CallUserFunc requires a valid callable'); + $callables = (new Parameter($this->callable))->values($rows, $context); + $arguments = array_map(static fn(ScalarFunction $parameter): array => (new Parameter($parameter))->values( + $rows, + $context, + ), $this->parameters); + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($callables as $i => $callable) { + if (!is_callable($callable)) { + throw new InvalidArgumentException('CallUserFunc requires a valid callable'); + } + + $parameters = []; + + foreach ($arguments as $key => $argument) { + $parameters[$key] = $argument[$i]; + } + + // The callable's output may not match the declared type - coerce it before trusting it. + // @mago-ignore analysis:mixed-assignment + $result = call_user_func($callable, ...$parameters); + + $results[] = $result === null ? null : $this->returnType->cast($result); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - $parameters = []; - - foreach ($this->parameters as $key => $parameter) { - $parameters[$key] = (new Parameter($parameter))->eval($row, $context); - } - - // The callable's output may not match the declared type - coerce it before trusting it. - // @mago-ignore analysis:mixed-assignment - $result = call_user_func($callable, ...$parameters); - - return $result === null ? null : $this->returnType->cast($result); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Capitalize.php b/src/core/etl/src/Flow/ETL/Function/Capitalize.php index b69ffa1864..8892f7fa09 100644 --- a/src/core/etl/src/Flow/ETL/Function/Capitalize.php +++ b/src/core/etl/src/Flow/ETL/Function/Capitalize.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -54,18 +58,31 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->eval($row, $context); + $strings = (new Parameter($this->string))->values($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('Capitalize function requires non-null value'); - } + try { + // @mago-ignore analysis:mixed-assignment + foreach ($strings as $i => $string) { + if ($string === null) { + throw new InvalidArgumentException('Capitalize function requires non-null value'); + } + + if (function_exists('mb_convert_case')) { + $results[] = mb_convert_case(is_scalar($string) ? (string) $string : '', MB_CASE_TITLE); + + continue; + } - if (function_exists('mb_convert_case')) { - return mb_convert_case(is_scalar($string) ? (string) $string : '', MB_CASE_TITLE); + $results[] = ucwords(is_scalar($string) ? (string) $string : ''); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return ucwords(is_scalar($string) ? (string) $string : ''); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Cast.php b/src/core/etl/src/Flow/ETL/Function/Cast.php index 7d629ac112..0bb7617f49 100644 --- a/src/core/etl/src/Flow/ETL/Function/Cast.php +++ b/src/core/etl/src/Flow/ETL/Function/Cast.php @@ -4,11 +4,15 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\UnsupportedUnionTypeException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Exception\CastingException; use Flow\Types\Exception\InvalidArgumentException as TypesInvalidArgumentException; use Flow\Types\Type; @@ -79,18 +83,28 @@ public function returns(): Type return $this->type; } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); - - if (null === $value && !type_is_nullable($this->type)) { - throw new InvalidArgumentException('Cast function requires non-null value'); - } + $results = []; + $i = 0; try { - return $this->type->cast($value); - } catch (CastingException $e) { - throw new InvalidArgumentException('Cast function failed: ' . $e->getMessage()); + // @mago-ignore analysis:mixed-assignment + foreach ((new Parameter($this->value))->values($rows, $context) as $i => $value) { + if (null === $value && !type_is_nullable($this->type)) { + throw new InvalidArgumentException('Cast function requires non-null value'); + } + + try { + $results[] = $this->type->cast($value); + } catch (CastingException $e) { + throw new InvalidArgumentException('Cast function failed: ' . $e->getMessage(), 0, $e); + } + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Chunk.php b/src/core/etl/src/Flow/ETL/Function/Chunk.php index 610ab231f5..07b2055312 100644 --- a/src/core/etl/src/Flow/ETL/Function/Chunk.php +++ b/src/core/etl/src/Flow/ETL/Function/Chunk.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Symfony\Component\String\AbstractString; @@ -53,27 +57,36 @@ public function returns(): Type return type_list(type_string()); } - /** - * @return array - */ - public function eval(Row $row, FlowContext $context): array + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $size = (new Parameter($this->size))->asInt($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $sizes = (new Parameter($this->size))->asInts($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('Chunk function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $size = $sizes[$i]; - if ($size === null || $size <= 0) { - throw new InvalidArgumentException('Chunk function requires non-null, positive size'); - } + if ($value === null) { + throw new InvalidArgumentException('Chunk function requires non-null value'); + } - $chunks = s($value)->chunk($size); + if ($size === null || $size <= 0) { + throw new InvalidArgumentException('Chunk function requires non-null, positive size'); + } + + $chunks = s($value)->chunk($size); + + $results[] = array_map( + static fn(AbstractString $chunk): string => $chunk->toString(), + iterator_to_array($chunks, false), + ); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } - return array_map( - static fn(AbstractString $chunk): string => $chunk->toString(), - iterator_to_array($chunks, false), - ); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Coalesce.php b/src/core/etl/src/Flow/ETL/Function/Coalesce.php index b1841fa2c1..598ae8576f 100644 --- a/src/core/etl/src/Flow/ETL/Function/Coalesce.php +++ b/src/core/etl/src/Flow/ETL/Function/Coalesce.php @@ -4,8 +4,11 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Function\Evaluation\Selection; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Unifier\NullabilityRule; @@ -13,6 +16,7 @@ use function array_map; use function array_values; +use function range; final class Coalesce implements ScalarFunction { @@ -61,16 +65,39 @@ public function returns(): Type ); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { + $pending = $rows->isEmpty() ? [] : range(0, $rows->count() - 1); + $values = []; + foreach ($this->values as $value) { - $result = (new Parameter($value))->eval($row, $context); + if ($pending === []) { + break; + } + + $column = (new Selection($pending))->evaluate($value, $rows, $context); + $stillNull = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $k => $result) { + if ($result === null) { + $stillNull[] = $pending[$k]; + + continue; + } - if ($result !== null) { - return $result; + $values[$pending[$k]] = $result; } + + $pending = $stillNull; + } + + $results = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $results[] = $values[$i] ?? null; } - return null; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/CodePointLength.php b/src/core/etl/src/Flow/ETL/Function/CodePointLength.php index f697a4add5..63ff7fea5f 100644 --- a/src/core/etl/src/Flow/ETL/Function/CodePointLength.php +++ b/src/core/etl/src/Flow/ETL/Function/CodePointLength.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_integer(); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('CodePointLength function requires non-null value'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('CodePointLength function requires non-null value'); + } + + $results[] = s($value)->toCodePointString()->length(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->toCodePointString()->length(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/CollapseWhitespace.php b/src/core/etl/src/Flow/ETL/Function/CollapseWhitespace.php index 02e8053d3b..c9a28a04ed 100644 --- a/src/core/etl/src/Flow/ETL/Function/CollapseWhitespace.php +++ b/src/core/etl/src/Flow/ETL/Function/CollapseWhitespace.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('CollapseWhitespace function requires non-null value'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('CollapseWhitespace function requires non-null value'); + } + + $results[] = s($value)->collapseWhitespace()->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->collapseWhitespace()->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Collect.php b/src/core/etl/src/Flow/ETL/Function/Collect.php index c06c2f4a13..80b4b37625 100644 --- a/src/core/etl/src/Flow/ETL/Function/Collect.php +++ b/src/core/etl/src/Flow/ETL/Function/Collect.php @@ -4,14 +4,15 @@ namespace Flow\ETL\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Type; -use function current; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_optional; +use function sprintf; final class Collect implements AggregatingFunction { @@ -48,18 +49,25 @@ public function withChildren(array $children): static return new self($children[0]); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref)) { + if ($rows->schema()->findDefinition($this->ref->base()) === null) { return; } - /** @var array $values */ - $values = []; + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->take($indices)->values() as $value) { + $this->collection[] = $value; + } + } - $values[$this->ref->name()] = $row->get($this->ref); + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); + } - $this->collection[] = current($values); + $this->collection = [...$this->collection, ...$other->collection]; } public function outputName(): string diff --git a/src/core/etl/src/Flow/ETL/Function/CollectUnique.php b/src/core/etl/src/Flow/ETL/Function/CollectUnique.php index e7354dd0b8..02577165a8 100644 --- a/src/core/etl/src/Flow/ETL/Function/CollectUnique.php +++ b/src/core/etl/src/Flow/ETL/Function/CollectUnique.php @@ -4,15 +4,16 @@ namespace Flow\ETL\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Type; -use function current; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_optional; use function in_array; +use function sprintf; final class CollectUnique implements AggregatingFunction { @@ -49,22 +50,31 @@ public function withChildren(array $children): static return new self($children[0]); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref)) { + if ($rows->schema()->findDefinition($this->ref->base()) === null) { return; } - /** @var array $values */ - $values = []; - - $values[$this->ref->name()] = $row->get($this->ref); + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->take($indices)->values() as $value) { + if (!in_array($value, $this->collection, true)) { + $this->collection[] = $value; + } + } + } - /** @var mixed $value */ - $value = current($values); + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); + } - if (!in_array($value, $this->collection, true)) { - $this->collection[] = $value; + // @mago-ignore analysis:mixed-assignment + foreach ($other->collection as $value) { + if (!in_array($value, $this->collection, true)) { + $this->collection[] = $value; + } } } diff --git a/src/core/etl/src/Flow/ETL/Function/Combine.php b/src/core/etl/src/Flow/ETL/Function/Combine.php index d4a7c3e54b..9cc5ebfe4f 100644 --- a/src/core/etl/src/Flow/ETL/Function/Combine.php +++ b/src/core/etl/src/Flow/ETL/Function/Combine.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; @@ -72,37 +76,48 @@ public function returns(): Type return type_map($keys->element(), $values->element()); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - $keys = (new Parameter($this->keys))->asArray($row, $context); - $values = (new Parameter($this->values))->asArray($row, $context); - - if (null === $keys || null === $values) { - throw new InvalidArgumentException('Combine function requires non-null arrays'); - } - - if ([] === $keys) { - return []; - } - - if (!array_is_list($keys)) { - throw new InvalidArgumentException('Combine function requires keys to be a list'); - } - - if (count($keys) !== count($values)) { - throw new InvalidArgumentException( - 'Combine function requires keys and values arrays to have the same length', - ); - } - - if (!is_string($keys[0] ?? null) && !is_int($keys[0] ?? null)) { - throw new InvalidArgumentException('Combine function requires keys to be strings or integers'); + $keysList = (new Parameter($this->keys))->asArrays($rows, $context); + $valuesList = (new Parameter($this->values))->asArrays($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($keysList as $i => $keys) { + $values = $valuesList[$i]; + + if (null === $keys || null === $values) { + throw new InvalidArgumentException('Combine function requires non-null arrays'); + } + + if ([] === $keys) { + $results[] = []; + + continue; + } + + if (!array_is_list($keys)) { + throw new InvalidArgumentException('Combine function requires keys to be a list'); + } + + if (count($keys) !== count($values)) { + throw new InvalidArgumentException( + 'Combine function requires keys and values arrays to have the same length', + ); + } + + if (!is_string($keys[0] ?? null) && !is_int($keys[0] ?? null)) { + throw new InvalidArgumentException('Combine function requires keys to be strings or integers'); + } + + /** @var array $keys */ + $results[] = array_combine($keys, $values); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - /** @var array $keys */ - return array_combine($keys, $values); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Concat.php b/src/core/etl/src/Flow/ETL/Function/Concat.php index 84319f0885..05f2c3447c 100644 --- a/src/core/etl/src/Flow/ETL/Function/Concat.php +++ b/src/core/etl/src/Flow/ETL/Function/Concat.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function array_map; @@ -56,21 +60,34 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): string + public function eval(Rows $rows, FlowContext $context): Column { - /** @var array $concatValues */ - $concatValues = []; + $arguments = array_map(static fn(ScalarFunction $ref): array => (new Parameter($ref))->values( + $rows, + $context, + ), $this->refs); + $results = []; + $i = 0; - foreach ($this->refs as $ref) { - $value = (new Parameter($ref))->eval($row, $context); + try { + for ($count = $rows->count(); $i < $count; $i++) { + /** @var array $concatValues */ + $concatValues = []; - if ($value === null) { - continue; - } + foreach ($arguments as $argument) { + if ($argument[$i] === null) { + continue; + } + + $concatValues[] = type_string()->cast($argument[$i]); + } - $concatValues[] = type_string()->cast($value); + $results[] = implode('', $concatValues); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return implode('', $concatValues); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ConcatWithSeparator.php b/src/core/etl/src/Flow/ETL/Function/ConcatWithSeparator.php index ab2a99a8f0..7ce0740596 100644 --- a/src/core/etl/src/Flow/ETL/Function/ConcatWithSeparator.php +++ b/src/core/etl/src/Flow/ETL/Function/ConcatWithSeparator.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function array_map; @@ -65,28 +69,43 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): string + public function eval(Rows $rows, FlowContext $context): Column { - $separator = (new Parameter($this->separator))->asString($row, $context); - - if (!is_string($separator)) { - throw new InvalidArgumentException('ConcatWithSeparator function requires non-null separator'); - } - - /** @var array $concatValues */ - $concatValues = []; - - foreach ($this->refs as $value) { - $value = (new Parameter($value))->eval($row, $context); - - if (is_type(type_list(type_string()), $value)) { - /** @var list $value */ - $concatValues = array_merge($concatValues, $value); - } elseif ($value !== null) { - $concatValues[] = type_string()->cast($value); + $separators = (new Parameter($this->separator))->asStrings($rows, $context); + $arguments = array_map(static fn(ScalarFunction $ref): array => (new Parameter($ref))->values( + $rows, + $context, + ), $this->refs); + $results = []; + $i = 0; + + try { + foreach ($separators as $i => $separator) { + if (!is_string($separator)) { + throw new InvalidArgumentException('ConcatWithSeparator function requires non-null separator'); + } + + /** @var array $concatValues */ + $concatValues = []; + + foreach ($arguments as $argument) { + // @mago-ignore analysis:mixed-assignment + $value = $argument[$i]; + + if (is_type(type_list(type_string()), $value)) { + /** @var list $value */ + $concatValues = array_merge($concatValues, $value); + } elseif ($value !== null) { + $concatValues[] = type_string()->cast($value); + } + } + + $results[] = implode($separator, $concatValues); } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return implode($separator, $concatValues); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Contains.php b/src/core/etl/src/Flow/ETL/Function/Contains.php index 27818935c5..c7bc47b20b 100644 --- a/src/core/etl/src/Flow/ETL/Function/Contains.php +++ b/src/core/etl/src/Flow/ETL/Function/Contains.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -55,19 +59,35 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->haystack->returns(), $this->needle->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $haystack = (new Parameter($this->haystack))->as($row, $context, type_string(), type_array()); - $needle = (new Parameter($this->needle))->asString($row, $context); + $haystacks = (new Parameter($this->haystack))->asTypes($rows, $context, type_string(), type_array()); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($haystack === null || $needle === null) { - return null; - } + try { + foreach ($haystacks as $i => $haystack) { + $needle = $needles[$i]; + + if ($haystack === null || $needle === null) { + $results[] = null; + + continue; + } + + if (is_string($haystack)) { + $results[] = str_contains($haystack, $needle); + + continue; + } - if (is_string($haystack)) { - return str_contains($haystack, $needle); + $results[] = in_array($needle, $haystack, true); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return in_array($needle, $haystack, true); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Count.php b/src/core/etl/src/Flow/ETL/Function/Count.php index e3cf739df2..754c6fad84 100644 --- a/src/core/etl/src/Flow/ETL/Function/Count.php +++ b/src/core/etl/src/Flow/ETL/Function/Count.php @@ -4,18 +4,21 @@ namespace Flow\ETL\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\ETL\Window; use Flow\ETL\Window\Accumulator\CountAccumulator; use Flow\ETL\Window\FrameAccumulator; use Flow\ETL\Window\WindowContext; use Flow\Types\Type; +use function count; use function Flow\Types\DSL\type_integer; +use function sprintf; final class Count implements AggregatingFunction, FrameAccumulating, WindowFunction { @@ -70,16 +73,22 @@ public function withChildren(array $children): static return new self($children[0], $this->window); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if ($this->ref !== null && !$row->has($this->ref)) { + if ($this->ref !== null && $rows->schema()->findDefinition($this->ref->base()) === null) { return; } - if ($this->ref) { - $row->get($this->ref); + $this->count += count($indices); + } + + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); } - $this->count++; + + $this->count += $other->count; } public function accumulator(FlowContext $context): FrameAccumulator @@ -95,8 +104,10 @@ public function apply(WindowContext $window): mixed $accumulator = $this->accumulator($window->flowContext()); - foreach ($window->frame() as $frameRow) { - $accumulator->accumulate($frameRow); + $frame = $window->frame(); + + for ($index = 0, $count = $frame->count(); $index < $count; $index++) { + $accumulator->accumulate($frame, $index); } return $accumulator->value(); diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementAttributeValue.php b/src/core/etl/src/Flow/ETL/Function/DOMElementAttributeValue.php index 1514416abe..8a54a74512 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementAttributeValue.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementAttributeValue.php @@ -7,9 +7,13 @@ use Dom\HTMLElement; use DOMDocument; use DOMNode; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -60,7 +64,7 @@ public function returns(): Type return type_optional(type_string()); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { $types = [ type_instance_of(DOMNode::class), @@ -72,42 +76,59 @@ public function eval(Row $row, FlowContext $context): ?string $types[] = type_list(type_instance_of(HTMLElement::class)); } - $node = (new Parameter($this->domElement))->as($row, $context, ...$types); + $nodes = (new Parameter($this->domElement))->asTypes($rows, $context, ...$types); + $attributeNames = (new Parameter($this->attribute))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($node instanceof DOMDocument) { - $node = $node->documentElement; - } + try { + foreach ($nodes as $i => $node) { + $attributeName = $attributeNames[$i]; - if (is_array($node) && count($node)) { - $node = reset($node); - } + if ($node instanceof DOMDocument) { + $node = $node->documentElement; + } - $attributeName = (new Parameter($this->attribute))->asString($row, $context); + if (is_array($node) && count($node)) { + $node = reset($node); + } - if ($node === null) { - throw new InvalidArgumentException('DOMElementAttributeValue requires non-null DOMNode'); - } + if ($node === null) { + throw new InvalidArgumentException('DOMElementAttributeValue requires non-null DOMNode'); + } - if ($attributeName === null) { - throw new InvalidArgumentException('DOMElementAttributeValue requires non-null attribute name'); - } + if ($attributeName === null) { + throw new InvalidArgumentException('DOMElementAttributeValue requires non-null attribute name'); + } - if (!$node instanceof DOMNode && !$node instanceof HTMLElement) { - return null; - } + if (!$node instanceof DOMNode && !$node instanceof HTMLElement) { + $results[] = null; - $attributes = $node->attributes; + continue; + } - if ($attributes === null) { - return null; - } + $attributes = $node->attributes; + + if ($attributes === null) { + $results[] = null; + + continue; + } + + $namedItem = $attributes->getNamedItem($attributeName); + + if ($namedItem === null) { + $results[] = null; - $namedItem = $attributes->getNamedItem($attributeName); + continue; + } - if ($namedItem === null) { - return null; + $results[] = $namedItem->nodeValue; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $namedItem->nodeValue; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementAttributesCount.php b/src/core/etl/src/Flow/ETL/Function/DOMElementAttributesCount.php index 81a5040a24..0201f41256 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementAttributesCount.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementAttributesCount.php @@ -7,9 +7,13 @@ use Dom\HTMlElement; use DOMElement; use DOMNode; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -53,7 +57,7 @@ public function returns(): Type return type_integer(); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { $types = [ type_instance_of(DOMElement::class), @@ -63,12 +67,22 @@ public function eval(Row $row, FlowContext $context): ?int $types[] = type_instance_of(HTMLElement::class); } - $domElement = (new Parameter($this->domElement))->as($row, $context, ...$types); + $domElements = (new Parameter($this->domElement))->asTypes($rows, $context, ...$types); + $results = []; + $i = 0; - if ($domElement === null) { - throw new InvalidArgumentException('DOMElementAttributesCount requires non-null DOMElement'); + try { + foreach ($domElements as $i => $domElement) { + if ($domElement === null) { + throw new InvalidArgumentException('DOMElementAttributesCount requires non-null DOMElement'); + } + + $results[] = $domElement->attributes->length ?? 0; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $domElement->attributes->length ?? 0; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementNamespaceValue.php b/src/core/etl/src/Flow/ETL/Function/DOMElementNamespaceValue.php index 7477752e06..188031376a 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementNamespaceValue.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementNamespaceValue.php @@ -11,9 +11,13 @@ use DOMDocument; use DOMNode; use DOMXPath; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -64,7 +68,7 @@ public function returns(): Type return type_optional(type_string()); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { $types = [ type_instance_of(DOMNode::class), @@ -76,8 +80,28 @@ public function eval(Row $row, FlowContext $context): ?string $types[] = type_list(type_instance_of(Element::class)); } - $node = (new Parameter($this->domElement))->as($row, $context, ...$types); + $nodes = (new Parameter($this->domElement))->asTypes($rows, $context, ...$types); + $attributeNames = (new Parameter($this->attribute))->asStrings($rows, $context); + $results = []; + $i = 0; + try { + // @mago-ignore analysis:mixed-assignment + foreach ($nodes as $i => $node) { + $results[] = $this->namespaceValue($node, $attributeNames[$i]); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } + + return (new ResultColumn())->of($this, $results); + } + + /** + * @param mixed $node the evaluated DOM operand of one row + */ + public function namespaceValue(mixed $node, ?string $attributeName): ?string + { if ($node instanceof DOMDocument) { $node = $node->documentElement; } @@ -94,8 +118,6 @@ public function eval(Row $row, FlowContext $context): ?string return null; } - $attributeName = (new Parameter($this->attribute))->asString($row, $context); - if ($attributeName === null) { return $node->namespaceURI; } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementNextSibling.php b/src/core/etl/src/Flow/ETL/Function/DOMElementNextSibling.php index 86f3d1faae..6df9b508f7 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementNextSibling.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementNextSibling.php @@ -9,9 +9,13 @@ use DOMDocument; use DOMElement; use DOMNode; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -56,7 +60,7 @@ public function returns(): Type return type_optional(type_xml_element()); } - public function eval(Row $row, FlowContext $context): ?DOMElement + public function eval(Rows $rows, FlowContext $context): Column { $types = [ type_instance_of(DOMNode::class), @@ -67,21 +71,31 @@ public function eval(Row $row, FlowContext $context): ?DOMElement $types[] = type_instance_of(HTMLElement::class); } - $node = (new Parameter($this->element))->as($row, $context, ...$types); - - if ($node instanceof DOMDocument) { - $node = $node->documentElement; - } - - if (!$node instanceof DOMElement) { - throw new InvalidArgumentException('DOMElementNextSibling requires DOMElement.'); - } - - // @mago-ignore analysis:impossible-condition - if ($node instanceof CharacterData) { - throw new InvalidArgumentException('DOMElementNextSibling requires HTMLElement.'); + $nodes = (new Parameter($this->element))->asTypes($rows, $context, ...$types); + $results = []; + $i = 0; + + try { + foreach ($nodes as $i => $node) { + if ($node instanceof DOMDocument) { + $node = $node->documentElement; + } + + if (!$node instanceof DOMElement) { + throw new InvalidArgumentException('DOMElementNextSibling requires DOMElement.'); + } + + // @mago-ignore analysis:impossible-condition + if ($node instanceof CharacterData) { + throw new InvalidArgumentException('DOMElementNextSibling requires HTMLElement.'); + } + + $results[] = $node->nextElementSibling; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $node->nextElementSibling; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementParent.php b/src/core/etl/src/Flow/ETL/Function/DOMElementParent.php index d703f9d709..2f0b4c238b 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementParent.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementParent.php @@ -8,9 +8,13 @@ use DOMDocument; use DOMElement; use DOMNode; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -55,7 +59,7 @@ public function returns(): Type return type_optional(type_xml_element()); } - public function eval(Row $row, FlowContext $context): DOMNode|HTMLElement|null + public function eval(Rows $rows, FlowContext $context): Column { $types = [ type_instance_of(DOMNode::class), @@ -65,22 +69,33 @@ public function eval(Row $row, FlowContext $context): DOMNode|HTMLElement|null $types[] = type_instance_of(HTMLElement::class); } - $node = (new Parameter($this->element))->as($row, $context, ...$types); + $nodes = (new Parameter($this->element))->asTypes($rows, $context, ...$types); + $results = []; + $i = 0; - if ($node instanceof DOMDocument) { - $node = $node->documentElement; - } + try { + foreach ($nodes as $i => $node) { + if ($node instanceof DOMDocument) { + $node = $node->documentElement; + } - if ($node === null) { - throw new InvalidArgumentException('DOMElementParent requires non-null DOMNode or HTMLElement.'); - } + if ($node === null) { + throw new InvalidArgumentException('DOMElementParent requires non-null DOMNode or HTMLElement.'); + } + + if ($node instanceof HTMLElement) { + $results[] = $node->parentElement; + + continue; + } - if ($node instanceof HTMLElement) { - // @mago-ignore analysis:less-specific-return-statement - return $node->parentElement; + // parentNode of a root element is the DOMDocument, which is not an xml_element. + $results[] = $node->parentNode instanceof DOMElement ? $node->parentNode : null; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - // parentNode of a root element is the DOMDocument, which is not an xml_element. - return $node->parentNode instanceof DOMElement ? $node->parentNode : null; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementPreviousSibling.php b/src/core/etl/src/Flow/ETL/Function/DOMElementPreviousSibling.php index 5047db8ea3..64a0b0ae33 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementPreviousSibling.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementPreviousSibling.php @@ -9,9 +9,13 @@ use DOMDocument; use DOMElement; use DOMNode; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -56,7 +60,7 @@ public function returns(): Type return type_optional(type_xml_element()); } - public function eval(Row $row, FlowContext $context): ?DOMElement + public function eval(Rows $rows, FlowContext $context): Column { $types = [ type_instance_of(DOMNode::class), @@ -67,21 +71,31 @@ public function eval(Row $row, FlowContext $context): ?DOMElement $types[] = type_instance_of(HTMLElement::class); } - $node = (new Parameter($this->element))->as($row, $context, ...$types); - - if ($node instanceof DOMDocument) { - $node = $node->documentElement; - } - - if (!$node instanceof DOMElement) { - throw new InvalidArgumentException('DOMElementPreviousSibling requires DOMElement.'); - } - - // @mago-ignore analysis:impossible-condition - if ($node instanceof CharacterData) { - throw new InvalidArgumentException('DOMElementPreviousSibling requires HTMLElement.'); + $nodes = (new Parameter($this->element))->asTypes($rows, $context, ...$types); + $results = []; + $i = 0; + + try { + foreach ($nodes as $i => $node) { + if ($node instanceof DOMDocument) { + $node = $node->documentElement; + } + + if (!$node instanceof DOMElement) { + throw new InvalidArgumentException('DOMElementPreviousSibling requires DOMElement.'); + } + + // @mago-ignore analysis:impossible-condition + if ($node instanceof CharacterData) { + throw new InvalidArgumentException('DOMElementPreviousSibling requires HTMLElement.'); + } + + $results[] = $node->previousElementSibling; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $node->previousElementSibling; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementValue.php b/src/core/etl/src/Flow/ETL/Function/DOMElementValue.php index 3f5a45472c..f1b34f3bf4 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementValue.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementValue.php @@ -9,8 +9,12 @@ use DOMDocument; use DOMElement; use DOMNode; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -59,7 +63,7 @@ public function returns(): Type return type_optional(type_string()); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { $types = [ type_instance_of(DOMNode::class), @@ -72,24 +76,38 @@ public function eval(Row $row, FlowContext $context): mixed $types[] = type_list(type_instance_of(HTMLElement::class)); } - $node = (new Parameter($this->node))->as($row, $context, ...$types); + $nodes = (new Parameter($this->node))->asTypes($rows, $context, ...$types); + $results = []; + $i = 0; - if (is_array($node) && count($node)) { - $node = reset($node); - } + try { + foreach ($nodes as $i => $node) { + if (is_array($node) && count($node)) { + $node = reset($node); + } - if ($node instanceof DOMDocument) { - $node = $node->documentElement; - } + if ($node instanceof DOMDocument) { + $node = $node->documentElement; + } - if ($node instanceof DOMElement) { - return $node->nodeValue; - } + if ($node instanceof DOMElement) { + $results[] = $node->nodeValue; + + continue; + } + + if ($node instanceof CharacterData || $node instanceof HTMLElement) { + $results[] = $node->textContent; + + continue; + } - if ($node instanceof CharacterData || $node instanceof HTMLElement) { - return $node->textContent; + $results[] = null; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return null; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DateTimeFormat.php b/src/core/etl/src/Flow/ETL/Function/DateTimeFormat.php index 95d580be2d..e10cf3d127 100644 --- a/src/core/etl/src/Flow/ETL/Function/DateTimeFormat.php +++ b/src/core/etl/src/Flow/ETL/Function/DateTimeFormat.php @@ -5,9 +5,13 @@ namespace Flow\ETL\Function; use DateTimeInterface; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -51,15 +55,27 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->dateTime))->asInstanceOf($row, $context, DateTimeInterface::class); - $format = (new Parameter($this->format))->asString($row, $context); + $values = (new Parameter($this->dateTime))->asInstancesOf($rows, $context, DateTimeInterface::class); + $formats = (new Parameter($this->format))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null || $format === null) { - throw new InvalidArgumentException('DateTimeFormat function requires non-null values'); + try { + foreach ($values as $i => $value) { + $format = $formats[$i]; + + if ($value === null || $format === null) { + throw new InvalidArgumentException('DateTimeFormat function requires non-null values'); + } + + $results[] = $value->format($format); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $value->format($format); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DenseRank.php b/src/core/etl/src/Flow/ETL/Function/DenseRank.php index d0ecd17f16..6f192d9423 100644 --- a/src/core/etl/src/Flow/ETL/Function/DenseRank.php +++ b/src/core/etl/src/Flow/ETL/Function/DenseRank.php @@ -55,18 +55,15 @@ public function rankPartition(Rows $partition): array throw new BaseRuntimeException('Dens Rank window function requires to be ordered by one column'); } - $comparator = new PeerComparator($orderBy); $ranks = []; $rank = 1; - $previous = null; - foreach ($partition as $row) { - if ($previous !== null && !$comparator->arePeers($previous, $row, $partition->schema())) { + foreach ((new PeerComparator($orderBy))->peersOfPrevious($partition) as $index => $peer) { + if ($index > 0 && !$peer) { $rank++; } $ranks[] = $rank; - $previous = $row; } return $ranks; diff --git a/src/core/etl/src/Flow/ETL/Function/Divide.php b/src/core/etl/src/Flow/ETL/Function/Divide.php index 544fd71f09..79739e1a7b 100644 --- a/src/core/etl/src/Flow/ETL/Function/Divide.php +++ b/src/core/etl/src/Flow/ETL/Function/Divide.php @@ -4,11 +4,14 @@ namespace Flow\ETL\Function; -use Flow\Calculator\Calculator; +use Exception; use Flow\Calculator\Rounding; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -60,21 +63,34 @@ public function returns(): Type return type_float(); } - public function eval(Row $row, FlowContext $context): int|float|null + public function eval(Rows $rows, FlowContext $context): Column { - $leftValue = (new Parameter($this->left))->asNumber($row, $context); - $rightValue = (new Parameter($this->right))->asNumber($row, $context); - $scale = (new Parameter($this->scale))->asInt($row, $context); - $rounding = (new Parameter($this->rounding))->asEnum($row, $context, Rounding::class); + $lefts = (new Parameter($this->left))->asNumbers($rows, $context); + $rights = (new Parameter($this->right))->asNumbers($rows, $context); + $scales = (new Parameter($this->scale))->asInts($rows, $context); + $roundings = (new Parameter($this->rounding))->asEnums($rows, $context, Rounding::class); + $calculator = $context->calculator(); + $results = []; + $i = 0; - if ($leftValue === null || $rightValue === null) { - throw new InvalidArgumentException('Divide function requires non-null values'); - } + try { + foreach ($lefts as $i => $leftValue) { + $rightValue = $rights[$i]; + + if ($leftValue === null || $rightValue === null) { + throw new InvalidArgumentException('Divide function requires non-null values'); + } + + if ($rightValue === 0) { + throw new InvalidArgumentException('Divide function cannot divide by zero'); + } - if ($rightValue === 0) { - throw new InvalidArgumentException('Divide function cannot divide by zero'); + $results[] = $calculator->divide($leftValue, $rightValue, $scales[$i], $roundings[$i]); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return (new Calculator())->divide($leftValue, $rightValue, $scale, $rounding); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EndsWith.php b/src/core/etl/src/Flow/ETL/Function/EndsWith.php index 220956a0c4..f99110cb78 100644 --- a/src/core/etl/src/Flow/ETL/Function/EndsWith.php +++ b/src/core/etl/src/Flow/ETL/Function/EndsWith.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -51,15 +55,29 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->haystack->returns(), $this->needle->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $haystack = (new Parameter($this->haystack))->asString($row, $context); - $needle = (new Parameter($this->needle))->asString($row, $context); + $haystacks = (new Parameter($this->haystack))->asStrings($rows, $context); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($haystack === null || $needle === null) { - return null; + try { + foreach ($haystacks as $i => $haystack) { + $needle = $needles[$i]; + + if ($haystack === null || $needle === null) { + $results[] = null; + + continue; + } + + $results[] = str_ends_with($haystack, $needle); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return str_ends_with($haystack, $needle); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EnsureEnd.php b/src/core/etl/src/Flow/ETL/Function/EnsureEnd.php index e622b1b0b8..66e0689792 100644 --- a/src/core/etl/src/Flow/ETL/Function/EnsureEnd.php +++ b/src/core/etl/src/Flow/ETL/Function/EnsureEnd.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -51,19 +55,33 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $suffix = (new Parameter($this->suffix))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $suffixes = (new Parameter($this->suffix))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('EnsureEnd function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $suffix = $suffixes[$i]; + + if ($value === null) { + throw new InvalidArgumentException('EnsureEnd function requires non-null value'); + } + + if ($suffix === null || $suffix === '') { + $results[] = $value; + + continue; + } - if ($suffix === null || $suffix === '') { - return $value; + $results[] = s($value)->ensureEnd($suffix)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->ensureEnd($suffix)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EnsureStart.php b/src/core/etl/src/Flow/ETL/Function/EnsureStart.php index 785928e340..4e09853e59 100644 --- a/src/core/etl/src/Flow/ETL/Function/EnsureStart.php +++ b/src/core/etl/src/Flow/ETL/Function/EnsureStart.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -51,19 +55,33 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $prefix = (new Parameter($this->prefix))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $prefixes = (new Parameter($this->prefix))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('EnsureStart function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $prefix = $prefixes[$i]; + + if ($value === null) { + throw new InvalidArgumentException('EnsureStart function requires non-null value'); + } + + if ($prefix === null || $prefix === '') { + $results[] = $value; + + continue; + } - if ($prefix === null || $prefix === '') { - return $value; + $results[] = s($value)->ensureStart($prefix)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->ensureStart($prefix)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EnumName.php b/src/core/etl/src/Flow/ETL/Function/EnumName.php index 1a6e4399d3..bc3b44b209 100644 --- a/src/core/etl/src/Flow/ETL/Function/EnumName.php +++ b/src/core/etl/src/Flow/ETL/Function/EnumName.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use UnitEnum; @@ -49,14 +53,25 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): string + public function eval(Rows $rows, FlowContext $context): Column { - $enum = (new Parameter($this->value))->eval($row, $context); + $enums = (new Parameter($this->value))->values($rows, $context); + $results = []; + $i = 0; - if (!$enum instanceof UnitEnum) { - throw new InvalidArgumentException('EnumName function requires a UnitEnum value'); + try { + // @mago-ignore analysis:mixed-assignment + foreach ($enums as $i => $enum) { + if (!$enum instanceof UnitEnum) { + throw new InvalidArgumentException('EnumName function requires a UnitEnum value'); + } + + $results[] = $enum->name; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $enum->name; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EnumValue.php b/src/core/etl/src/Flow/ETL/Function/EnumValue.php index 3fed477765..29c7c2aee1 100644 --- a/src/core/etl/src/Flow/ETL/Function/EnumValue.php +++ b/src/core/etl/src/Flow/ETL/Function/EnumValue.php @@ -5,10 +5,14 @@ namespace Flow\ETL\Function; use BackedEnum; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Native\EnumType; use ReflectionEnum; @@ -65,14 +69,25 @@ public function returns(): Type return $backingType !== null && $backingType->getName() === 'int' ? type_integer() : type_string(); } - public function eval(Row $row, FlowContext $context): int|string + public function eval(Rows $rows, FlowContext $context): Column { - $enum = (new Parameter($this->value))->eval($row, $context); - - if (!$enum instanceof BackedEnum) { - throw new InvalidArgumentException('EnumValue function requires a BackedEnum value'); + $enums = (new Parameter($this->value))->values($rows, $context); + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($enums as $i => $enum) { + if (!$enum instanceof BackedEnum) { + throw new InvalidArgumentException('EnumValue function requires a BackedEnum value'); + } + + $results[] = $enum->value; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $enum->value; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Equals.php b/src/core/etl/src/Flow/ETL/Function/Equals.php index af9c492343..3f4ef5eb54 100644 --- a/src/core/etl/src/Flow/ETL/Function/Equals.php +++ b/src/core/etl/src/Flow/ETL/Function/Equals.php @@ -7,13 +7,19 @@ use DateInterval; use DateTimeImmutable; use DateTimeInterface; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; use Flow\Types\Type\ValueComparator; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; final class Equals implements ScalarFunction @@ -56,24 +62,56 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->left->returns(), $this->right->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $left = (new Parameter($this->left))->eval($row, $context); - $right = (new Parameter($this->right))->eval($row, $context); + $leftColumn = (new Parameter($this->left))->column($rows, $context); + $rightColumn = (new Parameter($this->right))->column($rows, $context); + $comparable = new ComparableValues(); + $sameType = type_bare($leftColumn->type())::class === type_bare($rightColumn->type())::class; + [$lefts, $rights] = $sameType + ? [$comparable->equality($leftColumn), $comparable->equality($rightColumn)] + : [$leftColumn->values(), $rightColumn->values()]; + $results = []; + $i = 0; - if ($left === null || $right === null) { - return null; + // same-typed physicals: every arm of the dispatch below is === on them + if ($sameType && $comparable->equalByPhysical($leftColumn->type())) { + // @mago-ignore analysis:mixed-assignment + foreach ($lefts as $i => $left) { + $results[] = $left === null || $rights[$i] === null ? null : $left === $rights[$i]; + } + + return (new ResultColumn())->of($this, $results); + } + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($lefts as $i => $left) { + // @mago-ignore analysis:mixed-assignment + $right = $rights[$i]; + + if ($left === null || $right === null) { + $results[] = null; + + continue; + } + + // The dispatch picks a comparison strategy from the values, never a column type - bind has + // already proved the pair comparable in returns(). + // @mago-expect analysis:mixed-operand(2) + $results[] = match (true) { + is_int($left) || is_float($left) || is_int($right) || is_float($right) => $left == $right, + $left instanceof DateTimeInterface && $right instanceof DateTimeInterface => $left == $right, + $left instanceof DateInterval && $right instanceof DateInterval => (new DateTimeImmutable( + '@0', + ))->add($left) == (new DateTimeImmutable('@0'))->add($right), + default => $left === $right, + }; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - // The dispatch picks a comparison strategy from the values, never a column type - bind has - // already proved the pair comparable in returns(). - return match (true) { - is_int($left) || is_float($left) || is_int($right) || is_float($right) => $left == $right, - $left instanceof DateTimeInterface && $right instanceof DateTimeInterface => $left == $right, - $left instanceof DateInterval && $right instanceof DateInterval => (new DateTimeImmutable('@0'))->add( - $left, - ) == (new DateTimeImmutable('@0'))->add($right), - default => $left === $right, - }; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Evaluation/ResultColumn.php b/src/core/etl/src/Flow/ETL/Function/Evaluation/ResultColumn.php new file mode 100644 index 0000000000..9d1bc4b9c7 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Function/Evaluation/ResultColumn.php @@ -0,0 +1,161 @@ +` column of an ExpandResults function: one list per row. + * + * @param list> $lists + */ + public function lists(ScalarFunction $function, array $lists): Column + { + $element = ReturnTypes::of($function); + + if ($element === null) { + return new ValueColumn($lists); + } + + return $this->typed(type_optional(type_list($element)), $lists); + } + + /** + * @param list $values logical or raw, cast once by the builder + */ + public function of(ScalarFunction $function, array $values): Column + { + $returns = ReturnTypes::of($function); + + if ($returns === null) { + return new ValueColumn($values); + } + + // nullable on purpose: only the step that stores the column (withEntry/filter gate) enforces NOT NULL, as today + return $this->typed($returns instanceof NullType ? $returns : type_optional(type_bare($returns)), $values); + } + + /** + * An intermediate keeps its values in a typed column only when that column holds them losslessly: a type with a + * column kind, no xml/xml_element/html/html_element (a column keeps markup, not the live node) and no untyped + * array (a column keeps it as json) at any depth. + * + * @param Type $type + */ + public function holdsLosslessly(Type $type): bool + { + return (new PhysicalFor())->supports($type) && $this->keepsValues($type); + } + + /** + * @param Type $type + */ + public function keepsValues(Type $type): bool + { + $base = type_bare($type); + + if ( + $base instanceof ArrayType + || $base instanceof XMLType + || $base instanceof XMLElementType + || $base instanceof HTMLType + || $base instanceof HTMLElementType + ) { + return false; + } + + if ($base instanceof ListType) { + return $this->keepsValues($base->element()); + } + + if ($base instanceof MapType) { + return $this->keepsValues($base->value()); + } + + if ($base instanceof StructureType) { + foreach ($base->elements() as $element) { + if (!$this->keepsValues($element->type)) { + return false; + } + } + } + + return true; + } + + /** + * @param Type $type + * @param list $values + */ + public function typed(Type $type, array $values): Column + { + $bare = type_bare($type); + $native = match ($bare::class) { + BooleanType::class => 'bool', + IntegerType::class => 'int', + FloatType::class => 'float', + StringType::class => 'string', + default => null, + }; + + // values that already hold the column's PHP type are its physicals: no definition, no casting builder + if ($native !== null && $type instanceof OptionalType) { + $nulls = 0; + + // @mago-ignore analysis:mixed-assignment + foreach ($values as $value) { + if ($value === null) { + $nulls++; + } elseif (get_debug_type($value) !== $native) { + $native = null; + + break; + } + } + + if ($native !== null) { + return new ScalarColumn($bare, new IdentityPhysical(), $values, $nulls); + } + } + + if (!$this->holdsLosslessly($type)) { + return new ValueColumn($values); + } + + $builder = (new PhpBackend())->builder(definition_from_type('value', $type)); + $builder->appendMany($values); + + return $builder->finish(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Function/Evaluation/ReturnTypes.php b/src/core/etl/src/Flow/ETL/Function/Evaluation/ReturnTypes.php new file mode 100644 index 0000000000..7b29aeeb88 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Function/Evaluation/ReturnTypes.php @@ -0,0 +1,42 @@ +> false: the result schema is not derivable + */ + private static ?WeakMap $types = null; + + /** + * @return null|Type null when the function's result schema is not derivable + */ + public static function of(ScalarFunction $function): ?Type + { + self::$types ??= new WeakMap(); + + if (!self::$types->offsetExists($function)) { + try { + self::$types[$function] = $function->returns(); + } catch (SchemaNotDerivableException) { + self::$types[$function] = false; + } + } + + $type = self::$types[$function]; + + return $type === false ? null : $type; + } +} diff --git a/src/core/etl/src/Flow/ETL/Function/Evaluation/Selection.php b/src/core/etl/src/Flow/ETL/Function/Evaluation/Selection.php new file mode 100644 index 0000000000..7ca64a59ae --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Function/Evaluation/Selection.php @@ -0,0 +1,52 @@ + $indices ascending rows of the batch passed to evaluate() + */ + public function __construct( + private array $indices, + ) {} + + /** + * $function over the selected rows only; an error names the row of $rows it failed on. + */ + public function evaluate(ScalarFunction $function, Rows $rows, FlowContext $context): Column + { + if (count($this->indices) === $rows->count()) { + return $function->eval($rows, $context); + } + + $schema = $rows->schema(); + $names = []; + + // only the columns $function reads are copied; a reference the batch lacks (e.g. inside on_each()) is not one + foreach ((new ReferencedColumns())->in($function)->all() as $ref) { + if ($schema->findDefinition($ref->to()) !== null) { + $names[] = $ref->to(); + } + } + + $subset = $rows->project($schema->keep(...$names))->gather($this->indices); + + try { + return $function->eval($subset, $context); + } catch (EvaluationException $e) { + throw EvaluationException::at($this->indices[$e->rowIndex], $e); + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Function/Evaluation/TolerantEvaluation.php b/src/core/etl/src/Flow/ETL/Function/Evaluation/TolerantEvaluation.php new file mode 100644 index 0000000000..018556453a --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Function/Evaluation/TolerantEvaluation.php @@ -0,0 +1,81 @@ +, values: array} values of every row that did not fail + */ + public function evaluate(ScalarFunction $function, Rows $rows, FlowContext $context): array + { + $live = $rows->isEmpty() ? [] : range(0, $rows->count() - 1); + $failed = []; + $values = []; + $retries = 0; + + while (true) { + try { + // @mago-ignore analysis:mixed-assignment + foreach ((new Selection($live)) + ->evaluate($function, $rows, $context) + ->values() as $k => $value) { + $values[$live[$k]] = $value; + } + + break; + } catch (EvaluationException $e) { + $failed[$e->rowIndex] = true; + $live = array_values(array_diff($live, [$e->rowIndex])); + + if (++$retries === self::RETRIES || $live === []) { + $lane = $this->rowByRow($function, $rows, $live, $context); + + return ['failed' => $failed + $lane['failed'], 'values' => $values + $lane['values']]; + } + } catch (Exception) { + // no row coordinate: nothing to exclude + $lane = $this->rowByRow($function, $rows, $live, $context); + + return ['failed' => $failed + $lane['failed'], 'values' => $values + $lane['values']]; + } + } + + return ['failed' => $failed, 'values' => $values]; + } + + /** + * @param list $indices + * + * @return array{failed: array, values: array} + */ + public function rowByRow(ScalarFunction $function, Rows $rows, array $indices, FlowContext $context): array + { + $failed = []; + $values = []; + + foreach ($indices as $i) { + try { + $values[$i] = $function->eval($rows->slice($i, 1), $context)->values()[0]; + } catch (Exception) { + $failed[$i] = true; + } + } + + return ['failed' => $failed, 'values' => $values]; + } +} diff --git a/src/core/etl/src/Flow/ETL/Function/Exists.php b/src/core/etl/src/Flow/ETL/Function/Exists.php index 295720b486..86cccddf84 100644 --- a/src/core/etl/src/Flow/ETL/Function/Exists.php +++ b/src/core/etl/src/Flow/ETL/Function/Exists.php @@ -4,12 +4,16 @@ namespace Flow\ETL\Function; -use Exception; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Function\Evaluation\TolerantEvaluation; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Type; +use function array_fill; +use function array_key_exists; use function Flow\Types\DSL\type_boolean; final class Exists implements ScalarFunction @@ -48,20 +52,28 @@ public function returns(): Type return type_boolean(); } - public function eval(Row $row, FlowContext $context): bool + public function eval(Rows $rows, FlowContext $context): Column { - try { - if ($this->ref instanceof Reference) { - return $row->has($this->ref->name()); - } + if ($this->ref instanceof Reference) { + $exists = $rows->schema()->findDefinition($this->ref->name()) !== null; - (new Parameter($this->ref))->eval($row, $context); + // @mago-ignore analysis:possibly-invalid-argument + return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), $exists)); + } + + // the operand is left unresolved by the gate (children() is empty): a reference the batch lacks stays + // unresolved and throws, which is this function's "no" + $failed = (new TolerantEvaluation())->evaluate( + (new ReferenceResolver())->resolve($this->ref, $rows->schema()), + $rows, + $context, + )['failed']; + $results = []; - return true; - } catch (Exception) { - // "Can this reference be reached" is this function's whole question - a throwing - // operand legitimately means "no". Deliberately kept after the LENIENT removal. - return false; + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $results[] = !array_key_exists($i, $failed); } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/First.php b/src/core/etl/src/Flow/ETL/Function/First.php index f828d818e0..e1bd1c8808 100644 --- a/src/core/etl/src/Flow/ETL/Function/First.php +++ b/src/core/etl/src/Flow/ETL/Function/First.php @@ -4,12 +4,14 @@ namespace Flow\ETL\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\Types\DSL\type_optional; +use function sprintf; final class First implements AggregatingFunction { @@ -49,16 +51,29 @@ public function withChildren(array $children): static return new self($children[0]); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref)) { + if ($this->found || $indices === [] || $rows->schema()->findDefinition($this->ref->base()) === null) { return; } - if (!$this->found) { - $this->first = $row->get($this->ref); - $this->found = true; + // @mago-ignore analysis:mixed-property-type-coercion + $this->first = $rows->column($this->ref->base())->value($indices[0]); + $this->found = true; + } + + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); } + + if ($this->found || !$other->found) { + return; + } + + $this->first = $other->first; + $this->found = true; } public function outputName(): string diff --git a/src/core/etl/src/Flow/ETL/Function/GreaterThan.php b/src/core/etl/src/Flow/ETL/Function/GreaterThan.php index b6b024a158..d2c8eebd3c 100644 --- a/src/core/etl/src/Flow/ETL/Function/GreaterThan.php +++ b/src/core/etl/src/Flow/ETL/Function/GreaterThan.php @@ -6,13 +6,19 @@ use DateInterval; use DateTimeImmutable; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; use Flow\Types\Type\ValueComparator; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; final class GreaterThan implements ScalarFunction @@ -55,23 +61,45 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->left->returns(), $this->right->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $left = (new Parameter($this->left))->eval($row, $context); - $right = (new Parameter($this->right))->eval($row, $context); - - if ($left === null || $right === null) { - return null; - } - - // The dispatch picks a comparison strategy from the values, never a column type - bind has - // already proved the pair comparable in returns(). - if ($left instanceof DateInterval && $right instanceof DateInterval) { - $reference = new DateTimeImmutable('@0'); - - return $reference->add($left) > $reference->add($right); + $leftColumn = (new Parameter($this->left))->column($rows, $context); + $rightColumn = (new Parameter($this->right))->column($rows, $context); + $comparable = new ComparableValues(); + [$lefts, $rights] = type_bare($leftColumn->type())::class === type_bare($rightColumn->type())::class + ? [$comparable->ordering($leftColumn), $comparable->ordering($rightColumn)] + : [$leftColumn->values(), $rightColumn->values()]; + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($lefts as $i => $left) { + // @mago-ignore analysis:mixed-assignment + $right = $rights[$i]; + + if ($left === null || $right === null) { + $results[] = null; + + continue; + } + + // The dispatch picks a comparison strategy from the values, never a column type - bind has + // already proved the pair comparable in returns(). + if ($left instanceof DateInterval && $right instanceof DateInterval) { + $reference = new DateTimeImmutable('@0'); + $results[] = $reference->add($left) > $reference->add($right); + + continue; + } + + // @mago-expect analysis:mixed-operand(2) + $results[] = $left > $right; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $left > $right; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/GreaterThanEqual.php b/src/core/etl/src/Flow/ETL/Function/GreaterThanEqual.php index 32d6f68883..cf397c1f27 100644 --- a/src/core/etl/src/Flow/ETL/Function/GreaterThanEqual.php +++ b/src/core/etl/src/Flow/ETL/Function/GreaterThanEqual.php @@ -6,13 +6,19 @@ use DateInterval; use DateTimeImmutable; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; use Flow\Types\Type\ValueComparator; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; final class GreaterThanEqual implements ScalarFunction @@ -55,23 +61,45 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->left->returns(), $this->right->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $left = (new Parameter($this->left))->eval($row, $context); - $right = (new Parameter($this->right))->eval($row, $context); - - if ($left === null || $right === null) { - return null; - } - - // The dispatch picks a comparison strategy from the values, never a column type - bind has - // already proved the pair comparable in returns(). - if ($left instanceof DateInterval && $right instanceof DateInterval) { - $reference = new DateTimeImmutable('@0'); - - return $reference->add($left) >= $reference->add($right); + $leftColumn = (new Parameter($this->left))->column($rows, $context); + $rightColumn = (new Parameter($this->right))->column($rows, $context); + $comparable = new ComparableValues(); + [$lefts, $rights] = type_bare($leftColumn->type())::class === type_bare($rightColumn->type())::class + ? [$comparable->ordering($leftColumn), $comparable->ordering($rightColumn)] + : [$leftColumn->values(), $rightColumn->values()]; + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($lefts as $i => $left) { + // @mago-ignore analysis:mixed-assignment + $right = $rights[$i]; + + if ($left === null || $right === null) { + $results[] = null; + + continue; + } + + // The dispatch picks a comparison strategy from the values, never a column type - bind has + // already proved the pair comparable in returns(). + if ($left instanceof DateInterval && $right instanceof DateInterval) { + $reference = new DateTimeImmutable('@0'); + $results[] = $reference->add($left) >= $reference->add($right); + + continue; + } + + // @mago-expect analysis:mixed-operand(2) + $results[] = $left >= $right; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $left >= $right; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Greatest.php b/src/core/etl/src/Flow/ETL/Function/Greatest.php index 67da939ddb..600e99c180 100644 --- a/src/core/etl/src/Flow/ETL/Function/Greatest.php +++ b/src/core/etl/src/Flow/ETL/Function/Greatest.php @@ -4,8 +4,10 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Unifier\NullabilityRule; @@ -69,23 +71,27 @@ public function returns(): Type ); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - // NULL iff every argument is NULL - nulls are skipped, never compared - $values = []; - - foreach ($this->values as $value) { - $evaluated = (new Parameter($value))->eval($row, $context); - - if ($evaluated !== null) { - $values[] = $evaluated; + $arguments = array_map(static fn(ScalarFunction $value): array => (new Parameter($value))->values( + $rows, + $context, + ), $this->values); + $results = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + // NULL iff every argument is NULL - nulls are skipped, never compared + $values = []; + + foreach ($arguments as $argument) { + if ($argument[$i] !== null) { + $values[] = $argument[$i]; + } } - } - if ($values === []) { - return null; + $results[] = $values === [] ? null : max($values); } - return max($values); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelector.php b/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelector.php index f7eebc79c6..b47e6e68b4 100644 --- a/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelector.php +++ b/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelector.php @@ -4,13 +4,16 @@ namespace Flow\ETL\Function; -use Dom\Element; use Dom\HTMLDocument; use Dom\HTMLElement; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RequiredPHPVersionException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -61,24 +64,36 @@ public function returns(): Type return type_optional(type_html_element()); } - public function eval(Row $row, FlowContext $context): ?Element + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->as( - $row, + $values = (new Parameter($this->value))->asTypes( + $rows, $context, type_instance_of(HTMLDocument::class), type_instance_of(HTMLElement::class), ); - $selector = (new Parameter($this->selector))->asString($row, $context); + $selectors = (new Parameter($this->selector))->asStrings($rows, $context); + $results = []; + $i = 0; - if (null === $value) { - throw new InvalidArgumentException('HTMLQuerySelector requires non-null HTMLDocument'); - } + try { + foreach ($values as $i => $value) { + $selector = $selectors[$i]; + + if (null === $value) { + throw new InvalidArgumentException('HTMLQuerySelector requires non-null HTMLDocument'); + } + + if (null === $selector) { + throw new InvalidArgumentException('HTMLQuerySelector requires non-null selector'); + } - if (null === $selector) { - throw new InvalidArgumentException('HTMLQuerySelector requires non-null selector'); + $results[] = $value->querySelector($selector); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $value->querySelector($selector); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelectorAll.php b/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelectorAll.php index e086960e85..4d4eefc79f 100644 --- a/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelectorAll.php +++ b/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelectorAll.php @@ -7,10 +7,14 @@ use DOM\Element; use DOM\HTMLDocument; use Dom\HTMLElement; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RequiredPHPVersionException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function class_exists; @@ -62,43 +66,54 @@ public function returns(): Type return type_optional(type_list(type_html_element())); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->as( - $row, + $values = (new Parameter($this->value))->asTypes( + $rows, $context, type_instance_of(HTMLDocument::class), type_instance_of(HTMLElement::class), ); - $selector = (new Parameter($this->selector))->asString($row, $context); + $selectors = (new Parameter($this->selector))->asStrings($rows, $context); + $results = []; + $i = 0; - if (null === $value) { - throw new InvalidArgumentException('HTMLQuerySelectorAll requires non-null HTMLDocument'); - } + try { + foreach ($values as $i => $value) { + $selector = $selectors[$i]; - if (null === $selector) { - throw new InvalidArgumentException('HTMLQuerySelectorAll requires non-null selector'); - } + if (null === $value) { + throw new InvalidArgumentException('HTMLQuerySelectorAll requires non-null HTMLDocument'); + } - $result = $value->querySelectorAll($selector); + if (null === $selector) { + throw new InvalidArgumentException('HTMLQuerySelectorAll requires non-null selector'); + } - if (0 === $result->count()) { - return null; - } + $result = $value->querySelectorAll($selector); - $nodes = []; + if (0 === $result->count()) { + $results[] = null; - foreach ($result as $node) { - if (!$node instanceof Element) { - continue; - } + continue; + } + + $nodes = []; + + foreach ($result as $node) { + if (!$node instanceof Element) { + continue; + } - $nodes[] = $node; + $nodes[] = $node; + } + + $results[] = $nodes; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $nodes; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Hash.php b/src/core/etl/src/Flow/ETL/Function/Hash.php index 8f5fcfdf40..e1672318ae 100644 --- a/src/core/etl/src/Flow/ETL/Function/Hash.php +++ b/src/core/etl/src/Flow/ETL/Function/Hash.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Hash\Algorithm; use Flow\ETL\Hash\NativePHPHash; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Value\Json; @@ -56,20 +60,31 @@ public function returns(): Type return type_optional(type_string()); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); + $values = (new Parameter($this->value))->values($rows, $context); + $results = []; + $i = 0; - if ($value instanceof Json) { - $value = $value->toArray(); + try { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + if ($value instanceof Json) { + $value = $value->toArray(); + } + + $results[] = match ($value) { + null => null, + default => match (gettype($value)) { + 'array', 'object' => $this->algorithm->hash(serialize($value)), + default => $this->algorithm->hash(is_scalar($value) ? (string) $value : ''), + }, + }; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return match ($value) { - null => null, - default => match (gettype($value)) { - 'array', 'object' => $this->algorithm->hash(serialize($value)), - default => $this->algorithm->hash(is_scalar($value) ? (string) $value : ''), - }, - }; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IndexOf.php b/src/core/etl/src/Flow/ETL/Function/IndexOf.php index a496787bb7..47e09ffa21 100644 --- a/src/core/etl/src/Flow/ETL/Function/IndexOf.php +++ b/src/core/etl/src/Flow/ETL/Function/IndexOf.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -60,21 +64,40 @@ public function returns(): Type return type_optional(type_integer()); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); - $needle = (new Parameter($this->needle))->asString($row, $context); - $offset = type_integer()->assert((new Parameter($this->offset))->as($row, $context, type_integer())); - $ignoreCase = (new Parameter($this->ignoreCase))->asBoolean($row, $context) ?? false; + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $offsets = (new Parameter($this->offset))->asTypes($rows, $context, type_integer()); + $ignoreCases = (new Parameter($this->ignoreCase))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($string === null || $needle === null) { - throw new InvalidArgumentException('IndexOf function requires non-null string and needle'); - } + try { + foreach ($strings as $i => $string) { + $needle = $needles[$i]; + $offset = $offsets[$i]; + $ignoreCase = $ignoreCases[$i]; + + $offset = type_integer()->assert($offset); + $ignoreCase ??= false; + + if ($string === null || $needle === null) { + throw new InvalidArgumentException('IndexOf function requires non-null string and needle'); + } + + if ($ignoreCase) { + $results[] = u($string)->ignoreCase()->indexOf($needle, $offset); + + continue; + } - if ($ignoreCase) { - return u($string)->ignoreCase()->indexOf($needle, $offset); + $results[] = u($string)->indexOf($needle, $offset); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return u($string)->indexOf($needle, $offset); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IndexOfLast.php b/src/core/etl/src/Flow/ETL/Function/IndexOfLast.php index 28cd3845c4..7c5387b323 100644 --- a/src/core/etl/src/Flow/ETL/Function/IndexOfLast.php +++ b/src/core/etl/src/Flow/ETL/Function/IndexOfLast.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -60,21 +64,40 @@ public function returns(): Type return type_optional(type_integer()); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); - $needle = (new Parameter($this->needle))->asString($row, $context); - $offset = type_integer()->assert((new Parameter($this->offset))->as($row, $context, type_integer())); - $ignoreCase = (new Parameter($this->ignoreCase))->asBoolean($row, $context) ?? false; + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $offsets = (new Parameter($this->offset))->asTypes($rows, $context, type_integer()); + $ignoreCases = (new Parameter($this->ignoreCase))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($string === null || $needle === null) { - throw new InvalidArgumentException('IndexOfLast function requires non-null string and needle'); - } + try { + foreach ($strings as $i => $string) { + $needle = $needles[$i]; + $offset = $offsets[$i]; + $ignoreCase = $ignoreCases[$i]; + + $offset = type_integer()->assert($offset); + $ignoreCase ??= false; + + if ($string === null || $needle === null) { + throw new InvalidArgumentException('IndexOfLast function requires non-null string and needle'); + } + + if ($ignoreCase) { + $results[] = u($string)->ignoreCase()->indexOfLast($needle, $offset); + + continue; + } - if ($ignoreCase) { - return u($string)->ignoreCase()->indexOfLast($needle, $offset); + $results[] = u($string)->indexOfLast($needle, $offset); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return u($string)->indexOfLast($needle, $offset); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsEmpty.php b/src/core/etl/src/Flow/ETL/Function/IsEmpty.php index 91d8a4287e..31b4d05aa7 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsEmpty.php +++ b/src/core/etl/src/Flow/ETL/Function/IsEmpty.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -49,14 +53,26 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->value->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - return null; + try { + foreach ($values as $i => $value) { + if ($value === null) { + $results[] = null; + + continue; + } + + $results[] = s($value)->isEmpty(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->isEmpty(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsIn.php b/src/core/etl/src/Flow/ETL/Function/IsIn.php index 19ff851ed0..403a2f9b85 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsIn.php +++ b/src/core/etl/src/Flow/ETL/Function/IsIn.php @@ -5,8 +5,14 @@ namespace Flow\ETL\Function; use DateTimeInterface; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Column\Php\PhysicalFor; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; use Flow\Types\Type\Logical\MapType; @@ -14,7 +20,9 @@ use Flow\Types\Type\ValueComparator; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; +use function get_debug_type; use function in_array; final class IsIn implements ScalarFunction @@ -76,37 +84,78 @@ public function returns(): Type return $nullability->any(type_boolean(), $haystack, $needle); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $haystack = (new Parameter($this->haystack))->asArray($row, $context); - $needle = (new Parameter($this->needle))->eval($row, $context); - - if ($haystack === null || $needle === null) { - return null; + $haystackParameter = new Parameter($this->haystack); + $haystackColumn = $haystackParameter->column($rows, $context); + $needleColumn = (new Parameter($this->needle))->column($rows, $context); + $haystackType = type_bare($haystackColumn->type()); + $comparable = new ComparableValues(); + + // a list of the needle's type compares by the physical form of its elements: list physicals are the + // element physicals + if ( + $haystackType instanceof ListType + && type_bare($haystackType->element())::class === type_bare($needleColumn->type())::class + && $comparable->equalByPhysical($needleColumn->type()) + ) { + /** @var list> $haystacks */ + $haystacks = $haystackColumn->physicals(); + $needles = $needleColumn->physicals(); + $physical = null; + } else { + $haystacks = $haystackParameter->arraysOf($haystackColumn); + $needles = $needleColumn->values(); + // a candidate of the needle's kind compares by its physical form, as the list path above does + $physical = $comparable->equalByPhysical($needleColumn->type()) + ? (new PhysicalFor())->type(type_bare($needleColumn->type())) + : null; } - // Equals::eval()'s dispatch minus its DateInterval arm, which IsIn never had: two equal - // DateIntervals still compare equal under equals() and NOT equal under isIn(). Bind has - // already proved the pair comparable in returns(). - // @mago-ignore analysis:mixed-assignment - foreach ($haystack as $candidate) { - if ($candidate === null) { - continue; - } - - // @mago-ignore analysis:mixed-operand - if (match (true) { - is_int($needle) || is_float($needle) || is_int($candidate) || is_float($candidate) => $needle - == $candidate, - $needle instanceof DateTimeInterface && $candidate instanceof DateTimeInterface => $needle - == $candidate, - default => $needle === $candidate, - }) { - return true; + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($needles as $i => $needle) { + $haystack = $haystacks[$i]; + + if ($haystack === null || $needle === null) { + $results[] = null; + + continue; + } + + // Bind has already proved the pair comparable in returns(). + // @mago-ignore analysis:mixed-assignment + foreach ($haystack as $candidate) { + if ($candidate === null) { + continue; + } + + // @mago-expect analysis:mixed-operand(2) + if (match (true) { + is_int($needle) || is_float($needle) || is_int($candidate) || is_float($candidate) => $needle + == $candidate, + $needle instanceof DateTimeInterface && $candidate instanceof DateTimeInterface => $needle + == $candidate, + $physical !== null && get_debug_type($needle) === get_debug_type($candidate) + => $physical->toPhysical($needle) === $physical->toPhysical($candidate), + default => $needle === $candidate, + }) { + $results[] = true; + + continue 2; + } + } + + // A match beats a NULL element; no match with a NULL element is unknowable + $results[] = in_array(null, $haystack, true) ? null : false; } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - // A match beats a NULL element; no match with a NULL element is unknowable - return in_array(null, $haystack, true) ? null : false; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsNotNull.php b/src/core/etl/src/Flow/ETL/Function/IsNotNull.php index 4d1e6afbe3..56e4b3189d 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsNotNull.php +++ b/src/core/etl/src/Flow/ETL/Function/IsNotNull.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; +use function array_fill; use function Flow\ETL\DSL\lit; use function Flow\Types\DSL\type_boolean; @@ -47,8 +50,21 @@ public function returns(): Type return type_boolean(); } - public function eval(Row $row, FlowContext $context): bool + public function eval(Rows $rows, FlowContext $context): Column { - return (new Parameter($this->value))->eval($row, $context) !== null; + $column = (new Parameter($this->value))->column($rows, $context); + + if ($column->nullCount() === 0) { + // @mago-ignore analysis:possibly-invalid-argument + return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), true)); + } + + $results = []; + + for ($i = 0, $count = $column->count(); $i < $count; $i++) { + $results[] = !$column->isNull($i); + } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsNotNumeric.php b/src/core/etl/src/Flow/ETL/Function/IsNotNumeric.php index 100ab7e3b6..6904b73a91 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsNotNumeric.php +++ b/src/core/etl/src/Flow/ETL/Function/IsNotNumeric.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -49,14 +53,27 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->value->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); + $values = (new Parameter($this->value))->values($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - return null; + try { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + if ($value === null) { + $results[] = null; + + continue; + } + + $results[] = !is_numeric($value); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return !is_numeric($value); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsNull.php b/src/core/etl/src/Flow/ETL/Function/IsNull.php index 0349acf157..03509005bd 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsNull.php +++ b/src/core/etl/src/Flow/ETL/Function/IsNull.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; +use function array_fill; use function Flow\ETL\DSL\lit; use function Flow\Types\DSL\type_boolean; @@ -47,8 +50,21 @@ public function returns(): Type return type_boolean(); } - public function eval(Row $row, FlowContext $context): bool + public function eval(Rows $rows, FlowContext $context): Column { - return (new Parameter($this->value))->eval($row, $context) === null; + $column = (new Parameter($this->value))->column($rows, $context); + + if ($column->nullCount() === 0) { + // @mago-ignore analysis:possibly-invalid-argument + return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), false)); + } + + $results = []; + + for ($i = 0, $count = $column->count(); $i < $count; $i++) { + $results[] = $column->isNull($i); + } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsNumeric.php b/src/core/etl/src/Flow/ETL/Function/IsNumeric.php index aa41618711..92a0652d08 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsNumeric.php +++ b/src/core/etl/src/Flow/ETL/Function/IsNumeric.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -49,14 +53,27 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->value->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); + $values = (new Parameter($this->value))->values($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - return null; + try { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + if ($value === null) { + $results[] = null; + + continue; + } + + $results[] = is_numeric($value); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return is_numeric($value); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsType.php b/src/core/etl/src/Flow/ETL/Function/IsType.php index f1c1b132b9..4095385cbd 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsType.php +++ b/src/core/etl/src/Flow/ETL/Function/IsType.php @@ -4,8 +4,10 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; use Flow\Types\Type\TypeFactory; @@ -61,22 +63,30 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->value->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); + $results = []; - // A NULL operand is unknowable, even against type_null() - ->isNull() is the null test. - if ($value === null) { - return null; - } + // @mago-ignore analysis:mixed-assignment + foreach ((new Parameter($this->value))->values($rows, $context) as $value) { + // A NULL operand is unknowable, even against type_null() - ->isNull() is the null test. + if ($value === null) { + $results[] = null; - foreach ($this->types as $type) { - // @mago-ignore analysis:redundant-type-comparison - if ($type->isValid($value)) { - return true; + continue; } + + foreach ($this->types as $type) { + if ($type->isValid($value)) { + $results[] = true; + + continue 2; + } + } + + $results[] = false; } - return false; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsUtf8.php b/src/core/etl/src/Flow/ETL/Function/IsUtf8.php index b078eec7dd..0ddebe4ff5 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsUtf8.php +++ b/src/core/etl/src/Flow/ETL/Function/IsUtf8.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -49,14 +53,26 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->string->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - return null; + try { + foreach ($strings as $i => $string) { + if ($string === null) { + $results[] = null; + + continue; + } + + $results[] = b($string)->isUtf8(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return b($string)->isUtf8(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/JsonDecode.php b/src/core/etl/src/Flow/ETL/Function/JsonDecode.php index 69b51a897c..ccdc808ddb 100644 --- a/src/core/etl/src/Flow/ETL/Function/JsonDecode.php +++ b/src/core/etl/src/Flow/ETL/Function/JsonDecode.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Value\Json; use JsonException; @@ -55,40 +59,59 @@ public function returns(): Type return type_array(); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); - $flags = (int) (new Parameter($this->flags))->asInt($row, $context); + $values = (new Parameter($this->value))->values($rows, $context); + $flagsList = (new Parameter($this->flags))->asInts($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('JsonDecode function requires non-null value'); - } + try { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + $flags = $flagsList[$i]; - if ($value instanceof Json) { - return $value->toArray(); - } + $flags = (int) $flags; - if (is_array($value)) { - return $value; - } + if ($value === null) { + throw new InvalidArgumentException('JsonDecode function requires non-null value'); + } - if (!is_string($value)) { - throw new InvalidArgumentException('JsonDecode function requires string, array, or Json value'); - } + if ($value instanceof Json) { + $results[] = $value->toArray(); - try { - // @mago-ignore analysis:mixed-assignment - $decoded = json_decode($value, true, 512, $flags); - } catch (JsonException $e) { - throw new InvalidArgumentException('JsonDecode error: ' . $e->getMessage()); - } + continue; + } + + if (is_array($value)) { + $results[] = $value; + + continue; + } + + if (!is_string($value)) { + throw new InvalidArgumentException('JsonDecode function requires string, array, or Json value'); + } + + try { + // @mago-ignore analysis:mixed-assignment + $decoded = json_decode($value, true, 512, $flags); + } catch (JsonException $e) { + throw new InvalidArgumentException('JsonDecode error: ' . $e->getMessage(), 0, $e); + } + + if (!is_array($decoded)) { + throw new InvalidArgumentException( + 'JsonDecode function requires JSON that decodes to an array, cast scalar JSON instead', + ); + } - if (!is_array($decoded)) { - throw new InvalidArgumentException( - 'JsonDecode function requires JSON that decodes to an array, cast scalar JSON instead', - ); + $results[] = $decoded; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $decoded; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/JsonEncode.php b/src/core/etl/src/Flow/ETL/Function/JsonEncode.php index b4c6142dbd..12e981cd9f 100644 --- a/src/core/etl/src/Flow/ETL/Function/JsonEncode.php +++ b/src/core/etl/src/Flow/ETL/Function/JsonEncode.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\JsonType; use Flow\Types\Type\Logical\ListType; @@ -72,29 +76,48 @@ public function returns(): Type return type_optional($isContainer ? type_json() : type_string()); } - public function eval(Row $row, FlowContext $context): Json|string|null + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); - $flags = (int) (new Parameter($this->flags))->asInt($row, $context); - - if ($value === null) { - return null; - } + $values = (new Parameter($this->value))->values($rows, $context); + $flagsList = (new Parameter($this->flags))->asInts($rows, $context); + $results = []; + $i = 0; try { - $encoded = json_encode($value, $flags); + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + $flags = $flagsList[$i]; - if ($encoded === false) { - throw new InvalidArgumentException('JsonEncode error: json_encode returned false'); - } + $flags = (int) $flags; - if (is_array($value) || is_object($value)) { - return new Json($encoded); - } + if ($value === null) { + $results[] = null; + + continue; + } + + try { + $encoded = json_encode($value, $flags); - return $encoded; - } catch (JsonException $e) { - throw new InvalidArgumentException('JsonEncode error: ' . $e->getMessage()); + if ($encoded === false) { + throw new InvalidArgumentException('JsonEncode error: json_encode returned false'); + } + + if (is_array($value) || is_object($value)) { + $results[] = new Json($encoded); + + continue; + } + + $results[] = $encoded; + } catch (JsonException $e) { + throw new InvalidArgumentException('JsonEncode error: ' . $e->getMessage()); + } + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Last.php b/src/core/etl/src/Flow/ETL/Function/Last.php index 4e0147450a..eb52ddbad4 100644 --- a/src/core/etl/src/Flow/ETL/Function/Last.php +++ b/src/core/etl/src/Flow/ETL/Function/Last.php @@ -4,17 +4,22 @@ namespace Flow\ETL\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Type; +use function count; use function Flow\Types\DSL\type_optional; +use function sprintf; final class Last implements AggregatingFunction { use ResolvesFromChildren; + private bool $found = false; + /** * @var null|array|bool|float|int|object|string */ @@ -46,13 +51,29 @@ public function withChildren(array $children): static return new self($children[0]); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref)) { + if ($indices === [] || $rows->schema()->findDefinition($this->ref->base()) === null) { + return; + } + + // @mago-ignore analysis:mixed-property-type-coercion + $this->last = $rows->column($this->ref->base())->value($indices[count($indices) - 1]); + $this->found = true; + } + + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); + } + + if (!$other->found) { return; } - $this->last = $row->get($this->ref); + $this->last = $other->last; + $this->found = true; } public function outputName(): string diff --git a/src/core/etl/src/Flow/ETL/Function/Least.php b/src/core/etl/src/Flow/ETL/Function/Least.php index f10a4d10a3..65146ef23c 100644 --- a/src/core/etl/src/Flow/ETL/Function/Least.php +++ b/src/core/etl/src/Flow/ETL/Function/Least.php @@ -4,8 +4,10 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Unifier\NullabilityRule; @@ -69,23 +71,27 @@ public function returns(): Type ); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - // NULL iff every argument is NULL - nulls are skipped, never compared - $values = []; - - foreach ($this->values as $value) { - $evaluated = (new Parameter($value))->eval($row, $context); - - if ($evaluated !== null) { - $values[] = $evaluated; + $arguments = array_map(static fn(ScalarFunction $value): array => (new Parameter($value))->values( + $rows, + $context, + ), $this->values); + $results = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + // NULL iff every argument is NULL - nulls are skipped, never compared + $values = []; + + foreach ($arguments as $argument) { + if ($argument[$i] !== null) { + $values[] = $argument[$i]; + } } - } - if ($values === []) { - return null; + $results[] = $values === [] ? null : min($values); } - return min($values); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/LessThan.php b/src/core/etl/src/Flow/ETL/Function/LessThan.php index 6187efc934..f62ec28022 100644 --- a/src/core/etl/src/Flow/ETL/Function/LessThan.php +++ b/src/core/etl/src/Flow/ETL/Function/LessThan.php @@ -6,13 +6,19 @@ use DateInterval; use DateTimeImmutable; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; use Flow\Types\Type\ValueComparator; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; final class LessThan implements ScalarFunction @@ -55,23 +61,45 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->left->returns(), $this->right->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $left = (new Parameter($this->left))->eval($row, $context); - $right = (new Parameter($this->right))->eval($row, $context); - - if ($left === null || $right === null) { - return null; - } - - // The dispatch picks a comparison strategy from the values, never a column type - bind has - // already proved the pair comparable in returns(). - if ($left instanceof DateInterval && $right instanceof DateInterval) { - $reference = new DateTimeImmutable('@0'); - - return $reference->add($left) < $reference->add($right); + $leftColumn = (new Parameter($this->left))->column($rows, $context); + $rightColumn = (new Parameter($this->right))->column($rows, $context); + $comparable = new ComparableValues(); + [$lefts, $rights] = type_bare($leftColumn->type())::class === type_bare($rightColumn->type())::class + ? [$comparable->ordering($leftColumn), $comparable->ordering($rightColumn)] + : [$leftColumn->values(), $rightColumn->values()]; + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($lefts as $i => $left) { + // @mago-ignore analysis:mixed-assignment + $right = $rights[$i]; + + if ($left === null || $right === null) { + $results[] = null; + + continue; + } + + // The dispatch picks a comparison strategy from the values, never a column type - bind has + // already proved the pair comparable in returns(). + if ($left instanceof DateInterval && $right instanceof DateInterval) { + $reference = new DateTimeImmutable('@0'); + $results[] = $reference->add($left) < $reference->add($right); + + continue; + } + + // @mago-expect analysis:mixed-operand(2) + $results[] = $left < $right; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $left < $right; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/LessThanEqual.php b/src/core/etl/src/Flow/ETL/Function/LessThanEqual.php index c482637658..20dd4e2703 100644 --- a/src/core/etl/src/Flow/ETL/Function/LessThanEqual.php +++ b/src/core/etl/src/Flow/ETL/Function/LessThanEqual.php @@ -6,13 +6,19 @@ use DateInterval; use DateTimeImmutable; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; use Flow\Types\Type\ValueComparator; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; final class LessThanEqual implements ScalarFunction @@ -55,23 +61,45 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->left->returns(), $this->right->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $left = (new Parameter($this->left))->eval($row, $context); - $right = (new Parameter($this->right))->eval($row, $context); - - if ($left === null || $right === null) { - return null; - } - - // The dispatch picks a comparison strategy from the values, never a column type - bind has - // already proved the pair comparable in returns(). - if ($left instanceof DateInterval && $right instanceof DateInterval) { - $reference = new DateTimeImmutable('@0'); - - return $reference->add($left) <= $reference->add($right); + $leftColumn = (new Parameter($this->left))->column($rows, $context); + $rightColumn = (new Parameter($this->right))->column($rows, $context); + $comparable = new ComparableValues(); + [$lefts, $rights] = type_bare($leftColumn->type())::class === type_bare($rightColumn->type())::class + ? [$comparable->ordering($leftColumn), $comparable->ordering($rightColumn)] + : [$leftColumn->values(), $rightColumn->values()]; + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($lefts as $i => $left) { + // @mago-ignore analysis:mixed-assignment + $right = $rights[$i]; + + if ($left === null || $right === null) { + $results[] = null; + + continue; + } + + // The dispatch picks a comparison strategy from the values, never a column type - bind has + // already proved the pair comparable in returns(). + if ($left instanceof DateInterval && $right instanceof DateInterval) { + $reference = new DateTimeImmutable('@0'); + $results[] = $reference->add($left) <= $reference->add($right); + + continue; + } + + // @mago-expect analysis:mixed-operand(2) + $results[] = $left <= $right; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $left <= $right; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ListSelect.php b/src/core/etl/src/Flow/ETL/Function/ListSelect.php index a01cfd1a8c..573fb7c92e 100644 --- a/src/core/etl/src/Flow/ETL/Function/ListSelect.php +++ b/src/core/etl/src/Flow/ETL/Function/ListSelect.php @@ -4,13 +4,15 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; use Flow\ETL\Row\UnresolvedReference; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\ArrayKey; use Flow\Types\Type\Logical\ListType; @@ -18,6 +20,7 @@ use Flow\Types\Type\Logical\StructureType; use Flow\Types\Type\TypeWidener; +use function array_fill; use function array_key_exists; use function array_values; use function Flow\Types\DSL\structure_element; @@ -100,36 +103,41 @@ public function returns(): Type return type_optional(type_list(new StructureType($elements))); } - /** - * @return null|array> - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - if (!$row->has($this->ref)) { - return null; + if ($rows->schema()->findDefinition($this->ref->base()) === null) { + // @mago-ignore analysis:possibly-invalid-argument + return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), null)); } - $list = $row->get($this->ref); + $results = []; - if (!is_array($list)) { - return null; - } + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->values() as $value) { + if (!is_array($value)) { + $results[] = null; + + continue; + } - $output = []; + $output = []; - // @mago-ignore analysis:mixed-assignment - foreach (array_values($list) as $index => $element) { - $output[$index] = []; - - foreach ($this->refs as $ref) { - if (is_array($element) && array_key_exists($ref->to(), $element)) { - $output[$index][$ref->name()] = $element[$ref->to()]; - } else { - $output[$index][$ref->name()] = null; + // @mago-ignore analysis:mixed-assignment + foreach (array_values($value) as $index => $element) { + $output[$index] = []; + + foreach ($this->refs as $ref) { + if (is_array($element) && array_key_exists($ref->to(), $element)) { + $output[$index][$ref->name()] = $element[$ref->to()]; + } else { + $output[$index][$ref->name()] = null; + } } } + + $results[] = $output; } - return $output; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Literal.php b/src/core/etl/src/Flow/ETL/Function/Literal.php index 1191700f2e..c37076bb79 100644 --- a/src/core/etl/src/Flow/ETL/Function/Literal.php +++ b/src/core/etl/src/Flow/ETL/Function/Literal.php @@ -5,13 +5,21 @@ namespace Flow\ETL\Function; use Closure; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; +use Flow\Types\Type\Native\NullType; use Flow\Types\Type\TypeDetector; +use function array_fill; use function array_walk_recursive; +use function Flow\ETL\DSL\definition_from_type; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_null; use function Flow\Types\DSL\type_optional; use function is_array; @@ -20,6 +28,11 @@ final class Literal implements ScalarFunction { use ScalarFunctionChain; + /** + * The column of the last evaluated batch, handed out again for a batch of the same size. + */ + private ?Column $column = null; + public function __construct( private readonly mixed $value, ) { @@ -68,9 +81,19 @@ public function returns(): Type return $this->value === null ? type_optional(type_null()) : (new TypeDetector())->detectType($this->value); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - return $this->value; + if ($this->column?->count() === $rows->count()) { + return $this->column; + } + + $type = type_bare($this->returns()); + $type = $type instanceof NullType ? $type : type_optional($type); + + // @mago-ignore analysis:possibly-invalid-argument + return $this->column = (new ResultColumn())->holdsLosslessly($type) + ? (new PhpBackend())->constant(definition_from_type('value', $type), $this->value, $rows->count()) + : new ValueColumn($rows->isEmpty() ? [] : array_fill(0, $rows->count(), $this->value)); } public function value(): mixed diff --git a/src/core/etl/src/Flow/ETL/Function/MatchCases.php b/src/core/etl/src/Flow/ETL/Function/MatchCases.php index 17214fb6eb..6472a28f28 100644 --- a/src/core/etl/src/Flow/ETL/Function/MatchCases.php +++ b/src/core/etl/src/Flow/ETL/Function/MatchCases.php @@ -4,11 +4,15 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Function\Evaluation\Selection; use Flow\ETL\Function\MatchCases\MatchCondition; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Unifier\NullabilityRule; @@ -20,6 +24,7 @@ use function count; use function Flow\ETL\DSL\lit; use function json_encode; +use function range; final class MatchCases implements ScalarFunction { @@ -94,21 +99,64 @@ public function returns(): Type ); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - foreach ($this->cases as $condition) { - if ($condition->valid($row, $context)) { - return $condition->eval($row, $context); + $pending = $rows->isEmpty() ? [] : range(0, $rows->count() - 1); + $values = []; + + foreach ($this->cases as $case) { + if ($pending === []) { + break; + } + + $taken = []; + $rest = []; + + foreach ($case->valid($rows, $pending, $context) as $k => $valid) { + if ($valid) { + $taken[] = $pending[$k]; + } else { + $rest[] = $pending[$k]; + } } + + if ($taken !== []) { + // @mago-ignore analysis:mixed-assignment + foreach ((new Selection($taken)) + ->evaluate($case, $rows, $context) + ->values() as $k => $value) { + $values[$taken[$k]] = $value; + } + } + + $pending = $rest; } - if ($this->default !== null) { - return (new Parameter($this->default))->eval($row, $context); + if ($pending !== []) { + if ($this->default === null) { + throw new EvaluationException( + $pending[0], + new InvalidArgumentException( + 'Not a single case matches row, consider using default parameter, row: ' + . json_encode($rows->values($pending[0]), JSON_THROW_ON_ERROR), + ), + ); + } + + // @mago-ignore analysis:mixed-assignment + foreach ((new Selection($pending)) + ->evaluate($this->default, $rows, $context) + ->values() as $k => $value) { + $values[$pending[$k]] = $value; + } } - throw new InvalidArgumentException( - 'Not a single case matches row, consider using default parameter, row: ' - . json_encode($row->toArray(), JSON_THROW_ON_ERROR), - ); + $results = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $results[] = $values[$i] ?? null; + } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/MatchCases/MatchCondition.php b/src/core/etl/src/Flow/ETL/Function/MatchCases/MatchCondition.php index 7560ef4daa..e6d23d9d6f 100644 --- a/src/core/etl/src/Flow/ETL/Function/MatchCases/MatchCondition.php +++ b/src/core/etl/src/Flow/ETL/Function/MatchCases/MatchCondition.php @@ -4,15 +4,22 @@ namespace Flow\ETL\Function\MatchCases; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\Selection; use Flow\ETL\Function\FunctionTree; use Flow\ETL\Function\Parameter; use Flow\ETL\Function\ResolvesFromChildren; use Flow\ETL\Function\ScalarFunction; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; +use function get_debug_type; +use function is_scalar; +use function sprintf; final readonly class MatchCondition implements ScalarFunction { @@ -53,13 +60,33 @@ public function returns(): Type return $this->then->returns(); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - return (new Parameter($this->then))->eval($row, $context); + return (new Parameter($this->then))->column($rows, $context); } - public function valid(Row $row, FlowContext $context): bool + /** + * @param list $indices ascending rows of $rows + * + * @return list one per index + */ + public function valid(Rows $rows, array $indices, FlowContext $context): array { - return (new Parameter($this->condition))->asBoolean($row, $context) ?? false; + $column = (new Selection($indices))->evaluate($this->condition, $rows, $context); + $valid = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $k => $value) { + if ($value !== null && !is_scalar($value)) { + throw new EvaluationException( + $indices[$k], + new InvalidArgumentException(sprintf('Expected type "boolean", got "%s".', get_debug_type($value))), + ); + } + + $valid[] = (bool) $value; + } + + return $valid; } } diff --git a/src/core/etl/src/Flow/ETL/Function/Max.php b/src/core/etl/src/Flow/ETL/Function/Max.php index 27b43c3144..fc89efbafa 100644 --- a/src/core/etl/src/Flow/ETL/Function/Max.php +++ b/src/core/etl/src/Flow/ETL/Function/Max.php @@ -5,14 +5,16 @@ namespace Flow\ETL\Function; use DateTimeInterface; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\Types\DSL\type_optional; use function is_numeric; use function max; +use function sprintf; final class Max implements AggregatingFunction { @@ -46,30 +48,43 @@ public function withChildren(array $children): static return new self($children[0]); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref)) { + if ($rows->schema()->findDefinition($this->ref->base()) === null) { return; } - /** @var mixed $value */ - $value = $row->get($this->ref); - - if ($this->max === null) { - if (is_numeric($value)) { - $this->max = (float) $value; - } elseif ($value instanceof DateTimeInterface) { - $this->max = $value; - } - } else { - if (is_numeric($value)) { - $this->max = max($this->max, (float) $value); - } elseif ($value instanceof DateTimeInterface) { - $this->max = max($this->max, $value); + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->take($indices)->values() as $value) { + if ($this->max === null) { + if (is_numeric($value)) { + $this->max = (float) $value; + } elseif ($value instanceof DateTimeInterface) { + $this->max = $value; + } + } else { + if (is_numeric($value)) { + $this->max = max($this->max, (float) $value); + } elseif ($value instanceof DateTimeInterface) { + $this->max = max($this->max, $value); + } } } } + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); + } + + if ($other->max === null) { + return; + } + + $this->max = $this->max === null ? $other->max : max($this->max, $other->max); + } + public function outputName(): string { return $this->outputName; diff --git a/src/core/etl/src/Flow/ETL/Function/Min.php b/src/core/etl/src/Flow/ETL/Function/Min.php index 9a1d2b496e..7b061a988d 100644 --- a/src/core/etl/src/Flow/ETL/Function/Min.php +++ b/src/core/etl/src/Flow/ETL/Function/Min.php @@ -5,14 +5,16 @@ namespace Flow\ETL\Function; use DateTimeInterface; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\Types\DSL\type_optional; use function is_numeric; use function min; +use function sprintf; final class Min implements AggregatingFunction { @@ -46,30 +48,43 @@ public function withChildren(array $children): static return new self($children[0]); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref)) { + if ($rows->schema()->findDefinition($this->ref->base()) === null) { return; } - /** @var mixed $value */ - $value = $row->get($this->ref); - - if ($this->min === null) { - if (is_numeric($value)) { - $this->min = (float) $value; - } elseif ($value instanceof DateTimeInterface) { - $this->min = $value; - } - } else { - if (is_numeric($value)) { - $this->min = min($this->min, (float) $value); - } elseif ($value instanceof DateTimeInterface) { - $this->min = min($this->min, $value); + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->take($indices)->values() as $value) { + if ($this->min === null) { + if (is_numeric($value)) { + $this->min = (float) $value; + } elseif ($value instanceof DateTimeInterface) { + $this->min = $value; + } + } else { + if (is_numeric($value)) { + $this->min = min($this->min, (float) $value); + } elseif ($value instanceof DateTimeInterface) { + $this->min = min($this->min, $value); + } } } } + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); + } + + if ($other->min === null) { + return; + } + + $this->min = $this->min === null ? $other->min : min($this->min, $other->min); + } + public function outputName(): string { return $this->outputName; diff --git a/src/core/etl/src/Flow/ETL/Function/Minus.php b/src/core/etl/src/Flow/ETL/Function/Minus.php index 7d42f54c5b..a38578a9f0 100644 --- a/src/core/etl/src/Flow/ETL/Function/Minus.php +++ b/src/core/etl/src/Flow/ETL/Function/Minus.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Function; -use Flow\Calculator\Calculator; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Native\FloatType; @@ -17,6 +20,8 @@ use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_integer; +use function is_float; +use function is_int; final class Minus implements ScalarFunction { @@ -25,8 +30,11 @@ final class Minus implements ScalarFunction private readonly ScalarFunction $left; private readonly ScalarFunction $right; - public function __construct(ScalarFunction|int|float $left, ScalarFunction|int|float $right) - { + public function __construct( + ScalarFunction|int|float $left, + ScalarFunction|int|float $right, + private readonly bool $exact = false, + ) { $this->left = $left instanceof ScalarFunction ? $left : lit($left); $this->right = $right instanceof ScalarFunction ? $right : lit($right); } @@ -45,7 +53,7 @@ public function children(): array public function withChildren(array $children): static { /** @var list $children */ - return new self($children[0], $children[1]); + return new self($children[0], $children[1], $this->exact); } /** @@ -66,15 +74,39 @@ public function returns(): Type return $left instanceof IntegerType && $right instanceof IntegerType ? type_integer() : type_float(); } - public function eval(Row $row, FlowContext $context): int|float|null + public function eval(Rows $rows, FlowContext $context): Column { - $leftValue = (new Parameter($this->left))->asNumber($row, $context); - $rightValue = (new Parameter($this->right))->asNumber($row, $context); + $lefts = (new Parameter($this->left))->asNumbers($rows, $context); + $rights = (new Parameter($this->right))->asNumbers($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($lefts as $i => $left) { + $right = $rights[$i]; + + if ($left === null || $right === null) { + throw new InvalidArgumentException('Minus function requires non-null values'); + } + + if ($this->exact) { + $results[] = $context->calculator()->subtract($left, $right); + + continue; + } + + $result = $left - $right; + + if (is_int($left) && is_int($right) && is_float($result)) { + throw new InvalidArgumentException('Minus function integer overflow'); + } - if ($leftValue === null || $rightValue === null) { - throw new InvalidArgumentException('Minus function requires non-null values'); + $results[] = $result; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return (new Calculator())->subtract($leftValue, $rightValue); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Mod.php b/src/core/etl/src/Flow/ETL/Function/Mod.php index 126a305747..c5f2906921 100644 --- a/src/core/etl/src/Flow/ETL/Function/Mod.php +++ b/src/core/etl/src/Flow/ETL/Function/Mod.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Function; -use Flow\Calculator\Calculator; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -51,19 +54,32 @@ public function returns(): Type return type_integer(); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { - $leftValue = (new Parameter($this->left))->asInt($row, $context); - $rightValue = (new Parameter($this->right))->asInt($row, $context); + $lefts = (new Parameter($this->left))->asInts($rows, $context); + $rights = (new Parameter($this->right))->asInts($rows, $context); + $calculator = $context->calculator(); + $results = []; + $i = 0; - if ($leftValue === null || $rightValue === null) { - throw new InvalidArgumentException('Mod function requires non-null values'); - } + try { + foreach ($lefts as $i => $leftValue) { + $rightValue = $rights[$i]; + + if ($leftValue === null || $rightValue === null) { + throw new InvalidArgumentException('Mod function requires non-null values'); + } + + if ($rightValue === 0) { + throw new InvalidArgumentException('Mod function cannot perform modulo by zero'); + } - if ($rightValue === 0) { - throw new InvalidArgumentException('Mod function cannot perform modulo by zero'); + $results[] = $calculator->modulus($leftValue, $rightValue); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return (new Calculator())->modulus($leftValue, $rightValue); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ModifyDateTime.php b/src/core/etl/src/Flow/ETL/Function/ModifyDateTime.php index 3d48320ecb..d8ba466f22 100644 --- a/src/core/etl/src/Flow/ETL/Function/ModifyDateTime.php +++ b/src/core/etl/src/Flow/ETL/Function/ModifyDateTime.php @@ -7,9 +7,13 @@ use DateTime; use DateTimeImmutable; use DateTimeInterface; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\OptionalType; @@ -58,19 +62,33 @@ public function returns(): Type return $base instanceof DateTimeType ? $base : type_datetime(); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->reference))->asInstanceOf($row, $context, DateTimeInterface::class); - $modifier = (new Parameter($this->modifier))->asString($row, $context); + $values = (new Parameter($this->reference))->asInstancesOf($rows, $context, DateTimeInterface::class); + $modifiers = (new Parameter($this->modifier))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($modifier === null || $value === null) { - throw new InvalidArgumentException('ModifyDateTime function requires non-null values'); - } + try { + foreach ($values as $i => $value) { + $modifier = $modifiers[$i]; + + if ($modifier === null || $value === null) { + throw new InvalidArgumentException('ModifyDateTime function requires non-null values'); + } + + if (!$value instanceof DateTime && !$value instanceof DateTimeImmutable) { + throw new InvalidArgumentException( + 'ModifyDateTime function requires DateTime or DateTimeImmutable object', + ); + } - if (!$value instanceof DateTime && !$value instanceof DateTimeImmutable) { - throw new InvalidArgumentException('ModifyDateTime function requires DateTime or DateTimeImmutable object'); + $results[] = $value->modify($modifier); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $value->modify($modifier); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Multiply.php b/src/core/etl/src/Flow/ETL/Function/Multiply.php index 266569c541..dc7b95fd06 100644 --- a/src/core/etl/src/Flow/ETL/Function/Multiply.php +++ b/src/core/etl/src/Flow/ETL/Function/Multiply.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Function; -use Flow\Calculator\Calculator; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Native\FloatType; @@ -17,6 +20,8 @@ use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_integer; +use function is_float; +use function is_int; final class Multiply implements ScalarFunction { @@ -25,8 +30,11 @@ final class Multiply implements ScalarFunction private readonly ScalarFunction $left; private readonly ScalarFunction $right; - public function __construct(ScalarFunction|int|float $left, ScalarFunction|int|float $right) - { + public function __construct( + ScalarFunction|int|float $left, + ScalarFunction|int|float $right, + private readonly bool $exact = false, + ) { $this->left = $left instanceof ScalarFunction ? $left : lit($left); $this->right = $right instanceof ScalarFunction ? $right : lit($right); } @@ -45,7 +53,7 @@ public function children(): array public function withChildren(array $children): static { /** @var list $children */ - return new self($children[0], $children[1]); + return new self($children[0], $children[1], $this->exact); } /** @@ -66,15 +74,39 @@ public function returns(): Type return $left instanceof IntegerType && $right instanceof IntegerType ? type_integer() : type_float(); } - public function eval(Row $row, FlowContext $context): int|float|null + public function eval(Rows $rows, FlowContext $context): Column { - $leftValue = (new Parameter($this->left))->asNumber($row, $context); - $rightValue = (new Parameter($this->right))->asNumber($row, $context); + $lefts = (new Parameter($this->left))->asNumbers($rows, $context); + $rights = (new Parameter($this->right))->asNumbers($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($lefts as $i => $left) { + $right = $rights[$i]; + + if ($left === null || $right === null) { + throw new InvalidArgumentException('Multiply function requires non-null values'); + } + + if ($this->exact) { + $results[] = $context->calculator()->multiply($left, $right); + + continue; + } + + $result = $left * $right; + + if (is_int($left) && is_int($right) && is_float($result)) { + throw new InvalidArgumentException('Multiply function integer overflow'); + } - if ($leftValue === null || $rightValue === null) { - throw new InvalidArgumentException('Multiply function requires non-null values'); + $results[] = $result; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return (new Calculator())->multiply($leftValue, $rightValue); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Not.php b/src/core/etl/src/Flow/ETL/Function/Not.php index 35ae6c7b3a..461e6e6323 100644 --- a/src/core/etl/src/Flow/ETL/Function/Not.php +++ b/src/core/etl/src/Flow/ETL/Function/Not.php @@ -4,8 +4,10 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -44,11 +46,16 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->value->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); + $results = []; - // SQL NOT NULL is NULL - the row must drop, not flip to true. - return $value === null ? null : !$value; + // @mago-ignore analysis:mixed-assignment + foreach ((new Parameter($this->value))->values($rows, $context) as $value) { + // SQL NOT NULL is NULL - the row must drop, not flip to true. + $results[] = $value === null ? null : !$value; + } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/NotEquals.php b/src/core/etl/src/Flow/ETL/Function/NotEquals.php index 564d186d2d..0c4b153dfe 100644 --- a/src/core/etl/src/Flow/ETL/Function/NotEquals.php +++ b/src/core/etl/src/Flow/ETL/Function/NotEquals.php @@ -4,8 +4,10 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; use Flow\Types\Type\ValueComparator; @@ -53,10 +55,17 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->left->returns(), $this->right->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $equals = (new Equals($this->left, $this->right))->eval($row, $context); + $results = []; - return $equals === null ? null : !$equals; + // @mago-ignore analysis:mixed-assignment + foreach ((new Equals($this->left, $this->right)) + ->eval($rows, $context) + ->physicals() as $equals) { + $results[] = $equals === null ? null : !$equals; + } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/NotSame.php b/src/core/etl/src/Flow/ETL/Function/NotSame.php index fcf0bcd056..7dc50ccd2d 100644 --- a/src/core/etl/src/Flow/ETL/Function/NotSame.php +++ b/src/core/etl/src/Flow/ETL/Function/NotSame.php @@ -4,12 +4,18 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\ValueComparator; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; final class NotSame implements ScalarFunction @@ -52,11 +58,30 @@ public function returns(): Type return type_boolean(); } - public function eval(Row $row, FlowContext $context): bool + public function eval(Rows $rows, FlowContext $context): Column { - // PHP identity, not SQL equality: null !== null is a defined, useful answer - return ( - (new Parameter($this->left))->eval($row, $context) !== (new Parameter($this->right))->eval($row, $context) - ); + $leftColumn = (new Parameter($this->left))->column($rows, $context); + $rightColumn = (new Parameter($this->right))->column($rows, $context); + $comparable = new ComparableValues(); + [$lefts, $rights] = type_bare($leftColumn->type())::class === type_bare($rightColumn->type())::class + ? [$comparable->equality($leftColumn), $comparable->equality($rightColumn)] + : [$leftColumn->values(), $rightColumn->values()]; + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($lefts as $i => $left) { + // @mago-ignore analysis:mixed-assignment + $right = $rights[$i]; + + // PHP identity, not SQL equality: null !== null is a defined, useful answer + $results[] = $left !== $right; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Now.php b/src/core/etl/src/Flow/ETL/Function/Now.php index 8fbb62af99..925eb4b0e1 100644 --- a/src/core/etl/src/Flow/ETL/Function/Now.php +++ b/src/core/etl/src/Flow/ETL/Function/Now.php @@ -6,9 +6,13 @@ use DateTimeImmutable; use DateTimeZone; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; @@ -64,14 +68,24 @@ public function returns(): Type return $this->type; } - public function eval(Row $row, FlowContext $context): ?DateTimeImmutable + public function eval(Rows $rows, FlowContext $context): Column { - $tz = (new Parameter($this->timeZone))->asInstanceOf($row, $context, DateTimeZone::class); + $tzes = (new Parameter($this->timeZone))->asInstancesOf($rows, $context, DateTimeZone::class); + $results = []; + $i = 0; - if ($tz === null) { - throw new InvalidArgumentException('Now function requires valid DateTimeZone'); + try { + foreach ($tzes as $i => $tz) { + if ($tz === null) { + throw new InvalidArgumentException('Now function requires valid DateTimeZone'); + } + + $results[] = $this->type->cast(new DateTimeImmutable('now', $tz)); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $this->type->cast(new DateTimeImmutable('now', $tz)); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/NumberFormat.php b/src/core/etl/src/Flow/ETL/Function/NumberFormat.php index 915d162253..3dcf7ab824 100644 --- a/src/core/etl/src/Flow/ETL/Function/NumberFormat.php +++ b/src/core/etl/src/Flow/ETL/Function/NumberFormat.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -63,17 +67,36 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asNumber($row, $context); - $decimals = (new Parameter($this->decimals))->asInt($row, $context); - $decimalSeparator = (new Parameter($this->decimalSeparator))->asString($row, $context); - $thousandsSeparator = (new Parameter($this->thousandsSeparator))->asString($row, $context); + $values = (new Parameter($this->value))->asNumbers($rows, $context); + $decimalsList = (new Parameter($this->decimals))->asInts($rows, $context); + $decimalSeparators = (new Parameter($this->decimalSeparator))->asStrings($rows, $context); + $thousandsSeparators = (new Parameter($this->thousandsSeparator))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null || $decimals === null || $decimalSeparator === null || $thousandsSeparator === null) { - throw new InvalidArgumentException('NumberFormat function requires non-null values'); + try { + foreach ($values as $i => $value) { + $decimals = $decimalsList[$i]; + $decimalSeparator = $decimalSeparators[$i]; + $thousandsSeparator = $thousandsSeparators[$i]; + + if ( + $value === null + || $decimals === null + || $decimalSeparator === null + || $thousandsSeparator === null + ) { + throw new InvalidArgumentException('NumberFormat function requires non-null values'); + } + + $results[] = number_format((float) $value, $decimals, $decimalSeparator, $thousandsSeparator); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return number_format((float) $value, $decimals, $decimalSeparator, $thousandsSeparator); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/OnEach.php b/src/core/etl/src/Flow/ETL/Function/OnEach.php index 8bb1bb9905..30286219ff 100644 --- a/src/core/etl/src/Flow/ETL/Function/OnEach.php +++ b/src/core/etl/src/Flow/ETL/Function/OnEach.php @@ -4,20 +4,27 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; +use Flow\ETL\Schema; use Flow\Types\Type; use Flow\Types\Type\Logical\MapType; use Flow\Types\Type\Logical\StructureElement; use Flow\Types\Type\Logical\StructureType; -use function Flow\ETL\DSL\array_to_row; +use function array_keys; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\lit; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_optional; final class OnEach implements ScalarFunction { @@ -25,6 +32,11 @@ final class OnEach implements ScalarFunction private readonly ScalarFunction $array; + /** + * @var null|array{Schema, ScalarFunction, Type} + */ + private ?array $bound = null; + /** * @param array|ScalarFunction $array */ @@ -59,12 +71,44 @@ public function withChildren(array $children): static return new self($children[0], $this->function, $this->preserveKeys, $this->elementSchema); } + /** + * The element schema, the body resolved against it and the result type - derived once per node, not per batch. + * + * @return array{Schema, ScalarFunction, Type} + */ + public function bound(): array + { + if ($this->bound === null) { + $arrayType = type_bare($this->array->returns()); + $schema = $this->elementSchema->of($arrayType); + + $this->bound = [ + $schema, + (new ReferenceResolver())->resolve($this->function, $schema), + type_optional($this->typeOver($arrayType)), + ]; + } + + return $this->bound; + } + /** * @return Type */ public function returns(): Type { - $arrayType = type_bare($this->array->returns()); + return $this->typeOver(type_bare($this->array->returns())); + } + + /** + * The produced type for an operand of $arrayType - one read of the operand's returns() serves eval() and bind. + * + * @param Type $arrayType + * + * @return Type + */ + public function typeOver(Type $arrayType): Type + { $inner = $this->elementSchema->of($arrayType); $body = (new ReferenceResolver())->resolve($this->function, $inner); @@ -91,34 +135,54 @@ public function returns(): Type return type_list($bodyType); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->array))->asArray($row, $context); + $arrays = (new Parameter($this->array))->asArrays($rows, $context); + $elements = []; - if ($value === null) { - throw new InvalidArgumentException('OnEach requires non-null array'); - } + /** @var list $rowOf the row of $rows every element comes from */ + $rowOf = []; - $output = []; + foreach ($arrays as $i => $array) { + if ($array === null) { + throw new EvaluationException($i, new InvalidArgumentException('OnEach requires non-null array')); + } - $backend = $context->backend(); - // hoisted: array_to_row() runs per element, and the schema is the same for every one of them - $elementSchema = $this->elementSchema->of(type_bare($this->array->returns())); + // @mago-ignore analysis:mixed-assignment + foreach ($array as $item) { + $elements[] = ['element' => $item]; + $rowOf[] = $i; + } + } + + [$elementSchema, $body, $type] = $this->bound(); - // @mago-ignore analysis:mixed-assignment - foreach ($value as $key => $item) { - $result = (new Parameter($this->function))->eval( - array_to_row(['element' => $item], $elementSchema, $backend), + try { + $results = (new Parameter($body))->values( + array_to_rows($elements, $elementSchema, new PhpBackend()), $context, ); + } catch (EvaluationException $e) { + throw EvaluationException::at($rowOf[$e->rowIndex], $e); + } - if ($this->preserveKeys) { - $output[$key] = $result; - } else { - $output[] = $result; + $output = []; + $position = 0; + + foreach ($arrays as $array) { + $values = []; + + foreach (array_keys($array) as $key) { + if ($this->preserveKeys) { + $values[$key] = $results[$position++]; + } else { + $values[] = $results[$position++]; + } } + + $output[] = $values; } - return $output; + return (new ResultColumn())->typed($type, $output); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Optional.php b/src/core/etl/src/Flow/ETL/Function/Optional.php index ca75b1d37e..c21b73e1fe 100644 --- a/src/core/etl/src/Flow/ETL/Function/Optional.php +++ b/src/core/etl/src/Flow/ETL/Function/Optional.php @@ -4,11 +4,14 @@ namespace Flow\ETL\Function; -use Exception; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Function\Evaluation\TolerantEvaluation; +use Flow\ETL\Rows; use Flow\Types\Type; +use function array_key_exists; use function Flow\Types\DSL\type_optional; final class Optional implements ScalarFunction @@ -44,12 +47,15 @@ public function returns(): Type return type_optional($this->function->returns()); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - try { - return (new Parameter($this->function))->eval($row, $context); - } catch (Exception) { - return null; + $evaluated = (new TolerantEvaluation())->evaluate($this->function, $rows, $context); + $results = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $results[] = array_key_exists($i, $evaluated['failed']) ? null : $evaluated['values'][$i]; } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Parameter.php b/src/core/etl/src/Flow/ETL/Function/Parameter.php index 3a7680f8c2..147aa1fdbf 100644 --- a/src/core/etl/src/Flow/ETL/Function/Parameter.php +++ b/src/core/etl/src/Flow/ETL/Function/Parameter.php @@ -4,29 +4,41 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; -use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; +use Flow\Types\Type\Native\BooleanType; +use Flow\Types\Type\Native\FloatType; +use Flow\Types\Type\Native\IntegerType; +use Flow\Types\Type\Native\StringType; use Flow\Types\Value\Json; use UnitEnum; +use function array_map; use function Flow\ETL\DSL\lit; use function Flow\Types\DSL\type_array; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_instance_of; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_object; use function Flow\Types\DSL\type_string; +use function get_debug_type; use function implode; +use function is_float; +use function is_int; +use function is_numeric; +use function is_scalar; use function sprintf; /** - * Every as*() arm separates the two axes: a genuine NULL flowing through is not an error and - * propagates (or takes the arm's null-input default), while a non-null value that cannot coerce - * throws - optional() is the door for pipelines that want the old silent tolerance. + * Every as*() reader separates the two axes: a genuine NULL flowing through is not an error and + * propagates (or takes the reader's null-input default), while a non-null value that cannot coerce + * throws, naming its row - optional() is the door for pipelines that want the old silent tolerance. */ final readonly class Parameter { @@ -38,82 +50,81 @@ public function __construct(mixed $function) } /** - * @template T - * - * @param Type ...$types - * - * @return null|T + * @return list> */ - public function as(Row $row, FlowContext $context, Type ...$types): mixed + public function asArrays(Rows $rows, FlowContext $context): array { - $value = $this->eval($row, $context); - - if ($value === null) { - return null; - } - - foreach ($types as $nextType) { - if ($nextType->isValid($value)) { - return $value; - } - } - - throw new InvalidArgumentException(sprintf( - 'Expected one of "%s", got "%s".', - implode('", "', array_map(static fn(Type $type): string => $type->toString(), $types)), - get_debug_type($value), - )); + return $this->arraysOf($this->column($rows, $context)); } /** - * @return null|array + * @return list> */ - public function asArray(Row $row, FlowContext $context): ?array + public function arraysOf(Column $column): array { - $result = $this->eval($row, $context); + $type = type_array(); + $arrays = []; - if ($result === null) { - return null; - } + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $i => $value) { + if ($value === null) { + $arrays[] = null; - if ($result instanceof Json) { - return $result->toArray(); - } + continue; + } - $type = type_array(); + if ($value instanceof Json) { + $arrays[] = $value->toArray(); + + continue; + } + + if (!$type->isValid($value)) { + throw new EvaluationException( + $i, + new InvalidArgumentException(InvalidTypeException::value($value, $type)->getMessage()), + ); + } - if (!$type->isValid($result)) { - throw new InvalidArgumentException(InvalidTypeException::value($result, $type)->getMessage()); + $arrays[] = $value; } - return $result; + return $arrays; } - public function asBoolean(Row $row, FlowContext $context): ?bool + /** + * @return list + */ + public function asBooleans(Rows $rows, FlowContext $context): array { - $result = $this->eval($row, $context); + $column = $this->column($rows, $context); - if ($result === null) { - return null; + if (type_bare($column->type()) instanceof BooleanType) { + /** @var list */ + return $column->physicals(); } - if (!is_scalar($result)) { - throw new InvalidArgumentException(sprintf('Expected type "boolean", got "%s".', get_debug_type($result))); - } + $booleans = []; - return (bool) $result; - } + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $i => $value) { + if ($value === null) { + $booleans[] = null; - /** - * @return null|array|bool|float|int|object|string - */ - public function asValue(Row $row): mixed - { - if ($this->function instanceof Reference) { - return $row->has($this->function) ? $row->get($this->function) : null; + continue; + } + + if (!is_scalar($value)) { + throw new EvaluationException( + $i, + new InvalidArgumentException(sprintf('Expected type "boolean", got "%s".', get_debug_type($value))), + ); + } + + $booleans[] = (bool) $value; } - return null; + return $booleans; } /** @@ -121,40 +132,28 @@ public function asValue(Row $row): mixed * * @param class-string $enumClass * - * @return null|T + * @return list */ - public function asEnum(Row $row, FlowContext $context, string $enumClass): ?UnitEnum + public function asEnums(Rows $rows, FlowContext $context, string $enumClass): array { - $result = $this->eval($row, $context); - - if ($result === null) { - return null; - } - - $type = type_instance_of($enumClass); - - if (!$type->isValid($result)) { - throw new InvalidArgumentException(InvalidTypeException::value($result, $type)->getMessage()); - } - - return $result; + /** @var list */ + return $this->checked($this->values($rows, $context), type_instance_of($enumClass)); } - public function asFloat(Row $row, FlowContext $context): ?float + /** + * @return list + */ + public function asFloats(Rows $rows, FlowContext $context): array { - $result = $this->eval($row, $context); - - if ($result === null) { - return null; - } - - $type = type_float(); + $column = $this->column($rows, $context); - if (!$type->isValid($result)) { - throw new InvalidArgumentException(InvalidTypeException::value($result, $type)->getMessage()); + if (type_bare($column->type()) instanceof FloatType) { + /** @var list */ + return $column->physicals(); } - return $result; + /** @var list */ + return $this->checked($column->values(), type_float()); } /** @@ -162,149 +161,216 @@ public function asFloat(Row $row, FlowContext $context): ?float * * @param class-string $class * - * @return null|T + * @return list */ - public function asInstanceOf(Row $row, FlowContext $context, string $class): ?object + public function asInstancesOf(Rows $rows, FlowContext $context, string $class): array { - $result = $this->eval($row, $context); - - if ($result === null) { - return null; - } - - $type = type_instance_of($class); - - if (!$type->isValid($result)) { - throw new InvalidArgumentException(InvalidTypeException::value($result, $type)->getMessage()); - } - - return $result; + /** @var list */ + return $this->checked($this->values($rows, $context), type_instance_of($class)); } /** * $default applies to a NULL input only - a malformed value always throws. * - * @return ($default is null ? int|null : int) + * @return ($default is null ? list : list) */ - public function asInt(Row $row, FlowContext $context, ?int $default = null): ?int + public function asInts(Rows $rows, FlowContext $context, ?int $default = null): array { - $result = $this->eval($row, $context); + $column = $this->column($rows, $context); - if ($result === null) { - return $default; - } - - $type = type_integer(); + /** @var list $ints */ + $ints = type_bare($column->type()) instanceof IntegerType + ? $column->physicals() + : $this->checked($column->values(), type_integer()); - if (!$type->isValid($result)) { - throw new InvalidArgumentException(InvalidTypeException::value($result, $type)->getMessage()); - } - - return $result; + return $default === null ? $ints : array_map(static fn(?int $int): int => $int ?? $default, $ints); } /** * @param class-string $class * - * @return null|array + * @return list> */ - public function asListOfObjects(Row $row, FlowContext $context, string $class): ?array + public function asListsOfObjects(Rows $rows, FlowContext $context, string $class): array { - $result = $this->asArray($row, $context); + $objectType = type_instance_of($class); + $lists = []; - if ($result === null) { - return null; - } + foreach ($this->asArrays($rows, $context) as $i => $array) { + if ($array === null) { + $lists[] = null; - $objectType = type_instance_of($class); - $objects = []; + continue; + } - // @mago-ignore analysis:mixed-assignment - foreach ($result as $item) { - if (!$objectType->isValid($item)) { - throw new InvalidArgumentException(InvalidTypeException::value($item, $objectType)->getMessage()); + $objects = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($array as $item) { + if (!$objectType->isValid($item)) { + throw new EvaluationException( + $i, + new InvalidArgumentException(InvalidTypeException::value($item, $objectType)->getMessage()), + ); + } + + $objects[] = $item; } - $objects[] = $item; + $lists[] = $objects; } - return $objects; + return $lists; } /** * $default applies to a NULL input only - a malformed value always throws. * - * @return ($default is null ? int|float|null : int|float) + * @return ($default is null ? list : list) */ - public function asNumber(Row $row, FlowContext $context, int|float|null $default = null): int|float|null + public function asNumbers(Rows $rows, FlowContext $context, int|float|null $default = null): array { - $result = $this->eval($row, $context); + $column = $this->column($rows, $context); + $type = type_bare($column->type()); - if ($result === null) { - return $default; - } + if ($type instanceof IntegerType || $type instanceof FloatType) { + /** @var list $numbers */ + $numbers = $column->physicals(); - if (!is_numeric($result)) { - throw new InvalidArgumentException(sprintf('Expected type "numeric", got "%s".', get_debug_type($result))); + return $default === null + ? $numbers + : array_map(static fn(int|float|null $number): int|float => $number ?? $default, $numbers); } - if (is_int($result) || is_float($result)) { - return $result; - } + $numbers = []; - // numeric-string: prefer int if the value is integral, otherwise float. - if ((string) (int) $result === $result) { - return (int) $result; - } + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $i => $value) { + if ($value === null) { + $numbers[] = $default; - return (float) $result; - } + continue; + } - public function asObject(Row $row, FlowContext $context): ?object - { - $result = $this->eval($row, $context); + if (is_int($value) || is_float($value)) { + $numbers[] = $value; - if ($result === null) { - return null; - } + continue; + } - $type = type_object(); + if (!is_numeric($value)) { + throw new EvaluationException( + $i, + new InvalidArgumentException(sprintf('Expected type "numeric", got "%s".', get_debug_type($value))), + ); + } - if (!$type->isValid($result)) { - throw new InvalidArgumentException(InvalidTypeException::value($result, $type)->getMessage()); + // numeric-string: prefer int if the value is integral, otherwise float. + $numbers[] = (string) (int) $value === $value ? (int) $value : (float) $value; } - return $result; + return $numbers; + } + + /** + * @return list + */ + public function asObjects(Rows $rows, FlowContext $context): array + { + /** @var list */ + return $this->checked($this->values($rows, $context), type_object()); } /** * $default applies to a NULL input only - a malformed value always throws. * - * @return ($default is null ? string|null : string) + * @return ($default is null ? list : list) */ - public function asString(Row $row, FlowContext $context, ?string $default = null): ?string + public function asStrings(Rows $rows, FlowContext $context, ?string $default = null): array { - $result = $this->eval($row, $context); + $column = $this->column($rows, $context); + + /** @var list $strings */ + $strings = type_bare($column->type()) instanceof StringType + ? $column->physicals() + : $this->checked($column->values(), type_string()); + + return $default === null + ? $strings + : array_map(static fn(?string $string): string => $string ?? $default, $strings); + } - if ($result === null) { - return $default; + /** + * @template T + * + * @param Type ...$types + * + * @return list + */ + public function asTypes(Rows $rows, FlowContext $context, Type ...$types): array + { + $accepted = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($this->values($rows, $context) as $i => $value) { + if ($value === null) { + $accepted[] = null; + + continue; + } + + foreach ($types as $nextType) { + if ($nextType->isValid($value)) { + $accepted[] = $value; + + continue 2; + } + } + + throw new EvaluationException( + $i, + new InvalidArgumentException(sprintf( + 'Expected one of "%s", got "%s".', + implode('", "', array_map(static fn(Type $type): string => $type->toString(), $types)), + get_debug_type($value), + )), + ); } - $type = type_string(); + return $accepted; + } - if (!$type->isValid($result)) { - throw new InvalidArgumentException(InvalidTypeException::value($result, $type)->getMessage()); + /** + * @param list $values + * @param Type $type + * + * @return list + */ + public function checked(array $values, Type $type): array + { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + if ($value !== null && !$type->isValid($value)) { + throw new EvaluationException( + $i, + new InvalidArgumentException(InvalidTypeException::value($value, $type)->getMessage()), + ); + } } - return $result; + return $values; + } + + public function column(Rows $rows, FlowContext $context): Column + { + return $this->function->eval($rows, $context); } /** - * @return null|array|bool|float|int|object|string + * @return list */ - public function eval(Row $row, FlowContext $context): mixed + public function values(Rows $rows, FlowContext $context): array { - // @mago-ignore analysis:mixed-return-statement - return $this->function->eval($row, $context); + return $this->column($rows, $context)->values(); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Plus.php b/src/core/etl/src/Flow/ETL/Function/Plus.php index ce87007dbe..c8df629dc5 100644 --- a/src/core/etl/src/Flow/ETL/Function/Plus.php +++ b/src/core/etl/src/Flow/ETL/Function/Plus.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Function; -use Flow\Calculator\Calculator; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Native\FloatType; @@ -17,6 +20,8 @@ use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_integer; +use function is_float; +use function is_int; final class Plus implements ScalarFunction { @@ -25,8 +30,11 @@ final class Plus implements ScalarFunction private readonly ScalarFunction $left; private readonly ScalarFunction $right; - public function __construct(ScalarFunction|int|float $left, ScalarFunction|int|float $right) - { + public function __construct( + ScalarFunction|int|float $left, + ScalarFunction|int|float $right, + private readonly bool $exact = false, + ) { $this->left = $left instanceof ScalarFunction ? $left : lit($left); $this->right = $right instanceof ScalarFunction ? $right : lit($right); } @@ -45,7 +53,7 @@ public function children(): array public function withChildren(array $children): static { /** @var list $children */ - return new self($children[0], $children[1]); + return new self($children[0], $children[1], $this->exact); } /** @@ -66,15 +74,39 @@ public function returns(): Type return $left instanceof IntegerType && $right instanceof IntegerType ? type_integer() : type_float(); } - public function eval(Row $row, FlowContext $context): int|float|null + public function eval(Rows $rows, FlowContext $context): Column { - $leftValue = (new Parameter($this->left))->asNumber($row, $context); - $rightValue = (new Parameter($this->right))->asNumber($row, $context); + $lefts = (new Parameter($this->left))->asNumbers($rows, $context); + $rights = (new Parameter($this->right))->asNumbers($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($lefts as $i => $left) { + $right = $rights[$i]; + + if ($left === null || $right === null) { + throw new InvalidArgumentException('Plus function requires non-null values'); + } + + if ($this->exact) { + $results[] = $context->calculator()->add($left, $right); + + continue; + } + + $result = $left + $right; + + if (is_int($left) && is_int($right) && is_float($result)) { + throw new InvalidArgumentException('Plus function integer overflow'); + } - if ($leftValue === null || $rightValue === null) { - throw new InvalidArgumentException('Plus function requires non-null values'); + $results[] = $result; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return (new Calculator())->add($leftValue, $rightValue); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Power.php b/src/core/etl/src/Flow/ETL/Function/Power.php index 37dc3eb450..4402a1094a 100644 --- a/src/core/etl/src/Flow/ETL/Function/Power.php +++ b/src/core/etl/src/Flow/ETL/Function/Power.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Function; -use Flow\Calculator\Calculator; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Native\FloatType; @@ -17,6 +20,8 @@ use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_integer; +use function is_float; +use function is_int; final class Power implements ScalarFunction { @@ -25,8 +30,11 @@ final class Power implements ScalarFunction private readonly ScalarFunction $left; private readonly ScalarFunction $right; - public function __construct(ScalarFunction|int|float $left, ScalarFunction|int $right) - { + public function __construct( + ScalarFunction|int|float $left, + ScalarFunction|int $right, + private readonly bool $exact = false, + ) { $this->left = $left instanceof ScalarFunction ? $left : lit($left); $this->right = $right instanceof ScalarFunction ? $right : lit($right); } @@ -45,7 +53,7 @@ public function children(): array public function withChildren(array $children): static { /** @var list $children */ - return new self($children[0], $children[1]); + return new self($children[0], $children[1], $this->exact); } /** @@ -66,15 +74,43 @@ public function returns(): Type return $left instanceof IntegerType && $right instanceof IntegerType ? type_integer() : type_float(); } - public function eval(Row $row, FlowContext $context): float|int|null + public function eval(Rows $rows, FlowContext $context): Column { - $leftValue = (new Parameter($this->left))->asNumber($row, $context); - $rightValue = (new Parameter($this->right))->asInt($row, $context); + $lefts = (new Parameter($this->left))->asNumbers($rows, $context); + $rights = (new Parameter($this->right))->asInts($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($lefts as $i => $left) { + $right = $rights[$i]; + + if ($left === null || $right === null) { + throw new InvalidArgumentException('Power function requires non-null values'); + } + + if ($this->exact) { + $results[] = $context->calculator()->power($left, $right); + + continue; + } + + if (is_int($left) && $right < 0) { + throw new InvalidArgumentException('Power function of an integer requires a non-negative exponent'); + } + + $result = $left ** $right; + + if (is_int($left) && is_float($result)) { + throw new InvalidArgumentException('Power function integer overflow'); + } - if ($leftValue === null || $rightValue === null) { - throw new InvalidArgumentException('Power function requires non-null values'); + $results[] = $result; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return (new Calculator())->power($leftValue, $rightValue); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Prepend.php b/src/core/etl/src/Flow/ETL/Function/Prepend.php index 70e73e72b9..fc0af794f5 100644 --- a/src/core/etl/src/Flow/ETL/Function/Prepend.php +++ b/src/core/etl/src/Flow/ETL/Function/Prepend.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -51,19 +55,33 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $prefix = (new Parameter($this->prefix))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $prefixes = (new Parameter($this->prefix))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('Prepend function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $prefix = $prefixes[$i]; + + if ($value === null) { + throw new InvalidArgumentException('Prepend function requires non-null value'); + } + + if ($prefix === null) { + $results[] = $value; + + continue; + } - if ($prefix === null) { - return $value; + $results[] = s($value)->prepend($prefix)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->prepend($prefix)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RandomString.php b/src/core/etl/src/Flow/ETL/Function/RandomString.php index 5bc0953d62..e9b7240978 100644 --- a/src/core/etl/src/Flow/ETL/Function/RandomString.php +++ b/src/core/etl/src/Flow/ETL/Function/RandomString.php @@ -4,11 +4,15 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\RandomValueGenerator; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -57,14 +61,24 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $length = (new Parameter($this->length))->asInt($row, $context); + $lengths = (new Parameter($this->length))->asInts($rows, $context); + $results = []; + $i = 0; - if ($length === null) { - throw new InvalidArgumentException('RandomString requires non-null length'); + try { + foreach ($lengths as $i => $length) { + if ($length === null) { + throw new InvalidArgumentException('RandomString requires non-null length'); + } + + $results[] = $this->generator->string($length); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $this->generator->string($length); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Rank.php b/src/core/etl/src/Flow/ETL/Function/Rank.php index 9a38afd7e3..e771241b24 100644 --- a/src/core/etl/src/Flow/ETL/Function/Rank.php +++ b/src/core/etl/src/Flow/ETL/Function/Rank.php @@ -55,20 +55,15 @@ public function rankPartition(Rows $partition): array throw new BaseRuntimeException('Rank window function requires to be ordered by one column'); } - $comparator = new PeerComparator($orderBy); $ranks = []; $rank = 1; - $index = 0; - $previous = null; - foreach ($partition as $row) { - if ($previous !== null && !$comparator->arePeers($previous, $row, $partition->schema())) { + foreach ((new PeerComparator($orderBy))->peersOfPrevious($partition) as $index => $peer) { + if ($index > 0 && !$peer) { $rank = $index + 1; } $ranks[] = $rank; - $previous = $row; - $index++; } return $ranks; diff --git a/src/core/etl/src/Flow/ETL/Function/Regex.php b/src/core/etl/src/Flow/ETL/Function/Regex.php index f606bf7cad..be25b38470 100644 --- a/src/core/etl/src/Flow/ETL/Function/Regex.php +++ b/src/core/etl/src/Flow/ETL/Function/Regex.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -69,34 +73,46 @@ public function returns(): Type return type_optional(type_array()); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - $pattern = (new Parameter($this->pattern))->asString($row, $context); - $subject = (new Parameter($this->subject))->asString($row, $context); - $offset = (new Parameter($this->offset))->asInt($row, $context); - - if ($pattern === null) { - throw new InvalidArgumentException('Regex requires non-null pattern'); - } - - if ($subject === null) { - throw new InvalidArgumentException('Regex requires non-null subject'); - } - - if ($offset === null) { - throw new InvalidArgumentException('Regex requires non-null offset'); - } - - $matches = []; - - // preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or false on failure. - if (preg_match($pattern, $subject, $matches, $this->flags, $offset) === 1) { - return $matches; + $patterns = (new Parameter($this->pattern))->asStrings($rows, $context); + $subjects = (new Parameter($this->subject))->asStrings($rows, $context); + $offsets = (new Parameter($this->offset))->asInts($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($patterns as $i => $pattern) { + $subject = $subjects[$i]; + $offset = $offsets[$i]; + + if ($pattern === null) { + throw new InvalidArgumentException('Regex requires non-null pattern'); + } + + if ($subject === null) { + throw new InvalidArgumentException('Regex requires non-null subject'); + } + + if ($offset === null) { + throw new InvalidArgumentException('Regex requires non-null offset'); + } + + $matches = []; + + // preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or false on failure. + if (preg_match($pattern, $subject, $matches, $this->flags, $offset) === 1) { + $results[] = $matches; + + continue; + } + + $results[] = null; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return null; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RegexAll.php b/src/core/etl/src/Flow/ETL/Function/RegexAll.php index 7a217f1d1f..61778991a5 100644 --- a/src/core/etl/src/Flow/ETL/Function/RegexAll.php +++ b/src/core/etl/src/Flow/ETL/Function/RegexAll.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -73,38 +77,52 @@ public function returns(): Type return type_optional(type_array()); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - $pattern = (new Parameter($this->pattern))->asString($row, $context); - $subject = (new Parameter($this->subject))->asString($row, $context); - $offset = (new Parameter($this->offset))->asInt($row, $context); + $patterns = (new Parameter($this->pattern))->asStrings($rows, $context); + $subjects = (new Parameter($this->subject))->asStrings($rows, $context); + $offsets = (new Parameter($this->offset))->asInts($rows, $context); + $results = []; + $i = 0; - if ($pattern === null) { - throw new InvalidArgumentException('RegexAll requires non-null pattern'); - } + try { + foreach ($patterns as $i => $pattern) { + $subject = $subjects[$i]; + $offset = $offsets[$i]; - if ($subject === null) { - throw new InvalidArgumentException('RegexAll requires non-null subject'); - } + if ($pattern === null) { + throw new InvalidArgumentException('RegexAll requires non-null pattern'); + } - if ($offset === null) { - throw new InvalidArgumentException('RegexAll requires non-null offset'); - } + if ($subject === null) { + throw new InvalidArgumentException('RegexAll requires non-null subject'); + } - $matches = []; + if ($offset === null) { + throw new InvalidArgumentException('RegexAll requires non-null offset'); + } - // Returns the number of full pattern matches (which might be zero), or false on failure. - if (preg_match_all($pattern, $subject, $matches, $this->flags, $offset) !== false) { - if ($matches === [[]]) { - return null; - } + $matches = []; - return $matches; + // Returns the number of full pattern matches (which might be zero), or false on failure. + if (preg_match_all($pattern, $subject, $matches, $this->flags, $offset) !== false) { + if ($matches === [[]]) { + $results[] = null; + + continue; + } + + $results[] = $matches; + + continue; + } + + $results[] = null; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return null; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RegexMatch.php b/src/core/etl/src/Flow/ETL/Function/RegexMatch.php index 1e2c6d20ff..9b1c55dcfe 100644 --- a/src/core/etl/src/Flow/ETL/Function/RegexMatch.php +++ b/src/core/etl/src/Flow/ETL/Function/RegexMatch.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -68,17 +72,33 @@ public function returns(): Type ); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $pattern = (new Parameter($this->pattern))->asString($row, $context); - $subject = (new Parameter($this->subject))->asString($row, $context); - $flags = (new Parameter($this->flags))->asInt($row, $context); - $offset = (new Parameter($this->offset))->asInt($row, $context); + $patterns = (new Parameter($this->pattern))->asStrings($rows, $context); + $subjects = (new Parameter($this->subject))->asStrings($rows, $context); + $flagsList = (new Parameter($this->flags))->asInts($rows, $context); + $offsets = (new Parameter($this->offset))->asInts($rows, $context); + $results = []; + $i = 0; - if ($pattern === null || $subject === null || $flags === null || $offset === null) { - return null; + try { + foreach ($patterns as $i => $pattern) { + $subject = $subjects[$i]; + $flags = $flagsList[$i]; + $offset = $offsets[$i]; + + if ($pattern === null || $subject === null || $flags === null || $offset === null) { + $results[] = null; + + continue; + } + + $results[] = preg_match(pattern: $pattern, subject: $subject, flags: $flags, offset: $offset) === 1; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return preg_match(pattern: $pattern, subject: $subject, flags: $flags, offset: $offset) === 1; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RegexMatchAll.php b/src/core/etl/src/Flow/ETL/Function/RegexMatchAll.php index 56fee74850..3493a3cf16 100644 --- a/src/core/etl/src/Flow/ETL/Function/RegexMatchAll.php +++ b/src/core/etl/src/Flow/ETL/Function/RegexMatchAll.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -68,17 +72,34 @@ public function returns(): Type ); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $pattern = (new Parameter($this->pattern))->asString($row, $context); - $subject = (new Parameter($this->subject))->asString($row, $context); - $flags = (new Parameter($this->flags))->asInt($row, $context); - $offset = (new Parameter($this->offset))->asInt($row, $context); + $patterns = (new Parameter($this->pattern))->asStrings($rows, $context); + $subjects = (new Parameter($this->subject))->asStrings($rows, $context); + $flagsList = (new Parameter($this->flags))->asInts($rows, $context); + $offsets = (new Parameter($this->offset))->asInts($rows, $context); + $results = []; + $i = 0; - if ($pattern === null || $subject === null || $flags === null || $offset === null) { - return null; + try { + foreach ($patterns as $i => $pattern) { + $subject = $subjects[$i]; + $flags = $flagsList[$i]; + $offset = $offsets[$i]; + + if ($pattern === null || $subject === null || $flags === null || $offset === null) { + $results[] = null; + + continue; + } + + $results[] = + preg_match_all(pattern: $pattern, subject: $subject, flags: $flags, offset: $offset) !== false; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return preg_match_all(pattern: $pattern, subject: $subject, flags: $flags, offset: $offset) !== false; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RegexReplace.php b/src/core/etl/src/Flow/ETL/Function/RegexReplace.php index 299ab0200c..6e5f1ea087 100644 --- a/src/core/etl/src/Flow/ETL/Function/RegexReplace.php +++ b/src/core/etl/src/Flow/ETL/Function/RegexReplace.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function count; @@ -72,29 +76,45 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $pattern = (new Parameter($this->pattern))->asString($row, $context); - $replacement = (new Parameter($this->replacement))->asString($row, $context); - $subject = (new Parameter($this->subject))->asString($row, $context); - $limit = $this->limit !== null ? (new Parameter($this->limit))->asInt($row, $context) : -1; - - if ($pattern === null) { - throw new InvalidArgumentException('RegexReplace requires non-null pattern'); - } - - if ($replacement === null) { - throw new InvalidArgumentException('RegexReplace requires non-null replacement'); - } - - if ($subject === null) { - throw new InvalidArgumentException('RegexReplace requires non-null subject'); - } - - if ($limit === null) { - throw new InvalidArgumentException('RegexReplace requires non-null limit'); + $patterns = (new Parameter($this->pattern))->asStrings($rows, $context); + $replacements = (new Parameter($this->replacement))->asStrings($rows, $context); + $subjects = (new Parameter($this->subject))->asStrings($rows, $context); + $limits = (new Parameter($this->limit))->asInts($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($patterns as $i => $pattern) { + $replacement = $replacements[$i]; + $subject = $subjects[$i]; + $limit = $limits[$i]; + + $limit = $this->limit !== null ? $limit : -1; + + if ($pattern === null) { + throw new InvalidArgumentException('RegexReplace requires non-null pattern'); + } + + if ($replacement === null) { + throw new InvalidArgumentException('RegexReplace requires non-null replacement'); + } + + if ($subject === null) { + throw new InvalidArgumentException('RegexReplace requires non-null subject'); + } + + if ($limit === null) { + throw new InvalidArgumentException('RegexReplace requires non-null limit'); + } + + $results[] = preg_replace($pattern, $replacement, $subject, $limit); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return preg_replace($pattern, $replacement, $subject, $limit); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Repeat.php b/src/core/etl/src/Flow/ETL/Function/Repeat.php index 5a551d57a3..296a378c55 100644 --- a/src/core/etl/src/Flow/ETL/Function/Repeat.php +++ b/src/core/etl/src/Flow/ETL/Function/Repeat.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -51,19 +55,31 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $times = (new Parameter($this->times))->asInt($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $timesList = (new Parameter($this->times))->asInts($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('Repeat function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $times = $timesList[$i]; + + if ($value === null) { + throw new InvalidArgumentException('Repeat function requires non-null value'); + } + + if ($times === null || $times <= 0) { + throw new InvalidArgumentException('Repeat function requires non-null, positive times'); + } - if ($times === null || $times <= 0) { - throw new InvalidArgumentException('Repeat function requires non-null, positive times'); + $results[] = s($value)->repeat($times)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->repeat($times)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Reverse.php b/src/core/etl/src/Flow/ETL/Function/Reverse.php index 8f51678087..87c2348ca7 100644 --- a/src/core/etl/src/Flow/ETL/Function/Reverse.php +++ b/src/core/etl/src/Flow/ETL/Function/Reverse.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('Reverse function requires non-null value'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('Reverse function requires non-null value'); + } + + $results[] = s($value)->reverse()->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->reverse()->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Round.php b/src/core/etl/src/Flow/ETL/Function/Round.php index 9c3ec2dddb..76567d9d19 100644 --- a/src/core/etl/src/Flow/ETL/Function/Round.php +++ b/src/core/etl/src/Flow/ETL/Function/Round.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -56,20 +60,33 @@ public function returns(): Type return type_float(); } - public function eval(Row $row, FlowContext $context): float + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asNumber($row, $context); - $precision = (new Parameter($this->precision))->asInt($row, $context); - $mode = (new Parameter($this->mode))->asInt($row, $context); + $values = (new Parameter($this->value))->asNumbers($rows, $context); + $precisions = (new Parameter($this->precision))->asInts($rows, $context); + $modes = (new Parameter($this->mode))->asInts($rows, $context); + $results = []; + $i = 0; - if ($value === null || $precision === null || $mode === null) { - throw new InvalidArgumentException('Round function requires non-null values'); - } + try { + foreach ($values as $i => $value) { + $precision = $precisions[$i]; + $mode = $modes[$i]; + + if ($value === null || $precision === null || $mode === null) { + throw new InvalidArgumentException('Round function requires non-null values'); + } + + if ($mode < 1 || $mode > 4) { + $mode = 1; + } - if ($mode < 1 || $mode > 4) { - $mode = 1; + $results[] = round($value, $precision, $mode); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return round($value, $precision, $mode); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Same.php b/src/core/etl/src/Flow/ETL/Function/Same.php index 618bdfbd94..4148017d8d 100644 --- a/src/core/etl/src/Flow/ETL/Function/Same.php +++ b/src/core/etl/src/Flow/ETL/Function/Same.php @@ -4,12 +4,18 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\ComparableValues; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\ValueComparator; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; final class Same implements ScalarFunction @@ -52,11 +58,30 @@ public function returns(): Type return type_boolean(); } - public function eval(Row $row, FlowContext $context): bool + public function eval(Rows $rows, FlowContext $context): Column { - // PHP identity, not SQL equality: null === null is a defined, useful answer - return ( - (new Parameter($this->left))->eval($row, $context) === (new Parameter($this->right))->eval($row, $context) - ); + $leftColumn = (new Parameter($this->left))->column($rows, $context); + $rightColumn = (new Parameter($this->right))->column($rows, $context); + $comparable = new ComparableValues(); + [$lefts, $rights] = type_bare($leftColumn->type())::class === type_bare($rightColumn->type())::class + ? [$comparable->equality($leftColumn), $comparable->equality($rightColumn)] + : [$leftColumn->values(), $rightColumn->values()]; + $results = []; + $i = 0; + + try { + // @mago-ignore analysis:mixed-assignment + foreach ($lefts as $i => $left) { + // @mago-ignore analysis:mixed-assignment + $right = $rights[$i]; + + // PHP identity, not SQL equality: null === null is a defined, useful answer + $results[] = $left === $right; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Sanitize.php b/src/core/etl/src/Flow/ETL/Function/Sanitize.php index bb1aea0d2e..bb51f2de8e 100644 --- a/src/core/etl/src/Flow/ETL/Function/Sanitize.php +++ b/src/core/etl/src/Flow/ETL/Function/Sanitize.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -58,26 +62,42 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $val = (new Parameter($this->value))->asString($row, $context); - $placeholder = (new Parameter($this->placeholder))->asString($row, $context); - $skipCharacters = (new Parameter($this->skipCharacters))->asInt($row, $context); - - if ($val === null) { - throw new InvalidArgumentException('Sanitize function requires non-null value'); - } - - if ($placeholder === null) { - throw new InvalidArgumentException('Sanitize function requires non-null placeholder'); - } - - $size = mb_strlen($val); - - if ($skipCharacters !== null && $size > $skipCharacters) { - return mb_substr($val, 0, $skipCharacters) . str_repeat($placeholder, max(0, $size - $skipCharacters)); + $vals = (new Parameter($this->value))->asStrings($rows, $context); + $placeholders = (new Parameter($this->placeholder))->asStrings($rows, $context); + $skipCharactersList = (new Parameter($this->skipCharacters))->asInts($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($vals as $i => $val) { + $placeholder = $placeholders[$i]; + $skipCharacters = $skipCharactersList[$i]; + + if ($val === null) { + throw new InvalidArgumentException('Sanitize function requires non-null value'); + } + + if ($placeholder === null) { + throw new InvalidArgumentException('Sanitize function requires non-null placeholder'); + } + + $size = mb_strlen($val); + + if ($skipCharacters !== null && $size > $skipCharacters) { + $results[] = + mb_substr($val, 0, $skipCharacters) . str_repeat($placeholder, max(0, $size - $skipCharacters)); + + continue; + } + + $results[] = str_repeat($placeholder, $size); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return str_repeat($placeholder, $size); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ScalarFunction.php b/src/core/etl/src/Flow/ETL/Function/ScalarFunction.php index a0f1016369..b5be81bcb7 100644 --- a/src/core/etl/src/Flow/ETL/Function/ScalarFunction.php +++ b/src/core/etl/src/Flow/ETL/Function/ScalarFunction.php @@ -4,13 +4,17 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; interface ScalarFunction extends FunctionTree { - public function eval(Row $row, FlowContext $context): mixed; + /** + * One column of $rows->count() values, of returns()'s type (nullable), same row order. + */ + public function eval(Rows $rows, FlowContext $context): Column; /** * The type of the column this function produces, before any row is read. diff --git a/src/core/etl/src/Flow/ETL/Function/ScalarFunction/ExpandResults.php b/src/core/etl/src/Flow/ETL/Function/ScalarFunction/ExpandResults.php index ad08446328..e1496438f8 100644 --- a/src/core/etl/src/Flow/ETL/Function/ScalarFunction/ExpandResults.php +++ b/src/core/etl/src/Flow/ETL/Function/ScalarFunction/ExpandResults.php @@ -4,14 +4,9 @@ namespace Flow\ETL\Function\ScalarFunction; -use Flow\ETL\FlowContext; use Flow\ETL\Function\ScalarFunction; -use Flow\ETL\Row; -interface ExpandResults extends ScalarFunction -{ - /** - * @return array - */ - public function eval(Row $row, FlowContext $context): array; -} +/** + * eval returns a `list` column; the step explodes it. + */ +interface ExpandResults extends ScalarFunction {} diff --git a/src/core/etl/src/Flow/ETL/Function/ScalarFunction/UnpackResults.php b/src/core/etl/src/Flow/ETL/Function/ScalarFunction/UnpackResults.php index 87544ddbdf..0c2b81f658 100644 --- a/src/core/etl/src/Flow/ETL/Function/ScalarFunction/UnpackResults.php +++ b/src/core/etl/src/Flow/ETL/Function/ScalarFunction/UnpackResults.php @@ -4,14 +4,9 @@ namespace Flow\ETL\Function\ScalarFunction; -use Flow\ETL\FlowContext; use Flow\ETL\Function\ScalarFunction; -use Flow\ETL\Row; -interface UnpackResults extends ScalarFunction -{ - /** - * @return array - */ - public function eval(Row $row, FlowContext $context): array; -} +/** + * eval returns the `StructureType` column `returns()` declares. + */ +interface UnpackResults extends ScalarFunction {} diff --git a/src/core/etl/src/Flow/ETL/Function/ScalarFunctionChain.php b/src/core/etl/src/Flow/ETL/Function/ScalarFunctionChain.php index 2978207475..03c0d25f2e 100644 --- a/src/core/etl/src/Flow/ETL/Function/ScalarFunctionChain.php +++ b/src/core/etl/src/Flow/ETL/Function/ScalarFunctionChain.php @@ -497,9 +497,9 @@ public function lower(): ToLower return new ToLower($this); } - public function minus(ScalarFunction|int|float $ref): Minus + public function minus(ScalarFunction|int|float $ref, bool $exact = false): Minus { - return new Minus($this, $ref); + return new Minus($this, $ref, $exact); } public function mod(ScalarFunction|int $value): Mod @@ -512,9 +512,9 @@ public function modifyDateTime(string|ScalarFunction $modifier): ModifyDateTime return new ModifyDateTime($this, $modifier); } - public function multiply(ScalarFunction|int|float $value): Multiply + public function multiply(ScalarFunction|int|float $value, bool $exact = false): Multiply { - return new Multiply($this, $value); + return new Multiply($this, $value, $exact); } public function notEquals(mixed $value): NotEquals @@ -556,14 +556,14 @@ public function orNot(ScalarFunction $function): Any return new Any($this, new Not($function)); } - public function plus(ScalarFunction|int|float $ref): Plus + public function plus(ScalarFunction|int|float $ref, bool $exact = false): Plus { - return new Plus($this, $ref); + return new Plus($this, $ref, $exact); } - public function power(ScalarFunction|int $value): Power + public function power(ScalarFunction|int $value, bool $exact = false): Power { - return new Power($this, $value); + return new Power($this, $value, $exact); } public function prepend(ScalarFunction|string $prefix): Prepend diff --git a/src/core/etl/src/Flow/ETL/Function/Size.php b/src/core/etl/src/Flow/ETL/Function/Size.php index a6d796b80e..e6cdeb3bce 100644 --- a/src/core/etl/src/Flow/ETL/Function/Size.php +++ b/src/core/etl/src/Flow/ETL/Function/Size.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function count; @@ -52,18 +56,33 @@ public function returns(): Type return type_optional(type_integer()); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); + $values = (new Parameter($this->value))->values($rows, $context); + $results = []; + $i = 0; - if (is_string($value)) { - return s($value)->length(); - } + try { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + if (is_string($value)) { + $results[] = s($value)->length(); + + continue; + } + + if (is_countable($value)) { + $results[] = count($value); + + continue; + } - if (is_countable($value)) { - return count($value); + $results[] = null; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return null; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Slug.php b/src/core/etl/src/Flow/ETL/Function/Slug.php index 88faaaf4ee..e4fca095f7 100644 --- a/src/core/etl/src/Flow/ETL/Function/Slug.php +++ b/src/core/etl/src/Flow/ETL/Function/Slug.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Symfony\Component\String\Slugger\AsciiSlugger; @@ -62,19 +66,33 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); - $separator = (new Parameter($this->separator))->asString($row, $context, '-'); - $locale = (new Parameter($this->locale))->asString($row, $context); - $symbolsMap = (new Parameter($this->symbolsMap))->asArray($row, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $separators = (new Parameter($this->separator))->asStrings($rows, $context, '-'); + $locales = (new Parameter($this->locale))->asStrings($rows, $context); + $symbolsMaps = (new Parameter($this->symbolsMap))->asArrays($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('Slug function requires non-null value'); + try { + foreach ($strings as $i => $string) { + $separator = $separators[$i]; + $locale = $locales[$i]; + $symbolsMap = $symbolsMaps[$i]; + + if ($string === null) { + throw new InvalidArgumentException('Slug function requires non-null value'); + } + + $results[] = (new AsciiSlugger(symbolsMap: $symbolsMap)) + ->slug($string, $separator, $locale) + ->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return (new AsciiSlugger(symbolsMap: $symbolsMap)) - ->slug($string, $separator, $locale) - ->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Split.php b/src/core/etl/src/Flow/ETL/Function/Split.php index 1ad0e1aa8f..44ca94d995 100644 --- a/src/core/etl/src/Flow/ETL/Function/Split.php +++ b/src/core/etl/src/Flow/ETL/Function/Split.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Symfony\Component\String\AbstractString; @@ -59,26 +63,38 @@ public function returns(): Type return type_list(type_string()); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $separator = (new Parameter($this->separator))->asString($row, $context); - $limit = (new Parameter($this->limit))->asInt($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $separators = (new Parameter($this->separator))->asStrings($rows, $context); + $limits = (new Parameter($this->limit))->asInts($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('Split function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $separator = $separators[$i]; + $limit = $limits[$i]; + + if ($value === null) { + throw new InvalidArgumentException('Split function requires non-null value'); + } + + if ($separator === null || $limit === null || $separator === '') { + throw new InvalidArgumentException( + 'Split function requires non-null separator and limit, separator cannot be empty', + ); + } - if ($separator === null || $limit === null || $separator === '') { - throw new InvalidArgumentException( - 'Split function requires non-null separator and limit, separator cannot be empty', - ); + $results[] = array_map( + static fn(AbstractString $s): string => $s->toString(), + s($value)->split($separator, $limit), + ); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - // @mago-ignore analysis:less-specific-return-statement - return array_map(static fn(AbstractString $s): string => $s->toString(), s($value)->split($separator, $limit)); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Sprintf.php b/src/core/etl/src/Flow/ETL/Function/Sprintf.php index d404648804..ffbb29091f 100644 --- a/src/core/etl/src/Flow/ETL/Function/Sprintf.php +++ b/src/core/etl/src/Flow/ETL/Function/Sprintf.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function array_map; @@ -64,25 +68,36 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $format = (new Parameter($this->format))->asString($row, $context); - - /** - * @var array $values - */ - $values = array_map(static fn(ScalarFunction $value): mixed => (new Parameter($value))->eval( - $row, + $formats = (new Parameter($this->format))->asStrings($rows, $context); + $arguments = array_map(static fn(ScalarFunction $value): array => (new Parameter($value))->values( + $rows, $context, ), $this->values); - - if ($format === null || in_array(null, $values, true)) { - throw new InvalidArgumentException('Sprintf requires non-null format and values'); + $results = []; + $i = 0; + + try { + foreach ($formats as $i => $format) { + /** + * @var array $values + */ + $values = array_map(static fn(array $argument): mixed => $argument[$i], $arguments); + + if ($format === null || in_array(null, $values, true)) { + throw new InvalidArgumentException('Sprintf requires non-null format and values'); + } + + /** @var array $nonNullValues */ + $nonNullValues = $values; + + $results[] = sprintf($format, ...$nonNullValues); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - /** @var array $nonNullValues */ - $nonNullValues = $values; - - return sprintf($format, ...$nonNullValues); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StartsWith.php b/src/core/etl/src/Flow/ETL/Function/StartsWith.php index cc22032bec..341b9e6a33 100644 --- a/src/core/etl/src/Flow/ETL/Function/StartsWith.php +++ b/src/core/etl/src/Flow/ETL/Function/StartsWith.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -51,15 +55,29 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->haystack->returns(), $this->needle->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $haystack = (new Parameter($this->haystack))->asString($row, $context); - $needle = (new Parameter($this->needle))->asString($row, $context); + $haystacks = (new Parameter($this->haystack))->asStrings($rows, $context); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($haystack === null || $needle === null) { - return null; + try { + foreach ($haystacks as $i => $haystack) { + $needle = $needles[$i]; + + if ($haystack === null || $needle === null) { + $results[] = null; + + continue; + } + + $results[] = str_starts_with($haystack, $needle); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return str_starts_with($haystack, $needle); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StrPad.php b/src/core/etl/src/Flow/ETL/Function/StrPad.php index 4ad985609c..2574b89886 100644 --- a/src/core/etl/src/Flow/ETL/Function/StrPad.php +++ b/src/core/etl/src/Flow/ETL/Function/StrPad.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -59,21 +63,35 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $length = (new Parameter($this->length))->asInt($row, $context); - $padString = (new Parameter($this->padString))->asString($row, $context); - $type = (new Parameter($this->type))->asInt($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $lengths = (new Parameter($this->length))->asInts($rows, $context); + $padStrings = (new Parameter($this->padString))->asStrings($rows, $context); + $types = (new Parameter($this->type))->asInts($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('StrPad function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $length = $lengths[$i]; + $padString = $padStrings[$i]; + $type = $types[$i]; + + if ($value === null) { + throw new InvalidArgumentException('StrPad function requires non-null value'); + } + + if ($length === null || $padString === null || $type === null) { + throw new InvalidArgumentException('StrPad function requires non-null length, padString and type'); + } - if ($length === null || $padString === null || $type === null) { - throw new InvalidArgumentException('StrPad function requires non-null length, padString and type'); + $results[] = str_pad($value, $length, $padString, $type); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return str_pad($value, $length, $padString, $type); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StrReplace.php b/src/core/etl/src/Flow/ETL/Function/StrReplace.php index fd4e01e825..393b53904a 100644 --- a/src/core/etl/src/Flow/ETL/Function/StrReplace.php +++ b/src/core/etl/src/Flow/ETL/Function/StrReplace.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -63,23 +67,36 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $search = (new Parameter($this->search))->as($row, $context, type_string(), type_array()); - $replace = (new Parameter($this->replace))->as($row, $context, type_string(), type_array()); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $searches = (new Parameter($this->search))->asTypes($rows, $context, type_string(), type_array()); + $replaces = (new Parameter($this->replace))->asTypes($rows, $context, type_string(), type_array()); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('StrReplace function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $search = $searches[$i]; + $replace = $replaces[$i]; - if ($search === null || $replace === null) { - throw new InvalidArgumentException('StrReplace function requires non-null search and replace'); - } + if ($value === null) { + throw new InvalidArgumentException('StrReplace function requires non-null value'); + } + + if ($search === null || $replace === null) { + throw new InvalidArgumentException('StrReplace function requires non-null search and replace'); + } - $typedSearch = type_union(type_string(), type_list(type_string()))->assert($search); - $typedReplace = type_union(type_string(), type_list(type_string()))->assert($replace); + $typedSearch = type_union(type_string(), type_list(type_string()))->assert($search); + $typedReplace = type_union(type_string(), type_list(type_string()))->assert($replace); + + $results[] = str_replace($typedSearch, $typedReplace, $value); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } - return str_replace($typedSearch, $typedReplace, $value); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringAfter.php b/src/core/etl/src/Flow/ETL/Function/StringAfter.php index 8421cb5027..e64da55b37 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringAfter.php +++ b/src/core/etl/src/Flow/ETL/Function/StringAfter.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -58,21 +62,27 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $includeNeedles = (new Parameter($this->includeNeedle))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('StringAfter function requires non-null value'); - } + try { + foreach ($strings as $i => $string) { + if ($string === null) { + throw new InvalidArgumentException('StringAfter function requires non-null value'); + } - $needle = (new Parameter($this->needle))->asString($row, $context) ?? (new Parameter($this->needle))->asArray( - $row, - $context, - ); - $typedNeedle = type_union(type_string(), type_list(type_string()))->assert($needle); - $includeNeedle = (new Parameter($this->includeNeedle))->asBoolean($row, $context) ?? false; + $typedNeedle = type_union(type_string(), type_list(type_string()))->assert($needles[$i]); + $results[] = u($string)->after($typedNeedle, $includeNeedles[$i] ?? false)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } - return u($string)->after($typedNeedle, $includeNeedle)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringAfterLast.php b/src/core/etl/src/Flow/ETL/Function/StringAfterLast.php index 8c15e4ebe1..75244eb321 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringAfterLast.php +++ b/src/core/etl/src/Flow/ETL/Function/StringAfterLast.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -58,21 +62,27 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $includeNeedles = (new Parameter($this->includeNeedle))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('StringAfterLast function requires non-null value'); - } + try { + foreach ($strings as $i => $string) { + if ($string === null) { + throw new InvalidArgumentException('StringAfterLast function requires non-null value'); + } - $needle = (new Parameter($this->needle))->asString($row, $context) ?? (new Parameter($this->needle))->asArray( - $row, - $context, - ); - $typedNeedle = type_union(type_string(), type_list(type_string()))->assert($needle); - $includeNeedle = (new Parameter($this->includeNeedle))->asBoolean($row, $context) ?? false; + $typedNeedle = type_union(type_string(), type_list(type_string()))->assert($needles[$i]); + $results[] = u($string)->afterLast($typedNeedle, $includeNeedles[$i] ?? false)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } - return u($string)->afterLast($typedNeedle, $includeNeedle)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringAggregate.php b/src/core/etl/src/Flow/ETL/Function/StringAggregate.php index 0eccc85766..92bb789a3d 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringAggregate.php +++ b/src/core/etl/src/Flow/ETL/Function/StringAggregate.php @@ -4,10 +4,12 @@ namespace Flow\ETL\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Row\SortOrder; +use Flow\ETL\Rows; +use Flow\ETL\Sort\RowOrder; use Flow\Types\Type; use function count; @@ -17,6 +19,7 @@ use function is_string; use function rsort; use function sort; +use function sprintf; final class StringAggregate implements AggregatingFunction { @@ -54,17 +57,27 @@ public function withChildren(array $children): static return new self($children[0], $this->separator, $this->sort); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref->to())) { + if ($rows->schema()->findDefinition($this->ref->to()) === null) { return; } - $stringValue = $row->get($this->ref->to()); + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->to())->take($indices)->values() as $value) { + if (is_string($value)) { + $this->values[] = $value; + } + } + } - if (is_string($stringValue)) { - $this->values[] = $stringValue; + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); } + + $this->values = [...$this->values, ...$other->values]; } public function outputName(): string @@ -97,7 +110,8 @@ public function value(): string $values = $this->values; if ($this->sort) { - $this->sort === SortOrder::ASC ? sort($values) : rsort($values); + $flag = RowOrder::flag(type_string()); + $this->sort === SortOrder::ASC ? sort($values, $flag) : rsort($values, $flag); } return implode($this->separator, $values); diff --git a/src/core/etl/src/Flow/ETL/Function/StringBefore.php b/src/core/etl/src/Flow/ETL/Function/StringBefore.php index f9da268468..a6d092502d 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringBefore.php +++ b/src/core/etl/src/Flow/ETL/Function/StringBefore.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -58,21 +62,27 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $includeNeedles = (new Parameter($this->includeNeedle))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('StringBefore function requires non-null value'); - } + try { + foreach ($strings as $i => $string) { + if ($string === null) { + throw new InvalidArgumentException('StringBefore function requires non-null value'); + } - $needle = (new Parameter($this->needle))->asString($row, $context) ?? (new Parameter($this->needle))->asArray( - $row, - $context, - ); - $typedNeedle = type_union(type_string(), type_list(type_string()))->assert($needle); - $includeNeedle = (new Parameter($this->includeNeedle))->asBoolean($row, $context) ?? false; + $typedNeedle = type_union(type_string(), type_list(type_string()))->assert($needles[$i]); + $results[] = u($string)->before($typedNeedle, $includeNeedles[$i] ?? false)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } - return u($string)->before($typedNeedle, $includeNeedle)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringBeforeLast.php b/src/core/etl/src/Flow/ETL/Function/StringBeforeLast.php index df8752ef1f..241f23b3d3 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringBeforeLast.php +++ b/src/core/etl/src/Flow/ETL/Function/StringBeforeLast.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -58,21 +62,27 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $needles = (new Parameter($this->needle))->asStrings($rows, $context); + $includeNeedles = (new Parameter($this->includeNeedle))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('StringBeforeLast function requires non-null value'); - } + try { + foreach ($strings as $i => $string) { + if ($string === null) { + throw new InvalidArgumentException('StringBeforeLast function requires non-null value'); + } - $needle = (new Parameter($this->needle))->asString($row, $context) ?? (new Parameter($this->needle))->asArray( - $row, - $context, - ); - $typedNeedle = type_union(type_string(), type_list(type_string()))->assert($needle); - $includeNeedle = (new Parameter($this->includeNeedle))->asBoolean($row, $context) ?? false; + $typedNeedle = type_union(type_string(), type_list(type_string()))->assert($needles[$i]); + $results[] = u($string)->beforeLast($typedNeedle, $includeNeedles[$i] ?? false)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } - return u($string)->beforeLast($typedNeedle, $includeNeedle)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringContainsAny.php b/src/core/etl/src/Flow/ETL/Function/StringContainsAny.php index c4bdb879d3..416beffbe7 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringContainsAny.php +++ b/src/core/etl/src/Flow/ETL/Function/StringContainsAny.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -58,21 +62,35 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->value->returns(), $this->needles->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $needles = (new Parameter($this->needles))->asArray($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $needlesList = (new Parameter($this->needles))->asArrays($rows, $context); + $results = []; + $i = 0; - if ($value === null || $needles === null) { - return null; - } + try { + foreach ($values as $i => $value) { + $needles = $needlesList[$i]; - if (count($needles) === 0) { - throw new InvalidArgumentException('StringContainsAny function requires a non-empty needles array'); - } + if ($value === null || $needles === null) { + $results[] = null; + + continue; + } - $typedNeedles = type_list(type_string())->assert($needles); + if (count($needles) === 0) { + throw new InvalidArgumentException('StringContainsAny function requires a non-empty needles array'); + } + + $typedNeedles = type_list(type_string())->assert($needles); + + $results[] = s($value)->containsAny($typedNeedles); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); + } - return s($value)->containsAny($typedNeedles); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringEqualsTo.php b/src/core/etl/src/Flow/ETL/Function/StringEqualsTo.php index c96f8b13d5..8f0c55083a 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringEqualsTo.php +++ b/src/core/etl/src/Flow/ETL/Function/StringEqualsTo.php @@ -4,8 +4,12 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Nullability; @@ -51,15 +55,29 @@ public function returns(): Type return (new Nullability())->any(type_boolean(), $this->value->returns(), $this->string->returns()); } - public function eval(Row $row, FlowContext $context): ?bool + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $string = (new Parameter($this->string))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null || $string === null) { - return null; + try { + foreach ($values as $i => $value) { + $string = $strings[$i]; + + if ($value === null || $string === null) { + $results[] = null; + + continue; + } + + $results[] = s($value)->equalsTo($string); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->equalsTo($string); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringFold.php b/src/core/etl/src/Flow/ETL/Function/StringFold.php index e3011479bd..7f6371f378 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringFold.php +++ b/src/core/etl/src/Flow/ETL/Function/StringFold.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('StringFold function requires non-null value'); + try { + foreach ($strings as $i => $string) { + if ($string === null) { + throw new InvalidArgumentException('StringFold function requires non-null value'); + } + + $results[] = u($string)->folded()->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return u($string)->folded()->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringMatch.php b/src/core/etl/src/Flow/ETL/Function/StringMatch.php index 29b057c472..fc7d9dbfc2 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringMatch.php +++ b/src/core/etl/src/Flow/ETL/Function/StringMatch.php @@ -4,11 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; -use Throwable; use function count; use function Flow\ETL\DSL\lit; @@ -54,29 +57,38 @@ public function returns(): Type return type_optional(type_array()); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - $haystack = (new Parameter($this->haystack))->asString($row, $context); - $pattern = (new Parameter($this->pattern))->asString($row, $context); + $haystacks = (new Parameter($this->haystack))->asStrings($rows, $context); + $patterns = (new Parameter($this->pattern))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($haystack === null) { - throw new InvalidArgumentException('StringMatch function requires non-null haystack'); - } + try { + foreach ($haystacks as $i => $haystack) { + $pattern = $patterns[$i]; - if ($pattern === null) { - throw new InvalidArgumentException('StringMatch function requires non-null pattern'); - } + if ($haystack === null) { + throw new InvalidArgumentException('StringMatch function requires non-null haystack'); + } - try { - /** @var array $result */ - $result = s($haystack)->match($pattern); + if ($pattern === null) { + throw new InvalidArgumentException('StringMatch function requires non-null pattern'); + } - return count($result) > 0 ? $result : null; - } catch (Throwable $e) { - throw new InvalidArgumentException('StringMatch error: ' . $e->getMessage()); + try { + /** @var array $result */ + $result = s($haystack)->match($pattern); + + $results[] = count($result) > 0 ? $result : null; + } catch (Exception $e) { + throw new InvalidArgumentException('StringMatch error: ' . $e->getMessage(), 0, $e); + } + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringMatchAll.php b/src/core/etl/src/Flow/ETL/Function/StringMatchAll.php index 8114df29a8..835d72f099 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringMatchAll.php +++ b/src/core/etl/src/Flow/ETL/Function/StringMatchAll.php @@ -4,11 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; -use Throwable; use function Flow\ETL\DSL\lit; use function Flow\Types\DSL\type_array; @@ -54,32 +57,43 @@ public function returns(): Type return type_array(); } - /** - * @return array> - */ - public function eval(Row $row, FlowContext $context): array + public function eval(Rows $rows, FlowContext $context): Column { - $haystack = (new Parameter($this->haystack))->asString($row, $context); - $pattern = (new Parameter($this->pattern))->asString($row, $context); + $haystacks = (new Parameter($this->haystack))->asStrings($rows, $context); + $patterns = (new Parameter($this->pattern))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($haystack === null) { - throw new InvalidArgumentException('StringMatchAll function requires non-null haystack'); - } + try { + foreach ($haystacks as $i => $haystack) { + $pattern = $patterns[$i]; - if ($pattern === null) { - throw new InvalidArgumentException('StringMatchAll function requires non-null pattern'); - } + if ($haystack === null) { + throw new InvalidArgumentException('StringMatchAll function requires non-null haystack'); + } - try { - $matches = []; + if ($pattern === null) { + throw new InvalidArgumentException('StringMatchAll function requires non-null pattern'); + } - if (preg_match_all($pattern, $haystack, $matches, PREG_SET_ORDER) !== false) { - return $matches; - } + try { + $matches = []; + + if (preg_match_all($pattern, $haystack, $matches, PREG_SET_ORDER) !== false) { + $results[] = $matches; + + continue; + } - return []; - } catch (Throwable $e) { - throw new InvalidArgumentException('StringMatchAll error: ' . $e->getMessage()); + $results[] = []; + } catch (Exception $e) { + throw new InvalidArgumentException('StringMatchAll error: ' . $e->getMessage(), 0, $e); + } + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } + + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringNormalize.php b/src/core/etl/src/Flow/ETL/Function/StringNormalize.php index fd214bd39a..1649cb859b 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringNormalize.php +++ b/src/core/etl/src/Flow/ETL/Function/StringNormalize.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Normalizer; @@ -52,15 +56,27 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $form = (new Parameter($this->form))->asInt($row, $context, Normalizer::NFC); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $forms = (new Parameter($this->form))->asInts($rows, $context, Normalizer::NFC); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('StringNormalize function requires non-null value'); + try { + foreach ($values as $i => $value) { + $form = $forms[$i]; + + if ($value === null) { + throw new InvalidArgumentException('StringNormalize function requires non-null value'); + } + + $results[] = u($value)->normalize($form)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return u($value)->normalize($form)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringStyle.php b/src/core/etl/src/Flow/ETL/Function/StringStyle.php index 01faa18b9e..81611f2ac9 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringStyle.php +++ b/src/core/etl/src/Flow/ETL/Function/StringStyle.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\ETL\String\StringStyles; use Flow\Types\Type; @@ -52,23 +56,40 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); - $style = (new Parameter($this->style))->as($row, $context, type_string(), type_enum(StringStyles::class)); + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $styles = (new Parameter($this->style))->asTypes( + $rows, + $context, + type_string(), + type_enum(StringStyles::class), + ); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('StringStyle function requires non-null value'); - } + try { + foreach ($strings as $i => $string) { + $style = $styles[$i]; - if ($style === null) { - throw new InvalidArgumentException('StringStyle function requires non-null style'); - } + if ($string === null) { + throw new InvalidArgumentException('StringStyle function requires non-null value'); + } + + if ($style === null) { + throw new InvalidArgumentException('StringStyle function requires non-null style'); + } + + if (is_string($style)) { + $style = StringStyles::fromString($style); + } - if (is_string($style)) { - $style = StringStyles::fromString($style); + $results[] = $style->convert($string); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $style->convert($string); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringTitle.php b/src/core/etl/src/Flow/ETL/Function/StringTitle.php index 701a4483e9..2da8bc5115 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringTitle.php +++ b/src/core/etl/src/Flow/ETL/Function/StringTitle.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -51,15 +55,29 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $string = (new Parameter($this->string))->asString($row, $context); - $allWords = (new Parameter($this->allWords))->asBoolean($row, $context) ?? false; + $strings = (new Parameter($this->string))->asStrings($rows, $context); + $allWordsList = (new Parameter($this->allWords))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($string === null) { - throw new InvalidArgumentException('StringTitle function requires non-null value'); + try { + foreach ($strings as $i => $string) { + $allWords = $allWordsList[$i]; + + $allWords ??= false; + + if ($string === null) { + throw new InvalidArgumentException('StringTitle function requires non-null value'); + } + + $results[] = u($string)->title(allWords: $allWords)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return u($string)->title(allWords: $allWords)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringWidth.php b/src/core/etl/src/Flow/ETL/Function/StringWidth.php index 01aed5e651..dcfa6d1469 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringWidth.php +++ b/src/core/etl/src/Flow/ETL/Function/StringWidth.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_integer(); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('StringWidth function requires non-null value'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('StringWidth function requires non-null value'); + } + + $results[] = s($value)->width(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->width(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Structure.php b/src/core/etl/src/Flow/ETL/Function/Structure.php index 0c7f92fa37..d282f8f923 100644 --- a/src/core/etl/src/Flow/ETL/Function/Structure.php +++ b/src/core/etl/src/Flow/ETL/Function/Structure.php @@ -4,10 +4,12 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\StructureType; @@ -87,17 +89,26 @@ public function returns(): Type return new StructureType($elements); } - /** - * @return non-empty-array - */ - public function eval(Row $row, FlowContext $context): array + public function eval(Rows $rows, FlowContext $context): Column { - $values = []; + $elements = []; foreach ($this->elements as $name => $element) { - $values[$name] = $element->eval($row, $context); + $elements[$name] = (new Parameter($element))->values($rows, $context); + } + + $results = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $values = []; + + foreach ($elements as $name => $element) { + $values[$name] = $element[$i]; + } + + $results[] = $values; } - return $values; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StructureSelect.php b/src/core/etl/src/Flow/ETL/Function/StructureSelect.php index 29e3833470..e322192105 100644 --- a/src/core/etl/src/Flow/ETL/Function/StructureSelect.php +++ b/src/core/etl/src/Flow/ETL/Function/StructureSelect.php @@ -4,17 +4,20 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; use Flow\ETL\Row\UnresolvedReference; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\ArrayKey; use Flow\Types\Type\Logical\StructureType; +use function array_fill; use function array_key_exists; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_bare; @@ -88,30 +91,36 @@ public function returns(): Type return type_optional(new StructureType($elements)); } - /** - * @return null|array - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - if (!$row->has($this->ref)) { - return null; + if ($rows->schema()->findDefinition($this->ref->base()) === null) { + // @mago-ignore analysis:possibly-invalid-argument + return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), null)); } - $value = $row->get($this->ref); + $results = []; - if (!is_array($value)) { - return null; - } - $output = []; + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->values() as $value) { + if (!is_array($value)) { + $results[] = null; - foreach ($this->refs as $ref) { - if (array_key_exists($ref->to(), $value)) { - $output[$ref->name()] = $value[$ref->to()]; - } else { - $output[$ref->name()] = null; + continue; } + + $output = []; + + foreach ($this->refs as $ref) { + if (array_key_exists($ref->to(), $value)) { + $output[$ref->name()] = $value[$ref->to()]; + } else { + $output[$ref->name()] = null; + } + } + + $results[] = $output; } - return $output; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Sum.php b/src/core/etl/src/Flow/ETL/Function/Sum.php index 3737d7da5e..7c488fbf88 100644 --- a/src/core/etl/src/Flow/ETL/Function/Sum.php +++ b/src/core/etl/src/Flow/ETL/Function/Sum.php @@ -8,8 +8,8 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\ETL\Window; use Flow\ETL\Window\Accumulator\SumAccumulator; use Flow\ETL\Window\FrameAccumulator; @@ -19,6 +19,7 @@ use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_optional; use function is_numeric; +use function sprintf; final class Sum implements AggregatingFunction, FrameAccumulating, WindowFunction { @@ -30,15 +31,12 @@ final class Sum implements AggregatingFunction, FrameAccumulating, WindowFunctio private ?RunningSum $runningSum = null; - private float|int $sum; - public function __construct( private readonly Reference $ref, - private readonly ScalarFunction|bool $exact = false, + private readonly bool $exact = false, private readonly ?Window $window = null, ) { $this->outputName = $ref->hasAlias() ? $ref->name() : $ref->to() . '_sum'; - $this->sum = 0; } /** @@ -46,7 +44,7 @@ public function __construct( */ public function children(): array { - return $this->exact instanceof ScalarFunction ? [$this->ref, $this->exact] : [$this->ref]; + return [$this->ref]; } /** @@ -54,29 +52,41 @@ public function children(): array */ public function withChildren(array $children): static { - /** @var array{0: Reference, 1?: ScalarFunction} $children */ - return new self($children[0], $children[1] ?? $this->exact, $this->window); + /** @var array{0: Reference} $children */ + return new self($children[0], $this->exact, $this->window); } - public function aggregate(Row $row, FlowContext $context): void + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { - if (!$row->has($this->ref)) { + if ($rows->schema()->findDefinition($this->ref->base()) === null) { return; } - try { - $value = $row->get($this->ref); - + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->take($indices)->values() as $value) { if (is_int($value) || is_float($value) || is_string($value) && is_numeric($value)) { $this->runningSum ??= new RunningSum($context->calculator()); - $this->sum = $this->runningSum->add($this->sum, $value, $this->isExact($row, $context)); + $this->runningSum->add($value, $this->exact); $this->aggregated++; } - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException('Sum error: ' . $e->getMessage(), 0, $e); } } + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); + } + + if ($other->aggregated === 0 || $other->runningSum === null) { + return; + } + + $this->runningSum ??= new RunningSum($context->calculator()); + $this->runningSum->merge($other->runningSum, $this->exact); + $this->aggregated += $other->aggregated; + } + public function accumulator(FlowContext $context): FrameAccumulator { return new SumAccumulator($this->ref, $this->exact, $context); @@ -86,8 +96,10 @@ public function apply(WindowContext $window): mixed { $accumulator = $this->accumulator($window->flowContext()); - foreach ($window->frame() as $frameRow) { - $accumulator->accumulate($frameRow); + $frame = $window->frame(); + + for ($index = 0, $count = $frame->count(); $index < $count; $index++) { + $accumulator->accumulate($frame, $index); } return $accumulator->value(); @@ -99,12 +111,11 @@ public function over(Window $window): static } /** - * @return null|list null when $exact is a ScalarFunction - its entries cannot be - * statically enumerated, so spill column pruning must be disabled + * @return list */ - public function references(): ?array + public function references(): array { - return $this->exact instanceof ScalarFunction ? null : [$this->ref]; + return [$this->ref]; } public function outputName(): string @@ -113,7 +124,7 @@ public function outputName(): string } /** - * float, not the argument type - RunningSum::add() promotes to float on int overflow, so integer + * float, not the argument type - RunningSum promotes to float on int overflow, so integer * would be a declaration the accumulator can violate on ordinary data * * @return Type @@ -125,11 +136,11 @@ public function returns(): Type public function value(): ?float { - if ($this->aggregated === 0) { + if ($this->aggregated === 0 || $this->runningSum === null) { return null; } - return (float) $this->sum; + return (float) $this->runningSum->value(); } public function toString(): string @@ -145,13 +156,4 @@ public function window(): Window return $this->window; } - - private function isExact(Row $row, FlowContext $context): bool - { - if (is_bool($this->exact)) { - return $this->exact; - } - - return (new Parameter($this->exact))->asBoolean($row, $context) ?? false; - } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToDate.php b/src/core/etl/src/Flow/ETL/Function/ToDate.php index 948f861789..ceed1668e8 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToDate.php +++ b/src/core/etl/src/Flow/ETL/Function/ToDate.php @@ -6,11 +6,14 @@ use DateTime; use DateTimeImmutable; -use DateTimeInterface; use DateTimeZone; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -63,36 +66,56 @@ public function returns(): Type return type_date(); } - public function eval(Row $row, FlowContext $context): ?DateTimeInterface + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); - $format = (new Parameter($this->format))->asString($row, $context); - $timeZone = (new Parameter($this->timeZone))->asInstanceOf($row, $context, DateTimeZone::class); + $values = (new Parameter($this->value))->values($rows, $context); + $formats = (new Parameter($this->format))->asStrings($rows, $context); + $timeZones = (new Parameter($this->timeZone))->asInstancesOf($rows, $context, DateTimeZone::class); + $results = []; + $i = 0; - if ($value === null || $format === null || $timeZone === null) { - throw new InvalidArgumentException('ToDate function requires non-null values'); - } + try { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + $format = $formats[$i]; + $timeZone = $timeZones[$i]; - if (is_object($value)) { - if (is_a($value, DateTimeImmutable::class) || is_a($value, DateTime::class)) { - return $value->setTimezone($timeZone)->setTime(0, 0, 0, 0); - } + if ($value === null || $format === null || $timeZone === null) { + throw new InvalidArgumentException('ToDate function requires non-null values'); + } - throw new InvalidArgumentException('ToDate function requires DateTimeInterface object'); - } + if (is_object($value)) { + if (is_a($value, DateTimeImmutable::class) || is_a($value, DateTime::class)) { + $results[] = $value->setTimezone($timeZone)->setTime(0, 0, 0, 0); - if (is_int($value)) { - $date = DateTimeImmutable::createFromFormat('U', (string) $value, $timeZone); + continue; + } - return $date === false ? null : $date->setTime(0, 0, 0, 0); - } + throw new InvalidArgumentException('ToDate function requires DateTimeInterface object'); + } + + if (is_int($value)) { + $date = DateTimeImmutable::createFromFormat('U', (string) $value, $timeZone); - if (is_string($value)) { - $date = DateTimeImmutable::createFromFormat($format, $value, $timeZone); + $results[] = $date === false ? null : $date->setTime(0, 0, 0, 0); - return $date === false ? null : $date->setTime(0, 0, 0, 0); + continue; + } + + if (is_string($value)) { + $date = DateTimeImmutable::createFromFormat($format, $value, $timeZone); + + $results[] = $date === false ? null : $date->setTime(0, 0, 0, 0); + + continue; + } + + throw new InvalidArgumentException('ToDate function requires int or string value'); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - throw new InvalidArgumentException('ToDate function requires int or string value'); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToDateTime.php b/src/core/etl/src/Flow/ETL/Function/ToDateTime.php index 32b64556f7..e045a31acd 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToDateTime.php +++ b/src/core/etl/src/Flow/ETL/Function/ToDateTime.php @@ -7,10 +7,14 @@ use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Function\ToDateTime\PatternCoverage; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; @@ -102,36 +106,56 @@ public function returns(): Type return type_optional($this->type); } - public function eval(Row $row, FlowContext $context): ?DateTimeImmutable + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->eval($row, $context); - $format = (new Parameter($this->format))->asString($row, $context); - $timeZone = (new Parameter($this->timeZone))->asInstanceOf($row, $context, DateTimeZone::class); + $values = (new Parameter($this->value))->values($rows, $context); + $formats = (new Parameter($this->format))->asStrings($rows, $context); + $timeZones = (new Parameter($this->timeZone))->asInstancesOf($rows, $context, DateTimeZone::class); + $results = []; + $i = 0; - if ($value === null || $format === null || $timeZone === null) { - throw new InvalidArgumentException('ToDateTime function requires non-null values'); - } + try { + // @mago-ignore analysis:mixed-assignment + foreach ($values as $i => $value) { + $format = $formats[$i]; + $timeZone = $timeZones[$i]; - if (is_object($value)) { - if ($value instanceof DateTimeInterface) { - return $this->type->cast($value); - } + if ($value === null || $format === null || $timeZone === null) { + throw new InvalidArgumentException('ToDateTime function requires non-null values'); + } - throw new InvalidArgumentException('ToDateTime function requires DateTimeInterface object'); - } + if (is_object($value)) { + if ($value instanceof DateTimeInterface) { + $results[] = $this->type->cast($value); - if (is_int($value)) { - $dateTime = DateTimeImmutable::createFromFormat('U', (string) $value, $timeZone); + continue; + } - return $dateTime === false ? null : $this->type->cast($dateTime); - } + throw new InvalidArgumentException('ToDateTime function requires DateTimeInterface object'); + } + + if (is_int($value)) { + $dateTime = DateTimeImmutable::createFromFormat('U', (string) $value, $timeZone); - if (is_string($value)) { - $dateTime = DateTimeImmutable::createFromFormat($format, $value, $timeZone); + $results[] = $dateTime === false ? null : $this->type->cast($dateTime); - return $dateTime === false ? null : $this->type->cast($dateTime); + continue; + } + + if (is_string($value)) { + $dateTime = DateTimeImmutable::createFromFormat($format, $value, $timeZone); + + $results[] = $dateTime === false ? null : $this->type->cast($dateTime); + + continue; + } + + throw new InvalidArgumentException('ToDateTime function requires int or string value'); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - throw new InvalidArgumentException('ToDateTime function requires int or string value'); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToLower.php b/src/core/etl/src/Flow/ETL/Function/ToLower.php index 106fafdc23..07bd3a3236 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToLower.php +++ b/src/core/etl/src/Flow/ETL/Function/ToLower.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('ToLower function requires non-null value'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('ToLower function requires non-null value'); + } + + $results[] = strtolower($value); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return strtolower($value); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToTimeZone.php b/src/core/etl/src/Flow/ETL/Function/ToTimeZone.php index 528f326a85..2226b4bec5 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToTimeZone.php +++ b/src/core/etl/src/Flow/ETL/Function/ToTimeZone.php @@ -6,13 +6,18 @@ use DateTimeInterface; use DateTimeZone; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use function Flow\ETL\DSL\lit; +use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_datetime; final class ToTimeZone implements ScalarFunction @@ -57,14 +62,42 @@ public function returns(): Type return $this->type; } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $dateTime = (new Parameter($this->value))->asInstanceOf($row, $context, DateTimeInterface::class); + $column = (new Parameter($this->value))->column($rows, $context); - if ($dateTime === null) { - throw new InvalidArgumentException('ToTimeZone function requires non-null values'); + if (type_bare($column->type()) instanceof DateTimeType) { + for ($i = 0, $count = $column->count(); $column->nullCount() > 0 && $i < $count; $i++) { + if ($column->isNull($i)) { + throw new EvaluationException( + $i, + new InvalidArgumentException('ToTimeZone function requires non-null values'), + ); + } + } + + return $column->withType($this->type); + } + + $results = []; + $i = 0; + + try { + foreach ((new Parameter($this->value))->asInstancesOf( + $rows, + $context, + DateTimeInterface::class, + ) as $i => $dateTime) { + if ($dateTime === null) { + throw new InvalidArgumentException('ToTimeZone function requires non-null values'); + } + + $results[] = $this->type->cast($dateTime); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $this->type->cast($dateTime); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToUpper.php b/src/core/etl/src/Flow/ETL/Function/ToUpper.php index a587676f07..439a3f9f91 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToUpper.php +++ b/src/core/etl/src/Flow/ETL/Function/ToUpper.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('ToUpper function requires non-null value'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('ToUpper function requires non-null value'); + } + + $results[] = mb_strtoupper($value); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return mb_strtoupper($value); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Trim.php b/src/core/etl/src/Flow/ETL/Function/Trim.php index 01737f2b69..d7f505c31a 100644 --- a/src/core/etl/src/Flow/ETL/Function/Trim.php +++ b/src/core/etl/src/Flow/ETL/Function/Trim.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Function\Trim\Type; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type as FlowType; use function Flow\ETL\DSL\lit; @@ -61,24 +65,37 @@ public function returns(): FlowType return type_string(); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $type = (new Parameter($this->type))->asEnum($row, $context, Type::class); - $characters = (new Parameter($this->characters))->asString($row, $context); - - if ($value === null) { - throw new InvalidArgumentException('Trim function requires non-null value'); - } - - if ($type === null || $characters === null) { - throw new InvalidArgumentException('Trim function requires non-null type and characters'); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $types = (new Parameter($this->type))->asEnums($rows, $context, Type::class); + $charactersList = (new Parameter($this->characters))->asStrings($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($values as $i => $value) { + $type = $types[$i]; + $characters = $charactersList[$i]; + + if ($value === null) { + throw new InvalidArgumentException('Trim function requires non-null value'); + } + + if ($type === null || $characters === null) { + throw new InvalidArgumentException('Trim function requires non-null type and characters'); + } + + $results[] = match ($type) { + Type::LEFT => ltrim($value, $characters), + Type::RIGHT => rtrim($value, $characters), + Type::BOTH => trim($value, $characters), + }; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return match ($type) { - Type::LEFT => ltrim($value, $characters), - Type::RIGHT => rtrim($value, $characters), - Type::BOTH => trim($value, $characters), - }; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Truncate.php b/src/core/etl/src/Flow/ETL/Function/Truncate.php index 9658ff6931..580b60e859 100644 --- a/src/core/etl/src/Flow/ETL/Function/Truncate.php +++ b/src/core/etl/src/Flow/ETL/Function/Truncate.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -56,20 +60,35 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $length = (new Parameter($this->length))->asInt($row, $context); - $ellipsis = (new Parameter($this->ellipsis))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $lengths = (new Parameter($this->length))->asInts($rows, $context); + $ellipsisList = (new Parameter($this->ellipsis))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('Truncate function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $length = $lengths[$i]; + $ellipsis = $ellipsisList[$i]; + + if ($value === null) { + throw new InvalidArgumentException('Truncate function requires non-null value'); + } + + if ($length === null) { + $results[] = $value; + + continue; + } - if ($length === null) { - return $value; + $results[] = s($value)->truncate($length, $ellipsis ?? '...')->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->truncate($length, $ellipsis ?? '...')->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Ulid.php b/src/core/etl/src/Flow/ETL/Function/Ulid.php index d661a56a43..e5fca37fe3 100644 --- a/src/core/etl/src/Flow/ETL/Function/Ulid.php +++ b/src/core/etl/src/Flow/ETL/Function/Ulid.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use InvalidArgumentException as BaseInvalidArgumentException; use Symfony\Component\Uid\Ulid as SymfonyUlid; @@ -67,19 +71,37 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): string + public function eval(Rows $rows, FlowContext $context): Column { - $param = $this->ref === null ? null : (new Parameter($this->ref))->asString($row, $context); - - if (null !== $param) { - try { - // A ULID is a string column - the object form cannot be typed as one (L6). - return SymfonyUlid::fromString($param)->toBase32(); - } catch (BaseInvalidArgumentException $e) { - throw new InvalidArgumentException('Ulid requires valid ULID string: ' . $e->getMessage(), 0, $e); + $refs = (new Parameter($this->ref))->asStrings($rows, $context); + $results = []; + $i = 0; + + try { + foreach ($refs as $i => $ref) { + $param = $this->ref === null ? null : $ref; + + if (null !== $param) { + try { + // A ULID is a string column - the object form cannot be typed as one. + $results[] = SymfonyUlid::fromString($param)->toBase32(); + + continue; + } catch (BaseInvalidArgumentException $e) { + throw new InvalidArgumentException( + 'Ulid requires valid ULID string: ' . $e->getMessage(), + 0, + $e, + ); + } + } + + $results[] = (new SymfonyUlid())->toBase32(); } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return (new SymfonyUlid())->toBase32(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/UnicodeLength.php b/src/core/etl/src/Flow/ETL/Function/UnicodeLength.php index 65a5f7eb23..617050f7d5 100644 --- a/src/core/etl/src/Flow/ETL/Function/UnicodeLength.php +++ b/src/core/etl/src/Flow/ETL/Function/UnicodeLength.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -49,14 +53,24 @@ public function returns(): Type return type_integer(); } - public function eval(Row $row, FlowContext $context): ?int + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); + $values = (new Parameter($this->value))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('UnicodeLength function requires non-null value'); + try { + foreach ($values as $i => $value) { + if ($value === null) { + throw new InvalidArgumentException('UnicodeLength function requires non-null value'); + } + + $results[] = u($value)->length(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return u($value)->length(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Uuid.php b/src/core/etl/src/Flow/ETL/Function/Uuid.php index 9330d999c8..cd9f29903d 100644 --- a/src/core/etl/src/Flow/ETL/Function/Uuid.php +++ b/src/core/etl/src/Flow/ETL/Function/Uuid.php @@ -5,10 +5,14 @@ namespace Flow\ETL\Function; use DateTimeInterface; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Value\Uuid as FlowUuid; use Ramsey\Uuid\Uuid as RamseyUuid; @@ -86,24 +90,39 @@ public static function uuid7(ScalarFunction|DateTimeInterface $value): self return new self('uuid7', $value); } - public function eval(Row $row, FlowContext $context): FlowUuid + public function eval(Rows $rows, FlowContext $context): Column { + $results = []; + if ($this->uuidVersion === 'uuid4') { - return new FlowUuid($this->generateV4()); + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $results[] = new FlowUuid($this->generateV4()); + } + + return (new ResultColumn())->of($this, $results); } - $param = (new Parameter($this->value))->as( - $row, + $params = (new Parameter($this->value))->asTypes( + $rows, $context, type_string(), type_instance_of(DateTimeInterface::class), ); - - if (!$param instanceof DateTimeInterface) { - throw new InvalidArgumentException('Uuid uuid7 function requires a DateTimeInterface value'); + $i = 0; + + try { + foreach ($params as $i => $param) { + if (!$param instanceof DateTimeInterface) { + throw new InvalidArgumentException('Uuid uuid7 function requires a DateTimeInterface value'); + } + + $results[] = new FlowUuid($this->generateV7($param)); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return new FlowUuid($this->generateV7($param)); + return (new ResultColumn())->of($this, $results); } private function generateV4(): UuidV4|UuidInterface diff --git a/src/core/etl/src/Flow/ETL/Function/When.php b/src/core/etl/src/Flow/ETL/Function/When.php index c39f1968d3..cbeec600f9 100644 --- a/src/core/etl/src/Flow/ETL/Function/When.php +++ b/src/core/etl/src/Flow/ETL/Function/When.php @@ -4,8 +4,11 @@ namespace Flow\ETL\Function; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Function\Evaluation\Selection; +use Flow\ETL\Rows; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Unifier\NullabilityRule; @@ -75,18 +78,45 @@ public function returns(): Type return $this->else === null ? type_optional($result) : $result; } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - $condition = (new Parameter($this->condition))->asBoolean($row, $context); + $then = []; + $else = []; + + foreach ((new Parameter($this->condition))->asBooleans($rows, $context) as $i => $condition) { + if ($condition) { + $then[] = $i; + } else { + $else[] = $i; + } + } + + $values = []; - if ($condition) { - return (new Parameter($this->then))->eval($row, $context); + if ($then !== []) { + $column = (new Selection($then))->evaluate($this->then, $rows, $context); + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $k => $value) { + $values[$then[$k]] = $value; + } } - if ($this->else !== null) { - return (new Parameter($this->else))->eval($row, $context); + if ($else !== [] && $this->else !== null) { + $column = (new Selection($else))->evaluate($this->else, $rows, $context); + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $k => $value) { + $values[$else[$k]] = $value; + } + } + + $results = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $results[] = $values[$i] ?? null; } - return null; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Wordwrap.php b/src/core/etl/src/Flow/ETL/Function/Wordwrap.php index 8f3f78317f..40e5500213 100644 --- a/src/core/etl/src/Flow/ETL/Function/Wordwrap.php +++ b/src/core/etl/src/Flow/ETL/Function/Wordwrap.php @@ -4,9 +4,13 @@ namespace Flow\ETL\Function; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -60,25 +64,44 @@ public function returns(): Type return type_string(); } - public function eval(Row $row, FlowContext $context): ?string + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asString($row, $context); - $width = type_integer()->assert((new Parameter($this->width))->as($row, $context, type_integer())); - $break = (new Parameter($this->break))->asString($row, $context); - $cut = (new Parameter($this->cut))->asBoolean($row, $context) ?? false; + $values = (new Parameter($this->value))->asStrings($rows, $context); + $breaks = (new Parameter($this->break))->asStrings($rows, $context); + $widths = (new Parameter($this->width))->asTypes($rows, $context, type_integer()); + $cuts = (new Parameter($this->cut))->asBooleans($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('Wordwrap function requires non-null value'); - } + try { + foreach ($values as $i => $value) { + $break = $breaks[$i]; + $width = $widths[$i]; + $cut = $cuts[$i]; - if ($width <= 0) { - return $value; - } + $width = type_integer()->assert($width); + $cut ??= false; + + if ($value === null) { + throw new InvalidArgumentException('Wordwrap function requires non-null value'); + } + + if ($width <= 0) { + $results[] = $value; + + continue; + } + + if ($break === null) { + $break = "\n"; + } - if ($break === null) { - $break = "\n"; + $results[] = s($value)->wordwrap($width, $break, $cut)->toString(); + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return s($value)->wordwrap($width, $break, $cut)->toString(); + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/XPath.php b/src/core/etl/src/Flow/ETL/Function/XPath.php index ca98988d18..743260a5c8 100644 --- a/src/core/etl/src/Flow/ETL/Function/XPath.php +++ b/src/core/etl/src/Flow/ETL/Function/XPath.php @@ -10,9 +10,13 @@ use DOMNode; use DOMNodeList; use DOMXPath; +use Exception; +use Flow\ETL\Column\Column; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; +use Flow\ETL\Function\Evaluation\ResultColumn; +use Flow\ETL\Rows; use Flow\Types\Type; use function Flow\ETL\DSL\lit; @@ -58,52 +62,63 @@ public function returns(): Type return type_optional(type_list(type_xml_element())); } - /** - * @return null|list - */ - public function eval(Row $row, FlowContext $context): ?array + public function eval(Rows $rows, FlowContext $context): Column { - $value = (new Parameter($this->value))->asInstanceOf($row, $context, DOMNode::class); - $path = (new Parameter($this->path))->asString($row, $context); + $values = (new Parameter($this->value))->asInstancesOf($rows, $context, DOMNode::class); + $paths = (new Parameter($this->path))->asStrings($rows, $context); + $results = []; + $i = 0; - if ($value === null) { - throw new InvalidArgumentException('XPath requires non-null DOMNode value'); - } + try { + foreach ($values as $i => $value) { + $path = $paths[$i]; - if ($path === null) { - throw new InvalidArgumentException('XPath requires non-null path'); - } + if ($value === null) { + throw new InvalidArgumentException('XPath requires non-null DOMNode value'); + } - if (!$value instanceof DOMDocument) { - $dom = $value->ownerDocument ?? new DOMDocument(); - $importedNode = $dom->importNode($value, true); + if ($path === null) { + throw new InvalidArgumentException('XPath requires non-null path'); + } - if ($importedNode !== false && $importedNode->parentNode === null) { - $dom->appendChild($importedNode); - } + if (!$value instanceof DOMDocument) { + $dom = $value->ownerDocument ?? new DOMDocument(); + $importedNode = $dom->importNode($value, true); - $value = $dom; - } + if ($importedNode !== false && $importedNode->parentNode === null) { + $dom->appendChild($importedNode); + } - $xpath = new DOMXPath($value); - /** @var DOMNodeList|false $result */ - $result = $xpath->query($path); + $value = $dom; + } - if ($result === false || $result->length === 0) { - return null; - } + $xpath = new DOMXPath($value); + /** @var DOMNodeList|false $result */ + $result = $xpath->query($path); - $nodes = []; + if ($result === false || $result->length === 0) { + $results[] = null; - foreach ($result as $node) { - // text(), attribute and comment queries yield nodes the declared list cannot hold. - if (!$node instanceof DOMElement) { - continue; - } + continue; + } + + $nodes = []; - $nodes[] = $node; + foreach ($result as $node) { + // text(), attribute and comment queries yield nodes the declared list cannot hold. + if (!$node instanceof DOMElement) { + continue; + } + + $nodes[] = $node; + } + + $results[] = $nodes === [] ? null : $nodes; + } + } catch (Exception $e) { + throw EvaluationException::at($i, $e); } - return $nodes === [] ? null : $nodes; + return (new ResultColumn())->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/GroupBy.php b/src/core/etl/src/Flow/ETL/GroupBy.php index 4f4a52e820..cba3a4b179 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy.php +++ b/src/core/etl/src/Flow/ETL/GroupBy.php @@ -15,6 +15,7 @@ use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; +use function array_fill; use function array_unique; use function count; use function Flow\ETL\DSL\definition_from_type; @@ -120,17 +121,40 @@ public function outputSchema(Schema $input, Aggregators $bound): Schema return new Schema(...$definitions); } - public function keyValues(Row $row, Schema $input): GroupKey + /** + * @return list one per row of $rows + */ + public function keys(Rows $rows, Schema $input): array { - $values = []; + if ($rows->isEmpty()) { + return []; + } + + $columns = []; foreach ($this->refs as $ref) { // absent under a nullable declaration is a legitimate null; absent under NOT NULL is a - // row-shape violation, and Row::get() already names it and lists the available columns. - $values[$ref->name()] = !$row->has($ref) && $input->get($ref)->isNullable() ? null : $row->get($ref); + // row-shape violation, and Rows::column() names it and lists the available columns. + $columns[$ref->name()] = $rows->schema()->findDefinition($ref->base()) === null + && $input->get($ref)->isNullable() + // @mago-ignore analysis:possibly-invalid-argument + ? array_fill(0, $rows->count(), null) + : $rows->column($ref->base())->values(); + } + + $keys = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $values = []; + + foreach ($columns as $name => $column) { + $values[$name] = $column[$i]; + } + + $keys[] = new GroupKey($values); } - return new GroupKey($values); + return $keys; } public function pivot(Reference $ref, DeclaredPivotValues $values): void diff --git a/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php b/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php index 130d802c37..92e2f5284e 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/AggregatedGroups.php @@ -7,9 +7,10 @@ use Flow\ETL\FlowContext; use Flow\ETL\GroupBy; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Generator; +use function array_chunk; +use function array_key_exists; use function count; final class AggregatedGroups @@ -24,15 +25,46 @@ public function __construct( private readonly GroupByShape $shape, ) {} + /** + * @return array by the key's string form + */ + public function groups(): array + { + return $this->groups; + } + public function accumulate(Rows $batch, FlowContext $context): void { - foreach ($batch as $row) { - $key = $this->groupBy->keyValues($row, $this->shape->input); - $group = $this->groups[(string) $key] ??= new Group($key, $this->shape->aggregators->cloned()); - $group->aggregators->aggregate($row, $context); + /** @var array> $indices */ + $indices = []; + + /** @var array $keys */ + $keys = []; + + foreach ($this->groupBy->keys($batch, $this->shape->input) as $i => $key) { + $index = (string) $key; + $indices[$index][] = $i; + $keys[$index] ??= $key; + } + + foreach ($indices as $index => $rows) { + $group = $this->groups[$index] ??= new Group($keys[$index], $this->shape->aggregators->cloned()); + $group->aggregators->aggregate($batch, $rows, $context); } } + /** + * $group aggregated rows that come before every row this instance aggregated under the same key. + */ + public function absorbEarlier(string $key, Group $group, FlowContext $context): void + { + if (array_key_exists($key, $this->groups)) { + $group->aggregators->merge($this->groups[$key]->aggregators, $context); + } + + $this->groups[$key] = $group; + } + /** * @param int<1, max> $batchSize * @@ -40,23 +72,42 @@ public function accumulate(Rows $batch, FlowContext $context): void */ public function flush(int $batchSize, FlowContext $context): Generator { - $pending = []; + foreach (array_chunk($this->groups, $batchSize) as $groups) { + yield $this->rows($groups, $context); + } + } - foreach ($this->groups as $group) { - $pending[] = $this->groupBy->aggregatedValues($group->key, $group->aggregators, $this->shape->output); + /** + * @param list $groups + */ + public function rows(array $groups, FlowContext $context): Rows + { + $output = $this->shape->output; + $values = []; - if (count($pending) >= $batchSize) { - yield (new RowsBuilder($this->shape->output, $context->backend())) - ->appendRows($pending) - ->finish(); - $pending = []; + foreach ($output->definitions() as $name => $_) { + $values[$name] = []; + } + + foreach ($groups as $group) { + // @mago-ignore analysis:mixed-assignment + foreach ($group->key as $name => $value) { + $values[$output->get($name)->entry()->name()][] = $value; + } + + foreach ($group->aggregators as $aggregator) { + $values[$aggregator->outputName()][] = $aggregator->value(); } } - if ($pending !== []) { - yield (new RowsBuilder($this->shape->output, $context->backend())) - ->appendRows($pending) - ->finish(); + $columns = []; + + foreach ($output->definitions() as $name => $definition) { + $builder = $context->backend()->builder($definition); + $builder->appendMany($values[$name]); + $columns[$name] = $builder->finish(); } + + return Rows::fromColumns($output, $columns, count($groups)); } } diff --git a/src/core/etl/src/Flow/ETL/GroupBy/Aggregators.php b/src/core/etl/src/Flow/ETL/GroupBy/Aggregators.php index e6c787fcdb..7262fdf484 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/Aggregators.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/Aggregators.php @@ -11,7 +11,8 @@ use Flow\ETL\Function\AggregatingFunction; use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\ReferenceResolver; -use Flow\ETL\Row; +use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\ETL\Schema; use IteratorAggregate; use Traversable; @@ -35,10 +36,13 @@ public function __construct(AggregatingFunction ...$aggregators) $this->aggregators = $aggregators; } - public function aggregate(Row $row, FlowContext $context): void + /** + * @param list $indices + */ + public function aggregate(Rows $rows, array $indices, FlowContext $context): void { foreach ($this->aggregators as $aggregator) { - $aggregator->aggregate($row, $context); + $aggregator->aggregate($rows, $indices, $context); } } @@ -55,6 +59,16 @@ public function count(): int return count($this->aggregators); } + /** + * Folds $other's partial states into these, pairwise; $other aggregated rows that come after these. + */ + public function merge(self $other, FlowContext $context): void + { + foreach ($this->aggregators as $position => $aggregator) { + $aggregator->merge($other->aggregators[$position], $context); + } + } + public function first(): AggregatingFunction { if ($this->aggregators === []) { @@ -90,7 +104,7 @@ public function resolved(Schema $schema): self } /** - * @return null|list union of references read by all aggregators, or null when any + * @return null|list union of references read by all aggregators, or null when any * aggregator cannot enumerate them (disables spill column pruning) */ public function references(): ?array diff --git a/src/core/etl/src/Flow/ETL/GroupBy/BucketAggregation.php b/src/core/etl/src/Flow/ETL/GroupBy/BucketAggregation.php deleted file mode 100644 index c49e95130e..0000000000 --- a/src/core/etl/src/Flow/ETL/GroupBy/BucketAggregation.php +++ /dev/null @@ -1,75 +0,0 @@ - $batchSize - */ - public function __construct( - private int $batchSize = 1000, - ) { - // @mago-ignore analysis:invalid-operand - // @mago-ignore analysis:impossible-condition,redundant-comparison - if ($this->batchSize < 1) { - throw new InvalidArgumentException('Batch size must be greater than 0, given: ' . $this->batchSize); - } - } - - /** - * Reached only when the plan could not bind, so the shape comes from the first batch that carries rows. - * - * @param Generator $rows - * - * @return Generator - */ - public function aggregate(Generator $rows, FlowContext $context, GroupBy $groupBy): Generator - { - $groups = null; - - foreach ($rows as $batch) { - if ($groups === null) { - if (!$batch->count()) { - continue; - } - - $groups = new AggregatedGroups($groupBy, GroupByShape::of($groupBy, $batch->schema())); - } - - $groups->accumulate($batch, $context); - } - - if ($groups !== null) { - yield from $groups->flush($this->batchSize, $context); - } - } - - /** - * @param Generator $rows - * - * @return Generator - */ - public function aggregateBound( - Generator $rows, - FlowContext $context, - GroupBy $groupBy, - GroupByShape $shape, - ): Generator { - $groups = new AggregatedGroups($groupBy, $shape); - - foreach ($rows as $batch) { - $groups->accumulate($batch, $context); - } - - yield from $groups->flush($this->batchSize, $context); - } -} diff --git a/src/core/etl/src/Flow/ETL/GroupBy/DiscoveredPivotValues.php b/src/core/etl/src/Flow/ETL/GroupBy/DiscoveredPivotValues.php index 995d9857c1..77f7f61c3b 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/DiscoveredPivotValues.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/DiscoveredPivotValues.php @@ -10,6 +10,7 @@ use Flow\ETL\Extractor\Repeatability; use Flow\ETL\Plan\Trigger; use Flow\ETL\Row\Reference; +use Flow\ETL\Sort\RowOrder; use function array_values; use function count; @@ -37,14 +38,20 @@ public function resolve(DataFrame $source, Reference $pivot): DeclaredPivotValue } $distinct = []; + $type = null; // the frame, not its source: the pivot column may be produced by an earlier step, and an // earlier filter decides which values exist at all foreach ($source->get() as $batch) { - foreach ($batch as $row) { - /** @var mixed $value */ - $value = $row->get($pivot); + if ($batch->isEmpty()) { + continue; + } + + $column = $batch->column($pivot->base()); + $type ??= $column->type(); + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $value) { if ($value === null) { continue; } @@ -71,8 +78,8 @@ public function resolve(DataFrame $source, Reference $pivot): DeclaredPivotValue } $values = array_values($distinct); - // sorted so the discovered column order is deterministic across runs - sort($values); + // sorted so the discovered column order is deterministic across runs, in the order sortBy() uses + sort($values, RowOrder::flag($type ?? type_string())); return new DeclaredPivotValues(...$values); } diff --git a/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php b/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php index 2f7d420da8..fdeb7a7421 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/GroupBySteps.php @@ -7,11 +7,11 @@ use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\HashBucketing; use Flow\ETL\Bucketing\NativeHasher; +use Flow\ETL\Bucketing\Storage\SpillingBuckets; use Flow\ETL\Config; use Flow\ETL\Config\Grouping\GroupByAlgorithmBuilder; use Flow\ETL\GroupBy; use Flow\ETL\Processor; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\GroupByAggregationProcessor; use Flow\ETL\Processor\PivotProcessor; use Flow\ETL\Transformer; @@ -48,8 +48,13 @@ public static function of(GroupBy $groupBy, Config $config, ?GroupByAlgorithmBui $steps[] = new PruneEntriesTransformer(...array_values($pruned)); } - $buckets = new Buckets($grouping->bucketing->storage); - $steps[] = new BucketingProcessor( + $buckets = new Buckets(SpillingBuckets::around( + $grouping->bucketing, + $grouping->memoryLimit, + $config->backend(), + )); + $steps[] = new GroupByAggregationProcessor( + $groupBy, new HashBucketing( $groupBy->references(), $grouping->bucketing->bucketsCount, @@ -58,8 +63,9 @@ public static function of(GroupBy $groupBy, Config $config, ?GroupByAlgorithmBui 'group-by', ), $buckets, + $grouping->memoryLimit, + $grouping->bucketing->batchSize, ); - $steps[] = new GroupByAggregationProcessor($groupBy, $buckets, $grouping->bucketing->batchSize); return $steps; } diff --git a/src/core/etl/src/Flow/ETL/GroupBy/PivotedTable.php b/src/core/etl/src/Flow/ETL/GroupBy/PivotedTable.php index b91fc71eb9..4640403fd5 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/PivotedTable.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/PivotedTable.php @@ -36,22 +36,35 @@ public function __construct( public function accumulate(Rows $batch, FlowContext $context): void { - foreach ($batch as $row) { - $key = $this->groupBy->keyValues($row, $this->shape->input); + $keys = $this->groupBy->keys($batch, $this->shape->input); + + if ($keys === []) { + return; + } + + $pivotValues = $batch->column($this->shape->pivot->column->base())->values(); + + /** @var array>> $indices */ + $indices = []; + + foreach ($keys as $i => $key) { $index = (string) $key; $this->keys[$index] ??= $key; $this->accumulators[$index] ??= []; - $pivotValue = $row->get($this->shape->pivot->column); - - if ($pivotValue === null) { + if ($pivotValues[$i] === null) { continue; } - $column = type_union(type_string(), type_integer())->assert($pivotValue); - $accumulator = $this->accumulators[$index][$column] ??= clone $this->shape->aggregation; - $accumulator->aggregate($row, $context); + $indices[$index][type_union(type_string(), type_integer())->assert($pivotValues[$i])][] = $i; + } + + foreach ($indices as $index => $columns) { + foreach ($columns as $column => $rows) { + $accumulator = $this->accumulators[$index][$column] ??= clone $this->shape->aggregation; + $accumulator->aggregate($batch, $rows, $context); + } } } diff --git a/src/core/etl/src/Flow/ETL/Join/Comparison.php b/src/core/etl/src/Flow/ETL/Join/Comparison.php index 268162d645..b297b956d1 100644 --- a/src/core/etl/src/Flow/ETL/Join/Comparison.php +++ b/src/core/etl/src/Flow/ETL/Join/Comparison.php @@ -4,12 +4,17 @@ namespace Flow\ETL\Join; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; interface Comparison { - public function compare(Row $left, Row $right): bool; + /** + * $left and $right hold the same number of rows; pair i is (left row i, right row i). + * + * @return list + */ + public function compare(Rows $left, Rows $right): array; /** * @return array diff --git a/src/core/etl/src/Flow/ETL/Join/Comparison/All.php b/src/core/etl/src/Flow/ETL/Join/Comparison/All.php index 05e7224f60..8f5fa34f09 100644 --- a/src/core/etl/src/Flow/ETL/Join/Comparison/All.php +++ b/src/core/etl/src/Flow/ETL/Join/Comparison/All.php @@ -5,8 +5,8 @@ namespace Flow\ETL\Join\Comparison; use Flow\ETL\Join\Comparison; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use function array_merge; use function array_unique; @@ -23,15 +23,25 @@ public function __construct(Comparison $comparison, Comparison ...$comparisons) $this->comparisons = array_merge([$comparison], $comparisons); } - public function compare(Row $left, Row $right): bool + public function compare(Rows $left, Rows $right): array { + $result = null; + foreach ($this->comparisons as $comparison) { - if (!$comparison->compare($left, $right)) { - return false; + $compared = $comparison->compare($left, $right); + + if ($result === null) { + $result = $compared; + + continue; + } + + foreach ($compared as $i => $met) { + $result[$i] = $result[$i] && $met; } } - return true; + return $result ?? []; } /** diff --git a/src/core/etl/src/Flow/ETL/Join/Comparison/Any.php b/src/core/etl/src/Flow/ETL/Join/Comparison/Any.php index 7584490e84..2d43278819 100644 --- a/src/core/etl/src/Flow/ETL/Join/Comparison/Any.php +++ b/src/core/etl/src/Flow/ETL/Join/Comparison/Any.php @@ -5,8 +5,8 @@ namespace Flow\ETL\Join\Comparison; use Flow\ETL\Join\Comparison; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use function array_merge; use function array_unique; @@ -23,15 +23,25 @@ public function __construct(Comparison $comparison, Comparison ...$comparisons) $this->comparisons = array_merge([$comparison], $comparisons); } - public function compare(Row $left, Row $right): bool + public function compare(Rows $left, Rows $right): array { + $result = null; + foreach ($this->comparisons as $comparison) { - if ($comparison->compare($left, $right)) { - return true; + $compared = $comparison->compare($left, $right); + + if ($result === null) { + $result = $compared; + + continue; + } + + foreach ($compared as $i => $met) { + $result[$i] = $result[$i] || $met; } } - return false; + return $result ?? []; } /** diff --git a/src/core/etl/src/Flow/ETL/Join/Comparison/Equal.php b/src/core/etl/src/Flow/ETL/Join/Comparison/Equal.php index 6bce1b61ea..fdc56e3425 100644 --- a/src/core/etl/src/Flow/ETL/Join/Comparison/Equal.php +++ b/src/core/etl/src/Flow/ETL/Join/Comparison/Equal.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Join\Comparison; use Flow\ETL\Join\Comparison; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Row\UnresolvedReference; +use Flow\ETL\Rows; use Flow\Types\Value\Uuid; use function is_array; @@ -23,41 +23,30 @@ public function __construct( private string|Reference $entryRight, ) {} - public function compare(Row $left, Row $right): bool + public function compare(Rows $left, Rows $right): array { - $leftValue = $left->get($this->entryLeft); - $rightValue = $right->get($this->entryRight); - - // SQL semantics - null never equals anything, including null - if ($leftValue === null || $rightValue === null) { - return false; - } - - if (is_numeric($leftValue) && is_numeric($rightValue)) { - return (float) $leftValue == (float) $rightValue; - } - - if (is_string($leftValue) && is_string($rightValue)) { - return $leftValue === $rightValue; - } - - if (is_bool($leftValue) && is_bool($rightValue)) { - return $leftValue === $rightValue; - } - - if (is_array($leftValue) && is_array($rightValue)) { - return $leftValue === $rightValue; - } - - if (is_object($leftValue) && is_object($rightValue)) { - if ($leftValue instanceof Uuid && $rightValue instanceof Uuid) { - return $leftValue->isEqual($rightValue); - } - - return $leftValue == $rightValue; + $rightValues = $right->column($this->right()[0]->base())->values(); + $result = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($left->column($this->left()[0]->base())->values() as $i => $leftValue) { + // @mago-ignore analysis:mixed-assignment + $rightValue = $rightValues[$i]; + + $result[] = match (true) { + // SQL semantics - null never equals anything, including null + $leftValue === null || $rightValue === null => false, + is_numeric($leftValue) && is_numeric($rightValue) => (float) $leftValue == (float) $rightValue, + is_string($leftValue) && is_string($rightValue) => $leftValue === $rightValue, + is_bool($leftValue) && is_bool($rightValue) => $leftValue === $rightValue, + is_array($leftValue) && is_array($rightValue) => $leftValue === $rightValue, + $leftValue instanceof Uuid && $rightValue instanceof Uuid => $leftValue->isEqual($rightValue), + is_object($leftValue) && is_object($rightValue) => $leftValue == $rightValue, + default => false, + }; } - return false; + return $result; } /** diff --git a/src/core/etl/src/Flow/ETL/Join/Comparison/Identical.php b/src/core/etl/src/Flow/ETL/Join/Comparison/Identical.php index 177105bd1a..576c0e650f 100644 --- a/src/core/etl/src/Flow/ETL/Join/Comparison/Identical.php +++ b/src/core/etl/src/Flow/ETL/Join/Comparison/Identical.php @@ -4,11 +4,13 @@ namespace Flow\ETL\Join\Comparison; +use Flow\ETL\Column\ComparableValues; use Flow\ETL\Join\Comparison; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Row\UnresolvedReference; +use Flow\ETL\Rows; +use function Flow\Types\DSL\type_bare; use function is_string; final readonly class Identical implements Comparison @@ -18,17 +20,22 @@ public function __construct( private string|Reference $entryRight, ) {} - public function compare(Row $left, Row $right): bool + public function compare(Rows $left, Rows $right): array { - $leftValue = $left->get($this->entryLeft); - $rightValue = $right->get($this->entryRight); - - // SQL semantics - null never equals anything, including null - if ($leftValue === null || $rightValue === null) { - return false; + $leftColumn = $left->column($this->left()[0]->base()); + $rightColumn = $right->column($this->right()[0]->base()); + $comparable = new ComparableValues(); + $sameType = type_bare($leftColumn->type())::class === type_bare($rightColumn->type())::class; + $rightValues = $sameType ? $comparable->equality($rightColumn) : $rightColumn->values(); + $result = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($sameType ? $comparable->equality($leftColumn) : $leftColumn->values() as $i => $leftValue) { + // SQL semantics - null never equals anything, including null + $result[] = $leftValue !== null && $rightValues[$i] !== null && $leftValue === $rightValues[$i]; } - return $leftValue === $rightValue; + return $result; } /** diff --git a/src/core/etl/src/Flow/ETL/Join/Expression.php b/src/core/etl/src/Flow/ETL/Join/Expression.php index f7ac646e64..50d5106543 100644 --- a/src/core/etl/src/Flow/ETL/Join/Expression.php +++ b/src/core/etl/src/Flow/ETL/Join/Expression.php @@ -7,8 +7,8 @@ use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Join\Comparison\All; use Flow\ETL\Join\Comparison\Equal; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use function array_slice; use function gettype; @@ -81,7 +81,10 @@ public function left(): array return $this->comparison->left(); } - public function meet(Row $left, Row $right): bool + /** + * @return list pair i is (left row i, right row i) + */ + public function meet(Rows $left, Rows $right): array { return $this->comparison->compare($left, $right); } diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/HashTable.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/HashTable.php index 537973a189..4014dd7786 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/HashTable.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/HashTable.php @@ -4,12 +4,8 @@ namespace Flow\ETL\Join\HashJoin; -use Flow\ETL\Row; -use Generator; - use function array_key_exists; use function array_keys; -use function count; final class HashTable { @@ -18,10 +14,7 @@ final class HashTable */ private array $buckets = []; - /** - * @var list - */ - private array $rows = []; + private int $count = 0; /** * @var array @@ -32,11 +25,10 @@ public function __construct( private readonly bool $trackUnmatched = false, ) {} - public function add(string $hash, Row $row): void + public function add(string $hash, int $index): void { - $index = count($this->rows); - $this->rows[] = $row; $this->buckets[$hash][] = $index; + $this->count++; if ($this->trackUnmatched) { $this->unmatched[$index] = true; @@ -44,26 +36,16 @@ public function add(string $hash, Row $row): void } /** - * @return array + * @return list the build-side rows under $hash, in the order they were added */ public function candidatesFor(string $hash): array { - if (!array_key_exists($hash, $this->buckets)) { - return []; - } - - $candidates = []; - - foreach ($this->buckets[$hash] as $index) { - $candidates[$index] = $this->rows[$index]; - } - - return $candidates; + return array_key_exists($hash, $this->buckets) ? $this->buckets[$hash] : []; } public function count(): int { - return count($this->rows); + return $this->count; } public function matched(int $index): void @@ -72,12 +54,10 @@ public function matched(int $index): void } /** - * @return Generator + * @return list the build-side rows never matched, in the order they were added */ - public function unmatchedRows(): Generator + public function unmatched(): array { - foreach (array_keys($this->unmatched) as $index) { - yield $this->rows[$index]; - } + return array_keys($this->unmatched); } } diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/JoinSide.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/JoinSide.php index df7136da47..07bc92c01c 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/JoinSide.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/JoinSide.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Join\HashJoin; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; @@ -13,19 +12,19 @@ { /** * @param Generator $rows - * @param null|Row $nullRow pads a row on the opposite side that found no match + * @param null|Rows $nullRow the one-row batch that pads a row on the opposite side that found no match * @param null|Schema $schema the whole side's shape; a bucket pair only streams a slice of it */ private function __construct( public Generator $rows, - public ?Row $nullRow = null, + public ?Rows $nullRow = null, public ?Schema $schema = null, ) {} /** * @param Generator $rows */ - public static function of(Generator $rows, ?Row $nullRow = null, ?Schema $schema = null): self + public static function of(Generator $rows, ?Rows $nullRow = null, ?Schema $schema = null): self { return new self($rows, $nullRow, $schema); } diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php index 554a36bc84..a7c06266ff 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php @@ -8,19 +8,23 @@ use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\SingleBucketHasher; -use Flow\ETL\Column\Backend; use Flow\ETL\Exception\DuplicatedEntriesException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Join\Expression; use Flow\ETL\Join\Join; use Flow\ETL\Join\JoinSchema; use Flow\ETL\Join\JoinShape; -use Flow\ETL\Row; +use Flow\ETL\Row\Reference; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; +use function array_chunk; +use function array_fill; +use function array_map; +use function array_slice; +use function array_unique; +use function array_values; use function count; final class Joiner @@ -38,12 +42,11 @@ final class Joiner private readonly KeyValues $rightValues; /** - * @param int<1, max> $batchSize - size of output batches emitted for unmatched right side rows + * @param int<1, max> $batchSize - size of output batches emitted for unmatched build side rows */ public function __construct( private readonly Expression $expression, private readonly Join $type, - private readonly Backend $backend, private readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand @@ -79,100 +82,77 @@ public function join(JoinSide $left, JoinSide $right, bool $buildLeft = false): return; } - $nullLeftRow = $left->nullRow; - $nullRightRow = $right->nullRow; - $leftSideSchema = $left->schema; - $rightSideSchema = $right->schema; + [$build, $rightSchema] = $this->build($right); + $table = $this->table($build, $this->rightValues, $this->type === Join::right); - $hashTable = new HashTable(trackUnmatched: $this->type === Join::right); - $rightSchema = $rightSideSchema; + // the null row sits at $build->count(), so a gather pads an unmatched left row with it + $probe = $this->type === Join::left ? $this->padded($build, $right->nullRow, $rightSchema) : $build; + $nullIndex = $build->count(); - foreach ($right->rows as $batch) { - $rightSchema ??= $batch->schema(); - $hashes = $this->hasher->hash($this->rightValues->of($batch)); - - foreach ($batch as $i => $row) { - $hashTable->add($hashes[$i], $row); - } - } - - $rightSchema ??= new Schema(); - - if ($this->type === Join::left) { - $nullRightRow ??= (new NullRowBuilder($rightSchema))->row(); - } - - $leftSchema = $leftSideSchema; + $leftSchema = $left->schema; $outputSchema = null; foreach ($left->rows as $batch) { $leftSchema ??= $batch->schema(); $outputSchema ??= $this->joinSchema->of($this->type, $leftSchema, $rightSchema); - $hashes = $this->hasher->hash($this->leftValues->of($batch)); - $joined = []; + [$candidatesLeft, $candidatesRight] = $this->candidates($table, $this->leftValues->of($batch)); + $met = $this->meet($batch, $candidatesLeft, $build, $candidatesRight); + + $outputLeft = []; + $outputRight = []; + $pair = 0; + $pairs = count($candidatesLeft); - foreach ($batch as $i => $leftRow) { + for ($i = 0, $rows = $batch->count(); $i < $rows; $i++) { $matched = false; - foreach ($hashTable->candidatesFor($hashes[$i]) as $index => $rightRow) { - if (!$this->expression->meet($leftRow, $rightRow)) { + for (; $pair < $pairs && $candidatesLeft[$pair] === $i; $pair++) { + if (!$met[$pair]) { continue; } $matched = true; if ($this->type === Join::left_anti) { - break; + continue; } if ($this->type === Join::right) { - $hashTable->matched($index); + $table->matched($candidatesRight[$pair]); } - $joined[] = $this->merge($leftRow, $rightRow); - } - - if (!$matched && $this->type === Join::left) { - /** @var Row $nullRightRow */ - $joined[] = $this->merge($leftRow, $nullRightRow); + $outputLeft[] = $i; + $outputRight[] = $candidatesRight[$pair]; } - if (!$matched && $this->type === Join::left_anti) { - $joined[] = $leftRow->values(); + if (!$matched && ($this->type === Join::left || $this->type === Join::left_anti)) { + $outputLeft[] = $i; + $outputRight[] = $nullIndex; } } - if ($joined !== []) { - // a later batch can be wider than the side schema the output was derived from, and every arm answers - // for the same declared output - the builder ignores the undeclared keys and pads the nulls the join - // introduced - yield (new RowsBuilder($outputSchema, $this->backend)) - ->appendRows($joined) - ->finish(); + if ($outputLeft === []) { + continue; } + + // a later batch can be wider than the side schema the output was derived from, and every arm answers + // for the same declared output - the projection drops the undeclared columns and pads the nulls the join + // introduced + yield $this->type === Join::left_anti + ? $batch->gather($outputLeft)->project($outputSchema) + : $this->merge($batch->gather($outputLeft), $probe->gather($outputRight))->project($outputSchema); } if ($this->type === Join::right) { $leftSchema ??= new Schema(); - $nullLeftRow ??= (new NullRowBuilder($leftSchema))->row(); + $nullLeft = $left->nullRow ?? (new NullRowBuilder($leftSchema))->rows(); $outputSchema ??= $this->joinSchema->of($this->type, $leftSchema, $rightSchema); - $pending = []; - - foreach ($hashTable->unmatchedRows() as $rightRow) { - $pending[] = $this->merge($nullLeftRow, $rightRow); - - if (count($pending) >= $this->batchSize) { - yield (new RowsBuilder($outputSchema, $this->backend)) - ->appendRows($pending) - ->finish(); - $pending = []; - } - } - if ($pending !== []) { - yield (new RowsBuilder($outputSchema, $this->backend)) - ->appendRows($pending) - ->finish(); + foreach (array_chunk($table->unmatched(), $this->batchSize) as $unmatched) { + yield $this->merge( + $nullLeft->gather(array_fill(0, count($unmatched), 0)), + $build->gather($unmatched), + )->project($outputSchema); } } } @@ -191,104 +171,149 @@ public function schema(Schema $left, Schema $right): Schema } /** - * Mirror of the default execution - roles swap, output rows do not: merge($left, $right) - * argument order is preserved, unmatched-row tracking moves to whichever side sits in the table. - * - * - * @return Generator + * @return array{Rows, Schema} */ - private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator + private function build(JoinSide $side): array { - $nullLeftRow = $left->nullRow; - $nullRightRow = $right->nullRow; - $leftSideSchema = $left->schema; - $rightSideSchema = $right->schema; + $schema = $side->schema; + $parts = []; - $hashTable = new HashTable(trackUnmatched: $this->type === Join::left || $this->type === Join::left_anti); - $leftSchema = $leftSideSchema; + foreach ($side->rows as $batch) { + $schema ??= $batch->schema(); - foreach ($left->rows as $batch) { - $leftSchema ??= $batch->schema(); - $hashes = $this->hasher->hash($this->leftValues->of($batch)); + if (!$batch->isEmpty()) { + $parts[] = $batch->project($schema); + } + } + + $schema ??= new Schema(); + + return [$parts === [] ? Rows::empty($schema) : $parts[0]->concat(...array_slice($parts, 1)), $schema]; + } - foreach ($batch as $i => $row) { - $hashTable->add($hashes[$i], $row); + /** + * @param list> $keys + * + * @return array{list, list} + */ + private function candidates(HashTable $table, array $keys): array + { + $left = []; + $right = []; + + foreach ($this->hasher->hash($keys) as $i => $hash) { + foreach ($table->candidatesFor($hash) as $j) { + $left[] = $i; + $right[] = $j; } } - $leftSchema ??= new Schema(); - $nullLeftRow ??= (new NullRowBuilder($leftSchema))->row(); + return [$left, $right]; + } + + /** + * Mirror of the default execution - roles swap, output rows do not: merge($left, $right) + * argument order is preserved, unmatched-row tracking moves to whichever side sits in the table. + * + * @return Generator + */ + private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator + { + [$build, $leftSchema] = $this->build($left); + $table = $this->table($build, $this->leftValues, $this->type === Join::left || $this->type === Join::left_anti); + + $probe = $this->type === Join::right ? $this->padded($build, $left->nullRow, $leftSchema) : $build; + $nullIndex = $build->count(); - $rightSchema = $rightSideSchema; + $rightSchema = $right->schema; $outputSchema = null; foreach ($right->rows as $batch) { $rightSchema ??= $batch->schema(); $outputSchema ??= $this->joinSchema->of($this->type, $leftSchema, $rightSchema); - $hashes = $this->hasher->hash($this->rightValues->of($batch)); - $joined = []; + [$candidatesRight, $candidatesLeft] = $this->candidates($table, $this->rightValues->of($batch)); + $met = $this->meet($build, $candidatesLeft, $batch, $candidatesRight); - foreach ($batch as $i => $rightRow) { + $outputLeft = []; + $outputRight = []; + $pair = 0; + $pairs = count($candidatesRight); + + for ($i = 0, $rows = $batch->count(); $i < $rows; $i++) { $matched = false; - foreach ($hashTable->candidatesFor($hashes[$i]) as $index => $leftRow) { - if (!$this->expression->meet($leftRow, $rightRow)) { + for (; $pair < $pairs && $candidatesRight[$pair] === $i; $pair++) { + if (!$met[$pair]) { continue; } $matched = true; if ($this->type === Join::left || $this->type === Join::left_anti) { - $hashTable->matched($index); + $table->matched($candidatesLeft[$pair]); } if ($this->type !== Join::left_anti) { - $joined[] = $this->merge($leftRow, $rightRow); + $outputLeft[] = $candidatesLeft[$pair]; + $outputRight[] = $i; } } if (!$matched && $this->type === Join::right) { - $joined[] = $this->merge($nullLeftRow, $rightRow); + $outputLeft[] = $nullIndex; + $outputRight[] = $i; } } - if ($joined !== []) { - yield (new RowsBuilder($outputSchema, $this->backend)) - ->appendRows($joined) - ->finish(); + if ($outputLeft !== []) { + yield $this->merge($probe->gather($outputLeft), $batch->gather($outputRight))->project($outputSchema); } } $rightSchema ??= new Schema(); if ($this->type === Join::left || $this->type === Join::left_anti) { - $nullRightRow ??= (new NullRowBuilder($rightSchema))->row(); + $nullRight = $right->nullRow ?? (new NullRowBuilder($rightSchema))->rows(); $outputSchema ??= $this->joinSchema->of($this->type, $leftSchema, $rightSchema); - $pending = []; - - foreach ($hashTable->unmatchedRows() as $leftRow) { - $pending[] = $this->type === Join::left ? $this->merge($leftRow, $nullRightRow) : $leftRow->values(); - if (count($pending) >= $this->batchSize) { - yield (new RowsBuilder($outputSchema, $this->backend)) - ->appendRows($pending) - ->finish(); - $pending = []; - } + foreach (array_chunk($table->unmatched(), $this->batchSize) as $unmatched) { + yield $this->type === Join::left + ? $this->merge( + $build->gather($unmatched), + $nullRight->gather(array_fill(0, count($unmatched), 0)), + )->project($outputSchema) + : $build->gather($unmatched)->project($outputSchema); } + } + } - if ($pending !== []) { - yield (new RowsBuilder($outputSchema, $this->backend)) - ->appendRows($pending) - ->finish(); - } + /** + * @param list $leftIndices + * @param list $rightIndices + * + * @return list + */ + private function meet(Rows $left, array $leftIndices, Rows $right, array $rightIndices): array + { + if ($leftIndices === []) { + return []; } + + $names = static fn(array $refs): array => array_values(array_unique(array_map( + static fn(Reference $ref): string => $ref->base(), + $refs, + ))); + + return $this->expression->meet( + $left->project($left->schema()->keep(...$names($this->expression->left())))->gather($leftIndices), + $right->project($right->schema()->keep(...$names($this->expression->right())))->gather($rightIndices), + ); } /** - * @return array + * @throws DuplicatedEntriesException */ - private function merge(Row $left, Row $right): array + private function merge(Rows $left, Rows $right): Rows { try { return $this->merger->merge($left, $right); @@ -300,4 +325,22 @@ private function merge(Row $left, Row $right): array ); } } + + private function padded(Rows $build, ?Rows $nullRow, Schema $schema): Rows + { + $null = $nullRow ?? (new NullRowBuilder($schema))->rows(); + + return $build->withSchema($null->schema())->concat($null); + } + + private function table(Rows $build, KeyValues $values, bool $trackUnmatched): HashTable + { + $table = new HashTable(trackUnmatched: $trackUnmatched); + + foreach ($this->hasher->hash($values->of($build)) as $index => $hash) { + $table->add($hash, $index); + } + + return $table; + } } diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php index f456fc286f..f02b581ab9 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php @@ -4,30 +4,29 @@ namespace Flow\ETL\Join\HashJoin; -use Flow\ETL\Column\PhpBackend; -use Flow\ETL\Row; +use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Rows; use Flow\ETL\Schema; final readonly class NullRowBuilder { - private Row $row; + private Rows $rows; public function __construct(Schema $schema) { $nullable = $schema->makeNullable(); - $backend = new PhpBackend(); + $backend = new DefaultBackend(); $columns = []; foreach ($nullable->definitions() as $name => $definition) { $columns[$name] = $backend->constant($definition, null, 1); } - $this->row = Rows::fromColumns($nullable, $columns, 1)->row(0); + $this->rows = Rows::fromColumns($nullable, $columns, 1); } - public function row(): Row + public function rows(): Rows { - return $this->row; + return $this->rows; } } diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/RowMerger.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/RowMerger.php index 3e9a7b0d55..f4a0307480 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/RowMerger.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/RowMerger.php @@ -5,7 +5,8 @@ namespace Flow\ETL\Join\HashJoin; use Flow\ETL\Exception\DuplicatedEntriesException; -use Flow\ETL\Row; +use Flow\ETL\Rows; +use Flow\ETL\Schema; use function array_key_exists; use function array_keys; @@ -55,39 +56,46 @@ public function __construct( } /** - * @throws DuplicatedEntriesException + * Pair-aligned: row i of the result is left row i merged with right row i. * - * @return array + * @throws DuplicatedEntriesException */ - public function merge(Row $left, Row $right): array + public function merge(Rows $left, Rows $right): Rows { - $leftValues = $left->values(); - $rightValues = $right->values(); + $leftNames = array_keys($left->schema()->definitions()); + $rightNames = array_keys($right->schema()->definitions()); - $planKey = implode("\x00", array_keys($leftValues)) . "\x01" . implode("\x00", array_keys($rightValues)); + $planKey = implode("\x00", $leftNames) . "\x01" . implode("\x00", $rightNames); - [$keepLeft, $keepRight, $renames] = - $this->plans[$planKey] ??= $this->plan(array_keys($leftValues), array_keys($rightValues)); + [$keepLeft, $keepRight, $renames] = $this->plans[$planKey] ??= $this->plan($leftNames, $rightNames); - $values = []; + $definitions = []; + $columns = []; - // @mago-ignore analysis:mixed-assignment - foreach ($leftValues as $name => $value) { + foreach ($left->schema()->definitions() as $name => $definition) { if (array_key_exists($name, $keepLeft)) { - $values[$name] = $value; + $definitions[] = $definition; + $columns[$name] = $left->column($name); } } - // @mago-ignore analysis:mixed-assignment - foreach ($rightValues as $name => $value) { + foreach ($right->schema()->definitions() as $name => $definition) { if (!array_key_exists($name, $keepRight)) { continue; } - $values[$renames[$name] ?? $name] = $value; + if (array_key_exists($name, $renames)) { + $definitions[] = $definition->rename($renames[$name]); + $columns[$renames[$name]] = $right->column($name); + + continue; + } + + $definitions[] = $definition; + $columns[$name] = $right->column($name); } - return $values; + return Rows::fromColumns(new Schema(...$definitions), $columns, $left->count()); } /** diff --git a/src/core/etl/src/Flow/ETL/Join/JoinSteps.php b/src/core/etl/src/Flow/ETL/Join/JoinSteps.php index 5c6dff210e..9d6e9c0cef 100644 --- a/src/core/etl/src/Flow/ETL/Join/JoinSteps.php +++ b/src/core/etl/src/Flow/ETL/Join/JoinSteps.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Join; use Flow\ETL\Bucketing\Buckets; +use Flow\ETL\Bucketing\Storage\SpillingBuckets; use Flow\ETL\Config; use Flow\ETL\Config\Join\JoinAlgorithmBuilder; use Flow\ETL\Executor\PhysicalPlan; @@ -34,9 +35,10 @@ public static function of( $config->executor(), $on, $type, - new Buckets($join->bucketing->storage), - new Buckets($join->bucketing->storage), + new Buckets(SpillingBuckets::around($join->bucketing, $join->memoryLimit, $config->backend())), + new Buckets(SpillingBuckets::around($join->bucketing, $join->memoryLimit, $config->backend())), $config->randomValueGenerator(), + $join->memoryLimit, $join->bucketing->bucketsCount, $join->bucketing->batchSize, ), diff --git a/src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineSortAndLimit.php b/src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineSortAndLimit.php index 63c8530cc3..e0d2999512 100644 --- a/src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineSortAndLimit.php +++ b/src/core/etl/src/Flow/ETL/Optimizer/Rule/CombineSortAndLimit.php @@ -20,6 +20,6 @@ { public function apply(LogicalPlan $plan, FlowContext $context): LogicalPlan { - return $plan->transformUp(new TopNRewrite($context)); + return $plan->transformUp(new TopNRewrite()); } } diff --git a/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php b/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php index f6778ad354..2beb7e7720 100644 --- a/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php +++ b/src/core/etl/src/Flow/ETL/Optimizer/TopNRewrite.php @@ -4,8 +4,6 @@ namespace Flow\ETL\Optimizer; -use Flow\ETL\Config\Sort\ExternalSortConfig; -use Flow\ETL\FlowContext; use Flow\ETL\Plan\Node; use Flow\ETL\Plan\Node\Limit; use Flow\ETL\Plan\Node\Sort; @@ -17,10 +15,6 @@ */ final readonly class TopNRewrite implements Rewrite { - public function __construct( - private FlowContext $context, - ) {} - public function of(Node $node): Node { if (!$node instanceof Limit) { @@ -33,14 +27,7 @@ public function of(Node $node): Node return $node; } - $config = $this->context->config; - $algorithm = - $sort->algorithm?->build($config->cache->localFilesystemCacheDir, $config->backend()) ?? $config->sort; - - if ($algorithm instanceof ExternalSortConfig && $node->limit > $algorithm->runSize) { - return $node; - } - - return new TopN($sort->children()[0], $sort->refs, $node->limit); + // a TopN past its memory limit falls back to the sort's own spilling path, so any limit is safe to rewrite + return new TopN($sort->children()[0], $sort->refs, $node->limit, $sort->algorithm); } } diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/StepDetails.php b/src/core/etl/src/Flow/ETL/Plan/Explain/StepDetails.php index 26ad2c6fd6..9fa1e97900 100644 --- a/src/core/etl/src/Flow/ETL/Plan/Explain/StepDetails.php +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/StepDetails.php @@ -4,12 +4,13 @@ namespace Flow\ETL\Plan\Explain; +use Flow\ETL\Bucketing\BucketsStorage; +use Flow\ETL\Bucketing\Storage\SpillingBuckets; use Flow\ETL\Extractor; use Flow\ETL\Loader; use Flow\ETL\Processor; use Flow\ETL\Processor\BatchingByProcessor; use Flow\ETL\Processor\BatchingProcessor; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\CachingProcessor; use Flow\ETL\Processor\CollectingProcessor; use Flow\ETL\Processor\ConstrainedProcessor; @@ -22,6 +23,7 @@ use Flow\ETL\Processor\RepartitionProcessor; use Flow\ETL\Processor\TopNProcessor; use Flow\ETL\Processor\WindowProcessor; +use Flow\ETL\Row\NullsOrder; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; use Flow\ETL\Row\SortOrder; @@ -31,6 +33,7 @@ use function array_map; use function implode; +use function strtolower; final readonly class StepDetails { @@ -74,17 +77,19 @@ public function settings(Extractor|Loader|Processor|Transformer $step): array ? ['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, + 'Sort: ' . $this->sort($step->sort->refs), + 'Memory: ' . $step->sort->memoryLimit->inMb() . ' MB', + 'Spill: ' . $this->details->name($step->sort->spill->storage()), + 'Merge: ' . $step->sort->mergeFanIn . ' ways', + 'Batch: ' . $step->sort->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()), + 'Memory: ' . $step->memoryLimit->inMb() . ' MB', + 'Storage: ' . $this->storageName($step->buckets->storage()), 'Batch: ' . $step->batchSize, ], $step instanceof PivotProcessor => $this->pivot($step), @@ -92,11 +97,8 @@ public function settings(Extractor|Loader|Processor|Transformer $step): array $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()), + 'Memory: ' . $step->memoryLimit->inMb() . ' MB', + 'Storage: ' . $this->storageName($step->buckets->storage()), ], $step instanceof BatchingProcessor => ['Batch: ' . $step->size], $step instanceof BatchingByProcessor => $this->batchingBy($step), @@ -138,7 +140,7 @@ public function hashJoin(HashJoinProcessor $join): array return [ ...$lines, - 'Storage: ' . $this->details->name($join->rightBuckets->storage()), + ...$this->storage($join->rightBuckets->storage()), 'Buckets: ' . $join->bucketsCount, 'Batch: ' . $join->batchSize, ]; @@ -215,11 +217,35 @@ public function columns(References $refs): string return implode(', ', array_map(static fn(Reference $ref): string => $ref->name(), $refs->all())); } + /** + * @return list the configured storage, and the memory limit it stands behind + */ + public function storage(BucketsStorage $storage): array + { + return ( + $storage instanceof SpillingBuckets + ? ['Storage: ' . $this->storageName($storage), 'Memory: ' . $storage->memoryLimit->inMb() . ' MB'] + : ['Storage: ' . $this->storageName($storage)] + ); + } + + public function storageName(BucketsStorage $storage): string + { + return $this->details->name($storage instanceof SpillingBuckets ? $storage->disk : $storage); + } + public function sort(References $refs): string { return implode(', ', array_map( static fn(Reference $ref): string => ( - $ref->name() . ' ' . ($ref->sort() === SortOrder::ASC ? 'asc' : 'desc') + $ref->name() + . ' ' + . ($ref->sort() === SortOrder::ASC ? 'asc' : 'desc') + . ( + $ref->nulls() === NullsOrder::defaultFor($ref->sort()) + ? '' + : ' nulls ' . strtolower($ref->nulls()->name) + ) ), $refs->all(), )); diff --git a/src/core/etl/src/Flow/ETL/Plan/Node/TopN.php b/src/core/etl/src/Flow/ETL/Plan/Node/TopN.php index f54dee43a5..3af8e47b00 100644 --- a/src/core/etl/src/Flow/ETL/Plan/Node/TopN.php +++ b/src/core/etl/src/Flow/ETL/Plan/Node/TopN.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Plan\Node; +use Flow\ETL\Config\Sort\SortAlgorithmBuilder; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Plan\Materialization; use Flow\ETL\Plan\Node; @@ -25,6 +26,7 @@ public function __construct( private Node $input, public References $refs, public int $limit, + public ?SortAlgorithmBuilder $algorithm = null, ) { if ($this->limit < 1) { throw new InvalidArgumentException('TopN limit must be greater than 0, given: ' . $this->limit); @@ -41,7 +43,9 @@ public function children(): array public function withChildren(array $children): self { - return $children[0] === $this->input ? $this : new self($children[0], $this->refs, $this->limit); + return $children[0] === $this->input + ? $this + : new self($children[0], $this->refs, $this->limit, $this->algorithm); } public function rowCount(): RowCount diff --git a/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php b/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php index 354deaf9cb..eaab7e1459 100644 --- a/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php +++ b/src/core/etl/src/Flow/ETL/Planner/NodeTranslator.php @@ -103,7 +103,11 @@ public static function toSteps(Node $node, FlowContext $context, array $frames): $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\TopN => [new TopNProcessor( + $node->refs, + $node->limit, + SortSteps::external($node->refs, $context->config, $node->algorithm), + )], $node instanceof Node\Transform => [ $node->transformer instanceof Stateful ? $node->transformer->fresh() : $node->transformer, ], diff --git a/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php index 5bb915a52b..b202700e3c 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php @@ -5,17 +5,17 @@ namespace Flow\ETL\Processor; use Flow\ETL\BoundStep; +use Flow\ETL\Column\ComparableValues; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; use Flow\ETL\Processor; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; -use function count; +use function array_slice; /** * Groups rows into batches by column value. @@ -52,49 +52,69 @@ public function bind(Schema $input): BoundStep */ public function process(Generator $rows, FlowContext $context): Generator { - /** @var array $buffer */ - $buffer = []; + /** @var list $parts */ + $parts = []; + $buffered = 0; $currentValue = null; $hasValue = false; + $comparable = new ComparableValues(); $schema = null; while ($rows->valid()) { - $batch = $rows->current(); - $schema ??= $batch->schema(); + $schema ??= $rows->current()->schema(); + $batch = $rows->current()->matchTo($schema); + $start = 0; - foreach ($batch as $row) { - $value = $row->get($this->column); + if ($batch->isEmpty()) { + $rows->next(); + continue; + } + + // @mago-ignore analysis:mixed-assignment + foreach ($comparable->equality($batch->column($this->column->base())) as $i => $value) { if (!$hasValue) { + // @mago-ignore analysis:mixed-assignment $currentValue = $value; $hasValue = true; } if ($value !== $currentValue) { - if ($this->minSize === null || count($buffer) >= $this->minSize) { - if ($buffer !== []) { - $signal = yield Rows::of($schema, ...$buffer); + $size = $buffered + $i - $start; + + if (($this->minSize === null || $size >= $this->minSize) && $size > 0) { + if ($i > $start) { + $parts[] = $batch->slice($start, $i - $start); + } - if ($signal === Signal::STOP) { - $rows->send(Signal::STOP); + $signal = yield $parts[0]->concat(...array_slice($parts, 1)); - return; - } + if ($signal === Signal::STOP) { + $rows->send(Signal::STOP); - $buffer = []; + return; } + + $parts = []; + $buffered = 0; + $start = $i; } + + // @mago-ignore analysis:mixed-assignment $currentValue = $value; } + } - $buffer[] = $row; + if ($start < $batch->count()) { + $parts[] = $batch->slice($start, $batch->count() - $start); + $buffered += $batch->count() - $start; } $rows->next(); } - if ($buffer !== []) { - yield Rows::of($schema ?? new Schema(), ...$buffer); + if ($parts !== []) { + yield $parts[0]->concat(...array_slice($parts, 1)); } } } diff --git a/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php index 8d607c739d..cbf8cd43ff 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php @@ -9,14 +9,10 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; use Flow\ETL\Processor; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; -use function array_splice; -use function count; - /** * Re-batches rows into fixed-size batches. */ @@ -48,37 +44,34 @@ public function bind(Schema $input): BoundStep */ public function process(Generator $rows, FlowContext $context): Generator { - /** @var array $buffer */ - $buffer = []; - + $pending = null; $schema = null; while ($rows->valid()) { $batch = $rows->current(); $schema ??= $batch->schema(); - foreach ($batch as $row) { - $buffer[] = $row; + if (!$batch->isEmpty()) { + $pending = $pending === null ? $batch->matchTo($schema) : $pending->concat($batch->matchTo($schema)); - if (count($buffer) >= $this->size) { - $chunk = array_splice($buffer, 0, $this->size); - $signal = yield Rows::of($schema, ...$chunk); + while ($pending->count() >= $this->size) { + $signal = yield $pending->slice(0, $this->size); if ($signal === Signal::STOP) { $rows->send(Signal::STOP); return; } + + $pending = $pending->drop($this->size); } } $rows->next(); } - if ($buffer !== []) { - $schema ??= new Schema(); - - yield Rows::of($schema, ...$buffer); + if ($pending !== null && !$pending->isEmpty()) { + yield $pending; } } } diff --git a/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php deleted file mode 100644 index bfccdd1522..0000000000 --- a/src/core/etl/src/Flow/ETL/Processor/BucketingProcessor.php +++ /dev/null @@ -1,42 +0,0 @@ - $rows - * - * @return Generator - */ - public function process(Generator $rows, FlowContext $context): Generator - { - foreach ($this->strategy->bucketize($rows, $this->buckets->storage()) as $bucket) { - $this->buckets->add($bucket); - - yield Rows::of(Bucket::schema(), $bucket->toRow()); - } - } - - public function bind(Schema $input): BoundStep - { - return new BoundStep($this, $input); - } -} diff --git a/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php index 0ffea693c8..1ad082340c 100644 --- a/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php @@ -37,6 +37,6 @@ public function process(Generator $rows, FlowContext $context): Generator $collected = $collected === null ? $batch : $collected->merge($batch); } - yield $collected ?? Rows::of($this->declared ?? new Schema()); + yield $collected ?? Rows::empty($this->declared ?? new Schema()); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/ConstrainedProcessor.php b/src/core/etl/src/Flow/ETL/Processor/ConstrainedProcessor.php index b820ec1bcb..7d72c94316 100644 --- a/src/core/etl/src/Flow/ETL/Processor/ConstrainedProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/ConstrainedProcessor.php @@ -54,20 +54,32 @@ public function process(Generator $rows, FlowContext $context): Generator /** @var Rows $batch */ $batch = $rows->current(); - foreach ($batch->all() as $row) { - foreach ($this->constraints as $constraint) { - if (!$constraint->isSatisfiedBy($row, $batch->schema())) { - throw new ConstraintViolationException( - $constraint->toString(), - $constraint->violation($row, $batch->schema()), - $this->rowIndex, - ); - } + $violationIndex = null; + $violated = null; + + // a constraint sees only the rows before the earliest violation found so far - the row-by-row order + // in which an earlier constraint's violation stops the later ones + foreach ($this->constraints as $constraint) { + $index = $constraint->firstViolation( + $violationIndex === null ? $batch : $batch->slice(0, $violationIndex), + ); + + if ($index !== null) { + $violationIndex = $index; + $violated = $constraint; } + } - $this->rowIndex++; + if ($violated !== null && $violationIndex !== null) { + throw new ConstraintViolationException( + $violated->toString(), + $violated->violation($batch, $violationIndex), + $this->rowIndex + $violationIndex, + ); } + $this->rowIndex += $batch->count(); + $signal = yield $batch; if ($signal === Signal::STOP) { diff --git a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php index 0dd23bc0b7..2aed7fef40 100644 --- a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php @@ -6,12 +6,16 @@ use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\BucketShape; +use Flow\ETL\Bucketing\HashBucketing; +use Flow\ETL\Dataset\Memory\BoundedRead; +use Flow\ETL\Dataset\Memory\MemoryBudget; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\FlowContext; use Flow\ETL\GroupBy; -use Flow\ETL\GroupBy\BucketAggregation; +use Flow\ETL\GroupBy\AggregatedGroups; +use Flow\ETL\GroupBy\Group; use Flow\ETL\GroupBy\GroupByShape; use Flow\ETL\GroupBy\GroupKey; use Flow\ETL\Processor; @@ -20,8 +24,13 @@ use Flow\ETL\Schema; use Generator; +use function array_values; +use function iterator_to_array; + /** - * Aggregates buckets spilled by BucketingProcessor, one bucket per incoming metadata Row. + * Aggregates in one pass while the process stays under the memory limit. Past it, the rest of the stream is partitioned + * into buckets and each bucket aggregated on its own; the groups aggregated before the limit are merged into the bucket + * their key hashes to. */ final class GroupByAggregationProcessor implements Processor { @@ -36,7 +45,9 @@ final class GroupByAggregationProcessor implements Processor */ public function __construct( public readonly GroupBy $groupBy, + public readonly HashBucketing $bucketing, public readonly Buckets $buckets, + public readonly Unit $memoryLimit, public readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand @@ -51,7 +62,7 @@ public function __construct( */ public function bind(Schema $input): BoundStep { - $bound = new self($this->groupBy, $this->buckets, $this->batchSize); + $bound = new self($this->groupBy, $this->bucketing, $this->buckets, $this->memoryLimit, $this->batchSize); $bound->shape = GroupByShape::of($this->groupBy, $input); return new BoundStep($bound, $bound->shape->output); @@ -64,42 +75,106 @@ public function bind(Schema $input): BoundStep */ public function process(Generator $rows, FlowContext $context): Generator { - $aggregation = new BucketAggregation($this->batchSize); - $emitted = false; + $shape = $this->shape; + $groups = null; + $budget = new MemoryBudget($context->backend(), $this->memoryLimit); + $spilling = false; try { - foreach ($rows as $metadata) { - foreach ($metadata as $row) { - /** @var string $bucketId */ - $bucketId = $row->get(BucketShape::id->value); - $bucket = $this->buckets->rows($bucketId); - - $aggregated = $this->shape === null - ? $aggregation->aggregate($bucket, $context, $this->groupBy) - : $aggregation->aggregateBound($bucket, $context, $this->groupBy, $this->shape); - - // re-key batches, yield from would restart keys at 0 for every bucket - foreach ($aggregated as $aggregatedBatch) { - $emitted = true; - - yield $aggregatedBatch; - } + while ($rows->valid()) { + /** @var Rows $batch valid() holds, so current() is a batch */ + $batch = $rows->current(); + $rows->next(); + + if ($batch->isEmpty()) { + continue; } + + $shape ??= GroupByShape::of($this->groupBy, $batch->schema()); + $groups ??= new AggregatedGroups($this->groupBy, $shape); + $groups->accumulate($batch, $context); + + if ($budget->exceeded()) { + $spilling = true; + + break; + } + } + + if ($spilling && $groups !== null && $shape !== null) { + yield from $this->spilled($groups, $shape, $rows, $context); + + return; + } + + if ($groups !== null) { + yield from $groups->flush($this->batchSize, $context); + + return; } // SQL's scalar aggregate: no input and no grouping key is one row of the initial accumulators, // not no row. Only reachable bound - an unbound plan has no schema to type the defaults with. - if (!$emitted && $this->shape !== null && $this->groupBy->isGlobal()) { - yield (new RowsBuilder($this->shape->output, $context->backend()))->appendRows([ - $this->groupBy->aggregatedValues( - new GroupKey([]), - $this->shape->aggregators->cloned(), - $this->shape->output, - ), + if ($shape !== null && $this->groupBy->isGlobal()) { + yield (new RowsBuilder($shape->output, $context->backend()))->appendRows([ + $this->groupBy->aggregatedValues(new GroupKey([]), $shape->aggregators->cloned(), $shape->output), ])->finish(); } } finally { $this->buckets->clear(); } } + + /** + * @param Generator $rest the stream after the batch that passed the limit + * + * @return Generator + */ + public function spilled( + AggregatedGroups $earlier, + GroupByShape $shape, + Generator $rest, + FlowContext $context, + ): Generator { + foreach ($this->bucketing->bucketize( + (new BoundedRead($this->memoryLimit, $context->backend()))->followedBy([], $rest), + $this->buckets->storage(), + ) as $bucket) { + $this->buckets->add($bucket); + } + + /** @var array> $partials */ + $partials = []; + + foreach ($earlier->groups() as $key => $group) { + $partials[$this->bucketing->indexOf(array_values(iterator_to_array($group->key)))][$key] = $group; + } + + foreach ($this->buckets->all() as $bucket) { + $groups = new AggregatedGroups($this->groupBy, $shape); + + foreach ($this->buckets->rows($bucket->id) as $batch) { + $groups->accumulate($batch, $context); + } + + foreach ($partials[$bucket->index] ?? [] as $key => $group) { + $groups->absorbEarlier($key, $group, $context); + } + + unset($partials[$bucket->index]); + + yield from $groups->flush($this->batchSize, $context); + } + + // groups whose bucket received no row after the limit + $remaining = new AggregatedGroups($this->groupBy, $shape); + + foreach ($partials as $groups) { + foreach ($groups as $key => $group) { + $remaining->absorbEarlier($key, $group, $context); + } + } + + yield from $remaining->flush($this->batchSize, $context); + } } diff --git a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php index 3026cc11e1..fe589f1712 100644 --- a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php @@ -11,6 +11,8 @@ use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\ResidentBucketsStorage; use Flow\ETL\Bucketing\SingleBucketHasher; +use Flow\ETL\Dataset\Memory\BoundedRead; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\DuplicatedEntriesException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\JoinException; @@ -33,8 +35,10 @@ use Flow\ETL\Schema; use Generator; +use function array_diff_key; use function array_intersect_key; use function array_keys; +use function range; final class HashJoinProcessor implements Processor { @@ -58,6 +62,7 @@ public function __construct( public readonly Buckets $leftBuckets, public readonly Buckets $rightBuckets, private readonly RandomValueGenerator $random, + public readonly Unit $memoryLimit, public readonly int $bucketsCount = 64, public readonly int $batchSize = 1000, ) { @@ -86,6 +91,7 @@ public function bind(Schema $input): BoundStep $this->leftBuckets, $this->rightBuckets, $this->random, + $this->memoryLimit, $this->bucketsCount, $this->batchSize, ); @@ -119,7 +125,7 @@ public function process(Generator $rows, FlowContext $context): Generator } } - $joiner = new Joiner($this->expression, $this->type, $context->backend(), $this->batchSize); + $joiner = new Joiner($this->expression, $this->type, $this->batchSize); $equalityKeys = $joiner->keys(); $resident = $this->rightBuckets->storage() instanceof ResidentBucketsStorage; @@ -131,15 +137,31 @@ public function process(Generator $rows, FlowContext $context): Generator $equalityKeys !== null && $this->type !== Join::right ? $equalityKeys->rightRefs() : null, ); - $this->bucketize( - $rightRows, - $this->rightBuckets, - $equalityKeys !== null && !$resident ? $equalityKeys->rightRefs() : null, - 'join-right', - ); + /** @var null|list $held the build side, when all of it fits under the memory limit */ + $held = null; + + if (!$resident) { + $bounded = new BoundedRead($this->memoryLimit, $context->backend()); + [$read, $fits] = $bounded->read($rightRows); + + if ($fits) { + $held = $read; + } else { + $rightRows = $bounded->followedBy($read, $rightRows); + } + } + + if ($held === null) { + $this->bucketize( + $rightRows, + $this->rightBuckets, + $equalityKeys !== null && !$resident ? $equalityKeys->rightRefs() : null, + 'join-right', + ); + } $nullRightRow = $this->type === Join::left - ? (new NullRowBuilder($rightSchema ?? new Schema()))->row() + ? (new NullRowBuilder($rightSchema ?? new Schema()))->rows() : null; $leftRows = $this->tap( @@ -151,13 +173,20 @@ public function process(Generator $rows, FlowContext $context): Generator : null, ); - if ($resident) { + if ($resident || $held !== null) { $rightBucket = $this->rightBuckets->all()[0] ?? null; $joinedBatches = $joiner->join( JoinSide::of($leftRows, null, $leftSchema), JoinSide::of( - $rightBucket === null ? self::noRows() : $this->rightBuckets->rows($rightBucket->id), + match (true) { + $held !== null => (new BoundedRead($this->memoryLimit, $context->backend()))->followedBy( + $held, + self::noRows(), + ), + $rightBucket === null => self::noRows(), + default => $this->rightBuckets->rows($rightBucket->id), + }, $nullRightRow, $rightSchema, ), @@ -183,7 +212,7 @@ public function process(Generator $rows, FlowContext $context): Generator // only the bucketized path builds it here, the resident path above derives the null-left // row inside the Joiner while streaming $nullLeftRow = $this->type === Join::right - ? (new NullRowBuilder($leftSchema ?? new Schema()))->row() + ? (new NullRowBuilder($leftSchema ?? new Schema()))->rows() : null; foreach ($this->bucketPairs() as [$leftBucket, $rightBucket]) { @@ -287,19 +316,29 @@ private function tap(Generator $rows, ?Schema &$schema, ?array $dropNullKeyRefs) $schema ??= $batch->schema(); if ($dropNullKeyRefs !== null) { - $kept = []; + if ($batch->isEmpty()) { + continue; + } - foreach ($batch->all() as $row) { - foreach ($dropNullKeyRefs as $ref) { - if ($row->get($ref) === null) { - continue 2; - } + $null = []; + + foreach ($dropNullKeyRefs as $ref) { + $column = $batch->column($ref->base()); + + if ($column->nullCount() === 0) { + continue; } - $kept[] = $row; + for ($i = 0, $count = $column->count(); $i < $count; $i++) { + if ($column->isNull($i)) { + $null[$i] = true; + } + } } - $batch = Rows::of($batch->schema(), ...$kept); + if ($null !== []) { + $batch = $batch->gather(array_keys(array_diff_key(range(0, $batch->count() - 1), $null))); + } if ($batch->isEmpty()) { continue; diff --git a/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php b/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php index fef523e3b0..30c965fd5d 100644 --- a/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php @@ -7,12 +7,12 @@ use Flow\ETL\BoundStep; use Flow\ETL\FlowContext; use Flow\ETL\Processor; -use Flow\ETL\Row; use Flow\ETL\Row\References; use Flow\ETL\Rows; use Flow\ETL\Schema; use Generator; +use function array_slice; use function max; /** @@ -28,7 +28,7 @@ public function __construct( public function process(Generator $rows, FlowContext $context): Generator { - /** @var array $buffer */ + /** @var list $buffer */ $buffer = []; $maxSize = 1; @@ -41,15 +41,14 @@ public function process(Generator $rows, FlowContext $context): Generator } $maxSize = max($batch->count(), $maxSize); - - foreach ($batch->all() as $row) { - $buffer[] = $row; - } + $buffer[] = $batch->matchTo($this->declared ?? $schema); } - yield from Rows::of($this->declared ?? $schema ?? new Schema(), ...$buffer)->sortBy( - ...$this->refs->all(), - )->chunks($maxSize); + $all = $buffer === [] + ? Rows::empty($this->declared ?? $schema ?? new Schema()) + : $buffer[0]->concat(...array_slice($buffer, 1)); + + yield from $all->sortBy(...$this->refs->all())->chunks($maxSize); } public function bind(Schema $input): BoundStep diff --git a/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php b/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php index d7c53b4f4f..3095129018 100644 --- a/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/MergeSortProcessor.php @@ -5,49 +5,17 @@ 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\Processor; -use Flow\ETL\RandomValueGenerator; -use Flow\ETL\Row\References; use Flow\ETL\Schema; -use Flow\ETL\Sort\Merge\KWayMerge; +use Flow\ETL\Sort\ExternalSort; use Generator; -use function array_slice; -use function array_splice; -use function count; - -final class MergeSortProcessor implements Processor +final readonly class MergeSortProcessor implements Processor { - /** - * @param int<1, max> $mergeFanIn - * @param int<1, max> $batchSize - */ public function __construct( - public readonly References $refs, - public readonly Buckets $spill, - public readonly Buckets $merge, - private readonly RandomValueGenerator $random, - public readonly int $mergeFanIn = 10, - public readonly int $batchSize = 1000, - ) { - // @mago-ignore analysis:invalid-operand - // @mago-ignore analysis:impossible-condition,redundant-comparison - if ($this->mergeFanIn < 1) { - throw new InvalidArgumentException('Merge fan-in must be greater than 0, given: ' . $this->mergeFanIn); - } - - // @mago-ignore analysis:invalid-operand - // @mago-ignore analysis:impossible-condition,redundant-comparison - if ($this->batchSize < 1) { - throw new InvalidArgumentException('Batch size must be greater than 0, given: ' . $this->batchSize); - } - } + public ExternalSort $sort, + ) {} public function bind(Schema $input): BoundStep { @@ -56,62 +24,6 @@ public function bind(Schema $input): BoundStep public function process(Generator $rows, FlowContext $context): Generator { - /** @var list $runs */ - $runs = []; - - try { - // draining upstream inside the try is what makes a mid-stream failure release the spilled runs - foreach ($rows as $batch) { - foreach ($batch as $row) { - /** @var string $bucketId */ - $bucketId = $row->get(BucketShape::id->value); - $runs[] = new BucketRun($bucketId, $this->spill); - } - } - - $merger = new KWayMerge($this->refs, $context->backend(), $this->batchSize); - $mergedIndex = 0; - - while (count($runs) > $this->mergeFanIn) { - $runs[] = $this->reduce(array_slice($runs, 0, $this->mergeFanIn), $merger, $mergedIndex++); - array_splice($runs, 0, $this->mergeFanIn); - } - - yield from $merger->merge($runs); - } finally { - // nested, so a throwing spill clear still leaves the merge storage cleared - and chains as previous - try { - $this->spill->clear(); - } finally { - $this->merge->clear(); - } - } - } - - /** - * @param list $group - * - * @return BucketRun the merged run, bound to the merge storage that wrote it - */ - private function reduce(array $group, KWayMerge $merger, int $index): BucketRun - { - $bucketId = 'sort-merge-' . $this->random->string(16); - - // registered before the spill so clear() covers a partially written merged run - $this->merge->add(new Bucket($bucketId, 0, $index)); - $totalRows = 0; - - foreach ($merger->merge($group) as $batch) { - $this->merge->storage()->append($bucketId, $batch); - $totalRows += $batch->count(); - } - - foreach ($group as $run) { - $run->remove(); - } - - $this->merge->add(new Bucket($bucketId, $totalRows, $index)); - - return new BucketRun($bucketId, $this->merge); + yield from $this->sort->sort($rows, $context); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php b/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php index 660eb92d13..f9e39b1697 100644 --- a/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php @@ -6,11 +6,13 @@ use Flow\ETL\BoundStep; use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\BucketShape; +use Flow\ETL\Bucketing\HashBucketing; use Flow\ETL\Bucketing\Hasher; use Flow\ETL\Bucketing\KeyGrouping; use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; +use Flow\ETL\Dataset\Memory\BoundedRead; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\FlowContext; use Flow\ETL\Processor; use Flow\ETL\Row\References; @@ -18,16 +20,19 @@ use Flow\ETL\Schema; use Generator; -use function Flow\Types\DSL\type_string; +use function array_slice; /** - * Regroups buckets spilled by BucketingProcessor so every row sharing a key arrives in one batch. + * One batch per key. While the process stays under the memory limit the input is held and grouped in one pass; past + * it, the input is partitioned into buckets and each bucket grouped on its own. */ final readonly class RepartitionProcessor implements Processor { public function __construct( public References $by, + public HashBucketing $bucketing, public Buckets $buckets, + public Unit $memoryLimit, public Hasher $hasher = new NativeHasher(), ) {} @@ -39,16 +44,27 @@ public function __construct( public function process(Generator $rows, FlowContext $context): Generator { $grouping = new KeyGrouping(new KeyValues($this->by->all()), $this->hasher); + $bounded = new BoundedRead($this->memoryLimit, $context->backend()); + [$read, $fits] = $bounded->read($rows); try { - foreach ($rows as $metadata) { - foreach ($metadata as $row) { - $bucketId = type_string()->assert($row->get(BucketShape::id->value)); - - // re-key batches, yield from would restart keys at 0 for every bucket - foreach ($grouping->group($this->buckets->rows($bucketId)) as $group) { - yield $group; - } + if ($fits) { + yield from $grouping->group($this->concatenated($read)); + + return; + } + + foreach ($this->bucketing->bucketize( + $bounded->followedBy($read, $rows), + $this->buckets->storage(), + ) as $bucket) { + $this->buckets->add($bucket); + } + + foreach ($this->buckets->all() as $bucket) { + // re-key batches, yield from would restart keys at 0 for every bucket + foreach ($grouping->group($this->buckets->rows($bucket->id)) as $group) { + yield $group; } } } finally { @@ -60,4 +76,30 @@ public function bind(Schema $input): BoundStep { return new BoundStep($this, $input); } + + /** + * The held batches as one, so each key is gathered once rather than once per batch. + * + * @param list $batches + * + * @return Generator + */ + public function concatenated(array $batches): Generator + { + $parts = []; + $schema = null; + + foreach ($batches as $batch) { + if ($batch->isEmpty()) { + continue; + } + + $schema ??= $batch->schema(); + $parts[] = $batch->matchTo($schema); + } + + if ($parts !== []) { + yield $parts[0]->concat(...array_slice($parts, 1)); + } + } } diff --git a/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php b/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php index 92ed8cc5a1..534116ee4c 100644 --- a/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php @@ -5,16 +5,16 @@ namespace Flow\ETL\Processor; use Flow\ETL\BoundStep; +use Flow\ETL\Dataset\Memory\MemoryBudget; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; use Flow\ETL\Processor; -use Flow\ETL\Row; use Flow\ETL\Row\References; use Flow\ETL\Rows; use Flow\ETL\Schema; +use Flow\ETL\Sort\ExternalSort; use Generator; -use function count; use function max; /** @@ -30,6 +30,7 @@ public function __construct( public References $refs, public int $limit, + public ?ExternalSort $fallback = null, private ?Schema $declared = null, ) { if ($this->limit < 1) { @@ -39,17 +40,19 @@ public function __construct( public function bind(Schema $input): BoundStep { - return new BoundStep(new self($this->refs, $this->limit, $input), $input); + return new BoundStep(new self($this->refs, $this->limit, $this->fallback, $input), $input); } public function process(Generator $rows, FlowContext $context): Generator { - /** @var array $kept */ - $kept = []; + $kept = null; $maxSize = 1; $schema = null; + $budget = $this->fallback === null ? null : new MemoryBudget($context->backend(), $this->fallback->memoryLimit); - foreach ($rows as $batch) { + while ($rows->valid()) { + $batch = $rows->current(); + $rows->next(); $schema ??= $batch->schema(); if ($batch->isEmpty()) { @@ -57,31 +60,49 @@ public function process(Generator $rows, FlowContext $context): Generator } $maxSize = max($batch->count(), $maxSize); + $conformed = $batch->matchTo($this->declared ?? $schema); + $kept = $kept === null ? $conformed : $kept->concat($conformed); - foreach ($batch->all() as $row) { - $kept[] = $row; + // trimming only past twice the limit keeps the re-sorts amortised + if ($kept->count() > (2 * $this->limit)) { + $kept = $this->top($kept); } - // trimming only past twice the limit keeps the re-sorts amortised - if (count($kept) > (2 * $this->limit)) { - $kept = $this->top($kept, $schema); + // past the memory limit the kept rows and the rest of the stream go to the spilling sort; a trimmed row + // cannot be in the top $limit, so the result is the same + if ($this->fallback !== null && $budget?->exceeded()) { + yield from $this->fallback->sort($this->followedBy($kept, $rows), $context, $this->limit); + + return; } } - yield from Rows::of($this->declared ?? $schema ?? new Schema(), ...$this->top($kept, $schema))->chunks( - $maxSize, - ); + if ($kept === null) { + yield from Rows::empty($this->declared ?? $schema ?? new Schema())->chunks($maxSize); + + return; + } + + yield from $this->top($kept)->chunks($maxSize); } /** - * @param array $rows + * @param Generator $rest * - * @return array + * @return Generator */ - public function top(array $rows, ?Schema $schema): array + public function followedBy(Rows $kept, Generator $rest): Generator + { + yield $kept; + + // continues the half-read stream where it stopped; PHP refuses to yield from a generator that already finished + if ($rest->valid()) { + yield from $rest; + } + } + + public function top(Rows $rows): Rows { - return Rows::of($this->declared ?? $schema ?? new Schema(), ...$rows)->sortBy( - ...$this->refs->all(), - )->take($this->limit)->all(); + return $rows->sortBy(...$this->refs->all())->take($this->limit); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php b/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php index 64dba96775..118f14916d 100644 --- a/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php @@ -31,6 +31,6 @@ public function process(Generator $rows, FlowContext $context): Generator } // void() drops rows, not columns - yield Rows::of($this->declared ?? new Schema()); + yield Rows::empty($this->declared ?? new Schema()); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php b/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php index cb62ce6857..1441e28ee1 100644 --- a/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php @@ -5,9 +5,7 @@ namespace Flow\ETL\Processor; use Flow\ETL\BoundStep; -use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; -use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\FlowContext; use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\FrameAccumulating; @@ -15,7 +13,6 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\WindowFunction; use Flow\ETL\Processor; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; @@ -24,10 +21,7 @@ use Flow\ETL\Window\WindowFrame; use Generator; -use function array_values; -use function count; use function Flow\ETL\DSL\definition_from_type; -use function Flow\ETL\DSL\rows; /** * Applies window functions over partitioned and ordered data. @@ -58,14 +52,14 @@ public function process(Generator $rows, FlowContext $context): Generator $bound ??= $this->boundTo($batch->schema()); if (!$batch->count()) { - yield Rows::of($bound->output); + yield Rows::empty($bound->output); continue; } // one incoming batch is one partition: RepartitionSteps put every row sharing the // partition key into a single Rows before this processor ever sees it - yield $this->processPartition($bound, $batch->all(), $context); + yield $this->processPartition($bound, $batch, $context); } } @@ -95,12 +89,6 @@ private function boundTo(Schema $input): BoundWindow ); } - /** - * An order reference already failed loudly - sortBy() reaches Rows::sortDescending(), which throws - * on the first row of the first partition. Only the partition path degraded silently, because - * extractPartitionKey() substitutes null for a missing entry. This check makes both refuse - * identically, one batch earlier, with the gate's message. - */ private static function assertWindowReferences(WindowFunction $function, Schema $schema): void { $window = $function->window(); @@ -116,7 +104,7 @@ private static function assertWindowReferences(WindowFunction $function, Schema * Evaluates a frame-only window function for every row of the partition, reusing the previous * result whenever the frame bounds did not move. * - * @return array + * @return list */ private function accumulateValues( FrameAccumulating $function, @@ -124,10 +112,7 @@ private function accumulateValues( Rows $partition, FlowContext $context, ): array { - // Rows guarantees a list internally, but all() is typed array - narrow it here rather than - // widen the shared Rows contract. One copy per partition, not per row. - $rows = array_values($partition->all()); - $count = count($rows); + $count = $partition->count(); $values = []; $accumulator = null; $previousBounds = null; @@ -138,7 +123,7 @@ private function accumulateValues( $bounds = $frame->bounds($index, $partition); if ($bounds === $previousBounds) { - $values[$index] = $value; + $values[] = $value; continue; } @@ -152,39 +137,37 @@ private function accumulateValues( && $bounds[1] > $previousBounds[1] ) { for ($i = $previousBounds[1] + 1; $i <= $bounds[1]; $i++) { - $accumulator->accumulate($rows[$i]); + $accumulator->accumulate($partition, $i); } } else { $accumulator = $function->accumulator($context); for ($i = $bounds[0]; $i <= $bounds[1]; $i++) { - $accumulator->accumulate($rows[$i]); + $accumulator->accumulate($partition, $i); } } - // @mago-ignore analysis:mixed-assignment $value = $accumulator->value(); $previousBounds = $bounds; - $values[$index] = $value; + $values[] = $value; } return $values; } /** - * @param array $rows - never empty; process() answers a zero-row batch from the bound schema + * @param Rows $partition never empty; process() answers a zero-row batch from the bound schema */ - private function processPartition(BoundWindow $bound, array $rows, FlowContext $context): Rows + private function processPartition(BoundWindow $bound, Rows $partition, FlowContext $context): Rows { $resolved = $bound->resolved; $derived = $bound->derived; $window = $resolved->window(); $orderBy = $window->order(); $sortBy = $orderBy === [] ? $window->partitions()->all() : $orderBy; - $partitionRows = rows($bound->input, ...$rows)->sortBy(...$sortBy); + $partitionRows = $partition->matchTo($bound->input)->sortBy(...$sortBy); $frame = $window->frame(); - $builder = $context->backend()->builder($derived); $values = match (true) { $resolved instanceof PartitionRanking => $resolved->rankPartition($partitionRows), @@ -197,18 +180,17 @@ private function processPartition(BoundWindow $bound, array $rows, FlowContext $ default => null, }; - foreach ($partitionRows as $index => $row) { - $value = $values === null - ? $resolved->apply(new WindowContext($row, $index, $partitionRows, $frame, $context)) - : $values[$index]; + if ($values === null) { + $values = []; - try { - $builder->append($value === null ? null : $derived->type()->cast($value)); - } catch (ColumnMismatchException $e) { - throw new SchemaMismatchException($index, $e); + for ($index = 0, $count = $partitionRows->count(); $index < $count; $index++) { + $values[] = $resolved->apply(new WindowContext($index, $partitionRows, $frame, $context)); } } + $builder = $context->backend()->builder($derived); + $builder->appendMany($values); + return $partitionRows->withColumns($bound->output, [$derived->entry()->name() => $builder->finish()]); } } diff --git a/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php b/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php index 4e38044d69..3c6ba26992 100644 --- a/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php +++ b/src/core/etl/src/Flow/ETL/Repartition/RepartitionSteps.php @@ -7,10 +7,10 @@ use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\HashBucketing; use Flow\ETL\Bucketing\NativeHasher; +use Flow\ETL\Bucketing\Storage\SpillingBuckets; use Flow\ETL\Config; use Flow\ETL\Config\Repartition\RepartitionAlgorithmBuilder; use Flow\ETL\Processor; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\RepartitionProcessor; use Flow\ETL\Row\References; @@ -26,10 +26,15 @@ public static function of(References $by, Config $config, ?RepartitionAlgorithmB { $repartition = $algorithm?->build($config->cache->localFilesystemCacheDir, $config->backend()) ?? $config->repartition; - $buckets = new Buckets($repartition->bucketing->storage); + $buckets = new Buckets(SpillingBuckets::around( + $repartition->bucketing, + $repartition->memoryLimit, + $config->backend(), + )); return [ - new BucketingProcessor( + new RepartitionProcessor( + $by, new HashBucketing( $by->all(), $repartition->bucketing->bucketsCount, @@ -38,8 +43,8 @@ public static function of(References $by, Config $config, ?RepartitionAlgorithmB 'repartition', ), $buckets, + $repartition->memoryLimit, ), - new RepartitionProcessor($by, $buckets), ]; } } diff --git a/src/core/etl/src/Flow/ETL/Row.php b/src/core/etl/src/Flow/ETL/Row.php deleted file mode 100644 index 85e92082c8..0000000000 --- a/src/core/etl/src/Flow/ETL/Row.php +++ /dev/null @@ -1,108 +0,0 @@ -= $rows->count()) { - throw InvalidArgumentException::because( - 'Row %d does not exist in a batch of %d rows', - $index, - $rows->count(), - ); - } - } - - /** - * @throws InvalidArgumentException - * - * @return null|array|bool|float|int|object|string - */ - public function get(string|Reference $reference): mixed - { - // @mago-ignore analysis:mixed-return-statement - return $this->rows - ->column($reference instanceof Reference ? $reference->base() : $reference) - ->value($this->index); - } - - public function has(string|Reference ...$references): bool - { - foreach ($references as $reference) { - if ( - $this->rows->schema()->findDefinition($reference instanceof Reference ? $reference->base() : $reference) - === null - ) { - return false; - } - } - - return true; - } - - public function hash(Schema $schema, Algorithm $algorithm = new NativePHPHash()): string - { - $formatter = new TypedValueFormatter(); - $string = ''; - - foreach ($schema->sort()->definitions() as $definition) { - $name = $definition->entry()->name(); - $string .= $name . $formatter->format($definition->type(), $this->has($name) ? $this->get($name) : null); - } - - return $algorithm->hash($string); - } - - /** - * @return list - */ - public function names(): array - { - return array_values($this->rows->schema()->references()->names()); - } - - /** - * @return array - */ - public function toArray(bool $withKeys = true): array - { - $data = []; - - // @mago-ignore analysis:mixed-assignment - foreach ($this->values() as $name => $value) { - if ($value instanceof Json) { - $value = $value->toArray(); - } - - $withKeys ? ($data[$name] = $value) : ($data[] = $value); - } - - return $data; - } - - /** - * @return array - */ - public function values(): array - { - return $this->rows->values($this->index); - } -} diff --git a/src/core/etl/src/Flow/ETL/Row/Comparator.php b/src/core/etl/src/Flow/ETL/Row/Comparator.php deleted file mode 100644 index 7efb5c9d7e..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/Comparator.php +++ /dev/null @@ -1,13 +0,0 @@ -values()) !== array_keys($nextRow->values())) { - return false; - } - - $comparator = new TypedValueComparator(); - - foreach ($schema->definitions() as $definition) { - $name = $definition->entry()->name(); - - if (!$row->has($name) || !$nextRow->has($name)) { - continue; - } - - if (!$comparator->equals($definition->type(), $row->get($name), $nextRow->get($name))) { - return false; - } - } - - return true; - } -} diff --git a/src/core/etl/src/Flow/ETL/Row/NullsOrder.php b/src/core/etl/src/Flow/ETL/Row/NullsOrder.php new file mode 100644 index 0000000000..ea567f0848 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Row/NullsOrder.php @@ -0,0 +1,19 @@ +entry, $this->type, $alias, $this->sort); + return new self($this->entry, $this->type, $alias, $this->sort, $this->nulls); } - public function asc(): self + public function asc(NullsOrder $nulls = NullsOrder::FIRST): self { - return new self($this->entry, $this->type, $this->alias, SortOrder::ASC); + return new self($this->entry, $this->type, $this->alias, SortOrder::ASC, $nulls); } public function base(): string @@ -66,14 +68,14 @@ public function withChildren(array $children): static return $this; } - public function desc(): self + public function desc(NullsOrder $nulls = NullsOrder::LAST): self { - return new self($this->entry, $this->type, $this->alias, SortOrder::DESC); + return new self($this->entry, $this->type, $this->alias, SortOrder::DESC, $nulls); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - return $row->get($this->entry); + return $rows->column($this->base()); } public function hasAlias(): bool @@ -104,6 +106,11 @@ public function returns(): Type return $this->type; } + public function nulls(): NullsOrder + { + return $this->nulls; + } + public function sort(): SortOrder { return $this->sort; diff --git a/src/core/etl/src/Flow/ETL/Row/UnresolvedReference.php b/src/core/etl/src/Flow/ETL/Row/UnresolvedReference.php index 535e77675d..1e14517a89 100644 --- a/src/core/etl/src/Flow/ETL/Row/UnresolvedReference.php +++ b/src/core/etl/src/Flow/ETL/Row/UnresolvedReference.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Row; +use Flow\ETL\Column\Column; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\FlowContext; use Flow\ETL\Function\FunctionTree; @@ -11,7 +12,7 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\ScalarFunctionChain; use Flow\ETL\Function\StructureFunctions; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\ETL\Schema\Definition; use Flow\Types\Type; @@ -30,6 +31,7 @@ public function __construct( private readonly string $entry, private readonly ?string $alias = null, private readonly SortOrder $sort = SortOrder::ASC, + private readonly NullsOrder $nulls = NullsOrder::FIRST, ) {} public static function init(string|Reference $ref): Reference @@ -48,12 +50,12 @@ public function __toString(): string public function as(string $alias): self { - return new self($this->entry, $alias, $this->sort); + return new self($this->entry, $alias, $this->sort, $this->nulls); } - public function asc(): self + public function asc(NullsOrder $nulls = NullsOrder::FIRST): self { - return new self($this->entry, $this->alias, SortOrder::ASC); + return new self($this->entry, $this->alias, SortOrder::ASC, $nulls); } public function base(): string @@ -90,14 +92,14 @@ public function returns(): Type throw InvalidLogicException::because(self::UNRESOLVED, 'returns', $this->entry); } - public function desc(): self + public function desc(NullsOrder $nulls = NullsOrder::LAST): self { - return new self($this->entry, $this->alias, SortOrder::DESC); + return new self($this->entry, $this->alias, SortOrder::DESC, $nulls); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - return $row->get($this->entry); + throw InvalidLogicException::because(self::UNRESOLVED, 'eval', $this->entry); } public function hasAlias(): bool @@ -135,9 +137,15 @@ public function resolve(Definition $definition): ResolvedReference $definition->isNullable() ? type_optional($type) : $type, $this->alias, $this->sort, + $this->nulls, ); } + public function nulls(): NullsOrder + { + return $this->nulls; + } + public function sort(): SortOrder { return $this->sort; diff --git a/src/core/etl/src/Flow/ETL/Rows.php b/src/core/etl/src/Flow/ETL/Rows.php index 17bd56750c..e193f7e802 100644 --- a/src/core/etl/src/Flow/ETL/Rows.php +++ b/src/core/etl/src/Flow/ETL/Rows.php @@ -4,14 +4,12 @@ namespace Flow\ETL; -use ArrayAccess; -use ArrayIterator; use Countable; use Flow\ETL\Column\Column; use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Hash\Algorithm; use Flow\ETL\Hash\NativePHPHash; @@ -21,42 +19,37 @@ use Flow\ETL\Join\HashJoin\RowMerger; use Flow\ETL\Join\Join; use Flow\ETL\Join\JoinSchema; -use Flow\ETL\Row\Comparator; -use Flow\ETL\Row\Comparator\NativeComparator; use Flow\ETL\Row\Reference; -use Flow\ETL\Row\SortOrder; -use Flow\ETL\Rows\RowsBuilder; +use Flow\ETL\Row\UnresolvedReference; +use Flow\ETL\Rows\RowEquality; +use Flow\ETL\Rows\RowHashes; use Flow\ETL\Schema\Formatter\InlineSchemaFormatter; use Flow\ETL\Schema\SimilarNames; -use Flow\ETL\Sort\ValuesSorter; +use Flow\ETL\Sort\RowOrder; use Flow\Floe\FrameDecoder; use Flow\Floe\FrameEncoder; use Flow\Types\Exception\InvalidTypeException; +use Flow\Types\Value\Json; use Generator; -use Iterator; -use IteratorAggregate; use function array_diff_key; +use function array_fill; use function array_key_exists; use function array_keys; -use function array_map; -use function array_reverse; use function array_shift; +use function array_slice; use function array_values; use function count; use function Flow\Types\DSL\type_integer; use function implode; -use function is_int; +use function max; use function min; use function sprintf; /** * @type RowsPayload = array{schema: Schema, frame: string} - * - * @implements \ArrayAccess - * @implements \IteratorAggregate */ -final class Rows implements ArrayAccess, Countable, IteratorAggregate +final class Rows implements Countable { /** * @param array $columns keyed and ordered by $schema @@ -87,47 +80,16 @@ public function __unserialize(array $data): void $this->count = $rows->count; } - /** - * @throws SchemaMismatchException - */ - public static function of(Schema $schema, Row ...$rows): self + public static function empty(Schema $schema): self { - if ($rows === []) { - $backend = new DefaultBackend(); - $columns = []; - - foreach ($schema->definitions() as $name => $definition) { - $columns[$name] = $backend->builder($definition)->finish(); - } - - return new self($schema, $columns, 0); - } - - $rows = array_values($rows); - $batch = $rows[0]->rows; - $single = true; - - foreach ($rows as $row) { - if ($row->rows !== $batch) { - $single = false; - - break; - } - } - - if ($single && $batch->schema->isSame($schema)) { - $gathered = $batch->gather(array_map(static fn(Row $row): int => $row->index, $rows)); - - return new self($schema, $gathered->columns, $gathered->count); - } - - $builder = new RowsBuilder($schema, new DefaultBackend()); + $backend = new DefaultBackend(); + $columns = []; - foreach ($rows as $row) { - $builder->appendFrom($row->rows, $row->index); + foreach ($schema->definitions() as $name => $definition) { + $columns[$name] = $backend->builder($definition)->finish(); } - return $builder->finish(); + return new self($schema, $columns, 0); } /** @@ -158,6 +120,10 @@ public static function fromColumns(Schema $schema, array $columns, int $count): } foreach ($schema->definitions() as $name => $definition) { + if ($columns[$name] instanceof ValueColumn) { + throw ColumnMismatchException::untypedColumn($definition); + } + if (!$definition->isNullable() && $columns[$name]->nullCount() > 0) { $index = 0; @@ -175,34 +141,6 @@ public static function fromColumns(Schema $schema, array $columns, int $count): return new self($schema, $columns, $count); } - /** - * @throws SchemaMismatchException - */ - public function add(Row ...$rows): self - { - try { - $added = self::of($this->schema, ...$rows); - } catch (SchemaMismatchException $e) { - throw new SchemaMismatchException($e->rowIndex + $this->count, $e->cause); - } - - return $this->concat($added); - } - - /** - * @return list - */ - public function all(): array - { - $rows = []; - - for ($i = 0; $i < $this->count; $i++) { - $rows[] = new Row($this, $i); - } - - return $rows; - } - /** * @param int<1, max> $size * @@ -276,7 +214,7 @@ public function concat(self ...$others): self $head = array_shift($inputs); if ($head === null) { - return self::of($this->schema); + return self::empty($this->schema); } $backend = new DefaultBackend(); @@ -318,53 +256,13 @@ public function count(): int public function diffLeft(self $rows): self { - $comparator = new NativeComparator(); - $others = $rows->all(); - $kept = []; - - foreach ($this->all() as $row) { - $found = false; - - foreach ($others as $otherRow) { - if ($comparator->equals($row, $otherRow, $this->schema)) { - $found = true; - - break; - } - } - - if (!$found) { - $kept[] = $row->index; - } - } - - return $this->gather($kept); + return $this->gather((new RowEquality())->notIn($this, $rows, $this->schema)); } public function diffRight(self $rows): self { - $comparator = new NativeComparator(); - $own = $this->all(); - $kept = []; - - foreach ($rows->all() as $row) { - $found = false; - - foreach ($own as $otherRow) { - if ($comparator->equals($row, $otherRow, $this->schema)) { - $found = true; - - break; - } - } - - if (!$found) { - $kept[] = $row->index; - } - } - // the surviving rows come from the right side, so the right side's schema describes them - return $rows->gather($kept); + return $rows->gather((new RowEquality())->notIn($rows, $this, $this->schema)); } public function drop(int $size): self @@ -393,15 +291,6 @@ public function dropRight(int $size): self return $this->slice(0, $this->count - min($size, $this->count)); } - public function first(): Row - { - if ($this->count === 0) { - throw new RuntimeException('First row does not exist in empty collection'); - } - - return new Row($this, 0); - } - /** * @param list $indices rows to keep, in the order given * @@ -409,13 +298,15 @@ public function first(): Row */ public function gather(array $indices): self { - foreach ($indices as $index) { - if ($index < 0 || $index >= $this->count) { - throw new InvalidArgumentException(sprintf( - 'Rows::gather() index %d is outside a batch of %d rows', - $index, - $this->count, - )); + if ($indices !== [] && (min($indices) < 0 || max($indices) >= $this->count)) { + foreach ($indices as $index) { + if ($index < 0 || $index >= $this->count) { + throw new InvalidArgumentException(sprintf( + 'Rows::gather() index %d is outside a batch of %d rows', + $index, + $this->count, + )); + } } } @@ -428,23 +319,9 @@ public function gather(array $indices): self return new self($this->schema, $columns, count($indices)); } - /** - * @return \Iterator - */ - public function getIterator(): Iterator - { - return new ArrayIterator($this->all()); - } - public function hash(Algorithm $algorithm = new NativePHPHash()): string { - $hash = ''; - - for ($i = 0; $i < $this->count; $i++) { - $hash .= (new Row($this, $i))->hash($this->schema, $algorithm); - } - - return $algorithm->hash($hash); + return $algorithm->hash(implode('', (new RowHashes())->of($this, $algorithm))); } /** @@ -471,19 +348,19 @@ public function isEmpty(): bool public function joinCross(self $right, string $joinPrefix = 'joined_'): self { $schema = (new JoinSchema($joinPrefix))->cross($this->schema, $right->schema); - $merger = new RowMerger($joinPrefix); - $rightRows = $right->all(); - $joined = []; + $left = []; + $rightIndices = []; - foreach ($this->all() as $leftRow) { - foreach ($rightRows as $rightRow) { - $joined[] = $merger->merge($leftRow, $rightRow); + for ($i = 0; $i < $this->count; $i++) { + for ($j = 0; $j < $right->count; $j++) { + $left[] = $i; + $rightIndices[] = $j; } } - return (new RowsBuilder($schema, new DefaultBackend())) - ->appendRows($joined) - ->finish(); + return (new RowMerger($joinPrefix)) + ->merge($this->gather($left), $right->gather($rightIndices)) + ->project($schema); } /** @@ -518,11 +395,6 @@ public function joinRight(self $right, Expression $expression): self return $this->joinUsing($right, $expression, Join::right); } - public function last(): ?Row - { - return $this->count === 0 ? null : new Row($this, $this->count - 1); - } - /** * Adopts $schema, checking every column whose definition it changes (Definition::matches per value). * @@ -631,50 +503,6 @@ public function merge(self $rows): self return $this->concat($rows); } - /** - * @param int $offset - * - * @throws InvalidArgumentException - */ - public function offsetExists($offset): bool - { - // @mago-ignore analysis:impossible-condition,redundant-type-comparison - if (!is_int($offset)) { - throw new InvalidArgumentException('Rows accepts only integer offsets'); - } - - return $offset >= 0 && $offset < $this->count; - } - - /** - * @param int $offset - * - * @throws InvalidArgumentException - */ - public function offsetGet($offset): Row - { - if ($this->offsetExists($offset)) { - return new Row($this, $offset); - } - - throw new InvalidArgumentException("Row {$offset} does not exists."); - } - - public function offsetSet(mixed $offset, mixed $value): void - { - throw new RuntimeException('In order to add new rows use Rows::add(Row $row) : self'); - } - - /** - * @param int $offset - * - * @throws RuntimeException - */ - public function offsetUnset(mixed $offset): void - { - throw new RuntimeException('In order to remove rows use Rows::remove(int $offset) : self'); - } - /** * Drops the columns $schema does not declare and adopts it. Widening or retyping the batch is * not a projection - that goes through matchTo(). @@ -714,7 +542,7 @@ public function reduceToArray(string|Reference $reference): array public function remove(int $offset): self { - if (!$this->offsetExists($offset)) { + if ($offset < 0 || $offset >= $this->count) { throw new InvalidArgumentException("Rows does not have {$offset} offset"); } @@ -732,11 +560,6 @@ public function reverse(): self return $this->gather($indices); } - public function row(int $i): Row - { - return new Row($this, $i); - } - public function schema(): Schema { return $this->schema; @@ -770,17 +593,9 @@ public function slice(int $offset, int $length): self */ public function sortAscending(string|Reference $reference): self { - if ($this->count === 0) { - return $this; - } - - /** @var list $order */ - $order = array_keys(ValuesSorter::sort( - $this->column($reference instanceof Reference ? $reference->base() : $reference)->values(), - SortOrder::ASC, - )); - - return $this->gather($order); + return $this->sortBy( + (new UnresolvedReference($reference instanceof Reference ? $reference->base() : $reference))->asc(), + ); } /** @@ -788,13 +603,13 @@ public function sortAscending(string|Reference $reference): self */ public function sortBy(Reference ...$references): self { - $rows = $this; - - foreach (array_reverse($references) as $ref) { - $rows = $ref->sort() === SortOrder::ASC ? $rows->sortAscending($ref) : $rows->sortDescending($ref); + if ($this->count === 0) { + return $this; } - return $rows; + $order = new RowOrder(array_values($references)); + + return $this->gather($order->permutation($order->keys($this), $this->count)); } /** @@ -802,17 +617,9 @@ public function sortBy(Reference ...$references): self */ public function sortDescending(string|Reference $reference): self { - if ($this->count === 0) { - return $this; - } - - /** @var list $order */ - $order = array_keys(ValuesSorter::sort( - $this->column($reference instanceof Reference ? $reference->base() : $reference)->values(), - SortOrder::DESC, - )); - - return $this->gather($order); + return $this->sortBy( + (new UnresolvedReference($reference instanceof Reference ? $reference->base() : $reference))->desc(), + ); } /** @@ -858,37 +665,39 @@ public function takeRight(int $size): self */ public function toArray(bool $withKeys = true): array { - $array = []; + // @mago-ignore analysis:possibly-invalid-argument + $array = $this->count === 0 ? [] : array_fill(0, $this->count, []); - for ($i = 0; $i < $this->count; $i++) { - $array[] = (new Row($this, $i))->toArray($withKeys); + foreach ($this->columns as $name => $column) { + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $i => $value) { + if ($value instanceof Json) { + $value = $value->toArray(); + } + + $withKeys ? ($array[$i][$name] = $value) : ($array[$i][] = $value); + } } return $array; } - public function unique(Comparator $comparator = new NativeComparator()): self + public function unique(): self { - $unique = []; - - foreach ($this->all() as $row) { - foreach ($unique as $uniqueRow) { - if ($comparator->equals($row, $uniqueRow, $this->schema)) { - continue 2; - } - } - - $unique[] = $row; - } - - return $this->gather(array_map(static fn(Row $row): int => $row->index, $unique)); + return $this->gather((new RowEquality())->unique($this)); } /** + * @throws InvalidArgumentException + * * @return array the logical row, schema order */ public function values(int $i): array { + if ($i < 0 || $i >= $this->count) { + throw InvalidArgumentException::because('Row %d does not exist in a batch of %d rows', $i, $this->count); + } + $values = []; foreach ($this->columns as $name => $column) { @@ -975,15 +784,15 @@ private function joinUsing(self $right, Expression $expression, Join $type): sel yield $rows; }; - $joiner = new Joiner($expression, $type, new DefaultBackend()); + $joiner = new Joiner($expression, $type); $joined = []; foreach ($joiner->join(JoinSide::of($single($this)), JoinSide::of($single($right))) as $batch) { - foreach ($batch->all() as $row) { - $joined[] = $row; - } + $joined[] = $batch; } - return self::of($joiner->schema($this->schema, $right->schema), ...$joined); + return $joined === [] + ? self::empty($joiner->schema($this->schema, $right->schema)) + : $joined[0]->concat(...array_slice($joined, 1)); } } diff --git a/src/core/etl/src/Flow/ETL/Rows/RowEquality.php b/src/core/etl/src/Flow/ETL/Rows/RowEquality.php new file mode 100644 index 0000000000..ea9423627c --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Rows/RowEquality.php @@ -0,0 +1,161 @@ + + */ + public function bucketKeys(Rows $rows, Schema $schema): array + { + $comparable = new ComparableValues(); + $exact = []; + + foreach ($schema->definitions() as $name => $definition) { + if ( + $comparable->orderedByPhysical($definition->type()) + && $rows->schema()->findDefinition($name) !== null + ) { + $exact[] = $name; + } + } + + if ($exact === [] || $rows->isEmpty()) { + // @mago-ignore analysis:possibly-invalid-argument + return $rows->isEmpty() ? [] : array_fill(0, $rows->count(), ''); + } + + return (new RowHashes())->of($rows->project($rows->schema()->keep(...$exact))); + } + + /** + * @return array> + */ + public function columns(Rows $rows): array + { + $values = []; + + foreach ($rows->columns() as $name => $column) { + $values[$name] = $column->values(); + } + + return $values; + } + + /** + * @param array> $types + * @param array> $left + * @param array> $right + */ + public function equal(array $types, array $left, int $i, array $right, int $j): bool + { + foreach ($types as $name => $type) { + if (!array_key_exists($name, $left) || !array_key_exists($name, $right)) { + continue; + } + + if (!$this->comparator->equals($type, $left[$name][$i], $right[$name][$j])) { + return false; + } + } + + return true; + } + + /** + * @return list rows of $rows with no equal row in $other, compared by $schema's types + */ + public function notIn(Rows $rows, Rows $other, Schema $schema): array + { + $values = $this->columns($rows); + $others = $this->columns($other); + + if (array_keys($values) !== array_keys($others)) { + // @mago-ignore analysis:possibly-invalid-argument + return $rows->isEmpty() ? [] : array_keys(array_fill(0, $rows->count(), true)); + } + + $types = $this->types($schema); + + /** @var array> $buckets */ + $buckets = []; + + foreach ($this->bucketKeys($other, $schema) as $j => $key) { + $buckets[$key][] = $j; + } + + $kept = []; + + foreach ($this->bucketKeys($rows, $schema) as $i => $key) { + foreach ($buckets[$key] ?? [] as $j) { + if ($this->equal($types, $values, $i, $others, $j)) { + continue 2; + } + } + + $kept[] = $i; + } + + return $kept; + } + + /** + * @return array> + */ + public function types(Schema $schema): array + { + $types = []; + + foreach ($schema->definitions() as $name => $definition) { + $types[$name] = $definition->type(); + } + + return $types; + } + + /** + * @return list the first row of every group of equal rows + */ + public function unique(Rows $rows): array + { + $values = $this->columns($rows); + $types = $this->types($rows->schema()); + + /** @var array> $buckets */ + $buckets = []; + $kept = []; + + foreach ($this->bucketKeys($rows, $rows->schema()) as $i => $key) { + foreach ($buckets[$key] ?? [] as $j) { + if ($this->equal($types, $values, $i, $values, $j)) { + continue 2; + } + } + + $buckets[$key][] = $i; + $kept[] = $i; + } + + return $kept; + } +} diff --git a/src/core/etl/src/Flow/ETL/Rows/RowHashes.php b/src/core/etl/src/Flow/ETL/Rows/RowHashes.php new file mode 100644 index 0000000000..73e7f44ae4 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Rows/RowHashes.php @@ -0,0 +1,44 @@ + + */ + public function of(Rows $rows, Algorithm $algorithm = new NativePHPHash()): array + { + if ($rows->isEmpty()) { + return []; + } + + $formatter = new TypedValueFormatter(); + // @mago-ignore analysis:possibly-invalid-argument + $strings = array_fill(0, $rows->count(), ''); + + foreach ($rows->schema()->sort()->definitions() as $definition) { + $name = $definition->entry()->name(); + $type = $definition->type(); + + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($name)->values() as $i => $value) { + $strings[$i] .= $name . $formatter->format($type, $value); + } + } + + return array_map(static fn(string $string): string => $algorithm->hash($string), $strings); + } +} diff --git a/src/core/etl/src/Flow/ETL/Schema.php b/src/core/etl/src/Flow/ETL/Schema.php index 78d362f9ac..6eecfc34a9 100644 --- a/src/core/etl/src/Flow/ETL/Schema.php +++ b/src/core/etl/src/Flow/ETL/Schema.php @@ -13,6 +13,7 @@ use Flow\ETL\Row\UnresolvedReference; use Flow\ETL\Schema\Definition; use Flow\ETL\Schema\Metadata; +use Flow\ETL\Schema\SameSchemas; use Flow\ETL\Schema\SortingStrategy; use Flow\ETL\Schema\SortingStrategy\AlphabeticalStrategy; @@ -240,6 +241,10 @@ public function insertAt(int $index, Definition ...$definitions): self */ public function isSame(self $schema): bool { + if ($this === $schema || SameSchemas::proved($this, $schema)) { + return true; + } + if (array_keys($this->definitions) !== array_keys($schema->definitions)) { return false; } @@ -250,6 +255,8 @@ public function isSame(self $schema): bool } } + SameSchemas::remember($this, $schema); + return true; } diff --git a/src/core/etl/src/Flow/ETL/Schema/SameSchemas.php b/src/core/etl/src/Flow/ETL/Schema/SameSchemas.php new file mode 100644 index 0000000000..36266e326d --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Schema/SameSchemas.php @@ -0,0 +1,38 @@ +> + */ + private static ?WeakMap $proved = null; + + public static function proved(Schema $schema, Schema $other): bool + { + return ( + self::$proved !== null + && self::$proved->offsetExists($schema) + && self::$proved[$schema]->offsetExists($other) + ); + } + + public static function remember(Schema $schema, Schema $other): void + { + self::$proved ??= new WeakMap(); + /** @var WeakMap $others */ + $others = self::$proved->offsetExists($schema) ? self::$proved[$schema] : new WeakMap(); + $others[$other] = true; + self::$proved[$schema] = $others; + } +} diff --git a/src/core/etl/src/Flow/ETL/Sort/ExternalSort.php b/src/core/etl/src/Flow/ETL/Sort/ExternalSort.php new file mode 100644 index 0000000000..5a5ef3f917 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Sort/ExternalSort.php @@ -0,0 +1,202 @@ + $mergeFanIn + * @param int<1, max> $batchSize + */ + public function __construct( + public References $refs, + public Buckets $spill, + public Buckets $merge, + private RandomValueGenerator $random, + public Unit $memoryLimit, + public int $mergeFanIn = 10, + public int $batchSize = 1000, + ) { + // @mago-ignore analysis:invalid-operand + // @mago-ignore analysis:impossible-condition,redundant-comparison + if ($this->mergeFanIn < 1) { + throw new InvalidArgumentException('Merge fan-in must be greater than 0, given: ' . $this->mergeFanIn); + } + + // @mago-ignore analysis:invalid-operand + // @mago-ignore analysis:impossible-condition,redundant-comparison + if ($this->batchSize < 1) { + throw new InvalidArgumentException('Batch size must be greater than 0, given: ' . $this->batchSize); + } + } + + /** + * @param Generator $rows + * @param null|int $limit + * + * @return Generator + */ + public function sort(Generator $rows, FlowContext $context, ?int $limit = null): Generator + { + $budget = new MemoryBudget($context->backend(), $this->memoryLimit); + $runId = $this->random->string(16); + + /** @var list $buffer */ + $buffer = []; + + /** @var list $runs */ + $runs = []; + $schema = null; + + try { + // draining upstream inside the try is what makes a mid-stream failure release the spilled runs + foreach ($rows as $batch) { + if ($batch->isEmpty()) { + continue; + } + + $schema ??= $batch->schema(); + $buffer[] = $batch->matchTo($schema); + + // the whole process, not this buffer: another spilling step in the pipeline holds memory too + if ($budget->exceeded()) { + $runs[] = $this->spill($this->sorted($buffer, $limit), $runId, count($runs)); + $buffer = []; + $budget->released(); + } + } + + if ($runs === []) { + if ($buffer !== []) { + yield from $this->sorted($buffer, $limit)->chunks($this->batchSize); + } + + return; + } + + if ($buffer !== []) { + $runs[] = $this->spill($this->sorted($buffer, $limit), $runId, count($runs)); + } + + $merger = new KWayMerge($this->refs, $this->batchSize); + $mergedIndex = 0; + + // each pass merges neighbouring runs in place, so equal keys keep the order they arrived in + while (count($runs) > $this->mergeFanIn) { + $runs = array_map( + fn(array $group): BucketRun => $this->reduce($group, $merger, $mergedIndex++, $limit), + array_chunk($runs, $this->mergeFanIn), + ); + } + + yield from $this->firstRows($merger->merge($runs), $limit); + } finally { + // nested, so a throwing spill clear still leaves the merge storage cleared - and chains as previous + try { + $this->spill->clear(); + } finally { + $this->merge->clear(); + } + } + } + + /** + * @param Generator $batches + * @param null|int $limit + * + * @return Generator + */ + public function firstRows(Generator $batches, ?int $limit): Generator + { + $remaining = $limit; + + foreach ($batches as $batch) { + if ($remaining === null) { + yield $batch; + + continue; + } + + yield $batch->slice(0, min($remaining, $batch->count())); + $remaining -= min($remaining, $batch->count()); + + if ($remaining === 0) { + return; + } + } + } + + /** + * @param list $group + * @param null|int $limit + * + * @return BucketRun the merged run, bound to the merge storage that wrote it + */ + public function reduce(array $group, KWayMerge $merger, int $index, ?int $limit): BucketRun + { + $bucketId = 'sort-merge-' . $this->random->string(16); + + // registered before the spill so clear() covers a partially written merged run + $this->merge->add(new Bucket($bucketId, 0, $index)); + $totalRows = 0; + + foreach ($this->firstRows($merger->merge($group), $limit) as $batch) { + $this->merge->storage()->append($bucketId, $batch); + $totalRows += $batch->count(); + } + + foreach ($group as $run) { + $run->remove(); + } + + $this->merge->add(new Bucket($bucketId, $totalRows, $index)); + + return new BucketRun($bucketId, $this->merge); + } + + /** + * @param list $buffer + * @param null|int $limit + */ + public function sorted(array $buffer, ?int $limit): Rows + { + $sorted = $buffer[0]->concat(...array_slice($buffer, 1))->sortBy(...$this->refs->all()); + + return $limit === null ? $sorted : $sorted->take($limit); + } + + public function spill(Rows $run, string $runId, int $index): BucketRun + { + $bucketId = sprintf('sort-%s-%d', $runId, $index); + $this->spill->storage()->set($bucketId, $run); + $this->spill->add(new Bucket($bucketId, $run->count(), $index)); + + return new BucketRun($bucketId, $this->spill); + } +} diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/BucketCursor.php b/src/core/etl/src/Flow/ETL/Sort/Merge/BucketCursor.php index 0bf117cc64..e585c38b6e 100644 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/BucketCursor.php +++ b/src/core/etl/src/Flow/ETL/Sort/Merge/BucketCursor.php @@ -4,24 +4,22 @@ namespace Flow\ETL\Sort\Merge; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Schema; +use Flow\ETL\Sort\RowOrder; +use Flow\ETL\Sort\SortKey; use Generator; -use function array_values; -use function count; - final class BucketCursor { - private int $count = 0; + private Rows $batch; private int $index = 0; /** - * @var list + * @var list $batch's sort keys */ - private array $rows = []; + private array $keys = []; private ?Schema $schema = null; @@ -32,22 +30,39 @@ final class BucketCursor */ public function __construct( private readonly Generator $batches, + private readonly RowOrder $order, ) { + $this->batch = Rows::empty(new Schema()); $this->load(); } - public function current(): Row + public function advance(int $index): void { - return $this->rows[$this->index]; - } + $this->index = $index; - public function next(): void - { - if (++$this->index >= $this->count) { + if ($this->index >= $this->batch->count()) { $this->load(); } } + public function batch(): Rows + { + return $this->batch; + } + + public function index(): int + { + return $this->index; + } + + /** + * @return list + */ + public function keys(): array + { + return $this->keys; + } + public function schema(): Schema { return $this->schema ?? new Schema(); @@ -55,7 +70,7 @@ public function schema(): Schema public function valid(): bool { - return $this->index < $this->count; + return $this->index < $this->batch->count(); } /** @@ -78,8 +93,8 @@ private function load(): void if ($batch->count() > 0) { $this->schema ??= $batch->schema(); - $this->rows = array_values($batch->all()); - $this->count = count($this->rows); + $this->batch = $batch; + $this->keys = $this->order->keys($batch); return; } @@ -87,7 +102,7 @@ private function load(): void $this->batches->next(); } - $this->rows = []; - $this->count = 0; + $this->batch = Rows::empty(new Schema()); + $this->keys = []; } } diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/ComparableBucketRow.php b/src/core/etl/src/Flow/ETL/Sort/Merge/ComparableBucketRow.php deleted file mode 100644 index 562aa27d37..0000000000 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/ComparableBucketRow.php +++ /dev/null @@ -1,19 +0,0 @@ - $values - */ - public function __construct( - public array $values, - public Row $row, - public string $bucketId, - ) {} -} diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php index 10924cbb78..3db6dd4364 100644 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php +++ b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php @@ -5,14 +5,17 @@ namespace Flow\ETL\Sort\Merge; use Flow\ETL\Bucketing\BucketRun; -use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Row\References; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuffer; use Flow\ETL\Schema; +use Flow\ETL\Sort\RowOrder; use Generator; +use function array_filter; +use function array_slice; +use function array_values; + final readonly class KWayMerge { /** @@ -20,7 +23,6 @@ */ public function __construct( private References $refs, - private Backend $backend, private int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand @@ -31,48 +33,86 @@ public function __construct( } /** + * Merges block by block: every loaded row that sorts at or before the smallest last loaded row (the frontier) is + * final, because a run's unloaded rows sort after its loaded ones. Ties sort by run, then by position, so equal + * rows keep their input order. + * * @param list $runs * * @return Generator */ public function merge(array $runs): Generator { - $heap = new RowsMinHeap(...$this->refs->all()); + $order = new RowOrder($this->refs->all()); - /** @var array $cursors */ + /** @var list $cursors */ $cursors = []; $schema = null; foreach ($runs as $run) { - $cursor = new BucketCursor($run->rows()); + $cursor = new BucketCursor($run->rows(), $order); if ($cursor->valid()) { $schema ??= $cursor->schema(); - $heap->push($cursor->current(), $run->id); - $cursor->next(); - $cursors[$run->id] = $cursor; + $cursors[] = $cursor; } } - $buffer = new RowsBuffer($schema ?? new Schema(), $this->backend, $this->batchSize); + $schema ??= new Schema(); + $pending = Rows::empty($schema); - while (!$heap->isEmpty()) { - $top = $heap->extract(); + while ($cursors !== []) { + $frontier = 0; - if (null !== ($batch = $buffer->appendFrom($top->row->rows, $top->row->index))) { - yield $batch; + foreach ($cursors as $position => $cursor) { + if ( + $order->compare( + $cursor->keys(), + $cursor->batch()->count() - 1, + $cursors[$frontier]->keys(), + $cursors[$frontier]->batch()->count() - 1, + ) < 0 + ) { + $frontier = $position; + } } - $cursor = $cursors[$top->bucketId]; + $bound = $cursors[$frontier]->keys(); + $boundIndex = $cursors[$frontier]->batch()->count() - 1; + $slices = []; - if ($cursor->valid()) { - $heap->push($cursor->current(), $top->bucketId); - $cursor->next(); + foreach ($cursors as $position => $cursor) { + $from = $cursor->index(); + $to = $order->firstAfter( + $cursor->keys(), + $from, + $cursor->batch()->count(), + $bound, + $boundIndex, + $position <= $frontier, + ); + + if ($to > $from) { + $slices[] = $cursor + ->batch() + ->slice($from, $to - $from) + ->matchTo($schema); + $cursor->advance($to); + } + } + + $cursors = array_values(array_filter($cursors, static fn(BucketCursor $cursor): bool => $cursor->valid())); + $block = $slices[0]->concat(...array_slice($slices, 1)); + $pending = $pending->concat($block->gather($order->permutation($order->keys($block), $block->count()))); + + while ($pending->count() >= $this->batchSize) { + yield $pending->slice(0, $this->batchSize); + $pending = $pending->slice($this->batchSize, $pending->count() - $this->batchSize); } } - if (null !== ($batch = $buffer->flush())) { - yield $batch; + if (!$pending->isEmpty()) { + yield $pending; } } } diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/RowsMinHeap.php b/src/core/etl/src/Flow/ETL/Sort/Merge/RowsMinHeap.php deleted file mode 100644 index 4f4e3a4675..0000000000 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/RowsMinHeap.php +++ /dev/null @@ -1,83 +0,0 @@ - - */ -final class RowsMinHeap extends SplMinHeap -{ - private readonly References $ref; - - /** - * @var array - */ - private readonly array $orders; - - public function __construct(Reference ...$refs) - { - $this->ref = References::init(...$refs); - - $orders = []; - - foreach ($this->ref as $ref) { - $orders[] = $ref->sort(); - } - - $this->orders = $orders; - } - - public function __debugInfo(): array - { - $clone = clone $this; - $elements = []; - - while (!$clone->isEmpty()) { - $cachedRow = $clone->extract(); - $elements[] = [$cachedRow->bucketId => $cachedRow->row->toArray()]; - } - - return $elements; - } - - public function push(Row $row, string $bucketId): void - { - $values = []; - - foreach ($this->ref as $ref) { - $values[] = $row->get($ref->name()); - } - - parent::insert(new ComparableBucketRow($values, $row, $bucketId)); - } - - /** - * @param ComparableBucketRow $value1 - * @param ComparableBucketRow $value2 - */ - protected function compare($value1, $value2): int - { - $left = []; - $right = []; - - foreach ($this->orders as $index => $order) { - if ($order === SortOrder::DESC) { - $left[] = $value1->values[$index]; - $right[] = $value2->values[$index]; - } else { - $left[] = $value2->values[$index]; - $right[] = $value1->values[$index]; - } - } - - return $left <=> $right; - } -} diff --git a/src/core/etl/src/Flow/ETL/Sort/RowOrder.php b/src/core/etl/src/Flow/ETL/Sort/RowOrder.php new file mode 100644 index 0000000000..c020642c23 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Sort/RowOrder.php @@ -0,0 +1,191 @@ + $references + */ + public function __construct( + private array $references, + ) {} + + /** + * @param list $left + * @param list $right + * + * @return int negative when row $i of $left sorts before row $j of $right + */ + public function compare(array $left, int $i, array $right, int $j): int + { + foreach ($left as $position => $key) { + $other = $right[$position]; + $comparison = $key->ranks[$i] <=> $other->ranks[$j]; + + if ($comparison === 0 && $key->ranks[$i] === 1) { + // @mago-expect analysis:mixed-argument(2),mixed-operand(2) + $comparison = $key->flag === SORT_STRING + ? strcmp($key->values[$i], $other->values[$j]) <=> 0 + : $key->values[$i] <=> $other->values[$j]; + } + + if ($comparison !== 0) { + return $key->descending ? -$comparison : $comparison; + } + } + + return 0; + } + + /** + * The first row in [$from, $count) of a batch sorted in this order that sorts after row $boundIndex of $bound - + * or at or after it when rows equal to the bound are excluded. + * + * @param list $keys + * @param list $bound + */ + public function firstAfter( + array $keys, + int $from, + int $count, + array $bound, + int $boundIndex, + bool $includeEqual, + ): int { + $low = $from; + $high = $count; + + while ($low < $high) { + $middle = ($low + $high) >> 1; + $comparison = $this->compare($keys, $middle, $bound, $boundIndex); + + if ($comparison < 0 || $comparison === 0 && $includeEqual) { + $low = $middle + 1; + } else { + $high = $middle; + } + } + + return $low; + } + + /** + * @return list one per reference, in reference order + */ + public function keys(Rows $rows): array + { + $comparable = new ComparableValues(); + $keys = []; + + foreach ($this->references as $reference) { + $column = $rows->column($reference->base()); + $type = type_bare($column->type()); + $ordered = $comparable->orderedByPhysical($type); + $flag = self::flag($type); + $descending = $reference->sort() === SortOrder::DESC; + // nulls rank below every value, or above NaN when the reference moves them to the other end + $nullRank = $reference->nulls() === NullsOrder::defaultFor($reference->sort()) ? 0 : 3; + $ranks = []; + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($ordered ? $column->physicals() : $column->values() as $value) { + if ($value === null) { + $ranks[] = $nullRank; + $values[] = $flag === SORT_STRING ? '' : 0; + } elseif (is_float($value) && is_nan($value)) { + $ranks[] = 2; + $values[] = 0; + } else { + $ranks[] = 1; + // objects have no order: every one of them ties + $values[] = is_bool($value) ? (int) $value : (is_object($value) ? 0 : $value); + } + } + + $keys[] = new SortKey($ranks, $values, $flag, $descending); + } + + return $keys; + } + + /** + * The sort() flag of this order for non-null values of $type: strings by bytes, numbers, datetimes, dates, times + * and bools by their physical form. + * + * @param Type $type + */ + public static function flag(Type $type): int + { + $bare = type_bare($type); + + return match (true) { + $bare instanceof StringType => SORT_STRING, + (new ComparableValues())->orderedByPhysical($bare) => SORT_NUMERIC, + default => SORT_REGULAR, + }; + } + + /** + * @param list $keys of a batch of $count rows + * + * @return list the batch's indices in this order + */ + public function permutation(array $keys, int $count): array + { + // @mago-ignore analysis:possibly-invalid-argument + $positions = array_keys(array_fill(0, $count, true)); + + if ($keys === [] || $count < 2) { + return $positions; + } + + $arguments = []; + + foreach ($keys as $key) { + $direction = $key->descending ? SORT_DESC : SORT_ASC; + array_push($arguments, $key->ranks, $direction, SORT_NUMERIC, $key->values, $direction, $key->flag); + } + + // rows equal on every key keep their input order + $arguments[] = &$positions; + array_multisort(...$arguments); + + return $positions; + } +} diff --git a/src/core/etl/src/Flow/ETL/Sort/SortKey.php b/src/core/etl/src/Flow/ETL/Sort/SortKey.php new file mode 100644 index 0000000000..63c44022ce --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Sort/SortKey.php @@ -0,0 +1,23 @@ + $ranks + * @param list $values + */ + public function __construct( + public array $ranks, + public array $values, + public int $flag, + public bool $descending, + ) {} +} diff --git a/src/core/etl/src/Flow/ETL/Sort/SortSteps.php b/src/core/etl/src/Flow/ETL/Sort/SortSteps.php index adefd0ddd9..2b1ff765af 100644 --- a/src/core/etl/src/Flow/ETL/Sort/SortSteps.php +++ b/src/core/etl/src/Flow/ETL/Sort/SortSteps.php @@ -5,12 +5,10 @@ namespace Flow\ETL\Sort; use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\SortedRunBucketing; use Flow\ETL\Config; use Flow\ETL\Config\Sort\MemorySortConfig; use Flow\ETL\Config\Sort\SortAlgorithmBuilder; use Flow\ETL\Processor; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\MemorySortProcessor; use Flow\ETL\Processor\MergeSortProcessor; use Flow\ETL\Row\References; @@ -25,27 +23,34 @@ */ public static function of(References $refs, Config $config, ?SortAlgorithmBuilder $algorithm = null): array { + $external = self::external($refs, $config, $algorithm); + + return $external === null ? [new MemorySortProcessor($refs)] : [new MergeSortProcessor($external)]; + } + + /** + * @param null|SortAlgorithmBuilder $algorithm null defers to configuration + */ + public static function external( + References $refs, + Config $config, + ?SortAlgorithmBuilder $algorithm = null, + ): ?ExternalSort { $sort = $algorithm?->build($config->cache->localFilesystemCacheDir, $config->backend()) ?? $config->sort; if ($sort instanceof MemorySortConfig) { - return [new MemorySortProcessor($refs)]; + return null; } - $random = $config->randomValueGenerator(); - $spill = new Buckets($sort->bucketing->storage); - // without the ??, a merge side built on its own would silently spill to local disk for a MemoryBuckets user - $merge = new Buckets($sort->merge ?? $sort->bucketing->storage); - - return [ - new BucketingProcessor(new SortedRunBucketing($refs->all(), $sort->runSize, $random), $spill), - new MergeSortProcessor( - $refs, - $spill, - $merge, - $random, - $sort->bucketing->bucketsCount, - $sort->bucketing->batchSize, - ), - ]; + return new ExternalSort( + $refs, + new Buckets($sort->bucketing->storage), + // without the ??, a merge side built on its own would silently spill to local disk for a MemoryBuckets user + new Buckets($sort->merge ?? $sort->bucketing->storage), + $config->randomValueGenerator(), + $sort->memoryLimit, + $sort->bucketing->bucketsCount, + $sort->bucketing->batchSize, + ); } } diff --git a/src/core/etl/src/Flow/ETL/Sort/ValuesSorter.php b/src/core/etl/src/Flow/ETL/Sort/ValuesSorter.php deleted file mode 100644 index 26cc8d4be7..0000000000 --- a/src/core/etl/src/Flow/ETL/Sort/ValuesSorter.php +++ /dev/null @@ -1,129 +0,0 @@ - $values - * - * @return array the same key => value pairs, sorted, keys preserved - */ - public static function sort(array $values, SortOrder $order): array - { - $allNumeric = true; - $allStrings = true; - $allDateTimes = true; - - // @mago-ignore analysis:mixed-assignment - foreach ($values as $value) { - if ($allNumeric && !is_numeric($value)) { - $allNumeric = false; - } - - if ($allStrings && !is_string($value)) { - $allStrings = false; - } - - if ($allDateTimes && !$value instanceof DateTimeInterface) { - $allDateTimes = false; - } - - if (!$allNumeric && !$allStrings && !$allDateTimes) { - break; - } - } - - if ($allNumeric) { - $order === SortOrder::ASC ? asort($values, SORT_NUMERIC) : arsort($values, SORT_NUMERIC); - - return $values; - } - - if ($allStrings) { - $order === SortOrder::ASC ? asort($values, SORT_STRING) : arsort($values, SORT_STRING); - - return $values; - } - - if ($allDateTimes) { - $keys = []; - - // @mago-ignore analysis:mixed-assignment - foreach ($values as $index => $value) { - if ($value instanceof DateTimeInterface) { - // integer microsecond timestamp - exact chronological order, no float precision loss - $keys[$index] = ((int) $value->format('U') * 1_000_000) + (int) $value->format('u'); - } - } - - $order === SortOrder::ASC ? asort($keys, SORT_NUMERIC) : arsort($keys, SORT_NUMERIC); - - $sorted = []; - - foreach ($keys as $index => $_) { - $sorted[$index] = $values[$index]; - } - - return $sorted; - } - - uasort($values, static function (mixed $valueA, mixed $valueB) use ($order): int { - $result = self::compare($valueA, $valueB); - - return $order === SortOrder::ASC ? $result : -$result; - }); - - return $values; - } - - private static function compare(mixed $valueA, mixed $valueB): int - { - if (is_numeric($valueA) && is_numeric($valueB)) { - return (float) $valueA <=> (float) $valueB; - } - - if (is_string($valueA) && is_string($valueB)) { - return $valueA <=> $valueB; - } - - if ($valueA instanceof DateTimeInterface && $valueB instanceof DateTimeInterface) { - return $valueA <=> $valueB; - } - - if ($valueA instanceof DateInterval && $valueB instanceof DateInterval) { - // DateInterval objects are not comparable directly, anchor both to the epoch - $epoch = new DateTimeImmutable('@0'); - - return $epoch->add($valueA) <=> $epoch->add($valueB); - } - - if (is_array($valueA) && is_array($valueB)) { - return $valueA <=> $valueB; - } - - return 0; - } -} diff --git a/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php b/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php index 68b187fa68..fc80a9a6ef 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Transformer; +use Flow\ETL\Column\Backend; use Flow\ETL\Column\Column; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\SchemaMismatchException; @@ -11,6 +12,8 @@ use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; +use function Flow\Types\DSL\type_bare; + final readonly class DerivedColumns { /** @@ -24,20 +27,33 @@ public function declare(Schema $input, Definition $derived): Schema } /** + * The function's column as the stored derived column: NOT NULL enforced here (intermediates are nullable), the + * same type adopted into the configured backend, any other type rebuilt through it. + * * @param Definition $derived * * @throws SchemaMismatchException */ - public function value(Definition $derived, mixed $value, int $rowIndex): mixed + public function stored(Definition $derived, Column $column, Backend $backend): Column { - // @mago-ignore analysis:mixed-assignment - $cast = $value === null ? null : $derived->type()->cast($value); + if (!$derived->isNullable() && $column->nullCount() > 0) { + $index = 0; + + while (!$column->isNull($index)) { + $index++; + } - if (!$derived->matches($cast)) { - throw new SchemaMismatchException($rowIndex, ColumnMismatchException::valueDoesNotMatch($derived, $cast)); + throw new SchemaMismatchException($index, ColumnMismatchException::valueDoesNotMatch($derived, null)); } - return $cast; + if (type_bare($column->type())->normalize() === type_bare($derived->type())->normalize()) { + return $backend->adopt($derived, $column->withType($derived->type())); + } + + $builder = $backend->builder($derived); + $builder->appendMany($column->values()); + + return $builder->finish(); } public function rows(Rows $input, Schema $declared, Schema $output, string $name, Column $derived): Rows diff --git a/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php index 974c9baa39..19d5bb805a 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DropDuplicatesTransformer.php @@ -51,28 +51,32 @@ public function transform(Rows $rows, FlowContext $context): Rows $context->telemetry()->transformationStarted($this); try { - $newRows = []; + $columns = []; - foreach ($rows as $row) { + foreach ($this->entries as $entry) { + $name = $entry instanceof Reference ? $entry->base() : $entry; + + $columns[] = $rows->schema()->findDefinition($name) === null ? [] : $rows->column($name)->values(); + } + + $kept = []; + + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { $values = []; - foreach ($this->entries as $entry) { - try { - $values[] = $row->get($entry); - } catch (InvalidArgumentException) { - $values[] = null; - } + foreach ($columns as $column) { + $values[] = $column[$i] ?? null; } $hash = $this->hashAlgorithm->hash(serialize($values)); if (!$this->deduplication->exists($hash)) { - $newRows[] = $row; + $kept[] = $i; $this->deduplication->add($hash); } } - $result = Rows::of($rows->schema(), ...$newRows); + $result = $rows->gather($kept); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php index 70114cbd48..6a850c7309 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php @@ -20,10 +20,8 @@ use Flow\Types\Type\Unifier\PromotingUnifier; use Throwable; -use function array_key_exists; use function array_values; use function Flow\ETL\DSL\definition_from_type; -use function Flow\ETL\DSL\rows; use function Flow\Types\DSL\type_equals; final class DuplicateRowTransformer implements Transformer @@ -68,43 +66,41 @@ public function transform(Rows $rows, FlowContext $context): Rows $condition = $this->resolved ?? $this->resolve($rows->schema()); $output = $this->output ?? $this->declare($rows->schema()); $duplicated = []; - $sources = []; - foreach ($rows->all() as $position => $row) { - if ((new Parameter($condition))->asBoolean($row, $context) ?? false) { - $duplicated[] = $row; - $sources[$position] = true; + foreach ((new Parameter($condition))->asBooleans($rows, $context) as $position => $duplicate) { + if ($duplicate ?? false) { + $duplicated[] = $position; } } if ($duplicated !== []) { - // The maps inside ScalarFunctionTransformer are per-row and stateless, so applying + // The maps inside ScalarFunctionTransformer are column-wise and stateless, so applying // each entry once over all duplicated rows is equivalent to applying it per row. - $duplicatedRows = rows($rows->schema(), ...$duplicated); + $copies = $rows->gather($duplicated); foreach ($this->entries as $entry) { - $duplicatedRows = (new ScalarFunctionTransformer($entry->name, $entry->function))->transform( - $duplicatedRows, + $copies = (new ScalarFunctionTransformer($entry->name, $entry->function))->transform( + $copies, $context, ); } - $copies = $duplicatedRows->all(); + $count = $rows->count(); $copy = 0; $interleaved = []; // each copy follows the row it duplicates, so the output does not depend on where a batch ends - foreach ($rows->all() as $position => $row) { - $interleaved[] = $row; + for ($position = 0; $position < $count; $position++) { + $interleaved[] = $position; - if (array_key_exists($position, $sources)) { - $interleaved[] = $copies[$copy++]; + if ($copy < count($duplicated) && $duplicated[$copy] === $position) { + $interleaved[] = $count + $copy++; } } - $rows = Rows::of($output, ...$interleaved); + $rows = $rows->project($output)->concat($copies->project($output))->gather($interleaved); } else { - $rows = Rows::of($output, ...$rows->all()); + $rows = $rows->project($output); } $context->telemetry()->transformationCompleted($this, [ diff --git a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php index e45884745b..49c9fb549c 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php @@ -8,13 +8,11 @@ use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\FlowContext; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; use Flow\ETL\Transformer; use Throwable; -use function count; use function Flow\Types\DSL\type_array; final readonly class NestedExpandTransformer implements Transformer @@ -66,19 +64,10 @@ private function map(Rows $rows, FlowContext $context, Definition $derived): Row { $columns = new DerivedColumns(); $declared = $columns->declare($rows->schema(), $derived); - $cast = []; - $sources = []; - - foreach ($rows->all() as $index => $r) { - // @mago-ignore analysis:mixed-assignment - foreach ($this->expansion->eval($r, $context) as $value) { - $sources[] = $index; - $cast[] = $columns->value($derived, $value, count($cast)); - } - } + [$sources, $values] = $this->expansion->eval($rows, $context); $builder = $context->backend()->builder($derived); - $builder->appendMany($cast); + $builder->appendMany($values); return $columns->rows( $rows->gather($sources), @@ -93,29 +82,29 @@ private function unpack(Rows $rows, FlowContext $context, Schema $declared): Row { $columns = new UnpackedColumns(); $prefix = $this->entryName . '.'; - $prefixed = []; + [$sources, $payloads] = $this->expansion->eval($rows, $context); + $values = []; foreach ($declared->definitions() as $name => $_) { - $prefixed[] = $prefix . $name; + $values[$prefix . $name] = []; } - $payloads = []; - $sources = []; - - foreach ($rows->all() as $index => $r) { + // @mago-ignore analysis:mixed-assignment + foreach ($payloads as $payload) { // @mago-ignore analysis:mixed-assignment - foreach ($this->expansion->eval($r, $context) as $payload) { - $sources[] = $index; - $payloads[] = $columns->values($prefix, $declared, type_array()->assert($payload)); + foreach ($columns->values($prefix, $declared, type_array()->assert($payload)) as $name => $value) { + $values[$name][] = $value; } } - return $rows->gather($sources)->withColumns( - $this->output, - (new RowsBuilder($this->output->keep(...$prefixed), $context->backend())) - ->appendRows($payloads) - ->finish() - ->columns(), - ); + $unpacked = []; + + foreach ($values as $name => $columnValues) { + $builder = $context->backend()->builder($this->output->get((string) $name)); + $builder->appendMany($columnValues); + $unpacked[$name] = $builder->finish(); + } + + return $rows->gather($sources)->withColumns($this->output, $unpacked); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php b/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php index d48e698fa3..3b4ba14326 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php +++ b/src/core/etl/src/Flow/ETL/Transformer/NestedExpansion.php @@ -7,22 +7,23 @@ use Flow\ETL\FlowContext; use Flow\ETL\Function\ExpandingFunctions; use Flow\ETL\Function\FunctionTree; +use Flow\ETL\Function\Parameter; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\ScalarFunction\ExpandResults; -use Flow\ETL\Row; use Flow\ETL\Row\ResolvedReference; +use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; use Flow\Types\Type; use Flow\Types\Type\Logical\OptionalType; use Flow\Types\Type\TypeWidener; -use function array_fill; use function array_key_exists; use function array_map; use function array_values; use function count; use function Flow\ETL\DSL\definition_from_type; +use function is_array; use function max; use function spl_object_id; @@ -96,43 +97,56 @@ public function returns(): Type } /** - * @return list + * @return array{list, list} [$sources, $values] */ - public function eval(Row $row, FlowContext $context): array + public function eval(Rows $rows, FlowContext $context): array { $lists = []; foreach ($this->expands as $name => $expand) { - $lists[$name] = array_values($expand->eval($row, $context)); + $lists[$name] = (new Parameter($expand))->values($rows, $context); } - $length = max(array_map(count(...), $lists)); - $elements = $row->rows->gather(array_fill(0, $length, $row->index)); - $schema = $elements->schema()->isSame($this->input) - ? $this->elementSchema - : $elements->schema()->add(...array_values($this->expandDefinitions)); - $columns = []; + $sources = []; + $cells = []; - foreach ($lists as $name => $list) { - $builder = $context->backend()->builder($this->expandDefinitions[$name]); - $cells = []; + foreach ($lists as $name => $_) { + $cells[$name] = []; + } - for ($position = 0; $position < $length; $position++) { - $cells[] = $list[$position] ?? null; + for ($index = 0, $count = $rows->count(); $index < $count; $index++) { + $length = 0; + + foreach ($lists as $list) { + $length = max($length, is_array($list[$index]) ? count($list[$index]) : 0); } - $builder->appendMany($cells); - $columns[$name] = $builder->finish(); + foreach ($lists as $name => $list) { + $elements = is_array($list[$index]) ? array_values($list[$index]) : []; + + for ($position = 0; $position < $length; $position++) { + $cells[$name][] = $elements[$position] ?? null; + } + } + + for ($position = 0; $position < $length; $position++) { + $sources[] = $index; + } } - $batch = $elements->withColumns($schema, $columns); - $values = []; + $elements = $rows->gather($sources); + $schema = $elements->schema()->isSame($this->input) + ? $this->elementSchema + : $elements->schema()->add(...array_values($this->expandDefinitions)); + $columns = []; - for ($position = 0; $position < $length; $position++) { - $values[] = $this->root->eval($batch->row($position), $context); + foreach ($cells as $name => $values) { + $builder = $context->backend()->builder($this->expandDefinitions[$name]); + $builder->appendMany($values); + $columns[$name] = $builder->finish(); } - return $values; + return [$sources, (new Parameter($this->root))->values($elements->withColumns($schema, $columns), $context)]; } /** diff --git a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php index f6cbf85996..c7a9b6ef23 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionFilterTransformer.php @@ -16,6 +16,7 @@ use Flow\ETL\Transformer; use Throwable; +use function array_keys; use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_equals; @@ -42,16 +43,7 @@ public function transform(Rows $rows, FlowContext $context): Rows try { $function = $this->resolved ?? $this->resolve($rows->schema()); - $kept = []; - - foreach ($rows->all() as $r) { - // @mago-ignore analysis:mixed-operand - if ((bool) $function->eval($r, $context)) { - $kept[] = $r; - } - } - - $result = Rows::of($rows->schema(), ...$kept); + $result = $rows->gather(array_keys($function->eval($rows, $context)->physicals(), true, true)); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php index e8bad2afa8..d3d0430423 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php @@ -16,14 +16,12 @@ use Flow\ETL\Function\ScalarFunction\ExpandResults; use Flow\ETL\Function\ScalarFunction\UnpackResults; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; use Flow\ETL\Transformer; use Flow\Types\Type\Logical\StructureType; use Throwable; -use function count; use function Flow\ETL\DSL\definition_from_type; use function Flow\Types\DSL\type_array; use function sprintf; @@ -143,32 +141,39 @@ private function map(Rows $rows, FlowContext $context): Rows $derived = $this->derived ?? $this->derived($function); $declared = $columns->declare($rows->schema(), $derived); $output = $this->output ?? $declared; - $cast = []; - $sources = []; + $column = $function->eval($rows, $context); - foreach ($rows->all() as $index => $r) { - if ($function instanceof ExpandResults) { + if ($function instanceof ExpandResults) { + $sources = []; + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $index => $list) { // @mago-ignore analysis:mixed-assignment - foreach (type_array()->assert($function->eval($r, $context)) as $val) { + foreach (type_array()->assert($list) as $value) { $sources[] = $index; - $cast[] = $columns->value($derived, $val, count($cast)); + $values[] = $value; } - - continue; } - $cast[] = $columns->value($derived, $function->eval($r, $context), $index); - } + $builder = $context->backend()->builder($derived); + $builder->appendMany($values); - $builder = $context->backend()->builder($derived); - $builder->appendMany($cast); + return $columns->rows( + $rows->gather($sources), + $declared, + $output, + $derived->entry()->name(), + $builder->finish(), + ); + } return $columns->rows( - $function instanceof ExpandResults ? $rows->gather($sources) : $rows, + $rows, $declared, $output, $derived->entry()->name(), - $builder->finish(), + $columns->stored($derived, $column, $context->backend()), ); } @@ -206,24 +211,28 @@ private function unpack(Rows $rows, FlowContext $context): Rows $columns = new UnpackedColumns(); $output = $this->output ?? $columns->of($rows->schema(), $this->entryName() . '.', $declared); $prefix = $this->entryName() . '.'; - $prefixed = []; + $values = []; foreach ($declared->definitions() as $name => $_) { - $prefixed[] = $prefix . $name; + $values[$prefix . $name] = []; } - $payloads = []; + // @mago-ignore analysis:mixed-assignment + foreach ($function->eval($rows, $context)->values() as $payload) { + // @mago-ignore analysis:mixed-assignment + foreach ($columns->values($prefix, $declared, type_array()->assert($payload)) as $name => $value) { + $values[$name][] = $value; + } + } + + $unpacked = []; - foreach ($rows->all() as $r) { - $payloads[] = $columns->values($prefix, $declared, $function->eval($r, $context)); + foreach ($values as $name => $columnValues) { + $builder = $context->backend()->builder($output->get((string) $name)); + $builder->appendMany($columnValues); + $unpacked[$name] = $builder->finish(); } - return $rows->withColumns( - $output, - (new RowsBuilder($output->keep(...$prefixed), $context->backend())) - ->appendRows($payloads) - ->finish() - ->columns(), - ); + return $rows->withColumns($output, $unpacked); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php index b19e4ad1df..b5090081b1 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/SerializeTransformer.php @@ -15,7 +15,6 @@ use Throwable; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Serializer\DSL\serialize_to_string; @@ -63,8 +62,8 @@ public function transform(Rows $rows, FlowContext $context): Rows $serialized = $context->backend()->builder($column); - foreach ($rows->all() as $row) { - $serialized->append(serialize_to_string($serializer, rows($inputSchema, $row))); + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $serialized->append(serialize_to_string($serializer, $rows->slice($i, 1))); } $result = $this->standalone diff --git a/src/core/etl/src/Flow/ETL/Transformer/SerializedPayloadDecoder.php b/src/core/etl/src/Flow/ETL/Transformer/SerializedPayloadDecoder.php index 6b2528ccaa..f1fce1e025 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/SerializedPayloadDecoder.php +++ b/src/core/etl/src/Flow/ETL/Transformer/SerializedPayloadDecoder.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Transformer; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -24,7 +23,7 @@ private function __construct( private Serializer $serializer, private array $names, private string $prefix, - private Row $nothing, + private Rows $nothing, ) {} /** @@ -32,20 +31,17 @@ private function __construct( */ public static function of(Reference $source, Serializer $serializer, array $names, string $prefix = ''): self { - return new self($source, $serializer, $names, $prefix, Rows::fromColumns(new Schema(), [], 1)->row(0)); + return new self($source, $serializer, $names, $prefix, Rows::fromColumns(new Schema(), [], 1)); } - /** - * A view of the payload's declared columns under their output names; a payload that cannot be read is a view with - * no columns at all. - */ - public function decode(Row $row): Row + public function decode(Rows $rows, int $index): Rows { - if (!$row->has($this->source->name())) { + if ($rows->schema()->findDefinition($this->source->name()) === null) { return $this->nothing; } - $serialized = $row->get($this->source->name()); + // @mago-ignore analysis:mixed-assignment + $serialized = $rows->column($this->source->name())->value($index); if (!is_string($serialized)) { return $this->nothing; @@ -75,6 +71,6 @@ public function decode(Row $row): Row $columns[$this->prefix . $name] = $decoded->column($name); } - return Rows::fromColumns(new Schema(...$definitions), $columns, 1)->row(0); + return Rows::fromColumns(new Schema(...$definitions), $columns, 1); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer/UnserializeTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/UnserializeTransformer.php index 72d9f24841..3f6849fb3c 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/UnserializeTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/UnserializeTransformer.php @@ -62,9 +62,8 @@ public function transform(Rows $rows, FlowContext $context): Rows $decoder = SerializedPayloadDecoder::of($source, $serializer, $names, $prefix); $builder = new RowsBuilder($outputSchema->keep(...$outputNames), $context->backend()); - foreach ($rows->all() as $row) { - $payload = $decoder->decode($row); - $builder->appendFrom($payload->rows, $payload->index); + for ($i = 0, $count = $rows->count(); $i < $count; $i++) { + $builder->appendFrom($decoder->decode($rows, $i), 0); } $decoded = $builder->finish(); diff --git a/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php index c68c0a0c7a..0a9b0ed3c0 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php @@ -17,7 +17,6 @@ use Flow\ETL\Transformer; use Throwable; -use function count; use function Flow\Types\DSL\type_bare; use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_equals; @@ -51,27 +50,25 @@ public function transform(Rows $rows, FlowContext $context): Rows TelemetryAttributes::ATTR_TRANSFORMATION_OUTPUT_ROWS => 0, ]); - throw new LimitReachedException(0, Rows::of($rows->schema())); + throw new LimitReachedException(0, Rows::empty($rows->schema())); } // the unbound path has no plan to hold the resolved predicate, so it is memoised here - // until() stops the whole stream, not one batch $this->resolved ??= $this->resolve($rows->schema()); - $nextRows = []; - foreach ($rows as $row) { - if (!$this->resolved->eval($row, $context)) { + // @mago-ignore analysis:mixed-assignment + foreach ($this->resolved->eval($rows, $context)->physicals() as $i => $value) { + if (!$value) { $this->limitReached = true; $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), - TelemetryAttributes::ATTR_TRANSFORMATION_OUTPUT_ROWS => count($nextRows), + TelemetryAttributes::ATTR_TRANSFORMATION_OUTPUT_ROWS => $i, ]); - throw new LimitReachedException(0, Rows::of($rows->schema(), ...$nextRows)); + throw new LimitReachedException(0, $rows->slice(0, $i)); } - - $nextRows[] = $row; } $context->telemetry()->transformationCompleted($this, [ diff --git a/src/core/etl/src/Flow/ETL/Window/Accumulator/AverageAccumulator.php b/src/core/etl/src/Flow/ETL/Window/Accumulator/AverageAccumulator.php index ba820c526a..6c8390d5bf 100644 --- a/src/core/etl/src/Flow/ETL/Window/Accumulator/AverageAccumulator.php +++ b/src/core/etl/src/Flow/ETL/Window/Accumulator/AverageAccumulator.php @@ -6,10 +6,11 @@ use Flow\Calculator\Calculator; use Flow\Calculator\Rounding; +use Flow\Calculator\RunningSum; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\ETL\Window\FrameAccumulator; use function is_numeric; @@ -20,26 +21,28 @@ final class AverageAccumulator implements FrameAccumulator private int $count = 0; - private float|int $sum = 0; + private readonly RunningSum $runningSum; public function __construct( private readonly Reference $ref, private readonly int $scale, private readonly Rounding $rounding, + private readonly bool $exact, FlowContext $context, ) { $this->calculator = $context->calculator(); + $this->runningSum = new RunningSum($this->calculator); } - public function accumulate(Row $row): void + public function accumulate(Rows $rows, int $index): void { try { /** @var mixed $value */ - $value = $row->get($this->ref); + $value = $rows->column($this->ref->base())->value($index); if (is_numeric($value)) { // @mago-ignore analysis:possibly-invalid-argument - $this->sum = $this->calculator->add($this->sum, $value); + $this->runningSum->add($value, $this->exact); $this->count++; } } catch (InvalidArgumentException $e) { @@ -53,6 +56,6 @@ public function value(): float|int|null return null; } - return $this->calculator->divide($this->sum, $this->count, $this->scale, $this->rounding); + return $this->calculator->divide($this->runningSum->value(), $this->count, $this->scale, $this->rounding); } } diff --git a/src/core/etl/src/Flow/ETL/Window/Accumulator/CountAccumulator.php b/src/core/etl/src/Flow/ETL/Window/Accumulator/CountAccumulator.php index 3930ce0733..a64aa8944e 100644 --- a/src/core/etl/src/Flow/ETL/Window/Accumulator/CountAccumulator.php +++ b/src/core/etl/src/Flow/ETL/Window/Accumulator/CountAccumulator.php @@ -6,8 +6,8 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\ETL\Window\FrameAccumulator; final class CountAccumulator implements FrameAccumulator @@ -19,7 +19,7 @@ public function __construct( FlowContext $context, ) {} - public function accumulate(Row $row): void + public function accumulate(Rows $rows, int $index): void { if ($this->ref === null) { $this->count++; @@ -28,7 +28,7 @@ public function accumulate(Row $row): void } try { - if ($row->get($this->ref) !== null) { + if ($rows->column($this->ref->base())->value($index) !== null) { $this->count++; } } catch (InvalidArgumentException $e) { diff --git a/src/core/etl/src/Flow/ETL/Window/Accumulator/SumAccumulator.php b/src/core/etl/src/Flow/ETL/Window/Accumulator/SumAccumulator.php index 9cffa9afeb..6987b73523 100644 --- a/src/core/etl/src/Flow/ETL/Window/Accumulator/SumAccumulator.php +++ b/src/core/etl/src/Flow/ETL/Window/Accumulator/SumAccumulator.php @@ -7,45 +7,35 @@ use Flow\Calculator\RunningSum; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; -use Flow\ETL\Function\Parameter; -use Flow\ETL\Function\ScalarFunction; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\ETL\Window\FrameAccumulator; use function is_numeric; final class SumAccumulator implements FrameAccumulator { - /** - * Constant for a bool $exact, null when it is a ScalarFunction and has to be resolved per row. - */ - private readonly ?bool $constantExact; - private readonly RunningSum $runningSum; - private float|int|null $sum = null; + private bool $summed = false; public function __construct( private readonly Reference $ref, - private readonly ScalarFunction|bool $exact, - private readonly FlowContext $context, + private readonly bool $exact, + FlowContext $context, ) { - $this->constantExact = is_bool($exact) ? $exact : null; $this->runningSum = new RunningSum($context->calculator()); } - public function accumulate(Row $row): void + public function accumulate(Rows $rows, int $index): void { try { - $value = $row->get($this->ref); + // @mago-ignore analysis:mixed-assignment + $value = $rows->column($this->ref->base())->value($index); if (is_int($value) || is_float($value) || is_string($value) && is_numeric($value)) { - $this->sum = $this->runningSum->add( - $this->sum ?? 0, - $value, - $this->constantExact ?? (new Parameter($this->exact))->asBoolean($row, $this->context) ?? false, - ); + $this->runningSum->add($value, $this->exact); + $this->summed = true; } } catch (InvalidArgumentException $e) { throw new InvalidArgumentException('Sum window function error: ' . $e->getMessage(), 0, $e); @@ -54,6 +44,6 @@ public function accumulate(Row $row): void public function value(): float|int|null { - return $this->sum; + return $this->summed ? $this->runningSum->value() : null; } } diff --git a/src/core/etl/src/Flow/ETL/Window/FrameAccumulator.php b/src/core/etl/src/Flow/ETL/Window/FrameAccumulator.php index db059a7a9b..f9f24bb8fc 100644 --- a/src/core/etl/src/Flow/ETL/Window/FrameAccumulator.php +++ b/src/core/etl/src/Flow/ETL/Window/FrameAccumulator.php @@ -4,11 +4,11 @@ namespace Flow\ETL\Window; -use Flow\ETL\Row; +use Flow\ETL\Rows; interface FrameAccumulator { - public function accumulate(Row $row): void; + public function accumulate(Rows $rows, int $index): void; /** * Must be idempotent and non-destructive - WindowProcessor reads it after every growth step of an diff --git a/src/core/etl/src/Flow/ETL/Window/PeerComparator.php b/src/core/etl/src/Flow/ETL/Window/PeerComparator.php index 6c31187f90..fd83e12935 100644 --- a/src/core/etl/src/Flow/ETL/Window/PeerComparator.php +++ b/src/core/etl/src/Flow/ETL/Window/PeerComparator.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Window; -use Flow\ETL\Row; +use Flow\ETL\Column\ComparableValues; use Flow\ETL\Row\Reference; use Flow\ETL\Row\TypedValueComparator; -use Flow\ETL\Schema; +use Flow\ETL\Rows; +use Flow\Types\Type; + +use function is_float; +use function is_nan; /** * Two rows are peers when they carry equal values in every ORDER BY column. Compared with @@ -22,16 +26,69 @@ public function __construct( private array $orderBy, ) {} - public function arePeers(Row $left, Row $right, Schema $schema): bool + /** + * NaN is equal to itself here: the sort order puts it after every value. + * + * @param Type $type + */ + public function equal(Type $type, mixed $left, mixed $right): bool + { + if (is_float($left) && is_float($right) && is_nan($left) && is_nan($right)) { + return true; + } + + return (new TypedValueComparator())->equals($type, $left, $right); + } + + /** + * @return list per row: a peer of the row before it (row 0 never is) + */ + public function peersOfPrevious(Rows $partition): array { - $comparator = new TypedValueComparator(); + $count = $partition->count(); + $peers = []; + + for ($i = 0; $i < $count; $i++) { + $peers[] = $i > 0; + } + + $comparable = new ComparableValues(); foreach ($this->orderBy as $ref) { - if (!$comparator->equals($schema->get($ref)->type(), $left->get($ref), $right->get($ref))) { - return false; + $type = $partition->schema()->get($ref)->type(); + $column = $partition->column($ref->base()); + + if ($comparable->equalByPhysical($type)) { + // === on physicals is value equality; NaN is the one physical that is not === to itself + $physicals = $column->physicals(); + + for ($i = 1; $i < $count; $i++) { + // @mago-ignore analysis:mixed-assignment + $previous = $physicals[$i - 1]; + // @mago-ignore analysis:mixed-assignment + $current = $physicals[$i]; + + if ( + $peers[$i] + && $previous !== $current + && !(is_float($previous) && is_float($current) && is_nan($previous) && is_nan($current)) + ) { + $peers[$i] = false; + } + } + + continue; + } + + $values = $column->values(); + + for ($i = 1; $i < $count; $i++) { + if ($peers[$i] && !$this->equal($type, $values[$i - 1], $values[$i])) { + $peers[$i] = false; + } } } - return true; + return $peers; } } diff --git a/src/core/etl/src/Flow/ETL/Window/PeerFrame.php b/src/core/etl/src/Flow/ETL/Window/PeerFrame.php index 69493164a4..e7dc75226e 100644 --- a/src/core/etl/src/Flow/ETL/Window/PeerFrame.php +++ b/src/core/etl/src/Flow/ETL/Window/PeerFrame.php @@ -5,43 +5,58 @@ namespace Flow\ETL\Window; use Flow\ETL\Row\Reference; -use Flow\ETL\Row\TypedValueComparator; use Flow\ETL\Rows; +use WeakMap; + +use function array_reverse; final readonly class PeerFrame implements WindowFrame { + /** + * @var WeakMap> per partition: the last row of each row's peer group, derived once + */ + private WeakMap $ends; + /** * @param array $orderBy */ public function __construct( private array $orderBy, - ) {} + ) { + $this->ends = new WeakMap(); + } public function bounds(int $index, Rows $partition): array { - $lastIndex = $partition->count() - 1; - - if ($index > $lastIndex) { + if ($index > ($partition->count() - 1)) { return [1, 0]; } - $row = $partition[$index]; - $end = $index; - $schema = $partition->schema(); - $comparator = new TypedValueComparator(); + return [0, $this->ends($partition)[$index]]; + } + + /** + * @return list for every row the index of the last row of its peer group + */ + public function ends(Rows $partition): array + { + if (!$this->ends->offsetExists($partition)) { + $peers = (new PeerComparator($this->orderBy))->peersOfPrevious($partition); + $ends = []; + $end = $partition->count() - 1; - while ($end < $lastIndex) { - $next = $partition[$end + 1]; + // walking back, a row that is not a peer of the one before it closes the previous group + for ($i = $end; $i >= 0; $i--) { + $ends[] = $end; - foreach ($this->orderBy as $ref) { - if (!$comparator->equals($schema->get($ref)->type(), $row->get($ref), $next->get($ref))) { - return [0, $end]; + if ($i > 0 && !$peers[$i]) { + $end = $i - 1; } } - $end++; + $this->ends[$partition] = array_reverse($ends); } - return [0, $end]; + return $this->ends[$partition]; } } diff --git a/src/core/etl/src/Flow/ETL/Window/WindowContext.php b/src/core/etl/src/Flow/ETL/Window/WindowContext.php index 9f962e1c45..81712789dd 100644 --- a/src/core/etl/src/Flow/ETL/Window/WindowContext.php +++ b/src/core/etl/src/Flow/ETL/Window/WindowContext.php @@ -5,18 +5,13 @@ namespace Flow\ETL\Window; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Rows; -use function array_slice; -use function Flow\ETL\DSL\rows; - final class WindowContext { private ?Rows $frame = null; public function __construct( - private readonly Row $row, private readonly int $index, private readonly Rows $partition, private readonly WindowFrame $windowFrame, @@ -37,8 +32,8 @@ public function frame(): Rows [$start, $end] = $this->windowFrame->bounds($this->index, $this->partition); $this->frame = $start > $end - ? rows($this->partition->schema()) - : rows($this->partition->schema(), ...array_slice($this->partition->all(), $start, $end - $start + 1)); + ? Rows::empty($this->partition->schema()) + : $this->partition->slice($start, $end - $start + 1); } return $this->frame; @@ -53,9 +48,4 @@ public function partition(): Rows { return $this->partition; } - - public function row(): Row - { - return $this->row; - } } diff --git a/src/core/etl/tests/Flow/Calculator/Tests/Unit/RunningSumTest.php b/src/core/etl/tests/Flow/Calculator/Tests/Unit/RunningSumTest.php index 4264103144..0f02883651 100644 --- a/src/core/etl/tests/Flow/Calculator/Tests/Unit/RunningSumTest.php +++ b/src/core/etl/tests/Flow/Calculator/Tests/Unit/RunningSumTest.php @@ -8,23 +8,34 @@ use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; +use function is_nan; use function is_numeric; +use const INF; + final class RunningSumTest extends TestCase { #[TestWith([0, 1, 1])] #[TestWith([10, 5, 15])] - public function test_int_operands_stay_int(int $sum, int $value, int $output): void + public function test_int_operands_stay_int(int $first, int $second, int $output): void { - static::assertSame($output, (new RunningSum())->add($sum, $value, false)); + $sum = new RunningSum(); + $sum->add($first, false); + $sum->add($second, false); + + static::assertSame($output, $sum->value()); } #[TestWith([1.5, 1.5, 3.0])] #[TestWith([0, 2.5, 2.5])] #[TestWith([2.5, 0, 2.5])] - public function test_float_operand_yields_float(float|int $sum, float|int $value, float $output): void + public function test_float_operand_yields_float(float|int $first, float|int $second, float $output): void { - static::assertSame($output, (new RunningSum())->add($sum, $value, false)); + $sum = new RunningSum(); + $sum->add($first, false); + $sum->add($second, false); + + static::assertSame($output, $sum->value()); } #[TestWith(['10', 10.0])] @@ -33,21 +44,87 @@ public function test_numeric_string_operand_yields_float(string $value, float $o { assert(is_numeric($value), 'String parameter $value must be numeric'); - static::assertSame($output, (new RunningSum())->add(0, $value, false)); + $sum = new RunningSum(); + $sum->add($value, false); + + static::assertSame($output, $sum->value()); } - public function test_exact_mode_avoids_floating_point_drift(): void + public function test_compensation_keeps_ten_tenths_at_one(): void { - static::assertSame(0.3, (new RunningSum())->add(0.1, 0.2, true)); + $sum = new RunningSum(); + + for ($i = 0; $i < 10; $i++) { + $sum->add(0.1, false); + } + + // naive IEEE addition gives 0.9999999999999999 + static::assertSame(1.0, $sum->value()); } - public function test_inexact_mode_keeps_native_addition(): void + public function test_compensation_keeps_a_small_value_next_to_large_ones(): void { - static::assertSame(0.1 + 0.2, (new RunningSum())->add(0.1, 0.2, false)); + $sum = new RunningSum(); + $sum->add(1e16, false); + $sum->add(1.0, false); + $sum->add(-1e16, false); + + // naive IEEE addition gives 0.0 + static::assertSame(1.0, $sum->value()); + } + + public function test_an_infinite_sum_stays_infinite(): void + { + $sum = new RunningSum(); + $sum->add(INF, false); + $sum->add(1.5, false); + + static::assertSame(INF, $sum->value()); + static::assertFalse(is_nan($sum->value())); + } + + public function test_exact_mode_avoids_floating_point_drift(): void + { + $sum = new RunningSum(); + $sum->add(0.1, true); + $sum->add(0.2, true); + + static::assertSame(0.3, $sum->value()); } public function test_exact_mode_keeps_int_operands_int(): void { - static::assertSame(3, (new RunningSum())->add(1, 2, true)); + $sum = new RunningSum(); + $sum->add(1, true); + $sum->add(2, true); + + static::assertSame(3, $sum->value()); + } + + public function test_merge_carries_the_other_compensation(): void + { + $left = new RunningSum(); + $right = new RunningSum(); + + for ($i = 0; $i < 5; $i++) { + $left->add(0.1, false); + $right->add(0.1, false); + } + + $left->merge($right, false); + + static::assertSame(1.0, $left->value()); + } + + public function test_exact_merge_is_decimal(): void + { + $left = new RunningSum(); + $right = new RunningSum(); + $left->add(0.1, false); + $right->add(0.2, false); + + $left->merge($right, true); + + static::assertSame(0.3, $left->value()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowComparator.php b/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowComparator.php deleted file mode 100644 index 5dcb4604e8..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Comparator/RowComparator.php +++ /dev/null @@ -1,60 +0,0 @@ -names() !== $actual->names()) { - throw new ComparisonFailure( - $expected, - $actual, - $exporter->export($expected->names()), - $exporter->export($actual->names()), - 'Failed asserting that two Row objects have the same names.', - ); - } - - $expectedArray = $expected->toArray(); - $actualArray = $actual->toArray(); - - try { - $this - ->factory() - ->getComparatorFor($expectedArray, $actualArray) - ->assertEquals($expectedArray, $actualArray, $delta, $canonicalize, $ignoreCase); - } catch (ComparisonFailure) { - throw new ComparisonFailure( - $expected, - $actual, - $exporter->export($expectedArray), - $exporter->export($actualArray), - 'Failed asserting that two Row objects are equal.', - ); - } - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/BucketsStorageContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/BucketsStorageContext.php index 4edc301b79..ae08ac871d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/BucketsStorageContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/BucketsStorageContext.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Tests\Context; -use Flow\ETL\Row; use Flow\ETL\Rows; use Generator; @@ -15,14 +14,14 @@ final class BucketsStorageContext * * @param Generator $batches * - * @return list + * @return list> */ public static function rows(Generator $batches): array { $rows = []; foreach ($batches as $batch) { - foreach ($batch as $row) { + foreach ($batch->toArray() as $row) { $rows[] = $row; } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/FunctionContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/FunctionContext.php new file mode 100644 index 0000000000..184c377f95 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/FunctionContext.php @@ -0,0 +1,49 @@ +context = $context ?? flow_context(); + } + + /** + * @param list> $rows + */ + public function column(ScalarFunction $function, array $rows, Schema $schema): Column + { + return (new ReferenceResolver()) + ->resolve($function, $schema) + ->eval(array_to_rows($rows, $schema, $this->context->backend()), $this->context); + } + + /** + * Resolves $function against $schema (steps do the same), evaluates one row, returns its value as a parent + * function reads it. + * + * @param array $row + */ + public function eval(ScalarFunction $function, array $row, Schema $schema): mixed + { + return (new Parameter((new ReferenceResolver())->resolve($function, $schema)))->values( + array_to_rows([$row], $schema, $this->context->backend()), + $this->context, + )[0]; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/GroupByContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/GroupByContext.php index 9551e7ac2d..3c6e287722 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/GroupByContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/GroupByContext.php @@ -4,16 +4,10 @@ namespace Flow\ETL\Tests\Context; -use Flow\ETL\Bucketing\Bucket; -use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\HashBucketing; -use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\FlowContext; use Flow\ETL\GroupBy; use Flow\ETL\GroupBy\GroupBySteps; -use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\Processor; -use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Flow\ETL\Transformer; use Generator; @@ -63,28 +57,6 @@ public static function batches(Rows ...$batches): Generator yield from $batches; } - /** - * Spills $batches into $buckets the way BucketingProcessor does, returning one metadata Rows per - * bucket - the input GroupByAggregationProcessor::process() consumes. - * - * @param list $refs - * - * @return list - */ - public static function bucketMetadata(Buckets $buckets, array $refs, Rows ...$batches): array - { - $strategy = new HashBucketing($refs, 4, new NativeHasher(), new NativePHPRandomValueGenerator(), 'group-by'); - - $metadata = []; - - foreach ($strategy->bucketize(self::batches(...$batches), $buckets->storage()) as $bucket) { - $buckets->add($bucket); - $metadata[] = rows(Bucket::schema(), $bucket->toRow()); - } - - return $metadata; - } - /** * @param Generator $upstream * diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/GroupedRows.php b/src/core/etl/tests/Flow/ETL/Tests/Context/GroupedRows.php new file mode 100644 index 0000000000..62619a8af6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/GroupedRows.php @@ -0,0 +1,95 @@ + $batches + * + * @return array> output rows by the serialized value of $key, sorted + */ + public static function byKey(iterable $batches, string $key): array + { + $rows = []; + + foreach ($batches as $batch) { + foreach ($batch->toArray() as $row) { + $rows[serialize($row[$key])] = $row; + } + } + + ksort($rows); + + return $rows; + } + + /** + * @return Generator two batches: a 10, b 15, then a 20 + */ + public static function categories(): Generator + { + yield array_to_rows( + [['category' => 'a', 'amount' => 10], ['category' => 'b', 'amount' => 15]], + schema(str_schema('category'), int_schema('amount')), + ); + yield array_to_rows( + [['category' => 'a', 'amount' => 20]], + schema(str_schema('category'), int_schema('amount')), + ); + } + + /** + * @param iterable $batches + * + * @return list every batch serialized, sorted - the batches as a set, whatever order they came in + */ + public static function batchesAsSet(iterable $batches): array + { + $serialized = []; + + foreach ($batches as $batch) { + $serialized[] = serialize($batch->toArray()); + } + + sort($serialized); + + return $serialized; + } + + /** + * @param iterable $batches + * + * @return array amount_sum per category + */ + public static function sums(iterable $batches): array + { + $sums = []; + + foreach ($batches as $batch) { + foreach ($batch->toArray() as $row) { + $sums[$row['category']] = $row['amount_sum']; + } + } + + ksort($sums); + + return $sums; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/IdRows.php b/src/core/etl/tests/Flow/ETL/Tests/Context/IdRows.php new file mode 100644 index 0000000000..328478f98f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/IdRows.php @@ -0,0 +1,50 @@ + ...$batches + * + * @return Generator + */ + public static function batches(array ...$batches): Generator + { + foreach ($batches as $batch) { + yield array_to_rows(array_map(static fn(int $id): array => [ + 'id' => $id, + ], $batch), schema(int_schema('id'))); + } + } + + /** + * @param Generator $batches + * + * @return list + */ + public static function ids(Generator $batches): array + { + $ids = []; + + foreach ($batches as $batch) { + $ids = array_merge($ids, $batch->reduceToArray('id')); + } + + return $ids; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/WindowFrameContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/WindowFrameContext.php index 1fddebc210..35cb55e87f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/WindowFrameContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/WindowFrameContext.php @@ -22,9 +22,8 @@ public static function results(DataFrame $frame): array $results = []; foreach ($frame->get() as $batch) { - foreach ($batch as $row) { - $value = $row->get('result'); - + // @mago-ignore analysis:mixed-assignment + foreach ($batch->column('result')->values() as $value) { $results[] = is_int($value) || is_float($value) ? $value : null; } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/WindowProcessorContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/WindowProcessorContext.php index 42ade2eeaa..b8a97fffc5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/WindowProcessorContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/WindowProcessorContext.php @@ -48,8 +48,8 @@ public static function values(string|Definition $entry, WindowFunction $function $values = []; foreach (self::batches($entry, $function, $rows) as $batch) { - foreach ($batch as $row) { - $values[] = $row->get($name); + foreach ($batch->toArray() as $row) { + $values[] = $row[$name]; } } 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 10bfefb505..a5d481fde4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/AddStampToStringEntryTransformer.php @@ -36,12 +36,12 @@ public function transform(Rows $rows, FlowContext $context): Rows { $stamped = []; - foreach ($rows->all() as $row) { + for ($i = 0; $i < $rows->count(); $i++) { $stamped[] = [ - ...$row->values(), + ...$rows->values($i), $this->entryName => sprintf( '%s%s%s', - type_string()->assert($row->get($this->entryName)), + type_string()->assert($rows->column($this->entryName)->value($i)), $this->divider, $this->stamp, ), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ConstantComparison.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ConstantComparison.php new file mode 100644 index 0000000000..1c4853906a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ConstantComparison.php @@ -0,0 +1,36 @@ +isEmpty() ? [] : array_fill(0, $left->count(), $this->result); + } + + public function left(): array + { + return []; + } + + public function right(): array + { + return []; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingDOMDocument.php b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingDOMDocument.php new file mode 100644 index 0000000000..2b4a0ab78d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingDOMDocument.php @@ -0,0 +1,35 @@ + $calls + */ + public function __construct( + public readonly ArrayObject $calls, + ) { + parent::__construct(); + $this->loadXML(''); + } + + public function C14N( + bool $exclusive = false, + bool $withComments = false, + ?array $xpath = null, + ?array $nsPrefixes = null, + ): string|false { + $this->calls->append('C14N'); + + return parent::C14N($exclusive, $withComments, $xpath, $nsPrefixes); + } +} 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 030092d774..8a98023b91 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php @@ -16,7 +16,6 @@ use Generator; use function array_values; -use function count; use function Flow\ETL\DSL\rows; /** @@ -55,30 +54,30 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $this->extractCalls++; $this->contexts[] = $context; - $buffer = []; + $buffer = rows($this->schema); foreach ($this->batches as $rows) { - foreach ($rows->all() as $row) { - $buffer[] = $row; + for ($i = 0; $i < $rows->count(); $i++) { + $buffer = $buffer->concat($rows->slice($i, 1)->matchTo($this->schema)); - if (count($buffer) === $this->batchSize()) { + if ($buffer->count() === $this->batchSize()) { $this->batchesYielded++; - $signal = yield rows($this->schema, ...$buffer); + $signal = yield $buffer; if ($signal === Signal::STOP) { return; } - $buffer = []; + $buffer = rows($this->schema); } } } - if ($buffer !== []) { + if (!$buffer->isEmpty()) { $this->batchesYielded++; - yield rows($this->schema, ...$buffer); + yield $buffer; } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingFrameAccumulating.php b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingFrameAccumulating.php index b04f222955..9d87e452ab 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingFrameAccumulating.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingFrameAccumulating.php @@ -54,8 +54,10 @@ public function apply(WindowContext $window): mixed { $accumulator = $this->accumulator($window->flowContext()); - foreach ($window->frame() as $frameRow) { - $accumulator->accumulate($frameRow); + $frame = $window->frame(); + + for ($index = 0, $count = $frame->count(); $index < $count; $index++) { + $accumulator->accumulate($frame, $index); } return $accumulator->value(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingFrameAccumulator.php b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingFrameAccumulator.php index 54794a2fc6..947c5e9fe2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingFrameAccumulator.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingFrameAccumulator.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Tests\Double; -use Flow\ETL\Row; use Flow\ETL\Row\Reference; +use Flow\ETL\Rows; use Flow\ETL\Window\FrameAccumulator; final class CountingFrameAccumulator implements FrameAccumulator @@ -17,11 +17,12 @@ public function __construct( private readonly CountingFrameAccumulating $spy, ) {} - public function accumulate(Row $row): void + public function accumulate(Rows $rows, int $index): void { $this->spy->accumulateCalls++; - $value = $row->get($this->ref); + // @mago-ignore analysis:mixed-assignment + $value = $rows->column($this->ref->base())->value($index); if (is_int($value) || is_float($value)) { $this->sum += $value; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingReturnsFunction.php b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingReturnsFunction.php index 33ef8d468d..8585e606ba 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingReturnsFunction.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingReturnsFunction.php @@ -4,11 +4,12 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; use Flow\ETL\Function\FunctionTree; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\ScalarFunctionChain; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; /** @@ -46,9 +47,9 @@ public function withChildren(array $children): static return new self($children[0], $this->type); } - public function eval(Row $row, FlowContext $context): mixed + public function eval(Rows $rows, FlowContext $context): Column { - return $this->value->eval($row, $context); + return $this->value->eval($rows, $context); } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php index 199af1e31c..c116c6cc32 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php @@ -19,7 +19,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null): Generator { - yield Rows::of($this->schema()); + yield Rows::empty($this->schema()); } public function schema(): Schema diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FailingOnValuesFunction.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FailingOnValuesFunction.php new file mode 100644 index 0000000000..9e39558343 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FailingOnValuesFunction.php @@ -0,0 +1,108 @@ + + */ + public array $seen = []; + + /** + * @param list $failing + */ + public function __construct( + public readonly ScalarFunction $operand, + public readonly array $failing = [], + public readonly string $failure = self::WITH_ROW, + public readonly ?self $owner = null, + ) {} + + /** + * @return list + */ + public function children(): array + { + return [$this->operand]; + } + + public function counters(): self + { + return $this->owner ?? $this; + } + + public function eval(Rows $rows, FlowContext $context): Column + { + $this->counters()->evals++; + $this->counters()->seen[] = $rows; + $values = (new Parameter($this->operand))->asInts($rows, $context); + + foreach ($values as $i => $value) { + if (!in_array($value, $this->failing, true)) { + continue; + } + + $message = sprintf('fails on %d', $value); + + match ($this->failure) { + self::WITHOUT_ROW => throw new RuntimeException($message), + self::ERROR => throw new Error($message), + default => throw new EvaluationException($i, new RuntimeException($message)), + }; + } + + return (new ResultColumn())->of($this, $values); + } + + /** + * @return Type + */ + public function returns(): Type + { + return type_optional($this->operand->returns()); + } + + /** + * @param list $children + */ + public function withChildren(array $children): static + { + /** @var list $children */ + return new self($children[0], $this->failing, $this->failure, $this->counters()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FixedValuesColumn.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FixedValuesColumn.php new file mode 100644 index 0000000000..59923c27d1 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FixedValuesColumn.php @@ -0,0 +1,98 @@ + $type + * @param list $values + */ + public function __construct( + public Type $type, + public array $values, + ) {} + + public function at(int $i): mixed + { + return $this->values[$i]; + } + + public function concat(Column ...$others): Column + { + throw new RuntimeException('FixedValuesColumn cannot be concatenated'); + } + + public function count(): int + { + return count($this->values); + } + + public function encode(): array + { + throw new RuntimeException('FixedValuesColumn cannot be encoded'); + } + + public function isNull(int $i): bool + { + return $this->values[$i] === null; + } + + public function nullCount(): int + { + return 0; + } + + public function physicals(): array + { + return $this->values; + } + + public function slice(int $offset, int $length): Column + { + return new self($this->type, array_slice($this->values, $offset, $length)); + } + + public function take(array $indices): Column + { + $values = []; + + foreach ($indices as $index) { + $values[] = $this->values[$index]; + } + + return new self($this->type, $values); + } + + public function type(): Type + { + return $this->type; + } + + public function value(int $i): mixed + { + return $this->values[$i]; + } + + public function values(): array + { + return $this->values; + } + + public function withType(Type $type): Column + { + return new self($type, $this->values); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/HoldingExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/HoldingExtractor.php new file mode 100644 index 0000000000..cf39c9d388 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/HoldingExtractor.php @@ -0,0 +1,57 @@ + $batches + */ + public function __construct( + public readonly ReportedMemoryBackend $backend, + public readonly int $bytesPerBatch, + public readonly array $batches, + ) {} + + public function extract(FlowContext $context, ?int $limit = null): Generator + { + foreach ($this->batches as $batch) { + $this->backend->reported += $this->bytesPerBatch; + + $signal = yield $batch; + + if ($signal === Signal::STOP) { + return; + } + } + } + + public function schema(): Schema + { + return $this->batches[0]->schema(); + } + + public function statistics(): Statistics + { + return new Statistics(); + } + + public function withSchema(Schema $schema): static + { + return $this; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/NonStructureUnpackStub.php b/src/core/etl/tests/Flow/ETL/Tests/Double/NonStructureUnpackStub.php index 3c0d828219..7befb6f337 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/NonStructureUnpackStub.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/NonStructureUnpackStub.php @@ -4,14 +4,17 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\FlowContext; use Flow\ETL\Function\FunctionTree; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\ScalarFunction\UnpackResults; use Flow\ETL\Function\ScalarFunctionChain; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; +use function array_fill; use function Flow\Types\DSL\type_string; /** @@ -37,12 +40,10 @@ public function withChildren(array $children): static return $this; } - /** - * @return array - */ - public function eval(Row $row, FlowContext $context): array + public function eval(Rows $rows, FlowContext $context): Column { - return []; + // @mago-ignore analysis:possibly-invalid-argument + return new ValueColumn(array_fill(0, $rows->count(), [])); } /** 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 1661e3e89a..68343b27cc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/OneRowBatchesExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/OneRowBatchesExtractor.php @@ -15,8 +15,6 @@ use Flow\ETL\Schema; use Generator; -use function Flow\ETL\DSL\rows; - /** * Breaks exactly one clause of the batch contract: whatever its batch size, it never puts more than * one row in a batch. @@ -31,8 +29,8 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null): Generator { - foreach ($this->rows->all() as $row) { - $signal = yield rows($this->rows->schema(), $row); + for ($i = 0; $i < $this->rows->count(); $i++) { + $signal = yield $this->rows->slice($i, 1); if ($signal === Signal::STOP) { return; 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 1211caaa85..dbb28e01ca 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php @@ -35,7 +35,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null): Generator { - yield Rows::of($this->schema()); + yield Rows::empty($this->schema()); } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ReportedMemoryBackend.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ReportedMemoryBackend.php new file mode 100644 index 0000000000..091526bc00 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ReportedMemoryBackend.php @@ -0,0 +1,48 @@ +php->adopt($definition, $column); + } + + public function allocatedBytes(): int + { + return $this->reported; + } + + public function builder(Definition $definition): ColumnBuilder + { + return $this->php->builder($definition); + } + + public function constant(Definition $definition, mixed $value, int $count): Column + { + return $this->php->constant($definition, $value, $count); + } + + public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column + { + return $this->php->decode($definition, $buffers, $count, $nullCount); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ReportsResolvedOperand.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ReportsResolvedOperand.php index 4a59319a9c..c8ad84e976 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/ReportsResolvedOperand.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ReportsResolvedOperand.php @@ -4,13 +4,16 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\Column\Column; use Flow\ETL\FlowContext; +use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Function\FunctionTree; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\ScalarFunctionChain; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\Types\Type; +use function array_fill; use function Flow\Types\DSL\type_boolean; /** @@ -41,9 +44,10 @@ public function withChildren(array $children): static return new self($children[0]); } - public function eval(Row $row, FlowContext $context): bool + public function eval(Rows $rows, FlowContext $context): Column { - return $this->operand->resolved(); + // @mago-ignore analysis:possibly-invalid-argument + return (new ResultColumn())->of($this, array_fill(0, $rows->count(), $this->operand->resolved())); } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ReturnsSpyFunction.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ReturnsSpyFunction.php new file mode 100644 index 0000000000..8d2bc41f6a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ReturnsSpyFunction.php @@ -0,0 +1,69 @@ + + */ + public function children(): array + { + return []; + } + + public function eval(Rows $rows, FlowContext $context): Column + { + // @mago-ignore analysis:possibly-invalid-argument + return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), 1)); + } + + /** + * @return Type + */ + public function returns(): Type + { + $this->derivations++; + + if (!$this->derivable) { + throw SchemaNotDerivableException::function('counting', 'no declared type'); + } + + return type_integer(); + } + + /** + * @param list $children + */ + public function withChildren(array $children): static + { + return $this; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBucketsStorage.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBucketsStorage.php index 4a9e864b85..69b62466cf 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBucketsStorage.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBucketsStorage.php @@ -27,6 +27,11 @@ final class SpyBucketsStorage implements BucketsStorage */ private array $readBucketIds = []; + /** + * @var array rows of every set() call, by bucket + */ + public array $setRowCounts = []; + public function __construct( private readonly BucketsStorage $inner, ) {} @@ -77,6 +82,7 @@ public function remove(string $bucketId): void public function set(string $bucketId, Rows $rows): void { + $this->setRowCounts[$bucketId] = $rows->count(); $this->liveBucketIds[$bucketId] = true; $this->inner->set($bucketId, $rows); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyColumn.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyColumn.php new file mode 100644 index 0000000000..34f75089d9 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyColumn.php @@ -0,0 +1,109 @@ + $calls one method name per call + */ + public function __construct( + public Column $inner, + public ArrayObject $calls = new ArrayObject(), + ) {} + + public function at(int $i): mixed + { + $this->calls->append('at'); + + return $this->inner->at($i); + } + + public function concat(Column ...$others): Column + { + $this->calls->append('concat'); + + return new self( + $this->inner->concat(...array_map(static fn(Column $other): Column => $other instanceof self + ? $other->inner + : $other, $others)), + $this->calls, + ); + } + + public function count(): int + { + return $this->inner->count(); + } + + public function encode(): array + { + return $this->inner->encode(); + } + + public function isNull(int $i): bool + { + return $this->inner->isNull($i); + } + + public function nullCount(): int + { + return $this->inner->nullCount(); + } + + public function physicals(): array + { + $this->calls->append('physicals'); + + return $this->inner->physicals(); + } + + public function slice(int $offset, int $length): Column + { + return new self($this->inner->slice($offset, $length), $this->calls); + } + + public function take(array $indices): Column + { + return new self($this->inner->take($indices), $this->calls); + } + + /** + * @return Type + */ + public function type(): Type + { + return $this->inner->type(); + } + + public function value(int $i): mixed + { + $this->calls->append('value'); + + return $this->inner->value($i); + } + + public function values(): array + { + $this->calls->append('values'); + + return $this->inner->values(); + } + + public function withType(Type $type): Column + { + return new self($this->inner->withType($type), $this->calls); + } +} 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 d8093317f4..b04f38fc49 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowWhenRowMatches.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ThrowWhenRowMatches.php @@ -21,8 +21,8 @@ public function __construct( public function transform(Rows $rows, FlowContext $context): Rows { - foreach ($rows as $row) { - if ($row->get($this->column) === $this->value) { + foreach ($rows->toArray() as $row) { + if ($row[$this->column] === $this->value) { throw $this->throwable; } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/UnenumerableSum.php b/src/core/etl/tests/Flow/ETL/Tests/Double/UnenumerableSum.php new file mode 100644 index 0000000000..2714b3a3a7 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/UnenumerableSum.php @@ -0,0 +1,114 @@ + + */ + public readonly array $operands; + + public function __construct( + public readonly Reference $ref, + ScalarFunction ...$operands, + ) { + $this->operands = array_values($operands); + } + + public function aggregate(Rows $rows, array $indices, FlowContext $context): void + { + if ($rows->schema()->findDefinition($this->ref->base()) === null) { + return; + } + + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column($this->ref->base())->take($indices)->values() as $value) { + if (is_int($value) || is_float($value)) { + $this->total = ($this->total ?? 0.0) + $value; + } + } + } + + /** + * @return list + */ + public function children(): array + { + return [$this->ref, ...$this->operands]; + } + + public function merge(AggregatingFunction $other, FlowContext $context): void + { + if (!$other instanceof self) { + throw new InvalidArgumentException(sprintf('%s cannot merge %s', self::class, $other::class)); + } + + if ($other->total !== null) { + $this->total = ($this->total ?? 0.0) + $other->total; + } + } + + public function outputName(): string + { + return $this->ref->to() . '_sum'; + } + + public function references(): ?array + { + return null; + } + + /** + * @return Type + */ + public function returns(): Type + { + return type_optional(type_float()); + } + + public function value(): ?float + { + return $this->total; + } + + /** + * @param list $children + */ + public function withChildren(array $children): static + { + /** @var list $operands */ + $operands = array_slice($children, 1); + + return new self(type_instance_of(Reference::class)->assert($children[0]), ...$operands); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/WindowFunctionOverOperand.php b/src/core/etl/tests/Flow/ETL/Tests/Double/WindowFunctionOverOperand.php new file mode 100644 index 0000000000..6ce2168395 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/WindowFunctionOverOperand.php @@ -0,0 +1,74 @@ +operand->eval($window->frame(), $window->flowContext())->value(0); + } + + /** + * @return list + */ + public function children(): array + { + return [$this->operand]; + } + + public function over(Window $window): static + { + return new self($this->operand, $window); + } + + /** + * @return Type + */ + public function returns(): Type + { + return type_optional($this->operand->returns()); + } + + public function toString(): string + { + return 'operand()'; + } + + public function window(): Window + { + return $this->window ?? throw new RuntimeException('operand() requires an OVER clause.'); + } + + /** + * @param list $children + */ + public function withChildren(array $children): static + { + /** @var list $children */ + return new self($children[0], $this->window); + } +} 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 index 972611841a..c238b8e0a6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Fixtures/Join/AlwaysMeets.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Fixtures/Join/AlwaysMeets.php @@ -5,13 +5,19 @@ namespace Flow\ETL\Tests\Fixtures\Join; use Flow\ETL\Join\Comparison; -use Flow\ETL\Row; +use Flow\ETL\Rows; final readonly class AlwaysMeets implements Comparison { - public function compare(Row $left, Row $right): bool + public function compare(Rows $left, Rows $right): array { - return true; + $met = []; + + for ($i = 0, $count = $left->count(); $i < $count; $i++) { + $met[] = true; + } + + return $met; } public function left(): array diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/SpillingPathsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/SpillingPathsTest.php new file mode 100644 index 0000000000..d00d68ce73 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/SpillingPathsTest.php @@ -0,0 +1,113 @@ + $id, 'g' => $id % 4]; + } + + yield 'group by' => [ + static fn(SpyBucketsStorage $storage, Unit $limit): ConfigBuilder => config_builder()->groupBy( + hash_group_by()->storage($storage)->memoryLimit($limit)->batchSize(2)->bucketsCount(4), + ), + static fn(ConfigBuilder $config): DataFrame => data_frame($config->build()) + ->read(from_array($rows)) + ->batchSize(3) + ->groupBy('g') + ->aggregate(count(ref('id'))), + 4, + ]; + + yield 'repartition' => [ + static fn(SpyBucketsStorage $storage, Unit $limit): ConfigBuilder => config_builder()->repartition( + hash_repartition()->storage($storage)->memoryLimit($limit)->batchSize(2)->bucketsCount(4), + ), + static fn(ConfigBuilder $config): DataFrame => data_frame($config->build()) + ->read(from_array($rows)) + ->batchSize(3) + ->repartition(ref('g')), + 40, + ]; + + yield 'join' => [ + static fn(SpyBucketsStorage $storage, Unit $limit): ConfigBuilder => config_builder()->join( + hash_join()->storage($storage)->memoryLimit($limit)->batchSize(2)->bucketsCount(4), + ), + static fn(ConfigBuilder $config): DataFrame => data_frame($config->build()) + ->read(from_array($rows)) + ->batchSize(3) + ->join( + data_frame()->read(from_array([['g' => 0], ['g' => 1], ['g' => 2], ['g' => 3]]))->batchSize(1), + join_on(['g' => 'g'], 'r_'), + ), + 40, + ]; + } + + /** + * @param callable(SpyBucketsStorage, Unit): ConfigBuilder $config + * @param callable(ConfigBuilder): DataFrame $pipeline + */ + #[DataProvider('paths')] + public function test_under_the_limit_no_frame_is_written(callable $config, callable $pipeline, int $rows): void + { + $storage = new SpyBucketsStorage(new MemoryBuckets()); + + static::assertCount($rows, $pipeline($config($storage, Unit::fromGb(64)))->fetch()->toArray()); + static::assertSame([], $storage->appendedRows()); + } + + /** + * @param callable(SpyBucketsStorage, Unit): ConfigBuilder $config + * @param callable(ConfigBuilder): DataFrame $pipeline + */ + #[DataProvider('paths')] + public function test_past_the_limit_every_frame_holds_a_full_batch( + callable $config, + callable $pipeline, + int $rows, + ): void { + $storage = new SpyBucketsStorage(new MemoryBuckets()); + + static::assertCount($rows, $pipeline($config($storage, Unit::fromBytes(1)))->fetch()->toArray()); + + $frames = array_merge(...array_values($storage->appendedRows())); + + static::assertNotSame([], $frames); + static::assertSame( + array_map(static fn(): int => 2, $frames), + array_map(static fn(Rows $frame): int => $frame->count(), $frames), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php index c1b2883bd7..e16424a191 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php @@ -7,7 +7,6 @@ use DateTimeImmutable; use Flow\ETL\Bucketing\Storage\FilesystemBuckets; use Flow\ETL\Column\PhpBackend; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Tests\Context\BucketsStorageContext; use Flow\ETL\Tests\Double\SpyBackend; @@ -16,7 +15,6 @@ use Flow\Floe\FloeWriter; use function array_map; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; @@ -92,10 +90,7 @@ public function test_appends_accumulate_into_one_bucket_in_order(): void $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 4], ['id' => 5]], schema(int_schema('id')))); - static::assertSame( - [1, 2, 3, 4, 5], - array_map(static fn(Row $r): mixed => $r->get('id'), BucketsStorageContext::rows($storage->get('bucket'))), - ); + static::assertSame([1, 2, 3, 4, 5], array_column(BucketsStorageContext::rows($storage->get('bucket')), 'id')); $this->fs()->rm($cacheDir); } @@ -193,10 +188,7 @@ public function test_round_trips_rows_across_the_read_batch_boundary(): void $storage->append('bucket', array_to_rows($input, schema(int_schema('id')))); - static::assertSame($input, array_map( - static fn(Row $r): array => $r->toArray(), - BucketsStorageContext::rows($storage->get('bucket')), - )); + static::assertSame($input, BucketsStorageContext::rows($storage->get('bucket'))); $this->fs()->rm($cacheDir); } @@ -210,10 +202,7 @@ public function test_set_replaces_a_bucket_written_with_append(): void $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->set('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); - static::assertSame( - [3], - array_map(static fn(Row $r): mixed => $r->get('id'), BucketsStorageContext::rows($storage->get('bucket'))), - ); + static::assertSame([3], array_column(BucketsStorageContext::rows($storage->get('bucket')), 'id')); $this->fs()->rm($cacheDir); } @@ -238,15 +227,9 @@ public function test_round_trips_schema_changing_rows(): void $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); - $input = [ - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2, 'name' => 'John'], schema(int_schema('id'), str_schema('name'))), - array_to_row(['name' => 'Jane'], schema(str_schema('name'))), - ]; - - $storage->append('bucket', rows( + $storage->append('bucket', array_to_rows( + [['id' => 1], ['id' => 2, 'name' => 'John'], ['name' => 'Jane']], schema(int_schema('id', nullable: true), str_schema('name', nullable: true)), - ...$input, )); // one write session = one schema, and every row now carries every column the schema declares - @@ -257,7 +240,7 @@ public function test_round_trips_schema_changing_rows(): void ['id' => 2, 'name' => 'John'], ['id' => null, 'name' => 'Jane'], ], - array_map(static fn(Row $r): array => $r->toArray(), BucketsStorageContext::rows($storage->get('bucket'))), + BucketsStorageContext::rows($storage->get('bucket')), ); $this->fs()->rm($cacheDir); @@ -293,8 +276,8 @@ public function test_append_with_reordered_structure_keys_matches_and_keeps_ever $read = BucketsStorageContext::rows($storage->get('bucket')); static::assertCount(2, $read); - static::assertSame(['a' => 1, 'b' => 'x'], $read[0]->get('s')); - static::assertSame(['a' => 2, 'b' => 'y'], $read[1]->get('s')); + static::assertSame(['a' => 1, 'b' => 'x'], $read[0]['s']); + static::assertSame(['a' => 2, 'b' => 'y'], $read[1]['s']); $this->fs()->rm($cacheDir); } @@ -318,8 +301,8 @@ public function test_append_with_reordered_columns_matches_and_keeps_every_row() static::assertCount(2, $read); static::assertSame([['id' => 1, 'name' => 'x'], ['id' => 2, 'name' => 'y']], [ - $read[0]->toArray(), - $read[1]->toArray(), + $read[0], + $read[1], ]); $this->fs()->rm($cacheDir); @@ -358,7 +341,7 @@ public function test_datetime_values_read_back_as_admitted(): void $rows = array_to_rows([[ 'at' => new DateTimeImmutable('2026-01-02 03:04:05+05:00'), ]], schema(datetime_schema('at', zone: 'Europe/Warsaw'))); - $admitted = type_datetime()->assert($rows->first()->get('at'))->format('c'); + $admitted = type_datetime()->assert($rows->column('at')->value(0))->format('c'); $storage = new FilesystemBuckets($this->fs(), cacheDir: $cacheDir, backend: new PhpBackend()); $storage->set('b', $rows); @@ -366,7 +349,7 @@ public function test_datetime_values_read_back_as_admitted(): void static::assertSame('2026-01-01T23:04:05+01:00', $admitted); static::assertSame( $admitted, - type_datetime()->assert(BucketsStorageContext::rows($storage->get('b'))[0]->get('at'))->format('c'), + type_datetime()->assert(BucketsStorageContext::rows($storage->get('b'))[0]['at'])->format('c'), ); $this->fs()->rm($cacheDir); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php index 38192652c2..051ec918ac 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php @@ -6,14 +6,12 @@ use Exception; use Flow\ETL\Bucketing\Storage\PSRCacheBuckets; -use Flow\ETL\Row; use Flow\ETL\Tests\Context\BucketsStorageContext; use Flow\ETL\Tests\FlowIntegrationTestCase; use Override; use Symfony\Component\Cache\Adapter\RedisAdapter; use Symfony\Component\Cache\Psr16Cache; -use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -50,10 +48,7 @@ public function test_round_trips_rows_across_chunks_and_removes_the_bucket(): vo $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); - static::assertSame( - [1, 2, 3], - array_map(static fn(Row $r): mixed => $r->get('id'), BucketsStorageContext::rows($storage->get('bucket'))), - ); + static::assertSame([1, 2, 3], array_column(BucketsStorageContext::rows($storage->get('bucket')), 'id')); $storage->remove('bucket'); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/MemoryLimitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/MemoryLimitTest.php new file mode 100644 index 0000000000..951446e45b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Config/MemoryLimitTest.php @@ -0,0 +1,41 @@ +percentage(70)->inBytes(), MemoryLimit::default()->inBytes()); + } + + public function test_default_is_one_gib_when_the_memory_limit_is_unlimited(): void + { + ini_set('memory_limit', '-1'); + + static::assertSame(Unit::fromGb(1)->inBytes(), MemoryLimit::default()->inBytes()); + } + + public function test_the_environment_wins_over_the_memory_limit(): void + { + ini_set('memory_limit', '1G'); + putenv(MemoryLimit::ENV . '=64M'); + + try { + static::assertSame(Unit::fromMb(64)->inBytes(), MemoryLimit::default()->inBytes()); + } finally { + putenv(MemoryLimit::ENV); + } + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AlgorithmOverrideTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AlgorithmOverrideTest.php index 4bdef1fa70..f82bfdd829 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AlgorithmOverrideTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/AlgorithmOverrideTest.php @@ -8,6 +8,7 @@ use Flow\ETL\Cache\Implementation\InMemoryCache; use Flow\ETL\DataFrame; use Flow\ETL\DataFrameFactory; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Join\Join; use Flow\ETL\Rows; use Flow\ETL\Tests\Double\RecordingBucketsStorage; @@ -63,9 +64,16 @@ public function test_aggregate_override_reaches_the_aggregation(): void $configured = new RecordingBucketsStorage(new MemoryBuckets()); $output = []; - df(config_builder()->groupBy(hash_group_by()->storage($configured))->build()) + df( + config_builder() + ->groupBy(hash_group_by()->storage($configured)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) + ->build(), + ) ->read(from_array([['g' => 'a'], ['g' => 'b'], ['g' => 'a']])) - ->aggregate([count_agg(ref('g'))], hash_group_by()->storage($pinned)) + ->batchSize(1) + ->aggregate([count_agg(ref( + 'g', + ))], hash_group_by()->storage($pinned)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) ->write(to_array($output)) ->run(); @@ -79,9 +87,14 @@ public function test_group_by_override_reaches_the_aggregation(): void $configured = new RecordingBucketsStorage(new MemoryBuckets()); $output = []; - df(config_builder()->groupBy(hash_group_by()->storage($configured))->build()) + df( + config_builder() + ->groupBy(hash_group_by()->storage($configured)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) + ->build(), + ) ->read(from_array([['g' => 'a'], ['g' => 'b'], ['g' => 'a']])) - ->groupBy([ref('g')], hash_group_by()->storage($pinned)) + ->batchSize(1) + ->groupBy([ref('g')], hash_group_by()->storage($pinned)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) ->aggregate(count_agg(ref('g'))) ->write(to_array($output)) ->run(); @@ -136,13 +149,17 @@ public function test_join_override_reaches_the_hash_join(): void $configured = new RecordingBucketsStorage(new MemoryBuckets()); $output = []; - df(config_builder()->join(hash_join()->storage($configured))->build()) + df( + config_builder() + ->join(hash_join()->storage($configured)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) + ->build(), + ) ->read(from_array([['id' => 1], ['id' => 2]])) ->join( df()->read(from_array([['id' => 1, 'n' => 'a']])), join_on(['id' => 'id'], 'joined_'), Join::left, - hash_join()->storage($pinned), + hash_join()->storage($pinned)->memoryLimit(Unit::fromBytes(1))->batchSize(1), ) ->write(to_array($output)) ->run(); @@ -159,7 +176,7 @@ public function test_override_spill_root_comes_from_the_cache_config(): void $output = []; df(config_builder()->sort(external_sort()->storage(new MemoryBuckets()))->build()) ->read(from_array([['id' => 3], ['id' => 1], ['id' => 2]])) - ->sortBy([ref('id')], external_sort()->runSize(1)->bucketsCount(2)) + ->sortBy([ref('id')], external_sort()->memoryLimit(Unit::fromBytes(1))->batchSize(1)->bucketsCount(2)) ->write(to_array($output)) ->run(); @@ -179,9 +196,13 @@ public function test_sort_by_pins_the_algorithm_for_this_operation(): void $configured = new RecordingBucketsStorage(new MemoryBuckets()); $output = []; - df(config_builder()->sort(external_sort()->storage($configured)->runSize(1))->build()) + df( + config_builder() + ->sort(external_sort()->storage($configured)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) + ->build(), + ) ->read(from_array([['id' => 3], ['id' => 1], ['id' => 2]])) - ->sortBy([ref('id')], external_sort()->storage($pinned)->runSize(1)) + ->sortBy([ref('id')], external_sort()->storage($pinned)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) ->write(to_array($output)) ->run(); @@ -195,7 +216,11 @@ public function test_sort_by_without_an_algorithm_uses_the_configured_one(): voi $configured = new RecordingBucketsStorage(new MemoryBuckets()); $output = []; - df(config_builder()->sort(external_sort()->storage($configured)->runSize(1))->build()) + df( + config_builder() + ->sort(external_sort()->storage($configured)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) + ->build(), + ) ->read(from_array([['id' => 3], ['id' => 1], ['id' => 2]])) ->sortBy([ref('id')]) ->write(to_array($output)) 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 74905ee6c7..ec56dd24e6 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 @@ -252,11 +252,11 @@ public function test_group_by_multiples_columns_with_avg_aggregation_with_null() static::assertSame( [ + ['country' => 'US', 'gender' => null, 'age_avg' => 45.0], ['country' => 'PL', 'gender' => 'female', 'age_avg' => 30.0], ['country' => 'US', 'gender' => 'female', 'age_avg' => 40.0], ['country' => 'PL', 'gender' => 'male', 'age_avg' => 21.67], ['country' => 'US', 'gender' => 'male', 'age_avg' => 45.0], - ['country' => 'US', 'gender' => null, 'age_avg' => 45.0], ], $rows->sortBy(ref('gender'), ref('country'))->toArray(), ); 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 72d1520269..5bc8570ddb 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 @@ -70,8 +70,8 @@ public function test_mathematical_operations_on_floats(): void ], schema(integer_schema('id'), float_schema('price'), integer_schema('quantity'), float_schema('weight')), ))) - ->withEntry('discount', ref('price')->multiply(-0.1)) - ->withEntry('total_weight', ref('weight')->multiply(ref('quantity'))) + ->withEntry('discount', ref('price')->multiply(-0.1, exact: true)) + ->withEntry('total_weight', ref('weight')->multiply(ref('quantity'), exact: true)) ->forEach(static function (Rows $r) use (&$rows): void { $rows = $rows->merge($r); }); 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 ee39ed6925..914325adce 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 @@ -386,11 +386,11 @@ public function test_pagination_scenario(): void $data = array_map(static fn(int $id): array => ['id' => $id, 'name' => 'Item ' . $id], range(1, 100)); $page1 = df()->read(from_array($data))->offset(0)->limit(10)->fetch(); static::assertCount(10, $page1); - static::assertSame(1, $page1->first()->get('id')); - static::assertSame(10, $page1->all()[9]->get('id')); + static::assertSame(1, $page1->column('id')->value(0)); + static::assertSame(10, $page1->column('id')->value(9)); $page3 = df()->read(from_array($data))->offset(20)->limit(10)->fetch(); static::assertCount(10, $page3); - static::assertSame(21, $page3->first()->get('id')); - static::assertSame(30, $page3->all()[9]->get('id')); + static::assertSame(21, $page3->column('id')->value(0)); + static::assertSame(30, $page3->column('id')->value(9)); } } 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 94b13ff657..9501e715f2 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 @@ -370,6 +370,6 @@ public function test_pruning_single_partition(): void ->fetch(); static::assertCount(1, $rows); - static::assertSame(2023, $rows->first()->get('year')); + static::assertSame(2023, $rows->column('year')->value(0)); } } 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 bab5167d63..40b8745285 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 @@ -50,8 +50,8 @@ final class PlanBindTest extends FlowTestCase ]; /** - * One plan per bind class of the step table. The two exclusions the plan names - a refused bind - * (joinEach) and the BucketingProcessor metadata hop - are covered by their own tests. + * One plan per bind class of the step table. The exclusion the plan names - a refused bind (joinEach) - is + * covered by its own tests. * * @return Generator */ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php index ac7433fe7b..39a3f134f3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SinkRootBlockingOperationsTest.php @@ -173,7 +173,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 { - // 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 - in one batch, aggregated in memory. $spy = new SpyLoader(); $sumVByGroup = new CallbackTransformation(static function (DataFrame $df): DataFrame { return $df->groupBy([ref('g')])->aggregate(sum(ref('v'))); @@ -184,15 +184,15 @@ public function test_group_by_aggregate_inside_a_transformation_merges_groups_ac ->write(to_transformation($sumVByGroup, $spy)) ->run(); - static::assertSame([1, 1], $spy->loadedRowCounts()); + static::assertSame([2], $spy->loadedRowCounts()); static::assertSame([['g' => 'a', 'v_sum' => 6.0], ['g' => 'b', 'v_sum' => 60.0]], $spy->loadedRowsToArray()); } public function test_join_inside_a_transformation_matches_every_row(): void { - // REGRESSION GUARD - asserts CORRECT behaviour. HashJoinProcessor buffers the RIGHT side, which is a separate - // complete frame, and buckets the left side. Under one stream the buckets span the stream, so the output is - // grouped by join key in 2 chunks of 3 - byte for byte what the same join gives on the outer frame. + // REGRESSION GUARD - asserts CORRECT behaviour. HashJoinProcessor reads the RIGHT side, a separate complete + // frame, first; it fits under the memory limit, so the left stream joins batch by batch in its own order - + // byte for byte what the same join gives on the outer frame. $spy = new SpyLoader(); $joinNames = new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->join( data_frame()->process(array_to_rows( @@ -208,14 +208,14 @@ public function test_join_inside_a_transformation_matches_every_row(): void ->write(to_transformation($joinNames, $spy)) ->run(); - static::assertSame([3, 3], $spy->loadedRowCounts()); + static::assertSame([2, 2, 2], $spy->loadedRowCounts()); static::assertSame( [ ['g' => 'a', 'v' => 1, 'j_code' => 'a', 'j_n' => 'Alpha'], - ['g' => 'a', 'v' => 2, 'j_code' => 'a', 'j_n' => 'Alpha'], - ['g' => 'a', 'v' => 3, 'j_code' => 'a', 'j_n' => 'Alpha'], ['g' => 'b', 'v' => 10, 'j_code' => 'b', 'j_n' => 'Bravo'], + ['g' => 'a', 'v' => 2, 'j_code' => 'a', 'j_n' => 'Alpha'], ['g' => 'b', 'v' => 20, 'j_code' => 'b', 'j_n' => 'Bravo'], + ['g' => 'a', 'v' => 3, 'j_code' => 'a', 'j_n' => 'Alpha'], ['g' => 'b', 'v' => 30, 'j_code' => 'b', 'j_n' => 'Bravo'], ], $spy->loadedRowsToArray(), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SortTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SortTest.php index d441952df3..18d60f8ec9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SortTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/SortTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Integration\DataFrame; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Tests\Double\FakeExtractor; use Flow\ETL\Tests\FlowIntegrationTestCase; @@ -47,15 +48,15 @@ public function test_a_bare_reference_honours_its_sort_order(): void public function test_etl_sort_by_external_sort(): void { - $config = config_builder()->sort(external_sort()->runSize(100)); + $config = config_builder()->sort(external_sort()->memoryLimit(Unit::fromBytes(1))); $rows = df($config->build()) - ->read(new FakeExtractor(2500)) - ->batchSize(50) + ->read(new FakeExtractor(100)) + ->batchSize(20) ->sortBy([ref('int')]) ->fetch(); - static::assertSame(range(0, 2499), $rows->reduceToArray('int')); + static::assertSame(range(0, 99), $rows->reduceToArray('int')); } public function test_etl_sort_by_in_memory(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Dataset/SharedMemoryLimitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Dataset/SharedMemoryLimitTest.php new file mode 100644 index 0000000000..f203cd725b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Dataset/SharedMemoryLimitTest.php @@ -0,0 +1,62 @@ +backend($backend) + ->join(hash_join()->storage($joinStorage)->memoryLimit($limit)) + ->sort(external_sort()->storage($sortStorage)->memoryLimit($limit)) + ->build(), + ) + ->read(new HoldingExtractor($backend, 200 * $megabyte, [ + array_to_rows([['id' => 2]], $schema), + array_to_rows([['id' => 3]], $schema), + array_to_rows([['id' => 1]], $schema), + ])) + ->join(data_frame()->read(new HoldingExtractor($backend, 50 * $megabyte, [ + array_to_rows([['id' => 1], ['id' => 2]], $schema), + array_to_rows([['id' => 3]], $schema), + ])), join_on(['id' => 'id'], 'r_')) + ->sortBy(ref('id')) + ->fetch(); + + static::assertSame([1, 2, 3], $sorted->reduceToArray('id')); + static::assertSame([], $joinStorage->appendedRows(), 'the join build fits and stays in memory'); + static::assertNotSame([], $sortStorage->appended, 'the sort must spill: the process passed the limit'); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/ConfigIsolationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/ConfigIsolationTest.php index cc4799a6fa..456b369f49 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/ConfigIsolationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/ConfigIsolationTest.php @@ -37,7 +37,7 @@ public function test_a_failed_run_does_not_leave_a_stream_registered_on_a_shared ->batchSize(10) ->write(to_floe($destination, options: floe_options(buffer_size: 64))) ->write(new InlineLoader(static function (Rows $rows, FlowContext $context): void { - if ($rows->first()->get('id') === 101) { + if ($rows->column('id')->value(0) === 101) { throw new RuntimeException('aborted mid run'); } })) @@ -91,8 +91,8 @@ public function test_a_dead_run_does_not_bleed_into_the_next_on_the_same_sink(): $ids = []; foreach (data_frame($config)->read(from_floe($destination))->get() as $batch) { - foreach ($batch as $row) { - $ids[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayKeysStyleConvertTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayKeysStyleConvertTest.php index 800d22a5bd..105a6b540b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayKeysStyleConvertTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/ArrayKeysStyleConvertTest.php @@ -6,10 +6,10 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Memory\ArrayMemory; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_keys_style_convert; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\flow_context; @@ -45,8 +45,30 @@ public function test_array_keys_style_convert_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - array_keys_style_convert(ref('string'), 'camel')->eval(array_to_row([ - 'string' => 'test', - ], schema(str_schema('string'))), $context); + (new FunctionContext($context))->eval( + array_keys_style_convert(ref('string'), 'camel'), + [ + 'string' => 'test', + ], + schema(str_schema('string')), + ); + } + + public function test_a_nested_convert_stores_the_converted_shape(): void + { + data_frame() + ->read(from_array([ + ['id' => 1, 'array' => ['itemId' => 1, 'itemVariants' => [['variantName' => 'a']]]], + ])) + ->withEntry('array', array_keys_style_convert(ref('array'), 'snake')) + ->write(to_memory($memory = new ArrayMemory())) + ->run(); + + static::assertSame( + [ + ['id' => 1, 'array' => ['item_id' => 1, 'item_variants' => [['variant_name' => 'a']]]], + ], + $memory->dump(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/CastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/CastTest.php index b8b22f3a55..43e6a6c284 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/CastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/CastTest.php @@ -73,7 +73,8 @@ public function test_cast_to_array(): void ->fetch(); // Cast declares type_array (a json column) and the bind enforces that declaration. - $json = $rows->first()->get('b'); + // @mago-ignore analysis:mixed-assignment + $json = $rows->column('b')->value(0); static::assertInstanceOf(Json::class, $json); static::assertSame([1, 2, 3], $json->toArray()); @@ -81,15 +82,17 @@ public function test_cast_to_array(): void public function test_cast_non_deterministic_values(): void { - $row = df() - ->read(from_array([ - ['array' => []], - ])) - ->withEntry('list_int', ref('array')->cast(type_optional(type_list(type_integer())))) - ->drop('array') - ->fetch() - ->first(); - - static::assertSame([], $row->get('list_int')); + static::assertSame( + [], + df() + ->read(from_array([ + ['array' => []], + ])) + ->withEntry('list_int', ref('array')->cast(type_optional(type_list(type_integer())))) + ->drop('array') + ->fetch() + ->column('list_int') + ->value(0), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php index 5870506006..2d9cb560fc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/DOMElementNextSiblingTest.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Tests\Integration\Function; use DOMDocument; +use DOMElement; use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\RequiresPhp; @@ -17,6 +18,7 @@ use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_html_element; +use function Flow\Types\DSL\type_instance_of; final class DOMElementNextSiblingTest extends FlowTestCase { @@ -98,4 +100,20 @@ public function test_xml_sibling_element_value(): void $rows->toArray(), ); } + + public function test_storing_the_element_of_an_xpath_chain_keeps_its_markup(): void + { + $dom = new DOMDocument(); + $dom->loadXML('User Name01'); + + $rows = df() + ->read(from_rows(array_to_rows([['xml' => $dom]], schema(xml_schema('xml'))))) + ->withEntry('sibling', ref('xml')->xpath('/user/name')->arrayGet('0')->domElementNextSibling()) + ->select('sibling') + ->fetch(); + + $sibling = type_instance_of(DOMElement::class)->assert($rows->column('sibling')->value(0)); + + static::assertSame('01', $sibling->ownerDocument?->saveXML($sibling)); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/UntypedIntermediateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/UntypedIntermediateTest.php new file mode 100644 index 0000000000..06a62b3c7e --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/UntypedIntermediateTest.php @@ -0,0 +1,58 @@ +) still hands its values to a parent + * that can. + * + * @return Generator + */ + public static function trees(): Generator + { + yield 'upper of an array_get' => [ref('j')->jsonDecode()->arrayGet('name')->upper(), 'string', 'ANN']; + yield 'is null of an array_get' => [ref('j')->jsonDecode()->arrayGet('name')->isNull(), 'boolean', false]; + yield 'size of an array_get' => [ref('j')->jsonDecode()->arrayGet('tags')->size(), 'integer', 2]; + yield 'cast of an array_get' => [ref('j')->jsonDecode()->arrayGet('n')->cast(type_string()), 'string', '3']; + yield 'size of array_keys' => [ref('j')->jsonDecode()->arrayKeys()->size(), 'integer', 3]; + } + + #[DataProvider('trees')] + public function test_a_parent_of_an_untyped_node_runs(ScalarFunction $tree, string $type, mixed $value): void + { + $rows = data_frame() + ->read(from_array([['j' => '{"name":"ann","tags":["a","b"],"n":3}']], schema(json_schema('j')))) + ->withEntry('x', $tree) + ->fetch(); + + static::assertSame($type, $rows->schema()->get('x')->type()->toString()); + static::assertSame($value, $rows->values(0)['x']); + } + + public function test_storing_an_untyped_node_is_refused_at_bind(): void + { + $this->expectException(SchemaNotDerivableException::class); + + data_frame() + ->read(from_array([['j' => '{"name":"ann"}']], schema(json_schema('j')))) + ->withEntry('x', ref('j')->jsonDecode()->arrayGet('name')) + ->fetch(); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortLifecycleTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortLifecycleTest.php index b81a63e105..10d76afb30 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortLifecycleTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortLifecycleTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Integration\Sort\ExternalSort; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\Double\ThrowWhenRowMatches; use Flow\ETL\Tests\FlowIntegrationTestCase; @@ -22,8 +23,9 @@ final class ExternalSortLifecycleTest extends FlowIntegrationTestCase public function test_a_clean_run_leaves_no_spilled_runs(): void { $output = []; - df(config_builder()->sort(external_sort()->runSize(1)->bucketsCount(2))->build()) + df(config_builder()->sort(external_sort()->memoryLimit(Unit::fromBytes(1))->bucketsCount(2))->build()) ->read(from_array($this->descendingIds())) + ->batchSize(1) ->sortBy([ref('id')]) ->write(to_array($output)) ->run(); @@ -37,8 +39,9 @@ public function test_upstream_failure_leaves_no_spilled_runs(): void $output = []; try { - df(config_builder()->sort(external_sort()->runSize(1)->bucketsCount(2))->build()) + df(config_builder()->sort(external_sort()->memoryLimit(Unit::fromBytes(1))->bucketsCount(2))->build()) ->read(from_array($this->descendingIds())) + ->batchSize(1) ->with(new ThrowWhenRowMatches('id', 5, new RuntimeException('upstream failed mid-bucketing'))) ->sortBy([ref('id')]) ->write(to_array($output)) diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortMergeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortMergeTest.php index 2cc5a1422f..3027564133 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortMergeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortMergeTest.php @@ -5,7 +5,9 @@ namespace Flow\ETL\Tests\Integration\Sort\ExternalSort; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Tests\Double\RecordingBucketsStorage; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Filesystem\Path\Filter\KeepAll; @@ -28,18 +30,40 @@ public function test_external_sort_over_three_merge_generations_loses_no_rows(): { $input = []; - for ($id = 100; $id > 0; $id--) { + for ($id = 16; $id > 0; $id--) { $input[] = ['id' => $id]; } $output = []; - df(config_builder()->sort(external_sort()->runSize(1)->bucketsCount(2))->build()) + df(config_builder()->sort(external_sort()->memoryLimit(Unit::fromBytes(1))->bucketsCount(2))->build()) ->read(from_array($input)) + ->batchSize(2) ->sortBy([ref('id')]) ->write(to_array($output)) ->run(); - static::assertSame(range(1, 100), array_column($output, 'id')); + static::assertSame(range(1, 16), array_column($output, 'id')); + } + + public function test_spilled_runs_are_read_back_through_the_configured_backend(): void + { + $backend = new SpyBackend(); + $output = []; + + df( + config_builder() + ->backend($backend) + ->sort(external_sort()->memoryLimit(Unit::fromBytes(1))) + ->build(), + ) + ->read(from_array([['id' => 3], ['id' => 1], ['id' => 2]])) + ->batchSize(1) + ->sortBy(ref('id')) + ->write(to_array($output)) + ->run(); + + static::assertSame([1, 2, 3], array_column($output, 'id')); + static::assertGreaterThan(0, $backend->decodes()); } public function test_memory_storage_spills_nothing_to_disk(): void @@ -51,8 +75,13 @@ public function test_memory_storage_spills_nothing_to_disk(): void } $output = []; - df(config_builder()->sort(external_sort()->storage(new MemoryBuckets())->runSize(1)->bucketsCount(2))->build()) + df( + config_builder() + ->sort(external_sort()->storage(new MemoryBuckets())->memoryLimit(Unit::fromBytes(1))->bucketsCount(2)) + ->build(), + ) ->read(from_array($input)) + ->batchSize(1) ->sortBy([ref('id')]) ->write(to_array($output)) ->run(); @@ -80,10 +109,17 @@ public function test_merge_storage_receives_only_merged_runs(): void $output = []; df( config_builder() - ->sort(external_sort()->storage($spill)->mergeStorage($merge)->runSize(1)->bucketsCount(2)) + ->sort( + external_sort() + ->storage($spill) + ->mergeStorage($merge) + ->memoryLimit(Unit::fromBytes(1)) + ->bucketsCount(2), + ) ->build(), ) ->read(from_array($input)) + ->batchSize(1) ->sortBy([ref('id')]) ->write(to_array($output)) ->run(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortRunSizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortRunSizeTest.php new file mode 100644 index 0000000000..d7b61039cb --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Sort/ExternalSort/ExternalSortRunSizeTest.php @@ -0,0 +1,68 @@ +fs, path($this->cacheDir->path() . '/sort-runs'), new PhpBackend()), + ); + + // one ~1 MB row a batch against ~4.5 MB: a run holds a few batches - once spilled to disk, its memory is free + $input = (static function (): Generator { + for ($id = 40; $id > 0; $id--) { + yield array_to_rows( + [['id' => $id, 'payload' => str_repeat(chr(65 + ($id % 26)), 1_000_000)]], + schema(int_schema('id'), str_schema('payload')), + ); + } + })(); + + $sorted = iterator_to_array( + ExternalSortMother::with(refs('id'), $storage, Unit::fromBytes(memory_get_usage(false) + 4_500_000))->sort( + $input, + flow_context(config()), + ), + false, + ); + + $runs = array_values($storage->setRowCounts); + + static::assertSame(40, array_sum(array_map(static fn($batch): int => $batch->count(), $sorted))); + static::assertGreaterThanOrEqual(2, count($runs)); + + foreach (array_slice($runs, 0, -1) as $rows) { + static::assertGreaterThan(1, $rows, 'a run after a spill must hold more than one batch'); + } + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/ExternalSortMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/ExternalSortMother.php new file mode 100644 index 0000000000..aed13be662 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/ExternalSortMother.php @@ -0,0 +1,67 @@ + $batchSize + */ + public static function inMemory( + References $refs, + BucketsStorage $storage = new MemoryBuckets(), + int $batchSize = 1000, + ): ExternalSort { + return self::with($refs, $storage, Unit::fromGb(1), batchSize: $batchSize); + } + + /** + * A one byte limit - every non-empty batch is spilled as its own sorted run. + * + * @param int<1, max> $mergeFanIn + * @param int<1, max> $batchSize + */ + public static function spilling( + References $refs, + BucketsStorage $storage = new MemoryBuckets(), + int $mergeFanIn = 10, + int $batchSize = 1000, + ): ExternalSort { + return self::with($refs, $storage, Unit::fromBytes(1), $mergeFanIn, $batchSize); + } + + /** + * @param int<1, max> $mergeFanIn + * @param int<1, max> $batchSize + */ + public static function with( + References $refs, + BucketsStorage $storage, + Unit $memoryLimit, + int $mergeFanIn = 10, + int $batchSize = 1000, + ?BucketsStorage $mergeStorage = null, + ): ExternalSort { + return new ExternalSort( + $refs, + new Buckets($storage), + new Buckets($mergeStorage ?? $storage), + new NativePHPRandomValueGenerator(), + $memoryLimit, + $mergeFanIn, + $batchSize, + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/GroupByAggregationProcessorMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/GroupByAggregationProcessorMother.php new file mode 100644 index 0000000000..92298a5897 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/GroupByAggregationProcessorMother.php @@ -0,0 +1,54 @@ + $bucketsCount + * @param int<1, max> $batchSize + */ + public static function with( + GroupBy $groupBy, + BucketsStorage $storage, + Unit $memoryLimit, + int $bucketsCount = 4, + int $batchSize = 1000, + ): GroupByAggregationProcessor { + return new GroupByAggregationProcessor( + $groupBy, + new HashBucketing( + $groupBy->references(), + $bucketsCount, + new NativeHasher(), + new NativePHPRandomValueGenerator(), + 'group-by', + ), + new Buckets($storage), + $memoryLimit, + $batchSize, + ); + } +} 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 8859c806c8..c3697f60ca 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/HashJoinProcessorMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/HashJoinProcessorMother.php @@ -7,6 +7,7 @@ use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Executor; use Flow\ETL\Executor\PhysicalPlan; use Flow\ETL\Join\Expression; @@ -18,7 +19,7 @@ final class HashJoinProcessorMother { /** - * Non-resident in-memory storage - exercises the grace hash join path without disk I/O. + * Non-resident in-memory storage and a one-byte limit - exercises the grace hash join path without disk I/O. * * @param int<1, max> $bucketsCount * @param int<1, max> $batchSize @@ -38,6 +39,7 @@ public static function grace( $storage ?? new SpyBucketsStorage(new MemoryBuckets()), $bucketsCount, $batchSize, + Unit::fromBytes(1), ); } @@ -66,6 +68,7 @@ public static function with( BucketsStorage $storage, int $bucketsCount = 64, int $batchSize = 1000, + ?Unit $memoryLimit = null, ): HashJoinProcessor { return new HashJoinProcessor( $right, @@ -75,6 +78,7 @@ public static function with( new Buckets($storage), new Buckets($storage), new NativePHPRandomValueGenerator(), + $memoryLimit ?? Unit::fromGb(1), $bucketsCount, $batchSize, ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/ListColumnsMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/ListColumnsMother.php index cf28f32ae3..158beba2a9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/ListColumnsMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/ListColumnsMother.php @@ -4,10 +4,10 @@ namespace Flow\ETL\Tests\Mother; -use Flow\ETL\Row; +use Flow\ETL\Rows; use Flow\ETL\Schema; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\schema; @@ -33,16 +33,16 @@ public static function schema(): Schema /** * @param array $override */ - public static function row(array $override = []): Row + public static function rows(array $override = []): Rows { - return array_to_row([ + return array_to_rows([[ 'id' => 'a', 'tags' => ['x', 'y'], 'nums' => [1, 2, 3], 'lists' => [['q', 'r'], ['s']], 'flags' => [true, false], ...$override, - ], self::schema()->makeNullable()); + ]], self::schema()->makeNullable()); } public static function tagsSchema(): Schema diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/RepartitionProcessorMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/RepartitionProcessorMother.php new file mode 100644 index 0000000000..7215e5f352 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/RepartitionProcessorMother.php @@ -0,0 +1,49 @@ + $bucketsCount + */ + public static function with( + References $by, + BucketsStorage $storage, + Unit $memoryLimit, + int $bucketsCount = 4, + ): RepartitionProcessor { + return new RepartitionProcessor( + $by, + new HashBucketing( + $by->all(), + $bucketsCount, + new NativeHasher(), + new NativePHPRandomValueGenerator(), + 'repartition', + ), + new Buckets($storage), + $memoryLimit, + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/RowsMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/RowsMother.php index 6a3d4e30a5..4b69b1be0f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/RowsMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/RowsMother.php @@ -4,10 +4,8 @@ namespace Flow\ETL\Tests\Mother; -use Flow\ETL\Row; use Flow\ETL\Rows; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -77,11 +75,11 @@ public static function sequentialIds(int $count): Rows /** * One row whose "array_entry" structure nests a structure: {id, status, enabled, array: {foo}}. */ - public static function arrayEntry(): Row + public static function arrayEntry(): Rows { - return array_to_row([ + return array_to_rows([[ 'array_entry' => ['id' => 1, 'status' => 'PENDING', 'enabled' => true, 'array' => ['foo' => 'bar']], - ], schema(structure_schema('array_entry', type_structure([ + ]], schema(structure_schema('array_entry', type_structure([ 'id' => type_integer(), 'status' => type_string(), 'enabled' => type_boolean(), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/SortDatasetMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/SortDatasetMother.php new file mode 100644 index 0000000000..57253a9d95 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/SortDatasetMother.php @@ -0,0 +1,107 @@ +, + * runs: list>>, + * storedBatchSize: int<1, max>, + * mergeBatchSize: int<1, max> + * } + */ +final class SortDatasetMother +{ + /** + * Rows over small domains (many ties) with nulls, NaN, -0.0, numeric-looking strings and datetimes, split into + * 2-8 consecutive runs, sorted by 1-3 distinct random columns in random directions and null placements. "id" is unique and never a key. + * + * @return SortDatasetShape + */ + public static function random(int $seed): array + { + mt_srand($seed); + + $columns = ['i', 'f', 's', 'at', 'b']; + $floats = [null, NAN, -0.0, 0.0, 1.5, -2.25, 10.0]; + $strings = [null, '10', '9', '100', 'a', 'B', '', '09']; + $instants = [ + null, + '2026-01-01 00:00:00', + '2026-01-01 00:00:00.5', + '1969-12-31 23:59:59', + '2030-06-15 12:00:00', + ]; + $utc = new DateTimeZone('UTC'); + $rows = []; + + for ($id = 0, $count = mt_rand(0, 60); $id < $count; $id++) { + $instant = $instants[mt_rand(0, 4)]; + $rows[] = [ + 'id' => $id, + 'i' => mt_rand(0, 5) === 0 ? null : mt_rand(-3, 3), + 'f' => $floats[mt_rand(0, 6)], + 's' => $strings[mt_rand(0, 7)], + 'at' => $instant === null ? null : new DateTimeImmutable($instant, $utc), + 'b' => mt_rand(0, 3) === 0 ? null : mt_rand(0, 1) === 1, + ]; + } + + $references = []; + + for ($k = 0, $keyCount = mt_rand(1, 3); $k < $keyCount; $k++) { + $reference = ref(array_splice($columns, mt_rand(0, count($columns) - 1), 1)[0]); + $nulls = mt_rand(0, 1) === 1 ? NullsOrder::FIRST : NullsOrder::LAST; + $references[] = mt_rand(0, 1) === 1 ? $reference->asc($nulls) : $reference->desc($nulls); + } + + $runs = []; + $runCount = mt_rand(2, 8); + $offset = 0; + + for ($r = 0; $r < $runCount; $r++) { + $size = $r === ($runCount - 1) ? $count - $offset : mt_rand(0, $count - $offset); + $runs[] = array_slice($rows, $offset, $size); + $offset += $size; + } + + return [ + 'schema' => schema( + int_schema('id'), + int_schema('i', nullable: true), + float_schema('f', nullable: true), + str_schema('s', nullable: true), + datetime_schema('at', nullable: true), + bool_schema('b', nullable: true), + ), + 'references' => $references, + 'runs' => $runs, + 'storedBatchSize' => mt_rand(1, 7), + 'mergeBatchSize' => mt_rand(1, 10), + ]; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Mother/WindowContextMother.php b/src/core/etl/tests/Flow/ETL/Tests/Mother/WindowContextMother.php index d4b4c87b34..76ee36a471 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Mother/WindowContextMother.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Mother/WindowContextMother.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Tests\Mother; use Flow\ETL\FlowContext; -use Flow\ETL\Row; use Flow\ETL\Rows; use Flow\ETL\Window\WholePartitionFrame; use Flow\ETL\Window\WindowContext; @@ -21,22 +20,6 @@ public static function atIndex( ?WindowFrame $frame = null, ?FlowContext $context = null, ): WindowContext { - return self::forRow($partition[$index], $partition, $index, $frame, $context); - } - - public static function forRow( - Row $row, - Rows $partition, - int $index = 0, - ?WindowFrame $frame = null, - ?FlowContext $context = null, - ): WindowContext { - return new WindowContext( - $row, - $index, - $partition, - $frame ?? new WholePartitionFrame(), - $context ?? flow_context(), - ); + return new WindowContext($index, $partition, $frame ?? new WholePartitionFrame(), $context ?? flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketRunTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketRunTest.php index b686f2265d..c13663bbf5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketRunTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketRunTest.php @@ -11,7 +11,6 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\BucketMother; -use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -44,15 +43,11 @@ public function test_rows_are_read_through_the_buckets_that_wrote_them(): void static::assertSame( [1], - array_map(static fn($r): mixed => $r->get( - 'id', - ), BucketsStorageContext::rows((new BucketRun('shared-id', $a))->rows())), + array_column(BucketsStorageContext::rows((new BucketRun('shared-id', $a))->rows()), 'id'), ); static::assertSame( [2], - array_map(static fn($r): mixed => $r->get( - 'id', - ), BucketsStorageContext::rows((new BucketRun('shared-id', $b))->rows())), + array_column(BucketsStorageContext::rows((new BucketRun('shared-id', $b))->rows()), 'id'), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketShapeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketShapeTest.php deleted file mode 100644 index 478d51d9bf..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketShapeTest.php +++ /dev/null @@ -1,17 +0,0 @@ -value); - static::assertSame('_bucket_total_rows', BucketShape::totalRows->value); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketTest.php index 40ee74dd20..70d30eb219 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/BucketTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Tests\Unit\Bucketing; use Flow\ETL\Bucketing\Bucket; -use Flow\ETL\Bucketing\BucketShape; use Flow\ETL\Tests\FlowTestCase; final class BucketTest extends FlowTestCase @@ -18,13 +17,4 @@ public function test_exposes_identity_total_rows_and_index(): void static::assertSame(7, $bucket->totalRows); static::assertSame(3, $bucket->index); } - - public function test_to_row_carries_id_and_total_rows(): void - { - $row = (new Bucket('bucket-1', 4, 0))->toRow(); - - static::assertSame('bucket-1', $row->get(BucketShape::id->value)); - static::assertSame(4, $row->get(BucketShape::totalRows->value)); - static::assertCount(2, $row->values()); - } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/HashBucketingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/HashBucketingTest.php index 9467c23934..187311fd59 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/HashBucketingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/HashBucketingTest.php @@ -201,4 +201,27 @@ public function test_throws_when_buckets_count_below_one(): void // @mago-ignore analysis:invalid-argument new HashBucketing([ref('id')], 0, new NativeHasher(), new NativePHPRandomValueGenerator()); } + + public function test_rows_of_one_key_across_batches_stay_in_batch_order(): void + { + $strategy = new HashBucketing([ref('k')], 1, new NativeHasher(), new NativePHPRandomValueGenerator()); + $storage = new MemoryBuckets(); + + $generator = (static function () { + yield array_to_rows( + [['k' => 1, 'v' => 1], ['k' => 2, 'v' => 2], ['k' => 1, 'v' => 3]], + schema(int_schema('k'), int_schema('v')), + ); + yield array_to_rows([['k' => 1, 'v' => 4]], schema(int_schema('k'), int_schema('v'))); + })(); + + $buckets = iterator_to_array($strategy->bucketize($generator, $storage)); + $values = []; + + foreach ($storage->get($buckets[0]->id) as $batch) { + $values = [...$values, ...$batch->column('v')->values()]; + } + + static::assertSame([1, 2, 3, 4], $values); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyValuesTest.php index 1578c743a2..39dbca4b29 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/KeyValuesTest.php @@ -5,76 +5,74 @@ namespace Flow\ETL\Tests\Unit\Bucketing; use Flow\ETL\Bucketing\KeyValues; -use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; +use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; final class KeyValuesTest extends FlowTestCase { - public function test_of_projects_each_row(): void + public function test_a_missing_ref_throws(): void { - static::assertSame( - [[1], [2]], - (new KeyValues([ref('id')]))->of(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))), - ); + $this->expectException(SchemaDefinitionNotFoundException::class); + $this->expectExceptionMessage('Schema definition for entry "id" not found'); + + (new KeyValues([ref('id')]))->of(array_to_rows([['name' => 'flow']], schema(str_schema('name')))); } - public function test_of_row_preserves_null(): void + public function test_duplicated_refs_are_extracted_per_position(): void { static::assertSame( - [null], - (new KeyValues([ref('id')]))->ofRow(array_to_row([ - 'id' => null, - ], schema(str_schema('id', nullable: true))), schema(int_schema('id', nullable: true))), + [[1, 1]], + (new KeyValues([ref('id'), ref('id')]))->of(array_to_rows([['id' => 1]], schema(int_schema('id')))), ); } - public function test_of_row_projects_refs_in_order(): void + public function test_no_refs_is_an_empty_key_per_row(): void { static::assertSame( - [1, 'PL'], - (new KeyValues([ref('id'), ref('country')]))->ofRow( - array_to_row(['id' => 1, 'country' => 'PL'], schema(int_schema('id'), str_schema('country'))), - schema(int_schema('id'), str_schema('country')), - ), + [[], []], + (new KeyValues([]))->of(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))), ); } - public function test_duplicated_refs_are_extracted_per_position(): void + public function test_of_an_empty_batch_is_empty(): void + { + static::assertSame([], (new KeyValues([ref('id')]))->of(rows(schema(str_schema('name'))))); + } + + public function test_of_preserves_null(): void { static::assertSame( - [1, 1], - (new KeyValues([ref('id'), ref('id')]))->ofRow(array_to_row([ - 'id' => 1, - ], schema(int_schema('id'))), schema(int_schema('id'))), + [[null], ['a']], + (new KeyValues([ref('id')]))->of(array_to_rows([ + ['id' => null], + ['id' => 'a'], + ], schema(str_schema('id', nullable: true)))), ); } - public function test_a_missing_not_null_ref_throws(): void + public function test_of_projects_each_row(): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Column "id" does not exist'); - - (new KeyValues([ref('id')]))->ofRow( - array_to_row(['name' => 'flow'], schema(str_schema('name'))), - schema(int_schema('id'), str_schema('name')), + static::assertSame( + [[1], [2]], + (new KeyValues([ref('id')]))->of(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))), ); } - public function test_a_missing_nullable_ref_is_null_when_the_schema_allows_it(): void + public function test_of_projects_refs_in_order(): void { static::assertSame( - [null, 'flow'], - (new KeyValues([ref('id'), ref('name')]))->ofRow( - array_to_row(['name' => 'flow'], schema(str_schema('name'))), - schema(int_schema('id', nullable: true), str_schema('name')), - ), + [[1, 'PL'], [2, 'DE']], + (new KeyValues([ref('id'), ref('country')]))->of(array_to_rows( + [['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'DE']], + schema(int_schema('id'), str_schema('country')), + )), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/NativeHasherTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/NativeHasherTest.php index b8e47bbe4f..8831f572c3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/NativeHasherTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/NativeHasherTest.php @@ -80,4 +80,11 @@ public function test_normalize_distinguishes_null_from_string(): void { static::assertNotSame(NativeHasher::normalize(null), NativeHasher::normalize('null')); } + + public function test_values_do_not_run_into_the_next_one(): void + { + [$first, $second] = (new NativeHasher())->hash([['ab', 'c'], ['a', 'bc']]); + + static::assertNotSame($first, $second); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/SortedRunBucketingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/SortedRunBucketingTest.php deleted file mode 100644 index 8b870d4e00..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/SortedRunBucketingTest.php +++ /dev/null @@ -1,144 +0,0 @@ - 1], ['id' => 2]], schema(int_schema('id'))); - yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); - })(); - - $ids = []; - - foreach ($strategy->bucketize($generator, new MemoryBuckets()) as $bucket) { - static::assertMatchesRegularExpression('/^sort-[0-9a-f]{16}-\d+$/', $bucket->id); - $ids[] = $bucket->id; - } - - static::assertCount(2, $ids); - static::assertSame($ids, array_unique($ids)); - } - - public function test_emits_final_partial_run(): void - { - $strategy = new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()); - - $generator = (static function () { - yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); - })(); - - $sizes = []; - - foreach ($strategy->bucketize($generator, new MemoryBuckets()) as $bucket) { - $sizes[] = $bucket->totalRows; - } - - static::assertSame([2, 1], $sizes); - } - - public function test_runs_are_spilled_sorted_by_refs(): void - { - $strategy = new SortedRunBucketing([ref('id')], 3, new NativePHPRandomValueGenerator()); - $storage = new MemoryBuckets(); - - $generator = (static function () { - yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); - })(); - - $buckets = iterator_to_array($strategy->bucketize($generator, $storage)); - - static::assertCount(1, $buckets); - static::assertSame( - [1, 2, 3], - array_map(static fn(Row $r): mixed => $r->get( - 'id', - ), BucketsStorageContext::rows($storage->get($buckets[0]->id))), - ); - } - - public function test_runs_are_yielded_as_soon_as_they_are_complete(): void - { - $strategy = new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()); - $storage = new MemoryBuckets(); - - $generator = (static function () { - yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); - })(); - - $firstRun = $strategy->bucketize($generator, $storage)->current(); - - static::assertNotNull($firstRun); - static::assertSame(2, $firstRun->totalRows); - static::assertCount(2, BucketsStorageContext::rows($storage->get($firstRun->id))); - } - - public function test_splits_buffer_into_runs_of_run_size(): void - { - $strategy = new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()); - - $generator = (static function () { - yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); - })(); - - $sizes = []; - - foreach ($strategy->bucketize($generator, new MemoryBuckets()) as $bucket) { - $sizes[] = $bucket->totalRows; - } - - static::assertSame([2, 2], $sizes); - } - - public function test_runs_are_numbered_sequentially(): void - { - $strategy = new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()); - - $generator = (static function () { - yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - yield array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))); - yield array_to_rows([['id' => 5]], schema(int_schema('id'))); - })(); - - $indexes = []; - - foreach ($strategy->bucketize($generator, new MemoryBuckets()) as $bucket) { - $indexes[] = $bucket->index; - } - - static::assertSame([0, 1, 2], $indexes); - } - - public function test_throws_when_run_size_below_one(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Run size must be greater than 0, given: 0'); - - // @mago-ignore analysis:invalid-argument - new SortedRunBucketing([ref('id')], 0, new NativePHPRandomValueGenerator()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/MemoryBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/MemoryBucketsTest.php index 0abd2cbeb5..cfa808aca5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/MemoryBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/MemoryBucketsTest.php @@ -6,11 +6,9 @@ use Flow\ETL\Bucketing\ResidentBucketsStorage; use Flow\ETL\Bucketing\Storage\MemoryBuckets; -use Flow\ETL\Row; use Flow\ETL\Tests\Context\BucketsStorageContext; use Flow\ETL\Tests\FlowTestCase; -use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -23,10 +21,7 @@ public function test_append_accumulates_rows_in_order(): void $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); - static::assertSame( - [1, 2, 3], - array_map(static fn(Row $r): mixed => $r->get('id'), BucketsStorageContext::rows($storage->get('bucket'))), - ); + static::assertSame([1, 2, 3], array_column(BucketsStorageContext::rows($storage->get('bucket')), 'id')); } public function test_get_unknown_bucket_yields_nothing(): void @@ -54,9 +49,6 @@ public function test_set_replaces_previous_rows(): void $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $storage->set('bucket', array_to_rows([['id' => 42]], schema(int_schema('id')))); - static::assertSame( - [42], - array_map(static fn(Row $r): mixed => $r->get('id'), BucketsStorageContext::rows($storage->get('bucket'))), - ); + static::assertSame([42], array_column(BucketsStorageContext::rows($storage->get('bucket')), 'id')); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php index 6c303f72c4..e4fa99922f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php @@ -5,17 +5,14 @@ namespace Flow\ETL\Tests\Unit\Bucketing\Storage; use Flow\ETL\Bucketing\Storage\PSRCacheBuckets; -use Flow\ETL\Row; use Flow\ETL\Tests\Context\BucketsStorageContext; use Flow\ETL\Tests\Double\ArrayCache; use Flow\ETL\Tests\FlowTestCase; -use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; -use function iterator_to_array; final class PSRCacheBucketsTest extends FlowTestCase { @@ -25,10 +22,7 @@ public function test_append_then_get_returns_rows_in_order_across_chunks(): void $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); - static::assertSame( - [1, 2, 3], - array_map(static fn(Row $r): mixed => $r->get('id'), BucketsStorageContext::rows($storage->get('bucket'))), - ); + static::assertSame([1, 2, 3], array_column(BucketsStorageContext::rows($storage->get('bucket')), 'id')); } public function test_custom_prefix_is_used_in_keys(): void @@ -88,10 +82,7 @@ public function test_round_trips_schema_changing_rows(): void ); $storage->append('bucket', $input); - static::assertSame( - array_map(static fn(Row $r): array => $r->toArray(), iterator_to_array($input, false)), - array_map(static fn(Row $r): array => $r->toArray(), BucketsStorageContext::rows($storage->get('bucket'))), - ); + static::assertSame($input->toArray(), BucketsStorageContext::rows($storage->get('bucket'))); } public function test_set_replaces_previous_content(): void @@ -100,9 +91,6 @@ public function test_set_replaces_previous_content(): void $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->set('bucket', array_to_rows([['id' => 42]], schema(int_schema('id')))); - static::assertSame( - [42], - array_map(static fn(Row $r): mixed => $r->get('id'), BucketsStorageContext::rows($storage->get('bucket'))), - ); + static::assertSame([42], array_column(BucketsStorageContext::rows($storage->get('bucket')), 'id')); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/SpillingBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/SpillingBucketsTest.php new file mode 100644 index 0000000000..e0a1a3a50d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/SpillingBucketsTest.php @@ -0,0 +1,111 @@ +append('a', $batch); + } + + static::assertSame([], $disk->appendedRows()); + static::assertSame([1, 2, 3, 4], IdRows::ids($buckets->get('a'))); + } + + public function test_past_the_limit_every_frame_holds_a_full_batch_and_the_rest_is_read_after_them(): void + { + $disk = new SpyBucketsStorage(new MemoryBuckets()); + $buckets = new SpillingBuckets($disk, Unit::fromBytes(1), new PhpBackend(), 2); + + foreach (IdRows::batches([1], [2], [3], [4], [5]) as $batch) { + $buckets->append('a', $batch); + } + + static::assertSame( + ['a' => [2, 2]], + array_map(static fn(array $frames): array => array_map( + static fn(Rows $rows): int => $rows->count(), + $frames, + ), $disk->appendedRows()), + ); + static::assertSame([1, 2, 3, 4, 5], IdRows::ids($buckets->get('a'))); + } + + public function test_crossing_the_limit_moves_every_bucket_that_holds_a_full_batch(): void + { + $disk = new SpyBucketsStorage(new MemoryBuckets()); + $buckets = new SpillingBuckets($disk, Unit::fromBytes(1), new PhpBackend(), 2); + + $buckets->append('a', IdRows::batches([1, 2, 3])->current()); + + static::assertSame([1, 2], IdRows::ids($disk->get('a'))); + static::assertSame([1, 2, 3], IdRows::ids($buckets->get('a'))); + } + + public function test_remove_drops_the_buffer_and_the_frames(): void + { + $disk = new SpyBucketsStorage(new MemoryBuckets()); + $buckets = new SpillingBuckets($disk, Unit::fromBytes(1), new PhpBackend(), 1); + $buckets->append('a', IdRows::batches([1, 2])->current()); + + $buckets->remove('a'); + + static::assertSame([], IdRows::ids($buckets->get('a'))); + static::assertSame([], $disk->liveBucketIds()); + } + + public function test_set_replaces_what_the_bucket_held(): void + { + $buckets = new SpillingBuckets(new MemoryBuckets(), Unit::fromGb(64), new PhpBackend(), 2); + $buckets->append('a', IdRows::batches([1])->current()); + + $buckets->set('a', IdRows::batches([7, 8])->current()); + + static::assertSame([7, 8], IdRows::ids($buckets->get('a'))); + } + + public function test_an_unknown_bucket_reads_nothing(): void + { + static::assertSame( + [], + IdRows::ids((new SpillingBuckets(new MemoryBuckets(), Unit::fromGb(64), new PhpBackend()))->get('missing')), + ); + } + + public function test_around_keeps_a_resident_storage_and_wraps_any_other(): void + { + $resident = new MemoryBuckets(); + $disk = new SpyBucketsStorage(new MemoryBuckets()); + + static::assertSame($resident, SpillingBuckets::around( + new BucketingConfig($resident, 64, 1000), + Unit::fromMb(1), + new PhpBackend(), + )); + + $wrapped = SpillingBuckets::around(new BucketingConfig($disk, 64, 500), Unit::fromMb(3), new PhpBackend()); + + static::assertInstanceOf(SpillingBuckets::class, $wrapped); + static::assertSame($disk, $wrapped->disk); + static::assertSame(Unit::fromMb(3)->inBytes(), $wrapped->memoryLimit->inBytes()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php new file mode 100644 index 0000000000..68eb1c70a9 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php @@ -0,0 +1,131 @@ +, list}> + */ + public static function ordered(): Generator + { + yield 'integer' => [int_schema('a', nullable: true), [2, null, 1]]; + yield 'float' => [float_schema('a'), [1.5, 0.5]]; + yield 'boolean' => [bool_schema('a'), [true, false]]; + yield 'string' => [str_schema('a'), ['b', 'a']]; + yield 'datetime' => [ + datetime_schema('a'), + [new DateTimeImmutable('2024-01-02'), new DateTimeImmutable('2024-01-01')], + ]; + yield 'date' => [date_schema('a'), [new DateTimeImmutable('2024-01-02'), new DateTimeImmutable('2024-01-01')]]; + yield 'time' => [time_schema('a'), ['PT2H', 'PT1H']]; + } + + /** + * @return Generator, list}> + */ + public static function equal_by_physical(): Generator + { + yield 'uuid' => [uuid_schema('a'), ['00000000-0000-4000-8000-000000000001']]; + yield 'json' => [json_schema('a'), ['{"a":1}']]; + yield 'enum' => [enum_schema('a', BackedStringEnum::class), [BackedStringEnum::one]]; + yield 'xml' => [xml_schema('a'), ['1']]; + yield 'xml element' => [xml_element_schema('a'), ['1']]; + } + + /** + * @return Generator, list}> + */ + public static function by_value(): Generator + { + yield 'timezone' => [time_zone_schema('a'), ['UTC']]; + yield 'list' => [list_schema('a', type_list(type_integer())), [[1, 2]]]; + } + + #[RequiresPhp('>= 8.4.0')] + public function test_html_compares_by_physical(): void + { + $document = ColumnMother::of( + html_schema('a'), + ['

      a

      '], + ); + $element = ColumnMother::of(html_element_schema('a'), ['

      a

      ']); + + static::assertSame($document->physicals(), (new ComparableValues())->equality($document)); + static::assertSame($element->physicals(), (new ComparableValues())->equality($element)); + } + + /** + * @param Definition $definition + * @param list $values + */ + #[DataProvider('by_value')] + public function test_other_types_compare_their_values(Definition $definition, array $values): void + { + $column = ColumnMother::of($definition, $values); + + static::assertFalse((new ComparableValues())->orderedByPhysical($column->type())); + static::assertEquals($column->values(), (new ComparableValues())->ordering($column)); + static::assertEquals($column->values(), (new ComparableValues())->equality($column)); + } + + /** + * @param Definition $definition + * @param list $values + */ + #[DataProvider('equal_by_physical')] + public function test_equality_only_types_order_by_value(Definition $definition, array $values): void + { + $column = ColumnMother::of($definition, $values); + + static::assertFalse((new ComparableValues())->orderedByPhysical($column->type())); + static::assertEquals($column->values(), (new ComparableValues())->ordering($column)); + static::assertSame($column->physicals(), (new ComparableValues())->equality($column)); + } + + /** + * @param Definition $definition + * @param list $values + */ + #[DataProvider('ordered')] + public function test_ordered_types_read_physicals(Definition $definition, array $values): void + { + $column = ColumnMother::of($definition, $values); + + static::assertTrue((new ComparableValues())->orderedByPhysical($column->type())); + static::assertTrue((new ComparableValues())->equalByPhysical($column->type())); + static::assertSame($column->physicals(), (new ComparableValues())->ordering($column)); + static::assertSame($column->physicals(), (new ComparableValues())->equality($column)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php index d05c388663..0b767cd3bf 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php @@ -5,7 +5,9 @@ namespace Flow\ETL\Tests\Unit\Column; use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Tests\Double\ForeignColumnStub; use Flow\ETL\Tests\Mother\ColumnMother; use PHPUnit\Framework\TestCase; @@ -35,6 +37,14 @@ public function test_adopt_is_what_the_php_backend_adopts(): void ); } + public function test_adopt_refuses_an_untyped_column(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage('column "a": mixed cannot be a batch column'); + + (new DefaultBackend())->adopt(int_schema('a'), new ValueColumn([1])); + } + public function test_allocated_bytes_is_what_the_php_backend_allocates(): void { static::assertSame((new PhpBackend())->allocatedBytes(), (new DefaultBackend())->allocatedBytes()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnTest.php index 16a931a028..2a80ce5027 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnTest.php @@ -6,9 +6,11 @@ use DateTimeZone; use Flow\ETL\Column\Php\ListColumn; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\Mother\ColumnMother; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\definition_from_type; use function Flow\ETL\DSL\list_schema; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_time_zone; @@ -42,6 +44,23 @@ public function test_reads_physical_and_logical_cells(): void static::assertEquals(type_list(type_time_zone()), $column->type()); } + public function test_reads_cells_over_a_constant_element(): void + { + $column = new ListColumn( + type_list(type_time_zone()), + [0, 2, 2, 3], + (new PhpBackend())->constant(definition_from_type('element', type_time_zone()), 'UTC', 3), + [1 => true], + ); + + static::assertSame(['UTC', 'UTC'], $column->at(0)); + static::assertNull($column->at(1)); + static::assertSame(['UTC'], $column->at(2)); + static::assertEquals([new DateTimeZone('UTC'), new DateTimeZone('UTC')], $column->value(0)); + static::assertNull($column->value(1)); + static::assertEquals([new DateTimeZone('UTC')], $column->value(2)); + } + public function test_slice_and_take_rebuild_offsets_from_zero(): void { $column = ColumnMother::of(list_schema('a', type_list(type_time_zone()), nullable: true), [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnTest.php index 620fe52a65..65e0b224f8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnTest.php @@ -6,9 +6,11 @@ use DateTimeZone; use Flow\ETL\Column\Php\MapColumn; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\Mother\ColumnMother; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\definition_from_type; use function Flow\ETL\DSL\map_schema; use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_string; @@ -50,6 +52,27 @@ public function test_reads_physical_and_logical_cells(): void static::assertEquals(type_map(type_string(), type_time_zone()), $column->type()); } + public function test_reads_cells_over_constant_keys_and_values(): void + { + $backend = new PhpBackend(); + $keys = $backend->builder(definition_from_type('key', type_string())); + $keys->appendMany(['x', 'y']); + $column = new MapColumn( + type_map(type_string(), type_time_zone()), + [0, 1, 1, 2], + $keys->finish(), + $backend->constant(definition_from_type('value', type_time_zone()), 'UTC', 2), + [1 => true], + ); + + static::assertSame(['x' => 'UTC'], $column->at(0)); + static::assertNull($column->at(1)); + static::assertSame(['y' => 'UTC'], $column->at(2)); + static::assertEquals(['x' => new DateTimeZone('UTC')], $column->value(0)); + static::assertNull($column->value(1)); + static::assertEquals(['y' => new DateTimeZone('UTC')], $column->value(2)); + } + public function test_slice_and_take_rebuild_offsets_from_zero(): void { $column = ColumnMother::of(map_schema('a', type_map(type_string(), type_string()), nullable: true), [ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php index 39d640571d..b9b38c5687 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Column\Php; +use ArrayObject; use BackedEnum; use Flow\ETL\Column\Php\DatePhysical; use Flow\ETL\Column\Php\DateTimePhysical; @@ -23,6 +24,7 @@ use Flow\ETL\Column\Php\XmlDocumentPhysical; use Flow\ETL\Column\Php\XmlElementPhysical; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; use Flow\Types\Type; use Generator; @@ -31,10 +33,14 @@ use stdClass; use UnitEnum; +use function Flow\ETL\DSL\definition_from_type; +use function Flow\Types\DSL\type_array; use function Flow\Types\DSL\type_boolean; +use function Flow\Types\DSL\type_callable; use function Flow\Types\DSL\type_class_string; use function Flow\Types\DSL\type_date; use function Flow\Types\DSL\type_datetime; +use function Flow\Types\DSL\type_empty_array; use function Flow\Types\DSL\type_enum; use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_html; @@ -48,15 +54,19 @@ use function Flow\Types\DSL\type_non_empty_string; use function Flow\Types\DSL\type_null; use function Flow\Types\DSL\type_numeric_string; +use function Flow\Types\DSL\type_object; use function Flow\Types\DSL\type_optional; use function Flow\Types\DSL\type_positive_integer; +use function Flow\Types\DSL\type_scalar; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; use function Flow\Types\DSL\type_time; use function Flow\Types\DSL\type_time_zone; +use function Flow\Types\DSL\type_union; use function Flow\Types\DSL\type_uuid; use function Flow\Types\DSL\type_xml; use function Flow\Types\DSL\type_xml_element; +use function in_array; final class PhysicalForTest extends TestCase { @@ -104,6 +114,63 @@ public static function refusals(): Generator yield 'structure element' => [type_structure(['a' => type_mixed()]), 'a mixed element has no column kind']; } + /** + * @return Generator, bool}> + */ + public static function supported(): Generator + { + foreach (self::types() as $name => [$type]) { + yield $name => [ + $type, + !in_array($name, ['positive integer', 'non-empty string', 'numeric string', 'class string'], true), + ]; + } + + yield 'nullable union' => [type_union(type_string(), type_null()), true]; + yield 'array' => [type_array(), true]; + yield 'optional array' => [type_optional(type_array()), true]; + yield 'list of non-empty strings' => [type_list(type_non_empty_string()), true]; + yield 'list of optional integers' => [type_list(type_optional(type_integer())), true]; + yield 'structure of lists' => [ + type_structure(['a' => type_list(type_uuid()), 'b' => type_map(type_string(), type_date())]), + true, + ]; + yield 'mixed' => [type_mixed(), false]; + yield 'union' => [type_union(type_string(), type_integer()), false]; + yield 'object' => [type_object(), false]; + yield 'instance of' => [type_instance_of(ArrayObject::class), false]; + yield 'empty array' => [type_empty_array(), false]; + yield 'callable' => [type_callable(), false]; + yield 'scalar' => [type_scalar(), false]; + yield 'unit enum wildcard' => [type_enum(UnitEnum::class), false]; + yield 'backed enum wildcard' => [type_enum(BackedEnum::class), false]; + yield 'list of mixed' => [type_list(type_mixed()), false]; + yield 'list of arrays' => [type_list(type_array()), true]; + yield 'list of empty arrays' => [type_list(type_empty_array()), true]; + yield 'list of nullable unions' => [type_list(type_union(type_string(), type_null())), true]; + yield 'list of unions' => [type_list(type_union(type_string(), type_integer())), false]; + yield 'map of mixed' => [type_map(type_string(), type_mixed()), false]; + yield 'structure element' => [type_structure(['a' => type_integer(), 'b' => type_mixed()]), false]; + yield 'list of unit enums' => [type_list(type_enum(UnitEnum::class)), false]; + } + + /** + * @param Type $type + */ + #[DataProvider('supported')] + public function test_supports_agrees_with_definition_from_type_and_definition(Type $type, bool $supported): void + { + try { + (new PhysicalFor())->definition(definition_from_type('value', $type)); + $defined = true; + } catch (InvalidArgumentException|RuntimeException) { + $defined = false; + } + + static::assertSame($supported, (new PhysicalFor())->supports($type)); + static::assertSame($supported, $defined); + } + /** * @param Type $type * @param class-string $class diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValueColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValueColumnTest.php new file mode 100644 index 0000000000..60a1fc3bb8 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValueColumnTest.php @@ -0,0 +1,72 @@ +expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'An untyped function result (mixed) cannot be concatenated; it exists only inside function evaluation', + ); + + (new ValueColumn([1]))->concat(new ValueColumn([2])); + } + + public function test_encode_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'An untyped function result (mixed) cannot be encoded; it exists only inside function evaluation', + ); + + (new ValueColumn([1]))->encode(); + } + + public function test_reads_values_as_given(): void + { + $object = new ArrayObject([1]); + $column = new ValueColumn([['a' => 1], null, $object, 'x']); + + static::assertEquals(type_mixed(), $column->type()); + static::assertSame(4, $column->count()); + static::assertSame(1, $column->nullCount()); + static::assertTrue($column->isNull(1)); + static::assertFalse($column->isNull(0)); + static::assertSame(['a' => 1], $column->at(0)); + static::assertSame($object, $column->value(2)); + static::assertSame([['a' => 1], null, $object, 'x'], $column->physicals()); + static::assertSame([['a' => 1], null, $object, 'x'], $column->values()); + } + + public function test_slice_and_take(): void + { + $column = new ValueColumn(['a', null, 'c', 'd']); + + static::assertSame([null, 'c'], $column->slice(1, 2)->values()); + static::assertSame(['d', 'a', 'd'], $column->take([3, 0, 3])->values()); + static::assertSame(0, $column->take([])->count()); + } + + public function test_with_type_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'An untyped function result (mixed) cannot be retyped to integer; it exists only inside function evaluation', + ); + + (new ValueColumn([1]))->withType(type_integer()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php index 9089e131b1..b4b9ef3ae8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php @@ -11,6 +11,7 @@ use Dom\HTMLElement; use Flow\ETL\Column\Php\HtmlDocumentPhysical; use Flow\ETL\Column\Php\HtmlElementPhysical; +use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; @@ -605,6 +606,16 @@ public function test_adopt_refuses_a_null_under_not_null(): void (new PhpBackend())->adopt(int_schema('a'), $foreign); } + public function test_adopt_refuses_an_untyped_column(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage( + 'column "a": mixed cannot be a batch column, an untyped function result exists only inside function evaluation', + ); + + (new PhpBackend())->adopt(int_schema('a'), new ValueColumn([1, 2])); + } + public function test_allocated_bytes_is_zero(): void { static::assertSame(0, (new PhpBackend())->allocatedBytes()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php deleted file mode 100644 index 5684d1e7a9..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowComparatorTest.php +++ /dev/null @@ -1,90 +0,0 @@ - 1], schema(int_schema('id'))); - - static::assertTrue($comparator->accepts($row, $row)); - static::assertFalse($comparator->accepts($row, rows(schema(int_schema('id')), $row))); - static::assertFalse($comparator->accepts($row, ['id' => 1])); - } - - public function test_rows_of_different_batches_with_equal_values_pass(): void - { - $comparator = new RowComparator(); - $comparator->setFactory(Factory::getInstance()); - - $comparator->assertEquals( - array_to_rows([['id' => 1]], schema(int_schema('id')))->first(), - array_to_rows([['id' => 0], ['id' => 1]], schema(int_schema('id')))->last(), - ); - - $this->addToAssertionCount(1); - } - - public function test_the_schema_is_not_compared(): void - { - $comparator = new RowComparator(); - $comparator->setFactory(Factory::getInstance()); - - $comparator->assertEquals(array_to_row([ - 'phase' => null, - ], schema(str_schema('phase', nullable: true))), array_to_rows([['phase' => null]], schema(int_schema('phase', nullable: true)))->first()); - - $this->addToAssertionCount(1); - } - - public function test_a_name_order_difference_fails(): void - { - $comparator = new RowComparator(); - $comparator->setFactory(Factory::getInstance()); - - $this->expectException(ComparisonFailure::class); - $this->expectExceptionMessage('Failed asserting that two Row objects have the same names.'); - - $comparator->assertEquals( - array_to_row(['a' => 1, 'b' => 2], schema(int_schema('a'), int_schema('b'))), - array_to_row(['b' => 2, 'a' => 1], schema(int_schema('b'), int_schema('a'))), - ); - } - - public function test_a_value_difference_fails(): void - { - $comparator = new RowComparator(); - $comparator->setFactory(Factory::getInstance()); - - try { - $comparator->assertEquals( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - ); - } catch (ComparisonFailure $failure) { - static::assertSame('Failed asserting that two Row objects are equal.', $failure->getMessage()); - static::assertStringContainsString('1', $failure->getExpectedAsString()); - static::assertStringContainsString('2', $failure->getActualAsString()); - - return; - } - - static::fail('two Row objects with different values compared equal'); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php index b3aad4f832..e09e47b58d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/RowsComparatorTest.php @@ -11,7 +11,6 @@ use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Comparator\Factory; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -25,7 +24,7 @@ public function test_accepts_only_two_rows(): void $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); static::assertTrue($comparator->accepts($rows, $rows)); - static::assertFalse($comparator->accepts($rows, array_to_row(['id' => 1], schema(int_schema('id'))))); + static::assertFalse($comparator->accepts($rows, ['id' => 1])); static::assertFalse($comparator->accepts([], $rows)); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Join/HashJoinBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Join/HashJoinBuilderTest.php index 024c865e0d..c18935818e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Join/HashJoinBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Join/HashJoinBuilderTest.php @@ -7,6 +7,9 @@ use Flow\ETL\Bucketing\Storage\FilesystemBuckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Config\MemoryLimit; +use Flow\ETL\Dataset\Memory\Unit; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Path; @@ -29,6 +32,26 @@ public function test_default_builds_a_filesystem_buckets_storage(): void static::assertInstanceOf(FilesystemBuckets::class, $config->bucketing->storage); static::assertSame(64, $config->bucketing->bucketsCount); static::assertSame(1000, $config->bucketing->batchSize); + static::assertSame(MemoryLimit::default()->inBytes(), $config->memoryLimit->inBytes()); + } + + public function test_memory_limit_below_one_byte_is_rejected(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Join memory limit must be greater than 0 bytes'); + + hash_join()->memoryLimit(Unit::fromBytes(0)); + } + + public function test_memory_limit_is_set(): void + { + static::assertSame( + Unit::fromMb(128)->inBytes(), + hash_join() + ->memoryLimit(Unit::fromMb(128)) + ->build(Path::realpath(__DIR__), new PhpBackend()) + ->memoryLimit->inBytes(), + ); } public function test_injected_storage_wins_over_the_default(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/ExternalSortBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/ExternalSortBuilderTest.php index ccfc3a8cae..c550309da9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/ExternalSortBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Config/Sort/ExternalSortBuilderTest.php @@ -7,6 +7,8 @@ use Flow\ETL\Bucketing\Storage\FilesystemBuckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Config\MemoryLimit; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Path; @@ -30,7 +32,7 @@ public function test_default_builds_a_filesystem_buckets_storage(): void static::assertInstanceOf(FilesystemBuckets::class, $config->bucketing->storage); static::assertSame(100, $config->bucketing->bucketsCount); static::assertSame(1000, $config->bucketing->batchSize); - static::assertSame(10_000, $config->runSize); + static::assertSame(MemoryLimit::default()->inBytes(), $config->memoryLimit->inBytes()); } public function test_merge_storage_defaults_to_null_so_the_spill_storage_is_reused(): void @@ -60,20 +62,22 @@ public function test_injected_storage_wins_over_the_default(): void ); } - public function test_run_size_below_one_is_rejected(): void + public function test_memory_limit_below_one_byte_is_rejected(): void { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Run size must be greater than 0'); + $this->expectExceptionMessage('Sort memory limit must be greater than 0 bytes'); - // @mago-ignore analysis:invalid-argument - external_sort()->runSize(0); + external_sort()->memoryLimit(Unit::fromBytes(0)); } - public function test_run_size_is_set(): void + public function test_memory_limit_is_set(): void { static::assertSame( - 500, - external_sort()->runSize(500)->build(Path::realpath(__DIR__), new PhpBackend())->runSize, + Unit::fromMb(500)->inBytes(), + external_sort() + ->memoryLimit(Unit::fromMb(500)) + ->build(Path::realpath(__DIR__), new PhpBackend()) + ->memoryLimit->inBytes(), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/SortedConstraintTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/SortedConstraintTest.php index a9fe5a2a70..78a1677b9f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/SortedConstraintTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/SortedConstraintTest.php @@ -6,10 +6,10 @@ use DateTimeImmutable; use Flow\ETL\Constraint\SortedByConstraint; +use Flow\ETL\Row\NullsOrder; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; -use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; @@ -17,6 +17,8 @@ use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use const NAN; + final class SortedConstraintTest extends FlowTestCase { public function test_sorted_constraint_as_a_string(): void @@ -30,122 +32,140 @@ public function test_sorted_constraint_ascending_integers(): void { $constraint = new SortedByConstraint(ref('id')->asc()); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 1, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(int_schema('id'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 2, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(int_schema('id'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 3, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(int_schema('id'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 3, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertFalse($constraint->isSatisfiedBy(array_to_row([ - 'id' => 2, - ], schema(int_schema('id'))), schema(int_schema('id')))); + ]], schema(int_schema('id'))))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows([[ + 'id' => 2, + ]], schema(int_schema('id')))), + ); } public function test_sorted_constraint_ascending_strings(): void { $constraint = new SortedByConstraint(ref('name')->asc()); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + static::assertNull($constraint->firstViolation(array_to_rows([[ 'name' => 'Alice', - ], schema(str_schema('name'))), schema(str_schema('name')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(str_schema('name'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'name' => 'Bob', - ], schema(str_schema('name'))), schema(str_schema('name')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(str_schema('name'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'name' => 'Charlie', - ], schema(str_schema('name'))), schema(str_schema('name')))); - static::assertFalse($constraint->isSatisfiedBy(array_to_row([ - 'name' => 'Alice', - ], schema(str_schema('name'))), schema(str_schema('name')))); + ]], schema(str_schema('name'))))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows([[ + 'name' => 'Alice', + ]], schema(str_schema('name')))), + ); } public function test_sorted_constraint_default_order_is_ascending(): void { $constraint = new SortedByConstraint(ref('id')); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 1, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(int_schema('id'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 2, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(int_schema('id'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 3, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertFalse($constraint->isSatisfiedBy(array_to_row([ - 'id' => 1, - ], schema(int_schema('id'))), schema(int_schema('id')))); + ]], schema(int_schema('id'))))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id')))), + ); } public function test_sorted_constraint_descending_floats(): void { $constraint = new SortedByConstraint(ref('price')->desc()); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + static::assertNull($constraint->firstViolation(array_to_rows([[ 'price' => 99.99, - ], schema(float_schema('price'))), schema(float_schema('price')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(float_schema('price'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'price' => 49.99, - ], schema(float_schema('price'))), schema(float_schema('price')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(float_schema('price'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'price' => 19.99, - ], schema(float_schema('price'))), schema(float_schema('price')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(float_schema('price'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'price' => 19.99, - ], schema(float_schema('price'))), schema(float_schema('price')))); - static::assertFalse($constraint->isSatisfiedBy(array_to_row([ - 'price' => 29.99, - ], schema(float_schema('price'))), schema(float_schema('price')))); + ]], schema(float_schema('price'))))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows([[ + 'price' => 29.99, + ]], schema(float_schema('price')))), + ); } public function test_sorted_constraint_descending_integers(): void { $constraint = new SortedByConstraint(ref('id')->desc()); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 10, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(int_schema('id'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 5, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(int_schema('id'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 1, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertFalse($constraint->isSatisfiedBy(array_to_row([ - 'id' => 3, - ], schema(int_schema('id'))), schema(int_schema('id')))); + ]], schema(int_schema('id'))))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows([[ + 'id' => 3, + ]], schema(int_schema('id')))), + ); } public function test_sorted_constraint_multiple_columns(): void { $constraint = new SortedByConstraint(ref('category')->asc(), ref('price')->desc()); - static::assertTrue($constraint->isSatisfiedBy( - array_to_row(['category' => 'A', 'price' => 100.0], schema(str_schema('category'), float_schema('price'))), + static::assertNull($constraint->firstViolation(array_to_rows( + [['category' => 'A', 'price' => 100.0]], schema(str_schema('category'), float_schema('price')), - )); - static::assertTrue($constraint->isSatisfiedBy( - array_to_row(['category' => 'A', 'price' => 50.0], schema(str_schema('category'), float_schema('price'))), + ))); + static::assertNull($constraint->firstViolation(array_to_rows( + [['category' => 'A', 'price' => 50.0]], schema(str_schema('category'), float_schema('price')), - )); - static::assertTrue($constraint->isSatisfiedBy( - array_to_row(['category' => 'B', 'price' => 200.0], schema(str_schema('category'), float_schema('price'))), + ))); + static::assertNull($constraint->firstViolation(array_to_rows( + [['category' => 'B', 'price' => 200.0]], schema(str_schema('category'), float_schema('price')), - )); - static::assertTrue($constraint->isSatisfiedBy( - array_to_row(['category' => 'B', 'price' => 150.0], schema(str_schema('category'), float_schema('price'))), + ))); + static::assertNull($constraint->firstViolation(array_to_rows( + [['category' => 'B', 'price' => 150.0]], schema(str_schema('category'), float_schema('price')), - )); - static::assertFalse($constraint->isSatisfiedBy( - array_to_row(['category' => 'B', 'price' => 250.0], schema(str_schema('category'), float_schema('price'))), - schema(str_schema('category'), float_schema('price')), - )); + ))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows( + [['category' => 'B', 'price' => 250.0]], + schema(str_schema('category'), float_schema('price')), + )), + ); } public function test_sorted_constraint_multiple_columns_as_a_string(): void @@ -158,12 +178,12 @@ public function test_sorted_constraint_multiple_columns_as_a_string(): void public function test_sorted_constraint_violation_ascending(): void { $constraint = new SortedByConstraint(ref('id')->asc()); - $constraint->isSatisfiedBy(array_to_row(['id' => 5], schema(int_schema('id'))), schema(int_schema('id'))); - $constraint->isSatisfiedBy(array_to_row(['id' => 10], schema(int_schema('id'))), schema(int_schema('id'))); + $constraint->firstViolation(array_to_rows([['id' => 5]], schema(int_schema('id')))); + $constraint->firstViolation(array_to_rows([['id' => 10]], schema(int_schema('id')))); - $violation = $constraint->violation(array_to_row([ + $violation = $constraint->violation(array_to_rows([[ 'id' => 3, - ], schema(int_schema('id'))), schema(int_schema('id'))); + ]], schema(int_schema('id'))), 0); static::assertStringContainsString('expected ASC order', $violation); static::assertStringContainsString('id', $violation); @@ -174,12 +194,12 @@ public function test_sorted_constraint_violation_ascending(): void public function test_sorted_constraint_violation_descending(): void { $constraint = new SortedByConstraint(ref('id')->desc()); - $constraint->isSatisfiedBy(array_to_row(['id' => 10], schema(int_schema('id'))), schema(int_schema('id'))); - $constraint->isSatisfiedBy(array_to_row(['id' => 5], schema(int_schema('id'))), schema(int_schema('id'))); + $constraint->firstViolation(array_to_rows([['id' => 10]], schema(int_schema('id')))); + $constraint->firstViolation(array_to_rows([['id' => 5]], schema(int_schema('id')))); - $violation = $constraint->violation(array_to_row([ + $violation = $constraint->violation(array_to_rows([[ 'id' => 8, - ], schema(int_schema('id'))), schema(int_schema('id'))); + ]], schema(int_schema('id'))), 0); static::assertStringContainsString('expected DESC order', $violation); static::assertStringContainsString('id', $violation); @@ -191,26 +211,127 @@ public function test_sorted_constraint_with_dates(): void { $constraint = new SortedByConstraint(ref('date')->asc()); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + static::assertNull($constraint->firstViolation(array_to_rows([[ 'date' => new DateTimeImmutable('2025-01-01'), - ], schema(datetime_schema('date'))), schema(date_schema('date')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(datetime_schema('date'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'date' => new DateTimeImmutable('2025-01-02'), - ], schema(datetime_schema('date'))), schema(date_schema('date')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(datetime_schema('date'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'date' => new DateTimeImmutable('2025-01-03'), - ], schema(datetime_schema('date'))), schema(date_schema('date')))); - static::assertFalse($constraint->isSatisfiedBy(array_to_row([ - 'date' => new DateTimeImmutable('2025-01-01'), - ], schema(datetime_schema('date'))), schema(date_schema('date')))); + ]], schema(datetime_schema('date'))))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows([[ + 'date' => new DateTimeImmutable('2025-01-01'), + ]], schema(datetime_schema('date')))), + ); } public function test_sorted_constraint_with_single_row(): void { $constraint = new SortedByConstraint(ref('id')->asc()); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 42, - ], schema(int_schema('id'))), schema(int_schema('id')))); + ]], schema(int_schema('id'))))); + } + + public function test_first_violation_carries_the_previous_batch_last_row(): void + { + $constraint = new SortedByConstraint(ref('id')->asc()); + + static::assertNull($constraint->firstViolation(array_to_rows([ + ['id' => 1], + ['id' => 5], + ], schema(int_schema('id'))))); + + $batch = array_to_rows([['id' => 4], ['id' => 6]], schema(int_schema('id'))); + + static::assertSame(0, $constraint->firstViolation($batch)); + static::assertStringContainsString('current: 4, previous: 5', $constraint->violation($batch, 0)); + } + + public function test_first_violation_stops_advancing_at_the_violation(): void + { + $constraint = new SortedByConstraint(ref('id')->asc()); + $batch = array_to_rows([['id' => 1], ['id' => 3], ['id' => 2], ['id' => 9]], schema(int_schema('id'))); + + static::assertSame(2, $constraint->firstViolation($batch)); + static::assertStringContainsString('current: 2, previous: 3', $constraint->violation($batch, 2)); + } + + public function test_an_empty_batch_has_no_violation(): void + { + static::assertNull((new SortedByConstraint(ref('id')))->firstViolation(array_to_rows( + [], + schema(int_schema('id')), + ))); + } + + public function test_datetimes_are_compared_by_instant(): void + { + $constraint = new SortedByConstraint(ref('at')->asc()); + + static::assertSame( + 2, + $constraint->firstViolation(array_to_rows([ + ['at' => new DateTimeImmutable('2024-01-01 00:00:00.000001')], + ['at' => new DateTimeImmutable('2024-01-01 00:00:00.000002')], + ['at' => new DateTimeImmutable('2024-01-01 00:00:00.000001')], + ], schema(datetime_schema('at')))), + ); + } + + public function test_strings_are_in_byte_order_never_numeric(): void + { + static::assertSame( + 1, + (new SortedByConstraint(ref('code')->asc()))->firstViolation(array_to_rows([ + ['code' => '9'], + ['code' => '10'], + ], schema(str_schema('code')))), + ); + static::assertNull((new SortedByConstraint(ref('code')->asc()))->firstViolation(array_to_rows([ + ['code' => '10'], + ['code' => '9'], + ], schema(str_schema('code'))))); + } + + public function test_nulls_come_first_ascending_and_nan_last(): void + { + static::assertNull((new SortedByConstraint(ref('v')->asc()))->firstViolation(array_to_rows([ + ['v' => null], + ['v' => -1.5], + ['v' => 2.0], + ['v' => NAN], + ['v' => NAN], + ], schema(float_schema('v', true))))); + static::assertSame( + 1, + (new SortedByConstraint(ref('v')->desc()))->firstViolation(array_to_rows([ + ['v' => null], + ['v' => NAN], + ], schema(float_schema('v', true)))), + ); + } + + public function test_a_moved_null_placement_is_part_of_the_order(): void + { + $constraint = new SortedByConstraint(ref('v')->asc(NullsOrder::LAST)); + + static::assertSame('Sorted constraint on [v ASC NULLS LAST]', $constraint->toString()); + static::assertNull($constraint->firstViolation(array_to_rows([ + ['v' => 1], + ['v' => 2], + ['v' => null], + ], schema(int_schema('v', true))))); + static::assertSame( + 1, + (new SortedByConstraint(ref('v')->asc(NullsOrder::LAST)))->firstViolation(array_to_rows([ + ['v' => null], + ['v' => 1], + ], schema(int_schema('v', true)))), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/UniqueConstraintTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/UniqueConstraintTest.php index f866a371be..9b72c33f81 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/UniqueConstraintTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Constraint/UniqueConstraintTest.php @@ -8,9 +8,8 @@ use Flow\ETL\Constraint\UniqueConstraint; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\date_schema; -use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -27,37 +26,43 @@ public function test_unique_constraint_on_multiple_columns(): void { $constraint = new UniqueConstraint('id', 'sub_id'); - static::assertTrue($constraint->isSatisfiedBy( - array_to_row(['id' => 1, 'sub_id' => 1], schema(int_schema('id'), int_schema('sub_id'))), + static::assertNull($constraint->firstViolation(array_to_rows( + [['id' => 1, 'sub_id' => 1]], schema(int_schema('id'), int_schema('sub_id')), - )); - static::assertTrue($constraint->isSatisfiedBy( - array_to_row(['id' => 1, 'sub_id' => 2], schema(int_schema('id'), int_schema('sub_id'))), + ))); + static::assertNull($constraint->firstViolation(array_to_rows( + [['id' => 1, 'sub_id' => 2]], schema(int_schema('id'), int_schema('sub_id')), - )); - static::assertTrue($constraint->isSatisfiedBy( - array_to_row(['id' => 2, 'sub_id' => 1], schema(int_schema('id'), int_schema('sub_id'))), + ))); + static::assertNull($constraint->firstViolation(array_to_rows( + [['id' => 2, 'sub_id' => 1]], schema(int_schema('id'), int_schema('sub_id')), - )); - static::assertFalse($constraint->isSatisfiedBy( - array_to_row(['id' => 1, 'sub_id' => 1], schema(int_schema('id'), int_schema('sub_id'))), - schema(int_schema('id'), int_schema('sub_id')), - )); + ))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows( + [['id' => 1, 'sub_id' => 1]], + schema(int_schema('id'), int_schema('sub_id')), + )), + ); } public function test_unique_constraint_on_single_column(): void { $constraint = new UniqueConstraint('id'); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 1, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertTrue($constraint->isSatisfiedBy(array_to_row([ + ]], schema(int_schema('id'))))); + static::assertNull($constraint->firstViolation(array_to_rows([[ 'id' => 2, - ], schema(int_schema('id'))), schema(int_schema('id')))); - static::assertFalse($constraint->isSatisfiedBy(array_to_row([ - 'id' => 1, - ], schema(int_schema('id'))), schema(int_schema('id')))); + ]], schema(int_schema('id'))))); + static::assertSame( + 0, + $constraint->firstViolation(array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id')))), + ); } public function test_unique_constraint_violation(): void @@ -65,8 +70,8 @@ public function test_unique_constraint_violation(): void $constraint = new UniqueConstraint('id', 'sub_id'); static::assertSame('Values: [id = 1, sub_id = 1]', $constraint->violation( - array_to_row(['id' => 1, 'sub_id' => 1], schema(int_schema('id'), int_schema('sub_id'))), - schema(int_schema('id'), int_schema('sub_id')), + array_to_rows([['id' => 1, 'sub_id' => 1]], schema(int_schema('id'), int_schema('sub_id'))), + 0, )); } @@ -74,8 +79,43 @@ public function test_unique_constraint_violation_on_dates(): void { $constraint = new UniqueConstraint('date'); - static::assertSame('Values: [date = 2025-01-01]', $constraint->violation(array_to_row([ + static::assertSame('Values: [date = 2025-01-01]', $constraint->violation(array_to_rows([[ 'date' => new DateTimeImmutable('2025-01-01'), - ], schema(datetime_schema('date'))), schema(date_schema('date')))); + ]], schema(date_schema('date'))), 0)); + } + + public function test_first_violation_is_the_first_repeated_key_across_batches(): void + { + $constraint = new UniqueConstraint('id'); + + static::assertNull($constraint->firstViolation(array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id'))))); + static::assertSame( + 1, + $constraint->firstViolation(array_to_rows([ + ['id' => 3], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id')))), + ); + } + + public function test_first_violation_within_one_batch(): void + { + static::assertSame( + 2, + (new UniqueConstraint('id'))->firstViolation(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 1], + ], schema(int_schema('id')))), + ); + } + + public function test_an_empty_batch_has_no_violation(): void + { + static::assertNull((new UniqueConstraint('id'))->firstViolation(array_to_rows([], schema(int_schema('id'))))); } } 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 eaade52973..ca8be005ac 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php @@ -543,8 +543,8 @@ public function transform(Rows $rows, FlowContext $context): Rows { $stamped = []; - foreach ($rows->all() as $row) { - $stamped[] = [...$row->values(), 'stamp' => 'zero']; + for ($i = 0; $i < $rows->count(); $i++) { + $stamped[] = [...$rows->values($i), 'stamp' => 'zero']; } return array_to_rows($stamped, $rows->schema()->add(str_schema('stamp'))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/BoundedReadTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/BoundedReadTest.php new file mode 100644 index 0000000000..1b5f5a336b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/BoundedReadTest.php @@ -0,0 +1,44 @@ +read(IdRows::batches([1, 2], [3])); + + static::assertTrue($fits); + static::assertSame([[1, 2], [3]], array_map(static fn($rows): array => $rows->reduceToArray('id'), $read)); + } + + public function test_past_the_limit_reading_stops_and_the_rest_continues_where_it_stopped(): void + { + $rows = IdRows::batches([1, 2], [3], [4]); + $bounded = new BoundedRead(Unit::fromBytes(1), new PhpBackend()); + + [$read, $fits] = $bounded->read($rows); + + static::assertFalse($fits); + static::assertCount(1, $read); + static::assertSame([1, 2, 3, 4], IdRows::ids($bounded->followedBy($read, $rows))); + } + + public function test_followed_by_a_finished_stream_yields_only_what_was_read(): void + { + $rows = IdRows::batches([1]); + $bounded = new BoundedRead(Unit::fromGb(64), new PhpBackend()); + + [$read] = $bounded->read($rows); + + static::assertSame([1], IdRows::ids($bounded->followedBy($read, $rows))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/MemoryBudgetTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/MemoryBudgetTest.php new file mode 100644 index 0000000000..819365eea6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Memory/MemoryBudgetTest.php @@ -0,0 +1,48 @@ +exceeded()); + } + + public function test_native_memory_counts_towards_the_limit(): void + { + $budget = new MemoryBudget( + new ReportedMemoryBackend(2_000_000_000), + Unit::fromBytes(memory_get_usage(false) + 1_000_000_000), + ); + + static::assertTrue($budget->exceeded()); + } + + public function test_the_limit_follows_the_memory_the_process_holds_now(): void + { + $backend = new ReportedMemoryBackend(2_000_000_000); + $budget = new MemoryBudget($backend, Unit::fromBytes(memory_get_usage(false) + 1_000_000_000)); + + static::assertTrue($budget->exceeded()); + + $backend->reported = 0; + $budget->released(); + + static::assertFalse($budget->exceeded()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Statistics/ColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Statistics/ColumnTest.php index 0dde29d1c5..c17931a24d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Statistics/ColumnTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Statistics/ColumnTest.php @@ -7,13 +7,27 @@ use DateTimeImmutable; use Flow\ETL\Dataset\Statistics\Column; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\ColumnMother; +use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; +use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\structure_schema; use function Flow\ETL\DSL\time_zone_schema; +use function Flow\ETL\DSL\uuid_schema; use function Flow\Types\DSL\type_date; use function Flow\Types\DSL\type_datetime; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_structure; use function Flow\Types\DSL\type_time_zone; final class ColumnTest extends FlowTestCase @@ -22,20 +36,20 @@ public function test_collecting_column_statistics(): void { $definition = int_schema('a', true); - $statistics = new Column($definition, 1); + $statistics = new Column($definition, ColumnMother::of($definition, [1])); static::assertEquals(1, $statistics->distinctCount()); static::assertEquals(0, $statistics->nullCount()); static::assertEquals(1, $statistics->max()); static::assertEquals(1, $statistics->min()); - $statistics->add($definition, 2); + $statistics->add($definition, ColumnMother::of($definition, [2])); static::assertEquals(2, $statistics->distinctCount()); static::assertEquals(0, $statistics->nullCount()); static::assertEquals(2, $statistics->max()); static::assertEquals(1, $statistics->min()); - $statistics->add($definition, null); + $statistics->add($definition, ColumnMother::of($definition, [null])); static::assertEquals(2, $statistics->distinctCount()); static::assertEquals(1, $statistics->nullCount()); @@ -47,16 +61,16 @@ public function test_collecting_column_statistics_for_time_zone_entries(): void { $definition = time_zone_schema('tz', true); - $statistics = new Column($definition, type_time_zone()->cast('UTC')); + $statistics = new Column($definition, ColumnMother::of($definition, [type_time_zone()->cast('UTC')])); static::assertEquals(1, $statistics->distinctCount()); - $statistics->add($definition, type_time_zone()->cast('Europe/Warsaw')); + $statistics->add($definition, ColumnMother::of($definition, [type_time_zone()->cast('Europe/Warsaw')])); static::assertEquals(2, $statistics->distinctCount()); - $statistics->add($definition, type_time_zone()->cast('UTC')); + $statistics->add($definition, ColumnMother::of($definition, [type_time_zone()->cast('UTC')])); static::assertEquals(2, $statistics->distinctCount()); - $statistics->add($definition, null); + $statistics->add($definition, ColumnMother::of($definition, [null])); static::assertEquals(2, $statistics->distinctCount()); static::assertEquals(1, $statistics->nullCount()); } @@ -65,20 +79,20 @@ public function test_collecting_column_statistics_for_date_entries(): void { $definition = date_schema('a', true); - $statistics = new Column($definition, type_date()->cast('2024-01-01')); + $statistics = new Column($definition, ColumnMother::of($definition, [type_date()->cast('2024-01-01')])); static::assertEquals(1, $statistics->distinctCount()); static::assertEquals(0, $statistics->nullCount()); static::assertEquals(new DateTimeImmutable('2024-01-01'), $statistics->max()); static::assertEquals(new DateTimeImmutable('2024-01-01'), $statistics->min()); - $statistics->add($definition, type_date()->cast('2024-01-05')); + $statistics->add($definition, ColumnMother::of($definition, [type_date()->cast('2024-01-05')])); static::assertEquals(2, $statistics->distinctCount()); static::assertEquals(0, $statistics->nullCount()); static::assertEquals(new DateTimeImmutable('2024-01-05'), $statistics->max()); static::assertEquals(new DateTimeImmutable('2024-01-01'), $statistics->min()); - $statistics->add($definition, null); + $statistics->add($definition, ColumnMother::of($definition, [null])); static::assertEquals(2, $statistics->distinctCount()); static::assertEquals(1, $statistics->nullCount()); @@ -90,24 +104,125 @@ public function test_collecting_column_statistics_for_datetime_entries(): void { $definition = datetime_schema('a', true); - $statistics = new Column($definition, type_datetime()->cast('2024-01-01 00:00:01')); + $statistics = new Column($definition, ColumnMother::of($definition, [type_datetime()->cast( + '2024-01-01 00:00:01', + )])); static::assertEquals(1, $statistics->distinctCount()); static::assertEquals(0, $statistics->nullCount()); static::assertEquals(new DateTimeImmutable('2024-01-01 00:00:01'), $statistics->max()); static::assertEquals(new DateTimeImmutable('2024-01-01 00:00:01'), $statistics->min()); - $statistics->add($definition, type_datetime()->cast('2024-01-01 01:00:00')); + $statistics->add($definition, ColumnMother::of($definition, [type_datetime()->cast('2024-01-01 01:00:00')])); static::assertEquals(2, $statistics->distinctCount()); static::assertEquals(0, $statistics->nullCount()); static::assertEquals(new DateTimeImmutable('2024-01-01 01:00:00'), $statistics->max()); static::assertEquals(new DateTimeImmutable('2024-01-01 00:00:01'), $statistics->min()); - $statistics->add($definition, null); + $statistics->add($definition, ColumnMother::of($definition, [null])); static::assertEquals(2, $statistics->distinctCount()); static::assertEquals(1, $statistics->nullCount()); static::assertEquals(new DateTimeImmutable('2024-01-01 01:00:00'), $statistics->max()); static::assertEquals(new DateTimeImmutable('2024-01-01 00:00:01'), $statistics->min()); } + + public function test_a_column_of_many_values_with_nulls(): void + { + $definition = str_schema('s', true); + + $statistics = new Column($definition, ColumnMother::of($definition, ['abc', null, 'a', 'abc', null])); + + static::assertSame(2, $statistics->nullCount()); + static::assertSame(2, $statistics->distinctCount()); + static::assertSame(1, $statistics->minLength()); + static::assertSame(3, $statistics->maxLength()); + } + + public function test_a_column_of_only_nulls_counts_nulls(): void + { + $definition = int_schema('a', true); + + $statistics = new Column($definition, ColumnMother::of($definition, [null, null])); + + static::assertSame(2, $statistics->nullCount()); + static::assertSame(0, $statistics->distinctCount()); + static::assertNull($statistics->min()); + } + + public function test_another_column_is_ignored(): void + { + $statistics = new Column(int_schema('a'), ColumnMother::of(int_schema('a'), [1])); + + $statistics->add(int_schema('b'), ColumnMother::of(int_schema('b'), [5])); + + static::assertSame(1, $statistics->max()); + } + + public function test_booleans_and_floats(): void + { + $flags = new Column(bool_schema('b'), ColumnMother::of(bool_schema('b'), [true, false, true])); + $amounts = new Column(float_schema('f'), ColumnMother::of(float_schema('f'), [1.5, -0.5])); + + static::assertSame(2, $flags->distinctCount()); + static::assertFalse($flags->min()); + static::assertTrue($flags->max()); + static::assertSame(-0.5, $amounts->min()); + static::assertSame(1.5, $amounts->max()); + } + + public function test_datetimes_before_the_epoch_count_distinct_seconds(): void + { + $definition = datetime_schema('a'); + + $statistics = new Column($definition, ColumnMother::of($definition, [ + new DateTimeImmutable('1969-12-31 23:59:59.5'), + new DateTimeImmutable('1969-12-31 23:59:59.25'), + new DateTimeImmutable('1970-01-01 00:00:00'), + ])); + + static::assertSame(2, $statistics->distinctCount()); + static::assertEquals(new DateTimeImmutable('1969-12-31 23:59:59.25'), $statistics->min()); + static::assertEquals(new DateTimeImmutable('1970-01-01 00:00:00'), $statistics->max()); + } + + public function test_lists_and_maps_count_elements(): void + { + $lists = new Column( + list_schema('l', type_list(type_integer())), + ColumnMother::of(list_schema('l', type_list(type_integer())), [[1, 2, 3], [], [1, 2, 3]]), + ); + $maps = new Column( + map_schema('m', type_map(type_string(), type_integer())), + ColumnMother::of(map_schema('m', type_map(type_string(), type_integer())), [['a' => 1]]), + ); + + static::assertSame(2, $lists->distinctCount()); + static::assertSame(0, $lists->minElementsCount()); + static::assertSame(3, $lists->maxElementsCount()); + static::assertSame(1, $maps->maxElementsCount()); + } + + public function test_uuids_structures_and_json_count_by_value(): void + { + $uuids = new Column( + uuid_schema('u'), + ColumnMother::of( + uuid_schema('u'), + [ + '00000000-0000-4000-8000-000000000001', + '00000000-0000-4000-8000-000000000001', + ], + ), + ); + $structures = new Column( + structure_schema('s', type_structure(['a' => type_integer()])), + ColumnMother::of(structure_schema('s', type_structure(['a' => type_integer()])), [['a' => 1], ['a' => 2]]), + ); + $json = new Column(json_schema('j'), ColumnMother::of(json_schema('j'), ['{"a":1}'])); + + static::assertSame(1, $uuids->distinctCount()); + static::assertSame(2, $structures->distinctCount()); + static::assertSame(0, $json->distinctCount()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Statistics/ColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Statistics/ColumnsTest.php index 129dafc920..17d5b5a9b8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Statistics/ColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Dataset/Statistics/ColumnsTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Dataset\Statistics\Columns; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\ColumnMother; use InvalidArgumentException; use function Flow\ETL\DSL\integer_schema; @@ -17,12 +18,12 @@ public function test_columns_statistics(): void { $columns = new Columns(); - $columns->add(integer_schema('a'), 1); - $columns->add(integer_schema('a'), 100); - $columns->add(integer_schema('a'), -5); - $columns->add(string_schema('b', true), 'a'); - $columns->add(string_schema('b', true), 'some text'); - $columns->add(string_schema('b', true), null); + $columns->add(integer_schema('a'), ColumnMother::of(integer_schema('a'), [1])); + $columns->add(integer_schema('a'), ColumnMother::of(integer_schema('a'), [100])); + $columns->add(integer_schema('a'), ColumnMother::of(integer_schema('a'), [-5])); + $columns->add(string_schema('b', true), ColumnMother::of(string_schema('b', true), ['a'])); + $columns->add(string_schema('b', true), ColumnMother::of(string_schema('b', true), ['some text'])); + $columns->add(string_schema('b', true), ColumnMother::of(string_schema('b', true), [null])); static::assertCount(2, $columns->all()); static::assertSame(3, $columns->get('a')->distinctCount()); 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 7f8964d39e..b336040b35 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/ETLErrorHandlingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/ETLErrorHandlingTest.php @@ -287,7 +287,7 @@ public function bind(Schema $input): BoundStep public function transform(Rows $rows, FlowContext $context): Rows { - if ($rows->first()->get('id') === 101) { + if ($rows->column('id')->value(0) === 101) { throw new RuntimeException('Transformer Exception'); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/EvaluationExceptionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/EvaluationExceptionTest.php new file mode 100644 index 0000000000..df088f4a7f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Exception/EvaluationExceptionTest.php @@ -0,0 +1,44 @@ +rowIndex); + static::assertSame($cause, $exception->getPrevious()); + static::assertSame('division by zero (row 5)', $exception->getMessage()); + } + + public function test_at_wraps_any_other_exception(): void + { + $cause = new RuntimeException('division by zero'); + + $exception = EvaluationException::at(2, $cause); + + static::assertSame(2, $exception->rowIndex); + static::assertSame($cause, $exception->getPrevious()); + } + + public function test_carries_the_row_and_the_cause(): void + { + $cause = new RuntimeException('division by zero'); + + $exception = new EvaluationException(3, $cause); + + static::assertSame(3, $exception->rowIndex); + static::assertSame($cause, $exception->getPrevious()); + static::assertSame('division by zero (row 3)', $exception->getMessage()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php index a8f5eafec4..27cce26e98 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/OffsetPipelineTest.php @@ -260,10 +260,10 @@ public function test_process_with_transformer_before_offset(): void static::assertCount(1, $result); static::assertCount(3, $result[0]); $rows = $result[0]; - static::assertEquals(2, $rows->all()[0]->get('id')); - static::assertEquals(4, $rows->all()[0]->get('doubled')); - static::assertEquals(3, $rows->all()[1]->get('id')); - static::assertEquals(6, $rows->all()[1]->get('doubled')); + static::assertEquals(2, $rows->column('id')->value(0)); + static::assertEquals(4, $rows->column('doubled')->value(0)); + static::assertEquals(3, $rows->column('id')->value(1)); + static::assertEquals(6, $rows->column('doubled')->value(1)); } #[DataProvider('offset_values_data_provider')] @@ -280,7 +280,8 @@ public function test_process_with_various_offset_values(int $offset): void $totalRows = array_sum(array_map(static fn($batch) => $batch->count(), $result)); static::assertEquals($expectedCount, $totalRows); if ($expectedCount > 0) { - $firstRowId = $result[0]->first()->get('id'); + // @mago-ignore analysis:mixed-assignment + $firstRowId = $result[0]->column('id')->value(0); static::assertEquals($offset + 1, $firstRowId); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php index 09adab5564..a2622b4c6a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/WindowFunctionPipelineTest.php @@ -54,8 +54,8 @@ public function test_handles_no_order_by(): void static::assertCount(1, $result); static::assertCount(2, $result[0]); - static::assertEquals(250, $result[0][0]->get('total')); - static::assertEquals(250, $result[0][1]->get('total')); + static::assertEquals(250, $result[0]->column('total')->value(0)); + static::assertEquals(250, $result[0]->column('total')->value(1)); } public function test_handles_single_row_partition(): void @@ -98,12 +98,12 @@ public function test_processes_multiple_partitions_separately(): void static::assertCount(2, $result); static::assertCount(2, $result[0]); - static::assertEquals(1, $result[0][0]->get('row_num')); - static::assertEquals(2, $result[0][1]->get('row_num')); + static::assertEquals(1, $result[0]->column('row_num')->value(0)); + static::assertEquals(2, $result[0]->column('row_num')->value(1)); static::assertCount(2, $result[1]); - static::assertEquals(1, $result[1][0]->get('row_num')); - static::assertEquals(2, $result[1][1]->get('row_num')); + static::assertEquals(1, $result[1]->column('row_num')->value(0)); + static::assertEquals(2, $result[1]->column('row_num')->value(1)); } public function test_processes_single_partition_without_partition_by(): void @@ -122,9 +122,9 @@ public function test_processes_single_partition_without_partition_by(): void static::assertCount(1, $result); static::assertCount(3, $result[0]); - static::assertEquals(1, $result[0][0]->get('row_num')); - static::assertEquals(2, $result[0][1]->get('row_num')); - static::assertEquals(3, $result[0][2]->get('row_num')); + static::assertEquals(1, $result[0]->column('row_num')->value(0)); + static::assertEquals(2, $result[0]->column('row_num')->value(1)); + static::assertEquals(3, $result[0]->column('row_num')->value(2)); } public function test_sorts_partition_by_order_by(): void @@ -145,12 +145,12 @@ public function test_sorts_partition_by_order_by(): void $context = flow_context(config()); $result = iterator_to_array(ExecutedSegments::of($segments, $context)); - static::assertEquals(5000, $result[0][0]->get('salary')); - static::assertEquals(6000, $result[0][1]->get('salary')); - static::assertEquals(7000, $result[0][2]->get('salary')); + static::assertEquals(5000, $result[0]->column('salary')->value(0)); + static::assertEquals(6000, $result[0]->column('salary')->value(1)); + static::assertEquals(7000, $result[0]->column('salary')->value(2)); - static::assertEquals(1, $result[0][0]->get('row_num')); - static::assertEquals(2, $result[0][1]->get('row_num')); - static::assertEquals(3, $result[0][2]->get('row_num')); + static::assertEquals(1, $result[0]->column('row_num')->value(0)); + static::assertEquals(2, $result[0]->column('row_num')->value(1)); + static::assertEquals(3, $result[0]->column('row_num')->value(2)); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php index c7ffc00d3c..efeb84abb4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/ExecutorTest.php @@ -23,18 +23,23 @@ use Flow\ETL\Tests\Double\RecordingExtractor; use Flow\ETL\Tests\Double\RecordingFileExtractor; use Flow\ETL\Tests\Double\RecordingRule; +use Flow\ETL\Tests\Double\SpyColumn; use Flow\ETL\Tests\Double\SpyLoader; use Flow\ETL\Tests\Double\ThrowingTransformer; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\NodeMother; +use Flow\ETL\Tests\Mother\PhysicalPlanMother; use Flow\ETL\Tests\Mother\RowsMother; use Flow\ETL\Transformer\LimitTransformer; use Flow\ETL\Transformer\RenameEntryTransformer; use Flow\Filesystem\Tests\Double\RejectingFilter; use RuntimeException; +use function array_filter; +use function array_keys; use function array_map; use function array_sum; +use function array_values; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\config_builder; @@ -47,6 +52,45 @@ final class ExecutorTest extends FlowTestCase { + public function test_merge_concatenates_the_batches_once(): void + { + $calls = new ArrayObject(); + $schema = schema(int_schema('id')); + $batches = (static function () use ($schema, $calls) { + foreach ([[1], [2], [3], [4], [5]] as $ids) { + $column = array_to_rows([['id' => $ids[0]]], $schema)->column('id'); + + yield Rows::fromColumns($schema, ['id' => new SpyColumn($column, $calls)], 1); + } + })(); + + $merged = (new Executor())->merge($batches, PhysicalPlanMother::reading(from_array([]))); + + static::assertSame([1, 2, 3, 4, 5], $merged->reduceToArray('id')); + static::assertSame( + ['concat'], + array_values(array_filter($calls->getArrayCopy(), static fn(string $call): bool => $call === 'concat')), + ); + } + + public function test_merge_of_empty_batches_keeps_the_last_batch(): void + { + $batches = (static function () { + yield array_to_rows([], schema(int_schema('id'))); + yield array_to_rows([], schema(int_schema('other'))); + })(); + + static::assertSame( + ['other'], + array_keys( + (new Executor()) + ->merge($batches, PhysicalPlanMother::reading(from_array([]))) + ->schema() + ->definitions(), + ), + ); + } + public function test_a_single_pipeline_runs_its_segments_in_order(): void { $segments = new Segments(from_rows(RowsMother::sequentialIds(3))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ArrayExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ArrayExtractorTest.php index dd6426169d..6537e21283 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ArrayExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ArrayExtractorTest.php @@ -280,10 +280,7 @@ public function test_a_generator_is_described_exactly_and_extracted_once(): void public function test_positional_rows_are_named_like_the_hydrator_names_them(array $dataset, array $expected): void { static::assertSame($expected, array_keys(from_array($dataset)->schema()->definitions())); - static::assertSame( - $expected, - array_keys(data_frame()->read(from_array($dataset))->fetch()->first()->toArray()), - ); + static::assertSame($expected, array_keys(data_frame()->read(from_array($dataset))->fetch()->toArray()[0])); } public function test_a_bounded_sample_types_only_its_prefix(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php index da8e299ace..096a841b5c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/BatchByExtractorTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Extractor; +use DateTimeImmutable; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; @@ -12,12 +13,14 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\Double\DeclaringExtractor; use Flow\ETL\Tests\Double\VaryingBatchesExtractor; +use Flow\Types\Value\Uuid; use PHPUnit\Framework\TestCase; use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\batched_by; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_memory; use function Flow\ETL\DSL\from_rows; @@ -26,6 +29,7 @@ use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\uuid_schema; use function iterator_to_array; final class BatchByExtractorTest extends TestCase @@ -43,6 +47,71 @@ public function test_a_group_spanning_child_batches_answers_to_the_first_batch_s static::assertSame([['g' => 1, 'name' => 'a'], ['g' => 1, 'name' => null]], $batches[0]->toArray()); } + public function test_equal_uuids_stay_in_one_batch(): void + { + $batches = iterator_to_array( + batched_by( + from_rows(array_to_rows( + [ + ['id' => 1, 'u' => new Uuid('00000000-0000-4000-8000-000000000001')], + ['id' => 2, 'u' => new Uuid('00000000-0000-4000-8000-000000000001')], + ['id' => 3, 'u' => new Uuid('00000000-0000-4000-8000-000000000002')], + ], + schema(int_schema('id'), uuid_schema('u')), + )), + ref('u'), + )->extract(flow_context(config())), + false, + ); + + static::assertSame( + [[1, 2], [3]], + array_map(static fn(Rows $rows): array => $rows->reduceToArray('id'), $batches), + ); + } + + public function test_equal_datetimes_stay_in_one_batch(): void + { + $batches = iterator_to_array( + batched_by( + from_rows(array_to_rows( + [ + ['id' => 1, 'at' => new DateTimeImmutable('2026-01-01 00:00:00')], + ['id' => 2, 'at' => new DateTimeImmutable('2026-01-01 00:00:00')], + ['id' => 3, 'at' => new DateTimeImmutable('2026-01-02 00:00:00')], + ], + schema(int_schema('id'), datetime_schema('at')), + )), + ref('at'), + )->extract(flow_context(config())), + false, + ); + + static::assertSame( + [[1, 2], [3]], + array_map(static fn(Rows $rows): array => $rows->reduceToArray('id'), $batches), + ); + } + + public function test_nulls_are_a_group_of_their_own(): void + { + $batches = iterator_to_array( + batched_by( + from_rows(array_to_rows( + [['id' => 1, 'g' => null], ['id' => 2, 'g' => null], ['id' => 3, 'g' => 1]], + schema(int_schema('id'), int_schema('g', nullable: true)), + )), + ref('g'), + )->extract(flow_context(config())), + false, + ); + + static::assertSame( + [[1, 2], [3]], + array_map(static fn(Rows $rows): array => $rows->reduceToArray('id'), $batches), + ); + } + public function test_a_group_spanning_two_child_batches_is_one_batch(): void { $child = new VaryingBatchesExtractor( 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 85c6c045b6..89470dc73d 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 @@ -68,7 +68,7 @@ public function test_a_zero_string_extension_is_not_null(): void { $batches = iterator_to_array(files(__DIR__ . '/Fixtures/ZeroExtension/*')->extract(flow_context())); - static::assertSame('0', $batches[0]->first()->get('extension')); + static::assertSame('0', $batches[0]->column('extension')->value(0)); } public function test_partition_directories_become_string_columns(): void @@ -77,14 +77,14 @@ public function test_partition_directories_become_string_columns(): void . '/../../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(); + $first = iterator_to_array($extractor->extract(flow_context()), false)[0]->toArray()[0]; 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'), + 'day' => $first['day'], + 'month' => $first['month'], + 'year' => $first['year'], ]); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php index 12f77eab9c..6dd08212c6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php @@ -10,9 +10,7 @@ use Flow\Filesystem\Path\Filter\OnlyFiles; use function array_keys; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; -use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -41,15 +39,17 @@ public function test_apply_adds_a_column_the_inferred_schema_is_missing(): void public function test_apply_keeps_the_rows_it_was_given(): void { - static::assertEquals( - [array_to_row(['id' => 1, 'date' => null], schema(int_schema('id'), bool_schema('date', nullable: true)))], - (new PartitionColumns(new MemoryFilesystem()))->apply( - array_to_rows( - [['id' => 1, 'date' => null]], - schema(int_schema('id'), str_schema('date', nullable: true)), - ), - ['date' => true], - )->all(), + static::assertSame( + [['id' => 1, 'date' => null]], + (new PartitionColumns(new MemoryFilesystem())) + ->apply( + array_to_rows( + [['id' => 1, 'date' => null]], + schema(int_schema('id'), str_schema('date', nullable: true)), + ), + ['date' => true], + ) + ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllTest.php index 18a9496040..684eb7e14c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllTest.php @@ -5,13 +5,18 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Function\All; +use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Double\FailingOnValuesFunction; use Flow\ETL\Tests\FlowTestCase; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\all; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -43,37 +48,63 @@ public static function three_valued_and(): Generator #[DataProvider('three_valued_and')] public function test_three_valued_truth_table(?bool $left, ?bool $right, ?bool $expected): void { - static::assertSame($expected, (new All(lit($left), lit($right)))->eval( - array_to_row([], schema()), - flow_context(), + static::assertSame($expected, (new FunctionContext(flow_context()))->eval( + new All(lit($left), lit($right)), + [], + schema(), )); } public function test_all_expression_on_is_null_expression(): void { - static::assertTrue( - all(ref('value')->isNull()) - ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + all(ref('value')->isNull()), + ['value' => null], + schema(str_schema('value', nullable: true)), + )); } public function test_all_expression_on_multiple_boolean_values(): void { - static::assertTrue(all(lit(true), lit(true), lit(true))->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + all(lit(true), lit(true), lit(true)), + [], + schema(), + )); } public function test_all_expression_on_multiple_random_boolean_values(): void { - static::assertFalse(all(lit(true), lit(false), lit(true))->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval( + all(lit(true), lit(false), lit(true)), + [], + schema(), + )); } public function test_all_function_on_boolean_false_value(): void { - static::assertFalse(all(lit(false))->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval(all(lit(false)), [], schema())); } public function test_all_function_on_boolean_true_value(): void { - static::assertTrue(all(lit(true))->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval(all(lit(true)), [], schema())); + } + + public function test_an_undecided_row_only_reaches_the_next_argument(): void + { + $rows = array_to_rows( + [['c' => false, 'v' => 99], ['c' => true, 'v' => 1]], + schema(bool_schema('c'), int_schema('v')), + ); + + static::assertSame( + [false, true], + (new ReferenceResolver()) + ->resolve(all(ref('c'), (new FailingOnValuesFunction(ref('v'), [99]))->isNotNull()), $rows->schema()) + ->eval($rows, flow_context()) + ->values(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AnyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AnyTest.php index 534be7e28b..a4ed0a497f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AnyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AnyTest.php @@ -5,13 +5,18 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Function\Any; +use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Double\FailingOnValuesFunction; use Flow\ETL\Tests\FlowTestCase; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\any; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -43,32 +48,54 @@ public static function three_valued_or(): Generator #[DataProvider('three_valued_or')] public function test_three_valued_truth_table(?bool $left, ?bool $right, ?bool $expected): void { - static::assertSame($expected, (new Any(lit($left), lit($right)))->eval( - array_to_row([], schema()), - flow_context(), + static::assertSame($expected, (new FunctionContext(flow_context()))->eval( + new Any(lit($left), lit($right)), + [], + schema(), )); } public function test_any_expression_on_boolean_false_value(): void { - static::assertFalse(any(lit(false))->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval(any(lit(false)), [], schema())); } public function test_any_expression_on_boolean_true_value(): void { - static::assertTrue(any(lit(true))->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval(any(lit(true)), [], schema())); } public function test_any_expression_on_is_null_expression(): void { - static::assertTrue( - any(ref('value')->isNull()) - ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + any(ref('value')->isNull()), + ['value' => null], + schema(str_schema('value', nullable: true)), + )); } public function test_any_expression_on_multiple_boolean_values(): void { - static::assertTrue(any(lit(false), lit(true), lit(false))->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + any(lit(false), lit(true), lit(false)), + [], + schema(), + )); + } + + public function test_an_undecided_row_only_reaches_the_next_argument(): void + { + $rows = array_to_rows( + [['c' => true, 'v' => 99], ['c' => false, 'v' => 1]], + schema(bool_schema('c'), int_schema('v')), + ); + + static::assertSame( + [true, true], + (new ReferenceResolver()) + ->resolve(any(ref('c'), (new FailingOnValuesFunction(ref('v'), [99]))->isNotNull()), $rows->schema()) + ->eval($rows, flow_context()) + ->values(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AppendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AppendTest.php index 0459709f97..a57b43d41b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AppendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AppendTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; @@ -18,44 +18,38 @@ final class AppendTest extends FlowTestCase { public function test_append_empty_string_to_content(): void { - $result = ref('str') - ->append('') - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->append(''), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_append_to_empty_string(): void { - $result = ref('str') - ->append('hello') - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->append('hello'), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_append_to_non_empty_string(): void { - $result = ref('str') - ->append(' world') - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('hello world', $result); + static::assertEquals('hello world', (new FunctionContext(flow_context()))->eval( + ref('str')->append(' world'), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_append_with_null_suffix(): void { - $result = ref('str') - ->append(ref('suffix')) - ->eval( - array_to_row( - ['str' => 'hello', 'suffix' => null], - schema(str_schema('str'), str_schema('suffix', nullable: true)), - ), - flow_context(), - ); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->append(ref('suffix')), + ['str' => 'hello', 'suffix' => null], + schema(str_schema('str'), str_schema('suffix', nullable: true)), + )); } public function test_append_with_null_value(): void @@ -63,11 +57,11 @@ public function test_append_with_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Append function requires non-null value'); - $result = ref('str') - ->append(' world') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); - - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->append(' world'), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_append_with_null_value_in_strict_mode(): void @@ -76,20 +70,19 @@ public function test_append_with_null_value_in_strict_mode(): void $this->expectExceptionMessage('Append function requires non-null value'); $context = flow_context(config()); - ref('str') - ->append(' world') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), $context); + (new FunctionContext($context))->eval( + ref('str')->append(' world'), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_append_with_scalar_function_parameter(): void { - $result = ref('str') - ->append(ref('suffix')) - ->eval( - array_to_row(['str' => 'hello', 'suffix' => ' world'], schema(str_schema('str'), str_schema('suffix'))), - flow_context(), - ); - - static::assertEquals('hello world', $result); + static::assertEquals('hello world', (new FunctionContext(flow_context()))->eval( + ref('str')->append(ref('suffix')), + ['str' => 'hello', 'suffix' => ' world'], + schema(str_schema('str'), str_schema('suffix')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayExpandTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayExpandTest.php index ed000a591e..aef0d82eb6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayExpandTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayExpandTest.php @@ -8,11 +8,11 @@ use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Function\ArrayExpand\ArrayExpand; use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\DSL\array_expand; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -33,42 +33,55 @@ final class ArrayExpandTest extends FlowTestCase { public function test_expand_both(): void { - $row = array_to_row(['array' => [ - 'a' => 1, - 'b' => 2, - 'c' => 3, - ]], schema(map_schema('array', type_map(type_string(), type_integer())))); - static::assertSame( [ ['a' => 1], ['b' => 2], ['c' => 3], ], - array_expand(ref('array'), ArrayExpand::BOTH)->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + array_expand(ref('array'), ArrayExpand::BOTH), + ['array' => [ + 'a' => 1, + 'b' => 2, + 'c' => 3, + ]], + schema(map_schema('array', type_map(type_string(), type_integer()))), + ), ); } public function test_expand_keys(): void { - $row = array_to_row(['array' => [ - 'a' => 1, - 'b' => 2, - 'c' => 3, - ]], schema(map_schema('array', type_map(type_string(), type_integer())))); - - static::assertSame(['a', 'b', 'c'], array_expand(ref('array'), ArrayExpand::KEYS)->eval($row, flow_context())); + static::assertSame( + ['a', 'b', 'c'], + (new FunctionContext(flow_context()))->eval( + array_expand(ref('array'), ArrayExpand::KEYS), + ['array' => [ + 'a' => 1, + 'b' => 2, + 'c' => 3, + ]], + schema(map_schema('array', type_map(type_string(), type_integer()))), + ), + ); } public function test_expand_values(): void { - $row = array_to_row(['array' => [ - 'a' => 1, - 'b' => 2, - 'c' => 3, - ]], schema(map_schema('array', type_map(type_string(), type_integer())))); - - static::assertSame(['a' => 1, 'b' => 2, 'c' => 3], array_expand(ref('array'))->eval($row, flow_context())); + // an expand hands the step a list: the keys never reached the exploded column + static::assertSame( + [1, 2, 3], + (new FunctionContext(flow_context()))->eval( + array_expand(ref('array')), + ['array' => [ + 'a' => 1, + 'b' => 2, + 'c' => 3, + ]], + schema(map_schema('array', type_map(type_string(), type_integer()))), + ), + ); } public function test_for_not_array_entry(): void @@ -76,8 +89,11 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - array_expand(ref('integer_entry')) - ->eval(array_to_row(['integer_entry' => 1], schema(int_schema('integer_entry'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + array_expand(ref('integer_entry')), + ['integer_entry' => 1], + schema(int_schema('integer_entry')), + ); } public function test_for_not_array_entry_in_strict_mode(): void @@ -86,8 +102,11 @@ public function test_for_not_array_entry_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - array_expand(ref('integer_entry')) - ->eval(array_to_row(['integer_entry' => 1], schema(int_schema('integer_entry'))), $context); + (new FunctionContext($context))->eval( + array_expand(ref('integer_entry')), + ['integer_entry' => 1], + schema(int_schema('integer_entry')), + ); } public function test_values_over_a_structure_declare_the_unified_field_type(): void @@ -195,9 +214,13 @@ public function test_a_null_array_expands_to_nothing(ArrayExpand $expand): void { static::assertSame( [], - array_expand(ref('list'), $expand)->eval(array_to_row([ - 'list' => null, - ], schema(str_schema('list', nullable: true))), flow_context()), + (new FunctionContext(flow_context()))->eval( + array_expand(ref('list'), $expand), + [ + 'list' => null, + ], + schema(str_schema('list', nullable: true)), + ), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayFilterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayFilterTest.php index e8f317660d..b8c943b13c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayFilterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayFilterTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -25,12 +25,14 @@ public function test_array_filter(): void { static::assertSame( [1], - ref('list') - ->arrayFilter(lit(2)) - ->eval(array_to_row(['list' => [ + (new FunctionContext(flow_context()))->eval( + ref('list')->arrayFilter(lit(2)), + ['list' => [ 1, 2, - ]], schema(list_schema('list', type_list(type_integer())))), flow_context()), + ]], + schema(list_schema('list', type_list(type_integer()))), + ), ); } @@ -38,15 +40,11 @@ public function test_array_filter_by_entry_reference(): void { static::assertSame( [1], - ref('list') - ->arrayFilter(ref('int')) - ->eval( - array_to_row( - ['list' => [1, 2], 'int' => 2], - schema(list_schema('list', type_list(type_integer())), int_schema('int')), - ), - flow_context(), - ), + (new FunctionContext(flow_context()))->eval( + ref('list')->arrayFilter(ref('int')), + ['list' => [1, 2], 'int' => 2], + schema(list_schema('list', type_list(type_integer())), int_schema('int')), + ), ); } @@ -56,19 +54,25 @@ public function test_array_filter_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('map')->arrayFilter(lit(1))->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), $context); + (new FunctionContext($context))->eval( + ref('map')->arrayFilter(lit(1)), + ['map' => 'test'], + schema(str_schema('map')), + ); } public function test_array_filter_not_existing_value(): void { static::assertSame( [1, 2], - ref('list') - ->arrayFilter(lit(5)) - ->eval(array_to_row(['list' => [ + (new FunctionContext(flow_context()))->eval( + ref('list')->arrayFilter(lit(5)), + ['list' => [ 1, 2, - ]], schema(list_schema('list', type_list(type_integer())))), flow_context()), + ]], + schema(list_schema('list', type_list(type_integer()))), + ), ); } @@ -77,8 +81,10 @@ public function test_array_filter_on_non_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('map') - ->arrayFilter(lit(1)) - ->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('map')->arrayFilter(lit(1)), + ['map' => 'test'], + schema(str_schema('map')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetCollectionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetCollectionTest.php index d2b9640c4a..1fba097f60 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetCollectionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetCollectionTest.php @@ -5,13 +5,13 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\DSL\array_get_collection; use function Flow\ETL\DSL\array_get_collection_first; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -37,9 +37,12 @@ public function test_array_get_collection_in_strict_mode(): void $this->expectExceptionMessage('ArrayGetCollection function failed to evaluate parameters'); $context = flow_context(config()); - $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); - array_get_collection(ref('invalid_entry'), ['id'])->eval($row, $context); + (new FunctionContext($context))->eval( + array_get_collection(ref('invalid_entry'), ['id']), + ['invalid_entry' => 1], + schema(int_schema('invalid_entry')), + ); } public function test_for_not_array_entry(): void @@ -47,9 +50,11 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGetCollection function failed to evaluate parameters.'); - $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); - - array_get_collection(ref('invalid_entry'), ['id'])->eval($row, flow_context()); + (new FunctionContext(flow_context()))->eval( + array_get_collection(ref('invalid_entry'), ['id']), + ['invalid_entry' => 1], + schema(int_schema('invalid_entry')), + ); } public function test_getting_keys_from_simple_array(): void @@ -57,111 +62,127 @@ public function test_getting_keys_from_simple_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGetCollection function failed to evaluate parameters.'); - $row = RowsMother::arrayEntry(); + $rows = RowsMother::arrayEntry(); - array_get_collection(ref('array_entry'), ['id'])->eval($row, flow_context()); + (new FunctionContext(flow_context()))->eval( + array_get_collection(ref('array_entry'), ['id']), + $rows->values(0), + $rows->schema(), + ); } public function test_getting_specific_keys_from_collection_of_array(): void { - $row = array_to_row([ - 'array_entry' => [ - [ - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - [ - 'id' => 2, - 'status' => 'NEW', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - ], - ], schema(list_schema('array_entry', type_list(type_structure([ - 'id' => type_integer(), - 'status' => type_string(), - 'enabled' => type_boolean(), - 'array' => type_structure(['foo' => type_string()]), - ]))))); - static::assertEquals( [ ['id' => 1, 'status' => 'PENDING'], ['id' => 2, 'status' => 'NEW'], ], - array_get_collection(ref('array_entry'), ['id', 'status'])->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + array_get_collection(ref('array_entry'), ['id', 'status']), + [ + 'array_entry' => [ + [ + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'array' => ['foo' => 'bar'], + ], + [ + 'id' => 2, + 'status' => 'NEW', + 'enabled' => true, + 'array' => ['foo' => 'bar'], + ], + ], + ], + schema(list_schema( + 'array_entry', + type_list(type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ])), + )), + ), ); } public function test_getting_specific_keys_from_first_element_in_collection_of_array(): void { - $row = array_to_row([ - 'array_entry' => [ - [ - 'parent_id' => 1, - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - [ - 'parent_id' => 1, - 'id' => 2, - 'status' => 'NEW', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - ], - ], schema(list_schema('array_entry', type_list(type_structure([ - 'parent_id' => type_integer(), - 'id' => type_integer(), - 'status' => type_string(), - 'enabled' => type_boolean(), - 'array' => type_structure(['foo' => type_string()]), - ]))))); - static::assertEquals( [ 'parent_id' => 1, ], - ref('array_entry')->arrayGetCollectionFirst('parent_id')->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('array_entry')->arrayGetCollectionFirst('parent_id'), + [ + 'array_entry' => [ + [ + 'parent_id' => 1, + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'array' => ['foo' => 'bar'], + ], + [ + 'parent_id' => 1, + 'id' => 2, + 'status' => 'NEW', + 'enabled' => true, + 'array' => ['foo' => 'bar'], + ], + ], + ], + schema(list_schema( + 'array_entry', + type_list(type_structure([ + 'parent_id' => type_integer(), + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ])), + )), + ), ); } public function test_getting_specific_keys_from_first_element_in_collection_of_array_when_first_index_does_not_exists(): void { - $row = array_to_row([ - 'array_entry' => [ - 2 => [ - 'parent_id' => 1, - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - 3 => [ - 'parent_id' => 1, - 'id' => 2, - 'status' => 'NEW', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], - ], - ], schema(map_schema('array_entry', type_map(type_integer(), type_structure([ - 'parent_id' => type_integer(), - 'id' => type_integer(), - 'status' => type_string(), - 'enabled' => type_boolean(), - 'array' => type_structure(['foo' => type_string()]), - ]))))); - static::assertEquals( [ 'parent_id' => 1, ], - array_get_collection_first(ref('array_entry'), 'parent_id')->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + array_get_collection_first(ref('array_entry'), 'parent_id'), + [ + 'array_entry' => [ + 2 => [ + 'parent_id' => 1, + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'array' => ['foo' => 'bar'], + ], + 3 => [ + 'parent_id' => 1, + 'id' => 2, + 'status' => 'NEW', + 'enabled' => true, + 'array' => ['foo' => 'bar'], + ], + ], + ], + schema(map_schema('array_entry', type_map(type_integer(), type_structure([ + 'parent_id' => type_integer(), + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ])))), + ), ); } @@ -175,9 +196,13 @@ public function test_getting_specific_keys_from_first_element_in_collection_of_a #[TestWith([['a.b'], [['a' => ['b' => 1]]], [['a.b' => null]]])] public function test_keys_are_literal_keys(array $keys, array $collection, array $expected): void { - static::assertSame($expected, array_get_collection(ref('array_entry'), $keys)->eval(array_to_row([ - 'array_entry' => $collection, - ], schema(json_schema('array_entry'))), flow_context())); + static::assertSame($expected, (new FunctionContext(flow_context()))->eval( + array_get_collection(ref('array_entry'), $keys), + [ + 'array_entry' => $collection, + ], + schema(json_schema('array_entry')), + )); } public function test_a_non_scalar_key_fails(): void @@ -185,18 +210,22 @@ public function test_a_non_scalar_key_fails(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGetCollection function failed to evaluate parameters.'); - array_get_collection(ref('array_entry'), [[ + (new FunctionContext(flow_context()))->eval(array_get_collection(ref('array_entry'), [[ 'x', - ]])->eval(array_to_row(['array_entry' => [['x' => 1]]], schema(list_schema('array_entry', type_list(type_structure(['x' => type_integer()]))))), flow_context()); + ]]), ['array_entry' => [['x' => 1]]], schema(list_schema('array_entry', type_list(type_structure(['x' => type_integer()]))))); } public function test_an_empty_element_reads_null_keys(): void { static::assertSame( [['id' => null], ['id' => null]], - array_get_collection(ref('array_entry'), ['id'])->eval(array_to_row([ - 'array_entry' => [['name' => 'a'], []], - ], schema(json_schema('array_entry'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + array_get_collection(ref('array_entry'), ['id']), + [ + 'array_entry' => [['name' => 'a'], []], + ], + schema(json_schema('array_entry')), + ), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetTest.php index e3fda29a01..99882b85f1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayGetTest.php @@ -6,11 +6,13 @@ use DateTimeImmutable; use Flow\ArrayDot\Exception\InvalidPathException; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Function\ArrayGet; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; use Flow\Types\Type\Logical\StructureType; @@ -18,7 +20,6 @@ use function Flow\ETL\DSL\array_exists; use function Flow\ETL\DSL\array_get; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; @@ -112,12 +113,20 @@ public function test_array_access_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGet function failed to get value from array.'); - array_get(ref('integer_entry'), 'invalid_path')->eval(array_to_row([ - 'integer_entry' => 1, - ], schema(int_schema('integer_entry'))), flow_context()); - array_exists(ref('integer_entry'), 'invalid_path')->eval(array_to_row([ - 'integer_entry' => 1, - ], schema(int_schema('integer_entry'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + array_get(ref('integer_entry'), 'invalid_path'), + [ + 'integer_entry' => 1, + ], + schema(int_schema('integer_entry')), + ); + (new FunctionContext(flow_context()))->eval( + array_exists(ref('integer_entry'), 'invalid_path'), + [ + 'integer_entry' => 1, + ], + schema(int_schema('integer_entry')), + ); } public function test_array_access_for_not_array_entry_strict_mode(): void @@ -126,60 +135,118 @@ public function test_array_access_for_not_array_entry_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayGet function failed to get value from array'); - array_get(ref('integer_entry'), 'invalid_path')->eval(array_to_row([ - 'integer_entry' => 1, - ], schema(int_schema('integer_entry'))), $context); + (new FunctionContext($context))->eval( + array_get(ref('integer_entry'), 'invalid_path'), + [ + 'integer_entry' => 1, + ], + schema(int_schema('integer_entry')), + ); } public function test_array_accessor_transformer(): void { - $row = RowsMother::arrayEntry(); - static::assertEquals('bar', array_get(ref('array_entry'), 'array.foo')->eval($row, flow_context())); - static::assertTrue(array_exists(ref('array_entry'), 'array.foo')->eval($row, flow_context())); + $rows = RowsMother::arrayEntry(); + static::assertEquals('bar', (new FunctionContext(flow_context()))->eval( + array_get(ref('array_entry'), 'array.foo'), + $rows->values(0), + $rows->schema(), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + array_exists(ref('array_entry'), 'array.foo'), + $rows->values(0), + $rows->schema(), + )); } public function test_array_accessor_transformer_with_invalid_and_without_strict_path(): void { - $row = array_to_row([ - 'array_entry' => [ - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'datetime' => new DateTimeImmutable('2020-01-01 00:00:00 UTC'), - 'array' => ['foo' => 'bar'], + static::assertNull((new FunctionContext(flow_context()))->eval( + array_get(ref('array_entry'), '?invalid_path'), + [ + 'array_entry' => [ + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'datetime' => new DateTimeImmutable('2020-01-01 00:00:00 UTC'), + 'array' => ['foo' => 'bar'], + ], + ], + schema(structure_schema('array_entry', type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'datetime' => type_datetime(), + 'array' => type_structure(['foo' => type_string()]), + ]))), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + array_exists(ref('array_entry'), '?invalid_path'), + [ + 'array_entry' => [ + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'datetime' => new DateTimeImmutable('2020-01-01 00:00:00 UTC'), + 'array' => ['foo' => 'bar'], + ], ], - ], schema(structure_schema('array_entry', type_structure([ - 'id' => type_integer(), - 'status' => type_string(), - 'enabled' => type_boolean(), - 'datetime' => type_datetime(), - 'array' => type_structure(['foo' => type_string()]), - ])))); - static::assertNull(array_get(ref('array_entry'), '?invalid_path')->eval($row, flow_context())); - static::assertTrue(array_exists(ref('array_entry'), '?invalid_path')->eval($row, flow_context())); - static::assertFalse(array_exists(ref('array_entry'), 'invalid_path')->eval($row, flow_context())); + schema(structure_schema('array_entry', type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'datetime' => type_datetime(), + 'array' => type_structure(['foo' => type_string()]), + ]))), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + array_exists(ref('array_entry'), 'invalid_path'), + [ + 'array_entry' => [ + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'datetime' => new DateTimeImmutable('2020-01-01 00:00:00 UTC'), + 'array' => ['foo' => 'bar'], + ], + ], + schema(structure_schema('array_entry', type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'datetime' => type_datetime(), + 'array' => type_structure(['foo' => type_string()]), + ]))), + )); } public function test_array_accessor_transformer_with_invalid_but_strict_path(): void { - $this->expectException(InvalidPathException::class); - $this->expectExceptionMessage('Path "invalid_path" does not exists in array '); - - array_get(ref('array_entry'), 'invalid_path')->eval(array_to_row([ - 'array_entry' => [ - 'id' => 1, - 'status' => 'PENDING', - 'enabled' => true, - 'datetime' => new DateTimeImmutable('2020-01-01 00:00:00 UTC'), - 'array' => ['foo' => 'bar'], - ], - ], schema(structure_schema('array_entry', type_structure([ - 'id' => type_integer(), - 'status' => type_string(), - 'enabled' => type_boolean(), - 'datetime' => type_datetime(), - 'array' => type_structure(['foo' => type_string()]), - ])))), flow_context()); + try { + (new FunctionContext(flow_context()))->eval( + array_get(ref('array_entry'), 'invalid_path'), + [ + 'array_entry' => [ + 'id' => 1, + 'status' => 'PENDING', + 'enabled' => true, + 'datetime' => new DateTimeImmutable('2020-01-01 00:00:00 UTC'), + 'array' => ['foo' => 'bar'], + ], + ], + schema(structure_schema('array_entry', type_structure([ + 'id' => type_integer(), + 'status' => type_string(), + 'enabled' => type_boolean(), + 'datetime' => type_datetime(), + 'array' => type_structure(['foo' => type_string()]), + ]))), + ); + static::fail('expected an EvaluationException'); + } catch (EvaluationException $e) { + static::assertInstanceOf(InvalidPathException::class, $e->getPrevious()); + static::assertStringContainsString('Path "invalid_path" does not exists in array ', $e->getMessage()); + } } public function test_returns_rejects_a_non_structure_input(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeepTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeepTest.php index 60efbb1b77..7ce25035d1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeepTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeepTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -25,12 +25,14 @@ public function test_array_keep(): void { static::assertSame( [1 => 2], - ref('list') - ->arrayKeep(lit(2)) - ->eval(array_to_row(['list' => [ + (new FunctionContext(flow_context()))->eval( + ref('list')->arrayKeep(lit(2)), + ['list' => [ 1, 2, - ]], schema(list_schema('list', type_list(type_integer())))), flow_context()), + ]], + schema(list_schema('list', type_list(type_integer()))), + ), ); } @@ -38,15 +40,11 @@ public function test_array_keep_by_entry_reference(): void { static::assertSame( [1 => 2], - ref('list') - ->arrayKeep(ref('int')) - ->eval( - array_to_row( - ['list' => [1, 2], 'int' => 2], - schema(list_schema('list', type_list(type_integer())), int_schema('int')), - ), - flow_context(), - ), + (new FunctionContext(flow_context()))->eval( + ref('list')->arrayKeep(ref('int')), + ['list' => [1, 2], 'int' => 2], + schema(list_schema('list', type_list(type_integer())), int_schema('int')), + ), ); } @@ -56,19 +54,25 @@ public function test_array_keep_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('map')->arrayKeep(lit(1))->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), $context); + (new FunctionContext($context))->eval( + ref('map')->arrayKeep(lit(1)), + ['map' => 'test'], + schema(str_schema('map')), + ); } public function test_array_keep_not_existing_value(): void { static::assertSame( [], - ref('list') - ->arrayKeep(lit(5)) - ->eval(array_to_row(['list' => [ + (new FunctionContext(flow_context()))->eval( + ref('list')->arrayKeep(lit(5)), + ['list' => [ 1, 2, - ]], schema(list_schema('list', type_list(type_integer())))), flow_context()), + ]], + schema(list_schema('list', type_list(type_integer()))), + ), ); } @@ -77,6 +81,10 @@ public function test_array_keep_on_non_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('map')->arrayKeep(lit(1))->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('map')->arrayKeep(lit(1)), + ['map' => 'test'], + schema(str_schema('map')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeyRenameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeyRenameTest.php index de09dc376b..2f18854641 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeyRenameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeyRenameTest.php @@ -5,12 +5,13 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ArrayDot\Exception\InvalidPathException; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; use function Flow\ETL\DSL\array_key_rename; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -28,9 +29,12 @@ public function test_array_key_rename_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - $row = array_to_row(['integer_entry' => 1], schema(int_schema('integer_entry'))); - array_key_rename(ref('integer_entry'), 'invalid_path', 'new_name')->eval($row, $context); + (new FunctionContext($context))->eval( + array_key_rename(ref('integer_entry'), 'invalid_path', 'new_name'), + ['integer_entry' => 1], + schema(int_schema('integer_entry')), + ); } public function test_for_not_array_entry(): void @@ -38,42 +42,43 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - $row = array_to_row(['integer_entry' => 1], schema(int_schema('integer_entry'))); - - array_key_rename(ref('integer_entry'), 'invalid_path', 'new_name')->eval($row, flow_context()); + (new FunctionContext(flow_context()))->eval( + array_key_rename(ref('integer_entry'), 'invalid_path', 'new_name'), + ['integer_entry' => 1], + schema(int_schema('integer_entry')), + ); } public function test_renames_array_entry_keys_in_multiple_array_entry(): void { - $row = array_to_row( - [ - 'customer' => [ - 'first' => 'John', - 'last' => 'Snow', - ], - 'shipping' => [ - 'address' => [ - 'line' => '3644 Clement Street', - 'city' => 'Atalanta', - ], - 'estimated_delivery_date' => '2023-04-01T10:00:00+00:00', - ], - ], - schema( - structure_schema('customer', type_structure(['first' => type_string(), 'last' => type_string()])), - structure_schema('shipping', type_structure([ - 'address' => type_structure(['line' => type_string(), 'city' => type_string()]), - 'estimated_delivery_date' => type_string(), - ])), - ), - ); - static::assertEquals( [ 'first_name' => 'John', 'last' => 'Snow', ], - array_key_rename(ref('customer'), 'first', 'first_name')->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + array_key_rename(ref('customer'), 'first', 'first_name'), + [ + 'customer' => [ + 'first' => 'John', + 'last' => 'Snow', + ], + 'shipping' => [ + 'address' => [ + 'line' => '3644 Clement Street', + 'city' => 'Atalanta', + ], + 'estimated_delivery_date' => '2023-04-01T10:00:00+00:00', + ], + ], + schema( + structure_schema('customer', type_structure(['first' => type_string(), 'last' => type_string()])), + structure_schema('shipping', type_structure([ + 'address' => type_structure(['line' => type_string(), 'city' => type_string()]), + 'estimated_delivery_date' => type_string(), + ])), + ), + ), ); static::assertEquals( @@ -84,13 +89,35 @@ public function test_renames_array_entry_keys_in_multiple_array_entry(): void ], 'estimated_delivery_date' => '2023-04-01T10:00:00+00:00', ], - array_key_rename(ref('shipping'), 'address.line', 'street')->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + array_key_rename(ref('shipping'), 'address.line', 'street'), + [ + 'customer' => [ + 'first' => 'John', + 'last' => 'Snow', + ], + 'shipping' => [ + 'address' => [ + 'line' => '3644 Clement Street', + 'city' => 'Atalanta', + ], + 'estimated_delivery_date' => '2023-04-01T10:00:00+00:00', + ], + ], + schema( + structure_schema('customer', type_structure(['first' => type_string(), 'last' => type_string()])), + structure_schema('shipping', type_structure([ + 'address' => type_structure(['line' => type_string(), 'city' => type_string()]), + 'estimated_delivery_date' => type_string(), + ])), + ), + ), ); } public function test_renames_array_entry_keys_in_single_array_entry(): void { - $row = RowsMother::arrayEntry(); + $rows = RowsMother::arrayEntry(); static::assertEquals( [ @@ -99,17 +126,28 @@ public function test_renames_array_entry_keys_in_single_array_entry(): void 'enabled' => true, 'array' => ['new_name' => 'bar'], ], - array_key_rename(ref('array_entry'), 'array.foo', 'new_name')->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + array_key_rename(ref('array_entry'), 'array.foo', 'new_name'), + $rows->values(0), + $rows->schema(), + ), ); } public function test_throws_exception_for_invalid_path(): void { - $row = RowsMother::arrayEntry(); - - $this->expectException(InvalidPathException::class); - $this->expectExceptionMessage('Path "invalid_path" does not exists in array '); - - array_key_rename(ref('array_entry'), 'invalid_path', 'new_name')->eval($row, flow_context()); + $rows = RowsMother::arrayEntry(); + + try { + (new FunctionContext(flow_context()))->eval( + array_key_rename(ref('array_entry'), 'invalid_path', 'new_name'), + $rows->values(0), + $rows->schema(), + ); + static::fail('expected an EvaluationException'); + } catch (EvaluationException $e) { + static::assertInstanceOf(InvalidPathException::class, $e->getPrevious()); + static::assertStringContainsString('Path "invalid_path" does not exists in array ', $e->getMessage()); + } } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysStyleConverterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysStyleConverterTest.php index 087b95404e..07e34a2c7e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysStyleConverterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysStyleConverterTest.php @@ -8,10 +8,10 @@ use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\String\StringStyles; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_keys_style_convert; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\json_schema; @@ -31,9 +31,11 @@ public function test_for_invalid_style(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Unrecognized style invalid, please use one of following:'); - $row = array_to_row(['invalid_entry' => []], schema(json_schema('invalid_entry'))); - - array_keys_style_convert(ref('invalid_entry'), 'invalid')->eval($row, flow_context()); + (new FunctionContext(flow_context()))->eval( + array_keys_style_convert(ref('invalid_entry'), 'invalid'), + ['invalid_entry' => []], + schema(json_schema('invalid_entry')), + ); } public function test_for_not_array_entry(): void @@ -41,45 +43,15 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); - - array_keys_style_convert(ref('invalid_entry'), 'snake')->eval($row, flow_context()); + (new FunctionContext(flow_context()))->eval( + array_keys_style_convert(ref('invalid_entry'), 'snake'), + ['invalid_entry' => 1], + schema(int_schema('invalid_entry')), + ); } public function test_transforms_case_style_for_all_keys_in_array_entry(): void { - $row = array_to_row([ - 'arrayEntry' => [ - 'itemId' => 1, - 'itemStatus' => 'PENDING', - 'itemEnabled' => true, - 'itemVariants' => [ - 'variantStatuses' => [ - [ - 'statusId' => 1000, - 'statusName' => 'NEW', - ], - [ - 'statusId' => 2000, - 'statusName' => 'ACTIVE', - ], - ], - 'variantName' => 'Variant Name', - ], - ], - ], schema(structure_schema('arrayEntry', type_structure([ - 'itemId' => type_integer(), - 'itemStatus' => type_string(), - 'itemEnabled' => type_boolean(), - 'itemVariants' => type_structure([ - 'variantStatuses' => type_list(type_structure([ - 'statusId' => type_integer(), - 'statusName' => type_string(), - ])), - 'variantName' => type_string(), - ]), - ])))); - static::assertEquals( [ 'item_id' => 1, @@ -99,7 +71,41 @@ public function test_transforms_case_style_for_all_keys_in_array_entry(): void 'variant_name' => 'Variant Name', ], ], - array_keys_style_convert(ref('arrayEntry'), 'snake')->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + array_keys_style_convert(ref('arrayEntry'), 'snake'), + [ + 'arrayEntry' => [ + 'itemId' => 1, + 'itemStatus' => 'PENDING', + 'itemEnabled' => true, + 'itemVariants' => [ + 'variantStatuses' => [ + [ + 'statusId' => 1000, + 'statusName' => 'NEW', + ], + [ + 'statusId' => 2000, + 'statusName' => 'ACTIVE', + ], + ], + 'variantName' => 'Variant Name', + ], + ], + ], + schema(structure_schema('arrayEntry', type_structure([ + 'itemId' => type_integer(), + 'itemStatus' => type_string(), + 'itemEnabled' => type_boolean(), + 'itemVariants' => type_structure([ + 'variantStatuses' => type_list(type_structure([ + 'statusId' => type_integer(), + 'statusName' => type_string(), + ])), + 'variantName' => type_string(), + ]), + ]))), + ), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysTest.php index 1cee206571..a2e54ebcc2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayKeysTest.php @@ -8,9 +8,9 @@ use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\json_schema; @@ -65,12 +65,14 @@ public function test_array_keys(): void { static::assertSame( ['a', 'b'], - ref('map') - ->arrayKeys() - ->eval(array_to_row(['map' => [ + (new FunctionContext(flow_context()))->eval( + ref('map')->arrayKeys(), + ['map' => [ 'a' => 1, 'b' => 2, - ]], schema(map_schema('map', type_map(type_string(), type_integer())))), flow_context()), + ]], + schema(map_schema('map', type_map(type_string(), type_integer()))), + ), ); } @@ -80,7 +82,7 @@ public function test_array_keys_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('map')->arrayKeys()->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), $context); + (new FunctionContext($context))->eval(ref('map')->arrayKeys(), ['map' => 'test'], schema(str_schema('map'))); } public function test_array_keys_on_non_array(): void @@ -88,6 +90,10 @@ public function test_array_keys_on_non_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('map')->arrayKeys()->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('map')->arrayKeys(), + ['map' => 'test'], + schema(str_schema('map')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeCollectionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeCollectionTest.php index 2587afa983..cb7154f010 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeCollectionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeCollectionTest.php @@ -6,10 +6,10 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_merge_collection; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -31,9 +31,12 @@ public function test_array_merge_collection_in_strict_mode_with_non_array(): voi $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); - array_merge_collection(ref('invalid_entry'))->eval($row, $context); + (new FunctionContext($context))->eval( + array_merge_collection(ref('invalid_entry')), + ['invalid_entry' => 1], + schema(int_schema('invalid_entry')), + ); } public function test_array_merge_collection_in_strict_mode_with_non_array_elements(): void @@ -42,14 +45,17 @@ public function test_array_merge_collection_in_strict_mode_with_non_array_elemen $this->expectExceptionMessage('ArrayMergeCollection function requires array elements to be arrays'); $context = flow_context(config()); - $row = array_to_row([ - 'array_entry' => [ - ['foo' => 'bar'], - 1, - ], - ], schema(json_schema('array_entry'))); - array_merge_collection(ref('array_entry'))->eval($row, $context); + (new FunctionContext($context))->eval( + array_merge_collection(ref('array_entry')), + [ + 'array_entry' => [ + ['foo' => 'bar'], + 1, + ], + ], + schema(json_schema('array_entry')), + ); } public function test_attempt_of_merging_collection_where_not_every_element_is_array(): void @@ -57,14 +63,16 @@ public function test_attempt_of_merging_collection_where_not_every_element_is_ar $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ArrayMergeCollection function requires array elements to be arrays'); - $row = array_to_row([ - 'array_entry' => [ - ['foo' => 'bar'], - 1, + (new FunctionContext(flow_context()))->eval( + array_merge_collection(ref('array_entry')), + [ + 'array_entry' => [ + ['foo' => 'bar'], + 1, + ], ], - ], schema(json_schema('array_entry'))); - - array_merge_collection(ref('array_entry'))->eval($row, flow_context()); + schema(json_schema('array_entry')), + ); } public function test_for_not_array_entry(): void @@ -72,26 +80,33 @@ public function test_for_not_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - $row = array_to_row(['invalid_entry' => 1], schema(int_schema('invalid_entry'))); - - array_merge_collection(ref('invalid_entry'))->eval($row, flow_context()); + (new FunctionContext(flow_context()))->eval( + array_merge_collection(ref('invalid_entry')), + ['invalid_entry' => 1], + schema(int_schema('invalid_entry')), + ); } public function test_merging_collection_of_arrays(): void { - $row = array_to_row([ - 'array_entry' => [ + static::assertEquals( + [1, 2], + (new FunctionContext(flow_context()))->eval( + array_merge_collection(ref('array_entry')), [ - 1, + 'array_entry' => [ + [ + 1, + ], + [ + 2, + ], + [], + ], ], - [ - 2, - ], - [], - ], - ], schema(list_schema('array_entry', type_list(type_list(type_integer()))))); - - static::assertEquals([1, 2], array_merge_collection(ref('array_entry'))->eval($row, flow_context())); + schema(list_schema('array_entry', type_list(type_list(type_integer())))), + ), + ); } public function test_a_list_of_structures_declares_the_structure(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeTest.php index 8940ac05c3..ef762a0f60 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayMergeTest.php @@ -6,9 +6,9 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ArrayMerge; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -28,33 +28,25 @@ public function test_array_merge_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - ref('a') - ->arrayMerge(ref('b')) - ->eval( - array_to_row( - ['a' => 1, 'b' => ['b' => 2]], - schema(int_schema('a'), map_schema('b', type_map(type_string(), type_integer()))), - ), - $context, - ); + (new FunctionContext($context))->eval( + ref('a')->arrayMerge(ref('b')), + ['a' => 1, 'b' => ['b' => 2]], + schema(int_schema('a'), map_schema('b', type_map(type_string(), type_integer()))), + ); } public function test_array_merge_two_array_row_entries(): void { static::assertSame( ['a' => 1, 'b' => 2], - ref('a') - ->arrayMerge(ref('b')) - ->eval( - array_to_row( - ['a' => ['a' => 1], 'b' => ['b' => 2]], - schema( - map_schema('a', type_map(type_string(), type_integer())), - map_schema('b', type_map(type_string(), type_integer())), - ), - ), - flow_context(), + (new FunctionContext(flow_context()))->eval( + ref('a')->arrayMerge(ref('b')), + ['a' => ['a' => 1], 'b' => ['b' => 2]], + schema( + map_schema('a', type_map(type_string(), type_integer())), + map_schema('b', type_map(type_string(), type_integer())), ), + ), ); } @@ -62,7 +54,7 @@ public function test_array_merge_two_lit_functions(): void { $function = new ArrayMerge(lit(['a' => 1]), lit(['b' => 2])); - static::assertSame(['a' => 1, 'b' => 2], $function->eval(array_to_row([], schema()), flow_context())); + static::assertSame(['a' => 1, 'b' => 2], (new FunctionContext(flow_context()))->eval($function, [], schema())); } public function test_array_merge_when_left_side_is_not_an_array(): void @@ -70,15 +62,11 @@ public function test_array_merge_when_left_side_is_not_an_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - ref('a') - ->arrayMerge(ref('b')) - ->eval( - array_to_row( - ['a' => 1, 'b' => ['b' => 2]], - schema(int_schema('a'), map_schema('b', type_map(type_string(), type_integer()))), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('a')->arrayMerge(ref('b')), + ['a' => 1, 'b' => ['b' => 2]], + schema(int_schema('a'), map_schema('b', type_map(type_string(), type_integer()))), + ); } public function test_array_merge_when_right_side_is_not_an_array(): void @@ -86,14 +74,10 @@ public function test_array_merge_when_right_side_is_not_an_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - ref('a') - ->arrayMerge(ref('b')) - ->eval( - array_to_row( - ['a' => ['a' => 1], 'b' => 2], - schema(map_schema('a', type_map(type_string(), type_integer())), int_schema('b')), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('a')->arrayMerge(ref('b')), + ['a' => ['a' => 1], 'b' => 2], + schema(map_schema('a', type_map(type_string(), type_integer())), int_schema('b')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayReverseTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayReverseTest.php index 0dcbf1f38c..303e1ba232 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayReverseTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayReverseTest.php @@ -6,9 +6,9 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -28,14 +28,16 @@ public function test_array_reverse_array_entry(): void { static::assertSame( [5, 3, 10, 4], - ref('a') - ->arrayReverse() - ->eval(array_to_row(['a' => [ + (new FunctionContext(flow_context()))->eval( + ref('a')->arrayReverse(), + ['a' => [ 4, 10, 3, 5, - ]], schema(list_schema('a', type_list(type_integer())))), flow_context()), + ]], + schema(list_schema('a', type_list(type_integer()))), + ), ); } @@ -45,7 +47,7 @@ public function test_array_reverse_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "integer".'); $context = flow_context(config()); - ref('a')->arrayReverse()->eval(array_to_row(['a' => 123], schema(int_schema('a'))), $context); + (new FunctionContext($context))->eval(ref('a')->arrayReverse(), ['a' => 123], schema(int_schema('a'))); } public function test_array_reverse_non_array_entry(): void @@ -53,7 +55,7 @@ public function test_array_reverse_non_array_entry(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "integer".'); - ref('a')->arrayReverse()->eval(array_to_row(['a' => 123], schema(int_schema('a'))), flow_context()); + (new FunctionContext(flow_context()))->eval(ref('a')->arrayReverse(), ['a' => 123], schema(int_schema('a'))); } public function test_a_structure_operand_declares_reversed_fields(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArraySortTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArraySortTest.php index 2d2b0f9c58..94fbea451f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArraySortTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArraySortTest.php @@ -7,9 +7,12 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ArraySort\Sort; use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; +use Flow\Types\Value\Json; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\json_schema; @@ -19,6 +22,7 @@ use function Flow\ETL\DSL\structure_schema; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_array; +use function Flow\Types\DSL\type_instance_of; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_structure; use function json_decode; @@ -31,33 +35,138 @@ public function test_array_sort_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('array')->arraySort()->eval(array_to_row(['array' => 'string'], schema(str_schema('array'))), $context); + (new FunctionContext($context))->eval( + ref('array')->arraySort(), + ['array' => 'string'], + schema(str_schema('array')), + ); } - public function test_sorting_big_arrays(): void + public static function one_document_in_two_orders(): Generator + { + yield 'as stored' => [<<<'JSON' + [ + { + "asin": "B00PHQB8EE", + "images": [ + { + "images": [ + { + "link": "https://m.media-amazon.com/images/I/419NipwmTaL.jpg", + "width": 190, + "height": 500, + "variant": "MAIN" + }, + { + "link": "https://m.media-amazon.com/images/I/419NipwmTaL._SL75_.jpg", + "width": 29, + "height": 75, + "variant": "MAIN" + }, + { + "link": "https://m.media-amazon.com/images/I/61AQupUe5pL.jpg", + "width": 418, + "height": 1100, + "variant": "MAIN" + }, + { + "link": "https://m.media-amazon.com/images/I/51XvsWDOBuS.jpg", + "width": 500, + "height": 279, + "variant": "PT01" + }, + { + "link": "https://m.media-amazon.com/images/I/51XvsWDOBuS._SL75_.jpg", + "width": 75, + "height": 42, + "variant": "PT01" + } + ], + "marketplaceId": "ATVPDKIKX0DER" + } + ], + "synchronized_at": "2023-04-21 11:33:25" + } + ] + JSON]; + yield 'reordered' => [<<<'JSON' + [ + { + "asin": "B00PHQB8EE", + "images": [ + { + "images": [ + { + "link": "https://m.media-amazon.com/images/I/51XvsWDOBuS._SL75_.jpg", + "width": 75, + "height": 42, + "variant": "PT01" + }, + { + "link": "https://m.media-amazon.com/images/I/419NipwmTaL.jpg", + "width": 190, + "height": 500, + "variant": "MAIN" + }, + { + "link": "https://m.media-amazon.com/images/I/61AQupUe5pL.jpg", + "width": 418, + "height": 1100, + "variant": "MAIN" + }, + { + "link": "https://m.media-amazon.com/images/I/419NipwmTaL._SL75_.jpg", + "width": 29, + "height": 75, + "variant": "MAIN" + }, + { + "link": "https://m.media-amazon.com/images/I/51XvsWDOBuS.jpg", + "width": 500, + "height": 279, + "variant": "PT01" + } + ], + "marketplaceId": "ATVPDKIKX0DER" + } + ], + "synchronized_at": "2023-04-21 11:33:25" + } + ] + JSON]; + } + + #[DataProvider('one_document_in_two_orders')] + public function test_sorting_big_arrays(string $json): void { static::assertSame( - ref('array') - ->arraySort() - ->eval(array_to_row(['array' => type_array()->assert(json_decode( - $this->jsonDifferentOrder(), - true, - 512, - JSON_THROW_ON_ERROR, - ))], schema(json_schema('array'))), flow_context()), - ref('array') - ->arraySort() - ->eval(array_to_row(['array' => type_array()->assert(json_decode( - $this->json(), - true, - 512, - JSON_THROW_ON_ERROR, - ))], schema(json_schema('array'))), flow_context()), + [[ + '2023-04-21 11:33:25', + 'B00PHQB8EE', + [[ + 'ATVPDKIKX0DER', + [ + [29, 75, 'MAIN', 'https://m.media-amazon.com/images/I/419NipwmTaL._SL75_.jpg'], + [42, 75, 'PT01', 'https://m.media-amazon.com/images/I/51XvsWDOBuS._SL75_.jpg'], + [190, 500, 'MAIN', 'https://m.media-amazon.com/images/I/419NipwmTaL.jpg'], + [279, 500, 'PT01', 'https://m.media-amazon.com/images/I/51XvsWDOBuS.jpg'], + [418, 1100, 'MAIN', 'https://m.media-amazon.com/images/I/61AQupUe5pL.jpg'], + ], + ]], + ]], + type_instance_of(Json::class) + ->assert((new FunctionContext(flow_context()))->eval( + ref('array')->arraySort(), + ['array' => type_array()->assert(json_decode($json, true, 512, JSON_THROW_ON_ERROR))], + schema(json_schema('array')), + )) + ->toArray(), ); } public function test_sorting_nested_array_using_asort_algo(): void { + // a json operand gives a json column: the sorted array is read back from it static::assertSame( [ 'a' => [ @@ -68,24 +177,29 @@ public function test_sorting_nested_array_using_asort_algo(): void ], ], ], - ref('array') - ->arraySort(Sort::asort) - ->eval(array_to_row([ - 'array' => [ - 'a' => [ - 'b' => [ - 'e' => 'f', - 'c' => 'd', + type_instance_of(Json::class) + ->assert((new FunctionContext(flow_context()))->eval( + ref('array')->arraySort(Sort::asort), + [ + 'array' => [ + 'a' => [ + 'b' => [ + 'e' => 'f', + 'c' => 'd', + ], + 'g' => 'h', ], - 'g' => 'h', ], ], - ], schema(json_schema('array'))), flow_context()), + schema(json_schema('array')), + )) + ->toArray(), ); } public function test_sorting_nested_associative_array(): void { + // a json operand gives a json column: the sorted array is read back from it static::assertSame( [ 'a' => [ @@ -96,19 +210,23 @@ public function test_sorting_nested_associative_array(): void 'g' => 'h', ], ], - ref('array') - ->arraySort(Sort::ksort) - ->eval(array_to_row([ - 'array' => [ - 'a' => [ - 'g' => 'h', - 'b' => [ - 'e' => 'f', - 'c' => 'd', + type_instance_of(Json::class) + ->assert((new FunctionContext(flow_context()))->eval( + ref('array')->arraySort(Sort::ksort), + [ + 'array' => [ + 'a' => [ + 'g' => 'h', + 'b' => [ + 'e' => 'f', + 'c' => 'd', + ], ], ], ], - ], schema(json_schema('array'))), flow_context()), + schema(json_schema('array')), + )) + ->toArray(), ); } @@ -117,107 +235,11 @@ public function test_sorting_non_array_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('array') - ->arraySort() - ->eval(array_to_row(['array' => 'string'], schema(str_schema('array'))), flow_context()); - } - - private function json(): string - { - return <<<'JSON' - [ - { - "asin": "B00PHQB8EE", - "images": [ - { - "images": [ - { - "link": "https://m.media-amazon.com/images/I/419NipwmTaL.jpg", - "width": 190, - "height": 500, - "variant": "MAIN" - }, - { - "link": "https://m.media-amazon.com/images/I/419NipwmTaL._SL75_.jpg", - "width": 29, - "height": 75, - "variant": "MAIN" - }, - { - "link": "https://m.media-amazon.com/images/I/61AQupUe5pL.jpg", - "width": 418, - "height": 1100, - "variant": "MAIN" - }, - { - "link": "https://m.media-amazon.com/images/I/51XvsWDOBuS.jpg", - "width": 500, - "height": 279, - "variant": "PT01" - }, - { - "link": "https://m.media-amazon.com/images/I/51XvsWDOBuS._SL75_.jpg", - "width": 75, - "height": 42, - "variant": "PT01" - } - ], - "marketplaceId": "ATVPDKIKX0DER" - } - ], - "synchronized_at": "2023-04-21 11:33:25" - } - ] - JSON; - } - - private function jsonDifferentOrder(): string - { - return <<<'JSON' - [ - { - "asin": "B00PHQB8EE", - "images": [ - { - "images": [ - { - "link": "https://m.media-amazon.com/images/I/51XvsWDOBuS._SL75_.jpg", - "width": 75, - "height": 42, - "variant": "PT01" - }, - { - "link": "https://m.media-amazon.com/images/I/419NipwmTaL.jpg", - "width": 190, - "height": 500, - "variant": "MAIN" - }, - { - "link": "https://m.media-amazon.com/images/I/61AQupUe5pL.jpg", - "width": 418, - "height": 1100, - "variant": "MAIN" - }, - { - "link": "https://m.media-amazon.com/images/I/419NipwmTaL._SL75_.jpg", - "width": 29, - "height": 75, - "variant": "MAIN" - }, - { - "link": "https://m.media-amazon.com/images/I/51XvsWDOBuS.jpg", - "width": 500, - "height": 279, - "variant": "PT01" - } - ], - "marketplaceId": "ATVPDKIKX0DER" - } - ], - "synchronized_at": "2023-04-21 11:33:25" - } - ] - JSON; + (new FunctionContext(flow_context()))->eval( + ref('array')->arraySort(), + ['array' => 'string'], + schema(str_schema('array')), + ); } public function test_ksort_declares_key_sorted_structure_fields(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayUnpackTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayUnpackTest.php index 44910e4583..12fa101270 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayUnpackTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayUnpackTest.php @@ -6,9 +6,9 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ArrayUnpack; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; @@ -29,32 +29,30 @@ final class ArrayUnpackTest extends FlowTestCase { public function test_array_unpack(): void { + // the StructureType column returns() declares: the undeclared "array" field is not unpacked static::assertSame( [ 'status' => 'PENDING', 'enabled' => true, - 'array' => ['foo' => 'bar'], ], - (new ArrayUnpack(ref('array_entry'), schema(str_schema('status'), bool_schema('enabled'))))->eval( - array_to_row( - [ - 'id' => 1, - 'array_entry' => [ - 'status' => 'PENDING', - 'enabled' => true, - 'array' => ['foo' => 'bar'], - ], + (new FunctionContext(flow_context()))->eval( + new ArrayUnpack(ref('array_entry'), schema(str_schema('status'), bool_schema('enabled'))), + [ + 'id' => 1, + 'array_entry' => [ + 'status' => 'PENDING', + 'enabled' => true, + 'array' => ['foo' => 'bar'], ], - schema( - int_schema('id'), - structure_schema('array_entry', type_structure([ - 'status' => type_string(), - 'enabled' => type_boolean(), - 'array' => type_structure(['foo' => type_string()]), - ])), - ), + ], + schema( + int_schema('id'), + structure_schema('array_entry', type_structure([ + 'status' => type_string(), + 'enabled' => type_boolean(), + 'array' => type_structure(['foo' => type_string()]), + ])), ), - flow_context(), ), ); } @@ -64,15 +62,13 @@ public function test_array_unpack_with_null_in_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('array_unpack() requires a non-null array'); - (new ArrayUnpack(ref('array_entry'), schema(str_schema('status'))))->eval( - array_to_row( - [ - 'id' => 1, - 'array_entry' => null, - ], - schema(int_schema('id'), str_schema('array_entry', nullable: true)), - ), - flow_context(config()), + (new FunctionContext(flow_context(config())))->eval( + new ArrayUnpack(ref('array_entry'), schema(str_schema('status'))), + [ + 'id' => 1, + 'array_entry' => null, + ], + schema(int_schema('id'), str_schema('array_entry', nullable: true)), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayValuesTest.php index 8386a40915..3ef7bbb8cb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ArrayValuesTest.php @@ -7,9 +7,9 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\map_schema; @@ -30,12 +30,14 @@ public function test_array_values(): void { static::assertSame( [1, 2], - ref('map') - ->arrayValues() - ->eval(array_to_row(['map' => [ + (new FunctionContext(flow_context()))->eval( + ref('map')->arrayValues(), + ['map' => [ 'a' => 1, 'b' => 2, - ]], schema(map_schema('map', type_map(type_string(), type_integer())))), flow_context()), + ]], + schema(map_schema('map', type_map(type_string(), type_integer()))), + ), ); } @@ -45,7 +47,7 @@ public function test_array_values_in_strict_mode(): void $this->expectExceptionMessage('Expected type "array", got "string".'); $context = flow_context(config()); - ref('map')->arrayValues()->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), $context); + (new FunctionContext($context))->eval(ref('map')->arrayValues(), ['map' => 'test'], schema(str_schema('map'))); } public function test_array_values_on_non_array(): void @@ -53,7 +55,11 @@ public function test_array_values_on_non_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - ref('map')->arrayValues()->eval(array_to_row(['map' => 'test'], schema(str_schema('map'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('map')->arrayValues(), + ['map' => 'test'], + schema(str_schema('map')), + ); } public function test_a_structure_operand_declares_the_unified_field_type(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AsciiTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AsciiTest.php index 221087a214..0278246f14 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AsciiTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AsciiTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,9 +17,11 @@ final class AsciiTest extends FlowTestCase { public function test_ascii(): void { - static::assertSame('azcz', ref('str') - ->ascii() - ->eval(array_to_row(['str' => 'ąźćż'], schema(str_schema('str'))), flow_context())); + static::assertSame('azcz', (new FunctionContext(flow_context()))->eval( + ref('str')->ascii(), + ['str' => 'ąźćż'], + schema(str_schema('str')), + )); } public function test_ascii_on_null(): void @@ -27,8 +29,10 @@ public function test_ascii_on_null(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Ascii function requires non-null value'); - ref('str') - ->ascii() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->ascii(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AverageTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AverageTest.php index 2ce16fb56a..ca5f2f02ae 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AverageTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AverageTest.php @@ -7,17 +7,22 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; +use PHPUnit\Framework\Attributes\TestWith; -use function Flow\ETL\DSL\array_to_row; +use function array_fill; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\sum; use function Flow\ETL\DSL\window; +use function range; final class AverageTest extends FlowTestCase { @@ -30,13 +35,17 @@ public function test_aggregation_average_from_numeric_values(): void { $aggregator = average(ref('int')); - $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '30'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'not_int' => null, - ], schema(str_schema('not_int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '10']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '20']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '30']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '25']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'not_int' => null, + ]], schema(str_schema('not_int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(21.25, $aggregator->value()); } @@ -45,12 +54,16 @@ public function test_aggregation_average_including_null_value(): void { $aggregator = average(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'int' => null, - ], schema(int_schema('int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'int' => null, + ]], schema(int_schema('int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(20.0, $aggregator->value()); } @@ -59,10 +72,10 @@ public function test_aggregation_average_with_float_result(): void { $aggregator = average(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 25]], schema(int_schema('int'))), [0], flow_context()); static::assertSame(21.25, $aggregator->value()); } @@ -71,10 +84,10 @@ public function test_aggregation_average_with_integer_result(): void { $aggregator = average(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 40], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 40]], schema(int_schema('int'))), [0], flow_context()); static::assertSame(25.0, $aggregator->value()); } @@ -88,18 +101,20 @@ public function test_aggregation_average_of_nothing_is_null(): void public function test_window_function_average_on_partitioned_rows(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'value' => 1], + ['id' => 2, 'value' => 100], + ['id' => 3, 'value' => 25], + ['id' => 4, 'value' => 64], + ['id' => 5, 'value' => 23], + ], schema(int_schema('id'), int_schema('value')), - $row1 = array_to_row(['id' => 1, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 2, 'value' => 100], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 3, 'value' => 25], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 4, 'value' => 64], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 5, 'value' => 23], schema(int_schema('id'), int_schema('value'))), ); $avg = average(ref('value'))->over(window()->orderBy(ref('value'))); - static::assertSame(42.6, $avg->apply(WindowContextMother::forRow($row1, $rows))); + static::assertSame(42.6, $avg->apply(WindowContextMother::atIndex($rows, 0))); } public function test_window_function_average_with_missing_reference_in_strict_mode(): void @@ -107,16 +122,12 @@ public function test_window_function_average_with_missing_reference_in_strict_mo $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Average window function error:'); - $rows = rows( - schema(int_schema('id')), - $row1 = array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - ); + $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $avg = average(ref('missing_column'))->over(window()->orderBy(ref('id'))); $context = flow_context(config()); - $avg->apply(WindowContextMother::forRow($row1, $rows, context: $context)); + $avg->apply(WindowContextMother::atIndex($rows, 0, context: $context)); } public function test_with_children_rebuilds_the_aggregate_with_the_given_reference(): void @@ -130,4 +141,74 @@ public function test_with_children_rebuilds_the_aggregate_with_the_given_referen static::assertNotSame($aggregate, $rebuilt); static::assertEquals([ref('b')], $rebuilt->references()); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = average(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 0.5, + 1.25, + 2.0, + 3.0, + ]), schema(float_schema('v'))), + [0, 2], + flow_context(), + ); + + static::assertSame(1.25, $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 0.5, + 1.25, + 2.0, + 3.0, + ]), schema(float_schema('v'))); + $onePass = average(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = average(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = average(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + average(ref('v'))->merge(sum(ref('v')), flow_context()); + } + + #[TestWith([false])] + #[TestWith([true])] + public function test_ten_tenths_average_to_a_tenth(bool $exact): void + { + $aggregator = average(ref('v'), 17, exact: $exact); + $aggregator->aggregate(array_to_rows(array_fill(0, 10, [ + 'v' => 0.1, + ]), schema(float_schema('v'))), range(0, 9), flow_context()); + + // naive IEEE summation would give 0.09999999999999999 + static::assertSame(0.1, $aggregator->value()); + } + + public function test_merged_partial_averages_keep_their_compensation(): void + { + $left = average(ref('v'), 17); + $right = average(ref('v'), 17); + $rows = array_to_rows(array_fill(0, 5, ['v' => 0.1]), schema(float_schema('v'))); + $left->aggregate($rows, range(0, 4), flow_context()); + $right->aggregate($rows, range(0, 4), flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame(0.1, $left->value()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BetweenTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BetweenTest.php index 2ee76fd186..3bbcb9b6de 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BetweenTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BetweenTest.php @@ -6,9 +6,9 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\Between\Boundary; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\between; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -20,72 +20,120 @@ final class BetweenTest extends FlowTestCase { public function test_a_definite_false_short_circuits_past_a_null(): void { - static::assertFalse( - ref('value') - ->between(lit(10), lit(null)) - ->eval(array_to_row(['value' => 5], schema(int_schema('value'))), flow_context()), - ); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('value')->between(lit(10), lit(null)), + ['value' => 5], + schema(int_schema('value')), + )); } public function test_a_null_bound_that_could_change_the_answer_is_null(): void { - static::assertNull( - ref('value') - ->between(lit(10), lit(null)) - ->eval(array_to_row(['value' => 50], schema(int_schema('value'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->between(lit(10), lit(null)), + ['value' => 50], + schema(int_schema('value')), + )); } public function test_between_exclusive(): void { - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(array_to_row([ - 'value' => 11, - ], schema(int_schema('value'))), flow_context())); - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(array_to_row([ - 'value' => 49, - ], schema(int_schema('value'))), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(array_to_row([ - 'value' => 10, - ], schema(int_schema('value'))), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE)->eval(array_to_row([ - 'value' => 50, - ], schema(int_schema('value'))), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE), + [ + 'value' => 11, + ], + schema(int_schema('value')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE), + [ + 'value' => 49, + ], + schema(int_schema('value')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE), + [ + 'value' => 10, + ], + schema(int_schema('value')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::EXCLUSIVE), + [ + 'value' => 50, + ], + schema(int_schema('value')), + )); } public function test_between_inclusive(): void { - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(array_to_row([ - 'value' => 10, - ], schema(int_schema('value'))), flow_context())); - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(array_to_row([ - 'value' => 50, - ], schema(int_schema('value'))), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(array_to_row([ - 'value' => 9, - ], schema(int_schema('value'))), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE)->eval(array_to_row([ - 'value' => 51, - ], schema(int_schema('value'))), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE), + [ + 'value' => 10, + ], + schema(int_schema('value')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE), + [ + 'value' => 50, + ], + schema(int_schema('value')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE), + [ + 'value' => 9, + ], + schema(int_schema('value')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::INCLUSIVE), + [ + 'value' => 51, + ], + schema(int_schema('value')), + )); } public function test_between_left_inclusive(): void { - static::assertTrue(between(ref('value'), lit(10), lit(50))->eval(array_to_row([ - 'value' => 10, - ], schema(int_schema('value'))), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50))->eval(array_to_row([ - 'value' => 9, - ], schema(int_schema('value'))), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50)), + [ + 'value' => 10, + ], + schema(int_schema('value')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50)), + [ + 'value' => 9, + ], + schema(int_schema('value')), + )); } public function test_between_right_inclusive(): void { - static::assertTrue(between(ref('value'), lit(10), lit(50), Boundary::RIGHT_INCLUSIVE)->eval(array_to_row([ - 'value' => 50, - ], schema(int_schema('value'))), flow_context())); - static::assertFalse(between(ref('value'), lit(10), lit(50), Boundary::RIGHT_INCLUSIVE)->eval(array_to_row([ - 'value' => 51, - ], schema(int_schema('value'))), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::RIGHT_INCLUSIVE), + [ + 'value' => 50, + ], + schema(int_schema('value')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + between(ref('value'), lit(10), lit(50), Boundary::RIGHT_INCLUSIVE), + [ + 'value' => 51, + ], + schema(int_schema('value')), + )); } public function test_between_with_invalid_boundary_in_strict_mode(): void @@ -94,8 +142,12 @@ public function test_between_with_invalid_boundary_in_strict_mode(): void $this->expectExceptionMessage('Expected type "object", got "string".'); $context = flow_context(); - between(ref('value'), lit(10), lit(50), lit('invalid'))->eval(array_to_row([ - 'value' => 20, - ], schema(int_schema('value'))), $context); + (new FunctionContext($context))->eval( + between(ref('value'), lit(10), lit(50), lit('invalid')), + [ + 'value' => 20, + ], + schema(int_schema('value')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryComparisonsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryComparisonsTest.php index 4454781cd5..0552afe5d8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryComparisonsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryComparisonsTest.php @@ -22,9 +22,9 @@ use Flow\ETL\Function\NotSame; use Flow\ETL\Function\Same; use Flow\ETL\Function\StartsWith; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -42,7 +42,8 @@ final class BinaryComparisonsTest extends FlowTestCase { public function test_equals(): void { - $row = array_to_row( + static::assertTrue((new FunctionContext(flow_context()))->eval( + new Equals(ref('a'), ref('b')), [ 'a' => 100, 'b' => 100, @@ -51,16 +52,35 @@ public function test_equals(): void 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), ], schema(int_schema('a'), int_schema('b'), int_schema('c'), datetime_schema('d'), datetime_schema('e')), - ); - - static::assertTrue((new Equals(ref('a'), ref('b')))->eval($row, flow_context())); - static::assertTrue((new Equals(ref('d'), ref('e')))->eval($row, flow_context())); - static::assertFalse((new Equals(ref('a'), ref('c')))->eval($row, flow_context())); + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new Equals(ref('d'), ref('e')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + ], + schema(int_schema('a'), int_schema('b'), int_schema('c'), datetime_schema('d'), datetime_schema('e')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new Equals(ref('a'), ref('c')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + ], + schema(int_schema('a'), int_schema('b'), int_schema('c'), datetime_schema('d'), datetime_schema('e')), + )); } public function test_greater_than(): void { - $row = array_to_row( + static::assertTrue((new FunctionContext(flow_context()))->eval( + new GreaterThan(ref('a'), ref('c')), [ 'a' => 100, 'b' => 100, @@ -77,46 +97,261 @@ public function test_greater_than(): void datetime_schema('e'), str_schema('f', nullable: true), ), - ); - - static::assertTrue((new GreaterThan(ref('a'), ref('c')))->eval($row, flow_context())); - static::assertNull((new GreaterThan(ref('a'), ref('f')))->eval($row, flow_context())); - static::assertNull((new GreaterThan(ref('f'), ref('c')))->eval($row, flow_context())); - static::assertNull((new GreaterThan(ref('f'), ref('f')))->eval($row, flow_context())); - static::assertFalse((new GreaterThan(ref('a'), ref('b')))->eval($row, flow_context())); - static::assertTrue((new GreaterThanEqual(ref('a'), ref('c')))->eval($row, flow_context())); - static::assertTrue((new GreaterThanEqual(ref('a'), ref('b')))->eval($row, flow_context())); - static::assertTrue((new GreaterThanEqual(ref('e'), ref('d')))->eval($row, flow_context())); - static::assertTrue((new GreaterThanEqual( - ref('e'), - lit(new DateTimeImmutable('2022-01-01 00:00:00 UTC')), - ))->eval($row, flow_context())); - static::assertFalse((new GreaterThanEqual( - ref('e'), - lit(new DateTimeImmutable('2024-01-01 00:00:00 UTC')), - ))->eval($row, flow_context())); - static::assertNull((new GreaterThanEqual(ref('a'), ref('f')))->eval($row, flow_context())); - static::assertNull((new GreaterThanEqual(ref('f'), ref('c')))->eval($row, flow_context())); - static::assertNull((new GreaterThanEqual(ref('f'), ref('f')))->eval($row, flow_context())); + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new GreaterThan(ref('a'), ref('f')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new GreaterThan(ref('f'), ref('c')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new GreaterThan(ref('f'), ref('f')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new GreaterThan(ref('a'), ref('b')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new GreaterThanEqual(ref('a'), ref('c')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new GreaterThanEqual(ref('a'), ref('b')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new GreaterThanEqual(ref('e'), ref('d')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new GreaterThanEqual(ref('e'), lit(new DateTimeImmutable('2022-01-01 00:00:00 UTC'))), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new GreaterThanEqual(ref('e'), lit(new DateTimeImmutable('2024-01-01 00:00:00 UTC'))), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new GreaterThanEqual(ref('a'), ref('f')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new GreaterThanEqual(ref('f'), ref('c')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new GreaterThanEqual(ref('f'), ref('f')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-02 00:00:00 UTC'), + 'f' => null, + ], + schema( + int_schema('a'), + int_schema('b'), + int_schema('c'), + datetime_schema('d'), + datetime_schema('e'), + str_schema('f', nullable: true), + ), + )); } public function test_greater_than_equal_with_null_in_strict_mode(): void { $context = flow_context(); - $row = array_to_row(['a' => 100, 'f' => null], schema(int_schema('a'), str_schema('f', nullable: true))); - static::assertNull((new GreaterThanEqual(ref('a'), ref('f')))->eval($row, $context)); + static::assertNull((new FunctionContext($context))->eval( + new GreaterThanEqual(ref('a'), ref('f')), + ['a' => 100, 'f' => null], + schema(int_schema('a'), str_schema('f', nullable: true)), + )); } public function test_greater_than_with_null_in_strict_mode(): void { $context = flow_context(); - $row = array_to_row(['a' => 100, 'f' => null], schema(int_schema('a'), str_schema('f', nullable: true))); - static::assertNull((new GreaterThan(ref('a'), ref('f')))->eval($row, $context)); + static::assertNull((new FunctionContext($context))->eval( + new GreaterThan(ref('a'), ref('f')), + ['a' => 100, 'f' => null], + schema(int_schema('a'), str_schema('f', nullable: true)), + )); } public function test_is_in(): void { - $row = array_to_row( + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsIn(ref('a'), lit(1)), [ 'a' => [1, 2, 3, 4, 5], 'b' => ['a', 'b', 'c'], @@ -131,119 +366,269 @@ public function test_is_in(): void int_schema('d'), str_schema('e'), ), - ); - - static::assertTrue((new IsIn(ref('a'), lit(1)))->eval($row, flow_context())); - static::assertFalse((new IsIn(ref('a'), lit(10)))->eval($row, flow_context())); - static::assertTrue((new IsIn(ref('a'), ref('d')))->eval($row, flow_context())); - static::assertTrue((new IsIn(ref('b'), ref('e')))->eval($row, flow_context())); + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new IsIn(ref('a'), lit(10)), + [ + 'a' => [1, 2, 3, 4, 5], + 'b' => ['a', 'b', 'c'], + 'c' => 'another', + 'd' => 4, + 'e' => 'b', + ], + schema( + list_schema('a', type_list(type_integer())), + list_schema('b', type_list(type_string())), + str_schema('c'), + int_schema('d'), + str_schema('e'), + ), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsIn(ref('a'), ref('d')), + [ + 'a' => [1, 2, 3, 4, 5], + 'b' => ['a', 'b', 'c'], + 'c' => 'another', + 'd' => 4, + 'e' => 'b', + ], + schema( + list_schema('a', type_list(type_integer())), + list_schema('b', type_list(type_string())), + str_schema('c'), + int_schema('d'), + str_schema('e'), + ), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsIn(ref('b'), ref('e')), + [ + 'a' => [1, 2, 3, 4, 5], + 'b' => ['a', 'b', 'c'], + 'c' => 'another', + 'd' => 4, + 'e' => 'b', + ], + schema( + list_schema('a', type_list(type_integer())), + list_schema('b', type_list(type_string())), + str_schema('c'), + int_schema('d'), + str_schema('e'), + ), + )); } public function test_is_in_with_null_array_in_strict_mode(): void { $context = flow_context(); - $row = array_to_row(['a' => null, 'd' => 1], schema(str_schema('a', nullable: true), int_schema('d'))); - static::assertNull((new IsIn(ref('a'), ref('d')))->eval($row, $context)); + static::assertNull((new FunctionContext($context))->eval( + new IsIn(ref('a'), ref('d')), + ['a' => null, 'd' => 1], + schema(str_schema('a', nullable: true), int_schema('d')), + )); } public function test_is_numeric(): void { - $row = array_to_row(['a' => 100, 'b' => null], schema(int_schema('a'), str_schema('b', nullable: true))); - static::assertTrue((new IsNumeric(ref('a')))->eval($row, flow_context())); - static::assertNull((new IsNumeric(ref('b')))->eval($row, flow_context())); - static::assertFalse((new IsNotNumeric(ref('a')))->eval($row, flow_context())); - static::assertNull((new IsNotNumeric(ref('b')))->eval($row, flow_context())); - static::assertNull((new IsNotNumeric(lit(null)))->eval($row, flow_context())); - static::assertTrue((new IsNumeric(lit(1000)))->eval($row, flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsNumeric(ref('a')), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new IsNumeric(ref('b')), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new IsNotNumeric(ref('a')), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new IsNotNumeric(ref('b')), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new IsNotNumeric(lit(null)), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsNumeric(lit(1000)), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); } public function test_is_type(): void { - $row = array_to_row(['a' => 100, 'b' => null], schema(int_schema('a'), str_schema('b', nullable: true))); - - static::assertTrue((new IsType(ref('a'), 'integer', 'string'))->eval($row, flow_context())); - static::assertFalse((new IsType(ref('a'), type_string()))->eval($row, flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsType(ref('a'), 'integer', 'string'), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new IsType(ref('a'), type_string()), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); } public function test_is_type_with_non_existing_type_class(): void { $this->expectExceptionMessage('Unknown type \'aaa\''); - $row = array_to_row(['a' => 100, 'b' => null], schema(int_schema('a'), str_schema('b', nullable: true))); - - static::assertFalse((new IsType(ref('a'), 'aaa'))->eval($row, flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new IsType(ref('a'), 'aaa'), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); } public function test_less_than(): void { - $row = array_to_row( + static::assertFalse((new FunctionContext(flow_context()))->eval( + new LessThan(ref('a'), ref('c')), ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), - ); - - static::assertFalse((new LessThan(ref('a'), ref('c')))->eval($row, flow_context())); - static::assertNull((new LessThan(ref('a'), ref('d')))->eval($row, flow_context())); - static::assertNull((new LessThan(ref('d'), ref('d')))->eval($row, flow_context())); - static::assertNull((new LessThan(ref('d'), ref('c')))->eval($row, flow_context())); - static::assertFalse((new LessThan(ref('a'), ref('b')))->eval($row, flow_context())); - static::assertTrue((new LessThanEqual(ref('c'), ref('a')))->eval($row, flow_context())); - static::assertTrue((new LessThanEqual(ref('a'), ref('b')))->eval($row, flow_context())); - static::assertNull((new LessThanEqual(ref('a'), ref('d')))->eval($row, flow_context())); - static::assertNull((new LessThanEqual(ref('d'), ref('c')))->eval($row, flow_context())); - static::assertNull((new LessThanEqual(ref('d'), ref('d')))->eval($row, flow_context())); + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new LessThan(ref('a'), ref('d')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new LessThan(ref('d'), ref('d')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new LessThan(ref('d'), ref('c')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new LessThan(ref('a'), ref('b')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new LessThanEqual(ref('c'), ref('a')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new LessThanEqual(ref('a'), ref('b')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new LessThanEqual(ref('a'), ref('d')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new LessThanEqual(ref('d'), ref('c')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + new LessThanEqual(ref('d'), ref('d')), + ['a' => 100, 'b' => 100, 'c' => 10, 'd' => null], + schema(int_schema('a'), int_schema('b'), int_schema('c'), str_schema('d', nullable: true)), + )); } public function test_less_than_equal_with_null_in_strict_mode(): void { $context = flow_context(); - $row = array_to_row(['a' => 100, 'd' => null], schema(int_schema('a'), str_schema('d', nullable: true))); - static::assertNull((new LessThanEqual(ref('a'), ref('d')))->eval($row, $context)); + static::assertNull((new FunctionContext($context))->eval( + new LessThanEqual(ref('a'), ref('d')), + ['a' => 100, 'd' => null], + schema(int_schema('a'), str_schema('d', nullable: true)), + )); } public function test_less_than_with_null_in_strict_mode(): void { $context = flow_context(); - $row = array_to_row(['a' => 100, 'd' => null], schema(int_schema('a'), str_schema('d', nullable: true))); - static::assertNull((new LessThan(ref('a'), ref('d')))->eval($row, $context)); + static::assertNull((new FunctionContext($context))->eval( + new LessThan(ref('a'), ref('d')), + ['a' => 100, 'd' => null], + schema(int_schema('a'), str_schema('d', nullable: true)), + )); } public function test_not_equals(): void { - $row = array_to_row( + static::assertFalse((new FunctionContext(flow_context()))->eval( + new NotEquals(ref('a'), ref('b')), ['a' => 100, 'b' => 100, 'c' => 10], schema(int_schema('a'), int_schema('b'), int_schema('c')), - ); - - static::assertFalse((new NotEquals(ref('a'), ref('b')))->eval($row, flow_context())); - static::assertTrue((new NotEquals(ref('a'), ref('c')))->eval($row, flow_context())); + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new NotEquals(ref('a'), ref('c')), + ['a' => 100, 'b' => 100, 'c' => 10], + schema(int_schema('a'), int_schema('b'), int_schema('c')), + )); } public function test_not_same(): void { - $row = array_to_row( + static::assertTrue((new FunctionContext(flow_context()))->eval( + new NotSame(ref('a'), ref('c')), ['a' => 100, 'b' => 100, 'c' => 10], schema(int_schema('a'), int_schema('b'), int_schema('c')), - ); - - static::assertTrue((new NotSame(ref('a'), ref('c')))->eval($row, flow_context())); - static::assertFalse((new NotSame(ref('a'), ref('b')))->eval($row, flow_context())); + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new NotSame(ref('a'), ref('b')), + ['a' => 100, 'b' => 100, 'c' => 10], + schema(int_schema('a'), int_schema('b'), int_schema('c')), + )); } public function test_null(): void { - $row = array_to_row(['a' => 100, 'b' => null], schema(int_schema('a'), str_schema('b', nullable: true))); - - static::assertFalse((new IsNull(ref('a')))->eval($row, flow_context())); - static::assertTrue((new IsNull(ref('b')))->eval($row, flow_context())); - static::assertTrue((new IsNotNull(ref('a')))->eval($row, flow_context())); - static::assertFalse((new IsNotNull(ref('b')))->eval($row, flow_context())); - static::assertTrue((new IsNull(lit(null)))->eval($row, flow_context())); - static::assertTrue((new IsNotNull(lit(1000)))->eval($row, flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new IsNull(ref('a')), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsNull(ref('b')), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsNotNull(ref('a')), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new IsNotNull(ref('b')), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsNull(lit(null)), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new IsNotNull(lit(1000)), + ['a' => 100, 'b' => null], + schema(int_schema('a'), str_schema('b', nullable: true)), + )); } public function test_same(): void { - $row = array_to_row( + static::assertTrue((new FunctionContext(flow_context()))->eval( + new Same(ref('a'), ref('b')), [ 'a' => 100, 'b' => 100, @@ -252,16 +637,36 @@ public function test_same(): void 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), ], schema(int_schema('a'), int_schema('b'), int_schema('c'), datetime_schema('d'), datetime_schema('e')), - ); - - static::assertTrue((new Same(ref('a'), ref('b')))->eval($row, flow_context())); - static::assertFalse((new Same(ref('d'), ref('e')))->eval($row, flow_context())); - static::assertFalse((new Same(ref('a'), ref('c')))->eval($row, flow_context())); + )); + // two datetimes of the same instant are the same value + static::assertTrue((new FunctionContext(flow_context()))->eval( + new Same(ref('d'), ref('e')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + ], + schema(int_schema('a'), int_schema('b'), int_schema('c'), datetime_schema('d'), datetime_schema('e')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new Same(ref('a'), ref('c')), + [ + 'a' => 100, + 'b' => 100, + 'c' => 10, + 'd' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + 'e' => type_datetime()->cast('2023-01-01 00:00:00 UTC'), + ], + schema(int_schema('a'), int_schema('b'), int_schema('c'), datetime_schema('d'), datetime_schema('e')), + )); } public function test_starts_ends_with(): void { - $row = array_to_row( + static::assertTrue((new FunctionContext(flow_context()))->eval( + new StartsWith(ref('a'), lit('some not')), [ 'a' => 'some not too long string', 'b' => 'another not too long text', @@ -269,13 +674,56 @@ public function test_starts_ends_with(): void 'd' => 'text', ], schema(str_schema('a'), str_schema('b'), str_schema('c'), str_schema('d')), - ); - - static::assertTrue((new StartsWith(ref('a'), lit('some not')))->eval($row, flow_context())); - static::assertTrue((new EndsWith(ref('a'), lit('long string')))->eval($row, flow_context())); - static::assertTrue((new StartsWith(ref('b'), ref('c')))->eval($row, flow_context())); - static::assertTrue((new EndsWith(ref('b'), ref('d')))->eval($row, flow_context())); - static::assertTrue((new Contains(ref('a'), lit('too long')))->eval($row, flow_context())); - static::assertFalse((new Contains(ref('a'), lit('blablabla')))->eval($row, flow_context())); + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new EndsWith(ref('a'), lit('long string')), + [ + 'a' => 'some not too long string', + 'b' => 'another not too long text', + 'c' => 'another', + 'd' => 'text', + ], + schema(str_schema('a'), str_schema('b'), str_schema('c'), str_schema('d')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new StartsWith(ref('b'), ref('c')), + [ + 'a' => 'some not too long string', + 'b' => 'another not too long text', + 'c' => 'another', + 'd' => 'text', + ], + schema(str_schema('a'), str_schema('b'), str_schema('c'), str_schema('d')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new EndsWith(ref('b'), ref('d')), + [ + 'a' => 'some not too long string', + 'b' => 'another not too long text', + 'c' => 'another', + 'd' => 'text', + ], + schema(str_schema('a'), str_schema('b'), str_schema('c'), str_schema('d')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + new Contains(ref('a'), lit('too long')), + [ + 'a' => 'some not too long string', + 'b' => 'another not too long text', + 'c' => 'another', + 'd' => 'text', + ], + schema(str_schema('a'), str_schema('b'), str_schema('c'), str_schema('d')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new Contains(ref('a'), lit('blablabla')), + [ + 'a' => 'some not too long string', + 'b' => 'another not too long text', + 'c' => 'another', + 'd' => 'text', + ], + schema(str_schema('a'), str_schema('b'), str_schema('c'), str_schema('d')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryLengthTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryLengthTest.php index f6f20133d4..266b05164d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryLengthTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/BinaryLengthTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,25 +17,31 @@ final class BinaryLengthTest extends FlowTestCase { public function test_binary_length_ascii_string(): void { - static::assertSame(5, ref('str') - ->binaryLength() - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame(5, (new FunctionContext(flow_context()))->eval( + ref('str')->binaryLength(), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_binary_length_binary_data(): void { $binaryData = "\x00\x01\x02\x03\xFF"; - static::assertSame(5, ref('str') - ->binaryLength() - ->eval(array_to_row(['str' => $binaryData], schema(str_schema('str'))), flow_context())); + static::assertSame(5, (new FunctionContext(flow_context()))->eval( + ref('str')->binaryLength(), + ['str' => $binaryData], + schema(str_schema('str')), + )); } public function test_binary_length_empty_string(): void { - static::assertSame(0, ref('str') - ->binaryLength() - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + ref('str')->binaryLength(), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_binary_length_throws_on_null_input(): void @@ -43,15 +49,19 @@ public function test_binary_length_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('BinaryLength function requires non-null value'); - ref('str') - ->binaryLength() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->binaryLength(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_binary_length_string_with_newlines_and_tabs(): void { - static::assertSame(12, ref('str') - ->binaryLength() - ->eval(array_to_row(['str' => "hello\nworld\t"], schema(str_schema('str'))), flow_context())); + static::assertSame(12, (new FunctionContext(flow_context()))->eval( + ref('str')->binaryLength(), + ['str' => "hello\nworld\t"], + schema(str_schema('str')), + )); } } 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 8984971496..aa7b3e94e9 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 @@ -6,11 +6,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\CallUserFunc; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Unit\Function\Fixtures\CallUserFunc\StaticCalculator; use Flow\ETL\Transformer\ScalarFunctionTransformer; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\call; use function Flow\ETL\DSL\flow_context; @@ -40,15 +40,19 @@ public function test_named_parameters_survive_a_rebuild(): void $rebuilt = $function->withChildren($function->children()); static::assertEquals( - $function->eval(array_to_row([], schema()), flow_context()), - $rebuilt->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval($function, [], schema()), + (new FunctionContext(flow_context()))->eval($rebuilt, [], schema()), ); - static::assertEquals(['1', '2', '3'], $rebuilt->eval(array_to_row([], schema()), flow_context())); + static::assertEquals(['1', '2', '3'], (new FunctionContext(flow_context()))->eval($rebuilt, [], schema())); } public function test_call_user_func_as_dsl(): void { - static::assertIsInt(call(lit('time'), type_integer())->eval(array_to_row([], schema()), flow_context())); + static::assertIsInt((new FunctionContext(flow_context()))->eval( + call(lit('time'), type_integer()), + [], + schema(), + )); } public function test_a_non_scalar_function_cannot_replace_the_callable_child(): void @@ -63,53 +67,67 @@ public function test_a_non_scalar_function_cannot_replace_the_callable_child(): public function test_call_user_func_with_array_callable(): void { - static::assertSame(3, ref('list') - ->call(lit([new StaticCalculator(), 'count']), type_integer()) - ->eval(array_to_row(['list' => [ + static::assertSame(3, (new FunctionContext(flow_context()))->eval( + ref('list')->call(lit([new StaticCalculator(), 'count']), type_integer()), + ['list' => [ 1, 2, 3, - ]], schema(list_schema('list', type_list(type_integer())))), flow_context())); + ]], + schema(list_schema('list', type_list(type_integer()))), + )); } public function test_call_user_func_with_native_function(): void { - $row = array_to_row(['list' => [1, 2, 3]], schema(list_schema('list', type_list(type_integer())))); - - static::assertSame(3, ref('list')->call(lit('count'), type_integer())->eval($row, flow_context())); + static::assertSame(3, (new FunctionContext(flow_context()))->eval( + ref('list')->call(lit('count'), type_integer()), + ['list' => [1, 2, 3]], + schema(list_schema('list', type_list(type_integer()))), + )); } public function test_call_user_func_with_ref_alias_and_optional_arguments(): void { - $row = array_to_row(['item_ids' => '1,2,3'], schema(str_schema('item_ids'))); - static::assertEquals( ['1', '2', '3'], - ref('item_ids') - ->call(lit('explode'), type_list(type_string()), ['separator' => ','], refAlias: 'string') - ->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('item_ids')->call( + lit('explode'), + type_list(type_string()), + ['separator' => ','], + refAlias: 'string', + ), + ['item_ids' => '1,2,3'], + schema(str_schema('item_ids')), + ), ); } public function test_call_user_func_with_ref_alias_and_optional_arguments_and_return_type(): void { - $row = array_to_row(['item_ids' => '1,2,3'], schema(str_schema('item_ids'))); - static::assertEquals( [1, 2, 3], - ref('item_ids') - ->call(lit('explode'), type_list(type_integer()), ['separator' => ','], refAlias: 'string') - ->eval($row, flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('item_ids')->call( + lit('explode'), + type_list(type_integer()), + ['separator' => ','], + refAlias: 'string', + ), + ['item_ids' => '1,2,3'], + schema(str_schema('item_ids')), + ), ); } public function test_call_user_func_with_static_method(): void { - $row = array_to_row(['list' => [1, 2, 3]], schema(list_schema('list', type_list(type_integer())))); - - static::assertSame(3, ref('list') - ->call(lit(StaticCalculator::class . '::count'), type_integer()) - ->eval($row, flow_context())); + static::assertSame(3, (new FunctionContext(flow_context()))->eval( + ref('list')->call(lit(StaticCalculator::class . '::count'), type_integer()), + ['list' => [1, 2, 3]], + schema(list_schema('list', type_list(type_integer()))), + )); } public function test_a_callable_that_can_return_null_declares_a_nullable_column(): void @@ -127,6 +145,6 @@ public function test_a_null_return_lands_in_a_nullable_column(): void ))->transform(array_to_rows([['name' => 'a']], schema(str_schema('name'))), flow_context()); static::assertTrue($result->schema()->get('out')->isNullable()); - static::assertNull($result->first()->get('out')); + static::assertNull($result->column('out')->value(0)); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CapitalizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CapitalizeTest.php index e21bf2f2aa..72e040e5cb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CapitalizeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CapitalizeTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -16,8 +16,10 @@ final class CapitalizeTest extends FlowTestCase { public function test_capitalize_valid_string(): void { - static::assertSame('This Is A Value', ref('string') - ->capitalize() - ->eval(array_to_row(['string' => 'this is a value'], schema(str_schema('string'))), flow_context())); + static::assertSame('This Is A Value', (new FunctionContext(flow_context()))->eval( + ref('string')->capitalize(), + ['string' => 'this is a value'], + schema(str_schema('string')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php index 70570ea667..e6428a46ad 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php @@ -7,16 +7,18 @@ use DateTimeImmutable; use DateTimeZone; use DOMDocument; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Schema\Definition; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; +use Flow\Types\Exception\CastingException; use Flow\Types\Type; use Flow\Types\Value\Json; use Flow\Types\Value\Uuid; use Generator; use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\cast; use function Flow\ETL\DSL\datetime_schema; @@ -43,16 +45,38 @@ public function test_cast_of_a_null_value_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function requires non-null value'); - cast(ref('value'), 'int')->eval(array_to_row([ - 'value' => null, - ], schema(str_schema('value', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + cast(ref('value'), 'int'), + [ + 'value' => null, + ], + schema(str_schema('value', nullable: true)), + ); } public function test_cast_of_a_null_value_to_an_optional_target_is_null(): void { - static::assertNull(cast(ref('value'), type_optional(type_integer()))->eval(array_to_row([ - 'value' => null, - ], schema(str_schema('value', nullable: true))), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval( + cast(ref('value'), type_optional(type_integer())), + [ + 'value' => null, + ], + schema(str_schema('value', nullable: true)), + )); + } + + public function test_a_refused_cast_keeps_the_casting_error_as_the_cause(): void + { + try { + (new FunctionContext(flow_context()))->eval( + cast(ref('value'), type_optional(type_datetime())), + ['value' => 'abc'], + schema(str_schema('value')), + ); + static::fail('An unconvertible value must be refused.'); + } catch (EvaluationException $e) { + static::assertInstanceOf(CastingException::class, $e->getPrevious()?->getPrevious()); + } } public function test_casting_an_unconvertible_value_to_an_optional_target_throws(): void @@ -60,9 +84,13 @@ public function test_casting_an_unconvertible_value_to_an_optional_target_throws $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "string" into "datetime" type'); - cast(ref('value'), type_optional(type_datetime()))->eval(array_to_row([ - 'value' => 'abc', - ], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + cast(ref('value'), type_optional(type_datetime())), + [ + 'value' => 'abc', + ], + schema(str_schema('value')), + ); } public function test_constructor_rejects_a_non_representable_target(): void @@ -75,12 +103,20 @@ public function test_constructor_rejects_a_non_representable_target(): void public function test_double_and_real_resolve_to_float(): void { - static::assertSame(1.0, cast(ref('value'), 'double')->eval(array_to_row([ - 'value' => '1', - ], schema(str_schema('value'))), flow_context())); - static::assertSame(1.0, cast(ref('value'), 'real')->eval(array_to_row([ - 'value' => '1', - ], schema(str_schema('value'))), flow_context())); + static::assertSame(1.0, (new FunctionContext(flow_context()))->eval( + cast(ref('value'), 'double'), + [ + 'value' => '1', + ], + schema(str_schema('value')), + )); + static::assertSame(1.0, (new FunctionContext(flow_context()))->eval( + cast(ref('value'), 'real'), + [ + 'value' => '1', + ], + schema(str_schema('value')), + )); } public function test_constructor_rejects_json_pretty(): void @@ -190,11 +226,18 @@ public static function cast_provider(): array #[DataProvider('cast_provider')] public function test_cast(mixed $from, Definition $definition, string $to, mixed $expected): void { - $row = array_to_row(['value' => $from], schema($definition)); // @mago-ignore analysis:mixed-assignment - $resultRefCast = ref('value')->cast($to)->eval($row, flow_context()); + $resultRefCast = (new FunctionContext(flow_context()))->eval( + ref('value')->cast($to), + ['value' => $from], + schema($definition), + ); // @mago-ignore analysis:mixed-assignment - $resultCastRef = cast(ref('value'), $to)->eval($row, flow_context()); + $resultCastRef = (new FunctionContext(flow_context()))->eval( + cast(ref('value'), $to), + ['value' => $from], + schema($definition), + ); if (is_object($expected) || is_object($from)) { static::assertEquals($expected, $resultRefCast); @@ -212,7 +255,11 @@ public function test_casting_a_scalar_to_array_names_the_remedy(): void 'Cast function failed: Can\'t cast "string" into "array" type: wrap the value first, e.g. type_list(type_string())', ); - ref('value')->cast('array')->eval(array_to_row(['value' => '1'], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->cast('array'), + ['value' => '1'], + schema(str_schema('value')), + ); } public function test_casting_integer_to_timezone(): void @@ -220,9 +267,11 @@ public function test_casting_integer_to_timezone(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "int" into "timezone" type'); - ref('value') - ->cast('timezone') - ->eval(array_to_row(['value' => 123], schema(int_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->cast('timezone'), + ['value' => 123], + schema(int_schema('value')), + ); } public function test_casting_integer_to_xml(): void @@ -230,7 +279,11 @@ public function test_casting_integer_to_xml(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "int" into "xml" type'); - ref('value')->cast('xml')->eval(array_to_row(['value' => 1], schema(int_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->cast('xml'), + ['value' => 1], + schema(int_schema('value')), + ); } public function test_casting_invalid_string_to_timezone(): void @@ -238,9 +291,11 @@ public function test_casting_invalid_string_to_timezone(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "string" into "timezone" type'); - ref('value') - ->cast('timezone') - ->eval(array_to_row(['value' => 'invalid-timezone'], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->cast('timezone'), + ['value' => 'invalid-timezone'], + schema(str_schema('value')), + ); } public function test_casting_non_xml_string_to_xml(): void @@ -248,6 +303,10 @@ public function test_casting_non_xml_string_to_xml(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Cast function failed: Can\'t cast "string" into "xml" type'); - ref('value')->cast('xml')->eval(array_to_row(['value' => 'foo'], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->cast('xml'), + ['value' => 'foo'], + schema(str_schema('value')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ChunkTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ChunkTest.php index 36c530c7a4..3e0c5ce6b1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ChunkTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ChunkTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -20,7 +20,7 @@ public function test_chunk_empty_string(): void { static::assertSame( [], - ref('str')->chunk(3)->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()), + (new FunctionContext(flow_context()))->eval(ref('str')->chunk(3), ['str' => ''], schema(str_schema('str'))), ); } @@ -28,7 +28,11 @@ public function test_chunk_equal_to_string_length(): void { static::assertSame( ['hello'], - ref('str')->chunk(5)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('str')->chunk(5), + ['str' => 'hello'], + schema(str_schema('str')), + ), ); } @@ -36,7 +40,11 @@ public function test_chunk_larger_than_string_length(): void { static::assertSame( ['hello'], - ref('str')->chunk(10)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('str')->chunk(10), + ['str' => 'hello'], + schema(str_schema('str')), + ), ); } @@ -45,7 +53,11 @@ public function test_chunk_negative_size(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Chunk function requires non-null, positive size'); - ref('str')->chunk(-1)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->chunk(-1), + ['str' => 'hello'], + schema(str_schema('str')), + ); } public function test_chunk_null_input(): void @@ -53,16 +65,22 @@ public function test_chunk_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Chunk function requires non-null value'); - ref('str') - ->chunk(3) - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->chunk(3), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_chunk_string_basic_functionality(): void { static::assertSame( ['hel', 'lo '], - ref('str')->chunk(3)->eval(array_to_row(['str' => 'hello '], schema(str_schema('str'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('str')->chunk(3), + ['str' => 'hello '], + schema(str_schema('str')), + ), ); } @@ -71,27 +89,22 @@ public function test_chunk_with_null_size(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Chunk function requires non-null, positive size'); - ref('str') - ->chunk(ref('size')) - ->eval( - array_to_row( - ['str' => 'hello', 'size' => null], - schema(str_schema('str'), str_schema('size', nullable: true)), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('str')->chunk(ref('size')), + ['str' => 'hello', 'size' => null], + schema(str_schema('str'), str_schema('size', nullable: true)), + ); } public function test_chunk_with_scalar_function_size(): void { static::assertSame( ['he', 'll', 'o'], - ref('str') - ->chunk(ref('size')) - ->eval( - array_to_row(['str' => 'hello', 'size' => 2], schema(str_schema('str'), int_schema('size'))), - flow_context(), - ), + (new FunctionContext(flow_context()))->eval( + ref('str')->chunk(ref('size')), + ['str' => 'hello', 'size' => 2], + schema(str_schema('str'), int_schema('size')), + ), ); } @@ -100,6 +113,10 @@ public function test_chunk_zero_size(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Chunk function requires non-null, positive size'); - ref('str')->chunk(0)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->chunk(0), + ['str' => 'hello'], + schema(str_schema('str')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CoalesceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CoalesceTest.php index 97701a6ea4..3c0e133457 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CoalesceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CoalesceTest.php @@ -7,9 +7,11 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Double\FailingOnValuesFunction; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\coalesce; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -33,49 +35,63 @@ public function test_a_non_nullable_branch_makes_the_result_not_nullable(): void public function test_coalesce_entries(): void { - static::assertSame(1, coalesce(ref('name'), ref('id'), lit('N/A'))->eval( - array_to_row( - [ - 'name' => null, - 'id' => 1, - ], - schema(str_schema('name', nullable: true), int_schema('id')), - ), - flow_context(), + // coalesce() of string and integer declares string: the value is cast to it + static::assertSame('1', (new FunctionContext(flow_context()))->eval( + coalesce(ref('name'), ref('id'), lit('N/A')), + [ + 'name' => null, + 'id' => 1, + ], + schema(str_schema('name', nullable: true), int_schema('id')), )); } public function test_coalesce_on_null_entries_falls_through_to_lit(): void { - static::assertSame('N/A', coalesce(ref('name'), ref('string'), lit('N/A'))->eval( - array_to_row( - [ - 'name' => null, - 'string' => null, - ], - schema(str_schema('name', nullable: true), str_schema('string', nullable: true)), - ), - flow_context(), + static::assertSame('N/A', (new FunctionContext(flow_context()))->eval( + coalesce(ref('name'), ref('string'), lit('N/A')), + [ + 'name' => null, + 'string' => null, + ], + schema(str_schema('name', nullable: true), str_schema('string', nullable: true)), )); } public function test_coalesce_on_ref(): void { - static::assertSame(1, ref('name') - ->coalesce(ref('id'), lit('N/A')) - ->eval( - array_to_row(['name' => null, 'id' => 1], schema(str_schema('name', nullable: true), int_schema('id'))), - flow_context(), - )); + // coalesce() of string and integer declares string: the value is cast to it + static::assertSame('1', (new FunctionContext(flow_context()))->eval( + ref('name')->coalesce(ref('id'), lit('N/A')), + ['name' => null, 'id' => 1], + schema(str_schema('name', nullable: true), int_schema('id')), + )); } public function test_a_throwing_branch_is_not_swallowed(): void { $this->expectException(InvalidArgumentException::class); - coalesce(ref('a')->upper(), ref('b')->upper())->eval( - array_to_row(['a' => 1, 'b' => 2], schema(int_schema('a'), int_schema('b'))), - flow_context(), + (new FunctionContext(flow_context()))->eval( + coalesce(ref('a')->upper(), ref('b')->upper()), + ['a' => 1, 'b' => 2], + schema(int_schema('a'), int_schema('b')), + ); + } + + public function test_an_unreached_argument_that_would_throw_is_not_evaluated(): void + { + $rows = array_to_rows( + [['a' => 1, 'v' => 99], ['a' => null, 'v' => 2]], + schema(int_schema('a', nullable: true), int_schema('v')), + ); + + static::assertSame( + [1, 2], + (new ReferenceResolver()) + ->resolve(coalesce(ref('a'), new FailingOnValuesFunction(ref('v'), [99])), $rows->schema()) + ->eval($rows, flow_context()) + ->values(), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CodePointLengthTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CodePointLengthTest.php index 3e153abf45..d7e7d8ea7a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CodePointLengthTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CodePointLengthTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,16 +17,20 @@ final class CodePointLengthTest extends FlowTestCase { public function test_code_point_length_ascii_string(): void { - static::assertSame(5, ref('str') - ->codePointLength() - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame(5, (new FunctionContext(flow_context()))->eval( + ref('str')->codePointLength(), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_code_point_length_empty_string(): void { - static::assertSame(0, ref('str') - ->codePointLength() - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + ref('str')->codePointLength(), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_code_point_length_throws_on_null_input(): void @@ -34,8 +38,10 @@ public function test_code_point_length_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('CodePointLength function requires non-null value'); - ref('str') - ->codePointLength() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->codePointLength(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollapseWhitespaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollapseWhitespaceTest.php index 40e75fc2ae..5b4ff74f47 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollapseWhitespaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollapseWhitespaceTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,47 +17,47 @@ final class CollapseWhitespaceTest extends FlowTestCase { public function test_empty_string(): void { - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); - - static::assertEquals('', $result); + static::assertEquals('', (new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_leading_and_trailing_whitespace(): void { - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => ' Hello world '], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello world', $result); + static::assertEquals('Hello world', (new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => ' Hello world '], + schema(str_schema('str')), + )); } public function test_leading_whitespace(): void { - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => ' Hello world'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello world', $result); + static::assertEquals('Hello world', (new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => ' Hello world'], + schema(str_schema('str')), + )); } public function test_mixed_whitespace_types(): void { - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => "Hello\t\tworld\n\ntest"], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello world test', $result); + static::assertEquals('Hello world test', (new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => "Hello\t\tworld\n\ntest"], + schema(str_schema('str')), + )); } public function test_multiple_spaces_between_words(): void { - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => 'Hello world test'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello world test', $result); + static::assertEquals('Hello world test', (new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => 'Hello world test'], + schema(str_schema('str')), + )); } public function test_null_value(): void @@ -65,37 +65,37 @@ public function test_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('CollapseWhitespace function requires non-null value'); - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); - - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_single_spaces(): void { - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => 'Hello world test'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello world test', $result); + static::assertEquals('Hello world test', (new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => 'Hello world test'], + schema(str_schema('str')), + )); } public function test_single_word(): void { - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => 'Hello'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello', $result); + static::assertEquals('Hello', (new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => 'Hello'], + schema(str_schema('str')), + )); } public function test_trailing_whitespace(): void { - $result = ref('str') - ->collapseWhitespace() - ->eval(array_to_row(['str' => 'Hello world '], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello world', $result); + static::assertEquals('Hello world', (new FunctionContext(flow_context()))->eval( + ref('str')->collapseWhitespace(), + ['str' => 'Hello world '], + schema(str_schema('str')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectTest.php index 133f8b4e01..dcf73348cb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectTest.php @@ -4,11 +4,14 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\collect; +use function Flow\ETL\DSL\count; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -26,10 +29,10 @@ public function test_aggregation_collect_entry_values(): void { $aggregator = collect(ref('data')); - $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'a']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'c']], schema(str_schema('data'))), [0], flow_context()); static::assertSame( [ @@ -65,4 +68,48 @@ public function test_a_nullable_source_column_yields_a_nullable_element_type(): static::assertSame('?list', $resolved->returns()->toString()); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = collect(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 'a', + 'b', + 'c', + 'd', + ]), schema(str_schema('v'))), + [1, 3], + flow_context(), + ); + + static::assertSame(['b', 'd'], $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 'a', + 'b', + 'c', + 'd', + ]), schema(str_schema('v'))); + $onePass = collect(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = collect(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = collect(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + collect(ref('v'))->merge(count(ref('v')), flow_context()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectUniqueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectUniqueTest.php index 189e2873bc..0e3d41e024 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectUniqueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CollectUniqueTest.php @@ -4,9 +4,12 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\collect; use function Flow\ETL\DSL\collect_unique; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; @@ -24,10 +27,10 @@ public function test_aggregation_collect_unique_values(): void { $aggregator = collect_unique(ref('data')); - $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'a']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'c']], schema(str_schema('data'))), [0], flow_context()); static::assertSame( [ @@ -55,4 +58,48 @@ public function test_collecting_nothing_yields_an_empty_list(): void { static::assertSame([], collect_unique(ref('data'))->value()); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = collect_unique(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 'a', + 'b', + 'a', + 'c', + ]), schema(str_schema('v'))), + [0, 2], + flow_context(), + ); + + static::assertSame(['a'], $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 'a', + 'b', + 'a', + 'c', + ]), schema(str_schema('v'))); + $onePass = collect_unique(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = collect_unique(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = collect_unique(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + collect_unique(ref('v'))->merge(collect(ref('v')), flow_context()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CombineTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CombineTest.php index 37d750464a..4b95bf8139 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CombineTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CombineTest.php @@ -8,9 +8,9 @@ use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\combine; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; @@ -41,13 +41,13 @@ public function test_array_combine(): void { static::assertSame( ['a' => 1, 'b' => 2, 'c' => 3], - combine(lit(['a', 'b', 'c']), lit([1, 2, 3]))->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval(combine(lit(['a', 'b', 'c']), lit([1, 2, 3])), [], schema()), ); } public function test_array_combine_when_arrays_are_empty(): void { - static::assertSame([], combine(lit([]), lit([]))->eval(array_to_row([], schema()), flow_context())); + static::assertSame([], (new FunctionContext(flow_context()))->eval(combine(lit([]), lit([])), [], schema())); } public function test_array_combine_when_keys_are_not_array(): void @@ -55,14 +55,18 @@ public function test_array_combine_when_keys_are_not_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "array", got "string".'); - combine(lit('a'), lit([1, 2, 3]))->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval(combine(lit('a'), lit([1, 2, 3])), [], schema()); } public function test_array_combine_when_keys_are_not_unique(): void { static::assertSame( ['a' => 4, 'b' => 2, 'c' => 3], - combine(lit(['a', 'b', 'c', 'a']), lit([1, 2, 3, 4]))->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval( + combine(lit(['a', 'b', 'c', 'a']), lit([1, 2, 3, 4])), + [], + schema(), + ), ); } @@ -71,6 +75,6 @@ public function test_array_combine_when_one_of_arrays_is_empty(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Combine function requires keys and values arrays to have the same length'); - combine(lit(['a', 'b', 'c']), lit([]))->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval(combine(lit(['a', 'b', 'c']), lit([])), [], schema()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatTest.php index f736c68e43..33f944c3e3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\concat; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; @@ -20,34 +20,31 @@ final class ConcatTest extends FlowTestCase { public function test_concat_arrays(): void { - static::assertSame('["a"]["b","c"]', concat(ref('array_1'), ref('array_2'))->eval( - array_to_row( - [ - 'array_1' => ['a'], - 'array_2' => ['b', 'c'], - ], - schema( - list_schema('array_1', type_list(type_string())), - list_schema('array_2', type_list(type_string())), - ), - ), - flow_context(), + static::assertSame('["a"]["b","c"]', (new FunctionContext(flow_context()))->eval( + concat(ref('array_1'), ref('array_2')), + [ + 'array_1' => ['a'], + 'array_2' => ['b', 'c'], + ], + schema(list_schema('array_1', type_list(type_string())), list_schema('array_2', type_list(type_string()))), )); } public function test_concat_different_types_of_values(): void { - static::assertSame('1abc["a","b"]', concat(lit(1), lit('a'), lit('b'), lit('c'), lit(['a', 'b']))->eval( - array_to_row([], schema()), - flow_context(), + static::assertSame('1abc["a","b"]', (new FunctionContext(flow_context()))->eval( + concat(lit(1), lit('a'), lit('b'), lit('c'), lit(['a', 'b'])), + [], + schema(), )); } public function test_concat_string_values(): void { - static::assertSame('abc', concat(lit('a'), lit('b'), lit('c'))->eval( - array_to_row([], schema()), - flow_context(), + static::assertSame('abc', (new FunctionContext(flow_context()))->eval( + concat(lit('a'), lit('b'), lit('c')), + [], + schema(), )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatWithSeparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatWithSeparatorTest.php index ab26a5dd04..ad6e12fcf9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatWithSeparatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ConcatWithSeparatorTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\concat_ws; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -19,29 +19,25 @@ final class ConcatWithSeparatorTest extends FlowTestCase { public function test_concat_with_separator(): void { - static::assertSame('a,1', concat_ws(lit(','), ref('string'), ref('integer'))->eval( - array_to_row( - [ - 'string' => 'a', - 'integer' => 1, - ], - schema(str_schema('string'), int_schema('integer')), - ), - flow_context(), + static::assertSame('a,1', (new FunctionContext(flow_context()))->eval( + concat_ws(lit(','), ref('string'), ref('integer')), + [ + 'string' => 'a', + 'integer' => 1, + ], + schema(str_schema('string'), int_schema('integer')), )); } public function test_a_null_value_is_skipped(): void { - static::assertSame('a', concat_ws(lit(','), ref('string'), ref('missing_value'))->eval( - array_to_row( - [ - 'string' => 'a', - 'missing_value' => null, - ], - schema(str_schema('string'), str_schema('missing_value', nullable: true)), - ), - flow_context(), + static::assertSame('a', (new FunctionContext(flow_context()))->eval( + concat_ws(lit(','), ref('string'), ref('missing_value')), + [ + 'string' => 'a', + 'missing_value' => null, + ], + schema(str_schema('string'), str_schema('missing_value', nullable: true)), )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CountTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CountTest.php index 7f15d8d91e..efbdfb3a88 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CountTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CountTest.php @@ -8,16 +8,17 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\count; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\sum; use function Flow\ETL\DSL\window; final class CountTest extends FlowTestCase @@ -36,13 +37,17 @@ public function test_aggregation_count_from_numeric_values(): void { $aggregator = count(ref('int')); - $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'not_int' => null, - ], schema(str_schema('not_int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '10']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '20']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '55']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '25']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'not_int' => null, + ]], schema(str_schema('not_int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(4, $aggregator->value()); } @@ -51,10 +56,10 @@ public function test_aggregation_count_with_float_result(): void { $aggregator = count(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10.25], schema(float_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 305], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10.25]], schema(float_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 305]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 25]], schema(int_schema('int'))), [0], flow_context()); static::assertSame(4, $aggregator->value()); } @@ -63,13 +68,17 @@ public function test_aggregation_count_without_reference(): void { $aggregator = count(); - $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'not_int' => null, - ], schema(str_schema('not_int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '10']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '20']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '55']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '25']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'not_int' => null, + ]], schema(str_schema('not_int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(5, $aggregator->value()); } @@ -78,45 +87,49 @@ public function test_aggregation_when_row_does_not_have_entry(): void { $aggregator = count(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'int' => null, - ], schema(int_schema('int', nullable: true))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'test' => null, - ], schema(str_schema('test', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'int' => null, + ]], schema(int_schema('int', nullable: true))), + [0], + flow_context(), + ); + $aggregator->aggregate( + array_to_rows([[ + 'test' => null, + ]], schema(str_schema('test', nullable: true))), + [0], + flow_context(), + ); static::assertSame(4, $aggregator->value()); } public function test_window_function_count_of_a_reference_skips_nulls(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'value' => 10], ['id' => 2, 'value' => null], ['id' => 3, 'value' => 30]], schema(int_schema('id'), int_schema('value', nullable: true)), - $row1 = array_to_row(['id' => 1, 'value' => 10], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 2, 'value' => null], schema(int_schema('id'), int_schema('value', nullable: true))), - array_to_row(['id' => 3, 'value' => 30], schema(int_schema('id'), int_schema('value'))), ); $count = count(ref('value'))->over(window()->orderBy(ref('id'))); - static::assertSame(2, $count->apply(WindowContextMother::forRow($row1, $rows))); + static::assertSame(2, $count->apply(WindowContextMother::atIndex($rows, 0))); } public function test_window_function_count_without_a_reference_counts_every_row_in_the_frame(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'value' => 10], ['id' => 2, 'value' => null], ['id' => 3, 'value' => 30]], schema(int_schema('id'), int_schema('value', nullable: true)), - $row1 = array_to_row(['id' => 1, 'value' => 10], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 2, 'value' => null], schema(int_schema('id'), int_schema('value', nullable: true))), - array_to_row(['id' => 3, 'value' => 30], schema(int_schema('id'), int_schema('value'))), ); $count = count()->over(window()->orderBy(ref('id'))); - static::assertSame(3, $count->apply(WindowContextMother::forRow($row1, $rows))); + static::assertSame(3, $count->apply(WindowContextMother::atIndex($rows, 0))); } public function test_window_function_count_with_missing_reference_in_strict_mode(): void @@ -124,16 +137,12 @@ public function test_window_function_count_with_missing_reference_in_strict_mode $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Count window function error:'); - $rows = rows( - schema(int_schema('id')), - $row1 = array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - ); + $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $count = count(ref('missing_column'))->over(window()->orderBy(ref('id'))); $context = flow_context(config()); - $count->apply(WindowContextMother::forRow($row1, $rows, context: $context)); + $count->apply(WindowContextMother::atIndex($rows, 0, context: $context)); } public function test_with_children_rebuilds_the_aggregate_with_the_given_reference(): void @@ -160,4 +169,43 @@ public function test_counting_nothing_is_zero(): void { static::assertSame(0, count(ref('int'))->value()); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = count(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [1, 2, 3, 4]), schema(int_schema('v'))), + [1, 3], + flow_context(), + ); + + static::assertSame(2, $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 1, + 2, + 3, + 4, + ]), schema(int_schema('v'))); + $onePass = count(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = count(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = count(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + count(ref('v'))->merge(sum(ref('v')), flow_context()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributeValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributeValueTest.php index 75c6a7c369..ca38fdac04 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributeValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributeValueTest.php @@ -8,10 +8,10 @@ use Dom\HTMLElement; use DOMDocument; use DOMElement; +use Flow\ETL\Tests\Context\FunctionContext; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\ref; @@ -33,11 +33,13 @@ public function test_html_extracting_attribute_from_dom_element_entry(): void ); static::assertInstanceOf(HTMLElement::class, $element->documentElement); - static::assertEquals('foobar', ref('value') - ->domElementAttributeValue('id') - ->eval(array_to_row([ + static::assertEquals('foobar', (new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributeValue('id'), + [ 'value' => $element->documentElement, - ], schema(html_element_schema('value'))), flow_context())); + ], + schema(html_element_schema('value')), + )); } #[RequiresPhp('>= 8.4.0')] @@ -47,13 +49,13 @@ public function test_html_extracting_non_existing_attribute_from_dom_element_ent $element = HTMLDocument::createFromString('foobar', LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); static::assertInstanceOf(HTMLElement::class, $element->documentElement); - static::assertNull( - ref('value') - ->domElementAttributeValue('id') - ->eval(array_to_row([ - 'value' => $element->documentElement, - ], schema(html_element_schema('value'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributeValue('id'), + [ + 'value' => $element->documentElement, + ], + schema(html_element_schema('value')), + )); } public function test_xml_extracting_attribute_from_dom_element_entry(): void @@ -62,11 +64,13 @@ public function test_xml_extracting_attribute_from_dom_element_entry(): void $xml->loadXML('bar'); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertEquals('buz', ref('value') - ->domElementAttributeValue('baz') - ->eval(array_to_row([ + static::assertEquals('buz', (new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributeValue('baz'), + [ 'value' => $xml->documentElement->firstChild, - ], schema(xml_element_schema('value'))), flow_context())); + ], + schema(xml_element_schema('value')), + )); } public function test_xml_extracting_non_existing_attribute_from_dom_element_entry(): void @@ -75,12 +79,12 @@ public function test_xml_extracting_non_existing_attribute_from_dom_element_entr $xml->loadXML('bar'); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertNull( - ref('value') - ->domElementAttributeValue('bar') - ->eval(array_to_row([ - 'value' => $xml->documentElement->firstChild, - ], schema(xml_element_schema('value'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributeValue('bar'), + [ + 'value' => $xml->documentElement->firstChild, + ], + schema(xml_element_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributesCountTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributesCountTest.php index aa2b0dd904..2cc62b2ff1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributesCountTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementAttributesCountTest.php @@ -8,10 +8,10 @@ use Dom\HTMLElement; use DOMDocument; use DOMElement; +use Flow\ETL\Tests\Context\FunctionContext; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\ref; @@ -33,11 +33,13 @@ public function test_html_attributes_count_on_element_with_multiple_attributes() ); static::assertInstanceOf(HTMLElement::class, $element->documentElement); - static::assertSame(3, ref('value') - ->domElementAttributesCount() - ->eval(array_to_row([ + static::assertSame(3, (new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributesCount(), + [ 'value' => $element->documentElement, - ], schema(html_element_schema('value'))), flow_context())); + ], + schema(html_element_schema('value')), + )); } #[RequiresPhp('>= 8.4.0')] @@ -50,11 +52,13 @@ public function test_html_attributes_count_on_element_with_one_attribute(): void ); static::assertInstanceOf(HTMLElement::class, $element->documentElement); - static::assertSame(1, ref('value') - ->domElementAttributesCount() - ->eval(array_to_row([ + static::assertSame(1, (new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributesCount(), + [ 'value' => $element->documentElement, - ], schema(html_element_schema('value'))), flow_context())); + ], + schema(html_element_schema('value')), + )); } #[RequiresPhp('>= 8.4.0')] @@ -64,11 +68,13 @@ public function test_html_attributes_count_on_element_with_zero_attributes(): vo $element = HTMLDocument::createFromString('foobar', LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); static::assertInstanceOf(HTMLElement::class, $element->documentElement); - static::assertSame(0, ref('value') - ->domElementAttributesCount() - ->eval(array_to_row([ + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributesCount(), + [ 'value' => $element->documentElement, - ], schema(html_element_schema('value'))), flow_context())); + ], + schema(html_element_schema('value')), + )); } public function test_xml_attributes_count_on_element_with_multiple_attributes(): void @@ -77,11 +83,13 @@ public function test_xml_attributes_count_on_element_with_multiple_attributes(): $xml->loadXML('bar'); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertSame(3, ref('value') - ->domElementAttributesCount() - ->eval(array_to_row([ + static::assertSame(3, (new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributesCount(), + [ 'value' => $xml->documentElement->firstChild, - ], schema(xml_element_schema('value'))), flow_context())); + ], + schema(xml_element_schema('value')), + )); } public function test_xml_attributes_count_on_element_with_one_attribute(): void @@ -90,11 +98,13 @@ public function test_xml_attributes_count_on_element_with_one_attribute(): void $xml->loadXML('bar'); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertSame(1, ref('value') - ->domElementAttributesCount() - ->eval(array_to_row([ + static::assertSame(1, (new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributesCount(), + [ 'value' => $xml->documentElement->firstChild, - ], schema(xml_element_schema('value'))), flow_context())); + ], + schema(xml_element_schema('value')), + )); } public function test_xml_attributes_count_on_element_with_zero_attributes(): void @@ -103,10 +113,12 @@ public function test_xml_attributes_count_on_element_with_zero_attributes(): voi $xml->loadXML('bar'); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertSame(0, ref('value') - ->domElementAttributesCount() - ->eval(array_to_row([ + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + ref('value')->domElementAttributesCount(), + [ 'value' => $xml->documentElement->firstChild, - ], schema(xml_element_schema('value'))), flow_context())); + ], + schema(xml_element_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementNamespaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementNamespaceTest.php index 6c47661dc6..193f6cbc02 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementNamespaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementNamespaceTest.php @@ -8,10 +8,10 @@ use Dom\XMLDocument; use DOMDocument; use DOMElement; +use Flow\ETL\Tests\Context\FunctionContext; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -39,11 +39,15 @@ public function test_html_getting_element_namespace(): void $element = XMLDocument::createFromString(self::XML, LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); static::assertInstanceOf(Element::class, $element->documentElement); - static::assertSame('urn:oasis:names:specification:ubl:schema:xsd:Invoice-2', ref('node') - ->domElementNamespace() - ->eval(array_to_row([ + static::assertSame('urn:oasis:names:specification:ubl:schema:xsd:Invoice-2', (new FunctionContext( + flow_context(), + ))->eval( + ref('node')->domElementNamespace(), + [ 'node' => $element->documentElement, - ], schema(xml_element_schema('node'))), flow_context())); + ], + schema(xml_element_schema('node')), + )); } public function test_xml_getting_element_namespace(): void @@ -52,11 +56,15 @@ public function test_xml_getting_element_namespace(): void $xml->loadXML(self::XML); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertSame('urn:oasis:names:specification:ubl:schema:xsd:Invoice-2', ref('node') - ->domElementNamespace() - ->eval(array_to_row([ + static::assertSame('urn:oasis:names:specification:ubl:schema:xsd:Invoice-2', (new FunctionContext( + flow_context(), + ))->eval( + ref('node')->domElementNamespace(), + [ 'node' => $xml->documentElement, - ], schema(xml_element_schema('node'))), flow_context())); + ], + schema(xml_element_schema('node')), + )); } public function test_xml_getting_element_non_default_namespace(): void @@ -65,10 +73,14 @@ public function test_xml_getting_element_non_default_namespace(): void $xml->loadXML(self::XML); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertSame('http://www.unece.org/cefact/nodes/StandardBusinessDocumentHeader', ref('node') - ->domElementNamespace('xmlns:sh') - ->eval(array_to_row([ + static::assertSame('http://www.unece.org/cefact/nodes/StandardBusinessDocumentHeader', (new FunctionContext( + flow_context(), + ))->eval( + ref('node')->domElementNamespace('xmlns:sh'), + [ 'node' => $xml->documentElement, - ], schema(xml_element_schema('node'))), flow_context())); + ], + schema(xml_element_schema('node')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php index 410f534b0c..0f11e17a7b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementParentTest.php @@ -7,10 +7,10 @@ use Dom\HTMLDocument; use DOMDocument; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\html_element_schema; @@ -33,12 +33,14 @@ public function test_html_fails_when_parent_not_available_in_strict_mode(): void $context = flow_context(config()); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('DOMElementParent requires non-null DOMNode or HTMLElement.'); - ref('value') - ->domElementParent() - // @mago-ignore analysis:possibly-null-property-access - ->eval(array_to_row([ + (new FunctionContext($context))->eval( + ref('value')->domElementParent(), + [ + // @mago-ignore analysis:possibly-null-property-access 'value' => $element->documentElement->parentElement, - ], schema(html_element_schema('value', nullable: true))), $context); + ], + schema(html_element_schema('value', nullable: true)), + ); } #[RequiresPhp('>= 8.4.0')] @@ -51,7 +53,11 @@ public function test_html_getting_parent_element(): void ); static::assertEquals( $element->documentElement, - lit($element->querySelector('span'))->domElementParent()->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval( + lit($element->querySelector('span'))->domElementParent(), + [], + schema(), + ), ); } @@ -60,9 +66,11 @@ public function test_html_getting_parent_element_when_not_available(): void { // @mago-ignore analysis:unavailable-method $element = HTMLDocument::createFromString('bar', LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); - static::assertNull( - lit($element->documentElement)->domElementParent()->eval(array_to_row([], schema()), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + lit($element->documentElement)->domElementParent(), + [], + schema(), + )); } public function test_xml_fails_when_parent_not_available_in_strict_mode(): void @@ -72,11 +80,13 @@ public function test_xml_fails_when_parent_not_available_in_strict_mode(): void $context = flow_context(config()); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('DOMElementParent requires non-null DOMNode or HTMLElement.'); - static::assertEquals($xml, ref('value') - ->domElementParent() - ->eval(array_to_row([ + static::assertEquals($xml, (new FunctionContext($context))->eval( + ref('value')->domElementParent(), + [ 'value' => $xml->parentNode, - ], schema(xml_element_schema('value', nullable: true))), $context)); + ], + schema(xml_element_schema('value', nullable: true)), + )); } public function test_xml_getting_parent_element(): void @@ -87,9 +97,11 @@ public function test_xml_getting_parent_element(): void $xml->documentElement, // a batch stores the element's markup, so the parent is only reachable on the live node // @mago-ignore analysis:possibly-null-property-access - lit($xml->documentElement->firstChild) - ->domElementParent() - ->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval( + lit($xml->documentElement->firstChild)->domElementParent(), + [], + schema(), + ), ); } @@ -97,23 +109,23 @@ public function test_xml_getting_parent_element_when_not_available(): void { $xml = new DOMDocument(); $xml->loadXML('foobar'); - static::assertNull( - ref('value') - ->domElementParent() - ->eval(array_to_row([ - 'value' => $xml->documentElement, - ], schema(xml_element_schema('value'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->domElementParent(), + [ + 'value' => $xml->documentElement, + ], + schema(xml_element_schema('value')), + )); } public function test_xml_getting_parent_element_when_passing_document(): void { $xml = new DOMDocument(); $xml->loadXML('foobar'); - static::assertNull( - ref('value') - ->domElementParent() - ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->domElementParent(), + ['value' => $xml], + schema(xml_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementValueTest.php index 078c588a24..a780580879 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DOMElementValueTest.php @@ -8,10 +8,10 @@ use Dom\HTMLElement; use DOMDocument; use DOMElement; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\RequiresPhp; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\html_element_schema; use function Flow\ETL\DSL\ref; @@ -30,11 +30,13 @@ public function test_html_getting_element_value_with_children(): void $element = HTMLDocument::createFromString('

      foobar

      ', LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); static::assertInstanceOf(HTMLElement::class, $element->documentElement); - static::assertEquals('foobar', ref('value') - ->domElementValue() - ->eval(array_to_row([ + static::assertEquals('foobar', (new FunctionContext(flow_context()))->eval( + ref('value')->domElementValue(), + [ 'value' => $element->documentElement, - ], schema(html_element_schema('value'))), flow_context())); + ], + schema(html_element_schema('value')), + )); } #[RequiresPhp('>= 8.4.0')] @@ -44,11 +46,13 @@ public function test_html_getting_simple_element_value(): void $element = HTMLDocument::createFromString('bar', LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR); static::assertInstanceOf(HTMLElement::class, $element->documentElement); - static::assertEquals('bar', ref('value') - ->domElementValue() - ->eval(array_to_row([ + static::assertEquals('bar', (new FunctionContext(flow_context()))->eval( + ref('value')->domElementValue(), + [ 'value' => $element->documentElement, - ], schema(html_element_schema('value'))), flow_context())); + ], + schema(html_element_schema('value')), + )); } public function test_xml_getting_element_value_with_children(): void @@ -57,11 +61,13 @@ public function test_xml_getting_element_value_with_children(): void $xml->loadXML('baz'); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertEquals('baz', ref('value') - ->domElementValue() - ->eval(array_to_row([ + static::assertEquals('baz', (new FunctionContext(flow_context()))->eval( + ref('value')->domElementValue(), + [ 'value' => $xml->documentElement->firstChild, - ], schema(xml_element_schema('value'))), flow_context())); + ], + schema(xml_element_schema('value')), + )); } public function test_xml_getting_simple_element_value(): void @@ -70,10 +76,12 @@ public function test_xml_getting_simple_element_value(): void $xml->loadXML('bar'); static::assertInstanceOf(DOMElement::class, $xml->documentElement); - static::assertEquals('bar', ref('value') - ->domElementValue() - ->eval(array_to_row([ + static::assertEquals('bar', (new FunctionContext(flow_context()))->eval( + ref('value')->domElementValue(), + [ 'value' => $xml->documentElement->firstChild, - ], schema(xml_element_schema('value'))), flow_context())); + ], + schema(xml_element_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DateTimeFormatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DateTimeFormatTest.php index 97295adc0c..05520d7c39 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DateTimeFormatTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/DateTimeFormatTest.php @@ -7,9 +7,9 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\date_time_format; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; @@ -22,21 +22,20 @@ final class DateTimeFormatTest extends FlowTestCase { public function test_date_time_format(): void { - static::assertEquals('2020-01-01 00:00:00', date_time_format(ref('date_time'), 'Y-m-d H:i:s')->eval( - array_to_row(['date_time' => new DateTimeImmutable( - '2020-01-01 00:00:00', - new DateTimeZone('UTC'), - )], schema(datetime_schema('date_time'))), - flow_context(), + static::assertEquals('2020-01-01 00:00:00', (new FunctionContext(flow_context()))->eval( + date_time_format(ref('date_time'), 'Y-m-d H:i:s'), + ['date_time' => new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC'))], + schema(datetime_schema('date_time')), )); } public function test_formatting_now(): void { - static::assertInstanceOf(DateTimeImmutable::class, now()->eval(array_to_row( + static::assertInstanceOf(DateTimeImmutable::class, (new FunctionContext(flow_context()))->eval( + now(), ['date_time' => new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC'))], schema(datetime_schema('date_time')), - ), flow_context())); + )); } public function test_invalid_date_time_format(): void @@ -44,8 +43,12 @@ public function test_invalid_date_time_format(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "object", got "string".'); - date_time_format(ref('date_time'), 'Y-m-d H:i:s')->eval(array_to_row([ - 'date_time' => '2020-01-01 00:00:00', - ], schema(str_schema('date_time'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + date_time_format(ref('date_time'), 'Y-m-d H:i:s'), + [ + 'date_time' => '2020-01-01 00:00:00', + ], + schema(str_schema('date_time')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureEndTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureEndTest.php index 1470a863d5..92c440cab7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureEndTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureEndTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,26 +17,20 @@ final class EnsureEndTest extends FlowTestCase { public function test_empty_string_with_suffix(): void { - $result = ref('str') - ->ensureEnd('_suffix') - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); - - static::assertEquals('_suffix', $result); + static::assertEquals('_suffix', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureEnd('_suffix'), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_null_suffix(): void { - $result = ref('str') - ->ensureEnd(ref('suffix')) - ->eval( - array_to_row( - ['str' => 'hello', 'suffix' => null], - schema(str_schema('str'), str_schema('suffix', nullable: true)), - ), - flow_context(), - ); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureEnd(ref('suffix')), + ['str' => 'hello', 'suffix' => null], + schema(str_schema('str'), str_schema('suffix', nullable: true)), + )); } public function test_null_value(): void @@ -44,52 +38,46 @@ public function test_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('EnsureEnd function requires non-null value'); - $result = ref('str') - ->ensureEnd('_suffix') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); - - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->ensureEnd('_suffix'), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_string_already_ends_with_suffix(): void { - $result = ref('str') - ->ensureEnd('.txt') - ->eval(array_to_row(['str' => 'document.txt'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('document.txt', $result); + static::assertEquals('document.txt', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureEnd('.txt'), + ['str' => 'document.txt'], + schema(str_schema('str')), + )); } public function test_string_doesnt_end_with_suffix(): void { - $result = ref('str') - ->ensureEnd('.txt') - ->eval(array_to_row(['str' => 'document'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('document.txt', $result); + static::assertEquals('document.txt', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureEnd('.txt'), + ['str' => 'document'], + schema(str_schema('str')), + )); } public function test_string_with_empty_suffix(): void { - $result = ref('str') - ->ensureEnd('') - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureEnd(''), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_with_scalar_function_parameter(): void { - $result = ref('str') - ->ensureEnd(ref('suffix')) - ->eval( - array_to_row( - ['str' => 'document', 'suffix' => '.pdf'], - schema(str_schema('str'), str_schema('suffix')), - ), - flow_context(), - ); - - static::assertEquals('document.pdf', $result); + static::assertEquals('document.pdf', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureEnd(ref('suffix')), + ['str' => 'document', 'suffix' => '.pdf'], + schema(str_schema('str'), str_schema('suffix')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureStartTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureStartTest.php index 7e18ba2ca6..edb27d5484 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureStartTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnsureStartTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,26 +17,20 @@ final class EnsureStartTest extends FlowTestCase { public function test_empty_string_with_prefix(): void { - $result = ref('str') - ->ensureStart('prefix_') - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); - - static::assertEquals('prefix_', $result); + static::assertEquals('prefix_', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureStart('prefix_'), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_null_prefix(): void { - $result = ref('str') - ->ensureStart(ref('prefix')) - ->eval( - array_to_row( - ['str' => 'hello', 'prefix' => null], - schema(str_schema('str'), str_schema('prefix', nullable: true)), - ), - flow_context(), - ); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureStart(ref('prefix')), + ['str' => 'hello', 'prefix' => null], + schema(str_schema('str'), str_schema('prefix', nullable: true)), + )); } public function test_null_value(): void @@ -44,52 +38,46 @@ public function test_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('EnsureStart function requires non-null value'); - $result = ref('str') - ->ensureStart('prefix_') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); - - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->ensureStart('prefix_'), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_string_already_starts_with_prefix(): void { - $result = ref('str') - ->ensureStart('https://') - ->eval(array_to_row(['str' => 'https://example.com'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('https://example.com', $result); + static::assertEquals('https://example.com', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureStart('https://'), + ['str' => 'https://example.com'], + schema(str_schema('str')), + )); } public function test_string_doesnt_start_with_prefix(): void { - $result = ref('str') - ->ensureStart('https://') - ->eval(array_to_row(['str' => 'example.com'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('https://example.com', $result); + static::assertEquals('https://example.com', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureStart('https://'), + ['str' => 'example.com'], + schema(str_schema('str')), + )); } public function test_string_with_empty_prefix(): void { - $result = ref('str') - ->ensureStart('') - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureStart(''), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_with_scalar_function_parameter(): void { - $result = ref('str') - ->ensureStart(ref('prefix')) - ->eval( - array_to_row( - ['str' => 'example.com', 'prefix' => 'https://'], - schema(str_schema('str'), str_schema('prefix')), - ), - flow_context(), - ); - - static::assertEquals('https://example.com', $result); + static::assertEquals('https://example.com', (new FunctionContext(flow_context()))->eval( + ref('str')->ensureStart(ref('prefix')), + ['str' => 'example.com', 'prefix' => 'https://'], + schema(str_schema('str'), str_schema('prefix')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumNameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumNameTest.php index 466a5ac3bf..613114484b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumNameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumNameTest.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\Fixtures\Enum\BackedIntEnum; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; @@ -12,7 +13,6 @@ use PHPUnit\Framework\Attributes\TestWith; use UnitEnum; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\enum_name; use function Flow\ETL\DSL\enum_schema; @@ -26,7 +26,11 @@ final class EnumNameTest extends FlowTestCase { public function test_enum_name_accepts_literal_enum(): void { - static::assertSame('one', enum_name(BackedStringEnum::one)->eval(array_to_row([], schema()), flow_context())); + static::assertSame('one', (new FunctionContext(flow_context()))->eval( + enum_name(BackedStringEnum::one), + [], + schema(), + )); } public function test_enum_name_carries_string_type(): void @@ -36,11 +40,13 @@ public function test_enum_name_carries_string_type(): void public function test_enum_name_from_scalar_function_chain(): void { - static::assertSame('one', ref('e') - ->enumName() - ->eval(array_to_row([ + static::assertSame('one', (new FunctionContext(flow_context()))->eval( + ref('e')->enumName(), + [ 'e' => BackedIntEnum::one, - ], schema(enum_schema('e', BackedIntEnum::class))), flow_context())); + ], + schema(enum_schema('e', BackedIntEnum::class)), + )); } #[TestWith([BackedStringEnum::one])] @@ -48,8 +54,11 @@ public function test_enum_name_from_scalar_function_chain(): void #[TestWith([BasicEnum::one])] public function test_enum_name_returns_case_name(UnitEnum $enum): void { - static::assertSame('one', enum_name(ref('e')) - ->eval(array_to_row(['e' => $enum], schema(enum_schema('e', $enum::class))), flow_context())); + static::assertSame('one', (new FunctionContext(flow_context()))->eval( + enum_name(ref('e')), + ['e' => $enum], + schema(enum_schema('e', $enum::class)), + )); } #[TestWith([null])] @@ -61,6 +70,6 @@ public function test_enum_name_throws_in_strict_mode(mixed $input): void $this->expectExceptionMessage('EnumName function requires a UnitEnum value'); $context = flow_context(config()); - enum_name($input)->eval(array_to_row([], schema()), $context); + (new FunctionContext($context))->eval(enum_name($input), [], schema()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumValueTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumValueTest.php index d27f331555..ab6789320e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumValueTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EnumValueTest.php @@ -8,6 +8,7 @@ use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\Fixtures\Enum\BackedIntEnum; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; @@ -15,7 +16,6 @@ use PHPUnit\Framework\Attributes\TestWith; use UnitEnum; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\enum_schema; use function Flow\ETL\DSL\enum_value; @@ -31,24 +31,33 @@ final class EnumValueTest extends FlowTestCase { public function test_enum_value_accepts_literal_enum(): void { - static::assertSame(1, enum_value(BackedIntEnum::one)->eval(array_to_row([], schema()), flow_context())); + static::assertSame(1, (new FunctionContext(flow_context()))->eval( + enum_value(BackedIntEnum::one), + [], + schema(), + )); } public function test_enum_value_from_scalar_function_chain(): void { - static::assertSame(1, ref('e') - ->enumValue() - ->eval(array_to_row([ + static::assertSame(1, (new FunctionContext(flow_context()))->eval( + ref('e')->enumValue(), + [ 'e' => BackedIntEnum::one, - ], schema(enum_schema('e', BackedIntEnum::class))), flow_context())); + ], + schema(enum_schema('e', BackedIntEnum::class)), + )); } #[TestWith([BackedStringEnum::one, 'one'])] #[TestWith([BackedIntEnum::one, 1])] public function test_enum_value_returns_backing_value(UnitEnum $enum, int|string $expected): void { - static::assertSame($expected, enum_value(ref('e')) - ->eval(array_to_row(['e' => $enum], schema(enum_schema('e', $enum::class))), flow_context())); + static::assertSame($expected, (new FunctionContext(flow_context()))->eval( + enum_value(ref('e')), + ['e' => $enum], + schema(enum_schema('e', $enum::class)), + )); } #[TestWith([BasicEnum::one])] @@ -61,7 +70,7 @@ public function test_enum_value_throws_in_strict_mode(mixed $input): void $this->expectExceptionMessage('EnumValue function requires a BackedEnum value'); $context = flow_context(config()); - enum_value($input)->eval(array_to_row([], schema()), $context); + (new FunctionContext($context))->eval(enum_value($input), [], schema()); } public function test_a_non_enum_operand_is_refused_at_bind(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php index c340e3c6f8..a144742a98 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php @@ -4,48 +4,129 @@ namespace Flow\ETL\Tests\Unit\Function; +use DateInterval; +use DateTimeImmutable; +use DateTimeZone; +use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\FlowTestCase; +use Flow\Types\Exception\InvalidArgumentException as TypesInvalidArgumentException; +use Flow\Types\Type; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\definition_from_type; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; 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\Types\DSL\type_date; +use function Flow\Types\DSL\type_datetime; +use function Flow\Types\DSL\type_enum; +use function Flow\Types\DSL\type_json; +use function Flow\Types\DSL\type_time; +use function Flow\Types\DSL\type_uuid; final class EqualsTest extends FlowTestCase { public function test_null_operand_yields_null(): void { - static::assertNull( - ref('a') - ->equals(lit(1)) - ->eval(array_to_row(['a' => null], schema(str_schema('a', nullable: true))), flow_context()), - ); - static::assertNull( - ref('a') - ->equals(ref('b')) - ->eval( - array_to_row( - ['a' => null, 'b' => null], - schema(str_schema('a', nullable: true), str_schema('b', nullable: true)), - ), - flow_context(), - ), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('a')->equals(lit(1)), + ['a' => null], + schema(str_schema('a', nullable: true)), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('a')->equals(ref('b')), + ['a' => null, 'b' => null], + schema(str_schema('a', nullable: true), str_schema('b', nullable: true)), + )); } public function test_equal_values(): void { - static::assertTrue( - ref('a')->equals(lit(1))->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context()), - ); - static::assertTrue( - ref('a')->equals(lit('x'))->eval(array_to_row(['a' => 'x'], schema(str_schema('a'))), flow_context()), - ); - static::assertFalse( - ref('a')->equals(lit(2))->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('a')->equals(lit(1)), + ['a' => 1], + schema(int_schema('a')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('a')->equals(lit('x')), + ['a' => 'x'], + schema(str_schema('a')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('a')->equals(lit(2)), + ['a' => 1], + schema(int_schema('a')), + )); + } + + /** + * @return Generator, mixed, mixed, bool}> + */ + public static function values_of_one_type(): Generator + { + yield 'uuid' => [ + type_uuid(), + '00000000-0000-4000-8000-000000000001', + '00000000-0000-4000-8000-000000000001', + true, + ]; + yield 'other uuid' => [ + type_uuid(), + '00000000-0000-4000-8000-000000000001', + '00000000-0000-4000-8000-000000000002', + false, + ]; + yield 'json' => [type_json(), '{"a":1,"b":2}', '{"a":1,"b":2}', true]; + yield 'json compares its stored text' => [type_json(), '{"a":1,"b":2}', '{"b":2,"a":1}', false]; + yield 'enum' => [type_enum(BackedStringEnum::class), BackedStringEnum::one, BackedStringEnum::one, true]; + yield 'datetime of the same instant in another zone' => [ + type_datetime(), + new DateTimeImmutable('2024-01-01 12:00:00', new DateTimeZone('UTC')), + new DateTimeImmutable('2024-01-01 13:00:00', new DateTimeZone('Europe/Warsaw')), + true, + ]; + yield 'date' => [type_date(), new DateTimeImmutable('2024-01-01'), new DateTimeImmutable('2024-01-01'), true]; + yield 'time' => [type_time(), new DateInterval('PT60M'), new DateInterval('PT1H'), true]; + } + + /** + * @param Type $type + */ + #[DataProvider('values_of_one_type')] + public function test_values_of_one_type_compare_by_value(Type $type, mixed $left, mixed $right, bool $equal): void + { + static::assertSame($equal, (new FunctionContext(flow_context()))->eval( + ref('a')->equals(ref('b')), + ['a' => $left, 'b' => $right], + schema(definition_from_type('a', $type), definition_from_type('b', $type)), + )); + } + + public function test_a_datetime_equals_a_literal_of_the_same_instant_in_another_zone(): void + { + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('a')->equals(lit(new DateTimeImmutable('2024-01-01 13:00:00', new DateTimeZone('Europe/Warsaw')))), + ['a' => new DateTimeImmutable('2024-01-01 12:00:00', new DateTimeZone('UTC'))], + schema(definition_from_type('a', type_datetime())), + )); + } + + public function test_a_uuid_is_not_comparable_with_a_string(): void + { + $this->expectException(TypesInvalidArgumentException::class); + $this->expectExceptionMessage("Can't compare '(uuid == string)' due to data type mismatch"); + + (new ReferenceResolver()) + ->resolve( + ref('u')->equals(lit('00000000-0000-4000-8000-000000000001')), + schema(definition_from_type('u', type_uuid())), + ) + ->returns(); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ResultColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ResultColumnTest.php new file mode 100644 index 0000000000..c8c8c78729 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ResultColumnTest.php @@ -0,0 +1,151 @@ +of(lit(5), [5, null]); + + static::assertSame([5, null], $column->values()); + static::assertEquals(type_integer(), $column->type()); + } + + public function test_an_unresolved_tree_throws(): void + { + $this->expectException(InvalidLogicException::class); + + (new ResultColumn())->of(ref('a'), [1]); + } + + public function test_casts_each_value_into_the_returned_type(): void + { + static::assertSame([5, 6], (new ResultColumn())->of(lit(1), ['5', 6])->values()); + } + + public function test_is_a_php_column_whatever_the_configured_backend(): void + { + static::assertInstanceOf(ScalarColumn::class, (new ResultColumn())->of(lit(1), [1, 2])); + } + + public function test_null_type_builds_a_null_column(): void + { + $column = (new ResultColumn())->of(lit(null), [null, null]); + + static::assertEquals(type_null(), $column->type()); + static::assertSame(2, $column->nullCount()); + } + + public function test_refusal_names_the_row_of_the_value(): void + { + try { + (new ResultColumn())->of(lit(1), [1, 2, 'x']); + static::fail('expected a SchemaMismatchException'); + } catch (SchemaMismatchException $e) { + static::assertSame(2, $e->rowIndex); + } + } + + public function test_type_without_a_column_kind_is_an_untyped_column(): void + { + $column = (new ResultColumn())->of(call(lit('strval'), type_instance_of(ArrayObject::class)), [ + new ArrayObject(), + null, + ]); + + static::assertInstanceOf(ValueColumn::class, $column); + static::assertSame(2, $column->count()); + } + + public function test_underivable_return_is_an_untyped_column(): void + { + $function = (new ReferenceResolver())->resolve( + ref('j')->jsonDecode()->arrayGet('name'), + schema(json_schema('j')), + ); + + $column = (new ResultColumn())->of($function, ['a', ['b' => 1]]); + + static::assertInstanceOf(ValueColumn::class, $column); + static::assertSame(['a', ['b' => 1]], $column->values()); + } + + /** + * @return Generator, bool}> + */ + public static function intermediates(): Generator + { + yield 'integer' => [type_integer(), true]; + yield 'list of structures' => [type_list(type_structure(['a' => type_string()])), true]; + yield 'untyped array' => [type_array(), false]; + yield 'list of untyped arrays' => [type_list(type_array()), false]; + yield 'xml' => [type_xml(), false]; + yield 'xml element in a map' => [type_map(type_string(), type_xml_element()), false]; + yield 'html element in a structure' => [type_structure(['a' => type_optional(type_html_element())]), false]; + yield 'html in a list' => [type_list(type_html()), false]; + yield 'mixed' => [type_mixed(), false]; + } + + /** + * @param Type $type + */ + #[DataProvider('intermediates')] + public function test_a_typed_column_holds_an_intermediate_only_when_it_keeps_the_values( + Type $type, + bool $holds, + ): void { + static::assertSame($holds, (new ResultColumn())->holdsLosslessly($type)); + } + + public function test_an_untyped_array_keeps_its_objects(): void + { + $object = new ArrayObject(); + $column = (new ResultColumn())->typed(type_optional(type_array()), [[$object, 'count']]); + + static::assertInstanceOf(ValueColumn::class, $column); + static::assertSame([[$object, 'count']], $column->values()); + } + + public function test_lists_of_an_expand_are_a_list_column(): void + { + $column = (new ResultColumn())->lists(lit(1), [[1, 2], []]); + + static::assertEquals(type_list(type_integer()), $column->type()); + static::assertSame([[1, 2], []], $column->values()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ReturnTypesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ReturnTypesTest.php new file mode 100644 index 0000000000..a36b1861cb --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ReturnTypesTest.php @@ -0,0 +1,60 @@ + 1]], [['id' => 2], ['id' => 3]], [['id' => 4]]] as $batch) { + static::assertSame( + array_fill(0, count($batch), 1), + $function->eval(array_to_rows($batch, schema(int_schema('id'))), flow_context())->values(), + ); + } + + static::assertSame(1, $function->derivations); + } + + public function test_a_type_that_cannot_be_derived_is_tried_once(): void + { + $function = new ReturnsSpyFunction(derivable: false); + + foreach ([[['id' => 1]], [['id' => 2]]] as $batch) { + static::assertInstanceOf(ValueColumn::class, $function->eval( + array_to_rows($batch, schema(int_schema('id'))), + flow_context(), + )); + } + + static::assertNull(ReturnTypes::of($function)); + static::assertSame(1, $function->derivations); + } + + public function test_every_node_derives_its_own_type(): void + { + $first = new ReturnsSpyFunction(); + $second = new ReturnsSpyFunction(); + + static::assertSame('integer', ReturnTypes::of($first)?->toString()); + static::assertSame('integer', ReturnTypes::of($second)?->toString()); + static::assertSame(1, $first->derivations); + static::assertSame(1, $second->derivations); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/SelectionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/SelectionTest.php new file mode 100644 index 0000000000..5070196b0c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/SelectionTest.php @@ -0,0 +1,76 @@ + 1, 'name' => 'a'], ['v' => 2, 'name' => 'b']], + schema(int_schema('v'), str_schema('name')), + ); + $spy = new FailingOnValuesFunction(ref('v')); + + $column = (new Selection([0, 1]))->evaluate( + (new ReferenceResolver())->resolve($spy, $rows->schema()), + $rows, + flow_context(), + ); + + static::assertSame([1, 2], $column->values()); + static::assertSame($rows, $spy->seen[0]); + } + + public function test_an_error_names_the_row_of_the_batch(): void + { + $rows = array_to_rows([['v' => 1], ['v' => 2], ['v' => 3], ['v' => 4]], schema(int_schema('v'))); + + try { + (new Selection([1, 3]))->evaluate( + (new ReferenceResolver())->resolve(new FailingOnValuesFunction(ref('v'), [4]), $rows->schema()), + $rows, + flow_context(), + ); + static::fail('expected an EvaluationException'); + } catch (EvaluationException $e) { + static::assertSame(3, $e->rowIndex); + static::assertSame('fails on 4 (row 3)', $e->getMessage()); + } + } + + public function test_a_subset_holds_only_the_selected_rows_of_the_referenced_columns(): void + { + $rows = array_to_rows( + [['v' => 1, 'name' => 'a'], ['v' => 2, 'name' => 'b'], ['v' => 3, 'name' => 'c']], + schema(int_schema('v'), str_schema('name')), + ); + $spy = new FailingOnValuesFunction(ref('v')); + + $column = (new Selection([0, 2]))->evaluate( + (new ReferenceResolver())->resolve($spy, $rows->schema()), + $rows, + flow_context(), + ); + + static::assertSame([1, 3], $column->values()); + static::assertSame(['v'], array_keys($spy->seen[0]->columns())); + static::assertSame(2, $spy->seen[0]->count()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/TolerantEvaluationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/TolerantEvaluationTest.php new file mode 100644 index 0000000000..265a9330e6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/TolerantEvaluationTest.php @@ -0,0 +1,101 @@ + [], 'values' => []], + (new TolerantEvaluation())->evaluate( + (new ReferenceResolver())->resolve(new FailingOnValuesFunction(ref('id')), $rows->schema()), + $rows, + flow_context(), + ), + ); + } + + public function test_every_row_evaluates_in_one_batch_when_none_fails(): void + { + $spy = new FailingOnValuesFunction(ref('id')); + $rows = IdRows::batches(range(1, 3))->current(); + + static::assertSame( + ['failed' => [], 'values' => [0 => 1, 1 => 2, 2 => 3]], + (new TolerantEvaluation())->evaluate( + (new ReferenceResolver())->resolve($spy, $rows->schema()), + $rows, + flow_context(), + ), + ); + static::assertSame(1, $spy->evals); + } + + public function test_failing_rows_are_reported_and_left_out_of_the_values(): void + { + $spy = new FailingOnValuesFunction(ref('id'), [2, 4]); + $rows = IdRows::batches(range(1, 5))->current(); + + static::assertEquals( + ['failed' => [1 => true, 3 => true], 'values' => [0 => 1, 2 => 3, 4 => 5]], + (new TolerantEvaluation())->evaluate( + (new ReferenceResolver())->resolve($spy, $rows->schema()), + $rows, + flow_context(), + ), + ); + static::assertSame(3, $spy->evals); + } + + public function test_rows_past_the_retry_limit_go_one_by_one(): void + { + $spy = new FailingOnValuesFunction(ref('id'), range(1, 9)); + $rows = IdRows::batches(range(1, 10))->current(); + + $evaluated = (new TolerantEvaluation())->evaluate( + (new ReferenceResolver())->resolve($spy, $rows->schema()), + $rows, + flow_context(), + ); + + static::assertSame(range(0, 8), array_keys($evaluated['failed'])); + static::assertSame([9 => 10], $evaluated['values']); + static::assertSame(TolerantEvaluation::RETRIES + 2, $spy->evals); + } + + public function test_row_by_row_evaluates_each_given_row_alone(): void + { + $spy = new FailingOnValuesFunction(ref('id'), [2]); + $rows = IdRows::batches(range(1, 4))->current(); + + static::assertSame( + ['failed' => [1 => true], 'values' => [0 => 1, 3 => 4]], + (new TolerantEvaluation())->rowByRow( + (new ReferenceResolver())->resolve($spy, $rows->schema()), + $rows, + [0, 1, 3], + flow_context(), + ), + ); + static::assertSame(3, $spy->evals); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ExistsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ExistsTest.php index adf2e082e4..a80b3c4296 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ExistsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ExistsTest.php @@ -5,50 +5,103 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Function\Exists; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Double\FailingOnValuesFunction; use Flow\ETL\Tests\FlowTestCase; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\exists; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; 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 in_array; +use function range; final class ExistsTest extends FlowTestCase { public function test_a_throwing_operand_means_the_reference_does_not_exist(): void { - static::assertFalse((new Exists(ref('value')->upper()))->eval(array_to_row([ - 'value' => 1, - ], schema(int_schema('value'))), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval( + new Exists(ref('value')->upper()), + [ + 'value' => 1, + ], + schema(int_schema('value')), + )); } public function test_if_reference_exists(): void { - static::assertTrue( - ref('value') - ->exists() - ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('value')->exists(), + ['value' => 'test'], + schema(str_schema('value')), + )); } public function test_that_lit_function_exists(): void { - static::assertTrue((new Exists(lit('val')))->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval(new Exists(lit('val')), [], schema())); } public function test_that_null_reference_to_null_entry_exists(): void { - static::assertTrue( - ref('value') - ->exists() - ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('value')->exists(), + ['value' => null], + schema(str_schema('value', nullable: true)), + )); } public function test_that_reference_does_not_exists(): void { - static::assertFalse(ref('value')->exists()->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval(ref('value')->exists(), [], schema())); + } + + /** + * @return Generator, string, int}> + */ + public static function failing_rows(): Generator + { + yield 'one failing row: one retry' => [[3], FailingOnValuesFunction::WITH_ROW, 2]; + yield 'three failing rows: three retries' => [[2, 4, 6], FailingOnValuesFunction::WITH_ROW, 4]; + yield 'twelve failing rows: eight batch evals, then each remaining row alone' => [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + FailingOnValuesFunction::WITH_ROW, + 8 + 6, + ]; + yield 'a failure without a row: each row alone' => [[3], FailingOnValuesFunction::WITHOUT_ROW, 1 + 14]; + } + + /** + * @param list $failing + */ + #[DataProvider('failing_rows')] + public function test_only_the_failing_rows_are_false(array $failing, string $failure, int $evals): void + { + $spy = new FailingOnValuesFunction(ref('v'), $failing, $failure); + $rows = array_to_rows( + array_map(static fn(int $v): array => ['v' => $v], range(1, 14)), + schema(int_schema('v')), + ); + + $values = exists($spy)->eval($rows, flow_context())->values(); + + static::assertSame(array_map(static fn(int $v): bool => !in_array($v, $failing, true), range(1, 14)), $values); + static::assertSame($evals, $spy->evals); + } + + public function test_a_reference_is_a_schema_fact(): void + { + $rows = array_to_rows([['v' => 1], ['v' => 2]], schema(int_schema('v'))); + + static::assertSame([true, true], exists(ref('v'))->eval($rows, flow_context())->values()); + static::assertSame([false, false], exists(ref('missing'))->eval($rows, flow_context())->values()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/FirstTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/FirstTest.php index 85a638cb40..a1bb30abf7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/FirstTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/FirstTest.php @@ -4,13 +4,16 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\first; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\last; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -26,13 +29,17 @@ public function test_aggregation_firs_value(): void { $aggregator = first(ref('int')); - $aggregator->aggregate(array_to_row([ - 'not_int' => null, - ], schema(str_schema('not_int', nullable: true))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'not_int' => null, + ]], schema(str_schema('not_int', nullable: true))), + [0], + flow_context(), + ); + $aggregator->aggregate(array_to_rows([['int' => '10']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '20']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '55']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '25']], schema(str_schema('int'))), [0], flow_context()); static::assertSame('10', $aggregator->value()); } @@ -67,4 +74,55 @@ public function test_first_over_an_int_column_declares_optional_integer(): void ->toString(), ); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = first(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [1, 2, 3, 4]), schema(int_schema('v'))), + [1, 3], + flow_context(), + ); + + static::assertSame(2, $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 1, + 2, + 3, + 4, + ]), schema(int_schema('v'))); + $onePass = first(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = first(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = first(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + first(ref('v'))->merge(last(ref('v')), flow_context()); + } + + public function test_merge_into_an_empty_half_takes_the_other_value(): void + { + $rows = array_to_rows([['v' => 7]], schema(int_schema('v'))); + $right = first(ref('v')); + $right->aggregate($rows, [0], flow_context()); + $left = first(ref('v')); + + $left->merge($right, flow_context()); + + static::assertSame(7, $left->value()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanEqualTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanEqualTest.php index 02923961e9..80daa88ae0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanEqualTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanEqualTest.php @@ -6,10 +6,10 @@ use DateInterval; use DateTimeImmutable; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; @@ -29,159 +29,165 @@ public function test_greater_than_equal_arrays(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->greaterThanEqual(lit([1, 0])) - ->eval(array_to_row(['v' => [1, 9]], schema(list_schema('v', type_list(type_integer())))), $context), - ); - static::assertTrue( - ref('v') - ->greaterThanEqual(lit([1, 0])) - ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThanEqual(lit([1, 9])) - ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit([1, 0])), + ['v' => [1, 9]], + schema(list_schema('v', type_list(type_integer()))), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit([1, 0])), + ['v' => [1, 0]], + schema(list_schema('v', type_list(type_integer()))), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit([1, 9])), + ['v' => [1, 0]], + schema(list_schema('v', type_list(type_integer()))), + )); } public function test_greater_than_equal_datetimes(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-06-01'), - ], schema(datetime_schema('v'))), $context), - ); - static::assertTrue( - ref('v') - ->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-01-01'), - ], schema(datetime_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThanEqual(lit(new DateTimeImmutable('2024-06-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-01-01'), - ], schema(datetime_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2024-06-01'), + ], + schema(datetime_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2024-01-01'), + ], + schema(datetime_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(new DateTimeImmutable('2024-06-01'))), + [ + 'v' => new DateTimeImmutable('2024-01-01'), + ], + schema(datetime_schema('v')), + )); } public function test_greater_than_equal_floats(): void { $context = flow_context(); - static::assertTrue( - ref('v')->greaterThanEqual(lit(1.5))->eval(array_to_row(['v' => 2.5], schema(float_schema('v'))), $context), - ); - static::assertTrue( - ref('v')->greaterThanEqual(lit(1.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->greaterThanEqual(lit(2.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(1.5)), + ['v' => 2.5], + schema(float_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(1.5)), + ['v' => 1.5], + schema(float_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(2.5)), + ['v' => 1.5], + schema(float_schema('v')), + )); } public function test_greater_than_equal_integers(): void { $context = flow_context(); - static::assertTrue( - ref('v')->greaterThanEqual(lit(10))->eval(array_to_row(['v' => 20], schema(int_schema('v'))), $context), - ); - static::assertTrue( - ref('v')->greaterThanEqual(lit(10))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->greaterThanEqual(lit(20))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(10)), + ['v' => 20], + schema(int_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(10)), + ['v' => 10], + schema(int_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(20)), + ['v' => 10], + schema(int_schema('v')), + )); } public function test_greater_than_equal_returns_null_for_null_array(): void { - static::assertNull( - ref('v') - ->greaterThanEqual(lit([1, 0])) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThanEqual(lit([1, 0])), + ['v' => null], + schema(list_schema('v', type_list(type_integer()), nullable: true)), + )); } public function test_greater_than_equal_returns_null_for_null_datetime(): void { - static::assertNull( - ref('v') - ->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThanEqual(lit(new DateTimeImmutable('2024-01-01'))), + ['v' => null], + schema(datetime_schema('v', nullable: true)), + )); } public function test_greater_than_equal_returns_null_for_null_left(): void { - static::assertNull( - ref('v') - ->greaterThanEqual(lit(10)) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThanEqual(lit(10)), + ['v' => null], + schema(str_schema('v', nullable: true)), + )); } public function test_greater_than_equal_returns_null_for_null_right(): void { - static::assertNull( - ref('v') - ->greaterThanEqual(ref('other')) - ->eval( - array_to_row( - ['v' => 10, 'other' => null], - schema(int_schema('v'), str_schema('other', nullable: true)), - ), - flow_context(), - ), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThanEqual(ref('other')), + ['v' => 10, 'other' => null], + schema(int_schema('v'), str_schema('other', nullable: true)), + )); } public function test_greater_than_equal_returns_null_for_null_string(): void { - static::assertNull( - ref('v') - ->greaterThanEqual(lit('a')) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThanEqual(lit('a')), + ['v' => null], + schema(str_schema('v', nullable: true)), + )); } public function test_greater_than_equal_returns_null_for_null_time_interval(): void { - static::assertNull( - ref('v') - ->greaterThanEqual(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThanEqual(lit(new DateInterval('PT1H'))), + ['v' => null], + schema(time_schema('v', nullable: true)), + )); } public function test_greater_than_equal_strings(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->greaterThanEqual(lit('apple')) - ->eval(array_to_row(['v' => 'banana'], schema(str_schema('v'))), $context), - ); - static::assertTrue( - ref('v') - ->greaterThanEqual(lit('apple')) - ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThanEqual(lit('banana')) - ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit('apple')), + ['v' => 'banana'], + schema(str_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit('apple')), + ['v' => 'apple'], + schema(str_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit('banana')), + ['v' => 'apple'], + schema(str_schema('v')), + )); } public function test_greater_than_equal_throws_on_incompatible_types(): void @@ -195,20 +201,20 @@ public function test_greater_than_equal_time_intervals(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->greaterThanEqual(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => new DateInterval('PT5H')], schema(time_schema('v'))), $context), - ); - static::assertTrue( - ref('v') - ->greaterThanEqual(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThanEqual(lit(new DateInterval('PT5H'))) - ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(new DateInterval('PT1H'))), + ['v' => new DateInterval('PT5H')], + schema(time_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(new DateInterval('PT1H'))), + ['v' => new DateInterval('PT1H')], + schema(time_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThanEqual(lit(new DateInterval('PT5H'))), + ['v' => new DateInterval('PT1H')], + schema(time_schema('v')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanTest.php index b9d7b0bb76..a5d92c5ab2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreaterThanTest.php @@ -6,10 +6,10 @@ use DateInterval; use DateTimeImmutable; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; @@ -28,168 +28,176 @@ final class GreaterThanTest extends FlowTestCase public function test_an_integer_column_compared_to_a_string_literal_still_works(): void { // Comparator::comparable(integer, string) stays deliberately loose - 5 > '3' keeps working. - static::assertTrue( - ref('a')->greaterThan(lit('3'))->eval(array_to_row(['a' => 5], schema(int_schema('a'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('a')->greaterThan(lit('3')), + ['a' => 5], + schema(int_schema('a')), + )); } public function test_greater_than_arrays(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->greaterThan(lit([1, 0])) - ->eval(array_to_row(['v' => [1, 9]], schema(list_schema('v', type_list(type_integer())))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThan(lit([1, 9])) - ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThan(lit([1, 0])) - ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit([1, 0])), + ['v' => [1, 9]], + schema(list_schema('v', type_list(type_integer()))), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit([1, 9])), + ['v' => [1, 0]], + schema(list_schema('v', type_list(type_integer()))), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit([1, 0])), + ['v' => [1, 0]], + schema(list_schema('v', type_list(type_integer()))), + )); } public function test_greater_than_datetimes(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->greaterThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-06-01'), - ], schema(datetime_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2023-06-01'), - ], schema(datetime_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-01-01'), - ], schema(datetime_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2024-06-01'), + ], + schema(datetime_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2023-06-01'), + ], + schema(datetime_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2024-01-01'), + ], + schema(datetime_schema('v')), + )); } public function test_greater_than_floats(): void { $context = flow_context(); - static::assertTrue( - ref('v')->greaterThan(lit(1.5))->eval(array_to_row(['v' => 2.5], schema(float_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->greaterThan(lit(2.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->greaterThan(lit(1.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(1.5)), + ['v' => 2.5], + schema(float_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(2.5)), + ['v' => 1.5], + schema(float_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(1.5)), + ['v' => 1.5], + schema(float_schema('v')), + )); } public function test_greater_than_integers(): void { $context = flow_context(); - static::assertTrue( - ref('v')->greaterThan(lit(10))->eval(array_to_row(['v' => 20], schema(int_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->greaterThan(lit(20))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->greaterThan(lit(10))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(10)), + ['v' => 20], + schema(int_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(20)), + ['v' => 10], + schema(int_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(10)), + ['v' => 10], + schema(int_schema('v')), + )); } public function test_greater_than_returns_null_for_null_left(): void { - static::assertNull( - ref('v') - ->greaterThan(lit(10)) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThan(lit(10)), + ['v' => null], + schema(str_schema('v', nullable: true)), + )); } public function test_greater_than_returns_null_for_null_right(): void { - static::assertNull( - ref('v') - ->greaterThan(ref('other')) - ->eval( - array_to_row( - ['v' => 10, 'other' => null], - schema(int_schema('v'), str_schema('other', nullable: true)), - ), - flow_context(), - ), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThan(ref('other')), + ['v' => 10, 'other' => null], + schema(int_schema('v'), str_schema('other', nullable: true)), + )); } public function test_greater_than_returns_null_for_null_string(): void { - static::assertNull( - ref('v') - ->greaterThan(lit('a')) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThan(lit('a')), + ['v' => null], + schema(str_schema('v', nullable: true)), + )); } public function test_greater_than_returns_null_for_null_datetime(): void { - static::assertNull( - ref('v') - ->greaterThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThan(lit(new DateTimeImmutable('2024-01-01'))), + ['v' => null], + schema(datetime_schema('v', nullable: true)), + )); } public function test_greater_than_returns_null_for_null_time_interval(): void { - static::assertNull( - ref('v') - ->greaterThan(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThan(lit(new DateInterval('PT1H'))), + ['v' => null], + schema(time_schema('v', nullable: true)), + )); } public function test_greater_than_returns_null_for_null_array(): void { - static::assertNull( - ref('v') - ->greaterThan(lit([1, 0])) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->greaterThan(lit([1, 0])), + ['v' => null], + schema(list_schema('v', type_list(type_integer()), nullable: true)), + )); } public function test_greater_than_strings(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->greaterThan(lit('apple')) - ->eval(array_to_row(['v' => 'banana'], schema(str_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThan(lit('banana')) - ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThan(lit('apple')) - ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit('apple')), + ['v' => 'banana'], + schema(str_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit('banana')), + ['v' => 'apple'], + schema(str_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit('apple')), + ['v' => 'apple'], + schema(str_schema('v')), + )); } public function test_greater_than_throws_on_incompatible_types(): void @@ -203,20 +211,20 @@ public function test_greater_than_time_intervals(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->greaterThan(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => new DateInterval('PT5H')], schema(time_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThan(lit(new DateInterval('PT5H'))) - ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->greaterThan(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(new DateInterval('PT1H'))), + ['v' => new DateInterval('PT5H')], + schema(time_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(new DateInterval('PT5H'))), + ['v' => new DateInterval('PT1H')], + schema(time_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->greaterThan(lit(new DateInterval('PT1H'))), + ['v' => new DateInterval('PT1H')], + schema(time_schema('v')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreatestTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreatestTest.php index 4fd1c94590..8bf15b7382 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreatestTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/GreatestTest.php @@ -7,9 +7,9 @@ use DateTimeImmutable; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\greatest; use function Flow\ETL\DSL\int_schema; @@ -34,7 +34,11 @@ public function test_greatest_value(): void { $greatest = greatest(10, 20, ref('int'), 40); - static::assertSame(55, $greatest->eval(array_to_row(['int' => 55], schema(int_schema('int'))), flow_context())); + static::assertSame(55, (new FunctionContext(flow_context()))->eval( + $greatest, + ['int' => 55], + schema(int_schema('int')), + )); } public function test_greatest_with_non_comparable_values(): void @@ -53,24 +57,36 @@ public function test_an_integer_and_a_string_column_have_no_common_type(): void public function test_nulls_are_skipped(): void { - static::assertSame(20, greatest(null, 20, ref('int'))->eval(array_to_row([ - 'int' => 4, - ], schema(int_schema('int'))), flow_context())); + static::assertSame(20, (new FunctionContext(flow_context()))->eval( + greatest(null, 20, ref('int')), + [ + 'int' => 4, + ], + schema(int_schema('int')), + )); } public function test_null_only_when_every_argument_is_null(): void { - static::assertNull(greatest(null, null)->eval(array_to_row([ - 'int' => 4, - ], schema(int_schema('int'))), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval( + greatest(null, null), + [ + 'int' => 4, + ], + schema(int_schema('int')), + )); } public function test_greatest_with_null(): void { $greatest = greatest(null, 20, ref('int'), 1257); - static::assertSame(1257, $greatest->eval(array_to_row([ - 'int' => 55, - ], schema(int_schema('int'))), flow_context())); + static::assertSame(1257, (new FunctionContext(flow_context()))->eval( + $greatest, + [ + 'int' => 55, + ], + schema(int_schema('int')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorAllTest.php index d356e00b66..791284d339 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorAllTest.php @@ -8,10 +8,10 @@ use Dom\HTMLDocument; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RequiredPHPVersionException; +use Flow\ETL\Tests\Context\FunctionContext; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\ref; @@ -24,9 +24,11 @@ final class HTMLQuerySelectorAllTest extends TestCase public function test_getting_element_for_older_versions(): void { $this->expectException(RequiredPHPVersionException::class); - ref('value') - ->htmlQuerySelectorAll('body div p') - ->eval(array_to_row(['value' => ''], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->htmlQuerySelectorAll('body div p'), + ['value' => ''], + schema(str_schema('value')), + ); } #[RequiresPhp('>= 8.4.0')] @@ -37,9 +39,11 @@ public function test_getting_elements_for_given_path(): void '
      foobar
      ', ); /** @var array $result */ - $result = ref('value') - ->htmlQuerySelectorAll('body div span') - ->eval(array_to_row(['value' => $html], schema(html_schema('value'))), flow_context()); + $result = (new FunctionContext(flow_context()))->eval( + ref('value')->htmlQuerySelectorAll('body div span'), + ['value' => $html], + schema(html_schema('value')), + ); static::assertCount(1, $result); static::assertInstanceOf(Element::class, $result[0]); } @@ -51,10 +55,11 @@ public function test_getting_null_when_nothing_found(): void $html = HTMLDocument::createFromString( '
      foobar
      ', ); - $result = ref('value') - ->htmlQuerySelectorAll('body div p') - ->eval(array_to_row(['value' => $html], schema(html_schema('value'))), flow_context()); - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->htmlQuerySelectorAll('body div p'), + ['value' => $html], + schema(html_schema('value')), + )); } #[RequiresPhp('>= 8.4.0')] @@ -63,8 +68,10 @@ public function test_invalid_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected one of'); - ref('value') - ->htmlQuerySelectorAll('body div span') - ->eval(array_to_row(['value' => ''], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->htmlQuerySelectorAll('body div span'), + ['value' => ''], + schema(str_schema('value')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorTest.php index d56e88559b..51b6c88711 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HTMLQuerySelectorTest.php @@ -8,10 +8,10 @@ use Dom\HTMLDocument; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RequiredPHPVersionException; +use Flow\ETL\Tests\Context\FunctionContext; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\ref; @@ -24,9 +24,11 @@ final class HTMLQuerySelectorTest extends TestCase public function test_getting_element_for_older_versions(): void { $this->expectException(RequiredPHPVersionException::class); - ref('value') - ->htmlQuerySelector('body div p') - ->eval(array_to_row(['value' => ''], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->htmlQuerySelector('body div p'), + ['value' => ''], + schema(str_schema('value')), + ); } #[RequiresPhp('>= 8.4.0')] @@ -36,10 +38,11 @@ public function test_getting_elements_for_given_path(): void $html = HTMLDocument::createFromString( '
      foobar
      ', ); - $result = ref('value') - ->htmlQuerySelector('body div span') - ->eval(array_to_row(['value' => $html], schema(html_schema('value'))), flow_context()); - static::assertInstanceOf(Element::class, $result); + static::assertInstanceOf(Element::class, (new FunctionContext(flow_context()))->eval( + ref('value')->htmlQuerySelector('body div span'), + ['value' => $html], + schema(html_schema('value')), + )); } #[RequiresPhp('>= 8.4.0')] @@ -49,10 +52,11 @@ public function test_getting_null_when_nothing_found(): void $html = HTMLDocument::createFromString( '
      foobar
      ', ); - $result = ref('value') - ->htmlQuerySelector('body div p') - ->eval(array_to_row(['value' => $html], schema(html_schema('value'))), flow_context()); - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->htmlQuerySelector('body div p'), + ['value' => $html], + schema(html_schema('value')), + )); } #[RequiresPhp('>= 8.4.0')] @@ -61,8 +65,10 @@ public function test_invalid_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected one of'); - ref('value') - ->htmlQuerySelector('body div span') - ->eval(array_to_row(['value' => ''], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->htmlQuerySelector('body div span'), + ['value' => ''], + schema(str_schema('value')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HashTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HashTest.php index 34ff8482c9..fabf3824b3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HashTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/HashTest.php @@ -6,9 +6,9 @@ use DateTimeImmutable; use Flow\ETL\Hash\NativePHPHash; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\concat; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; @@ -25,45 +25,55 @@ final class HashTest extends FlowTestCase { public function test_hashing_array_value(): void { - static::assertSame('4450cf82dc53848e2bbe9798b70b0a6a', ref('value') - ->hash() - ->eval(array_to_row(['value' => [ + static::assertSame('4450cf82dc53848e2bbe9798b70b0a6a', (new FunctionContext(flow_context()))->eval( + ref('value')->hash(), + ['value' => [ 'test', - ]], schema(list_schema('value', type_list(type_string())))), flow_context())); + ]], + schema(list_schema('value', type_list(type_string()))), + )); } public function test_hashing_concat(): void { static::assertSame( NativePHPHash::xxh128('test_test'), - hash(concat(ref('value'), lit('_'), ref('value')), new NativePHPHash('xxh128'))->eval(array_to_row([ - 'value' => 'test', - ], schema(str_schema('value'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + hash(concat(ref('value'), lit('_'), ref('value')), new NativePHPHash('xxh128')), + [ + 'value' => 'test', + ], + schema(str_schema('value')), + ), ); } public function test_hashing_datetime(): void { - static::assertSame('5347d10de38eb5570c044eb710a5120a', ref('value') - ->hash() - ->eval(array_to_row([ + static::assertSame('5347d10de38eb5570c044eb710a5120a', (new FunctionContext(flow_context()))->eval( + ref('value')->hash(), + [ 'value' => new DateTimeImmutable('2021-01-01'), - ], schema(datetime_schema('value'))), flow_context())); + ], + schema(datetime_schema('value')), + )); } public function test_hashing_null_value(): void { - static::assertNull( - ref('value') - ->hash() - ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->hash(), + ['value' => null], + schema(str_schema('value', nullable: true)), + )); } public function test_hashing_string_value(): void { - static::assertSame('6c78e0e3bd51d358d01e758642b85fb8', ref('value') - ->hash() - ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); + static::assertSame('6c78e0e3bd51d358d01e758642b85fb8', (new FunctionContext(flow_context()))->eval( + ref('value')->hash(), + ['value' => 'test'], + schema(str_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfLastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfLastTest.php index ed766cc772..45eb15ea0f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfLastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfLastTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; @@ -18,18 +18,20 @@ final class IndexOfLastTest extends FlowTestCase { public function test_index_of_last_basic(): void { - static::assertSame(9, ref('str') - ->indexOfLast('l') - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context())); + static::assertSame(9, (new FunctionContext(flow_context()))->eval( + ref('str')->indexOfLast('l'), + ['str' => 'hello world'], + schema(str_schema('str')), + )); } public function test_index_of_last_not_found(): void { - static::assertNull( - ref('str') - ->indexOfLast('x') - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->indexOfLast('x'), + ['str' => 'hello world'], + schema(str_schema('str')), + )); } public function test_index_of_last_throws_on_null_needle(): void @@ -37,15 +39,11 @@ public function test_index_of_last_throws_on_null_needle(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('IndexOfLast function requires non-null string and needle'); - ref('str') - ->indexOfLast(ref('needle')) - ->eval( - array_to_row( - ['str' => 'hello', 'needle' => null], - schema(str_schema('str'), str_schema('needle', nullable: true)), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('str')->indexOfLast(ref('needle')), + ['str' => 'hello', 'needle' => null], + schema(str_schema('str'), str_schema('needle', nullable: true)), + ); } public function test_index_of_last_throws_on_null_string(): void @@ -53,21 +51,19 @@ public function test_index_of_last_throws_on_null_string(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('IndexOfLast function requires non-null string and needle'); - ref('str') - ->indexOfLast('l') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->indexOfLast('l'), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_index_of_last_with_scalar_function_parameters(): void { - static::assertSame(9, ref('str') - ->indexOfLast(ref('needle'), ref('ignore_case')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'L', 'ignore_case' => true], - schema(str_schema('str'), str_schema('needle'), bool_schema('ignore_case')), - ), - flow_context(), - )); + static::assertSame(9, (new FunctionContext(flow_context()))->eval( + ref('str')->indexOfLast(ref('needle'), ref('ignore_case')), + ['str' => 'hello world', 'needle' => 'L', 'ignore_case' => true], + schema(str_schema('str'), str_schema('needle'), bool_schema('ignore_case')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfTest.php index c416db60be..df96877f7b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IndexOfTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,23 +17,29 @@ final class IndexOfTest extends FlowTestCase { public function test_index_of(): void { - static::assertSame(5, ref('str') - ->indexOf('x', offset: 5) - ->eval(array_to_row(['str' => 'AbBAsxa'], schema(str_schema('str'))), flow_context())); + static::assertSame(5, (new FunctionContext(flow_context()))->eval( + ref('str')->indexOf('x', offset: 5), + ['str' => 'AbBAsxa'], + schema(str_schema('str')), + )); - static::assertSame(0, ref('str') - ->indexOf('A', ignoreCase: true) - ->eval(array_to_row(['str' => 'abbbbb'], schema(str_schema('str'))), flow_context())); + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + ref('str')->indexOf('A', ignoreCase: true), + ['str' => 'abbbbb'], + schema(str_schema('str')), + )); - static::assertSame(5, ref('str') - ->indexOf('x', offset: 5) - ->eval(array_to_row(['str' => 'AbBAsxa'], schema(str_schema('str'))), flow_context())); + static::assertSame(5, (new FunctionContext(flow_context()))->eval( + ref('str')->indexOf('x', offset: 5), + ['str' => 'AbBAsxa'], + schema(str_schema('str')), + )); - static::assertNull( - ref('str') - ->indexOf('x', offset: 2) - ->eval(array_to_row(['str' => 'Abba'], schema(str_schema('str'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->indexOf('x', offset: 2), + ['str' => 'Abba'], + schema(str_schema('str')), + )); } public function test_index_of_throws_on_null_needle(): void @@ -41,15 +47,11 @@ public function test_index_of_throws_on_null_needle(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('IndexOf function requires non-null string and needle'); - ref('str') - ->indexOf(ref('needle')) - ->eval( - array_to_row( - ['str' => 'x', 'needle' => null], - schema(str_schema('str'), str_schema('needle', nullable: true)), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('str')->indexOf(ref('needle')), + ['str' => 'x', 'needle' => null], + schema(str_schema('str'), str_schema('needle', nullable: true)), + ); } public function test_index_of_throws_on_null_string(): void @@ -57,8 +59,10 @@ public function test_index_of_throws_on_null_string(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('IndexOf function requires non-null string and needle'); - ref('str') - ->indexOf('x') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->indexOf('x'), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsEmptyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsEmptyTest.php index dd336c3153..8e96244a90 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsEmptyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsEmptyTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -16,31 +16,37 @@ final class IsEmptyTest extends FlowTestCase { public function test_is_empty_empty_string(): void { - static::assertTrue( - ref('str')->isEmpty()->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('str')->isEmpty(), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_is_empty_non_empty_string(): void { - static::assertFalse( - ref('str')->isEmpty()->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), - ); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('str')->isEmpty(), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_is_empty_returns_null_for_null_input(): void { - static::assertNull( - ref('str') - ->isEmpty() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->isEmpty(), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_is_empty_single_character_string(): void { - static::assertFalse( - ref('str')->isEmpty()->eval(array_to_row(['str' => 'a'], schema(str_schema('str'))), flow_context()), - ); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('str')->isEmpty(), + ['str' => 'a'], + schema(str_schema('str')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php index 9bb68873b0..b412d97a56 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php @@ -6,15 +6,30 @@ use DateInterval; use DateTimeImmutable; +use DateTimeZone; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; +use Flow\Types\Type; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\definition_from_type; use function Flow\ETL\DSL\flow_context; 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\Types\DSL\type_date; +use function Flow\Types\DSL\type_datetime; +use function Flow\Types\DSL\type_enum; +use function Flow\Types\DSL\type_json; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; +use function Flow\Types\DSL\type_string; +use function Flow\Types\DSL\type_time; +use function Flow\Types\DSL\type_uuid; final class IsInTest extends FlowTestCase { @@ -29,46 +44,53 @@ public function test_is_in_accepts_a_container_haystack_without_a_single_element ->returns() ->toString(), ); - static::assertTrue(lit('a')->isIn(lit([1, 'a']))->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval(lit('a')->isIn(lit([1, 'a'])), [], schema())); } public function test_is_in_matches_two_equal_datetimes(): void { // in_array(strict: true) compared these by identity and answered false - static::assertTrue( + static::assertTrue((new FunctionContext(flow_context()))->eval( lit(new DateTimeImmutable('2024-01-01 10:00:00')) - ->isIn(lit([new DateTimeImmutable('2024-01-01 10:00:00')])) - ->eval(array_to_row([], schema()), flow_context()), - ); + ->isIn(lit([new DateTimeImmutable('2024-01-01 10:00:00')])), + [], + schema(), + )); } - public function test_is_in_does_not_match_two_equal_date_intervals(): void + public function test_is_in_matches_two_equal_date_intervals_by_value(): void { - // Equals::eval() has a DateInterval arm and IsIn deliberately does not - static::assertTrue( - lit(new DateInterval('PT1H')) - ->equals(lit(new DateInterval('PT60M'))) - ->eval(array_to_row([], schema()), flow_context()), - ); - static::assertFalse( - lit(new DateInterval('PT1H')) - ->isIn(lit([new DateInterval('PT60M')])) - ->eval(array_to_row([], schema()), flow_context()), - ); + // a time list of the needle's type compares by the physical form, as equals() does + static::assertTrue((new FunctionContext(flow_context()))->eval( + lit(new DateInterval('PT1H'))->equals(lit(new DateInterval('PT60M'))), + [], + schema(), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + lit(new DateInterval('PT1H'))->isIn(lit([new DateInterval('PT60M')])), + [], + schema(), + )); } public function test_is_in_over_an_empty_haystack(): void { static::assertSame('boolean', lit('a')->isIn(lit([]))->returns()->toString()); - static::assertFalse(lit('a')->isIn(lit([]))->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval(lit('a')->isIn(lit([])), [], schema())); } public function test_is_in_agrees_with_equals_on_numeric_operands(): void { - $row = array_to_row(['a' => '1'], schema(str_schema('a'))); - - static::assertTrue(ref('a')->equals(lit(1))->eval($row, flow_context())); - static::assertTrue(ref('a')->isIn(lit([1]))->eval($row, flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('a')->equals(lit(1)), + ['a' => '1'], + schema(str_schema('a')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('a')->isIn(lit([1])), + ['a' => '1'], + schema(str_schema('a')), + )); } public function test_is_in_refuses_an_incomparable_element_type(): void @@ -83,26 +105,90 @@ public function test_is_in_refuses_an_incomparable_element_type(): void public function test_a_match_beats_a_null_element(): void { - static::assertTrue(lit(5)->isIn(lit([1, null, 5]))->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval(lit(5)->isIn(lit([1, null, 5])), [], schema())); } public function test_no_match_with_a_null_element_is_null(): void { - static::assertNull(lit(7)->isIn(lit([1, null, 5]))->eval(array_to_row([], schema()), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval(lit(7)->isIn(lit([1, null, 5])), [], schema())); } public function test_no_match_without_a_null_element_is_false(): void { - static::assertFalse(lit(7)->isIn(lit([1, 3, 5]))->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval(lit(7)->isIn(lit([1, 3, 5])), [], schema())); } public function test_a_null_needle_is_null(): void { - static::assertNull(lit(null)->isIn(lit([1, 3, 5]))->eval(array_to_row([], schema()), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval(lit(null)->isIn(lit([1, 3, 5])), [], schema())); } public function test_a_null_haystack_is_null(): void { - static::assertNull(lit(5)->isIn(lit(null))->eval(array_to_row([], schema()), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval(lit(5)->isIn(lit(null)), [], schema())); + } + + /** + * @return Generator, mixed, mixed, bool}> + */ + public static function values_of_one_type(): Generator + { + yield 'uuid' => [ + type_uuid(), + '00000000-0000-4000-8000-000000000001', + '00000000-0000-4000-8000-000000000001', + true, + ]; + yield 'other uuid' => [ + type_uuid(), + '00000000-0000-4000-8000-000000000001', + '00000000-0000-4000-8000-000000000002', + false, + ]; + yield 'json' => [type_json(), '{"a":1,"b":2}', '{"a":1,"b":2}', true]; + yield 'json compares its stored text' => [type_json(), '{"a":1,"b":2}', '{"b":2,"a":1}', false]; + yield 'enum' => [type_enum(BackedStringEnum::class), BackedStringEnum::one, BackedStringEnum::one, true]; + yield 'datetime of the same instant in another zone' => [ + type_datetime(), + new DateTimeImmutable('2024-01-01 12:00:00', new DateTimeZone('UTC')), + new DateTimeImmutable('2024-01-01 13:00:00', new DateTimeZone('Europe/Warsaw')), + true, + ]; + yield 'date' => [type_date(), new DateTimeImmutable('2024-01-01'), new DateTimeImmutable('2024-01-01'), true]; + yield 'time' => [type_time(), new DateInterval('PT60M'), new DateInterval('PT1H'), true]; + } + + /** + * @param Type $type + */ + #[DataProvider('values_of_one_type')] + public function test_a_list_of_the_needle_type_matches_by_value( + Type $type, + mixed $needle, + mixed $element, + bool $in, + ): void { + static::assertSame($in, (new FunctionContext(flow_context()))->eval( + ref('a')->isIn(ref('h')), + ['a' => $needle, 'h' => [$element]], + schema(definition_from_type('a', $type), definition_from_type('h', type_list($type))), + )); + } + + /** + * @param Type $type + */ + #[DataProvider('values_of_one_type')] + public function test_a_map_of_the_needle_type_matches_by_value( + Type $type, + mixed $needle, + mixed $element, + bool $in, + ): void { + static::assertSame($in, (new FunctionContext(flow_context()))->eval( + ref('a')->isIn(ref('h')), + ['a' => $needle, 'h' => ['k' => $element]], + schema(definition_from_type('a', $type), definition_from_type('h', type_map(type_string(), $type))), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsUtf8Test.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsUtf8Test.php index bd806a53a4..190565014c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsUtf8Test.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsUtf8Test.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -16,23 +16,25 @@ final class IsUtf8Test extends FlowTestCase { public function test_is_utf8_returns_null(): void { - static::assertNull( - ref('str') - ->isUtf8() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->isUtf8(), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_is_utf_8(): void { - static::assertTrue( - ref('str') - ->isUtf8() - ->eval(array_to_row(['str' => 'Lorem Ipsum'], schema(str_schema('str'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('str')->isUtf8(), + ['str' => 'Lorem Ipsum'], + schema(str_schema('str')), + )); - static::assertFalse( - ref('str')->isUtf8()->eval(array_to_row(['str' => "\xc3\x28"], schema(str_schema('str'))), flow_context()), - ); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('str')->isUtf8(), + ['str' => "\xc3\x28"], + schema(str_schema('str')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonDecodeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonDecodeTest.php index 95490ccbca..53b51b6181 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonDecodeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonDecodeTest.php @@ -4,10 +4,12 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; +use JsonException; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -20,9 +22,11 @@ public function test_json_decode_expression(): void { static::assertSame( ['value' => 1], - ref('value') - ->jsonDecode() - ->eval(array_to_row(['value' => '{"value": 1}'], schema(str_schema('value'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('value')->jsonDecode(), + ['value' => '{"value": 1}'], + schema(str_schema('value')), + ), ); } @@ -31,9 +35,25 @@ public function test_json_decode_expression_with_invalid_json(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('JsonDecode error: Syntax error'); - ref('value') - ->jsonDecode() - ->eval(array_to_row(['value' => '{"value": 1'], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->jsonDecode(), + ['value' => '{"value": 1'], + schema(str_schema('value')), + ); + } + + public function test_invalid_json_keeps_the_decoder_error_as_the_cause(): void + { + try { + (new FunctionContext(flow_context()))->eval( + ref('value')->jsonDecode(), + ['value' => '{"value": 1'], + schema(str_schema('value')), + ); + static::fail('Invalid JSON must be refused.'); + } catch (EvaluationException $e) { + static::assertInstanceOf(JsonException::class, $e->getPrevious()?->getPrevious()); + } } public function test_json_decode_on_non_json_value(): void @@ -41,7 +61,11 @@ public function test_json_decode_on_non_json_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('JsonDecode function requires string, array, or Json value'); - ref('value')->jsonDecode()->eval(array_to_row(['value' => 125], schema(int_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->jsonDecode(), + ['value' => 125], + schema(int_schema('value')), + ); } public function test_json_decode_on_scalar_json_throws(): void @@ -51,6 +75,10 @@ public function test_json_decode_on_scalar_json_throws(): void 'JsonDecode function requires JSON that decodes to an array, cast scalar JSON instead', ); - ref('value')->jsonDecode()->eval(array_to_row(['value' => '5'], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->jsonDecode(), + ['value' => '5'], + schema(str_schema('value')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonEncodeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonEncodeTest.php index a398cb67ae..18acd19570 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonEncodeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/JsonEncodeTest.php @@ -5,10 +5,10 @@ namespace Flow\ETL\Tests\Unit\Function; use DateTimeImmutable; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Value\Json; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -24,40 +24,46 @@ final class JsonEncodeTest extends FlowTestCase { public function test_json_encode_on_datetime(): void { - $result = ref('value') - ->jsonEncode() - ->eval(array_to_row([ + // json_encode() of a non-container operand declares string, so the encoded object is a string + static::assertSame('{"date":"2021-01-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"}', (new FunctionContext( + flow_context(), + ))->eval( + ref('value')->jsonEncode(), + [ 'value' => new DateTimeImmutable('2021-01-01'), - ], schema(datetime_schema('value'))), flow_context()); - - static::assertInstanceOf(Json::class, $result); - static::assertSame( - '{"date":"2021-01-01 00:00:00.000000","timezone_type":3,"timezone":"UTC"}', - $result->toString(), - ); + ], + schema(datetime_schema('value')), + )); } public function test_json_encode_on_integer(): void { - static::assertSame('125', ref('value') - ->jsonEncode() - ->eval(array_to_row(['value' => 125], schema(int_schema('value'))), flow_context())); + static::assertSame('125', (new FunctionContext(flow_context()))->eval( + ref('value')->jsonEncode(), + ['value' => 125], + schema(int_schema('value')), + )); } public function test_json_encode_on_string(): void { - static::assertSame('"test"', ref('value') - ->jsonEncode() - ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); + static::assertSame('"test"', (new FunctionContext(flow_context()))->eval( + ref('value')->jsonEncode(), + ['value' => 'test'], + schema(str_schema('value')), + )); } public function test_json_encode_on_valid_associative_array(): void { - $result = ref('value') - ->jsonEncode() - ->eval(array_to_row(['value' => [ + // @mago-ignore analysis:mixed-assignment + $result = (new FunctionContext(flow_context()))->eval( + ref('value')->jsonEncode(), + ['value' => [ 'value' => 1, - ]], schema(map_schema('value', type_map(type_string(), type_integer())))), flow_context()); + ]], + schema(map_schema('value', type_map(type_string(), type_integer()))), + ); static::assertInstanceOf(Json::class, $result); static::assertSame('{"value":1}', $result->toString()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LastTest.php index 2d17099a91..eab2e44197 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LastTest.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\first; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\last; @@ -26,13 +29,17 @@ public function test_aggregation_last_value(): void { $aggregator = last(ref('int')); - $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'not_int' => null, - ], schema(str_schema('not_int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '10']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '20']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '55']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '25']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'not_int' => null, + ]], schema(str_schema('not_int', nullable: true))), + [0], + flow_context(), + ); static::assertSame('25', $aggregator->value()); } @@ -67,4 +74,72 @@ public function test_last_over_an_int_column_declares_optional_integer(): void ->toString(), ); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = last(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [1, 2, 3, 4]), schema(int_schema('v'))), + [1, 3], + flow_context(), + ); + + static::assertSame(4, $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 1, + 2, + 3, + 4, + ]), schema(int_schema('v'))); + $onePass = last(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = last(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = last(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + last(ref('v'))->merge(first(ref('v')), flow_context()); + } + + public function test_merge_after_a_null_only_half_takes_the_null(): void + { + $rows = array_to_rows([ + ['v' => 1], + ['v' => 2], + ['v' => null], + ['v' => null], + ], schema(int_schema('v', nullable: true))); + $left = last(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = last(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertNull($left->value()); + } + + public function test_merge_with_an_empty_half_keeps_the_value(): void + { + $rows = array_to_rows([['v' => 1]], schema(int_schema('v'))); + $left = last(ref('v')); + $left->aggregate($rows, [0], flow_context()); + + $left->merge(last(ref('v')), flow_context()); + + static::assertSame(1, $left->value()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LeastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LeastTest.php index 70f0c7ee62..dab159f076 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LeastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LeastTest.php @@ -7,9 +7,9 @@ use DateTimeImmutable; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\least; @@ -46,22 +46,34 @@ public function test_an_integer_and_a_string_column_have_no_common_type(): void public function test_null_only_when_every_argument_is_null(): void { - static::assertNull(least(null, null)->eval(array_to_row([ - 'int' => 4, - ], schema(int_schema('int'))), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval( + least(null, null), + [ + 'int' => 4, + ], + schema(int_schema('int')), + )); } public function test_least_value(): void { $lest = least(10, 20, ref('int'), 40); - static::assertSame(10, $lest->eval(array_to_row(['int' => 55], schema(int_schema('int'))), flow_context())); + static::assertSame(10, (new FunctionContext(flow_context()))->eval( + $lest, + ['int' => 55], + schema(int_schema('int')), + )); } public function test_least_with_null(): void { - static::assertSame(4, least(null, 20, ref('int'), 1257)->eval(array_to_row([ - 'int' => 4, - ], schema(int_schema('int'))), flow_context())); + static::assertSame(4, (new FunctionContext(flow_context()))->eval( + least(null, 20, ref('int'), 1257), + [ + 'int' => 4, + ], + schema(int_schema('int')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanEqualTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanEqualTest.php index 948d63f315..7f3b0d1620 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanEqualTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanEqualTest.php @@ -6,10 +6,10 @@ use DateInterval; use DateTimeImmutable; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; @@ -29,159 +29,165 @@ public function test_less_than_equal_arrays(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->lessThanEqual(lit([1, 9])) - ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), - ); - static::assertTrue( - ref('v') - ->lessThanEqual(lit([1, 0])) - ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), - ); - static::assertFalse( - ref('v') - ->lessThanEqual(lit([1, 0])) - ->eval(array_to_row(['v' => [1, 9]], schema(list_schema('v', type_list(type_integer())))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit([1, 9])), + ['v' => [1, 0]], + schema(list_schema('v', type_list(type_integer()))), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit([1, 0])), + ['v' => [1, 0]], + schema(list_schema('v', type_list(type_integer()))), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit([1, 0])), + ['v' => [1, 9]], + schema(list_schema('v', type_list(type_integer()))), + )); } public function test_less_than_equal_datetimes(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->lessThanEqual(lit(new DateTimeImmutable('2024-06-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-01-01'), - ], schema(datetime_schema('v'))), $context), - ); - static::assertTrue( - ref('v') - ->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-01-01'), - ], schema(datetime_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-06-01'), - ], schema(datetime_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(new DateTimeImmutable('2024-06-01'))), + [ + 'v' => new DateTimeImmutable('2024-01-01'), + ], + schema(datetime_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2024-01-01'), + ], + schema(datetime_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2024-06-01'), + ], + schema(datetime_schema('v')), + )); } public function test_less_than_equal_floats(): void { $context = flow_context(); - static::assertTrue( - ref('v')->lessThanEqual(lit(2.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), - ); - static::assertTrue( - ref('v')->lessThanEqual(lit(1.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->lessThanEqual(lit(1.5))->eval(array_to_row(['v' => 2.5], schema(float_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(2.5)), + ['v' => 1.5], + schema(float_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(1.5)), + ['v' => 1.5], + schema(float_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(1.5)), + ['v' => 2.5], + schema(float_schema('v')), + )); } public function test_less_than_equal_integers(): void { $context = flow_context(); - static::assertTrue( - ref('v')->lessThanEqual(lit(20))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), - ); - static::assertTrue( - ref('v')->lessThanEqual(lit(10))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->lessThanEqual(lit(10))->eval(array_to_row(['v' => 20], schema(int_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(20)), + ['v' => 10], + schema(int_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(10)), + ['v' => 10], + schema(int_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(10)), + ['v' => 20], + schema(int_schema('v')), + )); } public function test_less_than_equal_returns_null_for_null_array(): void { - static::assertNull( - ref('v') - ->lessThanEqual(lit([1, 0])) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThanEqual(lit([1, 0])), + ['v' => null], + schema(list_schema('v', type_list(type_integer()), nullable: true)), + )); } public function test_less_than_equal_returns_null_for_null_datetime(): void { - static::assertNull( - ref('v') - ->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThanEqual(lit(new DateTimeImmutable('2024-01-01'))), + ['v' => null], + schema(datetime_schema('v', nullable: true)), + )); } public function test_less_than_equal_returns_null_for_null_left(): void { - static::assertNull( - ref('v') - ->lessThanEqual(lit(10)) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThanEqual(lit(10)), + ['v' => null], + schema(str_schema('v', nullable: true)), + )); } public function test_less_than_equal_returns_null_for_null_right(): void { - static::assertNull( - ref('v') - ->lessThanEqual(ref('other')) - ->eval( - array_to_row( - ['v' => 10, 'other' => null], - schema(int_schema('v'), str_schema('other', nullable: true)), - ), - flow_context(), - ), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThanEqual(ref('other')), + ['v' => 10, 'other' => null], + schema(int_schema('v'), str_schema('other', nullable: true)), + )); } public function test_less_than_equal_returns_null_for_null_string(): void { - static::assertNull( - ref('v') - ->lessThanEqual(lit('a')) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThanEqual(lit('a')), + ['v' => null], + schema(str_schema('v', nullable: true)), + )); } public function test_less_than_equal_returns_null_for_null_time_interval(): void { - static::assertNull( - ref('v') - ->lessThanEqual(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThanEqual(lit(new DateInterval('PT1H'))), + ['v' => null], + schema(time_schema('v', nullable: true)), + )); } public function test_less_than_equal_strings(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->lessThanEqual(lit('banana')) - ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), - ); - static::assertTrue( - ref('v') - ->lessThanEqual(lit('apple')) - ->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->lessThanEqual(lit('apple')) - ->eval(array_to_row(['v' => 'banana'], schema(str_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit('banana')), + ['v' => 'apple'], + schema(str_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit('apple')), + ['v' => 'apple'], + schema(str_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit('apple')), + ['v' => 'banana'], + schema(str_schema('v')), + )); } public function test_less_than_equal_throws_on_incompatible_types(): void @@ -195,20 +201,20 @@ public function test_less_than_equal_time_intervals(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->lessThanEqual(lit(new DateInterval('PT5H'))) - ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), - ); - static::assertTrue( - ref('v') - ->lessThanEqual(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->lessThanEqual(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => new DateInterval('PT5H')], schema(time_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(new DateInterval('PT5H'))), + ['v' => new DateInterval('PT1H')], + schema(time_schema('v')), + )); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(new DateInterval('PT1H'))), + ['v' => new DateInterval('PT1H')], + schema(time_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThanEqual(lit(new DateInterval('PT1H'))), + ['v' => new DateInterval('PT5H')], + schema(time_schema('v')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanTest.php index 36a07c51fd..e24c88e4c0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LessThanTest.php @@ -6,10 +6,10 @@ use DateInterval; use DateTimeImmutable; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; @@ -29,153 +29,165 @@ public function test_less_than_arrays(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->lessThan(lit([1, 9])) - ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), - ); - static::assertFalse( - ref('v') - ->lessThan(lit([1, 0])) - ->eval(array_to_row(['v' => [1, 9]], schema(list_schema('v', type_list(type_integer())))), $context), - ); - static::assertFalse( - ref('v') - ->lessThan(lit([1, 0])) - ->eval(array_to_row(['v' => [1, 0]], schema(list_schema('v', type_list(type_integer())))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThan(lit([1, 9])), + ['v' => [1, 0]], + schema(list_schema('v', type_list(type_integer()))), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit([1, 0])), + ['v' => [1, 9]], + schema(list_schema('v', type_list(type_integer()))), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit([1, 0])), + ['v' => [1, 0]], + schema(list_schema('v', type_list(type_integer()))), + )); } public function test_less_than_datetimes(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->lessThan(lit(new DateTimeImmutable('2024-06-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-01-01'), - ], schema(datetime_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->lessThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-06-01'), - ], schema(datetime_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->lessThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row([ - 'v' => new DateTimeImmutable('2024-01-01'), - ], schema(datetime_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(new DateTimeImmutable('2024-06-01'))), + [ + 'v' => new DateTimeImmutable('2024-01-01'), + ], + schema(datetime_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2024-06-01'), + ], + schema(datetime_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(new DateTimeImmutable('2024-01-01'))), + [ + 'v' => new DateTimeImmutable('2024-01-01'), + ], + schema(datetime_schema('v')), + )); } public function test_less_than_floats(): void { $context = flow_context(); - static::assertTrue( - ref('v')->lessThan(lit(2.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->lessThan(lit(1.5))->eval(array_to_row(['v' => 2.5], schema(float_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->lessThan(lit(1.5))->eval(array_to_row(['v' => 1.5], schema(float_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(2.5)), + ['v' => 1.5], + schema(float_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(1.5)), + ['v' => 2.5], + schema(float_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(1.5)), + ['v' => 1.5], + schema(float_schema('v')), + )); } public function test_less_than_integers(): void { $context = flow_context(); - static::assertTrue( - ref('v')->lessThan(lit(20))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->lessThan(lit(10))->eval(array_to_row(['v' => 20], schema(int_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->lessThan(lit(10))->eval(array_to_row(['v' => 10], schema(int_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(20)), + ['v' => 10], + schema(int_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(10)), + ['v' => 20], + schema(int_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(10)), + ['v' => 10], + schema(int_schema('v')), + )); } public function test_less_than_returns_null_for_null_array(): void { - static::assertNull( - ref('v') - ->lessThan(lit([1, 0])) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThan(lit([1, 0])), + ['v' => null], + schema(list_schema('v', type_list(type_integer()), nullable: true)), + )); } public function test_less_than_returns_null_for_null_datetime(): void { - static::assertNull( - ref('v') - ->lessThan(lit(new DateTimeImmutable('2024-01-01'))) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThan(lit(new DateTimeImmutable('2024-01-01'))), + ['v' => null], + schema(datetime_schema('v', nullable: true)), + )); } public function test_less_than_returns_null_for_null_left(): void { - static::assertNull( - ref('v') - ->lessThan(lit(10)) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThan(lit(10)), + ['v' => null], + schema(str_schema('v', nullable: true)), + )); } public function test_less_than_returns_null_for_null_right(): void { - static::assertNull( - ref('v') - ->lessThan(ref('other')) - ->eval( - array_to_row( - ['v' => 10, 'other' => null], - schema(int_schema('v'), str_schema('other', nullable: true)), - ), - flow_context(), - ), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThan(ref('other')), + ['v' => 10, 'other' => null], + schema(int_schema('v'), str_schema('other', nullable: true)), + )); } public function test_less_than_returns_null_for_null_string(): void { - static::assertNull( - ref('v') - ->lessThan(lit('a')) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThan(lit('a')), + ['v' => null], + schema(str_schema('v', nullable: true)), + )); } public function test_less_than_returns_null_for_null_time_interval(): void { - static::assertNull( - ref('v') - ->lessThan(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => null], schema(str_schema('v', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('v')->lessThan(lit(new DateInterval('PT1H'))), + ['v' => null], + schema(time_schema('v', nullable: true)), + )); } public function test_less_than_strings(): void { $context = flow_context(); - static::assertTrue( - ref('v')->lessThan(lit('banana'))->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->lessThan(lit('apple'))->eval(array_to_row(['v' => 'banana'], schema(str_schema('v'))), $context), - ); - static::assertFalse( - ref('v')->lessThan(lit('apple'))->eval(array_to_row(['v' => 'apple'], schema(str_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThan(lit('banana')), + ['v' => 'apple'], + schema(str_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit('apple')), + ['v' => 'banana'], + schema(str_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit('apple')), + ['v' => 'apple'], + schema(str_schema('v')), + )); } public function test_less_than_throws_on_incompatible_types(): void @@ -189,20 +201,20 @@ public function test_less_than_time_intervals(): void { $context = flow_context(); - static::assertTrue( - ref('v') - ->lessThan(lit(new DateInterval('PT5H'))) - ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->lessThan(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => new DateInterval('PT5H')], schema(time_schema('v'))), $context), - ); - static::assertFalse( - ref('v') - ->lessThan(lit(new DateInterval('PT1H'))) - ->eval(array_to_row(['v' => new DateInterval('PT1H')], schema(time_schema('v'))), $context), - ); + static::assertTrue((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(new DateInterval('PT5H'))), + ['v' => new DateInterval('PT1H')], + schema(time_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(new DateInterval('PT1H'))), + ['v' => new DateInterval('PT5H')], + schema(time_schema('v')), + )); + static::assertFalse((new FunctionContext($context))->eval( + ref('v')->lessThan(lit(new DateInterval('PT1H'))), + ['v' => new DateInterval('PT1H')], + schema(time_schema('v')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ListSelectTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ListSelectTest.php index 8be1555b0c..ca0c6bf3a5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ListSelectTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ListSelectTest.php @@ -7,9 +7,9 @@ use Flow\ETL\Function\ListSelect; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; @@ -58,73 +58,81 @@ public function test_selecting_from_a_list_of_scalars_declares_null_element_type public function test_selecting_non_existing_value_from_list_using_alias(): void { - $list = array_to_row([ - 'list' => [ - ['id' => 1, 'name' => 'test'], - ['id' => 2, 'name' => 'test2'], - ['id' => 3, 'name' => 'test3'], - ], - ], schema(list_schema('list', type_list(type_structure(['id' => type_integer(), 'name' => type_string()]))))); - static::assertEquals( [ ['id' => 1, 'mail' => null], ['id' => 2, 'mail' => null], ['id' => 3, 'mail' => null], ], - (new ListSelect(ref('list'), ref('id'), ref('mail')))->eval($list, flow_context()), + (new FunctionContext(flow_context()))->eval( + new ListSelect(ref('list'), ref('id'), ref('mail')), + [ + 'list' => [ + ['id' => 1, 'name' => 'test'], + ['id' => 2, 'name' => 'test2'], + ['id' => 3, 'name' => 'test3'], + ], + ], + schema(list_schema( + 'list', + type_list(type_structure(['id' => type_integer(), 'name' => type_string()])), + )), + ), ); } public function test_selecting_value_from_list(): void { - $list = array_to_row([ - 'list' => [ - ['id' => 1, 'name' => 'test'], - ['id' => 2, 'name' => 'test2'], - ['id' => 3, 'name' => 'test3'], - ], - ], schema(list_schema('list', type_list(type_structure(['id' => type_integer(), 'name' => type_string()]))))); - static::assertEquals( [ ['id' => 1], ['id' => 2], ['id' => 3], ], - (new ListSelect(ref('list'), 'id'))->eval($list, flow_context()), + (new FunctionContext(flow_context()))->eval( + new ListSelect(ref('list'), 'id'), + [ + 'list' => [ + ['id' => 1, 'name' => 'test'], + ['id' => 2, 'name' => 'test2'], + ['id' => 3, 'name' => 'test3'], + ], + ], + schema(list_schema( + 'list', + type_list(type_structure(['id' => type_integer(), 'name' => type_string()])), + )), + ), ); } public function test_selecting_value_from_list_using_alias(): void { - $list = array_to_row([ - 'list' => [ - ['id' => 1, 'name' => 'test'], - ['id' => 2, 'name' => 'test2'], - ['id' => 3, 'name' => 'test3'], - ], - ], schema(list_schema('list', type_list(type_structure(['id' => type_integer(), 'name' => type_string()]))))); - static::assertEquals( [ ['new_id' => 1], ['new_id' => 2], ['new_id' => 3], ], - (new ListSelect(ref('list'), ref('id')->as('new_id')))->eval($list, flow_context()), + (new FunctionContext(flow_context()))->eval( + new ListSelect(ref('list'), ref('id')->as('new_id')), + [ + 'list' => [ + ['id' => 1, 'name' => 'test'], + ['id' => 2, 'name' => 'test2'], + ['id' => 3, 'name' => 'test3'], + ], + ], + schema(list_schema( + 'list', + type_list(type_structure(['id' => type_integer(), 'name' => type_string()])), + )), + ), ); } public function test_selecting_value_from_simple_list(): void { - $list = array_to_row(['list' => [ - 'a', - 'b', - 'c', - 'd', - ]], schema(list_schema('list', type_list(type_string())))); - static::assertEquals( [ ['id' => null], @@ -132,7 +140,16 @@ public function test_selecting_value_from_simple_list(): void ['id' => null], ['id' => null], ], - (new ListSelect(ref('list'), ref('id')))->eval($list, flow_context()), + (new FunctionContext(flow_context()))->eval( + new ListSelect(ref('list'), ref('id')), + ['list' => [ + 'a', + 'b', + 'c', + 'd', + ]], + schema(list_schema('list', type_list(type_string()))), + ), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LiteralTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LiteralTest.php index 9e5d09a1d1..3d2fb59a82 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LiteralTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LiteralTest.php @@ -8,6 +8,12 @@ use Flow\ETL\Function\Literal; use Flow\ETL\Tests\FlowTestCase; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\lit; +use function Flow\ETL\DSL\schema; + final class LiteralTest extends FlowTestCase { public function test_constructor_rejects_a_closure_nested_in_an_array(): void @@ -29,4 +35,36 @@ public function test_constructor_rejects_a_closure(): void new Literal(static fn(): int => 1); } + + public function test_a_batch_of_the_same_size_reuses_the_column(): void + { + $literal = lit(7); + $first = $literal->eval(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), flow_context()); + + static::assertSame($first, $literal->eval(array_to_rows([ + ['id' => 3], + ['id' => 4], + ], schema(int_schema('id'))), flow_context())); + static::assertSame([7, 7], $first->values()); + } + + public function test_a_batch_of_another_size_gets_a_column_of_its_size(): void + { + $literal = lit('x'); + $two = $literal->eval(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), flow_context()); + $three = $literal->eval(array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id'))), flow_context()); + + static::assertSame(['x', 'x'], $two->values()); + static::assertSame(['x', 'x', 'x'], $three->values()); + static::assertSame( + ['x', 'x'], + $literal + ->eval(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), flow_context()) + ->values(), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LogicalFunctionsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LogicalFunctionsTest.php index cdb7696491..759ed93312 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LogicalFunctionsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LogicalFunctionsTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; @@ -17,29 +17,25 @@ final class LogicalFunctionsTest extends FlowTestCase { public function test_logical_operations(): void { - static::assertFalse( - ref('id') - ->isEven() - ->andNot(ref('id')->equals(lit(1))) - ->eval(array_to_row(['id' => 1], schema(int_schema('id'))), flow_context()), - ); - static::assertTrue( - ref('id') - ->isOdd() - ->and(ref('id')->equals(lit(1))) - ->eval(array_to_row(['id' => 1], schema(int_schema('id'))), flow_context()), - ); - static::assertTrue( - ref('id') - ->isEven() - ->or(ref('id')->equals(lit(1))) - ->eval(array_to_row(['id' => 1], schema(int_schema('id'))), flow_context()), - ); - static::assertFalse( - ref('id') - ->isOdd() - ->andNot(ref('id')->equals(lit(1))) - ->eval(array_to_row(['id' => 1], schema(int_schema('id'))), flow_context()), - ); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('id')->isEven()->andNot(ref('id')->equals(lit(1))), + ['id' => 1], + schema(int_schema('id')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('id')->isOdd()->and(ref('id')->equals(lit(1))), + ['id' => 1], + schema(int_schema('id')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('id')->isEven()->or(ref('id')->equals(lit(1))), + ['id' => 1], + schema(int_schema('id')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('id')->isOdd()->andNot(ref('id')->equals(lit(1))), + ['id' => 1], + schema(int_schema('id')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MatchCasesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MatchCasesTest.php index f99f30ac27..6ccc2af473 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MatchCasesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MatchCasesTest.php @@ -5,11 +5,16 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Double\FailingOnValuesFunction; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\match_cases; use function Flow\ETL\DSL\match_condition; @@ -24,9 +29,13 @@ public function test_no_matching_case_without_a_default_still_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Not a single case matches row, consider using default parameter'); - match_cases([ - match_condition(ref('string')->contains('_'), ref('string')->strReplace('_', ' ')), - ])->eval(array_to_row(['string' => 'weirdstring'], schema(str_schema('string'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + match_cases([ + match_condition(ref('string')->contains('_'), ref('string')->strReplace('_', ' ')), + ]), + ['string' => 'weirdstring'], + schema(str_schema('string')), + ); } public function test_case_match(): void @@ -36,12 +45,20 @@ public function test_case_match(): void match_condition(ref('string')->contains('-'), ref('string')->strReplace('-', ' ')), ]); - static::assertSame('this is slug', $match->eval(array_to_row([ - 'string' => 'this-is-slug', - ], schema(str_schema('string'))), flow_context())); - static::assertSame('this is slug', $match->eval(array_to_row([ - 'string' => 'this_is_slug', - ], schema(str_schema('string'))), flow_context())); + static::assertSame('this is slug', (new FunctionContext(flow_context()))->eval( + $match, + [ + 'string' => 'this-is-slug', + ], + schema(str_schema('string')), + )); + static::assertSame('this is slug', (new FunctionContext(flow_context()))->eval( + $match, + [ + 'string' => 'this_is_slug', + ], + schema(str_schema('string')), + )); } public function test_not_matching_anything_in_strict_mode(): void @@ -57,7 +74,7 @@ public function test_not_matching_anything_in_strict_mode(): void ]); $context = flow_context(config()); - $match->eval(array_to_row(['string' => 'weirdstring'], schema(str_schema('string'))), $context); + (new FunctionContext($context))->eval($match, ['string' => 'weirdstring'], schema(str_schema('string'))); } public function test_not_matching_anything_with_default(): void @@ -67,8 +84,31 @@ public function test_not_matching_anything_with_default(): void match_condition(ref('string')->contains('-'), ref('string')->strReplace('-', ' ')), ], default: lit('normal string')); - static::assertEquals('normal string', $match->eval(array_to_row([ - 'string' => 'weirdstring', - ], schema(str_schema('string'))), flow_context())); + static::assertEquals('normal string', (new FunctionContext(flow_context()))->eval( + $match, + [ + 'string' => 'weirdstring', + ], + schema(str_schema('string')), + )); + } + + public function test_a_later_case_runs_only_on_the_rows_no_earlier_case_took(): void + { + $rows = array_to_rows( + [['c' => true, 'v' => 99], ['c' => false, 'v' => 2]], + schema(bool_schema('c'), int_schema('v')), + ); + + static::assertSame( + [0, 2], + (new ReferenceResolver()) + ->resolve(match_cases([ + match_condition(ref('c'), lit(0)), + match_condition((new FailingOnValuesFunction(ref('v'), [99]))->isNotNull(), ref('v')), + ]), $rows->schema()) + ->eval($rows, flow_context()) + ->values(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MathTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MathTest.php index 0f72c2871f..9cd2706547 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MathTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MathTest.php @@ -11,9 +11,9 @@ use Flow\ETL\Function\Plus; use Flow\ETL\Function\Power; use Flow\ETL\Function\Round; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -25,59 +25,73 @@ final class MathTest extends FlowTestCase { public function test_divide(): void { - $row = array_to_row(['a' => 100, 'b' => 10], schema(int_schema('a'), int_schema('b'))); - - static::assertSame(10.0, (new Divide(ref('a'), ref('b')))->eval($row, flow_context())); + static::assertSame(10.0, (new FunctionContext(flow_context()))->eval( + new Divide(ref('a'), ref('b')), + ['a' => 100, 'b' => 10], + schema(int_schema('a'), int_schema('b')), + )); } public function test_minus(): void { - $row = array_to_row(['a' => 100, 'b' => 100], schema(int_schema('a'), int_schema('b'))); - - static::assertSame(0, (new Minus(ref('a'), ref('b')))->eval($row, flow_context())); + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + new Minus(ref('a'), ref('b')), + ['a' => 100, 'b' => 100], + schema(int_schema('a'), int_schema('b')), + )); } public function test_modulo(): void { - $row = array_to_row(['a' => 110, 'b' => 100], schema(int_schema('a'), int_schema('b'))); - - static::assertSame(10, (new Mod(ref('a'), ref('b')))->eval($row, flow_context())); + static::assertSame(10, (new FunctionContext(flow_context()))->eval( + new Mod(ref('a'), ref('b')), + ['a' => 110, 'b' => 100], + schema(int_schema('a'), int_schema('b')), + )); } public function test_multiple_operations(): void { - static::assertSame(200, ref('a') - ->plus(lit(100)) - ->plus(lit(100)) - ->minus(ref('b')) - ->eval(array_to_row(['a' => 100, 'b' => 100], schema(int_schema('a'), int_schema('b'))), flow_context())); + static::assertSame(200, (new FunctionContext(flow_context()))->eval( + ref('a')->plus(lit(100))->plus(lit(100))->minus(ref('b')), + ['a' => 100, 'b' => 100], + schema(int_schema('a'), int_schema('b')), + )); } public function test_multiply(): void { - $row = array_to_row(['a' => 100, 'b' => 100], schema(int_schema('a'), int_schema('b'))); - - static::assertSame(10_000, (new Multiply(ref('a'), ref('b')))->eval($row, flow_context())); + static::assertSame(10_000, (new FunctionContext(flow_context()))->eval( + new Multiply(ref('a'), ref('b')), + ['a' => 100, 'b' => 100], + schema(int_schema('a'), int_schema('b')), + )); } public function test_plus(): void { - $row = array_to_row(['a' => 100, 'b' => 100], schema(int_schema('a'), int_schema('b'))); - - static::assertSame(200, (new Plus(ref('a'), ref('b')))->eval($row, flow_context())); + static::assertSame(200, (new FunctionContext(flow_context()))->eval( + new Plus(ref('a'), ref('b')), + ['a' => 100, 'b' => 100], + schema(int_schema('a'), int_schema('b')), + )); } public function test_power(): void { - $row = array_to_row(['a' => 1, 'b' => 2], schema(int_schema('a'), int_schema('b'))); - - static::assertSame(1, (new Power(ref('a'), ref('b')))->eval($row, flow_context())); + static::assertSame(1, (new FunctionContext(flow_context()))->eval( + new Power(ref('a'), ref('b')), + ['a' => 1, 'b' => 2], + schema(int_schema('a'), int_schema('b')), + )); } public function test_round(): void { - $row = array_to_row(['a' => 1.009, 'b' => 2], schema(float_schema('a'), int_schema('b'))); - - static::assertSame(1.01, (new Round(ref('a'), ref('b')))->eval($row, flow_context())); + static::assertSame(1.01, (new FunctionContext(flow_context()))->eval( + new Round(ref('a'), ref('b')), + ['a' => 1.009, 'b' => 2], + schema(float_schema('a'), int_schema('b')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MaxTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MaxTest.php index f45a939752..b32ff2c343 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MaxTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MaxTest.php @@ -5,15 +5,18 @@ namespace Flow\ETL\Tests\Unit\Function; use DateTimeImmutable; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\max; +use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -30,13 +33,17 @@ public function test_aggregation_max_from_numeric_values(): void { $aggregator = max(ref('int')); - $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'not_int' => null, - ], schema(str_schema('not_int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '10']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '20']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '55']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '25']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'not_int' => null, + ]], schema(str_schema('not_int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(55.0, $aggregator->value()); } @@ -45,12 +52,16 @@ public function test_aggregation_max_including_null_value(): void { $aggregator = max(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'int' => null, - ], schema(int_schema('int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'int' => null, + ]], schema(int_schema('int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(30.0, $aggregator->value()); } @@ -59,18 +70,34 @@ public function test_aggregation_max_with_datetime_values(): void { $aggregator = max(ref('datetime')); - $aggregator->aggregate(array_to_row([ - 'datetime' => type_datetime()->cast('2021-01-01 00:00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'datetime' => type_datetime()->cast('2021-01-02 00:00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'datetime' => type_datetime()->cast('2021-01-03 00:00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'datetime' => type_datetime()->cast('2021-01-04 00:00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'datetime' => type_datetime()->cast('2021-01-01 00:00:00'), + ]], schema(datetime_schema('datetime'))), + [0], + flow_context(), + ); + $aggregator->aggregate( + array_to_rows([[ + 'datetime' => type_datetime()->cast('2021-01-02 00:00:00'), + ]], schema(datetime_schema('datetime'))), + [0], + flow_context(), + ); + $aggregator->aggregate( + array_to_rows([[ + 'datetime' => type_datetime()->cast('2021-01-03 00:00:00'), + ]], schema(datetime_schema('datetime'))), + [0], + flow_context(), + ); + $aggregator->aggregate( + array_to_rows([[ + 'datetime' => type_datetime()->cast('2021-01-04 00:00:00'), + ]], schema(datetime_schema('datetime'))), + [0], + flow_context(), + ); static::assertEquals(new DateTimeImmutable('2021-01-04 00:00:00'), $aggregator->value()); } @@ -79,10 +106,10 @@ public function test_aggregation_max_with_float_result(): void { $aggregator = max(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30.5], schema(float_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30.5]], schema(float_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 25]], schema(int_schema('int'))), [0], flow_context()); static::assertSame(30.5, $aggregator->value()); } @@ -91,10 +118,10 @@ public function test_aggregation_max_with_integer_result(): void { $aggregator = max(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 40], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 40]], schema(int_schema('int'))), [0], flow_context()); static::assertSame(40.0, $aggregator->value()); } @@ -126,4 +153,59 @@ public function test_max_over_an_int_column_declares_optional_integer(): void ->toString(), ); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = max(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 0.5, + 1.25, + 2.0, + 3.0, + ]), schema(float_schema('v'))), + [0, 2], + flow_context(), + ); + + static::assertSame(2.0, $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 0.5, + 1.25, + 2.0, + 3.0, + ]), schema(float_schema('v'))); + $onePass = max(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = max(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = max(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + max(ref('v'))->merge(min(ref('v')), flow_context()); + } + + public function test_merge_into_an_empty_half_takes_the_other_value(): void + { + $right = max(ref('v')); + $right->aggregate(array_to_rows([['v' => 1.5]], schema(float_schema('v'))), [0], flow_context()); + $left = max(ref('v')); + $left->merge(max(ref('v')), flow_context()); + $left->merge($right, flow_context()); + + static::assertSame(1.5, $left->value()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinTest.php index 1739f021c3..a585969211 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinTest.php @@ -5,14 +5,17 @@ namespace Flow\ETL\Tests\Unit\Function; use DateTimeImmutable; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\max; use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -30,7 +33,7 @@ public function test_the_output_suffix_survives_an_immutable_reference(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); static::assertSame('int_min', $aggregator->outputName()); } @@ -39,13 +42,17 @@ public function test_aggregation_min_from_numeric_values(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'not_int' => null, - ], schema(str_schema('not_int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '10']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '20']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '55']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '25']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'not_int' => null, + ]], schema(str_schema('not_int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(10.0, $aggregator->value()); } @@ -54,12 +61,16 @@ public function test_aggregation_min_including_null_value(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'int' => null, - ], schema(int_schema('int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'int' => null, + ]], schema(int_schema('int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(10.0, $aggregator->value()); } @@ -68,18 +79,34 @@ public function test_aggregation_min_with_datetime_values(): void { $aggregator = min(ref('datetime')); - $aggregator->aggregate(array_to_row([ - 'datetime' => type_datetime()->cast('2021-01-01 00:00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'datetime' => type_datetime()->cast('2021-01-02 00:00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'datetime' => type_datetime()->cast('2021-01-03 00:00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'datetime' => type_datetime()->cast('2021-01-04 00:00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'datetime' => type_datetime()->cast('2021-01-01 00:00:00'), + ]], schema(datetime_schema('datetime'))), + [0], + flow_context(), + ); + $aggregator->aggregate( + array_to_rows([[ + 'datetime' => type_datetime()->cast('2021-01-02 00:00:00'), + ]], schema(datetime_schema('datetime'))), + [0], + flow_context(), + ); + $aggregator->aggregate( + array_to_rows([[ + 'datetime' => type_datetime()->cast('2021-01-03 00:00:00'), + ]], schema(datetime_schema('datetime'))), + [0], + flow_context(), + ); + $aggregator->aggregate( + array_to_rows([[ + 'datetime' => type_datetime()->cast('2021-01-04 00:00:00'), + ]], schema(datetime_schema('datetime'))), + [0], + flow_context(), + ); static::assertEquals(new DateTimeImmutable('2021-01-01 00:00:00'), $aggregator->value()); } @@ -88,10 +115,10 @@ public function test_aggregation_min_with_float_result(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10.25], schema(float_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 305], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10.25]], schema(float_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 305]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 25]], schema(int_schema('int'))), [0], flow_context()); static::assertSame(10.25, $aggregator->value()); } @@ -100,10 +127,10 @@ public function test_aggregation_min_with_integer_result(): void { $aggregator = min(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 40], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 40]], schema(int_schema('int'))), [0], flow_context()); static::assertSame(10.0, $aggregator->value()); } @@ -135,4 +162,59 @@ public function test_min_over_an_int_column_declares_optional_integer(): void ->toString(), ); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = min(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 0.5, + 1.25, + 2.0, + 3.0, + ]), schema(float_schema('v'))), + [1, 3], + flow_context(), + ); + + static::assertSame(1.25, $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 0.5, + 1.25, + 2.0, + 3.0, + ]), schema(float_schema('v'))); + $onePass = min(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = min(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = min(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + min(ref('v'))->merge(max(ref('v')), flow_context()); + } + + public function test_merge_into_an_empty_half_takes_the_other_value(): void + { + $right = min(ref('v')); + $right->aggregate(array_to_rows([['v' => 1.5]], schema(float_schema('v'))), [0], flow_context()); + $left = min(ref('v')); + $left->merge(min(ref('v')), flow_context()); + $left->merge($right, flow_context()); + + static::assertSame(1.5, $left->value()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinusTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinusTest.php new file mode 100644 index 0000000000..11ff622580 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MinusTest.php @@ -0,0 +1,57 @@ +eval( + ref('a')->minus(ref('b'), exact: true), + ['a' => 0.3, 'b' => 0.1], + schema(float_schema('a'), float_schema('b')), + )); + } + + public function test_floats_use_ieee_arithmetic(): void + { + static::assertSame(0.19999999999999998, (new FunctionContext(flow_context()))->eval( + ref('a')->minus(ref('b')), + ['a' => 0.3, 'b' => 0.1], + schema(float_schema('a'), float_schema('b')), + )); + } + + public function test_integers_stay_integers(): void + { + static::assertSame(2, (new FunctionContext(flow_context()))->eval( + ref('a')->minus(ref('b')), + ['a' => 5, 'b' => 3], + schema(int_schema('a'), int_schema('b')), + )); + } + + public function test_integer_overflow_names_its_row(): void + { + $this->expectException(EvaluationException::class); + $this->expectExceptionMessage('Minus function integer overflow (row 0)'); + + (new FunctionContext(flow_context()))->eval( + ref('a')->minus(ref('b')), + ['a' => PHP_INT_MIN, 'b' => 1], + schema(int_schema('a'), int_schema('b')), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ModifyDateTimeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ModifyDateTimeTest.php index c0c055459c..455cf2e9e7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ModifyDateTimeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ModifyDateTimeTest.php @@ -7,9 +7,9 @@ use DateTimeImmutable; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; @@ -26,11 +26,13 @@ public function test_modify_date(): void { static::assertEquals( new DateTimeImmutable('2025-01-01 12:00:00 +00:00'), - ref('datetime') - ->modifyDateTime('noon') - ->eval(array_to_row([ + (new FunctionContext(flow_context()))->eval( + ref('datetime')->modifyDateTime('noon'), + [ 'datetime' => type_date()->cast('2025-01-01'), - ], schema(date_schema('datetime'))), flow_context()), + ], + schema(date_schema('datetime')), + ), ); } @@ -38,11 +40,13 @@ public function test_modify_datetime(): void { static::assertEquals( new DateTimeImmutable('2025-01-01 00:00:00 +00:00'), - ref('datetime') - ->modifyDateTime('midnight') - ->eval(array_to_row([ + (new FunctionContext(flow_context()))->eval( + ref('datetime')->modifyDateTime('midnight'), + [ 'datetime' => type_datetime()->cast('2025-01-01 10:00:23 +00:00'), - ], schema(datetime_schema('datetime'))), flow_context()), + ], + schema(datetime_schema('datetime')), + ), ); } @@ -51,11 +55,13 @@ public function test_modify_using_invalid_modifier(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "string", got "integer".'); - ref('datetime') - ->modifyDateTime(lit(1)) - ->eval(array_to_row([ + (new FunctionContext(flow_context()))->eval( + ref('datetime')->modifyDateTime(lit(1)), + [ 'datetime' => type_datetime()->cast('2025-01-01 10:00:23 +00:00'), - ], schema(datetime_schema('datetime'))), flow_context()); + ], + schema(datetime_schema('datetime')), + ); } public function test_zone_of_the_reference_is_kept(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MultiplyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MultiplyTest.php new file mode 100644 index 0000000000..7e41d8ea04 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/MultiplyTest.php @@ -0,0 +1,57 @@ +eval( + ref('a')->multiply(ref('b'), exact: true), + ['a' => 0.1, 'b' => 3], + schema(float_schema('a'), int_schema('b')), + )); + } + + public function test_floats_use_ieee_arithmetic(): void + { + static::assertSame(0.30000000000000004, (new FunctionContext(flow_context()))->eval( + ref('a')->multiply(ref('b')), + ['a' => 0.1, 'b' => 3], + schema(float_schema('a'), int_schema('b')), + )); + } + + public function test_integers_stay_integers(): void + { + static::assertSame(15, (new FunctionContext(flow_context()))->eval( + ref('a')->multiply(ref('b')), + ['a' => 5, 'b' => 3], + schema(int_schema('a'), int_schema('b')), + )); + } + + public function test_integer_overflow_names_its_row(): void + { + $this->expectException(EvaluationException::class); + $this->expectExceptionMessage('Multiply function integer overflow (row 0)'); + + (new FunctionContext(flow_context()))->eval( + ref('a')->multiply(ref('b')), + ['a' => PHP_INT_MAX, 'b' => 2], + schema(int_schema('a'), int_schema('b')), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NotTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NotTest.php index ef2e95181f..1ca34d9b7f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NotTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NotTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\from_array; @@ -52,45 +52,44 @@ public function test_not_over_a_null_predicate_drops_the_row(): void public function test_not_expression_on_array_true_value(): void { - static::assertFalse(not(lit([1, 2, 3]))->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval(not(lit([1, 2, 3])), [], schema())); } public function test_not_expression_on_boolean_true_value(): void { - static::assertFalse(not(lit(true))->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval(not(lit(true)), [], schema())); } public function test_not_expression_on_is_in_expression(): void { - static::assertTrue( - not(ref('value')->isIn(ref('array'))) - ->eval( - array_to_row( - ['array' => [1, 2, 3], 'value' => 10], - schema(list_schema('array', type_list(type_integer())), int_schema('value')), - ), - flow_context(), - ), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + not(ref('value')->isIn(ref('array'))), + ['array' => [1, 2, 3], 'value' => 10], + schema(list_schema('array', type_list(type_integer())), int_schema('value')), + )); } public function test_not_expression_with_and_operator(): void { - static::assertTrue( - not(ref('value')->isNull()->or(ref('value')->isType(type_integer()))) - ->eval(array_to_row(['value' => '10'], schema(str_schema('value'))), flow_context()), - ); - static::assertFalse( - not(ref('value')->isNull()->or(ref('value')->isType(type_integer()))) - ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()), - ); - static::assertTrue( - not(ref('value')->isNull()->and(ref('value')->size()->between(1, 10))) - ->eval(array_to_row(['value' => 'abcd'], schema(str_schema('value'))), flow_context()), - ); - static::assertTrue( - not(ref('value')->isNull()->or(ref('value')->size()->equals(1))) - ->eval(array_to_row(['value' => 'abcd'], schema(str_schema('value'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + not(ref('value')->isNull()->or(ref('value')->isType(type_integer()))), + ['value' => '10'], + schema(str_schema('value')), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + not(ref('value')->isNull()->or(ref('value')->isType(type_integer()))), + ['value' => null], + schema(str_schema('value', nullable: true)), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + not(ref('value')->isNull()->and(ref('value')->size()->between(1, 10))), + ['value' => 'abcd'], + schema(str_schema('value')), + )); + static::assertTrue((new FunctionContext(flow_context()))->eval( + not(ref('value')->isNull()->or(ref('value')->size()->equals(1))), + ['value' => 'abcd'], + schema(str_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NowTest.php index 89e3303c87..c87293ab65 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NowTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NowTest.php @@ -6,9 +6,9 @@ use DateTimeZone; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\now; use function Flow\ETL\DSL\ref; @@ -34,7 +34,11 @@ public function test_value_is_in_the_zone(): void static::assertSame( 'Europe/Warsaw', type_datetime() - ->assert(now(new DateTimeZone('Europe/Warsaw'))->eval(array_to_row([], schema()), flow_context())) + ->assert((new FunctionContext(flow_context()))->eval( + now(new DateTimeZone('Europe/Warsaw')), + [], + schema(), + )) ->getTimezone() ->getName(), ); @@ -45,12 +49,13 @@ public function test_function_zone_value_is_in_the_declared_zone(): void static::assertSame( 'UTC', type_datetime() - ->assert( - now(ref('tz')) - ->eval(array_to_row([ - 'tz' => new DateTimeZone('Europe/Warsaw'), - ], schema(time_zone_schema('tz'))), flow_context()), - ) + ->assert((new FunctionContext(flow_context()))->eval( + now(ref('tz')), + [ + 'tz' => new DateTimeZone('Europe/Warsaw'), + ], + schema(time_zone_schema('tz')), + )) ->getTimezone() ->getName(), ); @@ -61,7 +66,11 @@ public function test_function_zone_null_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Now function requires valid DateTimeZone'); - now(ref('tz'))->eval(array_to_row(['tz' => null], schema(str_schema('tz', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + now(ref('tz')), + ['tz' => null], + schema(str_schema('tz', nullable: true)), + ); } public function test_utc_alias_zone_lands_in_utc(): void @@ -69,7 +78,7 @@ public function test_utc_alias_zone_lands_in_utc(): void static::assertSame( 'UTC', type_datetime() - ->assert(now(new DateTimeZone('GMT'))->eval(array_to_row([], schema()), flow_context())) + ->assert((new FunctionContext(flow_context()))->eval(now(new DateTimeZone('GMT')), [], schema())) ->getTimezone() ->getName(), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NumberFormatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NumberFormatTest.php index 1782f51f10..eb3ba39a0b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NumberFormatTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/NumberFormatTest.php @@ -6,9 +6,9 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\NumberFormat; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -29,22 +29,20 @@ public function test_number_format(): void ref('thousands_separator'), ); - static::assertSame('1,234.57', $expression->eval( - array_to_row( - [ - 'value' => 1234.5678, - 'decimals' => 2, - 'decimal_separator' => '.', - 'thousands_separator' => ',', - ], - schema( - float_schema('value'), - int_schema('decimals'), - str_schema('decimal_separator'), - str_schema('thousands_separator'), - ), + static::assertSame('1,234.57', (new FunctionContext(flow_context()))->eval( + $expression, + [ + 'value' => 1234.5678, + 'decimals' => 2, + 'decimal_separator' => '.', + 'thousands_separator' => ',', + ], + schema( + float_schema('value'), + int_schema('decimals'), + str_schema('decimal_separator'), + str_schema('thousands_separator'), ), - flow_context(), )); } @@ -52,9 +50,13 @@ public function test_number_format_dsl(): void { $expression = number_format(ref('value'), lit(2), lit('.'), lit(',')); - static::assertSame('1,234.57', $expression->eval(array_to_row([ - 'value' => 1234.5678, - ], schema(float_schema('value'))), flow_context())); + static::assertSame('1,234.57', (new FunctionContext(flow_context()))->eval( + $expression, + [ + 'value' => 1234.5678, + ], + schema(float_schema('value')), + )); } public function test_number_format_on_decimals_that_are_not_integer(): void @@ -69,22 +71,20 @@ public function test_number_format_on_decimals_that_are_not_integer(): void ref('thousands_separator'), ); - $expression->eval( - array_to_row( - [ - 'value' => 1234.5678, - 'decimals' => 2.5, - 'decimal_separator' => '.', - 'thousands_separator' => ',', - ], - schema( - float_schema('value'), - float_schema('decimals'), - str_schema('decimal_separator'), - str_schema('thousands_separator'), - ), + (new FunctionContext(flow_context()))->eval( + $expression, + [ + 'value' => 1234.5678, + 'decimals' => 2.5, + 'decimal_separator' => '.', + 'thousands_separator' => ',', + ], + schema( + float_schema('value'), + float_schema('decimals'), + str_schema('decimal_separator'), + str_schema('thousands_separator'), ), - flow_context(), ); } @@ -100,22 +100,20 @@ public function test_number_format_on_non_int_entry(): void ref('thousands_separator'), ); - $expression->eval( - array_to_row( - [ - 'value' => 'test', - 'decimals' => 2, - 'decimal_separator' => '.', - 'thousands_separator' => ',', - ], - schema( - str_schema('value'), - int_schema('decimals'), - str_schema('decimal_separator'), - str_schema('thousands_separator'), - ), + (new FunctionContext(flow_context()))->eval( + $expression, + [ + 'value' => 'test', + 'decimals' => 2, + 'decimal_separator' => '.', + 'thousands_separator' => ',', + ], + schema( + str_schema('value'), + int_schema('decimals'), + str_schema('decimal_separator'), + str_schema('thousands_separator'), ), - flow_context(), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php index ac04ca6a66..732b95665a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php @@ -11,14 +11,19 @@ use Flow\ETL\Function\OnEachElementSchema; use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\Double\CountingReturnsFunction; +use Flow\ETL\Tests\Double\FailingOnValuesFunction; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Generator; use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\definition_from_type; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\map_schema; @@ -46,49 +51,55 @@ public function test_a_throwing_body_is_not_swallowed(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "string", got "integer"'); - (new ReferenceResolver()) - ->resolve( + (new FunctionContext(flow_context()))->eval( + (new ReferenceResolver())->resolve( ref('array')->onEach(ref('element')->upper()), schema(list_schema('array', type_list(type_integer()))), - ) - ->eval(array_to_row(['array' => [ + ), + ['array' => [ 1, 2, 3, - ]], schema(list_schema('array', type_list(type_integer())))), flow_context()); + ]], + schema(list_schema('array', type_list(type_integer()))), + ); } public function test_an_element_the_declared_type_refuses_is_not_swallowed(): void { $this->expectException(SchemaMismatchException::class); - (new ReferenceResolver()) - ->resolve( + (new FunctionContext(flow_context()))->eval( + (new ReferenceResolver())->resolve( ref('array')->onEach(ref('element')->upper()), schema(list_schema('array', type_list(type_string()))), - ) - ->eval(array_to_row(['array' => [ + ), + ['array' => [ 'a', null, - ]], schema(list_schema('array', type_list(type_optional(type_string()))))), flow_context()); + ]], + schema(list_schema('array', type_list(type_optional(type_string())))), + ); } public function test_executing_function_on_each_value_from_array(): void { static::assertSame( ['1', '2', '3', '4', '5'], - (new ReferenceResolver()) - ->resolve( + (new FunctionContext(flow_context()))->eval( + (new ReferenceResolver())->resolve( ref('array')->onEach(ref('element')->cast(type_string())), schema(list_schema('array', type_list(type_integer()))), - ) - ->eval(array_to_row(['array' => [ + ), + ['array' => [ 1, 2, 3, 4, 5, - ]], schema(list_schema('array', type_list(type_integer())))), flow_context()), + ]], + schema(list_schema('array', type_list(type_integer()))), + ), ); } @@ -96,15 +107,14 @@ public function test_executing_function_on_each_value_from_empty_array(): void { static::assertSame( [], - (new ReferenceResolver()) - ->resolve( + (new FunctionContext(flow_context()))->eval( + (new ReferenceResolver())->resolve( ref('array')->onEach(ref('element')->cast(type_string())), schema(list_schema('array', type_list(type_integer()))), - ) - ->eval(array_to_row( - ['array' => []], - schema(list_schema('array', type_list(type_integer()))), - ), flow_context()), + ), + ['array' => []], + schema(list_schema('array', type_list(type_integer()))), + ), ); } @@ -112,18 +122,20 @@ public function test_executing_function_on_each_value_with_preserving_keys(): vo { static::assertSame( ['a' => '1', 'b' => '2', 'c' => '3', 'd' => '4', 'e' => '5'], - (new ReferenceResolver()) - ->resolve( + (new FunctionContext(flow_context()))->eval( + (new ReferenceResolver())->resolve( ref('array')->onEach(ref('element')->cast(type_string()), true), schema(map_schema('array', type_map(type_string(), type_integer()))), - ) - ->eval(array_to_row(['array' => [ + ), + ['array' => [ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, - ]], schema(map_schema('array', type_map(type_string(), type_integer())))), flow_context()), + ]], + schema(map_schema('array', type_map(type_string(), type_integer()))), + ), ); } @@ -131,18 +143,20 @@ public function test_executing_function_on_each_value_without_preserving_keys(): { static::assertSame( ['1', '2', '3', '4', '5'], - (new ReferenceResolver()) - ->resolve( + (new FunctionContext(flow_context()))->eval( + (new ReferenceResolver())->resolve( ref('array')->onEach(ref('element')->cast(type_string()), false), schema(map_schema('array', type_map(type_string(), type_integer()))), - ) - ->eval(array_to_row(['array' => [ + ), + ['array' => [ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, - ]], schema(map_schema('array', type_map(type_string(), type_integer())))), flow_context()), + ]], + schema(map_schema('array', type_map(type_string(), type_integer()))), + ), ); } @@ -153,22 +167,28 @@ public function test_on_each_over_an_untyped_array_operand_is_refused(): void $this->expectException(SchemaNotDerivableException::class); $this->expectExceptionMessage('the array operand declares "json", which has no element type'); - (new ReferenceResolver()) - ->resolve( + (new FunctionContext(flow_context()))->eval( + (new ReferenceResolver())->resolve( ref('array')->onEach(ref('element')->cast(type_string())), schema(definition_from_type('array', type_array())), - ) - ->eval(array_to_row(['array' => [ + ), + ['array' => [ 1, 2, - ]], schema(list_schema('array', type_list(type_integer())))), flow_context()); + ]], + schema(list_schema('array', type_list(type_integer()))), + ); } public function test_the_element_schema_is_built_once_per_eval_not_once_per_element(): void { $operand = new CountingReturnsFunction(lit([1, 2, 3, 4, 5]), type_list(type_integer())); - (new OnEach($operand, ref('element')->cast(type_string())))->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval( + new OnEach($operand, ref('element')->cast(type_string())), + [], + schema(), + ); static::assertSame(1, $operand->returnsCalls); } @@ -257,9 +277,11 @@ public function test_a_null_array_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('OnEach requires non-null array'); - ref('tags') - ->onEach(ref('element')) - ->eval(array_to_row(['tags' => null], schema(str_schema('tags', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('tags')->onEach(ref('element')), + ['tags' => null], + schema(str_schema('tags', nullable: true)), + ); } public function test_with_children_keeps_the_element_schema(): void @@ -270,4 +292,49 @@ public function test_with_children_keeps_the_element_schema(): void // two stateless instances are equal, but serialize() names an instance it already wrote only by back-reference static::assertSame(1, substr_count(serialize([$elementSchema, $rebuilt]), 'OnEachElementSchema')); } + + public function test_the_body_is_bound_once_per_node_not_once_per_batch(): void + { + $operand = new CountingReturnsFunction(lit([1, 2]), type_list(type_integer())); + $onEach = new OnEach($operand, ref('element')->cast(type_string())); + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); + + static::assertSame([['1', '2']], $onEach->eval($rows, flow_context())->values()); + static::assertSame([['1', '2']], $onEach->eval($rows, flow_context())->values()); + static::assertSame(1, $operand->returnsCalls); + } + + public function test_the_element_batch_is_an_intermediate_built_without_the_configured_backend(): void + { + $backend = new SpyBackend(); + $rows = array_to_rows([['l' => [1, 2]]], schema(list_schema('l', type_list(type_integer())))); + + static::assertSame( + [['1', '2']], + (new ReferenceResolver()) + ->resolve(new OnEach(ref('l'), ref('element')->cast(type_string())), $rows->schema()) + ->eval($rows, flow_context(config_builder()->backend($backend)->build())) + ->values(), + ); + static::assertSame(0, $backend->builders()); + } + + public function test_the_function_evaluates_once_per_batch(): void + { + $spy = new FailingOnValuesFunction(ref('element')); + $rows = array_to_rows([ + ['l' => [1, 2]], + ['l' => [3]], + ['l' => []], + ], schema(list_schema('l', type_list(type_integer())))); + + static::assertSame( + [[1, 2], [3], []], + (new ReferenceResolver()) + ->resolve(new OnEach(ref('l'), $spy), $rows->schema()) + ->eval($rows, flow_context()) + ->values(), + ); + static::assertSame(1, $spy->evals); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OptionalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OptionalTest.php index 35aa11c8c4..a3f52b90e7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OptionalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OptionalTest.php @@ -4,14 +4,24 @@ namespace Flow\ETL\Tests\Unit\Function; +use Error; +use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Double\FailingOnValuesFunction; use Flow\ETL\Tests\FlowTestCase; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\optional; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function in_array; +use function range; final class OptionalTest extends FlowTestCase { @@ -22,9 +32,63 @@ public function test_optional_declares_the_inner_type_widened_to_optional(): voi public function test_optional_returns_null_when_the_inner_function_throws(): void { - static::assertNull( - optional(ref('name')->upper()) - ->eval(array_to_row(['other' => 'flow'], schema(str_schema('other'))), flow_context()), + static::assertNull((new FunctionContext(flow_context()))->eval( + optional(ref('name')->upper()), + ['other' => 'flow'], + schema(str_schema('other')), + )); + } + + /** + * @return Generator, string, int}> + */ + public static function failing_rows(): Generator + { + yield 'one failing row: one retry' => [[3], FailingOnValuesFunction::WITH_ROW, 2]; + yield 'three failing rows: three retries' => [[2, 4, 6], FailingOnValuesFunction::WITH_ROW, 4]; + yield 'twelve failing rows: eight batch evals, then each remaining row alone' => [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + FailingOnValuesFunction::WITH_ROW, + 8 + 6, + ]; + yield 'a failure without a row: each row alone' => [[3], FailingOnValuesFunction::WITHOUT_ROW, 1 + 14]; + } + + /** + * @param list $failing + */ + #[DataProvider('failing_rows')] + public function test_only_the_failing_rows_are_null(array $failing, string $failure, int $evals): void + { + $spy = new FailingOnValuesFunction(ref('v'), $failing, $failure); + $rows = array_to_rows( + array_map(static fn(int $v): array => ['v' => $v], range(1, 14)), + schema(int_schema('v')), + ); + + $values = (new ReferenceResolver()) + ->resolve(optional($spy), $rows->schema()) + ->eval($rows, flow_context()) + ->values(); + + static::assertSame( + array_map(static fn(int $v): ?int => in_array($v, $failing, true) ? null : $v, range(1, 14)), + $values, ); + static::assertSame($evals, $spy->evals); + } + + public function test_an_error_propagates(): void + { + $rows = array_to_rows([['v' => 1]], schema(int_schema('v'))); + + $this->expectException(Error::class); + + (new ReferenceResolver()) + ->resolve( + optional(new FailingOnValuesFunction(ref('v'), [1], FailingOnValuesFunction::ERROR)), + $rows->schema(), + ) + ->eval($rows, flow_context()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php index db878709a3..2e86f3e1f7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php @@ -7,16 +7,24 @@ use DateTimeImmutable; use DateTimeInterface; use Flow\Doctrine\Bulk\SQLParametersStyle; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\Parameter; +use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\String\StringStyles; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\RowsMother; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use stdClass; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -87,117 +95,96 @@ public static function string_data_provider(): Generator public function test_as_array_with_empty_array(): void { - $parameter = new Parameter(lit([])); - static::assertSame([], $parameter->asArray(array_to_row([], schema()), flow_context())); + static::assertSame([[]], (new Parameter(lit([])))->asArrays(RowsMother::sequentialIds(1), flow_context())); } - public function test_as_boolean_throws_on_a_malformed_value(): void - { - $this->expectException(InvalidArgumentException::class); - - (new Parameter(lit(['value'])))->asBoolean(array_to_row([], schema()), flow_context()); - } - - public function test_as_boolean_propagates_null(): void - { - static::assertNull((new Parameter(lit(null)))->asBoolean(array_to_row([], schema()), flow_context())); - } - - public function test_as_float_throws_on_a_malformed_value(): void - { - $this->expectException(InvalidArgumentException::class); - - (new Parameter(lit('3.14')))->asFloat(array_to_row([], schema()), flow_context()); - } - - public function test_as_float_propagates_null(): void - { - static::assertNull((new Parameter(lit(null)))->asFloat(array_to_row([], schema()), flow_context())); - } - - public function test_as_int_throws_on_a_malformed_value(): void - { - // A default never applies to a malformed value - only to a NULL input. - $this->expectException(InvalidArgumentException::class); - - (new Parameter(lit(3.14)))->asInt(array_to_row([], schema()), flow_context(), 99); - } - - public function test_as_int_propagates_null(): void - { - static::assertNull((new Parameter(lit(null)))->asInt(array_to_row([], schema()), flow_context())); - } - - public function test_as_number_throws_on_a_malformed_value(): void - { - $this->expectException(InvalidArgumentException::class); - - (new Parameter(lit('not numeric')))->asNumber(array_to_row([], schema()), flow_context(), 99); - } - - public function test_as_number_propagates_null(): void - { - static::assertNull((new Parameter(lit(null)))->asNumber(array_to_row([], schema()), flow_context())); - } - - public function test_as_string_throws_on_a_malformed_value(): void + public function test_as_array_with_valid_array(): void { - $this->expectException(InvalidArgumentException::class); - - (new Parameter(lit(42)))->asString(array_to_row([], schema()), flow_context(), 'default'); + static::assertSame( + [['key' => 'value', 'number' => 42]], + (new Parameter(lit(['key' => 'value', 'number' => 42])))->asArrays( + RowsMother::sequentialIds(1), + flow_context(), + ), + ); } - public function test_as_string_propagates_null(): void + public function test_as_arrays_reads_a_json_column_as_arrays(): void { - static::assertNull((new Parameter(lit(null)))->asString(array_to_row([], schema()), flow_context())); + static::assertSame( + [['a' => 1], null], + (new Parameter((new ReferenceResolver())->resolve( + ref('j'), + array_to_rows([ + ['j' => '{"a":1}'], + ['j' => null], + ], schema(json_schema('j', nullable: true)))->schema(), + )))->asArrays(array_to_rows([ + ['j' => '{"a":1}'], + ['j' => null], + ], schema(json_schema('j', nullable: true))), flow_context()), + ); } public function test_as_array_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an array')))->asArray(array_to_row([], schema()), flow_context()); + (new Parameter(lit('not an array')))->asArrays(RowsMother::sequentialIds(1), flow_context()); } public function test_as_array_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asArray(array_to_row([], schema()), flow_context())); - } - - public function test_as_array_with_valid_array(): void - { - $parameter = new Parameter(lit(['key' => 'value', 'number' => 42])); - $result = $parameter->asArray(array_to_row([], schema()), flow_context()); - - static::assertSame(['key' => 'value', 'number' => 42], $result); + static::assertSame([null], (new Parameter(lit(null)))->asArrays(RowsMother::sequentialIds(1), flow_context())); } + /** + * @param null|bool $expected + */ #[DataProvider('boolean_data_provider')] public function test_as_boolean(mixed $input, ?bool $expected): void { - $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asBoolean(array_to_row([], schema()), flow_context())); + static::assertSame( + [$expected], + (new Parameter(lit($input)))->asBooleans(RowsMother::sequentialIds(1), flow_context()), + ); } - public function test_as_value_with_literal(): void + public function test_as_booleans_reads_a_boolean_column_as_is(): void { - static::assertNull((new Parameter(lit('literal_value')))->asValue(array_to_row([], schema()))); + static::assertSame( + [true, null, false], + (new Parameter((new ReferenceResolver())->resolve( + ref('b'), + array_to_rows([ + ['b' => true], + ['b' => null], + ['b' => false], + ], schema(bool_schema('b', nullable: true)))->schema(), + )))->asBooleans(array_to_rows([ + ['b' => true], + ['b' => null], + ['b' => false], + ], schema(bool_schema('b', nullable: true))), flow_context()), + ); } - public function test_as_value_with_missing_reference(): void + public function test_as_boolean_throws_on_a_malformed_value(): void { - static::assertNull((new Parameter(ref('missing_column')))->asValue(array_to_row([ - 'other_column' => 'test_value', - ], schema(str_schema('other_column'))))); + $this->expectException(InvalidArgumentException::class); + + (new Parameter(lit(['value'])))->asBooleans(RowsMother::sequentialIds(1), flow_context()); } - public function test_as_value_with_reference(): void + public function test_as_enum_propagates_null(): void { static::assertSame( - 'test_value', - (new Parameter(ref('test_column')))->asValue(array_to_row([ - 'test_column' => 'test_value', - ], schema(str_schema('test_column')))), + [null], + (new Parameter(lit(null)))->asEnums( + RowsMother::sequentialIds(1), + flow_context(), + SQLParametersStyle::class, + ), ); } @@ -205,36 +192,31 @@ public function test_as_enum_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an enum')))->asEnum( - array_to_row([], schema()), + (new Parameter(lit('not an enum')))->asEnums( + RowsMother::sequentialIds(1), flow_context(), SQLParametersStyle::class, ); } - public function test_as_enum_propagates_null(): void - { - static::assertNull((new Parameter(lit(null)))->asEnum( - array_to_row([], schema()), - flow_context(), - SQLParametersStyle::class, - )); - } - public function test_as_enum_with_valid_enum(): void { - $parameter = new Parameter(lit(SQLParametersStyle::NAMED)); - $result = $parameter->asEnum(array_to_row([], schema()), flow_context(), SQLParametersStyle::class); - - static::assertSame(SQLParametersStyle::NAMED, $result); + static::assertSame( + [SQLParametersStyle::NAMED], + (new Parameter(lit(SQLParametersStyle::NAMED)))->asEnums( + RowsMother::sequentialIds(1), + flow_context(), + SQLParametersStyle::class, + ), + ); } public function test_as_enum_with_wrong_enum_class(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit(SQLParametersStyle::NAMED)))->asEnum( - array_to_row([], schema()), + (new Parameter(lit(SQLParametersStyle::NAMED)))->asEnums( + RowsMother::sequentialIds(1), flow_context(), StringStyles::class, ); @@ -243,63 +225,131 @@ public function test_as_enum_with_wrong_enum_class(): void #[DataProvider('float_data_provider')] public function test_as_float(mixed $input, ?float $expected): void { - $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asFloat(array_to_row([], schema()), flow_context())); + static::assertSame( + [$expected], + (new Parameter(lit($input)))->asFloats(RowsMother::sequentialIds(1), flow_context()), + ); } - public function test_as_instance_of_throws_on_a_malformed_value(): void + public function test_as_floats_refuses_an_integer_column(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an object')))->asInstanceOf( - array_to_row([], schema()), - flow_context(), - DateTimeImmutable::class, - ); + (new Parameter((new ReferenceResolver())->resolve( + ref('id'), + RowsMother::sequentialIds(2)->schema(), + )))->asFloats(RowsMother::sequentialIds(2), flow_context()); + } + + public function test_as_float_throws_on_a_malformed_value(): void + { + $this->expectException(InvalidArgumentException::class); + + (new Parameter(lit('3.14')))->asFloats(RowsMother::sequentialIds(1), flow_context()); } public function test_as_instance_of_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asInstanceOf( - array_to_row([], schema()), + static::assertSame( + [null], + (new Parameter(lit(null)))->asInstancesOf( + RowsMother::sequentialIds(1), + flow_context(), + DateTimeImmutable::class, + ), + ); + } + + public function test_as_instance_of_throws_on_a_malformed_value(): void + { + $this->expectException(InvalidArgumentException::class); + + (new Parameter(lit('not an object')))->asInstancesOf( + RowsMother::sequentialIds(1), flow_context(), DateTimeImmutable::class, - )); + ); } public function test_as_instance_of_with_valid_object(): void { $dateTime = new DateTimeImmutable('2023-01-01'); - $parameter = new Parameter(lit($dateTime)); - - $result = $parameter->asInstanceOf(array_to_row([], schema()), flow_context(), DateTimeImmutable::class); - static::assertSame($dateTime, $result); - - $result = $parameter->asInstanceOf(array_to_row([], schema()), flow_context(), DateTimeInterface::class); - static::assertSame($dateTime, $result); + $rows = array_to_rows([['at' => $dateTime]], schema(datetime_schema('at'))); + + static::assertEquals( + [$dateTime], + (new Parameter((new ReferenceResolver())->resolve(ref('at'), $rows->schema())))->asInstancesOf( + $rows, + flow_context(), + DateTimeImmutable::class, + ), + ); + static::assertEquals( + [$dateTime], + (new Parameter((new ReferenceResolver())->resolve(ref('at'), $rows->schema())))->asInstancesOf( + $rows, + flow_context(), + DateTimeInterface::class, + ), + ); } #[DataProvider('int_data_provider')] public function test_as_int(mixed $input, ?int $default, ?int $expected): void { - $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asInt(array_to_row([], schema()), flow_context(), $default)); + static::assertSame( + [$expected], + (new Parameter(lit($input)))->asInts(RowsMother::sequentialIds(1), flow_context(), $default), + ); } - public function test_as_list_of_objects_with_empty_array(): void + public function test_as_ints_reads_an_integer_column_as_is_and_defaults_its_nulls(): void { - $parameter = new Parameter(lit([])); - $result = $parameter->asListOfObjects(array_to_row([], schema()), flow_context(), DateTimeImmutable::class); + $rows = array_to_rows([['n' => 1], ['n' => null]], schema(int_schema('n', nullable: true))); - static::assertSame([], $result); + static::assertSame( + [1, null], + (new Parameter((new ReferenceResolver())->resolve(ref('n'), $rows->schema())))->asInts( + $rows, + flow_context(), + ), + ); + static::assertSame( + [1, 7], + (new Parameter((new ReferenceResolver())->resolve(ref('n'), $rows->schema())))->asInts( + $rows, + flow_context(), + 7, + ), + ); + } + + public function test_as_int_throws_on_a_malformed_value(): void + { + // A default never applies to a malformed value - only to a NULL input. + $this->expectException(InvalidArgumentException::class); + + (new Parameter(lit(3.14)))->asInts(RowsMother::sequentialIds(1), flow_context(), 99); + } + + public function test_as_list_of_objects_propagates_null(): void + { + static::assertSame( + [null], + (new Parameter(lit(null)))->asListsOfObjects( + RowsMother::sequentialIds(1), + flow_context(), + DateTimeImmutable::class, + ), + ); } public function test_as_list_of_objects_throws_on_a_malformed_element(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit([new DateTimeImmutable('2023-01-01'), 'not an object'])))->asListOfObjects( - array_to_row([], schema()), + (new Parameter(lit([new DateTimeImmutable('2023-01-01'), 'not an object'])))->asListsOfObjects( + RowsMother::sequentialIds(1), flow_context(), DateTimeImmutable::class, ); @@ -309,38 +359,46 @@ public function test_as_list_of_objects_throws_on_a_non_array(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an array')))->asListOfObjects( - array_to_row([], schema()), + (new Parameter(lit('not an array')))->asListsOfObjects( + RowsMother::sequentialIds(1), flow_context(), DateTimeImmutable::class, ); } - public function test_as_list_of_objects_propagates_null(): void + public function test_as_list_of_objects_with_empty_array(): void { - static::assertNull((new Parameter(lit(null)))->asListOfObjects( - array_to_row([], schema()), - flow_context(), - DateTimeImmutable::class, - )); + static::assertSame( + [[]], + (new Parameter(lit([])))->asListsOfObjects( + RowsMother::sequentialIds(1), + flow_context(), + DateTimeImmutable::class, + ), + ); } public function test_as_list_of_objects_with_valid_array(): void { $date1 = new DateTimeImmutable('2023-01-01'); $date2 = new DateTimeImmutable('2023-01-02'); - $parameter = new Parameter(lit([$date1, $date2])); - $result = $parameter->asListOfObjects(array_to_row([], schema()), flow_context(), DateTimeImmutable::class); - static::assertSame([$date1, $date2], $result); + static::assertEquals( + [[$date1, $date2]], + (new Parameter(lit([$date1, $date2])))->asListsOfObjects( + RowsMother::sequentialIds(1), + flow_context(), + DateTimeImmutable::class, + ), + ); } public function test_as_list_of_objects_with_wrong_object_type(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit([new DateTimeImmutable('2023-01-01'), new stdClass()])))->asListOfObjects( - array_to_row([], schema()), + (new Parameter(lit([new DateTimeImmutable('2023-01-01'), new stdClass()])))->asListsOfObjects( + RowsMother::sequentialIds(1), flow_context(), DateTimeImmutable::class, ); @@ -349,110 +407,196 @@ public function test_as_list_of_objects_with_wrong_object_type(): void #[DataProvider('number_data_provider')] public function test_as_number(mixed $input, int|float|null $default, int|float|null $expected): void { - $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asNumber(array_to_row([], schema()), flow_context(), $default)); + static::assertSame( + [$expected], + (new Parameter(lit($input)))->asNumbers(RowsMother::sequentialIds(1), flow_context(), $default), + ); } - public function test_as_object_throws_on_a_malformed_value(): void + public function test_as_numbers_reads_numeric_columns_as_is_and_defaults_their_nulls(): void + { + $rows = array_to_rows([['f' => 1.5], ['f' => null]], schema(float_schema('f', nullable: true))); + + static::assertSame( + [1.5, null], + (new Parameter((new ReferenceResolver())->resolve(ref('f'), $rows->schema())))->asNumbers( + $rows, + flow_context(), + ), + ); + static::assertSame( + [1.5, 0], + (new Parameter((new ReferenceResolver())->resolve(ref('f'), $rows->schema())))->asNumbers( + $rows, + flow_context(), + 0, + ), + ); + } + + public function test_as_number_throws_on_a_malformed_value(): void { $this->expectException(InvalidArgumentException::class); - (new Parameter(lit('not an object')))->asObject(array_to_row([], schema()), flow_context()); + (new Parameter(lit('not numeric')))->asNumbers(RowsMother::sequentialIds(1), flow_context(), 99); } public function test_as_object_propagates_null(): void { - static::assertNull((new Parameter(lit(null)))->asObject(array_to_row([], schema()), flow_context())); + static::assertSame([null], (new Parameter(lit(null)))->asObjects(RowsMother::sequentialIds(1), flow_context())); + } + + public function test_as_object_throws_on_a_malformed_value(): void + { + $this->expectException(InvalidArgumentException::class); + + (new Parameter(lit('not an object')))->asObjects(RowsMother::sequentialIds(1), flow_context()); } public function test_as_object_with_valid_object(): void { $object = new stdClass(); $object->property = 'value'; - $parameter = new Parameter(lit($object)); - static::assertSame($object, $parameter->asObject(array_to_row([], schema()), flow_context())); + static::assertSame( + [$object], + (new Parameter(lit($object)))->asObjects(RowsMother::sequentialIds(1), flow_context()), + ); } - public function test_as_one_of(): void + #[DataProvider('string_data_provider')] + public function test_as_string(mixed $input, ?string $default, ?string $expected): void { - static::assertSame('42', (new Parameter(ref('value')))->as( - array_to_row(['value' => '42'], schema(str_schema('value'))), - flow_context(), - type_string(), - type_integer(), - )); + static::assertSame( + [$expected], + (new Parameter(lit($input)))->asStrings(RowsMother::sequentialIds(1), flow_context(), $default), + ); } - public function test_as_throws_when_no_type_matches(): void + public function test_as_strings_reads_a_string_column_as_is_and_defaults_its_nulls(): void { - $this->expectException(InvalidArgumentException::class); + $rows = array_to_rows([['s' => 'a'], ['s' => null]], schema(str_schema('s', nullable: true))); - (new Parameter(ref('value')))->as( - array_to_row(['value' => '42'], schema(str_schema('value'))), - flow_context(), - type_integer(), - type_boolean(), + static::assertSame( + ['a', null], + (new Parameter((new ReferenceResolver())->resolve(ref('s'), $rows->schema())))->asStrings( + $rows, + flow_context(), + ), + ); + static::assertSame( + ['a', 'x'], + (new Parameter((new ReferenceResolver())->resolve(ref('s'), $rows->schema())))->asStrings( + $rows, + flow_context(), + 'x', + ), ); } - public function test_as_propagates_null(): void + public function test_as_string_throws_on_a_malformed_value(): void { - static::assertNull((new Parameter(lit(null)))->as(array_to_row([], schema()), flow_context(), type_integer())); + $this->expectException(InvalidArgumentException::class); + + (new Parameter(lit(42)))->asStrings(RowsMother::sequentialIds(1), flow_context(), 'default'); } - public function test_as_scalar(): void + public function test_as_types_accepts_the_first_type_that_matches(): void { - static::assertSame('42', (new Parameter(ref('value')))->as( - array_to_row(['value' => '42'], schema(str_schema('value'))), - flow_context(), - type_string(), - )); + static::assertSame( + ['42'], + (new Parameter((new ReferenceResolver())->resolve( + ref('value'), + array_to_rows([['value' => '42']], schema(str_schema('value')))->schema(), + )))->asTypes( + array_to_rows([['value' => '42']], schema(str_schema('value'))), + flow_context(), + type_string(), + type_integer(), + ), + ); } - #[DataProvider('string_data_provider')] - public function test_as_string(mixed $input, ?string $default, ?string $expected): void + public function test_as_types_propagates_null(): void { - $parameter = new Parameter(lit($input)); - static::assertSame($expected, $parameter->asString(array_to_row([], schema()), flow_context(), $default)); + static::assertSame( + [null], + (new Parameter(lit(null)))->asTypes(RowsMother::sequentialIds(1), flow_context(), type_integer()), + ); } - public function test_constructor_with_mixed_value(): void + public function test_as_types_throws_when_no_type_matches(): void { - $parameter = new Parameter('direct_string'); - static::assertSame('direct_string', $parameter->eval(array_to_row([], schema()), flow_context())); - - $parameter = new Parameter(123); - static::assertSame(123, $parameter->eval(array_to_row([], schema()), flow_context())); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Expected one of "integer", "boolean", got "string". (row 0)'); - $parameter = new Parameter(true); - static::assertTrue($parameter->eval(array_to_row([], schema()), flow_context())); + (new Parameter((new ReferenceResolver())->resolve( + ref('value'), + array_to_rows([['value' => '42']], schema(str_schema('value')))->schema(), + )))->asTypes( + array_to_rows([['value' => '42']], schema(str_schema('value'))), + flow_context(), + type_integer(), + type_boolean(), + ); } - public function test_constructor_with_scalar_function(): void + public function test_a_refused_value_names_its_row(): void { - $scalarFunction = lit('test'); - $parameter = new Parameter($scalarFunction); - - static::assertSame('test', $parameter->eval(array_to_row([], schema()), flow_context())); + try { + (new Parameter((new ReferenceResolver())->resolve( + ref('value'), + array_to_rows([ + ['value' => '1'], + ['value' => '2'], + ['value' => 'x'], + ], schema(str_schema('value')))->schema(), + )))->asInts(array_to_rows([ + ['value' => '1'], + ['value' => '2'], + ['value' => 'x'], + ], schema(str_schema('value'))), flow_context()); + static::fail('expected an EvaluationException'); + } catch (EvaluationException $e) { + static::assertSame(0, $e->rowIndex); + static::assertInstanceOf(InvalidArgumentException::class, $e->getPrevious()); + } } - public function test_eval_with_direct_value(): void + public function test_column_evaluates_the_function(): void { - $parameter = new Parameter(lit('direct_value')); - static::assertSame('direct_value', $parameter->eval(array_to_row([], schema()), flow_context())); + $rows = array_to_rows([['column' => 'ref_value']], schema(str_schema('column'))); - $parameter = new Parameter(lit(42)); - static::assertSame(42, $parameter->eval(array_to_row([], schema()), flow_context())); + static::assertSame( + ['ref_value'], + (new Parameter((new ReferenceResolver())->resolve(ref('column'), $rows->schema()))) + ->column($rows, flow_context()) + ->values(), + ); } - public function test_eval_with_reference(): void + public function test_constructor_with_mixed_value(): void { - $parameter = new Parameter(ref('column')); - $result = $parameter->eval(array_to_row([ - 'column' => 'ref_value', - ], schema(str_schema('column'))), flow_context()); + static::assertSame( + ['direct_string'], + (new Parameter('direct_string'))->values(RowsMother::sequentialIds(1), flow_context()), + ); + static::assertSame([123], (new Parameter(123))->values(RowsMother::sequentialIds(1), flow_context())); + static::assertSame([true], (new Parameter(true))->values(RowsMother::sequentialIds(1), flow_context())); + } - static::assertSame('ref_value', $result); + public function test_values_read_an_array_result_back_as_arrays(): void + { + static::assertSame( + [['name' => 'a']], + (new Parameter((new ReferenceResolver())->resolve( + ref('j')->jsonDecode(), + array_to_rows([[ + 'j' => '{"name":"a"}', + ]], schema(json_schema('j')))->schema(), + )))->values(array_to_rows([[ + 'j' => '{"name":"a"}', + ]], schema(json_schema('j'))), flow_context()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PlusTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PlusTest.php new file mode 100644 index 0000000000..c2b31b87ed --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PlusTest.php @@ -0,0 +1,57 @@ +eval( + ref('a')->plus(ref('b'), exact: true), + ['a' => 0.1, 'b' => 0.2], + schema(float_schema('a'), float_schema('b')), + )); + } + + public function test_floats_use_ieee_arithmetic(): void + { + static::assertSame(0.30000000000000004, (new FunctionContext(flow_context()))->eval( + ref('a')->plus(ref('b')), + ['a' => 0.1, 'b' => 0.2], + schema(float_schema('a'), float_schema('b')), + )); + } + + public function test_integers_stay_integers(): void + { + static::assertSame(8, (new FunctionContext(flow_context()))->eval( + ref('a')->plus(ref('b')), + ['a' => 5, 'b' => 3], + schema(int_schema('a'), int_schema('b')), + )); + } + + public function test_integer_overflow_names_its_row(): void + { + $this->expectException(EvaluationException::class); + $this->expectExceptionMessage('Plus function integer overflow (row 0)'); + + (new FunctionContext(flow_context()))->eval( + ref('a')->plus(ref('b')), + ['a' => PHP_INT_MAX, 'b' => 1], + schema(int_schema('a'), int_schema('b')), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PowerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PowerTest.php index 84282d0d50..789b841234 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PowerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PowerTest.php @@ -4,10 +4,12 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; @@ -22,16 +24,66 @@ public function test_power_non_numeric_values(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "integer", got "string".'); - ref('int') - ->power(lit('non numeric')) - ->eval(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - ref('str')->power(lit(2))->eval(array_to_row(['str' => 'abc'], schema(str_schema('str'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('int')->power(lit('non numeric')), + ['int' => 10], + schema(int_schema('int')), + ); + (new FunctionContext(flow_context()))->eval( + ref('str')->power(lit(2)), + ['str' => 'abc'], + schema(str_schema('str')), + ); } public function test_power_two_numeric_values(): void { - static::assertSame(100, ref('int') - ->power(lit(2)) - ->eval(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context())); + static::assertSame(100, (new FunctionContext(flow_context()))->eval( + ref('int')->power(lit(2)), + ['int' => 10], + schema(int_schema('int')), + )); + } + + public function test_exact_keeps_decimal_arithmetic(): void + { + static::assertSame(1.21, (new FunctionContext(flow_context()))->eval( + ref('a')->power(ref('b'), exact: true), + ['a' => 1.1, 'b' => 2], + schema(float_schema('a'), int_schema('b')), + )); + } + + public function test_floats_use_ieee_arithmetic(): void + { + static::assertSame(1.2100000000000002, (new FunctionContext(flow_context()))->eval( + ref('a')->power(ref('b')), + ['a' => 1.1, 'b' => 2], + schema(float_schema('a'), int_schema('b')), + )); + } + + public function test_a_negative_exponent_of_an_integer_is_refused(): void + { + $this->expectException(EvaluationException::class); + $this->expectExceptionMessage('Power function of an integer requires a non-negative exponent (row 0)'); + + (new FunctionContext(flow_context()))->eval( + ref('a')->power(ref('b')), + ['a' => 2, 'b' => -1], + schema(int_schema('a'), int_schema('b')), + ); + } + + public function test_integer_overflow_names_its_row(): void + { + $this->expectException(EvaluationException::class); + $this->expectExceptionMessage('Power function integer overflow (row 0)'); + + (new FunctionContext(flow_context()))->eval( + ref('a')->power(ref('b')), + ['a' => 10, 'b' => 30], + schema(int_schema('a'), int_schema('b')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PregReplaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PregReplaceTest.php index a7a669e5d8..c28ab749df 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PregReplaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PregReplaceTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex_replace; @@ -22,7 +22,7 @@ public function test_preg_replace_expression_on_invalid_pattern(): void $pregReplace = regex_replace(lit(1), lit('bar'), lit('foo is awesome')); - $pregReplace->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregReplace, [], schema()); } public function test_preg_replace_expression_on_invalid_replacement(): void @@ -32,7 +32,7 @@ public function test_preg_replace_expression_on_invalid_replacement(): void $pregReplace = regex_replace(lit('/(foo)/'), lit(2), lit('foo is awesome')); - $pregReplace->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregReplace, [], schema()); } public function test_preg_replace_expression_on_invalid_subject(): void @@ -42,13 +42,13 @@ public function test_preg_replace_expression_on_invalid_subject(): void $pregReplace = regex_replace(lit('/(foo)/'), lit('bar'), lit(3)); - $pregReplace->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregReplace, [], schema()); } public function test_preg_replace_expression_on_valid_strings(): void { $pregReplace = regex_replace(lit('/(foo)/'), lit('bar'), lit('foo is awesome')); - static::assertSame('bar is awesome', $pregReplace->eval(array_to_row([], schema()), flow_context())); + static::assertSame('bar is awesome', (new FunctionContext(flow_context()))->eval($pregReplace, [], schema())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PrependTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PrependTest.php index 42a111c115..ad9468f5fa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PrependTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/PrependTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,44 +17,38 @@ final class PrependTest extends FlowTestCase { public function test_prepend_empty_string_to_content(): void { - $result = ref('str') - ->prepend('') - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->prepend(''), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_prepend_to_empty_string(): void { - $result = ref('str') - ->prepend('hello') - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); - - static::assertEquals('hello', $result); + static::assertEquals('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->prepend('hello'), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_prepend_to_non_empty_string(): void { - $result = ref('str') - ->prepend('Hello ') - ->eval(array_to_row(['str' => 'world'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello world', $result); + static::assertEquals('Hello world', (new FunctionContext(flow_context()))->eval( + ref('str')->prepend('Hello '), + ['str' => 'world'], + schema(str_schema('str')), + )); } public function test_prepend_with_null_prefix(): void { - $result = ref('str') - ->prepend(ref('prefix')) - ->eval( - array_to_row( - ['str' => 'world', 'prefix' => null], - schema(str_schema('str'), str_schema('prefix', nullable: true)), - ), - flow_context(), - ); - - static::assertEquals('world', $result); + static::assertEquals('world', (new FunctionContext(flow_context()))->eval( + ref('str')->prepend(ref('prefix')), + ['str' => 'world', 'prefix' => null], + schema(str_schema('str'), str_schema('prefix', nullable: true)), + )); } public function test_prepend_with_null_value(): void @@ -62,22 +56,19 @@ public function test_prepend_with_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Prepend function requires non-null value'); - $result = ref('str') - ->prepend('Hello ') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); - - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->prepend('Hello '), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_prepend_with_scalar_function_parameter(): void { - $result = ref('str') - ->prepend(ref('prefix')) - ->eval( - array_to_row(['str' => 'world', 'prefix' => 'Hello '], schema(str_schema('str'), str_schema('prefix'))), - flow_context(), - ); - - static::assertEquals('Hello world', $result); + static::assertEquals('Hello world', (new FunctionContext(flow_context()))->eval( + ref('str')->prepend(ref('prefix')), + ['str' => 'world', 'prefix' => 'Hello '], + schema(str_schema('str'), str_schema('prefix')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexAllTest.php index c8e19adb21..7e250ac621 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexAllTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex_all; @@ -22,14 +22,14 @@ public function test_regex_all_expression_on_invalid_subject(): void $pregMatch = regex_all(lit('/\d+/'), lit(2)); - $pregMatch->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatch, [], schema()); } public function test_regex_all_expression_on_no_match(): void { $pregMatch = regex_all(lit('/\d+/'), lit('apples and oranges')); - static::assertNull($pregMatch->eval(array_to_row([], schema()), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval($pregMatch, [], schema())); } public function test_regex_all_expression_on_valid_strings(): void @@ -42,7 +42,7 @@ public function test_regex_all_expression_on_valid_strings(): void ['124.23', '12', '45'], ['EUR', 'USD', 'PLN'], ], - $pregMatch->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval($pregMatch, [], schema()), ); } @@ -53,6 +53,6 @@ public function test_regex_expression_on_invalid_pattern(): void $pregMatch = regex_all(lit(1), lit('12 apples and 45 oranges')); - $pregMatch->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatch, [], schema()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchAllTest.php index f031055579..85a7b0c14d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchAllTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex_match_all; @@ -22,7 +22,7 @@ public function test_regex_match_all_expression_on_invalid_flags(): void $pregMatchAll = regex_match_all(lit('/\d+/'), lit('12 apples and 45 oranges'), lit('invalid')); - $pregMatchAll->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatchAll, [], schema()); } public function test_regex_match_all_expression_on_invalid_pattern(): void @@ -32,7 +32,7 @@ public function test_regex_match_all_expression_on_invalid_pattern(): void $pregMatchAll = regex_match_all(lit(1), lit('12 apples and 45 oranges')); - $pregMatchAll->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatchAll, [], schema()); } public function test_regex_match_all_expression_on_invalid_subject(): void @@ -42,14 +42,14 @@ public function test_regex_match_all_expression_on_invalid_subject(): void $pregMatchAll = regex_match_all(lit('/\d+/'), lit(2)); - $pregMatchAll->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatchAll, [], schema()); } public function test_regex_match_all_expression_on_valid_strings(): void { $pregMatchAll = regex_match_all(lit('/\d+/'), lit('12 apples and 45 oranges')); - static::assertTrue($pregMatchAll->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval($pregMatchAll, [], schema())); } public function test_regex_match_all_expression_on_valid_strings_with_flags(): void @@ -60,6 +60,6 @@ public function test_regex_match_all_expression_on_valid_strings_with_flags(): v lit(PREG_PATTERN_ORDER), ); - static::assertTrue($pregMatchAll->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval($pregMatchAll, [], schema())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchTest.php index f83c99d74f..67419212cb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexMatchTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex_match; @@ -22,7 +22,7 @@ public function test_regex_match_expression_on_invalid_pattern(): void $pregMatch = regex_match(lit(1), lit('12 apples and 45 oranges')); - $pregMatch->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatch, [], schema()); } public function test_regex_match_expression_on_invalid_subject(): void @@ -32,20 +32,20 @@ public function test_regex_match_expression_on_invalid_subject(): void $pregMatch = regex_match(lit('/\d+/'), lit(2)); - $pregMatch->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatch, [], schema()); } public function test_regex_match_expression_on_no_match(): void { $pregMatch = regex_match(lit('/\d+/'), lit('apples and oranges')); - static::assertFalse($pregMatch->eval(array_to_row([], schema()), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval($pregMatch, [], schema())); } public function test_regex_match_expression_on_valid_strings(): void { $pregMatch = regex_match(lit('/\d+/'), lit('12 apples and 45 oranges')); - static::assertTrue($pregMatch->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval($pregMatch, [], schema())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexReplaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexReplaceTest.php index 8961a7d4ba..6d7bce3633 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexReplaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexReplaceTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; @@ -18,15 +18,23 @@ final class RegexReplaceTest extends FlowTestCase { public function test_a_null_limit_still_means_unlimited(): void { - static::assertSame('x x x', regex_replace(lit('/a/'), lit('x'), ref('text'))->eval(array_to_row([ - 'text' => 'a a a', - ], schema(str_schema('text'))), flow_context())); + static::assertSame('x x x', (new FunctionContext(flow_context()))->eval( + regex_replace(lit('/a/'), lit('x'), ref('text')), + [ + 'text' => 'a a a', + ], + schema(str_schema('text')), + )); } public function test_a_limit_caps_the_replacements(): void { - static::assertSame('x a a', regex_replace(lit('/a/'), lit('x'), ref('text'), lit(1))->eval(array_to_row([ - 'text' => 'a a a', - ], schema(str_schema('text'))), flow_context())); + static::assertSame('x a a', (new FunctionContext(flow_context()))->eval( + regex_replace(lit('/a/'), lit('x'), ref('text'), lit(1)), + [ + 'text' => 'a a a', + ], + schema(str_schema('text')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexTest.php index ace87e4da6..bb3557bcc0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RegexTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\regex; @@ -23,7 +23,7 @@ public function test_regex_expression_on_invalid_pattern(): void $pregMatch = regex(lit(1), lit('12 apples and 45 oranges')); - $pregMatch->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatch, [], schema()); } public function test_regex_expression_on_invalid_subject(): void @@ -33,20 +33,20 @@ public function test_regex_expression_on_invalid_subject(): void $pregMatch = regex(lit('/\d+/'), lit(2)); - $pregMatch->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($pregMatch, [], schema()); } public function test_regex_expression_on_no_match(): void { $pregMatch = regex(lit('/\d+/'), lit('apples and oranges')); - static::assertNull($pregMatch->eval(array_to_row([], schema()), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval($pregMatch, [], schema())); } public function test_regex_expression_on_valid_strings(): void { $pregMatch = regex_match_all(lit('/\d+/'), lit('12 apples and 45 oranges')); - static::assertTrue($pregMatch->eval(array_to_row([], schema()), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval($pregMatch, [], schema())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RepeatTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RepeatTest.php index 8971595212..c947204b18 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RepeatTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RepeatTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -18,9 +18,11 @@ final class RepeatTest extends FlowTestCase { public function test_repeat_empty_string(): void { - static::assertSame('', ref('str') - ->repeat(3) - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); + static::assertSame('', (new FunctionContext(flow_context()))->eval( + ref('str')->repeat(3), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_repeat_negative_times(): void @@ -28,7 +30,11 @@ public function test_repeat_negative_times(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Repeat function requires non-null, positive times'); - ref('str')->repeat(-1)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->repeat(-1), + ['str' => 'hello'], + schema(str_schema('str')), + ); } public function test_repeat_null_input(): void @@ -36,16 +42,20 @@ public function test_repeat_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Repeat function requires non-null value'); - ref('str') - ->repeat(3) - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->repeat(3), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_repeat_string_multiple_times(): void { - static::assertSame('hellohellohello', ref('str') - ->repeat(3) - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame('hellohellohello', (new FunctionContext(flow_context()))->eval( + ref('str')->repeat(3), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_repeat_with_null_times(): void @@ -53,25 +63,20 @@ public function test_repeat_with_null_times(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Repeat function requires non-null, positive times'); - ref('str') - ->repeat(ref('times')) - ->eval( - array_to_row( - ['str' => 'hello', 'times' => null], - schema(str_schema('str'), str_schema('times', nullable: true)), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('str')->repeat(ref('times')), + ['str' => 'hello', 'times' => null], + schema(str_schema('str'), str_schema('times', nullable: true)), + ); } public function test_repeat_with_scalar_function_times(): void { - static::assertSame('hellohello', ref('str') - ->repeat(ref('times')) - ->eval( - array_to_row(['str' => 'hello', 'times' => 2], schema(str_schema('str'), int_schema('times'))), - flow_context(), - )); + static::assertSame('hellohello', (new FunctionContext(flow_context()))->eval( + ref('str')->repeat(ref('times')), + ['str' => 'hello', 'times' => 2], + schema(str_schema('str'), int_schema('times')), + )); } public function test_repeat_zero_times(): void @@ -79,6 +84,10 @@ public function test_repeat_zero_times(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Repeat function requires non-null, positive times'); - ref('str')->repeat(0)->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->repeat(0), + ['str' => 'hello'], + schema(str_schema('str')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReverseTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReverseTest.php index f004f48caa..dde38a5ebf 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReverseTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ReverseTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,16 +17,20 @@ final class ReverseTest extends FlowTestCase { public function test_reverse_ascii_string(): void { - static::assertSame('olleh', ref('str') - ->reverse() - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame('olleh', (new FunctionContext(flow_context()))->eval( + ref('str')->reverse(), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_reverse_empty_string(): void { - static::assertSame('', ref('str') - ->reverse() - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); + static::assertSame('', (new FunctionContext(flow_context()))->eval( + ref('str')->reverse(), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_reverse_throws_on_null_input(): void @@ -34,8 +38,10 @@ public function test_reverse_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Reverse function requires non-null value'); - ref('str') - ->reverse() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->reverse(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RoundTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RoundTest.php index a154ba5e83..f0aad8479f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RoundTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RoundTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Function\Round; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; @@ -18,29 +18,45 @@ final class RoundTest extends FlowTestCase { public function test_round_float(): void { - static::assertEquals(10.12, ref('float') - ->round(lit(2)) - ->eval(array_to_row(['float' => 10.123], schema(float_schema('float'))), flow_context())); - - static::assertIsFloat( - ref('float') - ->round(lit(2)) - ->eval(array_to_row(['float' => 10.123], schema(float_schema('float'))), flow_context()), - ); + static::assertEquals(10.12, (new FunctionContext(flow_context()))->eval( + ref('float')->round(lit(2)), + ['float' => 10.123], + schema(float_schema('float')), + )); + + static::assertIsFloat((new FunctionContext(flow_context()))->eval( + ref('float')->round(lit(2)), + ['float' => 10.123], + schema(float_schema('float')), + )); } public function test_round_with_precision_0(): void { - static::assertSame(10.0, ref('float') - ->round(lit(0)) - ->eval(array_to_row(['float' => 10.123], schema(float_schema('float'))), flow_context())); + static::assertSame(10.0, (new FunctionContext(flow_context()))->eval( + ref('float')->round(lit(0)), + ['float' => 10.123], + schema(float_schema('float')), + )); } public function test_constructor_default_matches_the_dsl_default(): void { - $row = array_to_row(['float' => 10.12345], schema(float_schema('float'))); - - static::assertSame(round(10.12345, 2), (new Round(ref('float')))->eval($row, flow_context())); - static::assertSame(round(10.12345, 2), ref('float')->round()->eval($row, flow_context())); + static::assertSame( + round(10.12345, 2), + (new FunctionContext(flow_context()))->eval( + new Round(ref('float')), + ['float' => 10.12345], + schema(float_schema('float')), + ), + ); + static::assertSame( + round(10.12345, 2), + (new FunctionContext(flow_context()))->eval( + ref('float')->round(), + ['float' => 10.12345], + schema(float_schema('float')), + ), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RowNumberTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RowNumberTest.php index 20eb566ab2..a47f1b35c3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RowNumberTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/RowNumberTest.php @@ -7,11 +7,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\row_number; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\window; @@ -19,32 +18,33 @@ final class RowNumberTest extends FlowTestCase { public function test_row_number_is_the_position_in_the_ordered_partition(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 5, 'value' => 1], + ['id' => 4, 'value' => 1], + ['id' => 3, 'value' => 1], + ['id' => 2, 'value' => 1], + ['id' => 1, 'value' => 1], + ], schema(int_schema('id'), int_schema('value')), - array_to_row(['id' => 5, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 4, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 3, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 2, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - $row1 = array_to_row(['id' => 1, 'value' => 1], schema(int_schema('id'), int_schema('value'))), ); $rowNumber = row_number()->over(window()->partitionBy(ref('value'))->orderBy(ref('id')->desc())); - static::assertSame(5, $rowNumber->apply(WindowContextMother::forRow($row1, $rows, 4))); + static::assertSame(5, $rowNumber->apply(WindowContextMother::atIndex($rows, 4))); } public function test_row_number_numbers_duplicated_rows_separately(): void { - $rows = rows( + $rows = array_to_rows( + [['id' => 1, 'value' => 100], ['id' => 1, 'value' => 100]], schema(int_schema('id'), int_schema('value')), - $row1 = array_to_row(['id' => 1, 'value' => 100], schema(int_schema('id'), int_schema('value'))), - $row2 = array_to_row(['id' => 1, 'value' => 100], schema(int_schema('id'), int_schema('value'))), ); $rowNumber = row_number()->over(window()->orderBy(ref('value'))); - static::assertSame(1, $rowNumber->apply(WindowContextMother::forRow($row1, $rows, 0))); - static::assertSame(2, $rowNumber->apply(WindowContextMother::forRow($row2, $rows, 1))); + static::assertSame(1, $rowNumber->apply(WindowContextMother::atIndex($rows, 0))); + static::assertSame(2, $rowNumber->apply(WindowContextMother::atIndex($rows, 1))); } public function test_with_children_returns_the_same_leaf(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SameTest.php index 389e3aea16..66d7d9a189 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SameTest.php @@ -4,29 +4,90 @@ namespace Flow\ETL\Tests\Unit\Function; +use DateInterval; +use DateTimeImmutable; +use DateTimeZone; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Tests\FlowTestCase; +use Flow\Types\Type; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\definition_from_type; use function Flow\ETL\DSL\flow_context; 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\Types\DSL\type_date; +use function Flow\Types\DSL\type_datetime; +use function Flow\Types\DSL\type_enum; +use function Flow\Types\DSL\type_json; +use function Flow\Types\DSL\type_time; +use function Flow\Types\DSL\type_uuid; final class SameTest extends FlowTestCase { public function test_null_is_identical_to_null(): void { // PHP identity, not SQL equality - ->same() is the migration path for both-null checks. - static::assertTrue( - ref('a') - ->same(lit(null)) - ->eval(array_to_row(['a' => null], schema(str_schema('a', nullable: true))), flow_context()), - ); - static::assertFalse( - ref('a') - ->same(lit(1)) - ->eval(array_to_row(['a' => null], schema(str_schema('a', nullable: true))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('a')->same(lit(null)), + ['a' => null], + schema(str_schema('a', nullable: true)), + )); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('a')->same(lit(1)), + ['a' => null], + schema(str_schema('a', nullable: true)), + )); + } + + /** + * @return Generator, mixed, mixed, bool}> + */ + public static function values_of_one_type(): Generator + { + yield 'uuid' => [ + type_uuid(), + '00000000-0000-4000-8000-000000000001', + '00000000-0000-4000-8000-000000000001', + true, + ]; + yield 'other uuid' => [ + type_uuid(), + '00000000-0000-4000-8000-000000000001', + '00000000-0000-4000-8000-000000000002', + false, + ]; + yield 'json' => [type_json(), '{"a":1,"b":2}', '{"a":1,"b":2}', true]; + yield 'json compares its stored text' => [type_json(), '{"a":1,"b":2}', '{"b":2,"a":1}', false]; + yield 'enum' => [type_enum(BackedStringEnum::class), BackedStringEnum::one, BackedStringEnum::one, true]; + yield 'datetime of the same instant in another zone' => [ + type_datetime(), + new DateTimeImmutable('2024-01-01 12:00:00', new DateTimeZone('UTC')), + new DateTimeImmutable('2024-01-01 13:00:00', new DateTimeZone('Europe/Warsaw')), + true, + ]; + yield 'date' => [type_date(), new DateTimeImmutable('2024-01-01'), new DateTimeImmutable('2024-01-01'), true]; + yield 'time' => [type_time(), new DateInterval('PT60M'), new DateInterval('PT1H'), true]; + } + + /** + * @param Type $type + */ + #[DataProvider('values_of_one_type')] + public function test_values_of_one_type_are_the_same_by_value( + Type $type, + mixed $left, + mixed $right, + bool $same, + ): void { + static::assertSame($same, (new FunctionContext(flow_context()))->eval( + ref('a')->same(ref('b')), + ['a' => $left, 'b' => $right], + schema(definition_from_type('a', $type), definition_from_type('b', $type)), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SanitizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SanitizeTest.php index 4b2157a839..88d66e43b9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SanitizeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SanitizeTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; @@ -22,34 +22,46 @@ public function test_sanitize_on_non_string_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "string", got "integer".'); - ref('value')->sanitize()->eval(array_to_row(['value' => 1000], schema(int_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->sanitize(), + ['value' => 1000], + schema(int_schema('value')), + ); } public function test_sanitize_on_valid_string(): void { - static::assertSame('****', ref('value') - ->sanitize() - ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); + static::assertSame('****', (new FunctionContext(flow_context()))->eval( + ref('value')->sanitize(), + ['value' => 'test'], + schema(str_schema('value')), + )); } public function test_sanitize_on_valid_string_with_left_characters(): void { - static::assertSame('te**', ref('value') - ->sanitize(skipCharacters: lit(2)) - ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); + static::assertSame('te**', (new FunctionContext(flow_context()))->eval( + ref('value')->sanitize(skipCharacters: lit(2)), + ['value' => 'test'], + schema(str_schema('value')), + )); } public function test_sanitize_on_valid_string_with_left_characters_longer_than_string(): void { - static::assertSame('****', ref('value') - ->sanitize(skipCharacters: lit(5)) - ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); + static::assertSame('****', (new FunctionContext(flow_context()))->eval( + ref('value')->sanitize(skipCharacters: lit(5)), + ['value' => 'test'], + schema(str_schema('value')), + )); } public function test_sanitize_on_valid_string_with_placeholder(): void { - static::assertSame('----', ref('value') - ->sanitize(lit('-')) - ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); + static::assertSame('----', (new FunctionContext(flow_context()))->eval( + ref('value')->sanitize(lit('-')), + ['value' => 'test'], + schema(str_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SizeTest.php index 3730982cfc..2fdba80d9d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SizeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SizeTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\schema; @@ -16,16 +16,20 @@ final class SizeTest extends FlowTestCase { public function test_size_expression_on_array_value(): void { - static::assertSame(3, size(lit(['foo', 'bar', 'baz']))->eval(array_to_row([], schema()), flow_context())); + static::assertSame(3, (new FunctionContext(flow_context()))->eval( + size(lit(['foo', 'bar', 'baz'])), + [], + schema(), + )); } public function test_size_expression_on_integer_value(): void { - static::assertNull(size(lit(1))->eval(array_to_row([], schema()), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval(size(lit(1)), [], schema())); } public function test_size_expression_on_string_value(): void { - static::assertSame(3, size(lit('foo'))->eval(array_to_row([], schema()), flow_context())); + static::assertSame(3, (new FunctionContext(flow_context()))->eval(size(lit('foo')), [], schema())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SlugTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SlugTest.php index 636fb9ebd9..515bc4afd1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SlugTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SlugTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; @@ -20,9 +20,11 @@ public function test_a_malformed_separator_operand_throws(): void { $this->expectException(InvalidArgumentException::class); - ref('value') - ->slug(lit(123)) - ->eval(array_to_row(['value' => 'hello world'], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->slug(lit(123)), + ['value' => 'hello world'], + schema(str_schema('value')), + ); } public function test_ascii_on_null(): void @@ -30,22 +32,28 @@ public function test_ascii_on_null(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Slug function requires non-null value'); - ref('str') - ->slug() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->slug(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_slug(): void { - static::assertSame('azcz', ref('str') - ->slug() - ->eval(array_to_row(['str' => 'ąźćż'], schema(str_schema('str'))), flow_context())); + static::assertSame('azcz', (new FunctionContext(flow_context()))->eval( + ref('str')->slug(), + ['str' => 'ąźćż'], + schema(str_schema('str')), + )); } public function test_slug_separator(): void { - static::assertSame('Some_Text', ref('str') - ->slug('_') - ->eval(array_to_row(['str' => 'Some Text'], schema(str_schema('str'))), flow_context())); + static::assertSame('Some_Text', (new FunctionContext(flow_context()))->eval( + ref('str')->slug('_'), + ['str' => 'Some Text'], + schema(str_schema('str')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SplitTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SplitTest.php index 819d7fa8b1..a87af464f1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SplitTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SplitTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\schema; @@ -20,14 +20,14 @@ public function test_split_not_string(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Expected type "string", got "integer".'); - split(lit(123), ',')->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval(split(lit(123), ','), [], schema()); } public function test_split_string(): void { static::assertSame( ['foo', 'bar', 'baz'], - split(lit('foo,bar,baz'), ',')->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval(split(lit('foo,bar,baz'), ','), [], schema()), ); } @@ -35,7 +35,7 @@ public function test_split_string_with_limit(): void { static::assertSame( ['foo', 'bar,baz'], - split(lit('foo,bar,baz'), ',', 2)->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval(split(lit('foo,bar,baz'), ',', 2), [], schema()), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SprintfTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SprintfTest.php index 3f37938833..6e7aafacd2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SprintfTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SprintfTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\schema; @@ -22,13 +22,17 @@ public function test_sprintf_expression_on_invalid_format(): void $sprintf = sprintf(lit(1), lit('John'), lit(25)); - $sprintf->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval($sprintf, [], schema()); } public function test_sprintf_expression_on_valid_format_and_args(): void { $sprintf = sprintf(lit('Hello, %s! Your age is %d.'), lit('John'), lit(25)); - static::assertSame('Hello, John! Your age is 25.', $sprintf->eval(array_to_row([], schema()), flow_context())); + static::assertSame('Hello, John! Your age is 25.', (new FunctionContext(flow_context()))->eval( + $sprintf, + [], + schema(), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrPadTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrPadTest.php index 5936b0f3f3..ab01aabbf5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrPadTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrPadTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -18,8 +18,10 @@ final class StrPadTest extends FlowTestCase { public function test_str_pad_on_valid_string(): void { - static::assertSame('----N', ref('value') - ->strPad(5, '-', STR_PAD_LEFT) - ->eval(array_to_row(['value' => 'N'], schema(str_schema('value'))), flow_context())); + static::assertSame('----N', (new FunctionContext(flow_context()))->eval( + ref('value')->strPad(5, '-', STR_PAD_LEFT), + ['value' => 'N'], + schema(str_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrReplaceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrReplaceTest.php index f09abe2864..448444a9ed 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrReplaceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StrReplaceTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -16,15 +16,19 @@ final class StrReplaceTest extends FlowTestCase { public function test_str_replace_on_valid_string(): void { - static::assertSame('1', ref('value') - ->strReplace('test', '1') - ->eval(array_to_row(['value' => 'test'], schema(str_schema('value'))), flow_context())); + static::assertSame('1', (new FunctionContext(flow_context()))->eval( + ref('value')->strReplace('test', '1'), + ['value' => 'test'], + schema(str_schema('value')), + )); } public function test_str_replace_on_valid_string_with_array_of_replacements(): void { - static::assertSame('test was successful', ref('value') - ->strReplace(['is', 'broken'], ['was', 'successful']) - ->eval(array_to_row(['value' => 'test is broken'], schema(str_schema('value'))), flow_context())); + static::assertSame('test was successful', (new FunctionContext(flow_context()))->eval( + ref('value')->strReplace(['is', 'broken'], ['was', 'successful']), + ['value' => 'test is broken'], + schema(str_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterLastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterLastTest.php index 12bc1be420..d7d387fa36 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterLastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterLastTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,28 +17,20 @@ final class StringAfterLastTest extends FlowTestCase { public function test_string_after_last(): void { - static::assertSame('rld', ref('str') - ->stringAfterLast(ref('needle')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'o'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); + static::assertSame('rld', (new FunctionContext(flow_context()))->eval( + ref('str')->stringAfterLast(ref('needle')), + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_after_last_including_needle(): void { - static::assertSame('orld', ref('str') - ->stringAfterLast(ref('needle'), includeNeedle: true) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'o'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); + static::assertSame('orld', (new FunctionContext(flow_context()))->eval( + ref('str')->stringAfterLast(ref('needle'), includeNeedle: true), + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_after_last_throws_on_null_input(): void @@ -46,8 +38,10 @@ public function test_string_after_last_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringAfterLast function requires non-null value'); - ref('str') - ->stringAfterLast('x') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringAfterLast('x'), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterTest.php index 9bfb7c84e0..4477421804 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAfterTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,38 +17,26 @@ final class StringAfterTest extends FlowTestCase { public function test_string_after(): void { - static::assertSame(' world', ref('str') - ->stringAfter(ref('needle')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'hello'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); - - static::assertSame(' world', ref('str') - ->stringAfter(ref('needle')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'o'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); + static::assertSame(' world', (new FunctionContext(flow_context()))->eval( + ref('str')->stringAfter(ref('needle')), + ['str' => 'hello world', 'needle' => 'hello'], + schema(str_schema('str'), str_schema('needle')), + )); + + static::assertSame(' world', (new FunctionContext(flow_context()))->eval( + ref('str')->stringAfter(ref('needle')), + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_after_including_needle(): void { - static::assertSame('o world', ref('str') - ->stringAfter(ref('needle'), includeNeedle: true) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'o'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); + static::assertSame('o world', (new FunctionContext(flow_context()))->eval( + ref('str')->stringAfter(ref('needle'), includeNeedle: true), + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_after_throws_on_null_input(): void @@ -56,8 +44,10 @@ public function test_string_after_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringAfter function requires non-null value'); - ref('str') - ->stringAfter('x') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringAfter('x'), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAggregateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAggregateTest.php index 41619fd5ff..4a2651092c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAggregateTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringAggregateTest.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Row\SortOrder; use Flow\ETL\Tests\FlowTestCase; +use PHPUnit\Framework\Attributes\TestWith; -use function Flow\ETL\DSL\array_to_row; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\collect; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -26,10 +30,10 @@ public function test_string_agg(): void { $aggregator = string_agg(ref('data')); - $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'a']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'c']], schema(str_schema('data'))), [0], flow_context()); static::assertSame('a, b, b, c', $aggregator->value()); static::assertSame('data_str_agg', $aggregator->outputName()); @@ -46,10 +50,10 @@ public function test_string_agg_on_non_string(): void { $aggregator = string_agg(ref('data'), sort: SortOrder::DESC); - $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 1], schema(int_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'a']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 1]], schema(int_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'c']], schema(str_schema('data'))), [0], flow_context()); static::assertSame('c, b, a', $aggregator->value()); } @@ -58,10 +62,10 @@ public function test_string_agg_with_alias(): void { $aggregator = string_agg(ref('data')->as('string')); - $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'a']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'c']], schema(str_schema('data'))), [0], flow_context()); static::assertSame('a, b, b, c', $aggregator->value()); static::assertSame('string', $aggregator->outputName()); @@ -71,14 +75,33 @@ public function test_string_agg_with_order(): void { $aggregator = string_agg(ref('data'), sort: SortOrder::DESC); - $aggregator->aggregate(array_to_row(['data' => 'a'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'b'], schema(str_schema('data'))), flow_context()); - $aggregator->aggregate(array_to_row(['data' => 'c'], schema(str_schema('data'))), flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'a']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'b']], schema(str_schema('data'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['data' => 'c']], schema(str_schema('data'))), [0], flow_context()); static::assertSame('c, b, b, a', $aggregator->value()); } + #[TestWith([SortOrder::ASC, '10,100,9,B'])] + #[TestWith([SortOrder::DESC, 'B,9,100,10'])] + public function test_string_agg_orders_numeric_looking_strings_by_bytes(SortOrder $order, string $expected): void + { + $aggregator = string_agg(ref('data'), ',', $order); + $aggregator->aggregate( + array_to_rows([ + ['data' => '9'], + ['data' => '10'], + ['data' => '100'], + ['data' => 'B'], + ], schema(str_schema('data'))), + [0, 1, 2, 3], + flow_context(), + ); + + static::assertSame($expected, $aggregator->value()); + } + public function test_with_children_rebuilds_the_aggregate_with_the_given_reference(): void { $aggregate = string_agg(ref('a')); @@ -90,4 +113,48 @@ public function test_with_children_rebuilds_the_aggregate_with_the_given_referen static::assertNotSame($aggregate, $rebuilt); static::assertEquals([ref('b')], $rebuilt->references()); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = string_agg(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 'a', + 'b', + 'c', + 'd', + ]), schema(str_schema('v'))), + [1, 3], + flow_context(), + ); + + static::assertSame('b, d', $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 'a', + 'b', + 'c', + 'd', + ]), schema(str_schema('v'))); + $onePass = string_agg(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = string_agg(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = string_agg(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + string_agg(ref('v'))->merge(collect(ref('v')), flow_context()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeLastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeLastTest.php index bb8499a34a..acc98e2273 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeLastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeLastTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,38 +17,29 @@ final class StringBeforeLastTest extends FlowTestCase { public function test_string_before_last(): void { - static::assertSame('hello w', ref('str') - ->stringBeforeLast(ref('needle')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'o'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); + static::assertSame('hello w', (new FunctionContext(flow_context()))->eval( + ref('str')->stringBeforeLast(ref('needle')), + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_before_last_including_needle(): void { - static::assertSame('hello wo', ref('str') - ->stringBeforeLast(ref('needle'), includeNeedle: true) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'o'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); + static::assertSame('hello wo', (new FunctionContext(flow_context()))->eval( + ref('str')->stringBeforeLast(ref('needle'), includeNeedle: true), + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_before_last_returns_empty_string(): void { - static::assertSame('', ref('str') - ->stringBeforeLast(ref('needle')) - ->eval( - array_to_row(['str' => '', 'needle' => 'o'], schema(str_schema('str'), str_schema('needle'))), - flow_context(), - )); + static::assertSame('', (new FunctionContext(flow_context()))->eval( + ref('str')->stringBeforeLast(ref('needle')), + ['str' => '', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_before_last_throws_on_null_input(): void @@ -56,14 +47,10 @@ public function test_string_before_last_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringBeforeLast function requires non-null value'); - ref('str') - ->stringBeforeLast(ref('needle')) - ->eval( - array_to_row( - ['str' => null, 'needle' => 'o'], - schema(str_schema('str', nullable: true), str_schema('needle')), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringBeforeLast(ref('needle')), + ['str' => null, 'needle' => 'o'], + schema(str_schema('str', nullable: true), str_schema('needle')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeTest.php index 6d8d98ab80..5c268ce87a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringBeforeTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,48 +17,35 @@ final class StringBeforeTest extends FlowTestCase { public function test_string_before(): void { - static::assertSame('hello ', ref('str') - ->stringBefore(ref('needle')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'world'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); - - static::assertSame('hell', ref('str') - ->stringBefore(ref('needle')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'o'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); + static::assertSame('hello ', (new FunctionContext(flow_context()))->eval( + ref('str')->stringBefore(ref('needle')), + ['str' => 'hello world', 'needle' => 'world'], + schema(str_schema('str'), str_schema('needle')), + )); + + static::assertSame('hell', (new FunctionContext(flow_context()))->eval( + ref('str')->stringBefore(ref('needle')), + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_before_including_needle(): void { - static::assertSame('hello', ref('str') - ->stringBefore(ref('needle'), includeNeedle: true) - ->eval( - array_to_row( - ['str' => 'hello world', 'needle' => 'o'], - schema(str_schema('str'), str_schema('needle')), - ), - flow_context(), - )); + static::assertSame('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->stringBefore(ref('needle'), includeNeedle: true), + ['str' => 'hello world', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_before_returns_empty_string(): void { - static::assertSame('', ref('str') - ->stringBefore(ref('needle')) - ->eval( - array_to_row(['str' => '', 'needle' => 'o'], schema(str_schema('str'), str_schema('needle'))), - flow_context(), - )); + static::assertSame('', (new FunctionContext(flow_context()))->eval( + ref('str')->stringBefore(ref('needle')), + ['str' => '', 'needle' => 'o'], + schema(str_schema('str'), str_schema('needle')), + )); } public function test_string_before_throws_on_null_input(): void @@ -66,14 +53,10 @@ public function test_string_before_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringBefore function requires non-null value'); - ref('str') - ->stringBefore(ref('needle')) - ->eval( - array_to_row( - ['str' => null, 'needle' => 'o'], - schema(str_schema('str', nullable: true), str_schema('needle')), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringBefore(ref('needle')), + ['str' => null, 'needle' => 'o'], + schema(str_schema('str', nullable: true), str_schema('needle')), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringContainsAnyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringContainsAnyTest.php index a27f2c9433..afd6d9f1cc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringContainsAnyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringContainsAnyTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; @@ -24,75 +24,65 @@ public function test_contains_any_empty_needles_array(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringContainsAny function requires a non-empty needles array'); - ref('str') - ->stringContainsAny([]) - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringContainsAny([]), + ['str' => 'hello world'], + schema(str_schema('str')), + ); } public function test_contains_any_multiple_needles_one_found(): void { - static::assertTrue( - ref('str') - ->stringContainsAny(['foo', 'world', 'bar']) - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('str')->stringContainsAny(['foo', 'world', 'bar']), + ['str' => 'hello world'], + schema(str_schema('str')), + )); } public function test_contains_any_no_needles_found(): void { - static::assertFalse( - ref('str') - ->stringContainsAny(['foo', 'bar', 'baz']) - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()), - ); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('str')->stringContainsAny(['foo', 'bar', 'baz']), + ['str' => 'hello world'], + schema(str_schema('str')), + )); } public function test_contains_any_null_needles(): void { - static::assertNull( - ref('str') - ->stringContainsAny(ref('needles')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needles' => null], - schema(str_schema('str'), str_schema('needles', nullable: true)), - ), - flow_context(), - ), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->stringContainsAny(ref('needles')), + ['str' => 'hello world', 'needles' => null], + schema(str_schema('str'), str_schema('needles', nullable: true)), + )); } public function test_contains_any_null_string(): void { - static::assertNull( - ref('str') - ->stringContainsAny(['hello', 'world']) - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->stringContainsAny(['hello', 'world']), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_contains_any_null_string_in_strict_mode(): void { $context = flow_context(config()); - static::assertNull( - ref('str') - ->stringContainsAny(['hello', 'world']) - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), $context), - ); + static::assertNull((new FunctionContext($context))->eval( + ref('str')->stringContainsAny(['hello', 'world']), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_contains_any_with_scalar_function_parameter(): void { - static::assertTrue( - ref('str') - ->stringContainsAny(ref('needles')) - ->eval( - array_to_row( - ['str' => 'hello world', 'needles' => ['world', 'foo']], - schema(str_schema('str'), list_schema('needles', type_list(type_string()))), - ), - flow_context(), - ), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('str')->stringContainsAny(ref('needles')), + ['str' => 'hello world', 'needles' => ['world', 'foo']], + schema(str_schema('str'), list_schema('needles', type_list(type_string()))), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringEqualsToTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringEqualsToTest.php index df8b9d0991..c24dc19ecf 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringEqualsToTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringEqualsToTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -16,67 +16,55 @@ final class StringEqualsToTest extends FlowTestCase { public function test_equals_to_empty_strings(): void { - static::assertTrue( - ref('str') - ->stringEqualsTo('') - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('str')->stringEqualsTo(''), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_equals_to_exact_match(): void { - static::assertTrue( - ref('str') - ->stringEqualsTo('hello') - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('str')->stringEqualsTo('hello'), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_equals_to_no_match(): void { - static::assertFalse( - ref('str') - ->stringEqualsTo('world') - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context()), - ); + static::assertFalse((new FunctionContext(flow_context()))->eval( + ref('str')->stringEqualsTo('world'), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_equals_to_null_comparison_string_returns_null(): void { - static::assertNull( - ref('str') - ->stringEqualsTo(ref('compare')) - ->eval( - array_to_row( - ['str' => 'hello', 'compare' => null], - schema(str_schema('str'), str_schema('compare', nullable: true)), - ), - flow_context(), - ), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->stringEqualsTo(ref('compare')), + ['str' => 'hello', 'compare' => null], + schema(str_schema('str'), str_schema('compare', nullable: true)), + )); } public function test_equals_to_null_string_returns_null(): void { - static::assertNull( - ref('str') - ->stringEqualsTo('hello') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->stringEqualsTo('hello'), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_equals_to_with_scalar_function_parameter(): void { - static::assertTrue( - ref('str') - ->stringEqualsTo(ref('compare')) - ->eval( - array_to_row( - ['str' => 'hello', 'compare' => 'hello'], - schema(str_schema('str'), str_schema('compare')), - ), - flow_context(), - ), - ); + static::assertTrue((new FunctionContext(flow_context()))->eval( + ref('str')->stringEqualsTo(ref('compare')), + ['str' => 'hello', 'compare' => 'hello'], + schema(str_schema('str'), str_schema('compare')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringFoldTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringFoldTest.php index 75affd5b85..a2f3ab0fee 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringFoldTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringFoldTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,9 +17,11 @@ final class StringFoldTest extends FlowTestCase { public function test_string_folded(): void { - static::assertSame("die o'brian strasse", ref('str') - ->stringFold() - ->eval(array_to_row(['str' => "Die O'Brian Straße"], schema(str_schema('str'))), flow_context())); + static::assertSame("die o'brian strasse", (new FunctionContext(flow_context()))->eval( + ref('str')->stringFold(), + ['str' => "Die O'Brian Straße"], + schema(str_schema('str')), + )); } public function test_string_fold_throws_on_null_input(): void @@ -27,8 +29,10 @@ public function test_string_fold_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringFold function requires non-null value'); - ref('str') - ->stringFold() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringFold(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchAllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchAllTest.php index a56e7b0f9f..b2f5fc097f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchAllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchAllTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,29 +17,38 @@ final class StringMatchAllTest extends FlowTestCase { public function test_empty_haystack_string(): void { - $result = ref('str') - ->stringMatchAll('/hello/') - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); - - static::assertEquals([], $result); + static::assertEquals( + [], + (new FunctionContext(flow_context()))->eval( + ref('str')->stringMatchAll('/hello/'), + ['str' => ''], + schema(str_schema('str')), + ), + ); } public function test_multiple_successful_pattern_matches(): void { - $result = ref('str') - ->stringMatchAll('/\d+/') - ->eval(array_to_row(['str' => 'test 123 and 456 and 789'], schema(str_schema('str'))), flow_context()); - - static::assertEquals([['123'], ['456'], ['789']], $result); + static::assertEquals( + [['123'], ['456'], ['789']], + (new FunctionContext(flow_context()))->eval( + ref('str')->stringMatchAll('/\d+/'), + ['str' => 'test 123 and 456 and 789'], + schema(str_schema('str')), + ), + ); } public function test_no_matches_found(): void { - $result = ref('str') - ->stringMatchAll('/foo/') - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()); - - static::assertEquals([], $result); + static::assertEquals( + [], + (new FunctionContext(flow_context()))->eval( + ref('str')->stringMatchAll('/foo/'), + ['str' => 'hello world'], + schema(str_schema('str')), + ), + ); } public function test_null_haystack(): void @@ -47,9 +56,11 @@ public function test_null_haystack(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringMatchAll function requires non-null haystack'); - ref('str') - ->stringMatchAll('/hello/') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringMatchAll('/hello/'), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_null_pattern(): void @@ -57,29 +68,22 @@ public function test_null_pattern(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringMatchAll function requires non-null pattern'); - ref('str') - ->stringMatchAll(ref('pattern')) - ->eval( - array_to_row( - ['str' => 'hello world', 'pattern' => null], - schema(str_schema('str'), str_schema('pattern', nullable: true)), - ), - flow_context(), - ); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringMatchAll(ref('pattern')), + ['str' => 'hello world', 'pattern' => null], + schema(str_schema('str'), str_schema('pattern', nullable: true)), + ); } public function test_with_scalar_function_parameter(): void { - $result = ref('str') - ->stringMatchAll(ref('pattern')) - ->eval( - array_to_row( - ['str' => 'test 123 and 456', 'pattern' => '/\d+/'], - schema(str_schema('str'), str_schema('pattern')), - ), - flow_context(), - ); - - static::assertEquals([['123'], ['456']], $result); + static::assertEquals( + [['123'], ['456']], + (new FunctionContext(flow_context()))->eval( + ref('str')->stringMatchAll(ref('pattern')), + ['str' => 'test 123 and 456', 'pattern' => '/\d+/'], + schema(str_schema('str'), str_schema('pattern')), + ), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchTest.php index 567952e402..02a7192367 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringMatchTest.php @@ -4,11 +4,13 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; +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; @@ -17,11 +19,11 @@ final class StringMatchTest extends FlowTestCase { public function test_no_matches_found(): void { - $result = ref('str') - ->stringMatch('/foo/') - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()); - - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->stringMatch('/foo/'), + ['str' => 'hello world'], + schema(str_schema('str')), + )); } public function test_null_haystack(): void @@ -29,11 +31,11 @@ public function test_null_haystack(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringMatch function requires non-null haystack'); - $result = ref('str') - ->stringMatch('/hello/') - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); - - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->stringMatch('/hello/'), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_null_pattern(): void @@ -41,40 +43,49 @@ public function test_null_pattern(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringMatch function requires non-null pattern'); - $result = ref('str') - ->stringMatch(ref('pattern')) - ->eval( - array_to_row( - ['str' => 'hello world', 'pattern' => null], - schema(str_schema('str'), str_schema('pattern', nullable: true)), - ), - flow_context(), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->stringMatch(ref('pattern')), + ['str' => 'hello world', 'pattern' => null], + schema(str_schema('str'), str_schema('pattern', nullable: true)), + )); + } - static::assertNull($result); + public function test_an_invalid_pattern_keeps_the_regex_error_as_the_cause(): void + { + try { + (new FunctionContext(flow_context()))->eval( + ref('value')->stringMatch(lit('/(/')), + ['value' => 'abc'], + schema(str_schema('value')), + ); + static::fail('An invalid pattern must be refused.'); + } catch (EvaluationException $e) { + static::assertStringStartsWith('StringMatch error: ', (string) $e->getPrevious()?->getMessage()); + static::assertNotNull($e->getPrevious()?->getPrevious()); + } } public function test_successful_pattern_match(): void { - $result = ref('str') - ->stringMatch('/hello/') - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context()); - - static::assertEquals(['hello'], $result); + static::assertEquals( + ['hello'], + (new FunctionContext(flow_context()))->eval( + ref('str')->stringMatch('/hello/'), + ['str' => 'hello world'], + schema(str_schema('str')), + ), + ); } public function test_with_scalar_function_parameter(): void { - $result = ref('str') - ->stringMatch(ref('pattern')) - ->eval( - array_to_row( - ['str' => 'hello world', 'pattern' => '/world/'], - schema(str_schema('str'), str_schema('pattern')), - ), - flow_context(), - ); - - static::assertEquals(['world'], $result); + static::assertEquals( + ['world'], + (new FunctionContext(flow_context()))->eval( + ref('str')->stringMatch(ref('pattern')), + ['str' => 'hello world', 'pattern' => '/world/'], + schema(str_schema('str'), str_schema('pattern')), + ), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringNormalizeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringNormalizeTest.php index 4b0e0266aa..33ffd192f3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringNormalizeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringNormalizeTest.php @@ -5,10 +5,10 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Normalizer; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; @@ -22,44 +22,56 @@ public function test_a_malformed_form_operand_throws(): void { $this->expectException(InvalidArgumentException::class); - ref('value') - ->stringNormalize(lit('not-a-form')) - ->eval(array_to_row(['value' => 'abc'], schema(str_schema('value'))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->stringNormalize(lit('not-a-form')), + ['value' => 'abc'], + schema(str_schema('value')), + ); } public function test_normalize_already_normalized(): void { - static::assertSame('hello', ref('str') - ->stringNormalize(Normalizer::NFC) - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->stringNormalize(Normalizer::NFC), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_normalize_empty_string(): void { - static::assertSame('', ref('str') - ->stringNormalize() - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); + static::assertSame('', (new FunctionContext(flow_context()))->eval( + ref('str')->stringNormalize(), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_normalize_nfc_default(): void { - static::assertSame('é', ref('str') - ->stringNormalize() - ->eval(array_to_row(['str' => "e\u{0301}"], schema(str_schema('str'))), flow_context())); + static::assertSame('é', (new FunctionContext(flow_context()))->eval( + ref('str')->stringNormalize(), + ['str' => "e\u{0301}"], + schema(str_schema('str')), + )); } public function test_normalize_nfc_explicit(): void { - static::assertSame('é', ref('str') - ->stringNormalize(Normalizer::NFC) - ->eval(array_to_row(['str' => "e\u{0301}"], schema(str_schema('str'))), flow_context())); + static::assertSame('é', (new FunctionContext(flow_context()))->eval( + ref('str')->stringNormalize(Normalizer::NFC), + ['str' => "e\u{0301}"], + schema(str_schema('str')), + )); } public function test_normalize_nfd(): void { - static::assertSame("e\u{0301}", ref('str') - ->stringNormalize(Normalizer::NFD) - ->eval(array_to_row(['str' => 'é'], schema(str_schema('str'))), flow_context())); + static::assertSame("e\u{0301}", (new FunctionContext(flow_context()))->eval( + ref('str')->stringNormalize(Normalizer::NFD), + ['str' => 'é'], + schema(str_schema('str')), + )); } public function test_normalize_throws_on_null_input(): void @@ -67,23 +79,19 @@ public function test_normalize_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringNormalize function requires non-null value'); - ref('str') - ->stringNormalize() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringNormalize(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_normalize_with_scalar_function_form(): void { - $normalized = ref('str') - ->stringNormalize(ref('form')) - ->eval( - array_to_row( - ['str' => "e\u{0301}", 'form' => Normalizer::NFC], - schema(str_schema('str'), int_schema('form')), - ), - flow_context(), - ); - - static::assertSame('é', $normalized); + static::assertSame('é', (new FunctionContext(flow_context()))->eval( + ref('str')->stringNormalize(ref('form')), + ['str' => "e\u{0301}", 'form' => Normalizer::NFC], + schema(str_schema('str'), int_schema('form')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringStyleTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringStyleTest.php index 5a8437b86f..0359a1f841 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringStyleTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringStyleTest.php @@ -6,10 +6,10 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\String\StringStyles; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\DataProvider; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -22,9 +22,11 @@ public function test_a_null_value_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringStyle function requires non-null value'); - ref('value') - ->stringStyle(StringStyles::LOWER) - ->eval(array_to_row(['value' => null], schema(str_schema('value', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('value')->stringStyle(StringStyles::LOWER), + ['value' => null], + schema(str_schema('value', nullable: true)), + ); } /** @@ -59,36 +61,38 @@ public static function provideStringStyles(): iterable public function test_string_style_camel(): void { - static::assertSame('fooBarBaz', ref('str') - ->stringStyle(ref('style')) - ->eval( - array_to_row( - ['str' => 'Foo: Bar-baz.', 'style' => 'camel'], - schema(str_schema('str'), str_schema('style')), - ), - flow_context(), - )); + static::assertSame('fooBarBaz', (new FunctionContext(flow_context()))->eval( + ref('str')->stringStyle(ref('style')), + ['str' => 'Foo: Bar-baz.', 'style' => 'camel'], + schema(str_schema('str'), str_schema('style')), + )); } public function test_string_style_kebab(): void { - static::assertSame('foo-bar-baz', ref('str') - ->stringStyle('kebab') - ->eval(array_to_row(['str' => 'Foo: Bar-baz.'], schema(str_schema('str'))), flow_context())); + static::assertSame('foo-bar-baz', (new FunctionContext(flow_context()))->eval( + ref('str')->stringStyle('kebab'), + ['str' => 'Foo: Bar-baz.'], + schema(str_schema('str')), + )); } public function test_string_style_lower(): void { - static::assertSame('foo bar bri̇an', ref('str') - ->stringStyle('lower') - ->eval(array_to_row(['str' => 'FOO Bar Brİan'], schema(str_schema('str'))), flow_context())); + static::assertSame('foo bar bri̇an', (new FunctionContext(flow_context()))->eval( + ref('str')->stringStyle('lower'), + ['str' => 'FOO Bar Brİan'], + schema(str_schema('str')), + )); } #[DataProvider('provideStringStyles')] public function test_string_styles(StringStyles $style, ?string $value, ?string $expected): void { - static::assertSame($expected, ref('str') - ->stringStyle($style) - ->eval(array_to_row(['str' => $value], schema(str_schema('str', nullable: true))), flow_context())); + static::assertSame($expected, (new FunctionContext(flow_context()))->eval( + ref('str')->stringStyle($style), + ['str' => $value], + schema(str_schema('str', nullable: true)), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringTitleTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringTitleTest.php index b168baa153..7d722a5fab 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringTitleTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringTitleTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,16 +17,20 @@ final class StringTitleTest extends FlowTestCase { public function test_string_title(): void { - static::assertSame('Foo ijssel', ref('str') - ->stringTitle() - ->eval(array_to_row(['str' => 'foo ijssel'], schema(str_schema('str'))), flow_context())); + static::assertSame('Foo ijssel', (new FunctionContext(flow_context()))->eval( + ref('str')->stringTitle(), + ['str' => 'foo ijssel'], + schema(str_schema('str')), + )); } public function test_string_title_allwords(): void { - static::assertSame('Foo Ijssel', ref('str') - ->stringTitle(allWords: true) - ->eval(array_to_row(['str' => 'foo ijssel'], schema(str_schema('str'))), flow_context())); + static::assertSame('Foo Ijssel', (new FunctionContext(flow_context()))->eval( + ref('str')->stringTitle(allWords: true), + ['str' => 'foo ijssel'], + schema(str_schema('str')), + )); } public function test_string_title_throws_on_null_input(): void @@ -34,8 +38,10 @@ public function test_string_title_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringTitle function requires non-null value'); - ref('str') - ->stringTitle() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringTitle(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringWidthTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringWidthTest.php index 6e505d4d65..3c1f8ebb3e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringWidthTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StringWidthTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,16 +17,20 @@ final class StringWidthTest extends FlowTestCase { public function test_width_ascii_string(): void { - static::assertSame(5, ref('str') - ->stringWidth() - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame(5, (new FunctionContext(flow_context()))->eval( + ref('str')->stringWidth(), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_width_empty_string(): void { - static::assertSame(0, ref('str') - ->stringWidth() - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + ref('str')->stringWidth(), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_width_throws_on_null_input(): void @@ -34,15 +38,19 @@ public function test_width_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('StringWidth function requires non-null value'); - ref('str') - ->stringWidth() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->stringWidth(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_width_single_character(): void { - static::assertSame(1, ref('str') - ->stringWidth() - ->eval(array_to_row(['str' => 'a'], schema(str_schema('str'))), flow_context())); + static::assertSame(1, (new FunctionContext(flow_context()))->eval( + ref('str')->stringWidth(), + ['str' => 'a'], + schema(str_schema('str')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureSelectTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureSelectTest.php index 763ef9c88d..ebddc163c0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureSelectTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureSelectTest.php @@ -8,9 +8,9 @@ use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Function\StructureSelect; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; @@ -28,10 +28,14 @@ public function test_selecting_multiple_values_from_structure(): void { static::assertEquals( ['id' => 1, 'name' => 'test'], - (new StructureSelect(ref('struct'), ref('id'), ref('name')))->eval(array_to_row(['struct' => [ - 'id' => 1, - 'name' => 'test', - ]], schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()])))), flow_context()), + (new FunctionContext(flow_context()))->eval( + new StructureSelect(ref('struct'), ref('id'), ref('name')), + ['struct' => [ + 'id' => 1, + 'name' => 'test', + ]], + schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()]))), + ), ); } @@ -39,10 +43,14 @@ public function test_selecting_single_value_from_structure(): void { static::assertEquals( ['id' => 1], - (new StructureSelect(ref('struct'), 'id'))->eval(array_to_row(['struct' => [ - 'id' => 1, - 'name' => 'test', - ]], schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()])))), flow_context()), + (new FunctionContext(flow_context()))->eval( + new StructureSelect(ref('struct'), 'id'), + ['struct' => [ + 'id' => 1, + 'name' => 'test', + ]], + schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()]))), + ), ); } @@ -50,10 +58,14 @@ public function test_selecting_single_value_from_structure_with_alias(): void { static::assertEquals( ['new_id' => 1], - (new StructureSelect(ref('struct'), ref('id')->as('new_id')))->eval(array_to_row(['struct' => [ - 'id' => 1, - 'name' => 'test', - ]], schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()])))), flow_context()), + (new FunctionContext(flow_context()))->eval( + new StructureSelect(ref('struct'), ref('id')->as('new_id')), + ['struct' => [ + 'id' => 1, + 'name' => 'test', + ]], + schema(structure_schema('struct', type_structure(['id' => type_integer(), 'name' => type_string()]))), + ), ); } @@ -61,15 +73,19 @@ public function test_selecting_values_from_empty_structure(): void { static::assertEquals( ['new_id' => null], - (new StructureSelect(ref('struct'), ref('id')->as('new_id')))->eval(array_to_row(['struct' => [ - 'id' => null, - 'email' => 'email@email.com', - 'name' => null, - ]], schema(structure_schema('struct', type_structure([ - 'id' => type_optional(type_integer()), - 'email' => type_string(), - 'name' => type_optional(type_string()), - ])))), flow_context()), + (new FunctionContext(flow_context()))->eval( + new StructureSelect(ref('struct'), ref('id')->as('new_id')), + ['struct' => [ + 'id' => null, + 'email' => 'email@email.com', + 'name' => null, + ]], + schema(structure_schema('struct', type_structure([ + 'id' => type_optional(type_integer()), + 'email' => type_string(), + 'name' => type_optional(type_string()), + ]))), + ), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureTest.php index 45e5be0682..4f7eb866d3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/StructureTest.php @@ -7,9 +7,9 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; @@ -25,16 +25,14 @@ public function test_eval_preserves_key_order(): void { static::assertSame( ['second' => 'x', 'first' => 1], - structure(['second' => ref('b'), 'first' => ref('a')])->eval( - array_to_row( - [ - 'a' => 1, - 'b' => 'x', - 'q' => null, - ], - schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), - ), - flow_context(), + (new FunctionContext(flow_context()))->eval( + structure(['second' => ref('b'), 'first' => ref('a')]), + [ + 'a' => 1, + 'b' => 'x', + 'q' => null, + ], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), ), ); } @@ -43,16 +41,14 @@ public function test_eval_keeps_null_under_its_key(): void { static::assertSame( ['id' => 'x', 'quantity' => null], - structure(['id' => ref('b'), 'quantity' => ref('q')])->eval( - array_to_row( - [ - 'a' => 1, - 'b' => 'x', - 'q' => null, - ], - schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), - ), - flow_context(), + (new FunctionContext(flow_context()))->eval( + structure(['id' => ref('b'), 'quantity' => ref('q')]), + [ + 'a' => 1, + 'b' => 'x', + 'q' => null, + ], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), ), ); } @@ -61,12 +57,10 @@ public function test_eval_with_numeric_keys(): void { static::assertSame( [5 => 1, 7 => 'x'], - structure([5 => ref('a'), 7 => ref('b')])->eval( - array_to_row( - ['a' => 1, 'b' => 'x', 'q' => null], - schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), - ), - flow_context(), + (new FunctionContext(flow_context()))->eval( + structure([5 => ref('a'), 7 => ref('b')]), + ['a' => 1, 'b' => 'x', 'q' => null], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), ), ); } @@ -85,16 +79,14 @@ public function test_eval_nested_structure(): void { static::assertSame( ['user' => ['id' => 1]], - structure(['user' => structure(['id' => ref('a')])])->eval( - array_to_row( - [ - 'a' => 1, - 'b' => 'x', - 'q' => null, - ], - schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), - ), - flow_context(), + (new FunctionContext(flow_context()))->eval( + structure(['user' => structure(['id' => ref('a')])]), + [ + 'a' => 1, + 'b' => 'x', + 'q' => null, + ], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), ), ); } @@ -149,15 +141,11 @@ public function test_with_children_keeps_keys(): void { static::assertSame( ['id' => 1, 'name' => 'x'], - structure(['id' => ref('a'), 'name' => ref('b')]) - ->withChildren([lit(1), lit('x')]) - ->eval( - array_to_row( - ['a' => 1, 'b' => 'x', 'q' => null], - schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), - ), - flow_context(), - ), + (new FunctionContext(flow_context()))->eval( + structure(['id' => ref('a'), 'name' => ref('b')])->withChildren([lit(1), lit('x')]), + ['a' => 1, 'b' => 'x', 'q' => null], + schema(int_schema('a'), str_schema('b'), str_schema('q', nullable: true)), + ), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SumTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SumTest.php index e59ecb5fc8..40c5b5d3fa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SumTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/SumTest.php @@ -8,30 +8,22 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\WindowContextMother; -use function Flow\ETL\DSL\array_to_row; -use function Flow\ETL\DSL\bool_schema; +use function array_map; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\average; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\lit; -use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; use function Flow\ETL\DSL\window; -use function Flow\Types\DSL\type_map; -use function Flow\Types\DSL\type_string; +use function range; final class SumTest extends FlowTestCase { - public function test_references_is_null_when_exact_is_a_scalar_function(): void - { - static::assertNull(sum(ref('value'), exact: ref('flag'))->references()); - } - public function test_references_returns_the_aggregated_reference(): void { static::assertEquals([ref('value')], sum(ref('value'))->references()); @@ -42,13 +34,17 @@ public function test_aggregation_sum_from_numeric_values(): void { $aggregator = sum(ref('int')); - $aggregator->aggregate(array_to_row(['int' => '10'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '20'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '55'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => '25'], schema(str_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'not_int' => null, - ], schema(str_schema('not_int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '10']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '20']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '55']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => '25']], schema(str_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'not_int' => null, + ]], schema(str_schema('not_int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(110.0, $aggregator->value()); } @@ -57,12 +53,16 @@ public function test_aggregation_sum_including_null_value(): void { $aggregator = sum(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 30], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row([ - 'int' => null, - ], schema(int_schema('int', nullable: true))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 30]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate( + array_to_rows([[ + 'int' => null, + ]], schema(int_schema('int', nullable: true))), + [0], + flow_context(), + ); static::assertSame(60.0, $aggregator->value()); } @@ -71,10 +71,10 @@ public function test_aggregation_sum_with_float_result(): void { $aggregator = sum(ref('int')); - $aggregator->aggregate(array_to_row(['int' => 10.25], schema(float_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 20], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 305], schema(int_schema('int'))), flow_context()); - $aggregator->aggregate(array_to_row(['int' => 25], schema(int_schema('int'))), flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 10.25]], schema(float_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 20]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 305]], schema(int_schema('int'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['int' => 25]], schema(int_schema('int'))), [0], flow_context()); static::assertSame(360.25, $aggregator->value()); } @@ -83,37 +83,47 @@ public function test_aggregation_sum_of_decimal_fractions(): void { $aggregator = sum(ref('value')); - $aggregator->aggregate(array_to_row(['value' => 0.1], schema(float_schema('value'))), flow_context()); - $aggregator->aggregate(array_to_row(['value' => 0.2], schema(float_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 0.1]], schema(float_schema('value'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 0.2]], schema(float_schema('value'))), [0], flow_context()); static::assertSame(0.30000000000000004, $aggregator->value()); } + public function test_ten_tenths_sum_to_one_on_the_ieee_path(): void + { + $aggregator = sum(ref('value')); + $aggregator->aggregate(array_to_rows(array_fill(0, 10, [ + 'value' => 0.1, + ]), schema(float_schema('value'))), range(0, 9), flow_context()); + + // plain IEEE addition drifts to 0.9999999999999999 + static::assertSame(1.0, $aggregator->value()); + } + public function test_window_function_sum_of_decimal_fractions_uses_float_arithmetic_by_default(): void { - $rows = rows( - schema(int_schema('id'), float_schema('value')), - $row1 = array_to_row(['id' => 1, 'value' => 0.1], schema(int_schema('id'), float_schema('value'))), - array_to_row( + $rows = array_to_rows( + [ + ['id' => 1, 'value' => 0.1], [ 'id' => 2, 'value' => 0.2, ], - schema(int_schema('id'), float_schema('value')), - ), + ], + schema(int_schema('id'), float_schema('value')), ); $sum = sum(ref('value'))->over(window()->orderBy(ref('id')->desc())); - static::assertSame(0.1 + 0.2, $sum->apply(WindowContextMother::forRow($row1, $rows))); + static::assertSame(0.1 + 0.2, $sum->apply(WindowContextMother::atIndex($rows, 0))); } public function test_aggregation_sum_of_floats_stays_float_when_sum_is_whole(): void { $aggregator = sum(ref('value')); - $aggregator->aggregate(array_to_row(['value' => 2.5], schema(float_schema('value'))), flow_context()); - $aggregator->aggregate(array_to_row(['value' => 2.5], schema(float_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 2.5]], schema(float_schema('value'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 2.5]], schema(float_schema('value'))), [0], flow_context()); static::assertSame(5.0, $aggregator->value()); static::assertSame('?float', $aggregator->returns()->toString()); @@ -123,116 +133,59 @@ public function test_sum_over_an_int_column_declares_float(): void { $aggregator = sum(ref('value')); - $aggregator->aggregate(array_to_row(['value' => 1], schema(int_schema('value'))), flow_context()); - $aggregator->aggregate(array_to_row(['value' => 2], schema(int_schema('value'))), flow_context()); - $aggregator->aggregate(array_to_row(['value' => 3], schema(int_schema('value'))), flow_context()); - $aggregator->aggregate(array_to_row(['value' => 4], schema(int_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 1]], schema(int_schema('value'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 2]], schema(int_schema('value'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 3]], schema(int_schema('value'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 4]], schema(int_schema('value'))), [0], flow_context()); static::assertSame(10.0, $aggregator->value()); static::assertSame('?float', $aggregator->returns()->toString()); } - public function test_a_malformed_exact_operand_throws_wrapped_as_a_sum_error(): void - { - $aggregator = sum(ref('value'), exact: ref('exact')); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Sum error:'); - - $aggregator->aggregate( - array_to_row( - ['value' => 0.1, 'exact' => ['not' => 'a boolean']], - schema(float_schema('value'), map_schema('exact', type_map(type_string(), type_string()))), - ), - flow_context(), - ); - } - public function test_exact_aggregation_sum_of_decimal_fractions(): void { $aggregator = sum(ref('value'), exact: true); - $aggregator->aggregate(array_to_row(['value' => 0.1], schema(float_schema('value'))), flow_context()); - $aggregator->aggregate(array_to_row(['value' => 0.2], schema(float_schema('value'))), flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 0.1]], schema(float_schema('value'))), [0], flow_context()); + $aggregator->aggregate(array_to_rows([['value' => 0.2]], schema(float_schema('value'))), [0], flow_context()); static::assertSame(0.3, $aggregator->value()); } public function test_window_function_sum_on_partitioned_rows(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['id' => 1, 'value' => 1], + ['id' => 2, 'value' => 1], + ['id' => 3, 'value' => 1], + ['id' => 4, 'value' => 1], + ['id' => 5, 'value' => 1], + ], schema(int_schema('id'), int_schema('value')), - $row1 = array_to_row(['id' => 1, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 2, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 3, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 4, 'value' => 1], schema(int_schema('id'), int_schema('value'))), - array_to_row(['id' => 5, 'value' => 1], schema(int_schema('id'), int_schema('value'))), ); $sum = sum(ref('id'))->over(window()->orderBy(ref('id')->desc())); - static::assertSame(15, $sum->apply(WindowContextMother::forRow($row1, $rows))); + static::assertSame(15, $sum->apply(WindowContextMother::atIndex($rows, 0))); } public function test_window_function_sum_of_decimal_fractions_in_exact_mode(): void { - $rows = rows( - schema(int_schema('id'), float_schema('value')), - $row1 = array_to_row(['id' => 1, 'value' => 0.1], schema(int_schema('id'), float_schema('value'))), - array_to_row( + $rows = array_to_rows( + [ + ['id' => 1, 'value' => 0.1], [ 'id' => 2, 'value' => 0.2, ], - schema(int_schema('id'), float_schema('value')), - ), - ); - - $sum = sum(ref('value'), exact: true)->over(window()->orderBy(ref('id')->desc())); - - static::assertSame(0.3, $sum->apply(WindowContextMother::forRow($row1, $rows))); - } - - public function test_window_function_sum_with_exact_mode_from_column(): void - { - $rows = rows( - schema(int_schema('id'), float_schema('value'), bool_schema('is_exact')), - $row1 = array_to_row( - ['id' => 1, 'value' => 0.1, 'is_exact' => true], - schema(int_schema('id'), float_schema('value'), bool_schema('is_exact')), - ), - array_to_row( - [ - 'id' => 2, - 'value' => 0.2, - 'is_exact' => true, - ], - schema(int_schema('id'), float_schema('value'), bool_schema('is_exact')), - ), - ); - - $sum = sum(ref('value'), exact: ref('is_exact'))->over(window()->orderBy(ref('id')->desc())); - - static::assertSame(0.3, $sum->apply(WindowContextMother::forRow($row1, $rows))); - } - - public function test_window_function_sum_with_exact_mode_from_literal(): void - { - $rows = rows( + ], schema(int_schema('id'), float_schema('value')), - $row1 = array_to_row(['id' => 1, 'value' => 0.1], schema(int_schema('id'), float_schema('value'))), - array_to_row( - [ - 'id' => 2, - 'value' => 0.2, - ], - schema(int_schema('id'), float_schema('value')), - ), ); - $sum = sum(ref('value'), exact: lit(true))->over(window()->orderBy(ref('id')->desc())); + $sum = sum(ref('value'), exact: true)->over(window()->orderBy(ref('id')->desc())); - static::assertSame(0.3, $sum->apply(WindowContextMother::forRow($row1, $rows))); + static::assertSame(0.3, $sum->apply(WindowContextMother::atIndex($rows, 0))); } public function test_window_function_sum_with_missing_reference_in_strict_mode(): void @@ -240,16 +193,12 @@ public function test_window_function_sum_with_missing_reference_in_strict_mode() $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Sum window function error:'); - $rows = rows( - schema(int_schema('id')), - $row1 = array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - ); + $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $sum = sum(ref('missing_column'))->over(window()->orderBy(ref('id'))); $context = flow_context(config()); - $sum->apply(WindowContextMother::forRow($row1, $rows, context: $context)); + $sum->apply(WindowContextMother::atIndex($rows, 0, context: $context)); } public function test_with_children_rebuilds_the_aggregate_with_the_given_reference(): void @@ -264,14 +213,6 @@ public function test_with_children_rebuilds_the_aggregate_with_the_given_referen static::assertEquals([ref('b')], $rebuilt->references()); } - public function test_with_children_carries_the_exact_operand_as_a_child(): void - { - $aggregate = sum(ref('a'), lit(true)); - - static::assertCount(2, $aggregate->children()); - static::assertNull($aggregate->withChildren([ref('b'), lit(false)])->references()); - } - public function test_output_name_is_not_affected_by_a_shared_reference(): void { $shared = ref('value'); @@ -287,4 +228,69 @@ public function test_sum_of_nothing_is_null(): void { static::assertNull(sum(ref('value'))->value()); } + + public function test_aggregate_reads_only_given_indices(): void + { + $aggregator = sum(ref('v')); + $aggregator->aggregate( + array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 0.5, + 1.25, + 2.0, + 3.0, + ]), schema(float_schema('v'))), + [1, 3], + flow_context(), + ); + + static::assertSame(4.25, $aggregator->value()); + } + + public function test_merge_of_two_halves_equals_one_pass(): void + { + $rows = array_to_rows(array_map(static fn(mixed $v): array => ['v' => $v], [ + 0.5, + 1.25, + 2.0, + 3.0, + ]), schema(float_schema('v'))); + $onePass = sum(ref('v')); + $onePass->aggregate($rows, [0, 1, 2, 3], flow_context()); + $left = sum(ref('v')); + $left->aggregate($rows, [0, 1], flow_context()); + $right = sum(ref('v')); + $right->aggregate($rows, [2, 3], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame($onePass->value(), $left->value()); + } + + public function test_merge_refuses_another_class(): void + { + $this->expectException(InvalidArgumentException::class); + + sum(ref('v'))->merge(average(ref('v')), flow_context()); + } + + public function test_merge_of_an_empty_half_keeps_null(): void + { + $left = sum(ref('v')); + $left->merge(sum(ref('v')), flow_context()); + + static::assertNull($left->value()); + } + + public function test_exact_merge_of_decimal_fractions(): void + { + $rows = array_to_rows([['v' => 0.1], ['v' => 0.2]], schema(float_schema('v'))); + $left = sum(ref('v'), exact: true); + $left->aggregate($rows, [0], flow_context()); + $right = sum(ref('v'), exact: true); + $right->aggregate($rows, [1], flow_context()); + + $left->merge($right, flow_context()); + + static::assertSame(0.3, $left->value()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTest.php index 360cedc703..e6d613fed1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToDateTest.php @@ -6,9 +6,9 @@ use DateTimeImmutable; use DateTimeZone; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -23,11 +23,11 @@ public function test_date_time_to_date(): void { static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), - to_date(ref('date_time')) - ->eval(array_to_row(['date_time' => new DateTimeImmutable( - '2020-01-01 12:43:23', - new DateTimeZone('UTC'), - )], schema(datetime_schema('date_time'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + to_date(ref('date_time')), + ['date_time' => new DateTimeImmutable('2020-01-01 12:43:23', new DateTimeZone('UTC'))], + schema(datetime_schema('date_time')), + ), ); } @@ -35,10 +35,13 @@ public function test_int_to_date_time(): void { static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), - to_date(ref('int')) - ->eval(array_to_row([ + (new FunctionContext(flow_context()))->eval( + to_date(ref('int')), + [ 'int' => (int) (new DateTimeImmutable('2020-01-01 10:11:11', new DateTimeZone('UTC')))->format('U'), - ], schema(int_schema('int'))), flow_context()), + ], + schema(int_schema('int')), + ), ); } @@ -46,9 +49,13 @@ public function test_string_to_date_time(): void { static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), - to_date(ref('string'), 'Y-m-d H:i:s')->eval(array_to_row([ - 'string' => '2020-01-01 10:08:00', - ], schema(str_schema('string'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + to_date(ref('string'), 'Y-m-d H:i:s'), + [ + 'string' => '2020-01-01 10:08:00', + ], + schema(str_schema('string')), + ), ); } } 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 040f492977..ce1f97b3db 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,11 +8,11 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use stdClass; use function array_slice; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -72,11 +72,11 @@ public function test_date_time_to_date_time(): void { static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), - to_date_time(ref('date_time')) - ->eval(array_to_row(['date_time' => new DateTimeImmutable( - '2020-01-01 00:00:00', - new DateTimeZone('UTC'), - )], schema(datetime_schema('date_time'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + to_date_time(ref('date_time')), + ['date_time' => new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC'))], + schema(datetime_schema('date_time')), + ), ); } @@ -84,10 +84,13 @@ public function test_int_to_date_time(): void { static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), - to_date_time(ref('int')) - ->eval(array_to_row([ + (new FunctionContext(flow_context()))->eval( + to_date_time(ref('int')), + [ 'int' => (int) (new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')))->format('U'), - ], schema(int_schema('int'))), flow_context()), + ], + schema(int_schema('int')), + ), ); } @@ -95,17 +98,25 @@ public function test_string_to_date_time(): void { static::assertEquals( new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')), - to_date_time(ref('string'), 'Y-m-d H:i:s')->eval(array_to_row([ - 'string' => '2020-01-01 00:00:00', - ], schema(str_schema('string'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + to_date_time(ref('string'), 'Y-m-d H:i:s'), + [ + 'string' => '2020-01-01 00:00:00', + ], + schema(str_schema('string')), + ), ); } public function test_unparseable_string_to_date_time_is_null(): void { - static::assertNull(to_date_time(ref('string'), 'Y-m-d H:i:s')->eval(array_to_row([ - 'string' => 'not a datetime', - ], schema(str_schema('string'))), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval( + to_date_time(ref('string'), 'Y-m-d H:i:s'), + [ + 'string' => 'not a datetime', + ], + schema(str_schema('string')), + )); } public function test_constant_zone_returns_a_zoned_type(): void @@ -121,13 +132,11 @@ public function test_object_keeps_its_time(): void static::assertSame( '10:30:00', type_datetime() - ->assert( - to_date_time(ref('at')) - ->eval(array_to_row(['at' => new DateTimeImmutable( - '2020-01-01 10:30:00', - new DateTimeZone('UTC'), - )], schema(datetime_schema('at'))), flow_context()), - ) + ->assert((new FunctionContext(flow_context()))->eval( + to_date_time(ref('at')), + ['at' => new DateTimeImmutable('2020-01-01 10:30:00', new DateTimeZone('UTC'))], + schema(datetime_schema('at')), + )) ->format('H:i:s'), ); } @@ -137,9 +146,13 @@ public function test_int_lands_in_the_constant_zone(): void static::assertSame( '2020-01-01 11:30:00 Europe/Warsaw', type_datetime() - ->assert(to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('Europe/Warsaw'))->eval(array_to_row([ - 'at' => 1577874600, - ], schema(int_schema('at'))), flow_context())) + ->assert((new FunctionContext(flow_context()))->eval( + to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('Europe/Warsaw')), + [ + 'at' => 1577874600, + ], + schema(int_schema('at')), + )) ->format('Y-m-d H:i:s e'), ); } @@ -150,9 +163,13 @@ public function test_mutable_datetime_is_converted_without_mutation(): void static::assertEquals( new DateTimeImmutable('2020-01-01 11:30:00', new DateTimeZone('Europe/Warsaw')), - to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('Europe/Warsaw'))->eval(array_to_row([ - 'at' => $value, - ], schema(datetime_schema('at'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('Europe/Warsaw')), + [ + 'at' => $value, + ], + schema(datetime_schema('at')), + ), ); static::assertSame('2020-01-01 10:30:00 UTC', $value->format('Y-m-d H:i:s e')); } @@ -162,7 +179,7 @@ public function test_non_datetime_object_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ToDateTime function requires DateTimeInterface object'); - to_date_time(lit(new stdClass()))->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval(to_date_time(lit(new stdClass())), [], schema()); } public function test_string_in_a_utc_alias_zone_lands_in_utc(): void @@ -170,9 +187,13 @@ public function test_string_in_a_utc_alias_zone_lands_in_utc(): void static::assertSame( '2020-01-01 10:30:00 UTC', type_datetime() - ->assert(to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('GMT'))->eval(array_to_row([ - 'at' => '2020-01-01 10:30:00', - ], schema(str_schema('at'))), flow_context())) + ->assert((new FunctionContext(flow_context()))->eval( + to_date_time(ref('at'), 'Y-m-d H:i:s', new DateTimeZone('GMT')), + [ + 'at' => '2020-01-01 10:30:00', + ], + schema(str_schema('at')), + )) ->format('Y-m-d H:i:s e'), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToLowerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToLowerTest.php index 6dd194f27f..fe0f29196c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToLowerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToLowerTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\lower; @@ -16,6 +16,6 @@ final class ToLowerTest extends FlowTestCase { public function test_string_to_lower(): void { - static::assertSame('lower', lower(lit('LOWER'))->eval(array_to_row([], schema()), flow_context())); + static::assertSame('lower', (new FunctionContext(flow_context()))->eval(lower(lit('LOWER')), [], schema())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToTimeZoneTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToTimeZoneTest.php index be1d4fd7c0..1b75c509fb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToTimeZoneTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToTimeZoneTest.php @@ -9,10 +9,10 @@ use DateTimeInterface; use DateTimeZone; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Exception\InvalidArgumentException as TypesInvalidArgumentException; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\ref; @@ -35,10 +35,14 @@ public function test_abbreviation_zone_is_refused(): void public function test_casting_date_time_pst_to_utc_time_zone(): void { // @mago-ignore analysis:mixed-assignment - $result = to_timezone( - lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('PST'))), - new DateTimeZone('UTC'), - )->eval(array_to_row([], schema()), flow_context()); + $result = (new FunctionContext(flow_context()))->eval( + to_timezone( + lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('PST'))), + new DateTimeZone('UTC'), + ), + [], + schema(), + ); static::assertInstanceOf(DateTimeInterface::class, $result); static::assertSame('2020-01-01 08:00:00.000000', $result->format('Y-m-d H:i:s.u')); } @@ -46,9 +50,10 @@ public function test_casting_date_time_pst_to_utc_time_zone(): void public function test_casting_date_time_pst_to_utc_time_zone_from_string_tz(): void { // @mago-ignore analysis:mixed-assignment - $result = to_timezone(lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('PST'))), 'UTC')->eval( - array_to_row([], schema()), - flow_context(), + $result = (new FunctionContext(flow_context()))->eval( + to_timezone(lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('PST'))), 'UTC'), + [], + schema(), ); static::assertInstanceOf(DateTimeInterface::class, $result); static::assertSame('2020-01-01 08:00:00.000000', $result->format('Y-m-d H:i:s.u')); @@ -58,7 +63,7 @@ public function test_does_not_mutate_a_datetime(): void { $value = new DateTime('2020-01-01 00:00:00 UTC'); - to_timezone(lit($value), 'Europe/Warsaw')->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval(to_timezone(lit($value), 'Europe/Warsaw'), [], schema()); static::assertSame('UTC', $value->getTimezone()->getName()); } @@ -78,8 +83,12 @@ public function test_null_value_is_refused(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('ToTimeZone function requires non-null values'); - to_timezone(ref('at'), 'UTC')->eval(array_to_row([ - 'at' => null, - ], schema(str_schema('at', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + to_timezone(ref('at'), 'UTC'), + [ + 'at' => null, + ], + schema(str_schema('at', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToUpperTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToUpperTest.php index af38dc4178..1bb0d48735 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToUpperTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ToUpperTest.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\schema; @@ -16,6 +16,6 @@ final class ToUpperTest extends FlowTestCase { public function test_string_to_upper(): void { - static::assertSame('UPPER', upper(lit('upper'))->eval(array_to_row([], schema()), flow_context())); + static::assertSame('UPPER', (new FunctionContext(flow_context()))->eval(upper(lit('upper')), [], schema())); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TrimTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TrimTest.php index 1a9175c287..2abcfd8a54 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TrimTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TrimTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Function\Trim\Type; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,22 +17,28 @@ final class TrimTest extends FlowTestCase { public function test_trim_both_valid_string(): void { - static::assertSame('value', ref('string') - ->trim() - ->eval(array_to_row(['string' => ' value'], schema(str_schema('string'))), flow_context())); + static::assertSame('value', (new FunctionContext(flow_context()))->eval( + ref('string')->trim(), + ['string' => ' value'], + schema(str_schema('string')), + )); } public function test_trim_left_valid_string(): void { - static::assertSame('value ', ref('string') - ->trim(Type::LEFT) - ->eval(array_to_row(['string' => ' value '], schema(str_schema('string'))), flow_context())); + static::assertSame('value ', (new FunctionContext(flow_context()))->eval( + ref('string')->trim(Type::LEFT), + ['string' => ' value '], + schema(str_schema('string')), + )); } public function test_trim_right_valid_string(): void { - static::assertSame(' value', ref('string') - ->trim(Type::RIGHT) - ->eval(array_to_row(['string' => ' value '], schema(str_schema('string'))), flow_context())); + static::assertSame(' value', (new FunctionContext(flow_context()))->eval( + ref('string')->trim(Type::RIGHT), + ['string' => ' value '], + schema(str_schema('string')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TruncateTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TruncateTest.php index 290dfcf1e4..9994dd29e2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TruncateTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/TruncateTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -18,23 +18,29 @@ final class TruncateTest extends FlowTestCase { public function test_truncate_ellipsis_longer_than_limit(): void { - static::assertSame('hello', ref('str') - ->truncate(5, 'verylongellipsis') - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context())); + static::assertSame('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(5, 'verylongellipsis'), + ['str' => 'hello world'], + schema(str_schema('str')), + )); } public function test_truncate_empty_string(): void { - static::assertSame('', ref('str') - ->truncate(10) - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); + static::assertSame('', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(10), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_truncate_exact_length(): void { - static::assertSame('hello', ref('str') - ->truncate(5) - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(5), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_truncate_throws_on_null_input(): void @@ -42,86 +48,91 @@ public function test_truncate_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Truncate function requires non-null value'); - ref('str') - ->truncate(10) - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(10), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } public function test_truncate_string_longer_than_limit(): void { - static::assertSame('he...', ref('str') - ->truncate(5) - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context())); + static::assertSame('he...', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(5), + ['str' => 'hello world'], + schema(str_schema('str')), + )); } public function test_truncate_string_shorter_than_limit(): void { - static::assertSame('hello', ref('str') - ->truncate(10) - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame('hello', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(10), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_truncate_with_custom_ellipsis(): void { - static::assertSame('he***', ref('str') - ->truncate(5, '***') - ->eval(array_to_row(['str' => 'hello world'], schema(str_schema('str'))), flow_context())); + static::assertSame('he***', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(5, '***'), + ['str' => 'hello world'], + schema(str_schema('str')), + )); } public function test_truncate_with_length_one(): void { - static::assertSame('h', ref('str') - ->truncate(1) - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame('h', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(1), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_truncate_with_length_zero(): void { - static::assertSame('', ref('str') - ->truncate(0) - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame('', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(0), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_truncate_with_negative_length(): void { - static::assertSame('hell', ref('str') - ->truncate(-1) - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame('hell', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(-1), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_truncate_with_null_length(): void { - static::assertSame('hello world', ref('str') - ->truncate(ref('length')) - ->eval( - array_to_row( - ['str' => 'hello world', 'length' => null], - schema(str_schema('str'), str_schema('length', nullable: true)), - ), - flow_context(), - )); + static::assertSame('hello world', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(ref('length')), + ['str' => 'hello world', 'length' => null], + schema(str_schema('str'), str_schema('length', nullable: true)), + )); } public function test_truncate_with_scalar_function_ellipsis(): void { - static::assertSame('hel>>', ref('str') - ->truncate(5, ref('ellipsis')) - ->eval( - array_to_row( - ['str' => 'hello world', 'ellipsis' => '>>'], - schema(str_schema('str'), str_schema('ellipsis')), - ), - flow_context(), - )); + static::assertSame('hel>>', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(5, ref('ellipsis')), + ['str' => 'hello world', 'ellipsis' => '>>'], + schema(str_schema('str'), str_schema('ellipsis')), + )); } public function test_truncate_with_scalar_function_length(): void { - static::assertSame('he...', ref('str') - ->truncate(ref('length')) - ->eval( - array_to_row(['str' => 'hello world', 'length' => 5], schema(str_schema('str'), int_schema('length'))), - flow_context(), - )); + static::assertSame('he...', (new FunctionContext(flow_context()))->eval( + ref('str')->truncate(ref('length')), + ['str' => 'hello world', 'length' => 5], + schema(str_schema('str'), int_schema('length')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UlidTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UlidTest.php index 8c2df9e97a..dd9dc19b06 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UlidTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UlidTest.php @@ -5,10 +5,10 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Symfony\Component\Uid\Ulid; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\schema; @@ -19,13 +19,14 @@ final class UlidTest extends FlowTestCase public function test_ulid_produces_a_string_column(): void { $expression = ulid(); - $result = $expression->eval(array_to_row([], schema()), flow_context()); + // @mago-ignore analysis:mixed-assignment + $result = (new FunctionContext(flow_context()))->eval($expression, [], schema()); static::assertIsString($result); static::assertTrue(Ulid::isValid($result)); static::assertNotSame( - $expression->eval(array_to_row([], schema()), flow_context()), - $expression->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval($expression, [], schema()), + (new FunctionContext(flow_context()))->eval($expression, [], schema()), ); } @@ -34,8 +35,8 @@ public function test_ulid_is_unique(): void $expression = ulid(); static::assertNotEquals( - $expression->eval(array_to_row([], schema()), flow_context()), - $expression->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval($expression, [], schema()), + (new FunctionContext(flow_context()))->eval($expression, [], schema()), ); } @@ -44,6 +45,6 @@ public function test_ulid_with_invalid_value_throws(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Ulid requires valid ULID string: Invalid ULID'); - ulid(lit(''))->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval(ulid(lit('')), [], schema()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UnicodeLengthTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UnicodeLengthTest.php index 87ea1c4b7b..e6ebcb229c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UnicodeLengthTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UnicodeLengthTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -17,16 +17,20 @@ final class UnicodeLengthTest extends FlowTestCase { public function test_unicode_length_ascii_string(): void { - static::assertSame(5, ref('str') - ->unicodeLength() - ->eval(array_to_row(['str' => 'hello'], schema(str_schema('str'))), flow_context())); + static::assertSame(5, (new FunctionContext(flow_context()))->eval( + ref('str')->unicodeLength(), + ['str' => 'hello'], + schema(str_schema('str')), + )); } public function test_unicode_length_empty_string(): void { - static::assertSame(0, ref('str') - ->unicodeLength() - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context())); + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + ref('str')->unicodeLength(), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_unicode_length_throws_on_null_input(): void @@ -34,8 +38,10 @@ public function test_unicode_length_throws_on_null_input(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('UnicodeLength function requires non-null value'); - ref('str') - ->unicodeLength() - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); + (new FunctionContext(flow_context()))->eval( + ref('str')->unicodeLength(), + ['str' => null], + schema(str_schema('str', nullable: true)), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UuidTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UuidTest.php index b47b91d186..71d46ec092 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UuidTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/UuidTest.php @@ -7,13 +7,13 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Value\Uuid as FlowUuid; use Ramsey\Uuid\Uuid; use Symfony\Component\Uid\Uuid as SymfonyUuid; use function class_exists; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\lit; use function Flow\ETL\DSL\schema; @@ -36,12 +36,13 @@ public function test_uuid4(): void } $expression = uuid_v4(); - $result = $expression->eval(array_to_row([], schema()), flow_context()); + // @mago-ignore analysis:mixed-assignment + $result = (new FunctionContext(flow_context()))->eval($expression, [], schema()); static::assertInstanceOf(FlowUuid::class, $result); static::assertTrue(Uuid::isValid($result->toString())); static::assertNotSame( - $expression->eval(array_to_row([], schema()), flow_context()), - $expression->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval($expression, [], schema()), + (new FunctionContext(flow_context()))->eval($expression, [], schema()), ); } @@ -50,8 +51,8 @@ public function test_uuid4_is_unique(): void $expression = uuid_v4(); static::assertNotEquals( - $expression->eval(array_to_row([], schema()), flow_context()), - $expression->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval($expression, [], schema()), + (new FunctionContext(flow_context()))->eval($expression, [], schema()), ); } @@ -61,8 +62,12 @@ public function test_uuid7(): void static::markTestSkipped("Package 'ramsey/uuid' is required for this test."); } - $result = uuid_v7(lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')))) - ->eval(array_to_row([], schema()), flow_context()); + // @mago-ignore analysis:mixed-assignment + $result = (new FunctionContext(flow_context()))->eval( + uuid_v7(lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC')))), + [], + schema(), + ); static::assertInstanceOf(FlowUuid::class, $result); static::assertTrue(Uuid::isValid($result->toString())); } @@ -71,8 +76,8 @@ public function test_uuid7_is_unique(): void { $dateTime = lit(new DateTimeImmutable('2020-01-01 00:00:00', new DateTimeZone('UTC'))); static::assertNotEquals( - uuid_v7($dateTime)->eval(array_to_row([], schema()), flow_context()), - uuid_v7($dateTime)->eval(array_to_row([], schema()), flow_context()), + (new FunctionContext(flow_context()))->eval(uuid_v7($dateTime), [], schema()), + (new FunctionContext(flow_context()))->eval(uuid_v7($dateTime), [], schema()), ); } @@ -81,6 +86,6 @@ public function test_uuid_v7_requires_a_date_time(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Uuid uuid7 function requires a DateTimeInterface value'); - uuid_v7(lit(''))->eval(array_to_row([], schema()), flow_context()); + (new FunctionContext(flow_context()))->eval(uuid_v7(lit('')), [], schema()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WhenTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WhenTest.php index 8c36ad989c..ea91a492dd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WhenTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WhenTest.php @@ -4,11 +4,15 @@ namespace Flow\ETL\Tests\Unit\Function; +use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Function\Literal; +use Flow\ETL\Function\ReferenceResolver; use Flow\ETL\Function\When; +use Flow\ETL\Tests\Context\FunctionContext; +use Flow\ETL\Tests\Double\FailingOnValuesFunction; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -21,47 +25,147 @@ final class WhenTest extends FlowTestCase { public function test_a_falsy_else_branch_is_returned(): void { - static::assertFalse(when(ref('active'), lit('yes'), false)->eval(array_to_row([ - 'active' => false, - ], schema(bool_schema('active'))), flow_context())); - static::assertSame(0, when(ref('active'), lit('yes'), 0)->eval(array_to_row([ - 'active' => false, - ], schema(bool_schema('active'))), flow_context())); - static::assertSame('', when(ref('active'), lit('yes'), '')->eval(array_to_row([ - 'active' => false, - ], schema(bool_schema('active'))), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval( + when(ref('active'), lit(true), false), + [ + 'active' => false, + ], + schema(bool_schema('active')), + )); + static::assertSame(0, (new FunctionContext(flow_context()))->eval( + when(ref('active'), lit(1), 0), + [ + 'active' => false, + ], + schema(bool_schema('active')), + )); + static::assertSame('', (new FunctionContext(flow_context()))->eval( + when(ref('active'), lit('yes'), ''), + [ + 'active' => false, + ], + schema(bool_schema('active')), + )); static::assertSame( [], - when(ref('active'), lit('yes'), [])->eval(array_to_row([ - 'active' => false, - ], schema(bool_schema('active'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + when(ref('active'), lit(['yes']), []), + [ + 'active' => false, + ], + schema(bool_schema('active')), + ), ); - static::assertNull(when(ref('active'), lit('yes'))->eval(array_to_row([ - 'active' => false, - ], schema(bool_schema('active'))), flow_context())); + static::assertNull((new FunctionContext(flow_context()))->eval( + when(ref('active'), lit('yes')), + [ + 'active' => false, + ], + schema(bool_schema('active')), + )); } public function test_condition_not_satisfied_without_else(): void { - static::assertSame(1, (new When(ref('id')->equals(lit(2)), new Literal('then'), ref('id')))->eval(array_to_row([ - 'id' => 1, - ], schema(int_schema('id'))), flow_context())); + // when() of string and integer branches declares string: the value is cast to it + static::assertSame('1', (new FunctionContext(flow_context()))->eval( + new When(ref('id')->equals(lit(2)), new Literal('then'), ref('id')), + [ + 'id' => 1, + ], + schema(int_schema('id')), + )); } public function test_else(): void { - static::assertSame('else', (new When(new Literal(false), new Literal('then'), new Literal('else')))->eval( - array_to_row([ + static::assertSame('else', (new FunctionContext(flow_context()))->eval( + new When(new Literal(false), new Literal('then'), new Literal('else')), + [ 'id' => 1, - ], schema(int_schema('id'))), - flow_context(), + ], + schema(int_schema('id')), )); } public function test_when(): void { - static::assertSame('then', (new When(new Literal(true), new Literal('then')))->eval(array_to_row([ - 'id' => 1, - ], schema(int_schema('id'))), flow_context())); + static::assertSame('then', (new FunctionContext(flow_context()))->eval( + new When(new Literal(true), new Literal('then')), + [ + 'id' => 1, + ], + schema(int_schema('id')), + )); + } + + public function test_then_branch_error_names_the_batch_row(): void + { + $rows = array_to_rows( + [ + ['c' => true, 'v' => 1], + ['c' => false, 'v' => 99], + ['c' => true, 'v' => 3], + ['c' => false, 'v' => 99], + ['c' => false, 'v' => 99], + ['c' => true, 'v' => 50], + ], + schema(bool_schema('c'), int_schema('v')), + ); + + try { + (new ReferenceResolver()) + ->resolve(when(ref('c'), new FailingOnValuesFunction(ref('v'), [50]), lit(0)), $rows->schema()) + ->eval($rows, flow_context()); + static::fail('expected an EvaluationException'); + } catch (EvaluationException $e) { + static::assertSame(5, $e->rowIndex); + } + } + + public function test_else_branch_error_names_the_batch_row(): void + { + $rows = array_to_rows( + [ + ['c' => false, 'v' => 1], + ['c' => true, 'v' => 99], + ['c' => true, 'v' => 99], + ['c' => false, 'v' => 50], + ['c' => true, 'v' => 99], + ], + schema(bool_schema('c'), int_schema('v')), + ); + + try { + (new ReferenceResolver()) + ->resolve(when(ref('c'), lit(0), new FailingOnValuesFunction(ref('v'), [50])), $rows->schema()) + ->eval($rows, flow_context()); + static::fail('expected an EvaluationException'); + } catch (EvaluationException $e) { + static::assertSame(3, $e->rowIndex); + } + } + + public function test_a_branch_runs_only_on_the_rows_that_reach_it(): void + { + $rows = array_to_rows( + [ + ['c' => true, 'v' => 1], + ['c' => false, 'v' => 99], + ['c' => true, 'v' => 3], + ['c' => false, 'v' => 99], + ['c' => false, 'v' => 99], + ['c' => true, 'v' => 50], + ], + schema(bool_schema('c'), int_schema('v')), + ); + + static::assertSame( + [1, 0, 3, 0, 0, 50], + (new ReferenceResolver()) + ->resolve(when(ref('c'), new FailingOnValuesFunction(ref('v'), [99]), lit(0)), $rows->schema()) + ->eval($rows, flow_context()) + ->values(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WordwrapTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WordwrapTest.php index 8b69a21797..4828179f3f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WordwrapTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/WordwrapTest.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Tests\Unit\Function; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; @@ -19,35 +19,29 @@ final class WordwrapTest extends FlowTestCase { public function test_empty_string(): void { - $result = ref('str') - ->wordwrap(10) - ->eval(array_to_row(['str' => ''], schema(str_schema('str'))), flow_context()); - - static::assertEquals('', $result); + static::assertEquals('', (new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(10), + ['str' => ''], + schema(str_schema('str')), + )); } public function test_normal_word_wrapping(): void { - $result = ref('str') - ->wordwrap(10) - ->eval(array_to_row(['str' => 'The quick brown fox jumps'], schema(str_schema('str'))), flow_context()); - - static::assertEquals("The quick\nbrown fox\njumps", $result); + static::assertEquals("The quick\nbrown fox\njumps", (new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(10), + ['str' => 'The quick brown fox jumps'], + schema(str_schema('str')), + )); } public function test_null_break_character(): void { - $result = ref('str') - ->wordwrap(10, ref('break')) - ->eval( - array_to_row( - ['str' => 'Hello World Test', 'break' => null], - schema(str_schema('str'), str_schema('break', nullable: true)), - ), - flow_context(), - ); - - static::assertEquals("Hello\nWorld Test", $result); + static::assertEquals("Hello\nWorld Test", (new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(10, ref('break')), + ['str' => 'Hello World Test', 'break' => null], + schema(str_schema('str'), str_schema('break', nullable: true)), + )); } public function test_null_value(): void @@ -55,70 +49,55 @@ public function test_null_value(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Wordwrap function requires non-null value'); - $result = ref('str') - ->wordwrap(10) - ->eval(array_to_row(['str' => null], schema(str_schema('str', nullable: true))), flow_context()); - - static::assertNull($result); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(10), + ['str' => null], + schema(str_schema('str', nullable: true)), + )); } public function test_text_shorter_than_width(): void { - $result = ref('str') - ->wordwrap(20) - ->eval(array_to_row(['str' => 'Hello'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello', $result); + static::assertEquals('Hello', (new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(20), + ['str' => 'Hello'], + schema(str_schema('str')), + )); } public function test_width_zero(): void { - $result = ref('str') - ->wordwrap(0) - ->eval(array_to_row(['str' => 'Hello World'], schema(str_schema('str'))), flow_context()); - - static::assertEquals('Hello World', $result); + static::assertEquals('Hello World', (new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(0), + ['str' => 'Hello World'], + schema(str_schema('str')), + )); } public function test_with_scalar_function_break(): void { - $result = ref('str') - ->wordwrap(10, ref('break')) - ->eval( - array_to_row( - ['str' => 'Hello World Test', 'break' => ' | '], - schema(str_schema('str'), str_schema('break')), - ), - flow_context(), - ); - - static::assertEquals('Hello | World Test', $result); + static::assertEquals('Hello | World Test', (new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(10, ref('break')), + ['str' => 'Hello World Test', 'break' => ' | '], + schema(str_schema('str'), str_schema('break')), + )); } public function test_with_scalar_function_cut(): void { - $result = ref('str') - ->wordwrap(3, "\n", ref('cut')) - ->eval( - array_to_row(['str' => 'Hello', 'cut' => true], schema(str_schema('str'), bool_schema('cut'))), - flow_context(), - ); - - static::assertEquals("Hel\nlo", $result); + static::assertEquals("Hel\nlo", (new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(3, "\n", ref('cut')), + ['str' => 'Hello', 'cut' => true], + schema(str_schema('str'), bool_schema('cut')), + )); } public function test_with_scalar_function_width(): void { - $result = ref('str') - ->wordwrap(ref('width')) - ->eval( - array_to_row( - ['str' => 'Hello World Test', 'width' => 8], - schema(str_schema('str'), int_schema('width')), - ), - flow_context(), - ); - - static::assertEquals("Hello\nWorld\nTest", $result); + static::assertEquals("Hello\nWorld\nTest", (new FunctionContext(flow_context()))->eval( + ref('str')->wordwrap(ref('width')), + ['str' => 'Hello World Test', 'width' => 8], + schema(str_schema('str'), int_schema('width')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/XPathTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/XPathTest.php index f40c11543c..3f9229413f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/XPathTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/XPathTest.php @@ -6,9 +6,9 @@ use DOMDocument; use DOMElement; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -24,9 +24,11 @@ public function test_xpath_on_simple_xml_with_only_one_node_returned(): void static::assertInstanceOf(DOMElement::class, $xml->documentElement); static::assertEquals( [$xml->documentElement->firstChild], - ref('value') - ->xpath('/root/foo') - ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('value')->xpath('/root/foo'), + ['value' => $xml], + schema(xml_schema('value')), + ), ); } @@ -41,9 +43,11 @@ public function test_xpath_when_there_are_more_than_one_elements_under_given_pat $xml->documentElement->firstChild, $xml->documentElement->lastChild, ], - ref('value') - ->xpath('/root/foo') - ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), + (new FunctionContext(flow_context()))->eval( + ref('value')->xpath('/root/foo'), + ['value' => $xml], + schema(xml_schema('value')), + ), ); } @@ -52,11 +56,11 @@ public function test_xpath_with_invalid_path_syntax(): void $xml = new DOMDocument(); $xml->loadXML('bar'); - static::assertNull( - ref('value') - ->xpath('/root/foo/asa') - ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->xpath('/root/foo/asa'), + ['value' => $xml], + schema(xml_schema('value')), + )); } public function test_xpath_with_non_existing_path(): void @@ -64,11 +68,11 @@ public function test_xpath_with_non_existing_path(): void $xml = new DOMDocument(); $xml->loadXML('bar'); - static::assertNull( - ref('value') - ->xpath('/root/bar') - ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->xpath('/root/bar'), + ['value' => $xml], + schema(xml_schema('value')), + )); } public function test_xpath_selecting_non_element_nodes_returns_null(): void @@ -76,15 +80,15 @@ public function test_xpath_selecting_non_element_nodes_returns_null(): void $xml = new DOMDocument(); $xml->loadXML('bar'); - static::assertNull( - ref('value') - ->xpath('/root/foo/text()') - ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), - ); - static::assertNull( - ref('value') - ->xpath('/root/foo/@baz') - ->eval(array_to_row(['value' => $xml], schema(xml_schema('value'))), flow_context()), - ); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->xpath('/root/foo/text()'), + ['value' => $xml], + schema(xml_schema('value')), + )); + static::assertNull((new FunctionContext(flow_context()))->eval( + ref('value')->xpath('/root/foo/@baz'), + ['value' => $xml], + schema(xml_schema('value')), + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatorsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatorsTest.php index 50e95f33c5..9e9aeb6c9f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatorsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/AggregatorsTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\GroupBy\Aggregators; +use Flow\ETL\Tests\Double\UnenumerableSum; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\ListColumnsMother; @@ -49,7 +50,7 @@ public function test_references_union_all_aggregators(): void public function test_references_are_null_when_any_aggregator_cannot_enumerate_them(): void { static::assertNull( - (new Aggregators(count(ref('order_id')), sum(ref('discount'), exact: ref('flag'))))->references(), + (new Aggregators(count(ref('order_id')), new UnenumerableSum(ref('discount'))))->references(), ); } @@ -60,7 +61,7 @@ public function test_resolved_refuses_an_expand_in_an_aggregate(): void 'aggregate() cannot contain array_expand(), it turns one row into many rows. Expand with withEntry() first, then use the new column.', ); - (new Aggregators(sum(ref('n'), ref('flags')->expand()->equals(lit(true)))))->resolved( + (new Aggregators(new UnenumerableSum(ref('n'), ref('flags')->expand()->equals(lit(true)))))->resolved( ListColumnsMother::numberAndFlagsSchema(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/BucketAggregationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/BucketAggregationTest.php deleted file mode 100644 index da725d6cab..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/BucketAggregationTest.php +++ /dev/null @@ -1,218 +0,0 @@ -aggregate(sum(ref('v'))); - - $batches = (static function () { - yield array_to_rows( - [['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 10]], - schema(str_schema('k'), int_schema('v')), - ); - })(); - - $result = iterator_to_array( - (new BucketAggregation(batchSize: 1))->aggregate($batches, flow_context(), $groupBy), - preserve_keys: false, - ); - - static::assertCount(2, $result); - - foreach ($result as $batch) { - static::assertCount(1, $batch); - } - } - - public function test_throws_when_batch_size_below_one(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); - - // @mago-ignore analysis:invalid-argument - new BucketAggregation(0); - } - - public function test_folds_groups_across_multiple_batches(): void - { - $context = flow_context(); - - $groupBy = new GroupBy(ref('k')); - $groupBy->aggregate(sum(ref('v'))); - - $batches = (static function () { - yield array_to_rows( - [['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 10]], - schema(str_schema('k'), int_schema('v')), - ); - yield array_to_rows( - [['k' => 'a', 'v' => 2], ['k' => 'b', 'v' => 20]], - schema(str_schema('k'), int_schema('v')), - ); - })(); - - $sums = []; - - foreach ((new BucketAggregation())->aggregate($batches, $context, $groupBy) as $resultRows) { - foreach ($resultRows as $resultRow) { - $key = $resultRow->get(ref('k')); - assert(is_string($key)); - - $sums[$key] = $resultRow->get(ref('v_sum')); - } - } - - static::assertSame(['a' => 3.0, 'b' => 30.0], $sums); - } - - public function test_first_preserves_input_order_across_batches(): void - { - $context = flow_context(); - - $groupBy = new GroupBy(ref('k')); - $groupBy->aggregate(first(ref('v'))); - - $batches = (static function () { - yield array_to_rows([['k' => 'a', 'v' => 100]], schema(str_schema('k'), int_schema('v'))); - yield array_to_rows([['k' => 'a', 'v' => 200]], schema(str_schema('k'), int_schema('v'))); - })(); - - $firsts = []; - - foreach ((new BucketAggregation())->aggregate($batches, $context, $groupBy) as $resultRows) { - foreach ($resultRows as $resultRow) { - $key = $resultRow->get(ref('k')); - assert(is_string($key)); - - $firsts[$key] = $resultRow->get(ref('v_first')); - } - } - - static::assertSame(['a' => 100], $firsts); - } - - public function test_last_keeps_the_latest_across_batches(): void - { - $context = flow_context(); - - $groupBy = new GroupBy(ref('k')); - $groupBy->aggregate(last(ref('v'))); - - $batches = (static function () { - yield array_to_rows([['k' => 'a', 'v' => 100]], schema(str_schema('k'), int_schema('v'))); - yield array_to_rows([['k' => 'a', 'v' => 200]], schema(str_schema('k'), int_schema('v'))); - })(); - - $lasts = []; - - foreach ((new BucketAggregation())->aggregate($batches, $context, $groupBy) as $resultRows) { - foreach ($resultRows as $resultRow) { - $key = $resultRow->get(ref('k')); - assert(is_string($key)); - - $lasts[$key] = $resultRow->get(ref('v_last')); - } - } - - static::assertSame(['a' => 200], $lasts); - } - - public function test_a_leading_empty_batch_defers_the_bind_to_the_first_data_batch(): void - { - $groupBy = new GroupBy(ref('k')); - $groupBy->aggregate(sum(ref('v'))); - - $batches = (static function () { - yield rows(schema()); - yield array_to_rows( - [['k' => 'a', 'v' => 1], ['k' => 'a', 'v' => 2]], - schema(str_schema('k'), int_schema('v')), - ); - })(); - - $result = iterator_to_array( - (new BucketAggregation())->aggregate($batches, flow_context(), $groupBy), - preserve_keys: false, - ); - - static::assertCount(1, $result); - static::assertSame([['k' => 'a', 'v_sum' => 3.0]], $result[0]->toArray()); - } - - public function test_groups_in_one_run_share_one_output_definition(): void - { - $groupBy = new GroupBy(ref('k')); - $groupBy->aggregate(min(ref('v'))); - - $batches = (static function () { - yield array_to_rows( - [['k' => 'a', 'v' => 10.0], ['k' => 'b', 'v' => 0.5]], - schema(str_schema('k'), float_schema('v')), - ); - })(); - - $definitions = []; - $mins = []; - - foreach ((new BucketAggregation())->aggregate($batches, flow_context(), $groupBy) as $batch) { - $definitions[] = $batch->schema()->get('v_min'); - - foreach ($batch as $row) { - $mins[] = $row->get('v_min'); - } - } - - static::assertCount(2, $mins); - static::assertEquals([float_schema('v_min', true)], array_unique($definitions, SORT_REGULAR)); - } - - /** - * A group that accumulates nothing is the reachable twin of the never-aggregated instance: the - * rows carry the key but omit the aggregated column, so min() emits null under its nullable - * definition instead of the definition being widened after the fact. - */ - public function test_a_group_whose_aggregated_column_is_absent_emits_null_under_a_nullable_definition(): void - { - $groupBy = new GroupBy(ref('k')); - $groupBy->aggregate(min(ref('v'))); - - $batches = (static function () { - yield array_to_rows( - [['k' => 'a'], ['k' => 'a']], - schema(str_schema('k'), float_schema('v', nullable: true)), - ); - })(); - - $result = iterator_to_array( - (new BucketAggregation())->aggregate($batches, flow_context(), $groupBy), - preserve_keys: false, - ); - - static::assertSame([['k' => 'a', 'v_min' => null]], $result[0]->toArray()); - static::assertEquals(float_schema('v_min', true), $result[0]->schema()->get('v_min')); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/DiscoveredPivotValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/DiscoveredPivotValuesTest.php index b547b2a19c..995f837462 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/DiscoveredPivotValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/DiscoveredPivotValuesTest.php @@ -9,6 +9,7 @@ use Flow\ETL\GroupBy\DiscoveredPivotValues; use Flow\ETL\Tests\Double\EmptyExtractor; use Flow\ETL\Tests\FlowTestCase; +use Flow\Types\Exception\InvalidTypeException; use function Flow\ETL\DSL\concat; use function Flow\ETL\DSL\df; @@ -75,6 +76,36 @@ public function test_it_refuses_more_distinct_values_than_the_bound_allows(): vo ); } + public function test_numeric_looking_strings_are_ordered_by_bytes_as_sort_by_does(): void + { + static::assertSame( + ['10', '100', '9', 'B'], + (new DiscoveredPivotValues())->resolve( + df()->read(from_array([['code' => '9'], ['code' => '10'], ['code' => 'B'], ['code' => '100']])), + ref('code'), + )->all(), + ); + } + + public function test_only_string_and_integer_values_can_become_pivot_columns(): void + { + $this->expectException(InvalidTypeException::class); + $this->expectExceptionMessage('Expected type "integer|string", got "float".'); + + (new DiscoveredPivotValues())->resolve(df()->read(from_array([['code' => 1.5]])), ref('code')); + } + + public function test_integers_are_ordered_numerically(): void + { + static::assertSame( + [9, 10, 100], + (new DiscoveredPivotValues())->resolve( + df()->read(from_array([['code' => 100], ['code' => 9], ['code' => 10]])), + ref('code'), + )->all(), + ); + } + public function test_the_discovered_values_are_distinct_null_free_and_sorted(): void { static::assertSame( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/GroupByStepsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/GroupByStepsTest.php index 0ec2ff9e39..9f26823e39 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/GroupByStepsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupBy/GroupByStepsTest.php @@ -5,13 +5,14 @@ namespace Flow\ETL\Tests\Unit\GroupBy; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\GroupBy; use Flow\ETL\GroupBy\GroupBySteps; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\GroupByAggregationProcessor; use Flow\ETL\Processor\PivotProcessor; use Flow\ETL\Tests\Context\GroupByContext; use Flow\ETL\Tests\Double\SpyBucketsStorage; +use Flow\ETL\Tests\Double\UnenumerableSum; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\PruneEntriesTransformer; @@ -51,22 +52,20 @@ public function test_enumerable_references_add_a_pruning_transformer(): void $steps = GroupBySteps::of($groupBy, config()); - static::assertCount(3, $steps); + static::assertCount(2, $steps); static::assertInstanceOf(PruneEntriesTransformer::class, $steps[0]); - static::assertInstanceOf(BucketingProcessor::class, $steps[1]); - static::assertInstanceOf(GroupByAggregationProcessor::class, $steps[2]); + static::assertInstanceOf(GroupByAggregationProcessor::class, $steps[1]); } public function test_non_enumerable_references_skip_the_pruning_transformer(): void { $groupBy = new GroupBy(ref('category')); - $groupBy->aggregate(sum(ref('amount'), exact: ref('flag'))); + $groupBy->aggregate(new UnenumerableSum(ref('amount'))); $steps = GroupBySteps::of($groupBy, config()); - static::assertCount(2, $steps); - static::assertInstanceOf(BucketingProcessor::class, $steps[0]); - static::assertInstanceOf(GroupByAggregationProcessor::class, $steps[1]); + static::assertCount(1, $steps); + static::assertInstanceOf(GroupByAggregationProcessor::class, $steps[0]); } public function test_groups_across_multiple_batches(): void @@ -146,7 +145,11 @@ public function test_aggregates_many_buckets_and_flushes_per_bucket(): void $result = GroupByContext::aggregate( $groupBy, flow_context( - config_builder()->groupBy(hash_group_by()->storage(new MemoryBuckets())->bucketsCount(4))->build(), + config_builder() + ->groupBy( + hash_group_by()->storage(new MemoryBuckets())->memoryLimit(Unit::fromBytes(1))->bucketsCount(4), + ) + ->build(), ), ...$batches, ); @@ -175,11 +178,13 @@ public function test_removes_storage_buckets_after_last_bucket(): void GroupByContext::aggregate( $groupBy, - flow_context(config_builder()->groupBy(hash_group_by()->storage($storage))->build()), - array_to_rows( - [['category' => 'a', 'amount' => 10], ['category' => 'b', 'amount' => 15]], - schema(str_schema('category'), int_schema('amount')), + flow_context( + config_builder() + ->groupBy(hash_group_by()->storage($storage)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) + ->build(), ), + array_to_rows([['category' => 'a', 'amount' => 10]], schema(str_schema('category'), int_schema('amount'))), + array_to_rows([['category' => 'b', 'amount' => 15]], schema(str_schema('category'), int_schema('amount'))), ); static::assertNotSame([], $storage->readBucketIds()); @@ -222,20 +227,27 @@ public function test_spills_only_grouping_and_aggregation_columns(): void GroupByContext::aggregate( $groupBy, - flow_context(config_builder()->groupBy(hash_group_by()->storage($storage))->build()), + flow_context( + config_builder() + ->groupBy(hash_group_by()->storage($storage)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) + ->build(), + ), array_to_rows( - [ - ['category' => 'a', 'amount' => 10, 'noise' => 'x', 'id' => 1], - ['category' => 'b', 'amount' => 15, 'noise' => 'y', 'id' => 2], - ], + [['category' => 'a', 'amount' => 10, 'noise' => 'x', 'id' => 1]], + schema(str_schema('category'), int_schema('amount'), str_schema('noise'), int_schema('id')), + ), + array_to_rows( + [['category' => 'b', 'amount' => 15, 'noise' => 'y', 'id' => 2]], schema(str_schema('category'), int_schema('amount'), str_schema('noise'), int_schema('id')), ), ); + static::assertNotSame([], $storage->appendedRows()); + foreach ($storage->appendedRows() as $batches) { foreach ($batches as $batch) { - foreach ($batch as $spilledRow) { - static::assertSame(['category', 'amount'], $spilledRow->names()); + foreach ($batch->toArray() as $spilledRow) { + static::assertSame(['category', 'amount'], array_keys($spilledRow)); } } } @@ -244,31 +256,38 @@ public function test_spills_only_grouping_and_aggregation_columns(): void public function test_spills_all_columns_when_aggregator_references_cannot_be_enumerated(): void { $groupBy = new GroupBy(ref('category')); - $groupBy->aggregate(sum(ref('amount'), exact: ref('flag'))); + $groupBy->aggregate(new UnenumerableSum(ref('amount'))); $storage = new SpyBucketsStorage(new MemoryBuckets()); $result = GroupByContext::aggregate( $groupBy, - flow_context(config_builder()->groupBy(hash_group_by()->storage($storage))->build()), + flow_context( + config_builder() + ->groupBy(hash_group_by()->storage($storage)->memoryLimit(Unit::fromBytes(1))->batchSize(1)) + ->build(), + ), array_to_rows( - [ - ['category' => 'a', 'amount' => 0.1, 'flag' => true], - ['category' => 'a', 'amount' => 0.2, 'flag' => true], - ], + [['category' => 'a', 'amount' => 0.5, 'flag' => true]], + schema(str_schema('category'), float_schema('amount'), bool_schema('flag')), + ), + array_to_rows( + [['category' => 'a', 'amount' => 0.25, 'flag' => true]], schema(str_schema('category'), float_schema('amount'), bool_schema('flag')), ), ); + static::assertNotSame([], $storage->appendedRows()); + foreach ($storage->appendedRows() as $batches) { foreach ($batches as $batch) { - foreach ($batch as $spilledRow) { - static::assertSame(['category', 'amount', 'flag'], $spilledRow->names()); + foreach ($batch->toArray() as $spilledRow) { + static::assertSame(['category', 'amount', 'flag'], array_keys($spilledRow)); } } } - static::assertSame(0.3, $result[0]->first()->get('amount_sum')); + static::assertSame(0.75, $result[0]->column('amount_sum')->value(0)); } public function test_missing_aggregated_column_is_treated_as_null_in_strict_mode(): void @@ -286,7 +305,7 @@ public function test_missing_aggregated_column_is_treated_as_null_in_strict_mode ), ); - static::assertSame(10.0, $result[0]->first()->get('amount_sum')); + static::assertSame(10.0, $result[0]->column('amount_sum')->value(0)); } public function test_handles_empty_input(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php index 081963cd5b..0feb5d1de5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php @@ -8,13 +8,14 @@ use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\GroupBy; +use Flow\ETL\GroupBy\GroupKey; use Flow\ETL\GroupBy\PivotAggregation; use Flow\ETL\GroupBy\PivotShape; use Flow\ETL\Tests\Context\GroupByContext; use Flow\ETL\Tests\FlowTestCase; use Generator; -use function Flow\ETL\DSL\array_to_row; +use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\count; @@ -24,9 +25,11 @@ use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\pivot_values; use function Flow\ETL\DSL\ref; +use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; +use function iterator_to_array; final class GroupByTest extends FlowTestCase { @@ -366,25 +369,51 @@ public function test_a_nullable_group_key_stays_nullable_in_the_output_schema(): ); } - public function test_key_values_throws_when_a_row_lacks_a_not_null_key(): void + public function test_keys_throws_when_a_row_lacks_a_not_null_key(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Column "country" does not exist.'); - (new GroupBy('country'))->keyValues( - array_to_row(['age' => 20], schema(int_schema('age'))), + (new GroupBy('country'))->keys( + array_to_rows([['age' => 20]], schema(int_schema('age'))), schema(str_schema('country'), int_schema('age')), ); } - public function test_key_values_substitutes_null_when_a_row_lacks_a_nullable_key(): void + public function test_keys_substitutes_null_when_a_row_lacks_a_nullable_key(): void { + $keys = (new GroupBy('country'))->keys( + array_to_rows([['age' => 20], ['age' => 30]], schema(int_schema('age'))), + schema(str_schema('country', nullable: true), int_schema('age')), + ); + static::assertSame( - ['country' => null], - iterator_to_array((new GroupBy('country'))->keyValues( - array_to_row(['age' => 20], schema(int_schema('age'))), - schema(str_schema('country', nullable: true), int_schema('age')), - )), + [['country' => null], ['country' => null]], + array_map(static fn(GroupKey $key): array => iterator_to_array($key), $keys), + ); + } + + public function test_keys_reads_one_key_per_row(): void + { + $keys = (new GroupBy('country', 'age'))->keys( + array_to_rows( + [['country' => 'PL', 'age' => 20], ['country' => 'DE', 'age' => 30]], + schema(str_schema('country'), int_schema('age')), + ), + schema(str_schema('country'), int_schema('age')), + ); + + static::assertSame( + [['country' => 'PL', 'age' => 20], ['country' => 'DE', 'age' => 30]], + array_map(static fn(GroupKey $key): array => iterator_to_array($key), $keys), + ); + } + + public function test_keys_of_an_empty_batch_are_empty(): void + { + static::assertSame( + [], + (new GroupBy('country'))->keys(rows(schema(int_schema('age'))), schema(str_schema('country'))), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AllTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AllTest.php index 8200d42885..f53230595a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AllTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AllTest.php @@ -4,11 +4,12 @@ namespace Flow\ETL\Tests\Unit\Join\Comparison; -use Flow\ETL\Join\Comparison; use Flow\ETL\Join\Comparison\All; +use Flow\ETL\Join\Comparison\Equal; +use Flow\ETL\Tests\Double\ConstantComparison; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -16,29 +17,48 @@ final class AllTest extends FlowTestCase { public function test_failure(): void { - $comparison1 = self::createStub(Comparison::class); - $comparison1->method('compare')->willReturn(true); + $comparison1 = new ConstantComparison(true); - $comparison2 = self::createStub(Comparison::class); - $comparison2->method('compare')->willReturn(false); + $comparison2 = new ConstantComparison(false); - static::assertFalse((new All($comparison1, $comparison2))->compare( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - )); + static::assertSame( + [false], + (new All($comparison1, $comparison2))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + ), + ); } public function test_success(): void { - $comparison1 = self::createStub(Comparison::class); - $comparison1->method('compare')->willReturn(true); + $comparison1 = new ConstantComparison(true); - $comparison2 = self::createStub(Comparison::class); - $comparison2->method('compare')->willReturn(true); + $comparison2 = new ConstantComparison(true); - static::assertTrue((new All($comparison1, $comparison2))->compare( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - )); + static::assertSame( + [true], + (new All($comparison1, $comparison2))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + ), + ); + } + + public function test_combines_children_element_wise(): void + { + static::assertSame( + [true, false, false], + (new All(new Equal('a', 'a'), new Equal('b', 'b')))->compare( + array_to_rows( + [['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2], ['a' => 3, 'b' => 3]], + schema(int_schema('a'), int_schema('b')), + ), + array_to_rows( + [['a' => 1, 'b' => 1], ['a' => 1, 'b' => 9], ['a' => 9, 'b' => 9]], + schema(int_schema('a'), int_schema('b')), + ), + ), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AnyTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AnyTest.php index 25920a3021..567acd952d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AnyTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/AnyTest.php @@ -4,11 +4,12 @@ namespace Flow\ETL\Tests\Unit\Join\Comparison; -use Flow\ETL\Join\Comparison; use Flow\ETL\Join\Comparison\Any; +use Flow\ETL\Join\Comparison\Equal; +use Flow\ETL\Tests\Double\ConstantComparison; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -16,29 +17,48 @@ final class AnyTest extends FlowTestCase { public function test_failure(): void { - $comparison1 = self::createStub(Comparison::class); - $comparison1->method('compare')->willReturn(false); + $comparison1 = new ConstantComparison(false); - $comparison2 = self::createStub(Comparison::class); - $comparison2->method('compare')->willReturn(false); + $comparison2 = new ConstantComparison(false); - static::assertFalse((new Any($comparison1, $comparison2))->compare( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - )); + static::assertSame( + [false], + (new Any($comparison1, $comparison2))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + ), + ); } public function test_success(): void { - $comparison1 = self::createStub(Comparison::class); - $comparison1->method('compare')->willReturn(true); + $comparison1 = new ConstantComparison(true); - $comparison2 = self::createStub(Comparison::class); - $comparison2->method('compare')->willReturn(false); + $comparison2 = new ConstantComparison(false); - static::assertTrue((new Any($comparison1, $comparison2))->compare( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - )); + static::assertSame( + [true], + (new Any($comparison1, $comparison2))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + ), + ); + } + + public function test_combines_children_element_wise(): void + { + static::assertSame( + [true, true, false], + (new Any(new Equal('a', 'a'), new Equal('b', 'b')))->compare( + array_to_rows( + [['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2], ['a' => 3, 'b' => 3]], + schema(int_schema('a'), int_schema('b')), + ), + array_to_rows( + [['a' => 1, 'b' => 1], ['a' => 1, 'b' => 9], ['a' => 9, 'b' => 9]], + schema(int_schema('a'), int_schema('b')), + ), + ), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/EqualTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/EqualTest.php index ff9989029d..0b6b7a8418 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/EqualTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/EqualTest.php @@ -8,8 +8,9 @@ use Flow\ETL\Join\Comparison\Equal; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -18,67 +19,107 @@ final class EqualTest extends FlowTestCase { public function test_failure(): void { - static::assertFalse((new Equal('datetime', 'datetime'))->compare( - array_to_row([ - 'datetime' => new DateTimeImmutable('2022-10-01 00:00:00'), - ], schema(datetime_schema('datetime'))), - array_to_row([ - 'datetime' => new DateTimeImmutable('2022-10-01 01:00:00'), - ], schema(datetime_schema('datetime'))), - )); + static::assertSame( + [false], + (new Equal('datetime', 'datetime'))->compare( + array_to_rows([[ + 'datetime' => new DateTimeImmutable('2022-10-01 00:00:00'), + ]], schema(datetime_schema('datetime'))), + array_to_rows([[ + 'datetime' => new DateTimeImmutable('2022-10-01 01:00:00'), + ]], schema(datetime_schema('datetime'))), + ), + ); } public function test_null_is_not_equal_to_null(): void { - static::assertFalse((new Equal('id', 'id'))->compare( - array_to_row(['id' => null], schema(str_schema('id', nullable: true))), - array_to_row(['id' => null], schema(str_schema('id', nullable: true))), - )); + static::assertSame( + [false], + (new Equal('id', 'id'))->compare( + array_to_rows([['id' => null]], schema(str_schema('id', nullable: true))), + array_to_rows([['id' => null]], schema(str_schema('id', nullable: true))), + ), + ); } public function test_null_is_not_equal_to_value(): void { - static::assertFalse((new Equal('id', 'id'))->compare( - array_to_row(['id' => null], schema(int_schema('id', nullable: true))), - array_to_row(['id' => 1], schema(int_schema('id'))), - )); - static::assertFalse((new Equal('id', 'id'))->compare( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => null], schema(int_schema('id', nullable: true))), - )); + static::assertSame( + [false], + (new Equal('id', 'id'))->compare( + array_to_rows([['id' => null]], schema(int_schema('id', nullable: true))), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ), + ); + static::assertSame( + [false], + (new Equal('id', 'id'))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => null]], schema(int_schema('id', nullable: true))), + ), + ); } public function test_object_and_scalar_are_not_equal(): void { - static::assertFalse((new Equal('id', 'id'))->compare( - array_to_row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479'], schema(str_schema('id'))), - array_to_row(['id' => 1], schema(int_schema('id'))), - )); + static::assertSame( + [false], + (new Equal('id', 'id'))->compare( + array_to_rows([['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']], schema(str_schema('id'))), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ), + ); } public function test_uuid_objects_with_different_values_are_not_equal(): void { - static::assertFalse((new Equal('id', 'id'))->compare( - array_to_row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479'], schema(str_schema('id'))), - array_to_row(['id' => '00000000-0000-4000-8000-000000000000'], schema(str_schema('id'))), - )); + static::assertSame( + [false], + (new Equal('id', 'id'))->compare( + array_to_rows([['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']], schema(str_schema('id'))), + array_to_rows([['id' => '00000000-0000-4000-8000-000000000000']], schema(str_schema('id'))), + ), + ); } public function test_uuid_objects_with_same_value_are_equal(): void { - static::assertTrue((new Equal('id', 'id'))->compare( - array_to_row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479'], schema(str_schema('id'))), - array_to_row(['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479'], schema(str_schema('id'))), - )); + static::assertSame( + [true], + (new Equal('id', 'id'))->compare( + array_to_rows([['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']], schema(str_schema('id'))), + array_to_rows([['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479']], schema(str_schema('id'))), + ), + ); } public function test_success(): void { - static::assertTrue((new Equal('datetime', 'datetime'))->compare( - array_to_row([ - 'datetime' => $datetime = new DateTimeImmutable('2022-10-01 00:00:00'), - ], schema(datetime_schema('datetime'))), - array_to_row(['datetime' => $datetime], schema(datetime_schema('datetime'))), - )); + static::assertSame( + [true], + (new Equal('datetime', 'datetime'))->compare( + array_to_rows([[ + 'datetime' => $datetime = new DateTimeImmutable('2022-10-01 00:00:00'), + ]], schema(datetime_schema('datetime'))), + array_to_rows([['datetime' => $datetime]], schema(datetime_schema('datetime'))), + ), + ); + } + + public function test_compares_pair_aligned_batches(): void + { + static::assertSame( + [true, false, false, true], + (new Equal('a', 'b'))->compare( + array_to_rows([ + ['a' => 1], + ['a' => 2], + ['a' => null], + ['a' => 4], + ], schema(int_schema('a', nullable: true))), + array_to_rows([['b' => 1.0], ['b' => 3.0], ['b' => 1.0], ['b' => 4.0]], schema(float_schema('b'))), + ), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/IdenticalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/IdenticalTest.php index 527cf9ec02..b6f2823330 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/IdenticalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/Comparison/IdenticalTest.php @@ -4,49 +4,117 @@ namespace Flow\ETL\Tests\Unit\Join\Comparison; +use DateTimeImmutable; use Flow\ETL\Join\Comparison\Identical; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\uuid_schema; final class IdenticalTest extends FlowTestCase { public function test_failure(): void { - static::assertFalse((new Identical('id', 'id'))->compare( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 2], schema(int_schema('id'))), - )); + static::assertSame( + [false], + (new Identical('id', 'id'))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 2]], schema(int_schema('id'))), + ), + ); } public function test_null_is_not_identical_to_null(): void { - static::assertFalse((new Identical('id', 'id'))->compare( - array_to_row(['id' => null], schema(str_schema('id', nullable: true))), - array_to_row(['id' => null], schema(str_schema('id', nullable: true))), - )); + static::assertSame( + [false], + (new Identical('id', 'id'))->compare( + array_to_rows([['id' => null]], schema(str_schema('id', nullable: true))), + array_to_rows([['id' => null]], schema(str_schema('id', nullable: true))), + ), + ); } public function test_null_is_not_identical_to_value(): void { - static::assertFalse((new Identical('id', 'id'))->compare( - array_to_row(['id' => null], schema(int_schema('id', nullable: true))), - array_to_row(['id' => 1], schema(int_schema('id'))), - )); - static::assertFalse((new Identical('id', 'id'))->compare( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => null], schema(int_schema('id', nullable: true))), - )); + static::assertSame( + [false], + (new Identical('id', 'id'))->compare( + array_to_rows([['id' => null]], schema(int_schema('id', nullable: true))), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ), + ); + static::assertSame( + [false], + (new Identical('id', 'id'))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => null]], schema(int_schema('id', nullable: true))), + ), + ); } public function test_success(): void { - static::assertTrue((new Identical('id', 'id'))->compare( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 1], schema(int_schema('id'))), - )); + static::assertSame( + [true], + (new Identical('id', 'id'))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ), + ); + } + + public function test_compares_pair_aligned_batches(): void + { + static::assertSame( + [true, false, false], + (new Identical('id', 'id'))->compare( + array_to_rows([['id' => 1], ['id' => 2], ['id' => null]], schema(int_schema('id', nullable: true))), + array_to_rows([['id' => 1], ['id' => 3], ['id' => null]], schema(int_schema('id', nullable: true))), + ), + ); + } + + public function test_equal_datetimes_are_identical(): void + { + static::assertSame( + [true], + (new Identical('at', 'at'))->compare( + array_to_rows([['at' => new DateTimeImmutable('2024-01-01 00:00:00')]], schema(datetime_schema('at'))), + array_to_rows([['at' => new DateTimeImmutable('2024-01-01 00:00:00')]], schema(datetime_schema('at'))), + ), + ); + } + + public function test_equal_uuids_are_identical(): void + { + static::assertSame( + [true, false], + (new Identical('id', 'id'))->compare( + array_to_rows([ + ['id' => '00000000-0000-4000-8000-000000000001'], + ['id' => '00000000-0000-4000-8000-000000000001'], + ], schema(uuid_schema('id'))), + array_to_rows([ + ['id' => '00000000-0000-4000-8000-000000000001'], + ['id' => '00000000-0000-4000-8000-000000000002'], + ], schema(uuid_schema('id'))), + ), + ); + } + + public function test_values_of_different_types_are_not_identical(): void + { + static::assertSame( + [false], + (new Identical('id', 'id'))->compare( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => '1']], schema(str_schema('id'))), + ), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/ExpressionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/ExpressionTest.php index 6a9e0111e7..50a583400c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/ExpressionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/ExpressionTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Join\Expression; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\col; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -28,9 +28,12 @@ public function test_expression_comparison(): void { $expression = Expression::on(new Equal('id', 'id'), '_'); - static::assertTrue($expression->meet( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 1], schema(int_schema('id'))), - )); + static::assertSame( + [true], + $expression->meet( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 1]], schema(int_schema('id'))), + ), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/HashTableTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/HashTableTest.php index c6ef239f9e..8a444ebb42 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/HashTableTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/HashTableTest.php @@ -7,61 +7,41 @@ use Flow\ETL\Join\HashJoin\HashTable; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; -use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\schema; -use function Flow\ETL\DSL\str_schema; -use function iterator_to_array; - final class HashTableTest extends FlowTestCase { public function test_candidates_for_matching_hash(): void { $hashTable = new HashTable(); - $hashTable->add('hash-a', array_to_row( - ['user_id' => 1, 'name' => 'Alice'], - schema(int_schema('user_id'), str_schema('name')), - )); - $hashTable->add('hash-b', array_to_row( - ['user_id' => 2, 'name' => 'Bob'], - schema(int_schema('user_id'), str_schema('name')), - )); - - $candidates = $hashTable->candidatesFor('hash-a'); - - static::assertCount(1, $candidates); - static::assertSame('Alice', $candidates[0]->get('name')); + $hashTable->add('hash-a', 0); + $hashTable->add('hash-b', 1); + $hashTable->add('hash-a', 2); + + static::assertSame([0, 2], $hashTable->candidatesFor('hash-a')); + static::assertSame([1], $hashTable->candidatesFor('hash-b')); } public function test_constant_hash_makes_every_row_a_candidate(): void { $hashTable = new HashTable(); - $hashTable->add('0', array_to_row(['user_id' => 1], schema(int_schema('user_id')))); - $hashTable->add('0', array_to_row(['user_id' => 2], schema(int_schema('user_id')))); + $hashTable->add('0', 0); + $hashTable->add('0', 1); - static::assertCount(2, $hashTable->candidatesFor('0')); + static::assertSame([0, 1], $hashTable->candidatesFor('0')); } - public function test_duplicated_rows_are_preserved(): void + public function test_count_is_every_added_row(): void { $hashTable = new HashTable(); - $hashTable->add('hash-a', array_to_row( - ['user_id' => 1, 'name' => 'Alice'], - schema(int_schema('user_id'), str_schema('name')), - )); - $hashTable->add('hash-a', array_to_row( - ['user_id' => 1, 'name' => 'Alice'], - schema(int_schema('user_id'), str_schema('name')), - )); + $hashTable->add('hash-a', 0); + $hashTable->add('hash-a', 1); static::assertSame(2, $hashTable->count()); - static::assertCount(2, $hashTable->candidatesFor('hash-a')); } public function test_no_candidates_for_unknown_hash(): void { $hashTable = new HashTable(); - $hashTable->add('hash-a', array_to_row(['user_id' => 1], schema(int_schema('user_id')))); + $hashTable->add('hash-a', 0); static::assertSame([], $hashTable->candidatesFor('hash-404')); } @@ -69,33 +49,20 @@ public function test_no_candidates_for_unknown_hash(): void public function test_unmatched_rows_tracking(): void { $hashTable = new HashTable(trackUnmatched: true); - $hashTable->add('hash-a', array_to_row( - ['user_id' => 1, 'name' => 'Alice'], - schema(int_schema('user_id'), str_schema('name')), - )); - $hashTable->add('hash-b', array_to_row( - ['user_id' => 2, 'name' => 'Bob'], - schema(int_schema('user_id'), str_schema('name')), - )); - $hashTable->add('hash-c', array_to_row( - ['user_id' => 3, 'name' => 'Cid'], - schema(int_schema('user_id'), str_schema('name')), - )); + $hashTable->add('hash-a', 0); + $hashTable->add('hash-b', 1); + $hashTable->add('hash-c', 2); $hashTable->matched(1); - $unmatched = iterator_to_array($hashTable->unmatchedRows(), false); - - static::assertCount(2, $unmatched); - static::assertSame('Alice', $unmatched[0]->get('name')); - static::assertSame('Cid', $unmatched[1]->get('name')); + static::assertSame([0, 2], $hashTable->unmatched()); } public function test_unmatched_rows_without_tracking_are_empty(): void { $hashTable = new HashTable(); - $hashTable->add('hash-a', array_to_row(['user_id' => 1], schema(int_schema('user_id')))); + $hashTable->add('hash-a', 0); - static::assertSame([], iterator_to_array($hashTable->unmatchedRows(), false)); + static::assertSame([], $hashTable->unmatched()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php index 5851f3fb0a..8cfb579383 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php @@ -4,7 +4,6 @@ namespace Flow\ETL\Tests\Unit\Join\HashJoin; -use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\SchemaDefinitionNotUniqueException; use Flow\ETL\Join\Comparison\All; use Flow\ETL\Join\Comparison\Any; @@ -37,7 +36,6 @@ public function test_any_comparison_falls_back_to_verifying_every_pair(): void $joiner = new Joiner( Expression::on(new Any(new Equal('id', 'user_id'), new Equal('email', 'contact'))), Join::inner, - new PhpBackend(), ); foreach ($joiner->join( @@ -89,7 +87,6 @@ public function test_all_with_any_hashes_by_the_equality_and_verifies_the_rest() ), ), Join::inner, - new PhpBackend(), ); foreach ($joiner->join( @@ -136,7 +133,7 @@ public function test_duplicated_right_rows_are_all_joined(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); foreach ($joiner->join( JoinSide::of($batches(array_to_rows([['id' => 1]], schema(int_schema('id'))))), @@ -161,7 +158,7 @@ public function test_inner_join_emits_every_matching_right_row(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -199,7 +196,7 @@ public function test_inner_join_drops_duplicated_right_join_columns(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'id']), Join::inner, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'id']), Join::inner); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -228,7 +225,7 @@ public function test_left_anti_join_keeps_left_row_on_hash_hit_without_match(): $joined = []; // int 1 and string "1" hash into the same bucket but are not identical - $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left_anti, new PhpBackend()); + $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left_anti); $right = static function (): Generator { yield array_to_rows([['user_id' => '2']], schema(str_schema('user_id'))); @@ -257,7 +254,7 @@ public function test_left_join_keeps_left_row_on_hash_hit_without_match(): void $joined = []; // int 1 and string "1" hash into the same bucket but are not identical - $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left, new PhpBackend()); + $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -285,7 +282,7 @@ public function test_left_join_pads_unmatched_left_rows_with_nulls(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -320,7 +317,7 @@ public function test_prefix_collision_with_left_column_throws(): void $this->expectException(SchemaDefinitionNotUniqueException::class); $this->expectExceptionMessage('Entry definitions must be unique, duplicated entries: [left_name]'); - $joiner = new Joiner(join_on(['id' => 'user_id'], join_prefix: 'left_'), Join::inner, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id'], join_prefix: 'left_'), Join::inner); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -344,7 +341,7 @@ public function test_swapped_inner_join_emits_the_same_rows(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -383,7 +380,7 @@ public function test_swapped_left_anti_join_emits_unmatched_left_rows_at_the_end $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left_anti, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left_anti); foreach ($joiner->join( JoinSide::of($batches(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))))), @@ -406,7 +403,7 @@ public function test_swapped_left_join_pads_unmatched_left_rows_at_the_end(): vo $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -445,7 +442,7 @@ public function test_swapped_left_join_with_empty_right_side_pads_every_left_row $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -471,7 +468,7 @@ public function test_swapped_right_join_pads_unmatched_right_rows_inline(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -506,7 +503,7 @@ public function test_right_join_emits_unmatched_right_rows_with_null_left_entrie $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -538,7 +535,7 @@ public function test_left_join_emits_a_schema_declaring_the_right_side_nullable( yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); $emitted = iterator_to_array( $joiner->join( @@ -571,7 +568,7 @@ public function test_right_join_emits_a_schema_declaring_the_left_side_nullable( yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); $emitted = iterator_to_array( $joiner->join( @@ -600,7 +597,7 @@ public function test_right_join_emits_a_schema_declaring_the_left_side_nullable( public function test_every_batch_of_a_multi_batch_left_side_shares_one_output_schema(): void { - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); $emitted = iterator_to_array( $joiner->join( @@ -638,7 +635,7 @@ public function test_a_padded_row_covers_a_right_column_no_source_row_carried(): yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); $joined = []; @@ -673,7 +670,7 @@ public function test_a_row_omitting_a_nullable_join_key_is_unmatched_rather_than yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); $joined = []; @@ -707,7 +704,7 @@ public function test_a_left_batch_wider_than_the_output_schema_is_projected_not_ yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new PhpBackend()); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); $joined = []; @@ -729,4 +726,99 @@ public function test_a_left_batch_wider_than_the_output_schema_is_projected_not_ static::assertSame([['id' => 404, 'user_id' => null]], $joined); } + + public function test_a_build_side_spanning_batches_is_joined_as_one(): void + { + $right = static function (): Generator { + yield array_to_rows( + [['user_id' => 1, 'name' => 'Alice']], + schema(int_schema('user_id'), str_schema('name')), + ); + yield array_to_rows([], schema(int_schema('user_id'), str_schema('name'))); + yield array_to_rows([['user_id' => 2, 'name' => 'Bob']], schema(int_schema('user_id'), str_schema('name'))); + }; + $left = static function (): Generator { + yield array_to_rows([['id' => 2], ['id' => 1], ['id' => 3]], schema(int_schema('id'))); + }; + + $joined = []; + + foreach ((new Joiner(join_on(['id' => 'user_id']), Join::left))->join( + JoinSide::of($left()), + JoinSide::of($right()), + ) as $batch) { + $joined = [...$joined, ...$batch->toArray()]; + } + + static::assertSame( + [ + ['id' => 2, 'user_id' => 2, 'name' => 'Bob'], + ['id' => 1, 'user_id' => 1, 'name' => 'Alice'], + ['id' => 3, 'user_id' => null, 'name' => null], + ], + $joined, + ); + } + + public function test_swapped_unmatched_build_rows_are_emitted_in_chunks_of_batch_size(): void + { + $left = static function (): Generator { + yield array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ['id' => 4], + ['id' => 5], + ], schema(int_schema('id'))); + }; + $right = static function (): Generator { + yield array_to_rows([['user_id' => 3]], schema(int_schema('user_id'))); + }; + + $batches = []; + + foreach ((new Joiner(join_on(['id' => 'user_id']), Join::left, batchSize: 2))->join( + JoinSide::of($left()), + JoinSide::of($right()), + buildLeft: true, + ) as $batch) { + $batches[] = $batch->column('id')->values(); + } + + static::assertSame([[3], [1, 2], [4, 5]], $batches); + } + + public function test_unmatched_build_rows_are_emitted_in_chunks_of_batch_size(): void + { + $left = static function (): Generator { + yield array_to_rows([['id' => 3]], schema(int_schema('id'))); + }; + $right = static function (): Generator { + yield array_to_rows([ + ['user_id' => 1], + ['user_id' => 2], + ['user_id' => 3], + ['user_id' => 4], + ['user_id' => 5], + ], schema(int_schema('user_id'))); + }; + + $batches = []; + + foreach ((new Joiner(join_on(['id' => 'user_id']), Join::right, batchSize: 2))->join( + JoinSide::of($left()), + JoinSide::of($right()), + ) as $batch) { + $batches[] = $batch->toArray(); + } + + static::assertSame( + [ + [['id' => 3, 'user_id' => 3]], + [['id' => null, 'user_id' => 1], ['id' => null, 'user_id' => 2]], + [['id' => null, 'user_id' => 4], ['id' => null, 'user_id' => 5]], + ], + $batches, + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/NullRowBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/NullRowBuilderTest.php index c029e825c0..9bec52016a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/NullRowBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/NullRowBuilderTest.php @@ -7,30 +7,41 @@ use Flow\ETL\Join\HashJoin\NullRowBuilder; use Flow\ETL\Tests\FlowTestCase; +use function array_keys; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; final class NullRowBuilderTest extends FlowTestCase { - public function test_empty_schema_produces_empty_row(): void + public function test_empty_schema_produces_one_row_without_columns(): void { - static::assertSame([], (new NullRowBuilder(schema()))->row()->toArray()); + $rows = (new NullRowBuilder(schema()))->rows(); + + static::assertSame(1, $rows->count()); + static::assertSame([], $rows->columns()); } public function test_row_follows_schema_column_order(): void { static::assertSame( ['name', 'id'], - (new NullRowBuilder(schema(str_schema('name'), int_schema('id'))))->row()->names(), + array_keys((new NullRowBuilder(schema(str_schema('name'), int_schema('id'))))->rows()->columns()), ); } - public function test_row_nulls_every_schema_column(): void + public function test_row_nulls_every_schema_column_under_a_nullable_schema(): void { - static::assertSame( - ['id' => null, 'name' => null, 'country' => null], - (new NullRowBuilder(schema(int_schema('id'), str_schema('name'), str_schema('country'))))->row()->toArray(), + $rows = (new NullRowBuilder(schema(int_schema('id'), str_schema('name'), str_schema('country'))))->rows(); + + static::assertSame([['id' => null, 'name' => null, 'country' => null]], $rows->toArray()); + static::assertEquals( + schema( + int_schema('id', nullable: true), + str_schema('name', nullable: true), + str_schema('country', nullable: true), + ), + $rows->schema(), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php index 3baba11e2a..4b9165cd5f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/RowMergerTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Join\HashJoin\RowMerger; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -20,10 +20,12 @@ public function test_collision_between_left_and_right_names_throws(): void $this->expectException(DuplicatedEntriesException::class); $this->expectExceptionMessage('Merged entries names must be unique'); - (new RowMerger())->merge( - array_to_row(['id' => 1, 'name' => 'left'], schema(int_schema('id'), str_schema('name'))), - array_to_row(['name' => 'right'], schema(str_schema('name'))), - ); + (new RowMerger()) + ->merge( + array_to_rows([['id' => 1, 'name' => 'left']], schema(int_schema('id'), str_schema('name'))), + array_to_rows([['name' => 'right']], schema(str_schema('name'))), + ) + ->values(0); } public function test_drop_left_skips_duplicated_join_columns(): void @@ -32,10 +34,12 @@ public function test_drop_left_skips_duplicated_join_columns(): void static::assertSame( ['amount' => 100, 'id' => 1, 'name' => 'Alice'], - $merger->merge( - array_to_row(['id' => 1, 'amount' => 100], schema(int_schema('id'), int_schema('amount'))), - array_to_row(['id' => 1, 'name' => 'Alice'], schema(int_schema('id'), str_schema('name'))), - ), + $merger + ->merge( + array_to_rows([['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount'))), + array_to_rows([['id' => 1, 'name' => 'Alice']], schema(int_schema('id'), str_schema('name'))), + ) + ->values(0), ); } @@ -45,10 +49,12 @@ public function test_drop_right_skips_duplicated_join_columns(): void static::assertSame( ['id' => 1, 'amount' => 100, 'name' => 'Alice'], - $merger->merge( - array_to_row(['id' => 1, 'amount' => 100], schema(int_schema('id'), int_schema('amount'))), - array_to_row(['id' => 1, 'name' => 'Alice'], schema(int_schema('id'), str_schema('name'))), - ), + $merger + ->merge( + array_to_rows([['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount'))), + array_to_rows([['id' => 1, 'name' => 'Alice']], schema(int_schema('id'), str_schema('name'))), + ) + ->values(0), ); } @@ -56,10 +62,12 @@ public function test_merge_without_prefix_keeps_right_names(): void { static::assertSame( ['id' => 1, 'name' => 'Alice'], - (new RowMerger())->merge( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['name' => 'Alice'], schema(str_schema('name'))), - ), + (new RowMerger()) + ->merge( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['name' => 'Alice']], schema(str_schema('name'))), + ) + ->values(0), ); } @@ -67,29 +75,35 @@ public function test_prefix_collision_with_left_name_throws(): void { $this->expectException(DuplicatedEntriesException::class); - (new RowMerger('left_'))->merge( - array_to_row(['left_name' => 'left'], schema(str_schema('left_name'))), - array_to_row(['name' => 'right'], schema(str_schema('name'))), - ); + (new RowMerger('left_')) + ->merge( + array_to_rows([['left_name' => 'left']], schema(str_schema('left_name'))), + array_to_rows([['name' => 'right']], schema(str_schema('name'))), + ) + ->values(0); } public function test_prefix_renames_every_right_entry(): void { static::assertSame( ['id' => 1, 'right_id' => 1, 'right_name' => 'Alice'], - (new RowMerger('right_'))->merge( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['id' => 1, 'name' => 'Alice'], schema(int_schema('id'), str_schema('name'))), - ), + (new RowMerger('right_')) + ->merge( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['id' => 1, 'name' => 'Alice']], schema(int_schema('id'), str_schema('name'))), + ) + ->values(0), ); } public function test_renamed_entries_carry_renamed_names(): void { - $merged = (new RowMerger('r_'))->merge( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['name' => 'Alice'], schema(str_schema('name'))), - ); + $merged = (new RowMerger('r_')) + ->merge( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['name' => 'Alice']], schema(str_schema('name'))), + ) + ->values(0); static::assertSame(['id' => 1, 'r_name' => 'Alice'], $merged); } @@ -100,17 +114,21 @@ public function test_reused_plan_renames_rows_with_identical_name_sets(): void static::assertSame( ['id' => 1, 'r_x' => 'a'], - $merger->merge( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['x' => 'a'], schema(str_schema('x'))), - ), + $merger + ->merge( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['x' => 'a']], schema(str_schema('x'))), + ) + ->values(0), ); static::assertSame( ['id' => 2, 'r_x' => 5], - $merger->merge( - array_to_row(['id' => 2], schema(int_schema('id'))), - array_to_row(['x' => 5], schema(int_schema('x'))), - ), + $merger + ->merge( + array_to_rows([['id' => 2]], schema(int_schema('id'))), + array_to_rows([['x' => 5]], schema(int_schema('x'))), + ) + ->values(0), ); } @@ -120,24 +138,50 @@ public function test_reused_merger_handles_rows_with_different_entry_sets(): voi static::assertSame( ['id' => 1, 'name' => 'Alice'], - $merger->merge( - array_to_row(['id' => 1], schema(int_schema('id'))), - array_to_row(['name' => 'Alice'], schema(str_schema('name'))), - ), + $merger + ->merge( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + array_to_rows([['name' => 'Alice']], schema(str_schema('name'))), + ) + ->values(0), ); static::assertSame( ['id' => 2, 'name' => 'Bob', 'age' => 30], - $merger->merge( - array_to_row(['id' => 2], schema(int_schema('id'))), - array_to_row(['name' => 'Bob', 'age' => 30], schema(str_schema('name'), int_schema('age'))), - ), + $merger + ->merge( + array_to_rows([['id' => 2]], schema(int_schema('id'))), + array_to_rows([['name' => 'Bob', 'age' => 30]], schema(str_schema('name'), int_schema('age'))), + ) + ->values(0), ); static::assertSame( ['id' => 3, 'name' => 'Cid'], - $merger->merge( - array_to_row(['id' => 3], schema(int_schema('id'))), - array_to_row(['name' => 'Cid'], schema(str_schema('name'))), + $merger + ->merge( + array_to_rows([['id' => 3]], schema(int_schema('id'))), + array_to_rows([['name' => 'Cid']], schema(str_schema('name'))), + ) + ->values(0), + ); + } + + public function test_merges_pair_aligned_batches_with_renamed_definitions(): void + { + $merged = (new RowMerger('r_'))->merge( + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), + array_to_rows( + [['id' => 10, 'name' => null], ['id' => 20, 'name' => 'b']], + schema(int_schema('id'), str_schema('name', nullable: true)), ), ); + + static::assertEquals( + schema(int_schema('id'), int_schema('r_id'), str_schema('r_name', nullable: true)), + $merged->schema(), + ); + static::assertSame( + [['id' => 1, 'r_id' => 10, 'r_name' => null], ['id' => 2, 'r_id' => 20, 'r_name' => 'b']], + $merged->toArray(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php index 4af6037423..c40f0d691f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/JoinShapeTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Join\JoinShape; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\join_on; use function Flow\ETL\DSL\schema; @@ -105,10 +105,13 @@ public function test_the_merger_drops_the_same_column_the_schema_does(): void { static::assertSame( ['id' => 1, 'country' => 'PL', 'name' => 'Norbert'], - JoinShape::of(join_on(['id' => 'id']), Join::inner)->merger()->merge( - array_to_row(['id' => 1, 'country' => 'PL'], schema(int_schema('id'), str_schema('country'))), - array_to_row(['id' => 1, 'name' => 'Norbert'], schema(int_schema('id'), str_schema('name'))), - ), + JoinShape::of(join_on(['id' => 'id']), Join::inner) + ->merger() + ->merge( + array_to_rows([['id' => 1, 'country' => 'PL']], schema(int_schema('id'), str_schema('country'))), + array_to_rows([['id' => 1, 'name' => 'Norbert']], schema(int_schema('id'), str_schema('name'))), + ) + ->values(0), ); } @@ -116,10 +119,13 @@ public function test_the_merger_of_a_right_join_keeps_the_right_side_value(): vo { static::assertSame( ['country' => 'PL', 'id' => 2, 'name' => 'Norbert'], - JoinShape::of(join_on(['id' => 'id']), Join::right)->merger()->merge( - array_to_row(['id' => 1, 'country' => 'PL'], schema(int_schema('id'), str_schema('country'))), - array_to_row(['id' => 2, 'name' => 'Norbert'], schema(int_schema('id'), str_schema('name'))), - ), + JoinShape::of(join_on(['id' => 'id']), Join::right) + ->merger() + ->merge( + array_to_rows([['id' => 1, 'country' => 'PL']], schema(int_schema('id'), str_schema('country'))), + array_to_rows([['id' => 2, 'name' => 'Norbert']], schema(int_schema('id'), str_schema('name'))), + ) + ->values(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 index 89c76c22f8..40b51a92fe 100644 --- 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 @@ -7,7 +7,6 @@ use Flow\ETL\Memory\ArrayMemory; use Flow\ETL\Optimizer\Rule\CombineSortAndLimit; use Flow\ETL\Plan\LogicalPlan; -use Flow\ETL\Plan\Node\Limit; use Flow\ETL\Plan\Node\Outputs; use Flow\ETL\Plan\Node\Result; use Flow\ETL\Plan\Node\Sort; @@ -16,8 +15,6 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\NodeMother; -use function Flow\ETL\DSL\config_builder; -use function Flow\ETL\DSL\external_sort; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; use function Flow\ETL\DSL\to_memory; @@ -48,19 +45,6 @@ public function test_a_limit_over_anything_else_is_left_alone(): void 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()); 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 index 6e1232c096..053bafae5b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/TopNRewriteTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Optimizer/TopNRewriteTest.php @@ -4,16 +4,14 @@ namespace Flow\ETL\Tests\Unit\Optimizer; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Optimizer\TopNRewrite; -use Flow\ETL\Plan\Node\Limit; use Flow\ETL\Plan\Node\Sort; use Flow\ETL\Plan\Node\TopN; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\NodeMother; -use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\external_sort; -use function Flow\ETL\DSL\memory_sort; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; @@ -23,14 +21,14 @@ public function test_a_node_that_is_not_a_limit_is_returned_as_is(): void { $sort = NodeMother::sort(NodeMother::read()); - static::assertSame($sort, (new TopNRewrite(NodeMother::context()))->of($sort)); + static::assertSame($sort, (new TopNRewrite())->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)); + static::assertSame($limit, (new TopNRewrite())->of($limit)); } public function test_a_limit_over_a_sort_becomes_a_top_n_over_the_sorts_input_refs_and_limit(): void @@ -38,7 +36,7 @@ public function test_a_limit_over_a_sort_becomes_a_top_n_over_the_sorts_input_re $read = NodeMother::read(); $refs = refs(ref('id')); - $topN = (new TopNRewrite(NodeMother::context()))->of(NodeMother::limit(new Sort($read, $refs), 5)); + $topN = (new TopNRewrite())->of(NodeMother::limit(new Sort($read, $refs), 5)); static::assertInstanceOf(TopN::class, $topN); static::assertSame([$read], $topN->children()); @@ -46,31 +44,16 @@ public function test_a_limit_over_a_sort_becomes_a_top_n_over_the_sorts_input_re static::assertSame(5, $topN->limit); } - public function test_an_external_sort_is_rewritten_up_to_its_run_size_and_kept_beyond_it(): void + public function test_a_limit_over_any_sort_is_rewritten_and_keeps_the_pinned_algorithm(): void { - $rewrite = new TopNRewrite(NodeMother::context()); - $sort = new Sort(NodeMother::read(), refs(ref('id')), external_sort()->runSize(10)); + $algorithm = external_sort()->memoryLimit(Unit::fromMb(1)); - static::assertInstanceOf(TopN::class, $rewrite->of(NodeMother::limit($sort, 10))); - static::assertInstanceOf(Limit::class, $rewrite->of(NodeMother::limit($sort, 11))); - } + $topN = (new TopNRewrite())->of(NodeMother::limit( + new Sort(NodeMother::read(), refs(ref('id')), $algorithm), + 1_000_000, + )); - 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)), - ); + static::assertInstanceOf(TopN::class, $topN); + static::assertSame($algorithm, $topN->algorithm); } } 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 index bce4212b75..d8d612ddeb 100644 --- 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 @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Plan\Explain; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Plan\Explain\PhysicalOutline; use Flow\ETL\Plan\Explain\TreeLayout; use Flow\ETL\Tests\Double\UndescribableRowLessExtractor; @@ -12,6 +13,7 @@ use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\from_array; +use function Flow\ETL\DSL\hash_join; use function Flow\ETL\DSL\join_on; use function Flow\ETL\DSL\to_output; @@ -72,6 +74,7 @@ public function test_a_joined_frame_is_a_plan_of_its_own_under_the_step_that_rea │ On: id = id │ Prefix: joined_ │ Storage: FilesystemBuckets + │ Memory: 64 MB │ Buckets: 64 │ Batch: 1000 └─ Right side: Pipeline #0 @@ -84,6 +87,7 @@ public function test_a_joined_frame_is_a_plan_of_its_own_under_the_step_that_rea ->join( data_frame()->read(from_array([['id' => 1]])), join_on(['id' => 'id'], join_prefix: 'joined_'), + algorithm: hash_join()->memoryLimit(Unit::fromMb(64)), ) ->collect() ->write(to_output(truncate: false)), 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 index 1515448c22..ee505f89b8 100644 --- 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 @@ -5,11 +5,11 @@ namespace Flow\ETL\Tests\Unit\Plan\Explain; use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\HashBucketing; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\Storage\MemoryBuckets; use Flow\ETL\Cardinality; use Flow\ETL\Constraint\UniqueConstraint; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Executor; use Flow\ETL\Extractor\Statistics; use Flow\ETL\GroupBy; @@ -17,27 +17,27 @@ use Flow\ETL\Join\Comparison\Equal; use Flow\ETL\Join\Expression; use Flow\ETL\Join\Join; -use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\Plan\Explain\StepDetails; use Flow\ETL\Processor\BatchingByProcessor; use Flow\ETL\Processor\BatchingProcessor; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\CachingProcessor; use Flow\ETL\Processor\CollectingProcessor; use Flow\ETL\Processor\ConstrainedProcessor; -use Flow\ETL\Processor\GroupByAggregationProcessor; use Flow\ETL\Processor\MemorySortProcessor; use Flow\ETL\Processor\MergeSortProcessor; use Flow\ETL\Processor\OffsetProcessor; use Flow\ETL\Processor\PivotProcessor; -use Flow\ETL\Processor\RepartitionProcessor; use Flow\ETL\Processor\TopNProcessor; use Flow\ETL\Processor\VoidProcessor; use Flow\ETL\Processor\WindowProcessor; +use Flow\ETL\Row\NullsOrder; use Flow\ETL\Tests\Double\DeclaringExtractor; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\ExternalSortMother; +use Flow\ETL\Tests\Mother\GroupByAggregationProcessorMother; use Flow\ETL\Tests\Mother\HashJoinProcessorMother; use Flow\ETL\Tests\Mother\PhysicalPlanMother; +use Flow\ETL\Tests\Mother\RepartitionProcessorMother; use Flow\ETL\Transformer\CrossJoinRowsTransformer; use function Flow\ETL\DSL\from_array; @@ -110,19 +110,23 @@ public function test_sorting_steps_list_their_columns_with_the_direction(): void $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, - ), - ), + ['Sort: id desc', 'Memory: 64 MB', 'Spill: MemoryBuckets', 'Merge: 4 ways', 'Batch: 50'], + $details->settings(new MergeSortProcessor(ExternalSortMother::with( + refs(ref('id')->desc()), + new MemoryBuckets(), + Unit::fromMb(64), + 4, + 50, + ))), ); static::assertSame(['Top: 3', 'Sort: id asc'], $details->settings(new TopNProcessor(refs(ref('id')), 3))); + static::assertSame( + ['Sort: id asc nulls last, name desc nulls first'], + $details->settings(new MemorySortProcessor(refs( + ref('id')->asc(NullsOrder::LAST), + ref('name')->desc(NullsOrder::FIRST), + ))), + ); } public function test_a_group_by_lists_its_columns_and_aggregations(): void @@ -131,10 +135,13 @@ public function test_a_group_by_lists_its_columns_and_aggregations(): void $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), - ), + ['Group by: name', 'Aggregations: Sum', 'Memory: 64 MB', 'Storage: MemoryBuckets', 'Batch: 25'], + (new StepDetails())->settings(GroupByAggregationProcessorMother::with( + $groupBy, + new MemoryBuckets(), + Unit::fromMb(64), + batchSize: 25, + )), ); } @@ -159,10 +166,12 @@ public function test_a_pivot_lists_the_column_it_pivots_on(): void 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()), - ), + ['By: id', 'Hasher: NativeHasher', 'Memory: 64 MB', 'Storage: MemoryBuckets'], + (new StepDetails())->settings(RepartitionProcessorMother::with( + refs(ref('id')), + new MemoryBuckets(), + Unit::fromMb(64), + )), ); } @@ -235,17 +244,4 @@ public function test_a_source_that_declares_nothing_lists_no_statistics(): void { static::assertSame([], (new StepDetails())->settings(new DeclaringExtractor(new Statistics()))); } - - 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/Planner/NodeTranslatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php index 998fdbace3..08272e2083 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Planner/NodeTranslatorTest.php @@ -44,7 +44,6 @@ use Flow\ETL\Planner\NodeTranslator; use Flow\ETL\Processor\BatchingByProcessor; use Flow\ETL\Processor\BatchingProcessor; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\CachingProcessor; use Flow\ETL\Processor\CollectingProcessor; use Flow\ETL\Processor\ConstrainedProcessor; @@ -107,7 +106,7 @@ final class NodeTranslatorTest extends FlowTestCase public function test_aggregate_steps_are_the_exact_list_in_order(): void { static::assertSame( - [PruneEntriesTransformer::class, BucketingProcessor::class, GroupByAggregationProcessor::class], + [PruneEntriesTransformer::class, GroupByAggregationProcessor::class], array_map( static fn($step) => $step::class, NodeTranslator::toSteps( @@ -375,7 +374,7 @@ public function test_rename_steps_are_the_exact_list_in_order(): void public function test_repartition_steps_are_the_exact_list_in_order(): void { static::assertSame( - [BucketingProcessor::class, RepartitionProcessor::class], + [RepartitionProcessor::class], array_map( static fn($step) => $step::class, NodeTranslator::toSteps(new Repartition(NodeMother::read(), refs('id')), NodeMother::context(), []), @@ -498,7 +497,7 @@ public function test_window_column_steps_are_the_exact_list_in_order(): void 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], + [RepartitionProcessor::class, WindowProcessor::class], array_map( static fn($step) => $step::class, NodeTranslator::toSteps( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingByProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingByProcessorTest.php index 393e9d8a99..6c487677ed 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingByProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BatchingByProcessorTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Processor; +use DateTimeImmutable; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\Processor\BatchingByProcessor; @@ -11,13 +12,17 @@ use Flow\ETL\Tests\Double\CountingExtractor; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use Flow\Types\Value\Uuid; +use function array_map; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\uuid_schema; use function iterator_to_array; final class BatchingByProcessorTest extends FlowTestCase @@ -62,8 +67,20 @@ public function test_groups_rows_by_column_value(): void static::assertInstanceOf(Rows::class, $result[1]); static::assertCount(2, $result[0]); static::assertCount(2, $result[1]); - static::assertEquals('a', $result[0]->first()->get('group')); - static::assertEquals('b', $result[1]->first()->get('group')); + static::assertEquals('a', $result[0]->column('group')->value(0)); + static::assertEquals('b', $result[1]->column('group')->value(0)); + } + + public function test_an_empty_batch_is_skipped_without_reading_the_key(): void + { + $generator = (static function () { + yield array_to_rows([], schema(int_schema('id'))); + })(); + + static::assertSame( + [], + iterator_to_array((new BatchingByProcessor(ref('group')))->process($generator, flow_context())), + ); } public function test_handles_empty_input(): void @@ -116,4 +133,62 @@ public function test_throws_exception_for_invalid_min_size(): void // @mago-ignore analysis:invalid-argument new BatchingByProcessor(ref('group'), minSize: 0); } + + public function test_equal_datetimes_stay_in_one_batch(): void + { + $generator = (static function () { + yield array_to_rows( + [ + ['dt' => new DateTimeImmutable('2024-01-01 00:00:00'), 'id' => 1], + ['dt' => new DateTimeImmutable('2024-01-01 00:00:00'), 'id' => 2], + ['dt' => new DateTimeImmutable('2024-01-02 00:00:00'), 'id' => 3], + ], + schema(datetime_schema('dt'), int_schema('id')), + ); + yield array_to_rows( + [['dt' => new DateTimeImmutable('2024-01-02 00:00:00'), 'id' => 4]], + schema(datetime_schema('dt'), int_schema('id')), + ); + })(); + + $batches = iterator_to_array((new BatchingByProcessor(ref('dt')))->process($generator, flow_context()), false); + + static::assertSame( + [[1, 2], [3, 4]], + array_map(static fn(Rows $rows): array => $rows->column('id')->values(), $batches), + ); + } + + public function test_equal_uuids_stay_in_one_batch(): void + { + $generator = (static function () { + yield array_to_rows( + [ + ['u' => new Uuid('00000000-0000-4000-8000-000000000001'), 'id' => 1], + ['u' => new Uuid('00000000-0000-4000-8000-000000000001'), 'id' => 2], + ['u' => new Uuid('00000000-0000-4000-8000-000000000002'), 'id' => 3], + ], + schema(uuid_schema('u'), int_schema('id')), + ); + })(); + + $batches = iterator_to_array((new BatchingByProcessor(ref('u')))->process($generator, flow_context()), false); + + static::assertSame( + [[1, 2], [3]], + array_map(static fn(Rows $rows): array => $rows->column('id')->values(), $batches), + ); + } + + public function test_a_batch_under_another_schema_is_conformed_to_the_first(): void + { + $generator = (static function () { + yield array_to_rows([['g' => 'a', 'name' => 'x']], schema(str_schema('g'), str_schema('name', true))); + yield array_to_rows([['g' => 'a']], schema(str_schema('g'))); + })(); + + $batches = iterator_to_array((new BatchingByProcessor(ref('g')))->process($generator, flow_context()), false); + + static::assertSame([['g' => 'a', 'name' => 'x'], ['g' => 'a', 'name' => null]], $batches[0]->toArray()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BucketingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BucketingProcessorTest.php deleted file mode 100644 index 35177c4f7f..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/BucketingProcessorTest.php +++ /dev/null @@ -1,109 +0,0 @@ -bind($input)->output); - } - - public function test_empty_input_registers_no_buckets_and_yields_nothing(): void - { - $buckets = new Buckets(new MemoryBuckets()); - $processor = new BucketingProcessor( - new HashBucketing([ref('id')], 2, new NativeHasher(), new NativePHPRandomValueGenerator()), - $buckets, - ); - - $generator = (static function () { - yield from []; - })(); - - static::assertCount(0, iterator_to_array($processor->process($generator, flow_context(config())))); - static::assertCount(0, $buckets->all()); - } - - public function test_registers_every_yielded_bucket_in_the_repository(): void - { - $buckets = new Buckets(new MemoryBuckets()); - $processor = new BucketingProcessor( - new HashBucketing([ref('id')], 2, new NativeHasher(), new NativePHPRandomValueGenerator()), - $buckets, - ); - - $generator = (static function () { - yield array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); - })(); - - /** @var list $result */ - $result = iterator_to_array($processor->process($generator, flow_context(config()))); - - static::assertCount(count($buckets->all()), $result); - - $registeredIds = array_map(static fn(Bucket $bucket): string => $bucket->id, $buckets->all()); - - foreach ($result as $batch) { - static::assertContains($batch->first()->get(BucketShape::id->value), $registeredIds); - } - } - - public function test_yields_one_metadata_rows_batch_per_bucket(): void - { - $buckets = new Buckets(new MemoryBuckets()); - $processor = new BucketingProcessor( - new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()), - $buckets, - ); - - $generator = (static function () { - yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); - })(); - - /** @var list $result */ - $result = iterator_to_array($processor->process($generator, flow_context(config()))); - - static::assertCount(2, $result); - - $totalRows = 0; - - foreach ($result as $batch) { - static::assertCount(1, $batch); - $totalRows += (int) $batch->first()->get(BucketShape::totalRows->value); - } - - static::assertSame(3, $totalRows); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ConstrainedProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ConstrainedProcessorTest.php index 0e68eba4f9..105e15eb99 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ConstrainedProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/ConstrainedProcessorTest.php @@ -9,17 +9,19 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\Processor\ConstrainedProcessor; -use Flow\ETL\Row; use Flow\ETL\Rows; -use Flow\ETL\Schema; use Flow\ETL\Tests\Double\CountingExtractor; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\constraint_sorted_by; +use function Flow\ETL\DSL\constraint_unique; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; +use function is_int; final class ConstrainedProcessorTest extends FlowTestCase { @@ -56,9 +58,9 @@ public function test_handles_empty_constraints(): void public function test_handles_empty_input(): void { $constraint = new class implements Constraint { - public function isSatisfiedBy(Row $row, Schema $schema): bool + public function firstViolation(Rows $rows): ?int { - return true; + return null; } public function toString(): string @@ -66,7 +68,7 @@ public function toString(): string return 'always'; } - public function violation(Row $row, Schema $schema): string + public function violation(Rows $rows, int $index): string { return ''; } @@ -82,10 +84,16 @@ public function violation(Row $row, Schema $schema): string public function test_passes_rows_when_all_constraints_satisfied(): void { $constraint = new class implements Constraint { - public function isSatisfiedBy(Row $row, Schema $schema): bool + public function firstViolation(Rows $rows): ?int { - // @mago-ignore analysis:possibly-null-operand,possibly-invalid-operand - return $row->get('id') > 0; + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column('id')->values() as $i => $id) { + if (!is_int($id) || $id <= 0) { + return $i; + } + } + + return null; } public function toString(): string @@ -93,7 +101,7 @@ public function toString(): string return 'id > 0'; } - public function violation(Row $row, Schema $schema): string + public function violation(Rows $rows, int $index): string { return 'id must be greater than 0'; } @@ -119,10 +127,16 @@ public function test_throws_exception_for_invalid_constraint_type(): void public function test_throws_exception_when_constraint_violated(): void { $constraint = new class implements Constraint { - public function isSatisfiedBy(Row $row, Schema $schema): bool + public function firstViolation(Rows $rows): ?int { - // @mago-ignore analysis:possibly-null-operand,possibly-invalid-operand - return $row->get('id') > 0; + // @mago-ignore analysis:mixed-assignment + foreach ($rows->column('id')->values() as $i => $id) { + if (!is_int($id) || $id <= 0) { + return $i; + } + } + + return null; } public function toString(): string @@ -130,7 +144,7 @@ public function toString(): string return 'id > 0'; } - public function violation(Row $row, Schema $schema): string + public function violation(Rows $rows, int $index): string { return 'id must be greater than 0'; } @@ -142,4 +156,31 @@ public function violation(Row $row, Schema $schema): string $this->expectException(ConstraintViolationException::class); iterator_to_array($processor->process($generator, flow_context())); } + + public function test_the_earliest_violation_wins_and_names_the_stream_row(): void + { + $processor = new ConstrainedProcessor([ + constraint_unique('id'), + constraint_sorted_by(ref('n')), + ]); + $generator = (static function () { + yield array_to_rows( + [['id' => 1, 'n' => 1], ['id' => 2, 'n' => 2]], + schema(int_schema('id'), int_schema('n')), + ); + yield array_to_rows( + [['id' => 3, 'n' => 3], ['id' => 4, 'n' => 0], ['id' => 3, 'n' => 5]], + schema(int_schema('id'), int_schema('n')), + ); + })(); + + try { + iterator_to_array($processor->process($generator, flow_context())); + static::fail('expected a ConstraintViolationException'); + } catch (ConstraintViolationException $e) { + static::assertStringContainsString('Sorted constraint on [n ASC]', $e->getMessage()); + static::assertStringContainsString('current: 0, previous: 3', $e->getMessage()); + static::assertStringEndsWith('in row: 3', $e->getMessage()); + } + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php index 8543ff5b67..577b94e520 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/GroupByAggregationProcessorTest.php @@ -4,144 +4,177 @@ namespace Flow\ETL\Tests\Unit\Processor; -use Flow\ETL\Bucketing\Bucket; -use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\HashBucketing; -use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\GroupBy; -use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\Processor\GroupByAggregationProcessor; -use Flow\ETL\Tests\Context\GroupByContext; +use Flow\ETL\Tests\Context\GroupedRows; +use Flow\ETL\Tests\Double\ReportedMemoryBackend; use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\SpyBucketsStorage; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\GroupByAggregationProcessorMother; use Generator; +use PHPUnit\Framework\Attributes\DataProvider; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\collect; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\count; +use function Flow\ETL\DSL\first; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\last; +use function Flow\ETL\DSL\max; +use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\ref; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\sum; +use function iterator_to_array; +use function memory_get_usage; +use function mt_rand; +use function mt_srand; +use function serialize; final class GroupByAggregationProcessorTest extends FlowTestCase { - public function test_aggregates_every_bucket_from_the_metadata_stream(): void + public static function random_datasets(): Generator + { + for ($seed = 1; $seed <= 50; $seed++) { + yield "seed {$seed}" => [$seed]; + } + } + + public function test_under_the_limit_it_aggregates_in_one_pass_without_touching_the_buckets(): void { $groupBy = new GroupBy(ref('category')); $groupBy->aggregate(sum(ref('amount'))); + $storage = new SpyBucketsStorage(new MemoryBuckets()); - $buckets = new Buckets(new MemoryBuckets()); - $strategy = new HashBucketing( - [ref('category')], - 4, - new NativeHasher(), - new NativePHPRandomValueGenerator(), - 'group-by', - ); - - $input = (static function (): Generator { - yield array_to_rows( - [ - ['category' => 'a', 'amount' => 10], - ['category' => 'b', 'amount' => 15], - ['category' => 'a', 'amount' => 20], - ], - schema(str_schema('category'), int_schema('amount')), - ); - })(); - - $metadata = []; - - foreach ($strategy->bucketize($input, $buckets->storage()) as $bucket) { - $buckets->add($bucket); - $metadata[] = rows(Bucket::schema(), $bucket->toRow()); - } - - $result = iterator_to_array( - (new GroupByAggregationProcessor($groupBy, $buckets))->process( - (static function () use ($metadata): Generator { - yield from $metadata; - })(), + static::assertSame( + ['a' => 30.0, 'b' => 15.0], + GroupedRows::sums(GroupByAggregationProcessorMother::inMemory($groupBy, $storage)->process( + GroupedRows::categories(), flow_context(), - ), - preserve_keys: false, + )), ); - - $aggregated = []; - - foreach ($result as $batch) { - foreach ($batch->toArray() as $groupRow) { - $aggregated[$groupRow['category']] = $groupRow['amount_sum']; - } - } - - ksort($aggregated); - - static::assertSame(['a' => 30.0, 'b' => 15.0], $aggregated); + static::assertSame([], $storage->appendedRows()); } - public function test_aggregates_every_bucket_when_metadata_rows_arrive_in_one_batch(): void + public function test_past_the_limit_the_rest_is_partitioned_and_the_result_is_the_same(): void { $groupBy = new GroupBy(ref('category')); $groupBy->aggregate(sum(ref('amount'))); + $storage = new SpyBucketsStorage(new MemoryBuckets()); - $buckets = new Buckets(new MemoryBuckets()); - $strategy = new HashBucketing( - [ref('category')], - 4, - new NativeHasher(), - new NativePHPRandomValueGenerator(), - 'group-by', + static::assertSame( + ['a' => 30.0, 'b' => 15.0], + GroupedRows::sums(GroupByAggregationProcessorMother::with( + $groupBy, + $storage, + Unit::fromBytes(1), + batchSize: 1, + )->process(GroupedRows::categories(), flow_context())), ); + static::assertNotSame([], $storage->appendedRows()); + static::assertSame([], $storage->liveBucketIds()); + } - $input = (static function (): Generator { - yield array_to_rows( - [ - ['category' => 'a', 'amount' => 10], - ['category' => 'b', 'amount' => 15], - ['category' => 'a', 'amount' => 20], - ], - schema(str_schema('category'), int_schema('amount')), - ); - })(); + /** + * Any batch but the last can be the one that passes the limit: aggregation before it and partitioned aggregation + * after it give the result one in-memory pass gives - many keys, nulls, order-dependent aggregates included. + */ + #[DataProvider('random_datasets')] + public function test_crossing_the_limit_at_any_batch_equals_one_in_memory_pass(int $seed): void + { + mt_srand($seed); + $schema = schema(int_schema('k', nullable: true), int_schema('v')); + $batches = []; + + for ($b = 0, $count = mt_rand(3, 8); $b < $count; $b++) { + $rows = []; - $metadataRows = []; + for ($r = 0, $size = mt_rand(1, 20); $r < $size; $r++) { + $rows[] = ['k' => mt_rand(0, 6) === 0 ? null : mt_rand(0, 40), 'v' => mt_rand(-50, 50)]; + } - foreach ($strategy->bucketize($input, $buckets->storage()) as $bucket) { - $buckets->add($bucket); - $metadataRows[] = $bucket->toRow(); + $batches[] = array_to_rows($rows, $schema); } - $result = iterator_to_array( - (new GroupByAggregationProcessor($groupBy, $buckets))->process( - (static function () use ($metadataRows): Generator { - yield rows(Bucket::schema(), ...$metadataRows); - })(), - flow_context(), - ), - preserve_keys: false, + $crossAfter = mt_rand(0, $count - 2); + $groupBy = new GroupBy(ref('k')); + $groupBy->aggregate( + sum(ref('v')), + count(ref('v')), + min(ref('v')), + max(ref('v')), + first(ref('v')), + last(ref('v')), + collect(ref('v')), ); - $aggregated = []; + $backend = new ReportedMemoryBackend(); + $input = (static function () use ($batches, $crossAfter, $backend): Generator { + foreach ($batches as $position => $batch) { + if ($position === $crossAfter) { + $backend->reported = 1_000_000_000_000; + } - foreach ($result as $batch) { - foreach ($batch->toArray() as $groupRow) { - $aggregated[$groupRow['category']] = $groupRow['amount_sum']; + yield $batch; } - } + })(); + + $storage = new SpyBucketsStorage(new MemoryBuckets()); + $spilled = GroupByAggregationProcessorMother::with( + $groupBy, + $storage, + Unit::fromBytes(memory_get_usage(false) + 500_000_000), + batchSize: 3, + )->process($input, flow_context(config_builder()->backend($backend)->build())); + $inMemory = GroupByAggregationProcessorMother::inMemory($groupBy)->process( + (static fn(): Generator => yield from $batches)(), + flow_context(), + ); - ksort($aggregated); + static::assertSame(serialize(GroupedRows::byKey($inMemory, 'k')), serialize(GroupedRows::byKey($spilled, 'k'))); + static::assertNotSame([], $storage->appendedRows()); + } + + public function test_a_key_aggregated_before_the_limit_is_merged_with_its_rows_after_it(): void + { + $schema = schema(str_schema('k'), int_schema('v')); + $backend = new ReportedMemoryBackend(); + $input = (static function () use ($schema, $backend): Generator { + yield array_to_rows([['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 2]], $schema); + $backend->reported = 1_000_000_000_000; + + yield array_to_rows([['k' => 'a', 'v' => 3], ['k' => 'c', 'v' => 4]], $schema); + yield array_to_rows([['k' => 'a', 'v' => 5]], $schema); + })(); + $groupBy = new GroupBy(ref('k')); + $groupBy->aggregate(first(ref('v')), last(ref('v')), collect(ref('v')), sum(ref('v'))); + $storage = new SpyBucketsStorage(new MemoryBuckets()); - static::assertSame(['a' => 30.0, 'b' => 15.0], $aggregated); + static::assertSame( + [ + 's:1:"a";' => ['k' => 'a', 'v_first' => 1, 'v_last' => 5, 'v_collection' => [1, 3, 5], 'v_sum' => 9.0], + 's:1:"b";' => ['k' => 'b', 'v_first' => 2, 'v_last' => 2, 'v_collection' => [2], 'v_sum' => 2.0], + 's:1:"c";' => ['k' => 'c', 'v_first' => 4, 'v_last' => 4, 'v_collection' => [4], 'v_sum' => 4.0], + ], + GroupedRows::byKey( + GroupByAggregationProcessorMother::with( + $groupBy, + $storage, + Unit::fromBytes(memory_get_usage(false) + 500_000_000), + )->process($input, flow_context(config_builder()->backend($backend)->build())), + 'k', + ), + ); + static::assertNotSame([], $storage->appendedRows()); } public function test_bind_derives_the_group_by_columns_followed_by_the_aggregations(): void @@ -151,7 +184,7 @@ public function test_bind_derives_the_group_by_columns_followed_by_the_aggregati static::assertEquals( schema(str_schema('category'), float_schema('amount_sum', nullable: true)), - (new GroupByAggregationProcessor($groupBy, new Buckets(new MemoryBuckets())))->bind(schema( + GroupByAggregationProcessorMother::inMemory($groupBy)->bind(schema( str_schema('category'), int_schema('amount'), str_schema('dropped'), @@ -166,52 +199,7 @@ public function test_bind_refuses_a_group_by_column_missing_from_the_input(): vo $this->expectException(SchemaDefinitionNotFoundException::class); - (new GroupByAggregationProcessor($groupBy, new Buckets(new MemoryBuckets())))->bind(schema(int_schema( - 'amount', - ))); - } - - public function test_clears_storage_after_the_last_bucket(): void - { - $groupBy = new GroupBy(ref('category')); - $groupBy->aggregate(sum(ref('amount'))); - - $storage = new SpyBucketsStorage(new MemoryBuckets()); - $buckets = new Buckets($storage); - $strategy = new HashBucketing( - [ref('category')], - 4, - new NativeHasher(), - new NativePHPRandomValueGenerator(), - 'group-by', - ); - - $input = (static function (): Generator { - yield array_to_rows( - [['category' => 'a', 'amount' => 10], ['category' => 'b', 'amount' => 15]], - schema(str_schema('category'), int_schema('amount')), - ); - })(); - - $metadata = []; - - foreach ($strategy->bucketize($input, $buckets->storage()) as $bucket) { - $buckets->add($bucket); - $metadata[] = rows(Bucket::schema(), $bucket->toRow()); - } - - iterator_to_array( - (new GroupByAggregationProcessor($groupBy, $buckets))->process( - (static function () use ($metadata): Generator { - yield from $metadata; - })(), - flow_context(), - ), - preserve_keys: false, - ); - - static::assertNotSame([], $storage->readBucketIds()); - static::assertSame([], $storage->liveBucketIds()); + GroupByAggregationProcessorMother::inMemory($groupBy)->bind(schema(int_schema('amount'))); } public function test_throws_when_batch_size_below_one(): void @@ -220,25 +208,30 @@ public function test_throws_when_batch_size_below_one(): void $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); // @mago-ignore analysis:invalid-argument - new GroupByAggregationProcessor(new GroupBy(ref('category')), new Buckets(new MemoryBuckets()), 0); + GroupByAggregationProcessorMother::with( + new GroupBy(ref('category')), + new MemoryBuckets(), + Unit::fromGb(1), + 4, + 0, + ); } - public function test_handles_an_empty_metadata_stream(): void + public function test_handles_an_empty_stream(): void { $groupBy = new GroupBy(ref('category')); $groupBy->aggregate(sum(ref('amount'))); - $result = iterator_to_array( - (new GroupByAggregationProcessor($groupBy, new Buckets(new MemoryBuckets())))->process( - (static function (): Generator { - yield from []; - })(), - flow_context(), + static::assertSame( + [], + iterator_to_array( + GroupByAggregationProcessorMother::inMemory($groupBy)->process( + (static fn(): Generator => yield from [])(), + flow_context(), + ), + false, ), - preserve_keys: false, ); - - static::assertSame([], $result); } public function test_a_bound_global_aggregate_over_an_empty_stream_emits_one_row_of_defaults(): void @@ -246,20 +239,13 @@ public function test_a_bound_global_aggregate_over_an_empty_stream_emits_one_row $groupBy = new GroupBy(); $groupBy->aggregate(sum(ref('amount')), count(ref('amount'))); - $bound = (new GroupByAggregationProcessor($groupBy, new Buckets(new MemoryBuckets())))->bind(schema(int_schema( - 'amount', - ))); + $bound = GroupByAggregationProcessorMother::inMemory($groupBy)->bind(schema(int_schema('amount'))); static::assertInstanceOf(GroupByAggregationProcessor::class, $bound->step); $result = iterator_to_array( - $bound->step->process( - (static function (): Generator { - yield from []; - })(), - flow_context(), - ), - preserve_keys: false, + $bound->step->process((static fn(): Generator => yield from [])(), flow_context()), + false, ); static::assertCount(1, $result); @@ -272,7 +258,7 @@ public function test_a_bound_keyed_aggregate_over_an_empty_stream_emits_nothing( $groupBy = new GroupBy(ref('category')); $groupBy->aggregate(sum(ref('amount'))); - $bound = (new GroupByAggregationProcessor($groupBy, new Buckets(new MemoryBuckets())))->bind(schema( + $bound = GroupByAggregationProcessorMother::inMemory($groupBy)->bind(schema( str_schema('category'), int_schema('amount'), )); @@ -282,13 +268,8 @@ public function test_a_bound_keyed_aggregate_over_an_empty_stream_emits_nothing( static::assertSame( [], iterator_to_array( - $bound->step->process( - (static function (): Generator { - yield from []; - })(), - flow_context(), - ), - preserve_keys: false, + $bound->step->process((static fn(): Generator => yield from [])(), flow_context()), + false, ), ); } @@ -301,13 +282,11 @@ public function test_an_unbound_global_aggregate_over_an_empty_stream_emits_noth static::assertSame( [], iterator_to_array( - (new GroupByAggregationProcessor($groupBy, new Buckets(new MemoryBuckets())))->process( - (static function (): Generator { - yield from []; - })(), + GroupByAggregationProcessorMother::inMemory($groupBy)->process( + (static fn(): Generator => yield from [])(), flow_context(), ), - preserve_keys: false, + false, ), ); } @@ -317,24 +296,19 @@ public function test_a_bound_global_aggregate_with_input_emits_no_extra_row(): v $groupBy = new GroupBy(); $groupBy->aggregate(sum(ref('amount')), count(ref('amount'))); - $buckets = new Buckets(new MemoryBuckets()); - $metadata = GroupByContext::bucketMetadata($buckets, [], array_to_rows([ - ['amount' => 10], - ['amount' => 20], - ], schema(int_schema('amount')))); - - $bound = (new GroupByAggregationProcessor($groupBy, $buckets))->bind(schema(int_schema('amount'))); + $bound = GroupByAggregationProcessorMother::inMemory($groupBy)->bind(schema(int_schema('amount'))); static::assertInstanceOf(GroupByAggregationProcessor::class, $bound->step); $result = iterator_to_array( $bound->step->process( - (static function () use ($metadata): Generator { - yield from $metadata; - })(), + (static fn(): Generator => yield array_to_rows([ + ['amount' => 10], + ['amount' => 20], + ], schema(int_schema('amount'))))(), flow_context(), ), - preserve_keys: false, + false, ); static::assertCount(1, $result); @@ -346,35 +320,13 @@ public function test_output_builds_with_the_configured_backend(): void $backend = new SpyBackend(); $groupBy = new GroupBy(ref('category')); $groupBy->aggregate(sum(ref('amount'))); - $buckets = new Buckets(new MemoryBuckets()); - $strategy = new HashBucketing( - [ref('category')], - 2, - new NativeHasher(), - new NativePHPRandomValueGenerator(), - 'group-by', - ); - $input = (static function (): Generator { - yield array_to_rows( - [['category' => 'a', 'amount' => 10], ['category' => 'b', 'amount' => 15]], - schema(str_schema('category'), int_schema('amount')), - ); - })(); - $metadata = []; - - foreach ($strategy->bucketize($input, $buckets->storage()) as $bucket) { - $buckets->add($bucket); - $metadata[] = rows(Bucket::schema(), $bucket->toRow()); - } iterator_to_array( - (new GroupByAggregationProcessor($groupBy, $buckets))->process( - (static function () use ($metadata): Generator { - yield from $metadata; - })(), + GroupByAggregationProcessorMother::inMemory($groupBy)->process( + GroupedRows::categories(), flow_context(config_builder()->backend($backend)->build()), ), - preserve_keys: false, + false, ); static::assertGreaterThan(0, $backend->builders()); 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 1f2a72c1bd..23829a8c54 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 @@ -5,6 +5,7 @@ namespace Flow\ETL\Tests\Unit\Processor; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\JoinException; use Flow\ETL\Extractor\Signal; use Flow\ETL\Join\Comparison\Any; @@ -155,6 +156,70 @@ public function test_grace_and_resident_storages_produce_the_same_rows(): void static::assertSame($results[0], $results[1]); } + public function test_a_build_side_under_the_memory_limit_joins_in_memory_without_bucket_writes(): void + { + $storage = new SpyBucketsStorage(new MemoryBuckets()); + $processor = HashJoinProcessorMother::with( + PhysicalPlanMother::reading(from_rows(array_to_rows( + [['user_id' => 1, 'name' => 'Alice'], ['user_id' => 2, 'name' => 'Bob']], + schema(int_schema('user_id'), str_schema('name')), + ))), + Expression::on(['id' => 'user_id']), + Join::left, + $storage, + memoryLimit: Unit::fromGb(64), + ); + $generator = (static function () { + yield array_to_rows( + [['id' => 2, 'amount' => 20], ['id' => 404, 'amount' => 40]], + schema(int_schema('id'), int_schema('amount')), + ); + })(); + + static::assertSame( + [ + ['id' => 2, 'amount' => 20, 'user_id' => 2, 'name' => 'Bob'], + ['id' => 404, 'amount' => 40, 'user_id' => null, 'name' => null], + ], + iterator_to_array($processor->process($generator, flow_context()), false)[0]->toArray(), + ); + static::assertSame([], $storage->appendedRows()); + } + + public function test_a_build_side_past_the_memory_limit_spills_what_it_read_and_the_rest(): void + { + $storage = new SpyBucketsStorage(new MemoryBuckets()); + $processor = HashJoinProcessorMother::with( + PhysicalPlanMother::reading(from_rows( + array_to_rows([['user_id' => 1, 'name' => 'Alice']], schema(int_schema('user_id'), str_schema('name'))), + array_to_rows([['user_id' => 2, 'name' => 'Bob']], schema(int_schema('user_id'), str_schema('name'))), + )), + Expression::on(['id' => 'user_id']), + Join::inner, + $storage, + memoryLimit: Unit::fromBytes(1), + ); + $generator = (static function () { + yield array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); + })(); + + $joined = []; + + foreach ($processor->process($generator, flow_context()) as $batch) { + foreach ($batch->toArray() as $row) { + $joined[] = $row; + } + } + + usort($joined, static fn(array $left, array $right): int => (int) $left['id'] <=> (int) $right['id']); + + static::assertSame( + [['id' => 1, 'user_id' => 1, 'name' => 'Alice'], ['id' => 2, 'user_id' => 2, 'name' => 'Bob']], + $joined, + ); + static::assertNotSame([], $storage->appendedRows()); + } + public function test_handles_empty_left_side(): void { $processor = HashJoinProcessorMother::grace( @@ -578,8 +643,9 @@ public function test_pairs_with_a_missing_right_side_read_only_left_buckets(): v { $storage = new SpyBucketsStorage(new MemoryBuckets()); + // the right side's only key hashes to a bucket no left row lands in, so no pair has a right bucket $processor = HashJoinProcessorMother::grace( - PhysicalPlanMother::reading(from_rows(rows(schema()))), + PhysicalPlanMother::reading(from_rows(array_to_rows([['user_id' => 3]], schema(int_schema('user_id'))))), Expression::on(['id' => 'user_id']), Join::left, $storage, @@ -659,7 +725,7 @@ public function test_the_right_side_is_pulled_through_a_frame_output(): void static::assertSame([['id' => 1, 'r_id' => 1, 'r_name' => 'Alice']], $batches[0]->toArray()); } - public function test_join_output_builds_with_the_configured_backend(): void + public function test_join_output_gathers_the_input_columns_without_building(): void { $backend = new SpyBackend(); $processor = HashJoinProcessorMother::grace( @@ -674,11 +740,12 @@ public function test_join_output_builds_with_the_configured_backend(): void yield array_to_rows([['id' => 1, 'amount' => 100]], schema(int_schema('id'), int_schema('amount'))); })(); - iterator_to_array( + $joined = iterator_to_array( $processor->process($generator, flow_context(config_builder()->backend($backend)->build())), false, ); - static::assertGreaterThan(0, $backend->builders()); + static::assertSame([['id' => 1, 'amount' => 100, 'user_id' => 1, 'name' => 'Alice']], $joined[0]->toArray()); + static::assertSame(0, $backend->builders()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php index c1f91e6c85..fa07cde75a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/MergeSortProcessorTest.php @@ -4,327 +4,56 @@ namespace Flow\ETL\Tests\Unit\Processor; -use Flow\ETL\Bucketing\Bucket; -use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\SortedRunBucketing; use Flow\ETL\Bucketing\Storage\MemoryBuckets; -use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\NativePHPRandomValueGenerator; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\MergeSortProcessor; use Flow\ETL\Rows; -use Flow\ETL\Tests\Double\SpyBackend; -use Flow\ETL\Tests\Double\SpyBucketsStorage; -use Flow\ETL\Tests\Double\ThrowingRemoveBucketsStorage; +use Flow\ETL\Tests\Double\RecordingBucketsStorage; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\ExternalSortMother; use Generator; use function array_map; use function array_merge; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; -use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; use function Flow\ETL\DSL\schema; use function iterator_to_array; -use function range; final class MergeSortProcessorTest extends FlowTestCase { public function test_bind_returns_the_input_schema(): void { - $storage = new MemoryBuckets(); $input = schema(int_schema('id')); - $processor = new MergeSortProcessor( - refs(ref('id')), - new Buckets($storage), - new Buckets($storage), - new NativePHPRandomValueGenerator(), - ); - - static::assertEquals($input, $processor->bind($input)->output); - } - - public function test_descending_single_column(): void - { - $storage = new SpyBucketsStorage(new MemoryBuckets()); - $buckets = new Buckets($storage); - $context = flow_context(config()); - - $bucketing = new BucketingProcessor( - new SortedRunBucketing([ref('id')->desc()], 2, new NativePHPRandomValueGenerator()), - $buckets, - ); - $merge = new MergeSortProcessor( - refs(ref('id')->desc()), - $buckets, - new Buckets($storage), - new NativePHPRandomValueGenerator(), - 10, - 1000, - ); - - $input = (static function () { - yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 4], ['id' => 2]], schema(int_schema('id'))); - })(); - $result = iterator_to_array($merge->process($bucketing->process($input, $context), $context), false); - - static::assertSame( - [4, 3, 2, 1], - array_merge(...array_map(static fn(Rows $r): array => $r->reduceToArray('id'), $result)), + static::assertEquals( + $input, + (new MergeSortProcessor(ExternalSortMother::inMemory(refs('id'))))->bind($input)->output, ); - static::assertSame([], $storage->liveBucketIds()); } - public function test_empty_input_yields_nothing_and_leaves_storage_empty(): void + public function test_process_sorts_through_the_external_sort(): void { - $storage = new SpyBucketsStorage(new MemoryBuckets()); - $buckets = new Buckets($storage); - $context = flow_context(config()); - - $bucketing = new BucketingProcessor( - new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()), - $buckets, - ); - $merge = new MergeSortProcessor( - refs('id'), - $buckets, - new Buckets($storage), - new NativePHPRandomValueGenerator(), - 10, - 1000, - ); - - $input = (static function () { - yield from []; + $storage = new RecordingBucketsStorage(new MemoryBuckets()); + $input = (static function (): Generator { + yield array_to_rows([['id' => 3], ['id' => 1]], schema(int_schema('id'))); + yield array_to_rows([['id' => 2]], schema(int_schema('id'))); })(); - static::assertCount(0, iterator_to_array( - $merge->process($bucketing->process($input, $context), $context), + $result = iterator_to_array( + (new MergeSortProcessor(ExternalSortMother::spilling(refs('id'), $storage)))->process( + $input, + flow_context(config()), + ), false, - )); - static::assertSame([], $storage->liveBucketIds()); - } - - public function test_heap_merges_overlapping_runs_without_reduction(): void - { - $storage = new SpyBucketsStorage(new MemoryBuckets()); - $buckets = new Buckets($storage); - $context = flow_context(config()); - - $bucketing = new BucketingProcessor( - new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()), - $buckets, ); - $merge = new MergeSortProcessor( - refs('id'), - $buckets, - new Buckets($storage), - new NativePHPRandomValueGenerator(), - 10, - 1000, - ); - - $input = (static function () { - yield array_to_rows(array_map(static fn(int $i): array => ['id' => $i], [ - 0, - 10, - 1, - 11, - 2, - 12, - 3, - 13, - ]), schema(int_schema('id'))); - })(); - - $result = iterator_to_array($merge->process($bucketing->process($input, $context), $context), false); - - static::assertSame( - [0, 1, 2, 3, 10, 11, 12, 13], - array_merge(...array_map(static fn(Rows $r): array => $r->reduceToArray('id'), $result)), - ); - static::assertSame([], $storage->liveBucketIds()); - } - - public function test_sorts_by_multiple_columns(): void - { - $storage = new SpyBucketsStorage(new MemoryBuckets()); - $buckets = new Buckets($storage); - $context = flow_context(config()); - - $bucketing = new BucketingProcessor( - new SortedRunBucketing([ref('a'), ref('b')], 2, new NativePHPRandomValueGenerator()), - $buckets, - ); - $merge = new MergeSortProcessor( - refs('a', 'b'), - $buckets, - new Buckets($storage), - new NativePHPRandomValueGenerator(), - 10, - 1000, - ); - - $input = (static function () { - yield array_to_rows( - [['a' => 1, 'b' => 2], ['a' => 1, 'b' => 1], ['a' => 0, 'b' => 5], ['a' => 0, 'b' => 3]], - schema(int_schema('a'), int_schema('b')), - ); - })(); - - $result = iterator_to_array($merge->process($bucketing->process($input, $context), $context), false); static::assertSame( - [ - ['a' => 0, 'b' => 3], - ['a' => 0, 'b' => 5], - ['a' => 1, 'b' => 1], - ['a' => 1, 'b' => 2], - ], - array_merge(...array_map(static fn(Rows $r): array => $r->toArray(), $result)), + [1, 2, 3], + array_merge(...array_map(static fn(Rows $rows): array => $rows->reduceToArray('id'), $result)), ); - static::assertSame([], $storage->liveBucketIds()); - } - - public function test_multi_pass_reduction_produces_sorted_output(): void - { - $storage = new SpyBucketsStorage(new MemoryBuckets()); - $buckets = new Buckets($storage); - $context = flow_context(config()); - - $bucketing = new BucketingProcessor( - new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()), - $buckets, - ); - $merge = new MergeSortProcessor( - refs('id'), - $buckets, - new Buckets($storage), - new NativePHPRandomValueGenerator(), - 2, - 1000, - ); - - $input = (static function () { - yield array_to_rows( - array_map(static fn(int $i): array => ['id' => $i], range(19, 0)), - schema(int_schema('id')), - ); - })(); - - $result = iterator_to_array($merge->process($bucketing->process($input, $context), $context), false); - - static::assertSame( - range(0, 19), - array_merge(...array_map(static fn(Rows $r): array => $r->reduceToArray('id'), $result)), - ); - static::assertSame([], $storage->liveBucketIds()); - } - - public function test_both_storages_are_cleared_when_the_first_clear_throws(): void - { - $spillStorage = new SpyBucketsStorage(new MemoryBuckets()); - $mergeStorage = new SpyBucketsStorage(new MemoryBuckets()); - $spill = new Buckets(new ThrowingRemoveBucketsStorage($spillStorage)); - $merge = new Buckets($mergeStorage); - $context = flow_context(config()); - - // the upstream throws during the drain, so reduce() never writes a merged run - seed one, or the - // merge-side assertion is true whether or not the nested finally ran - $mergeStorage->append('pre-existing', array_to_rows([['id' => 1]], schema(int_schema('id')))); - $merge->add(new Bucket('pre-existing', 1, 0)); - - $bucketing = new BucketingProcessor( - new SortedRunBucketing([ref('id')], 2, new NativePHPRandomValueGenerator()), - $spill, - ); - $processor = new MergeSortProcessor(refs('id'), $spill, $merge, new NativePHPRandomValueGenerator(), 2, 1000); - - $upstream = (static function (): Generator { - yield array_to_rows( - array_map(static fn(int $i): array => ['id' => $i], range(9, 0)), - schema(int_schema('id')), - ); - - throw new RuntimeException('upstream failed'); - })(); - - try { - iterator_to_array($processor->process($bucketing->process($upstream, $context), $context), false); - static::fail('The upstream failure must escape.'); - } catch (RuntimeException $escaped) { - static::assertSame('spill clear failed', $escaped->getMessage()); - - $previous = $escaped->getPrevious(); - - static::assertInstanceOf(RuntimeException::class, $previous); - static::assertSame('upstream failed', $previous->getMessage()); - } - - // the nested finally runs the merge clear even though the spill clear threw - static::assertSame([], $mergeStorage->liveBucketIds()); - } - - public function test_throws_when_batch_size_below_one(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); - - // @mago-ignore analysis:invalid-argument - new MergeSortProcessor( - refs('id'), - new Buckets(new MemoryBuckets()), - new Buckets(new MemoryBuckets()), - new NativePHPRandomValueGenerator(), - 10, - 0, - ); - } - - public function test_throws_when_merge_fan_in_below_one(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Merge fan-in must be greater than 0, given: 0'); - - // @mago-ignore analysis:invalid-argument - new MergeSortProcessor( - refs('id'), - new Buckets(new MemoryBuckets()), - new Buckets(new MemoryBuckets()), - new NativePHPRandomValueGenerator(), - 0, - 1000, - ); - } - - public function test_merge_builds_with_the_configured_backend(): void - { - $backend = new SpyBackend(); - $storage = new MemoryBuckets(); - $buckets = new Buckets($storage); - $context = flow_context(config_builder()->backend($backend)->build()); - $bucketing = new BucketingProcessor( - new SortedRunBucketing([ref('id')->asc()], 2, new NativePHPRandomValueGenerator()), - $buckets, - ); - $merge = new MergeSortProcessor( - refs(ref('id')->asc()), - $buckets, - new Buckets($storage), - new NativePHPRandomValueGenerator(), - ); - $input = (static function () { - yield array_to_rows([['id' => 3], ['id' => 1], ['id' => 2]], schema(int_schema('id'))); - })(); - - iterator_to_array($merge->process($bucketing->process($input, $context), $context), false); - - static::assertGreaterThan(0, $backend->builders()); + static::assertNotSame([], $storage->appended); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/RepartitionProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/RepartitionProcessorTest.php index 00acb474f9..a0313581c0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/RepartitionProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/RepartitionProcessorTest.php @@ -4,127 +4,152 @@ namespace Flow\ETL\Tests\Unit\Processor; -use Flow\ETL\Bucketing\Bucket; -use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\HashBucketing; -use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\Storage\MemoryBuckets; -use Flow\ETL\NativePHPRandomValueGenerator; -use Flow\ETL\Processor\RepartitionProcessor; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Rows; +use Flow\ETL\Tests\Context\GroupedRows; +use Flow\ETL\Tests\Double\ReportedMemoryBackend; +use Flow\ETL\Tests\Double\SpyBucketsStorage; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\RepartitionProcessorMother; use Generator; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\TestWith; use function array_map; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; -use function usort; +use function memory_get_usage; +use function mt_rand; +use function mt_srand; +use function sort; final class RepartitionProcessorTest extends FlowTestCase { + public static function random_datasets(): Generator + { + for ($seed = 1; $seed <= 50; $seed++) { + yield "seed {$seed}" => [$seed]; + } + } + public function test_bind_returns_the_input_schema(): void { $input = schema(str_schema('k'), int_schema('v')); - $processor = new RepartitionProcessor(refs(ref('k')), new Buckets(new MemoryBuckets())); - static::assertEquals($input, $processor->bind($input)->output); + static::assertEquals($input, RepartitionProcessorMother::inMemory(refs(ref('k')))->bind($input)->output); + } + + public function test_under_the_limit_it_groups_in_one_pass_without_touching_the_buckets(): void + { + $storage = new SpyBucketsStorage(new MemoryBuckets()); + $schema = schema(str_schema('k'), int_schema('v')); + + $groups = iterator_to_array( + RepartitionProcessorMother::inMemory(refs(ref('k')), $storage)->process( + (static function () use ($schema): Generator { + yield array_to_rows([['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 2]], $schema); + yield array_to_rows([['k' => 'a', 'v' => 3], ['k' => 'b', 'v' => 4]], $schema); + })(), + flow_context(), + ), + false, + ); + + static::assertSame( + [[1, 3], [2, 4]], + array_map(static fn(Rows $group): array => $group->reduceToArray('v'), $groups), + ); + static::assertSame([], $storage->appendedRows()); } /** - * One bucket proves the grouping is the processor's own work; 64 proves a key is never split + * Past the limit: one bucket proves the grouping is the processor's own work; 64 prove a key is never split * across buckets, which is what makes the downstream window contiguous. * * @param int<1, max> $bucketsCount */ #[TestWith([1])] #[TestWith([64])] - public function test_every_row_sharing_a_key_arrives_in_one_batch(int $bucketsCount): void + public function test_past_the_limit_every_row_sharing_a_key_still_arrives_in_one_batch(int $bucketsCount): void { + $storage = new SpyBucketsStorage(new MemoryBuckets()); $schema = schema(str_schema('k'), int_schema('v')); - $buckets = new Buckets(new MemoryBuckets()); - $strategy = new HashBucketing( - [ref('k')], - $bucketsCount, - new NativeHasher(), - new NativePHPRandomValueGenerator(), - 'repartition', - ); - - $input = (static function () use ($schema): Generator { - yield array_to_rows([['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 2]], $schema); - yield array_to_rows([['k' => 'a', 'v' => 3], ['k' => 'b', 'v' => 4]], $schema); - })(); - - $metadata = []; - - foreach ($strategy->bucketize($input, $buckets->storage()) as $bucket) { - $buckets->add($bucket); - $metadata[] = rows(Bucket::schema(), $bucket->toRow()); - } $groups = array_map( - static fn(Rows $group): array => array_map( - static fn(array $values): int => (int) $values['v'], - $group->toArray(), - ), + static fn(Rows $group): array => $group->reduceToArray('v'), iterator_to_array( - (new RepartitionProcessor(refs(ref('k')), $buckets))->process( - (static function () use ($metadata): Generator { - yield from $metadata; + RepartitionProcessorMother::with(refs(ref('k')), $storage, Unit::fromBytes(1), $bucketsCount)->process( + (static function () use ($schema): Generator { + yield array_to_rows([['k' => 'a', 'v' => 1], ['k' => 'b', 'v' => 2]], $schema); + yield array_to_rows([['k' => 'a', 'v' => 3], ['k' => 'b', 'v' => 4]], $schema); })(), flow_context(), ), - preserve_keys: false, + false, ), ); - - usort($groups, static fn(array $a, array $b): int => $a[0] <=> $b[0]); + sort($groups); static::assertSame([[1, 3], [2, 4]], $groups); + static::assertNotSame([], $storage->appendedRows()); + static::assertSame([], $storage->liveBucketIds()); } - public function test_buckets_are_cleared_when_the_stream_is_done(): void + #[DataProvider('random_datasets')] + public function test_crossing_the_limit_at_any_batch_gives_the_groups_one_in_memory_pass_gives(int $seed): void { - $schema = schema(str_schema('k'), int_schema('v')); - $buckets = new Buckets(new MemoryBuckets()); - $strategy = new HashBucketing( - [ref('k')], - 4, - new NativeHasher(), - new NativePHPRandomValueGenerator(), - 'repartition', - ); + mt_srand($seed); + $schema = schema(int_schema('k', nullable: true), int_schema('v')); + $batches = []; + $id = 0; - $metadata = []; + for ($b = 0, $count = mt_rand(1, 8); $b < $count; $b++) { + $rows = []; - foreach ($strategy->bucketize( - (static function () use ($schema): Generator { - yield array_to_rows([['k' => 'a', 'v' => 1]], $schema); - })(), - $buckets->storage(), - ) as $bucket) { - $buckets->add($bucket); - $metadata[] = rows(Bucket::schema(), $bucket->toRow()); + for ($r = 0, $size = mt_rand(1, 20); $r < $size; $r++) { + $rows[] = ['k' => mt_rand(0, 6) === 0 ? null : mt_rand(0, 40), 'v' => $id++]; + } + + $batches[] = array_to_rows($rows, $schema); } - iterator_to_array( - (new RepartitionProcessor(refs(ref('k')), $buckets))->process( - (static function () use ($metadata): Generator { - yield from $metadata; - })(), + $crossAt = mt_rand(0, $count); + $backend = new ReportedMemoryBackend(); + $input = (static function () use ($batches, $crossAt, $backend): Generator { + foreach ($batches as $position => $batch) { + if ($position === $crossAt) { + $backend->reported = 1_000_000_000_000; + } + + yield $batch; + } + })(); + + $storage = new SpyBucketsStorage(new MemoryBuckets()); + + static::assertSame( + GroupedRows::batchesAsSet(RepartitionProcessorMother::inMemory(refs(ref('k')))->process( + (static fn(): Generator => yield from $batches)(), flow_context(), - ), - preserve_keys: false, + )), + GroupedRows::batchesAsSet(RepartitionProcessorMother::with( + refs(ref('k')), + $storage, + Unit::fromBytes(memory_get_usage(false) + 500_000_000), + )->process($input, flow_context(config_builder()->backend($backend)->build()))), ); - static::assertSame([], $buckets->all()); + // the batch at $crossAt is read past the limit: it and every later batch are partitioned + if ($crossAt < $count) { + static::assertNotSame([], $storage->appendedRows()); + } } } 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 index b8f98755d5..787c4af8fd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/TopNProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/TopNProcessorTest.php @@ -4,23 +4,128 @@ namespace Flow\ETL\Tests\Unit\Processor; +use Flow\ETL\Bucketing\Storage\MemoryBuckets; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Processor\MemorySortProcessor; use Flow\ETL\Processor\TopNProcessor; use Flow\ETL\Tests\Context\ScoredRows; +use Flow\ETL\Tests\Double\RecordingBucketsStorage; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\ExternalSortMother; +use Flow\ETL\Tests\Mother\SortDatasetMother; use Generator; +use PHPUnit\Framework\Attributes\DataProvider; +use function array_merge; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; +use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function iterator_to_array; +use function serialize; final class TopNProcessorTest extends FlowTestCase { + public static function random_datasets(): Generator + { + for ($seed = 1; $seed <= 200; $seed++) { + yield "seed {$seed}" => [$seed]; + } + } + + public function test_under_the_memory_limit_it_trims_in_memory_with_zero_spills(): void + { + $storage = new RecordingBucketsStorage(new MemoryBuckets()); + $refs = refs(ref('score')); + + $top = ScoredRows::merged((new TopNProcessor($refs, 2, ExternalSortMother::inMemory($refs, $storage)))->process( + ScoredRows::batches([[3, 'c'], [1, 'a']], [[2, 'b'], [0, 'z']]), + flow_context(), + )); + + static::assertSame([['score' => 0, 'name' => 'z'], ['score' => 1, 'name' => 'a']], $top); + static::assertSame([], $storage->appended); + } + + public function test_past_the_memory_limit_it_falls_back_to_the_spilling_sort(): void + { + $storage = new RecordingBucketsStorage(new MemoryBuckets()); + $refs = refs(ref('score')); + + $top = ScoredRows::merged((new TopNProcessor($refs, 2, ExternalSortMother::spilling($refs, $storage)))->process( + ScoredRows::batches([[3, 'c'], [1, 'a']], [[2, 'b'], [0, 'z']], [[1, 'y']]), + flow_context(), + )); + + static::assertSame([['score' => 0, 'name' => 'z'], ['score' => 1, 'name' => 'a']], $top); + static::assertNotSame([], $storage->appended); + } + + public function test_a_fallback_on_the_last_batch_emits_the_kept_rows(): void + { + $refs = refs(ref('score')); + + static::assertSame( + [['score' => 1, 'name' => 'a']], + ScoredRows::merged((new TopNProcessor($refs, 1, ExternalSortMother::spilling($refs)))->process( + ScoredRows::batches([[3, 'c'], [1, 'a']]), + flow_context(), + )), + ); + } + + #[DataProvider('random_datasets')] + public function test_the_fallback_equals_a_sort_followed_by_a_limit(int $seed): void + { + $dataset = SortDatasetMother::random($seed); + $limit = ($seed % 7) + 1; + $refs = refs(...$dataset['references']); + $input = (static function () use ($dataset): Generator { + foreach ($dataset['runs'] as $rows) { + yield array_to_rows($rows, $dataset['schema']); + } + })(); + + $top = rows($dataset['schema']); + $storage = new RecordingBucketsStorage(new MemoryBuckets()); + + foreach ((new TopNProcessor( + $refs, + $limit, + ExternalSortMother::spilling($refs, $storage, mergeFanIn: 2), + ))->process($input, flow_context()) as $batch) { + $top = $top->concat($batch->matchTo($dataset['schema'])); + } + + // serialized, so NaN and -0.0 compare by what they are + static::assertSame( + serialize( + array_to_rows(array_merge(...$dataset['runs']), $dataset['schema']) + ->sortBy(...$dataset['references']) + ->take($limit) + ->toArray(), + ), + serialize($top->toArray()), + ); + + if (array_merge(...$dataset['runs']) !== []) { + static::assertNotSame([], $storage->appended, 'the fallback must have spilled'); + } + } + + public function test_bind_keeps_the_fallback(): void + { + $fallback = ExternalSortMother::inMemory(refs(ref('score'))); + $bound = (new TopNProcessor(refs(ref('score')), 3, $fallback))->bind(schema(int_schema('score')))->step; + + static::assertInstanceOf(TopNProcessor::class, $bound); + static::assertSame($fallback, $bound->fallback); + } + public function test_it_emits_exactly_what_a_sort_followed_by_a_limit_emits(): void { $refs = refs(ref('score')->desc(), ref('name')); @@ -97,4 +202,27 @@ public function test_a_limit_below_one_is_refused(): void new TopNProcessor(refs(ref('score')), 0); } + + public function test_top_sorts_and_keeps_the_limit(): void + { + static::assertSame( + [['score' => 9, 'name' => 'a'], ['score' => 7, 'name' => 'b']], + (new TopNProcessor(refs(ref('score')->desc()), 2))->top(array_to_rows( + [['score' => 3, 'name' => 'c'], ['score' => 9, 'name' => 'a'], ['score' => 7, 'name' => 'b']], + schema(int_schema('score'), str_schema('name')), + ))->toArray(), + ); + } + + public function test_batches_are_conformed_to_the_declared_schema(): void + { + $declared = schema(int_schema('score', nullable: true), str_schema('name')); + $bound = (new TopNProcessor(refs(ref('score')), 5))->bind($declared)->step; + static::assertInstanceOf(TopNProcessor::class, $bound); + + $out = iterator_to_array($bound->process(ScoredRows::batches([[2, 'b'], [1, 'a']]), flow_context()), false); + + static::assertEquals($declared, $out[0]->schema()); + static::assertSame([['score' => 1, 'name' => 'a'], ['score' => 2, 'name' => 'b']], $out[0]->toArray()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/WindowProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/WindowProcessorTest.php index 18376822cd..cf0f85cd0e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/WindowProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/WindowProcessorTest.php @@ -12,6 +12,7 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\Context\WindowProcessorContext; use Flow\ETL\Tests\Double\CountingFrameAccumulating; +use Flow\ETL\Tests\Double\WindowFunctionOverOperand; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\ListColumnsMother; use Generator; @@ -186,8 +187,8 @@ public function test_definition_entry_keeps_its_type_and_metadata(): void static::assertCount(1, $batches); static::assertEquals(int_schema('total')->addMetadata('origin', 'window'), $batches[0]->schema()->get('total')); - foreach ($batches[0] as $row) { - static::assertSame(100, $row->get('total')); + foreach ($batches[0]->toArray() as $row) { + static::assertSame(100, $row['total']); } } @@ -403,8 +404,8 @@ public function test_a_running_sum_over_mixed_numerics_yields_one_definition(): foreach ($batches as $batch) { $definitions[] = $batch->schema()->get('total'); - foreach ($batch as $row) { - $values[] = $row->get('total'); + foreach ($batch->toArray() as $row) { + $values[] = $row['total']; } } @@ -461,8 +462,8 @@ public function test_a_leading_empty_batch_is_yielded_under_the_bound_schema(): $batches = iterator_to_array($processor->process($generator, flow_context()), preserve_keys: false); $values = []; - foreach ($batches[1] as $row) { - $values[] = $row->get('row_number'); + foreach ($batches[1]->toArray() as $row) { + $values[] = $row['row_number']; } static::assertCount(2, $batches); @@ -480,7 +481,9 @@ public function test_bind_refuses_an_expand_in_the_window_function(): void (new WindowProcessor( 's', - sum(ref('n'), ref('flags')->expand()->equals(lit(true)))->over(window()->partitionBy(ref('n'))), + (new WindowFunctionOverOperand(ref('flags')->expand()->equals(lit(true))))->over(window()->partitionBy(ref( + 'n', + ))), ))->bind(ListColumnsMother::numberAndFlagsSchema()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Repartition/RepartitionStepsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Repartition/RepartitionStepsTest.php index bfbbab6b55..30d65a0a51 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Repartition/RepartitionStepsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Repartition/RepartitionStepsTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Tests\Unit\Repartition; use Flow\ETL\Bucketing\Storage\MemoryBuckets; -use Flow\ETL\Processor\BucketingProcessor; use Flow\ETL\Processor\RepartitionProcessor; use Flow\ETL\Repartition\RepartitionSteps; use Flow\ETL\Tests\FlowTestCase; @@ -25,9 +24,8 @@ public function test_an_algorithm_builder_pins_the_algorithm_for_this_operation( hash_repartition()->storage(new MemoryBuckets())->bucketsCount(8), ); - static::assertCount(2, $steps); - static::assertInstanceOf(BucketingProcessor::class, $steps[0]); - static::assertInstanceOf(RepartitionProcessor::class, $steps[1]); + static::assertCount(1, $steps); + static::assertInstanceOf(RepartitionProcessor::class, $steps[0]); } public function test_config_supplies_the_algorithm_when_none_is_pinned(): void @@ -37,8 +35,7 @@ public function test_config_supplies_the_algorithm_when_none_is_pinned(): void config_builder()->repartition(hash_repartition()->storage(new MemoryBuckets()))->build(), ); - static::assertCount(2, $steps); - static::assertInstanceOf(BucketingProcessor::class, $steps[0]); - static::assertInstanceOf(RepartitionProcessor::class, $steps[1]); + static::assertCount(1, $steps); + static::assertInstanceOf(RepartitionProcessor::class, $steps[0]); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php deleted file mode 100644 index 88583bea0e..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/ArrayToRowTest.php +++ /dev/null @@ -1,108 +0,0 @@ - ['a', 'b', 'c', 'd']], - schema(list_schema('data', type_list(type_string()))), - flow_context(config())->backend(), - ); - - static::assertSame(['data' => ['a', 'b', 'c', 'd']], $row->toArray()); - } - - public function test_building_single_row_from_array_with_rows_fails(): void - { - $row = array_to_row( - [ - ['id' => 1234, 'deleted' => false, 'phase' => null], - ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], - ], - schema(json_schema('e00', nullable: true), json_schema('e01', nullable: true)), - flow_context(config())->backend(), - ); - - static::assertSame( - [ - 'e00' => ['id' => 1234, 'deleted' => false, 'phase' => null], - 'e01' => ['id' => 4321, 'deleted' => true, 'phase' => 'launch'], - ], - $row->toArray(), - ); - } - - public function test_refuses_an_undeclared_key(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage( - 'Rows do not match their schema: column "phase" (row 0) is not declared by the schema', - ); - - array_to_row( - ['id' => 1234, 'deleted' => false, 'phase' => null], - schema(int_schema('id'), bool_schema('deleted')), - flow_context(config())->backend(), - ); - } - - public function test_refuses_an_undeclared_partition(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage( - 'Rows do not match their schema: column "year" (row 0) is not declared by the schema', - ); - - array_to_row(['id' => 1234], schema(int_schema('id')), flow_context(config())->backend(), [partition( - 'year', - '2024', - )]); - } - - public function test_building_single_row_from_array_with_schema_but_entries_not_available_in_rows(): void - { - $row = array_to_row( - ['id' => 1234, 'deleted' => false], - schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', true)), - flow_context(config())->backend(), - ); - - static::assertSame(['id' => 1234, 'deleted' => false, 'phase' => null], $row->toArray()); - } - - public function test_building_single_row_from_flat_array(): void - { - $row = array_to_row( - [ - 'id' => 1234, - 'deleted' => false, - 'phase' => null, - ], - schema(int_schema('id'), bool_schema('deleted'), str_schema('phase', true)), - flow_context(config())->backend(), - ); - - static::assertSame(['id' => 1234, 'deleted' => false, 'phase' => null], $row->toArray()); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Comparator/NativeComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Comparator/NativeComparatorTest.php deleted file mode 100644 index d715eb6960..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Comparator/NativeComparatorTest.php +++ /dev/null @@ -1,42 +0,0 @@ -equals( - array_to_row(['test' => 'test'], schema(str_schema('test'))), - array_to_row(['test' => 'test'], schema(str_schema('test'))), - schema(str_schema('test')), - )); - } - - public function test_row_comparison_for_different_rows(): void - { - static::assertFalse((new NativeComparator())->equals( - array_to_row(['test' => 'test'], schema(str_schema('test'))), - array_to_row(['test' => 'other'], schema(str_schema('test'))), - schema(str_schema('test')), - )); - } - - public function test_row_comparison_for_rows_with_different_columns(): void - { - static::assertFalse((new NativeComparator())->equals( - array_to_row(['test' => 'test'], schema(str_schema('test'))), - array_to_row(['other' => 'test'], schema(str_schema('other'))), - schema(str_schema('test')), - )); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/NullsOrderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/NullsOrderTest.php new file mode 100644 index 0000000000..e3cea66e42 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/NullsOrderTest.php @@ -0,0 +1,18 @@ +name()); static::assertSame('integer', $aliased->returns()->toString()); } + + public function test_it_carries_the_sort_and_nulls_order(): void + { + $resolved = ref('a')->desc(NullsOrder::FIRST)->resolve(int_schema('a')); + + static::assertSame(SortOrder::DESC, $resolved->sort()); + static::assertSame(NullsOrder::FIRST, $resolved->nulls()); + static::assertSame(NullsOrder::FIRST, $resolved->as('b')->nulls()); + static::assertSame(NullsOrder::LAST, $resolved->asc(NullsOrder::LAST)->nulls()); + static::assertSame(NullsOrder::LAST, $resolved->desc()->nulls()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/UnresolvedReferenceTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/UnresolvedReferenceTest.php index 2db60cebf9..6608c1490a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/UnresolvedReferenceTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/UnresolvedReferenceTest.php @@ -4,10 +4,11 @@ namespace Flow\ETL\Tests\Unit\Row; +use Flow\ETL\Row\NullsOrder; use Flow\ETL\Row\SortOrder; +use Flow\ETL\Tests\Context\FunctionContext; use Flow\ETL\Tests\FlowTestCase; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -42,9 +43,10 @@ public function test_executing_equals_expression(): void { $ref = ref('a')->equals(ref('b')); - static::assertTrue($ref->eval( - array_to_row(['a' => 1, 'b' => 1], schema(int_schema('a'), int_schema('b'))), - flow_context(), + static::assertTrue((new FunctionContext(flow_context()))->eval( + $ref, + ['a' => 1, 'b' => 1], + schema(int_schema('a'), int_schema('b')), )); } @@ -52,24 +54,34 @@ public function test_executing_expression(): void { $ref = ref('b')->literal(100); - static::assertSame(100, $ref->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context())); + static::assertSame(100, (new FunctionContext(flow_context()))->eval($ref, ['a' => 1], schema(int_schema('a')))); } public function test_is_even(): void { $ref = ref('a')->isEven(); - static::assertFalse($ref->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval($ref, ['a' => 1], schema(int_schema('a')))); - static::assertTrue($ref->eval(array_to_row(['a' => 2], schema(int_schema('a'))), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval($ref, ['a' => 2], schema(int_schema('a')))); } public function test_is_odd(): void { $ref = ref('a')->isOdd(); - static::assertTrue($ref->eval(array_to_row(['a' => 1], schema(int_schema('a'))), flow_context())); + static::assertTrue((new FunctionContext(flow_context()))->eval($ref, ['a' => 1], schema(int_schema('a')))); - static::assertFalse($ref->eval(array_to_row(['a' => 2], schema(int_schema('a'))), flow_context())); + static::assertFalse((new FunctionContext(flow_context()))->eval($ref, ['a' => 2], schema(int_schema('a')))); + } + + public function test_nulls_default_to_the_smallest_value_and_can_be_moved(): void + { + static::assertSame(NullsOrder::FIRST, ref('a')->nulls()); + static::assertSame(NullsOrder::FIRST, ref('a')->asc()->nulls()); + static::assertSame(NullsOrder::LAST, ref('a')->desc()->nulls()); + static::assertSame(NullsOrder::LAST, ref('a')->asc(NullsOrder::LAST)->nulls()); + static::assertSame(NullsOrder::FIRST, ref('a')->desc(NullsOrder::FIRST)->nulls()); + static::assertSame(NullsOrder::LAST, ref('a')->asc(NullsOrder::LAST)->as('b')->nulls()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php deleted file mode 100644 index 36a09b0b3e..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowTest.php +++ /dev/null @@ -1,182 +0,0 @@ -expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Column "missing" does not exist'); - - array_to_row(['id' => 1], schema(int_schema('id')))->get('missing'); - } - - #[TestWith([-1])] - #[TestWith([1])] - public function test_a_view_outside_its_batch_is_refused(int $index): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage("Row {$index} does not exist in a batch of 1 rows"); - - array_to_row(['id' => 1], schema(int_schema('id')))->rows->row($index); - } - - public function test_has(): void - { - $row = array_to_row(['id' => 1, 'name' => 'one'], schema(int_schema('id'), str_schema('name'))); - - static::assertTrue($row->has('id')); - static::assertTrue($row->has('id', 'name')); - static::assertFalse($row->has('missing')); - static::assertFalse($row->has('id', 'missing')); - } - - /** - * The hash is a dedup key, so it stays order-independent: the Schema is sorted alphabetically - * before the values are folded, exactly as Entries::sort() did. - */ - public function test_hash_ignores_column_order(): void - { - $schema = schema(int_schema('id'), bool_schema('bool'), str_schema('string')); - - static::assertSame( - array_to_row( - ['id' => 1, 'string' => 'string', 'bool' => false], - schema(int_schema('id'), str_schema('string'), bool_schema('bool')), - )->hash($schema), - array_to_row( - ['bool' => false, 'id' => 1, 'string' => 'string'], - schema(bool_schema('bool'), int_schema('id'), str_schema('string')), - )->hash($schema), - ); - } - - public function test_hash_of_an_empty_row(): void - { - static::assertSame(array_to_row([], schema())->hash(schema()), array_to_row([], schema())->hash(schema())); - } - - public function test_hash_of_different_rows(): void - { - $schema = schema(list_schema('list', type_list(type_integer()))); - - static::assertNotSame( - array_to_row(['list' => [1, 2, 3]], schema(list_schema('list', type_list(type_integer()))))->hash($schema), - array_to_row(['list' => [3, 2, 1]], schema(list_schema('list', type_list(type_integer()))))->hash($schema), - ); - } - - public function test_names_and_values_keep_storage_order(): void - { - $row = array_to_row(['b' => 2, 'a' => 1], schema(int_schema('b'), int_schema('a'))); - - static::assertSame(['b', 'a'], $row->names()); - static::assertSame(['b' => 2, 'a' => 1], $row->values()); - } - - public function test_transforms_row_to_array(): void - { - $row = array_to_row( - [ - 'id' => 1234, - 'deleted' => false, - 'created-at' => $createdAt = new DateTimeImmutable('2020-07-13 15:00'), - 'phase' => null, - 'items' => ['item-id' => 1, 'name' => 'one'], - 'statuses' => ['NEW', 'PENDING'], - ], - schema( - int_schema('id'), - bool_schema('deleted'), - datetime_schema('created-at'), - str_schema('phase', nullable: true), - structure_schema('items', type_structure(['item-id' => type_integer(), 'name' => type_string()])), - list_schema('statuses', type_list(type_string())), - ), - ); - - static::assertEquals( - [ - 'id' => 1234, - 'deleted' => false, - 'created-at' => $createdAt, - 'phase' => null, - 'items' => ['item-id' => 1, 'name' => 'one'], - 'statuses' => ['NEW', 'PENDING'], - ], - $row->toArray(), - ); - } - - public function test_transforms_row_to_array_without_keys(): void - { - static::assertSame( - [1, 'one'], - array_to_row(['id' => 1, 'name' => 'one'], schema(int_schema('id'), str_schema('name')))->toArray( - withKeys: false, - ), - ); - } - - /** - * The Schema names, types and orders the columns; the Row is name-keyed storage. - */ - public function test_values_are_read_by_the_schema(): void - { - $schema = schema( - int_schema('id'), - str_schema('name'), - datetime_schema('created-at'), - structure_schema('items', type_structure(['a' => type_integer()])), - map_schema('statuses', type_map(type_integer(), type_string())), - ); - $createdAt = new DateTimeImmutable('2020-07-13 15:00'); - $row = array_to_row([ - 'id' => 1, - 'name' => 'one', - 'created-at' => $createdAt, - 'items' => ['a' => 1], - 'statuses' => ['NEW'], - ], $schema); - - $values = []; - - foreach ($schema->references()->names() as $name) { - $values[$name] = $row->get($name); - } - - static::assertEquals( - [ - 'id' => 1, - 'name' => 'one', - 'created-at' => $createdAt, - 'items' => ['a' => 1], - 'statuses' => ['NEW'], - ], - $values, - ); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowEqualityTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowEqualityTest.php new file mode 100644 index 0000000000..8f0b1a4abc --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowEqualityTest.php @@ -0,0 +1,165 @@ +equal( + ['id' => type_integer(), 'name' => type_string()], + ['id' => [1]], + 0, + ['id' => [1], 'name' => ['a']], + 0, + )); + } + + public function test_not_in_keeps_rows_without_an_equal_row_in_the_other_batch(): void + { + $schema = schema(int_schema('id'), str_schema('name')); + + static::assertSame( + [1, 2], + (new RowEquality())->notIn( + array_to_rows([ + ['id' => 1, 'name' => 'a'], + ['id' => 2, 'name' => 'b'], + ['id' => 1, 'name' => 'z'], + ], $schema), + array_to_rows([['id' => 1, 'name' => 'a'], ['id' => 3, 'name' => 'c']], $schema), + $schema, + ), + ); + } + + public function test_not_in_keeps_every_row_when_the_columns_differ(): void + { + static::assertSame( + [0, 1], + (new RowEquality())->notIn( + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), + array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))), + schema(int_schema('id')), + ), + ); + } + + public function test_unique_compares_values_not_instances(): void + { + $schema = schema(uuid_schema('id')); + + static::assertSame( + [0, 2], + (new RowEquality())->unique(array_to_rows([ + ['id' => new Uuid('0198f4f2-37e3-7e1c-9a2e-1f2b3c4d5e6f')], + ['id' => new Uuid('0198f4f2-37e3-7e1c-9a2e-1f2b3c4d5e6f')], + ['id' => new Uuid('0198f4f2-37e3-7e1c-9a2e-1f2b3c4d5e70')], + ], $schema)), + ); + } + + public function test_unique_compares_only_rows_whose_exact_columns_hash_alike(): void + { + $calls = new ArrayObject(); + $documents = []; + + for ($i = 0; $i < 20; $i++) { + $documents[] = new CountingDOMDocument($calls); + } + + $ids = array_to_rows( + array_map(static fn(int $id): array => ['id' => $id], range(0, 19)), + schema(int_schema('id')), + ); + $schema = schema(xml_schema('x'), int_schema('id')); + $rows = Rows::fromColumns( + $schema, + ['x' => new FixedValuesColumn(type_xml(), $documents), 'id' => $ids->column('id')], + 20, + ); + + static::assertSame(range(0, 19), (new RowEquality())->unique($rows)); + static::assertCount(0, $calls); + } + + public function test_not_in_compares_only_rows_whose_exact_columns_hash_alike(): void + { + $calls = new ArrayObject(); + $schema = schema(xml_schema('x'), int_schema('id')); + $batch = static fn(int $from): Rows => Rows::fromColumns( + $schema, + [ + 'x' => new FixedValuesColumn(type_xml(), array_map( + static fn(): CountingDOMDocument => new CountingDOMDocument($calls), + range(0, 9), + )), + 'id' => array_to_rows( + array_map(static fn(int $id): array => ['id' => $id], range($from, $from + 9)), + schema(int_schema('id')), + )->column('id'), + ], + 10, + ); + + static::assertSame(range(0, 9), (new RowEquality())->notIn($batch(0), $batch(100), $schema)); + static::assertCount(0, $calls); + } + + public function test_unique_keeps_json_rows_equal_by_value_although_they_hash_apart(): void + { + static::assertSame( + [0], + (new RowEquality())->unique(array_to_rows([ + ['j' => new Json('{"a":1,"b":2}')], + ['j' => new Json('{"b":2,"a":1}')], + ], schema(json_schema('j')))), + ); + } + + public function test_unique_keeps_the_first_row_of_every_equal_group(): void + { + static::assertSame( + [0, 1, 4], + (new RowEquality())->unique(array_to_rows( + [ + ['id' => 1, 'name' => 'a'], + ['id' => 2, 'name' => 'b'], + ['id' => 1, 'name' => 'a'], + ['id' => 2, 'name' => 'b'], + ['id' => 3, 'name' => null], + ], + schema(int_schema('id'), str_schema('name', nullable: true)), + )), + ); + } + + public function test_unique_of_an_empty_batch_is_empty(): void + { + static::assertSame([], (new RowEquality())->unique(array_to_rows([], schema(int_schema('id'))))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowHashesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowHashesTest.php new file mode 100644 index 0000000000..467f2b4b46 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowHashesTest.php @@ -0,0 +1,150 @@ + type_integer()])), + ); + $rows = array_to_rows([ + [ + 's' => 'a', + 'i' => 1, + 'f' => 1.5, + 'b' => true, + 'dt' => new DateTimeImmutable('2024-01-01 10:00:00.5'), + 'd' => new DateTimeImmutable('2024-01-01'), + 't' => 'PT1H', + 'u' => '00000000-0000-4000-8000-000000000001', + 'j' => '{"a":1}', + 'e' => BackedStringEnum::one, + 'x' => '1', + 'tz' => 'UTC', + 'l' => [1, 2], + 'm' => ['k' => 1], + 'st' => ['a' => 1], + ], + [ + 's' => null, + 'i' => 2, + 'f' => 0.0, + 'b' => false, + 'dt' => new DateTimeImmutable('1969-12-31 23:59:59'), + 'd' => new DateTimeImmutable('1969-12-31'), + 't' => 'PT0S', + 'u' => '00000000-0000-4000-8000-000000000002', + 'j' => '[]', + 'e' => BackedStringEnum::two, + 'x' => '', + 'tz' => 'Europe/Warsaw', + 'l' => [], + 'm' => [], + 'st' => ['a' => 2], + ], + ], $schema); + + $hashes = (new RowHashes())->of($rows); + + static::assertSame( + [(new RowHashes())->of($rows->slice(0, 1))[0], (new RowHashes())->of($rows->slice(1, 1))[0]], + $hashes, + ); + static::assertNotSame($hashes[0], $hashes[1]); + } + + public function test_a_hash_ignores_column_order(): void + { + static::assertSame( + (new RowHashes())->of(array_to_rows( + [['id' => 1, 'string' => 'string', 'bool' => false]], + schema(int_schema('id'), str_schema('string'), bool_schema('bool')), + )), + (new RowHashes())->of(array_to_rows( + [['bool' => false, 'id' => 1, 'string' => 'string']], + schema(bool_schema('bool'), int_schema('id'), str_schema('string')), + )), + ); + } + + public function test_rows_differing_in_element_order_hash_differently(): void + { + $hashes = (new RowHashes())->of(array_to_rows([ + ['list' => [1, 2, 3]], + ['list' => [3, 2, 1]], + ], schema(list_schema('list', type_list(type_integer()))))); + + static::assertNotSame($hashes[0], $hashes[1]); + } + + public function test_a_row_of_a_batch_without_columns_hashes_the_empty_string(): void + { + static::assertSame( + [(new NativePHPHash())->hash('')], + (new RowHashes())->of(Rows::fromColumns(schema(), [], 1)), + ); + } + + public function test_the_algorithm_hashes_each_row(): void + { + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); + + static::assertSame( + [(new NativePHPHash('md5'))->hash('id1')], + (new RowHashes())->of($rows, new NativePHPHash('md5')), + ); + } + + public function test_an_empty_batch_has_no_hashes(): void + { + static::assertSame([], (new RowHashes())->of(array_to_rows([], schema(int_schema('id'))))); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php index befb6de646..11cb90f76b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php @@ -441,11 +441,12 @@ public function test_a_value_the_schema_does_not_declare_is_dropped(): void { static::assertSame( ['id'], - (new RowsBuilder(schema(int_schema('id')), new PhpBackend())) - ->append(['id' => 1, 'undeclared' => 'x']) - ->finish() - ->first() - ->names(), + array_keys( + (new RowsBuilder(schema(int_schema('id')), new PhpBackend())) + ->append(['id' => 1, 'undeclared' => 'x']) + ->finish() + ->values(0), + ), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php index e07155d2e4..b5d7592e2a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php @@ -68,7 +68,8 @@ public function test_xml_column_metadata_survives_a_serialize_round_trip(): void /** @var Rows $restored */ $restored = unserialize(serialize($rows)); - $restoredDocument = $restored->first()->get('x'); + // @mago-ignore analysis:mixed-assignment + $restoredDocument = $restored->column('x')->value(0); assert($restoredDocument instanceof DOMDocument); static::assertSame(['src' => 'file.xml'], $restored->schema()->get('x')->metadata()->normalize()); @@ -81,9 +82,13 @@ public function test_xml_document_survives_a_round_trip(): void $document = new DOMDocument(); $document->loadXML('1'); - $restored = type_instance_of(DOMDocument::class)->assert(RowsSerializationContext::roundTrip(array_to_rows([[ - 'x' => $document, - ]], schema(xml_schema('x'))))->first()->get('x')); + $restored = type_instance_of(DOMDocument::class)->assert( + RowsSerializationContext::roundTrip(array_to_rows([[ + 'x' => $document, + ]], schema(xml_schema('x')))) + ->column('x') + ->value(0), + ); static::assertSame($document->C14N(), $restored->C14N()); } @@ -93,9 +98,13 @@ public function test_xml_element_survives_a_round_trip(): void $document = new DOMDocument(); $document->loadXML('1'); - $restored = type_instance_of(DOMElement::class)->assert(RowsSerializationContext::roundTrip(array_to_rows([[ - 'x' => $document->documentElement, - ]], schema(xml_element_schema('x'))))->first()->get('x')); + $restored = type_instance_of(DOMElement::class)->assert( + RowsSerializationContext::roundTrip(array_to_rows([[ + 'x' => $document->documentElement, + ]], schema(xml_element_schema('x')))) + ->column('x') + ->value(0), + ); static::assertSame('1', $restored->C14N()); } @@ -111,8 +120,8 @@ public function test_restored_xml_elements_do_not_canonicalize_to_an_empty_strin ['x' => $left->documentElement], ['x' => $right->documentElement], ], schema(xml_element_schema('x')))); - $restoredLeft = type_instance_of(DOMElement::class)->assert($restored->first()->get('x')); - $restoredRight = type_instance_of(DOMElement::class)->assert($restored->row(1)->get('x')); + $restoredLeft = type_instance_of(DOMElement::class)->assert($restored->column('x')->value(0)); + $restoredRight = type_instance_of(DOMElement::class)->assert($restored->column('x')->value(1)); static::assertNotSame('', $restoredLeft->C14N()); static::assertNotSame($restoredLeft->C14N(), $restoredRight->C14N()); @@ -125,9 +134,13 @@ public function test_html_document_survives_a_round_trip(): void static::assertSame( type_string()->cast($document), - type_string()->cast(RowsSerializationContext::roundTrip(array_to_rows([[ - 'x' => $document, - ]], schema(html_schema('x'))))->first()->get('x')), + type_string()->cast( + RowsSerializationContext::roundTrip(array_to_rows([[ + 'x' => $document, + ]], schema(html_schema('x')))) + ->column('x') + ->value(0), + ), ); } @@ -138,9 +151,13 @@ public function test_html_element_survives_a_round_trip(): void static::assertSame( type_string()->cast($element), - type_string()->cast(RowsSerializationContext::roundTrip(array_to_rows([[ - 'x' => $element, - ]], schema(html_element_schema('x'))))->first()->get('x')), + type_string()->cast( + RowsSerializationContext::roundTrip(array_to_rows([[ + 'x' => $element, + ]], schema(html_element_schema('x')))) + ->column('x') + ->value(0), + ), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php index 010107f1c5..6e4ff19d2a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php @@ -8,27 +8,25 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Row; -use Flow\ETL\Row\Comparator; -use Flow\ETL\Row\Comparator\NativeComparator; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Tests\FlowTestCase; use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestWith; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; +use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; @@ -38,6 +36,7 @@ use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_optional; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; @@ -142,27 +141,21 @@ public static function unique_rows_provider(): Generator yield 'simple identical rows' => [ array_to_rows([['number' => 1]], schema(int_schema('number'))), array_to_rows([['number' => 1], ['number' => 1]], schema(int_schema('number'))), - new NativeComparator(), ]; - } - - public function test_add_reports_the_violating_row_at_its_position_in_the_batch(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage('column "number" (row 1): could not convert \'x\' (string) to integer'); - - array_to_rows([['number' => 1]], schema(int_schema('number')))->add(array_to_row([ - 'number' => 'x', - ], schema(str_schema('number')))); - } - - public function test_adding_multiple_rows(): void - { - $one = array_to_row(['number' => 1, 'name' => 'one'], schema(int_schema('number'), str_schema('name'))); - $two = array_to_row(['number' => 2, 'name' => 'two'], schema(int_schema('number'), str_schema('name'))); - $schema = schema(int_schema('number'), str_schema('name')); - - static::assertEquals(rows($schema, $one, $two), rows($schema)->add($one, $two)); + yield 'rows equal in one column only' => [ + array_to_rows( + [['number' => 1, 'name' => 'a'], ['number' => 1, 'name' => 'b']], + schema(int_schema('number'), str_schema('name', true)), + ), + array_to_rows( + [['number' => 1, 'name' => 'a'], ['number' => 1, 'name' => 'b'], ['number' => 1, 'name' => 'a']], + schema(int_schema('number'), str_schema('name', true)), + ), + ]; + yield 'null and empty string are distinct' => [ + array_to_rows([['name' => null], ['name' => '']], schema(str_schema('name', true))), + array_to_rows([['name' => null], ['name' => ''], ['name' => null]], schema(str_schema('name', true))), + ]; } public function test_match_to_adopts_a_wider_schema_and_pads_the_new_nullable_column(): void @@ -195,11 +188,10 @@ public function test_project_drops_the_columns_the_schema_does_not_declare(): vo ->toArray(), ); static::assertSame( - ['name', 'id'], + ['name' => 'a', 'id' => 1], array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))) ->project(schema(str_schema('name'), int_schema('id'))) - ->first() - ->names(), + ->values(0), ); } @@ -226,10 +218,11 @@ public function test_project_rejects_a_schema_that_retypes_a_column(): void public function test_construct_reorders_row_storage_into_schema_order(): void { static::assertSame( - ['c', 'a', 'b'], - array_to_rows([['a' => 1, 'b' => 2, 'c' => 3]], schema(int_schema('c'), int_schema('a'), int_schema('b'))) - ->first() - ->names(), + ['c' => 3, 'a' => 1, 'b' => 2], + array_to_rows( + [['a' => 1, 'b' => 2, 'c' => 3]], + schema(int_schema('c'), int_schema('a'), int_schema('b')), + )->values(0), ); } @@ -241,53 +234,6 @@ public function test_construct_rejects_a_row_that_contradicts_the_schema(): void array_to_rows([['number' => 'x']], schema(int_schema('number'))); } - public function test_the_epic_repro_is_unconstructible(): void - { - $this->expectException(SchemaMismatchException::class); - $this->expectExceptionMessage( - 'Rows do not match their schema: column "code" (row 1): could not convert 1000 (integer) to string', - ); - - rows( - schema(str_schema('code')), - array_to_row(['code' => 'AB-01'], schema(str_schema('code'))), - array_to_row(['code' => 1000], schema(int_schema('code'))), - ); - } - - public function test_array_access_exists(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - static::assertTrue(isset($rows[0])); - static::assertFalse(isset($rows[3])); - } - - public function test_array_access_get(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - static::assertSame(1, $rows[0]->get('id')); - static::assertSame(2, $rows[1]->get('id')); - static::assertSame(3, $rows[2]->get('id')); - } - - public function test_array_access_set(): void - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('In order to add new rows use Rows::add(Row $row) : self'); - $rows = rows(schema()); - $rows[0] = array_to_row(['id' => 1], schema(int_schema('id'))); - } - - public function test_array_access_unset(): void - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('In order to remove rows use Rows::remove(int $offset) : self'); - $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); - unset($rows[0]); - } - public function test_chunks_with_less(): void { $rows = array_to_rows([ @@ -335,8 +281,8 @@ public function test_drop(): void $rows = $rows->drop(1); static::assertCount(2, $rows); - static::assertSame(2, $rows[0]->get('id')); - static::assertSame(3, $rows[1]->get('id')); + static::assertSame(2, $rows->column('id')->value(0)); + static::assertSame(3, $rows->column('id')->value(1)); } public function test_drop_all(): void @@ -364,8 +310,8 @@ public function test_drop_right(): void $rows = $rows->dropRight(1); static::assertCount(2, $rows); - static::assertSame(1, $rows[0]->get('id')); - static::assertSame(2, $rows[1]->get('id')); + static::assertSame(1, $rows->column('id')->value(0)); + static::assertSame(2, $rows->column('id')->value(1)); } public function test_drop_right_all(): void @@ -401,13 +347,6 @@ public function test_empty_rows(): void static::assertFalse(array_to_rows([['id' => 1]], schema(int_schema('id')))->isEmpty()); } - public function test_first_on_empty_rows(): void - { - $this->expectException(RuntimeException::class); - - rows(schema())->first(); - } - public function test_hash(): void { $rows = array_to_rows( @@ -501,9 +440,9 @@ public function test_head(): void $head = $rows->head(3); static::assertCount(3, $head); - static::assertSame(1, $head[0]->get('id')); - static::assertSame(2, $head[1]->get('id')); - static::assertSame(3, $head[2]->get('id')); + static::assertSame(1, $head->column('id')->value(0)); + static::assertSame(2, $head->column('id')->value(1)); + static::assertSame(3, $head->column('id')->value(2)); } public function test_head_on_empty_rows(): void @@ -520,9 +459,9 @@ public function test_head_with_count_larger_than_available(): void $head = $rows->head(10); static::assertCount(3, $head); - static::assertSame(1, $head[0]->get('id')); - static::assertSame(2, $head[1]->get('id')); - static::assertSame(3, $head[2]->get('id')); + static::assertSame(1, $head->column('id')->value(0)); + static::assertSame(2, $head->column('id')->value(1)); + static::assertSame(3, $head->column('id')->value(2)); } public function test_head_with_negative_count(): void @@ -544,33 +483,6 @@ public function test_head_with_zero_count(): void static::assertCount(0, $head); } - public function test_last(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $lastRow = $rows->last(); - - static::assertNotNull($lastRow); - static::assertSame(3, $lastRow->get('id')); - } - - public function test_last_on_empty_rows(): void - { - $lastRow = rows(schema())->last(); - - static::assertNull($lastRow); - } - - public function test_last_on_single_row(): void - { - $rows = array_to_rows([['id' => 42]], schema(int_schema('id'))); - - $lastRow = $rows->last(); - - static::assertNotNull($lastRow); - static::assertSame(42, $lastRow->get('id')); - } - public function test_merge_accepts_an_empty_side_with_any_schema(): void { $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); @@ -616,21 +528,6 @@ public function test_merges_collection_together(): void ); } - public function test_offset_exists_with_non_int_offset(): void - { - $this->expectException(InvalidArgumentException::class); - - // @mago-ignore analysis:invalid-argument - rows(schema())->offsetExists('a'); - } - - public function test_offset_get_on_empty_rows(): void - { - $this->expectException(InvalidArgumentException::class); - - rows(schema())[5]; - } - public function test_remove(): void { $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); @@ -638,8 +535,8 @@ public function test_remove(): void $rows = $rows->remove(1); static::assertCount(2, $rows); - static::assertSame(1, $rows[0]->get('id')); - static::assertSame(3, $rows[1]->get('id')); + static::assertSame(1, $rows->column('id')->value(0)); + static::assertSame(3, $rows->column('id')->value(1)); } public function test_remove_on_empty_rows(): void @@ -649,18 +546,6 @@ public function test_remove_on_empty_rows(): void rows(schema())->remove(1); } - public function test_returns_first_row(): void - { - $rows = rows( - schema(int_schema('number'), str_schema('name')), - $first = array_to_row(['number' => 3, 'name' => 'three'], schema(int_schema('number'), str_schema('name'))), - array_to_row(['number' => 1, 'name' => 'one'], schema(int_schema('number'), str_schema('name'))), - array_to_row(['number' => 2, 'name' => 'two'], schema(int_schema('number'), str_schema('name'))), - ); - - static::assertEquals($first, $rows->first()); - } - public function test_reverse(): void { $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); @@ -668,9 +553,9 @@ public function test_reverse(): void $rows = $rows->reverse(); static::assertCount(3, $rows); - static::assertSame(3, $rows[0]->get('id')); - static::assertSame(2, $rows[1]->get('id')); - static::assertSame(1, $rows[2]->get('id')); + static::assertSame(3, $rows->column('id')->value(0)); + static::assertSame(2, $rows->column('id')->value(1)); + static::assertSame(1, $rows->column('id')->value(2)); } #[DataProvider('rows_diff_left_provider')] @@ -729,11 +614,13 @@ public function test_rows_reject_a_row_whose_list_contradicts_the_declared_eleme 'Rows do not match their schema: column "list" (row 1): could not convert array (list) to list', ); - rows( - schema(list_schema('list', type_list(type_string()))), - array_to_row(['list' => ['one', 'two']], schema(list_schema('list', type_list(type_string())))), - array_to_row(['list' => [1, 2]], schema(list_schema('list', type_list(type_integer())))), - ); + array_to_rows([ + ['list' => []], + ['list' => [1, 2]], + ], schema(list_schema('list', type_list(type_integer()))))->matchTo(schema(list_schema( + 'list', + type_list(type_string()), + ))); } public function test_rows_serialization(): void @@ -750,12 +637,9 @@ public function test_rows_serialization(): void } #[DataProvider('unique_rows_provider')] - public function test_rows_unique( - Rows $expected, - Rows $notUnique, - Comparator $comparator = new NativeComparator(), - ): void { - static::assertEquals($expected, $notUnique->unique($comparator)); + public function test_rows_unique(Rows $expected, Rows $notUnique): void + { + static::assertSame($expected->toArray(), $notUnique->unique()->toArray()); } public function test_sort_rows_by_not_existing_column(): void @@ -821,28 +705,23 @@ public function test_sort_rows_by_two_columns(): void public function test_sort_rows_without_changing_original_collection(): void { - $rows = rows( + $rows = array_to_rows( + [ + ['number' => 3, 'name' => 'three'], + ['number' => 1, 'name' => 'one'], + ['number' => 5, 'name' => 'five'], + ['number' => 2, 'name' => 'two'], + ['number' => 4, 'name' => 'four'], + ], schema(int_schema('number'), str_schema('name')), - $three = array_to_row(['number' => 3, 'name' => 'three'], schema(int_schema('number'), str_schema('name'))), - $one = array_to_row(['number' => 1, 'name' => 'one'], schema(int_schema('number'), str_schema('name'))), - $five = array_to_row(['number' => 5, 'name' => 'five'], schema(int_schema('number'), str_schema('name'))), - $two = array_to_row(['number' => 2, 'name' => 'two'], schema(int_schema('number'), str_schema('name'))), - $four = array_to_row(['number' => 4, 'name' => 'four'], schema(int_schema('number'), str_schema('name'))), ); $ascending = $rows->sortAscending(ref('number')); $descending = $rows->sortDescending(ref('number')); - static::assertEquals( - rows(schema(int_schema('number'), str_schema('name')), $one, $two, $three, $four, $five), - $ascending, - ); - static::assertEquals( - rows(schema(int_schema('number'), str_schema('name')), $five, $four, $three, $two, $one), - $descending, - ); - static::assertNotEquals($ascending, $rows); - static::assertNotEquals($descending, $rows); + static::assertSame([1, 2, 3, 4, 5], $ascending->column('number')->values()); + static::assertSame([5, 4, 3, 2, 1], $descending->column('number')->values()); + static::assertSame([3, 1, 5, 2, 4], $rows->column('number')->values()); } public function test_tail(): void @@ -858,9 +737,9 @@ public function test_tail(): void $tail = $rows->tail(3); static::assertCount(3, $tail); - static::assertSame(3, $tail[0]->get('id')); - static::assertSame(4, $tail[1]->get('id')); - static::assertSame(5, $tail[2]->get('id')); + static::assertSame(3, $tail->column('id')->value(0)); + static::assertSame(4, $tail->column('id')->value(1)); + static::assertSame(5, $tail->column('id')->value(2)); } public function test_tail_maintains_correct_order(): void @@ -876,8 +755,8 @@ public function test_tail_maintains_correct_order(): void $tail = $rows->tail(2); static::assertCount(2, $tail); - static::assertSame(4, $tail[0]->get('id')); - static::assertSame(5, $tail[1]->get('id')); + static::assertSame(4, $tail->column('id')->value(0)); + static::assertSame(5, $tail->column('id')->value(1)); } public function test_tail_on_empty_rows(): void @@ -894,9 +773,9 @@ public function test_tail_with_count_larger_than_available(): void $tail = $rows->tail(10); static::assertCount(3, $tail); - static::assertSame(1, $tail[0]->get('id')); - static::assertSame(2, $tail[1]->get('id')); - static::assertSame(3, $tail[2]->get('id')); + static::assertSame(1, $tail->column('id')->value(0)); + static::assertSame(2, $tail->column('id')->value(1)); + static::assertSame(3, $tail->column('id')->value(2)); } public function test_tail_with_negative_count(): void @@ -925,7 +804,7 @@ public function test_take(): void $rows = $rows->take(1); static::assertCount(1, $rows); - static::assertSame(1, $rows[0]->get('id')); + static::assertSame(1, $rows->column('id')->value(0)); } public function test_take_all(): void @@ -935,9 +814,9 @@ public function test_take_all(): void $rows = $rows->take(3); static::assertCount(3, $rows); - static::assertSame(1, $rows[0]->get('id')); - static::assertSame(2, $rows[1]->get('id')); - static::assertSame(3, $rows[2]->get('id')); + static::assertSame(1, $rows->column('id')->value(0)); + static::assertSame(2, $rows->column('id')->value(1)); + static::assertSame(3, $rows->column('id')->value(2)); } public function test_take_more_than_exists(): void @@ -947,9 +826,9 @@ public function test_take_more_than_exists(): void $rows = $rows->take(4); static::assertCount(3, $rows); - static::assertSame(1, $rows[0]->get('id')); - static::assertSame(2, $rows[1]->get('id')); - static::assertSame(3, $rows[2]->get('id')); + static::assertSame(1, $rows->column('id')->value(0)); + static::assertSame(2, $rows->column('id')->value(1)); + static::assertSame(3, $rows->column('id')->value(2)); } public function test_take_right(): void @@ -959,7 +838,7 @@ public function test_take_right(): void $rows = $rows->takeRight(1); static::assertCount(1, $rows); - static::assertSame(3, $rows[0]->get('id')); + static::assertSame(3, $rows->column('id')->value(0)); } public function test_take_right_all(): void @@ -969,9 +848,9 @@ public function test_take_right_all(): void $rows = $rows->takeRight(3); static::assertCount(3, $rows); - static::assertSame(3, $rows[0]->get('id')); - static::assertSame(2, $rows[1]->get('id')); - static::assertSame(1, $rows[2]->get('id')); + static::assertSame(3, $rows->column('id')->value(0)); + static::assertSame(2, $rows->column('id')->value(1)); + static::assertSame(1, $rows->column('id')->value(2)); } public function test_take_right_more_than_exists(): void @@ -981,9 +860,9 @@ public function test_take_right_more_than_exists(): void $rows = $rows->takeRight(4); static::assertCount(3, $rows); - static::assertSame(3, $rows[0]->get('id')); - static::assertSame(2, $rows[1]->get('id')); - static::assertSame(1, $rows[2]->get('id')); + static::assertSame(3, $rows->column('id')->value(0)); + static::assertSame(2, $rows->column('id')->value(1)); + static::assertSame(1, $rows->column('id')->value(2)); } public function test_transforms_rows_to_array(): void @@ -1024,6 +903,74 @@ public function test_transforms_rows_to_array_without_keys(): void ); } + public function test_values_of_a_row_are_keyed_in_schema_order(): void + { + $createdAt = new DateTimeImmutable('2020-07-13 15:00'); + + static::assertEquals( + [ + 'id' => 1234, + 'deleted' => false, + 'created-at' => $createdAt, + 'phase' => null, + 'items' => ['item-id' => 1, 'name' => 'one'], + 'statuses' => [1 => 'NEW'], + ], + array_to_rows( + [ + [ + 'id' => 1, + 'deleted' => true, + 'created-at' => $createdAt, + 'phase' => 'x', + 'items' => [ + 'item-id' => 0, + 'name' => 'zero', + ], + 'statuses' => [], + ], + [ + 'statuses' => [1 => 'NEW'], + 'phase' => null, + 'items' => [ + 'item-id' => 1, + 'name' => 'one', + ], + 'id' => 1234, + 'created-at' => $createdAt, + 'deleted' => false, + ], + ], + schema( + int_schema('id'), + bool_schema('deleted'), + datetime_schema('created-at'), + str_schema('phase', nullable: true), + structure_schema('items', type_structure(['item-id' => type_integer(), 'name' => type_string()])), + map_schema('statuses', type_map(type_integer(), type_string())), + ), + )->values(1), + ); + } + + #[TestWith([-1])] + #[TestWith([1])] + public function test_values_outside_the_batch_are_refused(int $index): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Row {$index} does not exist in a batch of 1 rows"); + + array_to_rows([['id' => 1]], schema(int_schema('id')))->values($index); + } + + public function test_an_absent_column_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column "missing" does not exist'); + + array_to_rows([['id' => 1]], schema(int_schema('id')))->column('missing'); + } + public function test_structure_field_order_is_a_schema_difference_not_a_value_difference(): void { $left = array_to_rows([['s' => [ @@ -1058,9 +1005,13 @@ public function test_rows_hop_a_foreign_zone_at_ingest(): void static::assertSame( '2026-01-01 22:04:05 UTC', type_datetime() - ->assert(array_to_rows([[ - 'at' => new DateTimeImmutable('2026-01-02 03:04:05+05:00'), - ]], schema(datetime_schema('at')))->first()->get('at')) + ->assert( + array_to_rows([[ + 'at' => new DateTimeImmutable('2026-01-02 03:04:05+05:00'), + ]], schema(datetime_schema('at'))) + ->column('at') + ->value(0), + ) ->format('Y-m-d H:i:s e'), ); } @@ -1070,12 +1021,14 @@ public function test_rows_hop_nested_datetimes(): void static::assertSame( '2026-01-02 04:04:05 Europe/Warsaw', type_list(type_datetime()) - ->assert(array_to_rows([['l' => [new DateTimeImmutable( - '2026-01-02 03:04:05', - new DateTimeZone('UTC'), - )]]], schema(list_schema('l', type_list(type_datetime('Europe/Warsaw')))))->first()->get( - 'l', - ))[0]->format('Y-m-d H:i:s e'), + ->assert( + array_to_rows([['l' => [new DateTimeImmutable( + '2026-01-02 03:04:05', + new DateTimeZone('UTC'), + )]]], schema(list_schema('l', type_list(type_datetime('Europe/Warsaw'))))) + ->column('l') + ->value(0), + )[0]->format('Y-m-d H:i:s e'), ); } @@ -1084,74 +1037,79 @@ public function test_rows_hop_nested_optional_datetimes(): void static::assertSame( '2026-01-02 04:04:05 Europe/Warsaw', type_list(type_optional(type_datetime())) - ->assert(array_to_rows([['l' => [ - new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), - null, - ]]], schema(list_schema('l', type_list(type_optional(type_datetime('Europe/Warsaw'))))))->first()->get( - 'l', - ))[0]?->format('Y-m-d H:i:s e'), + ->assert( + array_to_rows([['l' => [ + new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), + null, + ]]], schema(list_schema('l', type_list(type_optional(type_datetime('Europe/Warsaw')))))) + ->column('l') + ->value(0), + )[0]?->format('Y-m-d H:i:s e'), ); } /** - * @return Generator + * @return Generator */ - public static function from_rows_refusals(): Generator + public static function match_to_refusals(): Generator { yield 'other column, same count' => [ schema(int_schema('a'), int_schema('b')), - array_to_row(['a' => 1, 'z' => 2], schema(int_schema('a'), int_schema('z'))), - 'Rows do not match their schema: column "b" (row 0) declared by the schema is missing from the row', + array_to_rows([['a' => 1, 'z' => 2]], schema(int_schema('a'), int_schema('z'))), + 'Rows do not match their schema: column "z" (row 0) is not declared by the schema', ]; yield 'null under not-null' => [ schema(str_schema('a')), - array_to_row(['a' => null], schema(int_schema('a', nullable: true))), + array_to_rows([['a' => null]], schema(int_schema('a', nullable: true))), 'column "a" (row 0): could not convert null to string, column is not nullable', ]; yield 'missing not-null column' => [ schema(int_schema('a'), int_schema('b')), - array_to_row(['a' => 1], schema(int_schema('a'))), + array_to_rows([['a' => 1]], schema(int_schema('a'))), 'Rows do not match their schema: column "b" (row 0) declared by the schema is missing from the row', ]; yield 'unknown column' => [ schema(int_schema('a')), - array_to_row(['a' => 1, 'b' => 2], schema(int_schema('a'), int_schema('b'))), + array_to_rows([['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b'))), 'Rows do not match their schema: column "b" (row 0) is not declared by the schema', ]; yield 'any column against schema()' => [ schema(), - array_to_row(['a' => 1], schema(int_schema('a'))), + array_to_rows([['a' => 1]], schema(int_schema('a'))), 'Rows do not match their schema: column "a" (row 0) is not declared by the schema', ]; yield 'same names, third value wrong' => [ schema(int_schema('a'), str_schema('b'), str_schema('c')), - array_to_row(['a' => 1, 'b' => 'x', 'c' => 3], schema(int_schema('a'), str_schema('b'), int_schema('c'))), + array_to_rows( + [['a' => 1, 'b' => 'x', 'c' => 3]], + schema(int_schema('a'), str_schema('b'), int_schema('c')), + ), 'Rows do not match their schema: column "c" (row 0): could not convert 3 (integer) to string', ]; yield 'reordered, wrong type' => [ schema(int_schema('a'), int_schema('b')), - array_to_row(['b' => 'x', 'a' => 1], schema(str_schema('b'), int_schema('a'))), + array_to_rows([['b' => 'x', 'a' => 1]], schema(str_schema('b'), int_schema('a'))), 'Rows do not match their schema: column "b" (row 0): could not convert \'x\' (string) to integer', ]; yield 'null under not-null datetime' => [ schema(datetime_schema('at')), - array_to_row(['at' => null], schema(str_schema('at', nullable: true))), + array_to_rows([['at' => null]], schema(str_schema('at', nullable: true))), 'column "at" (row 0): could not convert null to datetime, column is not nullable', ]; yield 'string in a datetime column' => [ schema(datetime_schema('at')), - array_to_row(['at' => '2026-01-02 03:04:05'], schema(str_schema('at'))), + array_to_rows([['at' => '2026-01-02 03:04:05']], schema(str_schema('at'))), 'column "at" (row 0): could not convert \'2026-01-02 03:04:05\' (string) to datetime', ]; } - #[DataProvider('from_rows_refusals')] - public function test_from_rows_refuses(Schema $schema, Row $row, string $message): void + #[DataProvider('match_to_refusals')] + public function test_match_to_refuses(Schema $schema, Rows $rows, string $message): void { $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage($message); - rows($schema, $row); + $rows->matchTo($schema); } public function test_from_rows_refuses_null_under_not_null_in_row_1(): void @@ -1162,40 +1120,19 @@ public function test_from_rows_refuses_null_under_not_null_in_row_1(): void array_to_rows([['id' => 1], ['id' => null]], schema(int_schema('id'))); } - public function test_from_rows_gathers_views_of_one_batch_whose_schema_is_same(): void - { - $schema = schema(int_schema('id')); - $batch = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], $schema); - - static::assertSame([['id' => 3], ['id' => 1]], rows($schema, $batch->row(2), $batch->row(0))->toArray()); - } - - public function test_from_rows_copies_views_of_two_batches_with_the_same_schema(): void - { - $schema = schema(int_schema('id')); - $constant = Rows::fromColumns($schema, ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], 2); - $scalar = array_to_rows([['id' => 1], ['id' => 2]], $schema); - - $copied = rows($schema, $scalar->row(1), $constant->row(0), $scalar->row(0)); - - static::assertSame([['id' => 2], ['id' => 7], ['id' => 1]], $copied->toArray()); - static::assertInstanceOf( - (new DefaultBackend()) - ->builder(int_schema('id')) - ->finish()::class, - $copied->column('id'), - ); - } - public function test_from_rows_reorders_and_hops_into_the_column_zone(): void { static::assertSame( '2026-01-02 04:04:05 Europe/Warsaw', type_datetime() - ->assert(array_to_rows( - [['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), 'id' => 1]], - schema(int_schema('id'), datetime_schema('at', zone: 'Europe/Warsaw')), - )->first()->get('at')) + ->assert( + array_to_rows( + [['at' => new DateTimeImmutable('2026-01-02 03:04:05', new DateTimeZone('UTC')), 'id' => 1]], + schema(int_schema('id'), datetime_schema('at', zone: 'Europe/Warsaw')), + ) + ->column('at') + ->value(0), + ) ->format('Y-m-d H:i:s e'), ); } @@ -1319,6 +1256,40 @@ public function test_with_columns_beside_a_constant_column(): void ); } + public function test_empty_has_one_empty_column_per_definition(): void + { + $rows = Rows::empty(schema(int_schema('id'), str_schema('name', nullable: true))); + + static::assertSame(0, $rows->count()); + static::assertSame(['id', 'name'], array_keys($rows->columns())); + static::assertSame(0, $rows->column('name')->count()); + static::assertEquals(schema(int_schema('id'), str_schema('name', nullable: true)), $rows->schema()); + } + + public function test_empty_of_an_empty_schema(): void + { + static::assertSame([], Rows::empty(schema())->columns()); + } + + public function test_from_columns_refuses_an_untyped_column(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage('column "id": mixed cannot be a batch column'); + + Rows::fromColumns(schema(int_schema('id')), ['id' => new ValueColumn([1])], 1); + } + + public function test_with_columns_refuses_an_untyped_column(): void + { + $this->expectException(ColumnMismatchException::class); + $this->expectExceptionMessage('column "n": mixed cannot be a batch column'); + + array_to_rows([['id' => 1]], schema(int_schema('id')))->withColumns( + schema(int_schema('id'), int_schema('n')), + ['n' => new ValueColumn([1])], + ); + } + public function test_with_columns_refuses_a_column_of_another_count(): void { $this->expectException(InvalidArgumentException::class); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/SameSchemasTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/SameSchemasTest.php new file mode 100644 index 0000000000..f942687696 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/SameSchemasTest.php @@ -0,0 +1,28 @@ +isSame(schema(int_schema('id'), str_schema('name'))); + + static::assertTrue(type_instance_of(Schema::class)->assert(unserialize(serialize($schema)))->isSame($schema)); + } + + public function test_a_schema_proved_the_same_stays_the_same_and_another_stays_different(): void + { + $schema = schema(int_schema('id'), str_schema('name')); + $same = schema(int_schema('id'), str_schema('name')); + $other = schema(int_schema('id'), str_schema('name', nullable: true)); + + static::assertTrue($schema->isSame($same)); + static::assertTrue($schema->isSame($same)); + static::assertFalse($schema->isSame($other)); + static::assertFalse($schema->isSame($other)); + } + public static function provide_add_after_reference_inputs(): Generator { yield 'string reference' => ['id']; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ExternalSortTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ExternalSortTest.php new file mode 100644 index 0000000000..926d175619 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ExternalSortTest.php @@ -0,0 +1,307 @@ + [$seed]; + } + } + + public function test_data_under_the_limit_sorts_with_zero_spills(): void + { + $storage = new RecordingBucketsStorage(new MemoryBuckets()); + + static::assertSame( + [1, 2, 3, 4, 5], + IdRows::ids(ExternalSortMother::inMemory(refs('id'), $storage)->sort( + IdRows::batches([4, 2], [5], [1, 3]), + flow_context(config()), + )), + ); + static::assertSame([], $storage->appended); + static::assertSame([], $storage->read); + } + + public function test_data_under_the_limit_is_emitted_in_batches_of_the_configured_size(): void + { + $batches = iterator_to_array( + ExternalSortMother::inMemory(refs('id'), batchSize: 2)->sort( + IdRows::batches([5, 4, 3], [2, 1]), + flow_context(config()), + ), + false, + ); + + static::assertSame([2, 2, 1], array_map(static fn(Rows $rows): int => $rows->count(), $batches)); + } + + public function test_data_over_the_limit_spills_and_merges(): void + { + $storage = new SpyBucketsStorage(new MemoryBuckets()); + + static::assertSame( + [0, 1, 2, 3, 10, 11, 12, 13], + IdRows::ids(ExternalSortMother::spilling(refs('id'), $storage)->sort( + IdRows::batches([10, 0], [11, 1], [2, 12], [13, 3]), + flow_context(config()), + )), + ); + static::assertCount(4, array_filter($storage->readBucketIds(), static fn(string $id): bool => str_starts_with( + $id, + 'sort-', + ))); + static::assertSame([], $storage->liveBucketIds()); + } + + public function test_descending_single_column(): void + { + static::assertSame( + [4, 3, 2, 1], + IdRows::ids(ExternalSortMother::spilling(refs(ref('id')->desc()))->sort( + IdRows::batches([3, 1], [4, 2]), + flow_context(config()), + )), + ); + } + + public function test_sorts_by_multiple_columns(): void + { + $input = (static function (): Generator { + yield array_to_rows([['a' => 1, 'b' => 2], ['a' => 1, 'b' => 1]], schema(int_schema('a'), int_schema('b'))); + yield array_to_rows([['a' => 0, 'b' => 5], ['a' => 0, 'b' => 3]], schema(int_schema('a'), int_schema('b'))); + })(); + + $sorted = rows(schema(int_schema('a'), int_schema('b'))); + + foreach (ExternalSortMother::spilling(refs('a', 'b'))->sort($input, flow_context(config())) as $batch) { + $sorted = $sorted->concat($batch); + } + + static::assertSame( + [['a' => 0, 'b' => 3], ['a' => 0, 'b' => 5], ['a' => 1, 'b' => 1], ['a' => 1, 'b' => 2]], + $sorted->toArray(), + ); + } + + public function test_empty_input_yields_nothing_and_writes_nothing(): void + { + $storage = new RecordingBucketsStorage(new MemoryBuckets()); + + static::assertSame( + [], + IdRows::ids(ExternalSortMother::spilling(refs('id'), $storage)->sort( + IdRows::batches([], []), + flow_context(config()), + )), + ); + static::assertSame([], $storage->appended); + } + + public function test_runs_past_the_fan_in_are_reduced_to_merged_runs_first(): void + { + $storage = new RecordingBucketsStorage(new MemoryBuckets()); + + static::assertSame( + range(0, 19), + IdRows::ids(ExternalSortMother::spilling(refs('id'), $storage, mergeFanIn: 2)->sort( + IdRows::batches(...array_map(static fn(int $i): array => [($i * 2) + 1, $i * 2], range(9, 0))), + flow_context(config()), + )), + ); + static::assertNotSame([], array_filter($storage->appended, static fn(string $id): bool => str_starts_with( + $id, + 'sort-merge-', + ))); + } + + public function test_merged_runs_go_to_the_merge_storage(): void + { + $spill = new RecordingBucketsStorage(new MemoryBuckets()); + $merge = new RecordingBucketsStorage(new MemoryBuckets()); + + IdRows::ids(ExternalSortMother::with(refs('id'), $spill, Unit::fromBytes(1), 2, mergeStorage: $merge)->sort( + IdRows::batches([3], [2], [1]), + flow_context(config()), + )); + + static::assertSame([], array_filter($spill->appended, static fn(string $id): bool => str_starts_with( + $id, + 'sort-merge-', + ))); + static::assertNotSame([], $merge->appended); + } + + public function test_a_limit_under_the_memory_limit_keeps_the_first_rows(): void + { + static::assertSame( + [1, 2], + IdRows::ids(ExternalSortMother::inMemory(refs('id'))->sort( + IdRows::batches([4, 2], [5], [1, 3]), + flow_context(config()), + 2, + )), + ); + } + + public function test_a_limit_over_the_memory_limit_stops_every_merge_at_the_limit(): void + { + $storage = new SpyBucketsStorage(new MemoryBuckets()); + + static::assertSame( + [0, 1, 2], + IdRows::ids(ExternalSortMother::spilling(refs('id'), $storage, mergeFanIn: 2)->sort( + IdRows::batches(...array_map(static fn(int $i): array => [$i + 10, $i], range(9, 0))), + flow_context(config()), + 3, + )), + ); + + $merged = array_filter( + $storage->appendedRows(), + static fn(string $id): bool => str_starts_with($id, 'sort-merge-'), + ARRAY_FILTER_USE_KEY, + ); + + static::assertNotSame([], $merged); + + foreach ($merged as $batches) { + static::assertLessThanOrEqual( + 3, + array_sum(array_map(static fn(Rows $rows): int => $rows->count(), $batches)), + ); + } + } + + #[DataProvider('random_datasets')] + public function test_spilled_sort_equals_one_in_memory_sort(int $seed): void + { + $dataset = SortDatasetMother::random($seed); + $input = (static function () use ($dataset): Generator { + foreach ($dataset['runs'] as $rows) { + yield array_to_rows($rows, $dataset['schema']); + } + })(); + + $sorted = rows($dataset['schema']); + + foreach (ExternalSortMother::spilling( + refs(...$dataset['references']), + mergeFanIn: 2, + batchSize: $dataset['mergeBatchSize'], + )->sort($input, flow_context(config())) as $batch) { + $sorted = $sorted->concat($batch->matchTo($dataset['schema'])); + } + + // serialized, so NaN and -0.0 compare by what they are + static::assertSame( + serialize( + array_to_rows(array_merge(...$dataset['runs']), $dataset['schema']) + ->sortBy(...$dataset['references']) + ->toArray(), + ), + serialize($sorted->toArray()), + ); + } + + public function test_both_storages_are_cleared_when_the_first_clear_throws(): void + { + $spillStorage = new SpyBucketsStorage(new MemoryBuckets()); + $mergeStorage = new SpyBucketsStorage(new MemoryBuckets()); + $spill = new Buckets(new ThrowingRemoveBucketsStorage($spillStorage)); + $merge = new Buckets($mergeStorage); + + // the upstream throws during the drain, so reduce() never writes a merged run - seed one, or the + // merge-side assertion is true whether or not the nested finally ran + $mergeStorage->append('pre-existing', array_to_rows([['id' => 1]], schema(int_schema('id')))); + $merge->add(new Bucket('pre-existing', 1, 0)); + + $sort = new ExternalSort( + refs('id'), + $spill, + $merge, + new NativePHPRandomValueGenerator(), + Unit::fromBytes(1), + 2, + ); + + $upstream = (static function (): Generator { + yield from IdRows::batches([9, 8], [7, 6]); + + throw new RuntimeException('upstream failed'); + })(); + + try { + iterator_to_array($sort->sort($upstream, flow_context(config())), false); + static::fail('The upstream failure must escape.'); + } catch (RuntimeException $escaped) { + static::assertSame('spill clear failed', $escaped->getMessage()); + + $previous = $escaped->getPrevious(); + + static::assertInstanceOf(RuntimeException::class, $previous); + static::assertSame('upstream failed', $previous->getMessage()); + } + + static::assertSame([], $mergeStorage->liveBucketIds()); + } + + public function test_throws_when_batch_size_below_one(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); + + // @mago-ignore analysis:invalid-argument + ExternalSortMother::with(refs('id'), new MemoryBuckets(), Unit::fromGb(1), 10, 0); + } + + public function test_throws_when_merge_fan_in_below_one(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Merge fan-in must be greater than 0, given: 0'); + + // @mago-ignore analysis:invalid-argument + ExternalSortMother::with(refs('id'), new MemoryBuckets(), Unit::fromGb(1), 0); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php index 303b2e8c7d..9a831f572c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php @@ -4,12 +4,19 @@ namespace Flow\ETL\Tests\Unit\Sort\Merge; +use DateTimeImmutable; +use DateTimeZone; use Flow\ETL\Sort\Merge\BucketCursor; +use Flow\ETL\Sort\RowOrder; +use Flow\ETL\Sort\SortKey; use Flow\ETL\Tests\FlowTestCase; use Generator; +use function array_map; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; @@ -22,13 +29,13 @@ public function test_iterates_rows_across_batch_boundaries(): void yield array_to_rows([['id' => 3]], schema(int_schema('id'))); }; - $cursor = new BucketCursor($batches()); + $cursor = new BucketCursor($batches(), new RowOrder([ref('id')])); $ids = []; while ($cursor->valid()) { - $ids[] = $cursor->current()->get('id'); - $cursor->next(); + $ids[] = $cursor->batch()->column('id')->value($cursor->index()); + $cursor->advance($cursor->index() + 1); } static::assertSame([1, 2, 3], $ids); @@ -40,7 +47,7 @@ public function test_empty_batch_stream_is_invalid_from_the_start(): void yield from []; }; - static::assertFalse((new BucketCursor($batches()))->valid()); + static::assertFalse((new BucketCursor($batches(), new RowOrder([ref('id')])))->valid()); } public function test_skips_empty_batches(): void @@ -52,13 +59,13 @@ public function test_skips_empty_batches(): void yield array_to_rows([['id' => 2]], schema(int_schema('id'))); }; - $cursor = new BucketCursor($batches()); + $cursor = new BucketCursor($batches(), new RowOrder([ref('id')])); $ids = []; while ($cursor->valid()) { - $ids[] = $cursor->current()->get('id'); - $cursor->next(); + $ids[] = $cursor->batch()->column('id')->value($cursor->index()); + $cursor->advance($cursor->index() + 1); } static::assertSame([1, 2], $ids); @@ -72,18 +79,19 @@ public function test_next_batch_is_not_decoded_until_the_current_one_is_exhauste }; $generator = $batches(); - $cursor = new BucketCursor($generator); + $cursor = new BucketCursor($generator, new RowOrder([ref('id')])); static::assertSame(0, $generator->key()); - $cursor->next(); + $cursor->advance(1); static::assertSame(0, $generator->key()); - $cursor->next(); + $cursor->advance(2); static::assertSame(1, $generator->key()); - static::assertSame(3, $cursor->current()->get('id')); + static::assertSame(0, $cursor->index()); + static::assertSame([['id' => 3]], $cursor->batch()->toArray()); } public function test_stream_of_only_empty_batches_is_invalid(): void @@ -93,6 +101,33 @@ public function test_stream_of_only_empty_batches_is_invalid(): void yield rows(schema()); }; - static::assertFalse((new BucketCursor($batches()))->valid()); + static::assertFalse((new BucketCursor($batches(), new RowOrder([ref('id')])))->valid()); + } + + public function test_keys_are_the_sort_keys_of_every_ref_in_order(): void + { + $batches = static function (): Generator { + yield array_to_rows( + [['id' => 2, 'at' => new DateTimeImmutable('1970-01-01 00:00:01', new DateTimeZone('UTC'))]], + schema(int_schema('id'), datetime_schema('at')), + ); + }; + + $cursor = new BucketCursor($batches(), new RowOrder([ref('at'), ref('id')])); + + static::assertSame( + [[1_000_000], [2]], + array_map(static fn(SortKey $key): array => $key->values, $cursor->keys()), + ); + static::assertEquals(schema(int_schema('id'), datetime_schema('at')), $cursor->schema()); + } + + public function test_schema_of_an_empty_stream_is_empty(): void + { + $batches = static function (): Generator { + yield from []; + }; + + static::assertEquals(schema(), (new BucketCursor($batches(), new RowOrder([ref('id')])))->schema()); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php index df3147f866..9d20a27514 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php @@ -7,23 +7,70 @@ use Flow\ETL\Bucketing\BucketRun; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; -use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Constraint\SortedByConstraint; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Row; use Flow\ETL\Sort\Merge\KWayMerge; use Flow\ETL\Tests\Context\BucketsStorageContext; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\SortDatasetMother; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; -use function array_map; +use function array_chunk; +use function array_merge; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\refs; +use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function serialize; final class KWayMergeTest extends FlowTestCase { + public static function random_datasets(): Generator + { + for ($seed = 1; $seed <= 200; $seed++) { + yield "seed {$seed}" => [$seed]; + } + } + + #[DataProvider('random_datasets')] + public function test_merging_sorted_runs_equals_one_in_memory_sort(int $seed): void + { + $dataset = SortDatasetMother::random($seed); + $buckets = new Buckets(new MemoryBuckets()); + $runs = []; + + foreach ($dataset['runs'] as $run => $rows) { + foreach (array_to_rows($rows, $dataset['schema']) + ->sortBy(...$dataset['references']) + ->chunks($dataset['storedBatchSize']) as $batch) { + $buckets->storage()->append("run-{$run}", $batch); + } + + $runs[] = new BucketRun("run-{$run}", $buckets); + } + + $merged = rows($dataset['schema']); + + foreach ((new KWayMerge(refs(...$dataset['references']), $dataset['mergeBatchSize']))->merge($runs) as $batch) { + $merged = $merged->concat($batch->matchTo($dataset['schema'])); + } + + // serialized, so NaN and -0.0 compare by what they are + static::assertSame( + serialize( + array_to_rows(array_merge(...$dataset['runs']), $dataset['schema']) + ->sortBy(...$dataset['references']) + ->toArray(), + ), + serialize($merged->toArray()), + ); + static::assertNull((new SortedByConstraint(...$dataset['references']))->firstViolation($merged)); + } + public function test_merges_multiple_sorted_runs_ascending(): void { $buckets = new Buckets(new MemoryBuckets()); @@ -43,13 +90,18 @@ public function test_merges_multiple_sorted_runs_ascending(): void ['id' => 9], ], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); + $merge = new KWayMerge(refs(ref('id')->asc())); static::assertSame( [1, 2, 3, 4, 5, 6, 7, 8, 9], - array_map(static fn(Row $r): mixed => $r->get( + array_column( + BucketsStorageContext::rows($merge->merge([ + new BucketRun('a', $buckets), + new BucketRun('b', $buckets), + new BucketRun('c', $buckets), + ])), 'id', - ), BucketsStorageContext::rows($merge->merge([new BucketRun('a', $buckets), new BucketRun('b', $buckets), new BucketRun('c', $buckets)]))), + ), ); } @@ -65,16 +117,17 @@ public function test_merge_reads_each_run_through_its_own_storage(): void static::assertSame([], BucketsStorageContext::rows($spill->storage()->get('sort-merge-0'))); static::assertSame([], BucketsStorageContext::rows($merged->storage()->get('sort-run-0'))); - $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); + $merge = new KWayMerge(refs(ref('id')->asc())); static::assertSame( [1, 2, 3, 4], - array_map(static fn(Row $r): mixed => $r->get( + array_column( + BucketsStorageContext::rows($merge->merge([ + new BucketRun('sort-run-0', $spill), + new BucketRun('sort-merge-0', $merged), + ])), 'id', - ), BucketsStorageContext::rows($merge->merge([ - new BucketRun('sort-run-0', $spill), - new BucketRun('sort-merge-0', $merged), - ]))), + ), ); } @@ -92,13 +145,17 @@ public function test_merges_multiple_sorted_runs_descending(): void ['id' => 2], ], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->desc()), new PhpBackend()); + $merge = new KWayMerge(refs(ref('id')->desc())); static::assertSame( [8, 7, 5, 4, 2, 1], - array_map(static fn(Row $r): mixed => $r->get( + array_column( + BucketsStorageContext::rows($merge->merge([ + new BucketRun('a', $buckets), + new BucketRun('b', $buckets), + ])), 'id', - ), BucketsStorageContext::rows($merge->merge([new BucketRun('a', $buckets), new BucketRun('b', $buckets)]))), + ), ); } @@ -112,13 +169,17 @@ public function test_merges_runs_of_uneven_length(): void ], schema(int_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 4]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); + $merge = new KWayMerge(refs(ref('id')->asc())); static::assertSame( [1, 2, 3, 4], - array_map(static fn(Row $r): mixed => $r->get( + array_column( + BucketsStorageContext::rows($merge->merge([ + new BucketRun('a', $buckets), + new BucketRun('b', $buckets), + ])), 'id', - ), BucketsStorageContext::rows($merge->merge([new BucketRun('a', $buckets), new BucketRun('b', $buckets)]))), + ), ); } @@ -128,13 +189,17 @@ public function test_merges_non_numeric_values(): void $buckets->storage()->append('a', array_to_rows([['id' => 'a'], ['id' => 'c']], schema(str_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 'b'], ['id' => 'd']], schema(str_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); + $merge = new KWayMerge(refs(ref('id')->asc())); static::assertSame( ['a', 'b', 'c', 'd'], - array_map(static fn(Row $r): mixed => $r->get( + array_column( + BucketsStorageContext::rows($merge->merge([ + new BucketRun('a', $buckets), + new BucketRun('b', $buckets), + ])), 'id', - ), BucketsStorageContext::rows($merge->merge([new BucketRun('a', $buckets), new BucketRun('b', $buckets)]))), + ), ); } @@ -147,17 +212,14 @@ public function test_runs_under_different_schemas_are_conformed_to_the_first(): )); $buckets->storage()->append('b', array_to_rows([['id' => 2]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); + $merge = new KWayMerge(refs(ref('id')->asc())); static::assertSame( [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null]], - array_map( - static fn(Row $r): array => $r->toArray(), - BucketsStorageContext::rows($merge->merge([ - new BucketRun('a', $buckets), - new BucketRun('b', $buckets), - ])), - ), + BucketsStorageContext::rows($merge->merge([ + new BucketRun('a', $buckets), + new BucketRun('b', $buckets), + ])), ); } @@ -166,19 +228,17 @@ public function test_single_run_passthrough(): void $buckets = new Buckets(new MemoryBuckets()); $buckets->storage()->append('a', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); + $merge = new KWayMerge(refs(ref('id')->asc())); static::assertSame( [1, 2], - array_map(static fn(Row $r): mixed => $r->get( - 'id', - ), BucketsStorageContext::rows($merge->merge([new BucketRun('a', $buckets)]))), + array_column(BucketsStorageContext::rows($merge->merge([new BucketRun('a', $buckets)])), 'id'), ); } public function test_empty_bucket_set_yields_nothing(): void { - $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend()); + $merge = new KWayMerge(refs(ref('id')->asc())); static::assertSame([], BucketsStorageContext::rows($merge->merge([]))); } @@ -193,7 +253,7 @@ public function test_merged_rows_are_yielded_in_batches_of_batch_size(): void ], schema(int_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 2], ['id' => 4]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc()), new PhpBackend(), batchSize: 2); + $merge = new KWayMerge(refs(ref('id')->asc()), batchSize: 2); $sizes = []; @@ -210,6 +270,42 @@ public function test_throws_when_batch_size_below_one(): void $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); // @mago-ignore analysis:invalid-argument - new KWayMerge(refs(ref('id')->asc()), new PhpBackend(), batchSize: 0); + new KWayMerge(refs(ref('id')->asc()), batchSize: 0); + } + + public function test_interleaves_runs_across_batch_boundaries_like_one_sort(): void + { + $buckets = new Buckets(new MemoryBuckets()); + $all = []; + + foreach (['a' => [2, 0], 'b' => [3, 1], 'c' => [5, 2]] as $run => [$batchSize, $offset]) { + $rows = []; + + for ($i = 0; $i < 10; $i++) { + $rows[] = ['id' => ($i * 3) + $offset, 'run' => $run]; + } + + $all = [...$all, ...$rows]; + + foreach (array_chunk($rows, $batchSize) as $chunk) { + $buckets->storage()->append($run, array_to_rows($chunk, schema(int_schema('id'), str_schema('run')))); + } + } + + $merged = []; + + foreach ((new KWayMerge(refs(ref('id')->asc()), batchSize: 4))->merge([ + new BucketRun('a', $buckets), + new BucketRun('b', $buckets), + new BucketRun('c', $buckets), + ]) as $batch) { + static::assertLessThanOrEqual(4, $batch->count()); + $merged = [...$merged, ...$batch->toArray()]; + } + + static::assertSame( + array_to_rows($all, schema(int_schema('id'), str_schema('run')))->sortBy(ref('id')->asc())->toArray(), + $merged, + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/RowsMinHeapTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/RowsMinHeapTest.php deleted file mode 100644 index 1f1f0d7b55..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/RowsMinHeapTest.php +++ /dev/null @@ -1,116 +0,0 @@ -asc()); - - $minHeap->push(array_to_row(['id' => 1], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 2], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 3], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 4], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 5], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 6], schema(int_schema('id'))), 'cache_id'); - - static::assertEquals( - [ - ['id' => 1], - ['id' => 2], - ['id' => 3], - ['id' => 4], - ['id' => 5], - ['id' => 6], - ], - array_map(static fn() => $minHeap->extract()->row->toArray(), range(1, count($minHeap))), - ); - } - - public function test_min_heap_desc(): void - { - $minHeap = new RowsMinHeap(ref('id')->desc()); - - $minHeap->push(array_to_row(['id' => 1], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 2], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 3], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 4], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 5], schema(int_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 6], schema(int_schema('id'))), 'cache_id'); - - static::assertEquals( - [ - ['id' => 6], - ['id' => 5], - ['id' => 4], - ['id' => 3], - ['id' => 2], - ['id' => 1], - ], - array_map(static fn() => $minHeap->extract()->row->toArray(), range(1, count($minHeap))), - ); - } - - public function test_min_heap_on_non_numeric_values(): void - { - $minHeap = new RowsMinHeap(ref('id')->asc()); - - $minHeap->push(array_to_row(['id' => 'a'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'b'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'c'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'd'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'e'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'f'], schema(str_schema('id'))), 'cache_id'); - - static::assertEquals( - [ - ['id' => 'a'], - ['id' => 'b'], - ['id' => 'c'], - ['id' => 'd'], - ['id' => 'e'], - ['id' => 'f'], - ], - array_map(static fn() => $minHeap->extract()->row->toArray(), range(1, count($minHeap))), - ); - } - - public function test_min_heap_on_non_numeric_values_desc(): void - { - $minHeap = new RowsMinHeap(ref('id')->desc()); - - $minHeap->push(array_to_row(['id' => 'a'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'b'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'c'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'd'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'e'], schema(str_schema('id'))), 'cache_id'); - $minHeap->push(array_to_row(['id' => 'f'], schema(str_schema('id'))), 'cache_id'); - - static::assertEquals( - [ - ['id' => 'f'], - ['id' => 'e'], - ['id' => 'd'], - ['id' => 'c'], - ['id' => 'b'], - ['id' => 'a'], - ], - array_map(static fn() => $minHeap->extract()->row->toArray(), range(1, count($minHeap))), - ); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/RowOrderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/RowOrderTest.php new file mode 100644 index 0000000000..87592fcaca --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/RowOrderTest.php @@ -0,0 +1,258 @@ + 3], ['v' => null], ['v' => -1], ['v' => null]], schema(int_schema('v', true))); + $ascending = new RowOrder([ref('v')->asc()]); + $descending = new RowOrder([ref('v')->desc()]); + + static::assertSame([1, 3, 2, 0], $ascending->permutation($ascending->keys($rows), 4)); + static::assertSame([0, 2, 1, 3], $descending->permutation($descending->keys($rows), 4)); + } + + public function test_nan_sorts_after_every_value_and_ties_with_nan(): void + { + $rows = array_to_rows([ + ['v' => 1.0], + ['v' => NAN], + ['v' => -1.0], + ['v' => NAN], + ['v' => null], + ], schema(float_schema('v', true))); + $ascending = new RowOrder([ref('v')->asc()]); + $descending = new RowOrder([ref('v')->desc()]); + + static::assertSame([4, 2, 0, 1, 3], $ascending->permutation($ascending->keys($rows), 5)); + static::assertSame([1, 3, 0, 2, 4], $descending->permutation($descending->keys($rows), 5)); + static::assertSame(0, $ascending->compare($ascending->keys($rows), 1, $ascending->keys($rows), 3)); + } + + public function test_negative_zero_ties_with_zero(): void + { + $rows = array_to_rows([['v' => 0.0], ['v' => -0.0], ['v' => 0.0]], schema(float_schema('v'))); + $order = new RowOrder([ref('v')->desc()]); + + static::assertSame([0, 1, 2], $order->permutation($order->keys($rows), 3)); + } + + public function test_strings_compare_by_bytes_never_as_numbers(): void + { + $rows = array_to_rows([ + ['v' => '9'], + ['v' => '10'], + ['v' => 'a'], + ['v' => 'B'], + ['v' => ''], + ['v' => '09'], + ['v' => '100'], + ], schema(str_schema('v'))); + $order = new RowOrder([ref('v')->asc()]); + + static::assertSame( + ['', '09', '10', '100', '9', 'B', 'a'], + $rows + ->gather($order->permutation($order->keys($rows), 7)) + ->column('v') + ->values(), + ); + } + + public function test_false_sorts_before_true(): void + { + $rows = array_to_rows([['v' => true], ['v' => false], ['v' => null]], schema(bool_schema('v', true))); + $order = new RowOrder([ref('v')->asc()]); + + static::assertSame([2, 1, 0], $order->permutation($order->keys($rows), 3)); + } + + public function test_datetimes_sort_by_instant_whatever_their_zone(): void + { + $rows = array_to_rows([ + ['v' => new DateTimeImmutable('2026-01-01 02:00:00', new DateTimeZone('Europe/Warsaw'))], + ['v' => new DateTimeImmutable('2026-01-01 00:30:00', new DateTimeZone('UTC'))], + ['v' => new DateTimeImmutable('2026-01-01 01:00:00', new DateTimeZone('UTC'))], + ], schema(datetime_schema('v'))); + $order = new RowOrder([ref('v')->asc()]); + + static::assertSame([1, 0, 2], $order->permutation($order->keys($rows), 3)); + } + + public function test_dates_sort_by_day_and_times_by_duration(): void + { + $rows = array_to_rows( + [ + ['d' => new DateTimeImmutable('2026-03-01'), 't' => new DateInterval('PT2H')], + ['d' => new DateTimeImmutable('1969-12-31'), 't' => new DateInterval('PT90M')], + ['d' => new DateTimeImmutable('2026-02-28'), 't' => new DateInterval('PT1H30M1S')], + ], + schema(date_schema('d'), time_schema('t')), + ); + $byDay = new RowOrder([ref('d')->asc()]); + $byDuration = new RowOrder([ref('t')->asc()]); + + static::assertSame([1, 2, 0], $byDay->permutation($byDay->keys($rows), 3)); + static::assertSame([1, 2, 0], $byDuration->permutation($byDuration->keys($rows), 3)); + } + + public function test_values_without_an_order_tie_and_keep_their_input_order(): void + { + $rows = array_to_rows([ + ['v' => Uuid::fromString('00000000-0000-4000-8000-000000000002')], + ['v' => Uuid::fromString('00000000-0000-4000-8000-000000000001')], + ], schema(uuid_schema('v'))); + $order = new RowOrder([ref('v')->asc()]); + + static::assertSame([0, 1], $order->permutation($order->keys($rows), 2)); + } + + public function test_later_keys_break_ties_in_their_own_direction(): void + { + $rows = array_to_rows( + [['a' => 1, 'b' => 'x'], ['a' => 2, 'b' => 'y'], ['a' => 1, 'b' => 'y'], ['a' => 2, 'b' => 'x']], + schema(int_schema('a'), str_schema('b')), + ); + $order = new RowOrder([ref('a')->desc(), ref('b')->asc()]); + + static::assertSame([3, 1, 0, 2], $order->permutation($order->keys($rows), 4)); + } + + public function test_rows_equal_on_every_key_keep_their_input_order(): void + { + $rows = array_to_rows([['v' => 1], ['v' => 1], ['v' => 0], ['v' => 1]], schema(int_schema('v'))); + $order = new RowOrder([ref('v')->desc()]); + + static::assertSame([0, 1, 3, 2], $order->permutation($order->keys($rows), 4)); + } + + public function test_a_batch_of_fewer_than_two_rows_keeps_its_order(): void + { + $order = new RowOrder([ref('v')->asc()]); + + static::assertSame([], $order->permutation($order->keys(array_to_rows([], schema(int_schema('v')))), 0)); + static::assertSame( + [0], + $order->permutation($order->keys(array_to_rows([['v' => 1]], schema(int_schema('v')))), 1), + ); + } + + public function test_first_after_finds_the_first_row_past_the_bound(): void + { + $rows = array_to_rows([['v' => 1], ['v' => 2], ['v' => 2], ['v' => 3]], schema(int_schema('v'))); + $bound = array_to_rows([['v' => 2]], schema(int_schema('v'))); + $order = new RowOrder([ref('v')->asc()]); + $keys = $order->keys($rows); + + static::assertSame(3, $order->firstAfter($keys, 0, 4, $order->keys($bound), 0, true)); + static::assertSame(1, $order->firstAfter($keys, 0, 4, $order->keys($bound), 0, false)); + static::assertSame(3, $order->firstAfter($keys, 3, 4, $order->keys($bound), 0, false)); + } + + public function test_compare_agrees_with_the_permutation(): void + { + for ($seed = 1; $seed <= 50; $seed++) { + $dataset = SortDatasetMother::random($seed); + $rows = array_to_rows(array_merge(...$dataset['runs']), $dataset['schema']); + $order = new RowOrder($dataset['references']); + $keys = $order->keys($rows); + $permutation = $order->permutation($keys, $rows->count()); + + for ($i = 1; $i < $rows->count(); $i++) { + $comparison = $order->compare($keys, $permutation[$i - 1], $keys, $permutation[$i]); + + static::assertTrue( + $comparison < 0 || $comparison === 0 && $permutation[$i - 1] < $permutation[$i], + "seed {$seed}, position {$i}", + ); + } + } + } + + public function test_the_explicit_default_placement_orders_like_the_implicit_one(): void + { + $rows = array_to_rows([ + ['v' => 1.0], + ['v' => null], + ['v' => NAN], + ['v' => -1.0], + ], schema(float_schema('v', true))); + + foreach ([ + [ref('v')->asc(NullsOrder::FIRST), ref('v')->asc()], + [ref('v')->desc(NullsOrder::LAST), ref('v')->desc()], + ] as [$explicit, $implicit]) { + $explicitOrder = new RowOrder([$explicit]); + $implicitOrder = new RowOrder([$implicit]); + + static::assertSame( + $implicitOrder->permutation($implicitOrder->keys($rows), 4), + $explicitOrder->permutation($explicitOrder->keys($rows), 4), + ); + } + + $ascending = new RowOrder([ref('v')->asc(NullsOrder::FIRST)]); + $descending = new RowOrder([ref('v')->desc(NullsOrder::LAST)]); + + static::assertSame([1, 3, 0, 2], $ascending->permutation($ascending->keys($rows), 4)); + static::assertSame([2, 0, 3, 1], $descending->permutation($descending->keys($rows), 4)); + } + + public function test_a_reference_moves_nulls_to_the_other_end(): void + { + $rows = array_to_rows([ + ['v' => 1.0], + ['v' => null], + ['v' => NAN], + ['v' => -1.0], + ], schema(float_schema('v', true))); + $ascendingLast = new RowOrder([ref('v')->asc(NullsOrder::LAST)]); + $descendingFirst = new RowOrder([ref('v')->desc(NullsOrder::FIRST)]); + + static::assertSame([3, 0, 2, 1], $ascendingLast->permutation($ascendingLast->keys($rows), 4)); + static::assertSame([1, 2, 0, 3], $descendingFirst->permutation($descendingFirst->keys($rows), 4)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/SortStepsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/SortStepsTest.php index db9f2dd4dc..965062cf70 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/SortStepsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/SortStepsTest.php @@ -5,16 +5,16 @@ namespace Flow\ETL\Tests\Unit\Sort; use Flow\ETL\Bucketing\Storage\MemoryBuckets; -use Flow\ETL\Processor\BucketingProcessor; +use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Processor\MemorySortProcessor; use Flow\ETL\Processor\MergeSortProcessor; +use Flow\ETL\Sort\ExternalSort; use Flow\ETL\Sort\SortSteps; use Flow\ETL\Tests\Double\RecordingBucketsStorage; use Flow\ETL\Tests\FlowTestCase; use Generator; use function array_filter; -use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\config_builder; @@ -31,16 +31,36 @@ final class SortStepsTest extends FlowTestCase { - public function test_external_sort_config_builds_bucketing_and_merge_processors(): void + public function test_external_sort_config_builds_one_merge_sort_processor(): void { $steps = SortSteps::of( refs(ref('id')), config_builder()->sort(external_sort()->storage(new MemoryBuckets()))->build(), ); - static::assertCount(2, $steps); - static::assertInstanceOf(BucketingProcessor::class, $steps[0]); - static::assertInstanceOf(MergeSortProcessor::class, $steps[1]); + static::assertCount(1, $steps); + static::assertInstanceOf(MergeSortProcessor::class, $steps[0]); + } + + public function test_external_carries_the_configured_memory_limit(): void + { + $sort = SortSteps::external( + refs(ref('id')), + config_builder()->sort(external_sort()->memoryLimit(Unit::fromMb(3)))->build(), + ); + + static::assertInstanceOf(ExternalSort::class, $sort); + static::assertSame(Unit::fromMb(3)->inBytes(), $sort->memoryLimit->inBytes()); + } + + public function test_external_is_null_for_the_memory_sort(): void + { + static::assertNull(SortSteps::external(refs(ref('id')), config_builder()->sort(memory_sort())->build())); + } + + public function test_pinned_algorithm_wins_over_configuration(): void + { + static::assertNull(SortSteps::external(refs(ref('id')), config_builder()->build(), memory_sort())); } public function test_external_sort_resolves_both_phases_over_the_same_storage_by_default(): void @@ -50,21 +70,21 @@ public function test_external_sort_resolves_both_phases_over_the_same_storage_by $steps = SortSteps::of( refs(ref('id')), - config_builder()->sort(external_sort()->storage($spill)->runSize(1)->bucketsCount(2))->build(), + config_builder() + ->sort(external_sort()->storage($spill)->memoryLimit(Unit::fromBytes(1))->bucketsCount(2)) + ->build(), ); $context = flow_context(config()); $input = (static function (): Generator { - yield array_to_rows( - array_map(static fn(int $i): array => ['id' => $i], range(9, 0)), - schema(int_schema('id')), - ); + foreach (range(9, 0) as $i) { + yield array_to_rows([['id' => $i]], schema(int_schema('id'))); + } })(); - static::assertInstanceOf(BucketingProcessor::class, $steps[0]); - static::assertInstanceOf(MergeSortProcessor::class, $steps[1]); + static::assertInstanceOf(MergeSortProcessor::class, $steps[0]); - iterator_to_array($steps[1]->process($steps[0]->process($input, $context), $context), false); + iterator_to_array($steps[0]->process($input, $context), false); static::assertNotSame([], array_filter($spill->appended, static fn(string $id): bool => str_starts_with( $id, @@ -80,21 +100,26 @@ public function test_external_sort_routes_merged_runs_to_the_merge_storage_when_ $steps = SortSteps::of( refs(ref('id')), config_builder() - ->sort(external_sort()->storage($spill)->mergeStorage($merge)->runSize(1)->bucketsCount(2)) + ->sort( + external_sort() + ->storage($spill) + ->mergeStorage($merge) + ->memoryLimit(Unit::fromBytes(1)) + ->bucketsCount(2), + ) ->build(), ); $context = flow_context(config()); $input = (static function (): Generator { - yield array_to_rows( - array_map(static fn(int $i): array => ['id' => $i], range(9, 0)), - schema(int_schema('id')), - ); + foreach (range(9, 0) as $i) { + yield array_to_rows([['id' => $i]], schema(int_schema('id'))); + } })(); - static::assertInstanceOf(MergeSortProcessor::class, $steps[1]); + static::assertInstanceOf(MergeSortProcessor::class, $steps[0]); - iterator_to_array($steps[1]->process($steps[0]->process($input, $context), $context), false); + iterator_to_array($steps[0]->process($input, $context), false); static::assertSame([], array_filter($spill->appended, static fn(string $id): bool => str_starts_with( $id, @@ -110,9 +135,8 @@ public function test_external_sort_is_the_default(): void { $steps = SortSteps::of(refs(ref('id')), config_builder()->build()); - static::assertCount(2, $steps); - static::assertInstanceOf(BucketingProcessor::class, $steps[0]); - static::assertInstanceOf(MergeSortProcessor::class, $steps[1]); + static::assertCount(1, $steps); + static::assertInstanceOf(MergeSortProcessor::class, $steps[0]); } public function test_memory_sort_config_builds_a_memory_sort_processor(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ValuesSorterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ValuesSorterTest.php deleted file mode 100644 index 94fcc05d30..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ValuesSorterTest.php +++ /dev/null @@ -1,105 +0,0 @@ -value(int_schema('a'), '5', 0)); + $column = ColumnMother::of(int_schema('a', nullable: true), [1, 2]); + $backend = new SpyBackend(); + + $stored = (new DerivedColumns())->stored(int_schema('a'), $column, $backend); + + static::assertSame([1, 2], $stored->values()); + static::assertSame(1, $backend->adopts()); } - public function test_value_keeps_null_under_a_nullable_definition(): void + public function test_stored_rebuilds_a_column_of_another_type(): void { - static::assertNull((new DerivedColumns())->value(int_schema('a', nullable: true), null, 0)); + $stored = (new DerivedColumns())->stored( + int_schema('a'), + ColumnMother::of(str_schema('a'), ['5', '6']), + new PhpBackend(), + ); + + static::assertSame([5, 6], $stored->values()); + } + + public function test_stored_rebuilds_an_untyped_column(): void + { + static::assertSame( + [5, null], + (new DerivedColumns()) + ->stored(int_schema('a', nullable: true), new ValueColumn(['5', null]), new PhpBackend()) + ->values(), + ); + } + + public function test_stored_keeps_null_under_a_nullable_definition(): void + { + static::assertSame( + [null], + (new DerivedColumns()) + ->stored( + int_schema('a', nullable: true), + ColumnMother::of(int_schema('a', nullable: true), [null]), + new PhpBackend(), + ) + ->values(), + ); } - public function test_value_names_the_row_of_a_null_under_a_not_null_definition(): void + public function test_stored_names_the_row_of_a_null_under_a_not_null_definition(): void { $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage( 'Rows do not match their schema: column "a" (row 3): could not convert null to integer, column is not nullable', ); - (new DerivedColumns())->value(int_schema('a'), null, 3); + (new DerivedColumns())->stored(int_schema('a'), ColumnMother::of(int_schema('a', nullable: true), [ + 1, + 2, + 3, + null, + ]), new PhpBackend()); } public function test_rows_adds_the_derived_column_under_the_output_schema(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php index d4b74ede62..fb702dfef7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php @@ -310,7 +310,7 @@ public function test_an_unbound_transform_refuses_an_expand_in_an_entry(): void ); (new DuplicateRowTransformer(lit(true), with_entry('t', ref('tags')->expand())))->transform( - rows(ListColumnsMother::schema(), ListColumnsMother::row()), + ListColumnsMother::rows()->matchTo(ListColumnsMother::schema()), flow_context(config()), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/NestedExpansionTest.php index a7be86f8b1d9ab0f75a5c918f6c5cfb55aebb4a3..5c8562525f4c5160376d727333c626f6ec7e6e1e 100644 GIT binary patch delta 453 zcmca=`p$C0T}H;@$%;%en}0G!v2Yh_sN|QW78PZtq)z@QF2x*e7`wTgjh{EDSRuZT7{%(K%9bRiLuJ(~)O8fpD?vn+I+C(jkolX>2~S}LS{fa# zo(nc?@$#vp}lh=vIf-IlREupKK3UpCrd}>Z=Zfaghd|qO1YH@r?MrwRfetCRm zNqllXNFc2!KXT*JoCtEUmIo>!V%tgc{drx0zZqhJ)Pqo7`r zm<|first()->names()); + static::assertSame(['x', 'b'], array_keys($renamed->values(0))); static::assertSame([['x' => 1, 'b' => 2]], $renamed->toArray()); } @@ -112,7 +112,7 @@ public function test_renaming_entry_preserves_metadata(): void 'old_name' => 'test value', ]], schema(string_schema('old_name', metadata: $metadata))), flow_context(config())); - static::assertSame('test value', $outputRows->first()->get('new_name')); + static::assertSame('test value', $outputRows->column('new_name')->value(0)); static::assertTrue($outputRows->schema()->get('new_name')->metadata()->isEqual($metadata)); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformer/MathTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformer/MathTest.php index 3c4a0a435b..f81e061c54 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformer/MathTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformer/MathTest.php @@ -51,7 +51,7 @@ public static function minus_data_provider(): Generator 0.3, float_schema('b'), 0.1, - ['result' => 0.2, 'a' => 0.3, 'b' => 0.1], + ['result' => 0.19999999999999998, 'a' => 0.3, 'b' => 0.1], ]; yield [ @@ -67,7 +67,7 @@ public static function minus_data_provider(): Generator 0.3, float_schema('b'), 0.1, - ['result' => 0.2, 'a' => 0.3_0000_0000_0000_000, 'b' => 0.1_0000_0000_0000_000], + ['result' => 0.19999999999999998, 'a' => 0.3_0000_0000_0000_000, 'b' => 0.1_0000_0000_0000_000], ]; } @@ -97,7 +97,7 @@ public static function plus_data_provider(): Generator 0.3, float_schema('b'), -0.1, - ['result' => 0.2, 'a' => 0.3, 'b' => -0.1], + ['result' => 0.19999999999999998, 'a' => 0.3, 'b' => -0.1], ]; yield [ @@ -124,7 +124,7 @@ public static function power_data_provider(): Generator -0.3, integer_schema('b'), 10, - ['result' => 5.9049E-6, 'a' => -0.3, 'b' => 10], + ['result' => 5.9048999999999975E-6, 'a' => -0.3, 'b' => 10], ]; } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php index aeebde0603..2d0b327bac 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php @@ -195,7 +195,7 @@ public function test_xml_xpath_expression_when_there_is_more_than_one_node_under 'xml' => type_xml()->cast($xml), ]], schema(xml_schema('xml'))), flow_context(config())); - static::assertEquals($expected, $result->first()->get('xpath')); + static::assertEquals($expected, $result->column('xpath')->value(0)); static::assertEquals(type_list(type_xml_element()), $result->schema()->get('xpath')->type()); static::assertTrue($result->schema()->get('xpath')->isNullable()); } @@ -421,7 +421,7 @@ public function test_an_unbound_expand_inside_an_expand_is_refused(): void ); (new ScalarFunctionTransformer('v', ref('lists')->expand()->expand()))->transform( - rows(ListColumnsMother::schema(), ListColumnsMother::row()), + ListColumnsMother::rows()->matchTo(ListColumnsMother::schema()), flow_context(config()), ); } @@ -434,4 +434,36 @@ public function test_bind_refuses_an_unpack_whose_type_is_not_a_structure(): voi (new ScalarFunctionTransformer('u', new NonStructureUnpackStub()))->bind(schema()); } + + public function test_an_expand_explodes_every_row_of_the_batch_in_order(): void + { + $rows = array_to_rows( + [['id' => 1, 'list' => [1, 2]], ['id' => 2, 'list' => []], ['id' => 3, 'list' => [3]]], + schema(int_schema('id'), list_schema('list', type_list(type_integer()))), + ); + + static::assertSame( + [['id' => 1, 'value' => 1], ['id' => 1, 'value' => 2], ['id' => 3, 'value' => 3]], + (new ScalarFunctionTransformer('value', ref('list')->expand())) + ->transform($rows, flow_context()) + ->project(schema(int_schema('id'), int_schema('value'))) + ->toArray(), + ); + } + + public function test_an_unpack_fills_one_column_per_declared_element_for_every_row(): void + { + $rows = array_to_rows([ + ['s' => ['a' => 1, 'b' => 'x']], + ['s' => ['a' => 2, 'b' => null]], + ], schema(structure_schema('s', type_structure(['a' => type_integer(), 'b' => type_optional(type_string())])))); + + static::assertSame( + [['s.a' => 1, 's.b' => 'x'], ['s.a' => 2, 's.b' => null]], + (new ScalarFunctionTransformer('s', ref('s')->unpack(schema(int_schema('a'), str_schema('b'))))) + ->transform($rows, flow_context()) + ->project(schema(int_schema('s.a', nullable: true), str_schema('s.b', nullable: true))) + ->toArray(), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php index 8c1ac29a63..8aa15cf0e8 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php @@ -4,17 +4,17 @@ namespace Flow\ETL\Tests\Unit\Transformer; +use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\SerializeTransformer; use Flow\Floe\FloeSerializer; use Flow\Serializer\Base64Serializer; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Serializer\DSL\serialize_to_string; @@ -52,7 +52,7 @@ public function test_bind_replaces_the_target_column_with_a_string_column(): voi public function test_serializing_empty_row_under_one_entry(): void { - $rows = rows($rowSchema = schema(), $row1 = array_to_row([], schema())); + $rows = Rows::fromColumns(schema(), [], 1); $transformer = new SerializeTransformer('serialized'); $transformedRows = $transformer->transform($rows, flow_context()); @@ -60,10 +60,7 @@ public function test_serializing_empty_row_under_one_entry(): void static::assertEquals( [ [ - 'serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row1), - ), + 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows), ], ], $transformedRows->toArray(), @@ -78,27 +75,10 @@ public function test_serializing_row_under_one_entry(): void bool_schema('active'), list_schema('tags', type_list(type_string())), ); - $rows = rows( - $rowSchema, - $row1 = array_to_row( - ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], - schema( - int_schema('id'), - str_schema('name'), - bool_schema('active'), - list_schema('tags', type_list(type_string())), - ), - ), - $row2 = array_to_row( - ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], - schema( - int_schema('id'), - str_schema('name'), - bool_schema('active'), - list_schema('tags', type_list(type_string())), - ), - ), - ); + $rows = array_to_rows([ + ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], + ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], + ], $rowSchema); $transformer = new SerializeTransformer('serialized'); @@ -111,20 +91,14 @@ public function test_serializing_row_under_one_entry(): void 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2'], - 'serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row1), - ), + 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows->slice(0, 1)), ], [ 'id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4'], - 'serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row2), - ), + 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows->slice(1, 1)), ], ], $transformedRows->toArray(), @@ -139,27 +113,10 @@ public function test_serializing_row_under_standalone_entry(): void bool_schema('active'), list_schema('tags', type_list(type_string())), ); - $rows = rows( - $rowSchema, - $row1 = array_to_row( - ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], - schema( - int_schema('id'), - str_schema('name'), - bool_schema('active'), - list_schema('tags', type_list(type_string())), - ), - ), - $row2 = array_to_row( - ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], - schema( - int_schema('id'), - str_schema('name'), - bool_schema('active'), - list_schema('tags', type_list(type_string())), - ), - ), - ); + $rows = array_to_rows([ + ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], + ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], + ], $rowSchema); $transformer = new SerializeTransformer('serialized', true); @@ -168,16 +125,10 @@ public function test_serializing_row_under_standalone_entry(): void static::assertEquals( [ [ - 'serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row1), - ), + 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows->slice(0, 1)), ], [ - 'serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row2), - ), + 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows->slice(1, 1)), ], ], $transformedRows->toArray(), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php index c95ea41611..19de37e805 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php @@ -9,7 +9,6 @@ use Flow\Floe\FloeSerializer; use Flow\Serializer\Base64Serializer; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -27,40 +26,40 @@ public function test_a_multi_row_payload_gives_up(): void ], schema(int_schema('id')))); static::assertSame( - [], + [[]], SerializedPayloadDecoderTest::decoder() - ->decode(array_to_row(['serialized' => $payload], schema(str_schema('serialized')))) - ->values(), + ->decode(array_to_rows([['serialized' => $payload]], schema(str_schema('serialized'))), 0) + ->toArray(), ); } public function test_a_non_string_value_gives_up(): void { static::assertSame( - [], + [[]], SerializedPayloadDecoderTest::decoder() - ->decode(array_to_row(['serialized' => 123], schema(int_schema('serialized')))) - ->values(), + ->decode(array_to_rows([['serialized' => 123]], schema(int_schema('serialized'))), 0) + ->toArray(), ); } public function test_a_payload_that_does_not_deserialize_gives_up(): void { static::assertSame( - [], + [[]], SerializedPayloadDecoderTest::decoder() - ->decode(array_to_row(['serialized' => 'not-serialized'], schema(str_schema('serialized')))) - ->values(), + ->decode(array_to_rows([['serialized' => 'not-serialized']], schema(str_schema('serialized'))), 0) + ->toArray(), ); } public function test_a_row_without_the_source_column_gives_up(): void { static::assertSame( - [], + [[]], SerializedPayloadDecoderTest::decoder() - ->decode(array_to_row(['other' => 1], schema(int_schema('other')))) - ->values(), + ->decode(array_to_rows([['other' => 1]], schema(int_schema('other'))), 0) + ->toArray(), ); } @@ -71,10 +70,13 @@ public function test_it_reads_the_declared_columns_out_of_the_payload(): void ]], schema(int_schema('id')))); static::assertSame( - ['id' => 7], + [['id' => 7]], SerializedPayloadDecoderTest::decoder() - ->decode(array_to_row(['serialized' => $payload], schema(str_schema('serialized')))) - ->values(), + ->decode(array_to_rows([ + ['serialized' => 'not-serialized'], + ['serialized' => $payload], + ], schema(str_schema('serialized'))), 1) + ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php index c0ec0a81fa..53fde0bee6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php @@ -10,13 +10,11 @@ use Flow\Floe\FloeSerializer; use Flow\Serializer\Base64Serializer; -use function Flow\ETL\DSL\array_to_row; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\list_schema; -use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; use function Flow\Serializer\DSL\serialize_to_string; @@ -81,34 +79,20 @@ public function test_bind_without_merging_keeps_only_the_declared_target(): void public function test_unserializing_row_from_entry(): void { - $row1 = array_to_row( - ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], - schema( - int_schema('id'), - str_schema('name'), - bool_schema('active'), - list_schema('tags', type_list(type_string())), - ), - ); $rowSchema = schema( int_schema('id'), str_schema('name'), bool_schema('active'), list_schema('tags', type_list(type_string())), ); - $row2 = array_to_row( + $source = array_to_rows([ + ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], - schema( - int_schema('id'), - str_schema('name'), - bool_schema('active'), - list_schema('tags', type_list(type_string())), - ), - ); + ], $rowSchema); $rows = array_to_rows([ - ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), rows($rowSchema, $row1))], - ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), rows($rowSchema, $row2))], + ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $source->slice(0, 1))], + ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $source->slice(1, 1))], ], schema(str_schema('serialized'))); $transformer = new UnserializeTransformer('serialized', $rowSchema); @@ -120,7 +104,7 @@ public function test_unserializing_row_from_entry(): void [ 'serialized' => serialize_to_string( new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row1), + $source->slice(0, 1), ), 'id' => 1, 'name' => 'John', @@ -130,7 +114,7 @@ public function test_unserializing_row_from_entry(): void [ 'serialized' => serialize_to_string( new Base64Serializer(new FloeSerializer()), - rows($rowSchema, $row2), + $source->slice(1, 1), ), 'id' => 2, 'name' => 'Jane', @@ -211,34 +195,20 @@ public function test_the_declared_columns_land_under_the_merge_prefix(): void public function test_unserializing_without_merge(): void { - $row1 = array_to_row( - ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], - schema( - int_schema('id'), - str_schema('name'), - bool_schema('active'), - list_schema('tags', type_list(type_string())), - ), - ); $rowSchema = schema( int_schema('id'), str_schema('name'), bool_schema('active'), list_schema('tags', type_list(type_string())), ); - $row2 = array_to_row( + $source = array_to_rows([ + ['id' => 1, 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2']], ['id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4']], - schema( - int_schema('id'), - str_schema('name'), - bool_schema('active'), - list_schema('tags', type_list(type_string())), - ), - ); + ], $rowSchema); $rows = array_to_rows([ - ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), rows($rowSchema, $row1))], - ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), rows($rowSchema, $row2))], + ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $source->slice(0, 1))], + ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $source->slice(1, 1))], ], schema(str_schema('serialized'))); $transformer = new UnserializeTransformer('serialized', $rowSchema, false); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/AverageAccumulatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/AverageAccumulatorTest.php index 69ae0029bc..81d0cde6b1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/AverageAccumulatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/AverageAccumulatorTest.php @@ -9,7 +9,7 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Window\Accumulator\AverageAccumulator; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -20,17 +20,19 @@ final class AverageAccumulatorTest extends FlowTestCase { public function test_averages_accumulated_values(): void { - $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()); + $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 20], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 10]], schema(int_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => 20]], schema(int_schema('value'))), 0); static::assertSame(15.0, $accumulator->value()); } public function test_empty_frame_averages_to_null(): void { - static::assertNull((new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()))->value()); + static::assertNull( + (new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, false, flow_context()))->value(), + ); } public function test_missing_entry_throws_in_strict_mode(): void @@ -39,52 +41,52 @@ public function test_missing_entry_throws_in_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessageMatches('/^Average window function error: /'); - (new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, $context))->accumulate(array_to_row([ + (new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, false, $context))->accumulate(array_to_rows([[ 'other' => 'x', - ], schema(str_schema('other')))); + ]], schema(str_schema('other'))), 0); } public function test_non_numeric_values_are_skipped(): void { - $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()); + $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 'not a number'], schema(str_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => null], schema(str_schema('value', nullable: true)))); - $accumulator->accumulate(array_to_row(['value' => 20], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 10]], schema(int_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => 'not a number']], schema(str_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => null]], schema(str_schema('value', nullable: true))), 0); + $accumulator->accumulate(array_to_rows([['value' => 20]], schema(int_schema('value'))), 0); static::assertSame(15.0, $accumulator->value()); } public function test_only_null_values_still_average_to_null(): void { - $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()); + $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => null], schema(str_schema('value', nullable: true)))); + $accumulator->accumulate(array_to_rows([['value' => null]], schema(str_schema('value', nullable: true))), 0); static::assertNull($accumulator->value()); } public function test_scale_and_rounding_are_applied(): void { - $accumulator = new AverageAccumulator(ref('value'), 3, Rounding::HALF_UP, flow_context()); + $accumulator = new AverageAccumulator(ref('value'), 3, Rounding::HALF_UP, false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 20], schema(int_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 25], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 10]], schema(int_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => 20]], schema(int_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => 25]], schema(int_schema('value'))), 0); static::assertSame(18.333, $accumulator->value()); } public function test_value_is_idempotent(): void { - $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); + $accumulator = new AverageAccumulator(ref('value'), 2, Rounding::HALF_UP, false, flow_context()); + $accumulator->accumulate(array_to_rows([['value' => 10]], schema(int_schema('value'))), 0); static::assertSame(10.0, $accumulator->value()); static::assertSame(10.0, $accumulator->value()); - $accumulator->accumulate(array_to_row(['value' => 20], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 20]], schema(int_schema('value'))), 0); static::assertSame(15.0, $accumulator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/CountAccumulatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/CountAccumulatorTest.php index 1d377f3d26..1dd10b00d7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/CountAccumulatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/CountAccumulatorTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Window\Accumulator\CountAccumulator; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; @@ -21,8 +21,8 @@ public function test_counts_every_row_when_reference_is_null(): void { $accumulator = new CountAccumulator(null, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 1], schema(int_schema('value')))); - $accumulator->accumulate(array_to_row(['other' => 'x'], schema(str_schema('other')))); + $accumulator->accumulate(array_to_rows([['value' => 1]], schema(int_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['other' => 'x']], schema(str_schema('other'))), 0); static::assertSame(2, $accumulator->value()); } @@ -31,9 +31,9 @@ public function test_counts_only_non_null_values(): void { $accumulator = new CountAccumulator(ref('value'), flow_context()); - $accumulator->accumulate(array_to_row(['value' => 1], schema(int_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => null], schema(int_schema('value', nullable: true)))); - $accumulator->accumulate(array_to_row(['value' => 3], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 1]], schema(int_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => null]], schema(int_schema('value', nullable: true))), 0); + $accumulator->accumulate(array_to_rows([['value' => 3]], schema(int_schema('value'))), 0); static::assertSame(2, $accumulator->value()); } @@ -54,20 +54,20 @@ public function test_missing_entry_throws_in_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessageMatches('/^Count window function error: /'); - (new CountAccumulator(ref('value'), $context))->accumulate(array_to_row([ + (new CountAccumulator(ref('value'), $context))->accumulate(array_to_rows([[ 'other' => 'x', - ], schema(str_schema('other')))); + ]], schema(str_schema('other'))), 0); } public function test_value_is_idempotent(): void { $accumulator = new CountAccumulator(ref('value'), flow_context()); - $accumulator->accumulate(array_to_row(['value' => 1], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 1]], schema(int_schema('value'))), 0); static::assertSame(1, $accumulator->value()); static::assertSame(1, $accumulator->value()); - $accumulator->accumulate(array_to_row(['value' => 2], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 2]], schema(int_schema('value'))), 0); static::assertSame(2, $accumulator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/SumAccumulatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/SumAccumulatorTest.php index 2b66e26b8c..2b38dc1fd5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/SumAccumulatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/Accumulator/SumAccumulatorTest.php @@ -8,11 +8,10 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Window\Accumulator\SumAccumulator; -use function Flow\ETL\DSL\array_to_row; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; -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; @@ -24,22 +23,12 @@ public function test_empty_frame_sums_to_null(): void static::assertNull((new SumAccumulator(ref('value'), false, flow_context()))->value()); } - public function test_exact_as_scalar_function_is_resolved_per_row(): void - { - $accumulator = new SumAccumulator(ref('value'), lit(true), flow_context()); - - $accumulator->accumulate(array_to_row(['value' => 0.1], schema(float_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 0.2], schema(float_schema('value')))); - - static::assertSame(0.3, $accumulator->value()); - } - public function test_exact_sum_avoids_floating_point_drift(): void { $accumulator = new SumAccumulator(ref('value'), true, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 0.1], schema(float_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 0.2], schema(float_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 0.1]], schema(float_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => 0.2]], schema(float_schema('value'))), 0); static::assertSame(0.3, $accumulator->value()); } @@ -48,8 +37,8 @@ public function test_inexact_sum_keeps_native_addition(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 0.1], schema(float_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 0.2], schema(float_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 0.1]], schema(float_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => 0.2]], schema(float_schema('value'))), 0); static::assertSame(0.1 + 0.2, $accumulator->value()); } @@ -60,19 +49,19 @@ public function test_missing_entry_throws_in_strict_mode(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessageMatches('/^Sum window function error: /'); - (new SumAccumulator(ref('value'), false, $context))->accumulate(array_to_row([ + (new SumAccumulator(ref('value'), false, $context))->accumulate(array_to_rows([[ 'other' => 'x', - ], schema(str_schema('other')))); + ]], schema(str_schema('other'))), 0); } public function test_non_numeric_values_are_skipped(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 'not a number'], schema(str_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => null], schema(str_schema('value', nullable: true)))); - $accumulator->accumulate(array_to_row(['value' => 5], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 10]], schema(int_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => 'not a number']], schema(str_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => null]], schema(str_schema('value', nullable: true))), 0); + $accumulator->accumulate(array_to_rows([['value' => 5]], schema(int_schema('value'))), 0); static::assertSame(15, $accumulator->value()); } @@ -81,8 +70,8 @@ public function test_numeric_strings_are_summed(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => '10'], schema(str_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => '2.5'], schema(str_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => '10']], schema(str_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => '2.5']], schema(str_schema('value'))), 0); static::assertSame(12.5, $accumulator->value()); } @@ -91,7 +80,7 @@ public function test_only_non_numeric_values_still_sums_to_null(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => null], schema(str_schema('value', nullable: true)))); + $accumulator->accumulate(array_to_rows([['value' => null]], schema(str_schema('value', nullable: true))), 0); static::assertNull($accumulator->value()); } @@ -99,12 +88,12 @@ public function test_only_non_numeric_values_still_sums_to_null(): void public function test_value_is_idempotent(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 10], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 10]], schema(int_schema('value'))), 0); static::assertSame(10, $accumulator->value()); static::assertSame(10, $accumulator->value()); - $accumulator->accumulate(array_to_row(['value' => 5], schema(int_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 5]], schema(int_schema('value'))), 0); static::assertSame(15, $accumulator->value()); } @@ -113,8 +102,8 @@ public function test_whole_float_result_stays_float(): void { $accumulator = new SumAccumulator(ref('value'), false, flow_context()); - $accumulator->accumulate(array_to_row(['value' => 1.5], schema(float_schema('value')))); - $accumulator->accumulate(array_to_row(['value' => 2.5], schema(float_schema('value')))); + $accumulator->accumulate(array_to_rows([['value' => 1.5]], schema(float_schema('value'))), 0); + $accumulator->accumulate(array_to_rows([['value' => 2.5]], schema(float_schema('value'))), 0); static::assertSame(4.0, $accumulator->value()); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerComparatorTest.php new file mode 100644 index 0000000000..39a37736e7 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerComparatorTest.php @@ -0,0 +1,92 @@ + new DateTimeImmutable('2024-01-01 01:00:00', new DateTimeZone('+01:00')), 'n' => 1], + ['at' => new DateTimeImmutable('2024-01-01 00:00:00', new DateTimeZone('UTC')), 'n' => 1], + ['at' => new DateTimeImmutable('2024-01-01 00:00:00', new DateTimeZone('UTC')), 'n' => 2], + ], + schema(datetime_schema('at'), int_schema('n')), + ); + static::assertSame( + [false, true, false], + (new PeerComparator([ref('at'), ref('n')]))->peersOfPrevious($partition), + ); + } + + public function test_nan_is_a_peer_of_nan(): void + { + $partition = array_to_rows([['v' => NAN], ['v' => NAN], ['v' => 1.0]], schema(float_schema('v'))); + static::assertSame([false, true, false], (new PeerComparator([ref('v')]))->peersOfPrevious($partition)); + } + + public function test_peers_of_previous_marks_each_row_against_the_row_before_it(): void + { + $partition = array_to_rows( + [ + ['at' => new DateTimeImmutable('2024-01-01 01:00:00', new DateTimeZone('+01:00')), 'n' => 1], + ['at' => new DateTimeImmutable('2024-01-01 00:00:00', new DateTimeZone('UTC')), 'n' => 1], + ['at' => new DateTimeImmutable('2024-01-01 00:00:00', new DateTimeZone('UTC')), 'n' => 2], + ], + schema(datetime_schema('at'), int_schema('n')), + ); + + static::assertSame( + [false, true, false], + (new PeerComparator([ref('at'), ref('n')]))->peersOfPrevious($partition), + ); + } + + public function test_peers_of_previous_treats_nan_as_a_peer_of_nan(): void + { + static::assertSame( + [false, true, false], + (new PeerComparator([ref('v')]))->peersOfPrevious(array_to_rows([ + ['v' => NAN], + ['v' => NAN], + ['v' => 1.0], + ], schema(float_schema('v')))), + ); + static::assertSame( + [], + (new PeerComparator([ref('v')]))->peersOfPrevious(array_to_rows([], schema(float_schema('v')))), + ); + } + + public function test_peers_of_previous_compares_values_without_a_physical_order(): void + { + static::assertSame( + [false, true, false], + (new PeerComparator([ref('l')]))->peersOfPrevious(array_to_rows([ + ['l' => [1, 2]], + ['l' => [1, 2]], + ['l' => [2]], + ], schema(list_schema('l', type_list(type_integer()))))), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerFrameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerFrameTest.php index 65ebcd9851..c753640480 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerFrameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerFrameTest.php @@ -4,10 +4,14 @@ namespace Flow\ETL\Tests\Unit\Window; +use ArrayObject; use DateTimeImmutable; +use Flow\ETL\Rows; +use Flow\ETL\Tests\Double\SpyColumn; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Window\PeerFrame; +use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; @@ -15,6 +19,8 @@ use function Flow\ETL\DSL\rows; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function intdiv; +use function range; final class PeerFrameTest extends FlowTestCase { @@ -29,6 +35,26 @@ public function test_all_rows_tied_covers_the_whole_partition(): void static::assertSame([0, 2], $frame->bounds(2, $partition)); } + public function test_the_partition_is_read_once_for_every_row_of_it(): void + { + $calls = new ArrayObject(); + $schema = schema(int_schema('v')); + $column = array_to_rows( + array_map(static fn(int $i): array => ['v' => intdiv($i, 10)], range(0, 49)), + $schema, + )->column('v'); + $partition = Rows::fromColumns($schema, ['v' => new SpyColumn($column, $calls)], 50); + $frame = new PeerFrame([ref('v')]); + $ends = []; + + for ($index = 0; $index < 50; $index++) { + $ends[] = $frame->bounds($index, $partition)[1]; + } + + static::assertSame(array_map(static fn(int $i): int => (intdiv($i, 10) * 10) + 9, range(0, 49)), $ends); + static::assertCount(1, $calls); + } + public function test_datetime_peers_are_matched_by_value_not_identity(): void { $partition = array_to_rows([ diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/WindowContextTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/WindowContextTest.php index 9513f61655..166f837171 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/WindowContextTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/WindowContextTest.php @@ -22,7 +22,16 @@ public function test_accessors_return_what_was_passed_in(): void static::assertSame(2, $context->index()); static::assertSame($partition, $context->partition()); - static::assertSame($partition[2]->values(), $context->row()->values()); + } + + public function test_frame_is_the_slice_of_the_partition_between_the_bounds(): void + { + static::assertSame( + [['id' => 2], ['id' => 3], ['id' => 4]], + WindowContextMother::atIndex(RowsMother::sequentialIds(5), 3, new RowsFrame(preceding(2), current_row())) + ->frame() + ->toArray(), + ); } public function test_empty_bounds_produce_an_empty_frame(): void @@ -67,8 +76,8 @@ public function test_frame_is_sliced_according_to_the_window_frame(): void )->frame(); static::assertCount(3, $frame); - static::assertSame(2, $frame[0]->get('id')); - static::assertSame(3, $frame[1]->get('id')); - static::assertSame(4, $frame[2]->get('id')); + static::assertSame(2, $frame->column('id')->value(0)); + static::assertSame(3, $frame->column('id')->value(1)); + static::assertSame(4, $frame->column('id')->value(2)); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php index 90254104c4..fd3a732f11 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php @@ -107,15 +107,13 @@ public static function frameTypes(Filesystem $filesystem, Path $path): array public static function reconstruct(Filesystem $filesystem, Path $path): Rows { $file = (new FloeReader($filesystem))->read($path); - $rows = []; + $rows = rows($file->footer()->schema()); foreach ($file->rows() as $batch) { - foreach ($batch->all() as $row) { - $rows[] = $row; - } + $rows = $rows->concat($batch->matchTo($file->footer()->schema())); } - return rows($file->footer()->schema(), ...$rows); + return $rows; } /** diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php index 4ded8fe3e9..4841f06e93 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeDataFrameTest.php @@ -86,8 +86,8 @@ public function test_a_timezone_column_round_trips_through_floe(): void $names = []; - foreach ($read as $row) { - $names[] = type_instance_of(DateTimeZone::class)->assert($row->get('tz'))->getName(); + foreach ($read->toArray() as $row) { + $names[] = type_instance_of(DateTimeZone::class)->assert($row['tz'])->getName(); } static::assertSame(['Europe/Warsaw', 'UTC'], $names); @@ -113,12 +113,14 @@ public function test_inferred_nested_arrays_are_projected_to_json_and_round_trip // column nullable - NOT NULL is a declaration, never an inference. static::assertTrue($rows->schema()->get('body')->isNullable()); - $first = $rows[0]->get('body'); + // @mago-ignore analysis:mixed-assignment + $first = $rows->column('body')->value(0); static::assertIsArray($first); static::assertInstanceOf(Json::class, $first['data']); static::assertSame([1, 'a'], $first['data']->toArray()); - $second = $rows[1]->get('body'); + // @mago-ignore analysis:mixed-assignment + $second = $rows->column('body')->value(1); static::assertIsArray($second); static::assertInstanceOf(Json::class, $second['data']); static::assertSame([], $second['data']->toArray()); @@ -140,7 +142,8 @@ public function test_list_of_json_round_trip(): void static::assertSame('list', $rows->schema()->get('json_list')->type()->toString()); - $list = $rows[0]->get('json_list'); + // @mago-ignore analysis:mixed-assignment + $list = $rows->column('json_list')->value(0); static::assertIsArray($list); static::assertInstanceOf(Json::class, $list[0]); static::assertSame(['a' => 1], $list[0]->toArray()); @@ -165,7 +168,7 @@ public function test_schema_and_extract_agree_in_both_metadata_states(): void static::assertSame( array_keys($extractor->schema()->definitions()), - array_keys(data_frame()->read($extractor)->fetch()->first()->toArray()), + array_keys(data_frame()->read($extractor)->fetch()->toArray()[0]), ); } } @@ -181,7 +184,7 @@ public function test_input_file_uri_is_added_when_configured(): void $rows = data_frame()->read(from_floe($path)->withMetadataColumns(true))->fetch(); - static::assertTrue($rows->first()->has('_input_file_uri')); + static::assertNotNull($rows->schema()->findDefinition('_input_file_uri')); } public function test_offset_and_limit_pushdown(): void @@ -263,7 +266,7 @@ public function test_round_trip(): void $result = data_frame()->read(from_floe($path))->fetch(); static::assertSame(2, $result->count()); - static::assertSame(['id', 'name'], $result->first()->names()); + static::assertSame(['id', 'name'], array_keys($result->values(0))); } public function test_a_close_that_fails_during_closure_leaves_no_file(): void diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php index d5f83e844a..8949aa0432 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php @@ -159,8 +159,8 @@ public function test_a_utc_file_is_rezoned_after_reading(): void ->read(from_floe($path, filesystem: $this->fs())) ->withEntry('at', to_timezone(ref('at'), 'Europe/Warsaw')) ->fetch() - ->first() - ->get('at'), + ->column('at') + ->value(0), ) ->format('Y-m-d H:i:s e'), ); @@ -189,8 +189,9 @@ public function test_two_files_read_in_the_first_footer_zone(): void foreach (df() ->read(from_floe($this->cacheDir->suffix('zones/*.floe'), filesystem: $this->fs())) - ->fetch() as $row) { - $zones[] = type_datetime()->assert($row->get('at'))->getTimezone()->getName(); + ->fetch() + ->toArray() as $row) { + $zones[] = type_datetime()->assert($row['at'])->getTimezone()->getName(); } static::assertSame(['Europe/Warsaw', 'Europe/Warsaw'], $zones); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php index 540e5d4823..4dac191043 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php @@ -60,9 +60,9 @@ public function test_merged_multi_schema_file_reads_seamlessly(): void $read = []; foreach ($reader->rows() as $batch) { - foreach ($batch->all() as $row) { - static::assertSame(['id', 'email'], $row->names()); - $read[] = [$row->get('id'), $row->get('email')]; + foreach ($batch->toArray() as $row) { + static::assertSame(['id', 'email'], array_keys($row)); + $read[] = [$row['id'], $row['email']]; } } @@ -100,8 +100,8 @@ public function test_file_larger_than_compaction_threshold_round_trips(): void foreach ((new FloeReader($this->fs(), chunkSize: 4096)) ->read($path) ->rows(500) as $batch) { - foreach ($batch->all() as $row) { - static::assertSame($read, $row->get('id')); + foreach ($batch->toArray() as $row) { + static::assertSame($read, $row['id']); $read++; } } @@ -126,7 +126,7 @@ public function test_round_trip_of_all_entry_types_through_local_filesystem(): v ); static::assertCount(1, $batches); - static::assertEquals($rows->all(), $batches[0]->all()); + static::assertEquals($rows->toArray(), $batches[0]->toArray()); } public function test_round_trip_of_heterogeneous_rows_through_local_filesystem(): void 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 3488e2906f..6dc5defddd 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeExtractorTest.php @@ -142,7 +142,7 @@ public function test_extract_adds_input_file_uri_when_configured(): void $extractor = from_floe($path, filesystem: $memory)->withMetadataColumns(true); $batches = iterator_to_array($extractor->extract($context)); - static::assertSame($path->uri(), $batches[0]->first()->get('_input_file_uri')); + static::assertSame($path->uri(), $batches[0]->column('_input_file_uri')->value(0)); } public function test_extract_applies_offset_within_a_file(): void @@ -158,8 +158,8 @@ public function test_extract_applies_offset_within_a_file(): void $ids = []; foreach (from_floe($path, filesystem: $memory)->withOffset(1)->extract($context) as $batch) { - foreach ($batch->all() as $extractedRow) { - $ids[] = $extractedRow->get('id'); + foreach ($batch->toArray() as $extractedRow) { + $ids[] = $extractedRow['id']; } } @@ -181,8 +181,8 @@ public function test_extract_honors_limit(): void $ids = []; foreach ($extractor->extract($context, limit: 2) as $batch) { - foreach ($batch->all() as $extractedRow) { - $ids[] = $extractedRow->get('id'); + foreach ($batch->toArray() as $extractedRow) { + $ids[] = $extractedRow['id']; } } @@ -201,7 +201,7 @@ public function test_extract_omits_input_file_uri_by_default(): void $batches = iterator_to_array(from_floe($path, filesystem: $memory)->extract($context)); - static::assertSame(['id'], $batches[0]->first()->names()); + static::assertSame(['id'], array_keys($batches[0]->values(0))); } public function test_extract_reads_rows(): void @@ -217,8 +217,8 @@ public function test_extract_reads_rows(): void $ids = []; foreach (from_floe($path, filesystem: $memory)->extract($context) as $batch) { - foreach ($batch->all() as $extractedRow) { - $ids[] = $extractedRow->get('id'); + foreach ($batch->toArray() as $extractedRow) { + $ids[] = $extractedRow['id']; } } @@ -244,8 +244,8 @@ public function test_extract_skips_whole_files_with_offset(): void foreach (from_floe(path('memory://skip-files/*.floe'), filesystem: $memory) ->withOffset(2) ->extract($context) as $batch) { - foreach ($batch->all() as $extractedRow) { - $ids[] = $extractedRow->get('id'); + foreach ($batch->toArray() as $extractedRow) { + $ids[] = $extractedRow['id']; } } @@ -287,8 +287,8 @@ public function test_extract_yields_the_metadata_column_schema_promises(): void $batches = iterator_to_array($extractor->extract($context)); - static::assertSame($extractor->schema()->references()->names(), $batches[0]->first()->names()); - static::assertSame($path->uri(), $batches[0]->first()->get('_input_file_uri')); + static::assertSame($extractor->schema()->references()->names(), array_keys($batches[0]->values(0))); + static::assertSame($path->uri(), $batches[0]->column('_input_file_uri')->value(0)); } public function test_with_schema_is_refused(): void @@ -362,8 +362,8 @@ public function test_extract_fills_partition_columns_from_the_path(): void $values = []; foreach ($extractor->extract(flow_context(config())) as $rows) { - foreach ($rows as $row) { - $values[] = $row->toArray(); + foreach ($rows->toArray() as $row) { + $values[] = $row; } } @@ -422,7 +422,7 @@ public function test_declared_partition_types_reach_the_rows(): void foreach ($extractor->extract(flow_context(config())) as $rows) { static::assertEquals($extractor->schema(), $rows->schema()); - static::assertSame(2024, $rows->first()->get('year')); + static::assertSame(2024, $rows->column('year')->value(0)); return; } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php index 7979226c90..38ef8670fd 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php @@ -38,8 +38,8 @@ public function test_closure_writes_a_readable_non_torn_file(): void $ids = []; foreach (from_floe($path, filesystem: $memory)->extract($context) as $batch) { - foreach ($batch->all() as $extractedRow) { - $ids[] = $extractedRow->get('id'); + foreach ($batch->toArray() as $extractedRow) { + $ids[] = $extractedRow['id']; } } @@ -109,8 +109,8 @@ public function test_partitioned_batches_write_one_file_per_partition(): void $ids = []; foreach (from_floe(path('memory://parts/**/*.floe'), filesystem: $memory)->extract($context) as $batch) { - foreach ($batch->all() as $extractedRow) { - $ids[] = $extractedRow->get('id'); + foreach ($batch->toArray() as $extractedRow) { + $ids[] = $extractedRow['id']; } } @@ -134,8 +134,8 @@ public function test_repeated_loads_write_a_single_file(): void // reading the concrete (non-pattern) path proves all rows landed in one file foreach (from_floe($path, filesystem: $memory)->extract($context) as $batch) { - foreach ($batch->all() as $extractedRow) { - $ids[] = $extractedRow->get('id'); + foreach ($batch->toArray() as $extractedRow) { + $ids[] = $extractedRow['id']; } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php index 45bff3fe4d..4f74a0598d 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php @@ -311,9 +311,7 @@ public function test_offset_read_after_merge_seeks_across_sources(): void foreach ((new FloeReader($fs)) ->read(path('memory://out.floe')) ->rows(batchSize: 100, offset: 3) as $batch) { - foreach ($batch as $r) { - $read[] = $r->get('id'); - } + $read = [...$read, ...$batch->column('id')->values()]; } static::assertSame([4], $read); @@ -488,8 +486,8 @@ public function test_merge_of_different_datetime_zones_widens_to_utc(): void FloeStreamReaderContext::footer($fs, path('memory://merged.floe'))->schema()->get('at')->type()->toString(), ); static::assertSame([$warsaw->getTimestamp(), $utc->getTimestamp()], [ - type_datetime()->assert($merged->all()[0]->get('at'))->getTimestamp(), - type_datetime()->assert($merged->all()[1]->get('at'))->getTimestamp(), + type_datetime()->assert($merged->column('at')->value(0))->getTimestamp(), + type_datetime()->assert($merged->column('at')->value(1))->getTimestamp(), ]); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php index 12d2e28173..54b997e172 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php @@ -22,7 +22,6 @@ use function array_map; use function array_merge; use function array_slice; -use function count; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -53,7 +52,7 @@ public function test_all_entry_types_round_trip(): void ); static::assertCount(1, $batches); - static::assertEquals($rows->all(), $batches[0]->all()); + static::assertEquals($rows->toArray(), $batches[0]->toArray()); } public function test_batches_follow_requested_size(): void @@ -108,8 +107,8 @@ public function test_limit_caps_returned_rows(): void foreach ((new FloeReader($filesystem)) ->read($path) ->rows(batchSize: 100, offset: 0, limit: 2) as $batch) { - foreach ($batch->all() as $row) { - $ids[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; } } @@ -134,7 +133,7 @@ public function test_limit_stops_within_a_batch(): void ); static::assertCount(1, $batches); - static::assertCount(2, $batches[0]->all()); + static::assertCount(2, $batches[0]); } public function test_negative_offset_throws(): void @@ -189,8 +188,8 @@ public function test_offset_skips_leading_rows_within_a_single_section(): void foreach ((new FloeReader($filesystem)) ->read($path) ->rows(offset: 2) as $batch) { - foreach ($batch->all() as $row) { - $ids[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; } } @@ -226,10 +225,10 @@ public function test_offset_skips_whole_sections(): void foreach ((new FloeReader($filesystem)) ->read($path) ->rows(offset: 4) as $batch) { - foreach ($batch->all() as $row) { - $ids[] = $row->get('id'); - $names[] = $row->names(); - $emails[] = $row->get('email'); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; + $names[] = array_keys($row); + $emails[] = $row['email']; } } @@ -313,8 +312,8 @@ public function test_offset_and_limit_combined(): void foreach ((new FloeReader($filesystem)) ->read($path) ->rows(batchSize: 100, offset: 1, limit: 2) as $batch) { - foreach ($batch->all() as $row) { - $ids[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; } } @@ -347,8 +346,8 @@ public function test_offset_matches_tail_of_full_read(): void $full = []; foreach ($reader->rows() as $batch) { - foreach ($batch->all() as $row) { - $full[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $full[] = $row['id']; } } @@ -356,8 +355,8 @@ public function test_offset_matches_tail_of_full_read(): void $tail = []; foreach ($reader->rows(offset: $offset) as $batch) { - foreach ($batch->all() as $row) { - $tail[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $tail[] = $row['id']; } } @@ -381,8 +380,8 @@ public function test_offset_reads_through_a_custom_identity_codec(): void foreach ((new FloeReader($filesystem, new CodecStub(0x00))) ->read($path) ->rows(offset: 1) as $batch) { - foreach ($batch->all() as $extractedRow) { - $ids[] = $extractedRow->get('id'); + foreach ($batch->toArray() as $extractedRow) { + $ids[] = $extractedRow['id']; } } @@ -645,7 +644,7 @@ public function test_rows_through_a_custom_identity_codec(): void ); static::assertCount(1, $batches); - static::assertCount(2, $batches[0]->all()); + static::assertCount(2, $batches[0]); } public function test_torn_file_without_footer_throws_in_strict_mode(): void @@ -711,8 +710,8 @@ public function test_head_returns_first_rows(): void foreach ((new FloeReader($filesystem)) ->read($path) ->head(3) as $batch) { - foreach ($batch->all() as $row) { - $ids[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; } } @@ -735,8 +734,8 @@ public function test_head_count_beyond_total_returns_all_rows(): void foreach ((new FloeReader($filesystem)) ->read($path) ->head(5) as $batch) { - foreach ($batch->all() as $row) { - $ids[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; } } @@ -755,7 +754,7 @@ public function test_head_respects_batch_size(): void $writer->close(); $sizes = array_map( - static fn(Rows $batch): int => count($batch->all()), + static fn(Rows $batch): int => $batch->count(), iterator_to_array( (new FloeReader($filesystem)) ->read($path) @@ -812,9 +811,9 @@ public function test_tail_returns_last_rows_across_sections(): void foreach ((new FloeReader($filesystem)) ->read($path) ->tail(3) as $batch) { - foreach ($batch->all() as $row) { - $ids[] = $row->get('id'); - $names[] = $row->names(); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; + $names[] = array_keys($row); } } @@ -838,8 +837,8 @@ public function test_tail_count_beyond_total_returns_all_rows(): void foreach ((new FloeReader($filesystem)) ->read($path) ->tail(5) as $batch) { - foreach ($batch->all() as $row) { - $ids[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $ids[] = $row['id']; } } @@ -858,7 +857,7 @@ public function test_tail_respects_batch_size(): void $writer->close(); $sizes = array_map( - static fn(Rows $batch): int => count($batch->all()), + static fn(Rows $batch): int => $batch->count(), iterator_to_array( (new FloeReader($filesystem)) ->read($path) @@ -893,8 +892,8 @@ public function test_tail_matches_slice_of_full_read(): void $full = []; foreach ($reader->rows() as $batch) { - foreach ($batch->all() as $row) { - $full[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $full[] = $row['id']; } } @@ -902,8 +901,8 @@ public function test_tail_matches_slice_of_full_read(): void $tail = []; foreach ($reader->tail($count) as $batch) { - foreach ($batch->all() as $row) { - $tail[] = $row->get('id'); + foreach ($batch->toArray() as $row) { + $tail[] = $row['id']; } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php index 3d24e8dbae..3c1dc07652 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php @@ -201,7 +201,7 @@ public function test_batch_omitting_a_nullable_session_column_is_accepted_and_ro $footer = FloeStreamReaderContext::footer($filesystem, $path); static::assertSame(2, $footer->statistics->rows); static::assertNotSame([], $footer->schema); - static::assertCount(2, FloeStreamReaderContext::readAll($filesystem, $path)->all()); + static::assertCount(2, FloeStreamReaderContext::readAll($filesystem, $path)); } /** diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php index e616ba4255..f2f9d6fc66 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeValueRoundTripTest.php @@ -141,8 +141,8 @@ public function test_html_entries(): void ]], schema(html_schema('html'))); static::assertSame( - type_string()->cast($rows->first()->get('html')), - type_string()->cast(FloeStreamReaderContext::roundTrip($rows)->first()->get('html')), + type_string()->cast($rows->column('html')->value(0)), + type_string()->cast(FloeStreamReaderContext::roundTrip($rows)->column('html')->value(0)), ); } @@ -346,15 +346,12 @@ public function test_round_trip_rewrites_value_key_order_into_schema_order(): vo $inOrder = array_to_rows([['s' => ['a' => 1, 'b' => 'x']]], schema(structure_schema('s', $type))); - static::assertSame( - $inOrder->first()->values(), - FloeStreamReaderContext::roundTrip($inOrder)->first()->values(), - ); + static::assertSame($inOrder->values(0), FloeStreamReaderContext::roundTrip($inOrder)->values(0)); $outOfOrder = array_to_rows([['s' => ['b' => 'x', 'a' => 1]]], schema(structure_schema('s', $type))); - $decoded = FloeStreamReaderContext::roundTrip($outOfOrder)->first(); + $decoded = FloeStreamReaderContext::roundTrip($outOfOrder); - static::assertSame(['a' => 1, 'b' => 'x'], $decoded->get('s')); + static::assertSame(['a' => 1, 'b' => 'x'], $decoded->column('s')->value(0)); } public function test_uuid_entries(): void diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php index 760ed8c741..589fcdc271 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php @@ -451,7 +451,7 @@ public function test_within_batch_heterogeneous_rows_encode_under_one_union_sche static::assertNotNull($fileSchema->findDefinition('a')); static::assertTrue($fileSchema->findDefinition('b')?->isNullable()); static::assertTrue($fileSchema->findDefinition('c')?->isNullable()); - static::assertCount(3, FloeStreamReaderContext::readAll($filesystem, $path)->all()); + static::assertCount(3, FloeStreamReaderContext::readAll($filesystem, $path)); } public function test_section_offsets_point_at_frames(): void diff --git a/src/extension/flow-php-ext/src/backend.rs b/src/extension/flow-php-ext/src/backend.rs index 9643335dab..3039034dbc 100644 --- a/src/extension/flow-php-ext/src/backend.rs +++ b/src/extension/flow-php-ext/src/backend.rs @@ -13,14 +13,17 @@ use ext_php_rs::types::{ZendHashTable, Zval}; use flow_batch_frame::column::decode; use flow_batch_frame::layout::buffer_count; -use crate::builder::NativeColumnBuilder; +use crate::builder::{throw, NativeColumnBuilder}; use crate::column::NativeColumn; -use crate::ctx::{call_method, zval_long}; +use crate::ctx::{call_method, call_static, expect_object, find_class, zval_long}; use crate::exception::ext_exception; use crate::interfaces::backend_ce; use crate::plan::{physical_for_definition, type_plan, TypePlan}; use crate::render::{decode_exception, invalid_argument}; +const COLUMN_MISMATCH: &str = "Flow\\ETL\\Exception\\ColumnMismatchException"; +const MIXED_TYPE: &str = "Flow\\Types\\Type\\Native\\MixedType"; + /// A return typed `Flow\ETL\Column\Column`: `adopt()` hands back its argument itself. pub struct ColumnValue(Zval); @@ -106,6 +109,10 @@ impl DefaultBackend { return Ok(ColumnValue(column.shallow_clone())); } + if expect_object(&call_method(column, "type", &mut [])?, "a Type")?.instance_of(find_class(MIXED_TYPE)?) { + return Err(throw(call_static(COLUMN_MISMATCH, "untypedColumn", &mut [definition.shallow_clone()])?)); + } + let mut builder = self.builder(definition)?; let count = call_method(column, "count", &mut [])? .long() diff --git a/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt b/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt index c56d48474a..fc8c3d7c17 100644 --- a/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt +++ b/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt @@ -1,5 +1,5 @@ --TEST-- -native and PHP columns build into each other: appendFrom/appendTake, Rows::concat, Rows::of, adopt() both ways +native and PHP columns build into each other: appendFrom/appendTake, Rows::concat, Rows::gather, adopt() both ways --SKIPIF-- --FILE-- @@ -42,7 +42,7 @@ $same('native appendFrom of a PHP column', $php->gather([5, 0, 3, 3]), $rebuilt( $same('PHP appendTake of a native column', $php->gather([5, 0, 3, 3]), $rebuilt($native, new PhpBackend(), true)); $same('Rows::concat PHP + native', $php->concat($php), $php->concat($native)); $same('Rows::concat native + PHP', $php->concat($php), $native->concat($php)); -$same('Rows::of over both', Rows::of($schema, $php->row(1), $php->row(4)), Rows::of($schema, $native->row(1), $php->row(4))); +$same('Rows::gather over both', $php->gather([1, 4]), $native->gather([1, 4])); foreach ($schema->definitions() as $name => $definition) { $phpColumn = $php->column((string) $name); @@ -66,5 +66,5 @@ native appendFrom of a PHP column: identical PHP appendTake of a native column: identical Rows::concat PHP + native: identical Rows::concat native + PHP: identical -Rows::of over both: identical +Rows::gather over both: identical adopt identical diff --git a/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt b/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt new file mode 100644 index 0000000000..08a05b0f46 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt @@ -0,0 +1,21 @@ +--TEST-- +DefaultBackend::adopt() refuses an untyped (mixed) column with the PHP wording +--SKIPIF-- + +--FILE-- + (new DefaultBackend())->adopt(int_schema('a'), new ValueColumn([1, null]))), "\n"; +$typed = (new PhpBackend())->constant(int_schema('a', nullable: true), 1, 2); + +echo get_class((new DefaultBackend())->adopt(int_schema('a', nullable: true), $typed)), "\n"; +?> +--EXPECT-- +Flow\ETL\Exception\ColumnMismatchException: Row does not match its schema: column "a": mixed cannot be a batch column, an untyped function result exists only inside function evaluation +Flow\ETL\Column\NativeColumn diff --git a/web/landing/content/examples/topics/inspecting/fetch/code.php b/web/landing/content/examples/topics/inspecting/fetch/code.php index 0bcd5d1b0d..4fcdc638c0 100644 --- a/web/landing/content/examples/topics/inspecting/fetch/code.php +++ b/web/landing/content/examples/topics/inspecting/fetch/code.php @@ -16,8 +16,8 @@ ->fetch(2); echo 'fetched ' . $rows->count() . " rows\n"; -echo 'first name: ' . $rows->first()->get('name') . "\n"; +echo 'first name: ' . $rows->column('name')->value(0) . "\n"; -foreach ($rows as $row) { - echo " {$row->get('id')}: {$row->get('name')}\n"; +foreach ($rows->toArray() as $row) { + echo " {$row['id']}: {$row['name']}\n"; } diff --git a/web/landing/resources/api.json b/web/landing/resources/api.json index c2e0a73e83..430255d623 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\/Function\/ResolvesFromChildren.php","start_line_in_file":23,"slug":"deterministic","name":"deterministic","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":23,"slug":"setup","name":"setUp","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"config","type":[{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","is_nullable":false,"is_variadic":false},{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":28,"slug":"extract","name":"extract","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":33,"slug":"from","name":"from","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":38,"slug":"process","name":"process","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"rows","type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":46,"slug":"read","name":"read","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRmxvdzo6ZXh0cmFjdCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":74,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"aggregations","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBBZ2dyZWdhdGlvbnMgJGFnZ3JlZ2F0aW9ucwogICAgICogQHBhcmFtIG51bGx8R3JvdXBCeUFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUKICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGdvcml0aG0gZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":98,"slug":"batchby","name":"batchBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"column","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"minSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBidXQga2VlcCB0aG9zZSB3aXRoIGNvbW1vbiB2YWx1ZSBpbiBnaXZlbiBjb2x1bW4gdG9nZXRoZXIuCiAgICAgKiBUaGlzIHdvcmtzIHByb3Blcmx5IG9ubHkgb24gc29ydGVkIGRhdGFzZXRzLgogICAgICoKICAgICAqIFdoZW4gbWluU2l6ZSBpcyBub3QgcHJvdmlkZWQsIGJhdGNoZXMgd2lsbCBiZSBjcmVhdGVkIG9ubHkgd2hlbiB0aGVyZSBpcyBhIGNoYW5nZSBpbiB2YWx1ZSBvZiB0aGUgY29sdW1uLgogICAgICogV2hlbiBtaW5TaXplIGlzIHByb3ZpZGVkLCBiYXRjaGVzIHdpbGwgYmUgY3JlYXRlZCBvbmx5IHdoZW4gdGhlcmUgaXMgYSBjaGFuZ2UgaW4gdmFsdWUgb2YgdGhlIGNvbHVtbiBvcgogICAgICogd2hlbiB0aGVyZSBhcmUgYXQgbGVhc3QgbWluU2l6ZSByb3dzIGluIHRoZSBiYXRjaC4KICAgICAqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAkY29sdW1uIC0gY29sdW1uIHRvIGdyb3VwIGJ5IChhbGwgcm93cyB3aXRoIHNhbWUgdmFsdWUgc3RheSB0b2dldGhlcikKICAgICAqIEBwYXJhbSBudWxsfGludDwxLCBtYXg+ICRtaW5TaXplIC0gb3B0aW9uYWwgbWluaW11bSByb3dzIHBlciBiYXRjaCBmb3IgZWZmaWNpZW5jeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":118,"slug":"batchsize","name":"batchSize","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplLgogICAgICogRm9yIGV4YW1wbGUsIHdoZW4gRXh0cmFjdG9yIGlzIHlpZWxkaW5nIG9uZSByb3cgYXQgdGltZSwgdGhpcyBtZXRob2Qgd2lsbCBtZXJnZSB0aGVtIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplCiAgICAgKiBiZWZvcmUgcGFzc2luZyB0aGVtIHRvIHRoZSBuZXh0IHBpcGVsaW5lIGVsZW1lbnQuCiAgICAgKiBTaW1pbGFybHkgd2hlbiBFeHRyYWN0b3IgaXMgeWllbGRpbmcgYmF0Y2hlcyBvZiByb3dzLCB0aGlzIG1ldGhvZCB3aWxsIHNwbGl0IHRoZW0gaW50byBzbWFsbGVyIGJhdGNoZXMgb2YgZ2l2ZW4KICAgICAqIHNpemUuCiAgICAgKgogICAgICogSW4gb3JkZXIgdG8gbWVyZ2UgYWxsIFJvd3MgaW50byBhIHNpbmdsZSBiYXRjaCB1c2UgRGF0YUZyYW1lOjpjb2xsZWN0KCkgbWV0aG9kIG9yIHNldCBzaXplIHRvIC0xIG9yIDAuCiAgICAgKgogICAgICogQHBhcmFtIGludDwtMSwgbWF4PiAkc2l6ZQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":150,"slug":"cache","name":"cache","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"id","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cacheBatchSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cache","type":[{"name":"Cache","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTdGFydCBwcm9jZXNzaW5nIHJvd3MgdXAgdG8gdGhpcyBtb21lbnQgYW5kIHB1dCBlYWNoIGluc3RhbmNlIG9mIFJvd3MKICAgICAqIGludG8gcHJldmlvdXNseSBkZWZpbmVkIGNhY2hlLgogICAgICogQ2FjaGUgdHlwZSBjYW4gYmUgc2V0IHRocm91Z2ggQ29uZmlnQnVpbGRlci4KICAgICAqIEJ5IGRlZmF1bHQgZXZlcnl0aGluZyBpcyBjYWNoZWQgaW4gc3lzdGVtIHRtcCBkaXIuCiAgICAgKgogICAgICogSW1wb3J0YW50OiBjYWNoZSBiYXRjaCBzaXplIG1pZ2h0IHNpZ25pZmljYW50bHkgaW1wcm92ZSBwZXJmb3JtYW5jZSB3aGVuIHByb2Nlc3NpbmcgbGFyZ2UgYW1vdW50IG9mIHJvd3MuCiAgICAgKiBMYXJnZXIgYmF0Y2ggc2l6ZSB3aWxsIGluY3JlYXNlIG1lbW9yeSBjb25zdW1wdGlvbiBidXQgd2lsbCByZWR1Y2UgbnVtYmVyIG9mIElPIG9wZXJhdGlvbnMuCiAgICAgKiBXaGVuIG5vdCBzZXQsIHRoZSBiYXRjaCBzaXplIGlzIHRha2VuIGZyb20gdGhlIGxhc3QgRGF0YUZyYW1lOjpiYXRjaFNpemUoKSBjYWxsLgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHBhcmFtIG51bGx8c3RyaW5nICRpZAogICAgICogQHBhcmFtIG51bGx8Q2FjaGUgJGNhY2hlIHJlYWRzIG9mIHRoaXMgY2FjaGUgbXVzdCBwYXNzIHRoZSBzYW1lIGluc3RhbmNlIHRvIGZyb21fY2FjaGUoKQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":167,"slug":"collect","name":"collect","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZWZvcmUgdHJhbnNmb3JtaW5nIHJvd3MsIGNvbGxlY3QgdGhlbSBhbmQgbWVyZ2UgaW50byBzaW5nbGUgUm93cyBpbnN0YW5jZS4KICAgICAqIFRoaXMgbWlnaHQgbGVhZCB0byBtZW1vcnkgaXNzdWVzIHdoZW4gcHJvY2Vzc2luZyBsYXJnZSBhbW91bnQgb2Ygcm93cywgdXNlIHdpdGggY2F1dGlvbi4KICAgICAqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":186,"slug":"collectrefs","name":"collectRefs","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"References","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGlzIG1ldGhvZCBhbGxvd3MgdG8gY29sbGVjdCByZWZlcmVuY2VzIHRvIGFsbCBlbnRyaWVzIHVzZWQgaW4gdGhpcyBwaXBlbGluZS4KICAgICAqCiAgICAgKiBgYGBwaHAKICAgICAqIChuZXcgRmxvdygpKQogICAgICogICAtPnJlYWQoRnJvbTo6Y2hhaW4oKSkKICAgICAqICAgLT5jb2xsZWN0UmVmcygkcmVmcyA9IHJlZnMoKSkKICAgICAqICAgLT5ydW4oKTsKICAgICAqIGBgYAogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":193,"slug":"constrain","name":"constrain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"constraint","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"constraints","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":204,"slug":"count","name":"count","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICogUmV0dXJuIHRvdGFsIGNvdW50IG9mIHJvd3MgcHJvY2Vzc2VkIGJ5IHRoaXMgcGlwZWxpbmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":224,"slug":"crossjoin","name":"crossJoin","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"prefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"''"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":241,"slug":"display","name":"display","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gaW50ICRsaW1pdCBtYXhpbXVtIG51bWJlcnMgb2Ygcm93cyB0byBkaXNwbGF5CiAgICAgKiBAcGFyYW0gYm9vbHxpbnQgJHRydW5jYXRlIGZhbHNlIG9yIGlmIHNldCB0byAwIGNvbHVtbnMgYXJlIG5vdCB0cnVuY2F0ZWQsIG90aGVyd2lzZSBkZWZhdWx0IHRydW5jYXRlIHRvIDIwCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJhY3RlcnMKICAgICAqIEBwYXJhbSBGb3JtYXR0ZXIgJGZvcm1hdHRlcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":268,"slug":"drop","name":"drop","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBEcm9wIGdpdmVuIGVudHJpZXMuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":282,"slug":"dropduplicates","name":"dropDuplicates","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAuLi4kZW50cmllcwogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHJldHVybiAkdGhpcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":289,"slug":"duplicaterow","name":"duplicateRow","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"condition","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":308,"slug":"fetch","name":"fetch","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZSBhd2FyZSB0aGF0IGZldGNoIGlzIG5vdCBtZW1vcnkgc2FmZSBhbmQgd2lsbCBsb2FkIGFsbCByb3dzIGludG8gbWVtb3J5LgogICAgICogSWYgeW91IHdhbnQgdG8gc2FmZWx5IGl0ZXJhdGUgb3ZlciBSb3dzIHVzZSBvZSBvZiB0aGUgZm9sbG93aW5nIG1ldGhvZHM6LgogICAgICoKICAgICAqIERhdGFGcmFtZTo6Z2V0KCkgOiBcR2VuZXJhdG9yCiAgICAgKiBEYXRhRnJhbWU6OmdldEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqIERhdGFGcmFtZTo6Z2V0RWFjaEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":325,"slug":"filter","name":"filter","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":337,"slug":"filters","name":"filters","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"functions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxTY2FsYXJGdW5jdGlvbj4gJGZ1bmN0aW9ucwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":351,"slug":"foreach","name":"forEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"callback","type":[{"name":"callable","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEBwYXJhbSBudWxsfGNhbGxhYmxlKFJvd3MgJHJvd3MsIEZsb3dDb250ZXh0ICRjb250ZXh0KSA6IHZvaWQgJGNhbGxiYWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":372,"slug":"get","name":"get","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gaW5zdGFuY2Ugb2YgUm93cy4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxSb3dzPgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":391,"slug":"getasarray","name":"getAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gYXJyYXkuCiAgICAgKgogICAgICogQHRyaWdnZXIKICAgICAqCiAgICAgKiBAcmV0dXJuIFxHZW5lcmF0b3I8YXJyYXk8YXJyYXk8bWl4ZWQ+Pj4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":410,"slug":"geteachasarray","name":"getEachAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZCBlYWNoIHJvdyBhcyBhbiBhcnJheS4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxhcnJheTxtaXhlZD4+CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":431,"slug":"groupby","name":"groupBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"GroupedDataFrame","namespace":"Flow\\ETL\\DataFrame","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBHcm91cEJ5UmVmZXJlbmNlc3xSZWZlcmVuY2V8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBncm91cGVkIGJ5IG9uIGl0cyBvd24KICAgICAqIEBwYXJhbSBudWxsfEdyb3VwQnlBbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxnb3JpdGhtIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":450,"slug":"join","name":"join","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."},{"name":"algorithm","type":[{"name":"JoinAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Join","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfEpvaW5BbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlIGFsZ29yaXRobQogICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":478,"slug":"joineach","name":"joinEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"factory","type":[{"name":"DataFrameFactory","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBKb2lucyBpbiBtZW1vcnkgcGVyIGJhdGNoOyBpdCBpcyBub3QgZ292ZXJuZWQgYnkgdGhlIGpvaW4gYWxnb3JpdGhtIGFuZCB0YWtlcyBubyBhbGdvcml0aG0gb3ZlcnJpZGUuCiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAcGFyYW0gc3RyaW5nfEpvaW4gJHR5cGUKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":494,"slug":"limit","name":"limit","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":508,"slug":"load","name":"load","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":554,"slug":"match","name":"match","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"validator","type":[{"name":"SchemaValidator","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfFNjaGVtYVZhbGlkYXRvciAkdmFsaWRhdG9yIC0gd2hlbiBudWxsLCBTdHJpY3RWYWxpZGF0b3IgZ2V0cyBpbml0aWFsaXplZAogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":575,"slug":"offset","name":"offset","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"offset","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTa2lwIGdpdmVuIG51bWJlciBvZiByb3dzIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF0YXNldC4KICAgICAqIFdoZW4gJG9mZnNldCBpcyBudWxsLCBub3RoaW5nIGhhcHBlbnMgKG5vIHJvd3MgYXJlIHNraXBwZWQpLgogICAgICoKICAgICAqIFBlcmZvcm1hbmNlIE5vdGU6IERhdGFGcmFtZSBtdXN0IGl0ZXJhdGUgdGhyb3VnaCBhbmQgcHJvY2VzcyBhbGwgc2tpcHBlZCByb3dzCiAgICAgKiB0byByZWFjaCB0aGUgb2Zmc2V0IHBvc2l0aW9uLiBGb3IgbGFyZ2Ugb2Zmc2V0cywgdGhpcyBjYW4gaW1wYWN0IHBlcmZvcm1hbmNlCiAgICAgKiBhcyB0aGUgZGF0YSBzb3VyY2Ugc3RpbGwgbmVlZHMgdG8gYmUgcmVhZCBhbmQgcHJvY2Vzc2VkIHVwIHRvIHRoZSBvZmZzZXQgcG9pbnQuCiAgICAgKgogICAgICogQHBhcmFtID9pbnQ8MCwgbWF4PiAkb2Zmc2V0CiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":589,"slug":"onerror","name":"onError","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"handler","type":[{"name":"ErrorHandler","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":601,"slug":"repartition","name":"repartition","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogU2h1ZmZsZXMgdGhlIHN0cmVhbSBzbyBldmVyeSByb3cgc2hhcmluZyB0aGUgZ2l2ZW4gY29sdW1ucyBhcnJpdmVzIGluIG9uZSBiYXRjaC4gSXQgZG9lcyBub3QKICAgICAqIHdyaXRlIGRpcmVjdG9yaWVzIC0gdGhhdCBpcyBkZWNsYXJlZCBvbiB0aGUgbG9hZGVyLCBgdG9fY3N2KC4uLiktPnBhcnRpdGlvbkJ5KCdyZWdpb24nKWAuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":613,"slug":"printrows","name":"printRows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":633,"slug":"explain","name":"explain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"trigger","type":[{"name":"Trigger","namespace":"Flow\\ETL\\Plan","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Plan\\Trigger::..."}],"return_type":[{"name":"Plan","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgcGxhbiAkdHJpZ2dlciB3b3VsZCBydW4gb3ZlciB0aGlzIGZyYW1lLCBmcm96ZW46IGxhdGVyIHZlcmJzIG9uIHRoaXMgZnJhbWUgZG8gbm90IHJlYWNoIGl0LiBUaGUgZGVmYXVsdAogICAgICogYWRkcyBubyBjb25zdW1lciBvZiBpdHMgb3duIC0gaXQgZHJhd3MgdGhlIGZyYW1lIGFzIGJ1aWx0LCBpdHMgY2hhaW4gYW5kIGl0cyBzaW5rcy4gdG9TdHJpbmcoKSBwcmludHMgaXQgYXMgYQogICAgICogdHJlZS4gQW5zd2VycyBmcm9tIHRoZSBwbGFuIHdpdGhvdXQgcmVhZGluZyBhIHJvdy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":643,"slug":"printschema","name":"printSchema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"formatter","type":[{"name":"SchemaFormatter","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\Formatter\\ASCIISchemaFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":651,"slug":"rename","name":"rename","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"from","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"to","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":658,"slug":"renameeach","name":"renameEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"strategies","type":[{"name":"RenameEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":669,"slug":"rows","name":"rows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6dHJhbnNmb3JtIG1ldGhvZC4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":686,"slug":"run","name":"run","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"analyze","type":[{"name":"Analyze","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Report","namespace":"Flow\\ETL\\Dataset","is_nullable":true,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIFdoZW4gYW5hbHl6aW5nIHBpcGVsaW5lIGV4ZWN1dGlvbiB3ZSBjYW4gY2hvc2UgdG8gY29sbGVjdCB2YXJpb3VzIG1ldHJpY3MgdGhyb3VnaCBhbmFseXplKCktPndpdGgqKCkgbWV0aG9kCiAgICAgKgogICAgICogLSBjb2x1bW4gc3RhdGlzdGljcyAtIGFuYWx5emUoKS0+d2l0aENvbHVtblN0YXRpc3RpY3MoKQogICAgICogLSBzY2hlbWEgLSBhbmFseXplKCktPndpdGhTY2hlbWEoKQogICAgICoKICAgICAqIEBwYXJhbSBBbmFseXplfGJvb2wgJGFuYWx5emUgLSB3aGVuIHNldCBydW4gd2lsbCByZXR1cm4gUmVwb3J0CiAgICAgKgogICAgICogQHJldHVybiAoJGFuYWx5emUgaXMgQW5hbHl6ZXx0cnVlID8gUmVwb3J0IDogbnVsbCkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":714,"slug":"schema","name":"schema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":727,"slug":"select","name":"select","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogS2VlcCBvbmx5IGdpdmVuIGVudHJpZXMuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":741,"slug":"sortby","name":"sortBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"SortAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBSZWZlcmVuY2V8U29ydFJlZmVyZW5jZXN8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBzb3J0ZWQgYnkgb24gaXRzIG93bgogICAgICogQHBhcmFtIG51bGx8U29ydEFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUgYWxnb3JpdGhtCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":755,"slug":"transform","name":"transform","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRGF0YUZyYW1lOjp3aXRoKCkuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":766,"slug":"until","name":"until","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGZpbHRlciBhbmQgdW50aWwgaXMgdGhhdCBmaWx0ZXIgd2lsbCBrZWVwIGZpbHRlcmluZyByb3dzIHVudGlsIGV4dHJhY3RvcnMgZmluaXNoIHlpZWxkaW5nCiAgICAgKiByb3dzLiBVbnRpbCB3aWxsIHNlbmQgYSBTVE9QIHNpZ25hbCB0byB0aGUgRXh0cmFjdG9yIHdoZW4gdGhlIGNvbmRpdGlvbiBpcyBub3QgbWV0LgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":780,"slug":"void","name":"void","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogVGhpcyBtZXRob2QgaXMgdXNlZnVsIG1vc3RseSBpbiBkZXZlbG9wbWVudCB3aGVuCiAgICAgKiB5b3Ugd2FudCB0byBwYXVzZSBwcm9jZXNzaW5nIGF0IGNlcnRhaW4gbW9tZW50IHdpdGhvdXQKICAgICAqIHJlbW92aW5nIGNvZGUuIEFsbCBvcGVyYXRpb25zIHdpbGwgZ2V0IHByb2Nlc3NlZCB1cCB0byB0aGlzIHBvaW50LAogICAgICogZnJvbSBoZXJlIG5vIHJvd3MgYXJlIHBhc3NlZCBmb3J3YXJkLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":790,"slug":"with","name":"with","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":818,"slug":"withentries","name":"withEntries","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxpbnQsIFdpdGhFbnRyeT58YXJyYXk8c3RyaW5nLCBTY2FsYXJGdW5jdGlvbnxXaW5kb3dGdW5jdGlvbnxXaXRoRW50cnk+ICRyZWZlcmVuY2VzCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":836,"slug":"withentry","name":"withEntry","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"reference","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"WindowFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gRGVmaW5pdGlvbjxtaXhlZD58c3RyaW5nICRlbnRyeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":849,"slug":"write","name":"write","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6bG9hZCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":21,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"aggregations","type":[{"name":"AggregatingFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":28,"slug":"pivot","name":"pivot","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"ref","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"values","type":[{"name":"PivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null}] \ No newline at end of file +[{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":31,"slug":"and","name":"and","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":36,"slug":"andnot","name":"andNot","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"All","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":41,"slug":"append","name":"append","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"suffix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Append","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":54,"slug":"arrayfilter","name":"arrayFilter","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayFilter","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBGaWx0ZXJzIGFuIGFycmF5IGJ5IHJlbW92aW5nIGFsbCBlbGVtZW50cyB0aGF0IG1hdGNoZXMgcGFzc2VkIHZhbHVlLgogICAgICogQXBwbGljYWJsZSB0byBhbGwgZGF0YSBzdHJ1Y3R1cmVzIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhbiBhcnJheToKICAgICAqICAgIC0ganNvbgogICAgICogICAgLSBsaXN0CiAgICAgKiAgICAtIG1hcAogICAgICogICAgLSBzdHJ1Y3R1cmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":59,"slug":"arrayget","name":"arrayGet","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayGet","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":67,"slug":"arraygetcollection","name":"arrayGetCollection","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"keys","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayGetCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGtleXMKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":72,"slug":"arraygetcollectionfirst","name":"arrayGetCollectionFirst","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"keys","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ArrayGetCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":85,"slug":"arraykeep","name":"arrayKeep","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayKeep","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBGaWx0ZXJzIGFuIGFycmF5IGJ5IGtlZXBpbmcgb25seSBlbGVtZW50cyB0aGF0IG1hdGNoZXMgcGFzc2VkIHZhbHVlLgogICAgICogQXBwbGljYWJsZSB0byBhbGwgZGF0YSBzdHJ1Y3R1cmVzIHRoYXQgY2FuIGJlIGNvbnZlcnRlZCB0byBhbiBhcnJheToKICAgICAqICAgLSBqc29uCiAgICAgKiAgIC0gbGlzdAogICAgICogICAtIG1hcAogICAgICogICAtIHN0cnVjdHVyZS4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":98,"slug":"arraykeys","name":"arrayKeys","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayKeys","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGFsbCBrZXlzIGZyb20gYW4gYXJyYXksIGlnbm9yaW5nIHRoZSB2YWx1ZXMuCiAgICAgKiBBcHBsaWNhYmxlIHRvIGFsbCBkYXRhIHN0cnVjdHVyZXMgdGhhdCBjYW4gYmUgY29udmVydGVkIHRvIGFuIGFycmF5OgogICAgICogICAtIGpzb24KICAgICAqICAgLSBsaXN0CiAgICAgKiAgIC0gbWFwCiAgICAgKiAgIC0gc3RydWN0dXJlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":106,"slug":"arraymerge","name":"arrayMerge","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayMerge","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHJlZgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":111,"slug":"arraymergecollection","name":"arrayMergeCollection","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayMergeCollection","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":116,"slug":"arraypathexists","name":"arrayPathExists","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayPathExists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":121,"slug":"arrayreverse","name":"arrayReverse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"preserveKeys","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"ArrayReverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":126,"slug":"arraysort","name":"arraySort","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"sortFunction","type":[{"name":"Sort","namespace":"Flow\\ETL\\Function\\ArraySort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"recursive","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"}],"return_type":[{"name":"ArraySort","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":142,"slug":"arrayvalues","name":"arrayValues","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ArrayValues","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGFsbCB2YWx1ZXMgZnJvbSBhbiBhcnJheSwgaWdub3JpbmcgdGhlIGtleXMuCiAgICAgKiBBcHBsaWNhYmxlIHRvIGFsbCBkYXRhIHN0cnVjdHVyZXMgdGhhdCBjYW4gYmUgY29udmVydGVkIHRvIGFuIGFycmF5OgogICAgICogICAtIGpzb24KICAgICAqICAgLSBsaXN0CiAgICAgKiAgIC0gbWFwCiAgICAgKiAgIC0gc3RydWN0dXJlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":147,"slug":"ascii","name":"ascii","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Ascii","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":157,"slug":"between","name":"between","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"lowerBoundRef","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"upperBoundRef","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"boundary","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Boundary","namespace":"Flow\\ETL\\Function\\Between","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\Between\\Boundary::..."}],"return_type":[{"name":"Between","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gbWl4ZWR8U2NhbGFyRnVuY3Rpb24gJGxvd2VyQm91bmRSZWYKICAgICAqIEBwYXJhbSBtaXhlZHxTY2FsYXJGdW5jdGlvbiAkdXBwZXJCb3VuZFJlZgogICAgICogQHBhcmFtIEJvdW5kYXJ5fFNjYWxhckZ1bmN0aW9uICRib3VuZGFyeQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":165,"slug":"binarylength","name":"binaryLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"BinaryLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":174,"slug":"call","name":"call","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"callable","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"returnType","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"arguments","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"refAlias","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"CallUserFunc","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGFyZ3VtZW50cwogICAgICogQHBhcmFtIFR5cGU8bWl4ZWQ+ICRyZXR1cm5UeXBlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":183,"slug":"capitalize","name":"capitalize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Capitalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":191,"slug":"cast","name":"cast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Cast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gc3RyaW5nfFR5cGU8bWl4ZWQ+ICR0eXBlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":196,"slug":"chunk","name":"chunk","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"size","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Chunk","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":201,"slug":"coalesce","name":"coalesce","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Coalesce","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":206,"slug":"codepointlength","name":"codePointLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"CodePointLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":211,"slug":"collapsewhitespace","name":"collapseWhitespace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"CollapseWhitespace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":216,"slug":"concat","name":"concat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Concat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":221,"slug":"concatwithseparator","name":"concatWithSeparator","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"ConcatWithSeparator","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":228,"slug":"contains","name":"contains","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Contains","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":233,"slug":"dateformat","name":"dateFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d'"}],"return_type":[{"name":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":238,"slug":"datetimeformat","name":"dateTimeFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d H:i:s'"}],"return_type":[{"name":"DateTimeFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":243,"slug":"divide","name":"divide","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"scale","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"rounding","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Rounding","namespace":"Flow\\Calculator","is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Divide","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":251,"slug":"domelementattributescount","name":"domElementAttributesCount","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementAttributesCount","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":256,"slug":"domelementattributevalue","name":"domElementAttributeValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"attribute","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DOMElementAttributeValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":261,"slug":"domelementnamespace","name":"domElementNamespace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"attribute","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DOMElementNamespaceValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":266,"slug":"domelementnextsibling","name":"domElementNextSibling","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementNextSibling","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":271,"slug":"domelementparent","name":"domElementParent","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementParent","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":276,"slug":"domelementprevioussibling","name":"domElementPreviousSibling","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementPreviousSibling","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":281,"slug":"domelementvalue","name":"domElementValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"DOMElementValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":286,"slug":"endswith","name":"endsWith","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EndsWith","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":291,"slug":"ensureend","name":"ensureEnd","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"suffix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EnsureEnd","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":296,"slug":"ensurestart","name":"ensureStart","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"prefix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"EnsureStart","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":301,"slug":"enumname","name":"enumName","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"EnumName","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":306,"slug":"enumvalue","name":"enumValue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"EnumValue","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":311,"slug":"equals","name":"equals","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Equals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":316,"slug":"exists","name":"exists","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Exists","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":345,"slug":"expand","name":"expand","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"expand","type":[{"name":"ArrayExpand","namespace":"Flow\\ETL\\Function\\ArrayExpand","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\ArrayExpand\\ArrayExpand::..."}],"return_type":[{"name":"ArrayExpand","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBFeHBhbmRzIGVhY2ggdmFsdWUgaW50byBlbnRyeSwgaWYgdGhlcmUgYXJlIG1vcmUgdGhhbiBvbmUgdmFsdWUsIG11bHRpcGxlIHJvd3Mgd2lsbCBiZSBjcmVhdGVkLgogICAgICogQXJyYXkga2V5cyBhcmUgaWdub3JlZCwgb25seSB2YWx1ZXMgYXJlIHVzZWQgdG8gY3JlYXRlIG5ldyByb3dzLgogICAgICogTmVzdGVkIGluIGFub3RoZXIgZnVuY3Rpb24gKHN0cnVjdHVyZSgpLCBjb25jYXQoKSwgLi4uKSBpdCBzdGlsbCBnaXZlcyBvbmUgcm93IHBlciBlbGVtZW50LiBTZXZlcmFsCiAgICAgKiBleHBhbmRzIGluIG9uZSBleHByZXNzaW9uIGFyZSB6aXBwZWQgdG8gdGhlIGxvbmdlc3QgbGlzdDsgYSBzaG9ydGVyIG9uZSBnaXZlcyBudWxsLCBzbyBpdHMgZWxlbWVudAogICAgICogdHlwZSBiZWNvbWVzIG51bGxhYmxlLiBJdCBpcyByZWZ1c2VkIGluc2lkZSBhbm90aGVyIGFycmF5X2V4cGFuZCgpIGFuZCBpbiBmaWx0ZXIoKSwgdW50aWwoKSwKICAgICAqIGR1cGxpY2F0ZVJvdygpLCBhZ2dyZWdhdGUoKSwgb3ZlcigpIGFuZCBvbkVhY2goKS4KICAgICAqCiAgICAgKiBCZWZvcmU6CiAgICAgKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogICAgICogICB8aWR8ICAgICAgICAgICAgICBhcnJheXwKICAgICAqICAgKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAgICAgKiAgIHwgMXx7ImEiOjEsImIiOjIsImMiOjN9fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqCiAgICAgKiBBZnRlcjoKICAgICAqICAgKy0tKy0tLS0tLS0tKwogICAgICogICB8aWR8ZXhwYW5kZWR8CiAgICAgKiAgICstLSstLS0tLS0tLSsKICAgICAqICAgfCAxfCAgICAgICAxfAogICAgICogICB8IDF8ICAgICAgIDJ8CiAgICAgKiAgIHwgMXwgICAgICAgM3wKICAgICAqICAgKy0tKy0tLS0tLS0tKwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":350,"slug":"greaterthan","name":"greaterThan","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"GreaterThan","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":355,"slug":"greaterthanequal","name":"greaterThanEqual","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"GreaterThanEqual","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":360,"slug":"hash","name":"hash","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"algorithm","type":[{"name":"Algorithm","namespace":"Flow\\ETL\\Hash","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Hash\\NativePHPHash::..."}],"return_type":[{"name":"Hash","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":365,"slug":"htmlqueryselector","name":"htmlQuerySelector","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HTMLQuerySelector","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":370,"slug":"htmlqueryselectorall","name":"htmlQuerySelectorAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"path","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"HTMLQuerySelectorAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":378,"slug":"indexof","name":"indexOf","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ignoreCase","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"IndexOf","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBpbmRleCBvZiBnaXZlbiAkbmVlZGxlIGluIHN0cmluZy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":389,"slug":"indexoflast","name":"indexOfLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ignoreCase","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"IndexOfLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBsYXN0IGluZGV4IG9mIGdpdmVuICRuZWVkbGUgaW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":397,"slug":"isempty","name":"isEmpty","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsEmpty","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":402,"slug":"iseven","name":"isEven","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Equals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":407,"slug":"isfalse","name":"isFalse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":415,"slug":"isin","name":"isIn","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"haystack","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"IsIn","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJGhheXN0YWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":420,"slug":"isnotnull","name":"isNotNull","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNotNull","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":425,"slug":"isnotnumeric","name":"isNotNumeric","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNotNumeric","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":430,"slug":"isnull","name":"isNull","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNull","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":435,"slug":"isnumeric","name":"isNumeric","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsNumeric","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":440,"slug":"isodd","name":"isOdd","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"NotEquals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":445,"slug":"istrue","name":"isTrue","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":453,"slug":"istype","name":"isType","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"types","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"IsType","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gc3RyaW5nfFR5cGU8bWl4ZWQ+ICR0eXBlcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":465,"slug":"isutf8","name":"isUtf8","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"IsUtf8","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDaGVjayBzdHJpbmcgaXMgdXRmOCBhbmQgcmV0dXJucyB0cnVlIG9yIGZhbHNlLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":470,"slug":"jsondecode","name":"jsonDecode","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"4194304"}],"return_type":[{"name":"JsonDecode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":475,"slug":"jsonencode","name":"jsonEncode","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"4194304"}],"return_type":[{"name":"JsonEncode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":480,"slug":"lessthan","name":"lessThan","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LessThan","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":485,"slug":"lessthanequal","name":"lessThanEqual","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"LessThanEqual","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":490,"slug":"literal","name":"literal","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Literal","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":495,"slug":"lower","name":"lower","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ToLower","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":500,"slug":"minus","name":"minus","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Minus","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":505,"slug":"mod","name":"mod","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Mod","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":510,"slug":"modifydatetime","name":"modifyDateTime","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"modifier","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ModifyDateTime","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":515,"slug":"multiply","name":"multiply","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Multiply","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":520,"slug":"notequals","name":"notEquals","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"NotEquals","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":525,"slug":"notsame","name":"notSame","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"NotSame","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":530,"slug":"numberformat","name":"numberFormat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"decimals","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"decimalSeparator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'.'"},{"name":"thousandsSeparator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"','"}],"return_type":[{"name":"NumberFormat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":544,"slug":"oneach","name":"onEach","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"preserveKeys","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"}],"return_type":[{"name":"OnEach","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBFeGVjdXRlIGEgc2NhbGFyIGZ1bmN0aW9uIG9uIGVhY2ggZWxlbWVudCBvZiBhbiBhcnJheS9saXN0L21hcC9zdHJ1Y3R1cmUgZW50cnkuCiAgICAgKiBJbiBvcmRlciB0byB1c2UgdGhpcyBmdW5jdGlvbiwgeW91IG5lZWQgdG8gcHJvdmlkZSBhIHJlZmVyZW5jZSB0byB0aGUgImVsZW1lbnQiIHRoYXQgd2lsbCBiZSB1c2VkIGluIHRoZSBmdW5jdGlvbi4KICAgICAqCiAgICAgKiBFeGFtcGxlOiAkZGYtPndpdGhFbnRyeSgnYXJyYXknLCByZWYoJ2FycmF5JyktPm9uRWFjaChyZWYoJ2VsZW1lbnQnKS0+Y2FzdCh0eXBlX3N0cmluZygpKSkpCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":549,"slug":"or","name":"or","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":554,"slug":"ornot","name":"orNot","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Any","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":559,"slug":"plus","name":"plus","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"ref","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Plus","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":564,"slug":"power","name":"power","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Power","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":569,"slug":"prepend","name":"prepend","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"prefix","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Prepend","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":574,"slug":"regex","name":"regex","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"Regex","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":579,"slug":"regexall","name":"regexAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":584,"slug":"regexmatch","name":"regexMatch","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexMatch","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":592,"slug":"regexmatchall","name":"regexMatchAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"flags","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"},{"name":"offset","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"0"}],"return_type":[{"name":"RegexMatchAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":600,"slug":"regexreplace","name":"regexReplace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"replacement","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"RegexReplace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":608,"slug":"repeat","name":"repeat","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"times","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Repeat","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":613,"slug":"reverse","name":"reverse","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Reverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":618,"slug":"round","name":"round","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"precision","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"mode","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"}],"return_type":[{"name":"Round","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":623,"slug":"same","name":"same","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"value","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Same","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":628,"slug":"sanitize","name":"sanitize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"placeholder","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'*'"},{"name":"skipCharacters","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Sanitize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":635,"slug":"size","name":"size","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"Size","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":643,"slug":"slug","name":"slug","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'-'"},{"name":"locale","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"symbolsMap","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Slug","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258bnVsbHxhcnJheTxhcnJheS1rZXksIG1peGVkPiAkc3ltYm9sc01hcAogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":651,"slug":"split","name":"split","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"separator","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"9223372036854775807"}],"return_type":[{"name":"Split","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":656,"slug":"sprintf","name":"sprintf","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"params","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Sprintf","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":661,"slug":"startswith","name":"startsWith","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StartsWith","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":669,"slug":"stringafter","name":"stringAfter","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringAfter","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBhZnRlciB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiB0aGUgZ2l2ZW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":677,"slug":"stringafterlast","name":"stringAfterLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringAfterLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBhZnRlciB0aGUgbGFzdCBvY2N1cnJlbmNlIG9mIHRoZSBnaXZlbiBzdHJpbmcuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":687,"slug":"stringbefore","name":"stringBefore","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringBefore","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBiZWZvcmUgdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgdGhlIGdpdmVuIHN0cmluZy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":697,"slug":"stringbeforelast","name":"stringBeforeLast","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"includeNeedle","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringBeforeLast","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIHRoZSBjb250ZW50cyBmb3VuZCBiZWZvcmUgdGhlIGxhc3Qgb2NjdXJyZW5jZSBvZiB0aGUgZ2l2ZW4gc3RyaW5nLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":707,"slug":"stringcontainsany","name":"stringContainsAny","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"needles","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringContainsAny","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8c3RyaW5nPnxTY2FsYXJGdW5jdGlvbiAkbmVlZGxlcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":712,"slug":"stringequalsto","name":"stringEqualsTo","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"string","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringEqualsTo","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":720,"slug":"stringfold","name":"stringFold","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"StringFold","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBSZXR1cm5zIGEgc3RyaW5nIHRoYXQgeW91IGNhbiB1c2UgaW4gY2FzZS1pbnNlbnNpdGl2ZSBjb21wYXJpc29ucy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":725,"slug":"stringmatch","name":"stringMatch","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringMatch","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":730,"slug":"stringmatchall","name":"stringMatchAll","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"pattern","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringMatchAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":735,"slug":"stringnormalize","name":"stringNormalize","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"form","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"16"}],"return_type":[{"name":"StringNormalize","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":744,"slug":"stringstyle","name":"stringStyle","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"style","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"StringStyles","namespace":"Flow\\ETL\\String","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StringStyle","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDb3ZlcnQgc3RyaW5nIHRvIGEgc3R5bGUgZnJvbSBlbnVtIGxpc3QsIHBhc3NlZCBpbiBwYXJhbWV0ZXIuCiAgICAgKiBDYW4gYmUgc3RyaW5nICJ1cHBlciIgb3IgU3RyaW5nU3R5bGVzOjpVUFBFUiBmb3IgVXBwZXIgKGV4YW1wbGUpLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":752,"slug":"stringtitle","name":"stringTitle","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"allWords","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StringTitle","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBDaGFuZ2VzIGFsbCBncmFwaGVtZXMvY29kZSBwb2ludHMgdG8gInRpdGxlIGNhc2UiLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":757,"slug":"stringwidth","name":"stringWidth","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"StringWidth","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":762,"slug":"strpad","name":"strPad","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"},{"name":"type","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"1"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":767,"slug":"strpadboth","name":"strPadBoth","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":772,"slug":"strpadleft","name":"strPadLeft","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":777,"slug":"strpadright","name":"strPadRight","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"pad_string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' '"}],"return_type":[{"name":"StrPad","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":786,"slug":"strreplace","name":"strReplace","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"search","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"replace","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"StrReplace","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gYXJyYXk8c3RyaW5nPnxTY2FsYXJGdW5jdGlvbnxzdHJpbmcgJHNlYXJjaAogICAgICogQHBhcmFtIGFycmF5PHN0cmluZz58U2NhbGFyRnVuY3Rpb258c3RyaW5nICRyZXBsYWNlCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":794,"slug":"todate","name":"toDate","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d\\\\TH:i:sP'"},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"DateTimeZone::..."}],"return_type":[{"name":"ToDate","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258c3RyaW5nICRmb3JtYXQgLSBjdXJyZW50IGZvcm1hdCBvZiB0aGUgZGF0ZSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjcmVhdGUgRGF0ZVRpbWVJbW11dGFibGUgaW5zdGFuY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":805,"slug":"todatetime","name":"toDateTime","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"format","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'Y-m-d H:i:s'"},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"DateTimeZone::..."}],"return_type":[{"name":"ToDateTime","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gU2NhbGFyRnVuY3Rpb258c3RyaW5nICRmb3JtYXQgLSBjdXJyZW50IGZvcm1hdCBvZiB0aGUgZGF0ZSB0aGF0IHdpbGwgYmUgdXNlZCB0byBjcmVhdGUgRGF0ZVRpbWVJbW11dGFibGUgaW5zdGFuY2UKICAgICAqIEBwYXJhbSBcRGF0ZVRpbWVab25lfFNjYWxhckZ1bmN0aW9uICR0aW1lWm9uZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":812,"slug":"trim","name":"trim","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"type","type":[{"name":"Type","namespace":"Flow\\ETL\\Function\\Trim","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Function\\Trim\\Type::..."},{"name":"characters","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"' \\t\\n\\r\\0\u000b'"}],"return_type":[{"name":"Trim","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":817,"slug":"truncate","name":"truncate","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"length","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"ellipsis","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'...'"}],"return_type":[{"name":"Truncate","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":822,"slug":"unicodelength","name":"unicodeLength","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"UnicodeLength","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":846,"slug":"unpack","name":"unpack","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ArrayUnpack","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":"LyoqCiAgICAgKiBVbnBhY2tzIGVhY2ggZWxlbWVudCBvZiBhbiBhcnJheSBpbnRvIGEgbmV3IGVudHJ5LCB1c2luZyB0aGUgYXJyYXkga2V5IGFzIHRoZSBlbnRyeSBuYW1lLgogICAgICoKICAgICAqIEJlZm9yZToKICAgICAqICAgKy0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rCiAgICAgKiAgIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqICAgfCAxfHsiYSI6MSwiYiI6MiwiYyI6M318CiAgICAgKiAgIHwgMnx7ImQiOjQsImUiOjUsImYiOjZ9fAogICAgICogICArLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsKICAgICAqCiAgICAgKiBBZnRlcjoKICAgICAqICAgKy0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKwogICAgICogICB8aWR8YXJyLmJ8YXJyLmN8YXJyLmR8YXJyLmV8YXJyLmZ8CiAgICAgKiAgICstLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSsKICAgICAqICAgfCAxfCAgICAyfCAgICAzfCAgICAgfCAgICAgfCAgICAgfAogICAgICogICB8IDJ8ICAgICB8ICAgICB8ICAgIDR8ICAgIDV8ICAgIDZ8CiAgICAgKiAgICstLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSsKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":851,"slug":"upper","name":"upper","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"ToUpper","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":856,"slug":"wordwrap","name":"wordwrap","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"width","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"break","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"'\\n'"},{"name":"cut","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Wordwrap","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ScalarFunctionChain.php","start_line_in_file":864,"slug":"xpath","name":"xpath","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[{"name":"string","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"XPath","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ResolvesFromChildren.php","start_line_in_file":12,"slug":"resolved","name":"resolved","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Function\/ResolvesFromChildren.php","start_line_in_file":23,"slug":"deterministic","name":"deterministic","class":"Flow\\ETL\\Function\\ScalarFunctionChain","class_slug":"scalarfunctionchain","parameters":[],"return_type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":23,"slug":"setup","name":"setUp","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"config","type":[{"name":"ConfigBuilder","namespace":"Flow\\ETL\\Config","is_nullable":false,"is_variadic":false},{"name":"Config","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":28,"slug":"extract","name":"extract","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":33,"slug":"from","name":"from","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":38,"slug":"process","name":"process","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"rows","type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/Flow.php","start_line_in_file":46,"slug":"read","name":"read","class":"Flow\\ETL\\Flow","class_slug":"flow","parameters":[{"name":"extractor","type":[{"name":"Extractor","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRmxvdzo6ZXh0cmFjdCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":74,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"aggregations","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBBZ2dyZWdhdGlvbnMgJGFnZ3JlZ2F0aW9ucwogICAgICogQHBhcmFtIG51bGx8R3JvdXBCeUFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUKICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGdvcml0aG0gZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":98,"slug":"batchby","name":"batchBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"column","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"minSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBidXQga2VlcCB0aG9zZSB3aXRoIGNvbW1vbiB2YWx1ZSBpbiBnaXZlbiBjb2x1bW4gdG9nZXRoZXIuCiAgICAgKiBUaGlzIHdvcmtzIHByb3Blcmx5IG9ubHkgb24gc29ydGVkIGRhdGFzZXRzLgogICAgICoKICAgICAqIFdoZW4gbWluU2l6ZSBpcyBub3QgcHJvdmlkZWQsIGJhdGNoZXMgd2lsbCBiZSBjcmVhdGVkIG9ubHkgd2hlbiB0aGVyZSBpcyBhIGNoYW5nZSBpbiB2YWx1ZSBvZiB0aGUgY29sdW1uLgogICAgICogV2hlbiBtaW5TaXplIGlzIHByb3ZpZGVkLCBiYXRjaGVzIHdpbGwgYmUgY3JlYXRlZCBvbmx5IHdoZW4gdGhlcmUgaXMgYSBjaGFuZ2UgaW4gdmFsdWUgb2YgdGhlIGNvbHVtbiBvcgogICAgICogd2hlbiB0aGVyZSBhcmUgYXQgbGVhc3QgbWluU2l6ZSByb3dzIGluIHRoZSBiYXRjaC4KICAgICAqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAkY29sdW1uIC0gY29sdW1uIHRvIGdyb3VwIGJ5IChhbGwgcm93cyB3aXRoIHNhbWUgdmFsdWUgc3RheSB0b2dldGhlcikKICAgICAqIEBwYXJhbSBudWxsfGludDwxLCBtYXg+ICRtaW5TaXplIC0gb3B0aW9uYWwgbWluaW11bSByb3dzIHBlciBiYXRjaCBmb3IgZWZmaWNpZW5jeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":118,"slug":"batchsize","name":"batchSize","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"size","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBNZXJnZS9TcGxpdCBSb3dzIHlpZWxkZWQgYnkgRXh0cmFjdG9yIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplLgogICAgICogRm9yIGV4YW1wbGUsIHdoZW4gRXh0cmFjdG9yIGlzIHlpZWxkaW5nIG9uZSByb3cgYXQgdGltZSwgdGhpcyBtZXRob2Qgd2lsbCBtZXJnZSB0aGVtIGludG8gYmF0Y2hlcyBvZiBnaXZlbiBzaXplCiAgICAgKiBiZWZvcmUgcGFzc2luZyB0aGVtIHRvIHRoZSBuZXh0IHBpcGVsaW5lIGVsZW1lbnQuCiAgICAgKiBTaW1pbGFybHkgd2hlbiBFeHRyYWN0b3IgaXMgeWllbGRpbmcgYmF0Y2hlcyBvZiByb3dzLCB0aGlzIG1ldGhvZCB3aWxsIHNwbGl0IHRoZW0gaW50byBzbWFsbGVyIGJhdGNoZXMgb2YgZ2l2ZW4KICAgICAqIHNpemUuCiAgICAgKgogICAgICogSW4gb3JkZXIgdG8gbWVyZ2UgYWxsIFJvd3MgaW50byBhIHNpbmdsZSBiYXRjaCB1c2UgRGF0YUZyYW1lOjpjb2xsZWN0KCkgbWV0aG9kIG9yIHNldCBzaXplIHRvIC0xIG9yIDAuCiAgICAgKgogICAgICogQHBhcmFtIGludDwtMSwgbWF4PiAkc2l6ZQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":150,"slug":"cache","name":"cache","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"id","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cacheBatchSize","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"},{"name":"cache","type":[{"name":"Cache","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTdGFydCBwcm9jZXNzaW5nIHJvd3MgdXAgdG8gdGhpcyBtb21lbnQgYW5kIHB1dCBlYWNoIGluc3RhbmNlIG9mIFJvd3MKICAgICAqIGludG8gcHJldmlvdXNseSBkZWZpbmVkIGNhY2hlLgogICAgICogQ2FjaGUgdHlwZSBjYW4gYmUgc2V0IHRocm91Z2ggQ29uZmlnQnVpbGRlci4KICAgICAqIEJ5IGRlZmF1bHQgZXZlcnl0aGluZyBpcyBjYWNoZWQgaW4gc3lzdGVtIHRtcCBkaXIuCiAgICAgKgogICAgICogSW1wb3J0YW50OiBjYWNoZSBiYXRjaCBzaXplIG1pZ2h0IHNpZ25pZmljYW50bHkgaW1wcm92ZSBwZXJmb3JtYW5jZSB3aGVuIHByb2Nlc3NpbmcgbGFyZ2UgYW1vdW50IG9mIHJvd3MuCiAgICAgKiBMYXJnZXIgYmF0Y2ggc2l6ZSB3aWxsIGluY3JlYXNlIG1lbW9yeSBjb25zdW1wdGlvbiBidXQgd2lsbCByZWR1Y2UgbnVtYmVyIG9mIElPIG9wZXJhdGlvbnMuCiAgICAgKiBXaGVuIG5vdCBzZXQsIHRoZSBiYXRjaCBzaXplIGlzIHRha2VuIGZyb20gdGhlIGxhc3QgRGF0YUZyYW1lOjpiYXRjaFNpemUoKSBjYWxsLgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHBhcmFtIG51bGx8c3RyaW5nICRpZAogICAgICogQHBhcmFtIG51bGx8Q2FjaGUgJGNhY2hlIHJlYWRzIG9mIHRoaXMgY2FjaGUgbXVzdCBwYXNzIHRoZSBzYW1lIGluc3RhbmNlIHRvIGZyb21fY2FjaGUoKQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":167,"slug":"collect","name":"collect","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZWZvcmUgdHJhbnNmb3JtaW5nIHJvd3MsIGNvbGxlY3QgdGhlbSBhbmQgbWVyZ2UgaW50byBzaW5nbGUgUm93cyBpbnN0YW5jZS4KICAgICAqIFRoaXMgbWlnaHQgbGVhZCB0byBtZW1vcnkgaXNzdWVzIHdoZW4gcHJvY2Vzc2luZyBsYXJnZSBhbW91bnQgb2Ygcm93cywgdXNlIHdpdGggY2F1dGlvbi4KICAgICAqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":186,"slug":"collectrefs","name":"collectRefs","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"References","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGlzIG1ldGhvZCBhbGxvd3MgdG8gY29sbGVjdCByZWZlcmVuY2VzIHRvIGFsbCBlbnRyaWVzIHVzZWQgaW4gdGhpcyBwaXBlbGluZS4KICAgICAqCiAgICAgKiBgYGBwaHAKICAgICAqIChuZXcgRmxvdygpKQogICAgICogICAtPnJlYWQoRnJvbTo6Y2hhaW4oKSkKICAgICAqICAgLT5jb2xsZWN0UmVmcygkcmVmcyA9IHJlZnMoKSkKICAgICAqICAgLT5ydW4oKTsKICAgICAqIGBgYAogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":193,"slug":"constrain","name":"constrain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"constraint","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"constraints","type":[{"name":"Constraint","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":204,"slug":"count","name":"count","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICogUmV0dXJuIHRvdGFsIGNvdW50IG9mIHJvd3MgcHJvY2Vzc2VkIGJ5IHRoaXMgcGlwZWxpbmUuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":224,"slug":"crossjoin","name":"crossJoin","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"prefix","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"''"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":241,"slug":"display","name":"display","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gaW50ICRsaW1pdCBtYXhpbXVtIG51bWJlcnMgb2Ygcm93cyB0byBkaXNwbGF5CiAgICAgKiBAcGFyYW0gYm9vbHxpbnQgJHRydW5jYXRlIGZhbHNlIG9yIGlmIHNldCB0byAwIGNvbHVtbnMgYXJlIG5vdCB0cnVuY2F0ZWQsIG90aGVyd2lzZSBkZWZhdWx0IHRydW5jYXRlIHRvIDIwCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJhY3RlcnMKICAgICAqIEBwYXJhbSBGb3JtYXR0ZXIgJGZvcm1hdHRlcgogICAgICoKICAgICAqIEB0cmlnZ2VyCiAgICAgKgogICAgICogQHRocm93cyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":268,"slug":"drop","name":"drop","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBEcm9wIGdpdmVuIGVudHJpZXMuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":282,"slug":"dropduplicates","name":"dropDuplicates","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gUmVmZXJlbmNlfHN0cmluZyAuLi4kZW50cmllcwogICAgICoKICAgICAqIEBsYXp5CiAgICAgKgogICAgICogQHJldHVybiAkdGhpcwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":289,"slug":"duplicaterow","name":"duplicateRow","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"condition","type":[{"name":"mixed","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":308,"slug":"fetch","name":"fetch","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBCZSBhd2FyZSB0aGF0IGZldGNoIGlzIG5vdCBtZW1vcnkgc2FmZSBhbmQgd2lsbCBsb2FkIGFsbCByb3dzIGludG8gbWVtb3J5LgogICAgICogSWYgeW91IHdhbnQgdG8gc2FmZWx5IGl0ZXJhdGUgb3ZlciBSb3dzIHVzZSBvZSBvZiB0aGUgZm9sbG93aW5nIG1ldGhvZHM6LgogICAgICoKICAgICAqIERhdGFGcmFtZTo6Z2V0KCkgOiBcR2VuZXJhdG9yCiAgICAgKiBEYXRhRnJhbWU6OmdldEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqIERhdGFGcmFtZTo6Z2V0RWFjaEFzQXJyYXkoKSA6IFxHZW5lcmF0b3IKICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":325,"slug":"filter","name":"filter","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":337,"slug":"filters","name":"filters","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"functions","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxTY2FsYXJGdW5jdGlvbj4gJGZ1bmN0aW9ucwogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":351,"slug":"foreach","name":"forEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"callback","type":[{"name":"callable","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEBwYXJhbSBudWxsfGNhbGxhYmxlKFJvd3MgJHJvd3MsIEZsb3dDb250ZXh0ICRjb250ZXh0KSA6IHZvaWQgJGNhbGxiYWNrCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":372,"slug":"get","name":"get","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gaW5zdGFuY2Ugb2YgUm93cy4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxSb3dzPgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":391,"slug":"getasarray","name":"getAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZHMgZWFjaCByb3cgYXMgYW4gYXJyYXkuCiAgICAgKgogICAgICogQHRyaWdnZXIKICAgICAqCiAgICAgKiBAcmV0dXJuIFxHZW5lcmF0b3I8YXJyYXk8YXJyYXk8bWl4ZWQ+Pj4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":410,"slug":"geteachasarray","name":"getEachAsArray","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Generator","namespace":"","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBZaWVsZCBlYWNoIHJvdyBhcyBhbiBhcnJheS4KICAgICAqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIEByZXR1cm4gXEdlbmVyYXRvcjxhcnJheTxtaXhlZD4+CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":431,"slug":"groupby","name":"groupBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"GroupByAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Grouping","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"GroupedDataFrame","namespace":"Flow\\ETL\\DataFrame","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBHcm91cEJ5UmVmZXJlbmNlc3xSZWZlcmVuY2V8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBncm91cGVkIGJ5IG9uIGl0cyBvd24KICAgICAqIEBwYXJhbSBudWxsfEdyb3VwQnlBbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxnb3JpdGhtIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":450,"slug":"join","name":"join","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"dataFrame","type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."},{"name":"algorithm","type":[{"name":"JoinAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Join","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfEpvaW5BbGdvcml0aG1CdWlsZGVyICRhbGdvcml0aG0gbnVsbCBkZWZlcnMgdG8gY29uZmlndXJhdGlvbjsgYSBidWlsZGVyIHBpbnMgdGhlIGFsZ29yaXRobQogICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciB0aGlzIG9wZXJhdGlvbiBhbmQgc2tpcHMgYW55IGF1dG9tYXRpYyBjaG9pY2UKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":478,"slug":"joineach","name":"joinEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"factory","type":[{"name":"DataFrameFactory","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"on","type":[{"name":"Expression","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"type","type":[{"name":"Join","namespace":"Flow\\ETL\\Join","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Join\\Join::..."}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBKb2lucyBpbiBtZW1vcnkgcGVyIGJhdGNoOyBpdCBpcyBub3QgZ292ZXJuZWQgYnkgdGhlIGpvaW4gYWxnb3JpdGhtIGFuZCB0YWtlcyBubyBhbGdvcml0aG0gb3ZlcnJpZGUuCiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAcGFyYW0gc3RyaW5nfEpvaW4gJHR5cGUKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":494,"slug":"limit","name":"limit","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":508,"slug":"load","name":"load","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":554,"slug":"match","name":"match","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"schema","type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"validator","type":[{"name":"SchemaValidator","namespace":"Flow\\ETL","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBudWxsfFNjaGVtYVZhbGlkYXRvciAkdmFsaWRhdG9yIC0gd2hlbiBudWxsLCBTdHJpY3RWYWxpZGF0b3IgZ2V0cyBpbml0aWFsaXplZAogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":575,"slug":"offset","name":"offset","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"offset","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBTa2lwIGdpdmVuIG51bWJlciBvZiByb3dzIGZyb20gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF0YXNldC4KICAgICAqIFdoZW4gJG9mZnNldCBpcyBudWxsLCBub3RoaW5nIGhhcHBlbnMgKG5vIHJvd3MgYXJlIHNraXBwZWQpLgogICAgICoKICAgICAqIFBlcmZvcm1hbmNlIE5vdGU6IERhdGFGcmFtZSBtdXN0IGl0ZXJhdGUgdGhyb3VnaCBhbmQgcHJvY2VzcyBhbGwgc2tpcHBlZCByb3dzCiAgICAgKiB0byByZWFjaCB0aGUgb2Zmc2V0IHBvc2l0aW9uLiBGb3IgbGFyZ2Ugb2Zmc2V0cywgdGhpcyBjYW4gaW1wYWN0IHBlcmZvcm1hbmNlCiAgICAgKiBhcyB0aGUgZGF0YSBzb3VyY2Ugc3RpbGwgbmVlZHMgdG8gYmUgcmVhZCBhbmQgcHJvY2Vzc2VkIHVwIHRvIHRoZSBvZmZzZXQgcG9pbnQuCiAgICAgKgogICAgICogQHBhcmFtID9pbnQ8MCwgbWF4PiAkb2Zmc2V0CiAgICAgKgogICAgICogQGxhenkKICAgICAqCiAgICAgKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":589,"slug":"onerror","name":"onError","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"handler","type":[{"name":"ErrorHandler","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":601,"slug":"repartition","name":"repartition","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogU2h1ZmZsZXMgdGhlIHN0cmVhbSBzbyBldmVyeSByb3cgc2hhcmluZyB0aGUgZ2l2ZW4gY29sdW1ucyBhcnJpdmVzIGluIG9uZSBiYXRjaC4gSXQgZG9lcyBub3QKICAgICAqIHdyaXRlIGRpcmVjdG9yaWVzIC0gdGhhdCBpcyBkZWNsYXJlZCBvbiB0aGUgbG9hZGVyLCBgdG9fY3N2KC4uLiktPnBhcnRpdGlvbkJ5KCdyZWdpb24nKWAuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":613,"slug":"printrows","name":"printRows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"20"},{"name":"truncate","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"20"},{"name":"formatter","type":[{"name":"Formatter","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Formatter\\AsciiTableFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":633,"slug":"explain","name":"explain","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"trigger","type":[{"name":"Trigger","namespace":"Flow\\ETL\\Plan","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Plan\\Trigger::..."}],"return_type":[{"name":"Plan","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgcGxhbiAkdHJpZ2dlciB3b3VsZCBydW4gb3ZlciB0aGlzIGZyYW1lLCBmcm96ZW46IGxhdGVyIHZlcmJzIG9uIHRoaXMgZnJhbWUgZG8gbm90IHJlYWNoIGl0LiBUaGUgZGVmYXVsdAogICAgICogYWRkcyBubyBjb25zdW1lciBvZiBpdHMgb3duIC0gaXQgZHJhd3MgdGhlIGZyYW1lIGFzIGJ1aWx0LCBpdHMgY2hhaW4gYW5kIGl0cyBzaW5rcy4gdG9TdHJpbmcoKSBwcmludHMgaXQgYXMgYQogICAgICogdHJlZS4gQW5zd2VycyBmcm9tIHRoZSBwbGFuIHdpdGhvdXQgcmVhZGluZyBhIHJvdy4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":643,"slug":"printschema","name":"printSchema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"formatter","type":[{"name":"SchemaFormatter","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Row\\Formatter\\ASCIISchemaFormatter::..."}],"return_type":[{"name":"void","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":651,"slug":"rename","name":"rename","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"from","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"to","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":658,"slug":"renameeach","name":"renameEach","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"strategies","type":[{"name":"RenameEntryStrategy","namespace":"Flow\\ETL\\Transformer\\Rename","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":669,"slug":"rows","name":"rows","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6dHJhbnNmb3JtIG1ldGhvZC4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":686,"slug":"run","name":"run","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"analyze","type":[{"name":"Analyze","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"Report","namespace":"Flow\\ETL\\Dataset","is_nullable":true,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAdHJpZ2dlcgogICAgICoKICAgICAqIFdoZW4gYW5hbHl6aW5nIHBpcGVsaW5lIGV4ZWN1dGlvbiB3ZSBjYW4gY2hvc2UgdG8gY29sbGVjdCB2YXJpb3VzIG1ldHJpY3MgdGhyb3VnaCBhbmFseXplKCktPndpdGgqKCkgbWV0aG9kCiAgICAgKgogICAgICogLSBjb2x1bW4gc3RhdGlzdGljcyAtIGFuYWx5emUoKS0+d2l0aENvbHVtblN0YXRpc3RpY3MoKQogICAgICogLSBzY2hlbWEgLSBhbmFseXplKCktPndpdGhTY2hlbWEoKQogICAgICoKICAgICAqIEBwYXJhbSBBbmFseXplfGJvb2wgJGFuYWx5emUgLSB3aGVuIHNldCBydW4gd2lsbCByZXR1cm4gUmVwb3J0CiAgICAgKgogICAgICogQHJldHVybiAoJGFuYWx5emUgaXMgQW5hbHl6ZXx0cnVlID8gUmVwb3J0IDogbnVsbCkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":714,"slug":"schema","name":"schema","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"Schema","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEB0aHJvd3MgU2NoZW1hTm90RGVyaXZhYmxlRXhjZXB0aW9uCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":727,"slug":"select","name":"select","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogS2VlcCBvbmx5IGdpdmVuIGVudHJpZXMuCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":741,"slug":"sortby","name":"sortBy","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entries","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"algorithm","type":[{"name":"SortAlgorithmBuilder","namespace":"Flow\\ETL\\Config\\Sort","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBSZWZlcmVuY2V8U29ydFJlZmVyZW5jZXN8c3RyaW5nICRlbnRyaWVzIGEgc2luZ2xlIGNvbHVtbiBpcyBzb3J0ZWQgYnkgb24gaXRzIG93bgogICAgICogQHBhcmFtIG51bGx8U29ydEFsZ29yaXRobUJ1aWxkZXIgJGFsZ29yaXRobSBudWxsIGRlZmVycyB0byBjb25maWd1cmF0aW9uOyBhIGJ1aWxkZXIgcGlucyB0aGUgYWxnb3JpdGhtCiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIHRoaXMgb3BlcmF0aW9uIGFuZCBza2lwcyBhbnkgYXV0b21hdGljIGNob2ljZQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":755,"slug":"transform","name":"transform","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBBbGlhcyBmb3IgRGF0YUZyYW1lOjp3aXRoKCkuCiAgICAgKgogICAgICogQGxhenkKICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":766,"slug":"until","name":"until","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"function","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGZpbHRlciBhbmQgdW50aWwgaXMgdGhhdCBmaWx0ZXIgd2lsbCBrZWVwIGZpbHRlcmluZyByb3dzIHVudGlsIGV4dHJhY3RvcnMgZmluaXNoIHlpZWxkaW5nCiAgICAgKiByb3dzLiBVbnRpbCB3aWxsIHNlbmQgYSBTVE9QIHNpZ25hbCB0byB0aGUgRXh0cmFjdG9yIHdoZW4gdGhlIGNvbmRpdGlvbiBpcyBub3QgbWV0LgogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":780,"slug":"void","name":"void","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogVGhpcyBtZXRob2QgaXMgdXNlZnVsIG1vc3RseSBpbiBkZXZlbG9wbWVudCB3aGVuCiAgICAgKiB5b3Ugd2FudCB0byBwYXVzZSBwcm9jZXNzaW5nIGF0IGNlcnRhaW4gbW9tZW50IHdpdGhvdXQKICAgICAqIHJlbW92aW5nIGNvZGUuIEFsbCBvcGVyYXRpb25zIHdpbGwgZ2V0IHByb2Nlc3NlZCB1cCB0byB0aGlzIHBvaW50LAogICAgICogZnJvbSBoZXJlIG5vIHJvd3MgYXJlIHBhc3NlZCBmb3J3YXJkLgogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":790,"slug":"with","name":"with","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformations","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"WithEntry","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":818,"slug":"withentries","name":"withEntries","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"references","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICoKICAgICAqIEBwYXJhbSBhcnJheTxpbnQsIFdpdGhFbnRyeT58YXJyYXk8c3RyaW5nLCBTY2FsYXJGdW5jdGlvbnxXaW5kb3dGdW5jdGlvbnxXaXRoRW50cnk+ICRyZWZlcmVuY2VzCiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":836,"slug":"withentry","name":"withEntry","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"entry","type":[{"name":"Definition","namespace":"Flow\\ETL\\Schema","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"reference","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"WindowFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAcGFyYW0gRGVmaW5pdGlvbjxtaXhlZD58c3RyaW5nICRlbnRyeQogICAgICoKICAgICAqIEBsYXp5CiAgICAgKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame.php","start_line_in_file":849,"slug":"write","name":"write","class":"Flow\\ETL\\DataFrame","class_slug":"dataframe","parameters":[{"name":"sink","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Sink","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":"LyoqCiAgICAgKiBAbGF6eQogICAgICogQWxpYXMgZm9yIEVUTDo6bG9hZCBmdW5jdGlvbi4KICAgICAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":21,"slug":"aggregate","name":"aggregate","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"aggregations","type":[{"name":"AggregatingFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"DataFrame","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DataFrame\/GroupedDataFrame.php","start_line_in_file":28,"slug":"pivot","name":"pivot","class":"Flow\\ETL\\DataFrame\\GroupedDataFrame","class_slug":"groupeddataframe","parameters":[{"name":"ref","type":[{"name":"Reference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"values","type":[{"name":"PivotValues","namespace":"Flow\\ETL\\GroupBy","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"self","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[],"scalar_function_chain":false,"doc_comment":null}] \ No newline at end of file diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json index 2f2cf816ad..60c64fe1c6 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":283,"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":291,"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":297,"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":309,"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":316,"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":332,"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":353,"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":373,"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":379,"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":385,"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":391,"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":403,"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":417,"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":423,"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":429,"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":443,"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":457,"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":467,"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":481,"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":489,"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":499,"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":509,"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":519,"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":539,"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":545,"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":551,"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":561,"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":570,"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":576,"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":585,"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":595,"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":602,"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":608,"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":620,"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":626,"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":632,"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":638,"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":644,"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":650,"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":659,"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":665,"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":674,"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":680,"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":687,"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":693,"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":699,"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":708,"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":714,"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":725,"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":734,"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":743,"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":749,"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":758,"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":768,"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":777,"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":783,"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":789,"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":797,"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":810,"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":816,"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":822,"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":832,"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":841,"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":850,"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":856,"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":869,"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":878,"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":887,"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":893,"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":902,"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":908,"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":914,"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":920,"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":926,"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":938,"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":965,"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":995,"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":1001,"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":1007,"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":1013,"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":1019,"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":1025,"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":1031,"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":1037,"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":1043,"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":1049,"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":1055,"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":1061,"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":"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":1067,"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":1073,"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":1079,"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":1085,"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":1095,"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":1105,"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":1115,"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":1125,"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":1135,"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":1141,"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":1150,"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":1159,"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":1173,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."},{"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":1192,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."}],"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":1236,"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":1242,"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":1248,"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":1254,"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":1260,"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":1266,"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":1272,"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":1278,"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":1284,"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":1290,"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":1296,"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":1302,"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":1308,"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":1314,"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":1320,"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":1326,"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":1332,"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":1338,"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":1344,"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":1350,"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":1356,"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":1367,"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":1376,"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":1385,"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":1397,"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":1407,"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":1416,"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":1422,"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":1428,"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":1437,"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":1450,"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":1459,"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":1465,"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":1474,"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":1480,"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":1486,"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":1492,"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":1506,"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":1520,"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":1538,"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":1544,"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":1550,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1560,"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":1566,"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":1572,"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":1578,"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":1584,"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":1590,"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":1596,"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":1609,"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":1620,"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":1626,"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":1639,"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":1672,"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":1724,"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":1730,"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":1736,"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":1742,"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":1748,"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":1754,"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":1760,"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":1766,"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":1772,"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":1778,"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":1787,"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":1797,"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":1803,"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":1812,"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":1822,"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":1828,"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":1837,"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":1843,"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":1852,"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":1858,"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":1867,"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":1873,"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":1879,"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":1885,"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":1891,"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":1897,"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":1903,"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":1914,"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":1920,"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":1929,"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":1940,"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":1951,"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":1961,"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":1995,"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":2003,"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":2012,"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":2020,"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":2037,"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":2054,"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":2071,"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":2077,"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":2083,"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":2093,"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":2102,"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":2108,"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":2114,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":573,"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}],"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":582,"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":592,"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":599,"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":605,"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":617,"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":623,"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":629,"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":635,"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":641,"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":647,"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":656,"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":662,"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":671,"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":677,"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":684,"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":690,"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":696,"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":705,"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":711,"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":722,"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":731,"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":740,"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":746,"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":755,"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":765,"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":774,"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":780,"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":786,"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":794,"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":807,"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":813,"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":819,"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":829,"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":838,"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":847,"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":853,"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":866,"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":875,"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":884,"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":890,"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":899,"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":905,"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":911,"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":917,"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":923,"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":935,"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":962,"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":992,"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":998,"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":1004,"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":1010,"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":1016,"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":1022,"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":1028,"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":1034,"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":1040,"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":1046,"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":1052,"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":1058,"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":"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":1064,"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":1070,"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":1076,"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":1082,"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":1092,"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":1102,"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":1112,"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":1122,"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":1132,"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":1138,"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":1147,"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":1156,"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":1169,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."}],"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":1213,"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":1219,"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":1225,"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":1231,"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::..."},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"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":1241,"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":1247,"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":1253,"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":1259,"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":1265,"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":1271,"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":1277,"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":1283,"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":1289,"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":1295,"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":1301,"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":1307,"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":"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":1313,"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":1319,"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":1325,"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":1331,"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":1337,"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":1348,"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":1357,"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":1366,"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":1378,"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":1388,"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":1397,"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":1403,"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":1409,"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":1418,"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":1431,"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":1440,"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":1446,"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":1455,"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":1461,"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":1467,"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":1473,"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":1487,"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":1501,"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":1519,"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":1525,"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":1531,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1541,"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":1547,"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":1553,"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":1559,"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":1565,"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":1571,"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":1577,"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":1590,"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":1601,"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":1607,"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":1620,"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":1653,"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":1705,"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":1711,"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":1717,"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":1723,"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":1729,"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":1735,"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":1741,"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":1747,"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":1753,"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":1759,"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":1768,"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":1778,"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":1784,"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":1793,"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":1803,"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":1809,"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":1818,"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":1824,"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":1833,"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":1839,"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":1848,"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":1854,"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":1860,"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":1866,"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":1872,"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":1878,"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":1884,"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":1895,"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":1901,"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":1910,"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":1921,"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":1932,"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":1942,"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":1976,"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":1984,"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":1993,"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":2001,"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":2018,"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":2035,"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":2052,"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":2058,"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":2064,"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":2074,"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":2083,"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":2089,"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":2095,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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 From 844ffc7ea22c314932252d16e606dba3f1c330e4 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Tue, 29 Sep 2026 20:04:19 +0200 Subject: [PATCH 07/21] feat(flow-php/flow-php-ext): Parquet read and write inside flow_php - Rust Parquet core: row groups straight into native columns, offset/limit reads only the row groups needed - from_parquet()/to_parquet() use flow_php when loaded and no engine is given - Rows cast to the writer schema once, in the loader, for every engine - Flow float written as Parquet DOUBLE; invalid UTF-8 refused on write - PHP engine: nested columns read page by page, DELTA_BINARY_PACKED follows the spec, RLE booleans in v2 pages, required structs with null children --- .nix/pkgs/php-flow-php-ext/package.nix | 2 +- documentation/components/adapters/parquet.md | 21 + .../components/extensions/flow-php-ext.md | 40 +- documentation/upgrading.md | 30 + src/adapter/etl-adapter-parquet/composer.json | 3 + .../Adapter/Parquet/EngineParquetOpenSink.php | 26 + .../Parquet/EngineParquetOpenSource.php | 41 + .../Adapter/Parquet/EngineParquetOpener.php | 36 + .../Adapter/Parquet/NativeParquetOpenSink.php | 24 + .../Parquet/NativeParquetOpenSource.php | 43 + .../Adapter/Parquet/NativeParquetOpener.php | 37 + .../ETL/Adapter/Parquet/ParquetEncoder.php | 18 +- .../ETL/Adapter/Parquet/ParquetExtractor.php | 26 +- .../ETL/Adapter/Parquet/ParquetLoader.php | 48 +- .../ETL/Adapter/Parquet/ParquetOpenSink.php | 14 + .../ETL/Adapter/Parquet/ParquetOpenSource.php | 24 + .../ETL/Adapter/Parquet/ParquetOpener.php | 22 + .../ETL/Adapter/Parquet/ParquetOpeners.php | 22 + .../Parquet/ParquetSchemaConformance.php | 62 ++ .../ETL/Adapter/Parquet/ParquetSourceFile.php | 7 +- .../ETL/Adapter/Parquet/ParquetStoredType.php | 35 + .../ETL/Adapter/Parquet/SchemaConverter.php | 2 +- .../Tests/Context/ParquetFilesContext.php | 74 ++ .../Parquet/Tests/Integration/ParquetTest.php | 152 +++- .../Tests/Unit/EngineParquetOpenSinkTest.php | 42 + .../Unit/EngineParquetOpenSourceTest.php | 74 ++ .../Tests/Unit/EngineParquetOpenerTest.php | 55 ++ .../Tests/Unit/FlowToParquetSchemaTest.php | 2 +- .../Tests/Unit/NativeParquetOpenSinkTest.php | 83 ++ .../Unit/NativeParquetOpenSourceTest.php | 120 +++ .../Tests/Unit/NativeParquetOpenerTest.php | 53 ++ .../Parquet/Tests/Unit/ParquetEncoderTest.php | 11 - .../Tests/Unit/ParquetExtractorTest.php | 2 +- .../Parquet/Tests/Unit/ParquetOpenersTest.php | 40 + .../Unit/ParquetSchemaConformanceTest.php | 111 +++ .../Tests/Unit/ParquetSourceFileTest.php | 13 + .../Tests/Unit/ParquetStoredTypeTest.php | 54 ++ .../Unit/Plan/Explain/StepDetailsTest.php | 2 - src/extension/flow-php-ext/Cargo.lock | 149 +++- src/extension/flow-php-ext/Cargo.toml | 4 +- src/extension/flow-php-ext/composer.json | 3 +- .../Adapter/Parquet/NativeParquetReader.php | 44 + .../Adapter/Parquet/NativeParquetWriter.php | 40 + src/extension/flow-php-ext/src/backend.rs | 2 +- src/extension/flow-php-ext/src/lib.rs | 3 + .../flow-php-ext/src/parquet/canonical.rs | 793 ++++++++++++++++++ .../flow-php-ext/src/parquet/error.rs | 55 ++ src/extension/flow-php-ext/src/parquet/etl.rs | 243 ++++++ src/extension/flow-php-ext/src/parquet/mod.rs | 11 + .../flow-php-ext/src/parquet/options.rs | 370 ++++++++ .../flow-php-ext/src/parquet/read.rs | 284 +++++++ .../flow-php-ext/src/parquet/sink.rs | 31 + .../flow-php-ext/src/parquet/source.rs | 290 +++++++ .../flow-php-ext/src/parquet/write.rs | 55 ++ src/extension/flow-php-ext/src/render.rs | 55 +- .../tests/phpt/068_parquet_read_parity.phpt | 113 +++ .../tests/phpt/069_parquet_offset_limit.phpt | 71 ++ .../phpt/070_parquet_write_roundtrip.phpt | 114 +++ .../tests/phpt/071_parquet_no_leaks.phpt | 70 ++ .../phpt/072_parquet_allocations_counted.phpt | 58 ++ .../Double/FailingAppendDestinationStream.php | 48 ++ .../Tests/Double/FailingReadSourceStream.php | 59 ++ .../Parquet/Data/DeltaBinaryPackedDecoder.php | 18 +- .../Parquet/Data/DeltaBinaryPackedEncoder.php | 7 +- .../ColumnData/PagedFlatColumnValues.php | 50 ++ .../Flow/Parquet/Dremel/DremelAssembler.php | 5 +- .../Flow/Parquet/Dremel/ReadColumnData.php | 5 +- .../Flow/Parquet/Engine/PhpParquetEngine.php | 31 +- .../Flow/Parquet/Reader/ColumnDataDecoder.php | 18 + .../Parquet/Tests/Context/FlatColumnPages.php | 132 +++ .../Integration/IO/EdgeCasesReadingTest.php | 28 +- .../Integration/IO/SimpleTypesReadingTest.php | 23 + .../ColumnData/PagedFlatColumnValuesTest.php | 97 +++ .../Unit/Dremel/DremelStructuresTest.php | 50 ++ .../Tests/Unit/Dremel/ReadColumnDataTest.php | 20 + 75 files changed, 4787 insertions(+), 133 deletions(-) create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSink.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSource.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSink.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaConformance.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetStoredType.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSinkTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSourceTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSchemaConformanceTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetStoredTypeTest.php create mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php create mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php create mode 100644 src/extension/flow-php-ext/src/parquet/canonical.rs create mode 100644 src/extension/flow-php-ext/src/parquet/error.rs create mode 100644 src/extension/flow-php-ext/src/parquet/etl.rs create mode 100644 src/extension/flow-php-ext/src/parquet/mod.rs create mode 100644 src/extension/flow-php-ext/src/parquet/options.rs create mode 100644 src/extension/flow-php-ext/src/parquet/read.rs create mode 100644 src/extension/flow-php-ext/src/parquet/sink.rs create mode 100644 src/extension/flow-php-ext/src/parquet/source.rs create mode 100644 src/extension/flow-php-ext/src/parquet/write.rs create mode 100644 src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt create mode 100644 src/lib/filesystem/tests/Flow/Filesystem/Tests/Double/FailingAppendDestinationStream.php create mode 100644 src/lib/filesystem/tests/Flow/Filesystem/Tests/Double/FailingReadSourceStream.php create mode 100644 src/lib/parquet/src/Flow/Parquet/Dremel/ColumnData/PagedFlatColumnValues.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Context/FlatColumnPages.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ColumnData/PagedFlatColumnValuesTest.php diff --git a/.nix/pkgs/php-flow-php-ext/package.nix b/.nix/pkgs/php-flow-php-ext/package.nix index 2f11a72ac8..ebc7bab5af 100644 --- a/.nix/pkgs/php-flow-php-ext/package.nix +++ b/.nix/pkgs/php-flow-php-ext/package.nix @@ -58,7 +58,7 @@ let doCheck = false; meta = with lib; { - description = "Flow PHP native extension (Rust) - native column backend and CSV reader"; + description = "Flow PHP native extension (Rust) - native column backend, CSV reader, Parquet reader and writer"; license = licenses.mit; }; }; diff --git a/documentation/components/adapters/parquet.md b/documentation/components/adapters/parquet.md index 3091c46f65..8c4510f1eb 100644 --- a/documentation/components/adapters/parquet.md +++ b/documentation/components/adapters/parquet.md @@ -22,6 +22,27 @@ the robust and adaptable nature of the Flow PHP ecosystem. For detailed installation instructions, see the [installation page](/documentation/installation/packages/etl-adapter-parquet.md). +## Engines + +Without `engine:`, Parquet is read and written by the [`flow_php` extension](/documentation/components/extensions/flow-php-ext.md) +when it is loaded, else by `AdaptiveParquetEngine`. An explicit engine is always used: + +```php +read(from_parquet(__DIR__ . '/orders.parquet', engine: new PhpParquetEngine())) + ->write(to_parquet(__DIR__ . '/copy.parquet', engine: new PhpParquetEngine())) + ->run(); +``` + +Flow `float` columns are written as Parquet `DOUBLE`. + ## Schema The file footer is the schema: `from_parquet(...)->withSchema()` throws. Project with `columns:`, change types after diff --git a/documentation/components/extensions/flow-php-ext.md b/documentation/components/extensions/flow-php-ext.md index 855f4ba9e1..7fa4700b6c 100644 --- a/documentation/components/extensions/flow-php-ext.md +++ b/documentation/components/extensions/flow-php-ext.md @@ -8,7 +8,7 @@ package: flow-php/flow-php-ext [TOC] -This extension is Flow's native column backend and reads CSV natively in Rust via +This extension is Flow's native column backend and reads CSV and Parquet and writes Parquet natively in Rust via [ext-php-rs](https://github.com/extphprs/ext-php-rs). The pure-PHP implementations in `flow-php/etl` are the canonical behaviour reference and work without the extension - loading it is purely an optimization. @@ -64,3 +64,41 @@ The extension registers the interfaces `Flow\ETL\Column\{Backend, Column, Column `Flow\ETL\Column\{DefaultBackend, NativeColumn, NativeColumnBuilder}`, and `Flow\ETL\Adapter\CSV\RustCSVReaderNative` and `Flow\ETL\Adapter\CSV\RustColumnFoldNative`, which read CSV straight into native columns and narrow string columns to their types. + +## Parquet + +With the extension loaded, `from_parquet()` and `to_parquet()` without an `engine:` read and write Parquet inside the +extension: row groups become `NativeColumn`s, and `Rows` are written without a PHP value per cell. + +```php +read(from_parquet(__DIR__ . '/orders.parquet')->withOffset(50_000)) // only the row groups from row 50 000 are decoded + ->write(to_parquet(__DIR__ . '/copy.parquet')) + ->run(); + +df() + ->read(from_parquet(__DIR__ . '/orders.parquet', engine: new PhpParquetEngine())) // an explicit engine opts out + ->write(to_parquet(__DIR__ . '/copy.parquet', engine: new PhpParquetEngine())) + ->run(); +``` + +A column type the extension has no cast for is refused before the first batch, naming the engine that reads it: + +``` +Parquet column "emptylist" (Null) is not supported by the flow_php Parquet reader; read the file with +from_parquet($path, engine: new \Flow\Parquet\Engine\PhpParquetEngine()) +``` + +A string that is not valid UTF-8 is refused on write, naming the column and its 0-based row in the batch +(`Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8`). Everything the reader and writer allocate is counted by +`DefaultBackend::allocatedBytes()`. + +The extension also registers `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}`, the reader and +writer `from_parquet()` and `to_parquet()` use. diff --git a/documentation/upgrading.md b/documentation/upgrading.md index c788cf3a89..ec6ee92a68 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -858,6 +858,36 @@ public function eval(Rows $rows, FlowContext $context): Column | `discover_pivot_values()` over `'9', '10', '100'` - columns `9, 10, 100` | `10, 100, 9`; integer pivot values stay numeric | | `->stringMatch()` / `->stringMatchAll()` turned a PHP `\Error` into an exception `optional()` swallowed | an `\Error` propagates; `->jsonDecode()`, `cast()`, `->arrayPathExists()`, `->stringMatch*()` errors keep their cause as `getPrevious()` | +### 79) `flow-php/etl-adapter-parquet` - with `flow_php` loaded and no engine given, `flow_php` reads and writes Parquet + +| Before | After | +|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `from_parquet($path)` / `to_parquet($path)` - `AdaptiveParquetEngine` (arrow-ext when loaded, else the PHP engine) | with `flow_php` loaded: `flow_php` itself (row groups straight into native columns); without it: unchanged | +| `engine: new PhpParquetEngine()` / `new ArrowParquetEngine()` | honoured as before - an explicit engine opts out of `flow_php` | +| a column type arrow-ext could not read failed inside arrow-ext | refused before the first batch: `Parquet column "" () is not supported by the flow_php Parquet reader; read the file with from_parquet($path, engine: new \Flow\Parquet\Engine\PhpParquetEngine())` | +| `flow-php/etl-adapter-parquet` installable with any `flow_php` version | `conflict: ext-flow_php <0.45` - load a `flow_php` of this release or none | + +### 80) `flow-php/etl-adapter-parquet` - Flow `float` columns are written as Parquet `DOUBLE` + +| Before | After | +|---------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| +| `float_schema('amount')` written as Parquet `FLOAT` (32-bit): `0.14` read back as `0.14000000059604645` | written as `DOUBLE` (64-bit), read back exactly; readers of the file see a `DOUBLE` column | + +### 81) `flow-php/etl-adapter-parquet` - with `flow_php`, a string that is not valid UTF-8 is refused on write + +| Before | After | +|------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| +| without arrow-ext, `PhpParquetEngine` wrote `"\xff\xfe"` into a `STRING` column other readers reject (DuckDB: `is not valid UTF8`) | `Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8` - the row is 0-based within the batch written | +| with arrow-ext: `Column 'name': expected string, got string` | the same refusal; `engine: new PhpParquetEngine()` still writes the bytes | + +### 82) `flow-php/parquet` - `DELTA_BINARY_PACKED` follows the spec; affected files written by `PhpParquetEngine` must be rewritten + +| Before | After | +|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| +| `PhpParquetEngine` wrote `DELTA_BINARY_PACKED` blocks that other readers misread (a partial last block without all miniblock bit widths, zero-width miniblocks with 4 padding bytes) | spec-conformant blocks; DuckDB, arrow-rs and `flow_php` read the values back | +| it read other writers' `DELTA_BINARY_PACKED` `INT64` wrong after an outlier (`9223372036854645807` read as `9223372036788279061`, garbage after) | reads them as DuckDB and arrow-rs do | +| affected: `INT32`/`INT64` columns `PhpParquetEngine` wrote with `Option::WRITER_VERSION` `2` or `COLUMNS_ENCODINGS` `DELTA_BINARY_PACKED` (the default is version `1`, `PLAIN`) | no spec-conformant reader returns their values: read them with the Flow version that wrote them and write them again (or re-export from the source) | + --- ## Upgrading from 0.43.x to 0.44.x diff --git a/src/adapter/etl-adapter-parquet/composer.json b/src/adapter/etl-adapter-parquet/composer.json index 8a9b26f4d5..15c7c9ac65 100644 --- a/src/adapter/etl-adapter-parquet/composer.json +++ b/src/adapter/etl-adapter-parquet/composer.json @@ -16,6 +16,9 @@ "flow-php/etl": "self.version", "flow-php/parquet": "self.version" }, + "conflict": { + "ext-flow_php": "<0.45" + }, "config": { "optimize-autoloader": true, "sort-packages": true diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSink.php new file mode 100644 index 0000000000..aa8edbad71 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSink.php @@ -0,0 +1,26 @@ +writer->close(); + } + + public function write(Rows $rows): void + { + $this->writer->writeBatch($this->encoder->encode($rows)); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSource.php new file mode 100644 index 0000000000..a102839c24 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSource.php @@ -0,0 +1,41 @@ + $definition + ->entry() + ->name(), $schema->definitions())); + + foreach ($this->file->columns($batchSize, $names, $limit, $offset) as $chunk) { + $builder = new RowsBuilder($schema, $backend); + + foreach ($names as $name) { + $builder->column($name)->appendMany($chunk[$name]); + } + + yield $builder->finish(); + } + } + + public function close(): void {} +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php new file mode 100644 index 0000000000..01f5d07d01 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php @@ -0,0 +1,36 @@ +engine); + $writer->openForStream($stream, $schema); + + return new EngineParquetOpenSink($writer, new ParquetEncoder($schema)); + } + + public function source(ParquetSourceFile $file): ParquetOpenSource + { + return new EngineParquetOpenSource($file->file); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSink.php new file mode 100644 index 0000000000..bf44b7c53c --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSink.php @@ -0,0 +1,24 @@ +writer->close(); + } + + public function write(Rows $rows): void + { + $this->writer->write($rows); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php new file mode 100644 index 0000000000..f119687fd9 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php @@ -0,0 +1,43 @@ +reader?->close(); + $reader = $this->reader = new NativeParquetReader($this->stream, $schema, $batchSize, $offset, $limit); + + while (($batch = $reader->next()) !== null) { + $columns = []; + $native = $batch->columns(); + + // every batch goes through the configured backend, which keeps its own columns and copies the native ones + foreach ($schema->definitions() as $name => $definition) { + $columns[$name] = $backend->adopt($definition, $native[$name]); + } + + yield Rows::fromColumns($schema, $columns, $batch->count()); + } + } + + public function close(): void + { + $this->reader?->close(); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php new file mode 100644 index 0000000000..359e32200c --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php @@ -0,0 +1,37 @@ +stream); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetEncoder.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetEncoder.php index f5956dd057..59e91a3805 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetEncoder.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetEncoder.php @@ -8,24 +8,26 @@ use Flow\ETL\Adapter\Parquet\ValueConverter\ValueConverters; use Flow\ETL\Rows; use Flow\Parquet\ParquetFile\Schema as ParquetSchema; -use Flow\Types\Type; use function array_key_exists; final class ParquetEncoder { /** - * @var array, ?ValueConverter}> + * @var array */ private array $encodePlan; public function __construct(ParquetSchema $schema) { - $converter = new SchemaConverter(); $encodePlan = []; foreach ($schema->columns() as $column) { - $encodePlan[$column->name()] = [$converter->parquetToFlowType($column), ValueConverters::for($column)]; + $valueConverter = ValueConverters::for($column); + + if ($valueConverter !== null) { + $encodePlan[$column->name()] = $valueConverter; + } } $this->encodePlan = $encodePlan; @@ -51,13 +53,9 @@ public function encode(Rows $rows): array $values[$name] = $column[$i]; } - foreach ($this->encodePlan as $name => [$type, $valueConverter]) { + foreach ($this->encodePlan as $name => $valueConverter) { if (array_key_exists($name, $values) && $values[$name] !== null) { - $values[$name] = $type->cast($values[$name]); - - if ($valueConverter !== null) { - $values[$name] = $valueConverter->encode($values[$name]); - } + $values[$name] = $valueConverter->encode($values[$name]); } } 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 e2eec51e67..e21aa43080 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 @@ -17,7 +17,6 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Validator\StrictValidator; use Flow\Filesystem\Filesystem; @@ -109,8 +108,11 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $target = $this->schema(); $fileColumns = $this->fileColumns($this->filesystem, $this->path); + $opener = ParquetOpeners::select($this->engine); foreach ($this->files($pathFilter) as $file) { + $source = null; + // finally, not a close() per exit: the limit/STOP returns below and an abandoned // generator have to release the handle too (b73) try { @@ -140,21 +142,16 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $constants = $fileColumns->forFile($file->source(), $rowsSchema); $matchTo = !$rowsSchema->isSame($target) ? $target : null; - foreach ($file->file->columns( + $source = $file->open($opener); + + foreach ($source->batches( + $body, $batchSize, - $this->columns, - $limit === null ? null : $limit - $yielded, $fileOffset, - ) as $chunk) { - $builder = new RowsBuilder($body, $backend); - - foreach ($body->definitions() as $definition) { - $builder - ->column($definition->entry()->name()) - ->appendMany($chunk[$definition->entry()->name()]); - } - - $rows = $constants->fillRows($builder->finish(), $rowsSchema, $backend); + $limit === null ? null : $limit - $yielded, + $backend, + ) as $rows) { + $rows = $constants->fillRows($rows, $rowsSchema, $backend); if ($matchTo !== null) { $rows = $rows->matchTo($matchTo); @@ -175,6 +172,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $fileOffset = max($fileOffset - $fileRows, 0); } finally { + $source?->close(); $file->close(); } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php index 905f75614c..3b0639cff4 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php @@ -19,18 +19,16 @@ use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\Filesystem\DestinationStream; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; use Flow\Filesystem\Path\Option; use Flow\Filesystem\Path\Option\ContentType; -use Flow\Parquet\Engine\AdaptiveParquetEngine; use Flow\Parquet\Option as ParquetOption; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Compressions; -use Flow\Parquet\Writer; +use Flow\Parquet\ParquetFile\Schema as ParquetSchema; use Throwable; use function sprintf; @@ -45,19 +43,23 @@ final class ParquetLoader implements Closure, Discardable, FileLoader, Loader, P private ?FilesSink $files = null; - /** @var array */ + /** @var array */ private array $writers = []; private Compressions $compressions = Compressions::SNAPPY; private readonly SchemaConverter $converter; - private ?ParquetEncoder $encoder = null; - private ?ParquetEngine $engine = null; private ?Schema $inferredSchema = null; + private ?ParquetSchemaConformance $conformance = null; + + private ?ParquetOpener $opener = null; + + private ?ParquetSchema $parquetSchema = null; + private Options $options; private readonly Path $path; @@ -126,13 +128,24 @@ public function load(Rows $rows, FlowContext $context): void $this->inferredSchema ??= $rows->schema()->makeNullable(); } - foreach ($this->router->route($rows) as [$partitions, $group]) { + $opener = $this->opener ??= ParquetOpeners::select($this->engine); + $parquetSchema = $this->parquetSchema ??= $this->converter->toParquet($this->schema()); + $conformed = ($this->conformance ??= new ParquetSchemaConformance($parquetSchema))->conform( + $rows, + $context->backend(), + ); + + foreach ($this->router->route($conformed) as [$partitions, $group]) { $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( $partitions->toArray(), ); - ($this->writers[$stream->path()->uri()] ??= - $this->openWriter($stream))->writeBatch($this->encoder()->encode($group)); + ($this->writers[$stream->path()->uri()] ??= $opener->sink( + $stream, + $parquetSchema, + $this->compressions, + $this->options, + ))->write($group); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); @@ -197,23 +210,6 @@ private function closeWriters(): void } } - private function encoder(): ParquetEncoder - { - return $this->encoder ??= new ParquetEncoder($this->converter->toParquet($this->schema())); - } - - private function openWriter(DestinationStream $stream): Writer - { - $writer = new Writer( - compression: $this->compressions, - options: $this->options, - engine: $this->engine ?? new AdaptiveParquetEngine(), - ); - $writer->openForStream($stream, $this->converter->toParquet($this->schema())); - - return $writer; - } - private function schema(): Schema { return ($this->schema diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php new file mode 100644 index 0000000000..9929b33f6d --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php @@ -0,0 +1,14 @@ + $batchSize + * + * @return Generator + */ + public function batches(Schema $schema, int $batchSize, ?int $offset, ?int $limit, Backend $backend): Generator; + + public function close(): void; +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php new file mode 100644 index 0000000000..2f2f06fe80 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php @@ -0,0 +1,22 @@ + new EngineParquetOpener($engine), + extension_loaded('flow_php') => new NativeParquetOpener(), + default => new EngineParquetOpener(new AdaptiveParquetEngine()), + }; + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaConformance.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaConformance.php new file mode 100644 index 0000000000..cc494baacf --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaConformance.php @@ -0,0 +1,62 @@ +> + */ + private array $definitions; + + public function __construct(ParquetSchema $schema) + { + $definitions = []; + + foreach ((new SchemaConverter()) + ->toFlow($schema) + ->definitions() as $definition) { + $definitions[$definition->entry()->name()] = $definition; + } + + $this->definitions = $definitions; + } + + public function conform(Rows $rows, Backend $backend): Rows + { + $columns = $rows->columns(); + $definitions = []; + $cast = false; + + foreach ($rows->schema()->definitions() as $key => $own) { + $writer = $this->definitions[$own->entry()->name()] ?? null; + + if ( + $writer === null + || ParquetStoredType::of($writer->type()->normalize()) === ParquetStoredType::of( + $own->type()->normalize(), + ) + ) { + $definitions[] = $own; + + continue; + } + + $builder = $backend->builder($writer); + $builder->appendMany($columns[$key]->values()); + $columns[$key] = $builder->finish(); + $definitions[] = $writer; + $cast = true; + } + + return $cast ? Rows::fromColumns(new Schema(...$definitions), $columns, $rows->count()) : $rows; + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php index 6ee4a400a4..e902a22a50 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php @@ -21,7 +21,7 @@ */ public function __construct( public ParquetFile $file, - private SourceStream $stream, + public SourceStream $stream, private SourceFile $source, private SchemaConverter $converter, private array $columns, @@ -32,6 +32,11 @@ public function close(): void $this->stream->close(); } + public function open(ParquetOpener $opener): ParquetOpenSource + { + return $opener->source($this); + } + /** * Pruning belongs to the describer, not the fold: it is applied per file, before the merge. */ diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetStoredType.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetStoredType.php new file mode 100644 index 0000000000..9bdeaed5de --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetStoredType.php @@ -0,0 +1,35 @@ + $normalized Type::normalize() + * + * @return array + */ + public static function of(array $normalized): array + { + if (array_key_exists('type', $normalized) && $normalized['type'] === 'datetime') { + unset($normalized['zone']); + } + + // @mago-ignore analysis:mixed-assignment + foreach ($normalized as $key => $value) { + if (is_array($value)) { + $normalized[$key] = self::of($value); + } + } + + return $normalized; + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php index 60c3a61170..56db8c9221 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php @@ -111,7 +111,7 @@ private function flowToParquet(string $name, Type $type, bool $nullable): Column $repetition = $nullable ? ParquetSchema\Repetition::OPTIONAL : ParquetSchema\Repetition::REQUIRED; return match ($type::class) { - FloatType::class => FlatColumn::float($name, $repetition), + FloatType::class => FlatColumn::double($name, $repetition), IntegerType::class => FlatColumn::int64($name, $repetition), HTMLType::class, HTMLElementType::class, diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php index 6725488098..307eab51f8 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php @@ -4,10 +4,23 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Context; +use Flow\ETL\Adapter\Parquet\NativeParquetOpenSink; +use Flow\ETL\Adapter\Parquet\NativeParquetWriter; +use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Rows; +use Flow\ETL\Schema as FlowSchema; use Flow\Filesystem\Filesystem; +use Flow\Parquet\Engine\Arrow\OptionsConverter; +use Flow\Parquet\Engine\Arrow\SchemaConverter as ArrowSchemaConverter; +use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Option; +use Flow\Parquet\Options; +use Flow\Parquet\ParquetFile\Encodings; +use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\Column; +use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\Reader; +use Flow\Parquet\Writer; use function array_map; use function Flow\ETL\Adapter\Parquet\to_parquet; @@ -15,6 +28,7 @@ use function Flow\ETL\DSL\from_rows; use function Flow\Filesystem\DSL\path; use function iterator_to_array; +use function range; final class ParquetFilesContext { @@ -57,4 +71,64 @@ public static function write(Filesystem $filesystem, array $files): void ->run(); } } + + /** + * `id` 0..$rows-1 and `name` "n", one row group per $rowsPerGroup rows. + */ + public static function rowGroups(Filesystem $filesystem, string $uri, int $rows, int $rowsPerGroup): void + { + $options = Options::default()->set(Option::ROW_GROUP_SIZE_BYTES, 1)->set( + Option::ROW_GROUP_SIZE_CHECK_INTERVAL, + $rowsPerGroup, + ); + $writer = new Writer(options: $options, engine: new PhpParquetEngine(options: $options)); + $writer->openForStream( + $filesystem->writeTo(path($uri)), + Schema::with(FlatColumn::int64('id'), FlatColumn::string('name')), + ); + $writer->writeBatch(array_map( + static fn(int $id): array => ['id' => $id, 'name' => 'n' . $id], + range(0, $rows - 1), + )); + $writer->close(); + } + + /** + * @return list> + */ + public static function phpEngineValues(Filesystem $filesystem, string $uri): array + { + return iterator_to_array( + (new Reader(engine: new PhpParquetEngine())) + ->readStream($filesystem->readFrom(path($uri))) + ->values(), + false, + ); + } + + public static function nativeSink(Filesystem $filesystem, string $uri, FlowSchema $schema): NativeParquetOpenSink + { + return new NativeParquetOpenSink( + new NativeParquetWriter( + $filesystem->writeTo(path($uri)), + ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), + 'SNAPPY', + OptionsConverter::toExtension(Options::default()), + ), + ); + } + + /** + * An int64 `id` column written by PhpParquetEngine with DELTA_BINARY_PACKED. + * + * @param list $ids + */ + public static function deltaEncoded(Filesystem $filesystem, string $uri, array $ids): void + { + $options = Options::default()->set(Option::COLUMNS_ENCODINGS, ['id' => Encodings::DELTA_BINARY_PACKED]); + $writer = new Writer(options: $options, engine: new PhpParquetEngine(options: $options)); + $writer->openForStream($filesystem->writeTo(path($uri)), Schema::with(FlatColumn::int64('id'))); + $writer->writeBatch(array_map(static fn(int $id): array => ['id' => $id], $ids)); + $writer->close(); + } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php index 5b88c7e569..abbb122a23 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php @@ -6,6 +6,7 @@ use DateTimeImmutable; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; +use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\Context\LoaderEndingContext; use Flow\ETL\Tests\Context\MemoryTelemetryContext; use Flow\ETL\Tests\Double\FakeExtractor; @@ -18,11 +19,16 @@ use Flow\Parquet\Engine\PhpParquetEngine; use Flow\Parquet\Option; use Flow\Parquet\Options; +use Flow\Parquet\ParquetEngine; use Flow\Types\Value\Json; use Flow\Types\Value\Uuid as FlowUuid; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Ramsey\Uuid\Uuid; use function array_keys; +use function array_map; use function extension_loaded; use function file_exists; use function Flow\ETL\Adapter\Parquet\from_parquet; @@ -31,6 +37,7 @@ use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\data_frame; use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\from_rows; use function Flow\ETL\DSL\from_sequence_number; @@ -59,10 +66,20 @@ use function Flow\Types\DSL\type_structure; use function Flow\Types\DSL\type_uuid; use function iterator_to_array; +use function range; use function unlink; final class ParquetTest extends FlowTestCase { + /** + * @return Generator + */ + public static function engines(): Generator + { + yield 'default opener' => [null]; + yield 'php engine' => [new PhpParquetEngine()]; + } + public function test_writing_and_reading_into_parquet(): void { $memory = memory_filesystem(); @@ -316,7 +333,8 @@ public function test_writing_and_reading_parquet_orders(): void static::assertEquals(1000, data_frame($config)->read(from_parquet($path))->count()); } - public function test_writing_with_provided_schema(): void + #[DataProvider('engines')] + public function test_writing_with_provided_schema(?ParquetEngine $engine): void { $memory = memory_filesystem(); $path = path('memory://var/file_schema.snappy.parquet'); @@ -340,6 +358,7 @@ public function test_writing_with_provided_schema(): void $path, filesystem: $memory, schema: schema(str_schema('id'), str_schema('name'), str_schema('uuid'), json_schema('json')), + engine: $engine, )) ->run(); @@ -358,12 +377,94 @@ public function test_writing_with_provided_schema(): void 'json' => [['id' => 1, 'name' => 'test'], ['id' => 2, 'name' => 'test']], ], ], - data_frame($config)->read(from_parquet($path, filesystem: $memory))->fetch()->toArray(), + data_frame($config) + ->read(from_parquet($path, filesystem: $memory, engine: $engine)) + ->fetch() + ->toArray(), ); static::assertTrue($memory->status($path)?->isFile()); } + /** + * Flow float is written as Parquet DOUBLE: no f32 rounding on the way back. + */ + #[DataProvider('engines')] + public function test_a_float_round_trips_exactly(?ParquetEngine $engine): void + { + $memory = memory_filesystem(); + $path = path('memory://var/floats.parquet'); + + data_frame() + ->read(from_rows(array_to_rows([ + ['amount' => 0.14], + ['amount' => 1234567890123456.8], + ], schema(float_schema('amount'))))) + ->write(to_parquet($path, filesystem: $memory, engine: $engine)) + ->run(); + + static::assertSame( + [['amount' => 0.14], ['amount' => 1234567890123456.8]], + data_frame() + ->read(from_parquet($path, filesystem: $memory, engine: $engine)) + ->fetch() + ->toArray(), + ); + } + + #[RequiresPhpExtension('flow_php')] + public function test_flow_php_refuses_a_string_that_is_not_valid_utf8(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8', + ); + + data_frame() + ->read(from_rows(array_to_rows([['name' => "\xff\xfe"]], schema(str_schema('name'))))) + ->write(to_parquet(path('memory://var/invalid.parquet'), filesystem: memory_filesystem())) + ->run(); + } + + /** + * 200 values: a full block and a partial one, both with zero-width miniblocks - read by arrow-rs, not only by PHP. + */ + #[RequiresPhpExtension('flow_php')] + public function test_a_php_written_delta_binary_packed_column_reads_back_through_flow_php(): void + { + $memory = memory_filesystem(); + $ids = array_map(static fn(int $i): int => $i * 3, range(0, 199)); + ParquetFilesContext::deltaEncoded($memory, 'memory://var/delta.parquet', $ids); + + static::assertSame( + array_map(static fn(int $id): array => ['id' => $id], $ids), + data_frame() + ->read(from_parquet(path('memory://var/delta.parquet'), filesystem: $memory)) + ->fetch() + ->toArray(), + ); + } + + #[RequiresPhpExtension('flow_php')] + public function test_a_given_engine_is_honoured_with_flow_php_loaded(): void + { + $memory = memory_filesystem(); + $path = path('memory://var/engine.parquet'); + + data_frame() + ->read(from_rows(array_to_rows([['name' => "\xff\xfe"]], schema(str_schema('name'))))) + ->write(to_parquet($path, filesystem: $memory, engine: new PhpParquetEngine())) + ->run(); + + static::assertSame( + [['name' => "\xff\xfe"]], + data_frame() + ->read(from_parquet($path, filesystem: $memory, engine: new PhpParquetEngine())) + ->fetch() + ->toArray(), + ); + } + public function test_transformation_loader_writes_all_batches_to_parquet(): void { data_frame() @@ -532,7 +633,51 @@ public function test_partitions_written_with_an_explicit_php_engine_each_get_the static::assertSame([['v' => 4]], ParquetFilesContext::values($memory, 'memory://var/engine/p=c/file.parquet')); } - public function test_write_columns_keeps_the_partition_column_in_the_file(): void + #[DataProvider('engines')] + public function test_a_zoned_datetime_reads_back_as_the_same_instant(?ParquetEngine $engine): void + { + $memory = memory_filesystem(); + $path = path('memory://var/zoned.parquet'); + + data_frame() + ->read(from_rows(array_to_rows([[ + 'at' => new DateTimeImmutable('2026-09-01 12:30:00.123456 Europe/Warsaw'), + ]], schema(datetime_schema('at', zone: 'Europe/Warsaw'))))) + ->write(to_parquet($path, filesystem: $memory, engine: $engine)) + ->run(); + + static::assertEquals( + [['at' => new DateTimeImmutable('2026-09-01 10:30:00.123456 UTC')]], + data_frame() + ->read(from_parquet($path, filesystem: $memory, engine: $engine)) + ->fetch() + ->toArray(), + ); + } + + #[DataProvider('engines')] + public function test_every_partition_is_written_cast_to_the_declared_schema(?ParquetEngine $engine): void + { + $memory = memory_filesystem(); + + data_frame() + ->read(from_array([['group' => 'a', 'id' => 1], ['group' => 'b', 'id' => 2], ['group' => 'a', 'id' => 3]])) + ->write(to_parquet( + path('memory://var/partitioned_cast/file.parquet'), + schema: schema(str_schema('group'), str_schema('id')), + filesystem: $memory, + engine: $engine, + )->partitionBy(partition_by('group'))) + ->run(); + + static::assertSame([[['id' => '1'], ['id' => '3']], [['id' => '2']]], [ + ParquetFilesContext::phpEngineValues($memory, 'memory://var/partitioned_cast/group=a/file.parquet'), + ParquetFilesContext::phpEngineValues($memory, 'memory://var/partitioned_cast/group=b/file.parquet'), + ]); + } + + #[DataProvider('engines')] + public function test_write_columns_keeps_the_partition_column_in_the_file(?ParquetEngine $engine): void { $memory = memory_filesystem(); @@ -546,6 +691,7 @@ public function test_write_columns_keeps_the_partition_column_in_the_file(): voi path('memory://var/write_columns/file.parquet'), schema: schema(str_schema('id'), datetime_schema('date'), int_schema('clicks')), filesystem: $memory, + engine: $engine, )->partitionBy(partition_by('date')->writeColumns()), ) ->run(); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSinkTest.php new file mode 100644 index 0000000000..7717bba4c5 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSinkTest.php @@ -0,0 +1,42 @@ +toParquet($schema); + $writer = new Writer(engine: new PhpParquetEngine()); + $writer->openForStream($filesystem->writeTo(path('memory://out.parquet')), $parquetSchema); + $sink = new EngineParquetOpenSink($writer, new ParquetEncoder($parquetSchema)); + + $sink->write(array_to_rows([['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null]], $schema)); + $sink->write(array_to_rows([['id' => 3, 'name' => 'c']], $schema)); + $sink->close(); + + static::assertSame( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null], ['id' => 3, 'name' => 'c']], + ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), + ); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSourceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSourceTest.php new file mode 100644 index 0000000000..e278647a36 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSourceTest.php @@ -0,0 +1,74 @@ + $ids + */ + #[TestWith([null, null, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])] + #[TestWith([3, 5, [3, 4, 5, 6, 7]])] + #[TestWith([6, null, [6, 7, 8, 9]])] + #[TestWith([0, 1, [0]])] + public function test_offset_and_limit_cross_row_groups(?int $offset, ?int $limit, array $ids): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + + $read = []; + + foreach ((new EngineParquetOpenSource((new Reader( + engine: new PhpParquetEngine(), + ))->readStream($filesystem->readFrom(path('memory://groups.parquet')))))->batches( + schema(int_schema('id')), + 3, + $offset, + $limit, + new PhpBackend(), + ) as $rows) { + static::assertLessThanOrEqual(3, $rows->count()); + $read = [...$read, ...$rows->column('id')->values()]; + } + + static::assertSame($ids, $read); + } + + public function test_batches_hold_the_schema_columns(): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + $source = new EngineParquetOpenSource((new Reader( + engine: new PhpParquetEngine(), + ))->readStream($filesystem->readFrom(path('memory://groups.parquet')))); + + $names = []; + + foreach ($source->batches(schema(str_schema('name')), 100, null, null, new PhpBackend()) as $rows) { + static::assertEquals(schema(str_schema('name')), $rows->schema()); + $names = [...$names, ...$rows->column('name')->values()]; + } + + $source->close(); + + static::assertSame(array_map(static fn(int $id): string => 'n' . $id, range(0, 9)), $names); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php new file mode 100644 index 0000000000..a362d44206 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php @@ -0,0 +1,55 @@ +sink( + $filesystem->writeTo(path('memory://out.parquet')), + (new SchemaConverter())->toParquet($schema), + Compressions::SNAPPY, + Options::default(), + ); + + $sink->write(array_to_rows([['id' => 1], ['id' => 2]], $schema)); + $sink->close(); + + static::assertSame( + [['id' => 1], ['id' => 2]], + ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), + ); + } + + public function test_source_reads_the_file_through_its_parquet_file(): void + { + $file = ParquetSourceFileContext::over(new NativeLocalFilesystem()); + + static::assertEquals( + new EngineParquetOpenSource($file->file), + (new EngineParquetOpener(new PhpParquetEngine()))->source($file), + ); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/FlowToParquetSchemaTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/FlowToParquetSchemaTest.php index c1f41b9f04..8fce623443 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/FlowToParquetSchemaTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/FlowToParquetSchemaTest.php @@ -38,7 +38,7 @@ public function test_convert_etl_entries_to_parquet_fields(): void FlatColumn::int64('integer', ParquetSchema\Repetition::REQUIRED), FlatColumn::boolean('boolean', ParquetSchema\Repetition::REQUIRED), FlatColumn::string('string', ParquetSchema\Repetition::REQUIRED), - FlatColumn::float('float', ParquetSchema\Repetition::REQUIRED), + FlatColumn::double('float', ParquetSchema\Repetition::REQUIRED), FlatColumn::dateTime('datetime', ParquetSchema\Repetition::REQUIRED), FlatColumn::json('json', ParquetSchema\Repetition::REQUIRED), NestedColumn::list('list', ParquetSchema\ListElement::string(true), ParquetSchema\Repetition::REQUIRED), diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php new file mode 100644 index 0000000000..f7a04e331b --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php @@ -0,0 +1,83 @@ +write(array_to_rows( + [['id' => 1, 'name' => 'a', 'amount' => 0.14], ['id' => 2, 'name' => null, 'amount' => 1.5]], + $schema, + new PhpBackend(), + )); + $sink->close(); + + static::assertSame( + [['id' => 1, 'name' => 'a', 'amount' => 0.14], ['id' => 2, 'name' => null, 'amount' => 1.5]], + ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), + ); + } + + public function test_a_string_that_is_not_valid_utf8_is_refused_naming_column_and_row(): void + { + $schema = schema(str_schema('name')); + $sink = ParquetFilesContext::nativeSink(memory_filesystem(), 'memory://out.parquet', $schema); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'Parquet column "name" row 1 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8', + ); + + $sink->write(array_to_rows([['name' => 'ok'], ['name' => "\xff\xfe"]], $schema, new PhpBackend())); + } + + public function test_an_exception_append_throws_surfaces_as_itself(): void + { + $filesystem = memory_filesystem(); + $schema = schema(int_schema('id')); + $sink = new NativeParquetOpenSink( + new NativeParquetWriter( + new FailingAppendDestinationStream($filesystem->writeTo(path('memory://out.parquet'))), + ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), + 'SNAPPY', + OptionsConverter::toExtension(Options::default()), + ), + ); + $sink->write(array_to_rows([['id' => 1]], $schema)); + + $this->expectException(FilesystemRuntimeException::class); + $this->expectExceptionMessage('Appending to "memory://out.parquet" failed'); + + $sink->close(); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php new file mode 100644 index 0000000000..2179f93136 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php @@ -0,0 +1,120 @@ + $ids + */ + #[TestWith([null, null, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])] + #[TestWith([3, 5, [3, 4, 5, 6, 7]])] + #[TestWith([6, null, [6, 7, 8, 9]])] + #[TestWith([0, 1, [0]])] + public function test_offset_and_limit_cross_row_groups(?int $offset, ?int $limit, array $ids): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + + $read = []; + + foreach ((new NativeParquetOpenSource($filesystem->readFrom(path('memory://groups.parquet'))))->batches( + schema(int_schema('id')), + 3, + $offset, + $limit, + new DefaultBackend(), + ) as $rows) { + static::assertLessThanOrEqual(3, $rows->count()); + $read = [...$read, ...$rows->column('id')->values()]; + } + + static::assertSame($ids, $read); + } + + public function test_columns_are_adopted_by_the_backend(): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + $source = new NativeParquetOpenSource($filesystem->readFrom(path('memory://groups.parquet'))); + + $names = []; + + foreach ($source->batches(schema(str_schema('name')), 100, null, null, new PhpBackend()) as $rows) { + static::assertEquals(schema(str_schema('name')), $rows->schema()); + static::assertInstanceOf(ScalarColumn::class, $rows->column('name')); + $names = [...$names, ...$rows->column('name')->values()]; + } + + $source->close(); + + static::assertSame(array_map(static fn(int $id): string => 'n' . $id, range(0, 9)), $names); + } + + public function test_a_second_batches_call_closes_the_first_reader(): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + $source = new NativeParquetOpenSource($filesystem->readFrom(path('memory://groups.parquet'))); + $first = $source->batches(schema(int_schema('id')), 3, null, null, new DefaultBackend()); + static::assertSame([0, 1, 2], $first->current()->column('id')->values()); + + $second = []; + + foreach ($source->batches(schema(int_schema('id')), 3, null, null, new DefaultBackend()) as $rows) { + $second = [...$second, ...$rows->column('id')->values()]; + } + + $first->next(); + + static::assertFalse($first->valid()); + static::assertSame(range(0, 9), $second); + } + + public function test_an_exception_the_stream_throws_surfaces_as_itself(): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Reading "memory://groups.parquet" failed'); + + (new NativeParquetOpenSource(new FailingReadSourceStream($filesystem->readFrom(path( + 'memory://groups.parquet', + ))))) + ->batches(schema(int_schema('id')), 3, null, null, new DefaultBackend()) + ->current(); + } + + public function test_close_before_batches_is_harmless(): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + + (new NativeParquetOpenSource($filesystem->readFrom(path('memory://groups.parquet'))))->close(); + + $this->expectNotToPerformAssertions(); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php new file mode 100644 index 0000000000..c05256fd36 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php @@ -0,0 +1,53 @@ +sink( + $filesystem->writeTo(path('memory://out.parquet')), + (new SchemaConverter())->toParquet($schema), + Compressions::ZSTD, + Options::default(), + ); + + $sink->write(array_to_rows([['id' => 1], ['id' => 2]], $schema)); + $sink->close(); + + static::assertSame( + [['id' => 1], ['id' => 2]], + ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), + ); + } + + public function test_source_reads_the_stream_the_file_holds(): void + { + $file = ParquetSourceFileContext::over(new NativeLocalFilesystem()); + + static::assertEquals(new NativeParquetOpenSource($file->stream), (new NativeParquetOpener())->source($file)); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetEncoderTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetEncoderTest.php index 1d869da1aa..b21e37dfac 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetEncoderTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetEncoderTest.php @@ -35,17 +35,6 @@ final class ParquetEncoderTest extends FlowTestCase { - public function test_encode_coerces_values_to_the_column_type(): void - { - static::assertSame( - [['id' => '1', 'name' => 'test']], - (new ParquetEncoder(ParquetSchema::with( - FlatColumn::string('id'), - FlatColumn::string('name'), - )))->encode(array_to_rows([['id' => 1, 'name' => 'test']], schema(int_schema('id'), str_schema('name')))), - ); - } - public function test_encode_keeps_datetime_and_scalar_values(): void { $at = new DateTimeImmutable('2024-01-01 12:00:00 UTC'); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php index 62999b137b..ad6b9fce6b 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php @@ -185,6 +185,6 @@ public function test_extract_builds_through_the_config_backend(): void ->extract(flow_context(config_builder()->backend($backend)->build())) ->current(); - static::assertGreaterThanOrEqual(1, $backend->builders()); + static::assertGreaterThanOrEqual(1, $backend->builders() + $backend->adopts()); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php new file mode 100644 index 0000000000..8c59438b8b --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php @@ -0,0 +1,40 @@ +toParquet(schema( + str_schema('id'), + str_schema('name'), + ))))->conform( + array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], + schema(int_schema('id'), str_schema('name')), + ), + new DefaultBackend(), + ); + + static::assertEquals(schema(str_schema('id'), str_schema('name')), $conformed->schema()); + static::assertSame(['1', '2'], $conformed->column('id')->values()); + } + + public function test_a_date_is_cast_to_a_datetime(): void + { + $conformed = (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema(datetime_schema( + 'at', + )))))->conform(array_to_rows([[ + 'at' => new DateTimeImmutable('2026-09-01'), + ]], schema(date_schema('at'))), new DefaultBackend()); + + static::assertEquals(schema(datetime_schema('at')), $conformed->schema()); + static::assertEquals([new DateTimeImmutable('2026-09-01 00:00:00 UTC')], $conformed->column('at')->values()); + } + + public function test_a_null_typed_column_is_cast_to_a_string_column(): void + { + $conformed = (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema(null_schema( + 'nothing', + )))))->conform(array_to_rows([['nothing' => null]], schema(null_schema('nothing'))), new DefaultBackend()); + + static::assertEquals(schema(str_schema('nothing', nullable: true)), $conformed->schema()); + static::assertSame([null], $conformed->column('nothing')->values()); + } + + public function test_a_matching_column_is_passed_on_as_it_is(): void + { + $rows = array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))); + + $conformed = (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema( + str_schema('id'), + str_schema('name'), + ))))->conform($rows, new DefaultBackend()); + + static::assertSame($rows->column('name'), $conformed->column('name')); + } + + public function test_a_zoned_datetime_column_is_passed_on_as_it_is(): void + { + $schema = schema( + datetime_schema('at', zone: 'Europe/Warsaw'), + list_schema('history', type_list(type_datetime('Asia/Tokyo'))), + ); + $rows = array_to_rows([[ + 'at' => new DateTimeImmutable('2026-09-01 10:00:00 UTC'), + 'history' => [new DateTimeImmutable('2026-09-01 11:00:00 UTC')], + ]], $schema); + + static::assertSame($rows, (new ParquetSchemaConformance((new SchemaConverter())->toParquet($schema)))->conform( + $rows, + new DefaultBackend(), + )); + } + + public function test_rows_matching_the_writer_schema_are_passed_on_as_they_are(): void + { + $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); + + static::assertSame($rows, (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema(int_schema( + 'id', + )))))->conform($rows, new DefaultBackend())); + } + + public function test_a_column_the_writer_does_not_know_is_passed_on_as_it_is(): void + { + $rows = array_to_rows([['id' => 1, 'extra' => 'x']], schema(int_schema('id'), str_schema('extra'))); + + static::assertSame($rows, (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema(int_schema( + 'id', + )))))->conform($rows, new DefaultBackend())); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php index 394a5f2515..e38c2a4173 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php @@ -4,11 +4,14 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; +use Flow\ETL\Adapter\Parquet\EngineParquetOpener; +use Flow\ETL\Adapter\Parquet\EngineParquetOpenSource; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetSourceFileContext; use Flow\ETL\Extractor\SourceFile; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; +use Flow\Parquet\Engine\PhpParquetEngine; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -25,6 +28,16 @@ public function test_close_releases_the_stream(): void static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); } + public function test_open_hands_the_file_to_the_opener(): void + { + $file = ParquetSourceFileContext::over(new NativeLocalFilesystem()); + + static::assertEquals( + new EngineParquetOpenSource($file->file), + $file->open(new EngineParquetOpener(new PhpParquetEngine())), + ); + } + public function test_schema_comes_from_the_file_footer(): void { static::assertEquals( diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetStoredTypeTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetStoredTypeTest.php new file mode 100644 index 0000000000..36cfaf0e20 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetStoredTypeTest.php @@ -0,0 +1,54 @@ +normalize()), + ParquetStoredType::of(type_datetime('Europe/Warsaw')->normalize()), + ); + } + + public function test_a_nested_datetime_zone_is_not_stored(): void + { + static::assertSame( + ParquetStoredType::of( + type_structure([ + 'at' => type_list(type_datetime()), + 'by' => type_map(type_string(), type_datetime()), + ])->normalize(), + ), + ParquetStoredType::of( + type_structure([ + 'at' => type_list(type_datetime('America/New_York')), + 'by' => type_map(type_string(), type_datetime('Asia/Tokyo')), + ])->normalize(), + ), + ); + } + + public function test_other_types_keep_their_shape(): void + { + static::assertSame(type_time_zone()->normalize(), ParquetStoredType::of(type_time_zone()->normalize())); + static::assertNotSame( + ParquetStoredType::of(type_list(type_integer())->normalize()), + ParquetStoredType::of(type_list(type_string())->normalize()), + ); + } +} 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 index ee505f89b8..872856ea41 100644 --- 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 @@ -4,8 +4,6 @@ namespace Flow\ETL\Tests\Unit\Plan\Explain; -use Flow\ETL\Bucketing\Buckets; -use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\Storage\MemoryBuckets; use Flow\ETL\Cardinality; use Flow\ETL\Constraint\UniqueConstraint; diff --git a/src/extension/flow-php-ext/Cargo.lock b/src/extension/flow-php-ext/Cargo.lock index 6c22e19ec1..b63938ba30 100644 --- a/src/extension/flow-php-ext/Cargo.lock +++ b/src/extension/flow-php-ext/Cargo.lock @@ -42,6 +42,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "android_system_properties" version = "0.1.6" @@ -100,11 +115,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "arrow-ipc" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcc41681ea80f521df14c36725b74d4c60702c47f0793af2be469c04527e2599" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", + "flatbuffers", +] + [[package]] name = "arrow-schema" version = "59.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10fab8d4563491417ba801fab29d205104d20d4bdf37bda6cd1cf425cff598cd" +dependencies = [ + "serde_core", + "serde_json", +] [[package]] name = "arrow-select" @@ -132,6 +165,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "base64ct" version = "1.8.3" @@ -154,6 +193,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "brotli" +version = "8.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -559,6 +619,16 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "flatbuffers" +version = "25.12.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3" +dependencies = [ + "bitflags", + "rustc_version", +] + [[package]] name = "flate2" version = "1.1.9" @@ -591,10 +661,12 @@ dependencies = [ "arrow-data", "arrow-schema", "arrow-select", + "bytes", "ext-php-rs", "ext-php-rs-build", "flow-batch-frame", "memchr", + "parquet", "serde", "serde_json", ] @@ -875,6 +947,15 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "lz4_flex" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecbdfe44b1bd960b68170b417450a628c43f7cf56bb3c5317e61cb230ee7f226" +dependencies = [ + "twox-hash", +] + [[package]] name = "lzma-rust2" version = "0.16.5" @@ -1049,6 +1130,37 @@ dependencies = [ "windows-link", ] +[[package]] +name = "parquet" +version = "59.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff322f54b1a0f9288e614ed1f2d329b380af5476420db19f46ffb865e1163d73" +dependencies = [ + "ahash", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-ipc", + "arrow-schema", + "arrow-select", + "base64 0.23.1", + "brotli", + "bytes", + "chrono", + "flate2", + "half", + "hashbrown", + "lz4_flex", + "num-bigint", + "num-integer", + "num-traits", + "seq-macro", + "simdutf8", + "snap", + "twox-hash", + "zstd", +] + [[package]] name = "pbkdf2" version = "0.13.0" @@ -1193,6 +1305,15 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.1.4" @@ -1278,6 +1399,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + [[package]] name = "serde" version = "1.0.228" @@ -1361,6 +1488,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "skeptic" version = "0.13.7" @@ -1388,6 +1521,12 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +[[package]] +name = "snap" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "199905e6153d6405f9728fe44daace35f8f837bbf830bb6e85fbd5828709a886" + [[package]] name = "strsim" version = "0.11.1" @@ -1447,6 +1586,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "twox-hash" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" + [[package]] name = "typed-path" version = "0.12.3" @@ -1483,7 +1628,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" dependencies = [ - "base64", + "base64 0.22.1", "der", "flate2", "log", @@ -1501,7 +1646,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" dependencies = [ - "base64", + "base64 0.22.1", "http", "httparse", "log", diff --git a/src/extension/flow-php-ext/Cargo.toml b/src/extension/flow-php-ext/Cargo.toml index 2288de06c5..ff9f05970f 100644 --- a/src/extension/flow-php-ext/Cargo.toml +++ b/src/extension/flow-php-ext/Cargo.toml @@ -10,11 +10,13 @@ crate-type = ["cdylib"] arrow-array = "59" arrow-buffer = "59" arrow-data = "59" -arrow-schema = "59" +arrow-schema = { version = "59", features = ["canonical_extension_types"] } arrow-select = "59" +bytes = "1" ext-php-rs = "0.15" flow-batch-frame = { path = "crates/flow-batch-frame" } memchr = "2" +parquet = { version = "59", default-features = false, features = ["arrow", "arrow_canonical_extension_types", "snap", "flate2", "flate2-zlib-rs", "zstd", "lz4", "brotli", "simdutf8"] } serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["raw_value"] } diff --git a/src/extension/flow-php-ext/composer.json b/src/extension/flow-php-ext/composer.json index 36039d089e..ce0ee0708a 100644 --- a/src/extension/flow-php-ext/composer.json +++ b/src/extension/flow-php-ext/composer.json @@ -1,7 +1,7 @@ { "name": "flow-php/flow-php-ext", "type": "php-ext", - "description": "Flow PHP native extension (Rust) - native column backend and CSV reader", + "description": "Flow PHP native extension (Rust) - native column backend, CSV reader, Parquet reader and writer", "keywords": ["serializer", "binary", "extension", "rust", "native", "dataframe"], "license": "MIT", "require": { @@ -10,6 +10,7 @@ "autoload": { "psr-4": { "Flow\\ETL\\Adapter\\CSV\\": "php/Flow/ETL/Adapter/CSV/", + "Flow\\ETL\\Adapter\\Parquet\\": "php/Flow/ETL/Adapter/Parquet/", "Flow\\Floe\\": "php/Flow/Floe/" } }, diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php new file mode 100644 index 0000000000..49abacc66d --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php @@ -0,0 +1,44 @@ + $batchSize + * + * @throws \Flow\ETL\Exception\InvalidArgumentException for a negative $offset or $limit + */ + public function __construct(SourceStream $stream, Schema $schema, int $batchSize, ?int $offset, ?int $limit) + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function close(): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * The next batch of at most $batchSize rows under the schema, null after the last. + */ + public function next(): ?Rows + { + throw new RuntimeException('flow_php extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php new file mode 100644 index 0000000000..49fea56280 --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php @@ -0,0 +1,40 @@ + $schema Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension() + * @param array $options Flow\Parquet\Engine\Arrow\OptionsConverter::toExtension() + */ + public function __construct(DestinationStream $stream, array $schema, string $compression, array $options) + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function close(): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * The writer schema's columns by name; a column the rows lack is written as nulls. + */ + public function write(Rows $rows): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/src/backend.rs b/src/extension/flow-php-ext/src/backend.rs index 3039034dbc..2fd13b71a8 100644 --- a/src/extension/flow-php-ext/src/backend.rs +++ b/src/extension/flow-php-ext/src/backend.rs @@ -25,7 +25,7 @@ const COLUMN_MISMATCH: &str = "Flow\\ETL\\Exception\\ColumnMismatchException"; const MIXED_TYPE: &str = "Flow\\Types\\Type\\Native\\MixedType"; /// A return typed `Flow\ETL\Column\Column`: `adopt()` hands back its argument itself. -pub struct ColumnValue(Zval); +pub struct ColumnValue(pub Zval); impl IntoZval for ColumnValue { const TYPE: DataType = DataType::Object(Some("Flow\\ETL\\Column\\Column")); diff --git a/src/extension/flow-php-ext/src/lib.rs b/src/extension/flow-php-ext/src/lib.rs index 7dc1d014b5..60fc6baa32 100644 --- a/src/extension/flow-php-ext/src/lib.rs +++ b/src/extension/flow-php-ext/src/lib.rs @@ -11,6 +11,7 @@ mod globals; mod interfaces; mod json_check; mod kind_builder; +mod parquet; mod physical; mod plan; mod render; @@ -191,4 +192,6 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { .class::() .class::() .class::() + .class::() + .class::() } diff --git a/src/extension/flow-php-ext/src/parquet/canonical.rs b/src/extension/flow-php-ext/src/parquet/canonical.rs new file mode 100644 index 0000000000..f2f14172f9 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/canonical.rs @@ -0,0 +1,793 @@ +//! The cast table between what arrow-rs reads from / writes to Parquet and the canonical arrays: one arrow type per +//! storage (`flow_batch_frame::kind::data_type`'s layout), keyed on the arrow `DataType` alone. Temporal and decimal +//! casts are this module's own - `arrow_cast` rounds toward zero and nulls out overflows. + +use std::sync::Arc; + +use arrow_array::cast::AsArray; +use arrow_array::types::{ + Date32Type, Date64Type, Decimal128Type, Decimal256Type, DecimalType, DurationMicrosecondType, Float32Type, + Float64Type, GenericBinaryType, Int16Type, Int32Type, Int64Type, Int8Type, Time32MillisecondType, Time32SecondType, + Time64NanosecondType, TimestampMicrosecondType, TimestampMillisecondType, TimestampNanosecondType, + TimestampSecondType, UInt16Type, UInt32Type, UInt64Type, UInt8Type, +}; +use arrow_array::{ + make_array, Array, ArrayRef, ArrowPrimitiveType, BinaryArray, Float64Array, GenericByteArray, ListArray, MapArray, + PrimitiveArray, StructArray, +}; +use arrow_buffer::{OffsetBuffer, ScalarBuffer}; +use arrow_schema::{DataType, Field, FieldRef, Fields, TimeUnit}; + +use crate::parquet::error::{parent_row, Error}; + +const UTC: &str = "UTC"; + +fn unsupported(data_type: &DataType) -> Error { + Error::Unsupported { + column: String::new(), + parquet: data_type.to_string(), + } +} + +fn timestamp() -> DataType { + DataType::Timestamp(TimeUnit::Microsecond, Some(UTC.into())) +} + +fn item(data_type: DataType) -> FieldRef { + Arc::new(Field::new("item", data_type, true)) +} + +fn entries(key: DataType, value: DataType) -> FieldRef { + Arc::new(Field::new( + "entries", + DataType::Struct(Fields::from(vec![Field::new("key", key, false), Field::new("value", value, true)])), + false, + )) +} + +/// The canonical type `canonical()` turns an array of `field`'s type into. +pub fn canonical_type(field: &Field) -> Result { + canonical_data_type(field.data_type()).map_err(|e| e.in_column(field.name())) +} + +fn canonical_data_type(data_type: &DataType) -> Result { + Ok(match data_type { + DataType::Boolean | DataType::Int64 | DataType::Float64 | DataType::Date32 | DataType::FixedSizeBinary(16) => { + data_type.clone() + } + DataType::Int8 + | DataType::Int16 + | DataType::Int32 + | DataType::UInt8 + | DataType::UInt16 + | DataType::UInt32 + | DataType::UInt64 => DataType::Int64, + DataType::Float32 | DataType::Decimal128(_, _) | DataType::Decimal256(_, _) => DataType::Float64, + DataType::Utf8 | DataType::Binary | DataType::LargeUtf8 | DataType::LargeBinary => DataType::Binary, + DataType::Timestamp(_, _) => timestamp(), + DataType::Time64(TimeUnit::Microsecond | TimeUnit::Nanosecond) + | DataType::Time32(TimeUnit::Millisecond | TimeUnit::Second) => DataType::Duration(TimeUnit::Microsecond), + DataType::Date64 => DataType::Date32, + DataType::List(element) | DataType::LargeList(element) => { + DataType::List(item(canonical_data_type(element.data_type())?)) + } + DataType::Map(field, _) => { + let (key, value) = map_fields(field)?; + + DataType::Map( + entries(canonical_data_type(key.data_type())?, canonical_data_type(value.data_type())?), + false, + ) + } + DataType::Struct(fields) => DataType::Struct(struct_fields(fields)?), + other => return Err(unsupported(other)), + }) +} + +fn map_fields(entries: &FieldRef) -> Result<(&FieldRef, &FieldRef), Error> { + match entries.data_type() { + DataType::Struct(fields) if fields.len() == 2 => Ok((&fields[0], &fields[1])), + other => Err(unsupported(other)), + } +} + +fn struct_fields(fields: &Fields) -> Result { + fields + .iter() + .map(|field| Ok(Field::new(field.name(), canonical_data_type(field.data_type())?, true))) + .collect() +} + +/// `array` (of `field`'s type, as arrow-rs read it) as its canonical array; refusals name `field`. +pub fn canonical(field: &Field, array: &ArrayRef) -> Result { + cast(array).map_err(|e| e.in_column(field.name())) +} + +fn widened(array: &ArrayRef) -> ArrayRef +where + T::Native: Into, +{ + Arc::new(array.as_primitive::().unary::<_, Int64Type>(Into::into)) +} + +/// Every valid value through `f`; the first `None` refuses its row. +fn checked( + array: &ArrayRef, + f: impl Fn(T::Native) -> Option, +) -> Result, Error> { + let input = array.as_primitive::(); + let mut values = Vec::with_capacity(input.len()); + + for (row, value) in input.values().iter().enumerate() { + values.push(if input.is_null(row) { + O::Native::default() + } else { + f(*value).ok_or(Error::Overflow { + column: String::new(), + row, + })? + }); + } + + Ok(PrimitiveArray::new(ScalarBuffer::from(values), input.nulls().cloned())) +} + +fn retagged(array: &ArrayRef, to: DataType) -> ArrayRef { + make_array(unsafe { array.to_data().into_builder().data_type(to).build_unchecked() }) +} + +fn micros>(array: &ArrayRef, f: impl Fn(i64) -> Option) -> Result { + Ok(Arc::new(checked::(array, f)?.with_timezone(UTC))) +} + +fn decimals(array: &ArrayRef, precision: u8, scale: i8) -> Result { + let input = array.as_primitive::(); + let mut values = Vec::with_capacity(input.len()); + + for (row, value) in input.values().iter().enumerate() { + values.push(if input.is_null(row) { + 0.0 + } else { + T::format_decimal(*value, precision, scale) + .parse::() + .map_err(|e| Error::Arrow(arrow_schema::ArrowError::ParseError(e.to_string())))? + }); + } + + Ok(Arc::new(Float64Array::new(ScalarBuffer::from(values), input.nulls().cloned()))) +} + +/// Large offsets narrowed to i32 and rebased to 0, with the values they span. +fn narrowed(offsets: &[i64]) -> Result, Error> { + let first = offsets[0]; + let narrowed = offsets + .iter() + .enumerate() + .map(|(i, offset)| { + i32::try_from(offset - first).map_err(|_| Error::Overflow { + column: String::new(), + row: i.saturating_sub(1), + }) + }) + .collect::, _>>()?; + + Ok(OffsetBuffer::new(ScalarBuffer::from(narrowed))) +} + +fn large_binary(array: &ArrayRef) -> Result { + let data = array.to_data(); + let offsets = data.buffers()[0].typed_data::(); + let offsets = &offsets[data.offset()..data.offset() + data.len() + 1]; + let values = data.buffers()[1].slice_with_length(offsets[0] as usize, (offsets[data.len()] - offsets[0]) as usize); + + Ok(Arc::new(GenericByteArray::>::new( + narrowed(offsets)?, + values, + data.nulls().cloned(), + ))) +} + +fn cast(array: &ArrayRef) -> Result { + Ok(match array.data_type() { + DataType::Boolean | DataType::Int64 | DataType::Float64 | DataType::Date32 | DataType::FixedSizeBinary(16) => { + Arc::clone(array) + } + DataType::Timestamp(TimeUnit::Microsecond, Some(zone)) if zone.as_ref() == UTC => Arc::clone(array), + DataType::Int8 => widened::(array), + DataType::Int16 => widened::(array), + DataType::Int32 => widened::(array), + DataType::UInt8 => widened::(array), + DataType::UInt16 => widened::(array), + DataType::UInt32 => widened::(array), + DataType::UInt64 => Arc::new(checked::(array, |value| i64::try_from(value).ok())?), + DataType::Float32 => Arc::new(array.as_primitive::().unary::<_, Float64Type>(f64::from)), + DataType::Utf8 | DataType::Binary => retagged(array, DataType::Binary), + DataType::LargeUtf8 | DataType::LargeBinary => large_binary(array)?, + DataType::Timestamp(TimeUnit::Microsecond, _) => retagged(array, timestamp()), + DataType::Timestamp(TimeUnit::Millisecond, _) => { + micros::(array, |ms| ms.checked_mul(1_000))? + } + DataType::Timestamp(TimeUnit::Second, _) => { + micros::(array, |s| s.checked_mul(1_000_000))? + } + DataType::Timestamp(TimeUnit::Nanosecond, _) => { + micros::(array, |ns| Some(ns.div_euclid(1_000)))? + } + DataType::Time64(TimeUnit::Microsecond) => retagged(array, DataType::Duration(TimeUnit::Microsecond)), + DataType::Time64(TimeUnit::Nanosecond) => Arc::new( + array + .as_primitive::() + .unary::<_, DurationMicrosecondType>(|ns| ns.div_euclid(1_000)), + ), + DataType::Time32(TimeUnit::Millisecond) => Arc::new( + array + .as_primitive::() + .unary::<_, DurationMicrosecondType>(|ms| i64::from(ms) * 1_000), + ), + DataType::Time32(TimeUnit::Second) => Arc::new( + array + .as_primitive::() + .unary::<_, DurationMicrosecondType>(|s| i64::from(s) * 1_000_000), + ), + DataType::Date64 => Arc::new(checked::( + array, + |ms| i32::try_from(ms.div_euclid(86_400_000)).ok(), + )?), + DataType::Decimal128(precision, scale) => decimals::(array, *precision, *scale)?, + DataType::Decimal256(precision, scale) => decimals::(array, *precision, *scale)?, + DataType::List(_) => { + let list = array.as_list::(); + let values = cast(list.values()).map_err(|e| e.at_row(|child| parent_row(list.value_offsets(), child)))?; + + Arc::new(ListArray::try_new( + item(values.data_type().clone()), + list.offsets().clone(), + values, + list.nulls().cloned(), + )?) + } + DataType::LargeList(_) => { + let list = array.as_list::(); + let offsets = list.value_offsets(); + let (first, last) = (offsets[0] as usize, offsets[offsets.len() - 1] as usize); + let values = cast(&list.values().slice(first, last - first)) + .map_err(|e| e.at_row(|child| parent_row(offsets, child + first)))?; + + Arc::new(ListArray::try_new( + item(values.data_type().clone()), + narrowed(offsets)?, + values, + list.nulls().cloned(), + )?) + } + DataType::Map(field, _) => { + map_fields(field)?; + let map = array.as_map(); + let at_parent = |e: Error| e.at_row(|child| parent_row(map.value_offsets(), child)); + let keys = cast(map.keys()).map_err(at_parent)?; + let values = cast(map.values()).map_err(at_parent)?; + let field = entries(keys.data_type().clone(), values.data_type().clone()); + let DataType::Struct(fields) = field.data_type() else { + unreachable!("entries() builds a struct") + }; + + Arc::new(MapArray::try_new( + Arc::clone(&field), + map.offsets().clone(), + StructArray::try_new_with_length(fields.clone(), vec![keys, values], None, map.entries().len())?, + map.nulls().cloned(), + false, + )?) + } + DataType::Struct(fields) => { + let structure = array.as_struct(); + let children = structure.columns().iter().map(cast).collect::, _>>()?; + let fields = fields + .iter() + .zip(&children) + .map(|(field, child)| Field::new(field.name(), child.data_type().clone(), true)) + .collect::(); + + Arc::new(StructArray::try_new_with_length( + fields, + children, + structure.nulls().cloned(), + structure.len(), + )?) + } + other => return Err(unsupported(other)), + }) +} + +/// A canonical array as the writer schema's `target` type: the inverse retags, UTF-8 validated where Parquet requires +/// it, nested children renamed to the target's fields. Refusals carry no column - the writer names it. +pub fn to_parquet(array: &ArrayRef, target: &DataType) -> Result { + if array.data_type() == target { + return Ok(Arc::clone(array)); + } + + Ok(match (array.data_type(), target) { + (DataType::Binary, DataType::Utf8) => utf8(array)?, + (DataType::Duration(TimeUnit::Microsecond), DataType::Time64(TimeUnit::Microsecond)) => { + retagged(array, target.clone()) + } + (DataType::Timestamp(TimeUnit::Microsecond, Some(zone)), DataType::Timestamp(TimeUnit::Microsecond, _)) + if zone.as_ref() == UTC => + { + retagged(array, target.clone()) + } + (DataType::List(_), DataType::List(element)) => { + let list = array.as_list::(); + + Arc::new(ListArray::try_new( + Arc::clone(element), + list.offsets().clone(), + to_parquet(list.values(), element.data_type()) + .map_err(|e| e.at_row(|child| parent_row(list.value_offsets(), child)))?, + list.nulls().cloned(), + )?) + } + (DataType::Map(_, _), DataType::Map(field, sorted)) => { + let (key, value) = map_fields(field)?; + let DataType::Struct(fields) = field.data_type() else { + unreachable!("map_fields() matched a struct") + }; + let map = array.as_map(); + let at_parent = |e: Error| e.at_row(|child| parent_row(map.value_offsets(), child)); + + Arc::new(MapArray::try_new( + Arc::clone(field), + map.offsets().clone(), + StructArray::try_new_with_length( + fields.clone(), + vec![ + to_parquet(map.keys(), key.data_type()).map_err(at_parent)?, + to_parquet(map.values(), value.data_type()).map_err(at_parent)?, + ], + None, + map.entries().len(), + )?, + map.nulls().cloned(), + *sorted, + )?) + } + (DataType::Struct(from), DataType::Struct(fields)) if from.len() == fields.len() => { + let structure = array.as_struct(); + + Arc::new(StructArray::try_new_with_length( + fields.clone(), + structure + .columns() + .iter() + .zip(fields.iter()) + .map(|(child, field)| to_parquet(child, field.data_type())) + .collect::, _>>()?, + structure.nulls().cloned(), + structure.len(), + )?) + } + _ => return Err(unsupported(target)), + }) +} + +/// Binary as Utf8 over the same buffers once every value is valid UTF-8; else the first row that is not. +fn utf8(array: &ArrayRef) -> Result { + match array.to_data().into_builder().data_type(DataType::Utf8).build() { + Ok(data) => Ok(make_array(data)), + Err(error) => { + let binary: &BinaryArray = array.as_binary::(); + + Err((0..binary.len()) + .find(|row| binary.is_valid(*row) && std::str::from_utf8(binary.value(*row)).is_err()) + .map_or(Error::Arrow(error), |row| Error::InvalidUtf8 { + column: String::new(), + row, + })) + } + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use arrow_array::builder::{Int32Builder, ListBuilder, MapBuilder, StringBuilder}; + use arrow_array::cast::AsArray; + use arrow_array::types::{ + Date32Type, DurationMicrosecondType, Float64Type, Int64Type, Time64MicrosecondType, TimestampMicrosecondType, + }; + use arrow_array::{ + Array, ArrayRef, BinaryArray, BooleanArray, Date32Array, Date64Array, Decimal128Array, Decimal256Array, + DurationMicrosecondArray, FixedSizeBinaryArray, Float32Array, Float64Array, Int16Array, Int32Array, Int64Array, + Int8Array, LargeBinaryArray, LargeListArray, LargeStringArray, ListArray, StringArray, StructArray, + Time32MillisecondArray, Time32SecondArray, Time64MicrosecondArray, Time64NanosecondArray, + TimestampMicrosecondArray, TimestampMillisecondArray, TimestampNanosecondArray, TimestampSecondArray, + UInt16Array, UInt32Array, UInt64Array, UInt8Array, + }; + use arrow_buffer::i256; + use arrow_schema::{DataType, Field, Fields, TimeUnit}; + use flow_batch_frame::kind::{data_type, Field as KindField, Kind}; + + use super::{canonical, canonical_type, to_parquet}; + use crate::parquet::error::Error; + + fn read(array: ArrayRef) -> ArrayRef { + let field = Field::new("column", array.data_type().clone(), true); + let canonical = canonical(&field, &array).unwrap(); + + assert_eq!(canonical.data_type(), &canonical_type(&field).unwrap()); + + canonical + } + + fn refusal(array: ArrayRef) -> Error { + canonical(&Field::new("column", array.data_type().clone(), true), &array).unwrap_err() + } + + fn int64(array: &ArrayRef) -> Vec> { + array.as_primitive::().iter().collect() + } + + fn kind(kind: Kind) -> KindField { + KindField { + name: String::new(), + kind, + optional: true, + } + } + + #[test] + fn canonical_types_are_kept() { + let arrays: Vec = vec![ + Arc::new(BooleanArray::from(vec![Some(true), None])), + Arc::new(Int64Array::from(vec![Some(1), None])), + Arc::new(Float64Array::from(vec![Some(1.5), None])), + Arc::new(Date32Array::from(vec![Some(-1), None])), + Arc::new(FixedSizeBinaryArray::try_from_iter(vec![[7u8; 16]].into_iter()).unwrap()), + Arc::new(TimestampMicrosecondArray::from(vec![Some(-1), None]).with_timezone("UTC")), + ]; + + for array in arrays { + assert!(Arc::ptr_eq(&read(Arc::clone(&array)), &array)); + } + } + + #[test] + fn integers_widen_to_int64() { + let expected = vec![Some(-3), None, Some(7)]; + + assert_eq!(int64(&read(Arc::new(Int8Array::from(vec![Some(-3), None, Some(7)])))), expected); + assert_eq!(int64(&read(Arc::new(Int16Array::from(vec![Some(-3), None, Some(7)])))), expected); + assert_eq!(int64(&read(Arc::new(Int32Array::from(vec![Some(-3), None, Some(7)])))), expected); + assert_eq!(int64(&read(Arc::new(UInt8Array::from(vec![Some(255), None])))), vec![Some(255), None]); + assert_eq!(int64(&read(Arc::new(UInt16Array::from(vec![Some(65_535), None])))), vec![Some(65_535), None]); + assert_eq!( + int64(&read(Arc::new(UInt32Array::from(vec![Some(u32::MAX), None])))), + vec![Some(i64::from(u32::MAX)), None] + ); + assert_eq!( + int64(&read(Arc::new(UInt64Array::from(vec![Some(i64::MAX as u64), None])))), + vec![Some(i64::MAX), None] + ); + } + + #[test] + fn uint64_above_int64_is_refused_at_its_row() { + let error = refusal(Arc::new(UInt64Array::from(vec![Some(1), None, Some(i64::MAX as u64 + 1)]))); + + assert!(matches!(error, Error::Overflow { column, row: 2 } if column == "column")); + } + + #[test] + fn a_null_slot_never_overflows() { + let values = UInt64Array::new(vec![1, u64::MAX].into(), Some(vec![true, false].into())); + + assert_eq!(int64(&read(Arc::new(values))), vec![Some(1), None]); + } + + #[test] + fn float32_widens_to_float64() { + let canonical = read(Arc::new(Float32Array::from(vec![Some(0.5), None]))); + + assert_eq!(canonical.as_primitive::().iter().collect::>(), vec![Some(0.5), None]); + } + + #[test] + fn strings_and_binaries_are_binary() { + let expected: Vec> = vec![Some(b"a"), None, Some(b"")]; + + for array in [ + Arc::new(StringArray::from(vec![Some("a"), None, Some("")])) as ArrayRef, + Arc::new(BinaryArray::from(expected.clone())), + Arc::new(LargeStringArray::from(vec![Some("a"), None, Some("")])), + Arc::new(LargeBinaryArray::from(expected.clone())), + ] { + let canonical = read(array); + + assert_eq!(canonical.as_binary::().iter().collect::>(), expected); + } + } + + #[test] + fn a_sliced_large_string_is_rebased() { + let array = LargeStringArray::from(vec!["skipped", "kept", "too"]).slice(1, 2); + + assert_eq!( + read(Arc::new(array)).as_binary::().iter().collect::>(), + vec![Some(&b"kept"[..]), Some(&b"too"[..])] + ); + } + + #[test] + fn timestamps_are_utc_microseconds() { + let micros = |array: ArrayRef| -> Vec> { + read(array).as_primitive::().iter().collect() + }; + + assert_eq!(micros(Arc::new(TimestampMicrosecondArray::from(vec![Some(-7), None]))), vec![Some(-7), None]); + assert_eq!( + micros(Arc::new(TimestampMicrosecondArray::from(vec![Some(5)]).with_timezone("Europe/Warsaw"))), + vec![Some(5)] + ); + assert_eq!(micros(Arc::new(TimestampMillisecondArray::from(vec![Some(-2), None]))), vec![Some(-2_000), None]); + assert_eq!(micros(Arc::new(TimestampSecondArray::from(vec![Some(3)]))), vec![Some(3_000_000)]); + assert_eq!( + micros(Arc::new(TimestampNanosecondArray::from(vec![Some(-1_500), Some(1_999), None]))), + vec![Some(-2), Some(1), None] + ); + } + + #[test] + fn a_timestamp_beyond_microseconds_is_refused() { + let error = refusal(Arc::new(TimestampMillisecondArray::from(vec![Some(0), Some(i64::MAX)]))); + + assert!(matches!(error, Error::Overflow { row: 1, .. })); + assert!(matches!( + refusal(Arc::new(TimestampSecondArray::from(vec![Some(i64::MIN)]))), + Error::Overflow { row: 0, .. } + )); + } + + #[test] + fn times_are_microsecond_durations() { + let micros = |array: ArrayRef| -> Vec> { + read(array).as_primitive::().iter().collect() + }; + + assert_eq!(micros(Arc::new(Time64MicrosecondArray::from(vec![Some(5), None]))), vec![Some(5), None]); + assert_eq!(micros(Arc::new(Time64NanosecondArray::from(vec![Some(1_999), None]))), vec![Some(1), None]); + assert_eq!(micros(Arc::new(Time32MillisecondArray::from(vec![Some(2), None]))), vec![Some(2_000), None]); + assert_eq!(micros(Arc::new(Time32SecondArray::from(vec![Some(3)]))), vec![Some(3_000_000)]); + } + + #[test] + fn date64_floors_to_days() { + let days = read(Arc::new(Date64Array::from(vec![Some(-1), Some(86_400_000), None]))); + + assert_eq!(days.as_primitive::().iter().collect::>(), vec![Some(-1), Some(1), None]); + assert!(matches!(refusal(Arc::new(Date64Array::from(vec![Some(i64::MAX)]))), Error::Overflow { row: 0, .. })); + } + + #[test] + fn decimals_are_floats_through_their_decimal_text() { + let decimal128 = Decimal128Array::from(vec![Some(12_345), Some(-5), None]).with_precision_and_scale(9, 2).unwrap(); + let decimal256 = Decimal256Array::from(vec![Some(i256::from_i128(10_000_000_001)), None]) + .with_precision_and_scale(50, 10) + .unwrap(); + + assert_eq!( + read(Arc::new(decimal128)).as_primitive::().iter().collect::>(), + vec![Some(123.45), Some(-0.05), None] + ); + assert_eq!( + read(Arc::new(decimal256)).as_primitive::().iter().collect::>(), + vec![Some(1.0000000001), None] + ); + } + + #[test] + fn lists_are_renamed_to_the_kind_layout() { + let mut builder = ListBuilder::new(Int32Builder::new()).with_field(Field::new("element", DataType::Int32, false)); + builder.append_value([Some(1), Some(2)]); + builder.append_null(); + builder.append_value([Some(3)]); + let canonical = read(Arc::new(builder.finish())); + + assert_eq!(canonical.data_type(), &data_type(&Kind::List(Box::new(kind(Kind::Int64))))); + assert_eq!(int64(canonical.as_list::().values()), vec![Some(1), Some(2), Some(3)]); + assert!(canonical.is_null(1)); + } + + #[test] + fn large_lists_narrow_their_offsets() { + let array = LargeListArray::from_iter_primitive::(vec![ + Some(vec![Some(9)]), + Some(vec![Some(1), None]), + None, + ]) + .slice(1, 2); + let canonical = read(Arc::new(array)); + let list = canonical.as_list::(); + + assert_eq!(canonical.data_type(), &data_type(&Kind::List(Box::new(kind(Kind::Int64))))); + assert_eq!(list.value_offsets(), &[0, 2, 2]); + assert_eq!(int64(list.values()), vec![Some(1), None]); + } + + #[test] + fn maps_are_renamed_to_the_kind_layout() { + let mut builder = MapBuilder::new(None, StringBuilder::new(), Int32Builder::new()); + builder.keys().append_value("a"); + builder.values().append_value(1); + builder.append(true).unwrap(); + builder.append(false).unwrap(); + let canonical = read(Arc::new(builder.finish())); + + assert_eq!( + canonical.data_type(), + &data_type(&Kind::Map(Box::new(kind(Kind::Bytes)), Box::new(kind(Kind::Int64)))) + ); + assert_eq!(int64(canonical.as_map().values()), vec![Some(1)]); + assert!(canonical.is_null(1)); + } + + #[test] + fn structs_are_relabelled_nullable() { + let array = StructArray::from(vec![ + (Arc::new(Field::new("id", DataType::Int32, false)), Arc::new(Int32Array::from(vec![1, 2])) as ArrayRef), + ( + Arc::new(Field::new("name", DataType::Utf8, false)), + Arc::new(StringArray::from(vec!["a", "b"])) as ArrayRef, + ), + ]); + let canonical = read(Arc::new(array)); + + assert_eq!( + canonical.data_type(), + &data_type(&Kind::Struct(vec![ + KindField { + name: "id".into(), + kind: Kind::Int64, + optional: false + }, + KindField { + name: "name".into(), + kind: Kind::Bytes, + optional: false + }, + ])) + ); + assert_eq!(int64(canonical.as_struct().column(0)), vec![Some(1), Some(2)]); + } + + #[test] + fn a_nested_overflow_is_refused_at_its_parent_row() { + let values = Arc::new(UInt64Array::from(vec![1, 2, u64::MAX])); + let list = ListArray::new( + Arc::new(Field::new("element", DataType::UInt64, false)), + arrow_buffer::OffsetBuffer::new(vec![0, 2, 3].into()), + values, + None, + ); + + assert!(matches!(refusal(Arc::new(list)), Error::Overflow { row: 1, .. })); + } + + #[test] + fn unsupported_types_are_refused_naming_the_type() { + let field = Field::new("emptylist", DataType::List(Arc::new(Field::new("element", DataType::Null, true))), true); + + assert!(matches!( + canonical_type(&field), + Err(Error::Unsupported { column, parquet }) if column == "emptylist" && parquet == "Null" + )); + assert!(matches!( + canonical_type(&Field::new("f", DataType::FixedSizeBinary(8), true)), + Err(Error::Unsupported { .. }) + )); + assert!(matches!( + refusal(Arc::new(arrow_array::DurationSecondArray::from(vec![1]))), + Error::Unsupported { .. } + )); + } + + #[test] + fn to_parquet_keeps_equal_types() { + let array: ArrayRef = Arc::new(Int64Array::from(vec![1])); + + assert!(Arc::ptr_eq(&to_parquet(&array, &DataType::Int64).unwrap(), &array)); + } + + #[test] + fn to_parquet_retags_temporal_types() { + let time: ArrayRef = Arc::new(DurationMicrosecondArray::from(vec![Some(5), None])); + let timestamp: ArrayRef = Arc::new(TimestampMicrosecondArray::from(vec![Some(-1)]).with_timezone("UTC")); + + assert_eq!( + to_parquet(&time, &DataType::Time64(TimeUnit::Microsecond)) + .unwrap() + .as_primitive::() + .iter() + .collect::>(), + vec![Some(5), None] + ); + assert_eq!( + to_parquet(×tamp, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap().data_type(), + &DataType::Timestamp(TimeUnit::Microsecond, None) + ); + } + + #[test] + fn to_parquet_writes_valid_utf8_as_strings() { + let binary: ArrayRef = Arc::new(BinaryArray::from(vec![Some(&b"zazolc"[..]), None])); + + assert_eq!( + to_parquet(&binary, &DataType::Utf8).unwrap().as_string::().iter().collect::>(), + vec![Some("zazolc"), None] + ); + } + + #[test] + fn to_parquet_refuses_invalid_utf8_at_its_row() { + let binary: ArrayRef = Arc::new(BinaryArray::from(vec![Some(&b"ok"[..]), None, Some(&b"\xff\xfe"[..])])); + + assert!(matches!(to_parquet(&binary, &DataType::Utf8), Err(Error::InvalidUtf8 { row: 2, .. }))); + } + + #[test] + fn to_parquet_refuses_invalid_utf8_at_its_parent_row() { + let list: ArrayRef = Arc::new(ListArray::new( + Arc::new(Field::new("item", DataType::Binary, true)), + arrow_buffer::OffsetBuffer::new(vec![0, 1, 3].into()), + Arc::new(BinaryArray::from(vec![&b"a"[..], b"b", b"\xff"])), + None, + )); + let target = DataType::List(Arc::new(Field::new("element", DataType::Utf8, true))); + + assert!(matches!(to_parquet(&list, &target), Err(Error::InvalidUtf8 { row: 1, .. }))); + } + + #[test] + fn to_parquet_renames_nested_children_to_the_target() { + let key = kind(Kind::Bytes); + let map = read({ + let mut builder = MapBuilder::new(None, StringBuilder::new(), Int32Builder::new()); + builder.keys().append_value("a"); + builder.values().append_value(1); + builder.append(true).unwrap(); + Arc::new(builder.finish()) + }); + let target = DataType::Map( + Arc::new(Field::new( + "key_value", + DataType::Struct(Fields::from(vec![ + Field::new("key", DataType::Utf8, false), + Field::new("value", DataType::Int64, true), + ])), + false, + )), + false, + ); + + assert_eq!(map.data_type(), &data_type(&Kind::Map(Box::new(key), Box::new(kind(Kind::Int64))))); + assert_eq!(to_parquet(&map, &target).unwrap().data_type(), &target); + + let structure = read(Arc::new(StructArray::from(vec![( + Arc::new(Field::new("id", DataType::Int64, true)), + Arc::new(Int64Array::from(vec![1])) as ArrayRef, + )]))); + let target = DataType::Struct(Fields::from(vec![Field::new("id", DataType::Int64, false)])); + + assert_eq!(to_parquet(&structure, &target).unwrap().data_type(), &target); + } + + #[test] + fn to_parquet_refuses_what_has_no_cast() { + let array: ArrayRef = Arc::new(Int64Array::from(vec![1])); + + assert!(matches!( + to_parquet(&array, &DataType::Float32), + Err(Error::Unsupported { parquet, .. }) if parquet == "Float32" + )); + } +} diff --git a/src/extension/flow-php-ext/src/parquet/error.rs b/src/extension/flow-php-ext/src/parquet/error.rs new file mode 100644 index 0000000000..9b264ad7f6 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/error.rs @@ -0,0 +1,55 @@ +//! What the Parquet core refuses, as data: `render.rs` turns each variant into the PHP exception and its message. + +use arrow_schema::ArrowError; +use parquet::errors::ParquetError; + +#[derive(Debug)] +pub enum Error { + Parquet(ParquetError), + Arrow(ArrowError), + MissingColumn(String), + /// `parquet`: the arrow type (or codec) the core has no cast for. + Unsupported { column: String, parquet: String }, + Overflow { column: String, row: usize }, + InvalidUtf8 { column: String, row: usize }, + Options(String), + Stream(String), +} + +impl Error { + /// The same refusal named after the root column it happened in. + pub fn in_column(self, name: &str) -> Self { + match self { + Error::Unsupported { parquet, .. } => Error::Unsupported { column: name.to_string(), parquet }, + Error::Overflow { row, .. } => Error::Overflow { column: name.to_string(), row }, + Error::InvalidUtf8 { row, .. } => Error::InvalidUtf8 { column: name.to_string(), row }, + error => error, + } + } + + /// The same refusal at the parent row `parent` maps a child row to. + pub fn at_row(self, parent: impl Fn(usize) -> usize) -> Self { + match self { + Error::Overflow { column, row } => Error::Overflow { column, row: parent(row) }, + Error::InvalidUtf8 { column, row } => Error::InvalidUtf8 { column, row: parent(row) }, + error => error, + } + } +} + +impl From for Error { + fn from(error: ParquetError) -> Self { + Error::Parquet(error) + } +} + +impl From for Error { + fn from(error: ArrowError) -> Self { + Error::Arrow(error) + } +} + +/// The parent row of child row `child` under list/map `offsets`. +pub fn parent_row>(offsets: &[O], child: usize) -> usize { + offsets.partition_point(|offset| (*offset).into() <= child as i64).saturating_sub(1) +} diff --git a/src/extension/flow-php-ext/src/parquet/etl.rs b/src/extension/flow-php-ext/src/parquet/etl.rs new file mode 100644 index 0000000000..7f408b1083 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/etl.rs @@ -0,0 +1,243 @@ +//! `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}`: `Rows` of `NativeColumn`s straight from the +//! core's canonical arrays, and any `Rows` straight to them. + +use std::rc::Rc; +use std::sync::Arc; + +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::{ZendHashTable, Zval}; +use flow_batch_frame::kind::data_type; + +use crate::backend::DefaultBackend; +use crate::column::NativeColumn; +use crate::ctx::{call_method, call_static, ht_for_each, ht_get, ht_insert, null_zval, zval_long, zval_str}; +use crate::exception::ext_exception; +use crate::parquet::error::Error; +use crate::parquet::options; +use crate::parquet::read::{ParquetReader, ReadPlan}; +use crate::parquet::sink::PhpSink; +use crate::parquet::source::{PhpSource, PhpStream}; +use crate::parquet::write::ParquetWriter; +use crate::plan::{type_plan, TypePlan}; +use crate::render::{invalid_argument, parquet_exception, Side}; + +fn rows(value: Option, name: &str) -> PhpResult> { + value + .map(|value| { + u64::try_from(value) + .map_err(|_| invalid_argument(format!("flow_php Parquet {name} must be greater or equal to 0"))) + }) + .transpose() +} + +/// `Schema::definitions()` as (name, definition): an int key is a numeric column name. +fn definitions(schema: &Zval) -> PhpResult, Zval)>> { + let definitions = call_method(schema, "definitions", &mut [])?; + let definitions = definitions + .array() + .ok_or_else(|| ext_exception("flow_php expected Schema::definitions() to return an array"))?; + let mut named = Vec::with_capacity(definitions.len()); + + ht_for_each(definitions, |name, index, definition| { + named.push(( + name.map_or_else(|| index.to_string().into_bytes(), |name| name.as_bytes().to_vec()), + definition.shallow_clone(), + )); + + Ok(()) + })?; + + Ok(named) +} + +#[php_class] +#[php(name = "Flow\\ETL\\Adapter\\Parquet\\NativeParquetReader", flags = ClassFlags::Final)] +pub struct NativeParquetReader { + reader: Option, + stream: Arc, + schema: Zval, + columns: Vec<(Vec, Rc)>, +} + +#[php_impl] +impl NativeParquetReader { + pub fn __construct( + stream: &Zval, + schema: &Zval, + batch_size: i64, + offset: Option, + limit: Option, + ) -> PhpResult { + let batch_size = usize::try_from(batch_size) + .ok() + .filter(|size| *size > 0) + .ok_or_else(|| invalid_argument("flow_php Parquet batch size must be greater than 0".to_string()))?; + let (offset, limit) = (rows(offset, "offset")?.unwrap_or(0), rows(limit, "limit")?); + let stream = Arc::new(PhpStream::new(stream)?); + let refused = |error| parquet_exception(error, &stream, Side::Read); + let source = PhpSource::new(Arc::clone(&stream)).map_err(refused)?; + let meta = source.metadata().map_err(refused)?; + let plan = ReadPlan::new(&meta, offset, limit); + let mut columns = Vec::new(); + let mut names = Vec::new(); + + for (name, definition) in definitions(schema)? { + names.push(String::from_utf8_lossy(&name).into_owned()); + columns.push((name, type_plan(&call_method(&definition, "type", &mut [])?)?)); + } + + let reader = ParquetReader::open(source, meta, &names, plan, batch_size).map_err(refused)?; + + for ((field, canonical), (name, plan)) in reader.fields().iter().zip(reader.types()).zip(&columns) { + let stored = data_type(&plan.kind); + + if canonical != &stored { + let type_name = call_method(&plan.type_zv, "toString", &mut [])?; + + return Err(invalid_argument(format!( + "Parquet column \"{}\" ({}) is read as {canonical}, its schema type {} stores {stored}", + String::from_utf8_lossy(name), + field.data_type(), + String::from_utf8_lossy(type_name.zend_str().map_or(&b""[..], |name| name.as_bytes())), + ))); + } + } + + Ok(Self { + reader: Some(reader), + stream, + schema: schema.shallow_clone(), + columns, + }) + } + + /// The next batch as `Rows::fromColumns($schema, $columns, $count)`, null after the last. + pub fn next(&mut self) -> PhpResult { + let Some(reader) = self.reader.as_mut() else { + return Ok(null_zval()); + }; + + let (count, arrays) = match reader.next() { + None => { + self.reader = None; + + return Ok(null_zval()); + } + Some(batch) => batch.map_err(|error| parquet_exception(error, &self.stream, Side::Read))?, + }; + + let mut columns = ZendHashTable::with_capacity(self.columns.len() as u32); + + for ((name, plan), array) in self.columns.iter().zip(arrays) { + let mut native = Zval::new(); + ext_php_rs::convert::IntoZval::set_zval(NativeColumn::new(array, Rc::clone(plan)), &mut native, false)?; + ht_insert(&mut columns, name, native); + } + + let mut columns_zv = Zval::new(); + columns_zv.set_hashtable(columns); + + call_static( + "Flow\\ETL\\Rows", + "fromColumns", + &mut [self.schema.shallow_clone(), columns_zv, zval_long(count as i64)], + ) + } + + pub fn close(&mut self) { + self.reader = None; + } +} + +#[php_class] +#[php(name = "Flow\\ETL\\Adapter\\Parquet\\NativeParquetWriter", flags = ClassFlags::Final)] +pub struct NativeParquetWriter { + writer: Option, + stream: Arc, +} + +impl Drop for NativeParquetWriter { + fn drop(&mut self) { + self.stream.detach(); + } +} + +#[php_impl] +impl NativeParquetWriter { + /// `$schema`: `Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension()`, `$options`: `OptionsConverter::toExtension()`. + pub fn __construct(stream: &Zval, schema: &ZendHashTable, compression: String, options: &ZendHashTable) -> PhpResult { + let stream = Arc::new(PhpStream::new(stream)?); + let refused = |error| parquet_exception(error, &stream, Side::Write); + let writer = ParquetWriter::open( + PhpSink::new(Arc::clone(&stream)), + options::schema(schema).map_err(refused)?, + options::properties(&compression, options).map_err(refused)?, + ) + .map_err(refused)?; + + Ok(Self { + writer: Some(writer), + stream, + }) + } + + /// The writer schema's columns by name: a `NativeColumn` as it is, any other column adopted into one, a column + /// the rows lack as nulls. + pub fn write(&mut self, rows: &Zval) -> PhpResult<()> { + let writer = self.writer.as_mut().ok_or_else(|| ext_exception("flow_php Parquet writer is closed"))?; + let count = call_method(rows, "count", &mut [])? + .long() + .ok_or_else(|| ext_exception("flow_php expected Rows::count() to return an int"))? as usize; + let columns = call_method(rows, "columns", &mut [])?; + let columns = columns + .array() + .ok_or_else(|| ext_exception("flow_php expected Rows::columns() to return an array"))?; + let schema = call_method(rows, "schema", &mut [])?; + let mut arrays = Vec::with_capacity(writer.schema().fields().len()); + + for field in writer.schema().fields() { + let Some(column) = ht_get(columns, field.name().as_bytes()) else { + arrays.push(arrow_array::new_null_array(field.data_type(), count)); + + continue; + }; + + let adopted; + let native = match column.extract::<&NativeColumn>() { + Some(native) => native, + None => { + let definition = call_method(&schema, "get", &mut [zval_str(field.name().as_bytes())])?; + adopted = DefaultBackend.adopt(&definition, column)?.0; + adopted + .extract::<&NativeColumn>() + .ok_or_else(|| ext_exception("flow_php expected DefaultBackend::adopt() to build a NativeColumn"))? + } + }; + + arrays.push(Arc::clone(native.data())); + } + + writer + .write(count, &arrays) + .map_err(|error| parquet_exception(error, &self.stream, Side::Write)) + } + + /// The footer, then the stream closed - as the lib's Parquet writers close theirs. + pub fn close(&mut self) -> PhpResult<()> { + self.writer + .take() + .ok_or_else(|| ext_exception("flow_php Parquet writer is already closed"))? + .close() + .map_err(|error| parquet_exception(error, &self.stream, Side::Write))?; + + match self.stream.call("close", &mut []) { + Some(_) => Ok(()), + None => Err(parquet_exception( + Error::Stream("close() threw".to_string()), + &self.stream, + Side::Write, + )), + } + } +} diff --git a/src/extension/flow-php-ext/src/parquet/mod.rs b/src/extension/flow-php-ext/src/parquet/mod.rs new file mode 100644 index 0000000000..de88406871 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/mod.rs @@ -0,0 +1,11 @@ +//! Parquet inside flow_php: one reader, one cast table and one writer over Flow filesystem streams, with no Flow types +//! below `etl`, the `Flow\ETL\Adapter\Parquet` surface. + +pub mod canonical; +pub mod error; +pub mod etl; +pub mod options; +pub mod read; +pub mod sink; +pub mod source; +pub mod write; diff --git a/src/extension/flow-php-ext/src/parquet/options.rs b/src/extension/flow-php-ext/src/parquet/options.rs new file mode 100644 index 0000000000..c2ff49cc61 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/options.rs @@ -0,0 +1,370 @@ +//! Ported verbatim from arrow-ext (`src/parquet/type_converter.rs` `parse_time_unit`, `php_schema_entry_to_field`, +//! `php_schema_to_arrow`; `src/parquet/writer.rs` `parse_compression`, `parse_encoding`, `apply_writer_options` and +//! the writer constructor's properties): the arrays of `Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension()` and +//! `OptionsConverter::toExtension()`. + +use std::str::FromStr; +use std::sync::Arc; + +use arrow_schema::{ + extension::{Json, Uuid}, + DataType, Field, Fields, Schema, TimeUnit, +}; +use ext_php_rs::types::{ArrayKey, ZendHashTable}; +use parquet::basic::{BrotliLevel, Compression, Encoding, GzipLevel, ZstdLevel}; +use parquet::file::properties::{WriterProperties, WriterVersion}; +use parquet::schema::types::ColumnPath; + +use crate::parquet::error::Error; + +pub fn schema(ht: &ZendHashTable) -> Result { + php_schema_to_arrow(ht).map_err(Error::Options) +} + +pub fn properties(compression: &str, options: &ZendHashTable) -> Result { + if options.is_empty() { + let codec = parse_compression(compression, None, None, None).map_err(Error::Options)?; + + return Ok(WriterProperties::builder().set_compression(codec).build()); + } + + Ok(apply_writer_options(WriterProperties::builder(), options, compression) + .map_err(Error::Options)? + .build()) +} + +fn parse_time_unit(entry_ht: &ZendHashTable, name: &str) -> Result { + match entry_ht.get("unit").and_then(|z| z.str()) { + None | Some("MICROS") => Ok(TimeUnit::Microsecond), + Some("MILLIS") => Ok(TimeUnit::Millisecond), + Some("NANOS") => Ok(TimeUnit::Nanosecond), + Some(s) => Err(format!( + "Column '{}': unsupported unit '{}', expected MILLIS, MICROS or NANOS", + name, s + )), + } +} + +fn php_schema_entry_to_field(entry_ht: &ZendHashTable) -> Result { + let name = entry_ht + .get("name") + .and_then(|z| z.str()) + .ok_or_else(|| "Schema entry must have a 'name' string key".to_string())? + .to_string(); + + let type_str = entry_ht + .get("type") + .and_then(|z| z.str()) + .ok_or_else(|| "Schema entry must have a 'type' string key".to_string())? + .to_string(); + + let nullable = entry_ht + .get("optional") + .and_then(|z| z.bool()) + .unwrap_or(true); + + let data_type = match type_str.as_str() { + "BOOLEAN" => DataType::Boolean, + "INT8" => DataType::Int8, + "INT16" => DataType::Int16, + "INT32" => DataType::Int32, + "INT64" => DataType::Int64, + "UINT8" => DataType::UInt8, + "UINT16" => DataType::UInt16, + "UINT32" => DataType::UInt32, + "UINT64" => DataType::UInt64, + "FLOAT" => DataType::Float32, + "DOUBLE" => DataType::Float64, + "STRING" => DataType::Utf8, + "BINARY" => DataType::Binary, + "DATE" => DataType::Date32, + "TIMESTAMP" => { + let unit = parse_time_unit(entry_ht, &name)?; + let utc = entry_ht.get("utc").and_then(|z| z.bool()).unwrap_or(true); + DataType::Timestamp(unit, if utc { Some("UTC".into()) } else { None }) + } + "TIME" => match parse_time_unit(entry_ht, &name)? { + TimeUnit::Millisecond => DataType::Time32(TimeUnit::Millisecond), + unit => DataType::Time64(unit), + }, + "DECIMAL" => { + let precision = entry_ht + .get("precision") + .and_then(|z| z.long()) + .ok_or_else(|| { + format!( + "Column '{}': DECIMAL type requires 'precision' integer key", + name + ) + })? as u8; + let scale = entry_ht + .get("scale") + .and_then(|z| z.long()) + .ok_or_else(|| { + format!( + "Column '{}': DECIMAL type requires 'scale' integer key", + name + ) + })? as i8; + DataType::Decimal128(precision, scale) + } + "UUID" => { + let mut field = Field::new(&name, DataType::FixedSizeBinary(16), nullable); + field.try_with_extension_type(Uuid).map_err(|e| { + format!( + "Column '{}': failed to set UUID extension type: {}", + name, e + ) + })?; + return Ok(field); + } + "JSON" => { + let mut field = Field::new(&name, DataType::Utf8, nullable); + field + .try_with_extension_type(Json::default()) + .map_err(|e| { + format!( + "Column '{}': failed to set JSON extension type: {}", + name, e + ) + })?; + return Ok(field); + } + "FIXED_SIZE_BINARY" => { + let length = entry_ht + .get("length") + .and_then(|z| z.long()) + .ok_or_else(|| { + format!( + "Column '{}': FIXED_SIZE_BINARY type requires 'length' integer key", + name + ) + })? as i32; + DataType::FixedSizeBinary(length) + } + "LIST" => { + let children = entry_ht + .get("children") + .and_then(|z| z.array()) + .ok_or_else(|| format!("Column '{}': LIST type requires 'children' array", name))?; + let child_zv = children.values().next().ok_or_else(|| { + format!("Column '{}': LIST type requires exactly one child", name) + })?; + let child_ht = child_zv + .array() + .ok_or_else(|| format!("Column '{}': LIST child must be an array", name))?; + let child_field = php_schema_entry_to_field(child_ht)?; + DataType::List(Arc::new(child_field)) + } + "STRUCT" => { + let children = entry_ht + .get("children") + .and_then(|z| z.array()) + .ok_or_else(|| { + format!("Column '{}': STRUCT type requires 'children' array", name) + })?; + let fields: Result, String> = children + .values() + .map(|child_zv| { + let child_ht = child_zv.array().ok_or_else(|| { + format!("Column '{}': STRUCT child must be an array", name) + })?; + php_schema_entry_to_field(child_ht) + }) + .collect(); + DataType::Struct(Fields::from(fields?)) + } + "MAP" => { + let children = entry_ht + .get("children") + .and_then(|z| z.array()) + .ok_or_else(|| format!("Column '{}': MAP type requires 'children' array", name))?; + let mut child_iter = children.values(); + let key_zv = child_iter.next().ok_or_else(|| { + format!( + "Column '{}': MAP type requires key and value children", + name + ) + })?; + let val_zv = child_iter.next().ok_or_else(|| { + format!( + "Column '{}': MAP type requires key and value children", + name + ) + })?; + let key_field = + php_schema_entry_to_field(key_zv.array().ok_or_else(|| { + format!("Column '{}': MAP key child must be an array", name) + })?)?; + let val_field = + php_schema_entry_to_field(val_zv.array().ok_or_else(|| { + format!("Column '{}': MAP value child must be an array", name) + })?)?; + let entries_struct = DataType::Struct(Fields::from(vec![key_field, val_field])); + DataType::Map( + Arc::new(Field::new("entries", entries_struct, false)), + false, + ) + } + other => { + return Err(format!("Column '{}': Unsupported type '{}'", name, other)); + } + }; + + Ok(Field::new(&name, data_type, nullable)) +} + +fn php_schema_to_arrow(schema: &ZendHashTable) -> Result { + if schema.is_empty() { + return Err("Schema must have at least one column".into()); + } + + let mut fields = Vec::with_capacity(schema.len()); + + for (_key, zv) in schema.iter() { + let entry_ht = zv + .array() + .ok_or_else(|| "Schema entry must be an array".to_string())?; + fields.push(php_schema_entry_to_field(entry_ht)?); + } + + Ok(Schema::new(fields)) +} + +fn parse_compression( + s: &str, + gzip_level: Option, + brotli_level: Option, + zstd_level: Option, +) -> Result { + match s.to_uppercase().as_str() { + "UNCOMPRESSED" => Ok(Compression::UNCOMPRESSED), + "SNAPPY" => Ok(Compression::SNAPPY), + "GZIP" => { + let level = match gzip_level { + Some(l) => GzipLevel::try_new(l) + .map_err(|e| format!("Invalid GZIP compression level: {}", e))?, + None => Default::default(), + }; + Ok(Compression::GZIP(level)) + } + "ZSTD" => { + let level = match zstd_level { + Some(l) => ZstdLevel::try_new(l) + .map_err(|e| format!("Invalid ZSTD compression level: {}", e))?, + None => Default::default(), + }; + Ok(Compression::ZSTD(level)) + } + "LZ4" | "LZ4_RAW" => Ok(Compression::LZ4_RAW), + "BROTLI" => { + let level = match brotli_level { + Some(l) => BrotliLevel::try_new(l) + .map_err(|e| format!("Invalid BROTLI compression level: {}", e))?, + None => Default::default(), + }; + Ok(Compression::BROTLI(level)) + } + other => Err(format!( + "Unsupported compression codec '{}'. Supported: UNCOMPRESSED, SNAPPY, GZIP, ZSTD, LZ4, LZ4_RAW, BROTLI", + other + )), + } +} + +fn parse_encoding(s: &str) -> Result { + Encoding::from_str(&s.to_uppercase()) + .map_err(|e| format!("Unsupported encoding '{}': {}", s, e)) +} + +fn apply_writer_options( + mut builder: parquet::file::properties::WriterPropertiesBuilder, + options: &ZendHashTable, + compression_str: &str, +) -> Result { + let gzip_level = options + .get("GZIP_COMPRESSION_LEVEL") + .and_then(|z| z.long()) + .map(|v| v as u32); + + let brotli_level = options + .get("BROTLI_COMPRESSION_LEVEL") + .and_then(|z| z.long()) + .map(|v| v as u32); + + let zstd_level = options + .get("ZSTD_COMPRESSION_LEVEL") + .and_then(|z| z.long()) + .map(|v| v as i32); + + let codec = parse_compression(compression_str, gzip_level, brotli_level, zstd_level)?; + builder = builder.set_compression(codec); + + if let Some(val) = options.get("ROW_GROUP_SIZE_BYTES").and_then(|z| z.long()) { + builder = builder.set_max_row_group_bytes(Some(val as usize)); + } + + if let Some(val) = options.get("PAGE_SIZE_BYTES").and_then(|z| z.long()) { + builder = builder.set_data_page_size_limit(val as usize); + } + + if let Some(val) = options.get("DICTIONARY_PAGE_SIZE").and_then(|z| z.long()) { + builder = builder.set_dictionary_page_size_limit(val as usize); + } + + if let Some(val) = options.get("WRITER_VERSION").and_then(|z| z.long()) { + let version = match val { + 1 => WriterVersion::PARQUET_1_0, + 2 => WriterVersion::PARQUET_2_0, + other => { + return Err(format!( + "Invalid WRITER_VERSION '{}'. Must be 1 or 2", + other + )) + } + }; + builder = builder.set_writer_version(version); + } + + if let Some(col_comp_zval) = options.get("COLUMNS_COMPRESSIONS") { + if let Some(col_comp_ht) = col_comp_zval.array() { + for (key, val) in col_comp_ht.iter() { + let col_path_str = match key { + ArrayKey::String(ref s) => s.clone(), + ArrayKey::Str(s) => s.to_string(), + _ => continue, + }; + if let Some(codec_str) = val.str() { + let parts: Vec = + col_path_str.split('.').map(|s| s.to_string()).collect(); + let col_path = ColumnPath::new(parts); + let col_codec = + parse_compression(codec_str, gzip_level, brotli_level, zstd_level)?; + builder = builder.set_column_compression(col_path, col_codec); + } + } + } + } + + if let Some(col_enc_zval) = options.get("COLUMNS_ENCODINGS") { + if let Some(col_enc_ht) = col_enc_zval.array() { + for (key, val) in col_enc_ht.iter() { + let col_path_str = match key { + ArrayKey::String(ref s) => s.clone(), + ArrayKey::Str(s) => s.to_string(), + _ => continue, + }; + if let Some(enc_str) = val.str() { + let parts: Vec = + col_path_str.split('.').map(|s| s.to_string()).collect(); + let col_path = ColumnPath::new(parts); + let encoding = parse_encoding(enc_str)?; + builder = builder.set_column_encoding(col_path, encoding); + } + } + } + } + + Ok(builder) +} + diff --git a/src/extension/flow-php-ext/src/parquet/read.rs b/src/extension/flow-php-ext/src/parquet/read.rs new file mode 100644 index 0000000000..3d16cde0c2 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/read.rs @@ -0,0 +1,284 @@ +//! Row groups of a Parquet file as canonical arrays: only the groups an offset/limit window overlaps are decoded, and +//! every projected column is checked against the cast table before the first batch. + +use std::sync::Arc; + +use arrow_array::{ArrayRef, RecordBatchReader}; +use arrow_schema::{DataType, FieldRef}; +use parquet::arrow::arrow_reader::{ + ArrowReaderMetadata, ArrowReaderOptions, ParquetRecordBatchReader, ParquetRecordBatchReaderBuilder, +}; +use parquet::arrow::ProjectionMask; +use parquet::basic::Compression; +use parquet::file::metadata::{PageIndexPolicy, ParquetMetaData, ParquetMetaDataReader}; + +use crate::parquet::canonical::{canonical, canonical_type}; +use crate::parquet::error::Error; +use crate::parquet::source::PhpSource; + +/// The row groups overlapping [offset, offset + limit) and the rows to skip in the first of them. +#[derive(Debug, PartialEq, Eq)] +pub struct ReadPlan { + pub row_groups: Vec, + pub skip: usize, + pub limit: Option, +} + +impl ReadPlan { + pub fn new(meta: &ParquetMetaData, offset: u64, limit: Option) -> Self { + let (mut row_groups, mut skip, mut start) = (Vec::new(), 0, 0); + + for (index, group) in meta.row_groups().iter().enumerate() { + let end = start + group.num_rows() as u64; + + if end > offset && limit.is_none_or(|limit| start < offset + limit) { + if row_groups.is_empty() { + skip = (offset - start) as usize; + } + + row_groups.push(index); + } + + start = end; + } + + Self { + row_groups, + skip, + limit: limit.map(|limit| limit as usize), + } + } +} + +pub struct ParquetReader { + batches: ParquetRecordBatchReader, + fields: Vec, + /// `canonical_type()` of each of `fields`. + types: Vec, + /// Where each of `fields` sits in the projected batches. + positions: Vec, +} + +impl ParquetReader { + /// `meta`: the footer `plan` was built from (`PhpSource::metadata()`); the page index is read on top of it only + /// when the plan skips rows inside its first row group. + pub fn open( + source: PhpSource, + meta: ParquetMetaData, + columns: &[String], + plan: ReadPlan, + batch_size: usize, + ) -> Result { + let meta = if plan.skip > 0 { + let mut reader = ParquetMetaDataReader::new_with_metadata(meta).with_page_index_policy(PageIndexPolicy::Optional); + reader.read_page_indexes(&source)?; + reader.finish()? + } else { + meta + }; + let meta = ArrowReaderMetadata::try_new(Arc::new(meta), ArrowReaderOptions::new())?; + let schema = meta.schema(); + let roots = columns + .iter() + .map(|name| schema.index_of(name).map_err(|_| Error::MissingColumn(name.clone()))) + .collect::, _>>()?; + let fields = roots.iter().map(|root| Arc::clone(&schema.fields()[*root])).collect::>(); + let types = fields.iter().map(|field| canonical_type(field)).collect::, _>>()?; + + if let Some(codec) = unsupported_codec(meta.metadata(), &plan.row_groups, &fields) { + return Err(codec); + } + + let mask = ProjectionMask::roots(meta.metadata().file_metadata().schema_descr(), roots.iter().copied()); + let mut builder = ParquetRecordBatchReaderBuilder::new_with_metadata(source, meta) + .with_row_groups(plan.row_groups) + .with_projection(mask) + .with_batch_size(batch_size); + + if plan.skip > 0 { + builder = builder.with_offset(plan.skip); + } + + if let Some(limit) = plan.limit { + builder = builder.with_limit(limit); + } + + let batches = builder.build()?; + let projected = batches.schema(); + let positions = columns + .iter() + .map(|name| projected.index_of(name).map_err(|_| Error::MissingColumn(name.clone()))) + .collect::, _>>()?; + + Ok(Self { + batches, + fields, + types, + positions, + }) + } + + /// The canonical type each of `fields()` is read as. + pub fn types(&self) -> &[DataType] { + &self.types + } + + pub fn fields(&self) -> &[FieldRef] { + &self.fields + } + + pub fn next(&mut self) -> Option), Error>> { + let batch = match self.batches.next()? { + Ok(batch) => batch, + Err(error) => return Some(Err(error.into())), + }; + + Some( + self.fields + .iter() + .zip(&self.positions) + .map(|(field, position)| canonical(field, batch.column(*position))) + .collect::, _>>() + .map(|columns| (batch.num_rows(), columns)), + ) + } +} + +/// A codec the parquet crate is built without, in a projected column chunk of the planned row groups. +fn unsupported_codec(meta: &ParquetMetaData, row_groups: &[usize], fields: &[FieldRef]) -> Option { + row_groups.iter().find_map(|group| { + meta.row_group(*group).columns().iter().find_map(|chunk| { + let root = chunk.column_path().parts().first()?; + + (chunk.compression() == Compression::LZO && fields.iter().any(|field| field.name() == root)).then(|| { + Error::Unsupported { + column: root.clone(), + parquet: "LZO".to_string(), + } + }) + }) + }) +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use arrow_array::{Int64Array, RecordBatch, StringArray}; + use arrow_schema::{DataType, Field, FieldRef, Schema}; + use bytes::Bytes; + use parquet::arrow::ArrowWriter; + use parquet::basic::Compression; + use parquet::file::metadata::{ParquetMetaData, ParquetMetaDataReader}; + use parquet::file::properties::WriterProperties; + + use super::{unsupported_codec, ReadPlan}; + use crate::parquet::error::Error; + + fn eight_groups_of_8192() -> parquet::file::metadata::ParquetMetaData { + let schema = Arc::new(Schema::new(vec![Field::new("id", DataType::Int64, false)])); + let mut file = Vec::new(); + let mut writer = ArrowWriter::try_new( + &mut file, + Arc::clone(&schema), + Some(WriterProperties::builder().set_max_row_group_row_count(Some(8_192)).build()), + ) + .unwrap(); + writer + .write(&RecordBatch::try_new(schema, vec![Arc::new(Int64Array::from_iter_values(0..65_536))]).unwrap()) + .unwrap(); + writer.close().unwrap(); + + ParquetMetaDataReader::new().parse_and_finish(&Bytes::from(file)).unwrap() + } + + fn plan(offset: u64, limit: u64) -> (Vec, usize) { + let plan = ReadPlan::new(&eight_groups_of_8192(), offset, Some(limit)); + + assert_eq!(plan.limit, Some(limit as usize)); + + (plan.row_groups, plan.skip) + } + + #[test] + fn plan_reads_the_groups_a_window_overlaps() { + assert_eq!(eight_groups_of_8192().row_groups().len(), 8); + assert_eq!(plan(0, 10), (vec![0], 0)); + assert_eq!(plan(5_399, 3), (vec![0], 5_399)); + assert_eq!(plan(20_000, 15_000), (vec![2, 3, 4], 3_616)); + assert_eq!(plan(65_000, 100), (vec![7], 7_656)); + assert_eq!(plan(65_046, 1), (vec![7], 7_702)); + } + + #[test] + fn plan_without_limit_reads_every_group_from_the_offset() { + let plan = ReadPlan::new(&eight_groups_of_8192(), 16_384, None); + + assert_eq!( + plan, + ReadPlan { + row_groups: vec![2, 3, 4, 5, 6, 7], + skip: 0, + limit: None + } + ); + } + + fn with_lzo_names() -> ParquetMetaData { + let schema = Arc::new(Schema::new(vec![ + Field::new("id", DataType::Int64, false), + Field::new("name", DataType::Utf8, true), + ])); + let mut file = Vec::new(); + let mut writer = ArrowWriter::try_new(&mut file, Arc::clone(&schema), None).unwrap(); + writer + .write( + &RecordBatch::try_new( + schema, + vec![Arc::new(Int64Array::from(vec![1])), Arc::new(StringArray::from(vec!["a"]))], + ) + .unwrap(), + ) + .unwrap(); + writer.close().unwrap(); + + let mut builder = ParquetMetaDataReader::new().parse_and_finish(&Bytes::from(file)).unwrap().into_builder(); + let row_groups = builder + .take_row_groups() + .into_iter() + .map(|group| { + let columns = group + .columns() + .iter() + .map(|chunk| match chunk.column_path().string().as_str() { + "name" => chunk.clone().into_builder().set_compression(Compression::LZO).build().unwrap(), + _ => chunk.clone(), + }) + .collect(); + + group.into_builder().set_column_metadata(columns).build().unwrap() + }) + .collect(); + + builder.set_row_groups(row_groups).build() + } + + #[test] + fn an_lzo_column_chunk_is_refused_when_projected() { + let meta = with_lzo_names(); + let name: FieldRef = Arc::new(Field::new("name", DataType::Utf8, true)); + let id: FieldRef = Arc::new(Field::new("id", DataType::Int64, false)); + + assert!(matches!( + unsupported_codec(&meta, &[0], &[Arc::clone(&id), name]), + Some(Error::Unsupported { column, parquet }) if column == "name" && parquet == "LZO" + )); + assert!(unsupported_codec(&meta, &[0], &[id]).is_none()); + } + + #[test] + fn plan_past_the_end_reads_nothing() { + assert_eq!(plan(65_536, 10), (vec![], 0)); + assert_eq!(plan(0, 0), (vec![], 0)); + } +} diff --git a/src/extension/flow-php-ext/src/parquet/sink.rs b/src/extension/flow-php-ext/src/parquet/sink.rs new file mode 100644 index 0000000000..998744da18 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/sink.rs @@ -0,0 +1,31 @@ +//! Parquet bytes to a `Flow\Filesystem\DestinationStream` (`append(string $data)`). + +use std::io::{self, Write}; +use std::sync::Arc; + +use crate::ctx::zval_str; +use crate::parquet::source::PhpStream; + +pub struct PhpSink { + stream: Arc, +} + +impl PhpSink { + pub fn new(stream: Arc) -> Self { + Self { stream } + } +} + +impl Write for PhpSink { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.stream + .call("append", &mut [zval_str(buf)]) + .ok_or_else(|| io::Error::other("append() threw"))?; + + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/src/extension/flow-php-ext/src/parquet/source.rs b/src/extension/flow-php-ext/src/parquet/source.rs new file mode 100644 index 0000000000..140135088a --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/source.rs @@ -0,0 +1,290 @@ +//! Parquet bytes from a `Flow\Filesystem\SourceStream` (`read(int $length, int $offset): string`, `size(): ?int`), and +//! the PHP stream object both the source and the sink call into. + +use std::cell::{Cell, RefCell}; +use std::io::{self, Read}; +use std::sync::Arc; + +use bytes::{Buf, Bytes}; +use ext_php_rs::boxed::ZBox; +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::{ZendObject, Zval}; +use parquet::errors::ParquetError; +use parquet::file::reader::{ChunkReader, Length}; + +use crate::ctx::{call_handle_catching, ce_method_ref, expect_object, zval_long}; +use crate::parquet::error::Error; + +/// What `get_read()` pulls from the stream per `read()` call. +pub const WINDOW: usize = 64 * 1024; + +/// A PHP stream object. An exception its method throws is kept here, for the surface to rethrow as itself once the +/// Parquet call it broke returns. +pub struct PhpStream { + stream: Zval, + thrown: RefCell>>, + detached: Cell, +} + +// SAFETY: the stream belongs to the request thread that built it; the parquet crate requires Send + Sync of its +// readers and writers but calls them only from that thread, synchronously. +unsafe impl Send for PhpStream {} +unsafe impl Sync for PhpStream {} + +impl PhpStream { + pub fn new(stream: &Zval) -> Result { + expect_object(stream, "a stream")?; + + Ok(Self { + stream: stream.shallow_clone(), + thrown: RefCell::new(None), + detached: Cell::new(false), + }) + } + + /// `$stream->$method(...$args)`; `None` when it threw, or once the stream is detached. + pub fn call(&self, method: &str, args: &mut [Zval]) -> Option { + if self.detached.get() { + return None; + } + + let object = self.stream.object()?; + let function = ce_method_ref(unsafe { object.ce.as_ref() }?, method).ok()?; + + match call_handle_catching(function, Some(object), args) { + Ok(value) => Some(value), + Err(exception) => { + self.thrown.replace(Some(exception)); + + None + } + } + } + + /// No PHP call from here on: what an abandoned Parquet writer flushes while it is dropped - possibly while a PHP + /// exception unwinds, which a call would take - never reaches the stream. + pub fn detach(&self) { + self.detached.set(true); + } + + /// The exception a call threw, taken. + pub fn thrown(&self) -> Option> { + self.thrown.take() + } +} + +/// Bytes at an offset of a source: the one call `WindowedRead` and `get_bytes()` make. +pub trait ReadAt { + fn read_at(&self, offset: u64, length: usize) -> Result; +} + +impl ReadAt for PhpStream { + fn read_at(&self, offset: u64, length: usize) -> Result { + let read = self + .call("read", &mut [zval_long(length as i64), zval_long(offset as i64)]) + .ok_or_else(|| ParquetError::External("read() threw".into()))?; + + Ok(Bytes::copy_from_slice( + read.zend_str() + .ok_or_else(|| ParquetError::External("read() must return a string".into()))? + .as_bytes(), + )) + } +} + +pub struct PhpSource { + stream: Arc, + size: u64, +} + +impl PhpSource { + pub fn new(stream: Arc) -> Result { + let size = stream + .call("size", &mut []) + .ok_or_else(|| Error::Stream("size() threw".to_string()))? + .long() + .ok_or_else(|| Error::Stream("size() must return the stream size".to_string()))?; + + Ok(Self { + stream, + size: u64::try_from(size).map_err(|_| Error::Stream(format!("size() returned {size}")))?, + }) + } + + /// The footer, without the page index. + pub fn metadata(&self) -> Result { + Ok(parquet::file::metadata::ParquetMetaDataReader::new().parse_and_finish(self)?) + } +} + +impl Length for PhpSource { + fn len(&self) -> u64 { + self.size + } +} + +impl ChunkReader for PhpSource { + type T = WindowedRead; + + fn get_read(&self, start: u64) -> Result { + Ok(WindowedRead::new(Arc::clone(&self.stream), start, self.size)) + } + + fn get_bytes(&self, start: u64, length: usize) -> Result { + exact(self.stream.as_ref(), start, length) + } +} + +/// Exactly `length` bytes at `start`, in one read. +pub fn exact(source: &R, start: u64, length: usize) -> Result { + if length == 0 { + return Ok(Bytes::new()); + } + + let bytes = source.read_at(start, length)?; + + if bytes.len() != length { + return Err(ParquetError::EOF(format!("expected {length} bytes at offset {start}, read {}", bytes.len()))); + } + + Ok(bytes) +} + +/// A `Read` from `position` to `end` that pulls `WINDOW` bytes at a time, only when the previous window is used up. +pub struct WindowedRead { + source: Arc, + position: u64, + end: u64, + window: Bytes, +} + +impl WindowedRead { + pub fn new(source: Arc, position: u64, end: u64) -> Self { + Self { + source, + position, + end, + window: Bytes::new(), + } + } +} + +impl Read for WindowedRead { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + if self.window.is_empty() { + if self.position >= self.end { + return Ok(0); + } + + let length = (self.end - self.position).min(WINDOW as u64) as usize; + self.window = self.source.read_at(self.position, length).map_err(io::Error::other)?; + self.position += self.window.len() as u64; + } + + let read = buf.len().min(self.window.len()); + buf[..read].copy_from_slice(&self.window[..read]); + self.window.advance(read); + + Ok(read) + } +} + +#[cfg(test)] +mod tests { + use std::io::Read; + use std::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::Arc; + + use bytes::Bytes; + use parquet::errors::ParquetError; + + use super::{exact, ReadAt, WindowedRead, WINDOW}; + + struct Counting { + data: Vec, + reads: AtomicUsize, + bytes: AtomicUsize, + } + + impl Counting { + fn new(size: usize) -> Self { + Self { + data: (0..size).map(|i| i as u8).collect(), + reads: AtomicUsize::new(0), + bytes: AtomicUsize::new(0), + } + } + } + + impl ReadAt for Counting { + fn read_at(&self, offset: u64, length: usize) -> Result { + let start = (offset as usize).min(self.data.len()); + let end = (start + length).min(self.data.len()); + self.reads.fetch_add(1, Ordering::Relaxed); + self.bytes.fetch_add(end - start, Ordering::Relaxed); + + Ok(Bytes::copy_from_slice(&self.data[start..end])) + } + } + + #[test] + fn windowed_read_pulls_one_window_for_a_small_read() { + let source = Arc::new(Counting::new(10 * WINDOW)); + let mut read = WindowedRead::new(Arc::clone(&source), 100, source.data.len() as u64); + let mut header = [0u8; 32]; + + read.read_exact(&mut header).unwrap(); + + assert_eq!(header.to_vec(), source.data[100..132].to_vec()); + assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (1, WINDOW)); + } + + #[test] + fn windowed_read_pulls_the_next_window_only_when_the_first_is_used_up() { + let source = Arc::new(Counting::new(10 * WINDOW)); + let mut read = WindowedRead::new(Arc::clone(&source), 0, source.data.len() as u64); + let mut buffer = vec![0u8; WINDOW + 1]; + + read.read_exact(&mut buffer[..WINDOW]).unwrap(); + assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (1, WINDOW)); + + read.read_exact(&mut buffer[WINDOW..]).unwrap(); + assert_eq!(buffer, source.data[..WINDOW + 1].to_vec()); + assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (2, 2 * WINDOW)); + } + + #[test] + fn windowed_read_never_reads_past_the_end() { + let source = Arc::new(Counting::new(3 * WINDOW)); + let mut read = WindowedRead::new(Arc::clone(&source), 3 * WINDOW as u64 - 10, 3 * WINDOW as u64); + let mut rest = Vec::new(); + + read.read_to_end(&mut rest).unwrap(); + + assert_eq!(rest, source.data[3 * WINDOW - 10..].to_vec()); + assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (1, 10)); + } + + #[test] + fn exact_reads_the_length_asked_in_one_read() { + let source = Counting::new(10 * WINDOW); + + assert_eq!(exact(&source, 5, 3 * WINDOW).unwrap().to_vec(), source.data[5..5 + 3 * WINDOW].to_vec()); + assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (1, 3 * WINDOW)); + } + + #[test] + fn exact_refuses_a_short_read() { + let source = Counting::new(100); + + assert!(matches!(exact(&source, 90, 20), Err(ParquetError::EOF(_)))); + } + + #[test] + fn exact_reads_nothing_for_zero_bytes() { + let source = Counting::new(100); + + assert!(exact(&source, 0, 0).unwrap().is_empty()); + assert_eq!(source.reads.load(Ordering::Relaxed), 0); + } +} diff --git a/src/extension/flow-php-ext/src/parquet/write.rs b/src/extension/flow-php-ext/src/parquet/write.rs new file mode 100644 index 0000000000..4eaf234486 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/write.rs @@ -0,0 +1,55 @@ +//! Canonical arrays to Parquet: each batch cast to the writer schema's types (`to_parquet`) and written by arrow-rs. + +use std::sync::Arc; + +use arrow_array::{ArrayRef, RecordBatch, RecordBatchOptions}; +use arrow_schema::{Schema, SchemaRef}; +use parquet::arrow::ArrowWriter; +use parquet::file::properties::WriterProperties; + +use crate::parquet::canonical::to_parquet; +use crate::parquet::error::Error; +use crate::parquet::sink::PhpSink; + +pub struct ParquetWriter { + writer: ArrowWriter, + schema: SchemaRef, +} + +impl ParquetWriter { + pub fn open(sink: PhpSink, schema: Schema, props: WriterProperties) -> Result { + let schema = Arc::new(schema); + + Ok(Self { + writer: ArrowWriter::try_new(sink, Arc::clone(&schema), Some(props))?, + schema, + }) + } + + pub fn schema(&self) -> &SchemaRef { + &self.schema + } + + /// `columns`: canonical, one per writer schema field, in its order. + pub fn write(&mut self, rows: usize, columns: &[ArrayRef]) -> Result<(), Error> { + let arrays = columns + .iter() + .zip(self.schema.fields()) + .map(|(column, field)| to_parquet(column, field.data_type()).map_err(|e| e.in_column(field.name()))) + .collect::, _>>()?; + + self.writer.write(&RecordBatch::try_new_with_options( + Arc::clone(&self.schema), + arrays, + &RecordBatchOptions::new().with_row_count(Some(rows)), + )?)?; + + Ok(()) + } + + pub fn close(self) -> Result<(), Error> { + self.writer.close()?; + + Ok(()) + } +} diff --git a/src/extension/flow-php-ext/src/render.rs b/src/extension/flow-php-ext/src/render.rs index 1d27a46d3b..e5814adf42 100644 --- a/src/extension/flow-php-ext/src/render.rs +++ b/src/extension/flow-php-ext/src/render.rs @@ -1,6 +1,6 @@ //! flow-batch-frame refusals rendered as the exceptions `PhpBackend::decode()` throws for the same buffers: the //! `Flow\ETL\Exception\InvalidArgumentException` (or `OffsetOverflow`) with its exact message, a nested type named by -//! its PHP `toString()`. +//! its PHP `toString()`. Parquet core refusals rendered for the reader and the writer of `Flow\ETL\Adapter\Parquet`. use ext_php_rs::exception::PhpException; use ext_php_rs::types::Zval; @@ -9,11 +9,14 @@ use flow_batch_frame::kind::Kind; use flow_batch_frame::layout::node_count; use flow_batch_frame::Error; -use crate::ctx::{call_method, expect_object, find_class, read_property}; +use crate::ctx::{call_method, expect_object, find_class, read_property, transparent_exception}; use crate::exception::ext_exception; +use crate::parquet::error::Error as ParquetError; +use crate::parquet::source::PhpStream; const INVALID_ARGUMENT: &str = "Flow\\ETL\\Exception\\InvalidArgumentException"; const OFFSET_OVERFLOW: &str = "Flow\\ETL\\Exception\\OffsetOverflow"; +const RUNTIME: &str = "Flow\\ETL\\Exception\\RuntimeException"; pub fn exception(class: &str, message: String) -> PhpException { match find_class(class) { @@ -166,3 +169,51 @@ fn type_at(type_zv: Zval, kind: &Kind, node: usize) -> Result Err(ext_exception("flow_php could not find a nested node")), } } + +/// Which Parquet surface refused: the same core refusal names what to do about it per side. +pub enum Side { + Read, + Write, +} + +/// A Parquet core refusal; an exception the stream threw while the core called it surfaces as itself. +pub fn parquet_exception(error: ParquetError, stream: &PhpStream, side: Side) -> PhpException { + if let Some(mut thrown) = stream.thrown() { + return transparent_exception(&mut thrown); + } + + match (error, side) { + (ParquetError::Unsupported { column, parquet }, Side::Read) => exception( + RUNTIME, + format!( + "Parquet column \"{column}\" ({parquet}) is not supported by the flow_php Parquet reader; read the file \ + with from_parquet($path, engine: new \\Flow\\Parquet\\Engine\\PhpParquetEngine())" + ), + ), + (ParquetError::Unsupported { column, parquet }, Side::Write) => exception( + RUNTIME, + format!( + "Parquet column \"{column}\" ({parquet}) is not supported by the flow_php Parquet writer; write the file \ + with to_parquet($path, engine: new \\Flow\\Parquet\\Engine\\PhpParquetEngine())" + ), + ), + (ParquetError::Overflow { column, row }, _) => exception( + RUNTIME, + format!("Parquet column \"{column}\" row {row} holds a value out of the range flow_php stores it in"), + ), + (ParquetError::InvalidUtf8 { column, row }, _) => exception( + RUNTIME, + format!( + "Parquet column \"{column}\" row {row} holds a string that is not valid UTF-8; Parquet STRING columns \ + require UTF-8" + ), + ), + (ParquetError::MissingColumn(name), _) => invalid_argument(format!("Parquet file has no column \"{name}\"")), + (ParquetError::Options(message), _) => invalid_argument(message), + (ParquetError::Stream(message), _) => ext_exception(format!("flow_php Parquet stream {message}")), + (ParquetError::Parquet(error), Side::Read) => ext_exception(format!("flow_php failed to read Parquet: {error}")), + (ParquetError::Arrow(error), Side::Read) => ext_exception(format!("flow_php failed to read Parquet: {error}")), + (ParquetError::Parquet(error), Side::Write) => ext_exception(format!("flow_php failed to write Parquet: {error}")), + (ParquetError::Arrow(error), Side::Write) => ext_exception(format!("flow_php failed to write Parquet: {error}")), + } +} diff --git a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt new file mode 100644 index 0000000000..238acf5987 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt @@ -0,0 +1,113 @@ +--TEST-- +NativeParquetReader reads every lib Parquet fixture as PhpParquetEngine does, or refuses it naming the engine that reads it +--SKIPIF-- + +--FILE-- +backend(new PhpBackend())->build()); + +foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.parquet')] as $file) { + foreach ([100, 10_000] as $batchSize) { + $php = outcome(static function () use ($file, $batchSize, $context): array { + $rows = []; + + foreach (from_parquet($file, engine: new PhpParquetEngine())->withBatchSize($batchSize)->extract($context) as $batch) { + array_push($rows, ...$batch->toArray()); + } + + return $rows; + }); + $native = outcome(static function () use ($file, $batchSize, $filesystem): array { + $reader = new NativeParquetReader( + $filesystem->readFrom(path($file)), + (new SchemaConverter())->toFlow((new Reader(engine: new PhpParquetEngine()))->read($file)->schema()), + $batchSize, + null, + null, + ); + $rows = []; + + while (($batch = $reader->next()) !== null) { + array_push($rows, ...$batch->toArray()); + } + + return $rows; + }); + $name = substr($file, strlen($fixtures) + 1) . ' ' . $batchSize; + + echo match (true) { + $php === $native => "{$name}: identical\n", + str_contains($native, 'is not supported by the flow_php Parquet reader') => "{$name}: {$native}\n", + default => "{$name}: DIFFER\n php: " . substr($php, 0, 300) . "\n native: " . substr($native, 0, 300) . "\n", + }; + } +} + +$emptylist = realpath($fixtures . '/EdgeCases/null_list.parquet'); +echo outcome(static fn() => new NativeParquetReader( + $filesystem->readFrom(path($emptylist)), + schema(list_schema('emptylist', type_list(type_integer()))), + 100, + null, + null, +)), "\n"; +echo outcome(static fn() => new NativeParquetReader( + $filesystem->readFrom(path($fixtures . '/multiple_pages.parquet')), + schema(str_schema('int64')), + 100, + null, + null, +)), "\n"; +echo outcome(static fn() => new NativeParquetReader( + $filesystem->readFrom(path($fixtures . '/multiple_pages.parquet')), + schema(str_schema('missing')), + 100, + null, + null, +)), "\n"; +?> +--EXPECT-- +columns.required.parquet 100: identical +columns.required.parquet 10000: identical +decimals_fixed_len.parquet 100: identical +decimals_fixed_len.parquet 10000: identical +delta_binary_acked_encoded_integers.parquet 100: identical +delta_binary_acked_encoded_integers.parquet 10000: identical +lists.parquet 100: identical +lists.parquet 10000: identical +logical_types.parquet 100: identical +logical_types.parquet 10000: identical +maps.parquet 100: identical +maps.parquet 10000: identical +multiple_pages.parquet 100: identical +multiple_pages.parquet 10000: identical +pagination_row_group_1kb_5k_rows.snappy.parquet 100: identical +pagination_row_group_1kb_5k_rows.snappy.parquet 10000: identical +primitives.parquet 100: identical +primitives.parquet 10000: identical +structs.parquet 100: identical +structs.parquet 10000: identical +EdgeCases/datapage_v2.snappy.parquet 100: identical +EdgeCases/datapage_v2.snappy.parquet 10000: identical +EdgeCases/nonnullable.impala.parquet 100: identical +EdgeCases/nonnullable.impala.parquet 10000: identical +EdgeCases/null_list.parquet 100: identical +EdgeCases/null_list.parquet 10000: identical +Flow\ETL\Exception\RuntimeException: Parquet column "emptylist" (Null) is not supported by the flow_php Parquet reader; read the file with from_parquet($path, engine: new \Flow\Parquet\Engine\PhpParquetEngine()) +Flow\ETL\Exception\InvalidArgumentException: Parquet column "int64" (Int64) is read as Int64, its schema type string stores Binary +Flow\ETL\Exception\InvalidArgumentException: Parquet file has no column "missing" diff --git a/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt b/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt new file mode 100644 index 0000000000..ccfde90f89 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt @@ -0,0 +1,71 @@ +--TEST-- +NativeParquetReader reads offset/limit windows of an 8-row-group file, and refuses a batch size, offset or limit out of range +--SKIPIF-- + +--FILE-- +writeTo(path('memory://groups.parquet')), + ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), + 'SNAPPY', + OptionsConverter::toExtension(Options::default()->set(Option::ROW_GROUP_SIZE_BYTES, 1)), +); + +for ($group = 0; $group < 8; $group++) { + $writer->write(array_to_rows(array_map(static fn(int $id): array => ['id' => $id], range($group * 8192, $group * 8192 + 8191)), $schema)); +} + +$writer->close(); + +echo 'row groups: ', implode(',', array_map( + static fn($rowGroup): int => $rowGroup->rowsCount(), + (new Reader())->readStream($filesystem->readFrom(path('memory://groups.parquet')))->metadata()->rowGroups()->all(), +)), "\n"; + +foreach ([[0, 10], [5399, 3], [20000, 15000], [65000, 100], [65046, 1], [65536, 10], [65530, null]] as [$offset, $limit]) { + $reader = new NativeParquetReader($filesystem->readFrom(path('memory://groups.parquet')), $schema, 1000, $offset, $limit); + $ids = []; + + while (($batch = $reader->next()) !== null) { + array_push($ids, ...$batch->column('id')->values()); + } + + printf("%d %s: %d rows, %s\n", $offset, $limit ?? 'null', count($ids), $ids === [] ? '-' : $ids[0] . '..' . $ids[count($ids) - 1]); + var_dump($ids === ($ids === [] ? [] : range($offset, $offset + count($ids) - 1))); +} + +foreach ([[0, null, null], [-1, null, null], [10, -1, null], [10, null, -1]] as [$batchSize, $offset, $limit]) { + echo outcome(static fn() => new NativeParquetReader($filesystem->readFrom(path('memory://groups.parquet')), $schema, $batchSize, $offset, $limit)), "\n"; +} +?> +--EXPECT-- +row groups: 8192,8192,8192,8192,8192,8192,8192,8192 +0 10: 10 rows, 0..9 +bool(true) +5399 3: 3 rows, 5399..5401 +bool(true) +20000 15000: 15000 rows, 20000..34999 +bool(true) +65000 100: 100 rows, 65000..65099 +bool(true) +65046 1: 1 rows, 65046..65046 +bool(true) +65536 10: 0 rows, - +bool(true) +65530 null: 6 rows, 65530..65535 +bool(true) +Flow\ETL\Exception\InvalidArgumentException: flow_php Parquet batch size must be greater than 0 +Flow\ETL\Exception\InvalidArgumentException: flow_php Parquet batch size must be greater than 0 +Flow\ETL\Exception\InvalidArgumentException: flow_php Parquet offset must be greater or equal to 0 +Flow\ETL\Exception\InvalidArgumentException: flow_php Parquet limit must be greater or equal to 0 diff --git a/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt b/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt new file mode 100644 index 0000000000..49727acd15 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt @@ -0,0 +1,114 @@ +--TEST-- +NativeParquetWriter writes native and PHP columns that PhpParquetEngine reads back equal, and refuses a string that is not valid UTF-8 +--SKIPIF-- + +--FILE-- + type_integer(), 'name' => type_optional(type_string())])), +); +$values = [ + [ + 'int' => -7, 'string' => 'zażółć', 'float' => 0.14, 'bool' => true, + 'datetime' => new DateTimeImmutable('1969-12-31 23:59:59.999999 UTC'), 'date' => new DateTimeImmutable('1900-01-01'), + 'time' => new DateInterval('PT1H2M3S'), 'uuid' => new Uuid('26fd21b0-6080-4d6c-bdb4-1214f1feffef'), + 'json' => '{"a":[1,2]}', 'list' => [1, null, 3], 'map' => ['a' => 1, 'b' => 2], 'structure' => ['id' => 1, 'name' => null], + ], + [ + 'int' => PHP_INT_MAX, 'string' => null, 'float' => 1234567890123456.8, 'bool' => false, + 'datetime' => new DateTimeImmutable('2026-09-29 12:00:00.5 UTC'), 'date' => new DateTimeImmutable('2026-09-29'), + 'time' => null, 'uuid' => new Uuid('00000000-0000-0000-0000-000000000000'), + 'json' => '[]', 'list' => [], 'map' => [], 'structure' => ['id' => 2, 'name' => 'x'], + ], +]; +$context = flow_context(config_builder()->backend(new PhpBackend())->build()); +$write = static function (Schema $schema, array $batches): void { + $writer = new NativeParquetWriter( + memory_filesystem()->writeTo(path('memory://unused.parquet')), + ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), + 'ZSTD', + OptionsConverter::toExtension(Options::default()), + ); + + foreach ($batches as $batch) { + $writer->write($batch); + } + + $writer->close(); +}; + +$filesystem = memory_filesystem(); +$writer = new NativeParquetWriter( + $filesystem->writeTo(path('memory://roundtrip.parquet')), + ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), + 'ZSTD', + OptionsConverter::toExtension(Options::default()), +); +$writer->write(native_rows($schema, $values)); +$writer->write(php_rows($schema, $values)); +$writer->close(); + +$read = []; + +foreach (from_parquet(path('memory://roundtrip.parquet'), filesystem: $filesystem, engine: new PhpParquetEngine())->extract($context) as $batch) { + array_push($read, ...$batch->toArray()); +} + +var_dump(comparable($read) === comparable([...php_rows($schema, $values)->toArray(), ...php_rows($schema, $values)->toArray()])); + +$partial = memory_filesystem(); +$partialWriter = new NativeParquetWriter( + $partial->writeTo(path('memory://partial.parquet')), + ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet(schema(int_schema('id'), str_schema('name', nullable: true)))), + 'SNAPPY', + OptionsConverter::toExtension(Options::default()), +); +$partialWriter->write(native_rows(schema(int_schema('id')), [['id' => 1], ['id' => 2]])); +$partialWriter->close(); +$partialRead = []; + +foreach (from_parquet(path('memory://partial.parquet'), filesystem: $partial, engine: new PhpParquetEngine())->extract($context) as $batch) { + array_push($partialRead, ...$batch->toArray()); +} + +echo json_encode($partialRead), "\n"; + +$names = schema(str_schema('name')); +echo outcome(static fn() => $write($names, [native_rows($names, [['name' => 'ok'], ['name' => "\xff\xfe"]])])), "\n"; +echo outcome(static fn() => $write($names, [php_rows($names, [['name' => "\xff\xfe"]])])), "\n"; + +$nested = schema(list_schema('tags', type_list(type_string()))); +echo outcome(static fn() => $write($nested, [native_rows($nested, [['tags' => ['a']], ['tags' => ['b', "\xff"]]])])), "\n"; +?> +--EXPECT-- +bool(true) +[{"id":1,"name":null},{"id":2,"name":null}] +Flow\ETL\Exception\RuntimeException: Parquet column "name" row 1 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 +Flow\ETL\Exception\RuntimeException: Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 +Flow\ETL\Exception\RuntimeException: Parquet column "tags" row 1 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 diff --git a/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt new file mode 100644 index 0000000000..9b29a50240 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt @@ -0,0 +1,70 @@ +--TEST-- +NativeParquetReader and NativeParquetWriter leak neither PHP memory nor native allocations, refusals included +--SKIPIF-- + +--FILE-- + ['id' => $i, 'name' => $i % 3 ? "n{$i}" : null, 'tags' => [(string) $i, null]], range(0, 99)); +$extension = ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)); +$options = OptionsConverter::toExtension(Options::default()); +// built once: a fresh Type object per cycle would grow flow_php's type-plan cache, which is bounded, not leaked +$mismatched = schema(str_schema('id')); +$invalid = [['id' => 1, 'name' => "\xff", 'tags' => []]]; + +$cycle = static function () use ($schema, $values, $extension, $options, $mismatched, $invalid): void { + $filesystem = memory_filesystem(); + $writer = new NativeParquetWriter($filesystem->writeTo(path('memory://leaks.parquet')), $extension, 'SNAPPY', $options); + $writer->write(native_rows($schema, $values)); + $writer->write(php_rows($schema, $values)); + $writer->close(); + + $reader = new NativeParquetReader($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, 10, 150); + + while ($reader->next() !== null) { + } + + $refused = new NativeParquetWriter($filesystem->writeTo(path('memory://refused.parquet')), $extension, 'SNAPPY', $options); + + try { + $refused->write(native_rows($schema, $invalid)); + throw new LogicException('invalid UTF-8 was written'); + } catch (Flow\ETL\Exception\RuntimeException) { + } + + try { + new NativeParquetReader($filesystem->readFrom(path('memory://leaks.parquet')), $mismatched, 30, null, null); + throw new LogicException('a mismatched schema was accepted'); + } catch (Flow\ETL\Exception\InvalidArgumentException) { + } +}; + +for ($i = 0; $i < 10; $i++) { + $cycle(); +} +gc_collect_cycles(); +$baseline = memory_get_usage(false); +$baselineRust = (new DefaultBackend())->allocatedBytes(); + +for ($i = 0; $i < 300; $i++) { + $cycle(); +} +gc_collect_cycles(); + +var_dump(memory_get_usage(false) <= $baseline); +var_dump((new DefaultBackend())->allocatedBytes() === $baselineRust); +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt b/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt new file mode 100644 index 0000000000..e8555daf23 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt @@ -0,0 +1,58 @@ +--TEST-- +Batches NativeParquetReader holds are counted by DefaultBackend::allocatedBytes(): at least their columns' buffer bytes +--SKIPIF-- + +--FILE-- +writeTo(path('memory://held.parquet')), + ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), + 'SNAPPY', + OptionsConverter::toExtension(Options::default()), +); + +foreach (array_chunk(range(0, 65_535), 8_192) as $ids) { + $writer->write(native_rows($schema, array_map(static fn(int $i): array => ['id' => $i, 'email' => "user{$i}@example.com", 'amount' => $i % 5 ? $i / 7 : null], $ids))); +} + +$writer->close(); +gc_collect_cycles(); + +$before = (new DefaultBackend())->allocatedBytes(); +$reader = new NativeParquetReader($filesystem->readFrom(path('memory://held.parquet')), $schema, 1_000, null, null); +$held = []; + +while (($batch = $reader->next()) !== null) { + $held[] = $batch; +} + +$reader->close(); +unset($reader); +gc_collect_cycles(); + +$bufferBytes = 0; + +foreach ($held as $batch) { + foreach ($batch->columns() as $column) { + $bufferBytes += array_sum(array_map(strlen(...), $column->encode())); + } +} + +var_dump(array_sum(array_map(count(...), $held))); +var_dump((new DefaultBackend())->allocatedBytes() - $before >= $bufferBytes); +?> +--EXPECT-- +int(65536) +bool(true) diff --git a/src/lib/filesystem/tests/Flow/Filesystem/Tests/Double/FailingAppendDestinationStream.php b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Double/FailingAppendDestinationStream.php new file mode 100644 index 0000000000..7a9f96d683 --- /dev/null +++ b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Double/FailingAppendDestinationStream.php @@ -0,0 +1,48 @@ +inner->path()->uri())); + } + + public function close(): void + { + $this->inner->close(); + } + + /** + * @param resource $resource + */ + public function fromResource($resource): self + { + $this->inner->fromResource($resource); + + return $this; + } + + public function isOpen(): bool + { + return $this->inner->isOpen(); + } + + public function path(): Path + { + return $this->inner->path(); + } +} diff --git a/src/lib/filesystem/tests/Flow/Filesystem/Tests/Double/FailingReadSourceStream.php b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Double/FailingReadSourceStream.php new file mode 100644 index 0000000000..d5da9b19df --- /dev/null +++ b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Double/FailingReadSourceStream.php @@ -0,0 +1,59 @@ +inner->close(); + } + + public function content(): string + { + return $this->inner->content(); + } + + public function isOpen(): bool + { + return $this->inner->isOpen(); + } + + public function iterate(int $length = 1): Generator + { + return $this->inner->iterate($length); + } + + public function path(): Path + { + return $this->inner->path(); + } + + public function read(int $length, int $offset): string + { + throw new RuntimeException(sprintf('Reading "%s" failed', $this->inner->path()->uri())); + } + + public function readLines(string $separator = "\n", ?int $length = null): Generator + { + return $this->inner->readLines($separator, $length); + } + + public function size(): ?int + { + return $this->inner->size(); + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/Data/DeltaBinaryPackedDecoder.php b/src/lib/parquet/src/Flow/Parquet/Data/DeltaBinaryPackedDecoder.php index e2d7724587..54bfd95b81 100644 --- a/src/lib/parquet/src/Flow/Parquet/Data/DeltaBinaryPackedDecoder.php +++ b/src/lib/parquet/src/Flow/Parquet/Data/DeltaBinaryPackedDecoder.php @@ -63,20 +63,18 @@ public function decode(string $data, int $valueCount): array return [$header->firstValue]; } - return $this->reconstructValues( - $header->firstValue, - $this->readBlocks($reader, $valueCount - 1, $header->blockSize), - ); + return $this->reconstructValues($header->firstValue, $this->readBlocks($reader, $valueCount - 1, $header)); } /** * @return array */ - private function readBlock(BinaryBufferReader $reader, int $blockDeltaCount): array + private function readBlock(BinaryBufferReader $reader, int $blockDeltaCount, DeltaHeader $header): array { $minDelta = $this->readSignedLEB128($reader); - $miniblockCount = (int) ceil($blockDeltaCount / $this->miniblockSize); + // every block carries the header's count of bit widths, even when its last miniblocks hold no deltas + $miniblockCount = $header->miniblockCount; $bitWidths = []; @@ -97,7 +95,7 @@ private function readBlock(BinaryBufferReader $reader, int $blockDeltaCount): ar if ($bitWidth === null) { throw new RuntimeException('Missing bit width for miniblock index ' . $miniblockIndex); } - $miniblockSize = $this->miniblockSize; + $miniblockSize = intdiv($header->blockSize, $header->miniblockCount); $remainingDeltas = $blockDeltaCount - $deltasRead; $valuesToRead = min($miniblockSize, $remainingDeltas); @@ -150,16 +148,16 @@ static function ($delta) use ($minDelta) { /** * @return array */ - private function readBlocks(BinaryBufferReader $reader, int $deltaCount, int $blockSize): array + private function readBlocks(BinaryBufferReader $reader, int $deltaCount, DeltaHeader $header): array { $deltas = []; $deltasRead = 0; while ($deltasRead < $deltaCount) { $remainingDeltas = $deltaCount - $deltasRead; - $blockDeltaCount = min($blockSize, $remainingDeltas); + $blockDeltaCount = min($header->blockSize, $remainingDeltas); - $blockDeltas = $this->readBlock($reader, $blockDeltaCount); + $blockDeltas = $this->readBlock($reader, $blockDeltaCount, $header); $deltas = array_merge($deltas, $blockDeltas); $deltasRead += count($blockDeltas); } diff --git a/src/lib/parquet/src/Flow/Parquet/Data/DeltaBinaryPackedEncoder.php b/src/lib/parquet/src/Flow/Parquet/Data/DeltaBinaryPackedEncoder.php index 55565b84a2..2301841bba 100644 --- a/src/lib/parquet/src/Flow/Parquet/Data/DeltaBinaryPackedEncoder.php +++ b/src/lib/parquet/src/Flow/Parquet/Data/DeltaBinaryPackedEncoder.php @@ -7,6 +7,7 @@ use Flow\Parquet\BinaryWriter\BinaryBufferWriter; use Flow\Parquet\Exception\InvalidArgumentException; +use function array_pad; use function count; final readonly class DeltaBinaryPackedEncoder @@ -57,8 +58,9 @@ public function encode(array $values): string */ private function packMiniblock(array $values, int $bitWidth): string { + // a zero-width miniblock has no body: its bit width alone says every delta equals the block's minimum if ($bitWidth === 0) { - return str_repeat("\x00", max(0, (int) ceil($this->miniblockSize / 8))); + return ''; } $buffer = ''; @@ -181,7 +183,8 @@ private function writeBlock(BinaryBufferWriter $writer, array $blockDeltas): voi $packedMiniblocks[] = $this->packMiniblock($padded, $bitWidth); } - $writer->writeBytes($bitWidths); + // a partial last block still carries every miniblock's bit width, the unused ones zero, without their bodies + $writer->writeBytes(array_pad($bitWidths, intdiv($this->blockSize, $this->miniblockSize), 0)); foreach ($packedMiniblocks as $packed) { $writer->append($packed); diff --git a/src/lib/parquet/src/Flow/Parquet/Dremel/ColumnData/PagedFlatColumnValues.php b/src/lib/parquet/src/Flow/Parquet/Dremel/ColumnData/PagedFlatColumnValues.php new file mode 100644 index 0000000000..06b56cc210 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/Dremel/ColumnData/PagedFlatColumnValues.php @@ -0,0 +1,50 @@ + $pages + */ + public function __construct( + public FlatColumn $column, + private Generator $pages, + ) {} + + /** + * @return Generator + */ + public function assembleFlat(DataConverter $dataConverter): Generator + { + foreach ($this->pages as $page) { + // @mago-ignore analysis:mixed-assignment + foreach ($page->assembleFlat($dataConverter) as $value) { + yield $value; + } + } + } + + public function flatPath(): string + { + return $this->column->flatPath(); + } + + /** + * @return Generator + */ + public function iterator(): Generator + { + foreach ($this->pages as $page) { + foreach ($page->iterator() as $value) { + yield $value; + } + } + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/Dremel/DremelAssembler.php b/src/lib/parquet/src/Flow/Parquet/Dremel/DremelAssembler.php index 14d94ef915..5a066ce7b5 100644 --- a/src/lib/parquet/src/Flow/Parquet/Dremel/DremelAssembler.php +++ b/src/lib/parquet/src/Flow/Parquet/Dremel/DremelAssembler.php @@ -360,12 +360,15 @@ private function assemblyStructure( } if (!$repeated) { + // a REQUIRED struct adds no definition level: a child null below it leaves the struct present + $definitionLevel = $column->repetitions()->maxDefinitionLevel(); + foreach ($iterator as $iteration) { $structure = []; // @mago-ignore analysis:mixed-assignment foreach ($iteration as $propertyName => $propertyValue) { - if ($propertyValue instanceof NullLevel && $propertyValue->level < $depth) { + if ($propertyValue instanceof NullLevel && $propertyValue->level < $definitionLevel) { yield new NullLevel($propertyValue->level); continue 2; diff --git a/src/lib/parquet/src/Flow/Parquet/Dremel/ReadColumnData.php b/src/lib/parquet/src/Flow/Parquet/Dremel/ReadColumnData.php index 46caffebc1..c609df1414 100644 --- a/src/lib/parquet/src/Flow/Parquet/Dremel/ReadColumnData.php +++ b/src/lib/parquet/src/Flow/Parquet/Dremel/ReadColumnData.php @@ -5,6 +5,7 @@ namespace Flow\Parquet\Dremel; use Flow\Parquet\Dremel\ColumnData\FlatValue; +use Flow\Parquet\Dremel\ColumnData\PagedFlatColumnValues; use Flow\Parquet\Dremel\ColumnData\ReadFlatColumnValues; use Flow\Parquet\Exception\InvalidArgumentException; use Flow\Parquet\ParquetFile\Schema\Column; @@ -19,13 +20,13 @@ public Column $column; /** - * @var array + * @var array */ public array $flatValues; /** * @param Column $column - * @param array $flatValues + * @param array $flatValues */ public function __construct(Column $column, array $flatValues = []) { diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php index caa82d06d5..6cd00f8094 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php @@ -7,7 +7,7 @@ use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; use Flow\Parquet\Binary\ByteOrder; -use Flow\Parquet\Dremel\ColumnData\ReadFlatColumnValues; +use Flow\Parquet\Dremel\ColumnData\PagedFlatColumnValues; use Flow\Parquet\Dremel\DremelAssembler; use Flow\Parquet\Dremel\ReadColumnData; use Flow\Parquet\Exception\InvalidArgumentException; @@ -30,10 +30,8 @@ use Flow\Parquet\ThriftModel\FileMetaData; use Generator; -use function array_push; use function count; use function is_array; -use function iterator_to_array; use function min; use function unpack; @@ -215,32 +213,17 @@ private function readColumn( } } } elseif ($column instanceof NestedColumn) { - $mergedFlatData = []; + $flatData = []; foreach ($column->childrenFlat() as $child) { - $pages = iterator_to_array($chunkReader->read($rowGroup->getColumnChunk($child), $child, $stream)); - - $allRepetitionLevels = []; - $allDefinitionLevels = []; - - foreach ($pages as $page) { - array_push($allRepetitionLevels, ...$page->repetitionLevels()); - array_push($allDefinitionLevels, ...$page->definitionLevels()); - } - - $mergedFlatData[] = new ReadFlatColumnValues( + $flatData[] = new PagedFlatColumnValues($child, $chunkReader->read( + $rowGroup->getColumnChunk($child), $child, - (static function () use ($pages) { - foreach ($pages as $page) { - yield from $page->rawValues(); - } - })(), - $allRepetitionLevels, - $allDefinitionLevels, - ); + $stream, + )); } - $columnData = new ReadColumnData($column, $mergedFlatData); + $columnData = new ReadColumnData($column, $flatData); $rowsSkipped = 0; diff --git a/src/lib/parquet/src/Flow/Parquet/Reader/ColumnDataDecoder.php b/src/lib/parquet/src/Flow/Parquet/Reader/ColumnDataDecoder.php index 45129871e2..3d83bc730e 100644 --- a/src/lib/parquet/src/Flow/Parquet/Reader/ColumnDataDecoder.php +++ b/src/lib/parquet/src/Flow/Parquet/Reader/ColumnDataDecoder.php @@ -19,6 +19,7 @@ use Flow\Parquet\ParquetFile\Page\Header\DictionaryPageHeader; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\PhysicalType; +use Generator; use function array_fill; use function array_key_exists; @@ -170,6 +171,23 @@ public function decodeDataV2( ); } + if ($pageHeader->encoding() === Encodings::RLE && $column->type() === PhysicalType::BOOLEAN) { + // RLE data values, unlike levels in a v2 page, carry their 4-byte length first + $reader->seekBytes(4); + $values = $this->readRLEBitPackedHybrid($reader, $RLEBitPackedHybrid, 1, $nonEmptyValuesCount); + + return new ReadFlatColumnValues( + $column, + (static function () use ($values): Generator { + foreach ($values as $value) { + yield $value === 1; + } + })(), + $repetitionLevels, + $definitionLevels, + ); + } + if ($pageHeader->encoding() === Encodings::DELTA_BINARY_PACKED) { if (!in_array($column->type(), [PhysicalType::INT32, PhysicalType::INT64], true)) { throw new RuntimeException('Delta encoding only supports INT32 and INT64 physical types'); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Context/FlatColumnPages.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/FlatColumnPages.php new file mode 100644 index 0000000000..0298fb04c4 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/FlatColumnPages.php @@ -0,0 +1,132 @@ +> $rows + * + * @return list + */ + public static function merged(Schema $schema, array $rows): array + { + $pages = []; + + foreach (self::shredded($schema, $rows) as $written) { + $pages[] = self::page( + $written, + $written->repetitionLevels(), + $written->definitionLevels(), + $written->values(), + ); + } + + return $pages; + } + + /** + * @param array> $rows + * + * @return list + */ + public static function paged(Schema $schema, array $rows, int $firstPageRows): array + { + $paged = []; + + foreach (self::shredded($schema, $rows) as $written) { + $paged[] = new PagedFlatColumnValues($written->column, self::cut($written, $firstPageRows)); + } + + return $paged; + } + + /** + * @param array> $rows + * + * @return array + */ + public static function shredded(Schema $schema, array $rows): array + { + return (new DremelShredder(new ColumnDataValidator(), DataConverter::initialize(Options::default())))->shred( + $schema, + $rows, + ); + } + + /** + * @return Generator + */ + public static function cut(WriteFlatColumnValues $written, int $firstPageRows): Generator + { + $at = 0; + $rows = 0; + + foreach ($written->repetitionLevels() as $level) { + if ($level === 0 && $rows++ === $firstPageRows) { + break; + } + + $at++; + } + + $maxDefinitionLevel = $written->column->repetitions()->maxDefinitionLevel(); + $values = count(array_filter( + array_slice($written->definitionLevels(), 0, $at), + static fn(int $level): bool => $level === $maxDefinitionLevel, + )); + + yield self::page( + $written, + array_slice($written->repetitionLevels(), 0, $at), + array_slice($written->definitionLevels(), 0, $at), + array_slice($written->values(), 0, $values), + ); + yield self::page( + $written, + array_slice($written->repetitionLevels(), $at), + array_slice($written->definitionLevels(), $at), + array_slice($written->values(), $values), + ); + } + + /** + * @param array $repetitionLevels + * @param array $definitionLevels + * @param array $values + */ + public static function page( + WriteFlatColumnValues $written, + array $repetitionLevels, + array $definitionLevels, + array $values, + ): ReadFlatColumnValues { + return new ReadFlatColumnValues( + $written->column, + (static function () use ($values): Generator { + yield from $values; + })(), + $repetitionLevels, + $definitionLevels, + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/EdgeCasesReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/EdgeCasesReadingTest.php index 0ad6a8952c..138f7c4137 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/EdgeCasesReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/EdgeCasesReadingTest.php @@ -60,25 +60,23 @@ public function test_nonullable_impala(ParquetEngine $engine): void ); } - public function test_read_datapage_v2_snappy_list(): void + #[DataProvider('engine_provider')] + public function test_read_datapage_v2_snappy_list(ParquetEngine $engine): void { - $this->expectExceptionMessage('Encoding RLE not supported'); - - $path = __DIR__ . '/Fixtures/EdgeCases/datapage_v2.snappy.parquet'; - - $reader = Reader::php()->read($path); - - $rows = []; - - foreach ($reader->values() as $row) { - $rows[] = $row; - } - static::assertSame( [ - ['emptylist' => null], + ['a' => 'abc', 'b' => 1, 'c' => 2.0, 'd' => true, 'e' => [1, 2, 3]], + ['a' => 'abc', 'b' => 2, 'c' => 3.0, 'd' => true, 'e' => null], + ['a' => 'abc', 'b' => 3, 'c' => 4.0, 'd' => true, 'e' => null], + ['a' => null, 'b' => 4, 'c' => 5.0, 'd' => false, 'e' => [1, 2, 3]], + ['a' => 'abc', 'b' => 5, 'c' => 2.0, 'd' => true, 'e' => [1, 2]], ], - $rows, + iterator_to_array( + (new Reader(engine: $engine)) + ->read(__DIR__ . '/Fixtures/EdgeCases/datapage_v2.snappy.parquet') + ->values(), + false, + ), ); } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesReadingTest.php index 69468f7eb8..6adf1b3e87 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesReadingTest.php @@ -12,9 +12,11 @@ use PHPUnit\Framework\Attributes\DataProvider; use function array_filter; +use function array_map; use function array_merge_recursive; use function count; use function iterator_to_array; +use function range; class SimpleTypesReadingTest extends ParquetIntegrationTestCase { @@ -221,6 +223,27 @@ public function test_reading_delta_binary_packed_encoded_integers(ParquetEngine static::assertGreaterThan(0, count(array_filter($floatValues, static fn($v) => $v !== 0.0))); } + #[DataProvider('engine_provider')] + public function test_reading_every_delta_binary_packed_value(ParquetEngine $engine): void + { + static::assertSame( + array_map( + static fn(int $n): array => [ + 'int32_column' => $n, + 'int64_column' => ($n % 10) === 0 ? PHP_INT_MAX - ($n * 1000) : $n, + 'float_column' => ($n % 7) === 0 ? 3.4028234663852886E+38 : $n + 0.5, + ], + range(1, 1000), + ), + iterator_to_array( + (new Reader(engine: $engine)) + ->read(__DIR__ . '/Fixtures/delta_binary_acked_encoded_integers.parquet') + ->values(), + false, + ), + ); + } + #[DataProvider('engine_provider')] public function test_reading_double_column(ParquetEngine $engine): void { diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ColumnData/PagedFlatColumnValuesTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ColumnData/PagedFlatColumnValuesTest.php new file mode 100644 index 0000000000..eceb9c59c9 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ColumnData/PagedFlatColumnValuesTest.php @@ -0,0 +1,97 @@ +>}> + */ + public static function nested(): Generator + { + yield 'list' => [ + Schema::with(NestedColumn::list('l', ListElement::int32())), + 'l', + [['l' => [1, 2]], ['l' => null], ['l' => [3, null]], ['l' => []], ['l' => [4]]], + ]; + yield 'map' => [ + Schema::with(NestedColumn::map('m', MapKey::string(), MapValue::int32())), + 'm', + [['m' => ['a' => 1, 'b' => 2]], ['m' => null], ['m' => ['c' => null]], ['m' => ['d' => 4]]], + ]; + yield 'struct' => [ + Schema::with(NestedColumn::struct('s', [FlatColumn::int32('a'), FlatColumn::string('b')])), + 's', + [ + ['s' => ['a' => 1, 'b' => 'x']], + ['s' => null], + ['s' => ['a' => null, 'b' => 'y']], + ['s' => [ + 'a' => 4, + 'b' => null, + ]], + ], + ]; + } + + /** + * @param array> $rows + */ + #[DataProvider('nested')] + public function test_two_pages_assemble_as_one_merged_page(Schema $schema, string $name, array $rows): void + { + $assembler = new DremelAssembler(DataConverter::initialize(Options::default())); + $column = $schema->get($name); + + $merged = iterator_to_array($assembler->assemble( + $column, + new ReadColumnData($column, FlatColumnPages::merged($schema, $rows)), + )); + + static::assertSame($rows, $merged); + static::assertSame( + $merged, + iterator_to_array($assembler->assemble( + $column, + new ReadColumnData($column, FlatColumnPages::paged($schema, $rows, 2)), + )), + ); + } + + /** + * @param array> $rows + */ + #[DataProvider('nested')] + public function test_two_pages_iterate_as_one_merged_page(Schema $schema, string $name, array $rows): void + { + $merged = FlatColumnPages::merged($schema, $rows); + $paged = FlatColumnPages::paged($schema, $rows, 2); + + foreach ($merged as $index => $page) { + static::assertSame($page->flatPath(), $paged[$index]->flatPath()); + static::assertEquals( + iterator_to_array($page->iterator(), false), + iterator_to_array($paged[$index]->iterator()), + ); + } + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelStructuresTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelStructuresTest.php index b4afac63bc..fe18b45b6e 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelStructuresTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelStructuresTest.php @@ -17,6 +17,10 @@ use Flow\Parquet\ParquetFile\Schema\MapKey; use Flow\Parquet\ParquetFile\Schema\MapValue; use Flow\Parquet\ParquetFile\Schema\NestedColumn; +use Flow\Parquet\ParquetFile\Schema\Repetition; +use Flow\Parquet\Tests\Context\FlatColumnPages; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; @@ -24,6 +28,52 @@ final class DremelStructuresTest extends TestCase { + /** + * @return Generator>}> + */ + public static function structs_with_a_null_optional_child(): Generator + { + $children = static fn(): array => [FlatColumn::int64('id', Repetition::REQUIRED), FlatColumn::string('name')]; + + yield 'required struct' => [ + NestedColumn::struct('s', $children(), Repetition::REQUIRED), + [['s' => ['id' => 1, 'name' => null]], ['s' => ['id' => 2, 'name' => 'x']]], + ]; + yield 'optional struct' => [ + NestedColumn::struct('s', $children()), + [['s' => ['id' => 1, 'name' => null]], ['s' => null], ['s' => ['id' => 2, 'name' => 'x']]], + ]; + yield 'required struct in an optional struct' => [ + NestedColumn::struct('s', [NestedColumn::struct('inner', $children(), Repetition::REQUIRED)]), + [['s' => ['inner' => ['id' => 1, 'name' => null]]], ['s' => null]], + ]; + yield 'required struct in a list' => [ + NestedColumn::list('s', ListElement::structure($children(), required: true)), + [['s' => [['id' => 1, 'name' => null], ['id' => 2, 'name' => 'x']]], ['s' => null]], + ]; + yield 'optional struct as a map value' => [ + NestedColumn::map('s', MapKey::string(), MapValue::structure($children())), + [['s' => ['a' => ['id' => 1, 'name' => null]]], ['s' => ['b' => ['id' => 2, 'name' => 'x']]]], + ]; + } + + /** + * @param array> $rows + */ + #[DataProvider('structs_with_a_null_optional_child')] + public function test_a_null_optional_child_keeps_its_struct(NestedColumn $column, array $rows): void + { + $schema = Schema::with($column); + + static::assertSame( + $rows, + iterator_to_array((new DremelAssembler(DataConverter::initialize(Options::default())))->assemble( + $schema->get('s'), + new ReadColumnData($schema->get('s'), FlatColumnPages::merged($schema, $rows)), + )), + ); + } + /** * @param array $row */ diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ReadColumnDataTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ReadColumnDataTest.php index dca0f55e29..51c4ae2176 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ReadColumnDataTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ReadColumnDataTest.php @@ -12,6 +12,7 @@ use Flow\Parquet\ParquetFile\Schema\MapKey; use Flow\Parquet\ParquetFile\Schema\MapValue; use Flow\Parquet\ParquetFile\Schema\NestedColumn; +use Flow\Parquet\Tests\Context\FlatColumnPages; use PHPUnit\Framework\TestCase; use function iterator_to_array; @@ -121,4 +122,23 @@ public function test_iterating_over_map_column_data(): void iterator_to_array($columnData->iterator($valueColumn)), ); } + + public function test_iterating_over_a_paged_column_chains_its_pages(): void + { + $schema = Schema::with(NestedColumn::map('m', MapKey::string(), MapValue::int32())); + $rows = [['m' => ['a' => 1]], ['m' => ['b' => 2]], ['m' => ['c' => 3]]]; + $keyColumn = $schema->get('m.key_value.key'); + static::assertInstanceOf(FlatColumn::class, $keyColumn); + + $columnData = new ReadColumnData($schema->get('m'), FlatColumnPages::paged($schema, $rows, 1)); + + static::assertEquals( + [ + new FlatValue($keyColumn, 0, 2, 'a'), + new FlatValue($keyColumn, 0, 2, 'b'), + new FlatValue($keyColumn, 0, 2, 'c'), + ], + iterator_to_array($columnData->iterator($keyColumn)), + ); + } } From 2b4f33d613df1b0c561c14b096a00b0e6f53d194 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Wed, 30 Sep 2026 10:23:07 +0200 Subject: [PATCH 08/21] feat(flow-php/parquet): Reader/Writer::arrow() run on flow_php, arrow-ext deprecated - ParquetEngine::openForRead() returns a ParquetFileReader, replaces readColumns() - flow_php lib surface: footer read and decoded once in Rust, PHP engine values and write acceptance - column chunks fetched once per row group instead of per page header - PhpParquetEngine reads unsigned ints and INT96 exactly, refuses values it wrote wrongly - from_parquet opens each file once and reads ENUM columns --- .../components/extensions/arrow-ext.md | 6 + .../components/extensions/flow-php-ext.md | 27 +- documentation/components/libs/parquet.md | 56 +- .../installation/packages/arrow-ext.md | 6 + documentation/upgrading.md | 57 +- .../Adapter/Parquet/EngineParquetOpener.php | 18 + .../Parquet/NativeParquetOpenSource.php | 6 +- .../Adapter/Parquet/NativeParquetOpener.php | 28 +- .../ETL/Adapter/Parquet/ParquetExtractor.php | 98 ++- .../ETL/Adapter/Parquet/ParquetLoader.php | 3 +- .../ETL/Adapter/Parquet/ParquetOpener.php | 16 + .../ETL/Adapter/Parquet/ParquetOpeners.php | 18 +- .../Adapter/Parquet/ParquetSchemaPassFile.php | 41 ++ .../ETL/Adapter/Parquet/ParquetSourceFile.php | 46 +- .../ETL/Adapter/Parquet/SchemaConverter.php | 7 +- .../Tests/Context/ParquetFilesContext.php | 15 + .../Context/ParquetSourceFileContext.php | 22 +- .../Fixtures/EdgeCases/interval.parquet | Bin 0 -> 283 bytes .../Fixtures/EdgeCases/unsigned.parquet | Bin 0 -> 298 bytes .../ParquetExtractorFooterTest.php | 135 ++++ .../Parquet/Tests/Integration/ParquetTest.php | 75 +- .../Tests/Unit/EngineParquetOpenerTest.php | 4 +- .../Unit/NativeParquetOpenSourceTest.php | 40 +- .../Tests/Unit/NativeParquetOpenerTest.php | 24 +- .../Tests/Unit/ParquetExtractorTest.php | 6 + .../Parquet/Tests/Unit/ParquetOpenersTest.php | 97 ++- .../Tests/Unit/ParquetSourceFileTest.php | 3 +- .../Tests/Unit/ParquetToFlowSchemaTest.php | 4 + src/extension/arrow-ext/composer.json | 1 + src/extension/flow-php-ext/composer.json | 1 + .../Adapter/Parquet/NativeParquetReader.php | 5 +- .../Native/NativeParquetColumnsReader.php | 40 + .../Engine/Native/NativeParquetFile.php | 64 ++ .../Engine/Native/NativeParquetRowsWriter.php | 56 ++ src/extension/flow-php-ext/src/ctx.rs | 14 + .../flow-php-ext/src/kind_builder.rs | 102 +++ src/extension/flow-php-ext/src/lib.rs | 4 + .../flow-php-ext/src/parquet/canonical.rs | 398 +++++++++- .../flow-php-ext/src/parquet/cells.rs | 683 ++++++++++++++++++ .../flow-php-ext/src/parquet/error.rs | 13 + src/extension/flow-php-ext/src/parquet/etl.rs | 28 +- .../flow-php-ext/src/parquet/fetch.rs | 293 ++++++++ .../flow-php-ext/src/parquet/footer.rs | 171 +++++ .../flow-php-ext/src/parquet/library.rs | 403 +++++++++++ src/extension/flow-php-ext/src/parquet/mod.rs | 4 + .../flow-php-ext/src/parquet/read.rs | 481 ++++++++++-- .../flow-php-ext/src/parquet/source.rs | 67 +- src/extension/flow-php-ext/src/render.rs | 77 +- src/extension/flow-php-ext/src/thrift.rs | 420 +++++++++++ src/extension/flow-php-ext/src/values.rs | 11 +- .../tests/phpt/068_parquet_read_parity.phpt | 30 +- .../tests/phpt/069_parquet_offset_limit.phpt | 6 +- .../tests/phpt/071_parquet_no_leaks.phpt | 6 +- .../phpt/072_parquet_allocations_counted.phpt | 4 +- .../phpt/073_parquet_lib_read_parity.phpt | 76 ++ .../phpt/074_parquet_lib_write_parity.phpt | 42 ++ .../075_parquet_footer_thrift_parity.phpt | 57 ++ .../tests/phpt/076_parquet_lib_no_leaks.phpt | 73 ++ .../flow-php-ext/tests/phpt/bootstrap.php | 8 + .../ParquetViewer/Command/ReadDDLCommand.php | 4 +- .../ParquetViewer/Command/ReadDataCommand.php | 4 +- .../Command/ReadMetadataCommand.php | 4 +- src/lib/parquet/composer.json | 5 +- .../Flow/Parquet/Dremel/DremelShredder.php | 85 ++- .../src/Flow/Parquet/Dremel/Validator.php | 4 +- .../Dremel/Validator/ColumnDataValidator.php | 116 ++- .../Dremel/Validator/DisabledValidator.php | 2 +- .../Parquet/Engine/AdaptiveParquetEngine.php | 20 +- .../Parquet/Engine/Arrow/SchemaConverter.php | 40 +- .../Parquet/Engine/ArrowParquetEngine.php | 118 +-- .../Parquet/Engine/ArrowParquetFileReader.php | 116 +++ .../Engine/NativeParquetFileReader.php | 109 +++ .../Engine/NativeParquetFileWriter.php | 53 ++ .../Flow/Parquet/Engine/PhpParquetEngine.php | 228 +----- .../Parquet/Engine/PhpParquetFileReader.php | 191 +++++ .../src/Flow/Parquet/ParquetEngine.php | 21 +- .../parquet/src/Flow/Parquet/ParquetFile.php | 80 +- .../Data/Converter/Int96DateTimeConverter.php | 25 +- .../Converter/UnsignedIntegerConverter.php | 57 ++ .../ParquetFile/Data/DataConverter.php | 2 + .../Parquet/ParquetFile/Schema/FlatColumn.php | 2 +- .../ParquetFile/Schema/LogicalType.php | 17 +- .../Schema/LogicalType/Integer.php | 55 ++ .../src/Flow/Parquet/ParquetFileReader.php | 42 ++ src/lib/parquet/src/Flow/Parquet/Reader.php | 15 +- .../src/Flow/Parquet/Reader/ColumnReader.php | 104 +++ .../ThriftModel/BloomFilterAlgorithm.php | 2 +- .../ThriftModel/BloomFilterCompression.php | 2 +- .../Parquet/ThriftModel/BloomFilterHash.php | 2 +- .../Parquet/ThriftModel/BloomFilterHeader.php | 6 +- .../Flow/Parquet/ThriftModel/ColumnChunk.php | 4 +- .../ThriftModel/ColumnCryptoMetaData.php | 4 +- .../Flow/Parquet/ThriftModel/ColumnIndex.php | 2 +- .../Parquet/ThriftModel/ColumnMetaData.php | 14 +- .../Flow/Parquet/ThriftModel/ColumnOrder.php | 2 +- .../Parquet/ThriftModel/DataPageHeader.php | 8 +- .../Parquet/ThriftModel/DataPageHeaderV2.php | 4 +- .../ThriftModel/DictionaryPageHeader.php | 2 +- .../ThriftModel/EncryptionAlgorithm.php | 4 +- .../ThriftModel/FileCryptoMetaData.php | 2 +- .../Flow/Parquet/ThriftModel/FileMetaData.php | 10 +- .../Flow/Parquet/ThriftModel/LogicalType.php | 28 +- .../Flow/Parquet/ThriftModel/OffsetIndex.php | 2 +- .../Parquet/ThriftModel/PageEncodingStats.php | 4 +- .../Flow/Parquet/ThriftModel/PageHeader.php | 10 +- .../src/Flow/Parquet/ThriftModel/RowGroup.php | 4 +- .../Parquet/ThriftModel/SchemaElement.php | 8 +- .../src/Flow/Parquet/ThriftModel/TimeType.php | 2 +- .../src/Flow/Parquet/ThriftModel/TimeUnit.php | 6 +- .../Parquet/ThriftModel/TimestampType.php | 2 +- .../Flow/Parquet/Writer/RowGroupBuilder.php | 14 +- .../Flow/Parquet/Tests/Context/EveryType.php | 109 +++ .../Parquet/Tests/Context/FlatColumnPages.php | 1 + .../Tests/Context/MemoryParquetFile.php | 73 ++ .../Parquet/Tests/Context/ParquetRows.php | 50 ++ .../Parquet/Tests/Context/WriteAcceptance.php | 190 +++++ .../Tests/Double/ReadCountingSourceStream.php | 72 ++ .../Tests/Double/SpyParquetFileReader.php | 64 ++ .../Parquet/Tests/Double/StringableUuid.php | 22 + .../Parquet/Tests/Double/ToStringUuid.php | 20 + .../Engine/ArrowParquetEngineReadTest.php | 50 +- .../Engine/ArrowParquetEngineWriteTest.php | 4 +- .../Integration/Engine/CrossEngineTest.php | 15 +- .../Integration/Engine/EngineParityTest.php | 4 +- .../Engine/NativeLibParityTest.php | 146 ++++ .../Engine/NativeLibRegressionTest.php | 183 +++++ .../Engine/NativeLibWriteParityTest.php | 107 +++ .../Engine/NativeParquetFileReaderTest.php | 115 +++ .../Integration/Engine/ReadColumnsTest.php | 7 +- .../IO/Fixtures/EdgeCases/int96.parquet | Bin 0 -> 351 bytes .../IO/Fixtures/EdgeCases/interval.parquet | Bin 0 -> 283 bytes .../IO/Fixtures/EdgeCases/map_keys.parquet | Bin 0 -> 1069 bytes .../EdgeCases/uint64_overflow.parquet | Bin 0 -> 196 bytes .../IO/Fixtures/EdgeCases/unsigned.parquet | Bin 0 -> 298 bytes .../IO/ParquetIntegrationTestCase.php | 4 +- .../Integration/IO/SchemaReadingTest.php | 4 +- .../Integration/IO/SimpleTypesWritingTest.php | 2 +- .../Integration/ParquetFile/SchemaTest.php | 2 +- .../ColumnData/WriteFlatColumnValuesTest.php | 4 +- .../Tests/Unit/Dremel/DremelFlatTest.php | 6 +- .../Tests/Unit/Dremel/DremelListsTest.php | 36 +- .../Tests/Unit/Dremel/DremelMapsTest.php | 40 +- .../Tests/Unit/Dremel/DremelShredderTest.php | 22 +- .../Unit/Dremel/DremelStructuresTest.php | 32 +- .../Validator/ColumnDataValidatorTest.php | 206 ++++++ .../Unit/Engine/AdaptiveParquetEngineTest.php | 12 +- .../Unit/Engine/ArrowParquetEngineTest.php | 70 +- .../Engine/ArrowParquetFileWriterTest.php | 4 +- .../Engine/NativeParquetFileWriterTest.php | 176 +++++ .../Unit/Engine/PhpParquetFileReaderTest.php | 113 +++ .../Converter/Int96DateTimeConverterTest.php | 50 ++ .../UnsignedIntegerConverterTest.php | 91 +++ .../ParquetFile/Schema/FlatColumnTest.php | 10 + .../Schema/LogicalType/IntegerTest.php | 78 ++ .../ParquetFile/Schema/LogicalTypeTest.php | 14 + .../Parquet/Tests/Unit/ParquetFileTest.php | 91 +++ .../Tests/Unit/Reader/ColumnReaderTest.php | 68 ++ .../Flow/Parquet/Tests/Unit/ReaderTest.php | 2 +- .../PageBuilder/DictionaryBuilderTest.php | 2 +- .../Flow/Parquet/Tests/Unit/WriterTest.php | 4 +- 160 files changed, 7573 insertions(+), 965 deletions(-) create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaPassFile.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/Fixtures/EdgeCases/interval.parquet create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/Fixtures/EdgeCases/unsigned.parquet create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetExtractorFooterTest.php create mode 100644 src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetColumnsReader.php create mode 100644 src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetFile.php create mode 100644 src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetRowsWriter.php create mode 100644 src/extension/flow-php-ext/src/parquet/cells.rs create mode 100644 src/extension/flow-php-ext/src/parquet/fetch.rs create mode 100644 src/extension/flow-php-ext/src/parquet/footer.rs create mode 100644 src/extension/flow-php-ext/src/parquet/library.rs create mode 100644 src/extension/flow-php-ext/src/thrift.rs create mode 100644 src/extension/flow-php-ext/tests/phpt/073_parquet_lib_read_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/074_parquet_lib_write_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/075_parquet_footer_thrift_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/076_parquet_lib_no_leaks.phpt create mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php create mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileReader.php create mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileWriter.php create mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetFileReader.php create mode 100644 src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/Converter/UnsignedIntegerConverter.php create mode 100644 src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/LogicalType/Integer.php create mode 100644 src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php create mode 100644 src/lib/parquet/src/Flow/Parquet/Reader/ColumnReader.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Context/EveryType.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Context/MemoryParquetFile.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Context/ParquetRows.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Context/WriteAcceptance.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Double/ReadCountingSourceStream.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Double/SpyParquetFileReader.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Double/StringableUuid.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Double/ToStringUuid.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeParquetFileReaderTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/int96.parquet create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/interval.parquet create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/map_keys.parquet create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/uint64_overflow.parquet create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/unsigned.parquet create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/Validator/ColumnDataValidatorTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/NativeParquetFileWriterTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/PhpParquetFileReaderTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Data/Converter/Int96DateTimeConverterTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Data/Converter/UnsignedIntegerConverterTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/LogicalType/IntegerTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFileTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Reader/ColumnReaderTest.php diff --git a/documentation/components/extensions/arrow-ext.md b/documentation/components/extensions/arrow-ext.md index 73bedf0c0f..c5a054827d 100644 --- a/documentation/components/extensions/arrow-ext.md +++ b/documentation/components/extensions/arrow-ext.md @@ -8,6 +8,12 @@ package: flow-php/arrow-ext [TOC] +> [!WARNING] +> **Deprecated.** Parquet through this extension is deprecated and will be removed; `flow-php/arrow-ext` is abandoned in +> favour of [flow-php/flow-php-ext](/documentation/components/extensions/flow-php-ext.md). Install the `flow_php` +> extension: `ArrowParquetEngine` uses it when it is loaded, and falls back to this extension with an +> `E_USER_DEPRECATED` notice otherwise. + [Apache Arrow](https://arrow.apache.org/) is a language-independent columnar memory format for flat and hierarchical data. The Arrow ecosystem provides high-performance implementations for common data operations - including I/O for formats like Parquet, CSV, JSON, and Arrow IPC - in C++, Rust, Java, Python, and other languages. diff --git a/documentation/components/extensions/flow-php-ext.md b/documentation/components/extensions/flow-php-ext.md index 7fa4700b6c..0d48627fc2 100644 --- a/documentation/components/extensions/flow-php-ext.md +++ b/documentation/components/extensions/flow-php-ext.md @@ -84,15 +84,16 @@ df() ->run(); df() - ->read(from_parquet(__DIR__ . '/orders.parquet', engine: new PhpParquetEngine())) // an explicit engine opts out + ->read(from_parquet(__DIR__ . '/orders.parquet', engine: new PhpParquetEngine())) // PhpParquetEngine opts out ->write(to_parquet(__DIR__ . '/copy.parquet', engine: new PhpParquetEngine())) ->run(); ``` -A column type the extension has no cast for is refused before the first batch, naming the engine that reads it: +`engine: new ArrowParquetEngine()` and `new AdaptiveParquetEngine()` read and write through the extension too. A column +type the extension has no cast for is refused before the first batch, naming the engine that reads it: ``` -Parquet column "emptylist" (Null) is not supported by the flow_php Parquet reader; read the file with +Parquet column "iv" (Interval(DayTime)) is not supported by the flow_php Parquet reader; read the file with from_parquet($path, engine: new \Flow\Parquet\Engine\PhpParquetEngine()) ``` @@ -102,3 +103,23 @@ A string that is not valid UTF-8 is refused on write, naming the column and its The extension also registers `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}`, the reader and writer `from_parquet()` and `to_parquet()` use. + +### The parquet library + +`Flow\Parquet\Reader::arrow()` / `Writer::arrow()` (`ArrowParquetEngine`) read and write through the extension: the +values are the ones `Reader::php()` returns, and writes accept and refuse what `Writer::php()` does. The footer is read +once and decoded in Rust; `schema()`, `rowsNumber()` and `totalByteSize()` never build the PHP metadata graph. + +```php +read(__DIR__ . '/orders.parquet'); + +$file->reader()->rowsNumber(); // from the footer, no PHP metadata graph +$file->values(['address.city'], limit: 10, offset: 5_000); // a struct path; only the row groups from row 5 000 +``` + +The classes behind it are `Flow\Parquet\Engine\Native\{NativeParquetFile, NativeParquetColumnsReader, +NativeParquetRowsWriter}`. diff --git a/documentation/components/libs/parquet.md b/documentation/components/libs/parquet.md index 9d09c1ac52..0416dfa623 100644 --- a/documentation/components/libs/parquet.md +++ b/documentation/components/libs/parquet.md @@ -14,19 +14,13 @@ For detailed installation instructions, see the [installation page](/documentati ## Engine System -The parquet library supports a pluggable engine system with two implementations: - -- **PHP Engine** (`PhpParquetEngine`) - Pure PHP implementation. Works everywhere with no extra dependencies beyond - optional compression extensions. -- **Arrow Engine** (`ArrowParquetEngine`) - Uses - the [arrow PHP extension](/documentation/components/extensions/arrow-ext.md) for native Rust-powered performance. All - compression codecs are built into the extension. -- **Adaptive Engine** (`AdaptiveParquetEngine`) - Default. Automatically selects Arrow if the `arrow` extension is - loaded, otherwise falls back to PHP. - -### Engine Selection - -By default, `new Reader()` and `new Writer()` use the adaptive engine: +- **PHP Engine** (`PhpParquetEngine`) - pure PHP, no extra dependencies beyond optional compression extensions. +- **Arrow Engine** (`ArrowParquetEngine`) - native Rust through the + [flow_php extension](/documentation/components/extensions/flow-php-ext.md); every compression codec is built in. + Without `flow_php` it falls back to the deprecated [arrow extension](/documentation/components/extensions/arrow-ext.md) + and raises `E_USER_DEPRECATED`. +- **Adaptive Engine** (`AdaptiveParquetEngine`) - the default: `ArrowParquetEngine` when `flow_php` or `arrow` is + loaded, `PhpParquetEngine` otherwise. ```php [!NOTE] -> When using the Arrow engine, all compression codecs are built into the native extension. The PHP compression -> extensions listed below are only required when using the PHP engine. +> With the Arrow engine every compression codec is built into the extension. The PHP compression extensions listed below +> are only required by the PHP engine. Parquet supports several compression algorithms. diff --git a/documentation/installation/packages/arrow-ext.md b/documentation/installation/packages/arrow-ext.md index 64fc3c63bd..943ff3a336 100644 --- a/documentation/installation/packages/arrow-ext.md +++ b/documentation/installation/packages/arrow-ext.md @@ -11,6 +11,12 @@ seo_description: > [TOC] +> [!WARNING] +> **Deprecated.** Parquet through this extension is deprecated and will be removed; `flow-php/arrow-ext` is abandoned in +> favour of [flow-php/flow-php-ext](/documentation/components/extensions/flow-php-ext.md). Install the `flow_php` +> extension: `ArrowParquetEngine` uses it when it is loaded, and falls back to this extension with an +> `E_USER_DEPRECATED` notice otherwise. + ## Precompiled Binaries Precompiled binaries are available for download from the [GitHub Releases](https://github.com/flow-php/arrow-ext/releases/latest) page. diff --git a/documentation/upgrading.md b/documentation/upgrading.md index ec6ee92a68..24f9a01124 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -863,7 +863,7 @@ public function eval(Rows $rows, FlowContext $context): Column | Before | After | |--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `from_parquet($path)` / `to_parquet($path)` - `AdaptiveParquetEngine` (arrow-ext when loaded, else the PHP engine) | with `flow_php` loaded: `flow_php` itself (row groups straight into native columns); without it: unchanged | -| `engine: new PhpParquetEngine()` / `new ArrowParquetEngine()` | honoured as before - an explicit engine opts out of `flow_php` | +| `engine: new PhpParquetEngine()` / `new ArrowParquetEngine()` | `engine: new PhpParquetEngine()` opts out of `flow_php`; `new ArrowParquetEngine()` / `new AdaptiveParquetEngine()` read and write through `flow_php` when it is loaded | | a column type arrow-ext could not read failed inside arrow-ext | refused before the first batch: `Parquet column "" () is not supported by the flow_php Parquet reader; read the file with from_parquet($path, engine: new \Flow\Parquet\Engine\PhpParquetEngine())` | | `flow-php/etl-adapter-parquet` installable with any `flow_php` version | `conflict: ext-flow_php <0.45` - load a `flow_php` of this release or none | @@ -875,10 +875,10 @@ public function eval(Rows $rows, FlowContext $context): Column ### 81) `flow-php/etl-adapter-parquet` - with `flow_php`, a string that is not valid UTF-8 is refused on write -| Before | After | -|------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| -| without arrow-ext, `PhpParquetEngine` wrote `"\xff\xfe"` into a `STRING` column other readers reject (DuckDB: `is not valid UTF8`) | `Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8` - the row is 0-based within the batch written | -| with arrow-ext: `Column 'name': expected string, got string` | the same refusal; `engine: new PhpParquetEngine()` still writes the bytes | +| Before | After | +|------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| without arrow-ext, `PhpParquetEngine` wrote `"\xff\xfe"` into a `STRING` column other readers reject (DuckDB: `is not valid UTF8`) | `Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8` - the row is 0-based within the batch written | +| with arrow-ext: `Column 'name': expected string, got string` | the same refusal; invalid UTF-8 into `STRING` / `JSON` / `ENUM` is refused by both engines; `Option::VALIDATE_DATA = false` on `PhpParquetEngine` writes it unvalidated (a file other readers reject); `flow_php` always refuses | ### 82) `flow-php/parquet` - `DELTA_BINARY_PACKED` follows the spec; affected files written by `PhpParquetEngine` must be rewritten @@ -888,6 +888,53 @@ public function eval(Rows $rows, FlowContext $context): Column | it read other writers' `DELTA_BINARY_PACKED` `INT64` wrong after an outlier (`9223372036854645807` read as `9223372036788279061`, garbage after) | reads them as DuckDB and arrow-rs do | | affected: `INT32`/`INT64` columns `PhpParquetEngine` wrote with `Option::WRITER_VERSION` `2` or `COLUMNS_ENCODINGS` `DELTA_BINARY_PACKED` (the default is version `1`, `PLAIN`) | no spec-conformant reader returns their values: read them with the Flow version that wrote them and write them again (or re-export from the source) | +### 83) `flow-php/parquet` - `ParquetEngine::openForRead()` replaces `readColumns()` + +| Before | After | +|---------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `$engine->readColumns($stream, $schema, $columns, $batchSize, $limit, $offset)` | `$engine->openForRead($stream)->readColumns($columns, $batchSize, $limit, $offset)` | +| a custom `ParquetEngine` implements `readColumns()` | it implements `openForRead(SourceStream): ParquetFileReader` - `metadata()`, `schema()`, `rowsNumber()`, `totalByteSize()`, `readColumns()`, `close()` (which closes the stream) | +| `new ParquetFile($stream, $byteOrder, $options, $engine)` | `new ParquetFile($stream, $options, $engine->openForRead($stream))` | +| a `ParquetFile` closed its stream only when destroyed | `ParquetFile::close()` closes its reader (once); `ParquetFile::reader()` returns it | + +### 84) `flow-php/parquet` - with `flow_php` loaded, `ArrowParquetEngine` reads and writes through it; arrow-ext's Parquet is deprecated + +| Before | After | +|----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Reader::arrow()` / `Writer::arrow()` / `new ArrowParquetEngine()` - arrow-ext | `flow_php` when it is loaded; arrow-ext otherwise, with an `E_USER_DEPRECATED` notice (`@`-silenced) | +| `new AdaptiveParquetEngine()` - arrow-ext when loaded, else the PHP engine | `flow_php` or arrow-ext loaded: `ArrowParquetEngine`; neither: `PhpParquetEngine` | +| `DATE` read as `DateTimeImmutable` in zone `+00:00` | zone `UTC`, as `PhpParquetEngine` | +| `TIME` of 25 hours read as `PT25H`, `days` `false` | `d` = 1, `h` = 1, `days` an int (the `diff()` interval `PhpParquetEngine` returns) | +| `INT96` outside 1677-2262 read wrapped (0001-01-01 → 1754-08-30) | read exactly, floored to the microsecond | +| `UINT_64` above `PHP_INT_MAX` read as a numeric string | refused, as by `PhpParquetEngine` | +| writes accepted an int into `FLOAT` / `DOUBLE` / `DATE` / `TIMESTAMP` / `TIME`, a numeric string into `DECIMAL` / `UINT_64` | refused - writes accept what `PhpParquetEngine` accepts; decimals are written from floats (or ints) as `PhpParquetEngine` writes them; an object with `toString()` into `UUID` is accepted | +| `TIME` writes dropped the interval's `d` | kept | +| an offset read decoded every row group before the offset; page headers were read to the end of the file | only the row groups a read needs, each column chunk read once | +| an `INTERVAL`, a path into a `LIST` / `MAP`, `LZO` or `INT96` under `Option::INT_96_AS_DATETIME = false` failed inside arrow-ext | refused before the first batch naming the column and `\Flow\Parquet\Reader::php()` | +| `Reader::read()` returned without touching the file; an invalid file failed at `metadata()` | with `flow_php` the footer is read when the file is opened: `Reader::read()` / `readStream()` throw `InvalidArgumentException` `Given file is not valid Parquet file: …` | +| `flow-php/parquet` installable with any `flow_php` version | `conflict: ext-flow_php <0.45` | + +### 85) `flow-php/parquet` - `PhpParquetEngine` reads unsigned integers and INT96 exactly; `FlatColumn::enum()` writes the ENUM logical type; values it wrote wrongly are refused + +| Before | After | +|-----------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `UINT_32` 4000000000 read as `-294967296`; `UINT_64` 18446744073709551615 read as `-1` | `4000000000`; a `UINT_64` above `PHP_INT_MAX` is refused | +| `INT96` 1960-01-01 23:59:59.999999999 read as 1960-01-02 00:00:00 (rounded) | 1960-01-01 23:59:59.999999 (floored, integer arithmetic) | +| `FlatColumn::enum()` wrote logical `STRING` + converted `ENUM`, a file arrow-rs refuses | logical `ENUM` + converted `ENUM` | +| `from_parquet()` refused a logical `ENUM` column (`ENUM is not supported`) | read as a `string` column, as `STRING` | +| an int outside an `INT_8/16/32` or `UINT_8/16/32/64` range written wrapped (4000000000 into `INT32` → `-294967296`), negatives into `UINT` accepted | `ValidationException` `Column "" row : … is out of the … range` | +| a `UUID` / `FIXED_LEN_BYTE_ARRAY(n)` value of another byte length written cut or short | refused naming column and row | +| invalid UTF-8 into `STRING` / `JSON` / `ENUM` written (other readers reject the file) | refused naming column and row | +| these checks | run under `Option::VALIDATE_DATA` (default `true`), as every other validator check | +| `Validator::validate(Column $column, mixed $data): void` | `Validator::validate(Column $column, mixed $data, int $row): void` - custom validators add the parameter (the 0-based row within the writer) | +| logical `INTEGER` read without its width and sign; written back as an `IntType` missing both (a footer arrow-rs refuses) | `LogicalType::integerData(): ?LogicalType\Integer` keeps them and writes them back; `LogicalType::integer()` → `LogicalType::integer(int $bitWidth, bool $isSigned)` | + +### 86) `flow-php/arrow-ext` - deprecated, replaced by `flow-php/flow-php-ext` + +| Before | After | +|----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------| +| `flow-php/arrow-ext` - the arrow extension, `ArrowParquetEngine`'s backend | `abandoned` in favour of `flow-php/flow-php-ext`: install the `flow_php` extension, which `ArrowParquetEngine` uses when it is loaded | + --- ## Upgrading from 0.43.x to 0.44.x diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php index 01f5d07d01..70d164f5f9 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php @@ -5,18 +5,33 @@ namespace Flow\ETL\Adapter\Parquet; use Flow\Filesystem\DestinationStream; +use Flow\Filesystem\SourceStream; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; +use Flow\Parquet\ParquetFile; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema as ParquetSchema; +use Flow\Parquet\ParquetFileReader; use Flow\Parquet\Writer; +/** + * @implements ParquetOpener + */ final readonly class EngineParquetOpener implements ParquetOpener { public function __construct( private ParquetEngine $engine, + private Options $options, ) {} + /** + * @return ParquetFile + */ + public function file(SourceStream $stream): ParquetFile + { + return new ParquetFile($stream, $this->options, $this->engine->openForRead($stream)); + } + public function sink( DestinationStream $stream, ParquetSchema $schema, @@ -29,6 +44,9 @@ public function sink( return new EngineParquetOpenSink($writer, new ParquetEncoder($schema)); } + /** + * @param ParquetSourceFile $file + */ public function source(ParquetSourceFile $file): ParquetOpenSource { return new EngineParquetOpenSource($file->file); diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php index f119687fd9..5802202496 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php @@ -7,7 +7,7 @@ use Flow\ETL\Column\Backend; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\Filesystem\SourceStream; +use Flow\Parquet\Engine\Native\NativeParquetFile; use Generator; final class NativeParquetOpenSource implements ParquetOpenSource @@ -15,13 +15,13 @@ final class NativeParquetOpenSource implements ParquetOpenSource private ?NativeParquetReader $reader = null; public function __construct( - private readonly SourceStream $stream, + private readonly NativeParquetFile $file, ) {} public function batches(Schema $schema, int $batchSize, ?int $offset, ?int $limit, Backend $backend): Generator { $this->reader?->close(); - $reader = $this->reader = new NativeParquetReader($this->stream, $schema, $batchSize, $offset, $limit); + $reader = $this->reader = new NativeParquetReader($this->file, $schema, $batchSize, $offset, $limit); while (($batch = $reader->next()) !== null) { $columns = []; diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php index 359e32200c..fc7a754de2 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php @@ -5,15 +5,38 @@ namespace Flow\ETL\Adapter\Parquet; use Flow\Filesystem\DestinationStream; +use Flow\Filesystem\SourceStream; use Flow\Parquet\Engine\Arrow\OptionsConverter; use Flow\Parquet\Engine\Arrow\SchemaConverter as ArrowSchemaConverter; use Flow\Parquet\Engine\ArrowParquetEngine; +use Flow\Parquet\Engine\Native\NativeParquetFile; +use Flow\Parquet\Engine\NativeParquetFileReader; use Flow\Parquet\Options; +use Flow\Parquet\ParquetFile; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema as ParquetSchema; +/** + * @implements ParquetOpener + */ final readonly class NativeParquetOpener implements ParquetOpener { + public function __construct( + private Options $options, + ) {} + + /** + * @return ParquetFile + */ + public function file(SourceStream $stream): ParquetFile + { + return new ParquetFile( + $stream, + $this->options, + new NativeParquetFileReader(new NativeParquetFile($stream), $this->options), + ); + } + public function sink( DestinationStream $stream, ParquetSchema $schema, @@ -30,8 +53,11 @@ public function sink( ); } + /** + * @param ParquetSourceFile $file + */ public function source(ParquetSourceFile $file): ParquetOpenSource { - return new NativeParquetOpenSource($file->stream); + return new NativeParquetOpenSource($file->file->reader()->file()); } } 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 e21aa43080..d4ba1fbb1d 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 @@ -13,6 +13,7 @@ use Flow\ETL\Extractor\FileReading; use Flow\ETL\Extractor\MetadataColumnsExtractor; use Flow\ETL\Extractor\RewindableExtractor; +use Flow\ETL\Extractor\SelfDescribingFile; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; @@ -27,7 +28,7 @@ use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; -use Flow\Parquet\Reader; +use Flow\Parquet\ParquetFileReader; use Generator; use function array_values; @@ -56,8 +57,17 @@ final class ParquetExtractor implements private ?ParquetEngine $engine = null; + /** + * The first file the schema pass opened, kept for the read that follows. + * + * @var null|ParquetSourceFile + */ + private ?ParquetSourceFile $firstFile = null; + private ?int $offset = null; + private ?ParquetOpener $opener = null; + private Options $options; private SchemaConverter $schemaConverter; @@ -88,6 +98,11 @@ public function __construct( $this->options = Options::default(); } + public function __destruct() + { + $this->closeFirstFile(); + } + public function isRepeatable(): bool { return true; @@ -104,11 +119,10 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $fileOffset = $this->offset ?? 0; // every file is read under the first file's schema, or the union of all of them - $expected = $this->derivedSchema($this->files(), $this->unionByName); + $expected = $this->derivedSchema($this->schemaFiles(), $this->unionByName); $target = $this->schema(); $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $opener = ParquetOpeners::select($this->engine); foreach ($this->files($pathFilter) as $file) { $source = null; @@ -116,7 +130,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi // finally, not a close() per exit: the limit/STOP returns below and an abandoned // generator have to release the handle too (b73) try { - $fileRows = $file->file->metadata()->rowsNumber(); + $fileRows = $file->file->reader()->rowsNumber(); if ($fileOffset > $fileRows) { $fileOffset -= $fileRows; @@ -142,7 +156,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $constants = $fileColumns->forFile($file->source(), $rowsSchema); $matchTo = !$rowsSchema->isSame($target) ? $target : null; - $source = $file->open($opener); + $source = $file->open($this->opener()); foreach ($source->batches( $body, @@ -181,7 +195,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi public function schema(): Schema { return $this->fileColumns($this->filesystem, $this->path)->declare($this->derivedSchema( - $this->files(), + $this->schemaFiles(), $this->unionByName, )); } @@ -198,6 +212,7 @@ public function unionByName(bool $union = true): self { $this->unionByName = $union; $this->derivedSchema = null; + $this->closeFirstFile(); $this->statistics = null; return $this; @@ -217,6 +232,8 @@ public function withByteOrder(ByteOrder $byteOrder): self { $this->byteOrder = $byteOrder; $this->derivedSchema = null; + $this->opener = null; + $this->closeFirstFile(); $this->statistics = null; return $this; @@ -229,6 +246,7 @@ public function withColumns(array $columns): self { $this->columns = $columns; $this->derivedSchema = null; + $this->closeFirstFile(); $this->statistics = null; return $this; @@ -238,6 +256,8 @@ public function withEngine(?ParquetEngine $engine): self { $this->engine = $engine; $this->derivedSchema = null; + $this->opener = null; + $this->closeFirstFile(); $this->statistics = null; return $this; @@ -259,6 +279,8 @@ public function withOptions(Options $options): self { $this->options = $options; $this->derivedSchema = null; + $this->opener = null; + $this->closeFirstFile(); $this->statistics = null; return $this; @@ -270,32 +292,78 @@ public function withOptions(Options $options): self */ private function declare(): Statistics { - return $this->derivedFooters($this->files(), $this->unionByName)->of( + return $this->derivedFooters($this->schemaFiles(), $this->unionByName)->of( iterator_count($this->sourceFiles($this->filesystem, $this->path)), $this->offset ?? 0, ); } + private function closeFirstFile(): void + { + $this->firstFile?->close(); + $this->firstFile = null; + } + /** - * @return Generator + * One open per file: with $keepFirst the first file stays open for the read that follows, which takes it for that + * path instead of opening it again - or closes it when the read starts at another path. + * + * @return Generator> */ - private function files(Filter $pathFilter = new OnlyFiles()): Generator + private function files(Filter $pathFilter = new OnlyFiles(), bool $keepFirst = false): Generator { + $kept = $this->firstFile; + $this->firstFile = null; + $first = true; + foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { - $stream = $this->filesystem->readFrom($source->path); + if ($first && $kept !== null && $kept->source()->uri() !== $source->uri()) { + $kept->close(); + $kept = null; + } - yield new ParquetSourceFile( - (new Reader(byteOrder: $this->byteOrder, options: $this->options, engine: $this->engine))->readStream( - $stream, - ), - $stream, + $file = ($first ? $kept : null) ?? new ParquetSourceFile( + $this->opener()->file($this->filesystem->readFrom($source->path)), $source, $this->schemaConverter, array_values($this->columns), ); + + if ($keepFirst && $first) { + $this->firstFile = $file; + } + + $first = false; + + yield $file; + } + + if ($first) { + $kept?->close(); + } + } + + /** + * The files the schema fold reads: the first one through a ParquetSchemaPassFile, which the fold's close() leaves + * open for the read that follows. + * + * @return Generator + */ + private function schemaFiles(): Generator + { + $first = true; + + foreach ($this->files(keepFirst: true) as $file) { + yield $first ? new ParquetSchemaPassFile($file) : $file; + $first = false; } } + private function opener(): ParquetOpener + { + return $this->opener ??= ParquetOpeners::select($this->engine, $this->byteOrder, $this->options); + } + public function withSchema(Schema $schema): static { throw new InvalidArgumentException( diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php index 3b0639cff4..4d8ebfa5ca 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php @@ -24,6 +24,7 @@ use Flow\Filesystem\Path; use Flow\Filesystem\Path\Option; use Flow\Filesystem\Path\Option\ContentType; +use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Option as ParquetOption; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; @@ -128,7 +129,7 @@ public function load(Rows $rows, FlowContext $context): void $this->inferredSchema ??= $rows->schema()->makeNullable(); } - $opener = $this->opener ??= ParquetOpeners::select($this->engine); + $opener = $this->opener ??= ParquetOpeners::select($this->engine, ByteOrder::LITTLE_ENDIAN, $this->options); $parquetSchema = $this->parquetSchema ??= $this->converter->toParquet($this->schema()); $conformed = ($this->conformance ??= new ParquetSchemaConformance($parquetSchema))->conform( $rows, diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php index 2f2f06fe80..5cd6a50a41 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php @@ -5,12 +5,25 @@ namespace Flow\ETL\Adapter\Parquet; use Flow\Filesystem\DestinationStream; +use Flow\Filesystem\SourceStream; use Flow\Parquet\Options; +use Flow\Parquet\ParquetFile; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema as ParquetSchema; +use Flow\Parquet\ParquetFileReader; +/** + * @template R of ParquetFileReader + */ interface ParquetOpener { + /** + * The file on $stream, opened with the reader its source() reads through. + * + * @return ParquetFile + */ + public function file(SourceStream $stream): ParquetFile; + public function sink( DestinationStream $stream, ParquetSchema $schema, @@ -18,5 +31,8 @@ public function sink( Options $options, ): ParquetOpenSink; + /** + * @param ParquetSourceFile $file + */ public function source(ParquetSourceFile $file): ParquetOpenSource; } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php index 5f3092d879..02480c6e1e 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php @@ -4,19 +4,25 @@ namespace Flow\ETL\Adapter\Parquet; +use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\AdaptiveParquetEngine; +use Flow\Parquet\Engine\ArrowParquetEngine; +use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; use function extension_loaded; final class ParquetOpeners { - public static function select(?ParquetEngine $engine): ParquetOpener + public static function select(?ParquetEngine $engine, ByteOrder $byteOrder, Options $options): ParquetOpener { - return match (true) { - $engine !== null => new EngineParquetOpener($engine), - extension_loaded('flow_php') => new NativeParquetOpener(), - default => new EngineParquetOpener(new AdaptiveParquetEngine()), - }; + if ( + extension_loaded('flow_php') + && ($engine === null || $engine instanceof AdaptiveParquetEngine || $engine instanceof ArrowParquetEngine) + ) { + return new NativeParquetOpener($options); + } + + return new EngineParquetOpener($engine ?? new AdaptiveParquetEngine($byteOrder, $options), $options); } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaPassFile.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaPassFile.php new file mode 100644 index 0000000000..7731944eea --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaPassFile.php @@ -0,0 +1,41 @@ + $file + */ + public function __construct( + private ParquetSourceFile $file, + ) {} + + public function close(): void {} + + public function schema(): Schema + { + return $this->file->schema(); + } + + public function source(): SourceFile + { + return $this->file->source(); + } + + public function statistics(): Statistics + { + return $this->file->statistics(); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php index e902a22a50..addff72960 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php @@ -9,19 +9,27 @@ use Flow\ETL\Extractor\SourceFile; use Flow\ETL\Extractor\Statistics; use Flow\ETL\Schema; -use Flow\Filesystem\SourceStream; use Flow\Parquet\ParquetFile; +use Flow\Parquet\ParquetFile\Schema as ParquetSchema; +use Flow\Parquet\ParquetFile\Schema\Column; +use Flow\Parquet\ParquetFileReader; +use function array_filter; use function count; +use function in_array; +/** + * @template R of ParquetFileReader + */ final readonly class ParquetSourceFile implements SelfDescribingFile { /** + * @param ParquetFile $file * @param list $columns */ public function __construct( + /** @var ParquetFile */ public ParquetFile $file, - public SourceStream $stream, private SourceFile $source, private SchemaConverter $converter, private array $columns, @@ -29,22 +37,36 @@ public function __construct( public function close(): void { - $this->stream->close(); + $this->file->close(); } + /** + * @param ParquetOpener $opener + */ public function open(ParquetOpener $opener): ParquetOpenSource { return $opener->source($this); } /** - * Pruning belongs to the describer, not the fold: it is applied per file, before the merge. + * Pruning belongs to the describer, not the fold: it is applied per file, before the merge. Only the projected + * columns are converted, so a column outside the projection never has to have a Flow type. */ public function schema(): Schema { - $schema = $this->converter->toFlow($this->file->schema()); + $schema = $this->file->schema(); + + if (!count($this->columns)) { + return $this->converter->toFlow($schema); + } - return count($this->columns) ? $schema->keep(...$this->columns) : $schema; + return $this->converter + ->toFlow(ParquetSchema::with(...array_filter($schema->columns(), fn(Column $column): bool => in_array( + $column->name(), + $this->columns, + true, + )))) + ->keep(...$this->columns); } public function source(): SourceFile @@ -57,13 +79,9 @@ public function source(): SourceFile */ public function statistics(): Statistics { - $metadata = $this->file->metadata(); - $bytes = 0; - - foreach ($metadata->rowGroups()->all() as $rowGroup) { - $bytes += $rowGroup->totalByteSize(); - } - - return new Statistics(rows: Cardinality::exact($metadata->rowsNumber()), size: Cardinality::exact($bytes)); + return new Statistics( + rows: Cardinality::exact($this->file->reader()->rowsNumber()), + size: Cardinality::exact($this->file->reader()->totalByteSize()), + ); } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php index 56db8c9221..8a31da9663 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php @@ -187,7 +187,10 @@ private function parquetToFlowDefinition(Column $column): Definition } return match ($logicalType->name()) { - ParquetSchema\LogicalType::STRING => str_schema($column->name(), $nullable), + ParquetSchema\LogicalType::STRING, ParquetSchema\LogicalType::ENUM => str_schema( + $column->name(), + $nullable, + ), ParquetSchema\LogicalType::TIME => time_schema($column->name(), $nullable), ParquetSchema\LogicalType::DATE => date_schema($column->name(), $nullable), ParquetSchema\LogicalType::TIMESTAMP => datetime_schema($column->name(), $nullable), @@ -262,7 +265,7 @@ public function parquetToFlowType(Column $column): Type } $type = match ($logicalType->name()) { - ParquetSchema\LogicalType::STRING => type_string(), + ParquetSchema\LogicalType::STRING, ParquetSchema\LogicalType::ENUM => type_string(), ParquetSchema\LogicalType::TIME => type_time(), ParquetSchema\LogicalType::DATE => type_date(), ParquetSchema\LogicalType::TIMESTAMP => type_datetime(), diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php index 307eab51f8..0e4e6bc605 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php @@ -9,7 +9,9 @@ use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Rows; use Flow\ETL\Schema as FlowSchema; +use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\Filesystem\Filesystem; +use Flow\Floe\Tests\Double\ClosingSpySourceStream; use Flow\Parquet\Engine\Arrow\OptionsConverter; use Flow\Parquet\Engine\Arrow\SchemaConverter as ArrowSchemaConverter; use Flow\Parquet\Engine\PhpParquetEngine; @@ -22,6 +24,7 @@ use Flow\Parquet\Reader; use Flow\Parquet\Writer; +use function array_count_values; use function array_map; use function Flow\ETL\Adapter\Parquet\to_parquet; use function Flow\ETL\DSL\data_frame; @@ -131,4 +134,16 @@ public static function deltaEncoded(Filesystem $filesystem, string $uri, array $ $writer->writeBatch(array_map(static fn(int $id): array => ['id' => $id], $ids)); $writer->close(); } + + /** + * How often each path was opened through the filesystem, by path. + * + * @return array + */ + public static function opensPerFile(CountingFilesystem $filesystem): array + { + return array_count_values(array_map(static fn(ClosingSpySourceStream $stream): string => $stream + ->path() + ->path(), $filesystem->openedStreams)); + } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php index f5faa3db62..b30b940234 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php @@ -4,12 +4,15 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Context; +use Flow\ETL\Adapter\Parquet\EngineParquetOpener; +use Flow\ETL\Adapter\Parquet\ParquetOpener; use Flow\ETL\Adapter\Parquet\ParquetSourceFile; use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Extractor\SourceFile; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; -use Flow\Parquet\Reader; +use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Options; use function Flow\Filesystem\DSL\path; @@ -21,15 +24,20 @@ public static function fixture(): Path } /** + * @template R of \Flow\Parquet\ParquetFileReader + * * @param list $columns + * @param ParquetOpener $opener + * + * @return ParquetSourceFile */ - public static function over(Filesystem $filesystem, array $columns = []): ParquetSourceFile - { - $stream = $filesystem->readFrom(self::fixture()); - + public static function over( + Filesystem $filesystem, + array $columns = [], + ParquetOpener $opener = new EngineParquetOpener(new PhpParquetEngine(), new Options()), + ): ParquetSourceFile { return new ParquetSourceFile( - (new Reader())->readStream($stream), - $stream, + $opener->file($filesystem->readFrom(self::fixture())), new SourceFile(self::fixture()), new SchemaConverter(), $columns, diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/Fixtures/EdgeCases/interval.parquet b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/Fixtures/EdgeCases/interval.parquet new file mode 100644 index 0000000000000000000000000000000000000000..c4d08ff2e13146ea4b7178a686d843d4dec6cf04 GIT binary patch literal 283 zcmYk2&q@O^5XQfRSbFI~4-*pDLoDpF%2G&iu|g4Adh%4nyL7u17yp5!c>ZBWw*^*f1&m@)pQ(wwHly}VjC~L~0{Z^=|HLtQ>g|z=X^dIjb#c4C0g{nRFuU(jL Wn|Tv&uH(~%uXBJee)(3usSQr^JvfnWRSwL|eQ3E6eVj&O({~@3r zqzD8=nIvsY86RC zjv9juP@^b=Bv^?klNgJbotTpvhm9G71`Egy5read(from_parquet(self::PAGINATION . '/01_1000.parquet', filesystem: $filesystem))->fetch(); + + static::assertSame( + [self::PAGINATION . '/01_1000.parquet' => 1], + ParquetFilesContext::opensPerFile($filesystem), + ); + static::assertSame(1, $filesystem->closedStreams()); + } + + public function test_every_file_is_opened_once_even_after_schema(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + $extractor = from_parquet(path(self::PAGINATION . '/*.parquet'), filesystem: $filesystem); + + $extractor->schema(); + iterator_to_array($extractor->extract(flow_context())); + + static::assertSame([1, 1, 1, 1, 1], array_values(ParquetFilesContext::opensPerFile($filesystem))); + static::assertSame(5, $filesystem->closedStreams()); + } + + public function test_changing_the_columns_closes_the_kept_file_and_opens_it_once_more(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + $extractor = from_parquet(path(self::PAGINATION . '/*.parquet'), filesystem: $filesystem); + + $extractor->schema(); + $extractor->withColumns(['id']); + + static::assertSame(1, $filesystem->closedStreams()); + + iterator_to_array($extractor->extract(flow_context())); + + static::assertSame([2, 1, 1, 1, 1], array_values(ParquetFilesContext::opensPerFile($filesystem))); + static::assertSame(6, $filesystem->closedStreams()); + } + + public function test_a_second_extract_opens_every_file_once_more(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + $extractor = from_parquet(path(self::PAGINATION . '/*.parquet'), filesystem: $filesystem); + + iterator_to_array($extractor->extract(flow_context())); + iterator_to_array($extractor->extract(flow_context())); + + static::assertSame([2, 2, 2, 2, 2], array_values(ParquetFilesContext::opensPerFile($filesystem))); + static::assertSame(10, $filesystem->closedStreams()); + } + + public function test_the_kept_file_is_closed_when_the_extractor_is_released_unread(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + $extractor = from_parquet(path(self::PAGINATION . '/*.parquet'), filesystem: $filesystem); + + $extractor->schema(); + + static::assertSame(0, $filesystem->closedStreams()); + + unset($extractor); + gc_collect_cycles(); + + static::assertSame(1, $filesystem->readFromCalls); + static::assertSame(1, $filesystem->closedStreams()); + } + + public function test_a_path_filter_excluding_the_first_file_closes_the_kept_one(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + $extractor = from_parquet(path(self::PAGINATION . '/*.parquet'), filesystem: $filesystem); + + $extractor->schema(); + $rows = iterator_to_array($extractor->extract(flow_context(), pathFilter: new KeepPaths([path(self::PAGINATION + . '/02_500.parquet')])), false); + + static::assertSame(500, array_sum(array_map(static fn(Rows $batch): int => $batch->count(), $rows))); + static::assertSame( + [self::PAGINATION . '/01_1000.parquet' => 1, self::PAGINATION . '/02_500.parquet' => 1], + ParquetFilesContext::opensPerFile($filesystem), + ); + static::assertSame(2, $filesystem->closedStreams()); + } + + public function test_a_partition_filter_excluding_the_first_file_closes_the_kept_one(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + + $rows = data_frame() + ->read(from_parquet(path(self::PAGINATION . '/partitioned/**/*.parquet'), filesystem: $filesystem)) + ->filter(ref('date')->equals(lit('2024-12-01'))) + ->fetch(); + + static::assertCount(2000, $rows); + static::assertSame( + [ + self::PAGINATION . '/partitioned/date=2024-01-01/01_1000.parquet' => 1, + self::PAGINATION . '/partitioned/date=2024-12-01/04_2000.parquet' => 1, + ], + ParquetFilesContext::opensPerFile($filesystem), + ); + static::assertSame(2, $filesystem->closedStreams()); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php index abbb122a23..394987482b 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php @@ -20,6 +20,9 @@ use Flow\Parquet\Option; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; +use Flow\Parquet\ParquetFile\Schema as ParquetSchema; +use Flow\Parquet\ParquetFile\Schema\FlatColumn; +use Flow\Parquet\Writer; use Flow\Types\Value\Json; use Flow\Types\Value\Uuid as FlowUuid; use Generator; @@ -27,6 +30,7 @@ use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Ramsey\Uuid\Uuid; +use function array_column; use function array_keys; use function array_map; use function extension_loaded; @@ -97,8 +101,8 @@ public function test_writing_and_reading_into_parquet(): void public function test_writing_and_reading_with_explicit_arrow_engine(): void { - if (!extension_loaded('arrow')) { - static::markTestSkipped('arrow extension is not loaded'); + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + static::markTestSkipped('neither flow_php nor arrow is loaded'); } $memory = memory_filesystem(); @@ -453,7 +457,12 @@ public function test_a_given_engine_is_honoured_with_flow_php_loaded(): void data_frame() ->read(from_rows(array_to_rows([['name' => "\xff\xfe"]], schema(str_schema('name'))))) - ->write(to_parquet($path, filesystem: $memory, engine: new PhpParquetEngine())) + ->write(to_parquet( + $path, + options: (new Options())->set(Option::VALIDATE_DATA, false), + engine: new PhpParquetEngine(), + filesystem: $memory, + )) ->run(); static::assertSame( @@ -465,6 +474,62 @@ public function test_a_given_engine_is_honoured_with_flow_php_loaded(): void ); } + /** + * @return Generator + */ + public static function reading_engines(): Generator + { + yield 'default engine' => [null]; + yield 'php engine' => [new PhpParquetEngine()]; + } + + #[DataProvider('reading_engines')] + public function test_a_column_outside_the_projection_never_needs_a_flow_type(?ParquetEngine $engine): void + { + static::assertSame( + [['id' => 1], ['id' => 2]], + data_frame() + ->read(from_parquet(__DIR__ . '/Fixtures/EdgeCases/interval.parquet', ['id'], engine: $engine)) + ->fetch() + ->toArray(), + ); + } + + #[DataProvider('reading_engines')] + public function test_an_unsigned_integer_reads_as_itself(?ParquetEngine $engine): void + { + static::assertSame( + [4_000_000_000, 1], + array_column( + data_frame() + ->read(from_parquet(__DIR__ . '/Fixtures/EdgeCases/unsigned.parquet', ['u32'], engine: $engine)) + ->fetch() + ->toArray(), + 'u32', + ), + ); + } + + #[DataProvider('reading_engines')] + public function test_an_enum_column_reads_as_strings(?ParquetEngine $engine): void + { + $memory = memory_filesystem(); + $path = path('memory://var/enum.parquet'); + Writer::php()->writeStream($memory->writeTo($path), ParquetSchema::with(FlatColumn::enum('color')), [ + ['color' => 'RED'], + ['color' => null], + ['color' => 'GREEN'], + ]); + + static::assertSame( + [['color' => 'RED'], ['color' => null], ['color' => 'GREEN']], + data_frame() + ->read(from_parquet($path, engine: $engine, filesystem: $memory)) + ->fetch() + ->toArray(), + ); + } + public function test_transformation_loader_writes_all_batches_to_parquet(): void { data_frame() @@ -579,8 +644,8 @@ public function test_a_path_only_partition_column_is_left_out_of_an_inferred_fil public function test_partitions_written_with_an_explicit_arrow_engine_each_get_their_own_file(): void { - if (!extension_loaded('arrow')) { - static::markTestSkipped('arrow extension is not loaded'); + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + static::markTestSkipped('neither flow_php nor arrow is loaded'); } $memory = memory_filesystem(); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php index a362d44206..6e3a6623a0 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php @@ -27,7 +27,7 @@ public function test_sink_writes_through_the_engine(): void { $filesystem = memory_filesystem(); $schema = schema(int_schema('id')); - $sink = (new EngineParquetOpener(new PhpParquetEngine()))->sink( + $sink = (new EngineParquetOpener(new PhpParquetEngine(), Options::default()))->sink( $filesystem->writeTo(path('memory://out.parquet')), (new SchemaConverter())->toParquet($schema), Compressions::SNAPPY, @@ -49,7 +49,7 @@ public function test_source_reads_the_file_through_its_parquet_file(): void static::assertEquals( new EngineParquetOpenSource($file->file), - (new EngineParquetOpener(new PhpParquetEngine()))->source($file), + (new EngineParquetOpener(new PhpParquetEngine(), Options::default()))->source($file), ); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php index 2179f93136..219174be8f 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php @@ -10,8 +10,7 @@ use Flow\ETL\Column\Php\ScalarColumn; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\FlowTestCase; -use Flow\Filesystem\Exception\RuntimeException; -use Flow\Filesystem\Tests\Double\FailingReadSourceStream; +use Flow\Parquet\Engine\Native\NativeParquetFile; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\TestWith; @@ -40,13 +39,9 @@ public function test_offset_and_limit_cross_row_groups(?int $offset, ?int $limit $read = []; - foreach ((new NativeParquetOpenSource($filesystem->readFrom(path('memory://groups.parquet'))))->batches( - schema(int_schema('id')), - 3, - $offset, - $limit, - new DefaultBackend(), - ) as $rows) { + foreach ((new NativeParquetOpenSource(new NativeParquetFile($filesystem->readFrom(path( + 'memory://groups.parquet', + )))))->batches(schema(int_schema('id')), 3, $offset, $limit, new DefaultBackend()) as $rows) { static::assertLessThanOrEqual(3, $rows->count()); $read = [...$read, ...$rows->column('id')->values()]; } @@ -58,7 +53,9 @@ public function test_columns_are_adopted_by_the_backend(): void { $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - $source = new NativeParquetOpenSource($filesystem->readFrom(path('memory://groups.parquet'))); + $source = new NativeParquetOpenSource(new NativeParquetFile($filesystem->readFrom(path( + 'memory://groups.parquet', + )))); $names = []; @@ -77,7 +74,9 @@ public function test_a_second_batches_call_closes_the_first_reader(): void { $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - $source = new NativeParquetOpenSource($filesystem->readFrom(path('memory://groups.parquet'))); + $source = new NativeParquetOpenSource(new NativeParquetFile($filesystem->readFrom(path( + 'memory://groups.parquet', + )))); $first = $source->batches(schema(int_schema('id')), 3, null, null, new DefaultBackend()); static::assertSame([0, 1, 2], $first->current()->column('id')->values()); @@ -93,27 +92,14 @@ public function test_a_second_batches_call_closes_the_first_reader(): void static::assertSame(range(0, 9), $second); } - public function test_an_exception_the_stream_throws_surfaces_as_itself(): void - { - $filesystem = memory_filesystem(); - ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Reading "memory://groups.parquet" failed'); - - (new NativeParquetOpenSource(new FailingReadSourceStream($filesystem->readFrom(path( - 'memory://groups.parquet', - ))))) - ->batches(schema(int_schema('id')), 3, null, null, new DefaultBackend()) - ->current(); - } - public function test_close_before_batches_is_harmless(): void { $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - (new NativeParquetOpenSource($filesystem->readFrom(path('memory://groups.parquet'))))->close(); + (new NativeParquetOpenSource(new NativeParquetFile($filesystem->readFrom(path( + 'memory://groups.parquet', + )))))->close(); $this->expectNotToPerformAssertions(); } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php index c05256fd36..7f3bc14734 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php @@ -10,7 +10,9 @@ use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetSourceFileContext; use Flow\ETL\Tests\FlowTestCase; +use Flow\Filesystem\Exception\RuntimeException; use Flow\Filesystem\Local\NativeLocalFilesystem; +use Flow\Filesystem\Tests\Double\FailingReadSourceStream; use Flow\Parquet\Options; use Flow\Parquet\ParquetFile\Compressions; use PHPUnit\Framework\Attributes\RequiresPhpExtension; @@ -28,7 +30,7 @@ public function test_sink_writes_through_flow_php(): void { $filesystem = memory_filesystem(); $schema = schema(int_schema('id')); - $sink = (new NativeParquetOpener())->sink( + $sink = (new NativeParquetOpener(Options::default()))->sink( $filesystem->writeTo(path('memory://out.parquet')), (new SchemaConverter())->toParquet($schema), Compressions::ZSTD, @@ -44,10 +46,24 @@ public function test_sink_writes_through_flow_php(): void ); } - public function test_source_reads_the_stream_the_file_holds(): void + public function test_source_reads_the_native_file_the_file_was_opened_with(): void { - $file = ParquetSourceFileContext::over(new NativeLocalFilesystem()); + $opener = new NativeParquetOpener(Options::default()); + $file = ParquetSourceFileContext::over(new NativeLocalFilesystem(), opener: $opener); - static::assertEquals(new NativeParquetOpenSource($file->stream), (new NativeParquetOpener())->source($file)); + static::assertEquals(new NativeParquetOpenSource($file->file->reader()->file()), $opener->source($file)); + } + + public function test_an_exception_the_stream_throws_while_opening_surfaces_as_itself(): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Reading "memory://groups.parquet" failed'); + + (new NativeParquetOpener(Options::default()))->file(new FailingReadSourceStream($filesystem->readFrom(path( + 'memory://groups.parquet', + )))); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php index ad6b9fce6b..7ef2b88d13 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php @@ -22,6 +22,7 @@ use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; +use function gc_collect_cycles; final class ParquetExtractorTest extends FlowTestCase { @@ -95,6 +96,11 @@ public function test_statistics_are_computed_at_most_once(): void static::assertSame($extractor->statistics(), $extractor->statistics()); static::assertSame(1, $filesystem->readFromCalls); + static::assertSame(0, $filesystem->closedStreams()); + + unset($extractor); + gc_collect_cycles(); + static::assertSame(1, $filesystem->closedStreams()); } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php index 8c59438b8b..c65f15721f 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php @@ -7,34 +7,119 @@ use Flow\ETL\Adapter\Parquet\EngineParquetOpener; use Flow\ETL\Adapter\Parquet\NativeParquetOpener; use Flow\ETL\Adapter\Parquet\ParquetOpeners; +use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetSourceFileContext; use Flow\ETL\Tests\FlowTestCase; +use Flow\Filesystem\Stream\NativeLocalSourceStream; +use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\AdaptiveParquetEngine; +use Flow\Parquet\Engine\ArrowParquetEngine; +use Flow\Parquet\Engine\NativeParquetFileReader; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\PhpParquetFileReader; +use Flow\Parquet\Options; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use function extension_loaded; final class ParquetOpenersTest extends FlowTestCase { - public function test_a_given_engine_is_always_honoured(): void + public function test_a_php_engine_is_always_honoured(): void { $engine = new PhpParquetEngine(); - static::assertEquals(new EngineParquetOpener($engine), ParquetOpeners::select($engine)); + static::assertEquals( + new EngineParquetOpener($engine, Options::default()), + ParquetOpeners::select($engine, ByteOrder::LITTLE_ENDIAN, Options::default()), + ); } #[RequiresPhpExtension('flow_php')] - public function test_without_an_engine_flow_php_opens_the_files(): void + public function test_with_flow_php_an_adaptive_engine_reads_through_flow_php(): void { - static::assertInstanceOf(NativeParquetOpener::class, ParquetOpeners::select(null)); + static::assertEquals( + new NativeParquetOpener(Options::default()), + ParquetOpeners::select(new AdaptiveParquetEngine(), ByteOrder::LITTLE_ENDIAN, Options::default()), + ); } - public function test_without_an_engine_and_flow_php_the_adaptive_engine_opens_the_files(): void + #[RequiresPhpExtension('flow_php')] + public function test_with_flow_php_an_arrow_engine_reads_through_flow_php(): void + { + static::assertEquals( + new NativeParquetOpener(Options::default()), + ParquetOpeners::select(new ArrowParquetEngine(), ByteOrder::LITTLE_ENDIAN, Options::default()), + ); + } + + #[RequiresPhpExtension('flow_php')] + public function test_with_flow_php_no_engine_reads_through_flow_php(): void + { + static::assertEquals( + new NativeParquetOpener(Options::default()), + ParquetOpeners::select(null, ByteOrder::LITTLE_ENDIAN, Options::default()), + ); + } + + public function test_without_flow_php_an_adaptive_engine_is_honoured(): void { if (extension_loaded('flow_php')) { static::markTestSkipped('flow_php is loaded'); } - static::assertEquals(new EngineParquetOpener(new AdaptiveParquetEngine()), ParquetOpeners::select(null)); + $engine = new AdaptiveParquetEngine(); + + static::assertEquals( + new EngineParquetOpener($engine, Options::default()), + ParquetOpeners::select($engine, ByteOrder::LITTLE_ENDIAN, Options::default()), + ); + } + + #[RequiresPhpExtension('arrow')] + public function test_without_flow_php_an_arrow_engine_is_honoured(): void + { + if (extension_loaded('flow_php')) { + static::markTestSkipped('flow_php is loaded'); + } + + $engine = new ArrowParquetEngine(); + + static::assertEquals( + new EngineParquetOpener($engine, Options::default()), + ParquetOpeners::select($engine, ByteOrder::LITTLE_ENDIAN, Options::default()), + ); + } + + public function test_without_flow_php_no_engine_opens_through_an_adaptive_engine(): void + { + if (extension_loaded('flow_php')) { + static::markTestSkipped('flow_php is loaded'); + } + + static::assertEquals( + new EngineParquetOpener( + new AdaptiveParquetEngine(ByteOrder::BIG_ENDIAN, Options::default()), + Options::default(), + ), + ParquetOpeners::select(null, ByteOrder::BIG_ENDIAN, Options::default()), + ); + } + + public function test_an_engine_opener_opens_files_with_its_engine_reader(): void + { + $file = (new EngineParquetOpener(new PhpParquetEngine(), Options::default()))->file( + NativeLocalSourceStream::open(ParquetSourceFileContext::fixture()), + ); + + static::assertInstanceOf(PhpParquetFileReader::class, $file->reader()); + } + + #[RequiresPhpExtension('flow_php')] + public function test_a_native_opener_opens_files_with_a_native_reader(): void + { + $file = (new NativeParquetOpener(Options::default()))->file( + NativeLocalSourceStream::open(ParquetSourceFileContext::fixture()), + ); + + static::assertInstanceOf(NativeParquetFileReader::class, $file->reader()); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php index e38c2a4173..27e5e5a2ec 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php @@ -12,6 +12,7 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Options; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -34,7 +35,7 @@ public function test_open_hands_the_file_to_the_opener(): void static::assertEquals( new EngineParquetOpenSource($file->file), - $file->open(new EngineParquetOpener(new PhpParquetEngine())), + $file->open(new EngineParquetOpener(new PhpParquetEngine(), Options::default())), ); } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetToFlowSchemaTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetToFlowSchemaTest.php index b5c5bb3856..51d51ae828 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetToFlowSchemaTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetToFlowSchemaTest.php @@ -54,6 +54,7 @@ public function test_converting_flat_fields_to_flow_schema(): void FlatColumn::dateTime('datetime'), FlatColumn::uuid('uuid'), FlatColumn::json('json'), + FlatColumn::enum('enum'), )); static::assertEquals( @@ -70,6 +71,7 @@ public function test_converting_flat_fields_to_flow_schema(): void datetime_schema('datetime', true), uuid_schema('uuid', true), json_schema('json', true), + str_schema('enum', true), ), $flowSchema, ); @@ -104,6 +106,7 @@ public function test_converting_struct_to_flow_schema(): void FlatColumn::uuid('uuid'), FlatColumn::string('name'), FlatColumn::boolean('active'), + FlatColumn::enum('color'), ]))); static::assertEquals( @@ -113,6 +116,7 @@ public function test_converting_struct_to_flow_schema(): void 'uuid' => type_optional(type_uuid()), 'name' => type_optional(type_string()), 'active' => type_optional(type_boolean()), + 'color' => type_optional(type_string()), ]), true, )), diff --git a/src/extension/arrow-ext/composer.json b/src/extension/arrow-ext/composer.json index 324b979249..9e21366e6a 100644 --- a/src/extension/arrow-ext/composer.json +++ b/src/extension/arrow-ext/composer.json @@ -4,6 +4,7 @@ "description": "Apache Arrow PHP extension powered by Rust", "keywords": ["arrow", "parquet", "extension", "rust", "native"], "license": "MIT", + "abandoned": "flow-php/flow-php-ext", "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, diff --git a/src/extension/flow-php-ext/composer.json b/src/extension/flow-php-ext/composer.json index ce0ee0708a..d6b9c98c96 100644 --- a/src/extension/flow-php-ext/composer.json +++ b/src/extension/flow-php-ext/composer.json @@ -11,6 +11,7 @@ "psr-4": { "Flow\\ETL\\Adapter\\CSV\\": "php/Flow/ETL/Adapter/CSV/", "Flow\\ETL\\Adapter\\Parquet\\": "php/Flow/ETL/Adapter/Parquet/", + "Flow\\Parquet\\Engine\\Native\\": "php/Flow/Parquet/Engine/Native/", "Flow\\Floe\\": "php/Flow/Floe/" } }, diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php index 49abacc66d..8bcd6f64cc 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php @@ -6,7 +6,7 @@ use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\Filesystem\SourceStream; +use Flow\Parquet\Engine\Native\NativeParquetFile; use RuntimeException; use function extension_loaded; @@ -18,13 +18,14 @@ final class NativeParquetReader { /** + * @param NativeParquetFile $file the open file, whose footer plans the read * @param Schema $schema the columns to read, in file order or a projection; every definition's type must store * what the file's column reads as * @param int<1, max> $batchSize * * @throws \Flow\ETL\Exception\InvalidArgumentException for a negative $offset or $limit */ - public function __construct(SourceStream $stream, Schema $schema, int $batchSize, ?int $offset, ?int $limit) + public function __construct(NativeParquetFile $file, Schema $schema, int $batchSize, ?int $offset, ?int $limit) { throw new RuntimeException('flow_php extension is not loaded'); } diff --git a/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetColumnsReader.php b/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetColumnsReader.php new file mode 100644 index 0000000000..1f2689aaa8 --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetColumnsReader.php @@ -0,0 +1,40 @@ + $columns root names or struct paths + * @param int<1, max> $batchSize + */ + public function __construct(NativeParquetFile $file, array $columns, int $batchSize, ?int $offset, ?int $limit) + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function close(): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * At most $batchSize rows, keyed by $columns, null after the last. + * + * @return null|array> + */ + public function next(): ?array + { + throw new RuntimeException('flow_php extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetFile.php b/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetFile.php new file mode 100644 index 0000000000..95be638f68 --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetFile.php @@ -0,0 +1,64 @@ + + */ + public function schema(): array + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * The whole footer, decoded on the first call. + */ + public function thrift(): FileMetaData + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * Σ row group total_byte_size (uncompressed). + */ + public function totalByteSize(): int + { + throw new RuntimeException('flow_php extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetRowsWriter.php b/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetRowsWriter.php new file mode 100644 index 0000000000..86712e39bd --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetRowsWriter.php @@ -0,0 +1,56 @@ + $schema Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension() + * @param array $options Flow\Parquet\Engine\Arrow\OptionsConverter::toExtension() + * @param int $batchSize rows per written batch; below 1 is refused + */ + public function __construct( + DestinationStream $stream, + array $schema, + string $compression, + array $options, + int $batchSize, + ) { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * Buffered rows, the footer, then the stream closed. + */ + public function close(): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * @param array $row a writer column the row lacks is null + */ + public function writeRow(array $row): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * @param list> $rows + */ + public function writeRows(array $rows): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/src/ctx.rs b/src/extension/flow-php-ext/src/ctx.rs index fa004b19f2..531e002110 100644 --- a/src/extension/flow-php-ext/src/ctx.rs +++ b/src/extension/flow-php-ext/src/ctx.rs @@ -17,6 +17,7 @@ use ext_php_rs::zend::{ClassEntry, ExecutorGlobals, Function}; use crate::exception::ext_exception; use crate::globals::with_ctx; use crate::plan::TypePlan; +use crate::thrift::Specs; /// PHP array-key coercion (`_zend_handle_numeric_str`): parse + canonical /// re-format equality rejects "+5", "-0", leading zeros and whitespace exactly @@ -404,6 +405,8 @@ pub struct Ctx { plans: HashMap, Rc>, /// `plans` by Type object handle; each entry holds its object, so the handle is not reused while cached. type_plans: HashMap)>, + /// The `$_TSPEC`s reachable from a root thrift class, by that class. + thrift_specs: HashMap>, } /// Type objects `type_plans` holds before it starts over. @@ -497,6 +500,17 @@ pub fn store_type_plan(type_zv: &Zval, plan: &Rc) -> Result<(), PhpExc Ok(()) } +pub fn thrift_specs(class: &str) -> Result>, PhpException> { + with_ctx(|ctx| Ok(ctx.thrift_specs.get(class).cloned())) +} + +pub fn store_thrift_specs(class: &str, specs: &Rc) -> Result<(), PhpException> { + with_ctx(|ctx| { + ctx.thrift_specs.insert(class.to_string(), Rc::clone(specs)); + Ok(()) + }) +} + /// A cached handle: read inside the context, resolved outside it on a miss, then stored. fn cached( read: impl FnOnce(&Ctx) -> Option, diff --git a/src/extension/flow-php-ext/src/kind_builder.rs b/src/extension/flow-php-ext/src/kind_builder.rs index 38d3a3af6e..e97800d169 100644 --- a/src/extension/flow-php-ext/src/kind_builder.rs +++ b/src/extension/flow-php-ext/src/kind_builder.rs @@ -218,6 +218,45 @@ impl KindBuilder { validity.append_non_null(); } + /// Drops every row past the first `len`: a row refused half-appended leaves no trace. + pub fn truncate(&mut self, len: usize) { + match self { + KindBuilder::Null { len: rows } => *rows = len, + KindBuilder::Fixed { width, values, validity } => { + values.truncate(len * *width); + validity.truncate(len); + } + KindBuilder::Boolean { values, validity } => { + values.truncate(len); + validity.truncate(len); + } + KindBuilder::Bytes { offsets, data, validity } => { + offsets.truncate(len + 1); + data.truncate(offsets[len] as usize); + validity.truncate(len); + } + KindBuilder::List { offsets, validity, element } => { + offsets.truncate(len + 1); + element.truncate(offsets[len] as usize); + validity.truncate(len); + } + KindBuilder::Map { offsets, validity, keys, values } => { + offsets.truncate(len + 1); + keys.truncate(offsets[len] as usize); + values.truncate(offsets[len] as usize); + validity.truncate(len); + } + KindBuilder::Struct { len: rows, validity, children } => { + *rows = len; + validity.truncate(len); + + for child in children { + child.truncate(len); + } + } + } + } + /// Row `i` of `array`, whose data type is `data_type(kind)`. pub fn append_from(&mut self, array: &dyn Array, kind: &Kind, i: usize) -> Result<(), OffsetOverflow> { if matches!(kind, Kind::Null) || array.is_null(i) { @@ -322,3 +361,66 @@ impl KindBuilder { builder.build() } } + +#[cfg(test)] +mod tests { + use arrow_array::cast::AsArray; + use arrow_array::types::Int64Type; + use arrow_array::{make_array, Array}; + use flow_batch_frame::kind::{Field, Kind}; + + use super::KindBuilder; + + fn field(kind: Kind) -> Box { + Box::new(Field { + name: "item".into(), + kind, + optional: true, + }) + } + + #[test] + fn truncate_drops_the_rows_past_the_length_in_every_nested_builder() { + let kind = Kind::Struct(vec![ + Field { + name: "id".into(), + kind: Kind::Int64, + optional: true, + }, + Field { + name: "tags".into(), + kind: Kind::List(field(Kind::Bytes)), + optional: true, + }, + Field { + name: "flags".into(), + kind: Kind::Map(field(Kind::Bytes), field(Kind::Boolean)), + optional: true, + }, + ]); + let mut builder = KindBuilder::new(&kind); + let mut row = |id: i64, tag: &[u8]| { + let children = builder.struct_children(); + children[0].append_fixed(&id.to_le_bytes()); + children[1].list_element().append_bytes(tag).ok(); + children[1].end_entries().ok(); + let (keys, values) = children[2].map_entries(); + keys.append_bytes(tag).ok(); + values.append_bool(true); + children[2].end_entries().ok(); + builder.end_struct(); + }; + + row(1, b"kept"); + row(2, b"dropped"); + builder.truncate(1); + let array = make_array(builder.finish(&kind).unwrap()); + let structure = array.as_struct(); + + assert_eq!(array.len(), 1); + assert_eq!(structure.column(0).as_primitive::().values().to_vec(), vec![1]); + assert_eq!(structure.column(1).as_list::().values().as_binary::().value(0), b"kept"); + assert_eq!(structure.column(1).as_list::().values().len(), 1); + assert_eq!(structure.column(2).as_map().keys().len(), 1); + } +} diff --git a/src/extension/flow-php-ext/src/lib.rs b/src/extension/flow-php-ext/src/lib.rs index 60fc6baa32..ae629e0b42 100644 --- a/src/extension/flow-php-ext/src/lib.rs +++ b/src/extension/flow-php-ext/src/lib.rs @@ -15,6 +15,7 @@ mod parquet; mod physical; mod plan; mod render; +mod thrift; mod uuid_check; mod values; @@ -194,4 +195,7 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { .class::() .class::() .class::() + .class::() + .class::() + .class::() } diff --git a/src/extension/flow-php-ext/src/parquet/canonical.rs b/src/extension/flow-php-ext/src/parquet/canonical.rs index f2f14172f9..625cdb5b00 100644 --- a/src/extension/flow-php-ext/src/parquet/canonical.rs +++ b/src/extension/flow-php-ext/src/parquet/canonical.rs @@ -12,8 +12,8 @@ use arrow_array::types::{ TimestampSecondType, UInt16Type, UInt32Type, UInt64Type, UInt8Type, }; use arrow_array::{ - make_array, Array, ArrayRef, ArrowPrimitiveType, BinaryArray, Float64Array, GenericByteArray, ListArray, MapArray, - PrimitiveArray, StructArray, + make_array, Array, ArrayRef, ArrowPrimitiveType, BinaryArray, FixedSizeBinaryArray, Float64Array, GenericByteArray, + ListArray, MapArray, PrimitiveArray, StructArray, }; use arrow_buffer::{OffsetBuffer, ScalarBuffer}; use arrow_schema::{DataType, Field, FieldRef, Fields, TimeUnit}; @@ -52,9 +52,12 @@ pub fn canonical_type(field: &Field) -> Result { fn canonical_data_type(data_type: &DataType) -> Result { Ok(match data_type { - DataType::Boolean | DataType::Int64 | DataType::Float64 | DataType::Date32 | DataType::FixedSizeBinary(16) => { - data_type.clone() - } + DataType::Null + | DataType::Boolean + | DataType::Int64 + | DataType::Float64 + | DataType::Date32 + | DataType::FixedSizeBinary(16) => data_type.clone(), DataType::Int8 | DataType::Int16 | DataType::Int32 @@ -63,7 +66,11 @@ fn canonical_data_type(data_type: &DataType) -> Result { | DataType::UInt32 | DataType::UInt64 => DataType::Int64, DataType::Float32 | DataType::Decimal128(_, _) | DataType::Decimal256(_, _) => DataType::Float64, - DataType::Utf8 | DataType::Binary | DataType::LargeUtf8 | DataType::LargeBinary => DataType::Binary, + DataType::Utf8 + | DataType::Binary + | DataType::LargeUtf8 + | DataType::LargeBinary + | DataType::FixedSizeBinary(_) => DataType::Binary, DataType::Timestamp(_, _) => timestamp(), DataType::Time64(TimeUnit::Microsecond | TimeUnit::Nanosecond) | DataType::Time32(TimeUnit::Millisecond | TimeUnit::Second) => DataType::Duration(TimeUnit::Microsecond), @@ -187,11 +194,40 @@ fn large_binary(array: &ArrayRef) -> Result { ))) } +/// Fixed-size values as Binary over the same value buffer: offsets `n·i`. +fn fixed_binary(array: &ArrayRef) -> Result { + let fixed = array.as_fixed_size_binary(); + let size = i32::try_from(fixed.value_size()).map_err(|_| Error::Overflow { + column: String::new(), + row: 0, + })?; + let offsets = (0..=fixed.len()) + .map(|row| { + i32::try_from(row) + .ok() + .and_then(|row| row.checked_mul(size)) + .ok_or(Error::Overflow { + column: String::new(), + row: row.saturating_sub(1), + }) + }) + .collect::, _>>()?; + + Ok(Arc::new(BinaryArray::new( + OffsetBuffer::new(ScalarBuffer::from(offsets)), + fixed.values().clone(), + fixed.nulls().cloned(), + ))) +} + fn cast(array: &ArrayRef) -> Result { Ok(match array.data_type() { - DataType::Boolean | DataType::Int64 | DataType::Float64 | DataType::Date32 | DataType::FixedSizeBinary(16) => { - Arc::clone(array) - } + DataType::Null + | DataType::Boolean + | DataType::Int64 + | DataType::Float64 + | DataType::Date32 + | DataType::FixedSizeBinary(16) => Arc::clone(array), DataType::Timestamp(TimeUnit::Microsecond, Some(zone)) if zone.as_ref() == UTC => Arc::clone(array), DataType::Int8 => widened::(array), DataType::Int16 => widened::(array), @@ -203,6 +239,7 @@ fn cast(array: &ArrayRef) -> Result { DataType::Float32 => Arc::new(array.as_primitive::().unary::<_, Float64Type>(f64::from)), DataType::Utf8 | DataType::Binary => retagged(array, DataType::Binary), DataType::LargeUtf8 | DataType::LargeBinary => large_binary(array)?, + DataType::FixedSizeBinary(_) => fixed_binary(array)?, DataType::Timestamp(TimeUnit::Microsecond, _) => retagged(array, timestamp()), DataType::Timestamp(TimeUnit::Millisecond, _) => { micros::(array, |ms| ms.checked_mul(1_000))? @@ -308,9 +345,48 @@ pub fn to_parquet(array: &ArrayRef, target: &DataType) -> Result utf8(array)?, + (DataType::Int64, DataType::Int8) => Arc::new(narrowed_int::(array)?), + (DataType::Int64, DataType::Int16) => Arc::new(narrowed_int::(array)?), + (DataType::Int64, DataType::Int32) => Arc::new(narrowed_int::(array)?), + (DataType::Int64, DataType::UInt8) => Arc::new(narrowed_int::(array)?), + (DataType::Int64, DataType::UInt16) => Arc::new(narrowed_int::(array)?), + (DataType::Int64, DataType::UInt32) => Arc::new(narrowed_int::(array)?), + (DataType::Int64, DataType::UInt64) => Arc::new(narrowed_int::(array)?), + (DataType::Float64, DataType::Float32) => { + Arc::new(array.as_primitive::().unary::<_, Float32Type>(|value| value as f32)) + } + (DataType::Float64, DataType::Decimal128(precision, scale)) => Arc::new( + checked_values::(array, |value| decimal_unscaled(value, *precision, *scale))? + .with_precision_and_scale(*precision, *scale)?, + ), + (DataType::Binary, DataType::FixedSizeBinary(size)) => fixed_size(array, *size)?, (DataType::Duration(TimeUnit::Microsecond), DataType::Time64(TimeUnit::Microsecond)) => { retagged(array, target.clone()) } + (DataType::Duration(TimeUnit::Microsecond), DataType::Time32(TimeUnit::Millisecond)) => Arc::new( + checked::(array, |us| { + i32::try_from(us.div_euclid(1_000)).ok() + })?, + ), + (DataType::Duration(TimeUnit::Microsecond), DataType::Time64(TimeUnit::Nanosecond)) => Arc::new( + checked::(array, |us| us.checked_mul(1_000))?, + ), + (DataType::Timestamp(TimeUnit::Microsecond, Some(zone)), DataType::Timestamp(TimeUnit::Millisecond, to)) + if zone.as_ref() == UTC => + { + Arc::new( + checked::(array, |us| Some(us.div_euclid(1_000)))? + .with_timezone_opt(to.clone()), + ) + } + (DataType::Timestamp(TimeUnit::Microsecond, Some(zone)), DataType::Timestamp(TimeUnit::Nanosecond, to)) + if zone.as_ref() == UTC => + { + Arc::new( + checked::(array, |us| us.checked_mul(1_000))? + .with_timezone_opt(to.clone()), + ) + } (DataType::Timestamp(TimeUnit::Microsecond, Some(zone)), DataType::Timestamp(TimeUnit::Microsecond, _)) if zone.as_ref() == UTC => { @@ -370,6 +446,108 @@ pub fn to_parquet(array: &ArrayRef, target: &DataType) -> Result(array: &ArrayRef) -> Result, Error> +where + T::Native: TryFrom, +{ + checked::(array, |value| T::Native::try_from(value).ok()) +} + +/// Every valid value through `f`, which refuses a row with the error it returns. +fn checked_values( + array: &ArrayRef, + f: impl Fn(T::Native) -> Result, +) -> Result, Error> { + let input = array.as_primitive::(); + let mut values = Vec::with_capacity(input.len()); + + for (row, value) in input.values().iter().enumerate() { + values.push(if input.is_null(row) { + O::Native::default() + } else { + f(*value).map_err(|error| error.at_row(|_| row))? + }); + } + + Ok(PrimitiveArray::new(ScalarBuffer::from(values), input.nulls().cloned())) +} + +/// `Flow\Parquet\Binary\decimal_unscaled()`: the float's shortest round-trip digits (Rust `{}` prints the digits PHP's +/// `var_export()` does, never an exponent), rounded half away from zero at `scale`; more than `precision` digits +/// overflow. +fn decimal_unscaled(value: f64, precision: u8, scale: i8) -> Result { + if !value.is_finite() { + return Err(Error::Value { + column: String::new(), + row: 0, + expected: "a finite number", + got: if value.is_nan() { + "NAN".to_string() + } else if value > 0.0 { + "INF".to_string() + } else { + "-INF".to_string() + }, + }); + } + + let overflow = || Error::Overflow { + column: String::new(), + row: 0, + }; + let text = format!("{}", value.abs()); + let (integer, fraction) = text.split_once('.').unwrap_or((&text, "")); + let scale = scale.max(0) as usize; + let kept = fraction.get(..scale.min(fraction.len())).unwrap_or(""); + let mut digits = format!("{integer}{kept}{}", "0".repeat(scale - kept.len())); + let round_up = fraction.as_bytes().get(scale).is_some_and(|digit| *digit >= b'5'); + digits = digits.trim_start_matches('0').to_string(); + + if digits.len() > usize::from(precision) || digits.len() > 38 { + return Err(overflow()); + } + + let mut unscaled = if digits.is_empty() { 0 } else { digits.parse::().map_err(|_| overflow())? }; + + if round_up { + unscaled += 1; + + if unscaled.to_string().len() > usize::from(precision) { + return Err(overflow()); + } + } + + Ok(if value.is_sign_negative() { -unscaled } else { unscaled }) +} + +/// Binary values of exactly `size` bytes as fixed-size binary; the first of another length refuses its row. +fn fixed_size(array: &ArrayRef, size: i32) -> Result { + let binary = array.as_binary::(); + let width = size as usize; + let mut values = vec![0u8; binary.len() * width]; + + for row in 0..binary.len() { + if binary.is_null(row) { + continue; + } + + let value = binary.value(row); + + if value.len() != width { + return Err(Error::Length { + column: String::new(), + row, + expected: width, + }); + } + + values[row * width..(row + 1) * width].copy_from_slice(value); + } + + Ok(Arc::new(FixedSizeBinaryArray::new(size, values.into(), binary.nulls().cloned()))) +} + /// Binary as Utf8 over the same buffers once every value is valid UTF-8; else the first row that is not. fn utf8(array: &ArrayRef) -> Result { match array.to_data().into_builder().data_type(DataType::Utf8).build() { @@ -394,7 +572,9 @@ mod tests { use arrow_array::builder::{Int32Builder, ListBuilder, MapBuilder, StringBuilder}; use arrow_array::cast::AsArray; use arrow_array::types::{ - Date32Type, DurationMicrosecondType, Float64Type, Int64Type, Time64MicrosecondType, TimestampMicrosecondType, + Date32Type, Decimal128Type, DurationMicrosecondType, Float32Type, Float64Type, Int64Type, Int8Type, + Time32MillisecondType, Time64MicrosecondType, Time64NanosecondType, TimestampMicrosecondType, + TimestampMillisecondType, TimestampNanosecondType, UInt64Type, }; use arrow_array::{ Array, ArrayRef, BinaryArray, BooleanArray, Date32Array, Date64Array, Decimal128Array, Decimal256Array, @@ -673,17 +853,28 @@ mod tests { assert!(matches!(refusal(Arc::new(list)), Error::Overflow { row: 1, .. })); } + #[test] + fn a_list_of_nulls_is_kept() { + let list: ArrayRef = Arc::new(ListArray::new( + Arc::new(Field::new("element", DataType::Null, true)), + arrow_buffer::OffsetBuffer::new(vec![0, 0, 2].into()), + Arc::new(arrow_array::NullArray::new(2)), + None, + )); + let canonical = read(list); + + assert_eq!(canonical.as_list::().value_offsets(), &[0, 0, 2]); + assert_eq!(canonical.as_list::().values().data_type(), &DataType::Null); + } + #[test] fn unsupported_types_are_refused_naming_the_type() { - let field = Field::new("emptylist", DataType::List(Arc::new(Field::new("element", DataType::Null, true))), true); + let interval = DataType::Interval(arrow_schema::IntervalUnit::DayTime); + let field = Field::new("intervals", DataType::List(Arc::new(Field::new("element", interval, true))), true); assert!(matches!( canonical_type(&field), - Err(Error::Unsupported { column, parquet }) if column == "emptylist" && parquet == "Null" - )); - assert!(matches!( - canonical_type(&Field::new("f", DataType::FixedSizeBinary(8), true)), - Err(Error::Unsupported { .. }) + Err(Error::Unsupported { column, parquet }) if column == "intervals" && parquet == "Interval(DayTime)" )); assert!(matches!( refusal(Arc::new(arrow_array::DurationSecondArray::from(vec![1]))), @@ -691,6 +882,181 @@ mod tests { )); } + #[test] + fn fixed_size_binaries_of_another_size_than_16_are_binary() { + let array = FixedSizeBinaryArray::try_from_sparse_iter_with_size( + vec![Some(*b"abcd"), None, Some(*b"wxyz"), Some(*b"skip")].into_iter(), + 4, + ) + .unwrap() + .slice(0, 3); + let canonical = read(Arc::new(array)); + + assert_eq!( + canonical.as_binary::().iter().collect::>(), + vec![Some(&b"abcd"[..]), None, Some(&b"wxyz"[..])] + ); + } + + #[test] + fn to_parquet_narrows_integers_in_range() { + let array: ArrayRef = Arc::new(Int64Array::from(vec![Some(-128), None, Some(127)])); + + assert_eq!( + to_parquet(&array, &DataType::Int8).unwrap().as_primitive::().iter().collect::>(), + vec![Some(-128), None, Some(127)] + ); + + let unsigned: ArrayRef = Arc::new(Int64Array::from(vec![Some(4_000_000_000), Some(i64::MAX)])); + + assert_eq!( + to_parquet(&unsigned, &DataType::UInt64).unwrap().as_primitive::().values().to_vec(), + vec![4_000_000_000, i64::MAX as u64] + ); + + for target in [DataType::Int16, DataType::Int32, DataType::UInt8, DataType::UInt16, DataType::UInt32] { + assert_eq!(to_parquet(&array.slice(1, 1), &target).unwrap().data_type(), &target); + } + } + + #[test] + fn to_parquet_refuses_integers_out_of_the_target_range_at_their_row() { + let cases = [ + (DataType::Int8, vec![1, 128]), + (DataType::Int16, vec![1, -32_769]), + (DataType::Int32, vec![1, 2_147_483_648]), + (DataType::UInt8, vec![1, 256]), + (DataType::UInt16, vec![1, -1]), + (DataType::UInt32, vec![1, 4_294_967_296]), + (DataType::UInt64, vec![1, -1]), + ]; + + for (target, values) in cases { + let array: ArrayRef = Arc::new(Int64Array::from(values)); + + assert!(matches!(to_parquet(&array, &target), Err(Error::Overflow { row: 1, .. })), "{target}"); + } + } + + #[test] + fn to_parquet_narrows_floats() { + let array: ArrayRef = Arc::new(Float64Array::from(vec![Some(0.5), None])); + + assert_eq!( + to_parquet(&array, &DataType::Float32).unwrap().as_primitive::().iter().collect::>(), + vec![Some(0.5), None] + ); + } + + fn unscaled(values: Vec>, precision: u8, scale: i8) -> Result>, Error> { + let array: ArrayRef = Arc::new(Float64Array::from(values)); + + to_parquet(&array, &DataType::Decimal128(precision, scale)) + .map(|decimal| decimal.as_primitive::().iter().collect()) + } + + #[test] + fn to_parquet_writes_decimals_from_the_shortest_digits_half_away_from_zero() { + assert_eq!( + unscaled(vec![Some(123.45), Some(-0.125), Some(0.125), Some(0.1249), None, Some(-0.001)], 9, 2).unwrap(), + vec![Some(12_345), Some(-13), Some(13), Some(12), None, Some(0)] + ); + assert_eq!(unscaled(vec![Some(1e20)], 38, 2).unwrap(), vec![Some(10i128.pow(22))]); + assert_eq!(unscaled(vec![Some(0.1 + 0.2)], 20, 17).unwrap(), vec![Some(30_000_000_000_000_004)]); + assert_eq!(unscaled(vec![Some(-5.0)], 1, -1).unwrap(), vec![Some(-5)]); + } + + #[test] + fn to_parquet_refuses_decimals_beyond_their_precision() { + assert!(matches!(unscaled(vec![Some(1.0), Some(100.0)], 4, 2), Err(Error::Overflow { row: 1, .. }))); + assert!(matches!(unscaled(vec![Some(99.995)], 4, 2), Err(Error::Overflow { row: 0, .. }))); + assert!(matches!(unscaled(vec![Some(1e300)], 38, 0), Err(Error::Overflow { row: 0, .. }))); + } + + #[test] + fn to_parquet_refuses_decimals_that_are_not_finite() { + for (value, got) in [(f64::NAN, "NAN"), (f64::INFINITY, "INF"), (f64::NEG_INFINITY, "-INF")] { + assert!(matches!( + unscaled(vec![Some(1.0), Some(value)], 9, 2), + Err(Error::Value { row: 1, expected, got: text, .. }) if expected == "a finite number" && text == got + )); + } + } + + #[test] + fn to_parquet_writes_fixed_size_binaries_of_their_length() { + let array: ArrayRef = Arc::new(BinaryArray::from(vec![Some(&b"abcd"[..]), None])); + let fixed = to_parquet(&array, &DataType::FixedSizeBinary(4)).unwrap(); + + assert_eq!( + fixed.as_fixed_size_binary().iter().collect::>(), + vec![Some(&b"abcd"[..]), None] + ); + assert!(matches!( + to_parquet(&array, &DataType::FixedSizeBinary(16)), + Err(Error::Length { row: 0, expected: 16, .. }) + )); + } + + #[test] + fn to_parquet_writes_times_in_milliseconds_and_nanoseconds() { + let time: ArrayRef = Arc::new(DurationMicrosecondArray::from(vec![Some(1_999), Some(-1), None])); + + assert_eq!( + to_parquet(&time, &DataType::Time32(TimeUnit::Millisecond)) + .unwrap() + .as_primitive::() + .iter() + .collect::>(), + vec![Some(1), Some(-1), None] + ); + assert_eq!( + to_parquet(&time, &DataType::Time64(TimeUnit::Nanosecond)) + .unwrap() + .as_primitive::() + .iter() + .collect::>(), + vec![Some(1_999_000), Some(-1_000), None] + ); + + let long: ArrayRef = Arc::new(DurationMicrosecondArray::from(vec![0, i64::MAX])); + + assert!(matches!( + to_parquet(&long, &DataType::Time32(TimeUnit::Millisecond)), + Err(Error::Overflow { row: 1, .. }) + )); + assert!(matches!( + to_parquet(&long, &DataType::Time64(TimeUnit::Nanosecond)), + Err(Error::Overflow { row: 1, .. }) + )); + } + + #[test] + fn to_parquet_writes_timestamps_in_milliseconds_and_nanoseconds() { + let timestamp: ArrayRef = + Arc::new(TimestampMicrosecondArray::from(vec![Some(1_999), Some(-1), None]).with_timezone("UTC")); + let millis = to_parquet(×tamp, &DataType::Timestamp(TimeUnit::Millisecond, None)).unwrap(); + let nanos = to_parquet(×tamp, &DataType::Timestamp(TimeUnit::Nanosecond, Some("UTC".into()))).unwrap(); + + assert_eq!(millis.data_type(), &DataType::Timestamp(TimeUnit::Millisecond, None)); + assert_eq!( + millis.as_primitive::().iter().collect::>(), + vec![Some(1), Some(-1), None] + ); + assert_eq!(nanos.data_type(), &DataType::Timestamp(TimeUnit::Nanosecond, Some("UTC".into()))); + assert_eq!( + nanos.as_primitive::().iter().collect::>(), + vec![Some(1_999_000), Some(-1_000), None] + ); + + let far: ArrayRef = Arc::new(TimestampMicrosecondArray::from(vec![0, i64::MAX]).with_timezone("UTC")); + + assert!(matches!( + to_parquet(&far, &DataType::Timestamp(TimeUnit::Nanosecond, None)), + Err(Error::Overflow { row: 1, .. }) + )); + } + #[test] fn to_parquet_keeps_equal_types() { let array: ArrayRef = Arc::new(Int64Array::from(vec![1])); diff --git a/src/extension/flow-php-ext/src/parquet/cells.rs b/src/extension/flow-php-ext/src/parquet/cells.rs new file mode 100644 index 0000000000..f1e8c1fefd --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/cells.rs @@ -0,0 +1,683 @@ +//! The `Flow\Parquet` lib's per-cell values over the core's canonical arrays: what `PhpParquetEngine` returns for a +//! Parquet value on read, and what it accepts per target type on write. + +use arrow_array::cast::AsArray; +use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; +use arrow_array::{make_array, Array, ArrayRef}; +use arrow_schema::{DataType, Field}; +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::{ZendHashTable, ZendObject, Zval}; +use ext_php_rs::zend::{ClassEntry, Function}; +use flow_batch_frame::kind::{Field as KindField, Kind}; + +use crate::ctx::{ + call_handle_transparent, ce_method_ref, find_class, ht_for_each, ht_get, ht_insert, ht_insert_long, + read_property, zval_long, zval_str, +}; +use crate::exception::ext_exception; +use crate::kind_builder::KindBuilder; +use crate::parquet::error::Error; +use crate::values::{date_from_days, datetime_days, datetime_from_micros, datetime_micros, uuid_bytes, uuid_text}; + +const UUID: &str = "arrow.uuid"; + +fn is_uuid(field: &Field) -> bool { + field.extension_type_name() == Some(UUID) +} + +fn unsupported(data_type: &DataType) -> Error { + Error::Unsupported { + column: String::new(), + parquet: data_type.to_string(), + } +} + +fn collected(error: impl std::fmt::Debug) -> PhpException { + ext_exception(format!("flow_php failed to collect a Parquet value: {error:?}")) +} + +/// How a canonical array's values become PHP values, per `PhpParquetEngine`. +pub enum ReadCell { + Null, + Bool, + Int, + Float, + Bytes, + /// `FixedSizeBinary(16)` under `arrow.uuid`: the lowercase 36-char text. + Uuid, + Date, + Timestamp, + Time, + List(Box), + Map(Box, Box), + Struct(Vec<(Vec, ReadCell)>), +} + +impl ReadCell { + /// `canonical`: the type the core reads the column as; `parquet`: the field it was read from (its extension type + /// tells a uuid from 16 bytes), walked in parallel with the canonical type's children. + pub fn new(canonical: &DataType, parquet: &Field) -> Result { + Ok(match canonical { + DataType::Null => ReadCell::Null, + DataType::Boolean => ReadCell::Bool, + DataType::Int64 => ReadCell::Int, + DataType::Float64 => ReadCell::Float, + DataType::Binary => ReadCell::Bytes, + DataType::FixedSizeBinary(16) if is_uuid(parquet) => ReadCell::Uuid, + DataType::FixedSizeBinary(16) => ReadCell::Bytes, + DataType::Date32 => ReadCell::Date, + DataType::Timestamp(_, _) => ReadCell::Timestamp, + DataType::Duration(_) => ReadCell::Time, + DataType::List(element) => ReadCell::List(Box::new(Self::new(element.data_type(), child(parquet, 0)?)?)), + DataType::Map(entries, _) => { + let DataType::Struct(fields) = entries.data_type() else { + return Err(unsupported(canonical)); + }; + let parquet_entries = child(parquet, 0)?; + let key = Self::new(fields[0].data_type(), child(parquet_entries, 0)?)?; + + if !matches!(key, ReadCell::Int | ReadCell::Bytes | ReadCell::Uuid) { + return Err(Error::MapKey { + column: String::new(), + key: key.php_type(), + }); + } + + ReadCell::Map( + Box::new(key), + Box::new(Self::new(fields[1].data_type(), child(parquet_entries, 1)?)?), + ) + } + DataType::Struct(fields) => ReadCell::Struct( + fields + .iter() + .enumerate() + .map(|(index, field)| { + Ok((field.name().as_bytes().to_vec(), Self::new(field.data_type(), child(parquet, index)?)?)) + }) + .collect::>()?, + ), + other => return Err(unsupported(other)), + }) + } + + /// The PHP type this cell's values have: what a MAP key refusal names. + fn php_type(&self) -> &'static str { + match self { + ReadCell::Null => "null", + ReadCell::Bool => "bool", + ReadCell::Int => "int", + ReadCell::Float => "float", + ReadCell::Bytes | ReadCell::Uuid => "string", + ReadCell::Date | ReadCell::Timestamp => "DateTimeImmutable", + ReadCell::Time => "DateInterval", + ReadCell::List(_) | ReadCell::Map(_, _) | ReadCell::Struct(_) => "array", + } + } + + pub fn needs_times(&self) -> bool { + match self { + ReadCell::Time => true, + ReadCell::List(element) => element.needs_times(), + ReadCell::Map(key, value) => key.needs_times() || value.needs_times(), + ReadCell::Struct(children) => children.iter().any(|(_, child)| child.needs_times()), + _ => false, + } + } + + /// Every value of `array` as a PHP list. + pub fn values(&self, array: &ArrayRef, times: Option<&Times>) -> Result { + let mut list = ZendHashTable::with_capacity(u32::try_from(array.len()).unwrap_or(u32::MAX)); + + for row in 0..array.len() { + list.push(self.value(array.as_ref(), row, times)?).map_err(collected)?; + } + + let mut zv = Zval::new(); + zv.set_hashtable(list); + + Ok(zv) + } + + fn value(&self, array: &dyn Array, row: usize, times: Option<&Times>) -> Result { + let mut zv = Zval::new(); + + if array.is_null(row) { + return Ok(zv); + } + + match self { + ReadCell::Null => {} + ReadCell::Bool => zv.set_bool(array.as_boolean().value(row)), + ReadCell::Int => zv = zval_long(array.as_primitive::().value(row)), + ReadCell::Float => zv.set_double(array.as_primitive::().value(row)), + ReadCell::Bytes => { + zv = zval_str(match array.data_type() { + DataType::FixedSizeBinary(_) => array.as_fixed_size_binary().value(row), + _ => array.as_binary::().value(row), + }); + } + ReadCell::Uuid => zv = zval_str(&uuid_text(array.as_fixed_size_binary().value(row))), + ReadCell::Date => zv = date_from_days(i64::from(array.as_primitive::().value(row)))?, + ReadCell::Timestamp => { + zv = datetime_from_micros(array.as_primitive::().value(row), b"+00:00")?; + } + ReadCell::Time => { + zv = times + .ok_or_else(|| ext_exception("flow_php Parquet reader has no TIME base"))? + .interval(array.as_primitive::().value(row))?; + } + ReadCell::List(element) => { + let list = array.as_list::(); + let offsets = list.value_offsets(); + let mut values = ZendHashTable::with_capacity((offsets[row + 1] - offsets[row]) as u32); + + for index in offsets[row] as usize..offsets[row + 1] as usize { + values.push(element.value(list.values().as_ref(), index, times)?).map_err(collected)?; + } + + zv.set_hashtable(values); + } + ReadCell::Map(key, value) => { + let map = array.as_map(); + let offsets = map.value_offsets(); + let mut entries = ZendHashTable::with_capacity((offsets[row + 1] - offsets[row]) as u32); + + for index in offsets[row] as usize..offsets[row + 1] as usize { + let entry = value.value(map.values().as_ref(), index, times)?; + + match key.value(map.keys().as_ref(), index, times)? { + k if k.is_long() => ht_insert_long(&mut entries, k.long().unwrap_or_default(), entry), + k => ht_insert(&mut entries, k.zend_str().map_or(&b""[..], |key| key.as_bytes()), entry), + } + } + + zv.set_hashtable(entries); + } + ReadCell::Struct(children) => { + let structure = array.as_struct(); + let mut values = ZendHashTable::with_capacity(children.len() as u32); + + for ((name, child), column) in children.iter().zip(structure.columns()) { + ht_insert(&mut values, name, child.value(column.as_ref(), row, times)?); + } + + zv.set_hashtable(values); + } + } + + Ok(zv) + } +} + +/// Child `index` of a nested Parquet-side field. +fn child(parquet: &Field, index: usize) -> Result<&Field, Error> { + match parquet.data_type() { + DataType::List(element) | DataType::LargeList(element) | DataType::FixedSizeList(element, _) if index == 0 => { + Ok(element) + } + DataType::Map(entries, _) if index == 0 => Ok(entries), + DataType::Struct(fields) if index < fields.len() => Ok(&fields[index]), + other => Err(unsupported(other)), + } +} + +/// `TimeConverter::toDateInterval()`: `$base->diff($base->modify("+{µs} microseconds"))` - `diff()` normalises the +/// duration into d/h and, past a month, m/d exactly as the PHP engine's value. A time of day (< 24 h) normalises into +/// nothing, so it is built directly with `DateInterval::__set_state()`, one call instead of two. +pub struct Times { + base: Zval, + modify: &'static Function, + diff: &'static Function, + set_state: &'static Function, +} + +const DAY: i64 = 86_400_000_000; + +impl Times { + /// `$base = new DateTimeImmutable('1970-01-01 00:00:00.000000', new DateTimeZone('UTC'))`, built once per reader. + pub fn new() -> Result { + let ce = find_class("DateTimeImmutable")?; + + Ok(Self { + base: datetime_from_micros(0, b"UTC")?, + modify: ce_method_ref(ce, "modify")?, + diff: ce_method_ref(ce, "diff")?, + set_state: ce_method_ref(find_class("DateInterval")?, "__set_state")?, + }) + } + + fn interval(&self, micros: i64) -> Result { + if (0..DAY).contains(µs) { + return self.time_of_day(micros); + } + + let base = self.base.object().ok_or_else(|| ext_exception("flow_php expected a TIME base datetime"))?; + let target = call_handle_transparent( + self.modify, + Some(base), + &mut [zval_str(format!("+{micros} microseconds").as_bytes())], + )?; + + call_handle_transparent(self.diff, Some(base), &mut [target]) + } + + /// `diff()`'s interval of a time of day: `days` 0, `f` from the whole microseconds. + fn time_of_day(&self, micros: i64) -> Result { + let mut state = ZendHashTable::with_capacity(10); + let double = |value: f64| { + let mut zv = Zval::new(); + zv.set_double(value); + zv + }; + + for (name, value) in [ + ("y", 0), + ("m", 0), + ("d", 0), + ("h", micros / 3_600_000_000), + ("i", micros / 60_000_000 % 60), + ("s", micros / 1_000_000 % 60), + ] { + ht_insert(&mut state, name.as_bytes(), zval_long(value)); + } + + // __set_state() stores `f` as (int) (f * 1e6): the half microsecond keeps the truncation on the exact value + // (0.519488 * 1e6 = 519487.99…), and `f` reads back as that value / 1e6, as diff()'s does + ht_insert(&mut state, b"f", double(((micros % 1_000_000) as f64 + 0.5) / 1_000_000.0)); + ht_insert(&mut state, b"invert", zval_long(0)); + ht_insert(&mut state, b"days", zval_long(0)); + let mut from_string = Zval::new(); + from_string.set_bool(false); + ht_insert(&mut state, b"from_string", from_string); + + let mut array = Zval::new(); + array.set_hashtable(state); + + call_handle_transparent(self.set_state, None, &mut [array]) + } +} + +/// A value `WriteCell::append` refuses. +pub enum Refusal { + /// What the target type accepts and what it got. + Value { expected: &'static str, got: String }, + /// A byte buffer past i32 offsets, or a day past i32. + Overflow, + /// A PHP exception a call into the value threw. + Php(PhpException), +} + +impl From for Refusal { + fn from(exception: PhpException) -> Self { + Refusal::Php(exception) + } +} + +/// `get_debug_type()`. +fn debug_type(value: &Zval) -> String { + if value.is_null() { + "null".to_string() + } else if value.is_bool() { + "bool".to_string() + } else if value.is_long() { + "int".to_string() + } else if value.is_double() { + "float".to_string() + } else if value.is_string() { + "string".to_string() + } else if value.is_array() { + "array".to_string() + } else if let Some(object) = value.object() { + object.get_class_name().unwrap_or_else(|_| "object".to_string()) + } else { + "unknown".to_string() + } +} + +fn refused(expected: &'static str, value: &Zval) -> Refusal { + Refusal::Value { + expected, + got: debug_type(value), + } +} + +/// The classes the write cells test instances of, resolved once per writer. +pub struct Classes { + datetime: &'static ClassEntry, + interval: &'static ClassEntry, +} + +impl Classes { + pub fn new() -> Result { + Ok(Self { + datetime: find_class("DateTimeInterface")?, + interval: find_class("DateInterval")?, + }) + } +} + +/// What a writer column accepts per `PhpParquetEngine`'s target type, appended to its canonical kind's builder; the +/// cast to the Parquet type (`to_parquet`) refuses what is out of the target's range. +pub enum WriteCell { + Bool, + Int, + Float, + /// DECIMAL: a float or an int. + Decimal, + Bytes, + /// UUID: a string, or an object's `toString()` / `__toString()`, whose dash-less text is 32 hex digits. + Uuid, + Date, + Timestamp, + Time, + List(Box, bool), + Map(Box, Box, bool), + Struct(Vec<(Vec, WriteCell, bool)>), +} + +impl WriteCell { + /// The cell for a writer schema field (`Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension()`), and the + /// canonical kind its values are built in. + pub fn new(target: &Field) -> Result<(Self, Kind), Error> { + Ok(match target.data_type() { + DataType::Boolean => (WriteCell::Bool, Kind::Boolean), + DataType::Int8 + | DataType::Int16 + | DataType::Int32 + | DataType::Int64 + | DataType::UInt8 + | DataType::UInt16 + | DataType::UInt32 + | DataType::UInt64 => (WriteCell::Int, Kind::Int64), + DataType::Float32 | DataType::Float64 => (WriteCell::Float, Kind::Float64), + DataType::Decimal128(_, _) => (WriteCell::Decimal, Kind::Float64), + DataType::Utf8 | DataType::Binary => (WriteCell::Bytes, Kind::Bytes), + DataType::FixedSizeBinary(16) if is_uuid(target) => (WriteCell::Uuid, Kind::Uuid), + DataType::FixedSizeBinary(_) => (WriteCell::Bytes, Kind::Bytes), + DataType::Date32 => (WriteCell::Date, Kind::Int32), + DataType::Timestamp(_, _) => (WriteCell::Timestamp, Kind::Timestamp), + DataType::Time32(_) | DataType::Time64(_) => (WriteCell::Time, Kind::Duration), + DataType::List(element) => { + let (cell, kind) = Self::new(element)?; + + ( + WriteCell::List(Box::new(cell), element.is_nullable()), + Kind::List(Box::new(KindField { + name: element.name().clone(), + kind, + optional: element.is_nullable(), + })), + ) + } + DataType::Map(entries, _) => { + let DataType::Struct(fields) = entries.data_type() else { + return Err(unsupported(target.data_type())); + }; + let (key, key_kind) = Self::new(&fields[0])?; + let (value, value_kind) = Self::new(&fields[1])?; + + ( + WriteCell::Map(Box::new(key), Box::new(value), fields[1].is_nullable()), + Kind::Map( + Box::new(KindField { + name: fields[0].name().clone(), + kind: key_kind, + optional: false, + }), + Box::new(KindField { + name: fields[1].name().clone(), + kind: value_kind, + optional: fields[1].is_nullable(), + }), + ), + ) + } + DataType::Struct(fields) => { + let mut cells = Vec::with_capacity(fields.len()); + let mut kinds = Vec::with_capacity(fields.len()); + + for field in fields { + let (cell, kind) = Self::new(field)?; + cells.push((field.name().as_bytes().to_vec(), cell, field.is_nullable())); + kinds.push(KindField { + name: field.name().clone(), + kind, + optional: field.is_nullable(), + }); + } + + (WriteCell::Struct(cells), Kind::Struct(kinds)) + } + other => return Err(unsupported(other)), + }) + } + + /// `value` appended to `builder`; a null only where `nullable`. + pub fn append(&self, builder: &mut KindBuilder, value: &Zval, nullable: bool, classes: &Classes) -> Result<(), Refusal> { + let value = value.dereference(); + + if value.is_null() { + if !nullable { + return Err(refused("a value", value)); + } + + builder.append_null(); + + return Ok(()); + } + + match self { + WriteCell::Bool => builder.append_bool(value.bool().ok_or_else(|| refused("bool", value))?), + WriteCell::Int => builder.append_fixed(&value.long().ok_or_else(|| refused("int", value))?.to_le_bytes()), + WriteCell::Float => { + builder.append_fixed(&value.double().ok_or_else(|| refused("float", value))?.to_le_bytes()); + } + WriteCell::Decimal => { + let float = match (value.double(), value.long()) { + (Some(float), _) => float, + (_, Some(int)) => int as f64, + _ => return Err(refused("float or int", value)), + }; + builder.append_fixed(&float.to_le_bytes()); + } + WriteCell::Bytes => { + let bytes = value.zend_str().ok_or_else(|| refused("string", value))?; + builder.append_bytes(bytes.as_bytes()).map_err(|_| Refusal::Overflow)?; + } + WriteCell::Uuid => { + let text = match value.object() { + Some(object) => uuid_text_of(object)?.ok_or_else(|| refused("uuid string or object", value))?, + None => value.shallow_clone(), + }; + let bytes = text + .zend_str() + .and_then(|text| uuid_bytes(text.as_bytes())) + .ok_or_else(|| refused("uuid string or object", value))?; + builder.append_fixed(&bytes); + } + WriteCell::Date => { + let datetime = datetime(value, classes).ok_or_else(|| refused("DateTimeInterface", value))?; + let days = match datetime_days(datetime) { + Some(days) => days, + None => fallback_days(datetime)?, + }; + let days = i32::try_from(days).map_err(|_| Refusal::Overflow)?; + builder.append_fixed(&days.to_le_bytes()); + } + WriteCell::Timestamp => { + let datetime = datetime(value, classes).ok_or_else(|| refused("DateTimeInterface", value))?; + let micros = match datetime_micros(datetime) { + Some(micros) => micros, + None => fallback_micros(datetime)?, + }; + builder.append_fixed(µs.to_le_bytes()); + } + WriteCell::Time => { + let interval = value + .object() + .filter(|object| object.instance_of(classes.interval)) + .ok_or_else(|| refused("DateInterval", value))?; + builder.append_fixed(&interval_micros(interval, value)?.to_le_bytes()); + } + WriteCell::List(element, element_nullable) => { + let values = value.array().ok_or_else(|| refused("array", value))?; + let mut failure = None; + + ht_for_each(values, |_, _, item| { + if failure.is_none() { + if let Err(refusal) = element.append(builder.list_element(), item, *element_nullable, classes) { + failure = Some(refusal); + } + } + + Ok(()) + })?; + + if let Some(refusal) = failure { + return Err(refusal); + } + + builder.end_entries().map_err(|_| Refusal::Overflow)?; + } + WriteCell::Map(key, map_value, value_nullable) => { + let entries = value.array().ok_or_else(|| refused("array", value))?; + let mut failure = None; + + ht_for_each(entries, |name, index, item| { + if failure.is_some() { + return Ok(()); + } + + let entry_key = match name { + Some(name) => zval_str(name.as_bytes()), + None => zval_long(index as i64), + }; + let (keys, values) = builder.map_entries(); + let appended = key + .append(keys, &entry_key, false, classes) + .and_then(|()| map_value.append(values, item, *value_nullable, classes)); + + if let Err(refusal) = appended { + failure = Some(refusal); + } + + Ok(()) + })?; + + if let Some(refusal) = failure { + return Err(refusal); + } + + builder.end_entries().map_err(|_| Refusal::Overflow)?; + } + WriteCell::Struct(children) => { + let values = value.array().ok_or_else(|| refused("array", value))?; + let null = Zval::new(); + + for ((name, cell, child_nullable), child) in children.iter().zip(builder.struct_children()) { + cell.append(child, ht_get(values, name).unwrap_or(&null), *child_nullable, classes)?; + } + + builder.end_struct(); + } + } + + Ok(()) + } +} + +/// `UuidConverter::toParquetType()`'s text of an object: `toString()`, else `__toString()`; `None` for neither. +fn uuid_text_of(object: &ZendObject) -> Result, PhpException> { + let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php expected a class entry"))?; + + for method in ["toString", "__toString"] { + if let Ok(function) = ce_method_ref(ce, method) { + return call_handle_transparent(function, Some(object), &mut []).map(Some); + } + } + + Ok(None) +} + +fn datetime<'a>(value: &'a Zval, classes: &Classes) -> Option<&'a ZendObject> { + value.object().filter(|object| object.instance_of(classes.datetime)) +} + +fn method_long(object: &ZendObject, method: &str, args: &mut [Zval]) -> Result { + let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php expected a class entry"))?; + let result = call_handle_transparent(ce_method_ref(ce, method)?, Some(object), args)?; + + result + .long() + .or_else(|| result.zend_str().and_then(|text| std::str::from_utf8(text.as_bytes()).ok()?.parse().ok())) + .ok_or_else(|| ext_exception(format!("flow_php expected {method}() to return an int"))) +} + +/// `getTimestamp() * 1_000_000 + format('u')`, for a datetime timelib has not brought up to date. +fn fallback_micros(datetime: &ZendObject) -> Result { + let seconds = method_long(datetime, "getTimestamp", &mut [])?; + let micros = method_long(datetime, "format", &mut [zval_str(b"u")])?; + + seconds.checked_mul(1_000_000).and_then(|us| us.checked_add(micros)).ok_or(Refusal::Overflow) +} + +/// `(getTimestamp() + getOffset())` floored to days, for a datetime timelib has not brought up to date. +fn fallback_days(datetime: &ZendObject) -> Result { + let seconds = method_long(datetime, "getTimestamp", &mut [])?; + let offset = method_long(datetime, "getOffset", &mut [])?; + + Ok((seconds + offset).div_euclid(86_400)) +} + +fn interval_part(interval: &ZendObject, name: &str) -> Result { + Ok(read_property(interval, name)?.long().unwrap_or_default()) +} + +/// `TimeConverter::toParquetType()`: `((d·24+h)·3600+i·60+s)·1e6 + (int)(f·1e6)`, `invert` ignored; y or m ≠ 0 is +/// refused. +fn interval_micros(interval: &ZendObject, value: &Zval) -> Result { + if interval_part(interval, "y")? != 0 || interval_part(interval, "m")? != 0 { + return Err(refused("DateInterval without years or months", value)); + } + + let seconds = ((interval_part(interval, "d")? * 24 + interval_part(interval, "h")?) * 3_600 + + interval_part(interval, "i")? * 60 + + interval_part(interval, "s")?) + .checked_mul(1_000_000) + .ok_or(Refusal::Overflow)?; + let fraction = (read_property(interval, "f")?.double().unwrap_or_default() * 1_000_000.0) as i64; + + seconds.checked_add(fraction).ok_or(Refusal::Overflow) +} + +/// Rows appended to one writer column, cast to canonical arrays in batches. +pub struct WriteColumn { + pub name: String, + pub cell: WriteCell, + pub kind: Kind, + pub nullable: bool, + pub builder: KindBuilder, +} + +impl WriteColumn { + pub fn new(target: &Field) -> Result { + let (cell, kind) = WriteCell::new(target).map_err(|e| e.in_column(target.name()))?; + + Ok(Self { + name: target.name().clone(), + builder: KindBuilder::new(&kind), + cell, + kind, + nullable: target.is_nullable(), + }) + } + + /// The rows appended since the last take, as a canonical array; the builder starts over. + pub fn take(&mut self) -> Result { + let data = self.builder.finish(&self.kind)?; + self.builder = KindBuilder::new(&self.kind); + + Ok(make_array(data)) + } +} diff --git a/src/extension/flow-php-ext/src/parquet/error.rs b/src/extension/flow-php-ext/src/parquet/error.rs index 9b264ad7f6..8acabbc2a3 100644 --- a/src/extension/flow-php-ext/src/parquet/error.rs +++ b/src/extension/flow-php-ext/src/parquet/error.rs @@ -12,6 +12,14 @@ pub enum Error { Unsupported { column: String, parquet: String }, Overflow { column: String, row: usize }, InvalidUtf8 { column: String, row: usize }, + /// A fixed-length target the value's byte length does not match. + Length { column: String, row: usize, expected: usize }, + /// MAP keys of a type a PHP array does not key by (int or string), named by the PHP type they would read as. + MapKey { column: String, key: &'static str }, + /// A value the target type does not accept: what it expects and what it got. + Value { column: String, row: usize, expected: &'static str, got: String }, + /// Bytes that are not a Parquet file: no footer where it must be. + NotParquet(String), Options(String), Stream(String), } @@ -23,6 +31,9 @@ impl Error { Error::Unsupported { parquet, .. } => Error::Unsupported { column: name.to_string(), parquet }, Error::Overflow { row, .. } => Error::Overflow { column: name.to_string(), row }, Error::InvalidUtf8 { row, .. } => Error::InvalidUtf8 { column: name.to_string(), row }, + Error::Length { row, expected, .. } => Error::Length { column: name.to_string(), row, expected }, + Error::MapKey { key, .. } => Error::MapKey { column: name.to_string(), key }, + Error::Value { row, expected, got, .. } => Error::Value { column: name.to_string(), row, expected, got }, error => error, } } @@ -32,6 +43,8 @@ impl Error { match self { Error::Overflow { column, row } => Error::Overflow { column, row: parent(row) }, Error::InvalidUtf8 { column, row } => Error::InvalidUtf8 { column, row: parent(row) }, + Error::Length { column, row, expected } => Error::Length { column, row: parent(row), expected }, + Error::Value { column, row, expected, got } => Error::Value { column, row: parent(row), expected, got }, error => error, } } diff --git a/src/extension/flow-php-ext/src/parquet/etl.rs b/src/extension/flow-php-ext/src/parquet/etl.rs index 7f408b1083..57637f9705 100644 --- a/src/extension/flow-php-ext/src/parquet/etl.rs +++ b/src/extension/flow-php-ext/src/parquet/etl.rs @@ -14,13 +14,14 @@ use crate::column::NativeColumn; use crate::ctx::{call_method, call_static, ht_for_each, ht_get, ht_insert, null_zval, zval_long, zval_str}; use crate::exception::ext_exception; use crate::parquet::error::Error; +use crate::parquet::library::NativeParquetFile; use crate::parquet::options; use crate::parquet::read::{ParquetReader, ReadPlan}; use crate::parquet::sink::PhpSink; -use crate::parquet::source::{PhpSource, PhpStream}; +use crate::parquet::source::PhpStream; use crate::parquet::write::ParquetWriter; use crate::plan::{type_plan, TypePlan}; -use crate::render::{invalid_argument, parquet_exception, Side}; +use crate::render::{invalid_argument, parquet_exception, Side, Surface}; fn rows(value: Option, name: &str) -> PhpResult> { value @@ -62,8 +63,9 @@ pub struct NativeParquetReader { #[php_impl] impl NativeParquetReader { + /// `$file`'s footer plans the read; no footer is read here. pub fn __construct( - stream: &Zval, + file: &NativeParquetFile, schema: &Zval, batch_size: i64, offset: Option, @@ -74,11 +76,10 @@ impl NativeParquetReader { .filter(|size| *size > 0) .ok_or_else(|| invalid_argument("flow_php Parquet batch size must be greater than 0".to_string()))?; let (offset, limit) = (rows(offset, "offset")?.unwrap_or(0), rows(limit, "limit")?); - let stream = Arc::new(PhpStream::new(stream)?); - let refused = |error| parquet_exception(error, &stream, Side::Read); - let source = PhpSource::new(Arc::clone(&stream)).map_err(refused)?; - let meta = source.metadata().map_err(refused)?; - let plan = ReadPlan::new(&meta, offset, limit); + let (stream, size, meta) = file.read()?; + let stream = Arc::clone(stream); + let refused = |error| parquet_exception(error, &stream, Side::Read, Surface::Etl); + let plan = ReadPlan::new(meta, offset, limit); let mut columns = Vec::new(); let mut names = Vec::new(); @@ -87,7 +88,7 @@ impl NativeParquetReader { columns.push((name, type_plan(&call_method(&definition, "type", &mut [])?)?)); } - let reader = ParquetReader::open(source, meta, &names, plan, batch_size).map_err(refused)?; + let reader = ParquetReader::open(Arc::clone(&stream), size, meta, &names, plan, batch_size).map_err(refused)?; for ((field, canonical), (name, plan)) in reader.fields().iter().zip(reader.types()).zip(&columns) { let stored = data_type(&plan.kind); @@ -124,7 +125,7 @@ impl NativeParquetReader { return Ok(null_zval()); } - Some(batch) => batch.map_err(|error| parquet_exception(error, &self.stream, Side::Read))?, + Some(batch) => batch.map_err(|error| parquet_exception(error, &self.stream, Side::Read, Surface::Etl))?, }; let mut columns = ZendHashTable::with_capacity(self.columns.len() as u32); @@ -168,7 +169,7 @@ impl NativeParquetWriter { /// `$schema`: `Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension()`, `$options`: `OptionsConverter::toExtension()`. pub fn __construct(stream: &Zval, schema: &ZendHashTable, compression: String, options: &ZendHashTable) -> PhpResult { let stream = Arc::new(PhpStream::new(stream)?); - let refused = |error| parquet_exception(error, &stream, Side::Write); + let refused = |error| parquet_exception(error, &stream, Side::Write, Surface::Etl); let writer = ParquetWriter::open( PhpSink::new(Arc::clone(&stream)), options::schema(schema).map_err(refused)?, @@ -220,7 +221,7 @@ impl NativeParquetWriter { writer .write(count, &arrays) - .map_err(|error| parquet_exception(error, &self.stream, Side::Write)) + .map_err(|error| parquet_exception(error, &self.stream, Side::Write, Surface::Etl)) } /// The footer, then the stream closed - as the lib's Parquet writers close theirs. @@ -229,7 +230,7 @@ impl NativeParquetWriter { .take() .ok_or_else(|| ext_exception("flow_php Parquet writer is already closed"))? .close() - .map_err(|error| parquet_exception(error, &self.stream, Side::Write))?; + .map_err(|error| parquet_exception(error, &self.stream, Side::Write, Surface::Etl))?; match self.stream.call("close", &mut []) { Some(_) => Ok(()), @@ -237,6 +238,7 @@ impl NativeParquetWriter { Error::Stream("close() threw".to_string()), &self.stream, Side::Write, + Surface::Etl, )), } } diff --git a/src/extension/flow-php-ext/src/parquet/fetch.rs b/src/extension/flow-php-ext/src/parquet/fetch.rs new file mode 100644 index 0000000000..ef4b62b308 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/fetch.rs @@ -0,0 +1,293 @@ +//! A planned read's column chunks, fetched a row group at a time: the first page request inside a planned row group +//! reads every projected column chunk of that group - adjacent chunks in one read - and every later page header and +//! page body of the group is a slice of those buffers. arrow-rs's sync page reader asks for each page header +//! separately (`get_read`), so answering from the stream per request would read the file many times over. +//! +//! arrow-rs advances each column's pages on its own, so one batch may take column `a` into the next row group while +//! column `b` still reads the previous one: a group's buffers are dropped once every projected column has moved past +//! it. Memory: the projected compressed chunks of the row groups one batch spans - the bound arrow-rs's async reader +//! and DuckDB accept, row groups being the writer's unit. + +use std::collections::btree_map::Entry; +use std::collections::BTreeMap; +use std::ops::Range; +use std::sync::{Arc, Mutex}; + +use bytes::buf::Reader; +use bytes::{Buf, Bytes}; +use parquet::errors::ParquetError; +use parquet::file::metadata::ParquetMetaData; +use parquet::file::reader::{ChunkReader, Length}; + +use crate::parquet::source::{exact, ReadAt}; + +/// A column chunk of the file and, when the read plans it, where: its planned group, its projected column, and the +/// coalesced read of that group holding it. +struct Chunk { + range: Range, + planned: Option<(usize, usize, usize)>, +} + +#[derive(Default)] +struct Fetched { + /// Planned group → its reads' bytes. + buffers: BTreeMap>, + /// Per projected column, the planned group it reads now. + progress: Vec, +} + +pub struct ChunkFetch { + source: Arc, + size: u64, + /// Per planned group, its projected chunks with every run of adjacent ones merged, in file order. + reads: Vec>>, + /// Every column chunk of the file, by start: page requests find theirs by binary search. + chunks: Vec, + fetched: Mutex, +} + +impl ChunkFetch { + /// `row_groups`: the planned groups; `leaves`: the projected leaf columns. + pub fn new(source: Arc, size: u64, meta: &ParquetMetaData, row_groups: &[usize], leaves: &[usize]) -> Self { + let range = |(start, length): (u64, u64)| start..start + length; + let planned = row_groups + .iter() + .map(|group| { + let columns = meta.row_group(*group).columns(); + + leaves.iter().map(|leaf| range(columns[*leaf].byte_range())).collect() + }) + .collect(); + let mut is_planned = vec![false; meta.num_row_groups()]; + let mut is_projected = vec![false; meta.file_metadata().schema_descr().num_columns()]; + row_groups.iter().for_each(|group| is_planned[*group] = true); + leaves.iter().for_each(|leaf| is_projected[*leaf] = true); + let (is_planned, is_projected) = (&is_planned, &is_projected); + let unplanned = meta + .row_groups() + .iter() + .enumerate() + .flat_map(|(group, columns)| { + columns + .columns() + .iter() + .enumerate() + .filter(move |(leaf, _)| !is_planned[group] || !is_projected[*leaf]) + .map(|(_, chunk)| range(chunk.byte_range())) + }) + .collect(); + + Self::from_ranges(source, size, planned, unplanned) + } + + /// `planned`: per planned group, its projected chunks, by projected column; `unplanned`: every other chunk. + fn from_ranges(source: Arc, size: u64, planned: Vec>>, unplanned: Vec>) -> Self { + let columns = planned.first().map_or(0, Vec::len); + let reads = planned.iter().map(|chunks| coalesced(chunks.clone())).collect::>(); + let mut chunks = unplanned + .into_iter() + .map(|range| Chunk { range, planned: None }) + .chain(planned.into_iter().enumerate().flat_map(|(group, chunks)| { + let reads = &reads[group]; + + chunks + .into_iter() + .enumerate() + .map(move |(column, range)| { + let read = reads.iter().position(|read| read.start <= range.start && range.end <= read.end); + + Chunk { + planned: read.map(|read| (group, column, read)), + range, + } + }) + .collect::>() + })) + .collect::>(); + chunks.sort_by_key(|chunk| chunk.range.start); + + Self { + source, + size, + reads, + chunks, + fetched: Mutex::new(Fetched { + buffers: BTreeMap::new(), + progress: vec![0; columns], + }), + } + } + + /// The column chunk holding `offset`. + fn chunk_at(&self, offset: u64) -> Option<&Chunk> { + let after = self.chunks.partition_point(|chunk| chunk.range.start <= offset); + + after.checked_sub(1).map(|index| &self.chunks[index]).filter(|chunk| offset < chunk.range.end) + } + + /// The fetched bytes of [start, end) when a planned column chunk holds it, fetching its row group first. + fn planned(&self, start: u64, end: u64) -> Result, ParquetError> { + let Some((group, column, read)) = self.chunk_at(start).and_then(|chunk| chunk.planned) else { + return Ok(None); + }; + let range = &self.reads[group][read]; + + if end > range.end { + return Ok(None); + } + + let mut fetched = self.fetched.lock().map_err(|_| ParquetError::General("chunk fetch poisoned".into()))?; + + if let Entry::Vacant(entry) = fetched.buffers.entry(group) { + entry.insert( + self.reads[group] + .iter() + .map(|range| exact(self.source.as_ref(), range.start, (range.end - range.start) as usize)) + .collect::, _>>()?, + ); + } + + let bytes = fetched.buffers[&group][read].slice((start - range.start) as usize..(end - range.start) as usize); + fetched.progress[column] = group; + let slowest = fetched.progress.iter().copied().min().unwrap_or(group); + fetched.buffers.retain(|fetched_group, _| *fetched_group >= slowest); + + Ok(Some(bytes)) + } +} + +/// Sorted ranges with every run of adjacent ones merged. +fn coalesced(mut ranges: Vec>) -> Vec> { + ranges.sort_by_key(|range| range.start); + let mut merged: Vec> = Vec::with_capacity(ranges.len()); + + for range in ranges { + match merged.last_mut() { + Some(last) if last.end == range.start => last.end = range.end, + _ => merged.push(range), + } + } + + merged +} + +impl Length for ChunkFetch { + fn len(&self) -> u64 { + self.size + } +} + +impl ChunkReader for ChunkFetch { + type T = Reader; + + /// A page header: the rest of its planned read; outside the plan, one exact read to the end of the column chunk + /// holding `start` (of the file when none does). + fn get_read(&self, start: u64) -> Result { + let end = self.chunk_at(start).map_or(self.size, |chunk| match chunk.planned { + Some((group, _, read)) => self.reads[group][read].end, + None => chunk.range.end, + }); + + Ok(match self.planned(start, end)? { + Some(bytes) => bytes, + None => exact(self.source.as_ref(), start, (end - start) as usize)?, + } + .reader()) + } + + fn get_bytes(&self, start: u64, length: usize) -> Result { + match self.planned(start, start + length as u64)? { + Some(bytes) => Ok(bytes), + None => exact(self.source.as_ref(), start, length), + } + } +} + +#[cfg(test)] +mod tests { + use std::io::Read; + use std::ops::Range; + use std::sync::Arc; + + use parquet::file::reader::ChunkReader; + + use super::{coalesced, ChunkFetch}; + use crate::parquet::source::fake::Counting; + + #[test] + fn adjacent_ranges_are_coalesced() { + assert_eq!(coalesced(vec![10..20, 0..10, 30..40, 20..25]), vec![0..25, 30..40]); + assert!(coalesced(vec![]).is_empty()); + } + + fn fetch(source: &Arc, planned: Vec>>, unplanned: Vec>) -> ChunkFetch { + ChunkFetch::from_ranges(Arc::clone(source), source.data.len() as u64, planned, unplanned) + } + + #[test] + fn a_read_outside_the_plan_is_one_exact_read_to_the_end_of_its_chunk() { + let source = Arc::new(Counting::new((0..100).collect())); + let fetch = fetch(&source, vec![vec![10..20]], vec![30..35, 40..60]); + let mut rest = Vec::new(); + + fetch.get_read(45).unwrap().read_to_end(&mut rest).unwrap(); + + assert_eq!(rest, (45..60).collect::>()); + assert_eq!(source.counted(), (1, 15)); + + rest.clear(); + fetch.get_read(90).unwrap().read_to_end(&mut rest).unwrap(); + + assert_eq!(rest, (90..100).collect::>()); + assert_eq!(fetch.get_bytes(70, 2).unwrap().to_vec(), vec![70, 71]); + assert_eq!(source.counted(), (3, 27)); + } + + #[test] + fn a_planned_group_is_fetched_once_in_coalesced_reads() { + let source = Arc::new(Counting::new((0..100).collect())); + let fetch = fetch(&source, vec![vec![0..10, 10..15, 20..30]], vec![]); + let mut header = Vec::new(); + + assert_eq!(fetch.get_bytes(22, 3).unwrap().to_vec(), vec![22, 23, 24]); + fetch.get_read(12).unwrap().read_to_end(&mut header).unwrap(); + assert_eq!(fetch.get_bytes(1, 2).unwrap().to_vec(), vec![1, 2]); + + assert_eq!(header, (12..15).collect::>()); + assert_eq!(source.counted(), (2, 25)); + } + + #[test] + fn a_group_is_dropped_once_every_column_moved_past_it() { + let source = Arc::new(Counting::new((0..100).collect())); + let fetch = fetch(&source, vec![vec![0..10, 20..30], vec![50..60, 70..80]], vec![]); + let groups = |fetch: &ChunkFetch| fetch.fetched.lock().unwrap().buffers.keys().copied().collect::>(); + + fetch.get_bytes(0, 1).unwrap(); + fetch.get_bytes(50, 1).unwrap(); + assert_eq!(groups(&fetch), vec![0, 1]); + + fetch.get_bytes(21, 1).unwrap(); + assert_eq!(groups(&fetch), vec![0, 1]); + + fetch.get_bytes(71, 1).unwrap(); + assert_eq!(groups(&fetch), vec![1]); + assert_eq!(source.counted(), (4, 40)); + } + + #[test] + fn page_requests_find_their_chunk_among_many() { + let source = Arc::new(Counting::new((0..=255).cycle().take(40_000).collect())); + let planned = (0..100).map(|group| vec![group * 400..group * 400 + 100, group * 400 + 200..group * 400 + 300]); + let fetch = fetch(&source, planned.collect(), (0..100).map(|group| group * 400 + 100..group * 400 + 200).collect()); + + assert_eq!(fetch.get_bytes(99 * 400 + 250, 2).unwrap().to_vec(), source.data[39_850..39_852].to_vec()); + assert_eq!(source.counted(), (2, 200)); + + let mut header = Vec::new(); + fetch.get_read(50 * 400 + 150).unwrap().read_to_end(&mut header).unwrap(); + + assert_eq!(header, source.data[20_150..20_200].to_vec()); + assert_eq!(source.counted(), (3, 250)); + } +} diff --git a/src/extension/flow-php-ext/src/parquet/footer.rs b/src/extension/flow-php-ext/src/parquet/footer.rs new file mode 100644 index 0000000000..58015a5b82 --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/footer.rs @@ -0,0 +1,171 @@ +//! A Parquet file's footer, read and decoded once: the readers plan and read from its `ParquetMetaData`, the lib +//! surface decodes its thrift bytes into PHP objects. + +use std::sync::Arc; + +use bytes::{Bytes, BytesMut}; +use parquet::file::metadata::{ParquetMetaData, ParquetMetaDataReader}; +use parquet::file::reader::ChunkReader; + +use crate::parquet::error::Error; + +/// What the first read takes from the end of the file: the whole footer of every file it is shorter than. +const TAIL: u64 = 64 * 1024; + +const MAGIC: &[u8; 4] = b"PAR1"; + +pub struct Footer { + /// The thrift `FileMetaData`. + bytes: Bytes, + meta: Arc, +} + +impl Footer { + /// One read of the last min(size, 64 KiB) bytes, a second only when the footer is longer. + pub fn read(source: &R) -> Result { + let size = source.len(); + + if size < 8 { + return Err(corrupt(format!("Invalid Parquet file. Size is {size} bytes, smaller than the footer"))); + } + + let read = size.min(TAIL); + let tail = source.get_bytes(size - read, read as usize)?; + let trailer = &tail[tail.len() - 8..]; + + if &trailer[4..] != MAGIC { + return Err(corrupt("Invalid Parquet file. Corrupt footer".to_string())); + } + + let length = u64::from(u32::from_le_bytes([trailer[0], trailer[1], trailer[2], trailer[3]])); + + if length + 8 > size { + return Err(corrupt(format!( + "Invalid Parquet file. Reported metadata length of {length} + 8 byte footer, but file is only {size} \ + bytes" + ))); + } + + let end = tail.len() - 8; + let bytes = if length + 8 <= read { + tail.slice(end - length as usize..end) + } else { + let mut bytes = BytesMut::with_capacity(length as usize); + bytes.extend_from_slice(&source.get_bytes(size - 8 - length, (length + 8 - read) as usize)?); + bytes.extend_from_slice(&tail[..end]); + bytes.freeze() + }; + let meta = ParquetMetaDataReader::decode_metadata(&bytes)?; + + Ok(Self { + bytes, + meta: Arc::new(meta), + }) + } + + pub fn meta(&self) -> &Arc { + &self.meta + } + + pub fn bytes(&self) -> &Bytes { + &self.bytes + } +} + +fn corrupt(message: String) -> Error { + Error::NotParquet(message) +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use arrow_array::{Int64Array, RecordBatch}; + use arrow_schema::{DataType, Field, Schema}; + use bytes::Bytes; + use parquet::arrow::ArrowWriter; + use parquet::errors::ParquetError; + use parquet::file::metadata::KeyValue; + use parquet::file::properties::WriterProperties; + use parquet::file::reader::{ChunkReader, Length}; + + use super::Footer; + use crate::parquet::error::Error; + use crate::parquet::source::fake::Counting; + use crate::parquet::source::{exact, WindowedRead}; + + struct Source(Arc); + + impl Length for Source { + fn len(&self) -> u64 { + self.0.data.len() as u64 + } + } + + impl ChunkReader for Source { + type T = WindowedRead; + + fn get_read(&self, start: u64) -> Result { + Ok(WindowedRead::new(Arc::clone(&self.0), start, self.len())) + } + + fn get_bytes(&self, start: u64, length: usize) -> Result { + exact(self.0.as_ref(), start, length) + } + } + + /// A file whose footer carries `padding` bytes of key/value metadata. + fn file(padding: usize) -> Vec { + let schema = Arc::new(Schema::new(vec![Field::new("id", DataType::Int64, false)])); + let props = WriterProperties::builder() + .set_key_value_metadata(Some(vec![KeyValue::new("padding".to_string(), "x".repeat(padding))])) + .build(); + let mut file = Vec::new(); + let mut writer = ArrowWriter::try_new(&mut file, Arc::clone(&schema), Some(props)).unwrap(); + writer + .write(&RecordBatch::try_new(schema, vec![Arc::new(Int64Array::from(vec![1, 2, 3]))]).unwrap()) + .unwrap(); + writer.close().unwrap(); + + file + } + + #[test] + fn a_footer_inside_the_tail_is_read_once() { + let counting = Arc::new(Counting::new(file(10))); + let footer = Footer::read(&Source(Arc::clone(&counting))).unwrap(); + + assert_eq!(counting.counted().0, 1); + assert_eq!(footer.meta().file_metadata().num_rows(), 3); + + let data = &counting.data; + let length = u32::from_le_bytes(data[data.len() - 8..data.len() - 4].try_into().unwrap()) as usize; + assert_eq!(footer.bytes().as_ref(), &data[data.len() - 8 - length..data.len() - 8]); + } + + #[test] + fn a_footer_longer_than_the_tail_takes_a_second_read() { + let counting = Arc::new(Counting::new(file(100 * 1024))); + let footer = Footer::read(&Source(Arc::clone(&counting))).unwrap(); + + assert_eq!(counting.counted().0, 2); + assert_eq!(footer.meta().file_metadata().num_rows(), 3); + assert_eq!( + footer.meta().file_metadata().key_value_metadata().unwrap()[0].value.as_ref().map(String::len), + Some(100 * 1024) + ); + } + + #[test] + fn a_file_without_the_magic_is_refused() { + let mut data = file(10); + let end = data.len(); + data[end - 1] = b'X'; + + assert!(matches!( + Footer::read(&Source(Arc::new(Counting::new(data)))), + Err(Error::NotParquet(message)) if message.contains("Corrupt footer") + )); + assert!(matches!(Footer::read(&Source(Arc::new(Counting::new(vec![1, 2, 3])))), Err(Error::NotParquet(_)))); + } +} diff --git a/src/extension/flow-php-ext/src/parquet/library.rs b/src/extension/flow-php-ext/src/parquet/library.rs new file mode 100644 index 0000000000..0e0f638c8f --- /dev/null +++ b/src/extension/flow-php-ext/src/parquet/library.rs @@ -0,0 +1,403 @@ +//! `Flow\Parquet\Engine\Native\{NativeParquetFile, NativeParquetColumnsReader, NativeParquetRowsWriter}`: the +//! `flow-php/parquet` lib's values over the core - one footer read per file, columns as lists of the values +//! `PhpParquetEngine` returns, rows written as it accepts them. + +use std::sync::Arc; + +use arrow_array::ArrayRef; +use ext_php_rs::boxed::ZBox; +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::{ZendHashTable, Zval}; +use parquet::file::metadata::ParquetMetaData; +use parquet::file::reader::Length; + +use crate::ctx::{ht_for_each, ht_get, ht_insert}; +use crate::parquet::cells::{Classes, ReadCell, Refusal, Times, WriteColumn}; +use crate::parquet::error::Error; +use crate::parquet::footer::Footer; +use crate::parquet::options; +use crate::parquet::read::{ParquetReader, ReadPlan}; +use crate::parquet::sink::PhpSink; +use crate::parquet::source::{PhpSource, PhpStream}; +use crate::parquet::write::ParquetWriter; +use crate::render::{exception, parquet_exception, Side, Surface}; +use crate::thrift; + +const FILE_META_DATA: &str = "Flow\\Parquet\\ThriftModel\\FileMetaData"; +/// `FileMetaData::$schema`'s field id. +const SCHEMA: i16 = 2; +const RUNTIME: &str = "Flow\\Parquet\\Exception\\RuntimeException"; +const INVALID_ARGUMENT: &str = "Flow\\Parquet\\Exception\\InvalidArgumentException"; + +fn closed() -> PhpException { + exception(RUNTIME, "Parquet file is closed".to_string()) +} + +fn rows(value: Option, name: &str) -> PhpResult> { + value + .map(|value| { + u64::try_from(value) + .map_err(|_| exception(INVALID_ARGUMENT, format!("flow_php Parquet {name} must be greater or equal to 0"))) + }) + .transpose() +} + +fn batch_size(value: i64) -> PhpResult { + usize::try_from(value) + .ok() + .filter(|size| *size > 0) + .ok_or_else(|| exception(INVALID_ARGUMENT, "flow_php Parquet batch size must be greater than 0".to_string())) +} + +#[php_class] +#[php(name = "Flow\\Parquet\\Engine\\Native\\NativeParquetFile", flags = ClassFlags::Final)] +pub struct NativeParquetFile { + stream: Arc, + source: PhpSource, + footer: Footer, + schema: Option, + thrift: Option, + closed: bool, +} + +impl NativeParquetFile { + fn open(&self) -> PhpResult<()> { + if self.closed { + return Err(closed()); + } + + Ok(()) + } + + /// The file's stream, size and footer, for a reader of it: the ETL's `NativeParquetReader` or the lib's. + pub fn read(&self) -> PhpResult<(&Arc, u64, &Arc)> { + self.open()?; + + Ok((&self.stream, self.source.len(), self.footer.meta())) + } +} + +#[php_impl] +impl NativeParquetFile { + /// Reads and decodes the footer; owns the stream from here on. + pub fn __construct(stream: &Zval) -> PhpResult { + let stream = Arc::new(PhpStream::new(stream)?); + let refused = |error| parquet_exception(error, &stream, Side::Read, Surface::Lib); + let source = PhpSource::new(Arc::clone(&stream)).map_err(refused)?; + let footer = Footer::read(&source).map_err(refused)?; + + Ok(Self { + stream, + source, + footer, + schema: None, + thrift: None, + closed: false, + }) + } + + /// `FileMetaData::$schema`: the list of `SchemaElement`s, decoded on the first call. + pub fn schema(&mut self) -> PhpResult { + self.open()?; + + if let Some(schema) = &self.schema { + return Ok(schema.shallow_clone()); + } + + let schema = thrift::decode(self.footer.bytes(), FILE_META_DATA, Some(SCHEMA))?; + self.schema = Some(schema.shallow_clone()); + + Ok(schema) + } + + #[php(name = "rowsNumber")] + pub fn rows_number(&self) -> PhpResult { + self.open()?; + + Ok(self.footer.meta().file_metadata().num_rows()) + } + + /// Σ row group `total_byte_size` (uncompressed). + #[php(name = "totalByteSize")] + pub fn total_byte_size(&self) -> PhpResult { + self.open()?; + + Ok(self.footer.meta().row_groups().iter().map(|group| group.total_byte_size()).sum()) + } + + /// The whole footer as `FileMetaData`, decoded on the first call. + pub fn thrift(&mut self) -> PhpResult { + self.open()?; + + if let Some(thrift) = &self.thrift { + return Ok(thrift.shallow_clone()); + } + + let thrift = thrift::decode(self.footer.bytes(), FILE_META_DATA, None)?; + self.thrift = Some(thrift.shallow_clone()); + + Ok(thrift) + } + + /// Closes the stream; any later call throws. + pub fn close(&mut self) -> PhpResult<()> { + self.open()?; + self.closed = true; + self.schema = None; + self.thrift = None; + + match self.stream.call("close", &mut []) { + Some(_) => Ok(()), + None => Err(parquet_exception( + Error::Stream("close() threw".to_string()), + &self.stream, + Side::Read, + Surface::Lib, + )), + } + } +} + +#[php_class] +#[php(name = "Flow\\Parquet\\Engine\\Native\\NativeParquetColumnsReader", flags = ClassFlags::Final)] +pub struct NativeParquetColumnsReader { + reader: Option, + stream: Arc, + columns: Vec<(Vec, ReadCell)>, + times: Option, +} + +#[php_impl] +impl NativeParquetColumnsReader { + /// `$columns`: root names or struct paths; `$batchSize` rows at most per `next()`. + pub fn __construct( + file: &NativeParquetFile, + columns: &ZendHashTable, + batch_size: i64, + offset: Option, + limit: Option, + ) -> PhpResult { + let batch_size = self::batch_size(batch_size)?; + let (offset, limit) = (rows(offset, "offset")?.unwrap_or(0), rows(limit, "limit")?); + let (stream, size, meta) = file.read()?; + let stream = Arc::clone(stream); + let refused = |error| parquet_exception(error, &stream, Side::Read, Surface::Lib); + let mut names = Vec::with_capacity(columns.len()); + + ht_for_each(columns, |_, _, name| { + names.push( + name.str() + .ok_or_else(|| exception(INVALID_ARGUMENT, "flow_php Parquet column names must be strings".to_string()))? + .to_string(), + ); + + Ok(()) + })?; + + let reader = + ParquetReader::open(Arc::clone(&stream), size, meta, &names, ReadPlan::new(meta, offset, limit), batch_size) + .map_err(refused)?; + let cells = reader + .fields() + .iter() + .zip(reader.types()) + .map(|(field, canonical)| ReadCell::new(canonical, field).map_err(|e| e.in_column(field.name()))) + .collect::, Error>>() + .map_err(refused)?; + let times = if cells.iter().any(ReadCell::needs_times) { Some(Times::new()?) } else { None }; + + Ok(Self { + reader: Some(reader), + stream, + columns: names.into_iter().map(String::into_bytes).zip(cells).collect(), + times, + }) + } + + /// At most `$batchSize` rows as lists keyed by column, null after the last. + pub fn next(&mut self) -> PhpResult>> { + let Some(reader) = self.reader.as_mut() else { + return Ok(None); + }; + + let arrays: Vec = match reader.next() { + None => { + self.reader = None; + + return Ok(None); + } + Some(batch) => { + batch + .map_err(|error| parquet_exception(error, &self.stream, Side::Read, Surface::Lib))? + .1 + } + }; + + let mut chunk = ZendHashTable::with_capacity(self.columns.len() as u32); + + for ((name, cell), array) in self.columns.iter().zip(&arrays) { + ht_insert(&mut chunk, name, cell.values(array, self.times.as_ref())?); + } + + Ok(Some(chunk)) + } + + pub fn close(&mut self) { + self.reader = None; + } +} + +#[php_class] +#[php(name = "Flow\\Parquet\\Engine\\Native\\NativeParquetRowsWriter", flags = ClassFlags::Final)] +pub struct NativeParquetRowsWriter { + writer: Option, + stream: Arc, + columns: Vec, + classes: Classes, + buffered: usize, + batch_size: usize, +} + +impl Drop for NativeParquetRowsWriter { + fn drop(&mut self) { + self.stream.detach(); + } +} + +impl NativeParquetRowsWriter { + fn refused(&self, error: Error) -> PhpException { + parquet_exception(error, &self.stream, Side::Write, Surface::Lib) + } + + /// The buffered rows through `ParquetWriter::write`. + fn flush(&mut self) -> PhpResult<()> { + if self.buffered == 0 { + return Ok(()); + } + + let arrays = self + .columns + .iter_mut() + .map(WriteColumn::take) + .collect::, Error>>() + .map_err(|error| self.refused(error))?; + let rows = std::mem::take(&mut self.buffered); + let writer = self.writer.as_mut().ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; + + writer + .write(rows, &arrays) + .map_err(|error| parquet_exception(error, &self.stream, Side::Write, Surface::Lib)) + } + + fn append(&mut self, row: &Zval) -> PhpResult<()> { + if self.writer.is_none() { + return Err(exception(RUNTIME, "Writer is not open".to_string())); + } + + let row = row + .array() + .ok_or_else(|| exception(INVALID_ARGUMENT, "flow_php Parquet writer rows must be arrays".to_string()))?; + let null = Zval::new(); + + for index in 0..self.columns.len() { + let column = &mut self.columns[index]; + let value = ht_get(row, column.name.as_bytes()).unwrap_or(&null); + + if let Err(refusal) = column.cell.append(&mut column.builder, value, column.nullable, &self.classes) { + let (name, row) = (column.name.clone(), self.buffered); + + // the row is refused whole: the columns before this one drop what it appended to them + for column in &mut self.columns[..=index] { + column.builder.truncate(row); + } + + return Err(match refusal { + Refusal::Value { expected, got } => self.refused(Error::Value { + column: name, + row, + expected, + got, + }), + Refusal::Overflow => self.refused(Error::Overflow { column: name, row }), + Refusal::Php(exception) => exception, + }); + } + } + + self.buffered += 1; + + if self.buffered >= self.batch_size { + self.flush()?; + } + + Ok(()) + } +} + +#[php_impl] +impl NativeParquetRowsWriter { + /// `$schema` / `$options`: `Flow\Parquet\Engine\Arrow\SchemaConverter` / `OptionsConverter::toExtension()`; + /// `$batchSize` rows per `ParquetWriter::write`. + pub fn __construct( + stream: &Zval, + schema: &ZendHashTable, + compression: String, + options: &ZendHashTable, + batch_size: i64, + ) -> PhpResult { + let batch_size = self::batch_size(batch_size)?; + let stream = Arc::new(PhpStream::new(stream)?); + let refused = |error| parquet_exception(error, &stream, Side::Write, Surface::Lib); + let schema = options::schema(schema).map_err(refused)?; + let columns = schema + .fields() + .iter() + .map(|field| WriteColumn::new(field)) + .collect::, Error>>() + .map_err(refused)?; + let writer = ParquetWriter::open( + PhpSink::new(Arc::clone(&stream)), + schema, + options::properties(&compression, options).map_err(refused)?, + ) + .map_err(refused)?; + + Ok(Self { + writer: Some(writer), + stream, + columns, + classes: Classes::new()?, + buffered: 0, + batch_size, + }) + } + + /// A writer column the row lacks is null. + #[php(name = "writeRow")] + pub fn write_row(&mut self, row: &Zval) -> PhpResult<()> { + self.append(row) + } + + #[php(name = "writeRows")] + pub fn write_rows(&mut self, rows: &ZendHashTable) -> PhpResult<()> { + for row in rows.values() { + self.append(row)?; + } + + Ok(()) + } + + /// Buffered rows, the footer, then the stream closed. + pub fn close(&mut self) -> PhpResult<()> { + let flushed = self.flush(); + let writer = self.writer.take().ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; + flushed?; + writer.close().map_err(|error| self.refused(error))?; + + match self.stream.call("close", &mut []) { + Some(_) => Ok(()), + None => Err(self.refused(Error::Stream("close() threw".to_string()))), + } + } +} diff --git a/src/extension/flow-php-ext/src/parquet/mod.rs b/src/extension/flow-php-ext/src/parquet/mod.rs index de88406871..5335840913 100644 --- a/src/extension/flow-php-ext/src/parquet/mod.rs +++ b/src/extension/flow-php-ext/src/parquet/mod.rs @@ -2,8 +2,12 @@ //! below `etl`, the `Flow\ETL\Adapter\Parquet` surface. pub mod canonical; +pub mod cells; pub mod error; pub mod etl; +pub mod fetch; +pub mod footer; +pub mod library; pub mod options; pub mod read; pub mod sink; diff --git a/src/extension/flow-php-ext/src/parquet/read.rs b/src/extension/flow-php-ext/src/parquet/read.rs index 3d16cde0c2..8c48d6b451 100644 --- a/src/extension/flow-php-ext/src/parquet/read.rs +++ b/src/extension/flow-php-ext/src/parquet/read.rs @@ -3,18 +3,22 @@ use std::sync::Arc; -use arrow_array::{ArrayRef, RecordBatchReader}; -use arrow_schema::{DataType, FieldRef}; +use arrow_array::cast::AsArray; +use arrow_array::{make_array, Array, ArrayRef, RecordBatchReader}; +use arrow_buffer::NullBuffer; +use arrow_schema::{DataType, Field, FieldRef, Fields, Schema, SchemaRef, TimeUnit}; use parquet::arrow::arrow_reader::{ ArrowReaderMetadata, ArrowReaderOptions, ParquetRecordBatchReader, ParquetRecordBatchReaderBuilder, }; use parquet::arrow::ProjectionMask; -use parquet::basic::Compression; +use parquet::basic::{Compression, Type}; use parquet::file::metadata::{PageIndexPolicy, ParquetMetaData, ParquetMetaDataReader}; +use parquet::schema::types::SchemaDescriptor; use crate::parquet::canonical::{canonical, canonical_type}; use crate::parquet::error::Error; -use crate::parquet::source::PhpSource; +use crate::parquet::fetch::ChunkFetch; +use crate::parquet::source::ReadAt; /// The row groups overlapping [offset, offset + limit) and the rows to skip in the first of them. #[derive(Debug, PartialEq, Eq)] @@ -50,47 +54,110 @@ impl ReadPlan { } } +/// A projected column: a root name, or a path through structs ("structure.int64") - the root first, then the child +/// names down to the column. +struct Projected { + path: Vec, + field: FieldRef, +} + +impl Projected { + /// A root named `name` as it is; else `name` as a path whose every segment but the last is a struct. + fn resolve(schema: &Schema, name: &str) -> Result { + if let Ok(root) = schema.field_with_name(name) { + return Ok(Self { + path: vec![name.to_string()], + field: Arc::new(root.clone()), + }); + } + + let missing = || Error::MissingColumn(name.to_string()); + let mut segments = name.split('.'); + let root = segments.next().ok_or_else(missing)?; + let mut field = schema.field_with_name(root).map_err(|_| missing())?; + let mut nullable = field.is_nullable(); + let mut path = vec![root.to_string()]; + + for segment in segments { + field = match field.data_type() { + DataType::Struct(children) => children.find(segment).ok_or_else(missing)?.1, + DataType::List(_) | DataType::LargeList(_) | DataType::FixedSizeList(_, _) | DataType::Map(_, _) => { + return Err(Error::Unsupported { + column: name.to_string(), + parquet: "a path into LIST/MAP".to_string(), + }) + } + _ => return Err(missing()), + }; + nullable |= field.is_nullable(); + path.push(segment.to_string()); + } + + Ok(Self { + path, + field: Arc::new(field.clone().with_name(name).with_nullable(nullable)), + }) + } + + fn reads_leaf(&self, parts: &[String]) -> bool { + parts.starts_with(&self.path) + } +} + pub struct ParquetReader { batches: ParquetRecordBatchReader, + /// Each column's field as the file stores it, named as it was asked for. fields: Vec, /// `canonical_type()` of each of `fields`. types: Vec, - /// Where each of `fields` sits in the projected batches. - positions: Vec, + /// Where each of `fields` sits in the projected batches: its root, then the struct children down to it. + positions: Vec<(usize, Vec)>, } impl ParquetReader { - /// `meta`: the footer `plan` was built from (`PhpSource::metadata()`); the page index is read on top of it only - /// when the plan skips rows inside its first row group. - pub fn open( - source: PhpSource, - meta: ParquetMetaData, + /// `source`: the file's bytes (`PhpStream`), `size` long; `meta`: its footer, which `plan` was built from. Only + /// the projected column chunks of the planned row groups are fetched (`ChunkFetch`); the page index is read on a + /// copy of `meta`, only when the plan skips rows inside its first row group. + pub fn open( + source: Arc, + size: u64, + meta: &Arc, columns: &[String], plan: ReadPlan, batch_size: usize, ) -> Result { - let meta = if plan.skip > 0 { - let mut reader = ParquetMetaDataReader::new_with_metadata(meta).with_page_index_policy(PageIndexPolicy::Optional); - reader.read_page_indexes(&source)?; - reader.finish()? - } else { - meta + let inferred = ArrowReaderMetadata::try_new(Arc::clone(meta), ArrowReaderOptions::new())?; + let options = match int96_hint(inferred.schema(), meta.file_metadata().schema_descr()) { + Some(hint) => ArrowReaderOptions::new().with_schema(hint), + None => ArrowReaderOptions::new(), }; - let meta = ArrowReaderMetadata::try_new(Arc::new(meta), ArrowReaderOptions::new())?; - let schema = meta.schema(); - let roots = columns + let schema = ArrowReaderMetadata::try_new(Arc::clone(meta), options.clone())?.schema().clone(); + let projected = columns .iter() - .map(|name| schema.index_of(name).map_err(|_| Error::MissingColumn(name.clone()))) + .map(|name| Projected::resolve(&schema, name)) .collect::, _>>()?; - let fields = roots.iter().map(|root| Arc::clone(&schema.fields()[*root])).collect::>(); + let fields = projected.iter().map(|column| Arc::clone(&column.field)).collect::>(); let types = fields.iter().map(|field| canonical_type(field)).collect::, _>>()?; - if let Some(codec) = unsupported_codec(meta.metadata(), &plan.row_groups, &fields) { + if let Some(codec) = unsupported_codec(meta, &plan.row_groups, &projected) { return Err(codec); } - let mask = ProjectionMask::roots(meta.metadata().file_metadata().schema_descr(), roots.iter().copied()); - let mut builder = ParquetRecordBatchReaderBuilder::new_with_metadata(source, meta) + let descr = meta.file_metadata().schema_descr(); + let leaves = (0..descr.num_columns()) + .filter(|leaf| projected.iter().any(|column| column.reads_leaf(descr.column(*leaf).path().parts()))) + .collect::>(); + let fetch = ChunkFetch::new(source, size, meta, &plan.row_groups, &leaves); + let meta = if plan.skip > 0 { + let mut reader = ParquetMetaDataReader::new_with_metadata(meta.as_ref().clone()) + .with_page_index_policy(PageIndexPolicy::Optional); + reader.read_page_indexes(&fetch)?; + ArrowReaderMetadata::try_new(Arc::new(reader.finish()?), options)? + } else { + ArrowReaderMetadata::try_new(Arc::clone(meta), options)? + }; + let mask = ProjectionMask::leaves(meta.metadata().file_metadata().schema_descr(), leaves); + let mut builder = ParquetRecordBatchReaderBuilder::new_with_metadata(fetch, meta) .with_row_groups(plan.row_groups) .with_projection(mask) .with_batch_size(batch_size); @@ -104,11 +171,16 @@ impl ParquetReader { } let batches = builder.build()?; - let projected = batches.schema(); - let positions = columns - .iter() - .map(|name| projected.index_of(name).map_err(|_| Error::MissingColumn(name.clone()))) - .collect::, _>>()?; + let schema = batches.schema(); + let positions = projected + .into_iter() + .map(|mut column| { + let root = schema.index_of(&column.path[0]).map_err(|_| Error::MissingColumn(column.field.name().clone()))?; + column.path.remove(0); + + Ok((root, column.path)) + }) + .collect::, Error>>()?; Ok(Self { batches, @@ -137,24 +209,82 @@ impl ParquetReader { self.fields .iter() .zip(&self.positions) - .map(|(field, position)| canonical(field, batch.column(*position))) + .map(|(field, (root, children))| canonical(field, &child(batch.column(*root), children)?)) .collect::, _>>() .map(|columns| (batch.num_rows(), columns)), ) } } +/// The struct child at `path` under `array`, null wherever a struct above it is. +fn child(array: &ArrayRef, path: &[String]) -> Result { + let mut array = Arc::clone(array); + + for name in path { + let structure = array.as_struct(); + let child = structure + .column_by_name(name) + .ok_or_else(|| Error::MissingColumn(name.clone()))?; + + array = match NullBuffer::union(structure.nulls(), child.nulls()) { + Some(nulls) if structure.nulls().is_some() => { + make_array(child.to_data().into_builder().nulls(Some(nulls)).build()?) + } + _ => Arc::clone(child), + }; + } + + Ok(array) +} + +/// The inferred schema with every INT96 leaf read as `Timestamp(µs, "UTC")` - exact over years 1 to 9999, where +/// arrow-rs's default nanoseconds wrap outside 1677-2262; `None` without INT96 leaves. +fn int96_hint(schema: &SchemaRef, descr: &SchemaDescriptor) -> Option { + let mut leaf = 0; + let mut hinted = false; + let fields = schema + .fields() + .iter() + .map(|field| int96_hinted(field, descr, &mut leaf, &mut hinted)) + .collect::(); + + hinted.then(|| Arc::new(Schema::new_with_metadata(fields, schema.metadata().clone()))) +} + +/// `field` with its INT96 leaves hinted; `leaf` counts the Parquet leaves `field`'s arrow leaves stand for, in order. +fn int96_hinted(field: &FieldRef, descr: &SchemaDescriptor, leaf: &mut usize, hinted: &mut bool) -> FieldRef { + let mut hint = |field: &FieldRef| int96_hinted(field, descr, leaf, hinted); + let data_type = match field.data_type() { + DataType::Struct(children) => DataType::Struct(children.iter().map(&mut hint).collect()), + DataType::List(element) => DataType::List(hint(element)), + DataType::LargeList(element) => DataType::LargeList(hint(element)), + DataType::FixedSizeList(element, size) => DataType::FixedSizeList(hint(element), *size), + DataType::Map(entries, sorted) => DataType::Map(hint(entries), *sorted), + _ => { + let index = *leaf; + *leaf += 1; + + if index >= descr.num_columns() || descr.column(index).physical_type() != Type::INT96 { + return Arc::clone(field); + } + + *hinted = true; + DataType::Timestamp(TimeUnit::Microsecond, Some("UTC".into())) + } + }; + + Arc::new(Field::clone(field).with_data_type(data_type)) +} + /// A codec the parquet crate is built without, in a projected column chunk of the planned row groups. -fn unsupported_codec(meta: &ParquetMetaData, row_groups: &[usize], fields: &[FieldRef]) -> Option { +fn unsupported_codec(meta: &ParquetMetaData, row_groups: &[usize], columns: &[Projected]) -> Option { row_groups.iter().find_map(|group| { meta.row_group(*group).columns().iter().find_map(|chunk| { - let root = chunk.column_path().parts().first()?; + let column = columns.iter().find(|column| column.reads_leaf(chunk.column_path().parts()))?; - (chunk.compression() == Compression::LZO && fields.iter().any(|field| field.name() == root)).then(|| { - Error::Unsupported { - column: root.clone(), - parquet: "LZO".to_string(), - } + (chunk.compression() == Compression::LZO).then(|| Error::Unsupported { + column: column.field.name().clone(), + parquet: "LZO".to_string(), }) }) }) @@ -164,16 +294,26 @@ fn unsupported_codec(meta: &ParquetMetaData, row_groups: &[usize], fields: &[Fie mod tests { use std::sync::Arc; - use arrow_array::{Int64Array, RecordBatch, StringArray}; - use arrow_schema::{DataType, Field, FieldRef, Schema}; + use arrow_array::builder::{Int64Builder, MapBuilder, StringBuilder}; + use arrow_array::cast::AsArray; + use arrow_array::types::TimestampMicrosecondType; + use arrow_array::{Array, ArrayRef, Int64Array, ListArray, RecordBatch, StringArray, StructArray}; + use arrow_buffer::NullBuffer; + use arrow_schema::{DataType, Field, Fields, Schema, TimeUnit}; use bytes::Bytes; use parquet::arrow::ArrowWriter; use parquet::basic::Compression; + use parquet::data_type::{Int64Type, Int96, Int96Type}; use parquet::file::metadata::{ParquetMetaData, ParquetMetaDataReader}; use parquet::file::properties::WriterProperties; + use parquet::file::writer::SerializedFileWriter; + use parquet::schema::parser::parse_message_type; + use parquet::schema::types::SchemaDescriptor; - use super::{unsupported_codec, ReadPlan}; + use super::{int96_hint, unsupported_codec, ParquetReader, Projected, ReadPlan}; use crate::parquet::error::Error; + use crate::parquet::footer::Footer; + use crate::parquet::source::fake::Counting; fn eight_groups_of_8192() -> parquet::file::metadata::ParquetMetaData { let schema = Arc::new(Schema::new(vec![Field::new("id", DataType::Int64, false)])); @@ -266,14 +406,265 @@ mod tests { #[test] fn an_lzo_column_chunk_is_refused_when_projected() { let meta = with_lzo_names(); - let name: FieldRef = Arc::new(Field::new("name", DataType::Utf8, true)); - let id: FieldRef = Arc::new(Field::new("id", DataType::Int64, false)); + let schema = Schema::new(vec![ + Field::new("id", DataType::Int64, false), + Field::new("name", DataType::Utf8, true), + ]); + let column = |name: &str| Projected::resolve(&schema, name).unwrap(); assert!(matches!( - unsupported_codec(&meta, &[0], &[Arc::clone(&id), name]), + unsupported_codec(&meta, &[0], &[column("id"), column("name")]), Some(Error::Unsupported { column, parquet }) if column == "name" && parquet == "LZO" )); - assert!(unsupported_codec(&meta, &[0], &[id]).is_none()); + assert!(unsupported_codec(&meta, &[0], &[column("id")]).is_none()); + } + + fn open(file: Vec, columns: &[&str], offset: u64, limit: Option) -> Result<(ParquetReader, Arc), Error> { + let footer = Footer::read(&Bytes::from(file.clone()))?; + let source = Arc::new(Counting::new(file)); + let size = source.data.len() as u64; + let columns = columns.iter().map(|column| column.to_string()).collect::>(); + let plan = ReadPlan::new(footer.meta(), offset, limit); + + Ok((ParquetReader::open(Arc::clone(&source), size, footer.meta(), &columns, plan, 1_024)?, source)) + } + + fn read(file: Vec, columns: &[&str]) -> Result, Error> { + let (mut reader, _) = open(file, columns, 0, None)?; + let (_, arrays) = reader.next().unwrap()?; + + assert!(reader.next().is_none()); + + Ok(arrays) + } + + fn int96(days_since_epoch: i64, nanos_of_day: i64) -> Int96 { + let mut value = Int96::new(); + value.set_data(nanos_of_day as u32, (nanos_of_day >> 32) as u32, (days_since_epoch + 2_440_588) as u32); + + value + } + + /// `ts` INT96 flat, `nanos` INT64 TIMESTAMP(NANOS), `st.ts` INT96 in a struct, `l` a list of INT96. + fn int96_file() -> Vec { + let schema = Arc::new( + parse_message_type( + "message s { optional int96 ts; optional int64 nanos (TIMESTAMP(NANOS,false)); \ + optional group st { optional int96 ts; } \ + optional group l (LIST) { repeated group list { optional int96 element; } } }", + ) + .unwrap(), + ); + let mut file = Vec::new(); + let mut writer = SerializedFileWriter::new(&mut file, schema, Arc::new(WriterProperties::builder().build())).unwrap(); + let mut group = writer.next_row_group().unwrap(); + let first = int96(-719_162, 1_000); + let last = int96(-3_653, 86_399_999_999_999); + + let mut column = group.next_column().unwrap().unwrap(); + column.typed::().write_batch(&[first, last], Some(&[1, 1]), None).unwrap(); + column.close().unwrap(); + let mut column = group.next_column().unwrap().unwrap(); + column.typed::().write_batch(&[1_500, -1_500], Some(&[1, 1]), None).unwrap(); + column.close().unwrap(); + let mut column = group.next_column().unwrap().unwrap(); + column.typed::().write_batch(&[first, last], Some(&[2, 2]), None).unwrap(); + column.close().unwrap(); + let mut column = group.next_column().unwrap().unwrap(); + column.typed::().write_batch(&[first, last], Some(&[3, 3]), Some(&[0, 0])).unwrap(); + column.close().unwrap(); + group.close().unwrap(); + writer.close().unwrap(); + + file + } + + fn micros(array: &ArrayRef) -> Vec> { + array.as_primitive::().iter().collect() + } + + #[test] + fn int96_leaves_are_read_as_exact_microseconds() { + let arrays = read(int96_file(), &["ts", "nanos", "st", "l"]).unwrap(); + let expected = vec![Some(-62_135_596_799_999_999), Some(-315_532_800_000_001)]; + + assert_eq!(micros(&arrays[0]), expected); + assert_eq!(micros(&arrays[1]), vec![Some(1), Some(-2)]); + assert_eq!(micros(arrays[2].as_struct().column(0)), expected); + assert_eq!(micros(arrays[3].as_list::().values()), expected); + } + + #[test] + fn int96_is_not_hinted_without_int96_leaves() { + let schema = parse_message_type("message s { optional int64 nanos (TIMESTAMP(NANOS,false)); }").unwrap(); + let descr = SchemaDescriptor::new(Arc::new(schema)); + let inferred = Arc::new(Schema::new(vec![Field::new( + "nanos", + DataType::Timestamp(TimeUnit::Nanosecond, None), + true, + )])); + + assert!(int96_hint(&inferred, &descr).is_none()); + } + + fn struct_file() -> Vec { + let children = Fields::from(vec![ + Field::new("int64", DataType::Int64, true), + Field::new("name", DataType::Utf8, false), + ]); + let structure = StructArray::new( + children.clone(), + vec![ + Arc::new(Int64Array::from(vec![Some(1), Some(2), None])), + Arc::new(StringArray::from(vec!["a", "b", "c"])), + ], + Some(NullBuffer::from(vec![true, false, true])), + ); + let list = ListArray::from_iter_primitive::(vec![Some(vec![Some(1)]); 3]); + let mut map = MapBuilder::new(None, StringBuilder::new(), Int64Builder::new()); + for _ in 0..3 { + map.keys().append_value("k"); + map.values().append_value(1); + map.append(true).unwrap(); + } + let map = map.finish(); + let schema = Arc::new(Schema::new(vec![ + Field::new("structure", DataType::Struct(children), true), + Field::new("list", list.data_type().clone(), true), + Field::new("map", map.data_type().clone(), true), + ])); + let mut file = Vec::new(); + let mut writer = ArrowWriter::try_new(&mut file, Arc::clone(&schema), None).unwrap(); + writer + .write(&RecordBatch::try_new(schema, vec![Arc::new(structure), Arc::new(list), Arc::new(map)]).unwrap()) + .unwrap(); + writer.close().unwrap(); + + file + } + + #[test] + fn a_struct_path_reads_the_child_null_under_a_null_struct() { + let arrays = read(struct_file(), &["structure.int64", "structure.name"]).unwrap(); + + assert_eq!( + arrays[0].as_primitive::().iter().collect::>(), + vec![Some(1), None, None] + ); + assert_eq!( + arrays[1].as_binary::().iter().collect::>(), + vec![Some(&b"a"[..]), None, Some(&b"c"[..])] + ); + } + + #[test] + fn a_struct_path_is_named_as_asked() { + let (reader, _) = open(struct_file(), &["structure.name"], 0, None).unwrap(); + + assert_eq!(reader.fields()[0].name(), "structure.name"); + assert!(reader.fields()[0].is_nullable()); + assert_eq!(reader.types(), &[DataType::Binary]); + } + + #[test] + fn a_path_into_a_list_or_a_map_is_refused() { + for path in ["list.list.element", "list.item", "map.key_value.key", "map.entries"] { + assert!(matches!( + read(struct_file(), &[path]), + Err(Error::Unsupported { column, parquet }) if column == path && parquet == "a path into LIST/MAP" + )); + } + } + + #[test] + fn a_path_that_names_nothing_is_missing() { + for path in ["structure.missing", "missing.int64", "structure.int64.deeper"] { + assert!(matches!(read(struct_file(), &[path]), Err(Error::MissingColumn(column)) if column == path)); + } + } + + /// Columns `a`, `b`, `c` (Int64) in four row groups of 100 rows. + fn four_groups() -> Vec { + let schema = Arc::new(Schema::new(vec![ + Field::new("a", DataType::Int64, false), + Field::new("b", DataType::Int64, false), + Field::new("c", DataType::Int64, false), + ])); + let column = || Arc::new(Int64Array::from_iter_values(0..400)) as ArrayRef; + let mut file = Vec::new(); + let mut writer = ArrowWriter::try_new( + &mut file, + Arc::clone(&schema), + Some(WriterProperties::builder().set_max_row_group_row_count(Some(100)).build()), + ) + .unwrap(); + writer.write(&RecordBatch::try_new(schema, vec![column(), column(), column()]).unwrap()).unwrap(); + writer.close().unwrap(); + + file + } + + /// The compressed bytes of `columns`' chunks in `groups`. + fn chunk_bytes(file: &[u8], groups: &[usize], columns: &[usize]) -> usize { + let meta = Footer::read(&Bytes::from(file.to_vec())).unwrap(); + + groups + .iter() + .flat_map(|group| columns.iter().map(move |column| (*group, *column))) + .map(|(group, column)| meta.meta().row_group(group).column(column).byte_range().1 as usize) + .sum() + } + + fn drained(mut reader: ParquetReader) -> usize { + let mut rows = 0; + + while let Some(batch) = reader.next() { + rows += batch.unwrap().0; + } + + rows + } + + #[test] + fn a_full_read_fetches_each_row_group_once() { + let file = four_groups(); + let (reader, source) = open(file.clone(), &["a", "b", "c"], 0, None).unwrap(); + + assert_eq!(drained(reader), 400); + assert_eq!(source.counted(), (4, chunk_bytes(&file, &[0, 1, 2, 3], &[0, 1, 2]))); + } + + #[test] + fn a_projected_read_fetches_only_the_projected_chunks() { + let file = four_groups(); + let (reader, source) = open(file.clone(), &["b"], 0, None).unwrap(); + + assert_eq!(drained(reader), 400); + assert_eq!(source.counted(), (4, chunk_bytes(&file, &[0, 1, 2, 3], &[1]))); + } + + #[test] + fn an_offset_read_fetches_only_the_planned_row_group_and_the_page_index() { + let file = four_groups(); + let (reader, source) = open(file.clone(), &["a", "c"], 250, Some(10)).unwrap(); + let meta = Footer::read(&Bytes::from(file.clone())).unwrap(); + let index = meta + .meta() + .row_groups() + .iter() + .flat_map(|group| group.columns()) + .map(|chunk| { + chunk.column_index_length().unwrap_or(0) as usize + chunk.offset_index_length().unwrap_or(0) as usize + }) + .sum::(); + + assert_eq!(drained(reader), 10); + + let (reads, bytes) = source.counted(); + + assert!(reads <= 3, "{reads} reads"); + assert!(bytes >= chunk_bytes(&file, &[2], &[0, 2]), "{bytes} bytes"); + assert!(bytes <= chunk_bytes(&file, &[2], &[0, 1, 2]) + index, "{bytes} bytes"); } #[test] diff --git a/src/extension/flow-php-ext/src/parquet/source.rs b/src/extension/flow-php-ext/src/parquet/source.rs index 140135088a..2de9a2ba45 100644 --- a/src/extension/flow-php-ext/src/parquet/source.rs +++ b/src/extension/flow-php-ext/src/parquet/source.rs @@ -92,6 +92,7 @@ impl ReadAt for PhpStream { } } +#[derive(Clone)] pub struct PhpSource { stream: Arc, size: u64, @@ -110,11 +111,6 @@ impl PhpSource { size: u64::try_from(size).map_err(|_| Error::Stream(format!("size() returned {size}")))?, }) } - - /// The footer, without the page index. - pub fn metadata(&self) -> Result { - Ok(parquet::file::metadata::ParquetMetaDataReader::new().parse_and_finish(self)?) - } } impl Length for PhpSource { @@ -189,31 +185,35 @@ impl Read for WindowedRead { } } +/// A `ReadAt` over bytes in memory that counts the reads made through it and the bytes they returned. #[cfg(test)] -mod tests { - use std::io::Read; +pub mod fake { use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::Arc; use bytes::Bytes; use parquet::errors::ParquetError; - use super::{exact, ReadAt, WindowedRead, WINDOW}; + use super::ReadAt; - struct Counting { - data: Vec, + pub struct Counting { + pub data: Bytes, reads: AtomicUsize, bytes: AtomicUsize, } impl Counting { - fn new(size: usize) -> Self { + pub fn new(data: Vec) -> Self { Self { - data: (0..size).map(|i| i as u8).collect(), + data: Bytes::from(data), reads: AtomicUsize::new(0), bytes: AtomicUsize::new(0), } } + + /// (reads, bytes) so far. + pub fn counted(&self) -> (usize, usize) { + (self.reads.load(Ordering::Relaxed), self.bytes.load(Ordering::Relaxed)) + } } impl ReadAt for Counting { @@ -223,68 +223,83 @@ mod tests { self.reads.fetch_add(1, Ordering::Relaxed); self.bytes.fetch_add(end - start, Ordering::Relaxed); - Ok(Bytes::copy_from_slice(&self.data[start..end])) + Ok(self.data.slice(start..end)) } } +} + +#[cfg(test)] +mod tests { + use std::io::Read; + use std::sync::Arc; + + use parquet::errors::ParquetError; + + use super::fake::Counting; + use super::{exact, WindowedRead, WINDOW}; + + fn sized(size: usize) -> Counting { + Counting::new((0..size).map(|i| i as u8).collect()) + } #[test] fn windowed_read_pulls_one_window_for_a_small_read() { - let source = Arc::new(Counting::new(10 * WINDOW)); + let source = Arc::new(sized(10 * WINDOW)); let mut read = WindowedRead::new(Arc::clone(&source), 100, source.data.len() as u64); let mut header = [0u8; 32]; read.read_exact(&mut header).unwrap(); assert_eq!(header.to_vec(), source.data[100..132].to_vec()); - assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (1, WINDOW)); + assert_eq!(source.counted(), (1, WINDOW)); } #[test] fn windowed_read_pulls_the_next_window_only_when_the_first_is_used_up() { - let source = Arc::new(Counting::new(10 * WINDOW)); + let source = Arc::new(sized(10 * WINDOW)); let mut read = WindowedRead::new(Arc::clone(&source), 0, source.data.len() as u64); let mut buffer = vec![0u8; WINDOW + 1]; read.read_exact(&mut buffer[..WINDOW]).unwrap(); - assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (1, WINDOW)); + assert_eq!(source.counted(), (1, WINDOW)); read.read_exact(&mut buffer[WINDOW..]).unwrap(); assert_eq!(buffer, source.data[..WINDOW + 1].to_vec()); - assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (2, 2 * WINDOW)); + assert_eq!(source.counted(), (2, 2 * WINDOW)); } #[test] fn windowed_read_never_reads_past_the_end() { - let source = Arc::new(Counting::new(3 * WINDOW)); + let source = Arc::new(sized(3 * WINDOW)); let mut read = WindowedRead::new(Arc::clone(&source), 3 * WINDOW as u64 - 10, 3 * WINDOW as u64); let mut rest = Vec::new(); read.read_to_end(&mut rest).unwrap(); assert_eq!(rest, source.data[3 * WINDOW - 10..].to_vec()); - assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (1, 10)); + assert_eq!(source.counted(), (1, 10)); } #[test] fn exact_reads_the_length_asked_in_one_read() { - let source = Counting::new(10 * WINDOW); + let source = sized(10 * WINDOW); assert_eq!(exact(&source, 5, 3 * WINDOW).unwrap().to_vec(), source.data[5..5 + 3 * WINDOW].to_vec()); - assert_eq!((source.reads.load(Ordering::Relaxed), source.bytes.load(Ordering::Relaxed)), (1, 3 * WINDOW)); + assert_eq!(source.counted(), (1, 3 * WINDOW)); } #[test] fn exact_refuses_a_short_read() { - let source = Counting::new(100); + let source = sized(100); assert!(matches!(exact(&source, 90, 20), Err(ParquetError::EOF(_)))); } #[test] fn exact_reads_nothing_for_zero_bytes() { - let source = Counting::new(100); + let source = sized(100); assert!(exact(&source, 0, 0).unwrap().is_empty()); - assert_eq!(source.reads.load(Ordering::Relaxed), 0); + assert_eq!(source.counted().0, 0); } } diff --git a/src/extension/flow-php-ext/src/render.rs b/src/extension/flow-php-ext/src/render.rs index e5814adf42..5d4b29d32a 100644 --- a/src/extension/flow-php-ext/src/render.rs +++ b/src/extension/flow-php-ext/src/render.rs @@ -176,44 +176,89 @@ pub enum Side { Write, } +/// Which API the refusal surfaces through: `Flow\ETL\Adapter\Parquet` or `Flow\Parquet`. +#[derive(Clone, Copy)] +pub enum Surface { + Etl, + Lib, +} + +const LIB_RUNTIME: &str = "Flow\\Parquet\\Exception\\RuntimeException"; +const LIB_VALIDATION: &str = "Flow\\Parquet\\Exception\\ValidationException"; +const LIB_INVALID_ARGUMENT: &str = "Flow\\Parquet\\Exception\\InvalidArgumentException"; + /// A Parquet core refusal; an exception the stream threw while the core called it surfaces as itself. -pub fn parquet_exception(error: ParquetError, stream: &PhpStream, side: Side) -> PhpException { +pub fn parquet_exception(error: ParquetError, stream: &PhpStream, side: Side, surface: Surface) -> PhpException { if let Some(mut thrown) = stream.thrown() { return transparent_exception(&mut thrown); } + let (runtime, validation, arguments) = match surface { + Surface::Etl => (RUNTIME, RUNTIME, INVALID_ARGUMENT), + Surface::Lib => (LIB_RUNTIME, LIB_VALIDATION, LIB_INVALID_ARGUMENT), + }; + let failure = |message: String| match surface { + Surface::Etl => ext_exception(message), + Surface::Lib => exception(LIB_RUNTIME, message), + }; + match (error, side) { (ParquetError::Unsupported { column, parquet }, Side::Read) => exception( - RUNTIME, + runtime, format!( - "Parquet column \"{column}\" ({parquet}) is not supported by the flow_php Parquet reader; read the file \ - with from_parquet($path, engine: new \\Flow\\Parquet\\Engine\\PhpParquetEngine())" + "Parquet column \"{column}\" ({parquet}) is not supported by the flow_php Parquet reader; {}", + match surface { + Surface::Etl => { + "read the file with from_parquet($path, engine: new \\Flow\\Parquet\\Engine\\PhpParquetEngine())" + } + Surface::Lib => "read the file with \\Flow\\Parquet\\Reader::php()", + } ), ), (ParquetError::Unsupported { column, parquet }, Side::Write) => exception( - RUNTIME, + runtime, format!( - "Parquet column \"{column}\" ({parquet}) is not supported by the flow_php Parquet writer; write the file \ - with to_parquet($path, engine: new \\Flow\\Parquet\\Engine\\PhpParquetEngine())" + "Parquet column \"{column}\" ({parquet}) is not supported by the flow_php Parquet writer; {}", + match surface { + Surface::Etl => { + "write the file with to_parquet($path, engine: new \\Flow\\Parquet\\Engine\\PhpParquetEngine())" + } + Surface::Lib => "write it with \\Flow\\Parquet\\Writer::php()", + } ), ), (ParquetError::Overflow { column, row }, _) => exception( - RUNTIME, + runtime, format!("Parquet column \"{column}\" row {row} holds a value out of the range flow_php stores it in"), ), (ParquetError::InvalidUtf8 { column, row }, _) => exception( - RUNTIME, + runtime, format!( "Parquet column \"{column}\" row {row} holds a string that is not valid UTF-8; Parquet STRING columns \ require UTF-8" ), ), - (ParquetError::MissingColumn(name), _) => invalid_argument(format!("Parquet file has no column \"{name}\"")), - (ParquetError::Options(message), _) => invalid_argument(message), - (ParquetError::Stream(message), _) => ext_exception(format!("flow_php Parquet stream {message}")), - (ParquetError::Parquet(error), Side::Read) => ext_exception(format!("flow_php failed to read Parquet: {error}")), - (ParquetError::Arrow(error), Side::Read) => ext_exception(format!("flow_php failed to read Parquet: {error}")), - (ParquetError::Parquet(error), Side::Write) => ext_exception(format!("flow_php failed to write Parquet: {error}")), - (ParquetError::Arrow(error), Side::Write) => ext_exception(format!("flow_php failed to write Parquet: {error}")), + (ParquetError::Length { column, row, expected }, _) => exception( + runtime, + format!("Parquet column \"{column}\" row {row} holds a value that is not {expected} bytes long"), + ), + (ParquetError::Value { column, row, expected, got }, _) => { + exception(validation, format!("Column \"{column}\" row {row}: expected {expected}, got {got}")) + } + (ParquetError::MapKey { column, key }, _) => exception( + arguments, + format!("Map key of Parquet column \"{column}\" must be int or string, got {key}"), + ), + (ParquetError::MissingColumn(name), _) => exception(arguments, format!("Parquet file has no column \"{name}\"")), + (ParquetError::Options(message), _) => exception(arguments, message), + (ParquetError::NotParquet(message), _) => match surface { + Surface::Etl => failure(format!("flow_php failed to read Parquet: {message}")), + Surface::Lib => exception(arguments, format!("Given file is not valid Parquet file: {message}")), + }, + (ParquetError::Stream(message), _) => failure(format!("flow_php Parquet stream {message}")), + (ParquetError::Parquet(error), Side::Read) => failure(format!("flow_php failed to read Parquet: {error}")), + (ParquetError::Arrow(error), Side::Read) => failure(format!("flow_php failed to read Parquet: {error}")), + (ParquetError::Parquet(error), Side::Write) => failure(format!("flow_php failed to write Parquet: {error}")), + (ParquetError::Arrow(error), Side::Write) => failure(format!("flow_php failed to write Parquet: {error}")), } } diff --git a/src/extension/flow-php-ext/src/thrift.rs b/src/extension/flow-php-ext/src/thrift.rs new file mode 100644 index 0000000000..c2d10bab0c --- /dev/null +++ b/src/extension/flow-php-ext/src/thrift.rs @@ -0,0 +1,420 @@ +//! Thrift compact-protocol bytes as the PHP objects of the classes the Thrift compiler generates: each class's static +//! `$_TSPEC` says which field id is which property and of which type, as the generated `read()` does. No Parquet +//! knowledge here. + +use std::collections::HashMap; +use std::rc::Rc; + +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::{ArrayKey, ZendHashTable, ZendObject, Zval}; +use ext_php_rs::zend::ClassEntry; + +use crate::ctx::{self, find_class, property_offset, zval_long, zval_str}; +use crate::exception::ext_exception; + +/// Nesting deeper than this is refused instead of recursing further. +const DEPTH: usize = 64; + +// the compact protocol's type ids (field headers, list headers) +const BOOLEAN_TRUE: u8 = 1; +const BOOLEAN_FALSE: u8 = 2; +const BYTE: u8 = 3; +const I16: u8 = 4; +const I32: u8 = 5; +const I64: u8 = 6; +const DOUBLE: u8 = 7; +const BINARY: u8 = 8; +const LIST: u8 = 9; +const SET: u8 = 10; +const MAP: u8 = 11; +const STRUCT: u8 = 12; + +/// A `$_TSPEC` field type; a struct is the index of its class in `Specs`. +enum Value { + Bool, + Byte, + I16, + I32, + I64, + Double, + String, + Struct(usize), + List(Box), +} + +impl Value { + /// Whether a field of this type arrives as compact type `wire`; any other is skipped, as the generated `read()`. + fn arrives_as(&self, wire: u8) -> bool { + match self { + Value::Bool => wire == BOOLEAN_TRUE || wire == BOOLEAN_FALSE, + Value::Byte => wire == BYTE, + Value::I16 => wire == I16, + Value::I32 => wire == I32, + Value::I64 => wire == I64, + Value::Double => wire == DOUBLE, + Value::String => wire == BINARY, + Value::Struct(_) => wire == STRUCT, + Value::List(_) => wire == LIST, + } + } +} + +struct Class { + ce: &'static ClassEntry, + /// By field id: the property's slot offset and its type. + fields: Vec>, +} + +/// Every class reachable from a root class, by index. +pub struct Specs { + classes: Vec, +} + +impl Specs { + /// The root class and every class its `$_TSPEC` reaches, root at index 0. + fn build(root: &str) -> Result { + let mut specs = Self { classes: Vec::new() }; + specs.class(root, &mut HashMap::new())?; + + Ok(specs) + } + + fn class(&mut self, name: &str, seen: &mut HashMap) -> Result { + let name = name.trim_start_matches('\\'); + + if let Some(index) = seen.get(name) { + return Ok(*index); + } + + let ce = find_class(name)?; + let index = self.classes.len(); + seen.insert(name.to_string(), index); + self.classes.push(Class { ce, fields: Vec::new() }); + + let spec = ce + .get_static_property::<&ZendHashTable>("_TSPEC") + .ok_or_else(|| ext_exception(format!("flow_php requires {name}::$_TSPEC to be an array")))?; + let mut fields: Vec> = Vec::new(); + + for (key, entry) in spec.iter() { + let ArrayKey::Long(id) = key else { + return Err(ext_exception(format!("flow_php requires {name}::$_TSPEC to be keyed by field id"))); + }; + let entry = entry + .array() + .ok_or_else(|| ext_exception(format!("flow_php requires {name}::$_TSPEC[{id}] to be an array")))?; + let var = entry + .get("var") + .and_then(Zval::str) + .ok_or_else(|| ext_exception(format!("flow_php requires {name}::$_TSPEC[{id}]['var']")))?; + let offset = property_offset(ce, var)?; + let value = self.value(entry, name, seen)?; + let id = usize::try_from(id) + .ok() + .filter(|id| *id <= i16::MAX as usize) + .ok_or_else(|| ext_exception(format!("flow_php requires {name}::$_TSPEC field ids in 0..=32767")))?; + + if fields.len() <= id { + fields.resize_with(id + 1, || None); + } + + fields[id] = Some((offset, value)); + } + + self.classes[index].fields = fields; + + Ok(index) + } + + /// A `$_TSPEC` entry's type (`'type'`, with `'class'` for a struct and `'elem'` for a list's element). + fn value(&mut self, entry: &ZendHashTable, class: &str, seen: &mut HashMap) -> Result { + let unsupported = |what: String| ext_exception(format!("flow_php cannot decode {class}::$_TSPEC {what}")); + + // Thrift\Type\TType + Ok(match entry.get("type").and_then(Zval::long) { + Some(2) => Value::Bool, + Some(3) => Value::Byte, + Some(4) => Value::Double, + Some(6) => Value::I16, + Some(8) => Value::I32, + Some(10) => Value::I64, + Some(11) => Value::String, + Some(12) => Value::Struct(self.class( + entry + .get("class") + .and_then(Zval::str) + .ok_or_else(|| unsupported("struct without a class".to_string()))?, + seen, + )?), + Some(15) => Value::List(Box::new( + self.value( + entry + .get("elem") + .and_then(Zval::array) + .ok_or_else(|| unsupported("list without an element".to_string()))?, + class, + seen, + )?, + )), + other => return Err(unsupported(format!("type {other:?}"))), + }) + } +} + +/// `class`'s instance decoded from `bytes`; with `field`, only that field of the root is decoded and returned (null +/// when absent), the fields before it skipped and the ones after it never read. STRUCT → object (created without its constructor, public properties set by +/// `var`), LIST → list, BOOL/BYTE/I16/I32/I64/DOUBLE/STRING (binary) → scalars; an unknown id, or a known one of another +/// type, is skipped by the compact skip rules. +pub fn decode(bytes: &[u8], class: &str, field: Option) -> Result { + let specs = match ctx::thrift_specs(class)? { + Some(specs) => specs, + None => { + let specs = Rc::new(Specs::build(class)?); + ctx::store_thrift_specs(class, &specs)?; + specs + } + }; + let mut reader = Reader { bytes, position: 0 }; + + match field { + None => reader.object(&specs, 0, 0), + Some(field) => reader.field(&specs, field), + } +} + +struct Reader<'a> { + bytes: &'a [u8], + position: usize, +} + +fn truncated() -> PhpException { + ext_exception("flow_php failed to decode thrift: the bytes end inside a value") +} + +impl Reader<'_> { + fn byte(&mut self) -> Result { + let byte = *self.bytes.get(self.position).ok_or_else(truncated)?; + self.position += 1; + + Ok(byte) + } + + fn take(&mut self, length: usize) -> Result<&[u8], PhpException> { + let end = self.position.checked_add(length).filter(|end| *end <= self.bytes.len()).ok_or_else(truncated)?; + let taken = &self.bytes[self.position..end]; + self.position = end; + + Ok(taken) + } + + fn varint(&mut self) -> Result { + let mut value = 0u64; + + for shift in (0..70).step_by(7) { + let byte = self.byte()?; + value |= u64::from(byte & 0x7f) << shift; + + if byte & 0x80 == 0 { + return Ok(value); + } + } + + Err(ext_exception("flow_php failed to decode thrift: a varint longer than 10 bytes")) + } + + fn zigzag(&mut self) -> Result { + let value = self.varint()?; + + Ok((value >> 1) as i64 ^ -((value & 1) as i64)) + } + + /// The next field's id and compact type, `None` at the struct's STOP. + fn field_header(&mut self, last: &mut i16) -> Result, PhpException> { + let header = self.byte()?; + + if header == 0 { + return Ok(None); + } + + let delta = header >> 4; + *last = if delta == 0 { + i16::try_from(self.zigzag()?).map_err(|_| ext_exception("flow_php failed to decode thrift: a field id"))? + } else { + last.wrapping_add(i16::from(delta)) + }; + + Ok(Some((*last, header & 0x0f))) + } + + /// A list or set header: its size and element type. + fn list_header(&mut self) -> Result<(usize, u8), PhpException> { + let header = self.byte()?; + let size = match header >> 4 { + 15 => usize::try_from(self.varint()?).map_err(|_| truncated())?, + size => usize::from(size), + }; + + Ok((size, header & 0x0f)) + } + + fn skip(&mut self, wire: u8, depth: usize) -> Result<(), PhpException> { + if depth > DEPTH { + return Err(ext_exception("flow_php failed to decode thrift: nested deeper than 64")); + } + + match wire { + BOOLEAN_TRUE | BOOLEAN_FALSE => {} + BYTE => { + self.byte()?; + } + I16 | I32 | I64 => { + self.varint()?; + } + DOUBLE => { + self.take(8)?; + } + BINARY => { + let length = usize::try_from(self.varint()?).map_err(|_| truncated())?; + self.take(length)?; + } + LIST | SET => { + let (size, element) = self.list_header()?; + + for _ in 0..size { + self.skip_element(element, depth + 1)?; + } + } + MAP => { + let size = usize::try_from(self.varint()?).map_err(|_| truncated())?; + + if size > 0 { + let types = self.byte()?; + + for _ in 0..size { + self.skip_element(types >> 4, depth + 1)?; + self.skip_element(types & 0x0f, depth + 1)?; + } + } + } + STRUCT => { + let mut last = 0; + + while let Some((_, wire)) = self.field_header(&mut last)? { + self.skip(wire, depth + 1)?; + } + } + other => return Err(ext_exception(format!("flow_php failed to decode thrift: compact type {other}"))), + } + + Ok(()) + } + + /// A container element: a bool is one byte there, not a field-header type. + fn skip_element(&mut self, wire: u8, depth: usize) -> Result<(), PhpException> { + match wire { + BOOLEAN_TRUE | BOOLEAN_FALSE => self.byte().map(|_| ()), + wire => self.skip(wire, depth), + } + } + + /// A value of type `value` that arrived as `wire`; `element`: inside a list, where a bool is a byte. + fn value(&mut self, specs: &Specs, value: &Value, wire: u8, element: bool, depth: usize) -> Result, PhpException> { + let mut zv = Zval::new(); + + match value { + Value::Bool => zv.set_bool(if element { self.byte()? == BOOLEAN_TRUE } else { wire == BOOLEAN_TRUE }), + Value::Byte => zv = zval_long(i64::from(self.byte()? as i8)), + Value::I16 | Value::I32 | Value::I64 => zv = zval_long(self.zigzag()?), + Value::Double => { + let bytes = self.take(8)?; + zv.set_double(f64::from_le_bytes(bytes.try_into().map_err(|_| truncated())?)); + } + Value::String => { + let length = usize::try_from(self.varint()?).map_err(|_| truncated())?; + zv = zval_str(self.take(length)?); + } + Value::Struct(class) => zv = self.object(specs, *class, depth + 1)?, + Value::List(item) => { + let (size, wire) = self.list_header()?; + + if !item.arrives_as(wire) { + for _ in 0..size { + self.skip_element(wire, depth + 1)?; + } + + return Ok(None); + } + + let mut list = ZendHashTable::with_capacity(u32::try_from(size).unwrap_or(u32::MAX)); + + for _ in 0..size { + let value = self.value(specs, item, wire, true, depth + 1)?.unwrap_or_default(); + list.push(value) + .map_err(|e| ext_exception(format!("flow_php failed to collect a thrift list: {e:?}")))?; + } + + zv.set_hashtable(list); + } + } + + Ok(Some(zv)) + } + + /// An instance of `specs`' class `class`, its properties set from the fields that arrive. + fn object(&mut self, specs: &Specs, class: usize, depth: usize) -> Result { + if depth > DEPTH { + return Err(ext_exception("flow_php failed to decode thrift: nested deeper than 64")); + } + + let class = &specs.classes[class]; + let mut object = ZendObject::new(class.ce); + let mut last = 0; + + while let Some((id, wire)) = self.field_header(&mut last)? { + match field_of(class, id) { + Some((offset, value)) if value.arrives_as(wire) => { + if let Some(decoded) = self.value(specs, value, wire, false, depth)? { + replace_slot(&mut object, *offset, decoded); + } + } + _ => self.skip(wire, depth)?, + } + } + + let mut zv = Zval::new(); + zv.set_object(&mut object); + + Ok(zv) + } + + /// Field `field` of the root class, the fields before it skipped; null when it never arrives. + fn field(&mut self, specs: &Specs, field: i16) -> Result { + let class = &specs.classes[0]; + let mut last = 0; + + while let Some((id, wire)) = self.field_header(&mut last)? { + match field_of(class, id) { + Some((_, value)) if id == field && value.arrives_as(wire) => { + if let Some(decoded) = self.value(specs, value, wire, false, 0)? { + return Ok(decoded); + } + } + _ => self.skip(wire, 0)?, + } + } + + Ok(Zval::new()) + } +} + +fn field_of(class: &Class, id: i16) -> Option<&(u32, Value)> { + usize::try_from(id).ok().and_then(|id| class.fields.get(id)).and_then(Option::as_ref) +} + +/// Moves `value` into a declared-property slot, releasing what the slot held (null on a fresh object, an earlier +/// value when a field id repeats). +fn replace_slot(object: &mut ZendObject, offset: u32, value: Zval) { + let slot = unsafe { std::ptr::from_mut(object).cast::().add(offset as usize).cast::() }; + + drop(unsafe { std::ptr::replace(slot, value) }); +} diff --git a/src/extension/flow-php-ext/src/values.rs b/src/extension/flow-php-ext/src/values.rs index 33774e1466..b140493f1e 100644 --- a/src/extension/flow-php-ext/src/values.rs +++ b/src/extension/flow-php-ext/src/values.rs @@ -224,8 +224,8 @@ pub fn interval_from_micros(micros: i64) -> Result { Ok(zv) } -/// `Uuid::fromBytes()`: the constructor-less instance holding the lowercase 36-char form. -pub fn uuid_from_bytes(bytes: &[u8]) -> Result { +/// The lowercase 36-char form of 16 uuid bytes. +pub fn uuid_text(bytes: &[u8]) -> Vec { const HEX: &[u8; 16] = b"0123456789abcdef"; let mut text = Vec::with_capacity(36); @@ -239,9 +239,14 @@ pub fn uuid_from_bytes(bytes: &[u8]) -> Result { text.push(HEX[usize::from(byte & 0x0f)]); } + text +} + +/// `Uuid::fromBytes()`: the constructor-less instance holding the lowercase 36-char form. +pub fn uuid_from_bytes(bytes: &[u8]) -> Result { let (uuid_ce, value_slot) = ctx::uuid()?; let mut uuid = ZendObject::new(uuid_ce); - write_slot(&mut uuid, value_slot, zval_str(&text)); + write_slot(&mut uuid, value_slot, zval_str(&uuid_text(bytes))); let mut zv = Zval::new(); zv.set_object(&mut uuid); diff --git a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt index 238acf5987..c1690a0ed9 100644 --- a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt @@ -1,11 +1,13 @@ --TEST-- -NativeParquetReader reads every lib Parquet fixture as PhpParquetEngine does, or refuses it naming the engine that reads it +NativeParquetReader reads every lib Parquet fixture as PhpParquetEngine does, both refuse it, or it refuses naming the engine that reads it --SKIPIF-- --FILE-- readFrom(path($file)), + new NativeParquetFile($filesystem->readFrom(path($file))), (new SchemaConverter())->toFlow((new Reader(engine: new PhpParquetEngine()))->read($file)->schema()), $batchSize, null, @@ -51,7 +53,9 @@ foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.p $name = substr($file, strlen($fixtures) + 1) . ' ' . $batchSize; echo match (true) { + $php === $native && refused($php) => "{$name}: both refuse\n", $php === $native => "{$name}: identical\n", + refused($php) && refused($native) => "{$name}: both refuse\n", str_contains($native, 'is not supported by the flow_php Parquet reader') => "{$name}: {$native}\n", default => "{$name}: DIFFER\n php: " . substr($php, 0, 300) . "\n native: " . substr($native, 0, 300) . "\n", }; @@ -60,21 +64,21 @@ foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.p $emptylist = realpath($fixtures . '/EdgeCases/null_list.parquet'); echo outcome(static fn() => new NativeParquetReader( - $filesystem->readFrom(path($emptylist)), + new NativeParquetFile($filesystem->readFrom(path($emptylist))), schema(list_schema('emptylist', type_list(type_integer()))), 100, null, null, )), "\n"; echo outcome(static fn() => new NativeParquetReader( - $filesystem->readFrom(path($fixtures . '/multiple_pages.parquet')), + new NativeParquetFile($filesystem->readFrom(path($fixtures . '/multiple_pages.parquet'))), schema(str_schema('int64')), 100, null, null, )), "\n"; echo outcome(static fn() => new NativeParquetReader( - $filesystem->readFrom(path($fixtures . '/multiple_pages.parquet')), + new NativeParquetFile($filesystem->readFrom(path($fixtures . '/multiple_pages.parquet'))), schema(str_schema('missing')), 100, null, @@ -104,10 +108,20 @@ structs.parquet 100: identical structs.parquet 10000: identical EdgeCases/datapage_v2.snappy.parquet 100: identical EdgeCases/datapage_v2.snappy.parquet 10000: identical +EdgeCases/int96.parquet 100: both refuse +EdgeCases/int96.parquet 10000: both refuse +EdgeCases/interval.parquet 100: both refuse +EdgeCases/interval.parquet 10000: both refuse +EdgeCases/map_keys.parquet 100: both refuse +EdgeCases/map_keys.parquet 10000: both refuse EdgeCases/nonnullable.impala.parquet 100: identical EdgeCases/nonnullable.impala.parquet 10000: identical -EdgeCases/null_list.parquet 100: identical -EdgeCases/null_list.parquet 10000: identical -Flow\ETL\Exception\RuntimeException: Parquet column "emptylist" (Null) is not supported by the flow_php Parquet reader; read the file with from_parquet($path, engine: new \Flow\Parquet\Engine\PhpParquetEngine()) +EdgeCases/null_list.parquet 100: both refuse +EdgeCases/null_list.parquet 10000: both refuse +EdgeCases/uint64_overflow.parquet 100: both refuse +EdgeCases/uint64_overflow.parquet 10000: both refuse +EdgeCases/unsigned.parquet 100: identical +EdgeCases/unsigned.parquet 10000: identical +Flow\ETL\Exception\InvalidArgumentException: Parquet column "emptylist" (List(Null)) is read as List(Null), its schema type list stores List(Int64) Flow\ETL\Exception\InvalidArgumentException: Parquet column "int64" (Int64) is read as Int64, its schema type string stores Binary Flow\ETL\Exception\InvalidArgumentException: Parquet file has no column "missing" diff --git a/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt b/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt index ccfde90f89..7b12d2d945 100644 --- a/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt +++ b/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt @@ -6,6 +6,8 @@ NativeParquetReader reads offset/limit windows of an 8-row-group file, and refus readFrom(path('memory://groups.parquet')), $schema, 1000, $offset, $limit); + $reader = new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://groups.parquet'))), $schema, 1000, $offset, $limit); $ids = []; while (($batch = $reader->next()) !== null) { @@ -46,7 +48,7 @@ foreach ([[0, 10], [5399, 3], [20000, 15000], [65000, 100], [65046, 1], [65536, } foreach ([[0, null, null], [-1, null, null], [10, -1, null], [10, null, -1]] as [$batchSize, $offset, $limit]) { - echo outcome(static fn() => new NativeParquetReader($filesystem->readFrom(path('memory://groups.parquet')), $schema, $batchSize, $offset, $limit)), "\n"; + echo outcome(static fn() => new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://groups.parquet'))), $schema, $batchSize, $offset, $limit)), "\n"; } ?> --EXPECT-- diff --git a/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt index 9b29a50240..c800427d64 100644 --- a/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt @@ -6,6 +6,8 @@ NativeParquetReader and NativeParquetWriter leak neither PHP memory nor native a write(php_rows($schema, $values)); $writer->close(); - $reader = new NativeParquetReader($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, 10, 150); + $reader = new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))), $schema, 30, 10, 150); while ($reader->next() !== null) { } @@ -44,7 +46,7 @@ $cycle = static function () use ($schema, $values, $extension, $options, $mismat } try { - new NativeParquetReader($filesystem->readFrom(path('memory://leaks.parquet')), $mismatched, 30, null, null); + new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))), $mismatched, 30, null, null); throw new LogicException('a mismatched schema was accepted'); } catch (Flow\ETL\Exception\InvalidArgumentException) { } diff --git a/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt b/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt index e8555daf23..d0d723f144 100644 --- a/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt +++ b/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt @@ -6,6 +6,8 @@ Batches NativeParquetReader holds are counted by DefaultBackend::allocatedBytes( close(); gc_collect_cycles(); $before = (new DefaultBackend())->allocatedBytes(); -$reader = new NativeParquetReader($filesystem->readFrom(path('memory://held.parquet')), $schema, 1_000, null, null); +$reader = new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://held.parquet'))), $schema, 1_000, null, null); $held = []; while (($batch = $reader->next()) !== null) { diff --git a/src/extension/flow-php-ext/tests/phpt/073_parquet_lib_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/073_parquet_lib_read_parity.phpt new file mode 100644 index 0000000000..a666a638f4 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/073_parquet_lib_read_parity.phpt @@ -0,0 +1,76 @@ +--TEST-- +Reader::arrow() on flow_php reads every lib Parquet fixture as Reader::php() does, both refuse it, or it refuses naming Reader::php() +--SKIPIF-- + +--FILE-- + ParquetRows::read(Reader::php()->read($file), $batchSize)); + $native = outcome(static fn() => ParquetRows::read(Reader::arrow()->read($file), $batchSize)); + $name = substr($file, strlen($fixtures) + 1) . ' ' . $batchSize; + + echo match (true) { + refused($php) && refused($native) => "{$name}: both refuse\n", + $php === $native => "{$name}: identical\n", + refused($native) && str_contains($native, 'Reader::php()') => "{$name}: {$native}\n", + default => "{$name}: DIFFER\n php: " . substr($php, 0, 300) . "\n native: " . substr($native, 0, 300) . "\n", + }; + } +} + +$interval = $fixtures . '/EdgeCases/interval.parquet'; +echo 'interval.parquet [id]: ', outcome(static fn() => ParquetRows::read(Reader::php()->read($interval), 10, ['id'])) === outcome(static fn() => ParquetRows::read(Reader::arrow()->read($interval), 10, ['id'])) ? 'identical' : 'DIFFER', "\n"; + +$everyType = MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows()); +echo 'every type: ', outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), $everyType), 2)) === outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $everyType), 2)) ? 'identical' : 'DIFFER', "\n"; +?> +--EXPECT-- +columns.required.parquet 100: identical +columns.required.parquet 10000: identical +decimals_fixed_len.parquet 100: identical +decimals_fixed_len.parquet 10000: identical +delta_binary_acked_encoded_integers.parquet 100: identical +delta_binary_acked_encoded_integers.parquet 10000: identical +lists.parquet 100: identical +lists.parquet 10000: identical +logical_types.parquet 100: identical +logical_types.parquet 10000: identical +maps.parquet 100: identical +maps.parquet 10000: identical +multiple_pages.parquet 100: identical +multiple_pages.parquet 10000: identical +pagination_row_group_1kb_5k_rows.snappy.parquet 100: identical +pagination_row_group_1kb_5k_rows.snappy.parquet 10000: identical +primitives.parquet 100: identical +primitives.parquet 10000: identical +structs.parquet 100: identical +structs.parquet 10000: identical +EdgeCases/datapage_v2.snappy.parquet 100: identical +EdgeCases/datapage_v2.snappy.parquet 10000: identical +EdgeCases/int96.parquet 100: identical +EdgeCases/int96.parquet 10000: identical +EdgeCases/interval.parquet 100: Flow\Parquet\Exception\RuntimeException: Parquet column "iv" (Interval(DayTime)) is not supported by the flow_php Parquet reader; read the file with \Flow\Parquet\Reader::php() +EdgeCases/interval.parquet 10000: Flow\Parquet\Exception\RuntimeException: Parquet column "iv" (Interval(DayTime)) is not supported by the flow_php Parquet reader; read the file with \Flow\Parquet\Reader::php() +EdgeCases/map_keys.parquet 100: both refuse +EdgeCases/map_keys.parquet 10000: both refuse +EdgeCases/nonnullable.impala.parquet 100: identical +EdgeCases/nonnullable.impala.parquet 10000: identical +EdgeCases/null_list.parquet 100: identical +EdgeCases/null_list.parquet 10000: identical +EdgeCases/uint64_overflow.parquet 100: both refuse +EdgeCases/uint64_overflow.parquet 10000: both refuse +EdgeCases/unsigned.parquet 100: identical +EdgeCases/unsigned.parquet 10000: identical +interval.parquet [id]: identical +every type: identical diff --git a/src/extension/flow-php-ext/tests/phpt/074_parquet_lib_write_parity.phpt b/src/extension/flow-php-ext/tests/phpt/074_parquet_lib_write_parity.phpt new file mode 100644 index 0000000000..1968e44503 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/074_parquet_lib_write_parity.phpt @@ -0,0 +1,42 @@ +--TEST-- +Writer::arrow() on flow_php accepts and refuses what Writer::php() does per target type, and what both accept reads back the same +--SKIPIF-- + +--FILE-- + outcome(static fn() => ParquetRows::read(MemoryParquetFile::read( + Reader::php(), + MemoryParquetFile::written($writer, Schema::with(WriteAcceptance::target($target)), [['c' => WriteAcceptance::input($input)]]), + ), 1)); + $php = $read(Writer::php()); + $native = $read(Writer::arrow()); + $cells++; + + match (true) { + refused($php) && refused($native) => $refused++, + !refused($php) && $php === $native => $accepted++, + default => print("{$target} <- {$input}: DIFFER\n php: " . substr($php, 0, 200) . "\n native: " . substr($native, 0, 200) . "\n"), + }; + } +} + +echo "{$cells} cells: {$accepted} accepted by both, {$refused} refused by both\n"; +echo 'every type: ', outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows())), 3)) === outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::arrow(), EveryType::schema(), EveryType::rows())), 3)) ? 'identical' : 'DIFFER', "\n"; +?> +--EXPECT-- +624 cells: 102 accepted by both, 522 refused by both +every type: identical diff --git a/src/extension/flow-php-ext/tests/phpt/075_parquet_footer_thrift_parity.phpt b/src/extension/flow-php-ext/tests/phpt/075_parquet_footer_thrift_parity.phpt new file mode 100644 index 0000000000..229028a867 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/075_parquet_footer_thrift_parity.phpt @@ -0,0 +1,57 @@ +--TEST-- +NativeParquetFile decodes the footer to the FileMetaData and schema the PHP thrift reader builds, from one footer read +--SKIPIF-- + +--FILE-- +read(new CompactProtocol(new MemoryBuffer(substr($bytes, -8 - $length, $length)))); + + $stream = new ReadCountingSourceStream(NativeLocalSourceStream::open(path_real($path))); + $file = new NativeParquetFile($stream); + $reads = $stream->reads; + + printf( + "%s: thrift %s, schema %s, footer reads %d\n", + substr($path, strlen($fixtures) + 1), + serialize($file->thrift()) === serialize($php) ? 'identical' : 'DIFFER', + serialize($file->schema()) === serialize($php->schema) ? 'identical' : 'DIFFER', + $reads, + ); + $file->close(); +} +?> +--EXPECT-- +columns.required.parquet: thrift identical, schema identical, footer reads 1 +decimals_fixed_len.parquet: thrift identical, schema identical, footer reads 1 +delta_binary_acked_encoded_integers.parquet: thrift identical, schema identical, footer reads 1 +lists.parquet: thrift identical, schema identical, footer reads 1 +logical_types.parquet: thrift identical, schema identical, footer reads 1 +maps.parquet: thrift identical, schema identical, footer reads 1 +multiple_pages.parquet: thrift identical, schema identical, footer reads 1 +pagination_row_group_1kb_5k_rows.snappy.parquet: thrift identical, schema identical, footer reads 2 +primitives.parquet: thrift identical, schema identical, footer reads 1 +structs.parquet: thrift identical, schema identical, footer reads 1 +EdgeCases/datapage_v2.snappy.parquet: thrift identical, schema identical, footer reads 1 +EdgeCases/int96.parquet: thrift identical, schema identical, footer reads 1 +EdgeCases/interval.parquet: thrift identical, schema identical, footer reads 1 +EdgeCases/map_keys.parquet: thrift identical, schema identical, footer reads 1 +EdgeCases/nonnullable.impala.parquet: thrift identical, schema identical, footer reads 1 +EdgeCases/null_list.parquet: thrift identical, schema identical, footer reads 1 +EdgeCases/uint64_overflow.parquet: thrift identical, schema identical, footer reads 1 +EdgeCases/unsigned.parquet: thrift identical, schema identical, footer reads 1 diff --git a/src/extension/flow-php-ext/tests/phpt/076_parquet_lib_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/076_parquet_lib_no_leaks.phpt new file mode 100644 index 0000000000..192928ade5 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/076_parquet_lib_no_leaks.phpt @@ -0,0 +1,73 @@ +--TEST-- +NativeParquetFile, NativeParquetColumnsReader and NativeParquetRowsWriter leak neither PHP memory nor native allocations, refusals included +--SKIPIF-- + +--FILE-- + $column->name(), EveryType::schema()->columns()); + +$cycle = static function () use ($schema, $options, $rows, $columns): void { + $filesystem = memory_filesystem(); + $writer = new NativeParquetRowsWriter($filesystem->writeTo(path('memory://leaks.parquet')), $schema, 'SNAPPY', $options, 2); + $writer->writeRows($rows); + $writer->writeRow($rows[0]); + + try { + $writer->writeRow(['int32' => 'not an int']); + throw new LogicException('a string was written into INT32'); + } catch (Flow\Parquet\Exception\ValidationException) { + } + + $writer->close(); + + $file = new NativeParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))); + $file->thrift(); + $file->schema(); + $reader = new NativeParquetColumnsReader($file, $columns, 2, 1, 3); + + while ($reader->next() !== null) { + } + + try { + new NativeParquetColumnsReader($file, ['missing'], 2, null, null); + throw new LogicException('a missing column was read'); + } catch (Flow\Parquet\Exception\InvalidArgumentException) { + } + + $file->close(); + + $abandoned = new NativeParquetRowsWriter($filesystem->writeTo(path('memory://abandoned.parquet')), $schema, 'SNAPPY', $options, 2); + $abandoned->writeRows($rows); +}; + +for ($i = 0; $i < 10; $i++) { + $cycle(); +} +gc_collect_cycles(); +$baseline = memory_get_usage(false); +$baselineRust = (new DefaultBackend())->allocatedBytes(); + +for ($i = 0; $i < 200; $i++) { + $cycle(); +} +gc_collect_cycles(); + +var_dump(memory_get_usage(false) <= $baseline); +var_dump((new DefaultBackend())->allocatedBytes() === $baselineRust); +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/bootstrap.php b/src/extension/flow-php-ext/tests/phpt/bootstrap.php index 25ed7924b8..626a5e612e 100644 --- a/src/extension/flow-php-ext/tests/phpt/bootstrap.php +++ b/src/extension/flow-php-ext/tests/phpt/bootstrap.php @@ -265,6 +265,14 @@ function outcome(callable $fn): string } } +/** + * Whether an outcome() is a refusal: the class and message of what the callable threw. + */ +function refused(string $outcome): bool +{ + return (bool) preg_match('/^[A-Za-z\\\\]+(Exception|Error|Overflow): /', $outcome); +} + function assert_same_outcome(callable $php, callable $native): void { $expected = outcome($php); diff --git a/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadDDLCommand.php b/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadDDLCommand.php index 077f5d29ca..530c065332 100644 --- a/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadDDLCommand.php +++ b/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadDDLCommand.php @@ -38,10 +38,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::FAILURE; } - $reader = new Reader(); - $parquetFile = $reader->read($filePath); - try { + $parquetFile = (new Reader())->read($filePath); $parquetFile->metadata(); } catch (InvalidArgumentException) { $style->error(sprintf('File "%s" is not a valid parquet file', $filePath)); diff --git a/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadDataCommand.php b/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadDataCommand.php index 55c38a10fc..c48fd2caed 100644 --- a/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadDataCommand.php +++ b/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadDataCommand.php @@ -56,10 +56,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::FAILURE; } - $reader = new Reader(); - $parquetFile = $reader->read($filePath); - try { + $parquetFile = (new Reader())->read($filePath); $parquetFile->metadata(); } catch (InvalidArgumentException) { $style->error(sprintf('File "%s" is not a valid parquet file', $filePath)); diff --git a/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadMetadataCommand.php b/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadMetadataCommand.php index 8d59450601..83b8eb2290 100644 --- a/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadMetadataCommand.php +++ b/src/lib/parquet-viewer/src/Flow/ParquetViewer/Command/ReadMetadataCommand.php @@ -62,10 +62,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $displayColumnChunks = type_boolean()->cast($input->getOption('column-chunks')); $displayPageHeaders = type_boolean()->cast($input->getOption('page-headers')); - $reader = new Reader(); - $parquetFile = $reader->read($filePath); - try { + $parquetFile = (new Reader())->read($filePath); $metadata = $parquetFile->metadata(); } catch (InvalidArgumentException $_e) { $style->error(sprintf('File "%s" is not a valid parquet file', $filePath)); diff --git a/src/lib/parquet/composer.json b/src/lib/parquet/composer.json index 1b9ac084cc..ed59bd108c 100644 --- a/src/lib/parquet/composer.json +++ b/src/lib/parquet/composer.json @@ -20,8 +20,11 @@ "packaged/thrift": "^0.15.0", "symfony/polyfill-mbstring": "^1.33" }, + "conflict": { + "ext-flow_php": "<0.45" + }, "suggest": { - "ext-arrow": "For high-performance Parquet reading/writing via Apache Arrow" + "ext-flow_php": "Native Parquet reading and writing (flow-php/flow-php-ext)" }, "config": { "optimize-autoloader": true, diff --git a/src/lib/parquet/src/Flow/Parquet/Dremel/DremelShredder.php b/src/lib/parquet/src/Flow/Parquet/Dremel/DremelShredder.php index 264d0a9241..cb0be47708 100644 --- a/src/lib/parquet/src/Flow/Parquet/Dremel/DremelShredder.php +++ b/src/lib/parquet/src/Flow/Parquet/Dremel/DremelShredder.php @@ -14,6 +14,7 @@ use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\NestedColumn; +use function array_values; use function count; use function gettype; use function is_array; @@ -29,10 +30,11 @@ public function __construct( /** * @param array> $rows + * @param int $firstRow the writer's 0-based index of the first of $rows, which validation refusals name * * @return array keyed by flatPath */ - public function shred(Schema $schema, array $rows): array + public function shred(Schema $schema, array $rows, int $firstRow): array { /** @var array $targets */ $targets = []; @@ -60,12 +62,13 @@ public function shred(Schema $schema, array $rows): array } foreach ($plans as $plan) { - foreach ($rows as $row) { + foreach (array_values($rows) as $offset => $row) { + $rowIndex = $firstRow + $offset; // @mago-ignore analysis:mixed-assignment $value = $row[$plan->childName] ?? null; if ($shouldValidate) { - $this->validator->validate($schema->get($plan->childName), $value); + $this->validator->validate($schema->get($plan->childName), $value, $rowIndex); } /** @var array $rowFirstWrite */ @@ -90,11 +93,29 @@ public function shred(Schema $schema, array $rows): array ); } } elseif ($plan instanceof ListPlan) { - $this->execList($plan, $this->narrowArrayOrNull($value), 0, 0, 0, $shouldValidate, $rowFirstWrite); + $this->execList( + $plan, + $this->narrowArrayOrNull($value), + 0, + 0, + 0, + $shouldValidate, + $rowIndex, + $rowFirstWrite, + ); } elseif ($plan instanceof MapPlan) { - $this->execMap($plan, $this->narrowArrayOrNull($value), 0, 0, 0, $shouldValidate, $rowFirstWrite); + $this->execMap( + $plan, + $this->narrowArrayOrNull($value), + 0, + 0, + 0, + $shouldValidate, + $rowIndex, + $rowFirstWrite, + ); } else { - $this->execStruct($plan, $value, 0, 0, 0, $shouldValidate, $rowFirstWrite); + $this->execStruct($plan, $value, 0, 0, 0, $shouldValidate, $rowIndex, $rowFirstWrite); } } } @@ -191,6 +212,7 @@ private function execList( int $repetitionLevel, int $depth, bool $shouldValidate, + int $rowIndex, array &$rowFirstWrite, ): void { $repetitionLevel++; @@ -273,6 +295,7 @@ private function execList( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -285,7 +308,7 @@ private function execList( if (!count($listValue)) { if ($shouldValidate && $plan->elementColumn !== null) { - $this->validator->validate($plan->elementColumn, null); + $this->validator->validate($plan->elementColumn, null, $rowIndex); } $this->execList( $element, @@ -294,6 +317,7 @@ private function execList( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -311,6 +335,7 @@ private function execList( $i === 0 ? $repetitionLevel - 1 : $depth, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); } @@ -327,6 +352,7 @@ private function execList( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -339,7 +365,7 @@ private function execList( if (!count($listValue)) { if ($shouldValidate && $plan->elementColumn !== null) { - $this->validator->validate($plan->elementColumn, null); + $this->validator->validate($plan->elementColumn, null, $rowIndex); } $this->execMap( $element, @@ -348,6 +374,7 @@ private function execList( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -365,6 +392,7 @@ private function execList( $i === 0 ? $repetitionLevel - 1 : $depth, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); } @@ -380,6 +408,7 @@ private function execList( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -392,7 +421,7 @@ private function execList( if (!count($listValue)) { if ($shouldValidate && $plan->elementColumn !== null) { - $this->validator->validate($plan->elementColumn, null); + $this->validator->validate($plan->elementColumn, null, $rowIndex); } $this->execStruct( $element, @@ -401,6 +430,7 @@ private function execList( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -418,6 +448,7 @@ private function execList( $i === 0 ? $repetitionLevel - 1 : $depth, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); } @@ -434,6 +465,7 @@ private function execMap( int $repetitionLevel, int $depth, bool $shouldValidate, + int $rowIndex, array &$rowFirstWrite, ): void { $repetitionLevel++; @@ -631,6 +663,7 @@ private function execMap( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -643,7 +676,7 @@ private function execMap( if (!count($mapValue)) { if ($shouldValidate && $plan->valueColumn !== null) { - $this->validator->validate($plan->valueColumn, null); + $this->validator->validate($plan->valueColumn, null, $rowIndex); } $repLvl = $repetitionLevel - 1; @@ -662,6 +695,7 @@ private function execMap( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -704,6 +738,7 @@ private function execMap( $repLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); $index++; @@ -730,6 +765,7 @@ private function execMap( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -742,7 +778,7 @@ private function execMap( if (!count($mapValue)) { if ($shouldValidate && $plan->valueColumn !== null) { - $this->validator->validate($plan->valueColumn, null); + $this->validator->validate($plan->valueColumn, null, $rowIndex); } $repLvl = $repetitionLevel - 1; @@ -761,6 +797,7 @@ private function execMap( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -803,6 +840,7 @@ private function execMap( $repLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); $index++; @@ -828,6 +866,7 @@ private function execMap( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -840,7 +879,7 @@ private function execMap( if (!count($mapValue)) { if ($shouldValidate && $plan->valueColumn !== null) { - $this->validator->validate($plan->valueColumn, null); + $this->validator->validate($plan->valueColumn, null, $rowIndex); } $repLvl = $repetitionLevel - 1; @@ -859,6 +898,7 @@ private function execMap( $repetitionLevel - 1, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -894,7 +934,16 @@ private function execMap( $keyTarget->values[] = $this->narrowFlatValue( $keyConverter !== null ? $keyConverter->toParquetType($key) : $key, ); - $this->execStruct($valuePlan, $value, $definitionLevel, $repLevel, $depth, $shouldValidate, $rowFirstWrite); + $this->execStruct( + $valuePlan, + $value, + $definitionLevel, + $repLevel, + $depth, + $shouldValidate, + $rowIndex, + $rowFirstWrite, + ); $index++; } } @@ -909,6 +958,7 @@ private function execStruct( int $repetitionLevel, int $depth, bool $shouldValidate, + int $rowIndex, array &$rowFirstWrite, ): void { if ($structureData === null) { @@ -938,6 +988,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -952,6 +1003,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -965,6 +1017,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); } @@ -1003,6 +1056,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -1017,6 +1071,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -1030,6 +1085,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); } @@ -1077,6 +1133,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -1091,6 +1148,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); @@ -1104,6 +1162,7 @@ private function execStruct( $repetitionLevel, $depth, $shouldValidate, + $rowIndex, $rowFirstWrite, ); } diff --git a/src/lib/parquet/src/Flow/Parquet/Dremel/Validator.php b/src/lib/parquet/src/Flow/Parquet/Dremel/Validator.php index 62737d9fb9..3ce76847aa 100644 --- a/src/lib/parquet/src/Flow/Parquet/Dremel/Validator.php +++ b/src/lib/parquet/src/Flow/Parquet/Dremel/Validator.php @@ -10,7 +10,9 @@ interface Validator { /** + * @param int $row the 0-based index of the row within the writer + * * @throws ValidationException */ - public function validate(Column $column, mixed $data): void; + public function validate(Column $column, mixed $data, int $row): void; } diff --git a/src/lib/parquet/src/Flow/Parquet/Dremel/Validator/ColumnDataValidator.php b/src/lib/parquet/src/Flow/Parquet/Dremel/Validator/ColumnDataValidator.php index 9d992fbfe3..3832480490 100644 --- a/src/lib/parquet/src/Flow/Parquet/Dremel/Validator/ColumnDataValidator.php +++ b/src/lib/parquet/src/Flow/Parquet/Dremel/Validator/ColumnDataValidator.php @@ -11,21 +11,33 @@ use Flow\Parquet\ParquetFile\Schema\Column; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\LogicalType; +use Flow\Parquet\ParquetFile\Schema\LogicalType\Integer; use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\ParquetFile\Schema\PhysicalType; use Flow\Parquet\ParquetFile\Schema\Repetition; +use Stringable; +use function ctype_xdigit; +use function get_debug_type; use function gettype; use function is_array; use function is_bool; use function is_float; use function is_int; +use function is_object; use function is_string; +use function mb_check_encoding; +use function method_exists; use function sprintf; +use function str_replace; +use function strlen; + +use const PHP_INT_MAX; +use const PHP_INT_MIN; final class ColumnDataValidator implements Validator { - public function validate(Column $column, mixed $data): void + public function validate(Column $column, mixed $data, int $row): void { $repetition = $column->repetition(); @@ -50,7 +62,7 @@ public function validate(Column $column, mixed $data): void } if ($column instanceof FlatColumn) { - $this->validateData($column, $data, $repetition); + $this->validateData($column, $data, $repetition, $row); return; } @@ -69,7 +81,7 @@ public function validate(Column $column, mixed $data): void // @mago-ignore analysis:mixed-assignment foreach ($data as $value) { - $this->validate($column->getListElement(), $value); + $this->validate($column->getListElement(), $value, $row); } return; @@ -88,10 +100,10 @@ public function validate(Column $column, mixed $data): void // @mago-ignore analysis:mixed-assignment foreach ($data as $key => $value) { - $this->validate($column->getMapKeyColumn(), $key); + $this->validate($column->getMapKeyColumn(), $key, $row); if ($valueColumn !== null) { - $this->validate($valueColumn, $value); + $this->validate($valueColumn, $value, $row); } } @@ -107,16 +119,16 @@ public function validate(Column $column, mixed $data): void } foreach ($column->children() as $child) { - $this->validate($child, $data[$child->name()] ?? null); + $this->validate($child, $data[$child->name()] ?? null, $row); } } - private function validateData(FlatColumn $column, mixed $data, ?Repetition $repetition): void + private function validateData(FlatColumn $column, mixed $data, ?Repetition $repetition, int $row): void { if (is_array($data)) { // @mago-ignore analysis:mixed-assignment foreach ($data as $value) { - $this->validateData($column, $value, $repetition); + $this->validateData($column, $value, $repetition, $row); } return; @@ -161,7 +173,7 @@ private function validateData(FlatColumn $column, mixed $data, ?Repetition $repe ? null : throw new ValidationException(sprintf('Column "%s" is not float', $column->flatPath())), PhysicalType::BYTE_ARRAY => match ($logicalTypeName) { - LogicalType::STRING, LogicalType::JSON, LogicalType::UUID => is_string($data) + LogicalType::STRING, LogicalType::JSON, LogicalType::ENUM, LogicalType::UUID => is_string($data) ? null : throw new ValidationException(sprintf( 'Column "%s" is not string, got "%s" instead', @@ -173,5 +185,91 @@ private function validateData(FlatColumn $column, mixed $data, ?Repetition $repe PhysicalType::FIXED_LEN_BYTE_ARRAY => null, default => throw new ValidationException(sprintf('Unknown column type "%s"', $type->name)), }; + + if (is_int($data) && ($type === PhysicalType::INT32 || $type === PhysicalType::INT64)) { + $integer = Integer::forColumn($column); + [$name, $min, $max] = match (true) { + $integer === null && $type === PhysicalType::INT32 && $column->logicalType() === null => [ + 'INT32', + -2_147_483_648, + 2_147_483_647, + ], + $integer === null => ['INT64', PHP_INT_MIN, PHP_INT_MAX], + $integer->isSigned() => [ + 'INT_' . $integer->bitWidth(), + $integer->bitWidth() === 64 ? PHP_INT_MIN : -(1 << ($integer->bitWidth() - 1)), + $integer->bitWidth() === 64 ? PHP_INT_MAX : (1 << ($integer->bitWidth() - 1)) - 1, + ], + default => [ + 'UINT_' . $integer->bitWidth(), + 0, + $integer->bitWidth() === 64 ? PHP_INT_MAX : (1 << $integer->bitWidth()) - 1, + ], + }; + + if ($data < $min || $data > $max) { + throw new ValidationException(sprintf( + 'Column "%s" row %d: %d is out of the %s range [%d, %d]', + $column->flatPath(), + $row, + $data, + $name, + $min, + $max, + )); + } + } + + if ($logicalTypeName === LogicalType::UUID) { + $hex = match (true) { + is_string($data) => str_replace('-', '', $data), + is_object($data) && method_exists($data, 'toString') => is_string($data->toString()) + ? str_replace('-', '', (string) $data->toString()) + : '', + $data instanceof Stringable => str_replace('-', '', (string) $data), + default => '', + }; + + if (strlen($hex) !== 32 || !ctype_xdigit($hex)) { + throw new ValidationException(sprintf( + 'Column "%s" row %d: %s is not a UUID of 32 hexadecimal digits', + $column->flatPath(), + $row, + get_debug_type($data), + )); + } + } + + if ( + $type === PhysicalType::FIXED_LEN_BYTE_ARRAY + && $logicalTypeName !== LogicalType::DECIMAL + && $logicalTypeName !== LogicalType::UUID + && is_string($data) + && strlen($data) !== $column->typeLength() + ) { + throw new ValidationException(sprintf( + 'Column "%s" row %d: a FIXED_LEN_BYTE_ARRAY(%d) value is %d bytes long', + $column->flatPath(), + $row, + (int) $column->typeLength(), + strlen($data), + )); + } + + if ( + ( + $logicalTypeName === LogicalType::STRING + || $logicalTypeName === LogicalType::JSON + || $logicalTypeName === LogicalType::ENUM + ) + && is_string($data) + && !mb_check_encoding($data, 'UTF-8') + ) { + throw new ValidationException(sprintf( + 'Column "%s" row %d: the string is not valid UTF-8', + $column->flatPath(), + $row, + )); + } } } diff --git a/src/lib/parquet/src/Flow/Parquet/Dremel/Validator/DisabledValidator.php b/src/lib/parquet/src/Flow/Parquet/Dremel/Validator/DisabledValidator.php index 0da80bc6a1..566c249634 100644 --- a/src/lib/parquet/src/Flow/Parquet/Dremel/Validator/DisabledValidator.php +++ b/src/lib/parquet/src/Flow/Parquet/Dremel/Validator/DisabledValidator.php @@ -9,5 +9,5 @@ final class DisabledValidator implements Validator { - public function validate(Column $column, mixed $data): void {} + public function validate(Column $column, mixed $data, int $row): void {} } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php index 3835c8b85b..1d4eb3c91b 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php @@ -11,8 +11,8 @@ use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; +use Flow\Parquet\ParquetFileReader; use Flow\Parquet\ParquetFileWriter; -use Generator; use function extension_loaded; @@ -22,11 +22,16 @@ public function __construct(ByteOrder $byteOrder = ByteOrder::LITTLE_ENDIAN, Options $options = new Options()) { - $this->delegate = extension_loaded('arrow') + $this->delegate = extension_loaded('flow_php') || extension_loaded('arrow') ? new ArrowParquetEngine($options) : new PhpParquetEngine($byteOrder, $options); } + public function openForRead(SourceStream $stream): ParquetFileReader + { + return $this->delegate->openForRead($stream); + } + public function openForWrite( DestinationStream $stream, Schema $schema, @@ -36,17 +41,6 @@ public function openForWrite( return $this->delegate->openForWrite($stream, $schema, $compression, $options); } - public function readColumns( - SourceStream $stream, - Schema $schema, - array $columns, - int $batchSize, - ?int $limit, - ?int $offset, - ): Generator { - return $this->delegate->readColumns($stream, $schema, $columns, $batchSize, $limit, $offset); - } - public function writeRows( DestinationStream $stream, Schema $schema, diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SchemaConverter.php b/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SchemaConverter.php index f68b013b6a..0ea3aec6b0 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SchemaConverter.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SchemaConverter.php @@ -10,6 +10,7 @@ use Flow\Parquet\ParquetFile\Schema\ConvertedType; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\LogicalType; +use Flow\Parquet\ParquetFile\Schema\LogicalType\Integer; use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\ParquetFile\Schema\PhysicalType; use Flow\Parquet\ParquetFile\Schema\Repetition; @@ -157,14 +158,15 @@ private static function resolveFromConvertedOrPhysical(FlatColumn $column): stri ConvertedType::JSON => 'JSON', ConvertedType::ENUM => 'STRING', ConvertedType::BSON => 'BINARY', - ConvertedType::INT_8 => 'INT8', - ConvertedType::INT_16 => 'INT16', - ConvertedType::INT_32 => 'INT32', - ConvertedType::INT_64 => 'INT64', - ConvertedType::UINT_8 => 'UINT8', - ConvertedType::UINT_16 => 'UINT16', - ConvertedType::UINT_32 => 'UINT32', - ConvertedType::UINT_64 => 'UINT64', + ConvertedType::INT_8, + ConvertedType::INT_16, + ConvertedType::INT_32, + ConvertedType::INT_64, + ConvertedType::UINT_8, + ConvertedType::UINT_16, + ConvertedType::UINT_32, + ConvertedType::UINT_64, + => self::resolveIntegerType($column), default => self::resolveFromPhysicalType($column), }; } @@ -188,20 +190,12 @@ private static function resolveFromPhysicalType(FlatColumn $column): string private static function resolveIntegerType(FlatColumn $column): string { - return match ($column->convertedType()) { - ConvertedType::INT_8 => 'INT8', - ConvertedType::INT_16 => 'INT16', - ConvertedType::INT_32 => 'INT32', - ConvertedType::INT_64 => 'INT64', - ConvertedType::UINT_8 => 'UINT8', - ConvertedType::UINT_16 => 'UINT16', - ConvertedType::UINT_32 => 'UINT32', - ConvertedType::UINT_64 => 'UINT64', - default => match ($column->type()) { - PhysicalType::INT32 => 'INT32', - PhysicalType::INT64 => 'INT64', - default => 'INT64', - }, - }; + $integer = Integer::forColumn($column); + + if ($integer === null) { + return self::resolveFromPhysicalType($column); + } + + return ($integer->isSigned() ? 'INT' : 'UINT') . $integer->bitWidth(); } } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php index 665bdb2dbf..5e7448eee4 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php @@ -4,39 +4,45 @@ namespace Flow\Parquet\Engine; -use Flow\Arrow\Parquet\Reader; use Flow\Arrow\Parquet\Writer; use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; +use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\Arrow\DestinationStreamAdapter; use Flow\Parquet\Engine\Arrow\OptionsConverter; use Flow\Parquet\Engine\Arrow\SchemaConverter; -use Flow\Parquet\Engine\Arrow\SourceStreamAdapter; +use Flow\Parquet\Engine\Native\NativeParquetFile; +use Flow\Parquet\Engine\Native\NativeParquetRowsWriter; use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\Option; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; +use Flow\Parquet\ParquetFileReader; use Flow\Parquet\ParquetFileWriter; -use Generator; use function array_column; -use function array_keys; -use function array_push; -use function array_slice; -use function count; use function extension_loaded; -use function min; +use function trigger_error; + +use const E_USER_DEPRECATED; final class ArrowParquetEngine implements ParquetEngine { public function __construct( private readonly Options $options = new Options(), ) { - if (!extension_loaded('arrow')) { - throw new RuntimeException('The arrow extension is required for ArrowParquetEngine. ' - . 'Install it from flow-php/arrow-ext.'); + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + throw new RuntimeException('ArrowParquetEngine requires the flow_php extension (flow-php/flow-php-ext).'); + } + + if (!extension_loaded('flow_php')) { + @trigger_error( + 'Parquet through the arrow extension is deprecated and will be removed; install the flow_php ' + . 'extension (flow-php/flow-php-ext), which ArrowParquetEngine uses when it is loaded.', + E_USER_DEPRECATED, + ); } } @@ -53,6 +59,17 @@ public static function mapCompression(Compressions $compression): string }; } + public function openForRead(SourceStream $stream): ParquetFileReader + { + return extension_loaded('flow_php') + ? new NativeParquetFileReader(new NativeParquetFile($stream), $this->options) + : new ArrowParquetFileReader( + new PhpParquetFileReader($stream, ByteOrder::LITTLE_ENDIAN, $this->options), + $stream, + $this->options, + ); + } + public function openForWrite( DestinationStream $stream, Schema $schema, @@ -61,6 +78,18 @@ public function openForWrite( ): ParquetFileWriter { $extensionSchema = SchemaConverter::toExtension($schema); + if (extension_loaded('flow_php')) { + return new NativeParquetFileWriter( + new NativeParquetRowsWriter( + $stream, + $extensionSchema, + self::mapCompression($compression), + OptionsConverter::toExtension($options), + $this->options->getInt(Option::ARROW_WRITE_BATCH_SIZE), + ), + ); + } + /** @var list $columnNames */ $columnNames = array_column($extensionSchema, 'name'); // the arrow Writer takes the stream by reference, so it has to be a variable @@ -80,73 +109,6 @@ public function openForWrite( ); } - public function readColumns( - SourceStream $stream, - Schema $schema, - array $columns, - int $batchSize, - ?int $limit, - ?int $offset, - ): Generator { - $adapter = new SourceStreamAdapter($stream); - $extensionOptions = OptionsConverter::toExtension($this->options); - $reader = new Reader($adapter, $extensionOptions); - - try { - $toSkip = $offset ?? 0; - $remaining = $limit; - /** @var array> $carry */ - $carry = []; - $carryCount = 0; - - while (($remaining === null || $remaining > 0) && null !== ($got = $reader->readRowGroup($columns))) { - $names = array_keys($got); - - if ($names === []) { - continue; - } - - $available = count($got[$names[0]]); - $cursor = min($toSkip, $available); - $toSkip -= $cursor; - - while ($cursor < $available && ($remaining === null || $remaining > 0)) { - $take = min($batchSize - $carryCount, $available - $cursor, $remaining ?? $available); - - foreach ($names as $name) { - /** @var list $slice */ - $slice = array_slice($got[$name], $cursor, $take); - - if ($carryCount === 0) { - $carry[$name] = $slice; - } else { - array_push($carry[$name], ...$slice); - } - } - - $carryCount += $take; - $cursor += $take; - - if ($remaining !== null) { - $remaining -= $take; - } - - if ($carryCount === $batchSize) { - yield $carry; - $carry = []; - $carryCount = 0; - } - } - } - - if ($carryCount > 0) { - yield $carry; - } - } finally { - $reader->close(); - } - } - public function writeRows( DestinationStream $stream, Schema $schema, diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php new file mode 100644 index 0000000000..9e4f1f6175 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php @@ -0,0 +1,116 @@ +footer->close(); + } + + public function metadata(): Metadata + { + return $this->footer->metadata(); + } + + public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator + { + $adapter = new SourceStreamAdapter($this->stream); + $extensionOptions = OptionsConverter::toExtension($this->options); + $reader = new Reader($adapter, $extensionOptions); + + try { + $toSkip = $offset ?? 0; + $remaining = $limit; + /** @var array> $carry */ + $carry = []; + $carryCount = 0; + + while (($remaining === null || $remaining > 0) && null !== ($got = $reader->readRowGroup($columns))) { + $names = array_keys($got); + + if ($names === []) { + continue; + } + + $available = count($got[$names[0]]); + $cursor = min($toSkip, $available); + $toSkip -= $cursor; + + while ($cursor < $available && ($remaining === null || $remaining > 0)) { + $take = min($batchSize - $carryCount, $available - $cursor, $remaining ?? $available); + + foreach ($names as $name) { + /** @var list $slice */ + $slice = array_slice($got[$name], $cursor, $take); + + if ($carryCount === 0) { + $carry[$name] = $slice; + } else { + array_push($carry[$name], ...$slice); + } + } + + $carryCount += $take; + $cursor += $take; + + if ($remaining !== null) { + $remaining -= $take; + } + + if ($carryCount === $batchSize) { + yield $carry; + $carry = []; + $carryCount = 0; + } + } + } + + if ($carryCount > 0) { + yield $carry; + } + } finally { + $reader->close(); + } + } + + public function rowsNumber(): int + { + return $this->footer->rowsNumber(); + } + + public function schema(): Schema + { + return $this->footer->schema(); + } + + public function totalByteSize(): int + { + return $this->footer->totalByteSize(); + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileReader.php new file mode 100644 index 0000000000..47055d49a6 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileReader.php @@ -0,0 +1,109 @@ +open || throw new RuntimeException('Reader is not open'); + + $this->open = false; + $this->file->close(); + } + + public function file(): NativeParquetFile + { + $this->open || throw new RuntimeException('Reader is not open'); + + return $this->file; + } + + public function metadata(): Metadata + { + $this->open || throw new RuntimeException('Reader is not open'); + + return $this->metadata ??= Metadata::fromThrift($this->file->thrift()); + } + + public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator + { + $this->open || throw new RuntimeException('Reader is not open'); + + if (!$this->options->getBool(Option::INT_96_AS_DATETIME)) { + foreach ($columns as $column) { + foreach ($this->schema()->columnsFlat() as $leaf) { + if ( + $leaf->type() === PhysicalType::INT96 + && ($leaf->flatPath() === $column || str_starts_with($leaf->flatPath(), $column . '.')) + ) { + throw new InvalidArgumentException(sprintf( + 'Parquet column "%s" holds INT96, which flow_php reads only as a datetime ' + . '(Option::INT_96_AS_DATETIME = true); read the file with \Flow\Parquet\Reader::php()', + $column, + )); + } + } + } + } + + $reader = new NativeParquetColumnsReader($this->file, $columns, $batchSize, $offset, $limit); + + try { + while (($chunk = $reader->next()) !== null) { + yield $chunk; + } + } finally { + $reader->close(); + } + } + + public function rowsNumber(): int + { + $this->open || throw new RuntimeException('Reader is not open'); + + return $this->file->rowsNumber(); + } + + public function schema(): Schema + { + $this->open || throw new RuntimeException('Reader is not open'); + + return $this->metadata?->schema() ?? ($this->schema ??= Schema::fromThrift($this->file->schema())); + } + + public function totalByteSize(): int + { + $this->open || throw new RuntimeException('Reader is not open'); + + return $this->file->totalByteSize(); + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileWriter.php b/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileWriter.php new file mode 100644 index 0000000000..e6b32abc12 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileWriter.php @@ -0,0 +1,53 @@ +writer = $writer; + } + + public function close(): void + { + $writer = $this->writer ?? throw new RuntimeException('Writer is not open'); + + try { + $writer->close(); + } finally { + $this->writer = null; + } + } + + public function writeBatch(iterable $rows): void + { + $writer = $this->writer ?? throw new RuntimeException('Writer is not open'); + + if (is_array($rows)) { + $writer->writeRows(array_values($rows)); + + return; + } + + foreach ($rows as $row) { + $writer->writeRow($row); + } + } + + public function writeRow(array $row): void + { + ($this->writer ?? throw new RuntimeException('Writer is not open'))->writeRow($row); + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php index 6cd00f8094..76823a4028 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetEngine.php @@ -7,33 +7,13 @@ use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; use Flow\Parquet\Binary\ByteOrder; -use Flow\Parquet\Dremel\ColumnData\PagedFlatColumnValues; -use Flow\Parquet\Dremel\DremelAssembler; -use Flow\Parquet\Dremel\ReadColumnData; -use Flow\Parquet\Exception\InvalidArgumentException; use Flow\Parquet\Option; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; -use Flow\Parquet\ParquetFile; use Flow\Parquet\ParquetFile\Compressions; -use Flow\Parquet\ParquetFile\Data\DataConverter; -use Flow\Parquet\ParquetFile\Metadata; use Flow\Parquet\ParquetFile\Schema; -use Flow\Parquet\ParquetFile\Schema\Column; -use Flow\Parquet\ParquetFile\Schema\FlatColumn; -use Flow\Parquet\ParquetFile\Schema\NestedColumn; +use Flow\Parquet\ParquetFileReader; use Flow\Parquet\ParquetFileWriter; -use Flow\Parquet\Reader\ColumnChunkReader; -use Flow\Parquet\Reader\PageReader; -use Flow\Parquet\Thrift\CompactProtocol; -use Flow\Parquet\Thrift\MemoryBuffer; -use Flow\Parquet\ThriftModel\FileMetaData; -use Generator; - -use function count; -use function is_array; -use function min; -use function unpack; final class PhpParquetEngine implements ParquetEngine { @@ -42,6 +22,11 @@ public function __construct( private readonly Options $options = new Options(), ) {} + public function openForRead(SourceStream $stream): ParquetFileReader + { + return new PhpParquetFileReader($stream, $this->byteOrder, $this->options); + } + public function openForWrite( DestinationStream $stream, Schema $schema, @@ -57,91 +42,6 @@ public function openForWrite( ); } - public function readColumns( - SourceStream $stream, - Schema $schema, - array $columns, - int $batchSize, - ?int $limit, - ?int $offset, - ): Generator { - $dataConverter = DataConverter::initialize($this->options); - $dremelAssembler = new DremelAssembler($dataConverter); - $chunkReader = new ColumnChunkReader(new PageReader($this->byteOrder, $this->options), $this->options); - - $metadata = $this->readMetadata($stream); - - $totalRows = $metadata->rowsNumber(); - - if ($offset !== null && $offset > $totalRows) { - return; - } - - if ($offset !== null) { - if ($totalRows > $offset) { - $totalRows -= $offset; - } else { - $totalRows = 0; - } - } - - $totalRows = min($totalRows, $limit ?? $totalRows); - - if ($totalRows === 0) { - return; - } - - $generators = []; - - foreach ($columns as $columnName) { - $generators[$columnName] = $this->readColumn( - $schema->get($columnName), - $metadata, - $stream, - $chunkReader, - $dremelAssembler, - $limit, - $offset, - ); - } - - $remaining = $totalRows; - - while ($remaining > 0) { - $take = min($batchSize, $remaining); - $chunk = []; - $read = 0; - - foreach ($generators as $name => $generator) { - $values = []; - - while (count($values) < $take && $generator->valid()) { - // @mago-ignore analysis:mixed-assignment - $entry = $generator->current(); - - if (is_array($entry)) { - // @mago-ignore analysis:mixed-assignment - foreach ($entry as $value) { - $values[] = $value; - } - } - - $generator->next(); - } - - $chunk[$name] = $values; - $read = count($values); - } - - if ($read === 0) { - return; - } - - yield $chunk; - $remaining -= $read; - } - } - public function writeRows( DestinationStream $stream, Schema $schema, @@ -164,120 +64,4 @@ public function writeRows( $file->close(); } - - private function readColumn( - Column $column, - Metadata $metadata, - SourceStream $stream, - ColumnChunkReader $chunkReader, - DremelAssembler $dremelAssembler, - ?int $limit, - ?int $offset, - ): Generator { - $yieldedRows = 0; - $rowGroupOffset = 0; - - foreach ($metadata->rowGroups()->all() as $rowGroup) { - if ($offset !== null) { - if (($rowGroupOffset + $rowGroup->rowsCount()) <= $offset) { - $rowGroupOffset += $rowGroup->rowsCount(); - - continue; - } - } - $skipRows = $offset !== null ? $offset - $rowGroupOffset : 0; - - if ($column instanceof FlatColumn) { - $rowsSkipped = 0; - - foreach ($chunkReader->read( - $rowGroup->getColumnChunk($column), - $column, - $stream, - ) as $flatColumnValues) { - $columnData = new ReadColumnData($column, [$flatColumnValues->flatPath() => $flatColumnValues]); - - // @mago-ignore analysis:mixed-assignment - foreach ($dremelAssembler->assemble($column, $columnData) as $row) { - if ($skipRows > 0 && $rowsSkipped < $skipRows) { - $rowsSkipped++; - - continue; - } - - if ($limit !== null && $yieldedRows >= $limit) { - return; - } - yield $row; - $yieldedRows++; - } - } - } elseif ($column instanceof NestedColumn) { - $flatData = []; - - foreach ($column->childrenFlat() as $child) { - $flatData[] = new PagedFlatColumnValues($child, $chunkReader->read( - $rowGroup->getColumnChunk($child), - $child, - $stream, - )); - } - - $columnData = new ReadColumnData($column, $flatData); - - $rowsSkipped = 0; - - // @mago-ignore analysis:mixed-assignment - foreach ($dremelAssembler->assemble($column, $columnData) as $row) { - if ($skipRows > 0 && $rowsSkipped < $skipRows) { - $rowsSkipped++; - - continue; - } - - if ($limit !== null && $yieldedRows >= $limit) { - return; - } - yield $row; - $yieldedRows++; - } - } else { - throw new InvalidArgumentException('Column must be instance of FlatColumn or NestedColumn'); - } - - $rowGroupOffset += $rowGroup->rowsCount(); - } - } - - private function readMetadata(SourceStream $stream): Metadata - { - $fileTotalSize = $stream->size(); - - if ($fileTotalSize === null) { - throw new InvalidArgumentException('Cannot determine Parquet file size'); - } - - if ($stream->read(4, $fileTotalSize - 4) !== ParquetFile::PARQUET_MAGIC_NUMBER) { - throw new InvalidArgumentException('Given file is not valid Parquet file'); - } - - $unpacked = unpack($this->byteOrder->value, $stream->read(4, $fileTotalSize - 8)); - - if ($unpacked === false) { - throw new InvalidArgumentException('Failed to read Parquet metadata length'); - } - - $metadataLength = $unpacked[1]; - - if ($metadataLength <= 0) { - throw new InvalidArgumentException('Parquet metadata length must be positive, got ' . $metadataLength); - } - - $metadata = $stream->read($metadataLength, $fileTotalSize - ($metadataLength + 8)); - - $thriftMetadata = new FileMetaData(); - $thriftMetadata->read(new CompactProtocol(new MemoryBuffer($metadata))); - - return Metadata::fromThrift($thriftMetadata); - } } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetFileReader.php new file mode 100644 index 0000000000..c91c412fe6 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetFileReader.php @@ -0,0 +1,191 @@ +open || throw new RuntimeException('Reader is not open'); + + $this->open = false; + $this->stream->close(); + } + + public function metadata(): Metadata + { + $this->open || throw new RuntimeException('Reader is not open'); + + if ($this->metadata !== null) { + return $this->metadata; + } + + $fileTotalSize = $this->stream->size(); + + if ($fileTotalSize === null) { + throw new InvalidArgumentException('Cannot determine Parquet file size'); + } + + if ($this->stream->read(4, $fileTotalSize - 4) !== ParquetFile::PARQUET_MAGIC_NUMBER) { + throw new InvalidArgumentException('Given file is not valid Parquet file'); + } + + $unpacked = unpack($this->byteOrder->value, $this->stream->read(4, $fileTotalSize - 8)); + + if ($unpacked === false) { + throw new InvalidArgumentException('Failed to read Parquet metadata length'); + } + + $metadataLength = $unpacked[1]; + + if ($metadataLength <= 0) { + throw new InvalidArgumentException('Parquet metadata length must be positive, got ' . $metadataLength); + } + + $metadata = $this->stream->read($metadataLength, $fileTotalSize - ($metadataLength + 8)); + + $thriftMetadata = new FileMetaData(); + $thriftMetadata->read(new CompactProtocol(new MemoryBuffer($metadata))); + + $this->metadata = Metadata::fromThrift($thriftMetadata); + + return $this->metadata; + } + + public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator + { + $this->open || throw new RuntimeException('Reader is not open'); + + $columnReader = new ColumnReader( + new ColumnChunkReader(new PageReader($this->byteOrder, $this->options), $this->options), + new DremelAssembler(DataConverter::initialize($this->options)), + ); + + $metadata = $this->metadata(); + + $totalRows = $metadata->rowsNumber(); + + if ($offset !== null && $offset > $totalRows) { + return; + } + + if ($offset !== null) { + if ($totalRows > $offset) { + $totalRows -= $offset; + } else { + $totalRows = 0; + } + } + + $totalRows = min($totalRows, $limit ?? $totalRows); + + if ($totalRows === 0) { + return; + } + + $generators = []; + + foreach ($columns as $columnName) { + $generators[$columnName] = $columnReader->read( + $metadata->schema()->get($columnName), + $metadata, + $this->stream, + $limit, + $offset, + ); + } + + $remaining = $totalRows; + + while ($remaining > 0) { + $take = min($batchSize, $remaining); + $chunk = []; + $read = 0; + + foreach ($generators as $name => $generator) { + $values = []; + + while (count($values) < $take && $generator->valid()) { + // @mago-ignore analysis:mixed-assignment + $entry = $generator->current(); + + if (is_array($entry)) { + // @mago-ignore analysis:mixed-assignment + foreach ($entry as $value) { + $values[] = $value; + } + } + + $generator->next(); + } + + $chunk[$name] = $values; + $read = count($values); + } + + if ($read === 0) { + return; + } + + yield $chunk; + $remaining -= $read; + } + } + + public function rowsNumber(): int + { + return $this->metadata()->rowsNumber(); + } + + public function schema(): Schema + { + return $this->metadata()->schema(); + } + + public function totalByteSize(): int + { + $bytes = 0; + + foreach ($this->metadata()->rowGroups()->all() as $rowGroup) { + $bytes += $rowGroup->totalByteSize(); + } + + return $bytes; + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php index d414293567..9fc91077dc 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php @@ -8,10 +8,14 @@ use Flow\Filesystem\SourceStream; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; -use Generator; interface ParquetEngine { + /** + * The file on $stream, its footer read by the returned reader, which owns the stream from here on. + */ + public function openForRead(SourceStream $stream): ParquetFileReader; + public function openForWrite( DestinationStream $stream, Schema $schema, @@ -19,21 +23,6 @@ public function openForWrite( Options $options, ): ParquetFileWriter; - /** - * @param list $columns resolved names, never empty - * @param int<1, max> $batchSize upper bound of rows per chunk - * - * @return Generator>> chunks keyed by column, every list the same length (>0) - */ - public function readColumns( - SourceStream $stream, - Schema $schema, - array $columns, - int $batchSize, - ?int $limit, - ?int $offset, - ): Generator; - /** * @param iterable> $rows */ diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile.php index cbd16e2599..b654c2482f 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFile.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile.php @@ -5,7 +5,6 @@ namespace Flow\Parquet; use Flow\Filesystem\SourceStream; -use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Exception\InvalidArgumentException; use Flow\Parquet\ParquetFile\Metadata; use Flow\Parquet\ParquetFile\Page\ColumnPageHeader; @@ -13,73 +12,51 @@ use Flow\Parquet\ParquetFile\Schema\Column; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\Reader\ColumnChunkViewer; -use Flow\Parquet\Thrift\CompactProtocol; -use Flow\Parquet\Thrift\MemoryBuffer; -use Flow\Parquet\ThriftModel\FileMetaData; use Generator; use function array_keys; use function array_map; use function array_values; use function count; -use function unpack; +/** + * @template-covariant R of ParquetFileReader + */ final class ParquetFile { public const string PARQUET_MAGIC_NUMBER = 'PAR1'; private const int VALUES_BATCH_SIZE = 1024; - private ?Metadata $metadata = null; + private bool $closed = false; + /** + * @param R $reader opened on $stream + */ public function __construct( private readonly SourceStream $stream, - private readonly ByteOrder $byteOrder, private readonly Options $options, - private readonly ParquetEngine $engine, + private readonly ParquetFileReader $reader, ) {} public function __destruct() { - $this->stream->close(); + $this->close(); } - public function metadata(): Metadata + public function close(): void { - if ($this->metadata !== null) { - return $this->metadata; - } - - $fileTotalSize = $this->stream->size(); - - if ($fileTotalSize === null) { - throw new InvalidArgumentException('Cannot determine Parquet file size'); - } - - if ($this->stream->read(4, $fileTotalSize - 4) !== self::PARQUET_MAGIC_NUMBER) { - throw new InvalidArgumentException('Given file is not valid Parquet file'); - } - - $unpacked = unpack($this->byteOrder->value, $this->stream->read(4, $fileTotalSize - 8)); - - if ($unpacked === false) { - throw new InvalidArgumentException('Failed to read Parquet metadata length'); - } - - $metadataLength = $unpacked[1]; - - if ($metadataLength <= 0) { - throw new InvalidArgumentException('Parquet metadata length must be positive, got ' . $metadataLength); + if ($this->closed) { + return; } - $metadata = $this->stream->read($metadataLength, $fileTotalSize - ($metadataLength + 8)); - - $thriftMetadata = new FileMetaData(); - $thriftMetadata->read(new CompactProtocol(new MemoryBuffer($metadata))); - - $this->metadata = Metadata::fromThrift($thriftMetadata); + $this->closed = true; + $this->reader->close(); + } - return $this->metadata; + public function metadata(): Metadata + { + return $this->reader->metadata(); } /** @@ -94,9 +71,17 @@ public function pageHeaders(): Generator } } + /** + * @return R + */ + public function reader(): ParquetFileReader + { + return $this->reader; + } + public function schema(): Schema { - return $this->metadata()->schema(); + return $this->reader->schema(); } /** @@ -123,19 +108,12 @@ public function columns(int $batchSize, array $columns = [], ?int $limit = null, } foreach ($columns as $columnName) { - if (!$this->metadata()->schema()->has($columnName)) { + if (!$this->schema()->has($columnName)) { throw new InvalidArgumentException("Column \"{$columnName}\" does not exist"); } } - yield from $this->engine->readColumns( - $this->stream, - $this->schema(), - array_values($columns), - $batchSize, - $limit, - $offset, - ); + yield from $this->reader->readColumns(array_values($columns), $batchSize, $limit, $offset); } /** diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/Converter/Int96DateTimeConverter.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/Converter/Int96DateTimeConverter.php index 2ecd509d5e..703285206f 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/Converter/Int96DateTimeConverter.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/Converter/Int96DateTimeConverter.php @@ -14,8 +14,7 @@ use function array_values; use function bin2hex; -use function floor; -use function round; +use function Flow\Parquet\floor_div; use function sprintf; use function unpack; @@ -65,22 +64,14 @@ private function convertRawBytesToDateTime(string $bytes): DateTimeImmutable | ($bytesArray[6] << 48) | ($bytesArray[7] << 56); - // The Julian epoch starts on January 1, 4713 BCE. - // The Unix epoch starts on January 1, 1970 CE. - // The number of days between these two dates is 2440588. - $daysSinceUnixEpoch = $daysInEpoch - 2440588; + $micros = (($daysInEpoch - 2_440_588) * 86_400_000_000) + floor_div($nanosecondsWithinDay, 1_000); + $seconds = floor_div($micros, 1_000_000); - // Convert the days since the Unix epoch and the nanoseconds within the day to a Unix timestamp - $timestampSeconds = ($daysSinceUnixEpoch * 86400) + ($nanosecondsWithinDay / 1e9); - - // Separate the seconds and fractional seconds parts of the timestamp - $seconds = floor($timestampSeconds); - $fraction = $timestampSeconds - $seconds; - - // Convert the fractional seconds to milliseconds - $microseconds = round($fraction * 1e6); - - $dateTime = DateTimeImmutable::createFromFormat('U.u', sprintf('%d.%06d', $seconds, $microseconds)); + $dateTime = DateTimeImmutable::createFromFormat('U.u', sprintf( + '%d.%06d', + $seconds, + $micros - ($seconds * 1_000_000), + )); if ($dateTime === false) { throw new RuntimeException('Failed to convert INT96 to DateTime, given bytes: ' . bin2hex($bytes)); diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/Converter/UnsignedIntegerConverter.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/Converter/UnsignedIntegerConverter.php new file mode 100644 index 0000000000..6d15ddd70b --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/Converter/UnsignedIntegerConverter.php @@ -0,0 +1,57 @@ +isSigned() + && ($integer->bitWidth() === 32 || $integer->bitWidth() === 64) + ? new self($column->flatPath(), $integer->bitWidth()) + : null; + } + + public function fromParquetType(mixed $data): int + { + if (!is_int($data)) { + throw new InvalidArgumentException(sprintf('Expected int, got %s', get_debug_type($data))); + } + + if ($data >= 0) { + return $data; + } + + if ($this->bitWidth === 32) { + return $data + 4_294_967_296; + } + + throw new RuntimeException(sprintf('Parquet column "%s" holds a UINT_64 value above PHP_INT_MAX', $this->path)); + } + + public function toParquetType(mixed $data): mixed + { + return $data; + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/DataConverter.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/DataConverter.php index 0351230a1f..01cafab35c 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/DataConverter.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Data/DataConverter.php @@ -12,6 +12,7 @@ use Flow\Parquet\ParquetFile\Data\Converter\Int96DateTimeConverter; use Flow\Parquet\ParquetFile\Data\Converter\JsonConverter; use Flow\Parquet\ParquetFile\Data\Converter\TimeConverter; +use Flow\Parquet\ParquetFile\Data\Converter\UnsignedIntegerConverter; use Flow\Parquet\ParquetFile\Data\Converter\UuidConverter; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Throwable; @@ -45,6 +46,7 @@ public static function initialize(Options $options): self DecimalConverter::class, UuidConverter::class, JsonConverter::class, + UnsignedIntegerConverter::class, ], $options); } diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/FlatColumn.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/FlatColumn.php index be2660f665..bda56927d8 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/FlatColumn.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/FlatColumn.php @@ -110,7 +110,7 @@ public static function double(string $name, Repetition $repetition = Repetition: public static function enum(string $string, Repetition $repetition = Repetition::OPTIONAL): self { - return new self($string, PhysicalType::BYTE_ARRAY, ConvertedType::ENUM, LogicalType::string(), $repetition); + return new self($string, PhysicalType::BYTE_ARRAY, ConvertedType::ENUM, LogicalType::enum(), $repetition); } public static function fixedSizeByteArray( diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/LogicalType.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/LogicalType.php index 61dcef2228..c4c5f4483e 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/LogicalType.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/LogicalType.php @@ -5,6 +5,7 @@ namespace Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\LogicalType\Decimal; +use Flow\Parquet\ParquetFile\Schema\LogicalType\Integer; use Flow\Parquet\ParquetFile\Schema\LogicalType\Time; use Flow\Parquet\ParquetFile\Schema\LogicalType\Timestamp; use Flow\Parquet\ThriftModel\BsonType; @@ -12,7 +13,6 @@ use Flow\Parquet\ThriftModel\DecimalType; use Flow\Parquet\ThriftModel\EnumType; use Flow\Parquet\ThriftModel\Float16Type; -use Flow\Parquet\ThriftModel\IntType; use Flow\Parquet\ThriftModel\JsonType; use Flow\Parquet\ThriftModel\ListType; use Flow\Parquet\ThriftModel\LogicalType as ThriftLogicalType; @@ -62,6 +62,7 @@ public function __construct( private ?Timestamp $timestamp = null, private ?Time $time = null, private ?Decimal $decimal = null, + private ?Integer $integer = null, ) {} public static function bson(): self @@ -208,12 +209,15 @@ public static function fromThrift(ThriftLogicalType $logicalType): ?self // @mago-ignore analysis:redundant-condition // @mago-ignore analysis:redundant-comparison decimal: $logicalType->DECIMAL !== null ? Decimal::fromThrift($logicalType->DECIMAL) : null, + // @mago-ignore analysis:redundant-condition + // @mago-ignore analysis:redundant-comparison + integer: $logicalType->INTEGER !== null ? Integer::fromThrift($logicalType->INTEGER) : null, ); } - public static function integer(): self + public static function integer(int $bitWidth, bool $isSigned): self { - return new self(self::INTEGER); + return new self(self::INTEGER, integer: new Integer($bitWidth, $isSigned)); } public static function json(): self @@ -261,6 +265,11 @@ public function decimalData(): ?Decimal return $this->decimal; } + public function integerData(): ?Integer + { + return $this->integer; + } + public function is(string $logicalType): bool { return $this->name() === $logicalType; @@ -292,7 +301,7 @@ public function toThrift(): ThriftLogicalType 'precision' => $this->decimalData()?->precision(), ]) : null, self::ENUM => $this->is(self::ENUM) ? new EnumType() : null, - self::INTEGER => $this->is(self::INTEGER) ? new IntType() : null, + self::INTEGER => $this->is(self::INTEGER) ? $this->integer?->toThrift() : null, self::JSON => $this->is(self::JSON) ? new JsonType() : null, self::LIST => $this->is(self::LIST) ? new ListType() : null, self::MAP => $this->is(self::MAP) ? new MapType() : null, diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/LogicalType/Integer.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/LogicalType/Integer.php new file mode 100644 index 0000000000..78d50df519 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema/LogicalType/Integer.php @@ -0,0 +1,55 @@ +convertedType()) { + ConvertedType::INT_8 => new self(8, true), + ConvertedType::INT_16 => new self(16, true), + ConvertedType::INT_32 => new self(32, true), + ConvertedType::INT_64 => new self(64, true), + ConvertedType::UINT_8 => new self(8, false), + ConvertedType::UINT_16 => new self(16, false), + ConvertedType::UINT_32 => new self(32, false), + ConvertedType::UINT_64 => new self(64, false), + default => $column->logicalType()?->integerData(), + }; + } + + public static function fromThrift(IntType $thrift): self + { + return new self((int) $thrift->bitWidth, $thrift->isSigned); + } + + public function bitWidth(): int + { + return $this->bitWidth; + } + + public function isSigned(): bool + { + return $this->isSigned; + } + + public function toThrift(): IntType + { + return new IntType(['bitWidth' => $this->bitWidth, 'isSigned' => $this->isSigned]); + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php new file mode 100644 index 0000000000..3655acfd27 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php @@ -0,0 +1,42 @@ + $columns resolved names, never empty + * @param int<1, max> $batchSize upper bound of rows per chunk + * + * @return Generator>> chunks keyed by column, every list the same length (>0) + */ + public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator; + + public function rowsNumber(): int; + + /** + * The file schema, without building the row-group metadata. + */ + public function schema(): Schema; + + /** + * Σ row group total_byte_size (uncompressed), without building the row-group metadata. + */ + public function totalByteSize(): int; +} diff --git a/src/lib/parquet/src/Flow/Parquet/Reader.php b/src/lib/parquet/src/Flow/Parquet/Reader.php index 82e94cd788..2d778541fa 100644 --- a/src/lib/parquet/src/Flow/Parquet/Reader.php +++ b/src/lib/parquet/src/Flow/Parquet/Reader.php @@ -35,18 +35,19 @@ public static function php(Options $options = new Options()): self return new self(options: $options, engine: new PhpParquetEngine(options: $options)); } + /** + * @return ParquetFile + */ public function read(string $path): ParquetFile { - return new ParquetFile( - NativeLocalSourceStream::open(path_real($path)), - $this->byteOrder, - $this->options, - $this->engine, - ); + return $this->readStream(NativeLocalSourceStream::open(path_real($path))); } + /** + * @return ParquetFile + */ public function readStream(SourceStream $stream): ParquetFile { - return new ParquetFile($stream, $this->byteOrder, $this->options, $this->engine); + return new ParquetFile($stream, $this->options, $this->engine->openForRead($stream)); } } diff --git a/src/lib/parquet/src/Flow/Parquet/Reader/ColumnReader.php b/src/lib/parquet/src/Flow/Parquet/Reader/ColumnReader.php new file mode 100644 index 0000000000..c7e87a3421 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/Reader/ColumnReader.php @@ -0,0 +1,104 @@ +rowGroups()->all() as $rowGroup) { + if ($offset !== null) { + if (($rowGroupOffset + $rowGroup->rowsCount()) <= $offset) { + $rowGroupOffset += $rowGroup->rowsCount(); + + continue; + } + } + $skipRows = $offset !== null ? $offset - $rowGroupOffset : 0; + + if ($column instanceof FlatColumn) { + $rowsSkipped = 0; + + foreach ($this->chunks->read( + $rowGroup->getColumnChunk($column), + $column, + $stream, + ) as $flatColumnValues) { + $columnData = new ReadColumnData($column, [$flatColumnValues->flatPath() => $flatColumnValues]); + + // @mago-ignore analysis:mixed-assignment + foreach ($this->assembler->assemble($column, $columnData) as $row) { + if ($skipRows > 0 && $rowsSkipped < $skipRows) { + $rowsSkipped++; + + continue; + } + + if ($limit !== null && $yieldedRows >= $limit) { + return; + } + yield $row; + $yieldedRows++; + } + } + } elseif ($column instanceof NestedColumn) { + $flatData = []; + + foreach ($column->childrenFlat() as $child) { + $flatData[] = new PagedFlatColumnValues($child, $this->chunks->read( + $rowGroup->getColumnChunk($child), + $child, + $stream, + )); + } + + $columnData = new ReadColumnData($column, $flatData); + + $rowsSkipped = 0; + + // @mago-ignore analysis:mixed-assignment + foreach ($this->assembler->assemble($column, $columnData) as $row) { + if ($skipRows > 0 && $rowsSkipped < $skipRows) { + $rowsSkipped++; + + continue; + } + + if ($limit !== null && $yieldedRows >= $limit) { + return; + } + yield $row; + $yieldedRows++; + } + } else { + throw new InvalidArgumentException('Column must be instance of FlatColumn or NestedColumn'); + } + + $rowGroupOffset += $rowGroup->rowsCount(); + } + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterAlgorithm.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterAlgorithm.php index e28cace801..fc6898e195 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterAlgorithm.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterAlgorithm.php @@ -24,7 +24,7 @@ class BloomFilterAlgorithm 'var' => 'BLOCK', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\SplitBlockAlgorithm', + 'class' => '\Flow\Parquet\ThriftModel\SplitBlockAlgorithm', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterCompression.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterCompression.php index ac977e23bd..b19c25b750 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterCompression.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterCompression.php @@ -21,7 +21,7 @@ class BloomFilterCompression 'var' => 'UNCOMPRESSED', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\Uncompressed', + 'class' => '\Flow\Parquet\ThriftModel\Uncompressed', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterHash.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterHash.php index 1ea5463ab7..1426be9ca5 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterHash.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterHash.php @@ -25,7 +25,7 @@ class BloomFilterHash 'var' => 'XXHASH', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\XxHash', + 'class' => '\Flow\Parquet\ThriftModel\XxHash', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterHeader.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterHeader.php index 314299c9ec..06682c552e 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterHeader.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/BloomFilterHeader.php @@ -30,19 +30,19 @@ class BloomFilterHeader 'var' => 'algorithm', 'isRequired' => true, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\BloomFilterAlgorithm', + 'class' => '\Flow\Parquet\ThriftModel\BloomFilterAlgorithm', ], 3 => [ 'var' => 'hash', 'isRequired' => true, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\BloomFilterHash', + 'class' => '\Flow\Parquet\ThriftModel\BloomFilterHash', ], 4 => [ 'var' => 'compression', 'isRequired' => true, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\BloomFilterCompression', + 'class' => '\Flow\Parquet\ThriftModel\BloomFilterCompression', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnChunk.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnChunk.php index 677365c030..bb1efef2e1 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnChunk.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnChunk.php @@ -31,7 +31,7 @@ class ColumnChunk 'var' => 'meta_data', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\ColumnMetaData', + 'class' => '\Flow\Parquet\ThriftModel\ColumnMetaData', ], 4 => [ 'var' => 'offset_index_offset', @@ -57,7 +57,7 @@ class ColumnChunk 'var' => 'crypto_metadata', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\ColumnCryptoMetaData', + 'class' => '\Flow\Parquet\ThriftModel\ColumnCryptoMetaData', ], 9 => [ 'var' => 'encrypted_column_metadata', diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnCryptoMetaData.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnCryptoMetaData.php index 0ee1ba3b50..cf578e9f76 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnCryptoMetaData.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnCryptoMetaData.php @@ -21,13 +21,13 @@ class ColumnCryptoMetaData 'var' => 'ENCRYPTION_WITH_FOOTER_KEY', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\EncryptionWithFooterKey', + 'class' => '\Flow\Parquet\ThriftModel\EncryptionWithFooterKey', ], 2 => [ 'var' => 'ENCRYPTION_WITH_COLUMN_KEY', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\EncryptionWithColumnKey', + 'class' => '\Flow\Parquet\ThriftModel\EncryptionWithColumnKey', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnIndex.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnIndex.php index a69987f6f2..2a962e08d1 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnIndex.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnIndex.php @@ -58,7 +58,7 @@ class ColumnIndex 'var' => 'boundary_order', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\BoundaryOrder', + 'class' => '\Flow\Parquet\ThriftModel\BoundaryOrder', ], 5 => [ 'var' => 'null_counts', diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnMetaData.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnMetaData.php index 4a38814f53..438c05118c 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnMetaData.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnMetaData.php @@ -24,7 +24,7 @@ class ColumnMetaData 'var' => 'type', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Type', + 'class' => '\Flow\Parquet\ThriftModel\Type', ], 2 => [ 'var' => 'encodings', @@ -33,7 +33,7 @@ class ColumnMetaData 'etype' => TType::I32, 'elem' => [ 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Encoding', + 'class' => '\Flow\Parquet\ThriftModel\Encoding', ], ], 3 => [ @@ -49,7 +49,7 @@ class ColumnMetaData 'var' => 'codec', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\CompressionCodec', + 'class' => '\Flow\Parquet\ThriftModel\CompressionCodec', ], 5 => [ 'var' => 'num_values', @@ -73,7 +73,7 @@ class ColumnMetaData 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\KeyValue', + 'class' => '\Flow\Parquet\ThriftModel\KeyValue', ], ], 9 => [ @@ -95,7 +95,7 @@ class ColumnMetaData 'var' => 'statistics', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\Statistics', + 'class' => '\Flow\Parquet\ThriftModel\Statistics', ], 13 => [ 'var' => 'encoding_stats', @@ -104,7 +104,7 @@ class ColumnMetaData 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\PageEncodingStats', + 'class' => '\Flow\Parquet\ThriftModel\PageEncodingStats', ], ], 14 => [ @@ -121,7 +121,7 @@ class ColumnMetaData 'var' => 'size_statistics', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\SizeStatistics', + 'class' => '\Flow\Parquet\ThriftModel\SizeStatistics', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnOrder.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnOrder.php index cb09aab8e2..d57d511bb3 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnOrder.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/ColumnOrder.php @@ -33,7 +33,7 @@ class ColumnOrder 'var' => 'TYPE_ORDER', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\TypeDefinedOrder', + 'class' => '\Flow\Parquet\ThriftModel\TypeDefinedOrder', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/DataPageHeader.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/DataPageHeader.php index 6b38b935c4..b61754efa5 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/DataPageHeader.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/DataPageHeader.php @@ -29,25 +29,25 @@ class DataPageHeader 'var' => 'encoding', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Encoding', + 'class' => '\Flow\Parquet\ThriftModel\Encoding', ], 3 => [ 'var' => 'definition_level_encoding', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Encoding', + 'class' => '\Flow\Parquet\ThriftModel\Encoding', ], 4 => [ 'var' => 'repetition_level_encoding', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Encoding', + 'class' => '\Flow\Parquet\ThriftModel\Encoding', ], 5 => [ 'var' => 'statistics', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\Statistics', + 'class' => '\Flow\Parquet\ThriftModel\Statistics', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/DataPageHeaderV2.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/DataPageHeaderV2.php index 674145a8b9..91f25116c0 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/DataPageHeaderV2.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/DataPageHeaderV2.php @@ -41,7 +41,7 @@ class DataPageHeaderV2 'var' => 'encoding', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Encoding', + 'class' => '\Flow\Parquet\ThriftModel\Encoding', ], 5 => [ 'var' => 'definition_levels_byte_length', @@ -62,7 +62,7 @@ class DataPageHeaderV2 'var' => 'statistics', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\Statistics', + 'class' => '\Flow\Parquet\ThriftModel\Statistics', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/DictionaryPageHeader.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/DictionaryPageHeader.php index b5efc68e18..f853a893f7 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/DictionaryPageHeader.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/DictionaryPageHeader.php @@ -30,7 +30,7 @@ class DictionaryPageHeader 'var' => 'encoding', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Encoding', + 'class' => '\Flow\Parquet\ThriftModel\Encoding', ], 3 => [ 'var' => 'is_sorted', diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/EncryptionAlgorithm.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/EncryptionAlgorithm.php index fb3d1d0cc5..c2001cd069 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/EncryptionAlgorithm.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/EncryptionAlgorithm.php @@ -21,13 +21,13 @@ class EncryptionAlgorithm 'var' => 'AES_GCM_V1', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\AesGcmV1', + 'class' => '\Flow\Parquet\ThriftModel\AesGcmV1', ], 2 => [ 'var' => 'AES_GCM_CTR_V1', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\AesGcmCtrV1', + 'class' => '\Flow\Parquet\ThriftModel\AesGcmCtrV1', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/FileCryptoMetaData.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/FileCryptoMetaData.php index 233de93e2f..53a398bb1b 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/FileCryptoMetaData.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/FileCryptoMetaData.php @@ -24,7 +24,7 @@ class FileCryptoMetaData 'var' => 'encryption_algorithm', 'isRequired' => true, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\EncryptionAlgorithm', + 'class' => '\Flow\Parquet\ThriftModel\EncryptionAlgorithm', ], 2 => [ 'var' => 'key_metadata', diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/FileMetaData.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/FileMetaData.php index e55606e54d..8c308ebf14 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/FileMetaData.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/FileMetaData.php @@ -32,7 +32,7 @@ class FileMetaData 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\SchemaElement', + 'class' => '\Flow\Parquet\ThriftModel\SchemaElement', ], ], 3 => [ @@ -47,7 +47,7 @@ class FileMetaData 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\RowGroup', + 'class' => '\Flow\Parquet\ThriftModel\RowGroup', ], ], 5 => [ @@ -57,7 +57,7 @@ class FileMetaData 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\KeyValue', + 'class' => '\Flow\Parquet\ThriftModel\KeyValue', ], ], 6 => [ @@ -72,14 +72,14 @@ class FileMetaData 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\ColumnOrder', + 'class' => '\Flow\Parquet\ThriftModel\ColumnOrder', ], ], 8 => [ 'var' => 'encryption_algorithm', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\EncryptionAlgorithm', + 'class' => '\Flow\Parquet\ThriftModel\EncryptionAlgorithm', ], 9 => [ 'var' => 'footer_signing_key_metadata', diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/LogicalType.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/LogicalType.php index a356a257a3..18ba9b0d1c 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/LogicalType.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/LogicalType.php @@ -28,85 +28,85 @@ class LogicalType 'var' => 'STRING', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\StringType', + 'class' => '\Flow\Parquet\ThriftModel\StringType', ], 2 => [ 'var' => 'MAP', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\MapType', + 'class' => '\Flow\Parquet\ThriftModel\MapType', ], 3 => [ 'var' => 'LIST', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\ListType', + 'class' => '\Flow\Parquet\ThriftModel\ListType', ], 4 => [ 'var' => 'ENUM', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\EnumType', + 'class' => '\Flow\Parquet\ThriftModel\EnumType', ], 5 => [ 'var' => 'DECIMAL', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\DecimalType', + 'class' => '\Flow\Parquet\ThriftModel\DecimalType', ], 6 => [ 'var' => 'DATE', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\DateType', + 'class' => '\Flow\Parquet\ThriftModel\DateType', ], 7 => [ 'var' => 'TIME', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\TimeType', + 'class' => '\Flow\Parquet\ThriftModel\TimeType', ], 8 => [ 'var' => 'TIMESTAMP', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\TimestampType', + 'class' => '\Flow\Parquet\ThriftModel\TimestampType', ], 10 => [ 'var' => 'INTEGER', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\IntType', + 'class' => '\Flow\Parquet\ThriftModel\IntType', ], 11 => [ 'var' => 'UNKNOWN', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\NullType', + 'class' => '\Flow\Parquet\ThriftModel\NullType', ], 12 => [ 'var' => 'JSON', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\JsonType', + 'class' => '\Flow\Parquet\ThriftModel\JsonType', ], 13 => [ 'var' => 'BSON', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\BsonType', + 'class' => '\Flow\Parquet\ThriftModel\BsonType', ], 14 => [ 'var' => 'UUID', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\UUIDType', + 'class' => '\Flow\Parquet\ThriftModel\UUIDType', ], 15 => [ 'var' => 'FLOAT16', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\Float16Type', + 'class' => '\Flow\Parquet\ThriftModel\Float16Type', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/OffsetIndex.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/OffsetIndex.php index cf298a2366..f92716c129 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/OffsetIndex.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/OffsetIndex.php @@ -31,7 +31,7 @@ class OffsetIndex 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\PageLocation', + 'class' => '\Flow\Parquet\ThriftModel\PageLocation', ], ], 2 => [ diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/PageEncodingStats.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/PageEncodingStats.php index 467340bc94..15a48a6129 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/PageEncodingStats.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/PageEncodingStats.php @@ -23,13 +23,13 @@ class PageEncodingStats 'var' => 'page_type', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\PageType', + 'class' => '\Flow\Parquet\ThriftModel\PageType', ], 2 => [ 'var' => 'encoding', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Encoding', + 'class' => '\Flow\Parquet\ThriftModel\Encoding', ], 3 => [ 'var' => 'count', diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/PageHeader.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/PageHeader.php index c12c3b0b76..b6639ab911 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/PageHeader.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/PageHeader.php @@ -21,7 +21,7 @@ class PageHeader 'var' => 'type', 'isRequired' => true, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\PageType', + 'class' => '\Flow\Parquet\ThriftModel\PageType', ], 2 => [ 'var' => 'uncompressed_page_size', @@ -42,25 +42,25 @@ class PageHeader 'var' => 'data_page_header', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\DataPageHeader', + 'class' => '\Flow\Parquet\ThriftModel\DataPageHeader', ], 6 => [ 'var' => 'index_page_header', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\IndexPageHeader', + 'class' => '\Flow\Parquet\ThriftModel\IndexPageHeader', ], 7 => [ 'var' => 'dictionary_page_header', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\DictionaryPageHeader', + 'class' => '\Flow\Parquet\ThriftModel\DictionaryPageHeader', ], 8 => [ 'var' => 'data_page_header_v2', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\DataPageHeaderV2', + 'class' => '\Flow\Parquet\ThriftModel\DataPageHeaderV2', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/RowGroup.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/RowGroup.php index 817c5e5c4f..ae4c23f498 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/RowGroup.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/RowGroup.php @@ -24,7 +24,7 @@ class RowGroup 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\ColumnChunk', + 'class' => '\Flow\Parquet\ThriftModel\ColumnChunk', ], ], 2 => [ @@ -44,7 +44,7 @@ class RowGroup 'etype' => TType::STRUCT, 'elem' => [ 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\SortingColumn', + 'class' => '\Flow\Parquet\ThriftModel\SortingColumn', ], ], 5 => [ diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/SchemaElement.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/SchemaElement.php index b5f223ab0b..525e6014f3 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/SchemaElement.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/SchemaElement.php @@ -27,7 +27,7 @@ class SchemaElement 'var' => 'type', 'isRequired' => false, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\Type', + 'class' => '\Flow\Parquet\ThriftModel\Type', ], 2 => [ 'var' => 'type_length', @@ -38,7 +38,7 @@ class SchemaElement 'var' => 'repetition_type', 'isRequired' => false, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\FieldRepetitionType', + 'class' => '\Flow\Parquet\ThriftModel\FieldRepetitionType', ], 4 => [ 'var' => 'name', @@ -54,7 +54,7 @@ class SchemaElement 'var' => 'converted_type', 'isRequired' => false, 'type' => TType::I32, - 'class' => '\Flow\Parquet\Thrift\ConvertedType', + 'class' => '\Flow\Parquet\ThriftModel\ConvertedType', ], 7 => [ 'var' => 'scale', @@ -75,7 +75,7 @@ class SchemaElement 'var' => 'logicalType', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\LogicalType', + 'class' => '\Flow\Parquet\ThriftModel\LogicalType', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimeType.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimeType.php index 4e1d123a9d..24ef8e9c47 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimeType.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimeType.php @@ -31,7 +31,7 @@ class TimeType 'var' => 'unit', 'isRequired' => true, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\TimeUnit', + 'class' => '\Flow\Parquet\ThriftModel\TimeUnit', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimeUnit.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimeUnit.php index 2f509bfac6..8367bda037 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimeUnit.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimeUnit.php @@ -21,19 +21,19 @@ class TimeUnit 'var' => 'MILLIS', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\MilliSeconds', + 'class' => '\Flow\Parquet\ThriftModel\MilliSeconds', ], 2 => [ 'var' => 'MICROS', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\MicroSeconds', + 'class' => '\Flow\Parquet\ThriftModel\MicroSeconds', ], 3 => [ 'var' => 'NANOS', 'isRequired' => false, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\NanoSeconds', + 'class' => '\Flow\Parquet\ThriftModel\NanoSeconds', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimestampType.php b/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimestampType.php index 4db030d8b0..2ad64ee927 100644 --- a/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimestampType.php +++ b/src/lib/parquet/src/Flow/Parquet/ThriftModel/TimestampType.php @@ -31,7 +31,7 @@ class TimestampType 'var' => 'unit', 'isRequired' => true, 'type' => TType::STRUCT, - 'class' => '\Flow\Parquet\Thrift\TimeUnit', + 'class' => '\Flow\Parquet\ThriftModel\TimeUnit', ], ]; diff --git a/src/lib/parquet/src/Flow/Parquet/Writer/RowGroupBuilder.php b/src/lib/parquet/src/Flow/Parquet/Writer/RowGroupBuilder.php index e8de322c4a..3720815145 100644 --- a/src/lib/parquet/src/Flow/Parquet/Writer/RowGroupBuilder.php +++ b/src/lib/parquet/src/Flow/Parquet/Writer/RowGroupBuilder.php @@ -26,6 +26,11 @@ final class RowGroupBuilder private int $rowsCount = 0; + /** + * Rows of the row groups flushed before this one: the writer's index of this group's first row. + */ + private int $flushedRows = 0; + public function __construct( private readonly Schema $schema, private readonly Compressions $compression, @@ -62,7 +67,7 @@ public function addRows(array $rows): void $this->flushBuffer(); foreach (array_chunk($rows, $interval) as $chunk) { - $flatColumnsData = $this->shredder->shred($this->schema, $chunk); + $flatColumnsData = $this->shredder->shred($this->schema, $chunk, $this->flushedRows + $this->rowsCount); foreach ($flatColumnsData as $flatPath => $columnValues) { $this->columnChunkBuilders->addColumnByFlatPath($flatPath, $columnValues); @@ -84,6 +89,7 @@ public function flush(int $fileOffset): RowGroupContainer $offset = $fileOffset; $buffer = ''; $chunks = []; + $this->flushedRows += $rowsCount; $this->rowsCount = 0; foreach ($this->columnChunkBuilders->flush($offset) as $container) { @@ -115,7 +121,11 @@ private function flushBuffer(): void return; } - $flatColumnsData = $this->shredder->shred($this->schema, $this->rowBuffer); + $flatColumnsData = $this->shredder->shred( + $this->schema, + $this->rowBuffer, + $this->flushedRows + $this->rowsCount - count($this->rowBuffer), + ); foreach ($flatColumnsData as $flatPath => $columnValues) { $this->columnChunkBuilders->addColumnByFlatPath($flatPath, $columnValues); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Context/EveryType.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/EveryType.php new file mode 100644 index 0000000000..ee88a7d3d3 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/EveryType.php @@ -0,0 +1,109 @@ +> + */ + public static function rows(): array + { + return [ + [ + 'boolean' => true, + 'int32' => -2_147_483_648, + 'int64' => PHP_INT_MAX, + 'float' => 0.1, + 'double' => 1 / 3, + 'string' => 'zażółć', + 'json' => '{"a":1}', + 'enum' => 'RED', + 'uuid' => '0190a6b0-6b1f-7c5e-9a3b-0123456789ab', + 'date' => new DateTimeImmutable('1969-12-31 23:00:00', new DateTimeZone('Europe/Warsaw')), + 'datetime' => new DateTimeImmutable('1960-01-01 12:34:56.789012', new DateTimeZone('America/New_York')), + 'time' => new DateInterval('PT25H3M4S'), + 'decimal' => 12_345_678.91, + 'decimal38' => 12_345_678_901_234_567_890.123456789, + 'fixed4' => "\x00\x01\x02\x03", + 'list_int' => [1, null, 3], + 'list_datetime' => [new DateTimeImmutable('2024-02-29 00:00:00.5')], + 'map_string_date' => ['a' => new DateTimeImmutable('2000-01-01'), 'b' => null], + 'struct' => [ + 'id' => '0190a6b0-6b1f-7c5e-9a3b-0123456789ab', + 'at' => new DateInterval('PT0S'), + 'amount' => -0.01, + ], + ], + array_fill_keys(array_map(static fn($column) => $column->name(), self::schema()->columns()), null), + [ + 'boolean' => false, + 'int32' => 0, + 'int64' => -1, + 'float' => -2.5e10, + 'double' => -0.0, + 'string' => '', + 'json' => '[]', + 'enum' => '', + 'uuid' => '00000000-0000-0000-0000-000000000000', + 'date' => new DateTimeImmutable('2262-04-11'), + 'datetime' => new DateTimeImmutable('@0'), + 'time' => new DateInterval('PT23H59M59S'), + 'decimal' => -99_999_999.99, + 'decimal38' => 0.000000001, + 'fixed4' => "\xFF\xFF\xFF\xFF", + 'list_int' => [], + 'list_datetime' => null, + 'map_string_date' => [], + 'struct' => ['id' => null, 'at' => null, 'amount' => null], + ], + ]; + } + + public static function schema(): Schema + { + return Schema::with( + FlatColumn::boolean('boolean'), + FlatColumn::int32('int32'), + FlatColumn::int64('int64'), + FlatColumn::float('float'), + FlatColumn::double('double'), + FlatColumn::string('string'), + FlatColumn::json('json'), + FlatColumn::enum('enum'), + FlatColumn::uuid('uuid'), + FlatColumn::date('date'), + FlatColumn::dateTime('datetime'), + FlatColumn::time('time'), + FlatColumn::decimal('decimal', 10, 2), + FlatColumn::decimal('decimal38', 38, 9), + FlatColumn::fixedSizeByteArray('fixed4', 4), + NestedColumn::list('list_int', ListElement::int64()), + NestedColumn::list('list_datetime', ListElement::datetime()), + NestedColumn::map('map_string_date', MapKey::string(), MapValue::date()), + NestedColumn::struct('struct', [ + FlatColumn::uuid('id'), + FlatColumn::time('at'), + FlatColumn::decimal('amount'), + ]), + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Context/FlatColumnPages.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/FlatColumnPages.php index 0298fb04c4..0eb8d501b1 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Context/FlatColumnPages.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/FlatColumnPages.php @@ -70,6 +70,7 @@ public static function shredded(Schema $schema, array $rows): array return (new DremelShredder(new ColumnDataValidator(), DataConverter::initialize(Options::default())))->shred( $schema, $rows, + 0, ); } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Context/MemoryParquetFile.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/MemoryParquetFile.php new file mode 100644 index 0000000000..f489726394 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/MemoryParquetFile.php @@ -0,0 +1,73 @@ +set(Option::ROW_GROUP_SIZE_BYTES, 1) + ->set(Option::ROW_GROUP_SIZE_CHECK_INTERVAL, 2) + ->set(Option::PAGE_SIZE_BYTES, 1) + ->set(Option::PAGE_SIZE_CHECK_INTERVAL, 1), + ), + Schema::with(FlatColumn::int64('id'), NestedColumn::list('tags', ListElement::string())), + array_map(static fn(int $id): array => ['id' => $id, 'tags' => ['t' . $id]], range(1, 6)), + ); + } + + /** + * @param non-empty-string $bytes + * + * @return ParquetFile + */ + public static function read(Reader $reader, string $bytes): ParquetFile + { + return $reader->readStream(new MemorySourceStream($bytes)); + } + + /** + * @param iterable> $rows + * + * @return non-empty-string + */ + public static function written(Writer $writer, Schema $schema, iterable $rows): string + { + $stream = new StringDestinationStream(path('memory://file.parquet')); + $writer->writeStream($stream, $schema, $rows); + $content = $stream->content(); + + return $content !== '' ? $content : throw new RuntimeException('Nothing was written'); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Context/ParquetRows.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/ParquetRows.php new file mode 100644 index 0000000000..d07045df5e --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/ParquetRows.php @@ -0,0 +1,50 @@ + $file + * @param int<1, max> $batchSize + * @param list $columns + * + * @return list> + */ + public static function read( + ParquetFile $file, + int $batchSize, + array $columns = [], + ?int $limit = null, + ?int $offset = null, + ): array { + $rows = []; + + foreach ($file->columns($batchSize, $columns, $limit, $offset) as $chunk) { + $names = array_keys($chunk); + + for ($i = 0, $count = count($chunk[$names[0]]); $i < $count; $i++) { + $row = []; + + foreach ($names as $name) { + $row[$name] = $chunk[$name][$i]; + } + + $rows[] = $row; + } + } + + return $rows; + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Context/WriteAcceptance.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/WriteAcceptance.php new file mode 100644 index 0000000000..879d490e66 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Context/WriteAcceptance.php @@ -0,0 +1,190 @@ + true, + 'int 1' => 1, + 'int -1' => -1, + 'int 4000000000' => 4_000_000_000, + 'int PHP_INT_MAX' => PHP_INT_MAX, + 'float 1.5' => 1.5, + 'float 1.0' => 1.0, + 'float 12345678.915' => 12_345_678.915, + 'string "1"' => '1', + 'string "1.25"' => '1.25', + 'string "abc"' => 'abc', + 'string 36 uuid' => '0190a6b0-6b1f-7c5e-9a3b-0123456789ab', + 'string 16 bytes' => str_repeat("\x01", 16), + 'string 4 bytes' => "\x00\x01\x02\x03", + 'string 5 bytes' => '12345', + 'string \xFF\xFE' => "\xFF\xFE", + 'DateTimeImmutable Warsaw' => new DateTimeImmutable( + '2024-02-29 23:30:00.123456', + new DateTimeZone('Europe/Warsaw'), + ), + 'DateInterval PT25H' => new DateInterval('PT25H'), + 'DateInterval P1M' => new DateInterval('P1M'), + 'DateInterval -PT1H' => (new DateTimeImmutable('@3600'))->diff(new DateTimeImmutable('@0')), + 'toString() uuid object' => new ToStringUuid('0190a6b0-6b1f-7c5e-9a3b-0123456789ab'), + 'array [1]' => [1], + 'array [a=>1]' => ['a' => 1], + 'null' => null, + default => throw new InvalidArgumentException("Unknown input \"{$name}\""), + }; + } + + /** + * @return list + */ + public static function inputs(): array + { + return [ + 'true', + 'int 1', + 'int -1', + 'int 4000000000', + 'int PHP_INT_MAX', + 'float 1.5', + 'float 1.0', + 'float 12345678.915', + 'string "1"', + 'string "1.25"', + 'string "abc"', + 'string 36 uuid', + 'string 16 bytes', + 'string 4 bytes', + 'string 5 bytes', + 'string \xFF\xFE', + 'DateTimeImmutable Warsaw', + 'DateInterval PT25H', + 'DateInterval P1M', + 'DateInterval -PT1H', + 'toString() uuid object', + 'array [1]', + 'array [a=>1]', + 'null', + ]; + } + + public static function target(string $name): Column + { + return match ($name) { + 'BOOLEAN' => FlatColumn::boolean('c'), + 'INT32' => FlatColumn::int32('c'), + 'INT32 INT_8' => new FlatColumn('c', PhysicalType::INT32, ConvertedType::INT_8), + 'INT32 UINT_32' => new FlatColumn('c', PhysicalType::INT32, ConvertedType::UINT_32), + 'INT64' => FlatColumn::int64('c'), + 'INT64 REQUIRED' => FlatColumn::int64('c', Repetition::REQUIRED), + 'INT64 UINT_64' => new FlatColumn('c', PhysicalType::INT64, ConvertedType::UINT_64), + 'FLOAT' => FlatColumn::float('c'), + 'DOUBLE' => FlatColumn::double('c'), + 'STRING' => FlatColumn::string('c'), + 'JSON' => FlatColumn::json('c'), + 'ENUM' => FlatColumn::enum('c'), + 'BYTE_ARRAY' => new FlatColumn('c', PhysicalType::BYTE_ARRAY), + 'UUID' => FlatColumn::uuid('c'), + 'FIXED(4)' => FlatColumn::fixedSizeByteArray('c', 4), + 'DECIMAL(10,2)' => FlatColumn::decimal('c', 10, 2), + 'DATE' => FlatColumn::date('c'), + 'TIMESTAMP MILLIS' => new FlatColumn( + 'c', + PhysicalType::INT64, + logicalType: new LogicalType( + LogicalType::TIMESTAMP, + timestamp: new Timestamp(true, TimeUnit::MILLISECONDS), + ), + ), + 'TIMESTAMP MICROS' => FlatColumn::dateTime('c'), + 'TIMESTAMP NANOS' => new FlatColumn( + 'c', + PhysicalType::INT64, + logicalType: new LogicalType( + LogicalType::TIMESTAMP, + timestamp: new Timestamp(true, TimeUnit::NANOSECONDS), + ), + ), + 'TIME MILLIS' => new FlatColumn( + 'c', + PhysicalType::INT32, + logicalType: new LogicalType(LogicalType::TIME, time: new Time(false, TimeUnit::MILLISECONDS)), + ), + 'TIME MICROS' => FlatColumn::time('c'), + 'TIME NANOS' => new FlatColumn( + 'c', + PhysicalType::INT64, + logicalType: new LogicalType(LogicalType::TIME, time: new Time(false, TimeUnit::NANOSECONDS)), + ), + 'LIST' => NestedColumn::list('c', ListElement::int64()), + 'MAP' => NestedColumn::map('c', MapKey::string(), MapValue::int64()), + 'STRUCT{a INT64}' => NestedColumn::struct('c', [FlatColumn::int64('a')]), + default => throw new InvalidArgumentException("Unknown target \"{$name}\""), + }; + } + + /** + * @return list + */ + public static function targets(): array + { + return [ + 'BOOLEAN', + 'INT32', + 'INT32 INT_8', + 'INT32 UINT_32', + 'INT64', + 'INT64 REQUIRED', + 'INT64 UINT_64', + 'FLOAT', + 'DOUBLE', + 'STRING', + 'JSON', + 'ENUM', + 'BYTE_ARRAY', + 'UUID', + 'FIXED(4)', + 'DECIMAL(10,2)', + 'DATE', + 'TIMESTAMP MILLIS', + 'TIMESTAMP MICROS', + 'TIMESTAMP NANOS', + 'TIME MILLIS', + 'TIME MICROS', + 'TIME NANOS', + 'LIST', + 'MAP', + 'STRUCT{a INT64}', + ]; + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Double/ReadCountingSourceStream.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Double/ReadCountingSourceStream.php new file mode 100644 index 0000000000..9094fb9946 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Double/ReadCountingSourceStream.php @@ -0,0 +1,72 @@ +closed = true; + $this->inner->close(); + } + + public function content(): string + { + return $this->inner->content(); + } + + public function isOpen(): bool + { + return $this->inner->isOpen(); + } + + public function iterate(int $length = 1): Generator + { + yield from $this->inner->iterate($length); + } + + public function path(): Path + { + return $this->inner->path(); + } + + public function read(int $length, int $offset): string + { + $read = $this->inner->read($length, $offset); + $this->reads++; + $this->bytes += strlen($read); + + return $read; + } + + public function readLines(string $separator = "\n", ?int $length = null): Generator + { + yield from $this->inner->readLines($separator, $length); + } + + public function size(): ?int + { + return $this->inner->size(); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Double/SpyParquetFileReader.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Double/SpyParquetFileReader.php new file mode 100644 index 0000000000..4e8282f569 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Double/SpyParquetFileReader.php @@ -0,0 +1,64 @@ +, int, ?int, ?int}> + */ + public array $reads = []; + + /** + * @param list>> $chunks + */ + public function __construct( + private readonly Schema $schema, + private readonly array $chunks = [], + ) {} + + public function close(): void + { + $this->closes++; + } + + public function metadata(): Metadata + { + return new Metadata($this->schema, new RowGroups([]), 0, 1, null); + } + + public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator + { + $this->reads[] = [$columns, $batchSize, $limit, $offset]; + + yield from $this->chunks; + } + + public function rowsNumber(): int + { + return 0; + } + + public function schema(): Schema + { + return $this->schema; + } + + public function totalByteSize(): int + { + return 0; + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Double/StringableUuid.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Double/StringableUuid.php new file mode 100644 index 0000000000..57e1a8d157 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Double/StringableUuid.php @@ -0,0 +1,22 @@ +text; + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Double/ToStringUuid.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Double/ToStringUuid.php new file mode 100644 index 0000000000..7d617fe2b6 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Double/ToStringUuid.php @@ -0,0 +1,20 @@ +text; + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php index 12fa023e43..0c800ac4f9 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php @@ -13,7 +13,6 @@ use Flow\Parquet\ParquetFile\Schema\MapValue; use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\ParquetFile\Schema\Repetition; -use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\Group; @@ -30,8 +29,8 @@ final class ArrowParquetEngineReadTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('arrow')) { - self::markTestSkipped('Arrow extension is not loaded'); + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + self::markTestSkipped('Neither flow_php nor arrow is loaded'); } } @@ -60,11 +59,8 @@ public function test_read_flat_columns(): void (new Writer())->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'name', 'active', 'score'], batchSize: 2, limit: null, @@ -99,11 +95,8 @@ public function test_read_nested_lists(): void (new Writer())->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'tags'], batchSize: 2, limit: null, @@ -132,11 +125,8 @@ public function test_read_nested_maps(): void (new Writer())->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'metadata'], batchSize: 2, limit: null, @@ -171,11 +161,8 @@ public function test_read_nested_structs(): void (new Writer())->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'address'], batchSize: 2, limit: null, @@ -208,11 +195,8 @@ public function test_read_nested_uuid_as_canonical_strings(): void ]]); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['top_uuid', 'body', 'uuid_list'], batchSize: 2, limit: null, @@ -249,11 +233,8 @@ public function test_read_with_column_projection(): void (new Writer())->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'name'], batchSize: 2, limit: null, @@ -276,11 +257,8 @@ public function test_read_with_limit(): void (new Writer())->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id'], batchSize: 2, limit: 5, @@ -303,11 +281,8 @@ public function test_read_with_limit_and_offset(): void (new Writer())->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id'], batchSize: 2, limit: 5, @@ -330,11 +305,8 @@ public function test_read_with_offset(): void (new Writer())->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id'], batchSize: 2, limit: null, diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php index d7cc6bafe8..7148792633 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php @@ -30,8 +30,8 @@ final class ArrowParquetEngineWriteTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('arrow')) { - self::markTestSkipped('Arrow extension is not loaded'); + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + self::markTestSkipped('Neither flow_php nor arrow is loaded'); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php index 335322461b..afb8769614 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php @@ -29,8 +29,8 @@ final class CrossEngineTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('arrow')) { - self::markTestSkipped('Arrow extension is not loaded'); + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + self::markTestSkipped('Neither flow_php nor arrow is loaded'); } } @@ -58,13 +58,9 @@ public function test_arrow_write_arrow_read_roundtrip(): void $writeStream = NativeLocalDestinationStream::openBlank(path($path)); $engine->writeRows($writeStream, $schema, Compressions::SNAPPY, new Options(), $inputData); - - $parquetFile = (new Reader())->read($path); $readStream = NativeLocalSourceStream::open(path_real($path)); $chunks = iterator_to_array( - $engine->readColumns( - $readStream, - $parquetFile->schema(), + $engine->openForRead($readStream)->readColumns( ['id', 'label', 'big_number'], batchSize: 2, limit: null, @@ -156,11 +152,8 @@ public function test_php_write_arrow_read(): void (new Writer(engine: new PhpParquetEngine()))->write($path, $schema, $inputData); $engine = new ArrowParquetEngine(); - $parquetFile = (new Reader())->read($path); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - $parquetFile->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'name', 'value'], batchSize: 2, limit: null, diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php index f96dc7af1d..39aab5124d 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php @@ -20,8 +20,8 @@ final class EngineParityTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('arrow')) { - self::markTestSkipped('Arrow extension is not loaded'); + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + self::markTestSkipped('Neither flow_php nor arrow is loaded'); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php new file mode 100644 index 0000000000..bd75d9ee60 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php @@ -0,0 +1,146 @@ +, ?int, ?int}> + */ + public static function fixtures(): Generator + { + $fixtures = __DIR__ . '/../IO/Fixtures'; + + foreach ([ + ...(glob($fixtures . '/*.parquet') ?: []), + ...(glob($fixtures . '/EdgeCases/*.parquet') ?: []), + ] as $path) { + if (in_array(basename($path), ['interval.parquet', 'uint64_overflow.parquet', 'map_keys.parquet'], true)) { + continue; + } + + [$limit, $offset] = str_starts_with(basename($path), 'pagination') ? [400, 4550] : [null, null]; + + foreach ([100, 10_000] as $batchSize) { + yield basename($path) . " batch {$batchSize}" => [$path, $batchSize, $limit, $offset]; + } + } + } + + /** + * @param int<1, max> $batchSize + */ + #[DataProvider('fixtures')] + public function test_a_fixture_reads_the_values_of_the_php_engine( + string $path, + int $batchSize, + ?int $limit, + ?int $offset, + ): void { + static::assertSame( + var_export(ParquetRows::read(Reader::php()->read($path), $batchSize, [], $limit, $offset), true), + var_export(ParquetRows::read(Reader::arrow()->read($path), $batchSize, [], $limit, $offset), true), + ); + } + + public function test_every_type_reads_the_values_of_the_php_engine(): void + { + $bytes = MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows()); + + static::assertSame( + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $bytes), 2), true), + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 2), true), + ); + } + + public function test_an_interval_column_is_refused_naming_it_and_the_php_reader(): void + { + $path = __DIR__ . '/../IO/Fixtures/EdgeCases/interval.parquet'; + + static::assertSame( + ParquetRows::read(Reader::php()->read($path), 100, ['id']), + ParquetRows::read(Reader::arrow()->read($path), 100, ['id']), + ); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'Parquet column "iv" (Interval(DayTime)) is not supported by the flow_php Parquet reader; read the file ' + . 'with \Flow\Parquet\Reader::php()', + ); + + ParquetRows::read(Reader::arrow()->read($path), 100); + } + + public function test_a_uint64_above_php_int_max_is_refused_by_both_engines(): void + { + $path = __DIR__ . '/../IO/Fixtures/EdgeCases/uint64_overflow.parquet'; + + try { + ParquetRows::read(Reader::php()->read($path), 100); + static::fail('PhpParquetEngine must refuse a UINT_64 above PHP_INT_MAX'); + } catch (DataConversionException $exception) { + static::assertStringContainsString('holds a UINT_64 value above PHP_INT_MAX', $exception->getMessage()); + } + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'Parquet column "u64" row 0 holds a value out of the range flow_php stores it in', + ); + + ParquetRows::read(Reader::arrow()->read($path), 100); + } + + #[TestWith(['double_key', 'float'])] + #[TestWith(['date_key', 'DateTimeImmutable'])] + #[TestWith(['bool_key', 'bool'])] + public function test_a_map_key_a_php_array_cannot_hold_is_refused_by_both_engines( + string $column, + string $type, + ): void { + $path = __DIR__ . '/../IO/Fixtures/EdgeCases/map_keys.parquet'; + + static::assertSame( + ParquetRows::read(Reader::php()->read($path), 10, ['id']), + ParquetRows::read(Reader::arrow()->read($path), 10, ['id']), + ); + + try { + ParquetRows::read(Reader::php()->read($path), 10, [$column]); + static::fail('PhpParquetEngine must refuse the map key'); + } catch (InvalidArgumentException $exception) { + static::assertSame("Map key must be int or string, got {$type}", $exception->getMessage()); + } + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage("Map key of Parquet column \"{$column}\" must be int or string, got {$type}"); + + ParquetRows::read(Reader::arrow()->read($path), 10, [$column]); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php new file mode 100644 index 0000000000..bbe5971dea --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php @@ -0,0 +1,183 @@ +read(self::PAGINATION)->metadata()->rowGroups()->all()[49]->columnChunks() as $chunk) { + $group += $chunk->totalCompressedSize(); + } + + $stream = new ReadCountingSourceStream(NativeLocalSourceStream::open(path_real(self::PAGINATION))); + $rows = iterator_to_array(Reader::arrow()->readStream($stream)->values([], 10, 4990), false); + + static::assertCount(10, $rows); + static::assertLessThanOrEqual($footer + 8 + $group, $stream->bytes); + } + + public function test_a_full_read_reads_the_file_about_once(): void + { + $stream = new ReadCountingSourceStream(NativeLocalSourceStream::open(path_real(self::PAGINATION))); + + static::assertCount(5000, iterator_to_array(Reader::arrow()->readStream($stream)->values(), false)); + static::assertLessThanOrEqual((int) filesize(self::PAGINATION) + (64 * 1024), $stream->bytes); + } + + public function test_invalid_utf8_is_refused_naming_column_and_row(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Parquet column "name" row 1 holds a string that is not valid UTF-8'); + + MemoryParquetFile::written(Writer::arrow(), Schema::with(FlatColumn::string('name')), [ + ['name' => 'ok'], + ['name' => "\xFF\xFE"], + ]); + } + + public function test_a_time_of_a_day_and_an_hour_keeps_its_day(): void + { + $interval = (new DateTimeImmutable('2024-01-01 00:00:00'))->diff(new DateTimeImmutable('2024-01-02 01:00:00')); + $bytes = MemoryParquetFile::written(Writer::arrow(), Schema::with(FlatColumn::time('t')), [['t' => $interval]]); + static::assertSame( + var_export($interval, true), + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 10)[0]['t'], true), + ); + } + + public function test_int96_reads_exactly_outside_the_nanosecond_range(): void + { + $values = array_column( + ParquetRows::read(Reader::arrow()->read(__DIR__ . '/../IO/Fixtures/EdgeCases/int96.parquet'), 10), + 'ts', + ); + + static::assertEquals(new DateTimeImmutable('0001-01-01 00:00:00.000001', new DateTimeZone('UTC')), $values[3]); + static::assertEquals(new DateTimeImmutable('1960-01-01 23:59:59.999999', new DateTimeZone('UTC')), $values[2]); + } + + public function test_dates_are_utc_and_times_carry_their_day_count(): void + { + $bytes = MemoryParquetFile::written( + Writer::php(), + Schema::with(FlatColumn::date('d'), FlatColumn::time('t')), + [[ + 'd' => new DateTimeImmutable('2024-02-29'), + 't' => (new DateTimeImmutable('@0'))->diff(new DateTimeImmutable('@90000')), + ]], + ); + + static::assertSame( + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $bytes), 1), true), + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 1), true), + ); + static::assertStringContainsString("'timezone' => 'UTC'", var_export( + ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 1)[0]['d'], + true, + )); + } + + public function test_a_logical_only_unsigned_integer_reads_as_itself_through_both_engines(): void + { + $bytes = MemoryParquetFile::written( + Writer::php(), + Schema::with(new FlatColumn('u', PhysicalType::INT32, logicalType: LogicalType::integer(32, false))), + [['u' => 4_000_000_000]], + ); + + static::assertSame( + [['u' => 4_000_000_000]], + ParquetRows::read(MemoryParquetFile::read(Reader::php(), $bytes), 1), + ); + static::assertSame( + [['u' => 4_000_000_000]], + ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 1), + ); + } + + public function test_a_schema_read_from_an_arrow_rs_file_rewritten_by_the_php_engine_opens_in_flow_php(): void + { + $arrow = MemoryParquetFile::written( + Writer::arrow(), + Schema::with( + new FlatColumn('i8', PhysicalType::INT32, ConvertedType::INT_8), + new FlatColumn('u32', PhysicalType::INT32, ConvertedType::UINT_32), + ), + [['i8' => -5, 'u32' => 4_000_000_000]], + ); + $schema = MemoryParquetFile::read(Reader::php(), $arrow)->schema(); + $rewritten = MemoryParquetFile::written(Writer::php(), $schema, [['i8' => -5, 'u32' => 4_000_000_000]]); + + static::assertSame(8, $schema->get('i8')->logicalType()?->integerData()?->bitWidth()); + static::assertGreaterThan(0, strlen($rewritten)); + static::assertSame( + [['i8' => -5, 'u32' => 4_000_000_000]], + ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $rewritten), 1), + ); + } + + public function test_times_of_day_and_longer_read_as_the_php_engine_reads_them(): void + { + $base = new DateTimeImmutable('1970-01-01 00:00:00.000000', new DateTimeZone('UTC')); + $rows = array_map(static fn(int $micros): array => [ + 't' => $base->diff($base->modify("+{$micros} microseconds")), + ], [ + 0, + 1, + 999_999, + 13_298_519_488, + 45_296_789_012, + 86_399_999_999, + 86_400_000_000, + 90_000_000_001, + ...range(1, 86_399_999_999, 172_799_999), + ]); + $bytes = MemoryParquetFile::written(Writer::php(), Schema::with(FlatColumn::time('t')), $rows); + + static::assertSame( + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $bytes), 1_000), true), + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 1_000), true), + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php new file mode 100644 index 0000000000..fe24913c2a --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php @@ -0,0 +1,107 @@ + + */ + public static function cells(): Generator + { + foreach (WriteAcceptance::targets() as $target) { + foreach (WriteAcceptance::inputs() as $input) { + yield "{$target} <- {$input}" => [$target, $input]; + } + } + } + + #[DataProvider('cells')] + public function test_both_writers_accept_and_refuse_the_same(string $target, string $input): void + { + $written = []; + + foreach (['php' => Writer::php(), 'native' => Writer::arrow()] as $engine => $writer) { + try { + $written[$engine] = MemoryParquetFile::written( + $writer, + Schema::with(WriteAcceptance::target($target)), + [['c' => WriteAcceptance::input($input)]], + ); + } catch (Throwable) { + $written[$engine] = null; + } + } + + static::assertSame($written['php'] === null, $written['native'] === null); + + if ($written['php'] !== null && $written['native'] !== null) { + static::assertSame( + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $written['php']), 1), true), + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $written['native']), 1), true), + ); + } + } + + /** + * The values PhpParquetEngine used to write wrongly (#27, #28, #16). + * + * @return Generator + */ + public static function wrongly_written(): Generator + { + yield 'INT32 out of range' => ['INT32', 'int 4000000000']; + yield 'INT_8 out of range' => ['INT32 INT_8', 'int PHP_INT_MAX']; + yield 'UINT_32 negative' => ['INT32 UINT_32', 'int -1']; + yield 'UINT_64 negative' => ['INT64 UINT_64', 'int -1']; + yield 'UUID of 16 raw bytes' => ['UUID', 'string 16 bytes']; + yield 'FIXED(4) of 5 bytes' => ['FIXED(4)', 'string 5 bytes']; + yield 'FIXED(4) of 36 bytes' => ['FIXED(4)', 'string 36 uuid']; + yield 'invalid UTF-8 into STRING' => ['STRING', 'string \xFF\xFE']; + yield 'invalid UTF-8 into JSON' => ['JSON', 'string \xFF\xFE']; + yield 'invalid UTF-8 into ENUM' => ['ENUM', 'string \xFF\xFE']; + } + + #[DataProvider('wrongly_written')] + public function test_the_php_engine_refuses_what_it_used_to_write_wrongly(string $target, string $input): void + { + $this->expectException(ValidationException::class); + $this->expectExceptionMessage('Column "c" row 0: '); + + MemoryParquetFile::written(Writer::php(), Schema::with(WriteAcceptance::target($target)), [[ + 'c' => WriteAcceptance::input($input), + ]]); + } + + public function test_every_type_writes_the_same_through_both_writers(): void + { + $php = MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows()); + $native = MemoryParquetFile::written(Writer::arrow(), EveryType::schema(), EveryType::rows()); + + static::assertSame( + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $php), 3), true), + var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $native), 3), true), + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeParquetFileReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeParquetFileReaderTest.php new file mode 100644 index 0000000000..77805283eb --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeParquetFileReaderTest.php @@ -0,0 +1,115 @@ + new NativeParquetFileReader( + new NativeParquetFile(NativeLocalSourceStream::open(path_real(self::FIXTURES . '/structs.parquet'))), + new Options(), + ); + $metadata = $open()->metadata(); + $bytes = 0; + + foreach ($metadata->rowGroups()->all() as $rowGroup) { + $bytes += $rowGroup->totalByteSize(); + } + + static::assertEquals($metadata->schema(), $open()->schema()); + static::assertSame($metadata->rowsNumber(), $open()->rowsNumber()); + static::assertSame($bytes, $open()->totalByteSize()); + static::assertEquals(Reader::php()->read(self::FIXTURES . '/structs.parquet')->metadata(), $metadata); + } + + public function test_every_call_after_close_throws(): void + { + $reader = new NativeParquetFileReader( + new NativeParquetFile(NativeLocalSourceStream::open(path_real(self::FIXTURES . '/structs.parquet'))), + new Options(), + ); + $reader->metadata(); + $reader->close(); + + foreach ([ + static fn() => $reader->metadata(), + static fn() => $reader->schema(), + static fn() => $reader->rowsNumber(), + static fn() => $reader->totalByteSize(), + static fn() => $reader->file(), + static fn() => iterator_to_array($reader->readColumns(['struct_flat'], 1, null, null)), + static fn() => $reader->close(), + ] as $call) { + try { + $call(); + static::fail('A call on a closed reader must throw'); + } catch (RuntimeException $exception) { + static::assertSame('Reader is not open', $exception->getMessage()); + } + } + } + + public function test_int96_is_refused_when_it_is_not_read_as_a_datetime(): void + { + $options = (new Options())->set(Option::INT_96_AS_DATETIME, false); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Parquet column "ts" holds INT96, which flow_php reads only as a datetime (Option::INT_96_AS_DATETIME = ' + . 'true); read the file with \Flow\Parquet\Reader::php()', + ); + + ParquetRows::read(Reader::arrow($options)->read(self::FIXTURES . '/EdgeCases/int96.parquet'), 10); + } + + public function test_a_struct_path_reads_the_values_of_the_php_engine(): void + { + static::assertSame( + ParquetRows::read(Reader::php()->read(self::FIXTURES . '/structs.parquet'), 30, ['struct_flat.int']), + ParquetRows::read(Reader::arrow()->read(self::FIXTURES . '/structs.parquet'), 30, ['struct_flat.int']), + ); + } + + public function test_a_path_into_a_list_is_refused_naming_the_php_reader(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'Parquet column "list.list.element" (a path into LIST/MAP) is not supported by the flow_php Parquet ' + . 'reader; read the file with \Flow\Parquet\Reader::php()', + ); + + ParquetRows::read(Reader::arrow()->read(self::FIXTURES . '/lists.parquet'), 10, ['list.list.element']); + } + + public function test_a_file_that_is_not_parquet_is_refused_when_it_is_opened(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Given file is not valid Parquet file: Invalid Parquet file. Corrupt footer'); + + Reader::arrow()->readStream(new MemorySourceStream('{"not": "parquet"}')); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php index a1ab6d3ef3..e7e615af4f 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php @@ -11,7 +11,6 @@ use Flow\Parquet\ParquetFile\Schema\ListElement; use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\ParquetFile\Schema\Repetition; -use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; use Flow\Parquet\Tests\Integration\IO\ParquetIntegrationTestCase; use Flow\Parquet\Writer; @@ -65,11 +64,7 @@ public function test_chunks_follow_batch_size_limit_and_offset( ); $chunks = iterator_to_array( - $engine->readColumns( - NativeLocalSourceStream::open(path_real($path)), - (new Reader()) - ->read($path) - ->schema(), + $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'tags'], $batchSize, $limit, diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/int96.parquet b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/int96.parquet new file mode 100644 index 0000000000000000000000000000000000000000..0a3967146e52027b7abc7753556e1c089689aab3 GIT binary patch literal 351 zcmWG=3^EjD5uLyYL_VTCq6|U|43+y?s*N-m7%p|GGQdEOtt!L+|9%sv_%SfJ>#H)n zV1~#9xkxcQhq8741v0#sow-j2D0QS=l|ht2R7_M%N0d)gK$K0Cje&s)D8X#c%-nH| zNm7VOQi2EB6d)JbAWZBWw*^*f1&m@)pQ(wwHly}VjC~L~0{Z^=|HLtQ>g|z=X^dIjb#c4C0g{nRFuU(jL Wn|Tv&uH(~%uXBJee)(I&^85%h|o>p6@%~Irp;q*^SMBWtdiANQ)#(0;o9z0F)%MI{OD(AH_)7&iTZ#}dHQJZLg`Lfl&5 z521?Nd|Cp;2{6AI18wzs{@*zvJ|{;#tB*{`GSnI9q6mf@`5`|sm9mx)jSDRYE3!+c z=|I3#0V_pHo|P&}49G6{wOK7|3PEU$E3*}m#(1aXfu?x!uxkN*m7kk05{VUWCA329 zY&XX@ZE}oM!Sx}y#G?wW;F|4LbImDx#s9Psf;K9@cNn9r%umfP;*unqq$&8$t69X) zsd69G%_{hH9(??l= M#R;|yP^TZo4}1@zD*ylh literal 0 HcmV?d00001 diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/uint64_overflow.parquet b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/Fixtures/EdgeCases/uint64_overflow.parquet new file mode 100644 index 0000000000000000000000000000000000000000..b8755d372bffa8cd2a7b46015729d861812e5e7f GIT binary patch literal 196 zcmWG=3^EjD5S0;C&=F+3usm>B;3usSQr^JvfnWRSwL|eQ3E6eVj&O({~@3r zqzD8=nIvsY86RC zjv9juP@^b=Bv^?klNgJbotTpvhm9G71`Egy5 [new PhpParquetEngine()]]; - if (extension_loaded('arrow')) { + if (extension_loaded('flow_php') || extension_loaded('arrow')) { $engines['arrow'] = [new ArrowParquetEngine()]; } @@ -34,7 +34,7 @@ public static function engine_pair_provider(): array { $pairs = ['php/php' => [new PhpParquetEngine(), new PhpParquetEngine()]]; - if (extension_loaded('arrow')) { + if (extension_loaded('flow_php') || extension_loaded('arrow')) { $pairs['php/arrow'] = [new PhpParquetEngine(), new ArrowParquetEngine()]; $pairs['arrow/php'] = [new ArrowParquetEngine(), new PhpParquetEngine()]; $pairs['arrow/arrow'] = [new ArrowParquetEngine(), new ArrowParquetEngine()]; diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SchemaReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SchemaReadingTest.php index 1c13ec745f..6d62ab6041 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SchemaReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SchemaReadingTest.php @@ -131,8 +131,8 @@ public function test_reading_primitives_schema_ddl(ParquetEngine $engine): void FlatColumn::time('time_nullable'), FlatColumn::string('uuid'), // files generated by python are storing uuid as strings FlatColumn::string('uuid_nullable'), - FlatColumn::enum('enum'), - FlatColumn::enum('enum_nullable'), + FlatColumn::string('enum'), // files generated by python are storing enums as strings + FlatColumn::string('enum_nullable'), FlatColumn::float('float'), FlatColumn::float('float_nullable'), FlatColumn::double('double'), diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php index 5fb6cc028a..e2f889f855 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php @@ -75,7 +75,7 @@ public static function decimalPrecisionProvider(): array $engines = ['php' => new PhpParquetEngine()]; - if (extension_loaded('arrow')) { + if (extension_loaded('flow_php') || extension_loaded('arrow')) { $engines['arrow'] = new ArrowParquetEngine(); } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/ParquetFile/SchemaTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/ParquetFile/SchemaTest.php index be7fc48d5f..eb468d4b70 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/ParquetFile/SchemaTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/ParquetFile/SchemaTest.php @@ -37,7 +37,7 @@ public function test_dremel_paper_data_schema(): void foreach ($rows as $row) { /** @var array $row */ static::assertIsArray($row); - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); foreach ($schema->columns() as $column) { $readFlatValues = []; diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ColumnData/WriteFlatColumnValuesTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ColumnData/WriteFlatColumnValuesTest.php index 46a2d5370d..ddc579ef7a 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ColumnData/WriteFlatColumnValuesTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/ColumnData/WriteFlatColumnValuesTest.php @@ -92,7 +92,7 @@ public function test_skip_rows_with_struct_containing_list_of_strings(): void )); $shredder = new DremelShredder(new ColumnDataValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $flatColumnValues = $result['struct.list_of_string.list.element']; static::assertSame(10, $flatColumnValues->rowsCount()); @@ -203,7 +203,7 @@ public function test_split_by_rows_with_struct_containing_list_of_strings(): voi )); $shredder = new DremelShredder(new ColumnDataValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $flatColumnValues = $result['struct.list_of_string.list.element']; $splitResult = $flatColumnValues->splitByRows(20); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelFlatTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelFlatTest.php index 4e07edb81d..c1572efa8d 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelFlatTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelFlatTest.php @@ -52,7 +52,7 @@ public function test_optional_int32(array $row, array $flatData): void static::assertEquals(0, $schema->get('int32')->repetitions()->maxRepetitionLevel()); $shredder = new DremelShredder(new ColumnDataValidator(), DataConverter::initialize(Options::default())); - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; @@ -118,9 +118,9 @@ public function test_required_int32(array $row, array $flatData, ?string $except if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelListsTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelListsTest.php index 29872a9fbb..35475ba76e 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelListsTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelListsTest.php @@ -102,7 +102,7 @@ public function test_optional_list_optional_int32(array $rows, array $expectedCo static::assertEquals(3, $schema->get('l.list.element')->repetitions()->maxDefinitionLevel()); static::assertEquals(1, $schema->get('l.list.element')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -267,7 +267,7 @@ public function test_optional_list_optional_list_optional_int32(array $rows, arr static::assertEquals(5, $schema->get('l.list.element.list.element')->repetitions()->maxDefinitionLevel()); static::assertEquals(2, $schema->get('l.list.element.list.element')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -387,7 +387,7 @@ public function test_optional_list_optional_list_optional_map_string_optional_in $schema->get('l.list.element.list.element.key_value.value')->repetitions()->maxRepetitionLevel(), ); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -586,7 +586,7 @@ public function test_optional_list_optional_list_optional_map_string_optional_st ->maxRepetitionLevel(), ); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -701,7 +701,7 @@ public function test_optional_list_optional_list_optional_struct_optional_int32_ $schema->get('l.list.element.list.element.string')->repetitions()->maxRepetitionLevel(), ); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -925,9 +925,9 @@ public function test_optional_list_optional_map_string_optional_int32( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1097,7 +1097,7 @@ public function test_optional_list_optional_struct_optional_int32_optional_list_ static::assertEquals(6, $schema->get('l.list.element.l.list.element')->repetitions()->maxDefinitionLevel()); static::assertEquals(2, $schema->get('l.list.element.l.list.element')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $readFlatValues = []; @@ -1236,7 +1236,7 @@ public function test_optional_list_optional_struct_optional_int32_optional_map_i static::assertEquals(6, $schema->get('l.list.element.m.key_value.value')->repetitions()->maxDefinitionLevel()); static::assertEquals(2, $schema->get('l.list.element.m.key_value.value')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1443,7 +1443,7 @@ public function test_optional_list_optional_struct_optional_int32_optional_strin static::assertEquals(4, $schema->get('l.list.element.string')->repetitions()->maxDefinitionLevel()); static::assertEquals(1, $schema->get('l.list.element.string')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1532,7 +1532,7 @@ public function test_optional_list_optional_struct_optional_struct_optional_int3 static::assertEquals(5, $schema->get('l.list.element.s.string')->repetitions()->maxDefinitionLevel()); static::assertEquals(1, $schema->get('l.list.element.s.string')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1605,7 +1605,7 @@ public function test_optional_list_required_int32(array $rows, array $expectedCo static::assertEquals(2, $schema->get('l.list.element')->repetitions()->maxDefinitionLevel()); static::assertEquals(1, $schema->get('l.list.element')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1666,7 +1666,7 @@ public function test_required_list_required_int32(array $rows, array $expectedFl static::assertEquals(1, $schema->get('l.list.element')->repetitions()->maxDefinitionLevel()); static::assertEquals(1, $schema->get('l.list.element')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1734,7 +1734,7 @@ public function test_required_list_required_list_required_int32(array $rows, arr static::assertEquals(2, $schema->get('l.list.element.list.element')->repetitions()->maxDefinitionLevel()); static::assertEquals(2, $schema->get('l.list.element.list.element')->repetitions()->maxRepetitionLevel()); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1840,9 +1840,9 @@ public function test_required_list_required_map_string_required_int32( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1978,9 +1978,9 @@ public function test_required_list_required_struct_required_int32_required_strin if ($exceptMessage) { $this->expectExceptionMessage($exceptMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelMapsTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelMapsTest.php index c9864c3415..13c0b7080d 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelMapsTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelMapsTest.php @@ -141,9 +141,9 @@ public function test_optional_map_string_optional_int32( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -350,9 +350,9 @@ public function test_optional_map_string_optional_list_optional_int32( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -612,9 +612,9 @@ public function test_optional_map_string_optional_map_string_optional_int( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -841,9 +841,9 @@ public function test_optional_map_string_optional_struct_optional_int32_optional if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -958,9 +958,9 @@ public function test_optional_map_string_optional_struct_optional_list_optional_ if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1055,9 +1055,9 @@ public function test_optional_map_string_required_int32( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1149,9 +1149,9 @@ public function test_required_map_string_required_int32( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1248,9 +1248,9 @@ public function test_required_map_string_required_list_required_int32( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1377,9 +1377,9 @@ public function test_required_map_string_required_map_string_required_int( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; @@ -1528,9 +1528,9 @@ public function test_required_map_string_required_struct_required_int32_required if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, $rows); + $shredder->shred($schema, $rows, 0); } else { - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); $normalized = []; diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelShredderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelShredderTest.php index 8409356d32..59cef3f907 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelShredderTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelShredderTest.php @@ -55,7 +55,7 @@ public function test_complex_schema(): void ]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame( [ @@ -87,7 +87,7 @@ public function test_flat_optional_column(): void $rows = [['id' => 1], ['id' => null], ['id' => 3]]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['id'], array_keys($result)); static::assertSame([1, 3], $result['id']->values()); @@ -101,7 +101,7 @@ public function test_flat_optional_column_all_nulls(): void $rows = [['id' => null], ['id' => null], ['id' => null]]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['id'], array_keys($result)); static::assertSame([], $result['id']->values()); @@ -115,7 +115,7 @@ public function test_flat_required_column(): void $rows = [['id' => 1], ['id' => 2], ['id' => 3]]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['id'], array_keys($result)); static::assertSame([1, 2, 3], $result['id']->values()); @@ -134,7 +134,7 @@ public function test_list_of_flat_values(): void ]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['tags.list.element'], array_keys($result)); static::assertSame(['a', 'b', 'c', 'd'], $result['tags.list.element']->values()); @@ -156,7 +156,7 @@ public function test_list_of_structs(): void ]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['items.list.element.id', 'items.list.element.name'], array_keys($result)); static::assertSame([1, 2, 3], $result['items.list.element.id']->values()); @@ -174,7 +174,7 @@ public function test_map_of_flat_values(): void ]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['props.key_value.key', 'props.key_value.value'], array_keys($result)); static::assertSame(['a', 'b', 'c'], $result['props.key_value.key']->values()); @@ -198,7 +198,7 @@ public function test_map_with_struct_values(): void ]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame( ['data.key_value.key', 'data.key_value.value.x', 'data.key_value.value.y'], @@ -219,7 +219,7 @@ public function test_multiple_flat_columns(): void ]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['id', 'name', 'active'], array_keys($result)); static::assertSame([1, 3], $result['id']->values()); @@ -238,7 +238,7 @@ public function test_nested_list_of_lists(): void ]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['matrix.list.element.list.element'], array_keys($result)); static::assertSame([1, 2, 3, 4], $result['matrix.list.element.list.element']->values()); @@ -257,7 +257,7 @@ public function test_struct_with_flat_children(): void ]; $shredder = new DremelShredder(new DisabledValidator(), DataConverter::initialize(Options::default())); - $result = $shredder->shred($schema, $rows); + $result = $shredder->shred($schema, $rows, 0); static::assertSame(['s.a', 's.b'], array_keys($result)); static::assertSame([1], $result['s.a']->values()); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelStructuresTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelStructuresTest.php index fe18b45b6e..98aebb8fca 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelStructuresTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/DremelStructuresTest.php @@ -180,9 +180,9 @@ public function test_optional_struct_optional_int_optional_string_optional_bool( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; @@ -314,9 +314,9 @@ public function test_optional_struct_optional_list_optional_int( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; @@ -477,9 +477,9 @@ public function test_optional_struct_optional_map_string_optional_int( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; @@ -624,9 +624,9 @@ public function test_optional_struct_optional_struct_optional_int32_optional_str if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; @@ -756,9 +756,9 @@ public function test_required_struct_required_int_required_string_required_bool( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; @@ -864,9 +864,9 @@ public function test_required_struct_required_list_required_int( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; @@ -987,9 +987,9 @@ public function test_required_struct_required_map_string_required_int( if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; @@ -1114,9 +1114,9 @@ public function test_required_struct_required_struct_required_int32_required_str if ($exceptionMessage) { $this->expectExceptionMessage($exceptionMessage); - $shredder->shred($schema, [$row]); + $shredder->shred($schema, [$row], 0); } else { - $shredResult = $shredder->shred($schema, [$row]); + $shredResult = $shredder->shred($schema, [$row], 0); $normalized = []; diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/Validator/ColumnDataValidatorTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/Validator/ColumnDataValidatorTest.php new file mode 100644 index 0000000000..b6a40192a8 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Dremel/Validator/ColumnDataValidatorTest.php @@ -0,0 +1,206 @@ + + */ + public static function integers_in_range(): Generator + { + yield 'INT_8 min' => [new FlatColumn('c', PhysicalType::INT32, ConvertedType::INT_8), -128]; + yield 'INT_16 max' => [new FlatColumn('c', PhysicalType::INT32, ConvertedType::INT_16), 32_767]; + yield 'INT_32 min' => [FlatColumn::int32('c'), -2_147_483_648]; + yield 'plain INT32 max' => [new FlatColumn('c', PhysicalType::INT32), 2_147_483_647]; + yield 'UINT_8 max' => [new FlatColumn('c', PhysicalType::INT32, ConvertedType::UINT_8), 255]; + yield 'UINT_16 max' => [new FlatColumn('c', PhysicalType::INT32, ConvertedType::UINT_16), 65_535]; + yield 'UINT_32 max' => [new FlatColumn('c', PhysicalType::INT32, ConvertedType::UINT_32), 4_294_967_295]; + yield 'UINT_64 max' => [new FlatColumn('c', PhysicalType::INT64, ConvertedType::UINT_64), PHP_INT_MAX]; + yield 'INT_64 min' => [FlatColumn::int64('c'), PHP_INT_MIN]; + yield 'plain INT64 unchecked' => [new FlatColumn('c', PhysicalType::INT64), PHP_INT_MIN]; + yield 'DECIMAL in INT32 unchecked' => [ + new FlatColumn('c', PhysicalType::INT32, logicalType: LogicalType::decimal(2, 9)), + PHP_INT_MAX, + ]; + } + + #[DataProvider('integers_in_range')] + public function test_an_integer_in_the_column_range_is_accepted(FlatColumn $column, int $value): void + { + (new ColumnDataValidator())->validate($column, $value, 0); + + $this->expectNotToPerformAssertions(); + } + + /** + * @return Generator + */ + public static function integers_out_of_range(): Generator + { + yield 'INT_8 above' => [ + new FlatColumn('c', PhysicalType::INT32, ConvertedType::INT_8), + 128, + '128 is out of the INT_8 range [-128, 127]', + ]; + yield 'INT_16 below' => [ + new FlatColumn('c', PhysicalType::INT32, ConvertedType::INT_16), + -32_769, + '-32769 is out of the INT_16 range [-32768, 32767]', + ]; + yield 'INT_32 above' => [ + FlatColumn::int32('c'), + 4_000_000_000, + '4000000000 is out of the INT_32 range [-2147483648, 2147483647]', + ]; + yield 'plain INT32 below' => [ + new FlatColumn('c', PhysicalType::INT32), + -2_147_483_649, + '-2147483649 is out of the INT32 range [-2147483648, 2147483647]', + ]; + yield 'UINT_8 above' => [ + new FlatColumn('c', PhysicalType::INT32, ConvertedType::UINT_8), + 256, + '256 is out of the UINT_8 range [0, 255]', + ]; + yield 'UINT_16 negative' => [ + new FlatColumn('c', PhysicalType::INT32, ConvertedType::UINT_16), + -1, + '-1 is out of the UINT_16 range [0, 65535]', + ]; + yield 'UINT_32 above' => [ + new FlatColumn('c', PhysicalType::INT32, ConvertedType::UINT_32), + 4_294_967_296, + '4294967296 is out of the UINT_32 range [0, 4294967295]', + ]; + yield 'UINT_64 negative' => [ + new FlatColumn('c', PhysicalType::INT64, ConvertedType::UINT_64), + -1, + '-1 is out of the UINT_64 range [0, 9223372036854775807]', + ]; + yield 'logical INTEGER(8, signed) above' => [ + new FlatColumn('c', PhysicalType::INT32, logicalType: LogicalType::integer(8, true)), + 200, + '200 is out of the INT_8 range [-128, 127]', + ]; + } + + #[DataProvider('integers_out_of_range')] + public function test_an_integer_out_of_the_column_range_is_refused_naming_its_row( + FlatColumn $column, + int $value, + string $message, + ): void { + $this->expectException(ValidationException::class); + $this->expectExceptionMessage('Column "c" row 3: ' . $message); + + (new ColumnDataValidator())->validate($column, $value, 3); + } + + /** + * @return Generator + */ + public static function uuids(): Generator + { + yield 'dashed string' => ['0190a6b0-6b1f-7c5e-9a3b-0123456789ab']; + yield 'dash-less string' => ['0190A6B06B1F7C5E9A3B0123456789AB']; + yield 'toString() object' => [new ToStringUuid('0190a6b0-6b1f-7c5e-9a3b-0123456789ab')]; + yield 'Stringable object' => [new StringableUuid('0190a6b0-6b1f-7c5e-9a3b-0123456789ab')]; + } + + #[DataProvider('uuids')] + public function test_a_uuid_of_32_hex_digits_is_accepted(mixed $value): void + { + (new ColumnDataValidator())->validate(FlatColumn::uuid('c'), $value, 0); + + $this->expectNotToPerformAssertions(); + } + + /** + * @return Generator + */ + public static function not_uuids(): Generator + { + yield '16 raw bytes' => ["\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01", 'string']; + yield 'too short' => ['0190a6b0-6b1f-7c5e-9a3b', 'string']; + yield 'not hexadecimal' => ['0190a6b0-6b1f-7c5e-9a3b-0123456789az', 'string']; + yield 'an int' => [1, 'int']; + yield 'an object without text' => [new DateTimeImmutable('2024-01-01'), 'DateTimeImmutable']; + } + + #[DataProvider('not_uuids')] + public function test_a_uuid_that_is_not_32_hex_digits_is_refused(mixed $value, string $type): void + { + $this->expectException(ValidationException::class); + $this->expectExceptionMessage('Column "c" row 1: ' . $type . ' is not a UUID of 32 hexadecimal digits'); + + (new ColumnDataValidator())->validate(FlatColumn::uuid('c'), $value, 1); + } + + public function test_a_fixed_length_value_of_its_length_is_accepted(): void + { + (new ColumnDataValidator())->validate(FlatColumn::fixedSizeByteArray('c', 4), "\x00\x01\x02\x03", 0); + + $this->expectNotToPerformAssertions(); + } + + public function test_a_fixed_length_value_of_another_length_is_refused(): void + { + $this->expectException(ValidationException::class); + $this->expectExceptionMessage('Column "c" row 2: a FIXED_LEN_BYTE_ARRAY(4) value is 5 bytes long'); + + (new ColumnDataValidator())->validate(FlatColumn::fixedSizeByteArray('c', 4), '12345', 2); + } + + /** + * @return Generator + */ + public static function utf8_columns(): Generator + { + yield 'STRING' => [FlatColumn::string('c')]; + yield 'JSON' => [FlatColumn::json('c')]; + yield 'ENUM' => [FlatColumn::enum('c')]; + } + + #[DataProvider('utf8_columns')] + public function test_invalid_utf8_is_refused(FlatColumn $column): void + { + $this->expectException(ValidationException::class); + $this->expectExceptionMessage('Column "c" row 0: the string is not valid UTF-8'); + + (new ColumnDataValidator())->validate($column, "\xFF\xFE", 0); + } + + #[DataProvider('utf8_columns')] + public function test_valid_utf8_is_accepted(FlatColumn $column): void + { + (new ColumnDataValidator())->validate($column, 'zażółć', 0); + + $this->expectNotToPerformAssertions(); + } + + public function test_invalid_utf8_into_a_plain_byte_array_is_accepted(): void + { + (new ColumnDataValidator())->validate(new FlatColumn('c', PhysicalType::BYTE_ARRAY), "\xFF\xFE", 0); + + $this->expectNotToPerformAssertions(); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php index 04becd6bca..aa0197fbd4 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php @@ -14,10 +14,10 @@ final class AdaptiveParquetEngineTest extends TestCase { - public function test_creates_arrow_engine_when_arrow_extension_loaded(): void + public function test_creates_arrow_engine_when_flow_php_or_arrow_is_loaded(): void { - if (!extension_loaded('arrow')) { - static::markTestSkipped('This test requires the arrow extension to be loaded'); + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + static::markTestSkipped('This test requires flow_php or arrow to be loaded'); } $engine = new AdaptiveParquetEngine(); @@ -30,10 +30,10 @@ public function test_creates_arrow_engine_when_arrow_extension_loaded(): void ); } - public function test_creates_php_engine_when_arrow_extension_not_loaded(): void + public function test_creates_php_engine_without_flow_php_and_arrow(): void { - if (extension_loaded('arrow')) { - static::markTestSkipped('This test requires the arrow extension to NOT be loaded'); + if (extension_loaded('flow_php') || extension_loaded('arrow')) { + static::markTestSkipped('This test requires neither flow_php nor arrow to be loaded'); } $engine = new AdaptiveParquetEngine(); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php index 8587c23d7e..f9be0888ff 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php @@ -4,28 +4,90 @@ namespace Flow\Parquet\Tests\Unit\Engine; +use Flow\Filesystem\Stream\MemorySourceStream; +use Flow\Filesystem\Stream\StringDestinationStream; use Flow\Parquet\Engine\ArrowParquetEngine; +use Flow\Parquet\Engine\ArrowParquetFileReader; +use Flow\Parquet\Engine\NativeParquetFileReader; +use Flow\Parquet\Engine\NativeParquetFileWriter; use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\ParquetFile\Compressions; +use Flow\Parquet\Tests\Context\MemoryParquetFile; +use Flow\Parquet\Tests\Mother\ParquetFileWriterMother; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use function extension_loaded; +use function Flow\Filesystem\DSL\path; +use function restore_error_handler; +use function set_error_handler; + +use const E_USER_DEPRECATED; final class ArrowParquetEngineTest extends TestCase { - public function test_constructor_throws_when_extension_not_loaded(): void + public function test_constructor_throws_without_flow_php_and_arrow(): void { - if (extension_loaded('arrow')) { - static::markTestSkipped('This test requires the arrow extension to NOT be loaded'); + if (extension_loaded('flow_php') || extension_loaded('arrow')) { + static::markTestSkipped('This test requires neither flow_php nor arrow to be loaded'); } $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('arrow extension is required'); + $this->expectExceptionMessage('ArrowParquetEngine requires the flow_php extension (flow-php/flow-php-ext).'); new ArrowParquetEngine(); } + #[RequiresPhpExtension('flow_php')] + public function test_with_flow_php_files_are_read_and_written_through_it(): void + { + $engine = new ArrowParquetEngine(); + + static::assertInstanceOf( + NativeParquetFileReader::class, + $engine->openForRead(new MemorySourceStream(MemoryParquetFile::threeRowGroups())), + ); + static::assertInstanceOf(NativeParquetFileWriter::class, ParquetFileWriterMother::open( + $engine, + new StringDestinationStream(path('memory://out.parquet')), + )); + } + + #[RequiresPhpExtension('arrow')] + public function test_with_arrow_only_files_are_read_through_arrow_with_a_deprecation(): void + { + if (extension_loaded('flow_php')) { + static::markTestSkipped('This test requires flow_php NOT to be loaded'); + } + + $deprecations = []; + set_error_handler(static function (int $level, string $message) use (&$deprecations): bool { + $deprecations[] = [$level, $message]; + + return true; + }); + + try { + $engine = new ArrowParquetEngine(); + } finally { + restore_error_handler(); + } + + static::assertSame( + [[ + E_USER_DEPRECATED, + 'Parquet through the arrow extension is deprecated and will be removed; install the flow_php ' + . 'extension (flow-php/flow-php-ext), which ArrowParquetEngine uses when it is loaded.', + ]], + $deprecations, + ); + static::assertInstanceOf( + ArrowParquetFileReader::class, + $engine->openForRead(new MemorySourceStream(MemoryParquetFile::threeRowGroups())), + ); + } + #[TestWith([Compressions::UNCOMPRESSED, 'UNCOMPRESSED'])] #[TestWith([Compressions::SNAPPY, 'SNAPPY'])] #[TestWith([Compressions::GZIP, 'GZIP'])] diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php index 75621106cb..27280fed10 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php @@ -24,8 +24,8 @@ final class ArrowParquetFileWriterTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('arrow')) { - static::markTestSkipped('arrow extension is not loaded'); + if (!extension_loaded('arrow') || extension_loaded('flow_php')) { + static::markTestSkipped('ArrowParquetEngine writes through arrow-ext only without flow_php'); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/NativeParquetFileWriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/NativeParquetFileWriterTest.php new file mode 100644 index 0000000000..29ba0d6102 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/NativeParquetFileWriterTest.php @@ -0,0 +1,176 @@ +writeTo(path('memory://file.parquet'))), + ); + + try { + $file->close(); + static::fail('close() was expected to throw'); + } catch (FilesystemRuntimeException $failure) { + static::assertSame('Closing "memory://file.parquet" failed', $failure->getMessage()); + } + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Writer is not open'); + + $file->close(); + } + + public function test_closing_twice_throws(): void + { + $file = ParquetFileWriterMother::open( + new ArrowParquetEngine(), + memory_filesystem()->writeTo(path('memory://file.parquet')), + ); + $file->close(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Writer is not open'); + + $file->close(); + } + + public function test_closing_writes_a_file_the_reader_reads_back(): void + { + $memory = memory_filesystem(); + $file = ParquetFileWriterMother::open( + new ArrowParquetEngine(), + $memory->writeTo(path('memory://file.parquet')), + ); + + $file->writeRow(['id' => 1]); + $file->writeBatch([['id' => 2]]); + $file->close(); + + static::assertSame( + [['id' => 1], ['id' => 2]], + iterator_to_array( + (new Reader(engine: new PhpParquetEngine())) + ->readStream($memory->readFrom(path('memory://file.parquet'))) + ->values(), + false, + ), + ); + } + + public function test_writing_a_batch_after_close_throws(): void + { + $file = ParquetFileWriterMother::open( + new ArrowParquetEngine(), + memory_filesystem()->writeTo(path('memory://file.parquet')), + ); + $file->close(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Writer is not open'); + + $file->writeBatch([['id' => 1]]); + } + + public function test_writing_a_row_after_close_throws(): void + { + $file = ParquetFileWriterMother::open( + new ArrowParquetEngine(), + memory_filesystem()->writeTo(path('memory://file.parquet')), + ); + $file->close(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Writer is not open'); + + $file->writeRow(['id' => 1]); + } + + public function test_rows_beyond_the_batch_size_are_written_once(): void + { + $memory = memory_filesystem(); + $file = ParquetFileWriterMother::open( + new ArrowParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 2)), + $memory->writeTo(path('memory://file.parquet')), + ); + + $file->writeRow(['id' => 1]); + $file->writeRow(['id' => 2]); + $file->writeRow(['id' => 3]); + $file->close(); + + static::assertSame( + [['id' => 1], ['id' => 2], ['id' => 3]], + iterator_to_array( + (new Reader(engine: new PhpParquetEngine())) + ->readStream($memory->readFrom(path('memory://file.parquet'))) + ->values(), + false, + ), + ); + } + + public function test_it_is_the_writer_arrow_opens_with_flow_php(): void + { + static::assertInstanceOf(NativeParquetFileWriter::class, ParquetFileWriterMother::open( + new ArrowParquetEngine(), + memory_filesystem()->writeTo(path('memory://file.parquet')), + )); + } + + public function test_a_refused_row_leaves_the_rows_before_it_written(): void + { + $memory = memory_filesystem(); + $file = ParquetFileWriterMother::open( + new ArrowParquetEngine(), + $memory->writeTo(path('memory://file.parquet')), + ); + + $file->writeRow(['id' => 1]); + + try { + $file->writeRow(['id' => 'two']); + static::fail('a string was written into INT32'); + } catch (ValidationException $refusal) { + static::assertSame('Column "id" row 1: expected int, got string', $refusal->getMessage()); + } + + $file->writeBatch(new ArrayIterator([['id' => 3]])); + $file->close(); + + static::assertSame( + [['id' => 1], ['id' => 3]], + iterator_to_array( + (new Reader(engine: new PhpParquetEngine())) + ->readStream($memory->readFrom(path('memory://file.parquet'))) + ->values(), + false, + ), + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/PhpParquetFileReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/PhpParquetFileReaderTest.php new file mode 100644 index 0000000000..7276cc8266 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/PhpParquetFileReaderTest.php @@ -0,0 +1,113 @@ +metadata(); + $reads = $stream->reads; + + static::assertSame($metadata, $reader->metadata()); + static::assertSame($metadata->schema(), $reader->schema()); + static::assertSame(6, $reader->rowsNumber()); + static::assertSame($reads, $stream->reads); + } + + public function test_total_byte_size_sums_the_row_groups(): void + { + $reader = new PhpParquetFileReader( + new MemorySourceStream(MemoryParquetFile::threeRowGroups()), + ByteOrder::LITTLE_ENDIAN, + new Options(), + ); + $expected = 0; + + foreach ($reader->metadata()->rowGroups()->all() as $rowGroup) { + $expected += $rowGroup->totalByteSize(); + } + + static::assertCount(3, $reader->metadata()->rowGroups()->all()); + static::assertGreaterThan(0, $expected); + static::assertSame($expected, $reader->totalByteSize()); + } + + /** + * @param int<1, max> $batchSize + * @param list> $ids + */ + #[TestWith([4, null, null, [[1, 2, 3, 4], [5, 6]]])] + #[TestWith([2, 3, 2, [[3, 4], [5]]])] + #[TestWith([2, null, 6, []])] + #[TestWith([2, null, 7, []])] + public function test_read_columns_chunks_the_rows(int $batchSize, ?int $limit, ?int $offset, array $ids): void + { + $reader = new PhpParquetFileReader( + new MemorySourceStream(MemoryParquetFile::threeRowGroups()), + ByteOrder::LITTLE_ENDIAN, + new Options(), + ); + $chunks = iterator_to_array($reader->readColumns(['id'], $batchSize, $limit, $offset), false); + + static::assertSame($ids, array_column($chunks, 'id')); + } + + public function test_close_closes_the_stream_and_every_later_call_throws(): void + { + $stream = new ReadCountingSourceStream(new MemorySourceStream(MemoryParquetFile::threeRowGroups())); + $reader = new PhpParquetFileReader($stream, ByteOrder::LITTLE_ENDIAN, new Options()); + $reader->metadata(); + + $reader->close(); + + static::assertTrue($stream->closed); + + foreach ([ + static fn() => $reader->metadata(), + static fn() => $reader->schema(), + static fn() => $reader->rowsNumber(), + static fn() => $reader->totalByteSize(), + static fn() => iterator_to_array($reader->readColumns(['id'], 1, null, null)), + static fn() => $reader->close(), + ] as $call) { + try { + $call(); + static::fail('A call on a closed reader must throw'); + } catch (RuntimeException $exception) { + static::assertSame('Reader is not open', $exception->getMessage()); + } + } + } + + public function test_a_file_without_the_parquet_magic_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Given file is not valid Parquet file'); + + (new PhpParquetFileReader( + new MemorySourceStream('not a parquet file'), + ByteOrder::LITTLE_ENDIAN, + new Options(), + ))->metadata(); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Data/Converter/Int96DateTimeConverterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Data/Converter/Int96DateTimeConverterTest.php new file mode 100644 index 0000000000..4c53b44f29 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Data/Converter/Int96DateTimeConverterTest.php @@ -0,0 +1,50 @@ + + */ + public static function int96_values(): Generator + { + yield 'nanoseconds floored' => [ + pack('PV', 45_296_789_012_345, 19_782 + 2_440_588), + '2024-02-29 12:34:56.789012', + ]; + yield 'epoch' => [pack('PV', 0, 2_440_588), '1970-01-01 00:00:00.000000']; + yield 'before the epoch, never rounded up' => [ + pack('PV', 86_399_999_999_999, -3_653 + 2_440_588), + '1960-01-01 23:59:59.999999', + ]; + yield 'first microsecond of year 1' => [pack('PV', 1_000, -719_162 + 2_440_588), '0001-01-01 00:00:00.000001']; + yield 'sub-microsecond of year 9999' => [pack('PV', 999, 2_932_896 + 2_440_588), '9999-12-31 00:00:00.000000']; + yield 'remainder of 999 nanoseconds' => [ + pack('PV', 123_456_789_999, 19_000 + 2_440_588), + '2022-01-08 00:02:03.456789', + ]; + } + + #[DataProvider('int96_values')] + public function test_int96_reads_as_the_microsecond_it_falls_in(string $bytes, string $datetime): void + { + static::assertSame( + $datetime, + (new Int96DateTimeConverter()) + ->fromParquetType($bytes) + ->format('Y-m-d H:i:s.u'), + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Data/Converter/UnsignedIntegerConverterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Data/Converter/UnsignedIntegerConverterTest.php new file mode 100644 index 0000000000..2907c4e028 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Data/Converter/UnsignedIntegerConverterTest.php @@ -0,0 +1,91 @@ +fromParquetType($stored)); + } + + public function test_uint64_up_to_php_int_max_reads_as_is(): void + { + static::assertSame(PHP_INT_MAX, (new UnsignedIntegerConverter('u64', 64))->fromParquetType(PHP_INT_MAX)); + } + + public function test_uint64_above_php_int_max_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Parquet column "u64" holds a UINT_64 value above PHP_INT_MAX'); + + (new UnsignedIntegerConverter('u64', 64))->fromParquetType(-1); + } + + public function test_a_value_that_is_not_an_int_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Expected int, got string'); + + (new UnsignedIntegerConverter('u32', 32))->fromParquetType('1'); + } + + public function test_writes_are_the_value_itself(): void + { + static::assertSame(4_000_000_000, (new UnsignedIntegerConverter('u32', 32))->toParquetType(4_000_000_000)); + } + + #[TestWith([ConvertedType::UINT_32, 32])] + #[TestWith([ConvertedType::UINT_64, 64])] + public function test_for_column_reads_the_converted_type(ConvertedType $convertedType, int $bitWidth): void + { + static::assertEquals( + new UnsignedIntegerConverter('u', $bitWidth), + UnsignedIntegerConverter::forColumn( + new FlatColumn('u', PhysicalType::INT64, $convertedType), + Options::default(), + ), + ); + } + + public function test_for_column_reads_a_logical_unsigned_integer(): void + { + static::assertEquals( + new UnsignedIntegerConverter('u', 32), + UnsignedIntegerConverter::forColumn( + new FlatColumn('u', PhysicalType::INT32, logicalType: LogicalType::integer(32, false)), + Options::default(), + ), + ); + } + + #[TestWith([ConvertedType::UINT_8])] + #[TestWith([ConvertedType::UINT_16])] + #[TestWith([ConvertedType::INT_32])] + #[TestWith([ConvertedType::INT_64])] + public function test_for_column_skips_what_a_signed_int_holds(ConvertedType $convertedType): void + { + static::assertNull(UnsignedIntegerConverter::forColumn( + new FlatColumn('u', PhysicalType::INT32, $convertedType), + Options::default(), + )); + static::assertNull(UnsignedIntegerConverter::forColumn(FlatColumn::int64('i'), Options::default())); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/FlatColumnTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/FlatColumnTest.php index c2b3a10840..fdd6851eb0 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/FlatColumnTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/FlatColumnTest.php @@ -8,6 +8,7 @@ use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\ConvertedType; use Flow\Parquet\ParquetFile\Schema\FlatColumn; +use Flow\Parquet\ParquetFile\Schema\LogicalType; use Flow\Parquet\ParquetFile\Schema\PhysicalType; use Flow\Parquet\ParquetFile\Schema\Repetition; use Flow\Parquet\ParquetFile\Schema\TimeUnit; @@ -108,4 +109,13 @@ public function test_repetitions(): void Schema::with(FlatColumn::int32('int32'))->get('int32')->repetitions()->toArray(), ); } + + public function test_enum_is_annotated_enum(): void + { + $column = FlatColumn::enum('color'); + + static::assertSame(ConvertedType::ENUM, $column->convertedType()); + static::assertSame(LogicalType::ENUM, $column->logicalType()?->name()); + static::assertNotNull($column->toThrift()->logicalType->ENUM); + } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/LogicalType/IntegerTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/LogicalType/IntegerTest.php new file mode 100644 index 0000000000..65350faebe --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/LogicalType/IntegerTest.php @@ -0,0 +1,78 @@ +toThrift(); + + static::assertEquals(new IntType(['bitWidth' => $bitWidth, 'isSigned' => $isSigned]), $thrift); + static::assertEquals(new Integer($bitWidth, $isSigned), Integer::fromThrift($thrift)); + static::assertSame($bitWidth, Integer::fromThrift($thrift)->bitWidth()); + static::assertSame($isSigned, Integer::fromThrift($thrift)->isSigned()); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/LogicalTypeTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/LogicalTypeTest.php index 592dc59318..bd043c1c1f 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/LogicalTypeTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFile/Schema/LogicalTypeTest.php @@ -6,7 +6,9 @@ use Flow\Parquet\ParquetFile\Schema\ConvertedType; use Flow\Parquet\ParquetFile\Schema\LogicalType; +use Flow\Parquet\ParquetFile\Schema\LogicalType\Integer; use Flow\Parquet\ParquetFile\Schema\TimeUnit; +use Flow\Parquet\ThriftModel\IntType; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\TestWith; @@ -96,4 +98,16 @@ public function test_timestamp_is_an_utc_instant(): void static::assertTrue(LogicalType::timestamp()->timestampData()?->isAdjustedToUTC()); static::assertSame(TimeUnit::MICROSECONDS, LogicalType::timestamp()->timestampData()?->unit()); } + + #[TestWith([8, true])] + #[TestWith([64, true])] + #[TestWith([32, false])] + #[TestWith([64, false])] + public function test_integer_keeps_its_width_and_sign_through_thrift(int $bitWidth, bool $isSigned): void + { + $thrift = LogicalType::integer($bitWidth, $isSigned)->toThrift(); + + static::assertEquals(new IntType(['bitWidth' => $bitWidth, 'isSigned' => $isSigned]), $thrift->INTEGER); + static::assertEquals(new Integer($bitWidth, $isSigned), LogicalType::fromThrift($thrift)?->integerData()); + } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFileTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFileTest.php new file mode 100644 index 0000000000..0df103c808 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ParquetFileTest.php @@ -0,0 +1,91 @@ +close(); + $file->close(); + unset($file); + + static::assertSame(1, $reader->closes); + } + + public function test_dropping_the_file_closes_the_reader(): void + { + $reader = new SpyParquetFileReader(Schema::with(FlatColumn::int64('id'))); + $file = new ParquetFile(new MemorySourceStream('PAR1'), new Options(), $reader); + + unset($file); + + static::assertSame(1, $reader->closes); + } + + public function test_metadata_schema_and_reader_come_from_the_reader(): void + { + $schema = Schema::with(FlatColumn::int64('id')); + $reader = new SpyParquetFileReader($schema); + $file = new ParquetFile(new MemorySourceStream('PAR1'), new Options(), $reader); + + static::assertSame($reader, $file->reader()); + static::assertSame($schema, $file->schema()); + static::assertSame($schema, $file->metadata()->schema()); + } + + public function test_columns_reads_the_asked_columns_through_the_reader(): void + { + $reader = new SpyParquetFileReader(Schema::with(FlatColumn::int64('id'), FlatColumn::string('name')), [[ + 'name' => ['a'], + 'id' => [1], + ]]); + $file = new ParquetFile(new MemorySourceStream('PAR1'), new Options(), $reader); + + static::assertSame( + [['name' => ['a'], 'id' => [1]]], + iterator_to_array($file->columns(10, [3 => 'name', 7 => 'id'], 5, 2), false), + ); + static::assertSame([[['name', 'id'], 10, 5, 2]], $reader->reads); + } + + public function test_columns_without_names_reads_every_root_column(): void + { + $reader = new SpyParquetFileReader(Schema::with(FlatColumn::int64('id'), FlatColumn::string('name'))); + $file = new ParquetFile(new MemorySourceStream('PAR1'), new Options(), $reader); + + iterator_to_array($file->columns(10)); + + static::assertSame([[['id', 'name'], 10, null, null]], $reader->reads); + } + + public function test_columns_refuses_a_column_the_schema_lacks(): void + { + $file = new ParquetFile( + new MemorySourceStream('PAR1'), + new Options(), + new SpyParquetFileReader(Schema::with(FlatColumn::int64('id'))), + ); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column "missing" does not exist'); + + iterator_to_array($file->columns(10, ['missing'])); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Reader/ColumnReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Reader/ColumnReaderTest.php new file mode 100644 index 0000000000..6af172fd28 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Reader/ColumnReaderTest.php @@ -0,0 +1,68 @@ + $ids + */ + #[TestWith([null, null, [1, 2, 3, 4, 5, 6]])] + #[TestWith([null, 3, [4, 5, 6]])] + #[TestWith([2, 1, [2, 3]])] + #[TestWith([3, 2, [3, 4, 5]])] + #[TestWith([1, 5, [6]])] + #[TestWith([null, 6, []])] + public function test_a_flat_column_reads_across_row_groups(?int $limit, ?int $offset, array $ids): void + { + $stream = new MemorySourceStream(MemoryParquetFile::threeRowGroups()); + $metadata = (new PhpParquetFileReader($stream, ByteOrder::LITTLE_ENDIAN, new Options()))->metadata(); + + $reader = new ColumnReader( + new ColumnChunkReader(new PageReader(ByteOrder::LITTLE_ENDIAN, new Options()), new Options()), + new DremelAssembler(DataConverter::initialize(new Options())), + ); + + static::assertSame( + array_map(static fn(int $id): array => ['id' => $id], $ids), + iterator_to_array( + $reader->read($metadata->schema()->get('id'), $metadata, $stream, $limit, $offset), + false, + ), + ); + } + + public function test_a_nested_column_reads_across_row_groups(): void + { + $stream = new MemorySourceStream(MemoryParquetFile::threeRowGroups()); + $metadata = (new PhpParquetFileReader($stream, ByteOrder::LITTLE_ENDIAN, new Options()))->metadata(); + + $reader = new ColumnReader( + new ColumnChunkReader(new PageReader(ByteOrder::LITTLE_ENDIAN, new Options()), new Options()), + new DremelAssembler(DataConverter::initialize(new Options())), + ); + + static::assertSame( + array_map(static fn(int $id): array => ['tags' => ['t' . $id]], [2, 3, 4]), + iterator_to_array($reader->read($metadata->schema()->get('tags'), $metadata, $stream, 3, 1), false), + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php index 42d6fbaccc..326cd692e0 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php @@ -19,7 +19,7 @@ final class ReaderTest extends TestCase { public function test_arrow_factory_creates_reader_with_arrow_engine(): void { - if (!extension_loaded('arrow')) { + if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { $this->expectException(RuntimeException::class); Reader::arrow(); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Writer/PageBuilder/DictionaryBuilderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Writer/PageBuilder/DictionaryBuilderTest.php index bc53eb570a..58b5f4aff0 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Writer/PageBuilder/DictionaryBuilderTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Writer/PageBuilder/DictionaryBuilderTest.php @@ -320,7 +320,7 @@ public function test_single_unique_value_creates_single_entry_dictionary(): void public function test_unsupported_byte_array_logical_type_throws_exception(): void { - $column = new FlatColumn('test_column', PhysicalType::BYTE_ARRAY, logicalType: LogicalType::integer()); + $column = new FlatColumn('test_column', PhysicalType::BYTE_ARRAY, logicalType: LogicalType::integer(32, true)); $data = new WriteFlatColumnValues($column, values: [1, 2, 3]); $this->expectException(RuntimeException::class); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php index 4ae9418a4a..cde93ceef3 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php @@ -16,8 +16,8 @@ final class WriterTest extends TestCase { public function test_arrow_factory_throws_when_extension_not_loaded(): void { - if (extension_loaded('arrow')) { - static::markTestSkipped('This test requires the arrow extension to NOT be loaded'); + if (extension_loaded('flow_php') || extension_loaded('arrow')) { + static::markTestSkipped('This test requires neither flow_php nor arrow to be loaded'); } $this->expectException(RuntimeException::class); From 7942514a73766678add81852966729b29c9dca47 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Wed, 30 Sep 2026 18:02:03 +0200 Subject: [PATCH 09/21] feat(flow-php/etl): every loader writes from columns - TextValues: one per-type text rule for CSV, JSON, XML and Text - CSV / JSON: one sink per adapter, encoder contracts with PHP and native implementations - flow_php: native CSV and JSON writers - Parquet: writeColumns() on the PHP, native and arrow writers - XML: column-wise encoding, XMLValueNodes - FloatType casts NAN, INF and -INF --- documentation/components/adapters/csv.md | 46 +- documentation/components/adapters/json.md | 45 ++ documentation/components/adapters/parquet.md | 3 + documentation/components/adapters/text.md | 34 ++ documentation/components/adapters/xml.md | 87 ++- .../components/extensions/flow-php-ext.md | 32 +- documentation/components/libs/parquet.md | 18 + documentation/upgrading.md | 115 ++++ .../src/Flow/ETL/Adapter/CSV/CSVEncoder.php | 183 +----- .../src/Flow/ETL/Adapter/CSV/CSVLoader.php | 50 +- .../src/Flow/ETL/Adapter/CSV/CSVOpenSink.php | 34 ++ .../Flow/ETL/Adapter/CSV/CSVSinkOpener.php | 39 ++ .../Flow/ETL/Adapter/CSV/CSVWriteOptions.php | 34 ++ .../Flow/ETL/Adapter/CSV/NativeCSVEncoder.php | 47 ++ .../Flow/ETL/Adapter/CSV/PhpCSVEncoder.php | 165 +++++ .../Adapter/CSV/Tests/Integration/CSVTest.php | 86 +++ .../CSV/Tests/Mother/CSVEncoderMother.php | 39 ++ .../Adapter/CSV/Tests/Unit/CSVEncoderTest.php | 112 ---- .../Adapter/CSV/Tests/Unit/CSVLoaderTest.php | 116 +++- .../CSV/Tests/Unit/CSVOpenSinkTest.php | 47 ++ .../CSV/Tests/Unit/CSVSinkOpenerTest.php | 41 ++ .../CSV/Tests/Unit/CSVWriteOptionsTest.php | 50 ++ .../CSV/Tests/Unit/NativeCSVEncoderTest.php | 123 ++++ .../CSV/Tests/Unit/PhpCSVEncoderTest.php | 283 +++++++++ src/adapter/etl-adapter-json/composer.json | 3 + .../src/Flow/ETL/Adapter/JSON/JSONEncoder.php | 172 +----- .../Flow/ETL/Adapter/JSON/JsonDocuments.php | 59 -- .../src/Flow/ETL/Adapter/JSON/JsonFraming.php | 48 ++ .../Flow/ETL/Adapter/JSON/JsonLinesLoader.php | 54 +- .../src/Flow/ETL/Adapter/JSON/JsonLoader.php | 82 +-- .../Flow/ETL/Adapter/JSON/JsonOpenSink.php | 45 ++ .../Flow/ETL/Adapter/JSON/JsonSinkOpener.php | 45 ++ .../ETL/Adapter/JSON/NativeJSONEncoder.php | 42 ++ .../Flow/ETL/Adapter/JSON/PhpJSONEncoder.php | 114 ++++ .../JSON/Tests/Mother/JSONEncoderMother.php | 34 ++ .../JSON/Tests/Unit/JSONEncoderTest.php | 199 ------- .../JSON/Tests/Unit/JsonFramingTest.php | 30 + .../JSON/Tests/Unit/JsonLinesLoaderTest.php | 96 ++- .../JSON/Tests/Unit/JsonLoaderTest.php | 107 +++- .../JSON/Tests/Unit/JsonOpenSinkTest.php | 79 +++ .../JSON/Tests/Unit/JsonSinkOpenerTest.php | 55 ++ .../JSON/Tests/Unit/NativeJSONEncoderTest.php | 123 ++++ .../JSON/Tests/Unit/PhpJSONEncoderTest.php | 343 +++++++++++ .../Adapter/Parquet/EngineParquetOpenSink.php | 2 +- .../ETL/Adapter/Parquet/ParquetEncoder.php | 30 +- .../Parquet/Tests/Unit/ParquetEncoderTest.php | 62 +- .../src/Flow/ETL/Adapter/Text/TextEncoder.php | 65 +- .../src/Flow/ETL/Adapter/Text/TextLoader.php | 3 +- .../Text/Tests/Integration/TextLoaderTest.php | 32 +- .../Text/Tests/Unit/TextEncoderTest.php | 65 +- .../Flow/ETL/Adapter/XML/Loader/XMLLoader.php | 8 +- .../src/Flow/ETL/Adapter/XML/XMLEncoder.php | 257 +++----- .../Flow/ETL/Adapter/XML/XMLValueNodes.php | 140 +++++ .../src/Flow/ETL/Adapter/XML/XMLWriter.php | 14 + .../XML/XMLWriter/DOMDocumentWriter.php | 19 + .../Adapter/XML/XMLWriter/StringXMLWriter.php | 58 ++ .../XML/Tests/Context/XMLWriterValues.php | 31 + .../Adapter/XML/Tests/Unit/XMLEncoderTest.php | 295 ++++----- .../Adapter/XML/Tests/Unit/XMLLoaderTest.php | 60 +- .../XML/Tests/Unit/XMLValueNodesTest.php | 168 ++++++ .../Unit/XMLWriter/DOMDocumentWriterTest.php | 66 ++ .../Unit/XMLWriter/StringXMLWriterTest.php | 62 ++ .../src/Flow/ETL/Column/DateFormatPattern.php | 72 +++ src/core/etl/src/Flow/ETL/Column/Elements.php | 98 +++ .../Flow/ETL/Column/RoundTripPrecision.php | 40 ++ .../etl/src/Flow/ETL/Column/TextValues.php | 418 +++++++++++++ src/core/etl/src/Flow/ETL/Function/Cast.php | 30 + .../src/Flow/ETL/Function/DateTimeFormat.php | 28 + .../etl/src/Flow/ETL/Loader/ArrayLoader.php | 6 +- .../etl/src/Flow/ETL/Memory/ArrayMemory.php | 4 +- .../ETL/Tests/Context/TextWriterBatches.php | 264 ++++++++ .../Unit/Column/DateFormatPatternTest.php | 48 ++ .../ETL/Tests/Unit/Column/ElementsTest.php | 45 ++ .../Unit/Column/RoundTripPrecisionTest.php | 71 +++ .../ETL/Tests/Unit/Column/TextValuesTest.php | 562 ++++++++++++++++++ .../Flow/ETL/Tests/Unit/Function/CastTest.php | 51 ++ .../Unit/Function/DateTimeFormatTest.php | 56 ++ .../ETL/Tests/Unit/Loader/ArrayLoaderTest.php | 16 +- .../ETL/Tests/Unit/Memory/ArrayMemoryTest.php | 5 +- src/extension/flow-php-ext/composer.json | 3 +- .../Flow/ETL/Adapter/CSV/NativeCSVWriter.php | 45 ++ .../ETL/Adapter/JSON/NativeJsonWriter.php | 43 ++ .../Engine/Native/NativeParquetRowsWriter.php | 9 + src/extension/flow-php-ext/src/cast.rs | 18 + src/extension/flow-php-ext/src/column.rs | 4 + src/extension/flow-php-ext/src/csv/mod.rs | 1 + src/extension/flow-php-ext/src/csv/write.rs | 181 ++++++ src/extension/flow-php-ext/src/json/mod.rs | 1 + src/extension/flow-php-ext/src/json/write.rs | 114 ++++ src/extension/flow-php-ext/src/lib.rs | 4 + .../flow-php-ext/src/parquet/library.rs | 104 ++++ src/extension/flow-php-ext/src/render.rs | 4 + src/extension/flow-php-ext/src/text/batch.rs | 135 +++++ src/extension/flow-php-ext/src/text/date.rs | 366 ++++++++++++ src/extension/flow-php-ext/src/text/float.rs | 47 ++ src/extension/flow-php-ext/src/text/json.rs | 134 +++++ src/extension/flow-php-ext/src/text/mod.rs | 54 ++ src/extension/flow-php-ext/src/text/value.rs | 490 +++++++++++++++ src/extension/flow-php-ext/src/values.rs | 19 +- .../tests/phpt/059_native_cast_parity.phpt | 8 +- .../tests/phpt/077_text_float_parity.phpt | 74 +++ .../phpt/078_text_json_string_parity.phpt | 103 ++++ .../phpt/079_text_date_format_parity.phpt | 119 ++++ .../tests/phpt/080_csv_write_parity.phpt | 76 +++ .../tests/phpt/081_json_write_parity.phpt | 66 ++ .../tests/phpt/082_write_no_leaks.phpt | 74 +++ .../083_parquet_write_columns_parity.phpt | 102 ++++ .../flow-php-ext/tests/phpt/bootstrap.php | 283 +++++++++ .../Flow/Parquet/Dremel/DremelShredder.php | 78 ++- .../Parquet/Engine/ArrowParquetFileWriter.php | 19 + .../Engine/NativeParquetFileWriter.php | 5 + .../Parquet/Engine/PhpParquetFileWriter.php | 28 + .../src/Flow/Parquet/ParquetFileWriter.php | 6 + src/lib/parquet/src/Flow/Parquet/Writer.php | 9 + .../src/Flow/Parquet/Writer/ColumnLists.php | 43 ++ .../Flow/Parquet/Writer/RowGroupBuilder.php | 40 ++ .../Flow/Parquet/Tests/Context/ColumnDoor.php | 109 ++++ .../Engine/NativeLibWriteParityTest.php | 28 + .../Tests/Unit/Dremel/DremelShredderTest.php | 78 +++ .../Engine/ArrowParquetFileWriterTest.php | 77 +++ .../Engine/NativeParquetFileWriterTest.php | 135 +++++ .../Unit/Engine/PhpParquetFileWriterTest.php | 95 +++ .../Tests/Unit/Writer/ColumnListsTest.php | 31 + .../src/Flow/Types/Type/Native/FloatType.php | 12 + .../Tests/Unit/Type/Native/FloatTypeTest.php | 35 ++ 125 files changed, 9029 insertions(+), 1290 deletions(-) create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSink.php create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSinkOpener.php create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVWriteOptions.php create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVEncoder.php create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVEncoder.php create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Mother/CSVEncoderMother.php delete mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVEncoderTest.php create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVOpenSinkTest.php create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSinkOpenerTest.php create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVWriteOptionsTest.php create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/NativeCSVEncoderTest.php create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/PhpCSVEncoderTest.php delete mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonDocuments.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonFraming.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSink.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSinkOpener.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJSONEncoder.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJSONEncoder.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JSONEncoderMother.php delete mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JSONEncoderTest.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFramingTest.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonOpenSinkTest.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonSinkOpenerTest.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/NativeJSONEncoderTest.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/PhpJSONEncoderTest.php create mode 100644 src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLValueNodes.php create mode 100644 src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Context/XMLWriterValues.php create mode 100644 src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLValueNodesTest.php create mode 100644 src/core/etl/src/Flow/ETL/Column/DateFormatPattern.php create mode 100644 src/core/etl/src/Flow/ETL/Column/Elements.php create mode 100644 src/core/etl/src/Flow/ETL/Column/RoundTripPrecision.php create mode 100644 src/core/etl/src/Flow/ETL/Column/TextValues.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Context/TextWriterBatches.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DateFormatPatternTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ElementsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/RoundTripPrecisionTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php create mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/NativeCSVWriter.php create mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonWriter.php create mode 100644 src/extension/flow-php-ext/src/csv/write.rs create mode 100644 src/extension/flow-php-ext/src/json/mod.rs create mode 100644 src/extension/flow-php-ext/src/json/write.rs create mode 100644 src/extension/flow-php-ext/src/text/batch.rs create mode 100644 src/extension/flow-php-ext/src/text/date.rs create mode 100644 src/extension/flow-php-ext/src/text/float.rs create mode 100644 src/extension/flow-php-ext/src/text/json.rs create mode 100644 src/extension/flow-php-ext/src/text/mod.rs create mode 100644 src/extension/flow-php-ext/src/text/value.rs create mode 100644 src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/079_text_date_format_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/080_csv_write_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/081_json_write_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/083_parquet_write_columns_parity.phpt create mode 100644 src/lib/parquet/src/Flow/Parquet/Writer/ColumnLists.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Context/ColumnDoor.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Writer/ColumnListsTest.php diff --git a/documentation/components/adapters/csv.md b/documentation/components/adapters/csv.md index 66cd8267e5..e1bf882572 100644 --- a/documentation/components/adapters/csv.md +++ b/documentation/components/adapters/csv.md @@ -35,16 +35,48 @@ $rows = data_frame() ## Loader -```php +```php read(from_rows( - array_to_rows( - [['id' => 1, 'name' => 'Norbert'], ['id' => 2, 'name' => 'Tomek'], ['id' => 3, 'name' => 'Dawid']], - schema(int_schema('id'), str_schema('name')), - ) + ->read(from_array( + [ + ['id' => 1, 'active' => true, 'price' => 0.1 + 0.2, 'at' => new DateTimeImmutable('2026-01-02 03:04:05 UTC'), 'days' => [new DateTimeImmutable('2026-01-02')], 'labels' => [0 => 'a', 1 => 'b'], 'size' => ['w' => 1, 'h' => 2], 'meta' => '{"tags": []}'], + ['id' => 2, 'active' => false, 'price' => 1.0, 'at' => null, 'days' => [], 'labels' => [], 'size' => ['w' => 3, 'h' => 4], 'meta' => '{}'], + ], + schema( + int_schema('id'), bool_schema('active'), float_schema('price'), datetime_schema('at', nullable: true), + list_schema('days', type_list(type_date())), map_schema('labels', type_map(type_integer(), type_string())), + structure_schema('size', type_structure(['w' => type_integer(), 'h' => type_integer()])), json_schema('meta'), + ), )) - ->load(to_csv($path, true, true)) + ->write(to_csv($path)) ->run(); ``` + +```csv +id,active,price,at,days,labels,size,meta +1,true,0.30000000000000004,2026-01-02T03:04:05+00:00,"[""2026-01-02""]","{""0"":""a"",""1"":""b""}","{""w"":1,""h"":2}","{""tags"": []}" +2,false,1.0,,[],{},"{""w"":3,""h"":4}",{} +``` + +| Column | Field | +|----------------------------|------------------------------------------------------------------------------------------------------------------------------------| +| `boolean` | `true` / `false` | +| `float` | the shortest text that reads back as the same float, always with a fraction or an exponent: `1.0`, `1.0e+25`; `NAN`, `INF`, `-INF` | +| `null`, `''` | an empty field - `from_csv()` reads both back as `null` unless `withEmptyToNull(false)` | +| `datetime`, `date` | `withDateTimeFormat()` (default `DATE_ATOM`) in the column zone, `withDateFormat()` (default `Y-m-d`) | +| `time` | microseconds | +| `list`, `map`, `structure` | JSON: a list is `[…]`, a map and a structure are always `{…}`; every element is written as a column of its type would be | +| `json` | the stored text | + +Floats are rendered under `serialize_precision = -1`. When the ini holds another value the writer sets it for the +render and restores it, so `ini_set()` must be allowed; otherwise it throws +`RuntimeException('Writing floats requires serialize_precision = -1 and ini_set() cannot change it')`. + +With the [`flow_php`](/documentation/components/extensions/flow-php-ext.md) extension loaded the same bytes are +rendered natively. diff --git a/documentation/components/adapters/json.md b/documentation/components/adapters/json.md index 065a27a56d..95398e16d0 100644 --- a/documentation/components/adapters/json.md +++ b/documentation/components/adapters/json.md @@ -88,6 +88,51 @@ data_frame() ->run(); ``` +## What the loaders write + +```php +read(from_array( + [ + ['id' => 1, 'active' => true, 'price' => 0.1 + 0.2, 'at' => new DateTimeImmutable('2026-01-02 03:04:05 UTC'), 'days' => [new DateTimeImmutable('2026-01-02')], 'labels' => [0 => 'a', 1 => 'b'], 'size' => ['w' => 1, 'h' => 2], 'meta' => '{"tags": []}'], + ['id' => 2, 'active' => false, 'price' => 1.0, 'at' => null, 'days' => [], 'labels' => [], 'size' => ['w' => 3, 'h' => 4], 'meta' => '{}'], + ], + schema( + int_schema('id'), bool_schema('active'), float_schema('price'), datetime_schema('at', nullable: true), + list_schema('days', type_list(type_date())), map_schema('labels', type_map(type_integer(), type_string())), + structure_schema('size', type_structure(['w' => type_integer(), 'h' => type_integer()])), json_schema('meta'), + ), + )) + ->write(to_json_lines($path)) + ->run(); +``` + +```json +{"id":1,"active":true,"price":0.30000000000000004,"at":"2026-01-02T03:04:05+00:00","days":["2026-01-02"],"labels":{"0":"a","1":"b"},"size":{"w":1,"h":2},"meta":{"tags":[]}} +{"id":2,"active":false,"price":1,"at":null,"days":[],"labels":{},"size":{"w":3,"h":4},"meta":{}} +``` + +The shape follows the column type, never the data: a `list` is always `[…]`, a `map`, a `structure` and a row are +always `{…}` (an empty map is `{}`, a map keyed `0, 1` is `{"0":…,"1":…}`), a `json` column keeps its objects and +lists. A `datetime` / `date` is written with `withDateTimeFormat()` / `withDateFormat()` at every depth, a `time` as +microseconds. A float has the shortest digits that read back as the same float (`1.0` is `1`, or `1.0` under +`JSON_PRESERVE_ZERO_FRACTION`); `NAN` and the infinities are refused: +`RuntimeException('Failed to encode JSON: Inf and NaN cannot be JSON encoded')`. + +Floats are rendered under `serialize_precision = -1`. When the ini holds another value the writer sets it for the +render and restores it, so `ini_set()` must be allowed; otherwise it throws +`RuntimeException('Writing floats requires serialize_precision = -1 and ini_set() cannot change it')`. + +With the [`flow_php`](/documentation/components/extensions/flow-php-ext.md) extension loaded and no flags beyond +`JSON_THROW_ON_ERROR`, `JSON_UNESCAPED_SLASHES`, `JSON_UNESCAPED_UNICODE` and `JSON_PRESERVE_ZERO_FRACTION`, the same +bytes are rendered natively. + ## JSON Schema conversion The adapter can convert [JSON Schema](https://json-schema.org) documents into Flow schemas and back. diff --git a/documentation/components/adapters/parquet.md b/documentation/components/adapters/parquet.md index 8c4510f1eb..41f32b7822 100644 --- a/documentation/components/adapters/parquet.md +++ b/documentation/components/adapters/parquet.md @@ -43,6 +43,9 @@ df() Flow `float` columns are written as Parquet `DOUBLE`. +With an engine of the `flow-php/parquet` library (`PhpParquetEngine`, or `ArrowParquetEngine` without `flow_php`) a +batch reaches the writer column by column, through `Writer::writeColumns()`. + ## Schema The file footer is the schema: `from_parquet(...)->withSchema()` throws. Project with `columns:`, change types after diff --git a/documentation/components/adapters/text.md b/documentation/components/adapters/text.md index d0c73148bb..1593d7755b 100644 --- a/documentation/components/adapters/text.md +++ b/documentation/components/adapters/text.md @@ -56,3 +56,37 @@ use function Flow\ETL\DSL\{array_to_rows, schema, str_schema}; ->load(to_text($path)) ->run(); ``` + +Every value of the single column is one line: + +```php +read(from_array([['price' => 0.1 + 0.2], ['price' => 1.0], ['price' => INF]], schema(float_schema('price')))) + ->write(to_text($path)) + ->run(); +``` + +``` +0.30000000000000004 +1.0 +INF +``` + +| Column | Line | +|----------------------------|------------------------------------------------------------------------------------------------------------------------------------| +| `boolean` | `true` / `false` | +| `float` | the shortest text that reads back as the same float, always with a fraction or an exponent: `1.0`, `1.0e+25`; `NAN`, `INF`, `-INF` | +| `null` | an empty line | +| `datetime`, `date` | `DATE_ATOM` in the column zone, `Y-m-d` | +| `time` | microseconds | +| `json` | the stored text | +| `list`, `map`, `structure` | refused: `Text data loader supports only scalar values, got array` | + +Floats are rendered under `serialize_precision = -1`. When the ini holds another value the writer sets it for the +render and restores it, so `ini_set()` must be allowed; otherwise it throws +`RuntimeException('Writing floats requires serialize_precision = -1 and ini_set() cannot change it')`. diff --git a/documentation/components/adapters/xml.md b/documentation/components/adapters/xml.md index 77e45da6dc..2809edff82 100644 --- a/documentation/components/adapters/xml.md +++ b/documentation/components/adapters/xml.md @@ -77,4 +77,89 @@ From there you can use built in expressions to extract data from XML. When working with collections XPath will return an ListEntry with XMLEntries inside. From there you can for example unpack or expand them. -For more examples please look into `/examples/topics/xml` directory in [flow monorepo](https://github.com/flow-php/flow) \ No newline at end of file +For more examples please look into `/examples/topics/xml` directory in [flow monorepo](https://github.com/flow-php/flow) + +## Loader + +```php +read(from_array( + [ + ['id' => 1, 'active' => true, 'price' => 0.1 + 0.2, 'at' => new DateTimeImmutable('2026-01-02 03:04:05 UTC'), 'days' => [new DateTimeImmutable('2026-01-02')], 'labels' => [0 => 'a', 1 => 'b'], 'size' => ['w' => 1, 'h' => 2], 'meta' => '{"tags": []}'], + ['id' => 2, 'active' => false, 'price' => 1.0, 'at' => null, 'days' => [], 'labels' => [], 'size' => ['w' => 3, 'h' => 4], 'meta' => '{}'], + ], + schema( + int_schema('id'), bool_schema('active'), float_schema('price'), datetime_schema('at', nullable: true), + list_schema('days', type_list(type_date())), map_schema('labels', type_map(type_integer(), type_string())), + structure_schema('size', type_structure(['w' => type_integer(), 'h' => type_integer()])), json_schema('meta'), + ), + )) + ->write(to_xml($path)) + ->run(); +``` + +```xml + + +1true0.300000000000000042026-01-02T03:04:05.000000+00:002026-01-020a1b12{"tags": []} +2false1.034{} + +``` + +| Column | Element | +|----------------------------|------------------------------------------------------------------------------------------------------------------------------------| +| `boolean` | `true` / `false` | +| `float` | the shortest text that reads back as the same float, always with a fraction or an exponent: `1.0`, `1.0e+25`; `NAN`, `INF`, `-INF` | +| `null` | an empty element | +| `datetime`, `date` | `withDateTimeFormat()` (default `Y-m-d\TH:i:s.uP`) in the column zone, `withDateFormat()` (default `Y-m-d`) | +| `time` | microseconds | +| `list`, `map`, `structure` | nested elements; every leaf is written as a column of its type would be | +| `json` | the stored text | + +A column whose name starts with the attribute prefix (`_` by default) is an attribute of its row; a null there is +refused. + +Floats are rendered under `serialize_precision = -1`. When the ini holds another value the writer sets it for the +render and restores it, so `ini_set()` must be allowed; otherwise it throws +`RuntimeException('Writing floats requires serialize_precision = -1 and ini_set() cannot change it')`. + +### Custom writers + +`XMLWriter` renders a column at a time: `elements()` and `attributes()` return one string per value, with the writer's +own escaping. A writer that only builds nodes delegates to `write()`: + +```php + substr($this->write(XMLNode::nested('x', new XMLAttribute($name, type_string()->cast($value)))), 2, -2), + $values, + ); + } + + public function elements(string $name, array $values): array + { + return array_map(fn (?string $value): string => $this->write(XMLNode::flatNode($name, $value ?? '')), $values); + } + + public function write(XMLNode $node): string + { + // ... + } +} +``` \ No newline at end of file diff --git a/documentation/components/extensions/flow-php-ext.md b/documentation/components/extensions/flow-php-ext.md index 0d48627fc2..9597e596c1 100644 --- a/documentation/components/extensions/flow-php-ext.md +++ b/documentation/components/extensions/flow-php-ext.md @@ -8,7 +8,7 @@ package: flow-php/flow-php-ext [TOC] -This extension is Flow's native column backend and reads CSV and Parquet and writes Parquet natively in Rust via +This extension is Flow's native column backend and reads CSV and Parquet and writes CSV, JSON and Parquet natively in Rust via [ext-php-rs](https://github.com/extphprs/ext-php-rs). The pure-PHP implementations in `flow-php/etl` are the canonical behaviour reference and work without the extension - loading it is purely an optimization. @@ -65,6 +65,34 @@ The extension registers the interfaces `Flow\ETL\Column\{Backend, Column, Column and `Flow\ETL\Adapter\CSV\RustColumnFoldNative`, which read CSV straight into native columns and narrow string columns to their types. +## CSV and JSON writers + +With the extension loaded, `to_csv()`, `to_json()` and `to_json_lines()` render a batch from the arrow buffers, without +a PHP value per cell. The bytes are the ones the PHP writers produce. + +```php +read(from_csv(__DIR__ . '/input.csv')) + ->write(to_csv(__DIR__ . '/output.csv')->withDateTimeFormat('Y-m-d H:i:s.u P')) // rendered natively + ->write(to_json_lines(__DIR__ . '/output.jsonl')->withDateTimeFormat('D, d M Y')) // `D` and `M`: this column renders in PHP + ->run(); +``` + +A datetime or date format is rendered natively when its letters are among `Y y m n d j H G i s u v e T P p O Z U c` +(and `\` escapes); any other letter renders that column in PHP. `xml`, `xml_element`, `html` and `html_element` columns, +a `json` column written to JSON, and a `list` / `map` / `structure` holding one of those also render in PHP - only +those columns, the rest of the batch stays native. `to_json()` and `to_json_lines()` render natively under the flags +`JSON_THROW_ON_ERROR`, `JSON_UNESCAPED_SLASHES`, `JSON_UNESCAPED_UNICODE` and `JSON_PRESERVE_ZERO_FRACTION`; any other +flag (`JSON_PRETTY_PRINT`, ...) writes through PHP. + +The classes are `Flow\ETL\Adapter\CSV\NativeCSVWriter` and `Flow\ETL\Adapter\JSON\NativeJsonWriter`. + ## Parquet With the extension loaded, `from_parquet()` and `to_parquet()` without an `engine:` read and write Parquet inside the @@ -122,4 +150,4 @@ $file->values(['address.city'], limit: 10, offset: 5_000); // a struct path; onl ``` The classes behind it are `Flow\Parquet\Engine\Native\{NativeParquetFile, NativeParquetColumnsReader, -NativeParquetRowsWriter}`. +NativeParquetRowsWriter}`. `Writer::writeColumns()` appends each list straight to its column. diff --git a/documentation/components/libs/parquet.md b/documentation/components/libs/parquet.md index 0416dfa623..8e42d4d42d 100644 --- a/documentation/components/libs/parquet.md +++ b/documentation/components/libs/parquet.md @@ -295,6 +295,24 @@ We can also open a file for a resource: $writer->openForStream($stream, $schema); ``` +### Writing columns + +A batch that is already held by column is written without building rows: one list per top-level column, every list of +the same length. A schema column the array lacks is written as nulls, a key the schema lacks is ignored. + +```php +$writer->open($path, $schema); +$writer->writeColumns(['id' => [1, 2, 3], 'name' => ['a', 'b', null]]); +$writer->writeColumns(['id' => [4], 'tags' => [['x', 'y']]]); +$writer->close(); +``` + +The file is the one `writeBatch()` writes for the same rows, and a value is accepted or refused as `writeBatch()` +accepts or refuses it. Lists of different lengths are refused: +`InvalidArgumentException('writeColumns() takes lists of one length, got "id": 3, "name": 2')`. + +A custom `ParquetFileWriter` implements `writeColumns(array $columns): void`. + ### Writing a single row ```php diff --git a/documentation/upgrading.md b/documentation/upgrading.md index 24f9a01124..22f110097f 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -935,6 +935,121 @@ public function eval(Rows $rows, FlowContext $context): Column |----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------| | `flow-php/arrow-ext` - the arrow extension, `ArrowParquetEngine`'s backend | `abandoned` in favour of `flow-php/flow-php-ext`: install the `flow_php` extension, which `ArrowParquetEngine` uses when it is loaded | +### 87) `flow-php/etl-adapter-csv` - `to_csv()` writes a boolean as `true` / `false` + +| Before | After | +|------------------------------------------------------------------|--------------------------------------------------------------------| +| `true` → `1`, `false` → an empty field, the same bytes as `null` | `true` / `false`; `null` stays an empty field | +| a NOT NULL boolean column could not be read back by `from_csv()` | reads back equal; a nullable column keeps `false` and `null` apart | + +### 88) `flow-php/etl-adapter-csv`, `-xml`, `-text`, `-json` - a float is written as the shortest text that reads back as the same float + +| Before | After | +|-----------------------------------------------------------------------------------------------|---------------------------------------------------------------| +| CSV / XML / Text: `(string) $float`, 14 digits under the `precision` ini: `0.1 + 0.2` → `0.3` | `0.30000000000000004` | +| `1 / 3` → `0.33333333333333`, `123456789012345.678` → `1.2345678901235E+14` | `0.3333333333333333`, `123456789012345.67` | +| `1.0` → `1`, `1e25` → `1.0E+25`, `-0.0` → `-0` | `1.0`, `1.0e+25`, `-0.0` - always a fraction or an exponent | +| `NAN`, `INF`, `-INF` | unchanged; refused inside a nested CSV cell (`JsonException`) | +| JSON: the digits followed the `serialize_precision` ini (`17` → `0.10000000000000001`) | the shortest digits under any ini value | + +Writing a float column forces `serialize_precision = -1` for the render and restores the ini afterwards. When the ini +holds another value, `ini_set()` must be allowed; otherwise the writers throw +`RuntimeException('Writing floats requires serialize_precision = -1 and ini_set() cannot change it')`. + +### 89) `flow-php/etl-adapter-csv`, `-json`, `-xml`, `-text` - a nested value is written by its type, as a column of that type is + +| Before | After | +|---------------------------------------------------------------------------------------------------------|----------------------------------------------------------------| +| CSV `list`: `[{"date":"2026-01-02 03:04:05.000000","timezone_type":3,"timezone":"UTC"}]` | `["2026-01-02T03:04:05+00:00"]` (the loader's datetime format) | +| CSV `list`: `[{}]`; `list', + 'node' => 'zażółć gęślą jaźń ☃ 😀', + ], + 'non-ascii attribute' => ['document' => '', 'node' => ''], + 'non-ascii name' => [ + 'document' => '<żółć ść="1"/>', + 'node' => '<żółć ść="1"/>', + ], + 'non-ascii comment, pi, cdata' => [ + 'document' => '', + 'node' => '', + ], + 'entities' => [ + 'document' => '<p> & © 😀 ', + 'node' => '<p> & © 😀 ', + ], + 'inherited namespace' => [ + 'document' => 'ż', + 'node' => 'ż', + ], + 'latin1 source' => [ + 'document' => "\xE9", + 'node' => 'é', + ], + 'whitespace and empty' => [ + 'document' => "\n \t ", + 'node' => "\n \t ", + ], + ]; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php index 432865bafa..c9493f7dbb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php @@ -33,4 +33,26 @@ public function test_builds_offsets_and_nulls(): void static::assertSame([1 => true], $column->nulls); static::assertSame([[1, 2], null, [], [3]], $column->physicals()); } + + public function test_a_bulk_append_builds_the_column_row_by_row_appends_build(): void + { + $physicals = [[[1, 2], []], null, [], [null, [3]], [5 => [4]]]; + $builder = static fn(): ListColumnBuilder => new ListColumnBuilder( + type_list(type_list(type_integer())), + new ListColumnBuilder( + type_list(type_integer()), + new ScalarColumnBuilder(type_integer(), new IdentityPhysical()), + ), + ); + $bulk = $builder(); + $bulk->appendPhysicalMany($physicals); + $rowByRow = $builder(); + + foreach ($physicals as $physical) { + $rowByRow->appendPhysical($physical); + } + + static::assertEquals($rowByRow->finish(), $bulk->finish()); + static::assertSame([[[1, 2], []], null, [], [null, [3]], [[4]]], $bulk->finish()->physicals()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php index b9b38c5687..ccbccde65f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php @@ -95,9 +95,17 @@ public static function types(): Generator yield 'xml element' => [type_xml_element(), XmlElementPhysical::class]; yield 'html' => [type_html(), HtmlDocumentPhysical::class]; yield 'html element' => [type_html_element(), HtmlElementPhysical::class]; - yield 'list' => [type_list(type_integer()), ListPhysical::class]; - yield 'map' => [type_map(type_string(), type_integer()), MapPhysical::class]; - yield 'structure' => [type_structure(['a' => type_integer()]), StructPhysical::class]; + yield 'list of identities' => [type_list(type_optional(type_integer())), IdentityPhysical::class]; + yield 'list of lists of identities' => [type_list(type_list(type_string())), IdentityPhysical::class]; + yield 'list' => [type_list(type_date()), ListPhysical::class]; + yield 'map of identities' => [type_map(type_string(), type_integer()), IdentityPhysical::class]; + yield 'map' => [type_map(type_string(), type_uuid()), MapPhysical::class]; + yield 'structure of identities' => [ + type_structure(['a' => type_integer(), 'b' => type_list(type_string())]), + IdentityPhysical::class, + ]; + yield 'structure' => [type_structure(['a' => type_integer(), 'b' => type_date()]), StructPhysical::class]; + yield 'structure of a list' => [type_structure(['a' => type_list(type_date())]), StructPhysical::class]; yield 'null' => [type_null(), NullPhysical::class]; } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php index e62a316812..2fc0509116 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php @@ -39,4 +39,15 @@ public function test_takes_the_null_count_the_caller_already_counted(): void static::assertSame([1, null, null, null, 5], $column->physicals()); static::assertSame(3, $column->nullCount()); } + + public function test_a_bulk_append_counts_only_nulls(): void + { + $builder = new ScalarColumnBuilder(type_optional(type_integer()), new IdentityPhysical()); + $builder->appendPhysicalMany([0, '', false, null, '0']); + + $column = $builder->finish(); + + static::assertSame([0, '', false, null, '0'], $column->physicals()); + static::assertSame(1, $column->nullCount()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php index ba86e0cf97..2c6ffcff93 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php @@ -5,12 +5,14 @@ namespace Flow\ETL\Tests\Unit\Column\Php; use Flow\ETL\Column\Php\IdentityPhysical; +use Flow\ETL\Column\Php\ListColumnBuilder; use Flow\ETL\Column\Php\ScalarColumnBuilder; use Flow\ETL\Column\Php\StructColumn; use Flow\ETL\Column\Php\StructColumnBuilder; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_structure; final class StructColumnBuilderTest extends TestCase @@ -33,4 +35,38 @@ public function test_a_null_parent_sets_every_child_bit_to_zero(): void static::assertSame([1, null, 3], $column->children['a']->physicals()); static::assertSame([2, null, null], $column->children['b']->physicals()); } + + public function test_a_bulk_append_builds_the_column_row_by_row_appends_build(): void + { + $physicals = [['a' => 1, 'b' => [1, 2]], null, ['b' => []], ['a' => null, 'b' => null], ['b' => [3], 'a' => 4]]; + $builder = static fn(): StructColumnBuilder => new StructColumnBuilder( + type_structure(['a' => type_integer(), 'b' => type_list(type_integer())]), + [ + 'a' => new ScalarColumnBuilder(type_integer(), new IdentityPhysical()), + 'b' => new ListColumnBuilder( + type_list(type_integer()), + new ScalarColumnBuilder(type_integer(), new IdentityPhysical()), + ), + ], + ); + $bulk = $builder(); + $bulk->appendPhysicalMany($physicals); + $rowByRow = $builder(); + + foreach ($physicals as $physical) { + $rowByRow->appendPhysical($physical); + } + + static::assertEquals($rowByRow->finish(), $bulk->finish()); + static::assertSame( + [ + ['a' => 1, 'b' => [1, 2]], + null, + ['a' => null, 'b' => []], + ['a' => null, 'b' => null], + ['a' => 4, 'b' => [3]], + ], + $bulk->finish()->physicals(), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php index 790e01e90f..727833eed1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php @@ -5,8 +5,13 @@ namespace Flow\ETL\Tests\Unit\Column\Php; use DOMDocument; +use DOMElement; use Flow\ETL\Column\Php\XmlDocumentPhysical; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Tests\Mother\XmlNodeMother; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_string; @@ -33,4 +38,48 @@ public function test_malformed_markup_is_refused(): void (new XmlDocumentPhysical())->fromPhysical(''); } + + public static function nodes(): Generator + { + foreach (XmlNodeMother::edges() as $label => ['node' => $node]) { + yield $label => [$node]; + } + } + + #[DataProvider('nodes')] + public function test_text_is_the_inverse_of_physical(string $node): void + { + $physical = new XmlDocumentPhysical(); + + static::assertSame($node, $physical->text($physical->physical($node))); + } + + #[TestWith(["\n\n"])] + #[TestWith(["\n\n\n"])] + #[TestWith(["\n\n\n"])] + #[TestWith(["\n\n\n"])] + #[TestWith(["\n\n\n"])] + #[TestWith(["\n\n\n"])] + #[TestWith(["\n\n"])] + #[TestWith(["\n"])] + #[TestWith(["\n\n"])] + #[TestWith([''])] + public function test_bytes_physical_did_not_produce_have_no_text(string $physical): void + { + static::assertNull((new XmlDocumentPhysical())->text($physical)); + } + + public function test_the_physical_of_a_node_is_the_markup_of_its_utf8_document(): void + { + $document = new DOMDocument('1.0', 'UTF-8'); + $row = new DOMElement('row'); + $document->appendChild($row); + $row->setAttribute('a', 'żółć'); + $row->appendChild(new DOMElement('b', 'ść')); + + static::assertSame( + (new XmlDocumentPhysical())->toPhysical($document), + (new XmlDocumentPhysical())->physical('ść'), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php index 17cf0e0d5f..d0774180c9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php @@ -6,6 +6,7 @@ use DateTimeImmutable; use DateTimeZone; +use Flow\ETL\Column\Php\XmlDocumentPhysical; use Flow\ETL\Column\TextValues; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; use Flow\Types\Type; @@ -80,6 +81,15 @@ public static function plain_values(): Generator ['' . "\n" . '' . "\n", null], ['', null], ]; + yield 'xml node documents' => [ + type_xml(), + [ + XmlDocumentPhysical::DECLARATION . '' . "\n", + XmlDocumentPhysical::DECLARATION . "\n\n", + null, + ], + ['', '', null], + ]; yield 'xml_element' => [type_xml_element(), ['', null], ['', null]]; yield 'html' => [type_html(), ['x', null], ['x', null]]; yield 'html_element' => [type_html_element(), ['

      x

      ', null], ['

      x

      ', null]]; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ComparatorExtensionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ComparatorExtensionTest.php new file mode 100644 index 0000000000..facb943252 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ComparatorExtensionTest.php @@ -0,0 +1,28 @@ + 1]], schema(int_schema('id'))); + + static::assertInstanceOf(RowsComparator::class, Factory::getInstance()->getComparatorFor($rows, $rows)); + static::assertInstanceOf(ColumnComparator::class, Factory::getInstance()->getComparatorFor( + $rows->column('id'), + $rows->column('id'), + )); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php index d791bb2aa1..960137fb5f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/CastTest.php @@ -7,6 +7,7 @@ use DateTimeImmutable; use DateTimeZone; use DOMDocument; +use DOMElement; use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Schema\Definition; @@ -210,6 +211,9 @@ public static function cast_provider(): array $xml = new DOMDocument(); $xml->loadXML($xmlString = 'bar'); + $node = new DOMDocument('1.0', 'UTF-8'); + $node->appendChild(new DOMElement('row', 'zażółć')); + $fullXMLString = <<<'XML' bar @@ -234,6 +238,7 @@ public static function cast_provider(): array ], 'string_to_xml' => [$xmlString, str_schema('value'), 'xml', $xml], 'xml_to_string' => [$xml, xml_schema('value'), 'string', 'bar'], + 'xml_node_document_to_string' => [$node, xml_schema('value'), 'string', 'zażółć'], 'full_xml_to_string' => [$fullXMLString, str_schema('value'), 'string', $fullXMLString], 'datetime' => [ new DateTimeImmutable('2023-01-01 00:00:00 UTC'), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php index 38af1722fc..4a493bd823 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ArrayToRowsTest.php @@ -149,4 +149,26 @@ public function test_building_rows_from_array_with_schema_but_entries_not_availa $rows, ); } + + public function test_a_numeric_key_is_the_declared_column_of_that_name(): void + { + static::assertSame( + [['0' => 'x', 'e07' => 'y']], + array_to_rows( + [[0 => 'x', 7 => 'y']], + schema(str_schema('0'), str_schema('e07')), + flow_context(config())->backend(), + )->toArray(), + ); + } + + public function test_refuses_an_undeclared_numeric_key_under_its_positional_name(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage( + 'Rows do not match their schema: column "e07" (row 0) is not declared by the schema', + ); + + array_to_rows([[0 => 'x', 7 => 'y']], schema(str_schema('0')), flow_context(config())->backend()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php index 11cb90f76b..03c75a0c36 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php @@ -711,4 +711,27 @@ public function test_append_rows_of_already_typed_values_is_idempotent(): void (new RowsBuilder($schema, new PhpBackend()))->appendRows([$rows->values(0)])->finish(), ); } + + public function test_a_present_null_and_an_absent_key_are_both_null(): void + { + static::assertSame( + [['id' => 1, 'name' => null], ['id' => 2, 'name' => null], ['id' => 3, 'name' => 'c']], + (new RowsBuilder(schema(int_schema('id'), str_schema('name', nullable: true)), new PhpBackend())) + ->appendRows([['id' => 1, 'name' => null], ['id' => 2], ['id' => 3, 'name' => 'c']]) + ->finish() + ->toArray(), + ); + } + + public function test_a_refused_value_in_a_column_every_row_carries_is_placed_at_its_row(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "id" (row 3): could not convert \'x\' (string) to integer'); + + (new RowsBuilder(schema(int_schema('id')), new PhpBackend()))->appendRows([['id' => 1]])->appendRows([ + ['id' => 2], + ['id' => 3], + ['id' => 'x'], + ]); + } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Fixtures/xml-node-before-utf8.floe b/src/core/etl/tests/Flow/Floe/Tests/Fixtures/xml-node-before-utf8.floe new file mode 100644 index 0000000000000000000000000000000000000000..d617d9d332bf17296e906cb6e61836f9b5865b6e GIT binary patch literal 523 zcmaJ<#t_+tvNa zI!pCeo)?J}W3nzxngl&Rmu29yV9WYvYil(10HNJ@>vGtFIr4O*L&vn+zzQAH^!xz} z{6X`$_dl`D#_ZDpvxD-Ck2nC51}nxCmic0&Rn$jpFyo7WB4hLGG8m Ms_S=*6XF~E0H^cacheDir->suffix('xml-node-utf8.floe'); + + df() + ->read(from_floe(__DIR__ . '/../Fixtures/xml-node-before-utf8.floe')) + ->write(to_floe($loaded, filesystem: $this->fs())) + ->run(); + + static::assertSame( + [ + ['node' => 'zażółć ☃ 😀'], + ['node' => ''], + ['node' => '<p> & ©'], + ], + df() + ->read(from_floe($loaded, filesystem: $this->fs())) + ->withEntry('node', ref('node')->cast(type_string())) + ->fetch() + ->toArray(), + ); + } } diff --git a/src/extension/flow-php-ext/src/builder.rs b/src/extension/flow-php-ext/src/builder.rs index 69bb9978e9..75af58ace2 100644 --- a/src/extension/flow-php-ext/src/builder.rs +++ b/src/extension/flow-php-ext/src/builder.rs @@ -12,11 +12,11 @@ use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, ZendObject, Zval}; use flow_batch_frame::kind::Kind; -use crate::cast::{cast_value, CastKind}; +use crate::cast::{cast_value, CastKind, MapKeyKind}; use crate::column::NativeColumn; use crate::ctx::{ self, call_handle_catching, call_method, call_static, construct_with_zvals, expect_object, find_class, - ht_for_each, null_zval, read_slot, transparent_exception, zval_long, + ht_for_each, ht_get, null_zval, read_slot, transparent_exception, zval_long, }; use crate::date_check::iso_instant_micros; use crate::exception::ext_exception; @@ -41,7 +41,7 @@ pub enum Native { Bytes(Zval), } -/// One value ready to append: `appendMany()` builds all of them before appending any. +/// One value ready to append, for `DefaultBackend::constant()`. pub enum Pending { Null, Native(Native), @@ -62,17 +62,25 @@ fn string_slot(object: &ZendObject, slot: u32) -> Option { /// The physical form of `value` for `plan`, when `cast.rs` casts it natively; `None` hands it to the PHP lane. pub fn native_lane(plan: &TypePlan, value: &Zval) -> Result, PhpException> { - if let (Kind::Timestamp, CastKind::DateTime(_)) = (&plan.kind, &plan.cast) { + native_leaf(&plan.kind, &plan.cast, value) +} + +fn native_leaf(kind: &Kind, cast_kind: &CastKind, value: &Zval) -> Result, PhpException> { + if let (Kind::Timestamp, CastKind::DateTime(_)) = (kind, cast_kind) { if let Some(micros) = value.zend_str().and_then(|string| iso_instant_micros(string.as_bytes())) { return Ok(Some(Native::Fixed(micros.to_le_bytes()))); } } - let Some(cast) = cast_value(&plan.cast, value)? else { + if nested(kind) { + return Ok(None); + } + + let Some(cast) = cast_value(cast_kind, value)? else { return Ok(None); }; - Ok(match (&plan.kind, &plan.cast) { + Ok(match (kind, cast_kind) { (Kind::Int64, CastKind::Integer | CastKind::PositiveInteger) => { cast.long().map(|long| Native::Fixed(long.to_le_bytes())) } @@ -106,6 +114,119 @@ pub fn native_lane(plan: &TypePlan, value: &Zval) -> Result, PhpE }) } +fn nested(kind: &Kind) -> bool { + matches!(kind, Kind::List(_) | Kind::Map(..) | Kind::Struct(_)) +} + +/// Casts `value` straight into `builder`, element by element. `Ok(false)`: Rust does not cast this value, and the row +/// is left half-appended for the caller to truncate before the PHP lane casts the whole value. +fn append_cast(builder: &mut KindBuilder, kind: &Kind, cast_kind: &CastKind, value: &Zval) -> Result { + let value = value.dereference(); + + match (kind, cast_kind) { + (_, CastKind::Optional(inner)) => { + if value.is_null() { + builder.append_null(); + + return Ok(true); + } + + append_cast(builder, kind, inner, value) + } + (Kind::List(element), CastKind::List(inner)) => { + let Some(values) = value.array() else { + return Ok(false); + }; + let mut expected = 0; + let mut cast = true; + + ht_for_each(values, |string_key, index, item| { + cast = cast + && string_key.is_none() + && index == expected + && append_cast(builder.list_element(), &element.kind, inner, item)?; + expected += 1; + + Ok(()) + })?; + + if cast { + builder.end_entries().map_err(overflow)?; + } + + Ok(cast) + } + (Kind::Map(key, item_kind), CastKind::Map(key_cast, inner)) => { + let Some(values) = value.array() else { + return Ok(false); + }; + let mut cast = true; + + ht_for_each(values, |string_key, index, item| { + if !cast { + return Ok(()); + } + + let (keys, items) = builder.map_entries(); + + cast = match (key_cast, string_key, &key.kind) { + (MapKeyKind::Int, None, Kind::Int64) => { + keys.append_fixed(&(index as i64).to_le_bytes()); + + true + } + (MapKeyKind::Str, Some(name), Kind::Bytes) => { + keys.append_bytes(name.as_bytes()).map_err(overflow)?; + + true + } + _ => false, + } && append_cast(items, &item_kind.kind, inner, item)?; + + Ok(()) + })?; + + if cast { + builder.end_entries().map_err(overflow)?; + } + + Ok(cast) + } + (Kind::Struct(fields), CastKind::Structure(elements)) => { + let Some(values) = value.array() else { + return Ok(false); + }; + + for ((child, field), element) in builder.struct_children().iter_mut().zip(fields).zip(elements) { + match ht_get(values, field.name.as_bytes()) { + None if element.required => return Ok(false), + None => child.append_null(), + Some(item) if item.dereference().is_null() && !matches!(element.kind, CastKind::Optional(_)) => { + return Ok(false); + } + Some(item) => { + if !append_cast(child, &field.kind, &element.kind, item)? { + return Ok(false); + } + } + } + } + + builder.end_struct(); + + Ok(true) + } + _ => match native_leaf(kind, cast_kind, value)? { + Some(native) => { + append_native(builder, native)?; + + Ok(true) + } + None => Ok(false), + }, + } +} + /// `$type->cast($value)`, then `$physical->toPhysical($cast)` unless the physical is the identity. pub fn php_lane(plan: &TypePlan, value: &Zval) -> Result { let type_obj = plan.type_zv.object().expect("a plan's type is an object"); @@ -134,17 +255,6 @@ fn append_native(builder: &mut KindBuilder, native: Native) -> Result<(), PhpExc Ok(()) } -fn append_pending(builder: &mut KindBuilder, kind: &Kind, pending: Pending) -> Result<(), PhpException> { - match pending { - Pending::Null => { - builder.append_null(); - Ok(()) - } - Pending::Native(native) => append_native(builder, native), - Pending::Physical(physical) => append_physical(builder, kind, &physical), - } -} - /// `ColumnMismatchException::valueDoesNotMatch($definition, $value[, $reason])`. pub fn value_does_not_match(definition: &Zval, value: Zval, reason: Option) -> Result { let mut args = vec![definition.shallow_clone(), value]; @@ -204,7 +314,7 @@ impl NativeColumnBuilder { }) } - /// One value for `append()`/`DefaultBackend::constant()`: refusals escape as PHP threw them. + /// One value for `DefaultBackend::constant()`: refusals escape as PHP threw them. pub fn pending(&self, value: &Zval) -> Result { let value = value.dereference(); @@ -228,8 +338,54 @@ impl NativeColumnBuilder { } } - pub fn append_pending(&mut self, pending: Pending) -> Result<(), PhpException> { - append_pending(&mut self.values, &self.plan.kind, pending) + /// One value cast and appended. With a `position`, refusals are `appendMany()`'s `SchemaMismatchException` at it; + /// without, they escape as PHP threw them, as `append()` lets them. + fn append_value(&mut self, value: &Zval, position: Option<&dyn Fn() -> Zval>) -> Result<(), PhpException> { + let value = value.dereference(); + let refuse = |cause: Zval| match position { + Some(position) => schema_mismatch(position(), cause), + None => throw(cause), + }; + + if value.is_null() { + if !self.nullable { + return Err(refuse(value_does_not_match(&self.definition, null_zval(), None)?)); + } + + self.values.append_null(); + + return Ok(()); + } + + if nested(&self.plan.kind) { + let row = self.values.len(); + + if append_cast(&mut self.values, &self.plan.kind, &self.plan.cast, value)? { + return Ok(()); + } + + self.values.truncate(row); + } else if let Some(native) = native_lane(&self.plan, value)? { + return append_native(&mut self.values, native); + } + + match php_lane(&self.plan, value) { + Ok(physical) => append_physical(&mut self.values, &self.plan.kind, &physical), + Err(Refusal::Cast(mut exception) | Refusal::Physical(mut exception)) + if position.is_none() || !is_types_exception(&exception)? => + { + Err(transparent_exception(&mut exception)) + } + // the cast's own reason is dropped, as CastingColumnBuilder::appendMany drops it + Err(Refusal::Cast(_)) => Err(refuse(value_does_not_match(&self.definition, value.shallow_clone(), None)?)), + Err(Refusal::Physical(mut exception)) => { + let mut reason = Zval::new(); + reason.set_object(&mut exception); + + // the value cast, so only the physical form's reason (a range) tells the user why it was refused + Err(refuse(value_does_not_match(&self.definition, value.shallow_clone(), Some(reason))?)) + } + } } fn not_null(&self, is_null: bool) -> Result<(), PhpException> { @@ -297,80 +453,31 @@ impl NativeColumnBuilder { } pub fn append(&mut self, value: &Zval) -> PhpResult<()> { - let pending = self.pending(value)?; + let start = self.values.len(); + let result = self.append_value(value, None); + + if result.is_err() { + self.values.truncate(start); + } - self.append_pending(pending) + result } #[php(name = "appendMany")] pub fn append_many(&mut self, values: &ZendHashTable) -> PhpResult<()> { - let mut pendings = Vec::with_capacity(values.len()); - - ht_for_each(values, |string_key, index, value| { - let value = value.dereference(); - let position = || match string_key { + let start = self.values.len(); + let result = ht_for_each(values, |string_key, index, value| { + self.append_value(value, Some(&|| match string_key { Some(name) => crate::ctx::zval_str(name.as_bytes()), None => zval_long(index as i64), - }; - - if value.is_null() { - if !self.nullable { - return Err(schema_mismatch( - position(), - value_does_not_match(&self.definition, null_zval(), None)?, - )); - } - - pendings.push(Pending::Null); - - return Ok(()); - } - - if let Some(native) = native_lane(&self.plan, value)? { - pendings.push(Pending::Native(native)); - - return Ok(()); - } + })) + }); - match php_lane(&self.plan, value) { - Ok(physical) => { - pendings.push(Pending::Physical(physical)); - - Ok(()) - } - Err(Refusal::Cast(mut exception)) => { - if !is_types_exception(&exception)? { - return Err(transparent_exception(&mut exception)); - } - - // the cast's own reason is dropped, as CastingColumnBuilder::appendMany drops it - Err(schema_mismatch( - position(), - value_does_not_match(&self.definition, value.shallow_clone(), None)?, - )) - } - Err(Refusal::Physical(mut exception)) => { - if !is_types_exception(&exception)? { - return Err(transparent_exception(&mut exception)); - } - - let mut reason = Zval::new(); - reason.set_object(&mut exception); - - // the value cast, so only the physical form's reason (a range) tells the user why it was refused - Err(schema_mismatch( - position(), - value_does_not_match(&self.definition, value.shallow_clone(), Some(reason))?, - )) - } - } - })?; - - for pending in pendings { - self.append_pending(pending)?; + if result.is_err() { + self.values.truncate(start); } - Ok(()) + result } #[php(name = "appendFrom")] diff --git a/src/extension/flow-php-ext/src/cast.rs b/src/extension/flow-php-ext/src/cast.rs index 0f4a0e555c..0b0b47c113 100644 --- a/src/extension/flow-php-ext/src/cast.rs +++ b/src/extension/flow-php-ext/src/cast.rs @@ -2,13 +2,11 @@ use std::os::raw::{c_char, c_int}; use ext_php_rs::boxed::ZBox; use ext_php_rs::exception::PhpException; -use ext_php_rs::flags::DataType; -use ext_php_rs::types::{ZendHashTable, ZendObject, ZendStr, Zval}; +use ext_php_rs::types::{ZendObject, ZendStr, Zval}; use ext_php_rs::zend::{ClassEntry, Function}; use crate::ctx::{ - self, array_key_index, call_handle_on, call_handle_transparent, expect_object, ht_insert, ht_insert_key, null_zval, - write_slot, zval_long, HtKey, HASH_FLAG_PACKED, + self, array_key_index, call_handle_on, call_handle_transparent, expect_object, null_zval, write_slot, zval_long, }; use crate::date_check::{iso_date_gate, iso_date_time_gate, IsoSuffix}; use crate::exception::ext_exception; @@ -38,9 +36,9 @@ pub enum MapKeyKind { } pub struct StructureElement { - name: String, - kind: CastKind, - required: bool, + pub name: String, + pub kind: CastKind, + pub required: bool, } pub enum CastKind { @@ -121,53 +119,6 @@ pub(crate) fn build_cast_kind(type_json: &TypeJson) -> CastKind { } } -/// In-order hashtable walk yielding `(string key, numeric key, value)` - the -/// early-exit sibling of `encode::ht_for_each` for the container cast checks. -struct HtEntries<'a> { - ht: &'a ZendHashTable, - packed: bool, - index: u32, -} - -fn ht_entries(ht: &ZendHashTable) -> HtEntries<'_> { - HtEntries { - ht, - packed: unsafe { ht.u.v.flags } & HASH_FLAG_PACKED != 0, - index: 0, - } -} - -impl<'a> Iterator for HtEntries<'a> { - type Item = (Option<&'a ZendStr>, u64, &'a Zval); - - fn next(&mut self) -> Option { - while self.index < self.ht.nNumUsed { - let position = self.index as usize; - self.index += 1; - - if self.packed { - let value = unsafe { &*self.ht.__bindgen_anon_1.arPacked.add(position) }; - - if value.get_type() == DataType::Undef { - continue; - } - - return Some((None, position as u64, value)); - } - - let bucket = unsafe { &*self.ht.__bindgen_anon_1.arData.add(position) }; - - if bucket.val.get_type() == DataType::Undef { - continue; - } - - return Some((unsafe { bucket.key.as_ref() }, bucket.h, &bucket.val)); - } - - None - } -} - fn engine_long(value: &Zval) -> i64 { unsafe { zval_get_long_func(std::ptr::from_ref(value), false) } } @@ -323,6 +274,17 @@ pub(crate) fn integer_from_str(bytes: &[u8]) -> Option { } } +/// `StringType::cast` of a non-finite float: the spelling the text writers produce, built without PHP's `(string)`, +/// which warns on NAN. +fn non_finite_text(value: f64) -> Option<&'static [u8]> { + match value { + value if value.is_nan() => Some(b"NAN"), + f64::INFINITY => Some(b"INF"), + f64::NEG_INFINITY => Some(b"-INF"), + _ => None, + } +} + /// The three non-finite spellings the text writers produce and `FloatType::cast` reads back, case-sensitive. fn named_float(bytes: &[u8]) -> Option { match bytes { @@ -383,7 +345,7 @@ pub(crate) fn parse_iso_date(bytes: &[u8]) -> Result, PhpException> date_from_free_form(bytes, Some(&mut utc)) } -/// Casts one value natively; `Ok(None)` bails the WHOLE column value to the +/// Casts one leaf value natively (containers: `builder.rs` `append_cast`); `Ok(None)` bails the WHOLE column value to the /// PHP fallback (`Type::cast`), which reproduces results, exception classes, /// messages and `previous` chains by re-running the canonical implementation. /// PHP calls made inside a branch discard their own thrown exceptions and bail @@ -442,6 +404,8 @@ pub(crate) fn cast_value(kind: &CastKind, value: &Zval) -> Result, zv.set_bool(parsed); zv }) + } else if value.double().is_some_and(|double| !double.is_finite()) { + None } else if value.is_long() || value.is_double() || value.is_null() { let mut zv = Zval::new(); zv.set_bool(value.coerce_to_bool()); @@ -453,6 +417,8 @@ pub(crate) fn cast_value(kind: &CastKind, value: &Zval) -> Result, CastKind::String => { if value.is_string() { Some(value.shallow_clone()) + } else if let Some(text) = value.double().and_then(non_finite_text) { + Some(ctx::zval_str(text)) } else if value.is_long() || value.is_double() { let mut zv = Zval::new(); zv.set_zend_string(engine_string(value)?); @@ -466,6 +432,8 @@ pub(crate) fn cast_value(kind: &CastKind, value: &Zval) -> Result, CastKind::NonEmptyString => { if value.zend_str().is_some_and(|s| !s.as_bytes().is_empty()) { Some(value.shallow_clone()) + } else if let Some(text) = value.double().and_then(non_finite_text) { + Some(ctx::zval_str(text)) } else if value.is_long() || value.is_double() { // engine string form of a number is never empty let mut zv = Zval::new(); @@ -495,7 +463,7 @@ pub(crate) fn cast_value(kind: &CastKind, value: &Zval) -> Result, Some((_, instant)) => Some(instant), None => None, } - } else if value.is_long() || value.is_double() { + } else if value.is_long() || value.double().is_some_and(f64::is_finite) { date_from_free_form(×tamp_string(value)?, None)? .map(|instant| in_zone(&instant, zone)) .transpose()? @@ -530,97 +498,6 @@ pub(crate) fn cast_value(kind: &CastKind, value: &Zval) -> Result, } } CastKind::Json => cast_json(value)?, - CastKind::List(inner) => { - let Some(values) = value.array() else { - return Ok(None); - }; - - let mut out = ZendHashTable::with_capacity(values.len() as u32); - - for (expected, (string_key, index, item)) in ht_entries(values).enumerate() { - if string_key.is_some() || index != expected as u64 { - return Ok(None); - } - - let Some(casted) = cast_value(inner, item)? else { - return Ok(None); - }; - - out.push(casted).map_err(|e| { - ext_exception(format!("flow_php failed to collect list values: {e:?}")) - })?; - } - - let mut zv = Zval::new(); - zv.set_hashtable(out); - Some(zv) - } - CastKind::Map(key_kind, value_kind) => { - let Some(values) = value.array() else { - return Ok(None); - }; - - let mut out = ZendHashTable::with_capacity(values.len() as u32); - - for (string_key, index, item) in ht_entries(values) { - let key = match (key_kind, string_key) { - (MapKeyKind::Int, None) => HtKey::Index(index as i64), - (MapKeyKind::Str, Some(name)) => HtKey::Str(name), - _ => return Ok(None), - }; - - let Some(casted) = cast_value(value_kind, item)? else { - return Ok(None); - }; - - ht_insert_key(&mut out, &key, casted); - } - - let mut zv = Zval::new(); - zv.set_hashtable(out); - Some(zv) - } - CastKind::Structure(elements) => { - let Some(values) = value.array() else { - return Ok(None); - }; - - let mut out = ZendHashTable::with_capacity(elements.len() as u32); - let mut matched = 0usize; - - for element in elements { - let Some(item) = values.get(element.name.as_str()) else { - if element.required { - // PHP throws MissingElementCastingException for absent required elements - return Ok(None); - } - - continue; - }; - - if item.is_null() && !matches!(element.kind, CastKind::Optional(_)) { - // PHP throws MissingElementCastingException for present-null elements - // whose type rejects null - required and structure-level optional alike - return Ok(None); - } - - let Some(casted) = cast_value(&element.kind, item)? else { - return Ok(None); - }; - - ht_insert(&mut out, element.name.as_bytes(), casted); - matched += 1; - } - - if matched == 0 { - // an all-optional structure with no matched keys fails PHP's assert - return Ok(None); - } - - let mut zv = Zval::new(); - zv.set_hashtable(out); - Some(zv) - } CastKind::Optional(inner) => { if value.is_null() { Some(null_zval()) @@ -628,7 +505,7 @@ pub(crate) fn cast_value(kind: &CastKind, value: &Zval) -> Result, cast_value(inner, value)? } } - CastKind::Fallback => None, + CastKind::List(_) | CastKind::Map(..) | CastKind::Structure(_) | CastKind::Fallback => None, }) } @@ -703,7 +580,7 @@ fn cast_date(value: &Zval) -> Result, PhpException> { return parse_iso_date(string.as_bytes()); } - let parsed = if value.is_long() || value.is_double() { + let parsed = if value.is_long() || value.double().is_some_and(f64::is_finite) { date_from_free_form(×tamp_string(value)?, None)? } else { None diff --git a/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt b/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt index 7f86491da4..1ee7cb8760 100644 --- a/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt @@ -11,7 +11,7 @@ use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\Double\ForeignTypeDefinition; use Flow\ETL\Tests\Double\ThrowingType; -use function Flow\ETL\DSL\{bool_schema, date_schema, datetime_schema, float_schema, int_schema, json_schema, list_schema, map_schema, uuid_schema}; +use function Flow\ETL\DSL\{bool_schema, date_schema, datetime_schema, float_schema, int_schema, json_schema, list_schema, map_schema, str_schema, uuid_schema}; use function Flow\Types\DSL\{type_integer, type_list, type_map, type_positive_integer, type_string}; $datetimes = [ @@ -61,6 +61,12 @@ foreach ([ $cases[] = $case; } +foreach ([bool_schema('a'), str_schema('s'), date_schema('d'), datetime_schema('at')] as $definition) { + foreach ([NAN, INF, -INF] as $value) { + $cases[] = [$definition, [$value]]; + } +} + $build = static fn(object $backend, object $definition, array $values, bool $many): Closure => static function () use ($backend, $definition, $values, $many): array { $builder = $backend->builder($definition); @@ -96,6 +102,6 @@ foreach (['UTC', 'Europe/Warsaw', 'America/Santiago'] as $timezone) { } ?> --EXPECT-- -date.timezone UTC: 446 of 446 identical -date.timezone Europe/Warsaw: 446 of 446 identical -date.timezone America/Santiago: 446 of 446 identical +date.timezone UTC: 470 of 470 identical +date.timezone Europe/Warsaw: 470 of 470 identical +date.timezone America/Santiago: 470 of 470 identical diff --git a/src/extension/flow-php-ext/tests/phpt/084_native_nested_cast_parity.phpt b/src/extension/flow-php-ext/tests/phpt/084_native_nested_cast_parity.phpt new file mode 100644 index 0000000000..073e50eaab --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/084_native_nested_cast_parity.phpt @@ -0,0 +1,65 @@ +--TEST-- +NativeColumnBuilder casts random nested values, raw and refused forms, as the PHP builder does through append() and appendMany() +--SKIPIF-- + +--FILE-- + 0; $i--) { + $values[] = cast_random_input($type, $generate()); + } + + foreach ([false, true] as $many) { + $column = static fn(object $backend): Closure => static function () use ($backend, $definition, $values, $many): object { + $builder = $backend->builder($definition); + + if ($many) { + $builder->appendMany($values); + } else { + foreach ($values as $value) { + $builder->append($value); + } + } + + return $builder->finish(); + }; + + foreach (['values', 'physicals', 'encode'] as $read) { + $cases++; + $php = outcome(static fn(): mixed => $column(new PhpBackend())()->{$read}()); + $native = outcome(static fn(): mixed => $column(new DefaultBackend())()->{$read}()); + + if ($php !== $native) { + echo ($many ? 'appendMany ' : 'append ') . "{$read} {$type->toString()} " . var_export($values, true) . "\n php: {$php}\n native: {$native}\n"; + + continue; + } + + $identical++; + $refused += refused($php) ? 1 : 0; + $nulls += str_contains(serialize($values), 'N;') ? 1 : 0; + } + } +} + +echo "{$identical} of {$cases} identical, {$refused} refused, {$nulls} with a null\n"; +?> +--EXPECT-- +2400 of 2400 identical, 690 refused, 654 with a null diff --git a/src/extension/flow-php-ext/tests/phpt/085_native_nested_cast_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/085_native_nested_cast_no_leaks.phpt new file mode 100644 index 0000000000..d97882966a --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/085_native_nested_cast_no_leaks.phpt @@ -0,0 +1,65 @@ +--TEST-- +nested values cast natively, handed to the PHP lane half-appended, and refused leak neither PHP memory nor native allocations +--SKIPIF-- + +--FILE-- + structure_element('id', type_integer()), + 'tags' => structure_element('tags', type_list(type_string())), + 'at' => structure_element('at', type_optional(type_datetime())), + 'note' => structure_element('note', type_string(), optional: true), +])); +$lists = list_schema('lists', type_list(type_list(type_integer()))); +$maps = map_schema('maps', type_map(type_string(), type_list(type_string()))); + +$cycle = static function () use ($backend, $orders, $lists, $maps): void { + $builder = $backend->builder($orders); + $builder->appendMany([ + ['id' => 1, 'tags' => ['a', 'b'], 'at' => '2026-01-02T03:04:05Z', 'note' => 'n'], + ['id' => '2', 'tags' => [], 'at' => null], + ['id' => 3, 'tags' => '["json", "text"]', 'at' => null], + ]); + $builder->finish()->values(); + $backend->builder($lists)->appendMany([[[1, 2], [3]], [[4, '5']], [[6, 7], [8]]]); + $backend->builder($maps)->appendMany([['a' => ['x'], 'b' => []], ['c' => ['y', 'z']]]); + + try { + $backend->builder($orders)->appendMany([['id' => 1, 'tags' => ['a'], 'at' => null], ['id' => 2, 'tags' => ['b', null]]]); + throw new LogicException('a refused value was accepted'); + } catch (Flow\ETL\Exception\SchemaMismatchException) { + } + + try { + $backend->builder($lists)->append([[1, 2], ['not an int']]); + throw new LogicException('a refused value was accepted'); + } catch (Flow\Types\Exception\CastingException) { + } +}; + +for ($i = 0; $i < 10; $i++) { + $cycle(); +} +gc_collect_cycles(); +$baseline = memory_get_usage(false); +$baselineRust = $backend->allocatedBytes(); + +for ($i = 0; $i < 100; $i++) { + $cycle(); +} +gc_collect_cycles(); + +var_dump(memory_get_usage(false) <= $baseline); +var_dump($backend->allocatedBytes() === $baselineRust); +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/bootstrap.php b/src/extension/flow-php-ext/tests/phpt/bootstrap.php index 47a27efbed..be29e8ce4a 100644 --- a/src/extension/flow-php-ext/tests/phpt/bootstrap.php +++ b/src/extension/flow-php-ext/tests/phpt/bootstrap.php @@ -957,6 +957,104 @@ static function () use ($values): array { return [type_optional($type), static fn(): mixed => mt_rand(0, 5) === 0 ? null : $value()]; } +/** + * A value of `$type` (from write_random_type()) in a random input form: as generated, in a raw form a reader hands over + * (numeric and ISO strings, Uuid and Json objects, a datetime in another zone), in a form the cast refuses (a wrong + * scalar, a scalar for a container, non-list keys, integer keys for string keys, a missing required element, a present + * null, an extra key), or null; containers recurse into their elements. `mt_srand()` first. + * + * @param Flow\Types\Type $type + */ +function cast_random_input(Flow\Types\Type $type, mixed $value): mixed +{ + static $zones = ['UTC', 'Europe/Warsaw', 'America/New_York', '+02:30', '-05:00']; + + $roll = mt_rand(0, 19); + + if ($value === null || $roll === 0) { + return null; + } + + $type = $type instanceof Flow\Types\Type\Logical\OptionalType ? $type->base() : $type; + + if ($roll === 1) { + return $type instanceof Flow\Types\Type\Logical\ListType + || $type instanceof Flow\Types\Type\Logical\MapType + || $type instanceof Flow\Types\Type\Logical\StructureType + ? [5, 'x', true][mt_rand(0, 2)] + : ['not a value', [1], -1.5][mt_rand(0, 2)]; + } + + $raw = $roll < 10; + + return match (true) { + $type instanceof Flow\Types\Type\Logical\ListType => (static function () use ($type, $value, $roll): array { + $list = array_map(static fn(mixed $item): mixed => cast_random_input( + $type->element(), + $item, + ), Flow\Types\DSL\type_list(Flow\Types\DSL\type_mixed())->assert($value)); + + return $roll === 2 && $list !== [] ? array_combine(range(1, count($list)), $list) : $list; + })(), + $type instanceof Flow\Types\Type\Logical\MapType => (static function () use ($type, $value, $roll): array { + $map = array_map(static fn(mixed $item): mixed => cast_random_input( + $type->value(), + $item, + ), Flow\Types\DSL\type_array()->assert($value)); + + if ($roll === 2 && $map !== []) { + $map[mt_rand(100, 200)] = reset($map); + } + + return $map; + })(), + $type instanceof Flow\Types\Type\Logical\StructureType => (static function () use ( + $type, + $value, + $roll, + ): array { + $structure = []; + + // @mago-ignore analysis:mixed-assignment + foreach (Flow\Types\DSL\type_array()->assert($value) as $name => $item) { + $structure[$name] = cast_random_input( + $type->element($name)->type ?? throw new LogicException('no such element'), + $item, + ); + } + + $names = array_keys($structure); + $name = $names === [] ? 'a' : $names[mt_rand(0, count($names) - 1)]; + + return match ($roll) { + 2 => array_diff_key($structure, [$name => true]), + 3 => array_replace($structure, [$name => null]), + 4 => $structure + ['extra key' => 1], + default => $structure, + }; + })(), + !$raw => $value, + $type instanceof Flow\Types\Type\Native\IntegerType, + $type instanceof Flow\Types\Type\Native\FloatType, + => Flow\Types\DSL\type_string()->cast($value), + $type instanceof Flow\Types\Type\Native\BooleanType => ['true', 'false', '1', '0', 'yes', 'off'][mt_rand(0, 5)], + $type instanceof Flow\Types\Type\Logical\DateTimeType, + $type instanceof Flow\Types\Type\Logical\DateType, + => mt_rand(0, 1) === 0 + ? Flow\Types\DSL\type_instance_of(DateTimeImmutable::class) + ->assert($value) + ->format($type instanceof Flow\Types\Type\Logical\DateType ? 'Y-m-d' : 'Y-m-d\\TH:i:s.uP') + : Flow\Types\DSL\type_instance_of(DateTimeImmutable::class) + ->assert($value) + ->setTimezone(new DateTimeZone($zones[mt_rand(0, count($zones) - 1)])), + $type instanceof Flow\Types\Type\Logical\UuidType + => new Flow\Types\Value\Uuid(Flow\Types\DSL\type_string()->assert($value)), + $type instanceof Flow\Types\Type\Logical\JsonType + => new Flow\Types\Value\Json(Flow\Types\DSL\type_string()->assert($value)), + default => $value, + }; +} + /** * A random batch for the text writers: 1-6 columns of random types (nesting <= 3) under plain and awkward names, 0-40 * rows. diff --git a/src/lib/types/src/Flow/Types/Type/Logical/DateTimeType.php b/src/lib/types/src/Flow/Types/Type/Logical/DateTimeType.php index 0ef8566988..18c06bb247 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/DateTimeType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/DateTimeType.php @@ -15,6 +15,7 @@ use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Native\String\StringTemporalParts; +use Flow\Types\Type\NonFiniteFloat; use Throwable; use function array_combine; @@ -197,6 +198,10 @@ public function cast(mixed $value): DateTimeImmutable return (new DateTimeImmutable($value, $this->zone))->setTimezone($this->zone); } + if (NonFiniteFloat::is($value)) { + throw new CastingException($value, $this, reason: 'value is not a point in time'); + } + if (is_numeric($value)) { return (new DateTimeImmutable('@' . $value))->setTimezone($this->zone); } diff --git a/src/lib/types/src/Flow/Types/Type/Logical/DateType.php b/src/lib/types/src/Flow/Types/Type/Logical/DateType.php index 682f8fa2d2..003d0a460e 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/DateType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/DateType.php @@ -14,6 +14,7 @@ use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; use Flow\Types\Type\Native\String\StringTemporalParts; +use Flow\Types\Type\NonFiniteFloat; use Throwable; use function is_bool; @@ -52,7 +53,7 @@ public function cast(mixed $value): DateTimeInterface try { if ($value instanceof DateTimeImmutable || $value instanceof DateTime) { - return DateTimeImmutable::createFromInterface($value)->setTime(0, 0, 0, 0); + return new DateTimeImmutable($value->format('Y-m-d'), $utc); } if (is_string($value)) { @@ -71,6 +72,10 @@ public function cast(mixed $value): DateTimeInterface return new DateTimeImmutable((new DateTimeImmutable($value))->format('Y-m-d'), $utc); } + if (NonFiniteFloat::is($value)) { + throw new CastingException($value, $this, reason: 'value is not a point in time'); + } + if (is_numeric($value)) { return (new DateTimeImmutable('@' . $value)) ->setTimezone($utc) diff --git a/src/lib/types/src/Flow/Types/Type/Logical/InstanceOfType.php b/src/lib/types/src/Flow/Types/Type/Logical/InstanceOfType.php index 03d32bcdf1..9e23c0c098 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/InstanceOfType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/InstanceOfType.php @@ -18,6 +18,7 @@ use function interface_exists; use function is_a; use function is_object; +use function is_scalar; use function is_string; /** @@ -75,7 +76,8 @@ public function cast(mixed $value): object } try { - $object = (object) $value; + // an explicit wrapper: PHP 8.5 warns on (object) NAN + $object = is_scalar($value) ? (object) ['scalar' => $value] : (object) $value; if (!$object instanceof $this->class) { throw new CastingException($value, type_instance_of($this->class)); diff --git a/src/lib/types/src/Flow/Types/Type/Logical/ListType.php b/src/lib/types/src/Flow/Types/Type/Logical/ListType.php index 58c32c0172..a48fdf0613 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/ListType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/ListType.php @@ -105,7 +105,12 @@ public function cast(mixed $value): array $castedList[$key] = $this->element()->cast($item); } - return $this->assert($castedList); + if ($castedList !== [] && !array_is_list($castedList)) { + throw InvalidTypeException::value($castedList, $this); + } + + /** @var T $castedList */ + return $castedList; } catch (Throwable $e) { throw new CastingException($value, $this, $e); } diff --git a/src/lib/types/src/Flow/Types/Type/Logical/MapType.php b/src/lib/types/src/Flow/Types/Type/Logical/MapType.php index 0b9fbe23fe..4f601bea05 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/MapType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/MapType.php @@ -14,6 +14,7 @@ use Throwable; use function array_key_exists; +use function array_keys; use function Flow\Types\DSL\type_array; use function Flow\Types\DSL\type_from_array; use function Flow\Types\DSL\type_literal; @@ -103,6 +104,7 @@ public function cast(mixed $value): array } $castedMap = []; + $castedKeys = []; // @mago-ignore analysis:mixed-assignment foreach ($value as $key => $item) { @@ -113,9 +115,16 @@ public function cast(mixed $value): array } $castedMap[$castedKey] = $this->value->cast($item); + $castedKeys[] = $castedKey; } - return $this->assert($castedMap); + // PHP turns a numeric string key back into an integer + if (array_keys($castedMap) !== $castedKeys) { + throw InvalidTypeException::value($castedMap, $this); + } + + /** @var T $castedMap */ + return $castedMap; } catch (Throwable $e) { throw new CastingException($value, $this, $e); } diff --git a/src/lib/types/src/Flow/Types/Type/Logical/NonEmptyStringType.php b/src/lib/types/src/Flow/Types/Type/Logical/NonEmptyStringType.php index efa560667e..a1ee10ec91 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/NonEmptyStringType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/NonEmptyStringType.php @@ -11,12 +11,14 @@ use Flow\Types\Exception\CastingException; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; +use Flow\Types\Type\NonFiniteFloat; use Stringable; use Throwable; use function Flow\Types\DSL\dom_element_to_string; use function is_array; use function is_bool; +use function is_float; use function is_object; use function is_scalar; use function is_string; @@ -83,6 +85,10 @@ public function cast(mixed $value): string throw new CastingException($value, $this); } + if (is_float($value) && ($text = NonFiniteFloat::text($value)) !== null) { + return $text; + } + if (is_scalar($value) || is_object($value) && method_exists($value, '__toString')) { return $this->assert((string) $value); } diff --git a/src/lib/types/src/Flow/Types/Type/Logical/NumericStringType.php b/src/lib/types/src/Flow/Types/Type/Logical/NumericStringType.php index c719cbf714..af915c8cb5 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/NumericStringType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/NumericStringType.php @@ -7,8 +7,11 @@ use Flow\Types\Exception\CastingException; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; +use Flow\Types\Type\NonFiniteFloat; use Stringable; +use function is_float; +use function is_int; use function is_numeric; use function is_string; @@ -40,7 +43,7 @@ public function cast(mixed $value): string return $value; } - if (is_numeric($value)) { + if (is_int($value) || is_float($value) && !NonFiniteFloat::is($value)) { return (string) $value; } diff --git a/src/lib/types/src/Flow/Types/Type/Logical/StructureType.php b/src/lib/types/src/Flow/Types/Type/Logical/StructureType.php index 8148d5ab21..7d58960131 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/StructureType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/StructureType.php @@ -199,7 +199,12 @@ public function cast(mixed $value): array $castedStructure[$element->name] = $element->type->cast($value[$element->name] ?? null); } - return $this->assert($castedStructure); + if ($castedStructure !== [] && array_is_list($castedStructure)) { + throw InvalidTypeException::value($castedStructure, $this); + } + + /** @var T $castedStructure */ + return $castedStructure; } catch (Throwable $e) { throw new CastingException($value, $this, $e); } diff --git a/src/lib/types/src/Flow/Types/Type/Logical/XMLElementType.php b/src/lib/types/src/Flow/Types/Type/Logical/XMLElementType.php index 9c8743a9ab..1cc7676b89 100644 --- a/src/lib/types/src/Flow/Types/Type/Logical/XMLElementType.php +++ b/src/lib/types/src/Flow/Types/Type/Logical/XMLElementType.php @@ -38,7 +38,10 @@ public function cast(mixed $value): DOMElement|Element if (is_string($value)) { $dom = new DOMDocument(); - $dom->loadXML($value); + + if (!@$dom->loadXML($value)) { + throw new CastingException($value, $this); + } return type_instance_of(DOMElement::class)->assert($dom->documentElement); } diff --git a/src/lib/types/src/Flow/Types/Type/Native/BooleanType.php b/src/lib/types/src/Flow/Types/Type/Native/BooleanType.php index 6b150bbff8..a535a8bdec 100644 --- a/src/lib/types/src/Flow/Types/Type/Native/BooleanType.php +++ b/src/lib/types/src/Flow/Types/Type/Native/BooleanType.php @@ -8,6 +8,7 @@ use Flow\Types\Exception\CastingException; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; +use Flow\Types\Type\NonFiniteFloat; use Throwable; use function in_array; @@ -54,6 +55,10 @@ public function cast(mixed $value): bool throw new CastingException($value, $this); } + if (NonFiniteFloat::is($value)) { + throw new CastingException($value, $this); + } + if (is_scalar($value)) { return (bool) $value; } diff --git a/src/lib/types/src/Flow/Types/Type/Native/FloatType.php b/src/lib/types/src/Flow/Types/Type/Native/FloatType.php index df9d8b5438..f0cbe1df12 100644 --- a/src/lib/types/src/Flow/Types/Type/Native/FloatType.php +++ b/src/lib/types/src/Flow/Types/Type/Native/FloatType.php @@ -10,10 +10,12 @@ use Flow\Types\Exception\CastingException; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; +use Flow\Types\Type\NonFiniteFloat; use function is_bool; use function is_float; use function is_numeric; +use function is_string; /** * @template T of float @@ -56,16 +58,10 @@ public function cast(mixed $value): float return ((float) $endTime->format('Uu') - (float) $reference->format('Uu')) / 1e6; } - if ($value === 'NAN') { - return NAN; - } - - if ($value === 'INF') { - return INF; - } + $nonFinite = is_string($value) ? NonFiniteFloat::fromText($value) : null; - if ($value === '-INF') { - return -INF; + if ($nonFinite !== null) { + return $nonFinite; } if (is_numeric($value)) { diff --git a/src/lib/types/src/Flow/Types/Type/Native/ObjectType.php b/src/lib/types/src/Flow/Types/Type/Native/ObjectType.php index 94d00d1920..d8e7748191 100644 --- a/src/lib/types/src/Flow/Types/Type/Native/ObjectType.php +++ b/src/lib/types/src/Flow/Types/Type/Native/ObjectType.php @@ -8,6 +8,7 @@ use Flow\Types\Type; use function is_object; +use function is_scalar; /** * @template T of object @@ -36,7 +37,8 @@ public function cast(mixed $value): object return $value; } - return (object) $value; + // an explicit wrapper: PHP 8.5 warns on (object) NAN + return is_scalar($value) ? (object) ['scalar' => $value] : (object) $value; } public function isValid(mixed $value): bool diff --git a/src/lib/types/src/Flow/Types/Type/Native/StringType.php b/src/lib/types/src/Flow/Types/Type/Native/StringType.php index 3b483b9d9d..f24d75f419 100644 --- a/src/lib/types/src/Flow/Types/Type/Native/StringType.php +++ b/src/lib/types/src/Flow/Types/Type/Native/StringType.php @@ -14,12 +14,14 @@ use Flow\Types\Exception\CastingException; use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Type; +use Flow\Types\Type\NonFiniteFloat; use Stringable; use Throwable; use function Flow\Types\DSL\dom_element_to_string; use function is_array; use function is_bool; +use function is_float; use function is_object; use function is_scalar; use function is_string; @@ -96,6 +98,10 @@ public function cast(mixed $value): string return $value->innerHTML; } + if (is_float($value) && ($text = NonFiniteFloat::text($value)) !== null) { + return $text; + } + if (is_scalar($value) || is_object($value) && method_exists($value, '__toString')) { return (string) $value; } diff --git a/src/lib/types/src/Flow/Types/Type/NonFiniteFloat.php b/src/lib/types/src/Flow/Types/Type/NonFiniteFloat.php new file mode 100644 index 0000000000..63a83b5baf --- /dev/null +++ b/src/lib/types/src/Flow/Types/Type/NonFiniteFloat.php @@ -0,0 +1,40 @@ + NAN, + 'INF' => INF, + '-INF' => -INF, + default => null, + }; + } + + public static function is(mixed $value): bool + { + return is_float($value) && !is_finite($value); + } + + /** + * @return null|'-INF'|'INF'|'NAN' + */ + public static function text(float $value): ?string + { + return match (true) { + is_nan($value) => 'NAN', + $value === INF => 'INF', + $value === -INF => '-INF', + default => null, + }; + } +} diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/CastResultIsValidTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/CastResultIsValidTest.php new file mode 100644 index 0000000000..bf5fed084c --- /dev/null +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/CastResultIsValidTest.php @@ -0,0 +1,124 @@ + [type_integer()]; + yield 'float' => [type_float()]; + yield 'boolean' => [type_boolean()]; + yield 'string' => [type_string()]; + yield 'numeric_string' => [type_numeric_string()]; + yield 'date' => [type_date()]; + yield 'datetime Europe/Warsaw' => [type_datetime('Europe/Warsaw')]; + yield 'uuid' => [type_uuid()]; + yield 'json' => [type_json()]; + yield 'xml' => [type_xml()]; + yield 'optional' => [type_optional(type_date())]; + yield 'list' => [type_list(type_date())]; + yield 'list' => [type_list(type_optional(type_numeric_string()))]; + yield 'list>' => [type_list(type_list(type_integer()))]; + yield 'map' => [type_map(type_string(), type_date())]; + yield 'map' => [type_map(type_integer(), type_string())]; + yield 'structure{a: date}' => [type_structure(['a' => type_date()])]; + yield 'structure{a: numeric_string, b?: numeric_string}' => [type_structure([ + 'a' => type_numeric_string(), + 'b' => structure_element('b', type_numeric_string(), optional: true), + ])]; + yield 'structure{a?: string}' => [type_structure(['a' => structure_element( + 'a', + type_string(), + optional: true, + )])]; + yield 'list' => [type_list(type_structure(['a' => type_float()]))]; + } + + /** + * @param Type $type + */ + #[DataProvider('types')] + public function test_every_cast_result_is_valid_for_its_type(Type $type): void + { + $warsaw = new DateTimeImmutable('2024-01-02 03:04:05.123456', new DateTimeZone('Europe/Warsaw')); + $values = [ + null, + true, + 0, + 5, + 1.5, + NAN, + INF, + '', + '5', + 'abc', + '1e3', + '2024-01-02', + '2024-01-02T03:04:05Z', + '0193f3a0-7b1c-7e6d-9d3a-1c2b3a4d5e6f', + '{"a":1}', + '', + $warsaw, + new DateTime('2024-01-02'), + new Uuid('0193f3a0-7b1c-7e6d-9d3a-1c2b3a4d5e6f'), + new Json('{"a":1}'), + ['5'], + ['a' => '2024-01-02'], + [1 => 'x'], + ['a' => $warsaw], + [[1, 2]], + ['a' => '1', 'b' => INF], + [], + [['a' => 1.5]], + ['1' => 'a', '2' => 'b'], + [null], + ]; + + foreach ($values as $index => $value) { + try { + // @mago-ignore analysis:mixed-assignment + $cast = $type->cast($value); + } catch (Throwable) { + continue; + } + + static::assertTrue( + $type->isValid($cast), + "value #{$index} cast into {$type->toString()} is not valid for it", + ); + } + } +} diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTimeTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTimeTypeTest.php index 1a4fabe99e..61ccd4635a 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTimeTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTimeTypeTest.php @@ -492,4 +492,14 @@ public function test_cast_does_not_mutate_a_datetime(): void static::assertSame('2021-01-01 00:00:00 UTC', $value->format('Y-m-d H:i:s e')); } + + #[TestWith([NAN])] + #[TestWith([INF])] + #[TestWith([-INF])] + public function test_a_non_finite_float_is_refused(float $value): void + { + $this->expectException(CastingException::class); + + type_datetime()->cast($value); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTypeTest.php index 6984c2523a..023f4dcb82 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/DateTypeTest.php @@ -284,4 +284,25 @@ public function test_string_date_is_midnight_utc_under_non_utc_default(string $v date_default_timezone_set($previous); } } + + #[TestWith(['2026-01-02 00:30:00', 'Europe/Warsaw'])] + #[TestWith(['2026-01-02 23:30:00', 'America/New_York'])] + public function test_a_zoned_datetime_casts_to_midnight_utc_of_its_calendar_day( + string $datetime, + string $zone, + ): void { + $date = type_date()->cast(new DateTimeImmutable($datetime, new DateTimeZone($zone))); + + static::assertSame('2026-01-02 00:00:00 UTC', $date->format('Y-m-d H:i:s e')); + } + + #[TestWith([NAN])] + #[TestWith([INF])] + #[TestWith([-INF])] + public function test_a_non_finite_float_is_refused(float $value): void + { + $this->expectException(CastingException::class); + + type_date()->cast($value); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/InstanceOfTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/InstanceOfTypeTest.php index d7004fe249..27dfe4330e 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/InstanceOfTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/InstanceOfTypeTest.php @@ -161,4 +161,9 @@ public function test_to_string(): void { static::assertSame('object', type_instance_of(DateTimeImmutable::class)->toString()); } + + public function test_a_nan_is_wrapped_as_its_scalar(): void + { + static::assertNan(type_instance_of(stdClass::class)->cast(NAN)->scalar); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/ListTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/ListTypeTest.php index 75c50bdd1b..41315c342e 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/ListTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/ListTypeTest.php @@ -4,6 +4,8 @@ namespace Flow\Types\Tests\Unit\Type\Logical; +use DateTimeImmutable; +use DateTimeInterface; use DateTimeZone; use Flow\Types\Exception\CastingException; use Flow\Types\Exception\InvalidTypeException; @@ -13,7 +15,9 @@ use PHPUnit\Framework\TestCase; use stdClass; +use function array_map; use function Flow\Types\DSL\type_boolean; +use function Flow\Types\DSL\type_date; use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_from_array; use function Flow\Types\DSL\type_integer; @@ -255,4 +259,32 @@ public function test_to_string(): void { static::assertSame('list', type_list(type_boolean())->toString()); } + + public function test_a_cast_that_keeps_non_list_keys_is_refused(): void + { + try { + type_list(type_string())->cast([1 => 'x']); + static::fail('Expected CastingException'); + } catch (CastingException $e) { + static::assertSame('Can\'t cast "array" into "list" type', $e->getMessage()); + static::assertInstanceOf(InvalidTypeException::class, $e->getPrevious()); + static::assertSame( + 'Expected type "list", got "map".', + $e->getPrevious()->getMessage(), + ); + } + } + + public function test_a_zoned_datetime_casts_to_its_calendar_day_in_a_list_of_dates(): void + { + $dates = type_list(type_date())->cast([new DateTimeImmutable( + '2026-01-02 00:30:00', + new DateTimeZone('Europe/Warsaw'), + )]); + + static::assertSame( + ['2026-01-02 00:00:00 UTC'], + array_map(static fn(DateTimeInterface $date): string => $date->format('Y-m-d H:i:s e'), $dates), + ); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/MapTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/MapTypeTest.php index 2c410c87d4..8c18158955 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/MapTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/MapTypeTest.php @@ -209,4 +209,19 @@ public function test_to_string(): void { static::assertSame('map', type_map(type_string(), type_string())->toString()); } + + public function test_a_key_php_coerces_back_is_refused(): void + { + try { + type_map(type_string(), type_integer())->cast([5 => 1]); + static::fail('Expected CastingException'); + } catch (CastingException $e) { + static::assertSame('Can\'t cast "array" into "map" type', $e->getMessage()); + static::assertInstanceOf(InvalidTypeException::class, $e->getPrevious()); + static::assertSame( + 'Expected type "map", got "map".', + $e->getPrevious()->getMessage(), + ); + } + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/NonEmptyStringTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/NonEmptyStringTypeTest.php index 8fad639c76..737521e74c 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/NonEmptyStringTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/NonEmptyStringTypeTest.php @@ -12,6 +12,7 @@ use Flow\Types\Exception\InvalidTypeException; use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_from_array; @@ -160,4 +161,12 @@ public function test_to_string(): void { static::assertSame('non_empty_string', type_non_empty_string()->toString()); } + + #[TestWith([NAN, 'NAN'])] + #[TestWith([INF, 'INF'])] + #[TestWith([-INF, '-INF'])] + public function test_a_non_finite_float_is_spelled_as_the_float_cast_reads_it(float $value, string $text): void + { + static::assertSame($text, type_non_empty_string()->cast($value)); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/NumericStringTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/NumericStringTypeTest.php index 1be82b860e..eaef39d2c6 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/NumericStringTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/NumericStringTypeTest.php @@ -10,6 +10,7 @@ use Flow\Types\Tests\Unit\Type\Fixtures\StringableObject; use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_from_array; @@ -154,4 +155,14 @@ public function test_to_string(): void { static::assertSame('numeric-string', type_numeric_string()->toString()); } + + #[TestWith([NAN])] + #[TestWith([INF])] + #[TestWith([-INF])] + public function test_a_non_finite_float_is_refused(float $value): void + { + $this->expectException(CastingException::class); + + type_numeric_string()->cast($value); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/StructureTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/StructureTypeTest.php index 4716ab3b54..864bb2cafa 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/StructureTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/StructureTypeTest.php @@ -868,4 +868,27 @@ public function test_to_string_with_optional_elements(): void $struct->toString(), ); } + + public function test_a_cast_whose_keys_form_a_list_is_refused(): void + { + try { + type_structure(['0' => structure_element('0', type_integer())])->cast(['0' => 1]); + static::fail('Expected CastingException'); + } catch (CastingException $e) { + static::assertSame('Can\'t cast "array" into "structure{0: integer}" type', $e->getMessage()); + static::assertInstanceOf(InvalidTypeException::class, $e->getPrevious()); + static::assertSame( + 'Expected type "structure{0: integer}", got "list".', + $e->getPrevious()->getMessage(), + ); + } + } + + public function test_an_all_optional_structure_casts_an_empty_array(): void + { + static::assertSame( + [], + type_structure(['a' => structure_element('a', type_string(), optional: true)])->cast([]), + ); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/XMLElementTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/XMLElementTypeTest.php index 93c98edf91..112aa4a245 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/XMLElementTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Logical/XMLElementTypeTest.php @@ -7,14 +7,18 @@ use DateTimeImmutable; use DateTimeZone; use DOMElement; +use Flow\Types\Exception\CastingException; use Flow\Types\Exception\InvalidTypeException; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use stdClass; +use function error_reporting; use function Flow\Types\DSL\type_from_array; use function Flow\Types\DSL\type_xml_element; +use function restore_error_handler; +use function set_error_handler; final class XMLElementTypeTest extends TestCase { @@ -157,4 +161,27 @@ public function test_to_string(): void { static::assertSame('xml_element', type_xml_element()->toString()); } + + public function test_a_string_that_is_not_xml_is_refused_without_a_warning(): void + { + $warnings = []; + set_error_handler(static function (int $level, string $message) use (&$warnings): bool { + if ((error_reporting() & $level) !== 0) { + $warnings[] = $message; + } + + return true; + }); + + try { + type_xml_element()->cast('not xml'); + static::fail('Expected CastingException'); + } catch (CastingException $e) { + static::assertSame('Can\'t cast "string" into "xml_element" type', $e->getMessage()); + } finally { + restore_error_handler(); + } + + static::assertSame([], $warnings); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/BooleanTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/BooleanTypeTest.php index 9c3437f1e9..9469fd3333 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/BooleanTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/BooleanTypeTest.php @@ -12,6 +12,7 @@ use Flow\Types\Exception\InvalidTypeException; use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_boolean; @@ -245,4 +246,14 @@ public function test_to_string(): void { static::assertSame('boolean', type_boolean()->toString()); } + + #[TestWith([NAN])] + #[TestWith([INF])] + #[TestWith([-INF])] + public function test_a_non_finite_float_is_refused(float $value): void + { + $this->expectException(CastingException::class); + + type_boolean()->cast($value); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/ObjectTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/ObjectTypeTest.php index de46d49090..9a05d15ae8 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/ObjectTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/ObjectTypeTest.php @@ -156,4 +156,12 @@ public function test_to_string(): void { static::assertSame('object', type_object()->toString()); } + + public function test_a_nan_is_wrapped_as_its_scalar(): void + { + $object = type_object()->cast(NAN); + + static::assertInstanceOf(stdClass::class, $object); + static::assertNan($object->scalar); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/StringTypeTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/StringTypeTest.php index c34b521389..29a52d1c74 100644 --- a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/StringTypeTest.php +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/Native/StringTypeTest.php @@ -18,6 +18,7 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\RequiresPhp; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use stdClass; use Stringable; @@ -290,4 +291,12 @@ public function test_to_string(): void { static::assertSame('string', type_string()->toString()); } + + #[TestWith([NAN, 'NAN'])] + #[TestWith([INF, 'INF'])] + #[TestWith([-INF, '-INF'])] + public function test_a_non_finite_float_is_spelled_as_the_float_cast_reads_it(float $value, string $text): void + { + static::assertSame($text, type_string()->cast($value)); + } } diff --git a/src/lib/types/tests/Flow/Types/Tests/Unit/Type/NonFiniteFloatTest.php b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/NonFiniteFloatTest.php new file mode 100644 index 0000000000..f490aa2e51 --- /dev/null +++ b/src/lib/types/tests/Flow/Types/Tests/Unit/Type/NonFiniteFloatTest.php @@ -0,0 +1,51 @@ + Date: Thu, 1 Oct 2026 11:34:11 +0200 Subject: [PATCH 11/21] fix(flow-php/etl): html and xml elements keep their parent through a column - element bytes carry the owner document, the element path and its markup - older element bytes still read - element columns compare by the element markup --- documentation/upgrading.md | 11 ++ .../src/Flow/ETL/Column/ComparableValues.php | 23 +++- .../Flow/ETL/Column/Php/ElementPosition.php | 121 ++++++++++++++++++ .../ETL/Column/Php/HtmlElementPhysical.php | 59 ++++++++- .../ETL/Column/Php/XmlElementPhysical.php | 40 +++++- .../etl/src/Flow/ETL/Column/TextValues.php | 31 +++-- src/core/etl/src/Flow/ETL/Function/IsIn.php | 8 +- .../src/Flow/ETL/Window/PeerComparator.php | 2 +- .../Unit/Column/ComparableValuesTest.php | 26 +++- .../Unit/Column/Php/ElementPositionTest.php | 67 ++++++++++ .../Column/Php/HtmlElementPhysicalTest.php | 71 +++++++++- .../Column/Php/XmlElementPhysicalTest.php | 74 ++++++++++- .../ETL/Tests/Unit/Column/PhpBackendTest.php | 7 +- .../ETL/Tests/Unit/Function/EqualsTest.php | 13 ++ .../Flow/ETL/Tests/Unit/Function/IsInTest.php | 13 ++ .../Tests/Unit/Window/PeerComparatorTest.php | 14 ++ .../Tests/Fixtures/v2/all-entry-types.floe | Bin 4829 -> 4877 bytes 17 files changed, 539 insertions(+), 41 deletions(-) create mode 100644 src/core/etl/src/Flow/ETL/Column/Php/ElementPosition.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php diff --git a/documentation/upgrading.md b/documentation/upgrading.md index db5f58ba0b..d3adf19184 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -1092,6 +1092,17 @@ A `date` column stored that calendar day before, and still does. | `type_date()`, `type_datetime()` `->cast(NAN)`, `INF`, `-INF` | `CastingException` from `new DateTimeImmutable('@NAN')` | `CastingException`, reason `value is not a point in time` | | `type_string()`, `type_non_empty_string()` `->cast(NAN)`, `INF`, `-INF` | `'NAN'`, `'INF'`, `'-INF'`, a PHP 8.5 warning for `NAN` | the same text, no warning | +### 102) `flow-php/etl` - `html_element` and `xml_element` bytes carry the owner document + +| | Before | After | +|-----------------------------------------------------------|-----------------------------------------|-----------------------------------------------------------------------------------| +| the bytes an element column stores (Floe, Parquet, spill) | the element's markup | `"\x01" . . "\0" . . "\0" . . ` | +| `domElementParent()` of an element read from a column | `` or nothing, from a re-parse | the element's parent | +| `cast(type_string())`, `to_json()`, `to_csv()` | the element's markup | unchanged | + +An element column now stores its whole owner document per value: its size grows with the document. +Files written before still read. + --- ## Upgrading from 0.43.x to 0.44.x diff --git a/src/core/etl/src/Flow/ETL/Column/ComparableValues.php b/src/core/etl/src/Flow/ETL/Column/ComparableValues.php index 8e5b2a938e..f1999950f6 100644 --- a/src/core/etl/src/Flow/ETL/Column/ComparableValues.php +++ b/src/core/etl/src/Flow/ETL/Column/ComparableValues.php @@ -10,6 +10,7 @@ use Flow\Types\Type\Logical\HTMLElementType; use Flow\Types\Type\Logical\HTMLType; use Flow\Types\Type\Logical\JsonType; +use Flow\Types\Type\Logical\ListType; use Flow\Types\Type\Logical\TimeType; use Flow\Types\Type\Logical\UuidType; use Flow\Types\Type\Logical\XMLElementType; @@ -48,7 +49,27 @@ public function equalByPhysical(Type $type): bool */ public function equality(Column $column): array { - return $this->equalByPhysical($column->type()) ? $column->physicals() : $column->values(); + return $this->equalByPhysical($column->type()) + ? $this->equalities($column->type(), $column->physicals()) + : $column->values(); + } + + /** + * Element physicals carry their owner document, so elements, and lists of them, compare by their own markup. + * + * @param Type $type + * @param list $physicals + * + * @return list === on these is value equality + */ + public function equalities(Type $type, array $physicals): array + { + $bare = type_bare($type); + $element = $bare instanceof ListType ? type_bare($bare->element()) : $bare; + + return $element instanceof HTMLElementType || $element instanceof XMLElementType + ? (new TextValues())->of($type, $physicals) + : $physicals; } /** diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ElementPosition.php b/src/core/etl/src/Flow/ETL/Column/Php/ElementPosition.php new file mode 100644 index 0000000000..c5f57e1211 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Php/ElementPosition.php @@ -0,0 +1,121 @@ +\0\0", the path + * counting element children from the document element. Earlier builds wrote "\0\0", and + * before that bare element markup. + */ +final readonly class ElementPosition +{ + /** + * @param \DOMElement|\Dom\Element $element + * + * @return ?string null for an element outside its owner document's tree + */ + public function path(object $element): ?string + { + $indices = []; + $node = $element; + + while ($node->parentNode !== null && $node->parentNode->nodeType === XML_ELEMENT_NODE) { + $index = 0; + + for ( + $sibling = $node->previousElementSibling; + $sibling !== null; + $sibling = $sibling->previousElementSibling + ) { + $index++; + } + + $indices[] = $index; + /** @var \DOMElement|\Dom\Element $node */ + $node = $node->parentNode; + } + + return $node === $element->ownerDocument?->documentElement ? implode('/', array_reverse($indices)) : null; + } + + public function physical(string $path, string $markup, string $document): string + { + return "\x01" . $path . "\0" . strlen($markup) . "\0" . $markup . $document; + } + + /** + * @return ?string null for bare element markup + */ + public function pathOf(string $physical): ?string + { + return str_starts_with($physical, "\x01") || str_starts_with($physical, "\0") + ? substr($physical, 1, (int) strpos($physical, "\0", 1) - 1) + : null; + } + + /** + * @return ?string null for bytes that do not carry the element markup + */ + public function markupOf(string $physical): ?string + { + if (!str_starts_with($physical, "\x01")) { + return null; + } + + $pathEnd = (int) strpos($physical, "\0", 1); + $lengthEnd = (int) strpos($physical, "\0", $pathEnd + 1); + + return substr($physical, $lengthEnd + 1, (int) substr($physical, $pathEnd + 1, $lengthEnd - $pathEnd - 1)); + } + + public function documentOf(string $physical): string + { + $pathEnd = (int) strpos($physical, "\0", 1); + + if (!str_starts_with($physical, "\x01")) { + return substr($physical, $pathEnd + 1); + } + + $lengthEnd = (int) strpos($physical, "\0", $pathEnd + 1); + + return substr($physical, $lengthEnd + 1 + (int) substr($physical, $pathEnd + 1, $lengthEnd - $pathEnd - 1)); + } + + /** + * @param null|\DOMElement|\Dom\Element $documentElement + * + * @return null|\DOMElement|\Dom\Element + */ + public function element(?object $documentElement, string $path): ?object + { + $node = $documentElement; + + foreach ($path === '' ? [] : array_map(intval(...), explode('/', $path)) as $index) { + $node = $node?->firstElementChild; + + for ($i = 0; $node !== null && $i < $index; $i++) { + $node = $node->nextElementSibling; + } + + if ($node === null) { + return null; + } + } + + return $node; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php index 30c58a2e6d..f7b7e44bae 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php @@ -13,10 +13,15 @@ use function is_string; use function sprintf; +use const LIBXML_HTML_NOIMPLIED; use const LIBXML_NOERROR; final readonly class HtmlElementPhysical implements Physical { + public function __construct( + private ElementPosition $position = new ElementPosition(), + ) {} + public function toPhysical(mixed $value): mixed { assert(is_object($value)); @@ -30,7 +35,18 @@ public function toPhysical(mixed $value): mixed throw new InvalidArgumentException('Floe failed to convert HTMLElement to HTML string'); } - return $html; + $path = $this->position->path($value); + + if ($path === null) { + return $html; + } + + // @mago-ignore analysis:non-existent-method + // @mago-ignore analysis:mixed-assignment + $document = $value->ownerDocument?->saveHtml(); + assert(is_string($document)); + + return $this->position->physical($path, $html, $document); } public function fromPhysical(mixed $physical): mixed @@ -41,11 +57,22 @@ public function fromPhysical(mixed $physical): mixed throw new InvalidArgumentException('Floe cannot restore HTML values, \Dom\HTMLDocument requires PHP 8.4+'); } + $path = $this->position->pathOf($physical); + // @mago-expect analysis:unavailable-method - $element = HTMLDocument::createFromString( - '' . $physical . '', - LIBXML_NOERROR, - )->body?->firstElementChild; + $element = $path === null + ? HTMLDocument::createFromString( + '' . $physical . '', + LIBXML_NOERROR, + )->body?->firstElementChild + : $this->position->element( + // @mago-expect analysis:unavailable-method + HTMLDocument::createFromString( + $this->position->documentOf($physical), + LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR, + )->documentElement, + $path, + ); if ($element === null) { throw new InvalidArgumentException(sprintf('Floe failed to restore HTMLElement from "%s"', $physical)); @@ -54,6 +81,28 @@ public function fromPhysical(mixed $physical): mixed return $element; } + public function markup(string $physical): string + { + $markup = $this->position->markupOf($physical); + + if ($markup !== null) { + return $markup; + } + + if ($this->position->pathOf($physical) === null) { + return $physical; + } + + /** @var \Dom\HTMLElement $element */ + $element = $this->fromPhysical($physical); + // @mago-ignore analysis:non-existent-method + // @mago-ignore analysis:mixed-assignment + $html = $element->ownerDocument?->saveHtml($element); + assert(is_string($html)); + + return $html; + } + public function fromPhysicalAll(array $physicals): array { $values = []; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php index 49e16486e3..8e4c2e0b42 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php @@ -21,36 +21,41 @@ { public function __construct( private XmlDocumentPhysical $document = new XmlDocumentPhysical(), + private ElementPosition $position = new ElementPosition(), ) {} public function toPhysical(mixed $value): mixed { if ($value instanceof DOMElement) { - $xml = $value->ownerDocument?->saveXML($value); + $path = $this->position->path($value); + $xml = $value->ownerDocument?->saveXML($path === null ? $value : null); if ($xml === null || $xml === false) { throw new InvalidArgumentException('Floe failed to convert DOMElement to XML string'); } - return $xml; + return $path === null ? $xml : $this->position->physical($path, $this->canonical($value), $xml); } /** @var \Dom\Element $value */ + $path = $this->position->path($value); // @mago-ignore analysis:non-existent-method // @mago-ignore analysis:mixed-assignment - $markup = $value->ownerDocument?->saveXml($value); + $markup = $value->ownerDocument?->saveXml($path === null ? $value : null); assert(is_string($markup)); - return $markup; + return $path === null ? $markup : $this->position->physical($path, $this->canonical($value), $markup); } public function fromPhysical(mixed $physical): mixed { assert(is_string($physical)); - $element = type_instance_of(DOMDocument::class)->assert($this->document->fromPhysical( - $physical, + $path = $this->position->pathOf($physical); + $root = type_instance_of(DOMDocument::class)->assert($this->document->fromPhysical( + $path === null ? $physical : $this->position->documentOf($physical), ))->documentElement; + $element = $path === null ? $root : $this->position->element($root, $path); if ($element === null) { throw new InvalidArgumentException(sprintf('Floe failed to restore DOMElement from "%s"', $physical)); @@ -59,6 +64,29 @@ public function fromPhysical(mixed $physical): mixed return $element; } + public function markup(string $physical): string + { + return ( + $this->position->markupOf( + $physical, + ) ?? $this->canonical(type_instance_of(DOMElement::class)->assert($this->fromPhysical($physical))) + ); + } + + /** + * @param DOMElement|\Dom\Element $element + */ + public function canonical(object $element): string + { + $markup = $element->C14N(); + + if (!is_string($markup)) { + throw new InvalidArgumentException('Floe failed to canonicalize XML element'); + } + + return $markup; + } + public function fromPhysicalAll(array $physicals): array { $values = []; diff --git a/src/core/etl/src/Flow/ETL/Column/TextValues.php b/src/core/etl/src/Flow/ETL/Column/TextValues.php index e9ee1b4f5a..77457b6eb7 100644 --- a/src/core/etl/src/Flow/ETL/Column/TextValues.php +++ b/src/core/etl/src/Flow/ETL/Column/TextValues.php @@ -6,13 +6,15 @@ use DateTimeInterface; use DOMDocument; -use DOMElement; +use Flow\ETL\Column\Php\HtmlElementPhysical; use Flow\ETL\Column\Php\PhysicalFor; use Flow\ETL\Column\Php\XmlDocumentPhysical; +use Flow\ETL\Column\Php\XmlElementPhysical; use Flow\ETL\Exception\RuntimeException; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; +use Flow\Types\Type\Logical\HTMLElementType; use Flow\Types\Type\Logical\JsonType; use Flow\Types\Type\Logical\ListType; use Flow\Types\Type\Logical\MapType; @@ -101,7 +103,19 @@ public function of(Type $type, array $physicals): array return $values; } - if ($bare instanceof XMLType || $bare instanceof XMLElementType) { + if ($bare instanceof HTMLElementType || $bare instanceof XMLElementType) { + $elements = $bare instanceof HTMLElementType ? new HtmlElementPhysical() : new XmlElementPhysical(); + $values = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + $values[] = $physical === null ? null : $elements->markup(type_string()->assert($physical)); + } + + return $values; + } + + if ($bare instanceof XMLType) { $nodes = (new PhysicalFor())->type($bare); $documents = new XmlDocumentPhysical(); $values = []; @@ -114,15 +128,11 @@ public function of(Type $type, array $physicals): array continue; } - if ($bare instanceof XMLType) { - $text = $documents->text(type_string()->assert($physical)); + $text = $documents->text(type_string()->assert($physical)); - if ($text === null) { - $document = type_instance_of(DOMDocument::class)->assert($nodes->fromPhysical($physical)); - $text = $document->saveXML($document->documentElement); - } - } else { - $text = type_instance_of(DOMElement::class)->assert($nodes->fromPhysical($physical))->C14N(); + if ($text === null) { + $document = type_instance_of(DOMDocument::class)->assert($nodes->fromPhysical($physical)); + $text = $document->saveXML($document->documentElement); } if ($text === false) { @@ -182,6 +192,7 @@ public function keepsPhysical(Type $type): bool $bare instanceof JsonType, $bare instanceof XMLType, $bare instanceof XMLElementType, + $bare instanceof HTMLElementType, $bare instanceof MapType, $bare instanceof StructureType, => false, diff --git a/src/core/etl/src/Flow/ETL/Function/IsIn.php b/src/core/etl/src/Flow/ETL/Function/IsIn.php index 403a2f9b85..73af3fcb5c 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsIn.php +++ b/src/core/etl/src/Flow/ETL/Function/IsIn.php @@ -100,8 +100,8 @@ public function eval(Rows $rows, FlowContext $context): Column && $comparable->equalByPhysical($needleColumn->type()) ) { /** @var list> $haystacks */ - $haystacks = $haystackColumn->physicals(); - $needles = $needleColumn->physicals(); + $haystacks = $comparable->equalities($haystackColumn->type(), $haystackColumn->physicals()); + $needles = $comparable->equality($needleColumn); $physical = null; } else { $haystacks = $haystackParameter->arraysOf($haystackColumn); @@ -140,7 +140,9 @@ public function eval(Rows $rows, FlowContext $context): Column $needle instanceof DateTimeInterface && $candidate instanceof DateTimeInterface => $needle == $candidate, $physical !== null && get_debug_type($needle) === get_debug_type($candidate) - => $physical->toPhysical($needle) === $physical->toPhysical($candidate), + => $comparable->equalities($needleColumn->type(), [$physical->toPhysical( + $needle, + )]) === $comparable->equalities($needleColumn->type(), [$physical->toPhysical($candidate)]), default => $needle === $candidate, }) { $results[] = true; diff --git a/src/core/etl/src/Flow/ETL/Window/PeerComparator.php b/src/core/etl/src/Flow/ETL/Window/PeerComparator.php index fd83e12935..b24a061c7b 100644 --- a/src/core/etl/src/Flow/ETL/Window/PeerComparator.php +++ b/src/core/etl/src/Flow/ETL/Window/PeerComparator.php @@ -60,7 +60,7 @@ public function peersOfPrevious(Rows $partition): array if ($comparable->equalByPhysical($type)) { // === on physicals is value equality; NaN is the one physical that is not === to itself - $physicals = $column->physicals(); + $physicals = $comparable->equality($column); for ($i = 1; $i < $count; $i++) { // @mago-ignore analysis:mixed-assignment diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php index 68eb1c70a9..2181bf1e8e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php @@ -30,8 +30,10 @@ use function Flow\ETL\DSL\uuid_schema; use function Flow\ETL\DSL\xml_element_schema; use function Flow\ETL\DSL\xml_schema; +use function Flow\Types\DSL\type_html_element; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_xml_element; final class ComparableValuesTest extends TestCase { @@ -61,7 +63,6 @@ public static function equal_by_physical(): Generator yield 'json' => [json_schema('a'), ['{"a":1}']]; yield 'enum' => [enum_schema('a', BackedStringEnum::class), [BackedStringEnum::one]]; yield 'xml' => [xml_schema('a'), ['1']]; - yield 'xml element' => [xml_element_schema('a'), ['1']]; } /** @@ -80,10 +81,29 @@ public function test_html_compares_by_physical(): void html_schema('a'), ['

      a

      '], ); - $element = ColumnMother::of(html_element_schema('a'), ['

      a

      ']); + $element = ColumnMother::of(html_element_schema('a'), [ + type_html_element()->cast('

      a

      ')->firstElementChild, + type_html_element()->cast('

      a

      ')->firstElementChild, + ]); static::assertSame($document->physicals(), (new ComparableValues())->equality($document)); - static::assertSame($element->physicals(), (new ComparableValues())->equality($element)); + static::assertSame(['

      a

      ', '

      a

      '], (new ComparableValues())->equality($element)); + } + + public function test_xml_elements_of_different_documents_compare_by_their_markup(): void + { + $first = type_xml_element()->cast('

      a

      ')->firstElementChild; + $second = type_xml_element()->cast('

      a

      ')->firstElementChild; + $elements = ColumnMother::of(xml_element_schema('a', nullable: true), [$first, $second, null]); + $lists = ColumnMother::of(list_schema('a', type_list(type_xml_element())), [[$first], [$second]]); + + static::assertTrue((new ComparableValues())->equalByPhysical($elements->type())); + static::assertEquals($elements->values(), (new ComparableValues())->ordering($elements)); + static::assertSame(['

      a

      ', '

      a

      ', null], (new ComparableValues())->equality($elements)); + static::assertSame( + [['

      a

      '], ['

      a

      ']], + (new ComparableValues())->equalities($lists->type(), $lists->physicals()), + ); } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php new file mode 100644 index 0000000000..46efb1d54f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php @@ -0,0 +1,67 @@ +loadXML('text'); + $position = new ElementPosition(); + $root = type_instance_of(DOMElement::class)->assert($document->documentElement); + $d = type_instance_of(DOMElement::class)->assert($root->lastElementChild?->lastElementChild); + + static::assertSame('', $position->path($root)); + static::assertSame('1/1', $position->path($d)); + static::assertSame($d, $position->element($root, '1/1')); + static::assertSame($root, $position->element($root, '')); + static::assertNull($position->element($root, '2')); + static::assertNull($position->element($root, '0/0')); + } + + public function test_an_element_outside_the_document_tree_has_no_path(): void + { + $document = new DOMDocument(); + $document->loadXML(''); + + static::assertNull((new ElementPosition())->path(type_instance_of(DOMElement::class)->assert($document->createElement( + 'detached', + )))); + } + + public function test_the_physical_splits_into_the_path_the_markup_and_the_document(): void + { + $position = new ElementPosition(); + $physical = $position->physical('0/2', "\0", "\0"); + + static::assertSame("\x010/2\x008\x00\0\0", $physical); + static::assertSame('0/2', $position->pathOf($physical)); + static::assertSame("\0", $position->markupOf($physical)); + static::assertSame("\0", $position->documentOf($physical)); + } + + public function test_the_document_without_the_markup_splits_into_the_path_and_the_document(): void + { + $position = new ElementPosition(); + + static::assertSame('0/2', $position->pathOf("\x000/2\x00")); + static::assertNull($position->markupOf("\x000/2\x00")); + static::assertSame('', $position->documentOf("\x000/2\x00")); + } + + public function test_bare_markup_has_no_position(): void + { + static::assertNull((new ElementPosition())->pathOf('')); + static::assertNull((new ElementPosition())->markupOf('')); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php index 87b36938ad..4b2b36254d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php @@ -18,11 +18,74 @@ final class HtmlElementPhysicalTest extends TestCase public function test_the_markup(): void { $physical = new HtmlElementPhysical(); - $markup = type_string()->assert($physical->toPhysical(type_html_element()->cast('

      a

      '))); + $bytes = type_string()->assert($physical->toPhysical(type_html_element()->cast('

      a

      '))); - static::assertSame('

      a

      ', $markup); - static::assertSame('

      a

      ', $physical->toPhysical($physical->fromPhysical('

      a

      '))); - static::assertNull($physical->fromPhysicalAll(['

      a

      ', null])[1]); + static::assertSame("\x01\x008\x00

      a

      a

      ", $bytes); + static::assertSame('

      a

      ', $physical->markup($bytes)); + static::assertSame('

      a

      ', $physical->markup('

      a

      ')); + static::assertNull($physical->fromPhysicalAll([$bytes, null])[1]); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_a_round_trip_keeps_the_parent_and_the_siblings(): void + { + $physical = new HtmlElementPhysical(); + $section = type_html_element() + ->cast('

      Name

      01
      ') + ->querySelector('section'); + + static::assertNotNull($section); + + $element = type_html_element()->assert($physical->fromPhysical($physical->toPhysical($section))); + + static::assertSame( + '

      Name

      ', + $physical->markup(type_string()->assert($physical->toPhysical($element))), + ); + static::assertSame('ARTICLE', $element->parentElement?->tagName); + static::assertNull($element->parentElement->parentElement); + static::assertSame('01', $element->nextElementSibling?->textContent); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_bare_element_markup_of_earlier_builds_still_loads(): void + { + $element = type_html_element()->assert((new HtmlElementPhysical())->fromPhysical( + '

      Name

      ', + )); + + static::assertSame('Name', $element->firstElementChild?->textContent); + static::assertSame('BODY', $element->parentElement?->tagName); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_the_document_without_the_element_markup_still_loads(): void + { + $physical = new HtmlElementPhysical(); + $bytes = "\x000\x00

      Name

      01
      "; + $element = type_html_element()->assert($physical->fromPhysical($bytes)); + + static::assertSame('SECTION', $element->tagName); + static::assertSame('ARTICLE', $element->parentElement?->tagName); + static::assertSame('

      Name

      ', $physical->markup($bytes)); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_a_detached_element_is_stored_as_its_markup(): void + { + $element = type_html_element()->cast('

      a

      '); + $element->remove(); + + static::assertSame('

      a

      ', (new HtmlElementPhysical())->toPhysical($element)); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_a_path_outside_the_document_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Floe failed to restore HTMLElement'); + + (new HtmlElementPhysical())->fromPhysical("\x015\x000\x00"); } #[RequiresPhp('>= 8.4.0')] diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php index fb23d176c5..d1776337fe 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php @@ -25,21 +25,81 @@ public function test_the_markup(): void $physical = new XmlElementPhysical(); static::assertNotNull($element); - static::assertSame('
      1', $physical->toPhysical($element)); - static::assertEquals($element, $physical->fromPhysical('1')); - static::assertEquals([$element, null], $physical->fromPhysicalAll(['1', null])); + + $bytes = type_string()->assert($physical->toPhysical($element)); + + static::assertSame( + "\x01\x0021\x001\n1\n", + $bytes, + ); + static::assertSame('1', $physical->markup($bytes)); + static::assertEquals($element, $physical->fromPhysical($bytes)); + static::assertEquals([$element, null], $physical->fromPhysicalAll([$bytes, null])); + } + + public function test_a_round_trip_keeps_the_parent_and_the_siblings(): void + { + $document = new DOMDocument(); + $document->loadXML('Name01'); + $physical = new XmlElementPhysical(); + $user = $document->documentElement?->firstElementChild; + + static::assertNotNull($user); + + $element = type_instance_of(DOMElement::class)->assert($physical->fromPhysical($physical->toPhysical($user))); + + static::assertSame('user', $element->tagName); + static::assertSame('Name', $element->textContent); + static::assertSame('root', $element->parentElement?->tagName); + static::assertSame('01', $element->nextElementSibling?->textContent); + } + + public function test_bare_element_markup_of_earlier_builds_still_loads(): void + { + static::assertSame( + 'Name', + type_instance_of(DOMElement::class)->assert((new XmlElementPhysical())->fromPhysical( + 'Name', + ))->textContent, + ); + } + + public function test_the_document_without_the_element_markup_still_loads(): void + { + $physical = new XmlElementPhysical(); + $bytes = "\x000\x00Name01"; + $element = type_instance_of(DOMElement::class)->assert($physical->fromPhysical($bytes)); + + static::assertSame('user', $element->tagName); + static::assertSame('root', $element->parentElement?->tagName); + static::assertSame('Name', $physical->markup($bytes)); + static::assertSame('value', $physical->markup('value')); + } + + public function test_a_path_outside_the_document_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Floe failed to restore DOMElement'); + + (new XmlElementPhysical())->fromPhysical("\x015\x000\x00"); } #[RequiresPhp('>= 8.4.0')] public function test_a_dom_element_of_the_new_api_reads_back_as_a_dom_element(): void { // @mago-ignore analysis:unavailable-method - $element = XMLDocument::createFromString('1')->documentElement; + $element = XMLDocument::createFromString('1')->documentElement?->firstElementChild; $physical = new XmlElementPhysical(); - $markup = type_string()->assert($physical->toPhysical($element)); + $bytes = type_string()->assert($physical->toPhysical($element)); - static::assertSame('1', $markup); - static::assertInstanceOf(DOMElement::class, $physical->fromPhysical($markup)); + static::assertSame( + "\x010\x008\x001\n1", + $bytes, + ); + static::assertSame( + 'root', + type_instance_of(DOMElement::class)->assert($physical->fromPhysical($bytes))->parentElement?->tagName, + ); } public function test_restoring_xml_element_from_string(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php index b4b9ef3ae8..852900d5c0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php @@ -316,7 +316,12 @@ public function test_html_round_trips(): void '

      a

      ', type_string()->assert((new HtmlDocumentPhysical())->toPhysical($document)), ); - static::assertSame('

      a

      ', (new HtmlElementPhysical())->toPhysical($element)); + static::assertSame( + '

      a

      ', + (new HtmlElementPhysical())->markup(type_string()->assert((new HtmlElementPhysical())->toPhysical( + $element, + ))), + ); } public function test_the_null_definition_holds_nulls_only(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php index a144742a98..f74056ea56 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/EqualsTest.php @@ -29,6 +29,7 @@ use function Flow\Types\DSL\type_json; use function Flow\Types\DSL\type_time; use function Flow\Types\DSL\type_uuid; +use function Flow\Types\DSL\type_xml_element; final class EqualsTest extends FlowTestCase { @@ -93,6 +94,18 @@ public static function values_of_one_type(): Generator ]; yield 'date' => [type_date(), new DateTimeImmutable('2024-01-01'), new DateTimeImmutable('2024-01-01'), true]; yield 'time' => [type_time(), new DateInterval('PT60M'), new DateInterval('PT1H'), true]; + yield 'xml elements of different documents' => [ + type_xml_element(), + type_xml_element()->cast('

      a

      ')->firstElementChild, + type_xml_element()->cast('

      a

      ')->firstElementChild, + true, + ]; + yield 'other xml elements' => [ + type_xml_element(), + type_xml_element()->cast('

      a

      ')->firstElementChild, + type_xml_element()->cast('

      b

      ')->firstElementChild, + false, + ]; } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php index b412d97a56..de03f69d32 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/IsInTest.php @@ -30,6 +30,7 @@ use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_time; use function Flow\Types\DSL\type_uuid; +use function Flow\Types\DSL\type_xml_element; final class IsInTest extends FlowTestCase { @@ -156,6 +157,18 @@ public static function values_of_one_type(): Generator ]; yield 'date' => [type_date(), new DateTimeImmutable('2024-01-01'), new DateTimeImmutable('2024-01-01'), true]; yield 'time' => [type_time(), new DateInterval('PT60M'), new DateInterval('PT1H'), true]; + yield 'xml elements of different documents' => [ + type_xml_element(), + type_xml_element()->cast('

      a

      ')->firstElementChild, + type_xml_element()->cast('

      a

      ')->firstElementChild, + true, + ]; + yield 'other xml elements' => [ + type_xml_element(), + type_xml_element()->cast('

      a

      ')->firstElementChild, + type_xml_element()->cast('

      b

      ')->firstElementChild, + false, + ]; } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerComparatorTest.php index 39a37736e7..9e77621b73 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerComparatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Window/PeerComparatorTest.php @@ -16,8 +16,10 @@ use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\xml_element_schema; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_xml_element; use const NAN; @@ -89,4 +91,16 @@ public function test_peers_of_previous_compares_values_without_a_physical_order( ], schema(list_schema('l', type_list(type_integer()))))), ); } + + public function test_xml_elements_of_different_documents_are_peers_by_their_markup(): void + { + static::assertSame( + [false, true, false], + (new PeerComparator([ref('e')]))->peersOfPrevious(array_to_rows([ + ['e' => type_xml_element()->cast('

      a

      ')->firstElementChild], + ['e' => type_xml_element()->cast('

      a

      ')->firstElementChild], + ['e' => type_xml_element()->cast('

      b

      ')->firstElementChild], + ], schema(xml_element_schema('e')))), + ); + } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Fixtures/v2/all-entry-types.floe b/src/core/etl/tests/Flow/Floe/Tests/Fixtures/v2/all-entry-types.floe index 5d3b93fda1d9b39e48d1c0f5c1a8deb5621aae5c..14876f23eac1ec3d21280f14d83341f8228b0af7 100644 GIT binary patch delta 149 zcmcbs+N;Ll=Hu_m#K3xEBgbQA#<0zAm}fIb`7tms{D%TY1|w4jo6M5bT!qXOTP0H^ zyRyWb(o`FLkdU2?eMN4LLRo52ab|v=t&*Xhfs(x)7f$6|n>VrxaLX7O7#i2=DCMS> VB&H;mBq~`|*Vf8%GcbVM0sx72F{uCm delta 101 zcmeBGyQ|9K=Hu_m#K5{@BgbQAM#ar;l{}hL&cgwK__ Date: Thu, 1 Oct 2026 15:13:20 +0200 Subject: [PATCH 12/21] feat(flow-php/flow-php-ext): NativeJsonReader reads JSON into native columns - from_json() / from_json_lines() read natively with flow_php through JsonSourceOpener - strict JSON on the native lane: malformed input refused with file and record - batch assembly shared by the CSV and JSON readers, one-value append shared with NativeColumnBuilder - a scalar JSON record throws RuntimeException instead of TypeError --- .github/workflows/pr-check.yml | 2 +- documentation/components/adapters/json.md | 5 + documentation/upgrading.md | 25 + .../JSON/JSONMachine/JsonExtractor.php | 13 +- .../JSON/JSONMachine/JsonFileReader.php | 17 +- .../JSON/JSONMachine/JsonLinesExtractor.php | 13 +- .../Flow/ETL/Adapter/JSON/JsonOpenSource.php | 28 + .../ETL/Adapter/JSON/JsonSourceOpener.php | 97 ++ .../ETL/Adapter/JSON/NativeJsonOpenSource.php | 73 + .../ETL/Adapter/JSON/PhpJsonOpenSource.php | 34 + .../JSON/Tests/Context/JsonFixtureContext.php | 122 ++ .../JSONMachine/JsonExtractorTest.php | 2 +- .../JSONMachine/JsonFileReaderTest.php | 20 + .../JSONMachine/JsonLinesExtractorTest.php | 2 +- .../Integration/JsonSourceOpenerTest.php | 135 ++ .../Integration/NativeJsonOpenSourceTest.php | 120 ++ .../Integration/NativeJsonRefusalTest.php | 118 ++ .../Integration/PhpJsonOpenSourceTest.php | 49 + .../Tests/Double/ClosingSpySourceStream.php | 20 +- src/extension/flow-php-ext/Cargo.toml | 2 +- .../ETL/Adapter/JSON/NativeJsonReader.php | 55 + .../flow-php-ext/src/batch_columns.rs | 259 ++++ src/extension/flow-php-ext/src/builder.rs | 129 +- src/extension/flow-php-ext/src/csv/columns.rs | 257 +--- src/extension/flow-php-ext/src/ctx.rs | 4 + src/extension/flow-php-ext/src/json/mod.rs | 1 + src/extension/flow-php-ext/src/json/read.rs | 1254 +++++++++++++++++ src/extension/flow-php-ext/src/lib.rs | 17 +- .../tests/phpt/086_json_read_parity.phpt | 221 +++ .../tests/phpt/087_json_read_no_leaks.phpt | 79 ++ .../tests/phpt/088_json_read_streaming.phpt | 80 ++ web/landing/resources/dsl.json | 2 +- 32 files changed, 2938 insertions(+), 317 deletions(-) create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSourceOpener.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJsonOpenSource.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonSourceOpenerTest.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonOpenSourceTest.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonRefusalTest.php create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/PhpJsonOpenSourceTest.php create mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonReader.php create mode 100644 src/extension/flow-php-ext/src/batch_columns.rs create mode 100644 src/extension/flow-php-ext/src/json/read.rs create mode 100644 src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/087_json_read_no_leaks.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/088_json_read_streaming.phpt diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 9042481b39..4f38ee48ac 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -18,7 +18,7 @@ jobs: permissions: pull-requests: write steps: - - uses: codelytv/pr-size-labeler@095a41fca88b8764fd9e008ad269bcdb82bb38b9 # v1 + - uses: codelytv/pr-size-labeler@095a41fca88b8764fd9e008ad269bcdb82bb38b9 # v1.10.4 with: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" xs_label: 'size: XS' diff --git a/documentation/components/adapters/json.md b/documentation/components/adapters/json.md index 95398e16d0..b0d0e93bc4 100644 --- a/documentation/components/adapters/json.md +++ b/documentation/components/adapters/json.md @@ -46,6 +46,11 @@ data_frame() In JSON lines, a line holding only whitespace (space, tab, CR, LF, VT, FF) is skipped, as DuckDB does; this is not configurable. +With the [`flow_php`](/documentation/components/extensions/flow-php-ext.md) extension loaded, JSON lines and a document +holding a top-level array are read natively, as strict JSON: malformed input throws +`RuntimeException('Malformed JSON in "" at line N: …')` (`at element N` in a document). A pointer, or a document +that is not an array, is read by the PHP reader. + ## Loader - JsonLoader ```php diff --git a/documentation/upgrading.md b/documentation/upgrading.md index d3adf19184..56f96156ef 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -1103,6 +1103,31 @@ A `date` column stored that calendar day before, and still does. An element column now stores its whole owner document per value: its size grows with the document. Files written before still read. +### 103) `flow-php/etl-adapter-json` - a scalar JSON record throws `RuntimeException` + +| | Before | After | +|---------------------------------------------------------------------|----------------------------|---------------------------------------| +| `from_json()` over `[1, {"id":1}]` | `TypeError` from `count()` | `Flow\ETL\Exception\RuntimeException` | +| `from_json()` over a JSON-lines file (`{"id":1}`) | `TypeError` from `count()` | `Flow\ETL\Exception\RuntimeException` | +| a pointer at scalars (`withPointer('/items')` over `{"items":[1]}`) | `TypeError` from `count()` | `Flow\ETL\Exception\RuntimeException` | + +The message is `A JSON record must be an object or an array, int given in "".`, the type being the scalar's +`get_debug_type()`. + +### 104) `flow-php/etl-adapter-json` - with `flow_php` loaded, `from_json()` / `from_json_lines()` read strict JSON + +JSON lines and a document holding a top-level array are read by the extension, which refuses what the PHP reader +tolerated, with `Flow\ETL\Exception\RuntimeException`. A pointer, or a document that is not an array, is read as +before. + +| | Before | After | +|------------------------------------------------------------------|----------------------------------------------|----------------------------------------------------------------------| +| `\v`, `\f` or BOM bytes between tokens (`[{"id":1}\v,{"id":2}]`) | read | `Malformed JSON in "" at element 0: …` | +| a BOM at the start of a later line | read | `Malformed JSON in "" at line N: …` | +| content after a line's record (`{"id":1}{"id":9}`) | the first record, the rest ignored | `Malformed JSON in "" at line N: …` | +| content after the closing `]` (`[{"id":1}] x`) | ignored | `Malformed JSON in "" at element N: …` | +| a scalar JSON line (`5`) | `JsonMachine\Exception\SyntaxErrorException` | `A JSON record must be an object or an array, int given in "".` | + --- ## Upgrading from 0.43.x to 0.44.x 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 0e23bdbf34..5e5bf925e6 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 @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; +use Flow\ETL\Adapter\JSON\JsonSourceOpener; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; @@ -19,7 +20,6 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -127,19 +127,14 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $schema = $fileColumns->declare($base); $body = $fileColumns->withoutTail($schema); + $opener = new JsonSourceOpener($this->filesystem, $reader, JsonFormat::Document, $this->pointer); foreach ($sources as $source) { // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body $constants = $fileColumns->forFile($source, $schema); - foreach ($reader->batches($source, $batchSize) as $rawBatch) { - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows($rawBatch) - ->finish(), - $schema, - $backend, - ); + foreach ($opener->batches($source, $body, $batchSize, $backend) as $batch) { + $rows = $constants->fillRows($batch, $schema, $backend); $yielded += $rows->count(); diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php index 42b8ec827e..215ab53f9b 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; +use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Extractor\SourceFile; use Flow\ETL\Schema\Inference\SchemaSampler; use Flow\Filesystem\Filesystem; @@ -14,9 +15,11 @@ use LimitIterator; use function count; +use function get_debug_type; use function is_array; use function iterator_to_array; use function json_decode; +use function sprintf; use function strlen; use function trim; @@ -93,8 +96,8 @@ public function chunks(SourceStream $stream, string $first): Generator /** * A 0-byte stream is no JSON text and yields nothing * - * A member is `mixed`, not an array: a document whose elements are scalars decodes to scalars, which reach - * count() in sample() and raise a TypeError - bug b79. + * A member is `mixed`, not an array: a document whose elements are scalars decodes to scalars, which sample() + * refuses. * * @return Generator */ @@ -168,12 +171,20 @@ public function sample(SourceFile $source, JsonReadBytes $read = new JsonReadByt JsonFormat::Lines => $this->lineItems($stream, $read), }; - /** @var array $row */ + // @mago-ignore analysis:mixed-assignment foreach ($items as $row) { if ($this->pointer !== null && $this->pointerToEntryName) { $row = [$this->pointer => $row]; } + if (!is_array($row)) { + throw new RuntimeException(sprintf( + 'A JSON record must be an object or an array, %s given in "%s".', + get_debug_type($row), + $source->uri(), + )); + } + // {} decodes to []: a record with no fields is skipped - bug b80 if (!count($row)) { continue; 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 96c11dcb86..72804253d5 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 @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; +use Flow\ETL\Adapter\JSON\JsonSourceOpener; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; @@ -19,7 +20,6 @@ use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -127,19 +127,14 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $schema = $fileColumns->declare($base); $body = $fileColumns->withoutTail($schema); + $opener = new JsonSourceOpener($this->filesystem, $reader, JsonFormat::Lines, $this->pointer); foreach ($sources as $source) { // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body $constants = $fileColumns->forFile($source, $schema); - foreach ($reader->batches($source, $batchSize) as $rawBatch) { - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows($rawBatch) - ->finish(), - $schema, - $backend, - ); + foreach ($opener->batches($source, $body, $batchSize, $backend) as $batch) { + $rows = $constants->fillRows($batch, $schema, $backend); $yielded += $rows->count(); diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php new file mode 100644 index 0000000000..c64fe2f83b --- /dev/null +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php @@ -0,0 +1,28 @@ + $batchSize + * + * @throws SchemaMismatchException + * + * @return Generator + */ + public function batches(Schema $schema, int $batchSize, Backend $backend): Generator; +} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSourceOpener.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSourceOpener.php new file mode 100644 index 0000000000..9c8be9750c --- /dev/null +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSourceOpener.php @@ -0,0 +1,97 @@ + $batchSize + * + * @return Generator + */ + public function batches(SourceFile $source, Schema $schema, int $batchSize, Backend $backend): Generator + { + $open = $this->open($source); + + try { + yield from $open->batches($schema, $batchSize, $backend); + } finally { + $open->close(); + } + } + + public function open(SourceFile $source): JsonOpenSource + { + if (!extension_loaded('flow_php') || $this->pointer !== null) { + return new PhpJsonOpenSource($this->reader, $source); + } + + $stream = $this->filesystem->readFrom($source->path); + + try { + $head = ''; + $offset = 0; + + if ($this->format === JsonFormat::Document) { + // the first byte after JSON whitespace and one leading BOM: '[' is native; an object, a scalar or an + // empty file is the PHP lane's (member iteration / JSON Machine's verdict) + $first = ''; + + for (; ($head = $stream->read(NativeJsonOpenSource::CHUNK, $offset)) !== ''; $offset += strlen($head)) { + $bytes = $offset === 0 && str_starts_with($head, "\u{FEFF}") ? substr($head, 3) : $head; + $skip = strspn($bytes, " \t\n\r"); + + if ($skip < strlen($bytes)) { + $first = $bytes[$skip]; + + break; + } + } + + if ($first !== '[') { + $stream->close(); + + return new PhpJsonOpenSource($this->reader, $source); + } + } + + return new NativeJsonOpenSource( + $stream, + new NativeJsonReader($this->format === JsonFormat::Lines, $source->uri()), + $head, + $offset, + ); + } catch (Throwable $e) { + $stream->close(); + + throw $e; + } + } +} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJsonOpenSource.php new file mode 100644 index 0000000000..b7986ec68f --- /dev/null +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJsonOpenSource.php @@ -0,0 +1,73 @@ + $offset + */ + public function __construct( + private SourceStream $stream, + private NativeJsonReader $reader, + private string $head = '', + private int $offset = 0, + ) {} + + public function batches(Schema $schema, int $batchSize, Backend $backend): Generator + { + // every batch goes through the configured backend, which keeps its own columns and copies the native ones + $adopted = static function (Rows $batch) use ($schema, $backend): Rows { + $columns = []; + $native = $batch->columns(); + + foreach ($schema->definitions() as $name => $definition) { + $columns[$name] = $backend->adopt($definition, $native[$name]); + } + + return Rows::fromColumns($schema, $columns, $batch->count()); + }; + + $offset = $this->offset; + $chunk = $this->head === '' ? $this->stream->read(self::CHUNK, $offset) : $this->head; + + while ($chunk !== '') { + $this->reader->feed($chunk); + + while (($batch = $this->reader->nextColumns($schema, $batchSize)) !== null) { + yield $adopted($batch); + } + + $offset += strlen($chunk); + $chunk = $this->stream->read(self::CHUNK, $offset); + } + + $this->reader->finish(); + + while (($batch = $this->reader->nextColumns($schema, $batchSize)) !== null) { + yield $adopted($batch); + } + } + + public function close(): void + { + $this->stream->close(); + } +} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php new file mode 100644 index 0000000000..466f0726dc --- /dev/null +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php @@ -0,0 +1,34 @@ +reader->batches($this->source, $batchSize) as $raw) { + yield (new RowsBuilder($schema, $backend)) + ->appendRows($raw) + ->finish(); + } + } + + /** + * JsonFileReader::batches() opens and closes its own stream. + */ + public function close(): void {} +} diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php index 8aa362e791..419158ec05 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php @@ -7,17 +7,38 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFileReader; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\JSONMachine\JsonLinesExtractor; +use Flow\ETL\Adapter\JSON\JSONMachine\JsonSamples; +use Flow\ETL\Adapter\JSON\JsonOpenSource; +use Flow\ETL\Adapter\JSON\JsonSourceOpener; +use Flow\ETL\Column\Backend; +use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Schema; +use Flow\ETL\Schema\Inference\SchemaInference; +use Flow\ETL\Schema\Inference\SchemaInferrer; use Flow\Filesystem\FileListing; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path\Filter\OnlyFiles; +use Flow\Types\Type\Logical\InstanceOfTypeNarrower; +use Generator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use SplFileInfo; +use function count; use function file_get_contents; use function Flow\ETL\Adapter\JSON\from_json_lines; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; use function Flow\Filesystem\DSL\path_real; +use function in_array; +use function serialize; +use function str_ends_with; +use function str_starts_with; +use function strlen; +use function substr; /** * Resolves the adapter's test fixtures and builds readers over them, so no test needs a private helper. @@ -43,6 +64,48 @@ public static function globReader( return new JsonFileReader($filesystem, $format, $pointer, $pointerToEntryName, $sources); } + /** + * Every *.json and *.jsonl under Fixtures/ outside json-schema/, keyed and valued by its path relative to Fixtures/. + * + * @return Generator + */ + public static function fixtures(): Generator + { + $root = self::path(''); + + /** @var SplFileInfo $file */ + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator( + $root, + RecursiveDirectoryIterator::SKIP_DOTS, + )) as $file) { + $fixture = substr($file->getPathname(), strlen($root)); + + if ( + !str_starts_with($fixture, 'json-schema/') && in_array($file->getExtension(), ['json', 'jsonl'], true) + ) { + yield $fixture => [$fixture]; + } + } + } + + public static function format(string $fixture): JsonFormat + { + return str_ends_with($fixture, '.jsonl') ? JsonFormat::Lines : JsonFormat::Document; + } + + /** + * The schema JsonExtractor / JsonLinesExtractor infer from the fixture. + */ + public static function infer(string $fixture, SchemaInference $inference = new SchemaInference()): Schema + { + $reader = self::reader(self::format($fixture), sources: [self::source($fixture)]); + + return (new SchemaInferrer($inference, new InstanceOfTypeNarrower()))->infer( + [], + new JsonSamples($reader->samples($inference->sampleSize)), + ); + } + /** * @param 'memory'|'native' $filesystem */ @@ -60,6 +123,65 @@ public static function linesExtractor(string $fixture, string $filesystem): Json return from_json_lines(path('memory://' . $fixture), filesystem: $memory); } + /** + * The opener JsonExtractor (Document) or JsonLinesExtractor (Lines) builds, over a reader of the same filesystem. + */ + public static function opener( + JsonFormat $format, + Filesystem $filesystem = new NativeLocalFilesystem(), + ?string $pointer = null, + ): JsonSourceOpener { + return new JsonSourceOpener( + $filesystem, + self::reader($format, $filesystem, pointer: $pointer), + $format, + $pointer, + ); + } + + /** + * The rows of every batch (of the first $batches when given) as one string, or the refusal's class, message, row + * and cause - consumes and closes the source. + * + * @param int<1, max> $batchSize + * @param null|int<1, max> $batches + */ + public static function outcome( + JsonOpenSource $open, + Schema $schema, + int $batchSize, + Backend $backend = new PhpBackend(), + ?int $batches = null, + ): string { + $read = []; + + try { + foreach ($open->batches($schema, $batchSize, $backend) as $batch) { + $read[] = $batch->toArray(); + + if (count($read) === $batches) { + break; + } + } + + return serialize($read); + } catch (SchemaMismatchException $e) { + return ( + $e::class + . ': ' + . $e->getMessage() + . ' @' + . $e->rowIndex + . ' <- ' + . $e->cause::class + . ': ' + . $e->cause->getMessage() + ); + } finally { + $open->close(); + } + } + public static function path(string $fixture): string { return __DIR__ . '/../Fixtures/' . $fixture; 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 16995488c5..56310c060f 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 @@ -701,6 +701,6 @@ public function test_extract_builds_through_the_config_backend(): void false, ); - static::assertGreaterThanOrEqual(1, $backend->builders()); + static::assertGreaterThanOrEqual(1, $backend->builders() + $backend->adopts()); } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php index 3220d7ee11..9867b9f56c 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php @@ -7,6 +7,9 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFileSample; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; +use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -19,6 +22,7 @@ use function array_map; use function array_slice; use function count; +use function Flow\Filesystem\DSL\path; use function Flow\Types\DSL\type_array; use function implode; use function iterator_to_array; @@ -314,6 +318,22 @@ public function test_a_whitespace_only_line_is_skipped_under_a_pointer(): void static::assertSame([1, 2], array_map(static fn(array $v): mixed => $v['a'], $rows)); } + #[TestWith(['[1, {"id":1}]', null])] + #[TestWith(['{"id":1}', null])] + #[TestWith(['{"items":[1]}', '/items'])] + public function test_a_scalar_record_is_refused(string $content, ?string $pointer): void + { + $filesystem = MemoryFiles::with(['memory://scalar.json' => $content]); + $reader = JsonFixtureContext::reader(JsonFormat::Document, $filesystem, pointer: $pointer); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'A JSON record must be an object or an array, int given in "memory://scalar.json".', + ); + + iterator_to_array($reader->sample(new SourceFile(path('memory://scalar.json'))), false); + } + public function test_a_nul_only_line_is_refused(): void { $filesystem = new NativeLocalFilesystem(); 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 c6bdcba131..ae5a32f5b5 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 @@ -753,6 +753,6 @@ public function test_extract_builds_through_the_config_backend(): void false, ); - static::assertGreaterThanOrEqual(1, $backend->builders()); + static::assertGreaterThanOrEqual(1, $backend->builders() + $backend->adopts()); } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonSourceOpenerTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonSourceOpenerTest.php new file mode 100644 index 0000000000..4bf36dcaa1 --- /dev/null +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonSourceOpenerTest.php @@ -0,0 +1,135 @@ +open(JsonFixtureContext::source($fixture)), + ); + } + + #[TestWith([JsonFormat::Document, 'five_rows.json'])] + #[TestWith([JsonFormat::Lines, 'five_rows.jsonl'])] + public function test_batches_closes_the_source_when_the_consumer_stops_early( + JsonFormat $format, + string $fixture, + ): void { + $counting = new CountingFilesystem(new NativeLocalFilesystem()); + $opener = JsonFixtureContext::opener($format, $counting); + + $batches = $opener->batches( + JsonFixtureContext::source($fixture), + schema(int_schema('id')), + 2, + new PhpBackend(), + ); + static::assertCount(2, $batches->current()); + unset($batches); + + static::assertSame(1, $counting->readFromCalls); + static::assertSame(1, $counting->closedStreams()); + } + + #[RequiresPhpExtension('flow_php')] + #[TestWith([JsonFormat::Lines, '{"id":1}'])] + #[TestWith([JsonFormat::Lines, '{}'])] + #[TestWith([JsonFormat::Document, "\u{FEFF} \n\t\r[{\"id\":1}]"])] + #[TestWith([JsonFormat::Document, '[]'])] + public function test_json_lines_and_a_top_level_array_are_read_natively(JsonFormat $format, string $content): void + { + $open = JsonFixtureContext::opener($format, MemoryFiles::with([ + 'memory://a.json' => $content, + ]))->open(new SourceFile(path('memory://a.json'))); + $open->close(); + + static::assertInstanceOf(NativeJsonOpenSource::class, $open); + } + + /** + * @param non-negative-int $spaces + */ + #[RequiresPhpExtension('flow_php')] + #[TestWith(["\u{FEFF} [{\"id\":1},{\"id\":2}]"])] + #[TestWith(['[{"id":1},{"id":2}]'])] + #[TestWith([' [{"id":1},{"id":2}]', 40_000])] + #[TestWith([' [{"id":1},{"id":2}]', 70_000])] + public function test_a_native_document_is_read_once_from_the_peeked_chunk_on(string $content, int $spaces = 0): void + { + $content = str_repeat(' ', $spaces) . $content; + $counting = new CountingFilesystem(MemoryFiles::with(['memory://a.json' => $content])); + + $open = JsonFixtureContext::opener(JsonFormat::Document, $counting)->open(new SourceFile(path( + 'memory://a.json', + ))); + static::assertInstanceOf(NativeJsonOpenSource::class, $open); + + static::assertSame( + serialize([[['id' => 1], ['id' => 2]]]), + JsonFixtureContext::outcome($open, schema(int_schema('id')), 2), + ); + static::assertSame(strlen($content), $counting->openedStreams[0]->readBytes); + } + + #[RequiresPhpExtension('flow_php')] + #[TestWith(['{"items":[{"id":1}]}'])] + #[TestWith([" \n\t"])] + #[TestWith([''])] + #[TestWith(['5'])] + public function test_a_document_not_opening_an_array_is_read_by_the_php_lane(string $content): void + { + $counting = new CountingFilesystem(MemoryFiles::with(['memory://a.json' => $content])); + + $open = JsonFixtureContext::opener(JsonFormat::Document, $counting)->open(new SourceFile(path( + 'memory://a.json', + ))); + + static::assertInstanceOf(PhpJsonOpenSource::class, $open); + static::assertSame($counting->readFromCalls, $counting->closedStreams(), 'the peek closes its stream'); + } + + #[RequiresPhpExtension('flow_php')] + #[TestWith([JsonFormat::Document, 'nested_timezones.json', '/timezones'])] + #[TestWith([JsonFormat::Lines, 'pointer_lines.jsonl', '/items'])] + public function test_a_pointer_is_read_by_the_php_lane(JsonFormat $format, string $fixture, string $pointer): void + { + $counting = new CountingFilesystem(new NativeLocalFilesystem()); + + $open = JsonFixtureContext::opener($format, $counting, $pointer)->open(JsonFixtureContext::source($fixture)); + + static::assertInstanceOf(PhpJsonOpenSource::class, $open); + static::assertSame(0, $counting->readFromCalls); + } +} diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonOpenSourceTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonOpenSourceTest.php new file mode 100644 index 0000000000..25c7fe419b --- /dev/null +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonOpenSourceTest.php @@ -0,0 +1,120 @@ + + */ + public static function fixtures(): Generator + { + foreach (JsonFixtureContext::fixtures() as $label => [$fixture]) { + if (!in_array($fixture, ['two_objects_on_a_line.jsonl', 'nul_line.jsonl', 'scalar_line.jsonl'], true)) { + yield $label => [$fixture]; + } + } + } + + #[DataProvider('fixtures')] + public function test_both_lanes_read_a_fixture_identically(string $fixture): void + { + // the orders fixtures (1 000 and 10 000 records) are sampled and read over their first 500 records only + $orders = str_starts_with($fixture, 'orders_'); + $format = JsonFixtureContext::format($fixture); + $schema = $orders + ? JsonFixtureContext::infer($fixture, infer_schema()->sampleSize(500)->build()) + : JsonFixtureContext::infer($fixture); + $source = JsonFixtureContext::source($fixture); + $batchSize = $orders ? 100 : 2; + $batches = $orders ? 5 : null; + + static::assertSame( + JsonFixtureContext::outcome( + new PhpJsonOpenSource(JsonFixtureContext::reader($format), $source), + $schema, + $batchSize, + batches: $batches, + ), + JsonFixtureContext::outcome( + JsonFixtureContext::opener($format)->open($source), + $schema, + $batchSize, + batches: $batches, + ), + ); + } + + public function test_a_value_past_the_sample_is_refused_as_the_php_lane_refuses_it(): void + { + $schema = JsonFixtureContext::infer('misfit.json', infer_schema()->sampleSize(3)->build()); + $source = JsonFixtureContext::source('misfit.json'); + + $native = JsonFixtureContext::outcome( + JsonFixtureContext::opener(JsonFormat::Document)->open($source), + $schema, + 2, + ); + + static::assertStringStartsWith(SchemaMismatchException::class . ':', $native); + static::assertSame( + JsonFixtureContext::outcome(new PhpJsonOpenSource(JsonFixtureContext::reader(), $source), $schema, 2), + $native, + ); + } + + public function test_under_the_php_backend_no_native_column_survives(): void + { + $open = JsonFixtureContext::opener(JsonFormat::Lines)->open(JsonFixtureContext::source('parity_people.jsonl')); + + try { + foreach ($open->batches(JsonFixtureContext::infer('parity_people.jsonl'), 2, new PhpBackend()) as $batch) { + foreach ($batch->columns() as $column) { + static::assertNotSame('Flow\ETL\Column\NativeColumn', $column::class); + } + } + } finally { + $open->close(); + } + } + + public function test_an_early_stop_closes_the_stream(): void + { + $counting = new CountingFilesystem(new NativeLocalFilesystem()); + + $batches = JsonFixtureContext::opener(JsonFormat::Document, $counting)->batches( + JsonFixtureContext::source('five_rows.json'), + schema(int_schema('id')), + 2, + new PhpBackend(), + ); + static::assertSame([['id' => 1], ['id' => 2]], $batches->current()->toArray()); + unset($batches); + + static::assertSame(1, $counting->readFromCalls); + static::assertSame(1, $counting->closedStreams()); + } +} diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonRefusalTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonRefusalTest.php new file mode 100644 index 0000000000..40f0bf7d11 --- /dev/null +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonRefusalTest.php @@ -0,0 +1,118 @@ + + */ + public static function malformed(): Generator + { + $deep = str_repeat('[', 512) . str_repeat(']', 512); + + yield 'two records on a line' => [JsonFormat::Lines, '{"id":1}{"id":9}', 'at line 1: ']; + yield 'a NUL line' => [JsonFormat::Lines, "{\"id\":1}\n\0\n", 'at line 2: ']; + yield 'a BOM on the second line' => [JsonFormat::Lines, "{\"id\":1}\n\u{FEFF}{\"id\":2}\n", 'at line 2: ']; + yield 'a vertical tab between tokens' => [JsonFormat::Document, "[{\"id\":1}\v,{\"id\":2}]", 'at element 0: ']; + yield 'a trailing comma' => [JsonFormat::Document, '[{"id":1},]', 'at element 1: ']; + yield 'a missing comma' => [JsonFormat::Document, '[{"id":1} {"id":2}]', 'at element 0: ']; + yield 'content after the array' => [JsonFormat::Document, '[{"id":1}] x', 'at element 1: ']; + yield 'a truncated document' => [JsonFormat::Document, '[{"id":1}', 'at element 0: ']; + yield 'invalid UTF-8 in a skipped member of an element' => [ + JsonFormat::Document, + "[{\"id\":1,\"skipped\":\"\xFF\"}]", + 'at element 0: ', + ]; + yield 'invalid UTF-8 in a skipped member of a line' => [ + JsonFormat::Lines, + "{\"id\":1,\"skipped\":\"\xFF\"}", + 'at line 1: ', + ]; + yield 'a lone surrogate escape in a skipped member of an element' => [ + JsonFormat::Document, + '[{"id":1,"skipped":"\\ud800"}]', + 'at element 0: Single unpaired UTF-16 surrogate in unicode escape', + ]; + yield 'a high surrogate escape without its low one in a line' => [ + JsonFormat::Lines, + '{"id":1,"skipped":"\\ud83d\\u0041"}', + 'at line 1: Single unpaired UTF-16 surrogate in unicode escape', + ]; + yield 'a raw control character in a string' => [JsonFormat::Lines, "{\"id\":\"\x01\"}", 'at line 1: ']; + yield 'a leading zero' => [JsonFormat::Lines, '{"id":01}', 'at line 1: ']; + yield 'NaN' => [JsonFormat::Lines, '{"id":NaN}', 'at line 1: ']; + yield 'True' => [JsonFormat::Lines, '{"id":True}', 'at line 1: ']; + yield 'an element nested as deep as json_decode refuses' => [ + JsonFormat::Document, + '[{"id":' . $deep . '}]', + 'at element 0: ', + ]; + yield 'a line nested as deep as json_decode refuses' => [ + JsonFormat::Lines, + '{"id":' . $deep . '}', + 'at line 1: ', + ]; + } + + #[DataProvider('malformed')] + public function test_malformed_json_is_refused_naming_the_file_and_the_record( + JsonFormat $format, + string $content, + string $record, + ): void { + $open = JsonFixtureContext::opener($format, MemoryFiles::with([ + 'memory://a.json' => $content, + ]))->open(new SourceFile(path('memory://a.json'))); + static::assertInstanceOf(NativeJsonOpenSource::class, $open); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessageMatches( + '/^' . preg_quote('Malformed JSON in "memory://a.json" ' . $record, '/') . '/', + ); + + try { + iterator_to_array($open->batches(schema(int_schema('id', nullable: true)), 2, new PhpBackend()), false); + } finally { + $open->close(); + } + } + + public function test_a_scalar_line_is_refused_as_a_scalar_record(): void + { + $open = JsonFixtureContext::opener(JsonFormat::Lines, MemoryFiles::with([ + 'memory://a.jsonl' => "{\"id\":1}\n5\n", + ]))->open(new SourceFile(path('memory://a.jsonl'))); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('A JSON record must be an object or an array, int given in "memory://a.jsonl".'); + + try { + iterator_to_array($open->batches(schema(int_schema('id')), 2, new PhpBackend()), false); + } finally { + $open->close(); + } + } +} diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/PhpJsonOpenSourceTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/PhpJsonOpenSourceTest.php new file mode 100644 index 0000000000..dadf9573a6 --- /dev/null +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/PhpJsonOpenSourceTest.php @@ -0,0 +1,49 @@ +batches(schema(int_schema('id')), 2, new PhpBackend()), false); + + static::assertSame([2, 2, 1], array_map(static fn(Rows $rows): int => $rows->count(), $batches)); + static::assertSame([['id' => 5]], $batches[2]->toArray()); + } + + public function test_a_refusal_carries_the_row_of_its_batch(): void + { + $open = new PhpJsonOpenSource( + JsonFixtureContext::reader(JsonFormat::Document), + JsonFixtureContext::source('misfit.json'), + ); + $batches = $open->batches(schema(int_schema('id')), 2, new PhpBackend()); + + static::assertSame([['id' => 1], ['id' => 2]], $batches->current()->toArray()); + + try { + $batches->next(); + static::fail('the second batch holds "n/a"'); + } catch (SchemaMismatchException $e) { + static::assertSame(1, $e->rowIndex); + } + } +} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Double/ClosingSpySourceStream.php b/src/core/etl/tests/Flow/Floe/Tests/Double/ClosingSpySourceStream.php index e2a1044f6b..db71014ec4 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Double/ClosingSpySourceStream.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Double/ClosingSpySourceStream.php @@ -8,10 +8,14 @@ use Flow\Filesystem\SourceStream; use Generator; +use function strlen; + final class ClosingSpySourceStream implements SourceStream { public int $closeCount = 0; + public int $readBytes = 0; + public function __construct( private readonly SourceStream $stream, ) {} @@ -24,7 +28,10 @@ public function close(): void public function content(): string { - return $this->stream->content(); + $content = $this->stream->content(); + $this->readBytes += strlen($content); + + return $content; } public function isOpen(): bool @@ -34,7 +41,11 @@ public function isOpen(): bool public function iterate(int $length = 1): Generator { - return $this->stream->iterate($length); + foreach ($this->stream->iterate($length) as $chunk) { + $this->readBytes += strlen($chunk); + + yield $chunk; + } } public function path(): Path @@ -44,7 +55,10 @@ public function path(): Path public function read(int $length, int $offset): string { - return $this->stream->read($length, $offset); + $bytes = $this->stream->read($length, $offset); + $this->readBytes += strlen($bytes); + + return $bytes; } public function readLines(string $separator = "\n", ?int $length = null): Generator diff --git a/src/extension/flow-php-ext/Cargo.toml b/src/extension/flow-php-ext/Cargo.toml index ff9f05970f..eed0c15e5a 100644 --- a/src/extension/flow-php-ext/Cargo.toml +++ b/src/extension/flow-php-ext/Cargo.toml @@ -18,7 +18,7 @@ flow-batch-frame = { path = "crates/flow-batch-frame" } memchr = "2" parquet = { version = "59", default-features = false, features = ["arrow", "arrow_canonical_extension_types", "snap", "flate2", "flate2-zlib-rs", "zstd", "lz4", "brotli", "simdutf8"] } serde = { version = "1", features = ["derive"] } -serde_json = { version = "1", features = ["raw_value"] } +serde_json = { version = "1", features = ["raw_value", "unbounded_depth"] } [build-dependencies] ext-php-rs-build = "0.1" diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonReader.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonReader.php new file mode 100644 index 0000000000..b59f220380 --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonReader.php @@ -0,0 +1,55 @@ + $batchSize + * + * @throws SchemaMismatchException a cast or schema refusal, as RowsBuilder::appendRows() throws it + * @throws FlowRuntimeException malformed JSON, or a scalar record + */ + public function nextColumns(Schema $schema, int $batchSize): ?Rows + { + throw new RuntimeException('flow_php extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/src/batch_columns.rs b/src/extension/flow-php-ext/src/batch_columns.rs new file mode 100644 index 0000000000..bae7bc3a75 --- /dev/null +++ b/src/extension/flow-php-ext/src/batch_columns.rs @@ -0,0 +1,259 @@ +//! A batch of native columns, one builder per schema definition, with `RowsBuilder::appendRows()`'s refusals: each +//! column keeps its first, the lowest refused row wins (then the earliest definition), and a NOT NULL column a row +//! lacks is refused only when nothing else was. The readers differ only in where a cell comes from. + +use std::rc::Rc; + +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::{ZendHashTable, Zval}; +use flow_batch_frame::kind::Kind; + +use crate::builder::{definition_nullable, schema_mismatch}; +use crate::cast::{bool_from_str, float_from_str, integer_from_str, json_gate, parse_iso_date, parse_iso_datetime, CastKind}; +use crate::column::NativeColumn; +use crate::ctx::{self, call_method, call_static, ht_for_each, ht_insert, ht_insert_long, zval_long}; +use crate::date_check::iso_instant_micros; +use crate::exception::ext_exception; +use crate::json_check::json_valid; +use crate::kind_builder::KindBuilder; +use crate::physical::overflow; +use crate::plan::{type_plan, TypePlan}; +use crate::render::invalid_argument; +use crate::uuid_check::is_uuid; +use crate::values::{datetime_days, datetime_micros, uuid_bytes}; + +/// A `Schema::definitions()` key: an int for a numeric name, as PHP keys it. +pub enum Key { + Index(i64), + Name(Vec), +} + +impl Key { + pub fn name(&self) -> Vec { + match self { + Key::Index(index) => index.to_string().into_bytes(), + Key::Name(name) => name.clone(), + } + } +} + +pub struct BatchColumn { + pub key: Key, + pub definition: Zval, + pub nullable: bool, + pub plan: Rc, + pub values: KindBuilder, + /// The first refused row and its `ColumnMismatchException`. + pub refusal: Option<(usize, Zval)>, + /// The first row lacking this NOT NULL column. + pub absent: Option, +} + +/// The batch being built, and the schema and batch size it is built for. +pub struct BatchColumns { + schema: Zval, + schema_json: Vec, + pub batch_size: usize, + pub columns: Vec, + pub rows: usize, +} + +/// A PHP `$batchSize` as a row count: refused unless greater than 0. +pub fn batch_size_of(batch_size: i64, what: &str) -> Result { + usize::try_from(batch_size) + .ok() + .filter(|size| *size > 0) + .ok_or_else(|| ext_exception(format!("flow_php {what} batch size must be greater than 0"))) +} + +fn schema_json(schema: &Zval) -> Result, PhpException> { + let normalized = call_method(schema, "normalize", &mut [])?; + let json = ctx::call_handle(ctx::json_encode()?, None, &mut [normalized], "encode a schema as JSON")?; + + Ok(json + .zend_str() + .ok_or_else(|| ext_exception("flow_php expected schema JSON to be a string"))? + .as_bytes() + .to_vec()) +} + +impl BatchColumns { + fn new(schema: &Zval, schema_json: Vec, batch_size: usize) -> Result { + let definitions = call_method(schema, "definitions", &mut [])?; + let definitions = definitions + .array() + .ok_or_else(|| ext_exception("flow_php expected Schema::definitions() to return an array"))?; + let mut columns = Vec::with_capacity(definitions.len()); + + ht_for_each(definitions, |name, index, definition| { + let plan = type_plan(&call_method(definition, "type", &mut [])?)?; + + columns.push(BatchColumn { + key: match name { + Some(name) => Key::Name(name.as_bytes().to_vec()), + None => Key::Index(index as i64), + }, + definition: definition.shallow_clone(), + nullable: definition_nullable(definition)?, + values: KindBuilder::new(&plan.kind), + plan, + refusal: None, + absent: None, + }); + + Ok(()) + })?; + + Ok(Self { + schema: schema.shallow_clone(), + schema_json, + batch_size, + columns, + rows: 0, + }) + } + + /// The state for `schema` and `batch_size`: the same object or the same `normalize()` JSON keeps it (`false`), any + /// other schema rebuilds it (`true`); changing the schema or the batch size of a batch with rows pending throws. + pub fn prepare<'a>( + pending: &'a mut Option, + schema: &Zval, + batch_size: usize, + what: &str, + ) -> Result<(&'a mut Self, bool), PhpException> { + let same_object = pending.as_ref().is_some_and(|state| { + state.schema.object().map(|object| object.handle) == schema.object().map(|object| object.handle) + }); + let mut rebuilt = false; + + if !same_object { + let json = schema_json(schema)?; + + match pending { + Some(state) if state.schema_json == json => state.schema = schema.shallow_clone(), + Some(state) if state.rows > 0 => { + return Err(ext_exception(format!("flow_php cannot change the schema of a pending {what} batch"))); + } + _ => { + *pending = Some(Self::new(schema, json, batch_size)?); + rebuilt = true; + } + } + } + + let state = pending.as_mut().expect("built above"); + + if state.batch_size != batch_size { + if state.rows > 0 { + return Err(ext_exception(format!("flow_php cannot change the batch size of a pending {what} batch"))); + } + + state.batch_size = batch_size; + } + + Ok((state, rebuilt)) + } + + pub fn reset(&mut self) { + self.rows = 0; + + for column in &mut self.columns { + column.values = KindBuilder::new(&column.plan.kind); + column.refusal = None; + column.absent = None; + } + } + + /// The batch as `Rows::fromColumns()`, or its refusal: the lowest refused row (ties: the earliest definition), + /// else the lowest absent row (ties: the earliest definition) as `missingColumn`. The state is reset either way. + pub fn finish(&mut self) -> Result { + let batch = self.build(); + self.reset(); + + batch + } + + fn build(&self) -> Result { + // min_by_key() keeps the first of equal rows: the earliest definition + if let Some((row, cause)) = self + .columns + .iter() + .filter_map(|column| column.refusal.as_ref()) + .min_by_key(|(row, _)| *row) + { + return Err(schema_mismatch(zval_long(*row as i64), cause.shallow_clone())); + } + + if let Some((row, column)) = self + .columns + .iter() + .filter_map(|column| Some((column.absent?, column))) + .min_by_key(|(row, _)| *row) + { + let cause = call_static( + "Flow\\ETL\\Exception\\ColumnMismatchException", + "missingColumn", + &mut [column.definition.shallow_clone()], + )?; + + return Err(schema_mismatch(zval_long(row as i64), cause)); + } + + let mut columns = ZendHashTable::with_capacity(self.columns.len() as u32); + + for column in &self.columns { + let data = column + .values + .finish(&column.plan.kind) + .map_err(|e| invalid_argument(format!("flow_php built an invalid column: {e}")))?; + let mut native = Zval::new(); + ext_php_rs::convert::IntoZval::set_zval( + NativeColumn::new(arrow_array::make_array(data), Rc::clone(&column.plan)), + &mut native, + false, + )?; + + match &column.key { + Key::Index(index) => ht_insert_long(&mut columns, *index, native), + Key::Name(name) => ht_insert(&mut columns, name, native), + } + } + + let mut columns_zv = Zval::new(); + columns_zv.set_hashtable(columns); + + call_static( + "Flow\\ETL\\Rows", + "fromColumns", + &mut [self.schema.shallow_clone(), columns_zv, zval_long(self.rows as i64)], + ) + } +} + +/// A text value `cast.rs` casts natively, appended in its physical form; `false` hands it to the PHP lane. +pub fn native_text(values: &mut KindBuilder, kind: &Kind, cast: &CastKind, bytes: &[u8]) -> Result { + match (kind, cast) { + (Kind::Int64, CastKind::Integer) => Ok(integer_from_str(bytes).map(|value| values.append_fixed(&value.to_le_bytes())).is_some()), + (Kind::Float64, CastKind::Float) => Ok(float_from_str(bytes).map(|value| values.append_fixed(&value.to_le_bytes())).is_some()), + (Kind::Boolean, CastKind::Boolean) => Ok(bool_from_str(bytes).map(|value| values.append_bool(value)).is_some()), + (Kind::Bytes, CastKind::String) => values.append_bytes(bytes).map(|()| true).map_err(overflow), + (Kind::Bytes, CastKind::NonEmptyString) if !bytes.is_empty() => values.append_bytes(bytes).map(|()| true).map_err(overflow), + (Kind::Bytes, CastKind::Json) if json_gate(bytes) && json_valid(bytes) => { + values.append_bytes(bytes).map(|()| true).map_err(overflow) + } + (Kind::Uuid, CastKind::Uuid) if is_uuid(bytes) => { + Ok(uuid_bytes(bytes).map(|uuid| values.append_fixed(&uuid)).is_some()) + } + (Kind::Timestamp, CastKind::DateTime(zone)) => Ok(match iso_instant_micros(bytes) { + Some(micros) => Some(micros), + None => parse_iso_datetime(bytes, zone)?.and_then(|(_, instant)| instant.object().and_then(datetime_micros)), + } + .map(|micros| values.append_fixed(µs.to_le_bytes())) + .is_some()), + (Kind::Int32, CastKind::Date) => Ok(parse_iso_date(bytes)? + .and_then(|instant| instant.object().and_then(datetime_days)) + .map(|days| values.append_fixed(&(days as i32).to_le_bytes())) + .is_some()), + _ => Ok(false), + } +} diff --git a/src/extension/flow-php-ext/src/builder.rs b/src/extension/flow-php-ext/src/builder.rs index 75af58ace2..3711f98ede 100644 --- a/src/extension/flow-php-ext/src/builder.rs +++ b/src/extension/flow-php-ext/src/builder.rs @@ -54,6 +54,14 @@ pub enum Refusal { Physical(ZBox), } +/// What `append_one()` did with a value. +pub enum Append { + Done, + /// `cause` is the `ColumnMismatchException` a positioned append wraps; `raised` the `Flow\Types` exception an + /// unpositioned append rethrows (`None` for a NOT NULL null). + Refused { cause: Zval, raised: Option> }, +} + fn string_slot(object: &ZendObject, slot: u32) -> Option { let value = read_slot(object, slot); @@ -65,7 +73,7 @@ pub fn native_lane(plan: &TypePlan, value: &Zval) -> Result, PhpE native_leaf(&plan.kind, &plan.cast, value) } -fn native_leaf(kind: &Kind, cast_kind: &CastKind, value: &Zval) -> Result, PhpException> { +pub(crate) fn native_leaf(kind: &Kind, cast_kind: &CastKind, value: &Zval) -> Result, PhpException> { if let (Kind::Timestamp, CastKind::DateTime(_)) = (kind, cast_kind) { if let Some(micros) = value.zend_str().and_then(|string| iso_instant_micros(string.as_bytes())) { return Ok(Some(Native::Fixed(micros.to_le_bytes()))); @@ -227,6 +235,72 @@ fn append_cast(builder: &mut KindBuilder, kind: &Kind, cast_kind: &CastKind, val } } +/// One value, as `NativeColumnBuilder::appendMany()` appends it: a null is refused under NOT NULL; a nested value +/// takes `append_cast()`, a leaf the native lane, and what neither casts the PHP lane. Exceptions other than +/// `Flow\Types` ones escape as thrown. +pub fn append_one( + values: &mut KindBuilder, + plan: &TypePlan, + definition: &Zval, + nullable: bool, + value: &Zval, +) -> Result { + let value = value.dereference(); + + if value.is_null() { + if !nullable { + return Ok(Append::Refused { + cause: value_does_not_match(definition, null_zval(), None)?, + raised: None, + }); + } + + values.append_null(); + + return Ok(Append::Done); + } + + if nested(&plan.kind) { + let row = values.len(); + + if append_cast(values, &plan.kind, &plan.cast, value)? { + return Ok(Append::Done); + } + + values.truncate(row); + } else if let Some(native) = native_lane(plan, value)? { + append_native(values, native)?; + + return Ok(Append::Done); + } + + match php_lane(plan, value) { + Ok(physical) => { + append_physical(values, &plan.kind, &physical)?; + + Ok(Append::Done) + } + Err(Refusal::Cast(mut exception) | Refusal::Physical(mut exception)) if !is_types_exception(&exception)? => { + Err(transparent_exception(&mut exception)) + } + // the cast's own reason is dropped, as CastingColumnBuilder::appendMany drops it + Err(Refusal::Cast(exception)) => Ok(Append::Refused { + cause: value_does_not_match(definition, value.shallow_clone(), None)?, + raised: Some(exception), + }), + Err(Refusal::Physical(mut exception)) => { + let mut reason = Zval::new(); + reason.set_object(&mut exception); + + // the value cast, so only the physical form's reason (a range) tells the user why it was refused + Ok(Append::Refused { + cause: value_does_not_match(definition, value.shallow_clone(), Some(reason))?, + raised: Some(exception), + }) + } + } +} + /// `$type->cast($value)`, then `$physical->toPhysical($cast)` unless the physical is the identity. pub fn php_lane(plan: &TypePlan, value: &Zval) -> Result { let type_obj = plan.type_zv.object().expect("a plan's type is an object"); @@ -241,7 +315,7 @@ pub fn php_lane(plan: &TypePlan, value: &Zval) -> Result { call_handle_catching(plan.to_physical, Some(physical), &mut [cast]).map_err(Refusal::Physical) } -fn append_native(builder: &mut KindBuilder, native: Native) -> Result<(), PhpException> { +pub(crate) fn append_native(builder: &mut KindBuilder, native: Native) -> Result<(), PhpException> { match native { Native::Fixed(bytes) => builder.append_fixed(&bytes), Native::Days(days) => builder.append_fixed(&days.to_le_bytes()), @@ -341,50 +415,13 @@ impl NativeColumnBuilder { /// One value cast and appended. With a `position`, refusals are `appendMany()`'s `SchemaMismatchException` at it; /// without, they escape as PHP threw them, as `append()` lets them. fn append_value(&mut self, value: &Zval, position: Option<&dyn Fn() -> Zval>) -> Result<(), PhpException> { - let value = value.dereference(); - let refuse = |cause: Zval| match position { - Some(position) => schema_mismatch(position(), cause), - None => throw(cause), - }; - - if value.is_null() { - if !self.nullable { - return Err(refuse(value_does_not_match(&self.definition, null_zval(), None)?)); - } - - self.values.append_null(); - - return Ok(()); - } - - if nested(&self.plan.kind) { - let row = self.values.len(); - - if append_cast(&mut self.values, &self.plan.kind, &self.plan.cast, value)? { - return Ok(()); - } - - self.values.truncate(row); - } else if let Some(native) = native_lane(&self.plan, value)? { - return append_native(&mut self.values, native); - } - - match php_lane(&self.plan, value) { - Ok(physical) => append_physical(&mut self.values, &self.plan.kind, &physical), - Err(Refusal::Cast(mut exception) | Refusal::Physical(mut exception)) - if position.is_none() || !is_types_exception(&exception)? => - { - Err(transparent_exception(&mut exception)) - } - // the cast's own reason is dropped, as CastingColumnBuilder::appendMany drops it - Err(Refusal::Cast(_)) => Err(refuse(value_does_not_match(&self.definition, value.shallow_clone(), None)?)), - Err(Refusal::Physical(mut exception)) => { - let mut reason = Zval::new(); - reason.set_object(&mut exception); - - // the value cast, so only the physical form's reason (a range) tells the user why it was refused - Err(refuse(value_does_not_match(&self.definition, value.shallow_clone(), Some(reason))?)) - } + match append_one(&mut self.values, &self.plan, &self.definition, self.nullable, value)? { + Append::Done => Ok(()), + Append::Refused { cause, raised } => Err(match (position, raised) { + (Some(position), _) => schema_mismatch(position(), cause), + (None, Some(mut raised)) => transparent_exception(&mut raised), + (None, None) => throw(cause), + }), } } diff --git a/src/extension/flow-php-ext/src/csv/columns.rs b/src/extension/flow-php-ext/src/csv/columns.rs index 102dc4dab7..bd7bf41391 100644 --- a/src/extension/flow-php-ext/src/csv/columns.rs +++ b/src/extension/flow-php-ext/src/csv/columns.rs @@ -1,158 +1,26 @@ -//! `RustCSVReaderNative::nextColumns()`: CSV cells straight into native columns, one builder per schema definition, -//! with `RowsBuilder::appendRows()`'s refusals - each column keeps its first, the lowest row wins (then the earliest -//! definition), and a NOT NULL column absent from the header is refused only when nothing else was. - -use std::rc::Rc; +//! `RustCSVReaderNative::nextColumns()`: CSV cells straight into native columns through `BatchColumns`; a NOT NULL +//! column absent from the header is absent from every row. use ext_php_rs::exception::PhpException; -use ext_php_rs::types::{ZendHashTable, Zval}; -use flow_batch_frame::kind::Kind; +use ext_php_rs::types::Zval; -use crate::builder::{ - definition_nullable, is_types_exception, php_lane, schema_mismatch, value_does_not_match, Refusal, -}; -use crate::cast::{bool_from_str, float_from_str, integer_from_str, json_gate, parse_iso_date, parse_iso_datetime, CastKind}; -use crate::column::NativeColumn; +use crate::batch_columns::{native_text, BatchColumn, BatchColumns}; +use crate::builder::{is_types_exception, php_lane, value_does_not_match, Refusal}; use crate::csv::CsvReader; -use crate::ctx::{ - self, call_method, call_static, ht_for_each, ht_insert, ht_insert_long, null_zval, transparent_exception, zval_long, - zval_str, -}; -use crate::date_check::iso_instant_micros; -use crate::exception::ext_exception; -use crate::json_check::json_valid; -use crate::kind_builder::KindBuilder; -use crate::physical::{append_physical, overflow}; -use crate::plan::{type_plan, TypePlan}; -use crate::render::invalid_argument; -use crate::uuid_check::is_uuid; -use crate::values::{datetime_days, datetime_micros, uuid_bytes}; - -/// A `Schema::definitions()` key: an int for a numeric name, as PHP keys it. -enum Key { - Index(i64), - Name(Vec), -} - -impl Key { - fn name(&self) -> Vec { - match self { - Key::Index(index) => index.to_string().into_bytes(), - Key::Name(name) => name.clone(), - } - } -} +use crate::ctx::{null_zval, transparent_exception, zval_str}; +use crate::physical::append_physical; -struct Column { - key: Key, - definition: Zval, - nullable: bool, - plan: Rc, - /// `None`: the header has no column of this name. - field: Option, - values: KindBuilder, - /// The first refused row and its `ColumnMismatchException`. - refusal: Option<(usize, Zval)>, -} - -/// The batch being built, and the schema and batch size it is built for. +/// The batch being built, and the field of the header each of its columns reads. +#[derive(Default)] pub struct CsvColumns { - schema: Zval, - schema_json: Vec, - batch_size: usize, - columns: Vec, - rows: usize, -} - -fn schema_json(schema: &Zval) -> Result, PhpException> { - let normalized = call_method(schema, "normalize", &mut [])?; - let json = crate::ctx::call_handle(ctx::json_encode()?, None, &mut [normalized], "encode a schema as JSON")?; - - Ok(json - .zend_str() - .ok_or_else(|| ext_exception("flow_php expected schema JSON to be a string"))? - .as_bytes() - .to_vec()) -} - -impl CsvColumns { - fn new(reader: &mut CsvReader, schema: &Zval, schema_json: Vec, batch_size: usize) -> Result { - let definitions = call_method(schema, "definitions", &mut [])?; - let definitions = definitions - .array() - .ok_or_else(|| ext_exception("flow_php expected Schema::definitions() to return an array"))?; - let mut columns = Vec::with_capacity(definitions.len()); - - ht_for_each(definitions, |name, index, definition| { - let key = match name { - Some(name) => Key::Name(name.as_bytes().to_vec()), - None => Key::Index(index as i64), - }; - let plan = type_plan(&call_method(definition, "type", &mut [])?)?; - - columns.push(Column { - field: reader.field_of(&key.name()), - key, - definition: definition.shallow_clone(), - nullable: definition_nullable(definition)?, - values: KindBuilder::new(&plan.kind), - plan, - refusal: None, - }); - - Ok(()) - })?; - - Ok(Self { - schema: schema.shallow_clone(), - schema_json, - batch_size, - columns, - rows: 0, - }) - } - - fn reset(&mut self) { - self.rows = 0; - - for column in &mut self.columns { - column.values = KindBuilder::new(&column.plan.kind); - column.refusal = None; - } - } -} - -/// A cell `cast.rs` casts natively, appended in its physical form; `false` hands it to the PHP lane. -fn native_cell(values: &mut KindBuilder, plan: &TypePlan, bytes: &[u8]) -> Result { - match (&plan.kind, &plan.cast) { - (Kind::Int64, CastKind::Integer) => Ok(integer_from_str(bytes).map(|value| values.append_fixed(&value.to_le_bytes())).is_some()), - (Kind::Float64, CastKind::Float) => Ok(float_from_str(bytes).map(|value| values.append_fixed(&value.to_le_bytes())).is_some()), - (Kind::Boolean, CastKind::Boolean) => Ok(bool_from_str(bytes).map(|value| values.append_bool(value)).is_some()), - (Kind::Bytes, CastKind::String) => values.append_bytes(bytes).map(|()| true).map_err(overflow), - (Kind::Bytes, CastKind::NonEmptyString) if !bytes.is_empty() => values.append_bytes(bytes).map(|()| true).map_err(overflow), - (Kind::Bytes, CastKind::Json) if json_gate(bytes) && json_valid(bytes) => { - values.append_bytes(bytes).map(|()| true).map_err(overflow) - } - (Kind::Uuid, CastKind::Uuid) if is_uuid(bytes) => { - Ok(uuid_bytes(bytes).map(|uuid| values.append_fixed(&uuid)).is_some()) - } - (Kind::Timestamp, CastKind::DateTime(zone)) => Ok(match iso_instant_micros(bytes) { - Some(micros) => Some(micros), - None => parse_iso_datetime(bytes, zone)?.and_then(|(_, instant)| instant.object().and_then(datetime_micros)), - } - .map(|micros| values.append_fixed(µs.to_le_bytes())) - .is_some()), - (Kind::Int32, CastKind::Date) => Ok(parse_iso_date(bytes)? - .and_then(|instant| instant.object().and_then(datetime_days)) - .map(|days| values.append_fixed(&(days as i32).to_le_bytes())) - .is_some()), - _ => Ok(false), - } + batch: Option, + /// `None`: the header has no column of this name. + fields: Vec>, } /// One cell into its column: a NOT NULL null or a PHP-lane `Flow\Types` refusal becomes the column's refusal, any /// other exception escapes as thrown. -fn append_cell(column: &mut Column, row: usize, cell: Option<&[u8]>) -> Result<(), PhpException> { +fn append_cell(column: &mut BatchColumn, row: usize, cell: Option<&[u8]>) -> Result<(), PhpException> { let Some(bytes) = cell else { if !column.nullable { column.refusal = Some((row, value_does_not_match(&column.definition, null_zval(), None)?)); @@ -165,7 +33,7 @@ fn append_cell(column: &mut Column, row: usize, cell: Option<&[u8]>) -> Result<( return Ok(()); }; - if native_cell(&mut column.values, &column.plan, bytes)? { + if native_text(&mut column.values, &column.plan.kind, &column.plan.cast, bytes)? { return Ok(()); } @@ -196,63 +64,9 @@ fn append_cell(column: &mut Column, row: usize, cell: Option<&[u8]>) -> Result<( } } -fn finish_batch(state: &mut CsvColumns) -> Result { - let refusal = state - .columns - .iter() - .filter_map(|column| column.refusal.as_ref()) - .fold(None::<&(usize, Zval)>, |lowest, refusal| match lowest { - Some(lowest) if lowest.0 <= refusal.0 => Some(lowest), - _ => Some(refusal), - }); - - if let Some((row, cause)) = refusal { - return Err(schema_mismatch(zval_long(*row as i64), cause.shallow_clone())); - } - - if let Some(absent) = state.columns.iter().find(|column| column.field.is_none() && !column.nullable) { - let cause = call_static( - "Flow\\ETL\\Exception\\ColumnMismatchException", - "missingColumn", - &mut [absent.definition.shallow_clone()], - )?; - - return Err(schema_mismatch(zval_long(0), cause)); - } - - let mut columns = ZendHashTable::with_capacity(state.columns.len() as u32); - - for column in &state.columns { - let data = column - .values - .finish(&column.plan.kind) - .map_err(|e| invalid_argument(format!("flow_php built an invalid column: {e}")))?; - let mut native = Zval::new(); - ext_php_rs::convert::IntoZval::set_zval( - NativeColumn::new(arrow_array::make_array(data), Rc::clone(&column.plan)), - &mut native, - false, - )?; - - match &column.key { - Key::Index(index) => ht_insert_long(&mut columns, *index, native), - Key::Name(name) => ht_insert(&mut columns, name, native), - } - } - - let mut columns_zv = Zval::new(); - columns_zv.set_hashtable(columns); - - call_static( - "Flow\\ETL\\Rows", - "fromColumns", - &mut [state.schema.shallow_clone(), columns_zv, zval_long(state.rows as i64)], - ) -} - pub fn next_columns( reader: &mut CsvReader, - pending: &mut Option, + pending: &mut CsvColumns, schema: &Zval, batch_size: usize, ) -> Result { @@ -260,47 +74,31 @@ pub fn next_columns( return Ok(null_zval()); } - let same_object = pending.as_ref().is_some_and(|state| { - state.schema.object().map(|object| object.handle) == schema.object().map(|object| object.handle) - }); - - if !same_object { - let json = schema_json(schema)?; - - match pending { - Some(state) if state.schema_json == json => state.schema = schema.shallow_clone(), - Some(state) if state.rows > 0 => { - return Err(ext_exception("flow_php cannot change the schema of a pending CSV batch")); - } - _ => *pending = Some(CsvColumns::new(reader, schema, json, batch_size)?), - } - } - - let state = pending.as_mut().expect("built above"); + let (state, rebuilt) = BatchColumns::prepare(&mut pending.batch, schema, batch_size, "CSV")?; - if state.batch_size != batch_size { - if state.rows > 0 { - return Err(ext_exception("flow_php cannot change the batch size of a pending CSV batch")); - } - - state.batch_size = batch_size; + if rebuilt { + pending.fields = state.columns.iter().map(|column| reader.field_of(&column.key.name())).collect(); } while state.rows < state.batch_size && reader.next_record() { let row = state.rows; - for column in &mut state.columns { + for (column, field) in state.columns.iter_mut().zip(&pending.fields) { if column.refusal.is_some() { continue; } - let Some(field) = column.field else { + let Some(field) = field else { + if !column.nullable { + column.absent = column.absent.or(Some(row)); + } + column.values.append_null(); continue; }; - if let Err(e) = append_cell(column, row, reader.cell(field)) { + if let Err(e) = append_cell(column, row, reader.cell(*field)) { state.reset(); return Err(e); @@ -314,8 +112,5 @@ pub fn next_columns( return Ok(null_zval()); } - let batch = finish_batch(state); - state.reset(); - - batch + state.finish() } diff --git a/src/extension/flow-php-ext/src/ctx.rs b/src/extension/flow-php-ext/src/ctx.rs index 531e002110..c68fe59cae 100644 --- a/src/extension/flow-php-ext/src/ctx.rs +++ b/src/extension/flow-php-ext/src/ctx.rs @@ -553,6 +553,10 @@ pub fn json_encode() -> Result<&'static Function, PhpException> { function("json_encode") } +pub fn json_decode() -> Result<&'static Function, PhpException> { + function("json_decode") +} + pub fn json_validate() -> Result<&'static Function, PhpException> { function("json_validate") } diff --git a/src/extension/flow-php-ext/src/json/mod.rs b/src/extension/flow-php-ext/src/json/mod.rs index d692799d76..62955290ce 100644 --- a/src/extension/flow-php-ext/src/json/mod.rs +++ b/src/extension/flow-php-ext/src/json/mod.rs @@ -1 +1,2 @@ +pub mod read; pub mod write; diff --git a/src/extension/flow-php-ext/src/json/read.rs b/src/extension/flow-php-ext/src/json/read.rs new file mode 100644 index 0000000000..99cdc7cb6e --- /dev/null +++ b/src/extension/flow-php-ext/src/json/read.rs @@ -0,0 +1,1254 @@ +//! `Flow\ETL\Adapter\JSON\NativeJsonReader`: JSON lines or a top-level JSON array, fed in chunks, read into native +//! columns by a schema with `RowsBuilder::appendRows()`'s results and refusals. This file frames records and maps their +//! members to columns; serde_json parses and validates. + +use std::borrow::Cow; +use std::collections::hash_map::Entry; +use std::collections::{HashMap, HashSet}; +use std::fmt; + +use ext_php_rs::binary_slice::BinarySlice; +use ext_php_rs::exception::PhpException; +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::Zval; +use flow_batch_frame::kind::{Field, Kind}; +use serde::de::{self, DeserializeSeed, Deserializer as _, IgnoredAny, MapAccess, SeqAccess, Visitor}; +use serde::Deserialize; +use serde_json::de::{SliceRead, StrRead}; +use serde_json::value::RawValue; +use serde_json::Deserializer; + +use crate::batch_columns::{batch_size_of, native_text, BatchColumns, Key}; +use crate::builder::{append_native, append_one, native_leaf, Append}; +use crate::cast::{CastKind, MapKeyKind}; +use crate::ctx::{self, array_key_index, null_zval, zval_str}; +use crate::exception::ext_exception; +use crate::kind_builder::KindBuilder; +use crate::physical::overflow; +use crate::render::runtime; + +/// JSON's insignificant whitespace. +const WHITESPACE: &[u8] = b" \t\n\r"; +/// `JsonFileReader::C_ISSPACE`: a line of only these bytes is no record. +const BLANK: &[u8] = b" \t\n\r\x0B\x0C"; +const BOM: &[u8] = b"\xEF\xBB\xBF"; +/// `json_decode()`'s default depth: a record nested this deep is refused, one level less is read. +const DEPTH: usize = 512; + +fn is_whitespace(byte: &u8) -> bool { + WHITESPACE.contains(byte) +} + +/// Why a record cannot be read; `ordinal` is its 1-based line or 0-based element. +#[derive(Debug, PartialEq)] +pub struct Malformed { + pub ordinal: usize, + pub message: String, +} + +/// One framed record: `records[start..end]`. +pub struct Record { + pub start: usize, + pub end: usize, + pub ordinal: usize, +} + +/// The document scanner: where the element being framed stands. +#[derive(Default)] +struct Scan { + depth: usize, + in_string: bool, + escape: bool, +} + +struct TooDeep; + +impl Scan { + /// From `bytes[from..]` on: `Some(i)` is the depth-0 `,` or `]` at `i`, `None` means `bytes` ends inside the value. + fn run(&mut self, bytes: &[u8], mut i: usize) -> Result, TooDeep> { + while i < bytes.len() { + if self.in_string { + if self.escape { + self.escape = false; + i += 1; + + continue; + } + + let Some(found) = memchr::memchr2(b'"', b'\\', &bytes[i..]) else { + return Ok(None); + }; + + i += found; + + if bytes[i] == b'\\' { + self.escape = true; + } else { + self.in_string = false; + } + + i += 1; + + continue; + } + + match bytes[i] { + b'"' => self.in_string = true, + b'{' | b'[' => { + self.depth += 1; + + if self.depth >= DEPTH { + return Err(TooDeep); + } + } + b'}' | b']' if self.depth > 0 => self.depth -= 1, + b']' | b',' if self.depth == 0 => return Ok(Some(i)), + _ => {} + } + + i += 1; + } + + Ok(None) + } +} + +const TOO_DEEP: &str = "Maximum stack depth exceeded"; +const LONE_SURROGATE: &str = "Single unpaired UTF-16 surrogate in unicode escape"; + +/// `{}` or `[]`: a record with no fields, skipped as `JsonFileReader::sample()` skips it. +fn empty_record(bytes: &[u8]) -> bool { + let start = bytes.iter().position(|byte| !is_whitespace(byte)).unwrap_or(bytes.len()); + let end = bytes.iter().rposition(|byte| !is_whitespace(byte)).map_or(start, |end| end + 1); + let trimmed = &bytes[start..end]; + + matches!( + (trimmed.first(), trimmed.last()), + (Some(b'{'), Some(b'}')) | (Some(b'['), Some(b']')) + ) && trimmed.len() >= 2 + && trimmed[1..trimmed.len() - 1].iter().all(is_whitespace) +} + +enum Document { + Start, + Elements, + Closed, +} + +/// Splits fed bytes into records without parsing values: lines on `\n`, a document's elements on its depth-0 `,` and +/// `]`. Holds the unframed input only. +pub struct Framing { + lines: bool, + input: Vec, + /// The first byte of `input` not yet framed. + start: usize, + /// How far past `start` the current record's end was searched. + scanned: usize, + scan: Scan, + document: Document, + bom: bool, + /// The next line (1-based) or element (0-based). + ordinal: usize, + finished: bool, +} + +impl Framing { + pub fn new(lines: bool) -> Self { + Self { + lines, + input: Vec::new(), + start: 0, + scanned: 0, + scan: Scan::default(), + document: Document::Start, + bom: true, + ordinal: usize::from(lines), + finished: false, + } + } + + pub fn feed(&mut self, chunk: &[u8]) { + if self.start > 0 && self.start * 2 >= self.input.len() { + self.input.drain(..self.start); + self.start = 0; + } + + self.input.extend_from_slice(chunk); + } + + pub fn finish(&mut self) { + self.finished = true; + } + + /// Copies the next record into `records`; `false` when no complete record is buffered. + pub fn next(&mut self, records: &mut Vec, bounds: &mut Vec) -> Result { + if self.bom { + let pending = &self.input[self.start..]; + + if pending.len() < BOM.len() && BOM.starts_with(pending) && !self.finished { + return Ok(false); + } + + if pending.starts_with(BOM) { + self.start += BOM.len(); + } + + self.bom = false; + } + + loop { + let framed = if self.lines { self.line() } else { self.element()? }; + + let Some((start, end, ordinal)) = framed else { + return Ok(false); + }; + + let bytes = &self.input[start..end]; + + if empty_record(bytes) { + continue; + } + + if lone_surrogate(bytes) { + return Err(Malformed { + ordinal, + message: LONE_SURROGATE.to_string(), + }); + } + + bounds.push(Record { + start: records.len(), + end: records.len() + bytes.len(), + ordinal, + }); + records.extend_from_slice(bytes); + + return Ok(true); + } + } + + fn line(&mut self) -> Option<(usize, usize, usize)> { + loop { + let pending = &self.input[self.start..]; + let (end, next) = match memchr::memchr(b'\n', &pending[self.scanned..]) { + Some(found) => (self.scanned + found, self.scanned + found + 1), + None if self.finished && !pending.is_empty() => (pending.len(), pending.len()), + None => { + self.scanned = pending.len(); + + return None; + } + }; + let line = (self.start, self.start + end, self.ordinal); + + self.ordinal += 1; + self.start += next; + self.scanned = 0; + + if !self.input[line.0..line.1].iter().all(|byte| BLANK.contains(byte)) { + return Some(line); + } + } + } + + fn element(&mut self) -> Result, Malformed> { + loop { + match self.document { + Document::Start => { + let pending = &self.input[self.start..]; + let Some(first) = pending.iter().position(|byte| !is_whitespace(byte)) else { + self.start = self.input.len(); + + return match self.finished { + true => Err(self.malformed("EOF while parsing a value".to_string())), + false => Ok(None), + }; + }; + + if pending[first] != b'[' { + return Err(self.malformed("expected `[`".to_string())); + } + + self.start += first + 1; + self.document = Document::Elements; + } + Document::Elements => { + let pending = &self.input[self.start..]; + let found = self.scan.run(pending, self.scanned).map_err(|TooDeep| self.malformed(TOO_DEEP.to_string()))?; + + let Some(found) = found else { + self.scanned = pending.len(); + + if !self.finished { + return Ok(None); + } + + return Err(self.malformed( + Deserializer::from_slice(pending) + .deserialize_ignored_any(IgnoredAny) + .err() + .map_or_else(|| "EOF while parsing a list".to_string(), |e| e.to_string()), + )); + }; + + let element = (self.start, self.start + found, self.ordinal); + let closing = pending[found] == b']'; + + self.start += found + 1; + self.scanned = 0; + self.scan = Scan::default(); + + if closing { + self.document = Document::Closed; + + if self.ordinal == 0 && self.input[element.0..element.1].iter().all(is_whitespace) { + continue; + } + } + + self.ordinal += 1; + + return Ok(Some(element)); + } + Document::Closed => { + let pending = &self.input[self.start..]; + let trailing = pending.iter().any(|byte| !is_whitespace(byte)); + + self.start = self.input.len(); + + if trailing { + return Err(self.malformed("trailing characters".to_string())); + } + + return Ok(None); + } + } + } + } + + fn malformed(&self, message: String) -> Malformed { + Malformed { + ordinal: self.ordinal, + message, + } + } +} + +/// The code unit of the `\uXXXX` escape at `bytes[at]`. +fn code_unit(bytes: &[u8], at: usize) -> Option { + let hex = bytes.get(at + 2..at + 6).filter(|_| bytes.get(at + 1) == Some(&b'u'))?; + + u16::from_str_radix(std::str::from_utf8(hex).ok()?, 16).ok() +} + +/// Whether a `\u` escape of `bytes` is a UTF-16 surrogate without its pair, which `json_decode()` refuses and serde +/// checks only when it unescapes a string. A backslash outside a string is serde's syntax error, so every one is walked. +fn lone_surrogate(bytes: &[u8]) -> bool { + let mut i = 0; + let mut low_expected_at = None; + + while let Some(found) = memchr::memchr(b'\\', &bytes[i..]) { + let at = i + found; + + match (low_expected_at.take(), code_unit(bytes, at)) { + (Some(expected), Some(0xDC00..=0xDFFF)) if expected == at => {} + (Some(_), _) | (None, Some(0xDC00..=0xDFFF)) => return true, + (None, Some(0xD800..=0xDBFF)) => low_expected_at = Some(at + 6), + (None, _) => {} + } + + i = (at + if bytes.get(at + 1) == Some(&b'u') { 6 } else { 2 }).min(bytes.len()); + } + + low_expected_at.is_some() +} + +/// A line's nesting checked as the document scanner checks an element's. +fn line_too_deep(line: &[u8]) -> bool { + memchr::memchr2_iter(b'[', b'{', line).count() >= DEPTH && Scan::default().run(line, 0).is_err() +} + +/// A JSON number as `json_decode()` reads it: integer-shaped text within the i64 range is an int, any other a float. +#[derive(Debug, PartialEq)] +pub enum Number { + Long(i64), + Double(f64), +} + +pub fn number(text: &str) -> Number { + if !text.bytes().any(|byte| matches!(byte, b'.' | b'e' | b'E')) { + if let Ok(long) = text.parse::() { + return Number::Long(long); + } + } + + Number::Double(text.parse::().unwrap_or(f64::NAN)) +} + +fn number_zval(text: &str) -> Zval { + let mut zval = Zval::new(); + + match number(text) { + Number::Long(long) => zval.set_long(long), + Number::Double(double) => zval.set_double(double), + } + + zval +} + +fn bool_zval(value: bool) -> Zval { + let mut zval = Zval::new(); + zval.set_bool(value); + + zval +} + +/// `get_debug_type()` of the scalar `json_decode()` reads from `text`. +fn scalar_type(text: &str) -> &'static str { + match text.as_bytes()[0] { + b'"' => "string", + b't' | b'f' => "bool", + b'n' => "null", + _ => match number(text) { + Number::Long(_) => "int", + Number::Double(_) => "float", + }, + } +} + +#[derive(Debug, PartialEq)] +pub enum RecordError { + Malformed(String), + /// The record is a scalar of this `get_debug_type()`. + Scalar(&'static str), +} + +fn deserializer(text: &[u8]) -> Deserializer> { + let mut deserializer = Deserializer::from_slice(text); + deserializer.disable_recursion_limit(); + + deserializer +} + +fn str_deserializer(text: &str) -> Deserializer> { + let mut deserializer = Deserializer::from_str(text); + deserializer.disable_recursion_limit(); + + deserializer +} + +/// A JSON string, borrowed when it has no escape. +struct Text; + +impl<'de> Visitor<'de> for Text { + type Value = Cow<'de, str>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a JSON string") + } + + fn visit_borrowed_str(self, value: &'de str) -> Result { + Ok(Cow::Borrowed(value)) + } + + fn visit_str(self, value: &str) -> Result { + Ok(Cow::Owned(value.to_owned())) + } +} + +impl<'de> DeserializeSeed<'de> for Text { + type Value = Cow<'de, str>; + + fn deserialize>(self, deserializer: D) -> Result { + deserializer.deserialize_str(self) + } +} + +/// The column each member feeds, resolved once per schema: an object's members by name, an array record's elements +/// by position (a definition keyed by that int). +#[derive(Default)] +pub struct MemberColumns { + names: HashMap, usize>, + positions: Vec>, +} + +impl MemberColumns { + pub fn of<'a>(keys: impl Iterator) -> Self { + let mut columns = Self::default(); + + for (column, key) in keys.enumerate() { + if let Key::Index(index) = key { + if let Ok(position) = usize::try_from(*index) { + columns.positions.resize(columns.positions.len().max(position + 1), None); + columns.positions[position] = Some(column); + } + } + + columns.names.insert(key.name(), column); + } + + columns + } +} + +/// A record's members, each stored as the span of its value in `slots[column]`. +struct Members<'a> { + columns: &'a MemberColumns, + slots: &'a mut [Option<(usize, usize)>], + base: usize, +} + +impl Members<'_> { + fn store(&mut self, column: Option, value: &RawValue) { + if let Some(column) = column { + let start = value.get().as_ptr() as usize - self.base; + + self.slots[column] = Some((start, start + value.get().len())); + } + } +} + +impl<'de> Visitor<'de> for Members<'_> { + type Value = (); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a JSON object or array") + } + + fn visit_map>(mut self, mut map: A) -> Result<(), A::Error> { + while let Some(name) = map.next_key_seed(Text)? { + let value: &'de RawValue = map.next_value()?; + + self.store(self.columns.names.get(name.as_bytes()).copied(), value); + } + + Ok(()) + } + + fn visit_seq>(mut self, mut seq: A) -> Result<(), A::Error> { + let mut position = 0; + + while let Some(value) = seq.next_element::<&'de RawValue>()? { + self.store(self.columns.positions.get(position).copied().flatten(), value); + position += 1; + } + + Ok(()) + } +} + +/// Maps one record's members onto `slots`, spans relative to `base` (the address of the batch's first byte). +pub fn map_record( + record: &[u8], + columns: &MemberColumns, + slots: &mut [Option<(usize, usize)>], + base: usize, +) -> Result<(), RecordError> { + let malformed = |e: serde_json::Error| RecordError::Malformed(e.to_string()); + + if let Some(b'{' | b'[') = record.iter().find(|byte| !is_whitespace(byte)) { + let mut deserializer = deserializer(record); + deserializer.deserialize_any(Members { columns, slots, base }).map_err(malformed)?; + + return deserializer.end().map_err(malformed); + } + + let mut deserializer = deserializer(record); + let value = <&RawValue>::deserialize(&mut deserializer).map_err(malformed)?; + deserializer.end().map_err(malformed)?; + + Err(RecordError::Scalar(scalar_type(value.get()))) +} + +fn custom(failure: &mut Option, cause: PhpException) -> E { + *failure = Some(cause); + + E::custom("flow_php refused a JSON value") +} + +/// A value `map_record()` validated (surrogates by `Framing`) that serde reads again cannot fail. +fn reread(error: serde_json::Error) -> PhpException { + ext_exception(format!("flow_php failed to read validated JSON again: {error}")) +} + +/// One value appended as `append_cast()` would append what `json_decode()` reads from it; `false` leaves a partial row +/// for the caller to truncate before the PHP lane takes the whole value. +fn into_column(values: &mut KindBuilder, kind: &Kind, cast: &CastKind, text: &str) -> Result { + if let CastKind::Optional(inner) = cast { + if text == "null" { + values.append_null(); + + return Ok(true); + } + + return into_column(values, kind, inner, text); + } + + let leaf = |values: &mut KindBuilder, value: Zval| -> Result { + match native_leaf(kind, cast, &value)? { + Some(native) => { + append_native(values, native)?; + + Ok(true) + } + None => Ok(false), + } + }; + + match text.as_bytes()[0] { + b'"' => { + let string = match text.contains('\\') { + true => str_deserializer(text).deserialize_str(Text).map_err(reread)?, + false => Cow::Borrowed(&text[1..text.len() - 1]), + }; + + native_text(values, kind, cast, string.as_bytes()) + } + b'n' => Ok(false), + b't' | b'f' => leaf(values, bool_zval(text == "true")), + b'[' => match (kind, cast) { + (Kind::List(element), CastKind::List(inner)) => { + let mut failure = None; + let cast = str_deserializer(text).deserialize_seq(Elements { + values: values.list_element(), + kind: &element.kind, + cast: inner, + failure: &mut failure, + }); + + match (cast, failure) { + (_, Some(failure)) => Err(failure), + (Err(e), None) => Err(reread(e)), + (Ok(false), None) => Ok(false), + (Ok(true), None) => { + values.end_entries().map_err(overflow)?; + + Ok(true) + } + } + } + _ => Ok(false), + }, + b'{' => match (kind, cast) { + (Kind::Map(key, item), CastKind::Map(key_cast, inner)) => { + let entries = str_deserializer(text).deserialize_map(Entries).map_err(reread)?; + + for (name, value) in last_wins(entries) { + let (keys, items) = values.map_entries(); + let cast = match (key_cast, array_key_index(name.as_bytes()), &key.kind) { + (MapKeyKind::Int, Some(index), Kind::Int64) => { + keys.append_fixed(&index.to_le_bytes()); + + true + } + (MapKeyKind::Str, None, Kind::Bytes) => { + keys.append_bytes(name.as_bytes()).map_err(overflow)?; + + true + } + _ => false, + } && into_column(items, &item.kind, inner, value.get())?; + + if !cast { + return Ok(false); + } + } + + values.end_entries().map_err(overflow)?; + + Ok(true) + } + (Kind::Struct(fields), CastKind::Structure(elements)) => { + let members = str_deserializer(text).deserialize_map(Fields(fields)).map_err(reread)?; + + for (((child, field), element), member) in + values.struct_children().iter_mut().zip(fields).zip(elements).zip(members) + { + match member.map(RawValue::get) { + None if element.required => return Ok(false), + None => child.append_null(), + Some("null") if !matches!(element.kind, CastKind::Optional(_)) => return Ok(false), + Some(value) => { + if !into_column(child, &field.kind, &element.kind, value)? { + return Ok(false); + } + } + } + } + + values.end_struct(); + + Ok(true) + } + _ => Ok(false), + }, + _ => leaf(values, number_zval(text)), + } +} + +/// The elements of a list, each through `into_column()`; the rest is skipped once one is not cast. +struct Elements<'a> { + values: &'a mut KindBuilder, + kind: &'a Kind, + cast: &'a CastKind, + failure: &'a mut Option, +} + +impl<'de> Visitor<'de> for Elements<'_> { + type Value = bool; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a JSON array") + } + + fn visit_seq>(self, mut seq: A) -> Result { + let Elements { values, kind, cast, failure } = self; + + while let Some(value) = seq.next_element::<&'de RawValue>()? { + match into_column(values, kind, cast, value.get()) { + Ok(true) => {} + Ok(false) => { + while seq.next_element::()?.is_some() {} + + return Ok(false); + } + Err(cause) => return Err(custom(failure, cause)), + } + } + + Ok(true) + } +} + +/// An object's members in document order, duplicates included. +struct Entries; + +impl<'de> Visitor<'de> for Entries { + type Value = Vec<(Cow<'de, str>, &'de RawValue)>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a JSON object") + } + + fn visit_map>(self, mut map: A) -> Result { + let mut entries = Vec::with_capacity(map.size_hint().unwrap_or(0)); + + while let Some(name) = map.next_key_seed(Text)? { + entries.push((name, map.next_value::<&'de RawValue>()?)); + } + + Ok(entries) + } +} + +/// An object's members by structure field, the last duplicate winning; a member no field names is skipped unread. +struct Fields<'a>(&'a [Field]); + +impl<'de> Visitor<'de> for Fields<'_> { + type Value = Vec>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a JSON object") + } + + fn visit_map>(self, mut map: A) -> Result { + let mut members = vec![None; self.0.len()]; + + while let Some(name) = map.next_key_seed(Text)? { + match self.0.iter().position(|field| field.name == name) { + Some(position) => members[position] = Some(map.next_value::<&'de RawValue>()?), + None => { + map.next_value::()?; + } + } + } + + Ok(members) + } +} + +/// Up to this many members a repeated key is looked for pair by pair (at most 120 comparisons of short keys), past it +/// through a hash set: hashing every key and allocating the set costs more than the comparisons it saves. +const PAIRWISE_DUPLICATE_CHECK: usize = 16; + +/// `json_decode()`'s array of the members: a repeated key keeps its first position and its last value. +fn last_wins<'a>(entries: Vec<(Cow<'a, str>, &'a RawValue)>) -> Vec<(Cow<'a, str>, &'a RawValue)> { + let repeated = if entries.len() <= PAIRWISE_DUPLICATE_CHECK { + entries + .iter() + .enumerate() + .any(|(i, (name, _))| entries[..i].iter().any(|(earlier, _)| earlier == name)) + } else { + let mut seen = HashSet::with_capacity(entries.len()); + + !entries.iter().all(|(name, _)| seen.insert(name.as_ref())) + }; + + if !repeated { + return entries; + } + + let mut positions: HashMap<&str, usize> = HashMap::with_capacity(entries.len()); + let mut kept: Vec<(usize, usize)> = Vec::with_capacity(entries.len()); + + for (index, (name, _)) in entries.iter().enumerate() { + match positions.entry(name.as_ref()) { + Entry::Occupied(position) => kept[*position.get()].1 = index, + Entry::Vacant(position) => { + position.insert(kept.len()); + kept.push((index, index)); + } + } + } + + kept.into_iter().map(|(key, value)| (entries[key].0.clone(), entries[value].1)).collect() +} + +/// The batch being built and the column each member feeds. +#[derive(Default)] +struct JsonColumns { + batch: Option, + members: MemberColumns, +} + +#[php_class] +#[php(name = "Flow\\ETL\\Adapter\\JSON\\NativeJsonReader", flags = ClassFlags::Final)] +pub struct NativeJsonReader { + uri: String, + framing: Framing, + /// The framed records of the pending batch, copied out of the input. + records: Vec, + bounds: Vec, + slots: Vec>, + columns: JsonColumns, +} + +/// `Malformed JSON in "" at line N: …` (lines, 1-based) or `at element N` (a document, 0-based). +fn malformed(uri: &str, lines: bool, ordinal: usize, message: &str) -> PhpException { + runtime(format!( + "Malformed JSON in \"{uri}\" at {} {ordinal}: {message}", + if lines { "line" } else { "element" }, + )) +} + +impl NativeJsonReader { + fn clear(&mut self) { + self.records.clear(); + self.bounds.clear(); + + if let Some(batch) = self.columns.batch.as_mut() { + batch.reset(); + } + } + + fn read(&mut self, schema: &Zval, batch_size: usize) -> PhpResult { + let (state, rebuilt) = BatchColumns::prepare(&mut self.columns.batch, schema, batch_size, "JSON")?; + + if rebuilt { + self.columns.members = MemberColumns::of(state.columns.iter().map(|column| &column.key)); + } + + let batch_size = state.batch_size; + let lines = self.framing.lines; + + while self.bounds.len() < batch_size { + match self.framing.next(&mut self.records, &mut self.bounds) { + Ok(true) => {} + Ok(false) => break, + Err(Malformed { ordinal, message }) => return Err(malformed(&self.uri, lines, ordinal, &message)), + } + + if lines { + let record = self.bounds.last().expect("framed above"); + + if line_too_deep(&self.records[record.start..record.end]) { + return Err(malformed(&self.uri, lines, record.ordinal, TOO_DEEP)); + } + } + } + + let state = self.columns.batch.as_mut().expect("prepared above"); + state.rows = self.bounds.len(); + + if self.bounds.is_empty() || (self.bounds.len() < state.batch_size && !self.framing.finished) { + return Ok(null_zval()); + } + + let width = state.columns.len(); + let base = self.records.as_ptr() as usize; + + self.slots.clear(); + self.slots.resize(self.bounds.len() * width, None); + + for (row, record) in self.bounds.iter().enumerate() { + let slots = &mut self.slots[row * width..(row + 1) * width]; + + match map_record(&self.records[record.start..record.end], &self.columns.members, slots, base) { + Ok(()) => {} + Err(RecordError::Malformed(message)) => return Err(malformed(&self.uri, lines, record.ordinal, &message)), + Err(RecordError::Scalar(given)) => { + return Err(runtime(format!( + "A JSON record must be an object or an array, {given} given in \"{}\".", + self.uri, + ))); + } + } + } + + for (position, column) in state.columns.iter_mut().enumerate() { + for row in 0..self.bounds.len() { + if column.refusal.is_some() { + break; + } + + let Some((start, end)) = self.slots[row * width + position] else { + if !column.nullable { + column.absent = column.absent.or(Some(row)); + } + + column.values.append_null(); + + continue; + }; + // SAFETY: every record of the batch passed map_record(), whose serde parse checked the UTF-8 of each + // member value; the span is one of those values, so it starts and ends on character boundaries + let text = unsafe { std::str::from_utf8_unchecked(&self.records[start..end]) }; + + let value = if text == "null" { + null_zval() + } else { + let len = column.values.len(); + + if into_column(&mut column.values, &column.plan.kind, &column.plan.cast, text)? { + continue; + } + + column.values.truncate(len); + + decode(text)? + }; + + if let Append::Refused { cause, .. } = + append_one(&mut column.values, &column.plan, &column.definition, column.nullable, &value)? + { + column.refusal = Some((row, cause)); + } + } + } + + self.records.clear(); + self.bounds.clear(); + + state.finish() + } +} + +/// `json_decode($text, true)`: PHP's own value of a JSON value `into_column()` did not cast. +fn decode(text: &str) -> Result { + let mut associative = Zval::new(); + associative.set_bool(true); + let value = ctx::call_handle(ctx::json_decode()?, None, &mut [zval_str(text.as_bytes()), associative], "decode JSON")?; + + if value.is_null() { + return Err(ext_exception("flow_php expected json_decode() to read validated JSON")); + } + + Ok(value) +} + +#[php_impl] +impl NativeJsonReader { + /// `$uri` names the file in refusals. + pub fn __construct(lines: bool, uri: BinarySlice) -> Self { + Self { + uri: String::from_utf8_lossy(&uri).into_owned(), + framing: Framing::new(lines), + records: Vec::new(), + bounds: Vec::new(), + slots: Vec::new(), + columns: JsonColumns::default(), + } + } + + pub fn feed(&mut self, chunk: BinarySlice) { + self.framing.feed(&chunk); + } + + /// Malformed input left in the buffer (a truncated record, a missing `]`) is refused by the next `nextColumns()`. + pub fn finish(&mut self) { + self.framing.finish(); + } + + /// Exactly `$batchSize` rows keyed and ordered by `$schema` while that many are buffered, the remainder after + /// `finish()`, else null. Refusals are `RowsBuilder::appendRows()`'s, row indexes relative to the batch. + #[php(name = "nextColumns")] + pub fn next_columns(&mut self, schema: &Zval, batch_size: i64) -> PhpResult { + let batch = self.read(schema, batch_size_of(batch_size, "JSON")?); + + if batch.is_err() { + self.clear(); + } + + batch + } +} + +#[cfg(test)] +mod tests { + use serde::de::Deserializer as _; + + use super::{ + last_wins, map_record, number, str_deserializer, Entries, Framing, Key, Malformed, MemberColumns, Number, Record, + RecordError, + }; + use crate::ctx::array_key_index; + + fn framed(lines: bool, chunks: &[&[u8]]) -> Result, Malformed> { + let mut framing = Framing::new(lines); + let mut records = Vec::new(); + let mut bounds: Vec = Vec::new(); + + for chunk in chunks { + framing.feed(chunk); + + while framing.next(&mut records, &mut bounds)? {} + } + + framing.finish(); + + while framing.next(&mut records, &mut bounds)? {} + + Ok(bounds + .iter() + .map(|record| (String::from_utf8(records[record.start..record.end].to_vec()).unwrap(), record.ordinal)) + .collect()) + } + + fn bytes(text: &str) -> Vec<&[u8]> { + text.as_bytes().chunks(1).collect() + } + + fn nested(depth: usize) -> String { + format!("{}1{}", "[".repeat(depth), "]".repeat(depth)) + } + + fn malformed(ordinal: usize, message: &str) -> Result, Malformed> { + Err(Malformed { + ordinal, + message: message.to_string(), + }) + } + + #[test] + fn a_nested_record_fed_byte_by_byte_is_one_record() { + let document = r#"[{"a":{"b":[1,"x]\"",{"c":2}]}},{"d":3}]"#; + + assert_eq!( + framed(false, &bytes(document)).unwrap(), + vec![(r#"{"a":{"b":[1,"x]\"",{"c":2}]}}"#.to_string(), 0), (r#"{"d":3}"#.to_string(), 1)], + ); + assert_eq!(framed(true, &bytes("{\"a\":[1,\n")).unwrap(), vec![(r#"{"a":[1,"#.to_string(), 1)]); + } + + #[test] + fn an_element_waits_for_its_end_across_chunks() { + assert_eq!( + framed(false, &[b"[{\"id\":1", b"2}, {\"id\"", b":3}\n]"]).unwrap(), + vec![(r#"{"id":12}"#.to_string(), 0), (r#" {"id":3}"#.to_string() + "\n", 1)], + ); + } + + #[test] + fn one_leading_bom_is_skipped() { + assert_eq!(framed(false, &[b"\xEF\xBB", b"\xBF [1]"]).unwrap(), vec![("1".to_string(), 0)]); + assert_eq!(framed(true, &[b"\xEF\xBB\xBF{\"a\":1}\n"]).unwrap(), vec![(r#"{"a":1}"#.to_string(), 1)]); + assert_eq!( + framed(true, &[b"{\"a\":1}\n\xEF\xBB\xBF{\"a\":2}"]).unwrap(), + vec![(r#"{"a":1}"#.to_string(), 1), ("\u{FEFF}{\"a\":2}".to_string(), 2)], + ); + } + + #[test] + fn blank_lines_and_empty_records_are_skipped_and_still_counted() { + assert_eq!( + framed(true, &[b"\n \t\x0B\x0C\r\n{}\n[ ]\n{\"a\":1}\r\n\n"]).unwrap(), + vec![("{\"a\":1}\r".to_string(), 5)], + ); + assert_eq!(framed(false, &[b"[{}, [], {\"a\":1}]"]).unwrap(), vec![(r#" {"a":1}"#.to_string(), 2)]); + } + + #[test] + fn an_empty_array_has_no_records_and_whitespace_may_follow_it() { + assert_eq!(framed(false, &[b" \n[ \n] \n\t"]).unwrap(), vec![]); + assert_eq!(framed(false, &[b"[1] \n"]).unwrap(), vec![("1".to_string(), 0)]); + } + + #[test] + fn content_after_the_closing_bracket_is_malformed() { + assert_eq!(framed(false, &[b"[{\"id\":1}] x"]), malformed(1, "trailing characters")); + } + + #[test] + fn a_truncated_document_is_malformed() { + assert_eq!(framed(false, &[b"[{\"id\":1}"]), malformed(0, "EOF while parsing a list")); + assert_eq!(framed(false, &[b"[{\"id\":"]), malformed(0, "EOF while parsing a value at line 1 column 6")); + assert_eq!(framed(false, &[b""]), malformed(0, "EOF while parsing a value")); + assert_eq!(framed(false, &[b"{}"]), malformed(0, "expected `[`")); + } + + #[test] + fn nesting_deeper_than_json_decode_reads_is_refused() { + assert_eq!(framed(false, &[format!("[{}]", nested(511)).as_bytes()]).unwrap().len(), 1); + assert_eq!( + framed(false, &[format!("[{}]", nested(512)).as_bytes()]), + malformed(0, "Maximum stack depth exceeded"), + ); + assert!(!super::line_too_deep(nested(511).as_bytes())); + assert!(super::line_too_deep(nested(512).as_bytes())); + assert!(!super::line_too_deep(format!("[\"{}\"]", "[".repeat(600)).as_bytes())); + } + + #[test] + fn numbers_follow_json_decode() { + assert_eq!(number("-0"), Number::Long(0)); + assert_eq!(number("9223372036854775807"), Number::Long(i64::MAX)); + assert_eq!(number("-9223372036854775808"), Number::Long(i64::MIN)); + assert_eq!(number("9223372036854775808"), Number::Double(9_223_372_036_854_775_808.0)); + assert_eq!(number("-9223372036854775809"), Number::Double(-9_223_372_036_854_775_809.0)); + assert_eq!(number("1E2"), Number::Double(100.0)); + assert_eq!(number("1e400"), Number::Double(f64::INFINITY)); + assert_eq!(number("1e-400"), Number::Double(0.0)); + + let Number::Double(negative_zero) = number("-0.0") else { + panic!("-0.0 is a float"); + }; + + assert!(negative_zero == 0.0 && negative_zero.is_sign_negative()); + } + + /// Columns keyed as `Schema::definitions()` keys them: a canonical int name by its int. + fn columns(names: &[&str]) -> MemberColumns { + let keys: Vec = names + .iter() + .map(|name| match array_key_index(name.as_bytes()) { + Some(index) => Key::Index(index), + None => Key::Name(name.as_bytes().to_vec()), + }) + .collect(); + + MemberColumns::of(keys.iter()) + } + + fn mapped(record: &str, names: &[&str]) -> Result>, RecordError> { + let mut slots = vec![None; names.len()]; + + map_record(record.as_bytes(), &columns(names), &mut slots, record.as_ptr() as usize)?; + + Ok(slots.iter().map(|slot| slot.map(|(start, end)| record[start..end].to_string())).collect()) + } + + #[test] + fn members_map_to_columns_by_name_and_the_last_duplicate_wins() { + assert_eq!( + mapped(r#" {"b": [1, {"x":2}], "zz": 0, "a": "1", "a": null} "#, &["a", "b", "c"]).unwrap(), + vec![Some("null".to_string()), Some(r#"[1, {"x":2}]"#.to_string()), None], + ); + assert_eq!( + mapped(r#"{"\u00e9\/":1,"e\u0301":2}"#, &["é/", "é"]).unwrap(), + vec![Some("1".to_string()), None], + ); + } + + #[test] + fn an_array_record_maps_elements_to_numeric_names() { + assert_eq!(mapped(r#"[10, "x", true]"#, &["2", "0"]).unwrap(), vec![Some("true".to_string()), Some("10".to_string())]); + } + + #[test] + fn a_scalar_record_names_its_type() { + assert_eq!(mapped(" 5 ", &[]), Err(RecordError::Scalar("int"))); + assert_eq!(mapped("-0", &[]), Err(RecordError::Scalar("int"))); + assert_eq!(mapped("9223372036854775808", &[]), Err(RecordError::Scalar("float"))); + assert_eq!(mapped(r#""x""#, &[]), Err(RecordError::Scalar("string"))); + assert_eq!(mapped("false", &[]), Err(RecordError::Scalar("bool"))); + assert_eq!(mapped("null", &[]), Err(RecordError::Scalar("null"))); + } + + #[test] + fn invalid_json_is_malformed() { + for record in [ + r#"{"id":1}{"id":9}"#, + "{\"id\":1}\x0B", + "\0", + "{\"a\":\"\x01\"}", + "01", + "NaN", + "True", + "{\"skipped\":\"\u{0}\"}", + ] { + assert!(matches!(mapped(record, &["id"]), Err(RecordError::Malformed(_))), "{record:?}"); + } + + let invalid_utf8 = b"{\"skipped\":\"\xFF\"}"; + + assert!(matches!( + map_record(invalid_utf8, &columns(&[]), &mut [], invalid_utf8.as_ptr() as usize), + Err(RecordError::Malformed(_)), + )); + } + + #[test] + fn a_lone_surrogate_escape_is_malformed_in_any_member() { + for record in [ + r#"{"skipped":"\ud800"}"#, + r#"{"skipped":"\udc00"}"#, + r#"{"skipped":"\ud83dx"}"#, + r#"{"skipped":"\ud83d\u0041"}"#, + r#"{"\ud800":1}"#, + r#"{"a":"\ud83d"}"#, + ] { + assert_eq!( + framed(true, &[record.as_bytes()]), + malformed(1, "Single unpaired UTF-16 surrogate in unicode escape"), + "{record}", + ); + } + + assert_eq!( + framed(true, &[r#"{"a":"\ud83d\ude00","b":"\\","c":"\\ud800"}"#.as_bytes()]).unwrap().len(), + 1, + "a pair, an escaped backslash, and an escaped backslash before u are no lone surrogates", + ); + } + + fn deduplicated(object: &str) -> Vec<(String, String)> { + let entries = str_deserializer(object).deserialize_map(Entries).unwrap(); + + last_wins(entries).into_iter().map(|(name, value)| (name.into_owned(), value.get().to_string())).collect() + } + + fn object(members: &[(String, usize)]) -> String { + format!("{{{}}}", members.iter().map(|(name, value)| format!("\"{name}\":{value}")).collect::>().join(",")) + } + + #[test] + fn a_repeated_key_keeps_its_first_position_and_its_last_value_below_and_past_the_pairwise_check() { + for size in [3, 40] { + let mut members: Vec<(String, usize)> = (0..size).map(|i| (format!("k{i}"), i)).collect(); + + assert_eq!( + deduplicated(&object(&members)), + members.iter().map(|(name, value)| (name.clone(), value.to_string())).collect::>(), + "{size} unique keys stay as read", + ); + + members.push(("k1".to_string(), 99)); + let mut expected: Vec<(String, String)> = + members[..size].iter().map(|(name, value)| (name.clone(), value.to_string())).collect(); + expected[1].1 = "99".to_string(); + + assert_eq!(deduplicated(&object(&members)), expected, "{size} keys and k1 again"); + } + } +} diff --git a/src/extension/flow-php-ext/src/lib.rs b/src/extension/flow-php-ext/src/lib.rs index 94a545bd95..22ef464290 100644 --- a/src/extension/flow-php-ext/src/lib.rs +++ b/src/extension/flow-php-ext/src/lib.rs @@ -1,5 +1,6 @@ mod alloc; mod backend; +mod batch_columns; mod builder; mod cast; mod column; @@ -53,20 +54,13 @@ pub unsafe extern "C" fn module_startup(_type: i32, _module_number: i32) -> i32 0 } -fn csv_batch_size(batch_size: i64) -> PhpResult { - usize::try_from(batch_size) - .ok() - .filter(|size| *size > 0) - .ok_or_else(|| ext_exception("flow_php CSV batch size must be greater than 0")) -} - /// Native counterpart of `CSVLineReader` + `CSVEncoder::decode()`: bytes in, rows or native columns out, /// byte-identical to the PHP path. Resumable - `feed` any chunk size, `finish` at EOF. #[php_class] #[php(name = "Flow\\ETL\\Adapter\\CSV\\RustCSVReaderNative")] pub struct RustCSVReaderNative { reader: csv::CsvReader, - columns: Option, + columns: csv::columns::CsvColumns, } #[php_impl] @@ -81,7 +75,7 @@ impl RustCSVReaderNative { ) -> PhpResult { Ok(Self { reader: csv::CsvReader::new(&separator, &enclosure, &escape, with_header, empty_to_null, remove_bom)?, - columns: None, + columns: csv::columns::CsvColumns::default(), }) } @@ -127,7 +121,7 @@ impl RustCSVReaderNative { pub fn next(&mut self, batch_size: i64) -> PhpResult { let mut zv = Zval::new(); - zv.set_hashtable(self.reader.next(csv_batch_size(batch_size)?)?); + zv.set_hashtable(self.reader.next(batch_columns::batch_size_of(batch_size, "CSV")?)?); Ok(zv) } @@ -136,7 +130,7 @@ impl RustCSVReaderNative { /// `finish()`, else null. Refusals are `RowsBuilder::appendRows()`'s, row indexes relative to the batch. #[php(name = "nextColumns")] pub fn next_columns(&mut self, schema: &Zval, batch_size: i64) -> PhpResult { - csv::columns::next_columns(&mut self.reader, &mut self.columns, schema, csv_batch_size(batch_size)?) + csv::columns::next_columns(&mut self.reader, &mut self.columns, schema, batch_columns::batch_size_of(batch_size, "CSV")?) } } @@ -196,6 +190,7 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { .class::() .class::() .class::() + .class::() .class::() .class::() .class::() diff --git a/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt new file mode 100644 index 0000000000..c6d001b27c --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt @@ -0,0 +1,221 @@ +--TEST-- +NativeJsonReader reads random valid JSON, whole or a byte at a time, into the frames or refusals of PhpJsonOpenSource, through either backend +--SKIPIF-- + +--FILE-- +}> + */ +function json_read_pool(): array +{ + $u = '\\' . 'u'; + $ints = ['1', '-0', '42', '9223372036854775807', '-9223372036854775808', '"42"', '1E2', 'null', '!9223372036854775808', '!"x"', '!1.5', '!true', '![1]']; + $strings = ['"a"', "\"{$u}00e9\"", "\"{$u}d83d{$u}de00\"", '"a\/b"', '""', '"tab\there"', '5', '-0.0', 'true', 'null', '![1]', '!{"a":1}']; + $person = type_structure([ + 'id' => structure_element('id', type_integer()), + 'name' => structure_element('name', type_optional(type_string()), optional: true), + ]); + $people = ['{"id":1,"name":"a"}', '{"id":1}', '{"id":"1","name":null}', '{"id":1,"name":"a","extra":[1]}', '{"id":1,"id":2}', '{"name":"b","id":3}', 'null', '!{"name":"a"}', '!{"id":1,"name":[5]}', '![1,"a"]', '!"x"']; + + return [ + [static fn(string $name): object => int_schema($name), $ints], + [static fn(string $name): object => int_schema($name, nullable: true), $ints], + [static fn(string $name): object => float_schema($name), ['0.1', '-0.0', '1e400', '-1e400', '1e-400', '1E2', '5', '-0', '"3.14"', 'null', '!"abc"', '![1]']], + [static fn(string $name): object => bool_schema($name), ['true', 'false', '"true"', '"off"', '"yes"', '1', '0', 'null', '!"x"', '![1]']], + [static fn(string $name): object => str_schema($name), $strings], + [static fn(string $name): object => str_schema($name, nullable: true), $strings], + [static fn(string $name): object => datetime_schema($name), ['"2026-01-02T03:04:05Z"', '"2026-01-02 03:04:05"', '"2026-01-02T03:04:05.123456+02:00"', 'null', '!"@1700000000"', '!"not a date"', '![1]']], + [static fn(string $name): object => date_schema($name), ['"2026-01-02"', '"2026-01-02T10:00:00Z"', 'null', '!"x"', '![1]']], + [static fn(string $name): object => uuid_schema($name), ['"6c4b5d1e-4f2a-4b8e-9c3d-2e1f0a9b8c7d"', 'null', '!"6C4B5D1E-4F2A-4B8E-9C3D-2E1F0A9B8C7D"', '!"6c4b5d1e"', '!1']], + [static fn(string $name): object => json_schema($name), ['{"a":1}', '{"a":1.0,"b":"\/"}', '[1,2]', '[]', '{}', '"{\"a\":1}"', "{\"{$u}00e9\":\"{$u}d83d{$u}de00\"}", 'null', '!"x"', '!1']], + [static fn(string $name): object => list_schema($name, type_list(type_integer())), ['[1,2]', '[]', '["1"]', '{"0":1,"1":2}', 'null', '!["x"]', '![1,null]', '!5']], + [static fn(string $name): object => map_schema($name, type_map(type_string(), type_integer())), ['{"a":1,"b":2}', '{"a":1,"a":"2"}', '{}', "{\"{$u}00e9\":3}", 'null', '!{"a":"x"}', '!5']], + [static fn(string $name): object => map_schema($name, type_map(type_integer(), type_string())), ['{"1":"a","2":"b"}', '["a","b"]', '{"-1":"y","2":"a","2":"b"}', 'null', '!{"a":"b"}', '!{"01":"x"}', '!5']], + [static fn(string $name): object => structure_schema($name, $person), $people], + [static fn(string $name): object => list_schema($name, type_list($person)), ['[' . $people[0] . ',' . $people[1] . ']', '[' . $people[4] . ',' . $people[5] . ']', '[]', 'null', '![' . ltrim($people[7], '!') . ']']], + [static fn(string $name): object => map_schema($name, type_map(type_string(), type_list(type_integer()))), ['{"a":[1,2],"b":[]}', '{"a":["2"],"a":[3]}', 'null', '!{"a":[1,"x"]}', '!{"a":[[1]]}']], + [static fn(string $name): object => structure_schema($name, type_structure(['tags' => structure_element('tags', type_list(type_map(type_string(), type_integer())))])), ['{"tags":[{"a":1},{"b":2,"b":3}]}', '{"tags":[]}', '{"tags":[{"a":"1"}]}', 'null', '!{"tags":[{"a":[1]}]}', '!{}']], + ]; +} + +/** + * A member name as JSON text, sometimes with escapes that unescape to the same name. + */ +function json_read_key(string $name): string +{ + return match (mt_rand(0, 3)) { + 0 => '"' . implode('', array_map(static fn(string $char): string => sprintf('\\u%04x', ord($char)), str_split($name))) . '"', + default => '"' . $name . '"', + }; +} + +/** + * Draws from a column's pool: a refusing draw ("!") only when $refuse, a null or an absence only when $nullable or + * $refuse. + * + * @param list $pool + */ +function json_read_draw(array $pool, bool $nullable, bool $refuse): string +{ + $draws = array_values(array_filter($pool, static fn(string $draw): bool => $refuse || (!str_starts_with($draw, '!') && ($nullable || $draw !== 'null')))); + + return ltrim($draws[mt_rand(0, count($draws) - 1)], '!'); +} + +/** + * @param list, bool}> $columns name, draw pool and nullability of every column + */ +function json_read_record(array $columns, bool $array, bool $refuse): string +{ + if ($array) { + return '[' . implode(', ', array_map(static fn(array $column): string => json_read_draw($column[1], $column[2], $refuse), $columns)) . ']'; + } + + $members = []; + + foreach ($columns as [$name, $pool, $nullable]) { + $draw = static fn(): string => json_read_draw($pool, $nullable, $refuse); + + // a duplicated key keeps its last value, so both stay in one group, in order + match (($nullable || $refuse) ? mt_rand(0, 9) : mt_rand(1, 9)) { + 0 => null, + 1 => $members[] = json_read_key($name) . ':' . json_read_draw($pool, true, true) . ', ' . json_read_key($name) . ':' . $draw(), + default => $members[] = json_read_key($name) . ' : ' . $draw(), + }; + + if (mt_rand(0, 9) === 0) { + $members[] = '"extra' . '\\' . 'u00e9" :' . json_read_draw($pool, true, true); + } + } + + shuffle($members); + + return '{' . implode(",\n ", $members) . '}'; +} + +$frames = static function (iterable $batches, object $backend): array { + $frames = []; + + foreach ($batches as $batch) { + foreach ($batch->columns() as $column) { + if ($backend instanceof PhpBackend && $column instanceof NativeColumn) { + return ['a NativeColumn survived PhpBackend']; + } + } + + $frames[] = bin2hex($batch->encodeFrame()); + } + + return $frames; +}; +// NativeJsonOpenSource::batches() over chunks of $chunk bytes +$bytes = static function (string $raw, bool $lines, Schema $schema, object $backend, int $chunk): Generator { + $reader = new NativeJsonReader($lines, 'memory://phpt.json'); + $adopted = static function (Rows $batch) use ($schema, $backend): Rows { + $columns = []; + + foreach ($schema->definitions() as $name => $definition) { + $columns[$name] = $backend->adopt($definition, $batch->columns()[$name]); + } + + return Rows::fromColumns($schema, $columns, $batch->count()); + }; + + foreach (str_split($raw, $chunk) as $piece) { + $reader->feed($piece); + + while (($batch = $reader->nextColumns($schema, 2)) !== null) { + yield $adopted($batch); + } + } + + $reader->finish(); + + while (($batch = $reader->nextColumns($schema, 2)) !== null) { + yield $adopted($batch); + } +}; + +mt_srand(10); +$pool = json_read_pool(); +$cases = 0; +$identical = 0; +$refused = 0; +$nulls = 0; + +for ($t = 0; $t < 400; $t++) { + $array = mt_rand(0, 4) === 0; + $columns = []; + $definitions = []; + + for ($c = mt_rand(1, 4) - 1; $c >= 0; $c--) { + [$definition, $draws] = $pool[mt_rand(0, count($pool) - 1)]; + $name = $array ? (string) count($columns) : 'c' . count($columns); + $definitions[] = $definition($name); + $columns[] = [$name, $draws, end($definitions)->isNullable()]; + } + + $schema = schema(...$definitions); + $refuse = mt_rand(0, 3) === 0; + $records = []; + + for ($r = mt_rand(1, 5); $r > 0; $r--) { + $records[] = mt_rand(0, 9) === 0 ? ['{}', '[ ]'][mt_rand(0, 1)] : json_read_record($columns, $array, $refuse); + } + + foreach ([true, false] as $lines) { + $raw = $lines + ? implode(["\n", "\r\n", "\n \n"][mt_rand(0, 2)], array_map(static fn(string $record): string => str_replace("\n", '', $record), $records)) . ["\n", ''][mt_rand(0, 1)] + : "[\n" . implode(" ,\n\t", $records) . "\n]\n"; + $filesystem = memory_filesystem(); + $stream = $filesystem->writeTo(path('memory://phpt.json')); + $stream->append($raw); + $stream->close(); + $source = new SourceFile(path('memory://phpt.json')); + $reader = new JsonFileReader($filesystem, $lines ? JsonFormat::Lines : JsonFormat::Document, null, false, [$source]); + $php = outcome(static fn(): array => $frames((new PhpJsonOpenSource($reader, $source))->batches($schema, 2, new PhpBackend()), new PhpBackend())); + + foreach ([new DefaultBackend(), new PhpBackend()] as $backend) { + $natives = [ + 'whole' => outcome(static fn(): array => $frames((new NativeJsonOpenSource(new StringSourceStream(path('memory://phpt.json'), $raw), new NativeJsonReader($lines, 'memory://phpt.json')))->batches($schema, 2, $backend), $backend)), + 'by byte' => outcome(static fn(): array => $frames($bytes($raw, $lines, $schema, $backend, 1), $backend)), + ]; + + foreach ($natives as $feed => $native) { + $cases++; + + if ($native !== $php) { + echo ($lines ? 'lines ' : 'document ') . "{$feed} " . get_class($backend) . ' ' . json_encode($raw) . "\n php: {$php}\n native: {$native}\n"; + + continue; + } + + $identical++; + $refused += refused($php) ? 1 : 0; + $nulls += str_contains($raw, 'null') ? 1 : 0; + } + } + } +} + +echo "{$identical} of {$cases} identical, {$refused} refused, {$nulls} with a null\n"; +?> +--EXPECT-- +3200 of 3200 identical, 600 refused, 936 with a null diff --git a/src/extension/flow-php-ext/tests/phpt/087_json_read_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/087_json_read_no_leaks.phpt new file mode 100644 index 0000000000..3c22bd3ef7 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/087_json_read_no_leaks.phpt @@ -0,0 +1,79 @@ +--TEST-- +NativeJsonReader reads, cast refusals and malformed refusals leak neither PHP memory nor native allocations +--SKIPIF-- + +--FILE-- + structure_element('id', type_integer()), + 'note' => structure_element('note', type_optional(type_string()), optional: true), + ])), +); +$valid = '{"id":1,"name":"aé","tags":["x","y"],"scores":{"a":1,"a":2},"owner":{"id":1}}'; +$read = static function (string $raw, bool $lines) use ($backend, $schema): void { + $open = new NativeJsonOpenSource(new StringSourceStream(path('memory://leak.json'), $raw), new NativeJsonReader($lines, 'memory://leak.json')); + + try { + foreach ($open->batches($schema, 2, $backend) as $batch) { + $batch->toArray(); + } + } finally { + $open->close(); + } +}; +$refused = static function (string $raw, bool $lines, string $class) use ($read): void { + try { + $read($raw, $lines); + throw new LogicException('a refused read was accepted'); + } catch (Throwable $e) { + if (!$e instanceof $class) { + throw $e; + } + } +}; +$cycle = static function () use ($read, $refused, $valid): void { + $read("[{$valid},{$valid},\n{$valid}]", false); + $read("{$valid}\n{$valid}\n\n{$valid}", true); + $read('[{"id":"2","tags":"[\"json\"]","scores":[],"owner":{"id":"3","note":null}}]', false); + $refused('[' . $valid . ',{"id":"x","tags":[],"scores":{},"owner":{"id":1}}]', false, SchemaMismatchException::class); + $refused('{"id":1,"tags":[1,[2]],"scores":{},"owner":{"note":"n"}}', true, SchemaMismatchException::class); + $refused($valid . "\n" . $valid . '}', true, RuntimeException::class); + $refused('[' . $valid . ',' . $valid, false, RuntimeException::class); + $refused($valid . "\n5", true, RuntimeException::class); +}; + +for ($i = 0; $i < 10; $i++) { + $cycle(); +} +gc_collect_cycles(); +$baseline = memory_get_usage(false); +$baselineRust = $backend->allocatedBytes(); + +for ($i = 0; $i < 100; $i++) { + $cycle(); +} +gc_collect_cycles(); + +var_dump(memory_get_usage(false) <= $baseline); +var_dump($backend->allocatedBytes() === $baselineRust); +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/088_json_read_streaming.phpt b/src/extension/flow-php-ext/tests/phpt/088_json_read_streaming.phpt new file mode 100644 index 0000000000..4711be532e --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/088_json_read_streaming.phpt @@ -0,0 +1,80 @@ +--TEST-- +NativeJsonOpenSource reads a JSON array and JSON lines in memory independent of the record count: one chunk, the largest record and one batch +--SKIPIF-- + +--FILE-- + 0 ? ($lines ? "\n" : ",\n") : '') . implode($lines ? "\n" : ",\n", $chunk)); + } + + fwrite($handle, $lines ? "\n" : "]\n"); + fclose($handle); +}; +// rows read, PHP peak over the read, the most native bytes held while a batch was +$read = static function (string $file, bool $lines) use ($backend, $schema): array { + gc_collect_cycles(); + memory_reset_peak_usage(); + $php = memory_get_usage(false); + $rust = $backend->allocatedBytes(); + $held = 0; + $rows = 0; + $open = new NativeJsonOpenSource((new NativeLocalFilesystem())->readFrom(path($file)), new NativeJsonReader($lines, $file)); + + foreach ($open->batches($schema, 1000, $backend) as $batch) { + $rows += $batch->count(); + $held = max($held, $backend->allocatedBytes() - $rust); + } + + $open->close(); + unset($batch, $open); + + return [$rows, memory_get_peak_usage(false) - $php, $held]; +}; + +// the Makefile phpt runner has no CLEAN section, so the files are removed here +foreach (['array' => false, 'lines' => true] as $label => $lines) { + $file = sys_get_temp_dir() . "/flow_php_088_{$label}.json"; + $measured = []; + + try { + foreach ([20_000, 200_000] as $records) { + $write($file, $records, $lines); + $measured[$records] = $read($file, $lines); + } + } finally { + @unlink($file); + } + + [$rows20, $php20, $rust20] = $measured[20_000]; + [$rows200, $php200, $rust200] = $measured[200_000]; + + echo "{$label}: {$rows20} and {$rows200} rows, PHP peak ", $php200 <= $php20 + NativeJsonOpenSource::CHUNK ? 'bounded' : "{$php20} -> {$php200}", + ', native held ', $rust200 <= $rust20 + NativeJsonOpenSource::CHUNK ? 'bounded' : "{$rust20} -> {$rust200}", "\n"; +} +?> +--EXPECT-- +array: 20000 and 200000 rows, PHP peak bounded, native held bounded +lines: 20000 and 200000 rows, PHP peak bounded, native held bounded diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json index 07a0da8ee6..1237f82819 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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":573,"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}],"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":582,"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":592,"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":599,"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":605,"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":617,"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":623,"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":629,"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":635,"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":641,"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":647,"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":656,"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":662,"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":671,"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":677,"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":684,"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":690,"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":696,"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":705,"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":711,"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":722,"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":731,"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":740,"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":746,"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":755,"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":765,"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":774,"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":780,"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":786,"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":794,"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":807,"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":813,"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":819,"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":829,"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":838,"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":847,"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":853,"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":866,"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":875,"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":884,"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":890,"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":899,"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":905,"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":911,"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":917,"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":923,"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":935,"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":962,"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":992,"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":998,"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":1004,"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":1010,"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":1016,"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":1022,"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":1028,"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":1034,"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":1040,"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":1046,"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":1052,"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":1058,"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":"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":1064,"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":1070,"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":1076,"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":1082,"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":1092,"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":1102,"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":1112,"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":1122,"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":1132,"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":1138,"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":1147,"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":1156,"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":1169,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."}],"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":1222,"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":1228,"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":1234,"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":1240,"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::..."},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"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":1250,"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":1256,"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":1262,"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":1268,"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":1274,"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":1280,"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":1286,"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":1292,"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":1298,"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":1304,"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":1310,"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":1316,"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":"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":1322,"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":1328,"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":1334,"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":1340,"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":1346,"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":1357,"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":1366,"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":1375,"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":1387,"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":1397,"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":1406,"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":1412,"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":1418,"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":1427,"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":1440,"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":1449,"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":1455,"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":1464,"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":1470,"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":1476,"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":1482,"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":1496,"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":1510,"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":1528,"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":1534,"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":1540,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1550,"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":1556,"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":1562,"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":1568,"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":1574,"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":1580,"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":1586,"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":1599,"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":1610,"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":1616,"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":1629,"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":1662,"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":1714,"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":1720,"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":1726,"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":1732,"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":1738,"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":1744,"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":1750,"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":1756,"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":1762,"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":1768,"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":1777,"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":1787,"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":1793,"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":1802,"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":1812,"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":1818,"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":1827,"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":1833,"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":1842,"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":1848,"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":1857,"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":1863,"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":1869,"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":1875,"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":1881,"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":1887,"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":1893,"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":1904,"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":1910,"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":1919,"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":1930,"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":1941,"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":1951,"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":1985,"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":1993,"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":2002,"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":2010,"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":2027,"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":2044,"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":2061,"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":2067,"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":2073,"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":2083,"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":2092,"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":2098,"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":2104,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":573,"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}],"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":582,"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":592,"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":599,"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":605,"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":617,"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":623,"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":629,"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":635,"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":641,"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":647,"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":656,"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":662,"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":671,"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":677,"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":684,"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":690,"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":696,"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":705,"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":711,"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":722,"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":731,"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":740,"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":746,"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":755,"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":765,"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":774,"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":780,"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":786,"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":794,"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":807,"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":813,"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":819,"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":829,"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":838,"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":847,"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":853,"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":866,"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":875,"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":884,"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":890,"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":899,"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":905,"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":911,"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":917,"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":923,"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":935,"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":962,"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":992,"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":998,"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":1004,"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":1010,"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":1016,"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":1022,"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":1028,"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":1034,"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":1040,"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":1046,"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":1052,"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":1058,"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":"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":1064,"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":1070,"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":1076,"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":1082,"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":1092,"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":1102,"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":1112,"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":1122,"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":1132,"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":1138,"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":1147,"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":1156,"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":1169,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."}],"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":1221,"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":1227,"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":1233,"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":1239,"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::..."},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"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":1249,"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":1255,"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":1261,"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":1267,"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":1273,"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":1279,"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":1285,"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":1291,"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":1297,"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":1303,"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":1309,"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":1315,"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":"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":1321,"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":1327,"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":1333,"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":1339,"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":1345,"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":1356,"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":1365,"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":1374,"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":1386,"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":1396,"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":1405,"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":1411,"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":1417,"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":1426,"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":1439,"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":1448,"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":1454,"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":1463,"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":1469,"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":1475,"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":1481,"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":1495,"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":1509,"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":1527,"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":1533,"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":1539,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1549,"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":1555,"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":1561,"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":1567,"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":1573,"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":1579,"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":1585,"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":1598,"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":1609,"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":1615,"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":1628,"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":1661,"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":1713,"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":1719,"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":1725,"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":1731,"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":1737,"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":1743,"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":1749,"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":1755,"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":1761,"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":1767,"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":1776,"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":1786,"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":1792,"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":1801,"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":1811,"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":1817,"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":1826,"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":1832,"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":1841,"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":1847,"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":1856,"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":1862,"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":1868,"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":1874,"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":1880,"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":1886,"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":1892,"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":1903,"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":1909,"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":1918,"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":1929,"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":1940,"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":1950,"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":1984,"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":1992,"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":2001,"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":2009,"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":2026,"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":2043,"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":2060,"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":2066,"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":2072,"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":2082,"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":2091,"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":2097,"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":2103,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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 From 481c7af51196773672e66d3f9355e23aa8a7a990 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Fri, 2 Oct 2026 10:46:51 +0200 Subject: [PATCH 13/21] feat(flow-php/arrow-ext): arrow-ext owns Parquet, flow_php reads it through the Arrow C Data Interface - Parquet core and lib surface moved from flow_php into arrow-ext, old Reader/Writer removed - ArrowParquetEngine runs on arrow-ext again, deprecation undone - flow_php ETL reader/writer exchange batches with arrow-ext via C Data, imports counted in allocatedBytes() - native ETL lane needs both extensions, flow_php alone uses the PHP engine - lib writer on typed arrow-rs builders, rows checked whole before appending --- .github/workflows/job-arrow-extension.yml | 12 +- .github/workflows/job-flow-php-extension.yml | 9 +- .nix/pkgs/php-arrow-ext/package.nix | 2 +- .nix/pkgs/php-flow-php-ext/package.nix | 2 +- .../components/extensions/arrow-ext.md | 259 +-- .../components/extensions/flow-php-ext.md | 54 +- documentation/components/libs/parquet.md | 10 +- .../installation/packages/arrow-ext.md | 6 - documentation/upgrading.md | 41 +- src/adapter/etl-adapter-parquet/composer.json | 1 + .../Parquet/NativeParquetOpenSource.php | 20 +- .../Adapter/Parquet/NativeParquetOpener.php | 21 +- .../ETL/Adapter/Parquet/ParquetOpeners.php | 1 + .../Tests/Context/ParquetFilesContext.php | 8 +- .../Parquet/Tests/Integration/ParquetTest.php | 23 +- .../Tests/Unit/NativeParquetOpenSinkTest.php | 12 +- .../Unit/NativeParquetOpenSourceTest.php | 17 +- .../Tests/Unit/NativeParquetOpenerTest.php | 3 +- .../Parquet/Tests/Unit/ParquetOpenersTest.php | 30 +- src/extension/arrow-ext/Cargo.lock | 3 + src/extension/arrow-ext/Cargo.toml | 7 +- src/extension/arrow-ext/Makefile | 18 +- src/extension/arrow-ext/build.rs | 21 + src/extension/arrow-ext/composer.json | 3 +- .../arrow-ext/examples/generate_fixtures.rs | 388 ---- .../arrow-ext/php/Flow/Arrow/ArrowBatch.php | 45 + .../arrow-ext/php/Flow/Arrow/ArrowSchema.php | 32 + .../php/Flow/Arrow/Parquet/BatchReader.php | 48 + .../php/Flow/Arrow/Parquet/ColumnsReader.php} | 14 +- .../php/Flow/Arrow/Parquet/Exception.php | 15 - .../php/Flow/Arrow/Parquet/ParquetFile.php} | 18 +- .../php/Flow/Arrow/Parquet/Reader.php | 61 - .../php/Flow/Arrow/Parquet/RowsWriter.php} | 25 +- .../php/Flow/Arrow/Parquet/Writer.php | 45 - src/extension/arrow-ext/src/alloc.rs | 61 + src/extension/arrow-ext/src/exception.rs | 14 + src/extension/arrow-ext/src/lib.rs | 26 +- src/extension/arrow-ext/src/parquet/batch.rs | 264 +++ .../src/parquet/canonical.rs | 56 +- src/extension/arrow-ext/src/parquet/cells.rs | 1098 +++++++++++ .../src/parquet/error.rs | 0 .../arrow-ext/src/parquet/exception.rs | 25 - .../src/parquet/fetch.rs | 0 .../src/parquet/footer.rs | 0 .../src/parquet/library.rs | 280 +-- src/extension/arrow-ext/src/parquet/mod.rs | 19 +- .../src/parquet/options.rs | 0 .../src/parquet/read.rs | 0 src/extension/arrow-ext/src/parquet/reader.rs | 424 ----- .../src/parquet/sink.rs | 2 +- .../src/parquet/source.rs | 2 +- .../arrow-ext/src/parquet/type_converter.rs | 1608 ----------------- .../src/parquet/write.rs | 0 src/extension/arrow-ext/src/parquet/writer.rs | 269 --- src/extension/arrow-ext/src/php.rs | 396 ++++ src/extension/arrow-ext/src/render.rs | 82 + src/extension/arrow-ext/src/stream/mod.rs | 2 - .../src/stream/php_destination_stream.rs | 53 - .../arrow-ext/src/stream/php_source_stream.rs | 104 -- .../{flow-php-ext => arrow-ext}/src/thrift.rs | 43 +- src/extension/arrow-ext/src/values.rs | 241 +++ .../tests/fixtures/all_flat_types.parquet | Bin 4837 -> 0 bytes .../tests/fixtures/decimals_fixed_len.parquet | Bin 1639 -> 0 bytes .../tests/fixtures/deeply_nested.parquet | Bin 1161 -> 0 bytes .../arrow-ext/tests/fixtures/nested.parquet | Bin 2290 -> 0 bytes .../arrow-ext/tests/fixtures/simple.parquet | Bin 492 -> 0 bytes .../tests/phpt/001_extension_loaded.phpt | 34 +- .../tests/phpt/002_reader_construct.phpt | 35 - .../tests/phpt/003_reader_null_size.phpt | 35 - .../tests/phpt/004_reader_schema.phpt | 47 - .../tests/phpt/005_reader_metadata.phpt | 41 - .../tests/phpt/006_reader_flat_columns.phpt | 51 - .../tests/phpt/007_reader_all_flat_types.phpt | 106 -- .../phpt/008_reader_column_projection.phpt | 56 - .../tests/phpt/009_reader_exhausted.phpt | 47 - .../arrow-ext/tests/phpt/010_reader_list.phpt | 57 - .../tests/phpt/011_reader_struct.phpt | 57 - .../arrow-ext/tests/phpt/012_reader_map.phpt | 54 - .../tests/phpt/013_reader_deeply_nested.phpt | 66 - .../tests/phpt/014_reader_null_nested.phpt | 62 - .../tests/phpt/015_writer_construct.phpt | 44 - .../tests/phpt/016_writer_flat_columns.phpt | 71 - .../tests/phpt/017_writer_roundtrip.phpt | 144 -- .../tests/phpt/018_writer_compression.phpt | 87 - .../tests/phpt/019_writer_null_values.phpt | 108 -- .../arrow-ext/tests/phpt/020_writer_list.phpt | 83 - .../tests/phpt/021_writer_struct.phpt | 79 - .../arrow-ext/tests/phpt/022_writer_map.phpt | 76 - .../tests/phpt/023_writer_deeply_nested.phpt | 97 - .../phpt/024_writer_roundtrip_all_types.phpt | 115 -- .../025_writer_options_row_group_size.phpt | 63 - .../026_writer_options_compression_level.phpt | 73 - .../phpt/027_writer_options_per_column.phpt | 69 - .../028_writer_options_writer_version.phpt | 67 - .../029_reader_options_unknown_ignored.phpt | 58 - .../tests/phpt/030_reader_batch_size.phpt | 67 - ...1_reader_batch_size_across_row_groups.phpt | 72 - .../phpt/032_reader_batch_size_null.phpt | 62 - .../tests/phpt/033_writer_int_overflow.phpt | 60 - .../tests/phpt/034_writer_float_overflow.phpt | 38 - ...6_interfaces_and_exception_registered.phpt | 6 +- ...037_writer_roundtrip_nested_uuid_json.phpt | 94 - .../phpt/039_reader_pre_epoch_timestamps.phpt | 64 - .../tests/phpt/040_reader_decimal256.phpt | 51 - .../tests/phpt/041_writer_date_lanes.phpt | 61 - .../tests/phpt/042_writer_temporal_units.phpt | 74 - .../phpt/043_writer_decimal_rounding.phpt | 53 - ...44_reader_schema_units_and_decimal256.phpt | 67 - .../phpt/045_parquet_lib_read_parity.phpt} | 41 +- .../phpt/046_parquet_lib_write_parity.phpt} | 12 +- .../047_parquet_footer_thrift_parity.phpt} | 37 +- .../tests/phpt/048_parquet_lib_no_leaks.phpt} | 20 +- .../049_parquet_write_columns_parity.phpt} | 6 +- .../phpt/050_parquet_batch_roundtrip.phpt | 92 + .../arrow-ext/tests/phpt/bootstrap.php | 32 + src/extension/flow-php-ext/Cargo.lock | 146 +- src/extension/flow-php-ext/Cargo.toml | 3 +- src/extension/flow-php-ext/Makefile | 8 +- src/extension/flow-php-ext/composer.json | 2 +- .../crates/flow-batch-frame/src/kind.rs | 1 + .../Adapter/Parquet/NativeParquetReader.php | 15 +- .../Adapter/Parquet/NativeParquetWriter.php | 12 +- .../php/Flow/ETL/Column/NativeArrowBatch.php | 46 + src/extension/flow-php-ext/src/alloc.rs | 16 +- src/extension/flow-php-ext/src/arrow_c.rs | 429 +++++ src/extension/flow-php-ext/src/ctx.rs | 14 - src/extension/flow-php-ext/src/lib.rs | 6 +- .../flow-php-ext/src/parquet/cells.rs | 683 ------- src/extension/flow-php-ext/src/parquet/etl.rs | 176 +- src/extension/flow-php-ext/src/parquet/mod.rs | 14 +- src/extension/flow-php-ext/src/render.rs | 99 +- .../tests/phpt/068_parquet_read_parity.phpt | 23 +- .../tests/phpt/069_parquet_offset_limit.phpt | 20 +- .../phpt/070_parquet_write_roundtrip.phpt | 24 +- .../tests/phpt/071_parquet_no_leaks.phpt | 13 +- .../phpt/072_parquet_allocations_counted.phpt | 18 +- .../phpt/089_parquet_arrow_c_no_leaks.phpt | 94 + .../090_parquet_schema_refused_at_open.phpt | 45 + ...091_parquet_canonical_layout_contract.phpt | 86 + .../flow-php-ext/tests/phpt/bootstrap.php | 28 + src/lib/parquet-viewer/composer.json | 3 + src/lib/parquet/composer.json | 4 +- .../Parquet/Engine/AdaptiveParquetEngine.php | 2 +- .../Engine/Arrow/DestinationStreamAdapter.php | 22 - .../Engine/Arrow/SourceStreamAdapter.php | 26 - .../Parquet/Engine/ArrowParquetEngine.php | 61 +- .../Parquet/Engine/ArrowParquetFileReader.php | 127 +- .../Parquet/Engine/ArrowParquetFileWriter.php | 78 +- .../Engine/NativeParquetFileReader.php | 109 -- .../Engine/NativeParquetFileWriter.php | 58 - .../Engine/ArrowParquetEngineReadTest.php | 4 +- .../Engine/ArrowParquetEngineWriteTest.php | 4 +- ...est.php => ArrowParquetFileReaderTest.php} | 20 +- .../Integration/Engine/CrossEngineTest.php | 4 +- .../Integration/Engine/EngineParityTest.php | 4 +- .../Engine/NativeLibParityTest.php | 8 +- .../Engine/NativeLibRegressionTest.php | 4 +- .../Engine/NativeLibWriteParityTest.php | 2 +- .../IO/ParquetIntegrationTestCase.php | 4 +- .../Integration/IO/SimpleTypesWritingTest.php | 2 +- .../Unit/Engine/AdaptiveParquetEngineTest.php | 12 +- .../Arrow/DestinationStreamAdapterTest.php | 37 - .../Engine/Arrow/SourceStreamAdapterTest.php | 40 - .../Unit/Engine/ArrowParquetEngineTest.php | 57 +- .../Engine/ArrowParquetFileWriterTest.php | 110 +- .../Engine/NativeParquetFileWriterTest.php | 311 ---- .../Flow/Parquet/Tests/Unit/ReaderTest.php | 2 +- .../Flow/Parquet/Tests/Unit/WriterTest.php | 4 +- 168 files changed, 4161 insertions(+), 8313 deletions(-) delete mode 100644 src/extension/arrow-ext/examples/generate_fixtures.rs create mode 100644 src/extension/arrow-ext/php/Flow/Arrow/ArrowBatch.php create mode 100644 src/extension/arrow-ext/php/Flow/Arrow/ArrowSchema.php create mode 100644 src/extension/arrow-ext/php/Flow/Arrow/Parquet/BatchReader.php rename src/extension/{flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetColumnsReader.php => arrow-ext/php/Flow/Arrow/Parquet/ColumnsReader.php} (52%) delete mode 100644 src/extension/arrow-ext/php/Flow/Arrow/Parquet/Exception.php rename src/extension/{flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetFile.php => arrow-ext/php/Flow/Arrow/Parquet/ParquetFile.php} (64%) delete mode 100644 src/extension/arrow-ext/php/Flow/Arrow/Parquet/Reader.php rename src/extension/{flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetRowsWriter.php => arrow-ext/php/Flow/Arrow/Parquet/RowsWriter.php} (63%) delete mode 100644 src/extension/arrow-ext/php/Flow/Arrow/Parquet/Writer.php create mode 100644 src/extension/arrow-ext/src/alloc.rs create mode 100644 src/extension/arrow-ext/src/exception.rs create mode 100644 src/extension/arrow-ext/src/parquet/batch.rs rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/canonical.rs (96%) create mode 100644 src/extension/arrow-ext/src/parquet/cells.rs rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/error.rs (100%) delete mode 100644 src/extension/arrow-ext/src/parquet/exception.rs rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/fetch.rs (100%) rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/footer.rs (100%) rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/library.rs (62%) rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/options.rs (100%) rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/read.rs (100%) delete mode 100644 src/extension/arrow-ext/src/parquet/reader.rs rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/sink.rs (96%) rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/source.rs (99%) delete mode 100644 src/extension/arrow-ext/src/parquet/type_converter.rs rename src/extension/{flow-php-ext => arrow-ext}/src/parquet/write.rs (100%) delete mode 100644 src/extension/arrow-ext/src/parquet/writer.rs create mode 100644 src/extension/arrow-ext/src/php.rs create mode 100644 src/extension/arrow-ext/src/render.rs delete mode 100644 src/extension/arrow-ext/src/stream/php_destination_stream.rs delete mode 100644 src/extension/arrow-ext/src/stream/php_source_stream.rs rename src/extension/{flow-php-ext => arrow-ext}/src/thrift.rs (88%) create mode 100644 src/extension/arrow-ext/src/values.rs delete mode 100644 src/extension/arrow-ext/tests/fixtures/all_flat_types.parquet delete mode 100644 src/extension/arrow-ext/tests/fixtures/decimals_fixed_len.parquet delete mode 100644 src/extension/arrow-ext/tests/fixtures/deeply_nested.parquet delete mode 100644 src/extension/arrow-ext/tests/fixtures/nested.parquet delete mode 100644 src/extension/arrow-ext/tests/fixtures/simple.parquet delete mode 100644 src/extension/arrow-ext/tests/phpt/002_reader_construct.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/003_reader_null_size.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/004_reader_schema.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/005_reader_metadata.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/006_reader_flat_columns.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/007_reader_all_flat_types.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/008_reader_column_projection.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/009_reader_exhausted.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/010_reader_list.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/011_reader_struct.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/012_reader_map.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/013_reader_deeply_nested.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/014_reader_null_nested.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/015_writer_construct.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/016_writer_flat_columns.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/017_writer_roundtrip.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/018_writer_compression.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/019_writer_null_values.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/020_writer_list.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/021_writer_struct.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/022_writer_map.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/023_writer_deeply_nested.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/024_writer_roundtrip_all_types.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/025_writer_options_row_group_size.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/026_writer_options_compression_level.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/027_writer_options_per_column.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/028_writer_options_writer_version.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/029_reader_options_unknown_ignored.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/030_reader_batch_size.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/031_reader_batch_size_across_row_groups.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/032_reader_batch_size_null.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/033_writer_int_overflow.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/034_writer_float_overflow.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/037_writer_roundtrip_nested_uuid_json.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/039_reader_pre_epoch_timestamps.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/040_reader_decimal256.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/041_writer_date_lanes.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/042_writer_temporal_units.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/043_writer_decimal_rounding.phpt delete mode 100644 src/extension/arrow-ext/tests/phpt/044_reader_schema_units_and_decimal256.phpt rename src/extension/{flow-php-ext/tests/phpt/073_parquet_lib_read_parity.phpt => arrow-ext/tests/phpt/045_parquet_lib_read_parity.phpt} (51%) rename src/extension/{flow-php-ext/tests/phpt/074_parquet_lib_write_parity.phpt => arrow-ext/tests/phpt/046_parquet_lib_write_parity.phpt} (56%) rename src/extension/{flow-php-ext/tests/phpt/075_parquet_footer_thrift_parity.phpt => arrow-ext/tests/phpt/047_parquet_footer_thrift_parity.phpt} (56%) rename src/extension/{flow-php-ext/tests/phpt/076_parquet_lib_no_leaks.phpt => arrow-ext/tests/phpt/048_parquet_lib_no_leaks.phpt} (59%) rename src/extension/{flow-php-ext/tests/phpt/083_parquet_write_columns_parity.phpt => arrow-ext/tests/phpt/049_parquet_write_columns_parity.phpt} (92%) create mode 100644 src/extension/arrow-ext/tests/phpt/050_parquet_batch_roundtrip.phpt create mode 100644 src/extension/arrow-ext/tests/phpt/bootstrap.php create mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Column/NativeArrowBatch.php create mode 100644 src/extension/flow-php-ext/src/arrow_c.rs delete mode 100644 src/extension/flow-php-ext/src/parquet/cells.rs create mode 100644 src/extension/flow-php-ext/tests/phpt/089_parquet_arrow_c_no_leaks.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/091_parquet_canonical_layout_contract.phpt delete mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/Arrow/DestinationStreamAdapter.php delete mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SourceStreamAdapter.php delete mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileReader.php delete mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileWriter.php rename src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/{NativeParquetFileReaderTest.php => ArrowParquetFileReaderTest.php} (84%) delete mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/DestinationStreamAdapterTest.php delete mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/SourceStreamAdapterTest.php delete mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/NativeParquetFileWriterTest.php diff --git a/.github/workflows/job-arrow-extension.yml b/.github/workflows/job-arrow-extension.yml index 31bea22951..1f134780ee 100644 --- a/.github/workflows/job-arrow-extension.yml +++ b/.github/workflows/job-arrow-extension.yml @@ -86,6 +86,12 @@ jobs: working-directory: src/extension/arrow-ext run: make build + - name: Install Composer Dependencies + uses: ./.github/actions/composer-install + with: + php-version: ${{ matrix.php }} + dependencies: locked + - name: Run PHPT tests working-directory: src/extension/arrow-ext run: make test @@ -98,12 +104,6 @@ jobs: echo "extension=arrow.so" | sudo tee -a "$(php -r 'echo php_ini_loaded_file();')" php -m | grep arrow - - name: Install Composer Dependencies - uses: ./.github/actions/composer-install - with: - php-version: ${{ matrix.php }} - dependencies: locked - - name: Run Parquet Integration Tests with Arrow run: just test --testsuite=lib-parquet-integration ${{ (matrix.php == '8.3' && runner.os == 'Linux') && '--coverage-clover=./var/phpunit/coverage/clover/coverage.xml' || '' }} diff --git a/.github/workflows/job-flow-php-extension.yml b/.github/workflows/job-flow-php-extension.yml index a0a3530b45..a99f97f359 100644 --- a/.github/workflows/job-flow-php-extension.yml +++ b/.github/workflows/job-flow-php-extension.yml @@ -45,7 +45,8 @@ jobs: ~/.cargo/registry ~/.cargo/git src/extension/flow-php-ext/target - key: ${{ runner.os }}-php${{ matrix.php }}-cargo-${{ hashFiles('src/extension/flow-php-ext/Cargo.lock') }} + src/extension/arrow-ext/target + key: ${{ runner.os }}-php${{ matrix.php }}-cargo-${{ hashFiles('src/extension/flow-php-ext/Cargo.lock', 'src/extension/arrow-ext/Cargo.lock') }} restore-keys: | ${{ runner.os }}-php${{ matrix.php }}-cargo- @@ -87,6 +88,10 @@ jobs: grep -q "version ? \"$expected\"" "$f" || { echo "$f: version literal must be $expected"; exit 1; } done + - name: Build arrow extension + working-directory: src/extension/arrow-ext + run: make build + - name: Build extension working-directory: src/extension/flow-php-ext run: make build @@ -103,7 +108,7 @@ jobs: - name: Run PHPT tests working-directory: src/extension/flow-php-ext - run: make test + run: make test ARROW_SO=../arrow-ext/ext/modules/arrow.so - name: Install extension and verify working-directory: src/extension/flow-php-ext diff --git a/.nix/pkgs/php-arrow-ext/package.nix b/.nix/pkgs/php-arrow-ext/package.nix index 0272a006de..32833f97a1 100644 --- a/.nix/pkgs/php-arrow-ext/package.nix +++ b/.nix/pkgs/php-arrow-ext/package.nix @@ -58,7 +58,7 @@ let doCheck = false; meta = with lib; { - description = "Apache Arrow PHP extension powered by Rust"; + description = "Apache Arrow and Parquet bindings for flow-php/parquet (Rust)"; license = licenses.mit; }; }; diff --git a/.nix/pkgs/php-flow-php-ext/package.nix b/.nix/pkgs/php-flow-php-ext/package.nix index ebc7bab5af..127977c554 100644 --- a/.nix/pkgs/php-flow-php-ext/package.nix +++ b/.nix/pkgs/php-flow-php-ext/package.nix @@ -58,7 +58,7 @@ let doCheck = false; meta = with lib; { - description = "Flow PHP native extension (Rust) - native column backend, CSV reader, Parquet reader and writer"; + description = "Flow PHP native extension (Rust) - native column backend, CSV/JSON readers, Parquet ETL through arrow-ext"; license = licenses.mit; }; }; diff --git a/documentation/components/extensions/arrow-ext.md b/documentation/components/extensions/arrow-ext.md index c5a054827d..440b119688 100644 --- a/documentation/components/extensions/arrow-ext.md +++ b/documentation/components/extensions/arrow-ext.md @@ -8,12 +8,6 @@ package: flow-php/arrow-ext [TOC] -> [!WARNING] -> **Deprecated.** Parquet through this extension is deprecated and will be removed; `flow-php/arrow-ext` is abandoned in -> favour of [flow-php/flow-php-ext](/documentation/components/extensions/flow-php-ext.md). Install the `flow_php` -> extension: `ArrowParquetEngine` uses it when it is loaded, and falls back to this extension with an -> `E_USER_DEPRECATED` notice otherwise. - [Apache Arrow](https://arrow.apache.org/) is a language-independent columnar memory format for flat and hierarchical data. The Arrow ecosystem provides high-performance implementations for common data operations - including I/O for formats like Parquet, CSV, JSON, and Arrow IPC - in C++, Rust, Java, Python, and other languages. @@ -40,13 +34,11 @@ The Arrow Rust crates offer additional I/O capabilities that are candidates for ## Features -- Read and write Apache Parquet files through PHP streaming interfaces -- Flat types: INT32, INT64, FLOAT, DOUBLE, BOOLEAN, STRING, BINARY, DATE, TIMESTAMP, TIME, DECIMAL +- Read and write Apache Parquet files over `flow-php/filesystem` streams, value for value as `PhpParquetEngine` - Nested types: LIST, STRUCT, MAP (arbitrarily nested) - Compression codecs: UNCOMPRESSED, SNAPPY, GZIP, ZSTD, LZ4_RAW, BROTLI -- Column projection for selective reads -- Configurable row group size, compression level, and writer version -- Columnar batch I/O for maximum throughput +- Column projection, offset and limit, read from one footer read +- Batches handed to other extensions through the [Arrow C Data Interface](https://arrow.apache.org/docs/format/CDataInterface.html) ## Requirements @@ -75,233 +67,71 @@ php -d extension=./ext/modules/arrow.so your_script.php ## Usage -### Implementing the Streaming Interfaces - -The extension operates on two PHP interfaces for I/O. You must provide implementations for your storage backend. - -**Source (reading):** +`ArrowParquetEngine` of the [parquet library](/documentation/components/libs/parquet.md) is this extension: ```php data = file_get_contents($path); - } - - public function read(int $length, int $offset): string - { - return substr($this->data, $offset, $length); - } - - public function size(): ?int - { - return strlen($this->data); - } -} +$reader = Reader::arrow(); +$writer = Writer::arrow(); ``` -**Destination (writing):** +### Classes ```php fh = fopen($path, 'wb'); - } - - public function append(string $data): self - { - fwrite($this->fh, $data); - return $this; - } - - public function __destruct() - { - fclose($this->fh); - } -} -``` - -### Reading Parquet Files +use Flow\Arrow\Parquet\{BatchReader, ColumnsReader, ParquetFile, RowsWriter}; +use Flow\Parquet\Engine\Arrow\{OptionsConverter, SchemaConverter}; +use Flow\Parquet\Options; -```php -readFrom(path('data.parquet'))); // one footer read +$file->rowsNumber(); +$file->thrift(); // Flow\Parquet\ThriftModel\FileMetaData -// Get schema and metadata -$schema = $reader->schema(); -$metadata = $reader->metadata(); +$columns = new ColumnsReader($file, ['id', 'name'], batchSize: 1_000, offset: null, limit: null); -// Read row groups (with optional column projection) -while ($batch = $reader->readRowGroup(['id', 'name'])) { - // $batch is ['column_name' => [values...], ...] - foreach ($batch['id'] as $i => $id) { - echo "$id: {$batch['name'][$i]}\n"; - } +while (($chunk = $columns->next()) !== null) { + // ['id' => [1, 2, ...], 'name' => ['a', 'b', ...]] } -$reader->close(); -``` - -### Writing Parquet Files - -```php - 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => true], -]; - -$writer = new Writer(new FileDestination('output.parquet'), $schema, 'SNAPPY'); -$writer->writeBatch([ - 'id' => [1, 2, 3], - 'name' => ['Alice', 'Bob', null], -]); -$writer->close(); +$writer = new RowsWriter( + $filesystem->writeTo(path('out.parquet')), + SchemaConverter::toExtension($schema), // Flow\Parquet\ParquetFile\Schema + 'SNAPPY', + OptionsConverter::toExtension(Options::default()), + batchSize: 1_000, +); +$writer->writeRows([['id' => 1, 'name' => 'a']]); +$writer->writeColumns(['id' => [2, 3], 'name' => ['b', null]]); +$writer->close(); // footer, then the stream closed + +$batches = new BatchReader($file, ['id', 'name'], batchSize: 1_000, offset: null, limit: null); +$batches->schema(); // Flow\Arrow\ArrowSchema +$batches->next(); // Flow\Arrow\ArrowBatch, null after the last ``` -### Schema Definition - -The schema is an array of column definitions. Each column has a `name`, `type`, and optional `optional` flag. - -| Type | PHP Read Value | Notes | -|-------------|-----------------------|-------------------------------------------------------------------------------------------------------------------| -| `BOOLEAN` | `bool` | | -| `INT32` | `int` | | -| `INT64` | `int` | | -| `FLOAT` | `float` | | -| `DOUBLE` | `float` | | -| `STRING` | `string` | | -| `BINARY` | `string` (raw bytes) | | -| `DATE` | `DateTimeImmutable` | `int` lane: days since epoch | -| `TIMESTAMP` | `DateTimeImmutable` | Keys `unit` (`MILLIS\|MICROS\|NANOS`, default `MICROS`) and `utc` (default `true`); `int` lane in the column unit | -| `TIME` | `DateInterval` | Key `unit` (`MILLIS\|MICROS\|NANOS`, default `MICROS`) | -| `DECIMAL` | `float` | Keys `precision`, `scale` | -| `UUID` | `string` | | -| `LIST` | `array` | Requires `children` key with 1 element | -| `STRUCT` | `array` (associative) | Requires `children` key with N elements | -| `MAP` | `array` (associative) | Requires `children` key with 2 elements (key + value) | - -**Nested schema example:** +Refusals are the `Flow\Parquet\Exception\*` the PHP engine throws; an exception the stream throws surfaces as itself. -```php - 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'tags', 'type' => 'LIST', 'optional' => true, 'children' => [ - ['name' => 'element', 'type' => 'STRING', 'optional' => true], - ]], - ['name' => 'address', 'type' => 'STRUCT', 'optional' => true, 'children' => [ - ['name' => 'street', 'type' => 'STRING', 'optional' => true], - ['name' => 'city', 'type' => 'STRING', 'optional' => true], - ]], - ['name' => 'metadata', 'type' => 'MAP', 'optional' => true, 'children' => [ - ['name' => 'key', 'type' => 'STRING', 'optional' => false], - ['name' => 'value', 'type' => 'STRING', 'optional' => true], - ]], -]; -``` - -### Writer Options - -Options are passed as the fourth argument to the `Writer` constructor: - -```php - 128 * 1024 * 1024, - 'WRITER_VERSION' => '2.0', -]); -``` - -| Option Key | Type | Description | -|---|---|---| -| `ROW_GROUP_SIZE_BYTES` | `int` | Maximum row group size in bytes | -| `COMPRESSION_LEVEL` | `int` | Compression level (codec-specific) | -| `WRITER_VERSION` | `string` | `"1.0"` or `"2.0"` | - -## API Reference +`ArrowBatch` (`BatchReader::next()`) carries one struct array: `arrowSchemaAddress()` (`FFI_ArrowSchema*`) and +`arrowArrayAddress()` (`FFI_ArrowArray*`). Its consumer, another extension, reads the schema by reference and moves the +array out. `RowsWriter::writeBatch()` takes the same pair from any extension's final internal class exposing both +methods, its children by writer column name. Userland cannot build either: the classes are final and their +constructors throw. ### Interfaces -**`Flow\Arrow\RandomAccessFile`** - -| Method | Parameters | Returns | Description | -|---|---|---|---| -| `read` | `int $length, int $offset` | `string` | Read `$length` bytes starting at `$offset` | -| `size` | - | `?int` | Return total size in bytes, or `null` if unknown | - -**`Flow\Arrow\OutputStream`** - -| Method | Parameters | Returns | Description | -|---|---|---|---| -| `append` | `string $data` | `self` | Append data to the output stream | - -### Classes - -**`Flow\Arrow\Parquet\Reader`** - -| Method | Parameters | Returns | Description | -|---|---|---|---| -| `__construct` | `RandomAccessFile $source, array $options = []` | - | Open a Parquet source for reading | -| `schema` | - | `array` | Return the file schema as nested arrays | -| `metadata` | - | `array` | Return file-level metadata (row count, row groups, key-value metadata) | -| `readRowGroup` | `?array $columns = null` | `?array` | Read next row group as columnar batch, or `null` when exhausted | -| `close` | - | `void` | Release resources | - -**`Flow\Arrow\Parquet\Writer`** - -| Method | Parameters | Returns | Description | -|---|---|---|---| -| `__construct` | `OutputStream $stream, array $schema, string $compression = 'SNAPPY', array $options = []` | - | Open a Parquet destination for writing | -| `writeBatch` | `array $batch` | `void` | Write a columnar batch (`['col' => [values...]]`) | -| `close` | - | `void` | Flush and finalize the Parquet file | - -**`Flow\Arrow\Parquet\Exception`** - -Extends `\RuntimeException`. Thrown on all Parquet read/write errors originating from the Rust layer. - -## Error Handling - -```php -readRowGroup()) { - // process batch - } - $reader->close(); -} catch (Exception $e) { - echo "Parquet error: " . $e->getMessage(); -} -``` +`Flow\Arrow\RandomAccessFile` (`read(int $length, int $offset): string`, `size(): ?int`) and +`Flow\Arrow\OutputStream` (`append(string $data): self`) are registered for stream implementations. ## Development @@ -328,8 +158,7 @@ make test - Built with [ext-php-rs](https://github.com/extphprs/ext-php-rs), which generates PHP bindings from Rust code - Uses Apache Arrow and Parquet Rust crates from the [Arrow ecosystem](https://github.com/apache/arrow-rs) - All compression codecs compiled into the extension - no external PHP compression extensions needed -- PHP streaming interfaces (`RandomAccessFile`, `OutputStream`) called from Rust via ext-php-rs callbacks -- Columnar batch format aligns with Parquet's native columnar storage +- Stream methods (`read`, `size`, `append`, `close`) called from Rust via ext-php-rs - PIE-compatible via `ext/config.m4` that delegates to `cargo build` ## See Also diff --git a/documentation/components/extensions/flow-php-ext.md b/documentation/components/extensions/flow-php-ext.md index 9597e596c1..39e33f837e 100644 --- a/documentation/components/extensions/flow-php-ext.md +++ b/documentation/components/extensions/flow-php-ext.md @@ -8,7 +8,8 @@ package: flow-php/flow-php-ext [TOC] -This extension is Flow's native column backend and reads CSV and Parquet and writes CSV, JSON and Parquet natively in Rust via +This extension is Flow's native column backend and reads CSV and JSON and writes CSV and JSON natively in Rust - Parquet +through the [arrow extension](/documentation/components/extensions/arrow-ext.md) - via [ext-php-rs](https://github.com/extphprs/ext-php-rs). The pure-PHP implementations in `flow-php/etl` are the canonical behaviour reference and work without the extension - loading it is purely an optimization. @@ -95,8 +96,17 @@ The classes are `Flow\ETL\Adapter\CSV\NativeCSVWriter` and `Flow\ETL\Adapter\JSO ## Parquet -With the extension loaded, `from_parquet()` and `to_parquet()` without an `engine:` read and write Parquet inside the -extension: row groups become `NativeColumn`s, and `Rows` are written without a PHP value per cell. +With both this extension and the [arrow extension](/documentation/components/extensions/arrow-ext.md) loaded, +`from_parquet()` and `to_parquet()` without an `engine:` read and write native columns: arrow-ext reads and writes the +file, and its batches cross into `NativeColumn`s (and back) through the Arrow C Data Interface, without a copy and +without a PHP value per cell. + +| loaded | `from_parquet()` / `to_parquet()` | +|-----------------|----------------------------------------------------------------------------| +| flow_php, arrow | native columns through the Arrow C Data Interface | +| arrow | `ArrowParquetEngine`, PHP values | +| flow_php | `PhpParquetEngine`; `DefaultBackend` adopts the values into native columns | +| neither | `PhpParquetEngine` | ```php run(); ``` -`engine: new ArrowParquetEngine()` and `new AdaptiveParquetEngine()` read and write through the extension too. A column -type the extension has no cast for is refused before the first batch, naming the engine that reads it: - -``` -Parquet column "iv" (Interval(DayTime)) is not supported by the flow_php Parquet reader; read the file with -from_parquet($path, engine: new \Flow\Parquet\Engine\PhpParquetEngine()) -``` - -A string that is not valid UTF-8 is refused on write, naming the column and its 0-based row in the batch -(`Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8`). Everything the reader and writer allocate is counted by -`DefaultBackend::allocatedBytes()`. - -The extension also registers `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}`, the reader and -writer `from_parquet()` and `to_parquet()` use. - -### The parquet library +A schema type that stores another arrow type than the file column reads as is refused before the first batch. The +imported batches are counted by `DefaultBackend::allocatedBytes()` for as long as they live; arrow-ext's own read +buffers (a row group's projected column chunks, decode buffers) are not, so a `MemoryBudget` does not see them. Read and +write refusals are arrow-ext's `Flow\Parquet\Exception\*`, as with `ArrowParquetEngine`. -`Flow\Parquet\Reader::arrow()` / `Writer::arrow()` (`ArrowParquetEngine`) read and write through the extension: the -values are the ones `Reader::php()` returns, and writes accept and refuse what `Writer::php()` does. The footer is read -once and decoded in Rust; `schema()`, `rowsNumber()` and `totalByteSize()` never build the PHP metadata graph. - -```php -read(__DIR__ . '/orders.parquet'); - -$file->reader()->rowsNumber(); // from the footer, no PHP metadata graph -$file->values(['address.city'], limit: 10, offset: 5_000); // a struct path; only the row groups from row 5 000 -``` +The extension registers `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}` (over +`Flow\Arrow\Parquet\BatchReader` / `RowsWriter`) and `Flow\ETL\Column\NativeArrowBatch`, the batch it exports. -The classes behind it are `Flow\Parquet\Engine\Native\{NativeParquetFile, NativeParquetColumnsReader, -NativeParquetRowsWriter}`. `Writer::writeColumns()` appends each list straight to its column. diff --git a/documentation/components/libs/parquet.md b/documentation/components/libs/parquet.md index 8e42d4d42d..90e5d9a278 100644 --- a/documentation/components/libs/parquet.md +++ b/documentation/components/libs/parquet.md @@ -16,11 +16,9 @@ For detailed installation instructions, see the [installation page](/documentati - **PHP Engine** (`PhpParquetEngine`) - pure PHP, no extra dependencies beyond optional compression extensions. - **Arrow Engine** (`ArrowParquetEngine`) - native Rust through the - [flow_php extension](/documentation/components/extensions/flow-php-ext.md); every compression codec is built in. - Without `flow_php` it falls back to the deprecated [arrow extension](/documentation/components/extensions/arrow-ext.md) - and raises `E_USER_DEPRECATED`. -- **Adaptive Engine** (`AdaptiveParquetEngine`) - the default: `ArrowParquetEngine` when `flow_php` or `arrow` is - loaded, `PhpParquetEngine` otherwise. + [arrow extension](/documentation/components/extensions/arrow-ext.md); every compression codec is built in. +- **Adaptive Engine** (`AdaptiveParquetEngine`) - the default: `ArrowParquetEngine` when `arrow` is loaded, + `PhpParquetEngine` otherwise. ```php [TOC] -> [!WARNING] -> **Deprecated.** Parquet through this extension is deprecated and will be removed; `flow-php/arrow-ext` is abandoned in -> favour of [flow-php/flow-php-ext](/documentation/components/extensions/flow-php-ext.md). Install the `flow_php` -> extension: `ArrowParquetEngine` uses it when it is loaded, and falls back to this extension with an -> `E_USER_DEPRECATED` notice otherwise. - ## Precompiled Binaries Precompiled binaries are available for download from the [GitHub Releases](https://github.com/flow-php/arrow-ext/releases/latest) page. diff --git a/documentation/upgrading.md b/documentation/upgrading.md index 56f96156ef..d672ce6c75 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -858,14 +858,14 @@ public function eval(Rows $rows, FlowContext $context): Column | `discover_pivot_values()` over `'9', '10', '100'` - columns `9, 10, 100` | `10, 100, 9`; integer pivot values stay numeric | | `->stringMatch()` / `->stringMatchAll()` turned a PHP `\Error` into an exception `optional()` swallowed | an `\Error` propagates; `->jsonDecode()`, `cast()`, `->arrayPathExists()`, `->stringMatch*()` errors keep their cause as `getPrevious()` | -### 79) `flow-php/etl-adapter-parquet` - with `flow_php` loaded and no engine given, `flow_php` reads and writes Parquet +### 79) `flow-php/etl-adapter-parquet` - with `flow_php` and arrow-ext loaded and no engine given, Parquet is read and written as native columns -| Before | After | -|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `from_parquet($path)` / `to_parquet($path)` - `AdaptiveParquetEngine` (arrow-ext when loaded, else the PHP engine) | with `flow_php` loaded: `flow_php` itself (row groups straight into native columns); without it: unchanged | -| `engine: new PhpParquetEngine()` / `new ArrowParquetEngine()` | `engine: new PhpParquetEngine()` opts out of `flow_php`; `new ArrowParquetEngine()` / `new AdaptiveParquetEngine()` read and write through `flow_php` when it is loaded | -| a column type arrow-ext could not read failed inside arrow-ext | refused before the first batch: `Parquet column "" () is not supported by the flow_php Parquet reader; read the file with from_parquet($path, engine: new \Flow\Parquet\Engine\PhpParquetEngine())` | -| `flow-php/etl-adapter-parquet` installable with any `flow_php` version | `conflict: ext-flow_php <0.45` - load a `flow_php` of this release or none | +| Before | After | +|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `from_parquet($path)` / `to_parquet($path)` - `AdaptiveParquetEngine` (arrow-ext when loaded, else the PHP engine) | with `flow_php` and arrow-ext loaded: arrow-ext's batches straight into native columns and back (Arrow C Data Interface); `flow_php` alone: the PHP engine, its values adopted into native columns; without `flow_php`: unchanged | +| `engine: new PhpParquetEngine()` / `new ArrowParquetEngine()` | `engine: new PhpParquetEngine()` opts out; `new ArrowParquetEngine()` / `new AdaptiveParquetEngine()` read and write native columns when both extensions are loaded | +| a column type arrow-ext could not read failed inside arrow-ext | refused before the first batch: `Flow\Parquet\Exception\RuntimeException` `Parquet column "" () is not supported by the arrow Parquet reader; read the file with \Flow\Parquet\Reader::php()` | +| `flow-php/etl-adapter-parquet` installable with any `flow_php` or arrow-ext version | `conflict: ext-flow_php <0.45`, `ext-arrow <0.45` - load extensions of this release or none | ### 80) `flow-php/etl-adapter-parquet` - Flow `float` columns are written as Parquet `DOUBLE` @@ -873,12 +873,12 @@ public function eval(Rows $rows, FlowContext $context): Column |---------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| | `float_schema('amount')` written as Parquet `FLOAT` (32-bit): `0.14` read back as `0.14000000059604645` | written as `DOUBLE` (64-bit), read back exactly; readers of the file see a `DOUBLE` column | -### 81) `flow-php/etl-adapter-parquet` - with `flow_php`, a string that is not valid UTF-8 is refused on write +### 81) `flow-php/etl-adapter-parquet` - with `flow_php` and arrow-ext, a string that is not valid UTF-8 is refused on write -| Before | After | -|------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| without arrow-ext, `PhpParquetEngine` wrote `"\xff\xfe"` into a `STRING` column other readers reject (DuckDB: `is not valid UTF8`) | `Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8` - the row is 0-based within the batch written | -| with arrow-ext: `Column 'name': expected string, got string` | the same refusal; invalid UTF-8 into `STRING` / `JSON` / `ENUM` is refused by both engines; `Option::VALIDATE_DATA = false` on `PhpParquetEngine` writes it unvalidated (a file other readers reject); `flow_php` always refuses | +| Before | After | +|------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| without arrow-ext, `PhpParquetEngine` wrote `"\xff\xfe"` into a `STRING` column other readers reject (DuckDB: `is not valid UTF8`) | `Flow\Parquet\Exception\RuntimeException` `Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8` - the row is 0-based within the batch written | +| with arrow-ext: `Column 'name': expected string, got string` | the same refusal; invalid UTF-8 into `STRING` / `JSON` / `ENUM` is refused by both engines; `Option::VALIDATE_DATA = false` on `PhpParquetEngine` writes it unvalidated (a file other readers reject); arrow-ext always refuses | ### 82) `flow-php/parquet` - `DELTA_BINARY_PACKED` follows the spec; affected files written by `PhpParquetEngine` must be rewritten @@ -897,12 +897,10 @@ public function eval(Rows $rows, FlowContext $context): Column | `new ParquetFile($stream, $byteOrder, $options, $engine)` | `new ParquetFile($stream, $options, $engine->openForRead($stream))` | | a `ParquetFile` closed its stream only when destroyed | `ParquetFile::close()` closes its reader (once); `ParquetFile::reader()` returns it | -### 84) `flow-php/parquet` - with `flow_php` loaded, `ArrowParquetEngine` reads and writes through it; arrow-ext's Parquet is deprecated +### 84) `flow-php/parquet` - `ArrowParquetEngine` reads and writes through arrow-ext's new Parquet core | Before | After | |----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `Reader::arrow()` / `Writer::arrow()` / `new ArrowParquetEngine()` - arrow-ext | `flow_php` when it is loaded; arrow-ext otherwise, with an `E_USER_DEPRECATED` notice (`@`-silenced) | -| `new AdaptiveParquetEngine()` - arrow-ext when loaded, else the PHP engine | `flow_php` or arrow-ext loaded: `ArrowParquetEngine`; neither: `PhpParquetEngine` | | `DATE` read as `DateTimeImmutable` in zone `+00:00` | zone `UTC`, as `PhpParquetEngine` | | `TIME` of 25 hours read as `PT25H`, `days` `false` | `d` = 1, `h` = 1, `days` an int (the `diff()` interval `PhpParquetEngine` returns) | | `INT96` outside 1677-2262 read wrapped (0001-01-01 → 1754-08-30) | read exactly, floored to the microsecond | @@ -911,8 +909,9 @@ public function eval(Rows $rows, FlowContext $context): Column | `TIME` writes dropped the interval's `d` | kept | | an offset read decoded every row group before the offset; page headers were read to the end of the file | only the row groups a read needs, each column chunk read once | | an `INTERVAL`, a path into a `LIST` / `MAP`, `LZO` or `INT96` under `Option::INT_96_AS_DATETIME = false` failed inside arrow-ext | refused before the first batch naming the column and `\Flow\Parquet\Reader::php()` | -| `Reader::read()` returned without touching the file; an invalid file failed at `metadata()` | with `flow_php` the footer is read when the file is opened: `Reader::read()` / `readStream()` throw `InvalidArgumentException` `Given file is not valid Parquet file: …` | -| `flow-php/parquet` installable with any `flow_php` version | `conflict: ext-flow_php <0.45` | +| `Reader::read()` returned without touching the file; an invalid file failed at `metadata()` | the footer is read when the file is opened: `Reader::read()` / `readStream()` throw `InvalidArgumentException` `Given file is not valid Parquet file: …` | +| `Flow\Arrow\Parquet\Reader` / `Writer` / `Exception` | removed: `Flow\Arrow\Parquet\{ParquetFile, ColumnsReader, RowsWriter, BatchReader}`; refusals are `Flow\Parquet\Exception\*` | +| `flow-php/parquet` installable with any arrow-ext version | `conflict: ext-arrow <0.45` | ### 85) `flow-php/parquet` - `PhpParquetEngine` reads unsigned integers and INT96 exactly; `FlatColumn::enum()` writes the ENUM logical type; values it wrote wrongly are refused @@ -929,11 +928,11 @@ public function eval(Rows $rows, FlowContext $context): Column | `Validator::validate(Column $column, mixed $data): void` | `Validator::validate(Column $column, mixed $data, int $row): void` - custom validators add the parameter (the 0-based row within the writer) | | logical `INTEGER` read without its width and sign; written back as an `IntType` missing both (a footer arrow-rs refuses) | `LogicalType::integerData(): ?LogicalType\Integer` keeps them and writes them back; `LogicalType::integer()` → `LogicalType::integer(int $bitWidth, bool $isSigned)` | -### 86) `flow-php/arrow-ext` - deprecated, replaced by `flow-php/flow-php-ext` +### 86) `flow-php/arrow-ext` - Parquet core replaced -| Before | After | -|----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------| -| `flow-php/arrow-ext` - the arrow extension, `ArrowParquetEngine`'s backend | `abandoned` in favour of `flow-php/flow-php-ext`: install the `flow_php` extension, which `ArrowParquetEngine` uses when it is loaded | +| Before | After | +|-------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Flow\Arrow\Parquet\Reader` / `Writer` - PHP values per call (`readRowGroup()`, `writeBatch()`) | `Flow\Arrow\Parquet\{ParquetFile, ColumnsReader, RowsWriter, BatchReader}` - the values `PhpParquetEngine` reads and accepts; `BatchReader` and `RowsWriter::writeBatch()` hand batches to other extensions through the Arrow C Data Interface | ### 87) `flow-php/etl-adapter-csv` - `to_csv()` writes a boolean as `true` / `false` diff --git a/src/adapter/etl-adapter-parquet/composer.json b/src/adapter/etl-adapter-parquet/composer.json index 15c7c9ac65..d4280f6447 100644 --- a/src/adapter/etl-adapter-parquet/composer.json +++ b/src/adapter/etl-adapter-parquet/composer.json @@ -17,6 +17,7 @@ "flow-php/parquet": "self.version" }, "conflict": { + "ext-arrow": "<0.45", "ext-flow_php": "<0.45" }, "config": { diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php index 5802202496..5ef822ce8a 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php @@ -4,24 +4,38 @@ namespace Flow\ETL\Adapter\Parquet; +use Flow\Arrow\Parquet\BatchReader; +use Flow\Arrow\Parquet\ParquetFile; use Flow\ETL\Column\Backend; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\Parquet\Engine\Native\NativeParquetFile; use Generator; +use function array_keys; +use function array_map; + final class NativeParquetOpenSource implements ParquetOpenSource { private ?NativeParquetReader $reader = null; public function __construct( - private readonly NativeParquetFile $file, + private readonly ParquetFile $file, ) {} public function batches(Schema $schema, int $batchSize, ?int $offset, ?int $limit, Backend $backend): Generator { $this->reader?->close(); - $reader = $this->reader = new NativeParquetReader($this->file, $schema, $batchSize, $offset, $limit); + $reader = + $this->reader = new NativeParquetReader( + new BatchReader( + $this->file, + array_map('strval', array_keys($schema->definitions())), + $batchSize, + $offset, + $limit, + ), + $schema, + ); while (($batch = $reader->next()) !== null) { $columns = []; diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php index fc7a754de2..79a74850e2 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php @@ -4,20 +4,22 @@ namespace Flow\ETL\Adapter\Parquet; +use Flow\Arrow\Parquet\ParquetFile as ArrowParquetFile; +use Flow\Arrow\Parquet\RowsWriter; use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; use Flow\Parquet\Engine\Arrow\OptionsConverter; use Flow\Parquet\Engine\Arrow\SchemaConverter as ArrowSchemaConverter; use Flow\Parquet\Engine\ArrowParquetEngine; -use Flow\Parquet\Engine\Native\NativeParquetFile; -use Flow\Parquet\Engine\NativeParquetFileReader; +use Flow\Parquet\Engine\ArrowParquetFileReader; +use Flow\Parquet\Option; use Flow\Parquet\Options; use Flow\Parquet\ParquetFile; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema as ParquetSchema; /** - * @implements ParquetOpener + * @implements ParquetOpener */ final readonly class NativeParquetOpener implements ParquetOpener { @@ -26,14 +28,14 @@ public function __construct( ) {} /** - * @return ParquetFile + * @return ParquetFile */ public function file(SourceStream $stream): ParquetFile { return new ParquetFile( $stream, $this->options, - new NativeParquetFileReader(new NativeParquetFile($stream), $this->options), + new ArrowParquetFileReader(new ArrowParquetFile($stream), $this->options), ); } @@ -43,18 +45,19 @@ public function sink( Compressions $compressions, Options $options, ): ParquetOpenSink { - return new NativeParquetOpenSink( - new NativeParquetWriter( + return new NativeParquetOpenSink(new NativeParquetWriter( + new RowsWriter( $stream, ArrowSchemaConverter::toExtension($schema), ArrowParquetEngine::mapCompression($compressions), OptionsConverter::toExtension($options), + $this->options->getInt(Option::ARROW_WRITE_BATCH_SIZE), ), - ); + )); } /** - * @param ParquetSourceFile $file + * @param ParquetSourceFile $file */ public function source(ParquetSourceFile $file): ParquetOpenSource { diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php index 02480c6e1e..f8909f7717 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php @@ -18,6 +18,7 @@ public static function select(?ParquetEngine $engine, ByteOrder $byteOrder, Opti { if ( extension_loaded('flow_php') + && extension_loaded('arrow') && ($engine === null || $engine instanceof AdaptiveParquetEngine || $engine instanceof ArrowParquetEngine) ) { return new NativeParquetOpener($options); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php index 0e4e6bc605..904484336e 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Context; +use Flow\Arrow\Parquet\RowsWriter; use Flow\ETL\Adapter\Parquet\NativeParquetOpenSink; use Flow\ETL\Adapter\Parquet\NativeParquetWriter; use Flow\ETL\Adapter\Parquet\SchemaConverter; @@ -111,14 +112,15 @@ public static function phpEngineValues(Filesystem $filesystem, string $uri): arr public static function nativeSink(Filesystem $filesystem, string $uri, FlowSchema $schema): NativeParquetOpenSink { - return new NativeParquetOpenSink( - new NativeParquetWriter( + return new NativeParquetOpenSink(new NativeParquetWriter( + new RowsWriter( $filesystem->writeTo(path($uri)), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), 'SNAPPY', OptionsConverter::toExtension(Options::default()), + Options::default()->getInt(Option::ARROW_WRITE_BATCH_SIZE), ), - ); + )); } /** diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php index 145ae35d61..2c4b5a06ee 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php @@ -6,7 +6,6 @@ use DateTimeImmutable; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; -use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\Context\LoaderEndingContext; use Flow\ETL\Tests\Context\MemoryTelemetryContext; use Flow\ETL\Tests\Double\FakeExtractor; @@ -17,6 +16,7 @@ use Flow\Filesystem\Tests\Double\FailingCloseFilesystem; use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Exception\RuntimeException as ParquetRuntimeException; use Flow\Parquet\Option; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; @@ -101,8 +101,8 @@ public function test_writing_and_reading_into_parquet(): void public function test_writing_and_reading_with_explicit_arrow_engine(): void { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { - static::markTestSkipped('neither flow_php nor arrow is loaded'); + if (!extension_loaded('arrow')) { + static::markTestSkipped('arrow is not loaded'); } $memory = memory_filesystem(); @@ -416,10 +416,10 @@ public function test_a_float_round_trips_exactly(?ParquetEngine $engine): void ); } - #[RequiresPhpExtension('flow_php')] - public function test_flow_php_refuses_a_string_that_is_not_valid_utf8(): void + #[RequiresPhpExtension('arrow')] + public function test_arrow_refuses_a_string_that_is_not_valid_utf8(): void { - $this->expectException(RuntimeException::class); + $this->expectException(ParquetRuntimeException::class); $this->expectExceptionMessage( 'Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8', ); @@ -433,8 +433,8 @@ public function test_flow_php_refuses_a_string_that_is_not_valid_utf8(): void /** * 200 values: a full block and a partial one, both with zero-width miniblocks - read by arrow-rs, not only by PHP. */ - #[RequiresPhpExtension('flow_php')] - public function test_a_php_written_delta_binary_packed_column_reads_back_through_flow_php(): void + #[RequiresPhpExtension('arrow')] + public function test_a_php_written_delta_binary_packed_column_reads_back_through_arrow(): void { $memory = memory_filesystem(); $ids = array_map(static fn(int $i): int => $i * 3, range(0, 199)); @@ -450,7 +450,8 @@ public function test_a_php_written_delta_binary_packed_column_reads_back_through } #[RequiresPhpExtension('flow_php')] - public function test_a_given_engine_is_honoured_with_flow_php_loaded(): void + #[RequiresPhpExtension('arrow')] + public function test_a_given_engine_is_honoured_with_both_extensions_loaded(): void { $memory = memory_filesystem(); $path = path('memory://var/engine.parquet'); @@ -644,8 +645,8 @@ public function test_a_path_only_partition_column_is_left_out_of_an_inferred_fil public function test_partitions_written_with_an_explicit_arrow_engine_each_get_their_own_file(): void { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { - static::markTestSkipped('neither flow_php nor arrow is loaded'); + if (!extension_loaded('arrow')) { + static::markTestSkipped('arrow is not loaded'); } $memory = memory_filesystem(); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php index f7a04e331b..34c02c3367 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php @@ -4,17 +4,19 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; +use Flow\Arrow\Parquet\RowsWriter; use Flow\ETL\Adapter\Parquet\NativeParquetOpenSink; use Flow\ETL\Adapter\Parquet\NativeParquetWriter; use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; use Flow\ETL\Column\PhpBackend; -use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Exception\RuntimeException as FilesystemRuntimeException; use Flow\Filesystem\Tests\Double\FailingAppendDestinationStream; use Flow\Parquet\Engine\Arrow\OptionsConverter; use Flow\Parquet\Engine\Arrow\SchemaConverter as ArrowSchemaConverter; +use Flow\Parquet\Exception\RuntimeException; +use Flow\Parquet\Option; use Flow\Parquet\Options; use PHPUnit\Framework\Attributes\RequiresPhpExtension; @@ -27,6 +29,7 @@ use function Flow\Filesystem\DSL\path; #[RequiresPhpExtension('flow_php')] +#[RequiresPhpExtension('arrow')] final class NativeParquetOpenSinkTest extends FlowTestCase { public function test_a_batch_of_php_columns_reads_back_equal(): void @@ -65,14 +68,15 @@ public function test_an_exception_append_throws_surfaces_as_itself(): void { $filesystem = memory_filesystem(); $schema = schema(int_schema('id')); - $sink = new NativeParquetOpenSink( - new NativeParquetWriter( + $sink = new NativeParquetOpenSink(new NativeParquetWriter( + new RowsWriter( new FailingAppendDestinationStream($filesystem->writeTo(path('memory://out.parquet'))), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), 'SNAPPY', OptionsConverter::toExtension(Options::default()), + Options::default()->getInt(Option::ARROW_WRITE_BATCH_SIZE), ), - ); + )); $sink->write(array_to_rows([['id' => 1]], $schema)); $this->expectException(FilesystemRuntimeException::class); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php index 219174be8f..a21af9cded 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php @@ -4,13 +4,13 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; +use Flow\Arrow\Parquet\ParquetFile; use Flow\ETL\Adapter\Parquet\NativeParquetOpenSource; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Column\Php\ScalarColumn; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\FlowTestCase; -use Flow\Parquet\Engine\Native\NativeParquetFile; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\TestWith; @@ -23,6 +23,7 @@ use function range; #[RequiresPhpExtension('flow_php')] +#[RequiresPhpExtension('arrow')] final class NativeParquetOpenSourceTest extends FlowTestCase { /** @@ -39,7 +40,7 @@ public function test_offset_and_limit_cross_row_groups(?int $offset, ?int $limit $read = []; - foreach ((new NativeParquetOpenSource(new NativeParquetFile($filesystem->readFrom(path( + foreach ((new NativeParquetOpenSource(new ParquetFile($filesystem->readFrom(path( 'memory://groups.parquet', )))))->batches(schema(int_schema('id')), 3, $offset, $limit, new DefaultBackend()) as $rows) { static::assertLessThanOrEqual(3, $rows->count()); @@ -53,9 +54,7 @@ public function test_columns_are_adopted_by_the_backend(): void { $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - $source = new NativeParquetOpenSource(new NativeParquetFile($filesystem->readFrom(path( - 'memory://groups.parquet', - )))); + $source = new NativeParquetOpenSource(new ParquetFile($filesystem->readFrom(path('memory://groups.parquet')))); $names = []; @@ -74,9 +73,7 @@ public function test_a_second_batches_call_closes_the_first_reader(): void { $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - $source = new NativeParquetOpenSource(new NativeParquetFile($filesystem->readFrom(path( - 'memory://groups.parquet', - )))); + $source = new NativeParquetOpenSource(new ParquetFile($filesystem->readFrom(path('memory://groups.parquet')))); $first = $source->batches(schema(int_schema('id')), 3, null, null, new DefaultBackend()); static::assertSame([0, 1, 2], $first->current()->column('id')->values()); @@ -97,9 +94,7 @@ public function test_close_before_batches_is_harmless(): void $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - (new NativeParquetOpenSource(new NativeParquetFile($filesystem->readFrom(path( - 'memory://groups.parquet', - )))))->close(); + (new NativeParquetOpenSource(new ParquetFile($filesystem->readFrom(path('memory://groups.parquet')))))->close(); $this->expectNotToPerformAssertions(); } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php index 7f3bc14734..ea0c051d79 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php @@ -24,9 +24,10 @@ use function Flow\Filesystem\DSL\path; #[RequiresPhpExtension('flow_php')] +#[RequiresPhpExtension('arrow')] final class NativeParquetOpenerTest extends FlowTestCase { - public function test_sink_writes_through_flow_php(): void + public function test_sink_writes_native_columns(): void { $filesystem = memory_filesystem(); $schema = schema(int_schema('id')); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php index c65f15721f..ca15f833da 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php @@ -13,7 +13,7 @@ use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\AdaptiveParquetEngine; use Flow\Parquet\Engine\ArrowParquetEngine; -use Flow\Parquet\Engine\NativeParquetFileReader; +use Flow\Parquet\Engine\ArrowParquetFileReader; use Flow\Parquet\Engine\PhpParquetEngine; use Flow\Parquet\Engine\PhpParquetFileReader; use Flow\Parquet\Options; @@ -34,7 +34,8 @@ public function test_a_php_engine_is_always_honoured(): void } #[RequiresPhpExtension('flow_php')] - public function test_with_flow_php_an_adaptive_engine_reads_through_flow_php(): void + #[RequiresPhpExtension('arrow')] + public function test_with_both_extensions_an_adaptive_engine_reads_native_columns(): void { static::assertEquals( new NativeParquetOpener(Options::default()), @@ -43,7 +44,8 @@ public function test_with_flow_php_an_adaptive_engine_reads_through_flow_php(): } #[RequiresPhpExtension('flow_php')] - public function test_with_flow_php_an_arrow_engine_reads_through_flow_php(): void + #[RequiresPhpExtension('arrow')] + public function test_with_both_extensions_an_arrow_engine_reads_native_columns(): void { static::assertEquals( new NativeParquetOpener(Options::default()), @@ -52,7 +54,8 @@ public function test_with_flow_php_an_arrow_engine_reads_through_flow_php(): voi } #[RequiresPhpExtension('flow_php')] - public function test_with_flow_php_no_engine_reads_through_flow_php(): void + #[RequiresPhpExtension('arrow')] + public function test_with_both_extensions_no_engine_reads_native_columns(): void { static::assertEquals( new NativeParquetOpener(Options::default()), @@ -60,10 +63,10 @@ public function test_with_flow_php_no_engine_reads_through_flow_php(): void ); } - public function test_without_flow_php_an_adaptive_engine_is_honoured(): void + public function test_without_both_extensions_an_adaptive_engine_is_honoured(): void { - if (extension_loaded('flow_php')) { - static::markTestSkipped('flow_php is loaded'); + if (extension_loaded('flow_php') && extension_loaded('arrow')) { + static::markTestSkipped('flow_php and arrow are loaded'); } $engine = new AdaptiveParquetEngine(); @@ -75,7 +78,7 @@ public function test_without_flow_php_an_adaptive_engine_is_honoured(): void } #[RequiresPhpExtension('arrow')] - public function test_without_flow_php_an_arrow_engine_is_honoured(): void + public function test_with_arrow_alone_an_arrow_engine_is_honoured(): void { if (extension_loaded('flow_php')) { static::markTestSkipped('flow_php is loaded'); @@ -89,10 +92,10 @@ public function test_without_flow_php_an_arrow_engine_is_honoured(): void ); } - public function test_without_flow_php_no_engine_opens_through_an_adaptive_engine(): void + public function test_without_both_extensions_no_engine_opens_through_an_adaptive_engine(): void { - if (extension_loaded('flow_php')) { - static::markTestSkipped('flow_php is loaded'); + if (extension_loaded('flow_php') && extension_loaded('arrow')) { + static::markTestSkipped('flow_php and arrow are loaded'); } static::assertEquals( @@ -114,12 +117,13 @@ public function test_an_engine_opener_opens_files_with_its_engine_reader(): void } #[RequiresPhpExtension('flow_php')] - public function test_a_native_opener_opens_files_with_a_native_reader(): void + #[RequiresPhpExtension('arrow')] + public function test_a_native_opener_opens_files_with_an_arrow_reader(): void { $file = (new NativeParquetOpener(Options::default()))->file( NativeLocalSourceStream::open(ParquetSourceFileContext::fixture()), ); - static::assertInstanceOf(NativeParquetFileReader::class, $file->reader()); + static::assertInstanceOf(ArrowParquetFileReader::class, $file->reader()); } } diff --git a/src/extension/arrow-ext/Cargo.lock b/src/extension/arrow-ext/Cargo.lock index af8a2539ff..12d2807d5e 100644 --- a/src/extension/arrow-ext/Cargo.lock +++ b/src/extension/arrow-ext/Cargo.lock @@ -81,6 +81,7 @@ dependencies = [ "arrow-schema", "bytes", "ext-php-rs", + "ext-php-rs-build", "parquet", ] @@ -97,6 +98,7 @@ dependencies = [ "chrono", "half", "hashbrown 0.17.1", + "libc", "num-complex", "num-integer", "num-traits", @@ -147,6 +149,7 @@ version = "59.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10fab8d4563491417ba801fab29d205104d20d4bdf37bda6cd1cf425cff598cd" dependencies = [ + "bitflags", "serde_core", "serde_json", ] diff --git a/src/extension/arrow-ext/Cargo.toml b/src/extension/arrow-ext/Cargo.toml index 9de8e105d4..059683a69a 100644 --- a/src/extension/arrow-ext/Cargo.toml +++ b/src/extension/arrow-ext/Cargo.toml @@ -9,11 +9,10 @@ crate-type = ["cdylib"] [dependencies] ext-php-rs = "0.15" parquet = { version = "59", default-features = false, features = ["arrow", "arrow_canonical_extension_types", "snap", "flate2", "flate2-zlib-rs", "zstd", "lz4", "brotli", "simdutf8"] } -arrow-array = "59" +arrow-array = { version = "59", features = ["ffi"] } arrow-buffer = "59" arrow-schema = { version = "59", features = ["canonical_extension_types"] } bytes = "1" -[[example]] -name = "generate_fixtures" -path = "examples/generate_fixtures.rs" +[build-dependencies] +ext-php-rs-build = "0.1" diff --git a/src/extension/arrow-ext/Makefile b/src/extension/arrow-ext/Makefile index b8bdfd6eac..fae03b517e 100644 --- a/src/extension/arrow-ext/Makefile +++ b/src/extension/arrow-ext/Makefile @@ -31,14 +31,26 @@ build: # Run PHPT tests test: build @echo "Running PHPT tests..." - @failed=0; total=0; passed=0; \ + @failed=0; total=0; passed=0; skipped=0; \ for f in tests/phpt/*.phpt; do \ total=$$((total + 1)); \ test_name=$$(basename "$$f"); \ tmp="$$(dirname "$$f")/_run_$${test_name%.phpt}.php"; \ + skipif="$$(dirname "$$f")/_skipif_$${test_name%.phpt}.php"; \ + sed -n '/^--SKIPIF--$$/,/^--FILE--$$/p' "$$f" | sed '1d;$$d' > "$$skipif"; \ + skip_out=""; \ + if [ -s "$$skipif" ]; then \ + skip_out=$$($(PHP) -d extension=$$(realpath $(EXTENSION_SO)) "$$skipif" 2>&1) || true; \ + fi; \ + rm -f "$$skipif"; \ + case "$$skip_out" in skip*) \ + echo "SKIP: $$test_name ($$skip_out)"; \ + skipped=$$((skipped + 1)); \ + continue;; \ + esac; \ sed -n '/^--FILE--$$/,/^--EXPECT/p' "$$f" | sed '1d;$$d' > "$$tmp"; \ expected=$$(sed -n '/^--EXPECT\(F\)\{0,1\}--$$/,$$p' "$$f" | sed '1d' | tr -d '\r'); \ - actual=$$($(PHP) -n -d extension=$$(realpath $(EXTENSION_SO)) "$$tmp" 2>&1) || true; \ + actual=$$($(PHP) -d extension=$$(realpath $(EXTENSION_SO)) "$$tmp" 2>&1) || true; \ actual=$$(printf '%s' "$$actual" | tr -d '\r'); \ rm -f "$$tmp"; \ if [ "$$actual" = "$$expected" ]; then \ @@ -51,7 +63,7 @@ test: build failed=1; \ fi; \ done; \ - echo "$$passed/$$total tests passed"; \ + echo "$$passed/$$total tests passed ($$skipped skipped)"; \ if [ $$failed -eq 1 ]; then exit 1; fi # Install to current PHP extension directory diff --git a/src/extension/arrow-ext/build.rs b/src/extension/arrow-ext/build.rs index eb491f8fb4..46afddbe9c 100644 --- a/src/extension/arrow-ext/build.rs +++ b/src/extension/arrow-ext/build.rs @@ -13,6 +13,27 @@ fn main() { println!("cargo:rustc-env=ARROW_LIB_VERSION={arrow_version}"); println!("cargo:rustc-env=PARQUET_LIB_VERSION={parquet_version}"); + + emit_php_version_cfg(); +} + +/// The `php84`/`php85` cfgs ext-php-rs sets for itself, for the same PHP (`PHP` first, then `PATH`): the extension +/// binary is bound to the PHP minor it is built against, so version gates are compile-time. +fn emit_php_version_cfg() { + use ext_php_rs_build::{emit_check_cfg, emit_php_cfg_flags, emit_rerun_if_env_changed, find_php, ApiVersion, PHPInfo}; + + emit_rerun_if_env_changed(); + emit_check_cfg(); + + let php = find_php().expect("cannot find the php executable"); + let info = PHPInfo::get(&php).expect("cannot read php -i"); + let version: ApiVersion = info + .zend_version() + .expect("cannot read the Zend API version") + .try_into() + .expect("unsupported Zend API version"); + + emit_php_cfg_flags(version); } fn extension_version(env_name: &str) -> String { diff --git a/src/extension/arrow-ext/composer.json b/src/extension/arrow-ext/composer.json index 9e21366e6a..df2565a79b 100644 --- a/src/extension/arrow-ext/composer.json +++ b/src/extension/arrow-ext/composer.json @@ -1,10 +1,9 @@ { "name": "flow-php/arrow-ext", "type": "php-ext", - "description": "Apache Arrow PHP extension powered by Rust", + "description": "Apache Arrow and Parquet bindings for flow-php/parquet (Rust)", "keywords": ["arrow", "parquet", "extension", "rust", "native"], "license": "MIT", - "abandoned": "flow-php/flow-php-ext", "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, diff --git a/src/extension/arrow-ext/examples/generate_fixtures.rs b/src/extension/arrow-ext/examples/generate_fixtures.rs deleted file mode 100644 index b4492eab15..0000000000 --- a/src/extension/arrow-ext/examples/generate_fixtures.rs +++ /dev/null @@ -1,388 +0,0 @@ -//! Standalone binary to generate test fixtures. -//! Run with: cargo run --example generate_fixtures - -use std::fs::File; -use std::sync::Arc; - -fn generate_simple() { - use parquet::basic::Type as PhysicalType; - use parquet::basic::{ConvertedType, Repetition}; - use parquet::column::writer::ColumnWriter; - use parquet::file::properties::WriterProperties; - use parquet::file::writer::SerializedFileWriter; - use parquet::schema::types::Type; - - let id_field = Arc::new( - Type::primitive_type_builder("id", PhysicalType::INT64) - .with_repetition(Repetition::REQUIRED) - .build() - .unwrap(), - ); - - let name_field = Arc::new( - Type::primitive_type_builder("name", PhysicalType::BYTE_ARRAY) - .with_repetition(Repetition::REQUIRED) - .with_converted_type(ConvertedType::UTF8) - .build() - .unwrap(), - ); - - let schema = Arc::new( - Type::group_type_builder("schema") - .with_fields(vec![id_field, name_field]) - .build() - .unwrap(), - ); - - let props = Arc::new( - WriterProperties::builder() - .set_compression(parquet::basic::Compression::UNCOMPRESSED) - .build(), - ); - - let file = File::create("tests/fixtures/simple.parquet").unwrap(); - let mut writer = SerializedFileWriter::new(file, schema, props).unwrap(); - - let mut row_group_writer = writer.next_row_group().unwrap(); - - // Write id column - if let Some(mut col_writer) = row_group_writer.next_column().unwrap() { - if let ColumnWriter::Int64ColumnWriter(ref mut w) = col_writer.untyped() { - w.write_batch(&[1, 2, 3], None, None).unwrap(); - } - col_writer.close().unwrap(); - } - - // Write name column - if let Some(mut col_writer) = row_group_writer.next_column().unwrap() { - if let ColumnWriter::ByteArrayColumnWriter(ref mut w) = col_writer.untyped() { - let values: Vec = - vec!["Alice".into(), "Bob".into(), "Charlie".into()]; - w.write_batch(&values, None, None).unwrap(); - } - col_writer.close().unwrap(); - } - - row_group_writer.close().unwrap(); - writer.close().unwrap(); - - println!("Generated tests/fixtures/simple.parquet"); -} - -fn generate_all_flat_types() { - use arrow_array::*; - use arrow_schema::{DataType, Field, Schema}; - use parquet::arrow::ArrowWriter; - - let schema = Arc::new(Schema::new(vec![ - Field::new("col_bool", DataType::Boolean, true), - Field::new("col_int8", DataType::Int8, true), - Field::new("col_int16", DataType::Int16, true), - Field::new("col_int32", DataType::Int32, true), - Field::new("col_int64", DataType::Int64, true), - Field::new("col_uint8", DataType::UInt8, true), - Field::new("col_uint16", DataType::UInt16, true), - Field::new("col_uint32", DataType::UInt32, true), - Field::new("col_uint64", DataType::UInt64, true), - Field::new("col_float", DataType::Float32, true), - Field::new("col_double", DataType::Float64, true), - Field::new("col_string", DataType::Utf8, true), - Field::new("col_binary", DataType::Binary, true), - Field::new("col_date", DataType::Date32, true), - Field::new( - "col_timestamp", - DataType::Timestamp(arrow_schema::TimeUnit::Microsecond, None), - true, - ), - Field::new("col_decimal", DataType::Decimal128(10, 2), true), - ])); - - let col_bool = BooleanArray::from(vec![Some(true), Some(false), None]); - let col_int8 = Int8Array::from(vec![Some(1i8), Some(-128i8), None]); - let col_int16 = Int16Array::from(vec![Some(256i16), Some(-32768i16), None]); - let col_int32 = Int32Array::from(vec![Some(100000i32), Some(-100000i32), None]); - let col_int64 = Int64Array::from(vec![Some(1000000000i64), Some(-1000000000i64), None]); - let col_uint8 = UInt8Array::from(vec![Some(0u8), Some(255u8), None]); - let col_uint16 = UInt16Array::from(vec![Some(0u16), Some(65535u16), None]); - let col_uint32 = UInt32Array::from(vec![Some(0u32), Some(4294967295u32), None]); - let col_uint64 = UInt64Array::from(vec![Some(0u64), Some(u64::MAX), None]); - let col_float = Float32Array::from(vec![Some(1.5f32), Some(-2.5f32), None]); - let col_double = Float64Array::from(vec![Some(1.23456f64), Some(-7.89012f64), None]); - let col_string = StringArray::from(vec![Some("hello"), Some("world"), None]); - - let col_binary: BinaryArray = vec![ - Some(b"\x00\x01\x02" as &[u8]), - Some(b"\xff\xfe" as &[u8]), - None, - ] - .into_iter() - .collect(); - - // 19000 days since epoch - let col_date = Date32Array::from(vec![Some(19000i32), Some(0i32), None]); - let col_timestamp = - TimestampMicrosecondArray::from(vec![Some(1700000000000000i64), Some(0i64), None]); - - // Decimal128: value is unscaled integer. 123.45 with scale=2 → 12345, -999.99 → -99999 - let col_decimal = Decimal128Array::from(vec![Some(12345i128), Some(-99999i128), None]) - .with_precision_and_scale(10, 2) - .unwrap(); - - let batch = RecordBatch::try_new( - schema.clone(), - vec![ - Arc::new(col_bool), - Arc::new(col_int8), - Arc::new(col_int16), - Arc::new(col_int32), - Arc::new(col_int64), - Arc::new(col_uint8), - Arc::new(col_uint16), - Arc::new(col_uint32), - Arc::new(col_uint64), - Arc::new(col_float), - Arc::new(col_double), - Arc::new(col_string), - Arc::new(col_binary), - Arc::new(col_date), - Arc::new(col_timestamp), - Arc::new(col_decimal), - ], - ) - .unwrap(); - - let file = File::create("tests/fixtures/all_flat_types.parquet").unwrap(); - let mut writer = ArrowWriter::try_new(file, schema, None).unwrap(); - writer.write(&batch).unwrap(); - writer.close().unwrap(); - - println!("Generated tests/fixtures/all_flat_types.parquet"); -} - -fn generate_nested() { - use arrow_array::builder::*; - use arrow_array::*; - use arrow_schema::{DataType, Field, Fields, Schema}; - use parquet::arrow::ArrowWriter; - - let schema = Arc::new(Schema::new(vec![ - Field::new("id", DataType::Int64, false), - Field::new( - "tags", - DataType::List(Arc::new(Field::new("item", DataType::Utf8, true))), - true, - ), - Field::new( - "metadata", - DataType::Struct(Fields::from(vec![ - Field::new("key", DataType::Utf8, false), - Field::new("value", DataType::Int64, false), - ])), - true, - ), - Field::new( - "props", - DataType::Map( - Arc::new(Field::new( - "entries", - DataType::Struct(Fields::from(vec![ - Field::new("keys", DataType::Utf8, false), - Field::new("values", DataType::Int64, true), - ])), - false, - )), - false, - ), - true, - ), - ])); - - // id column - let id_array = Int64Array::from(vec![1, 2, 3]); - - // tags column: Row 0: ["a","b","c"], Row 1: [] (empty), Row 2: null - let mut tags_builder = ListBuilder::new(StringBuilder::new()); - tags_builder.values().append_value("a"); - tags_builder.values().append_value("b"); - tags_builder.values().append_value("c"); - tags_builder.append(true); - tags_builder.append(true); // empty list - tags_builder.append(false); // null - let tags_array = tags_builder.finish(); - - // metadata column: Row 0: {key:"x", value:10}, Row 1: null, Row 2: {key:"y", value:20} - let meta_fields = Fields::from(vec![ - Field::new("key", DataType::Utf8, false), - Field::new("value", DataType::Int64, false), - ]); - let mut meta_builder = StructBuilder::new( - meta_fields, - vec![ - Box::new(StringBuilder::new()), - Box::new(Int64Builder::new()), - ], - ); - // Row 0: {key:"x", value:10} - meta_builder - .field_builder::(0) - .unwrap() - .append_value("x"); - meta_builder - .field_builder::(1) - .unwrap() - .append_value(10); - meta_builder.append(true); - // Row 1: null - meta_builder - .field_builder::(0) - .unwrap() - .append_null(); - meta_builder - .field_builder::(1) - .unwrap() - .append_null(); - meta_builder.append(false); - // Row 2: {key:"y", value:20} - meta_builder - .field_builder::(0) - .unwrap() - .append_value("y"); - meta_builder - .field_builder::(1) - .unwrap() - .append_value(20); - meta_builder.append(true); - let metadata_array = meta_builder.finish(); - - // props column: Row 0: {"p1":100, "p2":200}, Row 1: {"p3":300}, Row 2: null - let mut props_builder = MapBuilder::new(None, StringBuilder::new(), Int64Builder::new()); - props_builder.keys().append_value("p1"); - props_builder.values().append_value(100); - props_builder.keys().append_value("p2"); - props_builder.values().append_value(200); - props_builder.append(true).unwrap(); - props_builder.keys().append_value("p3"); - props_builder.values().append_value(300); - props_builder.append(true).unwrap(); - props_builder.append(false).unwrap(); // null - let props_array = props_builder.finish(); - - let batch = RecordBatch::try_new( - schema.clone(), - vec![ - Arc::new(id_array), - Arc::new(tags_array), - Arc::new(metadata_array), - Arc::new(props_array), - ], - ) - .unwrap(); - - let file = File::create("tests/fixtures/nested.parquet").unwrap(); - let mut writer = ArrowWriter::try_new(file, schema, None).unwrap(); - writer.write(&batch).unwrap(); - writer.close().unwrap(); - - println!("Generated tests/fixtures/nested.parquet"); -} - -fn generate_deeply_nested() { - use arrow_array::builder::*; - use arrow_array::*; - use arrow_schema::{DataType, Field, Fields, Schema}; - use parquet::arrow::ArrowWriter; - - let scores_field = Field::new( - "scores", - DataType::List(Arc::new(Field::new("item", DataType::Int64, true))), - true, - ); - let struct_fields = Fields::from(vec![ - Field::new("name", DataType::Utf8, false), - scores_field, - ]); - let groups_field = Field::new( - "groups", - DataType::List(Arc::new(Field::new( - "item", - DataType::Struct(struct_fields.clone()), - true, - ))), - true, - ); - - let schema = Arc::new(Schema::new(vec![groups_field])); - - // Build using nested builders - let scores_builder = ListBuilder::new(Int64Builder::new()); - let struct_builder = StructBuilder::new( - struct_fields, - vec![Box::new(StringBuilder::new()), Box::new(scores_builder)], - ); - let mut groups_builder = ListBuilder::new(struct_builder); - - // Row 0: [{name:"alpha", scores:[10,20]}, {name:"beta", scores:[30]}] - groups_builder - .values() - .field_builder::(0) - .unwrap() - .append_value("alpha"); - let scores_b = groups_builder - .values() - .field_builder::>(1) - .unwrap(); - scores_b.values().append_value(10); - scores_b.values().append_value(20); - scores_b.append(true); - groups_builder.values().append(true); - - groups_builder - .values() - .field_builder::(0) - .unwrap() - .append_value("beta"); - let scores_b = groups_builder - .values() - .field_builder::>(1) - .unwrap(); - scores_b.values().append_value(30); - scores_b.append(true); - groups_builder.values().append(true); - groups_builder.append(true); - - // Row 1: [{name:"gamma", scores:[]}] - groups_builder - .values() - .field_builder::(0) - .unwrap() - .append_value("gamma"); - let scores_b = groups_builder - .values() - .field_builder::>(1) - .unwrap(); - scores_b.append(true); // empty list - groups_builder.values().append(true); - groups_builder.append(true); - - // Row 2: null - groups_builder.append(false); - - let groups_array = groups_builder.finish(); - - let batch = RecordBatch::try_new(schema.clone(), vec![Arc::new(groups_array)]).unwrap(); - - let file = File::create("tests/fixtures/deeply_nested.parquet").unwrap(); - let mut writer = ArrowWriter::try_new(file, schema, None).unwrap(); - writer.write(&batch).unwrap(); - writer.close().unwrap(); - - println!("Generated tests/fixtures/deeply_nested.parquet"); -} - -fn main() { - std::fs::create_dir_all("tests/fixtures").unwrap(); - generate_simple(); - generate_all_flat_types(); - generate_nested(); - generate_deeply_nested(); -} diff --git a/src/extension/arrow-ext/php/Flow/Arrow/ArrowBatch.php b/src/extension/arrow-ext/php/Flow/Arrow/ArrowBatch.php new file mode 100644 index 0000000000..c962920e78 --- /dev/null +++ b/src/extension/arrow-ext/php/Flow/Arrow/ArrowBatch.php @@ -0,0 +1,45 @@ + $columns root column names + * @param int<1, max> $batchSize + */ + public function __construct(ParquetFile $file, array $columns, int $batchSize, ?int $offset, ?int $limit) + { + throw new RuntimeException('arrow extension is not loaded'); + } + + public function close(): void + { + throw new RuntimeException('arrow extension is not loaded'); + } + + /** + * At most $batchSize rows as one Arrow C Data struct array, null after the last. + */ + public function next(): ?ArrowBatch + { + throw new RuntimeException('arrow extension is not loaded'); + } + + /** + * The struct schema every batch has, before any batch is read. + */ + public function schema(): ArrowSchema + { + throw new RuntimeException('arrow extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetColumnsReader.php b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/ColumnsReader.php similarity index 52% rename from src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetColumnsReader.php rename to src/extension/arrow-ext/php/Flow/Arrow/Parquet/ColumnsReader.php index 1f2689aaa8..154336447c 100644 --- a/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetColumnsReader.php +++ b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/ColumnsReader.php @@ -2,30 +2,30 @@ declare(strict_types=1); -namespace Flow\Parquet\Engine\Native; +namespace Flow\Arrow\Parquet; use RuntimeException; use function extension_loaded; -if (extension_loaded('flow_php')) { +if (extension_loaded('arrow')) { return; } -final class NativeParquetColumnsReader +final class ColumnsReader { /** * @param list $columns root names or struct paths * @param int<1, max> $batchSize */ - public function __construct(NativeParquetFile $file, array $columns, int $batchSize, ?int $offset, ?int $limit) + public function __construct(ParquetFile $file, array $columns, int $batchSize, ?int $offset, ?int $limit) { - throw new RuntimeException('flow_php extension is not loaded'); + throw new RuntimeException('arrow extension is not loaded'); } public function close(): void { - throw new RuntimeException('flow_php extension is not loaded'); + throw new RuntimeException('arrow extension is not loaded'); } /** @@ -35,6 +35,6 @@ public function close(): void */ public function next(): ?array { - throw new RuntimeException('flow_php extension is not loaded'); + throw new RuntimeException('arrow extension is not loaded'); } } diff --git a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/Exception.php b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/Exception.php deleted file mode 100644 index 61ae8a70c0..0000000000 --- a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/Exception.php +++ /dev/null @@ -1,15 +0,0 @@ - $options - */ - public function __construct(RandomAccessFile $source, array $options = []) - { - throw new RuntimeException( - 'The arrow PHP extension is not loaded. Install ext-arrow to use Flow\Arrow\Parquet\Reader.', - ); - } - - public function close(): void {} - - /** - * @return array - */ - public function metadata(): array - { - return []; - } - - /** - * @param null|array $columns - * - * @return null|array> - */ - public function readRowGroup(?array $columns = null): ?array - { - return null; - } - - /** - * @return array> - */ - public function schema(): array - { - return []; - } -} diff --git a/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetRowsWriter.php b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RowsWriter.php similarity index 63% rename from src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetRowsWriter.php rename to src/extension/arrow-ext/php/Flow/Arrow/Parquet/RowsWriter.php index 304ae2fcb6..9d4dcda10b 100644 --- a/src/extension/flow-php-ext/php/Flow/Parquet/Engine/Native/NativeParquetRowsWriter.php +++ b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RowsWriter.php @@ -2,18 +2,18 @@ declare(strict_types=1); -namespace Flow\Parquet\Engine\Native; +namespace Flow\Arrow\Parquet; use Flow\Filesystem\DestinationStream; use RuntimeException; use function extension_loaded; -if (extension_loaded('flow_php')) { +if (extension_loaded('arrow')) { return; } -final class NativeParquetRowsWriter +final class RowsWriter { /** * @param array $schema Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension() @@ -27,7 +27,7 @@ public function __construct( array $options, int $batchSize, ) { - throw new RuntimeException('flow_php extension is not loaded'); + throw new RuntimeException('arrow extension is not loaded'); } /** @@ -35,7 +35,16 @@ public function __construct( */ public function close(): void { - throw new RuntimeException('flow_php extension is not loaded'); + throw new RuntimeException('arrow extension is not loaded'); + } + + /** + * An Arrow C Data struct batch, exported by an extension: its children by writer column name, a writer column + * the batch lacks is nulls, a child the writer lacks is ignored. + */ + public function writeBatch(object $batch): void + { + throw new RuntimeException('arrow extension is not loaded'); } /** @@ -44,7 +53,7 @@ public function close(): void */ public function writeColumns(array $columns): void { - throw new RuntimeException('flow_php extension is not loaded'); + throw new RuntimeException('arrow extension is not loaded'); } /** @@ -52,7 +61,7 @@ public function writeColumns(array $columns): void */ public function writeRow(array $row): void { - throw new RuntimeException('flow_php extension is not loaded'); + throw new RuntimeException('arrow extension is not loaded'); } /** @@ -60,6 +69,6 @@ public function writeRow(array $row): void */ public function writeRows(array $rows): void { - throw new RuntimeException('flow_php extension is not loaded'); + throw new RuntimeException('arrow extension is not loaded'); } } diff --git a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/Writer.php b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/Writer.php deleted file mode 100644 index 701f675123..0000000000 --- a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/Writer.php +++ /dev/null @@ -1,45 +0,0 @@ -> $schema - * @param array $options - */ - public function __construct( - OutputStream $stream, - array $schema, - string $compression = 'SNAPPY', - array $options = [], - ) { - throw new RuntimeException( - 'The arrow PHP extension is not loaded. Install ext-arrow to use Flow\Arrow\Parquet\Writer.', - ); - } - - public function close(): void {} - - /** - * @param array> $batch - */ - public function writeBatch(array $batch): void {} -} diff --git a/src/extension/arrow-ext/src/alloc.rs b/src/extension/arrow-ext/src/alloc.rs new file mode 100644 index 0000000000..11e181d473 --- /dev/null +++ b/src/extension/arrow-ext/src/alloc.rs @@ -0,0 +1,61 @@ +//! The test global allocator: `System`, counting the bytes each thread holds, so a cargo test pins what arrow's +//! native heap keeps while the other tests allocate on their own threads. + +use std::alloc::{GlobalAlloc, Layout, System}; +use std::cell::Cell; + +thread_local! { + static ALLOCATED: Cell = const { Cell::new(0) }; +} + +fn counted(delta: i64) { + // a thread being torn down has no counter left: nothing reads it again + let _ = ALLOCATED.try_with(|allocated| allocated.set(allocated.get() + delta)); +} + +struct Counting; + +unsafe impl GlobalAlloc for Counting { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let ptr = System.alloc(layout); + + if !ptr.is_null() { + counted(layout.size() as i64); + } + + ptr + } + + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + let ptr = System.alloc_zeroed(layout); + + if !ptr.is_null() { + counted(layout.size() as i64); + } + + ptr + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + System.dealloc(ptr, layout); + counted(-(layout.size() as i64)); + } + + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let new = System.realloc(ptr, layout, new_size); + + if !new.is_null() { + counted(new_size as i64 - layout.size() as i64); + } + + new + } +} + +#[global_allocator] +static GLOBAL: Counting = Counting; + +/// What the current thread holds. +pub fn allocated_bytes() -> i64 { + ALLOCATED.with(Cell::get) +} diff --git a/src/extension/arrow-ext/src/exception.rs b/src/extension/arrow-ext/src/exception.rs new file mode 100644 index 0000000000..6479c2bda6 --- /dev/null +++ b/src/extension/arrow-ext/src/exception.rs @@ -0,0 +1,14 @@ +use ext_php_rs::exception::PhpException; +use ext_php_rs::zend::{ce, ClassEntry}; + +/// What arrow throws for its own failures: the lib's runtime exception, plain `Exception` when the lib is not +/// autoloadable. +const EXCEPTION_CLASS: &str = "Flow\\Parquet\\Exception\\RuntimeException"; + +fn exception_ce() -> &'static ClassEntry { + ClassEntry::try_find(EXCEPTION_CLASS).unwrap_or_else(|| ce::exception()) +} + +pub fn ext_exception(message: impl Into) -> PhpException { + PhpException::new(message.into(), 0, exception_ce()) +} diff --git a/src/extension/arrow-ext/src/lib.rs b/src/extension/arrow-ext/src/lib.rs index 3f477a690b..8a470ff866 100644 --- a/src/extension/arrow-ext/src/lib.rs +++ b/src/extension/arrow-ext/src/lib.rs @@ -1,14 +1,21 @@ +#[cfg(test)] +mod alloc; +mod exception; mod parquet; +mod php; +mod render; mod stream; +mod thrift; +mod values; +#[cfg(not(test))] use std::alloc::System; use ext_php_rs::prelude::*; use ext_php_rs::zend::ModuleEntry; use ext_php_rs::{info_table_end, info_table_row, info_table_start}; -use parquet::reader::Reader; -use parquet::writer::Writer; +#[cfg(not(test))] #[global_allocator] static GLOBAL: System = System; @@ -34,10 +41,6 @@ pub unsafe extern "C" fn module_startup(_type: i32, _module_number: i32) -> i32 eprintln!("arrow: failed to register Flow\\Arrow\\RandomAccessFile: {e}"); return -1; } - if let Err(e) = parquet::exception::register() { - eprintln!("arrow: failed to register Flow\\Arrow\\Parquet\\Exception: {e}"); - return -1; - } 0 } @@ -47,6 +50,13 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { module .version(env!("ARROW_VERSION")) .info_function(php_module_info) - .class::() - .class::() + .globals(&php::GLOBALS) + .request_startup_function(php::request_startup) + .request_shutdown_function(php::request_shutdown) + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() } diff --git a/src/extension/arrow-ext/src/parquet/batch.rs b/src/extension/arrow-ext/src/parquet/batch.rs new file mode 100644 index 0000000000..03caf43d65 --- /dev/null +++ b/src/extension/arrow-ext/src/parquet/batch.rs @@ -0,0 +1,264 @@ +//! `Flow\Arrow\Parquet\BatchReader` and the Arrow C Data carriers: one batch = one struct-typed `FFI_ArrowSchema` (one +//! child per column) plus one struct-typed `FFI_ArrowArray`. The carrier owns both until a consumer moves the array +//! out; any extension's internal class exposing the two addresses is accepted. + +use std::collections::HashMap; +use std::ffi::{c_char, CStr}; +use std::sync::Arc; + +use arrow_array::ffi::{from_ffi, to_ffi, FFI_ArrowArray, FFI_ArrowSchema}; +use arrow_array::{Array, StructArray}; +use arrow_schema::{DataType, Field, Fields}; +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::{ZendObject, Zval}; +use ext_php_rs::zend::ClassEntry; + +use crate::parquet::error::Error; +use crate::parquet::library::{batch_size, rows, ParquetFile, INVALID_ARGUMENT}; +use crate::parquet::read::{ParquetReader, ReadPlan}; +use crate::parquet::source::PhpStream; +use crate::php::{call_handle_transparent, ce_method_ref}; +use crate::render::{exception, parquet_exception, Side}; + +/// Child field metadata: the arrow type of the file column the canonical child was read from. +pub const SOURCE_TYPE: &str = "parquet.source_type"; + +/// `ZEND_INTERNAL_CLASS` (zend_compile.h): a class an extension registered, which userland can neither declare nor +/// extend once final. +const ZEND_INTERNAL_CLASS: c_char = 1; + +#[php_class] +#[php(name = "Flow\\Arrow\\ArrowBatch", flags = ClassFlags::Final)] +pub struct ArrowBatch { + schema: FFI_ArrowSchema, + array: FFI_ArrowArray, + rows: usize, +} + +#[php_impl] +impl ArrowBatch { + pub fn count(&self) -> i64 { + self.rows as i64 + } + + #[php(name = "arrowSchemaAddress")] + pub fn arrow_schema_address(&self) -> i64 { + std::ptr::from_ref(&self.schema) as i64 + } + + #[php(name = "arrowArrayAddress")] + pub fn arrow_array_address(&self) -> i64 { + std::ptr::from_ref(&self.array) as i64 + } +} + +#[php_class] +#[php(name = "Flow\\Arrow\\ArrowSchema", flags = ClassFlags::Final)] +pub struct ArrowSchema { + schema: FFI_ArrowSchema, +} + +#[php_impl] +impl ArrowSchema { + #[php(name = "arrowSchemaAddress")] + pub fn arrow_schema_address(&self) -> i64 { + std::ptr::from_ref(&self.schema) as i64 + } +} + +#[php_class] +#[php(name = "Flow\\Arrow\\Parquet\\BatchReader", flags = ClassFlags::Final)] +pub struct BatchReader { + reader: Option, + stream: Arc, + /// The projection: canonical children named by column, each with its `SOURCE_TYPE`. + fields: Fields, +} + +#[php_impl] +impl BatchReader { + /// `$columns`: root names; `$batchSize` rows at most per `next()`. + pub fn __construct( + file: &ParquetFile, + columns: Vec, + batch_size: i64, + offset: Option, + limit: Option, + ) -> PhpResult { + let batch_size = self::batch_size(batch_size)?; + let (offset, limit) = (rows(offset, "offset")?.unwrap_or(0), rows(limit, "limit")?); + let (stream, size, meta) = file.read()?; + let stream = Arc::clone(stream); + let reader = + ParquetReader::open(Arc::clone(&stream), size, meta, &columns, ReadPlan::new(meta, offset, limit), batch_size) + .map_err(|error| parquet_exception(error, &stream, Side::Read))?; + let fields = columns + .iter() + .zip(reader.fields()) + .zip(reader.types()) + .map(|((name, field), canonical)| { + Field::new(name, canonical.clone(), true) + .with_metadata(HashMap::from([(SOURCE_TYPE.to_string(), field.data_type().to_string())])) + }) + .collect(); + + Ok(Self { + reader: Some(reader), + stream, + fields, + }) + } + + /// The struct schema of every batch, known before the first. + pub fn schema(&self) -> PhpResult { + Ok(ArrowSchema { + schema: FFI_ArrowSchema::try_from(&DataType::Struct(self.fields.clone())) + .map_err(|error| parquet_exception(Error::Arrow(error), &self.stream, Side::Read))?, + }) + } + + /// At most `$batchSize` rows as one struct batch, null after the last. + pub fn next(&mut self) -> PhpResult> { + let Some(reader) = self.reader.as_mut() else { + return Ok(None); + }; + + let (rows, arrays) = match reader.next() { + None => { + self.reader = None; + + return Ok(None); + } + Some(batch) => batch.map_err(|error| parquet_exception(error, &self.stream, Side::Read))?, + }; + + let exported = StructArray::try_new_with_length(self.fields.clone(), arrays, None, rows) + .and_then(|array| to_ffi(&array.to_data())) + .map_err(|error| parquet_exception(Error::Arrow(error), &self.stream, Side::Read))?; + + Ok(Some(ArrowBatch { + array: exported.0, + schema: exported.1, + rows, + })) + } + + pub fn close(&mut self) { + self.reader = None; + } +} + +fn refused(message: String) -> PhpException { + exception(INVALID_ARGUMENT, message) +} + +/// `$object->$method()` of an address method: a pointer the exporter owns. +fn address(object: &ZendObject, ce: &ClassEntry, method: &str) -> PhpResult { + let address = call_handle_transparent(ce_method_ref(ce, method)?, Some(object), &mut [])?; + + address + .long() + .and_then(|address| usize::try_from(address).ok()) + .filter(|address| *address != 0) + .ok_or_else(|| refused(format!("Arrow C Data {method}() must return a non-null address"))) +} + +/// The struct batch `$batch` carries, moved out of it: an internal class's `arrowSchemaAddress()` (read by reference) +/// and `arrowArrayAddress()` (moved, its release left NULL), refused before the move unless the schema is a struct +/// of as many children as the array and the array was not imported before. +pub fn import(batch: &Zval) -> PhpResult { + let object = batch.object().ok_or_else(|| refused("Arrow C Data batch must be an object".to_string()))?; + let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| refused("Arrow C Data batch has no class".to_string()))?; + + if ce.type_ != ZEND_INTERNAL_CLASS { + return Err(refused(format!( + "Arrow C Data batch must be an extension's class, got {}", + ce.name().unwrap_or_default() + ))); + } + + let schema = unsafe { &*(address(object, ce, "arrowSchemaAddress")? as *const FFI_ArrowSchema) }; + let source = unsafe { &mut *(address(object, ce, "arrowArrayAddress")? as *mut FFI_ArrowArray) }; + + if schema.format.is_null() || unsafe { CStr::from_ptr(schema.format) }.to_bytes() != b"+s" { + return Err(refused("Arrow C Data batch must be a struct array".to_string())); + } + + if source.release.is_none() { + return Err(refused("Arrow C Data batch is already imported".to_string())); + } + + if source.n_children != schema.n_children || source.length < 0 { + return Err(refused(format!( + "Arrow C Data batch of {} children does not match its schema of {}", + source.n_children, schema.n_children + ))); + } + + let moved = unsafe { std::ptr::read(source) }; + source.release = None; + + let data = unsafe { from_ffi(moved, schema) } + .and_then(|data| data.validate().map(|()| data)) + .map_err(|error| refused(format!("Arrow C Data batch is not a valid struct array: {error}")))?; + + Ok(StructArray::from(data)) +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use arrow_array::ffi::{from_ffi, to_ffi}; + use arrow_array::{Array, ArrayRef, Int64Array, ListArray, StructArray}; + use arrow_array::types::Int64Type; + use arrow_schema::{DataType, Field, Fields}; + + use crate::alloc::allocated_bytes; + + fn batch() -> StructArray { + let ids: ArrayRef = Arc::new(Int64Array::from_iter((0..1000).map(|i| (i % 7 != 0).then_some(i)))); + let lists: ArrayRef = Arc::new(ListArray::from_iter_primitive::( + (0..1000).map(|i| Some(vec![Some(i), None, Some(i * 2)])), + )); + + StructArray::new( + Fields::from(vec![ + Field::new("id", DataType::Int64, true), + Field::new("list", lists.data_type().clone(), true), + ]), + vec![ids, lists], + None, + ) + } + + #[test] + fn an_exported_batch_dropped_unimported_frees_everything() { + let baseline = allocated_bytes(); + + { + let exported = to_ffi(&batch().to_data()).unwrap(); + assert!(allocated_bytes() > baseline); + drop(exported); + } + + assert_eq!(allocated_bytes(), baseline); + } + + #[test] + fn an_exported_batch_imported_then_dropped_frees_everything() { + let baseline = allocated_bytes(); + + { + let (array, schema) = to_ffi(&batch().to_data()).unwrap(); + let imported = StructArray::from(unsafe { from_ffi(array, &schema) }.unwrap()); + assert_eq!(imported.len(), 1000); + assert_eq!(imported, batch()); + drop(schema); + drop(imported); + } + + assert_eq!(allocated_bytes(), baseline); + } +} diff --git a/src/extension/flow-php-ext/src/parquet/canonical.rs b/src/extension/arrow-ext/src/parquet/canonical.rs similarity index 96% rename from src/extension/flow-php-ext/src/parquet/canonical.rs rename to src/extension/arrow-ext/src/parquet/canonical.rs index 625cdb5b00..d619935bfd 100644 --- a/src/extension/flow-php-ext/src/parquet/canonical.rs +++ b/src/extension/arrow-ext/src/parquet/canonical.rs @@ -1,5 +1,5 @@ //! The cast table between what arrow-rs reads from / writes to Parquet and the canonical arrays: one arrow type per -//! storage (`flow_batch_frame::kind::data_type`'s layout), keyed on the arrow `DataType` alone. Temporal and decimal +//! storage (the layout flow_php's columns store), keyed on the arrow `DataType` alone. Temporal and decimal //! casts are this module's own - `arrow_cast` rounds toward zero and nulls out overflows. use std::sync::Arc; @@ -46,6 +46,7 @@ fn entries(key: DataType, value: DataType) -> FieldRef { } /// The canonical type `canonical()` turns an array of `field`'s type into. +// Must equal flow-batch-frame's kind::data_type() (flow-php-ext), nested names and nullability included - pinned by flow-php-ext phpt 091. pub fn canonical_type(field: &Field) -> Result { canonical_data_type(field.data_type()).map_err(|e| e.in_column(field.name())) } @@ -586,7 +587,6 @@ mod tests { }; use arrow_buffer::i256; use arrow_schema::{DataType, Field, Fields, TimeUnit}; - use flow_batch_frame::kind::{data_type, Field as KindField, Kind}; use super::{canonical, canonical_type, to_parquet}; use crate::parquet::error::Error; @@ -608,12 +608,21 @@ mod tests { array.as_primitive::().iter().collect() } - fn kind(kind: Kind) -> KindField { - KindField { - name: String::new(), - kind, - optional: true, - } + /// The canonical list layout: a nullable `item` child. + fn list_of(element: DataType) -> DataType { + DataType::List(Arc::new(Field::new("item", element, true))) + } + + /// The canonical map layout: `entries` of a non-null `key` and a nullable `value`. + fn map_of(key: DataType, value: DataType) -> DataType { + DataType::Map( + Arc::new(Field::new( + "entries", + DataType::Struct(Fields::from(vec![Field::new("key", key, false), Field::new("value", value, true)])), + false, + )), + false, + ) } #[test] @@ -773,7 +782,7 @@ mod tests { builder.append_value([Some(3)]); let canonical = read(Arc::new(builder.finish())); - assert_eq!(canonical.data_type(), &data_type(&Kind::List(Box::new(kind(Kind::Int64))))); + assert_eq!(canonical.data_type(), &list_of(DataType::Int64)); assert_eq!(int64(canonical.as_list::().values()), vec![Some(1), Some(2), Some(3)]); assert!(canonical.is_null(1)); } @@ -789,7 +798,7 @@ mod tests { let canonical = read(Arc::new(array)); let list = canonical.as_list::(); - assert_eq!(canonical.data_type(), &data_type(&Kind::List(Box::new(kind(Kind::Int64))))); + assert_eq!(canonical.data_type(), &list_of(DataType::Int64)); assert_eq!(list.value_offsets(), &[0, 2, 2]); assert_eq!(int64(list.values()), vec![Some(1), None]); } @@ -805,7 +814,7 @@ mod tests { assert_eq!( canonical.data_type(), - &data_type(&Kind::Map(Box::new(kind(Kind::Bytes)), Box::new(kind(Kind::Int64)))) + &map_of(DataType::Binary, DataType::Int64) ); assert_eq!(int64(canonical.as_map().values()), vec![Some(1)]); assert!(canonical.is_null(1)); @@ -824,17 +833,9 @@ mod tests { assert_eq!( canonical.data_type(), - &data_type(&Kind::Struct(vec![ - KindField { - name: "id".into(), - kind: Kind::Int64, - optional: false - }, - KindField { - name: "name".into(), - kind: Kind::Bytes, - optional: false - }, + &DataType::Struct(Fields::from(vec![ + Field::new("id", DataType::Int64, true), + Field::new("name", DataType::Binary, true), ])) ); assert_eq!(int64(canonical.as_struct().column(0)), vec![Some(1), Some(2)]); @@ -966,6 +967,14 @@ mod tests { assert_eq!(unscaled(vec![Some(-5.0)], 1, -1).unwrap(), vec![Some(-5)]); } + #[test] + fn to_parquet_rounds_decimals_of_binary_fractions_half_away_from_zero() { + assert_eq!( + unscaled(vec![Some(0.125), Some(2.675), Some(-0.125), Some(1.005), Some(9.995), Some(-99.995)], 9, 2).unwrap(), + vec![Some(13), Some(268), Some(-13), Some(101), Some(1_000), Some(-10_000)] + ); + } + #[test] fn to_parquet_refuses_decimals_beyond_their_precision() { assert!(matches!(unscaled(vec![Some(1.0), Some(100.0)], 4, 2), Err(Error::Overflow { row: 1, .. }))); @@ -1115,7 +1124,6 @@ mod tests { #[test] fn to_parquet_renames_nested_children_to_the_target() { - let key = kind(Kind::Bytes); let map = read({ let mut builder = MapBuilder::new(None, StringBuilder::new(), Int32Builder::new()); builder.keys().append_value("a"); @@ -1135,7 +1143,7 @@ mod tests { false, ); - assert_eq!(map.data_type(), &data_type(&Kind::Map(Box::new(key), Box::new(kind(Kind::Int64))))); + assert_eq!(map.data_type(), &map_of(DataType::Binary, DataType::Int64)); assert_eq!(to_parquet(&map, &target).unwrap().data_type(), &target); let structure = read(Arc::new(StructArray::from(vec![( diff --git a/src/extension/arrow-ext/src/parquet/cells.rs b/src/extension/arrow-ext/src/parquet/cells.rs new file mode 100644 index 0000000000..36ab5408f8 --- /dev/null +++ b/src/extension/arrow-ext/src/parquet/cells.rs @@ -0,0 +1,1098 @@ +//! The `Flow\Parquet` lib's per-cell values over the core's canonical arrays: what `PhpParquetEngine` returns for a +//! Parquet value on read, and what it accepts per target type on write. + +use std::any::Any; +use std::sync::Arc; + +use arrow_array::builder::{ + ArrayBuilder, BinaryBuilder, BooleanBuilder, Date32Builder, DurationMicrosecondBuilder, FixedSizeBinaryBuilder, + Float64Builder, Int64Builder, ListBuilder, MapBuilder, MapFieldNames, TimestampMicrosecondBuilder, +}; +use arrow_array::cast::AsArray; +use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; +use arrow_array::{Array, ArrayRef, StructArray}; +use arrow_buffer::NullBufferBuilder; +use arrow_schema::{DataType, Field, Fields, TimeUnit}; +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::{ZendHashTable, ZendObject, Zval}; +use ext_php_rs::zend::{ClassEntry, Function}; + +use crate::exception::ext_exception; +use crate::parquet::error::Error; +use crate::php::{ + call_handle_transparent, ce_method_ref, find_class, ht_for_each, ht_get, ht_insert, ht_insert_long, + read_property, zval_long, zval_str, +}; +use crate::values::{date_from_days, datetime_days, datetime_from_micros, datetime_micros, uuid_bytes, uuid_text}; + +const UUID: &str = "arrow.uuid"; + +fn is_uuid(field: &Field) -> bool { + field.extension_type_name() == Some(UUID) +} + +fn unsupported(data_type: &DataType) -> Error { + Error::Unsupported { + column: String::new(), + parquet: data_type.to_string(), + } +} + +fn collected(error: impl std::fmt::Debug) -> PhpException { + ext_exception(format!("arrow failed to collect a Parquet value: {error:?}")) +} + +/// How a canonical array's values become PHP values, per `PhpParquetEngine`. +pub enum ReadCell { + Null, + Bool, + Int, + Float, + Bytes, + /// `FixedSizeBinary(16)` under `arrow.uuid`: the lowercase 36-char text. + Uuid, + Date, + Timestamp, + Time, + List(Box), + Map(Box, Box), + Struct(Vec<(Vec, ReadCell)>), +} + +impl ReadCell { + /// `canonical`: the type the core reads the column as; `parquet`: the field it was read from (its extension type + /// tells a uuid from 16 bytes), walked in parallel with the canonical type's children. + pub fn new(canonical: &DataType, parquet: &Field) -> Result { + Ok(match canonical { + DataType::Null => ReadCell::Null, + DataType::Boolean => ReadCell::Bool, + DataType::Int64 => ReadCell::Int, + DataType::Float64 => ReadCell::Float, + DataType::Binary => ReadCell::Bytes, + DataType::FixedSizeBinary(16) if is_uuid(parquet) => ReadCell::Uuid, + DataType::FixedSizeBinary(16) => ReadCell::Bytes, + DataType::Date32 => ReadCell::Date, + DataType::Timestamp(_, _) => ReadCell::Timestamp, + DataType::Duration(_) => ReadCell::Time, + DataType::List(element) => ReadCell::List(Box::new(Self::new(element.data_type(), child(parquet, 0)?)?)), + DataType::Map(entries, _) => { + let DataType::Struct(fields) = entries.data_type() else { + return Err(unsupported(canonical)); + }; + let parquet_entries = child(parquet, 0)?; + let key = Self::new(fields[0].data_type(), child(parquet_entries, 0)?)?; + + if !matches!(key, ReadCell::Int | ReadCell::Bytes | ReadCell::Uuid) { + return Err(Error::MapKey { + column: String::new(), + key: key.php_type(), + }); + } + + ReadCell::Map( + Box::new(key), + Box::new(Self::new(fields[1].data_type(), child(parquet_entries, 1)?)?), + ) + } + DataType::Struct(fields) => ReadCell::Struct( + fields + .iter() + .enumerate() + .map(|(index, field)| { + Ok((field.name().as_bytes().to_vec(), Self::new(field.data_type(), child(parquet, index)?)?)) + }) + .collect::>()?, + ), + other => return Err(unsupported(other)), + }) + } + + /// The PHP type this cell's values have: what a MAP key refusal names. + fn php_type(&self) -> &'static str { + match self { + ReadCell::Null => "null", + ReadCell::Bool => "bool", + ReadCell::Int => "int", + ReadCell::Float => "float", + ReadCell::Bytes | ReadCell::Uuid => "string", + ReadCell::Date | ReadCell::Timestamp => "DateTimeImmutable", + ReadCell::Time => "DateInterval", + ReadCell::List(_) | ReadCell::Map(_, _) | ReadCell::Struct(_) => "array", + } + } + + pub fn needs_times(&self) -> bool { + match self { + ReadCell::Time => true, + ReadCell::List(element) => element.needs_times(), + ReadCell::Map(key, value) => key.needs_times() || value.needs_times(), + ReadCell::Struct(children) => children.iter().any(|(_, child)| child.needs_times()), + _ => false, + } + } + + /// Every value of `array` as a PHP list. + pub fn values(&self, array: &ArrayRef, times: Option<&Times>) -> Result { + let mut list = ZendHashTable::with_capacity(u32::try_from(array.len()).unwrap_or(u32::MAX)); + + for row in 0..array.len() { + list.push(self.value(array.as_ref(), row, times)?).map_err(collected)?; + } + + let mut zv = Zval::new(); + zv.set_hashtable(list); + + Ok(zv) + } + + fn value(&self, array: &dyn Array, row: usize, times: Option<&Times>) -> Result { + let mut zv = Zval::new(); + + if array.is_null(row) { + return Ok(zv); + } + + match self { + ReadCell::Null => {} + ReadCell::Bool => zv.set_bool(array.as_boolean().value(row)), + ReadCell::Int => zv = zval_long(array.as_primitive::().value(row)), + ReadCell::Float => zv.set_double(array.as_primitive::().value(row)), + ReadCell::Bytes => { + zv = zval_str(match array.data_type() { + DataType::FixedSizeBinary(_) => array.as_fixed_size_binary().value(row), + _ => array.as_binary::().value(row), + }); + } + ReadCell::Uuid => zv = zval_str(&uuid_text(array.as_fixed_size_binary().value(row))), + ReadCell::Date => zv = date_from_days(i64::from(array.as_primitive::().value(row)))?, + ReadCell::Timestamp => { + zv = datetime_from_micros(array.as_primitive::().value(row), b"+00:00")?; + } + ReadCell::Time => { + zv = times + .ok_or_else(|| ext_exception("arrow Parquet reader has no TIME base"))? + .interval(array.as_primitive::().value(row))?; + } + ReadCell::List(element) => { + let list = array.as_list::(); + let offsets = list.value_offsets(); + let mut values = ZendHashTable::with_capacity((offsets[row + 1] - offsets[row]) as u32); + + for index in offsets[row] as usize..offsets[row + 1] as usize { + values.push(element.value(list.values().as_ref(), index, times)?).map_err(collected)?; + } + + zv.set_hashtable(values); + } + ReadCell::Map(key, value) => { + let map = array.as_map(); + let offsets = map.value_offsets(); + let mut entries = ZendHashTable::with_capacity((offsets[row + 1] - offsets[row]) as u32); + + for index in offsets[row] as usize..offsets[row + 1] as usize { + let entry = value.value(map.values().as_ref(), index, times)?; + + match key.value(map.keys().as_ref(), index, times)? { + k if k.is_long() => ht_insert_long(&mut entries, k.long().unwrap_or_default(), entry), + k => ht_insert(&mut entries, k.zend_str().map_or(&b""[..], |key| key.as_bytes()), entry), + } + } + + zv.set_hashtable(entries); + } + ReadCell::Struct(children) => { + let structure = array.as_struct(); + let mut values = ZendHashTable::with_capacity(children.len() as u32); + + for ((name, child), column) in children.iter().zip(structure.columns()) { + ht_insert(&mut values, name, child.value(column.as_ref(), row, times)?); + } + + zv.set_hashtable(values); + } + } + + Ok(zv) + } +} + +/// Child `index` of a nested Parquet-side field. +fn child(parquet: &Field, index: usize) -> Result<&Field, Error> { + match parquet.data_type() { + DataType::List(element) | DataType::LargeList(element) | DataType::FixedSizeList(element, _) if index == 0 => { + Ok(element) + } + DataType::Map(entries, _) if index == 0 => Ok(entries), + DataType::Struct(fields) if index < fields.len() => Ok(&fields[index]), + other => Err(unsupported(other)), + } +} + +/// `TimeConverter::toDateInterval()`: `$base->diff($base->modify("+{µs} microseconds"))` - `diff()` normalises the +/// duration into d/h and, past a month, m/d exactly as the PHP engine's value. A time of day (< 24 h) normalises into +/// nothing, so it is built directly with `DateInterval::__set_state()`, one call instead of two. +pub struct Times { + base: Zval, + modify: &'static Function, + diff: &'static Function, + set_state: &'static Function, +} + +const DAY: i64 = 86_400_000_000; + +impl Times { + /// `$base = new DateTimeImmutable('1970-01-01 00:00:00.000000', new DateTimeZone('UTC'))`, built once per reader. + pub fn new() -> Result { + let ce = find_class("DateTimeImmutable")?; + + Ok(Self { + base: datetime_from_micros(0, b"UTC")?, + modify: ce_method_ref(ce, "modify")?, + diff: ce_method_ref(ce, "diff")?, + set_state: ce_method_ref(find_class("DateInterval")?, "__set_state")?, + }) + } + + fn interval(&self, micros: i64) -> Result { + if (0..DAY).contains(µs) { + return self.time_of_day(micros); + } + + let base = self.base.object().ok_or_else(|| ext_exception("arrow expected a TIME base datetime"))?; + let target = call_handle_transparent( + self.modify, + Some(base), + &mut [zval_str(format!("+{micros} microseconds").as_bytes())], + )?; + + call_handle_transparent(self.diff, Some(base), &mut [target]) + } + + /// `diff()`'s interval of a time of day: `days` 0, `f` from the whole microseconds. + fn time_of_day(&self, micros: i64) -> Result { + let mut state = ZendHashTable::with_capacity(10); + let double = |value: f64| { + let mut zv = Zval::new(); + zv.set_double(value); + zv + }; + + for (name, value) in [ + ("y", 0), + ("m", 0), + ("d", 0), + ("h", micros / 3_600_000_000), + ("i", micros / 60_000_000 % 60), + ("s", micros / 1_000_000 % 60), + ] { + ht_insert(&mut state, name.as_bytes(), zval_long(value)); + } + + // __set_state() stores `f` as (int) (f * 1e6): the half microsecond keeps the truncation on the exact value + // (0.519488 * 1e6 = 519487.99…), and `f` reads back as that value / 1e6, as diff()'s does + ht_insert(&mut state, b"f", double(((micros % 1_000_000) as f64 + 0.5) / 1_000_000.0)); + ht_insert(&mut state, b"invert", zval_long(0)); + ht_insert(&mut state, b"days", zval_long(0)); + let mut from_string = Zval::new(); + from_string.set_bool(false); + ht_insert(&mut state, b"from_string", from_string); + + let mut array = Zval::new(); + array.set_hashtable(state); + + call_handle_transparent(self.set_state, None, &mut [array]) + } +} + + +/// A value `WriteCell::check` refuses. +pub enum Refusal { + /// What the target type accepts and what it got. + Value { expected: &'static str, got: String }, + /// A byte buffer past i32 offsets, or a day past i32. + Overflow, + /// A PHP exception a call into the value threw. + Php(PhpException), +} + +impl From for Refusal { + fn from(exception: PhpException) -> Self { + Refusal::Php(exception) + } +} + +/// `get_debug_type()`. +fn debug_type(value: &Zval) -> String { + if value.is_null() { + "null".to_string() + } else if value.is_bool() { + "bool".to_string() + } else if value.is_long() { + "int".to_string() + } else if value.is_double() { + "float".to_string() + } else if value.is_string() { + "string".to_string() + } else if value.is_array() { + "array".to_string() + } else if let Some(object) = value.object() { + object.get_class_name().unwrap_or_else(|_| "object".to_string()) + } else { + "unknown".to_string() + } +} + +fn refused(expected: &'static str, value: &Zval) -> Refusal { + Refusal::Value { + expected, + got: debug_type(value), + } +} + +/// The classes the write cells test instances of, resolved once per writer. +pub struct Classes { + datetime: &'static ClassEntry, + interval: &'static ClassEntry, +} + +impl Classes { + pub fn new() -> Result { + Ok(Self { + datetime: find_class("DateTimeInterface")?, + interval: find_class("DateInterval")?, + }) + } +} + +/// A value a scalar cell accepted. `Copy`: a flat writer's row buffer clears without dropping anything. +#[derive(Clone, Copy)] +pub enum Scalar<'a> { + Null, + Bool(bool), + Int(i64), + Float(f64), + Bytes(&'a [u8]), + Uuid([u8; 16]), + Date(i32), + Micros(i64), +} + +impl Scalar<'_> { + /// The same value with its bytes, if any, read from `bytes`: a map key checked from a key zval built for the + /// check, whose bytes are the array key's. + fn rebound(self, bytes: &[u8]) -> Scalar<'_> { + match self { + Scalar::Null => Scalar::Null, + Scalar::Bool(value) => Scalar::Bool(value), + Scalar::Int(value) => Scalar::Int(value), + Scalar::Float(value) => Scalar::Float(value), + Scalar::Bytes(_) => Scalar::Bytes(bytes), + Scalar::Uuid(value) => Scalar::Uuid(value), + Scalar::Date(days) => Scalar::Date(days), + Scalar::Micros(micros) => Scalar::Micros(micros), + } + } +} + +fn missing<'a>(nullable: bool) -> Result, Refusal> { + match nullable { + true => Ok(Scalar::Null), + false => Err(Refusal::Value { + expected: "a value", + got: "null".to_string(), + }), + } +} + +/// A value a cell accepted, as its canonical builder appends it. +pub enum Validated<'a> { + Scalar(Scalar<'a>), + List(Vec>), + Map(Vec<(Validated<'a>, Validated<'a>)>), + Struct(Vec>), +} + +/// What a writer buffers per cell of a row until the whole row is checked: `Scalar` when every writer column is +/// scalar, `Validated` otherwise. +pub trait Checked<'a>: Sized { + fn check(cell: &WriteCell, value: &'a Zval, nullable: bool, classes: &Classes) -> Result; + + /// A writer column the row lacks: null, refused where not `nullable`. + fn missing(nullable: bool) -> Result; + + /// Whether `builder` takes the value with its offsets in i32. + fn fits(&self, cell: &WriteCell, builder: &mut ColumnBuilder) -> bool; + + fn append(&self, cell: &WriteCell, builder: &mut ColumnBuilder); +} + +impl<'a> Checked<'a> for Scalar<'a> { + fn check(cell: &WriteCell, value: &'a Zval, nullable: bool, classes: &Classes) -> Result { + cell.check_scalar(value, nullable, classes) + } + + fn missing(nullable: bool) -> Result { + missing(nullable) + } + + fn fits(&self, _: &WriteCell, builder: &mut ColumnBuilder) -> bool { + match (self, builder) { + (Scalar::Bytes(bytes), ColumnBuilder::Bytes(builder)) => offsets_fit(builder.values_slice().len(), bytes.len()), + _ => true, + } + } + + fn append(&self, cell: &WriteCell, builder: &mut ColumnBuilder) { + cell.append_scalar(builder, self); + } +} + +impl<'a> Checked<'a> for Validated<'a> { + fn check(cell: &WriteCell, value: &'a Zval, nullable: bool, classes: &Classes) -> Result { + cell.check(value, nullable, classes) + } + + fn missing(nullable: bool) -> Result { + missing(nullable).map(Validated::Scalar) + } + + fn fits(&self, cell: &WriteCell, builder: &mut ColumnBuilder) -> bool { + cell.fits(builder, &[self]) + } + + fn append(&self, cell: &WriteCell, builder: &mut ColumnBuilder) { + cell.append(builder, self); + } +} + +/// The builder of a writer cell's canonical type, resolved once per column: appends match it with the cell, nothing +/// is downcast per value. +pub enum ColumnBuilder { + Bool(BooleanBuilder), + Int(Int64Builder), + Float(Float64Builder), + Bytes(BinaryBuilder), + Uuid(FixedSizeBinaryBuilder), + Date(Date32Builder), + Timestamp(TimestampMicrosecondBuilder), + Time(DurationMicrosecondBuilder), + List(Box>), + Map(Box>), + Struct(Box), +} + +pub struct StructColumnBuilder { + fields: Fields, + children: Vec, + nulls: NullBufferBuilder, +} + +impl StructColumnBuilder { + fn finish(&mut self) -> ArrayRef { + let length = self.nulls.len(); + let children = self.children.iter_mut().map(ArrayBuilder::finish).collect(); + + Arc::new( + StructArray::try_new_with_length(self.fields.clone(), children, self.nulls.finish(), length) + .expect("every child appends a slot per struct slot"), + ) + } + + fn finish_cloned(&self) -> ArrayRef { + let children = self.children.iter().map(ArrayBuilder::finish_cloned).collect(); + + Arc::new( + StructArray::try_new_with_length(self.fields.clone(), children, self.nulls.finish_cloned(), self.nulls.len()) + .expect("every child appends a slot per struct slot"), + ) + } +} + +impl ColumnBuilder { + /// `canonical`: what `WriteCell::new()` returned for the cell. + pub fn new(canonical: &DataType, capacity: usize) -> Self { + match canonical { + DataType::Boolean => ColumnBuilder::Bool(BooleanBuilder::with_capacity(capacity)), + DataType::Int64 => ColumnBuilder::Int(Int64Builder::with_capacity(capacity)), + DataType::Float64 => ColumnBuilder::Float(Float64Builder::with_capacity(capacity)), + DataType::Binary => ColumnBuilder::Bytes(BinaryBuilder::with_capacity(capacity, 1024)), + DataType::FixedSizeBinary(size) => ColumnBuilder::Uuid(FixedSizeBinaryBuilder::with_capacity(capacity, *size)), + DataType::Date32 => ColumnBuilder::Date(Date32Builder::with_capacity(capacity)), + DataType::Timestamp(_, _) => ColumnBuilder::Timestamp( + TimestampMicrosecondBuilder::with_capacity(capacity).with_data_type(canonical.clone()), + ), + DataType::Duration(_) => ColumnBuilder::Time(DurationMicrosecondBuilder::with_capacity(capacity)), + DataType::List(element) => ColumnBuilder::List(Box::new( + ListBuilder::with_capacity(Self::new(element.data_type(), capacity), capacity).with_field(Arc::clone(element)), + )), + DataType::Map(entries, _) => { + let DataType::Struct(fields) = entries.data_type() else { + unreachable!("WriteCell::new() builds map entries as a struct") + }; + + ColumnBuilder::Map(Box::new( + MapBuilder::with_capacity( + Some(MapFieldNames { + entry: entries.name().clone(), + key: fields[0].name().clone(), + value: fields[1].name().clone(), + }), + Self::new(fields[0].data_type(), capacity), + Self::new(fields[1].data_type(), capacity), + capacity, + ) + .with_keys_field(Arc::clone(&fields[0])) + .with_values_field(Arc::clone(&fields[1])), + )) + } + DataType::Struct(fields) => ColumnBuilder::Struct(Box::new(StructColumnBuilder { + fields: fields.clone(), + children: fields.iter().map(|field| Self::new(field.data_type(), capacity)).collect(), + nulls: NullBufferBuilder::new(capacity), + })), + other => unreachable!("WriteCell::new() builds no {other} column"), + } + } +} + +impl ArrayBuilder for ColumnBuilder { + fn len(&self) -> usize { + match self { + ColumnBuilder::Bool(builder) => builder.len(), + ColumnBuilder::Int(builder) => builder.len(), + ColumnBuilder::Float(builder) => builder.len(), + ColumnBuilder::Bytes(builder) => builder.len(), + ColumnBuilder::Uuid(builder) => builder.len(), + ColumnBuilder::Date(builder) => builder.len(), + ColumnBuilder::Timestamp(builder) => builder.len(), + ColumnBuilder::Time(builder) => builder.len(), + ColumnBuilder::List(builder) => builder.len(), + ColumnBuilder::Map(builder) => builder.len(), + ColumnBuilder::Struct(builder) => builder.nulls.len(), + } + } + + fn finish(&mut self) -> ArrayRef { + match self { + ColumnBuilder::Bool(builder) => Arc::new(builder.finish()), + ColumnBuilder::Int(builder) => Arc::new(builder.finish()), + ColumnBuilder::Float(builder) => Arc::new(builder.finish()), + ColumnBuilder::Bytes(builder) => Arc::new(builder.finish()), + ColumnBuilder::Uuid(builder) => Arc::new(builder.finish()), + ColumnBuilder::Date(builder) => Arc::new(builder.finish()), + ColumnBuilder::Timestamp(builder) => Arc::new(builder.finish()), + ColumnBuilder::Time(builder) => Arc::new(builder.finish()), + ColumnBuilder::List(builder) => Arc::new(builder.finish()), + ColumnBuilder::Map(builder) => Arc::new(builder.finish()), + ColumnBuilder::Struct(builder) => builder.finish(), + } + } + + fn finish_cloned(&self) -> ArrayRef { + match self { + ColumnBuilder::Bool(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Int(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Float(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Bytes(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Uuid(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Date(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Timestamp(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Time(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::List(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Map(builder) => Arc::new(builder.finish_cloned()), + ColumnBuilder::Struct(builder) => builder.finish_cloned(), + } + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn into_box_any(self: Box) -> Box { + self + } +} + +/// Offsets stay i32: `current` entries plus `added` must not pass `i32::MAX`. +fn offsets_fit(current: usize, added: usize) -> bool { + current.checked_add(added).is_some_and(|total| total <= i32::MAX as usize) +} + +/// What a writer column accepts per `PhpParquetEngine`'s target type, appended to its canonical type's builder; the +/// cast to the Parquet type (`to_parquet`) refuses what is out of the target's range. +pub enum WriteCell { + Bool, + Int, + Float, + /// DECIMAL: a float or an int. + Decimal, + Bytes, + /// UUID: a string, or an object's `toString()` / `__toString()`, whose dash-less text is 32 hex digits. + Uuid, + Date, + Timestamp, + Time, + List(Box, bool), + Map(Box, Box, bool), + Struct(Vec<(Vec, WriteCell, bool)>), +} + +impl WriteCell { + /// The cell for a writer schema field (`Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension()`), and the + /// canonical type its values are built in. + pub fn new(target: &Field) -> Result<(Self, DataType), Error> { + Ok(match target.data_type() { + DataType::Boolean => (WriteCell::Bool, DataType::Boolean), + DataType::Int8 + | DataType::Int16 + | DataType::Int32 + | DataType::Int64 + | DataType::UInt8 + | DataType::UInt16 + | DataType::UInt32 + | DataType::UInt64 => (WriteCell::Int, DataType::Int64), + DataType::Float32 | DataType::Float64 => (WriteCell::Float, DataType::Float64), + DataType::Decimal128(_, _) => (WriteCell::Decimal, DataType::Float64), + DataType::Utf8 | DataType::Binary => (WriteCell::Bytes, DataType::Binary), + DataType::FixedSizeBinary(16) if is_uuid(target) => (WriteCell::Uuid, DataType::FixedSizeBinary(16)), + DataType::FixedSizeBinary(_) => (WriteCell::Bytes, DataType::Binary), + DataType::Date32 => (WriteCell::Date, DataType::Date32), + DataType::Timestamp(_, _) => { + (WriteCell::Timestamp, DataType::Timestamp(TimeUnit::Microsecond, Some("UTC".into()))) + } + DataType::Time32(_) | DataType::Time64(_) => (WriteCell::Time, DataType::Duration(TimeUnit::Microsecond)), + DataType::List(element) => { + let (cell, canonical) = Self::new(element)?; + + ( + WriteCell::List(Box::new(cell), element.is_nullable()), + DataType::List(Arc::new(Field::new("item", canonical, true))), + ) + } + DataType::Map(entries, _) => { + let DataType::Struct(fields) = entries.data_type() else { + return Err(unsupported(target.data_type())); + }; + let (key, key_type) = Self::new(&fields[0])?; + let (value, value_type) = Self::new(&fields[1])?; + + ( + WriteCell::Map(Box::new(key), Box::new(value), fields[1].is_nullable()), + DataType::Map( + Arc::new(Field::new( + "entries", + DataType::Struct(Fields::from(vec![ + Field::new("key", key_type, false), + Field::new("value", value_type, true), + ])), + false, + )), + false, + ), + ) + } + DataType::Struct(fields) => { + let mut cells = Vec::with_capacity(fields.len()); + let mut children = Vec::with_capacity(fields.len()); + + for field in fields { + let (cell, canonical) = Self::new(field)?; + cells.push((field.name().as_bytes().to_vec(), cell, field.is_nullable())); + children.push(Field::new(field.name(), canonical, true)); + } + + (WriteCell::Struct(cells), DataType::Struct(Fields::from(children))) + } + other => return Err(unsupported(other)), + }) + } + + /// `value` as this scalar cell accepts it, a null only where `nullable`; a nested cell refuses it as not an + /// array. + pub fn check_scalar<'a>(&self, value: &'a Zval, nullable: bool, classes: &Classes) -> Result, Refusal> { + let value = value.dereference(); + + if value.is_null() { + return if nullable { Ok(Scalar::Null) } else { Err(refused("a value", value)) }; + } + + Ok(match self { + WriteCell::Bool => Scalar::Bool(value.bool().ok_or_else(|| refused("bool", value))?), + WriteCell::Int => Scalar::Int(value.long().ok_or_else(|| refused("int", value))?), + WriteCell::Float => Scalar::Float(value.double().ok_or_else(|| refused("float", value))?), + WriteCell::Decimal => Scalar::Float(match (value.double(), value.long()) { + (Some(float), _) => float, + (_, Some(int)) => int as f64, + _ => return Err(refused("float or int", value)), + }), + WriteCell::Bytes => { + Scalar::Bytes(value.zend_str().ok_or_else(|| refused("string", value))?.as_bytes()) + } + WriteCell::Uuid => { + let text = match value.object() { + Some(object) => uuid_text_of(object)?.ok_or_else(|| refused("uuid string or object", value))?, + None => value.shallow_clone(), + }; + + Scalar::Uuid( + text.zend_str() + .and_then(|text| uuid_bytes(text.as_bytes())) + .ok_or_else(|| refused("uuid string or object", value))?, + ) + } + WriteCell::Date => { + let datetime = datetime(value, classes).ok_or_else(|| refused("DateTimeInterface", value))?; + let days = match datetime_days(datetime) { + Some(days) => days, + None => fallback_days(datetime)?, + }; + + Scalar::Date(i32::try_from(days).map_err(|_| Refusal::Overflow)?) + } + WriteCell::Timestamp => { + let datetime = datetime(value, classes).ok_or_else(|| refused("DateTimeInterface", value))?; + + Scalar::Micros(match datetime_micros(datetime) { + Some(micros) => micros, + None => fallback_micros(datetime)?, + }) + } + WriteCell::Time => { + let interval = value + .object() + .filter(|object| object.instance_of(classes.interval)) + .ok_or_else(|| refused("DateInterval", value))?; + + Scalar::Micros(interval_micros(interval, value)?) + } + WriteCell::List(_, _) | WriteCell::Map(_, _, _) | WriteCell::Struct(_) => return Err(refused("array", value)), + }) + } + + /// `value` as this cell accepts it; a null only where `nullable`. + pub fn check<'a>(&self, value: &'a Zval, nullable: bool, classes: &Classes) -> Result, Refusal> { + let value = value.dereference(); + + if value.is_null() { + return if nullable { Ok(Validated::Scalar(Scalar::Null)) } else { Err(refused("a value", value)) }; + } + + Ok(match self { + WriteCell::List(element, element_nullable) => { + let items = value.array().ok_or_else(|| refused("array", value))?; + let mut values = Vec::with_capacity(items.len()); + let mut failure = None; + + ht_for_each(items, |_, _, item| { + if failure.is_none() { + match element.check(item, *element_nullable, classes) { + Ok(validated) => values.push(validated), + Err(refusal) => failure = Some(refusal), + } + } + + Ok(()) + })?; + + if let Some(refusal) = failure { + return Err(refusal); + } + + Validated::List(values) + } + WriteCell::Map(key, map_value, value_nullable) => { + let items = value.array().ok_or_else(|| refused("array", value))?; + let mut entries = Vec::with_capacity(items.len()); + let mut failure = None; + + ht_for_each(items, |name, index, item| { + if failure.is_some() { + return Ok(()); + } + + let entry_key = match name { + Some(name) => zval_str(name.as_bytes()), + None => zval_long(index as i64), + }; + let checked = key + .check_scalar(&entry_key, false, classes) + .map(|key| Validated::Scalar(key.rebound(name.map_or(&[][..], |name| name.as_bytes())))) + .and_then(|key| Ok((key, map_value.check(item, *value_nullable, classes)?))); + + match checked { + Ok(entry) => entries.push(entry), + Err(refusal) => failure = Some(refusal), + } + + Ok(()) + })?; + + if let Some(refusal) = failure { + return Err(refusal); + } + + Validated::Map(entries) + } + WriteCell::Struct(children) => { + let values = value.array().ok_or_else(|| refused("array", value))?; + let mut checked = Vec::with_capacity(children.len()); + + for (name, cell, child_nullable) in children { + checked.push(match ht_get(values, name) { + Some(child) => cell.check(child, *child_nullable, classes)?, + None => Validated::Scalar(missing(*child_nullable)?), + }); + } + + Validated::Struct(checked) + } + scalar => Validated::Scalar(scalar.check_scalar(value, nullable, classes)?), + }) + } + + /// Whether `builder` takes `values` (one row's, every value bound for it) with its offsets in i32; only cells + /// holding offsets can pass it. + pub fn fits(&self, builder: &mut ColumnBuilder, values: &[&Validated]) -> bool { + match (self, builder) { + (WriteCell::Bytes, ColumnBuilder::Bytes(bytes)) => offsets_fit( + bytes.values_slice().len(), + values + .iter() + .map(|value| match value { + Validated::Scalar(Scalar::Bytes(bytes)) => bytes.len(), + _ => 0, + }) + .sum(), + ), + (WriteCell::List(element, _), ColumnBuilder::List(list)) => { + let items = values + .iter() + .flat_map(|value| match value { + Validated::List(items) => items.as_slice(), + _ => &[], + }) + .collect::>(); + + offsets_fit(list.values().len(), items.len()) && element.fits(list.values(), &items) + } + (WriteCell::Map(key, value, _), ColumnBuilder::Map(map)) => { + let entries = values + .iter() + .flat_map(|value| match value { + Validated::Map(entries) => entries.as_slice(), + _ => &[], + }) + .collect::>(); + let keys = entries.iter().map(|(key, _)| key).collect::>(); + let items = entries.iter().map(|(_, value)| value).collect::>(); + let (key_builder, value_builder) = map.entries(); + + offsets_fit(key_builder.len(), entries.len()) + && key.fits(key_builder, &keys) + && value.fits(value_builder, &items) + } + (WriteCell::Struct(children), ColumnBuilder::Struct(structure)) => { + children.iter().zip(&mut structure.children).enumerate().all(|(index, ((_, cell, _), child))| { + let values = values + .iter() + .filter_map(|value| match value { + Validated::Struct(children) => Some(&children[index]), + _ => None, + }) + .collect::>(); + + cell.fits(child, &values) + }) + } + _ => true, + } + } + + /// `value`, checked by this cell and fit by [`WriteCell::fits`], appended to `builder`. + pub fn append(&self, builder: &mut ColumnBuilder, value: &Validated) { + match (self, builder, value) { + (_, builder, Validated::Scalar(scalar)) => self.append_scalar(builder, scalar), + (WriteCell::List(element, _), ColumnBuilder::List(list), Validated::List(items)) => { + for item in items { + element.append(list.values(), item); + } + + list.append(true); + } + (WriteCell::Map(key, map_value, _), ColumnBuilder::Map(map), Validated::Map(entries)) => { + for (entry_key, entry_value) in entries { + let (keys, values) = map.entries(); + key.append(keys, entry_key); + map_value.append(values, entry_value); + } + + map.append(true).expect("every entry appends a key and a value"); + } + (WriteCell::Struct(children), ColumnBuilder::Struct(structure), Validated::Struct(values)) => { + for (((_, cell, _), child), value) in children.iter().zip(&mut structure.children).zip(values) { + cell.append(child, value); + } + + structure.nulls.append_non_null(); + } + _ => unreachable!("a cell appends only what it checked, to the builder of its canonical type"), + } + } + + /// `scalar`, checked by this cell, appended to `builder`. + pub fn append_scalar(&self, builder: &mut ColumnBuilder, scalar: &Scalar) { + match (self, builder, scalar) { + (_, builder, Scalar::Null) => self.append_null(builder), + (WriteCell::Bool, ColumnBuilder::Bool(builder), Scalar::Bool(value)) => builder.append_value(*value), + (WriteCell::Int, ColumnBuilder::Int(builder), Scalar::Int(value)) => builder.append_value(*value), + (WriteCell::Float | WriteCell::Decimal, ColumnBuilder::Float(builder), Scalar::Float(value)) => { + builder.append_value(*value); + } + (WriteCell::Bytes, ColumnBuilder::Bytes(builder), Scalar::Bytes(bytes)) => builder.append_value(bytes), + (WriteCell::Uuid, ColumnBuilder::Uuid(builder), Scalar::Uuid(bytes)) => { + builder.append_value(bytes).expect("a uuid is 16 bytes"); + } + (WriteCell::Date, ColumnBuilder::Date(builder), Scalar::Date(days)) => builder.append_value(*days), + (WriteCell::Timestamp, ColumnBuilder::Timestamp(builder), Scalar::Micros(micros)) => { + builder.append_value(*micros); + } + (WriteCell::Time, ColumnBuilder::Time(builder), Scalar::Micros(micros)) => builder.append_value(*micros), + _ => unreachable!("a cell appends only what it checked, to the builder of its canonical type"), + } + } + + /// Whether this cell holds one value per row: no list, map or struct. + pub fn is_scalar(&self) -> bool { + !matches!(self, WriteCell::List(_, _) | WriteCell::Map(_, _, _) | WriteCell::Struct(_)) + } + + /// A null slot; a struct's children get one too. + fn append_null(&self, builder: &mut ColumnBuilder) { + match (self, builder) { + (WriteCell::Struct(children), ColumnBuilder::Struct(structure)) => { + for ((_, cell, _), child) in children.iter().zip(&mut structure.children) { + cell.append_null(child); + } + + structure.nulls.append_null(); + } + (_, ColumnBuilder::Bool(builder)) => builder.append_null(), + (_, ColumnBuilder::Int(builder)) => builder.append_null(), + (_, ColumnBuilder::Float(builder)) => builder.append_null(), + (_, ColumnBuilder::Bytes(builder)) => builder.append_null(), + (_, ColumnBuilder::Uuid(builder)) => builder.append_null(), + (_, ColumnBuilder::Date(builder)) => builder.append_null(), + (_, ColumnBuilder::Timestamp(builder)) => builder.append_null(), + (_, ColumnBuilder::Time(builder)) => builder.append_null(), + (_, ColumnBuilder::List(builder)) => builder.append_null(), + (_, ColumnBuilder::Map(builder)) => builder.append(false).expect("a null map appends no entries"), + (_, ColumnBuilder::Struct(_)) => unreachable!("only a struct cell builds a struct column"), + } + } +} + +/// `UuidConverter::toParquetType()`'s text of an object: `toString()`, else `__toString()`; `None` for neither. +fn uuid_text_of(object: &ZendObject) -> Result, PhpException> { + let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("arrow expected a class entry"))?; + + for method in ["toString", "__toString"] { + if let Ok(function) = ce_method_ref(ce, method) { + return call_handle_transparent(function, Some(object), &mut []).map(Some); + } + } + + Ok(None) +} + +fn datetime<'a>(value: &'a Zval, classes: &Classes) -> Option<&'a ZendObject> { + value.object().filter(|object| object.instance_of(classes.datetime)) +} + +fn method_long(object: &ZendObject, method: &str, args: &mut [Zval]) -> Result { + let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("arrow expected a class entry"))?; + let result = call_handle_transparent(ce_method_ref(ce, method)?, Some(object), args)?; + + result + .long() + .or_else(|| result.zend_str().and_then(|text| std::str::from_utf8(text.as_bytes()).ok()?.parse().ok())) + .ok_or_else(|| ext_exception(format!("arrow expected {method}() to return an int"))) +} + +/// `getTimestamp() * 1_000_000 + format('u')`, for a datetime timelib has not brought up to date. +fn fallback_micros(datetime: &ZendObject) -> Result { + let seconds = method_long(datetime, "getTimestamp", &mut [])?; + let micros = method_long(datetime, "format", &mut [zval_str(b"u")])?; + + seconds.checked_mul(1_000_000).and_then(|us| us.checked_add(micros)).ok_or(Refusal::Overflow) +} + +/// `(getTimestamp() + getOffset())` floored to days, for a datetime timelib has not brought up to date. +fn fallback_days(datetime: &ZendObject) -> Result { + let seconds = method_long(datetime, "getTimestamp", &mut [])?; + let offset = method_long(datetime, "getOffset", &mut [])?; + + Ok((seconds + offset).div_euclid(86_400)) +} + +fn interval_part(interval: &ZendObject, name: &str) -> Result { + Ok(read_property(interval, name)?.long().unwrap_or_default()) +} + +/// `TimeConverter::toParquetType()`: `((d·24+h)·3600+i·60+s)·1e6 + (int)(f·1e6)`, `invert` ignored; y or m ≠ 0 is +/// refused. +fn interval_micros(interval: &ZendObject, value: &Zval) -> Result { + if interval_part(interval, "y")? != 0 || interval_part(interval, "m")? != 0 { + return Err(refused("DateInterval without years or months", value)); + } + + let seconds = ((interval_part(interval, "d")? * 24 + interval_part(interval, "h")?) * 3_600 + + interval_part(interval, "i")? * 60 + + interval_part(interval, "s")?) + .checked_mul(1_000_000) + .ok_or(Refusal::Overflow)?; + let fraction = (read_property(interval, "f")?.double().unwrap_or_default() * 1_000_000.0) as i64; + + seconds.checked_add(fraction).ok_or(Refusal::Overflow) +} + +/// Rows appended to one writer column, finished into canonical arrays in batches. +pub struct WriteColumn { + pub name: String, + pub cell: WriteCell, + pub nullable: bool, + pub builder: ColumnBuilder, +} + +impl WriteColumn { + pub fn new(target: &Field, capacity: usize) -> Result { + let (cell, canonical) = WriteCell::new(target).map_err(|e| e.in_column(target.name()))?; + + Ok(Self { + name: target.name().clone(), + builder: ColumnBuilder::new(&canonical, capacity), + cell, + nullable: target.is_nullable(), + }) + } + + /// The rows appended since the last take, as a canonical array; the builder starts over. + pub fn take(&mut self) -> ArrayRef { + self.builder.finish() + } +} + +#[cfg(test)] +mod tests { + use super::offsets_fit; + + #[test] + fn offsets_fit_up_to_i32_max() { + assert!(offsets_fit(i32::MAX as usize - 10, 10)); + assert!(!offsets_fit(i32::MAX as usize - 10, 11)); + assert!(!offsets_fit(usize::MAX, 1)); + } +} diff --git a/src/extension/flow-php-ext/src/parquet/error.rs b/src/extension/arrow-ext/src/parquet/error.rs similarity index 100% rename from src/extension/flow-php-ext/src/parquet/error.rs rename to src/extension/arrow-ext/src/parquet/error.rs diff --git a/src/extension/arrow-ext/src/parquet/exception.rs b/src/extension/arrow-ext/src/parquet/exception.rs deleted file mode 100644 index 2bf15073c3..0000000000 --- a/src/extension/arrow-ext/src/parquet/exception.rs +++ /dev/null @@ -1,25 +0,0 @@ -use ext_php_rs::builders::ClassBuilder; -use ext_php_rs::error::Result; -use ext_php_rs::exception::PhpException; -use ext_php_rs::flags::ClassFlags; -use ext_php_rs::zend::{ce, ClassEntry}; - -fn noop(_ce: &'static mut ClassEntry) {} - -pub fn register() -> Result<()> { - ClassBuilder::new("Flow\\Arrow\\Parquet\\Exception") - .extends((ce::exception, "Exception")) - .flags(ClassFlags::Final) - .registration(noop) - .register()?; - - Ok(()) -} - -fn parquet_exception_ce() -> &'static ClassEntry { - ClassEntry::try_find("Flow\\Arrow\\Parquet\\Exception").unwrap_or_else(|| ce::exception()) -} - -pub fn parquet_exception(message: impl Into) -> PhpException { - PhpException::new(message.into(), 0, parquet_exception_ce()) -} diff --git a/src/extension/flow-php-ext/src/parquet/fetch.rs b/src/extension/arrow-ext/src/parquet/fetch.rs similarity index 100% rename from src/extension/flow-php-ext/src/parquet/fetch.rs rename to src/extension/arrow-ext/src/parquet/fetch.rs diff --git a/src/extension/flow-php-ext/src/parquet/footer.rs b/src/extension/arrow-ext/src/parquet/footer.rs similarity index 100% rename from src/extension/flow-php-ext/src/parquet/footer.rs rename to src/extension/arrow-ext/src/parquet/footer.rs diff --git a/src/extension/flow-php-ext/src/parquet/library.rs b/src/extension/arrow-ext/src/parquet/library.rs similarity index 62% rename from src/extension/flow-php-ext/src/parquet/library.rs rename to src/extension/arrow-ext/src/parquet/library.rs index 7be5a2e7da..3663ae7860 100644 --- a/src/extension/flow-php-ext/src/parquet/library.rs +++ b/src/extension/arrow-ext/src/parquet/library.rs @@ -1,10 +1,10 @@ -//! `Flow\Parquet\Engine\Native\{NativeParquetFile, NativeParquetColumnsReader, NativeParquetRowsWriter}`: the -//! `flow-php/parquet` lib's values over the core - one footer read per file, columns as lists of the values -//! `PhpParquetEngine` returns, rows written as it accepts them. +//! `Flow\Arrow\Parquet\{ParquetFile, ColumnsReader, RowsWriter}`: the `flow-php/parquet` lib's values over the core - +//! one footer read per file, columns as lists of the values `PhpParquetEngine` returns, rows written as it accepts +//! them, and struct batches written as another extension exports them. use std::sync::Arc; -use arrow_array::ArrayRef; +use arrow_array::{new_null_array, Array, ArrayRef}; use ext_php_rs::boxed::ZBox; use ext_php_rs::flags::ClassFlags; use ext_php_rs::prelude::*; @@ -12,8 +12,8 @@ use ext_php_rs::types::{ZendHashTable, Zval}; use parquet::file::metadata::ParquetMetaData; use parquet::file::reader::Length; -use crate::ctx::{ht_for_each, ht_get, ht_insert}; -use crate::parquet::cells::{Classes, ReadCell, Refusal, Times, WriteColumn}; +use crate::parquet::batch; +use crate::parquet::cells::{Checked, Classes, ReadCell, Refusal, Scalar, Times, Validated, WriteColumn}; use crate::parquet::error::Error; use crate::parquet::footer::Footer; use crate::parquet::options; @@ -21,38 +21,39 @@ use crate::parquet::read::{ParquetReader, ReadPlan}; use crate::parquet::sink::PhpSink; use crate::parquet::source::{PhpSource, PhpStream}; use crate::parquet::write::ParquetWriter; -use crate::render::{exception, parquet_exception, Side, Surface}; +use crate::php::{ht_for_each, ht_get, ht_insert}; +use crate::render::{exception, parquet_exception, Side}; use crate::thrift; const FILE_META_DATA: &str = "Flow\\Parquet\\ThriftModel\\FileMetaData"; /// `FileMetaData::$schema`'s field id. const SCHEMA: i16 = 2; const RUNTIME: &str = "Flow\\Parquet\\Exception\\RuntimeException"; -const INVALID_ARGUMENT: &str = "Flow\\Parquet\\Exception\\InvalidArgumentException"; +pub const INVALID_ARGUMENT: &str = "Flow\\Parquet\\Exception\\InvalidArgumentException"; fn closed() -> PhpException { exception(RUNTIME, "Parquet file is closed".to_string()) } -fn rows(value: Option, name: &str) -> PhpResult> { +pub fn rows(value: Option, name: &str) -> PhpResult> { value .map(|value| { u64::try_from(value) - .map_err(|_| exception(INVALID_ARGUMENT, format!("flow_php Parquet {name} must be greater or equal to 0"))) + .map_err(|_| exception(INVALID_ARGUMENT, format!("arrow Parquet {name} must be greater or equal to 0"))) }) .transpose() } -fn batch_size(value: i64) -> PhpResult { +pub fn batch_size(value: i64) -> PhpResult { usize::try_from(value) .ok() .filter(|size| *size > 0) - .ok_or_else(|| exception(INVALID_ARGUMENT, "flow_php Parquet batch size must be greater than 0".to_string())) + .ok_or_else(|| exception(INVALID_ARGUMENT, "arrow Parquet batch size must be greater than 0".to_string())) } #[php_class] -#[php(name = "Flow\\Parquet\\Engine\\Native\\NativeParquetFile", flags = ClassFlags::Final)] -pub struct NativeParquetFile { +#[php(name = "Flow\\Arrow\\Parquet\\ParquetFile", flags = ClassFlags::Final)] +pub struct ParquetFile { stream: Arc, source: PhpSource, footer: Footer, @@ -61,7 +62,7 @@ pub struct NativeParquetFile { closed: bool, } -impl NativeParquetFile { +impl ParquetFile { fn open(&self) -> PhpResult<()> { if self.closed { return Err(closed()); @@ -70,7 +71,7 @@ impl NativeParquetFile { Ok(()) } - /// The file's stream, size and footer, for a reader of it: the ETL's `NativeParquetReader` or the lib's. + /// The file's stream, size and footer, for a reader of it: the lib's `ColumnsReader` or a `BatchReader`. pub fn read(&self) -> PhpResult<(&Arc, u64, &Arc)> { self.open()?; @@ -79,11 +80,11 @@ impl NativeParquetFile { } #[php_impl] -impl NativeParquetFile { +impl ParquetFile { /// Reads and decodes the footer; owns the stream from here on. pub fn __construct(stream: &Zval) -> PhpResult { let stream = Arc::new(PhpStream::new(stream)?); - let refused = |error| parquet_exception(error, &stream, Side::Read, Surface::Lib); + let refused = |error| parquet_exception(error, &stream, Side::Read); let source = PhpSource::new(Arc::clone(&stream)).map_err(refused)?; let footer = Footer::read(&source).map_err(refused)?; @@ -153,15 +154,14 @@ impl NativeParquetFile { Error::Stream("close() threw".to_string()), &self.stream, Side::Read, - Surface::Lib, )), } } } #[php_class] -#[php(name = "Flow\\Parquet\\Engine\\Native\\NativeParquetColumnsReader", flags = ClassFlags::Final)] -pub struct NativeParquetColumnsReader { +#[php(name = "Flow\\Arrow\\Parquet\\ColumnsReader", flags = ClassFlags::Final)] +pub struct ColumnsReader { reader: Option, stream: Arc, columns: Vec<(Vec, ReadCell)>, @@ -169,10 +169,10 @@ pub struct NativeParquetColumnsReader { } #[php_impl] -impl NativeParquetColumnsReader { +impl ColumnsReader { /// `$columns`: root names or struct paths; `$batchSize` rows at most per `next()`. pub fn __construct( - file: &NativeParquetFile, + file: &ParquetFile, columns: &ZendHashTable, batch_size: i64, offset: Option, @@ -182,13 +182,13 @@ impl NativeParquetColumnsReader { let (offset, limit) = (rows(offset, "offset")?.unwrap_or(0), rows(limit, "limit")?); let (stream, size, meta) = file.read()?; let stream = Arc::clone(stream); - let refused = |error| parquet_exception(error, &stream, Side::Read, Surface::Lib); + let refused = |error| parquet_exception(error, &stream, Side::Read); let mut names = Vec::with_capacity(columns.len()); ht_for_each(columns, |_, _, name| { names.push( name.str() - .ok_or_else(|| exception(INVALID_ARGUMENT, "flow_php Parquet column names must be strings".to_string()))? + .ok_or_else(|| exception(INVALID_ARGUMENT, "arrow Parquet column names must be strings".to_string()))? .to_string(), ); @@ -229,7 +229,7 @@ impl NativeParquetColumnsReader { } Some(batch) => { batch - .map_err(|error| parquet_exception(error, &self.stream, Side::Read, Surface::Lib))? + .map_err(|error| parquet_exception(error, &self.stream, Side::Read))? .1 } }; @@ -249,25 +249,48 @@ impl NativeParquetColumnsReader { } #[php_class] -#[php(name = "Flow\\Parquet\\Engine\\Native\\NativeParquetRowsWriter", flags = ClassFlags::Final)] -pub struct NativeParquetRowsWriter { +#[php(name = "Flow\\Arrow\\Parquet\\RowsWriter", flags = ClassFlags::Final)] +pub struct RowsWriter { writer: Option, stream: Arc, columns: Vec, classes: Classes, buffered: usize, + /// Every column holds one value per row: rows are checked into `Scalar`s. + scalar: bool, batch_size: usize, } -impl Drop for NativeParquetRowsWriter { +impl Drop for RowsWriter { fn drop(&mut self) { self.stream.detach(); } } -impl NativeParquetRowsWriter { +impl RowsWriter { fn refused(&self, error: Error) -> PhpException { - parquet_exception(error, &self.stream, Side::Write, Surface::Lib) + parquet_exception(error, &self.stream, Side::Write) + } + + fn open(&self) -> PhpResult<()> { + match self.writer { + Some(_) => Ok(()), + None => Err(exception(RUNTIME, "Writer is not open".to_string())), + } + } + + /// The refusal of `column` at buffered row `row`. + fn refusal(&self, refusal: Refusal, column: String, row: usize) -> PhpException { + match refusal { + Refusal::Value { expected, got } => self.refused(Error::Value { + column, + row, + expected, + got, + }), + Refusal::Overflow => self.refused(Error::Overflow { column, row }), + Refusal::Php(exception) => exception, + } } /// The buffered rows through `ParquetWriter::write`. @@ -276,56 +299,62 @@ impl NativeParquetRowsWriter { return Ok(()); } - let arrays = self - .columns - .iter_mut() - .map(WriteColumn::take) - .collect::, Error>>() - .map_err(|error| self.refused(error))?; + let arrays = self.columns.iter_mut().map(WriteColumn::take).collect::>(); let rows = std::mem::take(&mut self.buffered); let writer = self.writer.as_mut().ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; writer .write(rows, &arrays) - .map_err(|error| parquet_exception(error, &self.stream, Side::Write, Surface::Lib)) + .map_err(|error| parquet_exception(error, &self.stream, Side::Write)) } - fn append(&mut self, row: &Zval) -> PhpResult<()> { - if self.writer.is_none() { - return Err(exception(RUNTIME, "Writer is not open".to_string())); + /// One row whose every column was checked (`value` of column index): appended, unless a column's offsets would + /// pass i32, which refuses the row whole before anything is appended. + fn append_checked<'a, 'b, V: Checked<'a> + 'b>(&mut self, value: impl Fn(usize) -> &'b V) -> PhpResult<()> { + let overflow = self + .columns + .iter_mut() + .enumerate() + .position(|(index, column)| !value(index).fits(&column.cell, &mut column.builder)); + + if let Some(index) = overflow { + return Err(self.refused(Error::Overflow { + column: self.columns[index].name.clone(), + row: self.buffered, + })); } - let row = row - .array() - .ok_or_else(|| exception(INVALID_ARGUMENT, "flow_php Parquet writer rows must be arrays".to_string()))?; - let null = Zval::new(); + for (index, column) in self.columns.iter_mut().enumerate() { + value(index).append(&column.cell, &mut column.builder); + } - for index in 0..self.columns.len() { - let column = &mut self.columns[index]; - let value = ht_get(row, column.name.as_bytes()).unwrap_or(&null); + self.buffered += 1; - if let Err(refusal) = column.cell.append(&mut column.builder, value, column.nullable, &self.classes) { - let (name, row) = (column.name.clone(), self.buffered); + Ok(()) + } - // the row is refused whole: the columns before this one drop what it appended to them - for column in &mut self.columns[..=index] { - column.builder.truncate(row); - } + /// A row is checked whole into `checked` first; a refused row appends nothing. + fn append<'a, V: Checked<'a>>(&mut self, row: &'a Zval, checked: &mut Vec) -> PhpResult<()> { + self.open()?; - return Err(match refusal { - Refusal::Value { expected, got } => self.refused(Error::Value { - column: name, - row, - expected, - got, - }), - Refusal::Overflow => self.refused(Error::Overflow { column: name, row }), - Refusal::Php(exception) => exception, - }); + let row = row + .array() + .ok_or_else(|| exception(INVALID_ARGUMENT, "arrow Parquet writer rows must be arrays".to_string()))?; + checked.clear(); + + for column in &self.columns { + let value = match ht_get(row, column.name.as_bytes()) { + Some(value) => V::check(&column.cell, value, column.nullable, &self.classes), + None => V::missing(column.nullable), + }; + + match value { + Ok(value) => checked.push(value), + Err(refusal) => return Err(self.refusal(refusal, column.name.clone(), self.buffered)), } } - self.buffered += 1; + self.append_checked(|index| &checked[index])?; if self.buffered >= self.batch_size { self.flush()?; @@ -334,53 +363,57 @@ impl NativeParquetRowsWriter { Ok(()) } + fn append_rows<'a, V: Checked<'a>>(&mut self, rows: &'a ZendHashTable) -> PhpResult<()> { + let mut checked = Vec::with_capacity(self.columns.len()); + + for row in rows.values() { + self.append::(row, &mut checked)?; + } + + Ok(()) + } + /// `rows` values of every column from `first` on, column by column; a refused cell lowers the row limit of the /// columns after it, so the refusal raised and the rows kept are those of `append()` row by row. - fn append_columns(&mut self, lists: &[Option>], first: usize, rows: usize) -> PhpResult<()> { - let null = Zval::new(); + fn append_columns<'a, V: Checked<'a>>(&mut self, lists: &[Option>], first: usize, rows: usize) -> PhpResult<()> { let mut limit = rows; let mut refused = None; + let mut checked: Vec> = Vec::with_capacity(self.columns.len()); - for (index, column) in self.columns.iter_mut().enumerate() { - let refusal = (0..limit).find_map(|row| { - let value = lists[index].as_ref().map_or(&null, |values| values[first + row]); + for (index, column) in self.columns.iter().enumerate() { + let mut values = Vec::with_capacity(limit); + let mut stop = None; + + for row in 0..limit { + let value = match &lists[index] { + Some(values) => V::check(&column.cell, values[first + row], column.nullable, &self.classes), + None => V::missing(column.nullable), + }; - column - .cell - .append(&mut column.builder, value, column.nullable, &self.classes) - .err() - .map(|refusal| (row, refusal)) - }); + match value { + Ok(value) => values.push(value), + Err(refusal) => { + stop = Some((row, refusal)); - if let Some((row, refusal)) = refusal { + break; + } + } + } + + if let Some((row, refusal)) = stop { limit = row; refused = Some((column.name.clone(), refusal)); } + + checked.push(values); } - let kept = self.buffered + limit; + (0..limit).try_for_each(|row| self.append_checked(|index| &checked[index][row]))?; if let Some((name, refusal)) = refused { - for column in &mut self.columns { - column.builder.truncate(kept); - } - - self.buffered = kept; - - return Err(match refusal { - Refusal::Value { expected, got } => self.refused(Error::Value { - column: name, - row: kept, - expected, - got, - }), - Refusal::Overflow => self.refused(Error::Overflow { column: name, row: kept }), - Refusal::Php(exception) => exception, - }); + return Err(self.refusal(refusal, name, self.buffered)); } - self.buffered = kept; - if self.buffered >= self.batch_size { self.flush()?; } @@ -390,7 +423,7 @@ impl NativeParquetRowsWriter { } #[php_impl] -impl NativeParquetRowsWriter { +impl RowsWriter { /// `$schema` / `$options`: `Flow\Parquet\Engine\Arrow\SchemaConverter` / `OptionsConverter::toExtension()`; /// `$batchSize` rows per `ParquetWriter::write`. pub fn __construct( @@ -402,14 +435,15 @@ impl NativeParquetRowsWriter { ) -> PhpResult { let batch_size = self::batch_size(batch_size)?; let stream = Arc::new(PhpStream::new(stream)?); - let refused = |error| parquet_exception(error, &stream, Side::Write, Surface::Lib); + let refused = |error| parquet_exception(error, &stream, Side::Write); let schema = options::schema(schema).map_err(refused)?; let columns = schema .fields() .iter() - .map(|field| WriteColumn::new(field)) + .map(|field| WriteColumn::new(field, batch_size)) .collect::, Error>>() .map_err(refused)?; + let scalar = columns.iter().all(|column| column.cell.is_scalar()); let writer = ParquetWriter::open( PhpSink::new(Arc::clone(&stream)), schema, @@ -423,6 +457,7 @@ impl NativeParquetRowsWriter { columns, classes: Classes::new()?, buffered: 0, + scalar, batch_size, }) } @@ -430,16 +465,20 @@ impl NativeParquetRowsWriter { /// A writer column the row lacks is null. #[php(name = "writeRow")] pub fn write_row(&mut self, row: &Zval) -> PhpResult<()> { - self.append(row) + if self.scalar { + self.append::(row, &mut Vec::with_capacity(self.columns.len())) + } else { + self.append::(row, &mut Vec::with_capacity(self.columns.len())) + } } #[php(name = "writeRows")] pub fn write_rows(&mut self, rows: &ZendHashTable) -> PhpResult<()> { - for row in rows.values() { - self.append(row)?; + if self.scalar { + self.append_rows::(rows) + } else { + self.append_rows::(rows) } - - Ok(()) } /// Every list of one length; a writer column `$columns` lacks is nulls, a key the writer lacks is ignored. @@ -453,7 +492,7 @@ impl NativeParquetRowsWriter { for (key, values) in columns.iter() { let values = values.array().ok_or_else(|| { - exception(INVALID_ARGUMENT, "flow_php Parquet writer columns must be arrays".to_string()) + exception(INVALID_ARGUMENT, "arrow Parquet writer columns must be arrays".to_string()) })?; lengths.push((key.to_string(), values.len())); @@ -485,13 +524,42 @@ impl NativeParquetRowsWriter { while first < count { let rows = (count - first).min(self.batch_size - self.buffered); - self.append_columns(&lists, first, rows)?; + if self.scalar { + self.append_columns::(&lists, first, rows)?; + } else { + self.append_columns::(&lists, first, rows)?; + } first += rows; } Ok(()) } + /// An Arrow C Data struct batch another extension exported, moved out of `$batch`: its children by writer column + /// name, a writer column the batch lacks as nulls, a child the writer lacks ignored. Buffered rows go first. + #[php(name = "writeBatch")] + pub fn write_batch(&mut self, batch: &Zval) -> PhpResult<()> { + self.open()?; + self.flush()?; + + let batch = batch::import(batch)?; + let rows = batch.len(); + let writer = self.writer.as_mut().ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; + let arrays = writer + .schema() + .fields() + .iter() + .map(|field| match batch.column_by_name(field.name()) { + Some(column) => Arc::clone(column), + None => new_null_array(field.data_type(), rows), + }) + .collect::>(); + + writer + .write(rows, &arrays) + .map_err(|error| parquet_exception(error, &self.stream, Side::Write)) + } + /// Buffered rows, the footer, then the stream closed. pub fn close(&mut self) -> PhpResult<()> { let flushed = self.flush(); diff --git a/src/extension/arrow-ext/src/parquet/mod.rs b/src/extension/arrow-ext/src/parquet/mod.rs index d4036fa50a..ddda9c6c7c 100644 --- a/src/extension/arrow-ext/src/parquet/mod.rs +++ b/src/extension/arrow-ext/src/parquet/mod.rs @@ -1,4 +1,15 @@ -pub mod exception; -pub mod reader; -pub mod type_converter; -pub mod writer; +//! Parquet in arrow: one reader, one cast table and one writer over Flow filesystem streams, surfaced as the +//! `flow-php/parquet` lib's values (`library`) and as Arrow C Data struct batches (`batch`). + +pub mod batch; +pub mod canonical; +pub mod cells; +pub mod error; +pub mod fetch; +pub mod footer; +pub mod library; +pub mod options; +pub mod read; +pub mod sink; +pub mod source; +pub mod write; diff --git a/src/extension/flow-php-ext/src/parquet/options.rs b/src/extension/arrow-ext/src/parquet/options.rs similarity index 100% rename from src/extension/flow-php-ext/src/parquet/options.rs rename to src/extension/arrow-ext/src/parquet/options.rs diff --git a/src/extension/flow-php-ext/src/parquet/read.rs b/src/extension/arrow-ext/src/parquet/read.rs similarity index 100% rename from src/extension/flow-php-ext/src/parquet/read.rs rename to src/extension/arrow-ext/src/parquet/read.rs diff --git a/src/extension/arrow-ext/src/parquet/reader.rs b/src/extension/arrow-ext/src/parquet/reader.rs deleted file mode 100644 index f948fd4143..0000000000 --- a/src/extension/arrow-ext/src/parquet/reader.rs +++ /dev/null @@ -1,424 +0,0 @@ -use arrow_schema::{DataType, TimeUnit}; -use ext_php_rs::boxed::ZBox; -use ext_php_rs::prelude::*; -use ext_php_rs::types::{ZendHashTable, ZendObject}; -use parquet::arrow::arrow_reader::{ - ArrowReaderMetadata, ArrowReaderOptions, ParquetRecordBatchReader, - ParquetRecordBatchReaderBuilder, -}; -use parquet::arrow::ProjectionMask; - -use crate::parquet::exception::parquet_exception; -use crate::parquet::type_converter; -use crate::stream::php_source_stream::PhpSourceStream; - -#[php_class] -#[php(name = "Flow\\Arrow\\Parquet\\Reader")] -#[derive(Default)] -pub struct Reader { - stream: Option, - reader_metadata: Option, - num_row_groups: usize, - current_row_group: usize, - batch_size: Option, - active_batch_reader: Option, - active_columns: Vec, -} - -impl Reader { - fn ensure_open(&self) -> PhpResult<(&PhpSourceStream, &ArrowReaderMetadata)> { - match (&self.stream, &self.reader_metadata) { - (Some(s), Some(m)) => Ok((s, m)), - _ => Err(parquet_exception("Reader is closed")), - } - } - - fn batch_to_php( - batch: &arrow_array::RecordBatch, - columns: &[String], - ) -> PhpResult> { - let mut result = ZendHashTable::new(); - let schema = batch.schema(); - - for col_name in columns { - let column = batch.column_by_name(col_name).ok_or_else(|| { - parquet_exception(format!("Column '{}' not found in batch", col_name)) - })?; - let field = schema.field_with_name(col_name).ok(); - - let values = type_converter::arrow_array_to_php_values(column.as_ref(), field)?; - - let mut php_array = ZendHashTable::with_capacity(values.len() as u32); - - for zv in values { - php_array - .push(zv) - .map_err(|_| parquet_exception("Failed to build column array"))?; - } - - result - .insert(col_name.as_str(), php_array) - .map_err(|_| parquet_exception("Failed to build result array"))?; - } - - Ok(result) - } - - fn consume_all_batches( - reader: ParquetRecordBatchReader, - columns: &[String], - ) -> PhpResult>> { - let mut column_data: Vec> = - columns.iter().map(|_| Vec::new()).collect(); - - for batch_result in reader { - let batch = batch_result - .map_err(|e| parquet_exception(format!("Failed to read batch: {}", e)))?; - let schema = batch.schema(); - - for (idx, col_name) in columns.iter().enumerate() { - let column = batch.column_by_name(col_name).ok_or_else(|| { - parquet_exception(format!("Column '{}' not found in batch", col_name)) - })?; - let field = schema.field_with_name(col_name).ok(); - - let mut values = type_converter::arrow_array_to_php_values(column.as_ref(), field)?; - column_data[idx].append(&mut values); - } - } - - let mut result = ZendHashTable::new(); - - for (idx, col_name) in columns.iter().enumerate() { - let values = std::mem::take(&mut column_data[idx]); - let mut php_array = ZendHashTable::with_capacity(values.len() as u32); - - for zv in values { - php_array - .push(zv) - .map_err(|_| parquet_exception("Failed to build column array"))?; - } - - result - .insert(col_name.as_str(), php_array) - .map_err(|_| parquet_exception("Failed to build result array"))?; - } - - Ok(Some(result)) - } -} - -fn time_unit_name(unit: &TimeUnit) -> &'static str { - match unit { - // Parquet has no second unit; arrow-rs stores seconds as MILLIS. - TimeUnit::Second | TimeUnit::Millisecond => "MILLIS", - TimeUnit::Microsecond => "MICROS", - TimeUnit::Nanosecond => "NANOS", - } -} - -fn field_to_php_schema(field: &arrow_schema::Field) -> PhpResult> { - let mut entry = ZendHashTable::new(); - entry - .insert("name", field.name().as_str()) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - - let type_str = match field.data_type() { - DataType::Boolean => "BOOLEAN", - DataType::Int8 => "INT8", - DataType::Int16 => "INT16", - DataType::Int32 => "INT32", - DataType::Int64 => "INT64", - DataType::UInt8 => "UINT8", - DataType::UInt16 => "UINT16", - DataType::UInt32 => "UINT32", - DataType::UInt64 => "UINT64", - DataType::Float32 => "FLOAT", - DataType::Float64 => "DOUBLE", - DataType::Utf8 | DataType::LargeUtf8 => "STRING", - DataType::Binary | DataType::LargeBinary => "BINARY", - DataType::Date32 | DataType::Date64 => "DATE", - DataType::Timestamp(_, _) => "TIMESTAMP", - DataType::Time32(_) | DataType::Time64(_) => "TIME", - DataType::Decimal128(_, _) | DataType::Decimal256(_, _) => "DECIMAL", - DataType::FixedSizeBinary(_) => "FIXED_SIZE_BINARY", - DataType::List(_) | DataType::LargeList(_) => "LIST", - DataType::Struct(_) => "STRUCT", - DataType::Map(_, _) => "MAP", - other => { - return Err(parquet_exception(format!( - "Unsupported Arrow type in schema: {:?}", - other - ))); - } - }; - - entry - .insert("type", type_str) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - entry - .insert("optional", field.is_nullable()) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - - match field.data_type() { - DataType::Decimal128(precision, scale) | DataType::Decimal256(precision, scale) => { - entry - .insert("precision", *precision as i64) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - entry - .insert("scale", *scale as i64) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - } - DataType::Timestamp(unit, tz) => { - entry - .insert("unit", time_unit_name(unit)) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - entry - .insert("utc", tz.is_some()) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - } - DataType::Time32(unit) | DataType::Time64(unit) => { - entry - .insert("unit", time_unit_name(unit)) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - } - DataType::FixedSizeBinary(n) => { - entry - .insert("length", *n as i64) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - } - DataType::List(child_field) | DataType::LargeList(child_field) => { - let mut children = ZendHashTable::new(); - let child_schema = field_to_php_schema(child_field)?; - children - .push(child_schema) - .map_err(|_| parquet_exception("Failed to build schema children"))?; - entry - .insert("children", children) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - } - DataType::Struct(fields) => { - let mut children = ZendHashTable::new(); - for f in fields { - let child_schema = field_to_php_schema(f)?; - children - .push(child_schema) - .map_err(|_| parquet_exception("Failed to build schema children"))?; - } - entry - .insert("children", children) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - } - DataType::Map(struct_field, _) => { - if let DataType::Struct(fields) = struct_field.data_type() { - let mut children = ZendHashTable::new(); - for f in fields { - let child_schema = field_to_php_schema(f)?; - children - .push(child_schema) - .map_err(|_| parquet_exception("Failed to build schema children"))?; - } - entry - .insert("children", children) - .map_err(|_| parquet_exception("Failed to build schema entry"))?; - } - } - _ => {} - } - - Ok(entry) -} - -#[php_impl] -impl Reader { - pub fn __construct( - source: &mut ZendObject, - options: Option<&ZendHashTable>, - ) -> PhpResult { - let stream = PhpSourceStream::new(source).map_err(parquet_exception)?; - - let reader_metadata = ArrowReaderMetadata::load(&stream, ArrowReaderOptions::default()) - .map_err(|e| parquet_exception(format!("Failed to open Parquet file: {}", e)))?; - - let num_row_groups = reader_metadata.metadata().num_row_groups(); - - let batch_size = options - .and_then(|opts| opts.get("BATCH_SIZE")) - .and_then(|z| z.long()) - .map(|v| v as usize); - - Ok(Self { - stream: Some(stream), - reader_metadata: Some(reader_metadata), - num_row_groups, - current_row_group: 0, - batch_size, - active_batch_reader: None, - active_columns: Vec::new(), - }) - } - - pub fn schema(&self) -> PhpResult> { - let (_, reader_metadata) = self.ensure_open()?; - let arrow_schema = reader_metadata.schema(); - - let mut result = ZendHashTable::new(); - - for field in arrow_schema.fields() { - let entry = field_to_php_schema(field)?; - result - .push(entry) - .map_err(|_| parquet_exception("Failed to build schema array"))?; - } - - Ok(result) - } - - pub fn metadata(&self) -> PhpResult> { - let (_, reader_metadata) = self.ensure_open()?; - let metadata = reader_metadata.metadata(); - - let mut result = ZendHashTable::new(); - result - .insert("rows", metadata.file_metadata().num_rows()) - .map_err(|_| parquet_exception("Failed to build metadata"))?; - result - .insert("row_groups", metadata.num_row_groups() as i64) - .map_err(|_| parquet_exception("Failed to build metadata"))?; - - match metadata.file_metadata().created_by() { - Some(created_by) => { - result - .insert("created_by", created_by) - .map_err(|_| parquet_exception("Failed to build metadata"))?; - } - None => { - result - .insert("created_by", ()) - .map_err(|_| parquet_exception("Failed to build metadata"))?; - } - } - - let mut kv_metadata = ZendHashTable::new(); - - if let Some(kv_pairs) = metadata.file_metadata().key_value_metadata() { - for kv in kv_pairs { - if let Some(ref value) = kv.value { - kv_metadata - .insert(kv.key.as_str(), value.as_str()) - .map_err(|_| parquet_exception("Failed to build metadata"))?; - } - } - } - - result - .insert("metadata", kv_metadata) - .map_err(|_| parquet_exception("Failed to build metadata"))?; - - Ok(result) - } - - #[allow(non_snake_case)] - pub fn readRowGroup( - &mut self, - columns: Option>, - ) -> PhpResult>> { - loop { - if let Some(ref mut batch_reader) = self.active_batch_reader { - match batch_reader.next() { - Some(Ok(batch)) => { - return Ok(Some(Self::batch_to_php(&batch, &self.active_columns)?)); - } - Some(Err(e)) => { - self.active_batch_reader = None; - return Err(parquet_exception(format!("Failed to read batch: {}", e))); - } - None => { - self.active_batch_reader = None; - self.current_row_group += 1; - continue; - } - } - } - - if self.current_row_group >= self.num_row_groups { - return Ok(None); - } - - let (stream, reader_metadata) = self.ensure_open()?; - let arrow_schema = reader_metadata.schema().clone(); - let parquet_metadata = reader_metadata.metadata().clone(); - let cloned_stream = stream.clone(); - let cloned_metadata = reader_metadata.clone(); - - let selected_columns: Vec = if let Some(ref cols) = columns { - for col_name in cols { - if arrow_schema.field_with_name(col_name).is_err() { - return Err(parquet_exception(format!( - "Column '{}' not found in schema", - col_name - ))); - } - } - cols.clone() - } else { - arrow_schema - .fields() - .iter() - .map(|f| f.name().clone()) - .collect() - }; - - let parquet_schema = parquet_metadata.file_metadata().schema_descr(); - - let mut builder = - ParquetRecordBatchReaderBuilder::new_with_metadata(cloned_stream, cloned_metadata); - builder = builder.with_row_groups(vec![self.current_row_group]); - - if columns.is_some() { - let indices: Result, _> = selected_columns - .iter() - .map(|name| { - arrow_schema - .fields() - .iter() - .position(|f| f.name() == name) - .ok_or_else(|| { - parquet_exception(format!("Column '{}' not found in schema", name)) - }) - }) - .collect(); - let indices = indices?; - let mask = ProjectionMask::roots(parquet_schema, indices); - builder = builder.with_projection(mask); - } - - if let Some(bs) = self.batch_size { - builder = builder.with_batch_size(bs); - } - - let reader = builder - .build() - .map_err(|e| parquet_exception(format!("Failed to build batch reader: {}", e)))?; - - self.active_columns = selected_columns; - - if self.batch_size.is_some() { - self.active_batch_reader = Some(reader); - continue; - } else { - let result = Self::consume_all_batches(reader, &self.active_columns)?; - self.current_row_group += 1; - self.active_columns = Vec::new(); - return Ok(result); - } - } - } - - pub fn close(&mut self) { - self.active_batch_reader = None; - self.stream = None; - self.reader_metadata = None; - self.active_columns = Vec::new(); - } -} diff --git a/src/extension/flow-php-ext/src/parquet/sink.rs b/src/extension/arrow-ext/src/parquet/sink.rs similarity index 96% rename from src/extension/flow-php-ext/src/parquet/sink.rs rename to src/extension/arrow-ext/src/parquet/sink.rs index 998744da18..b7b70352d1 100644 --- a/src/extension/flow-php-ext/src/parquet/sink.rs +++ b/src/extension/arrow-ext/src/parquet/sink.rs @@ -3,7 +3,7 @@ use std::io::{self, Write}; use std::sync::Arc; -use crate::ctx::zval_str; +use crate::php::zval_str; use crate::parquet::source::PhpStream; pub struct PhpSink { diff --git a/src/extension/flow-php-ext/src/parquet/source.rs b/src/extension/arrow-ext/src/parquet/source.rs similarity index 99% rename from src/extension/flow-php-ext/src/parquet/source.rs rename to src/extension/arrow-ext/src/parquet/source.rs index 2de9a2ba45..2df23431ce 100644 --- a/src/extension/flow-php-ext/src/parquet/source.rs +++ b/src/extension/arrow-ext/src/parquet/source.rs @@ -12,7 +12,7 @@ use ext_php_rs::types::{ZendObject, Zval}; use parquet::errors::ParquetError; use parquet::file::reader::{ChunkReader, Length}; -use crate::ctx::{call_handle_catching, ce_method_ref, expect_object, zval_long}; +use crate::php::{call_handle_catching, ce_method_ref, expect_object, zval_long}; use crate::parquet::error::Error; /// What `get_read()` pulls from the stream per `read()` call. diff --git a/src/extension/arrow-ext/src/parquet/type_converter.rs b/src/extension/arrow-ext/src/parquet/type_converter.rs deleted file mode 100644 index 323e7c9e71..0000000000 --- a/src/extension/arrow-ext/src/parquet/type_converter.rs +++ /dev/null @@ -1,1608 +0,0 @@ -use arrow_array::builder::{ - BinaryBuilder, BooleanBuilder, Date32Builder, Decimal128Builder, FixedSizeBinaryBuilder, - Float32Builder, Float64Builder, Int16Builder, Int32Builder, Int64Builder, Int8Builder, - StringBuilder, UInt16Builder, UInt32Builder, UInt64Builder, UInt8Builder, -}; -use arrow_array::types::{Decimal128Type, Decimal256Type, DecimalType}; -use arrow_array::*; -use arrow_buffer::{NullBuffer, OffsetBuffer, ScalarBuffer}; -use arrow_schema::{ - extension::{Json, Uuid}, - DataType, Field, Fields, Schema, TimeUnit, -}; -use ext_php_rs::convert::IntoZvalDyn; -use ext_php_rs::prelude::*; -use ext_php_rs::types::{ArrayKey, ZendHashTable, ZendObject, Zval}; -use ext_php_rs::zend::ClassEntry; -use std::sync::Arc; - -use crate::parquet::exception::parquet_exception; - -fn split_epoch(value: i64, units_per_second: i64) -> (i64, i64) { - ( - value.div_euclid(units_per_second), - value.rem_euclid(units_per_second) * (1_000_000 / units_per_second), - ) -} - -fn create_datetime_immutable(seconds: i64, microseconds: i64) -> PhpResult { - let mut callable_ht = ZendHashTable::with_capacity(2); - let mut class_zv = Zval::new(); - class_zv - .set_string("DateTimeImmutable", false) - .map_err(|_| parquet_exception("Failed to create DateTimeImmutable callable"))?; - callable_ht - .push(class_zv) - .map_err(|_| parquet_exception("Failed to create DateTimeImmutable callable"))?; - let mut method_zv = Zval::new(); - method_zv - .set_string("createFromFormat", false) - .map_err(|_| parquet_exception("Failed to create DateTimeImmutable callable"))?; - callable_ht - .push(method_zv) - .map_err(|_| parquet_exception("Failed to create DateTimeImmutable callable"))?; - - let mut callable = Zval::new(); - callable.set_hashtable(callable_ht); - - let format = "U.u".to_string(); - let value = format!("{}.{:06}", seconds, microseconds); - - callable - .try_call(vec![ - &format as &dyn IntoZvalDyn, - &value as &dyn IntoZvalDyn, - ]) - .map_err(|e| { - parquet_exception(format!( - "Failed to call DateTimeImmutable::createFromFormat: {:?}", - e - )) - }) -} - -fn create_date_interval(total_microseconds: i64) -> PhpResult { - let hours = total_microseconds / 3_600_000_000; - let minutes = (total_microseconds / 60_000_000) % 60; - let secs = (total_microseconds / 1_000_000) % 60; - let remaining_us = total_microseconds % 1_000_000; - - let spec = format!("PT{}H{}M{}S", hours, minutes, secs); - - let ce = ClassEntry::try_find("DateInterval") - .ok_or_else(|| parquet_exception("DateInterval class not found"))?; - let mut obj = ZendObject::new(ce); - - obj.try_call_method("__construct", vec![&spec as &dyn IntoZvalDyn]) - .map_err(|e| parquet_exception(format!("Failed to construct DateInterval: {:?}", e)))?; - - if remaining_us > 0 { - let fraction = remaining_us as f64 / 1_000_000.0; - obj.set_property("f", fraction).map_err(|e| { - parquet_exception(format!("Failed to set DateInterval microseconds: {:?}", e)) - })?; - } - - let mut zv = Zval::new(); - zv.set_object(&mut obj); - Ok(zv) -} - -fn extract_datetime_timestamp(zv: &Zval, column_name: &str) -> Result<(i64, i64), String> { - let obj = zv - .object() - .ok_or_else(|| format!("Column '{}': expected object", column_name))?; - - let dt_ce = ClassEntry::try_find("DateTimeInterface") - .ok_or_else(|| format!("Column '{}': DateTimeInterface not found", column_name))?; - - if !obj.instance_of(dt_ce) { - return Err(format!( - "Column '{}': expected DateTimeInterface or int, got object", - column_name - )); - } - - let ts_zv = obj - .try_call_method("getTimestamp", vec![]) - .map_err(|e| format!("Column '{}': getTimestamp() failed: {:?}", column_name, e))?; - let seconds = ts_zv.long().ok_or_else(|| { - format!( - "Column '{}': getTimestamp() did not return int", - column_name - ) - })?; - - let format_u = "u".to_string(); - let us_zv = obj - .try_call_method("format", vec![&format_u as &dyn IntoZvalDyn]) - .map_err(|e| format!("Column '{}': format('u') failed: {:?}", column_name, e))?; - let us_str = us_zv.str().ok_or_else(|| { - format!( - "Column '{}': format('u') did not return string", - column_name - ) - })?; - let microseconds: i64 = us_str.parse().unwrap_or(0); - - Ok((seconds, microseconds)) -} - -fn extract_datetime_offset(zv: &Zval, column_name: &str) -> Result { - let obj = zv - .object() - .ok_or_else(|| format!("Column '{}': expected object", column_name))?; - - obj.try_call_method("getOffset", vec![]) - .map_err(|e| format!("Column '{}': getOffset() failed: {:?}", column_name, e))? - .long() - .ok_or_else(|| format!("Column '{}': getOffset() did not return int", column_name)) -} - -fn extract_date_interval_microseconds(zv: &Zval, column_name: &str) -> Result { - let obj = zv - .object() - .ok_or_else(|| format!("Column '{}': expected object", column_name))?; - - let di_ce = ClassEntry::try_find("DateInterval") - .ok_or_else(|| format!("Column '{}': DateInterval not found", column_name))?; - - if !obj.instance_of(di_ce) { - return Err(format!( - "Column '{}': expected DateInterval or int, got object", - column_name - )); - } - - let h: i64 = obj.get_property::("h").unwrap_or(0); - let i: i64 = obj.get_property::("i").unwrap_or(0); - let s: i64 = obj.get_property::("s").unwrap_or(0); - let f: f64 = obj.get_property::("f").unwrap_or(0.0); - - Ok(h * 3_600_000_000 + i * 60_000_000 + s * 1_000_000 + (f * 1_000_000.0) as i64) -} - -fn decimal_to_zval(value: T::Native, precision: u8, scale: i8) -> PhpResult { - let str_val = T::format_decimal(value, precision, scale); - let float_val: f64 = str_val.parse().map_err(|e| { - parquet_exception(format!( - "Failed to parse decimal value '{}': {}", - str_val, e - )) - })?; - let mut zv = Zval::new(); - zv.set_double(float_val); - Ok(zv) -} - -fn downcast_array<'a, T: 'static>(array: &'a dyn Array, type_name: &str) -> PhpResult<&'a T> { - array - .as_any() - .downcast_ref::() - .ok_or_else(|| parquet_exception(format!("Internal error: expected {}", type_name))) -} - -fn convert_primitive_values( - arr: &PrimitiveArray, - convert: impl Fn(T::Native) -> PhpResult, -) -> PhpResult> { - let len = arr.len(); - let mut result = Vec::with_capacity(len); - for i in 0..len { - if arr.is_null(i) { - let mut zv = Zval::new(); - zv.set_null(); - result.push(zv); - } else { - result.push(convert(arr.value(i))?); - } - } - Ok(result) -} - -fn convert_string_values(arr: &GenericStringArray) -> PhpResult> { - let len = arr.len(); - let mut result = Vec::with_capacity(len); - for i in 0..len { - let mut zv = Zval::new(); - if arr.is_null(i) { - zv.set_null(); - } else { - zv.set_string(arr.value(i), false) - .map_err(|_| parquet_exception("Failed to set string value"))?; - } - result.push(zv); - } - Ok(result) -} - -fn convert_binary_values(arr: &GenericBinaryArray) -> Vec { - let len = arr.len(); - let mut result = Vec::with_capacity(len); - for i in 0..len { - let mut zv = Zval::new(); - if arr.is_null(i) { - zv.set_null(); - } else { - zv.set_binary(arr.value(i).to_vec()); - } - result.push(zv); - } - result -} - -fn uuid_to_string(b: &[u8]) -> String { - format!( - "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", - b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], - b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15] - ) -} - -fn is_uuid_field(field: Option<&Field>) -> bool { - field.is_some_and(|f| f.try_extension_type::().is_ok()) -} - -fn convert_single_arrow_value(array: &dyn Array, index: usize, is_uuid: bool) -> PhpResult { - if array.is_null(index) { - let mut zv = Zval::new(); - zv.set_null(); - return Ok(zv); - } - - match array.data_type() { - DataType::Boolean => { - let arr = downcast_array::(array, "BooleanArray")?; - let mut zv = Zval::new(); - zv.set_bool(arr.value(index)); - Ok(zv) - } - DataType::Int8 => { - let arr = downcast_array::(array, "Int8Array")?; - let mut zv = Zval::new(); - zv.set_long(arr.value(index) as i64); - Ok(zv) - } - DataType::Int16 => { - let arr = downcast_array::(array, "Int16Array")?; - let mut zv = Zval::new(); - zv.set_long(arr.value(index) as i64); - Ok(zv) - } - DataType::Int32 => { - let arr = downcast_array::(array, "Int32Array")?; - let mut zv = Zval::new(); - zv.set_long(arr.value(index) as i64); - Ok(zv) - } - DataType::Int64 => { - let arr = downcast_array::(array, "Int64Array")?; - let mut zv = Zval::new(); - zv.set_long(arr.value(index)); - Ok(zv) - } - DataType::UInt8 => { - let arr = downcast_array::(array, "UInt8Array")?; - let mut zv = Zval::new(); - zv.set_long(arr.value(index) as i64); - Ok(zv) - } - DataType::UInt16 => { - let arr = downcast_array::(array, "UInt16Array")?; - let mut zv = Zval::new(); - zv.set_long(arr.value(index) as i64); - Ok(zv) - } - DataType::UInt32 => { - let arr = downcast_array::(array, "UInt32Array")?; - let mut zv = Zval::new(); - zv.set_long(arr.value(index) as i64); - Ok(zv) - } - DataType::UInt64 => { - let arr = downcast_array::(array, "UInt64Array")?; - let val = arr.value(index); - let mut zv = Zval::new(); - if val > i64::MAX as u64 { - zv.set_string(&val.to_string(), false) - .map_err(|_| parquet_exception("Failed to set uint64 string value"))?; - } else { - zv.set_long(val as i64); - } - Ok(zv) - } - DataType::Float32 => { - let arr = downcast_array::(array, "Float32Array")?; - let mut zv = Zval::new(); - zv.set_double(arr.value(index) as f64); - Ok(zv) - } - DataType::Float64 => { - let arr = downcast_array::(array, "Float64Array")?; - let mut zv = Zval::new(); - zv.set_double(arr.value(index)); - Ok(zv) - } - DataType::Utf8 => { - let arr = downcast_array::(array, "StringArray")?; - let mut zv = Zval::new(); - zv.set_string(arr.value(index), false) - .map_err(|_| parquet_exception("Failed to set string value"))?; - Ok(zv) - } - DataType::LargeUtf8 => { - let arr = downcast_array::(array, "LargeStringArray")?; - let mut zv = Zval::new(); - zv.set_string(arr.value(index), false) - .map_err(|_| parquet_exception("Failed to set string value"))?; - Ok(zv) - } - DataType::Binary => { - let arr = downcast_array::(array, "BinaryArray")?; - let mut zv = Zval::new(); - zv.set_binary(arr.value(index).to_vec()); - Ok(zv) - } - DataType::LargeBinary => { - let arr = downcast_array::(array, "LargeBinaryArray")?; - let mut zv = Zval::new(); - zv.set_binary(arr.value(index).to_vec()); - Ok(zv) - } - DataType::FixedSizeBinary(_) => { - let arr = downcast_array::(array, "FixedSizeBinaryArray")?; - let mut zv = Zval::new(); - if is_uuid && arr.value(index).len() == 16 { - zv.set_string(&uuid_to_string(arr.value(index)), false) - .map_err(|_| parquet_exception("Failed to set UUID string value"))?; - } else { - zv.set_binary(arr.value(index).to_vec()); - } - Ok(zv) - } - DataType::Date32 => { - let arr = downcast_array::(array, "Date32Array")?; - create_datetime_immutable(arr.value(index) as i64 * 86400, 0) - } - DataType::Date64 => { - let arr = downcast_array::(array, "Date64Array")?; - let (s, us) = split_epoch(arr.value(index), 1_000); - create_datetime_immutable(s, us) - } - DataType::Timestamp(TimeUnit::Second, _) => { - let arr = downcast_array::(array, "TimestampSecondArray")?; - create_datetime_immutable(arr.value(index), 0) - } - DataType::Timestamp(TimeUnit::Millisecond, _) => { - let arr = - downcast_array::(array, "TimestampMillisecondArray")?; - let (s, us) = split_epoch(arr.value(index), 1_000); - create_datetime_immutable(s, us) - } - DataType::Timestamp(TimeUnit::Microsecond, _) => { - let arr = - downcast_array::(array, "TimestampMicrosecondArray")?; - let (s, us) = split_epoch(arr.value(index), 1_000_000); - create_datetime_immutable(s, us) - } - DataType::Timestamp(TimeUnit::Nanosecond, _) => { - let arr = - downcast_array::(array, "TimestampNanosecondArray")?; - let (s, us) = split_epoch(arr.value(index).div_euclid(1_000), 1_000_000); - create_datetime_immutable(s, us) - } - DataType::Time32(TimeUnit::Second) => { - let arr = downcast_array::(array, "Time32SecondArray")?; - create_date_interval(arr.value(index) as i64 * 1_000_000) - } - DataType::Time32(TimeUnit::Millisecond) => { - let arr = downcast_array::(array, "Time32MillisecondArray")?; - create_date_interval(arr.value(index) as i64 * 1000) - } - DataType::Time64(TimeUnit::Microsecond) => { - let arr = downcast_array::(array, "Time64MicrosecondArray")?; - create_date_interval(arr.value(index)) - } - DataType::Time64(TimeUnit::Nanosecond) => { - let arr = downcast_array::(array, "Time64NanosecondArray")?; - create_date_interval(arr.value(index).div_euclid(1_000)) - } - DataType::Decimal128(precision, scale) => { - let arr = downcast_array::(array, "Decimal128Array")?; - decimal_to_zval::(arr.value(index), *precision, *scale) - } - DataType::Decimal256(precision, scale) => { - let arr = downcast_array::(array, "Decimal256Array")?; - decimal_to_zval::(arr.value(index), *precision, *scale) - } - DataType::List(element_field) => { - let list_array = downcast_array::(array, "ListArray")?; - let element_is_uuid = is_uuid_field(Some(element_field)); - let values = list_array.value(index); - let mut ht = ZendHashTable::with_capacity(values.len() as u32); - for j in 0..values.len() { - let child_zv = convert_single_arrow_value(values.as_ref(), j, element_is_uuid)?; - ht.push(child_zv) - .map_err(|_| parquet_exception("Failed to build list element"))?; - } - let mut zv = Zval::new(); - zv.set_hashtable(ht); - Ok(zv) - } - DataType::LargeList(element_field) => { - let list_array = downcast_array::(array, "LargeListArray")?; - let element_is_uuid = is_uuid_field(Some(element_field)); - let values = list_array.value(index); - let mut ht = ZendHashTable::with_capacity(values.len() as u32); - for j in 0..values.len() { - let child_zv = convert_single_arrow_value(values.as_ref(), j, element_is_uuid)?; - ht.push(child_zv) - .map_err(|_| parquet_exception("Failed to build list element"))?; - } - let mut zv = Zval::new(); - zv.set_hashtable(ht); - Ok(zv) - } - DataType::Struct(fields) => { - let struct_array = downcast_array::(array, "StructArray")?; - let mut ht = ZendHashTable::with_capacity(fields.len() as u32); - for (col_idx, field) in fields.iter().enumerate() { - let child_array = struct_array.column(col_idx); - let child_zv = convert_single_arrow_value( - child_array.as_ref(), - index, - is_uuid_field(Some(field)), - )?; - ht.insert(field.name().as_str(), child_zv) - .map_err(|_| parquet_exception("Failed to build struct field"))?; - } - let mut zv = Zval::new(); - zv.set_hashtable(ht); - Ok(zv) - } - DataType::Map(entries_field, _) => { - let map_array = downcast_array::(array, "MapArray")?; - let (key_is_uuid, val_is_uuid) = match entries_field.data_type() { - DataType::Struct(entry_fields) if entry_fields.len() == 2 => ( - is_uuid_field(Some(&entry_fields[0])), - is_uuid_field(Some(&entry_fields[1])), - ), - _ => (false, false), - }; - let entries = map_array.value(index); - let keys_array = entries.column(0); - let values_array = entries.column(1); - let mut ht = ZendHashTable::with_capacity(entries.len() as u32); - for j in 0..entries.len() { - let key_zv = convert_single_arrow_value(keys_array.as_ref(), j, key_is_uuid)?; - let val_zv = convert_single_arrow_value(values_array.as_ref(), j, val_is_uuid)?; - let key_str = if let Some(s) = key_zv.str() { - s.to_string() - } else if let Some(l) = key_zv.long() { - l.to_string() - } else { - j.to_string() - }; - ht.insert(key_str.as_str(), val_zv) - .map_err(|_| parquet_exception("Failed to build map entry"))?; - } - let mut zv = Zval::new(); - zv.set_hashtable(ht); - Ok(zv) - } - other => Err(parquet_exception(format!( - "Unsupported Arrow type in nested conversion: {:?}", - other - ))), - } -} - -pub fn arrow_array_to_php_values(array: &dyn Array, field: Option<&Field>) -> PhpResult> { - match array.data_type() { - DataType::Boolean => { - let arr = downcast_array::(array, "BooleanArray")?; - let len = arr.len(); - let mut result = Vec::with_capacity(len); - for i in 0..len { - let mut zv = Zval::new(); - if arr.is_null(i) { - zv.set_null(); - } else { - zv.set_bool(arr.value(i)); - } - result.push(zv); - } - Ok(result) - } - - DataType::Int8 => { - let arr = downcast_array::(array, "Int8Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_long(v as i64); - Ok(zv) - }) - } - DataType::Int16 => { - let arr = downcast_array::(array, "Int16Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_long(v as i64); - Ok(zv) - }) - } - DataType::Int32 => { - let arr = downcast_array::(array, "Int32Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_long(v as i64); - Ok(zv) - }) - } - DataType::Int64 => { - let arr = downcast_array::(array, "Int64Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_long(v); - Ok(zv) - }) - } - DataType::UInt8 => { - let arr = downcast_array::(array, "UInt8Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_long(v as i64); - Ok(zv) - }) - } - DataType::UInt16 => { - let arr = downcast_array::(array, "UInt16Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_long(v as i64); - Ok(zv) - }) - } - DataType::UInt32 => { - let arr = downcast_array::(array, "UInt32Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_long(v as i64); - Ok(zv) - }) - } - - DataType::UInt64 => { - let arr = downcast_array::(array, "UInt64Array")?; - convert_primitive_values(arr, |val| { - let mut zv = Zval::new(); - if val > i64::MAX as u64 { - zv.set_string(&val.to_string(), false) - .map_err(|_| parquet_exception("Failed to set uint64 string value"))?; - } else { - zv.set_long(val as i64); - } - Ok(zv) - }) - } - - DataType::Float32 => { - let arr = downcast_array::(array, "Float32Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_double(v as f64); - Ok(zv) - }) - } - DataType::Float64 => { - let arr = downcast_array::(array, "Float64Array")?; - convert_primitive_values(arr, |v| { - let mut zv = Zval::new(); - zv.set_double(v); - Ok(zv) - }) - } - - DataType::Utf8 => { - let arr = downcast_array::(array, "StringArray")?; - convert_string_values(arr) - } - DataType::LargeUtf8 => { - let arr = downcast_array::(array, "LargeStringArray")?; - convert_string_values(arr) - } - - DataType::Binary => { - let arr = downcast_array::(array, "BinaryArray")?; - Ok(convert_binary_values(arr)) - } - DataType::LargeBinary => { - let arr = downcast_array::(array, "LargeBinaryArray")?; - Ok(convert_binary_values(arr)) - } - - DataType::FixedSizeBinary(_) => { - let arr = downcast_array::(array, "FixedSizeBinaryArray")?; - let is_uuid = is_uuid_field(field); - let len = arr.len(); - let mut result = Vec::with_capacity(len); - for i in 0..len { - let mut zv = Zval::new(); - if arr.is_null(i) { - zv.set_null(); - } else if is_uuid && arr.value(i).len() == 16 { - zv.set_string(&uuid_to_string(arr.value(i)), false) - .map_err(|_| parquet_exception("Failed to set UUID string value"))?; - } else { - zv.set_binary(arr.value(i).to_vec()); - } - result.push(zv); - } - Ok(result) - } - - DataType::Date32 => { - let arr = downcast_array::(array, "Date32Array")?; - convert_primitive_values(arr, |v| create_datetime_immutable(v as i64 * 86400, 0)) - } - DataType::Date64 => { - let arr = downcast_array::(array, "Date64Array")?; - convert_primitive_values(arr, |v| { - let (s, us) = split_epoch(v, 1_000); - create_datetime_immutable(s, us) - }) - } - - DataType::Timestamp(TimeUnit::Second, _) => { - let arr = downcast_array::(array, "TimestampSecondArray")?; - convert_primitive_values(arr, |v| create_datetime_immutable(v, 0)) - } - DataType::Timestamp(TimeUnit::Millisecond, _) => { - let arr = - downcast_array::(array, "TimestampMillisecondArray")?; - convert_primitive_values(arr, |v| { - let (s, us) = split_epoch(v, 1_000); - create_datetime_immutable(s, us) - }) - } - DataType::Timestamp(TimeUnit::Microsecond, _) => { - let arr = - downcast_array::(array, "TimestampMicrosecondArray")?; - convert_primitive_values(arr, |v| { - let (s, us) = split_epoch(v, 1_000_000); - create_datetime_immutable(s, us) - }) - } - DataType::Timestamp(TimeUnit::Nanosecond, _) => { - let arr = - downcast_array::(array, "TimestampNanosecondArray")?; - convert_primitive_values(arr, |v| { - let (s, us) = split_epoch(v.div_euclid(1_000), 1_000_000); - create_datetime_immutable(s, us) - }) - } - - DataType::Time32(TimeUnit::Second) => { - let arr = downcast_array::(array, "Time32SecondArray")?; - convert_primitive_values(arr, |v| create_date_interval(v as i64 * 1_000_000)) - } - DataType::Time32(TimeUnit::Millisecond) => { - let arr = downcast_array::(array, "Time32MillisecondArray")?; - convert_primitive_values(arr, |v| create_date_interval(v as i64 * 1000)) - } - DataType::Time64(TimeUnit::Microsecond) => { - let arr = downcast_array::(array, "Time64MicrosecondArray")?; - convert_primitive_values(arr, create_date_interval) - } - DataType::Time64(TimeUnit::Nanosecond) => { - let arr = downcast_array::(array, "Time64NanosecondArray")?; - convert_primitive_values(arr, |v| create_date_interval(v.div_euclid(1_000))) - } - - DataType::Decimal128(precision, scale) => { - let arr = downcast_array::(array, "Decimal128Array")?; - convert_primitive_values(arr, |v| { - decimal_to_zval::(v, *precision, *scale) - }) - } - - DataType::Decimal256(precision, scale) => { - let arr = downcast_array::(array, "Decimal256Array")?; - convert_primitive_values(arr, |v| { - decimal_to_zval::(v, *precision, *scale) - }) - } - - DataType::List(_) | DataType::LargeList(_) | DataType::Struct(_) | DataType::Map(_, _) => { - let len = array.len(); - let is_uuid = is_uuid_field(field); - let mut result = Vec::with_capacity(len); - for i in 0..len { - result.push(convert_single_arrow_value(array, i, is_uuid)?); - } - Ok(result) - } - - other => Err(parquet_exception(format!( - "Unsupported Arrow array type: {:?}", - other - ))), - } -} - -fn zval_type_name(zv: &Zval) -> &'static str { - if zv.is_null() { - "null" - } else if zv.is_bool() { - "bool" - } else if zv.is_long() { - "int" - } else if zv.is_double() { - "float" - } else if zv.is_string() { - "string" - } else if zv.is_array() { - "array" - } else if zv.is_object() { - "object" - } else { - "unknown" - } -} - -fn round_decimal_half_away(repr: &str, scale: i8) -> String { - let (sign, digits) = match repr.strip_prefix('-') { - Some(stripped) => ("-", stripped), - None => ("", repr), - }; - let (integer_part, fractional_part) = match digits.find('.') { - Some(dot_pos) => (&digits[..dot_pos], &digits[dot_pos + 1..]), - None => (digits, ""), - }; - let scale = scale.max(0) as usize; - - if fractional_part.len() <= scale { - return format!( - "{}{}.{:0 = format!("{}{}", integer_part, &fractional_part[..scale]).into_bytes(); - - if fractional_part.as_bytes()[scale] >= b'5' { - let mut i = kept.len(); - loop { - if i == 0 { - kept.insert(0, b'1'); - break; - } - i -= 1; - if kept[i] == b'9' { - kept[i] = b'0'; - } else { - kept[i] += 1; - break; - } - } - } - - let kept = String::from_utf8(kept).unwrap_or_default(); - let split = kept.len() - scale; - - format!("{}{}.{}", sign, &kept[..split], &kept[split..]) -} - -fn parse_decimal_string(s: &str, scale: i8) -> Result { - let trimmed = s.trim(); - if trimmed.is_empty() { - return Err("Empty decimal string".into()); - } - - let (negative, digits_str) = if let Some(stripped) = trimmed.strip_prefix('-') { - (true, stripped) - } else if let Some(stripped) = trimmed.strip_prefix('+') { - (false, stripped) - } else { - (false, trimmed) - }; - - let (integer_part, fractional_part) = if let Some(dot_pos) = digits_str.find('.') { - (&digits_str[..dot_pos], &digits_str[dot_pos + 1..]) - } else { - (digits_str, "") - }; - - if !integer_part.chars().all(|c| c.is_ascii_digit()) { - return Err(format!("Invalid decimal integer part: '{}'", integer_part)); - } - if !fractional_part.chars().all(|c| c.is_ascii_digit()) { - return Err(format!( - "Invalid decimal fractional part: '{}'", - fractional_part - )); - } - - let scale_usize = scale as usize; - let adjusted_frac = if fractional_part.len() >= scale_usize { - fractional_part[..scale_usize].to_string() - } else { - format!("{:0 {{ - let mut builder = <$builder_type>::with_capacity($values.len()); - for zv in $values { - if zv.is_null() { - builder.append_null(); - } else if let Some(v) = zv.long() { - let converted = <$cast_type>::try_from(v).map_err(|_| { - format!( - "Column '{}': value {} out of range for {} (valid range: {} to {})", - $column_name, - v, - stringify!($cast_type), - <$cast_type>::MIN, - <$cast_type>::MAX - ) - })?; - builder.append_value(converted); - } else { - return Err(format!( - "Column '{}': expected int, got {}", - $column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(builder.finish()) as ArrayRef) - }}; -} - -macro_rules! build_float_array { - ($values:expr, $column_name:expr, $builder_type:ty, $cast_type:ty) => {{ - let mut builder = <$builder_type>::with_capacity($values.len()); - for zv in $values { - if zv.is_null() { - builder.append_null(); - } else if let Some(v) = zv.double() { - let converted = v as $cast_type; - if converted.is_infinite() && !v.is_infinite() { - return Err(format!( - "Column '{}': value {} overflows {}", - $column_name, - v, - stringify!($cast_type) - )); - } - builder.append_value(converted); - } else if let Some(v) = zv.long() { - builder.append_value(v as $cast_type); - } else { - return Err(format!( - "Column '{}': expected float or int, got {}", - $column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(builder.finish()) as ArrayRef) - }}; -} - -fn parse_time_unit(entry_ht: &ZendHashTable, name: &str) -> Result { - match entry_ht.get("unit").and_then(|z| z.str()) { - None | Some("MICROS") => Ok(TimeUnit::Microsecond), - Some("MILLIS") => Ok(TimeUnit::Millisecond), - Some("NANOS") => Ok(TimeUnit::Nanosecond), - Some(s) => Err(format!( - "Column '{}': unsupported unit '{}', expected MILLIS, MICROS or NANOS", - name, s - )), - } -} - -fn php_schema_entry_to_field(entry_ht: &ZendHashTable) -> Result { - let name = entry_ht - .get("name") - .and_then(|z| z.str()) - .ok_or_else(|| "Schema entry must have a 'name' string key".to_string())? - .to_string(); - - let type_str = entry_ht - .get("type") - .and_then(|z| z.str()) - .ok_or_else(|| "Schema entry must have a 'type' string key".to_string())? - .to_string(); - - let nullable = entry_ht - .get("optional") - .and_then(|z| z.bool()) - .unwrap_or(true); - - let data_type = match type_str.as_str() { - "BOOLEAN" => DataType::Boolean, - "INT8" => DataType::Int8, - "INT16" => DataType::Int16, - "INT32" => DataType::Int32, - "INT64" => DataType::Int64, - "UINT8" => DataType::UInt8, - "UINT16" => DataType::UInt16, - "UINT32" => DataType::UInt32, - "UINT64" => DataType::UInt64, - "FLOAT" => DataType::Float32, - "DOUBLE" => DataType::Float64, - "STRING" => DataType::Utf8, - "BINARY" => DataType::Binary, - "DATE" => DataType::Date32, - "TIMESTAMP" => { - let unit = parse_time_unit(entry_ht, &name)?; - let utc = entry_ht.get("utc").and_then(|z| z.bool()).unwrap_or(true); - DataType::Timestamp(unit, if utc { Some("UTC".into()) } else { None }) - } - "TIME" => match parse_time_unit(entry_ht, &name)? { - TimeUnit::Millisecond => DataType::Time32(TimeUnit::Millisecond), - unit => DataType::Time64(unit), - }, - "DECIMAL" => { - let precision = entry_ht - .get("precision") - .and_then(|z| z.long()) - .ok_or_else(|| { - format!( - "Column '{}': DECIMAL type requires 'precision' integer key", - name - ) - })? as u8; - let scale = entry_ht - .get("scale") - .and_then(|z| z.long()) - .ok_or_else(|| { - format!( - "Column '{}': DECIMAL type requires 'scale' integer key", - name - ) - })? as i8; - DataType::Decimal128(precision, scale) - } - "UUID" => { - let mut field = Field::new(&name, DataType::FixedSizeBinary(16), nullable); - field.try_with_extension_type(Uuid).map_err(|e| { - format!( - "Column '{}': failed to set UUID extension type: {}", - name, e - ) - })?; - return Ok(field); - } - "JSON" => { - let mut field = Field::new(&name, DataType::Utf8, nullable); - field - .try_with_extension_type(Json::default()) - .map_err(|e| { - format!( - "Column '{}': failed to set JSON extension type: {}", - name, e - ) - })?; - return Ok(field); - } - "FIXED_SIZE_BINARY" => { - let length = entry_ht - .get("length") - .and_then(|z| z.long()) - .ok_or_else(|| { - format!( - "Column '{}': FIXED_SIZE_BINARY type requires 'length' integer key", - name - ) - })? as i32; - DataType::FixedSizeBinary(length) - } - "LIST" => { - let children = entry_ht - .get("children") - .and_then(|z| z.array()) - .ok_or_else(|| format!("Column '{}': LIST type requires 'children' array", name))?; - let child_zv = children.values().next().ok_or_else(|| { - format!("Column '{}': LIST type requires exactly one child", name) - })?; - let child_ht = child_zv - .array() - .ok_or_else(|| format!("Column '{}': LIST child must be an array", name))?; - let child_field = php_schema_entry_to_field(child_ht)?; - DataType::List(Arc::new(child_field)) - } - "STRUCT" => { - let children = entry_ht - .get("children") - .and_then(|z| z.array()) - .ok_or_else(|| { - format!("Column '{}': STRUCT type requires 'children' array", name) - })?; - let fields: Result, String> = children - .values() - .map(|child_zv| { - let child_ht = child_zv.array().ok_or_else(|| { - format!("Column '{}': STRUCT child must be an array", name) - })?; - php_schema_entry_to_field(child_ht) - }) - .collect(); - DataType::Struct(Fields::from(fields?)) - } - "MAP" => { - let children = entry_ht - .get("children") - .and_then(|z| z.array()) - .ok_or_else(|| format!("Column '{}': MAP type requires 'children' array", name))?; - let mut child_iter = children.values(); - let key_zv = child_iter.next().ok_or_else(|| { - format!( - "Column '{}': MAP type requires key and value children", - name - ) - })?; - let val_zv = child_iter.next().ok_or_else(|| { - format!( - "Column '{}': MAP type requires key and value children", - name - ) - })?; - let key_field = - php_schema_entry_to_field(key_zv.array().ok_or_else(|| { - format!("Column '{}': MAP key child must be an array", name) - })?)?; - let val_field = - php_schema_entry_to_field(val_zv.array().ok_or_else(|| { - format!("Column '{}': MAP value child must be an array", name) - })?)?; - let entries_struct = DataType::Struct(Fields::from(vec![key_field, val_field])); - DataType::Map( - Arc::new(Field::new("entries", entries_struct, false)), - false, - ) - } - other => { - return Err(format!("Column '{}': Unsupported type '{}'", name, other)); - } - }; - - Ok(Field::new(&name, data_type, nullable)) -} - -pub fn php_schema_to_arrow(schema: &ZendHashTable) -> Result { - if schema.is_empty() { - return Err("Schema must have at least one column".into()); - } - - let mut fields = Vec::with_capacity(schema.len()); - - for (_key, zv) in schema.iter() { - let entry_ht = zv - .array() - .ok_or_else(|| "Schema entry must be an array".to_string())?; - fields.push(php_schema_entry_to_field(entry_ht)?); - } - - Ok(Schema::new(fields)) -} - -pub fn php_array_to_arrow( - values: &[&Zval], - data_type: &DataType, - column_name: &str, -) -> Result { - match data_type { - DataType::Boolean => { - let mut builder = BooleanBuilder::with_capacity(values.len()); - for zv in values { - if zv.is_null() { - builder.append_null(); - } else if let Some(v) = zv.bool() { - builder.append_value(v); - } else { - return Err(format!( - "Column '{}': expected bool, got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(builder.finish()) as ArrayRef) - } - DataType::Int8 => build_int_array!(values, column_name, Int8Builder, i8), - DataType::Int16 => build_int_array!(values, column_name, Int16Builder, i16), - DataType::Int32 => build_int_array!(values, column_name, Int32Builder, i32), - DataType::Int64 => build_int_array!(values, column_name, Int64Builder, i64), - DataType::UInt8 => build_int_array!(values, column_name, UInt8Builder, u8), - DataType::UInt16 => build_int_array!(values, column_name, UInt16Builder, u16), - DataType::UInt32 => build_int_array!(values, column_name, UInt32Builder, u32), - DataType::UInt64 => { - let mut builder = UInt64Builder::with_capacity(values.len()); - for zv in values { - if zv.is_null() { - builder.append_null(); - } else if let Some(v) = zv.long() { - let converted = - u64::try_from(v).map_err(|_| { - format!( - "Column '{}': value {} out of range for u64 (valid range: {} to {})", - column_name, v, u64::MIN, u64::MAX - ) - })?; - builder.append_value(converted); - } else if let Some(s) = zv.str() { - let parsed: u64 = s.parse().map_err(|e| { - format!( - "Column '{}': failed to parse '{}' as u64: {}", - column_name, s, e - ) - })?; - builder.append_value(parsed); - } else { - return Err(format!( - "Column '{}': expected int or string, got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(builder.finish()) as ArrayRef) - } - DataType::Float32 => build_float_array!(values, column_name, Float32Builder, f32), - DataType::Float64 => build_float_array!(values, column_name, Float64Builder, f64), - DataType::Utf8 => { - let mut builder = StringBuilder::with_capacity(values.len(), values.len() * 32); - for zv in values { - if zv.is_null() { - builder.append_null(); - } else if let Some(s) = zv.str() { - builder.append_value(s); - } else { - return Err(format!( - "Column '{}': expected string, got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(builder.finish()) as ArrayRef) - } - DataType::Binary => { - let mut builder = BinaryBuilder::with_capacity(values.len(), values.len() * 32); - for zv in values { - if zv.is_null() { - builder.append_null(); - } else if let Some(zend_str) = zv.zend_str() { - builder.append_value(zend_str.as_bytes()); - } else { - return Err(format!( - "Column '{}': expected string (binary), got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(builder.finish()) as ArrayRef) - } - DataType::FixedSizeBinary(n) => { - let mut builder = FixedSizeBinaryBuilder::with_capacity(values.len(), *n); - for zv in values { - if zv.is_null() { - builder.append_null(); - } else if let Some(zend_str) = zv.zend_str() { - let bytes = zend_str.as_bytes(); - if bytes.len() == *n as usize { - builder - .append_value(bytes) - .map_err(|e| format!("Column '{}': {}", column_name, e))?; - } else if *n == 16 && (bytes.len() == 36 || bytes.len() == 32) { - let hex: String = bytes - .iter() - .filter(|b| **b != b'-') - .map(|b| *b as char) - .collect(); - if hex.len() != 32 { - return Err(format!("Column '{}': invalid UUID string", column_name)); - } - let mut uuid_bytes = [0u8; 16]; - for i in 0..16 { - uuid_bytes[i] = u8::from_str_radix(&hex[i * 2..i * 2 + 2], 16) - .map_err(|e| { - format!("Column '{}': invalid UUID hex: {}", column_name, e) - })?; - } - builder - .append_value(uuid_bytes) - .map_err(|e| format!("Column '{}': {}", column_name, e))?; - } else { - return Err(format!( - "Column '{}': expected {} bytes for FIXED_SIZE_BINARY, got {}", - column_name, - n, - bytes.len() - )); - } - } else { - return Err(format!( - "Column '{}': expected string (binary), got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(builder.finish()) as ArrayRef) - } - DataType::Date32 => { - let mut builder = Date32Builder::with_capacity(values.len()); - for zv in values { - if zv.is_null() { - builder.append_null(); - } else if let Some(v) = zv.long() { - builder.append_value(i32::try_from(v).map_err(|_| { - format!( - "Column '{}': value {} out of range for DATE days", - column_name, v - ) - })?); - } else if zv.is_object() { - let (seconds, _) = extract_datetime_timestamp(zv, column_name)?; - let offset = extract_datetime_offset(zv, column_name)?; - builder.append_value((seconds + offset).div_euclid(86_400) as i32); - } else { - return Err(format!( - "Column '{}': expected DateTimeInterface or int, got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(builder.finish()) as ArrayRef) - } - DataType::Timestamp(unit, tz) => { - let mut result: Vec> = Vec::with_capacity(values.len()); - for zv in values { - if zv.is_null() { - result.push(None); - } else if let Some(v) = zv.long() { - result.push(Some(v)); - } else if zv.is_object() { - let (seconds, microseconds) = extract_datetime_timestamp(zv, column_name)?; - let total = seconds * 1_000_000 + microseconds; - result.push(Some(match unit { - TimeUnit::Second => total.div_euclid(1_000_000), - TimeUnit::Millisecond => total.div_euclid(1_000), - TimeUnit::Microsecond => total, - TimeUnit::Nanosecond => total.checked_mul(1_000).ok_or_else(|| { - format!( - "Column '{}': DateTime outside the TIMESTAMP(NANOS) range", - column_name - ) - })?, - })); - } else { - return Err(format!( - "Column '{}': expected DateTimeInterface or int, got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(match unit { - TimeUnit::Second => { - Arc::new(TimestampSecondArray::from(result).with_timezone_opt(tz.clone())) - as ArrayRef - } - TimeUnit::Millisecond => { - Arc::new(TimestampMillisecondArray::from(result).with_timezone_opt(tz.clone())) - as ArrayRef - } - TimeUnit::Microsecond => { - Arc::new(TimestampMicrosecondArray::from(result).with_timezone_opt(tz.clone())) - as ArrayRef - } - TimeUnit::Nanosecond => { - Arc::new(TimestampNanosecondArray::from(result).with_timezone_opt(tz.clone())) - as ArrayRef - } - }) - } - DataType::Time32(TimeUnit::Millisecond) => { - let mut result: Vec> = Vec::with_capacity(values.len()); - for zv in values { - if zv.is_null() { - result.push(None); - } else if let Some(v) = zv.long() { - result.push(Some(i32::try_from(v).map_err(|_| { - format!( - "Column '{}': value {} out of range for TIME(MILLIS)", - column_name, v - ) - })?)); - } else if zv.is_object() { - result.push(Some( - extract_date_interval_microseconds(zv, column_name)?.div_euclid(1_000) - as i32, - )); - } else { - return Err(format!( - "Column '{}': expected DateInterval or int, got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(Arc::new(Time32MillisecondArray::from(result)) as ArrayRef) - } - DataType::Time64(unit @ (TimeUnit::Microsecond | TimeUnit::Nanosecond)) => { - let mut result: Vec> = Vec::with_capacity(values.len()); - for zv in values { - if zv.is_null() { - result.push(None); - } else if let Some(v) = zv.long() { - result.push(Some(v)); - } else if zv.is_object() { - let micros = extract_date_interval_microseconds(zv, column_name)?; - result.push(Some(if *unit == TimeUnit::Nanosecond { - micros * 1_000 - } else { - micros - })); - } else { - return Err(format!( - "Column '{}': expected DateInterval or int, got {}", - column_name, - zval_type_name(zv) - )); - } - } - Ok(if *unit == TimeUnit::Nanosecond { - Arc::new(Time64NanosecondArray::from(result)) as ArrayRef - } else { - Arc::new(Time64MicrosecondArray::from(result)) as ArrayRef - }) - } - DataType::Decimal128(p, s) => { - let mut builder = Decimal128Builder::with_capacity(values.len()); - for zv in values { - if zv.is_null() { - builder.append_null(); - } else if let Some(str_val) = zv.str() { - let unscaled = parse_decimal_string(str_val, *s)?; - builder.append_value(unscaled); - } else if let Some(v) = zv.double() { - let str_val = round_decimal_half_away(&format!("{}", v), *s); - let unscaled = parse_decimal_string(&str_val, *s)?; - builder.append_value(unscaled); - } else if let Some(v) = zv.long() { - let str_val = format!("{}.{}", v, "0".repeat(*s as usize)); - let unscaled = parse_decimal_string(&str_val, *s)?; - builder.append_value(unscaled); - } else { - return Err(format!( - "Column '{}': expected string, float, or int for DECIMAL, got {}", - column_name, - zval_type_name(zv) - )); - } - } - let array = builder - .finish() - .with_precision_and_scale(*p, *s) - .map_err(|e| format!("Column '{}': {}", column_name, e))?; - Ok(Arc::new(array) as ArrayRef) - } - DataType::List(child_field) => { - let mut offsets = vec![0i32]; - let mut null_bits: Vec = Vec::with_capacity(values.len()); - let mut child_refs: Vec<&Zval> = Vec::new(); - - for zv in values { - if zv.is_null() { - null_bits.push(false); - offsets.push(*offsets.last().unwrap()); - } else { - null_bits.push(true); - let arr = zv.array().ok_or_else(|| { - format!( - "Column '{}': expected array for LIST, got {}", - column_name, - zval_type_name(zv) - ) - })?; - for (_key, elem) in arr.iter() { - child_refs.push(elem); - } - offsets.push(child_refs.len() as i32); - } - } - - let child_array = php_array_to_arrow( - &child_refs, - child_field.data_type(), - &format!("{}.item", column_name), - )?; - - let offsets_buffer = OffsetBuffer::new(ScalarBuffer::from(offsets)); - let null_buffer = NullBuffer::from(null_bits); - - Ok(Arc::new( - ListArray::try_new( - child_field.clone(), - offsets_buffer, - child_array, - Some(null_buffer), - ) - .map_err(|e| format!("Column '{}': {}", column_name, e))?, - ) as ArrayRef) - } - DataType::Struct(fields) => { - let null_zval = Zval::new(); - - for (row_idx, zv) in values.iter().enumerate() { - if !zv.is_null() { - let arr = zv.array().ok_or_else(|| { - format!( - "Column '{}': expected array for STRUCT at row {}, got {}", - column_name, - row_idx, - zval_type_name(zv) - ) - })?; - for field in fields.iter() { - if !field.is_nullable() { - let child_val = arr.get(field.name().as_str()); - if child_val.is_none() || child_val.unwrap().is_null() { - return Err(format!( - "Column '{}': non-nullable field '{}' is missing/null at row {}", - column_name, - field.name(), - row_idx - )); - } - } - } - } - } - - let null_bits: Vec = values.iter().map(|zv| !zv.is_null()).collect(); - let null_buffer = NullBuffer::from(null_bits); - - let child_arrays: Result, String> = fields - .iter() - .map(|field| { - let child_refs: Vec<&Zval> = values - .iter() - .map(|zv| { - if zv.is_null() { - &null_zval - } else { - zv.array() - .and_then(|arr| arr.get(field.name().as_str())) - .unwrap_or(&null_zval) - } - }) - .collect(); - - php_array_to_arrow( - &child_refs, - field.data_type(), - &format!("{}.{}", column_name, field.name()), - ) - }) - .collect(); - - Ok(Arc::new( - StructArray::try_new(fields.clone(), child_arrays?, Some(null_buffer)) - .map_err(|e| format!("Column '{}': {}", column_name, e))?, - ) as ArrayRef) - } - DataType::Map(entries_field, _) => { - let (key_field, val_field) = match entries_field.data_type() { - DataType::Struct(fields) if fields.len() == 2 => (&fields[0], &fields[1]), - _ => { - return Err(format!( - "Column '{}': MAP entries must be Struct with key and value", - column_name - )) - } - }; - - let mut offsets = vec![0i32]; - let mut null_bits: Vec = Vec::with_capacity(values.len()); - let mut key_zvals: Vec = Vec::new(); - let mut val_refs: Vec<&Zval> = Vec::new(); - - for zv in values { - if zv.is_null() { - null_bits.push(false); - offsets.push(*offsets.last().unwrap()); - } else { - null_bits.push(true); - let arr = zv.array().ok_or_else(|| { - format!( - "Column '{}': expected array for MAP, got {}", - column_name, - zval_type_name(zv) - ) - })?; - for (key, val) in arr.iter() { - let mut key_zv = Zval::new(); - let set_key = |zv: &mut Zval, s: &str| { - zv.set_string(s, false).map_err(|_| { - format!("Column '{}': failed to set MAP key string", column_name) - }) - }; - match key { - ArrayKey::Long(n) => key_zv.set_long(n), - ArrayKey::String(ref s) => set_key(&mut key_zv, s)?, - ArrayKey::Str(s) => set_key(&mut key_zv, s)?, - ArrayKey::ZendString(zs) => { - let s = zs.as_str().map_err(|_| { - format!( - "Column '{}': failed to read MAP key string", - column_name - ) - })?; - set_key(&mut key_zv, s)?; - } - } - key_zvals.push(key_zv); - val_refs.push(val); - } - offsets.push(val_refs.len() as i32); - } - } - - let key_refs: Vec<&Zval> = key_zvals.iter().collect(); - let key_array = php_array_to_arrow( - &key_refs, - key_field.data_type(), - &format!("{}.key", column_name), - )?; - let val_array = php_array_to_arrow( - &val_refs, - val_field.data_type(), - &format!("{}.value", column_name), - )?; - - let entries_struct = StructArray::try_new( - Fields::from(vec![key_field.clone(), val_field.clone()]), - vec![key_array, val_array], - None, - ) - .map_err(|e| format!("Column '{}': {}", column_name, e))?; - - let offsets_buffer = OffsetBuffer::new(ScalarBuffer::from(offsets)); - let null_buffer = NullBuffer::from(null_bits); - - let map_array = MapArray::try_new( - entries_field.clone(), - offsets_buffer, - entries_struct, - Some(null_buffer), - false, - ) - .map_err(|e| format!("Column '{}': {}", column_name, e))?; - - Ok(Arc::new(map_array) as ArrayRef) - } - _ => Err(format!( - "Column '{}': unsupported data type {:?} in writer", - column_name, data_type - )), - } -} diff --git a/src/extension/flow-php-ext/src/parquet/write.rs b/src/extension/arrow-ext/src/parquet/write.rs similarity index 100% rename from src/extension/flow-php-ext/src/parquet/write.rs rename to src/extension/arrow-ext/src/parquet/write.rs diff --git a/src/extension/arrow-ext/src/parquet/writer.rs b/src/extension/arrow-ext/src/parquet/writer.rs deleted file mode 100644 index be26ae0578..0000000000 --- a/src/extension/arrow-ext/src/parquet/writer.rs +++ /dev/null @@ -1,269 +0,0 @@ -use std::str::FromStr; -use std::sync::Arc; - -use arrow_array::RecordBatch; -use arrow_schema::Schema as ArrowSchema; -use ext_php_rs::prelude::*; -use ext_php_rs::types::{ArrayKey, ZendHashTable, ZendObject}; -use parquet::arrow::ArrowWriter; -use parquet::basic::{BrotliLevel, Compression, Encoding, GzipLevel, ZstdLevel}; -use parquet::file::properties::{WriterProperties, WriterVersion}; -use parquet::schema::types::ColumnPath; - -use crate::parquet::exception::parquet_exception; -use crate::parquet::type_converter; -use crate::stream::php_destination_stream::PhpDestinationStream; - -#[php_class] -#[php(name = "Flow\\Arrow\\Parquet\\Writer")] -#[derive(Default)] -pub struct Writer { - writer: Option>, - schema: Option>, -} - -fn parse_compression( - s: &str, - gzip_level: Option, - brotli_level: Option, - zstd_level: Option, -) -> Result { - match s.to_uppercase().as_str() { - "UNCOMPRESSED" => Ok(Compression::UNCOMPRESSED), - "SNAPPY" => Ok(Compression::SNAPPY), - "GZIP" => { - let level = match gzip_level { - Some(l) => GzipLevel::try_new(l) - .map_err(|e| format!("Invalid GZIP compression level: {}", e))?, - None => Default::default(), - }; - Ok(Compression::GZIP(level)) - } - "ZSTD" => { - let level = match zstd_level { - Some(l) => ZstdLevel::try_new(l) - .map_err(|e| format!("Invalid ZSTD compression level: {}", e))?, - None => Default::default(), - }; - Ok(Compression::ZSTD(level)) - } - "LZ4" | "LZ4_RAW" => Ok(Compression::LZ4_RAW), - "BROTLI" => { - let level = match brotli_level { - Some(l) => BrotliLevel::try_new(l) - .map_err(|e| format!("Invalid BROTLI compression level: {}", e))?, - None => Default::default(), - }; - Ok(Compression::BROTLI(level)) - } - other => Err(format!( - "Unsupported compression codec '{}'. Supported: UNCOMPRESSED, SNAPPY, GZIP, ZSTD, LZ4, LZ4_RAW, BROTLI", - other - )), - } -} - -fn parse_encoding(s: &str) -> Result { - Encoding::from_str(&s.to_uppercase()) - .map_err(|e| format!("Unsupported encoding '{}': {}", s, e)) -} - -fn apply_writer_options( - mut builder: parquet::file::properties::WriterPropertiesBuilder, - options: &ZendHashTable, - compression_str: &str, -) -> Result { - let gzip_level = options - .get("GZIP_COMPRESSION_LEVEL") - .and_then(|z| z.long()) - .map(|v| v as u32); - - let brotli_level = options - .get("BROTLI_COMPRESSION_LEVEL") - .and_then(|z| z.long()) - .map(|v| v as u32); - - let zstd_level = options - .get("ZSTD_COMPRESSION_LEVEL") - .and_then(|z| z.long()) - .map(|v| v as i32); - - let codec = parse_compression(compression_str, gzip_level, brotli_level, zstd_level)?; - builder = builder.set_compression(codec); - - if let Some(val) = options.get("ROW_GROUP_SIZE_BYTES").and_then(|z| z.long()) { - builder = builder.set_max_row_group_bytes(Some(val as usize)); - } - - if let Some(val) = options.get("PAGE_SIZE_BYTES").and_then(|z| z.long()) { - builder = builder.set_data_page_size_limit(val as usize); - } - - if let Some(val) = options.get("DICTIONARY_PAGE_SIZE").and_then(|z| z.long()) { - builder = builder.set_dictionary_page_size_limit(val as usize); - } - - if let Some(val) = options.get("WRITER_VERSION").and_then(|z| z.long()) { - let version = match val { - 1 => WriterVersion::PARQUET_1_0, - 2 => WriterVersion::PARQUET_2_0, - other => { - return Err(format!( - "Invalid WRITER_VERSION '{}'. Must be 1 or 2", - other - )) - } - }; - builder = builder.set_writer_version(version); - } - - if let Some(col_comp_zval) = options.get("COLUMNS_COMPRESSIONS") { - if let Some(col_comp_ht) = col_comp_zval.array() { - for (key, val) in col_comp_ht.iter() { - let col_path_str = match key { - ArrayKey::String(ref s) => s.clone(), - ArrayKey::Str(s) => s.to_string(), - _ => continue, - }; - if let Some(codec_str) = val.str() { - let parts: Vec = - col_path_str.split('.').map(|s| s.to_string()).collect(); - let col_path = ColumnPath::new(parts); - let col_codec = - parse_compression(codec_str, gzip_level, brotli_level, zstd_level)?; - builder = builder.set_column_compression(col_path, col_codec); - } - } - } - } - - if let Some(col_enc_zval) = options.get("COLUMNS_ENCODINGS") { - if let Some(col_enc_ht) = col_enc_zval.array() { - for (key, val) in col_enc_ht.iter() { - let col_path_str = match key { - ArrayKey::String(ref s) => s.clone(), - ArrayKey::Str(s) => s.to_string(), - _ => continue, - }; - if let Some(enc_str) = val.str() { - let parts: Vec = - col_path_str.split('.').map(|s| s.to_string()).collect(); - let col_path = ColumnPath::new(parts); - let encoding = parse_encoding(enc_str)?; - builder = builder.set_column_encoding(col_path, encoding); - } - } - } - } - - Ok(builder) -} - -impl Drop for Writer { - fn drop(&mut self) { - if let Some(writer) = self.writer.take() { - let _ = writer.close(); - } - } -} - -#[php_impl] -impl Writer { - pub fn __construct( - stream: &mut ZendObject, - schema: &ZendHashTable, - compression: Option, - options: Option<&ZendHashTable>, - ) -> PhpResult { - let dest = PhpDestinationStream::new(stream).map_err(parquet_exception)?; - - let arrow_schema = - type_converter::php_schema_to_arrow(schema).map_err(parquet_exception)?; - - let compression_str = compression.as_deref().unwrap_or("SNAPPY"); - - let props = if let Some(opts) = options { - if !opts.is_empty() { - let builder = WriterProperties::builder(); - apply_writer_options(builder, opts, compression_str) - .map_err(parquet_exception)? - .build() - } else { - let codec = parse_compression(compression_str, None, None, None) - .map_err(parquet_exception)?; - WriterProperties::builder().set_compression(codec).build() - } - } else { - let codec = - parse_compression(compression_str, None, None, None).map_err(parquet_exception)?; - WriterProperties::builder().set_compression(codec).build() - }; - - let schema_arc = Arc::new(arrow_schema); - - let writer = ArrowWriter::try_new(dest, schema_arc.clone(), Some(props)) - .map_err(|e| parquet_exception(format!("Failed to create Parquet writer: {}", e)))?; - - Ok(Self { - writer: Some(writer), - schema: Some(schema_arc), - }) - } - - #[allow(non_snake_case)] - pub fn writeBatch(&mut self, batch: &ZendHashTable) -> PhpResult<()> { - let schema = self - .schema - .clone() - .ok_or_else(|| parquet_exception("Writer is closed"))?; - - let writer = self - .writer - .as_mut() - .ok_or_else(|| parquet_exception("Writer is closed"))?; - - let mut columns = Vec::with_capacity(schema.fields().len()); - - for field in schema.fields() { - let col_zval = batch.get(field.name().as_str()).ok_or_else(|| { - parquet_exception(format!("Batch is missing column '{}'", field.name())) - })?; - - let php_ht = col_zval.array().ok_or_else(|| { - parquet_exception(format!("Column '{}' must be an array", field.name())) - })?; - - let values: Vec<&ext_php_rs::types::Zval> = php_ht.values().collect(); - - let array = - type_converter::php_array_to_arrow(&values, field.data_type(), field.name()) - .map_err(parquet_exception)?; - - columns.push(array); - } - - let record_batch = RecordBatch::try_new(schema, columns) - .map_err(|e| parquet_exception(format!("Failed to create record batch: {}", e)))?; - - writer - .write(&record_batch) - .map_err(|e| parquet_exception(format!("Failed to write batch: {}", e)))?; - - Ok(()) - } - - pub fn close(&mut self) -> PhpResult<()> { - let writer = self - .writer - .take() - .ok_or_else(|| parquet_exception("Writer is already closed"))?; - - self.schema = None; - - writer - .close() - .map_err(|e| parquet_exception(format!("Failed to close Parquet writer: {}", e)))?; - - Ok(()) - } -} diff --git a/src/extension/arrow-ext/src/php.rs b/src/extension/arrow-ext/src/php.rs new file mode 100644 index 0000000000..c9ec2ce6bb --- /dev/null +++ b/src/extension/arrow-ext/src/php.rs @@ -0,0 +1,396 @@ +//! PHP-engine plumbing: class-entry/slot lookups, hashtable helpers, calls, and the request-scoped cache of datetime +//! handles, timezones and thrift specs. + +use std::collections::HashMap; +use std::rc::Rc; + +use ext_php_rs::boxed::ZBox; +use ext_php_rs::exception::PhpException; +use ext_php_rs::ffi::{ + _zend_property_info, zend_call_known_function, zend_hash_index_update, zend_hash_str_find, zend_hash_str_update, + zend_ulong, +}; +use ext_php_rs::prelude::PhpResult; +use ext_php_rs::types::{ZendHashTable, ZendObject, ZendStr, Zval}; +use ext_php_rs::zend::{ClassEntry, ExecutorGlobals, Function, ModuleGlobal, ModuleGlobals}; + +use crate::exception::ext_exception; +use crate::thrift::Specs; + +/// PHP array-key coercion (`_zend_handle_numeric_str`): parse + canonical +/// re-format equality rejects "+5", "-0", leading zeros and whitespace exactly +/// like the engine. +fn array_key_index(key: &[u8]) -> Option { + let string = std::str::from_utf8(key).ok()?; + let value: i64 = string.parse().ok()?; + + (value.to_string().as_bytes() == key).then_some(value) +} + +/// Inserts with PHP array-assignment semantics; ownership of `value` moves +/// into the table. +pub fn ht_insert(ht: &mut ZendHashTable, key: &[u8], mut value: Zval) { + unsafe { + match array_key_index(key) { + Some(index) => { + zend_hash_index_update(ht, index as u64, std::ptr::from_mut(&mut value)); + } + None => { + zend_hash_str_update(ht, key.as_ptr().cast(), key.len(), std::ptr::from_mut(&mut value)); + } + } + } + + std::mem::forget(value); +} + +pub fn ht_insert_long(ht: &mut ZendHashTable, index: i64, mut value: Zval) { + unsafe { + zend_hash_index_update(ht, index as u64, std::ptr::from_mut(&mut value)); + } + + std::mem::forget(value); +} + +/// `$array[$key]` with PHP array-key coercion. +pub fn ht_get<'a>(ht: &'a ZendHashTable, key: &[u8]) -> Option<&'a Zval> { + match array_key_index(key) { + Some(index) => ht.get_index(index), + None => unsafe { zend_hash_str_find(ht, key.as_ptr().cast(), key.len()).as_ref() }, + } +} + +pub fn zval_str(bytes: &[u8]) -> Zval { + let mut zv = Zval::new(); + zv.set_zend_string(ZendStr::new(bytes, false)); + zv +} + +pub fn zval_long(value: i64) -> Zval { + let mut zv = Zval::new(); + zv.set_long(value); + zv +} + +pub fn find_class(name: &str) -> Result<&'static ClassEntry, PhpException> { + ClassEntry::try_find(name).ok_or_else(|| ext_exception(format!("arrow requires class \"{name}\" to be autoloadable"))) +} + +/// Fails when the last engine call left an exception pending, so PHP-level +/// failures are never silently ignored. +pub fn ensure_no_pending_exception(context: &str) -> Result<(), PhpException> { + if ExecutorGlobals::get().exception.is_null() { + return Ok(()); + } + + Err(ext_exception(format!("arrow failed to {context}"))) +} + +/// Resolves a declared property's property-table slot offset; keyed by the +/// plain (unmangled) name for private properties too. +pub fn property_offset(ce: &ClassEntry, name: &str) -> Result { + let properties_info: &ZendHashTable = &ce.properties_info; + + let info = properties_info + .get(name) + .and_then(|zv| unsafe { zv.ptr::<_zend_property_info>() }) + .ok_or_else(|| { + ext_exception(format!( + "arrow failed to resolve property \"{name}\" on class \"{}\"", + ce.name().unwrap_or_default() + )) + })?; + + Ok(unsafe { (*info).offset }) +} + +/// Reads one property with `BP_VAR_R` semantics; `ZendObject::get_property` passes `BP_VAR_W`, which trips the +/// readonly-property guard. +pub fn read_property(obj: &ZendObject, name: &str) -> Result { + let handler = unsafe { obj.handlers.as_ref() } + .and_then(|handlers| handlers.read_property) + .ok_or_else(|| ext_exception("arrow failed to resolve a property read handler"))?; + + let mut name_zstr = ZendStr::new(name, false); + let mut rv = Zval::new(); + + let value = unsafe { + handler( + std::ptr::from_ref(obj).cast_mut(), + std::ptr::from_mut(&mut *name_zstr), + 0, + std::ptr::null_mut(), + std::ptr::from_mut(&mut rv), + ) + .as_ref() + } + .ok_or_else(|| ext_exception(format!("arrow failed to read property \"{name}\"")))?; + ensure_no_pending_exception(&format!("read property \"{name}\""))?; + + Ok(value.shallow_clone()) +} + +pub fn ce_method_ref(ce: &ClassEntry, method: &str) -> Result<&'static Function, PhpException> { + let function = unsafe { + ext_php_rs::ffi::zend_hash_str_find_ptr_lc(&raw const ce.function_table, method.as_ptr().cast(), method.len()) + .cast::() + .as_ref() + }; + + function.ok_or_else(|| { + ext_exception(format!("arrow failed to resolve method {}::{method}", ce.name().unwrap_or_default())) + }) +} + +/// Calls a pre-resolved function handle and hands a PHP exception thrown by the callee back to the caller as the +/// exception OBJECT, so the caller can surface it verbatim or replace it with one of its own. Taking it also clears +/// the pending exception, leaving the engine ready for the next call. +pub fn call_handle_catching( + func: &Function, + object: Option<&ZendObject>, + args: &mut [Zval], +) -> Result> { + let mut retval = Zval::new(); + + let (object_ptr, called_scope) = match object { + Some(obj) => (std::ptr::from_ref(obj).cast_mut(), obj.ce), + None => (std::ptr::null_mut(), unsafe { func.common.scope }), + }; + + unsafe { + zend_call_known_function( + std::ptr::from_ref(func).cast_mut(), + object_ptr, + called_scope, + std::ptr::from_mut(&mut retval), + args.len() as u32, + args.as_mut_ptr(), + std::ptr::null_mut(), + ); + } + + match ExecutorGlobals::take_exception() { + Some(exception) => Err(exception), + None => Ok(retval), + } +} + +/// Surfaces a PHP exception object as ITSELF rather than wrapped, so the class and message PHP sees are the ones +/// thrown. +pub fn transparent_exception(exception: &mut ZendObject) -> PhpException { + let mut zv = Zval::new(); + zv.set_object(exception); + + PhpException::default(String::new()).with_object(zv) +} + +/// [`call_handle_catching`] with the exception object already re-raised as itself. +pub fn call_handle_transparent( + func: &Function, + object: Option<&ZendObject>, + args: &mut [Zval], +) -> Result { + call_handle_catching(func, object, args).map_err(|mut exception| transparent_exception(&mut exception)) +} + +/// Calls a pre-resolved function handle. Argument zvals stay caller-owned +/// (the engine copies what it keeps), so cached zvals pass as shallow clones. +pub fn call_handle( + func: &Function, + object: Option<&mut ZendObject>, + args: &mut [Zval], + context: &str, +) -> Result { + let mut retval = Zval::new(); + + let (object_ptr, called_scope) = match object { + Some(obj) => { + let scope = obj.ce; + (std::ptr::from_mut(obj), scope) + } + None => (std::ptr::null_mut(), unsafe { func.common.scope }), + }; + + unsafe { + zend_call_known_function( + std::ptr::from_ref(func).cast_mut(), + object_ptr, + called_scope, + std::ptr::from_mut(&mut retval), + args.len() as u32, + args.as_mut_ptr(), + std::ptr::null_mut(), + ); + } + + ensure_no_pending_exception(context)?; + + Ok(retval) +} + +/// `HASH_FLAG_PACKED` from zend_types.h. +const HASH_FLAG_PACKED: u8 = 1 << 2; + +/// Raw order-preserving iteration over packed and bucket layouts, binary-safe +/// for arbitrary keys (ext-php-rs's `iter()` panics on non-UTF-8 string keys). +pub fn ht_for_each<'a>( + ht: &'a ZendHashTable, + mut f: impl FnMut(Option<&'a ZendStr>, zend_ulong, &'a Zval) -> Result<(), PhpException>, +) -> Result<(), PhpException> { + let packed = unsafe { ht.u.v.flags } & HASH_FLAG_PACKED != 0; + + for index in 0..ht.nNumUsed { + if packed { + let value = unsafe { &*ht.__bindgen_anon_1.arPacked.add(index as usize) }; + + if value.get_type() == ext_php_rs::flags::DataType::Undef { + continue; + } + + f(None, zend_ulong::from(index), value)?; + } else { + let bucket = unsafe { &*ht.__bindgen_anon_1.arData.add(index as usize) }; + + if bucket.val.get_type() == ext_php_rs::flags::DataType::Undef { + continue; + } + + let key = unsafe { bucket.key.as_ref() }; + f(key, bucket.h, &bucket.val)?; + } + } + + Ok(()) +} + +pub fn expect_object<'a>(zv: &'a Zval, context: &str) -> Result<&'a ZendObject, PhpException> { + zv.object().ok_or_else(|| ext_exception(format!("arrow expected {context} to be an object"))) +} + +/// Request-scoped caches of class entries, function handles and value zvals, reached only through [`with_ctx`]: +/// every function below reads and writes the cache inside the closure and calls PHP (autoload, constructors) +/// outside it, so PHP code re-entering arrow never meets a borrowed `Ctx`. +#[derive(Default)] +pub struct Ctx { + timezone: Option, + datetime_immutable: Option, + timezones: HashMap, Zval>, + /// The `$_TSPEC`s reachable from a root thrift class, by that class. + pub thrift_specs: HashMap>, +} + +#[derive(Clone, Copy)] +pub struct DateTimeFns { + pub ce: &'static ClassEntry, + pub set_timezone: &'static Function, +} + +#[derive(Clone, Copy)] +struct TimezoneFns { + ce: &'static ClassEntry, + construct: &'static Function, +} + +/// A cached handle: read inside the context, resolved outside it on a miss, then stored. +fn cached( + read: impl FnOnce(&Ctx) -> Option, + resolve: impl FnOnce() -> Result, + store: impl FnOnce(&mut Ctx, &T), +) -> Result { + if let Some(value) = with_ctx(|ctx| Ok(read(ctx)))? { + return Ok(value); + } + + let value = resolve()?; + with_ctx(|ctx| { + store(ctx, &value); + Ok(()) + })?; + + Ok(value) +} + +pub fn datetime_immutable() -> Result { + cached( + |ctx| ctx.datetime_immutable, + || { + let ce = find_class("DateTimeImmutable")?; + Ok(DateTimeFns { + ce, + set_timezone: ce_method_ref(ce, "setTimezone")?, + }) + }, + |ctx, fns| ctx.datetime_immutable = Some(*fns), + ) +} + +fn timezone_fns() -> Result { + cached( + |ctx| ctx.timezone, + || { + let ce = find_class("DateTimeZone")?; + Ok(TimezoneFns { + ce, + construct: ce_method_ref(ce, "__construct")?, + }) + }, + |ctx, fns| ctx.timezone = Some(*fns), + ) +} + +/// `new DateTimeZone($name)`, one instance per name. +pub fn timezone(name: &[u8]) -> Result { + cached( + |ctx| ctx.timezones.get(name).map(Zval::shallow_clone), + || { + let fns = timezone_fns()?; + let mut timezone = ZendObject::new(fns.ce); + call_handle(fns.construct, Some(&mut timezone), &mut [zval_str(name)], "construct DateTimeZone")?; + + let mut zv = Zval::new(); + zv.set_object(&mut timezone); + + Ok(zv) + }, + |ctx, zv| { + ctx.timezones.insert(name.to_vec(), zv.shallow_clone()); + }, + ) +} + +/// Per-request state: the `Ctx` cache lives in module globals (per thread on ZTS), is built lazily and is dropped in +/// RSHUTDOWN, while the executor still runs; objects freed after RSHUTDOWN never touch it. +#[derive(Default)] +pub struct ArrowGlobals { + ctx: Option, + closed: bool, +} + +impl ModuleGlobal for ArrowGlobals {} + +pub static GLOBALS: ModuleGlobals = ModuleGlobals::new(); + +pub extern "C" fn request_startup(_type: i32, _module_number: i32) -> i32 { + unsafe { GLOBALS.get_mut() }.closed = false; + + 0 +} + +pub extern "C" fn request_shutdown(_type: i32, _module_number: i32) -> i32 { + let globals = unsafe { GLOBALS.get_mut() }; + globals.ctx = None; + globals.closed = true; + + 0 +} + +/// The only access to `Ctx`. `f` must not call PHP code: PHP re-entering arrow would alias the `&mut Ctx`. +pub fn with_ctx(f: impl FnOnce(&mut Ctx) -> PhpResult) -> PhpResult { + let globals = unsafe { GLOBALS.get_mut() }; + + if globals.closed { + return Err(ext_exception("arrow used after request shutdown")); + } + + f(globals.ctx.get_or_insert_with(Ctx::default)) +} diff --git a/src/extension/arrow-ext/src/render.rs b/src/extension/arrow-ext/src/render.rs new file mode 100644 index 0000000000..578414793d --- /dev/null +++ b/src/extension/arrow-ext/src/render.rs @@ -0,0 +1,82 @@ +//! Parquet core refusals rendered as the `Flow\Parquet` exceptions, for the readers and the writer. + +use ext_php_rs::exception::PhpException; + +use crate::parquet::error::Error; +use crate::parquet::source::PhpStream; +use crate::php::{find_class, transparent_exception}; + +const RUNTIME: &str = "Flow\\Parquet\\Exception\\RuntimeException"; +const VALIDATION: &str = "Flow\\Parquet\\Exception\\ValidationException"; +const INVALID_ARGUMENT: &str = "Flow\\Parquet\\Exception\\InvalidArgumentException"; + +pub fn exception(class: &str, message: String) -> PhpException { + match find_class(class) { + Ok(ce) => PhpException::new(message, 0, ce), + Err(e) => e, + } +} + +/// Which Parquet surface refused: the same core refusal names what to do about it per side. +pub enum Side { + Read, + Write, +} + +/// A Parquet core refusal; an exception the stream threw while the core called it surfaces as itself. +pub fn parquet_exception(error: Error, stream: &PhpStream, side: Side) -> PhpException { + if let Some(mut thrown) = stream.thrown() { + return transparent_exception(&mut thrown); + } + + let failure = |message: String| exception(RUNTIME, message); + + match (error, side) { + (Error::Unsupported { column, parquet }, Side::Read) => exception( + RUNTIME, + format!( + "Parquet column \"{column}\" ({parquet}) is not supported by the arrow Parquet reader; read the file \ + with \\Flow\\Parquet\\Reader::php()" + ), + ), + (Error::Unsupported { column, parquet }, Side::Write) => exception( + RUNTIME, + format!( + "Parquet column \"{column}\" ({parquet}) is not supported by the arrow Parquet writer; write it with \ + \\Flow\\Parquet\\Writer::php()" + ), + ), + (Error::Overflow { column, row }, _) => exception( + RUNTIME, + format!("Parquet column \"{column}\" row {row} holds a value out of the range arrow stores it in"), + ), + (Error::InvalidUtf8 { column, row }, _) => exception( + RUNTIME, + format!( + "Parquet column \"{column}\" row {row} holds a string that is not valid UTF-8; Parquet STRING columns \ + require UTF-8" + ), + ), + (Error::Length { column, row, expected }, _) => exception( + RUNTIME, + format!("Parquet column \"{column}\" row {row} holds a value that is not {expected} bytes long"), + ), + (Error::Value { column, row, expected, got }, _) => { + exception(VALIDATION, format!("Column \"{column}\" row {row}: expected {expected}, got {got}")) + } + (Error::MapKey { column, key }, _) => exception( + INVALID_ARGUMENT, + format!("Map key of Parquet column \"{column}\" must be int or string, got {key}"), + ), + (Error::MissingColumn(name), _) => exception(INVALID_ARGUMENT, format!("Parquet file has no column \"{name}\"")), + (Error::Options(message), _) => exception(INVALID_ARGUMENT, message), + (Error::NotParquet(message), _) => { + exception(INVALID_ARGUMENT, format!("Given file is not valid Parquet file: {message}")) + } + (Error::Stream(message), _) => failure(format!("arrow Parquet stream {message}")), + (Error::Parquet(error), Side::Read) => failure(format!("arrow failed to read Parquet: {error}")), + (Error::Arrow(error), Side::Read) => failure(format!("arrow failed to read Parquet: {error}")), + (Error::Parquet(error), Side::Write) => failure(format!("arrow failed to write Parquet: {error}")), + (Error::Arrow(error), Side::Write) => failure(format!("arrow failed to write Parquet: {error}")), + } +} diff --git a/src/extension/arrow-ext/src/stream/mod.rs b/src/extension/arrow-ext/src/stream/mod.rs index 89278b895d..7eb0716190 100644 --- a/src/extension/arrow-ext/src/stream/mod.rs +++ b/src/extension/arrow-ext/src/stream/mod.rs @@ -1,4 +1,2 @@ pub mod output_stream; -pub mod php_destination_stream; -pub mod php_source_stream; pub mod random_access_file; diff --git a/src/extension/arrow-ext/src/stream/php_destination_stream.rs b/src/extension/arrow-ext/src/stream/php_destination_stream.rs deleted file mode 100644 index da8569c012..0000000000 --- a/src/extension/arrow-ext/src/stream/php_destination_stream.rs +++ /dev/null @@ -1,53 +0,0 @@ -use ext_php_rs::boxed::ZBox; -use ext_php_rs::convert::IntoZvalDyn; -use ext_php_rs::types::{ZendObject, Zval}; -use ext_php_rs::zend::ClassEntry; -use std::io::{self, Write}; - -pub struct PhpDestinationStream { - obj: ZBox, -} - -// SAFETY: PhpDestinationStream wraps a PHP ZendObject that belongs to the -// current request thread. In NTS mode PHP is single-threaded; in ZTS mode each -// thread owns its own request context. The parquet crate requires Send+Sync for -// ArrowWriter but never sends across threads in synchronous usage. -unsafe impl Send for PhpDestinationStream {} -unsafe impl Sync for PhpDestinationStream {} - -impl PhpDestinationStream { - pub fn new(obj: &mut ZendObject) -> Result { - let ce = ClassEntry::try_find("Flow\\Arrow\\OutputStream").ok_or_else(|| { - "Interface Flow\\Arrow\\OutputStream not loaded. Did you require the file?".to_string() - })?; - if !obj.instance_of(ce) { - return Err("Destination must implement Flow\\Arrow\\OutputStream".to_string()); - } - - let ptr: *mut ZendObject = obj; - unsafe { (*ptr).gc.refcount += 1 }; - Ok(Self { - obj: unsafe { ZBox::from_raw(ptr) }, - }) - } -} - -impl Write for PhpDestinationStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - let mut data = Zval::new(); - data.set_binary(buf.to_vec()); - - let _result = self - .obj - .try_call_method("append", vec![&data as &dyn IntoZvalDyn]) - .map_err(|e| io::Error::other(format!("Failed to call append(): {:?}", e)))?; - - // OutputStream::append() is all-or-nothing: it returns self on success - // or throws on failure (caught above). No partial write path exists. - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} diff --git a/src/extension/arrow-ext/src/stream/php_source_stream.rs b/src/extension/arrow-ext/src/stream/php_source_stream.rs deleted file mode 100644 index 5d070a3762..0000000000 --- a/src/extension/arrow-ext/src/stream/php_source_stream.rs +++ /dev/null @@ -1,104 +0,0 @@ -use bytes::Bytes; -use ext_php_rs::boxed::ZBox; -use ext_php_rs::convert::IntoZvalDyn; -use ext_php_rs::types::ZendObject; -use ext_php_rs::zend::ClassEntry; -use parquet::errors::ParquetError; -use parquet::file::reader::{ChunkReader, Length}; -use std::io::Cursor; -use std::sync::Arc; - -struct PhpSourceStreamInner { - obj: ZBox, - len: u64, -} - -// SAFETY: PhpSourceStream wraps a PHP ZendObject that belongs to the current -// request thread. In NTS mode PHP is single-threaded; in ZTS mode each thread -// owns its own request context. The parquet crate requires Send+Sync for -// ChunkReader but never sends across threads in synchronous usage. -unsafe impl Send for PhpSourceStreamInner {} -unsafe impl Sync for PhpSourceStreamInner {} - -#[derive(Clone)] -pub struct PhpSourceStream { - inner: Arc, -} - -impl PhpSourceStream { - pub fn new(obj: &mut ZendObject) -> Result { - let ce = ClassEntry::try_find("Flow\\Arrow\\RandomAccessFile").ok_or_else(|| { - "Interface Flow\\Arrow\\RandomAccessFile not loaded. Did you require the file?" - .to_string() - })?; - if !obj.instance_of(ce) { - return Err("Source must implement Flow\\Arrow\\RandomAccessFile".to_string()); - } - - let ptr: *mut ZendObject = obj; - unsafe { (*ptr).gc.refcount += 1 }; - let owned = unsafe { ZBox::from_raw(ptr) }; - - let zval = owned - .try_call_method("size", vec![]) - .map_err(|e| format!("Failed to call size(): {:?}", e))?; - - if zval.is_null() { - return Err("size() returned null; file size is required for Parquet reading".into()); - } - - let size = zval - .long() - .ok_or_else(|| "size() must return an integer".to_string())?; - - Ok(Self { - inner: Arc::new(PhpSourceStreamInner { - obj: owned, - len: size as u64, - }), - }) - } -} - -impl Length for PhpSourceStream { - fn len(&self) -> u64 { - self.inner.len - } -} - -impl ChunkReader for PhpSourceStream { - type T = Cursor>; - - fn get_read(&self, start: u64) -> parquet::errors::Result { - let length = self.inner.len.saturating_sub(start) as usize; - let bytes = self.get_bytes(start, length)?; - Ok(Cursor::new(bytes.into())) - } - - fn get_bytes(&self, start: u64, length: usize) -> parquet::errors::Result { - if length == 0 { - return Ok(Bytes::new()); - } - - let length_arg = length as i64; - let offset_arg = start as i64; - - let result = self - .inner - .obj - .try_call_method( - "read", - vec![ - &length_arg as &dyn IntoZvalDyn, - &offset_arg as &dyn IntoZvalDyn, - ], - ) - .map_err(|e| ParquetError::General(format!("Failed to call read(): {:?}", e)))?; - - let zend_str = result - .zend_str() - .ok_or_else(|| ParquetError::General("read() must return a string".into()))?; - - Ok(Bytes::copy_from_slice(zend_str.as_bytes())) - } -} diff --git a/src/extension/flow-php-ext/src/thrift.rs b/src/extension/arrow-ext/src/thrift.rs similarity index 88% rename from src/extension/flow-php-ext/src/thrift.rs rename to src/extension/arrow-ext/src/thrift.rs index c2d10bab0c..c896ec4bd7 100644 --- a/src/extension/flow-php-ext/src/thrift.rs +++ b/src/extension/arrow-ext/src/thrift.rs @@ -9,7 +9,7 @@ use ext_php_rs::exception::PhpException; use ext_php_rs::types::{ArrayKey, ZendHashTable, ZendObject, Zval}; use ext_php_rs::zend::ClassEntry; -use crate::ctx::{self, find_class, property_offset, zval_long, zval_str}; +use crate::php::{find_class, property_offset, with_ctx, zval_long, zval_str}; use crate::exception::ext_exception; /// Nesting deeper than this is refused instead of recursing further. @@ -93,26 +93,26 @@ impl Specs { let spec = ce .get_static_property::<&ZendHashTable>("_TSPEC") - .ok_or_else(|| ext_exception(format!("flow_php requires {name}::$_TSPEC to be an array")))?; + .ok_or_else(|| ext_exception(format!("arrow requires {name}::$_TSPEC to be an array")))?; let mut fields: Vec> = Vec::new(); for (key, entry) in spec.iter() { let ArrayKey::Long(id) = key else { - return Err(ext_exception(format!("flow_php requires {name}::$_TSPEC to be keyed by field id"))); + return Err(ext_exception(format!("arrow requires {name}::$_TSPEC to be keyed by field id"))); }; let entry = entry .array() - .ok_or_else(|| ext_exception(format!("flow_php requires {name}::$_TSPEC[{id}] to be an array")))?; + .ok_or_else(|| ext_exception(format!("arrow requires {name}::$_TSPEC[{id}] to be an array")))?; let var = entry .get("var") .and_then(Zval::str) - .ok_or_else(|| ext_exception(format!("flow_php requires {name}::$_TSPEC[{id}]['var']")))?; + .ok_or_else(|| ext_exception(format!("arrow requires {name}::$_TSPEC[{id}]['var']")))?; let offset = property_offset(ce, var)?; let value = self.value(entry, name, seen)?; let id = usize::try_from(id) .ok() .filter(|id| *id <= i16::MAX as usize) - .ok_or_else(|| ext_exception(format!("flow_php requires {name}::$_TSPEC field ids in 0..=32767")))?; + .ok_or_else(|| ext_exception(format!("arrow requires {name}::$_TSPEC field ids in 0..=32767")))?; if fields.len() <= id { fields.resize_with(id + 1, || None); @@ -128,7 +128,7 @@ impl Specs { /// A `$_TSPEC` entry's type (`'type'`, with `'class'` for a struct and `'elem'` for a list's element). fn value(&mut self, entry: &ZendHashTable, class: &str, seen: &mut HashMap) -> Result { - let unsupported = |what: String| ext_exception(format!("flow_php cannot decode {class}::$_TSPEC {what}")); + let unsupported = |what: String| ext_exception(format!("arrow cannot decode {class}::$_TSPEC {what}")); // Thrift\Type\TType Ok(match entry.get("type").and_then(Zval::long) { @@ -161,16 +161,27 @@ impl Specs { } } +fn thrift_specs(class: &str) -> Result>, PhpException> { + with_ctx(|ctx| Ok(ctx.thrift_specs.get(class).cloned())) +} + +fn store_thrift_specs(class: &str, specs: &Rc) -> Result<(), PhpException> { + with_ctx(|ctx| { + ctx.thrift_specs.insert(class.to_string(), Rc::clone(specs)); + Ok(()) + }) +} + /// `class`'s instance decoded from `bytes`; with `field`, only that field of the root is decoded and returned (null /// when absent), the fields before it skipped and the ones after it never read. STRUCT → object (created without its constructor, public properties set by /// `var`), LIST → list, BOOL/BYTE/I16/I32/I64/DOUBLE/STRING (binary) → scalars; an unknown id, or a known one of another /// type, is skipped by the compact skip rules. pub fn decode(bytes: &[u8], class: &str, field: Option) -> Result { - let specs = match ctx::thrift_specs(class)? { + let specs = match thrift_specs(class)? { Some(specs) => specs, None => { let specs = Rc::new(Specs::build(class)?); - ctx::store_thrift_specs(class, &specs)?; + store_thrift_specs(class, &specs)?; specs } }; @@ -188,7 +199,7 @@ struct Reader<'a> { } fn truncated() -> PhpException { - ext_exception("flow_php failed to decode thrift: the bytes end inside a value") + ext_exception("arrow failed to decode thrift: the bytes end inside a value") } impl Reader<'_> { @@ -219,7 +230,7 @@ impl Reader<'_> { } } - Err(ext_exception("flow_php failed to decode thrift: a varint longer than 10 bytes")) + Err(ext_exception("arrow failed to decode thrift: a varint longer than 10 bytes")) } fn zigzag(&mut self) -> Result { @@ -238,7 +249,7 @@ impl Reader<'_> { let delta = header >> 4; *last = if delta == 0 { - i16::try_from(self.zigzag()?).map_err(|_| ext_exception("flow_php failed to decode thrift: a field id"))? + i16::try_from(self.zigzag()?).map_err(|_| ext_exception("arrow failed to decode thrift: a field id"))? } else { last.wrapping_add(i16::from(delta)) }; @@ -259,7 +270,7 @@ impl Reader<'_> { fn skip(&mut self, wire: u8, depth: usize) -> Result<(), PhpException> { if depth > DEPTH { - return Err(ext_exception("flow_php failed to decode thrift: nested deeper than 64")); + return Err(ext_exception("arrow failed to decode thrift: nested deeper than 64")); } match wire { @@ -303,7 +314,7 @@ impl Reader<'_> { self.skip(wire, depth + 1)?; } } - other => return Err(ext_exception(format!("flow_php failed to decode thrift: compact type {other}"))), + other => return Err(ext_exception(format!("arrow failed to decode thrift: compact type {other}"))), } Ok(()) @@ -350,7 +361,7 @@ impl Reader<'_> { for _ in 0..size { let value = self.value(specs, item, wire, true, depth + 1)?.unwrap_or_default(); list.push(value) - .map_err(|e| ext_exception(format!("flow_php failed to collect a thrift list: {e:?}")))?; + .map_err(|e| ext_exception(format!("arrow failed to collect a thrift list: {e:?}")))?; } zv.set_hashtable(list); @@ -363,7 +374,7 @@ impl Reader<'_> { /// An instance of `specs`' class `class`, its properties set from the fields that arrive. fn object(&mut self, specs: &Specs, class: usize, depth: usize) -> Result { if depth > DEPTH { - return Err(ext_exception("flow_php failed to decode thrift: nested deeper than 64")); + return Err(ext_exception("arrow failed to decode thrift: nested deeper than 64")); } let class = &specs.classes[class]; diff --git a/src/extension/arrow-ext/src/values.rs b/src/extension/arrow-ext/src/values.rs new file mode 100644 index 0000000000..0fc00d70b0 --- /dev/null +++ b/src/extension/arrow-ext/src/values.rs @@ -0,0 +1,241 @@ +//! PHP value construction through the engine's C date API. + +use std::ffi::{c_char, c_int, c_uint, c_void}; + +use ext_php_rs::exception::PhpException; +use ext_php_rs::types::{ZendObject, Zval}; + +use crate::exception::ext_exception; +use crate::php::{self, call_handle, ensure_no_pending_exception}; + +extern "C" { + fn php_date_instantiate(pce: *mut ext_php_rs::zend::ClassEntry, object: *mut Zval) -> *mut Zval; + + #[cfg(php84)] + fn php_date_initialize_from_ts_long(dateobj: *mut c_void, sec: i64, usec: c_int); + + fn php_date_initialize( + dateobj: *mut c_void, + time_str: *const c_char, + time_str_len: usize, + format: *const c_char, + timezone_object: *mut Zval, + flags: c_int, + ) -> bool; +} + +const PHP_DATE_OBJ_STD_OFFSET: usize = std::mem::size_of::<*const c_void>(); + +/// `php_date_obj_from_obj`: the `php_date_obj` a datetime `zend_object` is embedded in. +fn php_date_obj(object: &mut ZendObject) -> *mut c_void { + std::ptr::from_mut(object) + .cast::() + .wrapping_sub(PHP_DATE_OBJ_STD_OFFSET) + .cast::() +} + +// `timelib_time` up to `tim_uptodate` (ext/date/lib/timelib.h, identical in the 2022.14-2022.17 timelib of PHP 8.3-8.5) +#[repr(C)] +struct TimelibSpecial { + kind: c_uint, + amount: i64, +} + +#[repr(C)] +struct TimelibRelTime { + y: i64, + m: i64, + d: i64, + h: i64, + i: i64, + s: i64, + us: i64, + weekday: c_int, + weekday_behavior: c_int, + first_last_day_of: c_int, + invert: c_int, + days: i64, + special: TimelibSpecial, + have_weekday_relative: c_uint, + have_special_relative: c_uint, +} + +#[repr(C)] +struct TimelibTime { + y: i64, + m: i64, + d: i64, + h: i64, + i: i64, + s: i64, + us: i64, + z: c_int, + tz_abbr: *mut c_char, + tz_info: *mut c_void, + dst: c_int, + relative: TimelibRelTime, + sse: i64, + have_time: c_uint, + have_date: c_uint, + have_zone: c_uint, + have_relative: c_uint, + have_weeknr_day: c_uint, + sse_uptodate: c_uint, + tim_uptodate: c_uint, +} + +/// The up-to-date `timelib_time` of a `DateTimeImmutable` (or subclass) object. +fn timelib_time(datetime: &ZendObject) -> Option<&TimelibTime> { + let dateobj = std::ptr::from_ref(datetime) + .cast::() + .wrapping_sub(PHP_DATE_OBJ_STD_OFFSET) + .cast::<*const TimelibTime>(); + let time = unsafe { (*dateobj).as_ref() }?; + + (time.sse_uptodate != 0 && time.tim_uptodate != 0).then_some(time) +} + +/// `getTimestamp() * 1_000_000 + format('u')`, `None` on i64 overflow. +pub fn datetime_micros(datetime: &ZendObject) -> Option { + let time = timelib_time(datetime)?; + + time.sse.checked_mul(1_000_000)?.checked_add(time.us) +} + +/// Days since the epoch of the value's own calendar day, `None` outside i32. +pub fn datetime_days(datetime: &ZendObject) -> Option { + let time = timelib_time(datetime)?; + let days = days_from_civil(time.y, time.m, time.d)?; + + i32::try_from(days).is_ok().then_some(days) +} + +/// Days since 1970-01-01 of a proleptic Gregorian date, `None` on i64 overflow. +fn days_from_civil(year: i64, month: i64, day: i64) -> Option { + let year = year - i64::from(month <= 2); + let era = (if year >= 0 { year } else { year.checked_sub(399)? }) / 400; + let year_of_era = year - era * 400; + let day_of_year = (153 * (if month > 2 { month - 3 } else { month + 9 }) + 2) / 5 + day - 1; + let day_of_era = year_of_era * 365 + year_of_era / 4 - year_of_era / 100 + day_of_year; + + era.checked_mul(146_097)?.checked_add(day_of_era - 719_468) +} + +/// A fresh `DateTimeImmutable` initialised by `init` over its `php_date_obj`, then moved into `zone`. +fn datetime_in(zone: &[u8], init: impl FnOnce(*mut c_void) -> bool, failure: impl FnOnce() -> PhpException) -> Result { + let fns = php::datetime_immutable()?; + let mut datetime = Zval::new(); + + unsafe { + php_date_instantiate(std::ptr::from_ref(fns.ce).cast_mut(), std::ptr::from_mut(&mut datetime)); + } + + let datetime_obj = datetime + .object_mut() + .ok_or_else(|| ext_exception("arrow failed to instantiate a datetime object"))?; + let initialized = init(php_date_obj(datetime_obj)); + + ensure_no_pending_exception("restore a datetime value")?; + + if !initialized { + return Err(failure()); + } + + let datetime = call_handle(fns.set_timezone, Some(datetime_obj), &mut [php::timezone(zone)?], "restore a datetime timezone")?; + + if !datetime.is_object() { + return Err(ext_exception("arrow expected setTimezone to return a datetime object")); + } + + Ok(datetime) +} + +/// The instant `micros` in `zone`. +pub fn datetime_from_micros(micros: i64, zone: &[u8]) -> Result { + let seconds = micros.div_euclid(1_000_000); + let fraction = micros.rem_euclid(1_000_000); + + datetime_in( + zone, + |dateobj| { + // the createFromTimestamp() initializer, exported from PHP 8.4 + #[cfg(php84)] + { + unsafe { php_date_initialize_from_ts_long(dateobj, seconds, fraction as c_int) }; + + true + } + + #[cfg(not(php84))] + { + // timelib reads the byte AFTER the consumed input, so the buffer must be NUL-terminated like the + // zend_strings PHP hands it (length excludes the NUL) + let mut time_str = format!("{seconds}.{fraction:06}\0"); + + unsafe { + php_date_initialize( + dateobj, + time_str.as_mut_ptr().cast::(), + time_str.len() - 1, + c"U.u".as_ptr(), + std::ptr::null_mut(), + // PHP_DATE_INIT_FORMAT - the flags createFromFormat passes + 0x02, + ) + } + } + }, + || ext_exception(format!("arrow failed to restore datetime from \"{micros}\" microseconds")), + ) +} + +/// `new DateTimeImmutable('@' . ($days * 86_400))` in UTC. +pub fn date_from_days(days: i64) -> Result { + let mut time_str = format!("@{}\0", days * 86_400); + + datetime_in( + b"UTC", + |dateobj| unsafe { + php_date_initialize( + dateobj, + time_str.as_mut_ptr().cast::(), + time_str.len() - 1, + std::ptr::null(), + std::ptr::null_mut(), + 0, + ) + }, + || ext_exception(format!("arrow failed to restore date from \"{days}\" days")), + ) +} + +/// The lowercase 36-char form of 16 uuid bytes. +pub fn uuid_text(bytes: &[u8]) -> Vec { + const HEX: &[u8; 16] = b"0123456789abcdef"; + let mut text = Vec::with_capacity(36); + + for (index, byte) in bytes.iter().enumerate() { + if matches!(index, 4 | 6 | 8 | 10) { + text.push(b'-'); + } + + text.push(HEX[usize::from(byte >> 4)]); + text.push(HEX[usize::from(byte & 0x0f)]); + } + + text +} + +/// `hex2bin()` of a 36-char uuid with its dashes removed. +pub fn uuid_bytes(text: &[u8]) -> Option<[u8; 16]> { + let mut bytes = [0u8; 16]; + let mut digits = text.iter().filter(|byte| **byte != b'-').map(|byte| (*byte as char).to_digit(16)); + + for byte in &mut bytes { + let high = digits.next()??; + let low = digits.next()??; + *byte = (high * 16 + low) as u8; + } + + digits.next().is_none().then_some(bytes) +} diff --git a/src/extension/arrow-ext/tests/fixtures/all_flat_types.parquet b/src/extension/arrow-ext/tests/fixtures/all_flat_types.parquet deleted file mode 100644 index ba93367e4341d36463ea58b0a14079b5f46c3532..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4837 zcmb7IU1(ER96$MJdYeW~YtQ9Ig3E)sxUI8k+Ged&^d$YTwckT)WS~hC)3j;RCFzIV z%N|7bFm#9yGR7EEM8=-PhcRSyP{!D!i1^^+7=0XDkui$h|9|d1H#cc}tB2<1{Lla6 z_y4;86FSPqTPdLj>A_~|f{ly12(c4F91a_GQZMxm!WU^I#0H0-Z*OmdP$O+bX>WzJ z!(J&b6y8++yPGz0_4;dT`vDpd{*d3l{s>$mB$8eSx2*L{aiGdJeBRVAE)NQCC%=zB z<~R@l7RG?<&2iSw5E59klsDmYhHr2Evi8rJKMuLR{p|KT)_TY2F_GsQ@NFuc%jI#i zlrQ8`mWW5_5uxe8uxxhhrtR03N~ZF34xrXP={AK$&K^~cxuI$GWr<_b>k4TK31~U% zwEG(EKE+1hW21JTY=2j^I|)B@;``uJocL-~v+!L37QO}5EbMY%VZ&FkB+<-1MH2m8 zCE`T4L7TU5l{Q{@1s)ARd&?XVTEYXmRA^YVNZP$0}He`Vcn+Q zvjGN9C3wP!LX0wHf$>!nmE{Kq_P}Th8yKs0^=H+?yu0wrc_m^iR?DSs&fMrb1@~H*p6U4l8koNA(9q)M~u1$yfo5LT0Sa9^> zFeJR%d(`A9+I?}bDqlwXn~L(xsXlaShQac_hBwggtwVbmHdW$rjrv86Zg_ipU&F7_ z@VYQ8vTt~7O8=@$-Qb3e3jr zrUqq!@jYU!dG+kLbqpSaHcN~i+N@Q7tc4yDx0YgDW!OVIPc1;#5cHK-56oi*)#eok zEy*QyLsB0~SQ70rRJ6NsH`8(x|D8eP=al;8Ck^x@Z_oid1`^XinuQu^?C?g^Ncr8?|9Vb^?)jVB`A{k>42y^ zPc2Y?Le%?*0agClBfC@yzTg7!`4tZvA0L@Gsa@O3J$DPP&P+FBYz#iQ&NH^eVi`7o zNAS&9l%E3$G-Lfp!IAjZ`O!S6u|77$*a(Wn@(gq*QLK9m=>*72nOC z$QNjREbQs|(*2oA^<4liV>7$xM=_E5${>FU&Q3zUr@Nr&JPDdUXp9YUdPVrF$8XY~Nw!_gCeiQi zX>6J};+)gKP@mI4_VIdT@S87@4d^FPkIThmxEGVkE{uK%^}rp|5`x{tn;@FT*5poc zHuj~i-*$06IX4y_20F8+eryEwd6Vw0zcK_d7WdYFAN6???ykQ)4En&Iz~<}Duu*(p zVD%#nt13VJmHFX$f+})R{wU{1i;uq#=SRT_Ek8mZ@`E_h8T7B5AI;Mk9%%J8a>RP! z9n$M9io(YFdA?`S{&m9%y;d`5pZ9xWq9Zi4f?14>As$DGLg0M$#CZP*FEkKd#2Ky& zAU{AI0QJWO77|#5#H5`@jHrIY$xLNk z)t^fGbIFd|+P^!{2xA9R8Q(GJBSYP)Vap1TH_|$)1@8w*|0vl%BzsFTS&Lq4+kxIQ zMdKpVmaK2f_E(>M+h;Nlz2v#$yeo-Cgp%*F{zbMQs`hq=$qv;q|IuOX)#<;F=&G&h z_cUUd>^RS6FU_5IdXGK!ox!nQOmNPp;fG_A^BPYS`55O#o-7Jm0vx7rm*o5cu5fl& zIALfqj`jjhDM6LO?Lr3lYp|Kl3!@0yPX#<^9nW5w-TJlrF^0qCU8v3A`s5(|8%qNKJ^M zg(ueG4lFWJT9})PITlf$sMB#Rq1o9Ahv8wutV*tW?RsIYH(#mr=Bm|l&AL&jt}d5X Ytbu4>q%UHmO+xk`G6$bu2L59H0O8>4IsgCw diff --git a/src/extension/arrow-ext/tests/fixtures/deeply_nested.parquet b/src/extension/arrow-ext/tests/fixtures/deeply_nested.parquet deleted file mode 100644 index 99b577527ed8cf4ec641f37dbb4a334c399a20c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1161 zcmZuxOK;Oa5T2}ED^xkO6|?dp3sn`hibzWeP1T}SXwx(e&_dD!eO!HTGNaRpa)(LATZT!^2<1=jjp`=iuCsc)mJur~$Kt%c3AwL0Kwdx6>F1SR&;6NT? zSpp~-@ZlzdRXPC*^{JYRlB9F_CT*O=)TMx;@V#czIq#+@(A(W0T+#L2v(vO^qwZ-h zZlMd9n+M-*N3D1sb_0e{X4>c^@z_js=Y?-_L3%1s`49rksUmn&s@hjHDh6YC5oA_= z&d?`3470(iSg^zB&t`fWRGy|zeE^v$avL)EYe*n}I(SEZ6IcOObFJFRe`@`*NAjdR z*;l^FgkLhjXu$q(>e5{pj(v1HuB!Y0J`a$;9F+36z+;eKh4jKKIr^ojz|ZOZ{Z|K1 z?Bno%I1hOhbV+Mnr!TJ;T3_m|rhd*>Yu*T9=K9inZ+b^%ohN-tqJqEv1W@wYmj)@QPdk5xhq>p&pH2PXs zOg}5Sd}-?<9>Zty4Jo6yx2%3smrebtt68zt}0?_Bm0ZQ$XDs43w19oYGX>1%e)wMx3HMS{W z16jCL)CcebL{-#vmR;l#vgjhJy6B>dE~>8j2wmiybAKQ%$_VD?ob!F>XU+&Js+tzM zNQqQg7=q0)rZI1De~tL7V8Rq;0<3Pr*I7xDWz9RT8vxRVgGAp)ck z0|_JF2k?0@Uj~-I^AM3EK+cJ|NnePGY7q{m3t}Na%z_xlytlCT;ughX5Gdx>Nz?oh z&6yxp^PN~Z#kvy2I#H#D@A0+2Cj7F!kLL^GvFEsLnZ7xLZCGG#OU6j8xwfSp2oUJD zW9W8)b7uIeA*e>E;&&acdqOiP1ki=Gc-Mq?(zeAr8A1Xnx7R{WGsp(uVIl}8y8=`Q zoX6#3u>t|&?v*C;7^@`tOD;a96GRi2&m(lg?UnAE#qjhZN+$*p{91~+-R{}oo8G}u z^TZVxPY&#cICbL6XuG9Ay!OhY!Dm)!YJi?8uzZDeV~spL9!9+S^*0PP=!SRq=!GGkh=@66AmrytlUJJaBI^9ELz=-uvclJeY5re2EsneRKD~Fx zKJ^}v^=~wZV|2K#l-huwL#grrO<_zN-+qux z-p?j4lF1UD!M{Hq?$d@`WpPXP<)>huJVSeOk|RFQZmbv3Xe*C=xbudWSrHG7lR~di z+kFc0ZX=%T$Nma=9|FrJmWF~X_S?-pFZ>*aR@^;rl(sr`kmZoOlpF15a=@untpcDS z#UJLIuTgvydIgOXo^#vC|B&oS_=IMhjws+`)O(?$kTUiC)sOZ|yKR)#2~SpmKd=ew zr%q8nKvk|=-#hl|S4_7X#lrEEz3LHis7HA)%98&u|Lvj2htyQx{0_zgQS9L5=MNR6 zLVh>>{45_fX3|YIhJ!T3RDv-y9*7Bg@!)|N{y@bhG~q*wav~o5RsIZq zi3g9KoE8cfHoN;KvorJF%#ManS7cLb2sp%|)#La77`(xiV zMN4R8Fd<$szGouV&q*XW6Q z1L+I=RU*URibC+O#g6X^G=YwOjncP|`28|nwbpUEN|uXO|E7E0?diY(vOzN8k^J*N D+dMw2 diff --git a/src/extension/arrow-ext/tests/phpt/001_extension_loaded.phpt b/src/extension/arrow-ext/tests/phpt/001_extension_loaded.phpt index 8eaf6e756c..df5261568f 100644 --- a/src/extension/arrow-ext/tests/phpt/001_extension_loaded.phpt +++ b/src/extension/arrow-ext/tests/phpt/001_extension_loaded.phpt @@ -1,14 +1,38 @@ --TEST-- -arrow extension is loaded and classes are registered +arrow extension is loaded and the Parquet and Arrow C Data classes are registered --SKIPIF-- --FILE-- isInternal() ? 'internal' : 'userland', ', ', $r->isFinal() ? 'final' : 'open', "\n"; +} + +foreach (['Flow\Arrow\Parquet\Reader', 'Flow\Arrow\Parquet\Writer', 'Flow\Arrow\Parquet\Exception'] as $class) { + var_dump(class_exists($class, false)); +} + +foreach (['Flow\Arrow\ArrowBatch', 'Flow\Arrow\ArrowSchema'] as $class) { + try { + new $class(); + } catch (Throwable $e) { + echo $class, ': ', $e->getMessage(), "\n"; + } +} ?> --EXPECT-- bool(true) -bool(true) -bool(true) +Flow\Arrow\Parquet\ParquetFile: internal, final +Flow\Arrow\Parquet\ColumnsReader: internal, final +Flow\Arrow\Parquet\RowsWriter: internal, final +Flow\Arrow\Parquet\BatchReader: internal, final +Flow\Arrow\ArrowBatch: internal, final +Flow\Arrow\ArrowSchema: internal, final +bool(false) +bool(false) +bool(false) +Flow\Arrow\ArrowBatch: You cannot instantiate this class from PHP. +Flow\Arrow\ArrowSchema: You cannot instantiate this class from PHP. diff --git a/src/extension/arrow-ext/tests/phpt/002_reader_construct.phpt b/src/extension/arrow-ext/tests/phpt/002_reader_construct.phpt deleted file mode 100644 index 9c13a05cdd..0000000000 --- a/src/extension/arrow-ext/tests/phpt/002_reader_construct.phpt +++ /dev/null @@ -1,35 +0,0 @@ ---TEST-- -Reader constructor opens a Parquet file ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/simple.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -echo "Reader created\n"; -$reader->close(); -echo "Reader closed\n"; -?> ---EXPECT-- -Reader created -Reader closed diff --git a/src/extension/arrow-ext/tests/phpt/003_reader_null_size.phpt b/src/extension/arrow-ext/tests/phpt/003_reader_null_size.phpt deleted file mode 100644 index 6923332331..0000000000 --- a/src/extension/arrow-ext/tests/phpt/003_reader_null_size.phpt +++ /dev/null @@ -1,35 +0,0 @@ ---TEST-- -Reader constructor throws exception when size() returns null ---SKIPIF-- - ---FILE-- -getMessage(), 'null')); -} catch (\Exception $e) { - echo "Caught Exception\n"; - var_dump(str_contains($e->getMessage(), 'null')); -} -?> ---EXPECT-- -Caught Flow\Arrow\Parquet\Exception -bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/004_reader_schema.phpt b/src/extension/arrow-ext/tests/phpt/004_reader_schema.phpt deleted file mode 100644 index 53ff6b36c8..0000000000 --- a/src/extension/arrow-ext/tests/phpt/004_reader_schema.phpt +++ /dev/null @@ -1,47 +0,0 @@ ---TEST-- -Reader schema returns column descriptors ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/simple.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$schema = $reader->schema(); - -var_dump(count($schema)); -var_dump($schema[0]['name']); -var_dump($schema[0]['type']); -var_dump($schema[0]['optional']); -var_dump($schema[1]['name']); -var_dump($schema[1]['type']); -var_dump($schema[1]['optional']); -$reader->close(); -?> ---EXPECT-- -int(2) -string(2) "id" -string(5) "INT64" -bool(false) -string(4) "name" -string(6) "STRING" -bool(false) diff --git a/src/extension/arrow-ext/tests/phpt/005_reader_metadata.phpt b/src/extension/arrow-ext/tests/phpt/005_reader_metadata.phpt deleted file mode 100644 index fbfa6549ff..0000000000 --- a/src/extension/arrow-ext/tests/phpt/005_reader_metadata.phpt +++ /dev/null @@ -1,41 +0,0 @@ ---TEST-- -Reader metadata returns file info ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/simple.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$meta = $reader->metadata(); - -var_dump($meta['rows']); -var_dump($meta['row_groups']); -var_dump(is_string($meta['created_by'])); -var_dump(is_array($meta['metadata'])); -$reader->close(); -?> ---EXPECT-- -int(3) -int(1) -bool(true) -bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/006_reader_flat_columns.phpt b/src/extension/arrow-ext/tests/phpt/006_reader_flat_columns.phpt deleted file mode 100644 index 8d626a541e..0000000000 --- a/src/extension/arrow-ext/tests/phpt/006_reader_flat_columns.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -Reader reads flat columns from simple.parquet ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/simple.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$data = $reader->readRowGroup(); - -var_dump($data['id']); -var_dump($data['name']); -$reader->close(); -?> ---EXPECT-- -array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) -} -array(3) { - [0]=> - string(5) "Alice" - [1]=> - string(3) "Bob" - [2]=> - string(7) "Charlie" -} diff --git a/src/extension/arrow-ext/tests/phpt/007_reader_all_flat_types.phpt b/src/extension/arrow-ext/tests/phpt/007_reader_all_flat_types.phpt deleted file mode 100644 index e14c36ccba..0000000000 --- a/src/extension/arrow-ext/tests/phpt/007_reader_all_flat_types.phpt +++ /dev/null @@ -1,106 +0,0 @@ ---TEST-- -Reader converts all flat Arrow types correctly ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/all_flat_types.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$data = $reader->readRowGroup(); - -// Boolean -echo "bool: "; -var_dump($data['col_bool'][0] === true && $data['col_bool'][1] === false && $data['col_bool'][2] === null); - -// Integers -echo "int8: "; -var_dump($data['col_int8'][0] === 1 && $data['col_int8'][1] === -128 && $data['col_int8'][2] === null); - -echo "int16: "; -var_dump($data['col_int16'][0] === 256 && $data['col_int16'][1] === -32768 && $data['col_int16'][2] === null); - -echo "int32: "; -var_dump($data['col_int32'][0] === 100000 && $data['col_int32'][1] === -100000 && $data['col_int32'][2] === null); - -echo "int64: "; -var_dump($data['col_int64'][0] === 1000000000 && $data['col_int64'][1] === -1000000000 && $data['col_int64'][2] === null); - -// Unsigned integers -echo "uint8: "; -var_dump($data['col_uint8'][0] === 0 && $data['col_uint8'][1] === 255 && $data['col_uint8'][2] === null); - -echo "uint16: "; -var_dump($data['col_uint16'][0] === 0 && $data['col_uint16'][1] === 65535 && $data['col_uint16'][2] === null); - -echo "uint32: "; -var_dump($data['col_uint32'][0] === 0 && $data['col_uint32'][1] === 4294967295 && $data['col_uint32'][2] === null); - -echo "uint64: "; -var_dump($data['col_uint64'][0] === 0 && $data['col_uint64'][1] === "18446744073709551615" && $data['col_uint64'][2] === null); - -// Floats -echo "float: "; -var_dump(is_float($data['col_float'][0]) && is_float($data['col_float'][1]) && $data['col_float'][2] === null); - -echo "double: "; -var_dump($data['col_double'][0] === 1.23456 && $data['col_double'][1] === -7.89012 && $data['col_double'][2] === null); - -// String -echo "string: "; -var_dump($data['col_string'][0] === "hello" && $data['col_string'][1] === "world" && $data['col_string'][2] === null); - -// Binary -echo "binary: "; -var_dump($data['col_binary'][0] === "\x00\x01\x02" && $data['col_binary'][1] === "\xff\xfe" && $data['col_binary'][2] === null); - -// Date (19000 days since epoch = 2021-12-24) -echo "date: "; -var_dump($data['col_date'][0] instanceof DateTimeImmutable && $data['col_date'][0]->getTimestamp() === 1641600000 && $data['col_date'][1] instanceof DateTimeImmutable && $data['col_date'][1]->getTimestamp() === 0 && $data['col_date'][2] === null); - -// Timestamp (1700000000000000 microseconds = 2023-11-14T22:13:20) -echo "timestamp: "; -var_dump($data['col_timestamp'][0] instanceof DateTimeImmutable && $data['col_timestamp'][0]->getTimestamp() === 1700000000 && $data['col_timestamp'][1] instanceof DateTimeImmutable && $data['col_timestamp'][1]->getTimestamp() === 0 && $data['col_timestamp'][2] === null); - -// Decimal (string representation) -echo "decimal: "; -var_dump($data['col_decimal'][0] === 123.45 && $data['col_decimal'][1] === -999.99 && $data['col_decimal'][2] === null); - -$reader->close(); -?> ---EXPECT-- -bool: bool(true) -int8: bool(true) -int16: bool(true) -int32: bool(true) -int64: bool(true) -uint8: bool(true) -uint16: bool(true) -uint32: bool(true) -uint64: bool(true) -float: bool(true) -double: bool(true) -string: bool(true) -binary: bool(true) -date: bool(true) -timestamp: bool(true) -decimal: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/008_reader_column_projection.phpt b/src/extension/arrow-ext/tests/phpt/008_reader_column_projection.phpt deleted file mode 100644 index 33732a94fb..0000000000 --- a/src/extension/arrow-ext/tests/phpt/008_reader_column_projection.phpt +++ /dev/null @@ -1,56 +0,0 @@ ---TEST-- -Reader returns only selected columns with projection ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/simple.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$data = $reader->readRowGroup(['name']); - -echo "column count: "; -var_dump(count($data)); - -echo "has name: "; -var_dump(array_key_exists('name', $data)); - -echo "has id: "; -var_dump(array_key_exists('id', $data)); - -echo "name values: "; -var_dump($data['name']); - -$reader->close(); -?> ---EXPECT-- -column count: int(1) -has name: bool(true) -has id: bool(false) -name values: array(3) { - [0]=> - string(5) "Alice" - [1]=> - string(3) "Bob" - [2]=> - string(7) "Charlie" -} diff --git a/src/extension/arrow-ext/tests/phpt/009_reader_exhausted.phpt b/src/extension/arrow-ext/tests/phpt/009_reader_exhausted.phpt deleted file mode 100644 index 21d4db9781..0000000000 --- a/src/extension/arrow-ext/tests/phpt/009_reader_exhausted.phpt +++ /dev/null @@ -1,47 +0,0 @@ ---TEST-- -Reader returns null when all row groups are consumed ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/simple.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); - -$rg1 = $reader->readRowGroup(); -echo "first: "; -var_dump(is_array($rg1)); - -$rg2 = $reader->readRowGroup(); -echo "second: "; -var_dump($rg2); - -$rg3 = $reader->readRowGroup(); -echo "third: "; -var_dump($rg3); - -$reader->close(); -?> ---EXPECT-- -first: bool(true) -second: NULL -third: NULL diff --git a/src/extension/arrow-ext/tests/phpt/010_reader_list.phpt b/src/extension/arrow-ext/tests/phpt/010_reader_list.phpt deleted file mode 100644 index 0f1291bdc5..0000000000 --- a/src/extension/arrow-ext/tests/phpt/010_reader_list.phpt +++ /dev/null @@ -1,57 +0,0 @@ ---TEST-- -Reader reads LIST columns from nested.parquet ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/nested.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$data = $reader->readRowGroup(); - -// Row 0: ["a", "b", "c"] -echo "row0 is array: "; -var_dump(is_array($data['tags'][0])); -echo "row0 count: "; -var_dump(count($data['tags'][0])); -echo "row0 values: "; -var_dump($data['tags'][0][0] === "a" && $data['tags'][0][1] === "b" && $data['tags'][0][2] === "c"); - -// Row 1: [] (empty list) -echo "row1 is array: "; -var_dump(is_array($data['tags'][1])); -echo "row1 count: "; -var_dump(count($data['tags'][1])); - -// Row 2: null -echo "row2 is null: "; -var_dump($data['tags'][2] === null); - -$reader->close(); -?> ---EXPECT-- -row0 is array: bool(true) -row0 count: int(3) -row0 values: bool(true) -row1 is array: bool(true) -row1 count: int(0) -row2 is null: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/011_reader_struct.phpt b/src/extension/arrow-ext/tests/phpt/011_reader_struct.phpt deleted file mode 100644 index c2ac1fa15b..0000000000 --- a/src/extension/arrow-ext/tests/phpt/011_reader_struct.phpt +++ /dev/null @@ -1,57 +0,0 @@ ---TEST-- -Reader reads STRUCT columns from nested.parquet ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/nested.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$data = $reader->readRowGroup(); - -// Row 0: {key: "x", value: 10} -echo "row0 is array: "; -var_dump(is_array($data['metadata'][0])); -echo "row0 key: "; -var_dump($data['metadata'][0]['key']); -echo "row0 value: "; -var_dump($data['metadata'][0]['value']); - -// Row 1: null -echo "row1 is null: "; -var_dump($data['metadata'][1] === null); - -// Row 2: {key: "y", value: 20} -echo "row2 key: "; -var_dump($data['metadata'][2]['key']); -echo "row2 value: "; -var_dump($data['metadata'][2]['value']); - -$reader->close(); -?> ---EXPECT-- -row0 is array: bool(true) -row0 key: string(1) "x" -row0 value: int(10) -row1 is null: bool(true) -row2 key: string(1) "y" -row2 value: int(20) diff --git a/src/extension/arrow-ext/tests/phpt/012_reader_map.phpt b/src/extension/arrow-ext/tests/phpt/012_reader_map.phpt deleted file mode 100644 index d8189f8064..0000000000 --- a/src/extension/arrow-ext/tests/phpt/012_reader_map.phpt +++ /dev/null @@ -1,54 +0,0 @@ ---TEST-- -Reader reads MAP columns from nested.parquet ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/nested.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$data = $reader->readRowGroup(); - -// Row 0: {"p1": 100, "p2": 200} -echo "row0 is array: "; -var_dump(is_array($data['props'][0])); -echo "row0 p1: "; -var_dump($data['props'][0]['p1']); -echo "row0 p2: "; -var_dump($data['props'][0]['p2']); - -// Row 1: {"p3": 300} -echo "row1 p3: "; -var_dump($data['props'][1]['p3']); - -// Row 2: null -echo "row2 is null: "; -var_dump($data['props'][2] === null); - -$reader->close(); -?> ---EXPECT-- -row0 is array: bool(true) -row0 p1: int(100) -row0 p2: int(200) -row1 p3: int(300) -row2 is null: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/013_reader_deeply_nested.phpt b/src/extension/arrow-ext/tests/phpt/013_reader_deeply_nested.phpt deleted file mode 100644 index 95bb994c5e..0000000000 --- a/src/extension/arrow-ext/tests/phpt/013_reader_deeply_nested.phpt +++ /dev/null @@ -1,66 +0,0 @@ ---TEST-- -Reader reads deeply nested columns from deeply_nested.parquet ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/deeply_nested.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$data = $reader->readRowGroup(); - -// Row 0: [{name:"alpha", scores:[10,20]}, {name:"beta", scores:[30]}] -echo "row0 count: "; -var_dump(count($data['groups'][0])); -echo "row0[0] name: "; -var_dump($data['groups'][0][0]['name']); -echo "row0[0] scores: "; -var_dump($data['groups'][0][0]['scores'][0] === 10 && $data['groups'][0][0]['scores'][1] === 20); -echo "row0[1] name: "; -var_dump($data['groups'][0][1]['name']); -echo "row0[1] scores: "; -var_dump($data['groups'][0][1]['scores'][0] === 30); - -// Row 1: [{name:"gamma", scores:[]}] -echo "row1 count: "; -var_dump(count($data['groups'][1])); -echo "row1[0] name: "; -var_dump($data['groups'][1][0]['name']); -echo "row1[0] scores count: "; -var_dump(count($data['groups'][1][0]['scores'])); - -// Row 2: null -echo "row2 is null: "; -var_dump($data['groups'][2] === null); - -$reader->close(); -?> ---EXPECT-- -row0 count: int(2) -row0[0] name: string(5) "alpha" -row0[0] scores: bool(true) -row0[1] name: string(4) "beta" -row0[1] scores: bool(true) -row1 count: int(1) -row1[0] name: string(5) "gamma" -row1[0] scores count: int(0) -row2 is null: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/014_reader_null_nested.phpt b/src/extension/arrow-ext/tests/phpt/014_reader_null_nested.phpt deleted file mode 100644 index 0c80e70b3c..0000000000 --- a/src/extension/arrow-ext/tests/phpt/014_reader_null_nested.phpt +++ /dev/null @@ -1,62 +0,0 @@ ---TEST-- -Reader propagates nulls correctly in nested columns ---SKIPIF-- - ---FILE-- -data = file_get_contents($filePath); - } - - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - - public function size(): ?int { - return strlen($this->data); - } -} - -$stream = new TestSourceStream(__DIR__ . '/../fixtures/nested.parquet'); -$reader = new Flow\Arrow\Parquet\Reader($stream); -$data = $reader->readRowGroup(); - -// null list (row 2 tags) is PHP null, NOT empty array -echo "null list is null: "; -var_dump($data['tags'][2] === null); -echo "null list is not array: "; -var_dump(!is_array($data['tags'][2])); - -// empty list (row 1 tags) is PHP empty array, NOT null -echo "empty list is array: "; -var_dump(is_array($data['tags'][1])); -echo "empty list is not null: "; -var_dump($data['tags'][1] !== null); -echo "empty list count: "; -var_dump(count($data['tags'][1])); - -// null struct (row 1 metadata) is PHP null -echo "null struct is null: "; -var_dump($data['metadata'][1] === null); - -// null map (row 2 props) is PHP null -echo "null map is null: "; -var_dump($data['props'][2] === null); - -$reader->close(); -?> ---EXPECT-- -null list is null: bool(true) -null list is not array: bool(true) -empty list is array: bool(true) -empty list is not null: bool(true) -empty list count: int(0) -null struct is null: bool(true) -null map is null: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/015_writer_construct.phpt b/src/extension/arrow-ext/tests/phpt/015_writer_construct.phpt deleted file mode 100644 index 0ad24dcbc6..0000000000 --- a/src/extension/arrow-ext/tests/phpt/015_writer_construct.phpt +++ /dev/null @@ -1,44 +0,0 @@ ---TEST-- -Writer constructs, writes a minimal batch, and produces valid Parquet ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema); -$writer->writeBatch([ - 'id' => [1, 2, 3], -]); -$writer->close(); - -// Parquet files start and end with magic bytes "PAR1" -$magic = substr($dest->data, 0, 4); -$footer = substr($dest->data, -4); - -echo "starts_with_PAR1: "; -var_dump($magic === "PAR1"); -echo "ends_with_PAR1: "; -var_dump($footer === "PAR1"); -echo "size_gt_zero: "; -var_dump(strlen($dest->data) > 0); -?> ---EXPECT-- -starts_with_PAR1: bool(true) -ends_with_PAR1: bool(true) -size_gt_zero: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/016_writer_flat_columns.phpt b/src/extension/arrow-ext/tests/phpt/016_writer_flat_columns.phpt deleted file mode 100644 index 0306249dba..0000000000 --- a/src/extension/arrow-ext/tests/phpt/016_writer_flat_columns.phpt +++ /dev/null @@ -1,71 +0,0 @@ ---TEST-- -Writer writes INT64+STRING columns and Reader reads them back ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => false], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'id' => [1, 2, 3], - 'name' => ['Alice', 'Bob', 'Charlie'], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -var_dump($data['id']); -var_dump($data['name']); - -$reader->close(); -?> ---EXPECT-- -array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) -} -array(3) { - [0]=> - string(5) "Alice" - [1]=> - string(3) "Bob" - [2]=> - string(7) "Charlie" -} diff --git a/src/extension/arrow-ext/tests/phpt/017_writer_roundtrip.phpt b/src/extension/arrow-ext/tests/phpt/017_writer_roundtrip.phpt deleted file mode 100644 index 84b221e8eb..0000000000 --- a/src/extension/arrow-ext/tests/phpt/017_writer_roundtrip.phpt +++ /dev/null @@ -1,144 +0,0 @@ ---TEST-- -Writer roundtrips all 16 flat types through Writer then Reader ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'col_bool', 'type' => 'BOOLEAN', 'optional' => true], - ['name' => 'col_int8', 'type' => 'INT8', 'optional' => true], - ['name' => 'col_int16', 'type' => 'INT16', 'optional' => true], - ['name' => 'col_int32', 'type' => 'INT32', 'optional' => true], - ['name' => 'col_int64', 'type' => 'INT64', 'optional' => true], - ['name' => 'col_uint8', 'type' => 'UINT8', 'optional' => true], - ['name' => 'col_uint16', 'type' => 'UINT16', 'optional' => true], - ['name' => 'col_uint32', 'type' => 'UINT32', 'optional' => true], - ['name' => 'col_uint64', 'type' => 'UINT64', 'optional' => true], - ['name' => 'col_float', 'type' => 'FLOAT', 'optional' => true], - ['name' => 'col_double', 'type' => 'DOUBLE', 'optional' => true], - ['name' => 'col_string', 'type' => 'STRING', 'optional' => true], - ['name' => 'col_binary', 'type' => 'BINARY', 'optional' => true], - ['name' => 'col_date', 'type' => 'DATE', 'optional' => true], - ['name' => 'col_timestamp', 'type' => 'TIMESTAMP', 'optional' => true], - ['name' => 'col_decimal', 'type' => 'DECIMAL', 'optional' => true, 'precision' => 10, 'scale' => 2], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'col_bool' => [true, false, null], - 'col_int8' => [1, -128, null], - 'col_int16' => [256, -32768, null], - 'col_int32' => [100000, -100000, null], - 'col_int64' => [1000000000, -1000000000, null], - 'col_uint8' => [0, 255, null], - 'col_uint16' => [0, 65535, null], - 'col_uint32' => [0, 4294967295, null], - 'col_uint64' => [0, "18446744073709551615", null], - 'col_float' => [1.5, -2.5, null], - 'col_double' => [3.14159, -2.71828, null], - 'col_string' => ['hello', 'world', null], - 'col_binary' => ["\x00\x01\x02", "\xff\xfe", null], - 'col_date' => [19000, 0, null], - 'col_timestamp' => [1700000000000000, 0, null], - 'col_decimal' => ['123.45', '-999.99', null], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -echo "bool: "; -var_dump($data['col_bool'][0] === true && $data['col_bool'][1] === false && $data['col_bool'][2] === null); - -echo "int8: "; -var_dump($data['col_int8'][0] === 1 && $data['col_int8'][1] === -128 && $data['col_int8'][2] === null); - -echo "int16: "; -var_dump($data['col_int16'][0] === 256 && $data['col_int16'][1] === -32768 && $data['col_int16'][2] === null); - -echo "int32: "; -var_dump($data['col_int32'][0] === 100000 && $data['col_int32'][1] === -100000 && $data['col_int32'][2] === null); - -echo "int64: "; -var_dump($data['col_int64'][0] === 1000000000 && $data['col_int64'][1] === -1000000000 && $data['col_int64'][2] === null); - -echo "uint8: "; -var_dump($data['col_uint8'][0] === 0 && $data['col_uint8'][1] === 255 && $data['col_uint8'][2] === null); - -echo "uint16: "; -var_dump($data['col_uint16'][0] === 0 && $data['col_uint16'][1] === 65535 && $data['col_uint16'][2] === null); - -echo "uint32: "; -var_dump($data['col_uint32'][0] === 0 && $data['col_uint32'][1] === 4294967295 && $data['col_uint32'][2] === null); - -echo "uint64: "; -var_dump($data['col_uint64'][0] === 0 && $data['col_uint64'][1] === "18446744073709551615" && $data['col_uint64'][2] === null); - -echo "float: "; -var_dump(is_float($data['col_float'][0]) && is_float($data['col_float'][1]) && $data['col_float'][2] === null); - -echo "double: "; -var_dump($data['col_double'][0] === 3.14159 && $data['col_double'][1] === -2.71828 && $data['col_double'][2] === null); - -echo "string: "; -var_dump($data['col_string'][0] === "hello" && $data['col_string'][1] === "world" && $data['col_string'][2] === null); - -echo "binary: "; -var_dump($data['col_binary'][0] === "\x00\x01\x02" && $data['col_binary'][1] === "\xff\xfe" && $data['col_binary'][2] === null); - -echo "date: "; -var_dump($data['col_date'][0] instanceof DateTimeImmutable && $data['col_date'][0]->getTimestamp() === 1641600000 && $data['col_date'][1] instanceof DateTimeImmutable && $data['col_date'][1]->getTimestamp() === 0 && $data['col_date'][2] === null); - -echo "timestamp: "; -var_dump($data['col_timestamp'][0] instanceof DateTimeImmutable && $data['col_timestamp'][0]->getTimestamp() === 1700000000 && $data['col_timestamp'][1] instanceof DateTimeImmutable && $data['col_timestamp'][1]->getTimestamp() === 0 && $data['col_timestamp'][2] === null); - -echo "decimal: "; -var_dump($data['col_decimal'][0] === 123.45 && $data['col_decimal'][1] === -999.99 && $data['col_decimal'][2] === null); - -$reader->close(); -?> ---EXPECT-- -bool: bool(true) -int8: bool(true) -int16: bool(true) -int32: bool(true) -int64: bool(true) -uint8: bool(true) -uint16: bool(true) -uint32: bool(true) -uint64: bool(true) -float: bool(true) -double: bool(true) -string: bool(true) -binary: bool(true) -date: bool(true) -timestamp: bool(true) -decimal: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/018_writer_compression.phpt b/src/extension/arrow-ext/tests/phpt/018_writer_compression.phpt deleted file mode 100644 index a1b809aff9..0000000000 --- a/src/extension/arrow-ext/tests/phpt/018_writer_compression.phpt +++ /dev/null @@ -1,87 +0,0 @@ ---TEST-- -Writer supports all compression codecs and defaults to SNAPPY ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => false], -]; -$batch = [ - 'id' => [1, 2, 3], - 'name' => ['Alice', 'Bob', 'Charlie'], -]; - -$codecs = ['UNCOMPRESSED', 'SNAPPY', 'GZIP', 'ZSTD', 'LZ4', 'BROTLI']; - -foreach ($codecs as $codec) { - $dest = new TestDestinationStream(); - $writer = new Flow\Arrow\Parquet\Writer($dest, $schema, $codec); - $writer->writeBatch($batch); - $writer->close(); - - $source = new TestSourceStream($dest->data); - $reader = new Flow\Arrow\Parquet\Reader($source); - $data = $reader->readRowGroup(); - - $ok = $data['id'][0] === 1 - && $data['id'][1] === 2 - && $data['id'][2] === 3 - && $data['name'][0] === 'Alice' - && $data['name'][1] === 'Bob' - && $data['name'][2] === 'Charlie'; - - echo "$codec: "; - var_dump($ok); - $reader->close(); -} - -// Default compression (no arg) should also work (SNAPPY) -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema); -$writer->writeBatch($batch); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -echo "DEFAULT: "; -var_dump($data['id'][0] === 1 && $data['name'][2] === 'Charlie'); -$reader->close(); -?> ---EXPECT-- -UNCOMPRESSED: bool(true) -SNAPPY: bool(true) -GZIP: bool(true) -ZSTD: bool(true) -LZ4: bool(true) -BROTLI: bool(true) -DEFAULT: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/019_writer_null_values.phpt b/src/extension/arrow-ext/tests/phpt/019_writer_null_values.phpt deleted file mode 100644 index 64c612e23f..0000000000 --- a/src/extension/arrow-ext/tests/phpt/019_writer_null_values.phpt +++ /dev/null @@ -1,108 +0,0 @@ ---TEST-- -Writer preserves null values for multiple column types ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'col_int64', 'type' => 'INT64', 'optional' => true], - ['name' => 'col_string', 'type' => 'STRING', 'optional' => true], - ['name' => 'col_bool', 'type' => 'BOOLEAN', 'optional' => true], - ['name' => 'col_double', 'type' => 'DOUBLE', 'optional' => true], - ['name' => 'col_decimal', 'type' => 'DECIMAL', 'optional' => true, 'precision' => 10, 'scale' => 2], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'col_int64' => [null, 42, null, 99, null], - 'col_string' => ['hello', null, null, 'world', null], - 'col_bool' => [true, null, false, null, null], - 'col_double' => [null, null, 3.14, null, 2.71], - 'col_decimal' => ['1.23', null, null, '-4.56', null], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -echo "int64: "; -var_dump( - $data['col_int64'][0] === null - && $data['col_int64'][1] === 42 - && $data['col_int64'][2] === null - && $data['col_int64'][3] === 99 - && $data['col_int64'][4] === null -); - -echo "string: "; -var_dump( - $data['col_string'][0] === 'hello' - && $data['col_string'][1] === null - && $data['col_string'][2] === null - && $data['col_string'][3] === 'world' - && $data['col_string'][4] === null -); - -echo "bool: "; -var_dump( - $data['col_bool'][0] === true - && $data['col_bool'][1] === null - && $data['col_bool'][2] === false - && $data['col_bool'][3] === null - && $data['col_bool'][4] === null -); - -echo "double: "; -var_dump( - $data['col_double'][0] === null - && $data['col_double'][1] === null - && $data['col_double'][2] === 3.14 - && $data['col_double'][3] === null - && $data['col_double'][4] === 2.71 -); - -echo "decimal: "; -var_dump( - $data['col_decimal'][0] === 1.23 - && $data['col_decimal'][1] === null - && $data['col_decimal'][2] === null - && $data['col_decimal'][3] === -4.56 - && $data['col_decimal'][4] === null -); - -$reader->close(); -?> ---EXPECT-- -int64: bool(true) -string: bool(true) -bool: bool(true) -double: bool(true) -decimal: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/020_writer_list.phpt b/src/extension/arrow-ext/tests/phpt/020_writer_list.phpt deleted file mode 100644 index b9b69775ac..0000000000 --- a/src/extension/arrow-ext/tests/phpt/020_writer_list.phpt +++ /dev/null @@ -1,83 +0,0 @@ ---TEST-- -Writer roundtrips LIST(STRING) columns through Writer then Reader ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'tags', 'type' => 'LIST', 'optional' => true, 'children' => [ - ['name' => 'item', 'type' => 'STRING', 'optional' => true] - ]], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'id' => [1, 2, 3], - 'tags' => [["a", "b", "c"], [], null], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -// Row 0: ["a", "b", "c"] -echo "row0 is array: "; -var_dump(is_array($data['tags'][0])); -echo "row0 count: "; -var_dump(count($data['tags'][0])); -echo "row0 values: "; -var_dump($data['tags'][0][0] === "a" && $data['tags'][0][1] === "b" && $data['tags'][0][2] === "c"); - -// Row 1: [] (empty list) -echo "row1 is array: "; -var_dump(is_array($data['tags'][1])); -echo "row1 count: "; -var_dump(count($data['tags'][1])); - -// Row 2: null -echo "row2 is null: "; -var_dump($data['tags'][2] === null); - -// Verify id column -echo "ids: "; -var_dump($data['id'][0] === 1 && $data['id'][1] === 2 && $data['id'][2] === 3); - -$reader->close(); -?> ---EXPECT-- -row0 is array: bool(true) -row0 count: int(3) -row0 values: bool(true) -row1 is array: bool(true) -row1 count: int(0) -row2 is null: bool(true) -ids: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/021_writer_struct.phpt b/src/extension/arrow-ext/tests/phpt/021_writer_struct.phpt deleted file mode 100644 index 55aed2c1bc..0000000000 --- a/src/extension/arrow-ext/tests/phpt/021_writer_struct.phpt +++ /dev/null @@ -1,79 +0,0 @@ ---TEST-- -Writer roundtrips STRUCT columns through Writer then Reader ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'metadata', 'type' => 'STRUCT', 'optional' => true, 'children' => [ - ['name' => 'key', 'type' => 'STRING', 'optional' => false], - ['name' => 'value', 'type' => 'INT64', 'optional' => false], - ]], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'id' => [1, 2, 3], - 'metadata' => [['key' => 'x', 'value' => 10], null, ['key' => 'y', 'value' => 20]], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -// Row 0: {key: "x", value: 10} -echo "row0 is array: "; -var_dump(is_array($data['metadata'][0])); -echo "row0 key: "; -var_dump($data['metadata'][0]['key']); -echo "row0 value: "; -var_dump($data['metadata'][0]['value']); - -// Row 1: null -echo "row1 is null: "; -var_dump($data['metadata'][1] === null); - -// Row 2: {key: "y", value: 20} -echo "row2 key: "; -var_dump($data['metadata'][2]['key']); -echo "row2 value: "; -var_dump($data['metadata'][2]['value']); - -$reader->close(); -?> ---EXPECT-- -row0 is array: bool(true) -row0 key: string(1) "x" -row0 value: int(10) -row1 is null: bool(true) -row2 key: string(1) "y" -row2 value: int(20) diff --git a/src/extension/arrow-ext/tests/phpt/022_writer_map.phpt b/src/extension/arrow-ext/tests/phpt/022_writer_map.phpt deleted file mode 100644 index 080f20ec66..0000000000 --- a/src/extension/arrow-ext/tests/phpt/022_writer_map.phpt +++ /dev/null @@ -1,76 +0,0 @@ ---TEST-- -Writer roundtrips MAP(STRING, INT64) columns through Writer then Reader ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'props', 'type' => 'MAP', 'optional' => true, 'children' => [ - ['name' => 'keys', 'type' => 'STRING', 'optional' => false], - ['name' => 'values', 'type' => 'INT64', 'optional' => true], - ]], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'id' => [1, 2, 3], - 'props' => [['p1' => 100, 'p2' => 200], ['p3' => 300], null], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -// Row 0: {"p1": 100, "p2": 200} -echo "row0 is array: "; -var_dump(is_array($data['props'][0])); -echo "row0 p1: "; -var_dump($data['props'][0]['p1']); -echo "row0 p2: "; -var_dump($data['props'][0]['p2']); - -// Row 1: {"p3": 300} -echo "row1 p3: "; -var_dump($data['props'][1]['p3']); - -// Row 2: null -echo "row2 is null: "; -var_dump($data['props'][2] === null); - -$reader->close(); -?> ---EXPECT-- -row0 is array: bool(true) -row0 p1: int(100) -row0 p2: int(200) -row1 p3: int(300) -row2 is null: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/023_writer_deeply_nested.phpt b/src/extension/arrow-ext/tests/phpt/023_writer_deeply_nested.phpt deleted file mode 100644 index b1cc90682d..0000000000 --- a/src/extension/arrow-ext/tests/phpt/023_writer_deeply_nested.phpt +++ /dev/null @@ -1,97 +0,0 @@ ---TEST-- -Writer roundtrips deeply nested LIST(STRUCT(STRING, LIST(INT64))) through Writer then Reader ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'groups', 'type' => 'LIST', 'optional' => true, 'children' => [ - ['name' => 'item', 'type' => 'STRUCT', 'optional' => true, 'children' => [ - ['name' => 'name', 'type' => 'STRING', 'optional' => false], - ['name' => 'scores', 'type' => 'LIST', 'optional' => true, 'children' => [ - ['name' => 'item', 'type' => 'INT64', 'optional' => true] - ]], - ]], - ]], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'groups' => [ - // Row 0: [{name:"alpha", scores:[10,20]}, {name:"beta", scores:[30]}] - [['name' => 'alpha', 'scores' => [10, 20]], ['name' => 'beta', 'scores' => [30]]], - // Row 1: [{name:"gamma", scores:[]}] - [['name' => 'gamma', 'scores' => []]], - // Row 2: null - null, - ], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -// Row 0: [{name:"alpha", scores:[10,20]}, {name:"beta", scores:[30]}] -echo "row0 count: "; -var_dump(count($data['groups'][0])); -echo "row0[0] name: "; -var_dump($data['groups'][0][0]['name']); -echo "row0[0] scores: "; -var_dump($data['groups'][0][0]['scores'][0] === 10 && $data['groups'][0][0]['scores'][1] === 20); -echo "row0[1] name: "; -var_dump($data['groups'][0][1]['name']); -echo "row0[1] scores: "; -var_dump($data['groups'][0][1]['scores'][0] === 30); - -// Row 1: [{name:"gamma", scores:[]}] -echo "row1 count: "; -var_dump(count($data['groups'][1])); -echo "row1[0] name: "; -var_dump($data['groups'][1][0]['name']); -echo "row1[0] scores count: "; -var_dump(count($data['groups'][1][0]['scores'])); - -// Row 2: null -echo "row2 is null: "; -var_dump($data['groups'][2] === null); - -$reader->close(); -?> ---EXPECT-- -row0 count: int(2) -row0[0] name: string(5) "alpha" -row0[0] scores: bool(true) -row0[1] name: string(4) "beta" -row0[1] scores: bool(true) -row1 count: int(1) -row1[0] name: string(5) "gamma" -row1[0] scores count: int(0) -row2 is null: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/024_writer_roundtrip_all_types.phpt b/src/extension/arrow-ext/tests/phpt/024_writer_roundtrip_all_types.phpt deleted file mode 100644 index ecbc7aa8ed..0000000000 --- a/src/extension/arrow-ext/tests/phpt/024_writer_roundtrip_all_types.phpt +++ /dev/null @@ -1,115 +0,0 @@ ---TEST-- -Writer roundtrips flat and nested types combined in a single batch ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => true], - ['name' => 'score', 'type' => 'DOUBLE', 'optional' => true], - ['name' => 'tags', 'type' => 'LIST', 'optional' => true, 'children' => [ - ['name' => 'item', 'type' => 'STRING', 'optional' => true] - ]], - ['name' => 'meta', 'type' => 'STRUCT', 'optional' => true, 'children' => [ - ['name' => 'key', 'type' => 'STRING', 'optional' => false], - ['name' => 'val', 'type' => 'INT64', 'optional' => true], - ]], - ['name' => 'attrs', 'type' => 'MAP', 'optional' => true, 'children' => [ - ['name' => 'keys', 'type' => 'STRING', 'optional' => false], - ['name' => 'values', 'type' => 'STRING', 'optional' => true], - ]], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'id' => [1, 2, 3], - 'name' => ['Alice', null, 'Charlie'], - 'score' => [9.5, 8.0, null], - 'tags' => [['php', 'rust'], [], null], - 'meta' => [['key' => 'role', 'val' => 1], null, ['key' => 'team', 'val' => null]], - 'attrs' => [['color' => 'red', 'size' => 'large'], ['color' => 'blue'], null], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -// Flat columns -echo "id: "; -var_dump($data['id'][0] === 1 && $data['id'][1] === 2 && $data['id'][2] === 3); -echo "name: "; -var_dump($data['name'][0] === 'Alice' && $data['name'][1] === null && $data['name'][2] === 'Charlie'); -echo "score: "; -var_dump($data['score'][0] === 9.5 && $data['score'][1] === 8.0 && $data['score'][2] === null); - -// LIST -echo "tags0: "; -var_dump($data['tags'][0][0] === 'php' && $data['tags'][0][1] === 'rust'); -echo "tags1: "; -var_dump(is_array($data['tags'][1]) && count($data['tags'][1]) === 0); -echo "tags2: "; -var_dump($data['tags'][2] === null); - -// STRUCT -echo "meta0: "; -var_dump($data['meta'][0]['key'] === 'role' && $data['meta'][0]['val'] === 1); -echo "meta1: "; -var_dump($data['meta'][1] === null); -echo "meta2 key: "; -var_dump($data['meta'][2]['key'] === 'team'); -echo "meta2 val: "; -var_dump($data['meta'][2]['val'] === null); - -// MAP -echo "attrs0: "; -var_dump($data['attrs'][0]['color'] === 'red' && $data['attrs'][0]['size'] === 'large'); -echo "attrs1: "; -var_dump($data['attrs'][1]['color'] === 'blue'); -echo "attrs2: "; -var_dump($data['attrs'][2] === null); - -$reader->close(); -?> ---EXPECT-- -id: bool(true) -name: bool(true) -score: bool(true) -tags0: bool(true) -tags1: bool(true) -tags2: bool(true) -meta0: bool(true) -meta1: bool(true) -meta2 key: bool(true) -meta2 val: bool(true) -attrs0: bool(true) -attrs1: bool(true) -attrs2: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/025_writer_options_row_group_size.phpt b/src/extension/arrow-ext/tests/phpt/025_writer_options_row_group_size.phpt deleted file mode 100644 index 4b718445c9..0000000000 --- a/src/extension/arrow-ext/tests/phpt/025_writer_options_row_group_size.phpt +++ /dev/null @@ -1,63 +0,0 @@ ---TEST-- -Writer respects ROW_GROUP_SIZE_BYTES option to produce multiple row groups ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => false], -]; - -$dest = new TestDestinationStream(); -$options = ['ROW_GROUP_SIZE_BYTES' => 500]; -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED', $options); -for ($i = 0; $i < 100; $i++) { - $batch = [ - 'id' => [($i * 10) + 1, ($i * 10) + 2, ($i * 10) + 3, ($i * 10) + 4, ($i * 10) + 5, - ($i * 10) + 6, ($i * 10) + 7, ($i * 10) + 8, ($i * 10) + 9, ($i * 10) + 10], - 'name' => [str_repeat('x', 100), str_repeat('y', 100), str_repeat('z', 100), - str_repeat('a', 100), str_repeat('b', 100), str_repeat('c', 100), - str_repeat('d', 100), str_repeat('e', 100), str_repeat('f', 100), - str_repeat('g', 100)], - ]; - $writer->writeBatch($batch); -} -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$meta = $reader->metadata(); - -echo "multiple_row_groups: "; -var_dump($meta['row_groups'] > 1); -$reader->close(); -?> ---EXPECT-- -multiple_row_groups: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/026_writer_options_compression_level.phpt b/src/extension/arrow-ext/tests/phpt/026_writer_options_compression_level.phpt deleted file mode 100644 index 7ab7adfb3e..0000000000 --- a/src/extension/arrow-ext/tests/phpt/026_writer_options_compression_level.phpt +++ /dev/null @@ -1,73 +0,0 @@ ---TEST-- -Writer respects compression level options for GZIP, ZSTD, and BROTLI ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => false], -]; -$batch = [ - 'id' => [1, 2, 3], - 'name' => ['Alice', 'Bob', 'Charlie'], -]; - -$codecs = [ - 'GZIP' => ['GZIP_COMPRESSION_LEVEL' => 1], - 'ZSTD' => ['ZSTD_COMPRESSION_LEVEL' => 1], - 'BROTLI' => ['BROTLI_COMPRESSION_LEVEL' => 1], -]; - -foreach ($codecs as $codec => $options) { - $dest = new TestDestinationStream(); - $writer = new Flow\Arrow\Parquet\Writer($dest, $schema, $codec, $options); - $writer->writeBatch($batch); - $writer->close(); - - $source = new TestSourceStream($dest->data); - $reader = new Flow\Arrow\Parquet\Reader($source); - $data = $reader->readRowGroup(); - - $ok = $data['id'][0] === 1 - && $data['id'][1] === 2 - && $data['id'][2] === 3 - && $data['name'][0] === 'Alice' - && $data['name'][1] === 'Bob' - && $data['name'][2] === 'Charlie'; - - echo "$codec: "; - var_dump($ok); - $reader->close(); -} -?> ---EXPECT-- -GZIP: bool(true) -ZSTD: bool(true) -BROTLI: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/027_writer_options_per_column.phpt b/src/extension/arrow-ext/tests/phpt/027_writer_options_per_column.phpt deleted file mode 100644 index 93cfc1f820..0000000000 --- a/src/extension/arrow-ext/tests/phpt/027_writer_options_per_column.phpt +++ /dev/null @@ -1,69 +0,0 @@ ---TEST-- -Writer respects per-column compression via COLUMNS_COMPRESSIONS option ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => false], -]; -$batch = [ - 'id' => [1, 2, 3], - 'name' => ['Alice', 'Bob', 'Charlie'], -]; - -$dest = new TestDestinationStream(); -$options = [ - 'COLUMNS_COMPRESSIONS' => [ - 'id' => 'GZIP', - 'name' => 'ZSTD', - ], -]; -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'SNAPPY', $options); -$writer->writeBatch($batch); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -$ok = $data['id'][0] === 1 - && $data['id'][1] === 2 - && $data['id'][2] === 3 - && $data['name'][0] === 'Alice' - && $data['name'][1] === 'Bob' - && $data['name'][2] === 'Charlie'; - -echo "per_column_compression: "; -var_dump($ok); -$reader->close(); -?> ---EXPECT-- -per_column_compression: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/028_writer_options_writer_version.phpt b/src/extension/arrow-ext/tests/phpt/028_writer_options_writer_version.phpt deleted file mode 100644 index ecfc1860e3..0000000000 --- a/src/extension/arrow-ext/tests/phpt/028_writer_options_writer_version.phpt +++ /dev/null @@ -1,67 +0,0 @@ ---TEST-- -Writer respects WRITER_VERSION option for v1 and v2 ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => false], -]; -$batch = [ - 'id' => [1, 2, 3], - 'name' => ['Alice', 'Bob', 'Charlie'], -]; - -foreach ([1, 2] as $version) { - $dest = new TestDestinationStream(); - $options = ['WRITER_VERSION' => $version]; - $writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'SNAPPY', $options); - $writer->writeBatch($batch); - $writer->close(); - - $source = new TestSourceStream($dest->data); - $reader = new Flow\Arrow\Parquet\Reader($source); - $data = $reader->readRowGroup(); - - $ok = $data['id'][0] === 1 - && $data['id'][1] === 2 - && $data['id'][2] === 3 - && $data['name'][0] === 'Alice' - && $data['name'][1] === 'Bob' - && $data['name'][2] === 'Charlie'; - - echo "v$version: "; - var_dump($ok); - $reader->close(); -} -?> ---EXPECT-- -v1: bool(true) -v2: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/029_reader_options_unknown_ignored.phpt b/src/extension/arrow-ext/tests/phpt/029_reader_options_unknown_ignored.phpt deleted file mode 100644 index e4e8245acb..0000000000 --- a/src/extension/arrow-ext/tests/phpt/029_reader_options_unknown_ignored.phpt +++ /dev/null @@ -1,58 +0,0 @@ ---TEST-- -Reader silently ignores unknown options ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], -]; -$batch = [ - 'id' => [1, 2, 3], -]; - -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema); -$writer->writeBatch($batch); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$options = [ - 'SOME_UNKNOWN_OPTION' => 'whatever', - 'ANOTHER_ONE' => 42, -]; -$reader = new Flow\Arrow\Parquet\Reader($source, $options); -$data = $reader->readRowGroup(); - -echo "read_ok: "; -var_dump($data['id'][0] === 1 && $data['id'][1] === 2 && $data['id'][2] === 3); -$reader->close(); -?> ---EXPECT-- -read_ok: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/030_reader_batch_size.phpt b/src/extension/arrow-ext/tests/phpt/030_reader_batch_size.phpt deleted file mode 100644 index 4970bb5ab2..0000000000 --- a/src/extension/arrow-ext/tests/phpt/030_reader_batch_size.phpt +++ /dev/null @@ -1,67 +0,0 @@ ---TEST-- -Reader BATCH_SIZE option returns rows in batches ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], -]; - -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema); -$writer->writeBatch([ - 'id' => [1, 2, 3, 4, 5], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$options = ['BATCH_SIZE' => 2]; -$reader = new Flow\Arrow\Parquet\Reader($source, $options); - -$batch1 = $reader->readRowGroup(); -echo "batch1_count: " . count($batch1['id']) . "\n"; - -$batch2 = $reader->readRowGroup(); -echo "batch2_count: " . count($batch2['id']) . "\n"; - -$batch3 = $reader->readRowGroup(); -echo "batch3_count: " . count($batch3['id']) . "\n"; - -$batch4 = $reader->readRowGroup(); -echo "batch4_null: "; -var_dump($batch4 === null); - -$reader->close(); -?> ---EXPECT-- -batch1_count: 2 -batch2_count: 2 -batch3_count: 1 -batch4_null: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/031_reader_batch_size_across_row_groups.phpt b/src/extension/arrow-ext/tests/phpt/031_reader_batch_size_across_row_groups.phpt deleted file mode 100644 index 8cd98ba0f7..0000000000 --- a/src/extension/arrow-ext/tests/phpt/031_reader_batch_size_across_row_groups.phpt +++ /dev/null @@ -1,72 +0,0 @@ ---TEST-- -Reader BATCH_SIZE streams transparently across row group boundaries ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], - ['name' => 'name', 'type' => 'STRING', 'optional' => false], -]; - -$dest = new TestDestinationStream(); -$writerOptions = ['ROW_GROUP_SIZE_BYTES' => 500]; -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED', $writerOptions); - -$ids = []; -$names = []; -for ($i = 0; $i < 100; $i++) { - $ids[] = $i; - $names[] = "name_" . $i; -} -$writer->writeBatch(['id' => $ids, 'name' => $names]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$readerOptions = ['BATCH_SIZE' => 3]; -$reader = new Flow\Arrow\Parquet\Reader($source, $readerOptions); - -$totalRows = 0; -$batchCount = 0; -while (null !== ($batch = $reader->readRowGroup())) { - $totalRows += count($batch['id']); - $batchCount++; -} -$reader->close(); - -echo "total_rows: " . $totalRows . "\n"; -echo "multiple_batches: "; -var_dump($batchCount > 1); -echo "all_rows_read: "; -var_dump($totalRows === 100); -?> ---EXPECT-- -total_rows: 100 -multiple_batches: bool(true) -all_rows_read: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/032_reader_batch_size_null.phpt b/src/extension/arrow-ext/tests/phpt/032_reader_batch_size_null.phpt deleted file mode 100644 index 1e9fd69fa4..0000000000 --- a/src/extension/arrow-ext/tests/phpt/032_reader_batch_size_null.phpt +++ /dev/null @@ -1,62 +0,0 @@ ---TEST-- -Reader with BATCH_SIZE null returns full row group in one call ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$schema = [ - ['name' => 'id', 'type' => 'INT64', 'optional' => false], -]; - -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema); -$writer->writeBatch([ - 'id' => [1, 2, 3, 4, 5], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$options = ['BATCH_SIZE' => null]; -$reader = new Flow\Arrow\Parquet\Reader($source, $options); - -$batch = $reader->readRowGroup(); -echo "count: " . count($batch['id']) . "\n"; -echo "values_ok: "; -var_dump($batch['id'] === [1, 2, 3, 4, 5]); - -$next = $reader->readRowGroup(); -echo "exhausted: "; -var_dump($next === null); - -$reader->close(); -?> ---EXPECT-- -count: 5 -values_ok: bool(true) -exhausted: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/033_writer_int_overflow.phpt b/src/extension/arrow-ext/tests/phpt/033_writer_int_overflow.phpt deleted file mode 100644 index 3ef2a911b6..0000000000 --- a/src/extension/arrow-ext/tests/phpt/033_writer_int_overflow.phpt +++ /dev/null @@ -1,60 +0,0 @@ ---TEST-- -Writer throws exception when integer value overflows target type ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'col_int8', 'type' => 'INT8'], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); - -try { - $writer->writeBatch([ - 'col_int8' => [256], - ]); - echo "ERROR: No exception thrown\n"; -} catch (Flow\Arrow\Parquet\Exception $e) { - echo "Caught expected exception\n"; - echo (str_contains($e->getMessage(), 'out of range') ? "Message contains 'out of range'" : "ERROR: unexpected message: " . $e->getMessage()) . "\n"; - echo (str_contains($e->getMessage(), '256') ? "Message contains the value" : "ERROR: message missing value") . "\n"; -} - -// Also test negative value in unsigned type -$dest2 = new TestDestinationStream(); -$schema2 = [ - ['name' => 'col_uint64', 'type' => 'UINT64'], -]; - -$writer2 = new Flow\Arrow\Parquet\Writer($dest2, $schema2, 'UNCOMPRESSED'); - -try { - $writer2->writeBatch([ - 'col_uint64' => [-1], - ]); - echo "ERROR: No exception thrown\n"; -} catch (Flow\Arrow\Parquet\Exception $e) { - echo "Caught expected exception for negative uint64\n"; - echo (str_contains($e->getMessage(), 'out of range') ? "Message contains 'out of range'" : "ERROR: unexpected message: " . $e->getMessage()) . "\n"; -} -?> ---EXPECT-- -Caught expected exception -Message contains 'out of range' -Message contains the value -Caught expected exception for negative uint64 -Message contains 'out of range' diff --git a/src/extension/arrow-ext/tests/phpt/034_writer_float_overflow.phpt b/src/extension/arrow-ext/tests/phpt/034_writer_float_overflow.phpt deleted file mode 100644 index d731e80dec..0000000000 --- a/src/extension/arrow-ext/tests/phpt/034_writer_float_overflow.phpt +++ /dev/null @@ -1,38 +0,0 @@ ---TEST-- -Writer throws exception when float value overflows Float32 ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'col_float', 'type' => 'FLOAT'], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); - -try { - $writer->writeBatch([ - 'col_float' => [1.0e39], - ]); - echo "ERROR: No exception thrown\n"; -} catch (Flow\Arrow\Parquet\Exception $e) { - echo "Caught expected exception\n"; - echo (str_contains($e->getMessage(), 'overflows') ? "Message contains 'overflows'" : "ERROR: unexpected message: " . $e->getMessage()) . "\n"; -} -?> ---EXPECT-- -Caught expected exception -Message contains 'overflows' diff --git a/src/extension/arrow-ext/tests/phpt/036_interfaces_and_exception_registered.phpt b/src/extension/arrow-ext/tests/phpt/036_interfaces_and_exception_registered.phpt index 13923e021b..a0e2b958fd 100644 --- a/src/extension/arrow-ext/tests/phpt/036_interfaces_and_exception_registered.phpt +++ b/src/extension/arrow-ext/tests/phpt/036_interfaces_and_exception_registered.phpt @@ -1,13 +1,11 @@ --TEST-- -arrow extension registers OutputStream, RandomAccessFile interfaces and Parquet\Exception class +arrow extension registers the OutputStream and RandomAccessFile interfaces --SKIPIF-- --FILE-- isInterface()); @@ -26,5 +24,3 @@ bool(true) bool(true) bool(true) bool(true) -bool(true) -bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/037_writer_roundtrip_nested_uuid_json.phpt b/src/extension/arrow-ext/tests/phpt/037_writer_roundtrip_nested_uuid_json.phpt deleted file mode 100644 index 817564b7aa..0000000000 --- a/src/extension/arrow-ext/tests/phpt/037_writer_roundtrip_nested_uuid_json.phpt +++ /dev/null @@ -1,94 +0,0 @@ ---TEST-- -Writer roundtrips uuid and json nested in struct, list and map; reader returns canonical uuid strings at every depth ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$uuid = 'f6d6e0e8-4b7e-4b0e-8d7a-ff0a0c9c9a5a'; - -$dest = new TestDestinationStream(); -$schema = [ - ['name' => 'top_uuid', 'type' => 'UUID', 'optional' => true], - ['name' => 'body', 'type' => 'STRUCT', 'optional' => true, 'children' => [ - ['name' => 'id', 'type' => 'UUID', 'optional' => true], - ['name' => 'data', 'type' => 'JSON', 'optional' => true], - ['name' => 'inner', 'type' => 'STRUCT', 'optional' => true, 'children' => [ - ['name' => 'deep', 'type' => 'UUID', 'optional' => true], - ]], - ]], - ['name' => 'uuid_list', 'type' => 'LIST', 'optional' => true, 'children' => [ - ['name' => 'element', 'type' => 'UUID', 'optional' => true], - ]], - ['name' => 'uuid_map', 'type' => 'MAP', 'optional' => true, 'children' => [ - ['name' => 'key', 'type' => 'STRING', 'optional' => false], - ['name' => 'value', 'type' => 'UUID', 'optional' => true], - ]], - ['name' => 'json_map', 'type' => 'MAP', 'optional' => true, 'children' => [ - ['name' => 'key', 'type' => 'STRING', 'optional' => false], - ['name' => 'value', 'type' => 'JSON', 'optional' => true], - ]], -]; - -$writer = new Flow\Arrow\Parquet\Writer($dest, $schema, 'UNCOMPRESSED'); -$writer->writeBatch([ - 'top_uuid' => [$uuid], - 'body' => [['id' => $uuid, 'data' => '{"a":1}', 'inner' => ['deep' => $uuid]]], - 'uuid_list' => [[$uuid, $uuid, null]], - 'uuid_map' => [['k' => $uuid]], - 'json_map' => [['k' => '{"d":4}']], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -echo "top_uuid: "; -var_dump($data['top_uuid'][0] === $uuid); -echo "struct id: "; -var_dump($data['body'][0]['id'] === $uuid); -echo "struct json: "; -var_dump($data['body'][0]['data'] === '{"a":1}'); -echo "deep struct uuid: "; -var_dump($data['body'][0]['inner']['deep'] === $uuid); -echo "list: "; -var_dump($data['uuid_list'][0] === [$uuid, $uuid, null]); -echo "uuid map: "; -var_dump($data['uuid_map'][0] === ['k' => $uuid]); -echo "json map: "; -var_dump($data['json_map'][0] === ['k' => '{"d":4}']); -?> ---EXPECT-- -top_uuid: bool(true) -struct id: bool(true) -struct json: bool(true) -deep struct uuid: bool(true) -list: bool(true) -uuid map: bool(true) -json map: bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/039_reader_pre_epoch_timestamps.phpt b/src/extension/arrow-ext/tests/phpt/039_reader_pre_epoch_timestamps.phpt deleted file mode 100644 index 511e71049c..0000000000 --- a/src/extension/arrow-ext/tests/phpt/039_reader_pre_epoch_timestamps.phpt +++ /dev/null @@ -1,64 +0,0 @@ ---TEST-- -Reader floors pre-epoch timestamps with a sub-second fraction ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, [ - ['name' => 'ts', 'type' => 'TIMESTAMP', 'optional' => true], - ['name' => 'ts_list', 'type' => 'LIST', 'optional' => true, 'children' => [ - ['name' => 'item', 'type' => 'TIMESTAMP', 'optional' => true], - ]], -], 'UNCOMPRESSED'); -$writer->writeBatch([ - 'ts' => [-1500000, -1, 1577934245678901], - 'ts_list' => [[-1500000, -1, 1577934245678901], null, null], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -foreach ($data['ts'] as $value) { - echo $value->format('Y-m-d H:i:s.u'), "\n"; -} - -foreach ($data['ts_list'][0] as $value) { - echo $value->format('Y-m-d H:i:s.u'), "\n"; -} -?> ---EXPECT-- -1969-12-31 23:59:58.500000 -1969-12-31 23:59:59.999999 -2020-01-02 03:04:05.678901 -1969-12-31 23:59:58.500000 -1969-12-31 23:59:59.999999 -2020-01-02 03:04:05.678901 diff --git a/src/extension/arrow-ext/tests/phpt/040_reader_decimal256.phpt b/src/extension/arrow-ext/tests/phpt/040_reader_decimal256.phpt deleted file mode 100644 index 183d118b01..0000000000 --- a/src/extension/arrow-ext/tests/phpt/040_reader_decimal256.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -Reader converts FIXED_LEN_BYTE_ARRAY decimals of every width, Decimal256 included ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$source = new TestSourceStream(file_get_contents(__DIR__ . '/../fixtures/decimals_fixed_len.parquet')); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -foreach ([0, 1] as $row) { - foreach (['dec9', 'dec18', 'dec38', 'dec50'] as $column) { - var_dump($data[$column][$row]); - } -} -?> ---EXPECT-- -float(12345.67) -float(1234567890123456.8) -float(1.2345678901234568E+18) -float(1.2345678901234568E+39) -float(-12345.67) -float(-0.01) -float(-12345.67) -float(-12345.67) diff --git a/src/extension/arrow-ext/tests/phpt/041_writer_date_lanes.phpt b/src/extension/arrow-ext/tests/phpt/041_writer_date_lanes.phpt deleted file mode 100644 index fd437a5352..0000000000 --- a/src/extension/arrow-ext/tests/phpt/041_writer_date_lanes.phpt +++ /dev/null @@ -1,61 +0,0 @@ ---TEST-- -Writer DATE int lane is days since epoch, objects write their wall-clock day ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, [ - ['name' => 'd_int', 'type' => 'DATE', 'optional' => true], - ['name' => 'd_object', 'type' => 'DATE', 'optional' => true], -], 'UNCOMPRESSED'); -$writer->writeBatch([ - 'd_int' => [18263, -1], - 'd_object' => [ - new DateTimeImmutable('2024-01-01 00:00:00', new DateTimeZone('Europe/Warsaw')), - new DateTimeImmutable('1969-12-31 12:00:00', new DateTimeZone('UTC')), - ], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -foreach (['d_int', 'd_object'] as $column) { - foreach ($data[$column] as $value) { - echo $value->format('Y-m-d'), "\n"; - } -} -?> ---EXPECT-- -2020-01-02 -1969-12-31 -2024-01-01 -1969-12-31 diff --git a/src/extension/arrow-ext/tests/phpt/042_writer_temporal_units.phpt b/src/extension/arrow-ext/tests/phpt/042_writer_temporal_units.phpt deleted file mode 100644 index 863631e446..0000000000 --- a/src/extension/arrow-ext/tests/phpt/042_writer_temporal_units.phpt +++ /dev/null @@ -1,74 +0,0 @@ ---TEST-- -Writer honours the declared TIMESTAMP and TIME units ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$time = new DateInterval('PT3H4M5S'); -$time->f = 0.678901; - -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, [ - ['name' => 'ts_ms', 'type' => 'TIMESTAMP', 'optional' => true, 'unit' => 'MILLIS', 'utc' => false], - ['name' => 'ts_ns', 'type' => 'TIMESTAMP', 'optional' => true, 'unit' => 'NANOS'], - ['name' => 't_ms', 'type' => 'TIME', 'optional' => true, 'unit' => 'MILLIS'], - ['name' => 't_ns', 'type' => 'TIME', 'optional' => true, 'unit' => 'NANOS'], -], 'UNCOMPRESSED'); -$writer->writeBatch([ - 'ts_ms' => [new DateTimeImmutable('2020-01-02 03:04:05.678901 UTC')], - 'ts_ns' => [new DateTimeImmutable('2020-01-02 03:04:05.678901 UTC')], - 't_ms' => [$time], - 't_ns' => [$time], -]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); -$data = $reader->readRowGroup(); - -echo $data['ts_ms'][0]->format('Y-m-d H:i:s.u'), "\n"; -echo $data['ts_ns'][0]->format('Y-m-d H:i:s.u'), "\n"; -echo $data['t_ms'][0]->format('%H:%I:%S.%F'), "\n"; -echo $data['t_ns'][0]->format('%H:%I:%S.%F'), "\n"; - -try { - $invalid = new TestDestinationStream(); - new Flow\Arrow\Parquet\Writer($invalid, [ - ['name' => 'ts', 'type' => 'TIMESTAMP', 'optional' => true, 'unit' => 'SECONDS'], - ], 'UNCOMPRESSED'); -} catch (Flow\Arrow\Parquet\Exception $e) { - echo $e->getMessage(), "\n"; -} -?> ---EXPECT-- -2020-01-02 03:04:05.678000 -2020-01-02 03:04:05.678901 -03:04:05.678000 -03:04:05.678901 -Column 'ts': unsupported unit 'SECONDS', expected MILLIS, MICROS or NANOS diff --git a/src/extension/arrow-ext/tests/phpt/043_writer_decimal_rounding.phpt b/src/extension/arrow-ext/tests/phpt/043_writer_decimal_rounding.phpt deleted file mode 100644 index af4032e9f2..0000000000 --- a/src/extension/arrow-ext/tests/phpt/043_writer_decimal_rounding.phpt +++ /dev/null @@ -1,53 +0,0 @@ ---TEST-- -Writer rounds float DECIMAL values half away from zero ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, [ - ['name' => 'd', 'type' => 'DECIMAL', 'optional' => true, 'precision' => 9, 'scale' => 2], -], 'UNCOMPRESSED'); -$writer->writeBatch(['d' => [0.125, 2.675, -0.125, 1.005, 9.995, -99.995]]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); - -foreach ($reader->readRowGroup()['d'] as $value) { - var_dump($value); -} -?> ---EXPECT-- -float(0.13) -float(2.68) -float(-0.13) -float(1.01) -float(10) -float(-100) diff --git a/src/extension/arrow-ext/tests/phpt/044_reader_schema_units_and_decimal256.phpt b/src/extension/arrow-ext/tests/phpt/044_reader_schema_units_and_decimal256.phpt deleted file mode 100644 index 2a8e110a96..0000000000 --- a/src/extension/arrow-ext/tests/phpt/044_reader_schema_units_and_decimal256.phpt +++ /dev/null @@ -1,67 +0,0 @@ ---TEST-- -Reader schema describes temporal units, the UTC flag and Decimal256 columns ---SKIPIF-- - ---FILE-- -data .= $data; - return $this; - } -} - -class TestSourceStream implements Flow\Arrow\RandomAccessFile { - private string $data; - public function __construct(string $data) { - $this->data = $data; - } - public function read(int $length, int $offset): string { - return substr($this->data, $offset, $length); - } - public function size(): ?int { - return strlen($this->data); - } -} - -$dest = new TestDestinationStream(); -$writer = new Flow\Arrow\Parquet\Writer($dest, [ - ['name' => 'ts', 'type' => 'TIMESTAMP', 'optional' => true], - ['name' => 'ts_ms', 'type' => 'TIMESTAMP', 'optional' => true, 'unit' => 'MILLIS', 'utc' => false], - ['name' => 'ts_ns', 'type' => 'TIMESTAMP', 'optional' => true, 'unit' => 'NANOS'], - ['name' => 't_ms', 'type' => 'TIME', 'optional' => true, 'unit' => 'MILLIS'], - ['name' => 't_ns', 'type' => 'TIME', 'optional' => true, 'unit' => 'NANOS'], -], 'UNCOMPRESSED'); -$writer->writeBatch(['ts' => [0], 'ts_ms' => [0], 'ts_ns' => [0], 't_ms' => [0], 't_ns' => [0]]); -$writer->close(); - -$source = new TestSourceStream($dest->data); -$reader = new Flow\Arrow\Parquet\Reader($source); - -foreach ($reader->schema() as $column) { - echo $column['name'], ' ', $column['type'], ' ', $column['unit'], ' ', var_export($column['utc'] ?? null, true), "\n"; -} - -$fixture = new TestSourceStream(file_get_contents(__DIR__ . '/../fixtures/decimals_fixed_len.parquet')); -$decimals = new Flow\Arrow\Parquet\Reader($fixture); - -foreach ($decimals->schema() as $column) { - echo $column['name'], ' ', $column['type'], ' ', $column['precision'], ' ', $column['scale'], "\n"; -} -?> ---EXPECT-- -ts TIMESTAMP MICROS true -ts_ms TIMESTAMP MILLIS false -ts_ns TIMESTAMP NANOS true -t_ms TIME MILLIS NULL -t_ns TIME NANOS NULL -dec9 DECIMAL 9 2 -dec18 DECIMAL 18 2 -dec38 DECIMAL 38 10 -dec50 DECIMAL 50 10 diff --git a/src/extension/flow-php-ext/tests/phpt/073_parquet_lib_read_parity.phpt b/src/extension/arrow-ext/tests/phpt/045_parquet_lib_read_parity.phpt similarity index 51% rename from src/extension/flow-php-ext/tests/phpt/073_parquet_lib_read_parity.phpt rename to src/extension/arrow-ext/tests/phpt/045_parquet_lib_read_parity.phpt index a666a638f4..7e01bcfe70 100644 --- a/src/extension/flow-php-ext/tests/phpt/073_parquet_lib_read_parity.phpt +++ b/src/extension/arrow-ext/tests/phpt/045_parquet_lib_read_parity.phpt @@ -1,11 +1,13 @@ --TEST-- -Reader::arrow() on flow_php reads every lib Parquet fixture as Reader::php() does, both refuse it, or it refuses naming Reader::php() +Reader::arrow() on arrow reads every lib Parquet fixture as Reader::php() does, both refuse it, or it refuses naming Reader::php() --SKIPIF-- - + --FILE-- ParquetRows::read(Reader::php()->read($file), $batchSize)); - $native = outcome(static fn() => ParquetRows::read(Reader::arrow()->read($file), $batchSize)); + $php = arrow_outcome(static fn() => ParquetRows::read(Reader::php()->read($file), $batchSize)); + $native = arrow_outcome(static fn() => ParquetRows::read(Reader::arrow()->read($file), $batchSize)); $name = substr($file, strlen($fixtures) + 1) . ' ' . $batchSize; echo match (true) { - refused($php) && refused($native) => "{$name}: both refuse\n", + arrow_refused($php) && arrow_refused($native) => "{$name}: both refuse\n", $php === $native => "{$name}: identical\n", - refused($native) && str_contains($native, 'Reader::php()') => "{$name}: {$native}\n", + arrow_refused($native) && str_contains($native, 'Reader::php()') => "{$name}: {$native}\n", default => "{$name}: DIFFER\n php: " . substr($php, 0, 300) . "\n native: " . substr($native, 0, 300) . "\n", }; } } $interval = $fixtures . '/EdgeCases/interval.parquet'; -echo 'interval.parquet [id]: ', outcome(static fn() => ParquetRows::read(Reader::php()->read($interval), 10, ['id'])) === outcome(static fn() => ParquetRows::read(Reader::arrow()->read($interval), 10, ['id'])) ? 'identical' : 'DIFFER', "\n"; +echo 'interval.parquet [id]: ', arrow_outcome(static fn() => ParquetRows::read(Reader::php()->read($interval), 10, ['id'])) === arrow_outcome(static fn() => ParquetRows::read(Reader::arrow()->read($interval), 10, ['id'])) ? 'identical' : 'DIFFER', "\n"; $everyType = MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows()); -echo 'every type: ', outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), $everyType), 2)) === outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $everyType), 2)) ? 'identical' : 'DIFFER', "\n"; +echo 'every type: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), $everyType), 2)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $everyType), 2)) ? 'identical' : 'DIFFER', "\n"; + +// pre-epoch timestamps with a sub-second fraction are floored, flat and inside a list +$preEpoch = MemoryParquetFile::written( + Writer::php(), + Schema::with(FlatColumn::dateTime('ts'), NestedColumn::list('ts_list', ListElement::datetime())), + array_map( + static fn(DateTimeImmutable $at): array => ['ts' => $at, 'ts_list' => [$at]], + [(new DateTimeImmutable('@0'))->modify('-1500000 microseconds'), (new DateTimeImmutable('@0'))->modify('-1 microsecond'), new DateTimeImmutable('2020-01-02 03:04:05.678901 UTC')], + ), +); +echo 'pre-epoch timestamps: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), $preEpoch), 3)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $preEpoch), 3)) ? 'identical' : 'DIFFER', "\n"; + +foreach (ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $preEpoch), 3) as $row) { + echo $row['ts']->format('Y-m-d H:i:s.u'), ' ', $row['ts_list'][0]->format('Y-m-d H:i:s.u'), "\n"; +} ?> --EXPECT-- columns.required.parquet 100: identical @@ -60,8 +77,8 @@ EdgeCases/datapage_v2.snappy.parquet 100: identical EdgeCases/datapage_v2.snappy.parquet 10000: identical EdgeCases/int96.parquet 100: identical EdgeCases/int96.parquet 10000: identical -EdgeCases/interval.parquet 100: Flow\Parquet\Exception\RuntimeException: Parquet column "iv" (Interval(DayTime)) is not supported by the flow_php Parquet reader; read the file with \Flow\Parquet\Reader::php() -EdgeCases/interval.parquet 10000: Flow\Parquet\Exception\RuntimeException: Parquet column "iv" (Interval(DayTime)) is not supported by the flow_php Parquet reader; read the file with \Flow\Parquet\Reader::php() +EdgeCases/interval.parquet 100: Flow\Parquet\Exception\RuntimeException: Parquet column "iv" (Interval(DayTime)) is not supported by the arrow Parquet reader; read the file with \Flow\Parquet\Reader::php() +EdgeCases/interval.parquet 10000: Flow\Parquet\Exception\RuntimeException: Parquet column "iv" (Interval(DayTime)) is not supported by the arrow Parquet reader; read the file with \Flow\Parquet\Reader::php() EdgeCases/map_keys.parquet 100: both refuse EdgeCases/map_keys.parquet 10000: both refuse EdgeCases/nonnullable.impala.parquet 100: identical @@ -74,3 +91,7 @@ EdgeCases/unsigned.parquet 100: identical EdgeCases/unsigned.parquet 10000: identical interval.parquet [id]: identical every type: identical +pre-epoch timestamps: identical +1969-12-31 23:59:58.500000 1969-12-31 23:59:58.500000 +1969-12-31 23:59:59.999999 1969-12-31 23:59:59.999999 +2020-01-02 03:04:05.678901 2020-01-02 03:04:05.678901 diff --git a/src/extension/flow-php-ext/tests/phpt/074_parquet_lib_write_parity.phpt b/src/extension/arrow-ext/tests/phpt/046_parquet_lib_write_parity.phpt similarity index 56% rename from src/extension/flow-php-ext/tests/phpt/074_parquet_lib_write_parity.phpt rename to src/extension/arrow-ext/tests/phpt/046_parquet_lib_write_parity.phpt index 1968e44503..6afae60859 100644 --- a/src/extension/flow-php-ext/tests/phpt/074_parquet_lib_write_parity.phpt +++ b/src/extension/arrow-ext/tests/phpt/046_parquet_lib_write_parity.phpt @@ -1,7 +1,7 @@ --TEST-- -Writer::arrow() on flow_php accepts and refuses what Writer::php() does per target type, and what both accept reads back the same +Writer::arrow() on arrow accepts and refuses what Writer::php() does per target type, and what both accept reads back the same --SKIPIF-- - + --FILE-- outcome(static fn() => ParquetRows::read(MemoryParquetFile::read( + $read = static fn(Writer $writer): string => arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read( Reader::php(), MemoryParquetFile::written($writer, Schema::with(WriteAcceptance::target($target)), [['c' => WriteAcceptance::input($input)]]), ), 1)); @@ -27,15 +27,15 @@ foreach (WriteAcceptance::targets() as $target) { $cells++; match (true) { - refused($php) && refused($native) => $refused++, - !refused($php) && $php === $native => $accepted++, + arrow_refused($php) && arrow_refused($native) => $refused++, + !arrow_refused($php) && $php === $native => $accepted++, default => print("{$target} <- {$input}: DIFFER\n php: " . substr($php, 0, 200) . "\n native: " . substr($native, 0, 200) . "\n"), }; } } echo "{$cells} cells: {$accepted} accepted by both, {$refused} refused by both\n"; -echo 'every type: ', outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows())), 3)) === outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::arrow(), EveryType::schema(), EveryType::rows())), 3)) ? 'identical' : 'DIFFER', "\n"; +echo 'every type: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows())), 3)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::arrow(), EveryType::schema(), EveryType::rows())), 3)) ? 'identical' : 'DIFFER', "\n"; ?> --EXPECT-- 624 cells: 102 accepted by both, 522 refused by both diff --git a/src/extension/flow-php-ext/tests/phpt/075_parquet_footer_thrift_parity.phpt b/src/extension/arrow-ext/tests/phpt/047_parquet_footer_thrift_parity.phpt similarity index 56% rename from src/extension/flow-php-ext/tests/phpt/075_parquet_footer_thrift_parity.phpt rename to src/extension/arrow-ext/tests/phpt/047_parquet_footer_thrift_parity.phpt index 229028a867..66b5f6d83c 100644 --- a/src/extension/flow-php-ext/tests/phpt/075_parquet_footer_thrift_parity.phpt +++ b/src/extension/arrow-ext/tests/phpt/047_parquet_footer_thrift_parity.phpt @@ -1,13 +1,19 @@ --TEST-- -NativeParquetFile decodes the footer to the FileMetaData and schema the PHP thrift reader builds, from one footer read +ParquetFile decodes the footer to the FileMetaData and schema the PHP thrift reader builds, from one footer read --SKIPIF-- - + --FILE-- read(new CompactProtocol(new MemoryBuffer(substr($bytes, -8 - $length, $length)))); $stream = new ReadCountingSourceStream(NativeLocalSourceStream::open(path_real($path))); - $file = new NativeParquetFile($stream); + $file = new ParquetFile($stream); $reads = $stream->reads; printf( @@ -35,6 +41,26 @@ foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.p ); $file->close(); } + +// the temporal units and the UTC flag of every TIMESTAMP / TIME unit +$units = MemoryParquetFile::written(Writer::php(), Schema::with( + FlatColumn::dateTime('ts'), + new FlatColumn('ts_ms', PhysicalType::INT64, logicalType: new LogicalType(LogicalType::TIMESTAMP, timestamp: new Timestamp(false, TimeUnit::MILLISECONDS))), + new FlatColumn('ts_ns', PhysicalType::INT64, logicalType: new LogicalType(LogicalType::TIMESTAMP, timestamp: new Timestamp(true, TimeUnit::NANOSECONDS))), + new FlatColumn('t_ms', PhysicalType::INT32, logicalType: new LogicalType(LogicalType::TIME, time: new Time(false, TimeUnit::MILLISECONDS))), + new FlatColumn('t_ns', PhysicalType::INT64, logicalType: new LogicalType(LogicalType::TIME, time: new Time(false, TimeUnit::NANOSECONDS))), +), [['ts' => null, 'ts_ms' => null, 'ts_ns' => null, 't_ms' => null, 't_ns' => null]]); +$length = unpack('V', substr($units, -8, 4))[1]; +$php = new FileMetaData(); +$php->read(new CompactProtocol(new MemoryBuffer(substr($units, -8 - $length, $length)))); +$file = new ParquetFile(new MemorySourceStream($units)); + +printf( + "temporal units: thrift %s, schema %s\n", + serialize($file->thrift()) === serialize($php) ? 'identical' : 'DIFFER', + serialize($file->schema()) === serialize($php->schema) ? 'identical' : 'DIFFER', +); +$file->close(); ?> --EXPECT-- columns.required.parquet: thrift identical, schema identical, footer reads 1 @@ -55,3 +81,4 @@ EdgeCases/nonnullable.impala.parquet: thrift identical, schema identical, footer EdgeCases/null_list.parquet: thrift identical, schema identical, footer reads 1 EdgeCases/uint64_overflow.parquet: thrift identical, schema identical, footer reads 1 EdgeCases/unsigned.parquet: thrift identical, schema identical, footer reads 1 +temporal units: thrift identical, schema identical diff --git a/src/extension/flow-php-ext/tests/phpt/076_parquet_lib_no_leaks.phpt b/src/extension/arrow-ext/tests/phpt/048_parquet_lib_no_leaks.phpt similarity index 59% rename from src/extension/flow-php-ext/tests/phpt/076_parquet_lib_no_leaks.phpt rename to src/extension/arrow-ext/tests/phpt/048_parquet_lib_no_leaks.phpt index 192928ade5..d9593251ca 100644 --- a/src/extension/flow-php-ext/tests/phpt/076_parquet_lib_no_leaks.phpt +++ b/src/extension/arrow-ext/tests/phpt/048_parquet_lib_no_leaks.phpt @@ -1,14 +1,13 @@ --TEST-- -NativeParquetFile, NativeParquetColumnsReader and NativeParquetRowsWriter leak neither PHP memory nor native allocations, refusals included +ParquetFile, ColumnsReader and RowsWriter leak no PHP memory, refusals included --SKIPIF-- - + --FILE-- $column->name(), EveryType::schema()- $cycle = static function () use ($schema, $options, $rows, $columns): void { $filesystem = memory_filesystem(); - $writer = new NativeParquetRowsWriter($filesystem->writeTo(path('memory://leaks.parquet')), $schema, 'SNAPPY', $options, 2); + $writer = new RowsWriter($filesystem->writeTo(path('memory://leaks.parquet')), $schema, 'SNAPPY', $options, 2); $writer->writeRows($rows); $writer->writeRow($rows[0]); @@ -33,23 +32,23 @@ $cycle = static function () use ($schema, $options, $rows, $columns): void { $writer->close(); - $file = new NativeParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))); + $file = new ParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))); $file->thrift(); $file->schema(); - $reader = new NativeParquetColumnsReader($file, $columns, 2, 1, 3); + $reader = new ColumnsReader($file, $columns, 2, 1, 3); while ($reader->next() !== null) { } try { - new NativeParquetColumnsReader($file, ['missing'], 2, null, null); + new ColumnsReader($file, ['missing'], 2, null, null); throw new LogicException('a missing column was read'); } catch (Flow\Parquet\Exception\InvalidArgumentException) { } $file->close(); - $abandoned = new NativeParquetRowsWriter($filesystem->writeTo(path('memory://abandoned.parquet')), $schema, 'SNAPPY', $options, 2); + $abandoned = new RowsWriter($filesystem->writeTo(path('memory://abandoned.parquet')), $schema, 'SNAPPY', $options, 2); $abandoned->writeRows($rows); }; @@ -58,7 +57,6 @@ for ($i = 0; $i < 10; $i++) { } gc_collect_cycles(); $baseline = memory_get_usage(false); -$baselineRust = (new DefaultBackend())->allocatedBytes(); for ($i = 0; $i < 200; $i++) { $cycle(); @@ -66,8 +64,6 @@ for ($i = 0; $i < 200; $i++) { gc_collect_cycles(); var_dump(memory_get_usage(false) <= $baseline); -var_dump((new DefaultBackend())->allocatedBytes() === $baselineRust); ?> --EXPECT-- bool(true) -bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/083_parquet_write_columns_parity.phpt b/src/extension/arrow-ext/tests/phpt/049_parquet_write_columns_parity.phpt similarity index 92% rename from src/extension/flow-php-ext/tests/phpt/083_parquet_write_columns_parity.phpt rename to src/extension/arrow-ext/tests/phpt/049_parquet_write_columns_parity.phpt index b9a5609c18..3418916eb2 100644 --- a/src/extension/flow-php-ext/tests/phpt/083_parquet_write_columns_parity.phpt +++ b/src/extension/arrow-ext/tests/phpt/049_parquet_write_columns_parity.phpt @@ -1,7 +1,7 @@ --TEST-- -NativeParquetRowsWriter::writeColumns() accepts, refuses and keeps what writeRows() does, for every write-acceptance cell and across flushed batches +RowsWriter::writeColumns() accepts, refuses and keeps what writeRows() does, for every write-acceptance cell and across flushed batches --SKIPIF-- - + --FILE-- +--FILE-- + ['id' => $i, 'name' => $i % 3 ? "name {$i}" : null, 'tags' => $i % 4 ? [$i, $i + 1] : null], range(0, 249)); + +$roundTrip = static function (Filesystem $filesystem) use ($source, $target, $options, $rows): array { + $writer = new RowsWriter($filesystem->writeTo(path('memory://source.parquet')), SchemaConverter::toExtension($source), 'SNAPPY', $options, 100); + $writer->writeRows($rows); + $writer->close(); + + $batches = new BatchReader(new ParquetFile($filesystem->readFrom(path('memory://source.parquet'))), ['id', 'name', 'tags'], 100, null, null); + $schema = $batches->schema(); + $copy = new RowsWriter($filesystem->writeTo(path('memory://copy.parquet')), SchemaConverter::toExtension($target), 'SNAPPY', $options, 100); + $counts = []; + + while (($batch = $batches->next()) !== null) { + $counts[] = $batch->count(); + $copy->writeBatch($batch); + } + + $copy->close(); + + return [$schema, $counts]; +}; + +$filesystem = memory_filesystem(); +[$schema, $counts] = $roundTrip($filesystem); +$expected = array_map(static fn(array $row): array => ['id' => $row['id'], 'name' => $row['name'], 'missing' => null], $rows); + +echo get_class($schema), ' ', $schema->arrowSchemaAddress() > 0 ? 'has an address' : 'NO ADDRESS', "\n"; +echo 'batches: ', implode(',', $counts), "\n"; +echo 'round trip: ', iterator_to_array(Reader::php()->readStream($filesystem->readFrom(path('memory://copy.parquet')))->values(), false) === $expected ? 'identical' : 'DIFFER', "\n"; + +$batches = new BatchReader(new ParquetFile($filesystem->readFrom(path('memory://source.parquet'))), ['id', 'name', 'tags'], 100, null, null); +$batch = $batches->next(); +$twice = new RowsWriter($filesystem->writeTo(path('memory://twice.parquet')), SchemaConverter::toExtension($target), 'SNAPPY', $options, 100); +$twice->writeBatch($batch); +echo arrow_outcome(static fn() => $twice->writeBatch($batch)), "\n"; +echo arrow_outcome(static fn() => $twice->writeBatch(new UserlandBatch())), "\n"; +$twice->close(); + +for ($i = 0; $i < 10; $i++) { + $roundTrip(memory_filesystem()); +} +gc_collect_cycles(); +$baseline = memory_get_usage(false); + +for ($i = 0; $i < 100; $i++) { + $roundTrip(memory_filesystem()); +} +gc_collect_cycles(); + +var_dump(memory_get_usage(false) <= $baseline); +?> +--EXPECT-- +Flow\Arrow\ArrowSchema has an address +batches: 100,100,50 +round trip: identical +Flow\Parquet\Exception\InvalidArgumentException: Arrow C Data batch is already imported +Flow\Parquet\Exception\InvalidArgumentException: Arrow C Data batch must be an extension's class, got UserlandBatch +bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/bootstrap.php b/src/extension/arrow-ext/tests/phpt/bootstrap.php new file mode 100644 index 0000000000..3f38445793 --- /dev/null +++ b/src/extension/arrow-ext/tests/phpt/bootstrap.php @@ -0,0 +1,32 @@ +getPrevious(); + + return ( + get_class($e) + . ': ' + . $e->getMessage() + . ($previous === null ? '' : ' <- ' . get_class($previous) . ': ' . $previous->getMessage()) + ); + } +} + +/** + * Whether an arrow_outcome() is a refusal: the class and message of what the callable threw. + */ +function arrow_refused(string $outcome): bool +{ + return (bool) preg_match('/^[A-Za-z\\\\]+(Exception|Error|Overflow): /', $outcome); +} diff --git a/src/extension/flow-php-ext/Cargo.lock b/src/extension/flow-php-ext/Cargo.lock index b63938ba30..fe85342ee3 100644 --- a/src/extension/flow-php-ext/Cargo.lock +++ b/src/extension/flow-php-ext/Cargo.lock @@ -42,21 +42,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" -dependencies = [ - "alloc-no-stdlib", -] - [[package]] name = "android_system_properties" version = "0.1.6" @@ -85,6 +70,7 @@ dependencies = [ "chrono", "half", "hashbrown", + "libc", "num-complex", "num-integer", "num-traits", @@ -115,26 +101,13 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arrow-ipc" -version = "59.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc41681ea80f521df14c36725b74d4c60702c47f0793af2be469c04527e2599" -dependencies = [ - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "arrow-select", - "flatbuffers", -] - [[package]] name = "arrow-schema" version = "59.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10fab8d4563491417ba801fab29d205104d20d4bdf37bda6cd1cf425cff598cd" dependencies = [ + "bitflags", "serde_core", "serde_json", ] @@ -165,12 +138,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" - [[package]] name = "base64ct" version = "1.8.3" @@ -193,27 +160,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "brotli" -version = "8.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "5.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - [[package]] name = "bumpalo" version = "3.20.3" @@ -619,16 +565,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "flatbuffers" -version = "25.12.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3" -dependencies = [ - "bitflags", - "rustc_version", -] - [[package]] name = "flate2" version = "1.1.9" @@ -666,7 +602,6 @@ dependencies = [ "ext-php-rs-build", "flow-batch-frame", "memchr", - "parquet", "serde", "serde_json", ] @@ -947,15 +882,6 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" -[[package]] -name = "lz4_flex" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecbdfe44b1bd960b68170b417450a628c43f7cf56bb3c5317e61cb230ee7f226" -dependencies = [ - "twox-hash", -] - [[package]] name = "lzma-rust2" version = "0.16.5" @@ -1130,37 +1056,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "parquet" -version = "59.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff322f54b1a0f9288e614ed1f2d329b380af5476420db19f46ffb865e1163d73" -dependencies = [ - "ahash", - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-ipc", - "arrow-schema", - "arrow-select", - "base64 0.23.1", - "brotli", - "bytes", - "chrono", - "flate2", - "half", - "hashbrown", - "lz4_flex", - "num-bigint", - "num-integer", - "num-traits", - "seq-macro", - "simdutf8", - "snap", - "twox-hash", - "zstd", -] - [[package]] name = "pbkdf2" version = "0.13.0" @@ -1305,15 +1200,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "1.1.4" @@ -1399,12 +1285,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "seq-macro" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" - [[package]] name = "serde" version = "1.0.228" @@ -1488,12 +1368,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - [[package]] name = "skeptic" version = "0.13.7" @@ -1521,12 +1395,6 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" -[[package]] -name = "snap" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "199905e6153d6405f9728fe44daace35f8f837bbf830bb6e85fbd5828709a886" - [[package]] name = "strsim" version = "0.11.1" @@ -1586,12 +1454,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "twox-hash" -version = "2.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" - [[package]] name = "typed-path" version = "0.12.3" @@ -1628,7 +1490,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" dependencies = [ - "base64 0.22.1", + "base64", "der", "flate2", "log", @@ -1646,7 +1508,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" dependencies = [ - "base64 0.22.1", + "base64", "http", "httparse", "log", diff --git a/src/extension/flow-php-ext/Cargo.toml b/src/extension/flow-php-ext/Cargo.toml index eed0c15e5a..dc9c909510 100644 --- a/src/extension/flow-php-ext/Cargo.toml +++ b/src/extension/flow-php-ext/Cargo.toml @@ -7,7 +7,7 @@ publish = false crate-type = ["cdylib"] [dependencies] -arrow-array = "59" +arrow-array = { version = "59", features = ["ffi"] } arrow-buffer = "59" arrow-data = "59" arrow-schema = { version = "59", features = ["canonical_extension_types"] } @@ -16,7 +16,6 @@ bytes = "1" ext-php-rs = "0.15" flow-batch-frame = { path = "crates/flow-batch-frame" } memchr = "2" -parquet = { version = "59", default-features = false, features = ["arrow", "arrow_canonical_extension_types", "snap", "flate2", "flate2-zlib-rs", "zstd", "lz4", "brotli", "simdutf8"] } serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["raw_value", "unbounded_depth"] } diff --git a/src/extension/flow-php-ext/Makefile b/src/extension/flow-php-ext/Makefile index f307e63ba1..11a4e308ce 100644 --- a/src/extension/flow-php-ext/Makefile +++ b/src/extension/flow-php-ext/Makefile @@ -16,6 +16,10 @@ endif CARGO_OUTPUT := target/release/libflow_php.$(LIB_EXT) EXTENSION_SO := $(MODULE_DIR)/flow_php.so +# arrow-ext's built extension: loaded before flow_php in every test run, so the Parquet ETL phpts run instead of skip +ARROW_SO ?= +LOAD_ARROW := $(if $(ARROW_SO),-d extension=$(realpath $(ARROW_SO)),) + .PHONY: all build clean test install rebuild all: build @@ -40,7 +44,7 @@ test: build sed -n '/^--SKIPIF--$$/,/^--FILE--$$/p' "$$f" | sed '1d;$$d' > "$$skipif"; \ skip_out=""; \ if [ -s "$$skipif" ]; then \ - skip_out=$$($(PHP) -d extension=$$(realpath $(EXTENSION_SO)) "$$skipif" 2>&1) || true; \ + skip_out=$$($(PHP) $(LOAD_ARROW) -d extension=$$(realpath $(EXTENSION_SO)) "$$skipif" 2>&1) || true; \ fi; \ rm -f "$$skipif"; \ case "$$skip_out" in skip*) \ @@ -50,7 +54,7 @@ test: build esac; \ sed -n '/^--FILE--$$/,/^--EXPECT/p' "$$f" | sed '1d;$$d' > "$$tmp"; \ expected=$$(sed -n '/^--EXPECT\(F\)\{0,1\}--$$/,$$p' "$$f" | sed '1d' | tr -d '\r'); \ - actual=$$($(PHP) -d extension=$$(realpath $(EXTENSION_SO)) "$$tmp" 2>&1) || true; \ + actual=$$($(PHP) $(LOAD_ARROW) -d extension=$$(realpath $(EXTENSION_SO)) "$$tmp" 2>&1) || true; \ actual=$$(printf '%s' "$$actual" | tr -d '\r'); \ rm -f "$$tmp"; \ if [ "$$actual" = "$$expected" ]; then \ diff --git a/src/extension/flow-php-ext/composer.json b/src/extension/flow-php-ext/composer.json index cf5bafa5f8..ed4d7a07ef 100644 --- a/src/extension/flow-php-ext/composer.json +++ b/src/extension/flow-php-ext/composer.json @@ -1,7 +1,7 @@ { "name": "flow-php/flow-php-ext", "type": "php-ext", - "description": "Flow PHP native extension (Rust) - native column backend, CSV reader, CSV and JSON writers, Parquet reader and writer", + "description": "Flow PHP native extension (Rust) - native column backend, CSV/JSON readers, Parquet ETL through arrow-ext", "keywords": ["serializer", "binary", "extension", "rust", "native", "dataframe"], "license": "MIT", "require": { diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs index bad14c5cb1..7bf51215c2 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs @@ -175,6 +175,7 @@ pub fn kind_of(parsed: &TypeJson) -> Result { }) } +// Must equal arrow-ext's parquet/canonical.rs canonical_type(), nested names and nullability included - pinned by phpt 091. pub fn data_type(kind: &Kind) -> DataType { match kind { Kind::Null => DataType::Null, diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php index 8bcd6f64cc..6fc732783d 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Adapter\Parquet; +use Flow\Arrow\Parquet\BatchReader; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\Parquet\Engine\Native\NativeParquetFile; use RuntimeException; use function extension_loaded; @@ -18,14 +18,13 @@ final class NativeParquetReader { /** - * @param NativeParquetFile $file the open file, whose footer plans the read - * @param Schema $schema the columns to read, in file order or a projection; every definition's type must store - * what the file's column reads as - * @param int<1, max> $batchSize + * @param BatchReader $batches arrow-ext's batches of the schema's columns + * @param Schema $schema the columns to read; every definition's type must store what the file's column reads as, + * checked here, before any batch * - * @throws \Flow\ETL\Exception\InvalidArgumentException for a negative $offset or $limit + * @throws \Flow\ETL\Exception\InvalidArgumentException for a column whose type stores something else */ - public function __construct(NativeParquetFile $file, Schema $schema, int $batchSize, ?int $offset, ?int $limit) + public function __construct(BatchReader $batches, Schema $schema) { throw new RuntimeException('flow_php extension is not loaded'); } @@ -36,7 +35,7 @@ public function close(): void } /** - * The next batch of at most $batchSize rows under the schema, null after the last. + * The next batch under the schema, null after the last. */ public function next(): ?Rows { diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php index 49fea56280..1079df5a87 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Adapter\Parquet; +use Flow\Arrow\Parquet\RowsWriter; use Flow\ETL\Rows; -use Flow\Filesystem\DestinationStream; use RuntimeException; use function extension_loaded; @@ -17,21 +17,23 @@ final class NativeParquetWriter { /** - * @param array $schema Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension() - * @param array $options Flow\Parquet\Engine\Arrow\OptionsConverter::toExtension() + * @param RowsWriter $writer arrow-ext's writer, which owns the stream */ - public function __construct(DestinationStream $stream, array $schema, string $compression, array $options) + public function __construct(RowsWriter $writer) { throw new RuntimeException('flow_php extension is not loaded'); } + /** + * The writer's buffered rows, the footer, then the stream closed. + */ public function close(): void { throw new RuntimeException('flow_php extension is not loaded'); } /** - * The writer schema's columns by name; a column the rows lack is written as nulls. + * Every column of the rows as one Arrow C Data batch; a writer column the rows lack is written as nulls. */ public function write(Rows $rows): void { diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Column/NativeArrowBatch.php b/src/extension/flow-php-ext/php/Flow/ETL/Column/NativeArrowBatch.php new file mode 100644 index 0000000000..82c15de2c8 --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/ETL/Column/NativeArrowBatch.php @@ -0,0 +1,46 @@ + i64 { + IMPORTED.load(Ordering::Relaxed) +} + /// Process-wide: on ZTS every thread's allocations. pub fn allocated_bytes() -> i64 { - ALLOCATED.load(Ordering::Relaxed) + ALLOCATED.load(Ordering::Relaxed) + IMPORTED.load(Ordering::Relaxed) } diff --git a/src/extension/flow-php-ext/src/arrow_c.rs b/src/extension/flow-php-ext/src/arrow_c.rs new file mode 100644 index 0000000000..697fc88fe7 --- /dev/null +++ b/src/extension/flow-php-ext/src/arrow_c.rs @@ -0,0 +1,429 @@ +//! Batches across the Arrow C Data Interface, to and from another extension (arrow-ext): one batch = one struct-typed +//! `FFI_ArrowSchema` (one child per column) plus one struct-typed `FFI_ArrowArray`. Any extension's internal class +//! exposing the two addresses is accepted. An import moves the producer's array behind a release forwarder that counts +//! its buffers in `allocatedBytes()` for as long as they live. + +use std::ffi::{c_char, CStr}; +use std::rc::Rc; + +use arrow_array::ffi::{from_ffi, to_ffi, FFI_ArrowArray, FFI_ArrowSchema}; +use arrow_array::{Array, ArrayRef, StructArray}; +use arrow_schema::{ArrowError, DataType, Field, Fields}; +use ext_php_rs::exception::PhpException; +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::{ZendObject, Zval}; +use ext_php_rs::zend::ClassEntry; +use flow_batch_frame::kind::data_type; + +use crate::alloc; +use crate::ctx::{call_handle_transparent, call_method, ce_method_ref}; +use crate::plan::TypePlan; +use crate::render::invalid_argument; + +/// Child field metadata: the arrow type of the file column the canonical child was read from. +const SOURCE_TYPE: &str = "parquet.source_type"; + +/// `ZEND_INTERNAL_CLASS` (zend_compile.h): a class an extension registered, which userland can neither declare nor +/// extend once final. +const ZEND_INTERNAL_CLASS: c_char = 1; + +/// One exported batch, until its consumer moves the array out. +#[php_class] +#[php(name = "Flow\\ETL\\Column\\NativeArrowBatch", flags = ClassFlags::Final)] +pub struct NativeArrowBatch { + schema: FFI_ArrowSchema, + array: FFI_ArrowArray, + rows: usize, +} + +#[php_impl] +impl NativeArrowBatch { + pub fn count(&self) -> i64 { + self.rows as i64 + } + + #[php(name = "arrowSchemaAddress")] + pub fn arrow_schema_address(&self) -> i64 { + std::ptr::from_ref(&self.schema) as i64 + } + + #[php(name = "arrowArrayAddress")] + pub fn arrow_array_address(&self) -> i64 { + std::ptr::from_ref(&self.array) as i64 + } +} + +/// What an import refuses; nothing was taken from the producer. +#[derive(Debug)] +enum Refusal { + NotStruct, + Count { children: i64, columns: usize }, + Name { child: String, column: usize }, + /// Column `column` arrives as `child`, which its plan does not store. + Type { column: usize, child: Field }, + Schema(ArrowError), + Released, + Length { children: i64, schema: i64 }, + Invalid(ArrowError), +} + +/// The struct schema `schema`, its children named and typed as `columns` (name, stored type) are. +fn check(schema: &FFI_ArrowSchema, columns: &[(&[u8], DataType)]) -> Result<(), Refusal> { + if schema.format.is_null() || unsafe { CStr::from_ptr(schema.format) }.to_bytes() != b"+s" { + return Err(Refusal::NotStruct); + } + + if schema.n_children != columns.len() as i64 { + return Err(Refusal::Count { + children: schema.n_children, + columns: columns.len(), + }); + } + + for (column, (child, (name, stored))) in schema.children().zip(columns).enumerate() { + let child = Field::try_from(child).map_err(Refusal::Schema)?; + + if child.name().as_bytes() != *name { + return Err(Refusal::Name { + child: child.name().clone(), + column, + }); + } + + if child.data_type() != stored { + return Err(Refusal::Type { column, child }); + } + } + + Ok(()) +} + +/// An imported array: the producer's, moved here, and the bytes it counts while arrow-rs holds its buffers. +struct Counted { + inner: FFI_ArrowArray, + bytes: i64, +} + +/// The forwarder's release: arrow-rs calls it once, when the batch's last buffer drops; dropping `inner` runs the +/// producer's release. +unsafe extern "C" fn counted_release(array: *mut FFI_ArrowArray) { + let Some(array) = (unsafe { array.as_mut() }) else { + return; + }; + let Counted { inner, bytes } = *unsafe { Box::from_raw(array.private_data.cast::()) }; + + alloc::imported(-bytes); + drop(inner); + array.release = None; +} + +/// `source` moved out (its release left NULL) behind the counting forwarder, as the struct `schema` describes, after +/// [`check`]: the row count and one array per column. A refusal before the move takes nothing; after it the forwarder +/// owns the producer's array and releases it. +fn take( + schema: &FFI_ArrowSchema, + source: &mut FFI_ArrowArray, + columns: &[(&[u8], DataType)], +) -> Result<(usize, Vec), Refusal> { + check(schema, columns)?; + + if source.release.is_none() { + return Err(Refusal::Released); + } + + if source.n_children != schema.n_children || source.length < 0 { + return Err(Refusal::Length { + children: source.n_children, + schema: schema.n_children, + }); + } + + let moved = unsafe { std::ptr::read(source) }; + source.release = None; + + let counted = Box::into_raw(Box::new(Counted { inner: moved, bytes: 0 })); + let inner = unsafe { &(*counted).inner }; + let forward = FFI_ArrowArray { + length: inner.length, + null_count: inner.null_count, + offset: inner.offset, + n_buffers: inner.n_buffers, + n_children: inner.n_children, + buffers: inner.buffers, + children: inner.children, + dictionary: inner.dictionary, + release: Some(counted_release), + private_data: counted.cast(), + }; + + let data = unsafe { from_ffi(forward, schema) } + .and_then(|data| data.validate().map(|()| data)) + .map_err(Refusal::Invalid)?; + let bytes = data.get_buffer_memory_size() as i64; + + // the forwarder lives in arrow-rs's owner of `data`'s buffers, so `counted` does too + unsafe { (*counted).bytes = bytes }; + alloc::imported(bytes); + + let batch = StructArray::from(data); + + Ok((batch.len(), batch.into_parts().1)) +} + +fn refused(refusal: Refusal, columns: &[(Vec, Rc)]) -> PhpException { + let message = match refusal { + Refusal::NotStruct => "Arrow C Data batch must be a struct".to_string(), + Refusal::Count { children, columns } => { + format!("Arrow C Data batch of {children} children does not match the {columns} columns read") + } + Refusal::Name { child, column } => format!( + "Arrow C Data batch child \"{child}\" is not the column \"{}\"", + String::from_utf8_lossy(&columns[column].0) + ), + Refusal::Type { column, child } => { + let (name, plan) = &columns[column]; + let type_name = match call_method(&plan.type_zv, "toString", &mut []) { + Ok(type_name) => type_name, + Err(exception) => return exception, + }; + + format!( + "Parquet column \"{}\" ({}) is read as {}, its schema type {} stores {}", + String::from_utf8_lossy(name), + child.metadata().get(SOURCE_TYPE).map_or("", String::as_str), + child.data_type(), + String::from_utf8_lossy(type_name.zend_str().map_or(&b""[..], |name| name.as_bytes())), + data_type(&plan.kind), + ) + } + Refusal::Schema(error) => format!("Arrow C Data schema is refused: {error}"), + Refusal::Released => "Arrow C Data batch is already imported".to_string(), + Refusal::Length { children, schema } => { + format!("Arrow C Data batch of {children} children does not match its schema of {schema}") + } + Refusal::Invalid(error) => format!("Arrow C Data batch is not a valid struct array: {error}"), + }; + + invalid_argument(message) +} + +/// The object of an exporter's internal class. +fn exporter(carrier: &Zval) -> PhpResult<(&ZendObject, &ClassEntry)> { + let object = carrier + .object() + .ok_or_else(|| invalid_argument("Arrow C Data carrier must be an object".to_string()))?; + let ce = unsafe { object.ce.as_ref() } + .ok_or_else(|| invalid_argument("Arrow C Data carrier has no class".to_string()))?; + + if ce.type_ != ZEND_INTERNAL_CLASS { + return Err(invalid_argument(format!( + "Arrow C Data carrier must be an extension's class, got {}", + ce.name().unwrap_or_default() + ))); + } + + Ok((object, ce)) +} + +/// `$object->$method()` of an address method: a pointer the exporter owns. +fn address(object: &ZendObject, ce: &ClassEntry, method: &str) -> PhpResult { + let address = call_handle_transparent(ce_method_ref(ce, method)?, Some(object), &mut [])?; + + address + .long() + .and_then(|address| usize::try_from(address).ok()) + .filter(|address| *address != 0) + .ok_or_else(|| invalid_argument(format!("Arrow C Data {method}() must return a non-null address"))) +} + +fn stored(columns: &[(Vec, Rc)]) -> Vec<(&[u8], DataType)> { + columns.iter().map(|(name, plan)| (name.as_slice(), data_type(&plan.kind))).collect() +} + +/// Refuses a schema carrier (`arrowSchemaAddress()`) whose struct children are not `columns`, by name and stored type. +pub fn check_schema(schema: &Zval, columns: &[(Vec, Rc)]) -> PhpResult<()> { + let (object, ce) = exporter(schema)?; + let schema = unsafe { &*(address(object, ce, "arrowSchemaAddress")? as *const FFI_ArrowSchema) }; + + check(schema, &stored(columns)).map_err(|refusal| refused(refusal, columns)) +} + +/// The batch `batch` carries (`arrowSchemaAddress()` read by reference, `arrowArrayAddress()` moved): the row count +/// and one array per column of `columns`. +pub fn import(batch: &Zval, columns: &[(Vec, Rc)]) -> PhpResult<(usize, Vec)> { + let (object, ce) = exporter(batch)?; + let schema = unsafe { &*(address(object, ce, "arrowSchemaAddress")? as *const FFI_ArrowSchema) }; + let source = unsafe { &mut *(address(object, ce, "arrowArrayAddress")? as *mut FFI_ArrowArray) }; + + take(schema, source, &stored(columns)).map_err(|refusal| refused(refusal, columns)) +} + +/// `columns` as one struct batch of `rows` rows, every child nullable. +pub fn export(rows: usize, columns: Vec<(String, ArrayRef)>) -> PhpResult { + let fields = columns + .iter() + .map(|(name, array)| Field::new(name, array.data_type().clone(), true)) + .collect::(); + let arrays = columns.into_iter().map(|(_, array)| array).collect(); + let (array, schema) = StructArray::try_new_with_length(fields, arrays, None, rows) + .and_then(|batch| to_ffi(&batch.to_data())) + .map_err(|error| invalid_argument(format!("flow_php failed to export an Arrow C Data batch: {error}")))?; + + Ok(NativeArrowBatch { schema, array, rows }) +} + +#[cfg(test)] +mod tests { + use std::ffi::c_void; + use std::sync::atomic::{AtomicUsize, Ordering}; + use std::sync::{Arc, Mutex}; + + use arrow_array::ffi::{to_ffi, FFI_ArrowArray, FFI_ArrowSchema}; + use arrow_array::types::Int64Type; + use arrow_array::{Array, ArrayRef, Int64Array, ListArray, StructArray}; + use arrow_schema::{DataType, Field, Fields}; + + use super::{take, Refusal}; + use crate::alloc; + + /// `IMPORTED` is process-wide: the tests that import run one at a time. + static SERIAL: Mutex<()> = Mutex::new(()); + + static RELEASES: AtomicUsize = AtomicUsize::new(0); + + /// The producer: arrow-rs's export, wrapped so its release counts how often it ran. + unsafe extern "C" fn counting_release(array: *mut FFI_ArrowArray) { + let array = unsafe { &mut *array }; + drop(unsafe { Box::from_raw(array.private_data.cast::()) }); + array.release = None; + RELEASES.fetch_add(1, Ordering::SeqCst); + } + + fn columns() -> Vec<(String, ArrayRef)> { + vec![ + ( + "id".to_string(), + Arc::new(Int64Array::from_iter((0..1000).map(|i| (i % 3 != 0).then_some(i)))) as ArrayRef, + ), + ( + "list".to_string(), + Arc::new(ListArray::from_iter_primitive::( + (0..1000).map(|i| (i % 5 != 0).then(|| vec![Some(i), None])), + )) as ArrayRef, + ), + ] + } + + fn produced() -> (FFI_ArrowArray, FFI_ArrowSchema) { + let fields = columns() + .iter() + .map(|(name, array)| Field::new(name, array.data_type().clone(), true)) + .collect::(); + let batch = StructArray::new(fields, columns().into_iter().map(|(_, array)| array).collect(), None); + let (inner, schema) = to_ffi(&batch.to_data()).unwrap(); + let inner = Box::into_raw(Box::new(inner)); + let exported = unsafe { &*inner }; + let array = FFI_ArrowArray { + length: exported.length, + null_count: exported.null_count, + offset: exported.offset, + n_buffers: exported.n_buffers, + n_children: exported.n_children, + buffers: exported.buffers, + children: exported.children, + dictionary: exported.dictionary, + release: Some(counting_release), + private_data: inner.cast::(), + }; + + (array, schema) + } + + fn expected() -> Vec<(&'static [u8], DataType)> { + vec![(b"id", DataType::Int64), (b"list", columns()[1].1.data_type().clone())] + } + + fn imported() -> i64 { + alloc::imported_bytes() + } + + #[test] + fn an_imported_batch_counts_its_buffers_until_the_last_one_drops() { + let _serial = SERIAL.lock().unwrap(); + let (mut array, schema) = produced(); + let releases = RELEASES.load(Ordering::SeqCst); + + let (rows, arrays) = take(&schema, &mut array, &expected()).unwrap(); + + assert!(array.release.is_none()); + assert_eq!(rows, 1000); + assert_eq!(arrays.len(), 2); + assert_eq!(arrays[0].as_ref(), columns()[0].1.as_ref()); + assert_eq!(arrays[1].as_ref(), columns()[1].1.as_ref()); + assert_eq!( + imported(), + arrays.iter().map(|array| array.to_data().get_buffer_memory_size() as i64).sum::() + ); + + let first = arrays.into_iter().next().unwrap(); + assert!(imported() > 0); + assert_eq!(RELEASES.load(Ordering::SeqCst), releases); + + drop(first); + assert_eq!(imported(), 0); + assert_eq!(RELEASES.load(Ordering::SeqCst), releases + 1); + + drop(array); + drop(schema); + assert_eq!(RELEASES.load(Ordering::SeqCst), releases + 1); + } + + fn refused(columns: &[(&[u8], DataType)], refusal: impl Fn(&Refusal) -> bool) { + let _serial = SERIAL.lock().unwrap(); + let (mut array, schema) = produced(); + let releases = RELEASES.load(Ordering::SeqCst); + + assert!(refusal(&take(&schema, &mut array, columns).unwrap_err())); + assert_eq!(imported(), 0); + assert!(array.release.is_some()); + assert_eq!(RELEASES.load(Ordering::SeqCst), releases); + + drop(array); + assert_eq!(RELEASES.load(Ordering::SeqCst), releases + 1); + } + + #[test] + fn a_child_of_another_type_is_refused_before_the_move() { + refused(&[(b"id", DataType::Float64), (b"list", expected()[1].1.clone())], |refusal| { + matches!(refusal, Refusal::Type { column: 0, .. }) + }); + } + + #[test] + fn a_child_of_another_name_is_refused_before_the_move() { + refused(&[(b"id", DataType::Int64), (b"other", expected()[1].1.clone())], |refusal| { + matches!(refusal, Refusal::Name { column: 1, .. }) + }); + } + + #[test] + fn another_child_count_is_refused_before_the_move() { + refused(&[(b"id", DataType::Int64)], |refusal| matches!(refusal, Refusal::Count { children: 2, columns: 1 })); + } + + #[test] + fn an_already_imported_batch_is_refused() { + let _serial = SERIAL.lock().unwrap(); + let (mut array, schema) = produced(); + + let (_, arrays) = take(&schema, &mut array, &expected()).unwrap(); + let counted = imported(); + + assert!(matches!(take(&schema, &mut array, &expected()).unwrap_err(), Refusal::Released)); + assert_eq!(imported(), counted); + + drop(arrays); + assert_eq!(imported(), 0); + } +} diff --git a/src/extension/flow-php-ext/src/ctx.rs b/src/extension/flow-php-ext/src/ctx.rs index c68fe59cae..59aa6a5bdc 100644 --- a/src/extension/flow-php-ext/src/ctx.rs +++ b/src/extension/flow-php-ext/src/ctx.rs @@ -17,7 +17,6 @@ use ext_php_rs::zend::{ClassEntry, ExecutorGlobals, Function}; use crate::exception::ext_exception; use crate::globals::with_ctx; use crate::plan::TypePlan; -use crate::thrift::Specs; /// PHP array-key coercion (`_zend_handle_numeric_str`): parse + canonical /// re-format equality rejects "+5", "-0", leading zeros and whitespace exactly @@ -405,8 +404,6 @@ pub struct Ctx { plans: HashMap, Rc>, /// `plans` by Type object handle; each entry holds its object, so the handle is not reused while cached. type_plans: HashMap)>, - /// The `$_TSPEC`s reachable from a root thrift class, by that class. - thrift_specs: HashMap>, } /// Type objects `type_plans` holds before it starts over. @@ -500,17 +497,6 @@ pub fn store_type_plan(type_zv: &Zval, plan: &Rc) -> Result<(), PhpExc Ok(()) } -pub fn thrift_specs(class: &str) -> Result>, PhpException> { - with_ctx(|ctx| Ok(ctx.thrift_specs.get(class).cloned())) -} - -pub fn store_thrift_specs(class: &str, specs: &Rc) -> Result<(), PhpException> { - with_ctx(|ctx| { - ctx.thrift_specs.insert(class.to_string(), Rc::clone(specs)); - Ok(()) - }) -} - /// A cached handle: read inside the context, resolved outside it on a miss, then stored. fn cached( read: impl FnOnce(&Ctx) -> Option, diff --git a/src/extension/flow-php-ext/src/lib.rs b/src/extension/flow-php-ext/src/lib.rs index 22ef464290..de80b7cfa8 100644 --- a/src/extension/flow-php-ext/src/lib.rs +++ b/src/extension/flow-php-ext/src/lib.rs @@ -1,4 +1,5 @@ mod alloc; +mod arrow_c; mod backend; mod batch_columns; mod builder; @@ -18,7 +19,6 @@ mod physical; mod plan; mod render; mod text; -mod thrift; mod uuid_check; mod values; @@ -194,7 +194,5 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { .class::() .class::() .class::() - .class::() - .class::() - .class::() + .class::() } diff --git a/src/extension/flow-php-ext/src/parquet/cells.rs b/src/extension/flow-php-ext/src/parquet/cells.rs deleted file mode 100644 index f1e8c1fefd..0000000000 --- a/src/extension/flow-php-ext/src/parquet/cells.rs +++ /dev/null @@ -1,683 +0,0 @@ -//! The `Flow\Parquet` lib's per-cell values over the core's canonical arrays: what `PhpParquetEngine` returns for a -//! Parquet value on read, and what it accepts per target type on write. - -use arrow_array::cast::AsArray; -use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; -use arrow_array::{make_array, Array, ArrayRef}; -use arrow_schema::{DataType, Field}; -use ext_php_rs::exception::PhpException; -use ext_php_rs::types::{ZendHashTable, ZendObject, Zval}; -use ext_php_rs::zend::{ClassEntry, Function}; -use flow_batch_frame::kind::{Field as KindField, Kind}; - -use crate::ctx::{ - call_handle_transparent, ce_method_ref, find_class, ht_for_each, ht_get, ht_insert, ht_insert_long, - read_property, zval_long, zval_str, -}; -use crate::exception::ext_exception; -use crate::kind_builder::KindBuilder; -use crate::parquet::error::Error; -use crate::values::{date_from_days, datetime_days, datetime_from_micros, datetime_micros, uuid_bytes, uuid_text}; - -const UUID: &str = "arrow.uuid"; - -fn is_uuid(field: &Field) -> bool { - field.extension_type_name() == Some(UUID) -} - -fn unsupported(data_type: &DataType) -> Error { - Error::Unsupported { - column: String::new(), - parquet: data_type.to_string(), - } -} - -fn collected(error: impl std::fmt::Debug) -> PhpException { - ext_exception(format!("flow_php failed to collect a Parquet value: {error:?}")) -} - -/// How a canonical array's values become PHP values, per `PhpParquetEngine`. -pub enum ReadCell { - Null, - Bool, - Int, - Float, - Bytes, - /// `FixedSizeBinary(16)` under `arrow.uuid`: the lowercase 36-char text. - Uuid, - Date, - Timestamp, - Time, - List(Box), - Map(Box, Box), - Struct(Vec<(Vec, ReadCell)>), -} - -impl ReadCell { - /// `canonical`: the type the core reads the column as; `parquet`: the field it was read from (its extension type - /// tells a uuid from 16 bytes), walked in parallel with the canonical type's children. - pub fn new(canonical: &DataType, parquet: &Field) -> Result { - Ok(match canonical { - DataType::Null => ReadCell::Null, - DataType::Boolean => ReadCell::Bool, - DataType::Int64 => ReadCell::Int, - DataType::Float64 => ReadCell::Float, - DataType::Binary => ReadCell::Bytes, - DataType::FixedSizeBinary(16) if is_uuid(parquet) => ReadCell::Uuid, - DataType::FixedSizeBinary(16) => ReadCell::Bytes, - DataType::Date32 => ReadCell::Date, - DataType::Timestamp(_, _) => ReadCell::Timestamp, - DataType::Duration(_) => ReadCell::Time, - DataType::List(element) => ReadCell::List(Box::new(Self::new(element.data_type(), child(parquet, 0)?)?)), - DataType::Map(entries, _) => { - let DataType::Struct(fields) = entries.data_type() else { - return Err(unsupported(canonical)); - }; - let parquet_entries = child(parquet, 0)?; - let key = Self::new(fields[0].data_type(), child(parquet_entries, 0)?)?; - - if !matches!(key, ReadCell::Int | ReadCell::Bytes | ReadCell::Uuid) { - return Err(Error::MapKey { - column: String::new(), - key: key.php_type(), - }); - } - - ReadCell::Map( - Box::new(key), - Box::new(Self::new(fields[1].data_type(), child(parquet_entries, 1)?)?), - ) - } - DataType::Struct(fields) => ReadCell::Struct( - fields - .iter() - .enumerate() - .map(|(index, field)| { - Ok((field.name().as_bytes().to_vec(), Self::new(field.data_type(), child(parquet, index)?)?)) - }) - .collect::>()?, - ), - other => return Err(unsupported(other)), - }) - } - - /// The PHP type this cell's values have: what a MAP key refusal names. - fn php_type(&self) -> &'static str { - match self { - ReadCell::Null => "null", - ReadCell::Bool => "bool", - ReadCell::Int => "int", - ReadCell::Float => "float", - ReadCell::Bytes | ReadCell::Uuid => "string", - ReadCell::Date | ReadCell::Timestamp => "DateTimeImmutable", - ReadCell::Time => "DateInterval", - ReadCell::List(_) | ReadCell::Map(_, _) | ReadCell::Struct(_) => "array", - } - } - - pub fn needs_times(&self) -> bool { - match self { - ReadCell::Time => true, - ReadCell::List(element) => element.needs_times(), - ReadCell::Map(key, value) => key.needs_times() || value.needs_times(), - ReadCell::Struct(children) => children.iter().any(|(_, child)| child.needs_times()), - _ => false, - } - } - - /// Every value of `array` as a PHP list. - pub fn values(&self, array: &ArrayRef, times: Option<&Times>) -> Result { - let mut list = ZendHashTable::with_capacity(u32::try_from(array.len()).unwrap_or(u32::MAX)); - - for row in 0..array.len() { - list.push(self.value(array.as_ref(), row, times)?).map_err(collected)?; - } - - let mut zv = Zval::new(); - zv.set_hashtable(list); - - Ok(zv) - } - - fn value(&self, array: &dyn Array, row: usize, times: Option<&Times>) -> Result { - let mut zv = Zval::new(); - - if array.is_null(row) { - return Ok(zv); - } - - match self { - ReadCell::Null => {} - ReadCell::Bool => zv.set_bool(array.as_boolean().value(row)), - ReadCell::Int => zv = zval_long(array.as_primitive::().value(row)), - ReadCell::Float => zv.set_double(array.as_primitive::().value(row)), - ReadCell::Bytes => { - zv = zval_str(match array.data_type() { - DataType::FixedSizeBinary(_) => array.as_fixed_size_binary().value(row), - _ => array.as_binary::().value(row), - }); - } - ReadCell::Uuid => zv = zval_str(&uuid_text(array.as_fixed_size_binary().value(row))), - ReadCell::Date => zv = date_from_days(i64::from(array.as_primitive::().value(row)))?, - ReadCell::Timestamp => { - zv = datetime_from_micros(array.as_primitive::().value(row), b"+00:00")?; - } - ReadCell::Time => { - zv = times - .ok_or_else(|| ext_exception("flow_php Parquet reader has no TIME base"))? - .interval(array.as_primitive::().value(row))?; - } - ReadCell::List(element) => { - let list = array.as_list::(); - let offsets = list.value_offsets(); - let mut values = ZendHashTable::with_capacity((offsets[row + 1] - offsets[row]) as u32); - - for index in offsets[row] as usize..offsets[row + 1] as usize { - values.push(element.value(list.values().as_ref(), index, times)?).map_err(collected)?; - } - - zv.set_hashtable(values); - } - ReadCell::Map(key, value) => { - let map = array.as_map(); - let offsets = map.value_offsets(); - let mut entries = ZendHashTable::with_capacity((offsets[row + 1] - offsets[row]) as u32); - - for index in offsets[row] as usize..offsets[row + 1] as usize { - let entry = value.value(map.values().as_ref(), index, times)?; - - match key.value(map.keys().as_ref(), index, times)? { - k if k.is_long() => ht_insert_long(&mut entries, k.long().unwrap_or_default(), entry), - k => ht_insert(&mut entries, k.zend_str().map_or(&b""[..], |key| key.as_bytes()), entry), - } - } - - zv.set_hashtable(entries); - } - ReadCell::Struct(children) => { - let structure = array.as_struct(); - let mut values = ZendHashTable::with_capacity(children.len() as u32); - - for ((name, child), column) in children.iter().zip(structure.columns()) { - ht_insert(&mut values, name, child.value(column.as_ref(), row, times)?); - } - - zv.set_hashtable(values); - } - } - - Ok(zv) - } -} - -/// Child `index` of a nested Parquet-side field. -fn child(parquet: &Field, index: usize) -> Result<&Field, Error> { - match parquet.data_type() { - DataType::List(element) | DataType::LargeList(element) | DataType::FixedSizeList(element, _) if index == 0 => { - Ok(element) - } - DataType::Map(entries, _) if index == 0 => Ok(entries), - DataType::Struct(fields) if index < fields.len() => Ok(&fields[index]), - other => Err(unsupported(other)), - } -} - -/// `TimeConverter::toDateInterval()`: `$base->diff($base->modify("+{µs} microseconds"))` - `diff()` normalises the -/// duration into d/h and, past a month, m/d exactly as the PHP engine's value. A time of day (< 24 h) normalises into -/// nothing, so it is built directly with `DateInterval::__set_state()`, one call instead of two. -pub struct Times { - base: Zval, - modify: &'static Function, - diff: &'static Function, - set_state: &'static Function, -} - -const DAY: i64 = 86_400_000_000; - -impl Times { - /// `$base = new DateTimeImmutable('1970-01-01 00:00:00.000000', new DateTimeZone('UTC'))`, built once per reader. - pub fn new() -> Result { - let ce = find_class("DateTimeImmutable")?; - - Ok(Self { - base: datetime_from_micros(0, b"UTC")?, - modify: ce_method_ref(ce, "modify")?, - diff: ce_method_ref(ce, "diff")?, - set_state: ce_method_ref(find_class("DateInterval")?, "__set_state")?, - }) - } - - fn interval(&self, micros: i64) -> Result { - if (0..DAY).contains(µs) { - return self.time_of_day(micros); - } - - let base = self.base.object().ok_or_else(|| ext_exception("flow_php expected a TIME base datetime"))?; - let target = call_handle_transparent( - self.modify, - Some(base), - &mut [zval_str(format!("+{micros} microseconds").as_bytes())], - )?; - - call_handle_transparent(self.diff, Some(base), &mut [target]) - } - - /// `diff()`'s interval of a time of day: `days` 0, `f` from the whole microseconds. - fn time_of_day(&self, micros: i64) -> Result { - let mut state = ZendHashTable::with_capacity(10); - let double = |value: f64| { - let mut zv = Zval::new(); - zv.set_double(value); - zv - }; - - for (name, value) in [ - ("y", 0), - ("m", 0), - ("d", 0), - ("h", micros / 3_600_000_000), - ("i", micros / 60_000_000 % 60), - ("s", micros / 1_000_000 % 60), - ] { - ht_insert(&mut state, name.as_bytes(), zval_long(value)); - } - - // __set_state() stores `f` as (int) (f * 1e6): the half microsecond keeps the truncation on the exact value - // (0.519488 * 1e6 = 519487.99…), and `f` reads back as that value / 1e6, as diff()'s does - ht_insert(&mut state, b"f", double(((micros % 1_000_000) as f64 + 0.5) / 1_000_000.0)); - ht_insert(&mut state, b"invert", zval_long(0)); - ht_insert(&mut state, b"days", zval_long(0)); - let mut from_string = Zval::new(); - from_string.set_bool(false); - ht_insert(&mut state, b"from_string", from_string); - - let mut array = Zval::new(); - array.set_hashtable(state); - - call_handle_transparent(self.set_state, None, &mut [array]) - } -} - -/// A value `WriteCell::append` refuses. -pub enum Refusal { - /// What the target type accepts and what it got. - Value { expected: &'static str, got: String }, - /// A byte buffer past i32 offsets, or a day past i32. - Overflow, - /// A PHP exception a call into the value threw. - Php(PhpException), -} - -impl From for Refusal { - fn from(exception: PhpException) -> Self { - Refusal::Php(exception) - } -} - -/// `get_debug_type()`. -fn debug_type(value: &Zval) -> String { - if value.is_null() { - "null".to_string() - } else if value.is_bool() { - "bool".to_string() - } else if value.is_long() { - "int".to_string() - } else if value.is_double() { - "float".to_string() - } else if value.is_string() { - "string".to_string() - } else if value.is_array() { - "array".to_string() - } else if let Some(object) = value.object() { - object.get_class_name().unwrap_or_else(|_| "object".to_string()) - } else { - "unknown".to_string() - } -} - -fn refused(expected: &'static str, value: &Zval) -> Refusal { - Refusal::Value { - expected, - got: debug_type(value), - } -} - -/// The classes the write cells test instances of, resolved once per writer. -pub struct Classes { - datetime: &'static ClassEntry, - interval: &'static ClassEntry, -} - -impl Classes { - pub fn new() -> Result { - Ok(Self { - datetime: find_class("DateTimeInterface")?, - interval: find_class("DateInterval")?, - }) - } -} - -/// What a writer column accepts per `PhpParquetEngine`'s target type, appended to its canonical kind's builder; the -/// cast to the Parquet type (`to_parquet`) refuses what is out of the target's range. -pub enum WriteCell { - Bool, - Int, - Float, - /// DECIMAL: a float or an int. - Decimal, - Bytes, - /// UUID: a string, or an object's `toString()` / `__toString()`, whose dash-less text is 32 hex digits. - Uuid, - Date, - Timestamp, - Time, - List(Box, bool), - Map(Box, Box, bool), - Struct(Vec<(Vec, WriteCell, bool)>), -} - -impl WriteCell { - /// The cell for a writer schema field (`Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension()`), and the - /// canonical kind its values are built in. - pub fn new(target: &Field) -> Result<(Self, Kind), Error> { - Ok(match target.data_type() { - DataType::Boolean => (WriteCell::Bool, Kind::Boolean), - DataType::Int8 - | DataType::Int16 - | DataType::Int32 - | DataType::Int64 - | DataType::UInt8 - | DataType::UInt16 - | DataType::UInt32 - | DataType::UInt64 => (WriteCell::Int, Kind::Int64), - DataType::Float32 | DataType::Float64 => (WriteCell::Float, Kind::Float64), - DataType::Decimal128(_, _) => (WriteCell::Decimal, Kind::Float64), - DataType::Utf8 | DataType::Binary => (WriteCell::Bytes, Kind::Bytes), - DataType::FixedSizeBinary(16) if is_uuid(target) => (WriteCell::Uuid, Kind::Uuid), - DataType::FixedSizeBinary(_) => (WriteCell::Bytes, Kind::Bytes), - DataType::Date32 => (WriteCell::Date, Kind::Int32), - DataType::Timestamp(_, _) => (WriteCell::Timestamp, Kind::Timestamp), - DataType::Time32(_) | DataType::Time64(_) => (WriteCell::Time, Kind::Duration), - DataType::List(element) => { - let (cell, kind) = Self::new(element)?; - - ( - WriteCell::List(Box::new(cell), element.is_nullable()), - Kind::List(Box::new(KindField { - name: element.name().clone(), - kind, - optional: element.is_nullable(), - })), - ) - } - DataType::Map(entries, _) => { - let DataType::Struct(fields) = entries.data_type() else { - return Err(unsupported(target.data_type())); - }; - let (key, key_kind) = Self::new(&fields[0])?; - let (value, value_kind) = Self::new(&fields[1])?; - - ( - WriteCell::Map(Box::new(key), Box::new(value), fields[1].is_nullable()), - Kind::Map( - Box::new(KindField { - name: fields[0].name().clone(), - kind: key_kind, - optional: false, - }), - Box::new(KindField { - name: fields[1].name().clone(), - kind: value_kind, - optional: fields[1].is_nullable(), - }), - ), - ) - } - DataType::Struct(fields) => { - let mut cells = Vec::with_capacity(fields.len()); - let mut kinds = Vec::with_capacity(fields.len()); - - for field in fields { - let (cell, kind) = Self::new(field)?; - cells.push((field.name().as_bytes().to_vec(), cell, field.is_nullable())); - kinds.push(KindField { - name: field.name().clone(), - kind, - optional: field.is_nullable(), - }); - } - - (WriteCell::Struct(cells), Kind::Struct(kinds)) - } - other => return Err(unsupported(other)), - }) - } - - /// `value` appended to `builder`; a null only where `nullable`. - pub fn append(&self, builder: &mut KindBuilder, value: &Zval, nullable: bool, classes: &Classes) -> Result<(), Refusal> { - let value = value.dereference(); - - if value.is_null() { - if !nullable { - return Err(refused("a value", value)); - } - - builder.append_null(); - - return Ok(()); - } - - match self { - WriteCell::Bool => builder.append_bool(value.bool().ok_or_else(|| refused("bool", value))?), - WriteCell::Int => builder.append_fixed(&value.long().ok_or_else(|| refused("int", value))?.to_le_bytes()), - WriteCell::Float => { - builder.append_fixed(&value.double().ok_or_else(|| refused("float", value))?.to_le_bytes()); - } - WriteCell::Decimal => { - let float = match (value.double(), value.long()) { - (Some(float), _) => float, - (_, Some(int)) => int as f64, - _ => return Err(refused("float or int", value)), - }; - builder.append_fixed(&float.to_le_bytes()); - } - WriteCell::Bytes => { - let bytes = value.zend_str().ok_or_else(|| refused("string", value))?; - builder.append_bytes(bytes.as_bytes()).map_err(|_| Refusal::Overflow)?; - } - WriteCell::Uuid => { - let text = match value.object() { - Some(object) => uuid_text_of(object)?.ok_or_else(|| refused("uuid string or object", value))?, - None => value.shallow_clone(), - }; - let bytes = text - .zend_str() - .and_then(|text| uuid_bytes(text.as_bytes())) - .ok_or_else(|| refused("uuid string or object", value))?; - builder.append_fixed(&bytes); - } - WriteCell::Date => { - let datetime = datetime(value, classes).ok_or_else(|| refused("DateTimeInterface", value))?; - let days = match datetime_days(datetime) { - Some(days) => days, - None => fallback_days(datetime)?, - }; - let days = i32::try_from(days).map_err(|_| Refusal::Overflow)?; - builder.append_fixed(&days.to_le_bytes()); - } - WriteCell::Timestamp => { - let datetime = datetime(value, classes).ok_or_else(|| refused("DateTimeInterface", value))?; - let micros = match datetime_micros(datetime) { - Some(micros) => micros, - None => fallback_micros(datetime)?, - }; - builder.append_fixed(µs.to_le_bytes()); - } - WriteCell::Time => { - let interval = value - .object() - .filter(|object| object.instance_of(classes.interval)) - .ok_or_else(|| refused("DateInterval", value))?; - builder.append_fixed(&interval_micros(interval, value)?.to_le_bytes()); - } - WriteCell::List(element, element_nullable) => { - let values = value.array().ok_or_else(|| refused("array", value))?; - let mut failure = None; - - ht_for_each(values, |_, _, item| { - if failure.is_none() { - if let Err(refusal) = element.append(builder.list_element(), item, *element_nullable, classes) { - failure = Some(refusal); - } - } - - Ok(()) - })?; - - if let Some(refusal) = failure { - return Err(refusal); - } - - builder.end_entries().map_err(|_| Refusal::Overflow)?; - } - WriteCell::Map(key, map_value, value_nullable) => { - let entries = value.array().ok_or_else(|| refused("array", value))?; - let mut failure = None; - - ht_for_each(entries, |name, index, item| { - if failure.is_some() { - return Ok(()); - } - - let entry_key = match name { - Some(name) => zval_str(name.as_bytes()), - None => zval_long(index as i64), - }; - let (keys, values) = builder.map_entries(); - let appended = key - .append(keys, &entry_key, false, classes) - .and_then(|()| map_value.append(values, item, *value_nullable, classes)); - - if let Err(refusal) = appended { - failure = Some(refusal); - } - - Ok(()) - })?; - - if let Some(refusal) = failure { - return Err(refusal); - } - - builder.end_entries().map_err(|_| Refusal::Overflow)?; - } - WriteCell::Struct(children) => { - let values = value.array().ok_or_else(|| refused("array", value))?; - let null = Zval::new(); - - for ((name, cell, child_nullable), child) in children.iter().zip(builder.struct_children()) { - cell.append(child, ht_get(values, name).unwrap_or(&null), *child_nullable, classes)?; - } - - builder.end_struct(); - } - } - - Ok(()) - } -} - -/// `UuidConverter::toParquetType()`'s text of an object: `toString()`, else `__toString()`; `None` for neither. -fn uuid_text_of(object: &ZendObject) -> Result, PhpException> { - let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php expected a class entry"))?; - - for method in ["toString", "__toString"] { - if let Ok(function) = ce_method_ref(ce, method) { - return call_handle_transparent(function, Some(object), &mut []).map(Some); - } - } - - Ok(None) -} - -fn datetime<'a>(value: &'a Zval, classes: &Classes) -> Option<&'a ZendObject> { - value.object().filter(|object| object.instance_of(classes.datetime)) -} - -fn method_long(object: &ZendObject, method: &str, args: &mut [Zval]) -> Result { - let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php expected a class entry"))?; - let result = call_handle_transparent(ce_method_ref(ce, method)?, Some(object), args)?; - - result - .long() - .or_else(|| result.zend_str().and_then(|text| std::str::from_utf8(text.as_bytes()).ok()?.parse().ok())) - .ok_or_else(|| ext_exception(format!("flow_php expected {method}() to return an int"))) -} - -/// `getTimestamp() * 1_000_000 + format('u')`, for a datetime timelib has not brought up to date. -fn fallback_micros(datetime: &ZendObject) -> Result { - let seconds = method_long(datetime, "getTimestamp", &mut [])?; - let micros = method_long(datetime, "format", &mut [zval_str(b"u")])?; - - seconds.checked_mul(1_000_000).and_then(|us| us.checked_add(micros)).ok_or(Refusal::Overflow) -} - -/// `(getTimestamp() + getOffset())` floored to days, for a datetime timelib has not brought up to date. -fn fallback_days(datetime: &ZendObject) -> Result { - let seconds = method_long(datetime, "getTimestamp", &mut [])?; - let offset = method_long(datetime, "getOffset", &mut [])?; - - Ok((seconds + offset).div_euclid(86_400)) -} - -fn interval_part(interval: &ZendObject, name: &str) -> Result { - Ok(read_property(interval, name)?.long().unwrap_or_default()) -} - -/// `TimeConverter::toParquetType()`: `((d·24+h)·3600+i·60+s)·1e6 + (int)(f·1e6)`, `invert` ignored; y or m ≠ 0 is -/// refused. -fn interval_micros(interval: &ZendObject, value: &Zval) -> Result { - if interval_part(interval, "y")? != 0 || interval_part(interval, "m")? != 0 { - return Err(refused("DateInterval without years or months", value)); - } - - let seconds = ((interval_part(interval, "d")? * 24 + interval_part(interval, "h")?) * 3_600 - + interval_part(interval, "i")? * 60 - + interval_part(interval, "s")?) - .checked_mul(1_000_000) - .ok_or(Refusal::Overflow)?; - let fraction = (read_property(interval, "f")?.double().unwrap_or_default() * 1_000_000.0) as i64; - - seconds.checked_add(fraction).ok_or(Refusal::Overflow) -} - -/// Rows appended to one writer column, cast to canonical arrays in batches. -pub struct WriteColumn { - pub name: String, - pub cell: WriteCell, - pub kind: Kind, - pub nullable: bool, - pub builder: KindBuilder, -} - -impl WriteColumn { - pub fn new(target: &Field) -> Result { - let (cell, kind) = WriteCell::new(target).map_err(|e| e.in_column(target.name()))?; - - Ok(Self { - name: target.name().clone(), - builder: KindBuilder::new(&kind), - cell, - kind, - nullable: target.is_nullable(), - }) - } - - /// The rows appended since the last take, as a canonical array; the builder starts over. - pub fn take(&mut self) -> Result { - let data = self.builder.finish(&self.kind)?; - self.builder = KindBuilder::new(&self.kind); - - Ok(make_array(data)) - } -} diff --git a/src/extension/flow-php-ext/src/parquet/etl.rs b/src/extension/flow-php-ext/src/parquet/etl.rs index 57637f9705..fcc8cc2e37 100644 --- a/src/extension/flow-php-ext/src/parquet/etl.rs +++ b/src/extension/flow-php-ext/src/parquet/etl.rs @@ -1,36 +1,20 @@ -//! `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}`: `Rows` of `NativeColumn`s straight from the -//! core's canonical arrays, and any `Rows` straight to them. +//! `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}`: `Rows` of `NativeColumn`s straight from +//! arrow-ext's Parquet batches, and any `Rows` straight to its writer, through the Arrow C Data Interface. use std::rc::Rc; use std::sync::Arc; +use ext_php_rs::convert::IntoZval; use ext_php_rs::flags::ClassFlags; use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, Zval}; -use flow_batch_frame::kind::data_type; +use crate::arrow_c; use crate::backend::DefaultBackend; use crate::column::NativeColumn; -use crate::ctx::{call_method, call_static, ht_for_each, ht_get, ht_insert, null_zval, zval_long, zval_str}; +use crate::ctx::{call_method, call_static, ht_for_each, ht_insert, null_zval, zval_long, zval_str}; use crate::exception::ext_exception; -use crate::parquet::error::Error; -use crate::parquet::library::NativeParquetFile; -use crate::parquet::options; -use crate::parquet::read::{ParquetReader, ReadPlan}; -use crate::parquet::sink::PhpSink; -use crate::parquet::source::PhpStream; -use crate::parquet::write::ParquetWriter; use crate::plan::{type_plan, TypePlan}; -use crate::render::{invalid_argument, parquet_exception, Side, Surface}; - -fn rows(value: Option, name: &str) -> PhpResult> { - value - .map(|value| { - u64::try_from(value) - .map_err(|_| invalid_argument(format!("flow_php Parquet {name} must be greater or equal to 0"))) - }) - .transpose() -} /// `Schema::definitions()` as (name, definition): an int key is a numeric column name. fn definitions(schema: &Zval) -> PhpResult, Zval)>> { @@ -55,59 +39,26 @@ fn definitions(schema: &Zval) -> PhpResult, Zval)>> { #[php_class] #[php(name = "Flow\\ETL\\Adapter\\Parquet\\NativeParquetReader", flags = ClassFlags::Final)] pub struct NativeParquetReader { - reader: Option, - stream: Arc, + batches: Zval, schema: Zval, columns: Vec<(Vec, Rc)>, } #[php_impl] impl NativeParquetReader { - /// `$file`'s footer plans the read; no footer is read here. - pub fn __construct( - file: &NativeParquetFile, - schema: &Zval, - batch_size: i64, - offset: Option, - limit: Option, - ) -> PhpResult { - let batch_size = usize::try_from(batch_size) - .ok() - .filter(|size| *size > 0) - .ok_or_else(|| invalid_argument("flow_php Parquet batch size must be greater than 0".to_string()))?; - let (offset, limit) = (rows(offset, "offset")?.unwrap_or(0), rows(limit, "limit")?); - let (stream, size, meta) = file.read()?; - let stream = Arc::clone(stream); - let refused = |error| parquet_exception(error, &stream, Side::Read, Surface::Etl); - let plan = ReadPlan::new(meta, offset, limit); + /// `$batches`: a `Flow\Arrow\Parquet\BatchReader` over `$schema`'s columns; its schema is checked here, before + /// any batch. + pub fn __construct(batches: &Zval, schema: &Zval) -> PhpResult { let mut columns = Vec::new(); - let mut names = Vec::new(); for (name, definition) in definitions(schema)? { - names.push(String::from_utf8_lossy(&name).into_owned()); columns.push((name, type_plan(&call_method(&definition, "type", &mut [])?)?)); } - let reader = ParquetReader::open(Arc::clone(&stream), size, meta, &names, plan, batch_size).map_err(refused)?; - - for ((field, canonical), (name, plan)) in reader.fields().iter().zip(reader.types()).zip(&columns) { - let stored = data_type(&plan.kind); - - if canonical != &stored { - let type_name = call_method(&plan.type_zv, "toString", &mut [])?; - - return Err(invalid_argument(format!( - "Parquet column \"{}\" ({}) is read as {canonical}, its schema type {} stores {stored}", - String::from_utf8_lossy(name), - field.data_type(), - String::from_utf8_lossy(type_name.zend_str().map_or(&b""[..], |name| name.as_bytes())), - ))); - } - } + arrow_c::check_schema(&call_method(batches, "schema", &mut [])?, &columns)?; Ok(Self { - reader: Some(reader), - stream, + batches: batches.shallow_clone(), schema: schema.shallow_clone(), columns, }) @@ -115,24 +66,18 @@ impl NativeParquetReader { /// The next batch as `Rows::fromColumns($schema, $columns, $count)`, null after the last. pub fn next(&mut self) -> PhpResult { - let Some(reader) = self.reader.as_mut() else { - return Ok(null_zval()); - }; + let batch = call_method(&self.batches, "next", &mut [])?; - let (count, arrays) = match reader.next() { - None => { - self.reader = None; - - return Ok(null_zval()); - } - Some(batch) => batch.map_err(|error| parquet_exception(error, &self.stream, Side::Read, Surface::Etl))?, - }; + if batch.is_null() { + return Ok(null_zval()); + } + let (count, arrays) = arrow_c::import(&batch, &self.columns)?; let mut columns = ZendHashTable::with_capacity(self.columns.len() as u32); for ((name, plan), array) in self.columns.iter().zip(arrays) { let mut native = Zval::new(); - ext_php_rs::convert::IntoZval::set_zval(NativeColumn::new(array, Rc::clone(plan)), &mut native, false)?; + NativeColumn::new(array, Rc::clone(plan)).set_zval(&mut native, false)?; ht_insert(&mut columns, name, native); } @@ -146,47 +91,31 @@ impl NativeParquetReader { ) } - pub fn close(&mut self) { - self.reader = None; + pub fn close(&mut self) -> PhpResult<()> { + call_method(&self.batches, "close", &mut [])?; + + Ok(()) } } #[php_class] #[php(name = "Flow\\ETL\\Adapter\\Parquet\\NativeParquetWriter", flags = ClassFlags::Final)] pub struct NativeParquetWriter { - writer: Option, - stream: Arc, -} - -impl Drop for NativeParquetWriter { - fn drop(&mut self) { - self.stream.detach(); - } + writer: Zval, } #[php_impl] impl NativeParquetWriter { - /// `$schema`: `Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension()`, `$options`: `OptionsConverter::toExtension()`. - pub fn __construct(stream: &Zval, schema: &ZendHashTable, compression: String, options: &ZendHashTable) -> PhpResult { - let stream = Arc::new(PhpStream::new(stream)?); - let refused = |error| parquet_exception(error, &stream, Side::Write, Surface::Etl); - let writer = ParquetWriter::open( - PhpSink::new(Arc::clone(&stream)), - options::schema(schema).map_err(refused)?, - options::properties(&compression, options).map_err(refused)?, - ) - .map_err(refused)?; - - Ok(Self { - writer: Some(writer), - stream, - }) + /// `$writer`: a `Flow\Arrow\Parquet\RowsWriter`, which owns the stream. + pub fn __construct(writer: &Zval) -> Self { + Self { + writer: writer.shallow_clone(), + } } - /// The writer schema's columns by name: a `NativeColumn` as it is, any other column adopted into one, a column - /// the rows lack as nulls. + /// Every column of `$rows` - a `NativeColumn` as it is, any other column adopted into one - as one batch; the + /// writer takes its columns by name and writes a column the batch lacks as nulls. pub fn write(&mut self, rows: &Zval) -> PhpResult<()> { - let writer = self.writer.as_mut().ok_or_else(|| ext_exception("flow_php Parquet writer is closed"))?; let count = call_method(rows, "count", &mut [])? .long() .ok_or_else(|| ext_exception("flow_php expected Rows::count() to return an int"))? as usize; @@ -195,20 +124,15 @@ impl NativeParquetWriter { .array() .ok_or_else(|| ext_exception("flow_php expected Rows::columns() to return an array"))?; let schema = call_method(rows, "schema", &mut [])?; - let mut arrays = Vec::with_capacity(writer.schema().fields().len()); - - for field in writer.schema().fields() { - let Some(column) = ht_get(columns, field.name().as_bytes()) else { - arrays.push(arrow_array::new_null_array(field.data_type(), count)); - - continue; - }; + let mut arrays = Vec::with_capacity(columns.len()); + ht_for_each(columns, |name, index, column| { + let name = name.map_or_else(|| index.to_string().into_bytes(), |name| name.as_bytes().to_vec()); let adopted; let native = match column.extract::<&NativeColumn>() { Some(native) => native, None => { - let definition = call_method(&schema, "get", &mut [zval_str(field.name().as_bytes())])?; + let definition = call_method(&schema, "get", &mut [zval_str(&name)])?; adopted = DefaultBackend.adopt(&definition, column)?.0; adopted .extract::<&NativeColumn>() @@ -216,30 +140,22 @@ impl NativeParquetWriter { } }; - arrays.push(Arc::clone(native.data())); - } + arrays.push((String::from_utf8_lossy(&name).into_owned(), Arc::clone(native.data()))); + + Ok(()) + })?; + + let mut batch = Zval::new(); + arrow_c::export(count, arrays)?.set_zval(&mut batch, false)?; + call_method(&self.writer, "writeBatch", &mut [batch])?; - writer - .write(count, &arrays) - .map_err(|error| parquet_exception(error, &self.stream, Side::Write, Surface::Etl)) + Ok(()) } - /// The footer, then the stream closed - as the lib's Parquet writers close theirs. + /// The writer's buffered rows, the footer, then the stream closed. pub fn close(&mut self) -> PhpResult<()> { - self.writer - .take() - .ok_or_else(|| ext_exception("flow_php Parquet writer is already closed"))? - .close() - .map_err(|error| parquet_exception(error, &self.stream, Side::Write, Surface::Etl))?; - - match self.stream.call("close", &mut []) { - Some(_) => Ok(()), - None => Err(parquet_exception( - Error::Stream("close() threw".to_string()), - &self.stream, - Side::Write, - Surface::Etl, - )), - } + call_method(&self.writer, "close", &mut [])?; + + Ok(()) } } diff --git a/src/extension/flow-php-ext/src/parquet/mod.rs b/src/extension/flow-php-ext/src/parquet/mod.rs index 5335840913..518d60af32 100644 --- a/src/extension/flow-php-ext/src/parquet/mod.rs +++ b/src/extension/flow-php-ext/src/parquet/mod.rs @@ -1,15 +1,3 @@ -//! Parquet inside flow_php: one reader, one cast table and one writer over Flow filesystem streams, with no Flow types -//! below `etl`, the `Flow\ETL\Adapter\Parquet` surface. +//! Parquet in flow_php: the `Flow\ETL\Adapter\Parquet` surface over arrow-ext's Parquet batches. -pub mod canonical; -pub mod cells; -pub mod error; pub mod etl; -pub mod fetch; -pub mod footer; -pub mod library; -pub mod options; -pub mod read; -pub mod sink; -pub mod source; -pub mod write; diff --git a/src/extension/flow-php-ext/src/render.rs b/src/extension/flow-php-ext/src/render.rs index 3b287382bf..a745dea0e6 100644 --- a/src/extension/flow-php-ext/src/render.rs +++ b/src/extension/flow-php-ext/src/render.rs @@ -1,6 +1,6 @@ //! flow-batch-frame refusals rendered as the exceptions `PhpBackend::decode()` throws for the same buffers: the //! `Flow\ETL\Exception\InvalidArgumentException` (or `OffsetOverflow`) with its exact message, a nested type named by -//! its PHP `toString()`. Parquet core refusals rendered for the reader and the writer of `Flow\ETL\Adapter\Parquet`. +//! its PHP `toString()`. use ext_php_rs::exception::PhpException; use ext_php_rs::types::Zval; @@ -9,10 +9,8 @@ use flow_batch_frame::kind::Kind; use flow_batch_frame::layout::node_count; use flow_batch_frame::Error; -use crate::ctx::{call_method, expect_object, find_class, read_property, transparent_exception}; +use crate::ctx::{call_method, expect_object, find_class, read_property}; use crate::exception::ext_exception; -use crate::parquet::error::Error as ParquetError; -use crate::parquet::source::PhpStream; const INVALID_ARGUMENT: &str = "Flow\\ETL\\Exception\\InvalidArgumentException"; const OFFSET_OVERFLOW: &str = "Flow\\ETL\\Exception\\OffsetOverflow"; @@ -173,96 +171,3 @@ fn type_at(type_zv: Zval, kind: &Kind, node: usize) -> Result Err(ext_exception("flow_php could not find a nested node")), } } - -/// Which Parquet surface refused: the same core refusal names what to do about it per side. -pub enum Side { - Read, - Write, -} - -/// Which API the refusal surfaces through: `Flow\ETL\Adapter\Parquet` or `Flow\Parquet`. -#[derive(Clone, Copy)] -pub enum Surface { - Etl, - Lib, -} - -const LIB_RUNTIME: &str = "Flow\\Parquet\\Exception\\RuntimeException"; -const LIB_VALIDATION: &str = "Flow\\Parquet\\Exception\\ValidationException"; -const LIB_INVALID_ARGUMENT: &str = "Flow\\Parquet\\Exception\\InvalidArgumentException"; - -/// A Parquet core refusal; an exception the stream threw while the core called it surfaces as itself. -pub fn parquet_exception(error: ParquetError, stream: &PhpStream, side: Side, surface: Surface) -> PhpException { - if let Some(mut thrown) = stream.thrown() { - return transparent_exception(&mut thrown); - } - - let (runtime, validation, arguments) = match surface { - Surface::Etl => (RUNTIME, RUNTIME, INVALID_ARGUMENT), - Surface::Lib => (LIB_RUNTIME, LIB_VALIDATION, LIB_INVALID_ARGUMENT), - }; - let failure = |message: String| match surface { - Surface::Etl => ext_exception(message), - Surface::Lib => exception(LIB_RUNTIME, message), - }; - - match (error, side) { - (ParquetError::Unsupported { column, parquet }, Side::Read) => exception( - runtime, - format!( - "Parquet column \"{column}\" ({parquet}) is not supported by the flow_php Parquet reader; {}", - match surface { - Surface::Etl => { - "read the file with from_parquet($path, engine: new \\Flow\\Parquet\\Engine\\PhpParquetEngine())" - } - Surface::Lib => "read the file with \\Flow\\Parquet\\Reader::php()", - } - ), - ), - (ParquetError::Unsupported { column, parquet }, Side::Write) => exception( - runtime, - format!( - "Parquet column \"{column}\" ({parquet}) is not supported by the flow_php Parquet writer; {}", - match surface { - Surface::Etl => { - "write the file with to_parquet($path, engine: new \\Flow\\Parquet\\Engine\\PhpParquetEngine())" - } - Surface::Lib => "write it with \\Flow\\Parquet\\Writer::php()", - } - ), - ), - (ParquetError::Overflow { column, row }, _) => exception( - runtime, - format!("Parquet column \"{column}\" row {row} holds a value out of the range flow_php stores it in"), - ), - (ParquetError::InvalidUtf8 { column, row }, _) => exception( - runtime, - format!( - "Parquet column \"{column}\" row {row} holds a string that is not valid UTF-8; Parquet STRING columns \ - require UTF-8" - ), - ), - (ParquetError::Length { column, row, expected }, _) => exception( - runtime, - format!("Parquet column \"{column}\" row {row} holds a value that is not {expected} bytes long"), - ), - (ParquetError::Value { column, row, expected, got }, _) => { - exception(validation, format!("Column \"{column}\" row {row}: expected {expected}, got {got}")) - } - (ParquetError::MapKey { column, key }, _) => exception( - arguments, - format!("Map key of Parquet column \"{column}\" must be int or string, got {key}"), - ), - (ParquetError::MissingColumn(name), _) => exception(arguments, format!("Parquet file has no column \"{name}\"")), - (ParquetError::Options(message), _) => exception(arguments, message), - (ParquetError::NotParquet(message), _) => match surface { - Surface::Etl => failure(format!("flow_php failed to read Parquet: {message}")), - Surface::Lib => exception(arguments, format!("Given file is not valid Parquet file: {message}")), - }, - (ParquetError::Stream(message), _) => failure(format!("flow_php Parquet stream {message}")), - (ParquetError::Parquet(error), Side::Read) => failure(format!("flow_php failed to read Parquet: {error}")), - (ParquetError::Arrow(error), Side::Read) => failure(format!("flow_php failed to read Parquet: {error}")), - (ParquetError::Parquet(error), Side::Write) => failure(format!("flow_php failed to write Parquet: {error}")), - (ParquetError::Arrow(error), Side::Write) => failure(format!("flow_php failed to write Parquet: {error}")), - } -} diff --git a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt index c1690a0ed9..cddbf22da4 100644 --- a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt @@ -2,12 +2,11 @@ NativeParquetReader reads every lib Parquet fixture as PhpParquetEngine does, both refuse it, or it refuses naming the engine that reads it --SKIPIF-- + --FILE-- readFrom(path($file))), + $reader = native_parquet_reader( + $filesystem->readFrom(path($file)), (new SchemaConverter())->toFlow((new Reader(engine: new PhpParquetEngine()))->read($file)->schema()), $batchSize, null, @@ -56,29 +55,29 @@ foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.p $php === $native && refused($php) => "{$name}: both refuse\n", $php === $native => "{$name}: identical\n", refused($php) && refused($native) => "{$name}: both refuse\n", - str_contains($native, 'is not supported by the flow_php Parquet reader') => "{$name}: {$native}\n", + str_contains($native, 'is not supported by the arrow Parquet reader') => "{$name}: {$native}\n", default => "{$name}: DIFFER\n php: " . substr($php, 0, 300) . "\n native: " . substr($native, 0, 300) . "\n", }; } } $emptylist = realpath($fixtures . '/EdgeCases/null_list.parquet'); -echo outcome(static fn() => new NativeParquetReader( - new NativeParquetFile($filesystem->readFrom(path($emptylist))), +echo outcome(static fn() => native_parquet_reader( + $filesystem->readFrom(path($emptylist)), schema(list_schema('emptylist', type_list(type_integer()))), 100, null, null, )), "\n"; -echo outcome(static fn() => new NativeParquetReader( - new NativeParquetFile($filesystem->readFrom(path($fixtures . '/multiple_pages.parquet'))), +echo outcome(static fn() => native_parquet_reader( + $filesystem->readFrom(path($fixtures . '/multiple_pages.parquet')), schema(str_schema('int64')), 100, null, null, )), "\n"; -echo outcome(static fn() => new NativeParquetReader( - new NativeParquetFile($filesystem->readFrom(path($fixtures . '/multiple_pages.parquet'))), +echo outcome(static fn() => native_parquet_reader( + $filesystem->readFrom(path($fixtures . '/multiple_pages.parquet')), schema(str_schema('missing')), 100, null, @@ -124,4 +123,4 @@ EdgeCases/unsigned.parquet 100: identical EdgeCases/unsigned.parquet 10000: identical Flow\ETL\Exception\InvalidArgumentException: Parquet column "emptylist" (List(Null)) is read as List(Null), its schema type list stores List(Int64) Flow\ETL\Exception\InvalidArgumentException: Parquet column "int64" (Int64) is read as Int64, its schema type string stores Binary -Flow\ETL\Exception\InvalidArgumentException: Parquet file has no column "missing" +Flow\Parquet\Exception\InvalidArgumentException: Parquet file has no column "missing" diff --git a/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt b/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt index 7b12d2d945..af50ae5e8c 100644 --- a/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt +++ b/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt @@ -2,11 +2,12 @@ NativeParquetReader reads offset/limit windows of an 8-row-group file, and refuses a batch size, offset or limit out of range --SKIPIF-- + --FILE-- writeTo(path('memory://groups.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), 'SNAPPY', OptionsConverter::toExtension(Options::default()->set(Option::ROW_GROUP_SIZE_BYTES, 1)), -); + 1_000, +)); for ($group = 0; $group < 8; $group++) { $writer->write(array_to_rows(array_map(static fn(int $id): array => ['id' => $id], range($group * 8192, $group * 8192 + 8191)), $schema)); @@ -36,7 +38,7 @@ echo 'row groups: ', implode(',', array_map( )), "\n"; foreach ([[0, 10], [5399, 3], [20000, 15000], [65000, 100], [65046, 1], [65536, 10], [65530, null]] as [$offset, $limit]) { - $reader = new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://groups.parquet'))), $schema, 1000, $offset, $limit); + $reader = native_parquet_reader($filesystem->readFrom(path('memory://groups.parquet')), $schema, 1000, $offset, $limit); $ids = []; while (($batch = $reader->next()) !== null) { @@ -48,7 +50,7 @@ foreach ([[0, 10], [5399, 3], [20000, 15000], [65000, 100], [65046, 1], [65536, } foreach ([[0, null, null], [-1, null, null], [10, -1, null], [10, null, -1]] as [$batchSize, $offset, $limit]) { - echo outcome(static fn() => new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://groups.parquet'))), $schema, $batchSize, $offset, $limit)), "\n"; + echo outcome(static fn() => native_parquet_reader($filesystem->readFrom(path('memory://groups.parquet')), $schema, $batchSize, $offset, $limit)), "\n"; } ?> --EXPECT-- @@ -67,7 +69,7 @@ bool(true) bool(true) 65530 null: 6 rows, 65530..65535 bool(true) -Flow\ETL\Exception\InvalidArgumentException: flow_php Parquet batch size must be greater than 0 -Flow\ETL\Exception\InvalidArgumentException: flow_php Parquet batch size must be greater than 0 -Flow\ETL\Exception\InvalidArgumentException: flow_php Parquet offset must be greater or equal to 0 -Flow\ETL\Exception\InvalidArgumentException: flow_php Parquet limit must be greater or equal to 0 +Flow\Parquet\Exception\InvalidArgumentException: arrow Parquet batch size must be greater than 0 +Flow\Parquet\Exception\InvalidArgumentException: arrow Parquet batch size must be greater than 0 +Flow\Parquet\Exception\InvalidArgumentException: arrow Parquet offset must be greater or equal to 0 +Flow\Parquet\Exception\InvalidArgumentException: arrow Parquet limit must be greater or equal to 0 diff --git a/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt b/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt index 49727acd15..cd5dec1a68 100644 --- a/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt +++ b/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt @@ -2,10 +2,13 @@ NativeParquetWriter writes native and PHP columns that PhpParquetEngine reads back equal, and refuses a string that is not valid UTF-8 --SKIPIF-- + --FILE-- backend(new PhpBackend())->build()); $write = static function (Schema $schema, array $batches): void { - $writer = new NativeParquetWriter( + $writer = new NativeParquetWriter(new RowsWriter( memory_filesystem()->writeTo(path('memory://unused.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), 'ZSTD', OptionsConverter::toExtension(Options::default()), - ); + 1_000, + )); foreach ($batches as $batch) { $writer->write($batch); @@ -64,12 +68,13 @@ $write = static function (Schema $schema, array $batches): void { }; $filesystem = memory_filesystem(); -$writer = new NativeParquetWriter( +$writer = new NativeParquetWriter(new RowsWriter( $filesystem->writeTo(path('memory://roundtrip.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), 'ZSTD', OptionsConverter::toExtension(Options::default()), -); + 1_000, +)); $writer->write(native_rows($schema, $values)); $writer->write(php_rows($schema, $values)); $writer->close(); @@ -83,12 +88,13 @@ foreach (from_parquet(path('memory://roundtrip.parquet'), filesystem: $filesyste var_dump(comparable($read) === comparable([...php_rows($schema, $values)->toArray(), ...php_rows($schema, $values)->toArray()])); $partial = memory_filesystem(); -$partialWriter = new NativeParquetWriter( +$partialWriter = new NativeParquetWriter(new RowsWriter( $partial->writeTo(path('memory://partial.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet(schema(int_schema('id'), str_schema('name', nullable: true)))), 'SNAPPY', OptionsConverter::toExtension(Options::default()), -); + 1_000, +)); $partialWriter->write(native_rows(schema(int_schema('id')), [['id' => 1], ['id' => 2]])); $partialWriter->close(); $partialRead = []; @@ -109,6 +115,6 @@ echo outcome(static fn() => $write($nested, [native_rows($nested, [['tags' => [' --EXPECT-- bool(true) [{"id":1,"name":null},{"id":2,"name":null}] -Flow\ETL\Exception\RuntimeException: Parquet column "name" row 1 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 -Flow\ETL\Exception\RuntimeException: Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 -Flow\ETL\Exception\RuntimeException: Parquet column "tags" row 1 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 +Flow\Parquet\Exception\RuntimeException: Parquet column "name" row 1 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 +Flow\Parquet\Exception\RuntimeException: Parquet column "name" row 0 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 +Flow\Parquet\Exception\RuntimeException: Parquet column "tags" row 1 holds a string that is not valid UTF-8; Parquet STRING columns require UTF-8 diff --git a/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt index c800427d64..ff06b34a4b 100644 --- a/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt @@ -2,11 +2,12 @@ NativeParquetReader and NativeParquetWriter leak neither PHP memory nor native allocations, refusals included --SKIPIF-- + --FILE-- 1, 'name' => "\xff", 'tags' => []]]; $cycle = static function () use ($schema, $values, $extension, $options, $mismatched, $invalid): void { $filesystem = memory_filesystem(); - $writer = new NativeParquetWriter($filesystem->writeTo(path('memory://leaks.parquet')), $extension, 'SNAPPY', $options); + $writer = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://leaks.parquet')), $extension, 'SNAPPY', $options, 1_000)); $writer->write(native_rows($schema, $values)); $writer->write(php_rows($schema, $values)); $writer->close(); - $reader = new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))), $schema, 30, 10, 150); + $reader = native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, 10, 150); while ($reader->next() !== null) { } - $refused = new NativeParquetWriter($filesystem->writeTo(path('memory://refused.parquet')), $extension, 'SNAPPY', $options); + $refused = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://refused.parquet')), $extension, 'SNAPPY', $options, 1_000)); try { $refused->write(native_rows($schema, $invalid)); throw new LogicException('invalid UTF-8 was written'); - } catch (Flow\ETL\Exception\RuntimeException) { + } catch (Flow\Parquet\Exception\RuntimeException) { } try { - new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))), $mismatched, 30, null, null); + native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $mismatched, 30, null, null); throw new LogicException('a mismatched schema was accepted'); } catch (Flow\ETL\Exception\InvalidArgumentException) { } diff --git a/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt b/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt index d0d723f144..21e3050a1f 100644 --- a/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt +++ b/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt @@ -1,12 +1,13 @@ --TEST-- -Batches NativeParquetReader holds are counted by DefaultBackend::allocatedBytes(): at least their columns' buffer bytes +Batches NativeParquetReader holds are counted by DefaultBackend::allocatedBytes(): at least their columns' buffer bytes, and nothing once they are released --SKIPIF-- + --FILE-- writeTo(path('memory://held.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), 'SNAPPY', OptionsConverter::toExtension(Options::default()), -); + 1_000, +)); foreach (array_chunk(range(0, 65_535), 8_192) as $ids) { $writer->write(native_rows($schema, array_map(static fn(int $i): array => ['id' => $i, 'email' => "user{$i}@example.com", 'amount' => $i % 5 ? $i / 7 : null], $ids))); @@ -33,7 +35,7 @@ $writer->close(); gc_collect_cycles(); $before = (new DefaultBackend())->allocatedBytes(); -$reader = new NativeParquetReader(new NativeParquetFile($filesystem->readFrom(path('memory://held.parquet'))), $schema, 1_000, null, null); +$reader = native_parquet_reader($filesystem->readFrom(path('memory://held.parquet')), $schema, 1_000, null, null); $held = []; while (($batch = $reader->next()) !== null) { @@ -54,7 +56,13 @@ foreach ($held as $batch) { var_dump(array_sum(array_map(count(...), $held))); var_dump((new DefaultBackend())->allocatedBytes() - $before >= $bufferBytes); + +unset($held, $batch, $column); +gc_collect_cycles(); + +var_dump((new DefaultBackend())->allocatedBytes() === $before); ?> --EXPECT-- int(65536) bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/089_parquet_arrow_c_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/089_parquet_arrow_c_no_leaks.phpt new file mode 100644 index 0000000000..8e0123c2e7 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/089_parquet_arrow_c_no_leaks.phpt @@ -0,0 +1,94 @@ +--TEST-- +Batches crossing to and from arrow-ext through the Arrow C Data Interface leak neither PHP memory nor native allocations: abandoned, never imported, imported twice, refused before and after export, writer dropped unclosed +--SKIPIF-- + + +--FILE-- +toParquet($schema)); +$options = OptionsConverter::toExtension(Options::default()); +$values = array_map(static fn(int $i): array => ['id' => $i, 'name' => $i % 3 ? "name {$i}" : null, 'tags' => $i % 4 ? [$i, null] : null], range(0, 99)); +// built once: a fresh Type object per cycle would grow flow_php's type-plan cache, which is bounded, not leaked +$rows = native_rows($schema, $values); +$invalid = native_rows($schema, [['id' => 1, 'name' => "\xff", 'tags' => null]]); +$mismatched = schema(str_schema('id')); + +$cycle = static function () use ($schema, $extension, $options, $rows, $invalid, $mismatched): void { + $filesystem = memory_filesystem(); + $writer = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://leaks.parquet')), $extension, 'SNAPPY', $options, 30)); + $writer->write($rows); + $writer->write($rows); + $writer->close(); + + $reader = native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, null, null); + + while ($reader->next() !== null) { + } + + $abandoned = native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, null, null); + $abandoned->next(); + unset($abandoned); + + $batches = new BatchReader(new ParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))), ['id', 'name', 'tags'], 30, null, null); + $batches->next(); + $twice = $batches->next(); + $copy = new RowsWriter($filesystem->writeTo(path('memory://copy.parquet')), $extension, 'SNAPPY', $options, 30); + $copy->writeBatch($twice); + + try { + $copy->writeBatch($twice); + throw new LogicException('a batch was imported twice'); + } catch (Flow\Parquet\Exception\InvalidArgumentException) { + } + + $copy->close(); + + try { + native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $mismatched, 30, null, null); + throw new LogicException('a string schema read an int column'); + } catch (Flow\ETL\Exception\InvalidArgumentException) { + } + + $refused = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://refused.parquet')), $extension, 'SNAPPY', $options, 30)); + + try { + $refused->write($invalid); + throw new LogicException('invalid UTF-8 was written'); + } catch (Flow\Parquet\Exception\RuntimeException) { + } + + $unclosed = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://unclosed.parquet')), $extension, 'SNAPPY', $options, 30)); + $unclosed->write($rows); +}; + +for ($i = 0; $i < 10; $i++) { + $cycle(); +} +gc_collect_cycles(); +$baseline = memory_get_usage(false); +$baselineRust = (new DefaultBackend())->allocatedBytes(); + +for ($i = 0; $i < 200; $i++) { + $cycle(); +} +gc_collect_cycles(); + +var_dump(memory_get_usage(false) <= $baseline); +var_dump((new DefaultBackend())->allocatedBytes() === $baselineRust); +?> +--EXPECT-- +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt b/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt new file mode 100644 index 0000000000..04b38cf133 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt @@ -0,0 +1,45 @@ +--TEST-- +NativeParquetReader refuses a schema type that stores another arrow type at construction, before any batch: over a zero-row file and past the end of an 8-row-group file +--SKIPIF-- + + +--FILE-- +toParquet($schema)); + +$empty = new RowsWriter($filesystem->writeTo(path('memory://empty.parquet')), $extension, 'SNAPPY', OptionsConverter::toExtension(Options::default()), 10); +$empty->close(); + +$groups = new NativeParquetWriter(new RowsWriter( + $filesystem->writeTo(path('memory://groups.parquet')), + $extension, + 'SNAPPY', + OptionsConverter::toExtension(Options::default()->set(Option::ROW_GROUP_SIZE_BYTES, 1)), + 10, +)); + +for ($group = 0; $group < 8; $group++) { + $groups->write(array_to_rows(array_map(static fn(int $id): array => ['id' => $id], range($group * 10, $group * 10 + 9)), $schema)); +} + +$groups->close(); + +$mismatched = schema(str_schema('id')); +echo outcome(static fn() => native_parquet_reader($filesystem->readFrom(path('memory://empty.parquet')), $mismatched, 10, null, null)), "\n"; +echo outcome(static fn() => native_parquet_reader($filesystem->readFrom(path('memory://groups.parquet')), $mismatched, 10, 1_000, null)), "\n"; +?> +--EXPECT-- +Flow\ETL\Exception\InvalidArgumentException: Parquet column "id" (Int64) is read as Int64, its schema type string stores Binary +Flow\ETL\Exception\InvalidArgumentException: Parquet column "id" (Int64) is read as Int64, its schema type string stores Binary diff --git a/src/extension/flow-php-ext/tests/phpt/091_parquet_canonical_layout_contract.phpt b/src/extension/flow-php-ext/tests/phpt/091_parquet_canonical_layout_contract.phpt new file mode 100644 index 0000000000..2b7722ff70 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/091_parquet_canonical_layout_contract.phpt @@ -0,0 +1,86 @@ +--TEST-- +arrow-ext's canonical Arrow layout (parquet/canonical.rs) is the layout flow_php's columns store (flow-batch-frame kind::data_type()): every Flow type, nested included, crosses BatchReader → NativeParquetReader with its values intact +--SKIPIF-- + + +--FILE-- + type_integer(), 'name' => type_optional(type_string())]), nullable: true), + list_schema('list_of_structures', type_list(type_structure(['id' => type_integer(), 'tags' => type_optional(type_list(type_string()))])), nullable: true), + map_schema('map_of_lists', type_map(type_string(), type_list(type_integer())), nullable: true), +); +$values = [ + [ + 'int' => -7, 'float' => 0.14, 'bool' => true, 'string' => 'zażółć', + 'datetime' => new DateTimeImmutable('1969-12-31 23:59:59.999999 UTC'), 'date' => new DateTimeImmutable('1900-01-01'), + 'time' => new DateInterval('PT1H2M3S'), 'uuid' => new Uuid('26fd21b0-6080-4d6c-bdb4-1214f1feffef'), 'json' => '{"a":[1,2]}', + 'list' => [1, null, 3], 'map' => ['a' => 1, 'b' => null], 'structure' => ['id' => 1, 'name' => null], + 'list_of_structures' => [['id' => 1, 'tags' => ['x', 'y']], ['id' => 2, 'tags' => null]], + 'map_of_lists' => ['a' => [1, 2], 'b' => []], + ], + array_fill_keys(array_keys($schema->definitions()), null), +]; + +$filesystem = memory_filesystem(); +$writer = new NativeParquetWriter(new RowsWriter( + $filesystem->writeTo(path('memory://layout.parquet')), + ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), + 'SNAPPY', + OptionsConverter::toExtension(Options::default()), + 1_000, +)); +$writer->write(php_rows($schema, $values)); +$writer->close(); + +$read = []; +$reader = native_parquet_reader($filesystem->readFrom(path('memory://layout.parquet')), $schema, 10, null, null); + +while (($batch = $reader->next()) !== null) { + array_push($read, ...$batch->toArray()); +} + +$written = php_rows($schema, $values)->toArray(); + +foreach (array_keys($schema->definitions()) as $name) { + echo $name, ': ', comparable(array_column($read, $name)) === comparable(array_column($written, $name)) ? 'identical' : 'DIFFER', "\n"; +} +?> +--EXPECT-- +int: identical +float: identical +bool: identical +string: identical +datetime: identical +date: identical +time: identical +uuid: identical +json: identical +list: identical +map: identical +structure: identical +list_of_structures: identical +map_of_lists: identical diff --git a/src/extension/flow-php-ext/tests/phpt/bootstrap.php b/src/extension/flow-php-ext/tests/phpt/bootstrap.php index be29e8ce4a..58a6b7346f 100644 --- a/src/extension/flow-php-ext/tests/phpt/bootstrap.php +++ b/src/extension/flow-php-ext/tests/phpt/bootstrap.php @@ -4,12 +4,16 @@ require __DIR__ . '/../../../../../vendor/autoload.php'; +use Flow\Arrow\Parquet\BatchReader; +use Flow\Arrow\Parquet\ParquetFile; +use Flow\ETL\Adapter\Parquet\NativeParquetReader; use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; +use Flow\Filesystem\SourceStream; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; @@ -246,6 +250,30 @@ function comparable(mixed $value): string return serialize($plain($value)); } +/** + * `NativeParquetReader` over arrow-ext's batches of `$schema`'s columns of the Parquet file in `$stream`. + * + * @param int<1, max> $batchSize + */ +function native_parquet_reader( + SourceStream $stream, + Schema $schema, + int $batchSize, + ?int $offset, + ?int $limit, +): NativeParquetReader { + return new NativeParquetReader( + new BatchReader( + new ParquetFile($stream), + array_map('strval', array_keys($schema->definitions())), + $batchSize, + $offset, + $limit, + ), + $schema, + ); +} + /** * `comparable()` of the result, or `class: message <- previous class: message` of what it threw. */ diff --git a/src/lib/parquet-viewer/composer.json b/src/lib/parquet-viewer/composer.json index 9814cb7777..0dfa12e9c2 100644 --- a/src/lib/parquet-viewer/composer.json +++ b/src/lib/parquet-viewer/composer.json @@ -21,6 +21,9 @@ "optimize-autoloader": true, "sort-packages": true }, + "conflict": { + "ext-arrow": "<0.45" + }, "suggest": { "ext-arrow": "For high-performance Parquet reading/writing via Apache Arrow" }, diff --git a/src/lib/parquet/composer.json b/src/lib/parquet/composer.json index ed59bd108c..d81ab334c3 100644 --- a/src/lib/parquet/composer.json +++ b/src/lib/parquet/composer.json @@ -21,10 +21,10 @@ "symfony/polyfill-mbstring": "^1.33" }, "conflict": { - "ext-flow_php": "<0.45" + "ext-arrow": "<0.45" }, "suggest": { - "ext-flow_php": "Native Parquet reading and writing (flow-php/flow-php-ext)" + "ext-arrow": "Native Parquet reading and writing (flow-php/arrow-ext)" }, "config": { "optimize-autoloader": true, diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php index 1d4eb3c91b..1c34fc5443 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php @@ -22,7 +22,7 @@ public function __construct(ByteOrder $byteOrder = ByteOrder::LITTLE_ENDIAN, Options $options = new Options()) { - $this->delegate = extension_loaded('flow_php') || extension_loaded('arrow') + $this->delegate = extension_loaded('arrow') ? new ArrowParquetEngine($options) : new PhpParquetEngine($byteOrder, $options); } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/DestinationStreamAdapter.php b/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/DestinationStreamAdapter.php deleted file mode 100644 index 613e7c8e18..0000000000 --- a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/DestinationStreamAdapter.php +++ /dev/null @@ -1,22 +0,0 @@ -stream->append($data); - - return $this; - } -} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SourceStreamAdapter.php b/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SourceStreamAdapter.php deleted file mode 100644 index a10d1301b1..0000000000 --- a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SourceStreamAdapter.php +++ /dev/null @@ -1,26 +0,0 @@ - $length */ - return $this->stream->read($length, $offset); - } - - public function size(): ?int - { - return $this->stream->size(); - } -} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php index 5e7448eee4..1f7a5ea51b 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php @@ -4,15 +4,12 @@ namespace Flow\Parquet\Engine; -use Flow\Arrow\Parquet\Writer; +use Flow\Arrow\Parquet\ParquetFile; +use Flow\Arrow\Parquet\RowsWriter; use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; -use Flow\Parquet\Binary\ByteOrder; -use Flow\Parquet\Engine\Arrow\DestinationStreamAdapter; use Flow\Parquet\Engine\Arrow\OptionsConverter; use Flow\Parquet\Engine\Arrow\SchemaConverter; -use Flow\Parquet\Engine\Native\NativeParquetFile; -use Flow\Parquet\Engine\Native\NativeParquetRowsWriter; use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\Option; use Flow\Parquet\Options; @@ -22,27 +19,15 @@ use Flow\Parquet\ParquetFileReader; use Flow\Parquet\ParquetFileWriter; -use function array_column; use function extension_loaded; -use function trigger_error; - -use const E_USER_DEPRECATED; final class ArrowParquetEngine implements ParquetEngine { public function __construct( private readonly Options $options = new Options(), ) { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { - throw new RuntimeException('ArrowParquetEngine requires the flow_php extension (flow-php/flow-php-ext).'); - } - - if (!extension_loaded('flow_php')) { - @trigger_error( - 'Parquet through the arrow extension is deprecated and will be removed; install the flow_php ' - . 'extension (flow-php/flow-php-ext), which ArrowParquetEngine uses when it is loaded.', - E_USER_DEPRECATED, - ); + if (!extension_loaded('arrow')) { + throw new RuntimeException('ArrowParquetEngine requires the arrow extension (flow-php/arrow-ext).'); } } @@ -61,13 +46,7 @@ public static function mapCompression(Compressions $compression): string public function openForRead(SourceStream $stream): ParquetFileReader { - return extension_loaded('flow_php') - ? new NativeParquetFileReader(new NativeParquetFile($stream), $this->options) - : new ArrowParquetFileReader( - new PhpParquetFileReader($stream, ByteOrder::LITTLE_ENDIAN, $this->options), - $stream, - $this->options, - ); + return new ArrowParquetFileReader(new ParquetFile($stream), $this->options); } public function openForWrite( @@ -76,36 +55,14 @@ public function openForWrite( Compressions $compression, Options $options, ): ParquetFileWriter { - $extensionSchema = SchemaConverter::toExtension($schema); - - if (extension_loaded('flow_php')) { - return new NativeParquetFileWriter( - new NativeParquetRowsWriter( - $stream, - $extensionSchema, - self::mapCompression($compression), - OptionsConverter::toExtension($options), - $this->options->getInt(Option::ARROW_WRITE_BATCH_SIZE), - ), - ); - } - - /** @var list $columnNames */ - $columnNames = array_column($extensionSchema, 'name'); - // the arrow Writer takes the stream by reference, so it has to be a variable - $adapter = new DestinationStreamAdapter($stream); - return new ArrowParquetFileWriter( - new Writer( - $adapter, - $extensionSchema, + new RowsWriter( + $stream, + SchemaConverter::toExtension($schema), self::mapCompression($compression), OptionsConverter::toExtension($options), + $this->options->getInt(Option::ARROW_WRITE_BATCH_SIZE), ), - $stream, - $columnNames, - // write batching is an engine option, not a per-file one - $this->options->getInt(Option::ARROW_WRITE_BATCH_SIZE), ); } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php index 9e4f1f6175..af1e0f0422 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php @@ -4,95 +4,82 @@ namespace Flow\Parquet\Engine; -use Flow\Arrow\Parquet\Reader; -use Flow\Filesystem\SourceStream; -use Flow\Parquet\Engine\Arrow\OptionsConverter; -use Flow\Parquet\Engine\Arrow\SourceStreamAdapter; +use Flow\Arrow\Parquet\ColumnsReader; +use Flow\Arrow\Parquet\ParquetFile; +use Flow\Parquet\Exception\InvalidArgumentException; +use Flow\Parquet\Exception\RuntimeException; +use Flow\Parquet\Option; use Flow\Parquet\Options; use Flow\Parquet\ParquetFile\Metadata; use Flow\Parquet\ParquetFile\Schema; +use Flow\Parquet\ParquetFile\Schema\PhysicalType; use Flow\Parquet\ParquetFileReader; use Generator; -use function array_keys; -use function array_push; -use function array_slice; -use function count; -use function min; +use function sprintf; +use function str_starts_with; -final readonly class ArrowParquetFileReader implements ParquetFileReader +final class ArrowParquetFileReader implements ParquetFileReader { + private ?Metadata $metadata = null; + + private bool $open = true; + + private ?Schema $schema = null; + public function __construct( - private PhpParquetFileReader $footer, - private SourceStream $stream, - private Options $options, + private readonly ParquetFile $file, + private readonly Options $options, ) {} public function close(): void { - $this->footer->close(); - } + $this->open || throw new RuntimeException('Reader is not open'); - public function metadata(): Metadata - { - return $this->footer->metadata(); + $this->open = false; + $this->file->close(); } - public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator + public function file(): ParquetFile { - $adapter = new SourceStreamAdapter($this->stream); - $extensionOptions = OptionsConverter::toExtension($this->options); - $reader = new Reader($adapter, $extensionOptions); - - try { - $toSkip = $offset ?? 0; - $remaining = $limit; - /** @var array> $carry */ - $carry = []; - $carryCount = 0; - - while (($remaining === null || $remaining > 0) && null !== ($got = $reader->readRowGroup($columns))) { - $names = array_keys($got); - - if ($names === []) { - continue; - } - - $available = count($got[$names[0]]); - $cursor = min($toSkip, $available); - $toSkip -= $cursor; - - while ($cursor < $available && ($remaining === null || $remaining > 0)) { - $take = min($batchSize - $carryCount, $available - $cursor, $remaining ?? $available); - - foreach ($names as $name) { - /** @var list $slice */ - $slice = array_slice($got[$name], $cursor, $take); + $this->open || throw new RuntimeException('Reader is not open'); - if ($carryCount === 0) { - $carry[$name] = $slice; - } else { - array_push($carry[$name], ...$slice); - } - } + return $this->file; + } - $carryCount += $take; - $cursor += $take; + public function metadata(): Metadata + { + $this->open || throw new RuntimeException('Reader is not open'); - if ($remaining !== null) { - $remaining -= $take; - } + return $this->metadata ??= Metadata::fromThrift($this->file->thrift()); + } - if ($carryCount === $batchSize) { - yield $carry; - $carry = []; - $carryCount = 0; + public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator + { + $this->open || throw new RuntimeException('Reader is not open'); + + if (!$this->options->getBool(Option::INT_96_AS_DATETIME)) { + foreach ($columns as $column) { + foreach ($this->schema()->columnsFlat() as $leaf) { + if ( + $leaf->type() === PhysicalType::INT96 + && ($leaf->flatPath() === $column || str_starts_with($leaf->flatPath(), $column . '.')) + ) { + throw new InvalidArgumentException(sprintf( + 'Parquet column "%s" holds INT96, which arrow reads only as a datetime ' + . '(Option::INT_96_AS_DATETIME = true); read the file with \Flow\Parquet\Reader::php()', + $column, + )); } } } + } - if ($carryCount > 0) { - yield $carry; + $reader = new ColumnsReader($this->file, $columns, $batchSize, $offset, $limit); + + try { + while (($chunk = $reader->next()) !== null) { + yield $chunk; } } finally { $reader->close(); @@ -101,16 +88,22 @@ public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $o public function rowsNumber(): int { - return $this->footer->rowsNumber(); + $this->open || throw new RuntimeException('Reader is not open'); + + return $this->file->rowsNumber(); } public function schema(): Schema { - return $this->footer->schema(); + $this->open || throw new RuntimeException('Reader is not open'); + + return $this->metadata?->schema() ?? ($this->schema ??= Schema::fromThrift($this->file->schema())); } public function totalByteSize(): int { - return $this->footer->totalByteSize(); + $this->open || throw new RuntimeException('Reader is not open'); + + return $this->file->totalByteSize(); } } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileWriter.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileWriter.php index bdbd7df799..575840e47a 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileWriter.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileWriter.php @@ -4,93 +4,55 @@ namespace Flow\Parquet\Engine; -use Flow\Arrow\Parquet\Writer; -use Flow\Filesystem\DestinationStream; +use Flow\Arrow\Parquet\RowsWriter; use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\ParquetFileWriter; -use Flow\Parquet\Writer\ColumnLists; -use function array_fill_keys; +use function array_values; +use function is_array; final class ArrowParquetFileWriter implements ParquetFileWriter { - /** - * @var array> - */ - private array $batch; + private ?RowsWriter $writer; - private int $batchSize = 0; - - private ?Writer $arrowWriter; - - /** - * @param list $columnNames - */ - public function __construct( - Writer $arrowWriter, - private readonly DestinationStream $stream, - private readonly array $columnNames, - private readonly int $batchSizeLimit, - ) { - $this->arrowWriter = $arrowWriter; - $this->batch = array_fill_keys($this->columnNames, []); + public function __construct(RowsWriter $writer) + { + $this->writer = $writer; } public function close(): void { - $writer = $this->arrowWriter ?? throw new RuntimeException('Writer is not open'); + $writer = $this->writer ?? throw new RuntimeException('Writer is not open'); try { - if ($this->batchSize > 0) { - $writer->writeBatch($this->batch); - } - $writer->close(); - $this->stream->close(); } finally { - $this->arrowWriter = null; + $this->writer = null; } } public function writeBatch(iterable $rows): void { + $writer = $this->writer ?? throw new RuntimeException('Writer is not open'); + + if (is_array($rows)) { + $writer->writeRows(array_values($rows)); + + return; + } + foreach ($rows as $row) { - $this->writeRow($row); + $writer->writeRow($row); } } public function writeColumns(array $columns): void { - $count = (new ColumnLists())->length($columns); - $rows = []; - - for ($i = 0; $i < $count; $i++) { - $row = []; - - foreach ($columns as $name => $values) { - $row[$name] = $values[$i]; - } - - $rows[] = $row; - } - - $this->writeBatch($rows); + ($this->writer ?? throw new RuntimeException('Writer is not open'))->writeColumns($columns); } public function writeRow(array $row): void { - $writer = $this->arrowWriter ?? throw new RuntimeException('Writer is not open'); - - foreach ($this->columnNames as $name) { - $this->batch[$name][] = $row[$name] ?? null; - } - - $this->batchSize++; - - if ($this->batchSize >= $this->batchSizeLimit) { - $writer->writeBatch($this->batch); - $this->batch = array_fill_keys($this->columnNames, []); - $this->batchSize = 0; - } + ($this->writer ?? throw new RuntimeException('Writer is not open'))->writeRow($row); } } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileReader.php deleted file mode 100644 index 47055d49a6..0000000000 --- a/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileReader.php +++ /dev/null @@ -1,109 +0,0 @@ -open || throw new RuntimeException('Reader is not open'); - - $this->open = false; - $this->file->close(); - } - - public function file(): NativeParquetFile - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->file; - } - - public function metadata(): Metadata - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->metadata ??= Metadata::fromThrift($this->file->thrift()); - } - - public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator - { - $this->open || throw new RuntimeException('Reader is not open'); - - if (!$this->options->getBool(Option::INT_96_AS_DATETIME)) { - foreach ($columns as $column) { - foreach ($this->schema()->columnsFlat() as $leaf) { - if ( - $leaf->type() === PhysicalType::INT96 - && ($leaf->flatPath() === $column || str_starts_with($leaf->flatPath(), $column . '.')) - ) { - throw new InvalidArgumentException(sprintf( - 'Parquet column "%s" holds INT96, which flow_php reads only as a datetime ' - . '(Option::INT_96_AS_DATETIME = true); read the file with \Flow\Parquet\Reader::php()', - $column, - )); - } - } - } - } - - $reader = new NativeParquetColumnsReader($this->file, $columns, $batchSize, $offset, $limit); - - try { - while (($chunk = $reader->next()) !== null) { - yield $chunk; - } - } finally { - $reader->close(); - } - } - - public function rowsNumber(): int - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->file->rowsNumber(); - } - - public function schema(): Schema - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->metadata?->schema() ?? ($this->schema ??= Schema::fromThrift($this->file->schema())); - } - - public function totalByteSize(): int - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->file->totalByteSize(); - } -} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileWriter.php b/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileWriter.php deleted file mode 100644 index 3ce07b89c4..0000000000 --- a/src/lib/parquet/src/Flow/Parquet/Engine/NativeParquetFileWriter.php +++ /dev/null @@ -1,58 +0,0 @@ -writer = $writer; - } - - public function close(): void - { - $writer = $this->writer ?? throw new RuntimeException('Writer is not open'); - - try { - $writer->close(); - } finally { - $this->writer = null; - } - } - - public function writeBatch(iterable $rows): void - { - $writer = $this->writer ?? throw new RuntimeException('Writer is not open'); - - if (is_array($rows)) { - $writer->writeRows(array_values($rows)); - - return; - } - - foreach ($rows as $row) { - $writer->writeRow($row); - } - } - - public function writeColumns(array $columns): void - { - ($this->writer ?? throw new RuntimeException('Writer is not open'))->writeColumns($columns); - } - - public function writeRow(array $row): void - { - ($this->writer ?? throw new RuntimeException('Writer is not open'))->writeRow($row); - } -} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php index 0c800ac4f9..5f0d652018 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php @@ -29,8 +29,8 @@ final class ArrowParquetEngineReadTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { - self::markTestSkipped('Neither flow_php nor arrow is loaded'); + if (!extension_loaded('arrow')) { + self::markTestSkipped('arrow is not loaded'); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php index 7148792633..c78ba168ad 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php @@ -30,8 +30,8 @@ final class ArrowParquetEngineWriteTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { - self::markTestSkipped('Neither flow_php nor arrow is loaded'); + if (!extension_loaded('arrow')) { + self::markTestSkipped('arrow is not loaded'); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeParquetFileReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetFileReaderTest.php similarity index 84% rename from src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeParquetFileReaderTest.php rename to src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetFileReaderTest.php index 77805283eb..b1d848a4a0 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeParquetFileReaderTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetFileReaderTest.php @@ -4,10 +4,10 @@ namespace Flow\Parquet\Tests\Integration\Engine; +use Flow\Arrow\Parquet\ParquetFile; use Flow\Filesystem\Stream\MemorySourceStream; use Flow\Filesystem\Stream\NativeLocalSourceStream; -use Flow\Parquet\Engine\Native\NativeParquetFile; -use Flow\Parquet\Engine\NativeParquetFileReader; +use Flow\Parquet\Engine\ArrowParquetFileReader; use Flow\Parquet\Exception\InvalidArgumentException; use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\Option; @@ -22,15 +22,15 @@ use function iterator_to_array; #[Group('native-extension')] -#[RequiresPhpExtension('flow_php')] -final class NativeParquetFileReaderTest extends TestCase +#[RequiresPhpExtension('arrow')] +final class ArrowParquetFileReaderTest extends TestCase { public const string FIXTURES = __DIR__ . '/../IO/Fixtures'; public function test_schema_rows_and_bytes_agree_with_the_metadata(): void { - $open = static fn() => new NativeParquetFileReader( - new NativeParquetFile(NativeLocalSourceStream::open(path_real(self::FIXTURES . '/structs.parquet'))), + $open = static fn() => new ArrowParquetFileReader( + new ParquetFile(NativeLocalSourceStream::open(path_real(self::FIXTURES . '/structs.parquet'))), new Options(), ); $metadata = $open()->metadata(); @@ -48,8 +48,8 @@ public function test_schema_rows_and_bytes_agree_with_the_metadata(): void public function test_every_call_after_close_throws(): void { - $reader = new NativeParquetFileReader( - new NativeParquetFile(NativeLocalSourceStream::open(path_real(self::FIXTURES . '/structs.parquet'))), + $reader = new ArrowParquetFileReader( + new ParquetFile(NativeLocalSourceStream::open(path_real(self::FIXTURES . '/structs.parquet'))), new Options(), ); $reader->metadata(); @@ -79,7 +79,7 @@ public function test_int96_is_refused_when_it_is_not_read_as_a_datetime(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( - 'Parquet column "ts" holds INT96, which flow_php reads only as a datetime (Option::INT_96_AS_DATETIME = ' + 'Parquet column "ts" holds INT96, which arrow reads only as a datetime (Option::INT_96_AS_DATETIME = ' . 'true); read the file with \Flow\Parquet\Reader::php()', ); @@ -98,7 +98,7 @@ public function test_a_path_into_a_list_is_refused_naming_the_php_reader(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessage( - 'Parquet column "list.list.element" (a path into LIST/MAP) is not supported by the flow_php Parquet ' + 'Parquet column "list.list.element" (a path into LIST/MAP) is not supported by the arrow Parquet ' . 'reader; read the file with \Flow\Parquet\Reader::php()', ); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php index afb8769614..da00bcbccd 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php @@ -29,8 +29,8 @@ final class CrossEngineTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { - self::markTestSkipped('Neither flow_php nor arrow is loaded'); + if (!extension_loaded('arrow')) { + self::markTestSkipped('arrow is not loaded'); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php index 39aab5124d..56f7315fca 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php @@ -20,8 +20,8 @@ final class EngineParityTest extends TestCase { protected function setUp(): void { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { - self::markTestSkipped('Neither flow_php nor arrow is loaded'); + if (!extension_loaded('arrow')) { + self::markTestSkipped('arrow is not loaded'); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php index bd75d9ee60..583641d16c 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php @@ -26,7 +26,7 @@ use function var_export; #[Group('native-extension')] -#[RequiresPhpExtension('flow_php')] +#[RequiresPhpExtension('arrow')] final class NativeLibParityTest extends TestCase { /** @@ -91,7 +91,7 @@ public function test_an_interval_column_is_refused_naming_it_and_the_php_reader( $this->expectException(RuntimeException::class); $this->expectExceptionMessage( - 'Parquet column "iv" (Interval(DayTime)) is not supported by the flow_php Parquet reader; read the file ' + 'Parquet column "iv" (Interval(DayTime)) is not supported by the arrow Parquet reader; read the file ' . 'with \Flow\Parquet\Reader::php()', ); @@ -110,9 +110,7 @@ public function test_a_uint64_above_php_int_max_is_refused_by_both_engines(): vo } $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'Parquet column "u64" row 0 holds a value out of the range flow_php stores it in', - ); + $this->expectExceptionMessage('Parquet column "u64" row 0 holds a value out of the range arrow stores it in'); ParquetRows::read(Reader::arrow()->read($path), 100); } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php index bbe5971dea..f78d3d3be0 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php @@ -35,7 +35,7 @@ use function var_export; #[Group('native-extension')] -#[RequiresPhpExtension('flow_php')] +#[RequiresPhpExtension('arrow')] final class NativeLibRegressionTest extends TestCase { public const string PAGINATION = __DIR__ . '/../IO/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'; @@ -136,7 +136,7 @@ public function test_a_logical_only_unsigned_integer_reads_as_itself_through_bot ); } - public function test_a_schema_read_from_an_arrow_rs_file_rewritten_by_the_php_engine_opens_in_flow_php(): void + public function test_a_schema_read_from_an_arrow_rs_file_rewritten_by_the_php_engine_opens_in_arrow(): void { $arrow = MemoryParquetFile::written( Writer::arrow(), diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php index 8cd1ca2adc..fb597fb88c 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php @@ -25,7 +25,7 @@ use function var_export; #[Group('native-extension')] -#[RequiresPhpExtension('flow_php')] +#[RequiresPhpExtension('arrow')] final class NativeLibWriteParityTest extends TestCase { /** diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ParquetIntegrationTestCase.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ParquetIntegrationTestCase.php index c919398406..b85bbc681e 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ParquetIntegrationTestCase.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ParquetIntegrationTestCase.php @@ -20,7 +20,7 @@ public static function engine_provider(): array { $engines = ['php' => [new PhpParquetEngine()]]; - if (extension_loaded('flow_php') || extension_loaded('arrow')) { + if (extension_loaded('arrow')) { $engines['arrow'] = [new ArrowParquetEngine()]; } @@ -34,7 +34,7 @@ public static function engine_pair_provider(): array { $pairs = ['php/php' => [new PhpParquetEngine(), new PhpParquetEngine()]]; - if (extension_loaded('flow_php') || extension_loaded('arrow')) { + if (extension_loaded('arrow')) { $pairs['php/arrow'] = [new PhpParquetEngine(), new ArrowParquetEngine()]; $pairs['arrow/php'] = [new ArrowParquetEngine(), new PhpParquetEngine()]; $pairs['arrow/arrow'] = [new ArrowParquetEngine(), new ArrowParquetEngine()]; diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php index e2f889f855..5fb6cc028a 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php @@ -75,7 +75,7 @@ public static function decimalPrecisionProvider(): array $engines = ['php' => new PhpParquetEngine()]; - if (extension_loaded('flow_php') || extension_loaded('arrow')) { + if (extension_loaded('arrow')) { $engines['arrow'] = new ArrowParquetEngine(); } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php index aa0197fbd4..bc82b390f0 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php @@ -14,10 +14,10 @@ final class AdaptiveParquetEngineTest extends TestCase { - public function test_creates_arrow_engine_when_flow_php_or_arrow_is_loaded(): void + public function test_creates_arrow_engine_when_arrow_is_loaded(): void { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { - static::markTestSkipped('This test requires flow_php or arrow to be loaded'); + if (!extension_loaded('arrow')) { + static::markTestSkipped('This test requires arrow to be loaded'); } $engine = new AdaptiveParquetEngine(); @@ -30,10 +30,10 @@ public function test_creates_arrow_engine_when_flow_php_or_arrow_is_loaded(): vo ); } - public function test_creates_php_engine_without_flow_php_and_arrow(): void + public function test_creates_php_engine_without_arrow(): void { - if (extension_loaded('flow_php') || extension_loaded('arrow')) { - static::markTestSkipped('This test requires neither flow_php nor arrow to be loaded'); + if (extension_loaded('arrow')) { + static::markTestSkipped('This test requires arrow not to be loaded'); } $engine = new AdaptiveParquetEngine(); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/DestinationStreamAdapterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/DestinationStreamAdapterTest.php deleted file mode 100644 index b2e3379483..0000000000 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/DestinationStreamAdapterTest.php +++ /dev/null @@ -1,37 +0,0 @@ -append('hello '); - $adapter->append('world'); - - static::assertSame('hello world', $stream->content()); - } - - public function test_append_returns_self(): void - { - $handle = fopen('php://memory', 'r+b'); - $stream = new MemoryStream($handle, Path::realpath('/tmp/test')); - - $adapter = new DestinationStreamAdapter($stream); - - static::assertSame($adapter, $adapter->append('data')); - } -} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/SourceStreamAdapterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/SourceStreamAdapterTest.php deleted file mode 100644 index 7afd3df539..0000000000 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/SourceStreamAdapterTest.php +++ /dev/null @@ -1,40 +0,0 @@ -read(5, 0)); - static::assertSame('world', $adapter->read(5, 6)); - static::assertSame(' ', $adapter->read(1, 5)); - } - - public function test_size_delegates_to_source_stream(): void - { - $handle = fopen('php://memory', 'r+b'); - fwrite($handle, 'hello world'); - $stream = new MemoryStream($handle, Path::realpath('/tmp/test')); - - $adapter = new SourceStreamAdapter($stream); - - static::assertSame(11, $adapter->size()); - } -} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php index f9be0888ff..2c709b2d16 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php @@ -8,8 +8,7 @@ use Flow\Filesystem\Stream\StringDestinationStream; use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\ArrowParquetFileReader; -use Flow\Parquet\Engine\NativeParquetFileReader; -use Flow\Parquet\Engine\NativeParquetFileWriter; +use Flow\Parquet\Engine\ArrowParquetFileWriter; use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\Tests\Context\MemoryParquetFile; @@ -20,74 +19,36 @@ use function extension_loaded; use function Flow\Filesystem\DSL\path; -use function restore_error_handler; -use function set_error_handler; - -use const E_USER_DEPRECATED; final class ArrowParquetEngineTest extends TestCase { - public function test_constructor_throws_without_flow_php_and_arrow(): void + public function test_constructor_throws_without_arrow(): void { - if (extension_loaded('flow_php') || extension_loaded('arrow')) { - static::markTestSkipped('This test requires neither flow_php nor arrow to be loaded'); + if (extension_loaded('arrow')) { + static::markTestSkipped('This test requires arrow not to be loaded'); } $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('ArrowParquetEngine requires the flow_php extension (flow-php/flow-php-ext).'); + $this->expectExceptionMessage('ArrowParquetEngine requires the arrow extension (flow-php/arrow-ext).'); new ArrowParquetEngine(); } - #[RequiresPhpExtension('flow_php')] - public function test_with_flow_php_files_are_read_and_written_through_it(): void + #[RequiresPhpExtension('arrow')] + public function test_files_are_read_and_written_through_arrow(): void { $engine = new ArrowParquetEngine(); static::assertInstanceOf( - NativeParquetFileReader::class, + ArrowParquetFileReader::class, $engine->openForRead(new MemorySourceStream(MemoryParquetFile::threeRowGroups())), ); - static::assertInstanceOf(NativeParquetFileWriter::class, ParquetFileWriterMother::open( + static::assertInstanceOf(ArrowParquetFileWriter::class, ParquetFileWriterMother::open( $engine, new StringDestinationStream(path('memory://out.parquet')), )); } - #[RequiresPhpExtension('arrow')] - public function test_with_arrow_only_files_are_read_through_arrow_with_a_deprecation(): void - { - if (extension_loaded('flow_php')) { - static::markTestSkipped('This test requires flow_php NOT to be loaded'); - } - - $deprecations = []; - set_error_handler(static function (int $level, string $message) use (&$deprecations): bool { - $deprecations[] = [$level, $message]; - - return true; - }); - - try { - $engine = new ArrowParquetEngine(); - } finally { - restore_error_handler(); - } - - static::assertSame( - [[ - E_USER_DEPRECATED, - 'Parquet through the arrow extension is deprecated and will be removed; install the flow_php ' - . 'extension (flow-php/flow-php-ext), which ArrowParquetEngine uses when it is loaded.', - ]], - $deprecations, - ); - static::assertInstanceOf( - ArrowParquetFileReader::class, - $engine->openForRead(new MemorySourceStream(MemoryParquetFile::threeRowGroups())), - ); - } - #[TestWith([Compressions::UNCOMPRESSED, 'UNCOMPRESSED'])] #[TestWith([Compressions::SNAPPY, 'SNAPPY'])] #[TestWith([Compressions::GZIP, 'GZIP'])] diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php index f057cf1824..65803951e8 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php @@ -4,12 +4,15 @@ namespace Flow\Parquet\Tests\Unit\Engine; +use ArrayIterator; use Flow\Filesystem\Exception\RuntimeException as FilesystemRuntimeException; use Flow\Filesystem\Tests\Double\FailingCloseDestinationStream; use Flow\Parquet\Engine\ArrowParquetEngine; +use Flow\Parquet\Engine\ArrowParquetFileWriter; use Flow\Parquet\Engine\PhpParquetEngine; use Flow\Parquet\Exception\InvalidArgumentException; use Flow\Parquet\Exception\RuntimeException; +use Flow\Parquet\Exception\ValidationException; use Flow\Parquet\Option; use Flow\Parquet\Options; use Flow\Parquet\ParquetFile\Schema; @@ -17,23 +20,19 @@ use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\ColumnDoor; use Flow\Parquet\Tests\Mother\ParquetFileWriterMother; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; +use function array_map; use function array_slice; -use function extension_loaded; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; use function iterator_to_array; +use function range; +#[RequiresPhpExtension('arrow')] final class ArrowParquetFileWriterTest extends TestCase { - protected function setUp(): void - { - if (!extension_loaded('arrow') || extension_loaded('flow_php')) { - static::markTestSkipped('ArrowParquetEngine writes through arrow-ext only without flow_php'); - } - } - public function test_a_close_that_throws_leaves_the_writer_closed(): void { $file = ParquetFileWriterMother::open( @@ -143,6 +142,45 @@ public function test_rows_beyond_the_batch_size_are_written_once(): void ); } + public function test_it_is_the_writer_the_arrow_engine_opens(): void + { + static::assertInstanceOf(ArrowParquetFileWriter::class, ParquetFileWriterMother::open( + new ArrowParquetEngine(), + memory_filesystem()->writeTo(path('memory://file.parquet')), + )); + } + + public function test_a_refused_row_leaves_the_rows_before_it_written(): void + { + $memory = memory_filesystem(); + $file = ParquetFileWriterMother::open( + new ArrowParquetEngine(), + $memory->writeTo(path('memory://file.parquet')), + ); + + $file->writeRow(['id' => 1]); + + try { + $file->writeRow(['id' => 'two']); + static::fail('a string was written into INT32'); + } catch (ValidationException $refusal) { + static::assertSame('Column "id" row 1: expected int, got string', $refusal->getMessage()); + } + + $file->writeBatch(new ArrayIterator([['id' => 3]])); + $file->close(); + + static::assertSame( + [['id' => 1], ['id' => 3]], + iterator_to_array( + (new Reader(engine: new PhpParquetEngine())) + ->readStream($memory->readFrom(path('memory://file.parquet'))) + ->values(), + false, + ), + ); + } + public function test_columns_of_different_lengths_are_refused(): void { $file = ColumnDoor::open(new ArrowParquetEngine(), ColumnDoor::stream(), Schema::with(FlatColumn::int32('id'))); @@ -214,4 +252,60 @@ public function test_columns_write_the_bytes_a_batch_writes(): void static::assertTrue($batch->content() === $columns->content()); static::assertSame($rows, ColumnDoor::read($columns)); } + + public function test_columns_refuse_the_first_cell_of_the_first_refused_row_and_keep_the_rows_before_it(): void + { + $schema = Schema::with(FlatColumn::int32('a'), FlatColumn::int32('b'), FlatColumn::int32('c')); + $rows = array_map(static fn(int $i): array => ['a' => $i, 'b' => $i, 'c' => $i], range(0, 7)); + $rows[5]['a'] = 'five'; + $rows[2]['c'] = 'two'; + $outcomes = []; + + foreach (['batch', 'columns'] as $door) { + $stream = ColumnDoor::stream(); + $file = ColumnDoor::open(new ArrowParquetEngine(), $stream, $schema); + + try { + $door === 'batch' ? $file->writeBatch($rows) : $file->writeColumns(ColumnDoor::columns($rows)); + static::fail('a string was written into INT32'); + } catch (ValidationException $refusal) { + $file->close(); + $outcomes[$door] = [$refusal->getMessage(), ColumnDoor::read($stream)]; + } + } + + static::assertSame($outcomes['batch'], $outcomes['columns']); + static::assertSame( + [ + 'Column "c" row 2: expected int, got string', + [['a' => 0, 'b' => 0, 'c' => 0], ['a' => 1, 'b' => 1, 'c' => 1]], + ], + $outcomes['columns'], + ); + } + + public function test_a_refusal_past_a_flushed_batch_names_the_row_the_row_door_names(): void + { + $schema = Schema::with(FlatColumn::int32('a')); + $rows = array_map(static fn(int $i): array => ['a' => $i], range(0, 6)); + $rows[5]['a'] = 'five'; + $messages = []; + + foreach (['batch', 'columns'] as $door) { + $file = ColumnDoor::open( + new ArrowParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 2)), + ColumnDoor::stream(), + $schema, + ); + + try { + $door === 'batch' ? $file->writeBatch($rows) : $file->writeColumns(ColumnDoor::columns($rows)); + static::fail('a string was written into INT32'); + } catch (ValidationException $refusal) { + $messages[$door] = $refusal->getMessage(); + } + } + + static::assertSame($messages['batch'], $messages['columns']); + } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/NativeParquetFileWriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/NativeParquetFileWriterTest.php deleted file mode 100644 index 37de6870b9..0000000000 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/NativeParquetFileWriterTest.php +++ /dev/null @@ -1,311 +0,0 @@ -writeTo(path('memory://file.parquet'))), - ); - - try { - $file->close(); - static::fail('close() was expected to throw'); - } catch (FilesystemRuntimeException $failure) { - static::assertSame('Closing "memory://file.parquet" failed', $failure->getMessage()); - } - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->close(); - } - - public function test_closing_twice_throws(): void - { - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - memory_filesystem()->writeTo(path('memory://file.parquet')), - ); - $file->close(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->close(); - } - - public function test_closing_writes_a_file_the_reader_reads_back(): void - { - $memory = memory_filesystem(); - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - $memory->writeTo(path('memory://file.parquet')), - ); - - $file->writeRow(['id' => 1]); - $file->writeBatch([['id' => 2]]); - $file->close(); - - static::assertSame( - [['id' => 1], ['id' => 2]], - iterator_to_array( - (new Reader(engine: new PhpParquetEngine())) - ->readStream($memory->readFrom(path('memory://file.parquet'))) - ->values(), - false, - ), - ); - } - - public function test_writing_a_batch_after_close_throws(): void - { - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - memory_filesystem()->writeTo(path('memory://file.parquet')), - ); - $file->close(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->writeBatch([['id' => 1]]); - } - - public function test_writing_a_row_after_close_throws(): void - { - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - memory_filesystem()->writeTo(path('memory://file.parquet')), - ); - $file->close(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->writeRow(['id' => 1]); - } - - public function test_rows_beyond_the_batch_size_are_written_once(): void - { - $memory = memory_filesystem(); - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 2)), - $memory->writeTo(path('memory://file.parquet')), - ); - - $file->writeRow(['id' => 1]); - $file->writeRow(['id' => 2]); - $file->writeRow(['id' => 3]); - $file->close(); - - static::assertSame( - [['id' => 1], ['id' => 2], ['id' => 3]], - iterator_to_array( - (new Reader(engine: new PhpParquetEngine())) - ->readStream($memory->readFrom(path('memory://file.parquet'))) - ->values(), - false, - ), - ); - } - - public function test_it_is_the_writer_arrow_opens_with_flow_php(): void - { - static::assertInstanceOf(NativeParquetFileWriter::class, ParquetFileWriterMother::open( - new ArrowParquetEngine(), - memory_filesystem()->writeTo(path('memory://file.parquet')), - )); - } - - public function test_a_refused_row_leaves_the_rows_before_it_written(): void - { - $memory = memory_filesystem(); - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - $memory->writeTo(path('memory://file.parquet')), - ); - - $file->writeRow(['id' => 1]); - - try { - $file->writeRow(['id' => 'two']); - static::fail('a string was written into INT32'); - } catch (ValidationException $refusal) { - static::assertSame('Column "id" row 1: expected int, got string', $refusal->getMessage()); - } - - $file->writeBatch(new ArrayIterator([['id' => 3]])); - $file->close(); - - static::assertSame( - [['id' => 1], ['id' => 3]], - iterator_to_array( - (new Reader(engine: new PhpParquetEngine())) - ->readStream($memory->readFrom(path('memory://file.parquet'))) - ->values(), - false, - ), - ); - } - - public function test_columns_of_different_lengths_are_refused(): void - { - $file = ColumnDoor::open(new ArrowParquetEngine(), ColumnDoor::stream(), Schema::with(FlatColumn::int32('id'))); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('writeColumns() takes lists of one length, got "id": 2, "other": 1'); - - $file->writeColumns(['id' => [1, 2], 'other' => [1]]); - } - - public function test_a_column_the_array_lacks_is_written_as_nulls_and_an_unknown_key_is_ignored(): void - { - $stream = ColumnDoor::stream(); - $file = ColumnDoor::open( - new ArrowParquetEngine(), - $stream, - Schema::with(FlatColumn::int32('id'), FlatColumn::string('name')), - ); - - $file->writeColumns(['id' => [1, 2], 'unknown' => ['a', 'b']]); - $file->writeColumns([]); - $file->close(); - - static::assertSame([['id' => 1, 'name' => null], ['id' => 2, 'name' => null]], ColumnDoor::read($stream)); - } - - public function test_writing_columns_after_close_throws(): void - { - $file = ColumnDoor::open(new ArrowParquetEngine(), ColumnDoor::stream(), Schema::with(FlatColumn::int32('id'))); - $file->close(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->writeColumns(['id' => [1]]); - } - - public function test_columns_write_the_bytes_a_batch_writes(): void - { - $options = Options::default() - ->set(Option::ROW_GROUP_SIZE_BYTES, 2 * 1024) - ->set(Option::ROW_GROUP_SIZE_CHECK_INTERVAL, 140) - ->set(Option::PAGE_SIZE_BYTES, 256) - ->set(Option::PAGE_SIZE_CHECK_INTERVAL, 26); - $rows = ColumnDoor::rows(600); - $batch = ColumnDoor::stream(); - $columns = ColumnDoor::stream(); - - $file = ColumnDoor::open( - new ArrowParquetEngine($options->set(Option::ARROW_WRITE_BATCH_SIZE, 200)), - $batch, - ColumnDoor::schema(), - $options, - ); - $file->writeRow($rows[0]); - $file->writeBatch(array_slice($rows, 1)); - $file->close(); - - $file = ColumnDoor::open( - new ArrowParquetEngine($options->set(Option::ARROW_WRITE_BATCH_SIZE, 200)), - $columns, - ColumnDoor::schema(), - $options, - ); - $file->writeRow($rows[0]); - $file->writeColumns(ColumnDoor::columns(array_slice($rows, 1))); - $file->close(); - - static::assertTrue($batch->content() === $columns->content()); - static::assertSame($rows, ColumnDoor::read($columns)); - } - - public function test_columns_refuse_the_first_cell_of_the_first_refused_row_and_keep_the_rows_before_it(): void - { - $schema = Schema::with(FlatColumn::int32('a'), FlatColumn::int32('b'), FlatColumn::int32('c')); - $rows = array_map(static fn(int $i): array => ['a' => $i, 'b' => $i, 'c' => $i], range(0, 7)); - $rows[5]['a'] = 'five'; - $rows[2]['c'] = 'two'; - $outcomes = []; - - foreach (['batch', 'columns'] as $door) { - $stream = ColumnDoor::stream(); - $file = ColumnDoor::open(new ArrowParquetEngine(), $stream, $schema); - - try { - $door === 'batch' ? $file->writeBatch($rows) : $file->writeColumns(ColumnDoor::columns($rows)); - static::fail('a string was written into INT32'); - } catch (ValidationException $refusal) { - $file->close(); - $outcomes[$door] = [$refusal->getMessage(), ColumnDoor::read($stream)]; - } - } - - static::assertSame($outcomes['batch'], $outcomes['columns']); - static::assertSame( - [ - 'Column "c" row 2: expected int, got string', - [['a' => 0, 'b' => 0, 'c' => 0], ['a' => 1, 'b' => 1, 'c' => 1]], - ], - $outcomes['columns'], - ); - } - - public function test_a_refusal_past_a_flushed_batch_names_the_row_the_row_door_names(): void - { - $schema = Schema::with(FlatColumn::int32('a')); - $rows = array_map(static fn(int $i): array => ['a' => $i], range(0, 6)); - $rows[5]['a'] = 'five'; - $messages = []; - - foreach (['batch', 'columns'] as $door) { - $file = ColumnDoor::open( - new ArrowParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 2)), - ColumnDoor::stream(), - $schema, - ); - - try { - $door === 'batch' ? $file->writeBatch($rows) : $file->writeColumns(ColumnDoor::columns($rows)); - static::fail('a string was written into INT32'); - } catch (ValidationException $refusal) { - $messages[$door] = $refusal->getMessage(); - } - } - - static::assertSame($messages['batch'], $messages['columns']); - } -} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php index 326cd692e0..42d6fbaccc 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php @@ -19,7 +19,7 @@ final class ReaderTest extends TestCase { public function test_arrow_factory_creates_reader_with_arrow_engine(): void { - if (!extension_loaded('flow_php') && !extension_loaded('arrow')) { + if (!extension_loaded('arrow')) { $this->expectException(RuntimeException::class); Reader::arrow(); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php index cde93ceef3..f7abac9e02 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php @@ -16,8 +16,8 @@ final class WriterTest extends TestCase { public function test_arrow_factory_throws_when_extension_not_loaded(): void { - if (extension_loaded('flow_php') || extension_loaded('arrow')) { - static::markTestSkipped('This test requires neither flow_php nor arrow to be loaded'); + if (extension_loaded('arrow')) { + static::markTestSkipped('This test requires arrow not to be loaded'); } $this->expectException(RuntimeException::class); From 3b9392f17fd23e2c2f3d6444df453b492aefa351 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Fri, 2 Oct 2026 21:50:27 +0200 Subject: [PATCH 14/21] refactor: one Php / Rust / Adaptive pattern for every extension contract - extensions register the package interfaces; Rust classes implement them - Adaptive classes are the only extension_loaded() pick per contract - CSV, JSON and Parquet open sources move into Rust, iterating as Generators - openers, Default*, Native* and Arrow* classes removed - ext-php-rs 0.16 in both extensions, rustfmt at width 120 - tools updated, rust-toolchain action repinned --- .github/workflows/job-arrow-extension.yml | 4 +- .github/workflows/job-flow-php-extension.yml | 4 +- .../Format/Parquet/ParquetReadBench.php | 6 +- .../Format/Parquet/ParquetWriteBench.php | 6 +- documentation/components/adapters/parquet.md | 4 +- .../components/extensions/arrow-ext.md | 41 +- .../components/extensions/flow-php-ext.md | 47 +- documentation/components/libs/parquet.md | 15 +- documentation/contributing/rust.md | 17 +- documentation/installation/docker.md | 4 +- documentation/upgrading.md | 141 +- .../ETL/Adapter/CSV/AdaptiveCSVEncoder.php | 41 + .../ETL/Adapter/CSV/AdaptiveCSVOpenSource.php | 110 + .../src/Flow/ETL/Adapter/CSV/CSVEncoder.php | 6 + .../src/Flow/ETL/Adapter/CSV/CSVExtractor.php | 5 +- .../Flow/ETL/Adapter/CSV/CSVFileReader.php | 10 +- .../Flow/ETL/Adapter/CSV/CSVFileSample.php | 8 +- .../src/Flow/ETL/Adapter/CSV/CSVLoader.php | 11 +- .../Flow/ETL/Adapter/CSV/CSVOpenSource.php | 16 +- .../Flow/ETL/Adapter/CSV/CSVSinkOpener.php | 39 - .../Flow/ETL/Adapter/CSV/CSVSourceOpener.php | 69 - .../Flow/ETL/Adapter/CSV/NativeCSVEncoder.php | 47 - .../ETL/Adapter/CSV/NativeCSVOpenSource.php | 223 - .../Flow/ETL/Adapter/CSV/PhpCSVEncoder.php | 1 + .../Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php | 4 + .../CSV/Tests/Context/CSVFixtureContext.php | 35 +- .../Integration/AdaptiveCSVOpenSourceTest.php | 155 + .../Tests/Integration/CSVSourceOpenerTest.php | 87 - ...urceTest.php => RustCSVOpenSourceTest.php} | 137 +- .../CSV/Tests/Mother/CSVEncoderMother.php | 25 +- .../CSV/Tests/Unit/AdaptiveCSVEncoderTest.php | 46 + .../CSV/Tests/Unit/CSVSinkOpenerTest.php | 41 - .../CSV/Tests/Unit/CSVSourceOpenerTest.php | 87 - ...EncoderTest.php => RustCSVEncoderTest.php} | 32 +- .../Dialects/MySQLTransactionSinkTest.php | 6 +- .../PostgreSQLTransactionSinkTest.php | 6 +- .../Dialects/SqliteTransactionSinkTest.php | 6 +- .../Tests/Unit/DbalTransactionSinkTest.php | 6 +- .../Tests/Unit/DbalTransactionTest.php | 12 +- .../ETL/Adapter/JSON/AdaptiveJSONEncoder.php | 43 + .../Adapter/JSON/AdaptiveJsonOpenSource.php | 98 + .../src/Flow/ETL/Adapter/JSON/JSONEncoder.php | 6 + .../JSON/JSONMachine/JsonExtractor.php | 33 +- .../JSON/JSONMachine/JsonLinesExtractor.php | 27 +- .../Flow/ETL/Adapter/JSON/JsonLinesLoader.php | 18 +- .../src/Flow/ETL/Adapter/JSON/JsonLoader.php | 18 +- .../Flow/ETL/Adapter/JSON/JsonOpenSource.php | 12 +- .../Flow/ETL/Adapter/JSON/JsonSinkOpener.php | 45 - .../ETL/Adapter/JSON/JsonSourceOpener.php | 97 - .../ETL/Adapter/JSON/NativeJSONEncoder.php | 42 - .../ETL/Adapter/JSON/NativeJsonOpenSource.php | 73 - .../Flow/ETL/Adapter/JSON/PhpJSONEncoder.php | 1 + .../ETL/Adapter/JSON/PhpJsonOpenSource.php | 4 + .../JSON/Tests/Context/JsonFixtureContext.php | 12 +- ...est.php => AdaptiveJsonOpenSourceTest.php} | 59 +- ...rceTest.php => RustJsonOpenSourceTest.php} | 34 +- ...efusalTest.php => RustJsonRefusalTest.php} | 20 +- .../JSON/Tests/Mother/JSONEncoderMother.php | 11 +- ...erTest.php => AdaptiveJSONEncoderTest.php} | 22 +- ...ncoderTest.php => RustJSONEncoderTest.php} | 32 +- .../Parquet/AdaptiveParquetOpenSink.php | 55 + .../Parquet/AdaptiveParquetOpenSource.php | 37 + .../Adapter/Parquet/EngineParquetOpener.php | 54 - .../Adapter/Parquet/NativeParquetOpenSink.php | 24 - .../Parquet/NativeParquetOpenSource.php | 57 - .../Adapter/Parquet/NativeParquetOpener.php | 66 - .../ETL/Adapter/Parquet/ParquetExtractor.php | 46 +- .../ETL/Adapter/Parquet/ParquetLoader.php | 7 +- .../ETL/Adapter/Parquet/ParquetOpenSink.php | 6 + .../ETL/Adapter/Parquet/ParquetOpenSource.php | 12 +- .../ETL/Adapter/Parquet/ParquetOpener.php | 38 - .../ETL/Adapter/Parquet/ParquetOpeners.php | 29 - .../Adapter/Parquet/ParquetSchemaPassFile.php | 4 - .../ETL/Adapter/Parquet/ParquetSourceFile.php | 14 +- ...uetOpenSink.php => PhpParquetOpenSink.php} | 10 +- ...penSource.php => PhpParquetOpenSource.php} | 6 +- .../Tests/Context/ParquetFilesContext.php | 17 +- .../Context/ParquetSourceFileContext.php | 15 +- .../Tests/Double/RecordingParquetEngine.php | 50 + .../Parquet/Tests/Integration/ParquetTest.php | 8 +- .../Unit/AdaptiveParquetOpenSinkTest.php | 132 + .../Unit/AdaptiveParquetOpenSourceTest.php | 76 + .../Tests/Unit/EngineParquetOpenerTest.php | 55 - .../Tests/Unit/NativeParquetOpenerTest.php | 70 - .../Tests/Unit/ParquetExtractorTest.php | 18 + .../Parquet/Tests/Unit/ParquetOpenersTest.php | 129 - .../Unit/ParquetSchemaConformanceTest.php | 16 +- .../Tests/Unit/ParquetSourceFileTest.php | 20 +- ...inkTest.php => PhpParquetOpenSinkTest.php} | 19 +- ...eTest.php => PhpParquetOpenSourceTest.php} | 8 +- ...nkTest.php => RustParquetOpenSinkTest.php} | 16 +- ...Test.php => RustParquetOpenSourceTest.php} | 44 +- .../Unit/SkipTransactionRollbackTest.php | 16 +- .../RegisterFilesystemFactoriesPassTest.php | 16 +- .../migration.php | 4 +- .../Unit/FlowPostgreSqlTransportTest.php | 4 +- .../src/Flow/ETL/Column/AdaptiveBackend.php | 44 + src/core/etl/src/Flow/ETL/Column/Backend.php | 6 + src/core/etl/src/Flow/ETL/Column/Column.php | 6 + .../etl/src/Flow/ETL/Column/ColumnBuilder.php | 6 + .../ETL/Column/Php/XmlElementPhysical.php | 6 +- src/core/etl/src/Flow/ETL/Config.php | 4 +- .../etl/src/Flow/ETL/Config/ConfigBuilder.php | 4 +- .../etl/src/Flow/ETL/Config/MemoryLimit.php | 4 +- src/core/etl/src/Flow/ETL/DSL/functions.php | 4 +- .../Flow/ETL/Join/HashJoin/NullRowBuilder.php | 4 +- .../Row/Formatter/ASCIISchemaFormatter.php | 4 +- src/core/etl/src/Flow/ETL/Rows.php | 10 +- src/core/etl/src/Flow/Floe/FloeExtractor.php | 4 +- src/core/etl/src/Flow/Floe/FloeMerger.php | 4 +- src/core/etl/src/Flow/Floe/FloeReader.php | 4 +- src/core/etl/src/Flow/Floe/FloeSerializer.php | 10 +- .../etl/src/Flow/Floe/FloeStreamReader.php | 8 +- .../Double/FakeStaticOrdersExtractor.php | 4 +- ...ackendTest.php => AdaptiveBackendTest.php} | 20 +- .../Tests/Unit/Column/ColumnWithTypeTest.php | 7 +- .../Unit/Column/Php/ElementPositionTest.php | 6 +- .../Unit/Comparator/ColumnComparatorTest.php | 4 +- .../tests/Flow/ETL/Tests/Unit/RowsTest.php | 4 +- .../Schema/Inference/InferredTypesTest.php | 4 +- src/extension/arrow-ext/Cargo.lock | 139 +- src/extension/arrow-ext/Cargo.toml | 2 +- src/extension/arrow-ext/build.rs | 17 +- src/extension/arrow-ext/composer.json | 3 +- .../php/Flow/Arrow/Parquet/ColumnsReader.php | 40 - .../{BatchReader.php => RustBatchReader.php} | 13 +- .../Flow/Arrow/Parquet/RustColumnsReader.php | 62 + .../{ArrowSchema.php => RustArrowSchema.php} | 4 +- .../{ArrowBatch.php => RustParquetBatch.php} | 4 +- .../Flow/Parquet/Engine/RustParquetEngine.php | 57 + .../Engine/RustParquetFileReader.php} | 33 +- .../Engine/RustParquetFileWriter.php} | 22 +- src/extension/arrow-ext/rustfmt.toml | 1 + src/extension/arrow-ext/src/interfaces.rs | 152 + src/extension/arrow-ext/src/lib.rs | 18 +- src/extension/arrow-ext/src/parquet/batch.rs | 56 +- .../arrow-ext/src/parquet/canonical.rs | 338 +- src/extension/arrow-ext/src/parquet/cells.rs | 115 +- src/extension/arrow-ext/src/parquet/engine.rs | 98 + src/extension/arrow-ext/src/parquet/error.rs | 98 +- src/extension/arrow-ext/src/parquet/fetch.rs | 55 +- src/extension/arrow-ext/src/parquet/footer.rs | 14 +- .../arrow-ext/src/parquet/lib_calls.rs | 22 + .../arrow-ext/src/parquet/library.rs | 486 +- src/extension/arrow-ext/src/parquet/mod.rs | 6 + .../arrow-ext/src/parquet/options.rs | 143 +- src/extension/arrow-ext/src/parquet/read.rs | 111 +- src/extension/arrow-ext/src/parquet/sink.rs | 2 +- src/extension/arrow-ext/src/parquet/source.rs | 12 +- src/extension/arrow-ext/src/php.rs | 81 +- src/extension/arrow-ext/src/render.rs | 26 +- .../arrow-ext/src/stream/output_stream.rs | 12 +- .../src/stream/random_access_file.rs | 10 +- src/extension/arrow-ext/src/thrift.rs | 72 +- src/extension/arrow-ext/src/values.rs | 24 +- .../tests/phpt/001_extension_loaded.phpt | 21 +- .../phpt/045_parquet_lib_read_parity.phpt | 13 +- .../phpt/046_parquet_lib_write_parity.phpt | 7 +- .../047_parquet_footer_thrift_parity.phpt | 12 +- .../tests/phpt/048_parquet_lib_no_leaks.phpt | 28 +- .../049_parquet_write_columns_parity.phpt | 12 +- .../phpt/050_parquet_batch_roundtrip.phpt | 26 +- .../051_parquet_interfaces_reflection.phpt | 26 + ..._parquet_file_reader_writer_contracts.phpt | 201 + .../phpt/053_columns_reader_refusal_ends.phpt | 74 + .../arrow-ext/tests/phpt/bootstrap.php | 34 + src/extension/flow-php-ext/Cargo.lock | 143 +- src/extension/flow-php-ext/Cargo.toml | 2 +- src/extension/flow-php-ext/build.rs | 8 +- src/extension/flow-php-ext/composer.json | 6 +- .../crates/flow-batch-frame/src/body.rs | 11 +- .../crates/flow-batch-frame/src/column.rs | 57 +- .../crates/flow-batch-frame/src/kind.rs | 16 +- .../crates/flow-batch-frame/src/layout.rs | 21 +- .../crates/flow-batch-frame/tests/body.rs | 64 +- .../crates/flow-batch-frame/tests/column.rs | 96 +- .../crates/flow-batch-frame/tests/kind.rs | 26 +- ...NativeCSVWriter.php => RustCSVEncoder.php} | 16 +- ...ReaderNative.php => RustCSVOpenSource.php} | 55 +- .../ETL/Adapter/CSV/RustColumnFoldNative.php | 46 - .../ETL/Adapter/JSON/NativeJsonReader.php | 55 - ...tiveJsonWriter.php => RustJSONEncoder.php} | 20 +- .../ETL/Adapter/JSON/RustJsonOpenSource.php | 44 + ...quetWriter.php => RustParquetOpenSink.php} | 8 +- ...etReader.php => RustParquetOpenSource.php} | 28 +- .../php/Flow/ETL/Column/RustBackend.php} | 28 +- ...iveArrowBatch.php => RustColumnsBatch.php} | 4 +- .../php/Flow/ETL/RustIterator.php | 52 + .../Floe/Exception/ExtensionException.php | 15 - src/extension/flow-php-ext/rustfmt.toml | 1 + src/extension/flow-php-ext/src/alloc.rs | 2 +- src/extension/flow-php-ext/src/arrow_c.rs | 73 +- src/extension/flow-php-ext/src/backend.rs | 112 +- .../flow-php-ext/src/batch_columns.rs | 59 +- src/extension/flow-php-ext/src/builder.rs | 96 +- src/extension/flow-php-ext/src/cast.rs | 42 +- src/extension/flow-php-ext/src/column.rs | 58 +- src/extension/flow-php-ext/src/csv/columns.rs | 18 +- src/extension/flow-php-ext/src/csv/fold.rs | 50 +- src/extension/flow-php-ext/src/csv/mod.rs | 41 +- src/extension/flow-php-ext/src/csv/source.rs | 434 + .../flow-php-ext/src/csv/tokenizer.rs | 16 +- src/extension/flow-php-ext/src/csv/write.rs | 74 +- src/extension/flow-php-ext/src/ctx.rs | 119 +- src/extension/flow-php-ext/src/date_check.rs | 7 +- src/extension/flow-php-ext/src/exception.rs | 33 +- src/extension/flow-php-ext/src/interfaces.rs | 202 +- src/extension/flow-php-ext/src/iterator.rs | 117 + src/extension/flow-php-ext/src/json/mod.rs | 5 + src/extension/flow-php-ext/src/json/read.rs | 221 +- src/extension/flow-php-ext/src/json/source.rs | 119 + src/extension/flow-php-ext/src/json/write.rs | 61 +- src/extension/flow-php-ext/src/json_check.rs | 5 +- .../flow-php-ext/src/kind_builder.rs | 125 +- src/extension/flow-php-ext/src/lib.rs | 156 +- src/extension/flow-php-ext/src/parquet/etl.rs | 207 +- src/extension/flow-php-ext/src/parquet/mod.rs | 4 + src/extension/flow-php-ext/src/physical.rs | 28 +- src/extension/flow-php-ext/src/plan.rs | 13 +- src/extension/flow-php-ext/src/render.rs | 64 +- src/extension/flow-php-ext/src/source.rs | 58 + src/extension/flow-php-ext/src/text/batch.rs | 89 +- src/extension/flow-php-ext/src/text/date.rs | 82 +- src/extension/flow-php-ext/src/text/json.rs | 49 +- src/extension/flow-php-ext/src/text/mod.rs | 2 +- src/extension/flow-php-ext/src/text/value.rs | 49 +- src/extension/flow-php-ext/src/values.rs | 54 +- .../tests/phpt/001_extension_loaded.phpt | 42 +- .../tests/phpt/040_csv_tokenizer_parity.phpt | 8 +- .../tests/phpt/045_csv_no_leaks.phpt | 25 +- .../tests/phpt/046_csv_narrow_parity.phpt | 8 +- .../tests/phpt/048_csv_widen_parity.phpt | 25 +- .../tests/phpt/049_csv_fold_no_leaks.phpt | 27 +- .../tests/phpt/051_csv_guards.phpt | 64 +- .../tests/phpt/054_csv_consumed_bytes.phpt | 8888 ++++++++++++++++- .../phpt/055_column_interfaces_skew.phpt | 2 +- .../phpt/056_native_constructors_refused.phpt | 24 +- .../tests/phpt/057_native_encode_parity.phpt | 6 +- .../tests/phpt/058_native_values_parity.phpt | 4 +- .../tests/phpt/059_native_cast_parity.phpt | 6 +- .../phpt/060_native_decode_refusals.phpt | 6 +- .../phpt/061_native_mixed_class_building.phpt | 18 +- .../tests/phpt/062_native_no_leaks.phpt | 4 +- .../phpt/063_csv_next_columns_parity.phpt | 14 +- .../phpt/064_csv_next_columns_no_leaks.phpt | 30 +- .../tests/phpt/065_type_plan_by_object.phpt | 4 +- .../066_iso_datetime_fast_path_parity.phpt | 15 +- .../067_adopt_refuses_untyped_column.phpt | 10 +- .../tests/phpt/068_parquet_read_parity.phpt | 14 +- .../tests/phpt/069_parquet_offset_limit.phpt | 17 +- .../phpt/070_parquet_write_roundtrip.phpt | 19 +- .../tests/phpt/071_parquet_no_leaks.phpt | 23 +- .../phpt/072_parquet_allocations_counted.phpt | 24 +- .../tests/phpt/077_text_float_parity.phpt | 14 +- .../phpt/078_text_json_string_parity.phpt | 6 +- .../phpt/079_text_date_format_parity.phpt | 27 +- .../tests/phpt/080_csv_write_parity.phpt | 14 +- .../tests/phpt/081_json_write_parity.phpt | 12 +- .../tests/phpt/082_write_no_leaks.phpt | 63 +- .../phpt/084_native_nested_cast_parity.phpt | 6 +- .../phpt/085_native_nested_cast_no_leaks.phpt | 4 +- .../tests/phpt/086_json_read_parity.phpt | 49 +- .../tests/phpt/087_json_read_no_leaks.phpt | 10 +- .../tests/phpt/088_json_read_streaming.phpt | 14 +- .../phpt/089_parquet_arrow_c_no_leaks.phpt | 36 +- .../090_parquet_schema_refused_at_open.phpt | 21 +- ...091_parquet_canonical_layout_contract.phpt | 15 +- .../phpt/092_failure_without_autoloader.phpt | 24 + .../phpt/093_adapter_writers_contracts.phpt | 71 + .../094_rust_iterator_generator_parity.phpt | 95 + .../phpt/095_sources_reentrant_stream.phpt | 109 + .../096_encoders_columns_left_to_php.phpt | 45 + .../flow-php-ext/tests/phpt/bootstrap.php | 266 +- .../filesystem/src/Flow/Filesystem/Path.php | 8 +- .../Parquet/Engine/AdaptiveParquetEngine.php | 12 +- .../Parquet/Engine/Arrow/OptionsConverter.php | 17 + .../Parquet/Engine/Arrow/SchemaConverter.php | 1 + .../Parquet/Engine/ArrowParquetEngine.php | 84 - .../Parquet/Engine/ArrowParquetFileReader.php | 109 - .../Parquet/Engine/ArrowParquetFileWriter.php | 58 - .../Parquet/Engine/PhpParquetFileReader.php | 6 + .../src/Flow/Parquet/ParquetEngine.php | 6 + .../src/Flow/Parquet/ParquetFile/Metadata.php | 1 + .../src/Flow/Parquet/ParquetFile/Schema.php | 1 + .../src/Flow/Parquet/ParquetFileReader.php | 12 +- .../src/Flow/Parquet/ParquetFileWriter.php | 6 + src/lib/parquet/src/Flow/Parquet/Reader.php | 6 - src/lib/parquet/src/Flow/Parquet/Writer.php | 8 - .../Engine/ArrowParquetFileReaderTest.php | 115 - .../Integration/Engine/CrossEngineTest.php | 8 +- .../Integration/Engine/EngineParityTest.php | 7 +- .../Integration/Engine/ReadColumnsTest.php | 6 +- ...ibParityTest.php => RustLibParityTest.php} | 29 +- ...sionTest.php => RustLibRegressionTest.php} | 67 +- ...ityTest.php => RustLibWriteParityTest.php} | 17 +- ...Test.php => RustParquetEngineReadTest.php} | 22 +- ...est.php => RustParquetEngineWriteTest.php} | 12 +- .../Tests/Integration/IO/CompressionTest.php | 26 +- .../Integration/IO/EdgeCasesReadingTest.php | 11 +- .../IO/FixedLenByteArrayReadingTest.php | 8 +- .../Tests/Integration/IO/ListsReadingTest.php | 20 +- .../Tests/Integration/IO/ListsWritingTest.php | 35 +- .../IO/LogicalTypesReadingTest.php | 20 +- .../IO/LogicalTypesWritingTest.php | 22 +- .../Tests/Integration/IO/MapsReadingTest.php | 29 +- .../Tests/Integration/IO/MapsWritingTest.php | 20 +- .../Tests/Integration/IO/PaginationTest.php | 35 +- .../IO/ParquetIntegrationTestCase.php | 19 +- .../Tests/Integration/IO/ReaderTest.php | 8 +- .../Integration/IO/SchemaReadingTest.php | 17 +- .../Integration/IO/SimpleTypesReadingTest.php | 89 +- .../Integration/IO/SimpleTypesWritingTest.php | 92 +- .../Integration/IO/StructsReadingTest.php | 35 +- .../Integration/IO/StructsWritingTest.php | 11 +- .../Tests/Integration/IO/WriterTest.php | 59 +- .../Tests/Mother/ParquetEngineMother.php | 22 + .../Unit/Engine/AdaptiveParquetEngineTest.php | 88 +- .../Engine/Arrow/OptionsConverterTest.php | 22 + .../Unit/Engine/ArrowParquetEngineTest.php | 71 - .../Engine/ArrowParquetFileWriterTest.php | 311 - .../Unit/Engine/RustParquetEngineTest.php | 49 + .../Flow/Parquet/Tests/Unit/ReaderTest.php | 17 +- .../Flow/Parquet/Tests/Unit/WriterTest.php | 19 +- .../Constraint/ForeignKeyConstraintTest.php | 16 +- .../Telemetry/SignalLimitsIntegrationTest.php | 16 +- .../Tests/Unit/DSL/FunctionsTest.php | 4 +- .../AttributeFilteringLogMiddlewareTest.php | 4 +- tools/box/composer.lock | 155 +- tools/infection/composer.lock | 126 +- tools/mago/composer.lock | 12 +- tools/monorepo/composer.lock | 120 +- tools/phpbench/composer.lock | 80 +- tools/phpunit/composer.lock | 12 +- web/landing/resources/dsl.json | 2 +- 334 files changed, 17100 insertions(+), 5662 deletions(-) create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVEncoder.php create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php delete mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSinkOpener.php delete mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSourceOpener.php delete mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVEncoder.php delete mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/AdaptiveCSVOpenSourceTest.php delete mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVSourceOpenerTest.php rename src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/{NativeCSVOpenSourceTest.php => RustCSVOpenSourceTest.php} (79%) create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/AdaptiveCSVEncoderTest.php delete mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSinkOpenerTest.php delete mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSourceOpenerTest.php rename src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/{NativeCSVEncoderTest.php => RustCSVEncoderTest.php} (74%) create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJSONEncoder.php create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php delete mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSinkOpener.php delete mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSourceOpener.php delete mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJSONEncoder.php delete mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJsonOpenSource.php rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/{JsonSourceOpenerTest.php => AdaptiveJsonOpenSourceTest.php} (68%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/{NativeJsonOpenSourceTest.php => RustJsonOpenSourceTest.php} (76%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/{NativeJsonRefusalTest.php => RustJsonRefusalTest.php} (88%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/{JsonSinkOpenerTest.php => AdaptiveJSONEncoderTest.php} (71%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/{NativeJSONEncoderTest.php => RustJSONEncoderTest.php} (74%) create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSource.php delete mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php delete mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSink.php delete mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php delete mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php delete mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php delete mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php rename src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/{EngineParquetOpenSink.php => PhpParquetOpenSink.php} (53%) rename src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/{EngineParquetOpenSource.php => PhpParquetOpenSource.php} (88%) create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Double/RecordingParquetEngine.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSourceTest.php delete mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php delete mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php delete mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php rename src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/{EngineParquetOpenSinkTest.php => PhpParquetOpenSinkTest.php} (71%) rename src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/{EngineParquetOpenSourceTest.php => PhpParquetOpenSourceTest.php} (90%) rename src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/{NativeParquetOpenSinkTest.php => RustParquetOpenSinkTest.php} (90%) rename src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/{NativeParquetOpenSourceTest.php => RustParquetOpenSourceTest.php} (66%) create mode 100644 src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{DefaultBackendTest.php => AdaptiveBackendTest.php} (74%) delete mode 100644 src/extension/arrow-ext/php/Flow/Arrow/Parquet/ColumnsReader.php rename src/extension/arrow-ext/php/Flow/Arrow/Parquet/{BatchReader.php => RustBatchReader.php} (70%) create mode 100644 src/extension/arrow-ext/php/Flow/Arrow/Parquet/RustColumnsReader.php rename src/extension/arrow-ext/php/Flow/Arrow/{ArrowSchema.php => RustArrowSchema.php} (78%) rename src/extension/arrow-ext/php/Flow/Arrow/{ArrowBatch.php => RustParquetBatch.php} (91%) create mode 100644 src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetEngine.php rename src/extension/arrow-ext/php/Flow/{Arrow/Parquet/ParquetFile.php => Parquet/Engine/RustParquetFileReader.php} (54%) rename src/extension/arrow-ext/php/Flow/{Arrow/Parquet/RowsWriter.php => Parquet/Engine/RustParquetFileWriter.php} (75%) create mode 100644 src/extension/arrow-ext/rustfmt.toml create mode 100644 src/extension/arrow-ext/src/interfaces.rs create mode 100644 src/extension/arrow-ext/src/parquet/engine.rs create mode 100644 src/extension/arrow-ext/src/parquet/lib_calls.rs create mode 100644 src/extension/arrow-ext/tests/phpt/051_parquet_interfaces_reflection.phpt create mode 100644 src/extension/arrow-ext/tests/phpt/052_parquet_file_reader_writer_contracts.phpt create mode 100644 src/extension/arrow-ext/tests/phpt/053_columns_reader_refusal_ends.phpt rename src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/{NativeCSVWriter.php => RustCSVEncoder.php} (64%) rename src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/{RustCSVReaderNative.php => RustCSVOpenSource.php} (51%) delete mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustColumnFoldNative.php delete mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonReader.php rename src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/{NativeJsonWriter.php => RustJSONEncoder.php} (55%) create mode 100644 src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJsonOpenSource.php rename src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/{NativeParquetWriter.php => RustParquetOpenSink.php} (74%) rename src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/{NativeParquetReader.php => RustParquetOpenSource.php} (52%) rename src/{core/etl/src/Flow/ETL/Column/DefaultBackend.php => extension/flow-php-ext/php/Flow/ETL/Column/RustBackend.php} (57%) rename src/extension/flow-php-ext/php/Flow/ETL/Column/{NativeArrowBatch.php => RustColumnsBatch.php} (91%) create mode 100644 src/extension/flow-php-ext/php/Flow/ETL/RustIterator.php delete mode 100644 src/extension/flow-php-ext/php/Flow/Floe/Exception/ExtensionException.php create mode 100644 src/extension/flow-php-ext/rustfmt.toml create mode 100644 src/extension/flow-php-ext/src/csv/source.rs create mode 100644 src/extension/flow-php-ext/src/iterator.rs create mode 100644 src/extension/flow-php-ext/src/json/source.rs create mode 100644 src/extension/flow-php-ext/src/source.rs create mode 100644 src/extension/flow-php-ext/tests/phpt/092_failure_without_autoloader.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/093_adapter_writers_contracts.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/094_rust_iterator_generator_parity.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/095_sources_reentrant_stream.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/096_encoders_columns_left_to_php.phpt delete mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php delete mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php delete mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileWriter.php delete mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetFileReaderTest.php rename src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/{NativeLibParityTest.php => RustLibParityTest.php} (81%) rename src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/{NativeLibRegressionTest.php => RustLibRegressionTest.php} (73%) rename src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/{NativeLibWriteParityTest.php => RustLibWriteParityTest.php} (90%) rename src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/{ArrowParquetEngineReadTest.php => RustParquetEngineReadTest.php} (95%) rename src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/{ArrowParquetEngineWriteTest.php => RustParquetEngineWriteTest.php} (94%) create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Mother/ParquetEngineMother.php delete mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php delete mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/RustParquetEngineTest.php diff --git a/.github/workflows/job-arrow-extension.yml b/.github/workflows/job-arrow-extension.yml index 1f134780ee..f73ad4045f 100644 --- a/.github/workflows/job-arrow-extension.yml +++ b/.github/workflows/job-arrow-extension.yml @@ -34,7 +34,7 @@ jobs: install-dependencies: 'false' - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable + uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable with: toolchain: stable @@ -141,7 +141,7 @@ jobs: tools: 'composer:v2, phpize, php-config' - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable + uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable with: toolchain: stable diff --git a/.github/workflows/job-flow-php-extension.yml b/.github/workflows/job-flow-php-extension.yml index a99f97f359..c47cd6204e 100644 --- a/.github/workflows/job-flow-php-extension.yml +++ b/.github/workflows/job-flow-php-extension.yml @@ -34,7 +34,7 @@ jobs: install-dependencies: 'false' - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable + uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable with: toolchain: stable @@ -164,7 +164,7 @@ jobs: tools: 'composer:v2, phpize, php-config' - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable + uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable with: toolchain: stable diff --git a/benchmarks/suites/Format/Parquet/ParquetReadBench.php b/benchmarks/suites/Format/Parquet/ParquetReadBench.php index 86c7f670ff..366d7fa6ee 100644 --- a/benchmarks/suites/Format/Parquet/ParquetReadBench.php +++ b/benchmarks/suites/Format/Parquet/ParquetReadBench.php @@ -6,8 +6,8 @@ use Flow\Benchmarks\BenchmarkRows; use Flow\Benchmarks\Datasets\Datasets; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; use Generator; use PhpBench\Attributes as Bench; @@ -25,7 +25,7 @@ public function warm(array $params): void #[Bench\Groups(['format', 'format-parquet'])] public function bench_parquet_read(array $params): void { - $engine = $params['engine'] === ArrowParquetEngine::class ? new ArrowParquetEngine() : new PhpParquetEngine(); + $engine = $params['engine'] === RustParquetEngine::class ? new RustParquetEngine() : new PhpParquetEngine(); (new ParquetReadScenario((int) $params['rows'], $engine))->run(); } @@ -42,7 +42,7 @@ public function engines(): Generator yield 'php' => ['engine' => PhpParquetEngine::class]; if (extension_loaded('arrow')) { - yield 'arrow' => ['engine' => ArrowParquetEngine::class]; + yield 'arrow' => ['engine' => RustParquetEngine::class]; } } } diff --git a/benchmarks/suites/Format/Parquet/ParquetWriteBench.php b/benchmarks/suites/Format/Parquet/ParquetWriteBench.php index 6ffe41410d..0abe5acc71 100644 --- a/benchmarks/suites/Format/Parquet/ParquetWriteBench.php +++ b/benchmarks/suites/Format/Parquet/ParquetWriteBench.php @@ -6,8 +6,8 @@ use Flow\Benchmarks\BenchmarkRows; use Flow\Benchmarks\Datasets\Datasets; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; use Generator; use PhpBench\Attributes as Bench; @@ -25,7 +25,7 @@ public function warm(array $params): void #[Bench\Groups(['format', 'format-parquet'])] public function bench_parquet_write(array $params): void { - $engine = $params['engine'] === ArrowParquetEngine::class ? new ArrowParquetEngine() : new PhpParquetEngine(); + $engine = $params['engine'] === RustParquetEngine::class ? new RustParquetEngine() : new PhpParquetEngine(); (new ParquetWriteScenario((int) $params['rows'], $engine))->run(); } @@ -42,7 +42,7 @@ public function engines(): Generator yield 'php' => ['engine' => PhpParquetEngine::class]; if (extension_loaded('arrow')) { - yield 'arrow' => ['engine' => ArrowParquetEngine::class]; + yield 'arrow' => ['engine' => RustParquetEngine::class]; } } } diff --git a/documentation/components/adapters/parquet.md b/documentation/components/adapters/parquet.md index 41f32b7822..6dbb9bcb52 100644 --- a/documentation/components/adapters/parquet.md +++ b/documentation/components/adapters/parquet.md @@ -25,7 +25,7 @@ For detailed installation instructions, see the [installation page](/documentati ## Engines Without `engine:`, Parquet is read and written by the [`flow_php` extension](/documentation/components/extensions/flow-php-ext.md) -when it is loaded, else by `AdaptiveParquetEngine`. An explicit engine is always used: +and arrow-ext when both are loaded, else by `AdaptiveParquetEngine`. An explicit engine is always used: ```php readFrom(path('data.parquet'))); // one footer read +$file = new RustParquetFileReader($filesystem->readFrom(path('data.parquet'))); // Flow\Parquet\ParquetFileReader, one footer read $file->rowsNumber(); +$file->schema(); // Flow\Parquet\ParquetFile\Schema +$file->metadata(); // Flow\Parquet\ParquetFile\Metadata $file->thrift(); // Flow\Parquet\ThriftModel\FileMetaData -$columns = new ColumnsReader($file, ['id', 'name'], batchSize: 1_000, offset: null, limit: null); - -while (($chunk = $columns->next()) !== null) { +foreach ($file->readColumns(['id', 'name'], 1_000, null, null) as $chunk) { // RustColumnsReader, an Iterator that streams once // ['id' => [1, 2, ...], 'name' => ['a', 'b', ...]] } -$writer = new RowsWriter( +$writer = new RustParquetFileWriter( // Flow\Parquet\ParquetFileWriter $filesystem->writeTo(path('out.parquet')), SchemaConverter::toExtension($schema), // Flow\Parquet\ParquetFile\Schema - 'SNAPPY', + Compressions::SNAPPY, // LZO is refused OptionsConverter::toExtension(Options::default()), batchSize: 1_000, ); -$writer->writeRows([['id' => 1, 'name' => 'a']]); +$writer->writeBatch([['id' => 1, 'name' => 'a']]); // an array or any Traversable of rows $writer->writeColumns(['id' => [2, 3], 'name' => ['b', null]]); $writer->close(); // footer, then the stream closed -$batches = new BatchReader($file, ['id', 'name'], batchSize: 1_000, offset: null, limit: null); -$batches->schema(); // Flow\Arrow\ArrowSchema -$batches->next(); // Flow\Arrow\ArrowBatch, null after the last +$batches = new RustBatchReader($file, ['id', 'name'], batchSize: 1_000, offset: null, limit: null); +$batches->schema(); // Flow\Arrow\RustArrowSchema +$batches->next(); // Flow\Arrow\RustParquetBatch, null after the last ``` Refusals are the `Flow\Parquet\Exception\*` the PHP engine throws; an exception the stream throws surfaces as itself. ### Arrow C Data Interface -`ArrowBatch` (`BatchReader::next()`) carries one struct array: `arrowSchemaAddress()` (`FFI_ArrowSchema*`) and +`RustParquetBatch` (`RustBatchReader::next()`) carries one struct array: `arrowSchemaAddress()` (`FFI_ArrowSchema*`) and `arrowArrayAddress()` (`FFI_ArrowArray*`). Its consumer, another extension, reads the schema by reference and moves the -array out. `RowsWriter::writeBatch()` takes the same pair from any extension's final internal class exposing both +array out. `RustParquetFileWriter::writeArrowBatch()` takes the same pair from any extension's final internal class exposing both methods, its children by writer column name. Userland cannot build either: the classes are final and their constructors throw. diff --git a/documentation/components/extensions/flow-php-ext.md b/documentation/components/extensions/flow-php-ext.md index 39e33f837e..26d6a6ad69 100644 --- a/documentation/components/extensions/flow-php-ext.md +++ b/documentation/components/extensions/flow-php-ext.md @@ -43,28 +43,39 @@ df() ->run(); ``` -With the extension loaded, `Flow\ETL\Column\DefaultBackend` - the default of `config_builder()->backend()` - is the -extension's class and every batch column is a `Flow\ETL\Column\NativeColumn` over an Apache Arrow array: +With the extension loaded, `Flow\ETL\Column\AdaptiveBackend` - the default of `config_builder()->backend()` - picks the +extension's `RustBackend` and every batch column is a `Flow\ETL\Column\RustColumn` over an Apache Arrow array: ```php builder(int_schema('id')); +$builder = (new RustBackend())->builder(int_schema('id')); $builder->appendMany([1, '2', 3.0]); -$column = $builder->finish(); // Flow\ETL\Column\NativeColumn +$column = $builder->finish(); // Flow\ETL\Column\RustColumn $column->values(); // [1, 2, 3] -(new DefaultBackend())->allocatedBytes(); // bytes held outside PHP's memory manager +(new RustBackend())->allocatedBytes(); // bytes held outside PHP's memory manager ``` -The extension registers the interfaces `Flow\ETL\Column\{Backend, Column, ColumnBuilder}`, the classes -`Flow\ETL\Column\{DefaultBackend, NativeColumn, NativeColumnBuilder}`, and `Flow\ETL\Adapter\CSV\RustCSVReaderNative` -and `Flow\ETL\Adapter\CSV\RustColumnFoldNative`, which read CSV straight into native columns and narrow string -columns to their types. +Every contract with a Rust and a PHP implementation follows one pattern: the extension registers the interface, the +`Rust*` class implements it, `Php*` is the PHP implementation and `Adaptive*` picks one by `extension_loaded()`. + +| contract | Rust | PHP | picked by | +|----------------------------------------------|-------------------------|------------------------|-----------------------------| +| `Flow\ETL\Column\Backend` | `RustBackend` | `PhpBackend` | `AdaptiveBackend` | +| `Flow\ETL\Adapter\CSV\CSVOpenSource` | `RustCSVOpenSource` | `PhpCSVOpenSource` | `AdaptiveCSVOpenSource` | +| `Flow\ETL\Adapter\CSV\CSVEncoder` | `RustCSVEncoder` | `PhpCSVEncoder` | `AdaptiveCSVEncoder` | +| `Flow\ETL\Adapter\JSON\JsonOpenSource` | `RustJsonOpenSource` | `PhpJsonOpenSource` | `AdaptiveJsonOpenSource` | +| `Flow\ETL\Adapter\JSON\JSONEncoder` | `RustJSONEncoder` | `PhpJSONEncoder` | `AdaptiveJSONEncoder` | +| `Flow\ETL\Adapter\Parquet\ParquetOpenSource` | `RustParquetOpenSource` | `PhpParquetOpenSource` | `AdaptiveParquetOpenSource` | +| `Flow\ETL\Adapter\Parquet\ParquetOpenSink` | `RustParquetOpenSink` | `PhpParquetOpenSink` | `AdaptiveParquetOpenSink` | + +The extension also registers `Flow\ETL\Column\{Column, ColumnBuilder}` (`RustColumn`, `RustColumnBuilder`) and +`Flow\ETL\RustIterator`, the iterator its sources return. ## CSV and JSON writers @@ -92,20 +103,20 @@ those columns, the rest of the batch stays native. `to_json()` and `to_json_line `JSON_THROW_ON_ERROR`, `JSON_UNESCAPED_SLASHES`, `JSON_UNESCAPED_UNICODE` and `JSON_PRESERVE_ZERO_FRACTION`; any other flag (`JSON_PRETTY_PRINT`, ...) writes through PHP. -The classes are `Flow\ETL\Adapter\CSV\NativeCSVWriter` and `Flow\ETL\Adapter\JSON\NativeJsonWriter`. +`RustCSVEncoder` / `RustJSONEncoder` hold the PHP encoder they render the PHP columns with. ## Parquet With both this extension and the [arrow extension](/documentation/components/extensions/arrow-ext.md) loaded, `from_parquet()` and `to_parquet()` without an `engine:` read and write native columns: arrow-ext reads and writes the -file, and its batches cross into `NativeColumn`s (and back) through the Arrow C Data Interface, without a copy and +file, and its batches cross into `RustColumn`s (and back) through the Arrow C Data Interface, without a copy and without a PHP value per cell. | loaded | `from_parquet()` / `to_parquet()` | |-----------------|----------------------------------------------------------------------------| | flow_php, arrow | native columns through the Arrow C Data Interface | -| arrow | `ArrowParquetEngine`, PHP values | -| flow_php | `PhpParquetEngine`; `DefaultBackend` adopts the values into native columns | +| arrow | `RustParquetEngine` (arrow-ext), PHP values | +| flow_php | `PhpParquetEngine`; `RustBackend` adopts the values into native columns | | neither | `PhpParquetEngine` | ```php @@ -128,10 +139,10 @@ df() ``` A schema type that stores another arrow type than the file column reads as is refused before the first batch. The -imported batches are counted by `DefaultBackend::allocatedBytes()` for as long as they live; arrow-ext's own read +imported batches are counted by `RustBackend::allocatedBytes()` for as long as they live; arrow-ext's own read buffers (a row group's projected column chunks, decode buffers) are not, so a `MemoryBudget` does not see them. Read and -write refusals are arrow-ext's `Flow\Parquet\Exception\*`, as with `ArrowParquetEngine`. +write refusals are arrow-ext's `Flow\Parquet\Exception\*`, as with `RustParquetEngine`. -The extension registers `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}` (over -`Flow\Arrow\Parquet\BatchReader` / `RowsWriter`) and `Flow\ETL\Column\NativeArrowBatch`, the batch it exports. +`RustParquetOpenSource` reads through arrow-ext's `Flow\Arrow\Parquet\RustBatchReader`, `RustParquetOpenSink` writes +through its `Flow\Parquet\Engine\RustParquetFileWriter`. diff --git a/documentation/components/libs/parquet.md b/documentation/components/libs/parquet.md index 90e5d9a278..3c4fae3a56 100644 --- a/documentation/components/libs/parquet.md +++ b/documentation/components/libs/parquet.md @@ -15,10 +15,10 @@ For detailed installation instructions, see the [installation page](/documentati ## Engine System - **PHP Engine** (`PhpParquetEngine`) - pure PHP, no extra dependencies beyond optional compression extensions. -- **Arrow Engine** (`ArrowParquetEngine`) - native Rust through the - [arrow extension](/documentation/components/extensions/arrow-ext.md); every compression codec is built in. -- **Adaptive Engine** (`AdaptiveParquetEngine`) - the default: `ArrowParquetEngine` when `arrow` is loaded, - `PhpParquetEngine` otherwise. +- **Rust Engine** (`RustParquetEngine`) - registered by the + [arrow extension](/documentation/components/extensions/arrow-ext.md), every compression codec built in. +- **Adaptive Engine** (`AdaptiveParquetEngine`) - the default: `RustParquetEngine` when the arrow extension is loaded, + `PhpParquetEngine` otherwise. A big-endian `Reader` uses `PhpParquetEngine`. ```php [!TIP] -> `new Writer()` uses the adaptive engine. Use `Writer::arrow()` or `Writer::php()` to explicitly select an engine. +> `new Writer()` uses `AdaptiveParquetEngine`. Use `Writer::php()` to select the PHP engine. > See [Engine System](#engine-system). and write our data: diff --git a/documentation/contributing/rust.md b/documentation/contributing/rust.md index 8e4a04815c..077e8c99d2 100644 --- a/documentation/contributing/rust.md +++ b/documentation/contributing/rust.md @@ -7,8 +7,8 @@ This document describes how to develop the two Rust PHP extensions in this monor | Extension | Package | What it provides | |---|---|---| -| `arrow-ext` | `flow-php/arrow-ext` | Parquet reader and writer powered by the [Apache Arrow](https://arrow.apache.org/) Rust ecosystem, exposed as `Flow\Arrow\Parquet\Reader` and `Flow\Arrow\Parquet\Writer` | -| `flow-php-ext` | `flow-php/flow-php-ext` | The native column backend (`Flow\ETL\Column\DefaultBackend`, `NativeColumn`, `NativeColumnBuilder` over Apache Arrow arrays) and the native CSV reader | +| `arrow-ext` | `flow-php/arrow-ext` | Parquet reader and writer powered by the [Apache Arrow](https://arrow.apache.org/) Rust ecosystem, exposed as `Flow\Parquet\Engine\RustParquetEngine` | +| `flow-php-ext` | `flow-php/flow-php-ext` | The native column backend (`Flow\ETL\Column\RustBackend`, `RustColumn`, `RustColumnBuilder` over Apache Arrow arrays) and the Rust CSV / JSON / Parquet sources and encoders | Both are optional. The pure-PHP implementations in `flow-php/etl` remain the canonical behaviour reference, and Flow routes to the native code automatically when the extension is loaded. @@ -58,17 +58,20 @@ src/extension/flow-php-ext/ ├── Makefile # Build orchestration ├── src/ # Rust source code │ ├── lib.rs # Extension entry point, module registration -│ ├── interfaces.rs # Flow\ETL\Column\{Backend, Column, ColumnBuilder}, registered at MINIT -│ ├── backend.rs # DefaultBackend -│ ├── column.rs # NativeColumn -│ ├── builder.rs # NativeColumnBuilder: native cast lanes, PHP lane for the rest +│ ├── interfaces.rs # the package interfaces the Rust classes implement, registered at MINIT +│ ├── iterator.rs # RustIterator, the iterator the Rust sources return +│ ├── backend.rs # RustBackend +│ ├── column.rs # RustColumn +│ ├── builder.rs # RustColumnBuilder: native cast lanes, PHP lane for the rest │ ├── kind_builder.rs # Arrow storage appended row by row │ ├── physical.rs # Arrow rows as physical and logical zvals │ ├── plan.rs # Per-type plan, cached by Type object and type JSON │ ├── render.rs # flow-batch-frame refusals as the PHP messages │ ├── cast.rs # Value casting │ ├── json_check.rs # JSON validation shared by casting and CSV inference -│ ├── csv/ # CSV tokenizer, reader, native columns and schema-inference fold +│ ├── csv/ # CSV tokenizer, RustCSVOpenSource, RustCSVEncoder, schema-inference fold +│ ├── json/ # RustJsonOpenSource, RustJSONEncoder +│ ├── parquet/ # RustParquetOpenSource, RustParquetOpenSink │ ├── ctx.rs # Request-scoped context and engine helpers │ ├── globals.rs # Module globals, RINIT/RSHUTDOWN │ ├── alloc.rs # Counting global allocator (allocatedBytes()) diff --git a/documentation/installation/docker.md b/documentation/installation/docker.md index 43ff05d7e4..a8f8530860 100644 --- a/documentation/installation/docker.md +++ b/documentation/installation/docker.md @@ -76,7 +76,7 @@ that Flow detects and uses automatically: | Extension | Package | Effect when loaded | |------------|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| | `flow_php` | [flow-php/flow-php-ext](/documentation/components/extensions/flow-php-ext.md) | the CSV reader and the schema narrower run native | -| `arrow` | [flow-php/arrow-ext](/documentation/components/extensions/arrow-ext.md) | `AdaptiveParquetEngine` selects `ArrowParquetEngine`, so Parquet reads and writes run native | +| `arrow` | [flow-php/arrow-ext](/documentation/components/extensions/arrow-ext.md) | `AdaptiveParquetEngine` picks arrow-ext's `RustParquetEngine`, so Parquet reads and writes run native | | `pg_query` | [flow-php/pg-query-ext](/documentation/components/extensions/pg-query-ext.md) | `Flow\PostgreSql\Parser` becomes usable at all - SQL parsing, normalization and AST manipulation | | `protobuf` | `pecl/protobuf` | `Flow\PostgreSql\Parser` decodes the parse tree in C instead of pure PHP - measured ~69x faster end to end | @@ -114,5 +114,5 @@ $ docker run --rm -v /dev/null:/usr/local/etc/php/conf.d/docker-php-ext-flow_php ``` Once a native engine is selected it does **not** silently degrade. Extension failures surface as -`Flow\Floe\Exception\ExtensionException`, which `FloeReader` and `FloeWriter` wrap as +`Flow\ETL\Exception\RuntimeException`, which `FloeReader` and `FloeWriter` wrap as `Flow\Floe\Exception\FloeException`. diff --git a/documentation/upgrading.md b/documentation/upgrading.md index d672ce6c75..e839e9266d 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -230,15 +230,17 @@ after it shift by one. `Stage::physical` is new - see the core documentation. | `a,b` / `"x\"y",1` / `"p",2` | 1 row: `{"a":"x\\\"y","b":"1\n\"p\""}` | 2 rows: `{"a":"x\\\"y","b":1}`, `{"a":"p","b":2}` | | `a,b` / `x"y,1` / `"p",2` | 1 row: `{"a":"x\"y","b":"1\n\"p\""}` | 2 rows: `{"a":"x\"y","b":1}`, `{"a":"p","b":2}` | -### 23) `flow-php/etl-adapter-csv` - `CSVOpenSource` is an interface, `CSVLineReader` takes the separator and escape - -| Before | After | -|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| -| `new CSVLineReader($enclosure, $charactersReadInLine, $removeBOM)` | `new CSVLineReader($enclosure, $separator, $escape, $charactersReadInLine, $removeBOM)` | -| `new CSVOpenSource($stream, $dialect, $encoder, $lineReader)` | `new PhpCSVOpenSource($stream, $encoder, $lineReader)`; `CSVOpenSource` is its interface | -| `$open->stream`, `$open->dialect`, `$open->encoder`, `$open->lineReader` | removed | -| `CSVFileReader::samples()` yields `Generator`s | yields `CSVFileSample` (`IteratorAggregate`); `$unit->getIterator()` for the generator | -| `CSVFileReader::sample($source)` | `new CSVFileSample($opener, $source)` | +### 23) `flow-php/etl-adapter-csv` - `CSVOpenSource` is an interface, `CSVSourceOpener` removed, `CSVLineReader` takes the separator and escape + +| Before | After | +|--------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `new CSVLineReader($enclosure, $charactersReadInLine, $removeBOM)` | `new CSVLineReader($enclosure, $separator, $escape, $charactersReadInLine, $removeBOM)` | +| `final class CSVOpenSource`, `new CSVOpenSource($stream, $dialect, $encoder, $lineReader)` | `interface CSVOpenSource`, implemented by `PhpCSVOpenSource` (`new PhpCSVOpenSource($stream, $decoder, $lineReader)`, a `CSVDecoder`), `RustCSVOpenSource` (flow_php) and `AdaptiveCSVOpenSource` | +| `$open->stream`, `$open->dialect`, `$open->encoder`, `$open->lineReader` | removed | +| `(new CSVSourceOpener($filesystem, $options))->open($source)` | `new AdaptiveCSVOpenSource($filesystem, $source, $options)` | +| `new CSVFileReader($opener, $sources)` | `new CSVFileReader($filesystem, $options, $sources)` | +| `CSVFileReader::samples()` yields `Generator`s | yields `CSVFileSample` (`IteratorAggregate`); `$unit->getIterator()` for the generator | +| `CSVFileReader::sample($source)` | `new CSVFileSample($filesystem, $options, $source)` | ### 24) `flow-php/etl` - Floe footer carries a statistics block, existing `.floe` files must be rewritten @@ -609,11 +611,11 @@ different instant; it now stays a `datetime` unless it is cast to a date explici ### 61) `flow-php/etl` - Floe takes a `Backend` -| Before | After | -|-------------------------------------------------------------------------------------------|-------------------------------------------| -| `?Hydrator $hydrator` on `FloeReader`, `FloeStreamReader`, `FloeSerializer`, `FloeMerger` | `Backend $backend = new DefaultBackend()` | -| `?Hydrator $hydrator` on `FloeWriter`, `FloeStreamWriter` | removed | -| `FloeMerger(Filesystem, ?Hydrator, Codec)` | `FloeMerger(Filesystem, Backend, Codec)` | +| Before | After | +|-------------------------------------------------------------------------------------------|--------------------------------------------| +| `?Hydrator $hydrator` on `FloeReader`, `FloeStreamReader`, `FloeSerializer`, `FloeMerger` | `Backend $backend = new AdaptiveBackend()` | +| `?Hydrator $hydrator` on `FloeWriter`, `FloeStreamWriter` | removed | +| `FloeMerger(Filesystem, ?Hydrator, Codec)` | `FloeMerger(Filesystem, Backend, Codec)` | ### 62) adapters - encoders split into decoders and encoders @@ -621,7 +623,6 @@ different instant; it now stays a `datetime` unless it is cast to a date explici |--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| | `CSVEncoder::decode()`, `CSVEncoder::headers()` | `CSVDecoder::decode()`, `CSVDecoder::headers()` | | `new CSVEncoder(withHeader:, emptyToNull:, ...)` | `new CSVDecoder(withHeader:, emptyToNull:, ...)` - `CSVEncoder` keeps only the write options | -| `PhpCSVOpenSource(..., CSVEncoder $encoder, ...)` | `PhpCSVOpenSource(..., CSVDecoder $decoder, ...)` | | `TextEncoder::decode()` | removed - `TextExtractor` builds `['text' => $line]` rows itself | | `XMLEncoder::decode()` | removed - `XMLReaderExtractor` builds `['node' => $xml]` rows itself | | `ExcelEncoder(withHeader:, convertEmptyToNull:, timeFormat:)`, `decode()`, `headers()` | `ExcelDecoder(withHeader:, convertEmptyToNull:)` with `decode()`, `headers()`; `ExcelEncoder(timeFormat:)` | @@ -678,37 +679,35 @@ Project with `from_parquet(..., columns: [...])`. Change a type after reading, e | an XML/HTML value that cannot be converted to or from its string while building a column throws `FloeException` | throws `Flow\ETL\Exception\InvalidArgumentException`, same message | ### 67) `flow-php/flow-php-ext`, `flow-php/etl`, `flow-php/etl-adapter-csv` - the extension is the column backend -| Before | After | -|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| -| `Flow\Floe\RustFloeEncoderNative`, `Flow\ETL\Row\RustRowHydratorNative` | removed | -| - | `flow_php` registers `Flow\ETL\Column\{Backend, Column, ColumnBuilder, DefaultBackend, NativeColumn, NativeColumnBuilder}` | -| any `flow_php` installs beside `flow-php/etl` | Composer refuses `ext-flow_php` < 0.45 (`conflict`); forced past it: `Class "Flow\ETL\Column\DefaultBackend" not found` | -| untagged builds report `0.44.1+65.g…` | `0.45.0-dev+65.g…` (next minor, pre-release) | -| `Backend` has `builder`, `constant`, `decode` | also `adopt(Definition, Column): Column` and `allocatedBytes(): int`; custom backends implement both | -| `Consumption` / `analyze()` / telemetry memory = `memory_get_usage()` | plus the configured backend's `allocatedBytes()` (native columns are not bound by `memory_limit`) | -| `new Consumption()` | `new Consumption(Backend)` | -| `new TelemetryContext(Logger, Tracer, Meter, TelemetryOptions)` | `new TelemetryContext(Backend, Logger, Tracer, Meter, TelemetryOptions)` | -| `new KWayMerge(References, int)` | `new KWayMerge(References, Backend, int)` | -| `new Joiner(Expression, Join, int)` | `new Joiner(Expression, Join, Backend, int)` | -| `AggregatedGroups::flush(int)` | `flush(int, FlowContext)` | -| `CountingProcessor::rows(int)` | `rows(int, Backend)` | -| `BucketingConfigBuilder::build(Path)`, `SortAlgorithmBuilder`, `GroupByAlgorithmBuilder`, `JoinAlgorithmBuilder`, `RepartitionAlgorithmBuilder` and their implementations `build(Path)` | `build(Path, Backend)` - custom algorithm builders implement the new signature | -| `new FilesystemBuckets(Filesystem, Path, int)` | `new FilesystemBuckets(Filesystem, Path, Backend, int)` (required) | -| sort merges, joins, group-by, `count()`, spilled bucket reads and partition filters build with `DefaultBackend` or `PhpBackend` | the configured backend | -| `Rows` rebuilds (`of`, the `concat` mixed lane, `matchTo` null fills, `unserialize()`), `Rows::join()`, `Rows::joinCross()` build with `PhpBackend` | `DefaultBackend`: native columns with the extension loaded, even under a configured `PhpBackend`, and `Consumption` does not count them | -| a CSV read with the extension and a configured `PhpBackend` | PHP columns (`Backend::adopt()`) | -| a native string/list column past 2 GiB of offsets | `OffsetOverflow` at `concat()` / `appendMany()`, as at `encode()` | +| Before | After | +|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------| +| `Flow\Floe\RustFloeEncoderNative`, `Flow\ETL\Row\RustRowHydratorNative` | removed | +| - | `flow_php` registers `Flow\ETL\Column\{Backend, Column, ColumnBuilder, RustBackend, RustColumn, RustColumnBuilder}` | +| any `flow_php` installs beside `flow-php/etl` | Composer refuses `ext-flow_php` < 0.45 (`conflict`); forced past it: `Class "Flow\ETL\Column\RustBackend" not found` | +| untagged builds report `0.44.1+65.g…` | `0.45.0-dev+65.g…` (next minor, pre-release) | +| `Backend` has `builder`, `constant`, `decode` | also `adopt(Definition, Column): Column` and `allocatedBytes(): int`; custom backends implement both | +| `Consumption` / `analyze()` / telemetry memory = `memory_get_usage()` | plus the configured backend's `allocatedBytes()` (native columns are not bound by `memory_limit`) | +| `new Consumption()` | `new Consumption(Backend)` | +| `new TelemetryContext(Logger, Tracer, Meter, TelemetryOptions)` | `new TelemetryContext(Backend, Logger, Tracer, Meter, TelemetryOptions)` | +| `new KWayMerge(References, int)` | `new KWayMerge(References, Backend, int)` | +| `new Joiner(Expression, Join, int)` | `new Joiner(Expression, Join, Backend, int)` | +| `AggregatedGroups::flush(int)` | `flush(int, FlowContext)` | +| `CountingProcessor::rows(int)` | `rows(int, Backend)` | +| `BucketingConfigBuilder::build(Path)`, `SortAlgorithmBuilder`, `GroupByAlgorithmBuilder`, `JoinAlgorithmBuilder`, `RepartitionAlgorithmBuilder` and their implementations `build(Path)` | `build(Path, Backend)` - custom algorithm builders implement the new signature | +| `new FilesystemBuckets(Filesystem, Path, int)` | `new FilesystemBuckets(Filesystem, Path, Backend, int)` (required) | +| sort merges, joins, group-by, `count()`, spilled bucket reads and partition filters build with `AdaptiveBackend` or `PhpBackend` | the configured backend | +| `Rows` rebuilds (`of`, the `concat` mixed lane, `matchTo` null fills, `unserialize()`), `Rows::join()`, `Rows::joinCross()` build with `PhpBackend` | `AdaptiveBackend`: native columns with the extension loaded, even under a configured `PhpBackend`, and `Consumption` does not count them | +| a CSV read with the extension and a configured `PhpBackend` | PHP columns (`Backend::adopt()`) | +| a native string/list column past 2 GiB of offsets | `OffsetOverflow` at `concat()` / `appendMany()`, as at `encode()` | ### 68) `flow-php/etl`, adapters - `RawRowValues` removed, CSV sources yield batches | Before | After | |---------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------| | `RawRowValues`; `SchemaSampler`, `SniffsColumnTypes`, `SchemaInferrer::infer()/sniff()`, `ColumnTypes::observe()` over it | plain `array` rows | -| `CSVOpenSource::records(): Generator` | `Generator>` | -| - | `CSVOpenSource::batches(Schema, int, Backend): Generator` | +| `CSVOpenSource::records(): Generator` | `Iterator>` | +| - | `CSVOpenSource::batches(Schema, int, Backend): Iterator` | | `CSVFileReader::batches(SourceFile, int): Generator>` returning the header | `batches(SourceFile, Schema, int, Backend): Generator`, no return value | -| `RustCSVReaderNative::next(): list` | `list>` | -| - | `RustCSVReaderNative::nextColumns(Schema, int): ?Rows` | ### 69) `flow-php/etl` - `Row` removed, `Rows` is a columnar batch @@ -863,7 +862,7 @@ public function eval(Rows $rows, FlowContext $context): Column | Before | After | |--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `from_parquet($path)` / `to_parquet($path)` - `AdaptiveParquetEngine` (arrow-ext when loaded, else the PHP engine) | with `flow_php` and arrow-ext loaded: arrow-ext's batches straight into native columns and back (Arrow C Data Interface); `flow_php` alone: the PHP engine, its values adopted into native columns; without `flow_php`: unchanged | -| `engine: new PhpParquetEngine()` / `new ArrowParquetEngine()` | `engine: new PhpParquetEngine()` opts out; `new ArrowParquetEngine()` / `new AdaptiveParquetEngine()` read and write native columns when both extensions are loaded | +| `engine: new PhpParquetEngine()` / `new ArrowParquetEngine()` | `engine: new PhpParquetEngine()` opts out; `new AdaptiveParquetEngine()` reads and writes native columns when both extensions are loaded, `new RustParquetEngine()` reads them | | a column type arrow-ext could not read failed inside arrow-ext | refused before the first batch: `Flow\Parquet\Exception\RuntimeException` `Parquet column "" () is not supported by the arrow Parquet reader; read the file with \Flow\Parquet\Reader::php()` | | `flow-php/etl-adapter-parquet` installable with any `flow_php` or arrow-ext version | `conflict: ext-flow_php <0.45`, `ext-arrow <0.45` - load extensions of this release or none | @@ -897,7 +896,7 @@ public function eval(Rows $rows, FlowContext $context): Column | `new ParquetFile($stream, $byteOrder, $options, $engine)` | `new ParquetFile($stream, $options, $engine->openForRead($stream))` | | a `ParquetFile` closed its stream only when destroyed | `ParquetFile::close()` closes its reader (once); `ParquetFile::reader()` returns it | -### 84) `flow-php/parquet` - `ArrowParquetEngine` reads and writes through arrow-ext's new Parquet core +### 84) `flow-php/parquet` - the arrow engine (`RustParquetEngine`, was `ArrowParquetEngine`) reads and writes through arrow-ext's new Parquet core | Before | After | |----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -910,7 +909,7 @@ public function eval(Rows $rows, FlowContext $context): Column | an offset read decoded every row group before the offset; page headers were read to the end of the file | only the row groups a read needs, each column chunk read once | | an `INTERVAL`, a path into a `LIST` / `MAP`, `LZO` or `INT96` under `Option::INT_96_AS_DATETIME = false` failed inside arrow-ext | refused before the first batch naming the column and `\Flow\Parquet\Reader::php()` | | `Reader::read()` returned without touching the file; an invalid file failed at `metadata()` | the footer is read when the file is opened: `Reader::read()` / `readStream()` throw `InvalidArgumentException` `Given file is not valid Parquet file: …` | -| `Flow\Arrow\Parquet\Reader` / `Writer` / `Exception` | removed: `Flow\Arrow\Parquet\{ParquetFile, ColumnsReader, RowsWriter, BatchReader}`; refusals are `Flow\Parquet\Exception\*` | +| `Flow\Arrow\Parquet\Reader` / `Writer` / `Exception` | removed: `Flow\Parquet\Engine\{RustParquetFileReader, RustParquetFileWriter}`, `Flow\Arrow\Parquet\{RustColumnsReader, RustBatchReader}`; refusals are `Flow\Parquet\Exception\*` | | `flow-php/parquet` installable with any arrow-ext version | `conflict: ext-arrow <0.45` | ### 85) `flow-php/parquet` - `PhpParquetEngine` reads unsigned integers and INT96 exactly; `FlatColumn::enum()` writes the ENUM logical type; values it wrote wrongly are refused @@ -930,9 +929,9 @@ public function eval(Rows $rows, FlowContext $context): Column ### 86) `flow-php/arrow-ext` - Parquet core replaced -| Before | After | -|-------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `Flow\Arrow\Parquet\Reader` / `Writer` - PHP values per call (`readRowGroup()`, `writeBatch()`) | `Flow\Arrow\Parquet\{ParquetFile, ColumnsReader, RowsWriter, BatchReader}` - the values `PhpParquetEngine` reads and accepts; `BatchReader` and `RowsWriter::writeBatch()` hand batches to other extensions through the Arrow C Data Interface | +| Before | After | +|-------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Flow\Arrow\Parquet\Reader` / `Writer` - PHP values per call (`readRowGroup()`, `writeBatch()`) | `Flow\Parquet\Engine\{RustParquetEngine, RustParquetFileReader, RustParquetFileWriter}` implement `ParquetEngine`, `ParquetFileReader`, `ParquetFileWriter` - the values `PhpParquetEngine` reads and accepts; `Flow\Arrow\Parquet\RustBatchReader` and `RustParquetFileWriter::writeArrowBatch()` hand batches to other extensions through the Arrow C Data Interface | ### 87) `flow-php/etl-adapter-csv` - `to_csv()` writes a boolean as `true` / `false` @@ -970,23 +969,23 @@ holds another value, `ini_set()` must be allowed; otherwise the writers throw ### 90) `flow-php/etl-adapter-csv` - `CSVEncoder` is a contract; `PhpCSVEncoder` takes `CSVWriteOptions` and returns one string per batch -| Before | After | -|-------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------| -| `final class CSVEncoder` | `interface CSVEncoder { encode(Rows): string; encodeHeader(array $headers): string; }`, implemented by `PhpCSVEncoder` and `NativeCSVEncoder` | -| `new CSVEncoder($separator, $enclosure, $escape, $dateTimeFormat, $dateFormat, $newLineSeparator)` | `new PhpCSVEncoder(new CSVWriteOptions($separator, $enclosure, $escape, $newLineSeparator, $dateTimeFormat, $dateFormat))` | -| `CSVEncoder::encode(Rows): list` | `encode(Rows): string` | -| `CSVLoader::write(Rows, array $headers, array $partitions)` | removed - `load()` is the only entry | -| a separator or enclosure that is not one byte, an escape longer than one byte - failed in `fputcsv()` | `InvalidArgumentException` from `CSVWriteOptions` | +| Before | After | +|-------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `final class CSVEncoder` | `interface CSVEncoder { encode(Rows): string; encodeHeader(array $headers): string; }`, implemented by `PhpCSVEncoder`, `RustCSVEncoder` (flow_php) and `AdaptiveCSVEncoder` | +| `new CSVEncoder($separator, $enclosure, $escape, $dateTimeFormat, $dateFormat, $newLineSeparator)` | `new PhpCSVEncoder(new CSVWriteOptions($separator, $enclosure, $escape, $newLineSeparator, $dateTimeFormat, $dateFormat))` | +| `CSVEncoder::encode(Rows): list` | `encode(Rows): string` | +| `CSVLoader::write(Rows, array $headers, array $partitions)` | removed - `load()` is the only entry | +| a separator or enclosure that is not one byte, an escape longer than one byte - failed in `fputcsv()` | `InvalidArgumentException` from `CSVWriteOptions` | ### 91) `flow-php/etl-adapter-json` - `JSONEncoder` is a contract; `PhpJSONEncoder` returns JSON text; `JsonDocuments` and the loaders' `write()` are removed -| Before | After | -|--------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------| -| `final class JSONEncoder` | `interface JSONEncoder { encode(Rows, string $separator): string; }`, implemented by `PhpJSONEncoder` and `NativeJSONEncoder` | -| `new JSONEncoder($dateTimeFormat, $dateFormat)` | `new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat)` | -| `JSONEncoder::encode(Rows): list>` | `encode(Rows, string $separator): string` - one object per row, joined by `$separator` | -| `JsonDocuments`, `JsonLoader::write()`, `JsonLinesLoader::write()` | removed - `load()` is the only entry | -| no constraint on the extension | `"conflict": {"ext-flow_php": "<0.45"}` - upgrade the `flow_php` extension with the package | +| Before | After | +|--------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `final class JSONEncoder` | `interface JSONEncoder { encode(Rows, string $separator): string; }`, implemented by `PhpJSONEncoder`, `RustJSONEncoder` (flow_php) and `AdaptiveJSONEncoder` | +| `new JSONEncoder($dateTimeFormat, $dateFormat)` | `new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat)` | +| `JSONEncoder::encode(Rows): list>` | `encode(Rows, string $separator): string` - one object per row, joined by `$separator` | +| `JsonDocuments`, `JsonLoader::write()`, `JsonLinesLoader::write()` | removed - `load()` is the only entry | +| no constraint on the extension | `"conflict": {"ext-flow_php": "<0.45"}` - upgrade the `flow_php` extension with the package | ### 92) `flow-php/etl-adapter-xml` - `XMLWriter` renders columns; `XMLEncoder::encode()` returns one string per batch @@ -1127,6 +1126,30 @@ before. | content after the closing `]` (`[{"id":1}] x`) | ignored | `Malformed JSON in "" at element N: …` | | a scalar JSON line (`5`) | `JsonMachine\Exception\SyntaxErrorException` | `A JSON record must be an object or an array, int given in "".` | +### 105) `flow-php/parquet` - `ArrowParquetEngine`, `ArrowParquetFileWriter` and the `arrow()` factories removed + +| Before | After | +|----------------------------------------------------------------------------|--------------------------------------------------------------------------| +| `new ArrowParquetEngine($options)` | `new RustParquetEngine($options)` - arrow-ext's class | +| `Reader::arrow($options)` | `new Reader(options: $options, engine: new RustParquetEngine($options))` | +| `Writer::arrow($compression, $options)` | `new Writer($compression, $options, new RustParquetEngine())` | +| `ArrowParquetEngine::mapCompression($compression)` | removed - `RustParquetFileWriter` takes the `Compressions` case | +| `new ArrowParquetFileWriter(...)` | `RustParquetEngine::openForWrite(...)`, a `RustParquetFileWriter` | +| `new Reader(ByteOrder::BIG_ENDIAN)` with `arrow` loaded read through arrow | reads through `PhpParquetEngine` | + +`AdaptiveParquetEngine` stays the default of `Reader` and `Writer`. `Reader::php()` / `Writer::php()` stay. + +### 106) `flow-php/etl` - `Flow\Floe\Exception\ExtensionException` removed + +| Before | After | +|-----------------------------------------------------|--------------------------------------------------| +| `catch (Flow\Floe\Exception\ExtensionException $e)` | `catch (Flow\ETL\Exception\RuntimeException $e)` | + +flow_php throws `Flow\ETL\Exception\RuntimeException`, plain `\Exception` when `flow-php/etl` is not autoloadable. +`FloeStreamReader` wraps it as `FloeException`, `FloeSerializer` as `SerializationException`, both with the original +as `previous`; `FloeStreamWriter` lets it through. Both catch the base `Flow\ETL\Exception\RuntimeException` now, so +its subclasses thrown while decoding are wrapped as well. + --- ## Upgrading from 0.43.x to 0.44.x diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVEncoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVEncoder.php new file mode 100644 index 0000000000..8d3a8a4b32 --- /dev/null +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVEncoder.php @@ -0,0 +1,41 @@ +encoder = extension_loaded('flow_php') + ? new RustCSVEncoder( + $options->separator, + $options->enclosure, + $options->escape, + $options->newLineSeparator, + $options->dateTimeFormat, + $options->dateFormat, + $php, + ) + : $php; + } + + public function encode(Rows $rows): string + { + return $this->encoder->encode($rows); + } + + public function encodeHeader(array $headers): string + { + return $this->encoder->encodeHeader($headers); + } +} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php new file mode 100644 index 0000000000..18e99a735a --- /dev/null +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php @@ -0,0 +1,110 @@ +readFrom($source->path); + + // the callers' try/finally starts only after the constructor returns, and detection reads the stream + try { + $detected = csv_detect_separator($stream); + $dialect = new CSVDialect( + $options->separator ?? $detected->separator, + $options->enclosure ?? $detected->enclosure, + $options->escape ?? $detected->escape, + ); + + $this->source = extension_loaded('flow_php') + ? new RustCSVOpenSource( + $stream, + $dialect->separator, + $dialect->enclosure, + $dialect->escape, + $options->withHeader, + $options->emptyToNull, + $options->removeBOM, + $options->charactersReadInLine, + ) + : new PhpCSVOpenSource( + $stream, + new CSVDecoder( + withHeader: $options->withHeader, + separator: $dialect->separator, + enclosure: $dialect->enclosure, + escape: $dialect->escape, + emptyToNull: $options->emptyToNull, + ), + new CSVLineReader( + $dialect->enclosure, + $dialect->separator, + $dialect->escape, + $options->charactersReadInLine, + $options->removeBOM, + ), + ); + } catch (Throwable $e) { + $stream->close(); + + throw $e; + } + } + + public function close(): void + { + $this->source->close(); + } + + public function producedBytes(): int + { + return $this->source->producedBytes(); + } + + public function producedRows(): int + { + return $this->source->producedRows(); + } + + public function columns(): array + { + return $this->source->columns(); + } + + public function batches(Schema $schema, int $batchSize, Backend $backend): Iterator + { + return $this->source->batches($schema, $batchSize, $backend); + } + + public function headers(): array + { + return $this->source->headers(); + } + + public function records(): Iterator + { + return $this->source->records(); + } + + public function sniff(array $names, int $rowBudget, SchemaInference $inference, TypeNarrower $typer): ColumnTypes + { + return $this->source->sniff($names, $rowBudget, $inference, $typer); + } +} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php index bd1792eaaa..48df4f01f6 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php @@ -6,6 +6,12 @@ use Flow\ETL\Rows; +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} + interface CSVEncoder { public function encode(Rows $rows): string; 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 9b0c1bdcde..db1941dc16 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 @@ -100,7 +100,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); - $reader = new CSVFileReader(new CSVSourceOpener($this->filesystem, $this->readOptions), $sources); + $reader = new CSVFileReader($this->filesystem, $this->readOptions, $sources); if ($this->schema !== null) { $base = $this->schema; @@ -189,7 +189,8 @@ public function schema(): Schema if ($derived === null) { $reader = new CSVFileReader( - new CSVSourceOpener($this->filesystem, $this->readOptions), + $this->filesystem, + $this->readOptions, iterator_to_array($this->sourceFiles($this->filesystem, $this->path), false), ); diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php index d76a06a250..085302ff4a 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php @@ -9,6 +9,7 @@ use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaSampler; +use Flow\Filesystem\Filesystem; use Generator; final readonly class CSVFileReader implements SchemaSampler @@ -17,7 +18,8 @@ * @param list $sources materialised, not a Generator: header() and samples() both walk it */ public function __construct( - private CSVSourceOpener $opener, + private Filesystem $filesystem, + private CSVReadOptions $options, private array $sources, ) {} @@ -30,7 +32,7 @@ public function __construct( */ public function batches(SourceFile $source, Schema $schema, int $batchSize, Backend $backend): Generator { - $open = $this->opener->open($source); + $open = new AdaptiveCSVOpenSource($this->filesystem, $source, $this->options); try { yield from $open->batches($schema, $batchSize, $backend); @@ -44,7 +46,7 @@ public function batches(SourceFile $source, Schema $schema, int $batchSize, Back */ public function columns(SourceFile $source): array { - $open = $this->opener->open($source); + $open = new AdaptiveCSVOpenSource($this->filesystem, $source, $this->options); try { return $open->columns(); @@ -74,7 +76,7 @@ public function header(): CSVHeader public function samples(int $rowBudget): iterable { foreach ($this->sources as $source) { - yield new CSVFileSample($this->opener, $source); + yield new CSVFileSample($this->filesystem, $this->options, $source); } } } diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php index 593d89554e..e16b77672e 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php @@ -8,6 +8,7 @@ use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SniffsColumnTypes; +use Flow\Filesystem\Filesystem; use Flow\Types\Type\TypeNarrower; use Generator; use IteratorAggregate; @@ -20,7 +21,8 @@ final class CSVFileSample implements IteratorAggregate, SniffsColumnTypes private ?CSVSampledRows $sampled = null; public function __construct( - private readonly CSVSourceOpener $opener, + private readonly Filesystem $filesystem, + private readonly CSVReadOptions $options, private readonly SourceFile $source, ) {} @@ -31,7 +33,7 @@ public function __construct( */ public function getIterator(): Generator { - $open = $this->opener->open($this->source); + $open = new AdaptiveCSVOpenSource($this->filesystem, $this->source, $this->options); try { yield from $open->records(); @@ -46,7 +48,7 @@ public function sniffColumnTypes( SchemaInference $inference, TypeNarrower $typer, ): ColumnTypes { - $open = $this->opener->open($this->source); + $open = new AdaptiveCSVOpenSource($this->filesystem, $this->source, $this->options); try { $columnTypes = $open->sniff($names, $rowBudget, $inference, $typer); diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php index 0bcd085b07..1118c25996 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php @@ -47,7 +47,7 @@ final class CSVLoader implements Closure, Discardable, FileLoader, Loader, Parti private bool $header = true; - private ?CSVSinkOpener $opener = null; + private ?CSVWriteOptions $options = null; /** * @var array by stream URI @@ -118,8 +118,9 @@ public function load(Rows $rows, FlowContext $context): void $files = $this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode); $fresh = !$files->touched($partitions->toArray()); $stream = $files->writeTo($partitions->toArray()); - ($this->sinks[$stream->path()->uri()] ??= $this->opener()->open( + ($this->sinks[$stream->path()->uri()] ??= new CSVOpenSink( $stream, + new AdaptiveCSVEncoder($this->options()), $this->header && $fresh, ))->write($group); } @@ -188,15 +189,15 @@ public function withSeparator(string $separator): self return $this; } - private function opener(): CSVSinkOpener + private function options(): CSVWriteOptions { - return $this->opener ??= new CSVSinkOpener(new CSVWriteOptions( + return $this->options ??= new CSVWriteOptions( separator: $this->separator, enclosure: $this->enclosure, escape: $this->escape, newLineSeparator: $this->newLineSeparator, dateTimeFormat: $this->dateTimeFormat, dateFormat: $this->dateFormat, - )); + ); } } diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php index e8420fe20d..f6e56144e4 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php @@ -11,7 +11,13 @@ use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\Types\Type\TypeNarrower; -use Generator; +use Iterator; + +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} interface CSVOpenSource { @@ -46,9 +52,9 @@ public function columns(): array; * * @throws SchemaMismatchException * - * @return Generator + * @return Iterator */ - public function batches(Schema $schema, int $batchSize, Backend $backend): Generator; + public function batches(Schema $schema, int $batchSize, Backend $backend): Iterator; /** * The header records() resolved; [] before it ran or for a 0-byte source. @@ -60,9 +66,9 @@ public function headers(): array; /** * This instance is consumed afterwards. * - * @return Generator> + * @return Iterator> */ - public function records(): Generator; + public function records(): Iterator; /** * SchemaInferrer::sniff() over records(). This instance is consumed afterwards. diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSinkOpener.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSinkOpener.php deleted file mode 100644 index c7e2902311..0000000000 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSinkOpener.php +++ /dev/null @@ -1,39 +0,0 @@ -options); - - return new CSVOpenSink( - $stream, - extension_loaded('flow_php') - ? new NativeCSVEncoder( - new NativeCSVWriter( - $this->options->separator, - $this->options->enclosure, - $this->options->escape, - $this->options->newLineSeparator, - $this->options->dateTimeFormat, - $this->options->dateFormat, - ), - $php, - ) - : $php, - $header, - ); - } -} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSourceOpener.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSourceOpener.php deleted file mode 100644 index 72ac2f9ae1..0000000000 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVSourceOpener.php +++ /dev/null @@ -1,69 +0,0 @@ -filesystem->readFrom($source->path); - - // the callers' try/finally starts only after open() returns, and detection reads the stream - try { - $detected = csv_detect_separator($stream); - $dialect = new CSVDialect( - $this->options->separator ?? $detected->separator, - $this->options->enclosure ?? $detected->enclosure, - $this->options->escape ?? $detected->escape, - ); - - if (NativeCSVOpenSource::isSupported()) { - return new NativeCSVOpenSource( - $stream, - new RustCSVReaderNative( - $dialect->separator, - $dialect->enclosure, - $dialect->escape, - $this->options->withHeader, - $this->options->emptyToNull, - $this->options->removeBOM, - ), - $this->options->charactersReadInLine, - ); - } - - return new PhpCSVOpenSource( - $stream, - new CSVDecoder( - withHeader: $this->options->withHeader, - separator: $dialect->separator, - enclosure: $dialect->enclosure, - escape: $dialect->escape, - emptyToNull: $this->options->emptyToNull, - ), - new CSVLineReader( - $dialect->enclosure, - $dialect->separator, - $dialect->escape, - $this->options->charactersReadInLine, - $this->options->removeBOM, - ), - ); - } catch (Throwable $e) { - $stream->close(); - - throw $e; - } - } -} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVEncoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVEncoder.php deleted file mode 100644 index 39ef7aaa04..0000000000 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVEncoder.php +++ /dev/null @@ -1,47 +0,0 @@ - - */ - private array $unrendered = []; - - public function __construct( - private readonly NativeCSVWriter $writer, - private readonly PhpCSVEncoder $php, - ) {} - - public function encode(Rows $rows): string - { - $schema = $rows->schema(); - - // consecutive batches share one Schema object - if ($schema !== $this->schema) { - $this->unrendered = $this->writer->unrendered($schema); - $this->schema = $schema; - } - - $cells = []; - - foreach ($this->unrendered as $name) { - $cells[$name] = $this->php->cells($schema->get($name)->type(), $rows->column($name)); - } - - return $this->writer->encode($rows, $cells); - } - - public function encodeHeader(array $headers): string - { - return $this->php->encodeHeader($headers); - } -} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php deleted file mode 100644 index 3a26316592..0000000000 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/NativeCSVOpenSource.php +++ /dev/null @@ -1,223 +0,0 @@ - - */ - private readonly int $chunkSize; - - /** - * @var int<0, max> - */ - private int $producedRows = 0; - - /** - * @param null|int<1, max> $charactersReadInLine - */ - public function __construct( - private readonly SourceStream $stream, - private readonly RustCSVReaderNative $reader, - ?int $charactersReadInLine = null, - ) { - // a local file ignores the read length, as NativeLocalSourceStream::readLines() already does on the PHP path; - // for S3/Azure it is the range-request size - and from_csv() defaults it to 10 MB, which would be the chunk - $this->chunkSize = $stream instanceof NativeLocalSourceStream - ? self::CHUNK - : $charactersReadInLine ?? self::CHUNK; - } - - public static function isSupported(): bool - { - return extension_loaded('flow_php') && class_exists(RustCSVReaderNative::class, false); - } - - public function batches(Schema $schema, int $batchSize, Backend $backend): Generator - { - // every batch goes through the configured backend, which keeps its own columns and copies the native ones - $adopted = function (Rows $batch) use ($schema, $backend): Rows { - $columns = []; - $native = $batch->columns(); - - foreach ($schema->definitions() as $name => $definition) { - $columns[$name] = $backend->adopt($definition, $native[$name]); - } - - $this->producedRows += count($batch); - - return Rows::fromColumns($schema, $columns, $batch->count()); - }; - - foreach ($this->stream->iterate($this->chunkSize) as $chunk) { - $this->reader->feed($chunk); - - while (($batch = $this->reader->nextColumns($schema, $batchSize)) !== null) { - yield $adopted($batch); - } - } - - $this->reader->finish(); - - while (($batch = $this->reader->nextColumns($schema, $batchSize)) !== null) { - yield $adopted($batch); - } - } - - public function close(): void - { - $this->stream->close(); - } - - public function columns(): array - { - foreach ($this->stream->iterate($this->chunkSize) as $chunk) { - $this->reader->feed($chunk); - - $headers = $this->reader->headers(); - - if ($headers !== []) { - return $headers; - } - } - - $this->reader->finish(); - - return $this->reader->headers(); - } - - public function producedBytes(): int - { - return $this->reader->consumedBytes(); - } - - public function producedRows(): int - { - return $this->producedRows; - } - - public function headers(): array - { - return $this->reader->headers(); - } - - public function records(): Generator - { - foreach ($this->stream->iterate($this->chunkSize) as $chunk) { - $this->reader->feed($chunk); - - while (($batch = $this->reader->next(self::BATCH)) !== []) { - $this->producedRows += count($batch); - - foreach ($batch as $values) { - yield $values; - } - } - } - - $this->reader->finish(); - - while (($batch = $this->reader->next(self::BATCH)) !== []) { - $this->producedRows += count($batch); - - foreach ($batch as $values) { - yield $values; - } - } - } - - public function sniff(array $names, int $rowBudget, SchemaInference $inference, TypeNarrower $typer): ColumnTypes - { - // the Rust fold is StringTypeNarrower without its HTML and XML rungs - a DOMDocument per cell is not worth porting - if (!$typer instanceof StringTypeNarrower || $typer->emitsType(type_html()) || $typer->emitsType(type_xml())) { - return (new SchemaInferrer($inference, $typer))->sniff($names, $this->records(), $rowBudget); - } - - $fold = new RustColumnFoldNative($names, array_map( - static fn(Type $type): string => $type->toString(), - array_values(array_filter( - [ - type_json(), - type_uuid(), - type_float(), - type_integer(), - type_datetime(), - type_date(), - type_boolean(), - type_time_zone(), - ], - $typer->emitsType(...), - )), - )); - - foreach ($this->stream->iterate($this->chunkSize) as $chunk) { - $this->reader->feed($chunk); - $this->producedRows += $this->reader->fold( - $fold, - $rowBudget === -1 ? -1 : max(0, $rowBudget - $fold->rows()), - ); - - if ($rowBudget !== -1 && $fold->rows() >= $rowBudget) { - break; - } - } - - if ($rowBudget === -1 || $fold->rows() < $rowBudget) { - $this->reader->finish(); - $this->producedRows += $this->reader->fold( - $fold, - $rowBudget === -1 ? -1 : max(0, $rowBudget - $fold->rows()), - ); - } - - return ColumnTypes::fromColumnTypes( - array_map(TypeFactory::fromString(...), $fold->types()), - $fold->rows(), - $typer, - ); - } -} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVEncoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVEncoder.php index 7241113a1c..96425f0243 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVEncoder.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVEncoder.php @@ -49,6 +49,7 @@ public function __construct( $this->text = new TextValues($options->dateTimeFormat, $options->dateFormat); } + // called by name from flow_php RustCSVEncoder::encode(), pinned by phpt 082 /** * @param Type $type * diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php index 65ecd866ad..78ba7ca519 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/PhpCSVOpenSource.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Adapter\CSV; use Flow\ETL\Column\Backend; +use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\ColumnTypes; @@ -34,6 +35,9 @@ public function __construct( private readonly CSVLineReader $lineReader, ) {} + /** + * @return Generator + */ public function batches(Schema $schema, int $batchSize, Backend $backend): Generator { $rows = []; diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php index abce114d30..f1c5dc0f95 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\CSV\Tests\Context; +use Flow\ETL\Adapter\CSV\AdaptiveCSVOpenSource; use Flow\ETL\Adapter\CSV\CSVDecoder; use Flow\ETL\Adapter\CSV\CSVDialect; use Flow\ETL\Adapter\CSV\CSVFileReader; @@ -11,10 +12,8 @@ use Flow\ETL\Adapter\CSV\CSVLineReader; use Flow\ETL\Adapter\CSV\CSVOpenSource; use Flow\ETL\Adapter\CSV\CSVReadOptions; -use Flow\ETL\Adapter\CSV\CSVSourceOpener; -use Flow\ETL\Adapter\CSV\NativeCSVOpenSource; use Flow\ETL\Adapter\CSV\PhpCSVOpenSource; -use Flow\ETL\Adapter\CSV\RustCSVReaderNative; +use Flow\ETL\Adapter\CSV\RustCSVOpenSource; use Flow\ETL\Column\Backend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\SchemaMismatchException; @@ -67,7 +66,7 @@ public static function globReader( $sources[] = new SourceFile($status->path); } - return new CSVFileReader(new CSVSourceOpener($filesystem, $options), $sources); + return new CSVFileReader($filesystem, $options, $sources); } public static function open( @@ -75,7 +74,7 @@ public static function open( Filesystem $filesystem = new NativeLocalFilesystem(), CSVReadOptions $options = new CSVReadOptions(), ): CSVOpenSource { - return (new CSVSourceOpener($filesystem, $options))->open(self::source($fixture)); + return new AdaptiveCSVOpenSource($filesystem, self::source($fixture), $options); } /** @@ -101,7 +100,7 @@ public static function fixtures(): Generator } /** - * The dialect CSVSourceOpener would resolve: pinned options first, detection for the rest. + * The dialect AdaptiveCSVOpenSource resolves: pinned options first, detection for the rest. */ public static function dialect(SourceStream $stream, CSVReadOptions $options = new CSVReadOptions()): CSVDialect { @@ -121,7 +120,7 @@ public static function openNative( string $fixture, Filesystem $filesystem = new NativeLocalFilesystem(), CSVReadOptions $options = new CSVReadOptions(), - ): NativeCSVOpenSource { + ): RustCSVOpenSource { return self::openNativeStream($filesystem->readFrom(path_real(self::path($fixture))), $options); } @@ -131,19 +130,17 @@ public static function openNative( public static function openNativeStream( SourceStream $stream, CSVReadOptions $options = new CSVReadOptions(), - ): NativeCSVOpenSource { + ): RustCSVOpenSource { $dialect = self::dialect($stream, $options); - return new NativeCSVOpenSource( + return new RustCSVOpenSource( $stream, - new RustCSVReaderNative( - $dialect->separator, - $dialect->enclosure, - $dialect->escape, - $options->withHeader, - $options->emptyToNull, - $options->removeBOM, - ), + $dialect->separator, + $dialect->enclosure, + $dialect->escape, + $options->withHeader, + $options->emptyToNull, + $options->removeBOM, $options->charactersReadInLine, ); } @@ -378,7 +375,7 @@ public static function reader( array $sources = [], CSVReadOptions $options = new CSVReadOptions(), ): CSVFileReader { - return new CSVFileReader(new CSVSourceOpener($filesystem, $options), $sources); + return new CSVFileReader($filesystem, $options, $sources); } public static function sample( @@ -386,7 +383,7 @@ public static function sample( Filesystem $filesystem = new NativeLocalFilesystem(), CSVReadOptions $options = new CSVReadOptions(), ): CSVFileSample { - return new CSVFileSample(new CSVSourceOpener($filesystem, $options), self::source($fixture)); + return new CSVFileSample($filesystem, $options, self::source($fixture)); } /** diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/AdaptiveCSVOpenSourceTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/AdaptiveCSVOpenSourceTest.php new file mode 100644 index 0000000000..07a5581277 --- /dev/null +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/AdaptiveCSVOpenSourceTest.php @@ -0,0 +1,155 @@ +columns()); + } finally { + $open->close(); + } + } + + public function test_every_instance_opens_its_own_stream(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + $source = CSVFixtureContext::source('header_only.csv'); + + $first = new AdaptiveCSVOpenSource($filesystem, $source, new CSVReadOptions()); + $second = new AdaptiveCSVOpenSource($filesystem, $source, new CSVReadOptions()); + + try { + static::assertSame(['id', 'name'], $first->columns()); + static::assertSame(['id', 'name'], $second->columns()); + } finally { + $first->close(); + $second->close(); + } + } + + public function test_the_stream_is_closed_when_detection_throws(): void + { + $throwing = new ThrowingSourceFilesystem(new NativeLocalFilesystem()); + + $this->expectException(RuntimeException::class); + + try { + new AdaptiveCSVOpenSource($throwing, CSVFixtureContext::source('two_rows.csv'), new CSVReadOptions()); + } finally { + static::assertTrue( + $throwing->lastStream?->closed, + 'the constructor closes the stream it opened before rethrowing', + ); + } + } + + public function test_the_dialect_is_detected(): void + { + $open = new AdaptiveCSVOpenSource( + new CountingFilesystem(new NativeLocalFilesystem()), + CSVFixtureContext::source('semicolon.csv'), + new CSVReadOptions(), + ); + + try { + static::assertSame(['id', 'name'], $open->columns()); + } finally { + $open->close(); + } + } + + public function test_the_source_is_opened_exactly_once(): void + { + $counting = new CountingFilesystem(new NativeLocalFilesystem()); + $open = new AdaptiveCSVOpenSource($counting, CSVFixtureContext::source('two_rows.csv'), new CSVReadOptions()); + + static::assertSame(1, $counting->readFromCalls); + static::assertSame(0, $counting->closedStreams()); + + $open->close(); + } + + public function test_with_the_extension_the_rust_source_reads(): void + { + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); + } + + $open = new AdaptiveCSVOpenSource( + CSVFixtureContext::memory("id,name\n1,a\n"), + CSVFixtureContext::memorySource(), + new CSVReadOptions(), + ); + + try { + static::assertInstanceOf(RustIterator::class, $open->records()); + } finally { + $open->close(); + } + } + + public function test_without_the_extension_the_php_source_reads(): void + { + if (extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is loaded'); + } + + $open = new AdaptiveCSVOpenSource( + CSVFixtureContext::memory("id,name\n1,a\n"), + CSVFixtureContext::memorySource(), + new CSVReadOptions(), + ); + + try { + static::assertInstanceOf(Generator::class, $open->records()); + } finally { + $open->close(); + } + } + + public function test_characters_read_in_line_reaches_the_opened_source(): void + { + $filesystem = new LengthCapturingFilesystem(CSVFixtureContext::memory("id,name\n1,a\n")); + $open = new AdaptiveCSVOpenSource( + $filesystem, + CSVFixtureContext::memorySource(), + (new CSVReadOptions())->withCharactersReadInLine(4096), + ); + + try { + iterator_to_array($open->records()); + } finally { + $open->close(); + } + + extension_loaded('flow_php') + ? static::assertSame([4096], $filesystem->lastStream?->capturedIterateLengths) + : static::assertSame([null, 4096], $filesystem->lastStream?->capturedLengths); + } +} diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVSourceOpenerTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVSourceOpenerTest.php deleted file mode 100644 index ca2cce5379..0000000000 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/CSVSourceOpenerTest.php +++ /dev/null @@ -1,87 +0,0 @@ -open(CSVFixtureContext::source('semicolon.csv')); - - try { - static::assertSame(['id;name'], $open->columns()); - } finally { - $open->close(); - } - } - - public function test_open_builds_a_fresh_encoder_per_call(): void - { - $opener = new CSVSourceOpener(new CountingFilesystem(new NativeLocalFilesystem()), new CSVReadOptions()); - $source = CSVFixtureContext::source('header_only.csv'); - - $first = $opener->open($source); - $second = $opener->open($source); - - try { - static::assertSame(['id', 'name'], $first->columns()); - static::assertSame(['id', 'name'], $second->columns()); - } finally { - $first->close(); - $second->close(); - } - } - - public function test_open_closes_the_stream_when_detection_throws(): void - { - $throwing = new ThrowingSourceFilesystem(new NativeLocalFilesystem()); - $opener = new CSVSourceOpener($throwing, new CSVReadOptions()); - - $this->expectException(RuntimeException::class); - - try { - $opener->open(CSVFixtureContext::source('two_rows.csv')); - } finally { - static::assertTrue($throwing->lastStream?->closed, 'open() closes the stream it opened before rethrowing'); - } - } - - public function test_open_detects_the_dialect(): void - { - $open = (new CSVSourceOpener( - new CountingFilesystem(new NativeLocalFilesystem()), - new CSVReadOptions(), - ))->open(CSVFixtureContext::source('semicolon.csv')); - - try { - static::assertSame(['id', 'name'], $open->columns()); - } finally { - $open->close(); - } - } - - public function test_open_opens_the_source_exactly_once(): void - { - $counting = new CountingFilesystem(new NativeLocalFilesystem()); - $open = (new CSVSourceOpener($counting, new CSVReadOptions()))->open(CSVFixtureContext::source('two_rows.csv')); - - static::assertSame(1, $counting->readFromCalls); - static::assertSame(0, $counting->closedStreams()); - - $open->close(); - } -} diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/RustCSVOpenSourceTest.php similarity index 79% rename from src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php rename to src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/RustCSVOpenSourceTest.php index 2888e1ed6f..d6682ba406 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/NativeCSVOpenSourceTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/RustCSVOpenSourceTest.php @@ -5,8 +5,6 @@ namespace Flow\ETL\Adapter\CSV\Tests\Integration; use Flow\ETL\Adapter\CSV\CSVReadOptions; -use Flow\ETL\Adapter\CSV\NativeCSVOpenSource; -use Flow\ETL\Adapter\CSV\RustCSVReaderNative; use Flow\ETL\Adapter\CSV\Tests\Context\CSVFixtureContext; use Flow\ETL\Adapter\CSV\Tests\Double\LengthCapturingSourceStream; use Flow\ETL\Exception\ColumnMismatchException; @@ -28,8 +26,8 @@ use function array_keys; use function array_map; -use function class_exists; use function count; +use function extension_loaded; use function file_get_contents; use function Flow\ETL\DSL\infer_schema; use function Flow\ETL\DSL\int_schema; @@ -39,12 +37,12 @@ use function implode; use function iterator_to_array; -final class NativeCSVOpenSourceTest extends FlowTestCase +final class RustCSVOpenSourceTest extends FlowTestCase { public function test_close_closes_the_stream_once(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $counting = new CountingFilesystem(new NativeLocalFilesystem()); @@ -57,8 +55,8 @@ public function test_close_closes_the_stream_once(): void public function test_columns_of_an_empty_source_is_empty(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('empty.csv'); @@ -72,8 +70,8 @@ public function test_columns_of_an_empty_source_is_empty(): void public function test_columns_reads_a_quoted_multiline_header_as_one_record(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('multiline_header.csv'); @@ -87,8 +85,8 @@ public function test_columns_reads_a_quoted_multiline_header_as_one_record(): vo public function test_headers_are_the_header_records_resolved(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('header_only.csv'); @@ -104,8 +102,8 @@ public function test_headers_are_the_header_records_resolved(): void public function test_columns_reports_the_resolved_header(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('header_only.csv'); @@ -119,8 +117,8 @@ public function test_columns_reports_the_resolved_header(): void public function test_columns_without_a_header_line_are_generated(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('two_columns.csv', options: new CSVReadOptions(withHeader: false)); @@ -134,8 +132,8 @@ public function test_columns_without_a_header_line_are_generated(): void public function test_records_yields_every_row_with_the_full_key_set(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('ragged.csv'); @@ -155,8 +153,8 @@ public function test_records_yields_every_row_with_the_full_key_set(): void public function test_records_yields_one_logical_record_per_iteration(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('multiline_strings.csv'); @@ -174,8 +172,8 @@ public function test_records_yields_one_logical_record_per_iteration(): void #[DataProviderExternal(CSVFixtureContext::class, 'fixtures')] public function test_native_and_php_open_sources_yield_identical_records(string $fixture): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $php = CSVFixtureContext::openPhp($fixture); @@ -197,8 +195,8 @@ public function test_native_and_php_open_sources_yield_identical_records(string #[TestWith([4096])] public function test_records_are_identical_across_chunk_sizes(int $chunkSize): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $contents = (string) file_get_contents(CSVFixtureContext::path('multiline_strings.csv')); @@ -216,8 +214,8 @@ public function test_records_are_identical_across_chunk_sizes(int $chunkSize): v public function test_a_remote_stream_is_read_in_steps_of_characters_read_in_line(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $stream = new LengthCapturingSourceStream("id,name\n1,a\n", path('s3://bucket/a.csv')); @@ -232,15 +230,15 @@ public function test_a_remote_stream_is_read_in_steps_of_characters_read_in_line public function test_a_remote_stream_without_characters_read_in_line_is_read_in_default_chunks(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $stream = new LengthCapturingSourceStream("id,name\n1,a\n", path('s3://bucket/a.csv')); CSVFixtureContext::records(CSVFixtureContext::openNativeStream($stream)); - static::assertSame([NativeCSVOpenSource::CHUNK], $stream->capturedIterateLengths); + static::assertSame([1 << 15], $stream->capturedIterateLengths); } #[TestWith(['multiline_header.csv'])] @@ -249,8 +247,8 @@ public function test_a_remote_stream_without_characters_read_in_line_is_read_in_ #[TestWith(['single_quotes_csv.csv'])] public function test_columns_resolves_the_same_header_on_both_paths(string $fixture): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $php = CSVFixtureContext::openPhp($fixture); @@ -266,8 +264,8 @@ public function test_columns_resolves_the_same_header_on_both_paths(string $fixt public function test_a_zero_byte_source_resolves_no_header_on_both_paths(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $php = CSVFixtureContext::openPhp('empty.csv'); @@ -282,15 +280,6 @@ public function test_a_zero_byte_source_resolves_no_header_on_both_paths(): void } } - public function test_is_supported_is_false_without_the_extension(): void - { - if (class_exists(RustCSVReaderNative::class, false)) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is loaded'); - } - - static::assertFalse(NativeCSVOpenSource::isSupported()); - } - /** * @param int<0, max>|-1 $rowBudget */ @@ -299,8 +288,8 @@ public function test_is_supported_is_false_without_the_extension(): void #[TestWith([10, 5])] public function test_sniff_folds_at_most_the_row_budget(int $rowBudget, int $rows): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('five_rows.csv'); @@ -322,8 +311,8 @@ public function test_sniff_folds_at_most_the_row_budget(int $rowBudget, int $row public function test_sniff_folds_date_and_time_zone_columns_like_observing_the_records(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $contents = "at,day,zone,n\n2024-01-01 10:00:00,2024-01-01,Europe/Warsaw,\n2024-02-02 11:00:00,2024-02-02,+02:00,1\n"; @@ -349,8 +338,8 @@ public function test_sniff_folds_date_and_time_zone_columns_like_observing_the_r public function test_columns_of_a_header_without_a_trailing_newline(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } static::assertSame( @@ -363,8 +352,8 @@ public function test_columns_of_a_header_without_a_trailing_newline(): void public function test_produced_rows_and_bytes_exclude_the_header(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $open = CSVFixtureContext::openNative('five_rows.csv'); @@ -390,8 +379,8 @@ public function test_produced_rows_and_bytes_exclude_the_header(): void #[TestWith(['ragged.csv'])] public function test_php_and_native_paths_agree_on_bytes_per_row(string $fixture): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $header = CSVFixtureContext::openPhp($fixture); @@ -415,8 +404,8 @@ public function test_php_and_native_paths_agree_on_bytes_per_row(string $fixture public function test_batches_are_batch_size_rows(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $batches = CSVFixtureContext::batches( @@ -431,8 +420,8 @@ public function test_batches_are_batch_size_rows(): void public function test_batches_skip_undeclared_header_columns(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } static::assertSame( @@ -447,8 +436,8 @@ public function test_batches_skip_undeclared_header_columns(): void public function test_batches_pad_a_missing_nullable_column(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } static::assertSame( @@ -463,8 +452,8 @@ public function test_batches_pad_a_missing_nullable_column(): void public function test_batches_refuse_a_missing_not_null_column(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $refusal = CSVFixtureContext::batches( @@ -483,8 +472,8 @@ public function test_batches_refuse_a_missing_not_null_column(): void public function test_batches_refused_value_wins_over_absence(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $refusal = CSVFixtureContext::batches( @@ -506,8 +495,8 @@ public function test_batches_refused_value_wins_over_absence(): void public function test_batches_refusal_tie_goes_to_the_first_definition(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $refusal = CSVFixtureContext::batches( @@ -529,8 +518,8 @@ public function test_batches_refusal_tie_goes_to_the_first_definition(): void public function test_batches_refuse_an_empty_to_null_null_under_not_null(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $refusal = CSVFixtureContext::batches( @@ -552,8 +541,8 @@ public function test_batches_refuse_an_empty_to_null_null_under_not_null(): void public function test_batches_of_a_header_only_source_are_empty(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } static::assertSame( @@ -609,8 +598,8 @@ public static function batch_parity_cases(): Generator #[DataProvider('batch_parity_cases')] public function test_native_and_php_batches_are_identical(string $content, Schema $schema, int $batchSize): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } static::assertSame( @@ -636,8 +625,8 @@ public function test_native_and_php_batches_are_identical(string $content, Schem #[TestWith([7, "id,note\n1,\"a\nb\"\nx,\"a record that crosses\nthe chunk boundary\"\n"])] public function test_batches_are_identical_across_chunk_sizes(int $chunkSize, string $content): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $schema = schema(int_schema('id'), str_schema('note')); @@ -663,8 +652,8 @@ public function test_batches_are_identical_across_chunk_sizes(int $chunkSize, st public function test_batches_hand_every_column_to_the_backend(): void { - if (!NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is not loaded'); + if (!extension_loaded('flow_php')) { + static::markTestSkipped('flow_php extension is not loaded'); } $backend = new SpyBackend(); diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Mother/CSVEncoderMother.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Mother/CSVEncoderMother.php index ac4bb63abd..3efa748dce 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Mother/CSVEncoderMother.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Mother/CSVEncoderMother.php @@ -5,35 +5,28 @@ namespace Flow\ETL\Adapter\CSV\Tests\Mother; use Flow\ETL\Adapter\CSV\CSVWriteOptions; -use Flow\ETL\Adapter\CSV\NativeCSVEncoder; -use Flow\ETL\Adapter\CSV\NativeCSVWriter; use Flow\ETL\Adapter\CSV\PhpCSVEncoder; +use Flow\ETL\Adapter\CSV\RustCSVEncoder; final class CSVEncoderMother { public static function native(CSVWriteOptions $options = new CSVWriteOptions( newLineSeparator: "\n", - )): NativeCSVEncoder + )): RustCSVEncoder { - return new NativeCSVEncoder(self::writer($options), new PhpCSVEncoder($options)); - } - - public static function php(CSVWriteOptions $options = new CSVWriteOptions(newLineSeparator: "\n")): PhpCSVEncoder - { - return new PhpCSVEncoder($options); - } - - public static function writer(CSVWriteOptions $options = new CSVWriteOptions( - newLineSeparator: "\n", - )): NativeCSVWriter - { - return new NativeCSVWriter( + return new RustCSVEncoder( $options->separator, $options->enclosure, $options->escape, $options->newLineSeparator, $options->dateTimeFormat, $options->dateFormat, + new PhpCSVEncoder($options), ); } + + public static function php(CSVWriteOptions $options = new CSVWriteOptions(newLineSeparator: "\n")): PhpCSVEncoder + { + return new PhpCSVEncoder($options); + } } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/AdaptiveCSVEncoderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/AdaptiveCSVEncoderTest.php new file mode 100644 index 0000000000..563204786b --- /dev/null +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/AdaptiveCSVEncoderTest.php @@ -0,0 +1,46 @@ +write(array_to_rows([['id' => 1, 'name' => 'a;b']], schema(int_schema('id'), str_schema('name')))); + + static::assertSame("id;name\n1;\"a;b\"\n", $stream->content()); + } + + public function test_a_sink_without_a_header(): void + { + $stream = new StringDestinationStream(path('memory://out.csv')); + + (new CSVOpenSink( + $stream, + new AdaptiveCSVEncoder(new CSVWriteOptions(newLineSeparator: "\n")), + false, + ))->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); + + static::assertSame("1\n", $stream->content()); + } +} diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSinkOpenerTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSinkOpenerTest.php deleted file mode 100644 index 453a65967e..0000000000 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSinkOpenerTest.php +++ /dev/null @@ -1,41 +0,0 @@ -open($stream, true) - ->write(array_to_rows([['id' => 1, 'name' => 'a;b']], schema(int_schema('id'), str_schema('name')))); - - static::assertSame("id;name\n1;\"a;b\"\n", $stream->content()); - } - - public function test_an_opened_sink_without_a_header(): void - { - $stream = new StringDestinationStream(path('memory://out.csv')); - - (new CSVSinkOpener(new CSVWriteOptions(newLineSeparator: "\n"))) - ->open($stream, false) - ->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); - - static::assertSame("1\n", $stream->content()); - } -} diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSourceOpenerTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSourceOpenerTest.php deleted file mode 100644 index 6ad2c73203..0000000000 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVSourceOpenerTest.php +++ /dev/null @@ -1,87 +0,0 @@ -open( - CSVFixtureContext::memorySource(), - ); - - try { - static::assertInstanceOf(NativeCSVOpenSource::class, $open); - static::assertSame(['id', 'name'], $open->columns()); - } finally { - $open->close(); - } - } - - public function test_open_returns_the_php_source_when_the_extension_is_absent(): void - { - if (NativeCSVOpenSource::isSupported()) { - static::markTestSkipped('flow_php extension with RustCSVReaderNative is loaded'); - } - - $open = (new CSVSourceOpener(CSVFixtureContext::memory("id,name\n1,a\n"), new CSVReadOptions()))->open( - CSVFixtureContext::memorySource(), - ); - - try { - static::assertInstanceOf(PhpCSVOpenSource::class, $open); - static::assertSame(['id', 'name'], $open->columns()); - } finally { - $open->close(); - } - } - - public function test_a_failing_detection_closes_the_stream_on_both_paths(): void - { - $throwing = new ThrowingSourceFilesystem(CSVFixtureContext::memory("id,name\n1,a\n")); - - $this->expectException(RuntimeException::class); - - try { - (new CSVSourceOpener($throwing, new CSVReadOptions()))->open(CSVFixtureContext::memorySource()); - } finally { - static::assertTrue($throwing->lastStream?->closed, 'open() closes the stream it opened before rethrowing'); - } - } - - public function test_characters_read_in_line_reaches_the_opened_source(): void - { - $filesystem = new LengthCapturingFilesystem(CSVFixtureContext::memory("id,name\n1,a\n")); - $open = (new CSVSourceOpener($filesystem, (new CSVReadOptions())->withCharactersReadInLine(4096)))->open( - CSVFixtureContext::memorySource(), - ); - - try { - iterator_to_array($open->records()); - } finally { - $open->close(); - } - - NativeCSVOpenSource::isSupported() - ? static::assertSame([4096], $filesystem->lastStream?->capturedIterateLengths) - : static::assertSame([null, 4096], $filesystem->lastStream?->capturedLengths); - } -} diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/NativeCSVEncoderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/RustCSVEncoderTest.php similarity index 74% rename from src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/NativeCSVEncoderTest.php rename to src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/RustCSVEncoderTest.php index 0d4b207dc0..a6013b66e4 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/NativeCSVEncoderTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/RustCSVEncoderTest.php @@ -6,14 +6,13 @@ use Flow\ETL\Adapter\CSV\CSVWriteOptions; use Flow\ETL\Adapter\CSV\Tests\Mother\CSVEncoderMother; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\Context\TextWriterBatches; use Flow\ETL\Tests\FlowTestCase; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\RequiresPhpExtension; -use PHPUnit\Framework\Attributes\TestWith; use Throwable; use function Flow\ETL\DSL\array_to_rows; @@ -23,7 +22,7 @@ use function Flow\ETL\DSL\xml_schema; #[RequiresPhpExtension('flow_php')] -final class NativeCSVEncoderTest extends FlowTestCase +final class RustCSVEncoderTest extends FlowTestCase { /** * @return Generator @@ -49,7 +48,7 @@ public function test_encode_returns_what_the_php_encoder_returns(string $batch): foreach ([ 'php' => [CSVEncoderMother::php($options), new PhpBackend()], - 'native' => [CSVEncoderMother::native($options), new DefaultBackend()], + 'native' => [CSVEncoderMother::native($options), new AdaptiveBackend()], 'native over adopted php columns' => [CSVEncoderMother::native($options), new PhpBackend()], ] as $lane => [$encoder, $backend]) { try { @@ -68,31 +67,6 @@ public function test_encode_returns_what_the_php_encoder_returns(string $batch): } } - /** - * @param list $unrendered - */ - #[TestWith(['scalars with nulls', 'Y-m-d', []])] - #[TestWith(['temporal kinds', 'Y-m-d\TH:i:sP', []])] - #[TestWith(['temporal kinds', 'D, d M Y', ['at', 'offset', 'on']])] - #[TestWith(['a json column', 'Y-m-d', []])] - #[TestWith(['markup columns', 'Y-m-d', ['x', 'e']])] - #[TestWith(['nested kinds rendered natively', 'Y-m-d', []])] - #[TestWith(['nested kinds rendered natively', 'l', ['l', 's']])] - #[TestWith(['a list of json documents', 'Y-m-d', ['l']])] - #[TestWith(['nested markup leaves', 'Y-m-d', ['l', 's']])] - public function test_the_columns_the_writer_leaves_to_php_cells( - string $batch, - string $format, - array $unrendered, - ): void { - static::assertSame( - $unrendered, - CSVEncoderMother::writer(new CSVWriteOptions(dateTimeFormat: $format, dateFormat: $format))->unrendered( - TextWriterBatches::of($batch)[0], - ), - ); - } - public function test_the_not_finite_floats_are_written_by_name(): void { [$schema, $rows] = TextWriterBatches::of('not finite floats'); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php index b179583fda..44b30c650a 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php @@ -172,9 +172,9 @@ public function test_with_isolation_level(): void ))) ->write( new Transactional( - DbalTransaction::fromConnection( - $connection, - )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + DbalTransaction::fromConnection($connection)->withIsolationLevel( + TransactionIsolationLevel::SERIALIZABLE, + ), to_dbal_table_insert($connection, 'test_table'), ), ) diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php index 93e40ef4f7..3953a3089d 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php @@ -172,9 +172,9 @@ public function test_with_isolation_level(): void ))) ->write( new Transactional( - DbalTransaction::fromConnection( - $connection, - )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + DbalTransaction::fromConnection($connection)->withIsolationLevel( + TransactionIsolationLevel::SERIALIZABLE, + ), to_dbal_table_insert($connection, 'test_table'), ), ) diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php index 1bfec52afc..2e906a6795 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php @@ -172,9 +172,9 @@ public function test_with_isolation_level(): void ))) ->write( new Transactional( - DbalTransaction::fromConnection( - $connection, - )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + DbalTransaction::fromConnection($connection)->withIsolationLevel( + TransactionIsolationLevel::SERIALIZABLE, + ), to_dbal_table_insert($connection, 'test_table'), ), ) diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionSinkTest.php index cae29ca424..fae0b10c8f 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalTransactionSinkTest.php @@ -166,9 +166,9 @@ public function test_isolation_level_applies_to_the_closure_transaction_and_is_r ->batchSize(2) ->write( new Transactional( - DbalTransaction::fromConnection( - $connection, - )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), + DbalTransaction::fromConnection($connection)->withIsolationLevel( + TransactionIsolationLevel::SERIALIZABLE, + ), to_transformation( new CallbackTransformation(static fn(DataFrame $df): DataFrame => $df->sortBy([ref('id')])), $spy, 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 index f16186f38a..5022d110d8 100644 --- 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 @@ -43,9 +43,9 @@ public function test_the_isolation_level_is_set_before_begin_and_restored_after_ ->willReturnCallback(static function (TransactionIsolationLevel $level) use (&$levels): void { $levels[] = $level; }); - $transaction = DbalTransaction::fromConnection( - $connection, - )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); + $transaction = DbalTransaction::fromConnection($connection)->withIsolationLevel( + TransactionIsolationLevel::SERIALIZABLE, + ); $transaction->begin(); $transaction->commit(); @@ -97,9 +97,9 @@ public function test_a_failed_commit_leaves_the_restore_to_the_rollback_that_fol ->willReturnCallback(static function (TransactionIsolationLevel $level) use (&$levels): void { $levels[] = $level; }); - $transaction = DbalTransaction::fromConnection( - $connection, - )->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE); + $transaction = DbalTransaction::fromConnection($connection)->withIsolationLevel( + TransactionIsolationLevel::SERIALIZABLE, + ); $transaction->begin(); try { diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJSONEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJSONEncoder.php new file mode 100644 index 0000000000..2715815e7a --- /dev/null +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJSONEncoder.php @@ -0,0 +1,43 @@ +encoder = extension_loaded('flow_php') + && ( + $flags + & ~(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION) + ) + === 0 + ? new RustJSONEncoder($flags, $dateTimeFormat, $dateFormat, $php) + : $php; + } + + public function encode(Rows $rows, string $separator): string + { + return $this->encoder->encode($rows, $separator); + } +} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php new file mode 100644 index 0000000000..f13daae609 --- /dev/null +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php @@ -0,0 +1,98 @@ +source = new PhpJsonOpenSource($reader, $source); + + return; + } + + $stream = $filesystem->readFrom($source->path); + + try { + $head = ''; + $offset = 0; + + if ($format === JsonFormat::Document) { + // the first byte after JSON whitespace and one leading BOM: '[' is Rust's; an object, a scalar or an + // empty file is the PHP source's (member iteration / JSON Machine's verdict) + $first = ''; + + for (; ($head = $stream->read(self::CHUNK, $offset)) !== ''; $offset += strlen($head)) { + $bytes = $offset === 0 && str_starts_with($head, "\u{FEFF}") ? substr($head, 3) : $head; + $skip = strspn($bytes, " \t\n\r"); + + if ($skip < strlen($bytes)) { + $first = $bytes[$skip]; + + break; + } + } + + if ($first !== '[') { + $stream->close(); + $this->source = new PhpJsonOpenSource($reader, $source); + + return; + } + } + + $this->source = new RustJsonOpenSource( + $stream, + $format === JsonFormat::Lines, + $source->uri(), + $head, + $offset, + ); + } catch (Throwable $e) { + $stream->close(); + + throw $e; + } + } + + public function batches(Schema $schema, int $batchSize, Backend $backend): Iterator + { + return $this->source->batches($schema, $batchSize, $backend); + } + + public function close(): void + { + $this->source->close(); + } +} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php index 9575521211..036088b463 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php @@ -6,6 +6,12 @@ use Flow\ETL\Rows; +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} + interface JSONEncoder { public function encode(Rows $rows, string $separator): string; 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 5e5bf925e6..96e8ede9f0 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 @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; -use Flow\ETL\Adapter\JSON\JsonSourceOpener; +use Flow\ETL\Adapter\JSON\AdaptiveJsonOpenSource; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; @@ -127,26 +127,37 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $schema = $fileColumns->declare($base); $body = $fileColumns->withoutTail($schema); - $opener = new JsonSourceOpener($this->filesystem, $reader, JsonFormat::Document, $this->pointer); foreach ($sources as $source) { // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body $constants = $fileColumns->forFile($source, $schema); - foreach ($opener->batches($source, $body, $batchSize, $backend) as $batch) { - $rows = $constants->fillRows($batch, $schema, $backend); + $open = new AdaptiveJsonOpenSource( + $this->filesystem, + $reader, + JsonFormat::Document, + $this->pointer, + $source, + ); - $yielded += $rows->count(); + try { + foreach ($open->batches($body, $batchSize, $backend) as $batch) { + $rows = $constants->fillRows($batch, $schema, $backend); - $signal = yield $rows; + $yielded += $rows->count(); - if ($signal === Signal::STOP) { - return; - } + $signal = yield $rows; + + if ($signal === Signal::STOP) { + return; + } - if ($limit !== null && $yielded >= $limit) { - return; + if ($limit !== null && $yielded >= $limit) { + return; + } } + } finally { + $open->close(); } } } 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 72804253d5..c55765712f 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 @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; -use Flow\ETL\Adapter\JSON\JsonSourceOpener; +use Flow\ETL\Adapter\JSON\AdaptiveJsonOpenSource; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; @@ -127,26 +127,31 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $schema = $fileColumns->declare($base); $body = $fileColumns->withoutTail($schema); - $opener = new JsonSourceOpener($this->filesystem, $reader, JsonFormat::Lines, $this->pointer); foreach ($sources as $source) { // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body $constants = $fileColumns->forFile($source, $schema); - foreach ($opener->batches($source, $body, $batchSize, $backend) as $batch) { - $rows = $constants->fillRows($batch, $schema, $backend); + $open = new AdaptiveJsonOpenSource($this->filesystem, $reader, JsonFormat::Lines, $this->pointer, $source); - $yielded += $rows->count(); + try { + foreach ($open->batches($body, $batchSize, $backend) as $batch) { + $rows = $constants->fillRows($batch, $schema, $backend); - $signal = yield $rows; + $yielded += $rows->count(); - if ($signal === Signal::STOP) { - return; - } + $signal = yield $rows; + + if ($signal === Signal::STOP) { + return; + } - if ($limit !== null && $yielded >= $limit) { - return; + if ($limit !== null && $yielded >= $limit) { + return; + } } + } finally { + $open->close(); } } } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php index e7a8d1c443..48ab19bab0 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php @@ -43,8 +43,6 @@ final class JsonLinesLoader implements Closure, Discardable, FileLoader, Loader, private int $flags = JSON_THROW_ON_ERROR; - private ?JsonSinkOpener $opener = null; - private readonly Path $path; /** @@ -110,7 +108,11 @@ public function load(Rows $rows, FlowContext $context): void $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( $partitions->toArray(), ); - ($this->sinks[$stream->path()->uri()] ??= $this->opener()->open($stream))->write($group); + ($this->sinks[$stream->path()->uri()] ??= new JsonOpenSink( + $stream, + new AdaptiveJSONEncoder($this->flags, $this->dateTimeFormat, $this->dateFormat), + JsonFraming::LINES, + ))->write($group); } $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); @@ -148,14 +150,4 @@ public function withFlags(int $flags): self return $this; } - - private function opener(): JsonSinkOpener - { - return $this->opener ??= new JsonSinkOpener( - $this->flags, - $this->dateTimeFormat, - $this->dateFormat, - JsonFraming::LINES, - ); - } } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php index 8b8e6d2f7d..f5af11300f 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php @@ -43,8 +43,6 @@ final class JsonLoader implements Closure, Discardable, FileLoader, Loader, Part private int $flags = JSON_THROW_ON_ERROR; - private ?JsonSinkOpener $opener = null; - private readonly Path $path; private bool $putRowsInNewLines = false; @@ -112,7 +110,11 @@ public function load(Rows $rows, FlowContext $context): void $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( $partitions->toArray(), ); - ($this->sinks[$stream->path()->uri()] ??= $this->opener()->open($stream))->write($group); + ($this->sinks[$stream->path()->uri()] ??= new JsonOpenSink( + $stream, + new AdaptiveJSONEncoder($this->flags, $this->dateTimeFormat, $this->dateFormat), + $this->putRowsInNewLines ? JsonFraming::ARRAY_LINES : JsonFraming::ARRAY, + ))->write($group); } $context->telemetry()->loadingCompleted($this, [ @@ -159,14 +161,4 @@ public function withRowsInNewLines(bool $putRowsInNewLines): self return $this; } - - private function opener(): JsonSinkOpener - { - return $this->opener ??= new JsonSinkOpener( - $this->flags, - $this->dateTimeFormat, - $this->dateFormat, - $this->putRowsInNewLines ? JsonFraming::ARRAY_LINES : JsonFraming::ARRAY, - ); - } } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php index c64fe2f83b..9268f9e68c 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php @@ -8,7 +8,13 @@ use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Generator; +use Iterator; + +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} interface JsonOpenSource { @@ -22,7 +28,7 @@ public function close(): void; * * @throws SchemaMismatchException * - * @return Generator + * @return Iterator */ - public function batches(Schema $schema, int $batchSize, Backend $backend): Generator; + public function batches(Schema $schema, int $batchSize, Backend $backend): Iterator; } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSinkOpener.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSinkOpener.php deleted file mode 100644 index 2997828b84..0000000000 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSinkOpener.php +++ /dev/null @@ -1,45 +0,0 @@ -flags, $this->dateTimeFormat, $this->dateFormat); - - return new JsonOpenSink( - $stream, - extension_loaded('flow_php') - && ( - $this->flags - & ~(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION) - ) - === 0 - ? new NativeJSONEncoder( - new NativeJsonWriter($this->flags, $this->dateTimeFormat, $this->dateFormat), - $php, - ) - : $php, - $this->framing, - ); - } -} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSourceOpener.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSourceOpener.php deleted file mode 100644 index 9c8be9750c..0000000000 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonSourceOpener.php +++ /dev/null @@ -1,97 +0,0 @@ - $batchSize - * - * @return Generator - */ - public function batches(SourceFile $source, Schema $schema, int $batchSize, Backend $backend): Generator - { - $open = $this->open($source); - - try { - yield from $open->batches($schema, $batchSize, $backend); - } finally { - $open->close(); - } - } - - public function open(SourceFile $source): JsonOpenSource - { - if (!extension_loaded('flow_php') || $this->pointer !== null) { - return new PhpJsonOpenSource($this->reader, $source); - } - - $stream = $this->filesystem->readFrom($source->path); - - try { - $head = ''; - $offset = 0; - - if ($this->format === JsonFormat::Document) { - // the first byte after JSON whitespace and one leading BOM: '[' is native; an object, a scalar or an - // empty file is the PHP lane's (member iteration / JSON Machine's verdict) - $first = ''; - - for (; ($head = $stream->read(NativeJsonOpenSource::CHUNK, $offset)) !== ''; $offset += strlen($head)) { - $bytes = $offset === 0 && str_starts_with($head, "\u{FEFF}") ? substr($head, 3) : $head; - $skip = strspn($bytes, " \t\n\r"); - - if ($skip < strlen($bytes)) { - $first = $bytes[$skip]; - - break; - } - } - - if ($first !== '[') { - $stream->close(); - - return new PhpJsonOpenSource($this->reader, $source); - } - } - - return new NativeJsonOpenSource( - $stream, - new NativeJsonReader($this->format === JsonFormat::Lines, $source->uri()), - $head, - $offset, - ); - } catch (Throwable $e) { - $stream->close(); - - throw $e; - } - } -} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJSONEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJSONEncoder.php deleted file mode 100644 index 055f18a17d..0000000000 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJSONEncoder.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ - private array $unrendered = []; - - public function __construct( - private readonly NativeJsonWriter $writer, - private readonly PhpJSONEncoder $php, - ) {} - - public function encode(Rows $rows, string $separator): string - { - $schema = $rows->schema(); - - // consecutive batches share one Schema object - if ($schema !== $this->schema) { - $this->unrendered = $this->writer->unrendered($schema); - $this->schema = $schema; - } - - $fragments = []; - - foreach ($this->unrendered as $name) { - $fragments[$name] = $this->php->fragments($schema->get($name)->type(), $rows->column($name)); - } - - return $this->writer->encode($rows, $fragments, $separator); - } -} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJsonOpenSource.php deleted file mode 100644 index b7986ec68f..0000000000 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/NativeJsonOpenSource.php +++ /dev/null @@ -1,73 +0,0 @@ - $offset - */ - public function __construct( - private SourceStream $stream, - private NativeJsonReader $reader, - private string $head = '', - private int $offset = 0, - ) {} - - public function batches(Schema $schema, int $batchSize, Backend $backend): Generator - { - // every batch goes through the configured backend, which keeps its own columns and copies the native ones - $adopted = static function (Rows $batch) use ($schema, $backend): Rows { - $columns = []; - $native = $batch->columns(); - - foreach ($schema->definitions() as $name => $definition) { - $columns[$name] = $backend->adopt($definition, $native[$name]); - } - - return Rows::fromColumns($schema, $columns, $batch->count()); - }; - - $offset = $this->offset; - $chunk = $this->head === '' ? $this->stream->read(self::CHUNK, $offset) : $this->head; - - while ($chunk !== '') { - $this->reader->feed($chunk); - - while (($batch = $this->reader->nextColumns($schema, $batchSize)) !== null) { - yield $adopted($batch); - } - - $offset += strlen($chunk); - $chunk = $this->stream->read(self::CHUNK, $offset); - } - - $this->reader->finish(); - - while (($batch = $this->reader->nextColumns($schema, $batchSize)) !== null) { - yield $adopted($batch); - } - } - - public function close(): void - { - $this->stream->close(); - } -} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJSONEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJSONEncoder.php index 369bc6c1a3..5b2c6070ba 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJSONEncoder.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJSONEncoder.php @@ -74,6 +74,7 @@ public function encode(Rows $rows, string $separator): string return implode($separator, $documents); } + // called by name from flow_php RustJSONEncoder::encode(), pinned by phpt 082 /** * @param Type $type * diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php index 466f0726dc..75ce0b0e30 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php @@ -7,6 +7,7 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFileReader; use Flow\ETL\Column\Backend; use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Generator; @@ -18,6 +19,9 @@ public function __construct( private SourceFile $source, ) {} + /** + * @return Generator + */ public function batches(Schema $schema, int $batchSize, Backend $backend): Generator { foreach ($this->reader->batches($this->source, $batchSize) as $raw) { diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php index 419158ec05..c3f22862aa 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php @@ -4,12 +4,12 @@ namespace Flow\ETL\Adapter\JSON\Tests\Context; +use Flow\ETL\Adapter\JSON\AdaptiveJsonOpenSource; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFileReader; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\JSONMachine\JsonLinesExtractor; use Flow\ETL\Adapter\JSON\JSONMachine\JsonSamples; use Flow\ETL\Adapter\JSON\JsonOpenSource; -use Flow\ETL\Adapter\JSON\JsonSourceOpener; use Flow\ETL\Column\Backend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\SchemaMismatchException; @@ -124,18 +124,20 @@ public static function linesExtractor(string $fixture, string $filesystem): Json } /** - * The opener JsonExtractor (Document) or JsonLinesExtractor (Lines) builds, over a reader of the same filesystem. + * The source JsonExtractor (Document) or JsonLinesExtractor (Lines) opens, over a reader of the same filesystem. */ - public static function opener( + public static function open( JsonFormat $format, + SourceFile $source, Filesystem $filesystem = new NativeLocalFilesystem(), ?string $pointer = null, - ): JsonSourceOpener { - return new JsonSourceOpener( + ): AdaptiveJsonOpenSource { + return new AdaptiveJsonOpenSource( $filesystem, self::reader($format, $filesystem, pointer: $pointer), $format, $pointer, + $source, ); } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonSourceOpenerTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php similarity index 68% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonSourceOpenerTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php index 4bf36dcaa1..5a60aea9f6 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonSourceOpenerTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php @@ -5,15 +5,15 @@ namespace Flow\ETL\Adapter\JSON\Tests\Integration; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; -use Flow\ETL\Adapter\JSON\NativeJsonOpenSource; -use Flow\ETL\Adapter\JSON\PhpJsonOpenSource; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\RustIterator; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; +use Generator; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\TestWith; @@ -25,7 +25,7 @@ use function str_repeat; use function strlen; -final class JsonSourceOpenerTest extends FlowTestCase +final class AdaptiveJsonOpenSourceTest extends FlowTestCase { #[TestWith([JsonFormat::Document, 'five_rows.json'])] #[TestWith([JsonFormat::Lines, 'five_rows.jsonl'])] @@ -35,29 +35,26 @@ public function test_without_the_extension_a_file_is_read_by_the_php_lane(JsonFo static::markTestSkipped('flow_php reads this file natively'); } - static::assertInstanceOf( - PhpJsonOpenSource::class, - JsonFixtureContext::opener($format)->open(JsonFixtureContext::source($fixture)), - ); + $open = JsonFixtureContext::open($format, JsonFixtureContext::source($fixture)); + + static::assertInstanceOf(Generator::class, $open->batches(schema(int_schema('id')), 2, new PhpBackend())); + $open->close(); } #[TestWith([JsonFormat::Document, 'five_rows.json'])] #[TestWith([JsonFormat::Lines, 'five_rows.jsonl'])] - public function test_batches_closes_the_source_when_the_consumer_stops_early( - JsonFormat $format, - string $fixture, - ): void { + public function test_close_closes_the_one_stream_the_source_opened(JsonFormat $format, string $fixture): void + { $counting = new CountingFilesystem(new NativeLocalFilesystem()); - $opener = JsonFixtureContext::opener($format, $counting); + $open = JsonFixtureContext::open($format, JsonFixtureContext::source($fixture), $counting); - $batches = $opener->batches( - JsonFixtureContext::source($fixture), - schema(int_schema('id')), - 2, - new PhpBackend(), - ); - static::assertCount(2, $batches->current()); - unset($batches); + foreach ($open->batches(schema(int_schema('id')), 2, new PhpBackend()) as $rows) { + static::assertCount(2, $rows); + + break; + } + + $open->close(); static::assertSame(1, $counting->readFromCalls); static::assertSame(1, $counting->closedStreams()); @@ -70,12 +67,12 @@ public function test_batches_closes_the_source_when_the_consumer_stops_early( #[TestWith([JsonFormat::Document, '[]'])] public function test_json_lines_and_a_top_level_array_are_read_natively(JsonFormat $format, string $content): void { - $open = JsonFixtureContext::opener($format, MemoryFiles::with([ + $open = JsonFixtureContext::open($format, new SourceFile(path('memory://a.json')), MemoryFiles::with([ 'memory://a.json' => $content, - ]))->open(new SourceFile(path('memory://a.json'))); + ])); $open->close(); - static::assertInstanceOf(NativeJsonOpenSource::class, $open); + static::assertInstanceOf(RustIterator::class, $open->batches(schema(int_schema('id')), 2, new PhpBackend())); } /** @@ -91,10 +88,8 @@ public function test_a_native_document_is_read_once_from_the_peeked_chunk_on(str $content = str_repeat(' ', $spaces) . $content; $counting = new CountingFilesystem(MemoryFiles::with(['memory://a.json' => $content])); - $open = JsonFixtureContext::opener(JsonFormat::Document, $counting)->open(new SourceFile(path( - 'memory://a.json', - ))); - static::assertInstanceOf(NativeJsonOpenSource::class, $open); + $open = JsonFixtureContext::open(JsonFormat::Document, new SourceFile(path('memory://a.json')), $counting); + static::assertInstanceOf(RustIterator::class, $open->batches(schema(int_schema('id')), 2, new PhpBackend())); static::assertSame( serialize([[['id' => 1], ['id' => 2]]]), @@ -112,11 +107,9 @@ public function test_a_document_not_opening_an_array_is_read_by_the_php_lane(str { $counting = new CountingFilesystem(MemoryFiles::with(['memory://a.json' => $content])); - $open = JsonFixtureContext::opener(JsonFormat::Document, $counting)->open(new SourceFile(path( - 'memory://a.json', - ))); + $open = JsonFixtureContext::open(JsonFormat::Document, new SourceFile(path('memory://a.json')), $counting); - static::assertInstanceOf(PhpJsonOpenSource::class, $open); + static::assertInstanceOf(Generator::class, $open->batches(schema(int_schema('id')), 2, new PhpBackend())); static::assertSame($counting->readFromCalls, $counting->closedStreams(), 'the peek closes its stream'); } @@ -127,9 +120,9 @@ public function test_a_pointer_is_read_by_the_php_lane(JsonFormat $format, strin { $counting = new CountingFilesystem(new NativeLocalFilesystem()); - $open = JsonFixtureContext::opener($format, $counting, $pointer)->open(JsonFixtureContext::source($fixture)); + $open = JsonFixtureContext::open($format, JsonFixtureContext::source($fixture), $counting, $pointer); - static::assertInstanceOf(PhpJsonOpenSource::class, $open); + static::assertInstanceOf(Generator::class, $open->batches(schema(int_schema('id')), 2, new PhpBackend())); static::assertSame(0, $counting->readFromCalls); } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonOpenSourceTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonOpenSourceTest.php similarity index 76% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonOpenSourceTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonOpenSourceTest.php index 25c7fe419b..59c6607a4b 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonOpenSourceTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonOpenSourceTest.php @@ -23,10 +23,10 @@ use function str_starts_with; #[RequiresPhpExtension('flow_php')] -final class NativeJsonOpenSourceTest extends FlowTestCase +final class RustJsonOpenSourceTest extends FlowTestCase { /** - * Every fixture except the malformed ones NativeJsonRefusalTest covers. + * Every fixture except the malformed ones RustJsonRefusalTest covers. * * @return Generator */ @@ -60,7 +60,7 @@ public function test_both_lanes_read_a_fixture_identically(string $fixture): voi batches: $batches, ), JsonFixtureContext::outcome( - JsonFixtureContext::opener($format)->open($source), + JsonFixtureContext::open($format, $source), $schema, $batchSize, batches: $batches, @@ -73,11 +73,7 @@ public function test_a_value_past_the_sample_is_refused_as_the_php_lane_refuses_ $schema = JsonFixtureContext::infer('misfit.json', infer_schema()->sampleSize(3)->build()); $source = JsonFixtureContext::source('misfit.json'); - $native = JsonFixtureContext::outcome( - JsonFixtureContext::opener(JsonFormat::Document)->open($source), - $schema, - 2, - ); + $native = JsonFixtureContext::outcome(JsonFixtureContext::open(JsonFormat::Document, $source), $schema, 2); static::assertStringStartsWith(SchemaMismatchException::class . ':', $native); static::assertSame( @@ -88,12 +84,12 @@ public function test_a_value_past_the_sample_is_refused_as_the_php_lane_refuses_ public function test_under_the_php_backend_no_native_column_survives(): void { - $open = JsonFixtureContext::opener(JsonFormat::Lines)->open(JsonFixtureContext::source('parity_people.jsonl')); + $open = JsonFixtureContext::open(JsonFormat::Lines, JsonFixtureContext::source('parity_people.jsonl')); try { foreach ($open->batches(JsonFixtureContext::infer('parity_people.jsonl'), 2, new PhpBackend()) as $batch) { foreach ($batch->columns() as $column) { - static::assertNotSame('Flow\ETL\Column\NativeColumn', $column::class); + static::assertNotSame('Flow\ETL\Column\RustColumn', $column::class); } } } finally { @@ -101,18 +97,18 @@ public function test_under_the_php_backend_no_native_column_survives(): void } } - public function test_an_early_stop_closes_the_stream(): void + public function test_close_after_a_partial_read_closes_the_stream(): void { $counting = new CountingFilesystem(new NativeLocalFilesystem()); + $open = JsonFixtureContext::open(JsonFormat::Document, JsonFixtureContext::source('five_rows.json'), $counting); - $batches = JsonFixtureContext::opener(JsonFormat::Document, $counting)->batches( - JsonFixtureContext::source('five_rows.json'), - schema(int_schema('id')), - 2, - new PhpBackend(), - ); - static::assertSame([['id' => 1], ['id' => 2]], $batches->current()->toArray()); - unset($batches); + foreach ($open->batches(schema(int_schema('id')), 2, new PhpBackend()) as $rows) { + static::assertSame([['id' => 1], ['id' => 2]], $rows->toArray()); + + break; + } + + $open->close(); static::assertSame(1, $counting->readFromCalls); static::assertSame(1, $counting->closedStreams()); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonRefusalTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonRefusalTest.php similarity index 88% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonRefusalTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonRefusalTest.php index 40f0bf7d11..1047f12a54 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/NativeJsonRefusalTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonRefusalTest.php @@ -5,11 +5,11 @@ namespace Flow\ETL\Adapter\JSON\Tests\Integration; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; -use Flow\ETL\Adapter\JSON\NativeJsonOpenSource; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\RustIterator; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\FlowTestCase; use Generator; @@ -24,7 +24,7 @@ use function str_repeat; #[RequiresPhpExtension('flow_php')] -final class NativeJsonRefusalTest extends FlowTestCase +final class RustJsonRefusalTest extends FlowTestCase { /** * @return Generator @@ -83,10 +83,10 @@ public function test_malformed_json_is_refused_naming_the_file_and_the_record( string $content, string $record, ): void { - $open = JsonFixtureContext::opener($format, MemoryFiles::with([ + $open = JsonFixtureContext::open($format, new SourceFile(path('memory://a.json')), MemoryFiles::with([ 'memory://a.json' => $content, - ]))->open(new SourceFile(path('memory://a.json'))); - static::assertInstanceOf(NativeJsonOpenSource::class, $open); + ])); + static::assertInstanceOf(RustIterator::class, $open->batches(schema(int_schema('id')), 2, new PhpBackend())); $this->expectException(RuntimeException::class); $this->expectExceptionMessageMatches( @@ -102,9 +102,13 @@ public function test_malformed_json_is_refused_naming_the_file_and_the_record( public function test_a_scalar_line_is_refused_as_a_scalar_record(): void { - $open = JsonFixtureContext::opener(JsonFormat::Lines, MemoryFiles::with([ - 'memory://a.jsonl' => "{\"id\":1}\n5\n", - ]))->open(new SourceFile(path('memory://a.jsonl'))); + $open = JsonFixtureContext::open( + JsonFormat::Lines, + new SourceFile(path('memory://a.jsonl')), + MemoryFiles::with([ + 'memory://a.jsonl' => "{\"id\":1}\n5\n", + ]), + ); $this->expectException(RuntimeException::class); $this->expectExceptionMessage('A JSON record must be an object or an array, int given in "memory://a.jsonl".'); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JSONEncoderMother.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JSONEncoderMother.php index e2dec80416..680cfbf5be 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JSONEncoderMother.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JSONEncoderMother.php @@ -5,9 +5,8 @@ namespace Flow\ETL\Adapter\JSON\Tests\Mother; use DateTimeInterface; -use Flow\ETL\Adapter\JSON\NativeJSONEncoder; -use Flow\ETL\Adapter\JSON\NativeJsonWriter; use Flow\ETL\Adapter\JSON\PhpJSONEncoder; +use Flow\ETL\Adapter\JSON\RustJSONEncoder; use const JSON_THROW_ON_ERROR; @@ -17,9 +16,11 @@ public static function native( int $flags = JSON_THROW_ON_ERROR, string $dateTimeFormat = DateTimeInterface::ATOM, string $dateFormat = 'Y-m-d', - ): NativeJSONEncoder { - return new NativeJSONEncoder( - new NativeJsonWriter($flags, $dateTimeFormat, $dateFormat), + ): RustJSONEncoder { + return new RustJSONEncoder( + $flags, + $dateTimeFormat, + $dateFormat, new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat), ); } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonSinkOpenerTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJSONEncoderTest.php similarity index 71% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonSinkOpenerTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJSONEncoderTest.php index d2be2bc898..e516fcc183 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonSinkOpenerTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJSONEncoderTest.php @@ -5,8 +5,9 @@ namespace Flow\ETL\Adapter\JSON\Tests\Unit; use DateTimeImmutable; +use Flow\ETL\Adapter\JSON\AdaptiveJSONEncoder; use Flow\ETL\Adapter\JSON\JsonFraming; -use Flow\ETL\Adapter\JSON\JsonSinkOpener; +use Flow\ETL\Adapter\JSON\JsonOpenSink; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Stream\StringDestinationStream; @@ -21,17 +22,16 @@ use const JSON_THROW_ON_ERROR; use const JSON_UNESCAPED_SLASHES; -final class JsonSinkOpenerTest extends FlowTestCase +final class AdaptiveJSONEncoderTest extends FlowTestCase { - public function test_an_opened_sink_writes_with_the_options_of_its_opener(): void + public function test_a_sink_writes_with_the_options_of_its_encoder(): void { $stream = new StringDestinationStream(path('memory://out.json')); - $sink = (new JsonSinkOpener( - JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES, - 'd/m/Y H:i', - 'Y/m/d', + $sink = new JsonOpenSink( + $stream, + new AdaptiveJSONEncoder(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES, 'd/m/Y H:i', 'Y/m/d'), JsonFraming::ARRAY, - ))->open($stream); + ); $sink->write(array_to_rows( [['at' => new DateTimeImmutable('2023-10-01 12:02:01 UTC'), 'on' => new DateTimeImmutable('2023-10-01')]], @@ -45,7 +45,11 @@ public function test_an_opened_sink_writes_with_the_options_of_its_opener(): voi public function test_a_flag_the_native_writer_does_not_render_is_written_through_php(): void { $stream = new StringDestinationStream(path('memory://out.json')); - $sink = (new JsonSinkOpener(JSON_PRETTY_PRINT, 'Y-m-d', 'Y-m-d', JsonFraming::LINES))->open($stream); + $sink = new JsonOpenSink( + $stream, + new AdaptiveJSONEncoder(JSON_PRETTY_PRINT, 'Y-m-d', 'Y-m-d'), + JsonFraming::LINES, + ); $sink->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $sink->close(); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/NativeJSONEncoderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJSONEncoderTest.php similarity index 74% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/NativeJSONEncoderTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJSONEncoderTest.php index ec4472580d..526aceef73 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/NativeJSONEncoderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJSONEncoderTest.php @@ -5,9 +5,8 @@ namespace Flow\ETL\Adapter\JSON\Tests\Unit; use DateTimeInterface; -use Flow\ETL\Adapter\JSON\NativeJsonWriter; use Flow\ETL\Adapter\JSON\Tests\Mother\JSONEncoderMother; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\Context\TextWriterBatches; @@ -15,7 +14,6 @@ use Generator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\RequiresPhpExtension; -use PHPUnit\Framework\Attributes\TestWith; use Throwable; use function Flow\ETL\DSL\array_to_rows; @@ -31,7 +29,7 @@ use const JSON_UNESCAPED_UNICODE; #[RequiresPhpExtension('flow_php')] -final class NativeJSONEncoderTest extends FlowTestCase +final class RustJSONEncoderTest extends FlowTestCase { /** * @return Generator @@ -62,7 +60,7 @@ public function test_encode_returns_what_the_php_encoder_returns(string $batch): foreach ([ 'php' => [JSONEncoderMother::php($flags, $dateTimeFormat, $dateFormat), new PhpBackend()], - 'native' => [JSONEncoderMother::native($flags, $dateTimeFormat, $dateFormat), new DefaultBackend()], + 'native' => [JSONEncoderMother::native($flags, $dateTimeFormat, $dateFormat), new AdaptiveBackend()], 'native over adopted php columns' => [ JSONEncoderMother::native($flags, $dateTimeFormat, $dateFormat), new PhpBackend(), @@ -80,28 +78,6 @@ public function test_encode_returns_what_the_php_encoder_returns(string $batch): } } - /** - * @param list $unrendered - */ - #[TestWith(['scalars with nulls', 'Y-m-d', []])] - #[TestWith(['temporal kinds', 'Y-m-d\TH:i:sP', []])] - #[TestWith(['temporal kinds', 'D, d M Y', ['at', 'offset', 'on']])] - #[TestWith(['a json column', 'Y-m-d', ['j']])] - #[TestWith(['markup columns', 'Y-m-d', ['x', 'e']])] - #[TestWith(['nested kinds rendered natively', 'Y-m-d', []])] - #[TestWith(['a list of json documents', 'Y-m-d', ['l']])] - #[TestWith(['nested markup leaves', 'Y-m-d', ['l', 's']])] - public function test_the_columns_the_writer_leaves_to_php_fragments( - string $batch, - string $format, - array $unrendered, - ): void { - static::assertSame( - $unrendered, - (new NativeJsonWriter(JSON_THROW_ON_ERROR, $format, $format))->unrendered(TextWriterBatches::of($batch)[0]), - ); - } - public function test_a_batch_under_another_schema_is_rendered_by_that_schema(): void { $encoder = JSONEncoderMother::native(); @@ -118,6 +94,6 @@ public function test_the_writer_refuses_a_flag_it_does_not_render(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('flow_php JSON writer supports only the JSON_THROW_ON_ERROR'); - new NativeJsonWriter(JSON_PRETTY_PRINT, DateTimeInterface::ATOM, 'Y-m-d'); + JSONEncoderMother::native(JSON_PRETTY_PRINT); } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php new file mode 100644 index 0000000000..3585548428 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php @@ -0,0 +1,55 @@ +openForWrite( + $stream, + $schema, + $compressions, + $options, + ); + + $this->sink = extension_loaded('flow_php') && $file instanceof RustParquetFileWriter + ? new RustParquetOpenSink($file) + : new PhpParquetOpenSink($file, new ParquetEncoder($schema)); + } + + public function close(): void + { + $this->sink->close(); + } + + public function write(Rows $rows): void + { + $this->sink->write($rows); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSource.php new file mode 100644 index 0000000000..e738b8005c --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSource.php @@ -0,0 +1,37 @@ +reader(); + + $this->source = extension_loaded('flow_php') && $reader instanceof RustParquetFileReader + ? new RustParquetOpenSource($reader) + : new PhpParquetOpenSource($file); + } + + public function batches(Schema $schema, int $batchSize, ?int $offset, ?int $limit, Backend $backend): Iterator + { + return $this->source->batches($schema, $batchSize, $offset, $limit, $backend); + } + + public function close(): void + { + $this->source->close(); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php deleted file mode 100644 index 70d164f5f9..0000000000 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpener.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ -final readonly class EngineParquetOpener implements ParquetOpener -{ - public function __construct( - private ParquetEngine $engine, - private Options $options, - ) {} - - /** - * @return ParquetFile - */ - public function file(SourceStream $stream): ParquetFile - { - return new ParquetFile($stream, $this->options, $this->engine->openForRead($stream)); - } - - public function sink( - DestinationStream $stream, - ParquetSchema $schema, - Compressions $compressions, - Options $options, - ): ParquetOpenSink { - $writer = new Writer(compression: $compressions, options: $options, engine: $this->engine); - $writer->openForStream($stream, $schema); - - return new EngineParquetOpenSink($writer, new ParquetEncoder($schema)); - } - - /** - * @param ParquetSourceFile $file - */ - public function source(ParquetSourceFile $file): ParquetOpenSource - { - return new EngineParquetOpenSource($file->file); - } -} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSink.php deleted file mode 100644 index bf44b7c53c..0000000000 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSink.php +++ /dev/null @@ -1,24 +0,0 @@ -writer->close(); - } - - public function write(Rows $rows): void - { - $this->writer->write($rows); - } -} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php deleted file mode 100644 index 5ef822ce8a..0000000000 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpenSource.php +++ /dev/null @@ -1,57 +0,0 @@ -reader?->close(); - $reader = - $this->reader = new NativeParquetReader( - new BatchReader( - $this->file, - array_map('strval', array_keys($schema->definitions())), - $batchSize, - $offset, - $limit, - ), - $schema, - ); - - while (($batch = $reader->next()) !== null) { - $columns = []; - $native = $batch->columns(); - - // every batch goes through the configured backend, which keeps its own columns and copies the native ones - foreach ($schema->definitions() as $name => $definition) { - $columns[$name] = $backend->adopt($definition, $native[$name]); - } - - yield Rows::fromColumns($schema, $columns, $batch->count()); - } - } - - public function close(): void - { - $this->reader?->close(); - } -} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php deleted file mode 100644 index 79a74850e2..0000000000 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/NativeParquetOpener.php +++ /dev/null @@ -1,66 +0,0 @@ - - */ -final readonly class NativeParquetOpener implements ParquetOpener -{ - public function __construct( - private Options $options, - ) {} - - /** - * @return ParquetFile - */ - public function file(SourceStream $stream): ParquetFile - { - return new ParquetFile( - $stream, - $this->options, - new ArrowParquetFileReader(new ArrowParquetFile($stream), $this->options), - ); - } - - public function sink( - DestinationStream $stream, - ParquetSchema $schema, - Compressions $compressions, - Options $options, - ): ParquetOpenSink { - return new NativeParquetOpenSink(new NativeParquetWriter( - new RowsWriter( - $stream, - ArrowSchemaConverter::toExtension($schema), - ArrowParquetEngine::mapCompression($compressions), - OptionsConverter::toExtension($options), - $this->options->getInt(Option::ARROW_WRITE_BATCH_SIZE), - ), - )); - } - - /** - * @param ParquetSourceFile $file - */ - public function source(ParquetSourceFile $file): ParquetOpenSource - { - return new NativeParquetOpenSource($file->file->reader()->file()); - } -} 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 d4ba1fbb1d..2158859d96 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 @@ -15,6 +15,7 @@ use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\SelfDescribingFile; use Flow\ETL\Extractor\Signal; +use Flow\ETL\Extractor\SourceFile; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; @@ -26,10 +27,12 @@ use Flow\Filesystem\Path\Filter; use Flow\Filesystem\Path\Filter\OnlyFiles; use Flow\Parquet\Binary\ByteOrder; +use Flow\Parquet\Engine\AdaptiveParquetEngine; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; -use Flow\Parquet\ParquetFileReader; +use Flow\Parquet\ParquetFile; use Generator; +use Throwable; use function array_values; use function iterator_count; @@ -59,14 +62,12 @@ final class ParquetExtractor implements /** * The first file the schema pass opened, kept for the read that follows. - * - * @var null|ParquetSourceFile */ private ?ParquetSourceFile $firstFile = null; private ?int $offset = null; - private ?ParquetOpener $opener = null; + private ?ParquetEngine $openedWith = null; private Options $options; @@ -156,7 +157,7 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi $constants = $fileColumns->forFile($file->source(), $rowsSchema); $matchTo = !$rowsSchema->isSame($target) ? $target : null; - $source = $file->open($this->opener()); + $source = $file->open(); foreach ($source->batches( $body, @@ -232,7 +233,7 @@ public function withByteOrder(ByteOrder $byteOrder): self { $this->byteOrder = $byteOrder; $this->derivedSchema = null; - $this->opener = null; + $this->openedWith = null; $this->closeFirstFile(); $this->statistics = null; @@ -256,7 +257,7 @@ public function withEngine(?ParquetEngine $engine): self { $this->engine = $engine; $this->derivedSchema = null; - $this->opener = null; + $this->openedWith = null; $this->closeFirstFile(); $this->statistics = null; @@ -279,7 +280,7 @@ public function withOptions(Options $options): self { $this->options = $options; $this->derivedSchema = null; - $this->opener = null; + $this->openedWith = null; $this->closeFirstFile(); $this->statistics = null; @@ -308,7 +309,7 @@ private function closeFirstFile(): void * One open per file: with $keepFirst the first file stays open for the read that follows, which takes it for that * path instead of opening it again - or closes it when the read starts at another path. * - * @return Generator> + * @return Generator */ private function files(Filter $pathFilter = new OnlyFiles(), bool $keepFirst = false): Generator { @@ -322,12 +323,7 @@ private function files(Filter $pathFilter = new OnlyFiles(), bool $keepFirst = f $kept = null; } - $file = ($first ? $kept : null) ?? new ParquetSourceFile( - $this->opener()->file($this->filesystem->readFrom($source->path)), - $source, - $this->schemaConverter, - array_values($this->columns), - ); + $file = ($first ? $kept : null) ?? $this->open($source); if ($keepFirst && $first) { $this->firstFile = $file; @@ -359,9 +355,25 @@ private function schemaFiles(): Generator } } - private function opener(): ParquetOpener + private function open(SourceFile $source): ParquetSourceFile { - return $this->opener ??= ParquetOpeners::select($this->engine, $this->byteOrder, $this->options); + $stream = $this->filesystem->readFrom($source->path); + $engine = $this->openedWith ??= $this->engine ?? new AdaptiveParquetEngine($this->byteOrder, $this->options); + + try { + $reader = $engine->openForRead($stream); + } catch (Throwable $e) { + $stream->close(); + + throw $e; + } + + return new ParquetSourceFile( + new ParquetFile($stream, $this->options, $reader), + $source, + $this->schemaConverter, + array_values($this->columns), + ); } public function withSchema(Schema $schema): static diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php index 4d8ebfa5ca..6a5f1a3c43 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php @@ -24,7 +24,6 @@ use Flow\Filesystem\Path; use Flow\Filesystem\Path\Option; use Flow\Filesystem\Path\Option\ContentType; -use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Option as ParquetOption; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; @@ -57,8 +56,6 @@ final class ParquetLoader implements Closure, Discardable, FileLoader, Loader, P private ?ParquetSchemaConformance $conformance = null; - private ?ParquetOpener $opener = null; - private ?ParquetSchema $parquetSchema = null; private Options $options; @@ -129,7 +126,6 @@ public function load(Rows $rows, FlowContext $context): void $this->inferredSchema ??= $rows->schema()->makeNullable(); } - $opener = $this->opener ??= ParquetOpeners::select($this->engine, ByteOrder::LITTLE_ENDIAN, $this->options); $parquetSchema = $this->parquetSchema ??= $this->converter->toParquet($this->schema()); $conformed = ($this->conformance ??= new ParquetSchemaConformance($parquetSchema))->conform( $rows, @@ -141,11 +137,12 @@ public function load(Rows $rows, FlowContext $context): void $partitions->toArray(), ); - ($this->writers[$stream->path()->uri()] ??= $opener->sink( + ($this->writers[$stream->path()->uri()] ??= new AdaptiveParquetOpenSink( $stream, $parquetSchema, $this->compressions, $this->options, + $this->engine, ))->write($group); } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php index 9929b33f6d..93b43ea093 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php @@ -6,6 +6,12 @@ use Flow\ETL\Rows; +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} + interface ParquetOpenSink { public function close(): void; diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php index 21287d99d6..5b243fe8c0 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php @@ -7,7 +7,13 @@ use Flow\ETL\Column\Backend; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Generator; +use Iterator; + +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} interface ParquetOpenSource { @@ -16,9 +22,9 @@ interface ParquetOpenSource * * @param int<1, max> $batchSize * - * @return Generator + * @return Iterator */ - public function batches(Schema $schema, int $batchSize, ?int $offset, ?int $limit, Backend $backend): Generator; + public function batches(Schema $schema, int $batchSize, ?int $offset, ?int $limit, Backend $backend): Iterator; public function close(): void; } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php deleted file mode 100644 index 5cd6a50a41..0000000000 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpener.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ - public function file(SourceStream $stream): ParquetFile; - - public function sink( - DestinationStream $stream, - ParquetSchema $schema, - Compressions $compressions, - Options $options, - ): ParquetOpenSink; - - /** - * @param ParquetSourceFile $file - */ - public function source(ParquetSourceFile $file): ParquetOpenSource; -} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php deleted file mode 100644 index f8909f7717..0000000000 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpeners.php +++ /dev/null @@ -1,29 +0,0 @@ - $file - */ public function __construct( private ParquetSourceFile $file, ) {} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php index addff72960..d1aecaac33 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php @@ -18,17 +18,14 @@ use function count; use function in_array; -/** - * @template R of ParquetFileReader - */ final readonly class ParquetSourceFile implements SelfDescribingFile { /** - * @param ParquetFile $file + * @param ParquetFile $file * @param list $columns */ public function __construct( - /** @var ParquetFile */ + /** @var ParquetFile */ public ParquetFile $file, private SourceFile $source, private SchemaConverter $converter, @@ -40,12 +37,9 @@ public function close(): void $this->file->close(); } - /** - * @param ParquetOpener $opener - */ - public function open(ParquetOpener $opener): ParquetOpenSource + public function open(): ParquetOpenSource { - return $opener->source($this); + return new AdaptiveParquetOpenSource($this->file); } /** diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/PhpParquetOpenSink.php similarity index 53% rename from src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSink.php rename to src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/PhpParquetOpenSink.php index 9404efeb1b..4b2a08cb99 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSink.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/PhpParquetOpenSink.php @@ -5,22 +5,22 @@ namespace Flow\ETL\Adapter\Parquet; use Flow\ETL\Rows; -use Flow\Parquet\Writer; +use Flow\Parquet\ParquetFileWriter; -final readonly class EngineParquetOpenSink implements ParquetOpenSink +final readonly class PhpParquetOpenSink implements ParquetOpenSink { public function __construct( - private Writer $writer, + private ParquetFileWriter $file, private ParquetEncoder $encoder, ) {} public function close(): void { - $this->writer->close(); + $this->file->close(); } public function write(Rows $rows): void { - $this->writer->writeColumns($this->encoder->columns($rows)); + $this->file->writeColumns($this->encoder->columns($rows)); } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/PhpParquetOpenSource.php similarity index 88% rename from src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSource.php rename to src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/PhpParquetOpenSource.php index a102839c24..68eb9383da 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/EngineParquetOpenSource.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/PhpParquetOpenSource.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Adapter\Parquet; use Flow\ETL\Column\Backend; +use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; @@ -14,12 +15,15 @@ use function array_map; use function array_values; -final class EngineParquetOpenSource implements ParquetOpenSource +final class PhpParquetOpenSource implements ParquetOpenSource { public function __construct( private readonly ParquetFile $file, ) {} + /** + * @return Generator + */ public function batches(Schema $schema, int $batchSize, ?int $offset, ?int $limit, Backend $backend): Generator { $names = array_values(array_map(static fn(Definition $definition): string => $definition diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php index 904484336e..fc72becdf0 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetFilesContext.php @@ -4,9 +4,8 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Context; -use Flow\Arrow\Parquet\RowsWriter; -use Flow\ETL\Adapter\Parquet\NativeParquetOpenSink; -use Flow\ETL\Adapter\Parquet\NativeParquetWriter; +use Flow\ETL\Adapter\Parquet\ParquetOpenSink; +use Flow\ETL\Adapter\Parquet\RustParquetOpenSink; use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Rows; use Flow\ETL\Schema as FlowSchema; @@ -16,8 +15,10 @@ use Flow\Parquet\Engine\Arrow\OptionsConverter; use Flow\Parquet\Engine\Arrow\SchemaConverter as ArrowSchemaConverter; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\RustParquetFileWriter; use Flow\Parquet\Option; use Flow\Parquet\Options; +use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Encodings; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\Column; @@ -110,17 +111,17 @@ public static function phpEngineValues(Filesystem $filesystem, string $uri): arr ); } - public static function nativeSink(Filesystem $filesystem, string $uri, FlowSchema $schema): NativeParquetOpenSink + public static function nativeSink(Filesystem $filesystem, string $uri, FlowSchema $schema): ParquetOpenSink { - return new NativeParquetOpenSink(new NativeParquetWriter( - new RowsWriter( + return new RustParquetOpenSink( + new RustParquetFileWriter( $filesystem->writeTo(path($uri)), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), - 'SNAPPY', + Compressions::SNAPPY, OptionsConverter::toExtension(Options::default()), Options::default()->getInt(Option::ARROW_WRITE_BATCH_SIZE), ), - )); + ); } /** diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php index b30b940234..e76805a4c1 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php @@ -4,8 +4,6 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Context; -use Flow\ETL\Adapter\Parquet\EngineParquetOpener; -use Flow\ETL\Adapter\Parquet\ParquetOpener; use Flow\ETL\Adapter\Parquet\ParquetSourceFile; use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Extractor\SourceFile; @@ -13,6 +11,8 @@ use Flow\Filesystem\Path; use Flow\Parquet\Engine\PhpParquetEngine; use Flow\Parquet\Options; +use Flow\Parquet\ParquetEngine; +use Flow\Parquet\ParquetFile; use function Flow\Filesystem\DSL\path; @@ -24,20 +24,17 @@ public static function fixture(): Path } /** - * @template R of \Flow\Parquet\ParquetFileReader - * * @param list $columns - * @param ParquetOpener $opener - * - * @return ParquetSourceFile */ public static function over( Filesystem $filesystem, array $columns = [], - ParquetOpener $opener = new EngineParquetOpener(new PhpParquetEngine(), new Options()), + ParquetEngine $engine = new PhpParquetEngine(), ): ParquetSourceFile { + $stream = $filesystem->readFrom(self::fixture()); + return new ParquetSourceFile( - $opener->file($filesystem->readFrom(self::fixture())), + new ParquetFile($stream, new Options(), $engine->openForRead($stream)), new SourceFile(self::fixture()), new SchemaConverter(), $columns, diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Double/RecordingParquetEngine.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Double/RecordingParquetEngine.php new file mode 100644 index 0000000000..1a2941b7b8 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Double/RecordingParquetEngine.php @@ -0,0 +1,50 @@ +engine->openForRead($stream); + } + + public function openForWrite( + DestinationStream $stream, + Schema $schema, + Compressions $compression, + Options $options, + ): ParquetFileWriter { + $this->openedForWrite++; + + return $this->engine->openForWrite($stream, $schema, $compression, $options); + } + + public function writeRows( + DestinationStream $stream, + Schema $schema, + Compressions $compression, + Options $options, + iterable $rows, + ): void { + $this->engine->writeRows($stream, $schema, $compression, $options, $rows); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php index 2c4b5a06ee..b7fcaae8c1 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Integration/ParquetTest.php @@ -14,8 +14,8 @@ use Flow\Filesystem\Exception\RuntimeException as FilesystemRuntimeException; use Flow\Filesystem\SizeUnits; use Flow\Filesystem\Tests\Double\FailingCloseFilesystem; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\Exception\RuntimeException as ParquetRuntimeException; use Flow\Parquet\Option; use Flow\Parquet\Options; @@ -111,14 +111,14 @@ public function test_writing_and_reading_with_explicit_arrow_engine(): void data_frame($config) ->read(from_array([['id' => 1], ['id' => 2]])) - ->write(to_parquet($path, engine: new ArrowParquetEngine(), filesystem: $memory)) + ->write(to_parquet($path, engine: new RustParquetEngine(), filesystem: $memory)) ->run(); static::assertSame( 2, data_frame($config)->read(from_parquet( $path, - engine: new ArrowParquetEngine(), + engine: new RustParquetEngine(), filesystem: $memory, ))->count(), ); @@ -660,7 +660,7 @@ public function test_partitions_written_with_an_explicit_arrow_engine_each_get_t ])) ->write(to_parquet( path('memory://var/engine/file.parquet'), - engine: new ArrowParquetEngine(), + engine: new RustParquetEngine(), filesystem: $memory, )->partitionBy(partition_by('p'))) ->run(); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php new file mode 100644 index 0000000000..cd263290ac --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php @@ -0,0 +1,132 @@ + + */ + public static function engines(): iterable + { + yield 'no engine' => [null]; + yield 'adaptive engine' => [new AdaptiveParquetEngine()]; + } + + #[DataProvider('engines')] + public function test_a_default_engine_writes_a_file_php_reads(?ParquetEngine $engine): void + { + $filesystem = memory_filesystem(); + $schema = schema(int_schema('id')); + $sink = new AdaptiveParquetOpenSink( + $filesystem->writeTo(path('memory://out.parquet')), + (new SchemaConverter())->toParquet($schema), + Compressions::ZSTD, + Options::default(), + $engine, + ); + + $sink->write(array_to_rows([['id' => 1], ['id' => 2]], $schema)); + $sink->close(); + + static::assertSame( + [['id' => 1], ['id' => 2]], + ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), + ); + } + + /** + * The refusal of a string written into an int column names the lane that wrote: flow_php's native columns into + * arrow-ext, PHP values into arrow-ext, or PHP values into the PHP engine. + * + * @return iterable + */ + public static function lanes(): iterable + { + $arrow = extension_loaded('arrow'); + $rust = match (true) { + $arrow && extension_loaded('flow_php') => 'is not supported by the arrow Parquet writer', + $arrow => 'row 0: expected int, got string', + default => 'require integer as value', + }; + + yield 'no engine' => [static fn(): ?ParquetEngine => null, $rust]; + yield 'little-endian adaptive engine' => [static fn(): ParquetEngine => new AdaptiveParquetEngine(), $rust]; + yield 'big-endian adaptive engine' => [ + static fn(): ParquetEngine => new AdaptiveParquetEngine(ByteOrder::BIG_ENDIAN), + 'require integer as value', + ]; + yield 'php engine' => [static fn(): ParquetEngine => new PhpParquetEngine(), 'require integer as value']; + + if ($arrow) { + yield 'rust engine' => [static fn(): ParquetEngine => new RustParquetEngine(), $rust]; + } + } + + /** + * @param Closure(): ?ParquetEngine $engine + */ + #[DataProvider('lanes')] + public function test_the_engine_decides_which_lane_writes(Closure $engine, string $refusal): void + { + $sink = new AdaptiveParquetOpenSink( + memory_filesystem()->writeTo(path('memory://out.parquet')), + (new SchemaConverter())->toParquet(schema(int_schema('id'))), + Compressions::SNAPPY, + Options::default(), + $engine(), + ); + + $this->expectExceptionMessage($refusal); + + $sink->write(array_to_rows([['id' => 'one']], schema(str_schema('id')))); + } + + public function test_any_other_engine_writes_the_file(): void + { + $filesystem = memory_filesystem(); + $schema = schema(int_schema('id')); + $engine = new RecordingParquetEngine(); + $sink = new AdaptiveParquetOpenSink( + $filesystem->writeTo(path('memory://out.parquet')), + (new SchemaConverter())->toParquet($schema), + Compressions::SNAPPY, + Options::default(), + $engine, + ); + + $sink->write(array_to_rows([['id' => 1], ['id' => 2]], $schema)); + $sink->close(); + + static::assertSame(1, $engine->openedForWrite); + static::assertSame( + [['id' => 1], ['id' => 2]], + ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), + ); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSourceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSourceTest.php new file mode 100644 index 0000000000..86dccf0e2b --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSourceTest.php @@ -0,0 +1,76 @@ +file; + $source = new AdaptiveParquetOpenSource($file); + + static::assertInstanceOf(Generator::class, $source->batches( + schema(int_schema('id')), + 10, + null, + null, + new PhpBackend(), + )); + $source->close(); + } + + #[RequiresPhpExtension('flow_php')] + #[RequiresPhpExtension('arrow')] + public function test_with_flow_php_a_rust_engine_file_reads_through_rust(): void + { + // the file closes its reader when released, so it outlives the source as ParquetSourceFile does + $file = ParquetSourceFileContext::over(new NativeLocalFilesystem(), engine: new RustParquetEngine())->file; + $source = new AdaptiveParquetOpenSource($file); + + static::assertInstanceOf(RustIterator::class, $source->batches( + schema(int_schema('id')), + 10, + null, + null, + new PhpBackend(), + )); + $source->close(); + } + + #[RequiresPhpExtension('arrow')] + public function test_without_flow_php_a_rust_engine_file_reads_through_php(): void + { + if (extension_loaded('flow_php')) { + static::markTestSkipped('flow_php is loaded'); + } + + // the file closes its reader when released, so it outlives the source as ParquetSourceFile does + $file = ParquetSourceFileContext::over(new NativeLocalFilesystem(), engine: new RustParquetEngine())->file; + $source = new AdaptiveParquetOpenSource($file); + + static::assertInstanceOf(Generator::class, $source->batches( + schema(int_schema('id')), + 10, + null, + null, + new PhpBackend(), + )); + $source->close(); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php deleted file mode 100644 index 6e3a6623a0..0000000000 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenerTest.php +++ /dev/null @@ -1,55 +0,0 @@ -sink( - $filesystem->writeTo(path('memory://out.parquet')), - (new SchemaConverter())->toParquet($schema), - Compressions::SNAPPY, - Options::default(), - ); - - $sink->write(array_to_rows([['id' => 1], ['id' => 2]], $schema)); - $sink->close(); - - static::assertSame( - [['id' => 1], ['id' => 2]], - ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), - ); - } - - public function test_source_reads_the_file_through_its_parquet_file(): void - { - $file = ParquetSourceFileContext::over(new NativeLocalFilesystem()); - - static::assertEquals( - new EngineParquetOpenSource($file->file), - (new EngineParquetOpener(new PhpParquetEngine(), Options::default()))->source($file), - ); - } -} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php deleted file mode 100644 index ea0c051d79..0000000000 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenerTest.php +++ /dev/null @@ -1,70 +0,0 @@ -sink( - $filesystem->writeTo(path('memory://out.parquet')), - (new SchemaConverter())->toParquet($schema), - Compressions::ZSTD, - Options::default(), - ); - - $sink->write(array_to_rows([['id' => 1], ['id' => 2]], $schema)); - $sink->close(); - - static::assertSame( - [['id' => 1], ['id' => 2]], - ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), - ); - } - - public function test_source_reads_the_native_file_the_file_was_opened_with(): void - { - $opener = new NativeParquetOpener(Options::default()); - $file = ParquetSourceFileContext::over(new NativeLocalFilesystem(), opener: $opener); - - static::assertEquals(new NativeParquetOpenSource($file->file->reader()->file()), $opener->source($file)); - } - - public function test_an_exception_the_stream_throws_while_opening_surfaces_as_itself(): void - { - $filesystem = memory_filesystem(); - ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Reading "memory://groups.parquet" failed'); - - (new NativeParquetOpener(Options::default()))->file(new FailingReadSourceStream($filesystem->readFrom(path( - 'memory://groups.parquet', - )))); - } -} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php index 7ef2b88d13..f4883a2542 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetExtractorTest.php @@ -13,6 +13,7 @@ use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Parquet\Binary\ByteOrder; +use Flow\Parquet\Exception\InvalidArgumentException as NotParquet; use Flow\Parquet\Options; use Generator; use PHPUnit\Framework\Attributes\DataProvider; @@ -22,6 +23,8 @@ use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; +use function Flow\Filesystem\DSL\memory_filesystem; +use function Flow\Filesystem\DSL\path; use function gc_collect_cycles; final class ParquetExtractorTest extends FlowTestCase @@ -104,6 +107,21 @@ public function test_statistics_are_computed_at_most_once(): void static::assertSame(1, $filesystem->closedStreams()); } + public function test_a_file_that_is_not_parquet_closes_the_stream_it_opened(): void + { + $filesystem = new CountingFilesystem(memory_filesystem()); + $filesystem->writeTo(path('memory://not.parquet'))->append('id,name')->close(); + + try { + from_parquet(path('memory://not.parquet'), filesystem: $filesystem)->statistics(); + static::fail('a CSV file was read as Parquet'); + } catch (NotParquet) { + } + + static::assertSame(1, $filesystem->readFromCalls); + static::assertSame(1, $filesystem->closedStreams()); + } + public function test_union_by_name_sums_every_footer_exactly(): void { $statistics = from_parquet(__DIR__ . '/../Integration/Fixtures/Pagination/*.parquet') diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php deleted file mode 100644 index ca15f833da..0000000000 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetOpenersTest.php +++ /dev/null @@ -1,129 +0,0 @@ -file( - NativeLocalSourceStream::open(ParquetSourceFileContext::fixture()), - ); - - static::assertInstanceOf(PhpParquetFileReader::class, $file->reader()); - } - - #[RequiresPhpExtension('flow_php')] - #[RequiresPhpExtension('arrow')] - public function test_a_native_opener_opens_files_with_an_arrow_reader(): void - { - $file = (new NativeParquetOpener(Options::default()))->file( - NativeLocalSourceStream::open(ParquetSourceFileContext::fixture()), - ); - - static::assertInstanceOf(ArrowParquetFileReader::class, $file->reader()); - } -} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSchemaConformanceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSchemaConformanceTest.php index a86d012a4a..19229520fd 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSchemaConformanceTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSchemaConformanceTest.php @@ -7,7 +7,7 @@ use DateTimeImmutable; use Flow\ETL\Adapter\Parquet\ParquetSchemaConformance; use Flow\ETL\Adapter\Parquet\SchemaConverter; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_to_rows; @@ -33,7 +33,7 @@ public function test_a_column_of_another_type_is_cast_to_the_writer_type(): void [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')), ), - new DefaultBackend(), + new AdaptiveBackend(), ); static::assertEquals(schema(str_schema('id'), str_schema('name')), $conformed->schema()); @@ -46,7 +46,7 @@ public function test_a_date_is_cast_to_a_datetime(): void 'at', )))))->conform(array_to_rows([[ 'at' => new DateTimeImmutable('2026-09-01'), - ]], schema(date_schema('at'))), new DefaultBackend()); + ]], schema(date_schema('at'))), new AdaptiveBackend()); static::assertEquals(schema(datetime_schema('at')), $conformed->schema()); static::assertEquals([new DateTimeImmutable('2026-09-01 00:00:00 UTC')], $conformed->column('at')->values()); @@ -56,7 +56,7 @@ public function test_a_null_typed_column_is_cast_to_a_string_column(): void { $conformed = (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema(null_schema( 'nothing', - )))))->conform(array_to_rows([['nothing' => null]], schema(null_schema('nothing'))), new DefaultBackend()); + )))))->conform(array_to_rows([['nothing' => null]], schema(null_schema('nothing'))), new AdaptiveBackend()); static::assertEquals(schema(str_schema('nothing', nullable: true)), $conformed->schema()); static::assertSame([null], $conformed->column('nothing')->values()); @@ -69,7 +69,7 @@ public function test_a_matching_column_is_passed_on_as_it_is(): void $conformed = (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema( str_schema('id'), str_schema('name'), - ))))->conform($rows, new DefaultBackend()); + ))))->conform($rows, new AdaptiveBackend()); static::assertSame($rows->column('name'), $conformed->column('name')); } @@ -87,7 +87,7 @@ public function test_a_zoned_datetime_column_is_passed_on_as_it_is(): void static::assertSame($rows, (new ParquetSchemaConformance((new SchemaConverter())->toParquet($schema)))->conform( $rows, - new DefaultBackend(), + new AdaptiveBackend(), )); } @@ -97,7 +97,7 @@ public function test_rows_matching_the_writer_schema_are_passed_on_as_they_are() static::assertSame($rows, (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema(int_schema( 'id', - )))))->conform($rows, new DefaultBackend())); + )))))->conform($rows, new AdaptiveBackend())); } public function test_a_column_the_writer_does_not_know_is_passed_on_as_it_is(): void @@ -106,6 +106,6 @@ public function test_a_column_the_writer_does_not_know_is_passed_on_as_it_is(): static::assertSame($rows, (new ParquetSchemaConformance((new SchemaConverter())->toParquet(schema(int_schema( 'id', - )))))->conform($rows, new DefaultBackend())); + )))))->conform($rows, new AdaptiveBackend())); } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php index 27e5e5a2ec..00b2ac6c09 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php @@ -4,15 +4,12 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; -use Flow\ETL\Adapter\Parquet\EngineParquetOpener; -use Flow\ETL\Adapter\Parquet\EngineParquetOpenSource; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetSourceFileContext; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Extractor\SourceFile; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; -use Flow\Parquet\Engine\PhpParquetEngine; -use Flow\Parquet\Options; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; @@ -29,14 +26,19 @@ public function test_close_releases_the_stream(): void static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); } - public function test_open_hands_the_file_to_the_opener(): void + public function test_open_reads_the_batches_of_the_file(): void { $file = ParquetSourceFileContext::over(new NativeLocalFilesystem()); + $source = $file->open(); + $counts = []; - static::assertEquals( - new EngineParquetOpenSource($file->file), - $file->open(new EngineParquetOpener(new PhpParquetEngine(), Options::default())), - ); + foreach ($source->batches(schema(int_schema('id')), 400, 100, 850, new PhpBackend()) as $rows) { + $counts[] = $rows->count(); + } + + $source->close(); + + static::assertSame([400, 400, 50], $counts); } public function test_schema_comes_from_the_file_footer(): void diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/PhpParquetOpenSinkTest.php similarity index 71% rename from src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSinkTest.php rename to src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/PhpParquetOpenSinkTest.php index 7717bba4c5..7314563398 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSinkTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/PhpParquetOpenSinkTest.php @@ -4,13 +4,14 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; -use Flow\ETL\Adapter\Parquet\EngineParquetOpenSink; use Flow\ETL\Adapter\Parquet\ParquetEncoder; +use Flow\ETL\Adapter\Parquet\PhpParquetOpenSink; use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; use Flow\ETL\Tests\FlowTestCase; use Flow\Parquet\Engine\PhpParquetEngine; -use Flow\Parquet\Writer; +use Flow\Parquet\Options; +use Flow\Parquet\ParquetFile\Compressions; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; @@ -19,16 +20,22 @@ use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; -final class EngineParquetOpenSinkTest extends FlowTestCase +final class PhpParquetOpenSinkTest extends FlowTestCase { public function test_written_batches_read_back_equal(): void { $filesystem = memory_filesystem(); $schema = schema(int_schema('id'), str_schema('name', nullable: true)); $parquetSchema = (new SchemaConverter())->toParquet($schema); - $writer = new Writer(engine: new PhpParquetEngine()); - $writer->openForStream($filesystem->writeTo(path('memory://out.parquet')), $parquetSchema); - $sink = new EngineParquetOpenSink($writer, new ParquetEncoder($parquetSchema)); + $sink = new PhpParquetOpenSink( + (new PhpParquetEngine())->openForWrite( + $filesystem->writeTo(path('memory://out.parquet')), + $parquetSchema, + Compressions::SNAPPY, + Options::default(), + ), + new ParquetEncoder($parquetSchema), + ); $sink->write(array_to_rows([['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null]], $schema)); $sink->write(array_to_rows([['id' => 3, 'name' => 'c']], $schema)); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSourceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/PhpParquetOpenSourceTest.php similarity index 90% rename from src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSourceTest.php rename to src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/PhpParquetOpenSourceTest.php index e278647a36..61e9591630 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/EngineParquetOpenSourceTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/PhpParquetOpenSourceTest.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; -use Flow\ETL\Adapter\Parquet\EngineParquetOpenSource; +use Flow\ETL\Adapter\Parquet\PhpParquetOpenSource; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\FlowTestCase; @@ -20,7 +20,7 @@ use function Flow\Filesystem\DSL\path; use function range; -final class EngineParquetOpenSourceTest extends FlowTestCase +final class PhpParquetOpenSourceTest extends FlowTestCase { /** * @param list $ids @@ -36,7 +36,7 @@ public function test_offset_and_limit_cross_row_groups(?int $offset, ?int $limit $read = []; - foreach ((new EngineParquetOpenSource((new Reader( + foreach ((new PhpParquetOpenSource((new Reader( engine: new PhpParquetEngine(), ))->readStream($filesystem->readFrom(path('memory://groups.parquet')))))->batches( schema(int_schema('id')), @@ -56,7 +56,7 @@ public function test_batches_hold_the_schema_columns(): void { $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - $source = new EngineParquetOpenSource((new Reader( + $source = new PhpParquetOpenSource((new Reader( engine: new PhpParquetEngine(), ))->readStream($filesystem->readFrom(path('memory://groups.parquet')))); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/RustParquetOpenSinkTest.php similarity index 90% rename from src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php rename to src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/RustParquetOpenSinkTest.php index 34c02c3367..627e763458 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSinkTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/RustParquetOpenSinkTest.php @@ -4,9 +4,7 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; -use Flow\Arrow\Parquet\RowsWriter; -use Flow\ETL\Adapter\Parquet\NativeParquetOpenSink; -use Flow\ETL\Adapter\Parquet\NativeParquetWriter; +use Flow\ETL\Adapter\Parquet\RustParquetOpenSink; use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; use Flow\ETL\Column\PhpBackend; @@ -15,9 +13,11 @@ use Flow\Filesystem\Tests\Double\FailingAppendDestinationStream; use Flow\Parquet\Engine\Arrow\OptionsConverter; use Flow\Parquet\Engine\Arrow\SchemaConverter as ArrowSchemaConverter; +use Flow\Parquet\Engine\RustParquetFileWriter; use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\Option; use Flow\Parquet\Options; +use Flow\Parquet\ParquetFile\Compressions; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use function Flow\ETL\DSL\array_to_rows; @@ -30,7 +30,7 @@ #[RequiresPhpExtension('flow_php')] #[RequiresPhpExtension('arrow')] -final class NativeParquetOpenSinkTest extends FlowTestCase +final class RustParquetOpenSinkTest extends FlowTestCase { public function test_a_batch_of_php_columns_reads_back_equal(): void { @@ -68,15 +68,15 @@ public function test_an_exception_append_throws_surfaces_as_itself(): void { $filesystem = memory_filesystem(); $schema = schema(int_schema('id')); - $sink = new NativeParquetOpenSink(new NativeParquetWriter( - new RowsWriter( + $sink = new RustParquetOpenSink( + new RustParquetFileWriter( new FailingAppendDestinationStream($filesystem->writeTo(path('memory://out.parquet'))), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), - 'SNAPPY', + Compressions::SNAPPY, OptionsConverter::toExtension(Options::default()), Options::default()->getInt(Option::ARROW_WRITE_BATCH_SIZE), ), - )); + ); $sink->write(array_to_rows([['id' => 1]], $schema)); $this->expectException(FilesystemRuntimeException::class); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/RustParquetOpenSourceTest.php similarity index 66% rename from src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php rename to src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/RustParquetOpenSourceTest.php index a21af9cded..dd5bfd380a 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/NativeParquetOpenSourceTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/RustParquetOpenSourceTest.php @@ -4,13 +4,15 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; -use Flow\Arrow\Parquet\ParquetFile; -use Flow\ETL\Adapter\Parquet\NativeParquetOpenSource; +use Flow\ETL\Adapter\Parquet\RustParquetOpenSource; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Php\ScalarColumn; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\FlowTestCase; +use Flow\Filesystem\Exception\RuntimeException; +use Flow\Filesystem\Tests\Double\FailingReadSourceStream; +use Flow\Parquet\Engine\RustParquetFileReader; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\TestWith; @@ -24,7 +26,7 @@ #[RequiresPhpExtension('flow_php')] #[RequiresPhpExtension('arrow')] -final class NativeParquetOpenSourceTest extends FlowTestCase +final class RustParquetOpenSourceTest extends FlowTestCase { /** * @param list $ids @@ -40,9 +42,9 @@ public function test_offset_and_limit_cross_row_groups(?int $offset, ?int $limit $read = []; - foreach ((new NativeParquetOpenSource(new ParquetFile($filesystem->readFrom(path( + foreach ((new RustParquetOpenSource(new RustParquetFileReader($filesystem->readFrom(path( 'memory://groups.parquet', - )))))->batches(schema(int_schema('id')), 3, $offset, $limit, new DefaultBackend()) as $rows) { + )))))->batches(schema(int_schema('id')), 3, $offset, $limit, new AdaptiveBackend()) as $rows) { static::assertLessThanOrEqual(3, $rows->count()); $read = [...$read, ...$rows->column('id')->values()]; } @@ -54,7 +56,9 @@ public function test_columns_are_adopted_by_the_backend(): void { $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - $source = new NativeParquetOpenSource(new ParquetFile($filesystem->readFrom(path('memory://groups.parquet')))); + $source = new RustParquetOpenSource(new RustParquetFileReader($filesystem->readFrom(path( + 'memory://groups.parquet', + )))); $names = []; @@ -73,13 +77,16 @@ public function test_a_second_batches_call_closes_the_first_reader(): void { $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - $source = new NativeParquetOpenSource(new ParquetFile($filesystem->readFrom(path('memory://groups.parquet')))); - $first = $source->batches(schema(int_schema('id')), 3, null, null, new DefaultBackend()); + $source = new RustParquetOpenSource(new RustParquetFileReader($filesystem->readFrom(path( + 'memory://groups.parquet', + )))); + $first = $source->batches(schema(int_schema('id')), 3, null, null, new AdaptiveBackend()); + $first->rewind(); static::assertSame([0, 1, 2], $first->current()->column('id')->values()); $second = []; - foreach ($source->batches(schema(int_schema('id')), 3, null, null, new DefaultBackend()) as $rows) { + foreach ($source->batches(schema(int_schema('id')), 3, null, null, new AdaptiveBackend()) as $rows) { $second = [...$second, ...$rows->column('id')->values()]; } @@ -94,8 +101,23 @@ public function test_close_before_batches_is_harmless(): void $filesystem = memory_filesystem(); ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); - (new NativeParquetOpenSource(new ParquetFile($filesystem->readFrom(path('memory://groups.parquet')))))->close(); + (new RustParquetOpenSource(new RustParquetFileReader($filesystem->readFrom(path( + 'memory://groups.parquet', + )))))->close(); $this->expectNotToPerformAssertions(); } + + public function test_an_exception_the_stream_throws_while_opening_surfaces_as_itself(): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::rowGroups($filesystem, 'memory://groups.parquet', 10, 4); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Reading "memory://groups.parquet" failed'); + + new RustParquetOpenSource(new RustParquetFileReader(new FailingReadSourceStream($filesystem->readFrom(path( + 'memory://groups.parquet', + ))))); + } } diff --git a/src/bridge/phpunit/postgresql/tests/Flow/Bridge/PHPUnit/PostgreSQL/Tests/Unit/SkipTransactionRollbackTest.php b/src/bridge/phpunit/postgresql/tests/Flow/Bridge/PHPUnit/PostgreSQL/Tests/Unit/SkipTransactionRollbackTest.php index 7f66ee1ada..3936d02e9c 100644 --- a/src/bridge/phpunit/postgresql/tests/Flow/Bridge/PHPUnit/PostgreSQL/Tests/Unit/SkipTransactionRollbackTest.php +++ b/src/bridge/phpunit/postgresql/tests/Flow/Bridge/PHPUnit/PostgreSQL/Tests/Unit/SkipTransactionRollbackTest.php @@ -17,21 +17,27 @@ final class SkipTransactionRollbackTest extends TestCase { public function test_attribute_can_target_class(): void { - $attribute = (new ReflectionClass(SkipTransactionRollback::class))->getAttributes(Attribute::class)[0]->newInstance(); + $attribute = (new ReflectionClass(SkipTransactionRollback::class))->getAttributes( + Attribute::class, + )[0]->newInstance(); static::assertNotSame(0, $attribute->flags & Attribute::TARGET_CLASS); } public function test_attribute_can_target_method(): void { - $attribute = (new ReflectionClass(SkipTransactionRollback::class))->getAttributes(Attribute::class)[0]->newInstance(); + $attribute = (new ReflectionClass(SkipTransactionRollback::class))->getAttributes( + Attribute::class, + )[0]->newInstance(); static::assertNotSame(0, $attribute->flags & Attribute::TARGET_METHOD); } public function test_attribute_detected_on_class(): void { - static::assertNotEmpty((new ReflectionClass(SkippedTestCase::class))->getAttributes(SkipTransactionRollback::class)); + static::assertNotEmpty((new ReflectionClass(SkippedTestCase::class))->getAttributes( + SkipTransactionRollback::class, + )); } public function test_attribute_detected_on_method(): void @@ -54,6 +60,8 @@ public function test_attribute_detected_on_parent_abstract_class(): void public function test_attribute_not_present_on_normal_class(): void { - static::assertEmpty((new ReflectionClass(NormalTestCase::class))->getAttributes(SkipTransactionRollback::class)); + static::assertEmpty((new ReflectionClass(NormalTestCase::class))->getAttributes( + SkipTransactionRollback::class, + )); } } diff --git a/src/bridge/symfony/filesystem-bundle/tests/Flow/Bridge/Symfony/FilesystemBundle/Tests/Unit/DependencyInjection/Compiler/RegisterFilesystemFactoriesPassTest.php b/src/bridge/symfony/filesystem-bundle/tests/Flow/Bridge/Symfony/FilesystemBundle/Tests/Unit/DependencyInjection/Compiler/RegisterFilesystemFactoriesPassTest.php index ff8b659e2a..5d2f40ba11 100644 --- a/src/bridge/symfony/filesystem-bundle/tests/Flow/Bridge/Symfony/FilesystemBundle/Tests/Unit/DependencyInjection/Compiler/RegisterFilesystemFactoriesPassTest.php +++ b/src/bridge/symfony/filesystem-bundle/tests/Flow/Bridge/Symfony/FilesystemBundle/Tests/Unit/DependencyInjection/Compiler/RegisterFilesystemFactoriesPassTest.php @@ -31,7 +31,9 @@ public function test_does_nothing_when_registry_definition_absent(): void public function test_injects_tagged_factories_as_references(): void { $container = new ContainerBuilder(); - $container->setDefinition('.flow.filesystem.factory_registry', (new Definition(FilesystemFactoryRegistry::class))->setArgument(0, [])); + $container->setDefinition('.flow.filesystem.factory_registry', (new Definition( + FilesystemFactoryRegistry::class, + ))->setArgument(0, [])); $memory = new Definition(MemoryFilesystemFactory::class); $memory->addTag('flow.filesystem.factory', ['type' => 'memory']); @@ -57,7 +59,9 @@ public function test_injects_tagged_factories_as_references(): void public function test_leaves_registry_empty_when_no_tagged_services(): void { $container = new ContainerBuilder(); - $container->setDefinition('.flow.filesystem.factory_registry', (new Definition(FilesystemFactoryRegistry::class))->setArgument(0, [])); + $container->setDefinition('.flow.filesystem.factory_registry', (new Definition( + FilesystemFactoryRegistry::class, + ))->setArgument(0, [])); (new RegisterFilesystemFactoriesPass())->process($container); @@ -67,7 +71,9 @@ public function test_leaves_registry_empty_when_no_tagged_services(): void public function test_throws_on_duplicate_type_across_services(): void { $container = new ContainerBuilder(); - $container->setDefinition('.flow.filesystem.factory_registry', (new Definition(FilesystemFactoryRegistry::class))->setArgument(0, [])); + $container->setDefinition('.flow.filesystem.factory_registry', (new Definition( + FilesystemFactoryRegistry::class, + ))->setArgument(0, [])); $a = new Definition(MemoryFilesystemFactory::class); $a->addTag('flow.filesystem.factory', ['type' => 'memory']); @@ -86,7 +92,9 @@ public function test_throws_on_duplicate_type_across_services(): void public function test_throws_on_tag_without_type_attribute(): void { $container = new ContainerBuilder(); - $container->setDefinition('.flow.filesystem.factory_registry', (new Definition(FilesystemFactoryRegistry::class))->setArgument(0, [])); + $container->setDefinition('.flow.filesystem.factory_registry', (new Definition( + FilesystemFactoryRegistry::class, + ))->setArgument(0, [])); $memory = new Definition(MemoryFilesystemFactory::class); $memory->addTag('flow.filesystem.factory'); diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/migrations/container_access/20260601000000_container_access/migration.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/migrations/container_access/20260601000000_container_access/migration.php index 63e15741a1..a218de7e70 100644 --- a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/migrations/container_access/20260601000000_container_access/migration.php +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/migrations/container_access/20260601000000_container_access/migration.php @@ -14,7 +14,9 @@ return new class implements Migration { public function migrate(MigrationContext $context): void { - $container = type_instance_of(ContainerInterface::class)->assert($context->attribute(FlowPostgreSqlBundle::SERVICE_CONTAINER)); + $container = type_instance_of(ContainerInterface::class)->assert($context->attribute( + FlowPostgreSqlBundle::SERVICE_CONTAINER, + )); $table = type_string()->assert($container->getParameter('flow_test.container_table')); $seed = type_instance_of(MigrationSeedProvider::class) diff --git a/src/bridge/symfony/postgresql-messenger/tests/Flow/Bridge/Symfony/PostgreSQLMessenger/Tests/Unit/FlowPostgreSqlTransportTest.php b/src/bridge/symfony/postgresql-messenger/tests/Flow/Bridge/Symfony/PostgreSQLMessenger/Tests/Unit/FlowPostgreSqlTransportTest.php index de5b73efda..cde23cf3c0 100644 --- a/src/bridge/symfony/postgresql-messenger/tests/Flow/Bridge/Symfony/PostgreSQLMessenger/Tests/Unit/FlowPostgreSqlTransportTest.php +++ b/src/bridge/symfony/postgresql-messenger/tests/Flow/Bridge/Symfony/PostgreSQLMessenger/Tests/Unit/FlowPostgreSqlTransportTest.php @@ -47,7 +47,9 @@ public function test_all_delegates_to_receiver(): void public function test_does_not_implement_setupable_transport_interface(): void { - static::assertFalse((new ReflectionClass(FlowPostgreSqlTransport::class))->implementsInterface(SetupableTransportInterface::class)); + static::assertFalse((new ReflectionClass(FlowPostgreSqlTransport::class))->implementsInterface( + SetupableTransportInterface::class, + )); } public function test_find_delegates_to_receiver(): void diff --git a/src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php b/src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php new file mode 100644 index 0000000000..016237687b --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php @@ -0,0 +1,44 @@ +backend = extension_loaded('flow_php') ? new RustBackend() : new PhpBackend(); + } + + public function builder(Definition $definition): ColumnBuilder + { + return $this->backend->builder($definition); + } + + public function constant(Definition $definition, mixed $value, int $count): Column + { + return $this->backend->constant($definition, $value, $count); + } + + public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column + { + return $this->backend->decode($definition, $buffers, $count, $nullCount); + } + + public function adopt(Definition $definition, Column $column): Column + { + return $this->backend->adopt($definition, $column); + } + + public function allocatedBytes(): int + { + return $this->backend->allocatedBytes(); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Backend.php b/src/core/etl/src/Flow/ETL/Column/Backend.php index 20b2f02a13..187666215c 100644 --- a/src/core/etl/src/Flow/ETL/Column/Backend.php +++ b/src/core/etl/src/Flow/ETL/Column/Backend.php @@ -7,6 +7,12 @@ use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Schema\Definition; +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} + interface Backend { /** diff --git a/src/core/etl/src/Flow/ETL/Column/Column.php b/src/core/etl/src/Flow/ETL/Column/Column.php index 49cf3fd143..d4f7ae9817 100644 --- a/src/core/etl/src/Flow/ETL/Column/Column.php +++ b/src/core/etl/src/Flow/ETL/Column/Column.php @@ -6,6 +6,12 @@ use Flow\Types\Type; +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} + interface Column { /** diff --git a/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php index a6ece37bfe..c68309bce5 100644 --- a/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php @@ -6,6 +6,12 @@ use Flow\ETL\Exception\SchemaMismatchException; +use function extension_loaded; + +if (extension_loaded('flow_php')) { + return; +} + interface ColumnBuilder { /** diff --git a/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php index 8e4c2e0b42..847c9e2fcf 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php @@ -67,9 +67,9 @@ public function fromPhysical(mixed $physical): mixed public function markup(string $physical): string { return ( - $this->position->markupOf( - $physical, - ) ?? $this->canonical(type_instance_of(DOMElement::class)->assert($this->fromPhysical($physical))) + $this->position->markupOf($physical) ?? $this->canonical(type_instance_of( + DOMElement::class, + )->assert($this->fromPhysical($physical))) ); } diff --git a/src/core/etl/src/Flow/ETL/Config.php b/src/core/etl/src/Flow/ETL/Config.php index d58a9aafaf..005ce30f05 100644 --- a/src/core/etl/src/Flow/ETL/Config.php +++ b/src/core/etl/src/Flow/ETL/Config.php @@ -5,8 +5,8 @@ namespace Flow\ETL; use Flow\Calculator\Calculator; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Config\Cache\CacheConfig; use Flow\ETL\Config\ConfigBuilder; use Flow\ETL\Config\Grouping\HashGroupByConfig; @@ -43,7 +43,7 @@ public function __construct( public HashRepartitionConfig $repartition, private Calculator $calculator = new Calculator(), private RandomValueGenerator $randomValueGenerator = new NativePHPRandomValueGenerator(), - private Backend $backend = new DefaultBackend(), + private Backend $backend = new AdaptiveBackend(), ) { $this->planner = new Planner($optimizer); } diff --git a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php index 77d1c90692..86549122c1 100644 --- a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php @@ -7,8 +7,8 @@ use Flow\Clock\SystemClock; use Flow\ETL\Analyze; use Flow\ETL\Cache; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Config; use Flow\ETL\Config\Cache\CacheConfigBuilder; use Flow\ETL\Config\Grouping\GroupByAlgorithmBuilder; @@ -71,7 +71,7 @@ public function __construct() $this->id = null; $this->name = null; $this->serializer = null; - $this->backend = new DefaultBackend(); + $this->backend = new AdaptiveBackend(); $this->optimizer = null; $this->executor = null; $this->clock = null; diff --git a/src/core/etl/src/Flow/ETL/Config/MemoryLimit.php b/src/core/etl/src/Flow/ETL/Config/MemoryLimit.php index fa6006a3f7..c256473a02 100644 --- a/src/core/etl/src/Flow/ETL/Config/MemoryLimit.php +++ b/src/core/etl/src/Flow/ETL/Config/MemoryLimit.php @@ -33,7 +33,9 @@ public static function default(): Unit } return ( - (new Configuration(100 - self::PERCENTAGE_OF_MEMORY_LIMIT))->limit() ?? Unit::fromGb(self::WITHOUT_MEMORY_LIMIT_GB) + (new Configuration(100 - self::PERCENTAGE_OF_MEMORY_LIMIT))->limit() ?? Unit::fromGb( + self::WITHOUT_MEMORY_LIMIT_GB, + ) ); } } diff --git a/src/core/etl/src/Flow/ETL/DSL/functions.php b/src/core/etl/src/Flow/ETL/DSL/functions.php index 8195e12599..e92bf3df65 100644 --- a/src/core/etl/src/Flow/ETL/DSL/functions.php +++ b/src/core/etl/src/Flow/ETL/DSL/functions.php @@ -17,8 +17,8 @@ use Flow\ETL\Analyze; use Flow\ETL\Cache; use Flow\ETL\Cache\Implementation\FilesystemCache; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Config; use Flow\ETL\Config\ConfigBuilder; use Flow\ETL\Config\Grouping\HashGroupByBuilder; @@ -1166,7 +1166,7 @@ function number_format( * @param array>|array $data */ #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] -function array_to_rows(array $data, Schema $schema, Backend $backend = new DefaultBackend()): Rows +function array_to_rows(array $data, Schema $schema, Backend $backend = new AdaptiveBackend()): Rows { $isRows = true; diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php index f02b581ab9..da8e5849fb 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Join\HashJoin; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -15,7 +15,7 @@ public function __construct(Schema $schema) { $nullable = $schema->makeNullable(); - $backend = new DefaultBackend(); + $backend = new AdaptiveBackend(); $columns = []; foreach ($nullable->definitions() as $name => $definition) { diff --git a/src/core/etl/src/Flow/ETL/Row/Formatter/ASCIISchemaFormatter.php b/src/core/etl/src/Flow/ETL/Row/Formatter/ASCIISchemaFormatter.php index aa6cbd85bd..213f406330 100644 --- a/src/core/etl/src/Flow/ETL/Row/Formatter/ASCIISchemaFormatter.php +++ b/src/core/etl/src/Flow/ETL/Row/Formatter/ASCIISchemaFormatter.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Row\Formatter; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Formatter\AsciiTableFormatter; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; @@ -78,7 +78,7 @@ private function table(Schema $schema): Rows $columns[] = str_schema('metadata'); } - return (new RowsBuilder(schema(...$columns), new DefaultBackend())) + return (new RowsBuilder(schema(...$columns), new AdaptiveBackend())) ->appendRows($rows) ->finish(); } diff --git a/src/core/etl/src/Flow/ETL/Rows.php b/src/core/etl/src/Flow/ETL/Rows.php index e193f7e802..d9cb9f9100 100644 --- a/src/core/etl/src/Flow/ETL/Rows.php +++ b/src/core/etl/src/Flow/ETL/Rows.php @@ -5,8 +5,8 @@ namespace Flow\ETL; use Countable; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Column; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; @@ -73,7 +73,7 @@ public function __serialize(): array */ public function __unserialize(array $data): void { - $rows = (new FrameDecoder())->decode($data['frame'], $data['schema'], new DefaultBackend()); + $rows = (new FrameDecoder())->decode($data['frame'], $data['schema'], new AdaptiveBackend()); $this->schema = $rows->schema; $this->columns = $rows->columns; @@ -82,7 +82,7 @@ public function __unserialize(array $data): void public static function empty(Schema $schema): self { - $backend = new DefaultBackend(); + $backend = new AdaptiveBackend(); $columns = []; foreach ($schema->definitions() as $name => $definition) { @@ -217,7 +217,7 @@ public function concat(self ...$others): self return self::empty($this->schema); } - $backend = new DefaultBackend(); + $backend = new AdaptiveBackend(); $columns = []; foreach ($this->schema->definitions() as $name => $definition) { @@ -414,7 +414,7 @@ public function matchTo(Schema $schema): self } } - $backend = new DefaultBackend(); + $backend = new AdaptiveBackend(); $columns = []; $changed = []; diff --git a/src/core/etl/src/Flow/Floe/FloeExtractor.php b/src/core/etl/src/Flow/Floe/FloeExtractor.php index 0519eaf794..0bc366ecd8 100644 --- a/src/core/etl/src/Flow/Floe/FloeExtractor.php +++ b/src/core/etl/src/Flow/Floe/FloeExtractor.php @@ -4,8 +4,8 @@ namespace Flow\Floe; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; @@ -211,7 +211,7 @@ private function declare(): Statistics /** * @return Generator */ - private function files(Backend $backend = new DefaultBackend(), Filter $pathFilter = new OnlyFiles()): Generator + private function files(Backend $backend = new AdaptiveBackend(), Filter $pathFilter = new OnlyFiles()): Generator { foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { yield new FloeSourceFile( diff --git a/src/core/etl/src/Flow/Floe/FloeMerger.php b/src/core/etl/src/Flow/Floe/FloeMerger.php index 50ae228001..429082bdbb 100644 --- a/src/core/etl/src/Flow/Floe/FloeMerger.php +++ b/src/core/etl/src/Flow/Floe/FloeMerger.php @@ -4,8 +4,8 @@ namespace Flow\Floe; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; use Flow\ETL\Schema\Validator\EvolvingValidator; @@ -23,7 +23,7 @@ public function __construct( private Filesystem $filesystem, - private Backend $backend = new DefaultBackend(), + private Backend $backend = new AdaptiveBackend(), private Codec $codec = new NoopCodec(), ) { Format::validateCodecId($this->codec->id()); diff --git a/src/core/etl/src/Flow/Floe/FloeReader.php b/src/core/etl/src/Flow/Floe/FloeReader.php index 43c167f86b..12d72c0a50 100644 --- a/src/core/etl/src/Flow/Floe/FloeReader.php +++ b/src/core/etl/src/Flow/Floe/FloeReader.php @@ -4,8 +4,8 @@ namespace Flow\Floe; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; use Flow\Floe\Codec\NoopCodec; @@ -17,7 +17,7 @@ public function __construct( private Filesystem $filesystem, private Codec $codec = new NoopCodec(), private int $chunkSize = 65536, - private Backend $backend = new DefaultBackend(), + private Backend $backend = new AdaptiveBackend(), ) {} /** diff --git a/src/core/etl/src/Flow/Floe/FloeSerializer.php b/src/core/etl/src/Flow/Floe/FloeSerializer.php index c21ed81af6..3301819c8c 100644 --- a/src/core/etl/src/Flow/Floe/FloeSerializer.php +++ b/src/core/etl/src/Flow/Floe/FloeSerializer.php @@ -4,14 +4,14 @@ namespace Flow\Floe; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; use Flow\Floe\Codec\NoopCodec; -use Flow\Floe\Exception\ExtensionException; use Flow\Floe\Exception\FloeException; use Flow\Serializer\Exception\SerializationException; use Flow\Serializer\Serializer; @@ -28,7 +28,7 @@ final class FloeSerializer implements Serializer */ public function __construct( private readonly int $batchSize = 1000, - private readonly Backend $backend = new DefaultBackend(), + private readonly Backend $backend = new AdaptiveBackend(), ) { // @mago-ignore analysis:impossible-condition,redundant-comparison if ($this->batchSize < 1) { @@ -44,7 +44,7 @@ public function serialize(Rows $rows, DestinationStream $destination): void $writer->create($destination); $writer->write($rows); $writer->close(); - } catch (FloeException|ExtensionException $e) { + } catch (FloeException|RuntimeException $e) { throw new SerializationException($e->getMessage(), 0, $e); } } @@ -75,7 +75,7 @@ public function unserialize(SourceStream $source): Rows return $batches === [] ? (new RowsBuilder($reader->schema(), $this->backend))->finish() : $batches[0]->concat(...array_slice($batches, 1)); - } catch (FloeException|ExtensionException $e) { + } catch (FloeException|RuntimeException $e) { throw new SerializationException($e->getMessage(), 0, $e); } finally { $source->close(); diff --git a/src/core/etl/src/Flow/Floe/FloeStreamReader.php b/src/core/etl/src/Flow/Floe/FloeStreamReader.php index ec7a2b1fa4..2c1a41c57f 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamReader.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamReader.php @@ -4,13 +4,13 @@ namespace Flow\Floe; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; use Flow\Filesystem\SourceStream; -use Flow\Floe\Exception\ExtensionException; use Flow\Floe\Exception\FloeException; use Flow\Serializer\Exception\SerializationException; use Generator; @@ -37,7 +37,7 @@ public function __construct( private readonly SourceStream $source, private readonly Codec $codec, private readonly int $chunkSize, - private readonly Backend $backend = new DefaultBackend(), + private readonly Backend $backend = new AdaptiveBackend(), ) { Format::validateCodecId($this->codec->id()); $this->frameDecoder = new FrameDecoder($this->codec); @@ -257,7 +257,7 @@ private function walk( $position = 0; } } - } catch (SerializationException|ExtensionException $e) { + } catch (SerializationException|RuntimeException $e) { throw new FloeException($e->getMessage(), 0, $e); } } 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 b5168a55f6..5a02c2dac4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php @@ -5,8 +5,8 @@ namespace Flow\ETL\Tests\Double; use DateTimeImmutable; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\DefaultBackend; use Flow\ETL\Extractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; @@ -138,7 +138,7 @@ public function rawData(): Generator } } - public function toRows(Backend $backend = new DefaultBackend()): Rows + public function toRows(Backend $backend = new AdaptiveBackend()): Rows { $rows = rows(schema()); $schema = self::schema(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php similarity index 74% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php index 0b767cd3bf..0e56b06ae0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/DefaultBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Tests\Unit\Column; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\ColumnMismatchException; @@ -16,12 +16,12 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\str_schema; -final class DefaultBackendTest extends TestCase +final class AdaptiveBackendTest extends TestCase { protected function setUp(): void { if (extension_loaded('flow_php')) { - static::markTestSkipped('flow_php registers its own DefaultBackend'); + static::markTestSkipped('with flow_php AdaptiveBackend is RustBackend'); } } @@ -30,10 +30,10 @@ public function test_adopt_is_what_the_php_backend_adopts(): void $column = ColumnMother::of(int_schema('a'), [1, 2]); $foreign = new ForeignColumnStub($column); - static::assertSame($column, (new DefaultBackend())->adopt(int_schema('a'), $column)); + static::assertSame($column, (new AdaptiveBackend())->adopt(int_schema('a'), $column)); static::assertEquals( (new PhpBackend())->adopt(int_schema('a'), $foreign), - (new DefaultBackend())->adopt(int_schema('a'), $foreign), + (new AdaptiveBackend())->adopt(int_schema('a'), $foreign), ); } @@ -42,17 +42,17 @@ public function test_adopt_refuses_an_untyped_column(): void $this->expectException(ColumnMismatchException::class); $this->expectExceptionMessage('column "a": mixed cannot be a batch column'); - (new DefaultBackend())->adopt(int_schema('a'), new ValueColumn([1])); + (new AdaptiveBackend())->adopt(int_schema('a'), new ValueColumn([1])); } public function test_allocated_bytes_is_what_the_php_backend_allocates(): void { - static::assertSame((new PhpBackend())->allocatedBytes(), (new DefaultBackend())->allocatedBytes()); + static::assertSame((new PhpBackend())->allocatedBytes(), (new AdaptiveBackend())->allocatedBytes()); } public function test_builder_builds_what_the_php_backend_builds(): void { - $default = (new DefaultBackend())->builder(str_schema('a')); + $default = (new AdaptiveBackend())->builder(str_schema('a')); $default->append('x'); $php = (new PhpBackend())->builder(str_schema('a')); $php->append('x'); @@ -64,7 +64,7 @@ public function test_constant_is_what_the_php_backend_builds(): void { static::assertEquals( (new PhpBackend())->constant(int_schema('a'), 7, 3), - (new DefaultBackend())->constant(int_schema('a'), 7, 3), + (new AdaptiveBackend())->constant(int_schema('a'), 7, 3), ); } @@ -74,7 +74,7 @@ public function test_decode_is_what_the_php_backend_decodes(): void static::assertEquals( (new PhpBackend())->decode(int_schema('a', nullable: true), $buffers, 2, 1), - (new DefaultBackend())->decode(int_schema('a', nullable: true), $buffers, 2, 1), + (new AdaptiveBackend())->decode(int_schema('a', nullable: true), $buffers, 2, 1), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnWithTypeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnWithTypeTest.php index 605416f3e9..cfb0667ea6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnWithTypeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ColumnWithTypeTest.php @@ -131,9 +131,8 @@ public function test_an_enum_does_not_change_its_class(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('are different column kinds'); - ColumnMother::of( - enum_schema('a', BackedStringEnum::class), - [BackedStringEnum::one], - )->withType(type_enum(BackedIntEnum::class)); + ColumnMother::of(enum_schema('a', BackedStringEnum::class), [BackedStringEnum::one])->withType(type_enum( + BackedIntEnum::class, + )); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php index 46efb1d54f..3ae3f5de5e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php @@ -34,9 +34,9 @@ public function test_an_element_outside_the_document_tree_has_no_path(): void $document = new DOMDocument(); $document->loadXML(''); - static::assertNull((new ElementPosition())->path(type_instance_of(DOMElement::class)->assert($document->createElement( - 'detached', - )))); + static::assertNull((new ElementPosition())->path(type_instance_of( + DOMElement::class, + )->assert($document->createElement('detached')))); } public function test_the_physical_splits_into_the_path_the_markup_and_the_document(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ColumnComparatorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ColumnComparatorTest.php index a539e814b5..6844146eb4 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ColumnComparatorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Comparator/ColumnComparatorTest.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Tests\Unit\Comparator; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\Comparator\ColumnComparator; use Flow\ETL\Tests\Mother\ColumnMother; @@ -30,7 +30,7 @@ public function test_columns_of_both_backends_with_equal_values_pass(): void { $comparator = new ColumnComparator(); $comparator->setFactory(Factory::getInstance()); - $default = (new DefaultBackend())->builder(int_schema('a', nullable: true)); + $default = (new AdaptiveBackend())->builder(int_schema('a', nullable: true)); $default->appendMany([1, null]); $comparator->assertEquals(ColumnMother::of(int_schema('a', nullable: true), [1, null]), $default->finish()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php index 6e4ff19d2a..17ee488898 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php @@ -7,7 +7,7 @@ use Closure; use DateTimeImmutable; use DateTimeZone; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\ColumnMismatchException; @@ -1212,7 +1212,7 @@ public function test_concat_of_a_constant_and_a_scalar_column_yields_default_bac static::assertSame([['id' => 7], ['id' => 7], ['id' => 1]], $concatenated->toArray()); static::assertInstanceOf( - (new DefaultBackend()) + (new AdaptiveBackend()) ->builder(int_schema('id')) ->finish()::class, $concatenated->column('id'), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/InferredTypesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/InferredTypesTest.php index f5e4b142fd..9fb7341b95 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/InferredTypesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Schema/Inference/InferredTypesTest.php @@ -65,7 +65,9 @@ public function test_an_empty_list_is_rejected(): void public function test_a_parameterised_type_admits_its_whole_family(): void { - static::assertTrue((new InferredTypes(type_enum(BackedStringEnum::class)))->allows(type_enum(BackedStringEnum::class))); + static::assertTrue((new InferredTypes(type_enum(BackedStringEnum::class)))->allows(type_enum( + BackedStringEnum::class, + ))); } public function test_default_is_every_rung_but_markup(): void diff --git a/src/extension/arrow-ext/Cargo.lock b/src/extension/arrow-ext/Cargo.lock index 12d2807d5e..d69bb02fa8 100644 --- a/src/extension/arrow-ext/Cargo.lock +++ b/src/extension/arrow-ext/Cargo.lock @@ -192,6 +192,24 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bindgen" +version = "0.73.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "787ef8ef523575546b106a58213d6e6b06198a05c2f757258c68a74273670cfa" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "log", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex 2.0.1", + "syn 2.0.117", +] + [[package]] name = "bitflags" version = "2.11.0" @@ -295,7 +313,7 @@ dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex", + "shlex 1.3.0", ] [[package]] @@ -373,9 +391,9 @@ checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +checksum = "1af709f1f33454bf52eadfc8c78b3b9ef9cb26fb54d16dc9cd9a7299f899fd1b" dependencies = [ "unicode-segmentation", ] @@ -432,9 +450,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" dependencies = [ "darling_core", "darling_macro", @@ -442,26 +460,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" dependencies = [ "ident_case", "proc-macro2", "quote", "strsim", - "syn", + "syn 3.0.6", ] [[package]] name = "darling_macro" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core", "quote", - "syn", + "syn 3.0.6", ] [[package]] @@ -533,46 +551,28 @@ dependencies = [ [[package]] name = "ext-php-rs" -version = "0.15.15" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe62f25cd053f5f95dc7bbf94e5b41818ea3cf39b36cc25de8ca6b4de68a0eb" +checksum = "530651e90f34e23c956cbd1a33ec4878c05e19ea6b50dd13926b94dd6a2f2134" dependencies = [ "anyhow", + "bindgen", "bitflags", "cc", "cfg-if", - "ext-php-rs-bindgen", "ext-php-rs-build", "ext-php-rs-derive", + "ext-php-rs-introspection", "inventory", "native-tls", "once_cell", "parking_lot", "skeptic", + "thiserror", "ureq", "zip", ] -[[package]] -name = "ext-php-rs-bindgen" -version = "0.72.1-extphprs.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ceb73da3b8b18a3424765dd6926dbc29464a0a7bc31ab491600bfa02adc4bc" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", -] - [[package]] name = "ext-php-rs-build" version = "0.1.1" @@ -584,18 +584,24 @@ dependencies = [ [[package]] name = "ext-php-rs-derive" -version = "0.11.14" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f57a075f878ad51bcc56745fb21efe601429a509204f8a385bbe526566597320" +checksum = "cb3ec2dc5b2228bffa41f5a569b5656e48f964c39cd71633032eebae51e15ef1" dependencies = [ "convert_case", "darling", "itertools", "proc-macro2", "quote", - "syn", + "syn 3.0.6", ] +[[package]] +name = "ext-php-rs-introspection" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a31bb462ea3b026fc419c2c4a38283b270980ac34fed3888dd5afd635c3ef94" + [[package]] name = "fastrand" version = "2.3.0" @@ -836,9 +842,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" dependencies = [ "either", ] @@ -1063,7 +1069,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1188,7 +1194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.117", ] [[package]] @@ -1403,7 +1409,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1447,6 +1453,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "simd-adler32" version = "0.3.8" @@ -1509,6 +1521,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tempfile" version = "3.27.0" @@ -1522,6 +1545,26 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "thiserror" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + [[package]] name = "time" version = "0.3.47" @@ -1707,7 +1750,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -1793,7 +1836,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1804,7 +1847,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1870,7 +1913,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -1886,7 +1929,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -1945,7 +1988,7 @@ checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] diff --git a/src/extension/arrow-ext/Cargo.toml b/src/extension/arrow-ext/Cargo.toml index 059683a69a..e528e0f770 100644 --- a/src/extension/arrow-ext/Cargo.toml +++ b/src/extension/arrow-ext/Cargo.toml @@ -7,7 +7,7 @@ publish = false crate-type = ["cdylib"] [dependencies] -ext-php-rs = "0.15" +ext-php-rs = "0.16" parquet = { version = "59", default-features = false, features = ["arrow", "arrow_canonical_extension_types", "snap", "flate2", "flate2-zlib-rs", "zstd", "lz4", "brotli", "simdutf8"] } arrow-array = { version = "59", features = ["ffi"] } arrow-buffer = "59" diff --git a/src/extension/arrow-ext/build.rs b/src/extension/arrow-ext/build.rs index 46afddbe9c..fcb72c499f 100644 --- a/src/extension/arrow-ext/build.rs +++ b/src/extension/arrow-ext/build.rs @@ -7,8 +7,7 @@ fn main() { println!("cargo:rustc-env=ARROW_VERSION={version}"); println!("cargo:rerun-if-changed=Cargo.lock"); - let arrow_version = - resolve_dep_version("arrow-schema").unwrap_or_else(|| "unknown".to_string()); + let arrow_version = resolve_dep_version("arrow-schema").unwrap_or_else(|| "unknown".to_string()); let parquet_version = resolve_dep_version("parquet").unwrap_or_else(|| "unknown".to_string()); println!("cargo:rustc-env=ARROW_LIB_VERSION={arrow_version}"); @@ -20,7 +19,9 @@ fn main() { /// The `php84`/`php85` cfgs ext-php-rs sets for itself, for the same PHP (`PHP` first, then `PATH`): the extension /// binary is bound to the PHP minor it is built against, so version gates are compile-time. fn emit_php_version_cfg() { - use ext_php_rs_build::{emit_check_cfg, emit_php_cfg_flags, emit_rerun_if_env_changed, find_php, ApiVersion, PHPInfo}; + use ext_php_rs_build::{ + emit_check_cfg, emit_php_cfg_flags, emit_rerun_if_env_changed, find_php, ApiVersion, PHPInfo, + }; emit_rerun_if_env_changed(); emit_check_cfg(); @@ -103,7 +104,9 @@ fn as_semver(describe: &str) -> String { let mut numbers = tag.split('.').map(|number| number.parse::().ok()); match (numbers.next().flatten(), numbers.next().flatten()) { - (Some(major), Some(minor)) => format!("{major}.{}.0-dev+{distance}.{hash}", minor + 1), + (Some(major), Some(minor)) => { + format!("{major}.{}.0-dev+{distance}.{hash}", minor + 1) + } _ => describe.to_string(), } } @@ -120,11 +123,7 @@ fn resolve_dep_version(crate_name: &str) -> Option { for line in chunk.lines() { let line = line.trim(); if line.starts_with("version = ") { - return Some( - line.trim_start_matches("version = ") - .trim_matches('"') - .to_string(), - ); + return Some(line.trim_start_matches("version = ").trim_matches('"').to_string()); } } } diff --git a/src/extension/arrow-ext/composer.json b/src/extension/arrow-ext/composer.json index df2565a79b..d99b1fbed7 100644 --- a/src/extension/arrow-ext/composer.json +++ b/src/extension/arrow-ext/composer.json @@ -9,7 +9,8 @@ }, "autoload": { "psr-4": { - "Flow\\Arrow\\": "php/Flow/Arrow/" + "Flow\\Arrow\\": "php/Flow/Arrow/", + "Flow\\Parquet\\Engine\\": "php/Flow/Parquet/Engine/" } }, "scripts": { diff --git a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/ColumnsReader.php b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/ColumnsReader.php deleted file mode 100644 index 154336447c..0000000000 --- a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/ColumnsReader.php +++ /dev/null @@ -1,40 +0,0 @@ - $columns root names or struct paths - * @param int<1, max> $batchSize - */ - public function __construct(ParquetFile $file, array $columns, int $batchSize, ?int $offset, ?int $limit) - { - throw new RuntimeException('arrow extension is not loaded'); - } - - public function close(): void - { - throw new RuntimeException('arrow extension is not loaded'); - } - - /** - * At most $batchSize rows, keyed by $columns, null after the last. - * - * @return null|array> - */ - public function next(): ?array - { - throw new RuntimeException('arrow extension is not loaded'); - } -} diff --git a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/BatchReader.php b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RustBatchReader.php similarity index 70% rename from src/extension/arrow-ext/php/Flow/Arrow/Parquet/BatchReader.php rename to src/extension/arrow-ext/php/Flow/Arrow/Parquet/RustBatchReader.php index d96b6a0f8b..6ea532f5c8 100644 --- a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/BatchReader.php +++ b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RustBatchReader.php @@ -4,8 +4,9 @@ namespace Flow\Arrow\Parquet; -use Flow\Arrow\ArrowBatch; -use Flow\Arrow\ArrowSchema; +use Flow\Arrow\RustArrowSchema; +use Flow\Arrow\RustParquetBatch; +use Flow\Parquet\Engine\RustParquetFileReader; use RuntimeException; use function extension_loaded; @@ -14,13 +15,13 @@ return; } -final class BatchReader +final class RustBatchReader { /** * @param list $columns root column names * @param int<1, max> $batchSize */ - public function __construct(ParquetFile $file, array $columns, int $batchSize, ?int $offset, ?int $limit) + public function __construct(RustParquetFileReader $file, array $columns, int $batchSize, ?int $offset, ?int $limit) { throw new RuntimeException('arrow extension is not loaded'); } @@ -33,7 +34,7 @@ public function close(): void /** * At most $batchSize rows as one Arrow C Data struct array, null after the last. */ - public function next(): ?ArrowBatch + public function next(): ?RustParquetBatch { throw new RuntimeException('arrow extension is not loaded'); } @@ -41,7 +42,7 @@ public function next(): ?ArrowBatch /** * The struct schema every batch has, before any batch is read. */ - public function schema(): ArrowSchema + public function schema(): RustArrowSchema { throw new RuntimeException('arrow extension is not loaded'); } diff --git a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RustColumnsReader.php b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RustColumnsReader.php new file mode 100644 index 0000000000..bf7ee0a131 --- /dev/null +++ b/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RustColumnsReader.php @@ -0,0 +1,62 @@ +>> + */ +final class RustColumnsReader implements Iterator +{ + /** + * @param list $columns root names or struct paths + * @param int<1, max> $batchSize + */ + public function __construct(RustParquetFileReader $file, array $columns, int $batchSize, ?int $offset, ?int $limit) + { + throw new RuntimeException('arrow extension is not loaded'); + } + + /** + * At most $batchSize rows, keyed by $columns. + * + * @return null|array> + */ + public function current(): ?array + { + throw new RuntimeException('arrow extension is not loaded'); + } + + public function key(): ?int + { + throw new RuntimeException('arrow extension is not loaded'); + } + + public function next(): void + { + throw new RuntimeException('arrow extension is not loaded'); + } + + public function rewind(): void + { + throw new RuntimeException('arrow extension is not loaded'); + } + + public function valid(): bool + { + throw new RuntimeException('arrow extension is not loaded'); + } +} diff --git a/src/extension/arrow-ext/php/Flow/Arrow/ArrowSchema.php b/src/extension/arrow-ext/php/Flow/Arrow/RustArrowSchema.php similarity index 78% rename from src/extension/arrow-ext/php/Flow/Arrow/ArrowSchema.php rename to src/extension/arrow-ext/php/Flow/Arrow/RustArrowSchema.php index d9ccc5325b..260d5dc0ca 100644 --- a/src/extension/arrow-ext/php/Flow/Arrow/ArrowSchema.php +++ b/src/extension/arrow-ext/php/Flow/Arrow/RustArrowSchema.php @@ -13,9 +13,9 @@ } /** - * One Arrow C Data struct schema; built by Flow\Arrow\Parquet\BatchReader::schema(), never by userland. + * One Arrow C Data struct schema; built by Flow\Arrow\Parquet\RustBatchReader::schema(), never by userland. */ -final class ArrowSchema +final class RustArrowSchema { public function __construct() { diff --git a/src/extension/arrow-ext/php/Flow/Arrow/ArrowBatch.php b/src/extension/arrow-ext/php/Flow/Arrow/RustParquetBatch.php similarity index 91% rename from src/extension/arrow-ext/php/Flow/Arrow/ArrowBatch.php rename to src/extension/arrow-ext/php/Flow/Arrow/RustParquetBatch.php index c962920e78..7e4cef9760 100644 --- a/src/extension/arrow-ext/php/Flow/Arrow/ArrowBatch.php +++ b/src/extension/arrow-ext/php/Flow/Arrow/RustParquetBatch.php @@ -13,9 +13,9 @@ } /** - * One Arrow C Data struct array and its schema; built by Flow\Arrow\Parquet\BatchReader::next(), never by userland. + * One Arrow C Data struct array and its schema; built by Flow\Arrow\Parquet\RustBatchReader::next(), never by userland. */ -final class ArrowBatch +final class RustParquetBatch { public function __construct() { diff --git a/src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetEngine.php b/src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetEngine.php new file mode 100644 index 0000000000..ef3bff9c59 --- /dev/null +++ b/src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetEngine.php @@ -0,0 +1,57 @@ +> $rows + */ + public function writeRows( + DestinationStream $stream, + Schema $schema, + Compressions $compression, + Options $options, + iterable $rows, + ): void { + throw new RuntimeException('arrow extension is not loaded'); + } +} diff --git a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/ParquetFile.php b/src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetFileReader.php similarity index 54% rename from src/extension/arrow-ext/php/Flow/Arrow/Parquet/ParquetFile.php rename to src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetFileReader.php index e92f050741..7e041d8abc 100644 --- a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/ParquetFile.php +++ b/src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetFileReader.php @@ -2,11 +2,14 @@ declare(strict_types=1); -namespace Flow\Arrow\Parquet; +namespace Flow\Parquet\Engine; +use Flow\Arrow\Parquet\RustColumnsReader; use Flow\Filesystem\SourceStream; +use Flow\Parquet\ParquetFile\Metadata; +use Flow\Parquet\ParquetFile\Schema; +use Flow\Parquet\ParquetFileReader; use Flow\Parquet\ThriftModel\FileMetaData; -use Flow\Parquet\ThriftModel\SchemaElement; use RuntimeException; use function extension_loaded; @@ -15,33 +18,45 @@ return; } -final class ParquetFile +final class RustParquetFileReader implements ParquetFileReader { /** - * Reads and decodes the footer; owns the stream from here on. + * Reads and decodes the footer; owns the stream from here on. $int96AsDatetime false refuses to read an INT96 + * column, which arrow reads only as a datetime. */ - public function __construct(SourceStream $stream) + public function __construct(SourceStream $stream, bool $int96AsDatetime = true) { throw new RuntimeException('arrow extension is not loaded'); } /** - * Closes the stream; any later call throws \Flow\Parquet\Exception\RuntimeException('Parquet file is closed'). + * Closes the stream; any later call throws \Flow\Parquet\Exception\RuntimeException('Reader is not open'). */ public function close(): void { throw new RuntimeException('arrow extension is not loaded'); } - public function rowsNumber(): int + public function metadata(): Metadata { throw new RuntimeException('arrow extension is not loaded'); } /** - * @return list + * @param list $columns resolved names, never empty + * @param int<1, max> $batchSize upper bound of rows per chunk */ - public function schema(): array + public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): RustColumnsReader + { + throw new RuntimeException('arrow extension is not loaded'); + } + + public function rowsNumber(): int + { + throw new RuntimeException('arrow extension is not loaded'); + } + + public function schema(): Schema { throw new RuntimeException('arrow extension is not loaded'); } diff --git a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RowsWriter.php b/src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetFileWriter.php similarity index 75% rename from src/extension/arrow-ext/php/Flow/Arrow/Parquet/RowsWriter.php rename to src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetFileWriter.php index 9d4dcda10b..6c81f53bc3 100644 --- a/src/extension/arrow-ext/php/Flow/Arrow/Parquet/RowsWriter.php +++ b/src/extension/arrow-ext/php/Flow/Parquet/Engine/RustParquetFileWriter.php @@ -2,9 +2,11 @@ declare(strict_types=1); -namespace Flow\Arrow\Parquet; +namespace Flow\Parquet\Engine; use Flow\Filesystem\DestinationStream; +use Flow\Parquet\ParquetFile\Compressions; +use Flow\Parquet\ParquetFileWriter; use RuntimeException; use function extension_loaded; @@ -13,17 +15,19 @@ return; } -final class RowsWriter +final class RustParquetFileWriter implements ParquetFileWriter { /** * @param array $schema Flow\Parquet\Engine\Arrow\SchemaConverter::toExtension() * @param array $options Flow\Parquet\Engine\Arrow\OptionsConverter::toExtension() * @param int $batchSize rows per written batch; below 1 is refused + * + * @throws \Flow\Parquet\Exception\RuntimeException for Compressions::LZO */ public function __construct( DestinationStream $stream, array $schema, - string $compression, + Compressions $compression, array $options, int $batchSize, ) { @@ -42,7 +46,17 @@ public function close(): void * An Arrow C Data struct batch, exported by an extension: its children by writer column name, a writer column * the batch lacks is nulls, a child the writer lacks is ignored. */ - public function writeBatch(object $batch): void + public function writeArrowBatch(object $batch): void + { + throw new RuntimeException('arrow extension is not loaded'); + } + + /** + * An array as writeRows() (keys ignored), a Traversable row by row. + * + * @param iterable> $rows + */ + public function writeBatch(iterable $rows): void { throw new RuntimeException('arrow extension is not loaded'); } diff --git a/src/extension/arrow-ext/rustfmt.toml b/src/extension/arrow-ext/rustfmt.toml new file mode 100644 index 0000000000..7530651796 --- /dev/null +++ b/src/extension/arrow-ext/rustfmt.toml @@ -0,0 +1 @@ +max_width = 120 diff --git a/src/extension/arrow-ext/src/interfaces.rs b/src/extension/arrow-ext/src/interfaces.rs new file mode 100644 index 0000000000..cc8589a753 --- /dev/null +++ b/src/extension/arrow-ext/src/interfaces.rs @@ -0,0 +1,152 @@ +//! `Flow\Parquet\{ParquetEngine, ParquetFileReader, ParquetFileWriter}`: registered at MINIT with the package files' +//! exact signatures, so the extension's classes implement them and the package files (autoloaded only without arrow) +//! stay unused. + +use std::sync::atomic::{AtomicPtr, Ordering}; + +use ext_php_rs::args::{Arg, ArgInfoTables}; +use ext_php_rs::builders::{ClassBuilder, FunctionBuilder}; +use ext_php_rs::error::Result; +use ext_php_rs::flags::{ClassFlags, DataType, MethodFlags}; +use ext_php_rs::zend::ClassEntry; + +const SOURCE_STREAM: DataType = DataType::object("Flow\\Filesystem\\SourceStream"); +const DESTINATION_STREAM: DataType = DataType::object("Flow\\Filesystem\\DestinationStream"); +const SCHEMA: DataType = DataType::object("Flow\\Parquet\\ParquetFile\\Schema"); +const METADATA: DataType = DataType::object("Flow\\Parquet\\ParquetFile\\Metadata"); +const COMPRESSIONS: DataType = DataType::object("Flow\\Parquet\\ParquetFile\\Compressions"); +const OPTIONS: DataType = DataType::object("Flow\\Parquet\\Options"); +const PARQUET_FILE_READER: DataType = DataType::object("Flow\\Parquet\\ParquetFileReader"); +const PARQUET_FILE_WRITER: DataType = DataType::object("Flow\\Parquet\\ParquetFileWriter"); +const ITERATOR: DataType = DataType::object("Iterator"); + +// ClassEntry::try_find reads EG(class_table), which MINIT has not set, so each CE is kept from its registration +static PARQUET_ENGINE_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static PARQUET_FILE_READER_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static PARQUET_FILE_WRITER_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); + +fn store_parquet_engine(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + PARQUET_ENGINE_CE.store(ce, Ordering::Release); +} + +fn store_parquet_file_reader(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + PARQUET_FILE_READER_CE.store(ce, Ordering::Release); +} + +fn store_parquet_file_writer(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + PARQUET_FILE_WRITER_CE.store(ce, Ordering::Release); +} + +/// The engine borrows an interface's argument info tables for the life of the process. +pub fn keep(arg_info: ArgInfoTables) { + std::mem::forget(arg_info); +} + +fn load(ce: &AtomicPtr, name: &str) -> &'static ClassEntry { + unsafe { ce.load(Ordering::Acquire).as_ref() }.unwrap_or_else(|| panic!("{name} not registered")) +} + +pub fn parquet_engine_ce() -> &'static ClassEntry { + load(&PARQUET_ENGINE_CE, "Flow\\Parquet\\ParquetEngine") +} + +pub fn parquet_file_reader_ce() -> &'static ClassEntry { + load(&PARQUET_FILE_READER_CE, "Flow\\Parquet\\ParquetFileReader") +} + +pub fn parquet_file_writer_ce() -> &'static ClassEntry { + load(&PARQUET_FILE_WRITER_CE, "Flow\\Parquet\\ParquetFileWriter") +} + +fn method(name: &str, args: Vec>, returns: DataType) -> FunctionBuilder<'static> { + args.into_iter() + .fold(FunctionBuilder::new_abstract(name), FunctionBuilder::arg) + .returns(returns, false, false) +} + +fn interface( + name: &str, + store: fn(&'static mut ClassEntry, ArgInfoTables), + methods: Vec>, +) -> Result<()> { + methods + .into_iter() + .fold( + ClassBuilder::new(name).flags(ClassFlags::Interface).registration(store), + |class, method| class.method(method, MethodFlags::Public | MethodFlags::Abstract), + ) + .register() +} + +pub fn register() -> Result<()> { + interface( + "Flow\\Parquet\\ParquetFileReader", + store_parquet_file_reader, + vec![ + method("close", vec![], DataType::Void), + method("metadata", vec![], METADATA), + method( + "readColumns", + vec![ + Arg::new("columns", DataType::Array), + Arg::new("batchSize", DataType::Long), + Arg::new("limit", DataType::Long).allow_null(), + Arg::new("offset", DataType::Long).allow_null(), + ], + ITERATOR, + ), + method("rowsNumber", vec![], DataType::Long), + method("schema", vec![], SCHEMA), + method("totalByteSize", vec![], DataType::Long), + ], + )?; + interface( + "Flow\\Parquet\\ParquetFileWriter", + store_parquet_file_writer, + vec![ + method("close", vec![], DataType::Void), + method("writeBatch", vec![Arg::new("rows", DataType::Iterable)], DataType::Void), + method( + "writeColumns", + vec![Arg::new("columns", DataType::Array)], + DataType::Void, + ), + method("writeRow", vec![Arg::new("row", DataType::Array)], DataType::Void), + ], + )?; + interface( + "Flow\\Parquet\\ParquetEngine", + store_parquet_engine, + vec![ + method( + "openForRead", + vec![Arg::new("stream", SOURCE_STREAM)], + PARQUET_FILE_READER, + ), + method( + "openForWrite", + vec![ + Arg::new("stream", DESTINATION_STREAM), + Arg::new("schema", SCHEMA), + Arg::new("compression", COMPRESSIONS), + Arg::new("options", OPTIONS), + ], + PARQUET_FILE_WRITER, + ), + method( + "writeRows", + vec![ + Arg::new("stream", DESTINATION_STREAM), + Arg::new("schema", SCHEMA), + Arg::new("compression", COMPRESSIONS), + Arg::new("options", OPTIONS), + Arg::new("rows", DataType::Iterable), + ], + DataType::Void, + ), + ], + ) +} diff --git a/src/extension/arrow-ext/src/lib.rs b/src/extension/arrow-ext/src/lib.rs index 8a470ff866..94d0be3c15 100644 --- a/src/extension/arrow-ext/src/lib.rs +++ b/src/extension/arrow-ext/src/lib.rs @@ -1,6 +1,7 @@ #[cfg(test)] mod alloc; mod exception; +mod interfaces; mod parquet; mod php; mod render; @@ -33,6 +34,10 @@ pub extern "C" fn php_module_info(_module: *mut ModuleEntry) { /// Invoked by the PHP/Zend engine during module startup. Must only be called by /// the engine through the registered startup hook, never directly. pub unsafe extern "C" fn module_startup(_type: i32, _module_number: i32) -> i32 { + if let Err(e) = interfaces::register() { + eprintln!("arrow: failed to register the Flow\\Parquet interfaces: {e}"); + return -1; + } if let Err(e) = stream::output_stream::register() { eprintln!("arrow: failed to register Flow\\Arrow\\OutputStream: {e}"); return -1; @@ -53,10 +58,11 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { .globals(&php::GLOBALS) .request_startup_function(php::request_startup) .request_shutdown_function(php::request_shutdown) - .class::() - .class::() - .class::() - .class::() - .class::() - .class::() + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() } diff --git a/src/extension/arrow-ext/src/parquet/batch.rs b/src/extension/arrow-ext/src/parquet/batch.rs index 03caf43d65..60d5fde10f 100644 --- a/src/extension/arrow-ext/src/parquet/batch.rs +++ b/src/extension/arrow-ext/src/parquet/batch.rs @@ -1,4 +1,4 @@ -//! `Flow\Arrow\Parquet\BatchReader` and the Arrow C Data carriers: one batch = one struct-typed `FFI_ArrowSchema` (one +//! `Flow\Arrow\Parquet\RustBatchReader` and the Arrow C Data carriers: one batch = one struct-typed `FFI_ArrowSchema` (one //! child per column) plus one struct-typed `FFI_ArrowArray`. The carrier owns both until a consumer moves the array //! out; any extension's internal class exposing the two addresses is accepted. @@ -15,7 +15,7 @@ use ext_php_rs::types::{ZendObject, Zval}; use ext_php_rs::zend::ClassEntry; use crate::parquet::error::Error; -use crate::parquet::library::{batch_size, rows, ParquetFile, INVALID_ARGUMENT}; +use crate::parquet::library::{batch_size, rows, RustParquetFileReader, INVALID_ARGUMENT}; use crate::parquet::read::{ParquetReader, ReadPlan}; use crate::parquet::source::PhpStream; use crate::php::{call_handle_transparent, ce_method_ref}; @@ -29,15 +29,15 @@ pub const SOURCE_TYPE: &str = "parquet.source_type"; const ZEND_INTERNAL_CLASS: c_char = 1; #[php_class] -#[php(name = "Flow\\Arrow\\ArrowBatch", flags = ClassFlags::Final)] -pub struct ArrowBatch { +#[php(name = "Flow\\Arrow\\RustParquetBatch", flags = ClassFlags::Final)] +pub struct RustParquetBatch { schema: FFI_ArrowSchema, array: FFI_ArrowArray, rows: usize, } #[php_impl] -impl ArrowBatch { +impl RustParquetBatch { pub fn count(&self) -> i64 { self.rows as i64 } @@ -54,13 +54,13 @@ impl ArrowBatch { } #[php_class] -#[php(name = "Flow\\Arrow\\ArrowSchema", flags = ClassFlags::Final)] -pub struct ArrowSchema { +#[php(name = "Flow\\Arrow\\RustArrowSchema", flags = ClassFlags::Final)] +pub struct RustArrowSchema { schema: FFI_ArrowSchema, } #[php_impl] -impl ArrowSchema { +impl RustArrowSchema { #[php(name = "arrowSchemaAddress")] pub fn arrow_schema_address(&self) -> i64 { std::ptr::from_ref(&self.schema) as i64 @@ -68,8 +68,8 @@ impl ArrowSchema { } #[php_class] -#[php(name = "Flow\\Arrow\\Parquet\\BatchReader", flags = ClassFlags::Final)] -pub struct BatchReader { +#[php(name = "Flow\\Arrow\\Parquet\\RustBatchReader", flags = ClassFlags::Final)] +pub struct RustBatchReader { reader: Option, stream: Arc, /// The projection: canonical children named by column, each with its `SOURCE_TYPE`. @@ -77,10 +77,10 @@ pub struct BatchReader { } #[php_impl] -impl BatchReader { +impl RustBatchReader { /// `$columns`: root names; `$batchSize` rows at most per `next()`. pub fn __construct( - file: &ParquetFile, + file: &RustParquetFileReader, columns: Vec, batch_size: i64, offset: Option, @@ -90,16 +90,24 @@ impl BatchReader { let (offset, limit) = (rows(offset, "offset")?.unwrap_or(0), rows(limit, "limit")?); let (stream, size, meta) = file.read()?; let stream = Arc::clone(stream); - let reader = - ParquetReader::open(Arc::clone(&stream), size, meta, &columns, ReadPlan::new(meta, offset, limit), batch_size) - .map_err(|error| parquet_exception(error, &stream, Side::Read))?; + let reader = ParquetReader::open( + Arc::clone(&stream), + size, + meta, + &columns, + ReadPlan::new(meta, offset, limit), + batch_size, + ) + .map_err(|error| parquet_exception(error, &stream, Side::Read))?; let fields = columns .iter() .zip(reader.fields()) .zip(reader.types()) .map(|((name, field), canonical)| { - Field::new(name, canonical.clone(), true) - .with_metadata(HashMap::from([(SOURCE_TYPE.to_string(), field.data_type().to_string())])) + Field::new(name, canonical.clone(), true).with_metadata(HashMap::from([( + SOURCE_TYPE.to_string(), + field.data_type().to_string(), + )])) }) .collect(); @@ -111,15 +119,15 @@ impl BatchReader { } /// The struct schema of every batch, known before the first. - pub fn schema(&self) -> PhpResult { - Ok(ArrowSchema { + pub fn schema(&self) -> PhpResult { + Ok(RustArrowSchema { schema: FFI_ArrowSchema::try_from(&DataType::Struct(self.fields.clone())) .map_err(|error| parquet_exception(Error::Arrow(error), &self.stream, Side::Read))?, }) } /// At most `$batchSize` rows as one struct batch, null after the last. - pub fn next(&mut self) -> PhpResult> { + pub fn next(&mut self) -> PhpResult> { let Some(reader) = self.reader.as_mut() else { return Ok(None); }; @@ -137,7 +145,7 @@ impl BatchReader { .and_then(|array| to_ffi(&array.to_data())) .map_err(|error| parquet_exception(Error::Arrow(error), &self.stream, Side::Read))?; - Ok(Some(ArrowBatch { + Ok(Some(RustParquetBatch { array: exported.0, schema: exported.1, rows, @@ -168,7 +176,9 @@ fn address(object: &ZendObject, ce: &ClassEntry, method: &str) -> PhpResult PhpResult { - let object = batch.object().ok_or_else(|| refused("Arrow C Data batch must be an object".to_string()))?; + let object = batch + .object() + .ok_or_else(|| refused("Arrow C Data batch must be an object".to_string()))?; let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| refused("Arrow C Data batch has no class".to_string()))?; if ce.type_ != ZEND_INTERNAL_CLASS { @@ -211,8 +221,8 @@ mod tests { use std::sync::Arc; use arrow_array::ffi::{from_ffi, to_ffi}; - use arrow_array::{Array, ArrayRef, Int64Array, ListArray, StructArray}; use arrow_array::types::Int64Type; + use arrow_array::{Array, ArrayRef, Int64Array, ListArray, StructArray}; use arrow_schema::{DataType, Field, Fields}; use crate::alloc::allocated_bytes; diff --git a/src/extension/arrow-ext/src/parquet/canonical.rs b/src/extension/arrow-ext/src/parquet/canonical.rs index d619935bfd..45ddb218c9 100644 --- a/src/extension/arrow-ext/src/parquet/canonical.rs +++ b/src/extension/arrow-ext/src/parquet/canonical.rs @@ -40,7 +40,10 @@ fn item(data_type: DataType) -> FieldRef { fn entries(key: DataType, value: DataType) -> FieldRef { Arc::new(Field::new( "entries", - DataType::Struct(Fields::from(vec![Field::new("key", key, false), Field::new("value", value, true)])), + DataType::Struct(Fields::from(vec![ + Field::new("key", key, false), + Field::new("value", value, true), + ])), false, )) } @@ -83,7 +86,10 @@ fn canonical_data_type(data_type: &DataType) -> Result { let (key, value) = map_fields(field)?; DataType::Map( - entries(canonical_data_type(key.data_type())?, canonical_data_type(value.data_type())?), + entries( + canonical_data_type(key.data_type())?, + canonical_data_type(value.data_type())?, + ), false, ) } @@ -144,8 +150,13 @@ fn retagged(array: &ArrayRef, to: DataType) -> ArrayRef { make_array(unsafe { array.to_data().into_builder().data_type(to).build_unchecked() }) } -fn micros>(array: &ArrayRef, f: impl Fn(i64) -> Option) -> Result { - Ok(Arc::new(checked::(array, f)?.with_timezone(UTC))) +fn micros>( + array: &ArrayRef, + f: impl Fn(i64) -> Option, +) -> Result { + Ok(Arc::new( + checked::(array, f)?.with_timezone(UTC), + )) } fn decimals(array: &ArrayRef, precision: u8, scale: i8) -> Result { @@ -162,7 +173,10 @@ fn decimals(array: &ArrayRef, precision: u8, scale: i8) -> Resul }); } - Ok(Arc::new(Float64Array::new(ScalarBuffer::from(values), input.nulls().cloned()))) + Ok(Arc::new(Float64Array::new( + ScalarBuffer::from(values), + input.nulls().cloned(), + ))) } /// Large offsets narrowed to i32 and rebased to 0, with the values they span. @@ -236,7 +250,9 @@ fn cast(array: &ArrayRef) -> Result { DataType::UInt8 => widened::(array), DataType::UInt16 => widened::(array), DataType::UInt32 => widened::(array), - DataType::UInt64 => Arc::new(checked::(array, |value| i64::try_from(value).ok())?), + DataType::UInt64 => Arc::new(checked::(array, |value| { + i64::try_from(value).ok() + })?), DataType::Float32 => Arc::new(array.as_primitive::().unary::<_, Float64Type>(f64::from)), DataType::Utf8 | DataType::Binary => retagged(array, DataType::Binary), DataType::LargeUtf8 | DataType::LargeBinary => large_binary(array)?, @@ -245,9 +261,7 @@ fn cast(array: &ArrayRef) -> Result { DataType::Timestamp(TimeUnit::Millisecond, _) => { micros::(array, |ms| ms.checked_mul(1_000))? } - DataType::Timestamp(TimeUnit::Second, _) => { - micros::(array, |s| s.checked_mul(1_000_000))? - } + DataType::Timestamp(TimeUnit::Second, _) => micros::(array, |s| s.checked_mul(1_000_000))?, DataType::Timestamp(TimeUnit::Nanosecond, _) => { micros::(array, |ns| Some(ns.div_euclid(1_000)))? } @@ -267,10 +281,9 @@ fn cast(array: &ArrayRef) -> Result { .as_primitive::() .unary::<_, DurationMicrosecondType>(|s| i64::from(s) * 1_000_000), ), - DataType::Date64 => Arc::new(checked::( - array, - |ms| i32::try_from(ms.div_euclid(86_400_000)).ok(), - )?), + DataType::Date64 => Arc::new(checked::(array, |ms| { + i32::try_from(ms.div_euclid(86_400_000)).ok() + })?), DataType::Decimal128(precision, scale) => decimals::(array, *precision, *scale)?, DataType::Decimal256(precision, scale) => decimals::(array, *precision, *scale)?, DataType::List(_) => { @@ -353,9 +366,11 @@ pub fn to_parquet(array: &ArrayRef, target: &DataType) -> Result Arc::new(narrowed_int::(array)?), (DataType::Int64, DataType::UInt32) => Arc::new(narrowed_int::(array)?), (DataType::Int64, DataType::UInt64) => Arc::new(narrowed_int::(array)?), - (DataType::Float64, DataType::Float32) => { - Arc::new(array.as_primitive::().unary::<_, Float32Type>(|value| value as f32)) - } + (DataType::Float64, DataType::Float32) => Arc::new( + array + .as_primitive::() + .unary::<_, Float32Type>(|value| value as f32), + ), (DataType::Float64, DataType::Decimal128(precision, scale)) => Arc::new( checked_values::(array, |value| decimal_unscaled(value, *precision, *scale))? .with_precision_and_scale(*precision, *scale)?, @@ -364,14 +379,17 @@ pub fn to_parquet(array: &ArrayRef, target: &DataType) -> Result { retagged(array, target.clone()) } - (DataType::Duration(TimeUnit::Microsecond), DataType::Time32(TimeUnit::Millisecond)) => Arc::new( - checked::(array, |us| { - i32::try_from(us.div_euclid(1_000)).ok() - })?, - ), - (DataType::Duration(TimeUnit::Microsecond), DataType::Time64(TimeUnit::Nanosecond)) => Arc::new( - checked::(array, |us| us.checked_mul(1_000))?, - ), + (DataType::Duration(TimeUnit::Microsecond), DataType::Time32(TimeUnit::Millisecond)) => { + Arc::new(checked::( + array, + |us| i32::try_from(us.div_euclid(1_000)).ok(), + )?) + } + (DataType::Duration(TimeUnit::Microsecond), DataType::Time64(TimeUnit::Nanosecond)) => { + Arc::new(checked::(array, |us| { + us.checked_mul(1_000) + })?) + } (DataType::Timestamp(TimeUnit::Microsecond, Some(zone)), DataType::Timestamp(TimeUnit::Millisecond, to)) if zone.as_ref() == UTC => { @@ -509,7 +527,11 @@ fn decimal_unscaled(value: f64, precision: u8, scale: i8) -> Result return Err(overflow()); } - let mut unscaled = if digits.is_empty() { 0 } else { digits.parse::().map_err(|_| overflow())? }; + let mut unscaled = if digits.is_empty() { + 0 + } else { + digits.parse::().map_err(|_| overflow())? + }; if round_up { unscaled += 1; @@ -546,7 +568,11 @@ fn fixed_size(array: &ArrayRef, size: i32) -> Result { values[row * width..(row + 1) * width].copy_from_slice(value); } - Ok(Arc::new(FixedSizeBinaryArray::new(size, values.into(), binary.nulls().cloned()))) + Ok(Arc::new(FixedSizeBinaryArray::new( + size, + values.into(), + binary.nulls().cloned(), + ))) } /// Binary as Utf8 over the same buffers once every value is valid UTF-8; else the first row that is not. @@ -618,7 +644,10 @@ mod tests { DataType::Map( Arc::new(Field::new( "entries", - DataType::Struct(Fields::from(vec![Field::new("key", key, false), Field::new("value", value, true)])), + DataType::Struct(Fields::from(vec![ + Field::new("key", key, false), + Field::new("value", value, true), + ])), false, )), false, @@ -645,11 +674,26 @@ mod tests { fn integers_widen_to_int64() { let expected = vec![Some(-3), None, Some(7)]; - assert_eq!(int64(&read(Arc::new(Int8Array::from(vec![Some(-3), None, Some(7)])))), expected); - assert_eq!(int64(&read(Arc::new(Int16Array::from(vec![Some(-3), None, Some(7)])))), expected); - assert_eq!(int64(&read(Arc::new(Int32Array::from(vec![Some(-3), None, Some(7)])))), expected); - assert_eq!(int64(&read(Arc::new(UInt8Array::from(vec![Some(255), None])))), vec![Some(255), None]); - assert_eq!(int64(&read(Arc::new(UInt16Array::from(vec![Some(65_535), None])))), vec![Some(65_535), None]); + assert_eq!( + int64(&read(Arc::new(Int8Array::from(vec![Some(-3), None, Some(7)])))), + expected + ); + assert_eq!( + int64(&read(Arc::new(Int16Array::from(vec![Some(-3), None, Some(7)])))), + expected + ); + assert_eq!( + int64(&read(Arc::new(Int32Array::from(vec![Some(-3), None, Some(7)])))), + expected + ); + assert_eq!( + int64(&read(Arc::new(UInt8Array::from(vec![Some(255), None])))), + vec![Some(255), None] + ); + assert_eq!( + int64(&read(Arc::new(UInt16Array::from(vec![Some(65_535), None])))), + vec![Some(65_535), None] + ); assert_eq!( int64(&read(Arc::new(UInt32Array::from(vec![Some(u32::MAX), None])))), vec![Some(i64::from(u32::MAX)), None] @@ -662,7 +706,11 @@ mod tests { #[test] fn uint64_above_int64_is_refused_at_its_row() { - let error = refusal(Arc::new(UInt64Array::from(vec![Some(1), None, Some(i64::MAX as u64 + 1)]))); + let error = refusal(Arc::new(UInt64Array::from(vec![ + Some(1), + None, + Some(i64::MAX as u64 + 1), + ]))); assert!(matches!(error, Error::Overflow { column, row: 2 } if column == "column")); } @@ -678,7 +726,10 @@ mod tests { fn float32_widens_to_float64() { let canonical = read(Arc::new(Float32Array::from(vec![Some(0.5), None]))); - assert_eq!(canonical.as_primitive::().iter().collect::>(), vec![Some(0.5), None]); + assert_eq!( + canonical.as_primitive::().iter().collect::>(), + vec![Some(0.5), None] + ); } #[test] @@ -713,15 +764,30 @@ mod tests { read(array).as_primitive::().iter().collect() }; - assert_eq!(micros(Arc::new(TimestampMicrosecondArray::from(vec![Some(-7), None]))), vec![Some(-7), None]); assert_eq!( - micros(Arc::new(TimestampMicrosecondArray::from(vec![Some(5)]).with_timezone("Europe/Warsaw"))), + micros(Arc::new(TimestampMicrosecondArray::from(vec![Some(-7), None]))), + vec![Some(-7), None] + ); + assert_eq!( + micros(Arc::new( + TimestampMicrosecondArray::from(vec![Some(5)]).with_timezone("Europe/Warsaw") + )), vec![Some(5)] ); - assert_eq!(micros(Arc::new(TimestampMillisecondArray::from(vec![Some(-2), None]))), vec![Some(-2_000), None]); - assert_eq!(micros(Arc::new(TimestampSecondArray::from(vec![Some(3)]))), vec![Some(3_000_000)]); assert_eq!( - micros(Arc::new(TimestampNanosecondArray::from(vec![Some(-1_500), Some(1_999), None]))), + micros(Arc::new(TimestampMillisecondArray::from(vec![Some(-2), None]))), + vec![Some(-2_000), None] + ); + assert_eq!( + micros(Arc::new(TimestampSecondArray::from(vec![Some(3)]))), + vec![Some(3_000_000)] + ); + assert_eq!( + micros(Arc::new(TimestampNanosecondArray::from(vec![ + Some(-1_500), + Some(1_999), + None + ]))), vec![Some(-2), Some(1), None] ); } @@ -743,47 +809,77 @@ mod tests { read(array).as_primitive::().iter().collect() }; - assert_eq!(micros(Arc::new(Time64MicrosecondArray::from(vec![Some(5), None]))), vec![Some(5), None]); - assert_eq!(micros(Arc::new(Time64NanosecondArray::from(vec![Some(1_999), None]))), vec![Some(1), None]); - assert_eq!(micros(Arc::new(Time32MillisecondArray::from(vec![Some(2), None]))), vec![Some(2_000), None]); - assert_eq!(micros(Arc::new(Time32SecondArray::from(vec![Some(3)]))), vec![Some(3_000_000)]); + assert_eq!( + micros(Arc::new(Time64MicrosecondArray::from(vec![Some(5), None]))), + vec![Some(5), None] + ); + assert_eq!( + micros(Arc::new(Time64NanosecondArray::from(vec![Some(1_999), None]))), + vec![Some(1), None] + ); + assert_eq!( + micros(Arc::new(Time32MillisecondArray::from(vec![Some(2), None]))), + vec![Some(2_000), None] + ); + assert_eq!( + micros(Arc::new(Time32SecondArray::from(vec![Some(3)]))), + vec![Some(3_000_000)] + ); } #[test] fn date64_floors_to_days() { let days = read(Arc::new(Date64Array::from(vec![Some(-1), Some(86_400_000), None]))); - assert_eq!(days.as_primitive::().iter().collect::>(), vec![Some(-1), Some(1), None]); - assert!(matches!(refusal(Arc::new(Date64Array::from(vec![Some(i64::MAX)]))), Error::Overflow { row: 0, .. })); + assert_eq!( + days.as_primitive::().iter().collect::>(), + vec![Some(-1), Some(1), None] + ); + assert!(matches!( + refusal(Arc::new(Date64Array::from(vec![Some(i64::MAX)]))), + Error::Overflow { row: 0, .. } + )); } #[test] fn decimals_are_floats_through_their_decimal_text() { - let decimal128 = Decimal128Array::from(vec![Some(12_345), Some(-5), None]).with_precision_and_scale(9, 2).unwrap(); + let decimal128 = Decimal128Array::from(vec![Some(12_345), Some(-5), None]) + .with_precision_and_scale(9, 2) + .unwrap(); let decimal256 = Decimal256Array::from(vec![Some(i256::from_i128(10_000_000_001)), None]) .with_precision_and_scale(50, 10) .unwrap(); assert_eq!( - read(Arc::new(decimal128)).as_primitive::().iter().collect::>(), + read(Arc::new(decimal128)) + .as_primitive::() + .iter() + .collect::>(), vec![Some(123.45), Some(-0.05), None] ); assert_eq!( - read(Arc::new(decimal256)).as_primitive::().iter().collect::>(), + read(Arc::new(decimal256)) + .as_primitive::() + .iter() + .collect::>(), vec![Some(1.0000000001), None] ); } #[test] fn lists_are_renamed_to_the_kind_layout() { - let mut builder = ListBuilder::new(Int32Builder::new()).with_field(Field::new("element", DataType::Int32, false)); + let mut builder = + ListBuilder::new(Int32Builder::new()).with_field(Field::new("element", DataType::Int32, false)); builder.append_value([Some(1), Some(2)]); builder.append_null(); builder.append_value([Some(3)]); let canonical = read(Arc::new(builder.finish())); assert_eq!(canonical.data_type(), &list_of(DataType::Int64)); - assert_eq!(int64(canonical.as_list::().values()), vec![Some(1), Some(2), Some(3)]); + assert_eq!( + int64(canonical.as_list::().values()), + vec![Some(1), Some(2), Some(3)] + ); assert!(canonical.is_null(1)); } @@ -812,10 +908,7 @@ mod tests { builder.append(false).unwrap(); let canonical = read(Arc::new(builder.finish())); - assert_eq!( - canonical.data_type(), - &map_of(DataType::Binary, DataType::Int64) - ); + assert_eq!(canonical.data_type(), &map_of(DataType::Binary, DataType::Int64)); assert_eq!(int64(canonical.as_map().values()), vec![Some(1)]); assert!(canonical.is_null(1)); } @@ -823,7 +916,10 @@ mod tests { #[test] fn structs_are_relabelled_nullable() { let array = StructArray::from(vec![ - (Arc::new(Field::new("id", DataType::Int32, false)), Arc::new(Int32Array::from(vec![1, 2])) as ArrayRef), + ( + Arc::new(Field::new("id", DataType::Int32, false)), + Arc::new(Int32Array::from(vec![1, 2])) as ArrayRef, + ), ( Arc::new(Field::new("name", DataType::Utf8, false)), Arc::new(StringArray::from(vec!["a", "b"])) as ArrayRef, @@ -871,7 +967,11 @@ mod tests { #[test] fn unsupported_types_are_refused_naming_the_type() { let interval = DataType::Interval(arrow_schema::IntervalUnit::DayTime); - let field = Field::new("intervals", DataType::List(Arc::new(Field::new("element", interval, true))), true); + let field = Field::new( + "intervals", + DataType::List(Arc::new(Field::new("element", interval, true))), + true, + ); assert!(matches!( canonical_type(&field), @@ -904,18 +1004,32 @@ mod tests { let array: ArrayRef = Arc::new(Int64Array::from(vec![Some(-128), None, Some(127)])); assert_eq!( - to_parquet(&array, &DataType::Int8).unwrap().as_primitive::().iter().collect::>(), + to_parquet(&array, &DataType::Int8) + .unwrap() + .as_primitive::() + .iter() + .collect::>(), vec![Some(-128), None, Some(127)] ); let unsigned: ArrayRef = Arc::new(Int64Array::from(vec![Some(4_000_000_000), Some(i64::MAX)])); assert_eq!( - to_parquet(&unsigned, &DataType::UInt64).unwrap().as_primitive::().values().to_vec(), + to_parquet(&unsigned, &DataType::UInt64) + .unwrap() + .as_primitive::() + .values() + .to_vec(), vec![4_000_000_000, i64::MAX as u64] ); - for target in [DataType::Int16, DataType::Int32, DataType::UInt8, DataType::UInt16, DataType::UInt32] { + for target in [ + DataType::Int16, + DataType::Int32, + DataType::UInt8, + DataType::UInt16, + DataType::UInt32, + ] { assert_eq!(to_parquet(&array.slice(1, 1), &target).unwrap().data_type(), &target); } } @@ -935,7 +1049,10 @@ mod tests { for (target, values) in cases { let array: ArrayRef = Arc::new(Int64Array::from(values)); - assert!(matches!(to_parquet(&array, &target), Err(Error::Overflow { row: 1, .. })), "{target}"); + assert!( + matches!(to_parquet(&array, &target), Err(Error::Overflow { row: 1, .. })), + "{target}" + ); } } @@ -944,7 +1061,11 @@ mod tests { let array: ArrayRef = Arc::new(Float64Array::from(vec![Some(0.5), None])); assert_eq!( - to_parquet(&array, &DataType::Float32).unwrap().as_primitive::().iter().collect::>(), + to_parquet(&array, &DataType::Float32) + .unwrap() + .as_primitive::() + .iter() + .collect::>(), vec![Some(0.5), None] ); } @@ -959,27 +1080,63 @@ mod tests { #[test] fn to_parquet_writes_decimals_from_the_shortest_digits_half_away_from_zero() { assert_eq!( - unscaled(vec![Some(123.45), Some(-0.125), Some(0.125), Some(0.1249), None, Some(-0.001)], 9, 2).unwrap(), + unscaled( + vec![ + Some(123.45), + Some(-0.125), + Some(0.125), + Some(0.1249), + None, + Some(-0.001) + ], + 9, + 2 + ) + .unwrap(), vec![Some(12_345), Some(-13), Some(13), Some(12), None, Some(0)] ); assert_eq!(unscaled(vec![Some(1e20)], 38, 2).unwrap(), vec![Some(10i128.pow(22))]); - assert_eq!(unscaled(vec![Some(0.1 + 0.2)], 20, 17).unwrap(), vec![Some(30_000_000_000_000_004)]); + assert_eq!( + unscaled(vec![Some(0.1 + 0.2)], 20, 17).unwrap(), + vec![Some(30_000_000_000_000_004)] + ); assert_eq!(unscaled(vec![Some(-5.0)], 1, -1).unwrap(), vec![Some(-5)]); } #[test] fn to_parquet_rounds_decimals_of_binary_fractions_half_away_from_zero() { assert_eq!( - unscaled(vec![Some(0.125), Some(2.675), Some(-0.125), Some(1.005), Some(9.995), Some(-99.995)], 9, 2).unwrap(), + unscaled( + vec![ + Some(0.125), + Some(2.675), + Some(-0.125), + Some(1.005), + Some(9.995), + Some(-99.995) + ], + 9, + 2 + ) + .unwrap(), vec![Some(13), Some(268), Some(-13), Some(101), Some(1_000), Some(-10_000)] ); } #[test] fn to_parquet_refuses_decimals_beyond_their_precision() { - assert!(matches!(unscaled(vec![Some(1.0), Some(100.0)], 4, 2), Err(Error::Overflow { row: 1, .. }))); - assert!(matches!(unscaled(vec![Some(99.995)], 4, 2), Err(Error::Overflow { row: 0, .. }))); - assert!(matches!(unscaled(vec![Some(1e300)], 38, 0), Err(Error::Overflow { row: 0, .. }))); + assert!(matches!( + unscaled(vec![Some(1.0), Some(100.0)], 4, 2), + Err(Error::Overflow { row: 1, .. }) + )); + assert!(matches!( + unscaled(vec![Some(99.995)], 4, 2), + Err(Error::Overflow { row: 0, .. }) + )); + assert!(matches!( + unscaled(vec![Some(1e300)], 38, 0), + Err(Error::Overflow { row: 0, .. }) + )); } #[test] @@ -1003,7 +1160,11 @@ mod tests { ); assert!(matches!( to_parquet(&array, &DataType::FixedSizeBinary(16)), - Err(Error::Length { row: 0, expected: 16, .. }) + Err(Error::Length { + row: 0, + expected: 16, + .. + }) )); } @@ -1045,16 +1206,29 @@ mod tests { let timestamp: ArrayRef = Arc::new(TimestampMicrosecondArray::from(vec![Some(1_999), Some(-1), None]).with_timezone("UTC")); let millis = to_parquet(×tamp, &DataType::Timestamp(TimeUnit::Millisecond, None)).unwrap(); - let nanos = to_parquet(×tamp, &DataType::Timestamp(TimeUnit::Nanosecond, Some("UTC".into()))).unwrap(); + let nanos = to_parquet( + ×tamp, + &DataType::Timestamp(TimeUnit::Nanosecond, Some("UTC".into())), + ) + .unwrap(); assert_eq!(millis.data_type(), &DataType::Timestamp(TimeUnit::Millisecond, None)); assert_eq!( - millis.as_primitive::().iter().collect::>(), + millis + .as_primitive::() + .iter() + .collect::>(), vec![Some(1), Some(-1), None] ); - assert_eq!(nanos.data_type(), &DataType::Timestamp(TimeUnit::Nanosecond, Some("UTC".into()))); assert_eq!( - nanos.as_primitive::().iter().collect::>(), + nanos.data_type(), + &DataType::Timestamp(TimeUnit::Nanosecond, Some("UTC".into())) + ); + assert_eq!( + nanos + .as_primitive::() + .iter() + .collect::>(), vec![Some(1_999_000), Some(-1_000), None] ); @@ -1087,7 +1261,9 @@ mod tests { vec![Some(5), None] ); assert_eq!( - to_parquet(×tamp, &DataType::Timestamp(TimeUnit::Microsecond, None)).unwrap().data_type(), + to_parquet(×tamp, &DataType::Timestamp(TimeUnit::Microsecond, None)) + .unwrap() + .data_type(), &DataType::Timestamp(TimeUnit::Microsecond, None) ); } @@ -1097,7 +1273,11 @@ mod tests { let binary: ArrayRef = Arc::new(BinaryArray::from(vec![Some(&b"zazolc"[..]), None])); assert_eq!( - to_parquet(&binary, &DataType::Utf8).unwrap().as_string::().iter().collect::>(), + to_parquet(&binary, &DataType::Utf8) + .unwrap() + .as_string::() + .iter() + .collect::>(), vec![Some("zazolc"), None] ); } @@ -1106,7 +1286,10 @@ mod tests { fn to_parquet_refuses_invalid_utf8_at_its_row() { let binary: ArrayRef = Arc::new(BinaryArray::from(vec![Some(&b"ok"[..]), None, Some(&b"\xff\xfe"[..])])); - assert!(matches!(to_parquet(&binary, &DataType::Utf8), Err(Error::InvalidUtf8 { row: 2, .. }))); + assert!(matches!( + to_parquet(&binary, &DataType::Utf8), + Err(Error::InvalidUtf8 { row: 2, .. }) + )); } #[test] @@ -1119,7 +1302,10 @@ mod tests { )); let target = DataType::List(Arc::new(Field::new("element", DataType::Utf8, true))); - assert!(matches!(to_parquet(&list, &target), Err(Error::InvalidUtf8 { row: 1, .. }))); + assert!(matches!( + to_parquet(&list, &target), + Err(Error::InvalidUtf8 { row: 1, .. }) + )); } #[test] diff --git a/src/extension/arrow-ext/src/parquet/cells.rs b/src/extension/arrow-ext/src/parquet/cells.rs index 36ab5408f8..34426e151c 100644 --- a/src/extension/arrow-ext/src/parquet/cells.rs +++ b/src/extension/arrow-ext/src/parquet/cells.rs @@ -20,8 +20,8 @@ use ext_php_rs::zend::{ClassEntry, Function}; use crate::exception::ext_exception; use crate::parquet::error::Error; use crate::php::{ - call_handle_transparent, ce_method_ref, find_class, ht_for_each, ht_get, ht_insert, ht_insert_long, - read_property, zval_long, zval_str, + call_handle_transparent, ce_method_ref, find_class, ht_for_each, ht_get, ht_insert, ht_insert_long, read_property, + zval_long, zval_str, }; use crate::values::{date_from_days, datetime_days, datetime_from_micros, datetime_micros, uuid_bytes, uuid_text}; @@ -99,7 +99,10 @@ impl ReadCell { .iter() .enumerate() .map(|(index, field)| { - Ok((field.name().as_bytes().to_vec(), Self::new(field.data_type(), child(parquet, index)?)?)) + Ok(( + field.name().as_bytes().to_vec(), + Self::new(field.data_type(), child(parquet, index)?)?, + )) }) .collect::>()?, ), @@ -179,7 +182,9 @@ impl ReadCell { let mut values = ZendHashTable::with_capacity((offsets[row + 1] - offsets[row]) as u32); for index in offsets[row] as usize..offsets[row + 1] as usize { - values.push(element.value(list.values().as_ref(), index, times)?).map_err(collected)?; + values + .push(element.value(list.values().as_ref(), index, times)?) + .map_err(collected)?; } zv.set_hashtable(values); @@ -258,7 +263,10 @@ impl Times { return self.time_of_day(micros); } - let base = self.base.object().ok_or_else(|| ext_exception("arrow expected a TIME base datetime"))?; + let base = self + .base + .object() + .ok_or_else(|| ext_exception("arrow expected a TIME base datetime"))?; let target = call_handle_transparent( self.modify, Some(base), @@ -290,7 +298,11 @@ impl Times { // __set_state() stores `f` as (int) (f * 1e6): the half microsecond keeps the truncation on the exact value // (0.519488 * 1e6 = 519487.99…), and `f` reads back as that value / 1e6, as diff()'s does - ht_insert(&mut state, b"f", double(((micros % 1_000_000) as f64 + 0.5) / 1_000_000.0)); + ht_insert( + &mut state, + b"f", + double(((micros % 1_000_000) as f64 + 0.5) / 1_000_000.0), + ); ht_insert(&mut state, b"invert", zval_long(0)); ht_insert(&mut state, b"days", zval_long(0)); let mut from_string = Zval::new(); @@ -304,7 +316,6 @@ impl Times { } } - /// A value `WriteCell::check` refuses. pub enum Refusal { /// What the target type accepts and what it got. @@ -437,7 +448,9 @@ impl<'a> Checked<'a> for Scalar<'a> { fn fits(&self, _: &WriteCell, builder: &mut ColumnBuilder) -> bool { match (self, builder) { - (Scalar::Bytes(bytes), ColumnBuilder::Bytes(builder)) => offsets_fit(builder.values_slice().len(), bytes.len()), + (Scalar::Bytes(bytes), ColumnBuilder::Bytes(builder)) => { + offsets_fit(builder.values_slice().len(), bytes.len()) + } _ => true, } } @@ -502,8 +515,13 @@ impl StructColumnBuilder { let children = self.children.iter().map(ArrayBuilder::finish_cloned).collect(); Arc::new( - StructArray::try_new_with_length(self.fields.clone(), children, self.nulls.finish_cloned(), self.nulls.len()) - .expect("every child appends a slot per struct slot"), + StructArray::try_new_with_length( + self.fields.clone(), + children, + self.nulls.finish_cloned(), + self.nulls.len(), + ) + .expect("every child appends a slot per struct slot"), ) } } @@ -516,14 +534,17 @@ impl ColumnBuilder { DataType::Int64 => ColumnBuilder::Int(Int64Builder::with_capacity(capacity)), DataType::Float64 => ColumnBuilder::Float(Float64Builder::with_capacity(capacity)), DataType::Binary => ColumnBuilder::Bytes(BinaryBuilder::with_capacity(capacity, 1024)), - DataType::FixedSizeBinary(size) => ColumnBuilder::Uuid(FixedSizeBinaryBuilder::with_capacity(capacity, *size)), + DataType::FixedSizeBinary(size) => { + ColumnBuilder::Uuid(FixedSizeBinaryBuilder::with_capacity(capacity, *size)) + } DataType::Date32 => ColumnBuilder::Date(Date32Builder::with_capacity(capacity)), DataType::Timestamp(_, _) => ColumnBuilder::Timestamp( TimestampMicrosecondBuilder::with_capacity(capacity).with_data_type(canonical.clone()), ), DataType::Duration(_) => ColumnBuilder::Time(DurationMicrosecondBuilder::with_capacity(capacity)), DataType::List(element) => ColumnBuilder::List(Box::new( - ListBuilder::with_capacity(Self::new(element.data_type(), capacity), capacity).with_field(Arc::clone(element)), + ListBuilder::with_capacity(Self::new(element.data_type(), capacity), capacity) + .with_field(Arc::clone(element)), )), DataType::Map(entries, _) => { let DataType::Struct(fields) = entries.data_type() else { @@ -547,7 +568,10 @@ impl ColumnBuilder { } DataType::Struct(fields) => ColumnBuilder::Struct(Box::new(StructColumnBuilder { fields: fields.clone(), - children: fields.iter().map(|field| Self::new(field.data_type(), capacity)).collect(), + children: fields + .iter() + .map(|field| Self::new(field.data_type(), capacity)) + .collect(), nulls: NullBufferBuilder::new(capacity), })), other => unreachable!("WriteCell::new() builds no {other} column"), @@ -619,7 +643,9 @@ impl ArrayBuilder for ColumnBuilder { /// Offsets stay i32: `current` entries plus `added` must not pass `i32::MAX`. fn offsets_fit(current: usize, added: usize) -> bool { - current.checked_add(added).is_some_and(|total| total <= i32::MAX as usize) + current + .checked_add(added) + .is_some_and(|total| total <= i32::MAX as usize) } /// What a writer column accepts per `PhpParquetEngine`'s target type, appended to its canonical type's builder; the @@ -661,9 +687,10 @@ impl WriteCell { DataType::FixedSizeBinary(16) if is_uuid(target) => (WriteCell::Uuid, DataType::FixedSizeBinary(16)), DataType::FixedSizeBinary(_) => (WriteCell::Bytes, DataType::Binary), DataType::Date32 => (WriteCell::Date, DataType::Date32), - DataType::Timestamp(_, _) => { - (WriteCell::Timestamp, DataType::Timestamp(TimeUnit::Microsecond, Some("UTC".into()))) - } + DataType::Timestamp(_, _) => ( + WriteCell::Timestamp, + DataType::Timestamp(TimeUnit::Microsecond, Some("UTC".into())), + ), DataType::Time32(_) | DataType::Time64(_) => (WriteCell::Time, DataType::Duration(TimeUnit::Microsecond)), DataType::List(element) => { let (cell, canonical) = Self::new(element)?; @@ -717,7 +744,11 @@ impl WriteCell { let value = value.dereference(); if value.is_null() { - return if nullable { Ok(Scalar::Null) } else { Err(refused("a value", value)) }; + return if nullable { + Ok(Scalar::Null) + } else { + Err(refused("a value", value)) + }; } Ok(match self { @@ -729,9 +760,7 @@ impl WriteCell { (_, Some(int)) => int as f64, _ => return Err(refused("float or int", value)), }), - WriteCell::Bytes => { - Scalar::Bytes(value.zend_str().ok_or_else(|| refused("string", value))?.as_bytes()) - } + WriteCell::Bytes => Scalar::Bytes(value.zend_str().ok_or_else(|| refused("string", value))?.as_bytes()), WriteCell::Uuid => { let text = match value.object() { Some(object) => uuid_text_of(object)?.ok_or_else(|| refused("uuid string or object", value))?, @@ -769,7 +798,9 @@ impl WriteCell { Scalar::Micros(interval_micros(interval, value)?) } - WriteCell::List(_, _) | WriteCell::Map(_, _, _) | WriteCell::Struct(_) => return Err(refused("array", value)), + WriteCell::List(_, _) | WriteCell::Map(_, _, _) | WriteCell::Struct(_) => { + return Err(refused("array", value)) + } }) } @@ -778,7 +809,11 @@ impl WriteCell { let value = value.dereference(); if value.is_null() { - return if nullable { Ok(Validated::Scalar(Scalar::Null)) } else { Err(refused("a value", value)) }; + return if nullable { + Ok(Validated::Scalar(Scalar::Null)) + } else { + Err(refused("a value", value)) + }; } Ok(match self { @@ -895,8 +930,11 @@ impl WriteCell { && key.fits(key_builder, &keys) && value.fits(value_builder, &items) } - (WriteCell::Struct(children), ColumnBuilder::Struct(structure)) => { - children.iter().zip(&mut structure.children).enumerate().all(|(index, ((_, cell, _), child))| { + (WriteCell::Struct(children), ColumnBuilder::Struct(structure)) => children + .iter() + .zip(&mut structure.children) + .enumerate() + .all(|(index, ((_, cell, _), child))| { let values = values .iter() .filter_map(|value| match value { @@ -906,8 +944,7 @@ impl WriteCell { .collect::>(); cell.fits(child, &values) - }) - } + }), _ => true, } } @@ -967,7 +1004,10 @@ impl WriteCell { /// Whether this cell holds one value per row: no list, map or struct. pub fn is_scalar(&self) -> bool { - !matches!(self, WriteCell::List(_, _) | WriteCell::Map(_, _, _) | WriteCell::Struct(_)) + !matches!( + self, + WriteCell::List(_, _) | WriteCell::Map(_, _, _) | WriteCell::Struct(_) + ) } /// A null slot; a struct's children get one too. @@ -990,7 +1030,9 @@ impl WriteCell { (_, ColumnBuilder::Time(builder)) => builder.append_null(), (_, ColumnBuilder::List(builder)) => builder.append_null(), (_, ColumnBuilder::Map(builder)) => builder.append(false).expect("a null map appends no entries"), - (_, ColumnBuilder::Struct(_)) => unreachable!("only a struct cell builds a struct column"), + (_, ColumnBuilder::Struct(_)) => { + unreachable!("only a struct cell builds a struct column") + } } } } @@ -1018,7 +1060,11 @@ fn method_long(object: &ZendObject, method: &str, args: &mut [Zval]) -> Result Result { let seconds = method_long(datetime, "getTimestamp", &mut [])?; let micros = method_long(datetime, "format", &mut [zval_str(b"u")])?; - seconds.checked_mul(1_000_000).and_then(|us| us.checked_add(micros)).ok_or(Refusal::Overflow) + seconds + .checked_mul(1_000_000) + .and_then(|us| us.checked_add(micros)) + .ok_or(Refusal::Overflow) } /// `(getTimestamp() + getOffset())` floored to days, for a datetime timelib has not brought up to date. @@ -1052,8 +1101,8 @@ fn interval_micros(interval: &ZendObject, value: &Zval) -> Result let seconds = ((interval_part(interval, "d")? * 24 + interval_part(interval, "h")?) * 3_600 + interval_part(interval, "i")? * 60 + interval_part(interval, "s")?) - .checked_mul(1_000_000) - .ok_or(Refusal::Overflow)?; + .checked_mul(1_000_000) + .ok_or(Refusal::Overflow)?; let fraction = (read_property(interval, "f")?.double().unwrap_or_default() * 1_000_000.0) as i64; seconds.checked_add(fraction).ok_or(Refusal::Overflow) diff --git a/src/extension/arrow-ext/src/parquet/engine.rs b/src/extension/arrow-ext/src/parquet/engine.rs new file mode 100644 index 0000000000..4bb49a1518 --- /dev/null +++ b/src/extension/arrow-ext/src/parquet/engine.rs @@ -0,0 +1,98 @@ +//! `Flow\Parquet\Engine\RustParquetEngine`: `flow-php/parquet`'s arrow engine, its files read and written by +//! `RustParquetFileReader` / `RustParquetFileWriter`. + +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::Zval; + +use crate::exception::ext_exception; +use crate::interfaces::parquet_engine_ce; +use crate::parquet::lib_calls::{call_static, OPTIONS_TO_ENGINE, OPTIONS_TO_EXTENSION, SCHEMA_TO_EXTENSION}; +use crate::parquet::library::{RustParquetFileReader, RustParquetFileWriter}; +use crate::php::{ht_get, IterableArg}; + +#[php_class] +#[php( + name = "Flow\\Parquet\\Engine\\RustParquetEngine", + flags = ClassFlags::Final, + implements(ce = parquet_engine_ce, stub = "Flow\\Parquet\\ParquetEngine") +)] +pub struct RustParquetEngine { + int96_as_datetime: bool, + write_batch_size: i64, +} + +#[php_impl] +impl RustParquetEngine { + pub fn __construct(options: Option<&Zval>) -> PhpResult { + let mut options = [options.map_or_else(Zval::new, Zval::shallow_clone)]; + let engine = call_static(OPTIONS_TO_ENGINE, &mut options)?; + let engine = engine + .array() + .ok_or_else(|| ext_exception("arrow expected OptionsConverter::toEngine() to return an array"))?; + + Ok(Self { + int96_as_datetime: ht_get(engine, b"INT_96_AS_DATETIME") + .and_then(Zval::bool) + .ok_or_else(|| { + ext_exception("arrow expected OptionsConverter::toEngine() to hold INT_96_AS_DATETIME") + })?, + write_batch_size: ht_get(engine, b"ARROW_WRITE_BATCH_SIZE") + .and_then(Zval::long) + .ok_or_else(|| { + ext_exception("arrow expected OptionsConverter::toEngine() to hold ARROW_WRITE_BATCH_SIZE") + })?, + }) + } + + #[php(name = "openForRead")] + pub fn open_for_read(&self, stream: &Zval) -> PhpResult { + RustParquetFileReader::__construct(stream, self.int96_as_datetime) + } + + #[php(name = "openForWrite")] + pub fn open_for_write( + &self, + stream: &Zval, + schema: &Zval, + compression: &Zval, + options: &Zval, + ) -> PhpResult { + let schema = call_static(SCHEMA_TO_EXTENSION, &mut [schema.shallow_clone()])?; + let options = call_static(OPTIONS_TO_EXTENSION, &mut [options.shallow_clone()])?; + + RustParquetFileWriter::__construct( + stream, + schema + .array() + .ok_or_else(|| ext_exception("arrow expected SchemaConverter::toExtension() to return an array"))?, + compression, + options + .array() + .ok_or_else(|| ext_exception("arrow expected OptionsConverter::toExtension() to return an array"))?, + self.write_batch_size, + ) + } + + /// The writer is closed even when a row is refused; the refusal is what throws. + #[php(name = "writeRows")] + pub fn write_rows( + &self, + stream: &Zval, + schema: &Zval, + compression: &Zval, + options: &Zval, + rows: IterableArg, + ) -> PhpResult<()> { + let mut writer = self.open_for_write(stream, schema, compression, options)?; + + match writer.write_batch(rows) { + Ok(()) => writer.close(), + Err(e) => { + let _ = writer.close(); + + Err(e) + } + } + } +} diff --git a/src/extension/arrow-ext/src/parquet/error.rs b/src/extension/arrow-ext/src/parquet/error.rs index 8acabbc2a3..4817f37754 100644 --- a/src/extension/arrow-ext/src/parquet/error.rs +++ b/src/extension/arrow-ext/src/parquet/error.rs @@ -9,15 +9,36 @@ pub enum Error { Arrow(ArrowError), MissingColumn(String), /// `parquet`: the arrow type (or codec) the core has no cast for. - Unsupported { column: String, parquet: String }, - Overflow { column: String, row: usize }, - InvalidUtf8 { column: String, row: usize }, + Unsupported { + column: String, + parquet: String, + }, + Overflow { + column: String, + row: usize, + }, + InvalidUtf8 { + column: String, + row: usize, + }, /// A fixed-length target the value's byte length does not match. - Length { column: String, row: usize, expected: usize }, + Length { + column: String, + row: usize, + expected: usize, + }, /// MAP keys of a type a PHP array does not key by (int or string), named by the PHP type they would read as. - MapKey { column: String, key: &'static str }, + MapKey { + column: String, + key: &'static str, + }, /// A value the target type does not accept: what it expects and what it got. - Value { column: String, row: usize, expected: &'static str, got: String }, + Value { + column: String, + row: usize, + expected: &'static str, + got: String, + }, /// Bytes that are not a Parquet file: no footer where it must be. NotParquet(String), Options(String), @@ -28,12 +49,33 @@ impl Error { /// The same refusal named after the root column it happened in. pub fn in_column(self, name: &str) -> Self { match self { - Error::Unsupported { parquet, .. } => Error::Unsupported { column: name.to_string(), parquet }, - Error::Overflow { row, .. } => Error::Overflow { column: name.to_string(), row }, - Error::InvalidUtf8 { row, .. } => Error::InvalidUtf8 { column: name.to_string(), row }, - Error::Length { row, expected, .. } => Error::Length { column: name.to_string(), row, expected }, - Error::MapKey { key, .. } => Error::MapKey { column: name.to_string(), key }, - Error::Value { row, expected, got, .. } => Error::Value { column: name.to_string(), row, expected, got }, + Error::Unsupported { parquet, .. } => Error::Unsupported { + column: name.to_string(), + parquet, + }, + Error::Overflow { row, .. } => Error::Overflow { + column: name.to_string(), + row, + }, + Error::InvalidUtf8 { row, .. } => Error::InvalidUtf8 { + column: name.to_string(), + row, + }, + Error::Length { row, expected, .. } => Error::Length { + column: name.to_string(), + row, + expected, + }, + Error::MapKey { key, .. } => Error::MapKey { + column: name.to_string(), + key, + }, + Error::Value { row, expected, got, .. } => Error::Value { + column: name.to_string(), + row, + expected, + got, + }, error => error, } } @@ -41,10 +83,30 @@ impl Error { /// The same refusal at the parent row `parent` maps a child row to. pub fn at_row(self, parent: impl Fn(usize) -> usize) -> Self { match self { - Error::Overflow { column, row } => Error::Overflow { column, row: parent(row) }, - Error::InvalidUtf8 { column, row } => Error::InvalidUtf8 { column, row: parent(row) }, - Error::Length { column, row, expected } => Error::Length { column, row: parent(row), expected }, - Error::Value { column, row, expected, got } => Error::Value { column, row: parent(row), expected, got }, + Error::Overflow { column, row } => Error::Overflow { + column, + row: parent(row), + }, + Error::InvalidUtf8 { column, row } => Error::InvalidUtf8 { + column, + row: parent(row), + }, + Error::Length { column, row, expected } => Error::Length { + column, + row: parent(row), + expected, + }, + Error::Value { + column, + row, + expected, + got, + } => Error::Value { + column, + row: parent(row), + expected, + got, + }, error => error, } } @@ -64,5 +126,7 @@ impl From for Error { /// The parent row of child row `child` under list/map `offsets`. pub fn parent_row>(offsets: &[O], child: usize) -> usize { - offsets.partition_point(|offset| (*offset).into() <= child as i64).saturating_sub(1) + offsets + .partition_point(|offset| (*offset).into() <= child as i64) + .saturating_sub(1) } diff --git a/src/extension/arrow-ext/src/parquet/fetch.rs b/src/extension/arrow-ext/src/parquet/fetch.rs index ef4b62b308..ce141cc755 100644 --- a/src/extension/arrow-ext/src/parquet/fetch.rs +++ b/src/extension/arrow-ext/src/parquet/fetch.rs @@ -83,7 +83,10 @@ impl ChunkFetch { /// `planned`: per planned group, its projected chunks, by projected column; `unplanned`: every other chunk. fn from_ranges(source: Arc, size: u64, planned: Vec>>, unplanned: Vec>) -> Self { let columns = planned.first().map_or(0, Vec::len); - let reads = planned.iter().map(|chunks| coalesced(chunks.clone())).collect::>(); + let reads = planned + .iter() + .map(|chunks| coalesced(chunks.clone())) + .collect::>(); let mut chunks = unplanned .into_iter() .map(|range| Chunk { range, planned: None }) @@ -94,7 +97,9 @@ impl ChunkFetch { .into_iter() .enumerate() .map(move |(column, range)| { - let read = reads.iter().position(|read| read.start <= range.start && range.end <= read.end); + let read = reads + .iter() + .position(|read| read.start <= range.start && range.end <= read.end); Chunk { planned: read.map(|read| (group, column, read)), @@ -122,7 +127,10 @@ impl ChunkFetch { fn chunk_at(&self, offset: u64) -> Option<&Chunk> { let after = self.chunks.partition_point(|chunk| chunk.range.start <= offset); - after.checked_sub(1).map(|index| &self.chunks[index]).filter(|chunk| offset < chunk.range.end) + after + .checked_sub(1) + .map(|index| &self.chunks[index]) + .filter(|chunk| offset < chunk.range.end) } /// The fetched bytes of [start, end) when a planned column chunk holds it, fetching its row group first. @@ -136,7 +144,10 @@ impl ChunkFetch { return Ok(None); } - let mut fetched = self.fetched.lock().map_err(|_| ParquetError::General("chunk fetch poisoned".into()))?; + let mut fetched = self + .fetched + .lock() + .map_err(|_| ParquetError::General("chunk fetch poisoned".into()))?; if let Entry::Vacant(entry) = fetched.buffers.entry(group) { entry.insert( @@ -220,7 +231,11 @@ mod tests { assert!(coalesced(vec![]).is_empty()); } - fn fetch(source: &Arc, planned: Vec>>, unplanned: Vec>) -> ChunkFetch { + fn fetch( + source: &Arc, + planned: Vec>>, + unplanned: Vec>, + ) -> ChunkFetch { ChunkFetch::from_ranges(Arc::clone(source), source.data.len() as u64, planned, unplanned) } @@ -261,7 +276,16 @@ mod tests { fn a_group_is_dropped_once_every_column_moved_past_it() { let source = Arc::new(Counting::new((0..100).collect())); let fetch = fetch(&source, vec![vec![0..10, 20..30], vec![50..60, 70..80]], vec![]); - let groups = |fetch: &ChunkFetch| fetch.fetched.lock().unwrap().buffers.keys().copied().collect::>(); + let groups = |fetch: &ChunkFetch| { + fetch + .fetched + .lock() + .unwrap() + .buffers + .keys() + .copied() + .collect::>() + }; fetch.get_bytes(0, 1).unwrap(); fetch.get_bytes(50, 1).unwrap(); @@ -279,13 +303,24 @@ mod tests { fn page_requests_find_their_chunk_among_many() { let source = Arc::new(Counting::new((0..=255).cycle().take(40_000).collect())); let planned = (0..100).map(|group| vec![group * 400..group * 400 + 100, group * 400 + 200..group * 400 + 300]); - let fetch = fetch(&source, planned.collect(), (0..100).map(|group| group * 400 + 100..group * 400 + 200).collect()); - - assert_eq!(fetch.get_bytes(99 * 400 + 250, 2).unwrap().to_vec(), source.data[39_850..39_852].to_vec()); + let fetch = fetch( + &source, + planned.collect(), + (0..100).map(|group| group * 400 + 100..group * 400 + 200).collect(), + ); + + assert_eq!( + fetch.get_bytes(99 * 400 + 250, 2).unwrap().to_vec(), + source.data[39_850..39_852].to_vec() + ); assert_eq!(source.counted(), (2, 200)); let mut header = Vec::new(); - fetch.get_read(50 * 400 + 150).unwrap().read_to_end(&mut header).unwrap(); + fetch + .get_read(50 * 400 + 150) + .unwrap() + .read_to_end(&mut header) + .unwrap(); assert_eq!(header, source.data[20_150..20_200].to_vec()); assert_eq!(source.counted(), (3, 250)); diff --git a/src/extension/arrow-ext/src/parquet/footer.rs b/src/extension/arrow-ext/src/parquet/footer.rs index 58015a5b82..eab46a8ae6 100644 --- a/src/extension/arrow-ext/src/parquet/footer.rs +++ b/src/extension/arrow-ext/src/parquet/footer.rs @@ -26,7 +26,9 @@ impl Footer { let size = source.len(); if size < 8 { - return Err(corrupt(format!("Invalid Parquet file. Size is {size} bytes, smaller than the footer"))); + return Err(corrupt(format!( + "Invalid Parquet file. Size is {size} bytes, smaller than the footer" + ))); } let read = size.min(TAIL); @@ -151,7 +153,10 @@ mod tests { assert_eq!(counting.counted().0, 2); assert_eq!(footer.meta().file_metadata().num_rows(), 3); assert_eq!( - footer.meta().file_metadata().key_value_metadata().unwrap()[0].value.as_ref().map(String::len), + footer.meta().file_metadata().key_value_metadata().unwrap()[0] + .value + .as_ref() + .map(String::len), Some(100 * 1024) ); } @@ -166,6 +171,9 @@ mod tests { Footer::read(&Source(Arc::new(Counting::new(data)))), Err(Error::NotParquet(message)) if message.contains("Corrupt footer") )); - assert!(matches!(Footer::read(&Source(Arc::new(Counting::new(vec![1, 2, 3])))), Err(Error::NotParquet(_)))); + assert!(matches!( + Footer::read(&Source(Arc::new(Counting::new(vec![1, 2, 3])))), + Err(Error::NotParquet(_)) + )); } } diff --git a/src/extension/arrow-ext/src/parquet/lib_calls.rs b/src/extension/arrow-ext/src/parquet/lib_calls.rs new file mode 100644 index 0000000000..1cd3227ecd --- /dev/null +++ b/src/extension/arrow-ext/src/parquet/lib_calls.rs @@ -0,0 +1,22 @@ +//! The `flow-php/parquet` converters arrow calls by name: mago cannot see these calls, the phpts pin each one. + +use ext_php_rs::prelude::*; +use ext_php_rs::types::Zval; + +use crate::exception::ext_exception; +use crate::php::{call_handle_transparent, ce_method_ref, find_class}; + +pub const METADATA_FROM_THRIFT: &str = "Flow\\Parquet\\ParquetFile\\Metadata::fromThrift"; +pub const SCHEMA_FROM_THRIFT: &str = "Flow\\Parquet\\ParquetFile\\Schema::fromThrift"; +pub const SCHEMA_TO_EXTENSION: &str = "Flow\\Parquet\\Engine\\Arrow\\SchemaConverter::toExtension"; +pub const OPTIONS_TO_EXTENSION: &str = "Flow\\Parquet\\Engine\\Arrow\\OptionsConverter::toExtension"; +pub const OPTIONS_TO_ENGINE: &str = "Flow\\Parquet\\Engine\\Arrow\\OptionsConverter::toEngine"; + +/// `Class::method(...$args)`; an exception the method throws surfaces as itself. +pub fn call_static(name: &str, args: &mut [Zval]) -> PhpResult { + let (class, method) = name + .rsplit_once("::") + .ok_or_else(|| ext_exception(format!("arrow expected a static method name, got \"{name}\"")))?; + + call_handle_transparent(ce_method_ref(find_class(class)?, method)?, None, args) +} diff --git a/src/extension/arrow-ext/src/parquet/library.rs b/src/extension/arrow-ext/src/parquet/library.rs index 3663ae7860..b89418385f 100644 --- a/src/extension/arrow-ext/src/parquet/library.rs +++ b/src/extension/arrow-ext/src/parquet/library.rs @@ -1,27 +1,35 @@ -//! `Flow\Arrow\Parquet\{ParquetFile, ColumnsReader, RowsWriter}`: the `flow-php/parquet` lib's values over the core - +//! `Flow\Parquet\Engine\{RustParquetFileReader, RustParquetFileWriter}` and `Flow\Arrow\Parquet\RustColumnsReader`: the +//! `flow-php/parquet` lib's values over the core - //! one footer read per file, columns as lists of the values `PhpParquetEngine` returns, rows written as it accepts //! them, and struct batches written as another extension exports them. use std::sync::Arc; use arrow_array::{new_null_array, Array, ArrayRef}; -use ext_php_rs::boxed::ZBox; -use ext_php_rs::flags::ClassFlags; +use ext_php_rs::convert::IntoZval; +use ext_php_rs::error::Result as ZvalResult; +use ext_php_rs::flags::{ClassFlags, DataType}; use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, Zval}; +use ext_php_rs::zend::ce; +use parquet::basic::Type as PhysicalType; use parquet::file::metadata::ParquetMetaData; use parquet::file::reader::Length; +use crate::interfaces::{parquet_file_reader_ce, parquet_file_writer_ce}; use crate::parquet::batch; use crate::parquet::cells::{Checked, Classes, ReadCell, Refusal, Scalar, Times, Validated, WriteColumn}; use crate::parquet::error::Error; use crate::parquet::footer::Footer; +use crate::parquet::lib_calls::{call_static, METADATA_FROM_THRIFT, SCHEMA_FROM_THRIFT}; use crate::parquet::options; use crate::parquet::read::{ParquetReader, ReadPlan}; use crate::parquet::sink::PhpSink; use crate::parquet::source::{PhpSource, PhpStream}; use crate::parquet::write::ParquetWriter; -use crate::php::{ht_for_each, ht_get, ht_insert}; +use crate::php::{ + call_method, expect_object, for_each_value, ht_for_each, ht_get, ht_insert, read_property, IterableArg, +}; use crate::render::{exception, parquet_exception, Side}; use crate::thrift; @@ -32,37 +40,77 @@ const RUNTIME: &str = "Flow\\Parquet\\Exception\\RuntimeException"; pub const INVALID_ARGUMENT: &str = "Flow\\Parquet\\Exception\\InvalidArgumentException"; fn closed() -> PhpException { - exception(RUNTIME, "Parquet file is closed".to_string()) + exception(RUNTIME, "Reader is not open".to_string()) +} + +/// `ParquetFileReader::metadata()`'s return, typed `Flow\Parquet\ParquetFile\Metadata`. +pub struct MetadataObject(Zval); + +impl IntoZval for MetadataObject { + const TYPE: DataType = DataType::object("Flow\\Parquet\\ParquetFile\\Metadata"); + const NULLABLE: bool = false; + + fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { + *zv = self.0; + + Ok(()) + } +} + +/// `ParquetFileReader::schema()`'s return, typed `Flow\Parquet\ParquetFile\Schema`. +pub struct SchemaObject(Zval); + +impl IntoZval for SchemaObject { + const TYPE: DataType = DataType::object("Flow\\Parquet\\ParquetFile\\Schema"); + const NULLABLE: bool = false; + + fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { + *zv = self.0; + + Ok(()) + } } pub fn rows(value: Option, name: &str) -> PhpResult> { value .map(|value| { - u64::try_from(value) - .map_err(|_| exception(INVALID_ARGUMENT, format!("arrow Parquet {name} must be greater or equal to 0"))) + u64::try_from(value).map_err(|_| { + exception( + INVALID_ARGUMENT, + format!("arrow Parquet {name} must be greater or equal to 0"), + ) + }) }) .transpose() } pub fn batch_size(value: i64) -> PhpResult { - usize::try_from(value) - .ok() - .filter(|size| *size > 0) - .ok_or_else(|| exception(INVALID_ARGUMENT, "arrow Parquet batch size must be greater than 0".to_string())) + usize::try_from(value).ok().filter(|size| *size > 0).ok_or_else(|| { + exception( + INVALID_ARGUMENT, + "arrow Parquet batch size must be greater than 0".to_string(), + ) + }) } #[php_class] -#[php(name = "Flow\\Arrow\\Parquet\\ParquetFile", flags = ClassFlags::Final)] -pub struct ParquetFile { +#[php( + name = "Flow\\Parquet\\Engine\\RustParquetFileReader", + flags = ClassFlags::Final, + implements(ce = parquet_file_reader_ce, stub = "Flow\\Parquet\\ParquetFileReader") +)] +pub struct RustParquetFileReader { stream: Arc, source: PhpSource, footer: Footer, + int96_as_datetime: bool, + metadata: Option, schema: Option, thrift: Option, closed: bool, } -impl ParquetFile { +impl RustParquetFileReader { fn open(&self) -> PhpResult<()> { if self.closed { return Err(closed()); @@ -71,18 +119,60 @@ impl ParquetFile { Ok(()) } - /// The file's stream, size and footer, for a reader of it: the lib's `ColumnsReader` or a `BatchReader`. + /// The file's stream, size and footer, for a reader of it: the lib's `RustColumnsReader` or a `RustBatchReader`. pub fn read(&self) -> PhpResult<(&Arc, u64, &Arc)> { self.open()?; Ok((&self.stream, self.source.len(), self.footer.meta())) } + + /// `FileMetaData::$schema`: the list of `SchemaElement`s. + fn elements(&self) -> PhpResult { + thrift::decode(self.footer.bytes(), FILE_META_DATA, Some(SCHEMA)) + } + + /// Without `int96AsDatetime`, a requested column (a leaf path, or the path of its parent) holding INT96. + fn refuse_int96(&self, columns: &ZendHashTable) -> PhpResult<()> { + if self.int96_as_datetime { + return Ok(()); + } + + let leaves = self + .footer + .meta() + .file_metadata() + .schema_descr() + .columns() + .iter() + .filter(|leaf| leaf.physical_type() == PhysicalType::INT96) + .map(|leaf| leaf.path().string()) + .collect::>(); + + for column in columns.values().filter_map(Zval::str) { + if leaves + .iter() + .any(|leaf| leaf == column || leaf.starts_with(&format!("{column}."))) + { + return Err(exception( + INVALID_ARGUMENT, + format!( + "Parquet column \"{column}\" holds INT96, which arrow reads only as a datetime \ + (Option::INT_96_AS_DATETIME = true); read the file with \\Flow\\Parquet\\Reader::php()" + ), + )); + } + } + + Ok(()) + } } #[php_impl] -impl ParquetFile { - /// Reads and decodes the footer; owns the stream from here on. - pub fn __construct(stream: &Zval) -> PhpResult { +impl RustParquetFileReader { + /// Reads and decodes the footer; owns the stream from here on. `$int96AsDatetime`: false refuses to read an + /// INT96 column, which arrow reads only as a datetime. + #[php(defaults(int96AsDatetime = true))] + pub fn __construct(stream: &Zval, int96AsDatetime: bool) -> PhpResult { let stream = Arc::new(PhpStream::new(stream)?); let refused = |error| parquet_exception(error, &stream, Side::Read); let source = PhpSource::new(Arc::clone(&stream)).map_err(refused)?; @@ -92,24 +182,59 @@ impl ParquetFile { stream, source, footer, + int96_as_datetime: int96AsDatetime, + metadata: None, schema: None, thrift: None, closed: false, }) } - /// `FileMetaData::$schema`: the list of `SchemaElement`s, decoded on the first call. - pub fn schema(&mut self) -> PhpResult { + /// Closes the stream; any later call throws. + pub fn close(&mut self) -> PhpResult<()> { self.open()?; + self.closed = true; + self.metadata = None; + self.schema = None; + self.thrift = None; - if let Some(schema) = &self.schema { - return Ok(schema.shallow_clone()); + match self.stream.call("close", &mut []) { + Some(_) => Ok(()), + None => Err(parquet_exception( + Error::Stream("close() threw".to_string()), + &self.stream, + Side::Read, + )), } + } - let schema = thrift::decode(self.footer.bytes(), FILE_META_DATA, Some(SCHEMA))?; - self.schema = Some(schema.shallow_clone()); + /// The whole footer as `Metadata`, built on the first call. + pub fn metadata(&mut self) -> PhpResult { + self.open()?; + + if let Some(metadata) = &self.metadata { + return Ok(MetadataObject(metadata.shallow_clone())); + } + + let metadata = call_static(METADATA_FROM_THRIFT, &mut [self.thrift()?])?; + self.metadata = Some(metadata.shallow_clone()); + + Ok(MetadataObject(metadata)) + } + + /// `$columns` (resolved names) in chunks of at most `$batchSize` rows, keyed by column. + #[php(name = "readColumns")] + pub fn read_columns( + &self, + columns: &ZendHashTable, + batchSize: i64, + limit: Option, + offset: Option, + ) -> PhpResult { + self.open()?; + self.refuse_int96(columns)?; - Ok(schema) + RustColumnsReader::__construct(self, columns, batchSize, offset, limit) } #[php(name = "rowsNumber")] @@ -119,12 +244,36 @@ impl ParquetFile { Ok(self.footer.meta().file_metadata().num_rows()) } + /// The file schema, without building the row-group metadata. + pub fn schema(&mut self) -> PhpResult { + self.open()?; + + if let Some(metadata) = &self.metadata { + return Ok(SchemaObject(call_method(metadata, "schema", &mut [])?)); + } + + if let Some(schema) = &self.schema { + return Ok(SchemaObject(schema.shallow_clone())); + } + + let schema = call_static(SCHEMA_FROM_THRIFT, &mut [self.elements()?])?; + self.schema = Some(schema.shallow_clone()); + + Ok(SchemaObject(schema)) + } + /// Σ row group `total_byte_size` (uncompressed). #[php(name = "totalByteSize")] pub fn total_byte_size(&self) -> PhpResult { self.open()?; - Ok(self.footer.meta().row_groups().iter().map(|group| group.total_byte_size()).sum()) + Ok(self + .footer + .meta() + .row_groups() + .iter() + .map(|group| group.total_byte_size()) + .sum()) } /// The whole footer as `FileMetaData`, decoded on the first call. @@ -140,39 +289,103 @@ impl ParquetFile { Ok(thrift) } +} - /// Closes the stream; any later call throws. - pub fn close(&mut self) -> PhpResult<()> { - self.open()?; - self.closed = true; - self.schema = None; - self.thrift = None; +/// A chunk of `RustColumnsReader::current()`, typed `array`. +pub struct Chunk(Zval); - match self.stream.call("close", &mut []) { - Some(_) => Ok(()), - None => Err(parquet_exception( - Error::Stream("close() threw".to_string()), - &self.stream, - Side::Read, - )), - } +impl IntoZval for Chunk { + const TYPE: DataType = DataType::Array; + const NULLABLE: bool = false; + + fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { + *zv = self.0; + + Ok(()) } } #[php_class] -#[php(name = "Flow\\Arrow\\Parquet\\ColumnsReader", flags = ClassFlags::Final)] -pub struct ColumnsReader { +#[php( + name = "Flow\\Arrow\\Parquet\\RustColumnsReader", + flags = ClassFlags::Final, + implements(ce = ce::iterator, stub = "\\Iterator") +)] +pub struct RustColumnsReader { reader: Option, stream: Arc, columns: Vec<(Vec, ReadCell)>, times: Option, + current: Option, + /// The index of `current`. + key: i64, + started: bool, + /// `next()` moved past the first chunk: `rewind()` throws from here on. + advanced: bool, +} + +impl RustColumnsReader { + /// As a Generator, the reader starts on its first `rewind()`, `valid()`, `current()`, `key()` or `next()`. + fn start(&mut self) -> PhpResult<()> { + if self.started { + return Ok(()); + } + + self.started = true; + self.pull() + } + + /// A refused chunk ends the reader: it is never read again. + fn pull(&mut self) -> PhpResult<()> { + self.current = None; + let fetched = self.fetch(); + + if fetched.is_err() { + self.reader = None; + } + + self.current = fetched?; + + Ok(()) + } + + /// At most `$batchSize` rows as lists keyed by column, `None` after the last. + fn fetch(&mut self) -> PhpResult> { + let Some(reader) = self.reader.as_mut() else { + return Ok(None); + }; + + let arrays: Vec = match reader.next() { + None => { + self.reader = None; + + return Ok(None); + } + Some(batch) => { + batch + .map_err(|error| parquet_exception(error, &self.stream, Side::Read))? + .1 + } + }; + + let mut chunk = ZendHashTable::with_capacity(self.columns.len() as u32); + + for ((name, cell), array) in self.columns.iter().zip(&arrays) { + ht_insert(&mut chunk, name, cell.values(array, self.times.as_ref())?); + } + + let mut zv = Zval::new(); + zv.set_hashtable(chunk); + + Ok(Some(zv)) + } } #[php_impl] -impl ColumnsReader { - /// `$columns`: root names or struct paths; `$batchSize` rows at most per `next()`. +impl RustColumnsReader { + /// `$columns`: root names or struct paths; `$batchSize` rows at most per chunk. pub fn __construct( - file: &ParquetFile, + file: &RustParquetFileReader, columns: &ZendHashTable, batch_size: i64, offset: Option, @@ -188,16 +401,27 @@ impl ColumnsReader { ht_for_each(columns, |_, _, name| { names.push( name.str() - .ok_or_else(|| exception(INVALID_ARGUMENT, "arrow Parquet column names must be strings".to_string()))? + .ok_or_else(|| { + exception( + INVALID_ARGUMENT, + "arrow Parquet column names must be strings".to_string(), + ) + })? .to_string(), ); Ok(()) })?; - let reader = - ParquetReader::open(Arc::clone(&stream), size, meta, &names, ReadPlan::new(meta, offset, limit), batch_size) - .map_err(refused)?; + let reader = ParquetReader::open( + Arc::clone(&stream), + size, + meta, + &names, + ReadPlan::new(meta, offset, limit), + batch_size, + ) + .map_err(refused)?; let cells = reader .fields() .iter() @@ -205,52 +429,94 @@ impl ColumnsReader { .map(|(field, canonical)| ReadCell::new(canonical, field).map_err(|e| e.in_column(field.name()))) .collect::, Error>>() .map_err(refused)?; - let times = if cells.iter().any(ReadCell::needs_times) { Some(Times::new()?) } else { None }; + let times = if cells.iter().any(ReadCell::needs_times) { + Some(Times::new()?) + } else { + None + }; Ok(Self { reader: Some(reader), stream, columns: names.into_iter().map(String::into_bytes).zip(cells).collect(), times, + current: None, + key: 0, + started: false, + advanced: false, }) } - /// At most `$batchSize` rows as lists keyed by column, null after the last. - pub fn next(&mut self) -> PhpResult>> { - let Some(reader) = self.reader.as_mut() else { - return Ok(None); - }; + /// Reads the first chunk; the reader streams once, so it refuses to rewind after `next()`. + pub fn rewind(&mut self) -> PhpResult<()> { + if self.advanced { + return Err(exception(RUNTIME, "RustColumnsReader cannot rewind".to_string())); + } - let arrays: Vec = match reader.next() { - None => { - self.reader = None; + self.start() + } - return Ok(None); - } - Some(batch) => { - batch - .map_err(|error| parquet_exception(error, &self.stream, Side::Read))? - .1 - } - }; + pub fn valid(&mut self) -> PhpResult { + self.start()?; - let mut chunk = ZendHashTable::with_capacity(self.columns.len() as u32); + Ok(self.current.is_some()) + } - for ((name, cell), array) in self.columns.iter().zip(&arrays) { - ht_insert(&mut chunk, name, cell.values(array, self.times.as_ref())?); + pub fn current(&mut self) -> PhpResult> { + self.start()?; + + Ok(self.current.as_ref().map(|chunk| Chunk(chunk.shallow_clone()))) + } + + /// The chunk index from 0, null once the reader ended (as a Generator's). + pub fn key(&mut self) -> PhpResult> { + self.start()?; + + Ok(self.current.is_some().then_some(self.key)) + } + + pub fn next(&mut self) -> PhpResult<()> { + self.start()?; + + if self.current.is_none() { + return Ok(()); } - Ok(Some(chunk)) + self.advanced = true; + self.key += 1; + self.pull() } +} - pub fn close(&mut self) { - self.reader = None; +/// `Compressions::$name` as the Arrow codec name. +fn codec(compression: &Zval) -> PhpResult<&'static str> { + let name = read_property(expect_object(compression, "the compression")?, "name")?; + + match name.str() { + Some("UNCOMPRESSED") => Ok("UNCOMPRESSED"), + Some("SNAPPY") => Ok("SNAPPY"), + Some("GZIP") => Ok("GZIP"), + Some("BROTLI") => Ok("BROTLI"), + Some("LZ4" | "LZ4_RAW") => Ok("LZ4_RAW"), + Some("ZSTD") => Ok("ZSTD"), + Some("LZO") => Err(exception( + RUNTIME, + "LZO compression is not supported by the Arrow engine".to_string(), + )), + _ => Err(exception( + INVALID_ARGUMENT, + "arrow Parquet compression must be a Flow\\Parquet\\ParquetFile\\Compressions case".to_string(), + )), } } #[php_class] -#[php(name = "Flow\\Arrow\\Parquet\\RowsWriter", flags = ClassFlags::Final)] -pub struct RowsWriter { +#[php( + name = "Flow\\Parquet\\Engine\\RustParquetFileWriter", + flags = ClassFlags::Final, + implements(ce = parquet_file_writer_ce, stub = "Flow\\Parquet\\ParquetFileWriter") +)] +pub struct RustParquetFileWriter { writer: Option, stream: Arc, columns: Vec, @@ -261,13 +527,13 @@ pub struct RowsWriter { batch_size: usize, } -impl Drop for RowsWriter { +impl Drop for RustParquetFileWriter { fn drop(&mut self) { self.stream.detach(); } } -impl RowsWriter { +impl RustParquetFileWriter { fn refused(&self, error: Error) -> PhpException { parquet_exception(error, &self.stream, Side::Write) } @@ -301,7 +567,10 @@ impl RowsWriter { let arrays = self.columns.iter_mut().map(WriteColumn::take).collect::>(); let rows = std::mem::take(&mut self.buffered); - let writer = self.writer.as_mut().ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; + let writer = self + .writer + .as_mut() + .ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; writer .write(rows, &arrays) @@ -375,7 +644,12 @@ impl RowsWriter { /// `rows` values of every column from `first` on, column by column; a refused cell lowers the row limit of the /// columns after it, so the refusal raised and the rows kept are those of `append()` row by row. - fn append_columns<'a, V: Checked<'a>>(&mut self, lists: &[Option>], first: usize, rows: usize) -> PhpResult<()> { + fn append_columns<'a, V: Checked<'a>>( + &mut self, + lists: &[Option>], + first: usize, + rows: usize, + ) -> PhpResult<()> { let mut limit = rows; let mut refused = None; let mut checked: Vec> = Vec::with_capacity(self.columns.len()); @@ -423,17 +697,18 @@ impl RowsWriter { } #[php_impl] -impl RowsWriter { +impl RustParquetFileWriter { /// `$schema` / `$options`: `Flow\Parquet\Engine\Arrow\SchemaConverter` / `OptionsConverter::toExtension()`; /// `$batchSize` rows per `ParquetWriter::write`. pub fn __construct( stream: &Zval, schema: &ZendHashTable, - compression: String, + compression: &Zval, options: &ZendHashTable, batch_size: i64, ) -> PhpResult { let batch_size = self::batch_size(batch_size)?; + let compression = codec(compression)?; let stream = Arc::new(PhpStream::new(stream)?); let refused = |error| parquet_exception(error, &stream, Side::Write); let schema = options::schema(schema).map_err(refused)?; @@ -447,7 +722,7 @@ impl RowsWriter { let writer = ParquetWriter::open( PhpSink::new(Arc::clone(&stream)), schema, - options::properties(&compression, options).map_err(refused)?, + options::properties(compression, options).map_err(refused)?, ) .map_err(refused)?; @@ -492,7 +767,10 @@ impl RowsWriter { for (key, values) in columns.iter() { let values = values.array().ok_or_else(|| { - exception(INVALID_ARGUMENT, "arrow Parquet writer columns must be arrays".to_string()) + exception( + INVALID_ARGUMENT, + "arrow Parquet writer columns must be arrays".to_string(), + ) })?; lengths.push((key.to_string(), values.len())); @@ -501,7 +779,10 @@ impl RowsWriter { let count = lengths.first().map_or(0, |(_, length)| *length); if lengths.iter().any(|(_, length)| *length != count) { - let described = lengths.iter().map(|(name, length)| format!("\"{name}\": {length}")).collect::>(); + let described = lengths + .iter() + .map(|(name, length)| format!("\"{name}\": {length}")) + .collect::>(); return Err(exception( INVALID_ARGUMENT, @@ -535,16 +816,31 @@ impl RowsWriter { Ok(()) } + /// An array as `writeRows()` (keys ignored), a `Traversable` row by row. + #[php(name = "writeBatch")] + pub fn write_batch(&mut self, rows: IterableArg) -> PhpResult<()> { + self.open()?; + + if let Some(rows) = rows.0.array() { + return self.write_rows(rows); + } + + for_each_value(rows.0, |row| self.write_row(row)) + } + /// An Arrow C Data struct batch another extension exported, moved out of `$batch`: its children by writer column /// name, a writer column the batch lacks as nulls, a child the writer lacks ignored. Buffered rows go first. - #[php(name = "writeBatch")] - pub fn write_batch(&mut self, batch: &Zval) -> PhpResult<()> { + #[php(name = "writeArrowBatch")] + pub fn write_arrow_batch(&mut self, batch: &Zval) -> PhpResult<()> { self.open()?; self.flush()?; let batch = batch::import(batch)?; let rows = batch.len(); - let writer = self.writer.as_mut().ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; + let writer = self + .writer + .as_mut() + .ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; let arrays = writer .schema() .fields() @@ -560,16 +856,20 @@ impl RowsWriter { .map_err(|error| parquet_exception(error, &self.stream, Side::Write)) } - /// Buffered rows, the footer, then the stream closed. + /// Buffered rows, the footer, then the stream closed - closed even when a flush or the footer is refused; the + /// first refusal is the one thrown. pub fn close(&mut self) -> PhpResult<()> { let flushed = self.flush(); - let writer = self.writer.take().ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; - flushed?; - writer.close().map_err(|error| self.refused(error))?; - - match self.stream.call("close", &mut []) { + let writer = self + .writer + .take() + .ok_or_else(|| exception(RUNTIME, "Writer is not open".to_string()))?; + let written = flushed.and_then(|()| writer.close().map(|_| ()).map_err(|error| self.refused(error))); + let closed = match self.stream.call("close", &mut []) { Some(_) => Ok(()), None => Err(self.refused(Error::Stream("close() threw".to_string()))), - } + }; + + written.and(closed) } } diff --git a/src/extension/arrow-ext/src/parquet/mod.rs b/src/extension/arrow-ext/src/parquet/mod.rs index ddda9c6c7c..3a3b825f67 100644 --- a/src/extension/arrow-ext/src/parquet/mod.rs +++ b/src/extension/arrow-ext/src/parquet/mod.rs @@ -4,9 +4,15 @@ pub mod batch; pub mod canonical; pub mod cells; +pub mod engine; pub mod error; pub mod fetch; pub mod footer; +pub mod lib_calls; +#[allow( + non_snake_case, + reason = "PHP takes a parameter name from its Rust identifier: the contracts' are camelCase" +)] pub mod library; pub mod options; pub mod read; diff --git a/src/extension/arrow-ext/src/parquet/options.rs b/src/extension/arrow-ext/src/parquet/options.rs index c2ff49cc61..99dbd48b40 100644 --- a/src/extension/arrow-ext/src/parquet/options.rs +++ b/src/extension/arrow-ext/src/parquet/options.rs @@ -58,10 +58,7 @@ fn php_schema_entry_to_field(entry_ht: &ZendHashTable) -> Result .ok_or_else(|| "Schema entry must have a 'type' string key".to_string())? .to_string(); - let nullable = entry_ht - .get("optional") - .and_then(|z| z.bool()) - .unwrap_or(true); + let nullable = entry_ht.get("optional").and_then(|z| z.bool()).unwrap_or(true); let data_type = match type_str.as_str() { "BOOLEAN" => DataType::Boolean, @@ -91,55 +88,36 @@ fn php_schema_entry_to_field(entry_ht: &ZendHashTable) -> Result let precision = entry_ht .get("precision") .and_then(|z| z.long()) - .ok_or_else(|| { - format!( - "Column '{}': DECIMAL type requires 'precision' integer key", - name - ) - })? as u8; + .ok_or_else(|| format!("Column '{}': DECIMAL type requires 'precision' integer key", name))? + as u8; let scale = entry_ht .get("scale") .and_then(|z| z.long()) - .ok_or_else(|| { - format!( - "Column '{}': DECIMAL type requires 'scale' integer key", - name - ) - })? as i8; + .ok_or_else(|| format!("Column '{}': DECIMAL type requires 'scale' integer key", name))? + as i8; DataType::Decimal128(precision, scale) } "UUID" => { let mut field = Field::new(&name, DataType::FixedSizeBinary(16), nullable); - field.try_with_extension_type(Uuid).map_err(|e| { - format!( - "Column '{}': failed to set UUID extension type: {}", - name, e - ) - })?; + field + .try_with_extension_type(Uuid) + .map_err(|e| format!("Column '{}': failed to set UUID extension type: {}", name, e))?; return Ok(field); } "JSON" => { let mut field = Field::new(&name, DataType::Utf8, nullable); field .try_with_extension_type(Json::default()) - .map_err(|e| { - format!( - "Column '{}': failed to set JSON extension type: {}", - name, e - ) - })?; + .map_err(|e| format!("Column '{}': failed to set JSON extension type: {}", name, e))?; return Ok(field); } "FIXED_SIZE_BINARY" => { - let length = entry_ht - .get("length") - .and_then(|z| z.long()) - .ok_or_else(|| { - format!( - "Column '{}': FIXED_SIZE_BINARY type requires 'length' integer key", - name - ) - })? as i32; + let length = entry_ht.get("length").and_then(|z| z.long()).ok_or_else(|| { + format!( + "Column '{}': FIXED_SIZE_BINARY type requires 'length' integer key", + name + ) + })? as i32; DataType::FixedSizeBinary(length) } "LIST" => { @@ -147,9 +125,10 @@ fn php_schema_entry_to_field(entry_ht: &ZendHashTable) -> Result .get("children") .and_then(|z| z.array()) .ok_or_else(|| format!("Column '{}': LIST type requires 'children' array", name))?; - let child_zv = children.values().next().ok_or_else(|| { - format!("Column '{}': LIST type requires exactly one child", name) - })?; + let child_zv = children + .values() + .next() + .ok_or_else(|| format!("Column '{}': LIST type requires exactly one child", name))?; let child_ht = child_zv .array() .ok_or_else(|| format!("Column '{}': LIST child must be an array", name))?; @@ -160,15 +139,13 @@ fn php_schema_entry_to_field(entry_ht: &ZendHashTable) -> Result let children = entry_ht .get("children") .and_then(|z| z.array()) - .ok_or_else(|| { - format!("Column '{}': STRUCT type requires 'children' array", name) - })?; + .ok_or_else(|| format!("Column '{}': STRUCT type requires 'children' array", name))?; let fields: Result, String> = children .values() .map(|child_zv| { - let child_ht = child_zv.array().ok_or_else(|| { - format!("Column '{}': STRUCT child must be an array", name) - })?; + let child_ht = child_zv + .array() + .ok_or_else(|| format!("Column '{}': STRUCT child must be an array", name))?; php_schema_entry_to_field(child_ht) }) .collect(); @@ -180,31 +157,24 @@ fn php_schema_entry_to_field(entry_ht: &ZendHashTable) -> Result .and_then(|z| z.array()) .ok_or_else(|| format!("Column '{}': MAP type requires 'children' array", name))?; let mut child_iter = children.values(); - let key_zv = child_iter.next().ok_or_else(|| { - format!( - "Column '{}': MAP type requires key and value children", - name - ) - })?; - let val_zv = child_iter.next().ok_or_else(|| { - format!( - "Column '{}': MAP type requires key and value children", - name - ) - })?; - let key_field = - php_schema_entry_to_field(key_zv.array().ok_or_else(|| { - format!("Column '{}': MAP key child must be an array", name) - })?)?; - let val_field = - php_schema_entry_to_field(val_zv.array().ok_or_else(|| { - format!("Column '{}': MAP value child must be an array", name) - })?)?; + let key_zv = child_iter + .next() + .ok_or_else(|| format!("Column '{}': MAP type requires key and value children", name))?; + let val_zv = child_iter + .next() + .ok_or_else(|| format!("Column '{}': MAP type requires key and value children", name))?; + let key_field = php_schema_entry_to_field( + key_zv + .array() + .ok_or_else(|| format!("Column '{}': MAP key child must be an array", name))?, + )?; + let val_field = php_schema_entry_to_field( + val_zv + .array() + .ok_or_else(|| format!("Column '{}': MAP value child must be an array", name))?, + )?; let entries_struct = DataType::Struct(Fields::from(vec![key_field, val_field])); - DataType::Map( - Arc::new(Field::new("entries", entries_struct, false)), - false, - ) + DataType::Map(Arc::new(Field::new("entries", entries_struct, false)), false) } other => { return Err(format!("Column '{}': Unsupported type '{}'", name, other)); @@ -222,9 +192,7 @@ fn php_schema_to_arrow(schema: &ZendHashTable) -> Result { let mut fields = Vec::with_capacity(schema.len()); for (_key, zv) in schema.iter() { - let entry_ht = zv - .array() - .ok_or_else(|| "Schema entry must be an array".to_string())?; + let entry_ht = zv.array().ok_or_else(|| "Schema entry must be an array".to_string())?; fields.push(php_schema_entry_to_field(entry_ht)?); } @@ -242,16 +210,14 @@ fn parse_compression( "SNAPPY" => Ok(Compression::SNAPPY), "GZIP" => { let level = match gzip_level { - Some(l) => GzipLevel::try_new(l) - .map_err(|e| format!("Invalid GZIP compression level: {}", e))?, + Some(l) => GzipLevel::try_new(l).map_err(|e| format!("Invalid GZIP compression level: {}", e))?, None => Default::default(), }; Ok(Compression::GZIP(level)) } "ZSTD" => { let level = match zstd_level { - Some(l) => ZstdLevel::try_new(l) - .map_err(|e| format!("Invalid ZSTD compression level: {}", e))?, + Some(l) => ZstdLevel::try_new(l).map_err(|e| format!("Invalid ZSTD compression level: {}", e))?, None => Default::default(), }; Ok(Compression::ZSTD(level)) @@ -259,8 +225,7 @@ fn parse_compression( "LZ4" | "LZ4_RAW" => Ok(Compression::LZ4_RAW), "BROTLI" => { let level = match brotli_level { - Some(l) => BrotliLevel::try_new(l) - .map_err(|e| format!("Invalid BROTLI compression level: {}", e))?, + Some(l) => BrotliLevel::try_new(l).map_err(|e| format!("Invalid BROTLI compression level: {}", e))?, None => Default::default(), }; Ok(Compression::BROTLI(level)) @@ -273,8 +238,7 @@ fn parse_compression( } fn parse_encoding(s: &str) -> Result { - Encoding::from_str(&s.to_uppercase()) - .map_err(|e| format!("Unsupported encoding '{}': {}", s, e)) + Encoding::from_str(&s.to_uppercase()).map_err(|e| format!("Unsupported encoding '{}': {}", s, e)) } fn apply_writer_options( @@ -316,12 +280,7 @@ fn apply_writer_options( let version = match val { 1 => WriterVersion::PARQUET_1_0, 2 => WriterVersion::PARQUET_2_0, - other => { - return Err(format!( - "Invalid WRITER_VERSION '{}'. Must be 1 or 2", - other - )) - } + other => return Err(format!("Invalid WRITER_VERSION '{}'. Must be 1 or 2", other)), }; builder = builder.set_writer_version(version); } @@ -335,11 +294,9 @@ fn apply_writer_options( _ => continue, }; if let Some(codec_str) = val.str() { - let parts: Vec = - col_path_str.split('.').map(|s| s.to_string()).collect(); + let parts: Vec = col_path_str.split('.').map(|s| s.to_string()).collect(); let col_path = ColumnPath::new(parts); - let col_codec = - parse_compression(codec_str, gzip_level, brotli_level, zstd_level)?; + let col_codec = parse_compression(codec_str, gzip_level, brotli_level, zstd_level)?; builder = builder.set_column_compression(col_path, col_codec); } } @@ -355,8 +312,7 @@ fn apply_writer_options( _ => continue, }; if let Some(enc_str) = val.str() { - let parts: Vec = - col_path_str.split('.').map(|s| s.to_string()).collect(); + let parts: Vec = col_path_str.split('.').map(|s| s.to_string()).collect(); let col_path = ColumnPath::new(parts); let encoding = parse_encoding(enc_str)?; builder = builder.set_column_encoding(col_path, encoding); @@ -367,4 +323,3 @@ fn apply_writer_options( Ok(builder) } - diff --git a/src/extension/arrow-ext/src/parquet/read.rs b/src/extension/arrow-ext/src/parquet/read.rs index 8c48d6b451..bb661f2cf8 100644 --- a/src/extension/arrow-ext/src/parquet/read.rs +++ b/src/extension/arrow-ext/src/parquet/read.rs @@ -131,13 +131,21 @@ impl ParquetReader { Some(hint) => ArrowReaderOptions::new().with_schema(hint), None => ArrowReaderOptions::new(), }; - let schema = ArrowReaderMetadata::try_new(Arc::clone(meta), options.clone())?.schema().clone(); + let schema = ArrowReaderMetadata::try_new(Arc::clone(meta), options.clone())? + .schema() + .clone(); let projected = columns .iter() .map(|name| Projected::resolve(&schema, name)) .collect::, _>>()?; - let fields = projected.iter().map(|column| Arc::clone(&column.field)).collect::>(); - let types = fields.iter().map(|field| canonical_type(field)).collect::, _>>()?; + let fields = projected + .iter() + .map(|column| Arc::clone(&column.field)) + .collect::>(); + let types = fields + .iter() + .map(|field| canonical_type(field)) + .collect::, _>>()?; if let Some(codec) = unsupported_codec(meta, &plan.row_groups, &projected) { return Err(codec); @@ -145,7 +153,11 @@ impl ParquetReader { let descr = meta.file_metadata().schema_descr(); let leaves = (0..descr.num_columns()) - .filter(|leaf| projected.iter().any(|column| column.reads_leaf(descr.column(*leaf).path().parts()))) + .filter(|leaf| { + projected + .iter() + .any(|column| column.reads_leaf(descr.column(*leaf).path().parts())) + }) .collect::>(); let fetch = ChunkFetch::new(source, size, meta, &plan.row_groups, &leaves); let meta = if plan.skip > 0 { @@ -175,7 +187,9 @@ impl ParquetReader { let positions = projected .into_iter() .map(|mut column| { - let root = schema.index_of(&column.path[0]).map_err(|_| Error::MissingColumn(column.field.name().clone()))?; + let root = schema + .index_of(&column.path[0]) + .map_err(|_| Error::MissingColumn(column.field.name().clone()))?; column.path.remove(0); Ok((root, column.path)) @@ -280,7 +294,9 @@ fn int96_hinted(field: &FieldRef, descr: &SchemaDescriptor, leaf: &mut usize, hi fn unsupported_codec(meta: &ParquetMetaData, row_groups: &[usize], columns: &[Projected]) -> Option { row_groups.iter().find_map(|group| { meta.row_group(*group).columns().iter().find_map(|chunk| { - let column = columns.iter().find(|column| column.reads_leaf(chunk.column_path().parts()))?; + let column = columns + .iter() + .find(|column| column.reads_leaf(chunk.column_path().parts()))?; (chunk.compression() == Compression::LZO).then(|| Error::Unsupported { column: column.field.name().clone(), @@ -321,7 +337,11 @@ mod tests { let mut writer = ArrowWriter::try_new( &mut file, Arc::clone(&schema), - Some(WriterProperties::builder().set_max_row_group_row_count(Some(8_192)).build()), + Some( + WriterProperties::builder() + .set_max_row_group_row_count(Some(8_192)) + .build(), + ), ) .unwrap(); writer @@ -329,7 +349,9 @@ mod tests { .unwrap(); writer.close().unwrap(); - ParquetMetaDataReader::new().parse_and_finish(&Bytes::from(file)).unwrap() + ParquetMetaDataReader::new() + .parse_and_finish(&Bytes::from(file)) + .unwrap() } fn plan(offset: u64, limit: u64) -> (Vec, usize) { @@ -375,14 +397,20 @@ mod tests { .write( &RecordBatch::try_new( schema, - vec![Arc::new(Int64Array::from(vec![1])), Arc::new(StringArray::from(vec!["a"]))], + vec![ + Arc::new(Int64Array::from(vec![1])), + Arc::new(StringArray::from(vec!["a"])), + ], ) .unwrap(), ) .unwrap(); writer.close().unwrap(); - let mut builder = ParquetMetaDataReader::new().parse_and_finish(&Bytes::from(file)).unwrap().into_builder(); + let mut builder = ParquetMetaDataReader::new() + .parse_and_finish(&Bytes::from(file)) + .unwrap() + .into_builder(); let row_groups = builder .take_row_groups() .into_iter() @@ -391,7 +419,12 @@ mod tests { .columns() .iter() .map(|chunk| match chunk.column_path().string().as_str() { - "name" => chunk.clone().into_builder().set_compression(Compression::LZO).build().unwrap(), + "name" => chunk + .clone() + .into_builder() + .set_compression(Compression::LZO) + .build() + .unwrap(), _ => chunk.clone(), }) .collect(); @@ -419,14 +452,22 @@ mod tests { assert!(unsupported_codec(&meta, &[0], &[column("id")]).is_none()); } - fn open(file: Vec, columns: &[&str], offset: u64, limit: Option) -> Result<(ParquetReader, Arc), Error> { + fn open( + file: Vec, + columns: &[&str], + offset: u64, + limit: Option, + ) -> Result<(ParquetReader, Arc), Error> { let footer = Footer::read(&Bytes::from(file.clone()))?; let source = Arc::new(Counting::new(file)); let size = source.data.len() as u64; let columns = columns.iter().map(|column| column.to_string()).collect::>(); let plan = ReadPlan::new(footer.meta(), offset, limit); - Ok((ParquetReader::open(Arc::clone(&source), size, footer.meta(), &columns, plan, 1_024)?, source)) + Ok(( + ParquetReader::open(Arc::clone(&source), size, footer.meta(), &columns, plan, 1_024)?, + source, + )) } fn read(file: Vec, columns: &[&str]) -> Result, Error> { @@ -440,7 +481,11 @@ mod tests { fn int96(days_since_epoch: i64, nanos_of_day: i64) -> Int96 { let mut value = Int96::new(); - value.set_data(nanos_of_day as u32, (nanos_of_day >> 32) as u32, (days_since_epoch + 2_440_588) as u32); + value.set_data( + nanos_of_day as u32, + (nanos_of_day >> 32) as u32, + (days_since_epoch + 2_440_588) as u32, + ); value } @@ -456,22 +501,35 @@ mod tests { .unwrap(), ); let mut file = Vec::new(); - let mut writer = SerializedFileWriter::new(&mut file, schema, Arc::new(WriterProperties::builder().build())).unwrap(); + let mut writer = + SerializedFileWriter::new(&mut file, schema, Arc::new(WriterProperties::builder().build())).unwrap(); let mut group = writer.next_row_group().unwrap(); let first = int96(-719_162, 1_000); let last = int96(-3_653, 86_399_999_999_999); let mut column = group.next_column().unwrap().unwrap(); - column.typed::().write_batch(&[first, last], Some(&[1, 1]), None).unwrap(); + column + .typed::() + .write_batch(&[first, last], Some(&[1, 1]), None) + .unwrap(); column.close().unwrap(); let mut column = group.next_column().unwrap().unwrap(); - column.typed::().write_batch(&[1_500, -1_500], Some(&[1, 1]), None).unwrap(); + column + .typed::() + .write_batch(&[1_500, -1_500], Some(&[1, 1]), None) + .unwrap(); column.close().unwrap(); let mut column = group.next_column().unwrap().unwrap(); - column.typed::().write_batch(&[first, last], Some(&[2, 2]), None).unwrap(); + column + .typed::() + .write_batch(&[first, last], Some(&[2, 2]), None) + .unwrap(); column.close().unwrap(); let mut column = group.next_column().unwrap().unwrap(); - column.typed::().write_batch(&[first, last], Some(&[3, 3]), Some(&[0, 0])).unwrap(); + column + .typed::() + .write_batch(&[first, last], Some(&[3, 3]), Some(&[0, 0])) + .unwrap(); column.close().unwrap(); group.close().unwrap(); writer.close().unwrap(); @@ -548,7 +606,10 @@ mod tests { let arrays = read(struct_file(), &["structure.int64", "structure.name"]).unwrap(); assert_eq!( - arrays[0].as_primitive::().iter().collect::>(), + arrays[0] + .as_primitive::() + .iter() + .collect::>(), vec![Some(1), None, None] ); assert_eq!( @@ -595,10 +656,16 @@ mod tests { let mut writer = ArrowWriter::try_new( &mut file, Arc::clone(&schema), - Some(WriterProperties::builder().set_max_row_group_row_count(Some(100)).build()), + Some( + WriterProperties::builder() + .set_max_row_group_row_count(Some(100)) + .build(), + ), ) .unwrap(); - writer.write(&RecordBatch::try_new(schema, vec![column(), column(), column()]).unwrap()).unwrap(); + writer + .write(&RecordBatch::try_new(schema, vec![column(), column(), column()]).unwrap()) + .unwrap(); writer.close().unwrap(); file diff --git a/src/extension/arrow-ext/src/parquet/sink.rs b/src/extension/arrow-ext/src/parquet/sink.rs index b7b70352d1..647b7ce0dc 100644 --- a/src/extension/arrow-ext/src/parquet/sink.rs +++ b/src/extension/arrow-ext/src/parquet/sink.rs @@ -3,8 +3,8 @@ use std::io::{self, Write}; use std::sync::Arc; -use crate::php::zval_str; use crate::parquet::source::PhpStream; +use crate::php::zval_str; pub struct PhpSink { stream: Arc, diff --git a/src/extension/arrow-ext/src/parquet/source.rs b/src/extension/arrow-ext/src/parquet/source.rs index 2df23431ce..d0248331b3 100644 --- a/src/extension/arrow-ext/src/parquet/source.rs +++ b/src/extension/arrow-ext/src/parquet/source.rs @@ -12,8 +12,8 @@ use ext_php_rs::types::{ZendObject, Zval}; use parquet::errors::ParquetError; use parquet::file::reader::{ChunkReader, Length}; -use crate::php::{call_handle_catching, ce_method_ref, expect_object, zval_long}; use crate::parquet::error::Error; +use crate::php::{call_handle_catching, ce_method_ref, expect_object, zval_long}; /// What `get_read()` pulls from the stream per `read()` call. pub const WINDOW: usize = 64 * 1024; @@ -140,7 +140,10 @@ pub fn exact(source: &R, start: u64, length: usize) -> Result Zval { } pub fn find_class(name: &str) -> Result<&'static ClassEntry, PhpException> { - ClassEntry::try_find(name).ok_or_else(|| ext_exception(format!("arrow requires class \"{name}\" to be autoloadable"))) + ClassEntry::try_find(name) + .ok_or_else(|| ext_exception(format!("arrow requires class \"{name}\" to be autoloadable"))) } /// Fails when the last engine call left an exception pending, so PHP-level @@ -138,10 +141,21 @@ pub fn ce_method_ref(ce: &ClassEntry, method: &str) -> Result<&'static Function, }; function.ok_or_else(|| { - ext_exception(format!("arrow failed to resolve method {}::{method}", ce.name().unwrap_or_default())) + ext_exception(format!( + "arrow failed to resolve method {}::{method}", + ce.name().unwrap_or_default() + )) }) } +/// `$object->$method(...$args)`; an exception the method throws surfaces as itself. +pub fn call_method(object: &Zval, method: &str, args: &mut [Zval]) -> Result { + let object = expect_object(object, "a method receiver")?; + let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("arrow failed to resolve an object class"))?; + + call_handle_transparent(ce_method_ref(ce, method)?, Some(object), args) +} + /// Calls a pre-resolved function handle and hands a PHP exception thrown by the callee back to the caller as the /// exception OBJECT, so the caller can surface it verbatim or replace it with one of its own. Taking it also clears /// the pending exception, leaving the engine ready for the next call. @@ -181,7 +195,7 @@ pub fn transparent_exception(exception: &mut ZendObject) -> PhpException { let mut zv = Zval::new(); zv.set_object(exception); - PhpException::default(String::new()).with_object(zv) + PhpException::from_message(String::new()).with_object(zv) } /// [`call_handle_catching`] with the exception object already re-raised as itself. @@ -264,7 +278,8 @@ pub fn ht_for_each<'a>( } pub fn expect_object<'a>(zv: &'a Zval, context: &str) -> Result<&'a ZendObject, PhpException> { - zv.object().ok_or_else(|| ext_exception(format!("arrow expected {context} to be an object"))) + zv.object() + .ok_or_else(|| ext_exception(format!("arrow expected {context} to be an object"))) } /// Request-scoped caches of class entries, function handles and value zvals, reached only through [`with_ctx`]: @@ -345,7 +360,12 @@ pub fn timezone(name: &[u8]) -> Result { || { let fns = timezone_fns()?; let mut timezone = ZendObject::new(fns.ce); - call_handle(fns.construct, Some(&mut timezone), &mut [zval_str(name)], "construct DateTimeZone")?; + call_handle( + fns.construct, + Some(&mut timezone), + &mut [zval_str(name)], + "construct DateTimeZone", + )?; let mut zv = Zval::new(); zv.set_object(&mut timezone); @@ -394,3 +414,52 @@ pub fn with_ctx(f: impl FnOnce(&mut Ctx) -> PhpResult) -> PhpResult { f(globals.ctx.get_or_insert_with(Ctx::default)) } + +/// An `iterable` argument kept as its zval. ext-php-rs's `Iterable` opens a `zend_object_iterator` for a `Traversable` +/// and 0.16 never frees it (no `zend_iterator_dtor`): the iterator and its generator lived until the request ended. +pub struct IterableArg<'a>(pub &'a Zval); + +impl<'a> FromZval<'a> for IterableArg<'a> { + const TYPE: DataType = DataType::Iterable; + + fn from_zval(zval: &'a Zval) -> Option { + (zval.is_array() || zval.is_traversable()).then_some(Self(zval)) + } +} + +/// Every value of `$iterable` in order, keys ignored: an `Iterator` through `rewind()` / `valid()` / `current()` / +/// `next()` as `foreach` does, an `IteratorAggregate` through `getIterator()`. +pub fn for_each_value(iterable: &Zval, mut f: impl FnMut(&Zval) -> PhpResult<()>) -> PhpResult<()> { + if let Some(array) = iterable.array() { + for value in array.values() { + f(value)?; + } + + return Ok(()); + } + + let mut iterator = iterable.shallow_clone(); + + while iterator + .object() + .is_some_and(|object| object.instance_of(ce::aggregate())) + { + iterator = call_method(&iterator, "getIterator", &mut [])?; + } + + if !iterator + .object() + .is_some_and(|object| object.instance_of(ce::iterator())) + { + return Err(ext_exception("arrow expected getIterator() to return a Traversable")); + } + + call_method(&iterator, "rewind", &mut [])?; + + while call_method(&iterator, "valid", &mut [])?.bool().unwrap_or(false) { + f(&call_method(&iterator, "current", &mut [])?)?; + call_method(&iterator, "next", &mut [])?; + } + + Ok(()) +} diff --git a/src/extension/arrow-ext/src/render.rs b/src/extension/arrow-ext/src/render.rs index 578414793d..030ec2f9ed 100644 --- a/src/extension/arrow-ext/src/render.rs +++ b/src/extension/arrow-ext/src/render.rs @@ -61,18 +61,30 @@ pub fn parquet_exception(error: Error, stream: &PhpStream, side: Side) -> PhpExc RUNTIME, format!("Parquet column \"{column}\" row {row} holds a value that is not {expected} bytes long"), ), - (Error::Value { column, row, expected, got }, _) => { - exception(VALIDATION, format!("Column \"{column}\" row {row}: expected {expected}, got {got}")) - } + ( + Error::Value { + column, + row, + expected, + got, + }, + _, + ) => exception( + VALIDATION, + format!("Column \"{column}\" row {row}: expected {expected}, got {got}"), + ), (Error::MapKey { column, key }, _) => exception( INVALID_ARGUMENT, format!("Map key of Parquet column \"{column}\" must be int or string, got {key}"), ), - (Error::MissingColumn(name), _) => exception(INVALID_ARGUMENT, format!("Parquet file has no column \"{name}\"")), - (Error::Options(message), _) => exception(INVALID_ARGUMENT, message), - (Error::NotParquet(message), _) => { - exception(INVALID_ARGUMENT, format!("Given file is not valid Parquet file: {message}")) + (Error::MissingColumn(name), _) => { + exception(INVALID_ARGUMENT, format!("Parquet file has no column \"{name}\"")) } + (Error::Options(message), _) => exception(INVALID_ARGUMENT, message), + (Error::NotParquet(message), _) => exception( + INVALID_ARGUMENT, + format!("Given file is not valid Parquet file: {message}"), + ), (Error::Stream(message), _) => failure(format!("arrow Parquet stream {message}")), (Error::Parquet(error), Side::Read) => failure(format!("arrow failed to read Parquet: {error}")), (Error::Arrow(error), Side::Read) => failure(format!("arrow failed to read Parquet: {error}")), diff --git a/src/extension/arrow-ext/src/stream/output_stream.rs b/src/extension/arrow-ext/src/stream/output_stream.rs index b2c53a254d..7b778f574f 100644 --- a/src/extension/arrow-ext/src/stream/output_stream.rs +++ b/src/extension/arrow-ext/src/stream/output_stream.rs @@ -1,19 +1,23 @@ -use ext_php_rs::args::Arg; +use ext_php_rs::args::{Arg, ArgInfoTables}; use ext_php_rs::builders::{ClassBuilder, FunctionBuilder}; use ext_php_rs::error::Result; use ext_php_rs::flags::{ClassFlags, DataType, MethodFlags}; use ext_php_rs::zend::ClassEntry; -fn noop(_ce: &'static mut ClassEntry) {} +use crate::interfaces::keep; + +fn store(_ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); +} pub fn register() -> Result<()> { ClassBuilder::new("Flow\\Arrow\\OutputStream") .flags(ClassFlags::Interface) - .registration(noop) + .registration(store) .method( FunctionBuilder::new_abstract("append") .arg(Arg::new("data", DataType::String)) - .returns(DataType::Object(Some("self")), false, false), + .returns(DataType::object("self"), false, false), MethodFlags::Public | MethodFlags::Abstract, ) .register()?; diff --git a/src/extension/arrow-ext/src/stream/random_access_file.rs b/src/extension/arrow-ext/src/stream/random_access_file.rs index cfd7a5f899..3bafba6ab8 100644 --- a/src/extension/arrow-ext/src/stream/random_access_file.rs +++ b/src/extension/arrow-ext/src/stream/random_access_file.rs @@ -1,15 +1,19 @@ -use ext_php_rs::args::Arg; +use ext_php_rs::args::{Arg, ArgInfoTables}; use ext_php_rs::builders::{ClassBuilder, FunctionBuilder}; use ext_php_rs::error::Result; use ext_php_rs::flags::{ClassFlags, DataType, MethodFlags}; use ext_php_rs::zend::ClassEntry; -fn noop(_ce: &'static mut ClassEntry) {} +use crate::interfaces::keep; + +fn store(_ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); +} pub fn register() -> Result<()> { ClassBuilder::new("Flow\\Arrow\\RandomAccessFile") .flags(ClassFlags::Interface) - .registration(noop) + .registration(store) .method( FunctionBuilder::new_abstract("read") .arg(Arg::new("length", DataType::Long)) diff --git a/src/extension/arrow-ext/src/thrift.rs b/src/extension/arrow-ext/src/thrift.rs index c896ec4bd7..b00d6d31ef 100644 --- a/src/extension/arrow-ext/src/thrift.rs +++ b/src/extension/arrow-ext/src/thrift.rs @@ -9,8 +9,8 @@ use ext_php_rs::exception::PhpException; use ext_php_rs::types::{ArrayKey, ZendHashTable, ZendObject, Zval}; use ext_php_rs::zend::ClassEntry; -use crate::php::{find_class, property_offset, with_ctx, zval_long, zval_str}; use crate::exception::ext_exception; +use crate::php::{find_class, property_offset, with_ctx, zval_long, zval_str}; /// Nesting deeper than this is refused instead of recursing further. const DEPTH: usize = 64; @@ -98,7 +98,9 @@ impl Specs { for (key, entry) in spec.iter() { let ArrayKey::Long(id) = key else { - return Err(ext_exception(format!("arrow requires {name}::$_TSPEC to be keyed by field id"))); + return Err(ext_exception(format!( + "arrow requires {name}::$_TSPEC to be keyed by field id" + ))); }; let entry = entry .array() @@ -127,7 +129,12 @@ impl Specs { } /// A `$_TSPEC` entry's type (`'type'`, with `'class'` for a struct and `'elem'` for a list's element). - fn value(&mut self, entry: &ZendHashTable, class: &str, seen: &mut HashMap) -> Result { + fn value( + &mut self, + entry: &ZendHashTable, + class: &str, + seen: &mut HashMap, + ) -> Result { let unsupported = |what: String| ext_exception(format!("arrow cannot decode {class}::$_TSPEC {what}")); // Thrift\Type\TType @@ -139,13 +146,15 @@ impl Specs { Some(8) => Value::I32, Some(10) => Value::I64, Some(11) => Value::String, - Some(12) => Value::Struct(self.class( - entry - .get("class") - .and_then(Zval::str) - .ok_or_else(|| unsupported("struct without a class".to_string()))?, - seen, - )?), + Some(12) => Value::Struct( + self.class( + entry + .get("class") + .and_then(Zval::str) + .ok_or_else(|| unsupported("struct without a class".to_string()))?, + seen, + )?, + ), Some(15) => Value::List(Box::new( self.value( entry @@ -211,7 +220,11 @@ impl Reader<'_> { } fn take(&mut self, length: usize) -> Result<&[u8], PhpException> { - let end = self.position.checked_add(length).filter(|end| *end <= self.bytes.len()).ok_or_else(truncated)?; + let end = self + .position + .checked_add(length) + .filter(|end| *end <= self.bytes.len()) + .ok_or_else(truncated)?; let taken = &self.bytes[self.position..end]; self.position = end; @@ -230,7 +243,9 @@ impl Reader<'_> { } } - Err(ext_exception("arrow failed to decode thrift: a varint longer than 10 bytes")) + Err(ext_exception( + "arrow failed to decode thrift: a varint longer than 10 bytes", + )) } fn zigzag(&mut self) -> Result { @@ -314,7 +329,11 @@ impl Reader<'_> { self.skip(wire, depth + 1)?; } } - other => return Err(ext_exception(format!("arrow failed to decode thrift: compact type {other}"))), + other => { + return Err(ext_exception(format!( + "arrow failed to decode thrift: compact type {other}" + ))) + } } Ok(()) @@ -329,11 +348,22 @@ impl Reader<'_> { } /// A value of type `value` that arrived as `wire`; `element`: inside a list, where a bool is a byte. - fn value(&mut self, specs: &Specs, value: &Value, wire: u8, element: bool, depth: usize) -> Result, PhpException> { + fn value( + &mut self, + specs: &Specs, + value: &Value, + wire: u8, + element: bool, + depth: usize, + ) -> Result, PhpException> { let mut zv = Zval::new(); match value { - Value::Bool => zv.set_bool(if element { self.byte()? == BOOLEAN_TRUE } else { wire == BOOLEAN_TRUE }), + Value::Bool => zv.set_bool(if element { + self.byte()? == BOOLEAN_TRUE + } else { + wire == BOOLEAN_TRUE + }), Value::Byte => zv = zval_long(i64::from(self.byte()? as i8)), Value::I16 | Value::I32 | Value::I64 => zv = zval_long(self.zigzag()?), Value::Double => { @@ -419,13 +449,21 @@ impl Reader<'_> { } fn field_of(class: &Class, id: i16) -> Option<&(u32, Value)> { - usize::try_from(id).ok().and_then(|id| class.fields.get(id)).and_then(Option::as_ref) + usize::try_from(id) + .ok() + .and_then(|id| class.fields.get(id)) + .and_then(Option::as_ref) } /// Moves `value` into a declared-property slot, releasing what the slot held (null on a fresh object, an earlier /// value when a field id repeats). fn replace_slot(object: &mut ZendObject, offset: u32, value: Zval) { - let slot = unsafe { std::ptr::from_mut(object).cast::().add(offset as usize).cast::() }; + let slot = unsafe { + std::ptr::from_mut(object) + .cast::() + .add(offset as usize) + .cast::() + }; drop(unsafe { std::ptr::replace(slot, value) }); } diff --git a/src/extension/arrow-ext/src/values.rs b/src/extension/arrow-ext/src/values.rs index 0fc00d70b0..4bb8fb3020 100644 --- a/src/extension/arrow-ext/src/values.rs +++ b/src/extension/arrow-ext/src/values.rs @@ -122,7 +122,11 @@ fn days_from_civil(year: i64, month: i64, day: i64) -> Option { } /// A fresh `DateTimeImmutable` initialised by `init` over its `php_date_obj`, then moved into `zone`. -fn datetime_in(zone: &[u8], init: impl FnOnce(*mut c_void) -> bool, failure: impl FnOnce() -> PhpException) -> Result { +fn datetime_in( + zone: &[u8], + init: impl FnOnce(*mut c_void) -> bool, + failure: impl FnOnce() -> PhpException, +) -> Result { let fns = php::datetime_immutable()?; let mut datetime = Zval::new(); @@ -141,7 +145,12 @@ fn datetime_in(zone: &[u8], init: impl FnOnce(*mut c_void) -> bool, failure: imp return Err(failure()); } - let datetime = call_handle(fns.set_timezone, Some(datetime_obj), &mut [php::timezone(zone)?], "restore a datetime timezone")?; + let datetime = call_handle( + fns.set_timezone, + Some(datetime_obj), + &mut [php::timezone(zone)?], + "restore a datetime timezone", + )?; if !datetime.is_object() { return Err(ext_exception("arrow expected setTimezone to return a datetime object")); @@ -185,7 +194,11 @@ pub fn datetime_from_micros(micros: i64, zone: &[u8]) -> Result Vec { /// `hex2bin()` of a 36-char uuid with its dashes removed. pub fn uuid_bytes(text: &[u8]) -> Option<[u8; 16]> { let mut bytes = [0u8; 16]; - let mut digits = text.iter().filter(|byte| **byte != b'-').map(|byte| (*byte as char).to_digit(16)); + let mut digits = text + .iter() + .filter(|byte| **byte != b'-') + .map(|byte| (*byte as char).to_digit(16)); for byte in &mut bytes { let high = digits.next()??; diff --git a/src/extension/arrow-ext/tests/phpt/001_extension_loaded.phpt b/src/extension/arrow-ext/tests/phpt/001_extension_loaded.phpt index df5261568f..80f841ba90 100644 --- a/src/extension/arrow-ext/tests/phpt/001_extension_loaded.phpt +++ b/src/extension/arrow-ext/tests/phpt/001_extension_loaded.phpt @@ -6,7 +6,7 @@ arrow extension is loaded and the Parquet and Arrow C Data classes are registere isInternal() ? 'internal' : 'userland', ', ', $r->isFinal() ? 'final' : 'open', "\n"; } @@ -15,7 +15,7 @@ foreach (['Flow\Arrow\Parquet\Reader', 'Flow\Arrow\Parquet\Writer', 'Flow\Arrow\ var_dump(class_exists($class, false)); } -foreach (['Flow\Arrow\ArrowBatch', 'Flow\Arrow\ArrowSchema'] as $class) { +foreach (['Flow\Arrow\RustParquetBatch', 'Flow\Arrow\RustArrowSchema'] as $class) { try { new $class(); } catch (Throwable $e) { @@ -25,14 +25,15 @@ foreach (['Flow\Arrow\ArrowBatch', 'Flow\Arrow\ArrowSchema'] as $class) { ?> --EXPECT-- bool(true) -Flow\Arrow\Parquet\ParquetFile: internal, final -Flow\Arrow\Parquet\ColumnsReader: internal, final -Flow\Arrow\Parquet\RowsWriter: internal, final -Flow\Arrow\Parquet\BatchReader: internal, final -Flow\Arrow\ArrowBatch: internal, final -Flow\Arrow\ArrowSchema: internal, final +Flow\Parquet\Engine\RustParquetEngine: internal, final +Flow\Parquet\Engine\RustParquetFileReader: internal, final +Flow\Arrow\Parquet\RustColumnsReader: internal, final +Flow\Parquet\Engine\RustParquetFileWriter: internal, final +Flow\Arrow\Parquet\RustBatchReader: internal, final +Flow\Arrow\RustParquetBatch: internal, final +Flow\Arrow\RustArrowSchema: internal, final bool(false) bool(false) bool(false) -Flow\Arrow\ArrowBatch: You cannot instantiate this class from PHP. -Flow\Arrow\ArrowSchema: You cannot instantiate this class from PHP. +Flow\Arrow\RustParquetBatch: You cannot instantiate this class from PHP. +Flow\Arrow\RustArrowSchema: You cannot instantiate this class from PHP. diff --git a/src/extension/arrow-ext/tests/phpt/045_parquet_lib_read_parity.phpt b/src/extension/arrow-ext/tests/phpt/045_parquet_lib_read_parity.phpt index 7e01bcfe70..a7ce94a2ff 100644 --- a/src/extension/arrow-ext/tests/phpt/045_parquet_lib_read_parity.phpt +++ b/src/extension/arrow-ext/tests/phpt/045_parquet_lib_read_parity.phpt @@ -1,11 +1,12 @@ --TEST-- -Reader::arrow() on arrow reads every lib Parquet fixture as Reader::php() does, both refuse it, or it refuses naming Reader::php() +new Reader(engine: new RustParquetEngine()) on arrow reads every lib Parquet fixture as Reader::php() does, both refuse it, or it refuses naming Reader::php() --SKIPIF-- --FILE-- ParquetRows::read(Reader::php()->read($file), $batchSize)); - $native = arrow_outcome(static fn() => ParquetRows::read(Reader::arrow()->read($file), $batchSize)); + $native = arrow_outcome(static fn() => ParquetRows::read((new Reader(engine: new RustParquetEngine()))->read($file), $batchSize)); $name = substr($file, strlen($fixtures) + 1) . ' ' . $batchSize; echo match (true) { @@ -32,10 +33,10 @@ foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.p } $interval = $fixtures . '/EdgeCases/interval.parquet'; -echo 'interval.parquet [id]: ', arrow_outcome(static fn() => ParquetRows::read(Reader::php()->read($interval), 10, ['id'])) === arrow_outcome(static fn() => ParquetRows::read(Reader::arrow()->read($interval), 10, ['id'])) ? 'identical' : 'DIFFER', "\n"; +echo 'interval.parquet [id]: ', arrow_outcome(static fn() => ParquetRows::read(Reader::php()->read($interval), 10, ['id'])) === arrow_outcome(static fn() => ParquetRows::read((new Reader(engine: new RustParquetEngine()))->read($interval), 10, ['id'])) ? 'identical' : 'DIFFER', "\n"; $everyType = MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows()); -echo 'every type: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), $everyType), 2)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $everyType), 2)) ? 'identical' : 'DIFFER', "\n"; +echo 'every type: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), $everyType), 2)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $everyType), 2)) ? 'identical' : 'DIFFER', "\n"; // pre-epoch timestamps with a sub-second fraction are floored, flat and inside a list $preEpoch = MemoryParquetFile::written( @@ -46,9 +47,9 @@ $preEpoch = MemoryParquetFile::written( [(new DateTimeImmutable('@0'))->modify('-1500000 microseconds'), (new DateTimeImmutable('@0'))->modify('-1 microsecond'), new DateTimeImmutable('2020-01-02 03:04:05.678901 UTC')], ), ); -echo 'pre-epoch timestamps: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), $preEpoch), 3)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $preEpoch), 3)) ? 'identical' : 'DIFFER', "\n"; +echo 'pre-epoch timestamps: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), $preEpoch), 3)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $preEpoch), 3)) ? 'identical' : 'DIFFER', "\n"; -foreach (ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $preEpoch), 3) as $row) { +foreach (ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $preEpoch), 3) as $row) { echo $row['ts']->format('Y-m-d H:i:s.u'), ' ', $row['ts_list'][0]->format('Y-m-d H:i:s.u'), "\n"; } ?> diff --git a/src/extension/arrow-ext/tests/phpt/046_parquet_lib_write_parity.phpt b/src/extension/arrow-ext/tests/phpt/046_parquet_lib_write_parity.phpt index 6afae60859..a5da1e1e67 100644 --- a/src/extension/arrow-ext/tests/phpt/046_parquet_lib_write_parity.phpt +++ b/src/extension/arrow-ext/tests/phpt/046_parquet_lib_write_parity.phpt @@ -1,11 +1,12 @@ --TEST-- -Writer::arrow() on arrow accepts and refuses what Writer::php() does per target type, and what both accept reads back the same +new Writer(engine: new RustParquetEngine()) on arrow accepts and refuses what Writer::php() does per target type, and what both accept reads back the same --SKIPIF-- --FILE-- WriteAcceptance::input($input)]]), ), 1)); $php = $read(Writer::php()); - $native = $read(Writer::arrow()); + $native = $read(new Writer(engine: new RustParquetEngine())); $cells++; match (true) { @@ -35,7 +36,7 @@ foreach (WriteAcceptance::targets() as $target) { } echo "{$cells} cells: {$accepted} accepted by both, {$refused} refused by both\n"; -echo 'every type: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows())), 3)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::arrow(), EveryType::schema(), EveryType::rows())), 3)) ? 'identical' : 'DIFFER', "\n"; +echo 'every type: ', arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows())), 3)) === arrow_outcome(static fn() => ParquetRows::read(MemoryParquetFile::read(Reader::php(), MemoryParquetFile::written(new Writer(engine: new RustParquetEngine()), EveryType::schema(), EveryType::rows())), 3)) ? 'identical' : 'DIFFER', "\n"; ?> --EXPECT-- 624 cells: 102 accepted by both, 522 refused by both diff --git a/src/extension/arrow-ext/tests/phpt/047_parquet_footer_thrift_parity.phpt b/src/extension/arrow-ext/tests/phpt/047_parquet_footer_thrift_parity.phpt index 66b5f6d83c..ee944b0629 100644 --- a/src/extension/arrow-ext/tests/phpt/047_parquet_footer_thrift_parity.phpt +++ b/src/extension/arrow-ext/tests/phpt/047_parquet_footer_thrift_parity.phpt @@ -1,5 +1,5 @@ --TEST-- -ParquetFile decodes the footer to the FileMetaData and schema the PHP thrift reader builds, from one footer read +RustParquetFileReader decodes the footer to the FileMetaData and schema the PHP thrift reader builds, from one footer read --SKIPIF-- --FILE-- @@ -13,7 +13,7 @@ use Flow\Parquet\ParquetFile\Schema\LogicalType\{Time, Timestamp}; use Flow\Parquet\ParquetFile\Schema\TimeUnit; use Flow\Parquet\Tests\Context\MemoryParquetFile; use Flow\Parquet\Writer; -use Flow\Arrow\Parquet\ParquetFile; +use Flow\Parquet\Engine\RustParquetFileReader; use Flow\Parquet\Tests\Double\ReadCountingSourceStream; use Flow\Parquet\Thrift\{CompactProtocol, MemoryBuffer}; use Flow\Parquet\ThriftModel\FileMetaData; @@ -29,14 +29,14 @@ foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.p $php->read(new CompactProtocol(new MemoryBuffer(substr($bytes, -8 - $length, $length)))); $stream = new ReadCountingSourceStream(NativeLocalSourceStream::open(path_real($path))); - $file = new ParquetFile($stream); + $file = new RustParquetFileReader($stream); $reads = $stream->reads; printf( "%s: thrift %s, schema %s, footer reads %d\n", substr($path, strlen($fixtures) + 1), serialize($file->thrift()) === serialize($php) ? 'identical' : 'DIFFER', - serialize($file->schema()) === serialize($php->schema) ? 'identical' : 'DIFFER', + serialize($file->schema()) === serialize(Schema::fromThrift($php->schema)) ? 'identical' : 'DIFFER', $reads, ); $file->close(); @@ -53,12 +53,12 @@ $units = MemoryParquetFile::written(Writer::php(), Schema::with( $length = unpack('V', substr($units, -8, 4))[1]; $php = new FileMetaData(); $php->read(new CompactProtocol(new MemoryBuffer(substr($units, -8 - $length, $length)))); -$file = new ParquetFile(new MemorySourceStream($units)); +$file = new RustParquetFileReader(new MemorySourceStream($units)); printf( "temporal units: thrift %s, schema %s\n", serialize($file->thrift()) === serialize($php) ? 'identical' : 'DIFFER', - serialize($file->schema()) === serialize($php->schema) ? 'identical' : 'DIFFER', + serialize($file->schema()) === serialize(Schema::fromThrift($php->schema)) ? 'identical' : 'DIFFER', ); $file->close(); ?> diff --git a/src/extension/arrow-ext/tests/phpt/048_parquet_lib_no_leaks.phpt b/src/extension/arrow-ext/tests/phpt/048_parquet_lib_no_leaks.phpt index d9593251ca..d59a7583b7 100644 --- a/src/extension/arrow-ext/tests/phpt/048_parquet_lib_no_leaks.phpt +++ b/src/extension/arrow-ext/tests/phpt/048_parquet_lib_no_leaks.phpt @@ -1,5 +1,5 @@ --TEST-- -ParquetFile, ColumnsReader and RowsWriter leak no PHP memory, refusals included +RustParquetFileReader, RustColumnsReader and RustParquetFileWriter leak no PHP memory, refusals and Traversable batches included --SKIPIF-- --FILE-- @@ -7,9 +7,11 @@ ParquetFile, ColumnsReader and RowsWriter leak no PHP memory, refusals included require __DIR__ . '/bootstrap.php'; use Flow\Parquet\Engine\Arrow\{OptionsConverter, SchemaConverter}; -use Flow\Arrow\Parquet\{ColumnsReader, ParquetFile, RowsWriter}; +use Flow\Arrow\Parquet\RustColumnsReader; +use Flow\Parquet\Engine\{RustParquetFileReader, RustParquetFileWriter}; use Flow\Parquet\Options; use Flow\Parquet\Tests\Context\EveryType; +use Flow\Parquet\ParquetFile\Compressions; use function Flow\Filesystem\DSL\{memory_filesystem, path}; @@ -20,9 +22,13 @@ $columns = array_map(static fn($column) => $column->name(), EveryType::schema()- $cycle = static function () use ($schema, $options, $rows, $columns): void { $filesystem = memory_filesystem(); - $writer = new RowsWriter($filesystem->writeTo(path('memory://leaks.parquet')), $schema, 'SNAPPY', $options, 2); + $writer = new RustParquetFileWriter($filesystem->writeTo(path('memory://leaks.parquet')), $schema, Compressions::SNAPPY, $options, 2); $writer->writeRows($rows); $writer->writeRow($rows[0]); + $writer->writeBatch((static function () use ($rows): Generator { + yield from $rows; + })()); + $writer->writeBatch(new ArrayIterator($rows)); try { $writer->writeRow(['int32' => 'not an int']); @@ -32,27 +38,31 @@ $cycle = static function () use ($schema, $options, $rows, $columns): void { $writer->close(); - $file = new ParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))); + $file = new RustParquetFileReader($filesystem->readFrom(path('memory://leaks.parquet'))); $file->thrift(); $file->schema(); - $reader = new ColumnsReader($file, $columns, 2, 1, 3); + $file->metadata(); - while ($reader->next() !== null) { + foreach (new RustColumnsReader($file, $columns, 2, 1, 3) as $chunk) { + } + + foreach ($file->readColumns($columns, 2, 3, 1) as $chunk) { } try { - new ColumnsReader($file, ['missing'], 2, null, null); + new RustColumnsReader($file, ['missing'], 2, null, null); throw new LogicException('a missing column was read'); } catch (Flow\Parquet\Exception\InvalidArgumentException) { } $file->close(); - $abandoned = new RowsWriter($filesystem->writeTo(path('memory://abandoned.parquet')), $schema, 'SNAPPY', $options, 2); + $abandoned = new RustParquetFileWriter($filesystem->writeTo(path('memory://abandoned.parquet')), $schema, Compressions::SNAPPY, $options, 2); $abandoned->writeRows($rows); }; -for ($i = 0; $i < 10; $i++) { +// Schema::fromThrift() / Metadata::fromThrift() warm the allocator up once, whoever calls them +for ($i = 0; $i < 100; $i++) { $cycle(); } gc_collect_cycles(); diff --git a/src/extension/arrow-ext/tests/phpt/049_parquet_write_columns_parity.phpt b/src/extension/arrow-ext/tests/phpt/049_parquet_write_columns_parity.phpt index 3418916eb2..7b1543897a 100644 --- a/src/extension/arrow-ext/tests/phpt/049_parquet_write_columns_parity.phpt +++ b/src/extension/arrow-ext/tests/phpt/049_parquet_write_columns_parity.phpt @@ -1,12 +1,12 @@ --TEST-- -RowsWriter::writeColumns() accepts, refuses and keeps what writeRows() does, for every write-acceptance cell and across flushed batches +RustParquetFileWriter::writeColumns() accepts, refuses and keeps what writeRows() does, for every write-acceptance cell and across flushed batches --SKIPIF-- --FILE-- set(Option::ARROW_WRITE_BATCH_SIZE, $batchSize)), $stream, $schema); + $file = ColumnDoor::open(new RustParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, $batchSize)), $stream, $schema); $refusal = 'written'; try { @@ -74,18 +74,18 @@ foreach ([1_000, 3, 2, 1] as $batchSize) { $columns = ColumnDoor::columns(ColumnDoor::rows(50)); $batch = ColumnDoor::stream(); -$file = ColumnDoor::open(new ArrowParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 7)), $batch, ColumnDoor::schema()); +$file = ColumnDoor::open(new RustParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 7)), $batch, ColumnDoor::schema()); $file->writeBatch(ColumnDoor::rows(50)); $file->close(); $door = ColumnDoor::stream(); -$file = ColumnDoor::open(new ArrowParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 7)), $door, ColumnDoor::schema()); +$file = ColumnDoor::open(new RustParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 7)), $door, ColumnDoor::schema()); $file->writeColumns($columns); $file->close(); var_dump($batch->content() === $door->content()); foreach ([['a' => [1, 2], 'b' => [1]], ['a' => 'no list']] as $columns) { try { - ColumnDoor::open(new ArrowParquetEngine(), ColumnDoor::stream(), $schema)->writeColumns($columns); + ColumnDoor::open(new RustParquetEngine(), ColumnDoor::stream(), $schema)->writeColumns($columns); } catch (Throwable $e) { echo $e::class, ': ', $e->getMessage(), "\n"; } diff --git a/src/extension/arrow-ext/tests/phpt/050_parquet_batch_roundtrip.phpt b/src/extension/arrow-ext/tests/phpt/050_parquet_batch_roundtrip.phpt index c8365071ea..95aa5e661f 100644 --- a/src/extension/arrow-ext/tests/phpt/050_parquet_batch_roundtrip.phpt +++ b/src/extension/arrow-ext/tests/phpt/050_parquet_batch_roundtrip.phpt @@ -1,18 +1,20 @@ --TEST-- -BatchReader batches written back through RowsWriter::writeBatch() read as the file; writer columns the batch lacks are nulls, children the writer lacks are ignored, a batch imports once, userland objects are refused, nothing leaks +RustBatchReader batches written back through RustParquetFileWriter::writeArrowBatch() read as the file; writer columns the batch lacks are nulls, children the writer lacks are ignored, a batch imports once, userland objects are refused, nothing leaks --SKIPIF-- --FILE-- ['id' => $i, 'name' => $i % 3 ? "name {$i}" : null, 'tags' => $i % 4 ? [$i, $i + 1] : null], range(0, 249)); $roundTrip = static function (Filesystem $filesystem) use ($source, $target, $options, $rows): array { - $writer = new RowsWriter($filesystem->writeTo(path('memory://source.parquet')), SchemaConverter::toExtension($source), 'SNAPPY', $options, 100); + $writer = new RustParquetFileWriter($filesystem->writeTo(path('memory://source.parquet')), SchemaConverter::toExtension($source), Compressions::SNAPPY, $options, 100); $writer->writeRows($rows); $writer->close(); - $batches = new BatchReader(new ParquetFile($filesystem->readFrom(path('memory://source.parquet'))), ['id', 'name', 'tags'], 100, null, null); + $batches = new RustBatchReader(new RustParquetFileReader($filesystem->readFrom(path('memory://source.parquet'))), ['id', 'name', 'tags'], 100, null, null); $schema = $batches->schema(); - $copy = new RowsWriter($filesystem->writeTo(path('memory://copy.parquet')), SchemaConverter::toExtension($target), 'SNAPPY', $options, 100); + $copy = new RustParquetFileWriter($filesystem->writeTo(path('memory://copy.parquet')), SchemaConverter::toExtension($target), Compressions::SNAPPY, $options, 100); $counts = []; while (($batch = $batches->next()) !== null) { $counts[] = $batch->count(); - $copy->writeBatch($batch); + $copy->writeArrowBatch($batch); } $copy->close(); @@ -62,12 +64,12 @@ echo get_class($schema), ' ', $schema->arrowSchemaAddress() > 0 ? 'has an addres echo 'batches: ', implode(',', $counts), "\n"; echo 'round trip: ', iterator_to_array(Reader::php()->readStream($filesystem->readFrom(path('memory://copy.parquet')))->values(), false) === $expected ? 'identical' : 'DIFFER', "\n"; -$batches = new BatchReader(new ParquetFile($filesystem->readFrom(path('memory://source.parquet'))), ['id', 'name', 'tags'], 100, null, null); +$batches = new RustBatchReader(new RustParquetFileReader($filesystem->readFrom(path('memory://source.parquet'))), ['id', 'name', 'tags'], 100, null, null); $batch = $batches->next(); -$twice = new RowsWriter($filesystem->writeTo(path('memory://twice.parquet')), SchemaConverter::toExtension($target), 'SNAPPY', $options, 100); -$twice->writeBatch($batch); -echo arrow_outcome(static fn() => $twice->writeBatch($batch)), "\n"; -echo arrow_outcome(static fn() => $twice->writeBatch(new UserlandBatch())), "\n"; +$twice = new RustParquetFileWriter($filesystem->writeTo(path('memory://twice.parquet')), SchemaConverter::toExtension($target), Compressions::SNAPPY, $options, 100); +$twice->writeArrowBatch($batch); +echo arrow_outcome(static fn() => $twice->writeArrowBatch($batch)), "\n"; +echo arrow_outcome(static fn() => $twice->writeArrowBatch(new UserlandBatch())), "\n"; $twice->close(); for ($i = 0; $i < 10; $i++) { @@ -84,7 +86,7 @@ gc_collect_cycles(); var_dump(memory_get_usage(false) <= $baseline); ?> --EXPECT-- -Flow\Arrow\ArrowSchema has an address +Flow\Arrow\RustArrowSchema has an address batches: 100,100,50 round trip: identical Flow\Parquet\Exception\InvalidArgumentException: Arrow C Data batch is already imported diff --git a/src/extension/arrow-ext/tests/phpt/051_parquet_interfaces_reflection.phpt b/src/extension/arrow-ext/tests/phpt/051_parquet_interfaces_reflection.phpt new file mode 100644 index 0000000000..0d36a79f09 --- /dev/null +++ b/src/extension/arrow-ext/tests/phpt/051_parquet_interfaces_reflection.phpt @@ -0,0 +1,26 @@ +--TEST-- +arrow registers the flow-php/parquet and Arrow stream interfaces reflection-identical to the package files +--SKIPIF-- + +--FILE-- +getParameters()[$position]->getType(), "\n"; +} +?> +--EXPECT-- +library reflected +identical +Flow\Parquet\ParquetEngine::writeRows: iterable +Flow\Parquet\ParquetFileWriter::writeBatch: iterable diff --git a/src/extension/arrow-ext/tests/phpt/052_parquet_file_reader_writer_contracts.phpt b/src/extension/arrow-ext/tests/phpt/052_parquet_file_reader_writer_contracts.phpt new file mode 100644 index 0000000000..d047472fdf --- /dev/null +++ b/src/extension/arrow-ext/tests/phpt/052_parquet_file_reader_writer_contracts.phpt @@ -0,0 +1,201 @@ +--TEST-- +RustParquetFileReader implements ParquetFileReader and RustParquetFileWriter implements ParquetFileWriter: the lib's metadata and schema, RustColumnsReader as an Iterator that streams once, INT96 and LZO refusals, closed reader and writer texts +--SKIPIF-- + +--FILE-- + new RustParquetFileReader( + NativeLocalSourceStream::open(path_real("{$fixtures}/{$name}")), + $int96AsDatetime, +); + +echo "-- reader\n"; +$file = $open('structs.parquet'); +$metadata = $file->metadata(); +$bytes = array_sum(array_map(static fn($group): int => $group->totalByteSize(), $metadata->rowGroups()->all())); +var_dump($file instanceof ParquetFileReader); +var_dump(serialize($metadata) === serialize(Reader::php()->read("{$fixtures}/structs.parquet")->metadata())); +var_dump(serialize($open('structs.parquet')->schema()) === serialize($metadata->schema()), $file->schema() === $metadata->schema()); +var_dump($file->rowsNumber() === $metadata->rowsNumber(), $file->totalByteSize() === $bytes); + +$chunks = $file->readColumns(['struct_flat', 'struct_flat.int'], 30, 70, 5); +$php = (new PhpParquetEngine(ByteOrder::LITTLE_ENDIAN, new Options())) + ->openForRead(NativeLocalSourceStream::open(path_real("{$fixtures}/structs.parquet"))) + ->readColumns(['struct_flat', 'struct_flat.int'], 30, 70, 5); +var_dump($chunks instanceof Iterator); +$read = []; + +foreach ($chunks as $key => $chunk) { + $read[$key] = $chunk; +} + +echo json_encode(array_map(static fn(array $chunk): int => count($chunk['struct_flat.int']), $read)), "\n"; +var_dump($read == iterator_to_array($php)); +echo arrow_outcome(static fn() => $chunks->rewind()), "\n"; +echo arrow_outcome(static fn() => iterator_to_array($open('EdgeCases/int96.parquet', false)->readColumns(['ts'], 10, null, null))), "\n"; +var_dump(count(iterator_to_array($open('EdgeCases/int96.parquet')->readColumns(['ts'], 10, null, null))) > 0); +echo arrow_outcome(static fn() => $open('lists.parquet')->readColumns(['list.list.element'], 10, null, null)), "\n"; +echo arrow_outcome(static fn() => new RustParquetFileReader(new MemorySourceStream('{"not": "parquet"}'))), "\n"; + +$file->close(); + +foreach ([ + static fn() => $file->metadata(), + static fn() => $file->schema(), + static fn() => $file->rowsNumber(), + static fn() => $file->totalByteSize(), + static fn() => $file->thrift(), + static fn() => $file->readColumns(['struct_flat'], 1, null, null), + static fn() => $file->close(), +] as $call) { + echo arrow_outcome($call), "\n"; +} + +echo "-- writer\n"; +$filesystem = memory_filesystem(); +$schema = Schema::with(FlatColumn::int32('id'), FlatColumn::string('name')); +$writer = static fn($stream, Compressions $compression = Compressions::SNAPPY, int $batchSize = 1_000): RustParquetFileWriter => new RustParquetFileWriter( + $stream, + SchemaConverter::toExtension($schema), + $compression, + OptionsConverter::toExtension(new Options()), + $batchSize, +); +$values = static fn(string $uri): string => json_encode(iterator_to_array(Reader::php()->readStream($filesystem->readFrom(path($uri)))->values(), false)); + +$file = $writer($filesystem->writeTo(path('memory://doors.parquet')), Compressions::LZ4, 2); +var_dump($file instanceof ParquetFileWriter); +$file->writeRow(['id' => 1]); +$file->writeBatch([['id' => 2], 'key' => ['id' => 3, 'name' => 'c']]); +$file->writeBatch((static function () { + yield ['id' => 4]; + yield 'key' => ['id' => 5]; +})()); +echo arrow_outcome(static fn() => $file->writeRow(['id' => 'six'])), "\n"; +$file->writeBatch(new ArrayIterator([['id' => 6]])); +$file->writeColumns(['id' => [7, 8], 'unknown' => ['x', 'y']]); +echo arrow_outcome(static fn() => $file->writeBatch((static function () { + yield ['id' => 9]; + + throw new LogicException('the rows ran out'); +})())), "\n"; +$file->close(); +echo $values('memory://doors.parquet'), "\n"; + +foreach ([ + static fn() => $file->writeRow(['id' => 1]), + static fn() => $file->writeRows([['id' => 1]]), + static fn() => $file->writeBatch([]), + static fn() => $file->writeBatch(new ArrayIterator([['id' => 1]])), + static fn() => $file->writeColumns(['id' => [1]]), + static fn() => $file->close(), +] as $call) { + echo arrow_outcome($call), "\n"; +} + +$failing = $writer(new FailingCloseDestinationStream($filesystem->writeTo(path('memory://failing.parquet')))); +echo arrow_outcome(static fn() => $failing->close()), "\n"; +echo arrow_outcome(static fn() => $failing->close()), "\n"; +// a refused flush still closes the stream; the flush's refusal is the one thrown +$inner = new class($filesystem->writeTo(path('memory://append.parquet'))) implements Flow\Filesystem\DestinationStream { + public bool $closed = false; + + public function __construct(private Flow\Filesystem\DestinationStream $stream) {} + + public function append(string $data): self + { + $this->stream->append($data); + + return $this; + } + + public function close(): void + { + $this->closed = true; + } + + public function fromResource($resource): self + { + return $this; + } + + public function isOpen(): bool + { + return !$this->closed; + } + + public function path(): Flow\Filesystem\Path + { + return $this->stream->path(); + } +}; +$appending = $writer(new FailingAppendDestinationStream($inner)); +$appending->writeRow(['id' => 1, 'name' => 'a']); +echo arrow_outcome(static fn() => $appending->close()), "\n"; +var_dump($inner->closed); +echo arrow_outcome(static fn() => $writer($filesystem->writeTo(path('memory://lzo.parquet')), Compressions::LZO)), "\n"; +?> +--EXPECT-- +-- reader +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +[30,30,10] +bool(true) +Flow\Parquet\Exception\RuntimeException: RustColumnsReader cannot rewind +Flow\Parquet\Exception\InvalidArgumentException: Parquet column "ts" holds INT96, which arrow reads only as a datetime (Option::INT_96_AS_DATETIME = true); read the file with \Flow\Parquet\Reader::php() +bool(true) +Flow\Parquet\Exception\RuntimeException: Parquet column "list.list.element" (a path into LIST/MAP) is not supported by the arrow Parquet reader; read the file with \Flow\Parquet\Reader::php() +Flow\Parquet\Exception\InvalidArgumentException: Given file is not valid Parquet file: Invalid Parquet file. Corrupt footer +Flow\Parquet\Exception\RuntimeException: Reader is not open +Flow\Parquet\Exception\RuntimeException: Reader is not open +Flow\Parquet\Exception\RuntimeException: Reader is not open +Flow\Parquet\Exception\RuntimeException: Reader is not open +Flow\Parquet\Exception\RuntimeException: Reader is not open +Flow\Parquet\Exception\RuntimeException: Reader is not open +Flow\Parquet\Exception\RuntimeException: Reader is not open +-- writer +bool(true) +Flow\Parquet\Exception\ValidationException: Column "id" row 1: expected int, got string +LogicException: the rows ran out +[{"id":1,"name":null},{"id":2,"name":null},{"id":3,"name":"c"},{"id":4,"name":null},{"id":5,"name":null},{"id":6,"name":null},{"id":7,"name":null},{"id":8,"name":null},{"id":9,"name":null}] +Flow\Parquet\Exception\RuntimeException: Writer is not open +Flow\Parquet\Exception\RuntimeException: Writer is not open +Flow\Parquet\Exception\RuntimeException: Writer is not open +Flow\Parquet\Exception\RuntimeException: Writer is not open +Flow\Parquet\Exception\RuntimeException: Writer is not open +Flow\Parquet\Exception\RuntimeException: Writer is not open +Flow\Filesystem\Exception\RuntimeException: Closing "memory://failing.parquet" failed +Flow\Parquet\Exception\RuntimeException: Writer is not open +Flow\Filesystem\Exception\RuntimeException: Appending to "memory://append.parquet" failed +bool(true) +Flow\Parquet\Exception\RuntimeException: LZO compression is not supported by the Arrow engine diff --git a/src/extension/arrow-ext/tests/phpt/053_columns_reader_refusal_ends.phpt b/src/extension/arrow-ext/tests/phpt/053_columns_reader_refusal_ends.phpt new file mode 100644 index 0000000000..100fc339a7 --- /dev/null +++ b/src/extension/arrow-ext/tests/phpt/053_columns_reader_refusal_ends.phpt @@ -0,0 +1,74 @@ +--TEST-- +RustColumnsReader behaves as a Generator: it starts on first use, a refused chunk ends it for good (valid() false, key() and current() null, next() a no-op) and rewind() is refused only after next() +--SKIPIF-- + +--FILE-- +set(Option::ROW_GROUP_SIZE_BYTES, 1)->set(Option::ROW_GROUP_SIZE_CHECK_INTERVAL, 2); +$writer = new Writer(options: $options, engine: new PhpParquetEngine(options: $options)); +$writer->openForStream($filesystem->writeTo(path('memory://groups.parquet')), Schema::with(FlatColumn::int64('id'))); +$writer->writeBatch([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]]); +$writer->close(); + +$bytes = $filesystem->readFrom(path('memory://groups.parquet'))->content(); +$open = static fn(string $bytes): RustParquetFileReader => new RustParquetFileReader(new StringSourceStream(path('memory://groups.parquet'), $bytes)); +$chunk = $open($bytes)->metadata()->rowGroups()->all()[1]->columnChunks()[0]; +$corrupt = substr_replace($bytes, str_repeat("\xFF", $chunk->totalCompressedSize()), $chunk->pageOffset(), $chunk->totalCompressedSize()); + +$step = static function (string $label, callable $call): void { + try { + $result = json_encode($call()); + } catch (Throwable) { + $result = 'threw'; + } + + echo $label, ': ', $result, "\n"; +}; + +$reader = new RustColumnsReader($open($corrupt), ['id'], 2, null, null); +$step('key before rewind', static fn() => $reader->key()); +$step('current', static fn() => $reader->current()); +$step('rewind', static fn() => $reader->rewind()); +$step('next (chunk refused)', static fn() => $reader->next()); +$step('valid', static fn() => $reader->valid()); +$step('key', static fn() => $reader->key()); +$step('current', static fn() => $reader->current()); +$step('next', static fn() => $reader->next()); +$step('rewind', static fn() => $reader->rewind()); + +// refused before the first chunk: rewind() throws once, then the reader is empty and rewinds freely +$corrupt = substr_replace($bytes, str_repeat("\xFF", 8), 4, 8); +$reader = new RustColumnsReader($open($corrupt), ['id'], 2, null, null); +$step('rewind (chunk refused)', static fn() => $reader->rewind()); +$step('valid', static fn() => $reader->valid()); +$step('rewind', static fn() => $reader->rewind()); +?> +--EXPECT-- +key before rewind: 0 +current: {"id":[1,2]} +rewind: null +next (chunk refused): threw +valid: false +key: null +current: null +next: null +rewind: threw +rewind (chunk refused): threw +valid: false +rewind: null diff --git a/src/extension/arrow-ext/tests/phpt/bootstrap.php b/src/extension/arrow-ext/tests/phpt/bootstrap.php index 3f38445793..09a08cc646 100644 --- a/src/extension/arrow-ext/tests/phpt/bootstrap.php +++ b/src/extension/arrow-ext/tests/phpt/bootstrap.php @@ -30,3 +30,37 @@ function arrow_refused(string $outcome): bool { return (bool) preg_match('/^[A-Za-z\\\\]+(Exception|Error|Overflow): /', $outcome); } + +/** + * JSON of the interfaces arrow registers as reflection sees them: methods, parameters, types, optional, variadic, by-ref. + */ +function arrow_interfaces_reflection(): string +{ + $interfaces = []; + + foreach ([ + 'Flow\\Parquet\\ParquetEngine', + 'Flow\\Parquet\\ParquetFileReader', + 'Flow\\Parquet\\ParquetFileWriter', + 'Flow\\Arrow\\OutputStream', + 'Flow\\Arrow\\RandomAccessFile', + ] as $name) { + $class = new ReflectionClass($name); + $interfaces[$name] = [ + $class->isInterface(), + array_map(static fn(ReflectionMethod $method): array => [ + $method->getName(), + (string) $method->getReturnType(), + array_map(static fn(ReflectionParameter $parameter): array => [ + $parameter->getName(), + (string) $parameter->getType(), + $parameter->isOptional(), + $parameter->isVariadic(), + $parameter->isPassedByReference(), + ], $method->getParameters()), + ], $class->getMethods()), + ]; + } + + return (string) json_encode($interfaces); +} diff --git a/src/extension/flow-php-ext/Cargo.lock b/src/extension/flow-php-ext/Cargo.lock index fe85342ee3..3366a1782a 100644 --- a/src/extension/flow-php-ext/Cargo.lock +++ b/src/extension/flow-php-ext/Cargo.lock @@ -144,6 +144,24 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bindgen" +version = "0.73.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "787ef8ef523575546b106a58213d6e6b06198a05c2f757258c68a74273670cfa" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "log", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.118", +] + [[package]] name = "bitflags" version = "2.13.0" @@ -227,7 +245,7 @@ dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex 2.0.1", + "shlex", ] [[package]] @@ -317,9 +335,9 @@ checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +checksum = "1af709f1f33454bf52eadfc8c78b3b9ef9cb26fb54d16dc9cd9a7299f899fd1b" dependencies = [ "unicode-segmentation", ] @@ -390,9 +408,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" dependencies = [ "darling_core", "darling_macro", @@ -400,26 +418,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" dependencies = [ "ident_case", "proc-macro2", "quote", "strsim", - "syn", + "syn 3.0.6", ] [[package]] name = "darling_macro" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core", "quote", - "syn", + "syn 3.0.6", ] [[package]] @@ -490,46 +508,28 @@ dependencies = [ [[package]] name = "ext-php-rs" -version = "0.15.15" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe62f25cd053f5f95dc7bbf94e5b41818ea3cf39b36cc25de8ca6b4de68a0eb" +checksum = "530651e90f34e23c956cbd1a33ec4878c05e19ea6b50dd13926b94dd6a2f2134" dependencies = [ "anyhow", + "bindgen", "bitflags", "cc", "cfg-if", - "ext-php-rs-bindgen", "ext-php-rs-build", "ext-php-rs-derive", + "ext-php-rs-introspection", "inventory", "native-tls", "once_cell", "parking_lot", "skeptic", + "thiserror", "ureq", "zip", ] -[[package]] -name = "ext-php-rs-bindgen" -version = "0.72.1-extphprs.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ceb73da3b8b18a3424765dd6926dbc29464a0a7bc31ab491600bfa02adc4bc" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex 1.3.0", - "syn", -] - [[package]] name = "ext-php-rs-build" version = "0.1.1" @@ -541,18 +541,24 @@ dependencies = [ [[package]] name = "ext-php-rs-derive" -version = "0.11.14" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f57a075f878ad51bcc56745fb21efe601429a509204f8a385bbe526566597320" +checksum = "cb3ec2dc5b2228bffa41f5a569b5656e48f964c39cd71633032eebae51e15ef1" dependencies = [ "convert_case", "darling", "itertools", "proc-macro2", "quote", - "syn", + "syn 3.0.6", ] +[[package]] +name = "ext-php-rs-introspection" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a31bb462ea3b026fc419c2c4a38283b270980ac34fed3888dd5afd635c3ef94" + [[package]] name = "fastrand" version = "2.4.1" @@ -799,9 +805,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" dependencies = [ "either", ] @@ -1012,7 +1018,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -1105,16 +1111,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24" -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "proc-macro2" version = "1.0.106" @@ -1312,7 +1308,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -1350,12 +1346,6 @@ dependencies = [ "digest", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "shlex" version = "2.0.1" @@ -1412,6 +1402,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tempfile" version = "3.27.0" @@ -1425,6 +1426,26 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "thiserror" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + [[package]] name = "time" version = "0.3.53" @@ -1589,7 +1610,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.118", "wasm-bindgen-shared", ] @@ -1641,7 +1662,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -1652,7 +1673,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -1711,7 +1732,7 @@ checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] diff --git a/src/extension/flow-php-ext/Cargo.toml b/src/extension/flow-php-ext/Cargo.toml index dc9c909510..6ad5666997 100644 --- a/src/extension/flow-php-ext/Cargo.toml +++ b/src/extension/flow-php-ext/Cargo.toml @@ -13,7 +13,7 @@ arrow-data = "59" arrow-schema = { version = "59", features = ["canonical_extension_types"] } arrow-select = "59" bytes = "1" -ext-php-rs = "0.15" +ext-php-rs = "0.16" flow-batch-frame = { path = "crates/flow-batch-frame" } memchr = "2" serde = { version = "1", features = ["derive"] } diff --git a/src/extension/flow-php-ext/build.rs b/src/extension/flow-php-ext/build.rs index 1b7fbb4405..3c3391bc2c 100644 --- a/src/extension/flow-php-ext/build.rs +++ b/src/extension/flow-php-ext/build.rs @@ -12,7 +12,9 @@ fn main() { /// The `php84`/`php85` cfgs ext-php-rs sets for itself, for the same PHP (`PHP` first, then `PATH`): the extension /// binary is bound to the PHP minor it is built against, so version gates are compile-time. fn emit_php_version_cfg() { - use ext_php_rs_build::{emit_check_cfg, emit_php_cfg_flags, emit_rerun_if_env_changed, find_php, ApiVersion, PHPInfo}; + use ext_php_rs_build::{ + emit_check_cfg, emit_php_cfg_flags, emit_rerun_if_env_changed, find_php, ApiVersion, PHPInfo, + }; emit_rerun_if_env_changed(); emit_check_cfg(); @@ -95,7 +97,9 @@ fn as_semver(describe: &str) -> String { let mut numbers = tag.split('.').map(|number| number.parse::().ok()); match (numbers.next().flatten(), numbers.next().flatten()) { - (Some(major), Some(minor)) => format!("{major}.{}.0-dev+{distance}.{hash}", minor + 1), + (Some(major), Some(minor)) => { + format!("{major}.{}.0-dev+{distance}.{hash}", minor + 1) + } _ => describe.to_string(), } } diff --git a/src/extension/flow-php-ext/composer.json b/src/extension/flow-php-ext/composer.json index ed4d7a07ef..196e5d1785 100644 --- a/src/extension/flow-php-ext/composer.json +++ b/src/extension/flow-php-ext/composer.json @@ -9,11 +9,7 @@ }, "autoload": { "psr-4": { - "Flow\\ETL\\Adapter\\CSV\\": "php/Flow/ETL/Adapter/CSV/", - "Flow\\ETL\\Adapter\\JSON\\": "php/Flow/ETL/Adapter/JSON/", - "Flow\\ETL\\Adapter\\Parquet\\": "php/Flow/ETL/Adapter/Parquet/", - "Flow\\Parquet\\Engine\\Native\\": "php/Flow/Parquet/Engine/Native/", - "Flow\\Floe\\": "php/Flow/Floe/" + "Flow\\ETL\\": "php/Flow/ETL/" } }, "scripts": { diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs index 14dc07c016..687abfc424 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs @@ -116,9 +116,7 @@ pub fn decode_body(body: &[u8], kinds: &[Kind]) -> Result<(u32, Vec), return Err(Error::DirectoryTruncated); } - let words: Vec = (0..words_len) - .map(|_| directory.u32()) - .collect::>()?; + let words: Vec = (0..words_len).map(|_| directory.u32()).collect::>()?; let area = &body[area_start..]; let mut node = 0; let mut extent = 2 * expected_nodes; @@ -163,8 +161,7 @@ pub fn decode_body(body: &[u8], kinds: &[Kind]) -> Result<(u32, Vec), return Err(Error::BufferShorterThanPrefix { buffer }); } - let prefix = - i64::from_le_bytes(area[offset..offset + 8].try_into().expect("8-byte slice")); + let prefix = i64::from_le_bytes(area[offset..offset + 8].try_into().expect("8-byte slice")); if prefix != RAW { return Err(Error::CompressedBuffer { buffer, prefix }); @@ -187,9 +184,7 @@ pub fn decode_body(body: &[u8], kinds: &[Kind]) -> Result<(u32, Vec), if node_count(kind) == 1 { node += 1; } else { - for (derived_length, derived_nulls) in - nodes(kind, length, null_count, &buffers).map_err(malformed)? - { + for (derived_length, derived_nulls) in nodes(kind, length, null_count, &buffers).map_err(malformed)? { if words[2 * node] != derived_length || words[2 * node + 1] != derived_nulls { return Err(Error::NodesDisagree { column: index }); } diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs index 432eb24e5b..66fcb2c567 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/column.rs @@ -5,9 +5,7 @@ //! from 0 over exactly the rows' bytes and children, whatever slice or selection the array is. use arrow_array::cast::AsArray; -use arrow_array::types::{ - Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType, -}; +use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; use arrow_array::{make_array, Array, ArrowPrimitiveType}; use arrow_buffer::{Buffer, ToByteSlice}; use arrow_data::ArrayData; @@ -45,12 +43,7 @@ pub fn encode(data: &ArrayData, kind: &Kind) -> Result>, Error> { /// `ColumnDecoder::decode()` + `PhpBackend::decode()`: the same refusals in the same order. The result's data type is /// `data_type(kind)`. A top-level null under NOT NULL is not refused here (`Rows::fromColumns` does). -pub fn decode( - kind: &Kind, - buffers: &[&[u8]], - len: u32, - null_count: u32, -) -> Result { +pub fn decode(kind: &Kind, buffers: &[&[u8]], len: u32, null_count: u32) -> Result { let mut cursor = Cursor::new(buffers); let data = decode_node(kind, 0, &mut cursor, len, null_count)?; @@ -86,13 +79,7 @@ impl Rows { } } -fn encode_node( - array: &dyn Array, - kind: &Kind, - rows: &Rows, - parent: Option<&[bool]>, - out: &mut Vec>, -) { +fn encode_node(array: &dyn Array, kind: &Kind, rows: &Rows, parent: Option<&[bool]>, out: &mut Vec>) { if let Kind::Null = kind { return; } @@ -150,8 +137,7 @@ fn encode_node( for j in 0..rows.len() { if is_valid(valid, j) { let i = rows.at(j); - bytes - .extend_from_slice(&data[offsets[i] as usize..offsets[i + 1] as usize]); + bytes.extend_from_slice(&data[offsets[i] as usize..offsets[i + 1] as usize]); } packed.extend_from_slice(&(bytes.len() as u32).to_le_bytes()); @@ -186,11 +172,7 @@ fn encode_node( } /// The null of a row is its own or its parent structure's; `None` when every row is valid. -fn effective_validity( - array: &dyn Array, - rows: &Rows, - parent: Option<&[bool]>, -) -> Option> { +fn effective_validity(array: &dyn Array, rows: &Rows, parent: Option<&[bool]>) -> Option> { let nulls = array.nulls(); if nulls.is_none() && parent.is_none() { @@ -286,17 +268,11 @@ struct Cursor<'b, 'a> { impl<'b, 'a> Cursor<'b, 'a> { fn new(buffers: &'b [&'a [u8]]) -> Self { - Self { - buffers, - position: 0, - } + Self { buffers, position: 0 } } fn next(&mut self) -> Result<&'a [u8], Error> { - let buffer = self - .buffers - .get(self.position) - .ok_or(Error::BuffersExhausted)?; + let buffer = self.buffers.get(self.position).ok_or(Error::BuffersExhausted)?; self.position += 1; Ok(buffer) @@ -323,14 +299,7 @@ fn decode_node( let nodes = nodes_at(kind, node, len, null_count, &subtree)?; - return decode_nested( - kind, - node, - &mut Cursor::new(&subtree), - len, - null_count, - &nodes, - ); + return decode_nested(kind, node, &mut Cursor::new(&subtree), len, null_count, &nodes); } if let Kind::Null = kind { @@ -354,12 +323,7 @@ fn decode_node( } Kind::Int32 => builder.add_buffer(fixed_values(cursor.next()?, 4, len, Values::Int32)?), Kind::Float64 => builder.add_buffer(fixed_values(cursor.next()?, 8, len, Values::Float64)?), - Kind::Uuid => builder.add_buffer(fixed_values( - cursor.next()?, - 16, - len, - Values::FixedBinary16, - )?), + Kind::Uuid => builder.add_buffer(fixed_values(cursor.next()?, 16, len, Values::FixedBinary16)?), Kind::Boolean => { let buffer = cursor.next()?; let expected = (len as u64).div_ceil(8); @@ -538,8 +502,7 @@ fn check_offsets(buffer: &[u8], len: u32, of: Of) -> Result { }); } - let offset = - |i: usize| u32::from_le_bytes(buffer[i * 4..i * 4 + 4].try_into().expect("4-byte slice")); + let offset = |i: usize| u32::from_le_bytes(buffer[i * 4..i * 4 + 4].try_into().expect("4-byte slice")); if offset(0) != 0 { return Err(Error::OffsetsStart { diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs index 7bf51215c2..fbc24068a9 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/kind.rs @@ -138,17 +138,14 @@ pub fn kind_of(parsed: &TypeJson) -> Result { "integer" | "positive_integer" => Kind::Int64, "float" => Kind::Float64, "boolean" => Kind::Boolean, - "string" | "non_empty_string" | "numeric-string" | "class_string" | "json" | "enum" - | "timezone" | "xml" | "xml_element" | "html" | "html_element" => Kind::Bytes, + "string" | "non_empty_string" | "numeric-string" | "class_string" | "json" | "enum" | "timezone" | "xml" + | "xml_element" | "html" | "html_element" => Kind::Bytes, "datetime" => Kind::Timestamp, "date" => Kind::Int32, "time" => Kind::Duration, "uuid" => Kind::Uuid, "null" => Kind::Null, - "list" => Kind::List(child( - "item", - parsed.element().ok_or_else(|| missing(Part::Element))?, - )?), + "list" => Kind::List(child("item", parsed.element().ok_or_else(|| missing(Part::Element))?)?), "map" => Kind::Map( child("key", parsed.key().ok_or_else(|| missing(Part::Key))?)?, child("value", parsed.value().ok_or_else(|| missing(Part::Value))?)?, @@ -199,12 +196,7 @@ pub fn data_type(kind: &Kind) -> DataType { )), false, ), - Kind::Struct(fields) => DataType::Struct( - fields - .iter() - .map(|child| field(&child.name, &child.kind)) - .collect(), - ), + Kind::Struct(fields) => DataType::Struct(fields.iter().map(|child| field(&child.name, &child.kind)).collect()), } } diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/layout.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/layout.rs index a311f8dbd6..a39ee8dbdd 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/layout.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/layout.rs @@ -8,12 +8,7 @@ pub fn node_count(kind: &Kind) -> usize { match kind { Kind::List(element) => 1 + node_count(&element.kind), Kind::Map(key, value) => 2 + node_count(&key.kind) + node_count(&value.kind), - Kind::Struct(fields) => { - 1 + fields - .iter() - .map(|field| node_count(&field.kind)) - .sum::() - } + Kind::Struct(fields) => 1 + fields.iter().map(|field| node_count(&field.kind)).sum::(), _ => 1, } } @@ -23,12 +18,7 @@ pub fn buffer_count(kind: &Kind) -> usize { Kind::Null => 0, Kind::List(element) => 2 + buffer_count(&element.kind), Kind::Map(key, value) => 3 + buffer_count(&key.kind) + buffer_count(&value.kind), - Kind::Struct(fields) => { - 1 + fields - .iter() - .map(|field| buffer_count(&field.kind)) - .sum::() - } + Kind::Struct(fields) => 1 + fields.iter().map(|field| buffer_count(&field.kind)).sum::(), Kind::Bytes => 3, _ => 2, } @@ -37,12 +27,7 @@ pub fn buffer_count(kind: &Kind) -> usize { /// Pre-order `(length, null count)` of one column's tree: the first node as given, every child derived from the /// buffers - a null kind is `(length, length)`, list and map children span the last offset, a map entries node holds /// no nulls and structure children span their parent. -pub fn nodes( - kind: &Kind, - len: u32, - null_count: u32, - buffers: &[&[u8]], -) -> Result, Error> { +pub fn nodes(kind: &Kind, len: u32, null_count: u32, buffers: &[&[u8]]) -> Result, Error> { nodes_at(kind, 0, len, null_count, buffers) } diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs index 0b25c6e1e5..7aa30e24ad 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs @@ -18,12 +18,9 @@ fn kind_of(type_json: &str) -> Kind { /// FrameContext::directory(): the counts, then every node and extent word. fn directory(body: &[u8]) -> Vec { - let word = - |i: usize| u32::from_le_bytes(body[i * 4..i * 4 + 4].try_into().expect("4-byte slice")); + let word = |i: usize| u32::from_le_bytes(body[i * 4..i * 4 + 4].try_into().expect("4-byte slice")); - (0..3 + 2 * (word(1) + word(2)) as usize) - .map(word) - .collect() + (0..3 + 2 * (word(1) + word(2)) as usize).map(word).collect() } fn round_trips(body: &[u8], kinds: &[Kind]) { @@ -32,9 +29,7 @@ fn round_trips(body: &[u8], kinds: &[Kind]) { assert_eq!( body, - encode_body(&columns, row_count) - .expect("an encodable batch") - .as_slice() + encode_body(&columns, row_count).expect("an encodable batch").as_slice() ); } @@ -61,23 +56,16 @@ fn the_worked_example() { "020000000200000005000000020000000000000002000000010000000000000000000000000000001800000018000000090000002800000014000000400000000a00000000000000ffffffffffffffff01000000000000000200000000000000ffffffffffffffff0100000000000000ffffffffffffffff00000000020000000200000000000000ffffffffffffffff6162000000000000", hex(&body), ); - round_trips( - &body, - &[worked_example()[0].0.clone(), worked_example()[1].0.clone()], - ); + round_trips(&body, &[worked_example()[0].0.clone(), worked_example()[1].0.clone()]); } #[test] fn a_list_with_a_null_slot() { let kind = kind_of(r#"{"type":"list","element":{"type":"integer"}}"#); - let list = - ListArray::from_iter_primitive::(vec![Some(vec![Some(1), Some(2)]), None]); + let list = ListArray::from_iter_primitive::(vec![Some(vec![Some(1), Some(2)]), None]); let body = encode_body(&[(kind.clone(), list.into_data())], 2).expect("a list batch"); - assert_eq!( - vec![2, 2, 4, 2, 1, 2, 0, 0, 9, 16, 20, 0, 0, 40, 24], - directory(&body) - ); + assert_eq!(vec![2, 2, 4, 2, 1, 2, 0, 0, 9, 16, 20, 0, 0, 40, 24], directory(&body)); round_trips(&body, &[kind]); } @@ -106,9 +94,7 @@ fn a_map_entries_node_and_extent() { let body = encode_body(&[(kind.clone(), map.finish().into_data())], 2).expect("a map batch"); assert_eq!( - vec![ - 2, 4, 8, 2, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 20, 0, 0, 0, 0, 24, 24, 48, 11, 0, 0, 64, 32 - ], + vec![2, 4, 8, 2, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 20, 0, 0, 0, 0, 24, 24, 48, 11, 0, 0, 64, 32], directory(&body), ); round_trips(&body, &[kind]); @@ -116,8 +102,7 @@ fn a_map_entries_node_and_extent() { #[test] fn a_structure_with_a_null_parent() { - let kind = - kind_of(r#"{"type":"structure_v2","fields":[{"name":"a","type":{"type":"integer"}}]}"#); + let kind = kind_of(r#"{"type":"structure_v2","fields":[{"name":"a","type":{"type":"integer"}}]}"#); let structure = StructArray::try_new( vec![Arc::new(arrow_schema::Field::new( "a", @@ -131,23 +116,16 @@ fn a_structure_with_a_null_parent() { .expect("a valid struct"); let body = encode_body(&[(kind.clone(), structure.into_data())], 2).expect("a structure batch"); - assert_eq!( - vec![2, 2, 3, 2, 1, 2, 1, 0, 9, 16, 9, 32, 24], - directory(&body) - ); + assert_eq!(vec![2, 2, 3, 2, 1, 2, 1, 0, 9, 16, 9, 32, 24], directory(&body)); round_trips(&body, &[kind]); } #[test] fn a_null_column_has_a_full_null_node_and_no_extent() { let kind = kind_of(r#"{"type":"null"}"#); - let body = - encode_body(&[(kind.clone(), NullArray::new(2).into_data())], 2).expect("a null batch"); + let body = encode_body(&[(kind.clone(), NullArray::new(2).into_data())], 2).expect("a null batch"); - assert_eq!( - "020000000100000000000000020000000200000000000000", - hex(&body) - ); + assert_eq!("020000000100000000000000020000000200000000000000", hex(&body)); round_trips(&body, &[kind]); } @@ -173,10 +151,7 @@ fn encode_refuses_a_column_of_another_length() { #[test] fn decode_refuses_a_malformed_body() { - let kinds = [ - kind_of(r#"{"type":"integer"}"#), - kind_of(r#"{"type":"string"}"#), - ]; + let kinds = [kind_of(r#"{"type":"integer"}"#), kind_of(r#"{"type":"string"}"#)]; let body = encode_body(&worked_example(), 2).expect("the worked example"); let with = |at: usize, bytes: &[u8]| { let mut corrupt = body.clone(); @@ -194,10 +169,7 @@ fn decode_refuses_a_malformed_body() { )); assert!(matches!( decode_body(&body, &kinds[..1]), - Err(Error::FrameNodeCount { - frame: 2, - schema: 1 - }), + Err(Error::FrameNodeCount { frame: 2, schema: 1 }), )); assert!(matches!( decode_body(&with(12, &unhex("03000000")), &kinds), @@ -217,17 +189,11 @@ fn decode_refuses_a_malformed_body() { )); assert!(matches!( decode_body(&with(72, &unhex("0000000000000000")), &kinds), - Err(Error::CompressedBuffer { - buffer: 1, - prefix: 0 - }), + Err(Error::CompressedBuffer { buffer: 1, prefix: 0 }), )); assert!(matches!( decode_body(&with(36, &unhex("ff000000")), &kinds), - Err(Error::BufferOutsideArea { - buffer: 1, - area: 80 - }), + Err(Error::BufferOutsideArea { buffer: 1, area: 80 }), )); assert!(matches!( decode_body(&with(24, &unhex("00000000")), &kinds), diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs index 222a768ad2..36ff0d5b92 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/column.rs @@ -5,8 +5,8 @@ use std::sync::Arc; use arrow_array::builder::{BinaryBuilder, Int64Builder, MapBuilder, MapFieldNames}; use arrow_array::types::Int64Type; use arrow_array::{ - Array, ArrayRef, BinaryArray, BooleanArray, Date32Array, FixedSizeBinaryArray, Float64Array, - Int64Array, ListArray, NullArray, StructArray, TimestampMicrosecondArray, + Array, ArrayRef, BinaryArray, BooleanArray, Date32Array, FixedSizeBinaryArray, Float64Array, Int64Array, ListArray, + NullArray, StructArray, TimestampMicrosecondArray, }; use arrow_buffer::NullBuffer; use arrow_data::ArrayData; @@ -41,13 +41,7 @@ fn raw(kind: &Kind, buffers: &[&[u8]], len: u32, null_count: u32) -> Error { fn structure(fields: Vec<(&str, ArrayRef)>, nulls: Option>) -> ArrayData { let arrow_fields = fields .iter() - .map(|(name, array)| { - Arc::new(arrow_schema::Field::new( - *name, - array.data_type().clone(), - true, - )) - }) + .map(|(name, array)| Arc::new(arrow_schema::Field::new(*name, array.data_type().clone(), true))) .collect::>(); StructArray::try_new( @@ -211,11 +205,7 @@ fn a_selection_under_a_null_list_slot_is_compacted() { let kind = kind_of("{\"type\":\"list\",\"element\":{\"type\":\"string\"}}"); let strings = BinaryArray::from(vec![b"a".as_ref(), b"bc", b"d"]); let offsets = arrow_buffer::OffsetBuffer::new(vec![0, 1, 2, 3].into()); - let field = Arc::new(arrow_schema::Field::new( - "item", - arrow_schema::DataType::Binary, - true, - )); + let field = Arc::new(arrow_schema::Field::new("item", arrow_schema::DataType::Binary, true)); let list = ListArray::new( field, offsets, @@ -245,10 +235,7 @@ fn bytes_that_are_not_utf8_round_trip() { assert_eq!(vec!["", "0000000003000000", "61ff62"], buffers); assert_eq!( b"a\xFFb", - decoded(&kind, &buffers, 1, 0) - .expect("a binary column") - .buffers()[1] - .as_slice(), + decoded(&kind, &buffers, 1, 0).expect("a binary column").buffers()[1].as_slice(), ); } @@ -267,9 +254,7 @@ fn encode_refuses_a_foreign_data_type() { fn decode_refuses_corrupt_buffers() { let int = kind_of("{\"type\":\"integer\"}"); let string = kind_of("{\"type\":\"string\"}"); - let map = kind_of( - "{\"type\":\"map\",\"key\":{\"type\":\"string\"},\"value\":{\"type\":\"integer\"}}", - ); + let map = kind_of("{\"type\":\"map\",\"key\":{\"type\":\"string\"},\"value\":{\"type\":\"integer\"}}"); let null = kind_of("{\"type\":\"null\"}"); assert!(matches!(raw(&int, &[b""], 1, 0), Error::BuffersExhausted)); @@ -283,25 +268,13 @@ fn decode_refuses_corrupt_buffers() { }, )); assert!(matches!( - raw( - &string, - &[b"", b"\x01\x00\x00\x00\x02\x00\x00\x00", b"ab"], - 1, - 0 - ), - Error::OffsetsStart { - of: Of::Utf8, - first: 1 - }, + raw(&string, &[b"", b"\x01\x00\x00\x00\x02\x00\x00\x00", b"ab"], 1, 0), + Error::OffsetsStart { of: Of::Utf8, first: 1 }, )); assert!(matches!( raw( &string, - &[ - b"", - b"\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00", - b"ab" - ], + &[b"", b"\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00", b"ab"], 2, 0 ), @@ -313,12 +286,7 @@ fn decode_refuses_corrupt_buffers() { }, )); assert!(matches!( - raw( - &string, - &[b"", b"\x00\x00\x00\x00\x03\x00\x00\x00", b"ab"], - 1, - 0 - ), + raw(&string, &[b"", b"\x00\x00\x00\x00\x03\x00\x00\x00", b"ab"], 1, 0), Error::Utf8DataLength { bytes: 2, last_offset: 3 @@ -361,10 +329,7 @@ fn decode_refuses_corrupt_buffers() { )); assert!(matches!( raw(&null, &[], 2, 1), - Error::NullKindNullCount { - rows: 2, - null_count: 1 - } + Error::NullKindNullCount { rows: 2, null_count: 1 } )); assert!(matches!( raw(&int, &[b"", b"\x01\x00\x00\x00\x00\x00\x00\x00", b""], 1, 0), @@ -389,12 +354,7 @@ fn decode_refuses_corrupt_buffers() { /// never, a structure child always may. #[test] fn decode_refuses_nested_nulls_where_the_type_forbids_them() { - let one_null_child = [ - b"".as_ref(), - b"\x00\x00\x00\x00\x01\x00\x00\x00", - b"\x00", - &[0; 8], - ]; + let one_null_child = [b"".as_ref(), b"\x00\x00\x00\x00\x01\x00\x00\x00", b"\x00", &[0; 8]]; assert!(matches!( raw( @@ -424,21 +384,18 @@ fn decode_refuses_nested_nulls_where_the_type_forbids_them() { ) .is_ok()); - let entries = - |key_validity: &'static [u8], value_validity: &'static [u8]| -> [&'static [u8]; 7] { - [ - b"", - b"\x00\x00\x00\x00\x01\x00\x00\x00", - b"", - key_validity, - &[0; 8], - value_validity, - &[0; 8], - ] - }; - let map = kind_of( - "{\"type\":\"map\",\"key\":{\"type\":\"integer\"},\"value\":{\"type\":\"integer\"}}", - ); + let entries = |key_validity: &'static [u8], value_validity: &'static [u8]| -> [&'static [u8]; 7] { + [ + b"", + b"\x00\x00\x00\x00\x01\x00\x00\x00", + b"", + key_validity, + &[0; 8], + value_validity, + &[0; 8], + ] + }; + let map = kind_of("{\"type\":\"map\",\"key\":{\"type\":\"integer\"},\"value\":{\"type\":\"integer\"}}"); let optional_values = kind_of("{\"type\":\"map\",\"key\":{\"type\":\"integer\"},\"value\":{\"type\":\"optional\",\"base\":{\"type\":\"integer\"}}}"); @@ -460,9 +417,8 @@ fn decode_refuses_nested_nulls_where_the_type_forbids_them() { )); assert!(decode(&optional_values, &entries(b"", b"\x00"), 1, 0).is_ok()); - let structure = kind_of( - "{\"type\":\"structure_v2\",\"fields\":[{\"name\":\"x\",\"type\":{\"type\":\"integer\"}}]}", - ); + let structure = + kind_of("{\"type\":\"structure_v2\",\"fields\":[{\"name\":\"x\",\"type\":{\"type\":\"integer\"}}]}"); assert!(decode(&structure, &[b"".as_ref(), b"\x00", &[0; 8]], 1, 0).is_ok()); } diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/kind.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/kind.rs index fa6e8ff0fe..f6610f5508 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/kind.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/kind.rs @@ -21,10 +21,7 @@ fn parses_a_golden_footer_schema() { assert_eq!(26, definitions.len()); assert_eq!("string_null", definitions[8].name); assert!(definitions[8].nullable); - assert_eq!( - Some(b"Europe/Warsaw".as_ref()), - definitions[10].type_.zone() - ); + assert_eq!(Some(b"Europe/Warsaw".as_ref()), definitions[10].type_.zone()); assert_eq!( Some(br"Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum".as_ref()), definitions[18].type_.class() @@ -41,10 +38,7 @@ fn parses_a_golden_footer_schema() { #[test] fn refuses_schema_and_type_json_it_cannot_read() { - assert!(matches!( - parse_schema(b"[\xFF]"), - Err(Error::SchemaJsonUtf8) - )); + assert!(matches!(parse_schema(b"[\xFF]"), Err(Error::SchemaJsonUtf8))); assert!(matches!(parse_schema(b"[{"), Err(Error::SchemaJson(_)))); assert!(matches!(parse_type(b"\xFF"), Err(Error::TypeJsonUtf8))); assert!(matches!(parse_type(b"{}"), Err(Error::TypeJson(_)))); @@ -62,17 +56,11 @@ fn refuses_a_type_without_a_column_kind() { )); assert!(matches!( kind(br#"{"type":"map","key":{"type":"string"}}"#), - Err(Error::MissingPart { - part: Part::Value, - .. - }), + Err(Error::MissingPart { part: Part::Value, .. }), )); assert!(matches!( kind(br#"{"type":"optional"}"#), - Err(Error::MissingPart { - part: Part::Base, - .. - }) + Err(Error::MissingPart { part: Part::Base, .. }) )); } @@ -120,11 +108,7 @@ fn definitions() -> Vec<(&'static str, Kind)> { #[test] fn every_definition_has_its_kind() { for (type_json, expected) in definitions() { - assert_eq!( - expected, - kind(type_json.as_bytes()).expect(type_json), - "{type_json}" - ); + assert_eq!(expected, kind(type_json.as_bytes()).expect(type_json), "{type_json}"); } } diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/NativeCSVWriter.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVEncoder.php similarity index 64% rename from src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/NativeCSVWriter.php rename to src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVEncoder.php index f434653821..af254d42d9 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/NativeCSVWriter.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVEncoder.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\CSV; use Flow\ETL\Rows; -use Flow\ETL\Schema; use RuntimeException; use function extension_loaded; @@ -14,8 +13,11 @@ return; } -final class NativeCSVWriter +final class RustCSVEncoder implements CSVEncoder { + /** + * @param PhpCSVEncoder $php renders the columns this writer does not render itself, and the header + */ public function __construct( string $separator, string $enclosure, @@ -23,22 +25,20 @@ public function __construct( string $newLineSeparator, string $dateTimeFormat, string $dateFormat, + PhpCSVEncoder $php, ) { throw new RuntimeException('flow_php extension is not loaded'); } - /** - * @param array> $cells CSVEncoder::cells() of the unrendered columns, each of $rows->count() values - */ - public function encode(Rows $rows, array $cells): string + public function encode(Rows $rows): string { throw new RuntimeException('flow_php extension is not loaded'); } /** - * @return list the columns of $schema this writer does not render itself + * @param list $headers */ - public function unrendered(Schema $schema): array + public function encodeHeader(array $headers): string { throw new RuntimeException('flow_php extension is not loaded'); } diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVReaderNative.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVOpenSource.php similarity index 51% rename from src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVReaderNative.php rename to src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVOpenSource.php index 2193e94617..a3f41b99a7 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVReaderNative.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustCSVOpenSource.php @@ -4,9 +4,14 @@ namespace Flow\ETL\Adapter\CSV; -use Flow\ETL\Exception\SchemaMismatchException; +use Flow\ETL\Column\Backend; use Flow\ETL\Rows; +use Flow\ETL\RustIterator; use Flow\ETL\Schema; +use Flow\ETL\Schema\Inference\ColumnTypes; +use Flow\ETL\Schema\Inference\SchemaInference; +use Flow\Filesystem\SourceStream; +use Flow\Types\Type\TypeNarrower; use RuntimeException; use function extension_loaded; @@ -15,77 +20,63 @@ return; } -final class RustCSVReaderNative +final class RustCSVOpenSource implements CSVOpenSource { public function __construct( + SourceStream $stream, string $separator, string $enclosure, string $escape, bool $withHeader, bool $emptyToNull, bool $removeBOM, + ?int $charactersReadInLine = null, ) { throw new RuntimeException('flow_php extension is not loaded'); } /** - * The bytes, as read, of every row next(), nextColumns() and fold() produced so far - line endings included, the header - * record excluded. - * - * @return int<0, max> + * @return RustIterator */ - public function consumedBytes(): int + public function batches(Schema $schema, int $batchSize, Backend $backend): RustIterator { throw new RuntimeException('flow_php extension is not loaded'); } - public function feed(string $chunk): void + public function close(): void { throw new RuntimeException('flow_php extension is not loaded'); } - public function finish(): void + public function columns(): array { throw new RuntimeException('flow_php extension is not loaded'); } - /** - * @param int<0, max>|-1 $limit - * - * @return int<0, max> - */ - public function fold(RustColumnFoldNative $fold, int $limit): int + public function headers(): array { throw new RuntimeException('flow_php extension is not loaded'); } - /** - * @return list - */ - public function headers(): array + public function producedBytes(): int { throw new RuntimeException('flow_php extension is not loaded'); } - /** - * @param int<1, max> $batchSize - * - * @return list> - */ - public function next(int $batchSize): array + public function producedRows(): int { throw new RuntimeException('flow_php extension is not loaded'); } /** - * Exactly $batchSize rows keyed and ordered by $schema while that many are buffered, the remainder after finish(), - * else null; row indexes in refusals are relative to the batch. - * - * @param int<1, max> $batchSize - * - * @throws SchemaMismatchException + * @return RustIterator> */ - public function nextColumns(Schema $schema, int $batchSize): ?Rows + public function records(): RustIterator + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function sniff(array $names, int $rowBudget, SchemaInference $inference, TypeNarrower $typer): ColumnTypes { throw new RuntimeException('flow_php extension is not loaded'); } diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustColumnFoldNative.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustColumnFoldNative.php deleted file mode 100644 index 57e98214ee..0000000000 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/CSV/RustColumnFoldNative.php +++ /dev/null @@ -1,46 +0,0 @@ - $names - * @param list $candidates - the candidate types' toString() - */ - public function __construct(array $names, array $candidates) - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - public function narrowOne(string $value): string - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * @return int<0, max> - */ - public function rows(): int - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * @return array - */ - public function types(): array - { - throw new RuntimeException('flow_php extension is not loaded'); - } -} diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonReader.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonReader.php deleted file mode 100644 index b59f220380..0000000000 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonReader.php +++ /dev/null @@ -1,55 +0,0 @@ - $batchSize - * - * @throws SchemaMismatchException a cast or schema refusal, as RowsBuilder::appendRows() throws it - * @throws FlowRuntimeException malformed JSON, or a scalar record - */ - public function nextColumns(Schema $schema, int $batchSize): ?Rows - { - throw new RuntimeException('flow_php extension is not loaded'); - } -} diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonWriter.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJSONEncoder.php similarity index 55% rename from src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonWriter.php rename to src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJSONEncoder.php index b59e4fda3c..df176d2aa3 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/NativeJsonWriter.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJSONEncoder.php @@ -6,7 +6,6 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Rows; -use Flow\ETL\Schema; use RuntimeException; use function extension_loaded; @@ -15,28 +14,19 @@ return; } -final class NativeJsonWriter +final class RustJSONEncoder implements JSONEncoder { /** + * @param PhpJSONEncoder $php renders the columns this writer does not render itself + * * @throws InvalidArgumentException a flag outside JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION */ - public function __construct(int $flags, string $dateTimeFormat, string $dateFormat) + public function __construct(int $flags, string $dateTimeFormat, string $dateFormat, PhpJSONEncoder $php) { throw new RuntimeException('flow_php extension is not loaded'); } - /** - * @param array> $fragments JSONEncoder::fragments() of the unrendered columns - */ - public function encode(Rows $rows, array $fragments, string $separator): string - { - throw new RuntimeException('flow_php extension is not loaded'); - } - - /** - * @return list the columns of $schema this writer does not render itself - */ - public function unrendered(Schema $schema): array + public function encode(Rows $rows, string $separator): string { throw new RuntimeException('flow_php extension is not loaded'); } diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJsonOpenSource.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJsonOpenSource.php new file mode 100644 index 0000000000..3226c8b161 --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJsonOpenSource.php @@ -0,0 +1,44 @@ + $offset + */ + public function __construct(SourceStream $stream, bool $lines, string $uri, string $head, int $offset) + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + /** + * @return RustIterator + */ + public function batches(Schema $schema, int $batchSize, Backend $backend): RustIterator + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function close(): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/RustParquetOpenSink.php similarity index 74% rename from src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php rename to src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/RustParquetOpenSink.php index 1079df5a87..b6ff2c2628 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetWriter.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/RustParquetOpenSink.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Adapter\Parquet; -use Flow\Arrow\Parquet\RowsWriter; use Flow\ETL\Rows; +use Flow\Parquet\Engine\RustParquetFileWriter; use RuntimeException; use function extension_loaded; @@ -14,12 +14,12 @@ return; } -final class NativeParquetWriter +final class RustParquetOpenSink implements ParquetOpenSink { /** - * @param RowsWriter $writer arrow-ext's writer, which owns the stream + * @param RustParquetFileWriter $writer arrow-ext's writer, which owns the stream */ - public function __construct(RowsWriter $writer) + public function __construct(RustParquetFileWriter $writer) { throw new RuntimeException('flow_php extension is not loaded'); } diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/RustParquetOpenSource.php similarity index 52% rename from src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php rename to src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/RustParquetOpenSource.php index 6fc732783d..c7593c4384 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/NativeParquetReader.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/Parquet/RustParquetOpenSource.php @@ -4,9 +4,11 @@ namespace Flow\ETL\Adapter\Parquet; -use Flow\Arrow\Parquet\BatchReader; +use Flow\ETL\Column\Backend; use Flow\ETL\Rows; +use Flow\ETL\RustIterator; use Flow\ETL\Schema; +use Flow\Parquet\Engine\RustParquetFileReader; use RuntimeException; use function extension_loaded; @@ -15,29 +17,25 @@ return; } -final class NativeParquetReader +final class RustParquetOpenSource implements ParquetOpenSource { - /** - * @param BatchReader $batches arrow-ext's batches of the schema's columns - * @param Schema $schema the columns to read; every definition's type must store what the file's column reads as, - * checked here, before any batch - * - * @throws \Flow\ETL\Exception\InvalidArgumentException for a column whose type stores something else - */ - public function __construct(BatchReader $batches, Schema $schema) + public function __construct(RustParquetFileReader $file) { throw new RuntimeException('flow_php extension is not loaded'); } - public function close(): void + /** + * @throws \Flow\ETL\Exception\InvalidArgumentException for a column whose type stores something other than the + * file's column reads as, before any batch + * + * @return RustIterator + */ + public function batches(Schema $schema, int $batchSize, ?int $offset, ?int $limit, Backend $backend): RustIterator { throw new RuntimeException('flow_php extension is not loaded'); } - /** - * The next batch under the schema, null after the last. - */ - public function next(): ?Rows + public function close(): void { throw new RuntimeException('flow_php extension is not loaded'); } diff --git a/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php b/src/extension/flow-php-ext/php/Flow/ETL/Column/RustBackend.php similarity index 57% rename from src/core/etl/src/Flow/ETL/Column/DefaultBackend.php rename to src/extension/flow-php-ext/php/Flow/ETL/Column/RustBackend.php index 7c1e2e6b1a..5decae27bb 100644 --- a/src/core/etl/src/Flow/ETL/Column/DefaultBackend.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Column/RustBackend.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Column; use Flow\ETL\Schema\Definition; +use RuntimeException; use function extension_loaded; @@ -12,37 +13,30 @@ return; } -final readonly class DefaultBackend implements Backend +final class RustBackend implements Backend { - private PhpBackend $php; + public function adopt(Definition $definition, Column $column): Column + { + throw new RuntimeException('flow_php extension is not loaded'); + } - public function __construct() + public function allocatedBytes(): int { - $this->php = new PhpBackend(); + throw new RuntimeException('flow_php extension is not loaded'); } public function builder(Definition $definition): ColumnBuilder { - return $this->php->builder($definition); + throw new RuntimeException('flow_php extension is not loaded'); } public function constant(Definition $definition, mixed $value, int $count): Column { - return $this->php->constant($definition, $value, $count); + throw new RuntimeException('flow_php extension is not loaded'); } public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column { - return $this->php->decode($definition, $buffers, $count, $nullCount); - } - - public function adopt(Definition $definition, Column $column): Column - { - return $this->php->adopt($definition, $column); - } - - public function allocatedBytes(): int - { - return $this->php->allocatedBytes(); + throw new RuntimeException('flow_php extension is not loaded'); } } diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Column/NativeArrowBatch.php b/src/extension/flow-php-ext/php/Flow/ETL/Column/RustColumnsBatch.php similarity index 91% rename from src/extension/flow-php-ext/php/Flow/ETL/Column/NativeArrowBatch.php rename to src/extension/flow-php-ext/php/Flow/ETL/Column/RustColumnsBatch.php index 82c15de2c8..00376e445d 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Column/NativeArrowBatch.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Column/RustColumnsBatch.php @@ -13,10 +13,10 @@ } /** - * One Arrow C Data struct array and its schema; built by Flow\ETL\Adapter\Parquet\NativeParquetWriter::write(), never + * One Arrow C Data struct array and its schema; built by Flow\ETL\Adapter\Parquet\RustParquetOpenSink::write(), never * by userland. */ -final class NativeArrowBatch +final class RustColumnsBatch { public function __construct() { diff --git a/src/extension/flow-php-ext/php/Flow/ETL/RustIterator.php b/src/extension/flow-php-ext/php/Flow/ETL/RustIterator.php new file mode 100644 index 0000000000..5839796311 --- /dev/null +++ b/src/extension/flow-php-ext/php/Flow/ETL/RustIterator.php @@ -0,0 +1,52 @@ + + */ +final class RustIterator implements Iterator +{ + /** + * @return T + */ + public function current(): mixed + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function key(): ?int + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function next(): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function rewind(): void + { + throw new RuntimeException('flow_php extension is not loaded'); + } + + public function valid(): bool + { + throw new RuntimeException('flow_php extension is not loaded'); + } +} diff --git a/src/extension/flow-php-ext/php/Flow/Floe/Exception/ExtensionException.php b/src/extension/flow-php-ext/php/Flow/Floe/Exception/ExtensionException.php deleted file mode 100644 index 28972d4f34..0000000000 --- a/src/extension/flow-php-ext/php/Flow/Floe/Exception/ExtensionException.php +++ /dev/null @@ -1,15 +0,0 @@ - i64 { self.rows as i64 } @@ -58,13 +58,25 @@ impl NativeArrowBatch { #[derive(Debug)] enum Refusal { NotStruct, - Count { children: i64, columns: usize }, - Name { child: String, column: usize }, + Count { + children: i64, + columns: usize, + }, + Name { + child: String, + column: usize, + }, /// Column `column` arrives as `child`, which its plan does not store. - Type { column: usize, child: Field }, + Type { + column: usize, + child: Field, + }, Schema(ArrowError), Released, - Length { children: i64, schema: i64 }, + Length { + children: i64, + schema: i64, + }, Invalid(ArrowError), } @@ -202,7 +214,9 @@ fn refused(refusal: Refusal, columns: &[(Vec, Rc)]) -> PhpExceptio Refusal::Length { children, schema } => { format!("Arrow C Data batch of {children} children does not match its schema of {schema}") } - Refusal::Invalid(error) => format!("Arrow C Data batch is not a valid struct array: {error}"), + Refusal::Invalid(error) => { + format!("Arrow C Data batch is not a valid struct array: {error}") + } }; invalid_argument(message) @@ -238,7 +252,10 @@ fn address(object: &ZendObject, ce: &ClassEntry, method: &str) -> PhpResult, Rc)]) -> Vec<(&[u8], DataType)> { - columns.iter().map(|(name, plan)| (name.as_slice(), data_type(&plan.kind))).collect() + columns + .iter() + .map(|(name, plan)| (name.as_slice(), data_type(&plan.kind))) + .collect() } /// Refuses a schema carrier (`arrowSchemaAddress()`) whose struct children are not `columns`, by name and stored type. @@ -260,7 +277,7 @@ pub fn import(batch: &Zval, columns: &[(Vec, Rc)]) -> PhpResult<(u } /// `columns` as one struct batch of `rows` rows, every child nullable. -pub fn export(rows: usize, columns: Vec<(String, ArrayRef)>) -> PhpResult { +pub fn export(rows: usize, columns: Vec<(String, ArrayRef)>) -> PhpResult { let fields = columns .iter() .map(|(name, array)| Field::new(name, array.data_type().clone(), true)) @@ -270,7 +287,7 @@ pub fn export(rows: usize, columns: Vec<(String, ArrayRef)>) -> PhpResult() + arrays + .iter() + .map(|array| array.to_data().get_buffer_memory_size() as i64) + .sum::() ); let first = arrays.into_iter().next().unwrap(); @@ -395,21 +415,31 @@ mod tests { #[test] fn a_child_of_another_type_is_refused_before_the_move() { - refused(&[(b"id", DataType::Float64), (b"list", expected()[1].1.clone())], |refusal| { - matches!(refusal, Refusal::Type { column: 0, .. }) - }); + refused( + &[(b"id", DataType::Float64), (b"list", expected()[1].1.clone())], + |refusal| matches!(refusal, Refusal::Type { column: 0, .. }), + ); } #[test] fn a_child_of_another_name_is_refused_before_the_move() { - refused(&[(b"id", DataType::Int64), (b"other", expected()[1].1.clone())], |refusal| { - matches!(refusal, Refusal::Name { column: 1, .. }) - }); + refused( + &[(b"id", DataType::Int64), (b"other", expected()[1].1.clone())], + |refusal| matches!(refusal, Refusal::Name { column: 1, .. }), + ); } #[test] fn another_child_count_is_refused_before_the_move() { - refused(&[(b"id", DataType::Int64)], |refusal| matches!(refusal, Refusal::Count { children: 2, columns: 1 })); + refused(&[(b"id", DataType::Int64)], |refusal| { + matches!( + refusal, + Refusal::Count { + children: 2, + columns: 1 + } + ) + }); } #[test] @@ -420,7 +450,10 @@ mod tests { let (_, arrays) = take(&schema, &mut array, &expected()).unwrap(); let counted = imported(); - assert!(matches!(take(&schema, &mut array, &expected()).unwrap_err(), Refusal::Released)); + assert!(matches!( + take(&schema, &mut array, &expected()).unwrap_err(), + Refusal::Released + )); assert_eq!(imported(), counted); drop(arrays); diff --git a/src/extension/flow-php-ext/src/backend.rs b/src/extension/flow-php-ext/src/backend.rs index 2fd13b71a8..d2bf5b04fb 100644 --- a/src/extension/flow-php-ext/src/backend.rs +++ b/src/extension/flow-php-ext/src/backend.rs @@ -1,10 +1,12 @@ -//! `Flow\ETL\Column\DefaultBackend` when flow_php is loaded: every column is a `NativeColumn`. +//! `Flow\ETL\Column\RustBackend`: every column is a `RustColumn`. // a parameter's Rust name is its PHP name, and `Backend::decode()` names it `$nullCount` #![allow(non_snake_case)] use std::rc::Rc; +use arrow_array::ArrayRef; + use ext_php_rs::convert::IntoZval; use ext_php_rs::error::Result as ZvalResult; use ext_php_rs::flags::{ClassFlags, DataType}; @@ -13,9 +15,12 @@ use ext_php_rs::types::{ZendHashTable, Zval}; use flow_batch_frame::column::decode; use flow_batch_frame::layout::buffer_count; -use crate::builder::{throw, NativeColumnBuilder}; -use crate::column::NativeColumn; -use crate::ctx::{call_method, call_static, expect_object, find_class, zval_long}; +use crate::batch_columns::HeldBatch; +use crate::builder::{throw, RustColumnBuilder}; +use crate::column::RustColumn; +use crate::ctx::{ + call_method, call_static, column_key, expect_object, find_class, ht_for_each, ht_get, ht_insert, zval_long, +}; use crate::exception::ext_exception; use crate::interfaces::backend_ce; use crate::plan::{physical_for_definition, type_plan, TypePlan}; @@ -28,7 +33,7 @@ const MIXED_TYPE: &str = "Flow\\Types\\Type\\Native\\MixedType"; pub struct ColumnValue(pub Zval); impl IntoZval for ColumnValue { - const TYPE: DataType = DataType::Object(Some("Flow\\ETL\\Column\\Column")); + const TYPE: DataType = DataType::object("Flow\\ETL\\Column\\Column"); const NULLABLE: bool = false; fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { @@ -48,25 +53,25 @@ fn rows(count: i64, name: &str) -> PhpResult { #[php_class] #[php( - name = "Flow\\ETL\\Column\\DefaultBackend", + name = "Flow\\ETL\\Column\\RustBackend", flags = ClassFlags::Final, implements(ce = backend_ce, stub = "Flow\\ETL\\Column\\Backend") )] -pub struct DefaultBackend; +pub struct RustBackend; #[php_impl] -impl DefaultBackend { +impl RustBackend { pub fn __construct() -> Self { - DefaultBackend + RustBackend } - pub fn builder(&self, definition: &Zval) -> PhpResult { + pub fn builder(&self, definition: &Zval) -> PhpResult { physical_for_definition(definition)?; - NativeColumnBuilder::for_definition(definition, definition_plan(definition)?) + RustColumnBuilder::for_definition(definition, definition_plan(definition)?) } - pub fn constant(&self, definition: &Zval, value: &Zval, count: i64) -> PhpResult { + pub fn constant(&self, definition: &Zval, value: &Zval, count: i64) -> PhpResult { let mut builder = self.builder(definition)?; let pending = builder.pending(value)?; @@ -74,7 +79,13 @@ impl DefaultBackend { builder.finish_column() } - pub fn decode(&self, definition: &Zval, buffers: &ZendHashTable, count: i64, nullCount: i64) -> PhpResult { + pub fn decode( + &self, + definition: &Zval, + buffers: &ZendHashTable, + count: i64, + nullCount: i64, + ) -> PhpResult { let plan = definition_plan(definition)?; let bytes = buffers .values() @@ -87,8 +98,13 @@ impl DefaultBackend { .collect::, _>>()?; let needed = buffer_count(&plan.kind).min(bytes.len()); - let data = decode(&plan.kind, &bytes[..needed], rows(count, "row count")?, rows(nullCount, "null count")?) - .map_err(|e| decode_exception(e, &plan.type_zv, &plan.kind))?; + let data = decode( + &plan.kind, + &bytes[..needed], + rows(count, "row count")?, + rows(nullCount, "null count")?, + ) + .map_err(|e| decode_exception(e, &plan.type_zv, &plan.kind))?; if bytes.len() > needed { let entry = call_method(definition, "entry", &mut [])?; @@ -101,16 +117,20 @@ impl DefaultBackend { ))); } - Ok(NativeColumn::new(arrow_array::make_array(data), plan)) + Ok(RustColumn::new(arrow_array::make_array(data), plan)) } pub fn adopt(&self, definition: &Zval, column: &Zval) -> PhpResult { - if column.extract::<&NativeColumn>().is_some() { + if column.extract::<&RustColumn>().is_some() { return Ok(ColumnValue(column.shallow_clone())); } if expect_object(&call_method(column, "type", &mut [])?, "a Type")?.instance_of(find_class(MIXED_TYPE)?) { - return Err(throw(call_static(COLUMN_MISMATCH, "untypedColumn", &mut [definition.shallow_clone()])?)); + return Err(throw(call_static( + COLUMN_MISMATCH, + "untypedColumn", + &mut [definition.shallow_clone()], + )?)); } let mut builder = self.builder(definition)?; @@ -140,3 +160,59 @@ impl DefaultBackend { crate::alloc::allocated_bytes() } } + +/// `$held` as `Rows` with every column adopted by `$backend` - what a Rust open source yields: the configured backend +/// keeps its own columns and copies the native ones. +pub fn adopt_batch(schema: &Zval, backend: &Zval, held: HeldBatch) -> PhpResult { + let definitions = call_method(schema, "definitions", &mut [])?; + let definitions = definitions + .array() + .ok_or_else(|| ext_exception("flow_php expected Schema::definitions() to return an array"))?; + let mut columns = ZendHashTable::with_capacity(definitions.len() as u32); + + ht_for_each(definitions, |name, index, definition| { + let key = column_key(name, index); + let column = ht_get(&held.columns, &key).ok_or_else(|| { + ext_exception(format!( + "flow_php expected the batch to hold the column \"{}\"", + String::from_utf8_lossy(&key) + )) + })?; + ht_insert( + &mut columns, + &key, + call_method( + backend, + "adopt", + &mut [definition.shallow_clone(), column.shallow_clone()], + )?, + ); + + Ok(()) + })?; + + let mut columns_zv = Zval::new(); + columns_zv.set_hashtable(columns); + + call_static( + "Flow\\ETL\\Rows", + "fromColumns", + &mut [schema.shallow_clone(), columns_zv, zval_long(held.count as i64)], + ) +} + +/// `$column` as a `RustColumn`'s plan and data: itself, or `RustBackend`'s adoption of it under `$definition`. +pub fn native_column(definition: &Zval, column: &Zval) -> PhpResult<(Rc, ArrayRef)> { + let adopted; + let native = match column.extract::<&RustColumn>() { + Some(native) => native, + None => { + adopted = RustBackend.adopt(definition, column)?.0; + adopted + .extract::<&RustColumn>() + .ok_or_else(|| ext_exception("flow_php expected RustBackend::adopt() to build a RustColumn"))? + } + }; + + Ok((Rc::clone(native.plan()), ArrayRef::clone(native.data()))) +} diff --git a/src/extension/flow-php-ext/src/batch_columns.rs b/src/extension/flow-php-ext/src/batch_columns.rs index bae7bc3a75..c0af6311eb 100644 --- a/src/extension/flow-php-ext/src/batch_columns.rs +++ b/src/extension/flow-php-ext/src/batch_columns.rs @@ -4,13 +4,16 @@ use std::rc::Rc; +use ext_php_rs::boxed::ZBox; use ext_php_rs::exception::PhpException; use ext_php_rs::types::{ZendHashTable, Zval}; use flow_batch_frame::kind::Kind; use crate::builder::{definition_nullable, schema_mismatch}; -use crate::cast::{bool_from_str, float_from_str, integer_from_str, json_gate, parse_iso_date, parse_iso_datetime, CastKind}; -use crate::column::NativeColumn; +use crate::cast::{ + bool_from_str, float_from_str, integer_from_str, json_gate, parse_iso_date, parse_iso_datetime, CastKind, +}; +use crate::column::RustColumn; use crate::ctx::{self, call_method, call_static, ht_for_each, ht_insert, ht_insert_long, zval_long}; use crate::date_check::iso_instant_micros; use crate::exception::ext_exception; @@ -132,7 +135,9 @@ impl BatchColumns { match pending { Some(state) if state.schema_json == json => state.schema = schema.shallow_clone(), Some(state) if state.rows > 0 => { - return Err(ext_exception(format!("flow_php cannot change the schema of a pending {what} batch"))); + return Err(ext_exception(format!( + "flow_php cannot change the schema of a pending {what} batch" + ))); } _ => { *pending = Some(Self::new(schema, json, batch_size)?); @@ -145,7 +150,9 @@ impl BatchColumns { if state.batch_size != batch_size { if state.rows > 0 { - return Err(ext_exception(format!("flow_php cannot change the batch size of a pending {what} batch"))); + return Err(ext_exception(format!( + "flow_php cannot change the batch size of a pending {what} batch" + ))); } state.batch_size = batch_size; @@ -164,16 +171,16 @@ impl BatchColumns { } } - /// The batch as `Rows::fromColumns()`, or its refusal: the lowest refused row (ties: the earliest definition), - /// else the lowest absent row (ties: the earliest definition) as `missingColumn`. The state is reset either way. - pub fn finish(&mut self) -> Result { + /// The batch's columns, or its refusal: the lowest refused row (ties: the earliest definition), else the lowest + /// absent row (ties: the earliest definition) as `missingColumn`. The state is reset either way. + pub fn finish(&mut self) -> Result { let batch = self.build(); self.reset(); batch } - fn build(&self) -> Result { + fn build(&self) -> Result { // min_by_key() keeps the first of equal rows: the earliest definition if let Some((row, cause)) = self .columns @@ -208,7 +215,7 @@ impl BatchColumns { .map_err(|e| invalid_argument(format!("flow_php built an invalid column: {e}")))?; let mut native = Zval::new(); ext_php_rs::convert::IntoZval::set_zval( - NativeColumn::new(arrow_array::make_array(data), Rc::clone(&column.plan)), + RustColumn::new(arrow_array::make_array(data), Rc::clone(&column.plan)), &mut native, false, )?; @@ -219,25 +226,33 @@ impl BatchColumns { } } - let mut columns_zv = Zval::new(); - columns_zv.set_hashtable(columns); - - call_static( - "Flow\\ETL\\Rows", - "fromColumns", - &mut [self.schema.shallow_clone(), columns_zv, zval_long(self.rows as i64)], - ) + Ok(HeldBatch { + columns, + count: self.rows, + }) } } +/// A batch's native columns keyed as its schema's definitions, before the configured backend adopts them. +pub struct HeldBatch { + pub columns: ZBox, + pub count: usize, +} + /// A text value `cast.rs` casts natively, appended in its physical form; `false` hands it to the PHP lane. pub fn native_text(values: &mut KindBuilder, kind: &Kind, cast: &CastKind, bytes: &[u8]) -> Result { match (kind, cast) { - (Kind::Int64, CastKind::Integer) => Ok(integer_from_str(bytes).map(|value| values.append_fixed(&value.to_le_bytes())).is_some()), - (Kind::Float64, CastKind::Float) => Ok(float_from_str(bytes).map(|value| values.append_fixed(&value.to_le_bytes())).is_some()), + (Kind::Int64, CastKind::Integer) => Ok(integer_from_str(bytes) + .map(|value| values.append_fixed(&value.to_le_bytes())) + .is_some()), + (Kind::Float64, CastKind::Float) => Ok(float_from_str(bytes) + .map(|value| values.append_fixed(&value.to_le_bytes())) + .is_some()), (Kind::Boolean, CastKind::Boolean) => Ok(bool_from_str(bytes).map(|value| values.append_bool(value)).is_some()), (Kind::Bytes, CastKind::String) => values.append_bytes(bytes).map(|()| true).map_err(overflow), - (Kind::Bytes, CastKind::NonEmptyString) if !bytes.is_empty() => values.append_bytes(bytes).map(|()| true).map_err(overflow), + (Kind::Bytes, CastKind::NonEmptyString) if !bytes.is_empty() => { + values.append_bytes(bytes).map(|()| true).map_err(overflow) + } (Kind::Bytes, CastKind::Json) if json_gate(bytes) && json_valid(bytes) => { values.append_bytes(bytes).map(|()| true).map_err(overflow) } @@ -246,7 +261,9 @@ pub fn native_text(values: &mut KindBuilder, kind: &Kind, cast: &CastKind, bytes } (Kind::Timestamp, CastKind::DateTime(zone)) => Ok(match iso_instant_micros(bytes) { Some(micros) => Some(micros), - None => parse_iso_datetime(bytes, zone)?.and_then(|(_, instant)| instant.object().and_then(datetime_micros)), + None => { + parse_iso_datetime(bytes, zone)?.and_then(|(_, instant)| instant.object().and_then(datetime_micros)) + } } .map(|micros| values.append_fixed(µs.to_le_bytes())) .is_some()), diff --git a/src/extension/flow-php-ext/src/builder.rs b/src/extension/flow-php-ext/src/builder.rs index 3711f98ede..06463e724b 100644 --- a/src/extension/flow-php-ext/src/builder.rs +++ b/src/extension/flow-php-ext/src/builder.rs @@ -1,4 +1,4 @@ -//! `Flow\ETL\Column\NativeColumnBuilder`: `CastingColumnBuilder` over arrow storage. A value takes the native lane +//! `Flow\ETL\Column\RustColumnBuilder`: `CastingColumnBuilder` over arrow storage. A value takes the native lane //! where `cast.rs` casts it natively; every other value, and every value the native lane refuses, runs PHP's //! `$type->cast()` then `$physical->toPhysical()`, so results and refusals are PHP's own. @@ -13,10 +13,10 @@ use ext_php_rs::types::{ZendHashTable, ZendObject, Zval}; use flow_batch_frame::kind::Kind; use crate::cast::{cast_value, CastKind, MapKeyKind}; -use crate::column::NativeColumn; +use crate::column::RustColumn; use crate::ctx::{ - self, call_handle_catching, call_method, call_static, construct_with_zvals, expect_object, find_class, - ht_for_each, ht_get, null_zval, read_slot, transparent_exception, zval_long, + self, call_handle_catching, call_method, call_static, construct, expect_object, find_class, ht_for_each, ht_get, + null_zval, read_slot, transparent_exception, zval_long, }; use crate::date_check::iso_instant_micros; use crate::exception::ext_exception; @@ -41,7 +41,7 @@ pub enum Native { Bytes(Zval), } -/// One value ready to append, for `DefaultBackend::constant()`. +/// One value ready to append, for `RustBackend::constant()`. pub enum Pending { Null, Native(Native), @@ -59,7 +59,10 @@ pub enum Append { Done, /// `cause` is the `ColumnMismatchException` a positioned append wraps; `raised` the `Flow\Types` exception an /// unpositioned append rethrows (`None` for a NOT NULL null). - Refused { cause: Zval, raised: Option> }, + Refused { + cause: Zval, + raised: Option>, + }, } fn string_slot(object: &ZendObject, slot: u32) -> Option { @@ -75,7 +78,10 @@ pub fn native_lane(plan: &TypePlan, value: &Zval) -> Result, PhpE pub(crate) fn native_leaf(kind: &Kind, cast_kind: &CastKind, value: &Zval) -> Result, PhpException> { if let (Kind::Timestamp, CastKind::DateTime(_)) = (kind, cast_kind) { - if let Some(micros) = value.zend_str().and_then(|string| iso_instant_micros(string.as_bytes())) { + if let Some(micros) = value + .zend_str() + .and_then(|string| iso_instant_micros(string.as_bytes())) + { return Ok(Some(Native::Fixed(micros.to_le_bytes()))); } } @@ -128,7 +134,12 @@ fn nested(kind: &Kind) -> bool { /// Casts `value` straight into `builder`, element by element. `Ok(false)`: Rust does not cast this value, and the row /// is left half-appended for the caller to truncate before the PHP lane casts the whole value. -fn append_cast(builder: &mut KindBuilder, kind: &Kind, cast_kind: &CastKind, value: &Zval) -> Result { +fn append_cast( + builder: &mut KindBuilder, + kind: &Kind, + cast_kind: &CastKind, + value: &Zval, +) -> Result { let value = value.dereference(); match (kind, cast_kind) { @@ -235,7 +246,7 @@ fn append_cast(builder: &mut KindBuilder, kind: &Kind, cast_kind: &CastKind, val } } -/// One value, as `NativeColumnBuilder::appendMany()` appends it: a null is refused under NOT NULL; a nested value +/// One value, as `RustColumnBuilder::appendMany()` appends it: a null is refused under NOT NULL; a nested value /// takes `append_cast()`, a leaf the native lane, and what neither casts the PHP lane. Exceptions other than /// `Flow\Types` ones escape as thrown. pub fn append_one( @@ -304,7 +315,8 @@ pub fn append_one( /// `$type->cast($value)`, then `$physical->toPhysical($cast)` unless the physical is the identity. pub fn php_lane(plan: &TypePlan, value: &Zval) -> Result { let type_obj = plan.type_zv.object().expect("a plan's type is an object"); - let cast = call_handle_catching(plan.cast_fn, Some(type_obj), &mut [value.shallow_clone()]).map_err(Refusal::Cast)?; + let cast = + call_handle_catching(plan.cast_fn, Some(type_obj), &mut [value.shallow_clone()]).map_err(Refusal::Cast)?; if plan.identity { return Ok(cast); @@ -346,8 +358,7 @@ pub fn throw(mut exception: Zval) -> PhpException { /// `new SchemaMismatchException($position, $cause)`. pub fn schema_mismatch(position: Zval, cause: Zval) -> PhpException { - let built = find_class(SCHEMA_MISMATCH) - .and_then(|ce| construct_with_zvals(ce, &mut [position, cause], "a SchemaMismatchException")); + let built = find_class(SCHEMA_MISMATCH).and_then(|ce| construct(ce, &mut [position, cause])); match built { Ok(mut exception) => transparent_exception(&mut exception), @@ -367,18 +378,18 @@ pub fn is_types_exception(exception: &ZendObject) -> Result #[php_class] #[php( - name = "Flow\\ETL\\Column\\NativeColumnBuilder", + name = "Flow\\ETL\\Column\\RustColumnBuilder", flags = ClassFlags::Final, implements(ce = column_builder_ce, stub = "Flow\\ETL\\Column\\ColumnBuilder") )] -pub struct NativeColumnBuilder { +pub struct RustColumnBuilder { definition: Zval, nullable: bool, plan: Rc, values: KindBuilder, } -impl NativeColumnBuilder { +impl RustColumnBuilder { pub fn for_definition(definition: &Zval, plan: Rc) -> Result { Ok(Self { definition: definition.shallow_clone(), @@ -388,7 +399,7 @@ impl NativeColumnBuilder { }) } - /// One value for `DefaultBackend::constant()`: refusals escape as PHP threw them. + /// One value for `RustBackend::constant()`: refusals escape as PHP threw them. pub fn pending(&self, value: &Zval) -> Result { let value = value.dereference(); @@ -433,13 +444,13 @@ impl NativeColumnBuilder { Ok(()) } - fn same_kind<'a>(&self, column: &'a Zval) -> Option<&'a NativeColumn> { + fn same_kind<'a>(&self, column: &'a Zval) -> Option<&'a RustColumn> { column - .extract::<&NativeColumn>() + .extract::<&RustColumn>() .filter(|native| native.data().data_type() == &flow_batch_frame::kind::data_type(&self.plan.kind)) } - /// `count` copies of one value, for `DefaultBackend::constant()`. + /// `count` copies of one value, for `RustBackend::constant()`. pub fn append_repeated(&mut self, pending: Pending, count: u32) -> Result<(), PhpException> { match pending { Pending::Null => (0..count).for_each(|_| self.values.append_null()), @@ -458,7 +469,9 @@ impl NativeColumnBuilder { ); for _ in 0..count { - self.values.append_from(one.as_ref(), &self.plan.kind, 0).map_err(overflow)?; + self.values + .append_from(one.as_ref(), &self.plan.kind, 0) + .map_err(overflow)?; } } } @@ -466,13 +479,13 @@ impl NativeColumnBuilder { Ok(()) } - pub fn finish_column(&self) -> Result { + pub fn finish_column(&self) -> Result { let data = self .values .finish(&self.plan.kind) .map_err(|e| invalid_argument(format!("flow_php built an invalid column: {e}")))?; - Ok(NativeColumn::new(arrow_array::make_array(data), Rc::clone(&self.plan))) + Ok(RustColumn::new(arrow_array::make_array(data), Rc::clone(&self.plan))) } } @@ -484,9 +497,11 @@ fn index(i: i64, count: usize) -> Result { } #[php_impl] -impl NativeColumnBuilder { +impl RustColumnBuilder { pub fn __construct() -> PhpResult { - Err(ext_exception("Flow\\ETL\\Column\\NativeColumnBuilder is built by DefaultBackend")) + Err(ext_exception( + "Flow\\ETL\\Column\\RustColumnBuilder is built by RustBackend", + )) } pub fn append(&mut self, value: &Zval) -> PhpResult<()> { @@ -504,10 +519,13 @@ impl NativeColumnBuilder { pub fn append_many(&mut self, values: &ZendHashTable) -> PhpResult<()> { let start = self.values.len(); let result = ht_for_each(values, |string_key, index, value| { - self.append_value(value, Some(&|| match string_key { - Some(name) => crate::ctx::zval_str(name.as_bytes()), - None => zval_long(index as i64), - })) + self.append_value( + value, + Some(&|| match string_key { + Some(name) => crate::ctx::zval_str(name.as_bytes()), + None => zval_long(index as i64), + }), + ) }); if result.is_err() { @@ -529,7 +547,11 @@ impl NativeColumnBuilder { .map_err(overflow); } - self.not_null(call_method(column, "isNull", &mut [zval_long(i)])?.bool().unwrap_or(false))?; + self.not_null( + call_method(column, "isNull", &mut [zval_long(i)])? + .bool() + .unwrap_or(false), + )?; let physical = call_method(column, "at", &mut [zval_long(i)])?; append_physical(&mut self.values, &self.plan.kind, &physical) @@ -542,7 +564,11 @@ impl NativeColumnBuilder { let mut rows = Vec::with_capacity(indices.len()); ht_for_each(indices, |_, _, i| { - let row = index(i.long().ok_or_else(|| invalid_argument("flow_php column indices must be ints".into()))?, data.len())?; + let row = index( + i.long() + .ok_or_else(|| invalid_argument("flow_php column indices must be ints".into()))?, + data.len(), + )?; self.not_null(matches!(self.plan.kind, Kind::Null) || data.is_null(row))?; rows.push(row); @@ -550,14 +576,18 @@ impl NativeColumnBuilder { })?; for row in rows { - self.values.append_from(data.as_ref(), &self.plan.kind, row).map_err(overflow)?; + self.values + .append_from(data.as_ref(), &self.plan.kind, row) + .map_err(overflow)?; } return Ok(()); } let all = call_method(column, "physicals", &mut [])?; - let all = all.array().ok_or_else(|| ext_exception("flow_php expected Column::physicals() to return an array"))?; + let all = all + .array() + .ok_or_else(|| ext_exception("flow_php expected Column::physicals() to return an array"))?; let mut physicals = Vec::with_capacity(indices.len()); ht_for_each(indices, |_, _, i| { @@ -582,7 +612,7 @@ impl NativeColumnBuilder { self.values.len() as i64 } - pub fn finish(&self) -> PhpResult { + pub fn finish(&self) -> PhpResult { self.finish_column() } } diff --git a/src/extension/flow-php-ext/src/cast.rs b/src/extension/flow-php-ext/src/cast.rs index 0b0b47c113..46280c4a43 100644 --- a/src/extension/flow-php-ext/src/cast.rs +++ b/src/extension/flow-php-ext/src/cast.rs @@ -315,23 +315,25 @@ pub(crate) fn float_from_str(bytes: &[u8]) -> Option { /// The instant an ISO string names, parsed as `DateTimeType::cast` parses it (before moving it into the column zone); /// any other string is gated on StringTemporalParts, a PHP class, so it bails. pub(crate) fn parse_iso_datetime(bytes: &[u8], zone: &[u8]) -> Result, PhpException> { - Ok(match iso_date_time_gate(bytes).or_else(|| iso_date_gate(bytes).then_some(IsoSuffix::Naive)) { - Some(IsoSuffix::Zulu) => { - // mirrors DateTimeType::cast's Z branch - let local = bytes.strip_suffix(b"\n").unwrap_or(bytes); - let local = local.strip_suffix(b"Z").unwrap_or(local); - let mut utc = ctx::timezone(b"UTC")?; - - date_from_free_form(local, Some(&mut utc))?.map(|instant| (IsoSuffix::Zulu, instant)) - } - Some(IsoSuffix::Offset) => date_from_free_form(bytes, None)?.map(|instant| (IsoSuffix::Offset, instant)), - Some(IsoSuffix::Naive) => { - let mut column = ctx::timezone(zone)?; + Ok( + match iso_date_time_gate(bytes).or_else(|| iso_date_gate(bytes).then_some(IsoSuffix::Naive)) { + Some(IsoSuffix::Zulu) => { + // mirrors DateTimeType::cast's Z branch + let local = bytes.strip_suffix(b"\n").unwrap_or(bytes); + let local = local.strip_suffix(b"Z").unwrap_or(local); + let mut utc = ctx::timezone(b"UTC")?; + + date_from_free_form(local, Some(&mut utc))?.map(|instant| (IsoSuffix::Zulu, instant)) + } + Some(IsoSuffix::Offset) => date_from_free_form(bytes, None)?.map(|instant| (IsoSuffix::Offset, instant)), + Some(IsoSuffix::Naive) => { + let mut column = ctx::timezone(zone)?; - date_from_free_form(bytes, Some(&mut column))?.map(|instant| (IsoSuffix::Naive, instant)) - } - None => None, - }) + date_from_free_form(bytes, Some(&mut column))?.map(|instant| (IsoSuffix::Naive, instant)) + } + None => None, + }, + ) } /// `DateType::cast` of an ISO date string: midnight UTC. @@ -598,10 +600,7 @@ fn cast_date(value: &Zval) -> Result, PhpException> { set_midnight(set_time, object) } -fn set_midnight( - set_time: &'static Function, - object: &ZendObject, -) -> Result, PhpException> { +fn set_midnight(set_time: &'static Function, object: &ZendObject) -> Result, PhpException> { let mut args = [zval_long(0), zval_long(0), zval_long(0), zval_long(0)]; let Ok(result) = call_handle_transparent(set_time, Some(object), &mut args) else { @@ -642,8 +641,7 @@ fn cast_json(value: &Zval) -> Result, PhpException> { if value.is_array() { // Json::fromArray's json_encode, in its non-throwing flavor: `false` // (or a thrown JsonSerializable) bails to the PHP cast - let Ok(encoded) = call_handle_transparent(ctx::json_encode()?, None, &mut [value.shallow_clone()]) - else { + let Ok(encoded) = call_handle_transparent(ctx::json_encode()?, None, &mut [value.shallow_clone()]) else { return Ok(None); }; diff --git a/src/extension/flow-php-ext/src/column.rs b/src/extension/flow-php-ext/src/column.rs index fc98d160bd..315b08a714 100644 --- a/src/extension/flow-php-ext/src/column.rs +++ b/src/extension/flow-php-ext/src/column.rs @@ -1,4 +1,4 @@ -//! `Flow\ETL\Column\NativeColumn`: one arrow array of the column's kind, read as the PHP columns read. +//! `Flow\ETL\Column\RustColumn`: one arrow array of the column's kind, read as the PHP columns read. use std::rc::Rc; @@ -26,7 +26,7 @@ use crate::render::{invalid_argument, offset_overflow}; pub struct TypeObject(Zval); impl IntoZval for TypeObject { - const TYPE: DataType = DataType::Object(Some("Flow\\Types\\Type")); + const TYPE: DataType = DataType::object("Flow\\Types\\Type"); const NULLABLE: bool = false; fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { @@ -38,16 +38,16 @@ impl IntoZval for TypeObject { #[php_class] #[php( - name = "Flow\\ETL\\Column\\NativeColumn", + name = "Flow\\ETL\\Column\\RustColumn", flags = ClassFlags::Final, implements(ce = column_ce, stub = "Flow\\ETL\\Column\\Column") )] -pub struct NativeColumn { +pub struct RustColumn { data: ArrayRef, plan: Rc, } -impl NativeColumn { +impl RustColumn { pub fn new(data: ArrayRef, plan: Rc) -> Self { debug_assert_eq!(data.data_type(), &data_type(&plan.kind)); @@ -113,7 +113,11 @@ fn retype(from: Zval, to: Zval, array: &ArrayRef, kind: &Kind) -> Result<(), Php call_method( &instance("Flow\\ETL\\Column\\Php\\Retype")?, "assert", - &mut [from.shallow_clone(), to.shallow_clone(), zval_long(null_count(array.as_ref(), kind) as i64)], + &mut [ + from.shallow_clone(), + to.shallow_clone(), + zval_long(null_count(array.as_ref(), kind) as i64), + ], )?; match kind { @@ -151,8 +155,11 @@ fn retype(from: Zval, to: Zval, array: &ArrayRef, kind: &Kind) -> Result<(), Php let from_elements: Vec<&Zval> = from_elements.array().map(|a| a.values().collect()).unwrap_or_default(); let to_elements: Vec<&Zval> = to_elements.array().map(|a| a.values().collect()).unwrap_or_default(); - for (((field, child), from_element), to_element) in - fields.iter().zip(structure.columns()).zip(from_elements).zip(to_elements) + for (((field, child), from_element), to_element) in fields + .iter() + .zip(structure.columns()) + .zip(from_elements) + .zip(to_elements) { let from_element = expect_object(from_element, "a StructureElement")?; let to_element = expect_object(to_element, "a StructureElement")?; @@ -194,9 +201,9 @@ fn class_name(zv: &Zval) -> String { } #[php_impl] -impl NativeColumn { +impl RustColumn { pub fn __construct() -> PhpResult { - Err(ext_exception("Flow\\ETL\\Column\\NativeColumn is built by DefaultBackend")) + Err(ext_exception("Flow\\ETL\\Column\\RustColumn is built by RustBackend")) } #[php(name = "type")] @@ -236,9 +243,11 @@ impl NativeColumn { self.rows(|i| value_at(self.data.as_ref(), self.kind(), &self.plan.values, i)) } - pub fn slice(&self, offset: i64, length: i64) -> PhpResult { + pub fn slice(&self, offset: i64, length: i64) -> PhpResult { let (Ok(offset), Ok(length)) = (usize::try_from(offset), usize::try_from(length)) else { - return Err(invalid_argument(format!("flow_php cannot slice {length} rows from row {offset}"))); + return Err(invalid_argument(format!( + "flow_php cannot slice {length} rows from row {offset}" + ))); }; if offset.checked_add(length).is_none_or(|end| end > self.data.len()) { @@ -248,10 +257,10 @@ impl NativeColumn { ))); } - Ok(NativeColumn::new(self.data.slice(offset, length), Rc::clone(&self.plan))) + Ok(RustColumn::new(self.data.slice(offset, length), Rc::clone(&self.plan))) } - pub fn take(&self, indices: &ZendHashTable) -> PhpResult { + pub fn take(&self, indices: &ZendHashTable) -> PhpResult { let mut rows = Vec::with_capacity(indices.len()); ht_for_each(indices, |_, _, index| { @@ -266,12 +275,17 @@ impl NativeColumn { let data = arrow_select::take::take(self.data.as_ref(), &UInt32Array::from(rows), None) .map_err(|e| invalid_argument(format!("flow_php failed to take column rows: {e}")))?; - Ok(NativeColumn::new(data, Rc::clone(&self.plan))) + Ok(RustColumn::new(data, Rc::clone(&self.plan))) } #[php(name = "withType")] - pub fn with_type(&self, r#type: &Zval) -> PhpResult { - retype(self.plan.type_zv.shallow_clone(), r#type.shallow_clone(), &self.data, self.kind())?; + pub fn with_type(&self, r#type: &Zval) -> PhpResult { + retype( + self.plan.type_zv.shallow_clone(), + r#type.shallow_clone(), + &self.data, + self.kind(), + )?; let plan = type_plan(r#type)?; if data_type(&plan.kind) != data_type(self.kind()) { @@ -282,19 +296,19 @@ impl NativeColumn { ))); } - Ok(NativeColumn::new(self.data.clone(), plan)) + Ok(RustColumn::new(self.data.clone(), plan)) } - pub fn concat(&self, others: &[&Zval]) -> PhpResult { + pub fn concat(&self, others: &[&Zval]) -> PhpResult { let mut arrays: Vec<&dyn Array> = vec![self.data.as_ref()]; for other in others { let native = other - .extract::<&NativeColumn>() + .extract::<&RustColumn>() .filter(|native| native.data.data_type() == self.data.data_type()) .ok_or_else(|| { invalid_argument(format!( - "Flow\\ETL\\Column\\NativeColumn cannot concat {}", + "Flow\\ETL\\Column\\RustColumn cannot concat {}", class_name(other) )) })?; @@ -306,7 +320,7 @@ impl NativeColumn { e => invalid_argument(format!("flow_php failed to concat columns: {e}")), })?; - Ok(NativeColumn::new(data, Rc::clone(&self.plan))) + Ok(RustColumn::new(data, Rc::clone(&self.plan))) } pub fn encode(&self) -> PhpResult> { diff --git a/src/extension/flow-php-ext/src/csv/columns.rs b/src/extension/flow-php-ext/src/csv/columns.rs index bd7bf41391..b9f0ed0808 100644 --- a/src/extension/flow-php-ext/src/csv/columns.rs +++ b/src/extension/flow-php-ext/src/csv/columns.rs @@ -1,10 +1,10 @@ -//! `RustCSVReaderNative::nextColumns()`: CSV cells straight into native columns through `BatchColumns`; a NOT NULL +//! `RustCSVOpenSource::batches()`: CSV cells straight into native columns through `BatchColumns`; a NOT NULL //! column absent from the header is absent from every row. use ext_php_rs::exception::PhpException; use ext_php_rs::types::Zval; -use crate::batch_columns::{native_text, BatchColumn, BatchColumns}; +use crate::batch_columns::{native_text, BatchColumn, BatchColumns, HeldBatch}; use crate::builder::{is_types_exception, php_lane, value_does_not_match, Refusal}; use crate::csv::CsvReader; use crate::ctx::{null_zval, transparent_exception, zval_str}; @@ -69,15 +69,19 @@ pub fn next_columns( pending: &mut CsvColumns, schema: &Zval, batch_size: usize, -) -> Result { +) -> Result, PhpException> { if reader.headers().is_empty() { - return Ok(null_zval()); + return Ok(None); } let (state, rebuilt) = BatchColumns::prepare(&mut pending.batch, schema, batch_size, "CSV")?; if rebuilt { - pending.fields = state.columns.iter().map(|column| reader.field_of(&column.key.name())).collect(); + pending.fields = state + .columns + .iter() + .map(|column| reader.field_of(&column.key.name())) + .collect(); } while state.rows < state.batch_size && reader.next_record() { @@ -109,8 +113,8 @@ pub fn next_columns( } if state.rows == 0 || (state.rows < state.batch_size && !reader.is_finished()) { - return Ok(null_zval()); + return Ok(None); } - state.finish() + state.finish().map(Some) } diff --git a/src/extension/flow-php-ext/src/csv/fold.rs b/src/extension/flow-php-ext/src/csv/fold.rs index 74a3800632..05a37309ab 100644 --- a/src/extension/flow-php-ext/src/csv/fold.rs +++ b/src/extension/flow-php-ext/src/csv/fold.rs @@ -9,9 +9,9 @@ use std::collections::HashMap; use ext_php_rs::exception::PhpException; use ext_php_rs::types::{ZendHashTable, Zval}; -use crate::ctx::{self, call_handle, zval_str}; use crate::csv::php_trim; use crate::csv::tokenizer::is_space; +use crate::ctx::{self, call_handle, zval_str}; use crate::date_check::{checkdate, iso_date_gate, iso_date_time_gate}; use crate::exception::ext_exception; use crate::json_check::json_valid; @@ -133,9 +133,7 @@ pub struct Narrower { impl Narrower { fn new(candidates: Candidates) -> Result { - Ok(Self { - candidates, - }) + Ok(Self { candidates }) } pub fn narrow(&mut self, value: &[u8]) -> Result { @@ -190,7 +188,12 @@ impl Narrower { } // same one-sided rule as the cast: only PHP may say "not JSON" - let valid = call_handle(ctx::json_validate()?, None, &mut [zval_str(value)], "validate a JSON cell")?; + let valid = call_handle( + ctx::json_validate()?, + None, + &mut [zval_str(value)], + "validate a JSON cell", + )?; Ok(valid.bool().unwrap_or(false)) } @@ -206,7 +209,12 @@ impl Narrower { return Ok(Some(Leaf::Date)); } - let parts_zv = call_handle(ctx::date_parse()?, None, &mut [zval_str(value)], "parse a temporal cell")?; + let parts_zv = call_handle( + ctx::date_parse()?, + None, + &mut [zval_str(value)], + "parse a temporal cell", + )?; let parts = parts_zv .array() .ok_or_else(|| ext_exception("flow_php expected date_parse() to return an array"))?; @@ -259,14 +267,22 @@ fn is_null(value: &[u8]) -> bool { /// `Json::isValid()`'s shape gate before `json_validate()`. fn is_json_shaped(value: &[u8]) -> bool { - matches!((value.first(), value.last()), (Some(b'{'), Some(b'}')) | (Some(b'['), Some(b']'))) + matches!( + (value.first(), value.last()), + (Some(b'{'), Some(b'}')) | (Some(b'['), Some(b']')) + ) } /// PHP 8 `is_numeric()` on a string: optional leading and trailing whitespace, optional sign, /// `digits[.digits] | .digits | digits.`, optional exponent. No hex, no `INF`/`NAN`. fn is_numeric(value: &[u8]) -> bool { let mut position = value.iter().take_while(|byte| is_space(**byte)).count(); - let end = value.len() - value[position..].iter().rev().take_while(|byte| is_space(**byte)).count(); + let end = value.len() + - value[position..] + .iter() + .rev() + .take_while(|byte| is_space(**byte)) + .count(); if matches!(value.get(position), Some(b'+' | b'-')) { position += 1; @@ -336,7 +352,10 @@ fn has_explicit_day(value: &[u8]) -> bool { return true; } - groups >= 2 && value.windows(3).any(|window| window.iter().all(u8::is_ascii_alphabetic)) + groups >= 2 + && value + .windows(3) + .any(|window| window.iter().all(u8::is_ascii_alphabetic)) } /// `StringTypeNarrower::isTimeZone()`'s `/^[+-]\d{2}:\d{2}$/` on a trimmed value. @@ -352,7 +371,7 @@ struct Column { /// `ColumnTypes::observe()` over whole rows: names seeded `null` (then widened), names met only in rows start at /// their first observed type; a `string` / `?string` column skips non-null cells. pub struct Fold { - pub narrower: Narrower, + narrower: Narrower, columns: Vec, index: HashMap, usize>, rows: u64, @@ -381,7 +400,12 @@ impl Fold { } /// One cell of the current row; `None` is a null cell. `position` caches the cell's column across rows. - pub fn observe(&mut self, name: &[u8], position: &mut Option, value: Option<&[u8]>) -> Result<(), PhpException> { + pub fn observe( + &mut self, + name: &[u8], + position: &mut Option, + value: Option<&[u8]>, + ) -> Result<(), PhpException> { if position.is_none() { *position = self.index.get(name).copied(); } @@ -424,7 +448,9 @@ impl Fold { /// Column name => type code, first-seen order. pub fn types(&self) -> impl Iterator { - self.columns.iter().map(|column| (column.name.as_slice(), column.kind.code())) + self.columns + .iter() + .map(|column| (column.name.as_slice(), column.kind.code())) } } diff --git a/src/extension/flow-php-ext/src/csv/mod.rs b/src/extension/flow-php-ext/src/csv/mod.rs index 58e5d065ab..0d99539bf3 100644 --- a/src/extension/flow-php-ext/src/csv/mod.rs +++ b/src/extension/flow-php-ext/src/csv/mod.rs @@ -3,6 +3,11 @@ pub mod columns; pub mod fold; +#[allow( + non_snake_case, + reason = "PHP takes a parameter name from its Rust identifier: the contracts' are camelCase" +)] +pub mod source; pub mod tokenizer; pub mod write; @@ -133,7 +138,12 @@ impl CsvReader { self.resolve_headers(); self.headers.is_some() - && next_row(&mut self.first_row_pending, &mut self.tokenizer, &mut self.record, &mut self.consumed_bytes) + && next_row( + &mut self.first_row_pending, + &mut self.tokenizer, + &mut self.record, + &mut self.consumed_bytes, + ) } /// The current row's cell of `field`, as `CSVRowNormalizer::normalize()` shapes it; `None` is null. @@ -168,7 +178,12 @@ impl CsvReader { }; while batch.len() < batch_size { - if !next_row(&mut self.first_row_pending, &mut self.tokenizer, &mut self.record, &mut self.consumed_bytes) { + if !next_row( + &mut self.first_row_pending, + &mut self.tokenizer, + &mut self.record, + &mut self.consumed_bytes, + ) { break; } @@ -193,7 +208,12 @@ impl CsvReader { let mut positions = vec![None; self.cells.len()]; while limit.is_none_or(|limit| folded < limit) { - if !next_row(&mut self.first_row_pending, &mut self.tokenizer, &mut self.record, &mut self.consumed_bytes) { + if !next_row( + &mut self.first_row_pending, + &mut self.tokenizer, + &mut self.record, + &mut self.consumed_bytes, + ) { break; } @@ -239,13 +259,19 @@ impl CsvReader { } else { self.first_row_pending = true; - (0..record.len()).map(|index| Header::new(format!("e{index:02}").into_bytes())).collect() + (0..record.len()) + .map(|index| Header::new(format!("e{index:02}").into_bytes())) + .collect() }); let headers = self.headers.as_ref().expect("resolved above"); for (index, header) in headers.iter().enumerate() { - match self.cells.iter_mut().find(|cell| headers[cell.header_index].name == header.name) { + match self + .cells + .iter_mut() + .find(|cell| headers[cell.header_index].name == header.name) + { Some(cell) => cell.field_index = index, None => self.cells.push(Cell { header_index: index, @@ -303,7 +329,10 @@ fn row_values(headers: &[Header], record: &Record, empty_to_null: bool) -> Zval pub fn php_trim(bytes: &[u8]) -> &[u8] { let is_trimmed = |byte: &u8| matches!(byte, b' ' | b'\t' | b'\n' | b'\r' | b'\0' | 0x0B); let start = bytes.iter().position(|byte| !is_trimmed(byte)).unwrap_or(bytes.len()); - let end = bytes.iter().rposition(|byte| !is_trimmed(byte)).map_or(start, |end| end + 1); + let end = bytes + .iter() + .rposition(|byte| !is_trimmed(byte)) + .map_or(start, |end| end + 1); &bytes[start..end] } diff --git a/src/extension/flow-php-ext/src/csv/source.rs b/src/extension/flow-php-ext/src/csv/source.rs new file mode 100644 index 0000000000..cf994f1a7e --- /dev/null +++ b/src/extension/flow-php-ext/src/csv/source.rs @@ -0,0 +1,434 @@ +//! `Flow\ETL\Adapter\CSV\RustCSVOpenSource`: one CSV file read through the native tokenizer - the stream fed in chunks +//! (a `NativeLocalSourceStream` in `CHUNK`s, any other stream in `$charactersReadInLine`), batches as native columns +//! adopted by the configured backend, records as PHP arrays, the type sniff folded natively. + +use std::cell::{Cell, RefCell}; +use std::collections::VecDeque; +use std::rc::Rc; + +use ext_php_rs::binary_slice::BinarySlice; +use ext_php_rs::convert::IntoZval; +use ext_php_rs::error::Result as ZvalResult; +use ext_php_rs::flags::{ClassFlags, DataType}; +use ext_php_rs::prelude::*; +use ext_php_rs::types::{ZendHashTable, Zval}; + +use crate::batch_columns::{batch_size_of, HeldBatch}; +use crate::csv::columns::{next_columns, CsvColumns}; +use crate::csv::fold::{string_values, Fold}; +use crate::csv::CsvReader; +use crate::ctx::{call_function, call_method, call_static, construct, find_class, ht_insert, zval_long, zval_str}; +use crate::exception::ext_exception; +use crate::interfaces::csv_open_source_ce; +use crate::iterator::RustIterator; +use crate::source::{self, reading, Fed, CHUNK}; + +const CLASS: &str = "RustCSVOpenSource"; +const RECORDS_BATCH: usize = 1000; +const NATIVE_LOCAL_SOURCE_STREAM: &str = "Flow\\Filesystem\\Stream\\NativeLocalSourceStream"; +const STRING_TYPE_NARROWER: &str = "Flow\\Types\\Type\\Native\\String\\StringTypeNarrower"; +const SCHEMA_INFERRER: &str = "Flow\\ETL\\Schema\\Inference\\SchemaInferrer"; +/// The candidates the native fold narrows to, in `StringTypeNarrower`'s order; HTML and XML are never folded natively. +const FOLDED: [&str; 8] = [ + "Flow\\Types\\DSL\\type_json", + "Flow\\Types\\DSL\\type_uuid", + "Flow\\Types\\DSL\\type_float", + "Flow\\Types\\DSL\\type_integer", + "Flow\\Types\\DSL\\type_datetime", + "Flow\\Types\\DSL\\type_date", + "Flow\\Types\\DSL\\type_boolean", + "Flow\\Types\\DSL\\type_time_zone", +]; + +/// A contract method's `array` return. +pub struct ArrayValue(Zval); + +impl IntoZval for ArrayValue { + const TYPE: DataType = DataType::Array; + const NULLABLE: bool = false; + + fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { + *zv = self.0; + + Ok(()) + } +} + +/// `CSVOpenSource::sniff()`'s return, typed `Flow\ETL\Schema\Inference\ColumnTypes`. +pub struct ColumnTypesValue(Zval); + +impl IntoZval for ColumnTypesValue { + const TYPE: DataType = DataType::object("Flow\\ETL\\Schema\\Inference\\ColumnTypes"); + const NULLABLE: bool = false; + + fn set_zval(self, zv: &mut Zval, _persistent: bool) -> ZvalResult<()> { + *zv = self.0; + + Ok(()) + } +} + +struct Reading { + reader: CsvReader, + columns: CsvColumns, +} + +struct Shared { + stream: Zval, + chunk_size: i64, + reading: RefCell, + produced_rows: Cell, + produced_bytes: Cell, +} + +impl Shared { + /// `f` over the reader, no PHP stream call inside; `producedBytes()` follows what it consumed. + fn with(&self, f: impl FnOnce(&mut Reading) -> PhpResult) -> PhpResult { + let mut reading = reading(&self.reading, CLASS)?; + let result = f(&mut reading); + self.produced_bytes.set(reading.reader.consumed_bytes()); + + result + } + + fn produced(&self, rows: u64) { + self.produced_rows.set(self.produced_rows.get() + rows); + } + + /// `$stream->iterate($chunkSize)`, the generator one consuming method feeds from. + fn chunks(&self) -> PhpResult { + call_method(&self.stream, "iterate", &mut [zval_long(self.chunk_size)]) + } + + /// The next chunk of `chunks` fed to the reader; false once the generator is exhausted. The generator runs with no + /// borrow held: the stream may call back into the source. + fn feed(&self, chunks: &Zval) -> PhpResult { + if !call_method(chunks, "valid", &mut [])?.bool().unwrap_or(false) { + return Ok(false); + } + + let chunk = call_method(chunks, "current", &mut [])?; + let bytes = chunk + .zend_str() + .ok_or_else(|| ext_exception("flow_php expected SourceStream::iterate() to yield strings"))? + .as_bytes(); + self.with(|reading| { + reading.reader.feed(bytes); + + Ok(()) + })?; + call_method(chunks, "next", &mut [])?; + + Ok(true) + } + + fn finish(&self) -> PhpResult<()> { + self.with(|reading| { + reading.reader.finish(); + + Ok(()) + }) + } +} + +/// One `batches()` call over the shared reader. +struct CsvFeed { + shared: Rc, + chunks: Zval, + schema: Zval, + batch_size: usize, +} + +impl Fed for CsvFeed { + fn next_batch(&self) -> PhpResult> { + let batch = self + .shared + .with(|reading| next_columns(&mut reading.reader, &mut reading.columns, &self.schema, self.batch_size))?; + + if let Some(batch) = &batch { + self.shared.produced(batch.count as u64); + } + + Ok(batch) + } + + fn feed(&self) -> PhpResult { + self.shared.feed(&self.chunks) + } + + fn finish(&self) -> PhpResult<()> { + self.shared.finish() + } +} + +#[php_class] +#[php( + name = "Flow\\ETL\\Adapter\\CSV\\RustCSVOpenSource", + flags = ClassFlags::Final, + implements(ce = csv_open_source_ce, stub = "Flow\\ETL\\Adapter\\CSV\\CSVOpenSource") +)] +pub struct RustCSVOpenSource { + shared: Rc, +} + +impl RustCSVOpenSource { + fn records_iterator(&self) -> PhpResult { + let shared = Rc::clone(&self.shared); + let chunks = shared.chunks()?; + let mut pending: VecDeque = VecDeque::new(); + let mut finished = false; + + Ok(RustIterator::new(Box::new(move || loop { + if let Some(record) = pending.pop_front() { + return Ok(Some(record)); + } + + let batch = shared.with(|reading| reading.reader.next(RECORDS_BATCH))?; + + if !batch.is_empty() { + shared.produced(batch.len() as u64); + pending.extend(batch.values().map(Zval::shallow_clone)); + + continue; + } + + if finished { + return Ok(None); + } + + if !shared.feed(&chunks)? { + shared.finish()?; + finished = true; + } + }))) + } +} + +#[php_impl] +impl RustCSVOpenSource { + #[allow(clippy::too_many_arguments)] + pub fn __construct( + stream: &Zval, + separator: BinarySlice, + enclosure: BinarySlice, + escape: BinarySlice, + withHeader: bool, + emptyToNull: bool, + removeBOM: bool, + charactersReadInLine: Option, + ) -> PhpResult { + // a local file ignores the read length, as NativeLocalSourceStream::readLines() does on the PHP path; for + // S3/Azure it is the range-request size - and from_csv() defaults it to 10 MB, which would be the chunk + let local = match ( + stream.object(), + ext_php_rs::zend::ClassEntry::try_find(NATIVE_LOCAL_SOURCE_STREAM), + ) { + (Some(object), Some(ce)) => object.instance_of(ce), + _ => false, + }; + + Ok(Self { + shared: Rc::new(Shared { + stream: stream.shallow_clone(), + chunk_size: if local { + CHUNK + } else { + charactersReadInLine.unwrap_or(CHUNK) + }, + reading: RefCell::new(Reading { + reader: CsvReader::new(&separator, &enclosure, &escape, withHeader, emptyToNull, removeBOM)?, + columns: CsvColumns::default(), + }), + produced_rows: Cell::new(0), + produced_bytes: Cell::new(0), + }), + }) + } + + pub fn close(&self) -> PhpResult<()> { + call_method(&self.shared.stream, "close", &mut [])?; + + Ok(()) + } + + #[php(name = "producedBytes")] + pub fn produced_bytes(&self) -> i64 { + self.shared.produced_bytes.get() as i64 + } + + #[php(name = "producedRows")] + pub fn produced_rows(&self) -> i64 { + self.shared.produced_rows.get() as i64 + } + + pub fn columns(&self) -> PhpResult { + let chunks = self.shared.chunks()?; + + while self.shared.feed(&chunks)? { + if self.shared.with(|reading| Ok(!reading.reader.headers().is_empty()))? { + return self.headers(); + } + } + + self.shared.finish()?; + + self.headers() + } + + /// Exactly `$batchSize` rows keyed and ordered by `$schema` (the last may be shorter), every column adopted by + /// `$backend`; refusals are `RowsBuilder::appendRows()`'s, row indexes relative to the batch. + pub fn batches(&self, schema: &Zval, batchSize: i64, backend: &Zval) -> PhpResult { + let fed = CsvFeed { + shared: Rc::clone(&self.shared), + chunks: self.shared.chunks()?, + schema: schema.shallow_clone(), + batch_size: batch_size_of(batchSize, "CSV")?, + }; + + Ok(source::batches(fed, schema, backend)) + } + + pub fn headers(&self) -> PhpResult { + self.shared.with(|reading| headers(&mut reading.reader)).map(ArrayValue) + } + + pub fn records(&self) -> PhpResult { + self.records_iterator() + } + + /// `SchemaInferrer::sniff()` over `records()`; a `StringTypeNarrower` without its HTML and XML rungs folds natively. + pub fn sniff( + &self, + names: &ZendHashTable, + rowBudget: i64, + inference: &Zval, + typer: &Zval, + ) -> PhpResult { + if rowBudget < -1 { + return Err(ext_exception("flow_php CSV fold limit must be -1 or at least 0")); + } + + if !folds_natively(typer)? { + let mut records = Zval::new(); + self.records_iterator()?.set_zval(&mut records, false)?; + let mut names_zv = Zval::new(); + names_zv.set_hashtable(names.to_owned()); + let inferrer = construct( + find_class(SCHEMA_INFERRER)?, + &mut [inference.shallow_clone(), typer.shallow_clone()], + )? + .into_zval(false)?; + + return call_method(&inferrer, "sniff", &mut [names_zv, records, zval_long(rowBudget)]) + .map(ColumnTypesValue); + } + + let mut candidates = Vec::new(); + + for function in FOLDED { + let candidate = call_function(function, &mut [])?; + + if call_method(typer, "emitsType", &mut [candidate.shallow_clone()])? + .bool() + .unwrap_or(false) + { + candidates.push( + call_method(&candidate, "toString", &mut [])? + .zend_str() + .ok_or_else(|| ext_exception("flow_php expected Type::toString() to return a string"))? + .as_bytes() + .to_vec(), + ); + } + } + + let mut fold = Fold::new(string_values(names), &candidates)?; + let remaining = |fold: &Fold| match rowBudget { + -1 => None, + budget => Some((budget as u64).saturating_sub(fold.rows())), + }; + let chunks = self.shared.chunks()?; + + while self.shared.feed(&chunks)? { + let limit = remaining(&fold); + let folded = self.shared.with(|reading| reading.reader.fold(&mut fold, limit))?; + self.shared.produced(folded); + + if rowBudget != -1 && fold.rows() >= rowBudget as u64 { + break; + } + } + + if rowBudget == -1 || fold.rows() < rowBudget as u64 { + self.shared.finish()?; + let limit = remaining(&fold); + let folded = self.shared.with(|reading| reading.reader.fold(&mut fold, limit))?; + self.shared.produced(folded); + } + + let mut types = ZendHashTable::new(); + + for (name, code) in fold.types() { + ht_insert( + &mut types, + name, + call_static( + "Flow\\Types\\Type\\TypeFactory", + "fromString", + &mut [zval_str(code.as_bytes())], + )?, + ); + } + + let mut types_zv = Zval::new(); + types_zv.set_hashtable(types); + + call_static( + "Flow\\ETL\\Schema\\Inference\\ColumnTypes", + "fromColumnTypes", + &mut [types_zv, zval_long(fold.rows() as i64), typer.shallow_clone()], + ) + .map(ColumnTypesValue) + } +} + +/// The Rust fold is `StringTypeNarrower` without its HTML and XML rungs - a DOMDocument per cell is not worth porting. +fn folds_natively(typer: &Zval) -> PhpResult { + let narrower = match ( + typer.object(), + ext_php_rs::zend::ClassEntry::try_find(STRING_TYPE_NARROWER), + ) { + (Some(object), Some(ce)) => object.instance_of(ce), + _ => false, + }; + + if !narrower { + return Ok(false); + } + + for markup in ["Flow\\Types\\DSL\\type_html", "Flow\\Types\\DSL\\type_xml"] { + if call_method(typer, "emitsType", &mut [call_function(markup, &mut [])?])? + .bool() + .unwrap_or(false) + { + return Ok(false); + } + } + + Ok(true) +} + +fn headers(reader: &mut CsvReader) -> PhpResult { + let headers = reader.headers(); + let mut list = ZendHashTable::with_capacity(headers.len() as u32); + + for header in headers { + list.push(zval_str(header)) + .map_err(|e| ext_exception(format!("flow_php failed to collect a CSV header: {e:?}")))?; + } + + let mut zv = Zval::new(); + zv.set_hashtable(list); + + Ok(zv) +} diff --git a/src/extension/flow-php-ext/src/csv/tokenizer.rs b/src/extension/flow-php-ext/src/csv/tokenizer.rs index 1596d0ef35..54c959404f 100644 --- a/src/extension/flow-php-ext/src/csv/tokenizer.rs +++ b/src/extension/flow-php-ext/src/csv/tokenizer.rs @@ -156,7 +156,11 @@ impl Tokenizer { /// Advances the scan over unseen bytes; returns the position of the `\n` that ends the record. fn scan_to_record_end(&mut self) -> Option { - let Dialect { separator, enclosure, escape } = self.dialect; + let Dialect { + separator, + enclosure, + escape, + } = self.dialect; let bytes = &self.buffer; let mut position = self.scanned; let mut scan = self.scan; @@ -234,7 +238,11 @@ impl Tokenizer { /// `str_getcsv($record, ...)` into `record`. fn split(&self, range: Range, record: &mut Record) { - let Dialect { separator, enclosure, escape } = self.dialect; + let Dialect { + separator, + enclosure, + escape, + } = self.dialect; let escape = escape.filter(|escape| *escape != enclosure); let line = &self.buffer[range]; // next_record() already stripped every trailing \r and \n, so php_fgetcsv()'s line end is always empty here @@ -320,7 +328,9 @@ impl Tokenizer { } else { let delimiter = memchr(separator, &line[position..limit]).map(|offset| position + offset); - record.bytes.extend_from_slice(&line[position..delimiter.unwrap_or(limit)]); + record + .bytes + .extend_from_slice(&line[position..delimiter.unwrap_or(limit)]); let trimmed = field_start + trailing_line_end(&record.bytes[field_start..]); record.bytes.truncate(trimmed); diff --git a/src/extension/flow-php-ext/src/csv/write.rs b/src/extension/flow-php-ext/src/csv/write.rs index e8df45d31e..c09b9dca13 100644 --- a/src/extension/flow-php-ext/src/csv/write.rs +++ b/src/extension/flow-php-ext/src/csv/write.rs @@ -1,15 +1,18 @@ -//! `Flow\ETL\Adapter\CSV\NativeCSVWriter`: a `Rows` batch as the bytes `CSVEncoder::encode()` returns, rendered from -//! the arrow arrays; the columns it does not render arrive as the cells `CSVEncoder::cells()` produced. +//! `Flow\ETL\Adapter\CSV\RustCSVEncoder`: a `Rows` batch as the bytes `PhpCSVEncoder::encode()` returns, rendered +//! from the arrow arrays; the columns it does not render are the cells the held `PhpCSVEncoder::cells()` produces. +use ext_php_rs::binary::Binary; use ext_php_rs::binary_slice::BinarySlice; use ext_php_rs::exception::PhpException; use ext_php_rs::flags::ClassFlags; use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, Zval}; -use crate::ctx::{find_class, zval_str}; +use crate::ctx::{call_method, find_class}; +use crate::exception::ext_exception; +use crate::interfaces::csv_encoder_ce; use crate::render::invalid_argument; -use crate::text::batch::{batch, cells, renderer, unrendered}; +use crate::text::batch::{batch, cells, renderer, Unrendered}; use crate::text::value::Formats; use crate::text::Error; @@ -22,8 +25,12 @@ fn json_exception(error: Error) -> PhpException { } #[php_class] -#[php(name = "Flow\\ETL\\Adapter\\CSV\\NativeCSVWriter", flags = ClassFlags::Final)] -pub struct NativeCSVWriter { +#[php( + name = "Flow\\ETL\\Adapter\\CSV\\RustCSVEncoder", + flags = ClassFlags::Final, + implements(ce = csv_encoder_ce, stub = "Flow\\ETL\\Adapter\\CSV\\CSVEncoder") +)] +pub struct RustCSVEncoder { separator: u8, enclosure: u8, escape: Option, @@ -33,9 +40,12 @@ pub struct NativeCSVWriter { /// The separator, the enclosure and the escape character cannot occur in a number, a boolean or a uuid. plain_kinds: bool, formats: Formats, + /// The `PhpCSVEncoder` that renders the unrendered columns and the header. + php: Zval, + unrendered: Unrendered, } -impl NativeCSVWriter { +impl RustCSVEncoder { /// One field as `fputcsv()` writes it (ext/standard/file.c `php_fputcsv()`). fn field(&self, out: &mut Vec, text: &[u8]) { if !text.iter().any(|byte| self.enclosing[usize::from(*byte)]) { @@ -65,7 +75,7 @@ impl NativeCSVWriter { } #[php_impl] -impl NativeCSVWriter { +impl RustCSVEncoder { pub fn __construct( separator: BinarySlice, enclosure: BinarySlice, @@ -73,6 +83,7 @@ impl NativeCSVWriter { new_line_separator: BinarySlice, date_time_format: BinarySlice, date_format: BinarySlice, + php: &Zval, ) -> PhpResult { if separator.len() != 1 { return Err(invalid_argument("Separator must be a single character".to_string())); @@ -83,15 +94,25 @@ impl NativeCSVWriter { } if escape.len() > 1 { - return Err(invalid_argument("Escape must be empty or a single character".to_string())); + return Err(invalid_argument( + "Escape must be empty or a single character".to_string(), + )); } let (separator, enclosure, escape) = (separator[0], enclosure[0], escape.first().copied()); let mut enclosing = [false; 256]; - for byte in [Some(separator), Some(enclosure), escape, Some(b'\n'), Some(b'\r'), Some(b'\t'), Some(b' ')] - .into_iter() - .flatten() + for byte in [ + Some(separator), + Some(enclosure), + escape, + Some(b'\n'), + Some(b'\r'), + Some(b'\t'), + Some(b' '), + ] + .into_iter() + .flatten() { enclosing[usize::from(byte)] = true; } @@ -107,16 +128,30 @@ impl NativeCSVWriter { .flatten() .any(|byte| byte.is_ascii_alphanumeric() || b"_+./:-".contains(&byte) || byte >= 0x80), formats: Formats::parse(&date_time_format, &date_format), + php: php.shallow_clone(), + unrendered: Unrendered::default(), }) } - /// The columns of `$schema` this writer does not render itself. - pub fn unrendered(&self, schema: &Zval) -> PhpResult { - unrendered(schema, &self.formats, true) + /// The rows as `PhpCSVEncoder::encode()` writes them; the unrendered columns through the held encoder's `cells()`. + pub fn encode(&mut self, rows: &Zval) -> PhpResult> { + let cells = self.unrendered.render(rows, &self.php, "cells", &self.formats, true)?; + + self.render_rows(rows, &cells) } - /// `$cells`: `CSVEncoder::cells()` of the unrendered columns, each of `$rows->count()` values. - pub fn encode(&self, rows: &Zval, cells_of: &ZendHashTable) -> PhpResult { + #[php(name = "encodeHeader")] + pub fn encode_header(&self, headers: &Zval) -> PhpResult> { + call_method(&self.php, "encodeHeader", &mut [headers.shallow_clone()])? + .zend_str() + .map(|header| Binary::new(header.as_bytes())) + .ok_or_else(|| ext_exception("flow_php expected PhpCSVEncoder::encodeHeader() to return a string")) + } +} + +impl RustCSVEncoder { + /// `$cells_of`: `PhpCSVEncoder::cells()` of the unrendered columns, each of `$rows->count()` values. + fn render_rows(&self, rows: &Zval, cells_of: &ZendHashTable) -> PhpResult> { let batch = batch(rows, &self.formats, true)?; let mut fields = Vec::with_capacity(batch.columns.len()); let mut scratch = Vec::new(); @@ -161,7 +196,8 @@ impl NativeCSVWriter { } let mut out = Vec::with_capacity( - fields.iter().map(|(arena, _)| arena.len()).sum::() + batch.count * (fields.len() + self.new_line.len()), + fields.iter().map(|(arena, _)| arena.len()).sum::() + + batch.count * (fields.len() + self.new_line.len()), ); for i in 0..batch.count { @@ -176,6 +212,6 @@ impl NativeCSVWriter { out.extend_from_slice(&self.new_line); } - Ok(zval_str(&out)) + Ok(Binary::new(out)) } } diff --git a/src/extension/flow-php-ext/src/ctx.rs b/src/extension/flow-php-ext/src/ctx.rs index 59aa6a5bdc..f57a522d9b 100644 --- a/src/extension/flow-php-ext/src/ctx.rs +++ b/src/extension/flow-php-ext/src/ctx.rs @@ -7,8 +7,8 @@ use std::rc::Rc; use ext_php_rs::boxed::ZBox; use ext_php_rs::exception::PhpException; use ext_php_rs::ffi::{ - _zend_property_info, zend_call_known_function, zend_hash_index_update, zend_hash_str_find, - zend_hash_str_update, zend_hash_update, zend_ulong, + _zend_property_info, zend_call_known_function, zend_hash_index_update, zend_hash_str_find, zend_hash_str_update, + zend_hash_update, zend_ulong, }; use ext_php_rs::flags::ClassFlags; use ext_php_rs::types::{ZendHashTable, ZendObject, ZendStr, Zval}; @@ -37,12 +37,7 @@ pub fn ht_insert(ht: &mut ZendHashTable, key: &[u8], mut value: Zval) { zend_hash_index_update(ht, index as u64, std::ptr::from_mut(&mut value)); } None => { - zend_hash_str_update( - ht, - key.as_ptr().cast(), - key.len(), - std::ptr::from_mut(&mut value), - ); + zend_hash_str_update(ht, key.as_ptr().cast(), key.len(), std::ptr::from_mut(&mut value)); } } } @@ -68,11 +63,7 @@ pub fn ht_insert_key(ht: &mut ZendHashTable, key: &HtKey<'_>, mut value: Zval) { zend_hash_index_update(ht, *index as u64, std::ptr::from_mut(&mut value)); } HtKey::Str(name) => { - zend_hash_update( - ht, - std::ptr::from_ref(*name).cast_mut(), - std::ptr::from_mut(&mut value), - ); + zend_hash_update(ht, std::ptr::from_ref(*name).cast_mut(), std::ptr::from_mut(&mut value)); } } } @@ -115,11 +106,8 @@ pub fn null_zval() -> Zval { } pub fn find_class(name: &str) -> Result<&'static ClassEntry, PhpException> { - ClassEntry::try_find(name).ok_or_else(|| { - ext_exception(format!( - "flow_php requires class \"{name}\" to be autoloadable" - )) - }) + ClassEntry::try_find(name) + .ok_or_else(|| ext_exception(format!("flow_php requires class \"{name}\" to be autoloadable"))) } /// Fails when the last engine call left an exception pending, so PHP-level @@ -134,11 +122,7 @@ pub fn ensure_no_pending_exception(context: &str) -> Result<(), PhpException> { /// Writes one property through the object's write handler, which copies the /// value with assign semantics - the caller keeps ownership of `value`. -pub fn write_property_raw( - obj: &mut ZendObject, - name: &mut ZendStr, - mut value: Zval, -) -> Result<(), PhpException> { +pub fn write_property_raw(obj: &mut ZendObject, name: &mut ZendStr, mut value: Zval) -> Result<(), PhpException> { let handler = unsafe { obj.handlers.as_ref() } .and_then(|handlers| handlers.write_property) .ok_or_else(|| ext_exception("flow_php failed to resolve a property write handler"))?; @@ -178,10 +162,7 @@ pub fn property_offset(ce: &ClassEntry, name: &str) -> Result /// a plain userland class when the zval matches the declared type exactly. pub fn write_slot(obj: &mut ZendObject, offset: u32, value: Zval) { unsafe { - let slot = std::ptr::from_mut(obj) - .cast::() - .add(offset as usize) - .cast::(); + let slot = std::ptr::from_mut(obj).cast::().add(offset as usize).cast::(); std::ptr::write(slot, value); } } @@ -215,7 +196,8 @@ pub fn read_property(obj: &ZendObject, name: &str) -> Result /// `$object->$method(...$args)`; an exception the method throws surfaces as itself. pub fn call_method(object: &Zval, method: &str, args: &mut [Zval]) -> Result { let object = expect_object(object, "a method receiver")?; - let ce = unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php failed to resolve an object class"))?; + let ce = + unsafe { object.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php failed to resolve an object class"))?; call_handle_transparent(ce_method_ref(ce, method)?, Some(object), args) } @@ -225,36 +207,24 @@ pub fn call_static(class: &str, method: &str, args: &mut [Zval]) -> Result Result, PhpException> { - let mut obj = ZendObject::new(ce); - let constructor = ce_method_ref(ce, "__construct")?; - - call_handle( - constructor, - Some(&mut obj), - args, - &format!("construct {context}"), - )?; +/// `new $ce(...$args)` with already-owned zvals; an exception the constructor throws surfaces as itself. +pub fn construct(ce: &'static ClassEntry, args: &mut [Zval]) -> Result, PhpException> { + let object = ZendObject::new(ce); + call_handle_transparent(ce_method_ref(ce, "__construct")?, Some(&object), args)?; + + Ok(object) +} - Ok(obj) +/// A hashtable key as a column name: an int key is a numeric column name. +pub fn column_key(name: Option<&ZendStr>, index: zend_ulong) -> Vec { + name.map_or_else(|| index.to_string().into_bytes(), |name| name.as_bytes().to_vec()) } pub fn ce_method_ref(ce: &ClassEntry, method: &str) -> Result<&'static Function, PhpException> { let function = unsafe { - ext_php_rs::ffi::zend_hash_str_find_ptr_lc( - &raw const ce.function_table, - method.as_ptr().cast(), - method.len(), - ) - .cast::() - .as_ref() + ext_php_rs::ffi::zend_hash_str_find_ptr_lc(&raw const ce.function_table, method.as_ptr().cast(), method.len()) + .cast::() + .as_ref() }; function.ok_or_else(|| { @@ -326,13 +296,13 @@ pub fn call_handle_catching( } } -/// Surfaces a PHP exception object as ITSELF rather than wrapped in an -/// `ExtensionException`, so the class and message PHP sees are the ones thrown. +/// Surfaces a PHP exception object as ITSELF rather than wrapped in a +/// `RuntimeException`, so the class and message PHP sees are the ones thrown. pub fn transparent_exception(exception: &mut ZendObject) -> PhpException { let mut zv = Zval::new(); zv.set_object(exception); - PhpException::default(String::new()).with_object(zv) + PhpException::from_message(String::new()).with_object(zv) } /// [`call_handle_catching`] with the exception object already re-raised as @@ -344,8 +314,7 @@ pub fn call_handle_transparent( object: Option<&ZendObject>, args: &mut [Zval], ) -> Result { - call_handle_catching(func, object, args) - .map_err(|mut exception| transparent_exception(&mut exception)) + call_handle_catching(func, object, args).map_err(|mut exception| transparent_exception(&mut exception)) } /// Calls a pre-resolved function handle. Argument zvals stay caller-owned @@ -489,7 +458,8 @@ pub fn store_type_plan(type_zv: &Zval, plan: &Rc) -> Result<(), PhpExc } else { HashMap::new() }; - ctx.type_plans.insert(handle, (type_zv.shallow_clone(), Rc::clone(plan))); + ctx.type_plans + .insert(handle, (type_zv.shallow_clone(), Rc::clone(plan))); Ok(evicted) })?; @@ -535,6 +505,11 @@ fn function(name: &'static str) -> Result<&'static Function, PhpException> { ) } +/// `$name(...$args)` of a PHP function; an exception it throws surfaces as itself. +pub fn call_function(name: &'static str, args: &mut [Zval]) -> Result { + call_handle_transparent(function(name)?, None, args) +} + pub fn json_encode() -> Result<&'static Function, PhpException> { function("json_encode") } @@ -674,7 +649,12 @@ pub fn timezone(name: &[u8]) -> Result { || { let fns = timezone_fns()?; let mut timezone = ZendObject::new(fns.ce); - call_handle(fns.construct, Some(&mut timezone), &mut [zval_str(name)], "construct DateTimeZone")?; + call_handle( + fns.construct, + Some(&mut timezone), + &mut [zval_str(name)], + "construct DateTimeZone", + )?; let mut zv = Zval::new(); zv.set_object(&mut timezone); @@ -754,7 +734,12 @@ pub fn enum_case(class: &[u8], case: &[u8]) -> Result { "check an enum case", )?; let case_zv = if defined.bool().unwrap_or(false) { - call_handle(function("constant")?, None, &mut [constant_name_zv], "restore an enum case")? + call_handle( + function("constant")?, + None, + &mut [constant_name_zv], + "restore an enum case", + )? } else { null_zval() }; @@ -809,18 +794,10 @@ pub fn ht_for_each( } pub fn read_slot(obj: &ZendObject, offset: u32) -> &Zval { - unsafe { - &*std::ptr::from_ref(obj) - .cast::() - .add(offset as usize) - .cast::() - } + unsafe { &*std::ptr::from_ref(obj).cast::().add(offset as usize).cast::() } } -pub fn expect_object<'a>( - zv: &'a Zval, - context: &str, -) -> Result<&'a ZendObject, PhpException> { +pub fn expect_object<'a>(zv: &'a Zval, context: &str) -> Result<&'a ZendObject, PhpException> { zv.object() .ok_or_else(|| ext_exception(format!("flow_php expected {context} to be an object"))) } diff --git a/src/extension/flow-php-ext/src/date_check.rs b/src/extension/flow-php-ext/src/date_check.rs index 456ebb0e55..ab941fc99d 100644 --- a/src/extension/flow-php-ext/src/date_check.rs +++ b/src/extension/flow-php-ext/src/date_check.rs @@ -120,10 +120,9 @@ pub fn checkdate(month: i64, day: i64, year: i64) -> bool { pub fn iso_instant_micros(bytes: &[u8]) -> Option { let byte_at = |at: usize| bytes.get(at).copied(); let number = |at: usize, count: usize| -> Option { - bytes - .get(at..at + count)? - .iter() - .try_fold(0i64, |value, digit| digit.is_ascii_digit().then(|| value * 10 + i64::from(digit - b'0'))) + bytes.get(at..at + count)?.iter().try_fold(0i64, |value, digit| { + digit.is_ascii_digit().then(|| value * 10 + i64::from(digit - b'0')) + }) }; if [(4, b'-'), (7, b'-'), (10, b'T'), (13, b':'), (16, b':')] diff --git a/src/extension/flow-php-ext/src/exception.rs b/src/extension/flow-php-ext/src/exception.rs index 9c68c5ddda..2e2b28b3db 100644 --- a/src/extension/flow-php-ext/src/exception.rs +++ b/src/extension/flow-php-ext/src/exception.rs @@ -1,31 +1,18 @@ -use ext_php_rs::builders::ClassBuilder; -use ext_php_rs::error::Result; use ext_php_rs::exception::PhpException; -use ext_php_rs::flags::ClassFlags; use ext_php_rs::zend::{ce, ClassEntry}; use flow_batch_frame::error::Part; use flow_batch_frame::Error; -const EXCEPTION_CLASS: &str = "Flow\\Floe\\Exception\\ExtensionException"; - -fn noop(_ce: &'static mut ClassEntry) {} - -pub fn register() -> Result<()> { - ClassBuilder::new(EXCEPTION_CLASS) - .extends((ce::exception, "Exception")) - .flags(ClassFlags::Final) - .registration(noop) - .register()?; - - Ok(()) -} - -fn exception_ce() -> &'static ClassEntry { - ClassEntry::try_find(EXCEPTION_CLASS).unwrap_or_else(|| ce::exception()) -} +use crate::render::RUNTIME; +/// Never through `ctx::find_class()`: its not-found branch calls this function, so a missing class would recurse +/// until the stack overflows; without `flow-php/etl` the failure is a plain `\Exception`. pub fn ext_exception(message: impl Into) -> PhpException { - PhpException::new(message.into(), 0, exception_ce()) + PhpException::new( + message.into(), + 0, + ClassEntry::try_find(RUNTIME).unwrap_or_else(ce::exception), + ) } /// A flow-batch-frame refusal of schema or type JSON, which only `kind` returns. @@ -44,7 +31,9 @@ pub fn json_exception(error: Error) -> PhpException { Part::Base => "base", } ), - Error::UnknownType { type_name } => format!("flow_php cannot build a column for type \"{type_name}\""), + Error::UnknownType { type_name } => { + format!("flow_php cannot build a column for type \"{type_name}\"") + } error => unreachable!("kind returns JSON refusals only, got {error}"), }) } diff --git a/src/extension/flow-php-ext/src/interfaces.rs b/src/extension/flow-php-ext/src/interfaces.rs index 4557838403..bdf65485e5 100644 --- a/src/extension/flow-php-ext/src/interfaces.rs +++ b/src/extension/flow-php-ext/src/interfaces.rs @@ -1,37 +1,90 @@ -//! `Flow\ETL\Column\{Column, ColumnBuilder, Backend}`: registered at MINIT with the library files' exact signatures, so -//! the extension's classes implement them and the library files (autoloaded only without flow_php) stay unused. +//! `Flow\ETL\Column\{Column, ColumnBuilder, Backend}` and the CSV / JSON / Parquet adapters' encoder, open source and +//! open sink contracts: registered at MINIT with the package +//! files' exact signatures, so the extension's classes implement them and the package files (autoloaded only without +//! flow_php) stay unused. use std::sync::atomic::{AtomicPtr, Ordering}; -use ext_php_rs::args::Arg; +use ext_php_rs::args::{Arg, ArgInfoTables}; use ext_php_rs::builders::{ClassBuilder, FunctionBuilder}; use ext_php_rs::error::Result; use ext_php_rs::flags::{ClassFlags, DataType, MethodFlags}; use ext_php_rs::zend::ClassEntry; -const DEFINITION: DataType = DataType::Object(Some("Flow\\ETL\\Schema\\Definition")); -const TYPE: DataType = DataType::Object(Some("Flow\\Types\\Type")); -const COLUMN: DataType = DataType::Object(Some("Flow\\ETL\\Column\\Column")); -const COLUMN_BUILDER: DataType = DataType::Object(Some("Flow\\ETL\\Column\\ColumnBuilder")); -const SELF: DataType = DataType::Object(Some("self")); +const DEFINITION: DataType = DataType::object("Flow\\ETL\\Schema\\Definition"); +const TYPE: DataType = DataType::object("Flow\\Types\\Type"); +const COLUMN: DataType = DataType::object("Flow\\ETL\\Column\\Column"); +const COLUMN_BUILDER: DataType = DataType::object("Flow\\ETL\\Column\\ColumnBuilder"); +const SELF: DataType = DataType::object("self"); +const ROWS: DataType = DataType::object("Flow\\ETL\\Rows"); +const SCHEMA: DataType = DataType::object("Flow\\ETL\\Schema"); +const BACKEND: DataType = DataType::object("Flow\\ETL\\Column\\Backend"); +const ITERATOR: DataType = DataType::object("Iterator"); +const COLUMN_TYPES: DataType = DataType::object("Flow\\ETL\\Schema\\Inference\\ColumnTypes"); +const SCHEMA_INFERENCE: DataType = DataType::object("Flow\\ETL\\Schema\\Inference\\SchemaInference"); +const TYPE_NARROWER: DataType = DataType::object("Flow\\Types\\Type\\TypeNarrower"); // ClassEntry::try_find reads EG(class_table), which MINIT has not set, so each CE is kept from its registration static COLUMN_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); static COLUMN_BUILDER_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); static BACKEND_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static PARQUET_OPEN_SINK_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static CSV_ENCODER_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static JSON_ENCODER_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static CSV_OPEN_SOURCE_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static JSON_OPEN_SOURCE_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); +static PARQUET_OPEN_SOURCE_CE: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); -fn store_column(ce: &'static mut ClassEntry) { +fn store_column(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); COLUMN_CE.store(ce, Ordering::Release); } -fn store_column_builder(ce: &'static mut ClassEntry) { +fn store_column_builder(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); COLUMN_BUILDER_CE.store(ce, Ordering::Release); } -fn store_backend(ce: &'static mut ClassEntry) { +fn store_backend(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); BACKEND_CE.store(ce, Ordering::Release); } +fn store_parquet_open_sink(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + PARQUET_OPEN_SINK_CE.store(ce, Ordering::Release); +} + +fn store_csv_encoder(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + CSV_ENCODER_CE.store(ce, Ordering::Release); +} + +fn store_json_encoder(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + JSON_ENCODER_CE.store(ce, Ordering::Release); +} + +fn store_csv_open_source(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + CSV_OPEN_SOURCE_CE.store(ce, Ordering::Release); +} + +fn store_json_open_source(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + JSON_OPEN_SOURCE_CE.store(ce, Ordering::Release); +} + +fn store_parquet_open_source(ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { + keep(arg_info); + PARQUET_OPEN_SOURCE_CE.store(ce, Ordering::Release); +} + +/// The engine borrows an interface's argument info tables for the life of the process. +fn keep(arg_info: ArgInfoTables) { + std::mem::forget(arg_info); +} + fn load(ce: &AtomicPtr, name: &str) -> &'static ClassEntry { unsafe { ce.load(Ordering::Acquire).as_ref() }.unwrap_or_else(|| panic!("{name} not registered")) } @@ -48,13 +101,44 @@ pub fn backend_ce() -> &'static ClassEntry { load(&BACKEND_CE, "Flow\\ETL\\Column\\Backend") } +pub fn parquet_open_sink_ce() -> &'static ClassEntry { + load(&PARQUET_OPEN_SINK_CE, "Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSink") +} + +pub fn csv_encoder_ce() -> &'static ClassEntry { + load(&CSV_ENCODER_CE, "Flow\\ETL\\Adapter\\CSV\\CSVEncoder") +} + +pub fn json_encoder_ce() -> &'static ClassEntry { + load(&JSON_ENCODER_CE, "Flow\\ETL\\Adapter\\JSON\\JSONEncoder") +} + +pub fn csv_open_source_ce() -> &'static ClassEntry { + load(&CSV_OPEN_SOURCE_CE, "Flow\\ETL\\Adapter\\CSV\\CSVOpenSource") +} + +pub fn json_open_source_ce() -> &'static ClassEntry { + load(&JSON_OPEN_SOURCE_CE, "Flow\\ETL\\Adapter\\JSON\\JsonOpenSource") +} + +pub fn parquet_open_source_ce() -> &'static ClassEntry { + load( + &PARQUET_OPEN_SOURCE_CE, + "Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSource", + ) +} + fn method(name: &str, args: Vec>, returns: DataType) -> FunctionBuilder<'static> { args.into_iter() .fold(FunctionBuilder::new_abstract(name), FunctionBuilder::arg) .returns(returns, false, false) } -fn interface(name: &str, store: fn(&'static mut ClassEntry), methods: Vec>) -> Result<()> { +fn interface( + name: &str, + store: fn(&'static mut ClassEntry, ArgInfoTables), + methods: Vec>, +) -> Result<()> { methods .into_iter() .fold( @@ -139,5 +223,99 @@ pub fn register() -> Result<()> { ), method("allocatedBytes", vec![], DataType::Long), ], + )?; + interface( + "Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSink", + store_parquet_open_sink, + vec![ + method("close", vec![], DataType::Void), + method("write", vec![Arg::new("rows", ROWS)], DataType::Void), + ], + )?; + interface( + "Flow\\ETL\\Adapter\\CSV\\CSVEncoder", + store_csv_encoder, + vec![ + method("encode", vec![Arg::new("rows", ROWS)], DataType::String), + method( + "encodeHeader", + vec![Arg::new("headers", DataType::Array)], + DataType::String, + ), + ], + )?; + interface( + "Flow\\ETL\\Adapter\\JSON\\JSONEncoder", + store_json_encoder, + vec![method( + "encode", + vec![Arg::new("rows", ROWS), Arg::new("separator", DataType::String)], + DataType::String, + )], + )?; + interface( + "Flow\\ETL\\Adapter\\CSV\\CSVOpenSource", + store_csv_open_source, + vec![ + method("close", vec![], DataType::Void), + method("producedBytes", vec![], DataType::Long), + method("producedRows", vec![], DataType::Long), + method("columns", vec![], DataType::Array), + method( + "batches", + vec![ + Arg::new("schema", SCHEMA), + Arg::new("batchSize", DataType::Long), + Arg::new("backend", BACKEND), + ], + ITERATOR, + ), + method("headers", vec![], DataType::Array), + method("records", vec![], ITERATOR), + method( + "sniff", + vec![ + Arg::new("names", DataType::Array), + Arg::new("rowBudget", DataType::Long), + Arg::new("inference", SCHEMA_INFERENCE), + Arg::new("typer", TYPE_NARROWER), + ], + COLUMN_TYPES, + ), + ], + )?; + interface( + "Flow\\ETL\\Adapter\\JSON\\JsonOpenSource", + store_json_open_source, + vec![ + method("close", vec![], DataType::Void), + method( + "batches", + vec![ + Arg::new("schema", SCHEMA), + Arg::new("batchSize", DataType::Long), + Arg::new("backend", BACKEND), + ], + ITERATOR, + ), + ], + )?; + interface( + "Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSource", + store_parquet_open_source, + vec![ + method( + "batches", + vec![ + Arg::new("schema", SCHEMA), + Arg::new("batchSize", DataType::Long), + Arg::new("offset", DataType::Long).allow_null(), + Arg::new("limit", DataType::Long).allow_null(), + Arg::new("backend", BACKEND), + ], + ITERATOR, + ), + method("close", vec![], DataType::Void), + ], ) } diff --git a/src/extension/flow-php-ext/src/iterator.rs b/src/extension/flow-php-ext/src/iterator.rs new file mode 100644 index 0000000000..6af28c6476 --- /dev/null +++ b/src/extension/flow-php-ext/src/iterator.rs @@ -0,0 +1,117 @@ +//! `Flow\ETL\RustIterator`: the `\Iterator` the Rust open sources return from `batches()` / `records()` - keys 0..n, +//! each value pulled from a Rust producer on demand. It behaves as the Generator it replaced: it streams once +//! (`rewind()` after `next()` throws) and ends for good when the producer throws. + +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::Zval; +use ext_php_rs::zend::ce; + +use crate::render::runtime; + +pub type Producer = Box PhpResult>>; + +#[php_class] +#[php(name = "Flow\\ETL\\RustIterator", flags = ClassFlags::Final, implements(ce = ce::iterator, stub = "\\Iterator"))] +pub struct RustIterator { + producer: Producer, + current: Option, + /// The index of `current`. + key: i64, + started: bool, + /// `next()` moved past the first value: `rewind()` throws from here on. + advanced: bool, + /// The producer returned its last value or threw: it is never called again. + done: bool, +} + +impl RustIterator { + pub fn new(producer: Producer) -> Self { + Self { + producer, + current: None, + key: 0, + started: false, + advanced: false, + done: false, + } + } + + /// A Generator starts on its first `rewind()`, `valid()`, `current()`, `key()` or `next()`. + fn start(&mut self) -> PhpResult<()> { + if self.started { + return Ok(()); + } + + self.started = true; + self.pull() + } + + fn pull(&mut self) -> PhpResult<()> { + self.current = None; + + if self.done { + return Ok(()); + } + + match (self.producer)() { + Ok(Some(value)) => { + self.current = Some(value); + + Ok(()) + } + Ok(None) => { + self.done = true; + + Ok(()) + } + Err(error) => { + self.done = true; + + Err(error) + } + } + } +} + +#[php_impl] +impl RustIterator { + pub fn rewind(&mut self) -> PhpResult<()> { + if self.advanced { + return Err(runtime("RustIterator cannot rewind".to_string())); + } + + self.start() + } + + pub fn valid(&mut self) -> PhpResult { + self.start()?; + + Ok(self.current.is_some()) + } + + pub fn current(&mut self) -> PhpResult { + self.start()?; + + Ok(self.current.as_ref().map_or_else(Zval::new, Zval::shallow_clone)) + } + + /// Null once the iterator ended, as a Generator's. + pub fn key(&mut self) -> PhpResult> { + self.start()?; + + Ok(self.current.is_some().then_some(self.key)) + } + + pub fn next(&mut self) -> PhpResult<()> { + self.start()?; + + if self.done { + return Ok(()); + } + + self.advanced = true; + self.key += 1; + self.pull() + } +} diff --git a/src/extension/flow-php-ext/src/json/mod.rs b/src/extension/flow-php-ext/src/json/mod.rs index 62955290ce..1dd0818c44 100644 --- a/src/extension/flow-php-ext/src/json/mod.rs +++ b/src/extension/flow-php-ext/src/json/mod.rs @@ -1,2 +1,7 @@ pub mod read; +#[allow( + non_snake_case, + reason = "PHP takes a parameter name from its Rust identifier: the contracts' are camelCase" +)] +pub mod source; pub mod write; diff --git a/src/extension/flow-php-ext/src/json/read.rs b/src/extension/flow-php-ext/src/json/read.rs index 99cdc7cb6e..7367e286ed 100644 --- a/src/extension/flow-php-ext/src/json/read.rs +++ b/src/extension/flow-php-ext/src/json/read.rs @@ -1,4 +1,4 @@ -//! `Flow\ETL\Adapter\JSON\NativeJsonReader`: JSON lines or a top-level JSON array, fed in chunks, read into native +//! The reader behind `RustJsonOpenSource`: JSON lines or a top-level JSON array, fed in chunks, read into native //! columns by a schema with `RowsBuilder::appendRows()`'s results and refusals. This file frames records and maps their //! members to columns; serde_json parses and validates. @@ -7,9 +7,7 @@ use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::fmt; -use ext_php_rs::binary_slice::BinarySlice; use ext_php_rs::exception::PhpException; -use ext_php_rs::flags::ClassFlags; use ext_php_rs::prelude::*; use ext_php_rs::types::Zval; use flow_batch_frame::kind::{Field, Kind}; @@ -19,7 +17,7 @@ use serde_json::de::{SliceRead, StrRead}; use serde_json::value::RawValue; use serde_json::Deserializer; -use crate::batch_columns::{batch_size_of, native_text, BatchColumns, Key}; +use crate::batch_columns::{native_text, BatchColumns, HeldBatch, Key}; use crate::builder::{append_native, append_one, native_leaf, Append}; use crate::cast::{CastKind, MapKeyKind}; use crate::ctx::{self, array_key_index, null_zval, zval_str}; @@ -119,8 +117,14 @@ const LONE_SURROGATE: &str = "Single unpaired UTF-16 surrogate in unicode escape /// `{}` or `[]`: a record with no fields, skipped as `JsonFileReader::sample()` skips it. fn empty_record(bytes: &[u8]) -> bool { - let start = bytes.iter().position(|byte| !is_whitespace(byte)).unwrap_or(bytes.len()); - let end = bytes.iter().rposition(|byte| !is_whitespace(byte)).map_or(start, |end| end + 1); + let start = bytes + .iter() + .position(|byte| !is_whitespace(byte)) + .unwrap_or(bytes.len()); + let end = bytes + .iter() + .rposition(|byte| !is_whitespace(byte)) + .map_or(start, |end| end + 1); let trimmed = &bytes[start..end]; matches!( @@ -275,7 +279,10 @@ impl Framing { } Document::Elements => { let pending = &self.input[self.start..]; - let found = self.scan.run(pending, self.scanned).map_err(|TooDeep| self.malformed(TOO_DEEP.to_string()))?; + let found = self + .scan + .run(pending, self.scanned) + .map_err(|TooDeep| self.malformed(TOO_DEEP.to_string()))?; let Some(found) = found else { self.scanned = pending.len(); @@ -480,7 +487,9 @@ impl MemberColumns { for (column, key) in keys.enumerate() { if let Key::Index(index) = key { if let Ok(position) = usize::try_from(*index) { - columns.positions.resize(columns.positions.len().max(position + 1), None); + columns + .positions + .resize(columns.positions.len().max(position + 1), None); columns.positions[position] = Some(column); } } @@ -549,7 +558,9 @@ pub fn map_record( if let Some(b'{' | b'[') = record.iter().find(|byte| !is_whitespace(byte)) { let mut deserializer = deserializer(record); - deserializer.deserialize_any(Members { columns, slots, base }).map_err(malformed)?; + deserializer + .deserialize_any(Members { columns, slots, base }) + .map_err(malformed)?; return deserializer.end().map_err(malformed); } @@ -662,8 +673,12 @@ fn into_column(values: &mut KindBuilder, kind: &Kind, cast: &CastKind, text: &st (Kind::Struct(fields), CastKind::Structure(elements)) => { let members = str_deserializer(text).deserialize_map(Fields(fields)).map_err(reread)?; - for (((child, field), element), member) in - values.struct_children().iter_mut().zip(fields).zip(elements).zip(members) + for (((child, field), element), member) in values + .struct_children() + .iter_mut() + .zip(fields) + .zip(elements) + .zip(members) { match member.map(RawValue::get) { None if element.required => return Ok(false), @@ -703,7 +718,12 @@ impl<'de> Visitor<'de> for Elements<'_> { } fn visit_seq>(self, mut seq: A) -> Result { - let Elements { values, kind, cast, failure } = self; + let Elements { + values, + kind, + cast, + failure, + } = self; while let Some(value) = seq.next_element::<&'de RawValue>()? { match into_column(values, kind, cast, value.get()) { @@ -802,7 +822,9 @@ fn last_wins<'a>(entries: Vec<(Cow<'a, str>, &'a RawValue)>) -> Vec<(Cow<'a, str } } - kept.into_iter().map(|(key, value)| (entries[key].0.clone(), entries[value].1)).collect() + kept.into_iter() + .map(|(key, value)| (entries[key].0.clone(), entries[value].1)) + .collect() } /// The batch being built and the column each member feeds. @@ -812,9 +834,7 @@ struct JsonColumns { members: MemberColumns, } -#[php_class] -#[php(name = "Flow\\ETL\\Adapter\\JSON\\NativeJsonReader", flags = ClassFlags::Final)] -pub struct NativeJsonReader { +pub struct JsonReader { uri: String, framing: Framing, /// The framed records of the pending batch, copied out of the input. @@ -832,7 +852,7 @@ fn malformed(uri: &str, lines: bool, ordinal: usize, message: &str) -> PhpExcept )) } -impl NativeJsonReader { +impl JsonReader { fn clear(&mut self) { self.records.clear(); self.bounds.clear(); @@ -842,7 +862,7 @@ impl NativeJsonReader { } } - fn read(&mut self, schema: &Zval, batch_size: usize) -> PhpResult { + fn read(&mut self, schema: &Zval, batch_size: usize) -> PhpResult> { let (state, rebuilt) = BatchColumns::prepare(&mut self.columns.batch, schema, batch_size, "JSON")?; if rebuilt { @@ -872,7 +892,7 @@ impl NativeJsonReader { state.rows = self.bounds.len(); if self.bounds.is_empty() || (self.bounds.len() < state.batch_size && !self.framing.finished) { - return Ok(null_zval()); + return Ok(None); } let width = state.columns.len(); @@ -884,9 +904,16 @@ impl NativeJsonReader { for (row, record) in self.bounds.iter().enumerate() { let slots = &mut self.slots[row * width..(row + 1) * width]; - match map_record(&self.records[record.start..record.end], &self.columns.members, slots, base) { + match map_record( + &self.records[record.start..record.end], + &self.columns.members, + slots, + base, + ) { Ok(()) => {} - Err(RecordError::Malformed(message)) => return Err(malformed(&self.uri, lines, record.ordinal, &message)), + Err(RecordError::Malformed(message)) => { + return Err(malformed(&self.uri, lines, record.ordinal, &message)) + } Err(RecordError::Scalar(given)) => { return Err(runtime(format!( "A JSON record must be an object or an array, {given} given in \"{}\".", @@ -929,9 +956,13 @@ impl NativeJsonReader { decode(text)? }; - if let Append::Refused { cause, .. } = - append_one(&mut column.values, &column.plan, &column.definition, column.nullable, &value)? - { + if let Append::Refused { cause, .. } = append_one( + &mut column.values, + &column.plan, + &column.definition, + column.nullable, + &value, + )? { column.refusal = Some((row, cause)); } } @@ -940,7 +971,7 @@ impl NativeJsonReader { self.records.clear(); self.bounds.clear(); - state.finish() + state.finish().map(Some) } } @@ -948,7 +979,12 @@ impl NativeJsonReader { fn decode(text: &str) -> Result { let mut associative = Zval::new(); associative.set_bool(true); - let value = ctx::call_handle(ctx::json_decode()?, None, &mut [zval_str(text.as_bytes()), associative], "decode JSON")?; + let value = ctx::call_handle( + ctx::json_decode()?, + None, + &mut [zval_str(text.as_bytes()), associative], + "decode JSON", + )?; if value.is_null() { return Err(ext_exception("flow_php expected json_decode() to read validated JSON")); @@ -957,12 +993,11 @@ fn decode(text: &str) -> Result { Ok(value) } -#[php_impl] -impl NativeJsonReader { - /// `$uri` names the file in refusals. - pub fn __construct(lines: bool, uri: BinarySlice) -> Self { +impl JsonReader { + /// `uri` names the file in refusals. + pub fn new(lines: bool, uri: &[u8]) -> Self { Self { - uri: String::from_utf8_lossy(&uri).into_owned(), + uri: String::from_utf8_lossy(uri).into_owned(), framing: Framing::new(lines), records: Vec::new(), bounds: Vec::new(), @@ -971,8 +1006,8 @@ impl NativeJsonReader { } } - pub fn feed(&mut self, chunk: BinarySlice) { - self.framing.feed(&chunk); + pub fn feed(&mut self, chunk: &[u8]) { + self.framing.feed(chunk); } /// Malformed input left in the buffer (a truncated record, a missing `]`) is refused by the next `nextColumns()`. @@ -980,11 +1015,10 @@ impl NativeJsonReader { self.framing.finish(); } - /// Exactly `$batchSize` rows keyed and ordered by `$schema` while that many are buffered, the remainder after - /// `finish()`, else null. Refusals are `RowsBuilder::appendRows()`'s, row indexes relative to the batch. - #[php(name = "nextColumns")] - pub fn next_columns(&mut self, schema: &Zval, batch_size: i64) -> PhpResult { - let batch = self.read(schema, batch_size_of(batch_size, "JSON")?); + /// Exactly `batch_size` rows keyed and ordered by `schema` while that many are buffered, the remainder after + /// `finish()`, else none. Refusals are `RowsBuilder::appendRows()`'s, row indexes relative to the batch. + pub fn next_columns(&mut self, schema: &Zval, batch_size: usize) -> PhpResult> { + let batch = self.read(schema, batch_size); if batch.is_err() { self.clear(); @@ -999,8 +1033,8 @@ mod tests { use serde::de::Deserializer as _; use super::{ - last_wins, map_record, number, str_deserializer, Entries, Framing, Key, Malformed, MemberColumns, Number, Record, - RecordError, + last_wins, map_record, number, str_deserializer, Entries, Framing, Key, Malformed, MemberColumns, Number, + Record, RecordError, }; use crate::ctx::array_key_index; @@ -1021,7 +1055,12 @@ mod tests { Ok(bounds .iter() - .map(|record| (String::from_utf8(records[record.start..record.end].to_vec()).unwrap(), record.ordinal)) + .map(|record| { + ( + String::from_utf8(records[record.start..record.end].to_vec()).unwrap(), + record.ordinal, + ) + }) .collect()) } @@ -1046,9 +1085,15 @@ mod tests { assert_eq!( framed(false, &bytes(document)).unwrap(), - vec![(r#"{"a":{"b":[1,"x]\"",{"c":2}]}}"#.to_string(), 0), (r#"{"d":3}"#.to_string(), 1)], + vec![ + (r#"{"a":{"b":[1,"x]\"",{"c":2}]}}"#.to_string(), 0), + (r#"{"d":3}"#.to_string(), 1) + ], + ); + assert_eq!( + framed(true, &bytes("{\"a\":[1,\n")).unwrap(), + vec![(r#"{"a":[1,"#.to_string(), 1)] ); - assert_eq!(framed(true, &bytes("{\"a\":[1,\n")).unwrap(), vec![(r#"{"a":[1,"#.to_string(), 1)]); } #[test] @@ -1061,8 +1106,14 @@ mod tests { #[test] fn one_leading_bom_is_skipped() { - assert_eq!(framed(false, &[b"\xEF\xBB", b"\xBF [1]"]).unwrap(), vec![("1".to_string(), 0)]); - assert_eq!(framed(true, &[b"\xEF\xBB\xBF{\"a\":1}\n"]).unwrap(), vec![(r#"{"a":1}"#.to_string(), 1)]); + assert_eq!( + framed(false, &[b"\xEF\xBB", b"\xBF [1]"]).unwrap(), + vec![("1".to_string(), 0)] + ); + assert_eq!( + framed(true, &[b"\xEF\xBB\xBF{\"a\":1}\n"]).unwrap(), + vec![(r#"{"a":1}"#.to_string(), 1)] + ); assert_eq!( framed(true, &[b"{\"a\":1}\n\xEF\xBB\xBF{\"a\":2}"]).unwrap(), vec![(r#"{"a":1}"#.to_string(), 1), ("\u{FEFF}{\"a\":2}".to_string(), 2)], @@ -1075,7 +1126,10 @@ mod tests { framed(true, &[b"\n \t\x0B\x0C\r\n{}\n[ ]\n{\"a\":1}\r\n\n"]).unwrap(), vec![("{\"a\":1}\r".to_string(), 5)], ); - assert_eq!(framed(false, &[b"[{}, [], {\"a\":1}]"]).unwrap(), vec![(r#" {"a":1}"#.to_string(), 2)]); + assert_eq!( + framed(false, &[b"[{}, [], {\"a\":1}]"]).unwrap(), + vec![(r#" {"a":1}"#.to_string(), 2)] + ); } #[test] @@ -1091,15 +1145,24 @@ mod tests { #[test] fn a_truncated_document_is_malformed() { - assert_eq!(framed(false, &[b"[{\"id\":1}"]), malformed(0, "EOF while parsing a list")); - assert_eq!(framed(false, &[b"[{\"id\":"]), malformed(0, "EOF while parsing a value at line 1 column 6")); + assert_eq!( + framed(false, &[b"[{\"id\":1}"]), + malformed(0, "EOF while parsing a list") + ); + assert_eq!( + framed(false, &[b"[{\"id\":"]), + malformed(0, "EOF while parsing a value at line 1 column 6") + ); assert_eq!(framed(false, &[b""]), malformed(0, "EOF while parsing a value")); assert_eq!(framed(false, &[b"{}"]), malformed(0, "expected `[`")); } #[test] fn nesting_deeper_than_json_decode_reads_is_refused() { - assert_eq!(framed(false, &[format!("[{}]", nested(511)).as_bytes()]).unwrap().len(), 1); + assert_eq!( + framed(false, &[format!("[{}]", nested(511)).as_bytes()]).unwrap().len(), + 1 + ); assert_eq!( framed(false, &[format!("[{}]", nested(512)).as_bytes()]), malformed(0, "Maximum stack depth exceeded"), @@ -1114,8 +1177,14 @@ mod tests { assert_eq!(number("-0"), Number::Long(0)); assert_eq!(number("9223372036854775807"), Number::Long(i64::MAX)); assert_eq!(number("-9223372036854775808"), Number::Long(i64::MIN)); - assert_eq!(number("9223372036854775808"), Number::Double(9_223_372_036_854_775_808.0)); - assert_eq!(number("-9223372036854775809"), Number::Double(-9_223_372_036_854_775_809.0)); + assert_eq!( + number("9223372036854775808"), + Number::Double(9_223_372_036_854_775_808.0) + ); + assert_eq!( + number("-9223372036854775809"), + Number::Double(-9_223_372_036_854_775_809.0) + ); assert_eq!(number("1E2"), Number::Double(100.0)); assert_eq!(number("1e400"), Number::Double(f64::INFINITY)); assert_eq!(number("1e-400"), Number::Double(0.0)); @@ -1145,13 +1214,20 @@ mod tests { map_record(record.as_bytes(), &columns(names), &mut slots, record.as_ptr() as usize)?; - Ok(slots.iter().map(|slot| slot.map(|(start, end)| record[start..end].to_string())).collect()) + Ok(slots + .iter() + .map(|slot| slot.map(|(start, end)| record[start..end].to_string())) + .collect()) } #[test] fn members_map_to_columns_by_name_and_the_last_duplicate_wins() { assert_eq!( - mapped(r#" {"b": [1, {"x":2}], "zz": 0, "a": "1", "a": null} "#, &["a", "b", "c"]).unwrap(), + mapped( + r#" {"b": [1, {"x":2}], "zz": 0, "a": "1", "a": null} "#, + &["a", "b", "c"] + ) + .unwrap(), vec![Some("null".to_string()), Some(r#"[1, {"x":2}]"#.to_string()), None], ); assert_eq!( @@ -1162,7 +1238,10 @@ mod tests { #[test] fn an_array_record_maps_elements_to_numeric_names() { - assert_eq!(mapped(r#"[10, "x", true]"#, &["2", "0"]).unwrap(), vec![Some("true".to_string()), Some("10".to_string())]); + assert_eq!( + mapped(r#"[10, "x", true]"#, &["2", "0"]).unwrap(), + vec![Some("true".to_string()), Some("10".to_string())] + ); } #[test] @@ -1187,7 +1266,10 @@ mod tests { "True", "{\"skipped\":\"\u{0}\"}", ] { - assert!(matches!(mapped(record, &["id"]), Err(RecordError::Malformed(_))), "{record:?}"); + assert!( + matches!(mapped(record, &["id"]), Err(RecordError::Malformed(_))), + "{record:?}" + ); } let invalid_utf8 = b"{\"skipped\":\"\xFF\"}"; @@ -1216,7 +1298,9 @@ mod tests { } assert_eq!( - framed(true, &[r#"{"a":"\ud83d\ude00","b":"\\","c":"\\ud800"}"#.as_bytes()]).unwrap().len(), + framed(true, &[r#"{"a":"\ud83d\ude00","b":"\\","c":"\\ud800"}"#.as_bytes()]) + .unwrap() + .len(), 1, "a pair, an escaped backslash, and an escaped backslash before u are no lone surrogates", ); @@ -1225,11 +1309,21 @@ mod tests { fn deduplicated(object: &str) -> Vec<(String, String)> { let entries = str_deserializer(object).deserialize_map(Entries).unwrap(); - last_wins(entries).into_iter().map(|(name, value)| (name.into_owned(), value.get().to_string())).collect() + last_wins(entries) + .into_iter() + .map(|(name, value)| (name.into_owned(), value.get().to_string())) + .collect() } fn object(members: &[(String, usize)]) -> String { - format!("{{{}}}", members.iter().map(|(name, value)| format!("\"{name}\":{value}")).collect::>().join(",")) + format!( + "{{{}}}", + members + .iter() + .map(|(name, value)| format!("\"{name}\":{value}")) + .collect::>() + .join(",") + ) } #[test] @@ -1239,13 +1333,18 @@ mod tests { assert_eq!( deduplicated(&object(&members)), - members.iter().map(|(name, value)| (name.clone(), value.to_string())).collect::>(), + members + .iter() + .map(|(name, value)| (name.clone(), value.to_string())) + .collect::>(), "{size} unique keys stay as read", ); members.push(("k1".to_string(), 99)); - let mut expected: Vec<(String, String)> = - members[..size].iter().map(|(name, value)| (name.clone(), value.to_string())).collect(); + let mut expected: Vec<(String, String)> = members[..size] + .iter() + .map(|(name, value)| (name.clone(), value.to_string())) + .collect(); expected[1].1 = "99".to_string(); assert_eq!(deduplicated(&object(&members)), expected, "{size} keys and k1 again"); diff --git a/src/extension/flow-php-ext/src/json/source.rs b/src/extension/flow-php-ext/src/json/source.rs new file mode 100644 index 0000000000..b69387a81f --- /dev/null +++ b/src/extension/flow-php-ext/src/json/source.rs @@ -0,0 +1,119 @@ +//! `Flow\ETL\Adapter\JSON\RustJsonOpenSource`: JSON lines or a top-level JSON array read from the stream in `CHUNK`s +//! into native columns, every batch adopted by the configured backend. + +use std::cell::{Cell, RefCell}; +use std::rc::Rc; + +use ext_php_rs::binary_slice::BinarySlice; +use ext_php_rs::flags::ClassFlags; +use ext_php_rs::prelude::*; +use ext_php_rs::types::Zval; + +use crate::batch_columns::{batch_size_of, HeldBatch}; +use crate::ctx::{call_method, zval_long}; +use crate::exception::ext_exception; +use crate::interfaces::json_open_source_ce; +use crate::iterator::RustIterator; +use crate::json::read::JsonReader; +use crate::source::{self, reading, Fed, CHUNK}; + +const CLASS: &str = "RustJsonOpenSource"; + +struct Shared { + stream: Zval, + reader: RefCell, + /// The chunk the opener already read at `offset`; empty once fed. + head: RefCell>, + offset: Cell, +} + +/// One `batches()` call over the shared reader. +struct JsonFeed { + shared: Rc, + schema: Zval, + batch_size: usize, +} + +impl Fed for JsonFeed { + fn next_batch(&self) -> PhpResult> { + reading(&self.shared.reader, CLASS)?.next_columns(&self.schema, self.batch_size) + } + + /// `SourceStream::read()` runs with no borrow held: the stream may call back into the source. + fn feed(&self) -> PhpResult { + let head = std::mem::take(&mut *self.shared.head.borrow_mut()); + let chunk = if head.is_empty() { + let read = call_method( + &self.shared.stream, + "read", + &mut [zval_long(CHUNK), zval_long(self.shared.offset.get())], + )?; + + read.zend_str() + .ok_or_else(|| ext_exception("flow_php expected SourceStream::read() to return a string"))? + .as_bytes() + .to_vec() + } else { + head + }; + + if chunk.is_empty() { + return Ok(false); + } + + reading(&self.shared.reader, CLASS)?.feed(&chunk); + self.shared.offset.set(self.shared.offset.get() + chunk.len() as i64); + + Ok(true) + } + + fn finish(&self) -> PhpResult<()> { + reading(&self.shared.reader, CLASS)?.finish(); + + Ok(()) + } +} + +#[php_class] +#[php( + name = "Flow\\ETL\\Adapter\\JSON\\RustJsonOpenSource", + flags = ClassFlags::Final, + implements(ce = json_open_source_ce, stub = "Flow\\ETL\\Adapter\\JSON\\JsonOpenSource") +)] +pub struct RustJsonOpenSource { + shared: Rc, +} + +#[php_impl] +impl RustJsonOpenSource { + /// `$head`: the chunk the opener already read at `$offset` ('' for none); the bytes before it are JSON whitespace + /// after an optional BOM, which the reader would skip. `$uri` names the file in refusals. + pub fn __construct(stream: &Zval, lines: bool, uri: BinarySlice, head: BinarySlice, offset: i64) -> Self { + Self { + shared: Rc::new(Shared { + stream: stream.shallow_clone(), + reader: RefCell::new(JsonReader::new(lines, &uri)), + head: RefCell::new(head.to_vec()), + offset: Cell::new(offset), + }), + } + } + + /// Exactly `$batchSize` rows keyed and ordered by `$schema` (the last may be shorter), every column adopted by + /// `$backend`; refusals are `RowsBuilder::appendRows()`'s, row indexes relative to the batch. + pub fn batches(&self, schema: &Zval, batchSize: i64, backend: &Zval) -> PhpResult { + let fed = JsonFeed { + shared: Rc::clone(&self.shared), + schema: schema.shallow_clone(), + batch_size: batch_size_of(batchSize, "JSON")?, + }; + + Ok(source::batches(fed, schema, backend)) + } + + pub fn close(&self) -> PhpResult<()> { + call_method(&self.shared.stream, "close", &mut [])?; + + Ok(()) + } +} diff --git a/src/extension/flow-php-ext/src/json/write.rs b/src/extension/flow-php-ext/src/json/write.rs index f63392efdd..e44b5fafd3 100644 --- a/src/extension/flow-php-ext/src/json/write.rs +++ b/src/extension/flow-php-ext/src/json/write.rs @@ -1,15 +1,17 @@ -//! `Flow\ETL\Adapter\JSON\NativeJsonWriter`: a `Rows` batch as the text `JSONEncoder::encode()` returns, rendered from -//! the arrow arrays; the columns it does not render arrive as the fragments `JSONEncoder::fragments()` produced. +//! `Flow\ETL\Adapter\JSON\RustJSONEncoder`: a `Rows` batch as the text `PhpJSONEncoder::encode()` returns, rendered +//! from the arrow arrays; the columns it does not render are the fragments the held `PhpJSONEncoder::fragments()` +//! produces. +use ext_php_rs::binary::Binary; use ext_php_rs::binary_slice::BinarySlice; use ext_php_rs::exception::PhpException; use ext_php_rs::flags::ClassFlags; use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, Zval}; -use crate::ctx::zval_str; +use crate::interfaces::json_encoder_ce; use crate::render::{invalid_argument, runtime}; -use crate::text::batch::{batch, cells, renderer, unrendered}; +use crate::text::batch::{batch, cells, renderer, Unrendered}; use crate::text::json::{self, Flags}; use crate::text::value::{Formats, Renderer}; use crate::text::Error; @@ -29,16 +31,31 @@ enum Cells<'a> { } #[php_class] -#[php(name = "Flow\\ETL\\Adapter\\JSON\\NativeJsonWriter", flags = ClassFlags::Final)] -pub struct NativeJsonWriter { +#[php( + name = "Flow\\ETL\\Adapter\\JSON\\RustJSONEncoder", + flags = ClassFlags::Final, + implements(ce = json_encoder_ce, stub = "Flow\\ETL\\Adapter\\JSON\\JSONEncoder") +)] +pub struct RustJSONEncoder { flags: Flags, formats: Formats, + /// The `PhpJSONEncoder` that renders the unrendered columns. + php: Zval, + unrendered: Unrendered, } #[php_impl] -impl NativeJsonWriter { - pub fn __construct(flags: i64, date_time_format: BinarySlice, date_format: BinarySlice) -> PhpResult { - if flags & !(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION) != 0 { +impl RustJSONEncoder { + pub fn __construct( + flags: i64, + date_time_format: BinarySlice, + date_format: BinarySlice, + php: &Zval, + ) -> PhpResult { + if flags + & !(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION) + != 0 + { return Err(invalid_argument( "flow_php JSON writer supports only the JSON_THROW_ON_ERROR, JSON_UNESCAPED_SLASHES, JSON_UNESCAPED_UNICODE and JSON_PRESERVE_ZERO_FRACTION flags" .to_string(), @@ -52,16 +69,24 @@ impl NativeJsonWriter { preserve_zero_fraction: flags & JSON_PRESERVE_ZERO_FRACTION != 0, }, formats: Formats::parse(&date_time_format, &date_format), + php: php.shallow_clone(), + unrendered: Unrendered::default(), }) } - /// The columns of `$schema` this writer does not render itself. - pub fn unrendered(&self, schema: &Zval) -> PhpResult { - unrendered(schema, &self.formats, false) + /// One object per row, joined by `$separator`; the unrendered columns through the held encoder's `fragments()`. + pub fn encode(&mut self, rows: &Zval, separator: BinarySlice) -> PhpResult> { + let fragments = self + .unrendered + .render(rows, &self.php, "fragments", &self.formats, false)?; + + self.render_rows(rows, &fragments, &separator) } +} - /// `$fragments`: `JSONEncoder::fragments()` of the unrendered columns; one object per row, joined by `$separator`. - pub fn encode(&self, rows: &Zval, fragments: &ZendHashTable, separator: BinarySlice) -> PhpResult { +impl RustJSONEncoder { + /// `$fragments`: `PhpJSONEncoder::fragments()` of the unrendered columns. + fn render_rows(&self, rows: &Zval, fragments: &ZendHashTable, separator: &[u8]) -> PhpResult> { let batch = batch(rows, &self.formats, false)?; let mut keys = Vec::with_capacity(batch.columns.len()); let mut columns = Vec::with_capacity(batch.columns.len()); @@ -84,7 +109,7 @@ impl NativeJsonWriter { let mut non_finite = false; if i > 0 { - out.extend_from_slice(&separator); + out.extend_from_slice(separator); } if columns.is_empty() { @@ -95,7 +120,9 @@ impl NativeJsonWriter { out.extend_from_slice(key); match column { - Cells::Native(renderer) => renderer.json(&mut out, i, &self.flags, &mut non_finite).map_err(refused)?, + Cells::Native(renderer) => renderer + .json(&mut out, i, &self.flags, &mut non_finite) + .map_err(refused)?, Cells::Fragments(fragments) => out.extend_from_slice(fragments[i].ok_or_else(|| { invalid_argument("flow_php expected a JSON fragment of every row, got null".to_string()) })?), @@ -109,6 +136,6 @@ impl NativeJsonWriter { } } - Ok(zval_str(&out)) + Ok(Binary::new(out)) } } diff --git a/src/extension/flow-php-ext/src/json_check.rs b/src/extension/flow-php-ext/src/json_check.rs index fa2ebec9c7..1cdbdcb9aa 100644 --- a/src/extension/flow-php-ext/src/json_check.rs +++ b/src/extension/flow-php-ext/src/json_check.rs @@ -8,7 +8,10 @@ pub fn json_nesting_within_php_depth(bytes: &[u8]) -> bool { /// Any such escape, paired or not, is left to PHP. pub fn json_without_surrogate_escape(bytes: &[u8]) -> bool { !memchr::memchr_iter(b'\\', bytes).any(|at| { - matches!(bytes.get(at + 1..at + 4), Some([b'u', b'd' | b'D', b'8'..=b'9' | b'a'..=b'f' | b'A'..=b'F'])) + matches!( + bytes.get(at + 1..at + 4), + Some([b'u', b'd' | b'D', b'8'..=b'9' | b'a'..=b'f' | b'A'..=b'F']) + ) }) } diff --git a/src/extension/flow-php-ext/src/kind_builder.rs b/src/extension/flow-php-ext/src/kind_builder.rs index e97800d169..1445dec92d 100644 --- a/src/extension/flow-php-ext/src/kind_builder.rs +++ b/src/extension/flow-php-ext/src/kind_builder.rs @@ -112,7 +112,11 @@ impl KindBuilder { pub fn append_null(&mut self) { match self { KindBuilder::Null { len } => *len += 1, - KindBuilder::Fixed { width, values, validity } => { + KindBuilder::Fixed { + width, + values, + validity, + } => { values.resize(values.len() + *width, 0); validity.append_null(); } @@ -126,7 +130,11 @@ impl KindBuilder { offsets.push(*offsets.last().expect("offsets start at 0")); validity.append_null(); } - KindBuilder::Struct { len, validity, children } => { + KindBuilder::Struct { + len, + validity, + children, + } => { *len += 1; validity.append_null(); @@ -157,7 +165,12 @@ impl KindBuilder { } pub fn append_bytes(&mut self, bytes: &[u8]) -> Result<(), OffsetOverflow> { - let KindBuilder::Bytes { offsets, data, validity } = self else { + let KindBuilder::Bytes { + offsets, + data, + validity, + } = self + else { unreachable!("append_bytes on a non bytes kind"); }; @@ -189,8 +202,17 @@ impl KindBuilder { /// Closes a valid list or map row over the elements appended since the previous row. pub fn end_entries(&mut self) -> Result<(), OffsetOverflow> { let (offsets, validity, len) = match self { - KindBuilder::List { offsets, validity, element } => (offsets, validity, element.len()), - KindBuilder::Map { offsets, validity, keys, .. } => (offsets, validity, keys.len()), + KindBuilder::List { + offsets, + validity, + element, + } => (offsets, validity, element.len()), + KindBuilder::Map { + offsets, + validity, + keys, + .. + } => (offsets, validity, keys.len()), _ => unreachable!("end_entries on a non list/map kind"), }; @@ -222,7 +244,11 @@ impl KindBuilder { pub fn truncate(&mut self, len: usize) { match self { KindBuilder::Null { len: rows } => *rows = len, - KindBuilder::Fixed { width, values, validity } => { + KindBuilder::Fixed { + width, + values, + validity, + } => { values.truncate(len * *width); validity.truncate(len); } @@ -230,23 +256,40 @@ impl KindBuilder { values.truncate(len); validity.truncate(len); } - KindBuilder::Bytes { offsets, data, validity } => { + KindBuilder::Bytes { + offsets, + data, + validity, + } => { offsets.truncate(len + 1); data.truncate(offsets[len] as usize); validity.truncate(len); } - KindBuilder::List { offsets, validity, element } => { + KindBuilder::List { + offsets, + validity, + element, + } => { offsets.truncate(len + 1); element.truncate(offsets[len] as usize); validity.truncate(len); } - KindBuilder::Map { offsets, validity, keys, values } => { + KindBuilder::Map { + offsets, + validity, + keys, + values, + } => { offsets.truncate(len + 1); keys.truncate(offsets[len] as usize); values.truncate(offsets[len] as usize); validity.truncate(len); } - KindBuilder::Struct { len: rows, validity, children } => { + KindBuilder::Struct { + len: rows, + validity, + children, + } => { *rows = len; validity.truncate(len); @@ -268,8 +311,12 @@ impl KindBuilder { match kind { Kind::Null => unreachable!("appended above"), Kind::Int64 => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), - Kind::Timestamp => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), - Kind::Duration => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), + Kind::Timestamp => { + self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()) + } + Kind::Duration => { + self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()) + } Kind::Int32 => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), Kind::Float64 => self.append_fixed(&array.as_primitive::().value(i).to_le_bytes()), Kind::Uuid => self.append_fixed(array.as_fixed_size_binary().value(i)), @@ -280,7 +327,8 @@ impl KindBuilder { let offsets = list.value_offsets(); for j in offsets[i] as usize..offsets[i + 1] as usize { - self.list_element().append_from(list.values().as_ref(), &element.kind, j)?; + self.list_element() + .append_from(list.values().as_ref(), &element.kind, j)?; } self.end_entries()?; @@ -323,15 +371,37 @@ impl KindBuilder { (KindBuilder::Boolean { values, validity }, _) => builder .nulls(validity.finish_cloned()) .add_buffer(values.finish_cloned().into_inner()), - (KindBuilder::Bytes { offsets, data, validity }, _) => builder + ( + KindBuilder::Bytes { + offsets, + data, + validity, + }, + _, + ) => builder .nulls(validity.finish_cloned()) .add_buffer(Buffer::from_slice_ref(offsets)) .add_buffer(Buffer::from_slice_ref(data)), - (KindBuilder::List { offsets, validity, element }, Kind::List(field)) => builder + ( + KindBuilder::List { + offsets, + validity, + element, + }, + Kind::List(field), + ) => builder .nulls(validity.finish_cloned()) .add_buffer(Buffer::from_slice_ref(offsets)) .add_child_data(element.finish(&field.kind)?), - (KindBuilder::Map { offsets, validity, keys, values }, Kind::Map(key, value)) => { + ( + KindBuilder::Map { + offsets, + validity, + keys, + values, + }, + Kind::Map(key, value), + ) => { let arrow_schema::DataType::Map(entries, _) = data_type(kind) else { unreachable!("a map kind has a map data type") }; @@ -346,15 +416,15 @@ impl KindBuilder { .add_buffer(Buffer::from_slice_ref(offsets)) .add_child_data(entries) } - (KindBuilder::Struct { validity, children, .. }, Kind::Struct(fields)) => builder - .nulls(validity.finish_cloned()) - .child_data( + (KindBuilder::Struct { validity, children, .. }, Kind::Struct(fields)) => { + builder.nulls(validity.finish_cloned()).child_data( children .iter() .zip(fields) .map(|(child, field)| child.finish(&field.kind)) .collect::>()?, - ), + ) + } _ => unreachable!("a builder is finished with the kind it was built for"), }; @@ -418,8 +488,19 @@ mod tests { let structure = array.as_struct(); assert_eq!(array.len(), 1); - assert_eq!(structure.column(0).as_primitive::().values().to_vec(), vec![1]); - assert_eq!(structure.column(1).as_list::().values().as_binary::().value(0), b"kept"); + assert_eq!( + structure.column(0).as_primitive::().values().to_vec(), + vec![1] + ); + assert_eq!( + structure + .column(1) + .as_list::() + .values() + .as_binary::() + .value(0), + b"kept" + ); assert_eq!(structure.column(1).as_list::().values().len(), 1); assert_eq!(structure.column(2).as_map().keys().len(), 1); } diff --git a/src/extension/flow-php-ext/src/lib.rs b/src/extension/flow-php-ext/src/lib.rs index de80b7cfa8..1a1a61046e 100644 --- a/src/extension/flow-php-ext/src/lib.rs +++ b/src/extension/flow-php-ext/src/lib.rs @@ -11,6 +11,7 @@ mod date_check; mod exception; mod globals; mod interfaces; +mod iterator; mod json; mod json_check; mod kind_builder; @@ -18,19 +19,15 @@ mod parquet; mod physical; mod plan; mod render; +mod source; mod text; mod uuid_check; mod values; -use ext_php_rs::binary_slice::BinarySlice; use ext_php_rs::prelude::*; -use ext_php_rs::types::{ZendHashTable, Zval}; use ext_php_rs::zend::ModuleEntry; use ext_php_rs::{info_table_end, info_table_row, info_table_start}; -use crate::ctx::{ht_insert, zval_str}; -use crate::exception::ext_exception; - pub extern "C" fn php_module_info(_module: *mut ModuleEntry) { info_table_start!(); info_table_row!("flow_php.enabled", "true"); @@ -42,139 +39,14 @@ pub extern "C" fn php_module_info(_module: *mut ModuleEntry) { /// /// Only called by the PHP engine during module startup (MINIT). pub unsafe extern "C" fn module_startup(_type: i32, _module_number: i32) -> i32 { - if let Err(e) = exception::register() { - eprintln!("flow_php: failed to register Flow\\Floe\\Exception\\ExtensionException: {e}"); - return -1; - } if let Err(e) = interfaces::register() { - eprintln!("flow_php: failed to register the Flow\\ETL\\Column interfaces: {e}"); + eprintln!("flow_php: failed to register the Flow\\ETL interfaces: {e}"); return -1; } 0 } -/// Native counterpart of `CSVLineReader` + `CSVEncoder::decode()`: bytes in, rows or native columns out, -/// byte-identical to the PHP path. Resumable - `feed` any chunk size, `finish` at EOF. -#[php_class] -#[php(name = "Flow\\ETL\\Adapter\\CSV\\RustCSVReaderNative")] -pub struct RustCSVReaderNative { - reader: csv::CsvReader, - columns: csv::columns::CsvColumns, -} - -#[php_impl] -impl RustCSVReaderNative { - pub fn __construct( - separator: BinarySlice, - enclosure: BinarySlice, - escape: BinarySlice, - with_header: bool, - empty_to_null: bool, - remove_bom: bool, - ) -> PhpResult { - Ok(Self { - reader: csv::CsvReader::new(&separator, &enclosure, &escape, with_header, empty_to_null, remove_bom)?, - columns: csv::columns::CsvColumns::default(), - }) - } - - pub fn feed(&mut self, chunk: BinarySlice) { - self.reader.feed(&chunk); - } - - pub fn finish(&mut self) { - self.reader.finish(); - } - - pub fn headers(&mut self) -> PhpResult { - let headers = self.reader.headers(); - let mut list = ZendHashTable::with_capacity(headers.len() as u32); - - for header in headers { - list.push(zval_str(header)) - .map_err(|e| ext_exception(format!("flow_php failed to collect a CSV header: {e:?}")))?; - } - - let mut zv = Zval::new(); - zv.set_hashtable(list); - - Ok(zv) - } - - /// Folds up to `limit` buffered rows (-1: all) into `fold`; returns how many it folded. - pub fn fold(&mut self, fold: &mut RustColumnFoldNative, limit: i64) -> PhpResult { - let limit = match limit { - -1 => None, - limit => Some( - u64::try_from(limit).map_err(|_| ext_exception("flow_php CSV fold limit must be -1 or at least 0"))?, - ), - }; - - Ok(self.reader.fold(&mut fold.fold, limit)? as i64) - } - - #[php(name = "consumedBytes")] - pub fn consumed_bytes(&self) -> i64 { - self.reader.consumed_bytes() as i64 - } - - pub fn next(&mut self, batch_size: i64) -> PhpResult { - let mut zv = Zval::new(); - zv.set_hashtable(self.reader.next(batch_columns::batch_size_of(batch_size, "CSV")?)?); - - Ok(zv) - } - - /// Exactly `$batchSize` rows keyed and ordered by `$schema` while that many are buffered, the remainder after - /// `finish()`, else null. Refusals are `RowsBuilder::appendRows()`'s, row indexes relative to the batch. - #[php(name = "nextColumns")] - pub fn next_columns(&mut self, schema: &Zval, batch_size: i64) -> PhpResult { - csv::columns::next_columns(&mut self.reader, &mut self.columns, schema, batch_columns::batch_size_of(batch_size, "CSV")?) - } -} - -/// `ColumnTypes::observe()` over native CSV rows: a column fold seeded with the header names and gated by the -/// candidate types' `toString()` codes. HTML and XML candidates are never passed - the PHP side folds those itself. -#[php_class] -#[php(name = "Flow\\ETL\\Adapter\\CSV\\RustColumnFoldNative")] -pub struct RustColumnFoldNative { - fold: csv::fold::Fold, -} - -#[php_impl] -impl RustColumnFoldNative { - pub fn __construct(names: &ZendHashTable, candidates: &ZendHashTable) -> PhpResult { - Ok(Self { - fold: csv::fold::Fold::new(csv::fold::string_values(names), &csv::fold::string_values(candidates))?, - }) - } - - /// `StringTypeNarrower::narrow($value)->toString()` for the fold's candidates. - #[php(name = "narrowOne")] - pub fn narrow_one(&mut self, value: BinarySlice) -> PhpResult { - Ok(self.fold.narrower.narrow(&value)?.code().to_string()) - } - - /// Column name => type `toString()`, first-seen order. - pub fn types(&self) -> Zval { - let mut types = ZendHashTable::new(); - - for (name, code) in self.fold.types() { - ht_insert(&mut types, name, zval_str(code.as_bytes())); - } - - let mut zv = Zval::new(); - zv.set_hashtable(types); - - zv - } - - pub fn rows(&self) -> i64 { - self.fold.rows() as i64 - } -} - #[php_module] #[php(startup = "module_startup")] pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { @@ -184,15 +56,15 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { .globals(&globals::GLOBALS) .request_startup_function(globals::request_startup) .request_shutdown_function(globals::request_shutdown) - .class::() - .class::() - .class::() - .class::() - .class::() - .class::() - .class::() - .class::() - .class::() - .class::() - .class::() + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() + .class::() } diff --git a/src/extension/flow-php-ext/src/parquet/etl.rs b/src/extension/flow-php-ext/src/parquet/etl.rs index fcc8cc2e37..2f3999b1a4 100644 --- a/src/extension/flow-php-ext/src/parquet/etl.rs +++ b/src/extension/flow-php-ext/src/parquet/etl.rs @@ -1,6 +1,7 @@ -//! `Flow\ETL\Adapter\Parquet\{NativeParquetReader, NativeParquetWriter}`: `Rows` of `NativeColumn`s straight from +//! `Flow\ETL\Adapter\Parquet\{RustParquetOpenSource, RustParquetOpenSink}`: `Rows` of `RustColumn`s straight from //! arrow-ext's Parquet batches, and any `Rows` straight to its writer, through the Arrow C Data Interface. +use std::cell::RefCell; use std::rc::Rc; use std::sync::Arc; @@ -10,12 +11,21 @@ use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, Zval}; use crate::arrow_c; -use crate::backend::DefaultBackend; -use crate::column::NativeColumn; -use crate::ctx::{call_method, call_static, ht_for_each, ht_insert, null_zval, zval_long, zval_str}; +use crate::backend::{adopt_batch, native_column}; +use crate::batch_columns::HeldBatch; +use crate::column::RustColumn; +use crate::ctx::{ + call_method, column_key, construct, find_class, ht_for_each, ht_insert, null_zval, zval_long, zval_str, +}; use crate::exception::ext_exception; +use crate::interfaces::{parquet_open_sink_ce, parquet_open_source_ce}; +use crate::iterator::RustIterator; use crate::plan::{type_plan, TypePlan}; +const FILE_READER: &str = "Flow\\Parquet\\Engine\\RustParquetFileReader"; +const FILE_WRITER: &str = "Flow\\Parquet\\Engine\\RustParquetFileWriter"; +const BATCH_READER: &str = "Flow\\Arrow\\Parquet\\RustBatchReader"; + /// `Schema::definitions()` as (name, definition): an int key is a numeric column name. fn definitions(schema: &Zval) -> PhpResult, Zval)>> { let definitions = call_method(schema, "definitions", &mut [])?; @@ -25,10 +35,7 @@ fn definitions(schema: &Zval) -> PhpResult, Zval)>> { let mut named = Vec::with_capacity(definitions.len()); ht_for_each(definitions, |name, index, definition| { - named.push(( - name.map_or_else(|| index.to_string().into_bytes(), |name| name.as_bytes().to_vec()), - definition.shallow_clone(), - )); + named.push((column_key(name, index), definition.shallow_clone())); Ok(()) })?; @@ -36,89 +43,150 @@ fn definitions(schema: &Zval) -> PhpResult, Zval)>> { Ok(named) } -#[php_class] -#[php(name = "Flow\\ETL\\Adapter\\Parquet\\NativeParquetReader", flags = ClassFlags::Final)] -pub struct NativeParquetReader { - batches: Zval, - schema: Zval, - columns: Vec<(Vec, Rc)>, +/// The next Arrow C batch of `RustBatchReader` as `RustColumn`s under `columns`' plans. +fn next_batch(batches: &Zval, columns: &[(Vec, Rc)]) -> PhpResult> { + let batch = call_method(batches, "next", &mut [])?; + + if batch.is_null() { + return Ok(None); + } + + let (count, arrays) = arrow_c::import(&batch, columns)?; + let mut held = ZendHashTable::with_capacity(columns.len() as u32); + + for ((name, plan), array) in columns.iter().zip(arrays) { + let mut native = Zval::new(); + RustColumn::new(array, Rc::clone(plan)).set_zval(&mut native, false)?; + ht_insert(&mut held, name, native); + } + + Ok(Some(HeldBatch { columns: held, count })) } -#[php_impl] -impl NativeParquetReader { - /// `$batches`: a `Flow\Arrow\Parquet\BatchReader` over `$schema`'s columns; its schema is checked here, before - /// any batch. - pub fn __construct(batches: &Zval, schema: &Zval) -> PhpResult { - let mut columns = Vec::new(); +/// `$object` is arrow-ext's `$class`: the only object whose Arrow state flow_php can read. +fn expect_arrow(object: &Zval, class: &str) -> PhpResult<()> { + if object + .object() + .is_some_and(|object| find_class(class).is_ok_and(|ce| object.instance_of(ce))) + { + return Ok(()); + } - for (name, definition) in definitions(schema)? { - columns.push((name, type_plan(&call_method(&definition, "type", &mut [])?)?)); - } + Err(ext_exception(format!("flow_php expected a {class}"))) +} - arrow_c::check_schema(&call_method(batches, "schema", &mut [])?, &columns)?; +#[php_class] +#[php( + name = "Flow\\ETL\\Adapter\\Parquet\\RustParquetOpenSource", + flags = ClassFlags::Final, + implements(ce = parquet_open_source_ce, stub = "Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSource") +)] +pub struct RustParquetOpenSource { + file: Zval, + /// The `RustBatchReader` of the last `batches()`, closed by the next one and by `close()`. + batches: RefCell>, +} + +#[php_impl] +impl RustParquetOpenSource { + /// `$file`: arrow-ext's `Flow\Parquet\Engine\RustParquetFileReader`, which owns the stream. + pub fn __construct(file: &Zval) -> PhpResult { + expect_arrow(file, FILE_READER)?; Ok(Self { - batches: batches.shallow_clone(), - schema: schema.shallow_clone(), - columns, + file: file.shallow_clone(), + batches: RefCell::new(None), }) } - /// The next batch as `Rows::fromColumns($schema, $columns, $count)`, null after the last. - pub fn next(&mut self) -> PhpResult { - let batch = call_method(&self.batches, "next", &mut [])?; - - if batch.is_null() { - return Ok(null_zval()); - } - - let (count, arrays) = arrow_c::import(&batch, &self.columns)?; - let mut columns = ZendHashTable::with_capacity(self.columns.len() as u32); + /// Batches of at most `$batchSize` rows of `$schema`'s columns, every column adopted by `$backend`; the file's + /// schema is checked before any batch. + pub fn batches( + &self, + schema: &Zval, + batchSize: i64, + offset: Option, + limit: Option, + backend: &Zval, + ) -> PhpResult { + let mut columns = Vec::new(); + let mut names = ZendHashTable::new(); - for ((name, plan), array) in self.columns.iter().zip(arrays) { - let mut native = Zval::new(); - NativeColumn::new(array, Rc::clone(plan)).set_zval(&mut native, false)?; - ht_insert(&mut columns, name, native); + for (name, definition) in definitions(schema)? { + columns.push((name.clone(), type_plan(&call_method(&definition, "type", &mut [])?)?)); + names.push(zval_str(&name))?; } - let mut columns_zv = Zval::new(); - columns_zv.set_hashtable(columns); - - call_static( - "Flow\\ETL\\Rows", - "fromColumns", - &mut [self.schema.shallow_clone(), columns_zv, zval_long(count as i64)], - ) + let mut names_zv = Zval::new(); + names_zv.set_hashtable(names); + let optional = |value: Option| value.map_or_else(null_zval, zval_long); + + self.close()?; + + let batches = construct( + find_class(BATCH_READER)?, + &mut [ + self.file.shallow_clone(), + names_zv, + zval_long(batchSize), + optional(offset), + optional(limit), + ], + )? + .into_zval(false)?; + *self.batches.borrow_mut() = Some(batches.shallow_clone()); + + arrow_c::check_schema(&call_method(&batches, "schema", &mut [])?, &columns)?; + + let (schema, backend) = (schema.shallow_clone(), backend.shallow_clone()); + + Ok(RustIterator::new(Box::new(move || { + next_batch(&batches, &columns)? + .map(|batch| adopt_batch(&schema, &backend, batch)) + .transpose() + }))) } - pub fn close(&mut self) -> PhpResult<()> { - call_method(&self.batches, "close", &mut [])?; + pub fn close(&self) -> PhpResult<()> { + // the borrow ends before close() runs PHP + let batches = self.batches.borrow_mut().take(); + + if let Some(batches) = batches { + call_method(&batches, "close", &mut [])?; + } Ok(()) } } #[php_class] -#[php(name = "Flow\\ETL\\Adapter\\Parquet\\NativeParquetWriter", flags = ClassFlags::Final)] -pub struct NativeParquetWriter { +#[php( + name = "Flow\\ETL\\Adapter\\Parquet\\RustParquetOpenSink", + flags = ClassFlags::Final, + implements(ce = parquet_open_sink_ce, stub = "Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSink") +)] +pub struct RustParquetOpenSink { writer: Zval, } #[php_impl] -impl NativeParquetWriter { - /// `$writer`: a `Flow\Arrow\Parquet\RowsWriter`, which owns the stream. - pub fn __construct(writer: &Zval) -> Self { - Self { +impl RustParquetOpenSink { + /// `$writer`: arrow-ext's `Flow\Parquet\Engine\RustParquetFileWriter`, which owns the stream. + pub fn __construct(writer: &Zval) -> PhpResult { + expect_arrow(writer, FILE_WRITER)?; + + Ok(Self { writer: writer.shallow_clone(), - } + }) } - /// Every column of `$rows` - a `NativeColumn` as it is, any other column adopted into one - as one batch; the + /// Every column of `$rows` - a `RustColumn` as it is, any other column adopted into one - as one batch; the /// writer takes its columns by name and writes a column the batch lacks as nulls. pub fn write(&mut self, rows: &Zval) -> PhpResult<()> { let count = call_method(rows, "count", &mut [])? .long() - .ok_or_else(|| ext_exception("flow_php expected Rows::count() to return an int"))? as usize; + .ok_or_else(|| ext_exception("flow_php expected Rows::count() to return an int"))? + as usize; let columns = call_method(rows, "columns", &mut [])?; let columns = columns .array() @@ -127,27 +195,20 @@ impl NativeParquetWriter { let mut arrays = Vec::with_capacity(columns.len()); ht_for_each(columns, |name, index, column| { - let name = name.map_or_else(|| index.to_string().into_bytes(), |name| name.as_bytes().to_vec()); - let adopted; - let native = match column.extract::<&NativeColumn>() { - Some(native) => native, - None => { - let definition = call_method(&schema, "get", &mut [zval_str(&name)])?; - adopted = DefaultBackend.adopt(&definition, column)?.0; - adopted - .extract::<&NativeColumn>() - .ok_or_else(|| ext_exception("flow_php expected DefaultBackend::adopt() to build a NativeColumn"))? - } + let name = column_key(name, index); + let data = match column.extract::<&RustColumn>() { + Some(native) => Arc::clone(native.data()), + None => native_column(&call_method(&schema, "get", &mut [zval_str(&name)])?, column)?.1, }; - arrays.push((String::from_utf8_lossy(&name).into_owned(), Arc::clone(native.data()))); + arrays.push((String::from_utf8_lossy(&name).into_owned(), data)); Ok(()) })?; let mut batch = Zval::new(); arrow_c::export(count, arrays)?.set_zval(&mut batch, false)?; - call_method(&self.writer, "writeBatch", &mut [batch])?; + call_method(&self.writer, "writeArrowBatch", &mut [batch])?; Ok(()) } diff --git a/src/extension/flow-php-ext/src/parquet/mod.rs b/src/extension/flow-php-ext/src/parquet/mod.rs index 518d60af32..fcf58cca5e 100644 --- a/src/extension/flow-php-ext/src/parquet/mod.rs +++ b/src/extension/flow-php-ext/src/parquet/mod.rs @@ -1,3 +1,7 @@ //! Parquet in flow_php: the `Flow\ETL\Adapter\Parquet` surface over arrow-ext's Parquet batches. +#[allow( + non_snake_case, + reason = "PHP takes a parameter name from its Rust identifier: the contracts' are camelCase" +)] pub mod etl; diff --git a/src/extension/flow-php-ext/src/physical.rs b/src/extension/flow-php-ext/src/physical.rs index 32b52532fd..e79f1c7489 100644 --- a/src/extension/flow-php-ext/src/physical.rs +++ b/src/extension/flow-php-ext/src/physical.rs @@ -110,7 +110,11 @@ pub fn physical_at(array: &dyn Array, kind: &Kind, i: usize) -> Result R let mut ht = ZendHashTable::with_capacity((offsets[i + 1] - offsets[i]) as u32); for j in offsets[i] as usize..offsets[i + 1] as usize { - push(&mut ht, value_at(list.values().as_ref(), &element.kind, element_node, j)?)?; + push( + &mut ht, + value_at(list.values().as_ref(), &element.kind, element_node, j)?, + )?; } Ok(array_zval(ht)) @@ -173,7 +180,11 @@ pub fn value_at(array: &dyn Array, kind: &Kind, node: &ValueNode, i: usize) -> R continue; } - ht_insert(&mut ht, field.name.as_bytes(), value_at(child.as_ref(), &field.kind, child_node, i)?); + ht_insert( + &mut ht, + field.name.as_bytes(), + value_at(child.as_ref(), &field.kind, child_node, i)?, + ); } Ok(array_zval(ht)) @@ -230,12 +241,19 @@ pub fn append_physical(builder: &mut KindBuilder, kind: &Kind, physical: &Zval) builder.append_fixed(bytes); } Kind::Bytes => builder - .append_bytes(physical.zend_str().ok_or_else(|| wrong_physical(kind, physical))?.as_bytes()) + .append_bytes( + physical + .zend_str() + .ok_or_else(|| wrong_physical(kind, physical))? + .as_bytes(), + ) .map_err(overflow)?, Kind::List(element) => { let values = physical.array().ok_or_else(|| wrong_physical(kind, physical))?; - ht_for_each(values, |_, _, value| append_physical(builder.list_element(), &element.kind, value))?; + ht_for_each(values, |_, _, value| { + append_physical(builder.list_element(), &element.kind, value) + })?; builder.end_entries().map_err(overflow)?; } Kind::Map(key, value) => { diff --git a/src/extension/flow-php-ext/src/plan.rs b/src/extension/flow-php-ext/src/plan.rs index 385933c831..3344b2c07c 100644 --- a/src/extension/flow-php-ext/src/plan.rs +++ b/src/extension/flow-php-ext/src/plan.rs @@ -75,7 +75,8 @@ fn json_plan(type_zv: &Zval) -> Result, PhpException> { let parsed = parse_type(&json).map_err(json_exception)?; let type_obj = expect_object(type_zv, "a Type")?; - let type_ce = unsafe { type_obj.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php failed to resolve a Type class"))?; + let type_ce = + unsafe { type_obj.ce.as_ref() }.ok_or_else(|| ext_exception("flow_php failed to resolve a Type class"))?; let physical = call_method(&instance(PHYSICAL_FOR)?, "type", &mut [type_zv.shallow_clone()])?; let plan = Rc::new(TypePlan { kind: kind_of(&parsed).map_err(json_exception)?, @@ -98,12 +99,18 @@ fn json_plan(type_zv: &Zval) -> Result, PhpException> { /// `PhysicalFor::definition($definition)`: its refusals (wildcard enum, mixed, a foreign definition) are PHP's. pub fn physical_for_definition(definition: &Zval) -> Result { - call_method(&instance(PHYSICAL_FOR)?, "definition", &mut [definition.shallow_clone()]) + call_method( + &instance(PHYSICAL_FOR)?, + "definition", + &mut [definition.shallow_clone()], + ) } fn value_node(parsed: &TypeJson) -> Result { let child = |part: Option<&TypeJson>| -> Result, PhpException> { - Ok(Box::new(value_node(part.ok_or_else(|| ext_exception("flow_php type JSON is missing a nested type"))?)?)) + Ok(Box::new(value_node(part.ok_or_else(|| { + ext_exception("flow_php type JSON is missing a nested type") + })?)?)) }; Ok(match parsed.type_.as_str() { diff --git a/src/extension/flow-php-ext/src/render.rs b/src/extension/flow-php-ext/src/render.rs index a745dea0e6..9963536087 100644 --- a/src/extension/flow-php-ext/src/render.rs +++ b/src/extension/flow-php-ext/src/render.rs @@ -14,7 +14,7 @@ use crate::exception::ext_exception; const INVALID_ARGUMENT: &str = "Flow\\ETL\\Exception\\InvalidArgumentException"; const OFFSET_OVERFLOW: &str = "Flow\\ETL\\Exception\\OffsetOverflow"; -const RUNTIME: &str = "Flow\\ETL\\Exception\\RuntimeException"; +pub const RUNTIME: &str = "Flow\\ETL\\Exception\\RuntimeException"; pub fn exception(class: &str, message: String) -> PhpException { match find_class(class) { @@ -32,7 +32,10 @@ pub fn runtime(message: String) -> PhpException { } pub fn offset_overflow(last: u64) -> PhpException { - exception(OFFSET_OVERFLOW, format!("Offsets exceed the i32 range of a batch buffer: the last offset is {last}")) + exception( + OFFSET_OVERFLOW, + format!("Offsets exceed the i32 range of a batch buffer: the last offset is {last}"), + ) } fn of(of: Of) -> &'static str { @@ -58,18 +61,31 @@ pub fn decode_exception(error: Error, type_zv: &Zval, kind: &Kind) -> PhpExcepti let message = match error { Error::OffsetOverflow { last } => return offset_overflow(last), Error::BuffersExhausted => "Column buffers exhausted: the column needs more buffers than given".to_string(), - Error::OffsetsLength { of: layout, bytes, expected, rows } => format!( - "{} offsets buffer of {bytes} bytes, expected {expected} for {rows} rows", - of(layout) - ), + Error::OffsetsLength { + of: layout, + bytes, + expected, + rows, + } => { + format!( + "{} offsets buffer of {bytes} bytes, expected {expected} for {rows} rows", + of(layout) + ) + } Error::MapEntriesValidity { bytes } => format!("Map entries validity must be omitted, got {bytes} bytes"), - Error::ValidityTooShort { bytes, rows } => format!("Validity bitmap of {bytes} bytes is too short for {rows} rows"), + Error::ValidityTooShort { bytes, rows } => { + format!("Validity bitmap of {bytes} bytes is too short for {rows} rows") + } Error::NullKindNullCount { rows, null_count } => { format!("Null column of {rows} rows carries a null count of {null_count}") } - Error::NullCountMismatch { declared, derived, rows } => format!( - "Column null count {declared} disagrees with its validity bitmap ({derived} nulls in {rows} rows)" - ), + Error::NullCountMismatch { + declared, + derived, + rows, + } => { + format!("Column null count {declared} disagrees with its validity bitmap ({derived} nulls in {rows} rows)") + } Error::NestedNulls { node, role, nulls } => { let name = match type_name_at(type_zv, kind, node) { Ok(name) => name, @@ -85,7 +101,11 @@ pub fn decode_exception(error: Error, type_zv: &Zval, kind: &Kind) -> PhpExcepti } ) } - Error::BufferCount { node, buffers, expected } => { + Error::BufferCount { + node, + buffers, + expected, + } => { let name = match type_name_at(type_zv, kind, node) { Ok(name) => name, Err(e) => return e, @@ -94,15 +114,27 @@ pub fn decode_exception(error: Error, type_zv: &Zval, kind: &Kind) -> PhpExcepti format!("Column of type {name} holds {buffers} buffers, its layout needs {expected}") } Error::OffsetsStart { of: layout, first } => format!("{} offsets start at {first}, not 0", of(layout)), - Error::OffsetsNotMonotonic { of: layout, index, previous, current } => format!( + Error::OffsetsNotMonotonic { + of: layout, + index, + previous, + current, + } => format!( "{} offsets are not monotonic: offset {} is {previous}, offset {index} is {current}", of(layout), index - 1 ), - Error::ValuesLength { values: layout, bytes, expected, rows } => format!( - "{} values buffer of {bytes} bytes, expected {expected} for {rows} rows", - values(layout) - ), + Error::ValuesLength { + values: layout, + bytes, + expected, + rows, + } => { + format!( + "{} values buffer of {bytes} bytes, expected {expected} for {rows} rows", + values(layout) + ) + } Error::Utf8DataLength { bytes, last_offset } => { format!("Utf8 data buffer of {bytes} bytes, the last offset is {last_offset}") } diff --git a/src/extension/flow-php-ext/src/source.rs b/src/extension/flow-php-ext/src/source.rs new file mode 100644 index 0000000000..5ed7c32120 --- /dev/null +++ b/src/extension/flow-php-ext/src/source.rs @@ -0,0 +1,58 @@ +//! What the Rust open sources share: the chunk size they read streams in and the batches loop over a reader the +//! stream is fed into. + +use std::cell::{RefCell, RefMut}; + +use ext_php_rs::prelude::*; +use ext_php_rs::types::Zval; + +use crate::backend::adopt_batch; +use crate::batch_columns::HeldBatch; +use crate::iterator::RustIterator; +use crate::render::runtime; + +/// Each chunk is held as a PHP string, so it sets the read's peak memory: 32 KB matched the PHP path's own peak on wide +/// and narrow files. `AdaptiveJsonOpenSource::CHUNK` is its PHP copy. +pub const CHUNK: i64 = 1 << 15; + +/// A reader a stream is fed into, one consuming call at a time. +pub trait Fed { + /// The next full batch of what was fed (the remainder once finished), none while more input is needed. + fn next_batch(&self) -> PhpResult>; + + /// The next chunk of the stream fed in; false at its end. + fn feed(&self) -> PhpResult; + + fn finish(&self) -> PhpResult<()>; +} + +/// The batches of `fed`, each adopted by `backend` into `Rows` of `schema`. +pub fn batches(fed: impl Fed + 'static, schema: &Zval, backend: &Zval) -> RustIterator { + let (schema, backend) = (schema.shallow_clone(), backend.shallow_clone()); + let mut finished = false; + + RustIterator::new(Box::new(move || loop { + if let Some(batch) = fed.next_batch()? { + return adopt_batch(&schema, &backend, batch).map(Some); + } + + if finished { + return Ok(None); + } + + if !fed.feed()? { + fed.finish()?; + finished = true; + } + })) +} + +/// The reader, borrowed only while Rust code runs on it: a stream, a backend or an inferrer that calls back into the +/// source mid-read is refused, never a panic. +pub fn reading<'a, T>(reader: &'a RefCell, class: &str) -> PhpResult> { + reader.try_borrow_mut().map_err(|_| { + runtime(format!( + "{class} is already reading: a read cannot start from inside another" + )) + }) +} diff --git a/src/extension/flow-php-ext/src/text/batch.rs b/src/extension/flow-php-ext/src/text/batch.rs index 351e93369f..07920cbad4 100644 --- a/src/extension/flow-php-ext/src/text/batch.rs +++ b/src/extension/flow-php-ext/src/text/batch.rs @@ -4,12 +4,13 @@ use std::rc::Rc; use arrow_array::ArrayRef; +use ext_php_rs::boxed::ZBox; use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, Zval}; -use crate::backend::DefaultBackend; -use crate::column::NativeColumn; -use crate::ctx::{call_method, ht_get, zval_str}; +use crate::backend::native_column; +use crate::column::RustColumn; +use crate::ctx::{call_method, ht_get, ht_insert, zval_str}; use crate::exception::ext_exception; use crate::plan::{type_plan, TypePlan}; use crate::render::invalid_argument; @@ -31,30 +32,68 @@ fn definitions(schema: &Zval) -> PhpResult { } /// The names of the columns of `$schema` the native lane does not render. -pub fn unrendered(schema: &Zval, formats: &Formats, json_column_is_text: bool) -> PhpResult { +fn unrendered_names(schema: &Zval, formats: &Formats, json_column_is_text: bool) -> PhpResult>> { let definitions = definitions(schema)?; let definitions = definitions .array() .ok_or_else(|| ext_exception("flow_php expected Schema::definitions() to return an array"))?; - let mut names = ZendHashTable::new(); + let mut names = Vec::new(); for (name, definition) in definitions.iter() { - let plan = type_plan(&call_method(definition, "type", &mut [])?)?; - - if !renders(&plan.values, formats, json_column_is_text) { - names - .push(zval_str(name.to_string().as_bytes())) - .map_err(|e| ext_exception(format!("flow_php failed to collect column names: {e:?}")))?; + if !renders( + &type_plan(&call_method(definition, "type", &mut [])?)?.values, + formats, + json_column_is_text, + ) { + names.push(name.to_string().into_bytes()); } } - let mut zv = Zval::new(); - zv.set_hashtable(names); + Ok(names) +} + +/// The unrendered columns of the last `Schema` object a writer saw; consecutive batches share one. +#[derive(Default)] +pub struct Unrendered { + schema: Option, + names: Vec>, +} + +impl Unrendered { + /// `$php->$method($schema->get($name)->type(), $rows->column($name))` of every unrendered column, by name. + pub fn render( + &mut self, + rows: &Zval, + php: &Zval, + method: &str, + formats: &Formats, + json_column_is_text: bool, + ) -> PhpResult> { + let schema = call_method(rows, "schema", &mut [])?; + let held = self.schema.as_ref().and_then(Zval::object); + + if !matches!((held, schema.object()), (Some(held), Some(object)) if std::ptr::eq(held, object)) { + self.names = unrendered_names(&schema, formats, json_column_is_text)?; + self.schema = Some(schema.shallow_clone()); + } + + let mut rendered = ZendHashTable::with_capacity(self.names.len() as u32); + + for name in &self.names { + let definition = call_method(&schema, "get", &mut [zval_str(name)])?; + let mut args = [ + call_method(&definition, "type", &mut [])?, + call_method(rows, "column", &mut [zval_str(name)])?, + ]; + + ht_insert(&mut rendered, name, call_method(php, method, &mut args)?); + } - Ok(zv) + Ok(rendered) + } } -/// `$rows` in schema order; a rendered column that is not a `NativeColumn` is adopted into one. +/// `$rows` in schema order; a rendered column that is not a `RustColumn` is adopted into one. pub fn batch(rows: &Zval, formats: &Formats, json_column_is_text: bool) -> PhpResult { let count = call_method(rows, "count", &mut [])? .long() @@ -72,20 +111,22 @@ pub fn batch(rows: &Zval, formats: &Formats, json_column_is_text: bool) -> PhpRe for (name, definition) in definitions.iter() { let name = name.to_string().into_bytes(); let column = ht_get(held, &name).ok_or_else(|| { - ext_exception(format!("flow_php expected Rows to hold the column \"{}\"", String::from_utf8_lossy(&name))) + ext_exception(format!( + "flow_php expected Rows to hold the column \"{}\"", + String::from_utf8_lossy(&name) + )) })?; - let native = match column.extract::<&NativeColumn>() { + let native = match column.extract::<&RustColumn>() { Some(native) => renders(&native.plan().values, formats, json_column_is_text) .then(|| (Rc::clone(native.plan()), ArrayRef::clone(native.data()))), None => { - if renders(&type_plan(&call_method(definition, "type", &mut [])?)?.values, formats, json_column_is_text) { - let adopted = DefaultBackend.adopt(definition, column)?.0; - let adopted = adopted - .extract::<&NativeColumn>() - .ok_or_else(|| ext_exception("flow_php expected DefaultBackend::adopt() to build a NativeColumn"))?; - - Some((Rc::clone(adopted.plan()), ArrayRef::clone(adopted.data()))) + if renders( + &type_plan(&call_method(definition, "type", &mut [])?)?.values, + formats, + json_column_is_text, + ) { + Some(native_column(definition, column)?) } else { None } diff --git a/src/extension/flow-php-ext/src/text/date.rs b/src/extension/flow-php-ext/src/text/date.rs index 5001266e7e..17e58d80e2 100644 --- a/src/extension/flow-php-ext/src/text/date.rs +++ b/src/extension/flow-php-ext/src/text/date.rs @@ -100,7 +100,11 @@ impl Zone { return Ok(()); }; - let listed = call_method(&ctx::timezone(id)?, "getTransitions", &mut [zval_long(min_second), zval_long(max_second)])?; + let listed = call_method( + &ctx::timezone(id)?, + "getTransitions", + &mut [zval_long(min_second), zval_long(max_second)], + )?; let listed = listed .array() .ok_or_else(|| ext_exception("flow_php expected DateTimeZone::getTransitions() to return an array"))?; @@ -118,12 +122,17 @@ impl Zone { transitions.push(Transition { from: field(b"ts")?.long().unwrap_or(min_second), offset: field(b"offset")?.long().unwrap_or(0) as i32, - abbreviation: field(b"abbr")?.zend_str().map(|abbr| abbr.as_bytes().to_vec()).unwrap_or_default(), + abbreviation: field(b"abbr")? + .zend_str() + .map(|abbr| abbr.as_bytes().to_vec()) + .unwrap_or_default(), }); } if transitions.is_empty() { - return Err(ext_exception("flow_php expected DateTimeZone::getTransitions() to list the offset in force")); + return Err(ext_exception( + "flow_php expected DateTimeZone::getTransitions() to list the offset in force", + )); } Ok(()) @@ -135,9 +144,13 @@ impl Zone { Zone::Utc => (0, b"UTC"), Zone::Offset { seconds, abbreviation } => (*seconds, abbreviation), Zone::Named { transitions, .. } => { - let index = transitions.partition_point(|transition| transition.from <= second).saturating_sub(1); + let index = transitions + .partition_point(|transition| transition.from <= second) + .saturating_sub(1); - transitions.get(index).map_or((0, b"UTC"), |transition| (transition.offset, &transition.abbreviation)) + transitions + .get(index) + .map_or((0, b"UTC"), |transition| (transition.offset, &transition.abbreviation)) } } } @@ -207,7 +220,11 @@ fn civil(days: i64) -> (i64, i64, i64) { let day_of_year = day_of_era - (365 * year_of_era + year_of_era / 4 - year_of_era / 100); let month_index = (5 * day_of_year + 2) / 153; let day = day_of_year - (153 * month_index + 2) / 5 + 1; - let month = if month_index < 10 { month_index + 3 } else { month_index - 9 }; + let month = if month_index < 10 { + month_index + 3 + } else { + month_index - 9 + }; (year_of_era + era * 400 + i64::from(month <= 2), month, day) } @@ -321,8 +338,14 @@ mod tests { #[test] fn micros_before_the_epoch_floor_to_the_second_below() { - assert_eq!(formatted("Y-m-d H:i:s.u v U", -500_000, &Zone::Utc), "1969-12-31 23:59:59.500000 500 -1"); - assert_eq!(formatted("Y-m-d\\TH:i:s.u G\\h", 1_767_323_045_123_456, &Zone::Utc), "2026-01-02T03:04:05.123456 3h"); + assert_eq!( + formatted("Y-m-d H:i:s.u v U", -500_000, &Zone::Utc), + "1969-12-31 23:59:59.500000 500 -1" + ); + assert_eq!( + formatted("Y-m-d\\TH:i:s.u G\\h", 1_767_323_045_123_456, &Zone::Utc), + "2026-01-02T03:04:05.123456 3h" + ); } /// `edge-facts.log`: Europe/Warsaw across the 2026 gap and overlap, one transition list for the whole call. @@ -331,19 +354,43 @@ mod tests { let warsaw = Zone::Named { id: b"Europe/Warsaw".to_vec(), transitions: vec![ - Transition { from: 1_774_745_999, offset: 3_600, abbreviation: b"CET".to_vec() }, - Transition { from: 1_774_746_000, offset: 7_200, abbreviation: b"CEST".to_vec() }, - Transition { from: 1_792_890_000, offset: 3_600, abbreviation: b"CET".to_vec() }, + Transition { + from: 1_774_745_999, + offset: 3_600, + abbreviation: b"CET".to_vec(), + }, + Transition { + from: 1_774_746_000, + offset: 7_200, + abbreviation: b"CEST".to_vec(), + }, + Transition { + from: 1_792_890_000, + offset: 3_600, + abbreviation: b"CET".to_vec(), + }, ], }; for (second, expected) in [ - (1_774_745_999_i64, "2026-03-29T01:59:59+01:00 CET Europe/Warsaw +01:00 3600"), - (1_774_746_000, "2026-03-29T03:00:00+02:00 CEST Europe/Warsaw +02:00 7200"), - (1_792_889_999, "2026-10-25T02:59:59+02:00 CEST Europe/Warsaw +02:00 7200"), + ( + 1_774_745_999_i64, + "2026-03-29T01:59:59+01:00 CET Europe/Warsaw +01:00 3600", + ), + ( + 1_774_746_000, + "2026-03-29T03:00:00+02:00 CEST Europe/Warsaw +02:00 7200", + ), + ( + 1_792_889_999, + "2026-10-25T02:59:59+02:00 CEST Europe/Warsaw +02:00 7200", + ), (1_792_890_000, "2026-10-25T02:00:00+01:00 CET Europe/Warsaw +01:00 3600"), ] { - assert_eq!(formatted("Y-m-d\\TH:i:sP T e p Z", second * 1_000_000, &warsaw), expected); + assert_eq!( + formatted("Y-m-d\\TH:i:sP T e p Z", second * 1_000_000, &warsaw), + expected + ); } } @@ -354,7 +401,10 @@ mod tests { formatted("e|T|P|p|O|Z|c", 0, &Zone::of(b"+02:30")), "+02:30|GMT+0230|+02:30|+02:30|+0230|9000|1970-01-01T02:30:00+02:30" ); - assert_eq!(formatted("e|T|P|O|Z H:i", 0, &Zone::of(b"-05:00")), "-05:00|GMT-0500|-05:00|-0500|-18000 19:00"); + assert_eq!( + formatted("e|T|P|O|Z H:i", 0, &Zone::of(b"-05:00")), + "-05:00|GMT-0500|-05:00|-0500|-18000 19:00" + ); } #[test] diff --git a/src/extension/flow-php-ext/src/text/json.rs b/src/extension/flow-php-ext/src/text/json.rs index 743985b632..386e3806b1 100644 --- a/src/extension/flow-php-ext/src/text/json.rs +++ b/src/extension/flow-php-ext/src/text/json.rs @@ -30,7 +30,10 @@ pub fn string(out: &mut Vec, text: &[u8], flags: &Flags) -> Result<(), Error let mut rest = text; // runs of bytes written as they are, then the one that is escaped - while let Some(at) = rest.iter().position(|byte| matches!(byte, 0..=0x1f | b'"' | b'\\' | b'/')) { + while let Some(at) = rest + .iter() + .position(|byte| matches!(byte, 0..=0x1f | b'"' | b'\\' | b'/')) + { out.extend_from_slice(&rest[..at]); ascii(out, rest[at], flags); rest = &rest[at + 1..]; @@ -100,31 +103,59 @@ mod tests { assert_eq!(escaped(b"", &flags).unwrap(), r#""""#); assert_eq!(escaped(b"a\"b\\c/d", &flags).unwrap(), r#""a\"b\\c\/d""#); - assert_eq!(escaped(b"\x08\x0c\n\r\t\x00\x1f\x7f", &flags).unwrap(), "\"\\b\\f\\n\\r\\t\\u0000\\u001f\x7f\""); + assert_eq!( + escaped(b"\x08\x0c\n\r\t\x00\x1f\x7f", &flags).unwrap(), + "\"\\b\\f\\n\\r\\t\\u0000\\u001f\x7f\"" + ); assert_eq!(escaped("<>&'".as_bytes(), &flags).unwrap(), r#""<>&'""#); - assert_eq!(escaped("zażółć".as_bytes(), &flags).unwrap(), r#""za\u017c\u00f3\u0142\u0107""#); + assert_eq!( + escaped("zażółć".as_bytes(), &flags).unwrap(), + r#""za\u017c\u00f3\u0142\u0107""# + ); } #[test] fn a_character_beyond_the_basic_plane_is_a_surrogate_pair() { - assert_eq!(escaped("😀".as_bytes(), &Flags::default()).unwrap(), r#""\ud83d\ude00""#); - assert_eq!(escaped("\u{10000}\u{10ffff}".as_bytes(), &Flags::default()).unwrap(), r#""\ud800\udc00\udbff\udfff""#); + assert_eq!( + escaped("😀".as_bytes(), &Flags::default()).unwrap(), + r#""\ud83d\ude00""# + ); + assert_eq!( + escaped("\u{10000}\u{10ffff}".as_bytes(), &Flags::default()).unwrap(), + r#""\ud800\udc00\udbff\udfff""# + ); } #[test] fn unescaped_slashes_and_unicode() { - let slashes = Flags { unescaped_slashes: true, ..Flags::default() }; - let unicode = Flags { unescaped_unicode: true, ..Flags::default() }; + let slashes = Flags { + unescaped_slashes: true, + ..Flags::default() + }; + let unicode = Flags { + unescaped_unicode: true, + ..Flags::default() + }; assert_eq!(escaped("a/ż".as_bytes(), &slashes).unwrap(), r#""a/\u017c""#); assert_eq!(escaped("a/ż😀".as_bytes(), &unicode).unwrap(), "\"a\\/ż😀\""); // the line terminators stay escaped without JSON_UNESCAPED_LINE_TERMINATORS - assert_eq!(escaped("\u{2027}\u{2028}\u{2029}\u{202a}".as_bytes(), &unicode).unwrap(), "\"\u{2027}\\u2028\\u2029\u{202a}\""); + assert_eq!( + escaped("\u{2027}\u{2028}\u{2029}\u{202a}".as_bytes(), &unicode).unwrap(), + "\"\u{2027}\\u2028\\u2029\u{202a}\"" + ); } #[test] fn invalid_utf8_is_refused_and_appends_nothing() { - for text in [&b"\xff"[..], b"a\xc3\x28", b"\xed\xa0\x80", b"\xc0\xaf", b"\xf4\x90\x80\x80", b"abc\xe2\x82"] { + for text in [ + &b"\xff"[..], + b"a\xc3\x28", + b"\xed\xa0\x80", + b"\xc0\xaf", + b"\xf4\x90\x80\x80", + b"abc\xe2\x82", + ] { let mut out = b"kept".to_vec(); assert_eq!(string(&mut out, text, &Flags::default()), Err(Error::Utf8)); diff --git a/src/extension/flow-php-ext/src/text/mod.rs b/src/extension/flow-php-ext/src/text/mod.rs index 9b2ad7eab5..922f2b47cd 100644 --- a/src/extension/flow-php-ext/src/text/mod.rs +++ b/src/extension/flow-php-ext/src/text/mod.rs @@ -1,11 +1,11 @@ //! The text of column values as the PHP writers render it (`Flow\ETL\Column\TextValues` plus each encoder's syntax), //! read straight from the arrow arrays. +pub mod batch; pub mod date; pub mod float; pub mod json; pub mod value; -pub mod batch; /// What `json_encode()` refuses; `message()` and `code()` are `json_last_error_msg()` and `json_last_error()`. #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/src/extension/flow-php-ext/src/text/value.rs b/src/extension/flow-php-ext/src/text/value.rs index b4e7068ca6..45dfa83b63 100644 --- a/src/extension/flow-php-ext/src/text/value.rs +++ b/src/extension/flow-php-ext/src/text/value.rs @@ -7,8 +7,8 @@ use std::collections::HashMap; use arrow_array::cast::AsArray; use arrow_array::types::{Date32Type, DurationMicrosecondType, Float64Type, Int64Type, TimestampMicrosecondType}; use arrow_array::{ - Array, BinaryArray, BooleanArray, Date32Array, DurationMicrosecondArray, FixedSizeBinaryArray, Float64Array, Int64Array, - ListArray, MapArray, TimestampMicrosecondArray, + Array, BinaryArray, BooleanArray, Date32Array, DurationMicrosecondArray, FixedSizeBinaryArray, Float64Array, + Int64Array, ListArray, MapArray, TimestampMicrosecondArray, }; use arrow_buffer::NullBuffer; use ext_php_rs::exception::PhpException; @@ -94,7 +94,12 @@ pub fn renders(node: &ValueNode, formats: &Formats, json_column_is_text: bool) - fn renders_nested(node: &ValueNode, formats: &Formats) -> bool { match node { - ValueNode::Plain | ValueNode::Null | ValueNode::Time | ValueNode::Uuid | ValueNode::Enum(_) | ValueNode::TimeZone => true, + ValueNode::Plain + | ValueNode::Null + | ValueNode::Time + | ValueNode::Uuid + | ValueNode::Enum(_) + | ValueNode::TimeZone => true, ValueNode::DateTime(_) => formats.date_time.is_some(), ValueNode::Date => formats.date.is_some(), ValueNode::Json | ValueNode::Markup(_) => false, @@ -130,7 +135,12 @@ impl<'a> Renderer<'a> { Values::List { list, - element: Box::new(Renderer::new(element_node, &element.kind, list.values().as_ref(), formats)?), + element: Box::new(Renderer::new( + element_node, + &element.kind, + list.values().as_ref(), + formats, + )?), } } (ValueNode::Map(value_node), Kind::Map(key, value)) => { @@ -152,7 +162,11 @@ impl<'a> Renderer<'a> { .zip(fields) .zip(array.as_struct().columns()) .map(|((node, field), child)| { - Some((field.name.as_bytes(), field.optional, Renderer::new(node, &field.kind, child.as_ref(), formats)?)) + Some(( + field.name.as_bytes(), + field.optional, + Renderer::new(node, &field.kind, child.as_ref(), formats)?, + )) }) .collect::>()?, ), @@ -214,7 +228,9 @@ impl<'a> Renderer<'a> { Values::Bytes(array) => out.extend_from_slice(array.value(i)), Values::Uuid(array) => push_uuid_text(out, array.value(i)), Values::Instant { array, format, zone } => date::write(out, format, array.value(i), zone), - Values::Days { array, format } => date::write(out, format, i64::from(array.value(i)) * 86_400_000_000, &Zone::Utc), + Values::Days { array, format } => { + date::write(out, format, i64::from(array.value(i)) * 86_400_000_000, &Zone::Utc) + } Values::List { .. } | Values::Map { .. } | Values::Struct(_) => { let mut non_finite = false; @@ -262,7 +278,10 @@ impl<'a> Renderer<'a> { self.text(out, i)?; // a format of digits, dashes and colons needs no escaping; anything else is escaped as a string - if out[start + 1..].iter().all(|byte| matches!(byte, b' ' | b'+'..=b'.' | b'0'..=b':' | b'A'..=b'Z' | b'_' | b'a'..=b'z')) { + if out[start + 1..] + .iter() + .all(|byte| matches!(byte, b' ' | b'+'..=b'.' | b'0'..=b':' | b'A'..=b'Z' | b'_' | b'a'..=b'z')) + { out.push(b'"'); } else { let text = out.split_off(start + 1); @@ -290,7 +309,10 @@ impl<'a> Renderer<'a> { let offsets = map.value_offsets(); out.push(b'{'); - for (written, (j, last)) in entries(keys, offsets[i] as usize, offsets[i + 1] as usize).into_iter().enumerate() { + for (written, (j, last)) in entries(keys, offsets[i] as usize, offsets[i + 1] as usize) + .into_iter() + .enumerate() + { if written > 0 { out.push(b','); } @@ -380,8 +402,8 @@ mod tests { use std::sync::Arc; use arrow_array::builder::{BinaryBuilder, Int64Builder, MapBuilder}; - use arrow_array::{Array, ArrayRef, Int64Array, ListArray, StructArray}; use arrow_array::types::Int64Type; + use arrow_array::{Array, ArrayRef, Int64Array, ListArray, StructArray}; use arrow_schema::{DataType, Field as ArrowField}; use flow_batch_frame::kind::{Field, Kind}; @@ -403,7 +425,11 @@ mod tests { } fn field(name: &str, kind: Kind, optional: bool) -> Box { - Box::new(Field { name: name.to_owned(), kind, optional }) + Box::new(Field { + name: name.to_owned(), + kind, + optional, + }) } fn string_map(rows: &[&[(&[u8], i64)]]) -> ArrayRef { @@ -460,7 +486,8 @@ mod tests { #[test] fn a_list_is_always_a_list_and_a_null_is_null() { - let list = ListArray::from_iter_primitive::([Some(vec![Some(1), None, Some(3)]), Some(vec![]), None]); + let list = + ListArray::from_iter_primitive::([Some(vec![Some(1), None, Some(3)]), Some(vec![]), None]); let node = ValueNode::List(Box::new(ValueNode::Plain)); let kind = Kind::List(field("element", Kind::Int64, true)); diff --git a/src/extension/flow-php-ext/src/values.rs b/src/extension/flow-php-ext/src/values.rs index ebb6af086d..acffffc235 100644 --- a/src/extension/flow-php-ext/src/values.rs +++ b/src/extension/flow-php-ext/src/values.rs @@ -11,8 +11,7 @@ use crate::date_check::days_from_civil; use crate::exception::ext_exception; extern "C" { - fn php_date_instantiate(pce: *mut ext_php_rs::zend::ClassEntry, object: *mut Zval) - -> *mut Zval; + fn php_date_instantiate(pce: *mut ext_php_rs::zend::ClassEntry, object: *mut Zval) -> *mut Zval; #[cfg(php84)] fn php_date_initialize_from_ts_long(dateobj: *mut c_void, sec: i64, usec: c_int); @@ -114,7 +113,11 @@ pub fn datetime_days(datetime: &ZendObject) -> Option { } /// A fresh `DateTimeImmutable` initialised by `init` over its `php_date_obj`, then moved into `zone`. -fn datetime_in(zone: &[u8], init: impl FnOnce(*mut c_void) -> bool, failure: impl FnOnce() -> PhpException) -> Result { +fn datetime_in( + zone: &[u8], + init: impl FnOnce(*mut c_void) -> bool, + failure: impl FnOnce() -> PhpException, +) -> Result { let fns = ctx::datetime_immutable()?; let mut datetime = Zval::new(); @@ -132,10 +135,17 @@ fn datetime_in(zone: &[u8], init: impl FnOnce(*mut c_void) -> bool, failure: imp return Err(failure()); } - let datetime = call_handle(fns.set_timezone, Some(datetime_obj), &mut [ctx::timezone(zone)?], "restore a datetime timezone")?; + let datetime = call_handle( + fns.set_timezone, + Some(datetime_obj), + &mut [ctx::timezone(zone)?], + "restore a datetime timezone", + )?; if !datetime.is_object() { - return Err(ext_exception("flow_php expected setTimezone to return a datetime object")); + return Err(ext_exception( + "flow_php expected setTimezone to return a datetime object", + )); } Ok(datetime) @@ -176,7 +186,11 @@ pub fn datetime_from_micros(micros: i64, zone: &[u8]) -> Result Result { ); let fns = ctx::interval()?; let mut interval = ZendObject::new(fns.ce); - call_handle(fns.construct, Some(&mut interval), &mut [zval_str(spec.as_bytes())], "construct DateInterval")?; + call_handle( + fns.construct, + Some(&mut interval), + &mut [zval_str(spec.as_bytes())], + "construct DateInterval", + )?; let mut fraction = Zval::new(); fraction.set_double((magnitude % 1_000_000) as f64 / 1_000_000.0); write_property_raw(&mut interval, &mut ZendStr::new("f", false), fraction)?; - write_property_raw(&mut interval, &mut ZendStr::new("invert", false), zval_long(i64::from(micros < 0)))?; + write_property_raw( + &mut interval, + &mut ZendStr::new("invert", false), + zval_long(i64::from(micros < 0)), + )?; let mut zv = Zval::new(); zv.set_object(&mut interval); @@ -278,7 +301,10 @@ pub fn json_from_bytes(bytes: &[u8]) -> Result { /// `hex2bin()` of a 36-char uuid with its dashes removed. pub fn uuid_bytes(text: &[u8]) -> Option<[u8; 16]> { let mut bytes = [0u8; 16]; - let mut digits = text.iter().filter(|byte| **byte != b'-').map(|byte| (*byte as char).to_digit(16)); + let mut digits = text + .iter() + .filter(|byte| **byte != b'-') + .map(|byte| (*byte as char).to_digit(16)); for byte in &mut bytes { let high = digits.next()??; @@ -291,18 +317,12 @@ pub fn uuid_bytes(text: &[u8]) -> Option<[u8; 16]> { /// `new DateTimeImmutable($str, $timezone)` through the same C-level timelib parser, in its /// non-throwing `date_create()` flavor: `Ok(None)` on parse failure, no exception. -pub(crate) fn date_from_free_form( - bytes: &[u8], - timezone: Option<&mut Zval>, -) -> Result, PhpException> { +pub(crate) fn date_from_free_form(bytes: &[u8], timezone: Option<&mut Zval>) -> Result, PhpException> { let ce = ctx::datetime_immutable()?.ce; let mut datetime = Zval::new(); unsafe { - php_date_instantiate( - std::ptr::from_ref(ce).cast_mut(), - std::ptr::from_mut(&mut datetime), - ); + php_date_instantiate(std::ptr::from_ref(ce).cast_mut(), std::ptr::from_mut(&mut datetime)); } let datetime_obj = datetime diff --git a/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt b/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt index 2a2acae623..ea9d65f24a 100644 --- a/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt +++ b/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt @@ -1,27 +1,41 @@ --TEST-- -flow_php extension is loaded and symbols are registered +flow_php extension is loaded and registers the package interfaces and the Rust classes implementing them --SKIPIF-- --FILE-- getClassNames(); +sort($classes); -foreach (['Flow\ETL\Column\DefaultBackend', 'Flow\ETL\Column\NativeColumn', 'Flow\ETL\Column\NativeColumnBuilder', 'Flow\ETL\Adapter\CSV\RustCSVReaderNative', 'Flow\ETL\Adapter\CSV\RustColumnFoldNative', 'Flow\Floe\Exception\ExtensionException'] as $class) { - var_dump(class_exists($class, false)); +foreach ($classes as $class) { + $reflection = new ReflectionClass($class); + echo $reflection->isInterface() ? 'interface ' : 'class ', $class, $reflection->isInterface() ? '' : ' implements ' . implode(', ', array_diff($reflection->getInterfaceNames(), ['Traversable'])), "\n"; } + +var_dump(class_exists('Flow\Floe\Exception\ExtensionException', false) === false); ?> --EXPECT-- bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) +interface Flow\ETL\Adapter\CSV\CSVEncoder +interface Flow\ETL\Adapter\CSV\CSVOpenSource +class Flow\ETL\Adapter\CSV\RustCSVEncoder implements Flow\ETL\Adapter\CSV\CSVEncoder +class Flow\ETL\Adapter\CSV\RustCSVOpenSource implements Flow\ETL\Adapter\CSV\CSVOpenSource +interface Flow\ETL\Adapter\JSON\JSONEncoder +interface Flow\ETL\Adapter\JSON\JsonOpenSource +class Flow\ETL\Adapter\JSON\RustJSONEncoder implements Flow\ETL\Adapter\JSON\JSONEncoder +class Flow\ETL\Adapter\JSON\RustJsonOpenSource implements Flow\ETL\Adapter\JSON\JsonOpenSource +interface Flow\ETL\Adapter\Parquet\ParquetOpenSink +interface Flow\ETL\Adapter\Parquet\ParquetOpenSource +class Flow\ETL\Adapter\Parquet\RustParquetOpenSink implements Flow\ETL\Adapter\Parquet\ParquetOpenSink +class Flow\ETL\Adapter\Parquet\RustParquetOpenSource implements Flow\ETL\Adapter\Parquet\ParquetOpenSource +interface Flow\ETL\Column\Backend +interface Flow\ETL\Column\Column +interface Flow\ETL\Column\ColumnBuilder +class Flow\ETL\Column\RustBackend implements Flow\ETL\Column\Backend +class Flow\ETL\Column\RustColumn implements Flow\ETL\Column\Column +class Flow\ETL\Column\RustColumnBuilder implements Flow\ETL\Column\ColumnBuilder +class Flow\ETL\Column\RustColumnsBatch implements +class Flow\ETL\RustIterator implements Iterator bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/040_csv_tokenizer_parity.phpt b/src/extension/flow-php-ext/tests/phpt/040_csv_tokenizer_parity.phpt index b123216bde..ed70e73138 100644 --- a/src/extension/flow-php-ext/tests/phpt/040_csv_tokenizer_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/040_csv_tokenizer_parity.phpt @@ -6,8 +6,6 @@ native CSV fields match str_getcsv() byte for byte on every tokenizer edge case '612c622c63', 'quoted' => '2261222c226222', @@ -22,11 +20,7 @@ $cases = [ foreach ($cases as $case => $hex) { $input = hex2bin($hex); - $reader = new RustCSVReaderNative(',', '"', '\\', false, false, false); - $reader->feed($input . "\n"); - $reader->finish(); - - $fields = array_values($reader->next(10)[0]); + $fields = array_values(csv_native_rows($input . "\n", ',', '"', '\\', false, false, false)[1][0]); $expected = str_getcsv($input, ',', '"', '\\'); echo $case, ': ', $fields === $expected ? 'identical' : 'FAIL ' . json_encode(array_map(static fn(?string $f): ?string => $f === null ? null : bin2hex($f), $fields)), "\n"; diff --git a/src/extension/flow-php-ext/tests/phpt/045_csv_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/045_csv_no_leaks.phpt index b2d946369e..728f37fa9a 100644 --- a/src/extension/flow-php-ext/tests/phpt/045_csv_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/045_csv_no_leaks.phpt @@ -6,32 +6,27 @@ repeated native CSV reading does not leak memory feed($chunk); - $reader->next(2); + foreach ($source->records() as $record) { } - $reader->finish(); - $reader->headers(); + $source->headers(); - while ($reader->next(2) !== []) { - } - - $unfinished = new RustCSVReaderNative(';', "'", '', false, false, false); - $unfinished->feed("a;'open\n"); - $unfinished->next(10); + // abandoned after the first record + $unfinished = (new RustCSVOpenSource(new MemorySourceStream("a;'open\nb;c\n"), ';', "'", '', false, false, false, 4))->records(); + $unfinished->rewind(); try { - new RustCSVReaderNative(',,', '"', '\\', true, true, true); + new RustCSVOpenSource(new MemorySourceStream($raw), ',,', '"', '\\', true, true, true); throw new LogicException('an invalid separator was accepted'); - } catch (Flow\Floe\Exception\ExtensionException) { + } catch (Flow\ETL\Exception\RuntimeException) { } }; diff --git a/src/extension/flow-php-ext/tests/phpt/046_csv_narrow_parity.phpt b/src/extension/flow-php-ext/tests/phpt/046_csv_narrow_parity.phpt index 2f17aeaafc..ae99121d4d 100644 --- a/src/extension/flow-php-ext/tests/phpt/046_csv_narrow_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/046_csv_narrow_parity.phpt @@ -6,8 +6,9 @@ native narrowing matches StringTypeNarrower::narrow() on its fixtures, the byte- narrowOne($value)); + printf("%-32s %s\n", $value, rust_sniff_column([$value], $typer, false)->schema($floor)->get('v')->type()->toString()); } assert_narrow_parity('temporal candidates', $candidates, $temporal); diff --git a/src/extension/flow-php-ext/tests/phpt/048_csv_widen_parity.phpt b/src/extension/flow-php-ext/tests/phpt/048_csv_widen_parity.phpt index 972de86d42..d8cb0b1ba4 100644 --- a/src/extension/flow-php-ext/tests/phpt/048_csv_widen_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/048_csv_widen_parity.phpt @@ -6,9 +6,9 @@ the native fold widens every pair of CSV leaf types exactly like TypeWidener ['true', type_boolean()], 'timezone' => ['UTC', type_time_zone()], ]; -$candidates = array_map(static fn($type): string => $type->toString(), InferredTypes::default()->toArray()); +$typer = new StringTypeNarrower(InferredTypes::default()->toArray()); $widener = new TypeWidener(); $pairs = 0; $mismatches = 0; foreach ($leaves as $left => [$leftCell, $leftType]) { foreach ($leaves as $right => [$rightCell, $rightType]) { - $csv = fopen('php://memory', 'rb+'); - fputcsv($csv, ['c'], ',', '"', '\\'); - fputcsv($csv, [$leftCell ?? ''], ',', '"', '\\'); - fputcsv($csv, [$rightCell ?? ''], ',', '"', '\\'); - rewind($csv); - - $reader = new RustCSVReaderNative(',', '"', '\\', true, true, true); - $reader->feed((string) stream_get_contents($csv)); - $reader->finish(); - $fold = new RustColumnFoldNative([], $candidates); - $reader->fold($fold, -1); - - $expected = $widener->widen($leftType, $rightType)->toString(); - $actual = $fold->types()['c']; + $expected = ColumnTypes::fromColumnTypes(['v' => $widener->widen($leftType, $rightType)], 2, $typer); $pairs++; - if ($expected !== $actual) { + if ($expected != rust_sniff_column([$leftCell, $rightCell], $typer)) { $mismatches++; - echo "{$left} + {$right}: TypeWidener={$expected} native={$actual}\n"; + echo "{$left} + {$right}: TypeWidener=", $widener->widen($leftType, $rightType)->toString(), " native differs\n"; } } } diff --git a/src/extension/flow-php-ext/tests/phpt/049_csv_fold_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/049_csv_fold_no_leaks.phpt index 7f7c292b4d..6fcd28dea6 100644 --- a/src/extension/flow-php-ext/tests/phpt/049_csv_fold_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/049_csv_fold_no_leaks.phpt @@ -6,28 +6,19 @@ repeated native CSV folding - including every PHP callback and a rejected time z $type->toString(), InferredTypes::default()->toArray()); +$typer = new StringTypeNarrower(InferredTypes::default()->toArray()); $raw = "id,json,at,zone,offset,dup,dup\n1,\"{\"\"a\"\":1}\",2024-01-01 10:00:00,Europe/Warsaw,+99:60,x,\n2,[1],2024-02-30,UTC,+02:00,,y\n"; -$cycle = static function () use ($candidates, $raw): void { - $reader = new RustCSVReaderNative(',', '"', '\\', true, true, true); - $reader->feed($raw); - $reader->finish(); - $fold = new RustColumnFoldNative(['id', 'json'], $candidates); - $reader->fold($fold, -1); - $fold->types(); - $fold->rows(); - $fold->narrowOne('+99:60'); - $fold->narrowOne('{"a":[1,2]}'); - $fold->narrowOne('2024-01-01'); - - foreach (json_leak_cells() as $cell) { - $fold->narrowOne($cell); - } +$cycle = static function () use ($typer, $raw): void { + (new RustCSVOpenSource(new MemorySourceStream($raw), ',', '"', '\\', true, true, true)) + ->sniff(['id', 'json'], -1, new SchemaInference(), $typer); + rust_sniff_column(['+99:60', '{"a":[1,2]}', '2024-01-01', ...json_leak_cells()], $typer); }; for ($i = 0; $i < 10; $i++) { diff --git a/src/extension/flow-php-ext/tests/phpt/051_csv_guards.phpt b/src/extension/flow-php-ext/tests/phpt/051_csv_guards.phpt index 217c737d3b..24269f6bc8 100644 --- a/src/extension/flow-php-ext/tests/phpt/051_csv_guards.phpt +++ b/src/extension/flow-php-ext/tests/phpt/051_csv_guards.phpt @@ -1,48 +1,40 @@ --TEST-- -native CSV classes reject an invalid dialect, batch size, fold limit and HTML/XML candidates +RustCSVOpenSource rejects an invalid dialect, batch size and sniff row budget --SKIPIF-- --FILE-- new RustCSVReaderNative(',,', '"', '\\', true, true, true)); -expect_exception(static fn() => new RustCSVReaderNative(',', '', '\\', true, true, true)); -expect_exception(static fn() => new RustCSVReaderNative(',', '"', '\\\\', true, true, true)); -expect_exception(static fn() => (new RustCSVReaderNative(',', '"', '\\', true, true, true))->next(0)); -expect_exception(static fn() => (new RustCSVReaderNative(',', '"', '\\', true, true, true))->next(-1)); -$fold = new RustColumnFoldNative([], ['integer']); -expect_exception(static fn() => (new RustCSVReaderNative(',', '"', '\\', true, true, true))->fold($fold, -2)); -expect_exception(static fn() => new RustColumnFoldNative([], ['integer', 'html'])); -expect_exception(static fn() => new RustColumnFoldNative([], ['xml'])); +$source = static fn(string $separator = ',', string $enclosure = '"', string $escape = '\\'): RustCSVOpenSource => new RustCSVOpenSource( + new MemorySourceStream("id\n1\n"), + $separator, + $enclosure, + $escape, + true, + true, + true, +); -$pending = static function (): RustCSVReaderNative { - $reader = new RustCSVReaderNative(',', '"', '\\', true, true, true); - $reader->feed("id,name\n1,a\n"); - var_dump($reader->nextColumns(schema(int_schema('id'), str_schema('name')), 10)); - - return $reader; -}; -expect_exception(static fn() => $pending()->nextColumns(schema(int_schema('id')), 10)); -expect_exception(static fn() => $pending()->nextColumns(schema(int_schema('id'), str_schema('name')), 5)); -expect_exception(static fn() => (new RustCSVReaderNative(',', '"', '\\', true, true, true))->nextColumns(schema(int_schema('id')), 0)); +expect_exception(static fn() => $source(',,')); +expect_exception(static fn() => $source(',', '')); +expect_exception(static fn() => $source(',', '"', '\\\\')); +expect_exception(static fn() => $source()->batches(schema(int_schema('id')), 0, new RustBackend())); +expect_exception(static fn() => $source()->batches(schema(int_schema('id')), -1, new RustBackend())); +expect_exception(static fn() => $source()->sniff(['id'], -2, new SchemaInference(), new StringTypeNarrower())); ?> --EXPECT-- -Flow\Floe\Exception\ExtensionException: flow_php CSV separator must be exactly one byte -Flow\Floe\Exception\ExtensionException: flow_php CSV enclosure must be exactly one byte -Flow\Floe\Exception\ExtensionException: flow_php CSV escape must be empty or exactly one byte -Flow\Floe\Exception\ExtensionException: flow_php CSV batch size must be greater than 0 -Flow\Floe\Exception\ExtensionException: flow_php CSV batch size must be greater than 0 -Flow\Floe\Exception\ExtensionException: flow_php CSV fold limit must be -1 or at least 0 -Flow\Floe\Exception\ExtensionException: flow_php cannot fold html or xml candidates natively -Flow\Floe\Exception\ExtensionException: flow_php cannot fold html or xml candidates natively -NULL -Flow\Floe\Exception\ExtensionException: flow_php cannot change the schema of a pending CSV batch -NULL -Flow\Floe\Exception\ExtensionException: flow_php cannot change the batch size of a pending CSV batch -Flow\Floe\Exception\ExtensionException: flow_php CSV batch size must be greater than 0 +Flow\ETL\Exception\RuntimeException: flow_php CSV separator must be exactly one byte +Flow\ETL\Exception\RuntimeException: flow_php CSV enclosure must be exactly one byte +Flow\ETL\Exception\RuntimeException: flow_php CSV escape must be empty or exactly one byte +Flow\ETL\Exception\RuntimeException: flow_php CSV batch size must be greater than 0 +Flow\ETL\Exception\RuntimeException: flow_php CSV batch size must be greater than 0 +Flow\ETL\Exception\RuntimeException: flow_php CSV fold limit must be -1 or at least 0 diff --git a/src/extension/flow-php-ext/tests/phpt/054_csv_consumed_bytes.phpt b/src/extension/flow-php-ext/tests/phpt/054_csv_consumed_bytes.phpt index b54d75cbf4..c8f0789b22 100644 --- a/src/extension/flow-php-ext/tests/phpt/054_csv_consumed_bytes.phpt +++ b/src/extension/flow-php-ext/tests/phpt/054_csv_consumed_bytes.phpt @@ -1,88 +1,8800 @@ ---TEST-- -native CSV consumedBytes() counts the bytes of the rows it produced exactly like the PHP path, over any chunk size ---SKIPIF-- - ---FILE-- -records() as $values) { - if (++$taken >= $rows) { - break; - } - } - - return $source->producedBytes(); -}; - -$native = static function (string $raw, bool $withHeader, int $rows, int $chunk): int { - $reader = new RustCSVReaderNative(',', '"', '\\', $withHeader, true, true); - $fold = new RustColumnFoldNative([], []); - $folded = 0; - - foreach (str_split($raw, $chunk) as $piece) { - $reader->feed($piece); - $folded += $reader->fold($fold, $rows - $folded); - } - - $reader->finish(); - $reader->fold($fold, $rows - $folded); - - return $reader->consumedBytes(); -}; - -$cases = [ - 'LF' => ["a,b\n1,2\n33,44\n", true, 2], - 'CRLF' => ["a,b\r\n1,2\r\n33,44\r\n", true, 2], - 'quoted multi-line LF' => ["a,b\n\"x\ny\",1\n2,3\n", true, 2], - 'quoted multi-line CRLF' => ["a,b\r\n\"x\r\ny\",1\r\n2,3\r\n", true, 2], - 'blank lines' => ["a,b\n\n1,2\n\n", true, 3], - 'BOM without header' => ["\xEF\xBB\xBF1,2\n3,4\n", false, 2], - 'first two of three rows' => ["a,b\n1,2\n33,44\n555,666\n", true, 2], -]; - -foreach ($cases as $label => [$raw, $withHeader, $rows]) { - $expected = $php($raw, $withHeader, $rows); - $counts = array_unique(array_map( - static fn(int $chunk): int => $native($raw, $withHeader, $rows, $chunk), - [1, 3, 7, 4096], - )); - - echo $label, ': ', $counts === [$expected] ? 'identical ' . $expected : 'FAIL php=' . $expected . ' native=' . implode(',', $counts), "\n"; -} - -$reader = new RustCSVReaderNative(',', '"', '\\', true, true, true); -$reader->feed("a,b\n1,2\n33,44\n"); -$reader->finish(); -$reader->next(1); -echo 'next() counts too: ', $reader->consumedBytes(), "\n"; -$reader->next(10); -echo 'header excluded: ', $reader->consumedBytes(), "\n"; -?> ---EXPECT-- -LF: identical 10 -CRLF: identical 12 -quoted multi-line LF: identical 12 -quoted multi-line CRLF: identical 15 -blank lines: identical 6 -BOM without header: identical 11 -first two of three rows: identical 10 -next() counts too: 4 -header excluded: 10 +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +P$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +P$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +z$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +K$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +P$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +<$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +?$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +!$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +?$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +<$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +?$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +q$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +D$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +.$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +/$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +.$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +A$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +D$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +A$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +A$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +P$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +O$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +A$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +O$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +M$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +N$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +g$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +g$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +N$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +g$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +D$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +g$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +{$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +P$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +O$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +g$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +/$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +/$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +.$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +D$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +0$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +{$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; ++$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; ++$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +{$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +}$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +}$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +}$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +g$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +{$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +O$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +M$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +g$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +N$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +A$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +}$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +q$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +q$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +O$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +M$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +5$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +5$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +5$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +6$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +6$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +6$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +{$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +q$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +_$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +H$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +7$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +0$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +9$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +6$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +[$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +]$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +?$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +.$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +A$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +I$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +.$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +.$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +.$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +p$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +}$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +=$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +S$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +V$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +N$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +v$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +3$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +0$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +'$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +$$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +y$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +,$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +\$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +"$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +;$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +?$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +>$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +X$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +P$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +E$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +T$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +0$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +q$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +2$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +q$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +m$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +-$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +C$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +R$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +L$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +F$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +5$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +b$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +k$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +6$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +B$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +O$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +M$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +f$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +w$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +i$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +0$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +($source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +)$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +n$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +s$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +t$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +o$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +4$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +h$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +a$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +r$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +x$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +c$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +l$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +u$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +e$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +d$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +:$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + $source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +1$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; +0$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; + +$source = new RustCSVOpenSource(new MemorySourceStream("a,b\n1,2\n33,44\n"), ',', '"', '\\', true, true, true); +iterator_to_array($source->records()); +echo 'records() counts too, header excluded: ', $source->producedBytes(), "\n"; diff --git a/src/extension/flow-php-ext/tests/phpt/055_column_interfaces_skew.phpt b/src/extension/flow-php-ext/tests/phpt/055_column_interfaces_skew.phpt index fec7f9f69c..bea2adad21 100644 --- a/src/extension/flow-php-ext/tests/phpt/055_column_interfaces_skew.phpt +++ b/src/extension/flow-php-ext/tests/phpt/055_column_interfaces_skew.phpt @@ -1,5 +1,5 @@ --TEST-- -flow_php registers the column interfaces reflection-identical to the library files +flow_php registers the flow-php/etl and adapter interfaces reflection-identical to the package files --SKIPIF-- --FILE-- diff --git a/src/extension/flow-php-ext/tests/phpt/056_native_constructors_refused.phpt b/src/extension/flow-php-ext/tests/phpt/056_native_constructors_refused.phpt index 64e1cbccd2..bcf56f693a 100644 --- a/src/extension/flow-php-ext/tests/phpt/056_native_constructors_refused.phpt +++ b/src/extension/flow-php-ext/tests/phpt/056_native_constructors_refused.phpt @@ -1,18 +1,18 @@ --TEST-- -native columns and builders come only from DefaultBackend; a column is not serializable, a Rows of them is +native columns and builders come only from RustBackend; a column is not serializable, a Rows of them is --SKIPIF-- --FILE-- new NativeColumn()); -expect_exception(static fn() => new NativeColumnBuilder()); +expect_exception(static fn() => new RustColumn()); +expect_exception(static fn() => new RustColumnBuilder()); -foreach ([NativeColumn::class, NativeColumnBuilder::class] as $class) { +foreach ([RustColumn::class, RustColumnBuilder::class] as $class) { echo outcome(static fn() => (new ReflectionClass($class))->newInstanceWithoutConstructor()), "\n"; } @@ -23,10 +23,10 @@ echo outcome(static fn() => $rows->column('int')), "\n"; echo comparable(unserialize(serialize($rows))->toArray()) === comparable($rows->toArray()) ? 'round trip' : 'FAIL', "\n"; ?> --EXPECT-- -Flow\Floe\Exception\ExtensionException: Flow\ETL\Column\NativeColumn is built by DefaultBackend -Flow\Floe\Exception\ExtensionException: Flow\ETL\Column\NativeColumnBuilder is built by DefaultBackend -ReflectionException: Class Flow\ETL\Column\NativeColumn is an internal class marked as final that cannot be instantiated without invoking its constructor -ReflectionException: Class Flow\ETL\Column\NativeColumnBuilder is an internal class marked as final that cannot be instantiated without invoking its constructor -Flow\ETL\Column\NativeColumn -Exception: Serialization of 'Flow\ETL\Column\NativeColumn' is not allowed +Flow\ETL\Exception\RuntimeException: Flow\ETL\Column\RustColumn is built by RustBackend +Flow\ETL\Exception\RuntimeException: Flow\ETL\Column\RustColumnBuilder is built by RustBackend +ReflectionException: Class Flow\ETL\Column\RustColumn is an internal class marked as final that cannot be instantiated without invoking its constructor +ReflectionException: Class Flow\ETL\Column\RustColumnBuilder is an internal class marked as final that cannot be instantiated without invoking its constructor +Flow\ETL\Column\RustColumn +Exception: Serialization of 'Flow\ETL\Column\RustColumn' is not allowed round trip diff --git a/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt b/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt index 05ad3c9e67..794047b9ed 100644 --- a/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt @@ -6,7 +6,7 @@ native columns encode byte-identical frames to PHP columns, after every Rows res concat($native)->slice(0, $php->count())); $body = $php->encodeFrame(); $decodedPhp = (new FrameDecoder())->decode($body, $schema, new PhpBackend()); -$decodedNative = (new FrameDecoder())->decode($body, $schema, new DefaultBackend()); +$decodedNative = (new FrameDecoder())->decode($body, $schema, new RustBackend()); echo get_class($decodedNative->column('int')), "\n"; echo comparable($decodedPhp->toArray()) === comparable($decodedNative->toArray()) ? 'decoded rows identical' : 'DIFF', "\n"; ?> @@ -43,5 +43,5 @@ concat: identical project: identical withSchema: identical mixed: identical -Flow\ETL\Column\NativeColumn +Flow\ETL\Column\RustColumn decoded rows identical diff --git a/src/extension/flow-php-ext/tests/phpt/058_native_values_parity.phpt b/src/extension/flow-php-ext/tests/phpt/058_native_values_parity.phpt index 4c4b07cdfd..ca6599127d 100644 --- a/src/extension/flow-php-ext/tests/phpt/058_native_values_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/058_native_values_parity.phpt @@ -6,7 +6,7 @@ native columns read every row as the PHP columns read it: at(), value(), Rows::v encodeFrame(); foreach (['UTC', 'Europe/Warsaw', '+05:30'] as $zone) { $zoned = schema(datetime_schema('at', zone: $zone)); $expected = array_map($observe, (new FrameDecoder())->decode($frame, $zoned, new PhpBackend())->column('at')->values()); - $actual = array_map($observe, (new FrameDecoder())->decode($frame, $zoned, new DefaultBackend())->column('at')->values()); + $actual = array_map($observe, (new FrameDecoder())->decode($frame, $zoned, new RustBackend())->column('at')->values()); echo "zone {$zone}: ", serialize($expected) === serialize($actual) ? 'identical' : 'DIFF', "\n"; } diff --git a/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt b/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt index 1ee7cb8760..7f7c72b41f 100644 --- a/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/059_native_cast_parity.phpt @@ -1,12 +1,12 @@ --TEST-- -NativeColumnBuilder casts and refuses exactly as the PHP builder through append() and appendMany(), in every default zone +RustColumnBuilder casts and refuses exactly as the PHP builder through append() and appendMany(), in every default zone --SKIPIF-- --FILE-- --FILE-- [$definition, $buffers, $count, $nullCount]) { $php = outcome(static fn() => (new PhpBackend())->decode($definition, $buffers, $count, $nullCount)->values()); - $native = outcome(static fn() => (new DefaultBackend())->decode($definition, $buffers, $count, $nullCount)->values()); + $native = outcome(static fn() => (new RustBackend())->decode($definition, $buffers, $count, $nullCount)->values()); echo $label, ': ', $php === $native ? $native : "DIFF\n php: {$php}\n native: {$native}", "\n"; } diff --git a/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt b/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt index fc8c3d7c17..6c9cef8ae1 100644 --- a/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt +++ b/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt @@ -6,8 +6,8 @@ native and PHP columns build into each other: appendFrom/appendTake, Rows::conca gather([5, 0, 3, 3]), $rebuilt($php, new DefaultBackend(), true)); -$same('native appendFrom of a PHP column', $php->gather([5, 0, 3, 3]), $rebuilt($php, new DefaultBackend(), false)); +$same('native appendTake of a PHP column', $php->gather([5, 0, 3, 3]), $rebuilt($php, new RustBackend(), true)); +$same('native appendFrom of a PHP column', $php->gather([5, 0, 3, 3]), $rebuilt($php, new RustBackend(), false)); $same('PHP appendTake of a native column', $php->gather([5, 0, 3, 3]), $rebuilt($native, new PhpBackend(), true)); $same('Rows::concat PHP + native', $php->concat($php), $php->concat($native)); $same('Rows::concat native + PHP', $php->concat($php), $native->concat($php)); @@ -47,13 +47,13 @@ $same('Rows::gather over both', $php->gather([1, 4]), $native->gather([1, 4])); foreach ($schema->definitions() as $name => $definition) { $phpColumn = $php->column((string) $name); $nativeColumn = $native->column((string) $name); - $adopted = (new DefaultBackend())->adopt($definition, $phpColumn); - $empty = (new DefaultBackend())->adopt($definition, $phpColumn->slice(0, 0)); + $adopted = (new RustBackend())->adopt($definition, $phpColumn); + $empty = (new RustBackend())->adopt($definition, $phpColumn->slice(0, 0)); $back = (new PhpBackend())->adopt($definition, $nativeColumn); - if (!$adopted instanceof NativeColumn || $adopted->encode() !== $phpColumn->encode() || $empty->count() !== 0 - || $back instanceof NativeColumn || $back->encode() !== $phpColumn->encode() - || (new DefaultBackend())->adopt($definition, $nativeColumn) !== $nativeColumn) { + if (!$adopted instanceof RustColumn || $adopted->encode() !== $phpColumn->encode() || $empty->count() !== 0 + || $back instanceof RustColumn || $back->encode() !== $phpColumn->encode() + || (new RustBackend())->adopt($definition, $nativeColumn) !== $nativeColumn) { echo "adopt DIFF {$name}\n"; } } diff --git a/src/extension/flow-php-ext/tests/phpt/062_native_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/062_native_no_leaks.phpt index f8fa55f9aa..c38ef2f5f8 100644 --- a/src/extension/flow-php-ext/tests/phpt/062_native_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/062_native_no_leaks.phpt @@ -6,12 +6,12 @@ decode, value reads, take, encode and a refused appendMany leak neither PHP memo encodeFrame(); -$backend = new DefaultBackend(); +$backend = new RustBackend(); $cycle = static function () use ($schema, $frame, $backend): void { $rows = (new FrameDecoder())->decode($frame, $schema, $backend); diff --git a/src/extension/flow-php-ext/tests/phpt/063_csv_next_columns_parity.phpt b/src/extension/flow-php-ext/tests/phpt/063_csv_next_columns_parity.phpt index 077ced72ee..7cf76e412a 100644 --- a/src/extension/flow-php-ext/tests/phpt/063_csv_next_columns_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/063_csv_next_columns_parity.phpt @@ -1,13 +1,13 @@ --TEST-- -NativeCSVOpenSource::batches() yields the frames or refusals of PhpCSVOpenSource::batches(), through either backend +RustCSVOpenSource::batches() yields the frames or refusals of PhpCSVOpenSource::batches(), through either backend --SKIPIF-- --FILE-- o foreach ($open->batches($schema, 2, $backend) as $batch) { foreach ($batch->columns() as $column) { - if ($backend instanceof PhpBackend && $column instanceof NativeColumn) { - return ['a NativeColumn survived PhpBackend']; + if ($backend instanceof PhpBackend && $column instanceof RustColumn) { + return ['a RustColumn survived PhpBackend']; } } @@ -61,8 +61,8 @@ $identical = 0; foreach ($cases as [$raw, $schema]) { $php = $batches(new PhpCSVOpenSource($stream($raw), new CSVDecoder(), new CSVLineReader('"', ',', '\\')), $schema, new PhpBackend()); - foreach ([new DefaultBackend(), new PhpBackend()] as $backend) { - $native = $batches(new NativeCSVOpenSource($stream($raw), new RustCSVReaderNative(',', '"', '\\', true, true, true)), $schema, $backend); + foreach ([new RustBackend(), new PhpBackend()] as $backend) { + $native = $batches(new RustCSVOpenSource($stream($raw), ',', '"', '\\', true, true, true), $schema, $backend); if ($native === $php) { $identical++; diff --git a/src/extension/flow-php-ext/tests/phpt/064_csv_next_columns_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/064_csv_next_columns_no_leaks.phpt index 662e22b970..76f4c2e8be 100644 --- a/src/extension/flow-php-ext/tests/phpt/064_csv_next_columns_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/064_csv_next_columns_no_leaks.phpt @@ -1,13 +1,14 @@ --TEST-- -RustCSVReaderNative::nextColumns() leaks neither PHP memory nor native allocations +RustCSVOpenSource::batches() leaks neither PHP memory nor native allocations --SKIPIF-- --FILE-- feed($chunk); - $reader->nextColumns($schema, 2); - } - - $reader->finish(); - - while ($reader->nextColumns($schema, 2) !== null) { + foreach ((new RustCSVOpenSource(new MemorySourceStream($raw), ',', '"', '\\', true, true, true, 5))->batches($schema, 2, new RustBackend()) as $batch) { } - $refused = new RustCSVReaderNative(',', '"', '\\', true, true, true); - $refused->feed("name\nx\n"); - $refused->finish(); - try { - $refused->nextColumns($refusing, 2); + foreach ((new RustCSVOpenSource(new MemorySourceStream("name\nx\n"), ',', '"', '\\', true, true, true))->batches($refusing, 2, new RustBackend()) as $batch) { + } + throw new LogicException('a refused cell was accepted'); } catch (Flow\ETL\Exception\SchemaMismatchException) { } @@ -44,7 +34,7 @@ for ($i = 0; $i < 10; $i++) { } gc_collect_cycles(); $baseline = memory_get_usage(false); -$baselineRust = (new DefaultBackend())->allocatedBytes(); +$baselineRust = (new RustBackend())->allocatedBytes(); for ($i = 0; $i < 1000; $i++) { $cycle(); @@ -52,7 +42,7 @@ for ($i = 0; $i < 1000; $i++) { gc_collect_cycles(); var_dump(memory_get_usage(false) <= $baseline); -var_dump((new DefaultBackend())->allocatedBytes() === $baselineRust); +var_dump((new RustBackend())->allocatedBytes() === $baselineRust); ?> --EXPECT-- bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/065_type_plan_by_object.phpt b/src/extension/flow-php-ext/tests/phpt/065_type_plan_by_object.phpt index 36b307f03b..5873158540 100644 --- a/src/extension/flow-php-ext/tests/phpt/065_type_plan_by_object.phpt +++ b/src/extension/flow-php-ext/tests/phpt/065_type_plan_by_object.phpt @@ -6,10 +6,10 @@ a column's plan follows its Type object across the plan cache's eviction and a f finish()->physicals(); }; $csv = static function (object $definition, array $values): array { - $reader = new RustCSVReaderNative(',', '"', '', true, true, true); - $reader->feed("v\n" . implode("\n", $values) . "\n"); - $reader->finish(); + $source = new RustCSVOpenSource(new MemorySourceStream("v\n" . implode("\n", $values) . "\n"), ',', '"', '', true, true, true); - return $reader->nextColumns(schema($definition), count($values) + 1)->column('v')->physicals(); + return iterator_to_array($source->batches(schema($definition), count($values) + 1, new RustBackend()), false)[0]->column('v')->physicals(); }; foreach (['UTC', 'Europe/Warsaw', 'Pacific/Kiritimati'] as $zone) { $definition = datetime_schema('v', zone: $zone); $expected = $physicals(new PhpBackend(), $definition, $strings); - $appended = $physicals(new DefaultBackend(), $definition, $strings); + $appended = $physicals(new RustBackend(), $definition, $strings); $read = $csv($definition, $strings); $differ = static fn(array $actual): array => array_keys(array_filter( $expected, @@ -113,7 +112,7 @@ foreach (['UTC', 'Europe/Warsaw', 'Pacific/Kiritimati'] as $zone) { foreach ($nearMisses as $value) { $php = outcome(static fn(): array => $physicals(new PhpBackend(), $definition, [$value])); - $native = outcome(static fn(): array => $physicals(new DefaultBackend(), $definition, [$value])); + $native = outcome(static fn(): array => $physicals(new RustBackend(), $definition, [$value])); $php === $native ? $identical++ : print(json_encode($value) . "\n php: {$php}\n native: {$native}\n"); } diff --git a/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt b/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt index 08a05b0f46..cc727dcfd9 100644 --- a/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt +++ b/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt @@ -1,21 +1,21 @@ --TEST-- -DefaultBackend::adopt() refuses an untyped (mixed) column with the PHP wording +RustBackend::adopt() refuses an untyped (mixed) column with the PHP wording --SKIPIF-- --FILE-- (new DefaultBackend())->adopt(int_schema('a'), new ValueColumn([1, null]))), "\n"; +echo outcome(static fn() => (new RustBackend())->adopt(int_schema('a'), new ValueColumn([1, null]))), "\n"; $typed = (new PhpBackend())->constant(int_schema('a', nullable: true), 1, 2); -echo get_class((new DefaultBackend())->adopt(int_schema('a', nullable: true), $typed)), "\n"; +echo get_class((new RustBackend())->adopt(int_schema('a', nullable: true), $typed)), "\n"; ?> --EXPECT-- Flow\ETL\Exception\ColumnMismatchException: Row does not match its schema: column "a": mixed cannot be a batch column, an untyped function result exists only inside function evaluation -Flow\ETL\Column\NativeColumn +Flow\ETL\Column\RustColumn diff --git a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt index cddbf22da4..002a3aa27b 100644 --- a/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/068_parquet_read_parity.phpt @@ -1,5 +1,5 @@ --TEST-- -NativeParquetReader reads every lib Parquet fixture as PhpParquetEngine does, both refuse it, or it refuses naming the engine that reads it +RustParquetOpenSource reads every lib Parquet fixture as PhpParquetEngine does, both refuse it, or it refuses naming the engine that reads it --SKIPIF-- @@ -7,7 +7,7 @@ NativeParquetReader reads every lib Parquet fixture as PhpParquetEngine does, bo readFrom(path($file)), (new SchemaConverter())->toFlow((new Reader(engine: new PhpParquetEngine()))->read($file)->schema()), $batchSize, @@ -43,7 +43,7 @@ foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.p ); $rows = []; - while (($batch = $reader->next()) !== null) { + foreach ($reader as $batch) { array_push($rows, ...$batch->toArray()); } @@ -62,21 +62,21 @@ foreach ([...glob($fixtures . '/*.parquet'), ...glob($fixtures . '/EdgeCases/*.p } $emptylist = realpath($fixtures . '/EdgeCases/null_list.parquet'); -echo outcome(static fn() => native_parquet_reader( +echo outcome(static fn() => rust_parquet_batches( $filesystem->readFrom(path($emptylist)), schema(list_schema('emptylist', type_list(type_integer()))), 100, null, null, )), "\n"; -echo outcome(static fn() => native_parquet_reader( +echo outcome(static fn() => rust_parquet_batches( $filesystem->readFrom(path($fixtures . '/multiple_pages.parquet')), schema(str_schema('int64')), 100, null, null, )), "\n"; -echo outcome(static fn() => native_parquet_reader( +echo outcome(static fn() => rust_parquet_batches( $filesystem->readFrom(path($fixtures . '/multiple_pages.parquet')), schema(str_schema('missing')), 100, diff --git a/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt b/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt index af50ae5e8c..2aec1da3ea 100644 --- a/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt +++ b/src/extension/flow-php-ext/tests/phpt/069_parquet_offset_limit.phpt @@ -1,5 +1,5 @@ --TEST-- -NativeParquetReader reads offset/limit windows of an 8-row-group file, and refuses a batch size, offset or limit out of range +RustParquetOpenSource reads offset/limit windows of an 8-row-group file, and refuses a batch size, offset or limit out of range --SKIPIF-- @@ -7,21 +7,22 @@ NativeParquetReader reads offset/limit windows of an 8-row-group file, and refus writeTo(path('memory://groups.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), - 'SNAPPY', + Compressions::SNAPPY, OptionsConverter::toExtension(Options::default()->set(Option::ROW_GROUP_SIZE_BYTES, 1)), 1_000, )); @@ -38,10 +39,10 @@ echo 'row groups: ', implode(',', array_map( )), "\n"; foreach ([[0, 10], [5399, 3], [20000, 15000], [65000, 100], [65046, 1], [65536, 10], [65530, null]] as [$offset, $limit]) { - $reader = native_parquet_reader($filesystem->readFrom(path('memory://groups.parquet')), $schema, 1000, $offset, $limit); + $reader = rust_parquet_batches($filesystem->readFrom(path('memory://groups.parquet')), $schema, 1000, $offset, $limit); $ids = []; - while (($batch = $reader->next()) !== null) { + foreach ($reader as $batch) { array_push($ids, ...$batch->column('id')->values()); } @@ -50,7 +51,7 @@ foreach ([[0, 10], [5399, 3], [20000, 15000], [65000, 100], [65046, 1], [65536, } foreach ([[0, null, null], [-1, null, null], [10, -1, null], [10, null, -1]] as [$batchSize, $offset, $limit]) { - echo outcome(static fn() => native_parquet_reader($filesystem->readFrom(path('memory://groups.parquet')), $schema, $batchSize, $offset, $limit)), "\n"; + echo outcome(static fn() => rust_parquet_batches($filesystem->readFrom(path('memory://groups.parquet')), $schema, $batchSize, $offset, $limit)), "\n"; } ?> --EXPECT-- diff --git a/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt b/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt index cd5dec1a68..d8e2452276 100644 --- a/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt +++ b/src/extension/flow-php-ext/tests/phpt/070_parquet_write_roundtrip.phpt @@ -1,5 +1,5 @@ --TEST-- -NativeParquetWriter writes native and PHP columns that PhpParquetEngine reads back equal, and refuses a string that is not valid UTF-8 +RustParquetOpenSink writes native and PHP columns that PhpParquetEngine reads back equal, and refuses a string that is not valid UTF-8 --SKIPIF-- @@ -7,15 +7,16 @@ NativeParquetWriter writes native and PHP columns that PhpParquetEngine reads ba backend(new PhpBackend())->build()); $write = static function (Schema $schema, array $batches): void { - $writer = new NativeParquetWriter(new RowsWriter( + $writer = new RustParquetOpenSink(new RustParquetFileWriter( memory_filesystem()->writeTo(path('memory://unused.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), - 'ZSTD', + Compressions::ZSTD, OptionsConverter::toExtension(Options::default()), 1_000, )); @@ -68,10 +69,10 @@ $write = static function (Schema $schema, array $batches): void { }; $filesystem = memory_filesystem(); -$writer = new NativeParquetWriter(new RowsWriter( +$writer = new RustParquetOpenSink(new RustParquetFileWriter( $filesystem->writeTo(path('memory://roundtrip.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), - 'ZSTD', + Compressions::ZSTD, OptionsConverter::toExtension(Options::default()), 1_000, )); @@ -88,10 +89,10 @@ foreach (from_parquet(path('memory://roundtrip.parquet'), filesystem: $filesyste var_dump(comparable($read) === comparable([...php_rows($schema, $values)->toArray(), ...php_rows($schema, $values)->toArray()])); $partial = memory_filesystem(); -$partialWriter = new NativeParquetWriter(new RowsWriter( +$partialWriter = new RustParquetOpenSink(new RustParquetFileWriter( $partial->writeTo(path('memory://partial.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet(schema(int_schema('id'), str_schema('name', nullable: true)))), - 'SNAPPY', + Compressions::SNAPPY, OptionsConverter::toExtension(Options::default()), 1_000, )); diff --git a/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt index ff06b34a4b..fc8b479d01 100644 --- a/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/071_parquet_no_leaks.phpt @@ -1,5 +1,5 @@ --TEST-- -NativeParquetReader and NativeParquetWriter leak neither PHP memory nor native allocations, refusals included +RustParquetOpenSource and RustParquetOpenSink leak neither PHP memory nor native allocations, refusals included --SKIPIF-- @@ -7,12 +7,13 @@ NativeParquetReader and NativeParquetWriter leak neither PHP memory nor native a 1, 'name' => "\xff", 'tags' => []]]; $cycle = static function () use ($schema, $values, $extension, $options, $mismatched, $invalid): void { $filesystem = memory_filesystem(); - $writer = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://leaks.parquet')), $extension, 'SNAPPY', $options, 1_000)); + $writer = new RustParquetOpenSink(new RustParquetFileWriter($filesystem->writeTo(path('memory://leaks.parquet')), $extension, Compressions::SNAPPY, $options, 1_000)); $writer->write(native_rows($schema, $values)); $writer->write(php_rows($schema, $values)); $writer->close(); - $reader = native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, 10, 150); + $reader = rust_parquet_batches($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, 10, 150); - while ($reader->next() !== null) { + foreach ($reader as $_) { } - $refused = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://refused.parquet')), $extension, 'SNAPPY', $options, 1_000)); + $refused = new RustParquetOpenSink(new RustParquetFileWriter($filesystem->writeTo(path('memory://refused.parquet')), $extension, Compressions::SNAPPY, $options, 1_000)); try { $refused->write(native_rows($schema, $invalid)); @@ -47,7 +48,7 @@ $cycle = static function () use ($schema, $values, $extension, $options, $mismat } try { - native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $mismatched, 30, null, null); + rust_parquet_batches($filesystem->readFrom(path('memory://leaks.parquet')), $mismatched, 30, null, null); throw new LogicException('a mismatched schema was accepted'); } catch (Flow\ETL\Exception\InvalidArgumentException) { } @@ -58,7 +59,7 @@ for ($i = 0; $i < 10; $i++) { } gc_collect_cycles(); $baseline = memory_get_usage(false); -$baselineRust = (new DefaultBackend())->allocatedBytes(); +$baselineRust = (new RustBackend())->allocatedBytes(); for ($i = 0; $i < 300; $i++) { $cycle(); @@ -66,7 +67,7 @@ for ($i = 0; $i < 300; $i++) { gc_collect_cycles(); var_dump(memory_get_usage(false) <= $baseline); -var_dump((new DefaultBackend())->allocatedBytes() === $baselineRust); +var_dump((new RustBackend())->allocatedBytes() === $baselineRust); ?> --EXPECT-- bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt b/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt index 21e3050a1f..6847bfde4c 100644 --- a/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt +++ b/src/extension/flow-php-ext/tests/phpt/072_parquet_allocations_counted.phpt @@ -1,5 +1,5 @@ --TEST-- -Batches NativeParquetReader holds are counted by DefaultBackend::allocatedBytes(): at least their columns' buffer bytes, and nothing once they are released +Batches RustParquetOpenSource holds are counted by RustBackend::allocatedBytes(): at least their columns' buffer bytes, and nothing once they are released --SKIPIF-- @@ -7,22 +7,23 @@ Batches NativeParquetReader holds are counted by DefaultBackend::allocatedBytes( writeTo(path('memory://held.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), - 'SNAPPY', + Compressions::SNAPPY, OptionsConverter::toExtension(Options::default()), 1_000, )); @@ -34,15 +35,14 @@ foreach (array_chunk(range(0, 65_535), 8_192) as $ids) { $writer->close(); gc_collect_cycles(); -$before = (new DefaultBackend())->allocatedBytes(); -$reader = native_parquet_reader($filesystem->readFrom(path('memory://held.parquet')), $schema, 1_000, null, null); +$before = (new RustBackend())->allocatedBytes(); +$reader = rust_parquet_batches($filesystem->readFrom(path('memory://held.parquet')), $schema, 1_000, null, null); $held = []; -while (($batch = $reader->next()) !== null) { +foreach ($reader as $batch) { $held[] = $batch; } -$reader->close(); unset($reader); gc_collect_cycles(); @@ -55,12 +55,12 @@ foreach ($held as $batch) { } var_dump(array_sum(array_map(count(...), $held))); -var_dump((new DefaultBackend())->allocatedBytes() - $before >= $bufferBytes); +var_dump((new RustBackend())->allocatedBytes() - $before >= $bufferBytes); unset($held, $batch, $column); gc_collect_cycles(); -var_dump((new DefaultBackend())->allocatedBytes() === $before); +var_dump((new RustBackend())->allocatedBytes() === $before); ?> --EXPECT-- int(65536) diff --git a/src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt b/src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt index 23f585f248..2114b59588 100644 --- a/src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt @@ -8,9 +8,9 @@ require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\CSV\PhpCSVEncoder; use Flow\ETL\Adapter\CSV\CSVWriteOptions; -use Flow\ETL\Adapter\CSV\NativeCSVWriter; +use Flow\ETL\Adapter\CSV\RustCSVEncoder; use Flow\ETL\Adapter\JSON\PhpJSONEncoder; -use Flow\ETL\Adapter\JSON\NativeJsonWriter; +use Flow\ETL\Adapter\JSON\RustJSONEncoder; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\schema; @@ -26,7 +26,7 @@ while (count($floats) < 100_020) { $finite = array_values(array_filter($floats, is_finite(...))); $schema = schema(float_schema('f')); $options = new CSVWriteOptions(newLineSeparator: "\n"); -$csv = new NativeCSVWriter(',', '"', '\\', "\n", DATE_ATOM, 'Y-m-d'); +$csv = new RustCSVEncoder(',', '"', '\\', "\n", DATE_ATOM, 'Y-m-d', new PhpCSVEncoder($options)); $rows = static fn(callable $build, array $values): array => array_map( static fn(array $chunk): Flow\ETL\Rows => $build($schema, array_map(static fn(float $f): array => ['f' => $f], $chunk)), array_chunk($values, 10_000), @@ -37,20 +37,20 @@ foreach (['-1', '17'] as $precision) { ini_set('precision', $precision === '17' ? '5' : '14'); $php = implode('', array_map((new PhpCSVEncoder($options))->encode(...), $rows(php_rows(...), $floats))); - $native = implode('', array_map(static fn(Flow\ETL\Rows $batch): string => $csv->encode($batch, []), $rows(native_rows(...), $floats))); + $native = implode('', array_map(static fn(Flow\ETL\Rows $batch): string => $csv->encode($batch), $rows(native_rows(...), $floats))); printf("serialize_precision %s: csv %s, %d values\n", $precision, $php === $native ? 'identical' : 'DIFFERENT', substr_count($native, "\n")); foreach ([JSON_THROW_ON_ERROR, JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION] as $flags) { - $json = new NativeJsonWriter($flags, DATE_ATOM, 'Y-m-d'); + $json = new RustJSONEncoder($flags, DATE_ATOM, 'Y-m-d', new PhpJSONEncoder($flags)); $php = implode("\n", array_map(static fn(Flow\ETL\Rows $batch): string => (new PhpJSONEncoder($flags))->encode($batch, "\n"), $rows(php_rows(...), $finite))); - $native = implode("\n", array_map(static fn(Flow\ETL\Rows $batch): string => $json->encode($batch, [], "\n"), $rows(native_rows(...), $finite))); + $native = implode("\n", array_map(static fn(Flow\ETL\Rows $batch): string => $json->encode($batch, "\n"), $rows(native_rows(...), $finite))); printf("serialize_precision %s: json flags %d %s, %d values\n", $precision, $flags, $php === $native ? 'identical' : 'DIFFERENT', substr_count($native, "\n") + 1); } foreach ([NAN, INF, -INF] as $float) { $values = [['f' => 1.5], ['f' => $float]]; $php = written(static fn() => (new PhpJSONEncoder())->encode(php_rows($schema, $values), "\n")); - $native = written(static fn() => (new NativeJsonWriter(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d'))->encode(native_rows($schema, $values), [], "\n")); + $native = written(static fn() => (new RustJSONEncoder(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d', new PhpJSONEncoder()))->encode(native_rows($schema, $values), "\n")); printf("json %s: %s\n", var_export($float, true), $php === $native ? $php : 'DIFFERENT'); } diff --git a/src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt b/src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt index 94a34c3947..8cc6723ae4 100644 --- a/src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt @@ -7,7 +7,7 @@ The native JSON writer escapes a string as json_encode() does: random valid and require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\JSON\PhpJSONEncoder; -use Flow\ETL\Adapter\JSON\NativeJsonWriter; +use Flow\ETL\Adapter\JSON\RustJSONEncoder; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -68,7 +68,7 @@ for ($combination = 0; $combination < 16; $combination++) { | ($combination & 4 ? JSON_UNESCAPED_UNICODE : 0) | ($combination & 8 ? JSON_PRESERVE_ZERO_FRACTION : 0); $encoder = new PhpJSONEncoder($flags); - $writer = new NativeJsonWriter($flags, DATE_ATOM, 'Y-m-d'); + $writer = new RustJSONEncoder($flags, DATE_ATOM, 'Y-m-d', $encoder); $different = 0; $refused = 0; @@ -76,7 +76,7 @@ for ($combination = 0; $combination < 16; $combination++) { $expected = $encoded(static fn(): string => $encoder->encode($php[$i], "\n")); $refused += (int) refused($expected); - if ($expected !== $encoded(static fn(): string => $writer->encode($native[$i], [], "\n")) && ++$different <= 3) { + if ($expected !== $encoded(static fn(): string => $writer->encode($native[$i], "\n")) && ++$different <= 3) { echo bin2hex($text), ': ', $expected, "\n"; } } diff --git a/src/extension/flow-php-ext/tests/phpt/079_text_date_format_parity.phpt b/src/extension/flow-php-ext/tests/phpt/079_text_date_format_parity.phpt index fc308bd6ce..49f4718356 100644 --- a/src/extension/flow-php-ext/tests/phpt/079_text_date_format_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/079_text_date_format_parity.phpt @@ -6,7 +6,9 @@ The native writers format a datetime and a date as DateTimeInterface::format() d unrendered($schema) !== []) { - throw new LogicException("the format {$format} is not rendered natively"); - } - + $recorder = new RecordingPhpCSVEncoder(new PhpCSVEncoder(new CSVWriteOptions("\x01", "\x02", '', "\n", $format, 'Y-m-d'))); + $writer = new RustCSVEncoder("\x01", "\x02", '', "\n", $format, 'Y-m-d', $recorder); $expected = ''; foreach ($values as $value) { @@ -74,7 +72,11 @@ foreach (['UTC', '+02:30', 'Europe/Warsaw', 'America/New_York', 'Australia/Lord_ $compared++; // a field holding a space is enclosed: the enclosure is dropped, no format writes that byte - $written = str_replace("\x02", '', $writer->encode($rows, [])); + $written = str_replace("\x02", '', $writer->encode($rows)); + + if ($recorder->columns !== []) { + throw new LogicException("the format {$format} is not rendered natively"); + } if ($written !== $expected && ++$different <= 5) { echo "{$zone} {$format}\n php: ", substr(json_encode($expected), 0, 300), "\n native: ", substr(json_encode($written), 0, 300), "\n"; @@ -90,14 +92,14 @@ $days = [0, -1, 1, 20_455, -25_567, -719_528, -719_893, 2_932_896, 35_804_721]; $different = 0; foreach ($formats as $format) { - $writer = new NativeCSVWriter("\x01", "\x02", '', "\n", DATE_ATOM, $format); + $writer = new RustCSVEncoder("\x01", "\x02", '', "\n", DATE_ATOM, $format, new PhpCSVEncoder(new CSVWriteOptions("\x01", "\x02", '', "\n", DATE_ATOM, $format))); $expected = ''; foreach ($days as $day) { $expected .= (new DateTimeImmutable('@' . ($day * 86_400)))->setTimezone(new DateTimeZone('UTC'))->format($format) . "\n"; } - $written = str_replace("\x02", '', $writer->encode(native_rows($schema, array_map(static fn(int $day): array => ['on' => new DateTimeImmutable('@' . ($day * 86_400))], $days)), [])); + $written = str_replace("\x02", '', $writer->encode(native_rows($schema, array_map(static fn(int $day): array => ['on' => new DateTimeImmutable('@' . ($day * 86_400))], $days)))); if ($written !== $expected && ++$different <= 5) { echo "date {$format}\n php: ", substr(json_encode($expected), 0, 300), "\n native: ", substr(json_encode($written), 0, 300), "\n"; @@ -107,7 +109,10 @@ foreach ($formats as $format) { echo "date: {$different} of " . count($formats) . " differ\n"; foreach (['D, d M Y', 'Y-m-d I', 'N', 'Y\\'] as $format) { - printf("%s: %s\n", $format, json_encode((new NativeCSVWriter(',', '"', '\\', "\n", $format, $format))->unrendered(schema(datetime_schema('at'), date_schema('on'))))); + $recorder = new RecordingPhpCSVEncoder(new PhpCSVEncoder(new CSVWriteOptions(',', '"', '\\', "\n", $format, $format))); + $rows = native_rows(schema(datetime_schema('at'), date_schema('on')), [['at' => new DateTimeImmutable('2024-01-02 03:04:05'), 'on' => new DateTimeImmutable('2024-01-02')]]); + (new RustCSVEncoder(',', '"', '\\', "\n", $format, $format, $recorder))->encode($rows); + printf("%s: %s\n", $format, json_encode(recorded_names($recorder->columns, $rows))); } ?> --EXPECT-- diff --git a/src/extension/flow-php-ext/tests/phpt/080_csv_write_parity.phpt b/src/extension/flow-php-ext/tests/phpt/080_csv_write_parity.phpt index f0d123e937..75eaf5dc48 100644 --- a/src/extension/flow-php-ext/tests/phpt/080_csv_write_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/080_csv_write_parity.phpt @@ -1,5 +1,5 @@ --TEST-- -CSVOpenSink writes the same bytes through NativeCSVEncoder and PhpCSVEncoder: seeded random batches over every kind, nesting <= 3, random options +CSVOpenSink writes the same bytes through RustCSVEncoder and PhpCSVEncoder: seeded random batches over every kind, nesting <= 3, random options --SKIPIF-- --FILE-- @@ -8,8 +8,7 @@ require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\CSV\CSVOpenSink; use Flow\ETL\Adapter\CSV\CSVWriteOptions; -use Flow\ETL\Adapter\CSV\NativeCSVEncoder; -use Flow\ETL\Adapter\CSV\NativeCSVWriter; +use Flow\ETL\Adapter\CSV\RustCSVEncoder; use Flow\ETL\Adapter\CSV\PhpCSVEncoder; use Flow\Filesystem\DestinationStream; @@ -42,8 +41,8 @@ for ($i = 0; $i < 2_000; $i++) { } $header = mt_rand(0, 1) === 1; - $writer = new NativeCSVWriter($options->separator, $options->enclosure, $options->escape, $options->newLineSeparator, $options->dateTimeFormat, $options->dateFormat); - $unrendered += count($writer->unrendered($schema)); + $recorder = new RecordingPhpCSVEncoder(new PhpCSVEncoder($options)); + $writer = new RustCSVEncoder($options->separator, $options->enclosure, $options->escape, $options->newLineSeparator, $options->dateTimeFormat, $options->dateFormat, $recorder); // a second batch proves the header is written once and the encoders hold no state across batches $half = intdiv(count($rows), 2); @@ -52,14 +51,15 @@ for ($i = 0; $i < 2_000; $i++) { $sink->write(php_rows($schema, array_slice($rows, 0, $half))); $sink->write(php_rows($schema, array_slice($rows, $half))); }); - $native = written(static function (DestinationStream $stream) use ($schema, $rows, $options, $header, $half, $writer): void { - $sink = new CSVOpenSink($stream, new NativeCSVEncoder($writer, new PhpCSVEncoder($options)), $header); + $native = written(static function (DestinationStream $stream) use ($schema, $rows, $header, $half, $writer): void { + $sink = new CSVOpenSink($stream, $writer, $header); $sink->write(native_rows($schema, array_slice($rows, 0, $half))); // a PHP column inside the batch is adopted $sink->write(php_rows($schema, array_slice($rows, $half))); }); $refused += (int) refused($php); + $unrendered += count($recorder->columns); if ($php === $native) { $identical++; diff --git a/src/extension/flow-php-ext/tests/phpt/081_json_write_parity.phpt b/src/extension/flow-php-ext/tests/phpt/081_json_write_parity.phpt index abdb84aace..e6f102a023 100644 --- a/src/extension/flow-php-ext/tests/phpt/081_json_write_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/081_json_write_parity.phpt @@ -1,5 +1,5 @@ --TEST-- -JsonOpenSink writes the same bytes through NativeJSONEncoder and PhpJSONEncoder: seeded random batches over every kind, nesting <= 3, random flags and framings +JsonOpenSink writes the same bytes through RustJSONEncoder and PhpJSONEncoder: seeded random batches over every kind, nesting <= 3, random flags and framings --SKIPIF-- --FILE-- @@ -8,8 +8,7 @@ require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\JSON\JsonFraming; use Flow\ETL\Adapter\JSON\JsonOpenSink; -use Flow\ETL\Adapter\JSON\NativeJSONEncoder; -use Flow\ETL\Adapter\JSON\NativeJsonWriter; +use Flow\ETL\Adapter\JSON\RustJSONEncoder; use Flow\ETL\Adapter\JSON\PhpJSONEncoder; use Flow\Filesystem\DestinationStream; @@ -31,8 +30,8 @@ for ($i = 0; $i < 2_000; $i++) { $framing = JsonFraming::cases()[mt_rand(0, 2)]; $dateTimeFormat = $dateTimeFormats[mt_rand(0, count($dateTimeFormats) - 1)]; $dateFormat = $dateFormats[mt_rand(0, count($dateFormats) - 1)]; - $writer = new NativeJsonWriter($flags, $dateTimeFormat, $dateFormat); - $unrendered += count($writer->unrendered($schema)); + $recorder = new RecordingPhpJSONEncoder(new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat)); + $writer = new RustJSONEncoder($flags, $dateTimeFormat, $dateFormat, $recorder); $half = intdiv(count($rows), 2); $php = written(static function (DestinationStream $stream) use ($schema, $rows, $flags, $dateTimeFormat, $dateFormat, $framing, $half): void { @@ -42,7 +41,7 @@ for ($i = 0; $i < 2_000; $i++) { $sink->close(); }); $native = written(static function (DestinationStream $stream) use ($schema, $rows, $flags, $dateTimeFormat, $dateFormat, $framing, $half, $writer): void { - $sink = new JsonOpenSink($stream, new NativeJSONEncoder($writer, new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat)), $framing); + $sink = new JsonOpenSink($stream, $writer, $framing); $sink->write(native_rows($schema, array_slice($rows, 0, $half))); // a PHP column inside the batch is adopted $sink->write(php_rows($schema, array_slice($rows, $half))); @@ -50,6 +49,7 @@ for ($i = 0; $i < 2_000; $i++) { }); $refused += (int) refused($php); + $unrendered += count($recorder->columns); if ($php === $native) { $identical++; diff --git a/src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt index d39fc69b59..6b015e3084 100644 --- a/src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt @@ -6,9 +6,12 @@ The native CSV and JSON writers leak neither PHP memory nor native allocations o definitions(), static fn($definition): bool => $definition->entry()->name() !== 'string')); $refusedSchema = schema(str_schema('s'), float_schema('f'), list_schema('l', type_list(type_float()))); $refused = native_rows($refusedSchema, [['s' => "\xff", 'f' => NAN, 'l' => [INF]]]); -$csv = new NativeCSVWriter(',', '"', '\\', "\n", 'Y-m-d\TH:i:s.uP T', 'Y-m-d'); -$json = new NativeJsonWriter(JSON_THROW_ON_ERROR, 'Y-m-d\TH:i:s.uP T', 'Y-m-d'); -$backend = new DefaultBackend(); -$count = $native->count(); -$cells = static function (array $names, string $cell) use ($count): array { - return array_fill_keys($names, array_fill(0, $count, $cell)); +$dateTimeFormat = 'Y-m-d\TH:i:s.uP T'; +$csv = new RustCSVEncoder(',', '"', '\\', "\n", $dateTimeFormat, 'Y-m-d', new PhpCSVEncoder(new CSVWriteOptions(newLineSeparator: "\n", dateTimeFormat: $dateTimeFormat))); +$json = new RustJSONEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', new PhpJSONEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat)); +// stand-ins for the held encoder: a cell list of the wrong length, and an encoder that throws +$short = new class { + public function cells(): array + { + return ['too', 'few']; + } + + public function fragments(): array + { + return ['"too"', '"few"']; + } +}; +$throwing = new class { + public function cells(): array + { + throw new Flow\ETL\Exception\RuntimeException('cells refused'); + } + + public function fragments(): array + { + throw new Flow\ETL\Exception\RuntimeException('fragments refused'); + } }; +$backend = new RustBackend(); -$cycle = static function () use ($schema, $jsonSchema, $native, $php, $refused, $csv, $json, $cells): void { - $csv->encode($native, $cells($csv->unrendered($schema), 'cell')); +$cycle = static function () use ($schema, $jsonSchema, $native, $php, $refused, $csv, $json, $short, $throwing, $dateTimeFormat): void { + $csv->encode($native); // PHP columns are adopted for the encode and freed after it - $csv->encode($php, $cells($csv->unrendered($schema), 'cell')); - $json->encode($native->project($jsonSchema), $cells($json->unrendered($jsonSchema), '"fragment"'), "\n"); - $json->encode($php->project($jsonSchema), $cells($json->unrendered($jsonSchema), '"fragment"'), ','); + $csv->encode($php); + $json->encode($native->project($jsonSchema), "\n"); + $json->encode($php->project($jsonSchema), ','); foreach ([ - static fn() => $csv->encode($refused, []), - static fn() => $json->encode($refused, [], "\n"), - static fn() => $csv->encode($native, []), - static fn() => $json->encode($native, $cells($json->unrendered($schema), '"fragment"'), "\n"), - static fn() => $json->encode($native->project($jsonSchema), ['json' => ['too', 'few']], "\n"), + static fn() => $csv->encode($refused), + static fn() => $json->encode($refused, "\n"), + static fn() => $json->encode($native, "\n"), + static fn() => (new RustCSVEncoder(',', '"', '\\', "\n", $dateTimeFormat, 'Y-m-d', $short))->encode($native), + static fn() => (new RustJSONEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', $short))->encode($native->project($jsonSchema), "\n"), + static fn() => (new RustCSVEncoder(',', '"', '\\', "\n", $dateTimeFormat, 'Y-m-d', $throwing))->encode($native), + static fn() => (new RustJSONEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', $throwing))->encode($native->project($jsonSchema), "\n"), ] as $refusal) { try { $refusal(); diff --git a/src/extension/flow-php-ext/tests/phpt/084_native_nested_cast_parity.phpt b/src/extension/flow-php-ext/tests/phpt/084_native_nested_cast_parity.phpt index 073e50eaab..c9057be98c 100644 --- a/src/extension/flow-php-ext/tests/phpt/084_native_nested_cast_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/084_native_nested_cast_parity.phpt @@ -1,12 +1,12 @@ --TEST-- -NativeColumnBuilder casts random nested values, raw and refused forms, as the PHP builder does through append() and appendMany() +RustColumnBuilder casts random nested values, raw and refused forms, as the PHP builder does through append() and appendMany() --SKIPIF-- --FILE-- $column(new PhpBackend())()->{$read}()); - $native = outcome(static fn(): mixed => $column(new DefaultBackend())()->{$read}()); + $native = outcome(static fn(): mixed => $column(new RustBackend())()->{$read}()); if ($php !== $native) { echo ($many ? 'appendMany ' : 'append ') . "{$read} {$type->toString()} " . var_export($values, true) . "\n php: {$php}\n native: {$native}\n"; diff --git a/src/extension/flow-php-ext/tests/phpt/085_native_nested_cast_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/085_native_nested_cast_no_leaks.phpt index d97882966a..c0a3eb227c 100644 --- a/src/extension/flow-php-ext/tests/phpt/085_native_nested_cast_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/085_native_nested_cast_no_leaks.phpt @@ -6,12 +6,12 @@ nested values cast natively, handed to the PHP lane half-appended, and refused l structure_element('id', type_integer()), 'tags' => structure_element('tags', type_list(type_string())), diff --git a/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt index c6d001b27c..eff6c82344 100644 --- a/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt @@ -1,5 +1,5 @@ --TEST-- -NativeJsonReader reads random valid JSON, whole or a byte at a time, into the frames or refusals of PhpJsonOpenSource, through either backend +RustJsonOpenSource reads random valid JSON, whole or a byte at a time, into the frames or refusals of PhpJsonOpenSource, through either backend --SKIPIF-- --FILE-- @@ -7,8 +7,8 @@ NativeJsonReader reads random valid JSON, whole or a byte at a time, into the fr require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\JSON\JSONMachine\{JsonFileReader, JsonFormat}; -use Flow\ETL\Adapter\JSON\{NativeJsonOpenSource, NativeJsonReader, PhpJsonOpenSource}; -use Flow\ETL\Column\{DefaultBackend, NativeColumn, PhpBackend}; +use Flow\ETL\Adapter\JSON\{PhpJsonOpenSource, RustJsonOpenSource}; +use Flow\ETL\Column\{RustBackend, RustColumn, PhpBackend}; use Flow\ETL\Extractor\SourceFile; use Flow\ETL\{Rows, Schema}; use Flow\Filesystem\Stream\StringSourceStream; @@ -115,8 +115,8 @@ $frames = static function (iterable $batches, object $backend): array { foreach ($batches as $batch) { foreach ($batch->columns() as $column) { - if ($backend instanceof PhpBackend && $column instanceof NativeColumn) { - return ['a NativeColumn survived PhpBackend']; + if ($backend instanceof PhpBackend && $column instanceof RustColumn) { + return ['a RustColumn survived PhpBackend']; } } @@ -125,33 +125,14 @@ $frames = static function (iterable $batches, object $backend): array { return $frames; }; -// NativeJsonOpenSource::batches() over chunks of $chunk bytes -$bytes = static function (string $raw, bool $lines, Schema $schema, object $backend, int $chunk): Generator { - $reader = new NativeJsonReader($lines, 'memory://phpt.json'); - $adopted = static function (Rows $batch) use ($schema, $backend): Rows { - $columns = []; - - foreach ($schema->definitions() as $name => $definition) { - $columns[$name] = $backend->adopt($definition, $batch->columns()[$name]); - } - - return Rows::fromColumns($schema, $columns, $batch->count()); - }; - - foreach (str_split($raw, $chunk) as $piece) { - $reader->feed($piece); - - while (($batch = $reader->nextColumns($schema, 2)) !== null) { - yield $adopted($batch); - } - } - - $reader->finish(); - - while (($batch = $reader->nextColumns($schema, 2)) !== null) { - yield $adopted($batch); - } -}; +// RustJsonOpenSource::batches() over reads of $chunk bytes +$bytes = static fn(string $raw, bool $lines, Schema $schema, object $backend, int $chunk): Iterator => (new RustJsonOpenSource( + chunked_source_stream($raw, $chunk), + $lines, + 'memory://phpt.json', + '', + 0, +))->batches($schema, 2, $backend); mt_srand(10); $pool = json_read_pool(); @@ -192,9 +173,9 @@ for ($t = 0; $t < 400; $t++) { $reader = new JsonFileReader($filesystem, $lines ? JsonFormat::Lines : JsonFormat::Document, null, false, [$source]); $php = outcome(static fn(): array => $frames((new PhpJsonOpenSource($reader, $source))->batches($schema, 2, new PhpBackend()), new PhpBackend())); - foreach ([new DefaultBackend(), new PhpBackend()] as $backend) { + foreach ([new RustBackend(), new PhpBackend()] as $backend) { $natives = [ - 'whole' => outcome(static fn(): array => $frames((new NativeJsonOpenSource(new StringSourceStream(path('memory://phpt.json'), $raw), new NativeJsonReader($lines, 'memory://phpt.json')))->batches($schema, 2, $backend), $backend)), + 'whole' => outcome(static fn(): array => $frames((new RustJsonOpenSource(new StringSourceStream(path('memory://phpt.json'), $raw), $lines, 'memory://phpt.json', '', 0))->batches($schema, 2, $backend), $backend)), 'by byte' => outcome(static fn(): array => $frames($bytes($raw, $lines, $schema, $backend, 1), $backend)), ]; diff --git a/src/extension/flow-php-ext/tests/phpt/087_json_read_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/087_json_read_no_leaks.phpt index 3c22bd3ef7..9869977cb1 100644 --- a/src/extension/flow-php-ext/tests/phpt/087_json_read_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/087_json_read_no_leaks.phpt @@ -1,13 +1,13 @@ --TEST-- -NativeJsonReader reads, cast refusals and malformed refusals leak neither PHP memory nor native allocations +RustJsonOpenSource reads, cast refusals and malformed refusals leak neither PHP memory nor native allocations --SKIPIF-- --FILE-- batches($schema, 2, $backend) as $batch) { diff --git a/src/extension/flow-php-ext/tests/phpt/088_json_read_streaming.phpt b/src/extension/flow-php-ext/tests/phpt/088_json_read_streaming.phpt index 4711be532e..947e298dd6 100644 --- a/src/extension/flow-php-ext/tests/phpt/088_json_read_streaming.phpt +++ b/src/extension/flow-php-ext/tests/phpt/088_json_read_streaming.phpt @@ -1,20 +1,20 @@ --TEST-- -NativeJsonOpenSource reads a JSON array and JSON lines in memory independent of the record count: one chunk, the largest record and one batch +RustJsonOpenSource reads a JSON array and JSON lines in memory independent of the record count: one chunk, the largest record and one batch --SKIPIF-- --FILE-- allocatedBytes(); $held = 0; $rows = 0; - $open = new NativeJsonOpenSource((new NativeLocalFilesystem())->readFrom(path($file)), new NativeJsonReader($lines, $file)); + $open = new RustJsonOpenSource((new NativeLocalFilesystem())->readFrom(path($file)), $lines, $file, '', 0); foreach ($open->batches($schema, 1000, $backend) as $batch) { $rows += $batch->count(); @@ -71,8 +71,8 @@ foreach (['array' => false, 'lines' => true] as $label => $lines) { [$rows20, $php20, $rust20] = $measured[20_000]; [$rows200, $php200, $rust200] = $measured[200_000]; - echo "{$label}: {$rows20} and {$rows200} rows, PHP peak ", $php200 <= $php20 + NativeJsonOpenSource::CHUNK ? 'bounded' : "{$php20} -> {$php200}", - ', native held ', $rust200 <= $rust20 + NativeJsonOpenSource::CHUNK ? 'bounded' : "{$rust20} -> {$rust200}", "\n"; + echo "{$label}: {$rows20} and {$rows200} rows, PHP peak ", $php200 <= $php20 + (1 << 15) ? 'bounded' : "{$php20} -> {$php200}", + ', native held ', $rust200 <= $rust20 + (1 << 15) ? 'bounded' : "{$rust20} -> {$rust200}", "\n"; } ?> --EXPECT-- diff --git a/src/extension/flow-php-ext/tests/phpt/089_parquet_arrow_c_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/089_parquet_arrow_c_no_leaks.phpt index 8e0123c2e7..8bc9d2c594 100644 --- a/src/extension/flow-php-ext/tests/phpt/089_parquet_arrow_c_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/089_parquet_arrow_c_no_leaks.phpt @@ -7,11 +7,13 @@ Batches crossing to and from arrow-ext through the Arrow C Data Interface leak n writeTo(path('memory://leaks.parquet')), $extension, 'SNAPPY', $options, 30)); + $writer = new RustParquetOpenSink(new RustParquetFileWriter($filesystem->writeTo(path('memory://leaks.parquet')), $extension, Compressions::SNAPPY, $options, 30)); $writer->write($rows); $writer->write($rows); $writer->close(); - $reader = native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, null, null); + $reader = rust_parquet_batches($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, null, null); - while ($reader->next() !== null) { + foreach ($reader as $_) { } - $abandoned = native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, null, null); - $abandoned->next(); + $abandoned = rust_parquet_batches($filesystem->readFrom(path('memory://leaks.parquet')), $schema, 30, null, null); + $abandoned->rewind(); unset($abandoned); - $batches = new BatchReader(new ParquetFile($filesystem->readFrom(path('memory://leaks.parquet'))), ['id', 'name', 'tags'], 30, null, null); + $batches = new RustBatchReader(new RustParquetFileReader($filesystem->readFrom(path('memory://leaks.parquet'))), ['id', 'name', 'tags'], 30, null, null); $batches->next(); $twice = $batches->next(); - $copy = new RowsWriter($filesystem->writeTo(path('memory://copy.parquet')), $extension, 'SNAPPY', $options, 30); - $copy->writeBatch($twice); + $copy = new RustParquetFileWriter($filesystem->writeTo(path('memory://copy.parquet')), $extension, Compressions::SNAPPY, $options, 30); + $copy->writeArrowBatch($twice); try { - $copy->writeBatch($twice); + $copy->writeArrowBatch($twice); throw new LogicException('a batch was imported twice'); } catch (Flow\Parquet\Exception\InvalidArgumentException) { } @@ -57,12 +59,12 @@ $cycle = static function () use ($schema, $extension, $options, $rows, $invalid, $copy->close(); try { - native_parquet_reader($filesystem->readFrom(path('memory://leaks.parquet')), $mismatched, 30, null, null); + rust_parquet_batches($filesystem->readFrom(path('memory://leaks.parquet')), $mismatched, 30, null, null); throw new LogicException('a string schema read an int column'); } catch (Flow\ETL\Exception\InvalidArgumentException) { } - $refused = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://refused.parquet')), $extension, 'SNAPPY', $options, 30)); + $refused = new RustParquetOpenSink(new RustParquetFileWriter($filesystem->writeTo(path('memory://refused.parquet')), $extension, Compressions::SNAPPY, $options, 30)); try { $refused->write($invalid); @@ -70,7 +72,7 @@ $cycle = static function () use ($schema, $extension, $options, $rows, $invalid, } catch (Flow\Parquet\Exception\RuntimeException) { } - $unclosed = new NativeParquetWriter(new RowsWriter($filesystem->writeTo(path('memory://unclosed.parquet')), $extension, 'SNAPPY', $options, 30)); + $unclosed = new RustParquetOpenSink(new RustParquetFileWriter($filesystem->writeTo(path('memory://unclosed.parquet')), $extension, Compressions::SNAPPY, $options, 30)); $unclosed->write($rows); }; @@ -79,7 +81,7 @@ for ($i = 0; $i < 10; $i++) { } gc_collect_cycles(); $baseline = memory_get_usage(false); -$baselineRust = (new DefaultBackend())->allocatedBytes(); +$baselineRust = (new RustBackend())->allocatedBytes(); for ($i = 0; $i < 200; $i++) { $cycle(); @@ -87,7 +89,7 @@ for ($i = 0; $i < 200; $i++) { gc_collect_cycles(); var_dump(memory_get_usage(false) <= $baseline); -var_dump((new DefaultBackend())->allocatedBytes() === $baselineRust); +var_dump((new RustBackend())->allocatedBytes() === $baselineRust); ?> --EXPECT-- bool(true) diff --git a/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt b/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt index 04b38cf133..78da4d24ee 100644 --- a/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt +++ b/src/extension/flow-php-ext/tests/phpt/090_parquet_schema_refused_at_open.phpt @@ -1,5 +1,5 @@ --TEST-- -NativeParquetReader refuses a schema type that stores another arrow type at construction, before any batch: over a zero-row file and past the end of an 8-row-group file +RustParquetOpenSource refuses a schema type that stores another arrow type when batches() is called, before any batch: over a zero-row file and past the end of an 8-row-group file; a file other than RustParquetFileReader and a writer other than RustParquetFileWriter are refused --SKIPIF-- @@ -7,10 +7,11 @@ NativeParquetReader refuses a schema type that stores another arrow type at cons toParquet($schema)); -$empty = new RowsWriter($filesystem->writeTo(path('memory://empty.parquet')), $extension, 'SNAPPY', OptionsConverter::toExtension(Options::default()), 10); +$empty = new RustParquetFileWriter($filesystem->writeTo(path('memory://empty.parquet')), $extension, Compressions::SNAPPY, OptionsConverter::toExtension(Options::default()), 10); $empty->close(); -$groups = new NativeParquetWriter(new RowsWriter( +$groups = new RustParquetOpenSink(new RustParquetFileWriter( $filesystem->writeTo(path('memory://groups.parquet')), $extension, - 'SNAPPY', + Compressions::SNAPPY, OptionsConverter::toExtension(Options::default()->set(Option::ROW_GROUP_SIZE_BYTES, 1)), 10, )); @@ -37,9 +38,13 @@ for ($group = 0; $group < 8; $group++) { $groups->close(); $mismatched = schema(str_schema('id')); -echo outcome(static fn() => native_parquet_reader($filesystem->readFrom(path('memory://empty.parquet')), $mismatched, 10, null, null)), "\n"; -echo outcome(static fn() => native_parquet_reader($filesystem->readFrom(path('memory://groups.parquet')), $mismatched, 10, 1_000, null)), "\n"; +echo outcome(static fn() => rust_parquet_batches($filesystem->readFrom(path('memory://empty.parquet')), $mismatched, 10, null, null)), "\n"; +echo outcome(static fn() => rust_parquet_batches($filesystem->readFrom(path('memory://groups.parquet')), $mismatched, 10, 1_000, null)), "\n"; +echo outcome(static fn() => new Flow\ETL\Adapter\Parquet\RustParquetOpenSource(new stdClass())), "\n"; +echo outcome(static fn() => new Flow\ETL\Adapter\Parquet\RustParquetOpenSink(new stdClass())), "\n"; ?> --EXPECT-- Flow\ETL\Exception\InvalidArgumentException: Parquet column "id" (Int64) is read as Int64, its schema type string stores Binary Flow\ETL\Exception\InvalidArgumentException: Parquet column "id" (Int64) is read as Int64, its schema type string stores Binary +Flow\ETL\Exception\RuntimeException: flow_php expected a Flow\Parquet\Engine\RustParquetFileReader +Flow\ETL\Exception\RuntimeException: flow_php expected a Flow\Parquet\Engine\RustParquetFileWriter diff --git a/src/extension/flow-php-ext/tests/phpt/091_parquet_canonical_layout_contract.phpt b/src/extension/flow-php-ext/tests/phpt/091_parquet_canonical_layout_contract.phpt index 2b7722ff70..c28642ea9d 100644 --- a/src/extension/flow-php-ext/tests/phpt/091_parquet_canonical_layout_contract.phpt +++ b/src/extension/flow-php-ext/tests/phpt/091_parquet_canonical_layout_contract.phpt @@ -1,5 +1,5 @@ --TEST-- -arrow-ext's canonical Arrow layout (parquet/canonical.rs) is the layout flow_php's columns store (flow-batch-frame kind::data_type()): every Flow type, nested included, crosses BatchReader → NativeParquetReader with its values intact +arrow-ext's canonical Arrow layout (parquet/canonical.rs) is the layout flow_php's columns store (flow-batch-frame kind::data_type()): every Flow type, nested included, crosses RustBatchReader → RustParquetOpenSource with its values intact --SKIPIF-- @@ -7,11 +7,12 @@ arrow-ext's canonical Arrow layout (parquet/canonical.rs) is the layout flow_php writeTo(path('memory://layout.parquet')), ArrowSchemaConverter::toExtension((new SchemaConverter())->toParquet($schema)), - 'SNAPPY', + Compressions::SNAPPY, OptionsConverter::toExtension(Options::default()), 1_000, )); @@ -57,9 +58,9 @@ $writer->write(php_rows($schema, $values)); $writer->close(); $read = []; -$reader = native_parquet_reader($filesystem->readFrom(path('memory://layout.parquet')), $schema, 10, null, null); +$reader = rust_parquet_batches($filesystem->readFrom(path('memory://layout.parquet')), $schema, 10, null, null); -while (($batch = $reader->next()) !== null) { +foreach ($reader as $batch) { array_push($read, ...$batch->toArray()); } diff --git a/src/extension/flow-php-ext/tests/phpt/092_failure_without_autoloader.phpt b/src/extension/flow-php-ext/tests/phpt/092_failure_without_autoloader.phpt new file mode 100644 index 0000000000..e87433e110 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/092_failure_without_autoloader.phpt @@ -0,0 +1,24 @@ +--TEST-- +without an autoloader flow_php fails with a plain Exception, never recursing on the missing RuntimeException class +--SKIPIF-- + +--FILE-- + new Flow\ETL\Adapter\CSV\RustCSVOpenSource(new stdClass(), ',,', '"', '\\', true, true, true), + static fn() => new Flow\ETL\Column\RustColumn(), +] as $fn) { + try { + $fn(); + echo "FAIL: no exception thrown\n"; + } catch (Exception $e) { + echo get_class($e), ': ', $e->getMessage(), "\n"; + } +} + +var_dump(class_exists('Flow\ETL\Exception\RuntimeException', false)); +?> +--EXPECT-- +Exception: flow_php CSV separator must be exactly one byte +Exception: Flow\ETL\Column\RustColumn is built by RustBackend +bool(false) diff --git a/src/extension/flow-php-ext/tests/phpt/093_adapter_writers_contracts.phpt b/src/extension/flow-php-ext/tests/phpt/093_adapter_writers_contracts.phpt new file mode 100644 index 0000000000..3ae2b91508 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/093_adapter_writers_contracts.phpt @@ -0,0 +1,71 @@ +--TEST-- +RustCSVEncoder / RustJSONEncoder implement CSVEncoder / JSONEncoder: unrendered columns through the held PHP encoder's cells() / fragments(), the cache refreshed on a new Schema, the PHP header; RustParquetOpenSink implements ParquetOpenSink +--SKIPIF-- + +--FILE-- +implementsInterface(ParquetOpenSink::class)); + +$plain = schema(int_schema('id')); +$values = [['id' => 1, 'doc' => '1'], ['id' => 2, 'doc' => '']]; +$xml = schema(int_schema('id'), xml_schema('doc')); +$jsonDoc = schema(int_schema('id'), json_schema('doc')); +$jsonValues = [['id' => 1, 'doc' => '{"a":1}'], ['id' => 2, 'doc' => '[1,2]']]; + +$csvRecorder = new RecordingPhpCSVEncoder($csvPhp); +$jsonRecorder = new RecordingPhpJSONEncoder($jsonPhp); +$xmlRows = native_rows($xml, $values); +$jsonRows = native_rows($jsonDoc, $jsonValues); +(new RustCSVEncoder(',', '"', '\\', "\n", DATE_ATOM, 'Y-m-d', $csvRecorder))->encode($xmlRows); +(new RustJSONEncoder(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d', $jsonRecorder))->encode($jsonRows, "\n"); +echo json_encode([recorded_names($csvRecorder->columns, $xmlRows), recorded_names($jsonRecorder->columns, $jsonRows)]), "\n"; + +// the first batch caches a Schema without unrendered columns; a new Schema object must refresh it +foreach ([[$plain, [['id' => 1]]], [$xml, $values]] as [$schema, $batch]) { + echo $csv->encode(native_rows($schema, $batch)) === $csvPhp->encode(php_rows($schema, $batch)) ? 'csv identical' : 'csv DIFFERENT', "\n"; +} + +foreach ([[$plain, [['id' => 1]]], [$jsonDoc, $jsonValues]] as [$schema, $batch]) { + echo $json->encode(native_rows($schema, $batch), "\n") === $jsonPhp->encode(php_rows($schema, $batch), "\n") ? 'json identical' : 'json DIFFERENT', "\n"; +} + +echo $csv->encodeHeader(['id', 'a "b"', 'c,d']) === $csvPhp->encodeHeader(['id', 'a "b"', 'c,d']) ? 'header identical' : 'header DIFFERENT', "\n"; +echo $csv->encode(native_rows($xml, $values)); +echo $json->encode(native_rows($jsonDoc, $jsonValues), "\n"), "\n"; +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +[["doc"],["doc"]] +csv identical +csv identical +json identical +json identical +header identical +1,1 +2, +{"id":1,"doc":{"a":1}} +{"id":2,"doc":[1,2]} diff --git a/src/extension/flow-php-ext/tests/phpt/094_rust_iterator_generator_parity.phpt b/src/extension/flow-php-ext/tests/phpt/094_rust_iterator_generator_parity.phpt new file mode 100644 index 0000000000..21e73f6519 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/094_rust_iterator_generator_parity.phpt @@ -0,0 +1,95 @@ +--TEST-- +RustIterator behaves as the Generator it replaced: it starts on first use, ends for good when its producer throws (valid() false, key() and current() null, next() a no-op) and refuses rewind() only after next() +--SKIPIF-- + +--FILE-- + $rows === null ? 'null' : (string) $rows->toArray()[0]['id']; +$step = static function (string $label, callable $call): void { + // the class differs on purpose: RustIterator throws flow's RuntimeException, a Generator \Exception + try { + $result = var_export($call(), true); + } catch (Throwable) { + $result = 'threw'; + } + + echo $label, ': ', $result, "\n"; +}; +$drive = static function (Iterator $iterator) use ($id, $step): void { + $step('key before rewind', static fn() => $iterator->key()); + $step('current', static fn() => $id($iterator->current())); + $step('rewind', static fn() => $iterator->rewind()); + $step('next', static fn() => $iterator->next()); + $step('current', static fn() => $id($iterator->current())); + $step('next (producer throws)', static fn() => $iterator->next()); + $step('valid', static fn() => $iterator->valid()); + $step('key', static fn() => $iterator->key()); + $step('current', static fn() => $iterator->current()); + $step('next', static fn() => $iterator->next()); + $step('rewind', static fn() => $iterator->rewind()); +}; +$failingFirst = static function (Iterator $iterator) use ($step): void { + $step('rewind (producer throws)', static fn() => $iterator->rewind()); + $step('valid', static fn() => $iterator->valid()); + $step('rewind', static fn() => $iterator->rewind()); +}; + +$rows = static fn(int $id) => php_rows(schema(int_schema('id')), [['id' => $id]]); +$generator = (static function () use ($rows): Generator { + yield $rows(1); + yield $rows(2); + throw new RuntimeException('malformed'); +})(); +$rust = (new RustJsonOpenSource(new StringSourceStream(path('memory://a.jsonl'), "{\"id\":1}\n{\"id\":2}\nnot json\n"), true, 'memory://a.jsonl', '', 0)) + ->batches($schema, 1, new PhpBackend()); + +ob_start(); +$drive($generator); +$expected = ob_get_clean(); +ob_start(); +$drive($rust); +$actual = ob_get_clean(); +echo $actual, $actual === $expected ? "identical\n" : "DIFFERENT, Generator:\n{$expected}"; + +$generator = (static function (): Generator { + throw new RuntimeException('malformed'); + yield; +})(); +$rust = (new RustJsonOpenSource(new StringSourceStream(path('memory://b.jsonl'), "not json\n"), true, 'memory://b.jsonl', '', 0)) + ->batches($schema, 1, new PhpBackend()); + +ob_start(); +$failingFirst($generator); +$expected = ob_get_clean(); +ob_start(); +$failingFirst($rust); +$actual = ob_get_clean(); +echo $actual, $actual === $expected ? "identical\n" : "DIFFERENT, Generator:\n{$expected}"; +?> +--EXPECT-- +key before rewind: 0 +current: '1' +rewind: NULL +next: NULL +current: '2' +next (producer throws): threw +valid: false +key: NULL +current: NULL +next: NULL +rewind: threw +identical +rewind (producer throws): threw +valid: false +rewind: NULL +identical diff --git a/src/extension/flow-php-ext/tests/phpt/095_sources_reentrant_stream.phpt b/src/extension/flow-php-ext/tests/phpt/095_sources_reentrant_stream.phpt new file mode 100644 index 0000000000..8ebd75e250 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/095_sources_reentrant_stream.phpt @@ -0,0 +1,109 @@ +--TEST-- +RustCSVOpenSource and RustJsonOpenSource hold no borrow while their stream runs: a stream calling producedRows(), producedBytes() and close() back mid-read is answered, never a panic +--SKIPIF-- + +--FILE-- +stream = new StringSourceStream(path('memory://hooked'), $content); + } + + public function close(): void + { + $this->stream->close(); + } + + public function content(): string + { + return $this->stream->content(); + } + + public function isOpen(): bool + { + return $this->stream->isOpen(); + } + + public function iterate(int $length = 1): Generator + { + foreach ($this->stream->iterate(4) as $chunk) { + ($this->hook)(); + + yield $chunk; + } + } + + public function path(): Path + { + return $this->stream->path(); + } + + public function read(int $length, int $offset): string + { + ($this->hook)(); + + return $this->stream->read(4, $offset); + } + + public function readLines(string $separator = "\n", ?int $length = null): Generator + { + return $this->stream->readLines($separator, $length); + } + + public function size(): ?int + { + return $this->stream->size(); + } +} + +$schema = schema(int_schema('id')); +$stream = new HookedStream("id\n1\n2\n3\n"); +$csv = new RustCSVOpenSource($stream, ',', '"', '\\', true, true, true); +$seen = []; +$stream->hook = static function () use ($csv, &$seen): void { + $seen[] = $csv->producedRows() . '/' . $csv->producedBytes(); +}; +$ids = []; + +foreach ($csv->batches($schema, 1, new PhpBackend()) as $rows) { + $ids[] = $rows->toArray()[0]['id']; +} + +echo 'csv ids: ', json_encode($ids), ', counters answered mid-read: ', count($seen), ', after: ', $csv->producedRows(), "\n"; + +$stream = new HookedStream("{\"id\":1}\n{\"id\":2}\n"); +$json = new RustJsonOpenSource($stream, true, 'memory://hooked', '', 0); +$closed = false; +$stream->hook = static function () use ($json, &$closed): void { + if (!$closed) { + $closed = true; + $json->close(); + } +}; + +echo 'json close() mid-read: ', outcome(static fn() => count(iterator_to_array($json->batches($schema, 1, new PhpBackend())))), "\n"; +echo 'json closed: ', var_export($closed, true), "\n"; +?> +--EXPECT-- +csv ids: [1,2,3], counters answered mid-read: 3, after: 3 +json close() mid-read: i:2; +json closed: true diff --git a/src/extension/flow-php-ext/tests/phpt/096_encoders_columns_left_to_php.phpt b/src/extension/flow-php-ext/tests/phpt/096_encoders_columns_left_to_php.phpt new file mode 100644 index 0000000000..7995058b64 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/096_encoders_columns_left_to_php.phpt @@ -0,0 +1,45 @@ +--TEST-- +RustCSVEncoder / RustJSONEncoder render natively what they can and leave the rest, by column, to the held PHP encoder's cells() / fragments() +--SKIPIF-- + +--FILE-- +encode($rows); + (new RustJSONEncoder(JSON_THROW_ON_ERROR, $format, $format, $json))->encode($rows, "\n"); + + echo "{$batch} ({$format}): csv ", json_encode(recorded_names($csv->columns, $rows)), ', json ', json_encode(recorded_names($json->columns, $rows)), "\n"; +} +?> +--EXPECT-- +scalars with nulls (Y-m-d): csv [], json [] +temporal kinds (Y-m-d\TH:i:sP): csv [], json [] +temporal kinds (D, d M Y): csv ["at","offset","on"], json ["at","offset","on"] +a json column (Y-m-d): csv [], json ["j"] +markup columns (Y-m-d): csv ["x","e"], json ["x","e"] +nested kinds rendered natively (Y-m-d): csv [], json [] +nested kinds rendered natively (l): csv ["l","s"], json ["l","s"] +a list of json documents (Y-m-d): csv ["l"], json ["l"] +nested markup leaves (Y-m-d): csv ["l","s"], json ["l","s"] diff --git a/src/extension/flow-php-ext/tests/phpt/bootstrap.php b/src/extension/flow-php-ext/tests/phpt/bootstrap.php index 58a6b7346f..b97a316c9f 100644 --- a/src/extension/flow-php-ext/tests/phpt/bootstrap.php +++ b/src/extension/flow-php-ext/tests/phpt/bootstrap.php @@ -4,16 +4,15 @@ require __DIR__ . '/../../../../../vendor/autoload.php'; -use Flow\Arrow\Parquet\BatchReader; -use Flow\Arrow\Parquet\ParquetFile; -use Flow\ETL\Adapter\Parquet\NativeParquetReader; -use Flow\ETL\Column\DefaultBackend; +use Flow\ETL\Adapter\Parquet\RustParquetOpenSource; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\RustBackend; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; use Flow\Filesystem\SourceStream; +use Flow\Parquet\Engine\RustParquetFileReader; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; @@ -213,7 +212,7 @@ function php_rows(Schema $schema, array $values): Rows */ function native_rows(Schema $schema, array $values): Rows { - return (new RowsBuilder($schema, new DefaultBackend())) + return (new RowsBuilder($schema, new RustBackend())) ->appendRows($values) ->finish(); } @@ -251,26 +250,18 @@ function comparable(mixed $value): string } /** - * `NativeParquetReader` over arrow-ext's batches of `$schema`'s columns of the Parquet file in `$stream`. + * `RustParquetOpenSource::batches()` of `$schema`'s columns of the Parquet file in `$stream`, adopted by `RustBackend`. * * @param int<1, max> $batchSize */ -function native_parquet_reader( - SourceStream $stream, - Schema $schema, - int $batchSize, - ?int $offset, - ?int $limit, -): NativeParquetReader { - return new NativeParquetReader( - new BatchReader( - new ParquetFile($stream), - array_map('strval', array_keys($schema->definitions())), - $batchSize, - $offset, - $limit, - ), +function rust_parquet_batches(SourceStream $stream, Schema $schema, int $batchSize, ?int $offset, ?int $limit): Iterator +{ + return (new RustParquetOpenSource(new RustParquetFileReader($stream)))->batches( $schema, + $batchSize, + $offset, + $limit, + new RustBackend(), ); } @@ -310,14 +301,24 @@ function assert_same_outcome(callable $php, callable $native): void } /** - * JSON of the three column interfaces as reflection sees them: methods, parameters, types, variadics. + * JSON of the interfaces flow_php registers as reflection sees them: methods, parameters, types, optional, variadic, by-ref. */ function interfaces_reflection(): string { $interfaces = []; - foreach (['Backend', 'Column', 'ColumnBuilder'] as $name) { - $class = new ReflectionClass('Flow\\ETL\\Column\\' . $name); + foreach ([ + 'Flow\\ETL\\Column\\Backend', + 'Flow\\ETL\\Column\\Column', + 'Flow\\ETL\\Column\\ColumnBuilder', + 'Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSink', + 'Flow\\ETL\\Adapter\\CSV\\CSVEncoder', + 'Flow\\ETL\\Adapter\\JSON\\JSONEncoder', + 'Flow\\ETL\\Adapter\\CSV\\CSVOpenSource', + 'Flow\\ETL\\Adapter\\JSON\\JsonOpenSource', + 'Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSource', + ] as $name) { + $class = new ReflectionClass($name); $interfaces[$name] = [ $class->isInterface(), array_map(static fn(ReflectionMethod $method): array => [ @@ -326,6 +327,7 @@ function interfaces_reflection(): string array_map(static fn(ReflectionParameter $parameter): array => [ $parameter->getName(), (string) $parameter->getType(), + $parameter->isOptional(), $parameter->isVariadic(), $parameter->isPassedByReference(), ], $method->getParameters()), @@ -341,7 +343,7 @@ function expect_exception(callable $fn): void try { $fn(); echo "FAIL: no exception thrown\n"; - } catch (Flow\Floe\Exception\ExtensionException $e) { + } catch (Flow\ETL\Exception\RuntimeException $e) { echo get_class($e), ': ', $e->getMessage(), "\n"; } } @@ -382,7 +384,7 @@ function csv_php_rows( } /** - * RustCSVReaderNative fed `$raw` in `$chunk`-byte pieces, as `[headers, list of array::$values]`. + * RustCSVOpenSource over `$raw`, read in `$chunk`-byte pieces, as `[headers, list of array::$values]`. * * @param positive-int $chunk * @@ -398,32 +400,19 @@ function csv_native_rows( bool $removeBOM = true, int $chunk = 4096, ): array { - $reader = new Flow\ETL\Adapter\CSV\RustCSVReaderNative( + $source = new Flow\ETL\Adapter\CSV\RustCSVOpenSource( + new Flow\Filesystem\Stream\StringSourceStream(Flow\Filesystem\DSL\path('memory://phpt.csv'), $raw), $separator, $enclosure, $escape, $withHeader, $emptyToNull, $removeBOM, + $chunk, ); - $rows = []; - $drain = static function () use ($reader, &$rows): void { - while (($batch = $reader->next(3)) !== []) { - foreach ($batch as $values) { - $rows[] = $values; - } - } - }; - - foreach ($raw === '' ? [] : str_split($raw, $chunk) as $piece) { - $reader->feed($piece); - $drain(); - } + $rows = iterator_to_array($source->records(), false); - $reader->finish(); - $drain(); - - return [$reader->headers(), $rows]; + return [$source->headers(), $rows]; } /** @@ -631,27 +620,52 @@ function csv_narrow_corpus(): array } /** - * Prints every value where RustColumnFoldNative::narrowOne() and StringTypeNarrower::narrow() disagree. + * RustCSVOpenSource::sniff() of one CSV column "v" (no names seeded), one row per value - a null value is an empty cell, + * read as null with $emptyToNull. + * + * @param list $values + */ +function rust_sniff_column( + array $values, + Flow\Types\Type\TypeNarrower $typer, + bool $emptyToNull = true, +): Flow\ETL\Schema\Inference\ColumnTypes { + $csv = "v\n"; + + foreach ($values as $value) { + $csv .= ($value === null ? '' : '"' . str_replace('"', '""', $value) . '"') . "\n"; + } + + return (new Flow\ETL\Adapter\CSV\RustCSVOpenSource( + new Flow\Filesystem\Stream\MemorySourceStream($csv), + ',', + '"', + '', + true, + $emptyToNull, + false, + ))->sniff([], -1, new Flow\ETL\Schema\Inference\SchemaInference(), $typer); +} + +/** + * Prints every value whose one-row RustCSVOpenSource::sniff() differs from the PHP ColumnTypes::observe() fold of it - + * StringTypeNarrower::narrow() of the value. * * @param list> $candidates * @param list $corpus */ function assert_narrow_parity(string $label, array $candidates, array $corpus): void { - $php = new Flow\Types\Type\Native\String\StringTypeNarrower($candidates); - $native = new Flow\ETL\Adapter\CSV\RustColumnFoldNative([], array_map( - static fn(Flow\Types\Type $type): string => $type->toString(), - $candidates, - )); + $typer = new Flow\Types\Type\Native\String\StringTypeNarrower($candidates); $mismatches = 0; foreach ($corpus as $value) { - $expected = $php->narrow($value)->toString(); - $actual = $native->narrowOne($value); + $php = new Flow\ETL\Schema\Inference\ColumnTypes([], $typer); + $php->observe(['v' => $value]); - if ($expected !== $actual) { + if ($php != rust_sniff_column([$value], $typer, false)) { $mismatches++; - echo ' ', bin2hex($value), ' ', var_export($value, true), ": php={$expected} native={$actual}\n"; + echo ' ', bin2hex($value), ' ', var_export($value, true), "\n"; } } @@ -1133,3 +1147,147 @@ function written(callable $write): string return $stream->content(); } + +/** + * A stream over `$raw` whose read() returns at most `$chunk` bytes - a reader fed in pieces of that size. + * + * @param positive-int $chunk + */ +function chunked_source_stream(string $raw, int $chunk): Flow\Filesystem\SourceStream +{ + return new class( + new Flow\Filesystem\Stream\StringSourceStream(Flow\Filesystem\DSL\path('memory://phpt.json'), $raw), + $chunk, + ) implements Flow\Filesystem\SourceStream { + /** + * @param positive-int $chunk + */ + public function __construct( + private readonly Flow\Filesystem\Stream\StringSourceStream $stream, + private readonly int $chunk, + ) {} + + public function close(): void + { + $this->stream->close(); + } + + public function content(): string + { + return $this->stream->content(); + } + + public function isOpen(): bool + { + return $this->stream->isOpen(); + } + + /** + * @param positive-int $length + */ + public function iterate(int $length = 1): Generator + { + return $this->stream->iterate(min($length, $this->chunk)); + } + + public function path(): Flow\Filesystem\Path + { + return $this->stream->path(); + } + + /** + * @param positive-int $length + */ + public function read(int $length, int $offset): string + { + return $this->stream->read(min($length, $this->chunk), $offset); + } + + public function readLines(string $separator = "\n", ?int $length = null): Generator + { + return $this->stream->readLines($separator, $length); + } + + public function size(): ?int + { + return $this->stream->size(); + } + }; +} + +/** + * Stands in for the PhpCSVEncoder a RustCSVEncoder holds: renders through it and records every column left to it. + */ +final class RecordingPhpCSVEncoder +{ + /** + * @var list + */ + public array $columns = []; + + public function __construct( + private readonly Flow\ETL\Adapter\CSV\PhpCSVEncoder $php, + ) {} + + /** + * @return list + */ + public function cells(Flow\Types\Type $type, Flow\ETL\Column\Column $column): array + { + $this->columns[] = $column; + + return $this->php->cells($type, $column); + } + + /** + * @param list $headers + */ + public function encodeHeader(array $headers): string + { + return $this->php->encodeHeader($headers); + } +} + +/** + * Stands in for the PhpJSONEncoder a RustJSONEncoder holds: renders through it and records every column left to it. + */ +final class RecordingPhpJSONEncoder +{ + /** + * @var list + */ + public array $columns = []; + + public function __construct( + private readonly Flow\ETL\Adapter\JSON\PhpJSONEncoder $php, + ) {} + + /** + * @return list + */ + public function fragments(Flow\Types\Type $type, Flow\ETL\Column\Column $column): array + { + $this->columns[] = $column; + + return $this->php->fragments($type, $column); + } +} + +/** + * The names of the columns of `$rows` among `$recorded`. + * + * @param list $recorded + * + * @return list + */ +function recorded_names(array $recorded, Rows $rows): array +{ + return array_map( + 'strval', + array_keys(array_filter($rows->columns(), static fn(Flow\ETL\Column\Column $column): bool => in_array( + $column, + $recorded, + true, + ))), + ); +} diff --git a/src/lib/filesystem/src/Flow/Filesystem/Path.php b/src/lib/filesystem/src/Flow/Filesystem/Path.php index 99b2d6472e..d48e2fe7eb 100644 --- a/src/lib/filesystem/src/Flow/Filesystem/Path.php +++ b/src/lib/filesystem/src/Flow/Filesystem/Path.php @@ -83,10 +83,14 @@ public function extension(): string|false public function extractPlaceholderPartitions(self $path): Partitions { if ($this->implementation instanceof UnixPath) { - return $this->implementation->extractPlaceholderPartitions(type_instance_of(UnixPath::class)->assert($path->implementation)); + return $this->implementation->extractPlaceholderPartitions(type_instance_of( + UnixPath::class, + )->assert($path->implementation)); } - return $this->implementation->extractPlaceholderPartitions(type_instance_of(WindowsPath::class)->assert($path->implementation)); + return $this->implementation->extractPlaceholderPartitions(type_instance_of( + WindowsPath::class, + )->assert($path->implementation)); } public function filename(): string diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php index 1c34fc5443..1b7cfa8374 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php @@ -18,18 +18,18 @@ final readonly class AdaptiveParquetEngine implements ParquetEngine { - private ParquetEngine $delegate; + private ParquetEngine $engine; public function __construct(ByteOrder $byteOrder = ByteOrder::LITTLE_ENDIAN, Options $options = new Options()) { - $this->delegate = extension_loaded('arrow') - ? new ArrowParquetEngine($options) + $this->engine = extension_loaded('arrow') && $byteOrder === ByteOrder::LITTLE_ENDIAN + ? new RustParquetEngine($options) : new PhpParquetEngine($byteOrder, $options); } public function openForRead(SourceStream $stream): ParquetFileReader { - return $this->delegate->openForRead($stream); + return $this->engine->openForRead($stream); } public function openForWrite( @@ -38,7 +38,7 @@ public function openForWrite( Compressions $compression, Options $options, ): ParquetFileWriter { - return $this->delegate->openForWrite($stream, $schema, $compression, $options); + return $this->engine->openForWrite($stream, $schema, $compression, $options); } public function writeRows( @@ -48,6 +48,6 @@ public function writeRows( Options $options, iterable $rows, ): void { - $this->delegate->writeRows($stream, $schema, $compression, $options, $rows); + $this->engine->writeRows($stream, $schema, $compression, $options, $rows); } } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/OptionsConverter.php b/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/OptionsConverter.php index d4a464721c..7316773cdc 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/OptionsConverter.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/OptionsConverter.php @@ -11,6 +11,23 @@ final class OptionsConverter { + // called by name from arrow-ext RustParquetEngine::__construct(), pinned by phpts 047, 052 + /** + * The options the arrow engine itself reads, which Rust cannot read off the Option enum. + * + * @return array{INT_96_AS_DATETIME: bool, ARROW_WRITE_BATCH_SIZE: int} + */ + public static function toEngine(?Options $options): array + { + $options ??= new Options(); + + return [ + 'INT_96_AS_DATETIME' => $options->getBool(Option::INT_96_AS_DATETIME), + 'ARROW_WRITE_BATCH_SIZE' => $options->getInt(Option::ARROW_WRITE_BATCH_SIZE), + ]; + } + + // called by name from arrow-ext RustParquetEngine::openForWrite(), pinned by phpts 047, 052 /** * @return array */ diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SchemaConverter.php b/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SchemaConverter.php index 0ea3aec6b0..2004d1a185 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SchemaConverter.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/Arrow/SchemaConverter.php @@ -17,6 +17,7 @@ final class SchemaConverter { + // called by name from arrow-ext RustParquetEngine::openForWrite(), pinned by phpts 047, 052 /** * @return array> */ diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php deleted file mode 100644 index 1f7a5ea51b..0000000000 --- a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetEngine.php +++ /dev/null @@ -1,84 +0,0 @@ - 'UNCOMPRESSED', - Compressions::SNAPPY => 'SNAPPY', - Compressions::GZIP => 'GZIP', - Compressions::BROTLI => 'BROTLI', - Compressions::LZ4, Compressions::LZ4_RAW => 'LZ4_RAW', - Compressions::ZSTD => 'ZSTD', - Compressions::LZO => throw new RuntimeException('LZO compression is not supported by the Arrow engine'), - }; - } - - public function openForRead(SourceStream $stream): ParquetFileReader - { - return new ArrowParquetFileReader(new ParquetFile($stream), $this->options); - } - - public function openForWrite( - DestinationStream $stream, - Schema $schema, - Compressions $compression, - Options $options, - ): ParquetFileWriter { - return new ArrowParquetFileWriter( - new RowsWriter( - $stream, - SchemaConverter::toExtension($schema), - self::mapCompression($compression), - OptionsConverter::toExtension($options), - $this->options->getInt(Option::ARROW_WRITE_BATCH_SIZE), - ), - ); - } - - public function writeRows( - DestinationStream $stream, - Schema $schema, - Compressions $compression, - Options $options, - iterable $rows, - ): void { - $file = $this->openForWrite($stream, $schema, $compression, $options); - - try { - $file->writeBatch($rows); - } finally { - $file->close(); - } - } -} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php deleted file mode 100644 index af1e0f0422..0000000000 --- a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileReader.php +++ /dev/null @@ -1,109 +0,0 @@ -open || throw new RuntimeException('Reader is not open'); - - $this->open = false; - $this->file->close(); - } - - public function file(): ParquetFile - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->file; - } - - public function metadata(): Metadata - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->metadata ??= Metadata::fromThrift($this->file->thrift()); - } - - public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator - { - $this->open || throw new RuntimeException('Reader is not open'); - - if (!$this->options->getBool(Option::INT_96_AS_DATETIME)) { - foreach ($columns as $column) { - foreach ($this->schema()->columnsFlat() as $leaf) { - if ( - $leaf->type() === PhysicalType::INT96 - && ($leaf->flatPath() === $column || str_starts_with($leaf->flatPath(), $column . '.')) - ) { - throw new InvalidArgumentException(sprintf( - 'Parquet column "%s" holds INT96, which arrow reads only as a datetime ' - . '(Option::INT_96_AS_DATETIME = true); read the file with \Flow\Parquet\Reader::php()', - $column, - )); - } - } - } - } - - $reader = new ColumnsReader($this->file, $columns, $batchSize, $offset, $limit); - - try { - while (($chunk = $reader->next()) !== null) { - yield $chunk; - } - } finally { - $reader->close(); - } - } - - public function rowsNumber(): int - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->file->rowsNumber(); - } - - public function schema(): Schema - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->metadata?->schema() ?? ($this->schema ??= Schema::fromThrift($this->file->schema())); - } - - public function totalByteSize(): int - { - $this->open || throw new RuntimeException('Reader is not open'); - - return $this->file->totalByteSize(); - } -} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileWriter.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileWriter.php deleted file mode 100644 index 575840e47a..0000000000 --- a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowParquetFileWriter.php +++ /dev/null @@ -1,58 +0,0 @@ -writer = $writer; - } - - public function close(): void - { - $writer = $this->writer ?? throw new RuntimeException('Writer is not open'); - - try { - $writer->close(); - } finally { - $this->writer = null; - } - } - - public function writeBatch(iterable $rows): void - { - $writer = $this->writer ?? throw new RuntimeException('Writer is not open'); - - if (is_array($rows)) { - $writer->writeRows(array_values($rows)); - - return; - } - - foreach ($rows as $row) { - $writer->writeRow($row); - } - } - - public function writeColumns(array $columns): void - { - ($this->writer ?? throw new RuntimeException('Writer is not open'))->writeColumns($columns); - } - - public function writeRow(array $row): void - { - ($this->writer ?? throw new RuntimeException('Writer is not open'))->writeRow($row); - } -} diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetFileReader.php index c91c412fe6..76d0f74c38 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetFileReader.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/PhpParquetFileReader.php @@ -88,6 +88,12 @@ public function metadata(): Metadata return $this->metadata; } + /** + * @param list $columns + * @param int<1, max> $batchSize + * + * @return Generator>> + */ public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator { $this->open || throw new RuntimeException('Reader is not open'); diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php index 9fc91077dc..eafd9a2ccf 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php @@ -9,6 +9,12 @@ use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; +use function extension_loaded; + +if (extension_loaded('arrow')) { + return; +} + interface ParquetEngine { /** diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Metadata.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Metadata.php index f8b84ec8a1..b78a778e71 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Metadata.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Metadata.php @@ -17,6 +17,7 @@ public function __construct( private ?string $createdBy, ) {} + // called by name from arrow-ext RustParquetFileReader::metadata(), pinned by phpts 047, 052 public static function fromThrift(FileMetaData $thrift): self { return new self( diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema.php b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema.php index 4b9d3738f2..548e4cb0e6 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFile/Schema.php @@ -25,6 +25,7 @@ public function __construct( private readonly NestedColumn $schemaRoot, ) {} + // called by name from arrow-ext RustParquetFileReader::schema(), pinned by phpts 047, 052 /** * @param array $schemaElements */ diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php index 3655acfd27..841c5038d8 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php @@ -6,7 +6,13 @@ use Flow\Parquet\ParquetFile\Metadata; use Flow\Parquet\ParquetFile\Schema; -use Generator; +use Iterator; + +use function extension_loaded; + +if (extension_loaded('arrow')) { + return; +} interface ParquetFileReader { @@ -24,9 +30,9 @@ public function metadata(): Metadata; * @param list $columns resolved names, never empty * @param int<1, max> $batchSize upper bound of rows per chunk * - * @return Generator>> chunks keyed by column, every list the same length (>0) + * @return Iterator>> chunks keyed by column, every list the same length (>0) */ - public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Generator; + public function readColumns(array $columns, int $batchSize, ?int $limit, ?int $offset): Iterator; public function rowsNumber(): int; diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFileWriter.php b/src/lib/parquet/src/Flow/Parquet/ParquetFileWriter.php index 49b8187eef..80856dc0e9 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFileWriter.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFileWriter.php @@ -4,6 +4,12 @@ namespace Flow\Parquet; +use function extension_loaded; + +if (extension_loaded('arrow')) { + return; +} + interface ParquetFileWriter { /** diff --git a/src/lib/parquet/src/Flow/Parquet/Reader.php b/src/lib/parquet/src/Flow/Parquet/Reader.php index 2d778541fa..0e51e2f356 100644 --- a/src/lib/parquet/src/Flow/Parquet/Reader.php +++ b/src/lib/parquet/src/Flow/Parquet/Reader.php @@ -8,7 +8,6 @@ use Flow\Filesystem\Stream\NativeLocalSourceStream; use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\AdaptiveParquetEngine; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; use function Flow\Filesystem\DSL\path_real; @@ -25,11 +24,6 @@ public function __construct( $this->engine = $engine ?? new AdaptiveParquetEngine($this->byteOrder, $this->options); } - public static function arrow(Options $options = new Options()): self - { - return new self(options: $options, engine: new ArrowParquetEngine($options)); - } - public static function php(Options $options = new Options()): self { return new self(options: $options, engine: new PhpParquetEngine(options: $options)); diff --git a/src/lib/parquet/src/Flow/Parquet/Writer.php b/src/lib/parquet/src/Flow/Parquet/Writer.php index 9fb3f526cd..3dcfae9114 100644 --- a/src/lib/parquet/src/Flow/Parquet/Writer.php +++ b/src/lib/parquet/src/Flow/Parquet/Writer.php @@ -7,7 +7,6 @@ use Flow\Filesystem\DestinationStream; use Flow\Filesystem\Stream\NativeLocalDestinationStream; use Flow\Parquet\Engine\AdaptiveParquetEngine; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; use Flow\Parquet\Exception\InvalidArgumentException; use Flow\Parquet\Exception\RuntimeException; @@ -41,13 +40,6 @@ public function __construct( }; } - public static function arrow( - Compressions $compression = Compressions::SNAPPY, - Options $options = new Options(), - ): self { - return new self($compression, $options, new ArrowParquetEngine()); - } - public static function php(Compressions $compression = Compressions::SNAPPY, Options $options = new Options()): self { return new self($compression, $options, new PhpParquetEngine()); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetFileReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetFileReaderTest.php deleted file mode 100644 index b1d848a4a0..0000000000 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetFileReaderTest.php +++ /dev/null @@ -1,115 +0,0 @@ - new ArrowParquetFileReader( - new ParquetFile(NativeLocalSourceStream::open(path_real(self::FIXTURES . '/structs.parquet'))), - new Options(), - ); - $metadata = $open()->metadata(); - $bytes = 0; - - foreach ($metadata->rowGroups()->all() as $rowGroup) { - $bytes += $rowGroup->totalByteSize(); - } - - static::assertEquals($metadata->schema(), $open()->schema()); - static::assertSame($metadata->rowsNumber(), $open()->rowsNumber()); - static::assertSame($bytes, $open()->totalByteSize()); - static::assertEquals(Reader::php()->read(self::FIXTURES . '/structs.parquet')->metadata(), $metadata); - } - - public function test_every_call_after_close_throws(): void - { - $reader = new ArrowParquetFileReader( - new ParquetFile(NativeLocalSourceStream::open(path_real(self::FIXTURES . '/structs.parquet'))), - new Options(), - ); - $reader->metadata(); - $reader->close(); - - foreach ([ - static fn() => $reader->metadata(), - static fn() => $reader->schema(), - static fn() => $reader->rowsNumber(), - static fn() => $reader->totalByteSize(), - static fn() => $reader->file(), - static fn() => iterator_to_array($reader->readColumns(['struct_flat'], 1, null, null)), - static fn() => $reader->close(), - ] as $call) { - try { - $call(); - static::fail('A call on a closed reader must throw'); - } catch (RuntimeException $exception) { - static::assertSame('Reader is not open', $exception->getMessage()); - } - } - } - - public function test_int96_is_refused_when_it_is_not_read_as_a_datetime(): void - { - $options = (new Options())->set(Option::INT_96_AS_DATETIME, false); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage( - 'Parquet column "ts" holds INT96, which arrow reads only as a datetime (Option::INT_96_AS_DATETIME = ' - . 'true); read the file with \Flow\Parquet\Reader::php()', - ); - - ParquetRows::read(Reader::arrow($options)->read(self::FIXTURES . '/EdgeCases/int96.parquet'), 10); - } - - public function test_a_struct_path_reads_the_values_of_the_php_engine(): void - { - static::assertSame( - ParquetRows::read(Reader::php()->read(self::FIXTURES . '/structs.parquet'), 30, ['struct_flat.int']), - ParquetRows::read(Reader::arrow()->read(self::FIXTURES . '/structs.parquet'), 30, ['struct_flat.int']), - ); - } - - public function test_a_path_into_a_list_is_refused_naming_the_php_reader(): void - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage( - 'Parquet column "list.list.element" (a path into LIST/MAP) is not supported by the arrow Parquet ' - . 'reader; read the file with \Flow\Parquet\Reader::php()', - ); - - ParquetRows::read(Reader::arrow()->read(self::FIXTURES . '/lists.parquet'), 10, ['list.list.element']); - } - - public function test_a_file_that_is_not_parquet_is_refused_when_it_is_opened(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Given file is not valid Parquet file: Invalid Parquet file. Corrupt footer'); - - Reader::arrow()->readStream(new MemorySourceStream('{"not": "parquet"}')); - } -} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php index da00bcbccd..621e61217e 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/CrossEngineTest.php @@ -6,8 +6,8 @@ use Flow\Filesystem\Stream\NativeLocalDestinationStream; use Flow\Filesystem\Stream\NativeLocalSourceStream; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\Options; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; @@ -54,7 +54,7 @@ public function test_arrow_write_arrow_read_roundtrip(): void ['id' => 2, 'label' => 'second', 'big_number' => 2_000_000_000_000], ]; - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $writeStream = NativeLocalDestinationStream::openBlank(path($path)); $engine->writeRows($writeStream, $schema, Compressions::SNAPPY, new Options(), $inputData); @@ -90,7 +90,7 @@ public function test_arrow_write_php_read(): void ['id' => 20, 'name' => 'beta', 'active' => false], ]; - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $stream = NativeLocalDestinationStream::openBlank(path($path)); $engine->writeRows($stream, $schema, Compressions::SNAPPY, new Options(), $inputData); @@ -151,7 +151,7 @@ public function test_php_write_arrow_read(): void (new Writer(engine: new PhpParquetEngine()))->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'name', 'value'], diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php index 56f7315fca..6e26df80fe 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/EngineParityTest.php @@ -4,6 +4,7 @@ namespace Flow\Parquet\Tests\Integration\Engine; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\Reader; @@ -50,7 +51,11 @@ public function test_both_engines_decode_the_same_float32_bytes_identically(): v ]); static::assertSame( - iterator_to_array(Reader::arrow()->read($path)->values()), + iterator_to_array( + (new Reader(engine: new RustParquetEngine())) + ->read($path) + ->values(), + ), iterator_to_array(Reader::php()->read($path)->values()), ); } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php index e7e615af4f..2d0048446f 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ReadColumnsTest.php @@ -13,6 +13,7 @@ use Flow\Parquet\ParquetFile\Schema\Repetition; use Flow\Parquet\Tests\Context\TestParquetFile; use Flow\Parquet\Tests\Integration\IO\ParquetIntegrationTestCase; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use Generator; use PHPUnit\Framework\Attributes\DataProvider; @@ -25,7 +26,7 @@ final class ReadColumnsTest extends ParquetIntegrationTestCase { /** - * @return Generator, list>}> + * @return Generator, int, ?int, ?int, list, list>}> */ public static function chunkings(): Generator { @@ -45,13 +46,14 @@ public static function chunkings(): Generator */ #[DataProvider('chunkings')] public function test_chunks_follow_batch_size_limit_and_offset( - ParquetEngine $engine, + string $engineClass, int $batchSize, ?int $limit, ?int $offset, array $sizes, array $ids, ): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); (new Writer())->write( diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibParityTest.php similarity index 81% rename from src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php rename to src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibParityTest.php index 583641d16c..5032b05caf 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibParityTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibParityTest.php @@ -4,6 +4,7 @@ namespace Flow\Parquet\Tests\Integration\Engine; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\Exception\DataConversionException; use Flow\Parquet\Exception\InvalidArgumentException; use Flow\Parquet\Exception\RuntimeException; @@ -27,7 +28,7 @@ #[Group('native-extension')] #[RequiresPhpExtension('arrow')] -final class NativeLibParityTest extends TestCase +final class RustLibParityTest extends TestCase { /** * The 5000-row pagination fixture is read through a window crossing 5 row groups, skipping inside the first. @@ -66,7 +67,16 @@ public function test_a_fixture_reads_the_values_of_the_php_engine( ): void { static::assertSame( var_export(ParquetRows::read(Reader::php()->read($path), $batchSize, [], $limit, $offset), true), - var_export(ParquetRows::read(Reader::arrow()->read($path), $batchSize, [], $limit, $offset), true), + var_export( + ParquetRows::read( + (new Reader(engine: new RustParquetEngine()))->read($path), + $batchSize, + [], + $limit, + $offset, + ), + true, + ), ); } @@ -76,7 +86,10 @@ public function test_every_type_reads_the_values_of_the_php_engine(): void static::assertSame( var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $bytes), 2), true), - var_export(ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 2), true), + var_export( + ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $bytes), 2), + true, + ), ); } @@ -86,7 +99,7 @@ public function test_an_interval_column_is_refused_naming_it_and_the_php_reader( static::assertSame( ParquetRows::read(Reader::php()->read($path), 100, ['id']), - ParquetRows::read(Reader::arrow()->read($path), 100, ['id']), + ParquetRows::read((new Reader(engine: new RustParquetEngine()))->read($path), 100, ['id']), ); $this->expectException(RuntimeException::class); @@ -95,7 +108,7 @@ public function test_an_interval_column_is_refused_naming_it_and_the_php_reader( . 'with \Flow\Parquet\Reader::php()', ); - ParquetRows::read(Reader::arrow()->read($path), 100); + ParquetRows::read((new Reader(engine: new RustParquetEngine()))->read($path), 100); } public function test_a_uint64_above_php_int_max_is_refused_by_both_engines(): void @@ -112,7 +125,7 @@ public function test_a_uint64_above_php_int_max_is_refused_by_both_engines(): vo $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Parquet column "u64" row 0 holds a value out of the range arrow stores it in'); - ParquetRows::read(Reader::arrow()->read($path), 100); + ParquetRows::read((new Reader(engine: new RustParquetEngine()))->read($path), 100); } #[TestWith(['double_key', 'float'])] @@ -126,7 +139,7 @@ public function test_a_map_key_a_php_array_cannot_hold_is_refused_by_both_engine static::assertSame( ParquetRows::read(Reader::php()->read($path), 10, ['id']), - ParquetRows::read(Reader::arrow()->read($path), 10, ['id']), + ParquetRows::read((new Reader(engine: new RustParquetEngine()))->read($path), 10, ['id']), ); try { @@ -139,6 +152,6 @@ public function test_a_map_key_a_php_array_cannot_hold_is_refused_by_both_engine $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage("Map key of Parquet column \"{$column}\" must be int or string, got {$type}"); - ParquetRows::read(Reader::arrow()->read($path), 10, [$column]); + ParquetRows::read((new Reader(engine: new RustParquetEngine()))->read($path), 10, [$column]); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibRegressionTest.php similarity index 73% rename from src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php rename to src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibRegressionTest.php index f78d3d3be0..d080c07c5f 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibRegressionTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibRegressionTest.php @@ -7,6 +7,7 @@ use DateTimeImmutable; use DateTimeZone; use Flow\Filesystem\Stream\NativeLocalSourceStream; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\ConvertedType; @@ -36,7 +37,7 @@ #[Group('native-extension')] #[RequiresPhpExtension('arrow')] -final class NativeLibRegressionTest extends TestCase +final class RustLibRegressionTest extends TestCase { public const string PAGINATION = __DIR__ . '/../IO/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'; @@ -51,7 +52,12 @@ public function test_an_offset_read_reads_only_the_footer_and_the_row_group_it_n } $stream = new ReadCountingSourceStream(NativeLocalSourceStream::open(path_real(self::PAGINATION))); - $rows = iterator_to_array(Reader::arrow()->readStream($stream)->values([], 10, 4990), false); + $rows = iterator_to_array( + (new Reader(engine: new RustParquetEngine())) + ->readStream($stream) + ->values([], 10, 4990), + false, + ); static::assertCount(10, $rows); static::assertLessThanOrEqual($footer + 8 + $group, $stream->bytes); @@ -61,7 +67,12 @@ public function test_a_full_read_reads_the_file_about_once(): void { $stream = new ReadCountingSourceStream(NativeLocalSourceStream::open(path_real(self::PAGINATION))); - static::assertCount(5000, iterator_to_array(Reader::arrow()->readStream($stream)->values(), false)); + static::assertCount(5000, iterator_to_array( + (new Reader(engine: new RustParquetEngine())) + ->readStream($stream) + ->values(), + false, + )); static::assertLessThanOrEqual((int) filesize(self::PAGINATION) + (64 * 1024), $stream->bytes); } @@ -70,26 +81,44 @@ public function test_invalid_utf8_is_refused_naming_column_and_row(): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Parquet column "name" row 1 holds a string that is not valid UTF-8'); - MemoryParquetFile::written(Writer::arrow(), Schema::with(FlatColumn::string('name')), [ - ['name' => 'ok'], - ['name' => "\xFF\xFE"], - ]); + MemoryParquetFile::written( + new Writer(engine: new RustParquetEngine()), + Schema::with(FlatColumn::string('name')), + [ + ['name' => 'ok'], + ['name' => "\xFF\xFE"], + ], + ); } public function test_a_time_of_a_day_and_an_hour_keeps_its_day(): void { $interval = (new DateTimeImmutable('2024-01-01 00:00:00'))->diff(new DateTimeImmutable('2024-01-02 01:00:00')); - $bytes = MemoryParquetFile::written(Writer::arrow(), Schema::with(FlatColumn::time('t')), [['t' => $interval]]); + $bytes = MemoryParquetFile::written( + new Writer(engine: new RustParquetEngine()), + Schema::with(FlatColumn::time('t')), + [['t' => $interval]], + ); static::assertSame( var_export($interval, true), - var_export(ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 10)[0]['t'], true), + var_export( + ParquetRows::read( + MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $bytes), + 10, + )[0]['t'], + true, + ), ); } public function test_int96_reads_exactly_outside_the_nanosecond_range(): void { $values = array_column( - ParquetRows::read(Reader::arrow()->read(__DIR__ . '/../IO/Fixtures/EdgeCases/int96.parquet'), 10), + ParquetRows::read( + (new Reader(engine: new RustParquetEngine()))->read(__DIR__ + . '/../IO/Fixtures/EdgeCases/int96.parquet'), + 10, + ), 'ts', ); @@ -110,10 +139,13 @@ public function test_dates_are_utc_and_times_carry_their_day_count(): void static::assertSame( var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $bytes), 1), true), - var_export(ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 1), true), + var_export( + ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $bytes), 1), + true, + ), ); static::assertStringContainsString("'timezone' => 'UTC'", var_export( - ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 1)[0]['d'], + ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $bytes), 1)[0]['d'], true, )); } @@ -132,14 +164,14 @@ public function test_a_logical_only_unsigned_integer_reads_as_itself_through_bot ); static::assertSame( [['u' => 4_000_000_000]], - ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 1), + ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $bytes), 1), ); } public function test_a_schema_read_from_an_arrow_rs_file_rewritten_by_the_php_engine_opens_in_arrow(): void { $arrow = MemoryParquetFile::written( - Writer::arrow(), + new Writer(engine: new RustParquetEngine()), Schema::with( new FlatColumn('i8', PhysicalType::INT32, ConvertedType::INT_8), new FlatColumn('u32', PhysicalType::INT32, ConvertedType::UINT_32), @@ -153,7 +185,7 @@ public function test_a_schema_read_from_an_arrow_rs_file_rewritten_by_the_php_en static::assertGreaterThan(0, strlen($rewritten)); static::assertSame( [['i8' => -5, 'u32' => 4_000_000_000]], - ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $rewritten), 1), + ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $rewritten), 1), ); } @@ -177,7 +209,10 @@ public function test_times_of_day_and_longer_read_as_the_php_engine_reads_them() static::assertSame( var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $bytes), 1_000), true), - var_export(ParquetRows::read(MemoryParquetFile::read(Reader::arrow(), $bytes), 1_000), true), + var_export( + ParquetRows::read(MemoryParquetFile::read(new Reader(engine: new RustParquetEngine()), $bytes), 1_000), + true, + ), ); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibWriteParityTest.php similarity index 90% rename from src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php rename to src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibWriteParityTest.php index fb597fb88c..8731148b26 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/NativeLibWriteParityTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustLibWriteParityTest.php @@ -4,8 +4,8 @@ namespace Flow\Parquet\Tests\Integration\Engine; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\Exception\ValidationException; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\Reader; @@ -26,7 +26,7 @@ #[Group('native-extension')] #[RequiresPhpExtension('arrow')] -final class NativeLibWriteParityTest extends TestCase +final class RustLibWriteParityTest extends TestCase { /** * @return Generator @@ -45,7 +45,10 @@ public function test_both_writers_accept_and_refuse_the_same(string $target, str { $written = []; - foreach (['php' => Writer::php(), 'native' => Writer::arrow()] as $engine => $writer) { + foreach ([ + 'php' => Writer::php(), + 'native' => new Writer(engine: new RustParquetEngine()), + ] as $engine => $writer) { try { $written[$engine] = MemoryParquetFile::written( $writer, @@ -70,7 +73,7 @@ public function test_both_writers_accept_and_refuse_the_same(string $target, str #[DataProvider('cells')] public function test_the_column_door_accepts_and_refuses_what_the_row_door_does(string $target, string $input): void { - foreach ([new PhpParquetEngine(), new ArrowParquetEngine()] as $engine) { + foreach ([new PhpParquetEngine(), new RustParquetEngine()] as $engine) { $outcomes = []; foreach (['batch', 'columns'] as $door) { @@ -125,7 +128,11 @@ public function test_the_php_engine_refuses_what_it_used_to_write_wrongly(string public function test_every_type_writes_the_same_through_both_writers(): void { $php = MemoryParquetFile::written(Writer::php(), EveryType::schema(), EveryType::rows()); - $native = MemoryParquetFile::written(Writer::arrow(), EveryType::schema(), EveryType::rows()); + $native = MemoryParquetFile::written( + new Writer(engine: new RustParquetEngine()), + EveryType::schema(), + EveryType::rows(), + ); static::assertSame( var_export(ParquetRows::read(MemoryParquetFile::read(Reader::php(), $php), 3), true), diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustParquetEngineReadTest.php similarity index 95% rename from src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php rename to src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustParquetEngineReadTest.php index 5f0d652018..3e90a088c4 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineReadTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustParquetEngineReadTest.php @@ -5,7 +5,7 @@ namespace Flow\Parquet\Tests\Integration\Engine; use Flow\Filesystem\Stream\NativeLocalSourceStream; -use Flow\Parquet\Engine\ArrowParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\ListElement; @@ -25,7 +25,7 @@ use function range; #[Group('native-extension')] -final class ArrowParquetEngineReadTest extends TestCase +final class RustParquetEngineReadTest extends TestCase { protected function setUp(): void { @@ -58,7 +58,7 @@ public function test_read_flat_columns(): void (new Writer())->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'name', 'active', 'score'], @@ -94,7 +94,7 @@ public function test_read_nested_lists(): void (new Writer())->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'tags'], @@ -124,7 +124,7 @@ public function test_read_nested_maps(): void (new Writer())->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'metadata'], @@ -160,7 +160,7 @@ public function test_read_nested_structs(): void (new Writer())->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'address'], @@ -194,7 +194,7 @@ public function test_read_nested_uuid_as_canonical_strings(): void 'uuid_list' => [$uuid, $uuid], ]]); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['top_uuid', 'body', 'uuid_list'], @@ -232,7 +232,7 @@ public function test_read_with_column_projection(): void (new Writer())->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id', 'name'], @@ -256,7 +256,7 @@ public function test_read_with_limit(): void (new Writer())->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id'], @@ -280,7 +280,7 @@ public function test_read_with_limit_and_offset(): void (new Writer())->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id'], @@ -304,7 +304,7 @@ public function test_read_with_offset(): void (new Writer())->write($path, $schema, $inputData); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $chunks = iterator_to_array( $engine->openForRead(NativeLocalSourceStream::open(path_real($path)))->readColumns( ['id'], diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustParquetEngineWriteTest.php similarity index 94% rename from src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php rename to src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustParquetEngineWriteTest.php index c78ba168ad..ab83e87154 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/ArrowParquetEngineWriteTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/Engine/RustParquetEngineWriteTest.php @@ -5,7 +5,7 @@ namespace Flow\Parquet\Tests\Integration\Engine; use Flow\Filesystem\Stream\NativeLocalDestinationStream; -use Flow\Parquet\Engine\ArrowParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\Options; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; @@ -26,7 +26,7 @@ use function str_repeat; #[Group('native-extension')] -final class ArrowParquetEngineWriteTest extends TestCase +final class RustParquetEngineWriteTest extends TestCase { protected function setUp(): void { @@ -57,7 +57,7 @@ public function test_write_flat_columns_readable_by_php_engine(): void ['id' => 3, 'name' => 'Charlie', 'active' => true, 'score' => 92.1], ]; - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $stream = NativeLocalDestinationStream::openBlank(path($path)); $engine->writeRows($stream, $schema, Compressions::SNAPPY, new Options(), $inputData); @@ -91,7 +91,7 @@ public function test_write_nested_types(): void ['id' => 2, 'tags' => ['python'], 'address' => ['city' => 'Warsaw']], ]; - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $stream = NativeLocalDestinationStream::openBlank(path($path)); $engine->writeRows($stream, $schema, Compressions::SNAPPY, new Options(), $inputData); @@ -113,7 +113,7 @@ public function test_write_with_gzip_compression(): void $inputData = array_map(static fn(int $i): array => ['id' => $i, 'data' => 'value_' . $i], range(1, 20)); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $stream = NativeLocalDestinationStream::openBlank(path($path)); $engine->writeRows($stream, $schema, Compressions::GZIP, new Options(), $inputData); @@ -134,7 +134,7 @@ public function test_write_with_snappy_compression(): void $inputData = array_map(static fn(int $i): array => ['id' => $i, 'data' => str_repeat('a', 100)], range(1, 50)); - $engine = new ArrowParquetEngine(); + $engine = new RustParquetEngine(); $stream = NativeLocalDestinationStream::openBlank(path($path)); $engine->writeRows($stream, $schema, Compressions::SNAPPY, new Options(), $inputData); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/CompressionTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/CompressionTest.php index 2708cba8a3..3e30b3b0be 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/CompressionTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/CompressionTest.php @@ -6,7 +6,6 @@ use Faker\Factory; use Flow\Parquet\Consts; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; @@ -14,6 +13,7 @@ use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; @@ -29,8 +29,9 @@ class CompressionTest extends ParquetIntegrationTestCase { #[Group('brotli-extension')] #[DataProvider('engine_provider')] - public function test_writing_and_reading_file_with_brotli_compression(ParquetEngine $engine): void + public function test_writing_and_reading_file_with_brotli_compression(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); if (!extension_loaded('brotli')) { static::markTestSkipped('The Brotli extension is not available'); } @@ -85,8 +86,9 @@ public function test_writing_and_reading_file_with_brotli_compression(ParquetEng } #[DataProvider('engine_provider')] - public function test_writing_and_reading_file_with_gzip_compression(ParquetEngine $engine): void + public function test_writing_and_reading_file_with_gzip_compression(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(compression: Compressions::GZIP, engine: $engine); @@ -138,8 +140,9 @@ public function test_writing_and_reading_file_with_gzip_compression(ParquetEngin #[Group('lz4-extension')] #[DataProvider('engine_provider')] - public function test_writing_and_reading_file_with_lz4_compression(ParquetEngine $engine): void + public function test_writing_and_reading_file_with_lz4_compression(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); if (!extension_loaded('lz4')) { static::markTestSkipped('The lz4 extension is not available'); } @@ -195,8 +198,9 @@ public function test_writing_and_reading_file_with_lz4_compression(ParquetEngine #[Group('lz4-extension')] #[DataProvider('engine_provider')] - public function test_writing_and_reading_file_with_lz4_raw_compression(ParquetEngine $engine): void + public function test_writing_and_reading_file_with_lz4_raw_compression(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); if (!extension_loaded('lz4')) { static::markTestSkipped('The lz4 extension is not available'); } @@ -252,8 +256,9 @@ public function test_writing_and_reading_file_with_lz4_raw_compression(ParquetEn #[Group('snappy-extension')] #[DataProvider('engine_provider')] - public function test_writing_and_reading_file_with_snappy_compression(ParquetEngine $engine): void + public function test_writing_and_reading_file_with_snappy_compression(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); if (!extension_loaded('snappy')) { static::markTestSkipped('The snappy extension is not available'); } @@ -308,8 +313,9 @@ public function test_writing_and_reading_file_with_snappy_compression(ParquetEng } #[DataProvider('engine_provider')] - public function test_writing_and_reading_file_with_snappy_polyfill(ParquetEngine $engine): void + public function test_writing_and_reading_file_with_snappy_polyfill(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); if (extension_loaded('snappy')) { static::markTestSkipped('The snappy extension is available'); } @@ -364,8 +370,9 @@ public function test_writing_and_reading_file_with_snappy_polyfill(ParquetEngine } #[DataProvider('engine_provider')] - public function test_writing_and_reading_file_with_uncompressed_compression(ParquetEngine $engine): void + public function test_writing_and_reading_file_with_uncompressed_compression(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(compression: Compressions::UNCOMPRESSED, engine: $engine); @@ -417,8 +424,9 @@ public function test_writing_and_reading_file_with_uncompressed_compression(Parq #[Group('zstd-extension')] #[DataProvider('engine_provider')] - public function test_writing_and_reading_file_with_zstd_compression(ParquetEngine $engine): void + public function test_writing_and_reading_file_with_zstd_compression(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); if (!extension_loaded('zstd')) { static::markTestSkipped('The Zstd extension is not available'); } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/EdgeCasesReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/EdgeCasesReadingTest.php index 138f7c4137..56f2087287 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/EdgeCasesReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/EdgeCasesReadingTest.php @@ -4,8 +4,8 @@ namespace Flow\Parquet\Tests\Integration\IO; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\Reader; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use PHPUnit\Framework\Attributes\DataProvider; use function iterator_to_array; @@ -13,8 +13,9 @@ class EdgeCasesReadingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_nonullable_impala(ParquetEngine $engine): void + public function test_nonullable_impala(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = __DIR__ . '/Fixtures/EdgeCases/nonnullable.impala.parquet'; $reader = (new Reader(engine: $engine))->read($path); @@ -61,8 +62,9 @@ public function test_nonullable_impala(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_read_datapage_v2_snappy_list(ParquetEngine $engine): void + public function test_read_datapage_v2_snappy_list(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); static::assertSame( [ ['a' => 'abc', 'b' => 1, 'c' => 2.0, 'd' => true, 'e' => [1, 2, 3]], @@ -81,8 +83,9 @@ public function test_read_datapage_v2_snappy_list(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_read_null_list(ParquetEngine $engine): void + public function test_read_null_list(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = __DIR__ . '/Fixtures/EdgeCases/null_list.parquet'; $reader = (new Reader(engine: $engine))->read($path); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/FixedLenByteArrayReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/FixedLenByteArrayReadingTest.php index ba8bd06043..8ad5600156 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/FixedLenByteArrayReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/FixedLenByteArrayReadingTest.php @@ -4,12 +4,12 @@ namespace Flow\Parquet\Tests\Integration\IO; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\Repetition; use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; @@ -20,8 +20,9 @@ class FixedLenByteArrayReadingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_reading_and_writing_fixed_len_byte_array_without_logical_type(ParquetEngine $engine): void + public function test_reading_and_writing_fixed_len_byte_array_without_logical_type(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $schema = Schema::with(FlatColumn::fixedSizeByteArray('raw_bytes', 8, Repetition::REQUIRED)); @@ -55,8 +56,9 @@ public function test_reading_and_writing_fixed_len_byte_array_without_logical_ty } #[DataProvider('engine_provider')] - public function test_reading_fixed_len_byte_array_returns_raw_string(ParquetEngine $engine): void + public function test_reading_fixed_len_byte_array_returns_raw_string(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $schema = Schema::with(FlatColumn::fixedSizeByteArray('data', 16, Repetition::REQUIRED)); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ListsReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ListsReadingTest.php index 1342665f61..ba0064f50e 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ListsReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ListsReadingTest.php @@ -4,15 +4,16 @@ namespace Flow\Parquet\Tests\Integration\IO; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\Reader; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use PHPUnit\Framework\Attributes\DataProvider; class ListsReadingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_reading_list_column(ParquetEngine $engine): void + public function test_reading_list_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/lists.parquet'); @@ -35,8 +36,9 @@ public function test_reading_list_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_list_column_with_limit(ParquetEngine $engine): void + public function test_reading_list_column_with_limit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/lists.parquet'); @@ -58,8 +60,9 @@ public function test_reading_list_column_with_limit(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_list_nested_column(ParquetEngine $engine): void + public function test_reading_list_nested_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/lists.parquet'); @@ -89,8 +92,9 @@ public function test_reading_list_nested_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_list_nullable_column(ParquetEngine $engine): void + public function test_reading_list_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/lists.parquet'); @@ -117,8 +121,9 @@ public function test_reading_list_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_list_of_structures_column(ParquetEngine $engine): void + public function test_reading_list_of_structures_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/lists.parquet'); @@ -149,8 +154,9 @@ public function test_reading_list_of_structures_column(ParquetEngine $engine): v } #[DataProvider('engine_provider')] - public function test_reading_list_of_structures_nullable_column(ParquetEngine $engine): void + public function test_reading_list_of_structures_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/lists.parquet'); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ListsWritingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ListsWritingTest.php index 9bfaff3161..a6a54eda82 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ListsWritingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ListsWritingTest.php @@ -6,7 +6,6 @@ use Faker\Factory; use Flow\Parquet\Consts; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\ListElement; @@ -14,6 +13,7 @@ use Flow\Parquet\ParquetFile\Schema\Repetition; use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; @@ -26,8 +26,9 @@ class ListsWritingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_writing_empty_lists_of_ints(ParquetEngine $engine): void + public function test_writing_empty_lists_of_ints(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -55,8 +56,9 @@ public function test_writing_empty_lists_of_ints(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_list_of_decimals(ParquetEngine $engine): void + public function test_writing_list_of_decimals(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -77,8 +79,9 @@ public function test_writing_list_of_decimals(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_list_of_ints(ParquetEngine $engine): void + public function test_writing_list_of_ints(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -110,8 +113,9 @@ public function test_writing_list_of_ints(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_list_of_strings(ParquetEngine $engine): void + public function test_writing_list_of_strings(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -143,8 +147,9 @@ public function test_writing_list_of_strings(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_list_of_structures(ParquetEngine $engine): void + public function test_writing_list_of_structures(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -182,8 +187,9 @@ public function test_writing_list_of_structures(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_list_with_nullable_elements(ParquetEngine $engine): void + public function test_writing_list_with_nullable_elements(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -217,8 +223,9 @@ public function test_writing_list_with_nullable_elements(ParquetEngine $engine): } #[DataProvider('engine_provider')] - public function test_writing_list_with_nullable_list_values(ParquetEngine $engine): void + public function test_writing_list_with_nullable_list_values(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -252,8 +259,9 @@ public function test_writing_list_with_nullable_list_values(ParquetEngine $engin } #[DataProvider('engine_provider')] - public function test_writing_nullable_list_of_ints(ParquetEngine $engine): void + public function test_writing_nullable_list_of_ints(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -287,8 +295,9 @@ public function test_writing_nullable_list_of_ints(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_nullable_list_of_structures(ParquetEngine $engine): void + public function test_writing_nullable_list_of_structures(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -328,8 +337,9 @@ public function test_writing_nullable_list_of_structures(ParquetEngine $engine): } #[DataProvider('engine_provider')] - public function test_writing_nullable_list_of_structures_with_required_fields(ParquetEngine $engine): void + public function test_writing_nullable_list_of_structures_with_required_fields(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -365,8 +375,9 @@ public function test_writing_nullable_list_of_structures_with_required_fields(Pa } #[DataProvider('engine_provider')] - public function test_writing_nullable_lists_of_ints(ParquetEngine $engine): void + public function test_writing_nullable_lists_of_ints(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/LogicalTypesReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/LogicalTypesReadingTest.php index 06bf2f44f3..ebed7b0692 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/LogicalTypesReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/LogicalTypesReadingTest.php @@ -5,7 +5,6 @@ namespace Flow\Parquet\Tests\Integration\IO; use Flow\Parquet\Engine\PhpParquetEngine; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\ConvertedType; use Flow\Parquet\ParquetFile\Schema\FlatColumn; @@ -14,6 +13,7 @@ use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TemporalValues; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; @@ -22,8 +22,9 @@ final class LogicalTypesReadingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_reading_converted_type_only_columns(ParquetEngine $engine): void + public function test_reading_converted_type_only_columns(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); (new Writer(engine: new PhpParquetEngine()))->write( @@ -72,8 +73,9 @@ public function test_reading_converted_type_only_columns(ParquetEngine $engine): } #[DataProvider('engine_provider')] - public function test_reading_dates(ParquetEngine $engine): void + public function test_reading_dates(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); static::assertSame( [ ['d' => '2020-01-02 00:00:00.000000 +00:00'], @@ -89,8 +91,9 @@ public function test_reading_dates(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_fixed_len_decimals(ParquetEngine $engine): void + public function test_reading_fixed_len_decimals(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); static::assertSame( [ [ @@ -111,8 +114,9 @@ public function test_reading_fixed_len_decimals(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_int_backed_decimals(ParquetEngine $engine): void + public function test_reading_int_backed_decimals(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); static::assertSame( [ ['dec9' => 12345.67, 'dec18' => 1234567890123456.8], @@ -128,8 +132,9 @@ public function test_reading_int_backed_decimals(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_times_in_every_unit(ParquetEngine $engine): void + public function test_reading_times_in_every_unit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); static::assertSame( [ ['t_ms' => '03:04:05.678000', 't_us' => '03:04:05.678901', 't_ns' => '03:04:05.678901'], @@ -145,8 +150,9 @@ public function test_reading_times_in_every_unit(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_timestamps_in_every_unit(ParquetEngine $engine): void + public function test_reading_timestamps_in_every_unit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); static::assertSame( [ [ diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/LogicalTypesWritingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/LogicalTypesWritingTest.php index b69e676ae7..20d71d3257 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/LogicalTypesWritingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/LogicalTypesWritingTest.php @@ -6,7 +6,6 @@ use DateTimeImmutable; use DateTimeZone; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\LogicalType; @@ -18,6 +17,7 @@ use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TemporalValues; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; @@ -27,8 +27,10 @@ final class LogicalTypesWritingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_pair_provider')] - public function test_dates_are_the_wall_clock_day(ParquetEngine $writer, ParquetEngine $reader): void + public function test_dates_are_the_wall_clock_day(string $writerClass, string $readerClass): void { + $writer = ParquetEngineMother::create($writerClass); + $reader = ParquetEngineMother::create($readerClass); $path = TestParquetFile::path($this); (new Writer(engine: $writer))->write($path, Schema::with(FlatColumn::date('d')), [ @@ -52,8 +54,10 @@ public function test_dates_are_the_wall_clock_day(ParquetEngine $writer, Parquet } #[DataProvider('engine_pair_provider')] - public function test_decimals_round_half_away_from_zero(ParquetEngine $writer, ParquetEngine $reader): void + public function test_decimals_round_half_away_from_zero(string $writerClass, string $readerClass): void { + $writer = ParquetEngineMother::create($writerClass); + $reader = ParquetEngineMother::create($readerClass); $path = TestParquetFile::path($this); (new Writer(engine: $writer))->write($path, Schema::with(FlatColumn::decimal('d', 9, 2)), [ @@ -76,8 +80,10 @@ public function test_decimals_round_half_away_from_zero(ParquetEngine $writer, P } #[DataProvider('engine_pair_provider')] - public function test_decimals_round_trip(ParquetEngine $writer, ParquetEngine $reader): void + public function test_decimals_round_trip(string $writerClass, string $readerClass): void { + $writer = ParquetEngineMother::create($writerClass); + $reader = ParquetEngineMother::create($readerClass); $path = TestParquetFile::path($this); $rows = [ ['d9' => 12345.67, 'd38' => 12345.67, 'i32' => 12345.67, 'i64' => 12345.67, 'ba' => 12345.67], @@ -132,8 +138,10 @@ public function test_decimals_round_trip(ParquetEngine $writer, ParquetEngine $r } #[DataProvider('engine_pair_provider')] - public function test_times_round_trip_in_every_unit(ParquetEngine $writer, ParquetEngine $reader): void + public function test_times_round_trip_in_every_unit(string $writerClass, string $readerClass): void { + $writer = ParquetEngineMother::create($writerClass); + $reader = ParquetEngineMother::create($readerClass); $path = TestParquetFile::path($this); $time = (new DateTimeImmutable('2020-01-01 00:00:00 UTC'))->diff( new DateTimeImmutable('2020-01-01 03:04:05.678901 UTC'), @@ -168,8 +176,10 @@ public function test_times_round_trip_in_every_unit(ParquetEngine $writer, Parqu } #[DataProvider('engine_pair_provider')] - public function test_timestamps_round_trip_in_every_unit(ParquetEngine $writer, ParquetEngine $reader): void + public function test_timestamps_round_trip_in_every_unit(string $writerClass, string $readerClass): void { + $writer = ParquetEngineMother::create($writerClass); + $reader = ParquetEngineMother::create($readerClass); $path = TestParquetFile::path($this); $instant = new DateTimeImmutable('2020-01-02 04:04:05.678901 +01:00'); $preEpoch = new DateTimeImmutable('1969-12-31 23:59:58.5 UTC'); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/MapsReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/MapsReadingTest.php index bd9682cdfb..fcafb31aea 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/MapsReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/MapsReadingTest.php @@ -4,8 +4,8 @@ namespace Flow\Parquet\Tests\Integration\IO; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\Reader; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use PHPUnit\Framework\Attributes\DataProvider; use function array_key_first; @@ -13,8 +13,9 @@ class MapsReadingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_reading_map_column(ParquetEngine $engine): void + public function test_reading_map_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); @@ -37,8 +38,9 @@ public function test_reading_map_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_map_nullable_column(ParquetEngine $engine): void + public function test_reading_map_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); @@ -65,8 +67,9 @@ public function test_reading_map_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_map_of_complex_lists(ParquetEngine $engine): void + public function test_reading_map_of_complex_lists(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); @@ -95,8 +98,9 @@ public function test_reading_map_of_complex_lists(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_map_of_list_of_map_of_lists(ParquetEngine $engine): void + public function test_reading_map_of_list_of_map_of_lists(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); @@ -130,8 +134,9 @@ public function test_reading_map_of_list_of_map_of_lists(ParquetEngine $engine): } #[DataProvider('engine_provider')] - public function test_reading_map_of_lists(ParquetEngine $engine): void + public function test_reading_map_of_lists(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); @@ -156,8 +161,9 @@ public function test_reading_map_of_lists(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_map_of_maps_column(ParquetEngine $engine): void + public function test_reading_map_of_maps_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); @@ -181,8 +187,9 @@ public function test_reading_map_of_maps_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_map_of_struct_of_structs_column(ParquetEngine $engine): void + public function test_reading_map_of_struct_of_structs_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); @@ -216,8 +223,9 @@ public function test_reading_map_of_struct_of_structs_column(ParquetEngine $engi } #[DataProvider('engine_provider')] - public function test_reading_map_of_struct_of_structs_column_with_limit(ParquetEngine $engine): void + public function test_reading_map_of_struct_of_structs_column_with_limit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); @@ -250,8 +258,9 @@ public function test_reading_map_of_struct_of_structs_column_with_limit(ParquetE } #[DataProvider('engine_provider')] - public function test_reading_map_of_structs_column(ParquetEngine $engine): void + public function test_reading_map_of_structs_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/maps.parquet'); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/MapsWritingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/MapsWritingTest.php index 4e744070a8..c15ce552ab 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/MapsWritingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/MapsWritingTest.php @@ -6,13 +6,13 @@ use Faker\Factory; use Flow\Parquet\Consts; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\MapKey; use Flow\Parquet\ParquetFile\Schema\MapValue; use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; @@ -25,8 +25,9 @@ class MapsWritingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_writing_empty_map_of_int_int(ParquetEngine $engine): void + public function test_writing_empty_map_of_int_int(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -54,8 +55,9 @@ public function test_writing_empty_map_of_int_int(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_map_of_int_int(ParquetEngine $engine): void + public function test_writing_map_of_int_int(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -87,8 +89,9 @@ public function test_writing_map_of_int_int(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_map_of_int_int_with_all_maps_null(ParquetEngine $engine): void + public function test_writing_map_of_int_int_with_all_maps_null(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -116,8 +119,9 @@ public function test_writing_map_of_int_int_with_all_maps_null(ParquetEngine $en } #[DataProvider('engine_provider')] - public function test_writing_map_of_int_string(ParquetEngine $engine): void + public function test_writing_map_of_int_string(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -149,8 +153,9 @@ public function test_writing_map_of_int_string(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_map_of_string_decimal(ParquetEngine $engine): void + public function test_writing_map_of_string_decimal(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -171,8 +176,9 @@ public function test_writing_map_of_string_decimal(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_nullable_map_of_int_int(ParquetEngine $engine): void + public function test_writing_nullable_map_of_int_int(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/PaginationTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/PaginationTest.php index 7c92bda586..26d0c20456 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/PaginationTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/PaginationTest.php @@ -8,7 +8,6 @@ use Flow\Parquet\Exception\InvalidArgumentException; use Flow\Parquet\Option; use Flow\Parquet\Options; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\ListElement; @@ -17,6 +16,7 @@ use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use Generator; use PHPUnit\Framework\Attributes\DataProvider; @@ -54,8 +54,9 @@ public static function engine_with_offset_provider(): Generator } #[DataProvider('engine_provider')] - public function test_offset_past_first_page_of_multi_page_column(ParquetEngine $engine): void + public function test_offset_past_first_page_of_multi_page_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); Writer::php(options: Options::default()->set(Option::PAGE_SIZE_BYTES, 100)->set( @@ -78,8 +79,9 @@ public function test_offset_past_first_page_of_multi_page_column(ParquetEngine $ } #[DataProvider('engine_provider')] - public function test_reading_last_100_rows(ParquetEngine $engine): void + public function test_reading_last_100_rows(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = __DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'; $totalRows = (new Reader(engine: $engine)) @@ -102,11 +104,12 @@ public function test_reading_last_100_rows(ParquetEngine $engine): void #[DataProvider('engine_with_offset_provider')] public function test_setting_offset_larger_than_file( - ParquetEngine $engine, + string $engineClass, int $offset, ?int $limit, int $results, ): void { + $engine = ParquetEngineMother::create($engineClass); $path = __DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'; static::assertCount( @@ -120,8 +123,9 @@ public function test_setting_offset_larger_than_file( } #[DataProvider('engine_provider')] - public function test_setting_setting_limit_to_negative(ParquetEngine $engine): void + public function test_setting_setting_limit_to_negative(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = __DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'; $this->expectException(InvalidArgumentException::class); @@ -135,8 +139,9 @@ public function test_setting_setting_limit_to_negative(ParquetEngine $engine): v } #[DataProvider('engine_provider')] - public function test_setting_setting_offset_to_negative(ParquetEngine $engine): void + public function test_setting_setting_offset_to_negative(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = __DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'; $this->expectException(InvalidArgumentException::class); @@ -150,8 +155,9 @@ public function test_setting_setting_offset_to_negative(ParquetEngine $engine): } #[DataProvider('engine_provider')] - public function test_columns_refuses_a_batch_size_below_one(ParquetEngine $engine): void + public function test_columns_refuses_a_batch_size_below_one(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Batch size must be greater than 0'); @@ -163,8 +169,9 @@ public function test_columns_refuses_a_batch_size_below_one(ParquetEngine $engin } #[DataProvider('engine_provider')] - public function test_columns_refuses_a_limit_of_zero(ParquetEngine $engine): void + public function test_columns_refuses_a_limit_of_zero(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Limit must be greater than 0'); @@ -176,8 +183,9 @@ public function test_columns_refuses_a_limit_of_zero(ParquetEngine $engine): voi } #[DataProvider('engine_provider')] - public function test_columns_refuses_a_negative_offset_without_a_limit(ParquetEngine $engine): void + public function test_columns_refuses_a_negative_offset_without_a_limit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Offset must be greater than or equal to 0'); @@ -189,8 +197,9 @@ public function test_columns_refuses_a_negative_offset_without_a_limit(ParquetEn } #[DataProvider('engine_provider')] - public function test_columns_refuses_an_unknown_column(ParquetEngine $engine): void + public function test_columns_refuses_an_unknown_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Column "nope" does not exist'); @@ -202,8 +211,9 @@ public function test_columns_refuses_an_unknown_column(ParquetEngine $engine): v } #[DataProvider('engine_provider')] - public function test_values_equal_the_zip_of_columns(ParquetEngine $engine): void + public function test_values_equal_the_zip_of_columns(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $file = (new Reader(engine: $engine))->read(__DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'); @@ -221,8 +231,9 @@ public function test_values_equal_the_zip_of_columns(ParquetEngine $engine): voi } #[DataProvider('engine_provider')] - public function test_simple_pagination_on_small_row_group_size(ParquetEngine $engine): void + public function test_simple_pagination_on_small_row_group_size(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = __DIR__ . '/Fixtures/pagination_row_group_1kb_5k_rows.snappy.parquet'; // Uncomment only to apply changes to the dataset diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ParquetIntegrationTestCase.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ParquetIntegrationTestCase.php index b85bbc681e..30f496767d 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ParquetIntegrationTestCase.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ParquetIntegrationTestCase.php @@ -4,8 +4,9 @@ namespace Flow\Parquet\Tests\Integration\IO; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; +use Flow\Parquet\ParquetEngine; use Flow\Parquet\Tests\Context\TestParquetFile; use PHPUnit\Framework\TestCase; @@ -14,30 +15,30 @@ abstract class ParquetIntegrationTestCase extends TestCase { /** - * @return array + * @return array}> */ public static function engine_provider(): array { - $engines = ['php' => [new PhpParquetEngine()]]; + $engines = ['php' => [PhpParquetEngine::class]]; if (extension_loaded('arrow')) { - $engines['arrow'] = [new ArrowParquetEngine()]; + $engines['arrow'] = [RustParquetEngine::class]; } return $engines; } /** - * @return array + * @return array, class-string}> */ public static function engine_pair_provider(): array { - $pairs = ['php/php' => [new PhpParquetEngine(), new PhpParquetEngine()]]; + $pairs = ['php/php' => [PhpParquetEngine::class, PhpParquetEngine::class]]; if (extension_loaded('arrow')) { - $pairs['php/arrow'] = [new PhpParquetEngine(), new ArrowParquetEngine()]; - $pairs['arrow/php'] = [new ArrowParquetEngine(), new PhpParquetEngine()]; - $pairs['arrow/arrow'] = [new ArrowParquetEngine(), new ArrowParquetEngine()]; + $pairs['php/arrow'] = [PhpParquetEngine::class, RustParquetEngine::class]; + $pairs['arrow/php'] = [RustParquetEngine::class, PhpParquetEngine::class]; + $pairs['arrow/arrow'] = [RustParquetEngine::class, RustParquetEngine::class]; } return $pairs; diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ReaderTest.php index 4e18fda017..f30fdc967d 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ReaderTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/ReaderTest.php @@ -4,9 +4,9 @@ namespace Flow\Parquet\Tests\Integration\IO; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Page\ColumnPageHeader; use Flow\Parquet\Reader; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use PHPUnit\Framework\Attributes\DataProvider; use function array_map; @@ -16,8 +16,9 @@ class ReaderTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_reading_columns_with_multiple_data_pages(ParquetEngine $engine): void + public function test_reading_columns_with_multiple_data_pages(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); // File generated with https://gist.github.com/norberttech/325df9166bbdb33e18dffa94c1a033c4 $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/multiple_pages.parquet'); @@ -48,8 +49,9 @@ public function test_reading_columns_with_multiple_data_pages(ParquetEngine $eng } #[DataProvider('engine_provider')] - public function test_reading_required_columns(ParquetEngine $engine): void + public function test_reading_required_columns(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); // File generated with https://gist.github.com/norberttech/01322f61dca77cfde5161e31e94463ef $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/columns.required.parquet'); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SchemaReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SchemaReadingTest.php index 6d62ab6041..8908e21f24 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SchemaReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SchemaReadingTest.php @@ -4,7 +4,6 @@ namespace Flow\Parquet\Tests\Integration\IO; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\RowGroup\StatisticsReader; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; @@ -13,13 +12,15 @@ use Flow\Parquet\ParquetFile\Schema\MapValue; use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\Reader; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use PHPUnit\Framework\Attributes\DataProvider; class SchemaReadingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_reading_lists_schema_ddl(ParquetEngine $engine): void + public function test_reading_lists_schema_ddl(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $schema = new Schema(NestedColumn::create('schema', [ @@ -52,8 +53,9 @@ public function test_reading_lists_schema_ddl(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_maps_schema_ddl(ParquetEngine $engine): void + public function test_reading_maps_schema_ddl(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $schema = Schema::with( @@ -108,8 +110,9 @@ public function test_reading_maps_schema_ddl(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_primitives_schema_ddl(ParquetEngine $engine): void + public function test_reading_primitives_schema_ddl(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $schema = Schema::with( @@ -152,8 +155,9 @@ public function test_reading_primitives_schema_ddl(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_statistics(ParquetEngine $engine): void + public function test_reading_statistics(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $metadata = (new Reader(engine: $engine)) ->read(__DIR__ . '/Fixtures/primitives.parquet') ->metadata(); @@ -164,8 +168,9 @@ public function test_reading_statistics(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_structs_schema_ddl(ParquetEngine $engine): void + public function test_reading_structs_schema_ddl(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $schema = Schema::with( diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesReadingTest.php index 6adf1b3e87..50f580208b 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesReadingTest.php @@ -6,9 +6,9 @@ use DateInterval; use DateTimeImmutable; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema\PhysicalType; use Flow\Parquet\Reader; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use PHPUnit\Framework\Attributes\DataProvider; use function array_filter; @@ -21,8 +21,9 @@ class SimpleTypesReadingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_reading_bool_column(ParquetEngine $engine): void + public function test_reading_bool_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -38,8 +39,9 @@ public function test_reading_bool_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_bool_column_with_limit(ParquetEngine $engine): void + public function test_reading_bool_column_with_limit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -54,8 +56,9 @@ public function test_reading_bool_column_with_limit(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_bool_nullable_column(ParquetEngine $engine): void + public function test_reading_bool_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -72,8 +75,9 @@ public function test_reading_bool_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_bool_nullable_column_with_limit(ParquetEngine $engine): void + public function test_reading_bool_nullable_column_with_limit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -92,8 +96,9 @@ public function test_reading_bool_nullable_column_with_limit(ParquetEngine $engi } #[DataProvider('engine_provider')] - public function test_reading_date_column(ParquetEngine $engine): void + public function test_reading_date_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -111,8 +116,9 @@ public function test_reading_date_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_date_nullable_column(ParquetEngine $engine): void + public function test_reading_date_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -134,8 +140,9 @@ public function test_reading_date_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_decimal_column(ParquetEngine $engine): void + public function test_reading_decimal_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -152,8 +159,9 @@ public function test_reading_decimal_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_decimal_nullable_column(ParquetEngine $engine): void + public function test_reading_decimal_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -177,8 +185,9 @@ public function test_reading_decimal_nullable_column(ParquetEngine $engine): voi } #[DataProvider('engine_provider')] - public function test_reading_delta_binary_packed_encoded_integers(ParquetEngine $engine): void + public function test_reading_delta_binary_packed_encoded_integers(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/delta_binary_acked_encoded_integers.parquet'); @@ -224,8 +233,9 @@ public function test_reading_delta_binary_packed_encoded_integers(ParquetEngine } #[DataProvider('engine_provider')] - public function test_reading_every_delta_binary_packed_value(ParquetEngine $engine): void + public function test_reading_every_delta_binary_packed_value(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); static::assertSame( array_map( static fn(int $n): array => [ @@ -245,8 +255,9 @@ public function test_reading_every_delta_binary_packed_value(ParquetEngine $engi } #[DataProvider('engine_provider')] - public function test_reading_double_column(ParquetEngine $engine): void + public function test_reading_double_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -263,8 +274,9 @@ public function test_reading_double_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_double_nullable_column(ParquetEngine $engine): void + public function test_reading_double_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -285,8 +297,9 @@ public function test_reading_double_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_enum_column(ParquetEngine $engine): void + public function test_reading_enum_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -304,8 +317,9 @@ public function test_reading_enum_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_float_column(ParquetEngine $engine): void + public function test_reading_float_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -322,8 +336,9 @@ public function test_reading_float_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_float_nullable_column(ParquetEngine $engine): void + public function test_reading_float_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -344,8 +359,9 @@ public function test_reading_float_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_int32_column(ParquetEngine $engine): void + public function test_reading_int32_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -363,8 +379,9 @@ public function test_reading_int32_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_int32_nullable_column(ParquetEngine $engine): void + public function test_reading_int32_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -386,8 +403,9 @@ public function test_reading_int32_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_int64(ParquetEngine $engine): void + public function test_reading_int64(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -406,8 +424,9 @@ public function test_reading_int64(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_int64_nullable_column(ParquetEngine $engine): void + public function test_reading_int64_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -429,8 +448,9 @@ public function test_reading_int64_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_json_column(ParquetEngine $engine): void + public function test_reading_json_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -448,8 +468,9 @@ public function test_reading_json_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_json_nullable_column(ParquetEngine $engine): void + public function test_reading_json_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -471,8 +492,9 @@ public function test_reading_json_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_string_column(ParquetEngine $engine): void + public function test_reading_string_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -490,8 +512,9 @@ public function test_reading_string_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_string_nullable_column(ParquetEngine $engine): void + public function test_reading_string_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -513,8 +536,9 @@ public function test_reading_string_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_time_column(ParquetEngine $engine): void + public function test_reading_time_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -532,8 +556,9 @@ public function test_reading_time_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_time_nullable_column(ParquetEngine $engine): void + public function test_reading_time_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -555,8 +580,9 @@ public function test_reading_time_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_timestamp_column(ParquetEngine $engine): void + public function test_reading_timestamp_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -574,8 +600,9 @@ public function test_reading_timestamp_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_timestamp_nullable_column(ParquetEngine $engine): void + public function test_reading_timestamp_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -600,8 +627,9 @@ public function test_reading_timestamp_nullable_column(ParquetEngine $engine): v } #[DataProvider('engine_provider')] - public function test_reading_uuid_column(ParquetEngine $engine): void + public function test_reading_uuid_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); @@ -619,8 +647,9 @@ public function test_reading_uuid_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_uuid_nullable_column(ParquetEngine $engine): void + public function test_reading_uuid_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/primitives.parquet'); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php index 5fb6cc028a..efb5403813 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/SimpleTypesWritingTest.php @@ -7,13 +7,13 @@ use DateTimeImmutable; use Faker\Factory; use Flow\Parquet\Consts; -use Flow\Parquet\Engine\ArrowParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; -use Flow\Parquet\ParquetEngine; +use Flow\Parquet\Engine\RustParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; @@ -73,10 +73,10 @@ public static function decimalPrecisionProvider(): array 'precision 8, scale 8' => [8, 8, 0.99999999], ]; - $engines = ['php' => new PhpParquetEngine()]; + $engines = ['php' => PhpParquetEngine::class]; if (extension_loaded('arrow')) { - $engines['arrow'] = new ArrowParquetEngine(); + $engines['arrow'] = RustParquetEngine::class; } $result = []; @@ -91,8 +91,9 @@ public static function decimalPrecisionProvider(): array } #[DataProvider('engine_provider')] - public function test_writing_bool_column(ParquetEngine $engine): void + public function test_writing_bool_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -122,8 +123,9 @@ public function test_writing_bool_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_bool_nullable_column(ParquetEngine $engine): void + public function test_writing_bool_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -153,8 +155,9 @@ public function test_writing_bool_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_date_column(ParquetEngine $engine): void + public function test_writing_date_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -186,8 +189,9 @@ public function test_writing_date_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_date_column_before_1970(ParquetEngine $engine): void + public function test_writing_date_column_before_1970(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -222,8 +226,9 @@ public function test_writing_date_column_before_1970(ParquetEngine $engine): voi } #[DataProvider('engine_provider')] - public function test_writing_date_nullable_column(ParquetEngine $engine): void + public function test_writing_date_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -257,8 +262,9 @@ public function test_writing_date_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_decimal_column(ParquetEngine $engine): void + public function test_writing_decimal_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -291,11 +297,12 @@ public function test_writing_decimal_column(ParquetEngine $engine): void #[DataProvider('decimalPrecisionProvider')] public function test_writing_decimal_column_with_different_precisions( - ParquetEngine $engine, + string $engineClass, int $precision, int $scale, float $maxValue, ): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -331,8 +338,9 @@ public function test_writing_decimal_column_with_different_precisions( } #[DataProvider('engine_provider')] - public function test_writing_decimal_nullable_column(ParquetEngine $engine): void + public function test_writing_decimal_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -364,8 +372,9 @@ public function test_writing_decimal_nullable_column(ParquetEngine $engine): voi } #[DataProvider('engine_provider')] - public function test_writing_double_column(ParquetEngine $engine): void + public function test_writing_double_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -397,8 +406,9 @@ public function test_writing_double_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_double_nullable_column(ParquetEngine $engine): void + public function test_writing_double_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -430,8 +440,9 @@ public function test_writing_double_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_enum_column(ParquetEngine $engine): void + public function test_writing_enum_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -463,8 +474,9 @@ public function test_writing_enum_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_float_column(ParquetEngine $engine): void + public function test_writing_float_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -487,8 +499,9 @@ public function test_writing_float_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_float_nullable_column(ParquetEngine $engine): void + public function test_writing_float_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -513,8 +526,9 @@ public function test_writing_float_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_int32_column(ParquetEngine $engine): void + public function test_writing_int32_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -546,8 +560,9 @@ public function test_writing_int32_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_int32_nullable_column(ParquetEngine $engine): void + public function test_writing_int32_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -579,8 +594,9 @@ public function test_writing_int32_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_int64(ParquetEngine $engine): void + public function test_writing_int64(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -611,8 +627,9 @@ public function test_writing_int64(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_int64_nullable_column(ParquetEngine $engine): void + public function test_writing_int64_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -643,8 +660,9 @@ public function test_writing_int64_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_json_column(ParquetEngine $engine): void + public function test_writing_json_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -680,8 +698,9 @@ public function test_writing_json_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_json_nullable_column(ParquetEngine $engine): void + public function test_writing_json_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -719,8 +738,9 @@ public function test_writing_json_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_string_column(ParquetEngine $engine): void + public function test_writing_string_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -751,8 +771,9 @@ public function test_writing_string_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_string_nullable_column(ParquetEngine $engine): void + public function test_writing_string_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -783,8 +804,9 @@ public function test_writing_string_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_time_column(ParquetEngine $engine): void + public function test_writing_time_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -815,8 +837,9 @@ public function test_writing_time_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_time_nullable_column(ParquetEngine $engine): void + public function test_writing_time_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -849,8 +872,9 @@ public function test_writing_time_nullable_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_timestamp_column(ParquetEngine $engine): void + public function test_writing_timestamp_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -881,8 +905,9 @@ public function test_writing_timestamp_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_timestamp_column_for_years_before_1970(ParquetEngine $engine): void + public function test_writing_timestamp_column_for_years_before_1970(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -913,8 +938,9 @@ public function test_writing_timestamp_column_for_years_before_1970(ParquetEngin } #[DataProvider('engine_provider')] - public function test_writing_timestamp_nullable_column(ParquetEngine $engine): void + public function test_writing_timestamp_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -945,8 +971,9 @@ public function test_writing_timestamp_nullable_column(ParquetEngine $engine): v } #[DataProvider('engine_provider')] - public function test_writing_uuid_column(ParquetEngine $engine): void + public function test_writing_uuid_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -977,8 +1004,9 @@ public function test_writing_uuid_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_uuid_nullable_column(ParquetEngine $engine): void + public function test_writing_uuid_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/StructsReadingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/StructsReadingTest.php index 6c2779ba9e..e41955f8e9 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/StructsReadingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/StructsReadingTest.php @@ -4,15 +4,16 @@ namespace Flow\Parquet\Tests\Integration\IO; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\Reader; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use PHPUnit\Framework\Attributes\DataProvider; class StructsReadingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_reading_struct_deeply_nested_column(ParquetEngine $engine): void + public function test_reading_struct_deeply_nested_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -58,8 +59,9 @@ public function test_reading_struct_deeply_nested_column(ParquetEngine $engine): } #[DataProvider('engine_provider')] - public function test_reading_struct_deeply_nested_column_with_limit(ParquetEngine $engine): void + public function test_reading_struct_deeply_nested_column_with_limit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -104,8 +106,9 @@ public function test_reading_struct_deeply_nested_column_with_limit(ParquetEngin } #[DataProvider('engine_provider')] - public function test_reading_struct_flat_column(ParquetEngine $engine): void + public function test_reading_struct_flat_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -129,8 +132,9 @@ public function test_reading_struct_flat_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_struct_flat_nullable_column(ParquetEngine $engine): void + public function test_reading_struct_flat_nullable_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -158,8 +162,9 @@ public function test_reading_struct_flat_nullable_column(ParquetEngine $engine): } #[DataProvider('engine_provider')] - public function test_reading_struct_nested_column(ParquetEngine $engine): void + public function test_reading_struct_nested_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -187,8 +192,9 @@ public function test_reading_struct_nested_column(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_reading_struct_nested_with_list_of_lists_column(ParquetEngine $engine): void + public function test_reading_struct_nested_with_list_of_lists_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -215,8 +221,9 @@ public function test_reading_struct_nested_with_list_of_lists_column(ParquetEngi } #[DataProvider('engine_provider')] - public function test_reading_struct_nested_with_list_of_maps_column(ParquetEngine $engine): void + public function test_reading_struct_nested_with_list_of_maps_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -243,8 +250,9 @@ public function test_reading_struct_nested_with_list_of_maps_column(ParquetEngin } #[DataProvider('engine_provider')] - public function test_reading_struct_nested_with_map_of_list_of_ints_column(ParquetEngine $engine): void + public function test_reading_struct_nested_with_map_of_list_of_ints_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -275,8 +283,9 @@ public function test_reading_struct_nested_with_map_of_list_of_ints_column(Parqu } #[DataProvider('engine_provider')] - public function test_reading_struct_nested_with_map_of_string_map_of_string_string_column(ParquetEngine $engine): void + public function test_reading_struct_nested_with_map_of_string_map_of_string_string_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -315,8 +324,9 @@ public function test_reading_struct_nested_with_map_of_string_map_of_string_stri } #[DataProvider('engine_provider')] - public function test_reading_struct_nested_with_map_of_string_map_of_string_string_column_with_limit(ParquetEngine $engine): void + public function test_reading_struct_nested_with_map_of_string_map_of_string_string_column_with_limit(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); @@ -354,8 +364,9 @@ public function test_reading_struct_nested_with_map_of_string_map_of_string_stri } #[DataProvider('engine_provider')] - public function test_reading_struct_with_list_and_map_of_structs_column(ParquetEngine $engine): void + public function test_reading_struct_with_list_and_map_of_structs_column(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $reader = new Reader(engine: $engine); $file = $reader->read(__DIR__ . '/Fixtures/structs.parquet'); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/StructsWritingTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/StructsWritingTest.php index 4b229ebccc..6f4d5829e7 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/StructsWritingTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/StructsWritingTest.php @@ -6,13 +6,13 @@ use Faker\Factory; use Flow\Parquet\Consts; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\ListElement; use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; @@ -25,8 +25,9 @@ class StructsWritingTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_writing_flat_nullable_structure(ParquetEngine $engine): void + public function test_writing_flat_nullable_structure(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -77,8 +78,9 @@ public function test_writing_flat_nullable_structure(ParquetEngine $engine): voi } #[DataProvider('engine_provider')] - public function test_writing_flat_structure(ParquetEngine $engine): void + public function test_writing_flat_structure(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); @@ -127,8 +129,9 @@ public function test_writing_flat_structure(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_flat_structure_with_nullable_elements(ParquetEngine $engine): void + public function test_writing_flat_structure_with_nullable_elements(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $path = TestParquetFile::path($this); $writer = new Writer(engine: $engine); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/WriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/WriterTest.php index c79e2bbb8a..4c4dd581f4 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/WriterTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Integration/IO/WriterTest.php @@ -13,7 +13,6 @@ use Flow\Parquet\Engine\PhpParquetEngine; use Flow\Parquet\Option; use Flow\Parquet\Options; -use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Schema; use Flow\Parquet\ParquetFile\Schema\FlatColumn; use Flow\Parquet\ParquetFile\Schema\ListElement; @@ -22,6 +21,7 @@ use Flow\Parquet\ParquetFile\Schema\NestedColumn; use Flow\Parquet\Reader; use Flow\Parquet\Tests\Context\TestParquetFile; +use Flow\Parquet\Tests\Mother\ParquetEngineMother; use Flow\Parquet\Writer; use PHPUnit\Framework\Attributes\DataProvider; use RuntimeException; @@ -37,8 +37,9 @@ class WriterTest extends ParquetIntegrationTestCase { #[DataProvider('engine_provider')] - public function test_a_close_that_throws_leaves_the_writer_closed(ParquetEngine $engine): void + public function test_a_close_that_throws_leaves_the_writer_closed(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $writer->openForStream( new FailingCloseDestinationStream(memory_filesystem()->writeTo(path('memory://file.parquet'))), @@ -62,8 +63,9 @@ public function test_a_close_that_throws_leaves_the_writer_closed(ParquetEngine } #[DataProvider('engine_provider')] - public function test_closing_not_open_writer(ParquetEngine $engine): void + public function test_closing_not_open_writer(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $this->expectException(RuntimeException::class); @@ -91,8 +93,9 @@ public function test_created_by_metadata(): void } #[DataProvider('engine_provider')] - public function test_opening_already_open_writer(ParquetEngine $engine): void + public function test_opening_already_open_writer(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $path = TestParquetFile::path($this); @@ -108,8 +111,9 @@ public function test_opening_already_open_writer(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writers_sharing_one_engine_write_independent_files(ParquetEngine $engine): void + public function test_writers_sharing_one_engine_write_independent_files(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $memory = memory_filesystem(); $schema = Schema::with(FlatColumn::int32('id')); $first = new Writer(engine: $engine); @@ -144,8 +148,9 @@ public function test_writers_sharing_one_engine_write_independent_files(ParquetE } #[DataProvider('engine_provider')] - public function test_writing_all_column_types(ParquetEngine $engine): void + public function test_writing_all_column_types(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $schema = Schema::with( FlatColumn::int32('int32_col'), FlatColumn::int64('int64_col'), @@ -212,8 +217,9 @@ public function test_writing_all_column_types(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_batch_to_not_open_stream(ParquetEngine $engine): void + public function test_writing_batch_to_not_open_stream(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $this->expectException(RuntimeException::class); @@ -223,8 +229,9 @@ public function test_writing_batch_to_not_open_stream(ParquetEngine $engine): vo } #[DataProvider('engine_provider')] - public function test_writing_column_statistics(ParquetEngine $engine): void + public function test_writing_column_statistics(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(options: Options::default()->set(Option::WRITER_VERSION, 1), engine: $engine); $path = TestParquetFile::path($this); @@ -250,8 +257,9 @@ public function test_writing_column_statistics(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_column_statistics_with_null_values(ParquetEngine $engine): void + public function test_writing_column_statistics_with_null_values(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $schema = Schema::with( FlatColumn::string('all_null'), FlatColumn::string('all_string'), @@ -311,8 +319,9 @@ public function test_writing_data_page_v2_statistics(): void } #[DataProvider('engine_provider')] - public function test_writing_in_batches_to_file(ParquetEngine $engine): void + public function test_writing_in_batches_to_file(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $path = TestParquetFile::path($this); @@ -342,8 +351,9 @@ public function test_writing_in_batches_to_file(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_in_batches_to_file_without_explicit_close(ParquetEngine $engine): void + public function test_writing_in_batches_to_file_without_explicit_close(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $path = TestParquetFile::path($this); @@ -372,8 +382,9 @@ public function test_writing_in_batches_to_file_without_explicit_close(ParquetEn } #[DataProvider('engine_provider')] - public function test_writing_in_batches_to_stream(ParquetEngine $engine): void + public function test_writing_in_batches_to_stream(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $path = TestParquetFile::path($this); @@ -404,8 +415,9 @@ public function test_writing_in_batches_to_stream(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_one_row_that_is_nullable(ParquetEngine $engine): void + public function test_writing_one_row_that_is_nullable(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $schema = Schema::with($column = FlatColumn::int32('id')); @@ -447,8 +459,9 @@ public function test_writing_one_row_that_is_nullable(ParquetEngine $engine): vo } #[DataProvider('engine_provider')] - public function test_writing_row_to_not_open_stream(ParquetEngine $engine): void + public function test_writing_row_to_not_open_stream(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $this->expectException(RuntimeException::class); @@ -458,8 +471,9 @@ public function test_writing_row_to_not_open_stream(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_to_file(ParquetEngine $engine): void + public function test_writing_to_file(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $path = TestParquetFile::path($this); @@ -481,8 +495,9 @@ public function test_writing_to_file(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_to_file_v2(ParquetEngine $engine): void + public function test_writing_to_file_v2(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(options: Options::default()->set(Option::WRITER_VERSION, 2), engine: $engine); $path = TestParquetFile::path($this); @@ -511,8 +526,9 @@ public function test_writing_to_file_v2(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_to_stream(ParquetEngine $engine): void + public function test_writing_to_stream(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $writer = new Writer(engine: $engine); $path = TestParquetFile::path($this); @@ -547,8 +563,9 @@ public function test_writing_to_stream(ParquetEngine $engine): void } #[DataProvider('engine_provider')] - public function test_writing_with_all_nullable_columns(ParquetEngine $engine): void + public function test_writing_with_all_nullable_columns(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $schema = Schema::with(FlatColumn::int32('a'), FlatColumn::string('b'), FlatColumn::boolean('c')); $rows = [ @@ -573,8 +590,9 @@ public function test_writing_with_all_nullable_columns(ParquetEngine $engine): v } #[DataProvider('engine_provider')] - public function test_writing_with_dictionary_encoding(ParquetEngine $engine): void + public function test_writing_with_dictionary_encoding(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $schema = Schema::with(FlatColumn::int32('id')->makeRequired(), FlatColumn::string('category')); $rows = []; @@ -598,8 +616,9 @@ public function test_writing_with_dictionary_encoding(ParquetEngine $engine): vo } #[DataProvider('engine_provider')] - public function test_writing_with_empty_lists_and_maps(ParquetEngine $engine): void + public function test_writing_with_empty_lists_and_maps(string $engineClass): void { + $engine = ParquetEngineMother::create($engineClass); $schema = Schema::with( FlatColumn::int32('id')->makeRequired(), NestedColumn::list('items', ListElement::string()), diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Mother/ParquetEngineMother.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Mother/ParquetEngineMother.php new file mode 100644 index 0000000000..62e54afe08 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Mother/ParquetEngineMother.php @@ -0,0 +1,22 @@ + new RustParquetEngine(), + PhpParquetEngine::class => new PhpParquetEngine(), + default => throw new InvalidArgumentException("Unknown Parquet engine {$class}"), + }; + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php index bc82b390f0..f627389a2f 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php @@ -4,33 +4,58 @@ namespace Flow\Parquet\Tests\Unit\Engine; +use Flow\Filesystem\Stream\MemorySourceStream; +use Flow\Filesystem\Stream\StringDestinationStream; +use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\AdaptiveParquetEngine; -use Flow\Parquet\Engine\ArrowParquetEngine; -use Flow\Parquet\Engine\PhpParquetEngine; +use Flow\Parquet\Engine\PhpParquetFileReader; +use Flow\Parquet\Engine\PhpParquetFileWriter; +use Flow\Parquet\Engine\RustParquetFileReader; +use Flow\Parquet\Engine\RustParquetFileWriter; +use Flow\Parquet\Options; +use Flow\Parquet\ParquetFile\Compressions; +use Flow\Parquet\ParquetFile\Schema; +use Flow\Parquet\ParquetFile\Schema\FlatColumn; +use Flow\Parquet\Tests\Context\MemoryParquetFile; +use Flow\Parquet\Tests\Mother\ParquetFileWriterMother; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; -use ReflectionClass; use function extension_loaded; +use function Flow\Filesystem\DSL\memory_filesystem; +use function Flow\Filesystem\DSL\path; +use function iterator_to_array; final class AdaptiveParquetEngineTest extends TestCase { - public function test_creates_arrow_engine_when_arrow_is_loaded(): void + public function test_rows_written_through_the_contract_read_back(): void { - if (!extension_loaded('arrow')) { - static::markTestSkipped('This test requires arrow to be loaded'); - } - + $filesystem = memory_filesystem(); $engine = new AdaptiveParquetEngine(); - static::assertInstanceOf( - ArrowParquetEngine::class, - (new ReflectionClass($engine)) - ->getProperty('delegate') - ->getValue($engine), + $engine->writeRows( + $filesystem->writeTo(path('memory://out.parquet')), + Schema::with(FlatColumn::int32('id')), + Compressions::SNAPPY, + new Options(), + [['id' => 1], ['id' => 2]], + ); + + static::assertSame( + [['id' => [1, 2]]], + iterator_to_array( + $engine->openForRead($filesystem->readFrom(path('memory://out.parquet')))->readColumns( + ['id'], + 10, + null, + null, + ), + false, + ), ); } - public function test_creates_php_engine_without_arrow(): void + public function test_without_arrow_files_are_read_and_written_by_the_php_engine(): void { if (extension_loaded('arrow')) { static::markTestSkipped('This test requires arrow not to be loaded'); @@ -39,10 +64,37 @@ public function test_creates_php_engine_without_arrow(): void $engine = new AdaptiveParquetEngine(); static::assertInstanceOf( - PhpParquetEngine::class, - (new ReflectionClass($engine)) - ->getProperty('delegate') - ->getValue($engine), + PhpParquetFileReader::class, + $engine->openForRead(new MemorySourceStream(MemoryParquetFile::threeRowGroups())), + ); + static::assertInstanceOf(PhpParquetFileWriter::class, ParquetFileWriterMother::open( + $engine, + new StringDestinationStream(path('memory://out.parquet')), + )); + } + + #[RequiresPhpExtension('arrow')] + public function test_with_arrow_files_are_read_and_written_by_arrow(): void + { + $engine = new AdaptiveParquetEngine(); + + static::assertInstanceOf( + RustParquetFileReader::class, + $engine->openForRead(new MemorySourceStream(MemoryParquetFile::threeRowGroups())), + ); + static::assertInstanceOf(RustParquetFileWriter::class, ParquetFileWriterMother::open( + $engine, + new StringDestinationStream(path('memory://out.parquet')), + )); + } + + public function test_big_endian_is_read_by_the_php_engine(): void + { + static::assertInstanceOf( + PhpParquetFileReader::class, + (new AdaptiveParquetEngine(ByteOrder::BIG_ENDIAN))->openForRead( + new MemorySourceStream(MemoryParquetFile::threeRowGroups()), + ), ); } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/OptionsConverterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/OptionsConverterTest.php index 98808e7fb3..4d28e05175 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/OptionsConverterTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/Arrow/OptionsConverterTest.php @@ -13,6 +13,28 @@ final class OptionsConverterTest extends TestCase { + public function test_engine_options_default_without_options(): void + { + static::assertSame( + [ + 'INT_96_AS_DATETIME' => true, + 'ARROW_WRITE_BATCH_SIZE' => (new Options())->getInt(Option::ARROW_WRITE_BATCH_SIZE), + ], + OptionsConverter::toEngine(null), + ); + } + + public function test_engine_options_are_read_from_the_options(): void + { + static::assertSame( + ['INT_96_AS_DATETIME' => false, 'ARROW_WRITE_BATCH_SIZE' => 7], + OptionsConverter::toEngine((new Options())->set(Option::INT_96_AS_DATETIME, false)->set( + Option::ARROW_WRITE_BATCH_SIZE, + 7, + )), + ); + } + public function test_arrow_batch_size_is_excluded_when_null(): void { $options = new Options(); diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php deleted file mode 100644 index 2c709b2d16..0000000000 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetEngineTest.php +++ /dev/null @@ -1,71 +0,0 @@ -expectException(RuntimeException::class); - $this->expectExceptionMessage('ArrowParquetEngine requires the arrow extension (flow-php/arrow-ext).'); - - new ArrowParquetEngine(); - } - - #[RequiresPhpExtension('arrow')] - public function test_files_are_read_and_written_through_arrow(): void - { - $engine = new ArrowParquetEngine(); - - static::assertInstanceOf( - ArrowParquetFileReader::class, - $engine->openForRead(new MemorySourceStream(MemoryParquetFile::threeRowGroups())), - ); - static::assertInstanceOf(ArrowParquetFileWriter::class, ParquetFileWriterMother::open( - $engine, - new StringDestinationStream(path('memory://out.parquet')), - )); - } - - #[TestWith([Compressions::UNCOMPRESSED, 'UNCOMPRESSED'])] - #[TestWith([Compressions::SNAPPY, 'SNAPPY'])] - #[TestWith([Compressions::GZIP, 'GZIP'])] - #[TestWith([Compressions::BROTLI, 'BROTLI'])] - #[TestWith([Compressions::LZ4, 'LZ4_RAW'])] - #[TestWith([Compressions::LZ4_RAW, 'LZ4_RAW'])] - #[TestWith([Compressions::ZSTD, 'ZSTD'])] - public function test_map_compression(Compressions $input, string $expected): void - { - static::assertSame($expected, ArrowParquetEngine::mapCompression($input)); - } - - public function test_map_compression_throws_for_lzo(): void - { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('LZO compression is not supported'); - - ArrowParquetEngine::mapCompression(Compressions::LZO); - } -} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php deleted file mode 100644 index 65803951e8..0000000000 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowParquetFileWriterTest.php +++ /dev/null @@ -1,311 +0,0 @@ -writeTo(path('memory://file.parquet'))), - ); - - try { - $file->close(); - static::fail('close() was expected to throw'); - } catch (FilesystemRuntimeException $failure) { - static::assertSame('Closing "memory://file.parquet" failed', $failure->getMessage()); - } - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->close(); - } - - public function test_closing_twice_throws(): void - { - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - memory_filesystem()->writeTo(path('memory://file.parquet')), - ); - $file->close(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->close(); - } - - public function test_closing_writes_a_file_the_reader_reads_back(): void - { - $memory = memory_filesystem(); - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - $memory->writeTo(path('memory://file.parquet')), - ); - - $file->writeRow(['id' => 1]); - $file->writeBatch([['id' => 2]]); - $file->close(); - - static::assertSame( - [['id' => 1], ['id' => 2]], - iterator_to_array( - (new Reader(engine: new PhpParquetEngine())) - ->readStream($memory->readFrom(path('memory://file.parquet'))) - ->values(), - false, - ), - ); - } - - public function test_writing_a_batch_after_close_throws(): void - { - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - memory_filesystem()->writeTo(path('memory://file.parquet')), - ); - $file->close(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->writeBatch([['id' => 1]]); - } - - public function test_writing_a_row_after_close_throws(): void - { - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - memory_filesystem()->writeTo(path('memory://file.parquet')), - ); - $file->close(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->writeRow(['id' => 1]); - } - - public function test_rows_beyond_the_batch_size_are_written_once(): void - { - $memory = memory_filesystem(); - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 2)), - $memory->writeTo(path('memory://file.parquet')), - ); - - $file->writeRow(['id' => 1]); - $file->writeRow(['id' => 2]); - $file->writeRow(['id' => 3]); - $file->close(); - - static::assertSame( - [['id' => 1], ['id' => 2], ['id' => 3]], - iterator_to_array( - (new Reader(engine: new PhpParquetEngine())) - ->readStream($memory->readFrom(path('memory://file.parquet'))) - ->values(), - false, - ), - ); - } - - public function test_it_is_the_writer_the_arrow_engine_opens(): void - { - static::assertInstanceOf(ArrowParquetFileWriter::class, ParquetFileWriterMother::open( - new ArrowParquetEngine(), - memory_filesystem()->writeTo(path('memory://file.parquet')), - )); - } - - public function test_a_refused_row_leaves_the_rows_before_it_written(): void - { - $memory = memory_filesystem(); - $file = ParquetFileWriterMother::open( - new ArrowParquetEngine(), - $memory->writeTo(path('memory://file.parquet')), - ); - - $file->writeRow(['id' => 1]); - - try { - $file->writeRow(['id' => 'two']); - static::fail('a string was written into INT32'); - } catch (ValidationException $refusal) { - static::assertSame('Column "id" row 1: expected int, got string', $refusal->getMessage()); - } - - $file->writeBatch(new ArrayIterator([['id' => 3]])); - $file->close(); - - static::assertSame( - [['id' => 1], ['id' => 3]], - iterator_to_array( - (new Reader(engine: new PhpParquetEngine())) - ->readStream($memory->readFrom(path('memory://file.parquet'))) - ->values(), - false, - ), - ); - } - - public function test_columns_of_different_lengths_are_refused(): void - { - $file = ColumnDoor::open(new ArrowParquetEngine(), ColumnDoor::stream(), Schema::with(FlatColumn::int32('id'))); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('writeColumns() takes lists of one length, got "id": 2, "other": 1'); - - $file->writeColumns(['id' => [1, 2], 'other' => [1]]); - } - - public function test_a_column_the_array_lacks_is_written_as_nulls_and_an_unknown_key_is_ignored(): void - { - $stream = ColumnDoor::stream(); - $file = ColumnDoor::open( - new ArrowParquetEngine(), - $stream, - Schema::with(FlatColumn::int32('id'), FlatColumn::string('name')), - ); - - $file->writeColumns(['id' => [1, 2], 'unknown' => ['a', 'b']]); - $file->writeColumns([]); - $file->close(); - - static::assertSame([['id' => 1, 'name' => null], ['id' => 2, 'name' => null]], ColumnDoor::read($stream)); - } - - public function test_writing_columns_after_close_throws(): void - { - $file = ColumnDoor::open(new ArrowParquetEngine(), ColumnDoor::stream(), Schema::with(FlatColumn::int32('id'))); - $file->close(); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Writer is not open'); - - $file->writeColumns(['id' => [1]]); - } - - public function test_columns_write_the_bytes_a_batch_writes(): void - { - $options = Options::default() - ->set(Option::ROW_GROUP_SIZE_BYTES, 2 * 1024) - ->set(Option::ROW_GROUP_SIZE_CHECK_INTERVAL, 140) - ->set(Option::PAGE_SIZE_BYTES, 256) - ->set(Option::PAGE_SIZE_CHECK_INTERVAL, 26); - $rows = ColumnDoor::rows(600); - $batch = ColumnDoor::stream(); - $columns = ColumnDoor::stream(); - - $file = ColumnDoor::open( - new ArrowParquetEngine($options->set(Option::ARROW_WRITE_BATCH_SIZE, 200)), - $batch, - ColumnDoor::schema(), - $options, - ); - $file->writeRow($rows[0]); - $file->writeBatch(array_slice($rows, 1)); - $file->close(); - - $file = ColumnDoor::open( - new ArrowParquetEngine($options->set(Option::ARROW_WRITE_BATCH_SIZE, 200)), - $columns, - ColumnDoor::schema(), - $options, - ); - $file->writeRow($rows[0]); - $file->writeColumns(ColumnDoor::columns(array_slice($rows, 1))); - $file->close(); - - static::assertTrue($batch->content() === $columns->content()); - static::assertSame($rows, ColumnDoor::read($columns)); - } - - public function test_columns_refuse_the_first_cell_of_the_first_refused_row_and_keep_the_rows_before_it(): void - { - $schema = Schema::with(FlatColumn::int32('a'), FlatColumn::int32('b'), FlatColumn::int32('c')); - $rows = array_map(static fn(int $i): array => ['a' => $i, 'b' => $i, 'c' => $i], range(0, 7)); - $rows[5]['a'] = 'five'; - $rows[2]['c'] = 'two'; - $outcomes = []; - - foreach (['batch', 'columns'] as $door) { - $stream = ColumnDoor::stream(); - $file = ColumnDoor::open(new ArrowParquetEngine(), $stream, $schema); - - try { - $door === 'batch' ? $file->writeBatch($rows) : $file->writeColumns(ColumnDoor::columns($rows)); - static::fail('a string was written into INT32'); - } catch (ValidationException $refusal) { - $file->close(); - $outcomes[$door] = [$refusal->getMessage(), ColumnDoor::read($stream)]; - } - } - - static::assertSame($outcomes['batch'], $outcomes['columns']); - static::assertSame( - [ - 'Column "c" row 2: expected int, got string', - [['a' => 0, 'b' => 0, 'c' => 0], ['a' => 1, 'b' => 1, 'c' => 1]], - ], - $outcomes['columns'], - ); - } - - public function test_a_refusal_past_a_flushed_batch_names_the_row_the_row_door_names(): void - { - $schema = Schema::with(FlatColumn::int32('a')); - $rows = array_map(static fn(int $i): array => ['a' => $i], range(0, 6)); - $rows[5]['a'] = 'five'; - $messages = []; - - foreach (['batch', 'columns'] as $door) { - $file = ColumnDoor::open( - new ArrowParquetEngine(Options::default()->set(Option::ARROW_WRITE_BATCH_SIZE, 2)), - ColumnDoor::stream(), - $schema, - ); - - try { - $door === 'batch' ? $file->writeBatch($rows) : $file->writeColumns(ColumnDoor::columns($rows)); - static::fail('a string was written into INT32'); - } catch (ValidationException $refusal) { - $messages[$door] = $refusal->getMessage(); - } - } - - static::assertSame($messages['batch'], $messages['columns']); - } -} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/RustParquetEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/RustParquetEngineTest.php new file mode 100644 index 0000000000..c9f906815f --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/RustParquetEngineTest.php @@ -0,0 +1,49 @@ +set(Option::INT_96_AS_DATETIME, false)); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Parquet column "ts" holds INT96'); + + $engine->openForRead(NativeLocalSourceStream::open(path_real(__DIR__ + . '/../../Integration/IO/Fixtures/EdgeCases/int96.parquet')))->readColumns(['ts'], 10, null, null); + } + + public function test_lzo_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('LZO compression is not supported by the Arrow engine'); + + (new RustParquetEngine())->openForWrite( + new StringDestinationStream(path('memory://out.parquet')), + Schema::with(FlatColumn::int32('id')), + Compressions::LZO, + new Options(), + ); + } +} diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php index 42d6fbaccc..627e0732df 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/ReaderTest.php @@ -5,31 +5,22 @@ namespace Flow\Parquet\Tests\Unit; use Flow\Filesystem\Stream\NativeLocalSourceStream; -use Flow\Parquet\Engine\ArrowParquetEngine; +use Flow\Parquet\Engine\AdaptiveParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; -use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\Reader; use PHPUnit\Framework\TestCase; use ReflectionClass; -use function extension_loaded; use function Flow\Filesystem\DSL\path_real; final class ReaderTest extends TestCase { - public function test_arrow_factory_creates_reader_with_arrow_engine(): void + public function test_the_default_engine_is_adaptive(): void { - if (!extension_loaded('arrow')) { - $this->expectException(RuntimeException::class); - Reader::arrow(); - - return; - } - - $reader = Reader::arrow(); + $reader = new Reader(); static::assertInstanceOf( - ArrowParquetEngine::class, + AdaptiveParquetEngine::class, (new ReflectionClass($reader)) ->getProperty('engine') ->getValue($reader), diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php index f7abac9e02..e3bf3233d2 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/WriterTest.php @@ -4,25 +4,24 @@ namespace Flow\Parquet\Tests\Unit; +use Flow\Parquet\Engine\AdaptiveParquetEngine; use Flow\Parquet\Engine\PhpParquetEngine; -use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\Writer; use PHPUnit\Framework\TestCase; use ReflectionClass; -use function extension_loaded; - final class WriterTest extends TestCase { - public function test_arrow_factory_throws_when_extension_not_loaded(): void + public function test_the_default_engine_writes(): void { - if (extension_loaded('arrow')) { - static::markTestSkipped('This test requires arrow not to be loaded'); - } - - $this->expectException(RuntimeException::class); + $writer = new Writer(); - Writer::arrow(); + static::assertInstanceOf( + AdaptiveParquetEngine::class, + (new ReflectionClass($writer)) + ->getProperty('engine') + ->getValue($writer), + ); } public function test_php_factory_creates_writer_with_php_engine(): void diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ForeignKeyConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ForeignKeyConstraintTest.php index 38617f6d24..c955a3c430 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ForeignKeyConstraintTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ForeignKeyConstraintTest.php @@ -134,11 +134,9 @@ public function test_on_delete_restrict(): void public function test_on_delete_set_default(): void { - $constraint = ForeignKeyConstraint::create( - ['user_id'], - 'users', - ['id'], - )->onDelete(ReferentialAction::SET_DEFAULT); + $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])->onDelete( + ReferentialAction::SET_DEFAULT, + ); $ast = $constraint->toAst(); @@ -168,11 +166,9 @@ public function test_on_update_cascade(): void public function test_on_update_no_action(): void { - $constraint = ForeignKeyConstraint::create( - ['user_id'], - 'users', - ['id'], - )->onUpdate(ReferentialAction::NO_ACTION); + $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])->onUpdate( + ReferentialAction::NO_ACTION, + ); $ast = $constraint->toAst(); diff --git a/src/lib/telemetry/tests/Flow/Telemetry/Tests/Integration/Telemetry/SignalLimitsIntegrationTest.php b/src/lib/telemetry/tests/Flow/Telemetry/Tests/Integration/Telemetry/SignalLimitsIntegrationTest.php index dca6ea5a78..c7b002aae7 100644 --- a/src/lib/telemetry/tests/Flow/Telemetry/Tests/Integration/Telemetry/SignalLimitsIntegrationTest.php +++ b/src/lib/telemetry/tests/Flow/Telemetry/Tests/Integration/Telemetry/SignalLimitsIntegrationTest.php @@ -129,7 +129,9 @@ public function test_meter_counter_enforces_cardinality_limit(): void static::assertCount(4, $metrics); - $overflowMetrics = array_values(array_filter($metrics, static fn($m) => $m->attributes->has(MetricLimits::OVERFLOW_ATTRIBUTE))); + $overflowMetrics = array_values(array_filter($metrics, static fn($m) => $m->attributes->has( + MetricLimits::OVERFLOW_ATTRIBUTE, + ))); static::assertCount(1, $overflowMetrics); static::assertTrue($overflowMetrics[0]->attributes->get(MetricLimits::OVERFLOW_ATTRIBUTE)); @@ -154,7 +156,9 @@ public function test_meter_histogram_enforces_cardinality_limit(): void static::assertCount(3, $metrics); - $overflowMetrics = array_values(array_filter($metrics, static fn($m) => $m->attributes->has(MetricLimits::OVERFLOW_ATTRIBUTE))); + $overflowMetrics = array_values(array_filter($metrics, static fn($m) => $m->attributes->has( + MetricLimits::OVERFLOW_ATTRIBUTE, + ))); static::assertCount(1, $overflowMetrics); } @@ -175,7 +179,9 @@ public function test_meter_overflow_aggregates_excess_measurements(): void $metrics = $counter->collect(); - $overflowMetrics = array_values(array_filter($metrics, static fn($m) => $m->attributes->has(MetricLimits::OVERFLOW_ATTRIBUTE))); + $overflowMetrics = array_values(array_filter($metrics, static fn($m) => $m->attributes->has( + MetricLimits::OVERFLOW_ATTRIBUTE, + ))); static::assertSame(12, $overflowMetrics[0]->value); } @@ -196,7 +202,9 @@ public function test_meter_overflow_attribute_set_has_correct_attribute(): void static::assertCount(2, $metrics); - $overflowMetrics = array_values(array_filter($metrics, static fn($m) => $m->attributes->has(MetricLimits::OVERFLOW_ATTRIBUTE))); + $overflowMetrics = array_values(array_filter($metrics, static fn($m) => $m->attributes->has( + MetricLimits::OVERFLOW_ATTRIBUTE, + ))); static::assertTrue($overflowMetrics[0]->attributes->get(MetricLimits::OVERFLOW_ATTRIBUTE)); static::assertCount(1, $overflowMetrics[0]->attributes->normalize()); diff --git a/src/lib/telemetry/tests/Flow/Telemetry/Tests/Unit/DSL/FunctionsTest.php b/src/lib/telemetry/tests/Flow/Telemetry/Tests/Unit/DSL/FunctionsTest.php index 90177baa7f..af6bb024d3 100644 --- a/src/lib/telemetry/tests/Flow/Telemetry/Tests/Unit/DSL/FunctionsTest.php +++ b/src/lib/telemetry/tests/Flow/Telemetry/Tests/Unit/DSL/FunctionsTest.php @@ -195,7 +195,9 @@ public function test_meter_provider_with_limits(): void $metrics = $counter->collect(); static::assertCount(6, $metrics); - $overflowMetrics = array_filter($metrics, static fn($m) => $m->attributes->has(MetricLimits::OVERFLOW_ATTRIBUTE)); + $overflowMetrics = array_filter($metrics, static fn($m) => $m->attributes->has( + MetricLimits::OVERFLOW_ATTRIBUTE, + )); static::assertCount(1, $overflowMetrics); } diff --git a/src/lib/telemetry/tests/Flow/Telemetry/Tests/Unit/Logger/Middleware/AttributeFilteringLogMiddlewareTest.php b/src/lib/telemetry/tests/Flow/Telemetry/Tests/Unit/Logger/Middleware/AttributeFilteringLogMiddlewareTest.php index 6a1b214909..402edd78bd 100644 --- a/src/lib/telemetry/tests/Flow/Telemetry/Tests/Unit/Logger/Middleware/AttributeFilteringLogMiddlewareTest.php +++ b/src/lib/telemetry/tests/Flow/Telemetry/Tests/Unit/Logger/Middleware/AttributeFilteringLogMiddlewareTest.php @@ -241,7 +241,9 @@ public function test_does_not_leak_synthetic_severity_keys_onto_kept_entry(): vo static::assertSame($entry, $processed); static::assertFalse($processed->record->attributes->has(AttributeFilteringLogMiddleware::SEVERITY_KEY)); - static::assertFalse($processed->record->attributes->has(AttributeFilteringLogMiddleware::SEVERITY_NAME_KEY)); + static::assertFalse($processed->record->attributes->has( + AttributeFilteringLogMiddleware::SEVERITY_NAME_KEY, + )); } finally { $tmp->remove(); } diff --git a/tools/box/composer.lock b/tools/box/composer.lock index f69c122e6f..8d4b3744c2 100644 --- a/tools/box/composer.lock +++ b/tools/box/composer.lock @@ -902,16 +902,16 @@ }, { "name": "composer/semver", - "version": "3.4.4", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" + "reference": "f7a296f4c4cf8cb8bb83e35d6951a406bb11afa5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "url": "https://api.github.com/repos/composer/semver/zipball/f7a296f4c4cf8cb8bb83e35d6951a406bb11afa5", + "reference": "f7a296f4c4cf8cb8bb83e35d6951a406bb11afa5", "shasum": "" }, "require": { @@ -953,7 +953,7 @@ "homepage": "http://robbast.nl" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "Version comparison library that offers utilities, version constraint parsing and validation.", "keywords": [ "semantic", "semver", @@ -963,7 +963,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.4" + "source": "https://github.com/composer/semver/tree/3.5.0" }, "funding": [ { @@ -975,7 +975,7 @@ "type": "github" } ], - "time": "2025-08-20T19:15:30+00:00" + "time": "2026-09-24T14:38:51+00:00" }, { "name": "composer/xdebug-handler", @@ -1534,16 +1534,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "6.12.0", + "version": "6.13.1", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "8ef236a1a37df364b518b7411a4b5bb95b040d79" + "reference": "e54aacc4c0657b3a4af4f628428d2702146828c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/8ef236a1a37df364b518b7411a4b5bb95b040d79", - "reference": "8ef236a1a37df364b518b7411a4b5bb95b040d79", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/e54aacc4c0657b3a4af4f628428d2702146828c6", + "reference": "e54aacc4c0657b3a4af4f628428d2702146828c6", "shasum": "" }, "require": { @@ -1593,9 +1593,9 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/6.12.0" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.13.1" }, - "time": "2026-09-04T12:54:20+00:00" + "time": "2026-09-30T07:42:28+00:00" }, { "name": "kelunik/certificate", @@ -2021,20 +2021,25 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "2.2.0", + "version": "2.2.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + "reference": "ee15a5a2022c8383906b225055e9496a6a5e6e3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/ee15a5a2022c8383906b225055e9496a6a5e6e3b", + "reference": "ee15a5a2022c8383906b225055e9496a6a5e6e3b", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.25" }, "type": "library", "extra": { @@ -2058,7 +2063,7 @@ } ], "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "homepage": "https://www.phpdoc.org", "keywords": [ "FQSEN", "phpDocumentor", @@ -2068,9 +2073,9 @@ ], "support": { "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.2.1" }, - "time": "2020-06-27T09:03:43+00:00" + "time": "2025-11-10T21:21:55+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -2196,16 +2201,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.5", + "version": "2.3.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "148cefffaf0233e4c08cc13db8a195a56dd6dfe9" + "reference": "1427af4647235b4a73b13940b1f1258d3584f36e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/148cefffaf0233e4c08cc13db8a195a56dd6dfe9", - "reference": "148cefffaf0233e4c08cc13db8a195a56dd6dfe9", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1427af4647235b4a73b13940b1f1258d3584f36e", + "reference": "1427af4647235b4a73b13940b1f1258d3584f36e", "shasum": "" }, "require": { @@ -2237,9 +2242,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.5" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.6" }, - "time": "2026-08-31T16:05:28+00:00" + "time": "2026-09-27T20:07:45+00:00" }, { "name": "psr/container", @@ -2719,16 +2724,16 @@ }, { "name": "seld/phar-utils", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/Seldaek/phar-utils.git", - "reference": "990bbd0e92caa216d52eca0935f6e35e589bfaa5" + "reference": "65fb381613fd31745d39a740a112a233f978d2d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/990bbd0e92caa216d52eca0935f6e35e589bfaa5", - "reference": "990bbd0e92caa216d52eca0935f6e35e589bfaa5", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/65fb381613fd31745d39a740a112a233f978d2d9", + "reference": "65fb381613fd31745d39a740a112a233f978d2d9", "shasum": "" }, "require": { @@ -2761,22 +2766,22 @@ ], "support": { "issues": "https://github.com/Seldaek/phar-utils/issues", - "source": "https://github.com/Seldaek/phar-utils/tree/1.2.2" + "source": "https://github.com/Seldaek/phar-utils/tree/1.2.3" }, - "time": "2026-08-01T12:48:55+00:00" + "time": "2026-10-01T08:16:23+00:00" }, { "name": "symfony/console", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3a1973458b153f566a8d7499bc06ece323d60063" + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3a1973458b153f566a8d7499bc06ece323d60063", - "reference": "3a1973458b153f566a8d7499bc06ece323d60063", + "url": "https://api.github.com/repos/symfony/console/zipball/d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", "shasum": "" }, "require": { @@ -2841,7 +2846,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.19" + "source": "https://github.com/symfony/console/tree/v7.4.20" }, "funding": [ { @@ -2861,7 +2866,7 @@ "type": "tidelift" } ], - "time": "2026-09-13T10:38:41+00:00" + "time": "2026-09-18T15:55:00+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3086,16 +3091,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe" + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/1b900bc6ae5ba60c5eee69c11ba44566190576fe", - "reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe", + "url": "https://api.github.com/repos/symfony/finder/zipball/2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", "shasum": "" }, "require": { @@ -3130,7 +3135,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.19" + "source": "https://github.com/symfony/finder/tree/v7.4.20" }, "funding": [ { @@ -3150,7 +3155,7 @@ "type": "tidelift" } ], - "time": "2026-09-10T19:14:10+00:00" + "time": "2026-09-26T06:31:10+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3237,16 +3242,16 @@ }, { "name": "symfony/polyfill-iconv", - "version": "v1.37.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "2c5729fd241b4b22f6e4b436bc3354a4f262df57" + "reference": "254724d95fe01b679cd97d88786e9623ee00bfb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/2c5729fd241b4b22f6e4b436bc3354a4f262df57", - "reference": "2c5729fd241b4b22f6e4b436bc3354a4f262df57", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/254724d95fe01b679cd97d88786e9623ee00bfb7", + "reference": "254724d95fe01b679cd97d88786e9623ee00bfb7", "shasum": "" }, "require": { @@ -3297,7 +3302,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-iconv/tree/v1.37.0" + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.43.0" }, "funding": [ { @@ -3317,20 +3322,20 @@ "type": "tidelift" } ], - "time": "2026-04-10T16:19:22+00:00" + "time": "2026-09-29T06:25:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75", + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75", "shasum": "" }, "require": { @@ -3379,7 +3384,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0" }, "funding": [ { @@ -3399,20 +3404,20 @@ "type": "tidelift" } ], - "time": "2026-07-28T08:25:59+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.42.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b", + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b", "shasum": "" }, "require": { @@ -3464,7 +3469,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0" }, "funding": [ { @@ -3484,20 +3489,20 @@ "type": "tidelift" } ], - "time": "2026-08-07T06:33:24+00:00" + "time": "2026-09-23T22:02:09+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.38.2", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", "shasum": "" }, "require": { @@ -3549,7 +3554,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0" }, "funding": [ { @@ -3569,20 +3574,20 @@ "type": "tidelift" } ], - "time": "2026-05-27T06:59:30+00:00" + "time": "2026-09-24T15:19:04+00:00" }, { "name": "symfony/polyfill-php84", - "version": "v1.38.1", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa" + "reference": "22c6548499cbe5c5bb072fc0c42312dff062a015" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa", - "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/22c6548499cbe5c5bb072fc0c42312dff062a015", + "reference": "22c6548499cbe5c5bb072fc0c42312dff062a015", "shasum": "" }, "require": { @@ -3629,7 +3634,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.43.0" }, "funding": [ { @@ -3649,7 +3654,7 @@ "type": "tidelift" } ], - "time": "2026-05-26T12:51:13+00:00" + "time": "2026-09-23T22:01:09+00:00" }, { "name": "symfony/process", diff --git a/tools/infection/composer.lock b/tools/infection/composer.lock index 4fd6ff6c5e..fcad45ff58 100644 --- a/tools/infection/composer.lock +++ b/tools/infection/composer.lock @@ -239,23 +239,23 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.3.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678" + "reference": "d384a7d0d6e67aa497327260ca95023e92dc2032" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/d384a7d0d6e67aa497327260ca95023e92dc2032", + "reference": "d384a7d0d6e67aa497327260ca95023e92dc2032", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "fidry/makefile": "^0.2.0", + "fidry/makefile": "^0.2.0 || ^1.1.2", "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", "phpstan/phpstan": "^2.0", @@ -263,6 +263,7 @@ "phpstan/phpstan-phpunit": "^2.0", "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "symfony/polyfill-mbstring": "^1.33", "webmozarts/strict-phpunit": "^7.5" }, "type": "library", @@ -288,7 +289,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.4.1" }, "funding": [ { @@ -296,7 +297,7 @@ "type": "github" } ], - "time": "2025-08-14T07:29:31+00:00" + "time": "2026-09-29T22:11:39+00:00" }, { "name": "infection/abstract-testframework-adapter", @@ -479,16 +480,16 @@ }, { "name": "infection/infection", - "version": "0.35.4", + "version": "0.35.5", "source": { "type": "git", "url": "https://github.com/infection/infection.git", - "reference": "487bf060228e1272c6a9653468b87a4fe29436df" + "reference": "0db852996c8de64d908a4ed2112c36853232d992" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/infection/infection/zipball/487bf060228e1272c6a9653468b87a4fe29436df", - "reference": "487bf060228e1272c6a9653468b87a4fe29436df", + "url": "https://api.github.com/repos/infection/infection/zipball/0db852996c8de64d908a4ed2112c36853232d992", + "reference": "0db852996c8de64d908a4ed2112c36853232d992", "shasum": "" }, "require": { @@ -519,7 +520,7 @@ "symfony/finder": "^6.4 || ^7.4 || ^8.0", "symfony/polyfill-php85": "^1.33", "symfony/process": "^6.4 || ^7.4 || ^8.0", - "thecodingmachine/safe": "^v3.0", + "thecodingmachine/safe": "^v3.4", "webmozart/assert": "^1.11 || ^2.0" }, "conflict": { @@ -603,7 +604,7 @@ ], "support": { "issues": "https://github.com/infection/infection/issues", - "source": "https://github.com/infection/infection/tree/0.35.4" + "source": "https://github.com/infection/infection/tree/0.35.5" }, "funding": [ { @@ -615,7 +616,7 @@ "type": "open_collective" } ], - "time": "2026-09-02T13:30:25+00:00" + "time": "2026-09-27T14:35:40+00:00" }, { "name": "infection/mutator", @@ -672,16 +673,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "6.12.0", + "version": "6.13.1", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "8ef236a1a37df364b518b7411a4b5bb95b040d79" + "reference": "e54aacc4c0657b3a4af4f628428d2702146828c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/8ef236a1a37df364b518b7411a4b5bb95b040d79", - "reference": "8ef236a1a37df364b518b7411a4b5bb95b040d79", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/e54aacc4c0657b3a4af4f628428d2702146828c6", + "reference": "e54aacc4c0657b3a4af4f628428d2702146828c6", "shasum": "" }, "require": { @@ -731,9 +732,9 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/6.12.0" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.13.1" }, - "time": "2026-09-04T12:54:20+00:00" + "time": "2026-09-30T07:42:28+00:00" }, { "name": "marc-mabe/php-enum", @@ -1302,16 +1303,16 @@ }, { "name": "sanmai/pipeline", - "version": "7.10", + "version": "7.12", "source": { "type": "git", "url": "https://github.com/sanmai/pipeline.git", - "reference": "a8e4e57a6031efc7a92defd13fed9c1c4c73fc71" + "reference": "e7c1f115790ae68ea22f30a646578c587a691399" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sanmai/pipeline/zipball/a8e4e57a6031efc7a92defd13fed9c1c4c73fc71", - "reference": "a8e4e57a6031efc7a92defd13fed9c1c4c73fc71", + "url": "https://api.github.com/repos/sanmai/pipeline/zipball/e7c1f115790ae68ea22f30a646578c587a691399", + "reference": "e7c1f115790ae68ea22f30a646578c587a691399", "shasum": "" }, "require": { @@ -1328,7 +1329,6 @@ "phpstan/phpstan": "^2", "phpunit/phpunit": "^11 || ^12", "sanmai/phpstan-rules": "^0.3.11", - "sanmai/phpunit-double-colon-syntax": "^0.1.1", "vimeo/psalm": ">=2" }, "type": "library", @@ -1358,7 +1358,7 @@ "description": "General-purpose collections pipeline", "support": { "issues": "https://github.com/sanmai/pipeline/issues", - "source": "https://github.com/sanmai/pipeline/tree/7.10" + "source": "https://github.com/sanmai/pipeline/tree/7.12" }, "funding": [ { @@ -1366,7 +1366,7 @@ "type": "github" } ], - "time": "2026-08-03T04:56:22+00:00" + "time": "2026-09-30T13:46:33+00:00" }, { "name": "sebastian/diff", @@ -1449,16 +1449,16 @@ }, { "name": "symfony/console", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3a1973458b153f566a8d7499bc06ece323d60063" + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3a1973458b153f566a8d7499bc06ece323d60063", - "reference": "3a1973458b153f566a8d7499bc06ece323d60063", + "url": "https://api.github.com/repos/symfony/console/zipball/d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", "shasum": "" }, "require": { @@ -1523,7 +1523,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.19" + "source": "https://github.com/symfony/console/tree/v7.4.20" }, "funding": [ { @@ -1543,7 +1543,7 @@ "type": "tidelift" } ], - "time": "2026-09-13T10:38:41+00:00" + "time": "2026-09-18T15:55:00+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1688,16 +1688,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe" + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/1b900bc6ae5ba60c5eee69c11ba44566190576fe", - "reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe", + "url": "https://api.github.com/repos/symfony/finder/zipball/2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", "shasum": "" }, "require": { @@ -1732,7 +1732,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.19" + "source": "https://github.com/symfony/finder/tree/v7.4.20" }, "funding": [ { @@ -1752,7 +1752,7 @@ "type": "tidelift" } ], - "time": "2026-09-10T19:14:10+00:00" + "time": "2026-09-26T06:31:10+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1839,16 +1839,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75", + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75", "shasum": "" }, "require": { @@ -1897,7 +1897,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0" }, "funding": [ { @@ -1917,20 +1917,20 @@ "type": "tidelift" } ], - "time": "2026-07-28T08:25:59+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.42.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b", + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b", "shasum": "" }, "require": { @@ -1982,7 +1982,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0" }, "funding": [ { @@ -2002,20 +2002,20 @@ "type": "tidelift" } ], - "time": "2026-08-07T06:33:24+00:00" + "time": "2026-09-23T22:02:09+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.38.2", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", "shasum": "" }, "require": { @@ -2067,7 +2067,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0" }, "funding": [ { @@ -2087,20 +2087,20 @@ "type": "tidelift" } ], - "time": "2026-05-27T06:59:30+00:00" + "time": "2026-09-24T15:19:04+00:00" }, { "name": "symfony/polyfill-php85", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a" + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a", - "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/86a42cbcc07adc331481a5ab310a4024bfc227f6", + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6", "shasum": "" }, "require": { @@ -2147,7 +2147,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.43.0" }, "funding": [ { @@ -2167,7 +2167,7 @@ "type": "tidelift" } ], - "time": "2026-07-01T12:47:55+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/process", diff --git a/tools/mago/composer.lock b/tools/mago/composer.lock index cb1d1824ca..1692db3ad7 100644 --- a/tools/mago/composer.lock +++ b/tools/mago/composer.lock @@ -9,16 +9,16 @@ "packages-dev": [ { "name": "carthage-software/mago", - "version": "1.49.0", + "version": "1.51.0", "source": { "type": "git", "url": "https://github.com/carthage-software/mago.git", - "reference": "bbdaf378e69114f5d9c580862c8533dd3f01c050" + "reference": "9a62f0a1829490dcff31f62808589f7ab86779b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/carthage-software/mago/zipball/bbdaf378e69114f5d9c580862c8533dd3f01c050", - "reference": "bbdaf378e69114f5d9c580862c8533dd3f01c050", + "url": "https://api.github.com/repos/carthage-software/mago/zipball/9a62f0a1829490dcff31f62808589f7ab86779b5", + "reference": "9a62f0a1829490dcff31f62808589f7ab86779b5", "shasum": "" }, "require": { @@ -60,7 +60,7 @@ ], "support": { "issues": "https://github.com/carthage-software/mago/issues", - "source": "https://github.com/carthage-software/mago/tree/1.49.0" + "source": "https://github.com/carthage-software/mago/tree/1.51.0" }, "funding": [ { @@ -68,7 +68,7 @@ "type": "github" } ], - "time": "2026-09-16T05:38:39+00:00" + "time": "2026-10-01T20:37:34+00:00" }, { "name": "revolt/event-loop", diff --git a/tools/monorepo/composer.lock b/tools/monorepo/composer.lock index b194b2af7b..ba69c6c40a 100644 --- a/tools/monorepo/composer.lock +++ b/tools/monorepo/composer.lock @@ -462,16 +462,16 @@ }, { "name": "symfony/console", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3a1973458b153f566a8d7499bc06ece323d60063" + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3a1973458b153f566a8d7499bc06ece323d60063", - "reference": "3a1973458b153f566a8d7499bc06ece323d60063", + "url": "https://api.github.com/repos/symfony/console/zipball/d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", "shasum": "" }, "require": { @@ -536,7 +536,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.19" + "source": "https://github.com/symfony/console/tree/v7.4.20" }, "funding": [ { @@ -556,20 +556,20 @@ "type": "tidelift" } ], - "time": "2026-09-13T10:38:41+00:00" + "time": "2026-09-18T15:55:00+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.4.17", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f318ac9da5aba0be2cf43ecdd562c05a33bc11c0" + "reference": "a7faee783a87b55f27460fc571f8c639bf9d93a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f318ac9da5aba0be2cf43ecdd562c05a33bc11c0", - "reference": "f318ac9da5aba0be2cf43ecdd562c05a33bc11c0", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a7faee783a87b55f27460fc571f8c639bf9d93a2", + "reference": "a7faee783a87b55f27460fc571f8c639bf9d93a2", "shasum": "" }, "require": { @@ -620,7 +620,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.4.17" + "source": "https://github.com/symfony/dependency-injection/tree/v7.4.20" }, "funding": [ { @@ -640,7 +640,7 @@ "type": "tidelift" } ], - "time": "2026-08-21T17:40:08+00:00" + "time": "2026-09-29T12:35:16+00:00" }, { "name": "symfony/deprecation-contracts", @@ -715,16 +715,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.4.17", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8373921e231e190a88e2ad526951bbaa791576fa" + "reference": "82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8373921e231e190a88e2ad526951bbaa791576fa", - "reference": "8373921e231e190a88e2ad526951bbaa791576fa", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0", + "reference": "82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0", "shasum": "" }, "require": { @@ -773,7 +773,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.4.17" + "source": "https://github.com/symfony/error-handler/tree/v7.4.20" }, "funding": [ { @@ -793,7 +793,7 @@ "type": "tidelift" } ], - "time": "2026-08-21T17:40:08+00:00" + "time": "2026-09-22T18:56:40+00:00" }, { "name": "symfony/event-dispatcher", @@ -1032,16 +1032,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe" + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/1b900bc6ae5ba60c5eee69c11ba44566190576fe", - "reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe", + "url": "https://api.github.com/repos/symfony/finder/zipball/2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", "shasum": "" }, "require": { @@ -1076,7 +1076,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.19" + "source": "https://github.com/symfony/finder/tree/v7.4.20" }, "funding": [ { @@ -1096,20 +1096,20 @@ "type": "tidelift" } ], - "time": "2026-09-10T19:14:10+00:00" + "time": "2026-09-26T06:31:10+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f7b953be7801974a5a0685e1228bbc3b12b35936" + "reference": "9d0761c0da6bd5b801b401666834901a9a1ffc33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f7b953be7801974a5a0685e1228bbc3b12b35936", - "reference": "f7b953be7801974a5a0685e1228bbc3b12b35936", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9d0761c0da6bd5b801b401666834901a9a1ffc33", + "reference": "9d0761c0da6bd5b801b401666834901a9a1ffc33", "shasum": "" }, "require": { @@ -1158,7 +1158,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.19" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.20" }, "funding": [ { @@ -1178,20 +1178,20 @@ "type": "tidelift" } ], - "time": "2026-09-14T17:41:17+00:00" + "time": "2026-09-24T07:12:44+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "683507424cc84ca85ac1551adb609b6b98216667" + "reference": "392784b5d7b959b8d872542a2530c50c540a788f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/683507424cc84ca85ac1551adb609b6b98216667", - "reference": "683507424cc84ca85ac1551adb609b6b98216667", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/392784b5d7b959b8d872542a2530c50c540a788f", + "reference": "392784b5d7b959b8d872542a2530c50c540a788f", "shasum": "" }, "require": { @@ -1277,7 +1277,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.19" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.20" }, "funding": [ { @@ -1297,7 +1297,7 @@ "type": "tidelift" } ], - "time": "2026-09-15T07:09:35+00:00" + "time": "2026-09-29T14:05:16+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1384,16 +1384,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75", + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75", "shasum": "" }, "require": { @@ -1442,7 +1442,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0" }, "funding": [ { @@ -1462,20 +1462,20 @@ "type": "tidelift" } ], - "time": "2026-07-28T08:25:59+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.42.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b", + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b", "shasum": "" }, "require": { @@ -1527,7 +1527,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0" }, "funding": [ { @@ -1547,20 +1547,20 @@ "type": "tidelift" } ], - "time": "2026-08-07T06:33:24+00:00" + "time": "2026-09-23T22:02:09+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.38.2", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", "shasum": "" }, "require": { @@ -1612,7 +1612,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0" }, "funding": [ { @@ -1632,20 +1632,20 @@ "type": "tidelift" } ], - "time": "2026-05-27T06:59:30+00:00" + "time": "2026-09-24T15:19:04+00:00" }, { "name": "symfony/polyfill-php85", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a" + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a", - "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/86a42cbcc07adc331481a5ab310a4024bfc227f6", + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6", "shasum": "" }, "require": { @@ -1692,7 +1692,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.43.0" }, "funding": [ { @@ -1712,7 +1712,7 @@ "type": "tidelift" } ], - "time": "2026-07-01T12:47:55+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/process", diff --git a/tools/phpbench/composer.lock b/tools/phpbench/composer.lock index acf41e03dd..f48f69f579 100644 --- a/tools/phpbench/composer.lock +++ b/tools/phpbench/composer.lock @@ -86,27 +86,25 @@ }, { "name": "doctrine/lexer", - "version": "3.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + "reference": "71d305eaa6480d3d3460c7d053d1da7749fa9cca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/71d305eaa6480d3d3460c7d053d1da7749fa9cca", + "reference": "71d305eaa6480d3d3460c7d053d1da7749fa9cca", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.21" + "doctrine/coding-standard": "^14", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^10.5.58 || ^12.5.4" }, "type": "library", "autoload": { @@ -143,7 +141,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.1" + "source": "https://github.com/doctrine/lexer/tree/3.0.3" }, "funding": [ { @@ -159,7 +157,7 @@ "type": "tidelift" } ], - "time": "2024-02-05T11:56:58+00:00" + "time": "2026-10-01T06:59:29+00:00" }, { "name": "phpbench/container", @@ -529,16 +527,16 @@ }, { "name": "symfony/console", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3a1973458b153f566a8d7499bc06ece323d60063" + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3a1973458b153f566a8d7499bc06ece323d60063", - "reference": "3a1973458b153f566a8d7499bc06ece323d60063", + "url": "https://api.github.com/repos/symfony/console/zipball/d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", "shasum": "" }, "require": { @@ -603,7 +601,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.19" + "source": "https://github.com/symfony/console/tree/v7.4.20" }, "funding": [ { @@ -623,7 +621,7 @@ "type": "tidelift" } ], - "time": "2026-09-13T10:38:41+00:00" + "time": "2026-09-18T15:55:00+00:00" }, { "name": "symfony/deprecation-contracts", @@ -768,16 +766,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.19", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe" + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/1b900bc6ae5ba60c5eee69c11ba44566190576fe", - "reference": "1b900bc6ae5ba60c5eee69c11ba44566190576fe", + "url": "https://api.github.com/repos/symfony/finder/zipball/2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", "shasum": "" }, "require": { @@ -812,7 +810,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.19" + "source": "https://github.com/symfony/finder/tree/v7.4.20" }, "funding": [ { @@ -832,7 +830,7 @@ "type": "tidelift" } ], - "time": "2026-09-10T19:14:10+00:00" + "time": "2026-09-26T06:31:10+00:00" }, { "name": "symfony/options-resolver", @@ -990,16 +988,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75", + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75", "shasum": "" }, "require": { @@ -1048,7 +1046,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0" }, "funding": [ { @@ -1068,20 +1066,20 @@ "type": "tidelift" } ], - "time": "2026-07-28T08:25:59+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.42.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b", + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b", "shasum": "" }, "require": { @@ -1133,7 +1131,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0" }, "funding": [ { @@ -1153,20 +1151,20 @@ "type": "tidelift" } ], - "time": "2026-08-07T06:33:24+00:00" + "time": "2026-09-23T22:02:09+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.38.2", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", "shasum": "" }, "require": { @@ -1218,7 +1216,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0" }, "funding": [ { @@ -1238,7 +1236,7 @@ "type": "tidelift" } ], - "time": "2026-05-27T06:59:30+00:00" + "time": "2026-09-24T15:19:04+00:00" }, { "name": "symfony/process", diff --git a/tools/phpunit/composer.lock b/tools/phpunit/composer.lock index f8e0376642..6e158ed9d9 100644 --- a/tools/phpunit/composer.lock +++ b/tools/phpunit/composer.lock @@ -589,16 +589,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.35", + "version": "12.5.37", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "345ac22e42cb14cdc7aa8428655d8bb8c82a4aab" + "reference": "684340c1590e5f3f3b859f5e80619725d88b63ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/345ac22e42cb14cdc7aa8428655d8bb8c82a4aab", - "reference": "345ac22e42cb14cdc7aa8428655d8bb8c82a4aab", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/684340c1590e5f3f3b859f5e80619725d88b63ba", + "reference": "684340c1590e5f3f3b859f5e80619725d88b63ba", "shasum": "" }, "require": { @@ -667,7 +667,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.35" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.37" }, "funding": [ { @@ -675,7 +675,7 @@ "type": "other" } ], - "time": "2026-09-09T04:48:50+00:00" + "time": "2026-09-29T12:08:54+00:00" }, { "name": "sebastian/cli-parser", diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json index 1237f82819..14b4b3be63 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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":573,"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}],"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":582,"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":592,"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":599,"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":605,"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":617,"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":623,"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":629,"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":635,"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":641,"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":647,"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":656,"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":662,"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":671,"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":677,"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":684,"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":690,"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":696,"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":705,"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":711,"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":722,"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":731,"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":740,"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":746,"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":755,"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":765,"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":774,"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":780,"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":786,"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":794,"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":807,"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":813,"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":819,"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":829,"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":838,"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":847,"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":853,"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":866,"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":875,"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":884,"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":890,"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":899,"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":905,"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":911,"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":917,"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":923,"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":935,"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":962,"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":992,"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":998,"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":1004,"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":1010,"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":1016,"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":1022,"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":1028,"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":1034,"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":1040,"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":1046,"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":1052,"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":1058,"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":"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":1064,"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":1070,"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":1076,"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":1082,"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":1092,"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":1102,"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":1112,"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":1122,"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":1132,"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":1138,"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":1147,"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":1156,"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":1169,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\DefaultBackend::..."}],"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":1221,"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":1227,"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":1233,"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":1239,"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::..."},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"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":1249,"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":1255,"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":1261,"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":1267,"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":1273,"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":1279,"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":1285,"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":1291,"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":1297,"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":1303,"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":1309,"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":1315,"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":"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":1321,"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":1327,"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":1333,"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":1339,"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":1345,"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":1356,"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":1365,"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":1374,"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":1386,"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":1396,"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":1405,"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":1411,"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":1417,"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":1426,"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":1439,"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":1448,"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":1454,"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":1463,"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":1469,"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":1475,"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":1481,"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":1495,"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":1509,"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":1527,"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":1533,"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":1539,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1549,"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":1555,"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":1561,"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":1567,"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":1573,"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":1579,"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":1585,"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":1598,"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":1609,"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":1615,"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":1628,"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":1661,"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":1713,"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":1719,"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":1725,"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":1731,"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":1737,"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":1743,"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":1749,"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":1755,"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":1761,"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":1767,"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":1776,"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":1786,"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":1792,"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":1801,"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":1811,"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":1817,"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":1826,"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":1832,"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":1841,"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":1847,"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":1856,"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":1862,"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":1868,"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":1874,"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":1880,"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":1886,"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":1892,"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":1903,"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":1909,"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":1918,"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":1929,"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":1940,"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":1950,"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":1984,"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":1992,"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":2001,"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":2009,"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":2026,"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":2043,"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":2060,"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":2066,"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":2072,"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":2082,"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":2091,"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":2097,"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":2103,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":573,"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}],"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":582,"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":592,"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":599,"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":605,"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":617,"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":623,"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":629,"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":635,"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":641,"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":647,"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":656,"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":662,"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":671,"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":677,"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":684,"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":690,"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":696,"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":705,"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":711,"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":722,"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":731,"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":740,"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":746,"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":755,"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":765,"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":774,"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":780,"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":786,"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":794,"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":807,"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":813,"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":819,"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":829,"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":838,"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":847,"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":853,"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":866,"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":875,"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":884,"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":890,"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":899,"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":905,"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":911,"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":917,"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":923,"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":935,"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":962,"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":992,"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":998,"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":1004,"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":1010,"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":1016,"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":1022,"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":1028,"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":1034,"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":1040,"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":1046,"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":1052,"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":1058,"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":"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":1064,"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":1070,"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":1076,"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":1082,"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":1092,"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":1102,"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":1112,"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":1122,"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":1132,"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":1138,"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":1147,"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":1156,"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":1169,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\AdaptiveBackend::..."}],"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":1221,"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":1227,"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":1233,"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":1239,"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::..."},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"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":1249,"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":1255,"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":1261,"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":1267,"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":1273,"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":1279,"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":1285,"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":1291,"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":1297,"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":1303,"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":1309,"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":1315,"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":"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":1321,"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":1327,"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":1333,"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":1339,"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":1345,"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":1356,"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":1365,"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":1374,"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":1386,"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":1396,"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":1405,"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":1411,"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":1417,"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":1426,"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":1439,"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":1448,"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":1454,"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":1463,"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":1469,"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":1475,"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":1481,"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":1495,"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":1509,"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":1527,"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":1533,"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":1539,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1549,"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":1555,"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":1561,"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":1567,"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":1573,"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":1579,"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":1585,"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":1598,"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":1609,"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":1615,"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":1628,"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":1661,"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":1713,"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":1719,"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":1725,"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":1731,"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":1737,"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":1743,"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":1749,"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":1755,"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":1761,"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":1767,"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":1776,"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":1786,"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":1792,"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":1801,"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":1811,"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":1817,"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":1826,"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":1832,"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":1841,"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":1847,"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":1856,"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":1862,"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":1868,"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":1874,"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":1880,"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":1886,"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":1892,"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":1903,"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":1909,"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":1918,"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":1929,"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":1940,"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":1950,"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":1984,"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":1992,"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":2001,"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":2009,"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":2026,"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":2043,"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":2060,"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":2066,"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":2072,"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":2082,"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":2091,"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":2097,"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":2103,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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 From 49a51e20de1950bda968ba9750fc61a0b1126624 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sat, 3 Oct 2026 13:50:37 +0200 Subject: [PATCH 15/21] refactor: lazy-rows candidates cleanup - one file read loop and one write frame for every file format, per-read state out of extractors and loaders - the configured backend reaches every batch: extractor batches adopted at the read boundary, Rows::concat/matchTo/project, functions, joins, caches, Floe - no hidden default backend: Floe readers, merger, serializer, Config and caches take it explicitly - one record decoder for CSV, Excel and Google Sheet; one JSON extractor and loader - file plumbing moved to Extractor\File, Extractor\Memory and Loader\File; Column\Php split into Physical and Layout - dead API removed: Rows::merge and ten other Rows methods, Column::builder, RowsBuffer, XMLReaderExtractor --- documentation/components/adapters/csv.md | 8 + documentation/components/adapters/excel.md | 14 +- .../components/adapters/google-sheet.md | 10 + documentation/components/adapters/http.md | 13 + documentation/components/core/caching.md | 21 +- documentation/components/core/floe.md | 6 +- .../components/extensions/arrow-ext.md | 5 - .../components/extensions/flow-php-ext.md | 4 +- documentation/contributing/rust.md | 2 +- documentation/contributing/wasm.md | 2 +- documentation/upgrading.md | 363 ++++++++-- .../Adapter/Avro/FlixTech/AvroExtractor.php | 6 +- .../ETL/Adapter/Avro/FlixTech/AvroLoader.php | 2 +- .../ETL/Adapter/CSV/AdaptiveCSVOpenSource.php | 2 +- .../src/Flow/ETL/Adapter/CSV/CSVDecoder.php | 96 +-- .../src/Flow/ETL/Adapter/CSV/CSVExtractor.php | 106 +-- .../Flow/ETL/Adapter/CSV/CSVFileBatches.php | 50 ++ .../Flow/ETL/Adapter/CSV/CSVFileReader.php | 2 +- .../Flow/ETL/Adapter/CSV/CSVFileSample.php | 2 +- .../src/Flow/ETL/Adapter/CSV/CSVLoader.php | 67 +- .../src/Flow/ETL/Adapter/CSV/CSVOpenSink.php | 8 +- .../Flow/ETL/Adapter/CSV/CSVRowNormalizer.php | 51 -- .../CSV/Tests/Context/CSVFixtureContext.php | 2 +- .../Tests/Integration/CSVExtractorTest.php | 29 +- .../CSV/Tests/Unit/CSVFileBatchesTest.php | 64 ++ .../Adapter/CSV/Tests/Unit/CSVLoaderTest.php | 24 + .../CSV/Tests/Unit/CSVRowNormalizerTest.php | 176 ----- .../Flow/ETL/Adapter/Doctrine/DbalEncoder.php | 69 +- .../Doctrine/Tests/Unit/DbalEncoderTest.php | 25 + .../src/Flow/ETL/Adapter/Excel/CellStyler.php | 6 +- .../Flow/ETL/Adapter/Excel/ExcelDecoder.php | 94 --- .../Flow/ETL/Adapter/Excel/ExcelEncoder.php | 163 +++-- .../Flow/ETL/Adapter/Excel/ExcelExtractor.php | 163 +---- .../ETL/Adapter/Excel/ExcelFileBatches.php | 90 +++ .../Flow/ETL/Adapter/Excel/ExcelLoader.php | 25 +- .../Excel/Function/IsValidExcelSheetName.php | 2 +- .../ETL/Adapter/Excel/Sheet/OpenSheet.php | 4 +- .../Flow/ETL/Adapter/Excel/WorkbookReader.php | 8 +- .../ETL/Adapter/Excel/WorkbookSampler.php | 2 +- .../Tests/Context/ExcelFixtureContext.php | 2 +- .../Tests/Integration/ExcelExtractorTest.php | 20 +- .../Tests/Integration/Sheet/OpenSheetTest.php | 6 +- .../Excel/Tests/Unit/ExcelDecoderTest.php | 77 -- .../Excel/Tests/Unit/ExcelEncoderTest.php | 72 ++ .../Excel/Tests/Unit/ExcelFileBatchesTest.php | 102 +++ .../GoogleSheet/GoogleSheetDecoder.php | 119 --- .../GoogleSheet/GoogleSheetExtractor.php | 4 +- .../GoogleSheet/GoogleSheetReadOptions.php | 5 +- .../Adapter/GoogleSheet/GoogleSheetReader.php | 2 +- .../Tests/Unit/GoogleSheetDecoderTest.php | 188 ----- .../Tests/Unit/GoogleSheetExtractorTest.php | 5 +- .../Http/PsrHttpClientStaticExtractor.php | 34 +- ...srHttpClientExtractorBatchContractTest.php | 49 +- ...SONEncoder.php => AdaptiveJsonEncoder.php} | 10 +- .../Adapter/JSON/AdaptiveJsonOpenSource.php | 2 +- .../JSON/JSONMachine/JsonExtractor.php | 108 +-- .../JSON/JSONMachine/JsonFileBatches.php | 48 ++ .../JSON/JSONMachine/JsonFileReader.php | 2 +- .../JSON/JSONMachine/JsonFileSample.php | 2 +- .../JSON/JSONMachine/JsonLinesExtractor.php | 255 ------- .../JSON/{JSONEncoder.php => JsonEncoder.php} | 2 +- .../src/Flow/ETL/Adapter/JSON/JsonFraming.php | 30 +- .../Flow/ETL/Adapter/JSON/JsonLinesLoader.php | 153 ---- .../src/Flow/ETL/Adapter/JSON/JsonLoader.php | 100 ++- .../Flow/ETL/Adapter/JSON/JsonOpenSink.php | 5 +- ...{PhpJSONEncoder.php => PhpJsonEncoder.php} | 4 +- .../ETL/Adapter/JSON/PhpJsonOpenSource.php | 2 +- .../src/Flow/ETL/Adapter/JSON/functions.php | 12 +- .../JSON/Tests/Context/JsonFixtureContext.php | 10 +- .../AdaptiveJsonOpenSourceTest.php | 2 +- .../JsonExtractorBatchContractTest.php | 3 +- .../JSONMachine/JsonExtractorTest.php | 21 + .../JSONMachine/JsonFileReaderTest.php | 2 +- .../JSONMachine/JsonFileSampleTest.php | 2 +- .../JSONMachine/JsonLinesExtractorTest.php | 12 +- .../JSON/Tests/Integration/JsonLinesTest.php | 8 +- .../Tests/Integration/RustJsonRefusalTest.php | 2 +- ...ncoderMother.php => JsonEncoderMother.php} | 16 +- ...erTest.php => AdaptiveJsonEncoderTest.php} | 12 +- .../JSON/Tests/Unit/JsonFileBatchesTest.php | 65 ++ .../JSON/Tests/Unit/JsonFramingTest.php | 6 +- .../JSON/Tests/Unit/JsonLinesLoaderTest.php | 14 +- .../JSON/Tests/Unit/JsonLoaderTest.php | 22 + .../JSON/Tests/Unit/JsonOpenSinkTest.php | 32 +- ...EncoderTest.php => PhpJsonEncoderTest.php} | 26 +- ...ncoderTest.php => RustJsonEncoderTest.php} | 14 +- .../Parquet/AdaptiveParquetOpenSink.php | 3 +- .../ETL/Adapter/Parquet/ParquetExtractor.php | 132 +--- .../Adapter/Parquet/ParquetFileBatches.php | 90 +++ .../ETL/Adapter/Parquet/ParquetFileSink.php | 33 + .../ETL/Adapter/Parquet/ParquetFileSinks.php | 68 ++ .../ETL/Adapter/Parquet/ParquetLoader.php | 113 +-- .../Adapter/Parquet/ParquetSchemaPassFile.php | 4 +- .../ETL/Adapter/Parquet/ParquetSourceFile.php | 4 +- .../Parquet/ParquetSourceFileOpener.php | 49 ++ .../Context/ParquetSourceFileContext.php | 2 +- .../Tests/Double/RefusingParquetEngine.php | 45 ++ .../Tests/Integration/PaginationTest.php | 29 + .../Integration/ParquetExtractorTest.php | 20 + .../Tests/Unit/ParquetFileBatchesTest.php | 206 ++++++ .../Tests/Unit/ParquetFileSinkTest.php | 54 ++ .../Tests/Unit/ParquetFileSinksTest.php | 81 +++ .../Parquet/Tests/Unit/ParquetLoaderTest.php | 34 + .../Unit/ParquetSourceFileOpenerTest.php | 57 ++ .../Tests/Unit/ParquetSourceFileTest.php | 2 +- .../Adapter/PostgreSql/PostgreSqlEncoder.php | 37 +- .../Adapter/PostgreSql/PostgreSqlLoader.php | 6 +- .../QueryBuilder/InsertQueryBuilder.php | 37 +- .../Tests/Unit/PostgreSqlEncoderTest.php | 28 + .../QueryBuilder/InsertQueryBuilderTest.php | 32 +- .../src/Flow/ETL/Adapter/Seal/SealEncoder.php | 150 ++-- .../Seal/Tests/Unit/SealEncoderTest.php | 52 ++ .../Flow/ETL/Adapter/Text/TextExtractor.php | 104 +-- .../Flow/ETL/Adapter/Text/TextFileBatches.php | 75 ++ .../src/Flow/ETL/Adapter/Text/TextLoader.php | 53 +- .../Flow/ETL/Adapter/Text/TextOpenSink.php | 27 + .../Tests/Integration/TextExtractorTest.php | 50 +- .../Text/Tests/Integration/TextLoaderTest.php | 24 + .../Text/Tests/Unit/TextFileBatchesTest.php | 58 ++ .../Text/Tests/Unit/TextOpenSinkTest.php | 32 + .../Flow/ETL/Adapter/XML/Loader/XMLLoader.php | 88 +-- .../Flow/ETL/Adapter/XML/XMLFileBatches.php | 64 ++ .../Flow/ETL/Adapter/XML/XMLNodeBatches.php | 76 +- .../src/Flow/ETL/Adapter/XML/XMLOpenSink.php | 40 + .../ETL/Adapter/XML/XMLParserExtractor.php | 81 +-- .../ETL/Adapter/XML/XMLReaderExtractor.php | 238 ------ .../XMLExtractorBatchContractTest.php | 18 - .../XMLExtractorTypedColumnsTest.php | 2 +- .../Integration/XMLParserExtractorTest.php | 17 +- .../Integration/XMLReaderExtractorTest.php | 251 ------- .../XML/Tests/Unit/XMLFileBatchesTest.php | 64 ++ .../Adapter/XML/Tests/Unit/XMLLoaderTest.php | 28 + .../XML/Tests/Unit/XMLNodeBatchesTest.php | 2 +- .../Adapter/XML/Tests/Unit/XMLNodesTest.php | 2 +- .../XML/Tests/Unit/XMLOpenSinkTest.php | 47 ++ .../src/Flow/CLI/Factory/LoaderFactory.php | 2 +- .../src/Flow/ETL/Bucketing/KeyGrouping.php | 6 +- .../etl/src/Flow/ETL/Bucketing/KeyValues.php | 8 +- .../Bucketing/Storage/FilesystemBuckets.php | 12 +- .../ETL/Bucketing/Storage/PSRCacheBuckets.php | 3 +- .../ETL/Bucketing/Storage/SpillingBuckets.php | 8 +- .../etl/src/Flow/ETL/Cache/CacheIndex.php | 5 +- .../ETL/Cache/Implementation/ApcuCache.php | 16 +- .../Cache/Implementation/FilesystemCache.php | 3 +- .../Cache/Implementation/PSRSimpleCache.php | 3 +- src/core/etl/src/Flow/ETL/Column/Column.php | 1 + .../etl/src/Flow/ETL/Column/ColumnBuilder.php | 14 + .../src/Flow/ETL/Column/ComparableValues.php | 46 +- .../Column/{Php => Layout}/BooleanLayout.php | 2 +- .../ETL/Column/{ => Layout}/BufferLayout.php | 5 +- .../ETL/Column/{Php => Layout}/Buffers.php | 2 +- .../{Php => Layout}/FixedBinary16Layout.php | 2 +- .../Column/{Php => Layout}/Float64Layout.php | 2 +- .../Column/{Php => Layout}/Int32Layout.php | 2 +- .../Column/{Php => Layout}/Int64Layout.php | 2 +- .../ETL/Column/{Php => Layout}/Layout.php | 2 +- .../ETL/Column/{Php => Layout}/LayoutFor.php | 2 +- .../ETL/Column/{Php => Layout}/NullCount.php | 2 +- .../ETL/Column/{Php => Layout}/Offsets.php | 2 +- .../ETL/Column/{Php => Layout}/Utf8Layout.php | 2 +- .../ETL/Column/{Php => Layout}/Validity.php | 2 +- .../ETL/Column/Php/CastingColumnBuilder.php | 45 +- .../src/Flow/ETL/Column/Php/ColumnDecoder.php | 8 +- .../Flow/ETL/Column/Php/ConstantColumn.php | 6 +- .../src/Flow/ETL/Column/Php/ListColumn.php | 3 + .../Flow/ETL/Column/Php/ListColumnBuilder.php | 6 +- .../etl/src/Flow/ETL/Column/Php/MapColumn.php | 3 + .../Flow/ETL/Column/Php/MapColumnBuilder.php | 6 +- .../Flow/ETL/Column/Php/NullColumnBuilder.php | 3 +- .../Flow/ETL/Column/Php/PhpColumnBuilder.php | 2 +- .../etl/src/Flow/ETL/Column/Php/Retype.php | 52 -- .../src/Flow/ETL/Column/Php/ScalarColumn.php | 6 + .../ETL/Column/Php/ScalarColumnBuilder.php | 3 +- .../src/Flow/ETL/Column/Php/StructColumn.php | 2 + .../ETL/Column/Php/StructColumnBuilder.php | 4 +- .../etl/src/Flow/ETL/Column/PhpBackend.php | 7 +- .../Column/{Php => Physical}/DatePhysical.php | 2 +- .../{Php => Physical}/DateTimePhysical.php | 2 +- .../{Php => Physical}/DaysFromCivil.php | 2 +- .../{Php => Physical}/ElementPosition.php | 2 +- .../Column/{Php => Physical}/EnumPhysical.php | 2 +- .../HtmlDocumentPhysical.php | 2 +- .../{Php => Physical}/HtmlElementPhysical.php | 2 +- .../{Php => Physical}/IdentityPhysical.php | 2 +- .../Column/{Php => Physical}/JsonFactory.php | 2 +- .../Column/{Php => Physical}/JsonPhysical.php | 2 +- .../Column/{Php => Physical}/ListPhysical.php | 2 +- .../Column/{Php => Physical}/MapPhysical.php | 2 +- .../Column/{Php => Physical}/NullPhysical.php | 2 +- .../ETL/Column/{Php => Physical}/Physical.php | 2 +- .../{Php => Physical}/PhysicalBuilderFor.php | 10 +- .../Column/{Php => Physical}/PhysicalFor.php | 2 +- .../Flow/ETL/Column/Physical/PhysicalKind.php | 100 +++ .../{Php => Physical}/StructPhysical.php | 2 +- .../Column/{Php => Physical}/TimePhysical.php | 2 +- .../{Php => Physical}/TimeZonePhysical.php | 2 +- .../Column/{Php => Physical}/TimeZones.php | 2 +- .../Column/{Php => Physical}/UuidPhysical.php | 2 +- .../{Php => Physical}/XmlDocumentPhysical.php | 2 +- .../{Php => Physical}/XmlElementPhysical.php | 2 +- src/core/etl/src/Flow/ETL/Column/Retype.php | 119 +++ .../etl/src/Flow/ETL/Column/TextValues.php | 29 +- .../Flow/ETL/Column/{Php => }/ValueColumn.php | 3 +- src/core/etl/src/Flow/ETL/Config.php | 3 +- .../etl/src/Flow/ETL/Config/ConfigBuilder.php | 5 +- .../Flow/ETL/Constraint/UniqueConstraint.php | 2 +- src/core/etl/src/Flow/ETL/DSL/functions.php | 61 +- src/core/etl/src/Flow/ETL/Executor.php | 17 +- .../src/Flow/ETL/Executor/AdoptedBatches.php | 37 + .../etl/src/Flow/ETL/Executor/Segment.php | 2 +- .../src/Flow/ETL/Extractor/ArrayExtractor.php | 3 + .../Flow/ETL/Extractor/BatchByExtractor.php | 7 +- .../src/Flow/ETL/Extractor/BatchExtractor.php | 9 +- .../src/Flow/ETL/Extractor/CacheExtractor.php | 4 +- .../src/Flow/ETL/Extractor/ChainExtractor.php | 2 +- .../ETL/Extractor/CollectingExtractor.php | 11 +- .../Flow/ETL/Extractor/DataFrameExtractor.php | 22 +- .../src/Flow/ETL/Extractor/FeedExtractor.php | 2 +- .../{ => File}/DeclaresPartitionTypes.php | 2 +- .../Flow/ETL/Extractor/File/DerivedSchema.php | 35 + .../Flow/ETL/Extractor/File/FileBatches.php | 38 + .../ETL/Extractor/{ => File}/FileColumns.php | 15 +- .../Flow/ETL/Extractor/File/FileConstants.php | 62 ++ .../Extractor/{ => File}/FileExtractor.php | 3 +- .../Flow/ETL/Extractor/File/FileReadLoop.php | 86 +++ .../ETL/Extractor/{ => File}/FileReading.php | 2 +- .../Extractor/{ => File}/FooterStatistics.php | 3 +- .../ETL/Extractor/File/InferredColumns.php | 54 ++ .../ETL/Extractor/{ => File}/ListedFiles.php | 2 +- .../{ => File}/ListingPartitions.php | 2 +- .../Extractor/{ => File}/MetadataColumns.php | 2 +- .../{ => File}/MetadataColumnsExtractor.php | 2 +- .../File/OffsetSkippingFileBatches.php | 11 + .../Extractor/{ => File}/PartitionColumns.php | 42 +- .../Extractor/{ => File}/PartitionTypes.php | 2 +- .../Extractor/{ => File}/PathFiltering.php | 3 +- .../Flow/ETL/Extractor/File/ReadWindow.php | 29 + .../{ => File}/SelfDescribingFile.php | 3 +- .../ETL/Extractor/{ => File}/SourceFile.php | 2 +- .../src/Flow/ETL/Extractor/FileConstants.php | 73 -- .../src/Flow/ETL/Extractor/FilesExtractor.php | 27 +- .../Flow/ETL/Extractor/Grid/HeaderNames.php | 34 + .../Flow/ETL/Extractor/Grid/RecordDecoder.php | 89 +++ .../Extractor/{ => Memory}/InMemoryRows.php | 2 +- .../Extractor/{ => Memory}/InferredRows.php | 9 +- .../ETL/Extractor/{ => Memory}/SpillState.php | 2 +- .../Extractor/{ => Memory}/SpilledRows.php | 2 +- .../Flow/ETL/Extractor/MemoryExtractor.php | 2 + .../ETL/Extractor/PathPartitionsExtractor.php | 26 +- .../src/Flow/ETL/Extractor/RowsExtractor.php | 2 +- .../Flow/ETL/Extractor/SequenceExtractor.php | 2 + src/core/etl/src/Flow/ETL/Function/All.php | 2 +- src/core/etl/src/Flow/ETL/Function/Any.php | 2 +- src/core/etl/src/Flow/ETL/Function/Append.php | 2 +- .../etl/src/Flow/ETL/Function/ArrayExpand.php | 2 +- .../etl/src/Flow/ETL/Function/ArrayFilter.php | 2 +- .../etl/src/Flow/ETL/Function/ArrayGet.php | 2 +- .../Flow/ETL/Function/ArrayGetCollection.php | 2 +- .../etl/src/Flow/ETL/Function/ArrayKeep.php | 2 +- .../src/Flow/ETL/Function/ArrayKeyRename.php | 2 +- .../etl/src/Flow/ETL/Function/ArrayKeys.php | 2 +- .../ETL/Function/ArrayKeysStyleConvert.php | 2 +- .../etl/src/Flow/ETL/Function/ArrayMerge.php | 2 +- .../ETL/Function/ArrayMergeCollection.php | 2 +- .../src/Flow/ETL/Function/ArrayPathExists.php | 2 +- .../src/Flow/ETL/Function/ArrayReverse.php | 2 +- .../etl/src/Flow/ETL/Function/ArraySort.php | 2 +- .../etl/src/Flow/ETL/Function/ArrayUnpack.php | 2 +- .../etl/src/Flow/ETL/Function/ArrayValues.php | 2 +- src/core/etl/src/Flow/ETL/Function/Ascii.php | 2 +- .../etl/src/Flow/ETL/Function/Between.php | 2 +- .../src/Flow/ETL/Function/BinaryLength.php | 2 +- .../src/Flow/ETL/Function/CallUserFunc.php | 2 +- .../etl/src/Flow/ETL/Function/Capitalize.php | 2 +- src/core/etl/src/Flow/ETL/Function/Cast.php | 6 +- src/core/etl/src/Flow/ETL/Function/Chunk.php | 2 +- .../etl/src/Flow/ETL/Function/Coalesce.php | 2 +- .../src/Flow/ETL/Function/CodePointLength.php | 2 +- .../Flow/ETL/Function/CollapseWhitespace.php | 2 +- .../etl/src/Flow/ETL/Function/Combine.php | 2 +- src/core/etl/src/Flow/ETL/Function/Concat.php | 2 +- .../Flow/ETL/Function/ConcatWithSeparator.php | 2 +- .../etl/src/Flow/ETL/Function/Contains.php | 2 +- .../ETL/Function/DOMElementAttributeValue.php | 2 +- .../Function/DOMElementAttributesCount.php | 2 +- .../ETL/Function/DOMElementNamespaceValue.php | 2 +- .../ETL/Function/DOMElementNextSibling.php | 2 +- .../Flow/ETL/Function/DOMElementParent.php | 2 +- .../Function/DOMElementPreviousSibling.php | 2 +- .../src/Flow/ETL/Function/DOMElementValue.php | 2 +- .../src/Flow/ETL/Function/DateTimeFormat.php | 8 +- src/core/etl/src/Flow/ETL/Function/Divide.php | 2 +- .../etl/src/Flow/ETL/Function/EndsWith.php | 2 +- .../etl/src/Flow/ETL/Function/EnsureEnd.php | 2 +- .../etl/src/Flow/ETL/Function/EnsureStart.php | 2 +- .../etl/src/Flow/ETL/Function/EnumName.php | 2 +- .../etl/src/Flow/ETL/Function/EnumValue.php | 2 +- src/core/etl/src/Flow/ETL/Function/Equals.php | 4 +- .../ETL/Function/Evaluation/ResultColumn.php | 19 +- .../ETL/Function/Evaluation/Selection.php | 2 +- src/core/etl/src/Flow/ETL/Function/Exists.php | 7 +- .../etl/src/Flow/ETL/Function/GreaterThan.php | 2 +- .../Flow/ETL/Function/GreaterThanEqual.php | 2 +- .../etl/src/Flow/ETL/Function/Greatest.php | 2 +- .../Flow/ETL/Function/HTMLQuerySelector.php | 2 +- .../ETL/Function/HTMLQuerySelectorAll.php | 2 +- src/core/etl/src/Flow/ETL/Function/Hash.php | 2 +- .../etl/src/Flow/ETL/Function/IndexOf.php | 2 +- .../etl/src/Flow/ETL/Function/IndexOfLast.php | 2 +- .../etl/src/Flow/ETL/Function/IsEmpty.php | 2 +- src/core/etl/src/Flow/ETL/Function/IsIn.php | 4 +- .../etl/src/Flow/ETL/Function/IsNotNull.php | 7 +- .../src/Flow/ETL/Function/IsNotNumeric.php | 2 +- src/core/etl/src/Flow/ETL/Function/IsNull.php | 7 +- .../etl/src/Flow/ETL/Function/IsNumeric.php | 2 +- src/core/etl/src/Flow/ETL/Function/IsType.php | 2 +- src/core/etl/src/Flow/ETL/Function/IsUtf8.php | 2 +- .../etl/src/Flow/ETL/Function/JsonDecode.php | 2 +- .../etl/src/Flow/ETL/Function/JsonEncode.php | 2 +- src/core/etl/src/Flow/ETL/Function/Least.php | 2 +- .../etl/src/Flow/ETL/Function/LessThan.php | 2 +- .../src/Flow/ETL/Function/LessThanEqual.php | 2 +- .../etl/src/Flow/ETL/Function/ListSelect.php | 7 +- .../etl/src/Flow/ETL/Function/Literal.php | 16 +- .../etl/src/Flow/ETL/Function/MatchCases.php | 2 +- src/core/etl/src/Flow/ETL/Function/Minus.php | 2 +- src/core/etl/src/Flow/ETL/Function/Mod.php | 2 +- .../src/Flow/ETL/Function/ModifyDateTime.php | 2 +- .../etl/src/Flow/ETL/Function/Multiply.php | 2 +- src/core/etl/src/Flow/ETL/Function/Not.php | 2 +- .../etl/src/Flow/ETL/Function/NotEquals.php | 2 +- .../etl/src/Flow/ETL/Function/NotSame.php | 2 +- src/core/etl/src/Flow/ETL/Function/Now.php | 2 +- .../src/Flow/ETL/Function/NumberFormat.php | 2 +- src/core/etl/src/Flow/ETL/Function/OnEach.php | 5 +- .../etl/src/Flow/ETL/Function/Optional.php | 2 +- .../etl/src/Flow/ETL/Function/Parameter.php | 27 - src/core/etl/src/Flow/ETL/Function/Plus.php | 2 +- src/core/etl/src/Flow/ETL/Function/Power.php | 2 +- .../etl/src/Flow/ETL/Function/Prepend.php | 2 +- .../src/Flow/ETL/Function/RandomString.php | 2 +- src/core/etl/src/Flow/ETL/Function/Regex.php | 2 +- .../etl/src/Flow/ETL/Function/RegexAll.php | 2 +- .../etl/src/Flow/ETL/Function/RegexMatch.php | 2 +- .../src/Flow/ETL/Function/RegexMatchAll.php | 2 +- .../src/Flow/ETL/Function/RegexReplace.php | 2 +- src/core/etl/src/Flow/ETL/Function/Repeat.php | 2 +- .../etl/src/Flow/ETL/Function/Reverse.php | 2 +- src/core/etl/src/Flow/ETL/Function/Round.php | 2 +- src/core/etl/src/Flow/ETL/Function/Same.php | 2 +- .../etl/src/Flow/ETL/Function/Sanitize.php | 2 +- src/core/etl/src/Flow/ETL/Function/Size.php | 2 +- src/core/etl/src/Flow/ETL/Function/Slug.php | 2 +- src/core/etl/src/Flow/ETL/Function/Split.php | 2 +- .../etl/src/Flow/ETL/Function/Sprintf.php | 2 +- .../etl/src/Flow/ETL/Function/StartsWith.php | 2 +- src/core/etl/src/Flow/ETL/Function/StrPad.php | 2 +- .../etl/src/Flow/ETL/Function/StrReplace.php | 2 +- .../etl/src/Flow/ETL/Function/StringAfter.php | 2 +- .../src/Flow/ETL/Function/StringAfterLast.php | 2 +- .../src/Flow/ETL/Function/StringBefore.php | 2 +- .../Flow/ETL/Function/StringBeforeLast.php | 2 +- .../Flow/ETL/Function/StringContainsAny.php | 2 +- .../src/Flow/ETL/Function/StringEqualsTo.php | 2 +- .../etl/src/Flow/ETL/Function/StringFold.php | 2 +- .../etl/src/Flow/ETL/Function/StringMatch.php | 2 +- .../src/Flow/ETL/Function/StringMatchAll.php | 2 +- .../src/Flow/ETL/Function/StringNormalize.php | 2 +- .../etl/src/Flow/ETL/Function/StringStyle.php | 2 +- .../etl/src/Flow/ETL/Function/StringTitle.php | 2 +- .../etl/src/Flow/ETL/Function/StringWidth.php | 2 +- .../etl/src/Flow/ETL/Function/Structure.php | 2 +- .../src/Flow/ETL/Function/StructureSelect.php | 7 +- src/core/etl/src/Flow/ETL/Function/ToDate.php | 2 +- .../etl/src/Flow/ETL/Function/ToDateTime.php | 2 +- .../etl/src/Flow/ETL/Function/ToLower.php | 2 +- .../etl/src/Flow/ETL/Function/ToTimeZone.php | 2 +- .../etl/src/Flow/ETL/Function/ToUpper.php | 2 +- src/core/etl/src/Flow/ETL/Function/Trim.php | 2 +- .../etl/src/Flow/ETL/Function/Truncate.php | 2 +- src/core/etl/src/Flow/ETL/Function/Ulid.php | 2 +- .../src/Flow/ETL/Function/UnicodeLength.php | 2 +- src/core/etl/src/Flow/ETL/Function/Uuid.php | 4 +- src/core/etl/src/Flow/ETL/Function/When.php | 2 +- .../etl/src/Flow/ETL/Function/Wordwrap.php | 2 +- src/core/etl/src/Flow/ETL/Function/XPath.php | 2 +- src/core/etl/src/Flow/ETL/GroupBy.php | 52 +- .../etl/src/Flow/ETL/GroupBy/GroupKey.php | 6 +- .../etl/src/Flow/ETL/Join/HashJoin/Joiner.php | 45 +- .../Flow/ETL/Join/HashJoin/NullRowBuilder.php | 5 +- src/core/etl/src/Flow/ETL/Join/RowsJoin.php | 94 +++ .../Flow/ETL/Loader/{ => File}/FileLoader.php | 2 +- .../etl/src/Flow/ETL/Loader/File/FileSink.php | 14 + .../src/Flow/ETL/Loader/File/FileSinks.php | 18 + .../Flow/ETL/Loader/File/FileWriteFrame.php | 114 +++ .../{Filesystem => Loader/File}/FilesSink.php | 27 +- .../ETL/Loader/{ => File}/PartitionRouter.php | 17 +- .../Optimizer/Rule/PushFilterIntoSource.php | 2 +- .../etl/src/Flow/ETL/Plan/Explain/Details.php | 2 +- .../ETL/Processor/BatchingByProcessor.php | 6 +- .../Flow/ETL/Processor/BatchingProcessor.php | 4 +- .../Flow/ETL/Processor/CachingProcessor.php | 2 +- .../ETL/Processor/CollectingProcessor.php | 9 +- .../Processor/GroupByAggregationProcessor.php | 7 +- .../Flow/ETL/Processor/HashJoinProcessor.php | 6 +- .../ETL/Processor/MemorySortProcessor.php | 6 +- .../ETL/Processor/RepartitionProcessor.php | 11 +- .../src/Flow/ETL/Processor/TopNProcessor.php | 6 +- .../src/Flow/ETL/Processor/VoidProcessor.php | 2 +- .../Flow/ETL/Processor/WindowProcessor.php | 4 +- .../etl/src/Flow/ETL/Row/DeclaredColumns.php | 38 - src/core/etl/src/Flow/ETL/Rows.php | 364 +++------- .../etl/src/Flow/ETL/Rows/ColumnRetyping.php | 139 ++++ .../etl/src/Flow/ETL/Rows/RowEquality.php | 161 ----- src/core/etl/src/Flow/ETL/Rows/RowHashes.php | 18 +- src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php | 79 -- .../etl/src/Flow/ETL/Rows/RowsBuilder.php | 102 +++ .../etl/src/Flow/ETL/Sort/ExternalSort.php | 15 +- .../src/Flow/ETL/Sort/Merge/BucketCursor.php | 6 +- .../etl/src/Flow/ETL/Sort/Merge/KWayMerge.php | 15 +- .../Transformer/CrossJoinRowsTransformer.php | 3 +- .../Flow/ETL/Transformer/DerivedColumns.php | 24 +- .../Transformer/DropEntriesTransformer.php | 2 +- .../Transformer/DuplicateRowTransformer.php | 7 +- .../Transformer/JoinEachRowsTransformer.php | 11 +- .../Transformer/NestedExpandTransformer.php | 1 + .../Transformer/PruneEntriesTransformer.php | 2 +- .../Transformer/ScalarFunctionTransformer.php | 2 + .../Transformer/SelectEntriesTransformer.php | 2 +- .../Flow/ETL/Transformer/UntilTransformer.php | 2 +- .../etl/src/Flow/ETL/Window/WindowContext.php | 2 +- src/core/etl/src/Flow/Floe/DSL/functions.php | 4 +- src/core/etl/src/Flow/Floe/FloeExtractor.php | 103 +-- .../etl/src/Flow/Floe/FloeFileBatches.php | 77 ++ src/core/etl/src/Flow/Floe/FloeFileSink.php | 31 + src/core/etl/src/Flow/Floe/FloeFileSinks.php | 47 ++ src/core/etl/src/Flow/Floe/FloeLoader.php | 109 +-- src/core/etl/src/Flow/Floe/FloeMerger.php | 12 +- src/core/etl/src/Flow/Floe/FloeReader.php | 3 +- src/core/etl/src/Flow/Floe/FloeSerializer.php | 7 +- src/core/etl/src/Flow/Floe/FloeSourceFile.php | 4 +- .../etl/src/Flow/Floe/FloeStreamReader.php | 3 +- .../etl/src/Flow/Floe/FloeStreamWriter.php | 4 +- src/core/etl/src/Flow/Floe/FloeWriter.php | 7 +- src/core/etl/src/Flow/Floe/FrameDecoder.php | 2 +- src/core/etl/src/Flow/Floe/FrameEncoder.php | 2 +- .../Flow/ETL/Tests/Context/ExtractedRows.php | 35 +- .../ETL/Tests/Context/FileColumnsContext.php | 6 +- .../Flow/ETL/Tests/Context/GroupByContext.php | 2 +- .../ETL/Tests/Context/KeyGroupingContext.php | 3 +- .../Tests/Context/PartitionRoutingContext.php | 2 +- .../Tests/Context/ScalarFunctionFixtures.php | 58 +- .../Context/SelfDescribingFilesContext.php | 4 +- .../Tests/Double/AcceptingColumnBuilder.php | 7 +- .../ETL/Tests/Double/CountingExtractor.php | 6 +- .../ETL/Tests/Double/DeclaringExtractor.php | 3 +- .../Tests/Double/FailingOnValuesFunction.php | 2 +- .../Tests/Double/FakeSelfDescribingFile.php | 4 +- .../Double/FakeStaticOrdersExtractor.php | 4 +- .../ETL/Tests/Double/FileReadingExtractor.php | 6 +- .../ETL/Tests/Double/FixedValuesColumn.php | 98 --- .../ETL/Tests/Double/InMemoryFileBatches.php | 56 ++ .../Double/InMemoryUnskippableFileBatches.php | 53 ++ .../Tests/Double/NonStructureUnpackStub.php | 2 +- .../Tests/Double/RecordingFileExtractor.php | 2 +- .../ETL/Tests/Double/RepeatableExtractor.php | 3 +- .../Tests/Double/ReportsResolvedOperand.php | 6 +- .../ETL/Tests/Double/ReturnsSpyFunction.php | 5 +- .../Flow/ETL/Tests/Double/SpyBackend.php | 9 + .../Flow/ETL/Tests/Double/SpyFileSinks.php | 68 ++ .../Flow/ETL/Tests/Double/SpySerializer.php | 3 +- .../ETL/Tests/FlowIntegrationTestCase.php | 3 +- .../etl/tests/Flow/ETL/Tests/FlowTestCase.php | 17 +- .../Storage/FilesystemBucketsTest.php | 3 + .../Bucketing/Storage/PSRCacheBucketsTest.php | 8 +- .../Tests/Integration/Cache/CacheTestCase.php | 7 +- .../Integration/Cache/FilesystemCacheTest.php | 10 +- .../Cache/PSRSimpleFilesystemCacheTest.php | 15 +- .../Cache/PSRSimpleRedisCacheTest.php | 13 +- .../Tests/Integration/DataFrame/CacheTest.php | 10 +- .../DataFrame/ConfigBuilderTest.php | 17 + .../DataFrame/ConfiguredBackendTest.php | 68 ++ .../Tests/Integration/DataFrame/JoinTest.php | 17 + .../Tests/Integration/DataFrame/MathTest.php | 5 +- .../Extractor/CacheExtractorTest.php | 23 +- .../Extractor/PathPartitionsExtractorTest.php | 41 +- .../File}/FilesSink/FilesSinkTest.php | 40 +- .../File}/FilesSink/FilesSinkTestCase.php | 4 +- .../NotPartitioned/AppendModeTest.php | 4 +- .../ExceptionIfExistsModeTest.php | 4 +- .../NotPartitioned/IgnoreModeTest.php | 4 +- .../NotPartitioned/OverwriteModeTest.php | 6 +- .../FilesSink/Partitioned/AppendModeTest.php | 4 +- .../Partitioned/ExceptionIfExistsModeTest.php | 4 +- .../FilesSink/Partitioned/IgnoreModeTest.php | 4 +- .../Partitioned/OverwriteModeTest.php | 6 +- .../OverwriteMultipleFilesTest.php | 4 +- .../Partitioned/PartitionPlaceholdersTest.php | 6 +- .../File}/FilesSink/tmp/.gitignore | 0 .../Bucketing/Storage/PSRCacheBucketsTest.php | 38 +- .../ETL/Tests/Unit/Cache/CacheIndexTest.php | 14 +- .../Cache/Implementation/ApcuCacheTest.php | 16 +- .../Tests/Unit/Column/AdaptiveBackendTest.php | 2 +- .../Unit/Column/ComparableValuesTest.php | 15 +- .../{Php => Layout}/BooleanLayoutTest.php | 6 +- .../Column/{ => Layout}/BufferLayoutTest.php | 4 +- .../Column/{Php => Layout}/BuffersTest.php | 4 +- .../FixedBinary16LayoutTest.php | 6 +- .../{Php => Layout}/Float64LayoutTest.php | 6 +- .../{Php => Layout}/Int32LayoutTest.php | 6 +- .../{Php => Layout}/Int64LayoutTest.php | 6 +- .../Column/{Php => Layout}/LayoutForTest.php | 16 +- .../Column/{Php => Layout}/NullCountTest.php | 4 +- .../Column/{Php => Layout}/OffsetsTest.php | 4 +- .../Column/{Php => Layout}/Utf8LayoutTest.php | 6 +- .../Column/{Php => Layout}/ValidityTest.php | 4 +- .../Column/Php/CastingColumnBuilderTest.php | 80 ++ .../Unit/Column/Php/ColumnDecoderTest.php | 2 +- .../Unit/Column/Php/ConstantColumnTest.php | 6 +- .../Unit/Column/Php/ListColumnBuilderTest.php | 6 +- .../Unit/Column/Php/MapColumnBuilderTest.php | 4 +- .../Unit/Column/Php/NullColumnBuilderTest.php | 2 +- .../Column/Php/ScalarColumnBuilderTest.php | 10 +- .../Unit/Column/Php/ScalarColumnTest.php | 2 +- .../Column/Php/StructColumnBuilderTest.php | 6 +- .../ETL/Tests/Unit/Column/PhpBackendTest.php | 6 +- .../{Php => Physical}/DatePhysicalTest.php | 4 +- .../DateTimePhysicalTest.php | 4 +- .../{Php => Physical}/DaysFromCivilTest.php | 4 +- .../{Php => Physical}/ElementPositionTest.php | 4 +- .../{Php => Physical}/EnumPhysicalTest.php | 4 +- .../HtmlDocumentPhysicalTest.php | 4 +- .../HtmlElementPhysicalTest.php | 4 +- .../IdentityPhysicalTest.php | 4 +- .../{Php => Physical}/JsonFactoryTest.php | 4 +- .../{Php => Physical}/JsonPhysicalTest.php | 4 +- .../{Php => Physical}/ListPhysicalTest.php | 6 +- .../{Php => Physical}/MapPhysicalTest.php | 6 +- .../{Php => Physical}/NullPhysicalTest.php | 4 +- .../PhysicalBuilderForTest.php | 4 +- .../{Php => Physical}/PhysicalForTest.php | 36 +- .../Unit/Column/Physical/PhysicalKindTest.php | 63 ++ .../{Php => Physical}/StructPhysicalTest.php | 8 +- .../{Php => Physical}/TimePhysicalTest.php | 4 +- .../TimeZonePhysicalTest.php | 4 +- .../{Php => Physical}/TimeZonesTest.php | 4 +- .../{Php => Physical}/UuidPhysicalTest.php | 4 +- .../XmlDocumentPhysicalTest.php | 4 +- .../XmlElementPhysicalTest.php | 4 +- .../Unit/Column/{Php => }/RetypeTest.php | 57 +- .../ETL/Tests/Unit/Column/TextValuesTest.php | 22 +- .../Unit/Column/{Php => }/ValueColumnTest.php | 4 +- .../Unit/Executor/AdoptedBatchesTest.php | 69 ++ .../Unit/Extractor/File/DerivedSchemaTest.php | 37 + .../Extractor/{ => File}/FileColumnsTest.php | 24 +- .../Unit/Extractor/File/FileConstantsTest.php | 73 ++ .../Unit/Extractor/File/FileReadLoopTest.php | 217 ++++++ .../Extractor/{ => File}/FileReadingTest.php | 4 +- .../{ => File}/FooterStatisticsTest.php | 4 +- .../Extractor/File/InferredColumnsTest.php | 56 ++ .../Extractor/{ => File}/ListedFilesTest.php | 8 +- .../MetadataColumnsExtractorTest.php | 8 +- .../Extractor/File/PartitionColumnsTest.php | 105 +++ .../{ => File}/PartitionTypesTest.php | 6 +- .../Unit/Extractor/File/ReadWindowTest.php | 36 + .../Extractor/{ => File}/SourceFileTest.php | 4 +- .../Unit/Extractor/FileConstantsTest.php | 98 --- .../Unit/Extractor/FilesExtractorTest.php | 35 + .../Unit/Extractor/Grid/HeaderNamesTest.php | 25 + .../Unit/Extractor/Grid/RecordDecoderTest.php | 382 ++++++++++ .../{ => Memory}/InMemoryRowsTest.php | 4 +- .../{ => Memory}/InferredRowsTest.php | 4 +- .../{ => Memory}/SpilledRowsTest.php | 6 +- .../Unit/Extractor/PartitionColumnsTest.php | 218 ------ .../Unit/FlowTestCaseBatchContractTest.php | 3 +- ...ionsEvaluateOnTheConfiguredBackendTest.php | 113 +++ .../Function/Evaluation/ResultColumnTest.php | 34 +- .../Function/Evaluation/ReturnTypesTest.php | 2 +- .../ETL/Tests/Unit/Function/LiteralTest.php | 30 +- .../ETL/Tests/Unit/Function/OnEachTest.php | 4 +- .../ETL/Tests/Unit/Function/ParameterTest.php | 57 -- .../tests/Flow/ETL/Tests/Unit/GroupByTest.php | 70 ++ .../Tests/Unit/Join/HashJoin/JoinerTest.php | 47 +- .../Unit/Join/HashJoin/NullRowBuilderTest.php | 14 +- .../Tests/Unit/{ => Join}/RowsJoinTest.php | 119 ++- .../Unit/Loader/File/FileWriteFrameTest.php | 156 ++++ .../File}/FilesSinkTest.php | 18 +- .../Loader/{ => File}/PartitionRouterTest.php | 22 +- .../Unit/Processor/CachingProcessorTest.php | 3 +- .../Unit/Processor/TopNProcessorTest.php | 3 +- .../Tests/Unit/Row/DeclaredColumnsTest.php | 55 -- .../Tests/Unit/Rows/ColumnRetypingTest.php | 140 ++++ .../ETL/Tests/Unit/Rows/RowEqualityTest.php | 165 ----- .../ETL/Tests/Unit/Rows/RowHashesTest.php | 3 +- .../ETL/Tests/Unit/Rows/RowsBufferTest.php | 118 --- .../ETL/Tests/Unit/Rows/RowsBuilderTest.php | 106 +++ .../ETL/Tests/Unit/RowsSerializationTest.php | 4 +- .../tests/Flow/ETL/Tests/Unit/RowsTest.php | 682 +++++++----------- .../ETL/Tests/Unit/Sort/ExternalSortTest.php | 8 +- .../Unit/Sort/Merge/BucketCursorTest.php | 18 +- .../Tests/Unit/Sort/Merge/KWayMergeTest.php | 34 +- .../Unit/Transformer/DerivedColumnsTest.php | 4 +- .../DuplicateRowTransformerTest.php | 3 +- .../ScalarFunctionTransformerTest.php | 22 +- .../Transformer/SerializeTransformerTest.php | 26 +- .../SerializedPayloadDecoderTest.php | 11 +- .../UnserializeTransformerTest.php | 35 +- .../Floe/Tests/Context/FloeFilesContext.php | 5 +- .../Tests/Context/FloeStreamReaderContext.php | 23 +- .../Tests/Integration/FloeExtractorTest.php | 48 ++ .../Tests/Integration/FloeMergeDSLTest.php | 5 +- .../Tests/Integration/FloeStatisticsTest.php | 11 +- .../Integration/FloeStreamReaderTest.php | 23 +- .../Integration/FloeWriteContractTest.php | 13 +- .../Floe/Tests/Unit/FloeFileBatchesTest.php | 138 ++++ .../Flow/Floe/Tests/Unit/FloeFileSinkTest.php | 53 ++ .../Floe/Tests/Unit/FloeFileSinksTest.php | 58 ++ .../Flow/Floe/Tests/Unit/FloeLoaderTest.php | 28 + .../Flow/Floe/Tests/Unit/FloeMergerTest.php | 90 ++- .../Flow/Floe/Tests/Unit/FloeReaderTest.php | 149 ++-- .../Floe/Tests/Unit/FloeSerializerTest.php | 48 +- .../Floe/Tests/Unit/FloeSourceFileTest.php | 2 +- .../Floe/Tests/Unit/FloeStreamReaderTest.php | 17 +- .../Floe/Tests/Unit/FloeStreamWriterTest.php | 55 +- .../Flow/Floe/Tests/Unit/FloeWriterTest.php | 88 ++- .../Flow/Floe/Tests/Unit/FooterReaderTest.php | 7 +- .../tests/Flow/Floe/Tests/Unit/FooterTest.php | 5 +- .../arrow-ext/php/Flow/Arrow/OutputStream.php | 16 - .../php/Flow/Arrow/RandomAccessFile.php | 18 - src/extension/arrow-ext/src/lib.rs | 9 - src/extension/arrow-ext/src/stream/mod.rs | 2 - .../arrow-ext/src/stream/output_stream.rs | 26 - .../src/stream/random_access_file.rs | 31 - ...6_interfaces_and_exception_registered.phpt | 26 - .../051_parquet_interfaces_reflection.phpt | 2 +- .../arrow-ext/tests/phpt/bootstrap.php | 2 - .../crates/flow-batch-frame/src/body.rs | 204 ------ .../crates/flow-batch-frame/src/format.rs | 67 -- .../crates/flow-batch-frame/src/lib.rs | 8 +- .../crates/flow-batch-frame/tests/body.rs | 202 ------ ...ustJSONEncoder.php => RustJsonEncoder.php} | 6 +- src/extension/flow-php-ext/src/builder.rs | 29 + src/extension/flow-php-ext/src/column.rs | 2 +- src/extension/flow-php-ext/src/csv/mod.rs | 16 +- src/extension/flow-php-ext/src/interfaces.rs | 13 +- src/extension/flow-php-ext/src/json/write.rs | 18 +- src/extension/flow-php-ext/src/lib.rs | 2 +- src/extension/flow-php-ext/src/plan.rs | 12 +- .../tests/phpt/001_extension_loaded.phpt | 4 +- .../tests/phpt/044_csv_ragged_rows.phpt | 2 +- .../tests/phpt/057_native_encode_parity.phpt | 6 +- .../phpt/061_native_mixed_class_building.phpt | 4 +- .../067_adopt_refuses_untyped_column.phpt | 2 +- .../tests/phpt/077_text_float_parity.phpt | 12 +- .../phpt/078_text_json_string_parity.phpt | 8 +- .../tests/phpt/081_json_write_parity.phpt | 12 +- .../tests/phpt/082_write_no_leaks.phpt | 14 +- .../tests/phpt/086_json_read_parity.phpt | 2 +- .../phpt/093_adapter_writers_contracts.phpt | 18 +- .../096_encoders_columns_left_to_php.phpt | 8 +- .../tests/phpt/098_rust_append_physicals.phpt | 42 ++ .../flow-php-ext/tests/phpt/bootstrap.php | 8 +- .../assets/codemirror/completions/dsl.js | 46 +- .../examples/topics/caching/cache/code.php | 4 +- web/landing/resources/dsl.json | 2 +- .../Website/Service/FlowConfigFactory.php | 19 +- 666 files changed, 9566 insertions(+), 7124 deletions(-) create mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileBatches.php delete mode 100644 src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVRowNormalizer.php create mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVFileBatchesTest.php delete mode 100644 src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVRowNormalizerTest.php delete mode 100644 src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php create mode 100644 src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelFileBatches.php delete mode 100644 src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php create mode 100644 src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelFileBatchesTest.php delete mode 100644 src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php delete mode 100644 src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php rename src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/{AdaptiveJSONEncoder.php => AdaptiveJsonEncoder.php} (75%) create mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileBatches.php delete mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonLinesExtractor.php rename src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/{JSONEncoder.php => JsonEncoder.php} (91%) delete mode 100644 src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php rename src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/{PhpJSONEncoder.php => PhpJsonEncoder.php} (96%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/{JSONEncoderMother.php => JsonEncoderMother.php} (64%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/{AdaptiveJSONEncoderTest.php => AdaptiveJsonEncoderTest.php} (84%) create mode 100644 src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFileBatchesTest.php rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/{PhpJSONEncoderTest.php => PhpJsonEncoderTest.php} (94%) rename src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/{RustJSONEncoderTest.php => RustJsonEncoderTest.php} (88%) create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileBatches.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileSink.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileSinks.php create mode 100644 src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFileOpener.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Double/RefusingParquetEngine.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileBatchesTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileSinkTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileSinksTest.php create mode 100644 src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileOpenerTest.php create mode 100644 src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextFileBatches.php create mode 100644 src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextOpenSink.php create mode 100644 src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextFileBatchesTest.php create mode 100644 src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextOpenSinkTest.php create mode 100644 src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLFileBatches.php create mode 100644 src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLOpenSink.php delete mode 100644 src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLReaderExtractor.php delete mode 100644 src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLReaderExtractorTest.php create mode 100644 src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLFileBatchesTest.php create mode 100644 src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLOpenSinkTest.php rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/BooleanLayout.php (97%) rename src/core/etl/src/Flow/ETL/Column/{ => Layout}/BufferLayout.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/Buffers.php (95%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/FixedBinary16Layout.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/Float64Layout.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/Int32Layout.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/Int64Layout.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/Layout.php (92%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/LayoutFor.php (98%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/NullCount.php (92%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/Offsets.php (98%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/Utf8Layout.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Layout}/Validity.php (98%) delete mode 100644 src/core/etl/src/Flow/ETL/Column/Php/Retype.php rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/DatePhysical.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/DateTimePhysical.php (98%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/DaysFromCivil.php (94%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/ElementPosition.php (98%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/EnumPhysical.php (96%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/HtmlDocumentPhysical.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/HtmlElementPhysical.php (98%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/IdentityPhysical.php (91%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/JsonFactory.php (96%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/JsonPhysical.php (96%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/ListPhysical.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/MapPhysical.php (97%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/NullPhysical.php (92%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/Physical.php (93%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/PhysicalBuilderFor.php (81%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/PhysicalFor.php (99%) create mode 100644 src/core/etl/src/Flow/ETL/Column/Physical/PhysicalKind.php rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/StructPhysical.php (98%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/TimePhysical.php (98%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/TimeZonePhysical.php (96%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/TimeZones.php (89%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/UuidPhysical.php (96%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/XmlDocumentPhysical.php (98%) rename src/core/etl/src/Flow/ETL/Column/{Php => Physical}/XmlElementPhysical.php (98%) create mode 100644 src/core/etl/src/Flow/ETL/Column/Retype.php rename src/core/etl/src/Flow/ETL/Column/{Php => }/ValueColumn.php (97%) create mode 100644 src/core/etl/src/Flow/ETL/Executor/AdoptedBatches.php rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/DeclaresPartitionTypes.php (91%) create mode 100644 src/core/etl/src/Flow/ETL/Extractor/File/DerivedSchema.php create mode 100644 src/core/etl/src/Flow/ETL/Extractor/File/FileBatches.php rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/FileColumns.php (88%) create mode 100644 src/core/etl/src/Flow/ETL/Extractor/File/FileConstants.php rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/FileExtractor.php (95%) create mode 100644 src/core/etl/src/Flow/ETL/Extractor/File/FileReadLoop.php rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/FileReading.php (96%) rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/FooterStatistics.php (96%) create mode 100644 src/core/etl/src/Flow/ETL/Extractor/File/InferredColumns.php rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/ListedFiles.php (97%) rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/ListingPartitions.php (95%) rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/MetadataColumns.php (88%) rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/MetadataColumnsExtractor.php (80%) create mode 100644 src/core/etl/src/Flow/ETL/Extractor/File/OffsetSkippingFileBatches.php rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/PartitionColumns.php (63%) rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/PartitionTypes.php (97%) rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/PathFiltering.php (97%) create mode 100644 src/core/etl/src/Flow/ETL/Extractor/File/ReadWindow.php rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/SelfDescribingFile.php (83%) rename src/core/etl/src/Flow/ETL/Extractor/{ => File}/SourceFile.php (95%) delete mode 100644 src/core/etl/src/Flow/ETL/Extractor/FileConstants.php create mode 100644 src/core/etl/src/Flow/ETL/Extractor/Grid/HeaderNames.php create mode 100644 src/core/etl/src/Flow/ETL/Extractor/Grid/RecordDecoder.php rename src/core/etl/src/Flow/ETL/Extractor/{ => Memory}/InMemoryRows.php (97%) rename src/core/etl/src/Flow/ETL/Extractor/{ => Memory}/InferredRows.php (87%) rename src/core/etl/src/Flow/ETL/Extractor/{ => Memory}/SpillState.php (92%) rename src/core/etl/src/Flow/ETL/Extractor/{ => Memory}/SpilledRows.php (99%) create mode 100644 src/core/etl/src/Flow/ETL/Join/RowsJoin.php rename src/core/etl/src/Flow/ETL/Loader/{ => File}/FileLoader.php (87%) create mode 100644 src/core/etl/src/Flow/ETL/Loader/File/FileSink.php create mode 100644 src/core/etl/src/Flow/ETL/Loader/File/FileSinks.php create mode 100644 src/core/etl/src/Flow/ETL/Loader/File/FileWriteFrame.php rename src/core/etl/src/Flow/ETL/{Filesystem => Loader/File}/FilesSink.php (90%) rename src/core/etl/src/Flow/ETL/Loader/{ => File}/PartitionRouter.php (86%) delete mode 100644 src/core/etl/src/Flow/ETL/Row/DeclaredColumns.php create mode 100644 src/core/etl/src/Flow/ETL/Rows/ColumnRetyping.php delete mode 100644 src/core/etl/src/Flow/ETL/Rows/RowEquality.php delete mode 100644 src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php create mode 100644 src/core/etl/src/Flow/Floe/FloeFileBatches.php create mode 100644 src/core/etl/src/Flow/Floe/FloeFileSink.php create mode 100644 src/core/etl/src/Flow/Floe/FloeFileSinks.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/FixedValuesColumn.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/InMemoryFileBatches.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/InMemoryUnskippableFileBatches.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Double/SpyFileSinks.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/ConfiguredBackendTest.php rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/FilesSinkTest.php (87%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/FilesSinkTestCase.php (85%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/NotPartitioned/AppendModeTest.php (92%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/NotPartitioned/ExceptionIfExistsModeTest.php (90%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/NotPartitioned/IgnoreModeTest.php (90%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/NotPartitioned/OverwriteModeTest.php (91%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/Partitioned/AppendModeTest.php (95%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/Partitioned/ExceptionIfExistsModeTest.php (94%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/Partitioned/IgnoreModeTest.php (95%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/Partitioned/OverwriteModeTest.php (95%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/Partitioned/OverwriteMultipleFilesTest.php (96%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/Partitioned/PartitionPlaceholdersTest.php (97%) rename src/core/etl/tests/Flow/ETL/Tests/Integration/{Filesystem => Loader/File}/FilesSink/tmp/.gitignore (100%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/BooleanLayoutTest.php (92%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{ => Layout}/BufferLayoutTest.php (98%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/BuffersTest.php (91%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/FixedBinary16LayoutTest.php (89%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/Float64LayoutTest.php (89%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/Int32LayoutTest.php (90%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/Int64LayoutTest.php (91%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/LayoutForTest.php (90%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/NullCountTest.php (78%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/OffsetsTest.php (96%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/Utf8LayoutTest.php (90%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Layout}/ValidityTest.php (96%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/DatePhysicalTest.php (94%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/DateTimePhysicalTest.php (95%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/DaysFromCivilTest.php (88%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/ElementPositionTest.php (96%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/EnumPhysicalTest.php (85%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/HtmlDocumentPhysicalTest.php (92%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/HtmlElementPhysicalTest.php (97%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/IdentityPhysicalTest.php (82%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/JsonFactoryTest.php (88%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/JsonPhysicalTest.php (85%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/ListPhysicalTest.php (81%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/MapPhysicalTest.php (84%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/NullPhysicalTest.php (84%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/PhysicalBuilderForTest.php (95%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/PhysicalForTest.php (91%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalKindTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/StructPhysicalTest.php (84%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/TimePhysicalTest.php (96%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/TimeZonePhysicalTest.php (85%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/TimeZonesTest.php (81%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/UuidPhysicalTest.php (90%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/XmlDocumentPhysicalTest.php (96%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => Physical}/XmlElementPhysicalTest.php (97%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => }/RetypeTest.php (60%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Column/{Php => }/ValueColumnTest.php (96%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/AdoptedBatchesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/DerivedSchemaTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => File}/FileColumnsTest.php (92%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileConstantsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileReadLoopTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => File}/FileReadingTest.php (97%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => File}/FooterStatisticsTest.php (95%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/InferredColumnsTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => File}/ListedFilesTest.php (94%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => File}/MetadataColumnsExtractorTest.php (90%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/PartitionColumnsTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => File}/PartitionTypesTest.php (95%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/ReadWindowTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => File}/SourceFileTest.php (93%) delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Grid/HeaderNamesTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Grid/RecordDecoderTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => Memory}/InMemoryRowsTest.php (93%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => Memory}/InferredRowsTest.php (96%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/{ => Memory}/SpilledRowsTest.php (98%) delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllFunctionsEvaluateOnTheConfiguredBackendTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/{ => Join}/RowsJoinTest.php (86%) create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/FileWriteFrameTest.php rename src/core/etl/tests/Flow/ETL/Tests/Unit/{Filesystem => Loader/File}/FilesSinkTest.php (79%) rename src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/{ => File}/PartitionRouterTest.php (82%) delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Row/DeclaredColumnsTest.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ColumnRetypingTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowEqualityTest.php delete mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBufferTest.php create mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileBatchesTest.php create mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileSinkTest.php create mode 100644 src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileSinksTest.php delete mode 100644 src/extension/arrow-ext/php/Flow/Arrow/OutputStream.php delete mode 100644 src/extension/arrow-ext/php/Flow/Arrow/RandomAccessFile.php delete mode 100644 src/extension/arrow-ext/src/stream/mod.rs delete mode 100644 src/extension/arrow-ext/src/stream/output_stream.rs delete mode 100644 src/extension/arrow-ext/src/stream/random_access_file.rs delete mode 100644 src/extension/arrow-ext/tests/phpt/036_interfaces_and_exception_registered.phpt delete mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs delete mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/src/format.rs delete mode 100644 src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs rename src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/{RustJSONEncoder.php => RustJsonEncoder.php} (82%) create mode 100644 src/extension/flow-php-ext/tests/phpt/098_rust_append_physicals.phpt diff --git a/documentation/components/adapters/csv.md b/documentation/components/adapters/csv.md index e1bf882572..c60d8d6223 100644 --- a/documentation/components/adapters/csv.md +++ b/documentation/components/adapters/csv.md @@ -33,6 +33,14 @@ $rows = data_frame() ->fetch(); ``` +### Header and missing cells + +``` +header row [' id ', '', 'name'] → columns ['id', 'e01', 'name'] (trimmed, a blank cell named e + its position) +record ['1', 'a'] → ['id' => '1', 'e01' => 'a', 'name' => null] (a cell the record lacks is null) +record ['1', '', 'x'] → 'e01' => null (a present '' is null; `withEmptyToNull(false)` keeps it '') +``` + ## Loader ```php diff --git a/documentation/components/adapters/excel.md b/documentation/components/adapters/excel.md index 32696c41dd..4b775bb14a 100644 --- a/documentation/components/adapters/excel.md +++ b/documentation/components/adapters/excel.md @@ -71,6 +71,16 @@ $rows = data_frame() Row numbers count from 1 and include the header row, so `->withOffset(5)` on a sheet with a header skips rows 2-4 and starts at row 5. +### Header and missing cells + +``` +header row [' id ', '', 'name'] → columns ['id', 'e01', 'name'] (trimmed, a blank cell named e + its position) +record ['1', 'a'] → ['id' => '1', 'e01' => 'a', 'name' => null] (a cell the record lacks is null) +record ['1', '', 'x'] → 'e01' => null (a present '' is null; `withConvertEmptyToNull(false)` keeps it '') +``` + +A header cell that is not text (a date, a number) is named like a blank one. + ### Schema Without a declared schema, `from_excel()` samples the workbook before the first row is read, decides one schema, and @@ -215,7 +225,9 @@ data_frame() ### Cell Styling -Apply custom styles to individual cells based on their value and the column they belong to: +Apply custom styles to individual cells based on their value and the column they belong to. `$value` is the cell as +it is written: a backed enum's value or a unit enum's name, a uuid as text, a list / map / structure as JSON text, a +date or datetime as a `DateTimeInterface`. ```php run(); ``` +### Header and missing cells + +``` +header row [' id ', '', 'name'] → columns ['id', 'e01', 'name'] (trimmed, a blank cell named e + its position) +record ['1', 'a'] → ['id' => '1', 'e01' => 'a', 'name' => null] (a cell the record lacks is null) +record ['1', '', 'x'] → 'e01' => null (a present '' is null; `withEmptyToNull(false)` keeps it '') +``` + +Blank rows before the header are skipped, also under `withHeader(false)`. + ## Needed parameters - `$auth_config` diff --git a/documentation/components/adapters/http.md b/documentation/components/adapters/http.md index 3efc01a358..e5f58ce4cc 100644 --- a/documentation/components/adapters/http.md +++ b/documentation/components/adapters/http.md @@ -170,6 +170,19 @@ data_frame() ->run(); ``` +Each response is one row and, by default, one batch. Group responses into batches with `withBatchSize()`; a pushed +limit stops sending requests once it is reached: + +```php +read(from_static_http_requests($psr18Client, $requests())->withBatchSize(50)) + ->limit(10) // 10 requests sent + ->write(to_output()) + ->run(); +``` + ## Extractor - PsrHttpClientDynamicExtractor > Reach for this only when no built-in paginator fits. It is the lowest-level extractor of the three - you hand-write diff --git a/documentation/components/core/caching.md b/documentation/components/core/caching.md index 232398f1a3..75d600b79a 100644 --- a/documentation/components/core/caching.md +++ b/documentation/components/core/caching.md @@ -52,6 +52,17 @@ data_frame() By default, Flow is using Filesystem Cache, location of the cache storage can be adjusted through the `FLOW_LOCAL_FILESYSTEM_CACHE_DIR` environment variable. +To only move the cache directory, set it on the config - the default cache keeps the pipeline's serializer +and backend: + +```php +cacheDir(__DIR__ . '/var/cache'); +``` + To use different cache implementation please use `ConfigBuilder` ```php @@ -64,7 +75,8 @@ config_builder() new PSRSimpleCache( new Psr16Cache( new ArrayAdapter() - ) + ), + new FloeSerializer(new AdaptiveBackend()), ) ); ``` @@ -105,15 +117,16 @@ A `Serializer` writes to and reads from streams, so the default `FilesystemCache directly to and from the cache file. `PSRSimpleCache` materializes the payload string - its PSR-16 backend stores string values - bounded by `cacheBatchSize`. -You can swap the serializer per cache; the default `FilesystemCache` shares the same serializer as the -rest of the pipeline (so it uses the context hydrator): +The default `FilesystemCache` shares the serializer of the rest of the pipeline (so it decodes into the configured +backend). Build one with `filesystem_cache()` only for a custom serializer or filesystem - a cache you build takes +its serializer from you: ```php read(path(__DIR__ . '/output.floe')); +$file = (new FloeReader(native_local_filesystem(), new AdaptiveBackend()))->read(path(__DIR__ . '/output.floe')); foreach ($file->head(300) as $rows) { // first 300 rows; stops reading once 300 are yielded @@ -187,11 +188,14 @@ re-reads and re-writes every batch, coalescing same-schema runs into fewer secti ```php backend()` inside a pipeline). + +| Before | After | +|---------------------------------------------------------------------------------------|--------------------------------------------------------------------------| +| `FloeReader(Filesystem, Codec = Noop, int $chunkSize = 65536, ?Hydrator, FloeEngine)` | `FloeReader(Filesystem, Backend, Codec = Noop, int $chunkSize = 65536)` | +| `FloeStreamReader(SourceStream, Codec, int $chunkSize, ?Hydrator, FloeEngine)` | `FloeStreamReader(SourceStream, Codec, int $chunkSize, Backend)` | +| `FloeWriter(Filesystem, Schema, Options = new Options(), ?Hydrator, FloeEngine)` | `FloeWriter(Filesystem, Schema, Backend, Options = new Options())` | +| `FloeStreamWriter(Schema, Options = new Options(), ?Hydrator, FloeEngine)` | `FloeStreamWriter(Schema, Backend, Options = new Options())` | +| `FloeMerger(Filesystem, ?Hydrator = null, Codec = Noop)` | `FloeMerger(Filesystem, Backend, Codec = Noop)` | +| `FloeSerializer(int $batchSize = 1000, ?Hydrator = null)` | `FloeSerializer(Backend, int $batchSize = 1000)` | +| `merge_floe(array $sources, $dest, bool $compact = false, ?Metadata, Filesystem)` | `merge_floe(array $sources, $dest, Backend, bool $compact = false, ...)` | ### 62) adapters - encoders split into decoders and encoders @@ -671,7 +677,7 @@ Project with `from_parquet(..., columns: [...])`. Change a type after reading, e | `Flow\Floe\Decoding\*`, `Flow\Floe\ValueDecoder`, `Flow\Floe\SchemaDecoder`, `Flow\Floe\ColumnBlueprint` | removed - `Flow\Floe\FrameDecoder` | | `FrameWriter::row(string $body)` | `FrameWriter::frame(int $type, string $body)` | | `ValueEncoder::{xmlDocument,xmlElement,htmlElement}ToString()`, `ValueDecoder::{xmlDocument,xmlElement,htmlDocument,htmlElement}FromString()` | removed - `(new XmlDocumentPhysical())->toPhysical()` / `fromPhysical()` and the other `Flow\ETL\Column\Php\*Physical` | -| `Flow\Floe\Decoding\TimeZones` | `Flow\ETL\Column\Php\TimeZones` | +| `Flow\Floe\Decoding\TimeZones` | `Flow\ETL\Column\Physical\TimeZones` | | `Offsets::pack()` throws `InvalidArgumentException` past 2³¹−1 | throws `Flow\ETL\Exception\OffsetOverflow` (extends `InvalidArgumentException`) | | `from_floe()->withBatchSize($n)`, `FloeReader::rows($n)` - batches of exactly `$n` rows | at most `$n` rows, never spanning two BATCH frames - re-batch with `->batchSize($n)` | | a codec wraps every frame body | a codec wraps each buffer of a BATCH frame behind an i64 uncompressed length (`-1` = stored raw); the directory stays plaintext | @@ -679,26 +685,23 @@ Project with `from_parquet(..., columns: [...])`. Change a type after reading, e | an XML/HTML value that cannot be converted to or from its string while building a column throws `FloeException` | throws `Flow\ETL\Exception\InvalidArgumentException`, same message | ### 67) `flow-php/flow-php-ext`, `flow-php/etl`, `flow-php/etl-adapter-csv` - the extension is the column backend -| Before | After | -|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------| -| `Flow\Floe\RustFloeEncoderNative`, `Flow\ETL\Row\RustRowHydratorNative` | removed | -| - | `flow_php` registers `Flow\ETL\Column\{Backend, Column, ColumnBuilder, RustBackend, RustColumn, RustColumnBuilder}` | -| any `flow_php` installs beside `flow-php/etl` | Composer refuses `ext-flow_php` < 0.45 (`conflict`); forced past it: `Class "Flow\ETL\Column\RustBackend" not found` | -| untagged builds report `0.44.1+65.g…` | `0.45.0-dev+65.g…` (next minor, pre-release) | -| `Backend` has `builder`, `constant`, `decode` | also `adopt(Definition, Column): Column` and `allocatedBytes(): int`; custom backends implement both | -| `Consumption` / `analyze()` / telemetry memory = `memory_get_usage()` | plus the configured backend's `allocatedBytes()` (native columns are not bound by `memory_limit`) | -| `new Consumption()` | `new Consumption(Backend)` | -| `new TelemetryContext(Logger, Tracer, Meter, TelemetryOptions)` | `new TelemetryContext(Backend, Logger, Tracer, Meter, TelemetryOptions)` | -| `new KWayMerge(References, int)` | `new KWayMerge(References, Backend, int)` | -| `new Joiner(Expression, Join, int)` | `new Joiner(Expression, Join, Backend, int)` | -| `AggregatedGroups::flush(int)` | `flush(int, FlowContext)` | -| `CountingProcessor::rows(int)` | `rows(int, Backend)` | -| `BucketingConfigBuilder::build(Path)`, `SortAlgorithmBuilder`, `GroupByAlgorithmBuilder`, `JoinAlgorithmBuilder`, `RepartitionAlgorithmBuilder` and their implementations `build(Path)` | `build(Path, Backend)` - custom algorithm builders implement the new signature | -| `new FilesystemBuckets(Filesystem, Path, int)` | `new FilesystemBuckets(Filesystem, Path, Backend, int)` (required) | -| sort merges, joins, group-by, `count()`, spilled bucket reads and partition filters build with `AdaptiveBackend` or `PhpBackend` | the configured backend | -| `Rows` rebuilds (`of`, the `concat` mixed lane, `matchTo` null fills, `unserialize()`), `Rows::join()`, `Rows::joinCross()` build with `PhpBackend` | `AdaptiveBackend`: native columns with the extension loaded, even under a configured `PhpBackend`, and `Consumption` does not count them | -| a CSV read with the extension and a configured `PhpBackend` | PHP columns (`Backend::adopt()`) | -| a native string/list column past 2 GiB of offsets | `OffsetOverflow` at `concat()` / `appendMany()`, as at `encode()` | +| Before | After | +|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------| +| `Flow\Floe\RustFloeEncoderNative`, `Flow\ETL\Row\RustRowHydratorNative` | removed | +| - | `flow_php` registers `Flow\ETL\Column\{Backend, Column, ColumnBuilder, RustBackend, RustColumn, RustColumnBuilder}` | +| any `flow_php` installs beside `flow-php/etl` | Composer refuses `ext-flow_php` < 0.45 (`conflict`); forced past it: `Class "Flow\ETL\Column\RustBackend" not found` | +| untagged builds report `0.44.1+65.g…` | `0.45.0-dev+65.g…` (next minor, pre-release) | +| - | `Backend`: `builder()`, `constant()`, `decode()`, `adopt(Definition, Column): Column`, `allocatedBytes(): int` | +| `Consumption` / `analyze()` / telemetry memory = `memory_get_usage()` | plus the configured backend's `allocatedBytes()` (native columns are not bound by `memory_limit`) | +| `new Consumption(bool $realMemory = true)` | `new Consumption(Backend, bool $realMemory = true)` | +| `new TelemetryContext(Logger, Tracer, Meter, TelemetryOptions)` | `new TelemetryContext(Backend, Logger, Tracer, Meter, TelemetryOptions)` | +| `new KWayMerge(References, int $batchSize = 1000)` | `new KWayMerge(References, Backend, int $batchSize = 1000)` | +| `new Joiner(Expression, Join, int $batchSize = 1000)` | `new Joiner(Expression, Join, Backend, int $batchSize = 1000)` | +| `AggregatedGroups::flush(int $batchSize)` | `flush(int $batchSize, FlowContext)` | +| `BucketingConfigBuilder::build(Path)`, `SortAlgorithmBuilder`, `GroupByAlgorithmBuilder`, `JoinAlgorithmBuilder`, `RepartitionAlgorithmBuilder` and their implementations `build(Path)` | `build(Path, Backend)` - custom algorithm builders implement the new signature | +| `new FilesystemBuckets(Filesystem, Path, int $batchSize = 1000)` | `new FilesystemBuckets(Filesystem, Path, Backend, int $batchSize = 1000)` | +| sort merges, joins, group-by, `count()`, spilled bucket reads, partition filters, CSV reads | build in the configured backend (`config_builder()->backend()`, `AdaptiveBackend` by default) - `PhpBackend` keeps PHP columns | +| - | a native string/list column past 2 GiB of offsets throws `OffsetOverflow` at `concat()` / `appendMany()` / `encode()` | ### 68) `flow-php/etl`, adapters - `RawRowValues` removed, CSV sources yield batches @@ -711,20 +714,21 @@ Project with `from_parquet(..., columns: [...])`. Change a type after reading, e ### 69) `flow-php/etl` - `Row` removed, `Rows` is a columnar batch -| Before | After | -|---------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------| -| `foreach ($df->fetch() as $row) { $row->get('x'); }` | `foreach ($df->fetch()->toArray() as $row) { $row['x']; }` | -| `$rows->first()->get('x')`, `$rows[0]->get('x')` | `$rows->column('x')->value(0)`, `$rows->values(0)['x']` | -| `$rows->first()->toArray()` | `$rows->toArray()[0]` | -| `Rows::of($schema)` | `Rows::empty($schema)` | -| `Rows::of($schema, ...$row)`, `rows($schema, ...$row)`, `$rows->add(...$row)` | `$rows->gather([...])`, `$rows->concat($other->matchTo($rows->schema()))` | -| `Rows` implements `ArrayAccess`, `IteratorAggregate` | `Countable` only | -| `Rows::all()`, `first()`, `last()`, `row()`, `offsetGet()` | removed - `toArray()`, `values(int)`, `column(string)`, `slice()`, `gather()` | -| `Rows::values(int)` outside the batch - a PHP warning and nulls, or the extension's `row N is outside [0, M)` | `InvalidArgumentException`: `Row N does not exist in a batch of M rows` | -| `Rows::unique(Comparator)`, `Row\Comparator`, `NativeComparator` | `Rows::unique()` - value equality per column | -| `array_to_row(array $data, Schema, Backend, $partitions)` | `array_to_rows([$data], Schema, Backend)` | -| `SerializedPayloadDecoder::decode(Row): Row` | `decode(Rows, int): Rows` - no payload is a one-row batch without columns | -| `Formatter\ASCII\Body::rows()` | `count()`, `value(string, int)` | +| Before | After | +|-------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| +| `foreach ($df->fetch() as $row) { $row->get('x'); }` | `foreach ($df->fetch()->toArray() as $row) { $row['x']; }` | +| `$rows->first()->get('x')`, `$rows[0]->get('x')` | `$rows->column('x')->value(0)`, `$rows->values(0)['x']` | +| `$rows->first()->toArray()` | `$rows->toArray()[0]` | +| `new Rows($schema)`, `rows($schema)` | `Rows::empty(Schema, Backend)`, `rows(Schema, Backend = new AdaptiveBackend())` | +| `new Rows($schema, ...$row)`, `rows($schema, ...$row)`, `$rows->add(...$row)` | `array_to_rows(array $data, Schema, Backend = new AdaptiveBackend())`, `$rows->concat(Backend, ...$others)`, `$rows->gather(list)` | +| `Rows` implements `ArrayAccess`, `IteratorAggregate` | `Countable` only | +| `Rows::all()`, `first()`, `last()`, `offsetGet()` | removed - `toArray()`, `values(int)`, `column(string)`, `slice(int, int)`, `gather(list)` | +| `Rows::unique(Comparator)`, `Row\Comparator`, `NativeComparator` | removed - `$df->dropDuplicates()` | +| `array_to_row(array $data, Schema, Hydrator, $partitions)` | `array_to_rows([$data], Schema, Backend = new AdaptiveBackend())` | +| `SerializedPayloadDecoder::decode(Row): array` | `decode(Rows, int $index): Rows` - no payload is a one-row batch without columns | +| `Formatter\ASCII\Body::rows(): array` | `count(): int`, `value(string $entry, int $index): mixed` | + +`Rows::values(int)` outside the batch throws `InvalidArgumentException`: `Row N does not exist in a batch of M rows`. ### 70) `flow-php/etl` - `ScalarFunction` evaluates a batch @@ -797,16 +801,15 @@ public function eval(Rows $rows, FlowContext $context): Column ### 75) `flow-php/etl` - extension points take a batch -| Before | After | -|-----------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------| -| `AggregatingFunction::aggregate(Row, FlowContext)` | `aggregate(Rows, list $indices, FlowContext)` + `merge(AggregatingFunction, FlowContext)` | -| `Join\Comparison::compare(Row, Row): bool` | `compare(Rows $left, Rows $right): list` - pairwise | -| `Constraint::isSatisfiedBy(Row, Schema)`, `violation(Row, Schema)` | `firstViolation(Rows): ?int`, `violation(Rows, int)` | -| `FrameAccumulator::accumulate(Row)` | `accumulate(Rows, int)` | -| `WindowContext::row()` | removed - `WindowContext(int, Rows, WindowFrame, FlowContext)` | -| `PeerComparator::arePeers(Row, Row, Schema)` | `arePeers(Rows, int, int)` | -| `Dataset\Statistics\Columns::add(Definition, mixed)` | `add(Definition, Column)` | -| `new KWayMerge(References, Backend, int)`, `new Joiner(Expression, Join, Backend, int)` | `new KWayMerge(References, int)`, `new Joiner(Expression, Join, int)` - output is gathered from the input columns | +| Before | After | +|--------------------------------------------------------------------|------------------------------------------------------------------------------------------------| +| `AggregatingFunction::aggregate(Row, FlowContext)` | `aggregate(Rows, list $indices, FlowContext)` + `merge(AggregatingFunction, FlowContext)` | +| `Join\Comparison::compare(Row, Row): bool` | `compare(Rows $left, Rows $right): list` - pairwise | +| `Constraint::isSatisfiedBy(Row, Schema)`, `violation(Row, Schema)` | `firstViolation(Rows): ?int`, `violation(Rows, int)` | +| `FrameAccumulator::accumulate(Row)` | `accumulate(Rows, int)` | +| `WindowContext::row()` | removed - `WindowContext(int, Rows, WindowFrame, FlowContext)` | +| `PeerComparator::arePeers(Row, Row, Schema)` | `arePeers(Rows, int, int)` | +| `Dataset\Statistics\Columns::add(Definition, mixed)` | `add(Definition, Column)` | ### 76) `flow-php/etl` - one sort order: nulls smallest, strings by bytes @@ -1092,11 +1095,11 @@ A `date` column stored that calendar day before, and still does. ### 102) `flow-php/etl` - `html_element` and `xml_element` bytes carry the owner document -| | Before | After | -|-----------------------------------------------------------|-----------------------------------------|-----------------------------------------------------------------------------------| -| the bytes an element column stores (Floe, Parquet, spill) | the element's markup | `"\x01" . . "\0" . . "\0" . . ` | -| `domElementParent()` of an element read from a column | `` or nothing, from a re-parse | the element's parent | -| `cast(type_string())`, `to_json()`, `to_csv()` | the element's markup | unchanged | +| | Before | After | +|-----------------------------------------------------------|--------------------------------------|---------------------------------------------------------------------------------| +| the bytes an element column stores (Floe, Parquet, spill) | the element's markup | `"\x01" . . "\0" . . "\0" . . ` | +| `domElementParent()` of an element read from a column | `` or nothing, from a re-parse | the element's parent | +| `cast(type_string())`, `to_json()`, `to_csv()` | the element's markup | unchanged | An element column now stores its whole owner document per value: its size grows with the document. Files written before still read. @@ -1150,6 +1153,250 @@ flow_php throws `Flow\ETL\Exception\RuntimeException`, plain `\Exception` when ` as `previous`; `FloeStreamWriter` lets it through. Both catch the base `Flow\ETL\Exception\RuntimeException` now, so its subclasses thrown while decoding are wrapped as well. +### 107) `flow-php/etl` - `RowsBuffer`, `RowEquality` and eleven `Rows` methods removed, `Rows::join*()` moved to `RowsJoin` + +| Before | After | +|---------------------------------------------------------------------------------|------------------------------------------------------------------------------------| +| `$rows->head($n)` | `$rows->take($n)` | +| `$rows->tail($n)` | `$rows->slice(max(0, $rows->count() - $n), min($n, $rows->count()))` | +| `$rows->takeRight($n)` | the `tail()` replacement - rows keep their order, not reversed | +| `$rows->sortAscending('id')` / `sortDescending('id')` | `$rows->sortBy(ref('id')->asc())` / `sortBy(ref('id')->desc())` | +| `$rows->unique()` | `df()->dropDuplicates()` | +| `$rows->diffLeft($other)`, `diffRight()`, `hash()`, `reverse()` | removed, no replacement | +| `$left->joinCross($right, $prefix)` | `(new RowsJoin($backend))->cross($left, $right, $prefix)` | +| `$left->joinInner($right, $on)`, `joinLeft`, `joinLeftAnti`, `joinRight` | `(new RowsJoin($backend))->inner($left, $right, $on)`, `left`, `leftAnti`, `right` | +| `new RowsBuffer(...)`, `new RowEquality()` | removed, no replacement | +| `$fileColumns->apply($rows)`, `$partitionColumns->apply($rows, $names, $types)` | `FileConstants::fillRows()` | +| `$rows->merge($other)` | `$rows->concat($backend, $other)` | + +`RowsJoin` is `Flow\ETL\Join\RowsJoin`. + +`concat()` requires every part to carry the receiver's schema, an empty receiver too - `merge()` adopted the other +batch's schema when the receiver was empty. Start an accumulator from `null` instead of `rows(schema())`: + +```php +// before +$all = rows(schema()); +foreach ($batches as $batch) { + $all = $all->merge($batch); +} + +// after +$all = null; +foreach ($batches as $batch) { + $all = $all === null ? $batch : $all->concat($context->backend(), $batch); +} +``` + +### 108) `flow-php/etl-adapter-xml` - `XMLReaderExtractor` removed + +| Before | After | +|-----------------------------------------------|--------------------------------------------------| +| `new XMLReaderExtractor($path, $xmlNodePath)` | `from_xml($path)->withXMLNodePath($xmlNodePath)` | + +### 109) `flow-php/arrow-ext` - `Flow\Arrow\RandomAccessFile` and `Flow\Arrow\OutputStream` removed + +| Before | After | +|------------------------------------------------------------------|-----------------------------------------| +| `class S implements Flow\Arrow\RandomAccessFile`, `OutputStream` | removed - no arrow-ext class reads them | + +### 110) `flow-php/etl` - `Parameter::asObjects()` and `Parameter::asFloats()` removed + +| Before | After | +|--------------------------------------|---------------------------------------------------------------------------------------| +| `$parameter->asObjects($rows, $ctx)` | `$parameter->asInstancesOf($rows, $ctx, $class)` or `$parameter->values($rows, $ctx)` | +| `$parameter->asFloats($rows, $ctx)` | `$parameter->asNumbers($rows, $ctx)` | + +### 111) `flow-php/etl` - `FileConstants::fill()` and `PartitionColumns::fill()` removed + +| Before | After | +|---------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| +| `$constants->fill($row)` | `[...$row, ...$constants->values()]` per row, or `$constants->fillRows($rows, $schema, $backend)` per batch | +| `$partitionColumns->fill($row, $names, $values)` | `FileConstants::values()` | +| `new FileConstants($partitionColumns, $uri, $names, $values)` | `new FileConstants($uri, $names, $values)` | + +### 112) `flow-php/etl-adapter-json` - `JsonLinesExtractor` and `JsonLinesLoader` removed + +| Before | After | +|--------------------------------------------------|--------------------------------------------------------------------------------------| +| `new JsonLinesExtractor($path, $filesystem)` | `new JsonExtractor($path, $filesystem, JsonFormat::Lines)` | +| `new JsonLinesLoader($path, $filesystem)` | `new JsonLoader($path, $filesystem, JsonFraming::Lines)` | +| `from_json_lines()` returns `JsonLinesExtractor` | returns `JsonExtractor` | +| `to_json_lines()` returns `JsonLinesLoader` | returns `JsonLoader`; `withRowsInNewLines()` on it throws `InvalidArgumentException` | + +### 113) `flow-php/etl-adapter-json`, `flow-php/flow-php-ext` - `*JSONEncoder` renamed `*JsonEncoder` + +| Before | After | +|-----------------------------------------|-----------------------------------------| +| `Flow\ETL\Adapter\JSON\JSONEncoder` | `Flow\ETL\Adapter\JSON\JsonEncoder` | +| `PhpJSONEncoder`, `AdaptiveJSONEncoder` | `PhpJsonEncoder`, `AdaptiveJsonEncoder` | +| `RustJSONEncoder` (flow_php) | `RustJsonEncoder` | + +### 114) `flow-php/etl-adapter-csv`, `-excel`, `-google-sheet` - one record rule: header names, absent cells, blank leading rows + +Header names follow the CSV rule in all three: scalar as text, trimmed, a blank cell named `e` + its position. + +``` +header row [' id ', '', 'name'] +Excel before [' id ', '', 'name'] after ['id', 'e01', 'name'] +Google Sheet before [' id ', '', 'name'] after ['id', 'e01', 'name'] +``` + +| | Before | After | +|--------------------------------------------------------------------|---------------------------------------------|------------------------------------------------------------------------------------------------| +| CSV `withEmptyToNull(false)`, short line `1,a` under `id,name,age` | `['1', 'a', '']` | `['1', 'a', null]` - an absent cell is null, `emptyToNull` only turns a present `''` into null | +| Excel header cell that is not scalar (a date) | `''` | `e` + its position | +| Google Sheet `withHeader(false)`, a blank first row | the blank row read as a row with no columns | skipped; the next row sizes the `e00`… names | + +### 115) `flow-php/etl-adapter-xml` - `XMLLoader::write()` removed + +| Before | After | +|--------------------------------------|-------------------------------------------------------------------------| +| `$loader->write($rows, $partitions)` | `$loader->load($rows, $context)` - partitions come from `partitionBy()` | + +### 116) `flow-php/etl` - the configured `Backend` reaches every batch: `Rows`, joins, Floe writers + +| Before | After | +|--------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------| +| `$rows->matchTo($schema)` | `$rows->matchTo($schema, $context->backend())` | +| `$rows->project($schema)` | `$rows->project($schema, $context->backend())` | +| `rows($schema)` (DSL) | `rows($schema)` - builds in `new AdaptiveBackend()`; `rows($schema, $backend)` builds in `$backend` | +| `$rows->project($rows->schema()->keep(...$names))` to keep columns | `$rows->select(...$names)` - the columns as they are, in schema order, no conversion | +| `new FloeWriter($filesystem, $schema, $options)` | `new FloeWriter($filesystem, $schema, $backend, $options)` | +| `new FloeStreamWriter($schema, $options)` | `new FloeStreamWriter($schema, $backend, $options)` | + +Every batch an extractor yields is adopted into the configured backend before the first step sees it - a custom +extractor that builds `PhpBackend` rows reads as `RustColumn`s under `flow_php` with the default backend, and native +rows read as PHP columns under `config_builder()->backend(new PhpBackend())`. `$rows->concat($backend, ...)` returns +columns of `$backend` too. + +`Rows::matchTo()` restamps a changed column whose type change the types prove (same kind at every level, no nested +optional → required) and reads values only for any other change; a null under NOT NULL is reported at its row. + +### 117) `flow-php/etl` - `ColumnBuilder::appendPhysicals()` added, `PhpColumnBuilder::appendPhysicalMany()` renamed + +| Before | After | +|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------| +| `class MyBuilder implements ColumnBuilder` | must add `public function appendPhysicals(array $physicals, ?int $nullCount = null): void` | +| `$phpColumnBuilder->appendPhysicalMany($physicals, $nullCount)` | `$phpColumnBuilder->appendPhysicals($physicals, $nullCount)` | + +### 118) `flow-php/etl` - `DeclaredColumns` removed + +| Before | After | +|----------------------------------------------------------------------------|--------------------------------------------------------------------------| +| `array_to_rows((new DeclaredColumns())->project($rows, $schema), $schema)` | `(new RowsBuilder($schema, $backend))->appendProjected($rows)->finish()` | + +`RowsBuilder::appendRecords($data)` is what `array_to_rows()` does; the DSL function delegates to it. + +### 119) `flow-php/etl-adapter-postgresql` - `InsertQueryBuilder::build()` takes columns + +| Before | After | +|----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------| +| `$builder->build($encoder->encode($rows), $schema, $converters, $options)` | `$builder->build($encoder->columns($rows), $rows->count(), $schema, $converters, $options)` | + +### 120) `flow-php/etl-adapter-http` - `from_static_http_requests()` takes `withBatchSize()` and honours the limit + +``` +3 requests, from_static_http_requests($client, $requests) +before: 3 batches [1 row] [1 row] [1 row] +after: 3 batches [1 row] [1 row] [1 row] (default batch size 1, as before) + +3 requests, ->withBatchSize(2) +before: no withBatchSize() +after: 2 batches [2 rows] [1 row] + +extract($context, limit: 2) over 3 requests, ->withBatchSize(5) +before: no withBatchSize(); the pushed limit was ignored +after: 1 batch [2 rows], 2 requests sent +``` + +### 121) `flow-php/etl-adapter-excel` - markup cells written, nested values rendered as text, styler gets the cell + +| | Before | After | +|--------------------------------------------|-------------------------------------------------------------------------------------------|---------------------------------------------------------| +| `html`, `html_element`, `xml_element` cell | empty | its markup, e.g. `` | +| a datetime inside a list / map / structure | `{"date":"2026-01-02 03:04:05.000000","timezone_type":3,"timezone":"UTC"}` | `"2026-01-02T03:04:05+00:00"` | +| a float inside a list / map / structure | `{"a":1}` | `{"a":1.0}` | +| a time inside a list / map / structure | `{"y":0,"m":0,"d":0,"h":1,"i":2,"s":3,"f":0,"invert":0,"days":false,"from_string":false}` | `3723000000` (microseconds, as a time column stores it) | +| `CellStyler::style($value, …)` | the logical value (an enum case, a `Uuid`, …) | the cell as written (`'one'`, `'f47ac10b-…'`, …) | + +### 122) `flow-php/etl-adapter-seal` - an `xml_element` field keeps an end tag + +| Before | After | +|---------------------|------------------------| +| `` | `` | + +### 123) `flow-php/etl-adapter-doctrine`, `flow-php/etl-adapter-postgresql` - markup bound as rendered text + +| Before | After | +|---------------------------------------------------------------------------------------|---------------------------------------------------------------| +| `xml_element` `` | `` | +| PostgreSQL `xml` `\n…\n` | `…` | +| PostgreSQL `xml` with a DOCTYPE, comments or processing instructions outside the root | the root element only - they are dropped, as DBAL already did | + +### 124) `flow-php/etl` - `ResultColumn` takes the `Backend`; functions build in the configured backend + +| Before | After | +|---------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| +| `(new ResultColumn())->of($this, $values)` in a custom function | `(new ResultColumn($context->backend()))->of($this, $values)` | +| a function's result under `flow_php` - a PHP column, copied into the extension's buffers after the step | a column of the configured backend (`RustColumn` under `flow_php`) | +| `lit()` / `on_each()` columns | built by the configured backend | + + +### 125) `flow-php/etl` - file reading and writing plumbing moved to `Extractor\File` and `Loader\File` + +Class names are unchanged; only the namespace moves. `Statistics`, `FilesExtractor`, `PathPartitionsExtractor`, +`Partitioning`, `PartitioningLoader` and `SaveMode` stay where they are. `FilesSink::touched()` and +`FilesSink::openStreams()` are removed, no replacement. + +| Before | After | +|-----------------------------------------------|----------------------------------------------------| +| `Flow\ETL\Extractor\FileExtractor` | `Flow\ETL\Extractor\File\FileExtractor` | +| `Flow\ETL\Extractor\FileReading` | `Flow\ETL\Extractor\File\FileReading` | +| `Flow\ETL\Extractor\SourceFile` | `Flow\ETL\Extractor\File\SourceFile` | +| `Flow\ETL\Extractor\FileColumns` | `Flow\ETL\Extractor\File\FileColumns` | +| `Flow\ETL\Extractor\FileConstants` | `Flow\ETL\Extractor\File\FileConstants` | +| `Flow\ETL\Extractor\PartitionColumns` | `Flow\ETL\Extractor\File\PartitionColumns` | +| `Flow\ETL\Extractor\PartitionTypes` | `Flow\ETL\Extractor\File\PartitionTypes` | +| `Flow\ETL\Extractor\DeclaresPartitionTypes` | `Flow\ETL\Extractor\File\DeclaresPartitionTypes` | +| `Flow\ETL\Extractor\PathFiltering` | `Flow\ETL\Extractor\File\PathFiltering` | +| `Flow\ETL\Extractor\SelfDescribingFile` | `Flow\ETL\Extractor\File\SelfDescribingFile` | +| `Flow\ETL\Extractor\MetadataColumns` | `Flow\ETL\Extractor\File\MetadataColumns` | +| `Flow\ETL\Extractor\MetadataColumnsExtractor` | `Flow\ETL\Extractor\File\MetadataColumnsExtractor` | +| `Flow\ETL\Loader\FileLoader` | `Flow\ETL\Loader\File\FileLoader` | +| `Flow\ETL\Loader\PartitionRouter` | `Flow\ETL\Loader\File\PartitionRouter` | +| `Flow\ETL\Filesystem\FilesSink` | `Flow\ETL\Loader\File\FilesSink` | +| `Flow\ETL\Extractor\SpillState` | `Flow\ETL\Extractor\Memory\SpillState` | +| `Flow\ETL\Extractor\SpilledRows` | `Flow\ETL\Extractor\Memory\SpilledRows` | +| `Flow\ETL\Extractor\InMemoryRows` | `Flow\ETL\Extractor\Memory\InMemoryRows` | +| `Flow\ETL\Extractor\InferredRows` | `Flow\ETL\Extractor\Memory\InferredRows` | + +### 126) `flow-php/etl` - `FloeSerializer` and the caches take the backend and the serializer explicitly + +| Before | After | +|------------------------------------------------------------|-----------------------------------------------------------------------------------------| +| `new FloeSerializer()`, `new FloeSerializer($batchSize)` | `new FloeSerializer($backend)`, `new FloeSerializer($backend, $batchSize)` | +| `new FilesystemCache($filesystem, $cacheDir, $serializer)` | `new FilesystemCache($filesystem, $serializer, $cacheDir)` | +| `new PSRSimpleCache($cache, $ttl, $serializer)` | `new PSRSimpleCache($cache, $serializer, $ttl)` | +| `new PSRCacheBuckets($cache, $prefix, $ttl, $serializer)` | `new PSRCacheBuckets($cache, $serializer, $prefix, $ttl)` | +| `filesystem_cache($cacheDir, $filesystem, $serializer)` | `filesystem_cache($serializer, $cacheDir, $filesystem)` | +| `new ApcuCache($namespace)` | `new ApcuCache($serializer, $namespace)` - entries stored as serialized strings | +| `CacheIndex::toRows()` | `toRows(Backend)` | +| `new Config(..., HashRepartitionConfig, Calculator, ...)` | `new Config(..., HashRepartitionConfig, Backend, Calculator, ...)` - `Backend` required | + +To only move the cache directory, keep the default cache - it shares the pipeline's serializer and backend: + +```php +// before +config_builder()->cache(filesystem_cache($dir)); + +// after +config_builder()->cacheDir($dir); +``` + +Build a cache yourself only for a custom serializer or filesystem; it has no default serializer any more and takes it +from its caller, e.g. `filesystem_cache(new FloeSerializer(new AdaptiveBackend()), $dir)`. + --- ## Upgrading from 0.43.x to 0.44.x 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 f4b7e8e0d6..82bd2a81ce 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 @@ -7,8 +7,8 @@ use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Extractor; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Extractor\PathFiltering; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\PathFiltering; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; @@ -37,7 +37,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - yield Rows::empty(new Schema()); + yield Rows::empty(new Schema(), $context->backend()); } public function schema(): Schema diff --git a/src/adapter/etl-adapter-avro/src/Flow/ETL/Adapter/Avro/FlixTech/AvroLoader.php b/src/adapter/etl-adapter-avro/src/Flow/ETL/Adapter/Avro/FlixTech/AvroLoader.php index cde438c30d..709d7b2f10 100644 --- a/src/adapter/etl-adapter-avro/src/Flow/ETL/Adapter/Avro/FlixTech/AvroLoader.php +++ b/src/adapter/etl-adapter-avro/src/Flow/ETL/Adapter/Avro/FlixTech/AvroLoader.php @@ -9,7 +9,7 @@ use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php index 18e99a735a..2cc53700ae 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\CSV; use Flow\ETL\Column\Backend; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php index 89ad51cd55..1db33960af 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVDecoder.php @@ -4,64 +4,39 @@ namespace Flow\ETL\Adapter\CSV; -use function array_combine; -use function array_keys; +use Flow\ETL\Extractor\Grid\RecordDecoder; + use function array_map; -use function array_values; -use function count; -use function is_numeric; -use function is_scalar; -use function is_string; use function str_getcsv; -use function str_pad; -use function trim; final class CSVDecoder { - private readonly CSVRowNormalizer $rowNormalizer; - - /** - * @var null|list - */ - private ?array $headers = null; + private readonly RecordDecoder $records; public function __construct( - private readonly bool $withHeader = true, - private readonly string $separator = ',', - private readonly string $enclosure = '"', - private readonly string $escape = '\\', + bool $withHeader = true, + private string $separator = ',', + private string $enclosure = '"', + private string $escape = '\\', bool $emptyToNull = true, ) { - $this->rowNormalizer = new CSVRowNormalizer($emptyToNull); + $this->records = new RecordDecoder($withHeader, $emptyToNull); } /** * @param list $batch * - * @return list> + * @return list> */ public function decode(array $batch): array { - $maps = []; - - foreach ($batch as $line) { - /** @var list $fields */ - $fields = str_getcsv($line, $this->separator, $this->enclosure, $this->escape); - - if ($this->headers === null) { - if ($this->withHeader) { - $this->headers = $this->mapHeaders($fields); - - continue; - } - - $this->headers = $this->generateAutoHeaders(count($fields)); - } - - $maps[] = array_combine($this->headers, $this->rowNormalizer->normalize($fields, count($this->headers))); - } - - return $maps; + /** @var list> */ + return $this->records->decode(array_map(fn(string $line): array => str_getcsv( + $line, + $this->separator, + $this->enclosure, + $this->escape, + ), $batch)); } /** @@ -72,43 +47,6 @@ public function decode(array $batch): array */ public function headers(): ?array { - return $this->headers; - } - - /** - * @return list - */ - private function generateAutoHeaders(int $count): array - { - $headers = []; - - for ($i = 0; $i < $count; $i++) { - $headers[] = 'e' . str_pad((string) $i, 2, '0', STR_PAD_LEFT); - } - - return $headers; - } - - /** - * @param array $headers - * - * @return list - */ - private function mapHeaders(array $headers): array - { - $headers = array_map(static fn(mixed $header): string => trim(match (true) { - is_string($header) => $header, - is_numeric($header) => (string) $header, - $header === null => '', - default => is_scalar($header) ? (string) $header : '', - }), $headers); - - return array_values(array_map( - static fn(string $header, int|string $index): string => $header !== '' - ? $header - : 'e' . str_pad((string) $index, 2, '0', STR_PAD_LEFT), - $headers, - array_keys($headers), - )); + return $this->records->headers(); } } 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 db1941dc16..608d094f26 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 @@ -5,16 +5,18 @@ namespace Flow\ETL\Adapter\CSV; use Flow\ETL\Cardinality; -use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Extractor\FileReading; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\FileReading; +use Flow\ETL\Extractor\File\FileReadLoop; +use Flow\ETL\Extractor\File\InferredColumns; +use Flow\ETL\Extractor\File\ListedFiles; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\ReadWindow; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\ListedFiles; -use Flow\ETL\Extractor\MetadataColumnsExtractor; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; @@ -32,9 +34,6 @@ use Flow\Types\Type\Native\String\StringTypeNarrower; use Generator; -use function array_diff; -use function array_unique; -use function array_values; use function iterator_to_array; use function sprintf; @@ -58,6 +57,11 @@ final class CSVExtractor implements */ private ?CSVSampledFiles $sampled = null; + /** + * The source the inferred header was read from; '' until an inference ran. + */ + private string $inferredFrom = ''; + private ?Schema $schema = null; private ?Statistics $statistics = null; @@ -95,75 +99,27 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $backend = $context->backend(); - $batchSize = $this->batchSize(); - $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); + $schema = $this->schema(); $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); - $reader = new CSVFileReader($this->filesystem, $this->readOptions, $sources); - - if ($this->schema !== null) { - $base = $this->schema; - } else { - // a local, not the property: withoutTail() takes a non-nullable Schema and no analyzer narrows a property - $derived = $this->derivedSchema; - - if ($derived === null) { - $samples = new CSVSamples($reader->samples($this->inference->sampleSize)); - $derived = - $this->derivedSchema = (new SchemaInferrer( - $this->inference, - new StringTypeNarrower($this->inference->candidates()->toArray()), - ))->infer($reader->header()->names, $samples); - $this->sampled = $samples->sampledFiles(); - } - - $base = $fileColumns->withoutTail($derived); - } - $schema = $fileColumns->declare($base); - $body = $fileColumns->withoutTail($schema); - $tail = $fileColumns->tail(); - $expected = $base->references()->names(); - - foreach ($sources as $source) { - // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body - $constants = $fileColumns->forFile($source, $schema); - - // before any batch is built: a cell the inferred types refuse must not hide a file whose columns diverge - if ($this->schema === null && !$this->inference->unionByName) { - $columns = array_values(array_diff(array_unique($reader->columns($source)), $tail)); - - if ( - $columns !== [] - && (array_diff($columns, $expected) !== [] || array_diff($expected, $columns) !== []) - ) { - throw InferredSchemaException::columnsDiverge( - $source->uri(), - $reader->header()->source ?? '', - $base, - $columns, + yield from (new FileReadLoop($fileColumns, $schema))->read( + $sources, + new CSVFileBatches( + new CSVFileReader($this->filesystem, $this->readOptions, $sources), + $this->schema === null && !$this->inference->unionByName + ? new InferredColumns( + $fileColumns->withoutTail($schema), + $fileColumns->tail(), $this->inference, - ); - } - } - - foreach ($reader->batches($source, $body, $batchSize, $backend) as $batch) { - $rows = $constants->fillRows($batch, $schema, $backend); - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - } + $this->inferredFrom, + ) + : null, + ), + $this->batchSize(), + $context->backend(), + new ReadWindow(limit: $limit), + ); } public function inferSchema(SchemaInferenceBuilder $builder): static @@ -194,12 +150,14 @@ public function schema(): Schema iterator_to_array($this->sourceFiles($this->filesystem, $this->path), false), ); + $header = $reader->header(); + $this->inferredFrom = $header->source ?? ''; $samples = new CSVSamples($reader->samples($this->inference->sampleSize)); $derived = $this->derivedSchema = (new SchemaInferrer( $this->inference, new StringTypeNarrower($this->inference->candidates()->toArray()), - ))->infer($reader->header()->names, $samples); + ))->infer($header->names, $samples); $this->sampled = $samples->sampledFiles(); } diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileBatches.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileBatches.php new file mode 100644 index 0000000000..230fb9caa2 --- /dev/null +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileBatches.php @@ -0,0 +1,50 @@ + $batchSize + * + * @throws InferredSchemaException + * + * @return Generator + */ + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $this->inferred?->refuseDivergence($source->uri(), $this->reader->columns($source)); + + yield from $this->reader->batches($source, $body, $batchSize, $backend); + + return 0; + } +} diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php index 085302ff4a..37ee1b541e 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileReader.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\CSV; use Flow\ETL\Column\Backend; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaSampler; diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php index e16b77672e..90d156e4ff 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVFileSample.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\CSV; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SniffsColumnTypes; diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php index 1118c25996..24ed9e40b5 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVLoader.php @@ -5,38 +5,40 @@ namespace Flow\ETL\Adapter\CSV; use DateTimeInterface; -use Flow\ETL\Config\Telemetry\TelemetryAttributes; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; use Flow\ETL\Loader\Discardable; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; +use Flow\ETL\Loader\File\FileSink; +use Flow\ETL\Loader\File\FileSinks; +use Flow\ETL\Loader\File\FileWriteFrame; +use Flow\ETL\Loader\File\PartitionRouter; use Flow\ETL\Loader\Partitioning; use Flow\ETL\Loader\PartitioningLoader; -use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; +use Flow\Filesystem\DestinationStream; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; use Flow\Filesystem\Path\Option; use Flow\Filesystem\Path\Option\ContentType; -use Throwable; use function sprintf; -final class CSVLoader implements Closure, Discardable, FileLoader, Loader, PartitioningLoader +final class CSVLoader implements Closure, Discardable, FileLoader, FileSinks, Loader, PartitioningLoader { + private ?FileWriteFrame $frame = null; + private PartitionRouter $router; private readonly Filesystem $filesystem; private SaveMode $saveMode = SaveMode::ExceptionIfExists; - private ?FilesSink $files = null; - private string $dateFormat = 'Y-m-d'; private string $dateTimeFormat = DateTimeInterface::ATOM; @@ -49,11 +51,6 @@ final class CSVLoader implements Closure, Discardable, FileLoader, Loader, Parti private ?CSVWriteOptions $options = null; - /** - * @var array by stream URI - */ - private array $sinks = []; - private string $newLineSeparator = PHP_EOL; private readonly Path $path; @@ -86,16 +83,14 @@ public function partitionBy(Partitioning $partitioning): static public function closure(FlowContext $context): void { - $this->files?->publish(); - $this->files = null; - $this->sinks = []; + $this->frame?->closure(); + $this->frame = null; } public function discard(FlowContext $context): void { - $this->files?->abandon(); - $this->files = null; - $this->sinks = []; + $this->frame?->discard(); + $this->frame = null; } public function destination(): Path @@ -109,28 +104,18 @@ public function load(Rows $rows, FlowContext $context): void return; } - $context->telemetry()->loadingStarted($this, [ - TelemetryAttributes::ATTR_LOADER_DESTINATION_URI => $this->path->uri(), - ]); - - try { - foreach ($this->router->route($rows) as [$partitions, $group]) { - $files = $this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode); - $fresh = !$files->touched($partitions->toArray()); - $stream = $files->writeTo($partitions->toArray()); - ($this->sinks[$stream->path()->uri()] ??= new CSVOpenSink( - $stream, - new AdaptiveCSVEncoder($this->options()), - $this->header && $fresh, - ))->write($group); - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } + ($this->frame ??= new FileWriteFrame( + $this->filesystem, + $this->path, + $this->saveMode, + $this->router, + $this, + ))->write($rows, $context, $this); + } + + public function open(DestinationStream $stream, Backend $backend): FileSink + { + return new CSVOpenSink($stream, new AdaptiveCSVEncoder($this->options()), $this->header); } public function saveMode(SaveMode $mode): static diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSink.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSink.php index d3bae425e1..1e57410a03 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSink.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSink.php @@ -4,12 +4,13 @@ namespace Flow\ETL\Adapter\CSV; +use Flow\ETL\Loader\File\FileSink; use Flow\ETL\Rows; use Flow\Filesystem\DestinationStream; use function array_values; -final class CSVOpenSink +final class CSVOpenSink implements FileSink { private bool $written = false; @@ -19,6 +20,11 @@ public function __construct( private readonly bool $header, ) {} + /** + * The stream belongs to the FilesSink that opened it. + */ + public function close(): void {} + public function write(Rows $rows): void { $this->stream->append( diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVRowNormalizer.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVRowNormalizer.php deleted file mode 100644 index 72208cdd50..0000000000 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVRowNormalizer.php +++ /dev/null @@ -1,51 +0,0 @@ - $rowData - * @param int $headersCount - * - * @return array - */ - public function normalize(array $rowData, int $headersCount): array - { - $rowDataCount = count($rowData); - - if ($rowDataCount < $headersCount) { - $fillValue = $this->emptyToNull ? null : ''; - - for ($i = $rowDataCount; $i < $headersCount; $i++) { - $rowData[$i] = $fillValue; - } - } elseif ($rowDataCount > $headersCount) { - $rowData = array_slice($rowData, 0, $headersCount, true); - } - - if ($this->emptyToNull) { - foreach ($rowData as $i => $data) { - if ($data === '') { - $rowData[$i] = null; - } - } - } - - return $rowData; - } -} diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php index f1c5dc0f95..5fc9496539 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Context/CSVFixtureContext.php @@ -17,7 +17,7 @@ use Flow\ETL\Column\Backend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; 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 b856293e3e..1993e6a0f5 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 @@ -17,6 +17,7 @@ use Flow\ETL\Rows; use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\RecordingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Tests\OperatingSystem; @@ -524,10 +525,10 @@ public function test_without_empty_to_null_empty_cells_are_string_evidence(): vo $schema = from_csv(CSVFixtureContext::path('file_with_empty_columns.csv'))->withEmptyToNull(false)->schema(); static::assertSame(['id', 'name', 'active'], array_keys($schema->definitions())); - - foreach ($schema->definitions() as $definition) { - static::assertSame('string', $definition->type()->toString()); - } + static::assertSame('string', $schema->get('id')->type()->toString()); + static::assertSame('string', $schema->get('name')->type()->toString()); + // the last line has no `active` cell at all: an absent cell is null, not '' evidence + static::assertSame('boolean', $schema->get('active')->type()->toString()); } public function test_partition_columns_are_not_typed_by_the_sample(): void @@ -770,13 +771,13 @@ public function test_extracting_csv_empty_columns_as_empty_strings(): void [ 'id' => '', 'name' => '', - 'active' => 'false', + 'active' => false, '_input_file_uri' => $path->uri(), ], [ 'id' => '1', 'name' => 'Norbert', - 'active' => '', + 'active' => null, '_input_file_uri' => $path->uri(), ], ], @@ -1280,4 +1281,20 @@ public function test_html_or_xml_candidates_fall_back_to_the_php_path(): void CSVFixtureContext::infer($inference, 'orders_flow.csv'), ); } + + public function test_one_extractor_read_twice_interleaved_gives_each_read_every_row_and_closes_every_stream(): void + { + $filesystem = new RecordingFilesystem(native_local_filesystem()); + [$first, $second] = ExtractedRows::interleaved((new CSVExtractor( + path_real(__DIR__ . '/../Fixtures/glob_with_empty/*.csv'), + $filesystem, + ))->withBatchSize(7)); + + static::assertGreaterThan(0, $first->count()); + static::assertSame($first->toArray(), $second->toArray()); + static::assertSame( + count(array_keys($filesystem->calls, 'readFrom', true)), + count(array_keys($filesystem->calls, 'closeSource', true)), + ); + } } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVFileBatchesTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVFileBatchesTest.php new file mode 100644 index 0000000000..78dffaa11d --- /dev/null +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVFileBatchesTest.php @@ -0,0 +1,64 @@ + "id\n1\n2\n3\n"]); + $source = new SourceFile(path('memory://a.csv')); + $file = (new CSVFileBatches(new CSVFileReader($filesystem, new CSVReadOptions(), [$source]), null))->batches( + $source, + schema(int_schema('id')), + 2, + new PhpBackend(), + new ReadWindow(), + ); + + static::assertSame( + [[['id' => 1], ['id' => 2]], [['id' => 3]]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + static::assertSame(0, $file->getReturn()); + } + + public function test_a_file_whose_header_diverges_is_refused_before_a_row_is_read(): void + { + $filesystem = new CountingFilesystem(MemoryFiles::with(['memory://b.csv' => "age\n1\n"])); + $source = new SourceFile(path('memory://b.csv')); + + try { + iterator_to_array((new CSVFileBatches( + new CSVFileReader($filesystem, new CSVReadOptions(), [$source]), + new InferredColumns(schema(int_schema('id')), [], new SchemaInference(), 'memory://a.csv'), + ))->batches($source, schema(int_schema('id')), 2, new PhpBackend(), new ReadWindow())); + static::fail('a diverging header must be refused'); + } catch (InferredSchemaException $e) { + static::assertStringContainsString('unexpected [age], missing [id]', $e->getMessage()); + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + } +} diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVLoaderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVLoaderTest.php index 21752591c5..64ee401751 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVLoaderTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVLoaderTest.php @@ -12,6 +12,7 @@ use Flow\Filesystem\Path\Option\ContentType; use function array_keys; +use function array_map; use function count; use function Flow\ETL\Adapter\CSV\to_csv; use function Flow\ETL\DSL\array_to_rows; @@ -131,4 +132,27 @@ public function test_a_discarded_loader_starts_over(): void static::assertSame("id\n2\n", $filesystem->readFrom(path('memory://out.csv'))->content()); } + + public function test_two_runs_through_one_loader_write_independent_files(): void + { + $filesystem = memory_filesystem(); + $loader = to_csv(path('memory://out.csv'), filesystem: $filesystem) + ->withNewLineSeparator("\n") + ->partitionBy(partition_by('group')); + $read = []; + + foreach (['a' => [1, 2], 'b' => [3]] as $group => $ids) { + $loader->load( + array_to_rows( + array_map(static fn(int $id): array => ['id' => $id, 'group' => $group], $ids), + schema(int_schema('id'), str_schema('group')), + ), + flow_context(), + ); + $loader->closure(flow_context()); + $read[] = $filesystem->readFrom(path('memory://group=' . $group . '/out.csv'))->content(); + } + + static::assertSame(["id\n1\n2\n", "id\n3\n"], $read); + } } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVRowNormalizerTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVRowNormalizerTest.php deleted file mode 100644 index 8be17a439d..0000000000 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/CSVRowNormalizerTest.php +++ /dev/null @@ -1,176 +0,0 @@ -normalize($rowData, $headersCount); - - static::assertSame(['value1', null, 'value3', null], $result); - static::assertCount(4, $result); - } - - public function test_normalize_converts_empty_strings_to_null_when_enabled(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = ['value1', '', 'value3', '']; - $headersCount = 4; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['value1', null, 'value3', null], $result); - } - - public function test_normalize_handles_whitespace_strings_when_empty_to_null_enabled(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = ['value1', ' ', 'value3', "\t"]; - $headersCount = 4; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['value1', ' ', 'value3', "\t"], $result); - } - - public function test_normalize_mixed_types_in_row_data(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = ['string', '', null, '0', 'false']; - $headersCount = 5; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['string', null, null, '0', 'false'], $result); - } - - public function test_normalize_preserves_array_keys_when_truncating(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = [0 => 'value1', 1 => 'value2', 2 => 'value3', 3 => 'value4']; - $headersCount = 2; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame([0 => 'value1', 1 => 'value2'], $result); - static::assertArrayHasKey(0, $result); - static::assertArrayHasKey(1, $result); - static::assertArrayNotHasKey(2, $result); - } - - public function test_normalize_preserves_empty_strings_when_disabled(): void - { - $normalizer = new CSVRowNormalizer(false); - $rowData = ['value1', '', 'value3', '']; - $headersCount = 4; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['value1', '', 'value3', ''], $result); - } - - public function test_normalize_preserves_null_values(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = ['value1', null, 'value3']; - $headersCount = 3; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['value1', null, 'value3'], $result); - } - - public function test_normalize_row_data_fewer_columns_than_headers_with_empty_to_empty_string(): void - { - $normalizer = new CSVRowNormalizer(false); - $rowData = ['value1', 'value2']; - $headersCount = 4; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['value1', 'value2', '', ''], $result); - static::assertCount(4, $result); - } - - public function test_normalize_row_data_fewer_columns_than_headers_with_empty_to_null(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = ['value1', 'value2']; - $headersCount = 4; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['value1', 'value2', null, null], $result); - static::assertCount(4, $result); - } - - public function test_normalize_row_data_more_columns_than_headers(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = ['value1', 'value2', 'value3', 'value4', 'value5']; - $headersCount = 3; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['value1', 'value2', 'value3'], $result); - static::assertCount(3, $result); - } - - public function test_normalize_row_data_same_columns_as_headers(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = ['value1', 'value2', 'value3']; - $headersCount = 3; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['value1', 'value2', 'value3'], $result); - static::assertCount(3, $result); - } - - public function test_normalize_with_empty_row_data(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = []; - $headersCount = 3; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame([null, null, null], $result); - static::assertCount(3, $result); - } - - public function test_normalize_with_empty_row_data_and_empty_to_false(): void - { - $normalizer = new CSVRowNormalizer(false); - $rowData = []; - $headersCount = 3; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame(['', '', ''], $result); - static::assertCount(3, $result); - } - - public function test_normalize_with_zero_headers(): void - { - $normalizer = new CSVRowNormalizer(true); - $rowData = ['value1', 'value2']; - $headersCount = 0; - - $result = $normalizer->normalize($rowData, $headersCount); - - static::assertSame([], $result); - static::assertCount(0, $result); - } -} diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalEncoder.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalEncoder.php index 542118b54b..b1d0d040ba 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalEncoder.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/DbalEncoder.php @@ -4,15 +4,17 @@ namespace Flow\ETL\Adapter\Doctrine; -use Dom\Element; -use Dom\XMLDocument; -use DOMDocument; -use DOMElement; -use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\TextValues; use Flow\ETL\Rows; +use Flow\Types\Type; -final class DbalEncoder +final readonly class DbalEncoder { + public function __construct( + private TextValues $text = new TextValues(), + ) {} + /** * @return list> */ @@ -21,7 +23,8 @@ public function encode(Rows $rows): array $columns = []; foreach ($rows->schema()->definitions() as $definition) { - $columns[$definition->entry()->name()] = $rows->column($definition->entry()->name())->values(); + $name = $definition->entry()->name(); + $columns[$name] = $this->column($definition->type(), $rows->column($name)); } $normalized = []; @@ -30,7 +33,7 @@ public function encode(Rows $rows): array $row = []; foreach ($columns as $name => $column) { - $row[$name] = $this->renderValue($column[$i]); + $row[$name] = $column[$i]; } $normalized[] = $row; @@ -39,49 +42,13 @@ public function encode(Rows $rows): array return $normalized; } - private function renderValue(mixed $value): mixed - { - if ($value instanceof XMLDocument) { - return $this->domString($value->saveXml($value->documentElement)); - } - - if ($value instanceof DOMDocument) { - return $this->domString($value->saveXML($value->documentElement)); - } - - if ($value instanceof Element || $value instanceof DOMElement) { - return $this->elementToString($value); - } - - return $value; - } - - private function elementToString(Element|DOMElement $value): string - { - $ownerDocument = $value->ownerDocument; - - if ($ownerDocument === null) { - return ''; - } - - if ($ownerDocument instanceof XMLDocument) { - // @mago-ignore analysis:possibly-invalid-argument - return $this->domString($ownerDocument->saveXml($value)); - } - - /** @var false|string $serialized */ - // @mago-ignore analysis:possibly-invalid-argument,non-existent-method - $serialized = $ownerDocument->saveXML($value); - - return $this->domString($serialized); - } - - private function domString(string|false $serialized): string + /** + * @param Type $type + * + * @return list + */ + public function column(Type $type, Column $column): array { - if ($serialized === false) { - throw new RuntimeException('Failed to serialize XML document.'); - } - - return $serialized; + return $this->text->bindable($type, $column); } } diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalEncoderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalEncoderTest.php index 30a1fffe6b..8caa2add87 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalEncoderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/DbalEncoderTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Doctrine\Tests\Unit; +use DateTimeImmutable; use DOMDocument; use Flow\ETL\Adapter\Doctrine\DbalEncoder; use Flow\ETL\Tests\FlowTestCase; @@ -11,6 +12,7 @@ use function array_keys; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -69,4 +71,27 @@ public function test_passes_null_through_unchanged(): void )), ); } + + public function test_renders_an_empty_xml_element_with_an_end_tag(): void + { + $doc = new DOMDocument(); + $doc->loadXML(''); + + static::assertSame( + [['e' => '']], + (new DbalEncoder())->encode(array_to_rows([[ + 'e' => $doc->getElementsByTagName('a')->item(0), + ]], schema(xml_element_schema('e')))), + ); + } + + public function test_passes_a_datetime_as_its_logical_value(): void + { + $at = new DateTimeImmutable('2026-01-02 03:04:05 UTC'); + + static::assertEquals( + [['at' => $at]], + (new DbalEncoder())->encode(array_to_rows([['at' => $at]], schema(datetime_schema('at')))), + ); + } } diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/CellStyler.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/CellStyler.php index d5553cb483..cd31c5c29e 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/CellStyler.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/CellStyler.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Excel; +use DateTimeInterface; use Flow\ETL\Schema\Definition; use OpenSpout\Common\Entity\Style\Style; @@ -12,7 +13,10 @@ interface CellStyler /** * Return a Style for the given cell, or null for default styling. * - * @param mixed $value the value being written + * @param null|bool|DateTimeInterface|float|int|string $value the cell as it is written: a backed enum's value or a + * unit enum's name, a uuid as text, a list / map / + * structure as JSON text, a date or datetime as a + * DateTimeInterface * @param Definition $definition the column the value belongs to * @param int $rowNumber the 1-based row number in the sheet (1 = first data row, not header) * @param int $columnIndex the 0-based column index diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php deleted file mode 100644 index f89b0937c3..0000000000 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelDecoder.php +++ /dev/null @@ -1,94 +0,0 @@ - - */ - private ?array $headers = null; - - public function __construct( - private readonly bool $withHeader = true, - private readonly bool $convertEmptyToNull = true, - ) {} - - /** - * @param list> $batch - * - * @return list> - */ - public function decode(array $batch): array - { - $decoded = []; - - foreach ($batch as $cells) { - if ($this->headers === null) { - if ($this->withHeader) { - $this->headers = $this->mapHeaders($cells); - - continue; - } - - $this->headers = $this->generateAutoHeaders(count($cells)); - } - - $values = []; - - foreach ($this->headers as $index => $name) { - // @mago-ignore analysis:mixed-assignment - $cell = $cells[$index] ?? null; - $values[$name] = $this->convertEmptyToNull && '' === $cell ? null : $cell; - } - - $decoded[] = $values; - } - - return $decoded; - } - - /** - * The names decode() resolved from the first row it saw; null before the first decode(). - * - * @return null|list - */ - public function headers(): ?array - { - return $this->headers; - } - - /** - * @return list - */ - private function generateAutoHeaders(int $count): array - { - $headers = []; - - for ($i = 0; $i < $count; $i++) { - $headers[] = 'e' . str_pad((string) $i, 2, '0', STR_PAD_LEFT); - } - - return $headers; - } - - /** - * @param array $cells - * - * @return list - */ - private function mapHeaders(array $cells): array - { - return array_values(array_map(static fn(mixed $header): string => is_scalar($header) - ? (string) $header - : '', $cells)); - } -} diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelEncoder.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelEncoder.php index ce926bc4a2..db5c847893 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelEncoder.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelEncoder.php @@ -7,53 +7,110 @@ use BackedEnum; use DateInterval; use DateTimeInterface; -use DateTimeZone; -use Dom\XMLDocument; -use DOMDocument; -use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\Physical\PhysicalFor; +use Flow\ETL\Column\TextValues; use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; -use Flow\Types\Type\Logical\JsonType; -use Flow\Types\Type\Logical\ListType; -use Flow\Types\Type\Logical\MapType; -use Flow\Types\Type\Logical\StructureType; use Flow\Types\Type\Logical\TimeType; -use Flow\Types\Type\Logical\TimeZoneType; -use Flow\Types\Type\Logical\UuidType; -use Flow\Types\Type\Logical\XMLType; -use Flow\Types\Type\Native\ArrayType; +use Flow\Types\Type\Native\BooleanType; use Flow\Types\Type\Native\EnumType; -use Flow\Types\Value\Json; -use Flow\Types\Value\Uuid; +use Flow\Types\Type\Native\FloatType; +use Flow\Types\Type\Native\IntegerType; +use Flow\Types\Type\Native\StringType; use UnitEnum; use function array_values; -use function is_array; -use function is_scalar; -use function json_encode; +use function count; +use function Flow\Types\DSL\type_bare; +use function Flow\Types\DSL\type_instance_of; -use const JSON_THROW_ON_ERROR; - -final class ExcelEncoder +final readonly class ExcelEncoder { public function __construct( - private readonly string $timeFormat = '%H:%I:%S', + private string $timeFormat = '%H:%I:%S', + private TextValues $text = new TextValues(), ) {} /** - * @return list> + * A column's cells read once from its physicals: scalars as they are, a datetime or date as a DateTimeInterface + * (the reader types a cell from its style, a formatted string is any other text), a time in the time format, + * a backed enum as its backing value, every other type as TextValues renders it. + * + * @param Type $type + * + * @return list + */ + public function column(Type $type, Column $column): array + { + $bare = type_bare($type); + $physicals = $column->physicals(); + + if ( + $bare instanceof StringType + || $bare instanceof IntegerType + || $bare instanceof FloatType + || $bare instanceof BooleanType + ) { + /** @var list */ + return $physicals; + } + + if ($bare instanceof DateTimeType || $bare instanceof DateType || $bare instanceof TimeType) { + $values = (new PhysicalFor())->type($bare); + $cells = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + if ($physical === null) { + $cells[] = null; + + continue; + } + + $cells[] = $bare instanceof TimeType + ? type_instance_of(DateInterval::class) + ->assert($values->fromPhysical($physical)) + ->format($this->timeFormat) + : type_instance_of(DateTimeInterface::class)->assert($values->fromPhysical($physical)); + } + + return $cells; + } + + if ($bare instanceof EnumType) { + $values = (new PhysicalFor())->type($bare); + $cells = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + $case = $physical === null + ? null + : type_instance_of(UnitEnum::class)->assert($values->fromPhysical($physical)); + $cells[] = match (true) { + $case === null => null, + $case instanceof BackedEnum => (string) $case->value, + default => $case->name, + }; + } + + return $cells; + } + + return $this->text->texts($type, $physicals); + } + + /** + * @return list> */ public function encode(Rows $rows): array { $columns = []; - $types = []; foreach ($rows->schema()->definitions() as $definition) { - $name = $definition->entry()->name(); - $columns[$name] = $rows->column($name)->values(); - $types[$name] = $definition->type(); + $columns[] = $this->column($definition->type(), $rows->column($definition->entry()->name())); } $encoded = []; @@ -61,8 +118,8 @@ public function encode(Rows $rows): array for ($i = 0, $count = $rows->count(); $i < $count; $i++) { $cells = []; - foreach ($columns as $name => $column) { - $cells[] = $this->renderValue($types[$name], $column[$i]); + for ($c = 0, $width = count($columns); $c < $width; $c++) { + $cells[] = $columns[$c][$i]; } $encoded[] = $cells; @@ -80,54 +137,4 @@ public function encodeHeader(array $headers): array { return array_values($headers); } - - private function renderValue(Type $type, mixed $value): bool|DateTimeInterface|float|int|string|null - { - if ($value === null) { - return null; - } - - return match ($type::class) { - // a real DateTimeCell, not text: the reader types a cell from its style, and a formatted string is - // indistinguishable from any other text - DateTimeType::class, DateType::class => $value instanceof DateTimeInterface ? $value : null, - TimeType::class => $value instanceof DateInterval ? $value->format($this->timeFormat) : null, - EnumType::class => match (true) { - $value instanceof BackedEnum => (string) $value->value, - $value instanceof UnitEnum => $value->name, - default => null, - }, - JsonType::class => $value instanceof Json ? $value->toString() : null, - UuidType::class => $value instanceof Uuid ? $value->toString() : null, - TimeZoneType::class => $value instanceof DateTimeZone ? $value->getName() : null, - XMLType::class => $value instanceof XMLDocument || $value instanceof DOMDocument - ? $this->xmlToString($value) - : null, - ListType::class, MapType::class, StructureType::class, ArrayType::class => is_array($value) - ? json_encode($value, JSON_THROW_ON_ERROR) - : null, - default => $this->scalar($value), - }; - } - - private function scalar(mixed $value): bool|float|int|string|null - { - return match (true) { - is_scalar($value) => $value, - default => null, - }; - } - - private function xmlToString(XMLDocument|DOMDocument $value): string - { - $serialized = $value instanceof XMLDocument - ? $value->saveXml($value->documentElement) - : $value->saveXML($value->documentElement); - - if ($serialized === false) { - throw new RuntimeException('Failed to serialize XML document.'); - } - - return $serialized; - } } 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 6a6847d4be..e079d336de 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 @@ -5,22 +5,23 @@ namespace Flow\ETL\Adapter\Excel; use Flow\ETL\Cardinality; -use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Extractor\FileReading; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\FileReading; +use Flow\ETL\Extractor\File\FileReadLoop; +use Flow\ETL\Extractor\File\InferredColumns; +use Flow\ETL\Extractor\File\ListedFiles; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\ReadWindow; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\ListedFiles; -use Flow\ETL\Extractor\MetadataColumnsExtractor; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferenceBuilder; @@ -33,8 +34,6 @@ use Generator; use Throwable; -use function array_diff; -use function array_values; use function count; use function iterator_to_array; use function sprintf; @@ -124,139 +123,33 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $backend = $context->backend(); - $batchSize = $this->batchSize(); - $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); - $workbook = new WorkbookReader($this->readOptions, new ExcelFormatDetector($this->filesystem)); + $schema = $this->schema(); // only the first extract() after an inference reads on from its sample; every later one parses afresh - $sampled = $this->sampled; + $batches = new ExcelFileBatches( + new WorkbookReader($this->readOptions, new ExcelFormatDetector($this->filesystem)), + $this->sampled, + $this->schema === null && !$this->inference->unionByName + ? new InferredColumns( + $fileColumns->withoutTail($schema), + $fileColumns->tail(), + $this->inference, + $this->inferredFrom, + ) + : null, + ); $this->sampled = null; try { - if ($this->schema !== null) { - $base = $this->schema; - } else { - // a local, not the property: withoutTail() takes a non-nullable Schema and no analyzer narrows a property - $derived = $this->derivedSchema; - - if ($derived === null) { - $sampler = new WorkbookSampler($workbook, $sources); - - try { - // one header() call: after infer() the sampler's sheets are closed and asking again reopens one - $header = $sampler->header(); - $this->inferredFrom = $header->source ?? ''; - - $derived = - $this->derivedSchema = (new SchemaInferrer( - $this->inference, - new CellTypeNarrower($this->inference->candidates()), - ))->infer($header->names, $sampler->samples($this->inference->sampleSize)); - $this->sampledRows = $sampler->sampledRows(); - $this->sampledFiles = count($sources); - } catch (Throwable $failure) { - $sampler->close(); - - throw $failure; - } - - $sampled?->close(); - $sampled = $sampler; - } - - $base = $fileColumns->withoutTail($derived); - } - - $schema = $fileColumns->declare($base); - $body = $fileColumns->withoutTail($schema); - $tail = $fileColumns->tail(); - $expected = $base->references()->names(); - - foreach ($sources as $source) { - $sheet = $sampled?->take($source) ?? $workbook->sheet($source); - - try { - if ($this->schema === null && !$this->inference->unionByName) { - $columns = array_values(array_diff($sheet->columns(), $tail)); - - if ( - $columns !== [] - && (array_diff($columns, $expected) !== [] || array_diff($expected, $columns) !== []) - ) { - throw InferredSchemaException::columnsDiverge( - $source->uri(), - $this->inferredFrom, - $base, - $columns, - $this->inference, - ); - } - } - - // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body - $constants = $fileColumns->forFile($source, $schema); - $batch = []; - - foreach ($sheet->rows() as $rowValues) { - $batch[] = $rowValues; - - if (count($batch) < $batchSize) { - continue; - } - - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows($batch) - ->finish(), - $schema, - $backend, - ); - $batch = []; - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - - if ($batch === []) { - continue; - } - - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows($batch) - ->finish(), - $schema, - $backend, - ); - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } finally { - $sheet->close(); - } - } + yield from (new FileReadLoop($fileColumns, $schema))->read( + iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false), + $batches, + $this->batchSize(), + $context->backend(), + new ReadWindow(limit: $limit), + ); } finally { - $sampled?->close(); + $batches->close(); } } diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelFileBatches.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelFileBatches.php new file mode 100644 index 0000000000..28cee6aebe --- /dev/null +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelFileBatches.php @@ -0,0 +1,90 @@ + $batchSize + * + * @throws InferredSchemaException + * + * @return Generator + */ + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $sheet = $this->sample?->take($source) ?? $this->workbook->sheet($source); + + try { + $this->inferred?->refuseDivergence($source->uri(), $sheet->columns()); + + $batch = []; + + foreach ($sheet->rows() as $rowValues) { + $batch[] = $rowValues; + + if (count($batch) < $batchSize) { + continue; + } + + yield (new RowsBuilder($body, $backend)) + ->appendRows($batch) + ->finish(); + + $batch = []; + } + + if ($batch !== []) { + yield (new RowsBuilder($body, $backend)) + ->appendRows($batch) + ->finish(); + } + } finally { + $sheet->close(); + } + + return 0; + } + + /** + * Closes the sample sheets this read did not take. + */ + public function close(): void + { + $this->sample?->close(); + } +} diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelLoader.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelLoader.php index 2563bf312b..76d9f3bc97 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelLoader.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/ExcelLoader.php @@ -4,19 +4,20 @@ namespace Flow\ETL\Adapter\Excel; +use DateTimeInterface; use Flow\ETL\Adapter\Excel\Sheet\SheetNameAssertion; use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; use Flow\ETL\Loader\Discardable; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; +use Flow\ETL\Loader\File\FilesSink; +use Flow\ETL\Loader\File\PartitionRouter; use Flow\ETL\Loader\Partitioning; use Flow\ETL\Loader\PartitioningLoader; -use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; @@ -164,7 +165,7 @@ public function load(Rows $rows, FlowContext $context): void : null; $written = $sheetColumn === null ? $group - : $group->project($group->schema()->gracefulRemove($sheetColumn)); + : $group->project($group->schema()->gracefulRemove($sheetColumn), $context->backend()); $sheetValues = $sheetColumn === null ? null : $group->column($sheetColumn)->values(); /** @var array> $sheets */ @@ -186,19 +187,11 @@ public function load(Rows $rows, FlowContext $context): void ); } - $values = []; - - foreach ($sheetRows->schema()->definitions() as $definition) { - $values[$definition->entry()->name()] = $sheetRows - ->column($definition->entry()->name()) - ->values(); - } - foreach ($encoder->encode($sheetRows) as $k => $cells) { $manager->writeRow( $sheetName, $cells, - $this->resolveCellStyles($sheetRows->schema(), $values, $k, $indices[$k] + 1, $sheetName), + $this->resolveCellStyles($sheetRows->schema(), $cells, $indices[$k] + 1, $sheetName), ); } } @@ -327,18 +320,18 @@ private function encoder(): ExcelEncoder } /** - * @param array> $values + * @param array $cells the row as the encoder wrote it * * @return null|array */ - private function resolveCellStyles(Schema $schema, array $values, int $i, int $rowNumber, string $sheetName): ?array + private function resolveCellStyles(Schema $schema, array $cells, int $rowNumber, string $sheetName): ?array { $styles = []; $columnIndex = 0; foreach ($schema->definitions() as $definition) { $styles[$columnIndex] = $this->cellStyler?->style( - $values[$definition->entry()->name()][$i], + $cells[$columnIndex], $definition, $rowNumber, $columnIndex, diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Function/IsValidExcelSheetName.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Function/IsValidExcelSheetName.php index f5cb3fbf5b..865fcb2a5c 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Function/IsValidExcelSheetName.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Function/IsValidExcelSheetName.php @@ -63,6 +63,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $sheetName === null ? null : SheetNameAssertion::isValid($sheetName); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Sheet/OpenSheet.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Sheet/OpenSheet.php index fcbe7bdd6a..286a2a63be 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Sheet/OpenSheet.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/Sheet/OpenSheet.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\Excel\Sheet; -use Flow\ETL\Adapter\Excel\ExcelDecoder; +use Flow\ETL\Extractor\Grid\RecordDecoder; use Generator; use OpenSpout\Reader\ODS\Reader as OdsReader; use OpenSpout\Reader\XLSX\Reader as XlsxReader; @@ -20,7 +20,7 @@ public function __construct( private XlsxReader|OdsReader $reader, public Generator $cells, - public ExcelDecoder $decoder, + public RecordDecoder $decoder, ) {} public function close(): void diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookReader.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookReader.php index 0295f7f424..8a05b6fe31 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookReader.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookReader.php @@ -8,7 +8,8 @@ use Flow\ETL\Adapter\Excel\Sheet\SheetCells; use Flow\ETL\Adapter\Excel\Sheet\SheetsManager; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; +use Flow\ETL\Extractor\Grid\RecordDecoder; use Flow\Filesystem\Path; use OpenSpout\Reader\ODS\Reader as OdsReader; use OpenSpout\Reader\XLSX\Reader as XlsxReader; @@ -41,10 +42,7 @@ public function open(Path $path): OpenSheet return new OpenSheet( $reader, (new SheetCells($sheet, $this->options->withHeader, $this->options->offset))->rows(), - new ExcelDecoder( - withHeader: $this->options->withHeader, - convertEmptyToNull: $this->options->convertEmptyToNull, - ), + new RecordDecoder(withHeader: $this->options->withHeader, emptyToNull: $this->options->convertEmptyToNull), ); } diff --git a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSampler.php b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSampler.php index fb2e0bf2ed..b3109d71ab 100644 --- a/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSampler.php +++ b/src/adapter/etl-adapter-excel/src/Flow/ETL/Adapter/Excel/WorkbookSampler.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\Excel; use Flow\ETL\Cardinality; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema\Inference\SchemaSampler; use Generator; diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Context/ExcelFixtureContext.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Context/ExcelFixtureContext.php index 956f1e8acb..9f3fc90a8f 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Context/ExcelFixtureContext.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Context/ExcelFixtureContext.php @@ -13,7 +13,7 @@ use Flow\ETL\Adapter\Excel\WorkbookReader; use Flow\ETL\Adapter\Excel\WorkbookSampler; use Flow\ETL\Adapter\Excel\WorkbookSheet; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferrer; 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 c86d46c612..e4ad96e056 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 @@ -868,15 +868,17 @@ public function test_the_listing_is_read_once(): void static::assertSame(1, $filesystem->listCalls); } - public function test_a_filtered_extract_declares_unknown_rows(): void + public function test_a_filtered_extract_infers_over_every_listed_file(): void { - $extractor = from_excel(ExcelFixtureContext::path('sniff/*')); + $filtered = from_excel(ExcelFixtureContext::path('sniff/*')); + $whole = from_excel(ExcelFixtureContext::path('sniff/*')); - iterator_to_array($extractor->extract(flow_context(), null, new KeepPaths([ExcelFixtureContext::path( + iterator_to_array($filtered->extract(flow_context(), null, new KeepPaths([ExcelFixtureContext::path( 'sniff/a', )])), false); + $whole->schema(); - static::assertEquals(Cardinality::unknown(), $extractor->statistics()->rows); + static::assertEquals($whole->statistics()->rows, $filtered->statistics()->rows); } public function test_date_cell_in_a_zoned_column_is_converted(): void @@ -946,4 +948,14 @@ public function test_extract_builds_through_the_config_backend(): void static::assertGreaterThanOrEqual(1, $backend->builders()); } + + public function test_one_extractor_read_twice_interleaved_gives_each_read_every_row(): void + { + $extractor = from_excel(ExcelFixtureContext::path('sniff/*'))->withBatchSize(1); + $extractor->schema(); + [$first, $second] = ExtractedRows::interleaved($extractor); + + static::assertGreaterThan(0, $first->count()); + static::assertSame($first->toArray(), $second->toArray()); + } } diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/Sheet/OpenSheetTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/Sheet/OpenSheetTest.php index ef688d1abd..03043593b6 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/Sheet/OpenSheetTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Integration/Sheet/OpenSheetTest.php @@ -4,11 +4,11 @@ namespace Flow\ETL\Adapter\Excel\Tests\Integration\Sheet; -use Flow\ETL\Adapter\Excel\ExcelDecoder; use Flow\ETL\Adapter\Excel\Sheet\OpenSheet; use Flow\ETL\Adapter\Excel\Sheet\SheetCells; use Flow\ETL\Adapter\Excel\Sheet\SheetsManager; use Flow\ETL\Adapter\Excel\Tests\Context\ExcelFixtureContext; +use Flow\ETL\Extractor\Grid\RecordDecoder; use Flow\ETL\Tests\FlowTestCase; use OpenSpout\Reader\Exception\ReaderNotOpenedException; use OpenSpout\Reader\XLSX\Reader as XlsxReader; @@ -23,7 +23,7 @@ public function test_it_carries_the_cells_and_the_decoder_of_one_handle(): void $open = new OpenSheet( $reader, (new SheetCells((new SheetsManager($reader->getSheetIterator()))->first(), true, 1))->rows(), - $decoder = new ExcelDecoder(), + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true), ); static::assertSame(['id', 'name', 'email'], $open->cells->current()); @@ -40,7 +40,7 @@ public function test_closing_it_closes_the_reader_it_was_given(): void (new OpenSheet( $reader, (new SheetCells((new SheetsManager($reader->getSheetIterator()))->first(), true, 1))->rows(), - new ExcelDecoder(), + new RecordDecoder(withHeader: true, emptyToNull: true), ))->close(); $this->expectException(ReaderNotOpenedException::class); diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php deleted file mode 100644 index 8317e50140..0000000000 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelDecoderTest.php +++ /dev/null @@ -1,77 +0,0 @@ -decode([['id', 'name']])); - static::assertSame(['id' => 1, 'name' => 'Norbert'], $decoder->decode([[1, 'Norbert']])[0]); - } - - public function test_decode_generates_auto_headers_when_header_is_disabled(): void - { - static::assertSame( - ['e00' => 1, 'e01' => 'Norbert'], - (new ExcelDecoder(withHeader: false))->decode([[1, 'Norbert']])[0], - ); - } - - public function test_headers_are_generated_when_header_is_disabled(): void - { - $decoder = new ExcelDecoder(withHeader: false); - - static::assertCount(1, $decoder->decode([[1, 2, 3]])); - static::assertSame(['e00', 'e01', 'e02'], $decoder->headers()); - } - - public function test_headers_are_null_before_the_first_decode(): void - { - static::assertNull((new ExcelDecoder())->headers()); - } - - public function test_headers_are_stringified_and_blank_for_non_scalar_cells(): void - { - $decoder = new ExcelDecoder(); - $decoder->decode([[1, null, 'x']]); - - static::assertSame(['1', '', 'x'], $decoder->headers()); - } - - public function test_headers_are_the_header_row_after_decode(): void - { - $decoder = new ExcelDecoder(); - - static::assertSame([], $decoder->decode([['id', 'name']])); - static::assertSame(['id', 'name'], $decoder->headers()); - } - - public function test_decode_keeps_empty_cells_when_convert_empty_to_null_is_disabled(): void - { - static::assertSame( - ['id' => 1, 'name' => ''], - (new ExcelDecoder(convertEmptyToNull: false))->decode([['id', 'name'], [1, '']])[0], - ); - } - - public function test_decode_maps_cells_to_headers(): void - { - static::assertSame( - ['id' => 1, 'name' => 'Norbert'], - (new ExcelDecoder())->decode([['id', 'name'], [1, 'Norbert']])[0], - ); - } - - public function test_decode_turns_empty_cells_into_null_by_default(): void - { - static::assertSame(['id' => 1, 'name' => null], (new ExcelDecoder())->decode([['id', 'name'], [1, '']])[0]); - } -} diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelEncoderTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelEncoderTest.php index cf0bc3f9bf..028c6e779f 100644 --- a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelEncoderTest.php +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelEncoderTest.php @@ -7,12 +7,14 @@ use DateInterval; use DateTimeImmutable; use DateTimeZone; +use Dom\HTMLDocument; use DOMDocument; use Flow\ETL\Adapter\Excel\ExcelEncoder; use Flow\ETL\Tests\Fixtures\Enum\BackedIntEnum; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; use Flow\ETL\Tests\FlowTestCase; use Flow\Types\Value\Uuid; +use PHPUnit\Framework\Attributes\RequiresPhp; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; @@ -20,7 +22,10 @@ use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\enum_schema; use function Flow\ETL\DSL\float_schema; +use function Flow\ETL\DSL\html_element_schema; +use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\schema; @@ -29,7 +34,10 @@ use function Flow\ETL\DSL\time_schema; use function Flow\ETL\DSL\time_zone_schema; use function Flow\ETL\DSL\uuid_schema; +use function Flow\ETL\DSL\xml_element_schema; use function Flow\ETL\DSL\xml_schema; +use function Flow\Types\DSL\type_datetime; +use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_list; use function Flow\Types\DSL\type_map; @@ -149,4 +157,68 @@ public function test_encodes_null_values_as_null_cells(): void )), ); } + + public function test_encodes_an_xml_element_as_its_markup(): void + { + $document = new DOMDocument(); + $document->loadXML('x'); + + static::assertSame( + [['x']], + (new ExcelEncoder())->encode(array_to_rows([[ + 'e' => $document->getElementsByTagName('a')->item(0), + ]], schema(xml_element_schema('e')))), + ); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_encodes_html_and_html_elements_as_their_markup(): void + { + // @mago-ignore analysis:unavailable-method + $document = HTMLDocument::createFromString('

      hi

      ', LIBXML_NOERROR); + $element = $document->querySelector('p'); + + $cells = (new ExcelEncoder())->encode(array_to_rows( + [['h' => $document, 'e' => $element]], + schema(html_schema('h'), html_element_schema('e')), + ))[0]; + + static::assertIsString($cells[0]); + static::assertStringContainsString('

      hi

      ', $cells[0]); + static::assertSame('

      hi

      ', $cells[1]); + } + + public function test_encodes_a_datetime_column_with_nulls_as_datetimes_and_null_cells(): void + { + $cells = (new ExcelEncoder())->encode(array_to_rows([ + ['at' => new DateTimeImmutable('2026-01-02 03:04:05 UTC')], + ['at' => null], + ], schema(datetime_schema('at', nullable: true)))); + + static::assertInstanceOf(DateTimeImmutable::class, $cells[0][0]); + static::assertSame('2026-01-02T03:04:05+00:00', $cells[0][0]->format(DATE_ATOM)); + static::assertNull($cells[1][0]); + } + + public function test_encodes_a_json_column_as_its_text(): void + { + static::assertSame( + [['{"a":1}']], + (new ExcelEncoder())->encode(array_to_rows([['j' => '{"a":1}']], schema(json_schema('j')))), + ); + } + + public function test_encodes_nested_datetimes_as_text_and_keeps_float_fractions(): void + { + static::assertSame( + [['["2026-01-02T03:04:05+00:00"]', '{"a":1.0}']], + (new ExcelEncoder())->encode(array_to_rows( + [['l' => [new DateTimeImmutable('2026-01-02 03:04:05 UTC')], 'm' => ['a' => 1.0]]], + schema( + list_schema('l', type_list(type_datetime())), + map_schema('m', type_map(type_string(), type_float())), + ), + )), + ); + } } diff --git a/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelFileBatchesTest.php b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelFileBatchesTest.php new file mode 100644 index 0000000000..ad2484409e --- /dev/null +++ b/src/adapter/etl-adapter-excel/tests/Flow/ETL/Adapter/Excel/Tests/Unit/ExcelFileBatchesTest.php @@ -0,0 +1,102 @@ +batches( + ExcelFixtureContext::source('fixture.xlsx'), + $schema, + 2, + new PhpBackend(), + new ReadWindow(), + ); + $rows = array_merge(...array_map( + static fn(Rows $batch): array => $batch->toArray(), + iterator_to_array($fromSample, false), + )); + $sampled->close(); + + static::assertNotSame([], $rows); + static::assertSame(0, $fromSample->getReturn()); + static::assertSame( + $rows, + array_merge(...array_map( + static fn(Rows $batch): array => $batch->toArray(), + iterator_to_array( + $fresh->batches( + ExcelFixtureContext::source('fixture.xlsx'), + $schema, + 2, + new PhpBackend(), + new ReadWindow(), + ), + false, + ), + )), + ); + static::assertSame([], ExcelFixtureContext::leakedSharedStringsFoldersSince($before)); + } + + public function test_close_releases_the_sampled_sheets_the_read_never_took(): void + { + $before = ExcelFixtureContext::sharedStringsFolders(); + $sampler = ExcelFixtureContext::globSampler('diverging_header/*.xlsx'); + ExcelFixtureContext::infer($sampler); + + (new ExcelFileBatches(ExcelFixtureContext::reader(), $sampler, null))->close(); + + static::assertSame([], ExcelFixtureContext::leakedSharedStringsFoldersSince($before)); + } + + public function test_a_sheet_whose_header_diverges_is_refused_and_closed(): void + { + $before = ExcelFixtureContext::sharedStringsFolders(); + $sampler = ExcelFixtureContext::sampler('diverging_header/a.xlsx'); + $schema = ExcelFixtureContext::infer($sampler); + $sampler->close(); + + try { + iterator_to_array((new ExcelFileBatches( + ExcelFixtureContext::reader(), + null, + new InferredColumns($schema, [], new SchemaInference(), 'a.xlsx'), + ))->batches( + ExcelFixtureContext::source('diverging_header/b.xlsx'), + $schema, + 2, + new PhpBackend(), + new ReadWindow(), + )); + static::fail('a diverging header must be refused'); + } catch (InferredSchemaException $e) { + static::assertStringContainsString('the schema inferred from a.xlsx', $e->getMessage()); + } + + static::assertSame([], ExcelFixtureContext::leakedSharedStringsFoldersSince($before)); + } +} diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php deleted file mode 100644 index 2622644769..0000000000 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetDecoder.php +++ /dev/null @@ -1,119 +0,0 @@ - - */ - private array $headers = []; - - private int $headersCount = 0; - - public function __construct( - private readonly bool $withHeader = true, - private readonly bool $dropExtraColumns = true, - private readonly bool $emptyToNull = true, - ) {} - - /** - * @param list> $batch - * - * @return list> - */ - public function decode(array $batch): array - { - $maps = []; - - foreach ($batch as $rowData) { - $rowDataCount = count($rowData); - - if ($this->withHeader) { - if ([] === $this->headers) { - if ([] === $rowData) { - continue; - } - - /** @var list $rowData */ - $this->headers = array_map( - static fn(bool|float|int|string $header): string => (string) $header, - $rowData, - ); - $this->headersCount = $rowDataCount; - - continue; - } - } elseif (0 === $this->headersCount) { - $this->headersCount = $rowDataCount; - } - - for ($i = $rowDataCount; $i < $this->headersCount; $i++) { - $rowData[$i] = null; - } - - if ($rowDataCount > $this->headersCount) { - if (!$this->dropExtraColumns) { - throw InvalidArgumentException::because( - 'Row has more columns (%d) than headers (%d)', - $rowDataCount, - $this->headersCount, - ); - } - - $rowData = array_slice($rowData, 0, $this->headersCount); - } - - if ($this->emptyToNull) { - foreach (array_keys($rowData) as $i) { - if ($rowData[$i] === '') { - $rowData[$i] = null; - } - } - } - - $maps[] = array_combine( - $this->withHeader ? $this->headers : $this->generateAutoHeaders(count($rowData)), - $rowData, - ); - } - - return $maps; - } - - /** - * The header the first decoded row consumed, or the generated `e00`... names under withHeader(false); - * [] before any row. - * - * @return list - */ - public function headers(): array - { - return $this->withHeader ? $this->headers : $this->generateAutoHeaders($this->headersCount); - } - - /** - * @return list - */ - private function generateAutoHeaders(int $count): array - { - $headers = []; - - for ($i = 0; $i < $count; $i++) { - $headers[] = 'e' . str_pad((string) $i, 2, '0', STR_PAD_LEFT); - } - - return $headers; - } -} 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 6a73897499..66fc196333 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,9 +10,9 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; +use Flow\ETL\Extractor\File\MetadataColumns; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\MetadataColumns; -use Flow\ETL\Extractor\MetadataColumnsExtractor; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReadOptions.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReadOptions.php index 9d32fa7a43..7ed557043b 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReadOptions.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReadOptions.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\GoogleSheet; +use Flow\ETL\Extractor\Grid\RecordDecoder; use Flow\ETL\Schema\Inference\InferredTypes; use Flow\Types\Type\Logical\InstanceOfTypeNarrower; use Flow\Types\Type\Native\String\StringTypeNarrower; @@ -27,9 +28,9 @@ public function __construct( /** * A fresh decoder per pass - the sample and the read each consume their own header row. */ - public function decoder(): GoogleSheetDecoder + public function decoder(): RecordDecoder { - return new GoogleSheetDecoder($this->withHeader, $this->dropExtraColumns, $this->emptyToNull); + return new RecordDecoder($this->withHeader, $this->emptyToNull, $this->dropExtraColumns); } /** diff --git a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php index 49eaa1a3b9..144971b62d 100644 --- a/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php +++ b/src/adapter/etl-adapter-google-sheet/src/Flow/ETL/Adapter/GoogleSheet/GoogleSheetReader.php @@ -94,6 +94,6 @@ public function sample(int $rows): GoogleSheetSample $values->get($this->spreadsheetId, $range->toString(), $this->readOptions->options)->getValues() ?? [], )); - return new GoogleSheetSample($decoder->headers(), $decoded, $range->endRow >= $rowCount, $rowCount); + return new GoogleSheetSample($decoder->headers() ?? [], $decoded, $range->endRow >= $rowCount, $rowCount); } } diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php deleted file mode 100644 index 9a38cb4e37..0000000000 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetDecoderTest.php +++ /dev/null @@ -1,188 +0,0 @@ -decode([ - ['id', 'name'], - ['1', 'Norbert'], - ['2', 'Tomek'], - ]); - - static::assertSame( - [ - ['id' => '1', 'name' => 'Norbert'], - ['id' => '2', 'name' => 'Tomek'], - ], - $decoded, - ); - } - - public function test_skips_empty_rows_before_headers(): void - { - $decoder = new GoogleSheetDecoder(); - - $decoded = $decoder->decode([ - [], - ['id', 'name'], - ['1', 'Norbert'], - ]); - - static::assertSame([['id' => '1', 'name' => 'Norbert']], $decoded); - } - - public function test_keeps_headers_between_decode_calls(): void - { - $decoder = new GoogleSheetDecoder(); - - $decoder->decode([['id', 'name'], ['1', 'Norbert']]); - - static::assertSame([['id' => '2', 'name' => 'Tomek']], $decoder->decode([['2', 'Tomek']])); - } - - public function test_pads_shorter_rows_with_nulls(): void - { - $decoder = new GoogleSheetDecoder(); - - $decoded = $decoder->decode([ - ['id', 'name'], - ['1'], - ]); - - static::assertSame([['id' => '1', 'name' => null]], $decoded); - } - - public function test_drops_extra_columns(): void - { - $decoder = new GoogleSheetDecoder(); - - $decoded = $decoder->decode([ - ['id', 'name'], - ['1', 'Norbert', 'extra'], - ]); - - static::assertSame([['id' => '1', 'name' => 'Norbert']], $decoded); - } - - public function test_throws_on_extra_columns_when_drop_is_disabled(): void - { - $decoder = new GoogleSheetDecoder(dropExtraColumns: false); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Row has more columns (3) than headers (2)'); - - $decoder->decode([ - ['id', 'name'], - ['1', 'Norbert', 'extra'], - ]); - } - - public function test_generates_auto_headers_without_header_row(): void - { - $decoder = new GoogleSheetDecoder(withHeader: false); - - $decoded = $decoder->decode([ - ['1', 'Norbert'], - ['2', 'Tomek'], - ]); - - static::assertSame( - [ - ['e00' => '1', 'e01' => 'Norbert'], - ['e00' => '2', 'e01' => 'Tomek'], - ], - $decoded, - ); - } - - public function test_empty_cells_become_null_by_default(): void - { - $decoder = new GoogleSheetDecoder(); - - static::assertSame([['a' => null, 'b' => 'x']], $decoder->decode([['a', 'b'], ['', 'x']])); - } - - public function test_empty_cells_stay_strings_when_asked(): void - { - $decoder = new GoogleSheetDecoder(emptyToNull: false); - - static::assertSame([['a' => '', 'b' => 'x']], $decoder->decode([['a', 'b'], ['', 'x']])); - } - - public function test_omitted_trailing_cells_are_null_regardless_of_empty_to_null(): void - { - static::assertSame( - [['a' => 'x', 'b' => null]], - (new GoogleSheetDecoder())->decode([ - ['a', 'b'], - ['x'], - ]), - ); - static::assertSame( - [['a' => 'x', 'b' => null]], - (new GoogleSheetDecoder(emptyToNull: false))->decode([['a', 'b'], ['x']]), - ); - } - - public function test_headers_are_empty_before_the_first_row(): void - { - static::assertSame([], (new GoogleSheetDecoder())->headers()); - } - - public function test_headers_are_the_consumed_header_row(): void - { - $decoder = new GoogleSheetDecoder(); - $decoder->decode([['a', 'b'], ['1', '2']]); - - static::assertSame(['a', 'b'], $decoder->headers()); - } - - public function test_headers_skip_a_leading_empty_row(): void - { - $decoder = new GoogleSheetDecoder(); - $decoder->decode([[], ['a', 'b']]); - - static::assertSame(['a', 'b'], $decoder->headers()); - } - - public function test_headers_are_generated_without_a_header_row(): void - { - $decoder = new GoogleSheetDecoder(withHeader: false); - $decoder->decode([['1', '2', '3']]); - - static::assertSame(['e00', 'e01', 'e02'], $decoder->headers()); - } - - public function test_headers_are_strings_even_when_the_api_typed_them(): void - { - $decoder = new GoogleSheetDecoder(); - $decoder->decode([[1, '2'], ['x', 'y']]); - - static::assertSame(['1', '2'], $decoder->headers()); - } - - /** - * b88, pinned as it behaves rather than as it should: `1` and `true` both stringify to `'1'`, and - * array_combine() keeps the last value under a repeated key, so the row loses a column. Not specific to a - * typed header - `a,a` does the same in CSV - and not introduced by inference. - */ - public function test_two_header_cells_with_the_same_name_collapse_the_row_to_one_column(): void - { - $decoder = new GoogleSheetDecoder(); - $decoded = $decoder->decode([[1, true], ['x', 'y']]); - - static::assertSame(['1', '1'], $decoder->headers()); - static::assertSame(['1' => 'y'], $decoded[0]); - } -} diff --git a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php index 82f8963689..6ae6e9b50d 100644 --- a/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php +++ b/src/adapter/etl-adapter-google-sheet/tests/Flow/ETL/Adapter/GoogleSheet/Tests/Unit/GoogleSheetExtractorTest.php @@ -508,10 +508,9 @@ public function test_a_leading_blank_row_without_a_header_is_not_a_divergence(): $rows, )], [SheetValuesMother::batch([$rows])]); - // 3, not 2: the blank row still decodes to a column-less row, as it did before inference existed. What this - // pins is that the divergence check no longer reads that row as "every column is missing". + // a leading blank row is skipped before the generated header is sized, so the two data rows keep their columns self::assertExtractedRowsCount( - 3, + 2, GoogleSheetFixtureContext::extractor(GoogleSheetFixtureContext::service(100, $values))->withHeader(false), ); } 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 acb15cdd02..66651a3c10 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 @@ -5,6 +5,8 @@ namespace Flow\ETL\Adapter\Http; use Flow\ETL\Extractor; +use Flow\ETL\Extractor\BatchableExtractor; +use Flow\ETL\Extractor\Batches; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; @@ -24,8 +26,10 @@ use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_string; -final class PsrHttpClientStaticExtractor implements Extractor +final class PsrHttpClientStaticExtractor implements BatchableExtractor, Extractor { + use Batches; + /** * @var null|callable(RequestInterface, ResponseInterface) : void */ @@ -44,7 +48,10 @@ final class PsrHttpClientStaticExtractor implements Extractor public function __construct( private readonly ClientInterface $client, private readonly iterable $requests, - ) {} + ) { + // one request is one row: each response reaches the pipeline on its own unless withBatchSize() groups them + $this->batchSize = 1; + } /** * @return Generator @@ -53,6 +60,9 @@ public function extract(FlowContext $context, ?int $limit = null): Generator { $decoder = new HttpDecoder(); $backend = $context->backend(); + $schema = $this->schema(); + $builder = new RowsBuilder($schema, $backend); + $remaining = $limit; foreach ($this->requests as $request) { if ($this->preRequest) { @@ -65,15 +75,25 @@ public function extract(FlowContext $context, ?int $limit = null): Generator ($this->postRequest)($request, $response); } - $rows = (new RowsBuilder($this->schema(), $backend)) - ->appendRows($decoder->decode([new HttpExchange($request, $response)])) - ->finish(); + $builder->appendRows($decoder->decode([new HttpExchange($request, $response)])); + + if ($builder->count() < $this->batchSize() && ($remaining === null || $builder->count() < $remaining)) { + continue; + } - $signal = yield $rows; + $batch = $builder->finish(); + $remaining = $remaining === null ? null : $remaining - $batch->count(); + $signal = yield $batch; - if ($signal === Signal::STOP) { + if ($signal === Signal::STOP || $remaining === 0) { return; } + + $builder = new RowsBuilder($schema, $backend); + } + + if ($builder->count() > 0) { + yield $builder->finish(); } } diff --git a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientExtractorBatchContractTest.php b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientExtractorBatchContractTest.php index 546b40da2b..6305823cd8 100644 --- a/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientExtractorBatchContractTest.php +++ b/src/adapter/etl-adapter-http/tests/Flow/ETL/Adapter/HTTP/Tests/Integration/PsrHttpClientExtractorBatchContractTest.php @@ -24,8 +24,8 @@ use function iterator_to_array; /** - * One exchange is one row by construction, so these extractors take no batch size: every batch holds - * exactly one row, and the batches together hold every exchange, in order. + * One exchange is one row. The dynamic and paginated extractors yield one row per batch; the static one does too + * unless withBatchSize() groups exchanges, and it never sends more requests than the limit asks for. */ final class PsrHttpClientExtractorBatchContractTest extends FlowTestCase { @@ -147,4 +147,49 @@ public function test_static_extractor_yields_one_row_per_batch_and_every_exchang array_map(static fn(Rows $rows): mixed => $rows->column('request_uri')->value(0), $batches), ); } + + public function test_a_static_extractor_groups_exchanges_into_batches_of_its_batch_size(): void + { + $factory = new Psr17Factory(); + $client = new Client($factory); + + foreach ([1, 2, 3] as $id) { + $client->addResponse(new Response(200, [], '{"id":' . $id . '}')); + } + + $batches = iterator_to_array( + from_static_http_requests($client, array_map(static fn(int $id) => $factory->createRequest( + 'GET', + 'https://api.example.com/' . $id, + ), [1, 2, 3])) + ->withBatchSize(2) + ->extract(flow_context(config())), + false, + ); + + static::assertSame([2, 1], array_map(static fn(Rows $rows): int => $rows->count(), $batches)); + } + + public function test_a_static_extractor_sends_no_more_requests_than_the_limit_and_caps_the_batch(): void + { + $factory = new Psr17Factory(); + $client = new Client($factory); + + foreach ([1, 2, 3] as $id) { + $client->addResponse(new Response(200, [], '{"id":' . $id . '}')); + } + + $batches = iterator_to_array( + from_static_http_requests($client, array_map(static fn(int $id) => $factory->createRequest( + 'GET', + 'https://api.example.com/' . $id, + ), [1, 2, 3])) + ->withBatchSize(5) + ->extract(flow_context(config()), 2), + false, + ); + + static::assertSame([2], array_map(static fn(Rows $rows): int => $rows->count(), $batches)); + static::assertCount(2, $client->getRequests()); + } } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJSONEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonEncoder.php similarity index 75% rename from src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJSONEncoder.php rename to src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonEncoder.php index 2715815e7a..cecb9f7e6c 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJSONEncoder.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonEncoder.php @@ -14,25 +14,25 @@ use const JSON_UNESCAPED_SLASHES; use const JSON_UNESCAPED_UNICODE; -final readonly class AdaptiveJSONEncoder implements JSONEncoder +final readonly class AdaptiveJsonEncoder implements JsonEncoder { - private JSONEncoder $encoder; + private JsonEncoder $encoder; public function __construct( int $flags = JSON_THROW_ON_ERROR, string $dateTimeFormat = DateTimeInterface::ATOM, string $dateFormat = 'Y-m-d', ) { - $php = new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat); + $php = new PhpJsonEncoder($flags, $dateTimeFormat, $dateFormat); - // RustJSONEncoder renders only these flags; any other one writes through PHP + // RustJsonEncoder renders only these flags; any other one writes through PHP $this->encoder = extension_loaded('flow_php') && ( $flags & ~(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION) ) === 0 - ? new RustJSONEncoder($flags, $dateTimeFormat, $dateFormat, $php) + ? new RustJsonEncoder($flags, $dateTimeFormat, $dateFormat, $php) : $php; } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php index f13daae609..f0aa5c44da 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php @@ -7,7 +7,7 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFileReader; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Column\Backend; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Iterator; 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 96e8ede9f0..913e63e3c1 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 @@ -4,17 +4,18 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; -use Flow\ETL\Adapter\JSON\AdaptiveJsonOpenSource; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Extractor\FileReading; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\FileReading; +use Flow\ETL\Extractor\File\FileReadLoop; +use Flow\ETL\Extractor\File\ListedFiles; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\ReadWindow; use Flow\ETL\Extractor\InfersSchema; -use Flow\ETL\Extractor\ListedFiles; -use Flow\ETL\Extractor\MetadataColumnsExtractor; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; @@ -68,14 +69,16 @@ final class JsonExtractor implements public function __construct( private readonly Path $path, Filesystem $filesystem = new NativeLocalFilesystem(), + private readonly JsonFormat $format = JsonFormat::Document, ) { if (!$filesystem->supports($path)) { throw new InvalidArgumentException(sprintf( 'Filesystem %s serves "%s://" paths, given: "%s". Pass the filesystem that handles ' - . 'this scheme, e.g. from_json($path, filesystem: aws_s3_filesystem(...)).', + . 'this scheme, e.g. %s($path, filesystem: aws_s3_filesystem(...)).', $filesystem::class, $filesystem->mount()->protocol, $path->uri(), + $format === JsonFormat::Lines ? 'from_json_lines' : 'from_json', )); } @@ -93,73 +96,28 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $backend = $context->backend(); - $batchSize = $this->batchSize(); - $yielded = 0; $fileColumns = $this->fileColumns($this->filesystem, $this->path); + $schema = $this->schema(); $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); - $reader = new JsonFileReader( - $this->filesystem, - JsonFormat::Document, - $this->pointer, - $this->pointerToEntryName, - $sources, - ); - - if ($this->schema !== null) { - $base = $this->schema; - } else { - // a local, not the property: withoutTail() takes a non-nullable Schema and no analyzer narrows a property - $derived = $this->derivedSchema; - - if ($derived === null) { - $samples = new JsonSamples($reader->samples($this->inference->sampleSize)); - $derived = - $this->derivedSchema = (new SchemaInferrer($this->inference, new InstanceOfTypeNarrower()))->infer( - [], - $samples, - ); - $this->sampled = $samples->sampledFiles(); - } - - $base = $fileColumns->withoutTail($derived); - } - $schema = $fileColumns->declare($base); - $body = $fileColumns->withoutTail($schema); - - foreach ($sources as $source) { - // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body - $constants = $fileColumns->forFile($source, $schema); - - $open = new AdaptiveJsonOpenSource( + yield from (new FileReadLoop($fileColumns, $schema))->read( + $sources, + new JsonFileBatches( $this->filesystem, - $reader, - JsonFormat::Document, + new JsonFileReader( + $this->filesystem, + $this->format, + $this->pointer, + $this->pointerToEntryName, + $sources, + ), + $this->format, $this->pointer, - $source, - ); - - try { - foreach ($open->batches($body, $batchSize, $backend) as $batch) { - $rows = $constants->fillRows($batch, $schema, $backend); - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - } finally { - $open->close(); - } - } + ), + $this->batchSize(), + $context->backend(), + new ReadWindow(limit: $limit), + ); } public function inferSchema(SchemaInferenceBuilder $builder): static @@ -186,7 +144,7 @@ public function schema(): Schema if ($derived === null) { $reader = new JsonFileReader( $this->filesystem, - JsonFormat::Document, + $this->format, $this->pointer, $this->pointerToEntryName, iterator_to_array($this->sourceFiles($this->filesystem, $this->path), false), @@ -215,8 +173,9 @@ public function source(): Path } /** - * A document has no bytes-per-row unit, so rows are known only when the sample schema inference already read - * every element of every file. + * Rows come from what the sample schema inference already read; without one they are unknown, a sample is never + * read just for them. A document has no bytes-per-row unit, so its rows are known only when that sample read every + * element of every file; JSON lines estimate them from the sampled bytes per row. */ public function statistics(): Statistics { @@ -231,7 +190,12 @@ public function statistics(): Statistics return new Statistics(rows: Cardinality::unknown(), size: $size); } - return $this->statistics = new Statistics(rows: $this->sampled->exactRows($this->listed->count), size: $size); + return $this->statistics = new Statistics( + rows: $this->format === JsonFormat::Document + ? $this->sampled->exactRows($this->listed->count) + : $this->sampled->estimatedRows($this->listed->count, $size), + size: $size, + ); } /** diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileBatches.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileBatches.php new file mode 100644 index 0000000000..a5034731c5 --- /dev/null +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileBatches.php @@ -0,0 +1,48 @@ + $batchSize + * + * @return Generator + */ + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $open = new AdaptiveJsonOpenSource($this->filesystem, $this->reader, $this->format, $this->pointer, $source); + + try { + yield from $open->batches($body, $batchSize, $backend); + } finally { + $open->close(); + } + + return 0; + } +} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php index 215ab53f9b..26e5b0fc3d 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileReader.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema\Inference\SchemaSampler; use Flow\Filesystem\Filesystem; use Flow\Filesystem\SourceStream; diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileSample.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileSample.php index 76e628a2c2..268c70f423 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileSample.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonFileSample.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\JSON\JSONMachine; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Generator; use IteratorAggregate; 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 deleted file mode 100644 index c55765712f..0000000000 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONMachine/JsonLinesExtractor.php +++ /dev/null @@ -1,255 +0,0 @@ -supports($path)) { - throw new InvalidArgumentException(sprintf( - 'Filesystem %s serves "%s://" paths, given: "%s". Pass the filesystem that handles ' - . 'this scheme, e.g. from_json_lines($path, filesystem: aws_s3_filesystem(...)).', - $filesystem::class, - $filesystem->mount()->protocol, - $path->uri(), - )); - } - - $this->filesystem = $filesystem; - $this->inference = new SchemaInference(); - } - - public function isRepeatable(): bool - { - return true; - } - - /** - * @return Generator - */ - public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator - { - $backend = $context->backend(); - $batchSize = $this->batchSize(); - $yielded = 0; - $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); - $reader = new JsonFileReader( - $this->filesystem, - JsonFormat::Lines, - $this->pointer, - $this->pointerToEntryName, - $sources, - ); - - if ($this->schema !== null) { - $base = $this->schema; - } else { - // a local, not the property: withoutTail() takes a non-nullable Schema and no analyzer narrows a property - $derived = $this->derivedSchema; - - if ($derived === null) { - $samples = new JsonSamples($reader->samples($this->inference->sampleSize)); - $derived = - $this->derivedSchema = (new SchemaInferrer($this->inference, new InstanceOfTypeNarrower()))->infer( - [], - $samples, - ); - $this->sampled = $samples->sampledFiles(); - } - - $base = $fileColumns->withoutTail($derived); - } - - $schema = $fileColumns->declare($base); - $body = $fileColumns->withoutTail($schema); - - foreach ($sources as $source) { - // forFile() reads the PARTITION definitions, which only declare() creates - $base is the body - $constants = $fileColumns->forFile($source, $schema); - - $open = new AdaptiveJsonOpenSource($this->filesystem, $reader, JsonFormat::Lines, $this->pointer, $source); - - try { - foreach ($open->batches($body, $batchSize, $backend) as $batch) { - $rows = $constants->fillRows($batch, $schema, $backend); - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - } finally { - $open->close(); - } - } - } - - public function inferSchema(SchemaInferenceBuilder $builder): static - { - $this->inference = $builder->build(); - $this->derivedSchema = null; - $this->sampled = null; - $this->statistics = null; - - return $this; - } - - public function schema(): Schema - { - $fileColumns = $this->fileColumns($this->filesystem, $this->path); - - if ($this->schema !== null) { - return $fileColumns->declare($this->schema); - } - - // a local, not the property: withoutTail() takes a non-nullable Schema and no analyzer narrows a property - $derived = $this->derivedSchema; - - if ($derived === null) { - $reader = new JsonFileReader( - $this->filesystem, - JsonFormat::Lines, - $this->pointer, - $this->pointerToEntryName, - iterator_to_array($this->sourceFiles($this->filesystem, $this->path), false), - ); - - $samples = new JsonSamples($reader->samples($this->inference->sampleSize)); - $derived = - $this->derivedSchema = (new SchemaInferrer($this->inference, new InstanceOfTypeNarrower()))->infer( - [], - $samples, - ); - $this->sampled = $samples->sampledFiles(); - } - - 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; - } - - /** - * Rows come from the sample schema inference already read; without one they are unknown, a sample is never read - * just for them. - */ - public function statistics(): Statistics - { - if ($this->statistics !== null) { - return $this->statistics; - } - - $this->listed ??= ListedFiles::of($this->sourceFiles($this->filesystem, $this->path)); - $size = $this->listed->bytes; - - if ($this->sampled === null) { - return new Statistics(rows: Cardinality::unknown(), size: $size); - } - - return $this->statistics = new Statistics( - rows: $this->sampled->estimatedRows($this->listed->count, $size), - size: $size, - ); - } - - /** - * @param string $pointer - * @param bool $pointerToEntryName - when true pointer will be used as entry name for extracted data - */ - public function withPointer(string $pointer, bool $pointerToEntryName = false): self - { - $this->derivedSchema = null; - $this->sampled = null; - $this->statistics = null; - $this->pointer = $pointer; - $this->pointerToEntryName = $pointerToEntryName; - - return $this; - } - - public function withSchema(Schema $schema): static - { - $this->schema = $schema; - - return $this; - } -} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonEncoder.php similarity index 91% rename from src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php rename to src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonEncoder.php index 036088b463..d04d59f80c 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JSONEncoder.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonEncoder.php @@ -12,7 +12,7 @@ return; } -interface JSONEncoder +interface JsonEncoder { public function encode(Rows $rows, string $separator): string; } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonFraming.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonFraming.php index d5010460eb..a5df2cb0d3 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonFraming.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonFraming.php @@ -6,43 +6,43 @@ enum JsonFraming { - case ARRAY; - case ARRAY_LINES; - case LINES; + case Array; + case ArrayLines; + case Lines; public function closing(): string { return match ($this) { - self::LINES => "\n", - self::ARRAY => ']', - self::ARRAY_LINES => "\n]", + self::Lines => "\n", + self::Array => ']', + self::ArrayLines => "\n]", }; } public function empty(): string { return match ($this) { - self::LINES => '', - self::ARRAY => '[]', - self::ARRAY_LINES => "[\n\n]", + self::Lines => '', + self::Array => '[]', + self::ArrayLines => "[\n\n]", }; } public function opening(): string { return match ($this) { - self::LINES => '', - self::ARRAY => '[', - self::ARRAY_LINES => "[\n", + self::Lines => '', + self::Array => '[', + self::ArrayLines => "[\n", }; } public function separator(): string { return match ($this) { - self::LINES => "\n", - self::ARRAY => ',', - self::ARRAY_LINES => ",\n", + self::Lines => "\n", + self::Array => ',', + self::ArrayLines => ",\n", }; } } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php deleted file mode 100644 index 48ab19bab0..0000000000 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLinesLoader.php +++ /dev/null @@ -1,153 +0,0 @@ - by stream URI - */ - private array $sinks = []; - - public function __construct(Path $path, Filesystem $filesystem = new NativeLocalFilesystem()) - { - if (!$filesystem->supports($path)) { - throw new InvalidArgumentException(sprintf( - 'Filesystem %s serves "%s://" paths, given: "%s". Pass the filesystem that handles ' - . 'this scheme, e.g. to_json_lines($path, filesystem: aws_s3_filesystem(...)).', - $filesystem::class, - $filesystem->mount()->protocol, - $path->uri(), - )); - } - - $this->filesystem = $filesystem; - $this->router = new PartitionRouter(Partitioning::none()); - $this->path = $path->setOptionWhenEmpty(Option::CONTENT_TYPE->value, ContentType::JSON); - } - - public function partitionBy(Partitioning $partitioning): static - { - $this->router = new PartitionRouter($partitioning); - - return $this; - } - - public function closure(FlowContext $context): void - { - foreach ($this->sinks as $sink) { - $sink->close(); - } - - $this->files?->publish(); - $this->files = null; - $this->sinks = []; - } - - public function discard(FlowContext $context): void - { - $this->files?->abandon(); - $this->files = null; - $this->sinks = []; - } - - public function destination(): Path - { - return $this->path; - } - - public function load(Rows $rows, FlowContext $context): void - { - $context->telemetry()->loadingStarted($this, [ - TelemetryAttributes::ATTR_LOADER_DESTINATION_URI => $this->path->uri(), - ]); - - try { - foreach ($this->router->route($rows) as [$partitions, $group]) { - $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( - $partitions->toArray(), - ); - ($this->sinks[$stream->path()->uri()] ??= new JsonOpenSink( - $stream, - new AdaptiveJSONEncoder($this->flags, $this->dateTimeFormat, $this->dateFormat), - JsonFraming::LINES, - ))->write($group); - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } - } - - public function saveMode(SaveMode $mode): static - { - $this->saveMode = $mode; - - return $this; - } - - public function withDateFormat(string $dateFormat): self - { - $this->dateFormat = $dateFormat; - - return $this; - } - - public function withDateTimeFormat(string $dateTimeFormat): self - { - $this->dateTimeFormat = $dateTimeFormat; - - return $this; - } - - public function withFlags(int $flags): self - { - $this->flags = $flags &= ~JSON_PRETTY_PRINT; - - return $this; - } -} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php index f5af11300f..5e2bada428 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonLoader.php @@ -5,38 +5,40 @@ namespace Flow\ETL\Adapter\JSON; use DateTimeInterface; -use Flow\ETL\Config\Telemetry\TelemetryAttributes; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; use Flow\ETL\Loader\Discardable; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; +use Flow\ETL\Loader\File\FileSink; +use Flow\ETL\Loader\File\FileSinks; +use Flow\ETL\Loader\File\FileWriteFrame; +use Flow\ETL\Loader\File\PartitionRouter; use Flow\ETL\Loader\Partitioning; use Flow\ETL\Loader\PartitioningLoader; -use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; +use Flow\Filesystem\DestinationStream; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; use Flow\Filesystem\Path\Option; use Flow\Filesystem\Path\Option\ContentType; -use Throwable; use function sprintf; -final class JsonLoader implements Closure, Discardable, FileLoader, Loader, PartitioningLoader +final class JsonLoader implements Closure, Discardable, FileLoader, FileSinks, Loader, PartitioningLoader { + private ?FileWriteFrame $frame = null; + private PartitionRouter $router; private readonly Filesystem $filesystem; private SaveMode $saveMode = SaveMode::ExceptionIfExists; - private ?FilesSink $files = null; - private string $dateFormat = 'Y-m-d'; private string $dateTimeFormat = DateTimeInterface::ATOM; @@ -45,22 +47,19 @@ final class JsonLoader implements Closure, Discardable, FileLoader, Loader, Part private readonly Path $path; - private bool $putRowsInNewLines = false; - - /** - * @var array by stream URI - */ - private array $sinks = []; - - public function __construct(Path $path, Filesystem $filesystem = new NativeLocalFilesystem()) - { + public function __construct( + Path $path, + Filesystem $filesystem = new NativeLocalFilesystem(), + private JsonFraming $framing = JsonFraming::Array, + ) { if (!$filesystem->supports($path)) { throw new InvalidArgumentException(sprintf( 'Filesystem %s serves "%s://" paths, given: "%s". Pass the filesystem that handles ' - . 'this scheme, e.g. to_json($path, filesystem: aws_s3_filesystem(...)).', + . 'this scheme, e.g. %s($path, filesystem: aws_s3_filesystem(...)).', $filesystem::class, $filesystem->mount()->protocol, $path->uri(), + $framing === JsonFraming::Lines ? 'to_json_lines' : 'to_json', )); } @@ -78,20 +77,14 @@ public function partitionBy(Partitioning $partitioning): static public function closure(FlowContext $context): void { - foreach ($this->sinks as $sink) { - $sink->close(); - } - - $this->files?->publish(); - $this->files = null; - $this->sinks = []; + $this->frame?->closure(); + $this->frame = null; } public function discard(FlowContext $context): void { - $this->files?->abandon(); - $this->files = null; - $this->sinks = []; + $this->frame?->discard(); + $this->frame = null; } public function destination(): Path @@ -101,30 +94,22 @@ public function destination(): Path public function load(Rows $rows, FlowContext $context): void { - $context->telemetry()->loadingStarted($this, [ - TelemetryAttributes::ATTR_LOADER_DESTINATION_URI => $this->path->uri(), - ]); - - try { - foreach ($this->router->route($rows) as [$partitions, $group]) { - $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( - $partitions->toArray(), - ); - ($this->sinks[$stream->path()->uri()] ??= new JsonOpenSink( - $stream, - new AdaptiveJSONEncoder($this->flags, $this->dateTimeFormat, $this->dateFormat), - $this->putRowsInNewLines ? JsonFraming::ARRAY_LINES : JsonFraming::ARRAY, - ))->write($group); - } - - $context->telemetry()->loadingCompleted($this, [ - TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count(), - ]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } + ($this->frame ??= new FileWriteFrame( + $this->filesystem, + $this->path, + $this->saveMode, + $this->router, + $this, + ))->write($rows, $context, $this); + } + + public function open(DestinationStream $stream, Backend $backend): FileSink + { + return new JsonOpenSink( + $stream, + new AdaptiveJsonEncoder($this->flags, $this->dateTimeFormat, $this->dateFormat), + $this->framing, + ); } public function saveMode(SaveMode $mode): static @@ -150,14 +135,21 @@ public function withDateTimeFormat(string $dateTimeFormat): self public function withFlags(int $flags): self { - $this->flags = $flags; + $this->flags = $this->framing === JsonFraming::Lines ? $flags & ~JSON_PRETTY_PRINT : $flags; return $this; } + /** + * @throws InvalidArgumentException + */ public function withRowsInNewLines(bool $putRowsInNewLines): self { - $this->putRowsInNewLines = $putRowsInNewLines; + if ($this->framing === JsonFraming::Lines) { + throw new InvalidArgumentException('withRowsInNewLines() applies to to_json(), not to_json_lines()'); + } + + $this->framing = $putRowsInNewLines ? JsonFraming::ArrayLines : JsonFraming::Array; return $this; } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSink.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSink.php index 8c97bab613..bae8ac3f2c 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSink.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSink.php @@ -4,10 +4,11 @@ namespace Flow\ETL\Adapter\JSON; +use Flow\ETL\Loader\File\FileSink; use Flow\ETL\Rows; use Flow\Filesystem\DestinationStream; -final class JsonOpenSink +final class JsonOpenSink implements FileSink { private bool $touched = false; @@ -15,7 +16,7 @@ final class JsonOpenSink public function __construct( private readonly DestinationStream $stream, - private readonly JSONEncoder $encoder, + private readonly JsonEncoder $encoder, private readonly JsonFraming $framing, ) {} diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJSONEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonEncoder.php similarity index 96% rename from src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJSONEncoder.php rename to src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonEncoder.php index 5b2c6070ba..9769f277ed 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJSONEncoder.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonEncoder.php @@ -23,7 +23,7 @@ use const JSON_THROW_ON_ERROR; -final class PhpJSONEncoder implements JSONEncoder +final class PhpJsonEncoder implements JsonEncoder { private readonly TextValues $text; @@ -74,7 +74,7 @@ public function encode(Rows $rows, string $separator): string return implode($separator, $documents); } - // called by name from flow_php RustJSONEncoder::encode(), pinned by phpt 082 + // called by name from flow_php RustJsonEncoder::encode(), pinned by phpt 082 /** * @param Type $type * diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php index 75ce0b0e30..d7b5a9b324 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/PhpJsonOpenSource.php @@ -6,7 +6,7 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFileReader; use Flow\ETL\Column\Backend; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Rows; use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/functions.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/functions.php index 234d598ae5..78bc31569a 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/functions.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/functions.php @@ -10,7 +10,7 @@ use Flow\Documentation\Attribute\Module; use Flow\Documentation\Attribute\Type; use Flow\ETL\Adapter\JSON\JSONMachine\JsonExtractor; -use Flow\ETL\Adapter\JSON\JSONMachine\JsonLinesExtractor; +use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\JsonSchema\ReferenceResolver; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; @@ -55,9 +55,9 @@ function from_json( */ #[DocumentationDSL(module: Module::JSON, type: Type::EXTRACTOR)] #[DocumentationExample(topic: 'reading', example: 'jsonl')] -function from_json_lines(string|Path $path, Filesystem $filesystem = new NativeLocalFilesystem()): JsonLinesExtractor +function from_json_lines(string|Path $path, Filesystem $filesystem = new NativeLocalFilesystem()): JsonExtractor { - return new JsonLinesExtractor(is_string($path) ? path_real($path) : $path, $filesystem); + return new JsonExtractor(is_string($path) ? path_real($path) : $path, $filesystem, JsonFormat::Lines); } /** @@ -87,12 +87,12 @@ function to_json( * * @param Path|string $path * - * @return JsonLinesLoader + * @return JsonLoader */ #[DocumentationDSL(module: Module::JSON, type: Type::LOADER)] -function to_json_lines(string|Path $path, Filesystem $filesystem = new NativeLocalFilesystem()): JsonLinesLoader +function to_json_lines(string|Path $path, Filesystem $filesystem = new NativeLocalFilesystem()): JsonLoader { - return new JsonLinesLoader(is_string($path) ? path_real($path) : $path, $filesystem); + return new JsonLoader(is_string($path) ? path_real($path) : $path, $filesystem, JsonFraming::Lines); } /** diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php index c3f22862aa..dc16456826 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Context/JsonFixtureContext.php @@ -5,15 +5,15 @@ namespace Flow\ETL\Adapter\JSON\Tests\Context; use Flow\ETL\Adapter\JSON\AdaptiveJsonOpenSource; +use Flow\ETL\Adapter\JSON\JSONMachine\JsonExtractor; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFileReader; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; -use Flow\ETL\Adapter\JSON\JSONMachine\JsonLinesExtractor; use Flow\ETL\Adapter\JSON\JSONMachine\JsonSamples; use Flow\ETL\Adapter\JSON\JsonOpenSource; use Flow\ETL\Column\Backend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Schema\Inference\SchemaInferrer; @@ -94,7 +94,7 @@ public static function format(string $fixture): JsonFormat } /** - * The schema JsonExtractor / JsonLinesExtractor infer from the fixture. + * The schema JsonExtractor infer from the fixture. */ public static function infer(string $fixture, SchemaInference $inference = new SchemaInference()): Schema { @@ -109,7 +109,7 @@ public static function infer(string $fixture, SchemaInference $inference = new S /** * @param 'memory'|'native' $filesystem */ - public static function linesExtractor(string $fixture, string $filesystem): JsonLinesExtractor + public static function linesExtractor(string $fixture, string $filesystem): JsonExtractor { if ($filesystem === 'native') { return from_json_lines(self::path($fixture)); @@ -124,7 +124,7 @@ public static function linesExtractor(string $fixture, string $filesystem): Json } /** - * The source JsonExtractor (Document) or JsonLinesExtractor (Lines) opens, over a reader of the same filesystem. + * The source JsonExtractor (Document or Lines) opens, over a reader of the same filesystem. */ public static function open( JsonFormat $format, diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php index 5a60aea9f6..71c99b8728 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php @@ -7,7 +7,7 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; use Flow\ETL\Column\PhpBackend; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\RustIterator; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorBatchContractTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorBatchContractTest.php index 3b12164ad0..c0887cedaa 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorBatchContractTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonExtractorBatchContractTest.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Adapter\JSON\Tests\Integration\JSONMachine; use Flow\ETL\Adapter\JSON\JSONMachine\JsonExtractor; -use Flow\ETL\Adapter\JSON\JSONMachine\JsonLinesExtractor; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\RowsMother; @@ -26,7 +25,7 @@ public function test_json_extractor_honours_the_batch_contract(): void public function test_json_lines_extractor_honours_the_batch_contract(): void { self::assertExtractorHonoursBatchContract( - static fn(): JsonLinesExtractor => from_json_lines(JsonFixtureContext::path('five_rows.jsonl')), + static fn(): JsonExtractor => from_json_lines(JsonFixtureContext::path('five_rows.jsonl')), RowsMother::sequentialIds(5), ); } 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 56310c060f..89297df69e 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 @@ -16,6 +16,7 @@ use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\RecordingFilesystem; use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -25,6 +26,7 @@ use function array_keys; use function array_sum; +use function count; use function Flow\ETL\Adapter\JSON\from_json; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\config_builder; @@ -703,4 +705,23 @@ public function test_extract_builds_through_the_config_backend(): void static::assertGreaterThanOrEqual(1, $backend->builders() + $backend->adopts()); } + + public function test_one_extractor_read_twice_interleaved_gives_each_read_every_row_and_closes_every_stream(): void + { + $filesystem = new RecordingFilesystem(MemoryFiles::with([ + 'memory://in/a.json' => '[{"id":1},{"id":2}]', + 'memory://in/b.json' => '[{"id":3}]', + ])); + [$first, $second] = ExtractedRows::interleaved(from_json( + path('memory://in/*.json'), + filesystem: $filesystem, + )->withBatchSize(1)); + + static::assertSame([['id' => 1], ['id' => 2], ['id' => 3]], $first->toArray()); + static::assertSame($first->toArray(), $second->toArray()); + static::assertSame( + count(array_keys($filesystem->calls, 'readFrom', true)), + count(array_keys($filesystem->calls, 'closeSource', true)), + ); + } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php index 9867b9f56c..1dc992e448 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileReaderTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileSampleTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileSampleTest.php index 624c03290e..a4f1fcd695 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileSampleTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JSONMachine/JsonFileSampleTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\JSONMachine\JsonSampledRows; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\FlowTestCase; 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 ae5a32f5b5..817c815bae 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 @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\JSON\Tests\Integration\JSONMachine; use Closure; -use Flow\ETL\Adapter\JSON\JSONMachine\JsonLinesExtractor; +use Flow\ETL\Adapter\JSON\JSONMachine\JsonExtractor; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; use Flow\ETL\Cardinality; use Flow\ETL\Config; @@ -288,7 +288,7 @@ public function test_a_declared_schema_opens_each_file_once(): void } /** - * @param Closure(JsonLinesExtractor): void $setter + * @param Closure(JsonExtractor): void $setter */ #[DataProvider('shapeChangingSetters')] public function test_a_shape_changing_setter_drops_the_inferred_schema(Closure $setter): void @@ -306,12 +306,12 @@ public function test_a_shape_changing_setter_drops_the_inferred_schema(Closure $ } /** - * @return Generator + * @return Generator */ public static function shapeChangingSetters(): Generator { - yield 'withPointer' => [static fn(JsonLinesExtractor $e) => $e->withPointer('/timezones', true)]; - yield 'inferSchema' => [static fn(JsonLinesExtractor $e) => $e->inferSchema(infer_schema()->allStrings())]; + yield 'withPointer' => [static fn(JsonExtractor $e) => $e->withPointer('/timezones', true)]; + yield 'inferSchema' => [static fn(JsonExtractor $e) => $e->inferSchema(infer_schema()->allStrings())]; } public function test_infer_schema_drops_the_inferred_schema_and_all_strings_floors_it(): void @@ -607,7 +607,7 @@ public function test_is_repeatable(): void } /** - * @param Closure(JsonLinesExtractor): void $setter + * @param Closure(JsonExtractor): void $setter */ #[DataProvider('shapeChangingSetters')] public function test_a_shape_changing_setter_drops_the_sample(Closure $setter): void diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonLinesTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonLinesTest.php index 6707cd693b..6a583e1fde 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonLinesTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/JsonLinesTest.php @@ -4,7 +4,8 @@ namespace Flow\ETL\Adapter\JSON\Tests\Integration; -use Flow\ETL\Adapter\JSON\JsonLinesLoader; +use Flow\ETL\Adapter\JSON\JsonFraming; +use Flow\ETL\Adapter\JSON\JsonLoader; use Flow\ETL\Tests\Double\FakeExtractor; use Flow\ETL\Tests\FlowTestCase; @@ -79,7 +80,10 @@ public function test_jsonl_loader(): void public function test_jsonl_loader_loading_empty_string(): void { - $loader = new JsonLinesLoader(path($path = __DIR__ . '/var/test_json_loader_loading_empty_string.jsonl')); + $loader = new JsonLoader( + path($path = __DIR__ . '/var/test_json_loader_loading_empty_string.jsonl'), + framing: JsonFraming::Lines, + ); $loader->load(rows(schema()), $context = flow_context(config())); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonRefusalTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonRefusalTest.php index 1047f12a54..ccd8de72a0 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonRefusalTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/RustJsonRefusalTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\RustIterator; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\FlowTestCase; diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JSONEncoderMother.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JsonEncoderMother.php similarity index 64% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JSONEncoderMother.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JsonEncoderMother.php index 680cfbf5be..7a3e6a43f3 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JSONEncoderMother.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Mother/JsonEncoderMother.php @@ -5,23 +5,23 @@ namespace Flow\ETL\Adapter\JSON\Tests\Mother; use DateTimeInterface; -use Flow\ETL\Adapter\JSON\PhpJSONEncoder; -use Flow\ETL\Adapter\JSON\RustJSONEncoder; +use Flow\ETL\Adapter\JSON\PhpJsonEncoder; +use Flow\ETL\Adapter\JSON\RustJsonEncoder; use const JSON_THROW_ON_ERROR; -final class JSONEncoderMother +final class JsonEncoderMother { public static function native( int $flags = JSON_THROW_ON_ERROR, string $dateTimeFormat = DateTimeInterface::ATOM, string $dateFormat = 'Y-m-d', - ): RustJSONEncoder { - return new RustJSONEncoder( + ): RustJsonEncoder { + return new RustJsonEncoder( $flags, $dateTimeFormat, $dateFormat, - new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat), + new PhpJsonEncoder($flags, $dateTimeFormat, $dateFormat), ); } @@ -29,7 +29,7 @@ public static function php( int $flags = JSON_THROW_ON_ERROR, string $dateTimeFormat = DateTimeInterface::ATOM, string $dateFormat = 'Y-m-d', - ): PhpJSONEncoder { - return new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat); + ): PhpJsonEncoder { + return new PhpJsonEncoder($flags, $dateTimeFormat, $dateFormat); } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJSONEncoderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJsonEncoderTest.php similarity index 84% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJSONEncoderTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJsonEncoderTest.php index e516fcc183..42766441a0 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJSONEncoderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJsonEncoderTest.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\JSON\Tests\Unit; use DateTimeImmutable; -use Flow\ETL\Adapter\JSON\AdaptiveJSONEncoder; +use Flow\ETL\Adapter\JSON\AdaptiveJsonEncoder; use Flow\ETL\Adapter\JSON\JsonFraming; use Flow\ETL\Adapter\JSON\JsonOpenSink; use Flow\ETL\Tests\FlowTestCase; @@ -22,15 +22,15 @@ use const JSON_THROW_ON_ERROR; use const JSON_UNESCAPED_SLASHES; -final class AdaptiveJSONEncoderTest extends FlowTestCase +final class AdaptiveJsonEncoderTest extends FlowTestCase { public function test_a_sink_writes_with_the_options_of_its_encoder(): void { $stream = new StringDestinationStream(path('memory://out.json')); $sink = new JsonOpenSink( $stream, - new AdaptiveJSONEncoder(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES, 'd/m/Y H:i', 'Y/m/d'), - JsonFraming::ARRAY, + new AdaptiveJsonEncoder(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES, 'd/m/Y H:i', 'Y/m/d'), + JsonFraming::Array, ); $sink->write(array_to_rows( @@ -47,8 +47,8 @@ public function test_a_flag_the_native_writer_does_not_render_is_written_through $stream = new StringDestinationStream(path('memory://out.json')); $sink = new JsonOpenSink( $stream, - new AdaptiveJSONEncoder(JSON_PRETTY_PRINT, 'Y-m-d', 'Y-m-d'), - JsonFraming::LINES, + new AdaptiveJsonEncoder(JSON_PRETTY_PRINT, 'Y-m-d', 'Y-m-d'), + JsonFraming::Lines, ); $sink->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFileBatchesTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFileBatchesTest.php new file mode 100644 index 0000000000..c0aa355e17 --- /dev/null +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFileBatchesTest.php @@ -0,0 +1,65 @@ + '[{"id":1},{"id":2},{"id":3}]'])); + $source = new SourceFile(path('memory://a.json')); + $file = (new JsonFileBatches( + $filesystem, + new JsonFileReader($filesystem, JsonFormat::Document, null, false, [$source]), + JsonFormat::Document, + null, + ))->batches($source, schema(int_schema('id')), 2, new PhpBackend(), new ReadWindow()); + + static::assertSame( + [['id' => 1], ['id' => 2], ['id' => 3]], + array_merge(...array_map( + static fn(Rows $rows): array => $rows->toArray(), + iterator_to_array($file, false), + )), + ); + static::assertSame(0, $file->getReturn()); + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + + public function test_lines_yield_one_row_per_line(): void + { + $filesystem = MemoryFiles::with(['memory://a.jsonl' => "{\"id\":1}\n{\"id\":2}\n"]); + $source = new SourceFile(path('memory://a.jsonl')); + $file = (new JsonFileBatches( + $filesystem, + new JsonFileReader($filesystem, JsonFormat::Lines, null, false, [$source]), + JsonFormat::Lines, + null, + ))->batches($source, schema(int_schema('id')), 10, new PhpBackend(), new ReadWindow()); + + static::assertSame( + [[['id' => 1], ['id' => 2]]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + } +} diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFramingTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFramingTest.php index 3df0a9e1f4..a2d196b2f8 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFramingTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonFramingTest.php @@ -10,9 +10,9 @@ final class JsonFramingTest extends TestCase { - #[TestWith([JsonFraming::LINES, '', "\n", "\n", ''])] - #[TestWith([JsonFraming::ARRAY, '[', ',', ']', '[]'])] - #[TestWith([JsonFraming::ARRAY_LINES, "[\n", ",\n", "\n]", "[\n\n]"])] + #[TestWith([JsonFraming::Lines, '', "\n", "\n", ''])] + #[TestWith([JsonFraming::Array, '[', ',', ']', '[]'])] + #[TestWith([JsonFraming::ArrayLines, "[\n", ",\n", "\n]", "[\n\n]"])] public function test_framing( JsonFraming $framing, string $opening, diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonLinesLoaderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonLinesLoaderTest.php index 0dbfe6447a..bc342826d6 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonLinesLoaderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonLinesLoaderTest.php @@ -5,7 +5,9 @@ namespace Flow\ETL\Adapter\JSON\Tests\Unit; use DateTimeImmutable; -use Flow\ETL\Adapter\JSON\JsonLinesLoader; +use Flow\ETL\Adapter\JSON\JsonFraming; +use Flow\ETL\Adapter\JSON\JsonLoader; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\Double\RecordingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Path\Option; @@ -32,7 +34,7 @@ final class JsonLinesLoaderTest extends FlowTestCase { public function test_setting_content_type_on_path(): void { - $loader = new JsonLinesLoader(path(__DIR__ . '/file.jsonl')); + $loader = new JsonLoader(path(__DIR__ . '/file.jsonl'), framing: JsonFraming::Lines); static::assertEquals($loader->destination()->getOption(Option::CONTENT_TYPE), ContentType::JSON); } @@ -75,6 +77,14 @@ public function test_pretty_print_is_ignored_and_the_other_options_apply(): void ); } + public function test_rows_in_new_lines_is_refused_for_json_lines(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('withRowsInNewLines() applies to to_json(), not to_json_lines()'); + + to_json_lines(path('memory://out.jsonl'), filesystem: memory_filesystem())->withRowsInNewLines(true); + } + public function test_every_partition_file_ends_with_a_new_line(): void { $filesystem = memory_filesystem(); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonLoaderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonLoaderTest.php index f2dfd3817b..c5a1f68f0d 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonLoaderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonLoaderTest.php @@ -12,6 +12,7 @@ use Flow\Filesystem\Path\Option\ContentType; use function array_keys; +use function array_map; use function count; use function Flow\ETL\Adapter\JSON\to_json; use function Flow\ETL\DSL\array_to_rows; @@ -122,4 +123,25 @@ public function test_a_discarded_loader_starts_over(): void static::assertSame('[{"id":2}]', $filesystem->readFrom(path('memory://out.json'))->content()); } + + public function test_two_runs_through_one_loader_write_independent_files(): void + { + $filesystem = memory_filesystem(); + $loader = to_json(path('memory://out.json'), filesystem: $filesystem)->partitionBy(partition_by('group')); + $read = []; + + foreach (['a' => [1, 2], 'b' => [3]] as $group => $ids) { + $loader->load( + array_to_rows( + array_map(static fn(int $id): array => ['id' => $id, 'group' => $group], $ids), + schema(int_schema('id'), str_schema('group')), + ), + flow_context(), + ); + $loader->closure(flow_context()); + $read[] = $filesystem->readFrom(path('memory://group=' . $group . '/out.json'))->content(); + } + + static::assertSame(['[{"id":1},{"id":2}]', '[{"id":3}]'], $read); + } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonOpenSinkTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonOpenSinkTest.php index 87b8235a35..e8b6ae8765 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonOpenSinkTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/JsonOpenSinkTest.php @@ -6,7 +6,7 @@ use Flow\ETL\Adapter\JSON\JsonFraming; use Flow\ETL\Adapter\JSON\JsonOpenSink; -use Flow\ETL\Adapter\JSON\Tests\Mother\JSONEncoderMother; +use Flow\ETL\Adapter\JSON\Tests\Mother\JsonEncoderMother; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Stream\StringDestinationStream; use PHPUnit\Framework\Attributes\TestWith; @@ -18,13 +18,13 @@ final class JsonOpenSinkTest extends FlowTestCase { - #[TestWith([JsonFraming::LINES, "{\"id\":1}\n{\"id\":2}\n{\"id\":3}\n{\"id\":4}\n"])] - #[TestWith([JsonFraming::ARRAY, '[{"id":1},{"id":2},{"id":3},{"id":4}]'])] - #[TestWith([JsonFraming::ARRAY_LINES, "[\n{\"id\":1},\n{\"id\":2},\n{\"id\":3},\n{\"id\":4}\n]"])] + #[TestWith([JsonFraming::Lines, "{\"id\":1}\n{\"id\":2}\n{\"id\":3}\n{\"id\":4}\n"])] + #[TestWith([JsonFraming::Array, '[{"id":1},{"id":2},{"id":3},{"id":4}]'])] + #[TestWith([JsonFraming::ArrayLines, "[\n{\"id\":1},\n{\"id\":2},\n{\"id\":3},\n{\"id\":4}\n]"])] public function test_three_batches_under_a_framing(JsonFraming $framing, string $expected): void { $stream = new StringDestinationStream(path('memory://out.json')); - $sink = new JsonOpenSink($stream, JSONEncoderMother::php(), $framing); + $sink = new JsonOpenSink($stream, JsonEncoderMother::php(), $framing); $sink->write(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $sink->write(array_to_rows([['id' => 3]], schema(int_schema('id')))); @@ -34,25 +34,25 @@ public function test_three_batches_under_a_framing(JsonFraming $framing, string static::assertSame($expected, $stream->content()); } - #[TestWith([JsonFraming::LINES])] - #[TestWith([JsonFraming::ARRAY])] - #[TestWith([JsonFraming::ARRAY_LINES])] + #[TestWith([JsonFraming::Lines])] + #[TestWith([JsonFraming::Array])] + #[TestWith([JsonFraming::ArrayLines])] public function test_close_without_a_write_appends_nothing(JsonFraming $framing): void { $stream = new StringDestinationStream(path('memory://out.json')); - (new JsonOpenSink($stream, JSONEncoderMother::php(), $framing))->close(); + (new JsonOpenSink($stream, JsonEncoderMother::php(), $framing))->close(); static::assertSame('', $stream->content()); } - #[TestWith([JsonFraming::LINES, ''])] - #[TestWith([JsonFraming::ARRAY, '[]'])] - #[TestWith([JsonFraming::ARRAY_LINES, "[\n\n]"])] + #[TestWith([JsonFraming::Lines, ''])] + #[TestWith([JsonFraming::Array, '[]'])] + #[TestWith([JsonFraming::ArrayLines, "[\n\n]"])] public function test_only_empty_batches_close_an_empty_document(JsonFraming $framing, string $expected): void { $stream = new StringDestinationStream(path('memory://out.json')); - $sink = new JsonOpenSink($stream, JSONEncoderMother::php(), $framing); + $sink = new JsonOpenSink($stream, JsonEncoderMother::php(), $framing); $sink->write(array_to_rows([], schema(int_schema('id')))); $sink->write(array_to_rows([], schema(int_schema('id')))); @@ -61,12 +61,12 @@ public function test_only_empty_batches_close_an_empty_document(JsonFraming $fra static::assertSame($expected, $stream->content()); } - #[TestWith([JsonFraming::LINES, "{\"id\":1}\n{\"id\":2}\n"])] - #[TestWith([JsonFraming::ARRAY, '[{"id":1},{"id":2}]'])] + #[TestWith([JsonFraming::Lines, "{\"id\":1}\n{\"id\":2}\n"])] + #[TestWith([JsonFraming::Array, '[{"id":1},{"id":2}]'])] public function test_an_empty_batch_between_batches_leaves_no_trace(JsonFraming $framing, string $expected): void { $stream = new StringDestinationStream(path('memory://out.json')); - $sink = new JsonOpenSink($stream, JSONEncoderMother::php(), $framing); + $sink = new JsonOpenSink($stream, JsonEncoderMother::php(), $framing); $sink->write(array_to_rows([], schema(int_schema('id')))); $sink->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/PhpJSONEncoderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/PhpJsonEncoderTest.php similarity index 94% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/PhpJSONEncoderTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/PhpJsonEncoderTest.php index 3849f13f13..92673a51e2 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/PhpJSONEncoderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/PhpJsonEncoderTest.php @@ -7,7 +7,7 @@ use DateInterval; use DateTimeImmutable; use DateTimeZone; -use Flow\ETL\Adapter\JSON\PhpJSONEncoder; +use Flow\ETL\Adapter\JSON\PhpJsonEncoder; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Schema\Definition; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; @@ -63,7 +63,7 @@ use const JSON_UNESCAPED_SLASHES; use const JSON_UNESCAPED_UNICODE; -final class PhpJSONEncoderTest extends FlowTestCase +final class PhpJsonEncoderTest extends FlowTestCase { /** * @return Generator, list, string}> @@ -196,7 +196,7 @@ public function test_encode_renders_a_column_by_its_type( array $values, string $expected, ): void { - static::assertSame($expected, (new PhpJSONEncoder())->encode( + static::assertSame($expected, (new PhpJsonEncoder())->encode( array_to_rows(array_map(static fn(mixed $value): array => ['a' => $value], $values), schema($definition)), '|', )); @@ -205,7 +205,7 @@ public function test_encode_renders_a_column_by_its_type( #[RequiresPhp('>= 8.4.0')] public function test_encode_renders_html_as_its_markup(): void { - static::assertSame('{"doc":"<\/head>

      a<\/p><\/body><\/html>","el":"

      a<\/p>"}', (new PhpJSONEncoder())->encode( + static::assertSame('{"doc":"<\/head>

      a<\/p><\/body><\/html>","el":"

      a<\/p>"}', (new PhpJsonEncoder())->encode( array_to_rows( [['doc' => '

      a

      ', 'el' => '

      a

      ']], schema(html_schema('doc'), html_element_schema('el')), @@ -218,7 +218,7 @@ public function test_encode_writes_one_object_per_row_in_schema_order(): void { static::assertSame('{"id":1,"name":"Alice","active":true,"score":9.5,"missing":null}' . "\n" - . '{"id":2,"name":"Bob","active":false,"score":1,"missing":"x"}', (new PhpJSONEncoder())->encode( + . '{"id":2,"name":"Bob","active":false,"score":1,"missing":"x"}', (new PhpJsonEncoder())->encode( array_to_rows( [ ['name' => 'Alice', 'id' => 1, 'active' => true, 'score' => 9.5, 'missing' => null], @@ -238,7 +238,7 @@ public function test_encode_writes_one_object_per_row_in_schema_order(): void public function test_a_row_of_columns_named_0_and_1_is_an_object(): void { - static::assertSame('{"0":"a","1":"b"}', (new PhpJSONEncoder())->encode( + static::assertSame('{"0":"a","1":"b"}', (new PhpJsonEncoder())->encode( array_to_rows([['0' => 'a', '1' => 'b']], schema(str_schema('0'), str_schema('1'))), ',', )); @@ -246,7 +246,7 @@ public function test_a_row_of_columns_named_0_and_1_is_an_object(): void public function test_encode_of_an_empty_batch_is_empty(): void { - static::assertSame('', (new PhpJSONEncoder())->encode(array_to_rows([], schema(int_schema('a'))), ',')); + static::assertSame('', (new PhpJsonEncoder())->encode(array_to_rows([], schema(int_schema('a'))), ',')); } #[TestWith([JSON_THROW_ON_ERROR, '{"a":"a\/\u017c","f":1}'])] @@ -256,7 +256,7 @@ public function test_encode_of_an_empty_batch_is_empty(): void #[TestWith([JSON_PRETTY_PRINT, "{\n \"a\": \"a\\/\\u017c\",\n \"f\": 1\n}"])] public function test_encode_applies_the_flags(int $flags, string $expected): void { - static::assertSame($expected, (new PhpJSONEncoder($flags))->encode( + static::assertSame($expected, (new PhpJsonEncoder($flags))->encode( array_to_rows([['a' => 'a/ż', 'f' => 1.0]], schema(str_schema('a'), float_schema('f'))), ',', )); @@ -264,7 +264,7 @@ public function test_encode_applies_the_flags(int $flags, string $expected): voi public function test_encode_uses_the_configured_formats_at_every_depth(): void { - static::assertSame('{"at":"01\/10\/2023 12:02","on":"2023\/10\/01","l":["01\/10\/2023 12:02"]}', (new PhpJSONEncoder( + static::assertSame('{"at":"01\/10\/2023 12:02","on":"2023\/10\/01","l":["01\/10\/2023 12:02"]}', (new PhpJsonEncoder( JSON_THROW_ON_ERROR, 'd/m/Y H:i', 'Y/m/d', @@ -287,7 +287,7 @@ public function test_float_text_does_not_depend_on_serialize_precision(): void ini_set('serialize_precision', '17'); try { - $encoder = new PhpJSONEncoder(); + $encoder = new PhpJsonEncoder(); $rows = array_to_rows( [['f' => 0.1, 'l' => [1.0e25]]], schema(float_schema('f'), list_schema('l', type_list(type_float()))), @@ -308,7 +308,7 @@ public function test_a_not_finite_float_is_refused(int $flags): void $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Failed to encode JSON: Inf and NaN cannot be JSON encoded'); - (new PhpJSONEncoder($flags))->encode(array_to_rows([['f' => NAN]], schema(float_schema('f'))), ','); + (new PhpJsonEncoder($flags))->encode(array_to_rows([['f' => NAN]], schema(float_schema('f'))), ','); } public function test_malformed_utf8_is_refused(): void @@ -318,7 +318,7 @@ public function test_malformed_utf8_is_refused(): void 'Failed to encode JSON: Malformed UTF-8 characters, possibly incorrectly encoded', ); - (new PhpJSONEncoder())->encode(array_to_rows([['s' => "\xff"]], schema(str_schema('s'))), ','); + (new PhpJsonEncoder())->encode(array_to_rows([['s' => "\xff"]], schema(str_schema('s'))), ','); } public function test_fragments_are_the_json_text_of_every_cell(): void @@ -331,7 +331,7 @@ public function test_fragments_are_the_json_text_of_every_cell(): void str_schema('s', nullable: true), ), ); - $encoder = new PhpJSONEncoder(JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES); + $encoder = new PhpJsonEncoder(JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES); $fragments = []; foreach ($rows->schema()->definitions() as $definition) { diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJSONEncoderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJsonEncoderTest.php similarity index 88% rename from src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJSONEncoderTest.php rename to src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJsonEncoderTest.php index 526aceef73..b3f32a19e9 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJSONEncoderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/RustJsonEncoderTest.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\JSON\Tests\Unit; use DateTimeInterface; -use Flow\ETL\Adapter\JSON\Tests\Mother\JSONEncoderMother; +use Flow\ETL\Adapter\JSON\Tests\Mother\JsonEncoderMother; use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; @@ -29,7 +29,7 @@ use const JSON_UNESCAPED_UNICODE; #[RequiresPhpExtension('flow_php')] -final class RustJSONEncoderTest extends FlowTestCase +final class RustJsonEncoderTest extends FlowTestCase { /** * @return Generator @@ -59,10 +59,10 @@ public function test_encode_returns_what_the_php_encoder_returns(string $batch): $outcomes = []; foreach ([ - 'php' => [JSONEncoderMother::php($flags, $dateTimeFormat, $dateFormat), new PhpBackend()], - 'native' => [JSONEncoderMother::native($flags, $dateTimeFormat, $dateFormat), new AdaptiveBackend()], + 'php' => [JsonEncoderMother::php($flags, $dateTimeFormat, $dateFormat), new PhpBackend()], + 'native' => [JsonEncoderMother::native($flags, $dateTimeFormat, $dateFormat), new AdaptiveBackend()], 'native over adopted php columns' => [ - JSONEncoderMother::native($flags, $dateTimeFormat, $dateFormat), + JsonEncoderMother::native($flags, $dateTimeFormat, $dateFormat), new PhpBackend(), ], ] as $lane => [$encoder, $backend]) { @@ -80,7 +80,7 @@ public function test_encode_returns_what_the_php_encoder_returns(string $batch): public function test_a_batch_under_another_schema_is_rendered_by_that_schema(): void { - $encoder = JSONEncoderMother::native(); + $encoder = JsonEncoderMother::native(); static::assertSame(['{"v":"a b"}', '{"v":{"a":{}}}', '{"v":1.5}'], [ $encoder->encode(array_to_rows([['v' => 'a b']], schema(str_schema('v'))), "\n"), @@ -94,6 +94,6 @@ public function test_the_writer_refuses_a_flag_it_does_not_render(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('flow_php JSON writer supports only the JSON_THROW_ON_ERROR'); - JSONEncoderMother::native(JSON_PRETTY_PRINT); + JsonEncoderMother::native(JSON_PRETTY_PRINT); } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php index 3585548428..43cc251ac1 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Parquet; +use Flow\ETL\Loader\File\FileSink; use Flow\ETL\Rows; use Flow\Filesystem\DestinationStream; use Flow\Parquet\Binary\ByteOrder; @@ -16,7 +17,7 @@ use function extension_loaded; -final readonly class AdaptiveParquetOpenSink implements ParquetOpenSink +final readonly class AdaptiveParquetOpenSink implements FileSink, ParquetOpenSink { private ParquetOpenSink $sink; 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 2158859d96..fbfe8cb348 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 @@ -4,23 +4,24 @@ namespace Flow\ETL\Adapter\Parquet; -use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\DerivedSchema; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\FileReading; +use Flow\ETL\Extractor\File\FileReadLoop; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\ReadWindow; +use Flow\ETL\Extractor\File\SelfDescribingFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Extractor\RewindableExtractor; -use Flow\ETL\Extractor\SelfDescribingFile; use Flow\ETL\Extractor\Signal; -use Flow\ETL\Extractor\SourceFile; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\ETL\Schema\Validator\StrictValidator; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; @@ -30,13 +31,11 @@ use Flow\Parquet\Engine\AdaptiveParquetEngine; use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; -use Flow\Parquet\ParquetFile; use Generator; -use Throwable; use function array_values; use function iterator_count; -use function max; +use function iterator_to_array; use function sprintf; final class ParquetExtractor implements @@ -114,82 +113,30 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $backend = $context->backend(); - $batchSize = $this->batchSize(); - $yielded = 0; - - $fileOffset = $this->offset ?? 0; + $sources = iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false); // every file is read under the first file's schema, or the union of all of them - $expected = $this->derivedSchema($this->schemaFiles(), $this->unionByName); $target = $this->schema(); - $fileColumns = $this->fileColumns($this->filesystem, $this->path); + $batches = new ParquetFileBatches( + $this->opener(), + $fileColumns, + $this->firstFile, + $this->unionByName + ? null + : new DerivedSchema($this->derivedSchema($this->schemaFiles(), $this->unionByName), $this->derivedFrom), + ); + $this->firstFile = null; - foreach ($this->files($pathFilter) as $file) { - $source = null; - - // finally, not a close() per exit: the limit/STOP returns below and an abandoned - // generator have to release the handle too (b73) - try { - $fileRows = $file->file->reader()->rowsNumber(); - - if ($fileOffset > $fileRows) { - $fileOffset -= $fileRows; - - continue; - } - - if (!$this->unionByName) { - $validation = (new StrictValidator())->validate($expected, $file->schema()); - - if (!$validation->isValid()) { - throw InferredSchemaException::filesDiverge( - $file->source()->uri(), - $this->derivedFrom, - $validation, - ); - } - } - - $body = $fileColumns->withoutTail($file->schema()); - // R6: over the FILE's schema, never over schema()'s output - $rowsSchema = $fileColumns->declare($file->schema()); - $constants = $fileColumns->forFile($file->source(), $rowsSchema); - $matchTo = !$rowsSchema->isSame($target) ? $target : null; - - $source = $file->open(); - - foreach ($source->batches( - $body, - $batchSize, - $fileOffset, - $limit === null ? null : $limit - $yielded, - $backend, - ) as $rows) { - $rows = $constants->fillRows($rows, $rowsSchema, $backend); - - if ($matchTo !== null) { - $rows = $rows->matchTo($matchTo); - } - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - - $fileOffset = max($fileOffset - $fileRows, 0); - } finally { - $source?->close(); - $file->close(); - } + try { + yield from (new FileReadLoop($fileColumns, $target))->read( + $sources, + $batches, + $this->batchSize(), + $context->backend(), + new ReadWindow($this->offset ?? 0, $limit), + ); + } finally { + $batches->close(); } } @@ -357,20 +304,15 @@ private function schemaFiles(): Generator private function open(SourceFile $source): ParquetSourceFile { - $stream = $this->filesystem->readFrom($source->path); - $engine = $this->openedWith ??= $this->engine ?? new AdaptiveParquetEngine($this->byteOrder, $this->options); - - try { - $reader = $engine->openForRead($stream); - } catch (Throwable $e) { - $stream->close(); - - throw $e; - } + return $this->opener()->open($source); + } - return new ParquetSourceFile( - new ParquetFile($stream, $this->options, $reader), - $source, + private function opener(): ParquetSourceFileOpener + { + return new ParquetSourceFileOpener( + $this->filesystem, + $this->openedWith ??= $this->engine ?? new AdaptiveParquetEngine($this->byteOrder, $this->options), + $this->options, $this->schemaConverter, array_values($this->columns), ); diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileBatches.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileBatches.php new file mode 100644 index 0000000000..204b82b3c4 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileBatches.php @@ -0,0 +1,90 @@ + $batchSize + * + * @throws InferredSchemaException + * + * @return Generator + */ + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $kept = $this->firstFile; + $this->firstFile = null; + + if ($kept !== null && $kept->source()->uri() !== $source->uri()) { + $kept->close(); + $kept = null; + } + + $file = $kept ?? $this->opener->open($source); + $opened = null; + + try { + $fileRows = $file->file->reader()->rowsNumber(); + + if ($window->offset >= $fileRows) { + return $fileRows; + } + + $this->derived?->refuseDivergence($file->source()->uri(), $file->schema()); + + $fileBody = $this->fileColumns->withoutTail($file->schema()); + $opened = $file->open(); + + foreach ($opened->batches($fileBody, $batchSize, $window->offset, $window->limit, $backend) as $rows) { + yield $fileBody->isSame($body) ? $rows : $rows->matchTo($body, $backend); + } + + return $window->offset; + } finally { + $opened?->close(); + $file->close(); + } + } + + /** + * Closes the kept first file when the read never reached it. + */ + public function close(): void + { + $this->firstFile?->close(); + $this->firstFile = null; + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileSink.php new file mode 100644 index 0000000000..e1a72e1b8a --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileSink.php @@ -0,0 +1,33 @@ +writer?->close(); + } + + public function write(Rows $rows): void + { + $conformed = $this->sinks->conform($rows, $this->backend); + + ($this->writer ??= $this->sinks->writer($this->stream))->write($conformed); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileSinks.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileSinks.php new file mode 100644 index 0000000000..c89ff6a5e1 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetFileSinks.php @@ -0,0 +1,68 @@ +parquetSchema ??= $this->converter->toParquet($this->declared ?? $rows->schema()->makeNullable()); + + return ($this->conformance ??= new ParquetSchemaConformance($this->parquetSchema))->conform($rows, $backend); + } + + public function open(DestinationStream $stream, Backend $backend): FileSink + { + return new ParquetFileSink($this, $stream, $backend); + } + + /** + * The writer of one stream under the run's Parquet schema. + * + * @throws RuntimeException before the first conform() fixed the schema + */ + public function writer(DestinationStream $stream): AdaptiveParquetOpenSink + { + return new AdaptiveParquetOpenSink( + $stream, + $this->parquetSchema ?? throw new RuntimeException('The Parquet schema is fixed by the first conform()'), + $this->compressions, + $this->options, + $this->engine, + ); + } +} diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php index 6a5f1a3c43..8033706a08 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetLoader.php @@ -4,19 +4,17 @@ namespace Flow\ETL\Adapter\Parquet; -use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; use Flow\ETL\Loader\Discardable; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; +use Flow\ETL\Loader\File\FileWriteFrame; +use Flow\ETL\Loader\File\PartitionRouter; use Flow\ETL\Loader\Partitioning; use Flow\ETL\Loader\PartitioningLoader; -use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; @@ -28,36 +26,25 @@ use Flow\Parquet\Options; use Flow\Parquet\ParquetEngine; use Flow\Parquet\ParquetFile\Compressions; -use Flow\Parquet\ParquetFile\Schema as ParquetSchema; -use Throwable; use function sprintf; final class ParquetLoader implements Closure, Discardable, FileLoader, Loader, PartitioningLoader { + private ?FileWriteFrame $frame = null; + private PartitionRouter $router; private readonly Filesystem $filesystem; private SaveMode $saveMode = SaveMode::ExceptionIfExists; - private ?FilesSink $files = null; - - /** @var array */ - private array $writers = []; - private Compressions $compressions = Compressions::SNAPPY; private readonly SchemaConverter $converter; private ?ParquetEngine $engine = null; - private ?Schema $inferredSchema = null; - - private ?ParquetSchemaConformance $conformance = null; - - private ?ParquetSchema $parquetSchema = null; - private Options $options; private readonly Path $path; @@ -94,20 +81,14 @@ public function partitionBy(Partitioning $partitioning): static public function closure(FlowContext $context): void { - $this->closeWriters(); - - $this->files?->publish(); - $this->files = null; + $this->frame?->closure(); + $this->frame = null; } public function discard(FlowContext $context): void { - try { - $this->closeWriters(); - } finally { - $this->files?->abandon(); - $this->files = null; - } + $this->frame?->discard(); + $this->frame = null; } public function destination(): Path @@ -117,41 +98,19 @@ public function destination(): Path public function load(Rows $rows, FlowContext $context): void { - $context->telemetry()->loadingStarted($this, [ - TelemetryAttributes::ATTR_LOADER_DESTINATION_URI => $this->path->uri(), - ]); - - try { - if ($this->schema === null) { - $this->inferredSchema ??= $rows->schema()->makeNullable(); - } - - $parquetSchema = $this->parquetSchema ??= $this->converter->toParquet($this->schema()); - $conformed = ($this->conformance ??= new ParquetSchemaConformance($parquetSchema))->conform( - $rows, - $context->backend(), - ); - - foreach ($this->router->route($conformed) as [$partitions, $group]) { - $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( - $partitions->toArray(), - ); - - ($this->writers[$stream->path()->uri()] ??= new AdaptiveParquetOpenSink( - $stream, - $parquetSchema, - $this->compressions, - $this->options, - $this->engine, - ))->write($group); - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } + ($this->frame ??= new FileWriteFrame( + $this->filesystem, + $this->path, + $this->saveMode, + $this->router, + new ParquetFileSinks( + $this->schema?->gracefulRemove(...$this->router->droppedNames()), + $this->converter, + $this->compressions, + $this->options, + $this->engine, + ), + ))->write($rows, $context, $this); } public function saveMode(SaveMode $mode): static @@ -188,32 +147,4 @@ public function withSchema(Schema $schema): static return $this; } - - private function closeWriters(): void - { - $failure = null; - - foreach ($this->writers as $uri => $writer) { - unset($this->writers[$uri]); - - try { - $writer->close(); - } catch (Throwable $closeFailure) { - $failure ??= $closeFailure; - } - } - - if ($failure !== null) { - throw $failure; - } - } - - private function schema(): Schema - { - return ($this->schema - ?? $this->inferredSchema - ?? throw new RuntimeException( - 'Schema has not been inferred yet. Load at least one batch of rows first.', - ))->gracefulRemove(...$this->router->droppedNames()); - } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaPassFile.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaPassFile.php index f3fde99ea9..4ffc41c110 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaPassFile.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSchemaPassFile.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Adapter\Parquet; -use Flow\ETL\Extractor\SelfDescribingFile; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SelfDescribingFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Extractor\Statistics; use Flow\ETL\Schema; diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php index d1aecaac33..6c9095029b 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFile.php @@ -5,8 +5,8 @@ namespace Flow\ETL\Adapter\Parquet; use Flow\ETL\Cardinality; -use Flow\ETL\Extractor\SelfDescribingFile; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SelfDescribingFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Extractor\Statistics; use Flow\ETL\Schema; use Flow\Parquet\ParquetFile; diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFileOpener.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFileOpener.php new file mode 100644 index 0000000000..890bf57d07 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetSourceFileOpener.php @@ -0,0 +1,49 @@ + $columns the columns to read, every one when empty + */ + public function __construct( + private Filesystem $filesystem, + private ParquetEngine $engine, + private Options $options, + private SchemaConverter $schemaConverter, + private array $columns, + ) {} + + /** + * @throws Throwable the stream is closed when the engine refuses it + */ + public function open(SourceFile $source): ParquetSourceFile + { + $stream = $this->filesystem->readFrom($source->path); + + try { + $reader = $this->engine->openForRead($stream); + } catch (Throwable $e) { + $stream->close(); + + throw $e; + } + + return new ParquetSourceFile( + new ParquetFile($stream, $this->options, $reader), + $source, + $this->schemaConverter, + $this->columns, + ); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php index e76805a4c1..d6e9c840de 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Context/ParquetSourceFileContext.php @@ -6,7 +6,7 @@ use Flow\ETL\Adapter\Parquet\ParquetSourceFile; use Flow\ETL\Adapter\Parquet\SchemaConverter; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; use Flow\Parquet\Engine\PhpParquetEngine; diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Double/RefusingParquetEngine.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Double/RefusingParquetEngine.php new file mode 100644 index 0000000000..c2e346e102 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Double/RefusingParquetEngine.php @@ -0,0 +1,45 @@ + [1, 2, 3], 'b' => [4, 5, 6], 'c' => [7, 8, 9]] as $name => $ids) { + df() + ->read(from_array(array_map(static fn(int $id): array => ['id' => $id], $ids))) + ->write(to_parquet('memory://window/' . $name . '.parquet', filesystem: $filesystem)) + ->run(); + } + + $extractor = from_parquet('memory://window/*.parquet', filesystem: $filesystem)->withOffset(4); + $read = static fn(): array => array_merge(...array_map( + static fn(Rows $rows): array => $rows->column('id')->values(), + iterator_to_array($extractor->extract(flow_context(), limit: 4), false), + )); + + static::assertSame([5, 6, 7, 8], $read()); + static::assertSame([5, 6, 7, 8], $read()); + } } 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 493983f582..14bb23ac22 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 @@ -5,6 +5,7 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Integration; use DateTimeImmutable; +use Flow\ETL\Adapter\Parquet\ParquetExtractor; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InferredSchemaException; @@ -12,6 +13,7 @@ use Flow\ETL\Plan\Stage; use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Double\CountingFilesystem; +use Flow\ETL\Tests\Double\RecordingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Tests\Double\RejectingFilter; @@ -23,6 +25,7 @@ use Flow\Types\Value\Uuid; use function array_keys; +use function count; use function Flow\ETL\Adapter\Parquet\from_parquet; use function Flow\ETL\Adapter\Parquet\to_parquet; use function Flow\ETL\DSL\analyze; @@ -40,6 +43,7 @@ use function Flow\ETL\DSL\str_schema; use function Flow\ETL\DSL\structure_schema; use function Flow\Filesystem\DSL\memory_filesystem; +use function Flow\Filesystem\DSL\native_local_filesystem; use function Flow\Filesystem\DSL\path; use function Flow\Filesystem\DSL\path_real; use function Flow\Types\DSL\type_datetime; @@ -542,4 +546,20 @@ public function test_union_by_name_reads_every_file_under_one_schema(): void ->toArray(), ); } + + public function test_one_extractor_read_twice_interleaved_gives_each_read_every_row_and_closes_every_stream(): void + { + $filesystem = new RecordingFilesystem(native_local_filesystem()); + [$first, $second] = ExtractedRows::interleaved((new ParquetExtractor( + path_real(__DIR__ . '/Fixtures/Pagination/*.parquet'), + $filesystem, + ))->withBatchSize(7)); + + static::assertGreaterThan(0, $first->count()); + static::assertSame($first->toArray(), $second->toArray()); + static::assertSame( + count(array_keys($filesystem->calls, 'readFrom', true)), + count(array_keys($filesystem->calls, 'closeSource', true)), + ); + } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileBatchesTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileBatchesTest.php new file mode 100644 index 0000000000..2d91a62f77 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileBatchesTest.php @@ -0,0 +1,206 @@ + array_to_rows([ + ['id' => 1], + ['id' => 2], + ], schema(int_schema('id')))]); + $opener = new ParquetSourceFileOpener( + $filesystem, + new PhpParquetEngine(), + Options::default(), + new SchemaConverter(), + [], + ); + $file = (new ParquetFileBatches($opener, FileColumnsContext::discovering(names: []), null, null))->batches( + new SourceFile(path('memory://a.parquet')), + schema(int_schema('id', nullable: true)), + 10, + new PhpBackend(), + new ReadWindow(2), + ); + + static::assertSame([], iterator_to_array($file, false)); + static::assertSame(2, $file->getReturn()); + } + + public function test_an_offset_inside_the_file_starts_the_read_there_and_is_consumed(): void + { + $filesystem = memory_filesystem(); + ParquetFilesContext::write($filesystem, ['memory://a.parquet' => array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id')))]); + $opener = new ParquetSourceFileOpener( + $filesystem, + new PhpParquetEngine(), + Options::default(), + new SchemaConverter(), + [], + ); + $file = (new ParquetFileBatches($opener, FileColumnsContext::discovering(names: []), null, null))->batches( + new SourceFile(path('memory://a.parquet')), + schema(int_schema('id', nullable: true)), + 10, + new PhpBackend(), + new ReadWindow(1), + ); + + static::assertSame( + [[['id' => 2], ['id' => 3]]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + static::assertSame(1, $file->getReturn()); + } + + public function test_the_kept_first_file_is_read_instead_of_opened_again(): void + { + $filesystem = new CountingFilesystem(memory_filesystem()); + ParquetFilesContext::write($filesystem, ['memory://a.parquet' => array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id')))]); + $opener = new ParquetSourceFileOpener( + $filesystem, + new PhpParquetEngine(), + Options::default(), + new SchemaConverter(), + [], + ); + $kept = $opener->open(new SourceFile(path('memory://a.parquet'))); + $opened = $filesystem->readFromCalls; + + iterator_to_array((new ParquetFileBatches( + $opener, + FileColumnsContext::discovering(names: []), + $kept, + null, + ))->batches( + new SourceFile(path('memory://a.parquet')), + schema(int_schema('id', nullable: true)), + 10, + new PhpBackend(), + new ReadWindow(), + )); + + static::assertSame($opened, $filesystem->readFromCalls); + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + + public function test_a_kept_first_file_of_another_path_is_closed_and_the_file_opened(): void + { + $filesystem = new CountingFilesystem(memory_filesystem()); + ParquetFilesContext::write($filesystem, [ + 'memory://a.parquet' => array_to_rows([['id' => 1]], schema(int_schema('id'))), + 'memory://b.parquet' => array_to_rows([['id' => 2]], schema(int_schema('id'))), + ]); + $opener = new ParquetSourceFileOpener( + $filesystem, + new PhpParquetEngine(), + Options::default(), + new SchemaConverter(), + [], + ); + $kept = $opener->open(new SourceFile(path('memory://a.parquet'))); + + $rows = iterator_to_array( + (new ParquetFileBatches($opener, FileColumnsContext::discovering(names: []), $kept, null))->batches( + new SourceFile(path('memory://b.parquet')), + schema(int_schema('id', nullable: true)), + 10, + new PhpBackend(), + new ReadWindow(), + ), + false, + ); + + static::assertSame([['id' => 2]], $rows[0]->toArray()); + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + + public function test_close_releases_a_kept_first_file_the_read_never_reached(): void + { + $filesystem = new CountingFilesystem(memory_filesystem()); + ParquetFilesContext::write($filesystem, ['memory://a.parquet' => array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id')))]); + $opener = new ParquetSourceFileOpener( + $filesystem, + new PhpParquetEngine(), + Options::default(), + new SchemaConverter(), + [], + ); + $kept = $opener->open(new SourceFile(path('memory://a.parquet'))); + + (new ParquetFileBatches($opener, FileColumnsContext::discovering(names: []), $kept, null))->close(); + + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + + public function test_a_file_that_diverges_from_the_derived_schema_is_refused_and_closed(): void + { + $filesystem = new CountingFilesystem(memory_filesystem()); + ParquetFilesContext::write($filesystem, ['memory://b.parquet' => array_to_rows([[ + 'name' => 'x', + ]], schema(str_schema('name')))]); + $opener = new ParquetSourceFileOpener( + $filesystem, + new PhpParquetEngine(), + Options::default(), + new SchemaConverter(), + [], + ); + + try { + iterator_to_array((new ParquetFileBatches( + $opener, + FileColumnsContext::discovering(names: []), + null, + new DerivedSchema(schema(int_schema('id', nullable: true)), 'memory://a.parquet'), + ))->batches( + new SourceFile(path('memory://b.parquet')), + schema(int_schema('id')), + 10, + new PhpBackend(), + new ReadWindow(), + )); + static::fail('a diverging file must be refused'); + } catch (InferredSchemaException) { + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileSinkTest.php new file mode 100644 index 0000000000..4ff1478519 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileSinkTest.php @@ -0,0 +1,54 @@ +open(memory_filesystem()->writeTo(path('memory://a.parquet')), new PhpBackend()) + ->close(); + + static::assertSame(0, $engine->openedForWrite); + } + + public function test_the_first_write_opens_one_writer_for_every_write(): void + { + $filesystem = memory_filesystem(); + $engine = new RecordingParquetEngine(); + $sink = (new ParquetFileSinks( + null, + new SchemaConverter(), + Compressions::UNCOMPRESSED, + Options::default(), + $engine, + ))->open($filesystem->writeTo(path('memory://a.parquet')), new PhpBackend()); + + $sink->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); + $sink->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); + $sink->close(); + + static::assertSame(1, $engine->openedForWrite); + static::assertSame([['id' => 1], ['id' => 2]], ParquetFilesContext::values($filesystem, 'memory://a.parquet')); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileSinksTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileSinksTest.php new file mode 100644 index 0000000000..a9e6a60da0 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetFileSinksTest.php @@ -0,0 +1,81 @@ +open($filesystem->writeTo(path('memory://a.parquet')), new PhpBackend()); + $second = $sinks->open($filesystem->writeTo(path('memory://b.parquet')), new PhpBackend()); + + $first->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); + $second->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); + $first->close(); + $second->close(); + + static::assertSame(['id', 'name'], ParquetFilesContext::columnNames($filesystem, 'memory://b.parquet')); + static::assertSame( + [['id' => 2, 'name' => null]], + ParquetFilesContext::values($filesystem, 'memory://b.parquet'), + ); + } + + public function test_a_declared_schema_is_the_written_one(): void + { + $filesystem = memory_filesystem(); + $sink = (new ParquetFileSinks( + schema(int_schema('id', nullable: true), str_schema('note', nullable: true)), + new SchemaConverter(), + Compressions::UNCOMPRESSED, + Options::default(), + new PhpParquetEngine(), + ))->open($filesystem->writeTo(path('memory://a.parquet')), new PhpBackend()); + + $sink->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); + $sink->close(); + + static::assertSame(['id', 'note'], ParquetFilesContext::columnNames($filesystem, 'memory://a.parquet')); + } + + public function test_a_writer_before_the_first_conform_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The Parquet schema is fixed by the first conform()'); + + (new ParquetFileSinks( + null, + new SchemaConverter(), + Compressions::UNCOMPRESSED, + Options::default(), + new PhpParquetEngine(), + ))->writer(memory_filesystem()->writeTo(path('memory://a.parquet'))); + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetLoaderTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetLoaderTest.php index 0fa6c8f8f0..7bd214f679 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetLoaderTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetLoaderTest.php @@ -5,14 +5,48 @@ namespace Flow\ETL\Adapter\Parquet\Tests\Unit; use Flow\ETL\Adapter\Parquet\ParquetLoader; +use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; +use Flow\ETL\Filesystem\SaveMode; use Flow\Filesystem\Path\Option; use Flow\Filesystem\Path\Option\ContentType; use PHPUnit\Framework\TestCase; +use function Flow\ETL\Adapter\Parquet\to_parquet; +use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\config; +use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; +use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; +use function implode; +use function sort; final class ParquetLoaderTest extends TestCase { + public function test_a_second_run_writes_under_its_own_schema(): void + { + $context = flow_context(config()); + $memory = memory_filesystem(); + $loader = to_parquet(path('memory://runs/data.parquet'), filesystem: $memory)->saveMode(SaveMode::Append); + + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); + $loader->closure($context); + $loader->load(array_to_rows([['name' => 'a']], schema(str_schema('name'))), $context); + $loader->closure($context); + + $written = []; + + foreach ($memory->list(path('memory://runs/*.parquet')) as $file) { + $written[] = implode(',', ParquetFilesContext::columnNames($memory, $file->path->uri())); + } + + sort($written); + + static::assertSame(['id', 'name'], $written); + } + public function test_setting_content_type_on_path(): void { $loader = new ParquetLoader(path(__DIR__ . '/file.parquet')); diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileOpenerTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileOpenerTest.php new file mode 100644 index 0000000000..4f917d8e52 --- /dev/null +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileOpenerTest.php @@ -0,0 +1,57 @@ +open(new SourceFile(ParquetSourceFileContext::fixture())); + + static::assertEquals(schema(int_schema('id')), $file->schema()); + + $file->close(); + } + + public function test_a_stream_the_engine_refuses_is_closed(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + + try { + (new ParquetSourceFileOpener( + $filesystem, + new RefusingParquetEngine(), + Options::default(), + new SchemaConverter(), + [], + ))->open(new SourceFile(ParquetSourceFileContext::fixture())); + static::fail('the engine must refuse the stream'); + } catch (RuntimeException) { + static::assertSame(1, $filesystem->readFromCalls); + static::assertSame(1, $filesystem->closedStreams()); + } + } +} diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php index 00b2ac6c09..2ffe2c9b15 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/ParquetSourceFileTest.php @@ -6,7 +6,7 @@ use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetSourceFileContext; use Flow\ETL\Column\PhpBackend; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlEncoder.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlEncoder.php index 93bdab880d..ea4abb3d51 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlEncoder.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlEncoder.php @@ -4,21 +4,50 @@ namespace Flow\ETL\Adapter\PostgreSql; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\TextValues; use Flow\ETL\Rows; +use Flow\Types\Type; -final class PostgreSqlEncoder +final readonly class PostgreSqlEncoder { + public function __construct( + private TextValues $text = new TextValues(), + ) {} + /** - * @return list> + * @param Type $type + * + * @return list */ - public function encode(Rows $rows): array + public function column(Type $type, Column $column): array + { + return $this->text->bindable($type, $column); + } + + /** + * Every column's values, in schema order, as `column()` gives them. + * + * @return array> + */ + public function columns(Rows $rows): array { $columns = []; foreach ($rows->schema()->definitions() as $definition) { - $columns[$definition->entry()->name()] = $rows->column($definition->entry()->name())->values(); + $name = $definition->entry()->name(); + $columns[$name] = $this->column($definition->type(), $rows->column($name)); } + return $columns; + } + + /** + * @return list> + */ + public function encode(Rows $rows): array + { + $columns = $this->columns($rows); $encoded = []; for ($i = 0, $count = $rows->count(); $i < $count; $i++) { diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLoader.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLoader.php index 412d949e0b..1ea413e573 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLoader.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/PostgreSqlLoader.php @@ -138,7 +138,8 @@ private function insertRows(Rows $rows): void if ($rows->count() <= $maxRows) { $builder = new InsertQueryBuilder($this->table, $this->typesMap); [$query, $params] = $builder->build( - $this->encoder()->encode($rows), + $this->encoder()->columns($rows), + $rows->count(), $rows->schema(), $this->client->converters(), $this->insertOptions, @@ -159,7 +160,8 @@ private function insertRows(Rows $rows): void foreach ($rows->chunks($maxRows) as $chunk) { $builder = new InsertQueryBuilder($this->table, $this->typesMap); [$query, $params] = $builder->build( - $this->encoder()->encode($chunk), + $this->encoder()->columns($chunk), + $chunk->count(), $chunk->schema(), $this->client->converters(), $this->insertOptions, diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/InsertQueryBuilder.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/InsertQueryBuilder.php index 7071f82d38..51a634be94 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/InsertQueryBuilder.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/QueryBuilder/InsertQueryBuilder.php @@ -6,6 +6,7 @@ use Flow\ETL\Adapter\PostgreSql\EntryTypesMap; use Flow\ETL\Adapter\PostgreSql\LoaderOptions\InsertOptions; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Schema; use Flow\PostgreSql\Client\ConvertedParameters; use Flow\PostgreSql\Client\Types\ValueConverters; @@ -19,6 +20,7 @@ use function Flow\PostgreSql\DSL\bulk_insert; use function Flow\PostgreSql\DSL\conflict_columns; use function Flow\PostgreSql\DSL\conflict_constraint; +use function sprintf; final readonly class InsertQueryBuilder { @@ -29,32 +31,47 @@ public function __construct( /** * Every value already in PostgreSQL's text form. A column's converter is resolved once, on its first non-null - * value - so a column of an unmapped type holding only nulls passes. + * value - so a column of an unmapped type holding only nulls passes. Parameters are bound row by row, read + * straight from the columns. * - * @param list> $values pre-sorted encoded value maps + * @param array> $columns every column's encoded values, $count of them each + * + * @throws InvalidArgumentException a column that does not hold $count values * * @return array{Sql, ConvertedParameters} */ public function build( - array $values, + array $columns, + int $count, Schema $schema, ValueConverters $converters, ?InsertOptions $options = null, ): array { - $columns = $values === [] ? [] : array_keys($values[0]); + foreach ($columns as $name => $values) { + if (count($values) !== $count) { + throw new InvalidArgumentException(sprintf( + 'Column "%s" holds %d values, the insert %d rows', + $name, + count($values), + $count, + )); + } + } + $names = $count === 0 ? [] : array_keys($columns); $params = []; $types = []; $columnConverters = []; - // every row of a gated batch carries the same columns, so each column's type is resolved once - foreach ($columns as $column) { + foreach ($names as $column) { $types[$column] = $schema->get(ref($column))->type(); } - foreach ($values as $row) { - /** @var mixed $value */ - foreach ($row as $column => $value) { + for ($i = 0; $i < $count; $i++) { + foreach ($names as $column) { + // @mago-ignore analysis:mixed-assignment + $value = $columns[$column][$i]; + if ($value === null) { $params[] = null; @@ -72,7 +89,7 @@ public function build( } } - return [$this->query($columns, count($values), $options), new ConvertedParameters($params)]; + return [$this->query($names, $count, $options), new ConvertedParameters($params)]; } /** diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlEncoderTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlEncoderTest.php index dbe0167223..1bc0d68cce 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlEncoderTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/PostgreSqlEncoderTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\PostgreSql\Tests\Unit; +use DOMDocument; use Flow\ETL\Adapter\PostgreSql\PostgreSqlEncoder; use Flow\ETL\Tests\FlowTestCase; @@ -12,6 +13,8 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\xml_element_schema; +use function Flow\ETL\DSL\xml_schema; final class PostgreSqlEncoderTest extends FlowTestCase { @@ -41,4 +44,29 @@ public function test_encode_of_an_empty_batch_returns_empty(): void { static::assertSame([], (new PostgreSqlEncoder())->encode(array_to_rows([], schema(int_schema('id'))))); } + + public function test_columns_returns_every_columns_values_in_schema_order(): void + { + static::assertSame( + ['id' => [1, 2], 'name' => ['a', null]], + (new PostgreSqlEncoder())->columns(array_to_rows( + [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null]], + schema(int_schema('id'), str_schema('name', nullable: true)), + )), + ); + } + + public function test_columns_render_markup_from_the_physicals(): void + { + $document = new DOMDocument(); + $document->loadXML(''); + + static::assertSame( + ['x' => [''], 'e' => ['']], + (new PostgreSqlEncoder())->columns(array_to_rows( + [['x' => $document, 'e' => $document->getElementsByTagName('a')->item(0)]], + schema(xml_schema('x'), xml_element_schema('e')), + )), + ); + } } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/InsertQueryBuilderTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/InsertQueryBuilderTest.php index aebc74c042..a094c8193d 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/InsertQueryBuilderTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/InsertQueryBuilderTest.php @@ -7,6 +7,7 @@ use Flow\ETL\Adapter\PostgreSql\EntryTypesMap; use Flow\ETL\Adapter\PostgreSql\LoaderOptions\InsertOptions; use Flow\ETL\Adapter\PostgreSql\QueryBuilder\InsertQueryBuilder; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\PostgreSql\Client\Types\ValueConverters; use PHPUnit\Framework\TestCase; @@ -20,7 +21,8 @@ final class InsertQueryBuilderTest extends TestCase public function test_build_converts_each_value_with_its_columns_converter(): void { [$_query, $params] = (new InsertQueryBuilder('users', new EntryTypesMap()))->build( - [['id' => 1, 'name' => 'Alice', 'active' => true], ['id' => 2, 'name' => 'Bob', 'active' => false]], + ['id' => [1, 2], 'name' => ['Alice', 'Bob'], 'active' => [true, false]], + 2, schema(int_schema('id'), str_schema('name'), bool_schema('active')), ValueConverters::create(), ); @@ -31,7 +33,8 @@ public function test_build_converts_each_value_with_its_columns_converter(): voi public function test_build_simple_insert(): void { [$query, $params] = (new InsertQueryBuilder('users', new EntryTypesMap()))->build( - [['id' => 1, 'name' => 'Alice'], ['id' => 2, 'name' => 'Bob']], + ['id' => [1, 2], 'name' => ['Alice', 'Bob']], + 2, schema(int_schema('id'), str_schema('name')), ValueConverters::create(), ); @@ -45,7 +48,8 @@ public function test_build_simple_insert(): void public function test_build_with_null_values(): void { [$_query, $params] = (new InsertQueryBuilder('users', new EntryTypesMap()))->build( - [['id' => 1, 'name' => null]], + ['id' => [1], 'name' => [null]], + 1, schema(int_schema('id'), str_schema('name', nullable: true)), ValueConverters::create(), ); @@ -56,7 +60,8 @@ public function test_build_with_null_values(): void public function test_build_with_skip_conflicts(): void { [$query, $_params] = (new InsertQueryBuilder('users', new EntryTypesMap()))->build( - [['id' => 1, 'name' => 'Alice']], + ['id' => [1], 'name' => ['Alice']], + 1, schema(int_schema('id'), str_schema('name')), ValueConverters::create(), InsertOptions::skipConflicts(), @@ -68,7 +73,8 @@ public function test_build_with_skip_conflicts(): void public function test_build_with_upsert_on_columns(): void { [$query, $_params] = (new InsertQueryBuilder('users', new EntryTypesMap()))->build( - [['id' => 1, 'name' => 'Alice']], + ['id' => [1], 'name' => ['Alice']], + 1, schema(int_schema('id'), str_schema('name')), ValueConverters::create(), InsertOptions::upsertOnColumns(['id']), @@ -82,7 +88,8 @@ public function test_build_with_upsert_on_columns(): void public function test_build_with_upsert_on_constraint(): void { [$query, $_params] = (new InsertQueryBuilder('users', new EntryTypesMap()))->build( - [['id' => 1, 'name' => 'Alice']], + ['id' => [1], 'name' => ['Alice']], + 1, schema(int_schema('id'), str_schema('name')), ValueConverters::create(), InsertOptions::upsertOnConstraint('users_pkey'), @@ -92,4 +99,17 @@ public function test_build_with_upsert_on_constraint(): void static::assertStringContainsString('ON CONSTRAINT "users_pkey"', $sql); static::assertStringContainsString('DO UPDATE SET', $sql); } + + public function test_build_refuses_a_column_of_another_length(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Column "name" holds 1 values, the insert 2 rows'); + + (new InsertQueryBuilder('users', new EntryTypesMap()))->build( + ['id' => [1, 2], 'name' => ['Alice']], + 2, + schema(int_schema('id'), str_schema('name')), + ValueConverters::create(), + ); + } } diff --git a/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealEncoder.php b/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealEncoder.php index 5550f25832..b45895187c 100644 --- a/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealEncoder.php +++ b/src/adapter/etl-adapter-seal/src/Flow/ETL/Adapter/Seal/SealEncoder.php @@ -4,14 +4,11 @@ namespace Flow\ETL\Adapter\Seal; -use DateInterval; use DateTimeInterface; -use DateTimeZone; -use Dom\Element; -use Dom\XMLDocument; -use DOMDocument; -use DOMElement; -use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Column\Column; +use Flow\ETL\Column\Physical\IdentityPhysical; +use Flow\ETL\Column\Physical\PhysicalFor; +use Flow\ETL\Column\TextValues; use Flow\ETL\Rows; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; @@ -21,18 +18,12 @@ use Flow\Types\Type\Logical\MapType; use Flow\Types\Type\Logical\StructureType; use Flow\Types\Type\Logical\TimeType; -use Flow\Types\Type\Logical\TimeZoneType; -use Flow\Types\Type\Logical\UuidType; -use Flow\Types\Type\Logical\XMLElementType; -use Flow\Types\Type\Logical\XMLType; use Flow\Types\Type\Native\ArrayType; -use Flow\Types\Type\Native\EnumType; +use Flow\Types\Type\Native\NullType; use Flow\Types\Value\Json; -use Flow\Types\Value\Uuid; -use UnitEnum; use function array_keys; -use function Flow\ETL\DSL\date_interval_to_microseconds; +use function Flow\Types\DSL\type_bare; use function is_array; use function is_bool; use function is_float; @@ -41,10 +32,14 @@ final class SealEncoder { + private readonly TextValues $text; + public function __construct( private readonly string $dateTimeFormat = DateTimeInterface::ATOM, private readonly string $dateFormat = 'Y-m-d', - ) {} + ) { + $this->text = new TextValues($dateTimeFormat, $dateFormat); + } /** * @return list> @@ -52,12 +47,10 @@ public function __construct( public function encode(Rows $rows): array { $columns = []; - $types = []; foreach ($rows->schema()->definitions() as $definition) { $name = $definition->entry()->name(); - $columns[$name] = $rows->column($name)->values(); - $types[$name] = $definition->type(); + $columns[$name] = $this->column($definition->type(), $rows->column($name)); } $documents = []; @@ -66,7 +59,7 @@ public function encode(Rows $rows): array $document = []; foreach ($columns as $name => $column) { - $document[$name] = $this->renderValue($types[$name], $column[$i]); + $document[$name] = $column[$i]; } $documents[] = $document; @@ -75,24 +68,65 @@ public function encode(Rows $rows): array return $documents; } - private function renderValue(Type $type, mixed $value): string|float|int|bool|array|null + /** + * A column's document fields: datetime / date text from the physicals, json and containers as normalized arrays, + * physicals where the physical is the value (scalars, a time's microseconds, null), TextValues for every other type. + * + * @param Type $type + * + * @return list + */ + public function column(Type $type, Column $column): array { - if ($value === null) { - return null; + $bare = type_bare($type); + + if ($bare instanceof DateTimeType || $bare instanceof DateType) { + /** @var list $physicals */ + $physicals = $column->physicals(); + + return $this->text->dateTimes( + $bare, + $physicals, + $bare instanceof DateType ? $this->dateFormat : $this->dateTimeFormat, + ); } - return match ($type::class) { - DateType::class => $value instanceof DateTimeInterface ? $value->format($this->dateFormat) : null, - DateTimeType::class => $value instanceof DateTimeInterface ? $value->format($this->dateTimeFormat) : null, - TimeType::class => $value instanceof DateInterval ? date_interval_to_microseconds($value) : null, - UuidType::class => $value instanceof Uuid ? $value->toString() : null, - TimeZoneType::class => $value instanceof DateTimeZone ? $value->getName() : null, - EnumType::class => $value instanceof UnitEnum ? $value->name : null, - XMLType::class, XMLElementType::class => $this->xmlToString($value), - JsonType::class => $value instanceof Json ? $this->normalizeArray($value->toArray()) : null, - ListType::class, MapType::class, StructureType::class, ArrayType::class => $this->normalizeArray($value), - default => $this->normalizeValue($value), - }; + if ($bare instanceof JsonType) { + $fields = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $value) { + $fields[] = $value instanceof Json ? $this->normalizeArray($value->toArray()) : null; + } + + return $fields; + } + + if ( + $bare instanceof ListType + || $bare instanceof MapType + || $bare instanceof StructureType + || $bare instanceof ArrayType + ) { + $fields = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($column->values() as $value) { + $fields[] = $this->normalizeArray($value); + } + + return $fields; + } + + if ( + $bare instanceof TimeType + || $bare instanceof NullType + || (new PhysicalFor())->type($bare) instanceof IdentityPhysical + ) { + return $column->physicals(); + } + + return $this->text->texts($type, $column->physicals()); } /** @@ -129,50 +163,4 @@ private function normalizeValue(mixed $value): string|float|int|bool|array|null return null; } - - private function xmlToString(mixed $value): ?string - { - if ($value instanceof XMLDocument) { - return $this->domString($value->saveXml($value->documentElement)); - } - - if ($value instanceof DOMDocument) { - return $this->domString($value->saveXML($value->documentElement)); - } - - if ($value instanceof Element || $value instanceof DOMElement) { - return $this->elementToString($value); - } - - return null; - } - - private function elementToString(Element|DOMElement $value): string - { - $ownerDocument = $value->ownerDocument; - - if ($ownerDocument === null) { - return ''; - } - - if ($ownerDocument instanceof XMLDocument) { - // @mago-ignore analysis:possibly-invalid-argument - return $this->domString($ownerDocument->saveXml($value)); - } - - /** @var false|string $serialized */ - // @mago-ignore analysis:possibly-invalid-argument,non-existent-method - $serialized = $ownerDocument->saveXML($value); - - return $this->domString($serialized); - } - - private function domString(string|false $serialized): string - { - if ($serialized === false) { - throw new RuntimeException('Failed to serialize XML document.'); - } - - return $serialized; - } } diff --git a/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealEncoderTest.php b/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealEncoderTest.php index a609c77ed4..850b61bde8 100644 --- a/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealEncoderTest.php +++ b/src/adapter/etl-adapter-seal/tests/Flow/ETL/Adapter/Seal/Tests/Unit/SealEncoderTest.php @@ -16,18 +16,24 @@ use Flow\Types\Value\Uuid; use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhp; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\definition_from_type; +use function Flow\ETL\DSL\html_element_schema; +use function Flow\ETL\DSL\html_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; +use function Flow\ETL\DSL\xml_element_schema; use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_enum; use function Flow\Types\DSL\type_float; +use function Flow\Types\DSL\type_html_element; use function Flow\Types\DSL\type_integer; use function Flow\Types\DSL\type_json; use function Flow\Types\DSL\type_list; @@ -125,4 +131,50 @@ public function test_produces_documents_keyed_by_column_name(): void )), ); } + + public function test_encodes_an_xml_element_as_its_markup(): void + { + $document = new DOMDocument(); + $document->loadXML(''); + + static::assertSame( + [['e' => '']], + (new SealEncoder())->encode(array_to_rows([[ + 'e' => $document->getElementsByTagName('a')->item(0), + ]], schema(xml_element_schema('e')))), + ); + } + + public function test_encodes_a_datetime_column_with_nulls(): void + { + static::assertSame( + [['at' => '2026-01-02T03:04:05+00:00'], ['at' => null]], + (new SealEncoder())->encode(array_to_rows([ + ['at' => new DateTimeImmutable('2026-01-02 03:04:05 UTC')], + ['at' => null], + ], schema(datetime_schema('at', nullable: true)))), + ); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_encodes_an_html_document_as_its_markup(): void + { + static::assertSame( + [['h' => '

      a

      ']], + (new SealEncoder())->encode(array_to_rows([[ + 'h' => '

      a

      ', + ]], schema(html_schema('h')))), + ); + } + + #[RequiresPhp('>= 8.4.0')] + public function test_encodes_an_html_element_with_a_parent_as_its_markup(): void + { + static::assertSame( + [['e' => '

      a

      ']], + (new SealEncoder())->encode(array_to_rows([[ + 'e' => type_html_element()->cast('

      a

      ')->firstElementChild, + ]], schema(html_element_schema('e')))), + ); + } } 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 7bf318c408..6bbb6fbcba 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 @@ -8,16 +8,17 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\ListedFiles; -use Flow\ETL\Extractor\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\FileReading; +use Flow\ETL\Extractor\File\FileReadLoop; +use Flow\ETL\Extractor\File\ListedFiles; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\ReadWindow; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -26,10 +27,10 @@ use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; -use function count; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; -use function rtrim; +use function implode; +use function iterator_to_array; use function sprintf; final class TextExtractor implements @@ -75,77 +76,18 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $backend = $context->backend(); - $batchSize = $this->batchSize(); - $yielded = 0; - - $baseSchema = $this->schema ?? schema(str_schema('text')); - $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $schema = $fileColumns->declare($baseSchema); - $body = $fileColumns->withoutTail($schema); - - foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { - $stream = $this->filesystem->readFrom($source->path); - - try { - $constants = $fileColumns->forFile($source, $schema); - - $rawLines = []; - - foreach ($stream->readLines() as $line) { - $rawLines[] = ['text' => rtrim($line)]; - - if (count($rawLines) >= $batchSize) { - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows($rawLines) - ->finish(), - $schema, - $backend, - ); - - $rawLines = []; - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - if ($limit !== null && $yielded >= $limit) { - return; - } - } - } - - if ($rawLines !== []) { - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows($rawLines) - ->finish(), - $schema, - $backend, - ); - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - } finally { - $stream->close(); - } - } + yield from (new FileReadLoop( + $fileColumns, + $fileColumns->declare($this->schema ?? schema(str_schema('text'))), + ))->read( + iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false), + new TextFileBatches($this->filesystem), + $this->batchSize(), + $context->backend(), + new ReadWindow(limit: $limit), + ); } public function schema(): Schema @@ -170,8 +112,18 @@ public function statistics(): Statistics return new Statistics(size: $this->listed->bytes); } + /** + * @throws InvalidArgumentException when $schema has no "text" column, the one the lines are read into + */ public function withSchema(Schema $schema): static { + if ($schema->findDefinition('text') === null) { + throw new InvalidArgumentException(sprintf('from_text() reads every line into the "text" column, the schema declares no such column: %s', implode( + ', ', + $schema->references()->names(), + ))); + } + $this->schema = $schema; return $this; diff --git a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextFileBatches.php b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextFileBatches.php new file mode 100644 index 0000000000..4ca40d785b --- /dev/null +++ b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextFileBatches.php @@ -0,0 +1,75 @@ + $batchSize + * + * @return Generator + */ + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $text = new Schema($body->get('text')); + $stream = $this->filesystem->readFrom($source->path); + + try { + $lines = []; + + foreach ($stream->readLines() as $line) { + $lines[] = rtrim($line); + + if (count($lines) >= $batchSize) { + yield $this->batch($text, $lines, $body, $backend); + + $lines = []; + } + } + + if ($lines !== []) { + yield $this->batch($text, $lines, $body, $backend); + } + } finally { + $stream->close(); + } + + return 0; + } + + /** + * @param non-empty-list $lines + */ + public function batch(Schema $text, array $lines, Schema $body, Backend $backend): Rows + { + $builder = $backend->builder($text->get('text')); + $builder->appendMany($lines); + + return Rows::fromColumns($text, ['text' => $builder->finish()], count($lines))->matchTo($body, $backend); + } +} diff --git a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextLoader.php b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextLoader.php index 5a2d63fd7f..d96b15d485 100644 --- a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextLoader.php +++ b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextLoader.php @@ -4,38 +4,40 @@ namespace Flow\ETL\Adapter\Text; -use Flow\ETL\Config\Telemetry\TelemetryAttributes; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; use Flow\ETL\Loader\Discardable; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; +use Flow\ETL\Loader\File\FileSink; +use Flow\ETL\Loader\File\FileSinks; +use Flow\ETL\Loader\File\FileWriteFrame; +use Flow\ETL\Loader\File\PartitionRouter; use Flow\ETL\Loader\Partitioning; use Flow\ETL\Loader\PartitioningLoader; -use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; +use Flow\Filesystem\DestinationStream; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; use Flow\Filesystem\Path\Option; use Flow\Filesystem\Path\Option\ContentType; -use Throwable; use function sprintf; -final class TextLoader implements Closure, Discardable, FileLoader, Loader, PartitioningLoader +final class TextLoader implements Closure, Discardable, FileLoader, FileSinks, Loader, PartitioningLoader { + private ?FileWriteFrame $frame = null; + private PartitionRouter $router; private readonly Filesystem $filesystem; private SaveMode $saveMode = SaveMode::ExceptionIfExists; - private ?FilesSink $files = null; - private ?TextEncoder $encoder = null; private string $newLineSeparator = PHP_EOL; @@ -68,14 +70,14 @@ public function partitionBy(Partitioning $partitioning): static public function closure(FlowContext $context): void { - $this->files?->publish(); - $this->files = null; + $this->frame?->closure(); + $this->frame = null; } public function discard(FlowContext $context): void { - $this->files?->abandon(); - $this->files = null; + $this->frame?->discard(); + $this->frame = null; } public function destination(): Path @@ -89,23 +91,18 @@ public function load(Rows $rows, FlowContext $context): void return; } - $context->telemetry()->loadingStarted($this, [ - TelemetryAttributes::ATTR_LOADER_DESTINATION_URI => $this->path->uri(), - ]); - - try { - foreach ($this->router->route($rows) as [$partitions, $group]) { - ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode)) - ->writeTo($partitions->toArray()) - ->append($this->encoder()->encode($group)); - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); + ($this->frame ??= new FileWriteFrame( + $this->filesystem, + $this->path, + $this->saveMode, + $this->router, + $this, + ))->write($rows, $context, $this); + } - throw $e; - } + public function open(DestinationStream $stream, Backend $backend): FileSink + { + return new TextOpenSink($stream, $this->encoder()); } public function saveMode(SaveMode $mode): static diff --git a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextOpenSink.php b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextOpenSink.php new file mode 100644 index 0000000000..c392c611b6 --- /dev/null +++ b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextOpenSink.php @@ -0,0 +1,27 @@ +stream->append($this->encoder->encode($rows)); + } +} 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 3a57daea28..3a26ef3153 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 @@ -6,6 +6,7 @@ use Flow\ETL\Adapter\Text\TextExtractor; use Flow\ETL\Cardinality; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor\Signal; use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Context\MemoryFiles; @@ -15,6 +16,10 @@ use Flow\ETL\Tests\Double\UnsizedFilesystem; use Flow\ETL\Tests\FlowTestCase; +use function array_keys; +use function array_unique; +use function array_values; +use function count; use function Flow\ETL\Adapter\Text\from_text; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\config_builder; @@ -111,9 +116,9 @@ public function test_limit_reached_on_the_first_file_tail_batch_skips_the_remain public function test_metadata_columns_extend_a_declared_schema(): void { static::assertEquals( - schema(str_schema('line'), str_schema('_input_file_uri')), + schema(str_schema('text'), str_schema('_input_file_uri')), from_text(__DIR__ . '/../Fixtures/annual-enterprise-survey-2019-financial-year-provisional-csv.csv') - ->withSchema(schema(str_schema('line'))) + ->withSchema(schema(str_schema('text'))) ->withMetadataColumns(true) ->schema(), ); @@ -201,4 +206,45 @@ public function test_extract_builds_through_the_config_backend(): void static::assertGreaterThanOrEqual(1, $backend->builders()); } + + public function test_a_schema_without_the_text_column_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'from_text() reads every line into the "text" column, the schema declares no such column: line', + ); + + from_text(__DIR__ . '/../Fixtures/orders_flow.csv')->withSchema(schema(str_schema('line'))); + } + + public function test_columns_a_schema_declares_beside_text_are_padded_with_nulls(): void + { + $rows = data_frame() + ->read( + from_text(path_real(__DIR__ . '/../Fixtures/parity_lines.txt')) + ->withSchema(schema(str_schema('text'), str_schema('note', nullable: true))), + ) + ->fetch(); + + static::assertNotSame(0, $rows->count()); + static::assertSame([null], array_values(array_unique($rows->column('note')->values()))); + } + + public function test_one_extractor_read_twice_interleaved_gives_each_read_every_row_and_closes_every_stream(): void + { + $filesystem = new RecordingFilesystem(MemoryFiles::with([ + 'memory://in/a.txt' => "a\nb\n", + 'memory://in/b.txt' => "c\n", + ])); + [$first, $second] = ExtractedRows::interleaved(from_text(path('memory://in/*.txt'), $filesystem)->withBatchSize( + 1, + )); + + static::assertSame([['text' => 'a'], ['text' => 'b'], ['text' => 'c']], $first->toArray()); + static::assertSame($first->toArray(), $second->toArray()); + static::assertSame( + count(array_keys($filesystem->calls, 'readFrom', true)), + count(array_keys($filesystem->calls, 'closeSource', true)), + ); + } } diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextLoaderTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextLoaderTest.php index 2d195a947d..bfa09ad7e9 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextLoaderTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Integration/TextLoaderTest.php @@ -11,12 +11,15 @@ use Flow\Filesystem\Path\Option\ContentType; use function array_keys; +use function array_map; use function count; use function Flow\ETL\Adapter\Text\to_text; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\partition_by; use function Flow\ETL\DSL\schema; +use function Flow\ETL\DSL\str_schema; use function Flow\Filesystem\DSL\memory_filesystem; use function Flow\Filesystem\DSL\path; @@ -47,4 +50,25 @@ public function test_every_batch_is_one_append(): void ); static::assertSame(2, count(array_keys($filesystem->calls, 'append', true))); } + + public function test_two_runs_through_one_loader_write_independent_files(): void + { + $filesystem = memory_filesystem(); + $loader = to_text(path('memory://out.txt'), filesystem: $filesystem)->partitionBy(partition_by('group')); + $read = []; + + foreach (['a' => [1, 2], 'b' => [3]] as $group => $ids) { + $loader->load( + array_to_rows( + array_map(static fn(int $id): array => ['text' => (string) $id, 'group' => $group], $ids), + schema(str_schema('text'), str_schema('group')), + ), + flow_context(), + ); + $loader->closure(flow_context()); + $read[] = $filesystem->readFrom(path('memory://group=' . $group . '/out.txt'))->content(); + } + + static::assertSame(["1\n2\n", "3\n"], $read); + } } diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextFileBatchesTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextFileBatchesTest.php new file mode 100644 index 0000000000..a4c8385b49 --- /dev/null +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextFileBatchesTest.php @@ -0,0 +1,58 @@ + "a\nb\nc\n"])); + $file = (new TextFileBatches($filesystem))->batches( + new SourceFile(path('memory://a.txt')), + schema(str_schema('text')), + 2, + new PhpBackend(), + new ReadWindow(), + ); + + static::assertSame( + [[['text' => 'a'], ['text' => 'b']], [['text' => 'c']]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + static::assertSame(0, $file->getReturn()); + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + + public function test_a_column_the_body_declares_beside_text_is_padded_with_nulls(): void + { + $file = (new TextFileBatches(MemoryFiles::with(['memory://a.txt' => "a\n"])))->batches( + new SourceFile(path('memory://a.txt')), + schema(str_schema('text'), str_schema('note', nullable: true)), + 10, + new PhpBackend(), + new ReadWindow(), + ); + + static::assertSame( + [[['text' => 'a', 'note' => null]]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + } +} diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextOpenSinkTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextOpenSinkTest.php new file mode 100644 index 0000000000..b8a2dd5281 --- /dev/null +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextOpenSinkTest.php @@ -0,0 +1,32 @@ +writeTo(path('memory://out.txt')); + $sink = new TextOpenSink($stream, new TextEncoder("\n")); + + $sink->write(array_to_rows([['text' => 'a'], ['text' => 'b']], schema(str_schema('text')))); + $sink->write(array_to_rows([['text' => 'c']], schema(str_schema('text')))); + $sink->close(); + $stream->close(); + + static::assertSame("a\nb\nc\n", $filesystem->readFrom(path('memory://out.txt'))->content()); + } +} diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/Loader/XMLLoader.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/Loader/XMLLoader.php index b3dcb5b0cb..4ffd2be705 100644 --- a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/Loader/XMLLoader.php +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/Loader/XMLLoader.php @@ -5,41 +5,43 @@ namespace Flow\ETL\Adapter\XML\Loader; use Flow\ETL\Adapter\XML\XMLEncoder; +use Flow\ETL\Adapter\XML\XMLOpenSink; use Flow\ETL\Adapter\XML\XMLWriter; -use Flow\ETL\Config\Telemetry\TelemetryAttributes; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; use Flow\ETL\Loader\Discardable; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; +use Flow\ETL\Loader\File\FileSink; +use Flow\ETL\Loader\File\FileSinks; +use Flow\ETL\Loader\File\FileWriteFrame; +use Flow\ETL\Loader\File\PartitionRouter; use Flow\ETL\Loader\Partitioning; use Flow\ETL\Loader\PartitioningLoader; -use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; +use Flow\Filesystem\DestinationStream; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; -use Flow\Filesystem\Partition; use Flow\Filesystem\Path; use Flow\Filesystem\Path\Option; use Flow\Filesystem\Path\Option\ContentType; -use Throwable; use function sprintf; use function trim; -final class XMLLoader implements Closure, Discardable, FileLoader, Loader, PartitioningLoader +final class XMLLoader implements Closure, Discardable, FileLoader, FileSinks, Loader, PartitioningLoader { + private ?FileWriteFrame $frame = null; + private PartitionRouter $router; private readonly Filesystem $filesystem; private SaveMode $saveMode = SaveMode::ExceptionIfExists; - private ?FilesSink $files = null; - private string $attributePrefix = '_'; private string $dateFormat = 'Y-m-d'; @@ -96,18 +98,14 @@ public function partitionBy(Partitioning $partitioning): static public function closure(FlowContext $context): void { - foreach ($this->files?->openStreams() ?? [] as $stream) { - $stream->append('rootElementName . '>'); - } - - $this->files?->publish(); - $this->files = null; + $this->frame?->closure(); + $this->frame = null; } public function discard(FlowContext $context): void { - $this->files?->abandon(); - $this->files = null; + $this->frame?->discard(); + $this->frame = null; } public function destination(): Path @@ -121,21 +119,29 @@ public function load(Rows $rows, FlowContext $context): void return; } - $context->telemetry()->loadingStarted($this, [ - TelemetryAttributes::ATTR_LOADER_DESTINATION_URI => $this->path->uri(), - ]); - - try { - foreach ($this->router->route($rows) as [$partitions, $group]) { - $this->write($group, $partitions->toArray()); - } + ($this->frame ??= new FileWriteFrame( + $this->filesystem, + $this->path, + $this->saveMode, + $this->router, + $this, + ))->write($rows, $context, $this); + } - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); + public function open(DestinationStream $stream, Backend $backend): FileSink + { + $attributes = ''; - throw $e; + foreach ($this->xmlAttributes as $name => $value) { + $attributes .= $name . '="' . $value . '" '; } + + return new XMLOpenSink( + $stream, + $this->encoder(), + '\n<" . $this->rootElementName . ">\n", + $this->rootElementName, + ); } public function saveMode(SaveMode $mode): static @@ -218,30 +224,6 @@ public function withXMLAttributes(array $xmlAttributes): self return $this; } - /** - * @param array $partitions - */ - public function write(Rows $nextRows, array $partitions): void - { - $files = $this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode); - $opening = !$files->touched($partitions); - $stream = $files->writeTo($partitions); - - $head = ''; - - if ($opening) { - $attributes = ''; - - foreach ($this->xmlAttributes as $name => $value) { - $attributes .= $name . '="' . $value . '" '; - } - - $head = '\n<" . $this->rootElementName . ">\n"; - } - - $stream->append($head . $this->encoder()->encode($nextRows)); - } - private function encoder(): XMLEncoder { return $this->encoder ??= new XMLEncoder( diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLFileBatches.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLFileBatches.php new file mode 100644 index 0000000000..d04e0a57a2 --- /dev/null +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLFileBatches.php @@ -0,0 +1,64 @@ + $bufferSize + */ + public function __construct( + private Filesystem $filesystem, + private string $xmlNodePath, + private int $bufferSize, + ) {} + + /** + * @param int<1, max> $batchSize + * + * @return Generator + */ + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $batches = new XMLNodeBatches(new XMLNodes($this->xmlNodePath), $batchSize, $this->bufferSize); + $node = $body->get('node'); + $stream = $this->filesystem->readFrom($source->path); + + try { + yield from match (true) { + $node instanceof XMLDefinition && count($body->definitions()) === 1 => $batches->physicals( + $stream, + $node, + $body, + $backend, + ), + $node instanceof StringDefinition => $batches->strings($stream, $body, $backend), + default => $batches->documents($stream, $body, $backend), + }; + } finally { + $stream->close(); + } + + return 0; + } +} diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLNodeBatches.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLNodeBatches.php index 4b009f0a25..d48d696cd5 100644 --- a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLNodeBatches.php +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLNodeBatches.php @@ -5,11 +5,10 @@ namespace Flow\ETL\Adapter\XML; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\Php\ScalarColumn; -use Flow\ETL\Column\Php\XmlDocumentPhysical; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; use Flow\ETL\Rows; -use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; +use Flow\ETL\Schema\Definition; use Flow\ETL\Schema\Definition\XMLDefinition; use Flow\Filesystem\SourceStream; use Generator; @@ -33,24 +32,21 @@ public function __construct( */ public function documents(SourceStream $stream, Schema $body, Backend $backend): Generator { - $batch = []; + $node = $body->get('node'); + $nodes = []; foreach ($this->nodes->documents($stream, $this->bufferSize) as $document) { - $batch[] = ['node' => $document]; + $nodes[] = $document; - if (count($batch) >= $this->batchSize) { - yield (new RowsBuilder($body, $backend)) - ->appendRows($batch) - ->finish(); + if (count($nodes) >= $this->batchSize) { + yield $this->batch($node, $nodes, $body, $backend); - $batch = []; + $nodes = []; } } - if ($batch !== []) { - yield (new RowsBuilder($body, $backend)) - ->appendRows($batch) - ->finish(); + if ($nodes !== []) { + yield $this->batch($node, $nodes, $body, $backend); } } @@ -66,10 +62,12 @@ public function physicals(SourceStream $stream, XMLDefinition $node, Schema $bod $batch[] = $documents->physical($text); if (count($batch) >= $this->batchSize) { - yield Rows::fromColumns( + $builder = $backend->builder($node); + $builder->appendPhysicals($batch, 0); + + yield Rows::fromColumns(new Schema($node), ['node' => $builder->finish()], count($batch))->matchTo( $body, - ['node' => $backend->adopt($node, new ScalarColumn($node->type(), $documents, $batch, 0))], - count($batch), + $backend, ); $batch = []; @@ -77,10 +75,12 @@ public function physicals(SourceStream $stream, XMLDefinition $node, Schema $bod } if ($batch !== []) { - yield Rows::fromColumns( + $builder = $backend->builder($node); + $builder->appendPhysicals($batch, 0); + + yield Rows::fromColumns(new Schema($node), ['node' => $builder->finish()], count($batch))->matchTo( $body, - ['node' => $backend->adopt($node, new ScalarColumn($node->type(), $documents, $batch, 0))], - count($batch), + $backend, ); } } @@ -90,24 +90,38 @@ public function physicals(SourceStream $stream, XMLDefinition $node, Schema $bod */ public function strings(SourceStream $stream, Schema $body, Backend $backend): Generator { - $batch = []; + $node = $body->get('node'); + $nodes = []; foreach ($this->nodes->texts($stream, $this->bufferSize) as $text) { - $batch[] = ['node' => $text]; + $nodes[] = $text; - if (count($batch) >= $this->batchSize) { - yield (new RowsBuilder($body, $backend)) - ->appendRows($batch) - ->finish(); + if (count($nodes) >= $this->batchSize) { + yield $this->batch($node, $nodes, $body, $backend); - $batch = []; + $nodes = []; } } - if ($batch !== []) { - yield (new RowsBuilder($body, $backend)) - ->appendRows($batch) - ->finish(); + if ($nodes !== []) { + yield $this->batch($node, $nodes, $body, $backend); } } + + /** + * The node column built from $nodes; every other column $body declares is padded as matchTo() pads it. + * + * @param Definition $node + * @param non-empty-list $nodes + */ + public function batch(Definition $node, array $nodes, Schema $body, Backend $backend): Rows + { + $builder = $backend->builder($node); + $builder->appendMany($nodes); + + return Rows::fromColumns(new Schema($node), ['node' => $builder->finish()], count($nodes))->matchTo( + $body, + $backend, + ); + } } diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLOpenSink.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLOpenSink.php new file mode 100644 index 0000000000..58556d5985 --- /dev/null +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLOpenSink.php @@ -0,0 +1,40 @@ +written) { + $this->stream->append('rootElementName . '>'); + } + } + + public function write(Rows $rows): void + { + $this->stream->append(($this->written ? '' : $this->head) . $this->encoder->encode($rows)); + $this->written = true; + } +} 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 857fcfdb24..08ac7ea654 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 @@ -8,18 +8,18 @@ use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\ListedFiles; -use Flow\ETL\Extractor\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\FileReading; +use Flow\ETL\Extractor\File\FileReadLoop; +use Flow\ETL\Extractor\File\ListedFiles; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\ReadWindow; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\ETL\Schema\Definition\StringDefinition; -use Flow\ETL\Schema\Definition\XMLDefinition; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; @@ -27,9 +27,10 @@ use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; -use function count; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\xml_schema; +use function implode; +use function iterator_to_array; use function sprintf; final class XMLParserExtractor implements @@ -97,52 +98,18 @@ public function isRepeatable(): bool */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $backend = $context->backend(); - $yielded = 0; - $batches = new XMLNodeBatches(new XMLNodes($this->xmlNodePath), $this->batchSize(), $this->bufferSize); - - $baseSchema = $this->schema ?? schema(xml_schema('node')); - $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $schema = $fileColumns->declare($baseSchema); - $body = $fileColumns->withoutTail($schema); - $node = $body->findDefinition('node'); - - foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { - $stream = $this->filesystem->readFrom($source->path); - - try { - $constants = $fileColumns->forFile($source, $schema); - $lane = match (true) { - $node instanceof XMLDefinition && count($body->definitions()) === 1 => $batches->physicals( - $stream, - $node, - $body, - $backend, - ), - $node instanceof StringDefinition => $batches->strings($stream, $body, $backend), - default => $batches->documents($stream, $body, $backend), - }; - - foreach ($lane as $batch) { - $rows = $constants->fillRows($batch, $schema, $backend); - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - } finally { - $stream->close(); - } - } + + yield from (new FileReadLoop( + $fileColumns, + $fileColumns->declare($this->schema ?? schema(xml_schema('node'))), + ))->read( + iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false), + new XMLFileBatches($this->filesystem, $this->xmlNodePath, $this->bufferSize), + $this->batchSize(), + $context->backend(), + new ReadWindow(limit: $limit), + ); } public function schema(): Schema @@ -177,8 +144,18 @@ public function withBufferSize(int $bufferSize): self return $this; } + /** + * @throws InvalidArgumentException when $schema has no "node" column, the one the matched elements are read into + */ public function withSchema(Schema $schema): static { + if ($schema->findDefinition('node') === null) { + throw new InvalidArgumentException(sprintf('from_xml() reads every matched element into the "node" column, the schema declares no such column: %s', implode( + ', ', + $schema->references()->names(), + ))); + } + $this->schema = $schema; return $this; 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 deleted file mode 100644 index d9112e87f0..0000000000 --- a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLReaderExtractor.php +++ /dev/null @@ -1,238 +0,0 @@ - nodes us root/elements/element. - * - * - * - * - * - * - * - * - * $xmlNodePath does not support attributes and it's not xpath, it is just a sequence - * of node names separated with slash. - * - * @param string $xmlNodePath - */ - public function __construct( - private readonly Path $path, - private readonly string $xmlNodePath = '', - Filesystem $filesystem = new NativeLocalFilesystem(), - ) { - if (!$filesystem->supports($path)) { - throw new InvalidArgumentException(sprintf( - 'Filesystem %s serves "%s://" paths, given: "%s". Pass the filesystem that handles ' - . 'this scheme, e.g. from_xml($path, filesystem: aws_s3_filesystem(...)).', - $filesystem::class, - $filesystem->mount()->protocol, - $path->uri(), - )); - } - - $this->filesystem = $filesystem; - - if (!$this->path->isLocal()) { - throw new InvalidArgumentException( - 'XMLReaderExtractor supports only local files, please use XMLParserExtractor that depends on php-xml extension.', - ); - } - } - - public function isRepeatable(): bool - { - return true; - } - - /** - * @return Generator - */ - public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator - { - $backend = $context->backend(); - $batchSize = $this->batchSize(); - $yielded = 0; - - $baseSchema = $this->schema ?? schema(xml_schema('node')); - - $fileColumns = $this->fileColumns($this->filesystem, $this->path); - $schema = $fileColumns->declare($baseSchema); - $body = $fileColumns->withoutTail($schema); - - foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { - $constants = $fileColumns->forFile($source, $schema); - - $xmlReader = new XMLReader(); - $xmlReader->open($source->path->path()); - - try { - $previousDepth = 0; - $currentPathBreadCrumbs = []; - - $rawNodes = []; - - while ($xmlReader->read()) { - if ($xmlReader->nodeType === XMLReader::ELEMENT) { - if ($previousDepth === $xmlReader->depth) { - array_pop($currentPathBreadCrumbs); - $currentPathBreadCrumbs[] = $xmlReader->name; - } - - if ($xmlReader->depth > $previousDepth) { - $currentPathBreadCrumbs[] = $xmlReader->name; - } - - while ($xmlReader->depth < $previousDepth) { - array_pop($currentPathBreadCrumbs); - $previousDepth--; - } - - $currentPath = implode('/', array_map(strval(...), $currentPathBreadCrumbs)); - - if ( - $currentPath === $this->xmlNodePath - || $this->xmlNodePath === '' && $xmlReader->depth === 0 - ) { - $dom = new DOMDocument('1.0', ''); - $node = $xmlReader->expand($dom); - $rawNodes[] = ['node' => $node === false ? '' : (string) $dom->saveXML($node)]; - - if (count($rawNodes) >= $batchSize) { - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows($rawNodes) - ->finish(), - $schema, - $backend, - ); - - $rawNodes = []; - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - } - - $previousDepth = $xmlReader->depth; - } - } - - if ($rawNodes !== []) { - $rows = $constants->fillRows( - (new RowsBuilder($body, $backend)) - ->appendRows($rawNodes) - ->finish(), - $schema, - $backend, - ); - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - } finally { - $xmlReader->close(); - } - } - } - - 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; - } - - public function statistics(): Statistics - { - $this->listed ??= ListedFiles::of($this->sourceFiles($this->filesystem, $this->path)); - - return new Statistics(size: $this->listed->bytes); - } - - public function withSchema(Schema $schema): static - { - $this->schema = $schema; - - return $this; - } -} diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorBatchContractTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorBatchContractTest.php index 95b342869b..cde649fac1 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorBatchContractTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorBatchContractTest.php @@ -5,12 +5,10 @@ namespace Flow\ETL\Adapter\XML\Tests\Integration; use Flow\ETL\Adapter\XML\XMLParserExtractor; -use Flow\ETL\Adapter\XML\XMLReaderExtractor; use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\Adapter\XML\from_xml; -use function Flow\Filesystem\DSL\path_real; final class XMLExtractorBatchContractTest extends FlowTestCase { @@ -28,20 +26,4 @@ public function test_xml_parser_extractor_honours_the_batch_contract(): void ), ); } - - public function test_xml_reader_extractor_honours_the_batch_contract(): void - { - self::assertExtractorHonoursBatchContract( - // @mago-ignore analysis:deprecated-class - static fn(): XMLReaderExtractor => new XMLReaderExtractor( - path_real(__DIR__ . '/../Fixtures/simple_items.xml'), - 'root/items/item', - ), - // @mago-ignore analysis:deprecated-class - ExtractedRows::of((new XMLReaderExtractor( - path_real(__DIR__ . '/../Fixtures/simple_items.xml'), - 'root/items/item', - ))->withBatchSize(1)), - ); - } } diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php index a3efb7fe49..57c3927ad6 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLExtractorTypedColumnsTest.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\XML\Tests\Integration; use DOMDocument; -use Flow\ETL\Column\Php\XmlDocumentPhysical; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; use Flow\ETL\Config; use Flow\ETL\Tests\FlowTestCase; 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 ff6a87a6e2..0efe23ef0e 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 @@ -7,6 +7,7 @@ use Flow\ETL\Adapter\XML\XMLParserExtractor; use Flow\ETL\Cardinality; use Flow\ETL\Config; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Extractor\Signal; @@ -335,11 +336,21 @@ public function test_schema_defaults_to_a_single_node_column(): void public function test_schema_is_the_declared_one(): void { static::assertEquals( - schema(str_schema('name')), - from_xml(__DIR__ . '/../Fixtures/flow_orders.xml')->withSchema(schema(str_schema('name')))->schema(), + schema(str_schema('node')), + from_xml(__DIR__ . '/../Fixtures/flow_orders.xml')->withSchema(schema(str_schema('node')))->schema(), ); } + public function test_a_schema_without_the_node_column_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage( + 'from_xml() reads every matched element into the "node" column, the schema declares no such column: name', + ); + + from_xml(__DIR__ . '/../Fixtures/flow_orders.xml')->withSchema(schema(str_schema('name'))); + } + public function test_signal_stop(): void { $extractor = from_xml(path_real(__DIR__ . '/../Fixtures/flow_orders.xml'))->withXMLNodePath('root/row'); @@ -504,6 +515,6 @@ public function test_extract_builds_through_the_config_backend(): void false, ); - static::assertGreaterThanOrEqual(1, $backend->adopts()); + static::assertGreaterThanOrEqual(1, $backend->builders()); } } 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 deleted file mode 100644 index 021a30d61c..0000000000 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Integration/XMLReaderExtractorTest.php +++ /dev/null @@ -1,251 +0,0 @@ -withBatchSize(1); - - self::assertExtractedRowsCount(2, $extractor, flow_context(config()), limit: 2); - } - - public function test_partition_columns_are_not_leaking_between_streams(): void - { - $rows = data_frame() - ->read( - // @mago-ignore analysis:deprecated-class - new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/cross_stream/*/file.xml'), 'root/item'), - ) - ->fetch() - ->toArray(); - - static::assertSame(['node', 'date'], array_keys($rows[0])); - static::assertSame('2026-01-01', $rows[0]['date']); - static::assertSame(['node', 'date'], array_keys($rows[1])); - static::assertNull($rows[1]['date']); - } - - public function test_reading_deep_xml(): void - { - static::assertEquals( - 5, - data_frame() - ->read( - // @mago-ignore analysis:deprecated-class - new XMLReaderExtractor( - path(__DIR__ . '/../Fixtures/deepest_items_flat.xml'), - 'root/items/item/deep', - ), - ) - ->fetch() - ->count(), - ); - } - - public function test_reading_xml(): void - { - $xml = new DOMDocument(); - $xml->load(__DIR__ . '/../Fixtures/simple_items.xml'); - - static::assertEquals( - 1, - data_frame() - // @mago-ignore analysis:deprecated-class - ->read(new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/simple_items.xml'))) - ->fetch() - ->count(), - ); - } - - public function test_reading_xml_each_collection_item(): void - { - // @mago-ignore analysis:deprecated-class - $extractor1 = new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/simple_items_flat.xml'), 'root/items/item'); - static::assertXmlStringEqualsXmlString(<<<'XML' - - 1 - - XML, type_string()->cast(data_frame()->read($extractor1)->fetch()->column('node')->value(0))); - - // @mago-ignore analysis:deprecated-class - $extractor2 = new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/simple_items_flat.xml'), 'root/items/item'); - static::assertXmlStringEqualsXmlString(<<<'XML' - - 5 - - XML, type_string()->cast(data_frame()->read($extractor2)->fetch()->column('node')->value(4))); - } - - public function test_reading_xml_from_path(): void - { - static::assertXmlStringEqualsXmlString( - <<<'XML' - - - 1 - - - 2 - - - 3 - - - 4 - - - 5 - - - XML, - type_string()->cast( - data_frame() - // @mago-ignore analysis:deprecated-class - ->read(new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/simple_items.xml'), 'root/items')) - ->fetch() - ->column('node') - ->value(0), - ), - ); - } - - public function test_schema_appends_the_metadata_column(): void - { - // @mago-ignore analysis:deprecated-class - $extractor = new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/flow_orders.xml'), 'root/row'); - - static::assertEquals( - schema(xml_schema('node'), str_schema('_input_file_uri')), - $extractor->withMetadataColumns(true)->schema(), - ); - } - - public function test_schema_describes_a_single_node_column(): void - { - // @mago-ignore analysis:deprecated-class - $extractor = new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/flow_orders.xml'), 'root/row'); - - static::assertEquals(schema(xml_schema('node')), $extractor->schema()); - } - - public function test_signal_stop(): void - { - // @mago-ignore analysis:deprecated-class - $extractor = new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/flow_orders.xml'), 'root/row'); - - $generator = $extractor->extract(flow_context(config())); - - static::assertTrue($generator->valid()); - $generator->next(); - static::assertTrue($generator->valid()); - $generator->next(); - static::assertTrue($generator->valid()); - $generator->send(Signal::STOP); - static::assertFalse($generator->valid()); - } - - public function test_signal_stop_on_the_first_file_tail_batch_skips_the_remaining_files(): void - { - // @mago-ignore analysis:deprecated-class - $generator = (new XMLReaderExtractor(path(__DIR__ . '/../Fixtures/cross_stream/*/file.xml'), 'root/item')) - ->withBatchSize(10) - ->extract(flow_context(config())); - - static::assertTrue($generator->valid()); - $generator->send(Signal::STOP); - static::assertFalse($generator->valid()); - } - - public function test_limit_reached_on_the_first_file_tail_batch_skips_the_remaining_files(): void - { - // @mago-ignore analysis:deprecated-class - $extractor = (new XMLReaderExtractor( - path(__DIR__ . '/../Fixtures/cross_stream/*/file.xml'), - 'root/item', - ))->withBatchSize(10); - - static::assertCount(1, ExtractedRows::of($extractor, limit: 1)); - } - - public function test_is_repeatable(): void - { - static::assertTrue( - // @mago-ignore analysis:deprecated-class - (new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/flow_orders.xml'), 'root/row'))->isRepeatable(), - ); - } - - public function test_it_declares_the_listed_byte_total_exactly(): void - { - // @mago-ignore analysis:deprecated-class - $statistics = (new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/listed/*.xml')))->statistics(); - - static::assertEquals(Cardinality::exact(13), $statistics->size); - static::assertEquals(Cardinality::unknown(), $statistics->rows); - } - - public function test_a_member_without_a_size_makes_the_size_unknown(): void - { - $filesystem = new UnsizedFilesystem(native_local_filesystem(), [ - path_real(__DIR__ . '/../Fixtures/listed/b.xml')->uri(), - ]); - - // @mago-ignore analysis:deprecated-class - $extractor = new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/listed/*.xml'), '', $filesystem); - - static::assertEquals(Cardinality::unknown(), $extractor->statistics()->size); - } - - public function test_the_listing_is_read_once(): void - { - $filesystem = new CountingFilesystem(native_local_filesystem()); - // @mago-ignore analysis:deprecated-class - $extractor = new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/listed/*.xml'), '', $filesystem); - - $extractor->statistics(); - $extractor->statistics(); - - static::assertSame(1, $filesystem->listCalls); - } - - public function test_extract_builds_through_the_config_backend(): void - { - $backend = new SpyBackend(); - // @mago-ignore analysis:deprecated-class - $extractor = new XMLReaderExtractor(path_real(__DIR__ . '/../Fixtures/one_line_items.xml'), 'root/item'); - - iterator_to_array($extractor->extract(flow_context(config_builder()->backend($backend)->build())), false); - - static::assertGreaterThanOrEqual(1, $backend->builders()); - } -} diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLFileBatchesTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLFileBatchesTest.php new file mode 100644 index 0000000000..ed7de84b33 --- /dev/null +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLFileBatchesTest.php @@ -0,0 +1,64 @@ + '12', + ])); + $file = (new XMLFileBatches($filesystem, 'root/row', 8192))->batches( + new SourceFile(path('memory://a.xml')), + schema(str_schema('node')), + 10, + new PhpBackend(), + new ReadWindow(), + ); + + static::assertSame( + [[['node' => '1'], ['node' => '2']]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + static::assertSame(0, $file->getReturn()); + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + + public function test_a_column_the_body_declares_beside_node_is_padded_with_nulls(): void + { + $file = (new XMLFileBatches( + MemoryFiles::with(['memory://a.xml' => '1']), + 'root/row', + 8192, + ))->batches( + new SourceFile(path('memory://a.xml')), + schema(str_schema('node'), str_schema('note', nullable: true)), + 10, + new PhpBackend(), + new ReadWindow(), + ); + + static::assertSame( + [[['node' => '1', 'note' => null]]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + } +} diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLLoaderTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLLoaderTest.php index 14767df627..9f5d08dfd8 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLLoaderTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLLoaderTest.php @@ -12,6 +12,7 @@ use Flow\Filesystem\Path\Option\ContentType; use function array_keys; +use function array_map; use function count; use function Flow\ETL\Adapter\XML\to_xml; use function Flow\ETL\DSL\array_to_rows; @@ -76,4 +77,31 @@ public function test_every_partition_file_has_its_own_root(): void $filesystem->readFrom(path('memory://out/group=b/file.xml'))->content(), ); } + + public function test_two_runs_through_one_loader_write_independent_files(): void + { + $filesystem = memory_filesystem(); + $loader = to_xml(path('memory://out.xml'), filesystem: $filesystem)->partitionBy(partition_by('group')); + $read = []; + + foreach (['a' => [1, 2], 'b' => [3]] as $group => $ids) { + $loader->load( + array_to_rows( + array_map(static fn(int $id): array => ['id' => $id, 'group' => $group], $ids), + schema(int_schema('id'), str_schema('group')), + ), + flow_context(), + ); + $loader->closure(flow_context()); + $read[] = $filesystem->readFrom(path('memory://group=' . $group . '/out.xml'))->content(); + } + + static::assertSame( + [ + "\n\n1\n2\n", + "\n\n3\n", + ], + $read, + ); + } } diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLNodeBatchesTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLNodeBatchesTest.php index 514b6f37ff..afc2bdf992 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLNodeBatchesTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLNodeBatchesTest.php @@ -7,8 +7,8 @@ use DOMDocument; use Flow\ETL\Adapter\XML\XMLNodeBatches; use Flow\ETL\Adapter\XML\XMLNodes; -use Flow\ETL\Column\Php\XmlDocumentPhysical; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; use Flow\ETL\Rows; use Flow\ETL\Schema\Definition\XMLDefinition; use Flow\ETL\Tests\FlowTestCase; diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLNodesTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLNodesTest.php index bcf2eb457a..61028d3c2d 100644 --- a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLNodesTest.php +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLNodesTest.php @@ -7,7 +7,7 @@ use DOMDocument; use Flow\ETL\Adapter\XML\Tests\Context\SerializedNodes; use Flow\ETL\Adapter\XML\XMLNodes; -use Flow\ETL\Column\Php\XmlDocumentPhysical; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Tests\Mother\XmlNodeMother; diff --git a/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLOpenSinkTest.php b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLOpenSinkTest.php new file mode 100644 index 0000000000..05f0f038c1 --- /dev/null +++ b/src/adapter/etl-adapter-xml/tests/Flow/ETL/Adapter/XML/Tests/Unit/XMLOpenSinkTest.php @@ -0,0 +1,47 @@ +writeTo(path('memory://out.xml')); + $sink = new XMLOpenSink($stream, new XMLEncoder(new StringXMLWriter()), "\n\n", 'root'); + + $sink->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); + $sink->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); + $sink->close(); + $stream->close(); + + static::assertSame( + "\n\n1\n2\n", + $filesystem->readFrom(path('memory://out.xml'))->content(), + ); + } + + public function test_a_sink_that_wrote_nothing_closes_without_a_root_end(): void + { + $filesystem = memory_filesystem(); + $stream = $filesystem->writeTo(path('memory://out.xml')); + + (new XMLOpenSink($stream, new XMLEncoder(new StringXMLWriter()), "\n\n", 'root'))->close(); + $stream->close(); + + static::assertSame('', $filesystem->readFrom(path('memory://out.xml'))->content()); + } +} diff --git a/src/cli/src/Flow/CLI/Factory/LoaderFactory.php b/src/cli/src/Flow/CLI/Factory/LoaderFactory.php index 9d912b2748..8307cb9322 100644 --- a/src/cli/src/Flow/CLI/Factory/LoaderFactory.php +++ b/src/cli/src/Flow/CLI/Factory/LoaderFactory.php @@ -7,7 +7,7 @@ use Flow\CLI\Options\FileFormat; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Loader; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; use Flow\Filesystem\Path; use Symfony\Component\Console\Input\InputInterface; diff --git a/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php b/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php index 632d552db0..77fae4e479 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/KeyGrouping.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Bucketing; +use Flow\ETL\Column\Backend; use Flow\ETL\Rows; use Generator; @@ -18,6 +19,7 @@ public function __construct( private KeyValues $keys, private Hasher $hasher, + private Backend $backend, ) {} /** @@ -38,7 +40,7 @@ public function group(Generator $rows): Generator // bound once: every batch out of one bucket shares a schema $schema ??= $input->schema(); - $batch = $input->matchTo($schema); + $batch = $input->matchTo($schema, $this->backend); /** @var array> $indices */ $indices = []; @@ -53,7 +55,7 @@ public function group(Generator $rows): Generator } foreach ($groups as $parts) { - yield $parts[0]->concat(...array_slice($parts, 1)); + yield $parts[0]->concat($this->backend, ...array_slice($parts, 1)); } } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/KeyValues.php b/src/core/etl/src/Flow/ETL/Bucketing/KeyValues.php index 4c0d1bbe9a..57f652eadb 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/KeyValues.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/KeyValues.php @@ -4,12 +4,14 @@ namespace Flow\ETL\Bucketing; +use Flow\ETL\Column\ComparableValues; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; /** * Extracts bucket-key values positionally, in reference order - position, not column name, defines * key identity, so two sides of a join extract hash-compatible values from differently named columns. + * Each value is its column's equality form (ComparableValues): === on it is value equality. */ final readonly class KeyValues { @@ -35,9 +37,13 @@ public function of(Rows $rows): array $values[] = []; } + $comparable = new ComparableValues(); + foreach ($this->refs as $ref) { + $column = $rows->column($rows->schema()->get($ref)->entry()->name()); + // @mago-ignore analysis:mixed-assignment - foreach ($rows->column($rows->schema()->get($ref)->entry()->name())->values() as $i => $value) { + foreach ($comparable->equality($column) as $i => $value) { $values[$i][] = $value; } } diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php b/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php index 986ecbfb89..39cc33e4ed 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/Storage/FilesystemBuckets.php @@ -35,7 +35,7 @@ final class FilesystemBuckets implements BucketsStorage public function __construct( private readonly Filesystem $filesystem, Path $cacheDir, - Backend $backend, + private readonly Backend $backend, private readonly int $batchSize = 1000, ) { // @mago-ignore analysis:impossible-condition,redundant-comparison @@ -44,7 +44,7 @@ public function __construct( } $this->cacheDir = $cacheDir->suffix('/flow-php-buckets/'); - $this->reader = new FloeReader($this->filesystem, backend: $backend); + $this->reader = new FloeReader($this->filesystem, $backend); } /** @@ -56,7 +56,7 @@ public function __construct( public function append(string $bucketId, Rows $rows): void { if (!isset($this->writers[$bucketId])) { - $writer = new FloeWriter($this->filesystem, $rows->schema(), new Options()); + $writer = new FloeWriter($this->filesystem, $rows->schema(), $this->backend, new Options()); $writer->append($this->keyPath($bucketId)); $this->writers[$bucketId] = $writer; } @@ -86,7 +86,7 @@ public function get(string $bucketId): Generator try { foreach ($reader->rows($this->batchSize) as $batch) { if (($pendingRows + $batch->count()) > $this->batchSize) { - yield $pending[0]->concat(...array_slice($pending, 1)); + yield $pending[0]->concat($this->backend, ...array_slice($pending, 1)); $pending = []; $pendingRows = 0; } @@ -96,7 +96,7 @@ public function get(string $bucketId): Generator } if ($pending !== []) { - yield $pending[0]->concat(...array_slice($pending, 1)); + yield $pending[0]->concat($this->backend, ...array_slice($pending, 1)); } } finally { $reader->close(); @@ -116,7 +116,7 @@ public function set(string $bucketId, Rows $rows): void $this->closeWriter($bucketId); // validation stays on until an upstream mechanism guarantees Rows match their schema - $writer = new FloeWriter($this->filesystem, $rows->schema(), new Options()); + $writer = new FloeWriter($this->filesystem, $rows->schema(), $this->backend, new Options()); $writer->create($this->keyPath($bucketId)); $writer->write($rows); $writer->close(); diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Storage/PSRCacheBuckets.php b/src/core/etl/src/Flow/ETL/Bucketing/Storage/PSRCacheBuckets.php index b8e0ad39d0..cc59d6f887 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/Storage/PSRCacheBuckets.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/Storage/PSRCacheBuckets.php @@ -7,7 +7,6 @@ use DateInterval; use Flow\ETL\Bucketing\BucketsStorage; use Flow\ETL\Rows; -use Flow\Floe\FloeSerializer; use Flow\Serializer\Serializer; use Generator; use Psr\SimpleCache\CacheInterface; @@ -21,9 +20,9 @@ { public function __construct( private CacheInterface $cache, + private Serializer $serializer, private string $prefix = 'flow:buckets', private ?DateInterval $ttl = null, - private Serializer $serializer = new FloeSerializer(), ) {} public function append(string $bucketId, Rows $rows): void diff --git a/src/core/etl/src/Flow/ETL/Bucketing/Storage/SpillingBuckets.php b/src/core/etl/src/Flow/ETL/Bucketing/Storage/SpillingBuckets.php index 01474e6d6e..02ea02a79a 100644 --- a/src/core/etl/src/Flow/ETL/Bucketing/Storage/SpillingBuckets.php +++ b/src/core/etl/src/Flow/ETL/Bucketing/Storage/SpillingBuckets.php @@ -52,7 +52,7 @@ final class SpillingBuckets implements BucketsStorage public function __construct( public readonly BucketsStorage $disk, public readonly Unit $memoryLimit, - Backend $backend, + private readonly Backend $backend, private readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand @@ -61,7 +61,7 @@ public function __construct( throw new InvalidArgumentException('Batch size must be greater than 0, given: ' . $this->batchSize); } - $this->budget = new MemoryBudget($backend, $this->memoryLimit); + $this->budget = new MemoryBudget($this->backend, $this->memoryLimit); } /** @@ -108,7 +108,7 @@ public function get(string $bucketId): Generator return; } - $buffered = $this->buffers[$bucketId][0]->concat(...array_slice($this->buffers[$bucketId], 1)); + $buffered = $this->buffers[$bucketId][0]->concat($this->backend, ...array_slice($this->buffers[$bucketId], 1)); for ($offset = 0, $count = $buffered->count(); $offset < $count; $offset += $this->batchSize) { yield $buffered->slice($offset, min($this->batchSize, $count - $offset)); @@ -139,7 +139,7 @@ public function writeFullBatches(string $bucketId): void return; } - $buffered = $this->buffers[$bucketId][0]->concat(...array_slice($this->buffers[$bucketId], 1)); + $buffered = $this->buffers[$bucketId][0]->concat($this->backend, ...array_slice($this->buffers[$bucketId], 1)); $written = $count - ($count % $this->batchSize); for ($offset = 0; $offset < $written; $offset += $this->batchSize) { diff --git a/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php b/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php index 7a76f9c893..7151eba4bc 100644 --- a/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php +++ b/src/core/etl/src/Flow/ETL/Cache/CacheIndex.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Cache; use Flow\ETL\Cardinality; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Rows; @@ -89,9 +90,9 @@ public function rows(): Cardinality return Cardinality::exact($total); } - public function toRows(): Rows + public function toRows(Backend $backend): Rows { - return array_to_rows($this->chunks, schema(str_schema('key'), int_schema('rows', nullable: true))); + return array_to_rows($this->chunks, schema(str_schema('key'), int_schema('rows', nullable: true)), $backend); } /** diff --git a/src/core/etl/src/Flow/ETL/Cache/Implementation/ApcuCache.php b/src/core/etl/src/Flow/ETL/Cache/Implementation/ApcuCache.php index 08b895ce71..1a8b69bd8e 100644 --- a/src/core/etl/src/Flow/ETL/Cache/Implementation/ApcuCache.php +++ b/src/core/etl/src/Flow/ETL/Cache/Implementation/ApcuCache.php @@ -10,6 +10,8 @@ use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Rows; use Flow\ETL\Schema; +use Flow\Serializer\Exception\SerializationException; +use Flow\Serializer\Serializer; use function apcu_delete; use function apcu_enabled; @@ -17,12 +19,16 @@ use function apcu_fetch; use function apcu_store; use function extension_loaded; +use function Flow\Serializer\DSL\serialize_to_string; +use function Flow\Serializer\DSL\unserialize_from_string; +use function is_string; use function preg_quote; use function sprintf; final readonly class ApcuCache implements Cache { public function __construct( + private Serializer $serializer, private string $namespace = 'flow_php_cache', ) { if (!extension_loaded('apcu') || !apcu_enabled()) { @@ -56,14 +62,18 @@ public function get(string $key): Rows throw new KeyNotInCacheException($key); } - if (!$value instanceof Rows) { + if (!is_string($value)) { throw new RuntimeException(sprintf( 'Cache entry for key "%s" is corrupted or was not written by ApcuCache.', $key, )); } - return $value; + try { + return unserialize_from_string($this->serializer, $value); + } catch (SerializationException $e) { + throw new KeyNotInCacheException($key, $e); + } } public function has(string $key): bool @@ -95,7 +105,7 @@ public function schema(string $key): Schema public function set(string $key, Rows $value): void { if ( - apcu_store($this->namespacedKey($key), $value) === false + apcu_store($this->namespacedKey($key), serialize_to_string($this->serializer, $value)) === false || apcu_store($this->schemaKey($key), $value->schema()) === false ) { throw new RuntimeException(sprintf( diff --git a/src/core/etl/src/Flow/ETL/Cache/Implementation/FilesystemCache.php b/src/core/etl/src/Flow/ETL/Cache/Implementation/FilesystemCache.php index 62eb8cd556..19d8db3d4d 100644 --- a/src/core/etl/src/Flow/ETL/Cache/Implementation/FilesystemCache.php +++ b/src/core/etl/src/Flow/ETL/Cache/Implementation/FilesystemCache.php @@ -11,7 +11,6 @@ use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; -use Flow\Floe\FloeSerializer; use Flow\Serializer\Exception\SerializationException; use Flow\Serializer\Serializer; use JsonException; @@ -27,8 +26,8 @@ public function __construct( private Filesystem $filesystem, + private Serializer $serializer, ?Path $cacheDir = null, - private Serializer $serializer = new FloeSerializer(), ) { $this->cacheDir = $cacheDir ?? $this->filesystem->getSystemTmpDir(); } diff --git a/src/core/etl/src/Flow/ETL/Cache/Implementation/PSRSimpleCache.php b/src/core/etl/src/Flow/ETL/Cache/Implementation/PSRSimpleCache.php index f47f042bd5..128f1925de 100644 --- a/src/core/etl/src/Flow/ETL/Cache/Implementation/PSRSimpleCache.php +++ b/src/core/etl/src/Flow/ETL/Cache/Implementation/PSRSimpleCache.php @@ -9,7 +9,6 @@ use Flow\ETL\Exception\KeyNotInCacheException; use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\Floe\FloeSerializer; use Flow\Serializer\Exception\SerializationException; use Flow\Serializer\Serializer; use JsonException; @@ -26,8 +25,8 @@ { public function __construct( private CacheInterface $cache, + private Serializer $serializer, private int|DateInterval|null $ttl = null, - private Serializer $serializer = new FloeSerializer(), ) {} public function clear(): void diff --git a/src/core/etl/src/Flow/ETL/Column/Column.php b/src/core/etl/src/Flow/ETL/Column/Column.php index d4f7ae9817..63e50bdcfa 100644 --- a/src/core/etl/src/Flow/ETL/Column/Column.php +++ b/src/core/etl/src/Flow/ETL/Column/Column.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Column; +use Flow\ETL\Schema\Definition; use Flow\Types\Type; use function extension_loaded; diff --git a/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php index c68309bce5..1de7390c52 100644 --- a/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Column; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; use function extension_loaded; @@ -27,6 +28,19 @@ public function append(mixed $value): void; */ public function appendMany(array $values): void; + /** + * Physical values exactly as Column::physicals() returns them - no cast, no conversion. + * + * @param list $physicals + * @param null|int $nullCount exactly the nulls among $physicals when the caller counted them, null otherwise - a + * count that is not exact is undefined behaviour + * + * @throws SchemaMismatchException at the first null under a NOT NULL definition + * @throws InvalidArgumentException for a physical of another kind than the definition's (a string in an + * integer column, an int in a float column); nothing is appended + */ + public function appendPhysicals(array $physicals, ?int $nullCount = null): void; + /** * Copies one physical cell, no materialisation. */ diff --git a/src/core/etl/src/Flow/ETL/Column/ComparableValues.php b/src/core/etl/src/Flow/ETL/Column/ComparableValues.php index f1999950f6..2311f90966 100644 --- a/src/core/etl/src/Flow/ETL/Column/ComparableValues.php +++ b/src/core/etl/src/Flow/ETL/Column/ComparableValues.php @@ -22,6 +22,9 @@ use Flow\Types\Type\Native\StringType; use function Flow\Types\DSL\type_bare; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_mixed; final readonly class ComparableValues { @@ -67,11 +70,46 @@ public function equalities(Type $type, array $physicals): array $bare = type_bare($type); $element = $bare instanceof ListType ? type_bare($bare->element()) : $bare; + if ($bare instanceof DateType) { + return $this->instants($physicals); + } + + if ($element instanceof DateType) { + $lists = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $list) { + $lists[] = $list === null ? null : $this->instants(type_list(type_mixed())->assert($list)); + } + + return $lists; + } + return $element instanceof HTMLElementType || $element instanceof XMLElementType ? (new TextValues())->of($type, $physicals) : $physicals; } + /** + * A date's physical days on a datetime's microsecond scale, so a date and a datetime at the same instant compare + * and hash equal. + * + * @param list $days + * + * @return list + */ + public function instants(array $days): array + { + $instants = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($days as $day) { + $instants[] = $day === null ? null : type_integer()->assert($day) * 86_400_000_000; + } + + return $instants; + } + /** * @param Type $type */ @@ -95,6 +133,12 @@ public function orderedByPhysical(Type $type): bool */ public function ordering(Column $column): array { - return $this->orderedByPhysical($column->type()) ? $column->physicals() : $column->values(); + if (!$this->orderedByPhysical($column->type())) { + return $column->values(); + } + + return type_bare($column->type()) instanceof DateType + ? $this->instants($column->physicals()) + : $column->physicals(); } } diff --git a/src/core/etl/src/Flow/ETL/Column/Php/BooleanLayout.php b/src/core/etl/src/Flow/ETL/Column/Layout/BooleanLayout.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/BooleanLayout.php rename to src/core/etl/src/Flow/ETL/Column/Layout/BooleanLayout.php index ed5f1a9ff4..f4e90cb2d3 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/BooleanLayout.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/BooleanLayout.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/BufferLayout.php b/src/core/etl/src/Flow/ETL/Column/Layout/BufferLayout.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/BufferLayout.php rename to src/core/etl/src/Flow/ETL/Column/Layout/BufferLayout.php index 9468dcd606..9c801279fb 100644 --- a/src/core/etl/src/Flow/ETL/Column/BufferLayout.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/BufferLayout.php @@ -2,11 +2,8 @@ declare(strict_types=1); -namespace Flow\ETL\Column; +namespace Flow\ETL\Column\Layout; -use Flow\ETL\Column\Php\LayoutFor; -use Flow\ETL\Column\Php\Utf8Layout; -use Flow\ETL\Column\Php\Validity; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Buffers.php b/src/core/etl/src/Flow/ETL/Column/Layout/Buffers.php similarity index 95% rename from src/core/etl/src/Flow/ETL/Column/Php/Buffers.php rename to src/core/etl/src/Flow/ETL/Column/Layout/Buffers.php index 50a4274214..31dd9eddd8 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Buffers.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/Buffers.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/FixedBinary16Layout.php b/src/core/etl/src/Flow/ETL/Column/Layout/FixedBinary16Layout.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/FixedBinary16Layout.php rename to src/core/etl/src/Flow/ETL/Column/Layout/FixedBinary16Layout.php index ba548ff9ae..fd9e105a5d 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/FixedBinary16Layout.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/FixedBinary16Layout.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Float64Layout.php b/src/core/etl/src/Flow/ETL/Column/Layout/Float64Layout.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/Float64Layout.php rename to src/core/etl/src/Flow/ETL/Column/Layout/Float64Layout.php index eafd3e7512..e0445ff90a 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Float64Layout.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/Float64Layout.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Int32Layout.php b/src/core/etl/src/Flow/ETL/Column/Layout/Int32Layout.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/Int32Layout.php rename to src/core/etl/src/Flow/ETL/Column/Layout/Int32Layout.php index ed5a37477b..1d9e99072a 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Int32Layout.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/Int32Layout.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Int64Layout.php b/src/core/etl/src/Flow/ETL/Column/Layout/Int64Layout.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/Int64Layout.php rename to src/core/etl/src/Flow/ETL/Column/Layout/Int64Layout.php index 670680f4bf..22d6950fc9 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Int64Layout.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/Int64Layout.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Layout.php b/src/core/etl/src/Flow/ETL/Column/Layout/Layout.php similarity index 92% rename from src/core/etl/src/Flow/ETL/Column/Php/Layout.php rename to src/core/etl/src/Flow/ETL/Column/Layout/Layout.php index 356480e74c..2e31d5a45b 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Layout.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/Layout.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; interface Layout { diff --git a/src/core/etl/src/Flow/ETL/Column/Php/LayoutFor.php b/src/core/etl/src/Flow/ETL/Column/Layout/LayoutFor.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/LayoutFor.php rename to src/core/etl/src/Flow/ETL/Column/Layout/LayoutFor.php index 6e166e38b2..7fee2e178c 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/LayoutFor.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/LayoutFor.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/NullCount.php b/src/core/etl/src/Flow/ETL/Column/Layout/NullCount.php similarity index 92% rename from src/core/etl/src/Flow/ETL/Column/Php/NullCount.php rename to src/core/etl/src/Flow/ETL/Column/Layout/NullCount.php index f043badcdc..4225bf6c7d 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/NullCount.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/NullCount.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; final readonly class NullCount { diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Offsets.php b/src/core/etl/src/Flow/ETL/Column/Layout/Offsets.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/Offsets.php rename to src/core/etl/src/Flow/ETL/Column/Layout/Offsets.php index 2d60f9e5fa..771192ae2f 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Offsets.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/Offsets.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\OffsetOverflow; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Utf8Layout.php b/src/core/etl/src/Flow/ETL/Column/Layout/Utf8Layout.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/Utf8Layout.php rename to src/core/etl/src/Flow/ETL/Column/Layout/Utf8Layout.php index 3e619d4846..49e6dc2e13 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Utf8Layout.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/Utf8Layout.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Validity.php b/src/core/etl/src/Flow/ETL/Column/Layout/Validity.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/Validity.php rename to src/core/etl/src/Flow/ETL/Column/Layout/Validity.php index c441ba23be..d809503962 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Validity.php +++ b/src/core/etl/src/Flow/ETL/Column/Layout/Validity.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Layout; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php index 5e3635ac42..4e73b0e468 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/CastingColumnBuilder.php @@ -6,7 +6,11 @@ use Flow\ETL\Column\Column; use Flow\ETL\Column\ColumnBuilder; +use Flow\ETL\Column\Physical\IdentityPhysical; +use Flow\ETL\Column\Physical\Physical; +use Flow\ETL\Column\Physical\PhysicalKind; use Flow\ETL\Exception\ColumnMismatchException; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Schema\Definition; use Flow\ETL\Schema\Definition\NullDefinition; @@ -18,6 +22,7 @@ use Flow\Types\Type\Native\StringType; use function get_debug_type; +use function sprintf; final class CastingColumnBuilder implements ColumnBuilder { @@ -129,7 +134,43 @@ public function appendMany(array $values): void )); } - $this->physicals->appendPhysicalMany($physicals, $nulls); + $this->physicals->appendPhysicals($physicals, $nulls); + } + + /** + * @param list $physicals + * + * @throws SchemaMismatchException + */ + public function appendPhysicals(array $physicals, ?int $nullCount = null): void + { + $kind = new PhysicalKind(); + $type = $this->definition->type(); + $checkNulls = !$this->nullable && $nullCount !== 0; + + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $position => $physical) { + if ($physical === null) { + if ($checkNulls) { + throw new SchemaMismatchException($position, ColumnMismatchException::valueDoesNotMatch( + $this->definition, + null, + )); + } + + continue; + } + + if (!$kind->accepts($type, $physical)) { + throw new InvalidArgumentException(sprintf( + 'Cannot store a %s physical in a %s column', + get_debug_type($physical), + $type->toString(), + )); + } + } + + $this->physicals->appendPhysicals($physicals, $nullCount); } public function appendTake(Column $column, array $indices): void @@ -145,7 +186,7 @@ public function appendTake(Column $column, array $indices): void $physicals[] = $all[$index]; } - $this->physicals->appendPhysicalMany($physicals); + $this->physicals->appendPhysicals($physicals); } public function count(): int diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php b/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php index e239fa17c3..bffbb0e153 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/ColumnDecoder.php @@ -4,8 +4,14 @@ namespace Flow\ETL\Column\Php; -use Flow\ETL\Column\BufferLayout; use Flow\ETL\Column\Column; +use Flow\ETL\Column\Layout\BufferLayout; +use Flow\ETL\Column\Layout\Buffers; +use Flow\ETL\Column\Layout\LayoutFor; +use Flow\ETL\Column\Layout\Offsets; +use Flow\ETL\Column\Layout\Validity; +use Flow\ETL\Column\Physical\NullPhysical; +use Flow\ETL\Column\Physical\PhysicalFor; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ConstantColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/ConstantColumn.php index c6c988b314..7db6a65123 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ConstantColumn.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/ConstantColumn.php @@ -5,6 +5,10 @@ namespace Flow\ETL\Column\Php; use Flow\ETL\Column\Column; +use Flow\ETL\Column\Physical\Physical; +use Flow\ETL\Column\Physical\PhysicalBuilderFor; +use Flow\ETL\Column\Physical\PhysicalFor; +use Flow\ETL\Column\Retype; use Flow\Types\Type; use Flow\Types\Type\Logical\OptionalType; use Flow\Types\Type\Native\NullType; @@ -64,7 +68,7 @@ public function expand(): Column } $builder = (new PhysicalBuilderFor())->type($this->type); - $builder->appendPhysicalMany($this->physicals()); + $builder->appendPhysicals($this->physicals()); return $builder->finish(); } diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php index 0cd3a655c9..ebc75a359e 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/ListColumn.php @@ -5,6 +5,9 @@ namespace Flow\ETL\Column\Php; use Flow\ETL\Column\Column; +use Flow\ETL\Column\Layout\Offsets; +use Flow\ETL\Column\Layout\Validity; +use Flow\ETL\Column\Retype; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ListColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/ListColumnBuilder.php index 4f3bf422b7..64ae96d973 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ListColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/ListColumnBuilder.php @@ -42,11 +42,11 @@ public function appendPhysical(mixed $physical): void } assert(is_array($physical)); - $this->element->appendPhysicalMany(array_values($physical)); + $this->element->appendPhysicals(array_values($physical)); $this->offsets[] = $this->element->count(); } - public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + public function appendPhysicals(array $physicals, ?int $nullCount = null): void { $elements = []; $end = $this->offsets[count($this->offsets) - 1]; @@ -71,7 +71,7 @@ public function appendPhysicalMany(array $physicals, ?int $nullCount = null): vo $this->offsets[] = $end; } - $this->element->appendPhysicalMany($elements); + $this->element->appendPhysicals($elements); } public function count(): int diff --git a/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php index e1bf624351..fdff9f9197 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/MapColumn.php @@ -5,6 +5,9 @@ namespace Flow\ETL\Column\Php; use Flow\ETL\Column\Column; +use Flow\ETL\Column\Layout\Offsets; +use Flow\ETL\Column\Layout\Validity; +use Flow\ETL\Column\Retype; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; use Flow\Types\Type\Logical\MapType; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/MapColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/MapColumnBuilder.php index 1ebf6313a2..492c985189 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/MapColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/MapColumnBuilder.php @@ -44,12 +44,12 @@ public function appendPhysical(mixed $physical): void } assert(is_array($physical)); - $this->keys->appendPhysicalMany(array_keys($physical)); - $this->values->appendPhysicalMany(array_values($physical)); + $this->keys->appendPhysicals(array_keys($physical)); + $this->values->appendPhysicals(array_values($physical)); $this->offsets[] = $this->keys->count(); } - public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + public function appendPhysicals(array $physicals, ?int $nullCount = null): void { // @mago-ignore analysis:mixed-assignment foreach ($physicals as $physical) { diff --git a/src/core/etl/src/Flow/ETL/Column/Php/NullColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/NullColumnBuilder.php index 6da20f1822..7971fc8a25 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/NullColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/NullColumnBuilder.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Column\Php; use Flow\ETL\Column\Column; +use Flow\ETL\Column\Physical\NullPhysical; use Flow\Types\Type; use function count; @@ -25,7 +26,7 @@ public function appendPhysical(mixed $physical): void $this->count++; } - public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + public function appendPhysicals(array $physicals, ?int $nullCount = null): void { $this->count += count($physicals); } diff --git a/src/core/etl/src/Flow/ETL/Column/Php/PhpColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/PhpColumnBuilder.php index 5d4260280d..9b3072d4e3 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/PhpColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/PhpColumnBuilder.php @@ -17,7 +17,7 @@ public function appendPhysical(mixed $physical): void; * @param list $physicals * @param null|int $nullCount the nulls among $physicals when the caller already counted them */ - public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void; + public function appendPhysicals(array $physicals, ?int $nullCount = null): void; public function count(): int; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Retype.php b/src/core/etl/src/Flow/ETL/Column/Php/Retype.php deleted file mode 100644 index b10240f29d..0000000000 --- a/src/core/etl/src/Flow/ETL/Column/Php/Retype.php +++ /dev/null @@ -1,52 +0,0 @@ - $from - * @param Type $to - * - * @throws InvalidArgumentException - */ - public function assert(Type $from, Type $to, int $nullCount): void - { - if ($from instanceof OptionalType && !$to instanceof OptionalType && $nullCount > 0) { - throw new InvalidArgumentException(sprintf('%d null values under a required type', $nullCount)); - } - - $fromBase = $from instanceof OptionalType ? $from->base() : $from; - $toBase = $to instanceof OptionalType ? $to->base() : $to; - - $sameKind = match (true) { - $fromBase::class !== $toBase::class => false, - $fromBase instanceof EnumType && $toBase instanceof EnumType => $fromBase->class === $toBase->class, - $fromBase instanceof StructureType && $toBase instanceof StructureType => array_map( - static fn(StructureElement $element): int|string => $element->name, - $fromBase->elements(), - ) === array_map(static fn(StructureElement $element): int|string => $element->name, $toBase->elements()), - default => true, - }; - - if (!$sameKind) { - throw new InvalidArgumentException(sprintf( - '%s and %s are different column kinds', - $from->toString(), - $to->toString(), - )); - } - } -} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumn.php index 41963d8301..0fc13c5f31 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumn.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumn.php @@ -5,6 +5,12 @@ namespace Flow\ETL\Column\Php; use Flow\ETL\Column\Column; +use Flow\ETL\Column\Layout\LayoutFor; +use Flow\ETL\Column\Layout\NullCount; +use Flow\ETL\Column\Layout\Validity; +use Flow\ETL\Column\Physical\Physical; +use Flow\ETL\Column\Physical\PhysicalFor; +use Flow\ETL\Column\Retype; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumnBuilder.php index f287baa107..d2a92470c9 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/ScalarColumnBuilder.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Column\Php; use Flow\ETL\Column\Column; +use Flow\ETL\Column\Physical\Physical; use Flow\Types\Type; use function array_push; @@ -41,7 +42,7 @@ public function appendPhysical(mixed $physical): void $this->values[] = $physical; } - public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + public function appendPhysicals(array $physicals, ?int $nullCount = null): void { $this->nullCount += $nullCount ?? count(array_keys($physicals, null, true)); array_push($this->values, ...$physicals); diff --git a/src/core/etl/src/Flow/ETL/Column/Php/StructColumn.php b/src/core/etl/src/Flow/ETL/Column/Php/StructColumn.php index 995c4b7dd4..2be89158f4 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/StructColumn.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/StructColumn.php @@ -5,6 +5,8 @@ namespace Flow\ETL\Column\Php; use Flow\ETL\Column\Column; +use Flow\ETL\Column\Layout\Validity; +use Flow\ETL\Column\Retype; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; use Flow\Types\Type\Logical\OptionalType; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/StructColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/Php/StructColumnBuilder.php index 06cd44ebad..16ab249e2d 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/StructColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/Php/StructColumnBuilder.php @@ -49,7 +49,7 @@ public function appendPhysical(mixed $physical): void } } - public function appendPhysicalMany(array $physicals, ?int $nullCount = null): void + public function appendPhysicals(array $physicals, ?int $nullCount = null): void { $names = array_keys($this->children); $columns = array_fill_keys($names, []); @@ -68,7 +68,7 @@ public function appendPhysicalMany(array $physicals, ?int $nullCount = null): vo } foreach ($this->children as $name => $child) { - $child->appendPhysicalMany($columns[$name]); + $child->appendPhysicals($columns[$name]); } } diff --git a/src/core/etl/src/Flow/ETL/Column/PhpBackend.php b/src/core/etl/src/Flow/ETL/Column/PhpBackend.php index ebf5281a39..1662a4f33c 100644 --- a/src/core/etl/src/Flow/ETL/Column/PhpBackend.php +++ b/src/core/etl/src/Flow/ETL/Column/PhpBackend.php @@ -4,17 +4,16 @@ namespace Flow\ETL\Column; -use Flow\ETL\Column\Php\Buffers; +use Flow\ETL\Column\Layout\Buffers; use Flow\ETL\Column\Php\CastingColumnBuilder; use Flow\ETL\Column\Php\ColumnDecoder; use Flow\ETL\Column\Php\ConstantColumn; use Flow\ETL\Column\Php\ListColumn; use Flow\ETL\Column\Php\MapColumn; -use Flow\ETL\Column\Php\PhysicalBuilderFor; -use Flow\ETL\Column\Php\PhysicalFor; use Flow\ETL\Column\Php\ScalarColumn; use Flow\ETL\Column\Php\StructColumn; -use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\Physical\PhysicalBuilderFor; +use Flow\ETL\Column\Physical\PhysicalFor; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Schema\Definition; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/DatePhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/DatePhysical.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/DatePhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/DatePhysical.php index 0ab9fc63b9..2a67ef38fb 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/DatePhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/DatePhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use DateTimeImmutable; use DateTimeInterface; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/DateTimePhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/DateTimePhysical.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/DateTimePhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/DateTimePhysical.php index 061b9b072b..43c85b4c26 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/DateTimePhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/DateTimePhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use DateTimeImmutable; use DateTimeInterface; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/DaysFromCivil.php b/src/core/etl/src/Flow/ETL/Column/Physical/DaysFromCivil.php similarity index 94% rename from src/core/etl/src/Flow/ETL/Column/Php/DaysFromCivil.php rename to src/core/etl/src/Flow/ETL/Column/Physical/DaysFromCivil.php index d6064170f3..6f2079dc09 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/DaysFromCivil.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/DaysFromCivil.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use function intdiv; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ElementPosition.php b/src/core/etl/src/Flow/ETL/Column/Physical/ElementPosition.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/ElementPosition.php rename to src/core/etl/src/Flow/ETL/Column/Physical/ElementPosition.php index c5f57e1211..0eafe0448d 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ElementPosition.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/ElementPosition.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use function array_map; use function array_reverse; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/EnumPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/EnumPhysical.php similarity index 96% rename from src/core/etl/src/Flow/ETL/Column/Php/EnumPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/EnumPhysical.php index b05a5e9ff4..5c6487dc67 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/EnumPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/EnumPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use UnitEnum; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/HtmlDocumentPhysical.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/HtmlDocumentPhysical.php index f26feda04b..7d6e87037a 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/HtmlDocumentPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/HtmlDocumentPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use Dom\HTMLDocument; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/HtmlElementPhysical.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/HtmlElementPhysical.php index f7b7e44bae..bdcac7e7d8 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/HtmlElementPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/HtmlElementPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use Dom\HTMLDocument; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/IdentityPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/IdentityPhysical.php similarity index 91% rename from src/core/etl/src/Flow/ETL/Column/Php/IdentityPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/IdentityPhysical.php index 09c0780928..5f964cc81c 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/IdentityPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/IdentityPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; final readonly class IdentityPhysical implements Physical { diff --git a/src/core/etl/src/Flow/ETL/Column/Php/JsonFactory.php b/src/core/etl/src/Flow/ETL/Column/Physical/JsonFactory.php similarity index 96% rename from src/core/etl/src/Flow/ETL/Column/Php/JsonFactory.php rename to src/core/etl/src/Flow/ETL/Column/Physical/JsonFactory.php index 139ed2837d..68eb6b1edf 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/JsonFactory.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/JsonFactory.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use Closure; use Flow\Types\Value\Json; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/JsonPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/JsonPhysical.php similarity index 96% rename from src/core/etl/src/Flow/ETL/Column/Php/JsonPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/JsonPhysical.php index 49e1138185..285fbe8d7f 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/JsonPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/JsonPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use Flow\Types\Value\Json; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ListPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/ListPhysical.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/ListPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/ListPhysical.php index a933bb8696..9b7fbc66d5 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ListPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/ListPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use function assert; use function is_array; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/MapPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/MapPhysical.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/MapPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/MapPhysical.php index ef55b0795a..ed710e4dd0 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/MapPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/MapPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use function array_combine; use function array_keys; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/NullPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/NullPhysical.php similarity index 92% rename from src/core/etl/src/Flow/ETL/Column/Php/NullPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/NullPhysical.php index e24da61b97..699f862c17 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/NullPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/NullPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use function array_fill; use function count; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/Physical.php b/src/core/etl/src/Flow/ETL/Column/Physical/Physical.php similarity index 93% rename from src/core/etl/src/Flow/ETL/Column/Php/Physical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/Physical.php index 64a1ae88dc..568841eec1 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/Physical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/Physical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; interface Physical { diff --git a/src/core/etl/src/Flow/ETL/Column/Php/PhysicalBuilderFor.php b/src/core/etl/src/Flow/ETL/Column/Physical/PhysicalBuilderFor.php similarity index 81% rename from src/core/etl/src/Flow/ETL/Column/Php/PhysicalBuilderFor.php rename to src/core/etl/src/Flow/ETL/Column/Physical/PhysicalBuilderFor.php index f35e4e7d5c..9636117f56 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/PhysicalBuilderFor.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/PhysicalBuilderFor.php @@ -2,8 +2,14 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; - +namespace Flow\ETL\Column\Physical; + +use Flow\ETL\Column\Php\ListColumnBuilder; +use Flow\ETL\Column\Php\MapColumnBuilder; +use Flow\ETL\Column\Php\NullColumnBuilder; +use Flow\ETL\Column\Php\PhpColumnBuilder; +use Flow\ETL\Column\Php\ScalarColumnBuilder; +use Flow\ETL\Column\Php\StructColumnBuilder; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; use Flow\Types\Type\Logical\ListType; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php b/src/core/etl/src/Flow/ETL/Column/Physical/PhysicalFor.php similarity index 99% rename from src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php rename to src/core/etl/src/Flow/ETL/Column/Physical/PhysicalFor.php index 0605606ea1..ccd58a6b90 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/PhysicalFor.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/PhysicalFor.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use BackedEnum; use Flow\ETL\Exception\ColumnMismatchException; diff --git a/src/core/etl/src/Flow/ETL/Column/Physical/PhysicalKind.php b/src/core/etl/src/Flow/ETL/Column/Physical/PhysicalKind.php new file mode 100644 index 0000000000..019db9a397 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Physical/PhysicalKind.php @@ -0,0 +1,100 @@ + $type + */ + public function accepts(Type $type, mixed $physical): bool + { + if ($physical === null) { + return true; + } + + $base = $type instanceof OptionalType ? $type->base() : $type; + + return match (true) { + $base instanceof IntegerType, + $base instanceof PositiveIntegerType, + $base instanceof DateTimeType, + $base instanceof DateType, + $base instanceof TimeType, + => is_int($physical), + $base instanceof FloatType => is_float($physical), + $base instanceof BooleanType => is_bool($physical), + $base instanceof UuidType => is_string($physical) && strlen($physical) === 16, + $base instanceof NullType => true, + $base instanceof ListType => is_array($physical) && $this->all($base->element(), $physical), + $base instanceof MapType => is_array($physical) && $this->all($base->value(), $physical), + $base instanceof StructureType => is_array($physical) && $this->elements($base, $physical), + $base instanceof ArrayType => is_array($physical), + default => is_string($physical), + }; + } + + /** + * @param Type $type + * @param array $physicals + */ + public function all(Type $type, array $physicals): bool + { + // @mago-ignore analysis:mixed-assignment + foreach ($physicals as $physical) { + if (!$this->accepts($type, $physical)) { + return false; + } + } + + return true; + } + + /** + * @param StructureType $type + * @param array $physical + */ + public function elements(StructureType $type, array $physical): bool + { + foreach ($type->elements() as $element) { + if ( + array_key_exists($element->name, $physical) + && !$this->accepts($element->type, $physical[$element->name]) + ) { + return false; + } + } + + return true; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Php/StructPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/StructPhysical.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/StructPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/StructPhysical.php index 7215e7134d..776d42e6f4 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/StructPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/StructPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use function array_key_exists; use function assert; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/TimePhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/TimePhysical.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/TimePhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/TimePhysical.php index bd2dd6efc1..1f8db67dbd 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/TimePhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/TimePhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use DateInterval; use Flow\Types\Exception\CastingException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/TimeZonePhysical.php similarity index 96% rename from src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/TimeZonePhysical.php index f3c8d67722..e4d2a4e73d 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/TimeZonePhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/TimeZonePhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use DateTimeZone; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/TimeZones.php b/src/core/etl/src/Flow/ETL/Column/Physical/TimeZones.php similarity index 89% rename from src/core/etl/src/Flow/ETL/Column/Php/TimeZones.php rename to src/core/etl/src/Flow/ETL/Column/Physical/TimeZones.php index fdb2a16ed0..4614933b18 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/TimeZones.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/TimeZones.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use DateTimeZone; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/UuidPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/UuidPhysical.php similarity index 96% rename from src/core/etl/src/Flow/ETL/Column/Php/UuidPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/UuidPhysical.php index 36f8687b6b..0de84e7668 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/UuidPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/UuidPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use Flow\Types\Value\Uuid; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php index 6d19b0edfe..5fc8b20c7c 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/XmlDocumentPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use DOMDocument; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/XmlElementPhysical.php similarity index 98% rename from src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php rename to src/core/etl/src/Flow/ETL/Column/Physical/XmlElementPhysical.php index 847c9e2fcf..ddba6bea49 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/XmlElementPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/XmlElementPhysical.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column\Physical; use DOMDocument; use DOMElement; diff --git a/src/core/etl/src/Flow/ETL/Column/Retype.php b/src/core/etl/src/Flow/ETL/Column/Retype.php new file mode 100644 index 0000000000..a015b7b749 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Retype.php @@ -0,0 +1,119 @@ + $from + * @param Type $to + * + * @throws InvalidArgumentException + */ + public function assert(Type $from, Type $to, int $nullCount): void + { + if ($from instanceof OptionalType && !$to instanceof OptionalType && $nullCount > 0) { + throw new InvalidArgumentException(sprintf('%d null values under a required type', $nullCount)); + } + + if (!$this->sameKind($from, $to)) { + throw new InvalidArgumentException(sprintf( + '%s and %s are different column kinds', + $from->toString(), + $to->toString(), + )); + } + } + + /** + * Whether withType($to) on a column of $from can only fail on top-level nulls: the same kind at every level, and no + * nested level goes from optional to required (list element, map key / value, structure element by name - + * optional flag and type). + * + * @param Type $from + * @param Type $to + */ + public function proves(Type $from, Type $to): bool + { + if (!$this->sameKind($from, $to)) { + return false; + } + + $fromBase = $from instanceof OptionalType ? $from->base() : $from; + $toBase = $to instanceof OptionalType ? $to->base() : $to; + + if ($fromBase instanceof ListType && $toBase instanceof ListType) { + return $this->provesNested($fromBase->element(), $toBase->element()); + } + + if ($fromBase instanceof MapType && $toBase instanceof MapType) { + return ( + $this->provesNested($fromBase->key(), $toBase->key()) + && $this->provesNested($fromBase->value(), $toBase->value()) + ); + } + + if ($fromBase instanceof StructureType && $toBase instanceof StructureType) { + foreach ($toBase->elements() as $element) { + $own = $fromBase->element($element->name); + + if ( + $own === null + || $own->optional && !$element->optional + || !$this->provesNested($own->type, $element->type) + ) { + return false; + } + } + } + + return true; + } + + /** + * proves() one level down, where a null cannot be counted: optional to required is never proven. + * + * @param Type $from + * @param Type $to + */ + public function provesNested(Type $from, Type $to): bool + { + return !($from instanceof OptionalType && !$to instanceof OptionalType) && $this->proves($from, $to); + } + + /** + * The column kind rule: the same type class, an enum of the same class, a structure of the same element names. + * + * @param Type $from + * @param Type $to + */ + public function sameKind(Type $from, Type $to): bool + { + $fromBase = $from instanceof OptionalType ? $from->base() : $from; + $toBase = $to instanceof OptionalType ? $to->base() : $to; + + return match (true) { + $fromBase::class !== $toBase::class => false, + $fromBase instanceof EnumType && $toBase instanceof EnumType => $fromBase->class === $toBase->class, + $fromBase instanceof StructureType && $toBase instanceof StructureType => array_map( + static fn(StructureElement $element): int|string => $element->name, + $fromBase->elements(), + ) === array_map(static fn(StructureElement $element): int|string => $element->name, $toBase->elements()), + default => true, + }; + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/TextValues.php b/src/core/etl/src/Flow/ETL/Column/TextValues.php index 77457b6eb7..4757e9c272 100644 --- a/src/core/etl/src/Flow/ETL/Column/TextValues.php +++ b/src/core/etl/src/Flow/ETL/Column/TextValues.php @@ -6,15 +6,16 @@ use DateTimeInterface; use DOMDocument; -use Flow\ETL\Column\Php\HtmlElementPhysical; -use Flow\ETL\Column\Php\PhysicalFor; -use Flow\ETL\Column\Php\XmlDocumentPhysical; -use Flow\ETL\Column\Php\XmlElementPhysical; +use Flow\ETL\Column\Physical\HtmlElementPhysical; +use Flow\ETL\Column\Physical\PhysicalFor; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; +use Flow\ETL\Column\Physical\XmlElementPhysical; use Flow\ETL\Exception\RuntimeException; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; use Flow\Types\Type\Logical\DateType; use Flow\Types\Type\Logical\HTMLElementType; +use Flow\Types\Type\Logical\HTMLType; use Flow\Types\Type\Logical\JsonType; use Flow\Types\Type\Logical\ListType; use Flow\Types\Type\Logical\MapType; @@ -201,6 +202,26 @@ public function keepsPhysical(Type $type): bool }; } + /** + * The values a database driver binds for a column: markup (xml, xml_element, html, html_element) as the text its + * physicals render, every other type as its logical values - the driver's types convert those themselves. + * + * @param Type $type + * + * @return list + */ + public function bindable(Type $type, Column $column): array + { + $bare = type_bare($type); + + return $bare instanceof XMLType + || $bare instanceof XMLElementType + || $bare instanceof HTMLType + || $bare instanceof HTMLElementType + ? $this->texts($type, $column->physicals()) + : $column->values(); + } + /** * @param Type $type * @param list $physicals diff --git a/src/core/etl/src/Flow/ETL/Column/Php/ValueColumn.php b/src/core/etl/src/Flow/ETL/Column/ValueColumn.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Column/Php/ValueColumn.php rename to src/core/etl/src/Flow/ETL/Column/ValueColumn.php index d818aa39d4..57c5a8d599 100644 --- a/src/core/etl/src/Flow/ETL/Column/Php/ValueColumn.php +++ b/src/core/etl/src/Flow/ETL/Column/ValueColumn.php @@ -2,9 +2,8 @@ declare(strict_types=1); -namespace Flow\ETL\Column\Php; +namespace Flow\ETL\Column; -use Flow\ETL\Column\Column; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\Types\Type; diff --git a/src/core/etl/src/Flow/ETL/Config.php b/src/core/etl/src/Flow/ETL/Config.php index 005ce30f05..da08289996 100644 --- a/src/core/etl/src/Flow/ETL/Config.php +++ b/src/core/etl/src/Flow/ETL/Config.php @@ -5,7 +5,6 @@ namespace Flow\ETL; use Flow\Calculator\Calculator; -use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; use Flow\ETL\Config\Cache\CacheConfig; use Flow\ETL\Config\ConfigBuilder; @@ -41,9 +40,9 @@ public function __construct( public HashGroupByConfig $grouping, public HashJoinConfig $join, public HashRepartitionConfig $repartition, + private Backend $backend, private Calculator $calculator = new Calculator(), private RandomValueGenerator $randomValueGenerator = new NativePHPRandomValueGenerator(), - private Backend $backend = new AdaptiveBackend(), ) { $this->planner = new Planner($optimizer); } diff --git a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php index 86549122c1..d1e0008e27 100644 --- a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php @@ -107,9 +107,8 @@ public function build(): Config $id = $this->id ??= 'flow-php-' . $this->randomValueGenerator->string(32); $this->optimizer ??= Optimizer::default(); $this->executor ??= new Executor(); - $this->serializer ??= new FloeSerializer(backend: $this->backend); - - $serializer = $this->serializer; + // built per build(), not stored: a later backend() call must reach the next build's serializer + $serializer = $this->serializer ?? new FloeSerializer($this->backend); $optimizer = $this->optimizer; $executor = $this->executor; $dataframeName = $this->name ?? 'flow_dataframe'; diff --git a/src/core/etl/src/Flow/ETL/Constraint/UniqueConstraint.php b/src/core/etl/src/Flow/ETL/Constraint/UniqueConstraint.php index 073fc36e5f..2d5430ccf2 100644 --- a/src/core/etl/src/Flow/ETL/Constraint/UniqueConstraint.php +++ b/src/core/etl/src/Flow/ETL/Constraint/UniqueConstraint.php @@ -33,7 +33,7 @@ public function firstViolation(Rows $rows): ?int return null; } - foreach ((new RowHashes())->of($rows->project($rows->schema()->keep(...$this->reference))) as $i => $key) { + foreach ((new RowHashes())->of($rows->select(...$this->reference->names())) as $i => $key) { if ($this->storage->has($key)) { return $i; } diff --git a/src/core/etl/src/Flow/ETL/DSL/functions.php b/src/core/etl/src/Flow/ETL/DSL/functions.php index e92bf3df65..1ef78d2326 100644 --- a/src/core/etl/src/Flow/ETL/DSL/functions.php +++ b/src/core/etl/src/Flow/ETL/DSL/functions.php @@ -33,10 +33,8 @@ use Flow\ETL\ErrorHandler\IgnoreError; use Flow\ETL\ErrorHandler\SkipRows; use Flow\ETL\ErrorHandler\ThrowError; -use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Exception\UnsupportedUnionTypeException; use Flow\ETL\Extractor; use Flow\ETL\Extractor\ArrayExtractor; @@ -45,9 +43,9 @@ use Flow\ETL\Extractor\CacheExtractor; use Flow\ETL\Extractor\ChainExtractor; use Flow\ETL\Extractor\DataFrameExtractor; +use Flow\ETL\Extractor\File\PartitionTypes; use Flow\ETL\Extractor\FilesExtractor; use Flow\ETL\Extractor\MemoryExtractor; -use Flow\ETL\Extractor\PartitionTypes; use Flow\ETL\Extractor\PathPartitionsExtractor; use Flow\ETL\Extractor\RowsExtractor; use Flow\ETL\Extractor\SequenceExtractor; @@ -149,7 +147,6 @@ use Flow\ETL\Memory\Memory; use Flow\ETL\NativePHPRandomValueGenerator; use Flow\ETL\RandomValueGenerator; -use Flow\ETL\Row\ColumnName; use Flow\ETL\Row\Formatter\ASCIISchemaFormatter; use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; @@ -220,7 +217,6 @@ use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; use Flow\Filesystem\Stream\Mode; -use Flow\Floe\FloeSerializer; use Flow\Serializer\Serializer; use Flow\Types\Type; use Flow\Types\Type\Logical\DateTimeType; @@ -253,7 +249,6 @@ use function array_is_list; use function array_key_exists; use function array_map; -use function array_values; use function class_exists; use function enum_exists; use function Flow\Filesystem\DSL\path; @@ -386,11 +381,11 @@ function files(string|Path $directory, Filesystem $filesystem = new NativeLocalF #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] function filesystem_cache( + Serializer $serializer, Path|string|null $cache_dir = null, Filesystem $filesystem = new NativeLocalFilesystem(), - Serializer $serializer = new FloeSerializer(), ): FilesystemCache { - return new FilesystemCache($filesystem, is_string($cache_dir) ? path_real($cache_dir) : $cache_dir, $serializer); + return new FilesystemCache($filesystem, $serializer, is_string($cache_dir) ? path_real($cache_dir) : $cache_dir); } /** @@ -570,9 +565,9 @@ function rename_map(array $renames): RenameMapEntryStrategy } #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] -function rows(Schema $schema): Rows +function rows(Schema $schema, Backend $backend = new AdaptiveBackend()): Rows { - return Rows::empty($schema); + return Rows::empty($schema, $backend); } /** @@ -1168,52 +1163,8 @@ function number_format( #[DocumentationDSL(module: Module::CORE, type: DSLType::DATA_FRAME)] function array_to_rows(array $data, Schema $schema, Backend $backend = new AdaptiveBackend()): Rows { - $isRows = true; - - // @mago-ignore analysis:mixed-assignment - foreach ($data as $v) { - if (!is_array($v)) { - $isRows = false; - - break; - } - } - - $rawRows = $isRows ? $data : [$data]; - $maps = []; - $definitions = $schema->definitions(); - - // @mago-ignore analysis:mixed-assignment - foreach (array_values($rawRows) as $index => $row) { - $row = type_array()->assert($row); - - if (array_diff_key($row, $definitions) === []) { - $maps[] = $row; - - continue; - } - - $map = []; - - // @mago-ignore analysis:mixed-assignment - foreach ($row as $key => $value) { - // PHP gives back a numeric-string column name as an int key, which the positional rule - // would rename to eNN. A declared schema naming that column settles which one it is. - $declared = $schema->findDefinition((string) $key); - $name = $declared === null ? (new ColumnName())->of($key) : (string) $key; - - if ($declared === null && $schema->findDefinition($name) === null) { - throw new SchemaMismatchException($index, ColumnMismatchException::unexpectedColumn($name)); - } - - $map[$name] = $value; - } - - $maps[] = $map; - } - return (new RowsBuilder($schema, $backend)) - ->appendRows($maps) + ->appendRecords($data) ->finish(); } diff --git a/src/core/etl/src/Flow/ETL/Executor.php b/src/core/etl/src/Flow/ETL/Executor.php index 44ebdcc6af..60b6e75af9 100644 --- a/src/core/etl/src/Flow/ETL/Executor.php +++ b/src/core/etl/src/Flow/ETL/Executor.php @@ -6,9 +6,10 @@ use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\SchemaNotDerivableException; +use Flow\ETL\Executor\AdoptedBatches; use Flow\ETL\Executor\PhysicalPlan; use Flow\ETL\Executor\Pipeline; -use Flow\ETL\Extractor\FileExtractor; +use Flow\ETL\Extractor\File\FileExtractor; use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; use Throwable; @@ -107,7 +108,7 @@ public function merge(Generator $batches, PhysicalPlan $plan): Rows } if ($parts !== []) { - return $parts[0]->concat(...array_slice($parts, 1)); + return $parts[0]->concat($plan->root()->context()->backend(), ...array_slice($parts, 1)); } if ($last !== null) { @@ -115,9 +116,9 @@ public function merge(Generator $batches, PhysicalPlan $plan): Rows } try { - return Rows::empty($plan->schema()); + return Rows::empty($plan->schema(), $plan->root()->context()->backend()); } catch (SchemaNotDerivableException) { - return Rows::empty(new Schema()); + return Rows::empty(new Schema(), $plan->root()->context()->backend()); } } @@ -141,9 +142,11 @@ public function executePipeline(Pipeline $pipeline): Generator 'pipeline #%d', $leaf->id, )); - $generator = $source instanceof FileExtractor - ? $source->extract($leaf->context(), $leaf->limit(), $leaf->pathFilter()) - : $source->extract($leaf->context(), $leaf->limit()); + $generator = (new AdoptedBatches($leaf->context()->backend()))->of( + $source instanceof FileExtractor + ? $source->extract($leaf->context(), $leaf->limit(), $leaf->pathFilter()) + : $source->extract($leaf->context(), $leaf->limit()), + ); $sources = $leaf->sources(); if ($sources !== null) { diff --git a/src/core/etl/src/Flow/ETL/Executor/AdoptedBatches.php b/src/core/etl/src/Flow/ETL/Executor/AdoptedBatches.php new file mode 100644 index 0000000000..e9e57dc389 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Executor/AdoptedBatches.php @@ -0,0 +1,37 @@ + $batches what an extractor yields + * + * @return Generator + */ + public function of(Generator $batches): Generator + { + foreach ($batches as $batch) { + $signal = yield $batch->adoptedBy($this->backend); + + if ($signal === Signal::STOP) { + $batches->send(Signal::STOP); + + return; + } + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Executor/Segment.php b/src/core/etl/src/Flow/ETL/Executor/Segment.php index b504ba8901..14d57bb2c5 100644 --- a/src/core/etl/src/Flow/ETL/Executor/Segment.php +++ b/src/core/etl/src/Flow/ETL/Executor/Segment.php @@ -130,7 +130,7 @@ public function execute(Generator $input, FlowContext $context): Generator } catch (LimitReachedException $limit) { $context->telemetry()->limitReached(['limit' => $limit->limit]); // the remaining steps still run, on the trimmed batch - $rows = $limit->rows ?? Rows::empty($rows->schema()); + $rows = $limit->rows ?? Rows::empty($rows->schema(), $context->backend()); $stop = true; } catch (Throwable $failure) { if ($failure instanceof SinkFailure) { diff --git a/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php index 4832f04613..72fcd2079c 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/ArrayExtractor.php @@ -7,6 +7,9 @@ use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Extractor; +use Flow\ETL\Extractor\Memory\InferredRows; +use Flow\ETL\Extractor\Memory\InMemoryRows; +use Flow\ETL\Extractor\Memory\SpilledRows; use Flow\ETL\FlowContext; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php index 49649d73d0..7ef17eaf19 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchByExtractor.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Extractor; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; use Flow\ETL\FlowContext; @@ -44,7 +45,7 @@ public function isRepeatable(): bool public function extract(FlowContext $context, ?int $limit = null): Generator { return (new BatchingByProcessor($this->column, $this->minSize))->process( - $this->declared($this->extractor->extract($context)), + $this->declared($this->extractor->extract($context), $context->backend()), $context, ); } @@ -54,7 +55,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator * * @return Generator */ - public function declared(Generator $batches): Generator + public function declared(Generator $batches, Backend $backend): Generator { if ($this->schema === null) { yield from $batches; @@ -63,7 +64,7 @@ public function declared(Generator $batches): Generator } foreach ($batches as $batch) { - yield $batch->matchTo($this->schema); + yield $batch->matchTo($this->schema, $backend); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php index 7f8031afc6..962f956c61 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/BatchExtractor.php @@ -38,13 +38,13 @@ public function extract(FlowContext $context, ?int $limit = null): Generator foreach ($this->extractor->extract($context) as $rows) { $schema ??= $rows->schema(); - $pending[] = $rows->matchTo($schema); + $pending[] = $rows->matchTo($schema, $context->backend()); $pendingCount += $rows->count(); while ($pendingCount >= $this->batchSize) { // one variadic concat per window copies each row once; a pairwise concat per child batch would // re-copy everything pending - $window = Rows::empty($schema)->concat(...$pending); + $window = Rows::empty($schema, $context->backend())->concat($context->backend(), ...$pending); $signal = yield $window->slice(0, $this->batchSize); if ($signal === Signal::STOP) { @@ -59,7 +59,10 @@ public function extract(FlowContext $context, ?int $limit = null): Generator } if ($pendingCount > 0) { - yield Rows::empty($schema ?? $this->schema())->concat(...$pending); + yield Rows::empty($schema ?? $this->schema(), $context->backend())->concat( + $context->backend(), + ...$pending, + ); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/CacheExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/CacheExtractor.php index 488727bbd4..a2488e42ab 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/CacheExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/CacheExtractor.php @@ -47,7 +47,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator if (!$cache->has($this->id)) { if ($this->fallbackExtractor !== null) { foreach ($this->fallbackExtractor->extract($context) as $rows) { - $signal = yield $declared === null ? $rows : $rows->matchTo($declared); + $signal = yield $declared === null ? $rows : $rows->matchTo($declared, $context->backend()); if ($signal === Signal::STOP) { return; @@ -60,7 +60,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator foreach ($index->values() as $cacheKey) { $cached = $cache->get($cacheKey); - $signal = yield $folded === null ? $cached : $cached->matchTo($folded); + $signal = yield $folded === null ? $cached : $cached->matchTo($folded, $context->backend()); if ($signal === Signal::STOP) { return; diff --git a/src/core/etl/src/Flow/ETL/Extractor/ChainExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/ChainExtractor.php index 6f4a444d11..df3a827f23 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/ChainExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/ChainExtractor.php @@ -45,7 +45,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator foreach ($this->extractors as $extractor) { foreach ($extractor->extract($context) as $rows) { - $signal = yield $rows->matchTo($schema); + $signal = yield $rows->matchTo($schema, $context->backend()); if ($signal === Signal::STOP) { return; diff --git a/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php index abfff21eda..b6be4394b0 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/CollectingExtractor.php @@ -26,13 +26,18 @@ public function extract(FlowContext $context, ?int $limit = null): Generator foreach ($this->extractor->extract($context) as $rows) { if ($schema !== null) { - $rows = $rows->matchTo($schema); + $rows = $rows->matchTo($schema, $context->backend()); } - $collectedRows = $collectedRows === null ? $rows : $collectedRows->merge($rows); + // an empty part adds nothing, whatever its schema + $collectedRows = match (true) { + $collectedRows === null, $collectedRows->isEmpty() => $rows, + $rows->isEmpty() => $collectedRows, + default => $collectedRows->concat($context->backend(), $rows), + }; } - yield $collectedRows ?? Rows::empty($this->schema()); + yield $collectedRows ?? Rows::empty($this->schema(), $context->backend()); } public function isRepeatable(): bool diff --git a/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php index 58ccb5b394..febb950e9c 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/DataFrameExtractor.php @@ -10,13 +10,11 @@ use Flow\ETL\Plan; use Flow\ETL\Plan\Node\Limit; use Flow\ETL\Plan\Trigger; -use Flow\ETL\Row\DeclaredColumns; use Flow\ETL\Rows; +use Flow\ETL\Rows\ColumnRetyping; use Flow\ETL\Schema; use Generator; -use function Flow\ETL\DSL\array_to_rows; - final class DataFrameExtractor implements RewindableExtractor { private ?Schema $schema = null; @@ -47,11 +45,19 @@ public function extract(FlowContext $context, ?int $limit = null): Generator foreach ($config->executor()->execute($config->planner()->plan($logical, $this->plan->context)) as $rows) { if ($this->schema !== null) { - $rows = array_to_rows( - (new DeclaredColumns())->project($rows->toArray(), $this->schema), - $this->schema, - $context->backend(), - ); + $backend = $context->backend(); + $retyping = new ColumnRetyping(); + $columns = []; + + foreach ($this->schema->definitions() as $name => $definition) { + $own = $rows->schema()->findDefinition($definition->entry()->name()); + + $columns[$name] = $own === null + ? $retyping->absent($definition, $rows->count(), $backend) + : $retyping->cast($rows->column($definition->entry()->name()), $own, $definition, $backend); + } + + $rows = Rows::fromColumns($this->schema, $columns, $rows->count()); } $signal = yield $rows; diff --git a/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php index 8b022ee2cc..769f446420 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FeedExtractor.php @@ -59,7 +59,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator // is parked, so both operands can change between the yield and this check. if ($this->batch === null && !$this->finished) { // a downstream projection still sees the columns it was built against - $signal = yield Rows::empty($this->schema); + $signal = yield Rows::empty($this->schema, $context->backend()); if ($signal === Signal::STOP) { return; diff --git a/src/core/etl/src/Flow/ETL/Extractor/DeclaresPartitionTypes.php b/src/core/etl/src/Flow/ETL/Extractor/File/DeclaresPartitionTypes.php similarity index 91% rename from src/core/etl/src/Flow/ETL/Extractor/DeclaresPartitionTypes.php rename to src/core/etl/src/Flow/ETL/Extractor/File/DeclaresPartitionTypes.php index 6ab9804563..fe46d0c6b0 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/DeclaresPartitionTypes.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/DeclaresPartitionTypes.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; trait DeclaresPartitionTypes { diff --git a/src/core/etl/src/Flow/ETL/Extractor/File/DerivedSchema.php b/src/core/etl/src/Flow/ETL/Extractor/File/DerivedSchema.php new file mode 100644 index 0000000000..12a34851d0 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/File/DerivedSchema.php @@ -0,0 +1,35 @@ +validate($this->derived, $schema); + + if (!$validation->isValid()) { + throw InferredSchemaException::filesDiverge($source, $this->derivedFrom, $validation); + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Extractor/File/FileBatches.php b/src/core/etl/src/Flow/ETL/Extractor/File/FileBatches.php new file mode 100644 index 0000000000..6e33736842 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/File/FileBatches.php @@ -0,0 +1,38 @@ + $batchSize + * + * @return Generator + */ + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator; +} diff --git a/src/core/etl/src/Flow/ETL/Extractor/FileColumns.php b/src/core/etl/src/Flow/ETL/Extractor/File/FileColumns.php similarity index 88% rename from src/core/etl/src/Flow/ETL/Extractor/FileColumns.php rename to src/core/etl/src/Flow/ETL/Extractor/File/FileColumns.php index 9d86a02afb..96f1aca713 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FileColumns.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/FileColumns.php @@ -2,10 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Filesystem\Partition; use Throwable; @@ -31,11 +30,6 @@ public function __construct( private bool $metadataColumns, ) {} - public function apply(Rows $rows): Rows - { - return $this->partitionColumns->apply($rows, $this->partitionNames, $this->partitionTypes); - } - public function declare(Schema $schema): Schema { return $this->partitionColumns->declare( @@ -94,12 +88,7 @@ public function forFile(SourceFile $source, Schema $declared): FileConstants } } - return new FileConstants( - $this->partitionColumns, - $this->metadataColumns ? $source->uri() : null, - $this->partitionNames, - $values, - ); + return new FileConstants($this->metadataColumns ? $source->uri() : null, $this->partitionNames, $values); } /** diff --git a/src/core/etl/src/Flow/ETL/Extractor/File/FileConstants.php b/src/core/etl/src/Flow/ETL/Extractor/File/FileConstants.php new file mode 100644 index 0000000000..b9a5bb8462 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/File/FileConstants.php @@ -0,0 +1,62 @@ + $partitionNames + * @param array $partitionValues already the type the declared schema gives them + */ + public function __construct( + private ?string $uri, + private array $partitionNames, + private array $partitionValues, + ) {} + + /** + * The file's value of every column this file adds - `_input_file_uri` when metadata columns are on, then each + * partition column (null when the path does not carry it). + * + * @return array + */ + public function values(): array + { + $values = $this->uri === null ? [] : ['_input_file_uri' => $this->uri]; + + foreach ($this->partitionNames as $name => $_) { + $values[$name] = array_key_exists($name, $this->partitionValues) ? $this->partitionValues[$name] : null; + } + + return $values; + } + + /** + * values() over a batch the reader already matched to the file's body schema, adopting $declared - the schema + * FileColumns::declare() built over that body schema. A batch with nothing to add is returned as it is. + */ + public function fillRows(Rows $rows, Schema $declared, Backend $backend): Rows + { + if ($this->uri === null && $this->partitionNames === []) { + return $rows; + } + + $added = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($this->values() as $name => $value) { + $added[$name] = $backend->constant($declared->get($name), $value, $rows->count()); + } + + return $rows->withColumns($declared, $added); + } +} diff --git a/src/core/etl/src/Flow/ETL/Extractor/FileExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/File/FileExtractor.php similarity index 95% rename from src/core/etl/src/Flow/ETL/Extractor/FileExtractor.php rename to src/core/etl/src/Flow/ETL/Extractor/File/FileExtractor.php index a86f5ded4a..f8b5369cc0 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FileExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/FileExtractor.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; use Flow\ETL\Extractor; +use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; use Flow\ETL\Rows; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Extractor/File/FileReadLoop.php b/src/core/etl/src/Flow/ETL/Extractor/File/FileReadLoop.php new file mode 100644 index 0000000000..3375c2b4d1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/File/FileReadLoop.php @@ -0,0 +1,86 @@ + $sources + * @param int<1, max> $batchSize + * + * @return Generator + */ + public function read( + array $sources, + FileBatches $batches, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $body = $this->fileColumns->withoutTail($this->schema); + $offset = $window->offset; + $skips = $batches instanceof OffsetSkippingFileBatches; + $yielded = 0; + + foreach ($sources as $source) { + $constants = $this->fileColumns->forFile($source, $this->schema); + $wanted = $window->limit === null ? null : $window->limit - $yielded; + $file = $batches->batches( + $source, + $body, + $batchSize, + $backend, + // a format that cannot skip has to produce the offset it leaves to the loop before the rows wanted + $skips + ? new ReadWindow($offset, $wanted) + : new ReadWindow(0, $wanted === null ? null : $wanted + $offset), + ); + + foreach ($file as $batch) { + if (!$skips && $offset > 0) { + $skipped = min($offset, $batch->count()); + $offset -= $skipped; + + if ($skipped === $batch->count()) { + continue; + } + + $batch = $batch->slice($skipped, $batch->count() - $skipped); + } + + if ($window->limit !== null && $batch->count() > ($window->limit - $yielded)) { + $batch = $batch->slice(0, $window->limit - $yielded); + } + + $rows = $constants->fillRows($batch, $this->schema, $backend); + $yielded += $rows->count(); + $signal = yield $rows; + + if ($signal === Signal::STOP) { + return; + } + + if ($window->limit !== null && $yielded >= $window->limit) { + return; + } + } + + $offset -= $file->getReturn(); + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Extractor/FileReading.php b/src/core/etl/src/Flow/ETL/Extractor/File/FileReading.php similarity index 96% rename from src/core/etl/src/Flow/ETL/Extractor/FileReading.php rename to src/core/etl/src/Flow/ETL/Extractor/File/FileReading.php index bd57eb3735..361e85a034 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FileReading.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/FileReading.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; use Flow\Filesystem\FileListing; use Flow\Filesystem\Filesystem; diff --git a/src/core/etl/src/Flow/ETL/Extractor/FooterStatistics.php b/src/core/etl/src/Flow/ETL/Extractor/File/FooterStatistics.php similarity index 96% rename from src/core/etl/src/Flow/ETL/Extractor/FooterStatistics.php rename to src/core/etl/src/Flow/ETL/Extractor/File/FooterStatistics.php index ecfb822ab0..cfa7a287d3 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FooterStatistics.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/FooterStatistics.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Extractor\Statistics; use function max; use function round; diff --git a/src/core/etl/src/Flow/ETL/Extractor/File/InferredColumns.php b/src/core/etl/src/Flow/ETL/Extractor/File/InferredColumns.php new file mode 100644 index 0000000000..f4117cca6f --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/File/InferredColumns.php @@ -0,0 +1,54 @@ + $tail the file constant columns, never part of a file's own columns + * @param string $inferredFrom the source the inferred header was read from + */ + public function __construct( + private Schema $inferred, + private array $tail, + private SchemaInference $inference, + private string $inferredFrom, + ) {} + + /** + * Refuses a file whose own columns (header) are not the inferred ones; a file with no columns passes. + * + * @param list $columns the file's columns, constant columns and duplicates allowed + * + * @throws InferredSchemaException + */ + public function refuseDivergence(string $source, array $columns): void + { + $expected = $this->inferred->references()->names(); + $columns = array_values(array_diff(array_unique($columns), $this->tail)); + + if ($columns !== [] && (array_diff($columns, $expected) !== [] || array_diff($expected, $columns) !== [])) { + throw InferredSchemaException::columnsDiverge( + $source, + $this->inferredFrom, + $this->inferred, + $columns, + $this->inference, + ); + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Extractor/ListedFiles.php b/src/core/etl/src/Flow/ETL/Extractor/File/ListedFiles.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Extractor/ListedFiles.php rename to src/core/etl/src/Flow/ETL/Extractor/File/ListedFiles.php index c6c7c6e9bd..2b5c0b3733 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/ListedFiles.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/ListedFiles.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/src/Flow/ETL/Extractor/ListingPartitions.php b/src/core/etl/src/Flow/ETL/Extractor/File/ListingPartitions.php similarity index 95% rename from src/core/etl/src/Flow/ETL/Extractor/ListingPartitions.php rename to src/core/etl/src/Flow/ETL/Extractor/File/ListingPartitions.php index 5bd6f8eabb..a52430dd9e 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/ListingPartitions.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/ListingPartitions.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; diff --git a/src/core/etl/src/Flow/ETL/Extractor/MetadataColumns.php b/src/core/etl/src/Flow/ETL/Extractor/File/MetadataColumns.php similarity index 88% rename from src/core/etl/src/Flow/ETL/Extractor/MetadataColumns.php rename to src/core/etl/src/Flow/ETL/Extractor/File/MetadataColumns.php index de3a9247fe..6d77ae383d 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/MetadataColumns.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/MetadataColumns.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; trait MetadataColumns { diff --git a/src/core/etl/src/Flow/ETL/Extractor/MetadataColumnsExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/File/MetadataColumnsExtractor.php similarity index 80% rename from src/core/etl/src/Flow/ETL/Extractor/MetadataColumnsExtractor.php rename to src/core/etl/src/Flow/ETL/Extractor/File/MetadataColumnsExtractor.php index e93259fd0a..891f0ec6dc 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/MetadataColumnsExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/MetadataColumnsExtractor.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; interface MetadataColumnsExtractor { diff --git a/src/core/etl/src/Flow/ETL/Extractor/File/OffsetSkippingFileBatches.php b/src/core/etl/src/Flow/ETL/Extractor/File/OffsetSkippingFileBatches.php new file mode 100644 index 0000000000..90fd4375a1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/File/OffsetSkippingFileBatches.php @@ -0,0 +1,11 @@ +gracefulRemove(...array_keys($names))->add(...$definitions); } - - /** - * @param array $names - */ - public function apply(Rows $rows, array $names, PartitionTypes $types = new PartitionTypes()): Rows - { - $types->assertEveryNameIsAPartition($names); - - if ($names === []) { - return $rows; - } - - $definitions = []; - - foreach ($names as $name => $nullable) { - $definitions[] = $types->has($name) - ? definition_from_type($name, $types->get($name), nullable: $nullable) - : str_schema($name, nullable: $nullable); - } - - return $rows->matchTo($rows->schema()->gracefulRemove(...array_keys($names))->add(...$definitions)); - } - - /** - * @param array $names - * @param array $values partition name => value, for the path this row came from - * @param array $row - * - * @return array - */ - public function fill(array $row, array $names, array $values): array - { - foreach ($names as $name => $_) { - unset($row[$name]); - $row[$name] = array_key_exists($name, $values) ? $values[$name] : null; - } - - return $row; - } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/PartitionTypes.php b/src/core/etl/src/Flow/ETL/Extractor/File/PartitionTypes.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Extractor/PartitionTypes.php rename to src/core/etl/src/Flow/ETL/Extractor/File/PartitionTypes.php index ddd4bcf8cb..fee4ac9b32 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/PartitionTypes.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/PartitionTypes.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; use Flow\ETL\Exception\InvalidArgumentException; use Flow\Types\Type; diff --git a/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php b/src/core/etl/src/Flow/ETL/Extractor/File/PathFiltering.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php rename to src/core/etl/src/Flow/ETL/Extractor/File/PathFiltering.php index 866d872cf0..88db0dea72 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/PathFiltering.php +++ b/src/core/etl/src/Flow/ETL/Extractor/File/PathFiltering.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\File; use Flow\ETL\Cardinality; +use Flow\ETL\Extractor\Statistics; use Flow\ETL\Schema; use Flow\Filesystem\Path; use Flow\Filesystem\Path\Filter\OnlyFiles; diff --git a/src/core/etl/src/Flow/ETL/Extractor/File/ReadWindow.php b/src/core/etl/src/Flow/ETL/Extractor/File/ReadWindow.php new file mode 100644 index 0000000000..61b531ae5e --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/File/ReadWindow.php @@ -0,0 +1,29 @@ + $partitionNames - * @param array $partitionValues already the type the declared schema gives them - */ - public function __construct( - private PartitionColumns $partitionColumns, - private ?string $uri, - private array $partitionNames, - private array $partitionValues, - ) {} - - /** - * @param array $row - * - * @return array - */ - public function fill(array $row): array - { - // plain assignment, unlike the partition columns below: a body column named _input_file_uri - // keeps its position and is overwritten in place - if ($this->uri !== null) { - $row['_input_file_uri'] = $this->uri; - } - - return $this->partitionColumns->fill($row, $this->partitionNames, $this->partitionValues); - } - - /** - * fill() over a batch the reader already matched to the file's body schema, adopting $declared - the schema - * FileColumns::declare() built over that body schema. A batch with nothing to add is returned as it is. - */ - public function fillRows(Rows $rows, Schema $declared, Backend $backend): Rows - { - if ($this->uri === null && $this->partitionNames === []) { - return $rows; - } - - $added = []; - - if ($this->uri !== null) { - $added['_input_file_uri'] = $backend->constant( - $declared->get('_input_file_uri'), - $this->uri, - $rows->count(), - ); - } - - foreach ($this->partitionNames as $name => $_) { - $added[$name] = $backend->constant( - $declared->get($name), - array_key_exists($name, $this->partitionValues) ? $this->partitionValues[$name] : null, - $rows->count(), - ); - } - - return $rows->withColumns($declared, $added); - } -} diff --git a/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php index 30e920a768..41295a8a14 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/FilesExtractor.php @@ -7,7 +7,12 @@ use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\ListedFiles; +use Flow\ETL\Extractor\File\ListingPartitions; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\FlowContext; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\Filesystem\FileListing; use Flow\Filesystem\Filesystem; @@ -17,8 +22,6 @@ use Flow\Filesystem\Path\Filter\OnlyFiles; use Generator; -use function count; -use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -63,16 +66,16 @@ public function isRepeatable(): bool public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $batchSize = $this->batchSize(); + $backend = $context->backend(); $fileColumns = $this->fileColumns($this->filesystem, $this->path); $schema = $this->schema(); - $buffer = []; + $builder = new RowsBuilder($schema, $backend); $yielded = 0; foreach ((new FileListing($this->filesystem))->list($this->path, $pathFilter) as $fileStatus) { - $constants = $fileColumns->forFile(new SourceFile($fileStatus->path, $fileStatus->size), $schema); $extension = $fileStatus->path->extension(); - $buffer[] = $constants->fill([ + $builder->append([ 'path' => $fileStatus->path->path(), 'protocol' => $fileStatus->path->protocol(), 'file_name' => $fileStatus->path->filename(), @@ -82,29 +85,31 @@ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFi // 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, + ...$fileColumns->forFile(new SourceFile($fileStatus->path, $fileStatus->size), $schema)->values(), ]); - if (count($buffer) < $batchSize) { + if ($builder->count() < $batchSize) { continue; } - $yielded += count($buffer); + $rows = $builder->finish(); + $yielded += $rows->count(); - $signal = yield array_to_rows($buffer, $schema, $context->backend()); + $signal = yield $rows; if ($signal === Signal::STOP) { return; } - $buffer = []; + $builder = new RowsBuilder($schema, $backend); if ($limit !== null && $yielded >= $limit) { return; } } - if ($buffer !== []) { - yield array_to_rows($buffer, $schema, $context->backend()); + if ($builder->count() > 0) { + yield $builder->finish(); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/Grid/HeaderNames.php b/src/core/etl/src/Flow/ETL/Extractor/Grid/HeaderNames.php new file mode 100644 index 0000000000..aef355d841 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/Grid/HeaderNames.php @@ -0,0 +1,34 @@ + $cells + * + * @return list + */ + public function of(array $cells): array + { + $names = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($cells as $index => $cell) { + $name = trim(is_scalar($cell) ? (string) $cell : ''); + $names[] = $name !== '' ? $name : 'e' . str_pad((string) $index, 2, '0', STR_PAD_LEFT); + } + + return $names; + } +} diff --git a/src/core/etl/src/Flow/ETL/Extractor/Grid/RecordDecoder.php b/src/core/etl/src/Flow/ETL/Extractor/Grid/RecordDecoder.php new file mode 100644 index 0000000000..b02c610d2f --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Extractor/Grid/RecordDecoder.php @@ -0,0 +1,89 @@ + + */ + private ?array $headers = null; + + public function __construct( + private readonly bool $withHeader, + private readonly bool $emptyToNull, + private readonly bool $dropExtraColumns = true, + ) {} + + /** + * Records before the header is resolved that hold no cell are skipped. A cell a record lacks is null; a present + * '' cell is null under emptyToNull. + * + * @param list> $batch + * + * @throws InvalidArgumentException a record with more cells than headers, unless extra columns are dropped + * + * @return list> + */ + public function decode(array $batch): array + { + $decoded = []; + + foreach ($batch as $record) { + $cells = array_values($record); + + if ($this->headers === null) { + if ($cells === []) { + continue; + } + + $this->headers = (new HeaderNames())->of( + $this->withHeader ? $cells : array_fill(0, count($cells), null), + ); + + if ($this->withHeader) { + continue; + } + } + + if (!$this->dropExtraColumns && count($cells) > count($this->headers)) { + throw InvalidArgumentException::because( + 'Row has more columns (%d) than headers (%d)', + count($cells), + count($this->headers), + ); + } + + $values = []; + + foreach ($this->headers as $index => $name) { + // @mago-ignore analysis:mixed-assignment + $cell = $cells[$index] ?? null; + $values[$name] = $this->emptyToNull && $cell === '' ? null : $cell; + } + + $decoded[] = $values; + } + + return $decoded; + } + + /** + * @return null|list null before the first decode() resolved them + */ + public function headers(): ?array + { + return $this->headers; + } +} diff --git a/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php b/src/core/etl/src/Flow/ETL/Extractor/Memory/InMemoryRows.php similarity index 97% rename from src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php rename to src/core/etl/src/Flow/ETL/Extractor/Memory/InMemoryRows.php index 8c442232a9..64b1ba9103 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/InMemoryRows.php +++ b/src/core/etl/src/Flow/ETL/Extractor/Memory/InMemoryRows.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\Memory; use Flow\ETL\Row\ColumnName; use Flow\ETL\Schema\Inference\SchemaSampler; diff --git a/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php b/src/core/etl/src/Flow/ETL/Extractor/Memory/InferredRows.php similarity index 87% rename from src/core/etl/src/Flow/ETL/Extractor/InferredRows.php rename to src/core/etl/src/Flow/ETL/Extractor/Memory/InferredRows.php index 08faa59cf4..159ff6919f 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/InferredRows.php +++ b/src/core/etl/src/Flow/ETL/Extractor/Memory/InferredRows.php @@ -2,18 +2,17 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\Memory; use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Row\DeclaredColumns; use Flow\ETL\Rows; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\SchemaInference; use function count; -use function Flow\ETL\DSL\array_to_rows; /** * The gate places a refused row in its batch; only the source knows where that batch started, so a row past a @@ -39,7 +38,9 @@ public function __construct( public function of(array $rows, Schema $schema, Backend $backend): Rows { try { - $batch = array_to_rows((new DeclaredColumns())->project($rows, $schema), $schema, $backend); + $batch = (new RowsBuilder($schema, $backend)) + ->appendProjected($rows) + ->finish(); } catch (SchemaMismatchException $mismatch) { $row = $this->offset + $mismatch->rowIndex; diff --git a/src/core/etl/src/Flow/ETL/Extractor/SpillState.php b/src/core/etl/src/Flow/ETL/Extractor/Memory/SpillState.php similarity index 92% rename from src/core/etl/src/Flow/ETL/Extractor/SpillState.php rename to src/core/etl/src/Flow/ETL/Extractor/Memory/SpillState.php index 129b952cdc..9a36a8c6d4 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/SpillState.php +++ b/src/core/etl/src/Flow/ETL/Extractor/Memory/SpillState.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\Memory; /** * The lifecycle of one SpilledRows. Split into states rather than carried as booleans because the diff --git a/src/core/etl/src/Flow/ETL/Extractor/SpilledRows.php b/src/core/etl/src/Flow/ETL/Extractor/Memory/SpilledRows.php similarity index 99% rename from src/core/etl/src/Flow/ETL/Extractor/SpilledRows.php rename to src/core/etl/src/Flow/ETL/Extractor/Memory/SpilledRows.php index 4a5c9bba22..b4562a732d 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/SpilledRows.php +++ b/src/core/etl/src/Flow/ETL/Extractor/Memory/SpilledRows.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Extractor; +namespace Flow\ETL\Extractor\Memory; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Schema\Inference\SchemaSampler; diff --git a/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php index cf23c8822c..1161a8b1a1 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/MemoryExtractor.php @@ -5,6 +5,8 @@ namespace Flow\ETL\Extractor; use Flow\ETL\Extractor; +use Flow\ETL\Extractor\Memory\InferredRows; +use Flow\ETL\Extractor\Memory\InMemoryRows; use Flow\ETL\FlowContext; use Flow\ETL\Memory\Memory; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php index b68aff1262..d9a9fd0220 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/PathPartitionsExtractor.php @@ -7,7 +7,11 @@ use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\ListingPartitions; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\FlowContext; +use Flow\ETL\Rows\RowsBuilder; use Flow\ETL\Schema; use Flow\Filesystem\FileListing; use Flow\Filesystem\Filesystem; @@ -21,8 +25,6 @@ use function array_map; use function array_merge; use function array_values; -use function count; -use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\map_schema; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\str_schema; @@ -70,41 +72,43 @@ public function isRepeatable(): bool public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { $batchSize = $this->batchSize(); + $backend = $context->backend(); $fileColumns = $this->fileColumns($this->filesystem, $this->path); $schema = $this->schema(); - $buffer = []; + $builder = new RowsBuilder($schema, $backend); $yielded = 0; foreach ((new FileListing($this->filesystem))->list($this->path, $pathFilter) as $fileStatus) { - $constants = $fileColumns->forFile(new SourceFile($fileStatus->path, $fileStatus->size), $schema); - $buffer[] = $constants->fill([ + $builder->append([ 'path' => $fileStatus->path->uri(), 'partitions' => array_merge(...array_values(array_map(static fn(Partition $p) => [ $p->name => $p->value, ], $fileStatus->path->partitions()->toArray()))), + ...$fileColumns->forFile(new SourceFile($fileStatus->path, $fileStatus->size), $schema)->values(), ]); - if (count($buffer) < $batchSize) { + if ($builder->count() < $batchSize) { continue; } - $yielded += count($buffer); + $rows = $builder->finish(); + $yielded += $rows->count(); - $signal = yield array_to_rows($buffer, $schema, $context->backend()); + $signal = yield $rows; if ($signal === Signal::STOP) { return; } - $buffer = []; + $builder = new RowsBuilder($schema, $backend); if ($limit !== null && $yielded >= $limit) { return; } } - if ($buffer !== []) { - yield array_to_rows($buffer, $schema, $context->backend()); + if ($builder->count() > 0) { + yield $builder->finish(); } } diff --git a/src/core/etl/src/Flow/ETL/Extractor/RowsExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/RowsExtractor.php index a21dcb9dd2..89d1539c66 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/RowsExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/RowsExtractor.php @@ -40,7 +40,7 @@ public function extract(FlowContext $context, ?int $limit = null): Generator $schema = $this->schema(); foreach ($this->rows as $rows) { - $signal = yield $rows->matchTo($schema); + $signal = yield $rows->matchTo($schema, $context->backend()); if ($signal === Signal::STOP) { return; diff --git a/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php b/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php index 0567a7672e..4ef18782bf 100644 --- a/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php +++ b/src/core/etl/src/Flow/ETL/Extractor/SequenceExtractor.php @@ -5,6 +5,8 @@ namespace Flow\ETL\Extractor; use Flow\ETL\Extractor; +use Flow\ETL\Extractor\Memory\InferredRows; +use Flow\ETL\Extractor\Memory\InMemoryRows; use Flow\ETL\Extractor\SequenceGenerator\SequenceGenerator; use Flow\ETL\FlowContext; use Flow\ETL\Rows; diff --git a/src/core/etl/src/Flow/ETL/Function/All.php b/src/core/etl/src/Flow/ETL/Function/All.php index bb7251ad8a..30ee225ae9 100644 --- a/src/core/etl/src/Flow/ETL/Function/All.php +++ b/src/core/etl/src/Flow/ETL/Function/All.php @@ -119,7 +119,7 @@ public function eval(Rows $rows, FlowContext $context): Column $ordered[] = $results[$i]; } - return (new ResultColumn())->of($this, $ordered); + return (new ResultColumn($context->backend()))->of($this, $ordered); } public function or(ScalarFunction $scalarFunction): Any diff --git a/src/core/etl/src/Flow/ETL/Function/Any.php b/src/core/etl/src/Flow/ETL/Function/Any.php index a772ee85f9..0aa8cefbaa 100644 --- a/src/core/etl/src/Flow/ETL/Function/Any.php +++ b/src/core/etl/src/Flow/ETL/Function/Any.php @@ -119,7 +119,7 @@ public function eval(Rows $rows, FlowContext $context): Column $ordered[] = $results[$i]; } - return (new ResultColumn())->of($this, $ordered); + return (new ResultColumn($context->backend()))->of($this, $ordered); } public function or(ScalarFunction $scalarFunction): self diff --git a/src/core/etl/src/Flow/ETL/Function/Append.php b/src/core/etl/src/Flow/ETL/Function/Append.php index 753806cce8..4efca1292f 100644 --- a/src/core/etl/src/Flow/ETL/Function/Append.php +++ b/src/core/etl/src/Flow/ETL/Function/Append.php @@ -82,6 +82,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayExpand.php b/src/core/etl/src/Flow/ETL/Function/ArrayExpand.php index 1a2c886150..f0c37015bf 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayExpand.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayExpand.php @@ -105,6 +105,6 @@ public function eval(Rows $rows, FlowContext $context): Column }; } - return (new ResultColumn())->lists($this, $lists); + return (new ResultColumn($context->backend()))->lists($this, $lists); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayFilter.php b/src/core/etl/src/Flow/ETL/Function/ArrayFilter.php index f170e852ef..7163bd84ab 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayFilter.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayFilter.php @@ -89,6 +89,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayGet.php b/src/core/etl/src/Flow/ETL/Function/ArrayGet.php index f972f2f63c..bd2cd9155b 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayGet.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayGet.php @@ -134,6 +134,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayGetCollection.php b/src/core/etl/src/Flow/ETL/Function/ArrayGetCollection.php index a3a3ec4dcb..9fb6bf8e70 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayGetCollection.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayGetCollection.php @@ -155,6 +155,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayKeep.php b/src/core/etl/src/Flow/ETL/Function/ArrayKeep.php index f88c035e51..4dc931c48d 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayKeep.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayKeep.php @@ -89,6 +89,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayKeyRename.php b/src/core/etl/src/Flow/ETL/Function/ArrayKeyRename.php index caa5c4ddfe..80cb9b64ce 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayKeyRename.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayKeyRename.php @@ -69,6 +69,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayKeys.php b/src/core/etl/src/Flow/ETL/Function/ArrayKeys.php index 0563e6dcbb..2e43de00b6 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayKeys.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayKeys.php @@ -92,6 +92,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayKeysStyleConvert.php b/src/core/etl/src/Flow/ETL/Function/ArrayKeysStyleConvert.php index c3774d7427..76562e43af 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayKeysStyleConvert.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayKeysStyleConvert.php @@ -143,6 +143,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayMerge.php b/src/core/etl/src/Flow/ETL/Function/ArrayMerge.php index 4d7950d0c2..0cdc4186ba 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayMerge.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayMerge.php @@ -100,6 +100,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayMergeCollection.php b/src/core/etl/src/Flow/ETL/Function/ArrayMergeCollection.php index 08ef36d891..211af046c6 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayMergeCollection.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayMergeCollection.php @@ -115,6 +115,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayPathExists.php b/src/core/etl/src/Flow/ETL/Function/ArrayPathExists.php index 31d23ae164..a36ad8566b 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayPathExists.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayPathExists.php @@ -96,6 +96,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayReverse.php b/src/core/etl/src/Flow/ETL/Function/ArrayReverse.php index 6fad2cf0c9..c84ef64c11 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayReverse.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayReverse.php @@ -84,6 +84,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ArraySort.php b/src/core/etl/src/Flow/ETL/Function/ArraySort.php index 342bb4ca6c..5c3d6efc17 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArraySort.php +++ b/src/core/etl/src/Flow/ETL/Function/ArraySort.php @@ -115,7 +115,7 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } /** diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayUnpack.php b/src/core/etl/src/Flow/ETL/Function/ArrayUnpack.php index 0484074977..a7d0f21b42 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayUnpack.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayUnpack.php @@ -62,7 +62,7 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } /** diff --git a/src/core/etl/src/Flow/ETL/Function/ArrayValues.php b/src/core/etl/src/Flow/ETL/Function/ArrayValues.php index cee1daea1b..07bc1cec19 100644 --- a/src/core/etl/src/Flow/ETL/Function/ArrayValues.php +++ b/src/core/etl/src/Flow/ETL/Function/ArrayValues.php @@ -89,6 +89,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Ascii.php b/src/core/etl/src/Flow/ETL/Function/Ascii.php index 74ce671670..9a22561f53 100644 --- a/src/core/etl/src/Flow/ETL/Function/Ascii.php +++ b/src/core/etl/src/Flow/ETL/Function/Ascii.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Between.php b/src/core/etl/src/Flow/ETL/Function/Between.php index d2c01dadc1..29b09dbfd4 100644 --- a/src/core/etl/src/Flow/ETL/Function/Between.php +++ b/src/core/etl/src/Flow/ETL/Function/Between.php @@ -102,6 +102,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/BinaryLength.php b/src/core/etl/src/Flow/ETL/Function/BinaryLength.php index e63adf64fb..163fe989b9 100644 --- a/src/core/etl/src/Flow/ETL/Function/BinaryLength.php +++ b/src/core/etl/src/Flow/ETL/Function/BinaryLength.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php b/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php index 5dd7075ce4..ca3e20e57c 100644 --- a/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php +++ b/src/core/etl/src/Flow/ETL/Function/CallUserFunc.php @@ -122,6 +122,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Capitalize.php b/src/core/etl/src/Flow/ETL/Function/Capitalize.php index 8892f7fa09..b514286a1b 100644 --- a/src/core/etl/src/Flow/ETL/Function/Capitalize.php +++ b/src/core/etl/src/Flow/ETL/Function/Capitalize.php @@ -83,6 +83,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Cast.php b/src/core/etl/src/Flow/ETL/Function/Cast.php index a288d3fe0a..9a20cdc757 100644 --- a/src/core/etl/src/Flow/ETL/Function/Cast.php +++ b/src/core/etl/src/Flow/ETL/Function/Cast.php @@ -7,7 +7,7 @@ use DateTimeInterface; use Exception; use Flow\ETL\Column\Column; -use Flow\ETL\Column\Php\XmlDocumentPhysical; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; use Flow\ETL\Column\TextValues; use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; @@ -113,7 +113,7 @@ public function eval(Rows $rows, FlowContext $context): Column ); } - return (new ResultColumn())->of($this, (new TextValues())->dateTimes( + return (new ResultColumn($context->backend()))->of($this, (new TextValues())->dateTimes( $type, $physicals, DateTimeInterface::RFC3339, @@ -151,6 +151,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Chunk.php b/src/core/etl/src/Flow/ETL/Function/Chunk.php index 07b2055312..b61f84160c 100644 --- a/src/core/etl/src/Flow/ETL/Function/Chunk.php +++ b/src/core/etl/src/Flow/ETL/Function/Chunk.php @@ -87,6 +87,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Coalesce.php b/src/core/etl/src/Flow/ETL/Function/Coalesce.php index 598ae8576f..973bc9daa2 100644 --- a/src/core/etl/src/Flow/ETL/Function/Coalesce.php +++ b/src/core/etl/src/Flow/ETL/Function/Coalesce.php @@ -98,6 +98,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $values[$i] ?? null; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/CodePointLength.php b/src/core/etl/src/Flow/ETL/Function/CodePointLength.php index 63ff7fea5f..bb5bb9f3a2 100644 --- a/src/core/etl/src/Flow/ETL/Function/CodePointLength.php +++ b/src/core/etl/src/Flow/ETL/Function/CodePointLength.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/CollapseWhitespace.php b/src/core/etl/src/Flow/ETL/Function/CollapseWhitespace.php index c9a28a04ed..a5c69eb708 100644 --- a/src/core/etl/src/Flow/ETL/Function/CollapseWhitespace.php +++ b/src/core/etl/src/Flow/ETL/Function/CollapseWhitespace.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Combine.php b/src/core/etl/src/Flow/ETL/Function/Combine.php index 9cc5ebfe4f..2abb530a7e 100644 --- a/src/core/etl/src/Flow/ETL/Function/Combine.php +++ b/src/core/etl/src/Flow/ETL/Function/Combine.php @@ -118,6 +118,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Concat.php b/src/core/etl/src/Flow/ETL/Function/Concat.php index 05f2c3447c..433e2d45f4 100644 --- a/src/core/etl/src/Flow/ETL/Function/Concat.php +++ b/src/core/etl/src/Flow/ETL/Function/Concat.php @@ -88,6 +88,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ConcatWithSeparator.php b/src/core/etl/src/Flow/ETL/Function/ConcatWithSeparator.php index 7ce0740596..204e347fdc 100644 --- a/src/core/etl/src/Flow/ETL/Function/ConcatWithSeparator.php +++ b/src/core/etl/src/Flow/ETL/Function/ConcatWithSeparator.php @@ -106,6 +106,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Contains.php b/src/core/etl/src/Flow/ETL/Function/Contains.php index c7bc47b20b..e7a926de31 100644 --- a/src/core/etl/src/Flow/ETL/Function/Contains.php +++ b/src/core/etl/src/Flow/ETL/Function/Contains.php @@ -88,6 +88,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementAttributeValue.php b/src/core/etl/src/Flow/ETL/Function/DOMElementAttributeValue.php index 8a54a74512..c269fbfa3f 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementAttributeValue.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementAttributeValue.php @@ -129,6 +129,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementAttributesCount.php b/src/core/etl/src/Flow/ETL/Function/DOMElementAttributesCount.php index 0201f41256..ad48955c94 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementAttributesCount.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementAttributesCount.php @@ -83,6 +83,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementNamespaceValue.php b/src/core/etl/src/Flow/ETL/Function/DOMElementNamespaceValue.php index 188031376a..98e34bf146 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementNamespaceValue.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementNamespaceValue.php @@ -94,7 +94,7 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } /** diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementNextSibling.php b/src/core/etl/src/Flow/ETL/Function/DOMElementNextSibling.php index 6df9b508f7..97d9f5bacd 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementNextSibling.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementNextSibling.php @@ -96,6 +96,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementParent.php b/src/core/etl/src/Flow/ETL/Function/DOMElementParent.php index 2f0b4c238b..8815ebd412 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementParent.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementParent.php @@ -96,6 +96,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementPreviousSibling.php b/src/core/etl/src/Flow/ETL/Function/DOMElementPreviousSibling.php index 64a0b0ae33..478284313e 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementPreviousSibling.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementPreviousSibling.php @@ -96,6 +96,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DOMElementValue.php b/src/core/etl/src/Flow/ETL/Function/DOMElementValue.php index f1b34f3bf4..7015fba879 100644 --- a/src/core/etl/src/Flow/ETL/Function/DOMElementValue.php +++ b/src/core/etl/src/Flow/ETL/Function/DOMElementValue.php @@ -108,6 +108,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/DateTimeFormat.php b/src/core/etl/src/Flow/ETL/Function/DateTimeFormat.php index 26c22b245d..855b131510 100644 --- a/src/core/etl/src/Flow/ETL/Function/DateTimeFormat.php +++ b/src/core/etl/src/Flow/ETL/Function/DateTimeFormat.php @@ -81,7 +81,11 @@ public function eval(Rows $rows, FlowContext $context): Column ); } - return (new ResultColumn())->of($this, (new TextValues())->dateTimes($type, $physicals, $format)); + return (new ResultColumn($context->backend()))->of($this, (new TextValues())->dateTimes( + $type, + $physicals, + $format, + )); } } @@ -104,6 +108,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Divide.php b/src/core/etl/src/Flow/ETL/Function/Divide.php index 79739e1a7b..37c01c26b4 100644 --- a/src/core/etl/src/Flow/ETL/Function/Divide.php +++ b/src/core/etl/src/Flow/ETL/Function/Divide.php @@ -91,6 +91,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EndsWith.php b/src/core/etl/src/Flow/ETL/Function/EndsWith.php index f99110cb78..3b2fb9066c 100644 --- a/src/core/etl/src/Flow/ETL/Function/EndsWith.php +++ b/src/core/etl/src/Flow/ETL/Function/EndsWith.php @@ -78,6 +78,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EnsureEnd.php b/src/core/etl/src/Flow/ETL/Function/EnsureEnd.php index 66e0689792..d95ce27100 100644 --- a/src/core/etl/src/Flow/ETL/Function/EnsureEnd.php +++ b/src/core/etl/src/Flow/ETL/Function/EnsureEnd.php @@ -82,6 +82,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EnsureStart.php b/src/core/etl/src/Flow/ETL/Function/EnsureStart.php index 4e09853e59..6568e62336 100644 --- a/src/core/etl/src/Flow/ETL/Function/EnsureStart.php +++ b/src/core/etl/src/Flow/ETL/Function/EnsureStart.php @@ -82,6 +82,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EnumName.php b/src/core/etl/src/Flow/ETL/Function/EnumName.php index bc3b44b209..7336ef8421 100644 --- a/src/core/etl/src/Flow/ETL/Function/EnumName.php +++ b/src/core/etl/src/Flow/ETL/Function/EnumName.php @@ -72,6 +72,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/EnumValue.php b/src/core/etl/src/Flow/ETL/Function/EnumValue.php index 29c7c2aee1..56ef1af74f 100644 --- a/src/core/etl/src/Flow/ETL/Function/EnumValue.php +++ b/src/core/etl/src/Flow/ETL/Function/EnumValue.php @@ -88,6 +88,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Equals.php b/src/core/etl/src/Flow/ETL/Function/Equals.php index 3f4ef5eb54..16f3ab93ab 100644 --- a/src/core/etl/src/Flow/ETL/Function/Equals.php +++ b/src/core/etl/src/Flow/ETL/Function/Equals.php @@ -81,7 +81,7 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $left === null || $rights[$i] === null ? null : $left === $rights[$i]; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } try { @@ -112,6 +112,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Evaluation/ResultColumn.php b/src/core/etl/src/Flow/ETL/Function/Evaluation/ResultColumn.php index 9d1bc4b9c7..456e4ee78e 100644 --- a/src/core/etl/src/Flow/ETL/Function/Evaluation/ResultColumn.php +++ b/src/core/etl/src/Flow/ETL/Function/Evaluation/ResultColumn.php @@ -4,12 +4,10 @@ namespace Flow\ETL\Function\Evaluation; +use Flow\ETL\Column\Backend; use Flow\ETL\Column\Column; -use Flow\ETL\Column\Php\IdentityPhysical; -use Flow\ETL\Column\Php\PhysicalFor; -use Flow\ETL\Column\Php\ScalarColumn; -use Flow\ETL\Column\Php\ValueColumn; -use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\Physical\PhysicalFor; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Function\ScalarFunction; use Flow\Types\Type; use Flow\Types\Type\Logical\HTMLElementType; @@ -35,6 +33,10 @@ final readonly class ResultColumn { + public function __construct( + private Backend $backend, + ) {} + /** * The `list` column of an ExpandResults function: one list per row. * @@ -145,7 +147,10 @@ public function typed(Type $type, array $values): Column } if ($native !== null) { - return new ScalarColumn($bare, new IdentityPhysical(), $values, $nulls); + $builder = $this->backend->builder(definition_from_type('value', $type)); + $builder->appendPhysicals($values, $nulls); + + return $builder->finish(); } } @@ -153,7 +158,7 @@ public function typed(Type $type, array $values): Column return new ValueColumn($values); } - $builder = (new PhpBackend())->builder(definition_from_type('value', $type)); + $builder = $this->backend->builder(definition_from_type('value', $type)); $builder->appendMany($values); return $builder->finish(); diff --git a/src/core/etl/src/Flow/ETL/Function/Evaluation/Selection.php b/src/core/etl/src/Flow/ETL/Function/Evaluation/Selection.php index 7ca64a59ae..ac650c8817 100644 --- a/src/core/etl/src/Flow/ETL/Function/Evaluation/Selection.php +++ b/src/core/etl/src/Flow/ETL/Function/Evaluation/Selection.php @@ -41,7 +41,7 @@ public function evaluate(ScalarFunction $function, Rows $rows, FlowContext $cont } } - $subset = $rows->project($schema->keep(...$names))->gather($this->indices); + $subset = $rows->project($schema->keep(...$names), $context->backend())->gather($this->indices); try { return $function->eval($subset, $context); diff --git a/src/core/etl/src/Flow/ETL/Function/Exists.php b/src/core/etl/src/Flow/ETL/Function/Exists.php index 86cccddf84..efdb64eb18 100644 --- a/src/core/etl/src/Flow/ETL/Function/Exists.php +++ b/src/core/etl/src/Flow/ETL/Function/Exists.php @@ -58,7 +58,10 @@ public function eval(Rows $rows, FlowContext $context): Column $exists = $rows->schema()->findDefinition($this->ref->name()) !== null; // @mago-ignore analysis:possibly-invalid-argument - return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), $exists)); + return (new ResultColumn($context->backend()))->of( + $this, + $rows->isEmpty() ? [] : array_fill(0, $rows->count(), $exists), + ); } // the operand is left unresolved by the gate (children() is empty): a reference the batch lacks stays @@ -74,6 +77,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = !array_key_exists($i, $failed); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/GreaterThan.php b/src/core/etl/src/Flow/ETL/Function/GreaterThan.php index d2c8eebd3c..14fd765b0d 100644 --- a/src/core/etl/src/Flow/ETL/Function/GreaterThan.php +++ b/src/core/etl/src/Flow/ETL/Function/GreaterThan.php @@ -100,6 +100,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/GreaterThanEqual.php b/src/core/etl/src/Flow/ETL/Function/GreaterThanEqual.php index cf397c1f27..ef0a84a058 100644 --- a/src/core/etl/src/Flow/ETL/Function/GreaterThanEqual.php +++ b/src/core/etl/src/Flow/ETL/Function/GreaterThanEqual.php @@ -100,6 +100,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Greatest.php b/src/core/etl/src/Flow/ETL/Function/Greatest.php index 600e99c180..ac6f45fa1e 100644 --- a/src/core/etl/src/Flow/ETL/Function/Greatest.php +++ b/src/core/etl/src/Flow/ETL/Function/Greatest.php @@ -92,6 +92,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $values === [] ? null : max($values); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelector.php b/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelector.php index b47e6e68b4..916a900f1b 100644 --- a/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelector.php +++ b/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelector.php @@ -94,6 +94,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelectorAll.php b/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelectorAll.php index 4d4eefc79f..fcfee6954c 100644 --- a/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelectorAll.php +++ b/src/core/etl/src/Flow/ETL/Function/HTMLQuerySelectorAll.php @@ -114,6 +114,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Hash.php b/src/core/etl/src/Flow/ETL/Function/Hash.php index e1672318ae..4278743ae9 100644 --- a/src/core/etl/src/Flow/ETL/Function/Hash.php +++ b/src/core/etl/src/Flow/ETL/Function/Hash.php @@ -85,6 +85,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IndexOf.php b/src/core/etl/src/Flow/ETL/Function/IndexOf.php index 47e09ffa21..433afe2463 100644 --- a/src/core/etl/src/Flow/ETL/Function/IndexOf.php +++ b/src/core/etl/src/Flow/ETL/Function/IndexOf.php @@ -98,6 +98,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IndexOfLast.php b/src/core/etl/src/Flow/ETL/Function/IndexOfLast.php index 7c5387b323..b2852c454c 100644 --- a/src/core/etl/src/Flow/ETL/Function/IndexOfLast.php +++ b/src/core/etl/src/Flow/ETL/Function/IndexOfLast.php @@ -98,6 +98,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsEmpty.php b/src/core/etl/src/Flow/ETL/Function/IsEmpty.php index 31b4d05aa7..24a5557dfa 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsEmpty.php +++ b/src/core/etl/src/Flow/ETL/Function/IsEmpty.php @@ -73,6 +73,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsIn.php b/src/core/etl/src/Flow/ETL/Function/IsIn.php index 73af3fcb5c..02851f2e5e 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsIn.php +++ b/src/core/etl/src/Flow/ETL/Function/IsIn.php @@ -8,7 +8,7 @@ use Exception; use Flow\ETL\Column\Column; use Flow\ETL\Column\ComparableValues; -use Flow\ETL\Column\Php\PhysicalFor; +use Flow\ETL\Column\Physical\PhysicalFor; use Flow\ETL\Exception\EvaluationException; use Flow\ETL\FlowContext; use Flow\ETL\Function\Evaluation\ResultColumn; @@ -158,6 +158,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsNotNull.php b/src/core/etl/src/Flow/ETL/Function/IsNotNull.php index 56e4b3189d..94ca82a2b7 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsNotNull.php +++ b/src/core/etl/src/Flow/ETL/Function/IsNotNull.php @@ -56,7 +56,10 @@ public function eval(Rows $rows, FlowContext $context): Column if ($column->nullCount() === 0) { // @mago-ignore analysis:possibly-invalid-argument - return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), true)); + return (new ResultColumn($context->backend()))->of( + $this, + $rows->isEmpty() ? [] : array_fill(0, $rows->count(), true), + ); } $results = []; @@ -65,6 +68,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = !$column->isNull($i); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsNotNumeric.php b/src/core/etl/src/Flow/ETL/Function/IsNotNumeric.php index 6904b73a91..eab45a1066 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsNotNumeric.php +++ b/src/core/etl/src/Flow/ETL/Function/IsNotNumeric.php @@ -74,6 +74,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsNull.php b/src/core/etl/src/Flow/ETL/Function/IsNull.php index 03509005bd..063cb1fec3 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsNull.php +++ b/src/core/etl/src/Flow/ETL/Function/IsNull.php @@ -56,7 +56,10 @@ public function eval(Rows $rows, FlowContext $context): Column if ($column->nullCount() === 0) { // @mago-ignore analysis:possibly-invalid-argument - return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), false)); + return (new ResultColumn($context->backend()))->of( + $this, + $rows->isEmpty() ? [] : array_fill(0, $rows->count(), false), + ); } $results = []; @@ -65,6 +68,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $column->isNull($i); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsNumeric.php b/src/core/etl/src/Flow/ETL/Function/IsNumeric.php index 92a0652d08..36dd3eb6d5 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsNumeric.php +++ b/src/core/etl/src/Flow/ETL/Function/IsNumeric.php @@ -74,6 +74,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsType.php b/src/core/etl/src/Flow/ETL/Function/IsType.php index 4095385cbd..3b1c0c13bc 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsType.php +++ b/src/core/etl/src/Flow/ETL/Function/IsType.php @@ -87,6 +87,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = false; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/IsUtf8.php b/src/core/etl/src/Flow/ETL/Function/IsUtf8.php index 0ddebe4ff5..0b68c63b30 100644 --- a/src/core/etl/src/Flow/ETL/Function/IsUtf8.php +++ b/src/core/etl/src/Flow/ETL/Function/IsUtf8.php @@ -73,6 +73,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/JsonDecode.php b/src/core/etl/src/Flow/ETL/Function/JsonDecode.php index ccdc808ddb..fc0362b1e6 100644 --- a/src/core/etl/src/Flow/ETL/Function/JsonDecode.php +++ b/src/core/etl/src/Flow/ETL/Function/JsonDecode.php @@ -112,6 +112,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/JsonEncode.php b/src/core/etl/src/Flow/ETL/Function/JsonEncode.php index 12e981cd9f..2870052a8a 100644 --- a/src/core/etl/src/Flow/ETL/Function/JsonEncode.php +++ b/src/core/etl/src/Flow/ETL/Function/JsonEncode.php @@ -118,6 +118,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Least.php b/src/core/etl/src/Flow/ETL/Function/Least.php index 65146ef23c..c89fd37a4e 100644 --- a/src/core/etl/src/Flow/ETL/Function/Least.php +++ b/src/core/etl/src/Flow/ETL/Function/Least.php @@ -92,6 +92,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $values === [] ? null : min($values); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/LessThan.php b/src/core/etl/src/Flow/ETL/Function/LessThan.php index f62ec28022..f8a228c619 100644 --- a/src/core/etl/src/Flow/ETL/Function/LessThan.php +++ b/src/core/etl/src/Flow/ETL/Function/LessThan.php @@ -100,6 +100,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/LessThanEqual.php b/src/core/etl/src/Flow/ETL/Function/LessThanEqual.php index 20dd4e2703..de7af8e23e 100644 --- a/src/core/etl/src/Flow/ETL/Function/LessThanEqual.php +++ b/src/core/etl/src/Flow/ETL/Function/LessThanEqual.php @@ -100,6 +100,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ListSelect.php b/src/core/etl/src/Flow/ETL/Function/ListSelect.php index 573fb7c92e..45c5b54dbc 100644 --- a/src/core/etl/src/Flow/ETL/Function/ListSelect.php +++ b/src/core/etl/src/Flow/ETL/Function/ListSelect.php @@ -107,7 +107,10 @@ public function eval(Rows $rows, FlowContext $context): Column { if ($rows->schema()->findDefinition($this->ref->base()) === null) { // @mago-ignore analysis:possibly-invalid-argument - return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), null)); + return (new ResultColumn($context->backend()))->of( + $this, + $rows->isEmpty() ? [] : array_fill(0, $rows->count(), null), + ); } $results = []; @@ -138,6 +141,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $output; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Literal.php b/src/core/etl/src/Flow/ETL/Function/Literal.php index c37076bb79..cfeefc3764 100644 --- a/src/core/etl/src/Flow/ETL/Function/Literal.php +++ b/src/core/etl/src/Flow/ETL/Function/Literal.php @@ -5,9 +5,9 @@ namespace Flow\ETL\Function; use Closure; +use Flow\ETL\Column\Backend; use Flow\ETL\Column\Column; -use Flow\ETL\Column\Php\ValueColumn; -use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; use Flow\ETL\Function\Evaluation\ResultColumn; @@ -33,6 +33,11 @@ final class Literal implements ScalarFunction */ private ?Column $column = null; + /** + * The backend $column was built in: a column is reused only for the same row count in the same backend. + */ + private ?Backend $columnBackend = null; + public function __construct( private readonly mixed $value, ) { @@ -83,16 +88,17 @@ public function returns(): Type public function eval(Rows $rows, FlowContext $context): Column { - if ($this->column?->count() === $rows->count()) { + if ($this->column?->count() === $rows->count() && $this->columnBackend === $context->backend()) { return $this->column; } + $this->columnBackend = $context->backend(); $type = type_bare($this->returns()); $type = $type instanceof NullType ? $type : type_optional($type); // @mago-ignore analysis:possibly-invalid-argument - return $this->column = (new ResultColumn())->holdsLosslessly($type) - ? (new PhpBackend())->constant(definition_from_type('value', $type), $this->value, $rows->count()) + return $this->column = (new ResultColumn($context->backend()))->holdsLosslessly($type) + ? $context->backend()->constant(definition_from_type('value', $type), $this->value, $rows->count()) : new ValueColumn($rows->isEmpty() ? [] : array_fill(0, $rows->count(), $this->value)); } diff --git a/src/core/etl/src/Flow/ETL/Function/MatchCases.php b/src/core/etl/src/Flow/ETL/Function/MatchCases.php index 6472a28f28..15b3b567af 100644 --- a/src/core/etl/src/Flow/ETL/Function/MatchCases.php +++ b/src/core/etl/src/Flow/ETL/Function/MatchCases.php @@ -157,6 +157,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $values[$i] ?? null; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Minus.php b/src/core/etl/src/Flow/ETL/Function/Minus.php index a38578a9f0..6cd84d48a3 100644 --- a/src/core/etl/src/Flow/ETL/Function/Minus.php +++ b/src/core/etl/src/Flow/ETL/Function/Minus.php @@ -107,6 +107,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Mod.php b/src/core/etl/src/Flow/ETL/Function/Mod.php index c5f2906921..10be6b5f37 100644 --- a/src/core/etl/src/Flow/ETL/Function/Mod.php +++ b/src/core/etl/src/Flow/ETL/Function/Mod.php @@ -80,6 +80,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ModifyDateTime.php b/src/core/etl/src/Flow/ETL/Function/ModifyDateTime.php index d8ba466f22..ed2ffdecb6 100644 --- a/src/core/etl/src/Flow/ETL/Function/ModifyDateTime.php +++ b/src/core/etl/src/Flow/ETL/Function/ModifyDateTime.php @@ -89,6 +89,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Multiply.php b/src/core/etl/src/Flow/ETL/Function/Multiply.php index dc7b95fd06..f52699ee87 100644 --- a/src/core/etl/src/Flow/ETL/Function/Multiply.php +++ b/src/core/etl/src/Flow/ETL/Function/Multiply.php @@ -107,6 +107,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Not.php b/src/core/etl/src/Flow/ETL/Function/Not.php index 461e6e6323..09899bcc88 100644 --- a/src/core/etl/src/Flow/ETL/Function/Not.php +++ b/src/core/etl/src/Flow/ETL/Function/Not.php @@ -56,6 +56,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $value === null ? null : !$value; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/NotEquals.php b/src/core/etl/src/Flow/ETL/Function/NotEquals.php index 0c4b153dfe..75b702ff35 100644 --- a/src/core/etl/src/Flow/ETL/Function/NotEquals.php +++ b/src/core/etl/src/Flow/ETL/Function/NotEquals.php @@ -66,6 +66,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $equals === null ? null : !$equals; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/NotSame.php b/src/core/etl/src/Flow/ETL/Function/NotSame.php index 7dc50ccd2d..a47ee83a15 100644 --- a/src/core/etl/src/Flow/ETL/Function/NotSame.php +++ b/src/core/etl/src/Flow/ETL/Function/NotSame.php @@ -82,6 +82,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Now.php b/src/core/etl/src/Flow/ETL/Function/Now.php index 925eb4b0e1..1e94f520e7 100644 --- a/src/core/etl/src/Flow/ETL/Function/Now.php +++ b/src/core/etl/src/Flow/ETL/Function/Now.php @@ -86,6 +86,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/NumberFormat.php b/src/core/etl/src/Flow/ETL/Function/NumberFormat.php index 3dcf7ab824..f3e78fb7e6 100644 --- a/src/core/etl/src/Flow/ETL/Function/NumberFormat.php +++ b/src/core/etl/src/Flow/ETL/Function/NumberFormat.php @@ -97,6 +97,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/OnEach.php b/src/core/etl/src/Flow/ETL/Function/OnEach.php index 30286219ff..453a4e91a7 100644 --- a/src/core/etl/src/Flow/ETL/Function/OnEach.php +++ b/src/core/etl/src/Flow/ETL/Function/OnEach.php @@ -5,7 +5,6 @@ namespace Flow\ETL\Function; use Flow\ETL\Column\Column; -use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\EvaluationException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\FlowContext; @@ -159,7 +158,7 @@ public function eval(Rows $rows, FlowContext $context): Column try { $results = (new Parameter($body))->values( - array_to_rows($elements, $elementSchema, new PhpBackend()), + array_to_rows($elements, $elementSchema, $context->backend()), $context, ); } catch (EvaluationException $e) { @@ -183,6 +182,6 @@ public function eval(Rows $rows, FlowContext $context): Column $output[] = $values; } - return (new ResultColumn())->typed($type, $output); + return (new ResultColumn($context->backend()))->typed($type, $output); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Optional.php b/src/core/etl/src/Flow/ETL/Function/Optional.php index c21b73e1fe..d90583e559 100644 --- a/src/core/etl/src/Flow/ETL/Function/Optional.php +++ b/src/core/etl/src/Flow/ETL/Function/Optional.php @@ -56,6 +56,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = array_key_exists($i, $evaluated['failed']) ? null : $evaluated['values'][$i]; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Parameter.php b/src/core/etl/src/Flow/ETL/Function/Parameter.php index 147aa1fdbf..3547f35b79 100644 --- a/src/core/etl/src/Flow/ETL/Function/Parameter.php +++ b/src/core/etl/src/Flow/ETL/Function/Parameter.php @@ -22,10 +22,8 @@ use function Flow\ETL\DSL\lit; use function Flow\Types\DSL\type_array; use function Flow\Types\DSL\type_bare; -use function Flow\Types\DSL\type_float; use function Flow\Types\DSL\type_instance_of; use function Flow\Types\DSL\type_integer; -use function Flow\Types\DSL\type_object; use function Flow\Types\DSL\type_string; use function get_debug_type; use function implode; @@ -140,22 +138,6 @@ public function asEnums(Rows $rows, FlowContext $context, string $enumClass): ar return $this->checked($this->values($rows, $context), type_instance_of($enumClass)); } - /** - * @return list - */ - public function asFloats(Rows $rows, FlowContext $context): array - { - $column = $this->column($rows, $context); - - if (type_bare($column->type()) instanceof FloatType) { - /** @var list */ - return $column->physicals(); - } - - /** @var list */ - return $this->checked($column->values(), type_float()); - } - /** * @template T of object * @@ -272,15 +254,6 @@ public function asNumbers(Rows $rows, FlowContext $context, int|float|null $defa return $numbers; } - /** - * @return list - */ - public function asObjects(Rows $rows, FlowContext $context): array - { - /** @var list */ - return $this->checked($this->values($rows, $context), type_object()); - } - /** * $default applies to a NULL input only - a malformed value always throws. * diff --git a/src/core/etl/src/Flow/ETL/Function/Plus.php b/src/core/etl/src/Flow/ETL/Function/Plus.php index c8df629dc5..c6e0b13ccf 100644 --- a/src/core/etl/src/Flow/ETL/Function/Plus.php +++ b/src/core/etl/src/Flow/ETL/Function/Plus.php @@ -107,6 +107,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Power.php b/src/core/etl/src/Flow/ETL/Function/Power.php index 4402a1094a..f7450dbd85 100644 --- a/src/core/etl/src/Flow/ETL/Function/Power.php +++ b/src/core/etl/src/Flow/ETL/Function/Power.php @@ -111,6 +111,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Prepend.php b/src/core/etl/src/Flow/ETL/Function/Prepend.php index fc0af794f5..bb456a7a0d 100644 --- a/src/core/etl/src/Flow/ETL/Function/Prepend.php +++ b/src/core/etl/src/Flow/ETL/Function/Prepend.php @@ -82,6 +82,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RandomString.php b/src/core/etl/src/Flow/ETL/Function/RandomString.php index e9b7240978..00e767d344 100644 --- a/src/core/etl/src/Flow/ETL/Function/RandomString.php +++ b/src/core/etl/src/Flow/ETL/Function/RandomString.php @@ -79,6 +79,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Regex.php b/src/core/etl/src/Flow/ETL/Function/Regex.php index be25b38470..2f0d862d6d 100644 --- a/src/core/etl/src/Flow/ETL/Function/Regex.php +++ b/src/core/etl/src/Flow/ETL/Function/Regex.php @@ -113,6 +113,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RegexAll.php b/src/core/etl/src/Flow/ETL/Function/RegexAll.php index 61778991a5..db6bcf6b14 100644 --- a/src/core/etl/src/Flow/ETL/Function/RegexAll.php +++ b/src/core/etl/src/Flow/ETL/Function/RegexAll.php @@ -123,6 +123,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RegexMatch.php b/src/core/etl/src/Flow/ETL/Function/RegexMatch.php index 9b1c55dcfe..f59d0e3b4b 100644 --- a/src/core/etl/src/Flow/ETL/Function/RegexMatch.php +++ b/src/core/etl/src/Flow/ETL/Function/RegexMatch.php @@ -99,6 +99,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RegexMatchAll.php b/src/core/etl/src/Flow/ETL/Function/RegexMatchAll.php index 3493a3cf16..fd085b68f4 100644 --- a/src/core/etl/src/Flow/ETL/Function/RegexMatchAll.php +++ b/src/core/etl/src/Flow/ETL/Function/RegexMatchAll.php @@ -100,6 +100,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/RegexReplace.php b/src/core/etl/src/Flow/ETL/Function/RegexReplace.php index 6e5f1ea087..0789f19ffd 100644 --- a/src/core/etl/src/Flow/ETL/Function/RegexReplace.php +++ b/src/core/etl/src/Flow/ETL/Function/RegexReplace.php @@ -115,6 +115,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Repeat.php b/src/core/etl/src/Flow/ETL/Function/Repeat.php index 296a378c55..068b9dc9b6 100644 --- a/src/core/etl/src/Flow/ETL/Function/Repeat.php +++ b/src/core/etl/src/Flow/ETL/Function/Repeat.php @@ -80,6 +80,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Reverse.php b/src/core/etl/src/Flow/ETL/Function/Reverse.php index 87c2348ca7..d7aa4df4e6 100644 --- a/src/core/etl/src/Flow/ETL/Function/Reverse.php +++ b/src/core/etl/src/Flow/ETL/Function/Reverse.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Round.php b/src/core/etl/src/Flow/ETL/Function/Round.php index 76567d9d19..988d6a77a5 100644 --- a/src/core/etl/src/Flow/ETL/Function/Round.php +++ b/src/core/etl/src/Flow/ETL/Function/Round.php @@ -87,6 +87,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Same.php b/src/core/etl/src/Flow/ETL/Function/Same.php index 4148017d8d..2f0887105b 100644 --- a/src/core/etl/src/Flow/ETL/Function/Same.php +++ b/src/core/etl/src/Flow/ETL/Function/Same.php @@ -82,6 +82,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Sanitize.php b/src/core/etl/src/Flow/ETL/Function/Sanitize.php index bb51f2de8e..4164f02493 100644 --- a/src/core/etl/src/Flow/ETL/Function/Sanitize.php +++ b/src/core/etl/src/Flow/ETL/Function/Sanitize.php @@ -98,6 +98,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Size.php b/src/core/etl/src/Flow/ETL/Function/Size.php index e6cdeb3bce..a3e4799d91 100644 --- a/src/core/etl/src/Flow/ETL/Function/Size.php +++ b/src/core/etl/src/Flow/ETL/Function/Size.php @@ -83,6 +83,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Slug.php b/src/core/etl/src/Flow/ETL/Function/Slug.php index e4fca095f7..cffac03608 100644 --- a/src/core/etl/src/Flow/ETL/Function/Slug.php +++ b/src/core/etl/src/Flow/ETL/Function/Slug.php @@ -93,6 +93,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Split.php b/src/core/etl/src/Flow/ETL/Function/Split.php index 44ca94d995..00a8993816 100644 --- a/src/core/etl/src/Flow/ETL/Function/Split.php +++ b/src/core/etl/src/Flow/ETL/Function/Split.php @@ -95,6 +95,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Sprintf.php b/src/core/etl/src/Flow/ETL/Function/Sprintf.php index ffbb29091f..aa4a4aeae3 100644 --- a/src/core/etl/src/Flow/ETL/Function/Sprintf.php +++ b/src/core/etl/src/Flow/ETL/Function/Sprintf.php @@ -98,6 +98,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StartsWith.php b/src/core/etl/src/Flow/ETL/Function/StartsWith.php index 341b9e6a33..b5754a3c1e 100644 --- a/src/core/etl/src/Flow/ETL/Function/StartsWith.php +++ b/src/core/etl/src/Flow/ETL/Function/StartsWith.php @@ -78,6 +78,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StrPad.php b/src/core/etl/src/Flow/ETL/Function/StrPad.php index 2574b89886..a75e26dbd3 100644 --- a/src/core/etl/src/Flow/ETL/Function/StrPad.php +++ b/src/core/etl/src/Flow/ETL/Function/StrPad.php @@ -92,6 +92,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StrReplace.php b/src/core/etl/src/Flow/ETL/Function/StrReplace.php index 393b53904a..0657ec5b4d 100644 --- a/src/core/etl/src/Flow/ETL/Function/StrReplace.php +++ b/src/core/etl/src/Flow/ETL/Function/StrReplace.php @@ -97,6 +97,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringAfter.php b/src/core/etl/src/Flow/ETL/Function/StringAfter.php index e64da55b37..f1194932fa 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringAfter.php +++ b/src/core/etl/src/Flow/ETL/Function/StringAfter.php @@ -83,6 +83,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringAfterLast.php b/src/core/etl/src/Flow/ETL/Function/StringAfterLast.php index 75244eb321..80a23edb77 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringAfterLast.php +++ b/src/core/etl/src/Flow/ETL/Function/StringAfterLast.php @@ -83,6 +83,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringBefore.php b/src/core/etl/src/Flow/ETL/Function/StringBefore.php index a6d092502d..26e37e96b4 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringBefore.php +++ b/src/core/etl/src/Flow/ETL/Function/StringBefore.php @@ -83,6 +83,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringBeforeLast.php b/src/core/etl/src/Flow/ETL/Function/StringBeforeLast.php index 241f23b3d3..552dbcdac6 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringBeforeLast.php +++ b/src/core/etl/src/Flow/ETL/Function/StringBeforeLast.php @@ -83,6 +83,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringContainsAny.php b/src/core/etl/src/Flow/ETL/Function/StringContainsAny.php index 416beffbe7..e0164a5f7a 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringContainsAny.php +++ b/src/core/etl/src/Flow/ETL/Function/StringContainsAny.php @@ -91,6 +91,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringEqualsTo.php b/src/core/etl/src/Flow/ETL/Function/StringEqualsTo.php index 8f0c55083a..360bd7a675 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringEqualsTo.php +++ b/src/core/etl/src/Flow/ETL/Function/StringEqualsTo.php @@ -78,6 +78,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringFold.php b/src/core/etl/src/Flow/ETL/Function/StringFold.php index 7f6371f378..c3b22c99b2 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringFold.php +++ b/src/core/etl/src/Flow/ETL/Function/StringFold.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringMatch.php b/src/core/etl/src/Flow/ETL/Function/StringMatch.php index fc7d9dbfc2..b9085877d5 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringMatch.php +++ b/src/core/etl/src/Flow/ETL/Function/StringMatch.php @@ -89,6 +89,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringMatchAll.php b/src/core/etl/src/Flow/ETL/Function/StringMatchAll.php index 835d72f099..6355ad9e35 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringMatchAll.php +++ b/src/core/etl/src/Flow/ETL/Function/StringMatchAll.php @@ -94,6 +94,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringNormalize.php b/src/core/etl/src/Flow/ETL/Function/StringNormalize.php index 1649cb859b..21a7dbaa34 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringNormalize.php +++ b/src/core/etl/src/Flow/ETL/Function/StringNormalize.php @@ -77,6 +77,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringStyle.php b/src/core/etl/src/Flow/ETL/Function/StringStyle.php index 81611f2ac9..aec1c9d78f 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringStyle.php +++ b/src/core/etl/src/Flow/ETL/Function/StringStyle.php @@ -90,6 +90,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringTitle.php b/src/core/etl/src/Flow/ETL/Function/StringTitle.php index 2da8bc5115..060100931f 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringTitle.php +++ b/src/core/etl/src/Flow/ETL/Function/StringTitle.php @@ -78,6 +78,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StringWidth.php b/src/core/etl/src/Flow/ETL/Function/StringWidth.php index dcfa6d1469..1e21ef72da 100644 --- a/src/core/etl/src/Flow/ETL/Function/StringWidth.php +++ b/src/core/etl/src/Flow/ETL/Function/StringWidth.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Structure.php b/src/core/etl/src/Flow/ETL/Function/Structure.php index d282f8f923..c5f2f95c85 100644 --- a/src/core/etl/src/Flow/ETL/Function/Structure.php +++ b/src/core/etl/src/Flow/ETL/Function/Structure.php @@ -109,6 +109,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $values; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/StructureSelect.php b/src/core/etl/src/Flow/ETL/Function/StructureSelect.php index e322192105..f4e6211930 100644 --- a/src/core/etl/src/Flow/ETL/Function/StructureSelect.php +++ b/src/core/etl/src/Flow/ETL/Function/StructureSelect.php @@ -95,7 +95,10 @@ public function eval(Rows $rows, FlowContext $context): Column { if ($rows->schema()->findDefinition($this->ref->base()) === null) { // @mago-ignore analysis:possibly-invalid-argument - return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), null)); + return (new ResultColumn($context->backend()))->of( + $this, + $rows->isEmpty() ? [] : array_fill(0, $rows->count(), null), + ); } $results = []; @@ -121,6 +124,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $output; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToDate.php b/src/core/etl/src/Flow/ETL/Function/ToDate.php index ceed1668e8..5566808fd4 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToDate.php +++ b/src/core/etl/src/Flow/ETL/Function/ToDate.php @@ -116,6 +116,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToDateTime.php b/src/core/etl/src/Flow/ETL/Function/ToDateTime.php index e045a31acd..df32ee2c08 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToDateTime.php +++ b/src/core/etl/src/Flow/ETL/Function/ToDateTime.php @@ -156,6 +156,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToLower.php b/src/core/etl/src/Flow/ETL/Function/ToLower.php index 07bd3a3236..f2f85d6639 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToLower.php +++ b/src/core/etl/src/Flow/ETL/Function/ToLower.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToTimeZone.php b/src/core/etl/src/Flow/ETL/Function/ToTimeZone.php index 2226b4bec5..38eb7a8c3c 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToTimeZone.php +++ b/src/core/etl/src/Flow/ETL/Function/ToTimeZone.php @@ -98,6 +98,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/ToUpper.php b/src/core/etl/src/Flow/ETL/Function/ToUpper.php index 439a3f9f91..5e3719ce32 100644 --- a/src/core/etl/src/Flow/ETL/Function/ToUpper.php +++ b/src/core/etl/src/Flow/ETL/Function/ToUpper.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Trim.php b/src/core/etl/src/Flow/ETL/Function/Trim.php index d7f505c31a..3df1eee2ba 100644 --- a/src/core/etl/src/Flow/ETL/Function/Trim.php +++ b/src/core/etl/src/Flow/ETL/Function/Trim.php @@ -96,6 +96,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Truncate.php b/src/core/etl/src/Flow/ETL/Function/Truncate.php index 580b60e859..cca7ff4337 100644 --- a/src/core/etl/src/Flow/ETL/Function/Truncate.php +++ b/src/core/etl/src/Flow/ETL/Function/Truncate.php @@ -89,6 +89,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Ulid.php b/src/core/etl/src/Flow/ETL/Function/Ulid.php index e5fca37fe3..7a4a4c1e12 100644 --- a/src/core/etl/src/Flow/ETL/Function/Ulid.php +++ b/src/core/etl/src/Flow/ETL/Function/Ulid.php @@ -102,6 +102,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/UnicodeLength.php b/src/core/etl/src/Flow/ETL/Function/UnicodeLength.php index 617050f7d5..d1dbfd388e 100644 --- a/src/core/etl/src/Flow/ETL/Function/UnicodeLength.php +++ b/src/core/etl/src/Flow/ETL/Function/UnicodeLength.php @@ -71,6 +71,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Uuid.php b/src/core/etl/src/Flow/ETL/Function/Uuid.php index cd9f29903d..6c6ce3391a 100644 --- a/src/core/etl/src/Flow/ETL/Function/Uuid.php +++ b/src/core/etl/src/Flow/ETL/Function/Uuid.php @@ -99,7 +99,7 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = new FlowUuid($this->generateV4()); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } $params = (new Parameter($this->value))->asTypes( @@ -122,7 +122,7 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } private function generateV4(): UuidV4|UuidInterface diff --git a/src/core/etl/src/Flow/ETL/Function/When.php b/src/core/etl/src/Flow/ETL/Function/When.php index cbeec600f9..a6fbe6e64b 100644 --- a/src/core/etl/src/Flow/ETL/Function/When.php +++ b/src/core/etl/src/Flow/ETL/Function/When.php @@ -117,6 +117,6 @@ public function eval(Rows $rows, FlowContext $context): Column $results[] = $values[$i] ?? null; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/Wordwrap.php b/src/core/etl/src/Flow/ETL/Function/Wordwrap.php index 40e5500213..f189768ac8 100644 --- a/src/core/etl/src/Flow/ETL/Function/Wordwrap.php +++ b/src/core/etl/src/Flow/ETL/Function/Wordwrap.php @@ -102,6 +102,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/Function/XPath.php b/src/core/etl/src/Flow/ETL/Function/XPath.php index 743260a5c8..a6dd8a61ed 100644 --- a/src/core/etl/src/Flow/ETL/Function/XPath.php +++ b/src/core/etl/src/Flow/ETL/Function/XPath.php @@ -119,6 +119,6 @@ public function eval(Rows $rows, FlowContext $context): Column throw EvaluationException::at($i, $e); } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } diff --git a/src/core/etl/src/Flow/ETL/GroupBy.php b/src/core/etl/src/Flow/ETL/GroupBy.php index cba3a4b179..8644710e45 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy.php +++ b/src/core/etl/src/Flow/ETL/GroupBy.php @@ -4,6 +4,7 @@ namespace Flow\ETL; +use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; @@ -15,10 +16,12 @@ use Flow\ETL\Row\Reference; use Flow\ETL\Row\References; -use function array_fill; +use function array_key_exists; +use function array_key_last; use function array_unique; use function count; use function Flow\ETL\DSL\definition_from_type; +use function serialize; final class GroupBy { @@ -130,28 +133,47 @@ public function keys(Rows $rows, Schema $input): array return []; } - $columns = []; + $present = []; + $absent = []; - foreach ($this->refs as $ref) { - // absent under a nullable declaration is a legitimate null; absent under NOT NULL is a - // row-shape violation, and Rows::column() names it and lists the available columns. - $columns[$ref->name()] = $rows->schema()->findDefinition($ref->base()) === null - && $input->get($ref)->isNullable() - // @mago-ignore analysis:possibly-invalid-argument - ? array_fill(0, $rows->count(), null) - : $rows->column($ref->base())->values(); + foreach ($this->refs->all() as $ref) { + $absent[] = $rows->schema()->findDefinition($ref->base()) === null; + + if (!$absent[array_key_last($absent)]) { + $present[] = $ref; + } } $keys = []; + $built = []; + + // one key per distinct identity over every ref in order (an absent ref is a null slot), its values read from + // the first row that carries it + foreach ((new KeyValues($present))->of($rows) as $i => $presentValues) { + $identity = []; + $position = 0; + + foreach ($absent as $isAbsent) { + $identity[] = $isAbsent ? null : $presentValues[$position++]; + } + + $string = serialize($identity); + + if (!array_key_exists($string, $built)) { + $values = []; - for ($i = 0, $count = $rows->count(); $i < $count; $i++) { - $values = []; + foreach ($this->refs->all() as $index => $ref) { + // absent under a nullable declaration is a legitimate null; absent under NOT NULL is a + // row-shape violation, and Rows::column() names it and lists the available columns. + $values[$ref->name()] = $absent[$index] && $input->get($ref)->isNullable() + ? null + : $rows->column($ref->base())->value($i); + } - foreach ($columns as $name => $column) { - $values[$name] = $column[$i]; + $built[$string] = new GroupKey($values, $string); } - $keys[] = new GroupKey($values); + $keys[] = $built[$string]; } return $keys; diff --git a/src/core/etl/src/Flow/ETL/GroupBy/GroupKey.php b/src/core/etl/src/Flow/ETL/GroupBy/GroupKey.php index f313fd1362..76015ba396 100644 --- a/src/core/etl/src/Flow/ETL/GroupBy/GroupKey.php +++ b/src/core/etl/src/Flow/ETL/GroupBy/GroupKey.php @@ -9,8 +9,6 @@ use Stringable; use Traversable; -use function serialize; - /** * @implements IteratorAggregate */ @@ -18,14 +16,16 @@ { /** * @param array $values ref name => key value + * @param string $identity what tells two keys apart: the serialized equality forms of the key, in ref order */ public function __construct( private array $values, + private string $identity, ) {} public function __toString(): string { - return serialize($this->values); + return $this->identity; } public function getIterator(): Traversable diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php index a7c06266ff..854069e729 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/Joiner.php @@ -8,6 +8,7 @@ use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Bucketing\SingleBucketHasher; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\DuplicatedEntriesException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Join\Expression; @@ -47,6 +48,7 @@ final class Joiner public function __construct( private readonly Expression $expression, private readonly Join $type, + private readonly Backend $backend, private readonly int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand @@ -139,20 +141,23 @@ public function join(JoinSide $left, JoinSide $right, bool $buildLeft = false): // for the same declared output - the projection drops the undeclared columns and pads the nulls the join // introduced yield $this->type === Join::left_anti - ? $batch->gather($outputLeft)->project($outputSchema) - : $this->merge($batch->gather($outputLeft), $probe->gather($outputRight))->project($outputSchema); + ? $batch->gather($outputLeft)->project($outputSchema, $this->backend) + : $this->merge($batch->gather($outputLeft), $probe->gather($outputRight))->project( + $outputSchema, + $this->backend, + ); } if ($this->type === Join::right) { $leftSchema ??= new Schema(); - $nullLeft = $left->nullRow ?? (new NullRowBuilder($leftSchema))->rows(); + $nullLeft = $left->nullRow ?? (new NullRowBuilder($leftSchema, $this->backend))->rows(); $outputSchema ??= $this->joinSchema->of($this->type, $leftSchema, $rightSchema); foreach (array_chunk($table->unmatched(), $this->batchSize) as $unmatched) { yield $this->merge( $nullLeft->gather(array_fill(0, count($unmatched), 0)), $build->gather($unmatched), - )->project($outputSchema); + )->project($outputSchema, $this->backend); } } } @@ -182,13 +187,18 @@ private function build(JoinSide $side): array $schema ??= $batch->schema(); if (!$batch->isEmpty()) { - $parts[] = $batch->project($schema); + $parts[] = $batch->project($schema, $this->backend); } } $schema ??= new Schema(); - return [$parts === [] ? Rows::empty($schema) : $parts[0]->concat(...array_slice($parts, 1)), $schema]; + return [ + $parts === [] + ? Rows::empty($schema, $this->backend) + : $parts[0]->concat($this->backend, ...array_slice($parts, 1)), + $schema, + ]; } /** @@ -266,14 +276,17 @@ private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator } if ($outputLeft !== []) { - yield $this->merge($probe->gather($outputLeft), $batch->gather($outputRight))->project($outputSchema); + yield $this->merge($probe->gather($outputLeft), $batch->gather($outputRight))->project( + $outputSchema, + $this->backend, + ); } } $rightSchema ??= new Schema(); if ($this->type === Join::left || $this->type === Join::left_anti) { - $nullRight = $right->nullRow ?? (new NullRowBuilder($rightSchema))->rows(); + $nullRight = $right->nullRow ?? (new NullRowBuilder($rightSchema, $this->backend))->rows(); $outputSchema ??= $this->joinSchema->of($this->type, $leftSchema, $rightSchema); foreach (array_chunk($table->unmatched(), $this->batchSize) as $unmatched) { @@ -281,8 +294,8 @@ private function joinBuildingLeft(JoinSide $left, JoinSide $right): Generator ? $this->merge( $build->gather($unmatched), $nullRight->gather(array_fill(0, count($unmatched), 0)), - )->project($outputSchema) - : $build->gather($unmatched)->project($outputSchema); + )->project($outputSchema, $this->backend) + : $build->gather($unmatched)->project($outputSchema, $this->backend); } } } @@ -305,8 +318,12 @@ private function meet(Rows $left, array $leftIndices, Rows $right, array $rightI ))); return $this->expression->meet( - $left->project($left->schema()->keep(...$names($this->expression->left())))->gather($leftIndices), - $right->project($right->schema()->keep(...$names($this->expression->right())))->gather($rightIndices), + $left->project($left->schema()->keep(...$names($this->expression->left())), $this->backend)->gather( + $leftIndices, + ), + $right + ->project($right->schema()->keep(...$names($this->expression->right())), $this->backend) + ->gather($rightIndices), ); } @@ -328,9 +345,9 @@ private function merge(Rows $left, Rows $right): Rows private function padded(Rows $build, ?Rows $nullRow, Schema $schema): Rows { - $null = $nullRow ?? (new NullRowBuilder($schema))->rows(); + $null = $nullRow ?? (new NullRowBuilder($schema, $this->backend))->rows(); - return $build->withSchema($null->schema())->concat($null); + return $build->withSchema($null->schema())->concat($this->backend, $null); } private function table(Rows $build, KeyValues $values, bool $trackUnmatched): HashTable diff --git a/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php b/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php index da8e5849fb..6046242686 100644 --- a/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php +++ b/src/core/etl/src/Flow/ETL/Join/HashJoin/NullRowBuilder.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Join\HashJoin; -use Flow\ETL\Column\AdaptiveBackend; +use Flow\ETL\Column\Backend; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -12,10 +12,9 @@ { private Rows $rows; - public function __construct(Schema $schema) + public function __construct(Schema $schema, Backend $backend) { $nullable = $schema->makeNullable(); - $backend = new AdaptiveBackend(); $columns = []; foreach ($nullable->definitions() as $name => $definition) { diff --git a/src/core/etl/src/Flow/ETL/Join/RowsJoin.php b/src/core/etl/src/Flow/ETL/Join/RowsJoin.php new file mode 100644 index 0000000000..def69f4353 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Join/RowsJoin.php @@ -0,0 +1,94 @@ +cross($left->schema(), $right->schema()); + $leftIndices = []; + $rightIndices = []; + $rightCount = $right->count(); + + for ($i = 0; $i < $left->count(); $i++) { + for ($j = 0; $j < $rightCount; $j++) { + $leftIndices[] = $i; + $rightIndices[] = $j; + } + } + + return (new RowMerger($joinPrefix)) + ->merge($left->gather($leftIndices), $right->gather($rightIndices)) + ->project($schema, $this->backend); + } + + /** + * @throws InvalidArgumentException + */ + public function inner(Rows $left, Rows $right, Expression $expression): Rows + { + return $this->join($left, $right, $expression, Join::inner); + } + + /** + * @throws InvalidArgumentException + */ + public function left(Rows $left, Rows $right, Expression $expression): Rows + { + return $this->join($left, $right, $expression, Join::left); + } + + /** + * @throws InvalidArgumentException + */ + public function leftAnti(Rows $left, Rows $right, Expression $expression): Rows + { + return $this->join($left, $right, $expression, Join::left_anti); + } + + /** + * @throws InvalidArgumentException + */ + public function right(Rows $left, Rows $right, Expression $expression): Rows + { + return $this->join($left, $right, $expression, Join::right); + } + + /** + * @throws InvalidArgumentException + */ + public function join(Rows $left, Rows $right, Expression $expression, Join $type): Rows + { + $single = static function (Rows $rows): Generator { + yield $rows; + }; + + $joiner = new Joiner($expression, $type, $this->backend); + $joined = []; + + foreach ($joiner->join(JoinSide::of($single($left)), JoinSide::of($single($right))) as $batch) { + $joined[] = $batch; + } + + return $joined === [] + ? Rows::empty($joiner->schema($left->schema(), $right->schema()), $this->backend) + : $joined[0]->concat($this->backend, ...array_slice($joined, 1)); + } +} diff --git a/src/core/etl/src/Flow/ETL/Loader/FileLoader.php b/src/core/etl/src/Flow/ETL/Loader/File/FileLoader.php similarity index 87% rename from src/core/etl/src/Flow/ETL/Loader/FileLoader.php rename to src/core/etl/src/Flow/ETL/Loader/File/FileLoader.php index a88549e166..e836740b13 100644 --- a/src/core/etl/src/Flow/ETL/Loader/FileLoader.php +++ b/src/core/etl/src/Flow/ETL/Loader/File/FileLoader.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\ETL\Loader; +namespace Flow\ETL\Loader\File; use Flow\ETL\Filesystem\SaveMode; use Flow\Filesystem\Path; diff --git a/src/core/etl/src/Flow/ETL/Loader/File/FileSink.php b/src/core/etl/src/Flow/ETL/Loader/File/FileSink.php new file mode 100644 index 0000000000..47b6eea2b1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Loader/File/FileSink.php @@ -0,0 +1,14 @@ + by stream URI + */ + private array $open = []; + + public function __construct( + private readonly Filesystem $filesystem, + private readonly Path $path, + private readonly SaveMode $saveMode, + private readonly PartitionRouter $router, + private readonly FileSinks $sinks, + ) {} + + /** + * Closes every sink - the first close failure rethrown once all were closed - then publishes the files. + * + * @throws Throwable + */ + public function closure(): void + { + $failure = $this->closeSinks(); + + if ($failure !== null) { + throw $failure; + } + + $this->files?->publish(); + $this->files = null; + } + + /** + * Closes every sink, then abandons the files whatever a close threw. + * + * @throws Throwable + */ + public function discard(): void + { + $failure = $this->closeSinks(); + + $this->files?->abandon(); + $this->files = null; + + if ($failure !== null) { + throw $failure; + } + } + + public function write(Rows $rows, FlowContext $context, Loader $loader): void + { + $context->telemetry()->loadingStarted($loader, [ + TelemetryAttributes::ATTR_LOADER_DESTINATION_URI => $this->path->uri(), + ]); + + try { + foreach ($this->router->route($rows) as [$partitions, $group]) { + $files = $this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode); + $stream = $files->writeTo($partitions->toArray()); + + ($this->open[$stream->path()->uri()] ??= $this->sinks->open($stream, $context->backend()))->write( + $group, + ); + } + + $context->telemetry()->loadingCompleted($loader, [ + TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count(), + ]); + } catch (Throwable $e) { + $context->telemetry()->loadingFailed($loader, $e); + + throw $e; + } + } + + /** + * Closes every open sink, all of them even when one throws. + * + * @return null|Throwable the first close failure + */ + private function closeSinks(): ?Throwable + { + $failure = null; + + foreach ($this->open as $uri => $sink) { + unset($this->open[$uri]); + + try { + $sink->close(); + } catch (Throwable $e) { + $failure ??= $e; + } + } + + return $failure; + } +} diff --git a/src/core/etl/src/Flow/ETL/Filesystem/FilesSink.php b/src/core/etl/src/Flow/ETL/Loader/File/FilesSink.php similarity index 90% rename from src/core/etl/src/Flow/ETL/Filesystem/FilesSink.php rename to src/core/etl/src/Flow/ETL/Loader/File/FilesSink.php index 8090e628af..4fe2e93af8 100644 --- a/src/core/etl/src/Flow/ETL/Filesystem/FilesSink.php +++ b/src/core/etl/src/Flow/ETL/Loader/File/FilesSink.php @@ -2,15 +2,15 @@ declare(strict_types=1); -namespace Flow\ETL\Filesystem; +namespace Flow\ETL\Loader\File; use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Filesystem\SaveMode; use Flow\Filesystem\DestinationStream; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Partition; use Flow\Filesystem\Path; use Flow\Filesystem\Stream\VoidStream; -use Generator; use Throwable; use function array_key_exists; @@ -111,29 +111,6 @@ public function publish(): void } } - /** - * @param array $partitions - */ - public function touched(array $partitions = []): bool - { - return array_key_exists( - count($partitions) ? $this->destination->addPartitions(...$partitions)->uri() : $this->destination->uri(), - $this->streams, - ); - } - - /** - * @return \Generator - */ - public function openStreams(): Generator - { - foreach ($this->streams as $stream) { - if ($stream->isOpen()) { - yield $stream; - } - } - } - /** * @param array $partitions */ diff --git a/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php b/src/core/etl/src/Flow/ETL/Loader/File/PartitionRouter.php similarity index 86% rename from src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php rename to src/core/etl/src/Flow/ETL/Loader/File/PartitionRouter.php index 6657b445f1..ed55879263 100644 --- a/src/core/etl/src/Flow/ETL/Loader/PartitionRouter.php +++ b/src/core/etl/src/Flow/ETL/Loader/File/PartitionRouter.php @@ -2,19 +2,20 @@ declare(strict_types=1); -namespace Flow\ETL\Loader; +namespace Flow\ETL\Loader\File; use Flow\ETL\Bucketing\Hasher; use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Loader\Partitioning; +use Flow\ETL\Loader\RowPartitions; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Filesystem\Partitions; use Generator; -use function array_flip; -use function array_keys; +use function array_values; use function implode; use function sprintf; @@ -23,7 +24,7 @@ final class PartitionRouter private readonly RowPartitions $rowPartitions; /** - * @var array + * @var list the partition columns the files do not carry */ private readonly array $dropped; @@ -32,15 +33,15 @@ public function __construct( private readonly Hasher $hasher = new NativeHasher(), ) { $this->rowPartitions = new RowPartitions($partitioning->by); - $this->dropped = $partitioning->writeColumns ? [] : array_flip($partitioning->by->names()); + $this->dropped = $partitioning->writeColumns ? [] : array_values($partitioning->by->names()); } /** - * @return array + * @return list */ public function droppedNames(): array { - return array_keys($this->dropped); + return $this->dropped; } /** @@ -72,7 +73,7 @@ public function route(Rows $rows): Generator foreach ($groups as [$partitions, $indices]) { $group = $rows->gather($indices); - yield [$partitions, $this->dropped === [] ? $group : $group->project($stripped)]; + yield [$partitions, $this->dropped === [] ? $group : $group->select(...$stripped->references()->names())]; } } diff --git a/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushFilterIntoSource.php b/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushFilterIntoSource.php index 945f176528..3d597af875 100644 --- a/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushFilterIntoSource.php +++ b/src/core/etl/src/Flow/ETL/Optimizer/Rule/PushFilterIntoSource.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Optimizer\Rule; -use Flow\ETL\Extractor\FileExtractor; +use Flow\ETL\Extractor\File\FileExtractor; use Flow\ETL\Filesystem\ScalarFunctionFilter; use Flow\ETL\FlowContext; use Flow\ETL\Function\All; diff --git a/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php b/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php index d282c27e2d..fb8733ce71 100644 --- a/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php +++ b/src/core/etl/src/Flow/ETL/Plan/Explain/Details.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Plan\Explain; -use Flow\ETL\Extractor\FileExtractor; +use Flow\ETL\Extractor\File\FileExtractor; use Flow\ETL\Join\Comparison\Any; use Flow\ETL\Plan\Materialization; use Flow\ETL\Plan\Node; diff --git a/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php index b202700e3c..2e04885a23 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BatchingByProcessor.php @@ -62,7 +62,7 @@ public function process(Generator $rows, FlowContext $context): Generator while ($rows->valid()) { $schema ??= $rows->current()->schema(); - $batch = $rows->current()->matchTo($schema); + $batch = $rows->current()->matchTo($schema, $context->backend()); $start = 0; if ($batch->isEmpty()) { @@ -87,7 +87,7 @@ public function process(Generator $rows, FlowContext $context): Generator $parts[] = $batch->slice($start, $i - $start); } - $signal = yield $parts[0]->concat(...array_slice($parts, 1)); + $signal = yield $parts[0]->concat($context->backend(), ...array_slice($parts, 1)); if ($signal === Signal::STOP) { $rows->send(Signal::STOP); @@ -114,7 +114,7 @@ public function process(Generator $rows, FlowContext $context): Generator } if ($parts !== []) { - yield $parts[0]->concat(...array_slice($parts, 1)); + yield $parts[0]->concat($context->backend(), ...array_slice($parts, 1)); } } } diff --git a/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php index cbf8cd43ff..fae858c3b8 100644 --- a/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/BatchingProcessor.php @@ -52,7 +52,9 @@ public function process(Generator $rows, FlowContext $context): Generator $schema ??= $batch->schema(); if (!$batch->isEmpty()) { - $pending = $pending === null ? $batch->matchTo($schema) : $pending->concat($batch->matchTo($schema)); + $pending = $pending === null + ? $batch->matchTo($schema, $context->backend()) + : $pending->concat($context->backend(), $batch->matchTo($schema, $context->backend())); while ($pending->count() >= $this->size) { $signal = yield $pending->slice(0, $this->size); diff --git a/src/core/etl/src/Flow/ETL/Processor/CachingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/CachingProcessor.php index af160151f0..5d56387825 100644 --- a/src/core/etl/src/Flow/ETL/Processor/CachingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/CachingProcessor.php @@ -62,7 +62,7 @@ public function process(Generator $rows, FlowContext $context): Generator } } - $cache->set($id, $index->toRows()); + $cache->set($id, $index->toRows($context->backend())); } public function bind(Schema $input): BoundStep diff --git a/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php b/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php index 1ad082340c..697ba81af0 100644 --- a/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/CollectingProcessor.php @@ -34,9 +34,14 @@ public function process(Generator $rows, FlowContext $context): Generator $collected = null; foreach ($rows as $batch) { - $collected = $collected === null ? $batch : $collected->merge($batch); + // an empty part adds nothing, whatever its schema + $collected = match (true) { + $collected === null, $collected->isEmpty() => $batch, + $batch->isEmpty() => $collected, + default => $collected->concat($context->backend(), $batch), + }; } - yield $collected ?? Rows::empty($this->declared ?? new Schema()); + yield $collected ?? Rows::empty($this->declared ?? new Schema(), $context->backend()); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php index 2aed7fef40..a0e9e7f68b 100644 --- a/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/GroupByAggregationProcessor.php @@ -26,6 +26,7 @@ use function array_values; use function iterator_to_array; +use function serialize; /** * Aggregates in one pass while the process stays under the memory limit. Past it, the rest of the stream is partitioned @@ -117,7 +118,11 @@ public function process(Generator $rows, FlowContext $context): Generator // not no row. Only reachable bound - an unbound plan has no schema to type the defaults with. if ($shape !== null && $this->groupBy->isGlobal()) { yield (new RowsBuilder($shape->output, $context->backend()))->appendRows([ - $this->groupBy->aggregatedValues(new GroupKey([]), $shape->aggregators->cloned(), $shape->output), + $this->groupBy->aggregatedValues( + new GroupKey([], serialize([])), + $shape->aggregators->cloned(), + $shape->output, + ), ])->finish(); } } finally { diff --git a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php index fe589f1712..4feda5beed 100644 --- a/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/HashJoinProcessor.php @@ -125,7 +125,7 @@ public function process(Generator $rows, FlowContext $context): Generator } } - $joiner = new Joiner($this->expression, $this->type, $this->batchSize); + $joiner = new Joiner($this->expression, $this->type, $context->backend(), $this->batchSize); $equalityKeys = $joiner->keys(); $resident = $this->rightBuckets->storage() instanceof ResidentBucketsStorage; @@ -161,7 +161,7 @@ public function process(Generator $rows, FlowContext $context): Generator } $nullRightRow = $this->type === Join::left - ? (new NullRowBuilder($rightSchema ?? new Schema()))->rows() + ? (new NullRowBuilder($rightSchema ?? new Schema(), $context->backend()))->rows() : null; $leftRows = $this->tap( @@ -212,7 +212,7 @@ public function process(Generator $rows, FlowContext $context): Generator // only the bucketized path builds it here, the resident path above derives the null-left // row inside the Joiner while streaming $nullLeftRow = $this->type === Join::right - ? (new NullRowBuilder($leftSchema ?? new Schema()))->rows() + ? (new NullRowBuilder($leftSchema ?? new Schema(), $context->backend()))->rows() : null; foreach ($this->bucketPairs() as [$leftBucket, $rightBucket]) { diff --git a/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php b/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php index 30c965fd5d..1b84086f19 100644 --- a/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/MemorySortProcessor.php @@ -41,12 +41,12 @@ public function process(Generator $rows, FlowContext $context): Generator } $maxSize = max($batch->count(), $maxSize); - $buffer[] = $batch->matchTo($this->declared ?? $schema); + $buffer[] = $batch->matchTo($this->declared ?? $schema, $context->backend()); } $all = $buffer === [] - ? Rows::empty($this->declared ?? $schema ?? new Schema()) - : $buffer[0]->concat(...array_slice($buffer, 1)); + ? Rows::empty($this->declared ?? $schema ?? new Schema(), $context->backend()) + : $buffer[0]->concat($context->backend(), ...array_slice($buffer, 1)); yield from $all->sortBy(...$this->refs->all())->chunks($maxSize); } diff --git a/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php b/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php index f9e39b1697..9a80ee6351 100644 --- a/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/RepartitionProcessor.php @@ -11,6 +11,7 @@ use Flow\ETL\Bucketing\KeyGrouping; use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; +use Flow\ETL\Column\Backend; use Flow\ETL\Dataset\Memory\BoundedRead; use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\FlowContext; @@ -43,13 +44,13 @@ public function __construct( */ public function process(Generator $rows, FlowContext $context): Generator { - $grouping = new KeyGrouping(new KeyValues($this->by->all()), $this->hasher); + $grouping = new KeyGrouping(new KeyValues($this->by->all()), $this->hasher, $context->backend()); $bounded = new BoundedRead($this->memoryLimit, $context->backend()); [$read, $fits] = $bounded->read($rows); try { if ($fits) { - yield from $grouping->group($this->concatenated($read)); + yield from $grouping->group($this->concatenated($read, $context->backend())); return; } @@ -84,7 +85,7 @@ public function bind(Schema $input): BoundStep * * @return Generator */ - public function concatenated(array $batches): Generator + public function concatenated(array $batches, Backend $backend): Generator { $parts = []; $schema = null; @@ -95,11 +96,11 @@ public function concatenated(array $batches): Generator } $schema ??= $batch->schema(); - $parts[] = $batch->matchTo($schema); + $parts[] = $batch->matchTo($schema, $backend); } if ($parts !== []) { - yield $parts[0]->concat(...array_slice($parts, 1)); + yield $parts[0]->concat($backend, ...array_slice($parts, 1)); } } } diff --git a/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php b/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php index 534116ee4c..7c2f3f8e7f 100644 --- a/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/TopNProcessor.php @@ -60,8 +60,8 @@ public function process(Generator $rows, FlowContext $context): Generator } $maxSize = max($batch->count(), $maxSize); - $conformed = $batch->matchTo($this->declared ?? $schema); - $kept = $kept === null ? $conformed : $kept->concat($conformed); + $conformed = $batch->matchTo($this->declared ?? $schema, $context->backend()); + $kept = $kept === null ? $conformed : $kept->concat($context->backend(), $conformed); // trimming only past twice the limit keeps the re-sorts amortised if ($kept->count() > (2 * $this->limit)) { @@ -78,7 +78,7 @@ public function process(Generator $rows, FlowContext $context): Generator } if ($kept === null) { - yield from Rows::empty($this->declared ?? $schema ?? new Schema())->chunks($maxSize); + yield from Rows::empty($this->declared ?? $schema ?? new Schema(), $context->backend())->chunks($maxSize); return; } diff --git a/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php b/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php index 118f14916d..1fe4c3cc08 100644 --- a/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/VoidProcessor.php @@ -31,6 +31,6 @@ public function process(Generator $rows, FlowContext $context): Generator } // void() drops rows, not columns - yield Rows::empty($this->declared ?? new Schema()); + yield Rows::empty($this->declared ?? new Schema(), $context->backend()); } } diff --git a/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php b/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php index 1441e28ee1..50c2db02c3 100644 --- a/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php +++ b/src/core/etl/src/Flow/ETL/Processor/WindowProcessor.php @@ -52,7 +52,7 @@ public function process(Generator $rows, FlowContext $context): Generator $bound ??= $this->boundTo($batch->schema()); if (!$batch->count()) { - yield Rows::empty($bound->output); + yield Rows::empty($bound->output, $context->backend()); continue; } @@ -165,7 +165,7 @@ private function processPartition(BoundWindow $bound, Rows $partition, FlowConte $window = $resolved->window(); $orderBy = $window->order(); $sortBy = $orderBy === [] ? $window->partitions()->all() : $orderBy; - $partitionRows = $partition->matchTo($bound->input)->sortBy(...$sortBy); + $partitionRows = $partition->matchTo($bound->input, $context->backend())->sortBy(...$sortBy); $frame = $window->frame(); diff --git a/src/core/etl/src/Flow/ETL/Row/DeclaredColumns.php b/src/core/etl/src/Flow/ETL/Row/DeclaredColumns.php deleted file mode 100644 index 5085fead9e..0000000000 --- a/src/core/etl/src/Flow/ETL/Row/DeclaredColumns.php +++ /dev/null @@ -1,38 +0,0 @@ -> $rows - * - * @return list> - */ - public function project(array $rows, Schema $schema): array - { - $declared = array_flip($schema->references()->names()); - $projected = []; - - foreach ($rows as $row) { - foreach (array_keys(array_diff_key($row, $declared)) as $key) { - if (!is_int($key) || $schema->findDefinition((new ColumnName())->of($key)) === null) { - unset($row[$key]); - } - } - - $projected[] = $row; - } - - return $projected; - } -} diff --git a/src/core/etl/src/Flow/ETL/Rows.php b/src/core/etl/src/Flow/ETL/Rows.php index d9cb9f9100..68f35666d7 100644 --- a/src/core/etl/src/Flow/ETL/Rows.php +++ b/src/core/etl/src/Flow/ETL/Rows.php @@ -6,41 +6,31 @@ use Countable; use Flow\ETL\Column\AdaptiveBackend; +use Flow\ETL\Column\Backend; use Flow\ETL\Column\Column; -use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Hash\Algorithm; -use Flow\ETL\Hash\NativePHPHash; -use Flow\ETL\Join\Expression; -use Flow\ETL\Join\HashJoin\Joiner; -use Flow\ETL\Join\HashJoin\JoinSide; -use Flow\ETL\Join\HashJoin\RowMerger; -use Flow\ETL\Join\Join; -use Flow\ETL\Join\JoinSchema; use Flow\ETL\Row\Reference; -use Flow\ETL\Row\UnresolvedReference; -use Flow\ETL\Rows\RowEquality; -use Flow\ETL\Rows\RowHashes; +use Flow\ETL\Rows\ColumnRetyping; use Flow\ETL\Schema\Formatter\InlineSchemaFormatter; use Flow\ETL\Schema\SimilarNames; use Flow\ETL\Sort\RowOrder; use Flow\Floe\FrameDecoder; use Flow\Floe\FrameEncoder; -use Flow\Types\Exception\InvalidTypeException; use Flow\Types\Value\Json; use Generator; use function array_diff_key; use function array_fill; +use function array_flip; use function array_key_exists; use function array_keys; use function array_shift; -use function array_slice; use function array_values; use function count; -use function Flow\Types\DSL\type_integer; use function implode; use function max; use function min; @@ -69,6 +59,8 @@ public function __serialize(): array } /** + * A serialized batch carries no context, so it decodes in the default backend. + * * @param RowsPayload $data */ public function __unserialize(array $data): void @@ -80,9 +72,8 @@ public function __unserialize(array $data): void $this->count = $rows->count; } - public static function empty(Schema $schema): self + public static function empty(Schema $schema, Backend $backend): self { - $backend = new AdaptiveBackend(); $columns = []; foreach ($schema->definitions() as $name => $definition) { @@ -119,23 +110,14 @@ public static function fromColumns(Schema $schema, array $columns, int $count): } } + $retyping = new ColumnRetyping(); + foreach ($schema->definitions() as $name => $definition) { if ($columns[$name] instanceof ValueColumn) { throw ColumnMismatchException::untypedColumn($definition); } - if (!$definition->isNullable() && $columns[$name]->nullCount() > 0) { - $index = 0; - - while (!$columns[$name]->isNull($index)) { - $index++; - } - - throw new SchemaMismatchException($index, ColumnMismatchException::valueDoesNotMatch( - $definition, - null, - )); - } + $retyping->notNull($definition, $columns[$name]); } return new self($schema, $columns, $count); @@ -187,11 +169,29 @@ public function encodeFrame(): string } /** - * Every input carries this schema; zero-row inputs add no rows. + * The same batch with every column in $backend's storage - itself when $backend already owns every column. + * + * @throws ColumnMismatchException a null under NOT NULL on a column that is copied + */ + public function adoptedBy(Backend $backend): self + { + $columns = []; + $copied = false; + + foreach ($this->schema->definitions() as $name => $definition) { + $columns[$name] = $backend->adopt($definition, $this->columns[$name]); + $copied = $copied || $columns[$name] !== $this->columns[$name]; + } + + return $copied ? new self($this->schema, $columns, $this->count) : $this; + } + + /** + * Every input carries this schema; zero-row inputs add no rows. The result's columns are $backend's. * * @throws InvalidArgumentException */ - public function concat(self ...$others): self + public function concat(Backend $backend, self ...$others): self { $inputs = $this->count > 0 ? [$this] : []; $count = $this->count; @@ -199,7 +199,7 @@ public function concat(self ...$others): self foreach ($others as $other) { if (!$other->schema->isSame($this->schema)) { throw InvalidArgumentException::because( - 'Cannot merge Rows with different schemas: [%s] and [%s]', + 'Cannot concat Rows with different schemas: [%s] and [%s]', (new InlineSchemaFormatter())->format($this->schema), (new InlineSchemaFormatter())->format($other->schema), ); @@ -214,10 +214,9 @@ public function concat(self ...$others): self $head = array_shift($inputs); if ($head === null) { - return self::empty($this->schema); + return $this->adoptedBy($backend); } - $backend = new AdaptiveBackend(); $columns = []; foreach ($this->schema->definitions() as $name => $definition) { @@ -232,7 +231,7 @@ public function concat(self ...$others): self } if ($sameClass) { - $columns[$name] = $first->concat(...$rest); + $columns[$name] = $backend->adopt($definition, $first->concat(...$rest)); continue; } @@ -254,17 +253,6 @@ public function count(): int return $this->count; } - public function diffLeft(self $rows): self - { - return $this->gather((new RowEquality())->notIn($this, $rows, $this->schema)); - } - - public function diffRight(self $rows): self - { - // the surviving rows come from the right side, so the right side's schema describes them - return $rows->gather((new RowEquality())->notIn($rows, $this, $this->schema)); - } - public function drop(int $size): self { if ($size < 0) { @@ -319,88 +307,18 @@ public function gather(array $indices): self return new self($this->schema, $columns, count($indices)); } - public function hash(Algorithm $algorithm = new NativePHPHash()): string - { - return $algorithm->hash(implode('', (new RowHashes())->of($this, $algorithm))); - } - - /** - * @param int $count - Count of rows to return. Must be >= 0. - * - * @throws InvalidArgumentException When count is negative - * @throws InvalidTypeException When count is not an integer */ - public function head(int $count): self - { - $count = type_integer()->assert($count); - - if ($count < 0) { - throw new InvalidArgumentException('Count must be greater than or equal to 0'); - } - - return $this->slice(0, min($count, $this->count)); - } - public function isEmpty(): bool { return $this->count === 0; } - public function joinCross(self $right, string $joinPrefix = 'joined_'): self - { - $schema = (new JoinSchema($joinPrefix))->cross($this->schema, $right->schema); - $left = []; - $rightIndices = []; - - for ($i = 0; $i < $this->count; $i++) { - for ($j = 0; $j < $right->count; $j++) { - $left[] = $i; - $rightIndices[] = $j; - } - } - - return (new RowMerger($joinPrefix)) - ->merge($this->gather($left), $right->gather($rightIndices)) - ->project($schema); - } - - /** - * @throws InvalidArgumentException - */ - public function joinInner(self $right, Expression $expression): self - { - return $this->joinUsing($right, $expression, Join::inner); - } - - /** - * @throws InvalidArgumentException - */ - public function joinLeft(self $right, Expression $expression): self - { - return $this->joinUsing($right, $expression, Join::left); - } - - /** - * @throws InvalidArgumentException - */ - public function joinLeftAnti(self $right, Expression $expression): self - { - return $this->joinUsing($right, $expression, Join::left_anti); - } - - /** - * @throws InvalidArgumentException - */ - public function joinRight(self $right, Expression $expression): self - { - return $this->joinUsing($right, $expression, Join::right); - } - /** - * Adopts $schema, checking every column whose definition it changes (Definition::matches per value). + * Adopts $schema. A changed column whose type change the types prove is restamped; any other change is checked + * value by value and rebuilt in $backend. * * @throws SchemaMismatchException */ - public function matchTo(Schema $schema): self + public function matchTo(Schema $schema, Backend $backend): self { if ($schema->isSame($this->schema)) { return new self($schema, $this->columns, $this->count); @@ -414,116 +332,93 @@ public function matchTo(Schema $schema): self } } - $backend = new AdaptiveBackend(); $columns = []; $changed = []; + $retyping = new ColumnRetyping(); foreach ($schema->definitions() as $name => $definition) { $own = $this->schema->findDefinition($definition->entry()->name()); if ($own === null) { - if (!$definition->isNullable()) { - if ($this->count > 0) { - throw new SchemaMismatchException(0, ColumnMismatchException::missingColumn($definition)); - } - - $columns[$name] = $backend->builder($definition)->finish(); - - continue; - } - - $columns[$name] = $backend->constant($definition, null, $this->count); - - continue; - } - - if ($own->isSame($definition)) { - $columns[$name] = $this->columns[$name]; + $columns[$name] = $retyping->absent($definition, $this->count, $backend); continue; } - $changed[$name] = $definition; - } - - for ($i = 0; $i < $this->count; $i++) { - foreach ($changed as $name => $definition) { - // @mago-ignore analysis:mixed-assignment - $value = $this->columns[$name]->value($i); + $restamped = $retyping->restamped($this->columns[$name], $own, $definition); - if ($value === null ? !$definition->isNullable() : !$definition->matches($value)) { - throw new SchemaMismatchException($i, ColumnMismatchException::valueDoesNotMatch( - $definition, - $value, - )); - } + if ($restamped === null) { + $changed[$name] = [$this->columns[$name], $definition]; } - } - foreach ($changed as $name => $definition) { - try { - $columns[$name] = $this->columns[$name]->withType($definition->type()); - } catch (InvalidArgumentException) { - $builder = $backend->builder($definition); - $builder->appendMany($this->columns[$name]->values()); - $columns[$name] = $builder->finish(); - } + $columns[$name] = $restamped; } - $ordered = []; + $retyping->validate($changed, $this->count); - foreach ($schema->definitions() as $name => $_) { - $ordered[$name] = $columns[$name]; + foreach ($changed as $name => [$column, $definition]) { + $columns[$name] = $retyping->rebuilt($column, $definition, $backend); } - return self::fromColumns($schema, $ordered, $this->count); + /** @var array $columns */ + return self::fromColumns($schema, $columns, $this->count); } /** - * @throws InvalidArgumentException + * Drops the columns $schema does not declare and adopts it, converting a kept column whose definition $schema + * changes (in $backend). Contrast select(), which keeps the named columns as they are. Widening the batch with + * columns it lacks is not a projection - that goes through matchTo(). + * + * @throws SchemaMismatchException */ - public function merge(self $rows): self + public function project(Schema $schema, Backend $backend): self { - if ($this->isEmpty()) { - return $rows; - } + $definitions = []; + $columns = []; - if ($rows->isEmpty()) { - return $this; - } + foreach ($schema->definitions() as $name => $definition) { + $own = $this->schema->findDefinition($definition->entry()->name()); - if (!$this->schema->isSame($rows->schema())) { - throw InvalidArgumentException::because( - 'Cannot merge Rows with different schemas: [%s] and [%s]', - (new InlineSchemaFormatter())->format($this->schema), - (new InlineSchemaFormatter())->format($rows->schema), - ); + if ($own !== null) { + $definitions[] = $own; + $columns[$name] = $this->columns[$name]; + } } - return $this->concat($rows); + return (new self(new Schema(...$definitions), $columns, $this->count))->matchTo($schema, $backend); } /** - * Drops the columns $schema does not declare and adopts it. Widening or retyping the batch is - * not a projection - that goes through matchTo(). + * The named columns as they are, in schema order - every column kept unconverted, in whatever backend built it. + * Contrast project(), which adopts a given schema and converts the columns it changes. * - * @throws SchemaMismatchException + * @throws SchemaDefinitionNotFoundException */ - public function project(Schema $schema): self + public function select(string ...$names): self { + $keep = array_flip($names); $definitions = []; $columns = []; - foreach ($schema->definitions() as $name => $definition) { - $own = $this->schema->findDefinition($definition->entry()->name()); - - if ($own !== null) { - $definitions[] = $own; + foreach ($this->schema->definitions() as $name => $definition) { + if (array_key_exists($definition->entry()->name(), $keep)) { + $definitions[] = $definition; $columns[$name] = $this->columns[$name]; } } - return (new self(new Schema(...$definitions), $columns, $this->count))->matchTo($schema); + if (count($definitions) !== count($keep)) { + foreach ($names as $selected) { + if ($this->schema->findDefinition($selected) === null) { + throw SchemaDefinitionNotFoundException::withAvailable( + $selected, + ...$this->schema->references()->names(), + ); + } + } + } + + return new self(new Schema(...$definitions), $columns, $this->count); } /** @@ -549,17 +444,6 @@ public function remove(int $offset): self return $this->gather(array_values(array_diff_key(range(0, $this->count - 1), [$offset => true]))); } - public function reverse(): self - { - $indices = []; - - for ($i = $this->count - 1; $i >= 0; $i--) { - $indices[] = $i; - } - - return $this->gather($indices); - } - public function schema(): Schema { return $this->schema; @@ -588,16 +472,6 @@ public function slice(int $offset, int $length): self return new self($this->schema, $columns, $length); } - /** - * @throws InvalidArgumentException - */ - public function sortAscending(string|Reference $reference): self - { - return $this->sortBy( - (new UnresolvedReference($reference instanceof Reference ? $reference->base() : $reference))->asc(), - ); - } - /** * @throws InvalidArgumentException */ @@ -612,36 +486,6 @@ public function sortBy(Reference ...$references): self return $this->gather($order->permutation($order->keys($this), $this->count)); } - /** - * @throws InvalidArgumentException - */ - public function sortDescending(string|Reference $reference): self - { - return $this->sortBy( - (new UnresolvedReference($reference instanceof Reference ? $reference->base() : $reference))->desc(), - ); - } - - /** - * @param int $count - Count of rows to return. Must be >= 0. - * - * @throws InvalidArgumentException When count is negative - * @throws InvalidTypeException When count is not an integer */ - public function tail(int $count): self - { - $count = type_integer()->assert($count); - - if ($count < 0) { - throw new InvalidArgumentException('Count must be greater than or equal to 0'); - } - - if ($count >= $this->count) { - return $this; - } - - return $this->slice($this->count - $count, $count); - } - public function take(int $size): self { if ($size < 0) { @@ -651,15 +495,6 @@ public function take(int $size): self return $this->slice(0, min($size, $this->count)); } - public function takeRight(int $size): self - { - if ($size < 0) { - throw new InvalidArgumentException('Size must be greater than or equal to 0'); - } - - return $this->slice($this->count - min($size, $this->count), min($size, $this->count))->reverse(); - } - /** * @return array> */ @@ -682,11 +517,6 @@ public function toArray(bool $withKeys = true): array return $array; } - public function unique(): self - { - return $this->gather((new RowEquality())->unique($this)); - } - /** * @throws InvalidArgumentException * @@ -742,6 +572,7 @@ public function withColumns(Schema $schema, array $columns): self * Positional restamp: the n-th definition of $schema retypes the n-th column (Column::withType). * * @throws ColumnMismatchException + * @throws SchemaMismatchException a null under a NOT NULL definition, at its row * @throws InvalidArgumentException */ public function withSchema(Schema $schema): self @@ -757,13 +588,11 @@ public function withSchema(Schema $schema): self $columns = array_values($this->columns); $retyped = []; $position = 0; + $retyping = new ColumnRetyping(); foreach ($schema->definitions() as $name => $definition) { $column = $columns[$position++]; - - if (!$definition->isNullable() && $column->nullCount() > 0) { - throw ColumnMismatchException::valueDoesNotMatch($definition, null); - } + $retyping->notNull($definition, $column); try { $retyped[$name] = $column->withType($definition->type()); @@ -774,25 +603,4 @@ public function withSchema(Schema $schema): self return new self($schema, $retyped, $this->count); } - - /** - * @throws InvalidArgumentException - */ - private function joinUsing(self $right, Expression $expression, Join $type): self - { - $single = static function (self $rows): Generator { - yield $rows; - }; - - $joiner = new Joiner($expression, $type); - $joined = []; - - foreach ($joiner->join(JoinSide::of($single($this)), JoinSide::of($single($right))) as $batch) { - $joined[] = $batch; - } - - return $joined === [] - ? self::empty($joiner->schema($this->schema, $right->schema)) - : $joined[0]->concat(...array_slice($joined, 1)); - } } diff --git a/src/core/etl/src/Flow/ETL/Rows/ColumnRetyping.php b/src/core/etl/src/Flow/ETL/Rows/ColumnRetyping.php new file mode 100644 index 0000000000..93de4105b1 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Rows/ColumnRetyping.php @@ -0,0 +1,139 @@ + $definition + * + * @throws SchemaMismatchException + */ + public function absent(Definition $definition, int $count, Backend $backend): Column + { + if (!$definition->isNullable()) { + if ($count > 0) { + throw new SchemaMismatchException(0, ColumnMismatchException::missingColumn($definition)); + } + + return $backend->builder($definition)->finish(); + } + + return $backend->constant($definition, null, $count); + } + + /** + * $column under $definition for a declared schema over another frame's batch: restamped when the types prove the + * change, otherwise cast value by value into $backend - a value the definition does not take is cast, not refused. + * Contrast validate(), which refuses it. + * + * @param Definition $own + * @param Definition $definition + * + * @throws SchemaMismatchException a value the cast refuses, at its row + */ + public function cast(Column $column, Definition $own, Definition $definition, Backend $backend): Column + { + return $this->restamped($column, $own, $definition) ?? $this->rebuilt($column, $definition, $backend); + } + + /** + * Refuses the first null of $column when $definition is NOT NULL. + * + * @param Definition $definition + * + * @throws SchemaMismatchException + */ + public function notNull(Definition $definition, Column $column): void + { + if ($definition->isNullable() || $column->nullCount() === 0) { + return; + } + + $index = 0; + + while (!$column->isNull($index)) { + $index++; + } + + throw new SchemaMismatchException($index, ColumnMismatchException::valueDoesNotMatch($definition, null)); + } + + /** + * $column's values built anew under $definition in $backend. + * + * @param Definition $definition + * + * @throws SchemaMismatchException + */ + public function rebuilt(Column $column, Definition $definition, Backend $backend): Column + { + $builder = $backend->builder($definition); + $builder->appendMany($column->values()); + + return $builder->finish(); + } + + /** + * $column as it is when $own is $definition, restamped when the types prove the change and no null breaks a NOT NULL + * definition, null otherwise - the caller then casts or validates it. + * + * @param Definition $own + * @param Definition $definition + */ + public function restamped(Column $column, Definition $own, Definition $definition): ?Column + { + if ($own->isSame($definition)) { + return $column; + } + + if (!$definition->isNullable() && $column->nullCount() > 0) { + return null; + } + + return (new Retype())->proves($column->type(), $definition->type()) + ? $column->withType($definition->type()) + : null; + } + + /** + * Rows::matchTo()'s check of the columns restamped() could not prove: every value must already be one its + * definition takes - nothing is cast. One row-major scan, so the refusal names the lowest bad row and, within it, + * the first column in the given order. Contrast cast(), which converts such values instead. + * + * @param array}> $changed by name, in schema order + * + * @throws SchemaMismatchException + */ + public function validate(array $changed, int $count): void + { + for ($i = 0; $i < $count; $i++) { + foreach ($changed as [$column, $definition]) { + // @mago-ignore analysis:mixed-assignment + $value = $column->value($i); + + if ($value === null ? !$definition->isNullable() : !$definition->matches($value)) { + throw new SchemaMismatchException($i, ColumnMismatchException::valueDoesNotMatch( + $definition, + $value, + )); + } + } + } + } +} diff --git a/src/core/etl/src/Flow/ETL/Rows/RowEquality.php b/src/core/etl/src/Flow/ETL/Rows/RowEquality.php deleted file mode 100644 index ea9423627c..0000000000 --- a/src/core/etl/src/Flow/ETL/Rows/RowEquality.php +++ /dev/null @@ -1,161 +0,0 @@ - - */ - public function bucketKeys(Rows $rows, Schema $schema): array - { - $comparable = new ComparableValues(); - $exact = []; - - foreach ($schema->definitions() as $name => $definition) { - if ( - $comparable->orderedByPhysical($definition->type()) - && $rows->schema()->findDefinition($name) !== null - ) { - $exact[] = $name; - } - } - - if ($exact === [] || $rows->isEmpty()) { - // @mago-ignore analysis:possibly-invalid-argument - return $rows->isEmpty() ? [] : array_fill(0, $rows->count(), ''); - } - - return (new RowHashes())->of($rows->project($rows->schema()->keep(...$exact))); - } - - /** - * @return array> - */ - public function columns(Rows $rows): array - { - $values = []; - - foreach ($rows->columns() as $name => $column) { - $values[$name] = $column->values(); - } - - return $values; - } - - /** - * @param array> $types - * @param array> $left - * @param array> $right - */ - public function equal(array $types, array $left, int $i, array $right, int $j): bool - { - foreach ($types as $name => $type) { - if (!array_key_exists($name, $left) || !array_key_exists($name, $right)) { - continue; - } - - if (!$this->comparator->equals($type, $left[$name][$i], $right[$name][$j])) { - return false; - } - } - - return true; - } - - /** - * @return list rows of $rows with no equal row in $other, compared by $schema's types - */ - public function notIn(Rows $rows, Rows $other, Schema $schema): array - { - $values = $this->columns($rows); - $others = $this->columns($other); - - if (array_keys($values) !== array_keys($others)) { - // @mago-ignore analysis:possibly-invalid-argument - return $rows->isEmpty() ? [] : array_keys(array_fill(0, $rows->count(), true)); - } - - $types = $this->types($schema); - - /** @var array> $buckets */ - $buckets = []; - - foreach ($this->bucketKeys($other, $schema) as $j => $key) { - $buckets[$key][] = $j; - } - - $kept = []; - - foreach ($this->bucketKeys($rows, $schema) as $i => $key) { - foreach ($buckets[$key] ?? [] as $j) { - if ($this->equal($types, $values, $i, $others, $j)) { - continue 2; - } - } - - $kept[] = $i; - } - - return $kept; - } - - /** - * @return array> - */ - public function types(Schema $schema): array - { - $types = []; - - foreach ($schema->definitions() as $name => $definition) { - $types[$name] = $definition->type(); - } - - return $types; - } - - /** - * @return list the first row of every group of equal rows - */ - public function unique(Rows $rows): array - { - $values = $this->columns($rows); - $types = $this->types($rows->schema()); - - /** @var array> $buckets */ - $buckets = []; - $kept = []; - - foreach ($this->bucketKeys($rows, $rows->schema()) as $i => $key) { - foreach ($buckets[$key] ?? [] as $j) { - if ($this->equal($types, $values, $i, $values, $j)) { - continue 2; - } - } - - $buckets[$key][] = $i; - $kept[] = $i; - } - - return $kept; - } -} diff --git a/src/core/etl/src/Flow/ETL/Rows/RowHashes.php b/src/core/etl/src/Flow/ETL/Rows/RowHashes.php index 73e7f44ae4..c0a1b8d075 100644 --- a/src/core/etl/src/Flow/ETL/Rows/RowHashes.php +++ b/src/core/etl/src/Flow/ETL/Rows/RowHashes.php @@ -4,6 +4,8 @@ namespace Flow\ETL\Rows; +use Flow\ETL\Bucketing\NativeHasher; +use Flow\ETL\Column\ComparableValues; use Flow\ETL\Hash\Algorithm; use Flow\ETL\Hash\NativePHPHash; use Flow\ETL\Rows; @@ -15,7 +17,8 @@ final readonly class RowHashes { /** - * One hash per row over its values in sorted column order - name followed by the formatted value. + * One hash per row over its values in sorted column order - name followed by the value's equality form + * (ComparableValues) where the column has one, its formatted value otherwise. * * @return list */ @@ -26,15 +29,26 @@ public function of(Rows $rows, Algorithm $algorithm = new NativePHPHash()): arra } $formatter = new TypedValueFormatter(); + $comparable = new ComparableValues(); // @mago-ignore analysis:possibly-invalid-argument $strings = array_fill(0, $rows->count(), ''); foreach ($rows->schema()->sort()->definitions() as $definition) { $name = $definition->entry()->name(); $type = $definition->type(); + $column = $rows->column($name); + + if ($comparable->equalByPhysical($type)) { + // @mago-ignore analysis:mixed-assignment + foreach ($comparable->equality($column) as $i => $value) { + $strings[$i] .= $name . NativeHasher::normalize($value); + } + + continue; + } // @mago-ignore analysis:mixed-assignment - foreach ($rows->column($name)->values() as $i => $value) { + foreach ($column->values() as $i => $value) { $strings[$i] .= $name . $formatter->format($type, $value); } } diff --git a/src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php b/src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php deleted file mode 100644 index eb29710ffa..0000000000 --- a/src/core/etl/src/Flow/ETL/Rows/RowsBuffer.php +++ /dev/null @@ -1,79 +0,0 @@ - $size - */ - public function __construct( - private readonly Schema $schema, - private readonly Backend $backend, - private readonly int $size, - ) { - // @mago-ignore analysis:invalid-operand - // @mago-ignore analysis:impossible-condition,redundant-comparison - if ($this->size < 1) { - throw new InvalidArgumentException('Buffer size must be greater than 0, given: ' . $this->size); - } - - $this->builder = new RowsBuilder($this->schema, $this->backend); - } - - /** - * @param array $row - * - * @throws SchemaMismatchException - */ - public function append(array $row): ?Rows - { - $this->builder->append($row); - - return $this->builder->count() >= $this->size ? $this->flush() : null; - } - - /** - * @throws SchemaMismatchException - */ - public function appendFrom(Rows $rows, int $i): ?Rows - { - $this->builder->appendFrom($rows, $i); - - return $this->builder->count() >= $this->size ? $this->flush() : null; - } - - /** - * A take that overshoots the size is released whole. - * - * @param list $indices - */ - public function appendTake(Rows $rows, array $indices): ?Rows - { - $this->builder->appendTake($rows, $indices); - - return $this->builder->count() >= $this->size ? $this->flush() : null; - } - - public function flush(): ?Rows - { - if ($this->builder->count() === 0) { - return null; - } - - $batch = $this->builder->finish(); - $this->builder = new RowsBuilder($this->schema, $this->backend); - - return $batch; - } -} diff --git a/src/core/etl/src/Flow/ETL/Rows/RowsBuilder.php b/src/core/etl/src/Flow/ETL/Rows/RowsBuilder.php index e4758a91ed..0c42e4dcba 100644 --- a/src/core/etl/src/Flow/ETL/Rows/RowsBuilder.php +++ b/src/core/etl/src/Flow/ETL/Rows/RowsBuilder.php @@ -10,13 +10,19 @@ use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; +use Flow\ETL\Row\ColumnName; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; +use function array_diff_key; use function array_key_exists; +use function array_values; use function count; +use function Flow\Types\DSL\type_array; use function implode; +use function is_array; +use function is_int; use function sprintf; final class RowsBuilder @@ -193,6 +199,102 @@ public function appendFrom(Rows $rows, int $i): self return $this; } + /** + * Records projected onto the schema: a key it does not declare is dropped, an int key is kept under its positional + * name (ColumnName) when the schema declares that name. + * + * @param array> $rows + * + * @throws SchemaMismatchException + */ + public function appendProjected(array $rows): self + { + $definitions = $this->schema->definitions(); + $columnName = new ColumnName(); + $maps = []; + + foreach ($rows as $row) { + $map = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($row as $key => $value) { + if (array_key_exists($key, $definitions)) { + $map[$key] = $value; + + continue; + } + + if (is_int($key) && $this->schema->findDefinition($name = $columnName->of($key)) !== null) { + $map[$name] = $value; + } + } + + $maps[] = $map; + } + + return $this->appendRows($maps); + } + + /** + * One record or a list of them. A key the schema does not declare is refused at its row; a numeric-string key + * PHP turned into an int keeps its declared name, any other int key is named by its position (ColumnName). + * + * @param array $data + * + * @throws SchemaMismatchException + */ + public function appendRecords(array $data): self + { + $isRows = true; + + // @mago-ignore analysis:mixed-assignment + foreach ($data as $v) { + if (!is_array($v)) { + $isRows = false; + + break; + } + } + + $definitions = $this->schema->definitions(); + $columnName = new ColumnName(); + $maps = []; + + // @mago-ignore analysis:mixed-assignment + foreach (array_values($isRows ? $data : [$data]) as $index => $row) { + $row = type_array()->assert($row); + + if (array_diff_key($row, $definitions) === []) { + $maps[] = $row; + + continue; + } + + $map = []; + + // @mago-ignore analysis:mixed-assignment + foreach ($row as $key => $value) { + // PHP gives back a numeric-string column name as an int key, which the positional rule + // would rename to eNN. A declared schema naming that column settles which one it is. + $declared = $this->schema->findDefinition((string) $key); + $name = $declared === null ? $columnName->of($key) : (string) $key; + + if ($declared === null && $this->schema->findDefinition($name) === null) { + throw new SchemaMismatchException( + $this->count + $index, + ColumnMismatchException::unexpectedColumn($name), + ); + } + + $map[$name] = $value; + } + + $maps[] = $map; + } + + return $this->appendRows($maps); + } + /** * @param list> $rows name-keyed; a declared key a row lacks is null, or a missing column * under NOT NULL; a key the schema lacks is ignored diff --git a/src/core/etl/src/Flow/ETL/Sort/ExternalSort.php b/src/core/etl/src/Flow/ETL/Sort/ExternalSort.php index 5a5ef3f917..211644d330 100644 --- a/src/core/etl/src/Flow/ETL/Sort/ExternalSort.php +++ b/src/core/etl/src/Flow/ETL/Sort/ExternalSort.php @@ -7,6 +7,7 @@ use Flow\ETL\Bucketing\Bucket; use Flow\ETL\Bucketing\BucketRun; use Flow\ETL\Bucketing\Buckets; +use Flow\ETL\Column\Backend; use Flow\ETL\Dataset\Memory\MemoryBudget; use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\InvalidArgumentException; @@ -82,11 +83,11 @@ public function sort(Generator $rows, FlowContext $context, ?int $limit = null): } $schema ??= $batch->schema(); - $buffer[] = $batch->matchTo($schema); + $buffer[] = $batch->matchTo($schema, $context->backend()); // the whole process, not this buffer: another spilling step in the pipeline holds memory too if ($budget->exceeded()) { - $runs[] = $this->spill($this->sorted($buffer, $limit), $runId, count($runs)); + $runs[] = $this->spill($this->sorted($buffer, $limit, $context->backend()), $runId, count($runs)); $buffer = []; $budget->released(); } @@ -94,17 +95,17 @@ public function sort(Generator $rows, FlowContext $context, ?int $limit = null): if ($runs === []) { if ($buffer !== []) { - yield from $this->sorted($buffer, $limit)->chunks($this->batchSize); + yield from $this->sorted($buffer, $limit, $context->backend())->chunks($this->batchSize); } return; } if ($buffer !== []) { - $runs[] = $this->spill($this->sorted($buffer, $limit), $runId, count($runs)); + $runs[] = $this->spill($this->sorted($buffer, $limit, $context->backend()), $runId, count($runs)); } - $merger = new KWayMerge($this->refs, $this->batchSize); + $merger = new KWayMerge($this->refs, $context->backend(), $this->batchSize); $mergedIndex = 0; // each pass merges neighbouring runs in place, so equal keys keep the order they arrived in @@ -184,9 +185,9 @@ public function reduce(array $group, KWayMerge $merger, int $index, ?int $limit) * @param list $buffer * @param null|int $limit */ - public function sorted(array $buffer, ?int $limit): Rows + public function sorted(array $buffer, ?int $limit, Backend $backend): Rows { - $sorted = $buffer[0]->concat(...array_slice($buffer, 1))->sortBy(...$this->refs->all()); + $sorted = $buffer[0]->concat($backend, ...array_slice($buffer, 1))->sortBy(...$this->refs->all()); return $limit === null ? $sorted : $sorted->take($limit); } diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/BucketCursor.php b/src/core/etl/src/Flow/ETL/Sort/Merge/BucketCursor.php index e585c38b6e..26aee60f75 100644 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/BucketCursor.php +++ b/src/core/etl/src/Flow/ETL/Sort/Merge/BucketCursor.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Sort\Merge; +use Flow\ETL\Column\Backend; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Sort\RowOrder; @@ -31,8 +32,9 @@ final class BucketCursor public function __construct( private readonly Generator $batches, private readonly RowOrder $order, + private readonly Backend $backend, ) { - $this->batch = Rows::empty(new Schema()); + $this->batch = Rows::empty(new Schema(), $this->backend); $this->load(); } @@ -102,7 +104,7 @@ private function load(): void $this->batches->next(); } - $this->batch = Rows::empty(new Schema()); + $this->batch = Rows::empty(new Schema(), $this->backend); $this->keys = []; } } diff --git a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php index 3db6dd4364..6fea1d724e 100644 --- a/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php +++ b/src/core/etl/src/Flow/ETL/Sort/Merge/KWayMerge.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Sort\Merge; use Flow\ETL\Bucketing\BucketRun; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Row\References; use Flow\ETL\Rows; @@ -23,6 +24,7 @@ */ public function __construct( private References $refs, + private Backend $backend, private int $batchSize = 1000, ) { // @mago-ignore analysis:invalid-operand @@ -50,7 +52,7 @@ public function merge(array $runs): Generator $schema = null; foreach ($runs as $run) { - $cursor = new BucketCursor($run->rows(), $order); + $cursor = new BucketCursor($run->rows(), $order, $this->backend); if ($cursor->valid()) { $schema ??= $cursor->schema(); @@ -59,7 +61,7 @@ public function merge(array $runs): Generator } $schema ??= new Schema(); - $pending = Rows::empty($schema); + $pending = Rows::empty($schema, $this->backend); while ($cursors !== []) { $frontier = 0; @@ -96,14 +98,17 @@ public function merge(array $runs): Generator $slices[] = $cursor ->batch() ->slice($from, $to - $from) - ->matchTo($schema); + ->matchTo($schema, $this->backend); $cursor->advance($to); } } $cursors = array_values(array_filter($cursors, static fn(BucketCursor $cursor): bool => $cursor->valid())); - $block = $slices[0]->concat(...array_slice($slices, 1)); - $pending = $pending->concat($block->gather($order->permutation($order->keys($block), $block->count()))); + $block = $slices[0]->concat($this->backend, ...array_slice($slices, 1)); + $pending = $pending->concat( + $this->backend, + $block->gather($order->permutation($order->keys($block), $block->count())), + ); while ($pending->count() >= $this->batchSize) { yield $pending->slice(0, $this->batchSize); diff --git a/src/core/etl/src/Flow/ETL/Transformer/CrossJoinRowsTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/CrossJoinRowsTransformer.php index f3a65924eb..70a9b32f6e 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/CrossJoinRowsTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/CrossJoinRowsTransformer.php @@ -10,6 +10,7 @@ use Flow\ETL\Executor\PhysicalPlan; use Flow\ETL\FlowContext; use Flow\ETL\Join\JoinSchema; +use Flow\ETL\Join\RowsJoin; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; @@ -35,7 +36,7 @@ public function transform(Rows $rows, FlowContext $context): Rows $context->telemetry()->transformationStarted($this); try { - $result = $rows->joinCross($this->rows(), $this->prefix); + $result = (new RowsJoin($context->backend()))->cross($rows, $this->rows(), $this->prefix); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php b/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php index fc80a9a6ef..85e014fa4b 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DerivedColumns.php @@ -6,9 +6,9 @@ use Flow\ETL\Column\Backend; use Flow\ETL\Column\Column; -use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Rows; +use Flow\ETL\Rows\ColumnRetyping; use Flow\ETL\Schema; use Flow\ETL\Schema\Definition; @@ -36,15 +36,7 @@ public function declare(Schema $input, Definition $derived): Schema */ public function stored(Definition $derived, Column $column, Backend $backend): Column { - if (!$derived->isNullable() && $column->nullCount() > 0) { - $index = 0; - - while (!$column->isNull($index)) { - $index++; - } - - throw new SchemaMismatchException($index, ColumnMismatchException::valueDoesNotMatch($derived, null)); - } + (new ColumnRetyping())->notNull($derived, $column); if (type_bare($column->type())->normalize() === type_bare($derived->type())->normalize()) { return $backend->adopt($derived, $column->withType($derived->type())); @@ -56,10 +48,16 @@ public function stored(Definition $derived, Column $column, Backend $backend): C return $builder->finish(); } - public function rows(Rows $input, Schema $declared, Schema $output, string $name, Column $derived): Rows - { + public function rows( + Rows $input, + Schema $declared, + Schema $output, + string $name, + Column $derived, + Backend $backend, + ): Rows { $withDerived = $input->withColumns($declared, [$name => $derived]); - return $declared->isSame($output) ? $withDerived : $withDerived->matchTo($output); + return $declared->isSame($output) ? $withDerived : $withDerived->matchTo($output, $backend); } } diff --git a/src/core/etl/src/Flow/ETL/Transformer/DropEntriesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DropEntriesTransformer.php index 0b5f892af4..fd270b3ec0 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DropEntriesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DropEntriesTransformer.php @@ -34,7 +34,7 @@ public function transform(Rows $rows, FlowContext $context): Rows try { $schema = $rows->schema()->gracefulRemove(...$this->refs); - $result = $rows->project($schema); + $result = $rows->project($schema, $context->backend()); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php index 6a850c7309..5b06777d2d 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/DuplicateRowTransformer.php @@ -98,9 +98,12 @@ public function transform(Rows $rows, FlowContext $context): Rows } } - $rows = $rows->project($output)->concat($copies->project($output))->gather($interleaved); + $rows = $rows + ->project($output, $context->backend()) + ->concat($context->backend(), $copies->project($output, $context->backend())) + ->gather($interleaved); } else { - $rows = $rows->project($output); + $rows = $rows->project($output, $context->backend()); } $context->telemetry()->transformationCompleted($this, [ diff --git a/src/core/etl/src/Flow/ETL/Transformer/JoinEachRowsTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/JoinEachRowsTransformer.php index f585240fbc..2676a4eef0 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/JoinEachRowsTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/JoinEachRowsTransformer.php @@ -12,6 +12,7 @@ use Flow\ETL\FlowContext; use Flow\ETL\Join\Expression; use Flow\ETL\Join\Join; +use Flow\ETL\Join\RowsJoin; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Transformer; @@ -65,11 +66,13 @@ public function transform(Rows $rows, FlowContext $context): Rows try { $rightRows = $this->factory->from($rows)->fetch(); + $join = new RowsJoin($context->backend()); + $result = match ($this->type) { - Join::left => $rows->joinLeft($rightRows, $this->expression), - Join::left_anti => $rows->joinLeftAnti($rightRows, $this->expression), - Join::right => $rows->joinRight($rightRows, $this->expression), - default => $rows->joinInner($rightRows, $this->expression), + Join::left => $join->left($rows, $rightRows, $this->expression), + Join::left_anti => $join->leftAnti($rows, $rightRows, $this->expression), + Join::right => $join->right($rows, $rightRows, $this->expression), + default => $join->inner($rows, $rightRows, $this->expression), }; $context->telemetry()->transformationCompleted($this, [ diff --git a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php index 49c9fb549c..008a90be5b 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/NestedExpandTransformer.php @@ -75,6 +75,7 @@ private function map(Rows $rows, FlowContext $context, Definition $derived): Row $this->output, $derived->entry()->name(), $builder->finish(), + $context->backend(), ); } diff --git a/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php index e2d335ae42..29037ea755 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/PruneEntriesTransformer.php @@ -55,7 +55,7 @@ public function transform(Rows $rows, FlowContext $context): Rows } $schema = $rows->schema()->keep(...$present)->reorder(...$present); - $result = $rows->project($schema); + $result = $rows->project($schema, $context->backend()); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php index d3d0430423..a182cd3116 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/ScalarFunctionTransformer.php @@ -165,6 +165,7 @@ private function map(Rows $rows, FlowContext $context): Rows $output, $derived->entry()->name(), $builder->finish(), + $context->backend(), ); } @@ -174,6 +175,7 @@ private function map(Rows $rows, FlowContext $context): Rows $output, $derived->entry()->name(), $columns->stored($derived, $column, $context->backend()), + $context->backend(), ); } diff --git a/src/core/etl/src/Flow/ETL/Transformer/SelectEntriesTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/SelectEntriesTransformer.php index eaadb6a5b1..582693946d 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/SelectEntriesTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/SelectEntriesTransformer.php @@ -34,7 +34,7 @@ public function transform(Rows $rows, FlowContext $context): Rows try { $schema = $rows->schema()->keep(...$this->refs)->reorder(...$this->refs); - $result = $rows->project($schema); + $result = $rows->project($schema, $context->backend()); $context->telemetry()->transformationCompleted($this, [ TelemetryAttributes::ATTR_TRANSFORMATION_INPUT_ROWS => $rows->count(), diff --git a/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php b/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php index 0a9b0ed3c0..ee06fb5e51 100644 --- a/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php +++ b/src/core/etl/src/Flow/ETL/Transformer/UntilTransformer.php @@ -50,7 +50,7 @@ public function transform(Rows $rows, FlowContext $context): Rows TelemetryAttributes::ATTR_TRANSFORMATION_OUTPUT_ROWS => 0, ]); - throw new LimitReachedException(0, Rows::empty($rows->schema())); + throw new LimitReachedException(0, Rows::empty($rows->schema(), $context->backend())); } // the unbound path has no plan to hold the resolved predicate, so it is memoised here - diff --git a/src/core/etl/src/Flow/ETL/Window/WindowContext.php b/src/core/etl/src/Flow/ETL/Window/WindowContext.php index 81712789dd..d70fbe6cd7 100644 --- a/src/core/etl/src/Flow/ETL/Window/WindowContext.php +++ b/src/core/etl/src/Flow/ETL/Window/WindowContext.php @@ -32,7 +32,7 @@ public function frame(): Rows [$start, $end] = $this->windowFrame->bounds($this->index, $this->partition); $this->frame = $start > $end - ? Rows::empty($this->partition->schema()) + ? Rows::empty($this->partition->schema(), $this->flowContext->backend()) : $this->partition->slice($start, $end - $start + 1); } diff --git a/src/core/etl/src/Flow/Floe/DSL/functions.php b/src/core/etl/src/Flow/Floe/DSL/functions.php index b277ea5289..e607c94ff5 100644 --- a/src/core/etl/src/Flow/Floe/DSL/functions.php +++ b/src/core/etl/src/Flow/Floe/DSL/functions.php @@ -7,6 +7,7 @@ use Flow\Documentation\Attribute\DocumentationDSL; use Flow\Documentation\Attribute\Module; use Flow\Documentation\Attribute\Type as DSLType; +use Flow\ETL\Column\Backend; use Flow\ETL\Schema\Metadata; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -65,11 +66,12 @@ function floe_options(int $buffer_size = 65536, Codec $codec = new NoopCodec()): function merge_floe( array $sources, string|Path $dest, + Backend $backend, bool $compact = false, ?Metadata $metadata = null, Filesystem $filesystem = new NativeLocalFilesystem(), ): void { - (new FloeMerger($filesystem))->merge( + (new FloeMerger($filesystem, $backend))->merge( array_map(static fn(string|Path $source): Path => is_string($source) ? path_real($source) : $source, $sources), is_string($dest) ? path($dest) : $dest, $compact, diff --git a/src/core/etl/src/Flow/Floe/FloeExtractor.php b/src/core/etl/src/Flow/Floe/FloeExtractor.php index 0bc366ecd8..b612fe975b 100644 --- a/src/core/etl/src/Flow/Floe/FloeExtractor.php +++ b/src/core/etl/src/Flow/Floe/FloeExtractor.php @@ -4,22 +4,23 @@ namespace Flow\Floe; -use Flow\ETL\Column\AdaptiveBackend; -use Flow\ETL\Column\Backend; -use Flow\ETL\Exception\InferredSchemaException; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; -use Flow\ETL\Extractor\FileExtractor; -use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\DerivedSchema; +use Flow\ETL\Extractor\File\FileExtractor; +use Flow\ETL\Extractor\File\FileReading; +use Flow\ETL\Extractor\File\FileReadLoop; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\ReadWindow; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; +use Flow\ETL\Rows; use Flow\ETL\Schema; -use Flow\ETL\Schema\Validator\StrictValidator; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; @@ -29,6 +30,7 @@ use Generator; use function iterator_count; +use function iterator_to_array; use function sprintf; final class FloeExtractor implements @@ -74,75 +76,27 @@ public function isRepeatable(): bool } /** - * @return \Generator + * @return Generator */ public function extract(FlowContext $context, ?int $limit = null, Filter $pathFilter = new OnlyFiles()): Generator { - $fileOffset = $this->offset ?? 0; - $yielded = 0; - // every file is read under the first file's schema, or the union of all of them - $expected = $this->derivedSchema($this->files(), $this->unionByName); - $target = $this->schema(); - $fileColumns = $this->fileColumns($this->filesystem, $this->path); - foreach ($this->files($context->backend(), $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 { - $fileRows = $file->reader->totalRows(); - - if ($fileOffset >= $fileRows) { - $fileOffset -= $fileRows; - - continue; - } - - if (!$this->unionByName) { - $validation = (new StrictValidator())->validate($expected, $file->schema()); - - if (!$validation->isValid()) { - throw InferredSchemaException::filesDiverge( - $file->source()->uri(), - $this->derivedFrom, - $validation, - ); - } - } - - // R6: over the FILE's schema, never over schema()'s output - $fileSchema = $fileColumns->declare($file->schema()); - $constants = $fileColumns->forFile($file->source(), $fileSchema); - $matchTo = !$fileSchema->isSame($target) ? $target : null; - $remaining = $limit === null ? null : $limit - $yielded; - - foreach ($file->reader->rows($this->batchSize(), $fileOffset, $remaining) as $rows) { - // R7: the stamp stays after decoding - FloeStreamReader::rows() yields built Rows and must not - // learn about paths - but the constants are the shared ones, already typed - $rows = $constants->fillRows($rows, $fileSchema, $context->backend()); - - if ($matchTo !== null) { - $rows = $rows->matchTo($matchTo); - } - - $yielded += $rows->count(); - - $signal = yield $rows; - - if ($signal === Signal::STOP) { - return; - } - - if ($limit !== null && $yielded >= $limit) { - return; - } - } - - $fileOffset = 0; - } finally { - $file->close(); - } - } + yield from (new FileReadLoop($fileColumns, $this->schema()))->read( + iterator_to_array($this->sourceFiles($this->filesystem, $this->path, $pathFilter), false), + new FloeFileBatches( + $this->filesystem, + $this->codec, + $this->chunkSize, + $fileColumns, + $this->unionByName + ? null + : new DerivedSchema($this->derivedSchema($this->files(), $this->unionByName), $this->derivedFrom), + ), + $this->batchSize(), + $context->backend(), + new ReadWindow($this->offset ?? 0, $limit), + ); } /** @@ -211,15 +165,16 @@ private function declare(): Statistics /** * @return Generator */ - private function files(Backend $backend = new AdaptiveBackend(), Filter $pathFilter = new OnlyFiles()): Generator + private function files(): Generator { - foreach ($this->sourceFiles($this->filesystem, $this->path, $pathFilter) as $source) { + foreach ($this->sourceFiles($this->filesystem, $this->path) as $source) { yield new FloeSourceFile( + // only the footers are read here, no column is decoded: any backend would do (new FloeReader( $this->filesystem, + new PhpBackend(), $this->codec, $this->chunkSize, - backend: $backend, ))->read($source->path), $source, ); diff --git a/src/core/etl/src/Flow/Floe/FloeFileBatches.php b/src/core/etl/src/Flow/Floe/FloeFileBatches.php new file mode 100644 index 0000000000..0f6d2954c0 --- /dev/null +++ b/src/core/etl/src/Flow/Floe/FloeFileBatches.php @@ -0,0 +1,77 @@ + $batchSize + * + * @throws InferredSchemaException + * + * @return Generator + */ + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $file = new FloeSourceFile( + (new FloeReader($this->filesystem, $backend, $this->codec, $this->chunkSize))->read($source->path), + $source, + ); + + try { + $fileRows = $file->reader->totalRows(); + + if ($window->offset >= $fileRows) { + return $fileRows; + } + + $this->derived?->refuseDivergence($file->source()->uri(), $file->schema()); + + $fileBody = $this->fileColumns->withoutTail($file->schema()); + + foreach ($file->reader->rows($batchSize, $window->offset, $window->limit) as $rows) { + if (!$fileBody->isSame($file->schema())) { + $rows = $rows->project($fileBody, $backend); + } + + yield $fileBody->isSame($body) ? $rows : $rows->matchTo($body, $backend); + } + + return $window->offset; + } finally { + $file->close(); + } + } +} diff --git a/src/core/etl/src/Flow/Floe/FloeFileSink.php b/src/core/etl/src/Flow/Floe/FloeFileSink.php new file mode 100644 index 0000000000..01ece5a9b4 --- /dev/null +++ b/src/core/etl/src/Flow/Floe/FloeFileSink.php @@ -0,0 +1,31 @@ +writer?->close(); + } + + public function write(Rows $rows): void + { + ($this->writer ??= $this->sinks->writer($this->stream, $rows->schema(), $this->backend))->write($rows); + } +} diff --git a/src/core/etl/src/Flow/Floe/FloeFileSinks.php b/src/core/etl/src/Flow/Floe/FloeFileSinks.php new file mode 100644 index 0000000000..ba45f8c16e --- /dev/null +++ b/src/core/etl/src/Flow/Floe/FloeFileSinks.php @@ -0,0 +1,47 @@ +schema = $declared; + } + + public function open(DestinationStream $stream, Backend $backend): FileSink + { + return new FloeFileSink($this, $stream, $backend); + } + + /** + * The writer of one stream under the run's schema - the declared one, or the first written batch's. + */ + public function writer(DestinationStream $stream, Schema $written, Backend $backend): FloeWriter + { + $writer = new FloeWriter($this->filesystem, $this->schema ??= $written, $backend, $this->options); + $writer->createForStream($stream, $this->metadata); + + return $writer; + } +} diff --git a/src/core/etl/src/Flow/Floe/FloeLoader.php b/src/core/etl/src/Flow/Floe/FloeLoader.php index 735a301653..69c9465903 100644 --- a/src/core/etl/src/Flow/Floe/FloeLoader.php +++ b/src/core/etl/src/Flow/Floe/FloeLoader.php @@ -4,32 +4,30 @@ namespace Flow\Floe; -use Flow\ETL\Config\Telemetry\TelemetryAttributes; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; use Flow\ETL\FlowContext; use Flow\ETL\Loader; use Flow\ETL\Loader\Closure; use Flow\ETL\Loader\Discardable; -use Flow\ETL\Loader\FileLoader; +use Flow\ETL\Loader\File\FileLoader; +use Flow\ETL\Loader\File\FileWriteFrame; +use Flow\ETL\Loader\File\PartitionRouter; use Flow\ETL\Loader\Partitioning; use Flow\ETL\Loader\PartitioningLoader; -use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; -use Flow\Filesystem\DestinationStream; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Local\NativeLocalFilesystem; use Flow\Filesystem\Path; -use Flow\Floe\Exception\FloeException; -use Throwable; use function sprintf; final class FloeLoader implements Closure, Discardable, FileLoader, Loader, PartitioningLoader { + private ?FileWriteFrame $frame = null; + private PartitionRouter $router; public function partitionBy(Partitioning $partitioning): static @@ -43,15 +41,8 @@ public function partitionBy(Partitioning $partitioning): static private SaveMode $saveMode = SaveMode::ExceptionIfExists; - private ?FilesSink $files = null; - - /** @var array */ - private array $writers = []; - private ?Schema $schema = null; - private ?Schema $inferredSchema = null; - public function __construct( private readonly Path $path, private readonly ?Metadata $metadata = null, @@ -88,20 +79,14 @@ public function withSchema(Schema $schema): static public function closure(FlowContext $context): void { - $this->closeWriters(); - - $this->files?->publish(); - $this->files = null; + $this->frame?->closure(); + $this->frame = null; } public function discard(FlowContext $context): void { - try { - $this->closeWriters(); - } finally { - $this->files?->abandon(); - $this->files = null; - } + $this->frame?->discard(); + $this->frame = null; } public function destination(): Path @@ -111,68 +96,20 @@ public function destination(): Path public function load(Rows $rows, FlowContext $context): void { - $context->telemetry()->loadingStarted($this, [ - TelemetryAttributes::ATTR_LOADER_DESTINATION_URI => $this->path->uri(), - ]); - - try { - if ($this->schema === null && $this->inferredSchema === null) { - $this->inferredSchema = $rows->schema(); - } - - foreach ($this->router->route($rows) as [$partitions, $group]) { - $stream = ($this->files ??= new FilesSink($this->filesystem, $this->path, $this->saveMode))->writeTo( - $partitions->toArray(), - ); - - ($this->writers[$stream->path()->uri()] ??= $this->openWriter($stream))->write($group); - } - - $context->telemetry()->loadingCompleted($this, [TelemetryAttributes::ATTR_LOADING_ROWS => $rows->count()]); - } catch (Throwable $e) { - $context->telemetry()->loadingFailed($this, $e); - - throw $e; - } - } - - private function closeWriters(): void - { - $failure = null; - - foreach ($this->writers as $uri => $writer) { - unset($this->writers[$uri]); - - try { - $writer->close(); - } catch (Throwable $closeFailure) { - $failure ??= $closeFailure; - } - } - - if ($failure !== null) { - throw $failure; - } - } - - private function openWriter(DestinationStream $stream): FloeWriter - { - $declared = - $this->schema - ?? $this->inferredSchema - ?? throw new FloeException('Floe loader has no schema to write with'); - - // partitionBy() keeps the partition columns in the path rather than the body, so the file - // schema must not declare them either. Every other declared column stays - a batch that does - // not carry one is the writer's to refuse. - - $writer = new FloeWriter( + // partitionBy() keeps the partition columns in the path rather than the body, so the file schema must not + // declare them either. Every other declared column stays - a batch that does not carry one is the writer's + // to refuse. + ($this->frame ??= new FileWriteFrame( $this->filesystem, - $declared->gracefulRemove(...$this->router->droppedNames()), - $this->options, - ); - $writer->createForStream($stream, $this->metadata); - - return $writer; + $this->path, + $this->saveMode, + $this->router, + new FloeFileSinks( + $this->filesystem, + $this->schema?->gracefulRemove(...$this->router->droppedNames()), + $this->metadata, + $this->options, + ), + ))->write($rows, $context, $this); } } diff --git a/src/core/etl/src/Flow/Floe/FloeMerger.php b/src/core/etl/src/Flow/Floe/FloeMerger.php index 429082bdbb..cdac513cce 100644 --- a/src/core/etl/src/Flow/Floe/FloeMerger.php +++ b/src/core/etl/src/Flow/Floe/FloeMerger.php @@ -4,7 +4,6 @@ namespace Flow\Floe; -use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -23,7 +22,7 @@ public function __construct( private Filesystem $filesystem, - private Backend $backend = new AdaptiveBackend(), + private Backend $backend, private Codec $codec = new NoopCodec(), ) { Format::validateCodecId($this->codec->id()); @@ -142,10 +141,15 @@ private function mergeCompact(array $sources, array $layouts, ?Schema $merged, P $mergedMetadata = $mergedMetadata->merge($layout['footer']->metadata); } - $writer = new FloeWriter($this->filesystem, $merged ?? new Schema(), new Options(codec: $this->codec)); + $writer = new FloeWriter( + $this->filesystem, + $merged ?? new Schema(), + $this->backend, + new Options(codec: $this->codec), + ); $writer->create($dest, $mergedMetadata->merge($metadata)); - $reader = new FloeReader($this->filesystem, $this->codec, backend: $this->backend); + $reader = new FloeReader($this->filesystem, $this->backend, $this->codec); foreach ($sources as $source) { $streamReader = $reader->read($source); diff --git a/src/core/etl/src/Flow/Floe/FloeReader.php b/src/core/etl/src/Flow/Floe/FloeReader.php index 12d72c0a50..0ac998b76b 100644 --- a/src/core/etl/src/Flow/Floe/FloeReader.php +++ b/src/core/etl/src/Flow/Floe/FloeReader.php @@ -4,7 +4,6 @@ namespace Flow\Floe; -use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; @@ -15,9 +14,9 @@ { public function __construct( private Filesystem $filesystem, + private Backend $backend, private Codec $codec = new NoopCodec(), private int $chunkSize = 65536, - private Backend $backend = new AdaptiveBackend(), ) {} /** diff --git a/src/core/etl/src/Flow/Floe/FloeSerializer.php b/src/core/etl/src/Flow/Floe/FloeSerializer.php index 3301819c8c..f20f0c7ac4 100644 --- a/src/core/etl/src/Flow/Floe/FloeSerializer.php +++ b/src/core/etl/src/Flow/Floe/FloeSerializer.php @@ -4,7 +4,6 @@ namespace Flow\Floe; -use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Rows; @@ -27,8 +26,8 @@ final class FloeSerializer implements Serializer * @param int<1, max> $batchSize */ public function __construct( + private readonly Backend $backend, private readonly int $batchSize = 1000, - private readonly Backend $backend = new AdaptiveBackend(), ) { // @mago-ignore analysis:impossible-condition,redundant-comparison if ($this->batchSize < 1) { @@ -40,7 +39,7 @@ public function serialize(Rows $rows, DestinationStream $destination): void { try { // validation stays on until an upstream mechanism guarantees Rows match their schema - $writer = new FloeStreamWriter($rows->schema(), new Options()); + $writer = new FloeStreamWriter($rows->schema(), $this->backend, new Options()); $writer->create($destination); $writer->write($rows); $writer->close(); @@ -74,7 +73,7 @@ public function unserialize(SourceStream $source): Rows return $batches === [] ? (new RowsBuilder($reader->schema(), $this->backend))->finish() - : $batches[0]->concat(...array_slice($batches, 1)); + : $batches[0]->concat($this->backend, ...array_slice($batches, 1)); } catch (FloeException|RuntimeException $e) { throw new SerializationException($e->getMessage(), 0, $e); } finally { diff --git a/src/core/etl/src/Flow/Floe/FloeSourceFile.php b/src/core/etl/src/Flow/Floe/FloeSourceFile.php index ec5cf384e5..b12184a258 100644 --- a/src/core/etl/src/Flow/Floe/FloeSourceFile.php +++ b/src/core/etl/src/Flow/Floe/FloeSourceFile.php @@ -5,8 +5,8 @@ namespace Flow\Floe; use Flow\ETL\Cardinality; -use Flow\ETL\Extractor\SelfDescribingFile; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SelfDescribingFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Extractor\Statistics; use Flow\ETL\Schema; diff --git a/src/core/etl/src/Flow/Floe/FloeStreamReader.php b/src/core/etl/src/Flow/Floe/FloeStreamReader.php index 2c1a41c57f..f83bb56bb9 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamReader.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamReader.php @@ -4,7 +4,6 @@ namespace Flow\Floe; -use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\Backend; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Rows; @@ -37,7 +36,7 @@ public function __construct( private readonly SourceStream $source, private readonly Codec $codec, private readonly int $chunkSize, - private readonly Backend $backend = new AdaptiveBackend(), + private readonly Backend $backend, ) { Format::validateCodecId($this->codec->id()); $this->frameDecoder = new FrameDecoder($this->codec); diff --git a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php index b910b50f3d..609094fe8a 100644 --- a/src/core/etl/src/Flow/Floe/FloeStreamWriter.php +++ b/src/core/etl/src/Flow/Floe/FloeStreamWriter.php @@ -5,6 +5,7 @@ namespace Flow\Floe; use Composer\InstalledVersions; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\OffsetOverflow; use Flow\ETL\Rows; use Flow\ETL\Schema; @@ -64,6 +65,7 @@ final class FloeStreamWriter */ public function __construct( Schema $schema, + private readonly Backend $backend, private readonly Options $options = new Options(), ) { Format::validateCodecId($this->options->codec->id()); @@ -156,7 +158,7 @@ public function write(Rows $rows): void if (!$rows->schema()->isSame($this->sessionSchema)) { $this->assertBatchFitsSession($rows->schema()); - $matched = $rows->matchTo($this->sessionSchema); + $matched = $rows->matchTo($this->sessionSchema, $this->backend); } $bodies = []; diff --git a/src/core/etl/src/Flow/Floe/FloeWriter.php b/src/core/etl/src/Flow/Floe/FloeWriter.php index 38bcb7d211..894d36ead1 100644 --- a/src/core/etl/src/Flow/Floe/FloeWriter.php +++ b/src/core/etl/src/Flow/Floe/FloeWriter.php @@ -4,6 +4,8 @@ namespace Flow\Floe; +use Flow\ETL\Column\Backend; +use Flow\ETL\Loader\File\FileSink; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -14,7 +16,7 @@ use function sprintf; -final class FloeWriter +final class FloeWriter implements FileSink { private readonly FloeStreamWriter $inner; @@ -26,9 +28,10 @@ final class FloeWriter public function __construct( private readonly Filesystem $filesystem, Schema $schema, + Backend $backend, private readonly Options $options = new Options(), ) { - $this->inner = new FloeStreamWriter($schema, $this->options); + $this->inner = new FloeStreamWriter($schema, $backend, $this->options); } /** diff --git a/src/core/etl/src/Flow/Floe/FrameDecoder.php b/src/core/etl/src/Flow/Floe/FrameDecoder.php index 5e093fb37e..ef2bb237b5 100644 --- a/src/core/etl/src/Flow/Floe/FrameDecoder.php +++ b/src/core/etl/src/Flow/Floe/FrameDecoder.php @@ -5,7 +5,7 @@ namespace Flow\Floe; use Flow\ETL\Column\Backend; -use Flow\ETL\Column\BufferLayout; +use Flow\ETL\Column\Layout\BufferLayout; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Rows; diff --git a/src/core/etl/src/Flow/Floe/FrameEncoder.php b/src/core/etl/src/Flow/Floe/FrameEncoder.php index 560d8778b4..d9c0415c0f 100644 --- a/src/core/etl/src/Flow/Floe/FrameEncoder.php +++ b/src/core/etl/src/Flow/Floe/FrameEncoder.php @@ -4,7 +4,7 @@ namespace Flow\Floe; -use Flow\ETL\Column\BufferLayout; +use Flow\ETL\Column\Layout\BufferLayout; use Flow\ETL\Exception\OffsetOverflow; use Flow\ETL\Rows; use Flow\Floe\Codec\NoopCodec; 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 3b3fc220d6..836b22c590 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/ExtractedRows.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ExtractedRows.php @@ -26,12 +26,39 @@ public static function of( ?int $limit = null, Filter $pathFilter = new OnlyFiles(), ): Rows { - $extracted = rows(schema()); + $context ??= flow_context(); + $extracted = null; - foreach (FlowTestCase::extracted($extractor, $context ?? flow_context(), $limit, $pathFilter) as $batch) { - $extracted = $extracted->merge($batch); + foreach (FlowTestCase::extracted($extractor, $context, $limit, $pathFilter) as $batch) { + $extracted = $extracted === null ? $batch : $extracted->concat($context->backend(), $batch); } - return $extracted; + return $extracted ?? rows(schema()); + } + + /** + * Two reads of one extractor, their batches pulled in turn - each read's rows. + * + * @return array{Rows, Rows} + */ + public static function interleaved(Extractor $extractor, ?FlowContext $context = null): array + { + $context ??= flow_context(); + $reads = [$extractor->extract($context), $extractor->extract($context)]; + /** @var array{0: null|Rows, 1: null|Rows} $extracted */ + $extracted = [null, null]; + + while ($reads[0]->valid() || $reads[1]->valid()) { + foreach ($reads as $i => $read) { + if ($read->valid()) { + $extracted[$i] = $extracted[$i] === null + ? $read->current() + : $extracted[$i]->concat($context->backend(), $read->current()); + $read->next(); + } + } + } + + return [$extracted[0] ?? rows(schema()), $extracted[1] ?? rows(schema())]; } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/FileColumnsContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/FileColumnsContext.php index 084e4d7fac..d752ef1aaf 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/FileColumnsContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/FileColumnsContext.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Context; -use Flow\ETL\Extractor\FileColumns; -use Flow\ETL\Extractor\PartitionColumns; -use Flow\ETL\Extractor\PartitionTypes; +use Flow\ETL\Extractor\File\FileColumns; +use Flow\ETL\Extractor\File\PartitionColumns; +use Flow\ETL\Extractor\File\PartitionTypes; use function Flow\Filesystem\DSL\memory_filesystem; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/GroupByContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/GroupByContext.php index 3c6e287722..0550c307a2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/GroupByContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/GroupByContext.php @@ -43,7 +43,7 @@ public static function aggregated(GroupBy $groupBy, FlowContext $context, Rows . $result = null; foreach (self::aggregate($groupBy, $context, ...$batches) as $batch) { - $result = $result === null ? $batch : $result->merge($batch); + $result = $result === null ? $batch : $result->concat($context->backend(), $batch); } return $result ?? rows(schema()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/KeyGroupingContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/KeyGroupingContext.php index 7791908c1b..3e8a95080c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/KeyGroupingContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/KeyGroupingContext.php @@ -7,6 +7,7 @@ use Flow\ETL\Bucketing\KeyGrouping; use Flow\ETL\Bucketing\KeyValues; use Flow\ETL\Bucketing\NativeHasher; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Row\Reference; use Flow\ETL\Rows; use Generator; @@ -26,7 +27,7 @@ final class KeyGroupingContext public static function groups(array $by, Generator $input): array { return iterator_to_array( - (new KeyGrouping(new KeyValues($by), new NativeHasher()))->group($input), + (new KeyGrouping(new KeyValues($by), new NativeHasher(), new AdaptiveBackend()))->group($input), preserve_keys: false, ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/PartitionRoutingContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/PartitionRoutingContext.php index 7eda680892..7e1f925c66 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/PartitionRoutingContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/PartitionRoutingContext.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Tests\Context; +use Flow\ETL\Loader\File\PartitionRouter; use Flow\ETL\Loader\Partitioning; -use Flow\ETL\Loader\PartitionRouter; use Flow\ETL\Rows; use Flow\Filesystem\Partitions; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/ScalarFunctionFixtures.php b/src/core/etl/tests/Flow/ETL/Tests/Context/ScalarFunctionFixtures.php index 5d68ba484c..60cae32343 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/ScalarFunctionFixtures.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/ScalarFunctionFixtures.php @@ -4,7 +4,10 @@ namespace Flow\ETL\Tests\Context; +use DateTimeImmutable; +use DOMDocument; use Flow\ETL\Adapter\Excel\Function\IsValidExcelSheetName; +use Flow\ETL\Column\Backend; use Flow\ETL\Exception\RequiredPHPVersionException; use Flow\ETL\Exception\SchemaNotDerivableException; use Flow\ETL\Function; @@ -15,11 +18,13 @@ use Flow\ETL\Function\ScalarFunction; use Flow\ETL\Row\ResolvedReference; use Flow\ETL\Row\UnresolvedReference; +use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\String\StringStyles; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; use Flow\Types\Type; +use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\enum_schema; @@ -133,6 +138,57 @@ enum_schema('enum', BackedStringEnum::class, true), ); } + /** + * Three rows under schema(): two of values, the last all null. `html` stays null - a document needs PHP 8.4. + */ + public static function rows(Backend $backend): Rows + { + $document = new DOMDocument(); + $document->loadXML('12'); + + return array_to_rows( + [ + [ + 'string' => 'a', + 'integer' => 1, + 'float' => 1.5, + 'boolean' => true, + 'datetime' => new DateTimeImmutable('2026-01-02 03:04:05 UTC'), + 'json' => '{"a":1}', + 'xml' => '1', + 'xml_element' => $document->getElementsByTagName('a')->item(0), + 'html' => null, + 'enum' => BackedStringEnum::one, + 'list' => ['a', 'b'], + 'list_of_lists' => [['a'], ['b']], + 'list_of_structs' => [['field' => 'x']], + 'map' => ['k' => 1], + 'structure' => ['field' => 1], + ], + [ + 'string' => 'b', + 'integer' => 2, + 'float' => -0.5, + 'boolean' => false, + 'datetime' => new DateTimeImmutable('2026-01-03 00:00:00 UTC'), + 'json' => '[1,2]', + 'xml' => '2', + 'xml_element' => $document->getElementsByTagName('b')->item(0), + 'html' => null, + 'enum' => BackedStringEnum::two, + 'list' => [], + 'list_of_lists' => [], + 'list_of_structs' => [], + 'map' => [], + 'structure' => ['field' => 2], + ], + [], + ], + self::schema(), + $backend, + ); + } + /** * @param class-string $class * @@ -263,7 +319,7 @@ public static function all(): array ], Function\CallUserFunc::class => [ 'factory' => static fn(): ScalarFunction => new Function\CallUserFunc( - lit('strtoupper'), + lit('strval'), type_string(), [ref('string')], ), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Context/SelfDescribingFilesContext.php b/src/core/etl/tests/Flow/ETL/Tests/Context/SelfDescribingFilesContext.php index ca0b384d7f..16e54ddf43 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Context/SelfDescribingFilesContext.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Context/SelfDescribingFilesContext.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Tests\Context; -use Flow\ETL\Extractor\SelfDescribingFile; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SelfDescribingFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema; use Flow\ETL\Tests\Double\FakeSelfDescribingFile; use Generator; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingColumnBuilder.php b/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingColumnBuilder.php index d147154801..1232b7e067 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingColumnBuilder.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/AcceptingColumnBuilder.php @@ -7,7 +7,7 @@ use Flow\ETL\Column\Column; use Flow\ETL\Column\ColumnBuilder; use Flow\ETL\Column\Php\ConstantColumn; -use Flow\ETL\Column\Php\NullPhysical; +use Flow\ETL\Column\Physical\NullPhysical; use function count; use function Flow\Types\DSL\type_null; @@ -31,6 +31,11 @@ public function appendMany(array $values): void $this->count += count($values); } + public function appendPhysicals(array $physicals, ?int $nullCount = null): void + { + $this->count += count($physicals); + } + public function appendTake(Column $column, array $indices): void { $this->count += count($indices); 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 8a98023b91..f8eb6274e3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/CountingExtractor.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; use Flow\ETL\Extractor\Batches; @@ -58,7 +59,10 @@ public function extract(FlowContext $context, ?int $limit = null): Generator foreach ($this->batches as $rows) { for ($i = 0; $i < $rows->count(); $i++) { - $buffer = $buffer->concat($rows->slice($i, 1)->matchTo($this->schema)); + $buffer = $buffer->concat( + new AdaptiveBackend(), + $rows->slice($i, 1)->matchTo($this->schema, new AdaptiveBackend()), + ); if ($buffer->count() === $this->batchSize()) { $this->batchesYielded++; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php index c116c6cc32..365e063f2c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/DeclaringExtractor.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Extractor; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; @@ -19,7 +20,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null): Generator { - yield Rows::empty($this->schema()); + yield Rows::empty($this->schema(), new AdaptiveBackend()); } public function schema(): Schema diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FailingOnValuesFunction.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FailingOnValuesFunction.php index 9e39558343..23c3065139 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FailingOnValuesFunction.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FailingOnValuesFunction.php @@ -86,7 +86,7 @@ public function eval(Rows $rows, FlowContext $context): Column }; } - return (new ResultColumn())->of($this, $values); + return (new ResultColumn($context->backend()))->of($this, $values); } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeSelfDescribingFile.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeSelfDescribingFile.php index bcdd55f5eb..15460fe9ab 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeSelfDescribingFile.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeSelfDescribingFile.php @@ -5,8 +5,8 @@ namespace Flow\ETL\Tests\Double; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Extractor\SelfDescribingFile; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SelfDescribingFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Extractor\Statistics; use Flow\ETL\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 5a02c2dac4..f2f6ef2be9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FakeStaticOrdersExtractor.php @@ -140,11 +140,11 @@ public function rawData(): Generator public function toRows(Backend $backend = new AdaptiveBackend()): Rows { - $rows = rows(schema()); $schema = self::schema(); + $rows = rows($schema, $backend); foreach ($this->rawData() as $row) { - $rows = $rows->merge(array_to_rows($row, $schema, $backend)); + $rows = $rows->concat($backend, array_to_rows($row, $schema, $backend)); } return $rows; 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 cdd0e75ee4..68332ed393 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FileReadingExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/FileReadingExtractor.php @@ -4,9 +4,9 @@ namespace Flow\ETL\Tests\Double; -use Flow\ETL\Extractor\FileReading; -use Flow\ETL\Extractor\SelfDescribingFile; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\FileReading; +use Flow\ETL\Extractor\File\SelfDescribingFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/FixedValuesColumn.php b/src/core/etl/tests/Flow/ETL/Tests/Double/FixedValuesColumn.php deleted file mode 100644 index 59923c27d1..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/FixedValuesColumn.php +++ /dev/null @@ -1,98 +0,0 @@ - $type - * @param list $values - */ - public function __construct( - public Type $type, - public array $values, - ) {} - - public function at(int $i): mixed - { - return $this->values[$i]; - } - - public function concat(Column ...$others): Column - { - throw new RuntimeException('FixedValuesColumn cannot be concatenated'); - } - - public function count(): int - { - return count($this->values); - } - - public function encode(): array - { - throw new RuntimeException('FixedValuesColumn cannot be encoded'); - } - - public function isNull(int $i): bool - { - return $this->values[$i] === null; - } - - public function nullCount(): int - { - return 0; - } - - public function physicals(): array - { - return $this->values; - } - - public function slice(int $offset, int $length): Column - { - return new self($this->type, array_slice($this->values, $offset, $length)); - } - - public function take(array $indices): Column - { - $values = []; - - foreach ($indices as $index) { - $values[] = $this->values[$index]; - } - - return new self($this->type, $values); - } - - public function type(): Type - { - return $this->type; - } - - public function value(int $i): mixed - { - return $this->values[$i]; - } - - public function values(): array - { - return $this->values; - } - - public function withType(Type $type): Column - { - return new self($type, $this->values); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/InMemoryFileBatches.php b/src/core/etl/tests/Flow/ETL/Tests/Double/InMemoryFileBatches.php new file mode 100644 index 0000000000..9fe072eeac --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/InMemoryFileBatches.php @@ -0,0 +1,56 @@ +> + */ + public array $windows = []; + + /** + * @param array> $ids by URI + */ + public function __construct( + private readonly array $ids, + ) {} + + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $this->windows[$source->uri()][] = $window; + $ids = $this->ids[$source->uri()] ?? []; + $read = array_slice($ids, min($window->offset, count($ids)), $window->limit); + + foreach ($read === [] ? [] : array_chunk($read, $batchSize) as $chunk) { + yield array_to_rows(array_map(static fn(int $id): array => ['id' => $id], $chunk), $body, $backend); + } + + return min($window->offset, count($ids)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/InMemoryUnskippableFileBatches.php b/src/core/etl/tests/Flow/ETL/Tests/Double/InMemoryUnskippableFileBatches.php new file mode 100644 index 0000000000..3ce2e2b674 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/InMemoryUnskippableFileBatches.php @@ -0,0 +1,53 @@ +> + */ + public array $windows = []; + + /** + * @param array> $ids by URI + */ + public function __construct( + private readonly array $ids, + ) {} + + public function batches( + SourceFile $source, + Schema $body, + int $batchSize, + Backend $backend, + ReadWindow $window, + ): Generator { + $this->windows[$source->uri()][] = $window; + $ids = $this->ids[$source->uri()] ?? []; + $read = $ids; + + foreach ($read === [] ? [] : array_chunk($read, $batchSize) as $chunk) { + yield array_to_rows(array_map(static fn(int $id): array => ['id' => $id], $chunk), $body, $backend); + } + + return 0; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/NonStructureUnpackStub.php b/src/core/etl/tests/Flow/ETL/Tests/Double/NonStructureUnpackStub.php index 7befb6f337..87c6e18e29 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/NonStructureUnpackStub.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/NonStructureUnpackStub.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Tests\Double; use Flow\ETL\Column\Column; -use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\FlowContext; use Flow\ETL\Function\FunctionTree; use Flow\ETL\Function\ScalarFunction; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingFileExtractor.php b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingFileExtractor.php index 52cffddc9c..5e9cbe6011 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingFileExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RecordingFileExtractor.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Tests\Double; -use Flow\ETL\Extractor\FileExtractor; +use Flow\ETL\Extractor\File\FileExtractor; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; use Flow\ETL\Rows; 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 dbb28e01ca..4c2d60a258 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/RepeatableExtractor.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Extractor; use Flow\ETL\Extractor\OverridingExtractor; use Flow\ETL\Extractor\RewindableExtractor; @@ -35,7 +36,7 @@ public function __construct( public function extract(FlowContext $context, ?int $limit = null): Generator { - yield Rows::empty($this->schema()); + yield Rows::empty($this->schema(), new AdaptiveBackend()); } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ReportsResolvedOperand.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ReportsResolvedOperand.php index c8ad84e976..59e03bbd83 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/ReportsResolvedOperand.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ReportsResolvedOperand.php @@ -47,7 +47,11 @@ public function withChildren(array $children): static public function eval(Rows $rows, FlowContext $context): Column { // @mago-ignore analysis:possibly-invalid-argument - return (new ResultColumn())->of($this, array_fill(0, $rows->count(), $this->operand->resolved())); + return (new ResultColumn($context->backend()))->of($this, array_fill( + 0, + $rows->count(), + $this->operand->resolved(), + )); } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/ReturnsSpyFunction.php b/src/core/etl/tests/Flow/ETL/Tests/Double/ReturnsSpyFunction.php index 8d2bc41f6a..8e0738b54a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/ReturnsSpyFunction.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/ReturnsSpyFunction.php @@ -42,7 +42,10 @@ public function children(): array public function eval(Rows $rows, FlowContext $context): Column { // @mago-ignore analysis:possibly-invalid-argument - return (new ResultColumn())->of($this, $rows->isEmpty() ? [] : array_fill(0, $rows->count(), 1)); + return (new ResultColumn($context->backend()))->of( + $this, + $rows->isEmpty() ? [] : array_fill(0, $rows->count(), 1), + ); } /** diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php index 813e3942b1..692a45fbb3 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyBackend.php @@ -16,6 +16,8 @@ final class SpyBackend implements Backend private int $builders = 0; + private int $constants = 0; + private int $decodes = 0; private readonly PhpBackend $php; @@ -62,9 +64,16 @@ public function decodes(): int public function constant(Definition $definition, mixed $value, int $count): Column { + $this->constants++; + return $this->php->constant($definition, $value, $count); } + public function constants(): int + { + return $this->constants; + } + public function decode(Definition $definition, array $buffers, int $count, int $nullCount): Column { $this->decodes++; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpyFileSinks.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyFileSinks.php new file mode 100644 index 0000000000..0ca4f9fd49 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpyFileSinks.php @@ -0,0 +1,68 @@ + + */ + public array $opened = []; + + /** + * @var list + */ + public array $closed = []; + + /** + * @param bool $failing every write throws + * @param bool $failingClose every close() throws "close of failed" once it recorded the close + */ + public function __construct( + public readonly bool $failing = false, + public readonly bool $failingClose = false, + ) {} + + public function open(DestinationStream $stream, Backend $backend): FileSink + { + $this->opened[] = $stream->path()->uri(); + return new readonly class($stream, $this) implements FileSink { + public function __construct( + private DestinationStream $stream, + private SpyFileSinks $spy, + ) {} + + public function close(): void + { + $this->stream->append('closed;'); + $this->spy->closed[] = $this->stream->path()->uri(); + + if ($this->spy->failingClose) { + throw new RuntimeException('close of ' . $this->stream->path()->uri() . ' failed'); + } + } + + public function write(Rows $rows): void + { + if ($this->spy->failing) { + throw new RuntimeException('sink refused the batch'); + } + + $this->stream->append('rows:' . $rows->count() . ';'); + } + }; + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Double/SpySerializer.php b/src/core/etl/tests/Flow/ETL/Tests/Double/SpySerializer.php index b485dd23db..e1aafae1ed 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Double/SpySerializer.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Double/SpySerializer.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Double; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Rows; use Flow\Filesystem\DestinationStream; use Flow\Filesystem\SourceStream; @@ -26,7 +27,7 @@ final class SpySerializer implements Serializer public array $unserialized = []; public function __construct( - private readonly Serializer $inner = new FloeSerializer(), + private readonly Serializer $inner = new FloeSerializer(new AdaptiveBackend()), ) {} public function serialize(Rows $rows, DestinationStream $destination): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/FlowIntegrationTestCase.php b/src/core/etl/tests/Flow/ETL/Tests/FlowIntegrationTestCase.php index ba0845d0ae..174cfbbe2f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/FlowIntegrationTestCase.php +++ b/src/core/etl/tests/Flow/ETL/Tests/FlowIntegrationTestCase.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Config\Cache\CacheConfig; use Flow\Filesystem\Filesystem; use Flow\Filesystem\FilesystemTable; @@ -62,7 +63,7 @@ protected function setUp(): void $this->fs = new NativeLocalFilesystem(); $this->fstab = new FilesystemTable($this->fs, new StdOutFilesystem()); - $this->serializer = new FloeSerializer(); + $this->serializer = new FloeSerializer(new AdaptiveBackend()); $this->cleanupCacheDir($this->cacheDir); mkdir($this->cacheDir->path(), recursive: true); diff --git a/src/core/etl/tests/Flow/ETL/Tests/FlowTestCase.php b/src/core/etl/tests/Flow/ETL/Tests/FlowTestCase.php index a34a0cbea6..a62327205e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/FlowTestCase.php +++ b/src/core/etl/tests/Flow/ETL/Tests/FlowTestCase.php @@ -4,9 +4,10 @@ namespace Flow\ETL\Tests; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Extractor; use Flow\ETL\Extractor\BatchableExtractor; -use Flow\ETL\Extractor\FileExtractor; +use Flow\ETL\Extractor\File\FileExtractor; use Flow\ETL\Extractor\RewindableExtractor; use Flow\ETL\Extractor\Signal; use Flow\ETL\FlowContext; @@ -45,7 +46,7 @@ final public static function assertExtractorHonoursBatchContract( foreach ($extractor->extract(flow_context()) as $batch) { static::assertLessThanOrEqual($extractor->batchSize(), $batch->count(), $message); - $collected = $collected->merge($batch); + $collected = $collected->isEmpty() ? $batch : $collected->concat(new PhpBackend(), $batch); } static::assertEquals($expected->toArray(), $collected->toArray(), $message); @@ -75,11 +76,11 @@ final public static function assertExtractorHonoursBatchContract( $second = rows(schema()); foreach ($extractor->extract(flow_context()) as $batch) { - $first = $first->merge($batch); + $first = $first->isEmpty() ? $batch : $first->concat(new PhpBackend(), $batch); } foreach ($extractor->extract(flow_context()) as $batch) { - $second = $second->merge($batch); + $second = $second->isEmpty() ? $batch : $second->concat(new PhpBackend(), $batch); } static::assertEquals($first->toArray(), $second->toArray(), $message); @@ -123,7 +124,9 @@ final public static function assertExtractedRowsAsArrayEquals( $extractedRows = rows(schema()); foreach (self::extracted($extractor, $flowContext, $limit, $pathFilter) as $nextRows) { - $extractedRows = $extractedRows->merge($nextRows); + $extractedRows = $extractedRows->isEmpty() + ? $nextRows + : $extractedRows->concat(new PhpBackend(), $nextRows); } static::assertEquals($expectedArray, $extractedRows->toArray(), $message); @@ -165,7 +168,9 @@ final public static function assertExtractedRowsEquals( $extractedRows = rows(schema()); foreach (self::extracted($extractor, $flowContext, $limit, $pathFilter) as $nextRows) { - $extractedRows = $extractedRows->merge($nextRows); + $extractedRows = $extractedRows->isEmpty() + ? $nextRows + : $extractedRows->concat(new PhpBackend(), $nextRows); } static::assertEquals($expectedRows, $extractedRows, $message); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php index e16424a191..7534693611 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/FilesystemBucketsTest.php @@ -6,6 +6,7 @@ use DateTimeImmutable; use Flow\ETL\Bucketing\Storage\FilesystemBuckets; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Rows; use Flow\ETL\Tests\Context\BucketsStorageContext; @@ -318,6 +319,7 @@ public function test_append_resume_with_a_genuinely_different_column_set_still_t [['id' => 1, 'name' => 'x']], schema(int_schema('id'), str_schema('name')), ))->schema(), + new AdaptiveBackend(), ); $writer->create($path); $writer->write($first); @@ -326,6 +328,7 @@ public function test_append_resume_with_a_genuinely_different_column_set_still_t $writer = new FloeWriter( $this->fs(), array_to_rows([['id' => 2, 'city' => 'y']], schema(int_schema('id'), str_schema('city')))->schema(), + new AdaptiveBackend(), ); $this->expectException(IncompatibleSchemaException::class); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php index 051ec918ac..5c7f0db6f9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Bucketing/Storage/PSRCacheBucketsTest.php @@ -6,8 +6,10 @@ use Exception; use Flow\ETL\Bucketing\Storage\PSRCacheBuckets; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Tests\Context\BucketsStorageContext; use Flow\ETL\Tests\FlowIntegrationTestCase; +use Flow\Floe\FloeSerializer; use Override; use Symfony\Component\Cache\Adapter\RedisAdapter; use Symfony\Component\Cache\Psr16Cache; @@ -44,7 +46,11 @@ public function test_round_trips_rows_across_chunks_and_removes_the_bucket(): vo 'timeout' => 5, ]))); - $storage = new PSRCacheBuckets($cache, prefix: 'flow:buckets:test:round_trip'); + $storage = new PSRCacheBuckets( + $cache, + new FloeSerializer(new AdaptiveBackend()), + prefix: 'flow:buckets:test:round_trip', + ); $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/CacheTestCase.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/CacheTestCase.php index c5dac661c1..abdc23e6ec 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/CacheTestCase.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/CacheTestCase.php @@ -6,6 +6,7 @@ use Flow\ETL\Cache; use Flow\ETL\Cache\CacheIndex; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\KeyNotInCacheException; use Flow\ETL\Rows; use Flow\ETL\Tests\FlowIntegrationTestCase; @@ -44,7 +45,7 @@ public function test_caching_index(): void $index->add('chunk-1'); $index->add('chunk-2'); - $cache->set('index', $index->toRows()); + $cache->set('index', $index->toRows(new PhpBackend())); static::assertTrue($cache->has('index')); @@ -93,7 +94,7 @@ public function test_clearing_cache(): void { $cache = $this->cache(); - $cache->set('index', (new CacheIndex('index'))->toRows()); + $cache->set('index', (new CacheIndex('index'))->toRows(new PhpBackend())); $cache->set('row', array_to_rows([['name' => 'John']], schema(str_schema('name')))); $cache->set('rows', array_to_rows([['name' => 'John'], ['name' => 'Jane']], schema(str_schema('name')))); @@ -139,7 +140,7 @@ public function test_removing_from_cache(): void { $cache = $this->cache(); - $cache->set('index', (new CacheIndex('index'))->toRows()); + $cache->set('index', (new CacheIndex('index'))->toRows(new PhpBackend())); $cache->set('row', array_to_rows([['name' => 'John']], schema(str_schema('name')))); $cache->set('rows', array_to_rows([['name' => 'John'], ['name' => 'Jane']], schema(str_schema('name')))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/FilesystemCacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/FilesystemCacheTest.php index d17089a94e..ecaa3f02a5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/FilesystemCacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/FilesystemCacheTest.php @@ -6,8 +6,10 @@ use Flow\ETL\Cache; use Flow\ETL\Cache\Implementation\FilesystemCache; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Exception\KeyNotInCacheException; use Flow\ETL\Tests\Double\SpySerializer; +use Flow\Floe\FloeSerializer; use Flow\Types\Exception\InvalidArgumentException; use function file_get_contents; @@ -64,7 +66,7 @@ public function test_corrupted_frame_with_intact_footer_is_treated_as_a_cache_mi public function test_custom_serializer_is_used_for_set_and_get(): void { $spy = new SpySerializer(); - $cache = new FilesystemCache($this->fs(), path(__DIR__ . '/var/filesystem-cache-spy'), $spy); + $cache = new FilesystemCache($this->fs(), $spy, path(__DIR__ . '/var/filesystem-cache-spy')); $cache->clear(); $cache->set('spy', $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); @@ -137,6 +139,10 @@ public function test_legacy_structure_schema_payload_is_rejected_loudly(): void protected function cache(): Cache { - return new FilesystemCache($this->fs(), path(__DIR__ . '/var/filesystem-cache')); + return new FilesystemCache( + $this->fs(), + new FloeSerializer(new AdaptiveBackend()), + path(__DIR__ . '/var/filesystem-cache'), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleFilesystemCacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleFilesystemCacheTest.php index 8c7c651a8b..a21025a34b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleFilesystemCacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleFilesystemCacheTest.php @@ -6,7 +6,9 @@ use Flow\ETL\Cache; use Flow\ETL\Cache\Implementation\PSRSimpleCache; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Exception\KeyNotInCacheException; +use Flow\Floe\FloeSerializer; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Psr16Cache; @@ -19,7 +21,7 @@ final class PSRSimpleFilesystemCacheTest extends CacheTestCase public function test_torn_entry_is_treated_as_a_cache_miss(): void { $psr = new Psr16Cache(new FilesystemAdapter(directory: __DIR__ . '/var/psr-simple-file-cache')); - $cache = new PSRSimpleCache($psr); + $cache = new PSRSimpleCache($psr, new FloeSerializer(new AdaptiveBackend())); $cache->set('torn', array_to_rows([['id' => 1]], schema(int_schema('id')))); $psr->set('torn', 'not a valid floe payload'); @@ -32,7 +34,7 @@ public function test_torn_entry_is_treated_as_a_cache_miss(): void public function test_schema_of_an_entry_without_a_stored_schema_is_a_cache_miss(): void { $psr = new Psr16Cache(new FilesystemAdapter(directory: __DIR__ . '/var/psr-simple-file-cache')); - $cache = new PSRSimpleCache($psr); + $cache = new PSRSimpleCache($psr, new FloeSerializer(new AdaptiveBackend())); $cache->set('orphan', array_to_rows([['id' => 1]], schema(int_schema('id')))); $psr->delete('orphan.schema'); @@ -45,7 +47,7 @@ public function test_schema_of_an_entry_without_a_stored_schema_is_a_cache_miss( public function test_torn_schema_is_treated_as_a_cache_miss(): void { $psr = new Psr16Cache(new FilesystemAdapter(directory: __DIR__ . '/var/psr-simple-file-cache')); - $cache = new PSRSimpleCache($psr); + $cache = new PSRSimpleCache($psr, new FloeSerializer(new AdaptiveBackend())); $cache->set('torn-schema', array_to_rows([['id' => 1]], schema(int_schema('id')))); $psr->set('torn-schema.schema', 'not a valid schema payload'); @@ -57,8 +59,9 @@ public function test_torn_schema_is_treated_as_a_cache_miss(): void protected function cache(): Cache { - return new PSRSimpleCache(new Psr16Cache( - new FilesystemAdapter(directory: __DIR__ . '/var/psr-simple-file-cache'), - )); + return new PSRSimpleCache( + new Psr16Cache(new FilesystemAdapter(directory: __DIR__ . '/var/psr-simple-file-cache')), + new FloeSerializer(new AdaptiveBackend()), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleRedisCacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleRedisCacheTest.php index 11a56a2904..b713d85a41 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleRedisCacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Cache/PSRSimpleRedisCacheTest.php @@ -7,6 +7,8 @@ use Exception; use Flow\ETL\Cache; use Flow\ETL\Cache\Implementation\PSRSimpleCache; +use Flow\ETL\Column\AdaptiveBackend; +use Flow\Floe\FloeSerializer; use Override; use Symfony\Component\Cache\Adapter\RedisAdapter; use Symfony\Component\Cache\Psr16Cache; @@ -44,10 +46,13 @@ protected function tearDown(): void protected function cache(): Cache { - return new PSRSimpleCache(new Psr16Cache(new RedisAdapter(RedisAdapter::createConnection($this->dsn(), [ - 'retry_interval' => 2, - 'timeout' => 5, - ])))); + return new PSRSimpleCache( + new Psr16Cache(new RedisAdapter(RedisAdapter::createConnection($this->dsn(), [ + 'retry_interval' => 2, + 'timeout' => 5, + ]))), + new FloeSerializer(new AdaptiveBackend()), + ); } protected function dsn(): string 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 96db55cdaa..5c356efd94 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 @@ -7,6 +7,7 @@ use Flow\ETL\Cache\CacheIndex; use Flow\ETL\Cache\Implementation\FilesystemCache; use Flow\ETL\Cache\Implementation\InMemoryCache; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Extractor; use Flow\ETL\Extractor\Statistics; use Flow\ETL\FlowContext; @@ -15,6 +16,7 @@ use Flow\ETL\Tests\Double\FakeExtractor; use Flow\ETL\Tests\Double\SpySerializer; use Flow\ETL\Tests\FlowIntegrationTestCase; +use Flow\Floe\FloeSerializer; use Flow\Telemetry\Context\MemoryContextStorage; use Flow\Telemetry\Logger\LoggerProvider; use Flow\Telemetry\Meter\MeterProvider; @@ -120,9 +122,13 @@ public function test_cache_end_to_end_with_custom_serializer(): void { $input = array_map(static fn(int $i) => ['id' => $i], range(1, 25)); - $defaultCache = new FilesystemCache($this->fs(), path(__DIR__ . '/var/cache-mode-default')); + $defaultCache = new FilesystemCache( + $this->fs(), + new FloeSerializer(new AdaptiveBackend()), + path(__DIR__ . '/var/cache-mode-default'), + ); $spy = new SpySerializer(); - $customCache = new FilesystemCache($this->fs(), path(__DIR__ . '/var/cache-mode-custom'), $spy); + $customCache = new FilesystemCache($this->fs(), $spy, path(__DIR__ . '/var/cache-mode-custom')); df(config_builder()->cache($defaultCache))->read(from_array($input))->batchSize(10)->cache('parity')->run(); df(config_builder()->cache($customCache))->read(from_array($input))->batchSize(10)->cache('parity')->run(); 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 f157fed091..6e2c7e135c 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 @@ -15,6 +15,7 @@ use Flow\ETL\Optimizer; use Flow\ETL\Optimizer\Rule\PushLimitIntoSource; use Flow\ETL\Planner; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\Double\SpySerializer; use Flow\ETL\Tests\FlowIntegrationTestCase; use Override; @@ -26,6 +27,8 @@ use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\memory_sort; use function Flow\ETL\DSL\schema; +use function Flow\Serializer\DSL\serialize_to_string; +use function Flow\Serializer\DSL\unserialize_from_string; use function str_replace; final class ConfigBuilderTest extends FlowIntegrationTestCase @@ -196,4 +199,18 @@ public function test_executor_can_be_overridden(): void static::assertSame($executor, config_builder()->executor($executor)->build()->executor()); } + + public function test_the_default_serializer_follows_a_backend_set_after_a_build(): void + { + $builder = config_builder(); + $builder->build(); + $backend = new SpyBackend(); + $serializer = $builder->backend($backend)->build()->serializer(); + + unserialize_from_string($serializer, serialize_to_string($serializer, array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id'))))); + + static::assertSame(1, $backend->decodes()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/ConfiguredBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/ConfiguredBackendTest.php new file mode 100644 index 0000000000..7a0cddebfe --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/ConfiguredBackendTest.php @@ -0,0 +1,68 @@ +backend(new AdaptiveBackend())) + ->read(from_rows( + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')), new PhpBackend()), + array_to_rows([['id' => 3]], schema(int_schema('id')), new PhpBackend()), + )) + ->batchSize(3) + ->fetch(); + + static::assertSame([1, 2, 3], $rows->column('id')->values()); + static::assertSame( + extension_loaded('flow_php') ? 'Flow\ETL\Column\RustColumn' : 'Flow\ETL\Column\Php\ScalarColumn', + $rows->column('id')::class, + ); + } + + public function test_a_custom_extractor_yielding_php_rows_is_read_into_the_configured_backend(): void + { + $rows = data_frame(config_builder()->backend(new AdaptiveBackend())) + ->read( + new CountingExtractor( + schema(int_schema('id')), + array_to_rows([['id' => 1]], schema(int_schema('id')), new PhpBackend()), + ), + ) + ->fetch(); + + static::assertSame( + extension_loaded('flow_php') ? 'Flow\ETL\Column\RustColumn' : 'Flow\ETL\Column\Php\ScalarColumn', + $rows->column('id')::class, + ); + } + + #[RequiresPhpExtension('flow_php')] + public function test_native_rows_are_read_into_php_columns_under_a_php_backend(): void + { + $rows = data_frame(config_builder()->backend(new PhpBackend())) + ->read(from_rows(array_to_rows([['id' => 1]], schema(int_schema('id')), new RustBackend()))) + ->fetch(); + + static::assertSame([1], $rows->column('id')->values()); + static::assertSame('Flow\ETL\Column\Php\ScalarColumn', $rows->column('id')::class); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinTest.php index 79b67e7601..6bc19c79c0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/DataFrame/JoinTest.php @@ -17,6 +17,7 @@ use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\data_frame; +use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\df; use function Flow\ETL\DSL\from_rows; @@ -525,4 +526,20 @@ public function test_join_right_without_prefix(): void $rows->toArray(), ); } + + public function test_a_date_key_meets_an_equal_datetime_key(): void + { + $rows = df() + ->read(from_rows(array_to_rows([['k' => new DateTimeImmutable('2026-01-02')]], schema(date_schema('k'))))) + ->join( + df()->read(from_rows(array_to_rows([[ + 'r' => new DateTimeImmutable('2026-01-02 00:00:00 UTC'), + ]], schema(datetime_schema('r'))))), + join_on(['k' => 'r']), + Join::inner, + ) + ->fetch(); + + static::assertCount(1, $rows); + } } 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 5bc8570ddb..d2dbf89cca 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 @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Integration\DataFrame; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; @@ -40,7 +41,7 @@ public function test_aggregations_on_floats(): void ))) ->aggregate([sum(ref('price')), sum(ref('weight'))]) ->forEach(static function (Rows $r) use (&$rows): void { - $rows = $rows->merge($r); + $rows = $rows->isEmpty() ? $r : $rows->concat(new PhpBackend(), $r); }); static::assertSame( @@ -73,7 +74,7 @@ public function test_mathematical_operations_on_floats(): void ->withEntry('discount', ref('price')->multiply(-0.1, exact: true)) ->withEntry('total_weight', ref('weight')->multiply(ref('quantity'), exact: true)) ->forEach(static function (Rows $r) use (&$rows): void { - $rows = $rows->merge($r); + $rows = $rows->isEmpty() ? $r : $rows->concat(new PhpBackend(), $r); }); static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/CacheExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/CacheExtractorTest.php index 295dee42e5..32cf5f4fc6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/CacheExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Extractor/CacheExtractorTest.php @@ -8,12 +8,15 @@ use Flow\ETL\Cache\Implementation\FilesystemCache; use Flow\ETL\Cache\Implementation\InMemoryCache; use Flow\ETL\Cardinality; +use Flow\ETL\Column\AdaptiveBackend; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Extractor\Signal; use Flow\ETL\Rows; use Flow\ETL\Tests\Double\CountingCache; use Flow\ETL\Tests\Double\CountingExtractor; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\ETL\Tests\Mother\RowsMother; +use Flow\Floe\FloeSerializer; use function array_map; use function array_merge; @@ -127,7 +130,7 @@ public function test_extracting_rows_from_cache(): void flow_context(config())->backend(), )); - $cache->set('key', $index->toRows()); + $cache->set('key', $index->toRows(new PhpBackend())); $extractor = from_cache($cacheKey); @@ -165,7 +168,7 @@ public function test_extracting_rows_from_cache_with_clearing_cache_afterwards() flow_context(config())->backend(), )); - $cache->set('key', $index->toRows()); + $cache->set('key', $index->toRows(new PhpBackend())); $extractor = from_cache($cacheKey)->withClearOnFinish(true); @@ -180,7 +183,11 @@ public function test_extracting_rows_from_cache_with_clearing_cache_afterwards() public function test_extracting_rows_from_filesystem_cache(): void { - $cache = new FilesystemCache($this->fs(), path(__DIR__ . '/var/cache-extractor-streaming')); + $cache = new FilesystemCache( + $this->fs(), + new FloeSerializer(new AdaptiveBackend()), + path(__DIR__ . '/var/cache-extractor-streaming'), + ); $cache->clear(); $index = new CacheIndex($cacheKey = 'key'); @@ -197,7 +204,7 @@ public function test_extracting_rows_from_filesystem_cache(): void schema(int_schema('id')), flow_context(config())->backend(), )); - $cache->set('key', $index->toRows()); + $cache->set('key', $index->toRows(new PhpBackend())); $extractor = from_cache($cacheKey); @@ -214,7 +221,11 @@ public function test_extracting_rows_from_filesystem_cache(): void public function test_stop_signal_stops_extraction_and_skips_clearing(): void { - $cache = new FilesystemCache($this->fs(), path(__DIR__ . '/var/cache-extractor-streaming-stop')); + $cache = new FilesystemCache( + $this->fs(), + new FloeSerializer(new AdaptiveBackend()), + path(__DIR__ . '/var/cache-extractor-streaming-stop'), + ); $cache->clear(); $index = new CacheIndex($cacheKey = 'key'); @@ -231,7 +242,7 @@ public function test_stop_signal_stops_extraction_and_skips_clearing(): void schema(int_schema('id')), flow_context(config())->backend(), )); - $cache->set('key', $index->toRows()); + $cache->set('key', $index->toRows(new PhpBackend())); $generator = from_cache($cacheKey) ->withClearOnFinish(true) 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 138eac2586..5ef3666968 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 @@ -5,6 +5,7 @@ namespace Flow\ETL\Tests\Integration\Extractor; use Flow\ETL\Cardinality; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Extractor\PathPartitionsExtractor; use Flow\ETL\Rows; use Flow\ETL\Tests\Context\ExtractedRows; @@ -89,7 +90,7 @@ public function test_extracting_data_from_path_partitions(): void foreach ($extractedData as $nextRows) { static::assertInstanceOf(Rows::class, $nextRows); - $rows = $rows->merge($nextRows); + $rows = $rows->isEmpty() ? $nextRows : $rows->concat(new PhpBackend(), $nextRows); } static::assertSame(7, $rows->count()); @@ -194,6 +195,44 @@ public function test_batches_at_the_configured_batch_size(): void static::assertSame([2, 2, 2, 1], $sizes); } + public function test_every_row_of_a_batch_carries_its_own_files_partition_value(): void + { + $batches = iterator_to_array( + from_path_partitions('memory://dir/**/*.txt', MemoryFiles::with([ + 'memory://dir/year=2023/a.txt' => 'a', + 'memory://dir/year=2024/b.txt' => 'b', + 'memory://dir/year=2025/c.txt' => 'c', + ])) + ->withBatchSize(3) + ->extract(flow_context()), + false, + ); + + static::assertCount(1, $batches); + static::assertSame(['2023', '2024', '2025'], $batches[0]->column('year')->values()); + static::assertSame( + [['year' => '2023'], ['year' => '2024'], ['year' => '2025']], + $batches[0]->column('partitions')->values(), + ); + } + + public function test_a_limit_at_the_batch_boundary_keeps_each_rows_partition_value(): void + { + $batches = iterator_to_array( + from_path_partitions('memory://dir/**/*.txt', MemoryFiles::with([ + 'memory://dir/year=2023/a.txt' => 'a', + 'memory://dir/year=2024/b.txt' => 'b', + 'memory://dir/year=2025/c.txt' => 'c', + ])) + ->withBatchSize(2) + ->extract(flow_context(), limit: 2), + false, + ); + + static::assertCount(1, $batches); + static::assertSame(['2023', '2024'], $batches[0]->column('year')->values()); + } + public function test_path_partitions_extractor_honours_the_batch_contract(): void { self::assertExtractorHonoursBatchContract( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/FilesSinkTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/FilesSinkTest.php similarity index 87% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/FilesSinkTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/FilesSinkTest.php index 99042d3479..fbf336f780 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/FilesSinkTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/FilesSinkTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; +use Flow\ETL\Loader\File\FilesSink; use Flow\Filesystem\Exception\RuntimeException as FilesystemRuntimeException; use Flow\Filesystem\FileListing; use Flow\Filesystem\Path\Filter\KeepAll; @@ -194,37 +194,6 @@ public function test_abandoning_a_published_set_does_nothing(): void static::assertSame('some content', file_get_contents($file->path())); } - public function test_touched_reports_a_file_this_run_has_written_to(): void - { - $this->setupFiles([__FUNCTION__ => []]); - - $files = $this->files($this->getPath(__FUNCTION__ . '/file.txt')); - - static::assertFalse($files->touched()); - - $files->writeTo(); - - static::assertTrue($files->touched()); - - $files->publish(); - - static::assertFalse($files->touched()); - } - - public function test_open_streams_lists_only_streams_that_are_still_open(): void - { - $this->setupFiles([__FUNCTION__ => []]); - - $files = $this->files($this->getPath(__FUNCTION__ . '/file.txt')); - $stream = $files->writeTo(); - - static::assertSame([$stream], iterator_to_array($files->openStreams(), false)); - - $stream->close(); - - static::assertSame([], iterator_to_array($files->openStreams(), false)); - } - public function test_open_two_write_streams_to_stdout(): void { $this->expectExceptionMessage('Only one stream can be open at the same time for php://stdout'); @@ -257,10 +226,7 @@ public function test_scan(): void public function test_write_to_stdout(): void { - $files = $this->files(path('stdout://a.stdout'), stdout_filesystem()); - $files->writeTo(); - - static::assertTrue($files->touched()); + static::assertTrue($this->files(path('stdout://a.stdout'), stdout_filesystem())->writeTo()->isOpen()); } protected function saveMode(): SaveMode diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/FilesSinkTestCase.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/FilesSinkTestCase.php similarity index 85% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/FilesSinkTestCase.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/FilesSinkTestCase.php index 41da826ed0..593e84e9bc 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/FilesSinkTestCase.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/FilesSinkTestCase.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; +use Flow\ETL\Loader\File\FilesSink; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Filesystem\Filesystem; use Flow\Filesystem\Path; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/AppendModeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/AppendModeTest.php similarity index 92% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/AppendModeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/AppendModeTest.php index 6d6c5f584d..2aed26b855 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/AppendModeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/AppendModeTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\NotPartitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\NotPartitioned; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Override; use function Flow\ETL\DSL\append; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/ExceptionIfExistsModeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/ExceptionIfExistsModeTest.php similarity index 90% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/ExceptionIfExistsModeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/ExceptionIfExistsModeTest.php index f626629148..9efcfa5472 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/ExceptionIfExistsModeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/ExceptionIfExistsModeTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\NotPartitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\NotPartitioned; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Override; use function file_get_contents; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/IgnoreModeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/IgnoreModeTest.php similarity index 90% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/IgnoreModeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/IgnoreModeTest.php index cb990e50d2..94b22da14b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/IgnoreModeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/IgnoreModeTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\NotPartitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\NotPartitioned; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Override; use function file_get_contents; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/OverwriteModeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/OverwriteModeTest.php similarity index 91% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/OverwriteModeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/OverwriteModeTest.php index 685f65de04..c1afb09c31 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/NotPartitioned/OverwriteModeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/NotPartitioned/OverwriteModeTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\NotPartitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\NotPartitioned; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Loader\File\FilesSink; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Override; use function file_get_contents; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/AppendModeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/AppendModeTest.php similarity index 95% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/AppendModeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/AppendModeTest.php index 54f4cfc6a4..f39cf2c6c7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/AppendModeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/AppendModeTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\Partitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\Partitioned; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Flow\Filesystem\Partition; use Override; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/ExceptionIfExistsModeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/ExceptionIfExistsModeTest.php similarity index 94% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/ExceptionIfExistsModeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/ExceptionIfExistsModeTest.php index 7884b49d00..7835809f2b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/ExceptionIfExistsModeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/ExceptionIfExistsModeTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\Partitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\Partitioned; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Flow\Filesystem\Partition; use Override; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/IgnoreModeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/IgnoreModeTest.php similarity index 95% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/IgnoreModeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/IgnoreModeTest.php index eb473ee071..60a772eea7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/IgnoreModeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/IgnoreModeTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\Partitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\Partitioned; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Flow\Filesystem\Partition; use Override; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/OverwriteModeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/OverwriteModeTest.php similarity index 95% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/OverwriteModeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/OverwriteModeTest.php index 2200702510..ac58c721bb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/OverwriteModeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/OverwriteModeTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\Partitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\Partitioned; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Loader\File\FilesSink; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Flow\Filesystem\Partition; use Flow\Filesystem\Tests\Double\FakeNativeLocalFilesystem; use Override; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/OverwriteMultipleFilesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/OverwriteMultipleFilesTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/OverwriteMultipleFilesTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/OverwriteMultipleFilesTest.php index 37e1c3792f..cc276e58f9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/OverwriteMultipleFilesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/OverwriteMultipleFilesTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\Partitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\Partitioned; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Flow\Filesystem\Partition; use Override; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/PartitionPlaceholdersTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/PartitionPlaceholdersTest.php similarity index 97% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/PartitionPlaceholdersTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/PartitionPlaceholdersTest.php index 83aa851060..87d1cd1705 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/Partitioned/PartitionPlaceholdersTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/Partitioned/PartitionPlaceholdersTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Integration\Filesystem\FilesSink\Partitioned; +namespace Flow\ETL\Tests\Integration\Loader\File\FilesSink\Partitioned; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Filesystem\FilesSink; use Flow\ETL\Filesystem\SaveMode; -use Flow\ETL\Tests\Integration\Filesystem\FilesSink\FilesSinkTestCase; +use Flow\ETL\Loader\File\FilesSink; +use Flow\ETL\Tests\Integration\Loader\File\FilesSink\FilesSinkTestCase; use Flow\Filesystem\FileListing; use Flow\Filesystem\Partition; use Flow\Filesystem\Path\Filter\OnlyFiles; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/tmp/.gitignore b/src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/tmp/.gitignore similarity index 100% rename from src/core/etl/tests/Flow/ETL/Tests/Integration/Filesystem/FilesSink/tmp/.gitignore rename to src/core/etl/tests/Flow/ETL/Tests/Integration/Loader/File/FilesSink/tmp/.gitignore diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php index e4fa99922f..a951db54fe 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Bucketing/Storage/PSRCacheBucketsTest.php @@ -5,9 +5,11 @@ namespace Flow\ETL\Tests\Unit\Bucketing\Storage; use Flow\ETL\Bucketing\Storage\PSRCacheBuckets; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Tests\Context\BucketsStorageContext; use Flow\ETL\Tests\Double\ArrayCache; use Flow\ETL\Tests\FlowTestCase; +use Flow\Floe\FloeSerializer; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\int_schema; @@ -18,7 +20,7 @@ final class PSRCacheBucketsTest extends FlowTestCase { public function test_append_then_get_returns_rows_in_order_across_chunks(): void { - $storage = new PSRCacheBuckets(new ArrayCache()); + $storage = new PSRCacheBuckets(new ArrayCache(), new FloeSerializer(new AdaptiveBackend())); $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 3]], schema(int_schema('id')))); @@ -28,7 +30,11 @@ public function test_append_then_get_returns_rows_in_order_across_chunks(): void public function test_custom_prefix_is_used_in_keys(): void { $cache = new ArrayCache(); - (new PSRCacheBuckets($cache, prefix: 'custom:pfx'))->append('bucket', array_to_rows([[ + (new PSRCacheBuckets( + $cache, + new FloeSerializer(new AdaptiveBackend()), + prefix: 'custom:pfx', + ))->append('bucket', array_to_rows([[ 'id' => 1, ]], schema(int_schema('id')))); @@ -42,7 +48,12 @@ public function test_get_skips_non_string_chunk_payloads(): void $cache->set('flow:buckets:bucket:chunks', 1); $cache->set('flow:buckets:bucket:chunk:0', 123); - static::assertSame([], BucketsStorageContext::rows((new PSRCacheBuckets($cache))->get('bucket'))); + static::assertSame( + [], + BucketsStorageContext::rows((new PSRCacheBuckets($cache, new FloeSerializer(new AdaptiveBackend())))->get( + 'bucket', + )), + ); } public function test_get_treats_non_integer_chunk_counter_as_empty(): void @@ -50,18 +61,29 @@ public function test_get_treats_non_integer_chunk_counter_as_empty(): void $cache = new ArrayCache(); $cache->set('flow:buckets:bucket:chunks', 'garbage'); - static::assertSame([], BucketsStorageContext::rows((new PSRCacheBuckets($cache))->get('bucket'))); + static::assertSame( + [], + BucketsStorageContext::rows((new PSRCacheBuckets($cache, new FloeSerializer(new AdaptiveBackend())))->get( + 'bucket', + )), + ); } public function test_get_unknown_bucket_yields_nothing(): void { - static::assertSame([], BucketsStorageContext::rows((new PSRCacheBuckets(new ArrayCache()))->get('unknown'))); + static::assertSame( + [], + BucketsStorageContext::rows((new PSRCacheBuckets( + new ArrayCache(), + new FloeSerializer(new AdaptiveBackend()), + ))->get('unknown')), + ); } public function test_remove_deletes_all_chunk_keys_and_the_counter(): void { $cache = new ArrayCache(); - $storage = new PSRCacheBuckets($cache); + $storage = new PSRCacheBuckets($cache, new FloeSerializer(new AdaptiveBackend())); $storage->append('bucket', array_to_rows([['id' => 1]], schema(int_schema('id')))); $storage->append('bucket', array_to_rows([['id' => 2]], schema(int_schema('id')))); @@ -75,7 +97,7 @@ public function test_remove_deletes_all_chunk_keys_and_the_counter(): void public function test_round_trips_schema_changing_rows(): void { - $storage = new PSRCacheBuckets(new ArrayCache()); + $storage = new PSRCacheBuckets(new ArrayCache(), new FloeSerializer(new AdaptiveBackend())); $input = array_to_rows( [['id' => 1], ['id' => 2, 'name' => 'John'], ['name' => 'Jane']], schema(int_schema('id', nullable: true), str_schema('name', nullable: true)), @@ -87,7 +109,7 @@ public function test_round_trips_schema_changing_rows(): void public function test_set_replaces_previous_content(): void { - $storage = new PSRCacheBuckets(new ArrayCache()); + $storage = new PSRCacheBuckets(new ArrayCache(), new FloeSerializer(new AdaptiveBackend())); $storage->append('bucket', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); $storage->set('bucket', array_to_rows([['id' => 42]], schema(int_schema('id')))); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/CacheIndexTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/CacheIndexTest.php index 97b23f9896..8fe275a0bd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/CacheIndexTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/CacheIndexTest.php @@ -6,6 +6,7 @@ use Flow\ETL\Cache\CacheIndex; use Flow\ETL\Cardinality; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\FlowTestCase; @@ -20,7 +21,7 @@ public function test_empty_index_round_trip(): void { $index = new CacheIndex('dataset-id'); - $indexRows = $index->toRows(); + $indexRows = $index->toRows(new PhpBackend()); static::assertCount(0, $indexRows); static::assertEquals($index, CacheIndex::fromRows('dataset-id', $indexRows)); @@ -53,7 +54,7 @@ public function test_from_rows_key_comes_from_the_argument(): void $index = new CacheIndex('original-key'); $index->add('chunk-1'); - $reconstructed = CacheIndex::fromRows('different-key', $index->toRows()); + $reconstructed = CacheIndex::fromRows('different-key', $index->toRows(new PhpBackend())); static::assertSame('different-key', $reconstructed->key); static::assertSame(['chunk-1'], $reconstructed->values()); @@ -92,7 +93,10 @@ public function test_rows_sum_the_chunk_counts(): void $index->add('chunk-2', 0); $index->add('chunk-3', 4); - static::assertEquals(Cardinality::exact(7), CacheIndex::fromRows('dataset-id', $index->toRows())->rows()); + static::assertEquals( + Cardinality::exact(7), + CacheIndex::fromRows('dataset-id', $index->toRows(new PhpBackend()))->rows(), + ); } public function test_to_rows_from_rows_round_trip_preserves_order(): void @@ -102,7 +106,7 @@ public function test_to_rows_from_rows_round_trip_preserves_order(): void $index->add('chunk-a'); $index->add('chunk-c'); - $reconstructed = CacheIndex::fromRows('dataset-id', $index->toRows()); + $reconstructed = CacheIndex::fromRows('dataset-id', $index->toRows(new PhpBackend())); static::assertEquals($index, $reconstructed); static::assertSame(['chunk-b', 'chunk-a', 'chunk-c'], $reconstructed->values()); @@ -119,7 +123,7 @@ public function test_to_rows_stores_one_key_and_rows_entry_per_chunk(): void [['key' => 'chunk-1', 'rows' => 2], ['key' => 'chunk-2', 'rows' => null]], schema(str_schema('key'), int_schema('rows', nullable: true)), ), - $index->toRows(), + $index->toRows(new PhpBackend()), ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/ApcuCacheTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/ApcuCacheTest.php index ae54535208..c39d2ff38c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/ApcuCacheTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Cache/Implementation/ApcuCacheTest.php @@ -5,9 +5,11 @@ namespace Flow\ETL\Tests\Unit\Cache\Implementation; use Flow\ETL\Cache\Implementation\ApcuCache; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\KeyNotInCacheException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\FlowTestCase; +use Flow\Floe\FloeSerializer; use Override; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\RequiresPhpExtension; @@ -34,8 +36,8 @@ protected function setUp(): void static::markTestSkipped('APCu is not enabled for CLI (apc.enable_cli=0).'); } - $this->cache = new ApcuCache('flow_php_cache_test'); - $this->otherCache = new ApcuCache('flow_php_cache_test_other'); + $this->cache = new ApcuCache(new FloeSerializer(new PhpBackend()), 'flow_php_cache_test'); + $this->otherCache = new ApcuCache(new FloeSerializer(new PhpBackend()), 'flow_php_cache_test_other'); $this->cache->clear(); $this->otherCache->clear(); @@ -105,6 +107,16 @@ public function test_clearing_cache_removes_schemas(): void $this->cache->schema('rows'); } + public function test_getting_an_entry_another_writer_stored(): void + { + apcu_store('flow_php_cache_test:rows', array_to_rows([['id' => 1]], schema(int_schema('id')))); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Cache entry for key "rows" is corrupted or was not written by ApcuCache.'); + + $this->cache->get('rows'); + } + public function test_getting_corrupted_schema_entry(): void { apcu_store('flow_php_cache_test:rows:schema', 'not a schema'); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php index 0e56b06ae0..75820ec8fe 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php @@ -5,8 +5,8 @@ namespace Flow\ETL\Tests\Unit\Column; use Flow\ETL\Column\AdaptiveBackend; -use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Tests\Double\ForeignColumnStub; use Flow\ETL\Tests\Mother\ColumnMother; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php index 2181bf1e8e..8330844dd2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ComparableValuesTest.php @@ -50,7 +50,6 @@ public static function ordered(): Generator datetime_schema('a'), [new DateTimeImmutable('2024-01-02'), new DateTimeImmutable('2024-01-01')], ]; - yield 'date' => [date_schema('a'), [new DateTimeImmutable('2024-01-02'), new DateTimeImmutable('2024-01-01')]]; yield 'time' => [time_schema('a'), ['PT2H', 'PT1H']]; } @@ -148,4 +147,18 @@ public function test_ordered_types_read_physicals(Definition $definition, array static::assertSame($column->physicals(), (new ComparableValues())->ordering($column)); static::assertSame($column->physicals(), (new ComparableValues())->equality($column)); } + + public function test_a_date_compares_on_the_datetime_microsecond_scale(): void + { + $column = ColumnMother::of(date_schema('a', nullable: true), [new DateTimeImmutable('2024-01-02'), null]); + + static::assertSame([1_704_153_600_000_000, null], (new ComparableValues())->ordering($column)); + static::assertSame([1_704_153_600_000_000, null], (new ComparableValues())->equality($column)); + static::assertSame( + (new ComparableValues())->equality(ColumnMother::of(datetime_schema('a'), [new DateTimeImmutable( + '2024-01-02 00:00:00 UTC', + )])), + [(new ComparableValues())->equality($column)[0]], + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BooleanLayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BooleanLayoutTest.php similarity index 92% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BooleanLayoutTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BooleanLayoutTest.php index 4c41264f34..20ab3e713d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BooleanLayoutTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BooleanLayoutTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\BooleanLayout; -use Flow\ETL\Column\Php\Buffers; +use Flow\ETL\Column\Layout\BooleanLayout; +use Flow\ETL\Column\Layout\Buffers; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/BufferLayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BufferLayoutTest.php similarity index 98% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/BufferLayoutTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BufferLayoutTest.php index 41a2bbae34..e5c7dec134 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/BufferLayoutTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BufferLayoutTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\BufferLayout; +use Flow\ETL\Column\Layout\BufferLayout; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\Mother\ColumnMother; use Flow\Types\Type; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BuffersTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BuffersTest.php similarity index 91% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BuffersTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BuffersTest.php index 852e3142e1..e361b91e77 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/BuffersTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/BuffersTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\Buffers; +use Flow\ETL\Column\Layout\Buffers; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/FixedBinary16LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/FixedBinary16LayoutTest.php similarity index 89% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/FixedBinary16LayoutTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/FixedBinary16LayoutTest.php index d698c858ba..c762de9b2c 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/FixedBinary16LayoutTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/FixedBinary16LayoutTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\Buffers; -use Flow\ETL\Column\Php\FixedBinary16Layout; +use Flow\ETL\Column\Layout\Buffers; +use Flow\ETL\Column\Layout\FixedBinary16Layout; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Float64LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Float64LayoutTest.php similarity index 89% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Float64LayoutTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Float64LayoutTest.php index fde9eeee8b..8502ac0a52 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Float64LayoutTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Float64LayoutTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\Buffers; -use Flow\ETL\Column\Php\Float64Layout; +use Flow\ETL\Column\Layout\Buffers; +use Flow\ETL\Column\Layout\Float64Layout; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int32LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Int32LayoutTest.php similarity index 90% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int32LayoutTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Int32LayoutTest.php index 0716ba4d61..4289ba3400 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int32LayoutTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Int32LayoutTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\Buffers; -use Flow\ETL\Column\Php\Int32Layout; +use Flow\ETL\Column\Layout\Buffers; +use Flow\ETL\Column\Layout\Int32Layout; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int64LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Int64LayoutTest.php similarity index 91% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int64LayoutTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Int64LayoutTest.php index 36727b58ef..f72b88f103 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Int64LayoutTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Int64LayoutTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\Buffers; -use Flow\ETL\Column\Php\Int64Layout; +use Flow\ETL\Column\Layout\Buffers; +use Flow\ETL\Column\Layout\Int64Layout; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/LayoutForTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/LayoutForTest.php similarity index 90% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/LayoutForTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/LayoutForTest.php index 0538bece0a..e98384bf2d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/LayoutForTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/LayoutForTest.php @@ -2,15 +2,15 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\BooleanLayout; -use Flow\ETL\Column\Php\FixedBinary16Layout; -use Flow\ETL\Column\Php\Float64Layout; -use Flow\ETL\Column\Php\Int32Layout; -use Flow\ETL\Column\Php\Int64Layout; -use Flow\ETL\Column\Php\LayoutFor; -use Flow\ETL\Column\Php\Utf8Layout; +use Flow\ETL\Column\Layout\BooleanLayout; +use Flow\ETL\Column\Layout\FixedBinary16Layout; +use Flow\ETL\Column\Layout\Float64Layout; +use Flow\ETL\Column\Layout\Int32Layout; +use Flow\ETL\Column\Layout\Int64Layout; +use Flow\ETL\Column\Layout\LayoutFor; +use Flow\ETL\Column\Layout\Utf8Layout; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; use Flow\Types\Type; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullCountTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/NullCountTest.php similarity index 78% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullCountTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/NullCountTest.php index ba4f3f5c16..bb9551bef6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullCountTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/NullCountTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\NullCount; +use Flow\ETL\Column\Layout\NullCount; use PHPUnit\Framework\TestCase; final class NullCountTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/OffsetsTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/OffsetsTest.php index 29cc741e73..c4a1d6cbcf 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/OffsetsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/OffsetsTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\Offsets; +use Flow\ETL\Column\Layout\Offsets; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\OffsetOverflow; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Utf8LayoutTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Utf8LayoutTest.php similarity index 90% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Utf8LayoutTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Utf8LayoutTest.php index 81350102ff..c0675f16bd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/Utf8LayoutTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/Utf8LayoutTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\Buffers; -use Flow\ETL\Column\Php\Utf8Layout; +use Flow\ETL\Column\Layout\Buffers; +use Flow\ETL\Column\Layout\Utf8Layout; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValidityTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/ValidityTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValidityTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/ValidityTest.php index 2f2abf0036..44d7a04291 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValidityTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Layout/ValidityTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Layout; -use Flow\ETL\Column\Php\Validity; +use Flow\ETL\Column\Layout\Validity; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/CastingColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/CastingColumnBuilderTest.php index 7f6c277fc1..28f7416796 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/CastingColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/CastingColumnBuilderTest.php @@ -6,12 +6,21 @@ use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\ColumnMismatchException; +use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Tests\Mother\ColumnMother; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\list_schema; use function Flow\ETL\DSL\null_schema; +use function Flow\ETL\DSL\uuid_schema; +use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_string; final class CastingColumnBuilderTest extends TestCase { @@ -86,4 +95,75 @@ public function test_append_take_refuses_null_under_not_null(): void ->builder(int_schema('a')) ->appendTake(ColumnMother::of(int_schema('a', nullable: true), [1, null]), [0, 1]); } + + #[TestWith([2])] + #[TestWith([null])] + public function test_append_physicals_takes_physicals_with_nulls(?int $nullCount): void + { + $builder = (new PhpBackend())->builder(int_schema('id', nullable: true)); + $builder->appendPhysicals([1, null, 3, null], $nullCount); + $column = $builder->finish(); + + static::assertSame([1, null, 3, null], $column->values()); + static::assertSame(2, $column->nullCount()); + } + + public function test_append_physicals_refuses_null_under_not_null_at_its_position(): void + { + $builder = (new PhpBackend())->builder(int_schema('id')); + + try { + $builder->appendPhysicals([1, 2, null]); + static::fail('a null under NOT NULL must be refused'); + } catch (SchemaMismatchException $e) { + static::assertSame(2, $e->rowIndex); + } + + static::assertSame(0, $builder->count()); + } + + public function test_append_physicals_of_nothing_appends_nothing(): void + { + $builder = (new PhpBackend())->builder(int_schema('id')); + $builder->appendPhysicals([], 0); + + static::assertSame(0, $builder->finish()->count()); + } + + #[TestWith(['integer', '1'])] + #[TestWith(['float', 1])] + #[TestWith(['datetime', 'not micros'])] + #[TestWith(['uuid', 'too short'])] + #[TestWith(['list', 'not an array'])] + #[TestWith(['list_of_int', ['1']])] + public function test_append_physicals_refuses_a_physical_of_another_kind_and_appends_nothing( + string $definition, + mixed $physical, + ): void { + $builder = (new PhpBackend())->builder(match ($definition) { + 'integer' => int_schema('c'), + 'float' => float_schema('c'), + 'datetime' => datetime_schema('c'), + 'uuid' => uuid_schema('c'), + 'list' => list_schema('c', type_list(type_string())), + default => list_schema('c', type_list(type_integer())), + }); + + try { + $builder->appendPhysicals([$physical]); + static::fail('a physical of another kind must be refused'); + } catch (InvalidArgumentException $e) { + static::assertStringContainsString('physical in a', $e->getMessage()); + } + + static::assertSame(0, $builder->count()); + } + + public function test_append_physicals_stores_any_physical_of_a_null_column_as_null(): void + { + $builder = (new PhpBackend())->builder(null_schema('c')); + $builder->appendPhysicals([null]); + + static::assertSame([null], $builder->finish()->physicals()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php index 47686e3b69..05e62194b9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ColumnDecoderTest.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Tests\Unit\Column\Php; -use Flow\ETL\Column\Php\Buffers; +use Flow\ETL\Column\Layout\Buffers; use Flow\ETL\Column\Php\ColumnDecoder; use Flow\ETL\Column\Php\ConstantColumn; use Flow\ETL\Exception\InvalidArgumentException; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ConstantColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ConstantColumnTest.php index 1e974d8220..4dc098ded7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ConstantColumnTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ConstantColumnTest.php @@ -7,11 +7,11 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Column\Php\ConstantColumn; -use Flow\ETL\Column\Php\IdentityPhysical; use Flow\ETL\Column\Php\ListColumn; -use Flow\ETL\Column\Php\NullPhysical; -use Flow\ETL\Column\Php\TimeZonePhysical; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\Physical\IdentityPhysical; +use Flow\ETL\Column\Physical\NullPhysical; +use Flow\ETL\Column\Physical\TimeZonePhysical; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\Mother\ColumnMother; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php index c9493f7dbb..edfc094938 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListColumnBuilderTest.php @@ -4,10 +4,10 @@ namespace Flow\ETL\Tests\Unit\Column\Php; -use Flow\ETL\Column\Php\IdentityPhysical; use Flow\ETL\Column\Php\ListColumn; use Flow\ETL\Column\Php\ListColumnBuilder; use Flow\ETL\Column\Php\ScalarColumnBuilder; +use Flow\ETL\Column\Physical\IdentityPhysical; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_integer; @@ -22,7 +22,7 @@ public function test_builds_offsets_and_nulls(): void new ScalarColumnBuilder(type_integer(), new IdentityPhysical()), ); $builder->appendPhysical([5 => 1, 9 => 2]); - $builder->appendPhysicalMany([null, [], [3]]); + $builder->appendPhysicals([null, [], [3]]); static::assertSame(4, $builder->count()); @@ -45,7 +45,7 @@ public function test_a_bulk_append_builds_the_column_row_by_row_appends_build(): ), ); $bulk = $builder(); - $bulk->appendPhysicalMany($physicals); + $bulk->appendPhysicals($physicals); $rowByRow = $builder(); foreach ($physicals as $physical) { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnBuilderTest.php index 0d60d4a2e9..4735093aca 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapColumnBuilderTest.php @@ -4,10 +4,10 @@ namespace Flow\ETL\Tests\Unit\Column\Php; -use Flow\ETL\Column\Php\IdentityPhysical; use Flow\ETL\Column\Php\MapColumn; use Flow\ETL\Column\Php\MapColumnBuilder; use Flow\ETL\Column\Php\ScalarColumnBuilder; +use Flow\ETL\Column\Physical\IdentityPhysical; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_integer; @@ -24,7 +24,7 @@ public function test_builds_offsets_keys_values_and_nulls(): void new ScalarColumnBuilder(type_integer(), new IdentityPhysical()), ); $builder->appendPhysical(['a' => 1, 'b' => 2]); - $builder->appendPhysicalMany([null, ['c' => 3]]); + $builder->appendPhysicals([null, ['c' => 3]]); static::assertSame(3, $builder->count()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullColumnBuilderTest.php index 54741532e7..fb7b43d519 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullColumnBuilderTest.php @@ -16,7 +16,7 @@ public function test_counts_rows_into_a_null_constant(): void { $builder = new NullColumnBuilder(type_null()); $builder->appendPhysical(null); - $builder->appendPhysicalMany([null, null]); + $builder->appendPhysicals([null, null]); static::assertSame(3, $builder->count()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php index 2fc0509116..44fdcddc95 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnBuilderTest.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Tests\Unit\Column\Php; -use Flow\ETL\Column\Php\IdentityPhysical; use Flow\ETL\Column\Php\ScalarColumnBuilder; +use Flow\ETL\Column\Physical\IdentityPhysical; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_integer; @@ -18,7 +18,7 @@ public function test_collects_physicals_and_counts_nulls(): void $builder = new ScalarColumnBuilder(type_optional(type_integer()), new IdentityPhysical()); $builder->appendPhysical(1); $builder->appendPhysical(null); - $builder->appendPhysicalMany([null, 4]); + $builder->appendPhysicals([null, 4]); static::assertSame(4, $builder->count()); @@ -31,8 +31,8 @@ public function test_collects_physicals_and_counts_nulls(): void public function test_takes_the_null_count_the_caller_already_counted(): void { $builder = new ScalarColumnBuilder(type_optional(type_integer()), new IdentityPhysical()); - $builder->appendPhysicalMany([1, null], 1); - $builder->appendPhysicalMany([null, null, 5], 2); + $builder->appendPhysicals([1, null], 1); + $builder->appendPhysicals([null, null, 5], 2); $column = $builder->finish(); @@ -43,7 +43,7 @@ public function test_takes_the_null_count_the_caller_already_counted(): void public function test_a_bulk_append_counts_only_nulls(): void { $builder = new ScalarColumnBuilder(type_optional(type_integer()), new IdentityPhysical()); - $builder->appendPhysicalMany([0, '', false, null, '0']); + $builder->appendPhysicals([0, '', false, null, '0']); $column = $builder->finish(); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnTest.php index fab8565de0..3d33417579 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ScalarColumnTest.php @@ -6,7 +6,7 @@ use DateTimeZone; use Flow\ETL\Column\Php\ScalarColumn; -use Flow\ETL\Column\Php\TimeZonePhysical; +use Flow\ETL\Column\Physical\TimeZonePhysical; use Flow\ETL\Tests\Mother\ColumnMother; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php index 2c6ffcff93..5bb7d4e1ea 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructColumnBuilderTest.php @@ -4,11 +4,11 @@ namespace Flow\ETL\Tests\Unit\Column\Php; -use Flow\ETL\Column\Php\IdentityPhysical; use Flow\ETL\Column\Php\ListColumnBuilder; use Flow\ETL\Column\Php\ScalarColumnBuilder; use Flow\ETL\Column\Php\StructColumn; use Flow\ETL\Column\Php\StructColumnBuilder; +use Flow\ETL\Column\Physical\IdentityPhysical; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_integer; @@ -24,7 +24,7 @@ public function test_a_null_parent_sets_every_child_bit_to_zero(): void 'b' => new ScalarColumnBuilder(type_integer(), new IdentityPhysical()), ]); $builder->appendPhysical(['b' => 2, 'a' => 1]); - $builder->appendPhysicalMany([null, ['a' => 3]]); + $builder->appendPhysicals([null, ['a' => 3]]); static::assertSame(3, $builder->count()); @@ -50,7 +50,7 @@ public function test_a_bulk_append_builds_the_column_row_by_row_appends_build(): ], ); $bulk = $builder(); - $bulk->appendPhysicalMany($physicals); + $bulk->appendPhysicals($physicals); $rowByRow = $builder(); foreach ($physicals as $physical) { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php index 852900d5c0..921c386c9f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/PhpBackendTest.php @@ -9,10 +9,10 @@ use DateTimeZone; use Dom\HTMLDocument; use Dom\HTMLElement; -use Flow\ETL\Column\Php\HtmlDocumentPhysical; -use Flow\ETL\Column\Php\HtmlElementPhysical; -use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\Physical\HtmlDocumentPhysical; +use Flow\ETL\Column\Physical\HtmlElementPhysical; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DatePhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DatePhysicalTest.php similarity index 94% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DatePhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DatePhysicalTest.php index 323fec34ca..bd5b7ee498 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DatePhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DatePhysicalTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DateTimeImmutable; use DateTimeZone; -use Flow\ETL\Column\Php\DatePhysical; +use Flow\ETL\Column\Physical\DatePhysical; use Flow\Types\Exception\CastingException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DateTimePhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DateTimePhysicalTest.php similarity index 95% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DateTimePhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DateTimePhysicalTest.php index e3057c888e..3012d1fa61 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DateTimePhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DateTimePhysicalTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DateTimeImmutable; use DateTimeZone; -use Flow\ETL\Column\Php\DateTimePhysical; +use Flow\ETL\Column\Physical\DateTimePhysical; use Flow\Types\Exception\CastingException; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DaysFromCivilTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DaysFromCivilTest.php similarity index 88% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DaysFromCivilTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DaysFromCivilTest.php index 4b955a6c34..86123b068a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/DaysFromCivilTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/DaysFromCivilTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\DaysFromCivil; +use Flow\ETL\Column\Physical\DaysFromCivil; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/ElementPositionTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/ElementPositionTest.php index 3ae3f5de5e..f26d982423 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ElementPositionTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/ElementPositionTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DOMDocument; use DOMElement; -use Flow\ETL\Column\Php\ElementPosition; +use Flow\ETL\Column\Physical\ElementPosition; use PHPUnit\Framework\TestCase; use function Flow\Types\DSL\type_instance_of; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/EnumPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/EnumPhysicalTest.php similarity index 85% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/EnumPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/EnumPhysicalTest.php index cc4a409a37..834e2dc79f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/EnumPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/EnumPhysicalTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\EnumPhysical; +use Flow\ETL\Column\Physical\EnumPhysical; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/HtmlDocumentPhysicalTest.php similarity index 92% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/HtmlDocumentPhysicalTest.php index 068ffad461..8997be5485 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlDocumentPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/HtmlDocumentPhysicalTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\HtmlDocumentPhysical; +use Flow\ETL\Column\Physical\HtmlDocumentPhysical; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/HtmlElementPhysicalTest.php similarity index 97% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/HtmlElementPhysicalTest.php index 4b2b36254d..f1a2bd6c6e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/HtmlElementPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/HtmlElementPhysicalTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\HtmlElementPhysical; +use Flow\ETL\Column\Physical\HtmlElementPhysical; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/IdentityPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/IdentityPhysicalTest.php similarity index 82% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/IdentityPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/IdentityPhysicalTest.php index f9320df5b8..12def22f3d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/IdentityPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/IdentityPhysicalTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\IdentityPhysical; +use Flow\ETL\Column\Physical\IdentityPhysical; use PHPUnit\Framework\TestCase; final class IdentityPhysicalTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonFactoryTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/JsonFactoryTest.php similarity index 88% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonFactoryTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/JsonFactoryTest.php index 156008240d..45f6455f20 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonFactoryTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/JsonFactoryTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\JsonFactory; +use Flow\ETL\Column\Physical\JsonFactory; use Flow\Types\Value\Json; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/JsonPhysicalTest.php similarity index 85% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/JsonPhysicalTest.php index 8fd48f25ee..5ac45a85ee 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/JsonPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/JsonPhysicalTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\JsonPhysical; +use Flow\ETL\Column\Physical\JsonPhysical; use Flow\Types\Value\Json; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/ListPhysicalTest.php similarity index 81% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/ListPhysicalTest.php index c8b54febb0..d49b266a4f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ListPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/ListPhysicalTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DateTimeZone; -use Flow\ETL\Column\Php\ListPhysical; -use Flow\ETL\Column\Php\TimeZonePhysical; +use Flow\ETL\Column\Physical\ListPhysical; +use Flow\ETL\Column\Physical\TimeZonePhysical; use PHPUnit\Framework\TestCase; final class ListPhysicalTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/MapPhysicalTest.php similarity index 84% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/MapPhysicalTest.php index 43f9524834..d67c2a94eb 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/MapPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/MapPhysicalTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DateTimeZone; -use Flow\ETL\Column\Php\MapPhysical; -use Flow\ETL\Column\Php\TimeZonePhysical; +use Flow\ETL\Column\Physical\MapPhysical; +use Flow\ETL\Column\Physical\TimeZonePhysical; use PHPUnit\Framework\TestCase; final class MapPhysicalTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/NullPhysicalTest.php similarity index 84% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/NullPhysicalTest.php index 1a003f45b6..99c256fef5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/NullPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/NullPhysicalTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\NullPhysical; +use Flow\ETL\Column\Physical\NullPhysical; use PHPUnit\Framework\TestCase; final class NullPhysicalTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalBuilderForTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalBuilderForTest.php similarity index 95% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalBuilderForTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalBuilderForTest.php index f06dd1e386..4360db8cd6 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalBuilderForTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalBuilderForTest.php @@ -2,14 +2,14 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use Flow\ETL\Column\Php\ListColumnBuilder; use Flow\ETL\Column\Php\MapColumnBuilder; use Flow\ETL\Column\Php\NullColumnBuilder; -use Flow\ETL\Column\Php\PhysicalBuilderFor; use Flow\ETL\Column\Php\ScalarColumnBuilder; use Flow\ETL\Column\Php\StructColumnBuilder; +use Flow\ETL\Column\Physical\PhysicalBuilderFor; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalForTest.php similarity index 91% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalForTest.php index ccbccde65f..42ee0b927d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/PhysicalForTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalForTest.php @@ -2,27 +2,27 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use ArrayObject; use BackedEnum; -use Flow\ETL\Column\Php\DatePhysical; -use Flow\ETL\Column\Php\DateTimePhysical; -use Flow\ETL\Column\Php\EnumPhysical; -use Flow\ETL\Column\Php\HtmlDocumentPhysical; -use Flow\ETL\Column\Php\HtmlElementPhysical; -use Flow\ETL\Column\Php\IdentityPhysical; -use Flow\ETL\Column\Php\JsonPhysical; -use Flow\ETL\Column\Php\ListPhysical; -use Flow\ETL\Column\Php\MapPhysical; -use Flow\ETL\Column\Php\NullPhysical; -use Flow\ETL\Column\Php\PhysicalFor; -use Flow\ETL\Column\Php\StructPhysical; -use Flow\ETL\Column\Php\TimePhysical; -use Flow\ETL\Column\Php\TimeZonePhysical; -use Flow\ETL\Column\Php\UuidPhysical; -use Flow\ETL\Column\Php\XmlDocumentPhysical; -use Flow\ETL\Column\Php\XmlElementPhysical; +use Flow\ETL\Column\Physical\DatePhysical; +use Flow\ETL\Column\Physical\DateTimePhysical; +use Flow\ETL\Column\Physical\EnumPhysical; +use Flow\ETL\Column\Physical\HtmlDocumentPhysical; +use Flow\ETL\Column\Physical\HtmlElementPhysical; +use Flow\ETL\Column\Physical\IdentityPhysical; +use Flow\ETL\Column\Physical\JsonPhysical; +use Flow\ETL\Column\Physical\ListPhysical; +use Flow\ETL\Column\Physical\MapPhysical; +use Flow\ETL\Column\Physical\NullPhysical; +use Flow\ETL\Column\Physical\PhysicalFor; +use Flow\ETL\Column\Physical\StructPhysical; +use Flow\ETL\Column\Physical\TimePhysical; +use Flow\ETL\Column\Physical\TimeZonePhysical; +use Flow\ETL\Column\Physical\UuidPhysical; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; +use Flow\ETL\Column\Physical\XmlElementPhysical; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalKindTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalKindTest.php new file mode 100644 index 0000000000..3fc28a58ea --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/PhysicalKindTest.php @@ -0,0 +1,63 @@ +, mixed, bool}> + */ + public static function physicals(): Generator + { + yield 'null is any type\'s' => [type_integer(), null, true]; + yield 'int in an integer column' => [type_integer(), 1, true]; + yield 'string in an integer column' => [type_integer(), '1', false]; + yield 'int in a float column' => [type_float(), 1, false]; + yield 'float in a float column' => [type_float(), 1.5, true]; + yield 'bool' => [type_boolean(), true, true]; + yield 'datetime micros' => [type_datetime(), 1_700_000_000_000_000, true]; + yield 'datetime text' => [type_datetime(), '2026-01-01', false]; + yield 'uuid 16 bytes' => [type_uuid(), str_repeat("\0", 16), true]; + yield 'uuid text' => [type_uuid(), '00000000-0000-4000-8000-000000000000', false]; + yield 'json text' => [type_json(), '{"a":1}', true]; + yield 'optional unwrapped' => [type_optional(type_integer()), 1, true]; + yield 'anything in a null column' => [type_null(), 'x', true]; + yield 'list of ints' => [type_list(type_integer()), [1, null, 2], true]; + yield 'list with a wrong element' => [type_list(type_integer()), [1, '2'], false]; + yield 'list that is not an array' => [type_list(type_integer()), 'x', false]; + yield 'map values checked' => [type_map(type_string(), type_integer()), ['a' => 'b'], false]; + yield 'structure element checked' => [type_structure(['a' => type_integer()]), ['a' => 'x'], false]; + yield 'structure element absent' => [type_structure(['a' => type_integer()]), [], true]; + } + + /** + * @param Type $type + */ + #[DataProvider('physicals')] + public function test_accepts_the_kind_flow_php_stores(Type $type, mixed $physical, bool $accepts): void + { + static::assertSame($accepts, (new PhysicalKind())->accepts($type, $physical)); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/StructPhysicalTest.php similarity index 84% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/StructPhysicalTest.php index 57d74ef195..0cf40c2281 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/StructPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/StructPhysicalTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DateTimeZone; -use Flow\ETL\Column\Php\IdentityPhysical; -use Flow\ETL\Column\Php\StructPhysical; -use Flow\ETL\Column\Php\TimeZonePhysical; +use Flow\ETL\Column\Physical\IdentityPhysical; +use Flow\ETL\Column\Physical\StructPhysical; +use Flow\ETL\Column\Physical\TimeZonePhysical; use PHPUnit\Framework\TestCase; final class StructPhysicalTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimePhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimePhysicalTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimePhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimePhysicalTest.php index b5263e1139..189035b1aa 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimePhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimePhysicalTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DateInterval; -use Flow\ETL\Column\Php\TimePhysical; +use Flow\ETL\Column\Physical\TimePhysical; use Flow\Types\Exception\CastingException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonePhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimeZonePhysicalTest.php similarity index 85% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonePhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimeZonePhysicalTest.php index a59329ccec..b83c72038d 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonePhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimeZonePhysicalTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DateTimeZone; -use Flow\ETL\Column\Php\TimeZonePhysical; +use Flow\ETL\Column\Physical\TimeZonePhysical; use PHPUnit\Framework\TestCase; final class TimeZonePhysicalTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimeZonesTest.php similarity index 81% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonesTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimeZonesTest.php index 389ffe15ed..0f370b00f1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/TimeZonesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/TimeZonesTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\TimeZones; +use Flow\ETL\Column\Physical\TimeZones; use PHPUnit\Framework\TestCase; final class TimeZonesTest extends TestCase diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/UuidPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/UuidPhysicalTest.php similarity index 90% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/UuidPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/UuidPhysicalTest.php index b0647fd102..bb438f05de 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/UuidPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/UuidPhysicalTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; -use Flow\ETL\Column\Php\UuidPhysical; +use Flow\ETL\Column\Physical\UuidPhysical; use Flow\Types\Value\Uuid; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlDocumentPhysicalTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlDocumentPhysicalTest.php index 727833eed1..6d791269d1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlDocumentPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlDocumentPhysicalTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use DOMDocument; use DOMElement; -use Flow\ETL\Column\Php\XmlDocumentPhysical; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\Mother\XmlNodeMother; use Generator; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlElementPhysicalTest.php similarity index 97% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlElementPhysicalTest.php index d1776337fe..40a7dc7892 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/XmlElementPhysicalTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlElementPhysicalTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column\Physical; use Dom\XMLDocument; use DOMDocument; use DOMElement; -use Flow\ETL\Column\Php\XmlElementPhysical; +use Flow\ETL\Column\Physical\XmlElementPhysical; use Flow\ETL\Exception\InvalidArgumentException; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/RetypeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/RetypeTest.php similarity index 60% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/RetypeTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/RetypeTest.php index 9c987cae65..8fdc837744 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/RetypeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/RetypeTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column; -use Flow\ETL\Column\Php\Retype; +use Flow\ETL\Column\Retype; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Tests\Fixtures\Enum\BackedIntEnum; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; @@ -13,9 +13,12 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; +use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_enum; use function Flow\Types\DSL\type_integer; +use function Flow\Types\DSL\type_list; +use function Flow\Types\DSL\type_map; use function Flow\Types\DSL\type_optional; use function Flow\Types\DSL\type_string; use function Flow\Types\DSL\type_structure; @@ -100,4 +103,54 @@ public function test_refuses(Type $from, Type $to, int $nullCount, string $messa (new Retype())->assert($from, $to, $nullCount); } + + /** + * @return Generator, Type, bool}> + */ + public static function proofs(): Generator + { + yield 'same scalar kind' => [type_integer(), type_optional(type_integer()), true]; + yield 'integer to string' => [type_integer(), type_string(), false]; + yield 'enum of another class' => [type_enum(BackedIntEnum::class), type_enum(BackedStringEnum::class), false]; + yield 'structure with a renamed element' => [ + type_structure(['a' => type_integer()]), + type_structure(['b' => type_integer()]), + false, + ]; + yield 'optional list of optional ints to list of ints' => [ + type_optional(type_list(type_optional(type_integer()))), + type_list(type_integer()), + false, + ]; + yield 'list of ints to optional list of optional ints' => [ + type_list(type_integer()), + type_optional(type_list(type_optional(type_integer()))), + true, + ]; + yield 'map value optional to required' => [ + type_map(type_string(), type_optional(type_integer())), + type_map(type_string(), type_integer()), + false, + ]; + yield 'structure element optional to required' => [ + type_structure(['a' => structure_element('a', type_integer(), optional: true)]), + type_structure(['a' => structure_element('a', type_integer())]), + false, + ]; + yield 'structure element type optional to required' => [ + type_structure(['a' => type_optional(type_integer())]), + type_structure(['a' => type_integer()]), + false, + ]; + } + + /** + * @param Type $from + * @param Type $to + */ + #[DataProvider('proofs')] + public function test_proves(Type $from, Type $to, bool $proven): void + { + static::assertSame($proven, (new Retype())->proves($from, $to)); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php index d0774180c9..dcf10a83d7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/TextValuesTest.php @@ -6,9 +6,10 @@ use DateTimeImmutable; use DateTimeZone; -use Flow\ETL\Column\Php\XmlDocumentPhysical; +use Flow\ETL\Column\Physical\XmlDocumentPhysical; use Flow\ETL\Column\TextValues; use Flow\ETL\Tests\Fixtures\Enum\BasicEnum; +use Flow\ETL\Tests\Mother\ColumnMother; use Flow\Types\Type; use Flow\Types\Value\Uuid; use Generator; @@ -17,6 +18,8 @@ use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; +use function Flow\ETL\DSL\datetime_schema; +use function Flow\ETL\DSL\xml_schema; use function Flow\Types\DSL\structure_element; use function Flow\Types\DSL\type_boolean; use function Flow\Types\DSL\type_date; @@ -569,4 +572,21 @@ public function test_floats_of_an_empty_list(): void { static::assertSame([], (new TextValues())->floats([])); } + + public function test_bindable_renders_markup_from_its_physicals(): void + { + $column = ColumnMother::of(xml_schema('x'), ['']); + + static::assertSame([''], (new TextValues())->bindable($column->type(), $column)); + } + + public function test_bindable_hands_over_every_other_type_as_logical_values(): void + { + $column = ColumnMother::of(datetime_schema('at'), [new DateTimeImmutable('2026-01-02 03:04:05 UTC')]); + + static::assertEquals( + [new DateTimeImmutable('2026-01-02 03:04:05 UTC')], + (new TextValues())->bindable($column->type(), $column), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValueColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ValueColumnTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValueColumnTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ValueColumnTest.php index 60a1fc3bb8..c00ccee30f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Php/ValueColumnTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/ValueColumnTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Column\Php; +namespace Flow\ETL\Tests\Unit\Column; use ArrayObject; -use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use PHPUnit\Framework\TestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/AdoptedBatchesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/AdoptedBatchesTest.php new file mode 100644 index 0000000000..7f54bfa8e6 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Executor/AdoptedBatchesTest.php @@ -0,0 +1,69 @@ + $source */ + $source = (static function () use ($schema) { + yield array_to_rows([['id' => 1, 'name' => 'a']], $schema, new PhpBackend()); + yield array_to_rows([['id' => 2, 'name' => 'b']], $schema, new PhpBackend()); + })(); + + $batches = iterator_to_array((new AdoptedBatches($backend))->of($source), false); + + static::assertCount(2, $batches); + static::assertSame(4, $backend->adopts()); + } + + public function test_a_batch_the_backend_already_owns_passes_as_the_same_instance(): void + { + $batch = array_to_rows([['id' => 1]], schema(int_schema('id')), new PhpBackend()); + + /** @var Generator $source */ + $source = (static function () use ($batch) { + yield $batch; + })(); + $adopted = (new AdoptedBatches(new PhpBackend()))->of($source); + + static::assertSame($batch, $adopted->current()); + } + + public function test_a_stop_reaches_the_source(): void + { + $extractor = new CountingExtractor( + schema(int_schema('id')), + array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))), + ); + $extractor->withBatchSize(1); + $adopted = (new AdoptedBatches(new PhpBackend()))->of($extractor->extract(flow_context())); + + static::assertCount(1, $adopted->current()); + $adopted->send(Signal::STOP); + + static::assertFalse($adopted->valid()); + static::assertSame(1, $extractor->batchesYielded); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/DerivedSchemaTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/DerivedSchemaTest.php new file mode 100644 index 0000000000..eda8360df9 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/DerivedSchemaTest.php @@ -0,0 +1,37 @@ +expectNotToPerformAssertions(); + + (new DerivedSchema(schema(int_schema('id')), 'memory://a.floe'))->refuseDivergence( + 'memory://b.floe', + schema(int_schema('id')), + ); + } + + public function test_a_file_of_another_schema_is_refused_naming_both_files(): void + { + $this->expectException(InferredSchemaException::class); + $this->expectExceptionMessage('memory://b.floe'); + + (new DerivedSchema(schema(int_schema('id')), 'memory://a.floe'))->refuseDivergence( + 'memory://b.floe', + schema(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/File/FileColumnsTest.php similarity index 92% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileColumnsTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileColumnsTest.php index 88366141bc..4a59e11ad2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileColumnsTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\File; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Tests\Context\FileColumnsContext; use Flow\ETL\Tests\FlowTestCase; @@ -24,13 +24,13 @@ public function test_a_hive_null_partition_value_stays_null(): void $fileColumns = FileColumnsContext::discovering(names: ['year' => true]); static::assertSame( - ['name' => 'Norbert', 'year' => null], + ['year' => null], $fileColumns ->forFile( new SourceFile(path('memory://orders/year=__HIVE_DEFAULT_PARTITION__/data.csv')), $fileColumns->declare(schema()), ) - ->fill(['name' => 'Norbert']), + ->values(), ); } @@ -39,10 +39,10 @@ public function test_a_partition_missing_from_the_path_stays_null(): void $fileColumns = FileColumnsContext::discovering(names: ['year' => true]); static::assertSame( - ['name' => 'Norbert', 'year' => null], + ['year' => null], $fileColumns ->forFile(new SourceFile(path('memory://orders/data.csv')), $fileColumns->declare(schema())) - ->fill(['name' => 'Norbert']), + ->values(), ); } @@ -94,10 +94,10 @@ public function test_forFile_types_the_value_with_the_declared_partition_type(): $fileColumns = FileColumnsContext::discovering(types: partition_types(year: type_integer())); static::assertSame( - ['name' => 'Norbert', 'year' => 2024], + ['year' => 2024], $fileColumns ->forFile(new SourceFile(path('memory://orders/year=2024/data.csv')), $fileColumns->declare(schema())) - ->fill(['name' => 'Norbert']), + ->values(), ); } @@ -106,10 +106,10 @@ public function test_forFile_without_a_declared_type_leaves_the_path_value_a_str $fileColumns = FileColumnsContext::discovering(); static::assertSame( - ['name' => 'Norbert', 'year' => '2024'], + ['year' => '2024'], $fileColumns ->forFile(new SourceFile(path('memory://orders/year=2024/data.csv')), $fileColumns->declare(schema())) - ->fill(['name' => 'Norbert']), + ->values(), ); } @@ -129,13 +129,13 @@ public function test_the_declared_schema_types_the_value_forFile_produces(): voi $fileColumns = FileColumnsContext::discovering(); static::assertSame( - ['name' => 'Norbert', 'year' => 2024], + ['year' => 2024], $fileColumns ->forFile( new SourceFile(path('memory://orders/year=2024/data.csv')), $fileColumns->declare(schema(str_schema('name'), int_schema('year'))), ) - ->fill(['name' => 'Norbert']), + ->values(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileConstantsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileConstantsTest.php new file mode 100644 index 0000000000..0e901b20c3 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileConstantsTest.php @@ -0,0 +1,73 @@ +values()); + } + + public function test_values_carry_the_uri_when_metadata_columns_are_on(): void + { + static::assertSame( + ['_input_file_uri' => 'memory://orders/data.csv'], + (new FileConstants('memory://orders/data.csv', [], []))->values(), + ); + } + + public function test_values_carry_every_partition_and_null_for_one_the_path_lacks(): void + { + static::assertSame( + ['_input_file_uri' => 'memory://orders/year=2024/data.csv', 'year' => 2024, 'month' => null], + (new FileConstants( + 'memory://orders/year=2024/data.csv', + ['year' => false, 'month' => true], + ['year' => 2024], + ))->values(), + ); + } + + public function test_fill_rows_returns_a_batch_with_nothing_to_add_as_it_is(): void + { + $rows = array_to_rows([['name' => 'Norbert']], schema(str_schema('name'))); + + static::assertSame($rows, (new FileConstants(null, [], []))->fillRows( + $rows, + $rows->schema(), + new PhpBackend(), + )); + } + + public function test_fill_rows_adds_the_constants_to_every_row_under_the_declared_schema(): void + { + $declared = schema(str_schema('name'), str_schema('_input_file_uri'), int_schema('year')); + + static::assertEquals( + array_to_rows([ + ['name' => 'Norbert', '_input_file_uri' => 'memory://orders/data.csv', 'year' => 2024], + ['name' => 'Flow', '_input_file_uri' => 'memory://orders/data.csv', 'year' => 2024], + ], $declared), + (new FileConstants('memory://orders/data.csv', ['year' => false], ['year' => 2024]))->fillRows( + array_to_rows([ + ['name' => 'Norbert'], + ['name' => 'Flow'], + ], schema(str_schema('name'))), + $declared, + new PhpBackend(), + ), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileReadLoopTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileReadLoopTest.php new file mode 100644 index 0000000000..7357642e5f --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileReadLoopTest.php @@ -0,0 +1,217 @@ + [1, 2], + 'memory://orders/year=2024/b.csv' => [3], + ]); + + $rows = iterator_to_array($loop->read( + [ + new SourceFile(path('memory://orders/year=2023/a.csv')), + new SourceFile(path('memory://orders/year=2024/b.csv')), + ], + $batches, + 10, + new PhpBackend(), + new ReadWindow(), + )); + + static::assertSame( + [[['id' => 1, 'year' => '2023'], ['id' => 2, 'year' => '2023']], [['id' => 3, 'year' => '2024']]], + array_map(static fn(Rows $batch): array => $batch->toArray(), $rows), + ); + } + + public function test_stop_after_the_first_batch_ends_the_read(): void + { + $read = (new FileReadLoop(FileColumnsContext::discovering(names: []), schema(int_schema('id'))))->read( + [new SourceFile(path('memory://a.csv')), new SourceFile(path('memory://b.csv'))], + new InMemoryFileBatches(['memory://a.csv' => [1, 2, 3], 'memory://b.csv' => [4]]), + 1, + new PhpBackend(), + new ReadWindow(), + ); + + static::assertSame([['id' => 1]], $read->current()->toArray()); + + $read->send(Signal::STOP); + + static::assertFalse($read->valid()); + } + + public function test_a_limit_inside_a_file_ends_the_read_and_is_pushed_down(): void + { + $batches = new InMemoryFileBatches(['memory://a.csv' => [1, 2, 3], 'memory://b.csv' => [4]]); + + $rows = iterator_to_array((new FileReadLoop( + FileColumnsContext::discovering(names: []), + schema(int_schema('id')), + ))->read( + [new SourceFile(path('memory://a.csv')), new SourceFile(path('memory://b.csv'))], + $batches, + 10, + new PhpBackend(), + new ReadWindow(limit: 2), + )); + + static::assertSame( + [[['id' => 1], ['id' => 2]]], + array_map(static fn(Rows $batch): array => $batch->toArray(), $rows), + ); + static::assertEquals(['memory://a.csv' => [new ReadWindow(0, 2)]], $batches->windows); + } + + public function test_a_limit_at_a_file_boundary_opens_no_further_file(): void + { + $batches = new InMemoryFileBatches(['memory://a.csv' => [1, 2], 'memory://b.csv' => [3]]); + + $rows = iterator_to_array((new FileReadLoop( + FileColumnsContext::discovering(names: []), + schema(int_schema('id')), + ))->read( + [new SourceFile(path('memory://a.csv')), new SourceFile(path('memory://b.csv'))], + $batches, + 1, + new PhpBackend(), + new ReadWindow(limit: 2), + )); + + static::assertCount(2, $rows); + static::assertSame(['memory://a.csv'], array_keys($batches->windows)); + } + + public function test_the_offset_a_file_leaves_and_the_rows_still_wanted_reach_the_next_file(): void + { + $batches = new InMemoryFileBatches([ + 'memory://a.csv' => [1, 2], + 'memory://b.csv' => [3, 4], + 'memory://c.csv' => [5, 6, 7], + ]); + + $rows = iterator_to_array((new FileReadLoop( + FileColumnsContext::discovering(names: []), + schema(int_schema('id')), + ))->read( + [ + new SourceFile(path('memory://a.csv')), + new SourceFile(path('memory://b.csv')), + new SourceFile(path('memory://c.csv')), + ], + $batches, + 10, + new PhpBackend(), + new ReadWindow(offset: 3, limit: 2), + )); + + static::assertSame( + [[['id' => 4]], [['id' => 5]]], + array_map(static fn(Rows $batch): array => $batch->toArray(), $rows), + ); + static::assertEquals( + [ + 'memory://a.csv' => [new ReadWindow(3, 2)], + 'memory://b.csv' => [new ReadWindow(1, 2)], + 'memory://c.csv' => [new ReadWindow(0, 1)], + ], + $batches->windows, + ); + } + + public function test_no_sources_read_nothing(): void + { + static::assertSame( + [], + iterator_to_array((new FileReadLoop( + FileColumnsContext::discovering(names: []), + schema(int_schema('id')), + ))->read([], new InMemoryFileBatches([]), 10, new PhpBackend(), new ReadWindow())), + ); + } + + public function test_the_loop_slices_the_offset_a_format_cannot_skip_across_files(): void + { + $batches = new InMemoryUnskippableFileBatches([ + 'memory://a.csv' => [1, 2], + 'memory://b.csv' => [3, 4], + 'memory://c.csv' => [5, 6, 7], + ]); + + $rows = iterator_to_array( + (new FileReadLoop(FileColumnsContext::discovering(names: []), schema(int_schema('id'))))->read( + [ + new SourceFile(path('memory://a.csv')), + new SourceFile(path('memory://b.csv')), + new SourceFile(path('memory://c.csv')), + ], + $batches, + 10, + new PhpBackend(), + new ReadWindow(offset: 3, limit: 2), + ), + false, + ); + + static::assertSame( + [[['id' => 4]], [['id' => 5]]], + array_map(static fn(Rows $batch): array => $batch->toArray(), $rows), + ); + static::assertEquals( + [ + 'memory://a.csv' => [new ReadWindow(0, 5)], + 'memory://b.csv' => [new ReadWindow(0, 3)], + 'memory://c.csv' => [new ReadWindow(0, 1)], + ], + $batches->windows, + ); + } + + public function test_the_loop_skips_the_offset_and_trims_to_the_limit_for_a_format_that_cannot_skip(): void + { + $batches = new InMemoryUnskippableFileBatches(['memory://a.csv' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]); + + $rows = iterator_to_array( + (new FileReadLoop(FileColumnsContext::discovering(names: []), schema(int_schema('id'))))->read( + [new SourceFile(path('memory://a.csv'))], + $batches, + 10, + new PhpBackend(), + new ReadWindow(offset: 3, limit: 2), + ), + false, + ); + + static::assertSame( + [[['id' => 4], ['id' => 5]]], + array_map(static fn(Rows $batch): array => $batch->toArray(), $rows), + ); + static::assertEquals(['memory://a.csv' => [new ReadWindow(0, 5)]], $batches->windows); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileReadingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileReadingTest.php similarity index 97% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileReadingTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileReadingTest.php index ee21c126c1..f822dd8cb0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileReadingTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FileReadingTest.php @@ -2,10 +2,10 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\File; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Tests\Context\SelfDescribingFilesContext; use Flow\ETL\Tests\Double\FileReadingExtractor; use Flow\ETL\Tests\FlowTestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FooterStatisticsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FooterStatisticsTest.php similarity index 95% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FooterStatisticsTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FooterStatisticsTest.php index c8bbc86615..3f577f7a86 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FooterStatisticsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/FooterStatisticsTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\File; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Extractor\FooterStatistics; +use Flow\ETL\Extractor\File\FooterStatistics; use Flow\ETL\Extractor\Statistics; use Flow\ETL\Tests\FlowTestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/InferredColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/InferredColumnsTest.php new file mode 100644 index 0000000000..c4f068b361 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/InferredColumnsTest.php @@ -0,0 +1,56 @@ +expectNotToPerformAssertions(); + + (new InferredColumns( + schema(int_schema('id'), str_schema('name')), + ['_input_file_uri'], + new SchemaInference(), + 'memory://a.csv', + ))->refuseDivergence('memory://b.csv', ['name', 'id', 'id', '_input_file_uri']); + } + + public function test_a_file_without_columns_passes(): void + { + $this->expectNotToPerformAssertions(); + + (new InferredColumns( + schema(int_schema('id'), str_schema('name')), + ['_input_file_uri'], + new SchemaInference(), + 'memory://a.csv', + ))->refuseDivergence('memory://empty.csv', []); + } + + public function test_a_file_whose_columns_diverge_is_refused_naming_both_sources(): void + { + $this->expectException(InferredSchemaException::class); + $this->expectExceptionMessage( + 'Columns of memory://b.csv do not match the schema inferred from memory://a.csv: unexpected [age], missing [name]', + ); + + (new InferredColumns( + schema(int_schema('id'), str_schema('name')), + ['_input_file_uri'], + new SchemaInference(), + 'memory://a.csv', + ))->refuseDivergence('memory://b.csv', ['id', 'age']); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ListedFilesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/ListedFilesTest.php similarity index 94% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ListedFilesTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/ListedFilesTest.php index 74e434f185..184d1081fd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/ListedFilesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/ListedFilesTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\File; use Flow\ETL\Cardinality; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Extractor\ListedFiles; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\ListedFiles; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\FileStatus; @@ -18,7 +18,7 @@ final class ListedFilesTest extends FlowTestCase { public function test_a_zero_byte_member_reported_as_null_makes_the_total_unknown(): void { - $empty = native_local_filesystem()->status(path(__DIR__ . '/../../Fixtures/empty.txt')); + $empty = native_local_filesystem()->status(path(__DIR__ . '/../../../Fixtures/empty.txt')); static::assertNotNull($empty); static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/MetadataColumnsExtractorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/MetadataColumnsExtractorTest.php similarity index 90% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/MetadataColumnsExtractorTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/MetadataColumnsExtractorTest.php index 9adeff0f4b..d40f37b3a9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/MetadataColumnsExtractorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/MetadataColumnsExtractorTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\File; use Flow\ETL\Config; use Flow\ETL\Config\ConfigBuilder; use Flow\ETL\Extractor; -use Flow\ETL\Extractor\MetadataColumnsExtractor; +use Flow\ETL\Extractor\File\MetadataColumnsExtractor; use Flow\ETL\Tests\Context\ExtractorClasses; use Flow\ETL\Tests\FlowTestCase; use Generator; @@ -66,11 +66,9 @@ public function test_the_capability_is_declared_only_by_sources_that_have_metada 'Flow\ETL\Adapter\Excel\ExcelExtractor', 'Flow\ETL\Adapter\GoogleSheet\GoogleSheetExtractor', 'Flow\ETL\Adapter\JSON\JSONMachine\JsonExtractor', - 'Flow\ETL\Adapter\JSON\JSONMachine\JsonLinesExtractor', 'Flow\ETL\Adapter\Parquet\ParquetExtractor', 'Flow\ETL\Adapter\Text\TextExtractor', 'Flow\ETL\Adapter\XML\XMLParserExtractor', - 'Flow\ETL\Adapter\XML\XMLReaderExtractor', 'Flow\Floe\FloeExtractor', ], self::classesDeclaringMetadataColumns(), @@ -79,7 +77,7 @@ public function test_the_capability_is_declared_only_by_sources_that_have_metada public function test_the_census_covers_every_extractor_in_src(): void { - static::assertCount(33, ExtractorClasses::all()); + static::assertCount(31, ExtractorClasses::all()); } public function test_the_config_delegator_is_gone(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/PartitionColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/PartitionColumnsTest.php new file mode 100644 index 0000000000..e4d35a6b2c --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/PartitionColumnsTest.php @@ -0,0 +1,105 @@ +declare(schema(int_schema('date')), ['date' => true]), + ); + } + + public function test_declare_adds_each_name_with_the_nullability_it_was_given(): void + { + static::assertEquals( + schema(int_schema('id'), str_schema('date'), str_schema('region', nullable: true)), + (new PartitionColumns(new MemoryFilesystem()))->declare(schema(int_schema('id')), [ + 'date' => false, + 'region' => true, + ]), + ); + } + + public function test_declare_moves_a_partition_column_out_of_its_body_position_and_keeps_its_type(): void + { + // the file's own header puts `group` first; the partition block is appended, so the declared + // int type survives but the position does not + static::assertEquals( + schema(int_schema('id'), str_schema('value'), int_schema('group')), + (new PartitionColumns(new MemoryFilesystem()))->declare( + schema(int_schema('group'), int_schema('id'), str_schema('value')), + ['group' => false], + ), + ); + } + + public function test_declare_leaves_a_schema_alone_when_nothing_was_discovered(): void + { + static::assertEquals( + schema(int_schema('id')), + (new PartitionColumns(new MemoryFilesystem()))->declare(schema(int_schema('id')), []), + ); + } + + public function test_names_of_a_listing_without_partitions_is_empty(): void + { + $filesystem = new MemoryFilesystem(); + $filesystem->appendTo(path('memory://plain/data.csv'))->append('id')->close(); + + static::assertSame( + [], + (new PartitionColumns($filesystem))->names(path('memory://plain/*.csv'), new OnlyFiles()), + ); + } + + public function test_names_reports_a_partition_every_path_carries_as_non_nullable(): void + { + $filesystem = new MemoryFilesystem(); + $filesystem->appendTo(path('memory://all/date=2026-01-01/data.csv'))->append('id')->close(); + $filesystem->appendTo(path('memory://all/date=2026-01-02/data.csv'))->append('id')->close(); + + static::assertSame( + ['date' => false], + (new PartitionColumns($filesystem))->names(path('memory://all/*/*.csv'), new OnlyFiles()), + ); + } + + public function test_names_are_sorted_by_name_not_by_path_order(): void + { + $filesystem = new MemoryFilesystem(); + $filesystem->appendTo(path('memory://sorted/year=2026/month=01/region=eu/data.csv'))->append('id')->close(); + + static::assertSame( + ['month' => false, 'region' => false, 'year' => false], + (new PartitionColumns($filesystem))->names(path('memory://sorted/*/*/*/*.csv'), new OnlyFiles()), + ); + } + + public function test_names_reports_a_partition_only_some_paths_carry_as_nullable(): void + { + $filesystem = new MemoryFilesystem(); + $filesystem->appendTo(path('memory://mixed/date=2026-01-01/data.csv'))->append('id')->close(); + $filesystem->appendTo(path('memory://mixed/plain/data.csv'))->append('id')->close(); + + static::assertSame( + ['date' => true], + (new PartitionColumns($filesystem))->names(path('memory://mixed/*/*.csv'), new OnlyFiles()), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionTypesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/PartitionTypesTest.php similarity index 95% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionTypesTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/PartitionTypesTest.php index ae3d5883e9..e8d2ad1843 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionTypesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/PartitionTypesTest.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\File; use Flow\ETL\Exception\InvalidArgumentException; -use Flow\ETL\Extractor\PartitionColumns; -use Flow\ETL\Extractor\PartitionTypes; +use Flow\ETL\Extractor\File\PartitionColumns; +use Flow\ETL\Extractor\File\PartitionTypes; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\MemoryFilesystem; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/ReadWindowTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/ReadWindowTest.php new file mode 100644 index 0000000000..ab0333e226 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/ReadWindowTest.php @@ -0,0 +1,36 @@ +expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('ReadWindow offset must be 0 or more, got -1'); + + new ReadWindow(offset: -1); + } + + public function test_a_negative_limit_is_refused(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('ReadWindow limit must be 0 or more, got -1'); + + new ReadWindow(limit: -1); + } + + public function test_the_default_window_skips_nothing_and_wants_everything(): void + { + $window = new ReadWindow(); + + static::assertSame(0, $window->offset); + static::assertNull($window->limit); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SourceFileTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/SourceFileTest.php similarity index 93% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SourceFileTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/SourceFileTest.php index a87045a380..a3b6035d28 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SourceFileTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/File/SourceFileTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\File; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Tests\FlowTestCase; use function Flow\Filesystem\DSL\path; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php deleted file mode 100644 index b70abe3596..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/FileConstantsTest.php +++ /dev/null @@ -1,98 +0,0 @@ - 'memory://orders/data.csv', 'name' => 'Norbert'], - (new FileConstants(new PartitionColumns(memory_filesystem()), 'memory://orders/data.csv', [], []))->fill([ - '_input_file_uri' => 'hijacked', - 'name' => 'Norbert', - ]), - ); - } - - public function test_partition_columns_leave_their_body_position_and_are_re_appended(): void - { - static::assertSame( - ['name' => 'Norbert', 'year' => 2024], - (new FileConstants( - new PartitionColumns(memory_filesystem()), - null, - ['year' => false], - ['year' => 2024], - ))->fill(['year' => 'from the body', 'name' => 'Norbert']), - ); - } - - public function test_the_uri_is_stamped_only_when_metadata_columns_are_on(): void - { - static::assertSame( - ['name' => 'Norbert'], - (new FileConstants(new PartitionColumns(memory_filesystem()), null, [], []))->fill(['name' => 'Norbert']), - ); - } - - public function test_the_uri_joins_the_body_when_metadata_columns_are_on(): void - { - static::assertSame( - ['name' => 'Norbert', '_input_file_uri' => 'memory://orders/data.csv'], - (new FileConstants(new PartitionColumns(memory_filesystem()), 'memory://orders/data.csv', [], []))->fill([ - 'name' => 'Norbert', - ]), - ); - } - - public function test_fill_rows_returns_a_batch_with_nothing_to_add_as_it_is(): void - { - $rows = array_to_rows([['name' => 'Norbert']], schema(str_schema('name'))); - - static::assertSame($rows, (new FileConstants( - new PartitionColumns(memory_filesystem()), - null, - [], - [], - ))->fillRows($rows, $rows->schema(), new PhpBackend())); - } - - public function test_fill_rows_adds_the_constants_to_every_row_under_the_declared_schema(): void - { - $declared = schema(str_schema('name'), str_schema('_input_file_uri'), int_schema('year')); - - static::assertEquals( - array_to_rows([ - ['name' => 'Norbert', '_input_file_uri' => 'memory://orders/data.csv', 'year' => 2024], - ['name' => 'Flow', '_input_file_uri' => 'memory://orders/data.csv', 'year' => 2024], - ], $declared), - (new FileConstants( - new PartitionColumns(memory_filesystem()), - 'memory://orders/data.csv', - ['year' => false], - ['year' => 2024], - ))->fillRows( - array_to_rows([ - ['name' => 'Norbert'], - ['name' => 'Flow'], - ], schema(str_schema('name'))), - $declared, - new PhpBackend(), - ), - ); - } -} 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 89470dc73d..62e717d70f 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 @@ -160,6 +160,41 @@ public function test_batches_at_the_configured_batch_size(): void static::assertSame([2, 2, 2], $sizes); } + public function test_every_row_of_a_batch_carries_its_own_files_partition_value(): void + { + $batches = iterator_to_array( + files('memory://dir/**/*.txt', MemoryFiles::with([ + 'memory://dir/year=2023/a.txt' => 'a', + 'memory://dir/year=2024/b.txt' => 'b', + 'memory://dir/year=2025/c.txt' => 'c', + ])) + ->withBatchSize(3) + ->extract(flow_context()), + false, + ); + + static::assertCount(1, $batches); + static::assertSame(['2023', '2024', '2025'], $batches[0]->column('year')->values()); + static::assertSame(['a.txt', 'b.txt', 'c.txt'], $batches[0]->column('base_name')->values()); + } + + public function test_a_limit_at_the_batch_boundary_keeps_each_rows_partition_value(): void + { + $batches = iterator_to_array( + files('memory://dir/**/*.txt', MemoryFiles::with([ + 'memory://dir/year=2023/a.txt' => 'a', + 'memory://dir/year=2024/b.txt' => 'b', + 'memory://dir/year=2025/c.txt' => 'c', + ])) + ->withBatchSize(2) + ->extract(flow_context(), limit: 2), + false, + ); + + static::assertCount(1, $batches); + static::assertSame(['2023', '2024'], $batches[0]->column('year')->values()); + } + public function test_files_extractor_honours_the_batch_contract(): void { self::assertExtractorHonoursBatchContract( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Grid/HeaderNamesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Grid/HeaderNamesTest.php new file mode 100644 index 0000000000..b211919b9b --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Grid/HeaderNamesTest.php @@ -0,0 +1,25 @@ +of([' id ', 1, 2.5, true])); + } + + public function test_a_blank_or_non_scalar_cell_is_named_by_its_position(): void + { + static::assertSame( + ['e00', 'e01', 'e02', 'name', 'e04'], + (new HeaderNames())->of(['', null, ' ', 'name', new DateTimeImmutable('2026-01-01')]), + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Grid/RecordDecoderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Grid/RecordDecoderTest.php new file mode 100644 index 0000000000..e2892b218d --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Grid/RecordDecoderTest.php @@ -0,0 +1,382 @@ +decode([[' id ', '', null, 'name ']])); + static::assertSame(['id', 'e01', 'e02', 'name'], $records->headers()); + } + + public function test_a_numeric_header_cell_is_its_string(): void + { + $records = new RecordDecoder(withHeader: true, emptyToNull: true); + $records->decode([[1, 2.5, true]]); + + static::assertSame(['1', '2.5', '1'], $records->headers()); + } + + public function test_a_non_scalar_header_cell_is_named_by_its_position(): void + { + $records = new RecordDecoder(withHeader: true, emptyToNull: true); + $records->decode([[new DateTimeImmutable('2026-01-01'), 'name']]); + + static::assertSame(['e00', 'name'], $records->headers()); + } + + public function test_without_a_header_the_first_record_sizes_the_generated_names(): void + { + $records = new RecordDecoder(withHeader: false, emptyToNull: true); + + static::assertSame([['e00' => 'a', 'e01' => 'b']], $records->decode([['a', 'b']])); + static::assertSame(['e00', 'e01'], $records->headers()); + } + + #[TestWith([true])] + #[TestWith([false])] + public function test_a_cell_a_short_record_lacks_is_null(bool $emptyToNull): void + { + static::assertSame( + [['id' => '1', 'name' => 'a', 'age' => null]], + (new RecordDecoder(withHeader: true, emptyToNull: $emptyToNull))->decode([ + ['id', 'name', 'age'], + ['1', 'a'], + ]), + ); + } + + #[TestWith([true, null])] + #[TestWith([false, ''])] + public function test_a_present_empty_cell_is_null_only_under_empty_to_null( + bool $emptyToNull, + ?string $expected, + ): void { + static::assertSame( + [['id' => '1', 'name' => $expected]], + (new RecordDecoder(withHeader: true, emptyToNull: $emptyToNull))->decode([['id', 'name'], ['1', '']]), + ); + } + + public function test_a_non_string_cell_is_kept_as_read(): void + { + $at = new DateTimeImmutable('2026-01-01'); + + static::assertSame( + [['at' => $at, 'n' => 0]], + (new RecordDecoder(withHeader: true, emptyToNull: true))->decode([['at', 'n'], [$at, 0]]), + ); + } + + public function test_extra_cells_are_dropped_by_default(): void + { + static::assertSame( + [['id' => '1']], + (new RecordDecoder(withHeader: true, emptyToNull: true))->decode([['id'], ['1', 'extra']]), + ); + } + + public function test_extra_cells_are_refused_when_they_are_not_dropped(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Row has more columns (2) than headers (1)'); + + (new RecordDecoder(withHeader: true, emptyToNull: true, dropExtraColumns: false))->decode([ + ['id'], + ['1', 'extra'], + ]); + } + + public function test_leading_empty_records_are_skipped_before_the_header(): void + { + $records = new RecordDecoder(withHeader: true, emptyToNull: true); + + static::assertSame([['id' => '1']], $records->decode([[], [], ['id'], ['1']])); + static::assertSame(['id'], $records->headers()); + } + + public function test_an_empty_batch_decodes_to_nothing(): void + { + static::assertSame([], (new RecordDecoder(withHeader: true, emptyToNull: true))->decode([])); + } + + public function test_headers_are_null_before_the_first_decode(): void + { + static::assertNull((new RecordDecoder(withHeader: true, emptyToNull: true))->headers()); + } + + public function test_the_header_is_kept_between_batches(): void + { + $records = new RecordDecoder(withHeader: true, emptyToNull: true); + $records->decode([['id']]); + + static::assertSame([['id' => '2']], $records->decode([['2']])); + } + + public function test_decode_captures_headers_from_the_first_row_and_emits_no_row_for_it(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + + static::assertSame([], $decoder->decode([['id', 'name']])); + static::assertSame(['id' => 1, 'name' => 'Norbert'], $decoder->decode([[1, 'Norbert']])[0]); + } + + public function test_decode_generates_auto_headers_when_header_is_disabled(): void + { + static::assertSame( + ['e00' => 1, 'e01' => 'Norbert'], + (new RecordDecoder(withHeader: false, emptyToNull: true))->decode([[1, 'Norbert']])[0], + ); + } + + public function test_headers_are_generated_when_header_is_disabled(): void + { + $decoder = new RecordDecoder(withHeader: false, emptyToNull: true); + + static::assertCount(1, $decoder->decode([[1, 2, 3]])); + static::assertSame(['e00', 'e01', 'e02'], $decoder->headers()); + } + + public function test_excel_headers_are_null_before_the_first_decode(): void + { + static::assertNull((new RecordDecoder(withHeader: true, emptyToNull: true))->headers()); + } + + public function test_headers_are_stringified_and_named_by_position_for_blank_cells(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + $decoder->decode([[1, null, 'x']]); + + static::assertSame(['1', 'e01', 'x'], $decoder->headers()); + } + + public function test_headers_are_the_header_row_after_decode(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + + static::assertSame([], $decoder->decode([['id', 'name']])); + static::assertSame(['id', 'name'], $decoder->headers()); + } + + public function test_decode_keeps_empty_cells_when_convert_empty_to_null_is_disabled(): void + { + static::assertSame( + ['id' => 1, 'name' => ''], + (new RecordDecoder(withHeader: true, emptyToNull: false))->decode([['id', 'name'], [1, '']])[0], + ); + } + + public function test_decode_maps_cells_to_headers(): void + { + static::assertSame( + ['id' => 1, 'name' => 'Norbert'], + (new RecordDecoder(withHeader: true, emptyToNull: true))->decode([['id', 'name'], [1, 'Norbert']])[0], + ); + } + + public function test_decode_turns_empty_cells_into_null_by_default(): void + { + static::assertSame( + ['id' => 1, 'name' => null], + (new RecordDecoder(withHeader: true, emptyToNull: true))->decode([['id', 'name'], [1, '']])[0], + ); + } + + public function test_header_names_follow_the_csv_rule(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + $decoder->decode([[' id ', '', 'name']]); + + static::assertSame(['id', 'e01', 'name'], $decoder->headers()); + } + + public function test_decodes_rows_with_first_row_as_headers(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + + $decoded = $decoder->decode([ + ['id', 'name'], + ['1', 'Norbert'], + ['2', 'Tomek'], + ]); + + static::assertSame( + [ + ['id' => '1', 'name' => 'Norbert'], + ['id' => '2', 'name' => 'Tomek'], + ], + $decoded, + ); + } + + public function test_skips_empty_rows_before_headers(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + + $decoded = $decoder->decode([ + [], + ['id', 'name'], + ['1', 'Norbert'], + ]); + + static::assertSame([['id' => '1', 'name' => 'Norbert']], $decoded); + } + + public function test_keeps_headers_between_decode_calls(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + + $decoder->decode([['id', 'name'], ['1', 'Norbert']]); + + static::assertSame([['id' => '2', 'name' => 'Tomek']], $decoder->decode([['2', 'Tomek']])); + } + + public function test_pads_shorter_rows_with_nulls(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + + $decoded = $decoder->decode([ + ['id', 'name'], + ['1'], + ]); + + static::assertSame([['id' => '1', 'name' => null]], $decoded); + } + + public function test_drops_extra_columns(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + + $decoded = $decoder->decode([ + ['id', 'name'], + ['1', 'Norbert', 'extra'], + ]); + + static::assertSame([['id' => '1', 'name' => 'Norbert']], $decoded); + } + + public function test_throws_on_extra_columns_when_drop_is_disabled(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true, dropExtraColumns: false); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Row has more columns (3) than headers (2)'); + + $decoder->decode([ + ['id', 'name'], + ['1', 'Norbert', 'extra'], + ]); + } + + public function test_generates_auto_headers_without_header_row(): void + { + $decoder = new RecordDecoder(withHeader: false, emptyToNull: true); + + $decoded = $decoder->decode([ + ['1', 'Norbert'], + ['2', 'Tomek'], + ]); + + static::assertSame( + [ + ['e00' => '1', 'e01' => 'Norbert'], + ['e00' => '2', 'e01' => 'Tomek'], + ], + $decoded, + ); + } + + public function test_empty_cells_become_null_by_default(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + + static::assertSame([['a' => null, 'b' => 'x']], $decoder->decode([['a', 'b'], ['', 'x']])); + } + + public function test_empty_cells_stay_strings_when_asked(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: false); + + static::assertSame([['a' => '', 'b' => 'x']], $decoder->decode([['a', 'b'], ['', 'x']])); + } + + public function test_omitted_trailing_cells_are_null_regardless_of_empty_to_null(): void + { + static::assertSame( + [['a' => 'x', 'b' => null]], + (new RecordDecoder(withHeader: true, emptyToNull: true))->decode([ + ['a', 'b'], + ['x'], + ]), + ); + static::assertSame( + [['a' => 'x', 'b' => null]], + (new RecordDecoder(withHeader: true, emptyToNull: false))->decode([['a', 'b'], ['x']]), + ); + } + + public function test_headers_are_the_consumed_header_row(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + $decoder->decode([['a', 'b'], ['1', '2']]); + + static::assertSame(['a', 'b'], $decoder->headers()); + } + + public function test_headers_skip_a_leading_empty_row(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + $decoder->decode([[], ['a', 'b']]); + + static::assertSame(['a', 'b'], $decoder->headers()); + } + + public function test_headers_are_generated_without_a_header_row(): void + { + $decoder = new RecordDecoder(withHeader: false, emptyToNull: true); + $decoder->decode([['1', '2', '3']]); + + static::assertSame(['e00', 'e01', 'e02'], $decoder->headers()); + } + + public function test_headers_are_strings_even_when_the_api_typed_them(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + $decoder->decode([[1, '2'], ['x', 'y']]); + + static::assertSame(['1', '2'], $decoder->headers()); + } + + /** + * b88, pinned as it behaves rather than as it should: `1` and `true` both stringify to `'1'`, and + * array_combine() keeps the last value under a repeated key, so the row loses a column. Not specific to a + * typed header - `a,a` does the same in CSV - and not introduced by inference. + */ + public function test_two_header_cells_with_the_same_name_collapse_the_row_to_one_column(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + $decoded = $decoder->decode([[1, true], ['x', 'y']]); + + static::assertSame(['1', '1'], $decoder->headers()); + static::assertSame(['1' => 'y'], $decoded[0]); + } + + public function test_google_sheet_header_names_follow_the_csv_rule(): void + { + $decoder = new RecordDecoder(withHeader: true, emptyToNull: true); + $decoder->decode([[' id ', '', 'name']]); + + static::assertSame(['id', 'e01', 'name'], $decoder->headers()); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InMemoryRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/InMemoryRowsTest.php similarity index 93% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InMemoryRowsTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/InMemoryRowsTest.php index 556b5bb14f..dc0aad7362 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InMemoryRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/InMemoryRowsTest.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\Memory; -use Flow\ETL\Extractor\InMemoryRows; +use Flow\ETL\Extractor\Memory\InMemoryRows; use Flow\ETL\Tests\FlowTestCase; use function array_keys; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/InferredRowsTest.php similarity index 96% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/InferredRowsTest.php index 921ce8c475..a3609e2042 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/InferredRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/InferredRowsTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\Memory; use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InferredSchemaException; use Flow\ETL\Exception\SchemaMismatchException; -use Flow\ETL\Extractor\InferredRows; +use Flow\ETL\Extractor\Memory\InferredRows; use Flow\ETL\Schema\Inference\SchemaInference; use Flow\ETL\Tests\FlowTestCase; use PHPUnit\Framework\Attributes\TestWith; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SpilledRowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/SpilledRowsTest.php similarity index 98% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SpilledRowsTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/SpilledRowsTest.php index 5dbfdd9786..0651990aa5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/SpilledRowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/Memory/SpilledRowsTest.php @@ -2,12 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Extractor; +namespace Flow\ETL\Tests\Unit\Extractor\Memory; use DateTimeImmutable; use Flow\ETL\Exception\InvalidLogicException; -use Flow\ETL\Extractor\SpilledRows; -use Flow\ETL\Extractor\SpillState; +use Flow\ETL\Extractor\Memory\SpilledRows; +use Flow\ETL\Extractor\Memory\SpillState; use Flow\ETL\Tests\Double\RecordingFilesystem; use Flow\ETL\Tests\Double\ThrowingRmFilesystem; use Flow\ETL\Tests\Fixtures\Enum\BackedStringEnum; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php deleted file mode 100644 index 6dd08212c6..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Extractor/PartitionColumnsTest.php +++ /dev/null @@ -1,218 +0,0 @@ -declare(schema(int_schema('date')), ['date' => true]), - ); - } - - public function test_apply_adds_a_column_the_inferred_schema_is_missing(): void - { - static::assertEquals( - schema(int_schema('id'), str_schema('date', nullable: true)), - (new PartitionColumns(new MemoryFilesystem())) - ->apply(array_to_rows([['id' => 1]], schema(int_schema('id'))), ['date' => true]) - ->schema(), - ); - } - - public function test_apply_keeps_the_rows_it_was_given(): void - { - static::assertSame( - [['id' => 1, 'date' => null]], - (new PartitionColumns(new MemoryFilesystem())) - ->apply( - array_to_rows( - [['id' => 1, 'date' => null]], - schema(int_schema('id'), str_schema('date', nullable: true)), - ), - ['date' => true], - ) - ->toArray(), - ); - } - - public function test_apply_replaces_the_definition_inference_guessed(): void - { - static::assertEquals( - schema(int_schema('id'), str_schema('date', nullable: true)), - (new PartitionColumns(new MemoryFilesystem())) - ->apply( - array_to_rows([['id' => 1, 'date' => '2026-01-01']], schema(int_schema('id'), str_schema('date'))), - [ - 'date' => true, - ], - ) - ->schema(), - ); - } - - public function test_apply_takes_nullability_from_the_names_map(): void - { - static::assertEquals( - schema(str_schema('date'), str_schema('region', nullable: true)), - (new PartitionColumns(new MemoryFilesystem())) - ->apply(array_to_rows([['date' => '2026-01-01']], schema(str_schema('date', nullable: true))), [ - 'date' => false, - 'region' => true, - ]) - ->schema(), - ); - } - - public function test_declare_adds_each_name_with_the_nullability_it_was_given(): void - { - static::assertEquals( - schema(int_schema('id'), str_schema('date'), str_schema('region', nullable: true)), - (new PartitionColumns(new MemoryFilesystem()))->declare(schema(int_schema('id')), [ - 'date' => false, - 'region' => true, - ]), - ); - } - - public function test_declare_moves_a_partition_column_out_of_its_body_position_and_keeps_its_type(): void - { - // the file's own header puts `group` first; the partition block is appended, so the declared - // int type survives but the position does not - static::assertEquals( - schema(int_schema('id'), str_schema('value'), int_schema('group')), - (new PartitionColumns(new MemoryFilesystem()))->declare( - schema(int_schema('group'), int_schema('id'), str_schema('value')), - ['group' => false], - ), - ); - } - - public function test_apply_moves_a_partition_column_out_of_its_body_position(): void - { - static::assertEquals( - schema(int_schema('id'), str_schema('value'), str_schema('group')), - (new PartitionColumns(new MemoryFilesystem())) - ->apply( - array_to_rows( - [['group' => '1', 'id' => 1, 'value' => 'a']], - schema(str_schema('group'), int_schema('id'), str_schema('value')), - ), - ['group' => false], - ) - ->schema(), - ); - } - - public function test_declare_leaves_a_schema_alone_when_nothing_was_discovered(): void - { - static::assertEquals( - schema(int_schema('id')), - (new PartitionColumns(new MemoryFilesystem()))->declare(schema(int_schema('id')), []), - ); - } - - public function test_apply_leaves_rows_alone_when_nothing_was_discovered(): void - { - static::assertEquals( - array_to_rows([['id' => 1]], schema(int_schema('id'))), - (new PartitionColumns(new MemoryFilesystem()))->apply(array_to_rows([[ - 'id' => 1, - ]], schema(int_schema('id'))), []), - ); - } - - public function test_fill_leaves_a_row_untouched_when_there_are_no_partition_columns(): void - { - static::assertSame(['id' => 1], (new PartitionColumns(new MemoryFilesystem()))->fill(['id' => 1], [], [])); - } - - public function test_fill_nulls_a_column_the_path_does_not_carry(): void - { - static::assertSame( - ['id' => 1, 'date' => '2026-01-01', 'region' => null], - (new PartitionColumns(new MemoryFilesystem()))->fill( - ['id' => 1], - ['date' => false, 'region' => true], - ['date' => '2026-01-01'], - ), - ); - } - - public function test_names_of_a_listing_without_partitions_is_empty(): void - { - $filesystem = new MemoryFilesystem(); - $filesystem->appendTo(path('memory://plain/data.csv'))->append('id')->close(); - - static::assertSame( - [], - (new PartitionColumns($filesystem))->names(path('memory://plain/*.csv'), new OnlyFiles()), - ); - } - - public function test_names_reports_a_partition_every_path_carries_as_non_nullable(): void - { - $filesystem = new MemoryFilesystem(); - $filesystem->appendTo(path('memory://all/date=2026-01-01/data.csv'))->append('id')->close(); - $filesystem->appendTo(path('memory://all/date=2026-01-02/data.csv'))->append('id')->close(); - - static::assertSame( - ['date' => false], - (new PartitionColumns($filesystem))->names(path('memory://all/*/*.csv'), new OnlyFiles()), - ); - } - - public function test_names_are_sorted_by_name_not_by_path_order(): void - { - $filesystem = new MemoryFilesystem(); - $filesystem->appendTo(path('memory://sorted/year=2026/month=01/region=eu/data.csv'))->append('id')->close(); - - static::assertSame( - ['month' => false, 'region' => false, 'year' => false], - (new PartitionColumns($filesystem))->names(path('memory://sorted/*/*/*/*.csv'), new OnlyFiles()), - ); - } - - public function test_names_reports_a_partition_only_some_paths_carry_as_nullable(): void - { - $filesystem = new MemoryFilesystem(); - $filesystem->appendTo(path('memory://mixed/date=2026-01-01/data.csv'))->append('id')->close(); - $filesystem->appendTo(path('memory://mixed/plain/data.csv'))->append('id')->close(); - - static::assertSame( - ['date' => true], - (new PartitionColumns($filesystem))->names(path('memory://mixed/*/*.csv'), new OnlyFiles()), - ); - } - - public function test_fill_moves_a_colliding_body_column_into_the_partition_block(): void - { - // declare() re-appends every partition column at the tail, so fill() has to do the same or - // schema() and extract() disagree for a file that also carries a column of that name - static::assertSame( - ['id', 'date'], - array_keys((new PartitionColumns(new MemoryFilesystem()))->fill( - ['date' => '1999-01-01', 'id' => 1], - ['date' => false], - ['date' => '2024-01-01'], - )), - ); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowTestCaseBatchContractTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowTestCaseBatchContractTest.php index e7bb74dcc7..ce0f14defd 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowTestCaseBatchContractTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowTestCaseBatchContractTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Tests\Double\CountingExtractor; use Flow\ETL\Tests\Double\OneRowBatchesExtractor; use Flow\ETL\Tests\Double\StopIgnoringExtractor; @@ -49,7 +50,7 @@ public function test_contract_holds_for_a_varying_batch_source(): void $expected = RowsMother::sequentialIds(0); foreach ($batches as $batch) { - $expected = $expected->merge($batch); + $expected = $expected->concat(new PhpBackend(), $batch); } self::assertExtractorHonoursBatchContract( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllFunctionsEvaluateOnTheConfiguredBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllFunctionsEvaluateOnTheConfiguredBackendTest.php new file mode 100644 index 0000000000..fd1b941863 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/AllFunctionsEvaluateOnTheConfiguredBackendTest.php @@ -0,0 +1,113 @@ +}> + */ + public static function functions(): Generator + { + foreach (array_keys(ScalarFunctionFixtures::all()) as $class) { + yield $class => [$class]; + } + } + + /** + * @param class-string $class + */ + #[DataProvider('functions')] + public function test_a_function_gives_the_same_values_and_a_column_of_the_configured_backend(string $class): void + { + try { + // a fresh function per run: a function may keep what it evaluated (Literal keeps its column) + $resolve = static fn(): ScalarFunction => (new ReferenceResolver())->resolve( + ScalarFunctionFixtures::instance($class), + ScalarFunctionFixtures::schema(), + ); + $resolve(); + } catch (RequiredPHPVersionException $e) { + static::markTestSkipped($e->getMessage()); + } + + try { + $php = $resolve()->eval( + ScalarFunctionFixtures::rows(new PhpBackend()), + flow_context(config_builder()->backend(new PhpBackend())->build()), + ); + } catch (Throwable $phpFailure) { + $this->expectException($phpFailure::class); + $this->expectExceptionMessage($phpFailure->getMessage()); + + $resolve()->eval( + ScalarFunctionFixtures::rows(new AdaptiveBackend()), + flow_context(config_builder()->backend(new AdaptiveBackend())->build()), + ); + + return; + } + + $function = $resolve(); + $configured = $function->eval( + ScalarFunctionFixtures::rows(new AdaptiveBackend()), + flow_context(config_builder()->backend(new AdaptiveBackend())->build()), + ); + // the batch's columns come from another backend than the configured one + $adaptiveUnderPhp = $resolve()->eval( + ScalarFunctionFixtures::rows(new AdaptiveBackend()), + flow_context(config_builder()->backend(new PhpBackend())->build()), + ); + + if ($function->deterministic()) { + static::assertEquals($php->values(), $configured->values()); + static::assertEquals($php->values(), $adaptiveUnderPhp->values()); + } else { + static::assertSame($php->count(), $configured->count()); + static::assertSame($php->count(), $adaptiveUnderPhp->count()); + } + + static::assertStringStartsWith('Flow\ETL\Column\Php\\', $php::class, $class . ' under PhpBackend'); + + // a reference hands back the batch's own column, whatever backend built it + if (!$function instanceof Reference) { + static::assertStringStartsWith( + 'Flow\ETL\Column\Php\\', + $adaptiveUnderPhp::class, + $class . ' over Adaptive columns under PhpBackend', + ); + } + + if ($php instanceof ValueColumn) { + return; + } + + static::assertTrue( + extension_loaded('flow_php') + ? $configured::class === 'Flow\ETL\Column\RustColumn' + : str_starts_with($configured::class, 'Flow\ETL\Column\Php\\'), + $class . ' evaluated into a ' . $configured::class, + ); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ResultColumnTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ResultColumnTest.php index c8c8c78729..a09ace0f18 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ResultColumnTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ResultColumnTest.php @@ -5,12 +5,13 @@ namespace Flow\ETL\Tests\Unit\Function\Evaluation; use ArrayObject; -use Flow\ETL\Column\Php\ScalarColumn; -use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Function\Evaluation\ResultColumn; use Flow\ETL\Function\ReferenceResolver; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\Types\Type; use Generator; use PHPUnit\Framework\Attributes\DataProvider; @@ -40,7 +41,7 @@ final class ResultColumnTest extends TestCase { public function test_a_not_null_return_still_accepts_null(): void { - $column = (new ResultColumn())->of(lit(5), [5, null]); + $column = (new ResultColumn(new PhpBackend()))->of(lit(5), [5, null]); static::assertSame([5, null], $column->values()); static::assertEquals(type_integer(), $column->type()); @@ -50,22 +51,27 @@ public function test_an_unresolved_tree_throws(): void { $this->expectException(InvalidLogicException::class); - (new ResultColumn())->of(ref('a'), [1]); + (new ResultColumn(new PhpBackend()))->of(ref('a'), [1]); } public function test_casts_each_value_into_the_returned_type(): void { - static::assertSame([5, 6], (new ResultColumn())->of(lit(1), ['5', 6])->values()); + static::assertSame([5, 6], (new ResultColumn(new PhpBackend()))->of(lit(1), ['5', 6])->values()); } - public function test_is_a_php_column_whatever_the_configured_backend(): void + public function test_builds_through_the_backend_it_was_given(): void { - static::assertInstanceOf(ScalarColumn::class, (new ResultColumn())->of(lit(1), [1, 2])); + $backend = new SpyBackend(); + + (new ResultColumn($backend))->of(lit(1), [1, 2]); + (new ResultColumn($backend))->of(lit(1), ['1', 2]); + + static::assertSame(2, $backend->builders()); } public function test_null_type_builds_a_null_column(): void { - $column = (new ResultColumn())->of(lit(null), [null, null]); + $column = (new ResultColumn(new PhpBackend()))->of(lit(null), [null, null]); static::assertEquals(type_null(), $column->type()); static::assertSame(2, $column->nullCount()); @@ -74,7 +80,7 @@ public function test_null_type_builds_a_null_column(): void public function test_refusal_names_the_row_of_the_value(): void { try { - (new ResultColumn())->of(lit(1), [1, 2, 'x']); + (new ResultColumn(new PhpBackend()))->of(lit(1), [1, 2, 'x']); static::fail('expected a SchemaMismatchException'); } catch (SchemaMismatchException $e) { static::assertSame(2, $e->rowIndex); @@ -83,7 +89,7 @@ public function test_refusal_names_the_row_of_the_value(): void public function test_type_without_a_column_kind_is_an_untyped_column(): void { - $column = (new ResultColumn())->of(call(lit('strval'), type_instance_of(ArrayObject::class)), [ + $column = (new ResultColumn(new PhpBackend()))->of(call(lit('strval'), type_instance_of(ArrayObject::class)), [ new ArrayObject(), null, ]); @@ -99,7 +105,7 @@ public function test_underivable_return_is_an_untyped_column(): void schema(json_schema('j')), ); - $column = (new ResultColumn())->of($function, ['a', ['b' => 1]]); + $column = (new ResultColumn(new PhpBackend()))->of($function, ['a', ['b' => 1]]); static::assertInstanceOf(ValueColumn::class, $column); static::assertSame(['a', ['b' => 1]], $column->values()); @@ -129,13 +135,13 @@ public function test_a_typed_column_holds_an_intermediate_only_when_it_keeps_the Type $type, bool $holds, ): void { - static::assertSame($holds, (new ResultColumn())->holdsLosslessly($type)); + static::assertSame($holds, (new ResultColumn(new PhpBackend()))->holdsLosslessly($type)); } public function test_an_untyped_array_keeps_its_objects(): void { $object = new ArrayObject(); - $column = (new ResultColumn())->typed(type_optional(type_array()), [[$object, 'count']]); + $column = (new ResultColumn(new PhpBackend()))->typed(type_optional(type_array()), [[$object, 'count']]); static::assertInstanceOf(ValueColumn::class, $column); static::assertSame([[$object, 'count']], $column->values()); @@ -143,7 +149,7 @@ public function test_an_untyped_array_keeps_its_objects(): void public function test_lists_of_an_expand_are_a_list_column(): void { - $column = (new ResultColumn())->lists(lit(1), [[1, 2], []]); + $column = (new ResultColumn(new PhpBackend()))->lists(lit(1), [[1, 2], []]); static::assertEquals(type_list(type_integer()), $column->type()); static::assertSame([[1, 2], []], $column->values()); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ReturnTypesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ReturnTypesTest.php index a36b1861cb..add7c90c87 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ReturnTypesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/Evaluation/ReturnTypesTest.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Tests\Unit\Function\Evaluation; -use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Function\Evaluation\ReturnTypes; use Flow\ETL\Tests\Double\ReturnsSpyFunction; use Flow\ETL\Tests\FlowTestCase; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LiteralTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LiteralTest.php index 3d2fb59a82..ff93600f34 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LiteralTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/LiteralTest.php @@ -6,9 +6,12 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Function\Literal; +use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; +use Flow\ETL\Tests\Mother\RowsMother; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\config_builder; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\lit; @@ -39,12 +42,13 @@ public function test_constructor_rejects_a_closure(): void public function test_a_batch_of_the_same_size_reuses_the_column(): void { $literal = lit(7); - $first = $literal->eval(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), flow_context()); + $context = flow_context(); + $first = $literal->eval(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), $context); static::assertSame($first, $literal->eval(array_to_rows([ ['id' => 3], ['id' => 4], - ], schema(int_schema('id'))), flow_context())); + ], schema(int_schema('id'))), $context)); static::assertSame([7, 7], $first->values()); } @@ -67,4 +71,26 @@ public function test_a_batch_of_another_size_gets_a_column_of_its_size(): void ->values(), ); } + + public function test_the_column_is_a_constant_of_the_configured_backend(): void + { + $backend = new SpyBackend(); + + lit(5)->eval(RowsMother::sequentialIds(3), flow_context(config_builder()->backend($backend)->build())); + + static::assertSame(1, $backend->constants()); + } + + public function test_a_batch_of_the_same_size_in_another_backend_gets_a_column_of_that_backend(): void + { + $literal = lit(5); + $first = new SpyBackend(); + $second = new SpyBackend(); + + $literal->eval(RowsMother::sequentialIds(3), flow_context(config_builder()->backend($first)->build())); + $literal->eval(RowsMother::sequentialIds(3), flow_context(config_builder()->backend($second)->build())); + + static::assertSame(1, $first->constants()); + static::assertSame(1, $second->constants()); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php index 732b95665a..ce7c73f868 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/OnEachTest.php @@ -304,7 +304,7 @@ public function test_the_body_is_bound_once_per_node_not_once_per_batch(): void static::assertSame(1, $operand->returnsCalls); } - public function test_the_element_batch_is_an_intermediate_built_without_the_configured_backend(): void + public function test_the_element_batch_is_built_by_the_configured_backend(): void { $backend = new SpyBackend(); $rows = array_to_rows([['l' => [1, 2]]], schema(list_schema('l', type_list(type_integer())))); @@ -316,7 +316,7 @@ public function test_the_element_batch_is_an_intermediate_built_without_the_conf ->eval($rows, flow_context(config_builder()->backend($backend)->build())) ->values(), ); - static::assertSame(0, $backend->builders()); + static::assertGreaterThanOrEqual(1, $backend->builders()); } public function test_the_function_evaluates_once_per_batch(): void diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php index 2e86f3e1f7..c19f40c875 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Function/ParameterTest.php @@ -52,14 +52,6 @@ public static function boolean_data_provider(): Generator yield 'null propagates' => [null, null]; } - public static function float_data_provider(): Generator - { - yield 'valid float' => [3.14, 3.14]; - yield 'zero float' => [0.0, 0.0]; - yield 'negative float' => [-2.5, -2.5]; - yield 'null propagates' => [null, null]; - } - public static function int_data_provider(): Generator { yield 'valid integer' => [42, null, 42]; @@ -222,32 +214,6 @@ public function test_as_enum_with_wrong_enum_class(): void ); } - #[DataProvider('float_data_provider')] - public function test_as_float(mixed $input, ?float $expected): void - { - static::assertSame( - [$expected], - (new Parameter(lit($input)))->asFloats(RowsMother::sequentialIds(1), flow_context()), - ); - } - - public function test_as_floats_refuses_an_integer_column(): void - { - $this->expectException(InvalidArgumentException::class); - - (new Parameter((new ReferenceResolver())->resolve( - ref('id'), - RowsMother::sequentialIds(2)->schema(), - )))->asFloats(RowsMother::sequentialIds(2), flow_context()); - } - - public function test_as_float_throws_on_a_malformed_value(): void - { - $this->expectException(InvalidArgumentException::class); - - (new Parameter(lit('3.14')))->asFloats(RowsMother::sequentialIds(1), flow_context()); - } - public function test_as_instance_of_propagates_null(): void { static::assertSame( @@ -441,29 +407,6 @@ public function test_as_number_throws_on_a_malformed_value(): void (new Parameter(lit('not numeric')))->asNumbers(RowsMother::sequentialIds(1), flow_context(), 99); } - public function test_as_object_propagates_null(): void - { - static::assertSame([null], (new Parameter(lit(null)))->asObjects(RowsMother::sequentialIds(1), flow_context())); - } - - public function test_as_object_throws_on_a_malformed_value(): void - { - $this->expectException(InvalidArgumentException::class); - - (new Parameter(lit('not an object')))->asObjects(RowsMother::sequentialIds(1), flow_context()); - } - - public function test_as_object_with_valid_object(): void - { - $object = new stdClass(); - $object->property = 'value'; - - static::assertSame( - [$object], - (new Parameter(lit($object)))->asObjects(RowsMother::sequentialIds(1), flow_context()), - ); - } - #[DataProvider('string_data_provider')] public function test_as_string(mixed $input, ?string $default, ?string $expected): void { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php index 0feb5d1de5..4a9e5e947e 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/GroupByTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit; +use DateTimeImmutable; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; @@ -13,15 +14,20 @@ use Flow\ETL\GroupBy\PivotShape; use Flow\ETL\Tests\Context\GroupByContext; use Flow\ETL\Tests\FlowTestCase; +use Flow\Types\Value\Json; +use Flow\Types\Value\Uuid; use Generator; use function array_map; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\config; use function Flow\ETL\DSL\count; +use function Flow\ETL\DSL\date_schema; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\flow_context; use function Flow\ETL\DSL\int_schema; +use function Flow\ETL\DSL\json_schema; use function Flow\ETL\DSL\min; use function Flow\ETL\DSL\pivot_values; use function Flow\ETL\DSL\ref; @@ -29,6 +35,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\uuid_schema; use function iterator_to_array; final class GroupByTest extends FlowTestCase @@ -416,4 +423,67 @@ public function test_keys_of_an_empty_batch_are_empty(): void (new GroupBy('country'))->keys(rows(schema(int_schema('age'))), schema(str_schema('country'))), ); } + + public function test_equal_datetime_instants_in_other_zones_are_one_group(): void + { + $rows = array_to_rows([ + ['at' => new DateTimeImmutable('2026-01-02 10:00:00 UTC')], + ['at' => new DateTimeImmutable('2026-01-02 11:00:00 +01:00')], + ], schema(datetime_schema('at'))); + $keys = (new GroupBy('at'))->keys($rows, $rows->schema()); + + static::assertSame((string) $keys[0], (string) $keys[1]); + } + + public function test_a_date_and_an_equal_datetime_instant_share_a_key(): void + { + $dates = array_to_rows([['at' => new DateTimeImmutable('2026-01-02')]], schema(date_schema('at'))); + $datetimes = array_to_rows([[ + 'at' => new DateTimeImmutable('2026-01-02 00:00:00 UTC'), + ]], schema(datetime_schema('at'))); + + static::assertSame( + (string) (new GroupBy('at'))->keys($dates, $dates->schema())[0], + (string) (new GroupBy('at'))->keys($datetimes, $datetimes->schema())[0], + ); + } + + public function test_uuid_and_json_keys_group_equal_values_and_keep_their_values(): void + { + $rows = array_to_rows( + [ + ['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479', 'doc' => '{"a":1}'], + ['id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479', 'doc' => '{"a":1}'], + ['id' => '00000000-0000-4000-8000-000000000000', 'doc' => '{"a":1}'], + ], + schema(uuid_schema('id'), json_schema('doc')), + ); + $keys = (new GroupBy('id', 'doc'))->keys($rows, $rows->schema()); + + static::assertSame((string) $keys[0], (string) $keys[1]); + static::assertNotSame((string) $keys[0], (string) $keys[2]); + static::assertEquals( + ['id' => new Uuid('f47ac10b-58cc-4372-a567-0e02b2c3d479'), 'doc' => new Json('{"a":1}')], + iterator_to_array($keys[0]), + ); + } + + public function test_keys_of_a_batch_that_lacks_a_nullable_key_match_a_present_null(): void + { + $input = schema(str_schema('a'), str_schema('b', nullable: true)); + $lacking = (new GroupBy('a', 'b'))->keys(array_to_rows([['a' => 'x']], schema(str_schema('a'))), $input); + $present = (new GroupBy('a', 'b'))->keys(array_to_rows([['a' => 'x', 'b' => null]], $input), $input); + + static::assertSame(['a' => 'x', 'b' => null], iterator_to_array($lacking[0])); + static::assertSame((string) $present[0], (string) $lacking[0]); + } + + public function test_keys_of_swapped_absences_do_not_collide(): void + { + $input = schema(str_schema('a', nullable: true), str_schema('b', nullable: true)); + $lacksB = (new GroupBy('a', 'b'))->keys(array_to_rows([['a' => 'x']], schema(str_schema('a'))), $input); + $lacksA = (new GroupBy('a', 'b'))->keys(array_to_rows([['b' => 'x']], schema(str_schema('b'))), $input); + + static::assertNotSame((string) $lacksB[0], (string) $lacksA[0]); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php index 8cfb579383..8ee649f3e0 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/JoinerTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Join\HashJoin; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Exception\SchemaDefinitionNotUniqueException; use Flow\ETL\Join\Comparison\All; use Flow\ETL\Join\Comparison\Any; @@ -36,6 +37,7 @@ public function test_any_comparison_falls_back_to_verifying_every_pair(): void $joiner = new Joiner( Expression::on(new Any(new Equal('id', 'user_id'), new Equal('email', 'contact'))), Join::inner, + new AdaptiveBackend(), ); foreach ($joiner->join( @@ -87,6 +89,7 @@ public function test_all_with_any_hashes_by_the_equality_and_verifies_the_rest() ), ), Join::inner, + new AdaptiveBackend(), ); foreach ($joiner->join( @@ -133,7 +136,7 @@ public function test_duplicated_right_rows_are_all_joined(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows([['id' => 1]], schema(int_schema('id'))))), @@ -158,7 +161,7 @@ public function test_inner_join_emits_every_matching_right_row(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -196,7 +199,7 @@ public function test_inner_join_drops_duplicated_right_join_columns(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'id']), Join::inner); + $joiner = new Joiner(join_on(['id' => 'id']), Join::inner, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -225,7 +228,7 @@ public function test_left_anti_join_keeps_left_row_on_hash_hit_without_match(): $joined = []; // int 1 and string "1" hash into the same bucket but are not identical - $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left_anti); + $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left_anti, new AdaptiveBackend()); $right = static function (): Generator { yield array_to_rows([['user_id' => '2']], schema(str_schema('user_id'))); @@ -254,7 +257,7 @@ public function test_left_join_keeps_left_row_on_hash_hit_without_match(): void $joined = []; // int 1 and string "1" hash into the same bucket but are not identical - $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left); + $joiner = new Joiner(Expression::on(new Identical('id', 'user_id')), Join::left, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -282,7 +285,7 @@ public function test_left_join_pads_unmatched_left_rows_with_nulls(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -317,7 +320,7 @@ public function test_prefix_collision_with_left_column_throws(): void $this->expectException(SchemaDefinitionNotUniqueException::class); $this->expectExceptionMessage('Entry definitions must be unique, duplicated entries: [left_name]'); - $joiner = new Joiner(join_on(['id' => 'user_id'], join_prefix: 'left_'), Join::inner); + $joiner = new Joiner(join_on(['id' => 'user_id'], join_prefix: 'left_'), Join::inner, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -341,7 +344,7 @@ public function test_swapped_inner_join_emits_the_same_rows(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::inner, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -380,7 +383,7 @@ public function test_swapped_left_anti_join_emits_unmatched_left_rows_at_the_end $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left_anti); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left_anti, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))))), @@ -403,7 +406,7 @@ public function test_swapped_left_join_pads_unmatched_left_rows_at_the_end(): vo $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -442,7 +445,7 @@ public function test_swapped_left_join_with_empty_right_side_pads_every_left_row $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -468,7 +471,7 @@ public function test_swapped_right_join_pads_unmatched_right_rows_inline(): void $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -503,7 +506,7 @@ public function test_right_join_emits_unmatched_right_rows_with_null_left_entrie $joined = []; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new AdaptiveBackend()); foreach ($joiner->join( JoinSide::of($batches(array_to_rows( @@ -535,7 +538,7 @@ public function test_left_join_emits_a_schema_declaring_the_right_side_nullable( yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()); $emitted = iterator_to_array( $joiner->join( @@ -568,7 +571,7 @@ public function test_right_join_emits_a_schema_declaring_the_left_side_nullable( yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::right, new AdaptiveBackend()); $emitted = iterator_to_array( $joiner->join( @@ -597,7 +600,7 @@ public function test_right_join_emits_a_schema_declaring_the_left_side_nullable( public function test_every_batch_of_a_multi_batch_left_side_shares_one_output_schema(): void { - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()); $emitted = iterator_to_array( $joiner->join( @@ -635,7 +638,7 @@ public function test_a_padded_row_covers_a_right_column_no_source_row_carried(): yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()); $joined = []; @@ -670,7 +673,7 @@ public function test_a_row_omitting_a_nullable_join_key_is_unmatched_rather_than yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()); $joined = []; @@ -704,7 +707,7 @@ public function test_a_left_batch_wider_than_the_output_schema_is_projected_not_ yield $rows; }; - $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left); + $joiner = new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()); $joined = []; @@ -743,7 +746,7 @@ public function test_a_build_side_spanning_batches_is_joined_as_one(): void $joined = []; - foreach ((new Joiner(join_on(['id' => 'user_id']), Join::left))->join( + foreach ((new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend()))->join( JoinSide::of($left()), JoinSide::of($right()), ) as $batch) { @@ -777,7 +780,7 @@ public function test_swapped_unmatched_build_rows_are_emitted_in_chunks_of_batch $batches = []; - foreach ((new Joiner(join_on(['id' => 'user_id']), Join::left, batchSize: 2))->join( + foreach ((new Joiner(join_on(['id' => 'user_id']), Join::left, new AdaptiveBackend(), batchSize: 2))->join( JoinSide::of($left()), JoinSide::of($right()), buildLeft: true, @@ -805,7 +808,7 @@ public function test_unmatched_build_rows_are_emitted_in_chunks_of_batch_size(): $batches = []; - foreach ((new Joiner(join_on(['id' => 'user_id']), Join::right, batchSize: 2))->join( + foreach ((new Joiner(join_on(['id' => 'user_id']), Join::right, new AdaptiveBackend(), batchSize: 2))->join( JoinSide::of($left()), JoinSide::of($right()), ) as $batch) { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/NullRowBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/NullRowBuilderTest.php index 9bec52016a..debbd17a90 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/NullRowBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/HashJoin/NullRowBuilderTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Join\HashJoin; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Join\HashJoin\NullRowBuilder; use Flow\ETL\Tests\FlowTestCase; @@ -16,7 +17,7 @@ final class NullRowBuilderTest extends FlowTestCase { public function test_empty_schema_produces_one_row_without_columns(): void { - $rows = (new NullRowBuilder(schema()))->rows(); + $rows = (new NullRowBuilder(schema(), new AdaptiveBackend()))->rows(); static::assertSame(1, $rows->count()); static::assertSame([], $rows->columns()); @@ -26,13 +27,20 @@ public function test_row_follows_schema_column_order(): void { static::assertSame( ['name', 'id'], - array_keys((new NullRowBuilder(schema(str_schema('name'), int_schema('id'))))->rows()->columns()), + array_keys( + (new NullRowBuilder(schema(str_schema('name'), int_schema('id')), new AdaptiveBackend())) + ->rows() + ->columns(), + ), ); } public function test_row_nulls_every_schema_column_under_a_nullable_schema(): void { - $rows = (new NullRowBuilder(schema(int_schema('id'), str_schema('name'), str_schema('country'))))->rows(); + $rows = (new NullRowBuilder( + schema(int_schema('id'), str_schema('name'), str_schema('country')), + new AdaptiveBackend(), + ))->rows(); static::assertSame([['id' => null, 'name' => null, 'country' => null]], $rows->toArray()); static::assertEquals( diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsJoinTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/RowsJoinTest.php similarity index 86% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/RowsJoinTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Join/RowsJoinTest.php index e1ac1d9f4c..973d1fa315 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsJoinTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Join/RowsJoinTest.php @@ -2,10 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit; +namespace Flow\ETL\Tests\Unit\Join; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Exception\SchemaDefinitionNotUniqueException; use Flow\ETL\Join\Expression; +use Flow\ETL\Join\RowsJoin; use Flow\ETL\Tests\FlowTestCase; use function Flow\ETL\DSL\array_to_rows; @@ -30,7 +32,7 @@ public function test_cross_join(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinCross(array_to_rows( + $joined = (new RowsJoin(new AdaptiveBackend()))->cross($left, array_to_rows( [['num' => 1, 'active' => true], ['num' => 2, 'active' => false]], schema(int_schema('num'), bool_schema('active')), )); @@ -63,23 +65,30 @@ public function test_cross_join_empty(): void ); // n x 0 = 0, and a zero-row batch fits the cross schema vacuously - static::assertSame([], $left->joinCross(rows(schema()))->toArray()); + static::assertSame( + [], + (new RowsJoin(new AdaptiveBackend())) + ->cross($left, rows(schema())) + ->toArray(), + ); } public function test_cross_join_with_an_empty_side_yields_no_rows_under_the_cross_schema(): void { // a cross join with an empty side produces zero rows, and the batch still declares both // sides' columns - the schema describes the plan, not the cardinality - $emptyRight = array_to_rows( - [['id' => 1, 'country' => 'PL']], - schema(int_schema('id'), str_schema('country')), - )->joinCross(rows(schema(str_schema('code')))); + $emptyRight = (new RowsJoin(new AdaptiveBackend()))->cross( + array_to_rows([['id' => 1, 'country' => 'PL']], schema(int_schema('id'), str_schema('country'))), + rows(schema(str_schema('code'))), + ); static::assertSame(['id', 'country', 'joined_code'], $emptyRight->schema()->references()->names()); static::assertSame([], $emptyRight->toArray()); - $emptyLeft = rows(schema(int_schema('id'))) - ->joinCross(array_to_rows([['code' => 'PL']], schema(str_schema('code')))); + $emptyLeft = (new RowsJoin(new AdaptiveBackend()))->cross( + rows(schema(int_schema('id'))), + array_to_rows([['code' => 'PL']], schema(str_schema('code'))), + ); static::assertSame(['id', 'joined_code'], $emptyLeft->schema()->references()->names()); static::assertSame([], $emptyLeft->toArray()); @@ -89,7 +98,7 @@ public function test_cross_join_left_empty(): void { $left = rows(schema()); - $joined = $left->joinCross(array_to_rows( + $joined = (new RowsJoin(new AdaptiveBackend()))->cross($left, array_to_rows( [ ['id' => 1, 'country' => 'PL'], ['id' => 2, 'country' => 'PL'], @@ -119,7 +128,11 @@ public function test_cross_join_left_with_name_conflict(): void schema(int_schema('id'), str_schema('country'), bool_schema('active')), ); - $left->joinCross(array_to_rows([['active' => true]], schema(bool_schema('active'))), ''); + (new RowsJoin(new AdaptiveBackend()))->cross( + $left, + array_to_rows([['active' => true]], schema(bool_schema('active'))), + '', + ); } public function test_cross_join_left_with_name_conflict_with_prefix(): void @@ -134,7 +147,11 @@ public function test_cross_join_left_with_name_conflict_with_prefix(): void schema(int_schema('id'), str_schema('country'), bool_schema('active')), ); - $joined = $left->joinCross(array_to_rows([['active' => true]], schema(bool_schema('active'))), '_'); + $joined = (new RowsJoin(new AdaptiveBackend()))->cross( + $left, + array_to_rows([['active' => true]], schema(bool_schema('active'))), + '_', + ); static::assertEquals( [ @@ -159,7 +176,11 @@ public function test_inner_empty(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinInner(rows(schema()), Expression::on(['country' => 'code'])); + $joined = (new RowsJoin(new AdaptiveBackend()))->inner( + $left, + rows(schema()), + Expression::on(['country' => 'code']), + ); static::assertEquals(rows(schema(int_schema('id'), str_schema('country'))), $joined); } @@ -176,7 +197,8 @@ public function test_inner_join(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinInner( + $joined = (new RowsJoin(new AdaptiveBackend()))->inner( + $left, array_to_rows( [ ['code' => 'PL', 'name' => 'Poland'], @@ -200,10 +222,8 @@ public function test_inner_join(): void public function test_inner_join_emits_every_matching_right_row(): void { - $joined = array_to_rows( - [['id' => 1, 'country' => 'PL']], - schema(int_schema('id'), str_schema('country')), - )->joinInner( + $joined = (new RowsJoin(new AdaptiveBackend()))->inner( + array_to_rows([['id' => 1, 'country' => 'PL']], schema(int_schema('id'), str_schema('country'))), array_to_rows( [['code' => 1, 'city' => 'Warsaw'], ['code' => 1, 'city' => 'Cracow']], schema(int_schema('code'), str_schema('city')), @@ -224,7 +244,8 @@ public function test_inner_join_into_empty(): void { $left = rows(schema()); - $joined = $left->joinInner( + $joined = (new RowsJoin(new AdaptiveBackend()))->inner( + $left, array_to_rows( [ ['code' => 'PL', 'name' => 'Poland'], @@ -256,7 +277,8 @@ public function test_inner_join_with_duplicated_entries(): void schema(int_schema('id'), str_schema('country')), ); - $left->joinInner( + (new RowsJoin(new AdaptiveBackend()))->inner( + $left, array_to_rows( [ ['id' => 101, 'code' => 'PL', 'name' => 'Poland'], @@ -281,7 +303,8 @@ public function test_inner_join_without_prefix(): void schema(int_schema('id'), str_schema('country_code')), ); - $joined = $left->joinInner( + $joined = (new RowsJoin(new AdaptiveBackend()))->inner( + $left, array_to_rows( [ ['country_code' => 'PL', 'name' => 'Poland'], @@ -310,7 +333,8 @@ public function test_left_anti_join(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinLeftAnti( + $joined = (new RowsJoin(new AdaptiveBackend()))->leftAnti( + $left, array_to_rows( [['code' => 'US', 'name' => 'United States'], ['code' => 'FR', 'name' => 'France']], schema(str_schema('code'), str_schema('name')), @@ -331,7 +355,11 @@ public function test_left_anti_join_on_empty(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinLeftAnti(rows(schema()), Expression::on(['country' => 'code'])); + $joined = (new RowsJoin(new AdaptiveBackend()))->leftAnti( + $left, + rows(schema()), + Expression::on(['country' => 'code']), + ); static::assertEquals($left, $joined); } @@ -347,7 +375,8 @@ public function test_left_anti_join_without_prefix(): void schema(int_schema('id'), str_schema('country_code')), ); - $joined = $left->joinLeftAnti( + $joined = (new RowsJoin(new AdaptiveBackend()))->leftAnti( + $left, array_to_rows( [['country_code' => 'US', 'name' => 'United States'], ['country_code' => 'FR', 'name' => 'France']], schema(str_schema('country_code'), str_schema('name')), @@ -368,7 +397,8 @@ public function test_left_join(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinLeft( + $joined = (new RowsJoin(new AdaptiveBackend()))->left( + $left, array_to_rows( [ ['code' => 'PL', 'name' => 'Poland'], @@ -397,7 +427,11 @@ public function test_left_join_empty(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinLeft(rows(schema()), Expression::on(['country' => 'code'])); + $joined = (new RowsJoin(new AdaptiveBackend()))->left( + $left, + rows(schema()), + Expression::on(['country' => 'code']), + ); static::assertEquals( array_to_rows( @@ -419,7 +453,11 @@ public function test_left_join_empty_without_prefix(): void schema(int_schema('id'), str_schema('country_code')), ); - $joined = $left->joinLeft(rows(schema()), Expression::on(['country_code' => 'country_code'])); + $joined = (new RowsJoin(new AdaptiveBackend()))->left( + $left, + rows(schema()), + Expression::on(['country_code' => 'country_code']), + ); static::assertEquals( array_to_rows( @@ -438,7 +476,8 @@ public function test_left_join_to_empty(): void { $left = rows(schema()); - $joined = $left->joinLeft( + $joined = (new RowsJoin(new AdaptiveBackend()))->left( + $left, array_to_rows( [ ['code' => 'PL', 'name' => 'Poland'], @@ -468,7 +507,8 @@ public function test_left_join_with_the_duplicated_columns(): void schema(int_schema('id'), str_schema('country')), ); - $left->joinLeft( + (new RowsJoin(new AdaptiveBackend()))->left( + $left, array_to_rows( [ ['id' => 100, 'code' => 'PL', 'name' => 'Poland'], @@ -492,7 +532,8 @@ public function test_left_join_without_prefix(): void schema(int_schema('id'), str_schema('country_code')), ); - $joined = $left->joinLeft( + $joined = (new RowsJoin(new AdaptiveBackend()))->left( + $left, array_to_rows( [ ['country_code' => 'PL', 'name' => 'Poland'], @@ -526,7 +567,8 @@ public function test_right_join(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinRight( + $joined = (new RowsJoin(new AdaptiveBackend()))->right( + $left, array_to_rows( [ ['code' => 'PL', 'name' => 'Poland'], @@ -561,7 +603,11 @@ public function test_right_join_empty(): void schema(int_schema('id'), str_schema('country')), ); - $joined = $left->joinRight(rows(schema()), Expression::on(['country' => 'code'])); + $joined = (new RowsJoin(new AdaptiveBackend()))->right( + $left, + rows(schema()), + Expression::on(['country' => 'code']), + ); static::assertEquals( rows(schema(int_schema('id', nullable: true), str_schema('country', nullable: true))), @@ -573,7 +619,8 @@ public function test_right_join_to_empty(): void { $left = rows(schema()); - $joined = $left->joinRight( + $joined = (new RowsJoin(new AdaptiveBackend()))->right( + $left, array_to_rows( [ ['code' => 'PL', 'name' => 'Poland'], @@ -612,7 +659,8 @@ public function test_right_join_with_duplicated_entry_names(): void schema(int_schema('id'), str_schema('country')), ); - $left->joinRight( + (new RowsJoin(new AdaptiveBackend()))->right( + $left, array_to_rows( [ ['id' => 101, 'code' => 'PL', 'name' => 'Poland'], @@ -637,7 +685,8 @@ public function test_right_join_without_prefix(): void schema(int_schema('id'), str_schema('country_code')), ); - $joined = $left->joinRight( + $joined = (new RowsJoin(new AdaptiveBackend()))->right( + $left, array_to_rows( [ ['country_code' => 'PL', 'name' => 'Poland'], diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/FileWriteFrameTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/FileWriteFrameTest.php new file mode 100644 index 0000000000..dc82bc2526 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/FileWriteFrameTest.php @@ -0,0 +1,156 @@ +write( + array_to_rows([['id' => 1, 'group' => 'a'], ['id' => 2, 'group' => 'b']], $schema), + flow_context(), + to_array($output), + ); + $frame->write(array_to_rows([['id' => 3, 'group' => 'a']], $schema), flow_context(), to_array($output)); + $frame->closure(); + + static::assertSame(['memory://out/group=a/file.txt', 'memory://out/group=b/file.txt'], $sinks->opened); + static::assertSame( + 'rows:1;rows:1;closed;', + $filesystem->readFrom(path('memory://out/group=a/file.txt'))->content(), + ); + static::assertSame('rows:1;closed;', $filesystem->readFrom(path('memory://out/group=b/file.txt'))->content()); + } + + public function test_closure_closes_every_sink_before_it_publishes(): void + { + $filesystem = memory_filesystem(); + $frame = new FileWriteFrame( + $filesystem, + path('memory://out/file.txt'), + SaveMode::ExceptionIfExists, + new PartitionRouter(Partitioning::none()), + new SpyFileSinks(), + ); + $output = []; + + $frame->write(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context(), to_array($output)); + $frame->closure(); + + static::assertSame('rows:1;closed;', $filesystem->readFrom(path('memory://out/file.txt'))->content()); + } + + public function test_discard_closes_every_sink_and_leaves_no_file(): void + { + $filesystem = memory_filesystem(); + $sinks = new SpyFileSinks(); + $frame = new FileWriteFrame( + $filesystem, + path('memory://out/file.txt'), + SaveMode::ExceptionIfExists, + new PartitionRouter(Partitioning::none()), + $sinks, + ); + $output = []; + + $frame->write(array_to_rows([['id' => 1]], schema(int_schema('id'))), flow_context(), to_array($output)); + $frame->discard(); + + static::assertSame(['memory://out/file.txt'], $sinks->closed); + static::assertNull($filesystem->status(path('memory://out/file.txt'))); + } + + public function test_a_throwing_sink_reports_the_load_as_failed(): void + { + $telemetry = new MemoryTelemetryContext(telemetry_options(trace_loading: true)); + $telemetry->flowContext->telemetry()->dataFrameStarted($telemetry->flowContext); + $frame = new FileWriteFrame( + memory_filesystem(), + path('memory://out/file.txt'), + SaveMode::ExceptionIfExists, + new PartitionRouter(Partitioning::none()), + new SpyFileSinks(failing: true), + ); + $output = []; + + try { + $frame->write( + array_to_rows([['id' => 1]], schema(int_schema('id'))), + $telemetry->flowContext, + to_array($output), + ); + static::fail('the sink failure must reach the caller'); + } catch (RuntimeException $e) { + static::assertSame('sink refused the batch', $e->getMessage()); + } + + $failed = $telemetry->spans->endedSpans(); + static::assertCount(1, $failed); + static::assertTrue($failed[0]->status()?->isError() ?? false); + } + + public function test_closure_closes_every_sink_then_rethrows_the_first_close_failure(): void + { + $sinks = new SpyFileSinks(failingClose: true); + $frame = new FileWriteFrame( + memory_filesystem(), + path('memory://out/file.txt'), + SaveMode::ExceptionIfExists, + new PartitionRouter(partition_by('group')), + $sinks, + ); + $output = []; + + $frame->write( + array_to_rows( + [['id' => 1, 'group' => 'a'], ['id' => 2, 'group' => 'b']], + schema(int_schema('id'), str_schema('group')), + ), + flow_context(), + to_array($output), + ); + + try { + $frame->closure(); + static::fail('a failing close must reach the caller'); + } catch (RuntimeException $e) { + static::assertSame('close of memory://out/group=a/file.txt failed', $e->getMessage()); + } + + static::assertSame(['memory://out/group=a/file.txt', 'memory://out/group=b/file.txt'], $sinks->closed); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Filesystem/FilesSinkTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/FilesSinkTest.php similarity index 79% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Filesystem/FilesSinkTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/FilesSinkTest.php index 4bde83dddd..e1564d19e7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Filesystem/FilesSinkTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/FilesSinkTest.php @@ -2,13 +2,12 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Filesystem; +namespace Flow\ETL\Tests\Unit\Loader\File; use Flow\ETL\Exception\RuntimeException; -use Flow\ETL\Filesystem\FilesSink; +use Flow\ETL\Loader\File\FilesSink; use Flow\ETL\Tests\Double\RecordingFilesystem; use Flow\ETL\Tests\FlowTestCase; -use Flow\Filesystem\Partition; use function array_search; use function Flow\ETL\DSL\exception_if_exists; @@ -63,17 +62,4 @@ public function test_the_same_destination_returns_the_same_stream(): void static::assertSame($files->writeTo(), $files->writeTo()); } - - public function test_touched_is_answered_per_partition(): void - { - $files = new FilesSink(memory_filesystem(), path('memory://out.csv'), exception_if_exists()); - $partition = [new Partition('day', '2024-01-01')]; - - static::assertFalse($files->touched($partition)); - - $files->writeTo($partition); - - static::assertTrue($files->touched($partition)); - static::assertFalse($files->touched([new Partition('day', '2024-01-02')])); - } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/PartitionRouterTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/PartitionRouterTest.php similarity index 82% rename from src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/PartitionRouterTest.php rename to src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/PartitionRouterTest.php index 9662f1da99..2cd3624daf 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/PartitionRouterTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Loader/File/PartitionRouterTest.php @@ -2,8 +2,9 @@ declare(strict_types=1); -namespace Flow\ETL\Tests\Unit\Loader; +namespace Flow\ETL\Tests\Unit\Loader\File; +use DateTimeImmutable; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Loader\Partitioning; use Flow\ETL\Tests\Context\PartitionRoutingContext; @@ -11,6 +12,7 @@ use function array_map; use function Flow\ETL\DSL\array_to_rows; +use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; @@ -109,4 +111,22 @@ public function test_partitioning_by_every_column_is_allowed_with_write_columns( )[0][1]->toArray(), ); } + + public function test_equal_datetime_instants_route_to_one_partition_and_keep_the_path_name(): void + { + $groups = PartitionRoutingContext::route( + Partitioning::by(ref('at')), + array_to_rows( + [ + ['id' => 1, 'at' => new DateTimeImmutable('2026-01-02 10:00:00 UTC')], + ['id' => 2, 'at' => new DateTimeImmutable('2026-01-02 10:00:00 UTC')], + ], + schema(int_schema('id'), datetime_schema('at')), + ), + ); + + static::assertCount(1, $groups); + static::assertSame([1, 2], $groups[0][1]->reduceToArray(ref('id'))); + static::assertSame('2026-01-02', $groups[0][0]->get('at')->value); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CachingProcessorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CachingProcessorTest.php index 731db0db31..590a6db035 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CachingProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/CachingProcessorTest.php @@ -7,6 +7,7 @@ use Flow\ETL\Cache\CacheIndex; use Flow\ETL\Cache\Implementation\InMemoryCache; use Flow\ETL\Cardinality; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Extractor\Signal; use Flow\ETL\Processor\CachingProcessor; use Flow\ETL\Rows; @@ -105,7 +106,7 @@ public function test_passes_through_when_cache_exists(): void $cache = new InMemoryCache(); $context = flow_context(config_builder()->cache($cache)->build()); - $cache->set('test-cache', (new CacheIndex('test-cache'))->toRows()); + $cache->set('test-cache', (new CacheIndex('test-cache'))->toRows(new PhpBackend())); $processor = new CachingProcessor('test-cache'); 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 index 787c4af8fd..e66f3b20c7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/TopNProcessorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Processor/TopNProcessorTest.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Tests\Unit\Processor; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Processor\MemorySortProcessor; use Flow\ETL\Processor\TopNProcessor; @@ -98,7 +99,7 @@ public function test_the_fallback_equals_a_sort_followed_by_a_limit(int $seed): $limit, ExternalSortMother::spilling($refs, $storage, mergeFanIn: 2), ))->process($input, flow_context()) as $batch) { - $top = $top->concat($batch->matchTo($dataset['schema'])); + $top = $top->concat(new AdaptiveBackend(), $batch->matchTo($dataset['schema'], new AdaptiveBackend())); } // serialized, so NaN and -0.0 compare by what they are diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/DeclaredColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/DeclaredColumnsTest.php deleted file mode 100644 index ccc3c89555..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/DeclaredColumnsTest.php +++ /dev/null @@ -1,55 +0,0 @@ - 1, 'name' => 'one'], ['id' => 2]], - (new DeclaredColumns())->project( - [['id' => 1, 'name' => 'one'], ['id' => 2]], - schema(int_schema('id'), str_schema('name', nullable: true)), - ), - ); - } - - public function test_drops_a_column_the_schema_does_not_declare(): void - { - static::assertSame( - [['id' => 1], ['id' => 2]], - (new DeclaredColumns())->project([ - ['id' => 1, 'name' => 'one'], - ['id' => 2, 'nmae' => 'two'], - ], schema(int_schema('id'))), - ); - } - - public function test_keeps_a_numeric_column_name_declared_as_is(): void - { - static::assertSame( - [[2024 => 1]], - (new DeclaredColumns())->project([['2024' => 1, 'other' => 2]], schema(int_schema('2024'))), - ); - } - - public function test_keeps_a_position_declared_by_its_positional_name(): void - { - static::assertSame([[0 => 'a']], (new DeclaredColumns())->project([['a', 'b']], schema(str_schema('e00')))); - } - - public function test_an_empty_batch_projects_to_nothing(): void - { - static::assertSame([], (new DeclaredColumns())->project([], schema(int_schema('id')))); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ColumnRetypingTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ColumnRetypingTest.php new file mode 100644 index 0000000000..33ae9a8ea9 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/ColumnRetypingTest.php @@ -0,0 +1,140 @@ +absent(int_schema('id', nullable: true), 2, new PhpBackend()) + ->values(), + ); + } + + public function test_an_absent_not_null_column_is_refused_when_there_is_a_row(): void + { + $this->expectException(SchemaMismatchException::class); + + (new ColumnRetyping())->absent(int_schema('id'), 1, new PhpBackend()); + } + + public function test_an_absent_not_null_column_of_no_rows_is_empty(): void + { + static::assertSame( + 0, + (new ColumnRetyping()) + ->absent(int_schema('id'), 0, new PhpBackend()) + ->count(), + ); + } + + public function test_the_same_definition_keeps_the_column(): void + { + $column = ColumnMother::of(int_schema('id'), [1, 2]); + + static::assertSame($column, (new ColumnRetyping())->restamped($column, int_schema('id'), int_schema('id'))); + } + + public function test_a_change_the_types_cannot_prove_is_not_restamped(): void + { + static::assertNull((new ColumnRetyping())->restamped( + ColumnMother::of(str_schema('id'), ['1']), + str_schema('id'), + int_schema('id'), + )); + } + + public function test_a_proved_change_is_restamped(): void + { + $retyped = (new ColumnRetyping())->restamped( + ColumnMother::of(int_schema('id'), [1, 2]), + int_schema('id'), + int_schema('id', nullable: true), + ); + + static::assertNotNull($retyped); + static::assertSame([1, 2], $retyped->values()); + } + + public function test_not_null_refuses_the_first_null_at_its_position(): void + { + try { + (new ColumnRetyping())->notNull( + int_schema('id'), + ColumnMother::of( + int_schema('id', nullable: true), + [ + 1, + null, + null, + ], + ), + ); + static::fail('a null under NOT NULL must be refused'); + } catch (SchemaMismatchException $e) { + static::assertSame(1, $e->rowIndex); + } + } + + public function test_cast_casts_what_the_types_cannot_prove(): void + { + static::assertSame( + [1, 2], + (new ColumnRetyping()) + ->cast( + ColumnMother::of(str_schema('id'), ['1', '2']), + str_schema('id'), + int_schema('id'), + new PhpBackend(), + ) + ->values(), + ); + } + + public function test_validate_refuses_the_lowest_bad_row_across_columns(): void + { + try { + (new ColumnRetyping())->validate([ + 'a' => [ + ColumnMother::of(list_schema('a', type_list(type_optional(type_integer()))), [[1], [2], [null]]), + list_schema('a', type_list(type_integer())), + ], + 'b' => [ + ColumnMother::of(list_schema('b', type_list(type_optional(type_integer()))), [[1], [null], [3]]), + list_schema('b', type_list(type_integer())), + ], + ], 3); + static::fail('a value the definition does not take must be refused'); + } catch (SchemaMismatchException $e) { + static::assertSame(1, $e->rowIndex); + static::assertStringContainsString('"b"', $e->getMessage()); + } + } + + public function test_a_proved_change_with_a_null_under_not_null_is_left_to_validate(): void + { + static::assertNull((new ColumnRetyping())->restamped( + ColumnMother::of(int_schema('id', nullable: true), [1, null]), + int_schema('id', nullable: true), + int_schema('id'), + )); + } +} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowEqualityTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowEqualityTest.php deleted file mode 100644 index 8f0b1a4abc..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowEqualityTest.php +++ /dev/null @@ -1,165 +0,0 @@ -equal( - ['id' => type_integer(), 'name' => type_string()], - ['id' => [1]], - 0, - ['id' => [1], 'name' => ['a']], - 0, - )); - } - - public function test_not_in_keeps_rows_without_an_equal_row_in_the_other_batch(): void - { - $schema = schema(int_schema('id'), str_schema('name')); - - static::assertSame( - [1, 2], - (new RowEquality())->notIn( - array_to_rows([ - ['id' => 1, 'name' => 'a'], - ['id' => 2, 'name' => 'b'], - ['id' => 1, 'name' => 'z'], - ], $schema), - array_to_rows([['id' => 1, 'name' => 'a'], ['id' => 3, 'name' => 'c']], $schema), - $schema, - ), - ); - } - - public function test_not_in_keeps_every_row_when_the_columns_differ(): void - { - static::assertSame( - [0, 1], - (new RowEquality())->notIn( - array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), - array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))), - schema(int_schema('id')), - ), - ); - } - - public function test_unique_compares_values_not_instances(): void - { - $schema = schema(uuid_schema('id')); - - static::assertSame( - [0, 2], - (new RowEquality())->unique(array_to_rows([ - ['id' => new Uuid('0198f4f2-37e3-7e1c-9a2e-1f2b3c4d5e6f')], - ['id' => new Uuid('0198f4f2-37e3-7e1c-9a2e-1f2b3c4d5e6f')], - ['id' => new Uuid('0198f4f2-37e3-7e1c-9a2e-1f2b3c4d5e70')], - ], $schema)), - ); - } - - public function test_unique_compares_only_rows_whose_exact_columns_hash_alike(): void - { - $calls = new ArrayObject(); - $documents = []; - - for ($i = 0; $i < 20; $i++) { - $documents[] = new CountingDOMDocument($calls); - } - - $ids = array_to_rows( - array_map(static fn(int $id): array => ['id' => $id], range(0, 19)), - schema(int_schema('id')), - ); - $schema = schema(xml_schema('x'), int_schema('id')); - $rows = Rows::fromColumns( - $schema, - ['x' => new FixedValuesColumn(type_xml(), $documents), 'id' => $ids->column('id')], - 20, - ); - - static::assertSame(range(0, 19), (new RowEquality())->unique($rows)); - static::assertCount(0, $calls); - } - - public function test_not_in_compares_only_rows_whose_exact_columns_hash_alike(): void - { - $calls = new ArrayObject(); - $schema = schema(xml_schema('x'), int_schema('id')); - $batch = static fn(int $from): Rows => Rows::fromColumns( - $schema, - [ - 'x' => new FixedValuesColumn(type_xml(), array_map( - static fn(): CountingDOMDocument => new CountingDOMDocument($calls), - range(0, 9), - )), - 'id' => array_to_rows( - array_map(static fn(int $id): array => ['id' => $id], range($from, $from + 9)), - schema(int_schema('id')), - )->column('id'), - ], - 10, - ); - - static::assertSame(range(0, 9), (new RowEquality())->notIn($batch(0), $batch(100), $schema)); - static::assertCount(0, $calls); - } - - public function test_unique_keeps_json_rows_equal_by_value_although_they_hash_apart(): void - { - static::assertSame( - [0], - (new RowEquality())->unique(array_to_rows([ - ['j' => new Json('{"a":1,"b":2}')], - ['j' => new Json('{"b":2,"a":1}')], - ], schema(json_schema('j')))), - ); - } - - public function test_unique_keeps_the_first_row_of_every_equal_group(): void - { - static::assertSame( - [0, 1, 4], - (new RowEquality())->unique(array_to_rows( - [ - ['id' => 1, 'name' => 'a'], - ['id' => 2, 'name' => 'b'], - ['id' => 1, 'name' => 'a'], - ['id' => 2, 'name' => 'b'], - ['id' => 3, 'name' => null], - ], - schema(int_schema('id'), str_schema('name', nullable: true)), - )), - ); - } - - public function test_unique_of_an_empty_batch_is_empty(): void - { - static::assertSame([], (new RowEquality())->unique(array_to_rows([], schema(int_schema('id'))))); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowHashesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowHashesTest.php index 467f2b4b46..1452d743e5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowHashesTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowHashesTest.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Tests\Unit\Rows; use DateTimeImmutable; +use Flow\ETL\Bucketing\NativeHasher; use Flow\ETL\Hash\NativePHPHash; use Flow\ETL\Rows; use Flow\ETL\Rows\RowHashes; @@ -138,7 +139,7 @@ public function test_the_algorithm_hashes_each_row(): void $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); static::assertSame( - [(new NativePHPHash('md5'))->hash('id1')], + [(new NativePHPHash('md5'))->hash('id' . NativeHasher::normalize(1))], (new RowHashes())->of($rows, new NativePHPHash('md5')), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBufferTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBufferTest.php deleted file mode 100644 index be98f8b8f6..0000000000 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBufferTest.php +++ /dev/null @@ -1,118 +0,0 @@ -appendFrom(array_to_rows([['id' => 1]], schema(int_schema('id'))), 0); - - static::assertGreaterThanOrEqual(1, $backend->builders()); - } - - public function test_a_released_batch_carries_the_buffer_schema(): void - { - $schema = schema(int_schema('id', nullable: true)); - $buffer = new RowsBuffer($schema, new PhpBackend(), 1); - - static::assertTrue( - $buffer - ->appendFrom(array_to_rows([['id' => 1]], $schema), 0) - ?->schema() - ->isSame($schema), - ); - } - - public function test_append_from_checks_every_row(): void - { - $this->expectException(SchemaMismatchException::class); - - (new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 1))->appendFrom(array_to_rows([[ - 'id' => 'x', - ]], schema(str_schema('id'))), 0); - } - - public function test_append_from_returns_a_full_batch_and_resets(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 2); - - static::assertNull($buffer->appendFrom($rows, 0)); - - $batch = $buffer->appendFrom($rows, 1); - - static::assertNotNull($batch); - static::assertSame([1, 2], $batch->reduceToArray('id')); - static::assertNull($buffer->appendFrom($rows, 2)); - } - - public function test_append_from_returns_null_until_size_is_reached(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 3); - - static::assertNull($buffer->appendFrom($rows, 0)); - static::assertNull($buffer->appendFrom($rows, 1)); - } - - public function test_append_returns_a_full_batch(): void - { - $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 2); - - static::assertNull($buffer->append(['id' => 1])); - static::assertSame([1, 2], $buffer->append(['id' => 2])?->reduceToArray('id')); - } - - public function test_append_take_overshooting_the_size_is_released_whole(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 2); - - static::assertSame([3, 1, 2], $buffer->appendTake($rows, [2, 0, 1])?->reduceToArray('id')); - static::assertNull($buffer->flush()); - } - - public function test_flush_returns_null_when_empty(): void - { - static::assertNull((new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 2))->flush()); - } - - public function test_flush_returns_the_remainder(): void - { - $buffer = new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 3); - $buffer->append(['id' => 1]); - - $batch = $buffer->flush(); - - static::assertNotNull($batch); - static::assertSame([1], $batch->reduceToArray('id')); - static::assertNull($buffer->flush()); - } - - public function test_throws_when_size_below_one(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Buffer size must be greater than 0, given: 0'); - - // @mago-ignore analysis:invalid-argument - new RowsBuffer(schema(int_schema('id')), new PhpBackend(), 0); - } -} diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php index 03c75a0c36..e97eabe8e9 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Rows/RowsBuilderTest.php @@ -734,4 +734,110 @@ public function test_a_refused_value_in_a_column_every_row_carries_is_placed_at_ ['id' => 'x'], ]); } + + public function test_append_records_takes_a_single_record(): void + { + static::assertSame( + [['id' => 1]], + (new RowsBuilder(schema(int_schema('id')), new PhpBackend())) + ->appendRecords(['id' => 1]) + ->finish() + ->toArray(), + ); + } + + public function test_append_records_takes_a_list_of_records(): void + { + static::assertSame( + [['id' => 1], ['id' => 2]], + (new RowsBuilder(schema(int_schema('id')), new PhpBackend())) + ->appendRecords([['id' => 1], ['id' => 2]]) + ->finish() + ->toArray(), + ); + } + + public function test_append_records_matches_a_numeric_string_key_to_its_declared_name(): void + { + static::assertSame( + [1], + (new RowsBuilder(schema(int_schema('2024')), new PhpBackend())) + ->appendRecords([['2024' => 1]]) + ->finish() + ->column('2024') + ->values(), + ); + } + + public function test_append_records_refuses_an_undeclared_key_at_its_row(): void + { + try { + (new RowsBuilder(schema(int_schema('id')), new PhpBackend()))->appendRecords([ + ['id' => 1], + ['id' => 2, 'nmae' => 'two'], + ]); + static::fail('an undeclared key must be refused'); + } catch (SchemaMismatchException $e) { + static::assertSame(1, $e->rowIndex); + static::assertStringContainsString('nmae', $e->getMessage()); + } + } + + public function test_append_records_refuses_an_undeclared_key_at_its_row_after_a_prior_append(): void + { + try { + (new RowsBuilder(schema(int_schema('id')), new PhpBackend()))->appendRecords([ + ['id' => 1], + ['id' => 2], + ])->appendRecords([['id' => 3, 'nmae' => 'three']]); + static::fail('an undeclared key must be refused'); + } catch (SchemaMismatchException $e) { + static::assertSame(2, $e->rowIndex); + } + } + + public function test_append_projected_drops_an_undeclared_key(): void + { + static::assertSame( + [['id' => 1, 'name' => 'one'], ['id' => 2, 'name' => null]], + (new RowsBuilder(schema(int_schema('id'), str_schema('name', nullable: true)), new PhpBackend())) + ->appendProjected([['id' => 1, 'name' => 'one'], ['id' => 2, 'nmae' => 'two']]) + ->finish() + ->toArray(), + ); + } + + public function test_append_projected_keeps_an_int_key_whose_positional_name_is_declared(): void + { + static::assertSame( + [['e00' => 'a']], + (new RowsBuilder(schema(str_schema('e00')), new PhpBackend())) + ->appendProjected([['a', 'b']]) + ->finish() + ->toArray(), + ); + } + + public function test_append_projected_keeps_a_numeric_column_name_declared_as_is(): void + { + static::assertSame( + [1], + (new RowsBuilder(schema(int_schema('2024')), new PhpBackend())) + ->appendProjected([['2024' => 1, 'other' => 2]]) + ->finish() + ->column('2024') + ->values(), + ); + } + + public function test_append_projected_of_nothing_appends_nothing(): void + { + static::assertSame( + 0, + (new RowsBuilder(schema(int_schema('id')), new PhpBackend())) + ->appendProjected([]) + ->finish() + ->count(), + ); + } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php index b5d7592e2a..5ed2c1d30b 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsSerializationTest.php @@ -6,9 +6,9 @@ use DOMDocument; use DOMElement; -use Flow\ETL\Column\Php\HtmlDocumentPhysical; -use Flow\ETL\Column\Php\HtmlElementPhysical; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\Physical\HtmlDocumentPhysical; +use Flow\ETL\Column\Physical\HtmlElementPhysical; use Flow\ETL\Rows; use Flow\ETL\Schema\Metadata; use Flow\ETL\Tests\Context\RowsSerializationContext; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php index 17ee488898..d0043b79b1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/RowsTest.php @@ -8,16 +8,22 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Column\AdaptiveBackend; -use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\Php\ConstantColumn; +use Flow\ETL\Column\Php\ScalarColumn; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\RustBackend; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Exception\InvalidArgumentException; +use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Rows; use Flow\ETL\Schema; +use Flow\ETL\Tests\Double\SpyColumn; use Flow\ETL\Tests\FlowTestCase; use Generator; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\TestWith; use function Flow\ETL\DSL\array_to_rows; @@ -55,7 +61,6 @@ public static function negative_sizes(): Generator yield 'drop' => [static fn(Rows $rows): Rows => $rows->drop(-1)]; yield 'dropRight' => [static fn(Rows $rows): Rows => $rows->dropRight(-1)]; yield 'take' => [static fn(Rows $rows): Rows => $rows->take(-1)]; - yield 'takeRight' => [static fn(Rows $rows): Rows => $rows->takeRight(-1)]; } /** @@ -70,100 +75,12 @@ public function test_a_negative_size_is_refused(Closure $call): void $call(array_to_rows([['id' => 1]], schema(int_schema('id')))); } - public static function rows_diff_left_provider(): Generator - { - yield 'one entry identical row' => [ - rows(schema()), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - ]; - - yield 'one entry right different - missing entry' => [ - array_to_rows([['number' => 1]], schema(int_schema('number'))), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - rows(schema()), - ]; - - yield 'one entry left different - missing entry' => [ - rows(schema()), - rows(schema()), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - ]; - - yield 'one entry right different - different entry' => [ - array_to_rows([['number' => 1]], schema(int_schema('number'))), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - array_to_rows([['number' => 2]], schema(int_schema('number'))), - ]; - - yield 'one entry left different - different entry' => [ - array_to_rows([['number' => 2]], schema(int_schema('number'))), - array_to_rows([['number' => 2]], schema(int_schema('number'))), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - ]; - } - - public static function rows_diff_right_provider(): Generator - { - yield 'one entry identical row' => [ - rows(schema()), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - ]; - - yield 'one entry right different - missing entry' => [ - rows(schema()), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - rows(schema()), - ]; - - yield 'one entry left different - missing entry' => [ - array_to_rows([['number' => 1]], schema(int_schema('number'))), - rows(schema()), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - ]; - - yield 'one entry right different - different entry' => [ - array_to_rows([['number' => 2]], schema(int_schema('number'))), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - array_to_rows([['number' => 2]], schema(int_schema('number'))), - ]; - - yield 'one entry left different - different entry' => [ - array_to_rows([['number' => 1]], schema(int_schema('number'))), - array_to_rows([['number' => 2]], schema(int_schema('number'))), - array_to_rows([['number' => 1]], schema(int_schema('number'))), - ]; - } - - public static function unique_rows_provider(): Generator - { - yield 'simple identical rows' => [ - array_to_rows([['number' => 1]], schema(int_schema('number'))), - array_to_rows([['number' => 1], ['number' => 1]], schema(int_schema('number'))), - ]; - yield 'rows equal in one column only' => [ - array_to_rows( - [['number' => 1, 'name' => 'a'], ['number' => 1, 'name' => 'b']], - schema(int_schema('number'), str_schema('name', true)), - ), - array_to_rows( - [['number' => 1, 'name' => 'a'], ['number' => 1, 'name' => 'b'], ['number' => 1, 'name' => 'a']], - schema(int_schema('number'), str_schema('name', true)), - ), - ]; - yield 'null and empty string are distinct' => [ - array_to_rows([['name' => null], ['name' => '']], schema(str_schema('name', true))), - array_to_rows([['name' => null], ['name' => ''], ['name' => null]], schema(str_schema('name', true))), - ]; - } - public function test_match_to_adopts_a_wider_schema_and_pads_the_new_nullable_column(): void { static::assertSame( [['id' => 1, 'name' => null]], array_to_rows([['id' => 1]], schema(int_schema('id'))) - ->matchTo(schema(int_schema('id'), str_schema('name', true))) + ->matchTo(schema(int_schema('id'), str_schema('name', true)), new AdaptiveBackend()) ->toArray(), ); } @@ -173,7 +90,10 @@ public function test_match_to_reports_the_violating_row_at_its_position_in_the_b $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "id" (row 0): could not convert 1 (integer) to string'); - array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))->matchTo(schema(str_schema('id'))); + array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))->matchTo( + schema(str_schema('id')), + new AdaptiveBackend(), + ); } public function test_project_drops_the_columns_the_schema_does_not_declare(): void @@ -184,13 +104,13 @@ public function test_project_drops_the_columns_the_schema_does_not_declare(): vo [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')), ) - ->project(schema(int_schema('id'))) + ->project(schema(int_schema('id')), new AdaptiveBackend()) ->toArray(), ); static::assertSame( ['name' => 'a', 'id' => 1], array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))) - ->project(schema(str_schema('name'), int_schema('id'))) + ->project(schema(str_schema('name'), int_schema('id')), new AdaptiveBackend()) ->values(0), ); } @@ -201,7 +121,10 @@ public function test_project_rejects_a_schema_that_widens_the_batch(): void $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "name" (row 0) declared by the schema is missing from the row'); - array_to_rows([['id' => 1]], schema(int_schema('id')))->project(schema(int_schema('id'), str_schema('name'))); + array_to_rows([['id' => 1]], schema(int_schema('id')))->project( + schema(int_schema('id'), str_schema('name')), + new AdaptiveBackend(), + ); } public function test_project_rejects_a_schema_that_retypes_a_column(): void @@ -209,10 +132,10 @@ public function test_project_rejects_a_schema_that_retypes_a_column(): void $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage('column "id" (row 0): could not convert 1 (integer) to string'); - array_to_rows( - [['id' => 1, 'name' => 'a']], - schema(int_schema('id'), str_schema('name')), - )->project(schema(str_schema('id'))); + array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))->project( + schema(str_schema('id')), + new AdaptiveBackend(), + ); } public function test_construct_reorders_row_storage_into_schema_order(): void @@ -347,172 +270,27 @@ public function test_empty_rows(): void static::assertFalse(array_to_rows([['id' => 1]], schema(int_schema('id')))->isEmpty()); } - public function test_hash(): void - { - $rows = array_to_rows( - [ - ['id' => 1, 'bool' => false], - ['id' => 2, 'bool' => false], - ['id' => 3, 'bool' => false], - ['id' => 4, 'bool' => false], - ], - schema(int_schema('id'), bool_schema('bool')), - ); - - static::assertSame( - $rows->hash(), - array_to_rows( - [ - ['bool' => false, 'id' => 1], - ['bool' => false, 'id' => 2], - ['bool' => false, 'id' => 3], - ['bool' => false, 'id' => 4], - ], - schema(bool_schema('bool'), int_schema('id')), - )->hash(), - ); - } - - public function test_hash_empty_rows(): void - { - static::assertSame(rows(schema())->hash(), rows(schema())->hash()); - } - - public function test_hash_rows_with_different_columns(): void - { - $rows = array_to_rows( - [ - ['id' => 1, 'bool' => false], - ['id' => 3, 'bool' => false], - ['id' => 2, 'bool' => false], - ['id' => 4, 'bool' => false], - ], - schema(int_schema('id'), bool_schema('bool')), - ); - - static::assertNotSame( - $rows->hash(), - array_to_rows([ - ['bool' => false], - ['bool' => false], - ['bool' => false], - ['bool' => false], - ], schema(bool_schema('bool')))->hash(), - ); - } - - public function test_hash_rows_with_different_order(): void - { - $rows = array_to_rows( - [ - ['id' => 1, 'bool' => false], - ['id' => 3, 'bool' => false], - ['id' => 2, 'bool' => false], - ['id' => 4, 'bool' => false], - ], - schema(int_schema('id'), bool_schema('bool')), - ); - - static::assertNotSame( - $rows->hash(), - array_to_rows( - [ - ['bool' => false, 'id' => 1], - ['bool' => false, 'id' => 2], - ['bool' => false, 'id' => 3], - ['bool' => false, 'id' => 4], - ], - schema(bool_schema('bool'), int_schema('id')), - )->hash(), - ); - } - - public function test_head(): void - { - $rows = array_to_rows([ - ['id' => 1], - ['id' => 2], - ['id' => 3], - ['id' => 4], - ['id' => 5], - ], schema(int_schema('id'))); - - $head = $rows->head(3); - - static::assertCount(3, $head); - static::assertSame(1, $head->column('id')->value(0)); - static::assertSame(2, $head->column('id')->value(1)); - static::assertSame(3, $head->column('id')->value(2)); - } - - public function test_head_on_empty_rows(): void - { - $head = rows(schema())->head(5); - - static::assertCount(0, $head); - } - - public function test_head_with_count_larger_than_available(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $head = $rows->head(10); - - static::assertCount(3, $head); - static::assertSame(1, $head->column('id')->value(0)); - static::assertSame(2, $head->column('id')->value(1)); - static::assertSame(3, $head->column('id')->value(2)); - } - - public function test_head_with_negative_count(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Count must be greater than or equal to 0'); - - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $rows->head(-1); - } - - public function test_head_with_zero_count(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $head = $rows->head(0); - - static::assertCount(0, $head); - } - - public function test_merge_accepts_an_empty_side_with_any_schema(): void - { - $rows = array_to_rows([['id' => 1]], schema(int_schema('id'))); - - // an empty batch has nothing to disagree about, so it short-circuits before the schema check - static::assertEquals($rows, $rows->merge(rows(schema(str_schema('unrelated'))))); - static::assertEquals($rows, rows(schema(str_schema('unrelated')))->merge($rows)); - } - - public function test_merge_throws_when_schemas_disagree(): void + public function test_concat_throws_when_schemas_disagree(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( - 'Cannot merge Rows with different schemas: [id: integer] and [id: integer, name: string]', + 'Cannot concat Rows with different schemas: [id: integer] and [id: integer, name: string]', ); - array_to_rows([['id' => 1]], schema(int_schema('id')))->merge(array_to_rows( - [['id' => 2, 'name' => 'x']], - schema(int_schema('id'), str_schema('name')), - )); + array_to_rows([['id' => 1]], schema(int_schema('id')))->concat( + new PhpBackend(), + array_to_rows([['id' => 2, 'name' => 'x']], schema(int_schema('id'), str_schema('name'))), + ); } - public function test_merges_collection_together(): void + public function test_concat_joins_batches_in_order(): void { $rowsOne = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); $rowsTwo = array_to_rows([['id' => 3], ['id' => 4], ['id' => 5]], schema(int_schema('id'))); $rowsThree = array_to_rows([['id' => 6], ['id' => 7]], schema(int_schema('id'))); - $merged = $rowsOne->merge($rowsTwo)->merge($rowsThree); + $merged = $rowsOne->concat(new PhpBackend(), $rowsTwo)->concat(new PhpBackend(), $rowsThree); static::assertEquals( array_to_rows([ @@ -546,39 +324,6 @@ public function test_remove_on_empty_rows(): void rows(schema())->remove(1); } - public function test_reverse(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $rows = $rows->reverse(); - - static::assertCount(3, $rows); - static::assertSame(3, $rows->column('id')->value(0)); - static::assertSame(2, $rows->column('id')->value(1)); - static::assertSame(1, $rows->column('id')->value(2)); - } - - #[DataProvider('rows_diff_left_provider')] - public function test_rows_diff_left(Rows $expected, Rows $left, Rows $right): void - { - static::assertEquals($expected->toArray(), $left->diffLeft($right)->toArray()); - } - - #[DataProvider('rows_diff_right_provider')] - public function test_rows_diff_right(Rows $expected, Rows $left, Rows $right): void - { - static::assertEquals($expected->toArray(), $left->diffRight($right)->toArray()); - } - - public function test_rows_diff_right_carries_the_right_sides_schema(): void - { - // the surviving rows come from the right side, so the left side's schema cannot describe them - $left = array_to_rows([['number' => 1]], schema(int_schema('number'))); - $right = array_to_rows([['number' => 2, 'name' => 'two']], schema(int_schema('number'), str_schema('name'))); - - static::assertTrue($left->diffRight($right)->schema()->isSame($right->schema())); - } - public function test_rows_schema(): void { $rows = array_to_rows( @@ -617,10 +362,10 @@ public function test_rows_reject_a_row_whose_list_contradicts_the_declared_eleme array_to_rows([ ['list' => []], ['list' => [1, 2]], - ], schema(list_schema('list', type_list(type_integer()))))->matchTo(schema(list_schema( - 'list', - type_list(type_string()), - ))); + ], schema(list_schema('list', type_list(type_integer()))))->matchTo( + schema(list_schema('list', type_list(type_string()))), + new AdaptiveBackend(), + ); } public function test_rows_serialization(): void @@ -636,12 +381,6 @@ public function test_rows_serialization(): void static::assertTrue($rows->schema()->isSame($unserialized->schema())); } - #[DataProvider('unique_rows_provider')] - public function test_rows_unique(Rows $expected, Rows $notUnique): void - { - static::assertSame($expected->toArray(), $notUnique->unique()->toArray()); - } - public function test_sort_rows_by_not_existing_column(): void { $this->expectException(InvalidArgumentException::class); @@ -716,87 +455,14 @@ public function test_sort_rows_without_changing_original_collection(): void schema(int_schema('number'), str_schema('name')), ); - $ascending = $rows->sortAscending(ref('number')); - $descending = $rows->sortDescending(ref('number')); + $ascending = $rows->sortBy(ref('number')); + $descending = $rows->sortBy(ref('number')->desc()); static::assertSame([1, 2, 3, 4, 5], $ascending->column('number')->values()); static::assertSame([5, 4, 3, 2, 1], $descending->column('number')->values()); static::assertSame([3, 1, 5, 2, 4], $rows->column('number')->values()); } - public function test_tail(): void - { - $rows = array_to_rows([ - ['id' => 1], - ['id' => 2], - ['id' => 3], - ['id' => 4], - ['id' => 5], - ], schema(int_schema('id'))); - - $tail = $rows->tail(3); - - static::assertCount(3, $tail); - static::assertSame(3, $tail->column('id')->value(0)); - static::assertSame(4, $tail->column('id')->value(1)); - static::assertSame(5, $tail->column('id')->value(2)); - } - - public function test_tail_maintains_correct_order(): void - { - $rows = array_to_rows([ - ['id' => 1], - ['id' => 2], - ['id' => 3], - ['id' => 4], - ['id' => 5], - ], schema(int_schema('id'))); - - $tail = $rows->tail(2); - - static::assertCount(2, $tail); - static::assertSame(4, $tail->column('id')->value(0)); - static::assertSame(5, $tail->column('id')->value(1)); - } - - public function test_tail_on_empty_rows(): void - { - $tail = rows(schema())->tail(5); - - static::assertCount(0, $tail); - } - - public function test_tail_with_count_larger_than_available(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $tail = $rows->tail(10); - - static::assertCount(3, $tail); - static::assertSame(1, $tail->column('id')->value(0)); - static::assertSame(2, $tail->column('id')->value(1)); - static::assertSame(3, $tail->column('id')->value(2)); - } - - public function test_tail_with_negative_count(): void - { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Count must be greater than or equal to 0'); - - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $rows->tail(-1); - } - - public function test_tail_with_zero_count(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $tail = $rows->tail(0); - - static::assertCount(0, $tail); - } - public function test_take(): void { $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); @@ -831,40 +497,6 @@ public function test_take_more_than_exists(): void static::assertSame(3, $rows->column('id')->value(2)); } - public function test_take_right(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $rows = $rows->takeRight(1); - - static::assertCount(1, $rows); - static::assertSame(3, $rows->column('id')->value(0)); - } - - public function test_take_right_all(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $rows = $rows->takeRight(3); - - static::assertCount(3, $rows); - static::assertSame(3, $rows->column('id')->value(0)); - static::assertSame(2, $rows->column('id')->value(1)); - static::assertSame(1, $rows->column('id')->value(2)); - } - - public function test_take_right_more_than_exists(): void - { - $rows = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - - $rows = $rows->takeRight(4); - - static::assertCount(3, $rows); - static::assertSame(3, $rows->column('id')->value(0)); - static::assertSame(2, $rows->column('id')->value(1)); - static::assertSame(1, $rows->column('id')->value(2)); - } - public function test_transforms_rows_to_array(): void { $rows = array_to_rows( @@ -988,16 +620,12 @@ public function test_structure_field_order_is_a_schema_difference_not_a_value_di 'a' => type_integer(), ])))); - // Values are compared by content (ArrayComparison), so the two rows are equal ... - static::assertCount(0, $left->diffLeft($right)); - static::assertCount(0, $left->diffRight($right)); - - // ... and the field-order difference lives in the Schema, which 04c made positional, so R6 + // the field-order difference lives in the Schema, which 04c made positional, so R6 // refuses the merge rather than emitting a batch whose declared order no row agrees with. $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Cannot merge Rows with different schemas'); + $this->expectExceptionMessage('Cannot concat Rows with different schemas'); - $left->merge($right); + $left->concat(new PhpBackend(), $right); } public function test_rows_hop_a_foreign_zone_at_ingest(): void @@ -1109,7 +737,7 @@ public function test_match_to_refuses(Schema $schema, Rows $rows, string $messag $this->expectException(SchemaMismatchException::class); $this->expectExceptionMessage($message); - $rows->matchTo($schema); + $rows->matchTo($schema, new AdaptiveBackend()); } public function test_from_rows_refuses_null_under_not_null_in_row_1(): void @@ -1201,37 +829,148 @@ public function test_project_shares_kept_columns(): void { $rows = array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))); - static::assertSame($rows->column('id'), $rows->project(schema(int_schema('id')))->column('id')); + static::assertSame( + $rows->column('id'), + $rows->project(schema(int_schema('id')), new AdaptiveBackend())->column('id'), + ); } - public function test_concat_of_a_constant_and_a_scalar_column_yields_default_backend_columns(): void + public function test_concat_of_mixed_column_classes_rebuilds_in_the_given_backend(): void { $schema = schema(int_schema('id')); $constant = Rows::fromColumns($schema, ['id' => (new PhpBackend())->constant(int_schema('id'), 7, 2)], 2); - $concatenated = $constant->concat(array_to_rows([['id' => 1]], $schema)); + $concatenated = $constant->concat(new PhpBackend(), array_to_rows([['id' => 1]], $schema, new PhpBackend())); static::assertSame([['id' => 7], ['id' => 7], ['id' => 1]], $concatenated->toArray()); + static::assertInstanceOf(ScalarColumn::class, $concatenated->column('id')); + } + + public function test_adopted_by_a_backend_that_owns_every_column_is_the_same_batch(): void + { + $rows = array_to_rows([['id' => 1]], schema(int_schema('id')), new PhpBackend()); + + static::assertSame($rows, $rows->adoptedBy(new PhpBackend())); + } + + #[RequiresPhpExtension('flow_php')] + public function test_adopted_by_another_backend_copies_every_column_into_it(): void + { + $rows = array_to_rows( + [['id' => 1, 'name' => 'a']], + schema(int_schema('id'), str_schema('name')), + new PhpBackend(), + ); + + $adopted = $rows->adoptedBy(new RustBackend()); + + static::assertSame($rows->toArray(), $adopted->toArray()); + static::assertSame('Flow\ETL\Column\RustColumn', $adopted->column('id')::class); + static::assertSame('Flow\ETL\Column\RustColumn', $adopted->column('name')::class); + } + + #[RequiresPhpExtension('flow_php')] + public function test_concat_of_two_php_parts_builds_in_the_given_backend(): void + { + $schema = schema(int_schema('id')); + $concatenated = array_to_rows([['id' => 1]], $schema, new PhpBackend())->concat( + new RustBackend(), + array_to_rows([['id' => 2]], $schema, new PhpBackend()), + ); + + static::assertSame([1, 2], $concatenated->column('id')->values()); + static::assertSame('Flow\ETL\Column\RustColumn', $concatenated->column('id')::class); + } + + #[RequiresPhpExtension('flow_php')] + public function test_concat_with_no_rows_still_answers_in_the_given_backend(): void + { + $empty = Rows::empty(schema(int_schema('id')), new PhpBackend()); + + static::assertSame('Flow\ETL\Column\RustColumn', $empty->concat(new RustBackend())->column('id')::class); + } + + #[RequiresPhpExtension('flow_php')] + public function test_concat_of_a_php_part_and_a_rust_part_builds_in_the_given_backend(): void + { + $schema = schema(int_schema('id')); + $concatenated = array_to_rows([['id' => 1]], $schema, new PhpBackend())->concat( + new RustBackend(), + array_to_rows([['id' => 2]], $schema, new RustBackend()), + ); + + static::assertSame([1, 2], $concatenated->column('id')->values()); + static::assertSame('Flow\ETL\Column\RustColumn', $concatenated->column('id')::class); + } + + public function test_empty_builds_its_columns_in_the_given_backend(): void + { static::assertInstanceOf( - (new AdaptiveBackend()) - ->builder(int_schema('id')) - ->finish()::class, - $concatenated->column('id'), + ScalarColumn::class, + Rows::empty(schema(int_schema('id')), new PhpBackend())->column('id'), + ); + } + + public function test_match_to_builds_a_new_column_in_the_given_backend(): void + { + $matched = array_to_rows([['id' => 1]], schema(int_schema('id')), new PhpBackend())->matchTo( + schema(int_schema('id'), str_schema('name', nullable: true)), + new PhpBackend(), + ); + + static::assertInstanceOf(ConstantColumn::class, $matched->column('name')); + } + + public function test_match_to_reports_the_first_null_under_not_null(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('(row 2)'); + + array_to_rows([['id' => 1], ['id' => 2], ['id' => null]], schema(int_schema('id', nullable: true)))->matchTo( + schema(int_schema('id')), + new PhpBackend(), + ); + } + + public function test_match_to_restamps_a_provable_change_without_reading_values(): void + { + $spy = new SpyColumn((new PhpBackend())->constant(int_schema('id'), 1, 2)); + $matched = Rows::fromColumns(schema(int_schema('id')), ['id' => $spy], 2)->matchTo( + schema(int_schema('id', nullable: true)), + new PhpBackend(), + ); + + static::assertTrue($matched->schema()->get('id')->isNullable()); + static::assertNotContains('value', $spy->calls->getArrayCopy()); + static::assertNotContains('values', $spy->calls->getArrayCopy()); + } + + public function test_match_to_refuses_an_unprovable_change_at_the_bad_row(): void + { + $this->expectException(SchemaMismatchException::class); + $this->expectExceptionMessage('column "id" (row 1)'); + + array_to_rows([['id' => null], ['id' => 5]], schema(int_schema('id', nullable: true)))->matchTo( + schema(str_schema('id', nullable: true)), + new PhpBackend(), ); } public function test_concat_refuses_a_zero_row_input_with_another_schema(): void { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Cannot merge Rows with different schemas'); + $this->expectExceptionMessage('Cannot concat Rows with different schemas'); - array_to_rows([['id' => 1]], schema(int_schema('id')))->concat(rows(schema(str_schema('id')))); + array_to_rows([['id' => 1]], schema(int_schema('id')))->concat( + new PhpBackend(), + rows(schema(str_schema('id'))), + ); } public function test_concat_of_empty_inputs_is_an_empty_batch(): void { $schema = schema(int_schema('id')); - static::assertSame(0, rows($schema)->concat(rows($schema))->count()); + static::assertSame(0, rows($schema)->concat(new PhpBackend(), rows($schema))->count()); } public function test_with_columns_beside_a_constant_column(): void @@ -1258,7 +997,7 @@ public function test_with_columns_beside_a_constant_column(): void public function test_empty_has_one_empty_column_per_definition(): void { - $rows = Rows::empty(schema(int_schema('id'), str_schema('name', nullable: true))); + $rows = Rows::empty(schema(int_schema('id'), str_schema('name', nullable: true)), new AdaptiveBackend()); static::assertSame(0, $rows->count()); static::assertSame(['id', 'name'], array_keys($rows->columns())); @@ -1268,7 +1007,7 @@ public function test_empty_has_one_empty_column_per_definition(): void public function test_empty_of_an_empty_schema(): void { - static::assertSame([], Rows::empty(schema())->columns()); + static::assertSame([], Rows::empty(schema(), new AdaptiveBackend())->columns()); } public function test_from_columns_refuses_an_untyped_column(): void @@ -1318,14 +1057,18 @@ public function test_with_schema_refuses_another_definition_count(): void array_to_rows([['id' => 1]], schema(int_schema('id')))->withSchema(schema(int_schema('a'), int_schema('b'))); } - public function test_with_schema_refuses_nulls_under_not_null(): void + public function test_with_schema_refuses_a_null_under_not_null_at_its_row(): void { - $this->expectException(ColumnMismatchException::class); - $this->expectExceptionMessage('column "key": could not convert null to integer, column is not nullable'); - - array_to_rows([['id' => null]], schema(int_schema('id', nullable: true)))->withSchema(schema(int_schema( - 'key', - ))); + try { + array_to_rows([ + ['id' => 1], + ['id' => null], + ], schema(int_schema('id', nullable: true)))->withSchema(schema(int_schema('key'))); + static::fail('a null under NOT NULL must be refused'); + } catch (SchemaMismatchException $e) { + static::assertSame(1, $e->rowIndex); + static::assertStringContainsString('column "key"', $e->getMessage()); + } } public function test_with_schema_refuses_another_column_kind(): void @@ -1416,8 +1159,8 @@ public function test_an_empty_batch_sorts_to_itself_and_reduces_to_nothing(): vo { $rows = rows(schema(int_schema('id'))); - static::assertSame($rows, $rows->sortAscending('id')); - static::assertSame($rows, $rows->sortDescending('id')); + static::assertSame($rows, $rows->sortBy(ref('id'))); + static::assertSame($rows, $rows->sortBy(ref('id')->desc())); static::assertSame([], $rows->reduceToArray('id')); } @@ -1428,11 +1171,10 @@ public function test_match_to_rebuilds_a_column_its_type_cannot_restamp(): void $matched = array_to_rows([ ['s' => ['a' => 1]], ['s' => null], - ], schema(structure_schema('s', type_structure(['a' => type_optional(type_integer())]), nullable: true)))->matchTo(schema(structure_schema( - 's', - type_structure(['a' => type_integer()]), - nullable: true, - ))); + ], schema(structure_schema('s', type_structure(['a' => type_optional(type_integer())]), nullable: true)))->matchTo( + schema(structure_schema('s', type_structure(['a' => type_integer()]), nullable: true)), + new AdaptiveBackend(), + ); static::assertSame([['s' => ['a' => 1]], ['s' => null]], $matched->toArray()); static::assertSame('structure{a: integer}', $matched->column('s')->type()->toString()); @@ -1440,7 +1182,8 @@ public function test_match_to_rebuilds_a_column_its_type_cannot_restamp(): void public function test_match_to_adopts_a_not_null_column_an_empty_batch_lacks(): void { - $matched = rows(schema(int_schema('id')))->matchTo(schema(int_schema('id'), str_schema('name'))); + $matched = rows(schema(int_schema('id'))) + ->matchTo(schema(int_schema('id'), str_schema('name')), new AdaptiveBackend()); static::assertSame(0, $matched->count()); static::assertSame(['id', 'name'], $matched->schema()->references()->names()); @@ -1456,6 +1199,65 @@ public function test_match_to_refuses_a_midnight_outside_utc_in_a_date_column(): array_to_rows([['at' => new DateTimeImmutable( '2026-01-01 00:00:00', new DateTimeZone('Europe/Warsaw'), - )]], schema(datetime_schema('at', zone: 'Europe/Warsaw')))->matchTo(schema(date_schema('at'))); + )]], schema(datetime_schema('at', zone: 'Europe/Warsaw')))->matchTo( + schema(date_schema('at')), + new AdaptiveBackend(), + ); + } + + public function test_match_to_reports_a_bad_value_before_a_later_null_of_the_same_column(): void + { + try { + array_to_rows([ + ['n' => [1]], + ['n' => [null]], + ['n' => null], + ], schema(list_schema('n', type_list(type_optional(type_integer())), nullable: true)))->matchTo( + schema(list_schema('n', type_list(type_integer()))), + new PhpBackend(), + ); + static::fail('the bad value must be refused'); + } catch (SchemaMismatchException $e) { + static::assertSame(1, $e->rowIndex); + } + } + + public function test_match_to_reports_the_lowest_bad_row_and_its_column(): void + { + try { + array_to_rows( + [['a' => [1], 'b' => [1]], ['a' => [2], 'b' => [null]], ['a' => [null], 'b' => [3]]], + schema( + list_schema('a', type_list(type_optional(type_integer()))), + list_schema('b', type_list(type_optional(type_integer()))), + ), + )->matchTo( + schema(list_schema('a', type_list(type_integer())), list_schema('b', type_list(type_integer()))), + new PhpBackend(), + ); + static::fail('the bad value must be refused'); + } catch (SchemaMismatchException $e) { + static::assertSame(1, $e->rowIndex); + static::assertStringContainsString('"b"', $e->getMessage()); + } + } + + public function test_select_keeps_the_named_columns_as_they_are_in_schema_order(): void + { + $rows = array_to_rows( + [['id' => 1, 'name' => 'a', 'tag' => 'x']], + schema(int_schema('id'), str_schema('name'), str_schema('tag')), + ); + $selected = $rows->select('tag', 'id'); + + static::assertSame(['id', 'tag'], $selected->schema()->references()->names()); + static::assertSame($rows->column('tag'), $selected->column('tag')); + } + + public function test_select_refuses_a_name_the_batch_lacks(): void + { + $this->expectException(SchemaDefinitionNotFoundException::class); + + array_to_rows([['id' => 1]], schema(int_schema('id')))->select('id', 'missing'); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ExternalSortTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ExternalSortTest.php index 926d175619..6866d3cff1 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ExternalSortTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/ExternalSortTest.php @@ -7,6 +7,7 @@ use Flow\ETL\Bucketing\Bucket; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Dataset\Memory\Unit; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; @@ -116,7 +117,7 @@ public function test_sorts_by_multiple_columns(): void $sorted = rows(schema(int_schema('a'), int_schema('b'))); foreach (ExternalSortMother::spilling(refs('a', 'b'))->sort($input, flow_context(config())) as $batch) { - $sorted = $sorted->concat($batch); + $sorted = $sorted->concat(new AdaptiveBackend(), $batch); } static::assertSame( @@ -231,7 +232,10 @@ public function test_spilled_sort_equals_one_in_memory_sort(int $seed): void mergeFanIn: 2, batchSize: $dataset['mergeBatchSize'], )->sort($input, flow_context(config())) as $batch) { - $sorted = $sorted->concat($batch->matchTo($dataset['schema'])); + $sorted = $sorted->concat( + new AdaptiveBackend(), + $batch->matchTo($dataset['schema'], new AdaptiveBackend()), + ); } // serialized, so NaN and -0.0 compare by what they are diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php index 9a831f572c..6e8d51f712 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/BucketCursorTest.php @@ -6,6 +6,7 @@ use DateTimeImmutable; use DateTimeZone; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Sort\Merge\BucketCursor; use Flow\ETL\Sort\RowOrder; use Flow\ETL\Sort\SortKey; @@ -29,7 +30,7 @@ public function test_iterates_rows_across_batch_boundaries(): void yield array_to_rows([['id' => 3]], schema(int_schema('id'))); }; - $cursor = new BucketCursor($batches(), new RowOrder([ref('id')])); + $cursor = new BucketCursor($batches(), new RowOrder([ref('id')]), new AdaptiveBackend()); $ids = []; @@ -47,7 +48,7 @@ public function test_empty_batch_stream_is_invalid_from_the_start(): void yield from []; }; - static::assertFalse((new BucketCursor($batches(), new RowOrder([ref('id')])))->valid()); + static::assertFalse((new BucketCursor($batches(), new RowOrder([ref('id')]), new AdaptiveBackend()))->valid()); } public function test_skips_empty_batches(): void @@ -59,7 +60,7 @@ public function test_skips_empty_batches(): void yield array_to_rows([['id' => 2]], schema(int_schema('id'))); }; - $cursor = new BucketCursor($batches(), new RowOrder([ref('id')])); + $cursor = new BucketCursor($batches(), new RowOrder([ref('id')]), new AdaptiveBackend()); $ids = []; @@ -79,7 +80,7 @@ public function test_next_batch_is_not_decoded_until_the_current_one_is_exhauste }; $generator = $batches(); - $cursor = new BucketCursor($generator, new RowOrder([ref('id')])); + $cursor = new BucketCursor($generator, new RowOrder([ref('id')]), new AdaptiveBackend()); static::assertSame(0, $generator->key()); @@ -101,7 +102,7 @@ public function test_stream_of_only_empty_batches_is_invalid(): void yield rows(schema()); }; - static::assertFalse((new BucketCursor($batches(), new RowOrder([ref('id')])))->valid()); + static::assertFalse((new BucketCursor($batches(), new RowOrder([ref('id')]), new AdaptiveBackend()))->valid()); } public function test_keys_are_the_sort_keys_of_every_ref_in_order(): void @@ -113,7 +114,7 @@ public function test_keys_are_the_sort_keys_of_every_ref_in_order(): void ); }; - $cursor = new BucketCursor($batches(), new RowOrder([ref('at'), ref('id')])); + $cursor = new BucketCursor($batches(), new RowOrder([ref('at'), ref('id')]), new AdaptiveBackend()); static::assertSame( [[1_000_000], [2]], @@ -128,6 +129,9 @@ public function test_schema_of_an_empty_stream_is_empty(): void yield from []; }; - static::assertEquals(schema(), (new BucketCursor($batches(), new RowOrder([ref('id')])))->schema()); + static::assertEquals( + schema(), + (new BucketCursor($batches(), new RowOrder([ref('id')]), new AdaptiveBackend()))->schema(), + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php index 9d20a27514..ade2a81326 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Sort/Merge/KWayMergeTest.php @@ -7,6 +7,7 @@ use Flow\ETL\Bucketing\BucketRun; use Flow\ETL\Bucketing\Buckets; use Flow\ETL\Bucketing\Storage\MemoryBuckets; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Constraint\SortedByConstraint; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Sort\Merge\KWayMerge; @@ -55,8 +56,15 @@ public function test_merging_sorted_runs_equals_one_in_memory_sort(int $seed): v $merged = rows($dataset['schema']); - foreach ((new KWayMerge(refs(...$dataset['references']), $dataset['mergeBatchSize']))->merge($runs) as $batch) { - $merged = $merged->concat($batch->matchTo($dataset['schema'])); + foreach ((new KWayMerge( + refs(...$dataset['references']), + new AdaptiveBackend(), + $dataset['mergeBatchSize'], + ))->merge($runs) as $batch) { + $merged = $merged->concat( + new AdaptiveBackend(), + $batch->matchTo($dataset['schema'], new AdaptiveBackend()), + ); } // serialized, so NaN and -0.0 compare by what they are @@ -90,7 +98,7 @@ public function test_merges_multiple_sorted_runs_ascending(): void ['id' => 9], ], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend()); static::assertSame( [1, 2, 3, 4, 5, 6, 7, 8, 9], @@ -117,7 +125,7 @@ public function test_merge_reads_each_run_through_its_own_storage(): void static::assertSame([], BucketsStorageContext::rows($spill->storage()->get('sort-merge-0'))); static::assertSame([], BucketsStorageContext::rows($merged->storage()->get('sort-run-0'))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend()); static::assertSame( [1, 2, 3, 4], @@ -145,7 +153,7 @@ public function test_merges_multiple_sorted_runs_descending(): void ['id' => 2], ], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->desc())); + $merge = new KWayMerge(refs(ref('id')->desc()), new AdaptiveBackend()); static::assertSame( [8, 7, 5, 4, 2, 1], @@ -169,7 +177,7 @@ public function test_merges_runs_of_uneven_length(): void ], schema(int_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 4]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend()); static::assertSame( [1, 2, 3, 4], @@ -189,7 +197,7 @@ public function test_merges_non_numeric_values(): void $buckets->storage()->append('a', array_to_rows([['id' => 'a'], ['id' => 'c']], schema(str_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 'b'], ['id' => 'd']], schema(str_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend()); static::assertSame( ['a', 'b', 'c', 'd'], @@ -212,7 +220,7 @@ public function test_runs_under_different_schemas_are_conformed_to_the_first(): )); $buckets->storage()->append('b', array_to_rows([['id' => 2]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend()); static::assertSame( [['id' => 1, 'name' => 'a'], ['id' => 2, 'name' => null]], @@ -228,7 +236,7 @@ public function test_single_run_passthrough(): void $buckets = new Buckets(new MemoryBuckets()); $buckets->storage()->append('a', array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend()); static::assertSame( [1, 2], @@ -238,7 +246,7 @@ public function test_single_run_passthrough(): void public function test_empty_bucket_set_yields_nothing(): void { - $merge = new KWayMerge(refs(ref('id')->asc())); + $merge = new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend()); static::assertSame([], BucketsStorageContext::rows($merge->merge([]))); } @@ -253,7 +261,7 @@ public function test_merged_rows_are_yielded_in_batches_of_batch_size(): void ], schema(int_schema('id')))); $buckets->storage()->append('b', array_to_rows([['id' => 2], ['id' => 4]], schema(int_schema('id')))); - $merge = new KWayMerge(refs(ref('id')->asc()), batchSize: 2); + $merge = new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend(), batchSize: 2); $sizes = []; @@ -270,7 +278,7 @@ public function test_throws_when_batch_size_below_one(): void $this->expectExceptionMessage('Batch size must be greater than 0, given: 0'); // @mago-ignore analysis:invalid-argument - new KWayMerge(refs(ref('id')->asc()), batchSize: 0); + new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend(), batchSize: 0); } public function test_interleaves_runs_across_batch_boundaries_like_one_sort(): void @@ -294,7 +302,7 @@ public function test_interleaves_runs_across_batch_boundaries_like_one_sort(): v $merged = []; - foreach ((new KWayMerge(refs(ref('id')->asc()), batchSize: 4))->merge([ + foreach ((new KWayMerge(refs(ref('id')->asc()), new AdaptiveBackend(), batchSize: 4))->merge([ new BucketRun('a', $buckets), new BucketRun('b', $buckets), new BucketRun('c', $buckets), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php index 93e368d37d..ed0d31e347 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DerivedColumnsTest.php @@ -4,8 +4,8 @@ namespace Flow\ETL\Tests\Unit\Transformer; -use Flow\ETL\Column\Php\ValueColumn; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Tests\Double\SpyBackend; use Flow\ETL\Tests\FlowTestCase; @@ -109,6 +109,7 @@ public function test_rows_adds_the_derived_column_under_the_output_schema(): voi $output, 'note', (new PhpBackend())->constant(str_schema('note', nullable: true), 'x', 1), + new PhpBackend(), ) ->toArray(), ); @@ -127,6 +128,7 @@ public function test_rows_matches_a_batch_declared_under_another_schema(): void $declared->add(str_schema('extra', nullable: true)), 'note', (new PhpBackend())->constant(str_schema('note', nullable: true), 'x', 1), + new PhpBackend(), ) ->toArray(), ); diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php index fb702dfef7..c9e80c39e7 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/DuplicateRowTransformerTest.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Tests\Unit\Transformer; use DateTimeImmutable; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; use Flow\ETL\Tests\FlowTestCase; @@ -310,7 +311,7 @@ public function test_an_unbound_transform_refuses_an_expand_in_an_entry(): void ); (new DuplicateRowTransformer(lit(true), with_entry('t', ref('tags')->expand())))->transform( - ListColumnsMother::rows()->matchTo(ListColumnsMother::schema()), + ListColumnsMother::rows()->matchTo(ListColumnsMother::schema(), new AdaptiveBackend()), flow_context(config()), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php index 2d0b327bac..ed2090f73f 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/ScalarFunctionTransformerTest.php @@ -7,6 +7,8 @@ use DOMDocument; use DOMNodeList; use DOMXPath; +use Flow\ETL\Column\AdaptiveBackend; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\InvalidLogicException; use Flow\ETL\Exception\SchemaDefinitionNotFoundException; @@ -234,11 +236,14 @@ public function test_the_produced_definition_does_not_depend_on_batch_size(): vo ], schema(int_schema('v'))), flow_context(config())); $transformer = new ScalarFunctionTransformer('out', ref('v')->plus(lit(1))); - $single = $transformer - ->transform(array_to_rows([['v' => 1]], schema(int_schema('v'))), flow_context(config())) - ->merge($transformer->transform(array_to_rows([[ + $single = $transformer->transform(array_to_rows([[ + 'v' => 1, + ]], schema(int_schema('v'))), flow_context(config()))->concat( + new PhpBackend(), + $transformer->transform(array_to_rows([[ 'v' => 2, - ]], schema(int_schema('v'))), flow_context(config()))); + ]], schema(int_schema('v'))), flow_context(config())), + ); static::assertEquals($wholeBatch->schema()->get('out'), $single->schema()->get('out')); static::assertEquals($wholeBatch->toArray(), $single->toArray()); @@ -421,7 +426,7 @@ public function test_an_unbound_expand_inside_an_expand_is_refused(): void ); (new ScalarFunctionTransformer('v', ref('lists')->expand()->expand()))->transform( - ListColumnsMother::rows()->matchTo(ListColumnsMother::schema()), + ListColumnsMother::rows()->matchTo(ListColumnsMother::schema(), new AdaptiveBackend()), flow_context(config()), ); } @@ -446,7 +451,7 @@ public function test_an_expand_explodes_every_row_of_the_batch_in_order(): void [['id' => 1, 'value' => 1], ['id' => 1, 'value' => 2], ['id' => 3, 'value' => 3]], (new ScalarFunctionTransformer('value', ref('list')->expand())) ->transform($rows, flow_context()) - ->project(schema(int_schema('id'), int_schema('value'))) + ->project(schema(int_schema('id'), int_schema('value')), new AdaptiveBackend()) ->toArray(), ); } @@ -462,7 +467,10 @@ public function test_an_unpack_fills_one_column_per_declared_element_for_every_r [['s.a' => 1, 's.b' => 'x'], ['s.a' => 2, 's.b' => null]], (new ScalarFunctionTransformer('s', ref('s')->unpack(schema(int_schema('a'), str_schema('b'))))) ->transform($rows, flow_context()) - ->project(schema(int_schema('s.a', nullable: true), str_schema('s.b', nullable: true))) + ->project( + schema(int_schema('s.a', nullable: true), str_schema('s.b', nullable: true)), + new AdaptiveBackend(), + ) ->toArray(), ); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php index 8aa15cf0e8..f368647f47 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializeTransformerTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Transformer; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Rows; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\SerializeTransformer; @@ -60,7 +61,10 @@ public function test_serializing_empty_row_under_one_entry(): void static::assertEquals( [ [ - 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows), + 'serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $rows, + ), ], ], $transformedRows->toArray(), @@ -91,14 +95,20 @@ public function test_serializing_row_under_one_entry(): void 'name' => 'John', 'active' => true, 'tags' => ['tag1', 'tag2'], - 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows->slice(0, 1)), + 'serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $rows->slice(0, 1), + ), ], [ 'id' => 2, 'name' => 'Jane', 'active' => false, 'tags' => ['tag3', 'tag4'], - 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows->slice(1, 1)), + 'serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $rows->slice(1, 1), + ), ], ], $transformedRows->toArray(), @@ -125,10 +135,16 @@ public function test_serializing_row_under_standalone_entry(): void static::assertEquals( [ [ - 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows->slice(0, 1)), + 'serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $rows->slice(0, 1), + ), ], [ - 'serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $rows->slice(1, 1)), + 'serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $rows->slice(1, 1), + ), ], ], $transformedRows->toArray(), diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php index 19de37e805..b556832870 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/SerializedPayloadDecoderTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Transformer; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\SerializedPayloadDecoder; use Flow\Floe\FloeSerializer; @@ -20,7 +21,7 @@ final class SerializedPayloadDecoderTest extends FlowTestCase { public function test_a_multi_row_payload_gives_up(): void { - $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([ + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), array_to_rows([ ['id' => 1], ['id' => 2], ], schema(int_schema('id')))); @@ -65,7 +66,7 @@ public function test_a_row_without_the_source_column_gives_up(): void public function test_it_reads_the_declared_columns_out_of_the_payload(): void { - $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), array_to_rows([[ 'id' => 7, ]], schema(int_schema('id')))); @@ -82,6 +83,10 @@ public function test_it_reads_the_declared_columns_out_of_the_payload(): void public static function decoder(): SerializedPayloadDecoder { - return SerializedPayloadDecoder::of(ref('serialized'), new Base64Serializer(new FloeSerializer()), ['id']); + return SerializedPayloadDecoder::of( + ref('serialized'), + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + ['id'], + ); } } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php index 53fde0bee6..d85a996fb5 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Transformer/UnserializeTransformerTest.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Tests\Unit\Transformer; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Exception\SchemaMismatchException; use Flow\ETL\Tests\FlowTestCase; use Flow\ETL\Transformer\UnserializeTransformer; @@ -25,7 +26,7 @@ final class UnserializeTransformerTest extends FlowTestCase { public function test_a_payload_written_with_another_type_is_refused(): void { - $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), array_to_rows([[ 'id' => '12', ]], schema(str_schema('id')))); @@ -91,8 +92,14 @@ public function test_unserializing_row_from_entry(): void ], $rowSchema); $rows = array_to_rows([ - ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $source->slice(0, 1))], - ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $source->slice(1, 1))], + ['serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $source->slice(0, 1), + )], + ['serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $source->slice(1, 1), + )], ], schema(str_schema('serialized'))); $transformer = new UnserializeTransformer('serialized', $rowSchema); @@ -103,7 +110,7 @@ public function test_unserializing_row_from_entry(): void [ [ 'serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), $source->slice(0, 1), ), 'id' => 1, @@ -113,7 +120,7 @@ public function test_unserializing_row_from_entry(): void ], [ 'serialized' => serialize_to_string( - new Base64Serializer(new FloeSerializer()), + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), $source->slice(1, 1), ), 'id' => 2, @@ -161,7 +168,7 @@ public function test_unserializing_non_string_value_emits_the_declared_shape(): public function test_unserializing_multi_row_payload_emits_the_declared_shape(): void { - $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([ + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), array_to_rows([ ['id' => 1], ['id' => 2], ], schema(int_schema('id')))); @@ -177,7 +184,7 @@ public function test_unserializing_multi_row_payload_emits_the_declared_shape(): public function test_the_declared_columns_land_under_the_merge_prefix(): void { - $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), array_to_rows([[ 'id' => 7, ]], schema(int_schema('id')))); @@ -207,8 +214,14 @@ public function test_unserializing_without_merge(): void ], $rowSchema); $rows = array_to_rows([ - ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $source->slice(0, 1))], - ['serialized' => serialize_to_string(new Base64Serializer(new FloeSerializer()), $source->slice(1, 1))], + ['serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $source->slice(0, 1), + )], + ['serialized' => serialize_to_string( + new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), + $source->slice(1, 1), + )], ], schema(str_schema('serialized'))); $transformer = new UnserializeTransformer('serialized', $rowSchema, false); @@ -236,7 +249,7 @@ public function test_unserializing_without_merge(): void public function test_a_declared_column_replaces_an_input_column_of_the_same_name(): void { - $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), array_to_rows([[ 'id' => 7, ]], schema(int_schema('id')))); @@ -256,7 +269,7 @@ public function test_a_declared_column_replaces_an_input_column_of_the_same_name public function test_a_declared_column_the_payload_does_not_carry_is_null(): void { - $payload = serialize_to_string(new Base64Serializer(new FloeSerializer()), array_to_rows([[ + $payload = serialize_to_string(new Base64Serializer(new FloeSerializer(new AdaptiveBackend())), array_to_rows([[ 'id' => 7, ]], schema(int_schema('id')))); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php index 62f6da714b..15612414c2 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeFilesContext.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Context; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; @@ -23,12 +24,12 @@ final class FloeFilesContext { public static function phpWriter(Filesystem $filesystem, Schema $schema, Codec $codec = new NoopCodec()): FloeWriter { - return new FloeWriter($filesystem, $schema, new Options(codec: $codec)); + return new FloeWriter($filesystem, $schema, new AdaptiveBackend(), new Options(codec: $codec)); } public static function phpReader(Filesystem $filesystem, Codec $codec = new NoopCodec()): FloeReader { - return new FloeReader($filesystem, $codec); + return new FloeReader($filesystem, new AdaptiveBackend(), $codec); } /** diff --git a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php index fd3a732f11..bd73effb1d 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Context/FloeStreamReaderContext.php @@ -4,6 +4,8 @@ namespace Flow\Floe\Tests\Context; +use Flow\ETL\Column\AdaptiveBackend; +use Flow\ETL\Column\PhpBackend; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Schema\Metadata; @@ -73,13 +75,13 @@ public static function roundTrip(Rows $rows): Rows $filesystem = memory_filesystem(); $path = path('memory://round-trip.floe'); - $writer = new FloeWriter($filesystem, $rows->schema()); + $writer = new FloeWriter($filesystem, $rows->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($rows); $writer->close(); $batches = iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), ); @@ -106,11 +108,14 @@ public static function frameTypes(Filesystem $filesystem, Path $path): array */ public static function reconstruct(Filesystem $filesystem, Path $path): Rows { - $file = (new FloeReader($filesystem))->read($path); + $file = (new FloeReader($filesystem, new AdaptiveBackend()))->read($path); $rows = rows($file->footer()->schema()); foreach ($file->rows() as $batch) { - $rows = $rows->concat($batch->matchTo($file->footer()->schema())); + $rows = $rows->concat( + new AdaptiveBackend(), + $batch->matchTo($file->footer()->schema(), new AdaptiveBackend()), + ); } return $rows; @@ -123,10 +128,10 @@ public static function readAll(Filesystem $filesystem, Path $path): Rows { $merged = null; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows() as $batch) { - $merged = $merged === null ? $batch : $merged->merge($batch); + $merged = $merged === null ? $batch : $merged->concat(new PhpBackend(), $batch); } return $merged ?? rows(schema()); @@ -142,7 +147,7 @@ public static function write( array $metadata = [], Codec $codec = new NoopCodec(), ): void { - $writer = new FloeWriter($filesystem, $rows->schema(), new Options(codec: $codec)); + $writer = new FloeWriter($filesystem, $rows->schema(), new AdaptiveBackend(), new Options(codec: $codec)); $writer->create($path, Metadata::fromArray($metadata)); $writer->write($rows); $writer->close(); @@ -187,7 +192,7 @@ public static function writeBatches( array $batches, Options $options = new Options(), ): string { - $writer = new FloeWriter($filesystem, $schema, $options); + $writer = new FloeWriter($filesystem, $schema, new AdaptiveBackend(), $options); $writer->create($path); foreach ($batches as $batch) { @@ -206,7 +211,7 @@ public static function writeBatches( */ public static function writeWithoutFooter(Filesystem $filesystem, Path $path, Rows $rows): void { - $writer = new FloeWriter($filesystem, $rows->schema()); + $writer = new FloeWriter($filesystem, $rows->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($rows); $writer->close(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php index e5b7c4c712..382123a4ac 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeExtractorTest.php @@ -7,21 +7,31 @@ use DateTimeImmutable; use DateTimeZone; use Flow\ETL\Cardinality; +use Flow\ETL\Rows; +use Flow\ETL\Tests\Context\ExtractedRows; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowIntegrationTestCase; +use Flow\Floe\Tests\Context\FloeFilesContext; use Flow\Floe\Tests\Context\FloeStreamReaderContext; +use function array_map; +use function array_merge; use function Flow\ETL\DSL\array_to_rows; use function Flow\ETL\DSL\datetime_schema; use function Flow\ETL\DSL\df; +use function Flow\ETL\DSL\flow_context; +use function Flow\ETL\DSL\from_array; use function Flow\ETL\DSL\int_schema; use function Flow\ETL\DSL\ref; use function Flow\ETL\DSL\schema; use function Flow\ETL\DSL\to_timezone; +use function Flow\Filesystem\DSL\memory_filesystem; +use function Flow\Filesystem\DSL\path; use function Flow\Floe\DSL\from_floe; use function Flow\Floe\DSL\to_floe; use function Flow\Types\DSL\type_datetime; use function Flow\Types\DSL\type_string; +use function iterator_to_array; final class FloeExtractorTest extends FlowIntegrationTestCase { @@ -221,4 +231,42 @@ public function test_xml_nodes_written_before_utf8_node_documents_read_back_and_ ->toArray(), ); } + + public function test_an_offset_spanning_two_files_and_a_limit_inside_the_third_read_the_same_twice(): void + { + $filesystem = memory_filesystem(); + + foreach (['a' => [1, 2, 3], 'b' => [4, 5, 6], 'c' => [7, 8, 9]] as $name => $ids) { + df() + ->read(from_array(array_map(static fn(int $id): array => ['id' => $id], $ids))) + ->write(to_floe('memory://window/' . $name . '.floe', filesystem: $filesystem)) + ->run(); + } + + $extractor = from_floe('memory://window/*.floe', filesystem: $filesystem)->withOffset(4); + $read = static fn(): array => array_merge(...array_map( + static fn(Rows $rows): array => $rows->column('id')->values(), + iterator_to_array($extractor->extract(flow_context(), limit: 4), false), + )); + + static::assertSame([5, 6, 7, 8], $read()); + static::assertSame([5, 6, 7, 8], $read()); + } + + public function test_one_extractor_read_twice_interleaved_gives_each_read_every_row_and_closes_every_stream(): void + { + $filesystem = new CountingFilesystem(memory_filesystem()); + FloeFilesContext::writeFiles($filesystem, [ + 'memory://in/a.floe' => array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), + 'memory://in/b.floe' => array_to_rows([['id' => 3]], schema(int_schema('id'))), + ]); + [$first, $second] = ExtractedRows::interleaved(from_floe( + path('memory://in/*.floe'), + filesystem: $filesystem, + )->withBatchSize(1)); + + static::assertSame([['id' => 1], ['id' => 2], ['id' => 3]], $first->toArray()); + static::assertSame($first->toArray(), $second->toArray()); + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeMergeDSLTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeMergeDSLTest.php index 464013871c..5b2cd18a33 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeMergeDSLTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeMergeDSLTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Integration; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\Tests\Context\FloeStreamReaderContext; @@ -23,7 +24,7 @@ public function test_merge_floe_compact_over_path_objects(): void FloeStreamReaderContext::write($this->fs(), $a, array_to_rows([['id' => 1]], schema(int_schema('id')))); FloeStreamReaderContext::write($this->fs(), $b, array_to_rows([['id' => 2]], schema(int_schema('id')))); - merge_floe([$a, $b], $out, compact: true); + merge_floe([$a, $b], $out, new AdaptiveBackend(), compact: true); static::assertEquals( array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), @@ -40,7 +41,7 @@ public function test_merge_floe_splices_local_files_from_string_paths(): void FloeStreamReaderContext::write($this->fs(), $a, array_to_rows([['id' => 1]], schema(int_schema('id')))); FloeStreamReaderContext::write($this->fs(), $b, array_to_rows([['id' => 2]], schema(int_schema('id')))); - merge_floe([$a->path(), $b->path()], $out->path()); + merge_floe([$a->path(), $b->path()], $out->path(), new AdaptiveBackend()); static::assertEquals( array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))), diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStatisticsTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStatisticsTest.php index 917d4b250e..72b503dd5b 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStatisticsTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStatisticsTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Integration; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\FloeWriter; use Flow\Floe\Tests\Context\FloeStreamReaderContext; @@ -28,8 +29,8 @@ public function test_a_compacted_merge_reports_the_same_rows_as_a_spliced_one(): ], schema(int_schema('id')))); FloeStreamReaderContext::write($this->fs(), $b, array_to_rows([['id' => 3]], schema(int_schema('id')))); - merge_floe([$a, $b], $spliced); - merge_floe([$a, $b], $compacted, compact: true); + merge_floe([$a, $b], $spliced, new AdaptiveBackend()); + merge_floe([$a, $b], $compacted, new AdaptiveBackend(), compact: true); static::assertSame(3, FloeStreamReaderContext::footer($this->fs(), $spliced)->statistics->rows); static::assertSame(3, FloeStreamReaderContext::footer($this->fs(), $compacted)->statistics->rows); @@ -51,7 +52,7 @@ public function test_a_merged_file_reports_the_output_byte_size_not_the_inputs() 'name' => 'second', ]], schema(str_schema('name')))); - merge_floe([$a, $b], $out); + merge_floe([$a, $b], $out, new AdaptiveBackend()); $statistics = FloeStreamReaderContext::footer($this->fs(), $out)->statistics; @@ -73,7 +74,7 @@ public function test_a_multi_section_file_sums_its_sections(): void FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); foreach ([[2, 3], [4, 5, 6]] as $ids) { - $writer = new FloeWriter($this->fs(), schema(int_schema('id'))); + $writer = new FloeWriter($this->fs(), schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); foreach ($ids as $id) { @@ -117,7 +118,7 @@ public function test_an_appended_file_reports_the_combined_totals(): void FloeStreamReaderContext::write($this->fs(), $path, array_to_rows([['id' => 1]], schema(int_schema('id')))); $before = FloeStreamReaderContext::footer($this->fs(), $path)->statistics->byteSize; - $writer = new FloeWriter($this->fs(), schema(int_schema('id'))); + $writer = new FloeWriter($this->fs(), schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); $writer->write(array_to_rows([['id' => 2], ['id' => 3]], schema(int_schema('id')))); $writer->close(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php index 4dac191043..3f3813c64d 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeStreamReaderTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Integration; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Tests\FlowIntegrationTestCase; use Flow\Floe\FloeMerger; use Flow\Floe\FloeReader; @@ -28,7 +29,7 @@ public function test_merged_multi_schema_file_reads_seamlessly(): void $fileThree = $this->cacheDir->suffix('evolving-3.floe'); $rowsOne = array_to_rows([['id' => 1]], schema(int_schema('id'))); - $writer = new FloeWriter($this->fs(), $rowsOne->schema()); + $writer = new FloeWriter($this->fs(), $rowsOne->schema(), new AdaptiveBackend()); $writer->create($fileOne); $writer->write($rowsOne); $writer->close(); @@ -37,7 +38,7 @@ public function test_merged_multi_schema_file_reads_seamlessly(): void [['id' => 2, 'email' => null]], schema(int_schema('id'), str_schema('email', nullable: true)), ); - $writer = new FloeWriter($this->fs(), $rowsTwo->schema()); + $writer = new FloeWriter($this->fs(), $rowsTwo->schema(), new AdaptiveBackend()); $writer->create($fileTwo); $writer->write($rowsTwo); $writer->close(); @@ -46,14 +47,14 @@ public function test_merged_multi_schema_file_reads_seamlessly(): void [['id' => 3, 'email' => 'third@flow.php']], schema(int_schema('id'), str_schema('email')), ); - $writer = new FloeWriter($this->fs(), $rowsThree->schema()); + $writer = new FloeWriter($this->fs(), $rowsThree->schema(), new AdaptiveBackend()); $writer->create($fileThree); $writer->write($rowsThree); $writer->close(); - (new FloeMerger($this->fs()))->merge([$fileOne, $fileTwo, $fileThree], $path); + (new FloeMerger($this->fs(), new AdaptiveBackend()))->merge([$fileOne, $fileTwo, $fileThree], $path); - $reader = (new FloeReader($this->fs()))->read($path); + $reader = (new FloeReader($this->fs(), new AdaptiveBackend()))->read($path); static::assertSame(3, $reader->totalRows()); @@ -77,7 +78,7 @@ public function test_file_larger_than_compaction_threshold_round_trips(): void [['id' => 0, 'payload' => str_pad('row_0', 300, 'x')]], schema(int_schema('id'), str_schema('payload')), )->schema(); - $writer = new FloeWriter($this->fs(), $schema); + $writer = new FloeWriter($this->fs(), $schema, new AdaptiveBackend()); $writer->create($path); $written = 0; @@ -97,7 +98,7 @@ public function test_file_larger_than_compaction_threshold_round_trips(): void $read = 0; - foreach ((new FloeReader($this->fs(), chunkSize: 4096)) + foreach ((new FloeReader($this->fs(), new AdaptiveBackend(), chunkSize: 4096)) ->read($path) ->rows(500) as $batch) { foreach ($batch->toArray() as $row) { @@ -114,13 +115,13 @@ public function test_round_trip_of_all_entry_types_through_local_filesystem(): v $rows = RowsMother::withAllEntryTypes(); $path = $this->cacheDir->suffix('all-types.floe'); - $writer = new FloeWriter($this->fs(), $rows->schema()); + $writer = new FloeWriter($this->fs(), $rows->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($rows); $writer->close(); $batches = iterator_to_array( - (new FloeReader($this->fs())) + (new FloeReader($this->fs(), new AdaptiveBackend())) ->read($path) ->rows(), ); @@ -134,14 +135,14 @@ public function test_round_trip_of_heterogeneous_rows_through_local_filesystem() $rows = RowsMother::heterogeneous(); $path = $this->cacheDir->suffix('heterogeneous.floe'); - $writer = new FloeWriter($this->fs(), $rows->schema()); + $writer = new FloeWriter($this->fs(), $rows->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($rows); $writer->close(); $read = 0; - foreach ((new FloeReader($this->fs())) + foreach ((new FloeReader($this->fs(), new AdaptiveBackend())) ->read($path) ->rows() as $batch) { $read += $batch->count(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php index 85c5b55d25..9763c82b8c 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Integration/FloeWriteContractTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Integration; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Rows; use Flow\ETL\Schema; use Flow\ETL\Tests\FlowIntegrationTestCase; @@ -59,7 +60,7 @@ public function test_the_writer_rejects_the_value_with_the_message( string $expectedMessage, ): void { $path = $this->cacheDir->suffix('contract-' . md5($expectedMessage) . '.floe'); - $writer = new FloeWriter($this->fs(), $schema, new Options()); + $writer = new FloeWriter($this->fs(), $schema, new AdaptiveBackend(), new Options()); $writer->create($path); try { @@ -81,7 +82,7 @@ public function test_the_writer_rejects_the_value_with_the_message( public function test_a_rejected_batch_leaves_previously_written_rows_readable(): void { $path = $this->cacheDir->suffix('contract-survivor.floe'); - $writer = new FloeWriter($this->fs(), schema(int_schema('id')), new Options()); + $writer = new FloeWriter($this->fs(), schema(int_schema('id')), new AdaptiveBackend(), new Options()); $writer->create($path); $writer->write(array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id')))); @@ -107,6 +108,7 @@ public function test_a_batch_omitting_a_nullable_column_still_writes(): void $writer = new FloeWriter( $this->fs(), schema(int_schema('id'), str_schema('name', nullable: true)), + new AdaptiveBackend(), new Options(), ); $writer->create($path); @@ -130,7 +132,12 @@ public function test_a_batch_omitting_a_nullable_column_still_writes(): void public function test_a_batch_omitting_a_not_null_column_is_refused(): void { $path = $this->cacheDir->suffix('contract-absent-not-null.floe'); - $writer = new FloeWriter($this->fs(), schema(int_schema('id'), str_schema('name')), new Options()); + $writer = new FloeWriter( + $this->fs(), + schema(int_schema('id'), str_schema('name')), + new AdaptiveBackend(), + new Options(), + ); $writer->create($path); $writer->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileBatchesTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileBatchesTest.php new file mode 100644 index 0000000000..4fa80011ab --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileBatchesTest.php @@ -0,0 +1,138 @@ + array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id')))]); + $file = (new FloeFileBatches( + $filesystem, + new NoopCodec(), + 65536, + FileColumnsContext::discovering(names: []), + null, + ))->batches( + new SourceFile(path('memory://a.floe')), + schema(int_schema('id')), + 10, + new PhpBackend(), + new ReadWindow(3), + ); + + static::assertSame([], iterator_to_array($file, false)); + static::assertSame(3, $file->getReturn()); + } + + public function test_an_offset_inside_the_file_starts_the_read_there_and_is_consumed(): void + { + $filesystem = memory_filesystem(); + FloeFilesContext::writeFiles($filesystem, ['memory://a.floe' => array_to_rows([ + ['id' => 1], + ['id' => 2], + ['id' => 3], + ], schema(int_schema('id')))]); + $file = (new FloeFileBatches( + $filesystem, + new NoopCodec(), + 65536, + FileColumnsContext::discovering(names: []), + null, + ))->batches( + new SourceFile(path('memory://a.floe')), + schema(int_schema('id')), + 10, + new PhpBackend(), + new ReadWindow(1), + ); + + static::assertSame( + [[['id' => 2], ['id' => 3]]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + static::assertSame(1, $file->getReturn()); + } + + public function test_a_file_narrower_than_the_body_is_padded_with_nulls(): void + { + $filesystem = memory_filesystem(); + FloeFilesContext::writeFiles($filesystem, ['memory://a.floe' => array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id')))]); + $file = (new FloeFileBatches( + $filesystem, + new NoopCodec(), + 65536, + FileColumnsContext::discovering(names: []), + null, + ))->batches( + new SourceFile(path('memory://a.floe')), + schema(int_schema('id'), str_schema('name', nullable: true)), + 10, + new PhpBackend(), + new ReadWindow(), + ); + + static::assertSame( + [[['id' => 1, 'name' => null]]], + array_map(static fn(Rows $rows): array => $rows->toArray(), iterator_to_array($file, false)), + ); + } + + public function test_a_file_that_diverges_from_the_derived_schema_is_refused_and_closed(): void + { + $filesystem = new CountingFilesystem(memory_filesystem()); + FloeFilesContext::writeFiles($filesystem, ['memory://b.floe' => array_to_rows([[ + 'name' => 'x', + ]], schema(str_schema('name')))]); + + try { + iterator_to_array((new FloeFileBatches( + $filesystem, + new NoopCodec(), + 65536, + FileColumnsContext::discovering(names: []), + new DerivedSchema(schema(int_schema('id')), 'memory://a.floe'), + ))->batches( + new SourceFile(path('memory://b.floe')), + schema(int_schema('id')), + 10, + new PhpBackend(), + new ReadWindow(), + )); + static::fail('a diverging file must be refused'); + } catch (InferredSchemaException) { + static::assertSame($filesystem->readFromCalls, $filesystem->closedStreams()); + } + } +} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileSinkTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileSinkTest.php new file mode 100644 index 0000000000..e845923a3c --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileSinkTest.php @@ -0,0 +1,53 @@ +writeTo(path('memory://a.floe')); + + (new FloeFileSinks($filesystem, null, null, new Options())) + ->open($stream, new PhpBackend()) + ->close(); + $stream->close(); + + static::assertSame('', $filesystem->readFrom(path('memory://a.floe'))->content()); + } + + public function test_the_first_write_opens_the_writer_and_every_write_lands_in_the_file(): void + { + $filesystem = memory_filesystem(); + $stream = $filesystem->writeTo(path('memory://a.floe')); + $sink = (new FloeFileSinks($filesystem, null, null, new Options()))->open($stream, new PhpBackend()); + + $sink->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); + $sink->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); + $sink->close(); + $stream->close(); + + $rows = []; + + foreach (FloeFilesContext::phpReader($filesystem)->read(path('memory://a.floe'))->rows() as $batch) { + $rows = [...$rows, ...$batch->toArray()]; + } + + static::assertSame([['id' => 1], ['id' => 2]], $rows); + } +} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileSinksTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileSinksTest.php new file mode 100644 index 0000000000..2bdcdb0d20 --- /dev/null +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeFileSinksTest.php @@ -0,0 +1,58 @@ +open($filesystem->writeTo(path('memory://a.floe')), new PhpBackend()); + $second = $sinks->open($filesystem->writeTo(path('memory://b.floe')), new PhpBackend()); + + $first->write(array_to_rows([['id' => 1, 'name' => 'a']], $schema)); + $second->write(array_to_rows([['id' => 2, 'name' => null]], $schema)); + $first->close(); + $second->close(); + + static::assertEquals( + $schema, + FloeFilesContext::phpReader($filesystem)->read(path('memory://b.floe'))->schema(), + ); + } + + public function test_a_declared_schema_is_the_written_one(): void + { + $filesystem = memory_filesystem(); + $declared = schema(int_schema('id', nullable: true)); + $sink = (new FloeFileSinks($filesystem, $declared, null, new Options()))->open( + $filesystem->writeTo(path('memory://a.floe')), + new PhpBackend(), + ); + + $sink->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); + $sink->close(); + + static::assertEquals( + $declared, + FloeFilesContext::phpReader($filesystem)->read(path('memory://a.floe'))->schema(), + ); + } +} diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php index 38ef8670fd..422d42db74 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeLoaderTest.php @@ -5,7 +5,9 @@ namespace Flow\Floe\Tests\Unit; use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\Filesystem\SaveMode; use Flow\Floe\Exception\IncompatibleSchemaException; +use Flow\Floe\Tests\Context\FloeFilesContext; use PHPUnit\Framework\TestCase; use function Flow\ETL\DSL\array_to_rows; @@ -21,6 +23,7 @@ use function Flow\Filesystem\DSL\path; use function Flow\Floe\DSL\from_floe; use function Flow\Floe\DSL\to_floe; +use function implode; use function sort; final class FloeLoaderTest extends TestCase @@ -46,6 +49,31 @@ public function test_closure_writes_a_readable_non_torn_file(): void static::assertSame([1, 2], $ids); } + public function test_a_second_run_writes_under_its_own_schema(): void + { + $context = flow_context(config()); + $memory = memory_filesystem(); + $loader = to_floe(path('memory://runs/data.floe'), filesystem: $memory)->saveMode(SaveMode::Append); + + $loader->load(array_to_rows([['id' => 1]], schema(int_schema('id'))), $context); + $loader->closure($context); + $loader->load(array_to_rows([['name' => 'a']], schema(str_schema('name'))), $context); + $loader->closure($context); + + $schemas = []; + + foreach ($memory->list(path('memory://runs/*.floe')) as $file) { + $schemas[] = implode( + ',', + FloeFilesContext::phpReader($memory)->read($file->path)->schema()->references()->names(), + ); + } + + sort($schemas); + + static::assertSame(['id', 'name'], $schemas); + } + public function test_destination_returns_path(): void { $memory = memory_filesystem(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php index 4f74a0598d..818f4d439b 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeMergerTest.php @@ -6,6 +6,7 @@ use DateTimeImmutable; use DateTimeZone; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; use Flow\Floe\Exception\IncompatibleSchemaException; @@ -45,8 +46,11 @@ public function test_compact_reads_identically_to_splice(): void array_to_rows([['id' => 3]], schema(int_schema('id'))), ); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://splice.floe')); - (new FloeMerger($fs))->merge( + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://splice.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge( [path('memory://a.floe'), path('memory://b.floe')], path('memory://compact.floe'), compact: true, @@ -72,13 +76,16 @@ public function test_compact_coalesces_same_schema_sources_into_one_section(): v array_to_rows([['id' => 2]], schema(int_schema('id'))), ); - (new FloeMerger($fs))->merge( + (new FloeMerger($fs, new AdaptiveBackend()))->merge( [path('memory://a.floe'), path('memory://b.floe')], path('memory://compact.floe'), compact: true, ); - static::assertCount(1, (new FloeReader($fs))->read(path('memory://compact.floe'))->footer()->sections); + static::assertCount( + 1, + (new FloeReader($fs, new AdaptiveBackend()))->read(path('memory://compact.floe'))->footer()->sections, + ); } public function test_merge_of_same_columns_in_different_order_re_encodes_instead_of_splicing(): void @@ -95,7 +102,10 @@ public function test_merge_of_same_columns_in_different_order_re_encodes_instead array_to_rows([['b' => 200, 'a' => 2]], schema(int_schema('b'), int_schema('a'))), ); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://out.floe')); static::assertSame( [ @@ -105,7 +115,10 @@ public function test_merge_of_same_columns_in_different_order_re_encodes_instead FloeStreamReaderContext::readAll($fs, path('memory://out.floe'))->toArray(), ); // the compact path coalesces sources into one section - splicing would keep one per source - static::assertCount(1, (new FloeReader($fs))->read(path('memory://out.floe'))->footer()->sections); + static::assertCount( + 1, + (new FloeReader($fs, new AdaptiveBackend()))->read(path('memory://out.floe'))->footer()->sections, + ); } public function test_merge_of_same_columns_in_different_order_with_mixed_types_round_trips(): void @@ -122,7 +135,10 @@ public function test_merge_of_same_columns_in_different_order_with_mixed_types_r array_to_rows([['b' => 'two', 'a' => 2]], schema(str_schema('b'), int_schema('a'))), ); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://out.floe')); static::assertSame( [ @@ -148,7 +164,7 @@ public function test_empty_source_contributes_no_rows(): void array_to_rows([['id' => 2]], schema(int_schema('id'))), ); - (new FloeMerger($fs))->merge([ + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ path('memory://a.floe'), path('memory://empty.floe'), path('memory://b.floe'), @@ -165,7 +181,7 @@ public function test_empty_sources_list_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('at least one source'); - (new FloeMerger(memory_filesystem()))->merge([], path('memory://out.floe')); + (new FloeMerger(memory_filesystem(), new AdaptiveBackend()))->merge([], path('memory://out.floe')); } public function test_merging_a_source_that_adds_a_non_nullable_column_throws(): void @@ -187,7 +203,10 @@ public function test_merging_a_source_that_adds_a_non_nullable_column_throws(): $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('Floe merge cannot reconcile the schema of'); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://out.floe')); } public function test_merging_a_source_that_drops_a_non_nullable_column_throws(): void @@ -207,7 +226,10 @@ public function test_merging_a_source_that_drops_a_non_nullable_column_throws(): $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('Floe merge cannot reconcile the schema of'); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://out.floe')); } public function test_merging_sources_with_a_nullable_column_pads_missing_rows(): void @@ -227,7 +249,10 @@ public function test_merging_sources_with_a_nullable_column_pads_missing_rows(): array_to_rows([['id' => 2]], schema(int_schema('id'))), ); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://out.floe')); // "email" is nullable in A, so B's rows are legitimately padded with null on read-back. FloeStreamReaderContext::write( @@ -267,7 +292,7 @@ public function test_metadata_is_merged_with_new_keys_winning(): void ], ); - (new FloeMerger($fs))->merge( + (new FloeMerger($fs, new AdaptiveBackend()))->merge( [path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe'), metadata: Metadata::fromArray(['shared' => 'override']), @@ -275,7 +300,7 @@ public function test_metadata_is_merged_with_new_keys_winning(): void static::assertSame( ['a' => '1', 'shared' => 'override', 'b' => '2'], - (new FloeReader($fs)) + (new FloeReader($fs, new AdaptiveBackend())) ->read(path('memory://out.floe')) ->metadata() ->normalize(), @@ -287,7 +312,9 @@ public function test_missing_source_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('does not exist'); - (new FloeMerger(memory_filesystem()))->merge([path('memory://missing.floe')], path('memory://out.floe')); + (new FloeMerger(memory_filesystem(), new AdaptiveBackend()))->merge([path( + 'memory://missing.floe', + )], path('memory://out.floe')); } public function test_offset_read_after_merge_seeks_across_sources(): void @@ -304,11 +331,14 @@ public function test_offset_read_after_merge_seeks_across_sources(): void array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))), ); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://out.floe')); $read = []; - foreach ((new FloeReader($fs)) + foreach ((new FloeReader($fs, new AdaptiveBackend())) ->read(path('memory://out.floe')) ->rows(batchSize: 100, offset: 3) as $batch) { $read = [...$read, ...$batch->column('id')->values()]; @@ -323,7 +353,7 @@ public function test_single_source_is_a_copy(): void $value = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); FloeStreamReaderContext::write($fs, path('memory://a.floe'), $value); - (new FloeMerger($fs))->merge([path('memory://a.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([path('memory://a.floe')], path('memory://out.floe')); static::assertEquals($value, FloeStreamReaderContext::readAll($fs, path('memory://out.floe'))); } @@ -347,7 +377,7 @@ public function test_splices_three_files(): void array_to_rows([['id' => 3]], schema(int_schema('id'))), ); - (new FloeMerger($fs))->merge([ + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ path('memory://a.floe'), path('memory://b.floe'), path('memory://c.floe'), @@ -373,7 +403,10 @@ public function test_splices_two_files_with_the_same_schema(): void array_to_rows([['id' => 3], ['id' => 4]], schema(int_schema('id'))), ); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://out.floe')); static::assertEquals( array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))), @@ -398,7 +431,10 @@ public function test_type_conflict_throws(): void $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('Floe merge cannot reconcile the schema of'); - (new FloeMerger($fs))->merge([path('memory://a.floe'), path('memory://b.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ + path('memory://a.floe'), + path('memory://b.floe'), + ], path('memory://out.floe')); } public function test_unsized_source_throws(): void @@ -413,7 +449,9 @@ public function test_unsized_source_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('does not report its size'); - (new FloeMerger(new UnsizedFilesystem($fs)))->merge([path('memory://a.floe')], path('memory://out.floe')); + (new FloeMerger(new UnsizedFilesystem($fs), new AdaptiveBackend()))->merge([path( + 'memory://a.floe', + )], path('memory://out.floe')); } public function test_source_smaller_than_header_and_trailer_throws(): void @@ -427,7 +465,7 @@ public function test_source_smaller_than_header_and_trailer_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('too small'); - (new FloeMerger($fs))->merge([path('memory://tiny.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([path('memory://tiny.floe')], path('memory://out.floe')); } public function test_non_noop_codec_source_throws(): void @@ -441,7 +479,7 @@ public function test_non_noop_codec_source_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('written with codec 0x05'); - (new FloeMerger($fs))->merge([path('memory://codec.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([path('memory://codec.floe')], path('memory://out.floe')); } public function test_source_with_footer_larger_than_file_throws(): void @@ -455,7 +493,7 @@ public function test_source_with_footer_larger_than_file_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('footer does not fit'); - (new FloeMerger($fs))->merge([path('memory://torn.floe')], path('memory://out.floe')); + (new FloeMerger($fs, new AdaptiveBackend()))->merge([path('memory://torn.floe')], path('memory://out.floe')); } public function test_merge_of_different_datetime_zones_widens_to_utc(): void @@ -474,7 +512,7 @@ public function test_merge_of_different_datetime_zones_widens_to_utc(): void array_to_rows([['at' => $utc]], schema(datetime_schema('at'))), ); - (new FloeMerger($fs))->merge([ + (new FloeMerger($fs, new AdaptiveBackend()))->merge([ path('memory://warsaw.floe'), path('memory://utc.floe'), ], path('memory://merged.floe')); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php index 54b997e172..abe2a24bfa 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeReaderTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Unit; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Rows; use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; @@ -40,13 +41,13 @@ public function test_all_entry_types_round_trip(): void $path = path('memory://all-types.floe'); $rows = RowsMother::withAllEntryTypes(); - $writer = new FloeWriter($filesystem, $rows->schema()); + $writer = new FloeWriter($filesystem, $rows->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($rows); $writer->close(); $batches = iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), ); @@ -67,12 +68,12 @@ public function test_batches_follow_requested_size(): void ['id' => 4], ['id' => 5], ], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); - $reader = (new FloeReader($filesystem))->read($path); + $reader = (new FloeReader($filesystem, new AdaptiveBackend()))->read($path); $sizes = /** @@ -97,14 +98,14 @@ public function test_limit_caps_returned_rows(): void $path = path('memory://limit.floe'); $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); $ids = []; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(batchSize: 100, offset: 0, limit: 2) as $batch) { foreach ($batch->toArray() as $row) { @@ -121,13 +122,13 @@ public function test_limit_stops_within_a_batch(): void $path = path('memory://limit-batch.floe'); $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); $batches = iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(batchSize: 100, limit: 2), ); @@ -140,7 +141,7 @@ public function test_negative_offset_throws(): void { $filesystem = memory_filesystem(); $path = path('memory://neg-offset.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); @@ -148,7 +149,7 @@ public function test_negative_offset_throws(): void $this->expectExceptionMessage('offset must be greater or equal to 0'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(offset: -1), ); @@ -158,7 +159,7 @@ public function test_non_positive_limit_throws(): void { $filesystem = memory_filesystem(); $path = path('memory://zero-limit.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); @@ -166,7 +167,7 @@ public function test_non_positive_limit_throws(): void $this->expectExceptionMessage('limit must be greater than 0'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(limit: 0), ); @@ -178,14 +179,14 @@ public function test_offset_skips_leading_rows_within_a_single_section(): void $path = path('memory://offset-single.floe'); $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); $ids = []; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(offset: 2) as $batch) { foreach ($batch->toArray() as $row) { @@ -213,7 +214,7 @@ public function test_offset_skips_whole_sections(): void ], schema(int_schema('id'), str_schema('email', nullable: true)), ); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -222,7 +223,7 @@ public function test_offset_skips_whole_sections(): void $names = []; $emails = []; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(offset: 4) as $batch) { foreach ($batch->toArray() as $row) { @@ -244,7 +245,7 @@ public function test_offset_beyond_total_rows_yields_nothing(): void $path = path('memory://offset-past-end.floe'); $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -252,7 +253,7 @@ public function test_offset_beyond_total_rows_yields_nothing(): void static::assertSame( [], iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(offset: 2), ), @@ -260,7 +261,7 @@ public function test_offset_beyond_total_rows_yields_nothing(): void static::assertSame( [], iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(offset: 5), ), @@ -273,7 +274,7 @@ public function test_offset_respects_batch_size(): void $path = path('memory://offset-batches.floe'); $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -281,7 +282,7 @@ public function test_offset_respects_batch_size(): void $sizes = array_map( static fn(Rows $batch): int => $batch->count(), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(batchSize: 1, offset: 1), ), @@ -302,14 +303,14 @@ public function test_offset_and_limit_combined(): void ['id' => 4], ['id' => 5], ], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); $ids = []; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(batchSize: 100, offset: 1, limit: 2) as $batch) { foreach ($batch->toArray() as $row) { @@ -337,12 +338,12 @@ public function test_offset_matches_tail_of_full_read(): void ], schema(int_schema('id'), str_schema('email', nullable: true)), ); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); - $reader = (new FloeReader($filesystem))->read($path); + $reader = (new FloeReader($filesystem, new AdaptiveBackend()))->read($path); $full = []; foreach ($reader->rows() as $batch) { @@ -370,14 +371,19 @@ public function test_offset_reads_through_a_custom_identity_codec(): void $path = path('memory://offset-codec.floe'); $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema(), new Options(codec: new CodecStub(0x00))); + $writer = new FloeWriter( + $filesystem, + $data->schema(), + new AdaptiveBackend(), + new Options(codec: new CodecStub(0x00)), + ); $writer->create($path); $writer->write($data); $writer->close(); $ids = []; - foreach ((new FloeReader($filesystem, new CodecStub(0x00))) + foreach ((new FloeReader($filesystem, new AdaptiveBackend(), new CodecStub(0x00))) ->read($path) ->rows(offset: 1) as $batch) { foreach ($batch->toArray() as $extractedRow) { @@ -404,7 +410,7 @@ public function test_corrupt_row_body_throws_wrapped_exception(): void $this->expectExceptionMessage('Floe BATCH frame is truncated, its directory is incomplete'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), ); @@ -426,7 +432,7 @@ public function test_corrupted_frame_chain_throws(): void $this->expectExceptionMessage('frame body is incomplete'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), ); @@ -438,19 +444,19 @@ public function test_dead_footers_of_appended_files_are_skipped(): void $path = path('memory://appended.floe'); $created = array_to_rows([['id' => 1]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $created->schema()); + $writer = new FloeWriter($filesystem, $created->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($created); $writer->close(); $appended = array_to_rows([['id' => 2]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $appended->schema()); + $writer = new FloeWriter($filesystem, $appended->schema(), new AdaptiveBackend()); $writer->append($path); $writer->write($appended); $writer->close(); $batches = iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), false, @@ -467,11 +473,11 @@ public function test_empty_file_yields_no_batches(): void $filesystem = memory_filesystem(); $path = path('memory://empty.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); - $reader = (new FloeReader($filesystem))->read($path); + $reader = (new FloeReader($filesystem, new AdaptiveBackend()))->read($path); static::assertSame([], iterator_to_array($reader->rows(), false)); static::assertSame(0, $reader->totalRows()); @@ -488,7 +494,7 @@ public function test_evolved_file_rows_match_merged_schema(): void $evolvedFile = path('memory://evolved-new.floe'); $baseRows = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $baseRows->schema()); + $writer = new FloeWriter($filesystem, $baseRows->schema(), new AdaptiveBackend()); $writer->create($baseFile); $writer->write($baseRows); $writer->close(); @@ -497,15 +503,15 @@ public function test_evolved_file_rows_match_merged_schema(): void [['id' => 3, 'email' => null], ['id' => 4, 'email' => 'x@flow.php']], schema(int_schema('id'), str_schema('email', nullable: true)), ); - $writer = new FloeWriter($filesystem, $evolvedRows->schema()); + $writer = new FloeWriter($filesystem, $evolvedRows->schema(), new AdaptiveBackend()); $writer->create($evolvedFile); $writer->write($evolvedRows); $writer->close(); - (new FloeMerger($filesystem))->merge([$baseFile, $evolvedFile], $path); + (new FloeMerger($filesystem, new AdaptiveBackend()))->merge([$baseFile, $evolvedFile], $path); $batches = iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), false, @@ -538,7 +544,7 @@ public function test_footer_length_exceeding_file_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('footer does not fit inside the file'); - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->footer(); } @@ -554,7 +560,7 @@ public function test_footer_of_file_smaller_than_header_and_trailer_throws(): vo $this->expectException(FloeException::class); $this->expectExceptionMessage('too small'); - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->footer(); } @@ -564,14 +570,14 @@ public function test_footer_over_unsized_stream_throws(): void $filesystem = memory_filesystem(); $path = path('memory://unsized.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); $this->expectException(FloeException::class); $this->expectExceptionMessage('requires a sized stream'); - (new FloeReader(new UnsizedFilesystem($filesystem))) + (new FloeReader(new UnsizedFilesystem($filesystem), new AdaptiveBackend())) ->read($path) ->footer(); } @@ -582,12 +588,12 @@ public function test_footer_accessors(): void $path = path('memory://accessors.floe'); $data = array_to_rows([['id' => 1, 'name' => 'x']], schema(int_schema('id'), str_schema('name'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path, Metadata::fromArray(['source' => 'unit'])); $writer->write($data); $writer->close(); - $reader = (new FloeReader($filesystem))->read($path); + $reader = (new FloeReader($filesystem, new AdaptiveBackend()))->read($path); static::assertSame(Format::VERSION, $reader->footer()->version); static::assertSame(['source' => 'unit'], $reader->metadata()->normalize()); @@ -600,14 +606,14 @@ public function test_open_with_non_noop_codec_throws(): void { $filesystem = memory_filesystem(); $path = path('memory://x.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); $this->expectException(FloeException::class); $this->expectExceptionMessage('supports only the no-op codec, got codec 0x09'); - (new FloeReader($filesystem, new CodecStub(0x09)))->read($path); + (new FloeReader($filesystem, new AdaptiveBackend(), new CodecStub(0x09)))->read($path); } public function test_reader_with_mismatched_codec_flags_throws(): void @@ -621,7 +627,7 @@ public function test_reader_with_mismatched_codec_flags_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('written with codec 0x07'); - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->footer(); } @@ -632,13 +638,18 @@ public function test_rows_through_a_custom_identity_codec(): void $path = path('memory://custom-codec.floe'); $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema(), new Options(codec: new CodecStub(0x00))); + $writer = new FloeWriter( + $filesystem, + $data->schema(), + new AdaptiveBackend(), + new Options(codec: new CodecStub(0x00)), + ); $writer->create($path); $writer->write($data); $writer->close(); $batches = iterator_to_array( - (new FloeReader($filesystem, new CodecStub(0x00))) + (new FloeReader($filesystem, new AdaptiveBackend(), new CodecStub(0x00))) ->read($path) ->rows(), ); @@ -660,7 +671,7 @@ public function test_torn_file_without_footer_throws_in_strict_mode(): void $this->expectExceptionMessage('magic'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), ); @@ -682,7 +693,7 @@ public function test_unknown_frame_type_throws(): void $this->expectExceptionMessage('unknown frame type 0x55'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), ); @@ -700,14 +711,14 @@ public function test_head_returns_first_rows(): void ['id' => 4], ['id' => 5], ], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); $ids = []; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->head(3) as $batch) { foreach ($batch->toArray() as $row) { @@ -724,14 +735,14 @@ public function test_head_count_beyond_total_returns_all_rows(): void $path = path('memory://head-all.floe'); $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); $ids = []; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->head(5) as $batch) { foreach ($batch->toArray() as $row) { @@ -748,7 +759,7 @@ public function test_head_respects_batch_size(): void $path = path('memory://head-batches.floe'); $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -756,7 +767,7 @@ public function test_head_respects_batch_size(): void $sizes = array_map( static fn(Rows $batch): int => $batch->count(), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->head(3, batchSize: 1), ), @@ -769,7 +780,7 @@ public function test_head_non_positive_count_throws(): void { $filesystem = memory_filesystem(); $path = path('memory://head-zero.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); @@ -777,7 +788,7 @@ public function test_head_non_positive_count_throws(): void $this->expectExceptionMessage('head count must be greater than 0'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->head(0), ); @@ -800,7 +811,7 @@ public function test_tail_returns_last_rows_across_sections(): void ], schema(int_schema('id'), str_schema('email', nullable: true)), ); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -808,7 +819,7 @@ public function test_tail_returns_last_rows_across_sections(): void $ids = []; $names = []; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->tail(3) as $batch) { foreach ($batch->toArray() as $row) { @@ -827,14 +838,14 @@ public function test_tail_count_beyond_total_returns_all_rows(): void $path = path('memory://tail-all.floe'); $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); $ids = []; - foreach ((new FloeReader($filesystem)) + foreach ((new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->tail(5) as $batch) { foreach ($batch->toArray() as $row) { @@ -851,7 +862,7 @@ public function test_tail_respects_batch_size(): void $path = path('memory://tail-batches.floe'); $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -859,7 +870,7 @@ public function test_tail_respects_batch_size(): void $sizes = array_map( static fn(Rows $batch): int => $batch->count(), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->tail(3, batchSize: 1), ), @@ -882,12 +893,12 @@ public function test_tail_matches_slice_of_full_read(): void ['id' => 6], ['id' => 7], ], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); - $reader = (new FloeReader($filesystem))->read($path); + $reader = (new FloeReader($filesystem, new AdaptiveBackend()))->read($path); $full = []; @@ -914,7 +925,7 @@ public function test_tail_non_positive_count_throws(): void { $filesystem = memory_filesystem(); $path = path('memory://tail-zero.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); @@ -922,7 +933,7 @@ public function test_tail_non_positive_count_throws(): void $this->expectExceptionMessage('tail count must be greater than 0'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->tail(0), ); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php index 894daabc75..97b5a6e1f1 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSerializerTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Unit; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Rows; use Flow\ETL\Tests\Double\SpyBackend; use Flow\Floe\Exception\FloeException; @@ -63,14 +64,14 @@ public static function exactRoundTripValues(): array #[DataProvider('exactRoundTripValues')] public function test_serialize_unserialize_round_trip(Rows $value): void { - $serializer = new FloeSerializer(); + $serializer = new FloeSerializer(new AdaptiveBackend()); static::assertEquals($value, unserialize_from_string($serializer, serialize_to_string($serializer, $value))); } public function test_streaming_mode_round_trip(): void { - $serializer = new FloeSerializer(2); + $serializer = new FloeSerializer(new AdaptiveBackend(), 2); $value = RowsMother::withAllEntryTypes(); static::assertEquals($value, unserialize_from_string($serializer, serialize_to_string($serializer, $value))); @@ -84,14 +85,14 @@ public function test_cache_round_trip_preserves_rows_without_a_partition_table() ); static::assertEquals($value, unserialize_from_string( - new FloeSerializer(1), - serialize_to_string(new FloeSerializer(), $value), + new FloeSerializer(new AdaptiveBackend(), 1), + serialize_to_string(new FloeSerializer(new AdaptiveBackend()), $value), )); } public function test_heterogeneous_rows_round_trip_unpadded_but_union_widened(): void { - $serializer = new FloeSerializer(); + $serializer = new FloeSerializer(new AdaptiveBackend()); // one write session = one schema: rows keep their own columns (unpadded) but // entry types widen to the batch union - id and name become nullable because // each is absent from some row. Values are unchanged; only nullability widens. @@ -110,19 +111,19 @@ public function test_heterogeneous_rows_round_trip_unpadded_but_union_widened(): #[DataProvider('values')] public function test_read_batch_size_does_not_change_decoded_rows(Rows $value): void { - $bytes = serialize_to_string(new FloeSerializer(), $value); + $bytes = serialize_to_string(new FloeSerializer(new AdaptiveBackend()), $value); static::assertEquals( - unserialize_from_string(new FloeSerializer(), $bytes), - unserialize_from_string(new FloeSerializer(1), $bytes), + unserialize_from_string(new FloeSerializer(new AdaptiveBackend()), $bytes), + unserialize_from_string(new FloeSerializer(new AdaptiveBackend(), 1), $bytes), ); } #[DataProvider('exactRoundTripValues')] public function test_batch_sizes_decode_each_others_bytes(Rows $value): void { - $small = new FloeSerializer(1); - $default = new FloeSerializer(); + $small = new FloeSerializer(new AdaptiveBackend(), 1); + $default = new FloeSerializer(new AdaptiveBackend()); static::assertEquals($value, unserialize_from_string($default, serialize_to_string($small, $value))); static::assertEquals($value, unserialize_from_string($small, serialize_to_string($default, $value))); @@ -130,21 +131,21 @@ public function test_batch_sizes_decode_each_others_bytes(Rows $value): void public function test_batch_size_smaller_than_row_count(): void { - $serializer = new FloeSerializer(3); + $serializer = new FloeSerializer(new AdaptiveBackend(), 3); $value = array_to_rows( array_map(static fn(int $id): array => ['id' => $id], range(1, 10)), schema(int_schema('id')), ); static::assertEquals($value, unserialize_from_string($serializer, serialize_to_string( - new FloeSerializer(), + new FloeSerializer(new AdaptiveBackend()), $value, ))); } public function test_batch_size_larger_than_row_count(): void { - $serializer = new FloeSerializer(100); + $serializer = new FloeSerializer(new AdaptiveBackend(), 100); $value = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); static::assertEquals($value, unserialize_from_string($serializer, serialize_to_string($serializer, $value))); @@ -156,14 +157,14 @@ public function test_batch_size_below_one_throws(): void $this->expectExceptionMessage('Serializer batch size must be at least 1'); // @mago-ignore analysis:invalid-argument - new FloeSerializer(0); + new FloeSerializer(new AdaptiveBackend(), 0); } public function test_unserialize_rejects_torn_bytes(): void { $this->expectException(SerializationException::class); - unserialize_from_string(new FloeSerializer(), 'not a valid floe payload'); + unserialize_from_string(new FloeSerializer(new AdaptiveBackend()), 'not a valid floe payload'); } public function test_unserialize_rejects_empty_payload(): void @@ -171,12 +172,14 @@ public function test_unserialize_rejects_empty_payload(): void $this->expectException(SerializationException::class); $this->expectExceptionMessage('too small'); - unserialize_from_string(new FloeSerializer(), ''); + unserialize_from_string(new FloeSerializer(new AdaptiveBackend()), ''); } public function test_unserialize_rejects_row_count_mismatch(): void { - $bytes = serialize_to_string(new FloeSerializer(), array_to_rows([['id' => 1]], schema(int_schema('id')))); + $bytes = serialize_to_string(new FloeSerializer(new AdaptiveBackend()), array_to_rows([[ + 'id' => 1, + ]], schema(int_schema('id')))); // inflate the footer's row count while the body still holds a single row; the JSON // byte-length is unchanged (1 -> 2) so the trailer stays valid and the read reaches // the whole-value row-count guard @@ -185,7 +188,7 @@ public function test_unserialize_rejects_row_count_mismatch(): void $this->expectException(SerializationException::class); $this->expectExceptionMessage('decoded 1 of 2 rows'); - unserialize_from_string(new FloeSerializer(), $corrupted); + unserialize_from_string(new FloeSerializer(new AdaptiveBackend()), $corrupted); } public function test_unserialize_rejects_payload_smaller_than_header_and_trailer(): void @@ -193,7 +196,7 @@ public function test_unserialize_rejects_payload_smaller_than_header_and_trailer $this->expectException(SerializationException::class); $this->expectExceptionMessage('too small'); - unserialize_from_string(new FloeSerializer(), 'tiny'); + unserialize_from_string(new FloeSerializer(new AdaptiveBackend()), 'tiny'); } public function test_unserialize_rejects_footer_that_does_not_fit(): void @@ -201,7 +204,10 @@ public function test_unserialize_rejects_footer_that_does_not_fit(): void $this->expectException(SerializationException::class); $this->expectExceptionMessage('footer does not fit'); - unserialize_from_string(new FloeSerializer(), Format::header(0x00) . Format::trailer(1000)); + unserialize_from_string( + new FloeSerializer(new AdaptiveBackend()), + Format::header(0x00) . Format::trailer(1000), + ); } public function test_unserialize_builds_through_the_given_backend(): void @@ -216,7 +222,7 @@ public function test_unserialize_builds_through_the_given_backend(): void public function test_an_empty_payload_unserializes_to_an_empty_batch_of_its_schema(): void { - $serializer = new FloeSerializer(); + $serializer = new FloeSerializer(new AdaptiveBackend()); $rows = unserialize_from_string($serializer, serialize_to_string($serializer, rows(schema(int_schema('id'))))); static::assertSame(0, $rows->count()); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSourceFileTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSourceFileTest.php index 19eaba2a8a..9e7fc59d04 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSourceFileTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeSourceFileTest.php @@ -4,7 +4,7 @@ namespace Flow\Floe\Tests\Unit; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; use Flow\Floe\FloeSourceFile; diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php index defdb53193..4d51b2c161 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamReaderTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Unit; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Rows; use Flow\Floe\Codec\NoopCodec; use Flow\Floe\Exception\FloeException; @@ -33,14 +34,14 @@ public function test_close_closes_the_source_stream(): void $path = path('memory://close.floe'); $data = array_to_rows([['id' => 1]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); $source = new ClosingSpySourceStream($filesystem->readFrom($path)); - (new FloeStreamReader($source, new NoopCodec(), 65_536))->close(); + (new FloeStreamReader($source, new NoopCodec(), 65_536, new AdaptiveBackend()))->close(); static::assertSame(1, $source->closeCount); } @@ -61,7 +62,7 @@ public function test_a_row_frame_is_an_unknown_frame_type(): void $this->expectExceptionMessage('Floe found unknown frame type 0x02'); iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), false, @@ -86,7 +87,7 @@ public function test_offset_skips_a_whole_batch_frame_and_slices_the_next(): voi array_map( static fn(Rows $batch) => $batch->toArray(), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(offset: 4), false, @@ -112,7 +113,7 @@ public function test_limit_slices_a_batch_frame(): void array_map( static fn(Rows $batch) => $batch->toArray(), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(limit: 2), false, @@ -147,7 +148,7 @@ public function test_batch_size_is_an_upper_bound(): void array_map( static fn(Rows $batch) => $batch->count(), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($one) ->rows(2), false, @@ -159,7 +160,7 @@ public function test_batch_size_is_an_upper_bound(): void array_map( static fn(Rows $batch) => $batch->count(), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($two) ->rows(10), false, @@ -184,7 +185,7 @@ public function test_chunked_frames_yield_unique_keys(): void static::assertSame( [0, 1, 2, 3], array_keys(iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(2), )), diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php index 3c1dc07652..6a06069aa9 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeStreamWriterTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Unit; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\OffsetOverflow; use Flow\ETL\Rows; @@ -44,12 +45,12 @@ public function test_create_on_stream_is_byte_identical_to_path_create(): void ); $schema = $data->schema(); - $create = new FloeWriter($filesystem, $schema); + $create = new FloeWriter($filesystem, $schema, new AdaptiveBackend()); $create->create($viaCreate); $create->write($data); $create->close(); - $onStream = new FloeStreamWriter($schema); + $onStream = new FloeStreamWriter($schema, new AdaptiveBackend()); $onStream->create($filesystem->writeTo($viaStream)); $onStream->write($data); $onStream->close(); @@ -69,12 +70,12 @@ public function test_small_buffer_size_produces_byte_identical_output(): void $schema = $data->schema(); - $defaultWriter = new FloeStreamWriter($schema); + $defaultWriter = new FloeStreamWriter($schema, new AdaptiveBackend()); $defaultWriter->create($filesystem->writeTo($default)); $defaultWriter->write($data); $defaultWriter->close(); - $tinyWriter = new FloeStreamWriter($schema, new Options(bufferSize: 4)); + $tinyWriter = new FloeStreamWriter($schema, new AdaptiveBackend(), new Options(bufferSize: 4)); $tinyWriter->create($filesystem->writeTo($tiny)); $tinyWriter->write($data); $tinyWriter->close(); @@ -89,7 +90,7 @@ public function test_create_on_stream_round_trips(): void $data = array_to_rows([['id' => 1], ['id' => 2], ['id' => 3]], schema(int_schema('id'))); - $writer = new FloeStreamWriter($data->schema()); + $writer = new FloeStreamWriter($data->schema(), new AdaptiveBackend()); $writer->create($filesystem->writeTo($path), Metadata::fromArray(['source' => 'stream'])); $writer->write($data); $writer->close(); @@ -109,12 +110,12 @@ public function test_construct_with_non_noop_codec_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('supports only the no-op codec, got codec 0x05'); - new FloeStreamWriter(schema(), new Options(codec: new CodecStub(0x05))); + new FloeStreamWriter(schema(), new AdaptiveBackend(), new Options(codec: new CodecStub(0x05))); } public function test_creating_a_second_session_throws(): void { - $writer = new FloeStreamWriter(schema()); + $writer = new FloeStreamWriter(schema(), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://first.floe'))); $this->expectException(FloeException::class); @@ -125,7 +126,7 @@ public function test_creating_a_second_session_throws(): void public function test_write_before_create_throws(): void { - $writer = new FloeStreamWriter(schema()); + $writer = new FloeStreamWriter(schema(), new AdaptiveBackend()); $this->expectException(FloeException::class); $this->expectExceptionMessage('Floe writer session is not open'); @@ -145,13 +146,13 @@ public function test_a_multi_batch_session_reads_back_the_rows_of_a_single_batch ); $schema = $data->schema(); - $multiWriter = new FloeStreamWriter($schema); + $multiWriter = new FloeStreamWriter($schema, new AdaptiveBackend()); $multiWriter->create($filesystem->writeTo($multi)); $multiWriter->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); $multiWriter->write(array_to_rows([['id' => 2, 'name' => 'b']], schema(int_schema('id'), str_schema('name')))); $multiWriter->close(); - $singleWriter = new FloeStreamWriter($schema); + $singleWriter = new FloeStreamWriter($schema, new AdaptiveBackend()); $singleWriter->create($filesystem->writeTo($single)); $singleWriter->write($data); $singleWriter->close(); @@ -161,7 +162,7 @@ public function test_a_multi_batch_session_reads_back_the_rows_of_a_single_batch FloeStreamReaderContext::frameTypes($filesystem, $multi), ); static::assertSame( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($single) ->rows() ->current() @@ -169,7 +170,7 @@ public function test_a_multi_batch_session_reads_back_the_rows_of_a_single_batch array_merge(...array_map( static fn(Rows $batch) => $batch->toArray(), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($multi) ->rows(), false, @@ -192,7 +193,7 @@ public function test_batch_omitting_a_nullable_session_column_is_accepted_and_ro schema(int_schema('id'), str_schema('name', nullable: true)), ); - $writer = new FloeStreamWriter($first->schema()); + $writer = new FloeStreamWriter($first->schema(), new AdaptiveBackend()); $writer->create($filesystem->writeTo($path)); $writer->write($first); $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); @@ -212,7 +213,7 @@ public function test_batch_omitting_a_not_null_session_column_is_refused(): void { $first = array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name'))); - $writer = new FloeStreamWriter($first->schema()); + $writer = new FloeStreamWriter($first->schema(), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://subset-not-null.floe'))); $writer->write($first); @@ -224,7 +225,7 @@ public function test_batch_omitting_a_not_null_session_column_is_refused(): void public function test_batch_introducing_a_new_column_throws_naming_the_column(): void { - $writer = new FloeStreamWriter(schema(int_schema('id'))); + $writer = new FloeStreamWriter(schema(int_schema('id')), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://new-column.floe'))); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); @@ -236,7 +237,7 @@ public function test_batch_introducing_a_new_column_throws_naming_the_column(): public function test_batch_with_an_incompatible_type_throws_naming_the_column(): void { - $writer = new FloeStreamWriter(schema(int_schema('id'))); + $writer = new FloeStreamWriter(schema(int_schema('id')), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://type-drift.floe'))); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); @@ -248,7 +249,7 @@ public function test_batch_with_an_incompatible_type_throws_naming_the_column(): public function test_new_column_message_names_the_session_schema_and_the_column(): void { - $writer = new FloeStreamWriter(schema(int_schema('id'))); + $writer = new FloeStreamWriter(schema(int_schema('id')), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://hint.floe'))); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); @@ -265,7 +266,7 @@ public function test_explicit_session_schema_is_used_for_the_footer(): void $filesystem = memory_filesystem(); $path = path('memory://explicit-schema.floe'); - $writer = new FloeStreamWriter(schema(int_schema('id'), str_schema('name'))); + $writer = new FloeStreamWriter(schema(int_schema('id'), str_schema('name')), new AdaptiveBackend()); $writer->create($filesystem->writeTo($path)); $writer->write(array_to_rows([['id' => 1, 'name' => 'a']], schema(int_schema('id'), str_schema('name')))); $writer->close(); @@ -280,7 +281,7 @@ public function test_empty_batch_writes_no_schema_or_section(): void $filesystem = memory_filesystem(); $path = path('memory://empty.floe'); - $writer = new FloeStreamWriter(schema()); + $writer = new FloeStreamWriter(schema(), new AdaptiveBackend()); $writer->create($filesystem->writeTo($path)); $writer->write(rows(schema())); $writer->close(); @@ -297,7 +298,7 @@ public function test_writing_a_column_name_with_invalid_utf8_throws(): void { $badRows = array_to_rows([['badÿname' => 'x']], schema(str_schema('badÿname'))); - $writer = new FloeStreamWriter($badRows->schema()); + $writer = new FloeStreamWriter($badRows->schema(), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://bad-name.floe'))); $this->expectException(FloeException::class); @@ -313,7 +314,7 @@ public function test_a_later_null_into_a_non_nullable_session_column_is_rejected { $first = array_to_rows([['id' => 1, 'opt' => 'present']], schema(int_schema('id'), str_schema('opt'))); - $writer = new FloeStreamWriter($first->schema()); + $writer = new FloeStreamWriter($first->schema(), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://off-present-then-null.floe'))); $writer->write($first); @@ -330,7 +331,7 @@ public function test_validation_on_rejects_a_later_null_into_a_non_nullable_sess { $first = array_to_rows([['id' => 1, 'opt' => 'present']], schema(int_schema('id'), str_schema('opt'))); - $writer = new FloeStreamWriter($first->schema()); + $writer = new FloeStreamWriter($first->schema(), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://on-present-then-null.floe'))); $writer->write($first); @@ -349,7 +350,7 @@ public function test_validation_on_rejects_a_later_null_into_a_non_nullable_sess */ public function test_column_absent_from_the_session_schema_throws(): void { - $writer = new FloeStreamWriter(schema(int_schema('a'))); + $writer = new FloeStreamWriter(schema(int_schema('a')), new AdaptiveBackend()); $writer->create(memory_filesystem()->writeTo(path('memory://off-new-column.floe'))); $this->expectException(IncompatibleSchemaException::class); @@ -378,7 +379,7 @@ public function test_an_overflowing_batch_is_split_in_halves(): void 4, ); - $writer = new FloeStreamWriter($schema); + $writer = new FloeStreamWriter($schema, new AdaptiveBackend()); $writer->create($filesystem->writeTo($path)); $writer->write($rows); $writer->close(); @@ -392,7 +393,7 @@ public function test_an_overflowing_batch_is_split_in_halves(): void array_map( static fn(Rows $batch) => $batch->reduceToArray('id'), iterator_to_array( - (new FloeReader($filesystem)) + (new FloeReader($filesystem, new AdaptiveBackend())) ->read($path) ->rows(), false, @@ -411,7 +412,7 @@ public function test_a_corrupt_column_fails_on_the_first_encode(): void maxRows: 0, ); - $writer = new FloeStreamWriter($schema); + $writer = new FloeStreamWriter($schema, new AdaptiveBackend()); $writer->create($filesystem->writeTo(path('memory://corrupt.floe'))); try { @@ -433,7 +434,7 @@ public function test_a_single_overflowing_row_rethrows_offset_overflow(): void maxRows: 0, ); - $writer = new FloeStreamWriter($schema); + $writer = new FloeStreamWriter($schema, new AdaptiveBackend()); $writer->create($filesystem->writeTo(path('memory://single.floe'))); $this->expectException(OffsetOverflow::class); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php index 589fcdc271..7e0edd396d 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FloeWriterTest.php @@ -5,6 +5,7 @@ namespace Flow\Floe\Tests\Unit; use DateTimeImmutable; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Schema\Metadata; use Flow\Floe\Exception\FloeException; use Flow\Floe\Exception\IncompatibleSchemaException; @@ -39,12 +40,12 @@ public function test_create_for_stream_is_byte_identical_to_create_by_path(): vo ); $schema = $data->schema(); - $byPath = new FloeWriter($filesystem, $schema); + $byPath = new FloeWriter($filesystem, $schema, new AdaptiveBackend()); $byPath->create($viaPath); $byPath->write($data); $byPath->close(); - $byStream = new FloeWriter($filesystem, $schema); + $byStream = new FloeWriter($filesystem, $schema, new AdaptiveBackend()); $byStream->createForStream($filesystem->writeTo($viaStream)); $byStream->write($data); $byStream->close(); @@ -64,12 +65,12 @@ public function test_buffer_size_only_changes_flush_cadence_not_bytes(): void $schema = $data->schema(); - $defaultWriter = new FloeWriter($filesystem, $schema); + $defaultWriter = new FloeWriter($filesystem, $schema, new AdaptiveBackend()); $defaultWriter->create($default); $defaultWriter->write($data); $defaultWriter->close(); - $tinyWriter = new FloeWriter($filesystem, $schema, new Options(bufferSize: 4)); + $tinyWriter = new FloeWriter($filesystem, $schema, new AdaptiveBackend(), new Options(bufferSize: 4)); $tinyWriter->create($tiny); $tinyWriter->write($data); $tinyWriter->close(); @@ -82,7 +83,7 @@ public function test_append_on_missing_file_behaves_like_create(): void $filesystem = memory_filesystem(); $path = path('memory://missing.floe'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); @@ -96,7 +97,7 @@ public function test_append_on_empty_file_behaves_like_create(): void $path = path('memory://zero-bytes.floe'); $filesystem->writeTo($path)->close(); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); @@ -109,11 +110,11 @@ public function test_append_to_a_closed_zero_row_file_derives_the_schema_from_th $filesystem = memory_filesystem(); $path = path('memory://zero-rows.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); @@ -126,11 +127,11 @@ public function test_append_to_a_zero_row_file_with_an_explicit_schema_validates $filesystem = memory_filesystem(); $path = path('memory://zero-rows-schema.floe'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->create($path); $writer->close(); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); $this->expectException(IncompatibleSchemaException::class); @@ -144,7 +145,7 @@ public function test_create_with_an_explicit_schema_and_no_writes_records_the_sc $filesystem = memory_filesystem(); $path = path('memory://schema-only.floe'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->create($path); $writer->close(); @@ -159,14 +160,14 @@ public function test_append_over_unsized_stream_throws(): void $filesystem = memory_filesystem(); $path = path('memory://unsized.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); $this->expectException(FloeException::class); $this->expectExceptionMessage('requires a sized stream'); - (new FloeWriter(new UnsizedFilesystem($filesystem), schema()))->append($path); + (new FloeWriter(new UnsizedFilesystem($filesystem), schema(), new AdaptiveBackend()))->append($path); } public function test_append_with_footer_length_exceeding_file_throws(): void @@ -180,7 +181,7 @@ public function test_append_with_footer_length_exceeding_file_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('footer does not fit inside the file'); - (new FloeWriter($filesystem, schema()))->append($path); + (new FloeWriter($filesystem, schema(), new AdaptiveBackend()))->append($path); } public function test_append_metadata_merges_over_existing_footer_metadata(): void @@ -188,10 +189,10 @@ public function test_append_metadata_merges_over_existing_footer_metadata(): voi $filesystem = memory_filesystem(); $path = path('memory://meta.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path, Metadata::fromArray(['source' => 'create', 'kept' => 'yes'])); $writer->close(); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->append($path, Metadata::fromArray(['source' => 'append'])); $writer->close(); @@ -212,7 +213,7 @@ public function test_append_to_file_with_different_codec_flags_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('written with codec 0x05'); - (new FloeWriter($filesystem, schema()))->append($path); + (new FloeWriter($filesystem, schema(), new AdaptiveBackend()))->append($path); } public function test_append_to_torn_file_throws(): void @@ -226,7 +227,7 @@ public function test_append_to_torn_file_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('torn'); - (new FloeWriter($filesystem, schema()))->append($path); + (new FloeWriter($filesystem, schema(), new AdaptiveBackend()))->append($path); } public function test_append_to_truncated_stub_throws(): void @@ -240,7 +241,7 @@ public function test_append_to_truncated_stub_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('too small'); - (new FloeWriter($filesystem, schema()))->append($path); + (new FloeWriter($filesystem, schema(), new AdaptiveBackend()))->append($path); } public function test_append_with_incompatible_schema_keeps_previous_rows_readable(): void @@ -248,12 +249,12 @@ public function test_append_with_incompatible_schema_keeps_previous_rows_readabl $filesystem = memory_filesystem(); $path = path('memory://safe.floe'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->create($path); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); try { @@ -275,7 +276,7 @@ public function test_append_with_new_non_nullable_column_throws(): void $filesystem = memory_filesystem(); $path = path('memory://evolve.floe'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->create($path); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); @@ -283,7 +284,7 @@ public function test_append_with_new_non_nullable_column_throws(): void $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('new column "email"'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); $writer->write(array_to_rows([['id' => 2, 'email' => 'x']], schema(int_schema('id'), str_schema('email')))); } @@ -293,12 +294,12 @@ public function test_append_with_new_nullable_column_throws(): void $filesystem = memory_filesystem(); $path = path('memory://merge.floe'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->create($path); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); $this->expectException(IncompatibleSchemaException::class); @@ -315,12 +316,12 @@ public function test_append_with_same_schema_adds_a_section_reusing_the_footer_s $filesystem = memory_filesystem(); $path = path('memory://same-schema.floe'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->create($path); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->close(); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->append($path); $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); $writer->close(); @@ -339,7 +340,7 @@ public function test_append_with_same_schema_adds_a_section_reusing_the_footer_s public function test_close_twice_throws(): void { - $writer = new FloeWriter(memory_filesystem(), schema()); + $writer = new FloeWriter(memory_filesystem(), schema(), new AdaptiveBackend()); $writer->create(path('memory://closed.floe')); $writer->close(); @@ -351,7 +352,7 @@ public function test_close_twice_throws(): void public function test_opening_a_second_session_throws(): void { - $writer = new FloeWriter(memory_filesystem(), schema()); + $writer = new FloeWriter(memory_filesystem(), schema(), new AdaptiveBackend()); $writer->create(path('memory://first.floe')); $this->expectException(FloeException::class); @@ -365,7 +366,7 @@ public function test_closing_empty_file_writes_header_and_footer_only(): void $filesystem = memory_filesystem(); $path = path('memory://empty.floe'); - $writer = new FloeWriter($filesystem, schema()); + $writer = new FloeWriter($filesystem, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); @@ -383,9 +384,12 @@ public function test_create_with_non_noop_codec_throws(): void $this->expectException(FloeException::class); $this->expectExceptionMessage('supports only the no-op codec, got codec 0x05'); - (new FloeWriter(memory_filesystem(), schema(), new Options(codec: new CodecStub(0x05))))->create(path( - 'memory://codec.floe', - )); + (new FloeWriter( + memory_filesystem(), + schema(), + new AdaptiveBackend(), + new Options(codec: new CodecStub(0x05)), + ))->create(path('memory://codec.floe')); } public function test_two_writes_with_the_same_schema_in_one_session_share_one_section(): void @@ -393,7 +397,7 @@ public function test_two_writes_with_the_same_schema_in_one_session_share_one_se $filesystem = memory_filesystem(); $path = path('memory://continuation.floe'); - $writer = new FloeWriter($filesystem, schema(int_schema('id'))); + $writer = new FloeWriter($filesystem, schema(int_schema('id')), new AdaptiveBackend()); $writer->create($path); $writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')))); $writer->write(array_to_rows([['id' => 2]], schema(int_schema('id')))); @@ -414,7 +418,7 @@ public function test_nothing_reaches_the_stream_before_buffer_fills_or_close(): $filesystem = memory_filesystem(); $path = path('memory://buffered.floe'); - $writer = new FloeWriter($filesystem, schema(str_schema('data'))); + $writer = new FloeWriter($filesystem, schema(str_schema('data')), new AdaptiveBackend()); $writer->create($path); $writer->write(array_to_rows([['data' => 'x']], schema(str_schema('data')))); @@ -435,7 +439,7 @@ public function test_within_batch_heterogeneous_rows_encode_under_one_union_sche schema(int_schema('a'), str_schema('b', nullable: true), str_schema('c', nullable: true)), ); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -464,7 +468,7 @@ public function test_section_offsets_point_at_frames(): void schema(int_schema('a', nullable: true), str_schema('b', nullable: true)), ); - $writer = new FloeWriter($filesystem, $data->schema()); + $writer = new FloeWriter($filesystem, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -481,7 +485,7 @@ public function test_section_offsets_point_at_frames(): void public function test_write_after_close_throws(): void { - $writer = new FloeWriter(memory_filesystem(), schema()); + $writer = new FloeWriter(memory_filesystem(), schema(), new AdaptiveBackend()); $writer->create(path('memory://done.floe')); $writer->close(); @@ -496,7 +500,7 @@ public function test_append_refuses_a_different_datetime_zone(): void $filesystem = memory_filesystem(); $path = path('memory://zoned.floe'); - $writer = new FloeWriter($filesystem, schema(datetime_schema('at'))); + $writer = new FloeWriter($filesystem, schema(datetime_schema('at')), new AdaptiveBackend()); $writer->create($path); $writer->write(array_to_rows([[ 'at' => new DateTimeImmutable('2026-01-02 03:04:05'), @@ -506,6 +510,10 @@ public function test_append_refuses_a_different_datetime_zone(): void $this->expectException(IncompatibleSchemaException::class); $this->expectExceptionMessage('Floe append schema does not match the existing file schema.'); - (new FloeWriter($filesystem, schema(datetime_schema('at', zone: 'Europe/Warsaw'))))->append($path); + (new FloeWriter( + $filesystem, + schema(datetime_schema('at', zone: 'Europe/Warsaw')), + new AdaptiveBackend(), + ))->append($path); } } diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterReaderTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterReaderTest.php index 02de026a60..86dcd665f0 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterReaderTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterReaderTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Unit; +use Flow\ETL\Column\AdaptiveBackend; use Flow\Filesystem\Stream\MemorySourceStream; use Flow\Floe\Codec\NoopCodec; use Flow\Floe\Exception\FloeException; @@ -30,7 +31,7 @@ public function test_reads_footer_location_of_a_written_file(): void $fs = memory_filesystem(); $path = path('memory://footer.floe'); $data = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - $writer = new FloeWriter($fs, $data->schema()); + $writer = new FloeWriter($fs, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); @@ -46,7 +47,7 @@ public function test_unsized_stream_throws(): void { $fs = memory_filesystem(); $path = path('memory://unsized.floe'); - $writer = new FloeWriter($fs, schema()); + $writer = new FloeWriter($fs, schema(), new AdaptiveBackend()); $writer->create($path); $writer->close(); @@ -95,7 +96,7 @@ public function test_leaves_the_source_open_on_success(): void $fs = memory_filesystem(); $path = path('memory://close-ok.floe'); $data = array_to_rows([['id' => 1]], schema(int_schema('id'))); - $writer = new FloeWriter($fs, $data->schema()); + $writer = new FloeWriter($fs, $data->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($data); $writer->close(); diff --git a/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterTest.php b/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterTest.php index 731684e409..bbfbc3067a 100644 --- a/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterTest.php +++ b/src/core/etl/tests/Flow/Floe/Tests/Unit/FooterTest.php @@ -4,6 +4,7 @@ namespace Flow\Floe\Tests\Unit; +use Flow\ETL\Column\AdaptiveBackend; use Flow\Floe\Exception\FloeException; use Flow\Floe\FloeWriter; use Flow\Floe\Footer; @@ -195,7 +196,7 @@ public function test_reconstruct_rows_round_trips_unpartitioned_rows(): void $path = path('memory://footer-rows.floe'); $value = array_to_rows([['id' => 1], ['id' => 2]], schema(int_schema('id'))); - $writer = new FloeWriter($filesystem, $value->schema()); + $writer = new FloeWriter($filesystem, $value->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($value); $writer->close(); @@ -209,7 +210,7 @@ public function test_reconstruct_rows_round_trips_empty_rows(): void $path = path('memory://footer-empty.floe'); $value = rows(schema()); - $writer = new FloeWriter($filesystem, $value->schema()); + $writer = new FloeWriter($filesystem, $value->schema(), new AdaptiveBackend()); $writer->create($path); $writer->write($value); $writer->close(); diff --git a/src/extension/arrow-ext/php/Flow/Arrow/OutputStream.php b/src/extension/arrow-ext/php/Flow/Arrow/OutputStream.php deleted file mode 100644 index 781267cee9..0000000000 --- a/src/extension/arrow-ext/php/Flow/Arrow/OutputStream.php +++ /dev/null @@ -1,16 +0,0 @@ - i32 eprintln!("arrow: failed to register the Flow\\Parquet interfaces: {e}"); return -1; } - if let Err(e) = stream::output_stream::register() { - eprintln!("arrow: failed to register Flow\\Arrow\\OutputStream: {e}"); - return -1; - } - if let Err(e) = stream::random_access_file::register() { - eprintln!("arrow: failed to register Flow\\Arrow\\RandomAccessFile: {e}"); - return -1; - } 0 } diff --git a/src/extension/arrow-ext/src/stream/mod.rs b/src/extension/arrow-ext/src/stream/mod.rs deleted file mode 100644 index 7eb0716190..0000000000 --- a/src/extension/arrow-ext/src/stream/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod output_stream; -pub mod random_access_file; diff --git a/src/extension/arrow-ext/src/stream/output_stream.rs b/src/extension/arrow-ext/src/stream/output_stream.rs deleted file mode 100644 index 7b778f574f..0000000000 --- a/src/extension/arrow-ext/src/stream/output_stream.rs +++ /dev/null @@ -1,26 +0,0 @@ -use ext_php_rs::args::{Arg, ArgInfoTables}; -use ext_php_rs::builders::{ClassBuilder, FunctionBuilder}; -use ext_php_rs::error::Result; -use ext_php_rs::flags::{ClassFlags, DataType, MethodFlags}; -use ext_php_rs::zend::ClassEntry; - -use crate::interfaces::keep; - -fn store(_ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { - keep(arg_info); -} - -pub fn register() -> Result<()> { - ClassBuilder::new("Flow\\Arrow\\OutputStream") - .flags(ClassFlags::Interface) - .registration(store) - .method( - FunctionBuilder::new_abstract("append") - .arg(Arg::new("data", DataType::String)) - .returns(DataType::object("self"), false, false), - MethodFlags::Public | MethodFlags::Abstract, - ) - .register()?; - - Ok(()) -} diff --git a/src/extension/arrow-ext/src/stream/random_access_file.rs b/src/extension/arrow-ext/src/stream/random_access_file.rs deleted file mode 100644 index 3bafba6ab8..0000000000 --- a/src/extension/arrow-ext/src/stream/random_access_file.rs +++ /dev/null @@ -1,31 +0,0 @@ -use ext_php_rs::args::{Arg, ArgInfoTables}; -use ext_php_rs::builders::{ClassBuilder, FunctionBuilder}; -use ext_php_rs::error::Result; -use ext_php_rs::flags::{ClassFlags, DataType, MethodFlags}; -use ext_php_rs::zend::ClassEntry; - -use crate::interfaces::keep; - -fn store(_ce: &'static mut ClassEntry, arg_info: ArgInfoTables) { - keep(arg_info); -} - -pub fn register() -> Result<()> { - ClassBuilder::new("Flow\\Arrow\\RandomAccessFile") - .flags(ClassFlags::Interface) - .registration(store) - .method( - FunctionBuilder::new_abstract("read") - .arg(Arg::new("length", DataType::Long)) - .arg(Arg::new("offset", DataType::Long)) - .returns(DataType::String, false, false), - MethodFlags::Public | MethodFlags::Abstract, - ) - .method( - FunctionBuilder::new_abstract("size").returns(DataType::Long, false, true), - MethodFlags::Public | MethodFlags::Abstract, - ) - .register()?; - - Ok(()) -} diff --git a/src/extension/arrow-ext/tests/phpt/036_interfaces_and_exception_registered.phpt b/src/extension/arrow-ext/tests/phpt/036_interfaces_and_exception_registered.phpt deleted file mode 100644 index a0e2b958fd..0000000000 --- a/src/extension/arrow-ext/tests/phpt/036_interfaces_and_exception_registered.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -arrow extension registers the OutputStream and RandomAccessFile interfaces ---SKIPIF-- - ---FILE-- -isInterface()); -var_dump($r->hasMethod('append')); - -$r = new ReflectionClass('Flow\Arrow\RandomAccessFile'); -var_dump($r->isInterface()); -var_dump($r->hasMethod('read')); -var_dump($r->hasMethod('size')); -?> ---EXPECT-- -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) -bool(true) diff --git a/src/extension/arrow-ext/tests/phpt/051_parquet_interfaces_reflection.phpt b/src/extension/arrow-ext/tests/phpt/051_parquet_interfaces_reflection.phpt index 0d36a79f09..e99a778453 100644 --- a/src/extension/arrow-ext/tests/phpt/051_parquet_interfaces_reflection.phpt +++ b/src/extension/arrow-ext/tests/phpt/051_parquet_interfaces_reflection.phpt @@ -1,5 +1,5 @@ --TEST-- -arrow registers the flow-php/parquet and Arrow stream interfaces reflection-identical to the package files +arrow registers the flow-php/parquet interfaces reflection-identical to the package files --SKIPIF-- --FILE-- diff --git a/src/extension/arrow-ext/tests/phpt/bootstrap.php b/src/extension/arrow-ext/tests/phpt/bootstrap.php index 09a08cc646..000169488f 100644 --- a/src/extension/arrow-ext/tests/phpt/bootstrap.php +++ b/src/extension/arrow-ext/tests/phpt/bootstrap.php @@ -42,8 +42,6 @@ function arrow_interfaces_reflection(): string 'Flow\\Parquet\\ParquetEngine', 'Flow\\Parquet\\ParquetFileReader', 'Flow\\Parquet\\ParquetFileWriter', - 'Flow\\Arrow\\OutputStream', - 'Flow\\Arrow\\RandomAccessFile', ] as $name) { $class = new ReflectionClass($name); $interfaces[$name] = [ diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs deleted file mode 100644 index 687abfc424..0000000000 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/body.rs +++ /dev/null @@ -1,204 +0,0 @@ -//! The Floe BATCH frame body (`FrameEncoder` / `FrameDecoder`), Noop codec only: every stored buffer is prefixed with -//! the i64 -1. -//! -//! ```text -//! V rowCount, V nodeCount, V bufferCount, nodeCount × (V length, V nullCount), bufferCount × (V offset, V stored), -//! zero padding to 8, buffer area: per non-empty buffer the i64 prefix and its bytes, each zero padded to 8 -//! ``` - -use arrow_data::ArrayData; - -use crate::column; -use crate::error::Error; -use crate::format::{write_u32, Reader}; -use crate::kind::Kind; -use crate::layout::{buffer_count, node_count, nodes, null_count_of}; - -const RAW: i64 = -1; - -pub fn encode_body(columns: &[(Kind, ArrayData)], row_count: u32) -> Result, Error> { - let mut node_words = Vec::new(); - let mut extents = Vec::new(); - let mut area: Vec = Vec::new(); - let mut node_total: u32 = 0; - let mut buffer_total: u32 = 0; - - for (index, (kind, data)) in columns.iter().enumerate() { - if data.len() as u64 != row_count as u64 { - return Err(Error::ColumnRows { - column: index, - rows: data.len() as u64, - frame_rows: row_count as u64, - }); - } - - let buffers = column::encode(data, kind)?; - let buffers: Vec<&[u8]> = buffers.iter().map(Vec::as_slice).collect(); - let null_count = match kind { - Kind::Null => row_count, - _ => null_count_of(buffers[0], row_count)?, - }; - let column_nodes = if node_count(kind) == 1 { - vec![(row_count, null_count)] - } else { - nodes(kind, row_count, null_count, &buffers)? - }; - - for (length, nulls) in column_nodes { - write_u32(&mut node_words, length); - write_u32(&mut node_words, nulls); - node_total += 1; - } - - for buffer in buffers { - buffer_total += 1; - - if buffer.is_empty() { - write_u32(&mut extents, 0); - write_u32(&mut extents, 0); - - continue; - } - - write_u32(&mut extents, area.len() as u32); - write_u32(&mut extents, (8 + buffer.len()) as u32); - area.extend_from_slice(&RAW.to_le_bytes()); - area.extend_from_slice(buffer); - pad8(&mut area); - } - } - - let mut body = Vec::with_capacity(12 + node_words.len() + extents.len() + 8 + area.len()); - write_u32(&mut body, row_count); - write_u32(&mut body, node_total); - write_u32(&mut body, buffer_total); - body.extend_from_slice(&node_words); - body.extend_from_slice(&extents); - pad8(&mut body); - body.extend_from_slice(&area); - - if body.len() as u64 > u32::MAX as u64 { - return Err(Error::FrameTooLarge { - bytes: body.len() as u64, - }); - } - - Ok(body) -} - -/// `FrameDecoder::decode()`'s checks in its order, columns by index. Returns the row count and one array per kind. -pub fn decode_body(body: &[u8], kinds: &[Kind]) -> Result<(u32, Vec), Error> { - let mut directory = Reader::new(body); - let row_count = directory.u32()?; - let node_total = directory.u32()?; - let buffer_total = directory.u32()?; - let expected_nodes: usize = kinds.iter().map(node_count).sum(); - let expected_buffers: usize = kinds.iter().map(buffer_count).sum(); - - if node_total as u64 != expected_nodes as u64 { - return Err(Error::FrameNodeCount { - frame: node_total as u64, - schema: expected_nodes as u64, - }); - } - - if buffer_total as u64 != expected_buffers as u64 { - return Err(Error::FrameBufferCount { - frame: buffer_total as u64, - schema: expected_buffers as u64, - }); - } - - let words_len = 2 * (expected_nodes + expected_buffers); - let area_start = (12 + 4 * words_len).div_ceil(8) * 8; - - if body.len() < area_start { - return Err(Error::DirectoryTruncated); - } - - let words: Vec = (0..words_len).map(|_| directory.u32()).collect::>()?; - let area = &body[area_start..]; - let mut node = 0; - let mut extent = 2 * expected_nodes; - let mut buffer = 0; - let mut columns = Vec::with_capacity(kinds.len()); - - for (index, kind) in kinds.iter().enumerate() { - let length = words[2 * node]; - let null_count = words[2 * node + 1]; - - if length != row_count { - return Err(Error::ColumnRows { - column: index, - rows: length as u64, - frame_rows: row_count as u64, - }); - } - - if null_count > length { - return Err(Error::ColumnNulls { - column: index, - nulls: null_count as u64, - rows: length as u64, - }); - } - - let mut buffers: Vec<&[u8]> = Vec::with_capacity(buffer_count(kind)); - - for _ in 0..buffer_count(kind) { - let offset = words[extent] as usize; - let stored = words[extent + 1] as usize; - - if stored != 0 { - if offset as u64 + stored as u64 > area.len() as u64 { - return Err(Error::BufferOutsideArea { - buffer, - area: area.len() as u64, - }); - } - - if stored < 8 { - return Err(Error::BufferShorterThanPrefix { buffer }); - } - - let prefix = i64::from_le_bytes(area[offset..offset + 8].try_into().expect("8-byte slice")); - - if prefix != RAW { - return Err(Error::CompressedBuffer { buffer, prefix }); - } - - buffers.push(&area[offset + 8..offset + stored]); - } else { - buffers.push(&[]); - } - - buffer += 1; - extent += 2; - } - - let malformed = |error: Error| Error::MalformedColumn { - column: index, - error: Box::new(error), - }; - - if node_count(kind) == 1 { - node += 1; - } else { - for (derived_length, derived_nulls) in nodes(kind, length, null_count, &buffers).map_err(malformed)? { - if words[2 * node] != derived_length || words[2 * node + 1] != derived_nulls { - return Err(Error::NodesDisagree { column: index }); - } - - node += 1; - } - } - - columns.push(column::decode(kind, &buffers, row_count, null_count).map_err(malformed)?); - } - - Ok((row_count, columns)) -} - -fn pad8(bytes: &mut Vec) { - bytes.resize(bytes.len().div_ceil(8) * 8, 0); -} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/format.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/format.rs deleted file mode 100644 index 27d2d475ff..0000000000 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/format.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! Floe wire constants and a bounds-checked little-endian reader. The canonical definitions live in the pure-PHP -//! `Flow\Floe\Format`; mirror any change there. - -use crate::error::Error; - -pub const MAGIC: &[u8; 4] = b"FLOE"; -pub const VERSION: u8 = 0x02; - -pub const FRAME_BATCH: u8 = 0x05; -pub const FRAME_FOOTER: u8 = 0x06; - -pub struct Reader<'a> { - data: &'a [u8], - pos: usize, -} - -impl<'a> Reader<'a> { - pub fn new(data: &'a [u8]) -> Self { - Self { data, pos: 0 } - } - - pub fn is_eof(&self) -> bool { - self.pos >= self.data.len() - } - - fn take(&mut self, len: usize) -> Result<&'a [u8], Error> { - let end = self - .pos - .checked_add(len) - .filter(|end| *end <= self.data.len()) - .ok_or(Error::DirectoryTruncated)?; - let slice = &self.data[self.pos..end]; - self.pos = end; - - Ok(slice) - } - - pub fn u8(&mut self) -> Result { - Ok(self.take(1)?[0]) - } - - pub fn u32(&mut self) -> Result { - let bytes = self.take(4)?; - - Ok(u32::from_le_bytes(bytes.try_into().expect("4-byte slice"))) - } - - pub fn i64(&mut self) -> Result { - let bytes = self.take(8)?; - - Ok(i64::from_le_bytes(bytes.try_into().expect("8-byte slice"))) - } - - pub fn f64(&mut self) -> Result { - let bytes = self.take(8)?; - - Ok(f64::from_le_bytes(bytes.try_into().expect("8-byte slice"))) - } - - pub fn bytes(&mut self, len: usize) -> Result<&'a [u8], Error> { - self.take(len) - } -} - -pub fn write_u32(out: &mut Vec, value: u32) { - out.extend_from_slice(&value.to_le_bytes()); -} diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/src/lib.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/src/lib.rs index e4f6facd54..68d82efcc0 100644 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/src/lib.rs +++ b/src/extension/flow-php-ext/crates/flow-batch-frame/src/lib.rs @@ -1,17 +1,13 @@ //! Flow's batch layout in Rust: one column's buffers in the canonical form of `Flow\ETL\Column\Column::encode()` and -//! back (`column`), and the Floe BATCH frame body around them (`body`). The pure-PHP classes in flow-php/etl are the -//! reference; this crate holds no PHP types and no message text. -//! -//! arrow-ext will hold a copy of this crate: keep both copies identical. +//! back (`column`). The pure-PHP classes in flow-php/etl are the reference; this crate holds no PHP types and no message +//! text. // Floe is little-endian by construction; a big-endian host could never match its bytes. #[cfg(target_endian = "big")] compile_error!("flow-batch-frame only supports little-endian targets"); -pub mod body; pub mod column; pub mod error; -pub mod format; pub mod kind; pub mod layout; diff --git a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs b/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs deleted file mode 100644 index 7aa30e24ad..0000000000 --- a/src/extension/flow-php-ext/crates/flow-batch-frame/tests/body.rs +++ /dev/null @@ -1,202 +0,0 @@ -mod common; - -use std::sync::Arc; - -use arrow_array::builder::{BinaryBuilder, Int64Builder, MapBuilder, MapFieldNames}; -use arrow_array::types::Int64Type; -use arrow_array::{Array, BinaryArray, Int64Array, ListArray, NullArray, StructArray}; -use arrow_buffer::NullBuffer; -use arrow_data::ArrayData; -use common::{hex, unhex}; -use flow_batch_frame::body::{decode_body, encode_body}; -use flow_batch_frame::error::Error; -use flow_batch_frame::kind::{kind, Kind}; - -fn kind_of(type_json: &str) -> Kind { - kind(type_json.as_bytes()).expect("a valid type JSON") -} - -/// FrameContext::directory(): the counts, then every node and extent word. -fn directory(body: &[u8]) -> Vec { - let word = |i: usize| u32::from_le_bytes(body[i * 4..i * 4 + 4].try_into().expect("4-byte slice")); - - (0..3 + 2 * (word(1) + word(2)) as usize).map(word).collect() -} - -fn round_trips(body: &[u8], kinds: &[Kind]) { - let (row_count, arrays) = decode_body(body, kinds).expect("a decodable body"); - let columns: Vec<(Kind, ArrayData)> = kinds.iter().cloned().zip(arrays).collect(); - - assert_eq!( - body, - encode_body(&columns, row_count).expect("an encodable batch").as_slice() - ); -} - -fn worked_example() -> Vec<(Kind, ArrayData)> { - vec![ - ( - kind_of(r#"{"type":"integer"}"#), - Int64Array::from(vec![1, 2]).into_data(), - ), - ( - kind_of(r#"{"type":"string"}"#), - BinaryArray::from(vec![Some(b"ab".as_ref()), None]).into_data(), - ), - ] -} - -/// FrameEncoderTest.php:29-35. -#[test] -fn the_worked_example() { - let body = encode_body(&worked_example(), 2).expect("the worked example"); - - assert_eq!(152, body.len()); - assert_eq!( - "020000000200000005000000020000000000000002000000010000000000000000000000000000001800000018000000090000002800000014000000400000000a00000000000000ffffffffffffffff01000000000000000200000000000000ffffffffffffffff0100000000000000ffffffffffffffff00000000020000000200000000000000ffffffffffffffff6162000000000000", - hex(&body), - ); - round_trips(&body, &[worked_example()[0].0.clone(), worked_example()[1].0.clone()]); -} - -#[test] -fn a_list_with_a_null_slot() { - let kind = kind_of(r#"{"type":"list","element":{"type":"integer"}}"#); - let list = ListArray::from_iter_primitive::(vec![Some(vec![Some(1), Some(2)]), None]); - let body = encode_body(&[(kind.clone(), list.into_data())], 2).expect("a list batch"); - - assert_eq!(vec![2, 2, 4, 2, 1, 2, 0, 0, 9, 16, 20, 0, 0, 40, 24], directory(&body)); - round_trips(&body, &[kind]); -} - -#[test] -fn a_map_entries_node_and_extent() { - let kind = kind_of(r#"{"type":"map","key":{"type":"string"},"value":{"type":"integer"}}"#); - let mut map = MapBuilder::new( - Some(MapFieldNames { - entry: "entries".into(), - key: "key".into(), - value: "value".into(), - }), - BinaryBuilder::new(), - Int64Builder::new(), - ); - - for row in [vec![("a", 1)], vec![("b", 2), ("c", 3)]] { - for (key, value) in row { - map.keys().append_value(key.as_bytes()); - map.values().append_value(value); - } - - map.append(true).expect("a map row"); - } - - let body = encode_body(&[(kind.clone(), map.finish().into_data())], 2).expect("a map batch"); - - assert_eq!( - vec![2, 4, 8, 2, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 20, 0, 0, 0, 0, 24, 24, 48, 11, 0, 0, 64, 32], - directory(&body), - ); - round_trips(&body, &[kind]); -} - -#[test] -fn a_structure_with_a_null_parent() { - let kind = kind_of(r#"{"type":"structure_v2","fields":[{"name":"a","type":{"type":"integer"}}]}"#); - let structure = StructArray::try_new( - vec![Arc::new(arrow_schema::Field::new( - "a", - arrow_schema::DataType::Int64, - true, - ))] - .into(), - vec![Arc::new(Int64Array::from(vec![1, 5]))], - Some(NullBuffer::from(vec![true, false])), - ) - .expect("a valid struct"); - let body = encode_body(&[(kind.clone(), structure.into_data())], 2).expect("a structure batch"); - - assert_eq!(vec![2, 2, 3, 2, 1, 2, 1, 0, 9, 16, 9, 32, 24], directory(&body)); - round_trips(&body, &[kind]); -} - -#[test] -fn a_null_column_has_a_full_null_node_and_no_extent() { - let kind = kind_of(r#"{"type":"null"}"#); - let body = encode_body(&[(kind.clone(), NullArray::new(2).into_data())], 2).expect("a null batch"); - - assert_eq!("020000000100000000000000020000000200000000000000", hex(&body)); - round_trips(&body, &[kind]); -} - -#[test] -fn a_batch_without_columns_keeps_its_row_count() { - let body = encode_body(&[], 3).expect("a zero-column batch"); - - assert_eq!("03000000000000000000000000000000", hex(&body)); - round_trips(&body, &[]); -} - -#[test] -fn encode_refuses_a_column_of_another_length() { - assert!(matches!( - encode_body(&worked_example(), 3), - Err(Error::ColumnRows { - column: 0, - rows: 2, - frame_rows: 3 - }), - )); -} - -#[test] -fn decode_refuses_a_malformed_body() { - let kinds = [kind_of(r#"{"type":"integer"}"#), kind_of(r#"{"type":"string"}"#)]; - let body = encode_body(&worked_example(), 2).expect("the worked example"); - let with = |at: usize, bytes: &[u8]| { - let mut corrupt = body.clone(); - corrupt[at..at + bytes.len()].copy_from_slice(bytes); - corrupt - }; - - assert!(matches!( - decode_body(&body[..11], &kinds), - Err(Error::DirectoryTruncated) - )); - assert!(matches!( - decode_body(&body[..40], &kinds), - Err(Error::DirectoryTruncated) - )); - assert!(matches!( - decode_body(&body, &kinds[..1]), - Err(Error::FrameNodeCount { frame: 2, schema: 1 }), - )); - assert!(matches!( - decode_body(&with(12, &unhex("03000000")), &kinds), - Err(Error::ColumnRows { - column: 0, - rows: 3, - frame_rows: 2 - }), - )); - assert!(matches!( - decode_body(&with(24, &unhex("03000000")), &kinds), - Err(Error::ColumnNulls { - column: 1, - nulls: 3, - rows: 2 - }), - )); - assert!(matches!( - decode_body(&with(72, &unhex("0000000000000000")), &kinds), - Err(Error::CompressedBuffer { buffer: 1, prefix: 0 }), - )); - assert!(matches!( - decode_body(&with(36, &unhex("ff000000")), &kinds), - Err(Error::BufferOutsideArea { buffer: 1, area: 80 }), - )); - assert!(matches!( - decode_body(&with(24, &unhex("00000000")), &kinds), - Err(Error::MalformedColumn { column: 1, .. }), - )); -} diff --git a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJSONEncoder.php b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJsonEncoder.php similarity index 82% rename from src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJSONEncoder.php rename to src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJsonEncoder.php index df176d2aa3..09f3c63807 100644 --- a/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJSONEncoder.php +++ b/src/extension/flow-php-ext/php/Flow/ETL/Adapter/JSON/RustJsonEncoder.php @@ -14,14 +14,14 @@ return; } -final class RustJSONEncoder implements JSONEncoder +final class RustJsonEncoder implements JsonEncoder { /** - * @param PhpJSONEncoder $php renders the columns this writer does not render itself + * @param PhpJsonEncoder $php renders the columns this writer does not render itself * * @throws InvalidArgumentException a flag outside JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION */ - public function __construct(int $flags, string $dateTimeFormat, string $dateFormat, PhpJSONEncoder $php) + public function __construct(int $flags, string $dateTimeFormat, string $dateFormat, PhpJsonEncoder $php) { throw new RuntimeException('flow_php extension is not loaded'); } diff --git a/src/extension/flow-php-ext/src/builder.rs b/src/extension/flow-php-ext/src/builder.rs index 06463e724b..277b021658 100644 --- a/src/extension/flow-php-ext/src/builder.rs +++ b/src/extension/flow-php-ext/src/builder.rs @@ -2,6 +2,10 @@ //! where `cast.rs` casts it natively; every other value, and every value the native lane refuses, runs PHP's //! `$type->cast()` then `$physical->toPhysical()`, so results and refusals are PHP's own. +// `appendPhysicals()`'s `$nullCount`: ext-php-rs names a PHP parameter after its Rust identifier and binds it in a +// generated handler, which an `allow` on the method, the impl block or the parameter does not reach +#![allow(non_snake_case)] + use std::rc::Rc; use arrow_array::Array; @@ -535,6 +539,31 @@ impl RustColumnBuilder { result } + /// `ColumnBuilder::appendPhysicals()`: physical values as they are. A null under NOT NULL is refused at its + /// position, a physical of another kind as `append_physical()` refuses it; `$nullCount` is the PHP builders' hint, + /// this builder counts nulls as it appends. + #[php(name = "appendPhysicals")] + pub fn append_physicals(&mut self, physicals: &ZendHashTable, nullCount: Option) -> PhpResult<()> { + let _ = nullCount; + let start = self.values.len(); + let result = ht_for_each(physicals, |_, index, physical| { + if physical.is_null() && !self.nullable { + return Err(schema_mismatch( + zval_long(index as i64), + value_does_not_match(&self.definition, null_zval(), None)?, + )); + } + + append_physical(&mut self.values, &self.plan.kind, physical) + }); + + if result.is_err() { + self.values.truncate(start); + } + + result + } + #[php(name = "appendFrom")] pub fn append_from(&mut self, column: &Zval, i: i64) -> PhpResult<()> { if let Some(native) = self.same_kind(column) { diff --git a/src/extension/flow-php-ext/src/column.rs b/src/extension/flow-php-ext/src/column.rs index 315b08a714..8b1f7f5c30 100644 --- a/src/extension/flow-php-ext/src/column.rs +++ b/src/extension/flow-php-ext/src/column.rs @@ -111,7 +111,7 @@ fn base(type_zv: Zval) -> Result { /// structure element refuses the rows its optional one left absent. fn retype(from: Zval, to: Zval, array: &ArrayRef, kind: &Kind) -> Result<(), PhpException> { call_method( - &instance("Flow\\ETL\\Column\\Php\\Retype")?, + &instance("Flow\\ETL\\Column\\Retype")?, "assert", &mut [ from.shallow_clone(), diff --git a/src/extension/flow-php-ext/src/csv/mod.rs b/src/extension/flow-php-ext/src/csv/mod.rs index 0d99539bf3..534a4f614a 100644 --- a/src/extension/flow-php-ext/src/csv/mod.rs +++ b/src/extension/flow-php-ext/src/csv/mod.rs @@ -1,5 +1,5 @@ //! Native CSV reading: records and fields from `tokenizer`, rows shaped exactly like -//! `CSVEncoder::decode()` + `CSVRowNormalizer::normalize()` shape them. +//! `CSVDecoder::decode()` (`Flow\ETL\Extractor\Records`) shapes them. pub mod columns; pub mod fold; @@ -146,7 +146,7 @@ impl CsvReader { ) } - /// The current row's cell of `field`, as `CSVRowNormalizer::normalize()` shapes it; `None` is null. + /// The current row's cell of `field`, as `Records::decode()` shapes it; `None` is null. pub fn cell(&self, field: usize) -> Option<&[u8]> { cell_value(&self.record, field, self.empty_to_null) } @@ -232,7 +232,7 @@ impl CsvReader { Ok(folded) } - /// `CSVEncoder::decode()`'s first line: the header when `withHeader`, else `e00, e01, ...` sized by + /// `Records::decode()`'s first record: the header when `withHeader`, else `e00, e01, ...` sized by /// the first record, which then stays pending as the first row. fn resolve_headers(&mut self) { if self.headers.is_some() || !self.tokenizer.next(&mut self.record) { @@ -299,17 +299,17 @@ fn next_row( true } -/// `CSVRowNormalizer::normalize()` for one cell: padding past the record's end, `emptyToNull`; `None` is null. +/// `Records::decode()` for one cell: a cell past the record's end is null, a present `''` is null under `emptyToNull`; +/// `None` is null. fn cell_value(record: &Record, index: usize, empty_to_null: bool) -> Option<&[u8]> { match record.field(index) { Field::Value(value) if !(empty_to_null && value.is_empty()) => Some(value), - Field::Value(_) | Field::Null => None, - Field::Missing if empty_to_null => None, - Field::Missing => Some(b""), + Field::Value(_) | Field::Null | Field::Missing => None, } } -/// `array_combine($headers, $normalizer->normalize($fields, count($headers)))`. +/// `Records::decode()` for one record: one value per header, a duplicated header keeps its first position and its +/// last value. fn row_values(headers: &[Header], record: &Record, empty_to_null: bool) -> Zval { let mut values = ZendHashTable::with_capacity(headers.len() as u32); diff --git a/src/extension/flow-php-ext/src/interfaces.rs b/src/extension/flow-php-ext/src/interfaces.rs index bdf65485e5..d98a248442 100644 --- a/src/extension/flow-php-ext/src/interfaces.rs +++ b/src/extension/flow-php-ext/src/interfaces.rs @@ -110,7 +110,7 @@ pub fn csv_encoder_ce() -> &'static ClassEntry { } pub fn json_encoder_ce() -> &'static ClassEntry { - load(&JSON_ENCODER_CE, "Flow\\ETL\\Adapter\\JSON\\JSONEncoder") + load(&JSON_ENCODER_CE, "Flow\\ETL\\Adapter\\JSON\\JsonEncoder") } pub fn csv_open_source_ce() -> &'static ClassEntry { @@ -178,6 +178,15 @@ pub fn register() -> Result<()> { vec![ method("append", vec![Arg::new("value", DataType::Mixed)], DataType::Void), method("appendMany", vec![Arg::new("values", DataType::Array)], DataType::Void), + method( + "appendPhysicals", + vec![ + Arg::new("physicals", DataType::Array), + Arg::new("nullCount", DataType::Long).allow_null().default("null"), + ], + DataType::Void, + ) + .required_args(1), method( "appendFrom", vec![Arg::new("column", COLUMN), Arg::new("i", DataType::Long)], @@ -245,7 +254,7 @@ pub fn register() -> Result<()> { ], )?; interface( - "Flow\\ETL\\Adapter\\JSON\\JSONEncoder", + "Flow\\ETL\\Adapter\\JSON\\JsonEncoder", store_json_encoder, vec![method( "encode", diff --git a/src/extension/flow-php-ext/src/json/write.rs b/src/extension/flow-php-ext/src/json/write.rs index e44b5fafd3..b36d6c8886 100644 --- a/src/extension/flow-php-ext/src/json/write.rs +++ b/src/extension/flow-php-ext/src/json/write.rs @@ -1,5 +1,5 @@ -//! `Flow\ETL\Adapter\JSON\RustJSONEncoder`: a `Rows` batch as the text `PhpJSONEncoder::encode()` returns, rendered -//! from the arrow arrays; the columns it does not render are the fragments the held `PhpJSONEncoder::fragments()` +//! `Flow\ETL\Adapter\JSON\RustJsonEncoder`: a `Rows` batch as the text `PhpJsonEncoder::encode()` returns, rendered +//! from the arrow arrays; the columns it does not render are the fragments the held `PhpJsonEncoder::fragments()` //! produces. use ext_php_rs::binary::Binary; @@ -32,20 +32,20 @@ enum Cells<'a> { #[php_class] #[php( - name = "Flow\\ETL\\Adapter\\JSON\\RustJSONEncoder", + name = "Flow\\ETL\\Adapter\\JSON\\RustJsonEncoder", flags = ClassFlags::Final, - implements(ce = json_encoder_ce, stub = "Flow\\ETL\\Adapter\\JSON\\JSONEncoder") + implements(ce = json_encoder_ce, stub = "Flow\\ETL\\Adapter\\JSON\\JsonEncoder") )] -pub struct RustJSONEncoder { +pub struct RustJsonEncoder { flags: Flags, formats: Formats, - /// The `PhpJSONEncoder` that renders the unrendered columns. + /// The `PhpJsonEncoder` that renders the unrendered columns. php: Zval, unrendered: Unrendered, } #[php_impl] -impl RustJSONEncoder { +impl RustJsonEncoder { pub fn __construct( flags: i64, date_time_format: BinarySlice, @@ -84,8 +84,8 @@ impl RustJSONEncoder { } } -impl RustJSONEncoder { - /// `$fragments`: `PhpJSONEncoder::fragments()` of the unrendered columns. +impl RustJsonEncoder { + /// `$fragments`: `PhpJsonEncoder::fragments()` of the unrendered columns. fn render_rows(&self, rows: &Zval, fragments: &ZendHashTable, separator: &[u8]) -> PhpResult> { let batch = batch(rows, &self.formats, false)?; let mut keys = Vec::with_capacity(batch.columns.len()); diff --git a/src/extension/flow-php-ext/src/lib.rs b/src/extension/flow-php-ext/src/lib.rs index 1a1a61046e..63a3aa03df 100644 --- a/src/extension/flow-php-ext/src/lib.rs +++ b/src/extension/flow-php-ext/src/lib.rs @@ -63,7 +63,7 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { .class::() .class::() .class::() - .class::() + .class::() .class::() .class::() .class::() diff --git a/src/extension/flow-php-ext/src/plan.rs b/src/extension/flow-php-ext/src/plan.rs index 3344b2c07c..fe5bc01ab4 100644 --- a/src/extension/flow-php-ext/src/plan.rs +++ b/src/extension/flow-php-ext/src/plan.rs @@ -13,8 +13,8 @@ use crate::cast::{build_cast_kind, CastKind}; use crate::ctx::{self, call_handle, call_method, ce_method_ref, expect_object, find_class, instance}; use crate::exception::{ext_exception, json_exception}; -const PHYSICAL_FOR: &str = "Flow\\ETL\\Column\\Php\\PhysicalFor"; -const IDENTITY: &str = "Flow\\ETL\\Column\\Php\\IdentityPhysical"; +const PHYSICAL_FOR: &str = "Flow\\ETL\\Column\\Physical\\PhysicalFor"; +const IDENTITY: &str = "Flow\\ETL\\Column\\Physical\\IdentityPhysical"; pub struct TypePlan { pub kind: Kind, @@ -126,10 +126,10 @@ fn value_node(parsed: &TypeJson) -> Result { .to_vec(), ), "timezone" => ValueNode::TimeZone, - "xml" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Php\\XmlDocumentPhysical")?), - "xml_element" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Php\\XmlElementPhysical")?), - "html" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Php\\HtmlDocumentPhysical")?), - "html_element" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Php\\HtmlElementPhysical")?), + "xml" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Physical\\XmlDocumentPhysical")?), + "xml_element" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Physical\\XmlElementPhysical")?), + "html" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Physical\\HtmlDocumentPhysical")?), + "html_element" => ValueNode::Markup(instance("Flow\\ETL\\Column\\Physical\\HtmlElementPhysical")?), "null" => ValueNode::Null, "list" => ValueNode::List(child(parsed.element())?), "map" => ValueNode::Map(child(parsed.value())?), diff --git a/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt b/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt index ea9d65f24a..99e3f72c53 100644 --- a/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt +++ b/src/extension/flow-php-ext/tests/phpt/001_extension_loaded.phpt @@ -22,9 +22,9 @@ interface Flow\ETL\Adapter\CSV\CSVEncoder interface Flow\ETL\Adapter\CSV\CSVOpenSource class Flow\ETL\Adapter\CSV\RustCSVEncoder implements Flow\ETL\Adapter\CSV\CSVEncoder class Flow\ETL\Adapter\CSV\RustCSVOpenSource implements Flow\ETL\Adapter\CSV\CSVOpenSource -interface Flow\ETL\Adapter\JSON\JSONEncoder +interface Flow\ETL\Adapter\JSON\JsonEncoder interface Flow\ETL\Adapter\JSON\JsonOpenSource -class Flow\ETL\Adapter\JSON\RustJSONEncoder implements Flow\ETL\Adapter\JSON\JSONEncoder +class Flow\ETL\Adapter\JSON\RustJsonEncoder implements Flow\ETL\Adapter\JSON\JsonEncoder class Flow\ETL\Adapter\JSON\RustJsonOpenSource implements Flow\ETL\Adapter\JSON\JsonOpenSource interface Flow\ETL\Adapter\Parquet\ParquetOpenSink interface Flow\ETL\Adapter\Parquet\ParquetOpenSource diff --git a/src/extension/flow-php-ext/tests/phpt/044_csv_ragged_rows.phpt b/src/extension/flow-php-ext/tests/phpt/044_csv_ragged_rows.phpt index c447a601d0..32474af62a 100644 --- a/src/extension/flow-php-ext/tests/phpt/044_csv_ragged_rows.phpt +++ b/src/extension/flow-php-ext/tests/phpt/044_csv_ragged_rows.phpt @@ -1,5 +1,5 @@ --TEST-- -native CSV rows pad and truncate to the header like CSVRowNormalizer, under both emptyToNull settings +native CSV rows pad and truncate to the header like Records, under both emptyToNull settings --SKIPIF-- --FILE-- diff --git a/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt b/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt index 794047b9ed..38e2798bbf 100644 --- a/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/057_native_encode_parity.phpt @@ -24,10 +24,10 @@ $projection = schema($schema->get('uuid'), $schema->get('int'), $schema->get('st $frame('all types', $php, $native); $frame('slice', $php->slice(3, 3), $native->slice(3, 3)); $frame('gather', $php->gather([5, 0, 3, 3]), $native->gather([5, 0, 3, 3])); -$frame('concat', $php->concat($php->slice(1, 2)), $native->concat($native->slice(1, 2))); -$frame('project', $php->project($projection), $native->project($projection)); +$frame('concat', $php->concat(new PhpBackend(), $php->slice(1, 2)), $native->concat(new RustBackend(), $native->slice(1, 2))); +$frame('project', $php->project($projection, new Flow\ETL\Column\PhpBackend()), $native->project($projection, new Flow\ETL\Column\RustBackend())); $frame('withSchema', $php->withSchema(all_types_schema('UTC')), $native->withSchema(all_types_schema('UTC'))); -$frame('mixed', $php, $php->concat($native)->slice(0, $php->count())); +$frame('mixed', $php, $php->concat(new PhpBackend(), $native)->slice(0, $php->count())); $body = $php->encodeFrame(); $decodedPhp = (new FrameDecoder())->decode($body, $schema, new PhpBackend()); diff --git a/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt b/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt index 6c9cef8ae1..8053c0958b 100644 --- a/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt +++ b/src/extension/flow-php-ext/tests/phpt/061_native_mixed_class_building.phpt @@ -40,8 +40,8 @@ $rebuilt = static function (Rows $from, object $backend, bool $take) use ($schem $same('native appendTake of a PHP column', $php->gather([5, 0, 3, 3]), $rebuilt($php, new RustBackend(), true)); $same('native appendFrom of a PHP column', $php->gather([5, 0, 3, 3]), $rebuilt($php, new RustBackend(), false)); $same('PHP appendTake of a native column', $php->gather([5, 0, 3, 3]), $rebuilt($native, new PhpBackend(), true)); -$same('Rows::concat PHP + native', $php->concat($php), $php->concat($native)); -$same('Rows::concat native + PHP', $php->concat($php), $native->concat($php)); +$same('Rows::concat PHP + native', $php->concat(new PhpBackend(), $php), $php->concat(new RustBackend(), $native)); +$same('Rows::concat native + PHP', $php->concat(new PhpBackend(), $php), $native->concat(new PhpBackend(), $php)); $same('Rows::gather over both', $php->gather([1, 4]), $native->gather([1, 4])); foreach ($schema->definitions() as $name => $definition) { diff --git a/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt b/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt index cc727dcfd9..a57c2c4a34 100644 --- a/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt +++ b/src/extension/flow-php-ext/tests/phpt/067_adopt_refuses_untyped_column.phpt @@ -7,7 +7,7 @@ RustBackend::adopt() refuses an untyped (mixed) column with the PHP wording require __DIR__ . '/bootstrap.php'; use Flow\ETL\Column\RustBackend; -use Flow\ETL\Column\Php\ValueColumn; +use Flow\ETL\Column\ValueColumn; use Flow\ETL\Column\PhpBackend; use function Flow\ETL\DSL\int_schema; diff --git a/src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt b/src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt index 2114b59588..1a9802e3f2 100644 --- a/src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/077_text_float_parity.phpt @@ -9,8 +9,8 @@ require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\CSV\PhpCSVEncoder; use Flow\ETL\Adapter\CSV\CSVWriteOptions; use Flow\ETL\Adapter\CSV\RustCSVEncoder; -use Flow\ETL\Adapter\JSON\PhpJSONEncoder; -use Flow\ETL\Adapter\JSON\RustJSONEncoder; +use Flow\ETL\Adapter\JSON\PhpJsonEncoder; +use Flow\ETL\Adapter\JSON\RustJsonEncoder; use function Flow\ETL\DSL\float_schema; use function Flow\ETL\DSL\schema; @@ -41,16 +41,16 @@ foreach (['-1', '17'] as $precision) { printf("serialize_precision %s: csv %s, %d values\n", $precision, $php === $native ? 'identical' : 'DIFFERENT', substr_count($native, "\n")); foreach ([JSON_THROW_ON_ERROR, JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION] as $flags) { - $json = new RustJSONEncoder($flags, DATE_ATOM, 'Y-m-d', new PhpJSONEncoder($flags)); - $php = implode("\n", array_map(static fn(Flow\ETL\Rows $batch): string => (new PhpJSONEncoder($flags))->encode($batch, "\n"), $rows(php_rows(...), $finite))); + $json = new RustJsonEncoder($flags, DATE_ATOM, 'Y-m-d', new PhpJsonEncoder($flags)); + $php = implode("\n", array_map(static fn(Flow\ETL\Rows $batch): string => (new PhpJsonEncoder($flags))->encode($batch, "\n"), $rows(php_rows(...), $finite))); $native = implode("\n", array_map(static fn(Flow\ETL\Rows $batch): string => $json->encode($batch, "\n"), $rows(native_rows(...), $finite))); printf("serialize_precision %s: json flags %d %s, %d values\n", $precision, $flags, $php === $native ? 'identical' : 'DIFFERENT', substr_count($native, "\n") + 1); } foreach ([NAN, INF, -INF] as $float) { $values = [['f' => 1.5], ['f' => $float]]; - $php = written(static fn() => (new PhpJSONEncoder())->encode(php_rows($schema, $values), "\n")); - $native = written(static fn() => (new RustJSONEncoder(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d', new PhpJSONEncoder()))->encode(native_rows($schema, $values), "\n")); + $php = written(static fn() => (new PhpJsonEncoder())->encode(php_rows($schema, $values), "\n")); + $native = written(static fn() => (new RustJsonEncoder(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d', new PhpJsonEncoder()))->encode(native_rows($schema, $values), "\n")); printf("json %s: %s\n", var_export($float, true), $php === $native ? $php : 'DIFFERENT'); } diff --git a/src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt b/src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt index 8cc6723ae4..2ff5ccd911 100644 --- a/src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/078_text_json_string_parity.phpt @@ -6,8 +6,8 @@ The native JSON writer escapes a string as json_encode() does: random valid and --FILE-- @@ -8,8 +8,8 @@ require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\JSON\JsonFraming; use Flow\ETL\Adapter\JSON\JsonOpenSink; -use Flow\ETL\Adapter\JSON\RustJSONEncoder; -use Flow\ETL\Adapter\JSON\PhpJSONEncoder; +use Flow\ETL\Adapter\JSON\RustJsonEncoder; +use Flow\ETL\Adapter\JSON\PhpJsonEncoder; use Flow\Filesystem\DestinationStream; mt_srand(81); @@ -30,12 +30,12 @@ for ($i = 0; $i < 2_000; $i++) { $framing = JsonFraming::cases()[mt_rand(0, 2)]; $dateTimeFormat = $dateTimeFormats[mt_rand(0, count($dateTimeFormats) - 1)]; $dateFormat = $dateFormats[mt_rand(0, count($dateFormats) - 1)]; - $recorder = new RecordingPhpJSONEncoder(new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat)); - $writer = new RustJSONEncoder($flags, $dateTimeFormat, $dateFormat, $recorder); + $recorder = new RecordingPhpJsonEncoder(new PhpJsonEncoder($flags, $dateTimeFormat, $dateFormat)); + $writer = new RustJsonEncoder($flags, $dateTimeFormat, $dateFormat, $recorder); $half = intdiv(count($rows), 2); $php = written(static function (DestinationStream $stream) use ($schema, $rows, $flags, $dateTimeFormat, $dateFormat, $framing, $half): void { - $sink = new JsonOpenSink($stream, new PhpJSONEncoder($flags, $dateTimeFormat, $dateFormat), $framing); + $sink = new JsonOpenSink($stream, new PhpJsonEncoder($flags, $dateTimeFormat, $dateFormat), $framing); $sink->write(php_rows($schema, array_slice($rows, 0, $half))); $sink->write(php_rows($schema, array_slice($rows, $half))); $sink->close(); diff --git a/src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt b/src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt index 6b015e3084..2112c6bf1f 100644 --- a/src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt +++ b/src/extension/flow-php-ext/tests/phpt/082_write_no_leaks.phpt @@ -9,8 +9,8 @@ require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\CSV\CSVWriteOptions; use Flow\ETL\Adapter\CSV\RustCSVEncoder; use Flow\ETL\Adapter\CSV\PhpCSVEncoder; -use Flow\ETL\Adapter\JSON\RustJSONEncoder; -use Flow\ETL\Adapter\JSON\PhpJSONEncoder; +use Flow\ETL\Adapter\JSON\RustJsonEncoder; +use Flow\ETL\Adapter\JSON\PhpJsonEncoder; use Flow\ETL\Column\RustBackend; use function Flow\ETL\DSL\float_schema; @@ -29,7 +29,7 @@ $refusedSchema = schema(str_schema('s'), float_schema('f'), list_schema('l', typ $refused = native_rows($refusedSchema, [['s' => "\xff", 'f' => NAN, 'l' => [INF]]]); $dateTimeFormat = 'Y-m-d\TH:i:s.uP T'; $csv = new RustCSVEncoder(',', '"', '\\', "\n", $dateTimeFormat, 'Y-m-d', new PhpCSVEncoder(new CSVWriteOptions(newLineSeparator: "\n", dateTimeFormat: $dateTimeFormat))); -$json = new RustJSONEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', new PhpJSONEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat)); +$json = new RustJsonEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', new PhpJsonEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat)); // stand-ins for the held encoder: a cell list of the wrong length, and an encoder that throws $short = new class { public function cells(): array @@ -59,17 +59,17 @@ $cycle = static function () use ($schema, $jsonSchema, $native, $php, $refused, $csv->encode($native); // PHP columns are adopted for the encode and freed after it $csv->encode($php); - $json->encode($native->project($jsonSchema), "\n"); - $json->encode($php->project($jsonSchema), ','); + $json->encode($native->project($jsonSchema, new Flow\ETL\Column\RustBackend()), "\n"); + $json->encode($php->project($jsonSchema, new Flow\ETL\Column\PhpBackend()), ','); foreach ([ static fn() => $csv->encode($refused), static fn() => $json->encode($refused, "\n"), static fn() => $json->encode($native, "\n"), static fn() => (new RustCSVEncoder(',', '"', '\\', "\n", $dateTimeFormat, 'Y-m-d', $short))->encode($native), - static fn() => (new RustJSONEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', $short))->encode($native->project($jsonSchema), "\n"), + static fn() => (new RustJsonEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', $short))->encode($native->project($jsonSchema, new Flow\ETL\Column\RustBackend()), "\n"), static fn() => (new RustCSVEncoder(',', '"', '\\', "\n", $dateTimeFormat, 'Y-m-d', $throwing))->encode($native), - static fn() => (new RustJSONEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', $throwing))->encode($native->project($jsonSchema), "\n"), + static fn() => (new RustJsonEncoder(JSON_THROW_ON_ERROR, $dateTimeFormat, 'Y-m-d', $throwing))->encode($native->project($jsonSchema, new Flow\ETL\Column\RustBackend()), "\n"), ] as $refusal) { try { $refusal(); diff --git a/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt b/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt index eff6c82344..7a418d5980 100644 --- a/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt +++ b/src/extension/flow-php-ext/tests/phpt/086_json_read_parity.phpt @@ -9,7 +9,7 @@ require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\JSON\JSONMachine\{JsonFileReader, JsonFormat}; use Flow\ETL\Adapter\JSON\{PhpJsonOpenSource, RustJsonOpenSource}; use Flow\ETL\Column\{RustBackend, RustColumn, PhpBackend}; -use Flow\ETL\Extractor\SourceFile; +use Flow\ETL\Extractor\File\SourceFile; use Flow\ETL\{Rows, Schema}; use Flow\Filesystem\Stream\StringSourceStream; diff --git a/src/extension/flow-php-ext/tests/phpt/093_adapter_writers_contracts.phpt b/src/extension/flow-php-ext/tests/phpt/093_adapter_writers_contracts.phpt index 3ae2b91508..7bdcb32419 100644 --- a/src/extension/flow-php-ext/tests/phpt/093_adapter_writers_contracts.phpt +++ b/src/extension/flow-php-ext/tests/phpt/093_adapter_writers_contracts.phpt @@ -1,5 +1,5 @@ --TEST-- -RustCSVEncoder / RustJSONEncoder implement CSVEncoder / JSONEncoder: unrendered columns through the held PHP encoder's cells() / fragments(), the cache refreshed on a new Schema, the PHP header; RustParquetOpenSink implements ParquetOpenSink +RustCSVEncoder / RustJsonEncoder implement CSVEncoder / JsonEncoder: unrendered columns through the held PHP encoder's cells() / fragments(), the cache refreshed on a new Schema, the PHP header; RustParquetOpenSink implements ParquetOpenSink --SKIPIF-- --FILE-- @@ -10,9 +10,9 @@ use Flow\ETL\Adapter\CSV\CSVEncoder; use Flow\ETL\Adapter\CSV\CSVWriteOptions; use Flow\ETL\Adapter\CSV\RustCSVEncoder; use Flow\ETL\Adapter\CSV\PhpCSVEncoder; -use Flow\ETL\Adapter\JSON\JSONEncoder; -use Flow\ETL\Adapter\JSON\RustJSONEncoder; -use Flow\ETL\Adapter\JSON\PhpJSONEncoder; +use Flow\ETL\Adapter\JSON\JsonEncoder; +use Flow\ETL\Adapter\JSON\RustJsonEncoder; +use Flow\ETL\Adapter\JSON\PhpJsonEncoder; use Flow\ETL\Adapter\Parquet\RustParquetOpenSink; use Flow\ETL\Adapter\Parquet\ParquetOpenSink; @@ -23,10 +23,10 @@ use function Flow\ETL\DSL\xml_schema; $csvPhp = new PhpCSVEncoder(new CSVWriteOptions(newLineSeparator: "\n")); $csv = new RustCSVEncoder(',', '"', '\\', "\n", DATE_ATOM, 'Y-m-d', $csvPhp); -$jsonPhp = new PhpJSONEncoder(); -$json = new RustJSONEncoder(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d', $jsonPhp); +$jsonPhp = new PhpJsonEncoder(); +$json = new RustJsonEncoder(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d', $jsonPhp); -var_dump($csv instanceof CSVEncoder, $json instanceof JSONEncoder, (new ReflectionClass(RustParquetOpenSink::class))->implementsInterface(ParquetOpenSink::class)); +var_dump($csv instanceof CSVEncoder, $json instanceof JsonEncoder, (new ReflectionClass(RustParquetOpenSink::class))->implementsInterface(ParquetOpenSink::class)); $plain = schema(int_schema('id')); $values = [['id' => 1, 'doc' => '1'], ['id' => 2, 'doc' => '']]; @@ -35,11 +35,11 @@ $jsonDoc = schema(int_schema('id'), json_schema('doc')); $jsonValues = [['id' => 1, 'doc' => '{"a":1}'], ['id' => 2, 'doc' => '[1,2]']]; $csvRecorder = new RecordingPhpCSVEncoder($csvPhp); -$jsonRecorder = new RecordingPhpJSONEncoder($jsonPhp); +$jsonRecorder = new RecordingPhpJsonEncoder($jsonPhp); $xmlRows = native_rows($xml, $values); $jsonRows = native_rows($jsonDoc, $jsonValues); (new RustCSVEncoder(',', '"', '\\', "\n", DATE_ATOM, 'Y-m-d', $csvRecorder))->encode($xmlRows); -(new RustJSONEncoder(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d', $jsonRecorder))->encode($jsonRows, "\n"); +(new RustJsonEncoder(JSON_THROW_ON_ERROR, DATE_ATOM, 'Y-m-d', $jsonRecorder))->encode($jsonRows, "\n"); echo json_encode([recorded_names($csvRecorder->columns, $xmlRows), recorded_names($jsonRecorder->columns, $jsonRows)]), "\n"; // the first batch caches a Schema without unrendered columns; a new Schema object must refresh it diff --git a/src/extension/flow-php-ext/tests/phpt/096_encoders_columns_left_to_php.phpt b/src/extension/flow-php-ext/tests/phpt/096_encoders_columns_left_to_php.phpt index 7995058b64..7c815b1f02 100644 --- a/src/extension/flow-php-ext/tests/phpt/096_encoders_columns_left_to_php.phpt +++ b/src/extension/flow-php-ext/tests/phpt/096_encoders_columns_left_to_php.phpt @@ -1,5 +1,5 @@ --TEST-- -RustCSVEncoder / RustJSONEncoder render natively what they can and leave the rest, by column, to the held PHP encoder's cells() / fragments() +RustCSVEncoder / RustJsonEncoder render natively what they can and leave the rest, by column, to the held PHP encoder's cells() / fragments() --SKIPIF-- --FILE-- @@ -7,7 +7,7 @@ RustCSVEncoder / RustJSONEncoder render natively what they can and leave the res require __DIR__ . '/bootstrap.php'; use Flow\ETL\Adapter\CSV\{CSVWriteOptions, PhpCSVEncoder, RustCSVEncoder}; -use Flow\ETL\Adapter\JSON\{PhpJSONEncoder, RustJSONEncoder}; +use Flow\ETL\Adapter\JSON\{PhpJsonEncoder, RustJsonEncoder}; use Flow\ETL\Tests\Context\TextWriterBatches; $cases = [ @@ -26,9 +26,9 @@ foreach ($cases as [$batch, $format]) { [$schema, $values] = TextWriterBatches::of($batch); $rows = native_rows($schema, $values); $csv = new RecordingPhpCSVEncoder(new PhpCSVEncoder(new CSVWriteOptions(dateTimeFormat: $format, dateFormat: $format))); - $json = new RecordingPhpJSONEncoder(new PhpJSONEncoder(JSON_THROW_ON_ERROR, $format, $format)); + $json = new RecordingPhpJsonEncoder(new PhpJsonEncoder(JSON_THROW_ON_ERROR, $format, $format)); (new RustCSVEncoder(',', '"', '\\', "\n", $format, $format, $csv))->encode($rows); - (new RustJSONEncoder(JSON_THROW_ON_ERROR, $format, $format, $json))->encode($rows, "\n"); + (new RustJsonEncoder(JSON_THROW_ON_ERROR, $format, $format, $json))->encode($rows, "\n"); echo "{$batch} ({$format}): csv ", json_encode(recorded_names($csv->columns, $rows)), ', json ', json_encode(recorded_names($json->columns, $rows)), "\n"; } diff --git a/src/extension/flow-php-ext/tests/phpt/098_rust_append_physicals.phpt b/src/extension/flow-php-ext/tests/phpt/098_rust_append_physicals.phpt new file mode 100644 index 0000000000..274edf739b --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/098_rust_append_physicals.phpt @@ -0,0 +1,42 @@ +--TEST-- +RustColumnBuilder::appendPhysicals() appends physicals as they are: nulls with or without a count, nothing for [], a null under NOT NULL and a physical of another kind refused +--SKIPIF-- + +--FILE-- +builder(int_schema('id', nullable: true)); + $builder->appendPhysicals([1, null, 3, null], $nullCount); + $column = $builder->finish(); + echo json_encode($column->values()), ' ', $column->nullCount(), "\n"; +} + +$builder = (new RustBackend())->builder(int_schema('id')); +$builder->appendPhysicals([]); +echo $builder->count(), "\n"; + +try { + $builder->appendPhysicals([1, null]); +} catch (SchemaMismatchException $e) { + echo get_class($e), ' row ', $e->rowIndex, ' kept ', $builder->count(), "\n"; +} + +try { + $builder->appendPhysicals(['not an int']); +} catch (Throwable $e) { + echo get_class($e), ' kept ', $builder->count(), "\n"; +} +?> +--EXPECT-- +[1,null,3,null] 2 +[1,null,3,null] 2 +0 +Flow\ETL\Exception\SchemaMismatchException row 1 kept 0 +Flow\ETL\Exception\InvalidArgumentException kept 0 diff --git a/src/extension/flow-php-ext/tests/phpt/bootstrap.php b/src/extension/flow-php-ext/tests/phpt/bootstrap.php index b97a316c9f..35fb5ab463 100644 --- a/src/extension/flow-php-ext/tests/phpt/bootstrap.php +++ b/src/extension/flow-php-ext/tests/phpt/bootstrap.php @@ -313,7 +313,7 @@ function interfaces_reflection(): string 'Flow\\ETL\\Column\\ColumnBuilder', 'Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSink', 'Flow\\ETL\\Adapter\\CSV\\CSVEncoder', - 'Flow\\ETL\\Adapter\\JSON\\JSONEncoder', + 'Flow\\ETL\\Adapter\\JSON\\JsonEncoder', 'Flow\\ETL\\Adapter\\CSV\\CSVOpenSource', 'Flow\\ETL\\Adapter\\JSON\\JsonOpenSource', 'Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSource', @@ -1249,9 +1249,9 @@ public function encodeHeader(array $headers): string } /** - * Stands in for the PhpJSONEncoder a RustJSONEncoder holds: renders through it and records every column left to it. + * Stands in for the PhpJsonEncoder a RustJsonEncoder holds: renders through it and records every column left to it. */ -final class RecordingPhpJSONEncoder +final class RecordingPhpJsonEncoder { /** * @var list @@ -1259,7 +1259,7 @@ final class RecordingPhpJSONEncoder public array $columns = []; public function __construct( - private readonly Flow\ETL\Adapter\JSON\PhpJSONEncoder $php, + private readonly Flow\ETL\Adapter\JSON\PhpJsonEncoder $php, ) {} /** diff --git a/web/landing/assets/codemirror/completions/dsl.js b/web/landing/assets/codemirror/completions/dsl.js index 1808c5606f..b79cca30bc 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: 813 + * Total functions: 812 * * This completer provides autocompletion for all Flow PHP DSL functions: * - Extractors (flow-extractors) @@ -692,24 +692,6 @@ const dslFunctions = [ }, apply: snippet("\\Flow\\ETL\\Adapter\\Parquet\\array_to_generator(" + "$" + "{" + "1:data" + "}" + ")"), boost: 10 - }, { - label: "array_to_row", - type: "function", - detail: "flow\u002Ddsl\u002Ddata\u002Dframe", - info: () => { - const div = document.createElement("div") - div.innerHTML = ` -
      - array_to_row(array $data, Schema $schema, Backend $backend = Flow\\ETL\\Column\\DefaultBackend::..., Partitions|array $partitions = []) : Row -
      -
      - @param array>|array $data
      @param array|Partitions $partitions -
      - ` - return div - }, - apply: snippet("\\Flow\\ETL\\DSL\\array_to_row(" + "$" + "{" + "1:data" + "}" + ", " + "$" + "{" + "2:schema" + "}" + ", " + "$" + "{" + "3:backend" + "}" + ", " + "$" + "{" + "4:partitions" + "}" + ")"), - boost: 10 }, { label: "array_to_rows", type: "function", @@ -718,7 +700,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - array_to_rows(array $data, Schema $schema, Backend $backend = Flow\\ETL\\Column\\DefaultBackend::...) : Rows + array_to_rows(array $data, Schema $schema, Backend $backend) : Rows
      @param array>|array $data @@ -895,12 +877,12 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - average(Reference|string $ref, int $scale = 2, Rounding $rounding = Flow\\Calculator\\Rounding::...) : Average + average(Reference|string $ref, int $scale = 2, Rounding $rounding = Flow\\Calculator\\Rounding::..., bool $exact = false) : Average
      ` return div }, - apply: snippet("\\Flow\\ETL\\DSL\\average(" + "$" + "{" + "1:ref" + "}" + ", " + "$" + "{" + "2:scale" + "}" + ", " + "$" + "{" + "3:rounding" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\DSL\\average(" + "$" + "{" + "1:ref" + "}" + ", " + "$" + "{" + "2:scale" + "}" + ", " + "$" + "{" + "3:rounding" + "}" + ", " + "$" + "{" + "4:exact" + "}" + ")"), boost: 10 }, { label: "aws_s3_client", @@ -3799,12 +3781,12 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - filesystem_cache(Path|string|null $cache_dir = null, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::..., Serializer $serializer = Flow\\Floe\\FloeSerializer::...) : FilesystemCache + filesystem_cache(Serializer $serializer, Path|string|null $cache_dir = null, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : FilesystemCache
      ` return div }, - apply: snippet("\\Flow\\ETL\\DSL\\filesystem_cache(" + "$" + "{" + "1:cache_dir" + "}" + ", " + "$" + "{" + "2:filesystem" + "}" + ", " + "$" + "{" + "3:serializer" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\DSL\\filesystem_cache(" + "$" + "{" + "1:serializer" + "}" + ", " + "$" + "{" + "2:cache_dir" + "}" + ", " + "$" + "{" + "3:filesystem" + "}" + ")"), boost: 10 }, { label: "filesystem_telemetry_config", @@ -4423,7 +4405,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - from_json_lines(Path|string $path, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : JsonLinesExtractor + from_json_lines(Path|string $path, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : JsonExtractor
      Used to read from a JSON lines https://jsonlines.org/ formatted file.
      @param Path|string $path - string is internally turned into stream @@ -6415,7 +6397,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - merge_floe(array $sources, Path|string $dest, bool $compact = false, Metadata $metadata = null, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : void + merge_floe(array $sources, Path|string $dest, Backend $backend, bool $compact = false, Metadata $metadata = null, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : void
      Merges several Floe files (same or append-compatible evolving schema) into one. Byte-splices frame
      regions by default (O(bytes), no re-encode); compact re-encodes all rows into fewer sections.
      @param array $sources @@ -6423,7 +6405,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\Floe\\DSL\\merge_floe(" + "$" + "{" + "1:sources" + "}" + ", " + "$" + "{" + "2:dest" + "}" + ", " + "$" + "{" + "3:compact" + "}" + ", " + "$" + "{" + "4:metadata" + "}" + ", " + "$" + "{" + "5:filesystem" + "}" + ")"), + apply: snippet("\\Flow\\Floe\\DSL\\merge_floe(" + "$" + "{" + "1:sources" + "}" + ", " + "$" + "{" + "2:dest" + "}" + ", " + "$" + "{" + "3:backend" + "}" + ", " + "$" + "{" + "4:compact" + "}" + ", " + "$" + "{" + "5:metadata" + "}" + ", " + "$" + "{" + "6:filesystem" + "}" + ")"), boost: 10 }, { label: "meter_provider", @@ -8521,12 +8503,12 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - rows(Schema $schema, Row $row) : Rows + rows(Schema $schema, Backend $backend) : Rows
      ` return div }, - apply: snippet("\\Flow\\ETL\\DSL\\rows(" + "$" + "{" + "1:schema" + "}" + ", " + "$" + "{" + "2:row" + "}" + ")"), + apply: snippet("\\Flow\\ETL\\DSL\\rows(" + "$" + "{" + "1:schema" + "}" + ", " + "$" + "{" + "2:backend" + "}" + ")"), boost: 10 }, { label: "row_expr", @@ -10738,7 +10720,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - sum(Reference|string $ref, ScalarFunction|bool $exact = false) : Sum + sum(Reference|string $ref, bool $exact = false) : Sum
      ` return div @@ -11275,10 +11257,10 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - to_json_lines(Path|string $path, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : JsonLinesLoader + to_json_lines(Path|string $path, Filesystem $filesystem = Flow\\Filesystem\\Local\\NativeLocalFilesystem::...) : JsonLoader
      - Used to write to a JSON lines https://jsonlines.org/ formatted file.
      @param Path|string $path
      @return JsonLinesLoader + Used to write to a JSON lines https://jsonlines.org/ formatted file.
      @param Path|string $path
      @return JsonLoader
      ` return div diff --git a/web/landing/content/examples/topics/caching/cache/code.php b/web/landing/content/examples/topics/caching/cache/code.php index e3080eb2f4..50d07112fe 100644 --- a/web/landing/content/examples/topics/caching/cache/code.php +++ b/web/landing/content/examples/topics/caching/cache/code.php @@ -2,7 +2,7 @@ declare(strict_types=1); -use function Flow\ETL\DSL\{config_builder, data_frame, datetime_schema, filesystem_cache, from_cache, int_schema, ref, rename_replace, schema, str_schema, to_output}; +use function Flow\ETL\DSL\{config_builder, data_frame, datetime_schema, from_cache, int_schema, ref, rename_replace, schema, str_schema, to_output}; use Flow\ETL\Adapter\Http\DynamicExtractor\NextRequestFactory; use Flow\ETL\Adapter\Http\PsrHttpClientDynamicExtractor; use Http\Client\Curl\Client; @@ -30,7 +30,7 @@ public function create(?ResponseInterface $previousResponse = null) : ?RequestIn } }); -data_frame(config_builder()->cache(filesystem_cache(__DIR__ . '/output/cache'))) +data_frame(config_builder()->cacheDir(__DIR__ . '/output/cache')) ->read( from_cache( id: 'github_api', diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json index 14b4b3be63..740d46b1d2 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":280,"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":288,"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":294,"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":306,"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":313,"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":329,"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":350,"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":370,"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":376,"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":382,"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":388,"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":400,"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":414,"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":420,"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":426,"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":440,"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":454,"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":464,"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":478,"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":486,"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":496,"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":506,"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":516,"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":536,"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":542,"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":548,"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":558,"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":567,"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":573,"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}],"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":582,"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":592,"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":599,"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":605,"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":617,"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":623,"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":629,"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":635,"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":641,"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":647,"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":656,"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":662,"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":671,"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":677,"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":684,"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":690,"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":696,"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":705,"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":711,"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":722,"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":731,"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":740,"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":746,"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":755,"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":765,"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":774,"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":780,"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":786,"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":794,"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":807,"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":813,"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":819,"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":829,"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":838,"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":847,"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":853,"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":866,"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":875,"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":884,"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":890,"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":899,"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":905,"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":911,"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":917,"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":923,"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":935,"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":962,"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":992,"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":998,"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":1004,"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":1010,"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":1016,"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":1022,"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":1028,"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":1034,"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":1040,"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":1046,"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":1052,"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":1058,"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":"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":1064,"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":1070,"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":1076,"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":1082,"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":1092,"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":1102,"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":1112,"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":1122,"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":1132,"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":1138,"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":1147,"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":1156,"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":1169,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Column\\AdaptiveBackend::..."}],"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":1221,"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":1227,"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":1233,"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":1239,"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::..."},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"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":1249,"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":1255,"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":1261,"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":1267,"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":1273,"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":1279,"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":1285,"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":1291,"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":1297,"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":1303,"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":1309,"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":1315,"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":"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":1321,"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":1327,"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":1333,"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":1339,"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":1345,"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":1356,"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":1365,"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":1374,"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":1386,"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":1396,"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":1405,"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":1411,"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":1417,"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":1426,"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":1439,"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":1448,"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":1454,"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":1463,"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":1469,"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":1475,"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":1481,"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":1495,"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":1509,"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":1527,"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":1533,"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":1539,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1549,"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":1555,"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":1561,"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":1567,"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":1573,"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":1579,"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":1585,"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":1598,"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":1609,"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":1615,"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":1628,"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":1661,"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":1713,"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":1719,"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":1725,"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":1731,"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":1737,"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":1743,"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":1749,"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":1755,"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":1761,"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":1767,"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":1776,"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":1786,"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":1792,"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":1801,"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":1811,"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":1817,"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":1826,"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":1832,"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":1841,"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":1847,"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":1856,"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":1862,"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":1868,"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":1874,"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":1880,"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":1886,"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":1892,"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":1903,"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":1909,"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":1918,"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":1929,"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":1940,"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":1950,"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":1984,"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":1992,"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":2001,"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":2009,"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":2026,"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":2043,"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":2060,"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":2066,"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":2072,"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":2082,"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":2091,"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":2097,"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":2103,"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":30,"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":"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":43,"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":"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":53,"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":65,"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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":275,"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":283,"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":289,"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":301,"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":308,"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":324,"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":345,"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":365,"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":371,"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":377,"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":383,"slug":"filesystem-cache","name":"filesystem_cache","namespace":"Flow\\ETL\\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":"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::..."}],"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":395,"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":409,"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":415,"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":421,"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":435,"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":449,"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":459,"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":473,"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":481,"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":491,"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":501,"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":511,"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":531,"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":537,"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":543,"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":553,"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":562,"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":568,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","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":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":577,"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":587,"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":594,"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":600,"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":612,"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":618,"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":624,"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":630,"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":636,"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":642,"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":651,"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":657,"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":666,"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":672,"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":679,"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":685,"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":691,"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":700,"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":706,"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":717,"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":726,"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":735,"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":741,"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":750,"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":760,"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":769,"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":775,"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":781,"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":789,"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":802,"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":808,"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":814,"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":824,"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":833,"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":842,"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":848,"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":861,"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":870,"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":879,"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":885,"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":894,"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":900,"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":906,"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":912,"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":918,"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":930,"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":957,"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":987,"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":993,"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":999,"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":1005,"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":1011,"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":1017,"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":1023,"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":1029,"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":1035,"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":1041,"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":1047,"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":1053,"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":"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":1059,"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":1065,"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":1071,"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":1077,"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":1087,"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":1097,"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":1107,"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":1117,"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":1127,"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":1133,"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":1142,"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":1151,"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":1164,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","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":"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":1172,"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":1178,"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":1184,"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":1190,"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::..."},{"name":"exact","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"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":1200,"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":1206,"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":1212,"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":1218,"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":1224,"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":1230,"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":1236,"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":1242,"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":1248,"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":1254,"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":1260,"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":1266,"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":"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":1272,"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":1278,"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":1284,"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":1290,"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":1296,"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":1307,"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":1316,"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":1325,"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":1337,"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":1347,"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":1356,"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":1362,"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":1368,"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":1377,"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":1390,"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":1399,"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":1405,"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":1414,"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":1420,"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":1426,"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":1432,"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":1446,"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":1460,"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":1478,"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":1484,"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":1490,"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"},{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":1500,"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":1506,"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":1512,"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":1518,"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":1524,"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":1530,"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":1536,"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":1549,"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":1560,"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":1566,"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":1579,"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":1612,"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":1664,"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":1670,"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":1676,"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":1682,"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":1688,"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":1694,"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":1700,"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":1706,"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":1712,"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":1718,"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":1727,"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":1737,"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":1743,"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":1752,"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\\File","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":1762,"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":1768,"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":1777,"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":1783,"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":1792,"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":1798,"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":1807,"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":1813,"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":1819,"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":1825,"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":1831,"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":1837,"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":1843,"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":1854,"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":1860,"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":1869,"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":1880,"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":1891,"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":1901,"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":1935,"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":1943,"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":1952,"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":1960,"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":1977,"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":1994,"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":2011,"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":2017,"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":2023,"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":2033,"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":2042,"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":2048,"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":2054,"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":"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":44,"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":"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":54,"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":66,"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":"backend","type":[{"name":"Backend","namespace":"Flow\\ETL\\Column","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":"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":"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":"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":"LyoqCiAqIFVzZWQgdG8gd3JpdGUgdG8gYSBKU09OIGxpbmVzIGh0dHBzOi8vanNvbmxpbmVzLm9yZy8gZm9ybWF0dGVkIGZpbGUuCiAqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKgogKiBAcmV0dXJuIEpzb25Mb2FkZXIKICov"},{"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":71,"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":"[]"}],"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":86,"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":101,"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":122,"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":137,"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":150,"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":161,"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":172,"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":188,"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":198,"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":211,"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":224,"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":239,"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":248,"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":257,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[{"name":"zone","type":[{"name":"DateTimeZone","namespace":"","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":"'UTC'"}],"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":266,"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":275,"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":284,"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":293,"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":302,"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":311,"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":320,"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":329,"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":338,"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":347,"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":360,"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":369,"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":378,"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":387,"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":396,"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":405,"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":414,"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":423,"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":432,"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":441,"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":450,"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":463,"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":476,"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":485,"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":494,"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":506,"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":519,"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":528,"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":541,"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":547,"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":117,"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":134,"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":146,"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":159,"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":175,"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":184,"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":193,"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":205,"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":219,"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":231,"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":243,"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":256,"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":277,"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":304,"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":320,"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":335,"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":344,"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":370,"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":404,"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":418,"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":431,"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":440,"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":449,"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":458,"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":467,"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":478,"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":489,"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":503,"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":516,"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":530,"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":542,"slug":"collate","name":"collate","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":"collation","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":"Collate","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":"LyoqCiAqIENyZWF0ZSBhIENPTExBVEUgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIEV4cHJlc3Npb258c3RyaW5nICRleHByIEV4cHJlc3Npb24gdG8gY29sbGF0ZQogKiBAcGFyYW0gc3RyaW5nICRjb2xsYXRpb24gQ29sbGF0aW9uIG5hbWUgYXMgd3JpdHRlbiBpbiBTUUw6ICdDJywgJyJkZV9ERSInLCAncGdfY2F0YWxvZy4iQyInCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":557,"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":572,"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":587,"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":600,"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":616,"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":628,"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":642,"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":655,"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":666,"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":684,"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":705,"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":735,"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":750,"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":764,"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":776,"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":795,"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":804,"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":816,"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":825,"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":839,"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":861,"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":881,"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":894,"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":903,"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":912,"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":921,"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":930,"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":943,"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":957,"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":968,"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":977,"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":989,"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":1003,"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":1012,"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":1023,"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":1034,"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":1046,"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":1058,"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":1070,"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":1082,"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":1094,"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":1106,"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":1118,"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":1130,"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":1142,"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":1154,"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":1166,"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":1189,"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":1214,"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":1231,"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 diff --git a/web/landing/src/Flow/Website/Service/FlowConfigFactory.php b/web/landing/src/Flow/Website/Service/FlowConfigFactory.php index 6fc3545e7a..142a2a6222 100644 --- a/web/landing/src/Flow/Website/Service/FlowConfigFactory.php +++ b/web/landing/src/Flow/Website/Service/FlowConfigFactory.php @@ -5,8 +5,10 @@ namespace Flow\Website\Service; use Flow\ETL\Cache\Implementation\PSRSimpleCache; +use Flow\ETL\Column\AdaptiveBackend; use Flow\ETL\Config\ConfigBuilder; use Flow\Filesystem\Filesystem; +use Flow\Floe\FloeSerializer; use Flow\Telemetry\Provider\Clock\SystemClock; use Flow\Telemetry\Telemetry; use Symfony\Component\Cache\Adapter\FilesystemAdapter; @@ -68,13 +70,16 @@ public function telemetry(): Telemetry private function cache(string $directoryName, int $ttl): PSRSimpleCache { - return new PSRSimpleCache(new Psr16Cache( - new FilesystemAdapter( - 'flow-contributors', - $ttl, - directory: type_string()->assert($this->parameters->get('kernel.cache_dir')) . '/' - . ltrim($directoryName, '/'), + return new PSRSimpleCache( + new Psr16Cache( + new FilesystemAdapter( + 'flow-contributors', + $ttl, + directory: type_string()->assert($this->parameters->get('kernel.cache_dir')) . '/' + . ltrim($directoryName, '/'), + ), ), - )); + new FloeSerializer(new AdaptiveBackend()), + ); } } From 4444f9972b69d83ac7ab3bc00114111c5e5f8faa Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sat, 3 Oct 2026 18:47:34 +0200 Subject: [PATCH 16/21] feat: refuse mismatched native extensions, run Fibers in the WASM playground - flow_php and arrow-ext declare an ABI; a mismatched build is refused instead of failing on a missing class - local Path::uri() keeps the root slash (file:///...) - Parquet Option::BYTE_ARRAY_TO_STRING removed - WASM: ucontext shim over Emscripten fibers, so sinks running in a Fiber (to_branch()) work; undefined symbols now fail the link - published examples aligned with the columnar API; examples for the column backend, forEach() and CSV header/absent cells - docs updated for lazy-rows, new column-backend page --- documentation/components/adapters/csv.md | 4 +- documentation/components/adapters/doctrine.md | 121 ++++++++------ documentation/components/adapters/excel.md | 20 ++- documentation/components/adapters/json.md | 59 +++---- documentation/components/adapters/logger.md | 30 ++-- documentation/components/adapters/parquet.md | 18 +- .../components/adapters/postgresql.md | 41 +++-- documentation/components/adapters/seal.md | 69 ++++---- documentation/components/adapters/text.md | 26 ++- documentation/components/adapters/xml.md | 58 +++---- .../bridges/symfony-http-foundation-bridge.md | 14 +- documentation/components/cli/docs.md | 14 +- documentation/components/core/aggregations.md | 32 +++- .../components/core/batch-processing.md | 6 +- .../components/core/building-blocks.md | 12 +- documentation/components/core/caching.md | 45 ++--- .../components/core/column-backend.md | 69 ++++++++ documentation/components/core/core.md | 87 ++++++---- .../components/core/data-manipulation.md | 39 +---- .../components/core/data-retrieval.md | 4 +- .../components/core/error-handling.md | 29 ++-- documentation/components/core/filter.md | 25 ++- documentation/components/core/floe.md | 76 ++++----- documentation/components/core/group-by.md | 67 +++----- documentation/components/core/join.md | 40 +++-- documentation/components/core/partitioning.md | 4 +- documentation/components/core/pivot.md | 38 +++-- documentation/components/core/rename.md | 8 +- documentation/components/core/save-mode.md | 12 +- documentation/components/core/schema.md | 51 +++--- documentation/components/core/select-drop.md | 8 +- documentation/components/core/sort.md | 8 +- documentation/components/core/telemetry.md | 20 +-- .../components/core/transformations.md | 66 ++++---- .../components/core/window-functions.md | 17 +- .../components/extensions/arrow-ext.md | 4 +- .../components/extensions/flow-php-ext.md | 15 +- documentation/components/libs/array-dot.md | 2 + .../components/libs/doctrine-dbal-bulk.md | 96 +++++------ documentation/components/libs/parquet.md | 37 +++-- documentation/components/libs/snappy.md | 2 +- documentation/components/libs/types.md | 36 ++-- .../components/libs/types/architecture.md | 7 +- documentation/contributing/benchmarks.md | 2 +- documentation/contributing/c.md | 2 +- documentation/contributing/guidelines.md | 14 +- documentation/contributing/rust.md | 65 ++++++-- documentation/installation/docker.md | 29 ++-- .../installation/packages/arrow-ext.md | 8 + .../installation/packages/etl-adapter-csv.md | 5 + .../installation/packages/etl-adapter-json.md | 5 + .../packages/etl-adapter-parquet.md | 8 + documentation/installation/packages/etl.md | 9 + .../installation/packages/flow-php-ext.md | 9 + .../installation/packages/parquet.md | 3 +- documentation/quick-start.md | 23 ++- documentation/upgrading.md | 24 +++ .../ETL/Adapter/CSV/AdaptiveCSVEncoder.php | 7 +- .../ETL/Adapter/CSV/AdaptiveCSVOpenSource.php | 14 +- .../src/Flow/ETL/Adapter/CSV/CSVEncoder.php | 4 +- .../Flow/ETL/Adapter/CSV/CSVOpenSource.php | 4 +- .../Integration/AdaptiveCSVOpenSourceTest.php | 21 +++ .../CSV/Tests/Unit/AdaptiveCSVEncoderTest.php | 21 +++ .../ETL/Adapter/JSON/AdaptiveJsonEncoder.php | 6 +- .../Adapter/JSON/AdaptiveJsonOpenSource.php | 5 +- .../src/Flow/ETL/Adapter/JSON/JsonEncoder.php | 4 +- .../Flow/ETL/Adapter/JSON/JsonOpenSource.php | 4 +- .../AdaptiveJsonOpenSourceTest.php | 39 +++++ .../Tests/Unit/AdaptiveJsonEncoderTest.php | 10 ++ .../Parquet/AdaptiveParquetOpenSink.php | 7 +- .../Parquet/AdaptiveParquetOpenSource.php | 8 +- .../ETL/Adapter/Parquet/ParquetOpenSink.php | 4 +- .../ETL/Adapter/Parquet/ParquetOpenSource.php | 4 +- .../Unit/AdaptiveParquetOpenSinkTest.php | 17 ++ .../Unit/AdaptiveParquetOpenSourceTest.php | 12 ++ .../src/Flow/ETL/Adapter/Text/TextEncoder.php | 2 +- .../Text/Tests/Unit/TextEncoderTest.php | 7 +- .../src/Flow/ETL/Column/AdaptiveBackend.php | 7 +- src/core/etl/src/Flow/ETL/Column/Backend.php | 4 +- src/core/etl/src/Flow/ETL/Column/Column.php | 4 +- .../etl/src/Flow/ETL/Column/ColumnBuilder.php | 4 +- .../etl/src/Flow/ETL/Config/ConfigBuilder.php | 18 +- .../etl/src/Flow/ETL/FlowPhpExtension.php | 63 +++++++ .../DataFrame/PartitioningTest.php | 8 +- .../Extractor/PathPartitionsExtractorTest.php | 14 +- .../Tests/Unit/Column/AdaptiveBackendTest.php | 10 ++ .../Flow/ETL/Tests/Unit/DataFrameTest.php | 6 +- .../ETL/Tests/Unit/FlowPhpExtensionTest.php | 51 ++++++ .../Rule/PushFilterIntoSourceTest.php | 4 +- src/extension/arrow-ext/src/lib.rs | 5 + .../054_abi_matches_flow_php_parquet.phpt | 35 ++++ src/extension/flow-php-ext/src/lib.rs | 5 + .../phpt/099_abi_matches_flow_php_etl.phpt | 22 +++ .../src/Flow/Filesystem/Path/UnixPath.php | 4 + .../OS/Unix/NativeLocalFilesystemTest.php | 7 +- .../Tests/Unit/Path/UnixPathTest.php | 37 ++++- .../Flow/Filesystem/Tests/Unit/PathTest.php | 14 +- .../Parquet/Engine/AdaptiveParquetEngine.php | 11 +- .../Flow/Parquet/Engine/ArrowExtension.php | 63 +++++++ src/lib/parquet/src/Flow/Parquet/Option.php | 8 - src/lib/parquet/src/Flow/Parquet/Options.php | 1 - .../src/Flow/Parquet/ParquetEngine.php | 4 +- .../src/Flow/Parquet/ParquetFileReader.php | 4 +- .../src/Flow/Parquet/ParquetFileWriter.php | 4 +- .../Unit/Engine/AdaptiveParquetEngineTest.php | 25 +++ .../Tests/Unit/Engine/ArrowExtensionTest.php | 51 ++++++ wasm/build.sh | 19 ++- wasm/libc-emscripten.c | 41 +++++ wasm/ucontext-emscripten.c | 156 ++++++++++++++++++ .../codemirror/completions/dataframe.js | 2 +- .../assets/codemirror/completions/dsl.js | 4 +- .../completions/scalarfunctionchain.js | 16 +- web/landing/assets/wasm/data/orders.floe | Bin 56434 -> 42030 bytes web/landing/assets/wasm/data/orders.parquet | Bin 26568 -> 23914 bytes web/landing/assets/wasm/php.js | 4 +- web/landing/assets/wasm/php.wasm | Bin 17080387 -> 17089368 bytes web/landing/assets/wasm/tools/flow.phar | Bin 4003673 -> 4063059 bytes .../topics/batching/batch_by/description.md | 6 +- .../topics/batching/collect/description.md | 6 +- .../topics/batching/column_backend/_meta.yaml | 2 + .../topics/batching/column_backend/code.php | 20 +++ .../batching/column_backend/description.md | 4 + .../batching/column_backend/documentation.md | 5 + .../batching/constant_size/description.md | 6 +- .../topics/columns/create/description.md | 3 +- .../topics/columns/select/description.md | 3 +- .../examples/topics/errors/ignore/code.php | 6 +- .../topics/errors/ignore/description.md | 5 +- .../topics/filesystem/local/description.md | 3 +- .../topics/filesystem/stdout/description.md | 5 +- .../03_inferred_or_declared/code.php | 2 +- .../topics/inspecting/for_each/_meta.yaml | 2 + .../topics/inspecting/for_each/code.php | 23 +++ .../topics/inspecting/for_each/description.md | 2 + .../inspecting/for_each/documentation.md | 4 + .../examples/topics/joins/join/description.md | 7 +- .../examples/topics/joins/join_each/code.php | 5 +- .../topics/joins/join_each/description.md | 4 +- .../partition_placeholders/description.md | 22 +-- .../partition_pruning/description.md | 3 +- .../partitioning/append/description.md | 3 +- .../partitioning/partitioning/description.md | 35 ++-- .../exception_if_exists/description.md | 3 +- .../partitioning/ignore/description.md | 3 +- .../partitioning/overwrite/description.md | 3 +- .../path_partitions/description.md | 3 +- .../reading/after_append/description.md | 3 +- .../reading/after_overwrite/description.md | 3 +- .../partitioning/reading/basic/description.md | 3 +- .../topics/reading/array/description.md | 3 +- .../topics/reading/csv/description.md | 3 +- .../topics/reading/csv_cells/_meta.yaml | 2 + .../topics/reading/csv_cells/code.php | 16 ++ .../topics/reading/csv_cells/description.md | 2 + .../topics/reading/csv_cells/documentation.md | 4 + .../topics/reading/dbal/key_set/_meta.yaml | 2 +- .../reading/dbal/limit_offset/_meta.yaml | 2 +- .../topics/reading/dbal/queries/_meta.yaml | 2 +- .../topics/reading/dbal/query/_meta.yaml | 2 +- .../topics/reading/floe/description.md | 3 +- .../topics/reading/json/description.md | 3 +- .../topics/reading/jsonl/description.md | 3 +- .../topics/reading/parquet/description.md | 3 +- .../reading/sequence_date/description.md | 4 +- .../sequence_date_recurrences/description.md | 3 +- .../examples/topics/reading/xml/code.php | 3 - .../examples/topics/schema/apply/code.php | 6 +- .../topics/schema/apply/description.md | 3 +- .../topics/schema/display/description.md | 5 +- .../topics/schema/inferring/description.md | 3 +- .../topics/schema/strict_or_evolving/code.php | 2 +- .../examples/topics/schema/validate/code.php | 6 +- .../transformations/call/description.md | 3 +- .../transformations/custom/description.md | 3 +- .../filtering/basic/description.md | 3 +- .../topics/transformations/size/code.php | 5 +- .../transformations/size/description.md | 4 +- .../transformations/when/basic/description.md | 3 +- .../when/else_when/description.md | 3 +- .../topics/transformations/when/null/code.php | 2 +- .../transformations/when/null/description.md | 4 +- .../examples/topics/types/is_valid/code.php | 8 +- .../topics/types/is_valid/description.md | 2 + .../window_functions/dense_rank/code.php | 3 +- .../dense_rank/description.md | 5 +- .../topics/window_functions/description.md | 6 +- .../topics/window_functions/rank/code.php | 3 +- .../window_functions/rank/description.md | 5 +- .../window_functions/row_number/code.php | 3 +- .../row_number/description.md | 5 +- .../examples/topics/writing/array/code.php | 2 +- .../topics/writing/array/description.md | 5 +- .../topics/writing/dbal/delete/_meta.yaml | 2 +- .../topics/writing/dbal/delete/description.md | 3 +- .../topics/writing/dbal/insert/_meta.yaml | 2 +- .../topics/writing/dbal/insert/description.md | 4 +- .../topics/writing/dbal/upsert/_meta.yaml | 2 +- .../topics/writing/dbal/upsert/description.md | 4 +- .../topics/writing/excel/description.md | 3 +- .../topics/writing/floe/description.md | 3 +- .../topics/writing/jsonl/description.md | 3 +- .../topics/writing/overwrite/description.md | 3 +- .../topics/writing/parquet/description.md | 3 +- web/landing/resources/dsl.json | 2 +- .../documentation/navigation_left.html.twig | 1 + .../Functional/PlaygroundBranchSinkTest.php | 46 ++++++ 206 files changed, 2037 insertions(+), 990 deletions(-) create mode 100644 documentation/components/core/column-backend.md create mode 100644 src/core/etl/src/Flow/ETL/FlowPhpExtension.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/FlowPhpExtensionTest.php create mode 100644 src/extension/arrow-ext/tests/phpt/054_abi_matches_flow_php_parquet.phpt create mode 100644 src/extension/flow-php-ext/tests/phpt/099_abi_matches_flow_php_etl.phpt create mode 100644 src/lib/parquet/src/Flow/Parquet/Engine/ArrowExtension.php create mode 100644 src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowExtensionTest.php create mode 100644 wasm/libc-emscripten.c create mode 100644 wasm/ucontext-emscripten.c create mode 100644 web/landing/content/examples/topics/batching/column_backend/_meta.yaml create mode 100644 web/landing/content/examples/topics/batching/column_backend/code.php create mode 100644 web/landing/content/examples/topics/batching/column_backend/description.md create mode 100644 web/landing/content/examples/topics/batching/column_backend/documentation.md create mode 100644 web/landing/content/examples/topics/inspecting/for_each/_meta.yaml create mode 100644 web/landing/content/examples/topics/inspecting/for_each/code.php create mode 100644 web/landing/content/examples/topics/inspecting/for_each/description.md create mode 100644 web/landing/content/examples/topics/inspecting/for_each/documentation.md create mode 100644 web/landing/content/examples/topics/reading/csv_cells/_meta.yaml create mode 100644 web/landing/content/examples/topics/reading/csv_cells/code.php create mode 100644 web/landing/content/examples/topics/reading/csv_cells/description.md create mode 100644 web/landing/content/examples/topics/reading/csv_cells/documentation.md create mode 100644 web/landing/tests/Flow/Website/Tests/Functional/PlaygroundBranchSinkTest.php diff --git a/documentation/components/adapters/csv.md b/documentation/components/adapters/csv.md index c60d8d6223..b5f988c396 100644 --- a/documentation/components/adapters/csv.md +++ b/documentation/components/adapters/csv.md @@ -37,7 +37,7 @@ $rows = data_frame() ``` header row [' id ', '', 'name'] → columns ['id', 'e01', 'name'] (trimmed, a blank cell named e + its position) -record ['1', 'a'] → ['id' => '1', 'e01' => 'a', 'name' => null] (a cell the record lacks is null) +record ['1', 'a'] → ['id' => 1, 'e01' => 'a', 'name' => null] (a cell the record lacks is null) record ['1', '', 'x'] → 'e01' => null (a present '' is null; `withEmptyToNull(false)` keeps it '') ``` @@ -79,7 +79,7 @@ id,active,price,at,days,labels,size,meta | `null`, `''` | an empty field - `from_csv()` reads both back as `null` unless `withEmptyToNull(false)` | | `datetime`, `date` | `withDateTimeFormat()` (default `DATE_ATOM`) in the column zone, `withDateFormat()` (default `Y-m-d`) | | `time` | microseconds | -| `list`, `map`, `structure` | JSON: a list is `[…]`, a map and a structure are always `{…}`; every element is written as a column of its type would be | +| `list`, `map`, `structure` | JSON: a list is `[...]`, a map and a structure are always `{...}`; every element is written as a column of its type would be | | `json` | the stored text | Floats are rendered under `serialize_precision = -1`. When the ini holds another value the writer sets it for the diff --git a/documentation/components/adapters/doctrine.md b/documentation/components/adapters/doctrine.md index f2830d4353..e7651d6f8c 100644 --- a/documentation/components/adapters/doctrine.md +++ b/documentation/components/adapters/doctrine.md @@ -31,11 +31,16 @@ Adapter for [ETL](https://github.com/flow-php/etl) using bulk operations from [D ## Loader - DbalLoader ```php +use Doctrine\DBAL\Tools\DsnParser; + use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; +use function Flow\ETL\DSL\{data_frame, from_array}; + +$params = (new DsnParser(['postgresql' => 'pdo_pgsql']))->parse(\getenv('PGSQL_DATABASE_URL')); data_frame() ->read(from_array([['id' => 1, 'name' => 'norbert']])) - ->write(to_dbal_table_insert(['url' => \getenv('PGSQL_DATABASE_URL')], 'your-table-name')) + ->write(to_dbal_table_insert($params, 'users')) ->run(); ``` @@ -48,7 +53,8 @@ All supported DbalLoader operations via DSL functions: You can also configure bulk operations with platform-specific options: ```php -use function Flow\ETL\Adapter\Doctrine\{to_dbal_table_insert, postgresql_insert_options}; +use function Flow\ETL\Adapter\Doctrine\{postgresql_insert_options, to_dbal_table_insert}; +use function Flow\ETL\DSL\{data_frame, from_array}; data_frame() ->read(from_array([['id' => 1, 'name' => 'norbert']])) @@ -60,36 +66,36 @@ data_frame() ->run(); ``` -### Type Detection and Optimization - -`DbalLoader` now provides advanced type detection capabilities to optimize database operations: +### Types -#### Automatic Type Detection from Flow Schema - -By default, `DbalLoader` automatically detects column types from the Flow Schema of your data: +By default, `DbalLoader` binds every column with the DBAL type mapped from its Flow type +(the default map is listed under [Schema Converter - Types Map](#schema-converter---types-map)): ```php use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; +use function Flow\ETL\DSL\{data_frame, from_array}; data_frame() ->read(from_array([['id' => 1, 'name' => 'norbert']])) ->write(to_dbal_table_insert($connection, 'users')) ->run(); -// Types are automatically detected from the Flow Schema ``` #### Custom Types Map -For advanced scenarios, you can provide a custom type mapping to control how Flow types are converted to DBAL types: +A custom map replaces the default one, so spread `TypesMap::FLOW_TYPES` to keep the other types: ```php -use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; +use Doctrine\DBAL\Types\TextType; use Flow\ETL\Adapter\Doctrine\TypesMap; use Flow\Types\Type\Native\StringType; -use Doctrine\DBAL\Types\TextType; + +use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; +use function Flow\ETL\DSL\{data_frame, from_array}; $customTypesMap = new TypesMap([ - StringType::class => TextType::class, // Map Flow strings to DBAL text type + ...TypesMap::FLOW_TYPES, + StringType::class => TextType::class, ]); data_frame() @@ -99,26 +105,23 @@ data_frame() ->run(); ``` -#### Data Normalization +#### Bound values -`DbalLoader` automatically handles data normalization for database compatibility: - -- **XML Entries**: `XMLEntry` and `XMLElementEntry` objects are automatically converted to their string representation -- **Complex Types**: Lists, Maps, and Structures are serialized as JSON -- **Type Safety**: All data is normalized while preserving type information for optimal database performance +A column is bound as its values and converted by its DBAL type: `list`, `map` and `structure` become JSON through +`JsonType`. `xml`, `xml_element`, `html` and `html_element` are bound as their markup text: ```php -use function Flow\ETL\DSL\{data_frame, from_array, xml_entry}; use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; +use function Flow\ETL\DSL\{data_frame, from_array, int_schema, schema, xml_schema}; data_frame() - ->read(from_array([ - ['id' => 1, 'data' => $domDocument], - ['id' => 2, 'data' => $domElement], - ])) + ->read(from_array( + [['id' => 1, 'data' => '1']], + schema(int_schema('id'), xml_schema('data')), + )) ->write(to_dbal_table_insert($connection, 'xml_table')) ->run(); -// XML entries are automatically converted to strings before database insertion +// data is bound as '1' ``` ## Transactional Loading @@ -127,11 +130,11 @@ data_frame() transaction, and if any sink throws, the open transaction is rolled back: ```php -use function Flow\ETL\DSL\{data_frame, from_array}; use function Flow\ETL\Adapter\Doctrine\{to_dbal_table_insert, to_dbal_transaction}; +use function Flow\ETL\DSL\{data_frame, from_array}; data_frame() - ->read(from_array($data)) + ->read(from_array([['id' => 1, 'name' => 'norbert']])) ->write(to_dbal_transaction( $connection, to_dbal_table_insert($connection, 'users'), @@ -143,7 +146,7 @@ data_frame() 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. +`to_dbal_table_insert($params, 'users')`) opens its own connection and escapes the transaction. Sinks with blocking operations (`to_transformation()` / `to_branch(...)->withTransformation(...)` with `sortBy()`, `aggregate()`, `groupBy()->aggregate()`, `pivot()`, window functions, `collect()`, `join()` - see @@ -162,6 +165,8 @@ use Doctrine\DBAL\TransactionIsolationLevel; use Flow\ETL\Adapter\Doctrine\DbalTransaction; use Flow\ETL\Sink\Transactional; +use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; + new Transactional( DbalTransaction::fromConnection($connection)->withIsolationLevel(TransactionIsolationLevel::SERIALIZABLE), to_dbal_table_insert($connection, 'users'), @@ -170,55 +175,56 @@ new Transactional( ## Extractor - DbalQuery -This simple but powerful extractor let you extract data from a single or multiple parametrized queries. - `from_dbal_*()` extractors derive their schema from the query unless `->withSchema()` declares it - how that works and fails: [Doctrine DBAL sources](../core/schema.md#doctrine-dbal-sources-describe-themselves-and-keep-withschema). ### Single Query -```php + +```php +use function Flow\ETL\Adapter\Doctrine\from_dbal_query; use function Flow\ETL\DSL\{data_frame, to_output}; data_frame() - ->read(DbalQueryExtractor::singleQuery($connection, "SELECT * FROM {$table} ORDER BY id")) + ->read(from_dbal_query($connection, 'SELECT * FROM users ORDER BY id')) ->write(to_output()) ->run(); ``` ### Single Parametrized Query -```php +```php +use function Flow\ETL\Adapter\Doctrine\from_dbal_query; use function Flow\ETL\DSL\{data_frame, to_output}; data_frame() - ->read(DbalQueryExtractor::singleQuery($connection, "SELECT * FROM {$table} WHERE id = :id", ['id' => 1])) + ->read(from_dbal_query($connection, 'SELECT * FROM users WHERE id = :id', ['id' => 1])) ->write(to_output()) ->run(); ``` -### Multiple Parametrized Query -```php ignore +### Multiple Parametrized Queries + +```php +use Flow\ETL\Adapter\Doctrine\ParametersSet; + +use function Flow\ETL\Adapter\Doctrine\from_dbal_queries; use function Flow\ETL\DSL\{data_frame, to_output}; data_frame() - ->read( - new DbalQueryExtractor( - $connection, - "SELECT * FROM {$table} ORDER BY id LIMIT :limit OFFSET :offset", - new ParametersSet( - ['limit' => 2, 'offset' => 0], - ['limit' => 2, 'offset' => 2], - ['limit' => 2, 'offset' => 4], - ['limit' => 2, 'offset' => 6], - ['limit' => 2, 'offset' => 8], - ) - ) - ) + ->read(from_dbal_queries( + $connection, + 'SELECT * FROM users ORDER BY id LIMIT :limit OFFSET :offset', + new ParametersSet( + ['limit' => 2, 'offset' => 0], + ['limit' => 2, 'offset' => 2], + ['limit' => 2, 'offset' => 4], + ), + )) ->write(to_output()) - ->run() + ->run(); ``` -In this case, query will be executed exactly five times, taking every time next entry of parameters from ParametersSet. +The query runs once per parameter set, three times here. ## Schema Converter @@ -230,6 +236,8 @@ like length, primary key, index, precision, etc ```php +use Flow\ETL\Adapter\Doctrine\DbalMetadata; + use function Flow\ETL\DSL\bool_schema; use function Flow\ETL\DSL\date_schema; use function Flow\ETL\DSL\float_schema; @@ -273,20 +281,21 @@ Will generate: use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Types\Type; new Table( 'test', [ new Column('int', Type::getType('integer'), ['notnull' => true]), - new Column('str', Type::getType('string'), ['notnull' => false]), + new Column('str', Type::getType('string'), ['notnull' => true]), new Column('str_with_length', Type::getType('string'), ['notnull' => false, 'length' => 255]), new Column('str_unique', Type::getType('string'), ['notnull' => false]), + new Column('date', Type::getType('date_immutable'), ['notnull' => false]), new Column('float', Type::getType('float'), ['notnull' => false, 'precision' => 10, 'scale' => 2]), new Column('bool', Type::getType('boolean'), ['notnull' => false, 'default' => true]), new Column('json', Type::getType('json'), ['notnull' => false, 'platformOptions' => ['jsonb' => true]]), new Column('list', Type::getType('json'), ['notnull' => true, 'columnDefinition' => 'integer[]']), new Column('map', Type::getType('json'), ['notnull' => true, 'comment' => 'test comment!']), - new Column('date', Type::getType('date_immutable'), ['notnull' => false]), ], [ new Index('pk_test', ['int', 'str'], true, true), @@ -301,7 +310,7 @@ new Table( When types map is not provided, the default one will be used: ```php ignore -public const FLOW_TYPES = [ +public const array FLOW_TYPES = [ StringType::class => \Doctrine\DBAL\Types\StringType::class, IntegerType::class => \Doctrine\DBAL\Types\IntegerType::class, FloatType::class => \Doctrine\DBAL\Types\FloatType::class, @@ -310,9 +319,13 @@ public const FLOW_TYPES = [ TimeType::class => \Doctrine\DBAL\Types\TimeImmutableType::class, DateTimeType::class => \Doctrine\DBAL\Types\DateTimeImmutableType::class, UuidType::class => \Doctrine\DBAL\Types\GuidType::class, + TimeZoneType::class => \Doctrine\DBAL\Types\StringType::class, JsonType::class => \Doctrine\DBAL\Types\JsonType::class, XMLType::class => \Doctrine\DBAL\Types\StringType::class, XMLElementType::class => \Doctrine\DBAL\Types\StringType::class, + HTMLType::class => \Doctrine\DBAL\Types\StringType::class, + HTMLElementType::class => \Doctrine\DBAL\Types\StringType::class, + EnumType::class => \Doctrine\DBAL\Types\StringType::class, ListType::class => \Doctrine\DBAL\Types\JsonType::class, MapType::class => \Doctrine\DBAL\Types\JsonType::class, StructureType::class => \Doctrine\DBAL\Types\JsonType::class, diff --git a/documentation/components/adapters/excel.md b/documentation/components/adapters/excel.md index 4b775bb14a..6d34b653e4 100644 --- a/documentation/components/adapters/excel.md +++ b/documentation/components/adapters/excel.md @@ -178,9 +178,9 @@ data_frame() ->run(); ``` -### Dynamic Sheet Names from Entry +### Sheet Name from a Column -Route rows to different sheets based on entry values: +Write each row to the sheet named by its `category` value: ```php run(); ``` +### Cells + +| Column | Cell | +|----------------------------------------------|----------------------------------------------------------------------------------------| +| `string`, `integer`, `float`, `boolean` | the value | +| `datetime`, `date` | a date cell, displayed with `withDateTimeFormat()` / `withDateFormat()` | +| `time` | text, `withTimeFormat()` | +| `enum` | a backed enum's value, a unit enum's name | +| `uuid`, `json` | text | +| `xml`, `xml_element`, `html`, `html_element` | the markup, e.g. `` | +| `list`, `map`, `structure` | JSON text: a datetime element as `DATE_ATOM`, a time as microseconds, a float as `1.0` | + ### Cell Styling -Apply custom styles to individual cells based on their value and the column they belong to. `$value` is the cell as -it is written: a backed enum's value or a unit enum's name, a uuid as text, a list / map / structure as JSON text, a -date or datetime as a `DateTimeInterface`. +`$value` is the cell as it is written (see [Cells](#cells)), not the column value. ```php Json library is not explicitly required, you need to make sure it is available in your composer.json file. -> If you are only using Loader, this dependency is optional. - -## Extractor - JSONMachine - JsonExtractor +## Extractor ```php read(from_json(__DIR__ . '/data.json')) - ->collect() + ->write(to_output()) + ->run(); + +data_frame() + ->read(from_json_lines(__DIR__ . '/data.jsonl')) ->write(to_output()) ->run(); ``` +Both return a `JsonExtractor`. `from_json()` reads one document: a top-level array, or the subtree selected with +`withPointer()`. + In JSON lines, a line holding only whitespace (space, tab, CR, LF, VT, FF) is skipped, as DuckDB does; this is not configurable. With the [`flow_php`](/documentation/components/extensions/flow-php-ext.md) extension loaded, JSON lines and a document holding a top-level array are read natively, as strict JSON: malformed input throws -`RuntimeException('Malformed JSON in "" at line N: …')` (`at element N` in a document). A pointer, or a document +`RuntimeException('Malformed JSON in "" at line N: ...')` (`at element N` in a document). A pointer, or a document that is not an array, is read by the PHP reader. -## Loader - JsonLoader +## Loader ```php read(from_array( - \array_map( - fn (int $i) : array => ['id' => $i, 'name' => 'name_' . $i], - \range(0, 10) - ) - )) - ->collect() + ->read(from_array([['id' => 1, 'name' => 'name_1'], ['id' => 2, 'name' => 'name_2']])) ->write(to_json(\sys_get_temp_dir() . '/file.json')) - ->run(); -``` - -## Loader - JsonLoader - JSON lines - -It is also possible to export the rows using the [json lines](https://jsonlines.org/) format - -```php -read(from_array( - \array_map( - fn (int $i) : array => ['id' => $i, 'name' => 'name_' . $i], - \range(0, 10) - ) - )) - ->collect() ->write(to_json_lines(\sys_get_temp_dir() . '/file.jsonl')) ->run(); ``` +Both return a `JsonLoader`. `to_json()` writes one array document, `to_json_lines()` writes +[JSON lines](https://jsonlines.org/). + ## What the loaders write ```php @@ -123,8 +102,8 @@ data_frame() {"id":2,"active":false,"price":1,"at":null,"days":[],"labels":{},"size":{"w":3,"h":4},"meta":{}} ``` -The shape follows the column type, never the data: a `list` is always `[…]`, a `map`, a `structure` and a row are -always `{…}` (an empty map is `{}`, a map keyed `0, 1` is `{"0":…,"1":…}`), a `json` column keeps its objects and +The shape follows the column type, never the data: a `list` is always `[...]`, a `map`, a `structure` and a row are +always `{...}` (an empty map is `{}`, a map keyed `0, 1` is `{"0":...,"1":...}`), a `json` column keeps its objects and lists. A `datetime` / `date` is written with `withDateTimeFormat()` / `withDateFormat()` at every depth, a `time` as microseconds. A float has the shortest digits that read back as the same float (`1.0` is `1`, or `1.0` under `JSON_PRESERVE_ZERO_FRACTION`); `NAN` and the infinities are refused: diff --git a/documentation/components/adapters/logger.md b/documentation/components/adapters/logger.md index a9302795ee..231ad46189 100644 --- a/documentation/components/adapters/logger.md +++ b/documentation/components/adapters/logger.md @@ -14,26 +14,26 @@ ETL Adapter that provides PSR Logger support for ETL. For detailed installation instructions, see the [installation page](/documentation/installation/packages/etl-adapter-logger.md). -## Loader - PsrLogger +## Loader - PsrLoggerLoader -Load each row into PsrLoggerInterface implementation. To get `TestLogger` mock class first run: - -``` -composer require fig/log-test -``` +Logs each row as one record: the row's values are the log context. `TestLogger` below comes from +`composer require --dev fig/log-test`. ```php load(array_to_rows( - [['id' => 12345, 'name' => 'norbert']], - schema(int_schema('id'), str_schema('name')), -)); +$logger = new TestLogger(); + +data_frame() + ->read(from_array([['id' => 12345, 'name' => 'norbert']])) + ->write(new PsrLoggerLoader($logger, 'row log', LogLevel::ERROR)) + ->run(); -$this->assertTrue($logger->hasErrorRecords()); -$this->assertTrue($logger->hasError('row log')); -``` \ No newline at end of file +$logger->hasError(['message' => 'row log', 'context' => ['id' => 12345, 'name' => 'norbert']]); // true +``` diff --git a/documentation/components/adapters/parquet.md b/documentation/components/adapters/parquet.md index 6dbb9bcb52..862480ec79 100644 --- a/documentation/components/adapters/parquet.md +++ b/documentation/components/adapters/parquet.md @@ -24,8 +24,19 @@ For detailed installation instructions, see the [installation page](/documentati ## Engines -Without `engine:`, Parquet is read and written by the [`flow_php` extension](/documentation/components/extensions/flow-php-ext.md) -and arrow-ext when both are loaded, else by `AdaptiveParquetEngine`. An explicit engine is always used: +Without `engine:`, `AdaptiveParquetEngine` opens the file. The loaded extensions, arrow-ext and +[`flow_php`](/documentation/components/extensions/flow-php-ext.md), pick the lane: + +| arrow-ext | `flow_php` | Engine | Batches | +|-----------|------------|---------------------|---------------------------------------------------------------------| +| no | no | `PhpParquetEngine` | PHP columns | +| yes | no | `RustParquetEngine` | PHP columns built from arrow-ext's values | +| no | yes | `PhpParquetEngine` | native columns built from the PHP engine's values | +| yes | yes | `RustParquetEngine` | arrow-ext's batches straight into native columns, and back on write | + +`RustParquetEngine` needs little-endian byte order. Native columns come from the +[column backend](/documentation/components/core/column-backend.md). An explicit engine is always used; +`PhpParquetEngine` opts out of arrow-ext: ```php withSchema()` throws. Project with `columns:`, change types after diff --git a/documentation/components/adapters/postgresql.md b/documentation/components/adapters/postgresql.md index 639a1ef91f..fbdb221e69 100644 --- a/documentation/components/adapters/postgresql.md +++ b/documentation/components/adapters/postgresql.md @@ -292,6 +292,17 @@ df() ->run(); ``` +### Bound values + +`xml`, `xml_element`, `html` and `html_element` columns are bound as their markup text. An `xml` document is bound as +its root element only: the declaration, a DOCTYPE, and comments or processing instructions outside the root are +dropped. + +| Column | Value | Bound | +|---------------|----------------------------------------------------|------------------------| +| `xml` | `` | `` | +| `xml_element` | `` | `` | + ### Insert with Skip Conflicts (ON CONFLICT DO NOTHING) Skip rows that would cause a constraint violation: @@ -425,6 +436,8 @@ use Flow\ETL\Adapter\PostgreSql\PostgreSqlTransaction; use Flow\ETL\Sink\Transactional; use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel; +use function Flow\ETL\Adapter\PostgreSql\to_pgsql_table; + new Transactional( (new PostgreSqlTransaction($client))->withIsolationLevel(IsolationLevel::SERIALIZABLE), to_pgsql_table($client, 'users'), @@ -433,13 +446,13 @@ new Transactional( ## Loader DSL Functions Reference -| Function | Description | -|------------------------------------------------|-----------------------------------------------------------| -| `to_pgsql_table($client, $table)` | Create a PostgreSQL loader for a table | -| `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) | +| Function | Description | +|--------------------------------------------|--------------------------------------------------| +| `to_pgsql_table($client, $table)` | Create a PostgreSQL loader for a table | +| `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) | ## Schema Conversion @@ -515,7 +528,7 @@ $schema = schema( | `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::generated($expr)` | Make the column a generated 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 expressed by attaching the same name to several definitions. @@ -554,6 +567,10 @@ Because each index is tracked under its own metadata key, a single column can be `merge()` to attach more than one: ```php +use Flow\ETL\Adapter\PostgreSql\PostgreSqlMetadata; + +use function Flow\ETL\DSL\{datetime_schema, int_schema, schema}; + $schema = schema( int_schema('id', metadata: PostgreSqlMetadata::primaryKey('pk_orders') ->merge(PostgreSqlMetadata::index('orders_created_at_id_idx', position: 2))), @@ -608,7 +625,7 @@ $table = to_pgsql_schema_table( ### Schema Conversion DSL Functions Reference -| Function | Description | -|-----------------------------------------------------------------------|--------------------------------------------------------| -| `to_pgsql_schema_table($schema, $tableName, $databaseSchema, $typesMap)` | Convert a Flow `Schema` into a PostgreSQL `Table` | -| `pgsql_table_to_flow_schema($table, $typesMap)` | Convert a PostgreSQL `Table` into a Flow `Schema` | +| Function | Description | +|--------------------------------------------------------------------------|---------------------------------------------------| +| `to_pgsql_schema_table($schema, $tableName, $databaseSchema, $typesMap)` | Convert a Flow `Schema` into a PostgreSQL `Table` | +| `pgsql_table_to_flow_schema($table, $typesMap)` | Convert a PostgreSQL `Table` into a Flow `Schema` | diff --git a/documentation/components/adapters/seal.md b/documentation/components/adapters/seal.md index 5ddf238d99..f6b59d6d40 100644 --- a/documentation/components/adapters/seal.md +++ b/documentation/components/adapters/seal.md @@ -24,17 +24,17 @@ In addition to this adapter, install the SEAL engine adapter for your search bac composer require flow-php/etl-adapter-seal cmsig/seal-elasticsearch-adapter ``` -| Backend | Package | -|---------------|----------------------------------| -| Algolia | `cmsig/seal-algolia-adapter` | +| Backend | Package | +|---------------|------------------------------------| +| Algolia | `cmsig/seal-algolia-adapter` | | Elasticsearch | `cmsig/seal-elasticsearch-adapter` | -| Loupe | `cmsig/seal-loupe-adapter` | -| Meilisearch | `cmsig/seal-meilisearch-adapter` | -| Memory | `cmsig/seal-memory-adapter` | -| OpenSearch | `cmsig/seal-opensearch-adapter` | -| RediSearch | `cmsig/seal-redisearch-adapter` | -| Solr | `cmsig/seal-solr-adapter` | -| Typesense | `cmsig/seal-typesense-adapter` | +| Loupe | `cmsig/seal-loupe-adapter` | +| Meilisearch | `cmsig/seal-meilisearch-adapter` | +| Memory | `cmsig/seal-memory-adapter` | +| OpenSearch | `cmsig/seal-opensearch-adapter` | +| RediSearch | `cmsig/seal-redisearch-adapter` | +| Solr | `cmsig/seal-solr-adapter` | +| Typesense | `cmsig/seal-typesense-adapter` | ## Description @@ -97,8 +97,8 @@ to_seal_upsert($engine, 'users')->withBulkSize(500); ### Deleting Documents -`to_seal_delete()` removes documents by their identifiers. By default, the identifier is taken from the `id` entry of -each row - use `withIdentifierEntry()` when your identifier entry has a different name. +`to_seal_delete()` removes documents by their identifiers, read from the `id` column. `withIdentifierEntry()` names +another column. ```php use function Flow\ETL\Adapter\Seal\to_seal_delete; @@ -116,18 +116,19 @@ to_seal_delete($engine, 'products')->withIdentifierEntry('sku'); ### Data Normalization -Before saving, rows are normalized into search documents: +Each row becomes one document: -| Flow Type | Document Value | -|---------------------------|-------------------------------------------------| -| `string`, `int`, `float`, `bool` | unchanged | -| `uuid` | string representation | -| `datetime` | string, `DateTimeInterface::ATOM` by default | -| `date` | string, `Y-m-d` by default | -| `enum` | case name | -| `xml`, `xml_element` | serialized XML string | -| `json` | decoded array | -| `list`, `map`, `structure` | array (nested values normalized recursively) | +| Flow Type | Document Value | +|----------------------------------------------|----------------------------------------------| +| `string`, `int`, `float`, `bool` | unchanged | +| `uuid` | string representation | +| `datetime` | string, `DateTimeInterface::ATOM` by default | +| `date` | string, `Y-m-d` by default | +| `enum` | case name | +| `time` | microseconds | +| `xml`, `xml_element`, `html`, `html_element` | markup text, e.g. `` | +| `json` | decoded array | +| `list`, `map`, `structure` | array (nested values normalized recursively) | ## Schema Conversion @@ -156,20 +157,20 @@ $sealSchema = to_seal_schema( ### Type Mapping -| Flow Type | SEAL Field | Default Flags | -|------------------------------------|-------------------|------------------------| -| `string`, `uuid`, `enum`, `xml`, `html` | `TextField` | searchable | -| `integer` | `IntegerField` | filterable, sortable | -| `float` | `FloatField` | filterable, sortable | -| `boolean` | `BooleanField` | filterable | -| `datetime`, `date` | `DateTimeField` | filterable, sortable | -| `json`, `map` | `JsonObjectField` | - | -| `list` | field of `T` with `multiple: true` | as `T` | -| `structure` | `ObjectField` (recursive) | - | +| Flow Type | SEAL Field | Default Flags | +|-----------------------------------------|------------------------------------|----------------------| +| `string`, `uuid`, `enum`, `xml`, `html` | `TextField` | searchable | +| `integer` | `IntegerField` | filterable, sortable | +| `float` | `FloatField` | filterable, sortable | +| `boolean` | `BooleanField` | filterable | +| `datetime`, `date` | `DateTimeField` | filterable, sortable | +| `json`, `map` | `JsonObjectField` | - | +| `list` | field of `T` with `multiple: true` | as `T` | +| `structure` | `ObjectField` (recursive) | - | ### Field Flags -Default flags can be overridden per definition through entry metadata: +Default flags can be overridden per definition through its metadata: | Metadata | Effect | |------------------------------|-----------------------------------------| diff --git a/documentation/components/adapters/text.md b/documentation/components/adapters/text.md index 1593d7755b..1d75680647 100644 --- a/documentation/components/adapters/text.md +++ b/documentation/components/adapters/text.md @@ -29,31 +29,29 @@ For detailed installation instructions, see the [installation page](/documentati ```php read(from_text(path)) +$rows = data_frame() + ->read(from_text(__DIR__ . '/file.txt')) ->fetch(); ``` +Each line is one row with a single `string` column `text`. + ## Loader -> :warning: Heads up, TextLoader expects rows to have single entry in order to properly write them into file. +The batch must have at most one column. ```php process( - array_to_rows( - [['name' => 'Norbert'], ['name' => 'Tomek'], ['name' => 'Dawid']], - schema(str_schema('name')), - ) - ) - ->load(to_text($path)) +data_frame() + ->read(from_array([['name' => 'Norbert'], ['name' => 'Tomek'], ['name' => 'Dawid']])) + ->write(to_text(__DIR__ . '/names.txt')) ->run(); ``` diff --git a/documentation/components/adapters/xml.md b/documentation/components/adapters/xml.md index 2809edff82..627c52def1 100644 --- a/documentation/components/adapters/xml.md +++ b/documentation/components/adapters/xml.md @@ -23,11 +23,9 @@ aligning perfectly with the robust and adaptable nature of the Flow PHP ecosyste For detailed installation instructions, see the [installation page](/documentation/installation/packages/etl-adapter-xml.md). -## Extractor - XMLExtractor +## Extractor -Memory safe XML extractor - -`xml/simple_items.xml` +`simple_items.xml` ```xml @@ -35,49 +33,37 @@ Memory safe XML extractor 1 2 3 - 4 - 5 - 6 ``` -```php +```php read(XML::from(__FLOW_DATA__ . '/simple_items.xml', 'root/items/item')) - ->write(To::output(false)) - ->run() -; -``` +use function Flow\ETL\Adapter\XML\from_xml; +use function Flow\ETL\DSL\{data_frame, ref, to_output}; -Above code will generate Rows with 5 entries like the one below: +data_frame() + ->read(from_xml(__DIR__ . '/simple_items.xml')->withXMLNodePath('root/items/item')) + ->withEntry('id', ref('node')->xpath('id')->domElementValue()) + ->write(to_output(truncate: false)) + ->run(); +``` ```shell -+----------------------------------------------+ -| row | -+----------------------------------------------+ -| 1 | -| 2 | -| 3 | -| 4 | -| 5 | -| 6 | -+----------------------------------------------+ ++-------------------------+----+ +| node | id | ++-------------------------+----+ +| 1 | 1 | +| 2 | 2 | +| 3 | 3 | ++-------------------------+----+ +3 rows ``` -Each entry will be an XMLEntry type. -From there you can use built in expressions to extract data from XML. - -- `ref('row')->xpath('...');` -- `ref('row')->domNodeAttribute('...');` -- `ref('row')->domNodeValue('...');` - -When working with collections XPath will return an ListEntry with XMLEntries inside. -From there you can for example unpack or expand them. - -For more examples please look into `/examples/topics/xml` directory in [flow monorepo](https://github.com/flow-php/flow) +The file is streamed. Every node at `withXMLNodePath()` is one row with a single `xml` column `node`. Read it with +`xpath()` (returns a `list`), `domElementValue()`, `domElementAttributeValue()` and the other +`domElement*()` functions. ## Loader diff --git a/documentation/components/bridges/symfony-http-foundation-bridge.md b/documentation/components/bridges/symfony-http-foundation-bridge.md index 94f3c34ba8..48f81b7c7f 100644 --- a/documentation/components/bridges/symfony-http-foundation-bridge.md +++ b/documentation/components/bridges/symfony-http-foundation-bridge.md @@ -77,9 +77,9 @@ final class ReportsController extends AbstractController ## Available Outputs - `Flow\Bridge\Symfony\HttpFoundation\Output\CSVOutput` - `http_csv_output()` - converts dataset to CSV format. -- `Flow\Bridge\Symfony\HttpFoundation\Output\JSONOutput` - `http_json_output()` -converts dataset to JSON format. -- `Flow\Bridge\Symfony\HttpFoundation\Output\ParquetOutput` - `http_parquet_output()` -converts dataset to Parquet format. -- `Flow\Bridge\Symfony\HttpFoundation\Output\XMLOutput` - `http_xml_output()` -converts dataset to XML format. +- `Flow\Bridge\Symfony\HttpFoundation\Output\JsonOutput` - `http_json_output()` - converts dataset to JSON format. +- `Flow\Bridge\Symfony\HttpFoundation\Output\ParquetOutput` - `http_parquet_output()` - converts dataset to Parquet format. +- `Flow\Bridge\Symfony\HttpFoundation\Output\XMLOutput` - `http_xml_output()` - converts dataset to XML format. ## Modify output on the fly @@ -87,10 +87,16 @@ Sometimes we need to modify the output on the fly. To do that, FlowStreamedResponse allows passing a Transformation that will be applied on the dataset. ```php +withColumn('time', \time()); + return $dataFrame->withEntry('time', lit(\time())); } }; ``` diff --git a/documentation/components/cli/docs.md b/documentation/components/cli/docs.md index 506580ec8c..dd6102054d 100644 --- a/documentation/components/cli/docs.md +++ b/documentation/components/cli/docs.md @@ -338,23 +338,25 @@ Arguments: Options: --input-file-format=INPUT-FILE-FORMAT Source file format. When not set file format is guessed from source file path extension --input-file-limit=INPUT-FILE-LIMIT Limit number of rows that are going to be used to infer file schema, when not set whole file is analyzed + --input-file-offset=INPUT-FILE-OFFSET Number of rows to skip before starting to read data --config=CONFIG Path to a local php file that MUST return instance of: Flow\ETL\Config --input-json-pointer=INPUT-JSON-POINTER JSON Pointer to a subtree from which schema should be extracted --input-json-pointer-entry-name When set, JSON Pointer will be used as an entry name in the schema + --input-excel-header[=INPUT-EXCEL-HEADER] When set, Excel header will be used as a schema + --input-excel-sheet-name=INPUT-EXCEL-SHEET-NAME When set, Excel sheet name will be selected for reading + --input-excel-offset=INPUT-EXCEL-OFFSET Offset to start reading from --input-csv-header[=INPUT-CSV-HEADER] When set, CSV header will be used as a schema --input-csv-empty-to-null[=INPUT-CSV-EMPTY-TO-NULL] When set, empty CSV values will be treated as NULL values --input-csv-separator=INPUT-CSV-SEPARATOR CSV separator character --input-csv-enclosure=INPUT-CSV-ENCLOSURE CSV enclosure character --input-csv-escape=INPUT-CSV-ESCAPE CSV escape character - --input-excel-header=INPUT-EXCEL-HEADER When set, Excel header will be used as a schema - --input-excel-sheet-name=INPUT-EXCEL-SHEETNAME When set, Excel sheet name will be selected for reading - --input-excel-offset=INPUT-EXCEL-OFFSET Offset to start reading from --input-xml-node-path=INPUT-XML-NODE-PATH XML node path to a subtree from which schema should be extracted, for example /root/element This is not xpath, just a node names separated by slash --input-xml-buffer-size=INPUT-XML-BUFFER-SIZE XML buffer size in bytes --input-parquet-columns=INPUT-PARQUET-COLUMNS Columns to read from parquet file (multiple values allowed) --input-parquet-offset=INPUT-PARQUET-OFFSET Offset to start reading from -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question @@ -381,7 +383,8 @@ Options: --statistics Display column chunks statistics details --page-headers Display page headers details -h, --help Display help for the given command. When no command is given display help for the list command - -q, --quiet Do not output any message + --silent Do not output any message + -q, --quiet Only errors are displayed. All other output is suppressed -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question @@ -454,6 +457,7 @@ Options: --output-php Print schema as PHP code --output-table Print schema as ascii table --output-ascii Print schema as ascii list + --db-column[=DB-COLUMN] Filter schema by column name(s) (multiple values allowed) --config=CONFIG Path to a local php file that MUST return instance of: Flow\ETL\Config -c, --db-connection-file=DB-CONNECTION-FILE Path to file that returns and instance of \Doctrine\DBAL\Connection -h, --help Display help for the given command. When no command is given display help for the list command diff --git a/documentation/components/core/aggregations.md b/documentation/components/core/aggregations.md index 7087294a74..f956cfff11 100644 --- a/documentation/components/core/aggregations.md +++ b/documentation/components/core/aggregations.md @@ -17,17 +17,39 @@ Each group created by `groupBy` function can be aggregated using one of the aggr - [`COLLECT_UNIQUE()`](/src/core/etl/src/Flow/ETL/Function/CollectUnique.php) - [`FIRST()`](/src/core/etl/src/Flow/ETL/Function/First.php) - [`LAST()`](/src/core/etl/src/Flow/ETL/Function/Last.php) -- [`STRIRNG_AGG()`](/src/core/etl/src/Flow/ETL/Function/StringAggregate.php) +- [`STRING_AGG()`](/src/core/etl/src/Flow/ETL/Function/StringAggregate.php) -All aggregation functions are implementing [`AggregatingFunction`](/src/core/etl/src/Flow/ETL/Function/AggregatingFunction.php) interface. +All aggregation functions implement [`AggregatingFunction`](/src/core/etl/src/Flow/ETL/Function/AggregatingFunction.php): +`aggregate(Rows $rows, array $indices, FlowContext $context)` folds the rows of one group (`$indices` of the batch) +into the aggregator's state, and `merge()` folds in the partial state of another aggregator of the same class, which +group by uses after it spilled. + +## Float arithmetic + +`sum()` and `average()` add floats as IEEE 754 doubles with compensated summation. `exact: true` switches to decimal +arithmetic: + +```php +read(from_array([['a' => 0.1], ['a' => 0.2]]))->aggregate([sum(ref('a'))]); // 0.30000000000000004 +df()->read(from_array([['a' => 0.1], ['a' => 0.2]]))->aggregate([sum(ref('a'), exact: true)]); // 0.3 +``` ## Example ```php -read(from_csv(__DIR__ . '/power-plant-daily.csv', delimiter: ';')) + ->read(from_csv(__DIR__ . '/power-plant-daily.csv', separator: ';')) ->withEntry('production_kwh', ref('Produkcja(kWh)')) ->withEntry('consumption_kwh', ref('Zużycie(kWh)')) ->withEntry('date', ref('Zaktualizowany czas')->toDate('Y/m/d')->dateFormat('Y/m')) @@ -51,7 +73,7 @@ data_frame() ->withEntry('consumption_kwh_max', ref('consumption_kwh_max')->round(lit(2))) ->withEntry('production_kwh_sum', ref('production_kwh_sum')->round(lit(2))) ->withEntry('consumption_kwh_sum', ref('consumption_kwh_sum')->round(lit(2))) - ->withEntry('consumption', ref('consumption_kwh_sum')->divide(ref('production_kwh_sum'))) + ->withEntry('consumption', ref('consumption_kwh_sum')->divide(ref('production_kwh_sum'), 4, Rounding::HALF_UP)) ->withEntry('consumption', ref('consumption')->multiply(lit(100))->round(lit(2))) ->withEntry('consumption', concat(ref('consumption'), lit('%'))) ->write(to_output(truncate: false)) diff --git a/documentation/components/core/batch-processing.md b/documentation/components/core/batch-processing.md index 595d496e04..02b7371753 100644 --- a/documentation/components/core/batch-processing.md +++ b/documentation/components/core/batch-processing.md @@ -75,6 +75,7 @@ The `batchBy()` method ensures that all rows with the same column value stay in - When `minSize` is specified: batches accumulate until reaching minimum size, then yield on group boundary - When `minSize` is omitted: each unique group value gets its own batch - Batches may exceed `minSize` to keep large groups intact +- Group values compare by value (equal datetimes or uuids are one group); nulls form one group > **Use Case**: If you're loading orders with line items and using a DELETE+INSERT pattern, `batchBy('order_id')` ensures all line items for an order are in the same batch, preventing foreign key violations. @@ -89,7 +90,6 @@ $dataFrame = data_frame() ->read($extractor) ->filter($condition) ->collect() // Collect all filtered data into single batch - ->sortBy([col('name')]) // Now can sort the collected data ->write($loader) ->run(); ``` @@ -97,7 +97,7 @@ $dataFrame = data_frame() > **Memory Warning**: The `collect()` method loads all data into memory at once. This can cause memory exhaustion > with large datasets. Use only when: > - You're certain the entire dataset fits comfortably in available memory -> - You need operations that require all data (like sorting) +> - The next step needs the whole dataset in one batch > - You're working with small to medium datasets ## Memory Management Strategies @@ -116,5 +116,5 @@ $report = data_frame() ->write($loader) ->run(analyze: analyze()); -echo "Peak memory usage: " . $report->statistics()->memory->max()->inMb() . " bytes\n"; +echo "Peak memory usage: " . $report->statistics()->memory->max()->inMb() . " MB\n"; ``` \ No newline at end of file diff --git a/documentation/components/core/building-blocks.md b/documentation/components/core/building-blocks.md index f796b33abb..4a5431fe21 100644 --- a/documentation/components/core/building-blocks.md +++ b/documentation/components/core/building-blocks.md @@ -31,8 +31,8 @@ $rows = array_to_rows( ); ``` -Rows are the main data structure in Flow ETL, they're used to represent data in the data frame. -Extractors are yielding Rows and Loaders are saving Rows. +Extractors yield `Rows`, transformers return new `Rows`, loaders write them. A record is read back with +`$rows->values($i)` (one row as an array), `$rows->toArray()` (every row) or `$rows->column('name')->value($i)`. ## Column Types @@ -69,10 +69,10 @@ A column holds exactly one type. `null|T` spells a nullable column, and a nullab structure element; every other union is refused. Declare the widest common type with `str_schema()`, or `json_schema()` when the shape is genuinely dynamic. -The schema is declared, never guessed: `array_to_rows()` takes it as its second argument and the column backend -([`Backend`](/src/core/etl/src/Flow/ETL/Column/Backend.php)) builds `Rows` against it, casting each value to the type -its column declares. A value the declared type refuses aborts the batch -with a `SchemaMismatchException` naming the column and its row. +The schema is declared, never guessed: `array_to_rows()` takes it as its second argument and the +[column backend](/documentation/components/core/column-backend.md) builds `Rows` against it, casting each value to the +type its column declares. A value the declared type refuses aborts the batch with a `SchemaMismatchException` naming +the column and its row. Schema *inference* belongs to the readers, which sample a source and derive a schema from it before any row flows - see [Schema](/documentation/components/core/schema.md). diff --git a/documentation/components/core/caching.md b/documentation/components/core/caching.md index 75d600b79a..5053b0a47f 100644 --- a/documentation/components/core/caching.md +++ b/documentation/components/core/caching.md @@ -7,14 +7,10 @@ The goal of cache is to serialize and save on disk (or in another location defined by Cache implementation) already transformed dataset. -Cache will run a pipeline, catching each Rows and saving them into cache -from where those rows can be later extracted. +Cache runs the pipeline and saves each batch (`Rows`) into the cache, from where it can be read later. -Internally, each cached batch of Rows is stored under its own cache key, and the pipeline's cache id -points at an index - a single-column (`key`) Rows value listing those chunk keys in insertion order. - -This is useful for operations that require full transformation of dataset before -moving forward, like, for example, sorting. +Each batch is stored under its own cache key, and the pipeline's cache id points at an index - a batch with `key` +and `rows` columns listing those chunk keys and their row counts in insertion order. Another interesting use case for caching would be to share the dataset between multiple data processing pipelines. So instead of going to datasource multiple times and then repeating all transformations, only one ETL would @@ -68,17 +64,21 @@ To use different cache implementation please use `ConfigBuilder` ```php cache( - new PSRSimpleCache( - new Psr16Cache( - new ArrayAdapter() - ), - new FloeSerializer(new AdaptiveBackend()), - ) - ); + ->cache( + new PSRSimpleCache( + new Psr16Cache(new ArrayAdapter()), + new FloeSerializer(new AdaptiveBackend()), + ) + ); ``` The following implementations are available out of the box: @@ -86,6 +86,8 @@ The following implementations are available out of the box: * [InMemory](/src/core/etl/src/Flow/ETL/Cache/Implementation/InMemoryCache.php) * [LocalFilesystem](/src/core/etl/src/Flow/ETL/Cache/Implementation/FilesystemCache.php) * [PSRSimpleCache](/src/core/etl/src/Flow/ETL/Cache/Implementation/PSRSimpleCache.php) +* [ApcuCache](/src/core/etl/src/Flow/ETL/Cache/Implementation/ApcuCache.php) - `new ApcuCache($serializer, $namespace)`, + requires `ext-apcu` PSRSimpleCache makes possible to use any of the [psr/simple-cache-implementation](https://packagist.org/providers/psr/simple-cache-implementation) @@ -93,10 +95,12 @@ but it does not come with any out of the box. ## Serialization -Persisting caches (`FilesystemCache`, `PSRSimpleCache`) turn `Rows` into bytes through a +Persisting caches (`FilesystemCache`, `PSRSimpleCache`, `ApcuCache`) turn `Rows` into bytes through a [`Serializer`](/src/core/etl/src/Flow/Serializer/Serializer.php). The default is -[`FloeSerializer`](/src/core/etl/src/Flow/Floe/FloeSerializer.php), which encodes to the -[Floe](/documentation/components/core/floe.md) binary format. +[`FloeSerializer`](/src/core/etl/src/Flow/Floe/FloeSerializer.php), which writes each batch as one +[Floe](/documentation/components/core/floe.md) BATCH frame and reads it back into the +[column backend](/documentation/components/core/column-backend.md) it was built with - +`new FloeSerializer($backend, $batchSize = 1000)`. `Cache::get()` returns one fully materialized `Rows` per key. The caching processor writes exactly one batch per cache key, so each key holds a single batch bounded by `DataFrame::cache(cacheBatchSize:)` @@ -129,5 +133,6 @@ use function Flow\ETL\DSL\filesystem_cache; filesystem_cache(new MyCustomSerializer()); ``` -`FilesystemCache` stores each entry in a file named after the cache key, with no extension - the -on-disk bytes are whatever the configured serializer produced. \ No newline at end of file +`FilesystemCache` stores each entry in a file named after the cache key, with no extension, under hash-prefixed +subdirectories, and its schema the same way under `.schema` - the entry bytes are whatever the configured serializer +produced. \ No newline at end of file diff --git a/documentation/components/core/column-backend.md b/documentation/components/core/column-backend.md new file mode 100644 index 0000000000..770f0763c9 --- /dev/null +++ b/documentation/components/core/column-backend.md @@ -0,0 +1,69 @@ +# Column Backend + +[DOC_LINK:/documentation/components/core/core.md] + +[TOC] + +Every batch (`Rows`) stores one column per schema definition. The +[Backend](/src/core/etl/src/Flow/ETL/Column/Backend.php) decides where those columns live and builds them. A data +frame has exactly one backend, set on its config: + +```php +backend(new PhpBackend())) + ->read(from_array([['id' => 1], ['id' => 2]])) + ->withEntry('double', ref('id')->multiply(lit(2))) + ->fetch(); + +$rows->column('double')::class; // Flow\ETL\Column\Php\ScalarColumn +$rows->toArray(); // [['id' => 1, 'double' => 2], ['id' => 2, 'double' => 4]] +``` + +## Backends + +| Backend | Columns | Requires | +|--------------------------------------------------------------------------|-------------------------------|--------------------------------------------------------------------------------| +| [AdaptiveBackend](/src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php) | `RustBackend` or `PhpBackend` | nothing (the default) | +| [PhpBackend](/src/core/etl/src/Flow/ETL/Column/PhpBackend.php) | PHP arrays | nothing | +| `RustBackend` | Apache Arrow arrays | the [flow_php extension](/documentation/components/extensions/flow-php-ext.md) | + +When `extension_loaded('flow_php')` is true, `AdaptiveBackend` picks `RustBackend`. Else it picks `PhpBackend`. +Both produce the same values: `PhpBackend` is the reference implementation, the extension is an accelerator. Set +`PhpBackend` explicitly to opt out of the extension while it is loaded. + +## What the backend builds + +The configured backend builds every column a pipeline produces: + +- every batch an extractor yields: a batch built elsewhere is adopted (copied once) before the first step sees it, +- function results (`withEntry()`, `filter()`, `lit()`, ...), +- joins, sorts, group-by, window and repartition outputs, including their spilled reads, +- cache and Floe reads (the default `FloeSerializer` takes the same backend). + +Code that builds batches outside a pipeline passes the backend itself - `$context->backend()` inside an extractor, +transformer or function, or any `Backend` to the DSL: + +```php + 1], ['id' => 2]], schema(int_schema('id')), new PhpBackend()); +``` + +## Memory + +`RustBackend` keeps column buffers outside PHP's memory manager, where `memory_get_usage()` and `memory_limit` do not +see them. `Backend::allocatedBytes()` reports them, and Flow adds them to the process memory its spilling steps +(sort, join, group-by) compare with their memory limit. diff --git a/documentation/components/core/core.md b/documentation/components/core/core.md index 19ced77f0e..02254f9456 100644 --- a/documentation/components/core/core.md +++ b/documentation/components/core/core.md @@ -16,7 +16,8 @@ A Data Frame is the core component of Flow PHP's ETL framework. It represents a ## Key Features -- **Memory Efficient**: Processes data in chunks using generators, avoiding memory exhaustion +- **Memory Efficient**: Processes data in batches using generators, avoiding memory exhaustion +- **Columnar**: Every batch stores one column per schema definition, built by a configurable [column backend](/documentation/components/core/column-backend.md) - **Lazy Evaluation**: Operations are only executed when needed - **Immutable**: Each transformation returns a new DataFrame instance - **Type Safe**: Strict typing throughout with comprehensive schema support @@ -52,28 +53,37 @@ trigger it should print - `Trigger::rows` by default, `Trigger::run` for the pla for the plan `count()` executes. ```php -echo data_frame() - ->read(from_csv('orders.csv')) +$dataFrame = data_frame() + ->read(from_csv('/data/orders.csv')) ->filter(ref('email')->isNotNull()) ->write(to_json('out.json')) - ->explain()->toString(); + ->select('id', 'email'); + +echo $dataFrame->explain()->toString(); ``` ```text Outputs -├─ #3 Result +├─ #4 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 +│ └─ #3 Select +│ │ Columns: id, email +│ └─ #2 Filter +│ │ Condition: IsNotNull +│ └─ #1 Read +│ Extractor: CSVExtractor +│ Source: file:///data/orders.csv +└─ #5 Write │ Loader: JsonLoader └─ #2 Filter (shared) ``` ```php -echo $dataFrame->explain(Trigger::run)->toString(); +echo data_frame() + ->read(from_csv('/data/orders.csv')) + ->filter(ref('email')->isNotNull()) + ->write(to_json('out.json')) + ->explain(Trigger::run)->toString(); ``` ```text @@ -83,15 +93,15 @@ echo $dataFrame->explain(Trigger::run)->toString(); │ Condition: IsNotNull └─ #1 Read Extractor: CSVExtractor + Source: file:///data/orders.csv ``` `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. +`Outputs` lists everything the frame produces: `Result` is what a rows-returning trigger reads, `Write` is the sink. +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. @@ -102,7 +112,7 @@ input, numbered with the rest of the plan, and it runs with this frame's configu |------------------------------|-------------------------------------------------------------------------------------| | `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 | +| `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 | @@ -115,11 +125,14 @@ echo $dataFrame->explain()->toString(format: Format::flow); ```text #1 Read │ Extractor: CSVExtractor +│ Source: file:///data/orders.csv └─ #2 Filter │ Condition: IsNotNull - ├─ #3 Result - │ Rows this plan hands out: to the trigger, or to the node reading it - └─ #4 Write + ├─ #3 Select + │ │ Columns: id, email + │ └─ #4 Result + │ Rows this plan hands out: to the trigger, or to the node reading it + └─ #5 Write Loader: JsonLoader ``` @@ -132,21 +145,28 @@ echo $dataFrame->explain()->toString(format: Format::boxes); │ Outputs ├──────────────┐ └─────────────┬─────────────┘ │ ┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -│ #3 Result ││ #4 Write │ +│ #4 Result ││ #5 Write │ │ ──────────────────── ││ ──────────────────── │ │ Rows this plan hands out: ││ Loader: JsonLoader │ │ to the trigger, or to the ││ │ │ node reading it ││ │ └─────────────┬─────────────┘└─────────────┬─────────────┘ ┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -│ #2 Filter ││ #2 Filter │ +│ #3 Select ││ #2 Filter │ │ ──────────────────── ││ (shared) │ -│ Condition: IsNotNull ││ │ +│ Columns: id, email ││ │ └─────────────┬─────────────┘└───────────────────────────┘ ┌─────────────┴─────────────┐ +│ #2 Filter │ +│ ──────────────────── │ +│ Condition: IsNotNull │ +└─────────────┬─────────────┘ +┌─────────────┴─────────────┐ │ #1 Read │ │ ──────────────────── │ │ Extractor: CSVExtractor │ +│ Source: │ +│ file:///data/orders.csv │ └───────────────────────────┘ ``` @@ -181,6 +201,7 @@ Physical plan │ On: id = id │ Prefix: joined_ │ Storage: FilesystemBuckets + │ Memory: 1000 MB │ Buckets: 64 │ Batch: 1000 └─ Right side: Pipeline #0 @@ -188,6 +209,9 @@ Physical plan Statistics: rows exact 1 · size unknown ``` +`Memory: 1000 MB` is the default limit under `memory_limit = -1`. With a set `memory_limit` it is 70% of it, or +`FLOW_MAX_MEMORY`. + A joined frame is planned apart, so its pipelines are numbered apart - `Right side:` says which plan they belong to. Every source lists what it declares about itself before a row is read - `exact n`, `≤ n` (a guaranteed bound), `~n ±e%` (an estimate) or `unknown`. A source that declares nothing lists no `Statistics:` line. @@ -203,7 +227,7 @@ DataFrames are created using the `data_frame()` DSL function and populated with ```php read(from_array([ @@ -237,13 +261,13 @@ $dataFrame = data_frame() 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 | -| `CountFromStatistics` | `count()` over a source that knows its rows exactly reads that number, no rows | +| 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 | +| `CountFromStatistics` | `count()` over a source that knows its rows exactly reads that number, no rows | Rules live in `Flow\ETL\Optimizer\Rule` and are configured through `config_builder()->optimizer()`: @@ -273,7 +297,7 @@ data_frame(config_builder()->optimizer(Optimizer::default()->with(new MyRule())) For detailed information about specific DataFrame operations, see the following component documentation: ### Core Operations -- **[Building Blocks](/documentation/components/core/building-blocks.md)** - Understanding Rows, Entries, and basic data structures +- **[Building Blocks](/documentation/components/core/building-blocks.md)** - Rows, columns and the schema that describes them - **[Transformations](/documentation/components/core/transformations.md)** - Reusable DataFrame transformations and the Transformation interface - **[Select/Drop](/documentation/components/core/select-drop.md)** - Column selection and removal - **[Rename](/documentation/components/core/rename.md)** - Column renaming strategies @@ -291,10 +315,11 @@ For detailed information about specific DataFrame operations, see the following - **[Window Functions](/documentation/components/core/window-functions.md)** - Advanced analytical functions ### Memory & Performance +- **[Column Backend](/documentation/components/core/column-backend.md)** - Where batch columns live: PHP arrays or the flow_php extension - **[Batch Processing](/documentation/components/core/batch-processing.md)** - Controlling batch sizes and memory collection - **[Partitioning](/documentation/components/core/partitioning.md)** - Data partitioning for efficient processing - **[Caching](/documentation/components/core/caching.md)** - Performance optimization through caching -- **[Floe File Format](/documentation/components/core/floe.md)** - Flow's native self-describing binary row format +- **[Floe File Format](/documentation/components/core/floe.md)** - Flow's native self-describing columnar binary format - **[Source Statistics](/documentation/components/core/statistics.md)** - What a source declares about its rows and bytes before it is read - **[Data Retrieval](/documentation/components/core/data-retrieval.md)** - Methods for getting processed data diff --git a/documentation/components/core/data-manipulation.md b/documentation/components/core/data-manipulation.md index c2e4f9e50c..dae7a62fc9 100644 --- a/documentation/components/core/data-manipulation.md +++ b/documentation/components/core/data-manipulation.md @@ -37,7 +37,7 @@ data_frame() > the richest type that parses, so `'19.99'` read from a CSV infers as `?float`. Restrict the candidates with > `->types(...)`, or take strings only with `->allStrings()`. -## Adding Entries with withEntry() +## Adding Columns with withEntry() Add new columns or modify existing ones using expressions: @@ -61,7 +61,9 @@ data_frame() Create duplicate rows for testing or data expansion: -### duplicateRow() - Duplicate Specific Row +### duplicateRow() - Duplicate Matching Rows + +`duplicateRow()` takes a boolean condition; every row it is true for appears twice. ```php 2, 'name' => 'Product B'], ['id' => 3, 'name' => 'Product C'], ])) - ->duplicateRow(1) // Duplicate the second row (0-indexed) + ->duplicateRow(ref('id')->equals(lit(2))) ->write(to_output()) ->run(); @@ -81,29 +83,7 @@ data_frame() ## Removing Duplicates -Remove duplicate rows from your dataset: - -```php -read(from_array([ - ['id' => 1, 'name' => 'Product A', 'category' => 'Electronics'], - ['id' => 2, 'name' => 'Product B', 'category' => 'Books'], - ['id' => 1, 'name' => 'Product A', 'category' => 'Electronics'], // Duplicate - ['id' => 3, 'name' => 'Product C', 'category' => 'Electronics'], - ['id' => 2, 'name' => 'Product B', 'category' => 'Books'], // Duplicate - ])) - ->dropDuplicates() // Remove all duplicate rows - ->write(to_output()) - ->run(); - -// Result: Only unique rows remain -``` - -### Selective Duplicate Removal - -Remove duplicates based on specific columns: +`dropDuplicates()` takes at least one column and keeps the first row of each distinct combination of those columns: ```php read(from_array([ ['id' => 1, 'name' => 'Product A', 'version' => 1], - ['id' => 1, 'name' => 'Product A', 'version' => 2], // Same product, different version + ['id' => 1, 'name' => 'Product A', 'version' => 2], ['id' => 2, 'name' => 'Product B', 'version' => 1], - ['id' => 3, 'name' => 'Product C', 'version' => 1], ])) - ->dropDuplicates('id', 'name') // Remove duplicates based on id and name only + ->dropDuplicates('id', 'name') ->write(to_output()) ->run(); -// Result: Keep first occurrence of each id/name combination +// Result: [1, 'Product A', 1], [2, 'Product B', 1] ``` diff --git a/documentation/components/core/data-retrieval.md b/documentation/components/core/data-retrieval.md index f01f4a87f7..4344f242ea 100644 --- a/documentation/components/core/data-retrieval.md +++ b/documentation/components/core/data-retrieval.md @@ -67,8 +67,8 @@ foreach ($dataFrame->getEachAsArray() as $rowArray) { // Fetch limited results (safe) $firstTen = $dataFrame->fetch(10); -foreach ($firstTen as $row) { - // Process row +foreach ($firstTen->toArray() as $row) { + echo "ID: " . $row['id'] . "\n"; } // Fetch all results (dangerous for large datasets!) diff --git a/documentation/components/core/error-handling.md b/documentation/components/core/error-handling.md index 3a3bec58d9..b68c2b8b99 100644 --- a/documentation/components/core/error-handling.md +++ b/documentation/components/core/error-handling.md @@ -5,19 +5,19 @@ By default an exception thrown while reading, transforming or loading stops the pipeline. An [ErrorHandler](/src/core/etl/src/Flow/ETL/ErrorHandler.php) decides per failure instead: -| Method | Error carries | Action other than `propagate` (rethrow) | -|---|---|---| -| `onExtraction(ExtractionError): ExtractionAction` | `cause`, `extractor` | `endSource` - stop reading; rows read so far still flow and the run completes | -| `onTransformation(TransformationError): TransformationAction` | `cause`, `transformer`, `rows` | `skipBatch` - drop the batch, continue with the next one | -| `onLoading(LoadingError): LoadingAction` | `cause`, `loader`, `rows` | `skipLoader` - the failing loader misses this batch, the remaining steps still run | +| Method | Error carries | Action other than `propagate` (rethrow) | +|---------------------------------------------------------------|--------------------------------|------------------------------------------------------------------------------------| +| `onExtraction(ExtractionError): ExtractionAction` | `cause`, `extractor` | `endSource` - stop reading; rows read so far still flow and the run completes | +| `onTransformation(TransformationError): TransformationAction` | `cause`, `transformer`, `rows` | `skipBatch` - drop the batch, continue with the next one | +| `onLoading(LoadingError): LoadingAction` | `cause`, `loader`, `rows` | `skipLoader` - the failing loader misses this batch, the remaining steps still run | Built-in handlers: -| Handler | Extraction | Transformation | Loading | -|---|---|---|---| -| `throw_error_handler()` (default) | `propagate` | `propagate` | `propagate` | -| `ignore_error_handler()` | `endSource` | `skipBatch` | `skipLoader` | -| `skip_rows_handler()` | `endSource` | `skipBatch` | `propagate` | +| Handler | Extraction | Transformation | Loading | +|-----------------------------------|-------------|----------------|--------------| +| `throw_error_handler()` (default) | `propagate` | `propagate` | `propagate` | +| `ignore_error_handler()` | `endSource` | `skipBatch` | `skipLoader` | +| `skip_rows_handler()` | `endSource` | `skipBatch` | `propagate` | ```php upper()` over a null column. To tolerate the failure for +A scalar function that receives a value it cannot process throws `EvaluationException` (an +`InvalidArgumentException`) with the failing row of the batch, for example `ref('text')->upper()` over a null value: +`ToUpper function requires non-null value (row 1)`; the original exception is `getPrevious()`. To tolerate the failure for one function instead of the whole pipeline, wrap it in `optional()` - it evaluates the wrapped function and returns null when it throws: @@ -92,6 +93,8 @@ For fine-grained error handling during row processing operations: use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Rows; +use function Flow\ETL\DSL\{data_frame, from_array}; + function validateAndProcess(array $row): void { /* your code */ } function logInvalidRow(array $row, string $message): void { /* your code */ } function logGeneralError(array $row, Throwable $error): void { /* your code */ } @@ -100,7 +103,7 @@ $successCount = 0; $errorCount = 0; data_frame() - ->read($unreliableDataExtractor) + ->read(from_array([['id' => 1], ['id' => 2]])) ->forEach(function(Rows $rows) use (&$successCount, &$errorCount) { foreach ($rows->toArray() as $row) { try { diff --git a/documentation/components/core/filter.md b/documentation/components/core/filter.md index 1e6a3e82c1..0edb27daa4 100644 --- a/documentation/components/core/filter.md +++ b/documentation/components/core/filter.md @@ -15,11 +15,20 @@ data_frame() ['a' => 100, 'b' => 100], ['a' => 100, 'b' => 200] ])) - ->filter(ref('b')->divide(lit(2))->equals(lit('a'))) + ->filter(ref('b')->divide(lit(2))->equals(ref('a'))) ->write(to_output(false)) ->run(); ``` +```text ++-----+-----+ +| a | b | ++-----+-----+ +| 100 | 200 | ++-----+-----+ +1 rows +``` + ## Custom Filter Functions Business logic the built-in functions do not cover goes into a `ScalarFunction` that returns a boolean column: @@ -34,7 +43,7 @@ use Flow\ETL\Function\{Parameter, ScalarFunction, ScalarFunctionChain}; use Flow\ETL\Rows; use Flow\Types\Type; -use function Flow\ETL\DSL\{data_frame, ref}; +use function Flow\ETL\DSL\{data_frame, from_array, ref, to_output}; use function Flow\Types\DSL\type_boolean; final class HighValuePurchase implements ScalarFunction @@ -68,17 +77,21 @@ final class HighValuePurchase implements ScalarFunction $results[] = $amount > 1000 && $types[$i] === 'purchase'; } - return (new ResultColumn())->of($this, $results); + return (new ResultColumn($context->backend()))->of($this, $results); } } data_frame() - ->read($transactionExtractor) + ->read(from_array([ + ['amount' => 1500, 'type' => 'purchase'], + ['amount' => 1500, 'type' => 'refund'], + ['amount' => 200, 'type' => 'purchase'], + ])) ->filter(new HighValuePurchase(ref('amount'), ref('type'))) - ->write($highValueTransactionLoader) + ->write(to_output(false)) ->run(); ``` -> **Performance Note**: Callback-based filtering cannot be optimized by the engine and should be used sparingly. When possible, prefer built-in scalar functions for better performance. +> **Performance Note**: prefer built-in scalar functions when they cover the logic. - [Until](/documentation/components/core/until.md) diff --git a/documentation/components/core/floe.md b/documentation/components/core/floe.md index 8c6d1a6ec4..2ea723b4ca 100644 --- a/documentation/components/core/floe.md +++ b/documentation/components/core/floe.md @@ -4,9 +4,10 @@ [TOC] -Floe is Flow's native, self-describing binary file format for `Rows`. It stores the schema inside -the file, evolves seamlessly across appended sections, and reads back through the DataFrame API with -`from_floe()` / `to_floe()`. Files use the `.floe` extension. +Floe is Flow's native, self-describing, columnar binary file format. Each batch is written as one BATCH frame holding +every column in the Arrow buffer layout, the schema lives in the file's footer, and `from_floe()` reads the batches +back into the configured [column backend](/documentation/components/core/column-backend.md). Files use the `.floe` +extension. ## Writing @@ -69,8 +70,7 @@ machinery as other file loaders: ```php schema(flow_context(config())); +$schema = from_floe(__DIR__ . '/output.floe')->schema(); ``` ## Reading the First or Last Rows @@ -207,58 +206,45 @@ thrown before anything is written. `merge_floe()` works on the local filesystem; The whole-value serialization paths - the [cache](/documentation/components/core/caching.md) and `Flow\Floe\FloeSerializer` (the config default serializer) - stream: `serialize(Rows, DestinationStream)` goes through `FloeStreamWriter`, which writes one BATCH frame, and `unserialize(SourceStream)` through the -strict `FloeStreamReader::rows()`, read in frame-sized batches of at most `batchSize` rows (default 1000). String payloads round-trip through the -`Flow\Serializer\DSL` helpers `serialize_to_string()` / `unserialize_from_string()`. A whole-value -`unserialize()` verifies the decoded row count against the footer and rejects torn payloads. Numbers and -guidance live in the [caching documentation](/documentation/components/core/caching.md). +strict `FloeStreamReader::rows()`, read in frame-sized batches of at most `batchSize` rows (default 1000) and +returned as one `Rows` in the serializer's backend. String payloads round-trip through the `Flow\Serializer\DSL` +helpers `serialize_to_string()` / `unserialize_from_string()`. A whole-value `unserialize()` verifies the decoded row +count against the footer and rejects torn payloads. ## Validation -Floe asserts, it never casts. A value that does not match its column type is rejected - it is never -converted to fit. - -Two checks run when a batch is written: +Floe never casts. Values are checked when a batch is built - a value that does not fit its column throws +`SchemaMismatchException` before anything reaches the writer. The writer then checks each batch's schema against +the file's schema, fixed when the write session starts: `FloeWriter` takes it as an argument, `to_floe()` takes +`withSchema()` or else the first batch's schema: -- **Column set** - a row carrying a column the file's schema does not declare is rejected. Always on. -- **Per value** - every value must satisfy its column type. Gated by `validateData`, on by default. +| Batch schema | Result | +|---------------------------------------------------------------|-------------------------------| +| a column the file does not declare | `IncompatibleSchemaException` | +| lacks a column the file declares nullable | written, reads back as null | +| lacks a column the file declares not nullable | `IncompatibleSchemaException` | +| a column of another type, or nullable where the file's is not | `IncompatibleSchemaException` | ```php read(from_array([['id' => 1], ['id' => 'AB-1']])) - ->write(to_floe(__DIR__ . '/orders.floe')) - ->run(); -``` - -The first batch fixes the file's schema to `integer`, so the second one throws: +use Flow\ETL\Column\PhpBackend; +use Flow\Floe\FloeWriter; +use function Flow\ETL\DSL\{array_to_rows, int_schema, schema, str_schema}; +use function Flow\Filesystem\DSL\{native_local_filesystem, path}; -``` -Floe write session schema is fixed and this batch does not fit it: column "id" (row 0): -could not convert 'AB-1' (string) to integer. +$writer = new FloeWriter(native_local_filesystem(), schema(int_schema('id')), new PhpBackend()); +$writer->create(path(__DIR__ . '/orders.floe')); +$writer->write(array_to_rows([['id' => 1]], schema(int_schema('id')), new PhpBackend())); +$writer->write(array_to_rows([['id' => 'AB-1']], schema(str_schema('id')), new PhpBackend())); ``` -Both checks throw `IncompatibleSchemaException` before any bytes reach the destination, so a rejected -batch leaves the file readable. Other messages take the same shape: - ``` -column "amount" (row 0): could not convert null to string, column is not nullable -new column "email" +Floe write session schema is fixed and this batch does not fit it: Mismatched Definitions: + |-- expected: id, given: id ``` -`validate_data: false` skips the per-value check only. The column-set check still runs, so silent -column loss cannot be unlocked. This mirrors parquet-java's `ParquetWriter::withValidation()`. - -Two behaviours differ from other columnar formats on purpose: - -- **Absent is not null.** A row that omits a column writes an absent flag and reads back as null; - a row that carries an explicit `null` in a non-nullable column is rejected. Parquet turns a missing - optional field into a null and rejects a missing required one; Arrow cannot omit a column at all. -- **An int is not a float.** An integer value in a `float` column is rejected. pyarrow, parquet-java - and Avro all widen it silently. +The check runs before any bytes reach the destination, so a rejected batch leaves the file readable. ## On-Disk Layout diff --git a/documentation/components/core/group-by.md b/documentation/components/core/group-by.md index 31ff4d67ef..d6d3ddfa8f 100644 --- a/documentation/components/core/group-by.md +++ b/documentation/components/core/group-by.md @@ -2,11 +2,8 @@ [DOC_LINK:/documentation/components/core/core.md] -Grouping is a common operation in data analysis. The concept is no different from the one you know from SQL. - -To group data you need to use `DataFrame::groupBy` function. - -Example: +`DataFrame::groupBy()` returns a `GroupedDataFrame`; `aggregate()` turns it back into a `DataFrame` with one row per +group: ```php data_frame() @@ -16,41 +13,33 @@ data_frame() ['id' => 3, 'group' => 'A'], ['id' => 4, 'group' => 'B'], ['id' => 5, 'group' => 'A'], - ['id' => 6, 'group' => 'B'], - ['id' => 7, 'group' => 'A'], - ['id' => 8, 'group' => 'B'], - ['id' => 9, 'group' => 'A'], - ['id' => 10, 'group' => 'B'], ])) ->groupBy([ref('group')]) + ->aggregate(count(ref('id'))) ->write(to_output(truncate: false)) ->run(); ``` -However, the result of this operation is not very useful. It will just return a `DataFrame` with one column `group`: - ```console -+-------+ -| group | -+-------+ -| A | -| B | -+-------+ ++-------+----------+ +| group | id_count | ++-------+----------+ +| A | 3 | +| B | 2 | ++-------+----------+ 2 rows ``` -To make it more useful, you need to use one of the aggregation functions. - [Aggregations](/documentation/components/core/aggregations.md) ## Buckets Storage -`groupBy()` partitions rows by the hashed grouping key into buckets through a `BucketsStorage` - the -same abstraction used by [external sort](/documentation/components/core/sort.md) and -[join](/documentation/components/core/join.md). The default is `FilesystemBuckets`: buckets are -spilled to the local filesystem cache directory (as Floe files), so memory usage is bounded by the -largest bucket instead of the whole grouped dataset. Other implementations are `MemoryBuckets` -(buckets kept in memory) and `PSRCacheBuckets` (buckets in any PSR-16 cache). +While the process stays under the memory limit, `groupBy()` aggregates in one pass and writes nothing. Past the limit it +partitions the rest of the stream by the hashed grouping key into buckets of a `BucketsStorage` - the same abstraction +used by [external sort](/documentation/components/core/sort.md) and [join](/documentation/components/core/join.md) - +aggregates each bucket on its own and merges the groups aggregated before the limit into them. The default storage is +`FilesystemBuckets` (Floe files in the local cache directory); `MemoryBuckets` and `PSRCacheBuckets` (any PSR-16 +cache) are the alternatives. `groupBy()` takes an optional trailing `GroupByAlgorithmBuilder`, so one operation can override the configured algorithm: @@ -59,10 +48,8 @@ algorithm: ->groupBy([ref('country')], hash_group_by()->storage(new MemoryBuckets())) ``` -The algorithm is configured through `config_builder()->groupBy(hash_group_by())` - all its options -live on the `hash_group_by()` builder. While the process is under `memoryLimit()` (the same default as the join and -the sort) the input aggregates in one pass and nothing is written; past it the rest of the stream is partitioned into -buckets of the storage, in frames of `batchSize` rows: +The algorithm is configured through `config_builder()->groupBy(hash_group_by())`. `memoryLimit()` defaults to the +same limit as the join and the sort (`FLOW_MAX_MEMORY`, otherwise 70% of `memory_limit`): ```php memoryLimit(Unit::fromMb(512)) // process memory past which buckets go to the storage ->bucketsCount(64) // number of buckets (default 64) ->batchSize(1000) // rows per bucket frame and per batch read back (default 1000) - ->storage(new MemoryBuckets()) // keep buckets in memory instead of on disk ) ) ->read(from_parquet('orders.parquet')) @@ -84,19 +70,16 @@ data_frame( ``` -### Spill column pruning +### Column pruning -Before rows are spilled to buckets, they are pruned to only the columns the group by actually reads: -the grouping references plus every column referenced by the aggregators. A row that is missing one of -those columns is normalized to a `null` entry for it (Spark/DuckDB semantics) - aggregators silently -skip `null` values, and STRICT schema mode does not throw for aggregate columns missing under a -`groupBy()`. +Before aggregating, the batch is pruned to the columns the group by reads: the grouping references plus every column +referenced by the aggregators. A grouping or aggregated column the input does not have throws +`SchemaDefinitionNotFoundException`. -Custom aggregators participate through `AggregatingFunction::references()`: return the references the -aggregator reads, or `null` when they cannot be statically enumerated - returning `null` disables -column pruning for the whole pipeline (rows are spilled with all their columns). +Custom aggregators take part through `AggregatingFunction::references()`: return the references the aggregator reads, +or `null` when they cannot be listed - `null` turns pruning off for that group by. ### Output order -Grouped output follows hash-bucket order, not input order. Group order was never a contract - apply -[sortBy](/documentation/components/core/sort.md) after aggregation when a specific order is needed. \ No newline at end of file +Group order is not a contract - past the memory limit groups come out in bucket order. For a specific +order, apply [sortBy](/documentation/components/core/sort.md) after aggregation. \ No newline at end of file diff --git a/documentation/components/core/join.md b/documentation/components/core/join.md index 77dd80e784..2878496772 100644 --- a/documentation/components/core/join.md +++ b/documentation/components/core/join.md @@ -13,7 +13,7 @@ called, and runs with the left DataFrame's configuration and error handler. ### join () -Main join method that partitions the right DataFrame into buckets and probes them with left rows through a hash table. +Main join method: builds a hash table from the right DataFrame and probes it with left rows. ### crossJoin () - Cartesian Product @@ -21,7 +21,8 @@ Joins each row from the left side with each row on the right side, creating `cou ### joinEach () - Streaming Join -Right side is dynamically generated for each left row, useful for large right-side datasets that don't fit in memory. +The right side is built for each left batch by `DataFrameFactory::from(Rows $rows)`, useful for large right-side +datasets that don't fit in memory. ## Join Types @@ -38,38 +39,36 @@ Joins follow SQL semantics - every matching pair of rows produces one output row right rows is emitted multiple times. A `null` join key never matches anything, including another `null` - rows with `null` keys are dropped by inner joins and null-padded (or kept, for `left_anti`) by outer joins. -> Flow uses hash join implementation where hashes are stored in buckets to optimize memory usage and performance. -> Rows are bucketed by the values of the join columns and every candidate pair is verified against +> Rows are hashed by the values of the join columns and every candidate pair is verified against > the join expression, so non-equality expressions (like `compare_any()`) are supported as well. > Mixed expressions still hash by their equality conditions - in `compare_all(Equal, Any)` rows are -> bucketed by the `Equal` columns and the `Any` part is verified per candidate pair; only joins with +> hashed by the `Equal` columns and the `Any` part is verified per candidate pair; only joins with > no equality condition at all fall back to comparing every pair. ## Buckets Storage -`join()` always partitions the right DataFrame into buckets through a `BucketsStorage` - the same abstraction used by -external sort - and the configured implementation decides how the join executes: +While the process stays under the memory limit, `join()` holds the right DataFrame in memory and streams the left one +through its hash table, so left rows keep their order. Past the limit both sides are partitioned by join key into +buckets of a `BucketsStorage` - the same abstraction used by external sort - and joined bucket pair by bucket pair: -| Buckets storage | Behavior | -|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `FilesystemBuckets` - **Default** | Both sides are partitioned by join key into buckets spilled to disk (Floe files), then joined pair by pair - the hash table is built from the smaller bucket of each pair. Memory usage is bounded by that bucket, left row order is not preserved. | -| `MemoryBuckets` | Right DataFrame is held in memory, left rows are streamed through a hash table and keep their order. Memory usage is bounded by the right side. | -| `PSRCacheBuckets` | Buckets are spilled into any PSR-16 cache. Executes like `FilesystemBuckets` (left row order is not preserved). | +| Buckets storage | Past the memory limit | +|-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------| +| `FilesystemBuckets` - **Default** | Both sides are spilled to disk (Floe files); the hash table is built from the smaller bucket of each pair. Left row order is not preserved. | +| `PSRCacheBuckets` | Like `FilesystemBuckets`, with buckets in any PSR-16 cache. | +| `MemoryBuckets` | Never partitions: the right DataFrame stays in memory whatever its size and left rows keep their order. | `join()` takes an optional trailing `JoinAlgorithmBuilder`, so one join can override the configured algorithm: ```php ignore -->join($right, on(['id' => 'id']), Join::left, hash_join()->storage(new MemoryBuckets())) +->join($right, join_on(['id' => 'id']), Join::left, hash_join()->storage(new MemoryBuckets())) ``` -`joinEach()` deliberately does not take one - it builds a DataFrame per row, so a per-call algorithm would be -rebuilt per row too. +`joinEach()` does not take one - it builds a DataFrame per left batch, so a per-call algorithm would be rebuilt per +batch too. The join algorithm is configured through `config_builder()->join(hash_join())` - all its options live on the -`hash_join()` builder. While the process stays under `memoryLimit()` the right side is held in memory and the left -side streams through in its own order; past it, both sides are partitioned into buckets of the storage. The limit -defaults to `FLOW_MAX_MEMORY`, otherwise 70% of PHP's `memory_limit` (1 GiB when it is `-1`), and is compared with the -whole process, so a join and a sort in one pipeline stay under it together: +`hash_join()` builder. `memoryLimit()` defaults to `FLOW_MAX_MEMORY`, otherwise 70% of PHP's `memory_limit` (1 GB +when it is `-1`), and is compared with the whole process, so a join and a sort in one pipeline stay under it together: ```php join( hash_join() ->memoryLimit(Unit::fromMb(512)) // process memory past which rows go to the storage - ->storage(new MemoryBuckets()) // or FilesystemBuckets (default) ->bucketsCount(64) // number of buckets ->batchSize(1000) // rows per bucket frame and per batch read back ) @@ -87,7 +85,7 @@ data_frame( ->read(from_parquet('orders.parquet')) ->join( data_frame()->read(from_parquet('sellers.parquet')), - join_on(['seller_id' => 'id'], join_prefix: 'seller_'), + join_on(['seller_id' => 'id'], join_prefix: 'joined_'), ) ->run(); ``` diff --git a/documentation/components/core/partitioning.md b/documentation/components/core/partitioning.md index 3ab9e81c47..7b004e4e4d 100644 --- a/documentation/components/core/partitioning.md +++ b/documentation/components/core/partitioning.md @@ -266,5 +266,7 @@ Output carries `path`, a `partitions` map, and one string column per partition ( ## Repartitioning -`repartition()` shuffles rows between batches in memory. It does not write directories - use the +`repartition()` shuffles the stream so every row sharing the given columns arrives in one batch. While the process +stays under the memory limit it groups in memory; past it the input is partitioned into buckets first, configured with +`config_builder()->repartition(hash_repartition()->memoryLimit(...))`. It does not write directories - use the loader's `partitionBy()` for that. diff --git a/documentation/components/core/pivot.md b/documentation/components/core/pivot.md index 1ff890945e..2827a62d2c 100644 --- a/documentation/components/core/pivot.md +++ b/documentation/components/core/pivot.md @@ -32,20 +32,21 @@ $salesData = data_frame() ['region' => 'South', 'product' => 'Phone', 'month' => 'Jan', 'sales' => 700], ['region' => 'South', 'product' => 'Phone', 'month' => 'Feb', 'sales' => 850], ])) - ->groupBy(['region', 'product']) + ->groupBy(['region']) ->pivot(col('product'), pivot_values('Laptop', 'Phone')) // creates the 'Laptop' and 'Phone' columns ->aggregate(sum(col('sales')->as('total_sales'))) - ->write(to_output()) + ->write(to_output(truncate: false)) ->run(); ``` -**Result Structure:** - -``` -| region | Laptop | Phone | -|--------|--------|-------| -| North | 2200 | 1700 | -| South | 2400 | 1550 | +```console ++--------+-------------+-------------+ +| region | Laptop | Phone | ++--------+-------------+-------------+ +| North | 2200.000000 | 1700.000000 | +| South | 2400.000000 | 1550.000000 | ++--------+-------------+-------------+ +2 rows ``` ## Monthly Sales Pivot @@ -69,17 +70,20 @@ $monthlySales = data_frame() ->groupBy(['region']) ->pivot(col('month'), discover_pivot_values()) // reads the month column once at build time ->aggregate(average(col('sales')->as('avg_sales'))) - ->write(to_output()) + ->write(to_output(truncate: false)) ->run(); ``` -**Result:** +Discovered values are sorted, strings by bytes: -``` -| region | Jan | Feb | Mar | -|--------|------|------|------| -| North | 5000 | 5500 | 6000 | -| South | 4500 | 4800 | 5200 | +```console ++--------+-------------+-------------+-------------+ +| region | Feb | Jan | Mar | ++--------+-------------+-------------+-------------+ +| North | 5500.000000 | 5000.000000 | 6000.000000 | +| South | 4800.000000 | 4500.000000 | 5200.000000 | ++--------+-------------+-------------+-------------+ +2 rows ``` @@ -102,7 +106,7 @@ data_frame() ->aggregate(sum(col('sales'))); ``` -The scan is `DISTINCT`, skips nulls, sorts, and is bounded - `discover_pivot_values(50)` refuses a column with +The scan is `DISTINCT`, skips nulls, sorts like [`sortBy()`](/documentation/components/core/sort.md), and is bounded - `discover_pivot_values(50)` refuses a column with more than 50 distinct values. Because it reads the frame before the real run, it needs a source it can read twice, and refuses one it cannot: diff --git a/documentation/components/core/rename.md b/documentation/components/core/rename.md index 3d4247470c..d98315feaf 100644 --- a/documentation/components/core/rename.md +++ b/documentation/components/core/rename.md @@ -4,11 +4,11 @@ [TOC] -DataFrame provides several methods for renaming entries (columns) in your data. These operations are lazy and don't execute until a trigger operation is called. +DataFrame provides several methods for renaming columns. These operations are lazy and don't execute until a trigger operation is called. ## Single Column Rename -To rename a single entry, use `DataFrame::rename()`: +To rename a single column, use `DataFrame::rename()`: ```php .csv (e.g., data_5f8a3b2c.csv) -// When reading data.csv, Flow reads all files matching the pattern: data*.csv +// Read them all with a glob: from_csv(__DIR__ . '/data*.csv') ``` **How it works:** - If destination file doesn't exist: writes normally - If destination file exists: generates a new file with randomized name in the same directory -- Flow treats file paths as directories that can contain multiple files with the same extension **File structure after multiple runs:** ``` @@ -90,7 +89,7 @@ output/ └── orders_2140bfc5fd.csv # Fourth run ``` -When you read from `orders.csv`, Flow automatically reads all `orders*.csv` files in the directory. +Reading `orders.csv` reads that one file; read `orders*.csv` to get every run. **Important:** Flow does not check for duplicates. If you run the same pipeline twice, data will be duplicated across multiple files. @@ -152,8 +151,9 @@ Save modes work with partitioned data: ['date' => '2024-01-01', 'value' => 100], ['date' => '2024-01-02', 'value' => 200], ])) - ->partitionBy('date') - ->write(to_parquet(__DIR__ . '/data')->saveMode(overwrite())) + ->write(to_parquet(__DIR__ . '/data/file.parquet') + ->partitionBy(partition_by(ref('date'))) + ->saveMode(overwrite())) ->run(); // Structure: diff --git a/documentation/components/core/schema.md b/documentation/components/core/schema.md index fff9bcf9c7..52b24b2e57 100644 --- a/documentation/components/core/schema.md +++ b/documentation/components/core/schema.md @@ -17,8 +17,8 @@ A schema consists of column definitions that specify: - **Metadata**: Key-value pairs for additional context Structure field order is part of a structure type's identity: `structure{a, b}` and `structure{b, a}` -are different types, so `Schema::isSame()` and `Definition::isSame()` distinguish them. Value-level -comparisons (`Row::isEqual()`, `Rows::unique()`) stay field-order-insensitive. +are different types, so `Schema::isSame()` and `Definition::isSame()` distinguish them. Comparing two such columns +(`ref('a')->equals(ref('b'))`) is refused at plan time; cast one of them to the other's type first. ## Arrays in a Schema @@ -72,8 +72,8 @@ header to check). Every inferred column is nullable, and where narrowing is not sample that does not fit the inferred type fails the read with an `InferredSchemaException` naming that row - infer from every row with `->inferSchema(infer_schema()->sampleSize(-1))`, or declare the schema. -**Sources that do not.** For the rest, every value still gets its type detected as rows are created and each batch -carries its own schema. +**Sources that do not.** The rest know their schema before the first row: Parquet and Floe read it from the file, +PostgreSQL and DBAL derive it from the query (below), and the text, XML and HTTP extractors yield fixed columns. **`DataFrame::schema()` describes the plan, not the data.** It walks the pipeline's steps once, threading each step's output schema into the next, starting from the source's own `schema()` - so it may do the I/O that source @@ -157,8 +157,8 @@ list_schema('tags', type_list(type_union(type_string(), type_integer()))); ## Declaring the Source Schema Most extractors accept a schema up front: fluent `withSchema(Schema)`, or the optional `$schema` argument of the -`from_*` DSL function. Declared types drive row creation instead of inference, and the row keeps only the columns the -schema mentions. +`from_*` DSL function. The declared types replace inference, and each batch keeps only the columns the schema +mentions. ```php withSchema(...)` skips the probe; it helps the last row, and the one before it when the query runs as written. @@ -360,25 +360,28 @@ cannot be null. Flow PHP provides three built-in validation strategies: - **[StrictValidator](/src/core/etl/src/Flow/ETL/Schema/Validator/StrictValidator.php)** - Rows must exactly match the - schema; extra entries cause validation failure -- **[SelectiveValidator](/src/core/etl/src/Flow/ETL/Schema/Validator/SelectiveValidator.php)** - Only validates entries - defined in schema; ignores extra entries + schema; extra columns cause validation failure +- **[SelectiveValidator](/src/core/etl/src/Flow/ETL/Schema/Validator/SelectiveValidator.php)** - Only validates columns + defined in schema; ignores extra columns - **[EvolvingValidator](/src/core/etl/src/Flow/ETL/Schema/Validator/EvolvingValidator.php)** - Allows missing and extra - entries as long as nullability permits it + columns as long as nullability permits it By default, DataFrame uses `StrictValidator`, but you can specify a different validator as the second parameter to `DataFrame::match()`. ## Basic Schema Matching -Use `DataFrame::match()` to validate data against a schema: +Use `DataFrame::match()` to validate data against a schema. `from_array()` infers every column as nullable, so the +expected schema declares them nullable too: ```php read(from_array([ ['id' => 1, 'name' => 'Product 1', 'active' => true], @@ -387,9 +390,9 @@ data_frame() ])) ->match( schema( - int_schema('id', $nullable = false), - str_schema('name', $nullable = false), - bool_schema('active', $nullable = false, Metadata::empty()->add('key', 'value')), + int_schema('id', nullable: true), + str_schema('name', nullable: true), + bool_schema('active', nullable: true, metadata: Metadata::empty()->add('key', 'value')), ) ) ->write(to_output(false, Output::rows_and_schema)) @@ -409,8 +412,8 @@ data_frame() ])) ->match( schema( - int_schema('id'), - str_schema('name') + int_schema('id', nullable: true), + str_schema('name', nullable: true) ), schema_selective_validator() // Only validate id and name, ignore other fields ) diff --git a/documentation/components/core/select-drop.md b/documentation/components/core/select-drop.md index 79257f1363..3b2f1898d2 100644 --- a/documentation/components/core/select-drop.md +++ b/documentation/components/core/select-drop.md @@ -6,13 +6,13 @@ ## Select -To quickly select only relevant entries use Rows `DataFrame::select` +Keep only the listed columns with `DataFrame::select()`: ```php read(from_array(...)) + ->read(from_array([['id' => 1, 'name' => 'Norbert', 'email' => 'norbert@example.com']])) ->select("id", "name") ->write(to_output()) ->run(); @@ -20,13 +20,13 @@ data_frame() ## Drop -To quickly drop irrelevant entries use Rows `DataFrame::drop` +Remove the listed columns with `DataFrame::drop()`: ```php read(from_array(...)) + ->read(from_array([['id' => 1, 'name' => 'Norbert', '_tags' => 'internal']])) ->drop("_tags") ->write(to_output()) ->run(); diff --git a/documentation/components/core/sort.md b/documentation/components/core/sort.md index d9191bc21c..ef31f47cab 100644 --- a/documentation/components/core/sort.md +++ b/documentation/components/core/sort.md @@ -42,7 +42,7 @@ The sort algorithm is configured through `config_builder()->sort()` - all option it spills each sorted run as a bucket through a `BucketsStorage` (the same abstraction used by [join](/documentation/components/core/join.md) and [group by](/documentation/components/core/group-by.md)), then k-way merges the runs back into one sorted stream. - The memory limit defaults to `FLOW_MAX_MEMORY` when set, otherwise 70% of PHP's `memory_limit` (1 GiB when + The memory limit defaults to `FLOW_MAX_MEMORY` when set, otherwise 70% of PHP's `memory_limit` (1 GB when `memory_limit` is `-1`), and is compared with the whole process - a sort and a join in one pipeline stay under it together. - `memory_sort()` - buffers the whole dataset and sorts it in one pass; fastest, but everything must fit in RAM. It has @@ -112,10 +112,12 @@ to the spill storage, so `storage()` alone stays sufficient: ```php external_sort() - ->storage(new MemoryBuckets()) // spill runs - ->mergeStorage(new FilesystemBuckets($fs, path('/tmp/merge'))); // merged runs only + ->storage(new MemoryBuckets()) // spill runs + ->mergeStorage(new FilesystemBuckets($fs, path('/tmp/merge'), new AdaptiveBackend())); // merged runs only ``` +`FilesystemBuckets` reads runs back into the [column backend](/documentation/components/core/column-backend.md) it is given. + ## Example ```php diff --git a/documentation/components/core/telemetry.md b/documentation/components/core/telemetry.md index 9af0cf5d47..f6f0771ff3 100644 --- a/documentation/components/core/telemetry.md +++ b/documentation/components/core/telemetry.md @@ -124,7 +124,7 @@ $spanExporter = console_exporter(colors: true); $metricExporter = console_exporter(colors: true); // Logs are formatted with severity-based coloring -$logExporter = console_exporter(colors: true, maxBodyLength: 100); +$logExporter = console_exporter(colors: true, maxLogBodyLength: 100); ``` ### OTLP Export (Production) @@ -138,10 +138,7 @@ use function Flow\Telemetry\DSL\{ batching_log_processor, batching_metric_processor, batching_span_processor, logger_provider, memory_context_storage, meter_provider, resource, telemetry, tracer_provider }; -use function Flow\Bridge\Telemetry\OTLP\DSL\{ - otlp_curl_transport, otlp_json_serializer, - otlp_exporter, otlp_exporter, otlp_exporter -}; +use function Flow\Bridge\Telemetry\OTLP\DSL\{otlp_curl_transport, otlp_exporter, otlp_json_serializer}; $clock = new SystemClock(new DateTimeZone('UTC')); $contextStorage = memory_context_storage(); @@ -210,13 +207,14 @@ Every DataFrame execution creates a root span with the following attributes: When `trace_loading` is enabled, child spans are created for each loader with: -- Span name: Loader class name (e.g., `Flow\ETL\Loader\StreamLoader`) +- Span name: short loader class name (e.g., `StreamLoader`); the full name is in `flow.etl.loader.class` - Parent: DataFrame span - Status: OK on success, ERROR on failure When `trace_transformations` is enabled, child spans are created for each transformer with: -- Span name: Transformer class name (e.g., `Flow\ETL\Transformer\EntryNameTransformer`) +- Span name: short transformer class name (e.g., `ScalarFunctionTransformer`); the full name is in + `flow.etl.transformer.class`, the batch sizes in `flow.etl.transformation.input_rows` / `output_rows` - Parent: DataFrame span - Status: OK on success, ERROR on failure @@ -224,10 +222,10 @@ When `trace_transformations` is enabled, child spans are created for each transf When `collect_metrics` is enabled: -| Metric | Type | Unit | Description | -|----------------------------|------------|------------|------------------------------------| -| `flow.etl.rows.processed` | Counter | `{row}` | Cumulative count of processed rows | -| `flow.etl.rows.throughput` | Throughput | `{row}/s` | Rows processed per second | +| Metric | Type | Unit | Description | +|----------------------------|------------|---------|------------------------------------| +| `flow.etl.rows.processed` | Counter | `{row}` | Cumulative count of processed rows | +| `flow.etl.rows.throughput` | Throughput | `{row}` | Rows processed per second | ### Logs diff --git a/documentation/components/core/transformations.md b/documentation/components/core/transformations.md index 08b5e4afc6..0a3202c573 100644 --- a/documentation/components/core/transformations.md +++ b/documentation/components/core/transformations.md @@ -7,8 +7,8 @@ ## Introduction Transformations are a powerful abstraction in Flow PHP that allow you to modify DataFrames in a composable and reusable -way. Unlike Transformers which operate on individual Rows, Transformations work at the DataFrame level, providing access -to the full processing pipeline. +way. Unlike Transformers, which receive one batch (`Rows`) at a time, Transformations work at the DataFrame level, +providing access to the full processing pipeline. Every Transformation implements the `Transformation` interface with a single method: @@ -29,18 +29,18 @@ Transformations can be applied to DataFrames using two methods: Both methods accept `Transformation` objects directly or through convenient DSL functions. ```php -use function Flow\ETL\DSL\{df, from_array, select, drop}; +use function Flow\ETL\DSL\{df, from_array, select, drop, to_output}; // Using with() df() - ->read(from_array([/* ... */])) + ->read(from_array([['id' => 1, 'name' => 'Alice', 'temporary_column' => 'x']])) ->with(select('id', 'name')) ->write(to_output()) ->run(); // Using transform() - identical behavior df() - ->read(from_array([/* ... */])) + ->read(from_array([['id' => 1, 'name' => 'Alice', 'temporary_column' => 'x']])) ->transform(drop('temporary_column')) ->write(to_output()) ->run(); @@ -53,7 +53,7 @@ df() Select specific columns from the DataFrame, keeping only the columns you need. ```php -use function Flow\ETL\DSL\{df, from_array, select, ref}; +use function Flow\ETL\DSL\{df, from_array, select, ref, to_output}; // Select columns by name df() @@ -67,7 +67,7 @@ df() // Select using References for more control df() - ->read(from_array([/* ... */])) + ->read(from_array([['id' => 1, 'name' => 'Alice', 'city' => 'New York']])) ->with(select(ref('id'), ref('city'))) ->write(to_output()) ->run(); @@ -78,7 +78,7 @@ df() Remove unwanted columns from the DataFrame, keeping all other columns. ```php -use function Flow\ETL\DSL\{df, from_array, drop, ref}; +use function Flow\ETL\DSL\{df, from_array, drop, ref, to_output}; // Drop columns by name df() @@ -92,7 +92,7 @@ df() // Drop using References df() - ->read(from_array([/* ... */])) + ->read(from_array([['id' => 1, 'temp_column' => 'x', 'debug_info' => 'y']])) ->with(drop(ref('temp_column'), ref('debug_info'))) ->write(to_output()) ->run(); @@ -104,7 +104,9 @@ Control memory usage by setting the batch size for processing. Smaller batch siz processing large datasets. ```php -use function Flow\ETL\DSL\{df, from_csv, batch_size}; +use function Flow\ETL\Adapter\CSV\from_csv; +use function Flow\ETL\Adapter\Doctrine\to_dbal_table_insert; +use function Flow\ETL\DSL\{df, batch_size}; // Process large CSV file in batches of 100 rows df() @@ -119,7 +121,7 @@ df() Add an index column to each row, useful for tracking row position or creating unique identifiers. ```php -use function Flow\ETL\DSL\{df, from_array, add_row_index}; +use function Flow\ETL\DSL\{df, from_array, add_row_index, to_output}; use Flow\ETL\Transformation\AddRowIndex\StartFrom; // Add default index starting from 0 @@ -131,11 +133,11 @@ df() ->with(add_row_index()) ->write(to_output()) ->run(); -// Output: [['index' => 0, 'name' => 'Alice'], ['index' => 1, 'name' => 'Bob']] +// Output: [['name' => 'Alice', 'index' => 0], ['name' => 'Bob', 'index' => 1]] // Custom column name and start from 1 df() - ->read(from_array([/* ... */])) + ->read(from_array([['name' => 'Alice'], ['name' => 'Bob']])) ->with(add_row_index('row_number', StartFrom::ONE)) ->write(to_output()) ->run(); @@ -150,8 +152,9 @@ and every run uses that instance. Restrict the number of rows processed, useful for debugging or sampling data. ```php +use function Flow\ETL\Adapter\CSV\to_csv; use function Flow\ETL\Adapter\Doctrine\from_dbal_query; -use function Flow\ETL\DSL\{df, limit}; +use function Flow\ETL\DSL\{df, from_array, limit, to_output}; // Process only first 1000 rows df() @@ -162,7 +165,7 @@ df() // Remove limit (process all rows) df() - ->read(from_array([/* ... */])) + ->read(from_array([['id' => 1], ['id' => 2]])) ->with(limit(null)) ->write(to_output()) ->run(); @@ -173,7 +176,7 @@ df() Replace column values with a mask string, useful for hiding sensitive information. ```php -use function Flow\ETL\DSL\{df, from_array, mask_columns}; +use function Flow\ETL\DSL\{df, from_array, mask_columns, to_output}; // Mask sensitive columns with default mask df() @@ -188,7 +191,7 @@ df() // Use custom mask df() - ->read(from_array([/* ... */])) + ->read(from_array([['name' => 'Alice', 'credit_card' => '4111 1111 1111 1111']])) ->with(mask_columns(['credit_card'], '[REDACTED]')) ->write(to_output()) ->run(); @@ -198,8 +201,10 @@ df() Transformations can be chained together to create complex data processing pipelines: -```php -use function Flow\ETL\DSL\{df, from_csv, select, add_row_index, limit, batch_size}; +```php ignore +use function Flow\ETL\Adapter\CSV\from_csv; +use function Flow\ETL\Adapter\JSON\to_json; +use function Flow\ETL\DSL\{df, select, add_row_index, limit, batch_size}; df() ->read(from_csv('users.csv')) @@ -217,10 +222,11 @@ df() was written at, and planned and bound together with the rest of the frame. ```php -use function Flow\ETL\DSL\{df, from_array, lit, ref, select, to_branch, to_csv, to_transformation}; +use function Flow\ETL\Adapter\CSV\to_csv; +use function Flow\ETL\DSL\{df, from_array, lit, ref, select, to_branch, to_transformation}; df() - ->read(from_array([/* ... */])) + ->read(from_array([['id' => 1, 'name' => 'Alice', 'active' => true], ['id' => 2, 'name' => 'Bob', 'active' => false]])) ->write(to_transformation(select('id', 'name'), to_csv('names.csv'))) ->write(to_branch(ref('active')->equals(lit(true)), to_csv('active.csv'))) ->run(); @@ -252,7 +258,7 @@ $sortById = new class implements Transformation { }; df() - ->read(from_array([/* ... */])) + ->read(from_array([['id' => 2], ['id' => 1]])) ->write(to_transformation($sortById, to_output())) ->run(); ``` @@ -262,11 +268,11 @@ df() Correctness is the same everywhere; what differs between operations is how much they hold, and they hold it inside the sink. Three groups: -| Cost | Operations | -|----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Grows with the whole stream | `sortBy()`, `aggregate()`, `groupBy()->aggregate()`, `pivot()`, window functions, `collect()`, `join()`, `repartition()` | -| Grows with the number of distinct keys | `dropDuplicates()`, `constrain()` with a `UniqueConstraint` | -| Constant | `select()`, `withEntry()`, `filter()`, `add_row_index()`, `limit()`, `until()`, `offset()`, `cache($id)`, `batch_size()`, `batchBy()` | +| Cost | Operations | +|----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------| +| Grows with the whole stream | `sortBy()`, `aggregate()`, `groupBy()->aggregate()`, `pivot()`, window functions, `collect()`, `join()`, `repartition()` | +| Grows with the number of distinct keys | `dropDuplicates()`, `constrain()` with a `UniqueConstraint` | +| Constant | `select()`, `withEntry()`, `filter()`, `add_row_index()`, `limit()`, `until()`, `offset()`, `cache($id)`, `batch_size()`, `batchBy()` | The first group buffers - in memory, or spilled to disk by the external sort - exactly as it does on an outer frame. `offset()` and `cache($id)` are in the constant group: `offset()` counts the rows it skips, and `cache($id)` writes each @@ -292,7 +298,7 @@ A sink runs under the frame's `->onError(...)` handler, and each failure is offe ```php df() - ->read(from_array([/* ... */])) + ->read(from_array([['id' => 2], ['id' => 1]])) ->onError(skip_rows_handler()) // a failing step inside the sink skips that batch ->write(to_transformation($sortById, to_csv('sorted.csv'))) ->run(); @@ -314,6 +320,8 @@ You can create custom transformations by implementing the `Transformation` inter ```php use Flow\ETL\{DataFrame, Transformation}; +use function Flow\ETL\DSL\{df, from_array, ref, to_output}; + final class UppercaseNames implements Transformation { public function transform(DataFrame $dataFrame): DataFrame @@ -327,7 +335,7 @@ final class UppercaseNames implements Transformation // Use custom transformation df() - ->read(from_array([/* ... */])) + ->read(from_array([['name' => 'alice'], ['name' => 'bob']])) ->with(new UppercaseNames()) ->write(to_output()) ->run(); diff --git a/documentation/components/core/window-functions.md b/documentation/components/core/window-functions.md index 616664e922..eeabdb7794 100644 --- a/documentation/components/core/window-functions.md +++ b/documentation/components/core/window-functions.md @@ -21,7 +21,7 @@ smaller partitions on which later window function will be applied. - [`AVERAGE`](/src/core/etl/src/Flow/ETL/Function/Average.php) - [`COUNT`](/src/core/etl/src/Flow/ETL/Function/Count.php) -All window functions are implementing [`WindowFunction`](/src/core/etl/src/Flow/ETL/Function/WindowFunction.php) +All window functions implement [`WindowFunction`](/src/core/etl/src/Flow/ETL/Function/WindowFunction.php) interface. ### Example @@ -47,22 +47,17 @@ data_frame() Output: ```console -+----+-------+------------+--------+------+ -| id | name | department | salary | rank | -+----+-------+------------+--------+------+ -| 5 | Jane | Finances | 14000 | 1 | -| 3 | Tomas | Finances | 11000 | 2 | -| 4 | John | Finances | 9000 | 3 | -| 6 | Janet | Finances | 4000 | 4 | -+----+-------+------------+--------+------+ -4 rows +----+--------+------------+--------+------+ | id | name | department | salary | rank | +----+--------+------------+--------+------+ +| 5 | Jane | Finances | 14000 | 1 | +| 3 | Tomas | Finances | 11000 | 2 | +| 4 | John | Finances | 9000 | 3 | +| 6 | Janet | Finances | 4000 | 4 | | 1 | Greg | IT | 6000 | 1 | | 2 | Michal | IT | 5000 | 2 | +----+--------+------------+--------+------+ -2 rows +6 rows ``` ## Frames diff --git a/documentation/components/extensions/arrow-ext.md b/documentation/components/extensions/arrow-ext.md index be05651f18..f79d40880f 100644 --- a/documentation/components/extensions/arrow-ext.md +++ b/documentation/components/extensions/arrow-ext.md @@ -112,13 +112,13 @@ $writer = new RustParquetFileWriter( // Flow\Parquet\Parque SchemaConverter::toExtension($schema), // Flow\Parquet\ParquetFile\Schema Compressions::SNAPPY, // LZO is refused OptionsConverter::toExtension(Options::default()), - batchSize: 1_000, + 1_000, // rows per written batch ); $writer->writeBatch([['id' => 1, 'name' => 'a']]); // an array or any Traversable of rows $writer->writeColumns(['id' => [2, 3], 'name' => ['b', null]]); $writer->close(); // footer, then the stream closed -$batches = new RustBatchReader($file, ['id', 'name'], batchSize: 1_000, offset: null, limit: null); +$batches = new RustBatchReader($file, ['id', 'name'], 1_000, null, null); // batch size, offset, limit $batches->schema(); // Flow\Arrow\RustArrowSchema $batches->next(); // Flow\Arrow\RustParquetBatch, null after the last ``` diff --git a/documentation/components/extensions/flow-php-ext.md b/documentation/components/extensions/flow-php-ext.md index 2175402e16..8cdfaf6576 100644 --- a/documentation/components/extensions/flow-php-ext.md +++ b/documentation/components/extensions/flow-php-ext.md @@ -44,7 +44,8 @@ df() ``` With the extension loaded, `Flow\ETL\Column\AdaptiveBackend` - the default of `config_builder()->backend()` - picks the -extension's `RustBackend` and every batch column is a `Flow\ETL\Column\RustColumn` over an Apache Arrow array: +extension's `RustBackend` and every batch column is a `Flow\ETL\Column\RustColumn` over an Apache Arrow array. How to +choose a backend and what it builds: [Column Backend](/documentation/components/core/column-backend.md). ```php insert( +insert( $dbalConnection, - 'your-table-name', + 'users', new BulkData([ ['id' => 1, 'name' => 'Name One', 'description' => 'Description One'], ['id' => 2, 'name' => 'Name Two', 'description' => 'Description Two'], ['id' => 3, 'name' => 'Name Three', 'description' => 'Description Three'], - ]) + ]), ); - ``` -### Type Optimization with BulkData +### Column types -`BulkData` can accept optional type information to optimize database operations: +Without types, `Bulk` reads the column types of the table from the database, once per table and `Bulk` instance. Pass +them to `BulkData` to bind with exactly these types: ```php -use Doctrine\DBAL\Types\Type; -use Doctrine\DBAL\Types\Types; +insert( +use Doctrine\DBAL\Types\{Type, Types}; +use Flow\Doctrine\Bulk\{Bulk, BulkData}; + +Bulk::create()->insert( $dbalConnection, - 'your-table-name', + 'users', new BulkData( [ - ['id' => 1, 'name' => 'Name One', 'created_at' => new \DateTime()], - ['id' => 2, 'name' => 'Name Two', 'created_at' => new \DateTime()], + ['id' => 1, 'name' => 'Name One', 'created_at' => new \DateTimeImmutable()], + ['id' => 2, 'name' => 'Name Two', 'created_at' => new \DateTimeImmutable()], ], [ 'id' => Type::getType(Types::INTEGER), 'name' => Type::getType(Types::STRING), 'created_at' => Type::getType(Types::DATETIME_IMMUTABLE), - ] - ) + ], + ), ); ``` -**Type Detection Behavior:** +Update (PostgreSQL): -- **With Types**: When column types are provided, `BulkData` uses them directly for optimal performance -- **Without Types**: When no types are provided, `BulkData` automatically queries the database to understand the table structure and determine appropriate types - -This automatic type detection ensures data consistency but comes with a performance cost due to the additional database query. For optimal performance in high-throughput scenarios, explicitly providing column types is recommended. +```php +update( +Bulk::create()->update( $dbalConnection, - 'your-table-name', + 'users', new BulkData([ ['id' => 1, 'name' => 'Name One', 'description' => 'Description One'], ['id' => 2, 'name' => 'Name Two', 'description' => 'Description Two'], - ['id' => 3, 'name' => 'Name Three', 'description' => 'Description Three'], ]), - [ - 'primary_key_columns' => ['id'], - 'update_columns' => ['name'] - ] + new PostgreSQLUpdateOptions(primaryKeyColumns: ['id'], updateColumns: ['name']), ); - ``` +`Bulk::delete()` removes the rows matching every column of `BulkData`. + ## Supported Dialects -* PostgreSQL -* MySQL / MariaDB -* SQLite +- PostgreSQL +- MySQL / MariaDB +- SQLite ### Adding new Dialects -[Dialect](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/Dialect/Dialect.php) is basic abstraction of this library. -The main role of Dialect is to prepare SQL insert/update statement based -on [BulkData](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/BulkData.php) -and provided `options`. - -* `$insertOptions` -* `$updateOptions` - -Options are key => value maps without predefined structure that allows to manipulate building SQL statement. -Each dialect should define it own structure for options in order to support db engine features, including those -that are specific for given engine. - -[QueryFactory](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/QueryFactory.php) is abstraction for creating queries, there is currently only one -implementation, DbalPlatform. QueryFactory `insertOptions` and `updateOptions` is combination of all options provided -by supported Dialects where each entry must be optional. - -example: -`dialect_option?: string` +A [Dialect](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/Dialect/Dialect.php) builds the SQL of one insert, +update or delete from a [BulkData](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/BulkData.php) and the dialect's +own `InsertOptions` / `UpdateOptions` implementation (`PostgreSQLInsertOptions`, `MySQLInsertOptions`, +`SqliteInsertOptions`, ...). -[DbalPlatform](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/DbalPlatform.php) is a factory that detects which Dialect should be used for given -Doctrine DBAL Platform. +[DbalPlatform](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/DbalPlatform.php) picks the Dialect for a Doctrine +DBAL platform, and [DbalQueryFactory](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/QueryFactory/DbalQueryFactory.php), +the [QueryFactory](/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/QueryFactory.php) implementation, asks it for +the query. diff --git a/documentation/components/libs/parquet.md b/documentation/components/libs/parquet.md index 3c4fae3a56..37b52280a7 100644 --- a/documentation/components/libs/parquet.md +++ b/documentation/components/libs/parquet.md @@ -51,11 +51,11 @@ Row-based format: ----------------- -| ID | Name | Age | -|----|-------|-----| -| 1 | Alice | 20 | -| 2 | Bob | 25 | -| 3 | Carol | 30 | +| ID | Name | Age | +|-----|-------|-----| +| 1 | Alice | 20 | +| 2 | Bob | 25 | +| 3 | Carol | 30 | Column-based format: -------------------- @@ -115,10 +115,11 @@ $reader = new Reader(); > `new Reader()` uses the adaptive engine. See [Engine System](#engine-system) for how to explicitly choose the Arrow or > PHP engine. -The Reader accepts two arguments: +The Reader accepts three arguments: - `$byteOrder` - by default set to `ByteOrder::LITTLE_ENDIAN` - `$options` - a set of options that can be used to configure the reader. +- `$engine` - by default `AdaptiveParquetEngine` All available options are described in [Option](/src/lib/parquet/src/Flow/Parquet/Option.php) enum. @@ -126,7 +127,8 @@ All available options are described in [Option](/src/lib/parquet/src/Flow/Parque ### Reader Options -- `INT_96_AS_DATETIME` - default: `true` - if set to `true` then `INT96` values will be converted to `DateTime` objects. +- `INT_96_AS_DATETIME` - default: `true` - if set to `true` then `INT96` values are read as `DateTimeImmutable`, + floored to microseconds. ### Reading a file @@ -141,13 +143,16 @@ $file = $reader->read('path/to/file.parquet'); $file = $reader->readStream(\fopen('path/to/file.parquet', 'rb')); ``` -At this point, nothing is read yet. We just created a file object. +`RustParquetEngine` reads the footer when the file is opened, `PhpParquetEngine` on the first call that needs it. An +invalid file throws `InvalidArgumentException` `Given file is not valid Parquet file...`. There are several things we can read from parquet file: - `ParquetFile::values(array $columns = [], ?int $limit = null, ?int $offset = null) : \Generator` +- `ParquetFile::columns(int $batchSize, array $columns = [], ?int $limit = null, ?int $offset = null) : \Generator` - `ParquetFile::metadata() : Metadata` - `ParquetFile::schema() : Schema` - shortcut for `ParquetFile::metadata()->schema()` +- `ParquetFile::close() : void` - closes the reader and its stream ### Reading the whole file: @@ -326,15 +331,13 @@ $writer->close(); ### Writer Options -- `BYTE_ARRAY_TO_STRING` - default: `true` - if set to `true` then `BYTE_ARRAY` values will be converted to `string` - objects. - `DICTIONARY_PAGE_MIN_CARDINALITY_RATION` - default '0.4' - minimum ratio of unique values to total values for a column to have dictionary encoding. - `DICTIONARY_PAGE_SIZE` - default: `1Mb` - maximum size of dictionary page. - `GZIP_COMPRESSION_LEVEL` - default: `9` - compression level for GZIP compression (applied only when GZIP compression is enabled). -- `PAGE_SIZE_BYTES` - default: `8Kb` - maximum size of data page. -- `ROW_GROUP_SIZE_BYTES` - default: `8Mb` - maximum size of row group. +- `PAGE_SIZE_BYTES` - default: `128Kb` - maximum size of data page. +- `ROW_GROUP_SIZE_BYTES` - default: `32Mb` - maximum size of row group. - `ROW_GROUP_SIZE_CHECK_INTERVAL` default: `1000` - number of rows to write before checking if row group size limit is reached. - `VALIDATE_DATA` - default: `true` - if set to `true` then writer will validate data against schema. @@ -427,7 +430,7 @@ $options = Options::default()->set(Option::COLUMNS_COMPRESSIONS, [ ]); // Global compression serves as fallback for unspecified columns -$writer = new Writer(compressions: Compressions::GZIP, options: $options); +$writer = new Writer(compression: Compressions::GZIP, options: $options); ``` #### Nested Column Compression @@ -645,7 +648,7 @@ $options = Options::default()->set(Option::COLUMNS_ENCODINGS, [ 'description' => Encodings::PLAIN // High variance text ]); -$writer = new Writer(compressions: Compressions::SNAPPY, options: $options); +$writer = new Writer(compression: Compressions::SNAPPY, options: $options); ``` #### Nested Column Encoding (Flat Path Notation) @@ -762,9 +765,9 @@ $options = Options::default()->set(Option::COLUMNS_ENCODINGS, [ | Encoding | INT32/INT64 | BYTE_ARRAY | BOOLEAN | FLOAT/DOUBLE | FIXED_LEN_BYTE_ARRAY | |---------------------|-------------|------------|---------|--------------|----------------------| -| PLAIN | yes | yes | yes | yes | yes | -| RLE_DICTIONARY | yes | yes | yes | yes | no | -| DELTA_BINARY_PACKED | yes | no | no | no | no | +| PLAIN | yes | yes | yes | yes | yes | +| RLE_DICTIONARY | yes | yes | yes | yes | no | +| DELTA_BINARY_PACKED | yes | no | no | no | no | ### Performance Guidelines diff --git a/documentation/components/libs/snappy.md b/documentation/components/libs/snappy.md index 935dbc7405..94b97a6ceb 100644 --- a/documentation/components/libs/snappy.md +++ b/documentation/components/libs/snappy.md @@ -41,7 +41,7 @@ $faker = \Faker\Factory::create(); $texts = []; for ($i = 0; $i < 10_000; $i++) { - $textSize = \Flow\ETL\UniqueFactory::int(100, 5000); + $textSize = \random_int(100, 5000); $texts[] = $faker->text($textSize); } diff --git a/documentation/components/libs/types.md b/documentation/components/libs/types.md index 73cc0a2a49..848720df06 100644 --- a/documentation/components/libs/types.md +++ b/documentation/components/libs/types.md @@ -48,7 +48,7 @@ Examples: ```php get('some-input'); @@ -61,7 +61,7 @@ On top of that it will also narrow the `$string` variable to a string type, so y ```php get('some-input'); @@ -89,7 +89,7 @@ To cast a variable to a specific type, you just simply need to use the `cast` me ```php get('some-input'); @@ -164,8 +164,8 @@ List is a collection of elements of the same where keys start from 0 and are aut ```php type_string(), @@ -210,9 +210,9 @@ anywhere - including before a required one: ```php type_string(), @@ -233,10 +233,10 @@ All above types can be easily combined together, so for to get the list of users ```php backend(new PhpBackend())) ->read(from_parquet(__DIR__ . '/input.parquet', engine: new PhpParquetEngine())) ->write(to_floe(__DIR__ . '/output.floe')); ``` +`PhpBackend` keeps the batches in PHP, but CSV and JSON files are still parsed by `flow_php` while it is loaded. + To take the whole container off one native path, mount an empty file over that extension's ini: ```shell @@ -113,6 +116,6 @@ $ docker run --rm -v /dev/null:/usr/local/etc/php/conf.d/docker-php-ext-flow_php -v $(pwd):/flow-workspace ghcr.io/flow-php/flow:latest run /flow-workspace/pipeline.php ``` -Once a native engine is selected it does **not** silently degrade. Extension failures surface as -`Flow\ETL\Exception\RuntimeException`, which `FloeReader` and `FloeWriter` wrap as -`Flow\Floe\Exception\FloeException`. +Once a native path is selected it does **not** silently degrade. `flow_php` failures surface as +`Flow\ETL\Exception\RuntimeException`; a Floe read wraps them as `Flow\Floe\Exception\FloeException`. arrow-ext +failures surface as `Flow\Parquet\Exception\*`. diff --git a/documentation/installation/packages/arrow-ext.md b/documentation/installation/packages/arrow-ext.md index 64fc3c63bd..bddb914f30 100644 --- a/documentation/installation/packages/arrow-ext.md +++ b/documentation/installation/packages/arrow-ext.md @@ -44,6 +44,14 @@ echo "extension=arrow" > $(php -r "echo PHP_CONFIG_FILE_SCAN_DIR;")/arrow.ini php -m | grep arrow ``` +## Version + +Install the extension of the Flow release you use. `flow-php/parquet` and `flow-php/etl-adapter-parquet` conflict +with `ext-arrow <0.45`. + +An extension built for another release is refused with a `RuntimeException` naming its version and ABI, raised by +`AdaptiveParquetEngine`. `new PhpParquetEngine()` still runs. + ## PIE [PIE](https://github.com/php/pie) is the modern PHP extension installer. diff --git a/documentation/installation/packages/etl-adapter-csv.md b/documentation/installation/packages/etl-adapter-csv.md index 2e19ec4344..89726156ea 100644 --- a/documentation/installation/packages/etl-adapter-csv.md +++ b/documentation/installation/packages/etl-adapter-csv.md @@ -16,3 +16,8 @@ seo_description: > ```bash composer require flow-php/etl-adapter-csv:~--FLOW_PHP_VERSION-- ``` + +## Optional Extension + +With the [flow_php extension](/documentation/installation/packages/flow-php-ext.md) loaded, CSV files are read and +written in Rust. The adapter conflicts with `ext-flow_php <0.45`. diff --git a/documentation/installation/packages/etl-adapter-json.md b/documentation/installation/packages/etl-adapter-json.md index 98560e1203..28b1910842 100644 --- a/documentation/installation/packages/etl-adapter-json.md +++ b/documentation/installation/packages/etl-adapter-json.md @@ -20,3 +20,8 @@ composer require flow-php/etl-adapter-json:~--FLOW_PHP_VERSION-- ## Core Dependencies - [halaxa/json-machine](https://packagist.org/packages/halaxa/json-machine) + +## Optional Extension + +With the [flow_php extension](/documentation/installation/packages/flow-php-ext.md) loaded, JSON files are read and +written in Rust. The adapter conflicts with `ext-flow_php <0.45`. diff --git a/documentation/installation/packages/etl-adapter-parquet.md b/documentation/installation/packages/etl-adapter-parquet.md index e66a3b1590..26b48304d8 100644 --- a/documentation/installation/packages/etl-adapter-parquet.md +++ b/documentation/installation/packages/etl-adapter-parquet.md @@ -20,3 +20,11 @@ composer require flow-php/etl-adapter-parquet:~--FLOW_PHP_VERSION-- ## Core Dependencies - [flow-php/parquet](https://packagist.org/packages/flow-php/parquet) + +## Optional Extensions + +- [arrow-ext](/documentation/installation/packages/arrow-ext.md) - Parquet files are decoded and encoded in Rust. +- [flow_php](/documentation/installation/packages/flow-php-ext.md) - with arrow-ext also loaded, batches pass between + the extensions without PHP values. + +The adapter conflicts with `ext-arrow <0.45` and `ext-flow_php <0.45`. diff --git a/documentation/installation/packages/etl.md b/documentation/installation/packages/etl.md index 90e08442b0..1d695d54b0 100644 --- a/documentation/installation/packages/etl.md +++ b/documentation/installation/packages/etl.md @@ -25,3 +25,12 @@ composer require flow-php/etl:~--FLOW_PHP_VERSION-- ## Suggested Extensions - `ext-bcmath` - for more precise calculations (bundled with PHP, enable via your system package manager) + +## Optional Extension + +The [flow_php extension](/documentation/components/extensions/flow-php-ext.md) stores columns as Arrow arrays, see +[Column Backend](/documentation/components/core/column-backend.md). `flow-php/etl` conflicts with `ext-flow_php <0.45`. + +```bash +pie install flow-php/flow-php-ext +``` diff --git a/documentation/installation/packages/flow-php-ext.md b/documentation/installation/packages/flow-php-ext.md index 7a618ebde8..b41f432168 100644 --- a/documentation/installation/packages/flow-php-ext.md +++ b/documentation/installation/packages/flow-php-ext.md @@ -44,6 +44,15 @@ echo "extension=flow_php" > $(php -r "echo PHP_CONFIG_FILE_SCAN_DIR;")/flow_php. php -m | grep flow_php ``` +## Version + +Install the extension of the Flow release you use. `flow-php/etl`, `flow-php/etl-adapter-csv`, `-json` and `-parquet` +conflict with `ext-flow_php <0.45`. + +An extension built for another release is refused with a `RuntimeException` naming its version and ABI, raised by +the first `Adaptive*` class that picks a lane. A pipeline that reaches none, e.g. +`config_builder()->backend(new PhpBackend())` with `from_array()`, still runs. + ## PIE [PIE](https://github.com/php/pie) is the modern PHP extension installer. diff --git a/documentation/installation/packages/parquet.md b/documentation/installation/packages/parquet.md index d40a8d7dcb..b8aeb30b54 100644 --- a/documentation/installation/packages/parquet.md +++ b/documentation/installation/packages/parquet.md @@ -37,4 +37,5 @@ For high-performance Parquet reading/writing via Apache Arrow, install the arrow pie install flow-php/arrow-ext ``` -See [Arrow Extension installation](/documentation/installation/packages/arrow-ext.md) for full details. +`flow-php/parquet` conflicts with `ext-arrow <0.45`. See +[Arrow Extension installation](/documentation/installation/packages/arrow-ext.md) for full details. diff --git a/documentation/quick-start.md b/documentation/quick-start.md index 630033c720..803ab93952 100644 --- a/documentation/quick-start.md +++ b/documentation/quick-start.md @@ -14,8 +14,7 @@ Let's take a look at a simple example of how to use Flow ETL to read a CSV file, declare(strict_types=1); use function Flow\ETL\Adapter\CSV\{from_csv, to_csv}; -use function Flow\ETL\DSL\{data_frame, lit, ref, sum, to_output}; -use Flow\ETL\Filesystem\SaveMode; +use function Flow\ETL\DSL\{data_frame, lit, overwrite, ref, sum, to_output}; require __DIR__ . '/vendor/autoload.php'; @@ -50,15 +49,13 @@ It creates a new instance of the `Flow\ETL\Flow` class, which is the main class For comprehensive DataFrame documentation, see the [Data Frame Guide](/documentation/components/core/core.md). -[Data Frame Examples](/data_frame/#example) - -[Examples Documentation](/documentation/examples) +[Data Frame Examples](/getting_started/#example) ## Extraction - Reading The first step in creating a data processing pipeline is to read the data from a data source. Extractors are responsible for reading data from a data source and converting it into a format that can be processed by Flow ETL. -All extractors return \Generator and by design will return rows one by one - this is to ensure that memory consumption is constant and low. +All extractors return a `\Generator` of batches (`Rows`, one column per schema definition), so memory stays constant no matter how big the source is. ```php data_frame() @@ -74,7 +71,7 @@ data_frame() ->read(from_csv(__DIR__ . '/reports/*.csv')); ``` -[Extractors Examples](/data_reading/#example) +[Extractors Examples](/reading/#example) ## Transformation @@ -92,7 +89,7 @@ One of the most powerful features of Flow ETL is the ability to transform data u ->withEntry('revenue', ref('total_price')->minus(ref('discount'))) ``` -`withEntry()` function accepts two arguments, the first one is the name of the new entry (column), the second one is the value of the new column. +`withEntry()` function accepts two arguments, the first one is the name of the new column, the second one is the value of the new column. The value of the new column can be a literal value, a reference to an existing column or a function call. - `ref('created_at')` - creates a reference to the `created_at` column. @@ -125,8 +122,8 @@ truncating the output. ->write(to_csv(__DIR__ . '/daily_revenue.csv')->saveMode(overwrite())) ``` -Second write is writing the data to a CSV file, we're using the `mode()` function to set the save mode to `overwrite`. -There are three save modes available: +Second write is writing the data to a CSV file, we're using `saveMode(overwrite())` to set the save mode to `overwrite`. +There are four save modes available: - `SaveMode::Append` - If data sink already exists, data will be appended. This solution might cause data duplication since it does not check if the given rows already exist. - `SaveMode::ExceptionIfExists` - If data sink already exists an error will be thrown. @@ -134,10 +131,10 @@ There are three save modes available: - `SaveMode::Overwrite` - If data sink already exists, it will be removed and written again. > [!NOTE] -> Append mode is not really appending anything to existing files, instead it creates a folder in which it stores outputs under randomized file names. -> It can be later read using a glob-pattern, for example `from_csv('/path/to/folder/*.csv')`. +> Append mode does not append to an existing file. It writes a sibling file `name_.ext` next to it +> (`daily_revenue_ecd5b31525.csv`). Read all of them with a glob: `from_csv(__DIR__ . '/daily_revenue*.csv')`. -[Loaders Examples](/data_writing/#example) +[Loaders Examples](/writing/#example) ## Lazy Execution diff --git a/documentation/upgrading.md b/documentation/upgrading.md index 2c700c5ecd..135df3c1c5 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -1397,6 +1397,30 @@ config_builder()->cacheDir($dir); Build a cache yourself only for a custom serializer or filesystem; it has no default serializer any more and takes it from its caller, e.g. `filesystem_cache(new FloeSerializer(new AdaptiveBackend()), $dir)`. +### 127) `flow-php/filesystem` - `Path::uri()` of a local file keeps the root slash + +| | Before | After | +|----------------------------------------------------------------|--------------------------|---------------------------| +| `path('/data/orders.csv')->uri()` | `file://data/orders.csv` | `file:///data/orders.csv` | +| `path('/')->uri()` | `file://` | `file:///` | +| `_input_file_uri`, `explain()` `Source:` of a local file | `file://data/orders.csv` | `file:///data/orders.csv` | + +Other protocols are unchanged (`memory://path`, `s3://bucket/key`). Windows drive paths stay `file://C:/...`. + +### 128) `flow-php/parquet` - `Option::BYTE_ARRAY_TO_STRING` removed + +| Before | After | +|-------------------------------------------------------|---------| +| `$options->set(Option::BYTE_ARRAY_TO_STRING, $value)` | removed | + +### 129) `flow-php/etl`, `flow-php/parquet`, adapters - a mismatched `flow_php` or arrow extension is refused + +| Before | After | +|-------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| +| an extension built for another package version: `Class "...\RustBackend" not found` | `RuntimeException` `The loaded flow_php extension (, ABI ) does not match ...` | + +Rebuild or upgrade the extension with the package, or stop loading it. + --- ## Upgrading from 0.43.x to 0.44.x diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVEncoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVEncoder.php index 8d3a8a4b32..4104e22563 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVEncoder.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVEncoder.php @@ -4,19 +4,18 @@ namespace Flow\ETL\Adapter\CSV; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Rows; -use function extension_loaded; - final readonly class AdaptiveCSVEncoder implements CSVEncoder { private CSVEncoder $encoder; - public function __construct(CSVWriteOptions $options) + public function __construct(CSVWriteOptions $options, ?FlowPhpExtension $extension = null) { $php = new PhpCSVEncoder($options); - $this->encoder = extension_loaded('flow_php') + $this->encoder = ($extension ?? FlowPhpExtension::detect())->available() ? new RustCSVEncoder( $options->separator, $options->enclosure, diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php index 2cc53700ae..c1c0db02f7 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/AdaptiveCSVOpenSource.php @@ -6,6 +6,7 @@ use Flow\ETL\Column\Backend; use Flow\ETL\Extractor\File\SourceFile; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Schema; use Flow\ETL\Schema\Inference\ColumnTypes; use Flow\ETL\Schema\Inference\SchemaInference; @@ -14,14 +15,17 @@ use Iterator; use Throwable; -use function extension_loaded; - final readonly class AdaptiveCSVOpenSource implements CSVOpenSource { private CSVOpenSource $source; - public function __construct(Filesystem $filesystem, SourceFile $source, CSVReadOptions $options) - { + public function __construct( + Filesystem $filesystem, + SourceFile $source, + CSVReadOptions $options, + ?FlowPhpExtension $extension = null, + ) { + $native = ($extension ?? FlowPhpExtension::detect())->available(); $stream = $filesystem->readFrom($source->path); // the callers' try/finally starts only after the constructor returns, and detection reads the stream @@ -33,7 +37,7 @@ public function __construct(Filesystem $filesystem, SourceFile $source, CSVReadO $options->escape ?? $detected->escape, ); - $this->source = extension_loaded('flow_php') + $this->source = $native ? new RustCSVOpenSource( $stream, $dialect->separator, diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php index 48df4f01f6..fb1b824298 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVEncoder.php @@ -6,9 +6,9 @@ use Flow\ETL\Rows; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(CSVEncoder::class, false)) { return; } diff --git a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php index f6e56144e4..3bd70029d0 100644 --- a/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php +++ b/src/adapter/etl-adapter-csv/src/Flow/ETL/Adapter/CSV/CSVOpenSource.php @@ -13,9 +13,9 @@ use Flow\Types\Type\TypeNarrower; use Iterator; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(CSVOpenSource::class, false)) { return; } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/AdaptiveCSVOpenSourceTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/AdaptiveCSVOpenSourceTest.php index 07a5581277..7d3b6c9991 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/AdaptiveCSVOpenSourceTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Integration/AdaptiveCSVOpenSourceTest.php @@ -8,6 +8,8 @@ use Flow\ETL\Adapter\CSV\CSVReadOptions; use Flow\ETL\Adapter\CSV\Tests\Context\CSVFixtureContext; use Flow\ETL\Adapter\CSV\Tests\Double\LengthCapturingFilesystem; +use Flow\ETL\Exception\RuntimeException as ETLRuntimeException; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\RustIterator; use Flow\ETL\Tests\Double\CountingFilesystem; use Flow\ETL\Tests\FlowTestCase; @@ -152,4 +154,23 @@ public function test_characters_read_in_line_reaches_the_opened_source(): void ? static::assertSame([4096], $filesystem->lastStream?->capturedIterateLengths) : static::assertSame([null, 4096], $filesystem->lastStream?->capturedLengths); } + + public function test_a_flow_php_of_another_abi_is_refused_before_the_file_is_opened(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + + try { + new AdaptiveCSVOpenSource( + $filesystem, + CSVFixtureContext::source('header_only.csv'), + new CSVReadOptions(), + new FlowPhpExtension(true, FlowPhpExtension::ABI + 1, '0.46.0'), + ); + static::fail('a skewed flow_php must be refused'); + } catch (ETLRuntimeException $e) { + static::assertStringContainsString('does not match flow-php/etl', $e->getMessage()); + } + + static::assertSame(0, $filesystem->readFromCalls); + } } diff --git a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/AdaptiveCSVEncoderTest.php b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/AdaptiveCSVEncoderTest.php index 563204786b..0d3abbfaa8 100644 --- a/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/AdaptiveCSVEncoderTest.php +++ b/src/adapter/etl-adapter-csv/tests/Flow/ETL/Adapter/CSV/Tests/Unit/AdaptiveCSVEncoderTest.php @@ -7,6 +7,8 @@ use Flow\ETL\Adapter\CSV\AdaptiveCSVEncoder; use Flow\ETL\Adapter\CSV\CSVOpenSink; use Flow\ETL\Adapter\CSV\CSVWriteOptions; +use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Stream\StringDestinationStream; @@ -43,4 +45,23 @@ public function test_a_sink_without_a_header(): void static::assertSame("1\n", $stream->content()); } + + public function test_a_flow_php_of_another_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('does not match flow-php/etl'); + + new AdaptiveCSVEncoder(new CSVWriteOptions(), new FlowPhpExtension(true, FlowPhpExtension::ABI + 1, '0.46.0')); + } + + public function test_without_flow_php_the_php_encoder_writes(): void + { + static::assertSame( + "1\n", + (new AdaptiveCSVEncoder( + new CSVWriteOptions(newLineSeparator: "\n"), + new FlowPhpExtension(false, null), + ))->encode(array_to_rows([['id' => 1]], schema(int_schema('id')))), + ); + } } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonEncoder.php index cecb9f7e6c..6f00029200 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonEncoder.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonEncoder.php @@ -5,10 +5,9 @@ namespace Flow\ETL\Adapter\JSON; use DateTimeInterface; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Rows; -use function extension_loaded; - use const JSON_PRESERVE_ZERO_FRACTION; use const JSON_THROW_ON_ERROR; use const JSON_UNESCAPED_SLASHES; @@ -22,11 +21,12 @@ public function __construct( int $flags = JSON_THROW_ON_ERROR, string $dateTimeFormat = DateTimeInterface::ATOM, string $dateFormat = 'Y-m-d', + ?FlowPhpExtension $extension = null, ) { $php = new PhpJsonEncoder($flags, $dateTimeFormat, $dateFormat); // RustJsonEncoder renders only these flags; any other one writes through PHP - $this->encoder = extension_loaded('flow_php') + $this->encoder = ($extension ?? FlowPhpExtension::detect())->available() && ( $flags & ~(JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION) diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php index f0aa5c44da..db28342823 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/AdaptiveJsonOpenSource.php @@ -8,12 +8,12 @@ use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Column\Backend; use Flow\ETL\Extractor\File\SourceFile; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Schema; use Flow\Filesystem\Filesystem; use Iterator; use Throwable; -use function extension_loaded; use function str_starts_with; use function strlen; use function strspn; @@ -35,8 +35,9 @@ public function __construct( JsonFormat $format, ?string $pointer, SourceFile $source, + ?FlowPhpExtension $extension = null, ) { - if (!extension_loaded('flow_php') || $pointer !== null) { + if (!($extension ?? FlowPhpExtension::detect())->available() || $pointer !== null) { $this->source = new PhpJsonOpenSource($reader, $source); return; diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonEncoder.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonEncoder.php index d04d59f80c..ce10082a83 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonEncoder.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonEncoder.php @@ -6,9 +6,9 @@ use Flow\ETL\Rows; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(JsonEncoder::class, false)) { return; } diff --git a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php index 9268f9e68c..7ad2e630ac 100644 --- a/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php +++ b/src/adapter/etl-adapter-json/src/Flow/ETL/Adapter/JSON/JsonOpenSource.php @@ -10,9 +10,9 @@ use Flow\ETL\Schema; use Iterator; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(JsonOpenSource::class, false)) { return; } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php index 71c99b8728..89a8d6dae5 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Integration/AdaptiveJsonOpenSourceTest.php @@ -4,10 +4,13 @@ namespace Flow\ETL\Adapter\JSON\Tests\Integration; +use Flow\ETL\Adapter\JSON\AdaptiveJsonOpenSource; use Flow\ETL\Adapter\JSON\JSONMachine\JsonFormat; use Flow\ETL\Adapter\JSON\Tests\Context\JsonFixtureContext; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\RuntimeException; use Flow\ETL\Extractor\File\SourceFile; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\RustIterator; use Flow\ETL\Tests\Context\MemoryFiles; use Flow\ETL\Tests\Double\CountingFilesystem; @@ -125,4 +128,40 @@ public function test_a_pointer_is_read_by_the_php_lane(JsonFormat $format, strin static::assertInstanceOf(Generator::class, $open->batches(schema(int_schema('id')), 2, new PhpBackend())); static::assertSame(0, $counting->readFromCalls); } + + public function test_a_flow_php_of_another_abi_is_refused_before_the_file_is_opened(): void + { + $filesystem = new CountingFilesystem(new NativeLocalFilesystem()); + + try { + new AdaptiveJsonOpenSource( + $filesystem, + JsonFixtureContext::reader(JsonFormat::Lines, $filesystem), + JsonFormat::Lines, + null, + JsonFixtureContext::source('five_rows.jsonl'), + new FlowPhpExtension(true, FlowPhpExtension::ABI + 1, '0.46.0'), + ); + static::fail('a skewed flow_php must be refused'); + } catch (RuntimeException $e) { + static::assertStringContainsString('does not match flow-php/etl', $e->getMessage()); + } + + static::assertSame(0, $filesystem->readFromCalls); + } + + public function test_without_flow_php_a_file_is_read_by_the_php_lane_whatever_is_loaded(): void + { + $open = new AdaptiveJsonOpenSource( + new NativeLocalFilesystem(), + JsonFixtureContext::reader(JsonFormat::Lines, new NativeLocalFilesystem()), + JsonFormat::Lines, + null, + JsonFixtureContext::source('five_rows.jsonl'), + new FlowPhpExtension(false, null), + ); + + static::assertInstanceOf(Generator::class, $open->batches(schema(int_schema('id')), 2, new PhpBackend())); + $open->close(); + } } diff --git a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJsonEncoderTest.php b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJsonEncoderTest.php index 42766441a0..4a9a6886b5 100644 --- a/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJsonEncoderTest.php +++ b/src/adapter/etl-adapter-json/tests/Flow/ETL/Adapter/JSON/Tests/Unit/AdaptiveJsonEncoderTest.php @@ -8,6 +8,8 @@ use Flow\ETL\Adapter\JSON\AdaptiveJsonEncoder; use Flow\ETL\Adapter\JSON\JsonFraming; use Flow\ETL\Adapter\JSON\JsonOpenSink; +use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Stream\StringDestinationStream; @@ -56,4 +58,12 @@ public function test_a_flag_the_native_writer_does_not_render_is_written_through static::assertSame("{\n \"id\": 1\n}\n", $stream->content()); } + + public function test_a_flow_php_of_another_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('does not match flow-php/etl'); + + new AdaptiveJsonEncoder(extension: new FlowPhpExtension(true, FlowPhpExtension::ABI + 1, '0.46.0')); + } } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php index 43cc251ac1..c3ca5424dc 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSink.php @@ -4,6 +4,7 @@ namespace Flow\ETL\Adapter\Parquet; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Loader\File\FileSink; use Flow\ETL\Rows; use Flow\Filesystem\DestinationStream; @@ -15,8 +16,6 @@ use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema as ParquetSchema; -use function extension_loaded; - final readonly class AdaptiveParquetOpenSink implements FileSink, ParquetOpenSink { private ParquetOpenSink $sink; @@ -31,7 +30,9 @@ public function __construct( Compressions $compressions, Options $options, ?ParquetEngine $engine = null, + ?FlowPhpExtension $extension = null, ) { + $native = ($extension ?? FlowPhpExtension::detect())->available(); $file = ($engine ?? new AdaptiveParquetEngine(ByteOrder::LITTLE_ENDIAN, $options))->openForWrite( $stream, $schema, @@ -39,7 +40,7 @@ public function __construct( $options, ); - $this->sink = extension_loaded('flow_php') && $file instanceof RustParquetFileWriter + $this->sink = $native && $file instanceof RustParquetFileWriter ? new RustParquetOpenSink($file) : new PhpParquetOpenSink($file, new ParquetEncoder($schema)); } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSource.php index e738b8005c..4692df24a8 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSource.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/AdaptiveParquetOpenSource.php @@ -5,22 +5,22 @@ namespace Flow\ETL\Adapter\Parquet; use Flow\ETL\Column\Backend; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Schema; use Flow\Parquet\Engine\RustParquetFileReader; use Flow\Parquet\ParquetFile; use Iterator; -use function extension_loaded; - final readonly class AdaptiveParquetOpenSource implements ParquetOpenSource { private ParquetOpenSource $source; - public function __construct(ParquetFile $file) + public function __construct(ParquetFile $file, ?FlowPhpExtension $extension = null) { $reader = $file->reader(); - $this->source = extension_loaded('flow_php') && $reader instanceof RustParquetFileReader + $this->source = ($extension ?? FlowPhpExtension::detect())->available() + && $reader instanceof RustParquetFileReader ? new RustParquetOpenSource($reader) : new PhpParquetOpenSource($file); } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php index 93b43ea093..363a125eee 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSink.php @@ -6,9 +6,9 @@ use Flow\ETL\Rows; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(ParquetOpenSink::class, false)) { return; } diff --git a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php index 5b243fe8c0..c1cfc09013 100644 --- a/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php +++ b/src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/ParquetOpenSource.php @@ -9,9 +9,9 @@ use Flow\ETL\Schema; use Iterator; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(ParquetOpenSource::class, false)) { return; } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php index cd263290ac..28bb753c98 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php @@ -9,6 +9,8 @@ use Flow\ETL\Adapter\Parquet\SchemaConverter; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetFilesContext; use Flow\ETL\Adapter\Parquet\Tests\Double\RecordingParquetEngine; +use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Tests\FlowTestCase; use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\AdaptiveParquetEngine; @@ -129,4 +131,19 @@ public function test_any_other_engine_writes_the_file(): void ParquetFilesContext::phpEngineValues($filesystem, 'memory://out.parquet'), ); } + + public function test_a_flow_php_of_another_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('does not match flow-php/etl'); + + new AdaptiveParquetOpenSink( + memory_filesystem()->writeTo(path('memory://out.parquet')), + (new SchemaConverter())->toParquet(schema(int_schema('id'))), + Compressions::SNAPPY, + Options::default(), + new PhpParquetEngine(), + new FlowPhpExtension(true, FlowPhpExtension::ABI + 1, '0.46.0'), + ); + } } diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSourceTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSourceTest.php index 86dccf0e2b..ce01e23bad 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSourceTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSourceTest.php @@ -7,6 +7,8 @@ use Flow\ETL\Adapter\Parquet\AdaptiveParquetOpenSource; use Flow\ETL\Adapter\Parquet\Tests\Context\ParquetSourceFileContext; use Flow\ETL\Column\PhpBackend; +use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\RustIterator; use Flow\ETL\Tests\FlowTestCase; use Flow\Filesystem\Local\NativeLocalFilesystem; @@ -73,4 +75,14 @@ public function test_without_flow_php_a_rust_engine_file_reads_through_php(): vo )); $source->close(); } + + public function test_a_flow_php_of_another_abi_is_refused(): void + { + $file = ParquetSourceFileContext::over(new NativeLocalFilesystem())->file; + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('does not match flow-php/etl'); + + new AdaptiveParquetOpenSource($file, new FlowPhpExtension(true, FlowPhpExtension::ABI + 1, '0.46.0')); + } } diff --git a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextEncoder.php b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextEncoder.php index 8a403f588a..39e7f456a3 100644 --- a/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextEncoder.php +++ b/src/adapter/etl-adapter-text/src/Flow/ETL/Adapter/Text/TextEncoder.php @@ -36,7 +36,7 @@ public function encode(Rows $rows): string if (count($definitions) > 1) { throw new RuntimeException(sprintf( - 'Text data loader supports only a single entry rows, and you have %d rows.', + 'Text data loader writes at most one column, the batch has %d columns.', count($definitions), )); } diff --git a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextEncoderTest.php b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextEncoderTest.php index a5342b4af5..ae8b1c8dca 100644 --- a/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextEncoderTest.php +++ b/src/adapter/etl-adapter-text/tests/Flow/ETL/Adapter/Text/Tests/Unit/TextEncoderTest.php @@ -86,9 +86,12 @@ public function test_encode_ends_every_line_with_the_configured_separator(): voi public function test_encode_throws_when_a_row_has_more_than_one_column(): void { $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Text data loader supports only a single entry rows, and you have 2 rows.'); + $this->expectExceptionMessage('Text data loader writes at most one column, the batch has 3 columns.'); - (new TextEncoder())->encode(array_to_rows([['a' => 1, 'b' => 2]], schema(int_schema('a'), int_schema('b')))); + (new TextEncoder())->encode(array_to_rows( + [['a' => 1, 'b' => 2, 'c' => 3], ['a' => 4, 'b' => 5, 'c' => 6]], + schema(int_schema('a'), int_schema('b'), int_schema('c')), + )); } public function test_encode_of_an_empty_batch_with_more_than_one_column_returns_no_lines(): void diff --git a/src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php b/src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php index 016237687b..424a345c91 100644 --- a/src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php +++ b/src/core/etl/src/Flow/ETL/Column/AdaptiveBackend.php @@ -4,17 +4,16 @@ namespace Flow\ETL\Column; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Schema\Definition; -use function extension_loaded; - final readonly class AdaptiveBackend implements Backend { private Backend $backend; - public function __construct() + public function __construct(?FlowPhpExtension $extension = null) { - $this->backend = extension_loaded('flow_php') ? new RustBackend() : new PhpBackend(); + $this->backend = ($extension ?? FlowPhpExtension::detect())->available() ? new RustBackend() : new PhpBackend(); } public function builder(Definition $definition): ColumnBuilder diff --git a/src/core/etl/src/Flow/ETL/Column/Backend.php b/src/core/etl/src/Flow/ETL/Column/Backend.php index 187666215c..42b6799c74 100644 --- a/src/core/etl/src/Flow/ETL/Column/Backend.php +++ b/src/core/etl/src/Flow/ETL/Column/Backend.php @@ -7,9 +7,9 @@ use Flow\ETL\Exception\ColumnMismatchException; use Flow\ETL\Schema\Definition; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(Backend::class, false)) { return; } diff --git a/src/core/etl/src/Flow/ETL/Column/Column.php b/src/core/etl/src/Flow/ETL/Column/Column.php index 63e50bdcfa..8547fa1598 100644 --- a/src/core/etl/src/Flow/ETL/Column/Column.php +++ b/src/core/etl/src/Flow/ETL/Column/Column.php @@ -7,9 +7,9 @@ use Flow\ETL\Schema\Definition; use Flow\Types\Type; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(Column::class, false)) { return; } diff --git a/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php b/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php index 1de7390c52..d86a5fe647 100644 --- a/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php +++ b/src/core/etl/src/Flow/ETL/Column/ColumnBuilder.php @@ -7,9 +7,9 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\SchemaMismatchException; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('flow_php')) { +if (interface_exists(ColumnBuilder::class, false)) { return; } diff --git a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php index d1e0008e27..cc3d0ff8d1 100644 --- a/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php +++ b/src/core/etl/src/Flow/ETL/Config/ConfigBuilder.php @@ -40,7 +40,7 @@ final class ConfigBuilder private ?ClockInterface $clock; - private Backend $backend; + private ?Backend $backend; private ?GroupByAlgorithmBuilder $groupBy; @@ -71,7 +71,7 @@ public function __construct() $this->id = null; $this->name = null; $this->serializer = null; - $this->backend = new AdaptiveBackend(); + $this->backend = null; $this->optimizer = null; $this->executor = null; $this->clock = null; @@ -105,10 +105,12 @@ public function backend(Backend $backend): self public function build(): Config { $id = $this->id ??= 'flow-php-' . $this->randomValueGenerator->string(32); + // built here, not in the constructor: a backend() opt-out must not depend on the default's extension check + $backend = $this->backend ?? new AdaptiveBackend(); $this->optimizer ??= Optimizer::default(); $this->executor ??= new Executor(); // built per build(), not stored: a later backend() call must reach the next build's serializer - $serializer = $this->serializer ?? new FloeSerializer($this->backend); + $serializer = $this->serializer ?? new FloeSerializer($backend); $optimizer = $this->optimizer; $executor = $this->executor; $dataframeName = $this->name ?? 'flow_dataframe'; @@ -124,17 +126,17 @@ public function build(): Config $optimizer, $executor, $cacheConfig, - ($this->sort ?? new ExternalSortBuilder())->build($cacheConfig->localFilesystemCacheDir, $this->backend), + ($this->sort ?? new ExternalSortBuilder())->build($cacheConfig->localFilesystemCacheDir, $backend), $this->analyze, $this->telemetryConfig ?? TelemetryConfig::default($this->getClock()), - ($this->groupBy ?? new HashGroupByBuilder())->build($cacheConfig->localFilesystemCacheDir, $this->backend), - ($this->join ?? new HashJoinBuilder())->build($cacheConfig->localFilesystemCacheDir, $this->backend), + ($this->groupBy ?? new HashGroupByBuilder())->build($cacheConfig->localFilesystemCacheDir, $backend), + ($this->join ?? new HashJoinBuilder())->build($cacheConfig->localFilesystemCacheDir, $backend), ($this->repartition ?? new HashRepartitionBuilder())->build( $cacheConfig->localFilesystemCacheDir, - $this->backend, + $backend, ), randomValueGenerator: $this->randomValueGenerator, - backend: $this->backend, + backend: $backend, ); } diff --git a/src/core/etl/src/Flow/ETL/FlowPhpExtension.php b/src/core/etl/src/Flow/ETL/FlowPhpExtension.php new file mode 100644 index 0000000000..20844015ee --- /dev/null +++ b/src/core/etl/src/Flow/ETL/FlowPhpExtension.php @@ -0,0 +1,63 @@ +loaded) { + return false; + } + + if ($this->abi !== self::ABI) { + throw new RuntimeException(sprintf( + 'The loaded flow_php extension (%s, ABI %s) does not match flow-php/etl (ABI %d). Rebuild or upgrade ' + . 'flow_php to the version of flow-php/etl, or stop loading it to use the PHP implementation.', + $this->version, + $this->abi ?? 'none', + self::ABI, + )); + } + + return true; + } +} 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 9501e715f2..421acac53b 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 @@ -163,7 +163,7 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/Partitioning/overwrite/date=2024-04-01/file.txt', 'partitions' => ['date' => '2024-04-01'], 'date' => '2024-04-01', @@ -171,7 +171,7 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/Partitioning/overwrite/date=2024-04-02/file.txt', 'partitions' => ['date' => '2024-04-02'], 'date' => '2024-04-02', @@ -179,7 +179,7 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/Partitioning/overwrite/date=2024-04-03/file.txt', 'partitions' => ['date' => '2024-04-03'], 'date' => '2024-04-03', @@ -187,7 +187,7 @@ public function test_overwrite_save_mode_not_dropping_old_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/Partitioning/overwrite/date=2024-04-04/file.txt', 'partitions' => ['date' => '2024-04-04'], 'date' => '2024-04-04', 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 5ef3666968..f048299c3a 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 @@ -103,7 +103,7 @@ public function test_extracting_data_from_path_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/multi_partitioned/year=2022/month=12/day=30/file.txt', 'partitions' => ['year' => '2022', 'month' => '12', 'day' => '30'], 'day' => '30', @@ -113,7 +113,7 @@ public function test_extracting_data_from_path_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/multi_partitioned/year=2022/month=12/day=31/file.txt', 'partitions' => ['year' => '2022', 'month' => '12', 'day' => '31'], 'day' => '31', @@ -123,7 +123,7 @@ public function test_extracting_data_from_path_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/multi_partitioned/year=2023/month=1/day=1/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '1'], 'day' => '1', @@ -133,7 +133,7 @@ public function test_extracting_data_from_path_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/multi_partitioned/year=2023/month=1/day=2/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '2'], 'day' => '2', @@ -143,7 +143,7 @@ public function test_extracting_data_from_path_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/multi_partitioned/year=2023/month=1/day=3/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '3'], 'day' => '3', @@ -153,7 +153,7 @@ public function test_extracting_data_from_path_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/multi_partitioned/year=2023/month=1/day=4/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '4'], 'day' => '4', @@ -163,7 +163,7 @@ public function test_extracting_data_from_path_partitions(): void [ 'path' => 'file://' - . ltrim(str_replace('\\', '/', __DIR__), '/') + . str_replace('\\', '/', __DIR__) . '/Fixtures/multi_partitioned/year=2023/month=1/day=5/file.txt', 'partitions' => ['year' => '2023', 'month' => '1', 'day' => '5'], 'day' => '5', diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php index 75820ec8fe..07f406c467 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/AdaptiveBackendTest.php @@ -8,6 +8,8 @@ use Flow\ETL\Column\PhpBackend; use Flow\ETL\Column\ValueColumn; use Flow\ETL\Exception\ColumnMismatchException; +use Flow\ETL\Exception\RuntimeException; +use Flow\ETL\FlowPhpExtension; use Flow\ETL\Tests\Double\ForeignColumnStub; use Flow\ETL\Tests\Mother\ColumnMother; use PHPUnit\Framework\TestCase; @@ -77,4 +79,12 @@ public function test_decode_is_what_the_php_backend_decodes(): void (new AdaptiveBackend())->decode(int_schema('a', nullable: true), $buffers, 2, 1), ); } + + public function test_a_flow_php_of_another_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('does not match flow-php/etl'); + + new AdaptiveBackend(new FlowPhpExtension(true, FlowPhpExtension::ABI + 1, '0.46.0')); + } } 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 ca8be005ac..e9e50824f2 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/DataFrameTest.php @@ -962,11 +962,11 @@ public function test_a_pushed_limit_reaches_extract_and_leaves_the_users_extract static::assertSame(1, $extractor->limits[0]); static::assertSame(1, $extractor->limits[1]); static::assertStringEndsWith( - "#1 Read\n Extractor: RecordingFileExtractor\n Source: file://dev/null", + "#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" + "#1 Read\n Extractor: RecordingFileExtractor\n Source: file:///dev/null" . "\n Limit: 1", $frame->explain()->toString(), ); @@ -1209,7 +1209,7 @@ public function test_explain_prints_the_logical_plan_without_reading_a_row(): vo │ Condition: IsNotNull └─ #1 Read source · transparent · streaming Extractor: RecordingFileExtractor - Source: file://dev/null + Source: file:///dev/null PLAN, $dataFrame->explain()->toString(format: Format::declarations)); static::assertSame([], $extractor->limits); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowPhpExtensionTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowPhpExtensionTest.php new file mode 100644 index 0000000000..1ecd4d604a --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/FlowPhpExtensionTest.php @@ -0,0 +1,51 @@ +available()); + } + + public function test_a_loaded_extension_of_the_expected_abi_is_available(): void + { + static::assertTrue((new FlowPhpExtension(true, FlowPhpExtension::ABI))->available()); + } + + public function test_a_loaded_extension_of_another_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'The loaded flow_php extension (0.46.0, ABI 2) does not match flow-php/etl (ABI 1). Rebuild or upgrade ' + . 'flow_php to the version of flow-php/etl, or stop loading it to use the PHP implementation.', + ); + + (new FlowPhpExtension(true, FlowPhpExtension::ABI + 1, '0.46.0'))->available(); + } + + public function test_a_loaded_extension_without_an_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The loaded flow_php extension (0.44.1, ABI none) does not match flow-php/etl'); + + (new FlowPhpExtension(true, null, '0.44.1'))->available(); + } + + public function test_detect_reports_whether_flow_php_is_loaded(): void + { + $extension = FlowPhpExtension::detect(); + + static::assertSame(extension_loaded('flow_php'), $extension->loaded); + static::assertSame(extension_loaded('flow_php') ? FlowPhpExtension::ABI : null, $extension->abi); + } +} 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 index 9cdf73e140..5c0c37cb02 100644 --- 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 @@ -383,11 +383,11 @@ public function test_the_extractor_instance_is_never_mutated(): void $frame->fetch(); static::assertStringEndsWith( - "Extractor: RecordingFileExtractor\n Source: file://dev/null", + "Extractor: RecordingFileExtractor\n Source: file:///dev/null", $frame->explain()->toString(Stage::unoptimized), ); static::assertStringEndsWith( - "Extractor: RecordingFileExtractor\n Source: file://dev/null\n Files: Filters", + "Extractor: RecordingFileExtractor\n Source: file:///dev/null\n Files: Filters", $frame->explain()->toString(), ); } diff --git a/src/extension/arrow-ext/src/lib.rs b/src/extension/arrow-ext/src/lib.rs index c6f5dbdc7c..8804b3bff3 100644 --- a/src/extension/arrow-ext/src/lib.rs +++ b/src/extension/arrow-ext/src/lib.rs @@ -28,6 +28,10 @@ pub extern "C" fn php_module_info(_module: *mut ModuleEntry) { info_table_end!(); } +/// The contract version flow-php/parquet expects (`Flow\Parquet\Engine\ArrowExtension::ABI`); both change together +/// whenever a registered class or interface changes. +const FLOW_ARROW_ABI: i64 = 1; + /// # Safety /// /// Invoked by the PHP/Zend engine during module startup. Must only be called by @@ -46,6 +50,7 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { module .version(env!("ARROW_VERSION")) .info_function(php_module_info) + .constant(("FLOW_ARROW_ABI", FLOW_ARROW_ABI, &[])) .globals(&php::GLOBALS) .request_startup_function(php::request_startup) .request_shutdown_function(php::request_shutdown) diff --git a/src/extension/arrow-ext/tests/phpt/054_abi_matches_flow_php_parquet.phpt b/src/extension/arrow-ext/tests/phpt/054_abi_matches_flow_php_parquet.phpt new file mode 100644 index 0000000000..a9dd504db2 --- /dev/null +++ b/src/extension/arrow-ext/tests/phpt/054_abi_matches_flow_php_parquet.phpt @@ -0,0 +1,35 @@ +--TEST-- +arrow registers FLOW_ARROW_ABI equal to the ABI flow-php/parquet expects, so AdaptiveParquetEngine takes the Rust lane +--SKIPIF-- + +--FILE-- +available()); + +$writer = (new AdaptiveParquetEngine())->openForWrite( + new StringDestinationStream(path('memory://out.parquet')), + Schema::with(FlatColumn::int32('id')), + Compressions::UNCOMPRESSED, + new Options(), +); +var_dump($writer instanceof RustParquetFileWriter); +$writer->close(); +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) diff --git a/src/extension/flow-php-ext/src/lib.rs b/src/extension/flow-php-ext/src/lib.rs index 63a3aa03df..345286df8b 100644 --- a/src/extension/flow-php-ext/src/lib.rs +++ b/src/extension/flow-php-ext/src/lib.rs @@ -28,6 +28,10 @@ use ext_php_rs::prelude::*; use ext_php_rs::zend::ModuleEntry; use ext_php_rs::{info_table_end, info_table_row, info_table_start}; +/// The contract version flow-php/etl expects (`Flow\ETL\FlowPhpExtension::ABI`); both change together whenever a +/// registered class or interface changes. +const FLOW_PHP_ABI: i64 = 1; + pub extern "C" fn php_module_info(_module: *mut ModuleEntry) { info_table_start!(); info_table_row!("flow_php.enabled", "true"); @@ -53,6 +57,7 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { module .version(env!("FLOW_PHP_EXT_VERSION")) .info_function(php_module_info) + .constant(("FLOW_PHP_ABI", FLOW_PHP_ABI, &[])) .globals(&globals::GLOBALS) .request_startup_function(globals::request_startup) .request_shutdown_function(globals::request_shutdown) diff --git a/src/extension/flow-php-ext/tests/phpt/099_abi_matches_flow_php_etl.phpt b/src/extension/flow-php-ext/tests/phpt/099_abi_matches_flow_php_etl.phpt new file mode 100644 index 0000000000..412ea98207 --- /dev/null +++ b/src/extension/flow-php-ext/tests/phpt/099_abi_matches_flow_php_etl.phpt @@ -0,0 +1,22 @@ +--TEST-- +flow_php registers FLOW_PHP_ABI equal to the ABI flow-php/etl expects, so the Adaptive picks take the Rust lane +--SKIPIF-- + +--FILE-- +available()); +var_dump((new AdaptiveBackend())->constant(int_schema('id'), 1, 2) instanceof RustColumn); +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) diff --git a/src/lib/filesystem/src/Flow/Filesystem/Path/UnixPath.php b/src/lib/filesystem/src/Flow/Filesystem/Path/UnixPath.php index a408c7ee94..95d8f90028 100644 --- a/src/lib/filesystem/src/Flow/Filesystem/Path/UnixPath.php +++ b/src/lib/filesystem/src/Flow/Filesystem/Path/UnixPath.php @@ -525,6 +525,10 @@ public function suffix(string $string): self public function uri(): string { + if ($this->protocol === 'file') { + return 'file://' . $this->path; + } + return $this->protocol . '://' . ltrim($this->path, '/'); } diff --git a/src/lib/filesystem/tests/Flow/Filesystem/Tests/Integration/OS/Unix/NativeLocalFilesystemTest.php b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Integration/OS/Unix/NativeLocalFilesystemTest.php index 17eb48d473..c92fba7e47 100644 --- a/src/lib/filesystem/tests/Flow/Filesystem/Tests/Integration/OS/Unix/NativeLocalFilesystemTest.php +++ b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Integration/OS/Unix/NativeLocalFilesystemTest.php @@ -58,10 +58,7 @@ public function test_file_status_on_pattern_unix_uri_format(): void $statusForUri = $fs->status(path(__DIR__ . '/../var/some_path_to/*.txt')); static::assertNotNull($statusForUri); - static::assertSame( - 'file://' . ltrim(__DIR__, '/') . '/../var/some_path_to/file.txt', - $statusForUri->path->uri(), - ); + static::assertSame('file://' . __DIR__ . '/../var/some_path_to/file.txt', $statusForUri->path->uri()); $fs->rm(path(__DIR__ . '/../var/some_path_to')); } @@ -98,7 +95,7 @@ public function test_tmp_dir_unix_uri_format(): void { $fs = native_local_filesystem(); - static::assertSame('file://' . ltrim(sys_get_temp_dir(), '/'), $fs->getSystemTmpDir()->uri()); + static::assertSame('file://' . sys_get_temp_dir(), $fs->getSystemTmpDir()->uri()); } public function test_unix_absolute_path_behavior(): void diff --git a/src/lib/filesystem/tests/Flow/Filesystem/Tests/Unit/Path/UnixPathTest.php b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Unit/Path/UnixPathTest.php index 158356d083..51f60ead11 100644 --- a/src/lib/filesystem/tests/Flow/Filesystem/Tests/Unit/Path/UnixPathTest.php +++ b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Unit/Path/UnixPathTest.php @@ -62,7 +62,7 @@ public function test_absolute_path_handling(): void $path = new UnixPath('/path/to/file.txt'); static::assertEquals('/path/to/file.txt', $path->path()); - static::assertEquals('file://path/to/file.txt', $path->uri()); + static::assertEquals('file:///path/to/file.txt', $path->uri()); static::assertEquals('file.txt', $path->basename()); static::assertEquals('file', $path->filename()); static::assertEquals('txt', $path->extension()); @@ -414,8 +414,8 @@ public function test_partitions_paths_with_root_directory(): void $partitionPaths = $path->partitionsPaths(); static::assertCount(2, $partitionPaths); - static::assertEquals('file://country=US', $partitionPaths[0]->uri()); - static::assertEquals('file://country=US/region=west', $partitionPaths[1]->uri()); + static::assertEquals('file:///country=US', $partitionPaths[0]->uri()); + static::assertEquals('file:///country=US/region=west', $partitionPaths[1]->uri()); } public function test_partitions_paths_without_partitions(): void @@ -563,7 +563,7 @@ public function test_realpath_with_file_scheme_strips_protocol_prefix(): void static::assertSame('file', $path->protocol()); static::assertSame('/private/tmp/foo.txt', $path->path()); - static::assertSame('file://private/tmp/foo.txt', $path->uri()); + static::assertSame('file:///private/tmp/foo.txt', $path->uri()); } public function test_realpath_with_non_file_scheme(): void @@ -584,7 +584,7 @@ public function test_relative_path_normalization(): void $path = new UnixPath('relative/path/file.txt'); static::assertEquals('/relative/path/file.txt', $path->path()); - static::assertEquals('file://relative/path/file.txt', $path->uri()); + static::assertEquals('file:///relative/path/file.txt', $path->uri()); } public function test_root_directory_cases(): void @@ -614,7 +614,7 @@ public function test_root_partition_handling(): void $partitioned = $path->addPartitions(partition('group', 'a')); static::assertEquals('/group=a/file.txt', $partitioned->path()); - static::assertEquals('file://group=a/file.txt', $partitioned->uri()); + static::assertEquals('file:///group=a/file.txt', $partitioned->uri()); } public function test_set_extension_without_existing_extension(): void @@ -647,11 +647,11 @@ public function test_skip_directories(): void $skipped1 = $path->skipDirectories(1); static::assertNotNull($skipped1); - static::assertEquals('file://www/index.html', $skipped1->uri()); + static::assertEquals('file:///www/index.html', $skipped1->uri()); $skipped2 = $path->skipDirectories(2); static::assertNotNull($skipped2); - static::assertEquals('file://index.html', $skipped2->uri()); + static::assertEquals('file:///index.html', $skipped2->uri()); $skipped3 = $path->skipDirectories(3); static::assertNull($skipped3); @@ -721,6 +721,25 @@ public function test_uri_method(): void { $path = new UnixPath('/path/file.txt'); - static::assertEquals('file://path/file.txt', $path->uri()); + static::assertEquals('file:///path/file.txt', $path->uri()); + } + + public function test_uri_of_a_file_path_reads_back_as_the_same_path(): void + { + $path = new UnixPath('/path/file.txt'); + + static::assertSame('/path/file.txt', (new UnixPath($path->uri()))->path()); + static::assertSame('file:///path/file.txt', (new UnixPath($path->uri()))->uri()); + } + + public function test_uri_of_the_root_directory(): void + { + static::assertSame('file:///', (new UnixPath('/'))->uri()); + } + + public function test_uri_of_a_non_file_protocol_has_no_leading_slash(): void + { + static::assertSame('memory://path/file.txt', (new UnixPath('memory://path/file.txt'))->uri()); + static::assertSame('s3://bucket/key.txt', (new UnixPath('s3://bucket/key.txt'))->uri()); } } diff --git a/src/lib/filesystem/tests/Flow/Filesystem/Tests/Unit/PathTest.php b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Unit/PathTest.php index 74c86fa814..a600d6aba3 100644 --- a/src/lib/filesystem/tests/Flow/Filesystem/Tests/Unit/PathTest.php +++ b/src/lib/filesystem/tests/Flow/Filesystem/Tests/Unit/PathTest.php @@ -38,13 +38,13 @@ public static function directories(): Generator */ public static function paths(): Generator { - yield ['/file.csv', 'file', 'file://file.csv']; - yield ['file://file.csv', 'file', 'file://file.csv']; - yield ['file:///', 'file', 'file://']; - yield ['/', 'file', 'file://']; - yield ['/absolute/path/to/file.txt', 'file', 'file://absolute/path/to/file.txt']; - yield ['file://absolute/path/to/file.txt', 'file', 'file://absolute/path/to/file.txt']; - yield ['file:///absolute/path/to/file.txt', 'file', 'file://absolute/path/to/file.txt']; + yield ['/file.csv', 'file', 'file:///file.csv']; + yield ['file://file.csv', 'file', 'file:///file.csv']; + yield ['file:///', 'file', 'file:///']; + yield ['/', 'file', 'file:///']; + yield ['/absolute/path/to/file.txt', 'file', 'file:///absolute/path/to/file.txt']; + yield ['file://absolute/path/to/file.txt', 'file', 'file:///absolute/path/to/file.txt']; + yield ['file:///absolute/path/to/file.txt', 'file', 'file:///absolute/path/to/file.txt']; yield ['flow-file://', 'flow-file', 'flow-file://']; yield ['flow-file:///', 'flow-file', 'flow-file://']; yield ['flow-file://folder/file.csv', 'flow-file', 'flow-file://folder/file.csv']; diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php index 1b7cfa8374..d9477610ac 100644 --- a/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/Engine/AdaptiveParquetEngine.php @@ -14,15 +14,16 @@ use Flow\Parquet\ParquetFileReader; use Flow\Parquet\ParquetFileWriter; -use function extension_loaded; - final readonly class AdaptiveParquetEngine implements ParquetEngine { private ParquetEngine $engine; - public function __construct(ByteOrder $byteOrder = ByteOrder::LITTLE_ENDIAN, Options $options = new Options()) - { - $this->engine = extension_loaded('arrow') && $byteOrder === ByteOrder::LITTLE_ENDIAN + public function __construct( + ByteOrder $byteOrder = ByteOrder::LITTLE_ENDIAN, + Options $options = new Options(), + ?ArrowExtension $extension = null, + ) { + $this->engine = ($extension ?? ArrowExtension::detect())->available() && $byteOrder === ByteOrder::LITTLE_ENDIAN ? new RustParquetEngine($options) : new PhpParquetEngine($byteOrder, $options); } diff --git a/src/lib/parquet/src/Flow/Parquet/Engine/ArrowExtension.php b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowExtension.php new file mode 100644 index 0000000000..bf9ed403e4 --- /dev/null +++ b/src/lib/parquet/src/Flow/Parquet/Engine/ArrowExtension.php @@ -0,0 +1,63 @@ +loaded) { + return false; + } + + if ($this->abi !== self::ABI) { + throw new RuntimeException(sprintf( + 'The loaded arrow extension (%s, ABI %s) does not match flow-php/parquet (ABI %d). Rebuild or upgrade ' + . 'arrow-ext to the version of flow-php/parquet, or stop loading it to use the PHP implementation.', + $this->version, + $this->abi ?? 'none', + self::ABI, + )); + } + + return true; + } +} diff --git a/src/lib/parquet/src/Flow/Parquet/Option.php b/src/lib/parquet/src/Flow/Parquet/Option.php index 5f39b0c88e..b3caeefde9 100644 --- a/src/lib/parquet/src/Flow/Parquet/Option.php +++ b/src/lib/parquet/src/Flow/Parquet/Option.php @@ -35,14 +35,6 @@ enum Option */ case BROTLI_COMPRESSION_LEVEL; - /** - * Some parquet writers might not properly use LogicalTyp for storing Strings or JSON's. - * This option would tell the reader to treat all BYTE_ARRAY's as UTF-8 strings. - * - * Default value is true; - */ - case BYTE_ARRAY_TO_STRING; - /** * Per-column compression configuration using flat path notation. * Accepts array where key is column flat path and value is compression enum. diff --git a/src/lib/parquet/src/Flow/Parquet/Options.php b/src/lib/parquet/src/Flow/Parquet/Options.php index b16d2c4494..f64ae97ace 100644 --- a/src/lib/parquet/src/Flow/Parquet/Options.php +++ b/src/lib/parquet/src/Flow/Parquet/Options.php @@ -25,7 +25,6 @@ public function __construct() $this->options = [ Option::ARROW_BATCH_SIZE->name => 1024, Option::ARROW_WRITE_BATCH_SIZE->name => 1000, - Option::BYTE_ARRAY_TO_STRING->name => true, Option::INT_96_AS_DATETIME->name => true, Option::PAGE_MAXIMUM_ROWS_COUNT->name => 1000, Option::PAGE_SIZE_BYTES->name => SizeUnits::KiB_SIZE * 128, diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php b/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php index eafd9a2ccf..51974879cd 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetEngine.php @@ -9,9 +9,9 @@ use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('arrow')) { +if (interface_exists(ParquetEngine::class, false)) { return; } diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php b/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php index 841c5038d8..b98d703d9b 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFileReader.php @@ -8,9 +8,9 @@ use Flow\Parquet\ParquetFile\Schema; use Iterator; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('arrow')) { +if (interface_exists(ParquetFileReader::class, false)) { return; } diff --git a/src/lib/parquet/src/Flow/Parquet/ParquetFileWriter.php b/src/lib/parquet/src/Flow/Parquet/ParquetFileWriter.php index 80856dc0e9..b9e6b8a91d 100644 --- a/src/lib/parquet/src/Flow/Parquet/ParquetFileWriter.php +++ b/src/lib/parquet/src/Flow/Parquet/ParquetFileWriter.php @@ -4,9 +4,9 @@ namespace Flow\Parquet; -use function extension_loaded; +use function interface_exists; -if (extension_loaded('arrow')) { +if (interface_exists(ParquetFileWriter::class, false)) { return; } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php index f627389a2f..cea7cd486b 100644 --- a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/AdaptiveParquetEngineTest.php @@ -8,10 +8,12 @@ use Flow\Filesystem\Stream\StringDestinationStream; use Flow\Parquet\Binary\ByteOrder; use Flow\Parquet\Engine\AdaptiveParquetEngine; +use Flow\Parquet\Engine\ArrowExtension; use Flow\Parquet\Engine\PhpParquetFileReader; use Flow\Parquet\Engine\PhpParquetFileWriter; use Flow\Parquet\Engine\RustParquetFileReader; use Flow\Parquet\Engine\RustParquetFileWriter; +use Flow\Parquet\Exception\RuntimeException; use Flow\Parquet\Options; use Flow\Parquet\ParquetFile\Compressions; use Flow\Parquet\ParquetFile\Schema; @@ -97,4 +99,27 @@ public function test_big_endian_is_read_by_the_php_engine(): void ), ); } + + public function test_an_arrow_extension_of_another_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('does not match flow-php/parquet'); + + new AdaptiveParquetEngine(extension: new ArrowExtension(true, ArrowExtension::ABI + 1, '0.46.0')); + } + + public function test_without_arrow_files_are_opened_by_the_php_engine_whatever_is_loaded(): void + { + $filesystem = memory_filesystem(); + + static::assertInstanceOf(PhpParquetFileWriter::class, (new AdaptiveParquetEngine(extension: new ArrowExtension( + false, + null, + )))->openForWrite( + $filesystem->writeTo(path('memory://out.parquet')), + Schema::with(FlatColumn::int32('id')), + Compressions::UNCOMPRESSED, + new Options(), + )); + } } diff --git a/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowExtensionTest.php b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowExtensionTest.php new file mode 100644 index 0000000000..ef894a0435 --- /dev/null +++ b/src/lib/parquet/tests/Flow/Parquet/Tests/Unit/Engine/ArrowExtensionTest.php @@ -0,0 +1,51 @@ +available()); + } + + public function test_a_loaded_extension_of_the_expected_abi_is_available(): void + { + static::assertTrue((new ArrowExtension(true, ArrowExtension::ABI))->available()); + } + + public function test_a_loaded_extension_of_another_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'The loaded arrow extension (0.46.0, ABI 2) does not match flow-php/parquet (ABI 1). Rebuild or upgrade ' + . 'arrow-ext to the version of flow-php/parquet, or stop loading it to use the PHP implementation.', + ); + + (new ArrowExtension(true, ArrowExtension::ABI + 1, '0.46.0'))->available(); + } + + public function test_a_loaded_extension_without_an_abi_is_refused(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The loaded arrow extension (0.44.1, ABI none) does not match flow-php/parquet'); + + (new ArrowExtension(true, null, '0.44.1'))->available(); + } + + public function test_detect_reports_whether_arrow_is_loaded(): void + { + $extension = ArrowExtension::detect(); + + static::assertSame(extension_loaded('arrow'), $extension->loaded); + static::assertSame(extension_loaded('arrow') ? ArrowExtension::ABI : null, $extension->abi); + } +} diff --git a/wasm/build.sh b/wasm/build.sh index f557fa7ac7..19e5ea71c8 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -208,6 +208,11 @@ export PKG_CONFIG_PATH="$LIBZIP_INSTALL_DIR/lib/pkgconfig:${PKG_CONFIG_PATH:-}" export LIBZIP_CFLAGS="-I$LIBZIP_INSTALL_DIR/include" export LIBZIP_LIBS="-L$LIBZIP_INSTALL_DIR/lib -lzip" +# Without these, pkg-config finds the nix shell's own libxml2 and PHP compiles against its newer headers while linking +# the libxml2 built above - mismatched signatures, and calls into functions the linked library does not have. +export LIBXML_CFLAGS="-I$LIBXML2_INSTALL_DIR/include/libxml2" +export LIBXML_LIBS="-L$LIBXML2_INSTALL_DIR/lib -lxml2" + cd $PHP_PATH # The extension set and the reason for each is in documentation/contributing/wasm.md. @@ -287,7 +292,16 @@ mkdir -p out echo "Compile pib_eval wrapper" emcc $CFLAGS -I . -I Zend -I main -I TSRM/ ../pib_eval.c -c -o pib_eval.o +# --disable-fiber-asm makes Zend/zend_fibers.c switch Fiber stacks with getcontext/makecontext/swapcontext, which +# Emscripten's libc lacks. The shim implements them over Emscripten fibers (needs -sASYNCIFY below). +echo "Compile ucontext shim" +emcc $CFLAGS ../ucontext-emscripten.c -c -o ucontext-emscripten.o + +echo "Compile the libc functions Emscripten leaves out" +emcc $CFLAGS ../libc-emscripten.c -c -o libc-emscripten.o + echo "Link everything together" +# -s DEFAULT_TO_CXX=1 links libc++/libc++abi for the C++ snappy extension: operator new/delete, __cxxabiv1::__class_type_info / __si_class_type_info vtables emcc $CFLAGS $LDFLAGS $WASM64_MODE \ -s ENVIRONMENT=web \ -s EXPORTED_FUNCTIONS='["_pib_eval", "_pib_force_exit", "_pib_heap_bytes"]' \ @@ -301,11 +315,12 @@ emcc $CFLAGS $LDFLAGS $WASM64_MODE \ -s STACK_SIZE=5242880 \ -s ASSERTIONS=0 \ -s INVOKE_RUN=0 \ - -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ + -s ERROR_ON_UNDEFINED_SYMBOLS=1 \ + -s DEFAULT_TO_CXX=1 \ -s ASYNCIFY=1 \ -s STACK_OVERFLOW_CHECK=0 \ -s SAFE_HEAP=0 \ - libs/libphp.a pib_eval.o $LIBXML2_INSTALL_DIR/lib/libxml2.a $LIBPG_QUERY_INSTALL_DIR/libpg_query.a $LIBZIP_INSTALL_DIR/lib/libzip.a -o out/php.js + ucontext-emscripten.o libc-emscripten.o libs/libphp.a pib_eval.o $LIBXML2_INSTALL_DIR/lib/libxml2.a $LIBPG_QUERY_INSTALL_DIR/libpg_query.a $LIBZIP_INSTALL_DIR/lib/libzip.a -o out/php.js echo "Copy outputs to web/landing/assets/wasm" OUTPUT_DIR="$PROJECT_ROOT/../web/landing/assets/wasm" diff --git a/wasm/libc-emscripten.c b/wasm/libc-emscripten.c new file mode 100644 index 0000000000..5739bad0bf --- /dev/null +++ b/wasm/libc-emscripten.c @@ -0,0 +1,41 @@ +/* + * libc functions PHP calls that Emscripten leaves out of its libc build (tools/system_libs.py excludes musl's + * src/legacy and src/process). Defined here so the link runs with -sERROR_ON_UNDEFINED_SYMBOLS=1 instead of turning + * them into stubs that abort the runtime when called. + */ + +#include +#include +#include +#include +#include + +/* musl's src/legacy/getdtablesize.c - php://fd/N checks N against it */ +int getdtablesize(void) +{ + struct rlimit limit; + + getrlimit(RLIMIT_NOFILE, &limit); + + return limit.rlim_cur < INT_MAX ? (int) limit.rlim_cur : INT_MAX; +} + +/* a browser cannot start a process: proc_open() reports ENOSYS as a PHP warning instead of aborting */ +int posix_spawnp( + pid_t *restrict pid, + const char *restrict file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *restrict attributes, + char *const argv[restrict], + char *const envp[restrict] +) +{ + (void) pid; + (void) file; + (void) file_actions; + (void) attributes; + (void) argv; + (void) envp; + + return ENOSYS; +} diff --git a/wasm/ucontext-emscripten.c b/wasm/ucontext-emscripten.c new file mode 100644 index 0000000000..d0be6c4348 --- /dev/null +++ b/wasm/ucontext-emscripten.c @@ -0,0 +1,156 @@ +/* + * getcontext() / makecontext() / swapcontext() for Emscripten, built on its fiber API (needs -sASYNCIFY). + * + * PHP built with --disable-fiber-asm switches Fiber stacks through these three calls (Zend/zend_fibers.c), and + * Emscripten's libc has none of them. Only what zend_fibers.c does is supported; anything else aborts with a message: + * - getcontext() on a context that makecontext() prepares next, + * - makecontext() with no arguments, uc_link == NULL and uc_stack set, + * - swapcontext() from the running context to a prepared or previously saved one. The main context is never + * passed to getcontext() (zend_fiber_init() points it at uninitialised memory), so the running context is + * tracked here, and the main one is captured at the first swap. + */ + +#include +#include +#include +#include +#include + +/* + * At a swap, Asyncify spills the wasm locals of every frame on the stack into the context's buffer: about 1.2 bytes + * per byte of C stack in use (measured on PHP 8.5: ~336 against ~276 bytes per nested internal callback). + * A Fiber gives half of its own stack to the buffer, so nesting is bounded by the stack as on native PHP, at no extra + * memory. The main context is captured at its first swap, from Flow's pipeline loop (~1.3 KB measured); 256 KB covers + * ~750 nested internal callbacks there. Overflowing either buffer traps in Asyncify ("unreachable"), never corrupts. + */ +#define FLOW_UCONTEXT_MAIN_ASYNCIFY_SIZE (256 * 1024) +#define FLOW_UCONTEXT_MIN_STACK_SIZE (64 * 1024) + +typedef struct flow_ucontext { + emscripten_fiber_t fiber; + void (*entry)(void); + size_t asyncify_size; + char *asyncify_stack; +} flow_ucontext; + +_Static_assert(sizeof(((ucontext_t *) 0)->uc_mcontext) >= sizeof(flow_ucontext *), "uc_mcontext cannot hold the state pointer"); + +static flow_ucontext *running = NULL; +static flow_ucontext main_context; +static char main_asyncify_stack[FLOW_UCONTEXT_MAIN_ASYNCIFY_SIZE] __attribute__((aligned(16))); + +static _Noreturn void refuse(const char *what) +{ + fprintf(stderr, "ucontext-emscripten: %s is not supported\n", what); + abort(); +} + +static flow_ucontext **slot(ucontext_t *ucp) +{ + return (flow_ucontext **) &ucp->uc_mcontext; +} + +#ifdef FLOW_UCONTEXT_TRACE +/* the context that swapped away last: until it is resumed, its buffer holds its whole unwound stack */ +static flow_ucontext *unwound = NULL; +static size_t high_water_main = 0; +static size_t high_water_fiber = 0; + +static void trace(void) +{ + size_t used = (size_t) ((char *) unwound->fiber.asyncify_data.stack_ptr - unwound->asyncify_stack); + size_t *mark = unwound == &main_context ? &high_water_main : &high_water_fiber; + + if (used > *mark) { + *mark = used; + fprintf( + stderr, + "ucontext-emscripten: asyncify high water %s %zu bytes, C stack in use %zu bytes\n", + unwound == &main_context ? "main" : "fiber", + used, + (size_t) ((char *) unwound->fiber.stack_base - (char *) unwound->fiber.stack_ptr) + ); + } +} +#endif + +static void enter(void *arg) +{ +#ifdef FLOW_UCONTEXT_TRACE + trace(); +#endif + + ((flow_ucontext *) arg)->entry(); + + refuse("returning from a makecontext() entry (uc_link is NULL)"); +} + +int getcontext(ucontext_t *ucp) +{ + *slot(ucp) = NULL; + + return 0; +} + +void makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + if (argc != 0) { + refuse("makecontext() with arguments"); + } + + if (ucp->uc_link != NULL) { + refuse("makecontext() with uc_link"); + } + + char *bottom = (char *) ucp->uc_stack.ss_sp; + size_t size = ucp->uc_stack.ss_size; + + if (bottom == NULL || size < FLOW_UCONTEXT_MIN_STACK_SIZE) { + refuse("makecontext() without a uc_stack of at least 64 KiB"); + } + + /* the state and its Asyncify buffer take the top half of the stack, which grows down, and are freed with it */ + size_t asyncify_size = (size / 2 - sizeof(flow_ucontext) - 32) & ~(size_t) 15; + flow_ucontext *context = (flow_ucontext *) (((uintptr_t) bottom + size - sizeof(flow_ucontext) - asyncify_size - 32) & ~(uintptr_t) 15); + + context->entry = func; + context->asyncify_size = asyncify_size; + context->asyncify_stack = (char *) (((uintptr_t) (context + 1) + 15) & ~(uintptr_t) 15); + + emscripten_fiber_init(&context->fiber, enter, context, bottom, (size_t) ((char *) context - bottom), context->asyncify_stack, context->asyncify_size); + + *slot(ucp) = context; +} + +int swapcontext(ucontext_t *oucp, const ucontext_t *ucp) +{ + if (running == NULL) { + main_context.asyncify_size = sizeof(main_asyncify_stack); + main_context.asyncify_stack = main_asyncify_stack; + emscripten_fiber_init_from_current_context(&main_context.fiber, main_asyncify_stack, sizeof(main_asyncify_stack)); + running = &main_context; + } + + flow_ucontext *target = *slot((ucontext_t *) ucp); + + if (target == NULL) { + refuse("swapcontext() to a context makecontext() did not prepare"); + } + + flow_ucontext *previous = running; + + *slot(oucp) = previous; + running = target; + +#ifdef FLOW_UCONTEXT_TRACE + unwound = previous; +#endif + + emscripten_fiber_swap(&previous->fiber, &target->fiber); + +#ifdef FLOW_UCONTEXT_TRACE + trace(); +#endif + + return 0; +} diff --git a/web/landing/assets/codemirror/completions/dataframe.js b/web/landing/assets/codemirror/completions/dataframe.js index 5bcea27607..b2af0b323e 100644 --- a/web/landing/assets/codemirror/completions/dataframe.js +++ b/web/landing/assets/codemirror/completions/dataframe.js @@ -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","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"],"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"],"groupeddataframe":["aggregate"]}; // DataFrame methods const dataframeMethods = [ diff --git a/web/landing/assets/codemirror/completions/dsl.js b/web/landing/assets/codemirror/completions/dsl.js index b79cca30bc..19c7d7b703 100644 --- a/web/landing/assets/codemirror/completions/dsl.js +++ b/web/landing/assets/codemirror/completions/dsl.js @@ -700,7 +700,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - array_to_rows(array $data, Schema $schema, Backend $backend) : Rows + array_to_rows(array $data, Schema $schema, Backend $backend = Flow\\ETL\\Column\\AdaptiveBackend::...) : Rows
      @param array>|array $data @@ -8503,7 +8503,7 @@ const dslFunctions = [ const div = document.createElement("div") div.innerHTML = `
      - rows(Schema $schema, Backend $backend) : Rows + rows(Schema $schema, Backend $backend = Flow\\ETL\\Column\\AdaptiveBackend::...) : Rows
      ` return div diff --git a/web/landing/assets/codemirror/completions/scalarfunctionchain.js b/web/landing/assets/codemirror/completions/scalarfunctionchain.js index 53f109219a..745e7b229d 100644 --- a/web/landing/assets/codemirror/completions/scalarfunctionchain.js +++ b/web/landing/assets/codemirror/completions/scalarfunctionchain.js @@ -1133,12 +1133,12 @@ const scalarFunctionChainMethods = [ const div = document.createElement("div") div.innerHTML = `
      - minus(ScalarFunction|int|float $ref) : Minus + minus(ScalarFunction|int|float $ref, bool $exact = false) : Minus
      ` return div }, - apply: snippet("minus(" + "$" + "{" + "1:ref" + "}" + ")"), + apply: snippet("minus(" + "$" + "{" + "1:ref" + "}" + ", " + "$" + "{" + "2:exact" + "}" + ")"), boost: 10 }, { label: "mod", @@ -1178,12 +1178,12 @@ const scalarFunctionChainMethods = [ const div = document.createElement("div") div.innerHTML = `
      - multiply(ScalarFunction|int|float $value) : Multiply + multiply(ScalarFunction|int|float $value, bool $exact = false) : Multiply
      ` return div }, - apply: snippet("multiply(" + "$" + "{" + "1:value" + "}" + ")"), + apply: snippet("multiply(" + "$" + "{" + "1:value" + "}" + ", " + "$" + "{" + "2:exact" + "}" + ")"), boost: 10 }, { label: "notEquals", @@ -1286,12 +1286,12 @@ const scalarFunctionChainMethods = [ const div = document.createElement("div") div.innerHTML = `
      - plus(ScalarFunction|int|float $ref) : Plus + plus(ScalarFunction|int|float $ref, bool $exact = false) : Plus
      ` return div }, - apply: snippet("plus(" + "$" + "{" + "1:ref" + "}" + ")"), + apply: snippet("plus(" + "$" + "{" + "1:ref" + "}" + ", " + "$" + "{" + "2:exact" + "}" + ")"), boost: 10 }, { label: "power", @@ -1301,12 +1301,12 @@ const scalarFunctionChainMethods = [ const div = document.createElement("div") div.innerHTML = `
      - power(ScalarFunction|int $value) : Power + power(ScalarFunction|int $value, bool $exact = false) : Power
      ` return div }, - apply: snippet("power(" + "$" + "{" + "1:value" + "}" + ")"), + apply: snippet("power(" + "$" + "{" + "1:value" + "}" + ", " + "$" + "{" + "2:exact" + "}" + ")"), boost: 10 }, { label: "prepend", diff --git a/web/landing/assets/wasm/data/orders.floe b/web/landing/assets/wasm/data/orders.floe index 3136f68f7aa943972c9b85cf5f1cdb9ac81a179c..85b16c9bbdf0c354297a9840a643bf3f11039f42 100644 GIT binary patch literal 42030 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 literal 56434 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 bY$lGvjzhLrx0`& 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 literal 26568 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 YW0(YyL~MNfz~F=II*yBW{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;class EmscriptenEH{}class EmscriptenSjLj extends EmscriptenEH{}var readyPromiseResolve,readyPromiseReject;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;SOCKFS.root=FS.mount(SOCKFS,{},null);if(!Module["noFSInit"]&&!FS.initialized)FS.init();TTY.init();PIPEFS.root=FS.mount(PIPEFS,{},null);wasmExports["Lb"]();FS.ignorePermissions=false}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what=`Aborted(${what})`;err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("php.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;wasmExports=Asyncify.instrumentWasmExports(wasmExports);wasmExports=applySignatureConversions(wasmExports);assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var HEAP16;var HEAP32;var HEAP64;var HEAP8;var HEAPF32;var HEAPF64;var HEAPU16;var HEAPU32;var HEAPU64;var HEAPU8;var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var dynCalls={};function getValue(ptr,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":return HEAP8[ptr];case"i8":return HEAP8[ptr];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP64[ptr>>3];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];case"*":return Number(HEAPU64[ptr>>3]);default:abort(`invalid type for getValue: ${type}`)}}var noExitRuntime=true;function setValue(ptr,value,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":HEAP8[ptr]=value;break;case"i8":HEAP8[ptr]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":HEAP64[ptr>>3]=BigInt(value);break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;case"*":HEAPU64[ptr>>3]=BigInt(value);break;default:abort(`invalid type for setValue: ${type}`)}}var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>numINT53_MAX?NaN:Number(num);var UTF8Decoder=new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>{if(!ptr)return"";var end=findStringEnd(HEAPU8,ptr,maxBytesToRead,ignoreNul);return UTF8Decoder.decode(HEAPU8.subarray(ptr,end))};function ___assert_fail(condition,filename,line,func){condition=bigintToI53Checked(condition);filename=bigintToI53Checked(filename);func=bigintToI53Checked(func);return abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}var ___call_sighandler=function(fp,sig){fp=bigintToI53Checked(fp);return(a1=>dynCall_vi(fp,a1))(sig)};var initRandomFill=()=>view=>(crypto.getRandomValues(view),0);var randomFill=view=>(randomFill=initRandomFill())(view);var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.slice(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.slice(0,-1)}return root+dir},basename:path=>path&&path.match(/([^\/]+|\/)\/*$/)[1],join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).slice(1);to=PATH_FS.resolve(to).slice(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);return UTF8Decoder.decode(heapOrArray.buffer?heapOrArray.subarray(idx,endPtr):new Uint8Array(heapOrArray.slice(idx,endPtr)))};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var intArrayFromString=(stringy,dontAddNull,length)=>{var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array};var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(globalThis.window?.prompt){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output?.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(ptr,size)=>HEAPU8.fill(0,ptr,ptr+size);var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16895,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=MEMFS.emptyFileContents??=new Uint8Array(0)}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.atime=node.mtime=node.ctime=Date.now();if(parent){parent.contents[name]=node;parent.atime=parent.mtime=parent.ctime=node.atime}return node},getFileDataAsTypedArray(node){return node.contents.subarray(0,node.usedBytes)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents.length;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity)newCapacity=Math.max(newCapacity,256);var oldContents=MEMFS.getFileDataAsTypedArray(node);node.contents=new Uint8Array(newCapacity);node.contents.set(oldContents)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;var oldContents=node.contents;node.contents=new Uint8Array(newSize);node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)));node.usedBytes=newSize},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.atime);attr.mtime=new Date(node.mtime);attr.ctime=new Date(node.ctime);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){for(const key of["mode","atime","mtime","ctime"]){if(attr[key]!=null){node[key]=attr[key]}}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){if(!MEMFS.doesNotExistError){MEMFS.doesNotExistError=new FS.ErrnoError(44);MEMFS.doesNotExistError.stack=""}throw MEMFS.doesNotExistError},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){if(FS.isDir(old_node.mode)){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}FS.hashRemoveNode(new_node)}delete old_node.parent.contents[old_node.name];new_dir.contents[new_name]=old_node;old_node.name=new_name;new_dir.ctime=new_dir.mtime=old_node.parent.ctime=old_node.parent.mtime=Date.now()},unlink(parent,name){delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},readdir(node){return[".","..",...Object.keys(node.contents)]},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);buffer.set(contents.subarray(position,position+size),offset);return size},write(stream,buffer,offset,length,position,canOwn){if(buffer.buffer===HEAP8.buffer){canOwn=false}if(!length)return 0;var node=stream.node;node.mtime=node.ctime=Date.now();if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length}else if(node.usedBytes===0&&position===0){node.contents=buffer.slice(offset,offset+length);node.usedBytes=length}else{MEMFS.expandFileStorage(node,position+length);node.contents.set(buffer.subarray(offset,offset+length),position);node.usedBytes=Math.max(node.usedBytes,position+length)}return length},llseek(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(28)}return position},mmap(stream,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&contents.buffer===HEAP8.buffer){allocated=false;ptr=contents.byteOffset}else{allocated=true;ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}if(contents){if(position>0||position+length{if(typeof str!="string")return str;var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_fileDataToTypedArray=data=>{if(typeof data=="string"){data=intArrayFromString(data,true)}if(!data.subarray){data=new Uint8Array(data)}return data};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var asyncLoad=async url=>{var arrayBuffer=await readAsync(url);return new Uint8Array(arrayBuffer)};var FS_createDataFile=(...args)=>FS.createDataFile(...args);var getUniqueRunDependency=id=>id;var runDependencies=0;var dependenciesFulfilled=null;var removeRunDependency=id=>{runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}};var addRunDependency=id=>{runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)};var preloadPlugins=[];var FS_handledByPreloadPlugin=async(byteArray,fullname)=>{if(typeof Browser!="undefined")Browser.init();for(var plugin of preloadPlugins){if(plugin["canHandle"](fullname)){return plugin["handle"](byteArray,fullname)}}return byteArray};var FS_preloadFile=async(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);addRunDependency(dep);try{var byteArray=url;if(typeof url=="string"){byteArray=await asyncLoad(url)}byteArray=await FS_handledByPreloadPlugin(byteArray,fullname);preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}}finally{removeRunDependency(dep)}};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{FS_preloadFile(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish).then(onload).catch(onerror)};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,filesystems:null,syncFSRequests:0,ErrnoError:class{name="ErrnoError";constructor(errno){this.errno=errno}},FSStream:class{shared={};get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{node_ops={};stream_ops={};readMode=292|73;writeMode=146;mounted=null;constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.rdev=rdev;this.atime=this.mtime=this.ctime=Date.now()}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){if(!path){throw new FS.ErrnoError(44)}opts.follow_mount??=true;if(!PATH.isAbs(path)){path=FS.cwd()+"/"+path}linkloop:for(var nlinks=0;nlinks<40;nlinks++){var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}if(perms.includes("w")&&!(node.mode&146)){return 2}if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){if(!FS.isDir(dir.mode)){return 54}try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else if(FS.isDir(node.mode)){return 31}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}var mode=FS.flagsToPermissionString(flags);if(FS.isDir(node.mode)){if(mode!=="r"||flags&(512|64)){return 31}}return FS.nodePermissions(node,mode)},checkOpExists(op,err){if(!op){throw new FS.ErrnoError(err)}return op},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},doSetAttr(stream,node,attr){var setattr=stream?.stream_ops.setattr;var arg=setattr?stream:node;setattr??=node.node_ops.setattr;FS.checkOpExists(setattr,63);setattr(arg,attr)},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}for(var mount of mounts){if(mount.type.syncfs){mount.type.syncfs(mount,populate,done)}else{done(null)}}},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);for(var[hash,current]of Object.entries(FS.nameTable)){while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}}node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name){throw new FS.ErrnoError(28)}if(name==="."||name===".."){throw new FS.ErrnoError(20)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},statfs(path){return FS.statfsNode(FS.lookupPath(path,{follow:true}).node)},statfsStream(stream){return FS.statfsNode(stream.node)},statfsNode(node){var rtn={bsize:4096,frsize:4096,blocks:1e6,bfree:5e5,bavail:5e5,files:FS.nextInode,ffree:FS.nextInode-1,fsid:42,flags:2,namelen:255};if(node.node_ops.statfs){Object.assign(rtn,node.node_ops.statfs(node.mount.opts.root))}return rtn},create(path,mode=438){mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode=511){mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var dir of dirs){if(!dir)continue;if(d||PATH.isAbs(path))d+="/";d+=dir;try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name);old_node.parent=new_dir}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var readdir=FS.checkOpExists(node.node_ops.readdir,54);return readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return link.node_ops.readlink(link)},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;var getattr=FS.checkOpExists(node.node_ops.getattr,63);return getattr(node)},fstat(fd){var stream=FS.getStreamChecked(fd);var node=stream.node;var getattr=stream.stream_ops.getattr;var arg=getattr?stream:node;getattr??=node.node_ops.getattr;FS.checkOpExists(getattr,63);return getattr(arg)},lstat(path){return FS.stat(path,true)},doChmod(stream,node,mode,dontFollow){FS.doSetAttr(stream,node,{mode:mode&4095|node.mode&~4095,ctime:Date.now(),dontFollow})},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChmod(null,node,mode,dontFollow)},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.doChmod(stream,stream.node,mode,false)},doChown(stream,node,dontFollow){FS.doSetAttr(stream,node,{timestamp:Date.now(),dontFollow})},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChown(null,node,dontFollow)},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.doChown(stream,stream.node,false)},doTruncate(stream,node,len){if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}FS.doSetAttr(stream,node,{size:len,timestamp:Date.now()})},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}FS.doTruncate(null,node,len)},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if(len<0||(stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.doTruncate(stream,stream.node,len)},utime(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var setattr=FS.checkOpExists(node.node_ops.setattr,63);setattr(node,{atime,mtime})},open(path,flags,mode=438){if(path===""){throw new FS.ErrnoError(44)}flags=FS_modeStringToFlags(flags);if(flags&64){mode=mode&4095|32768}else{mode=0}var node;var isDirPath;if(typeof path=="object"){node=path}else{isDirPath=path.endsWith("/");var lookup=FS.lookupPath(path,{follow:!(flags&131072),noent_okay:true});node=lookup.node;path=lookup.path}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else if(isDirPath){throw new FS.ErrnoError(31)}else{node=FS.mknod(path,mode|511,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node,path:FS.getPath(node),flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(created){FS.chmod(node,mode&511)}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){abort(`Invalid encoding type "${opts.encoding}"`)}var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){buf=UTF8ArrayToString(buf)}FS.close(stream);return buf},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);data=FS_fileDataToTypedArray(data);FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn);FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length,llseek:()=>0});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomFill(randomBuffer);randomLeft=randomBuffer.byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16895,73);node.stream_ops={llseek:MEMFS.stream_ops.llseek};node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path},id:fd+1};ret.parent=ret;return ret},readdir(){return Array.from(FS.streams.entries()).filter(([k,v])=>v).map(([k,v])=>k.toString())}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;for(var stream of FS.streams){if(stream){FS.close(stream)}}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){if(e.errno!=20)throw e}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){data=FS_fileDataToTypedArray(data);FS.chmod(node,mode|146);var stream=FS.open(node,577);FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}},createDevice(parent,name,input,output){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);FS.createDevice.major??=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open(stream){stream.seekable=false},close(stream){if(output?.buffer?.length){output(10)}},read(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)abort("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)abort("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")abort("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(globalThis.XMLHttpRequest){if(!ENVIRONMENT_IS_WORKER)abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};for(const[key,fn]of Object.entries(node.stream_ops)){stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}}function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var SOCKFS={websocketArgs:{},callbacks:{},on(event,callback){SOCKFS.callbacks[event]=callback},emit(event,param){SOCKFS.callbacks[event]?.(param)},mount(mount){SOCKFS.websocketArgs=Module["websocket"]||{};(Module["websocket"]??={})["on"]=SOCKFS.on;return FS.createNode(null,"/",16895,0)},createSocket(family,type,protocol){if(family!=2){throw new FS.ErrnoError(5)}type&=~526336;if(type!=1&&type!=2){throw new FS.ErrnoError(28)}var streaming=type==1;if(streaming&&protocol&&protocol!=6){throw new FS.ErrnoError(66)}var sock={family,type,protocol,server:null,error:null,peers:{},pending:[],recv_queue:[],sock_ops:SOCKFS.websocket_sock_ops};var name=SOCKFS.nextname();var node=FS.createNode(SOCKFS.root,name,49152,0);node.sock=sock;var stream=FS.createStream({path:name,node,flags:2,seekable:false,stream_ops:SOCKFS.stream_ops});sock.stream=stream;return sock},getSocket(fd){var stream=FS.getStream(fd);if(!stream||!FS.isSocket(stream.node.mode)){return null}return stream.node.sock},stream_ops:{poll(stream){var sock=stream.node.sock;return sock.sock_ops.poll(sock)},ioctl(stream,request,varargs){var sock=stream.node.sock;return sock.sock_ops.ioctl(sock,request,varargs)},read(stream,buffer,offset,length,position){var sock=stream.node.sock;var msg=sock.sock_ops.recvmsg(sock,length);if(!msg){return 0}buffer.set(msg.buffer,offset);return msg.buffer.length},write(stream,buffer,offset,length,position){var sock=stream.node.sock;return sock.sock_ops.sendmsg(sock,buffer,offset,length)},close(stream){var sock=stream.node.sock;sock.sock_ops.close(sock)}},nextname(){if(!SOCKFS.nextname.current){SOCKFS.nextname.current=0}return`socket[${SOCKFS.nextname.current++}]`},websocket_sock_ops:{createPeer(sock,addr,port){var ws;if(typeof addr=="object"){ws=addr;addr=null;port=null}if(ws){if(ws._socket){addr=ws._socket.remoteAddress;port=ws._socket.remotePort}else{var result=/ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);if(!result){throw new Error("WebSocket URL must be in the format ws(s)://address:port")}addr=result[1];port=parseInt(result[2],10)}}else{try{var url="ws://".replace("#","//");var subProtocols="binary";var opts=undefined;if(SOCKFS.websocketArgs["url"]){url=SOCKFS.websocketArgs["url"]}if(SOCKFS.websocketArgs["subprotocol"]){subProtocols=SOCKFS.websocketArgs["subprotocol"]}else if(SOCKFS.websocketArgs["subprotocol"]===null){subProtocols="null"}if(url==="ws://"||url==="wss://"){var parts=addr.split("/");url=url+parts[0]+":"+port+"/"+parts.slice(1).join("/")}if(subProtocols!=="null"){subProtocols=subProtocols.replace(/^ +| +$/g,"").split(/ *, */);opts=subProtocols}var WebSocketConstructor;{WebSocketConstructor=WebSocket}ws=new WebSocketConstructor(url,opts);ws.binaryType="arraybuffer"}catch(e){throw new FS.ErrnoError(23)}}var peer={addr,port,socket:ws,msg_send_queue:[]};SOCKFS.websocket_sock_ops.addPeer(sock,peer);SOCKFS.websocket_sock_ops.handlePeerEvents(sock,peer);if(sock.type===2&&typeof sock.sport!="undefined"){peer.msg_send_queue.push(new Uint8Array([255,255,255,255,"p".charCodeAt(0),"o".charCodeAt(0),"r".charCodeAt(0),"t".charCodeAt(0),(sock.sport&65280)>>8,sock.sport&255]))}return peer},getPeer(sock,addr,port){return sock.peers[addr+":"+port]},addPeer(sock,peer){sock.peers[peer.addr+":"+peer.port]=peer},removePeer(sock,peer){delete sock.peers[peer.addr+":"+peer.port]},handlePeerEvents(sock,peer){var first=true;var handleOpen=function(){sock.connecting=false;SOCKFS.emit("open",sock.stream.fd);try{var queued=peer.msg_send_queue.shift();while(queued){peer.socket.send(queued);queued=peer.msg_send_queue.shift()}}catch(e){peer.socket.close()}};function handleMessage(data){if(typeof data=="string"){var encoder=new TextEncoder;data=encoder.encode(data)}else{if(data.byteLength==0){return}data=new Uint8Array(data)}var wasfirst=first;first=false;if(wasfirst&&data.length===10&&data[0]===255&&data[1]===255&&data[2]===255&&data[3]===255&&data[4]==="p".charCodeAt(0)&&data[5]==="o".charCodeAt(0)&&data[6]==="r".charCodeAt(0)&&data[7]==="t".charCodeAt(0)){var newport=data[8]<<8|data[9];SOCKFS.websocket_sock_ops.removePeer(sock,peer);peer.port=newport;SOCKFS.websocket_sock_ops.addPeer(sock,peer);return}sock.recv_queue.push({addr:peer.addr,port:peer.port,data});SOCKFS.emit("message",sock.stream.fd)}if(ENVIRONMENT_IS_NODE){peer.socket.on("open",handleOpen);peer.socket.on("message",function(data,isBinary){if(!isBinary){return}handleMessage(new Uint8Array(data).buffer)});peer.socket.on("close",function(){SOCKFS.emit("close",sock.stream.fd)});peer.socket.on("error",function(error){sock.error=14;SOCKFS.emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])})}else{peer.socket.onopen=handleOpen;peer.socket.onclose=function(){SOCKFS.emit("close",sock.stream.fd)};peer.socket.onmessage=function peer_socket_onmessage(event){handleMessage(event.data)};peer.socket.onerror=function(error){sock.error=14;SOCKFS.emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}}},poll(sock){if(sock.type===1&&sock.server){return sock.pending.length?64|1:0}var mask=0;var dest=sock.type===1?SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport):null;if(sock.recv_queue.length||!dest||dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=64|1}if(!dest||dest&&dest.socket.readyState===dest.socket.OPEN){mask|=4}if(dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){if(sock.connecting){mask|=4}else{mask|=16}}return mask},ioctl(sock,request,arg){switch(request){case 21531:var bytes=0;if(sock.recv_queue.length){bytes=sock.recv_queue[0].data.length}HEAP32[arg>>2]=bytes;return 0;case 21537:var on=HEAP32[arg>>2];if(on){sock.stream.flags|=2048}else{sock.stream.flags&=~2048}return 0;default:return 28}},close(sock){if(sock.server){try{sock.server.close()}catch(e){}sock.server=null}for(var peer of Object.values(sock.peers)){try{peer.socket.close()}catch(e){}SOCKFS.websocket_sock_ops.removePeer(sock,peer)}return 0},bind(sock,addr,port){if(typeof sock.saddr!="undefined"||typeof sock.sport!="undefined"){throw new FS.ErrnoError(28)}sock.saddr=addr;sock.sport=port;if(sock.type===2){if(sock.server){sock.server.close();sock.server=null}try{sock.sock_ops.listen(sock,0)}catch(e){if(!(e.name==="ErrnoError"))throw e;if(e.errno!==138)throw e}}},connect(sock,addr,port){if(sock.server){throw new FS.ErrnoError(138)}if(typeof sock.daddr!="undefined"&&typeof sock.dport!="undefined"){var dest=SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport);if(dest){if(dest.socket.readyState===dest.socket.CONNECTING){throw new FS.ErrnoError(7)}else{throw new FS.ErrnoError(30)}}}var peer=SOCKFS.websocket_sock_ops.createPeer(sock,addr,port);sock.daddr=peer.addr;sock.dport=peer.port;sock.connecting=true},listen(sock,backlog){if(!ENVIRONMENT_IS_NODE){throw new FS.ErrnoError(138)}},accept(listensock){if(!listensock.server||!listensock.pending.length){throw new FS.ErrnoError(28)}var newsock=listensock.pending.shift();newsock.stream.flags=listensock.stream.flags;return newsock},getname(sock,peer){var addr,port;if(peer){if(sock.daddr===undefined||sock.dport===undefined){throw new FS.ErrnoError(53)}addr=sock.daddr;port=sock.dport}else{addr=sock.saddr||0;port=sock.sport||0}return{addr,port}},sendmsg(sock,buffer,offset,length,addr,port){if(sock.type===2){if(addr===undefined||port===undefined){addr=sock.daddr;port=sock.dport}if(addr===undefined||port===undefined){throw new FS.ErrnoError(17)}}else{addr=sock.daddr;port=sock.dport}var dest=SOCKFS.websocket_sock_ops.getPeer(sock,addr,port);if(sock.type===1){if(!dest||dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){throw new FS.ErrnoError(53)}}if(ArrayBuffer.isView(buffer)){offset+=buffer.byteOffset;buffer=buffer.buffer}var data=buffer.slice(offset,offset+length);if(!dest||dest.socket.readyState!==dest.socket.OPEN){if(sock.type===2){if(!dest||dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){dest=SOCKFS.websocket_sock_ops.createPeer(sock,addr,port)}}dest.msg_send_queue.push(data);return length}try{dest.socket.send(data);return length}catch(e){throw new FS.ErrnoError(28)}},recvmsg(sock,length){if(sock.type===1&&sock.server){throw new FS.ErrnoError(53)}var queued=sock.recv_queue.shift();if(!queued){if(sock.type===1){var dest=SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport);if(!dest){throw new FS.ErrnoError(53)}if(dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){return null}throw new FS.ErrnoError(6)}throw new FS.ErrnoError(6)}var queuedLength=queued.data.byteLength||queued.data.length;var queuedOffset=queued.data.byteOffset||0;var queuedBuffer=queued.data.buffer||queued.data;var bytesRead=Math.min(length,queuedLength);var res={buffer:new Uint8Array(queuedBuffer,queuedOffset,bytesRead),addr:queued.addr,port:queued.port};if(sock.type===1&&bytesRead{var socket=SOCKFS.getSocket(fd);if(!socket)throw new FS.ErrnoError(8);return socket};var inetPton4=str=>{var b=str.split(".");for(var i=0;i<4;i++){var tmp=Number(b[i]);if(isNaN(tmp))return null;b[i]=tmp}return(b[0]|b[1]<<8|b[2]<<16|b[3]<<24)>>>0};var inetPton6=str=>{var words;var w,offset,z;var valid6regx=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;var parts=[];if(!valid6regx.test(str)){return null}if(str==="::"){return[0,0,0,0,0,0,0,0]}if(str.startsWith("::")){str=str.replace("::","Z:")}else{str=str.replace("::",":Z:")}if(str.indexOf(".")>0){str=str.replace(new RegExp("[.]","g"),":");words=str.split(":");words[words.length-4]=Number(words[words.length-4])+Number(words[words.length-3])*256;words[words.length-3]=Number(words[words.length-2])+Number(words[words.length-1])*256;words=words.slice(0,words.length-2)}else{words=str.split(":")}offset=0;z=0;for(w=0;w{switch(family){case 2:addr=inetPton4(addr);zeroMemory(sa,16);if(addrlen){HEAP32[addrlen>>2]=16}HEAP16[sa>>1]=family;HEAP32[sa+4>>2]=addr;HEAP16[sa+2>>1]=_htons(port);break;case 10:addr=inetPton6(addr);zeroMemory(sa,28);if(addrlen){HEAP32[addrlen>>2]=28}HEAP32[sa>>2]=family;HEAP32[sa+8>>2]=addr[0];HEAP32[sa+12>>2]=addr[1];HEAP32[sa+16>>2]=addr[2];HEAP32[sa+20>>2]=addr[3];HEAP16[sa+2>>1]=_htons(port);break;default:return 5}return 0};var DNS={address_map:{id:1,addrs:{},names:{}},lookup_name(name){var res=inetPton4(name);if(res!==null){return name}res=inetPton6(name);if(res!==null){return name}var addr;if(DNS.address_map.addrs[name]){addr=DNS.address_map.addrs[name]}else{var id=DNS.address_map.id++;addr="172.29."+(id&255)+"."+(id&65280);DNS.address_map.names[addr]=name;DNS.address_map.addrs[name]=addr}return addr},lookup_addr(addr){if(DNS.address_map.names[addr]){return DNS.address_map.names[addr]}return null}};function ___syscall_accept4(fd,addr,addrlen,flags,d1,d2){addr=bigintToI53Checked(addr);addrlen=bigintToI53Checked(addrlen);try{var sock=getSocketFromFD(fd);var newsock=sock.sock_ops.accept(sock);if(addr){var errno=writeSockaddr(addr,newsock.family,DNS.lookup_name(newsock.daddr),newsock.dport,addrlen)}return newsock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var inetNtop4=addr=>(addr&255)+"."+(addr>>8&255)+"."+(addr>>16&255)+"."+(addr>>24&255);var inetNtop6=ints=>{var str="";var word=0;var longest=0;var lastzero=0;var zstart=0;var len=0;var i=0;var parts=[ints[0]&65535,ints[0]>>16,ints[1]&65535,ints[1]>>16,ints[2]&65535,ints[2]>>16,ints[3]&65535,ints[3]>>16];var hasipv4=true;var v4part="";for(i=0;i<5;i++){if(parts[i]!==0){hasipv4=false;break}}if(hasipv4){v4part=inetNtop4(parts[6]|parts[7]<<16);if(parts[5]===-1){str="::ffff:";str+=v4part;return str}if(parts[5]===0){str="::";if(v4part==="0.0.0.0")v4part="";if(v4part==="0.0.0.1")v4part="1";str+=v4part;return str}}for(word=0;word<8;word++){if(parts[word]===0){if(word-lastzero>1){len=0}lastzero=word;len++}if(len>longest){longest=len;zstart=word-longest+1}}for(word=0;word<8;word++){if(longest>1){if(parts[word]===0&&word>=zstart&&word{var family=HEAP16[sa>>1];var port=_ntohs(HEAPU16[sa+2>>1]);var addr;switch(family){case 2:if(salen!==16){return{errno:28}}addr=HEAP32[sa+4>>2];addr=inetNtop4(addr);break;case 10:if(salen!==28){return{errno:28}}addr=[HEAP32[sa+8>>2],HEAP32[sa+12>>2],HEAP32[sa+16>>2],HEAP32[sa+20>>2]];addr=inetNtop6(addr);break;default:return{errno:5}}return{family,addr,port}};var getSocketAddress=(addrp,addrlen)=>{var info=readSockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info};function ___syscall_bind(fd,addr,addrlen,d1,d2,d3){addr=bigintToI53Checked(addr);addrlen=bigintToI53Checked(addrlen);try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,addrlen);sock.sock_ops.bind(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var SYSCALLS={calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return dir+"/"+path},writeStat(buf,stat){HEAPU32[buf>>2]=stat.dev;HEAPU32[buf+4>>2]=stat.mode;HEAPU64[buf+8>>3]=BigInt(stat.nlink);HEAPU32[buf+16>>2]=stat.uid;HEAPU32[buf+20>>2]=stat.gid;HEAPU32[buf+24>>2]=stat.rdev;HEAP64[buf+32>>3]=BigInt(stat.size);HEAP32[buf+40>>2]=4096;HEAP32[buf+44>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();HEAP64[buf+48>>3]=BigInt(Math.floor(atime/1e3));HEAPU64[buf+56>>3]=BigInt(atime%1e3*1e3*1e3);HEAP64[buf+64>>3]=BigInt(Math.floor(mtime/1e3));HEAPU64[buf+72>>3]=BigInt(mtime%1e3*1e3*1e3);HEAP64[buf+80>>3]=BigInt(Math.floor(ctime/1e3));HEAPU64[buf+88>>3]=BigInt(ctime%1e3*1e3*1e3);HEAP64[buf+96>>3]=BigInt(stat.ino);return 0},writeStatFs(buf,stats){HEAPU32[buf+8>>2]=stats.bsize;HEAPU32[buf+72>>2]=stats.bsize;HEAP64[buf+16>>3]=BigInt(stats.blocks);HEAP64[buf+24>>3]=BigInt(stats.bfree);HEAP64[buf+32>>3]=BigInt(stats.bavail);HEAP64[buf+40>>3]=BigInt(stats.files);HEAP64[buf+48>>3]=BigInt(stats.ffree);HEAPU32[buf+56>>2]=stats.fsid;HEAPU32[buf+80>>2]=stats.flags;HEAPU32[buf+64>>2]=stats.namelen},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_chdir(path){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);FS.chdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_chmod(path,mode){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_connect(fd,addr,addrlen,d1,d2,d3){addr=bigintToI53Checked(addr);addrlen=bigintToI53Checked(addrlen);try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,addrlen);sock.sock_ops.connect(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_dup(fd){try{var old=SYSCALLS.getStreamFromFD(fd);return FS.dupStream(old).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_faccessat(dirfd,path,amode,flags){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchmod(fd,mode){try{FS.fchmod(fd,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchownat(dirfd,path,owner,group,flags){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);var nofollow=flags&256;flags=flags&~256;path=SYSCALLS.calculateAt(dirfd,path);(nofollow?FS.lchown:FS.chown)(path,owner,group);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var syscallGetVarargP=()=>{var ret=Number(HEAPU64[SYSCALLS.varargs>>3]);SYSCALLS.varargs+=8;return ret};var syscallGetVarargI=()=>{var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret};function ___syscall_fcntl64(fd,cmd,varargs){varargs=bigintToI53Checked(varargs);SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 5:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fdatasync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){buf=bigintToI53Checked(buf);try{return SYSCALLS.writeStat(buf,FS.fstat(fd))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ftruncate64(fd,length){length=bigintToI53Checked(length);try{if(isNaN(length))return-61;FS.ftruncate(fd,length);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_getcwd(buf,size){buf=bigintToI53Checked(buf);size=bigintToI53Checked(size);try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>3]=BigInt(id);HEAP64[dirp+pos+8>>3]=BigInt((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getpeername(fd,addr,addrlen,d1,d2,d3){addr=bigintToI53Checked(addr);addrlen=bigintToI53Checked(addrlen);try{var sock=getSocketFromFD(fd);if(!sock.daddr){return-53}var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(sock.daddr),sock.dport,addrlen);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockname(fd,addr,addrlen,d1,d2,d3){addr=bigintToI53Checked(addr);addrlen=bigintToI53Checked(addrlen);try{var sock=getSocketFromFD(fd);var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(sock.saddr||"0.0.0.0"),sock.sport,addrlen);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockopt(fd,level,optname,optval,optlen,d1){optval=bigintToI53Checked(optval);optlen=bigintToI53Checked(optlen);try{var sock=getSocketFromFD(fd);if(level===1){if(optname===4){HEAP32[optval>>2]=sock.error;HEAP32[optlen>>2]=4;sock.error=null;return 0}}return-50}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){varargs=bigintToI53Checked(varargs);SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21537:case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_listen(fd,backlog){try{var sock=getSocketFromFD(fd);sock.sock_ops.listen(sock,backlog);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){path=bigintToI53Checked(path);buf=bigintToI53Checked(buf);try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.lstat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){path=bigintToI53Checked(path);buf=bigintToI53Checked(buf);try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.writeStat(buf,nofollow?FS.lstat(path):FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){path=bigintToI53Checked(path);varargs=bigintToI53Checked(varargs);SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var PIPEFS={BUCKET_BUFFER_SIZE:8192,mount(mount){return FS.createNode(null,"/",16384|511,0)},createPipe(){var pipe={buckets:[],refcnt:2,timestamp:new Date,readableHandlers:[],registerReadableHandler:callback=>{callback.registerCleanupFunc(()=>{const i=pipe.readableHandlers.indexOf(callback);if(i!==-1)pipe.readableHandlers.splice(i,1)});pipe.readableHandlers.push(callback)},notifyReadableHandlers:()=>{while(pipe.readableHandlers.length>0){const cb=pipe.readableHandlers.shift();if(cb)cb(64|1)}pipe.readableHandlers=[]}};pipe.buckets.push({buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:0,roffset:0});var rName=PIPEFS.nextname();var wName=PIPEFS.nextname();var rNode=FS.createNode(PIPEFS.root,rName,4096,0);var wNode=FS.createNode(PIPEFS.root,wName,4096,0);rNode.pipe=pipe;wNode.pipe=pipe;var readableStream=FS.createStream({path:rName,node:rNode,flags:0,seekable:false,stream_ops:PIPEFS.stream_ops});rNode.stream=readableStream;var writableStream=FS.createStream({path:wName,node:wNode,flags:1,seekable:false,stream_ops:PIPEFS.stream_ops});wNode.stream=writableStream;return{readable_fd:readableStream.fd,writable_fd:writableStream.fd}},stream_ops:{getattr(stream){var node=stream.node;var timestamp=node.pipe.timestamp;return{dev:14,ino:node.id,mode:4480,nlink:1,uid:0,gid:0,rdev:0,size:0,atime:timestamp,mtime:timestamp,ctime:timestamp,blksize:4096,blocks:0}},poll(stream,timeout,notifyCallback){var pipe=stream.node.pipe;if((stream.flags&2097155)===1){return 256|4}for(var bucket of pipe.buckets){if(bucket.offset-bucket.roffset>0){return 64|1}}if(notifyCallback)pipe.registerReadableHandler(notifyCallback);return 0},dup(stream){stream.node.pipe.refcnt++},ioctl(stream,request,varargs){return 28},fsync(stream){return 28},read(stream,buffer,offset,length,position){var pipe=stream.node.pipe;var currentLength=0;for(var bucket of pipe.buckets){currentLength+=bucket.offset-bucket.roffset}var data=buffer.subarray(offset,offset+length);if(length<=0){return 0}if(currentLength==0){throw new FS.ErrnoError(6)}var toRead=Math.min(currentLength,length);var totalRead=toRead;var toRemove=0;for(var bucket of pipe.buckets){var bucketSize=bucket.offset-bucket.roffset;if(toRead<=bucketSize){var tmpSlice=bucket.buffer.subarray(bucket.roffset,bucket.offset);if(toRead=dataLen){currBucket.buffer.set(data,currBucket.offset);currBucket.offset+=dataLen;pipe.notifyReadableHandlers();return dataLen}else if(freeBytesInCurrBuffer>0){currBucket.buffer.set(data.subarray(0,freeBytesInCurrBuffer),currBucket.offset);currBucket.offset+=freeBytesInCurrBuffer;data=data.subarray(freeBytesInCurrBuffer,data.byteLength)}var numBuckets=data.byteLength/PIPEFS.BUCKET_BUFFER_SIZE|0;var remElements=data.byteLength%PIPEFS.BUCKET_BUFFER_SIZE;for(var i=0;i0){var newBucket={buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:data.byteLength,roffset:0};pipe.buckets.push(newBucket);newBucket.buffer.set(data)}pipe.notifyReadableHandlers();return dataLen},close(stream){var pipe=stream.node.pipe;pipe.refcnt--;if(pipe.refcnt===0){pipe.buckets=null}}},nextname(){if(!PIPEFS.nextname.current){PIPEFS.nextname.current=0}return"pipe["+PIPEFS.nextname.current+++"]"}};function ___syscall_pipe2(fdPtr,flags){fdPtr=bigintToI53Checked(fdPtr);try{if(fdPtr==0){throw new FS.ErrnoError(21)}var validFlags=524288|2048;if(flags&~validFlags){throw new FS.ErrnoError(138)}var res=PIPEFS.createPipe();if(flags&2048){FS.getStream(res.readable_fd).flags|=2048;FS.getStream(res.writable_fd).flags|=2048}HEAP32[fdPtr>>2]=res.readable_fd;HEAP32[fdPtr+4>>2]=res.writable_fd;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var ___syscall_poll=function(fds,nfds,timeout){let innerFunc=()=>{fds=bigintToI53Checked(fds);try{const isAsyncContext=true;var resolve;var promise=new Promise(resolve_=>{resolve=resolve_});var cleanupFuncs=[];var notifyDone=false;function asyncPollComplete(count){if(notifyDone){return}notifyDone=true;cleanupFuncs.forEach(cb=>cb());resolve(count)}function makeNotifyCallback(stream,pollfd){var cb=flags=>{if(notifyDone){return}var events=HEAP16[pollfd+4>>1];flags&=events|8|16;HEAP16[pollfd+6>>1]=flags;asyncPollComplete(1)};cb.registerCleanupFunc=f=>{if(f)cleanupFuncs.push(f)};return cb}if(isAsyncContext){if(timeout>0){var t=setTimeout(()=>{asyncPollComplete(0)},timeout);cleanupFuncs.push(()=>clearTimeout(t))}}var count=0;for(var i=0;i>2];var events=HEAP16[pollfd+4>>1];var flags=32;var stream=FS.getStream(fd);if(stream){if(stream.stream_ops.poll){if(isAsyncContext&&timeout){flags=stream.stream_ops.poll(stream,timeout,makeNotifyCallback(stream,pollfd))}else flags=stream.stream_ops.poll(stream,-1)}else{flags=5}}flags&=events|8|16;if(flags)count++;HEAP16[pollfd+6>>1]=flags}if(isAsyncContext){if(count||!timeout){asyncPollComplete(count)}return promise}return count}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}};return Asyncify.handleAsync(innerFunc)};___syscall_poll.isAsync=true;function ___syscall_readlinkat(dirfd,path,buf,bufsize){path=bigintToI53Checked(path);buf=bigintToI53Checked(buf);bufsize=bigintToI53Checked(bufsize);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_recvfrom(fd,buf,len,flags,addr,addrlen){buf=bigintToI53Checked(buf);len=bigintToI53Checked(len);addr=bigintToI53Checked(addr);addrlen=bigintToI53Checked(addrlen);try{var sock=getSocketFromFD(fd);var msg=sock.sock_ops.recvmsg(sock,len);if(!msg)return 0;if(addr){var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(msg.addr),msg.port,addrlen)}HEAPU8.set(msg.buffer,buf);return msg.buffer.byteLength}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_renameat(olddirfd,oldpath,newdirfd,newpath){oldpath=bigintToI53Checked(oldpath);newpath=bigintToI53Checked(newpath);try{oldpath=SYSCALLS.getStr(oldpath);newpath=SYSCALLS.getStr(newpath);oldpath=SYSCALLS.calculateAt(olddirfd,oldpath);newpath=SYSCALLS.calculateAt(newdirfd,newpath);FS.rename(oldpath,newpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_sendto(fd,message,length,flags,addr,addr_len){message=bigintToI53Checked(message);length=bigintToI53Checked(length);addr=bigintToI53Checked(addr);addr_len=bigintToI53Checked(addr_len);try{var sock=getSocketFromFD(fd);if(!addr){return FS.write(sock.stream,HEAP8,message,length)}var dest=getSocketAddress(addr,addr_len);return sock.sock_ops.sendmsg(sock,HEAP8,message,length,dest.addr,dest.port)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_socket(domain,type,protocol){try{var sock=SOCKFS.createSocket(domain,type,protocol);return sock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){path=bigintToI53Checked(path);buf=bigintToI53Checked(buf);try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_statfs64(path,size,buf){path=bigintToI53Checked(path);size=bigintToI53Checked(size);buf=bigintToI53Checked(buf);try{SYSCALLS.writeStatFs(buf,FS.statfs(SYSCALLS.getStr(path)));return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_symlinkat(target,dirfd,linkpath){target=bigintToI53Checked(target);linkpath=bigintToI53Checked(linkpath);try{target=SYSCALLS.getStr(target);linkpath=SYSCALLS.getStr(linkpath);linkpath=SYSCALLS.calculateAt(dirfd,linkpath);FS.symlink(target,linkpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(!flags){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{return-28}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var readI53FromI64=ptr=>HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296;function ___syscall_utimensat(dirfd,path,times,flags){path=bigintToI53Checked(path);times=bigintToI53Checked(times);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path,true);var now=Date.now(),atime,mtime;if(!times){atime=now;mtime=now}else{var seconds=readI53FromI64(times);var nanoseconds=HEAP32[times+8>>2];if(nanoseconds==1073741823){atime=now}else if(nanoseconds==1073741822){atime=null}else{atime=seconds*1e3+nanoseconds/(1e3*1e3)}times+=16;seconds=readI53FromI64(times);nanoseconds=HEAP32[times+8>>2];if(nanoseconds==1073741823){mtime=now}else if(nanoseconds==1073741822){mtime=null}else{mtime=seconds*1e3+nanoseconds/(1e3*1e3)}}if((mtime??atime)!==null){FS.utime(path,atime,mtime)}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>abort("");function __emscripten_lookup_name(name){name=bigintToI53Checked(name);var nameString=UTF8ToString(name);return inetPton4(DNS.lookup_name(nameString))}var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var __emscripten_throw_longjmp=()=>{throw new EmscriptenSjLj};function __gmtime_js(time,tmPtr){time=bigintToI53Checked(time);tmPtr=bigintToI53Checked(tmPtr);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};function __localtime_js(time,tmPtr){time=bigintToI53Checked(time);tmPtr=bigintToI53Checked(tmPtr);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP64[tmPtr+40>>3]=BigInt(-(date.getTimezoneOffset()*60));var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}var __mktime_js=function(tmPtr){tmPtr=bigintToI53Checked(tmPtr);var ret=(()=>{var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();var timeMs=date.getTime();if(isNaN(timeMs)){return-1}return timeMs/1e3})();return BigInt(ret)};function __mmap_js(len,prot,flags,fd,offset,allocated,addr){len=bigintToI53Checked(len);offset=bigintToI53Checked(offset);allocated=bigintToI53Checked(allocated);addr=bigintToI53Checked(addr);try{var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU64[addr>>3]=BigInt(ptr);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){addr=bigintToI53Checked(addr);len=bigintToI53Checked(len);offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var __tzset_js=function(timezone,daylight,std_name,dst_name){timezone=bigintToI53Checked(timezone);daylight=bigintToI53Checked(daylight);std_name=bigintToI53Checked(std_name);dst_name=bigintToI53Checked(dst_name);var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU64[timezone>>3]=BigInt(stdTimezoneOffset*60);HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);if(summerOffsetDate.now();var nowIsMonotonic=1;var checkWasiClock=clock_id=>clock_id>=0&&clock_id<=3;function _clock_time_get(clk_id,ignored_precision,ptime){ignored_precision=bigintToI53Checked(ignored_precision);ptime=bigintToI53Checked(ptime);if(!checkWasiClock(clk_id)){return 28}var now;if(clk_id===0){now=_emscripten_date_now()}else if(nowIsMonotonic){now=_emscripten_get_now()}else{return 52}var nsec=Math.round(now*1e3*1e3);HEAP64[ptime>>3]=BigInt(nsec);return 0}var _emscripten_force_exit=status=>{__emscripten_runtime_keepalive_clear();_exit(status)};var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>BigInt(getHeapMax());var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};function _emscripten_resize_heap(requestedSize){requestedSize=bigintToI53Checked(requestedSize);var oldSize=HEAPU8.length;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false}var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};function _environ_get(__environ,environ_buf){__environ=bigintToI53Checked(__environ);environ_buf=bigintToI53Checked(environ_buf);var bufSize=0;var envp=0;for(var string of getEnvStrings()){var ptr=environ_buf+bufSize;HEAPU64[__environ+envp>>3]=BigInt(ptr);bufSize+=stringToUTF8(string,ptr,Infinity)+1;envp+=8}return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){penviron_count=bigintToI53Checked(penviron_count);penviron_buf_size=bigintToI53Checked(penviron_buf_size);var strings=getEnvStrings();HEAPU64[penviron_count>>3]=BigInt(strings.length);var bufSize=0;for(var string of strings){bufSize+=lengthBytesUTF8(string)+1}HEAPU64[penviron_buf_size>>3]=BigInt(bufSize);return 0}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){pbuf=bigintToI53Checked(pbuf);try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf]=type;HEAP16[pbuf+2>>1]=flags;HEAP64[pbuf+8>>3]=BigInt(rightsBase);HEAP64[pbuf+16>>3]=BigInt(rightsInheriting);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>3]);var len=Number(HEAPU64[iov+8>>3]);iov+=16;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>3]=BigInt(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset,whence,newOffset){offset=bigintToI53Checked(offset);newOffset=bigintToI53Checked(newOffset);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);HEAP64[newOffset>>3]=BigInt(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _fd_sync=function(fd){let innerFunc=()=>{try{var stream=SYSCALLS.getStreamFromFD(fd);var rtn=stream.stream_ops?.fsync?.(stream);return new Promise(resolve=>{var mount=stream.node.mount;if(mount?.type.syncfs){mount.type.syncfs(mount,false,err=>resolve(err?29:0))}else{resolve(rtn)}})}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}};return Asyncify.handleAsync(innerFunc)};_fd_sync.isAsync=true;var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>3]);var len=Number(HEAPU64[iov+8>>3]);iov+=16;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>3]=BigInt(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _getaddrinfo(node,service,hint,out){node=bigintToI53Checked(node);service=bigintToI53Checked(service);hint=bigintToI53Checked(hint);out=bigintToI53Checked(out);var addr=0;var port=0;var flags=0;var family=0;var type=0;var proto=0;var ai;function allocaddrinfo(family,type,proto,canon,addr,port){var sa,salen,ai;var errno;salen=family===10?28:16;addr=family===10?inetNtop6(addr):inetNtop4(addr);sa=_malloc(salen);errno=writeSockaddr(sa,family,addr,port);ai=_malloc(48);HEAP32[ai+4>>2]=family;HEAP32[ai+8>>2]=type;HEAP32[ai+12>>2]=proto;HEAPU64[ai+32>>3]=BigInt(canon);HEAPU64[ai+24>>3]=BigInt(sa);if(family===10){HEAP32[ai+16>>2]=28}else{HEAP32[ai+16>>2]=16}HEAP32[ai+40>>2]=0;return ai}if(hint){flags=HEAP32[hint>>2];family=HEAP32[hint+4>>2];type=HEAP32[hint+8>>2];proto=HEAP32[hint+12>>2]}if(type&&!proto){proto=type===2?17:6}if(!type&&proto){type=proto===17?2:1}if(proto===0){proto=6}if(type===0){type=1}if(!node&&!service){return-2}if(flags&~(1|2|4|1024|8|16|32)){return-1}if(hint!==0&&HEAP32[hint>>2]&2&&!node){return-1}if(flags&32){return-2}if(type!==0&&type!==1&&type!==2){return-7}if(family!==0&&family!==2&&family!==10){return-6}if(service){service=UTF8ToString(service);port=parseInt(service,10);if(isNaN(port)){if(flags&1024){return-2}return-8}}if(!node){if(family===0){family=2}if((flags&1)===0){if(family===2){addr=_htonl(2130706433)}else{addr=[0,0,0,_htonl(1)]}}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAPU64[out>>3]=BigInt(ai);return 0}node=UTF8ToString(node);addr=inetPton4(node);if(addr!==null){if(family===0||family===2){family=2}else if(family===10&&flags&8){addr=[0,0,_htonl(65535),addr];family=10}else{return-2}}else{addr=inetPton6(node);if(addr!==null){if(family===0||family===10){family=10}else{return-2}}}if(addr!=null){ai=allocaddrinfo(family,type,proto,node,addr,port);HEAPU64[out>>3]=BigInt(ai);return 0}if(flags&4){return-2}node=DNS.lookup_name(node);addr=inetPton4(node);if(family===0){family=2}else if(family===10){addr=[0,0,_htonl(65535),addr]}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAPU64[out>>3]=BigInt(ai);return 0}function _getcontext(...args){abort("missing function: getcontext")}_getcontext.stub=true;function _getdtablesize(...args){abort("missing function: getdtablesize")}_getdtablesize.stub=true;function _getnameinfo(sa,salen,node,nodelen,serv,servlen,flags){sa=bigintToI53Checked(sa);node=bigintToI53Checked(node);serv=bigintToI53Checked(serv);var info=readSockaddr(sa,salen);if(info.errno){return-6}var port=info.port;var addr=info.addr;var overflowed=false;if(node&&nodelen){var lookup;if(flags&1||!(lookup=DNS.lookup_addr(addr))){if(flags&8){return-2}}else{addr=lookup}var numBytesWrittenExclNull=stringToUTF8(addr,node,nodelen);if(numBytesWrittenExclNull+1>=nodelen){overflowed=true}}if(serv&&servlen){port=""+port;var numBytesWrittenExclNull=stringToUTF8(port,serv,servlen);if(numBytesWrittenExclNull+1>=servlen){overflowed=true}}if(overflowed){return-12}return 0}var Protocols={list:[],map:{}};var stringToAscii=(str,buffer)=>{for(var i=0;i{function allocprotoent(name,proto,aliases){var nameBuf=_malloc(name.length+1);stringToAscii(name,nameBuf);var j=0;var length=aliases.length;var aliasListBuf=_malloc((length+1)*4);for(var i=0;i>3]=BigInt(aliasBuf)}HEAPU64[aliasListBuf+j>>3]=0n;var pe=_malloc(24);HEAPU64[pe>>3]=BigInt(nameBuf);HEAPU64[pe+8>>3]=BigInt(aliasListBuf);HEAP32[pe+16>>2]=proto;return pe}var list=Protocols.list;var map=Protocols.map;if(list.length===0){var entry=allocprotoent("tcp",6,["TCP"]);list.push(entry);map["tcp"]=map["6"]=entry;entry=allocprotoent("udp",17,["UDP"]);list.push(entry);map["udp"]=map["17"]=entry}_setprotoent.index=0};var _getprotobyname=function(name){name=bigintToI53Checked(name);var ret=(()=>{name=UTF8ToString(name);_setprotoent(true);var result=Protocols.map[name];return result})();return BigInt(ret)};var _getprotobynumber=function(number){var ret=(()=>{_setprotoent(true);var result=Protocols.map[number];return result})();return BigInt(ret)};function _makecontext(...args){abort("missing function: makecontext")}_makecontext.stub=true;function _posix_spawnp(...args){abort("missing function: posix_spawnp")}_posix_spawnp.stub=true;var arraySum=(array,index)=>{var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum};var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];var addDays=(date,days)=>{var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate};var _strptime=function(buf,format,tm){buf=bigintToI53Checked(buf);format=bigintToI53Checked(format);tm=bigintToI53Checked(tm);var ret=(()=>{var pattern=UTF8ToString(format);var SPECIAL_CHARS="\\!@#$^&*()+=-[]/{}|:<>?,.";for(var i=0,ii=SPECIAL_CHARS.length;iEQUIVALENT_MATCHERS[c]||m).replace(/%(.)/g,(_,c)=>{let pat=DATE_PATTERNS[c];if(pat){capture.push(c);return`(${pat})`}else{return c}}).replace(/\s+/g,"\\s*");var matches=new RegExp("^"+pattern_out,"i").exec(UTF8ToString(buf));function initDate(){function fixup(value,min,max){return typeof value!="number"||isNaN(value)?min:value>=min?value<=max?value:max:min}return{year:fixup(HEAP32[tm+20>>2]+1900,1970,9999),month:fixup(HEAP32[tm+16>>2],0,11),day:fixup(HEAP32[tm+12>>2],1,31),hour:fixup(HEAP32[tm+8>>2],0,23),min:fixup(HEAP32[tm+4>>2],0,59),sec:fixup(HEAP32[tm>>2],0,59),gmtoff:0}}if(matches){var date=initDate();var value;var getMatch=symbol=>{var pos=capture.indexOf(symbol);if(pos>=0){return matches[pos+1]}return};if(value=getMatch("S")){date.sec=Number(value)}if(value=getMatch("M")){date.min=Number(value)}if(value=getMatch("H")){date.hour=Number(value)}else if(value=getMatch("I")){var hour=Number(value);if(value=getMatch("p")){hour+=value.toUpperCase()[0]==="P"?12:0}date.hour=hour}if(value=getMatch("Y")){date.year=Number(value)}else if(value=getMatch("y")){var year=Number(value);if(value=getMatch("C")){year+=Number(value)*100}else{year+=year<69?2e3:1900}date.year=year}if(value=getMatch("m")){date.month=Number(value)-1}else if(value=getMatch("b")){date.month=MONTH_NUMBERS[value.substring(0,3).toUpperCase()]||0}if(value=getMatch("d")){date.day=Number(value)}else if(value=getMatch("j")){var day=Number(value);var leapYear=isLeapYear(date.year);for(var month=0;month<12;++month){var daysUntilMonth=arraySum(leapYear?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,month-1);if(day<=daysUntilMonth+(leapYear?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[month]){date.day=day-daysUntilMonth}}}else if(value=getMatch("a")){var weekDay=value.substring(0,3).toUpperCase();if(value=getMatch("U")){var weekDayNumber=DAY_NUMBERS_SUN_FIRST[weekDay];var weekNumber=Number(value);var janFirst=new Date(date.year,0,1);var endDate;if(janFirst.getDay()===0){endDate=addDays(janFirst,weekDayNumber+7*(weekNumber-1))}else{endDate=addDays(janFirst,7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1))}date.day=endDate.getDate();date.month=endDate.getMonth()}else if(value=getMatch("W")){var weekDayNumber=DAY_NUMBERS_MON_FIRST[weekDay];var weekNumber=Number(value);var janFirst=new Date(date.year,0,1);var endDate;if(janFirst.getDay()===1){endDate=addDays(janFirst,weekDayNumber+7*(weekNumber-1))}else{endDate=addDays(janFirst,7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1))}date.day=endDate.getDate();date.month=endDate.getMonth()}}if(value=getMatch("z")){if(value.toLowerCase()==="z"){date.gmtoff=0}else{var match=value.match(/^((?:\-|\+)\d\d):?(\d\d)?/);date.gmtoff=match[1]*3600;if(match[2]){date.gmtoff+=date.gmtoff>0?match[2]*60:-match[2]*60}}}var fullDate=new Date(date.year,date.month,date.day,date.hour,date.min,date.sec,0);HEAP32[tm>>2]=fullDate.getSeconds();HEAP32[tm+4>>2]=fullDate.getMinutes();HEAP32[tm+8>>2]=fullDate.getHours();HEAP32[tm+12>>2]=fullDate.getDate();HEAP32[tm+16>>2]=fullDate.getMonth();HEAP32[tm+20>>2]=fullDate.getFullYear()-1900;HEAP32[tm+24>>2]=fullDate.getDay();HEAP32[tm+28>>2]=arraySum(isLeapYear(fullDate.getFullYear())?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,fullDate.getMonth()-1)+fullDate.getDate()-1;HEAP32[tm+32>>2]=0;HEAP64[tm+40>>3]=BigInt(date.gmtoff);return buf+lengthBytesUTF8(matches[0])}return 0})();return BigInt(ret)};function _swapcontext(...args){abort("missing function: swapcontext")}_swapcontext.stub=true;function _xmlFreeEntity(...args){abort("missing function: xmlFreeEntity")}_xmlFreeEntity.stub=true;function _xmlNewInputFromIO(...args){abort("missing function: xmlNewInputFromIO")}_xmlNewInputFromIO.stub=true;function _xmlXPathValuePop(...args){abort("missing function: xmlXPathValuePop")}_xmlXPathValuePop.stub=true;function _xmlXPathValuePush(...args){abort("missing function: xmlXPathValuePush")}_xmlXPathValuePush.stub=true;var runAndAbortIfError=func=>{try{return func()}catch(e){abort(e)}};var runtimeKeepalivePush=()=>{runtimeKeepaliveCounter+=1};var runtimeKeepalivePop=()=>{runtimeKeepaliveCounter-=1};var Asyncify={rewindArguments:new Map,instrumentWasmImports(imports){var importPattern=/^(invoke_.*|__asyncjs__.*)$/;for(let[x,original]of Object.entries(imports)){if(typeof original=="function"){let isAsyncifyImport=original.isAsync||importPattern.test(x)}}},saveRewindArguments(func,passedArguments){return Asyncify.rewindArguments.set(func,Array.from(passedArguments))},restoreRewindArguments(func){return Asyncify.rewindArguments.get(func)},instrumentFunction(original){var wrapper=(...args)=>{Asyncify.exportCallStack.push(original);try{Asyncify.saveRewindArguments(original,args);return original(...args)}finally{if(!ABORT){var top=Asyncify.exportCallStack.pop();Asyncify.maybeStopUnwind()}}};Asyncify.funcWrappers.set(original,wrapper);return wrapper},instrumentWasmExports(exports){var ret={};for(let[x,original]of Object.entries(exports)){if(typeof original=="function"){var wrapper=Asyncify.instrumentFunction(original);ret[x]=wrapper}else{ret[x]=original}}return ret},State:{Normal:0,Unwinding:1,Rewinding:2,Disabled:3},state:0,StackSize:4096,currData:null,handleSleepReturnValue:0,exportCallStack:[],callstackFuncToId:new Map,callStackIdToFunc:new Map,funcWrappers:new Map,callStackId:0,asyncPromiseHandlers:null,sleepCallbacks:[],getCallStackId(func){if(!Asyncify.callstackFuncToId.has(func)){var id=Asyncify.callStackId++;Asyncify.callstackFuncToId.set(func,id);Asyncify.callStackIdToFunc.set(id,func)}return Asyncify.callstackFuncToId.get(func)},maybeStopUnwind(){if(Asyncify.currData&&Asyncify.state===Asyncify.State.Unwinding&&Asyncify.exportCallStack.length===0){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_unwind);if(typeof Fibers!="undefined"){Fibers.trampoline()}}},whenDone(){return new Promise((resolve,reject)=>{Asyncify.asyncPromiseHandlers={resolve,reject}})},allocateData(){var ptr=_malloc(24+Asyncify.StackSize);Asyncify.setDataHeader(ptr,ptr+24,Asyncify.StackSize);Asyncify.setDataRewindFunc(ptr);return ptr},setDataHeader(ptr,stack,stackSize){HEAPU64[ptr>>3]=BigInt(stack);HEAPU64[ptr+8>>3]=BigInt(stack+stackSize)},setDataRewindFunc(ptr){var bottomOfCallStack=Asyncify.exportCallStack[0];var rewindId=Asyncify.getCallStackId(bottomOfCallStack);HEAP32[ptr+16>>2]=rewindId},getDataRewindFunc(ptr){var id=HEAP32[ptr+16>>2];var func=Asyncify.callStackIdToFunc.get(id);return func},doRewind(ptr){var original=Asyncify.getDataRewindFunc(ptr);var func=Asyncify.funcWrappers.get(original);func=func.bind(0,...Asyncify.restoreRewindArguments(original));return callUserCallback(func)},handleSleep(startAsync){if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){var reachedCallback=false;var reachedAfterCallback=false;startAsync((handleSleepReturnValue=0)=>{if(ABORT)return;Asyncify.handleSleepReturnValue=handleSleepReturnValue;reachedCallback=true;if(!reachedAfterCallback){return}Asyncify.state=Asyncify.State.Rewinding;runAndAbortIfError(()=>_asyncify_start_rewind(Asyncify.currData));if(typeof MainLoop!="undefined"&&MainLoop.func){MainLoop.resume()}var asyncWasmReturnValue,isError=false;try{asyncWasmReturnValue=Asyncify.doRewind(Asyncify.currData)}catch(err){asyncWasmReturnValue=err;isError=true}var handled=false;if(!Asyncify.currData){var asyncPromiseHandlers=Asyncify.asyncPromiseHandlers;if(asyncPromiseHandlers){Asyncify.asyncPromiseHandlers=null;(isError?asyncPromiseHandlers.reject:asyncPromiseHandlers.resolve)(asyncWasmReturnValue);handled=true}}if(isError&&!handled){throw asyncWasmReturnValue}});reachedAfterCallback=true;if(!reachedCallback){Asyncify.state=Asyncify.State.Unwinding;Asyncify.currData=Asyncify.allocateData();if(typeof MainLoop!="undefined"&&MainLoop.func){MainLoop.pause()}runAndAbortIfError(()=>_asyncify_start_unwind(Asyncify.currData))}}else if(Asyncify.state===Asyncify.State.Rewinding){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_rewind);_free(Asyncify.currData);Asyncify.currData=null;Asyncify.sleepCallbacks.forEach(callUserCallback)}else{abort(`invalid state: ${Asyncify.state}`)}return Asyncify.handleSleepReturnValue},handleAsync:startAsync=>Asyncify.handleSleep(async wakeUp=>{wakeUp(await startAsync())})};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={pointer:p=>BigInt(p),string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return BigInt(ret)},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return BigInt(ret)}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(Number(ret))}if(returnType==="pointer")return Number(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i0){Module["preInit"].shift()()}}}Module["ENV"]=ENV;Module["ccall"]=ccall;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;Module["FS"]=FS;var _pib_heap_bytes,_pib_eval,_free,_malloc,_htons,_ntohs,_htonl,_pib_force_exit,_emscripten_builtin_memalign,__emscripten_timeout,_setThrew,__emscripten_stack_restore,__emscripten_stack_alloc,_emscripten_stack_get_current,dynCall_vjj,dynCall_jjj,dynCall_ijjjj,dynCall_vjjj,dynCall_ijjj,dynCall_vj,dynCall_jj,dynCall_vjjjj,dynCall_ij,dynCall_jjjj,dynCall_vjjijjj,dynCall_vjjjiijj,dynCall_vjjij,dynCall_vjjjjj,dynCall_vjji,dynCall_vjjjjijiij,dynCall_ijj,dynCall_ijji,dynCall_jji,dynCall_jjji,dynCall_ii,dynCall_ijjjjj,dynCall_ijjjjjjj,dynCall_ijjjjjj,dynCall_vji,dynCall_j,dynCall_v,dynCall_jjjjj,dynCall_vjjiijjjjjjjjj,dynCall_jjjji,dynCall_iij,dynCall_vjij,dynCall_ji,dynCall_jjii,dynCall_vjjjji,dynCall_vjjii,dynCall_vjjji,dynCall_iji,dynCall_jjjiij,dynCall_jiij,dynCall_jjjjji,dynCall_ijjji,dynCall_iijj,dynCall_vjiji,dynCall_i,dynCall_vijj,dynCall_ijjii,dynCall_vi,dynCall_vii,dynCall_jjij,dynCall_vijij,dynCall_jjjjii,dynCall_jjjiiii,dynCall_vjjdi,dynCall_ijiijj,dynCall_vjjjij,dynCall_vjii,dynCall_iijjjj,dynCall_jjjjjjiijj,dynCall_ijjij,dynCall_jjjijj,dynCall_jjjij,dynCall_jijj,dynCall_vjjjjij,dynCall_vjjjjjj,dynCall_jjjjjj,dynCall_ijjiii,dynCall_jjjjijj,dynCall_jii,dynCall_vij,dynCall_ijjjjjji,dynCall_ijjjji,dynCall_ijiij,dynCall_vjijj,dynCall_vjiijijjj,dynCall_jjijj,dynCall_vjijjj,dynCall_iijjj,dynCall_ijij,dynCall_iiji,dynCall_ijdiiii,dynCall_jij,dynCall_ijjjjijj,dynCall_ijjjjji,dynCall_vijijj,dynCall_ijii,dynCall_viiijjj,dynCall_vjdj,dynCall_iii,dynCall_jjjjjjj,dynCall_ijjijj,dynCall_ijjjij,dynCall_ijjiij,dynCall_jjjjij,dynCall_vjjjjii,dynCall_vjjjii,_asyncify_start_unwind,_asyncify_stop_unwind,_asyncify_start_rewind,_asyncify_stop_rewind,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){_pib_heap_bytes=Module["_pib_heap_bytes"]=wasmExports["Mb"];_pib_eval=Module["_pib_eval"]=wasmExports["Nb"];_free=wasmExports["Ob"];_malloc=wasmExports["Pb"];_htons=wasmExports["Qb"];_ntohs=wasmExports["Rb"];_htonl=wasmExports["Sb"];_pib_force_exit=Module["_pib_force_exit"]=wasmExports["Tb"];_emscripten_builtin_memalign=wasmExports["Vb"];__emscripten_timeout=wasmExports["Wb"];_setThrew=wasmExports["Xb"];__emscripten_stack_restore=wasmExports["Yb"];__emscripten_stack_alloc=wasmExports["Zb"];_emscripten_stack_get_current=wasmExports["_b"];dynCall_vjj=dynCalls["vjj"]=wasmExports["$b"];dynCall_jjj=dynCalls["jjj"]=wasmExports["ac"];dynCall_ijjjj=dynCalls["ijjjj"]=wasmExports["bc"];dynCall_vjjj=dynCalls["vjjj"]=wasmExports["cc"];dynCall_ijjj=dynCalls["ijjj"]=wasmExports["dc"];dynCall_vj=dynCalls["vj"]=wasmExports["ec"];dynCall_jj=dynCalls["jj"]=wasmExports["fc"];dynCall_vjjjj=dynCalls["vjjjj"]=wasmExports["gc"];dynCall_ij=dynCalls["ij"]=wasmExports["hc"];dynCall_jjjj=dynCalls["jjjj"]=wasmExports["ic"];dynCall_vjjijjj=dynCalls["vjjijjj"]=wasmExports["jc"];dynCall_vjjjiijj=dynCalls["vjjjiijj"]=wasmExports["kc"];dynCall_vjjij=dynCalls["vjjij"]=wasmExports["lc"];dynCall_vjjjjj=dynCalls["vjjjjj"]=wasmExports["mc"];dynCall_vjji=dynCalls["vjji"]=wasmExports["nc"];dynCall_vjjjjijiij=dynCalls["vjjjjijiij"]=wasmExports["oc"];dynCall_ijj=dynCalls["ijj"]=wasmExports["pc"];dynCall_ijji=dynCalls["ijji"]=wasmExports["qc"];dynCall_jji=dynCalls["jji"]=wasmExports["rc"];dynCall_jjji=dynCalls["jjji"]=wasmExports["sc"];dynCall_ii=dynCalls["ii"]=wasmExports["tc"];dynCall_ijjjjj=dynCalls["ijjjjj"]=wasmExports["uc"];dynCall_ijjjjjjj=dynCalls["ijjjjjjj"]=wasmExports["vc"];dynCall_ijjjjjj=dynCalls["ijjjjjj"]=wasmExports["wc"];dynCall_vji=dynCalls["vji"]=wasmExports["xc"];dynCall_j=dynCalls["j"]=wasmExports["yc"];dynCall_v=dynCalls["v"]=wasmExports["zc"];dynCall_jjjjj=dynCalls["jjjjj"]=wasmExports["Ac"];dynCall_vjjiijjjjjjjjj=dynCalls["vjjiijjjjjjjjj"]=wasmExports["Bc"];dynCall_jjjji=dynCalls["jjjji"]=wasmExports["Cc"];dynCall_iij=dynCalls["iij"]=wasmExports["Dc"];dynCall_vjij=dynCalls["vjij"]=wasmExports["Ec"];dynCall_ji=dynCalls["ji"]=wasmExports["Fc"];dynCall_jjii=dynCalls["jjii"]=wasmExports["Gc"];dynCall_vjjjji=dynCalls["vjjjji"]=wasmExports["Hc"];dynCall_vjjii=dynCalls["vjjii"]=wasmExports["Ic"];dynCall_vjjji=dynCalls["vjjji"]=wasmExports["Jc"];dynCall_iji=dynCalls["iji"]=wasmExports["Kc"];dynCall_jjjiij=dynCalls["jjjiij"]=wasmExports["Lc"];dynCall_jiij=dynCalls["jiij"]=wasmExports["Mc"];dynCall_jjjjji=dynCalls["jjjjji"]=wasmExports["Nc"];dynCall_ijjji=dynCalls["ijjji"]=wasmExports["Oc"];dynCall_iijj=dynCalls["iijj"]=wasmExports["Pc"];dynCall_vjiji=dynCalls["vjiji"]=wasmExports["Qc"];dynCall_i=dynCalls["i"]=wasmExports["Rc"];dynCall_vijj=dynCalls["vijj"]=wasmExports["Sc"];dynCall_ijjii=dynCalls["ijjii"]=wasmExports["Tc"];dynCall_vi=dynCalls["vi"]=wasmExports["Uc"];dynCall_vii=dynCalls["vii"]=wasmExports["Vc"];dynCall_jjij=dynCalls["jjij"]=wasmExports["Wc"];dynCall_vijij=dynCalls["vijij"]=wasmExports["Xc"];dynCall_jjjjii=dynCalls["jjjjii"]=wasmExports["Yc"];dynCall_jjjiiii=dynCalls["jjjiiii"]=wasmExports["Zc"];dynCall_vjjdi=dynCalls["vjjdi"]=wasmExports["_c"];dynCall_ijiijj=dynCalls["ijiijj"]=wasmExports["$c"];dynCall_vjjjij=dynCalls["vjjjij"]=wasmExports["ad"];dynCall_vjii=dynCalls["vjii"]=wasmExports["bd"];dynCall_iijjjj=dynCalls["iijjjj"]=wasmExports["cd"];dynCall_jjjjjjiijj=dynCalls["jjjjjjiijj"]=wasmExports["dd"];dynCall_ijjij=dynCalls["ijjij"]=wasmExports["ed"];dynCall_jjjijj=dynCalls["jjjijj"]=wasmExports["fd"];dynCall_jjjij=dynCalls["jjjij"]=wasmExports["gd"];dynCall_jijj=dynCalls["jijj"]=wasmExports["hd"];dynCall_vjjjjij=dynCalls["vjjjjij"]=wasmExports["id"];dynCall_vjjjjjj=dynCalls["vjjjjjj"]=wasmExports["jd"];dynCall_jjjjjj=dynCalls["jjjjjj"]=wasmExports["kd"];dynCall_ijjiii=dynCalls["ijjiii"]=wasmExports["ld"];dynCall_jjjjijj=dynCalls["jjjjijj"]=wasmExports["md"];dynCall_jii=dynCalls["jii"]=wasmExports["nd"];dynCall_vij=dynCalls["vij"]=wasmExports["od"];dynCall_ijjjjjji=dynCalls["ijjjjjji"]=wasmExports["pd"];dynCall_ijjjji=dynCalls["ijjjji"]=wasmExports["qd"];dynCall_ijiij=dynCalls["ijiij"]=wasmExports["rd"];dynCall_vjijj=dynCalls["vjijj"]=wasmExports["sd"];dynCall_vjiijijjj=dynCalls["vjiijijjj"]=wasmExports["td"];dynCall_jjijj=dynCalls["jjijj"]=wasmExports["ud"];dynCall_vjijjj=dynCalls["vjijjj"]=wasmExports["vd"];dynCall_iijjj=dynCalls["iijjj"]=wasmExports["wd"];dynCall_ijij=dynCalls["ijij"]=wasmExports["xd"];dynCall_iiji=dynCalls["iiji"]=wasmExports["yd"];dynCall_ijdiiii=dynCalls["ijdiiii"]=wasmExports["zd"];dynCall_jij=dynCalls["jij"]=wasmExports["Ad"];dynCall_ijjjjijj=dynCalls["ijjjjijj"]=wasmExports["Bd"];dynCall_ijjjjji=dynCalls["ijjjjji"]=wasmExports["Cd"];dynCall_vijijj=dynCalls["vijijj"]=wasmExports["Dd"];dynCall_ijii=dynCalls["ijii"]=wasmExports["Ed"];dynCall_viiijjj=dynCalls["viiijjj"]=wasmExports["Fd"];dynCall_vjdj=dynCalls["vjdj"]=wasmExports["Gd"];dynCall_iii=dynCalls["iii"]=wasmExports["Hd"];dynCall_jjjjjjj=dynCalls["jjjjjjj"]=wasmExports["Id"];dynCall_ijjijj=dynCalls["ijjijj"]=wasmExports["Jd"];dynCall_ijjjij=dynCalls["ijjjij"]=wasmExports["Kd"];dynCall_ijjiij=dynCalls["ijjiij"]=wasmExports["Ld"];dynCall_jjjjij=dynCalls["jjjjij"]=wasmExports["Md"];dynCall_vjjjjii=dynCalls["vjjjjii"]=wasmExports["Nd"];dynCall_vjjjii=dynCalls["vjjjii"]=wasmExports["Od"];_asyncify_start_unwind=wasmExports["Pd"];_asyncify_stop_unwind=wasmExports["Qd"];_asyncify_start_rewind=wasmExports["Rd"];_asyncify_stop_rewind=wasmExports["Sd"];memory=wasmMemory=wasmExports["Kb"];__indirect_function_table=wasmTable=wasmExports["Ub"]}var wasmImports={m:___assert_fail,Ja:___call_sighandler,ya:___syscall_accept4,xa:___syscall_bind,eb:___syscall_chdir,fa:___syscall_chmod,P:___syscall_connect,cb:___syscall_dup,fb:___syscall_faccessat,bb:___syscall_fchmod,ea:___syscall_fchownat,q:___syscall_fcntl64,ab:___syscall_fdatasync,_a:___syscall_fstat64,Va:___syscall_ftruncate64,Ua:___syscall_getcwd,Ia:___syscall_getdents64,va:___syscall_getpeername,ua:___syscall_getsockname,ta:___syscall_getsockopt,ha:___syscall_ioctl,Gb:___syscall_listen,Ya:___syscall_lstat64,Ra:___syscall_mkdirat,Xa:___syscall_newfstatat,Q:___syscall_openat,La:___syscall_pipe2,ba:___syscall_poll,Ha:___syscall_readlinkat,Z:___syscall_recvfrom,Ga:___syscall_renameat,$:___syscall_rmdir,I:___syscall_sendto,sa:___syscall_socket,Za:___syscall_stat64,Fa:___syscall_statfs64,Ea:___syscall_symlinkat,aa:___syscall_unlinkat,Ba:___syscall_utimensat,gb:__abort_js,wa:__emscripten_lookup_name,Ka:__emscripten_runtime_keepalive_clear,za:__emscripten_throw_longjmp,Oa:__gmtime_js,Pa:__localtime_js,Qa:__mktime_js,Ma:__mmap_js,Na:__munmap_js,_:__setitimer_js,jb:__tzset_js,db:_clock_time_get,da:_emscripten_date_now,vb:_emscripten_force_exit,Da:_emscripten_get_heap_max,K:_emscripten_get_now,Aa:_emscripten_resize_heap,kb:_environ_get,lb:_environ_sizes_get,z:_exit,D:_fd_close,ca:_fd_fdstat_get,ga:_fd_read,Sa:_fd_seek,Wa:_fd_sync,R:_fd_write,sb:_getaddrinfo,Jb:_getcontext,Ca:_getdtablesize,J:_getnameinfo,hb:_getprotobyname,$a:_getprotobynumber,C:invoke_i,u:invoke_ii,X:invoke_iii,y:invoke_iij,Fb:invoke_iijj,t:invoke_ij,E:invoke_iji,tb:invoke_ijii,M:invoke_ijiij,U:invoke_ijiijj,w:invoke_ijij,e:invoke_ijj,Y:invoke_ijji,Eb:invoke_ijjii,na:invoke_ijjiii,xb:invoke_ijjijj,k:invoke_ijjj,H:invoke_ijjji,p:invoke_ijjjj,la:invoke_ijjjjijj,Bb:invoke_ijjjjji,zb:invoke_ijjjjjji,o:invoke_j,ia:invoke_ji,wb:invoke_jij,qa:invoke_jijj,b:invoke_jj,i:invoke_jji,ob:invoke_jjii,h:invoke_jjj,s:invoke_jjji,Cb:invoke_jjjiiii,l:invoke_jjjj,pb:invoke_jjjji,d:invoke_jjjjii,Ab:invoke_jjjjijj,n:invoke_jjjjj,ub:invoke_jjjjji,oa:invoke_jjjjjj,yb:invoke_jjjjjjiijj,c:invoke_v,O:invoke_vi,ra:invoke_vii,T:invoke_vij,S:invoke_vijijj,g:invoke_vijj,a:invoke_vj,x:invoke_vji,B:invoke_vjii,r:invoke_vjij,j:invoke_vjiji,F:invoke_vjijj,f:invoke_vjj,V:invoke_vjjdi,ma:invoke_vjji,A:invoke_vjjii,qb:invoke_vjjiijjjjjjjjj,L:invoke_vjjij,v:invoke_vjjj,ja:invoke_vjjjj,nb:invoke_vjjjji,pa:invoke_vjjjjij,ka:invoke_vjjjjj,N:invoke_vjjjjjj,Ib:_makecontext,mb:_posix_spawnp,ib:_proc_exit,Ta:_strptime,rb:_swapcontext,Hb:_xmlFreeEntity,Db:_xmlNewInputFromIO,W:_xmlXPathValuePop,G:_xmlXPathValuePush};function invoke_j(index){var sp=stackSave();try{return dynCall_j(Number(index))}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_jj(index,a1){var sp=stackSave();try{return dynCall_jj(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vj(index,a1){var sp=stackSave();try{dynCall_vj(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjj(index,a1,a2,a3){var sp=stackSave();try{dynCall_vjjj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjj(index,a1,a2){var sp=stackSave();try{dynCall_vjj(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{dynCall_v(Number(index))}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jji(index,a1,a2){var sp=stackSave();try{return dynCall_jji(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijj(index,a1,a2){var sp=stackSave();try{return dynCall_ijj(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjjj(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjjjj(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjj(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jjjjj(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijjj(index,a1,a2,a3){var sp=stackSave();try{return dynCall_ijjj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ii(index,a1){var sp=stackSave();try{return dynCall_ii(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vji(index,a1,a2){var sp=stackSave();try{dynCall_vji(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjj(index,a1,a2){var sp=stackSave();try{return dynCall_jjj(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vjjij(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjjij(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjiijjjjjjjjj(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13){var sp=stackSave();try{dynCall_vjjiijjjjjjjjj(Number(index),a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjji(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jjjji(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_iij(index,a1,a2){var sp=stackSave();try{return dynCall_iij(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjij(index,a1,a2,a3){var sp=stackSave();try{dynCall_vjij(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ij(index,a1){var sp=stackSave();try{return dynCall_ij(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ji(index,a1){var sp=stackSave();try{return dynCall_ji(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_jjii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jjii(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vjjjji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vjjjji(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjii(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjjii(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_iijj(index,a1,a2,a3){var sp=stackSave();try{return dynCall_iijj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjiji(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjiji(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return dynCall_i(Number(index))}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjji(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jjji(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vijj(index,a1,a2,a3){var sp=stackSave();try{dynCall_vijj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjii(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_ijjii(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijji(index,a1,a2,a3){var sp=stackSave();try{return dynCall_ijji(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return dynCall_iii(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{dynCall_vi(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{dynCall_vii(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_jjjjii(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_jjjiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_jjjiiii(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_jjjj(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jjjj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijjji(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_ijjji(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjjj(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_ijjjj(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_iji(index,a1,a2){var sp=stackSave();try{return dynCall_iji(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjdi(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjjdi(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijiijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_ijiijj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjii(index,a1,a2,a3){var sp=stackSave();try{dynCall_vjii(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjjjji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_ijjjjji(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jijj(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jijj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vjjjjij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_vjjjjij(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjjjjj(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_vjjjjjj(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjjj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_jjjjjj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijjiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_ijjiii(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjijj(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_jjjjijj(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vjji(index,a1,a2,a3){var sp=stackSave();try{dynCall_vjji(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2){var sp=stackSave();try{dynCall_vij(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjjjjji(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_ijjjjjji(Number(index),a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijiij(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_ijiij(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjijj(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjijj(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjjjiijj(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return dynCall_jjjjjjiijj(Number(index),a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_ijij(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_ijjijj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jij(index,a1,a2){var sp=stackSave();try{return dynCall_jij(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijjjjijj(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_ijjjjijj(Number(index),a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vijijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijijj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjjjj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vjjjjj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_jjjjji(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_ijii(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function applySignatureConversions(wasmExports){wasmExports=Object.assign({},wasmExports);var makeWrapper__p=f=>a0=>f(BigInt(a0));var makeWrapper_pp=f=>a0=>Number(f(BigInt(a0)));var makeWrapper_ppp=f=>(a0,a1)=>Number(f(BigInt(a0),BigInt(a1)));var makeWrapper_p=f=>()=>Number(f());var makeWrapper__p__=f=>(a0,a1,a2)=>f(BigInt(a0),a1,a2);var makeWrapper__p____=f=>(a0,a1,a2,a3,a4)=>f(BigInt(a0),a1,a2,a3,a4);var makeWrapper__p___=f=>(a0,a1,a2,a3)=>f(BigInt(a0),a1,a2,a3);var makeWrapper__p_=f=>(a0,a1)=>f(BigInt(a0),a1);var makeWrapper__p______=f=>(a0,a1,a2,a3,a4,a5,a6)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6);var makeWrapper__p_______=f=>(a0,a1,a2,a3,a4,a5,a6,a7)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6,a7);var makeWrapper__p_____=f=>(a0,a1,a2,a3,a4,a5)=>f(BigInt(a0),a1,a2,a3,a4,a5);var makeWrapper__p_________=f=>(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6,a7,a8,a9);var makeWrapper__p_____________=f=>(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13);var makeWrapper__p________=f=>(a0,a1,a2,a3,a4,a5,a6,a7,a8)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6,a7,a8);wasmExports["Ob"]=makeWrapper__p(wasmExports["Ob"]);wasmExports["Pb"]=makeWrapper_pp(wasmExports["Pb"]);wasmExports["Vb"]=makeWrapper_ppp(wasmExports["Vb"]);wasmExports["Xb"]=makeWrapper__p(wasmExports["Xb"]);wasmExports["Yb"]=makeWrapper__p(wasmExports["Yb"]);wasmExports["Zb"]=makeWrapper_pp(wasmExports["Zb"]);wasmExports["_b"]=makeWrapper_p(wasmExports["_b"]);wasmExports["$b"]=makeWrapper__p__(wasmExports["$b"]);wasmExports["ac"]=makeWrapper__p__(wasmExports["ac"]);wasmExports["bc"]=makeWrapper__p____(wasmExports["bc"]);wasmExports["cc"]=makeWrapper__p___(wasmExports["cc"]);wasmExports["dc"]=makeWrapper__p___(wasmExports["dc"]);wasmExports["ec"]=makeWrapper__p_(wasmExports["ec"]);wasmExports["fc"]=makeWrapper__p_(wasmExports["fc"]);wasmExports["gc"]=makeWrapper__p____(wasmExports["gc"]);wasmExports["hc"]=makeWrapper__p_(wasmExports["hc"]);wasmExports["ic"]=makeWrapper__p___(wasmExports["ic"]);wasmExports["jc"]=makeWrapper__p______(wasmExports["jc"]);wasmExports["kc"]=makeWrapper__p_______(wasmExports["kc"]);wasmExports["lc"]=makeWrapper__p____(wasmExports["lc"]);wasmExports["mc"]=makeWrapper__p_____(wasmExports["mc"]);wasmExports["nc"]=makeWrapper__p___(wasmExports["nc"]);wasmExports["oc"]=makeWrapper__p_________(wasmExports["oc"]);wasmExports["pc"]=makeWrapper__p__(wasmExports["pc"]);wasmExports["qc"]=makeWrapper__p___(wasmExports["qc"]);wasmExports["rc"]=makeWrapper__p__(wasmExports["rc"]);wasmExports["sc"]=makeWrapper__p___(wasmExports["sc"]);wasmExports["tc"]=makeWrapper__p_(wasmExports["tc"]);wasmExports["uc"]=makeWrapper__p_____(wasmExports["uc"]);wasmExports["vc"]=makeWrapper__p_______(wasmExports["vc"]);wasmExports["wc"]=makeWrapper__p______(wasmExports["wc"]);wasmExports["xc"]=makeWrapper__p__(wasmExports["xc"]);wasmExports["yc"]=makeWrapper__p(wasmExports["yc"]);wasmExports["zc"]=makeWrapper__p(wasmExports["zc"]);wasmExports["Ac"]=makeWrapper__p____(wasmExports["Ac"]);wasmExports["Bc"]=makeWrapper__p_____________(wasmExports["Bc"]);wasmExports["Cc"]=makeWrapper__p____(wasmExports["Cc"]);wasmExports["Dc"]=makeWrapper__p__(wasmExports["Dc"]);wasmExports["Ec"]=makeWrapper__p___(wasmExports["Ec"]);wasmExports["Fc"]=makeWrapper__p_(wasmExports["Fc"]);wasmExports["Gc"]=makeWrapper__p___(wasmExports["Gc"]);wasmExports["Hc"]=makeWrapper__p_____(wasmExports["Hc"]);wasmExports["Ic"]=makeWrapper__p____(wasmExports["Ic"]);wasmExports["Jc"]=makeWrapper__p____(wasmExports["Jc"]);wasmExports["Kc"]=makeWrapper__p__(wasmExports["Kc"]);wasmExports["Lc"]=makeWrapper__p_____(wasmExports["Lc"]);wasmExports["Mc"]=makeWrapper__p___(wasmExports["Mc"]);wasmExports["Nc"]=makeWrapper__p_____(wasmExports["Nc"]);wasmExports["Oc"]=makeWrapper__p____(wasmExports["Oc"]);wasmExports["Pc"]=makeWrapper__p___(wasmExports["Pc"]);wasmExports["Qc"]=makeWrapper__p____(wasmExports["Qc"]);wasmExports["Rc"]=makeWrapper__p(wasmExports["Rc"]);wasmExports["Sc"]=makeWrapper__p___(wasmExports["Sc"]);wasmExports["Tc"]=makeWrapper__p____(wasmExports["Tc"]);wasmExports["Uc"]=makeWrapper__p_(wasmExports["Uc"]);wasmExports["Vc"]=makeWrapper__p__(wasmExports["Vc"]);wasmExports["Wc"]=makeWrapper__p___(wasmExports["Wc"]);wasmExports["Xc"]=makeWrapper__p____(wasmExports["Xc"]);wasmExports["Yc"]=makeWrapper__p_____(wasmExports["Yc"]);wasmExports["Zc"]=makeWrapper__p______(wasmExports["Zc"]);wasmExports["_c"]=makeWrapper__p____(wasmExports["_c"]);wasmExports["$c"]=makeWrapper__p_____(wasmExports["$c"]);wasmExports["ad"]=makeWrapper__p_____(wasmExports["ad"]);wasmExports["bd"]=makeWrapper__p___(wasmExports["bd"]);wasmExports["cd"]=makeWrapper__p_____(wasmExports["cd"]);wasmExports["dd"]=makeWrapper__p_________(wasmExports["dd"]);wasmExports["ed"]=makeWrapper__p____(wasmExports["ed"]);wasmExports["fd"]=makeWrapper__p_____(wasmExports["fd"]);wasmExports["gd"]=makeWrapper__p____(wasmExports["gd"]);wasmExports["hd"]=makeWrapper__p___(wasmExports["hd"]);wasmExports["id"]=makeWrapper__p______(wasmExports["id"]);wasmExports["jd"]=makeWrapper__p______(wasmExports["jd"]);wasmExports["kd"]=makeWrapper__p_____(wasmExports["kd"]);wasmExports["ld"]=makeWrapper__p_____(wasmExports["ld"]);wasmExports["md"]=makeWrapper__p______(wasmExports["md"]);wasmExports["nd"]=makeWrapper__p__(wasmExports["nd"]);wasmExports["od"]=makeWrapper__p__(wasmExports["od"]);wasmExports["pd"]=makeWrapper__p_______(wasmExports["pd"]);wasmExports["qd"]=makeWrapper__p_____(wasmExports["qd"]);wasmExports["rd"]=makeWrapper__p____(wasmExports["rd"]);wasmExports["sd"]=makeWrapper__p____(wasmExports["sd"]);wasmExports["td"]=makeWrapper__p________(wasmExports["td"]);wasmExports["ud"]=makeWrapper__p____(wasmExports["ud"]);wasmExports["vd"]=makeWrapper__p_____(wasmExports["vd"]);wasmExports["wd"]=makeWrapper__p____(wasmExports["wd"]);wasmExports["xd"]=makeWrapper__p___(wasmExports["xd"]);wasmExports["yd"]=makeWrapper__p___(wasmExports["yd"]);wasmExports["zd"]=makeWrapper__p______(wasmExports["zd"]);wasmExports["Ad"]=makeWrapper__p__(wasmExports["Ad"]);wasmExports["Bd"]=makeWrapper__p_______(wasmExports["Bd"]);wasmExports["Cd"]=makeWrapper__p______(wasmExports["Cd"]);wasmExports["Dd"]=makeWrapper__p_____(wasmExports["Dd"]);wasmExports["Ed"]=makeWrapper__p___(wasmExports["Ed"]);wasmExports["Fd"]=makeWrapper__p______(wasmExports["Fd"]);wasmExports["Gd"]=makeWrapper__p___(wasmExports["Gd"]);wasmExports["Hd"]=makeWrapper__p__(wasmExports["Hd"]);wasmExports["Id"]=makeWrapper__p______(wasmExports["Id"]);wasmExports["Jd"]=makeWrapper__p_____(wasmExports["Jd"]);wasmExports["Kd"]=makeWrapper__p_____(wasmExports["Kd"]);wasmExports["Ld"]=makeWrapper__p_____(wasmExports["Ld"]);wasmExports["Md"]=makeWrapper__p_____(wasmExports["Md"]);wasmExports["Nd"]=makeWrapper__p______(wasmExports["Nd"]);wasmExports["Od"]=makeWrapper__p_____(wasmExports["Od"]);wasmExports["Pd"]=makeWrapper__p(wasmExports["Pd"]);wasmExports["Rd"]=makeWrapper__p(wasmExports["Rd"]);return wasmExports}function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} -;return moduleRtn}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=PHP;module.exports.default=PHP}else if(typeof define==="function"&&define["amd"])define([],()=>PHP); +var PHP=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var Module=moduleArg;var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var programArgs=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;class EmscriptenEH{}class EmscriptenSjLj extends EmscriptenEH{}var runtimeInitialized=false;function getMemoryBuffer(){return wasmMemory.buffer}function updateMemoryViews(){if(HEAP8?.buffer?.resizable)return;var b=getMemoryBuffer();HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){var preRun=Module["preRun"];if(preRun){if(typeof preRun=="function")preRun=[preRun];onPreRuns.push(...preRun)}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;SOCKFS.root=FS.mount(SOCKFS,{},null);if(!Module["noFSInit"]&&!FS.initialized)FS.init();TTY.init();PIPEFS.root=FS.mount(PIPEFS,{},null);wasmExports["Lb"]();FS.ignorePermissions=false}function postRun(){var postRun=Module["postRun"];if(postRun){if(typeof postRun=="function")postRun=[postRun];onPostRuns.push(...postRun)}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what=`Aborted(${what})`;err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("php.wasm")}function getBinarySync(file){if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance){wasmExports=instance.exports;wasmExports=Asyncify.instrumentWasmExports(wasmExports);wasmExports=applySignatureConversions(wasmExports);assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();var instantiateWasm=Module["instantiateWasm"];if(instantiateWasm){return new Promise(resolve=>{instantiateWasm(info,inst=>resolve(receiveInstance(inst)))})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var HEAP8;var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var onPreRuns=[];var dynCalls={};var noExitRuntime=true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>numINT53_MAX?NaN:Number(num);var UTF8Decoder=new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var HEAPU8;var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>{if(!ptr)return"";var end=findStringEnd(HEAPU8,ptr,maxBytesToRead,ignoreNul);return UTF8Decoder.decode(HEAPU8.subarray(ptr,end))};function ___assert_fail(condition,filename,line,func){condition=bigintToI53Checked(condition);filename=bigintToI53Checked(filename);func=bigintToI53Checked(func);return abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}var ___call_sighandler=function(fp,sig){fp=bigintToI53Checked(fp);return(a1=>dynCall_vi(fp,a1))(sig)};var initRandomFill=()=>view=>(crypto.getRandomValues(view),0);var randomFill=view=>(randomFill=initRandomFill())(view);var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.slice(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.slice(0,-1)}return root+dir},basename:path=>path&&path.match(/([^\/]+|\/)\/*$/)[1],join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).slice(1);to=PATH_FS.resolve(to).slice(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);return UTF8Decoder.decode(heapOrArray.buffer?heapOrArray.subarray(idx,endPtr):new Uint8Array(heapOrArray.slice(idx,endPtr)))};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var intArrayFromString=(stringy,dontAddNull,length)=>{var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array};var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(globalThis.window?.prompt){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output?.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(ptr,size)=>HEAPU8.fill(0,ptr,ptr+size);var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16895,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=MEMFS.emptyFileContents??=new Uint8Array(0)}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.atime=node.mtime=node.ctime=Date.now();if(parent){parent.contents[name]=node;parent.atime=parent.mtime=parent.ctime=node.atime}return node},getFileDataAsTypedArray(node){return node.contents.subarray(0,node.usedBytes)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents.length;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity)newCapacity=Math.max(newCapacity,256);var oldContents=MEMFS.getFileDataAsTypedArray(node);node.contents=new Uint8Array(newCapacity);node.contents.set(oldContents)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;var oldContents=node.contents;node.contents=new Uint8Array(newSize);node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)));node.usedBytes=newSize},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.atime);attr.mtime=new Date(node.mtime);attr.ctime=new Date(node.ctime);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){for(const key of["mode","atime","mtime","ctime"]){if(attr[key]!=null){node[key]=attr[key]}}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){if(!MEMFS.doesNotExistError){MEMFS.doesNotExistError=new FS.ErrnoError(44);MEMFS.doesNotExistError.stack=""}throw MEMFS.doesNotExistError},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){if(FS.isDir(old_node.mode)){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}FS.hashRemoveNode(new_node)}delete old_node.parent.contents[old_node.name];new_dir.contents[new_name]=old_node;old_node.name=new_name;new_dir.ctime=new_dir.mtime=old_node.parent.ctime=old_node.parent.mtime=Date.now()},unlink(parent,name){delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},readdir(node){return[".","..",...Object.keys(node.contents)]},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);buffer.set(contents.subarray(position,position+size),offset);return size},write(stream,buffer,offset,length,position,canOwn){if(buffer.buffer===HEAP8.buffer){canOwn=false}if(!length)return 0;var node=stream.node;node.mtime=node.ctime=Date.now();if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length}else if(!node.usedBytes&&!position){node.contents=buffer.slice(offset,offset+length);node.usedBytes=length}else{MEMFS.expandFileStorage(node,position+length);node.contents.set(buffer.subarray(offset,offset+length),position);node.usedBytes=Math.max(node.usedBytes,position+length)}return length},llseek(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(28)}return position},mmap(stream,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&contents.buffer===HEAP8.buffer){allocated=false;ptr=contents.byteOffset}else{allocated=true;ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}if(contents){if(position>0||position+length{if(typeof str!="string")return str;var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_fileDataToTypedArray=data=>{if(typeof data=="string"){data=intArrayFromString(data,true)}if(!data.subarray){data=new Uint8Array(data)}return data};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var asyncLoad=async url=>{var arrayBuffer=await readAsync(url);return new Uint8Array(arrayBuffer)};var FS_createDataFile=(...args)=>FS.createDataFile(...args);var getUniqueRunDependency=id=>id;var dependenciesPromise=null;var resolveRunDependencies=async()=>dependenciesPromise;var runDependencies=0;var dependenciesPromiseResolve=null;var removeRunDependency=id=>{runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(!runDependencies){dependenciesPromiseResolve()}};var addRunDependency=id=>{if(!runDependencies){dependenciesPromise=new Promise(resolve=>dependenciesPromiseResolve=resolve)}runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)};var preloadPlugins=[];var FS_handledByPreloadPlugin=async(byteArray,fullname)=>{if(typeof Browser!="undefined")Browser.init();for(var plugin of preloadPlugins){if(plugin["canHandle"](fullname)){return plugin["handle"](byteArray,fullname)}}return byteArray};var FS_preloadFile=async(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);addRunDependency(dep);try{var byteArray=url;if(typeof url=="string"){byteArray=await asyncLoad(url)}byteArray=await FS_handledByPreloadPlugin(byteArray,fullname);preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}}finally{removeRunDependency(dep)}};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{FS_preloadFile(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish).then(onload).catch(onerror)};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,filesystems:null,syncFSRequests:0,ErrnoError:class{name="ErrnoError";constructor(errno){this.errno=errno}},FSStream:class{shared={};get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{node_ops={};stream_ops={};readMode=292|73;writeMode=146;mounted=null;constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.rdev=rdev;this.atime=this.mtime=this.ctime=Date.now()}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}addListener(cb,exclusive=false){var entry={cb,exclusive};var listeners=this.listeners??=new Set;listeners.add(entry);return{listeners,entry}}notifyListeners(flags){if(!this.listeners)return;var excl;for(var entry of this.listeners){if(entry.exclusive)(excl||=[]).push(entry);else entry.cb(flags)}if(excl){var i=(this.exclTurn||0)%excl.length;this.exclTurn=i+1;excl[i].cb(flags)}}},lookupPath(path,opts={}){if(!path){throw new FS.ErrnoError(44)}opts.follow_mount??=true;if(!PATH.isAbs(path)){path=FS.cwd()+"/"+path}linkloop:for(var nlinks=0;nlinks<40;nlinks++){var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}if(perms.includes("w")&&!(node.mode&146)){return 2}if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){if(!FS.isDir(dir.mode)){return 54}try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else if(FS.isDir(node.mode)){return 31}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}var mode=FS.flagsToPermissionString(flags);if(FS.isDir(node.mode)){if(mode!=="r"||flags&(512|64)){return 31}}return FS.nodePermissions(node,mode)},checkOpExists(op,err){if(!op){throw new FS.ErrnoError(err)}return op},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},doSetAttr(stream,node,attr){var setattr=stream?.stream_ops.setattr;var arg=setattr?stream:node;setattr??=node.node_ops.setattr;FS.checkOpExists(setattr,63);try{setattr(arg,attr)}catch(e){if(e instanceof RangeError){throw new FS.ErrnoError(22)}throw e}},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}for(var mount of mounts){if(mount.type.syncfs){mount.type.syncfs(mount,populate,done)}else{done(null)}}},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);for(var[hash,current]of Object.entries(FS.nameTable)){while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}}node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name){throw new FS.ErrnoError(28)}if(name==="."||name===".."){throw new FS.ErrnoError(20)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},statfs(path){return FS.statfsNode(FS.lookupPath(path,{follow:true}).node)},statfsStream(stream){return FS.statfsNode(stream.node)},statfsNode(node){var rtn={bsize:4096,frsize:4096,blocks:1e6,bfree:5e5,bavail:5e5,files:FS.nextInode,ffree:FS.nextInode-1,fsid:42,flags:2,namelen:255};if(node.node_ops.statfs){Object.assign(rtn,node.node_ops.statfs(node.mount.opts.root))}return rtn},create(path,mode=438){mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode=511){mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var dir of dirs){if(!dir)continue;if(d||PATH.isAbs(path))d+="/";d+=dir;try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},link(oldpath,newpath,flags){var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.link){throw new FS.ErrnoError(34)}return parent.node_ops.link(parent,newname,oldpath,flags)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name);old_node.parent=new_dir}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var readdir=FS.checkOpExists(node.node_ops.readdir,54);return readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return link.node_ops.readlink(link)},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;var getattr=FS.checkOpExists(node.node_ops.getattr,63);return getattr(node)},fstat(fd){var stream=FS.getStreamChecked(fd);var node=stream.node;var getattr=stream.stream_ops.getattr;var arg=getattr?stream:node;getattr??=node.node_ops.getattr;FS.checkOpExists(getattr,63);return getattr(arg)},lstat(path){return FS.stat(path,true)},doChmod(stream,node,mode,dontFollow){FS.doSetAttr(stream,node,{mode:mode&4095|node.mode&~4095,ctime:Date.now(),dontFollow})},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChmod(null,node,mode,dontFollow)},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.doChmod(stream,stream.node,mode,false)},doChown(stream,node,dontFollow){FS.doSetAttr(stream,node,{timestamp:Date.now(),dontFollow})},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChown(null,node,dontFollow)},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.doChown(stream,stream.node,false)},doTruncate(stream,node,len){if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}FS.doSetAttr(stream,node,{size:len,timestamp:Date.now()})},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}FS.doTruncate(null,node,len)},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if(len<0||(stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.doTruncate(stream,stream.node,len)},utime(path,atime,mtime,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});FS.doSetAttr(null,lookup.node,{atime,mtime,dontFollow})},open(path,flags,mode=438){if(path===""){throw new FS.ErrnoError(44)}flags=FS_modeStringToFlags(flags);if(flags&64){mode=mode&4095|32768}else{mode=0}var node;var isDirPath;if(typeof path=="object"){node=path}else{isDirPath=path.endsWith("/");var lookup=FS.lookupPath(path,{follow:!(flags&131072),noent_okay:true});node=lookup.node;path=lookup.path}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else if(isDirPath){throw new FS.ErrnoError(31)}else{node=FS.mknod(path,mode|511,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node,path:FS.getPath(node),flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(created){FS.chmod(node,mode&511)}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;stream.node?.notifyListeners(32);try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},mmap(stream,length,position,prot,flags){if(prot&2&&!(flags&2)&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags??0;opts.encoding=opts.encoding??"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){abort(`Invalid encoding type "${opts.encoding}"`)}var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){buf=UTF8ArrayToString(buf)}FS.close(stream);return buf},writeFile(path,data,opts={}){opts.flags=opts.flags??577;var stream=FS.open(path,opts.flags,opts.mode);data=FS_fileDataToTypedArray(data);FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn);FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length,llseek:()=>0});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(!randomLeft){randomFill(randomBuffer);randomLeft=randomBuffer.byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16895,73);node.stream_ops={llseek:MEMFS.stream_ops.llseek};node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path},id:fd+1};ret.parent=ret;return ret},readdir(){return Array.from(FS.streams.entries()).filter(([k,v])=>v).map(([k,v])=>k.toString())}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;for(var stream of FS.streams){if(stream){FS.close(stream)}}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){if(e.errno!=20)throw e}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){data=FS_fileDataToTypedArray(data);FS.chmod(node,mode|146);var stream=FS.open(node,577);FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}},createDevice(parent,name,input,output){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);FS.createDevice.major??=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open(stream){stream.seekable=false},close(stream){if(output?.buffer?.length){output(10)}},read(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort(`Couldn't load ${url}. Status: ${xhr.status}`);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)abort(`invalid range (${from}, ${to}) or no bytes requested!`);if(to>datalength-1)abort(`only ${datalength} bytes available! programmer error!`);var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range",`bytes=${from}-${to}`);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort(`Couldn't load ${url}. Status: ${xhr.status}`);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText??"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")abort("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(globalThis.XMLHttpRequest){if(!ENVIRONMENT_IS_WORKER)abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};for(const[key,fn]of Object.entries(node.stream_ops)){stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}}function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var HEAP32;var SOCKFS={websocketArgs:{},callbacks:{},on(event,callback){SOCKFS.callbacks[event]=callback},emit(event,param){SOCKFS.callbacks[event]?.(param);var fd=event==="error"?param[0]:param;var flags={message:64|1,open:4,connection:64|1,close:1|16,error:8}[event];if(flags)FS.getStream(fd)?.node.notifyListeners(flags)},mount(mount){SOCKFS.websocketArgs=Module["websocket"]||{};(Module["websocket"]??={})["on"]=SOCKFS.on;return FS.createNode(null,"/",16895,0)},createSocket(family,type,protocol){if(family!=2){throw new FS.ErrnoError(5)}type&=~526336;if(type!=1&&type!=2){throw new FS.ErrnoError(28)}var streaming=type==1;if(streaming&&protocol&&protocol!=6){throw new FS.ErrnoError(66)}var sock={family,type,protocol,server:null,error:null,peers:{},pending:[],recv_queue:[],sock_ops:SOCKFS.websocket_sock_ops};var name=SOCKFS.nextname();var node=FS.createNode(SOCKFS.root,name,49152,0);node.sock=sock;var stream=FS.createStream({path:name,node,flags:2,seekable:false,stream_ops:SOCKFS.stream_ops});sock.stream=stream;return sock},getSocket(fd){var stream=FS.getStream(fd);if(!stream||!FS.isSocket(stream.node.mode)){return null}return stream.node.sock},stream_ops:{getattr(stream){var node=stream.node;return{dev:1,ino:node.id,mode:49152|511,nlink:1,uid:0,gid:0,rdev:0,size:0,atime:new Date(0),mtime:new Date(0),ctime:new Date(0),blksize:4096,blocks:0}},poll(stream){var sock=stream.node.sock;return sock.sock_ops.poll(sock)},ioctl(stream,request,varargs){var sock=stream.node.sock;return sock.sock_ops.ioctl(sock,request,varargs)},read(stream,buffer,offset,length,position){var sock=stream.node.sock;var msg=sock.sock_ops.recvmsg(sock,length);if(!msg){return 0}buffer.set(msg.buffer,offset);return msg.buffer.length},write(stream,buffer,offset,length,position){var sock=stream.node.sock;return sock.sock_ops.sendmsg(sock,buffer,offset,length)},close(stream){var sock=stream.node.sock;sock.sock_ops.close(sock)}},nextname(){if(!SOCKFS.nextname.current){SOCKFS.nextname.current=0}return`socket[${SOCKFS.nextname.current++}]`},websocket_sock_ops:{createPeer(sock,addr,port){var ws;if(typeof addr=="object"){ws=addr;addr=null;port=null}if(ws){if(ws._socket){addr=ws._socket.remoteAddress;port=ws._socket.remotePort}else{var result=/ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);if(!result){throw new Error("WebSocket URL must be in the format ws(s)://address:port")}addr=result[1];port=parseInt(result[2],10)}}else{try{var url="ws://".replace("#","//");var subProtocols="binary";var opts=undefined;if(SOCKFS.websocketArgs["url"]){url=SOCKFS.websocketArgs["url"]}if(SOCKFS.websocketArgs["subprotocol"]){subProtocols=SOCKFS.websocketArgs["subprotocol"]}else if(SOCKFS.websocketArgs["subprotocol"]===null){subProtocols="null"}if(url==="ws://"||url==="wss://"){var parts=addr.split("/");url=url+parts[0]+":"+port+"/"+parts.slice(1).join("/")}if(subProtocols!=="null"){subProtocols=subProtocols.replace(/^ +| +$/g,"").split(/ *, */);opts=subProtocols}var WebSocketConstructor;{WebSocketConstructor=WebSocket}ws=new WebSocketConstructor(url,opts);ws.binaryType="arraybuffer"}catch(e){throw new FS.ErrnoError(23)}}var peer={addr,port,socket:ws,msg_send_queue:[]};SOCKFS.websocket_sock_ops.addPeer(sock,peer);SOCKFS.websocket_sock_ops.handlePeerEvents(sock,peer);if(sock.type===2&&typeof sock.sport!="undefined"){peer.msg_send_queue.push(new Uint8Array([255,255,255,255,"p".charCodeAt(0),"o".charCodeAt(0),"r".charCodeAt(0),"t".charCodeAt(0),(sock.sport&65280)>>8,sock.sport&255]))}return peer},getPeer(sock,addr,port){return sock.peers[addr+":"+port]},addPeer(sock,peer){sock.peers[peer.addr+":"+peer.port]=peer},removePeer(sock,peer){delete sock.peers[peer.addr+":"+peer.port]},handlePeerEvents(sock,peer){var first=true;function handleOpen(){sock.connecting=false;SOCKFS.emit("open",sock.stream.fd);try{var queued=peer.msg_send_queue.shift();while(queued){peer.socket.send(queued);queued=peer.msg_send_queue.shift()}}catch(e){peer.socket.close()}}function handleMessage(data){if(typeof data=="string"){var encoder=new TextEncoder;data=encoder.encode(data)}else{if(data.byteLength==0){return}data=new Uint8Array(data)}var wasfirst=first;first=false;if(wasfirst&&data.length===10&&data[0]===255&&data[1]===255&&data[2]===255&&data[3]===255&&data[4]==="p".charCodeAt(0)&&data[5]==="o".charCodeAt(0)&&data[6]==="r".charCodeAt(0)&&data[7]==="t".charCodeAt(0)){var newport=data[8]<<8|data[9];SOCKFS.websocket_sock_ops.removePeer(sock,peer);peer.port=newport;SOCKFS.websocket_sock_ops.addPeer(sock,peer);return}sock.recv_queue.push({addr:peer.addr,port:peer.port,data});SOCKFS.emit("message",sock.stream.fd)}peer.socket.onopen=handleOpen;peer.socket.onclose=()=>SOCKFS.emit("close",sock.stream.fd);peer.socket.onmessage=event=>handleMessage(event.data);peer.socket.onerror=error=>{sock.error=14;SOCKFS.emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}},poll(sock){if(sock.type===1&&sock.server){return sock.pending.length?64|1:0}var mask=0;var dest=sock.type===1?SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport):null;if(sock.recv_queue.length||!dest||dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=64|1}if(!dest||dest&&dest.socket.readyState===dest.socket.OPEN){mask|=4}if(dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){if(sock.connecting){mask|=4}else{mask|=16|8192}}return mask},ioctl(sock,request,arg){switch(request){case 21531:var bytes=0;if(sock.recv_queue.length){bytes=sock.recv_queue[0].data.length}HEAP32[arg>>2]=bytes;return 0;case 21537:var on=HEAP32[arg>>2];if(on){sock.stream.flags|=2048}else{sock.stream.flags&=~2048}return 0;default:return 28}},close(sock){if(sock.server){try{sock.server.close()}catch(e){}sock.server=null}for(var peer of Object.values(sock.peers)){try{peer.socket.close()}catch(e){}SOCKFS.websocket_sock_ops.removePeer(sock,peer)}return 0},bind(sock,addr,port){if(typeof sock.saddr!="undefined"||typeof sock.sport!="undefined"){throw new FS.ErrnoError(28)}sock.saddr=addr;sock.sport=port;if(sock.type===2){if(sock.server){sock.server.close();sock.server=null}try{sock.sock_ops.listen(sock,0)}catch(e){if(!(e.name==="ErrnoError"))throw e;if(e.errno!==138)throw e}}},connect(sock,addr,port){if(sock.server){throw new FS.ErrnoError(138)}if(typeof sock.daddr!="undefined"&&typeof sock.dport!="undefined"){var dest=SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport);if(dest){if(dest.socket.readyState===dest.socket.CONNECTING){throw new FS.ErrnoError(7)}else{throw new FS.ErrnoError(30)}}}var peer=SOCKFS.websocket_sock_ops.createPeer(sock,addr,port);sock.daddr=peer.addr;sock.dport=peer.port;sock.connecting=true},listen(sock,backlog){if(!ENVIRONMENT_IS_NODE){throw new FS.ErrnoError(138)}},accept(listensock){if(!listensock.server||!listensock.pending.length){throw new FS.ErrnoError(28)}var newsock=listensock.pending.shift();newsock.stream.flags=listensock.stream.flags;return newsock},getname(sock,peer){var addr,port;if(peer){if(sock.daddr===undefined||sock.dport===undefined){throw new FS.ErrnoError(53)}addr=sock.daddr;port=sock.dport}else{addr=sock.saddr||0;port=sock.sport||0}return{addr,port}},sendmsg(sock,buffer,offset,length,addr,port){if(sock.type===2){if(addr===undefined||port===undefined){addr=sock.daddr;port=sock.dport}if(addr===undefined||port===undefined){throw new FS.ErrnoError(17)}}else{addr=sock.daddr;port=sock.dport}var dest=SOCKFS.websocket_sock_ops.getPeer(sock,addr,port);if(sock.type===1){if(!dest||dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){throw new FS.ErrnoError(53)}}if(ArrayBuffer.isView(buffer)){offset+=buffer.byteOffset;buffer=buffer.buffer}var data=buffer.slice(offset,offset+length);if(!dest||dest.socket.readyState!==dest.socket.OPEN){if(sock.type===2){if(!dest||dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){dest=SOCKFS.websocket_sock_ops.createPeer(sock,addr,port)}}dest.msg_send_queue.push(data);return length}try{dest.socket.send(data);return length}catch(e){throw new FS.ErrnoError(28)}},recvmsg(sock,length,flags){if(sock.type===1&&sock.server){throw new FS.ErrnoError(53)}var peek=flags&2;var queued=sock.recv_queue[0];if(!queued){if(sock.type===1){var dest=SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport);if(!dest){throw new FS.ErrnoError(53)}if(dest.socket.readyState===dest.socket.CLOSING||dest.socket.readyState===dest.socket.CLOSED){return null}throw new FS.ErrnoError(6)}throw new FS.ErrnoError(6)}var queuedLength=queued.data.byteLength||queued.data.length;var queuedOffset=queued.data.byteOffset||0;var queuedBuffer=queued.data.buffer||queued.data;var bytesRead=Math.min(length,queuedLength);var res={buffer:new Uint8Array(queuedBuffer,queuedOffset,bytesRead),addr:queued.addr,port:queued.port};if(peek)return res;sock.recv_queue.shift();if(sock.type===1&&bytesRead{var socket=SOCKFS.getSocket(fd);if(!socket)throw new FS.ErrnoError(8);return socket};var inetPton4=str=>{var b=str.split(".");for(var i=0;i<4;i++){var tmp=Number(b[i]);if(isNaN(tmp))return null;b[i]=tmp}return(b[0]|b[1]<<8|b[2]<<16|b[3]<<24)>>>0};var inetPton6=str=>{var words;var w,offset,z;var valid6regx=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;var parts=[];if(!valid6regx.test(str)){return null}if(str==="::"){return[0,0,0,0,0,0,0,0]}if(str.startsWith("::")){str=str.replace("::","Z:")}else{str=str.replace("::",":Z:")}if(str.indexOf(".")>0){str=str.replace(new RegExp("[.]","g"),":");words=str.split(":");words[words.length-4]=Number(words[words.length-4])+Number(words[words.length-3])*256;words[words.length-3]=Number(words[words.length-2])+Number(words[words.length-1])*256;words=words.slice(0,words.length-2)}else{words=str.split(":")}offset=0;z=0;for(w=0;w{switch(family){case 2:addr=inetPton4(DNS.lookup_name(addr));zeroMemory(sa,16);if(addrlen){HEAP32[addrlen>>2]=16}HEAP16[sa>>1]=family;HEAP32[sa+4>>2]=addr;HEAP16[sa+2>>1]=_htons(port);break;case 10:addr=inetPton6(DNS.lookup_name(addr));zeroMemory(sa,28);if(addrlen){HEAP32[addrlen>>2]=28}HEAP32[sa>>2]=family;HEAP32[sa+8>>2]=addr[0];HEAP32[sa+12>>2]=addr[1];HEAP32[sa+16>>2]=addr[2];HEAP32[sa+20>>2]=addr[3];HEAP16[sa+2>>1]=_htons(port);break;default:return 5}return 0};function ___syscall_accept4(fd,addr,len,flags,u1,u2){addr=bigintToI53Checked(addr);len=bigintToI53Checked(len);try{var sock=getSocketFromFD(fd);var newsock=sock.sock_ops.accept(sock);if(addr){var errno=writeSockaddr(addr,newsock.family,newsock.daddr,newsock.dport,len)}return newsock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var inetNtop4=addr=>(addr&255)+"."+(addr>>8&255)+"."+(addr>>16&255)+"."+(addr>>24&255);var inetNtop6=ints=>{var str="";var word=0;var longest=0;var lastzero=0;var zstart=0;var len=0;var i=0;var parts=[ints[0]&65535,ints[0]>>16,ints[1]&65535,ints[1]>>16,ints[2]&65535,ints[2]>>16,ints[3]&65535,ints[3]>>16];var hasipv4=true;var v4part="";for(i=0;i<5;i++){if(parts[i]){hasipv4=false;break}}if(hasipv4){v4part=inetNtop4(parts[6]|parts[7]<<16);if(parts[5]===-1){str="::ffff:";str+=v4part;return str}if(!parts[5]){str="::";if(v4part==="0.0.0.0")v4part="";if(v4part==="0.0.0.1")v4part="1";str+=v4part;return str}}for(word=0;word<8;word++){if(!parts[word]){if(word-lastzero>1){len=0}lastzero=word;len++}if(len>longest){longest=len;zstart=word-longest+1}}for(word=0;word<8;word++){if(longest>1){if(!parts[word]&&word>=zstart&&word{var family=HEAP16[sa>>1];var port=_ntohs(HEAPU16[sa+2>>1]);var addr;switch(family){case 2:if(salen!==16){return{errno:28}}addr=HEAP32[sa+4>>2];addr=inetNtop4(addr);break;case 10:if(salen!==28){return{errno:28}}addr=[HEAP32[sa+8>>2],HEAP32[sa+12>>2],HEAP32[sa+16>>2],HEAP32[sa+20>>2]];addr=inetNtop6(addr);break;default:return{errno:5}}return{family,addr,port}};var getSocketAddress=(addrp,addrlen)=>{var info=readSockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info};function ___syscall_bind(fd,addr,len,u1,u2,u3){addr=bigintToI53Checked(addr);try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,len);sock.sock_ops.bind(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var HEAPU32;var HEAP64;var HEAPU64;var SYSCALLS={currentUmask:18,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return dir+"/"+path},writeStat(buf,stat){HEAPU32[buf>>2]=stat.dev;HEAPU32[buf+4>>2]=stat.mode;HEAPU64[buf+8>>3]=BigInt(stat.nlink);HEAPU32[buf+16>>2]=stat.uid;HEAPU32[buf+20>>2]=stat.gid;HEAPU32[buf+24>>2]=stat.rdev;HEAP64[buf+32>>3]=BigInt(stat.size);HEAP32[buf+40>>2]=4096;HEAP32[buf+44>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();HEAP64[buf+48>>3]=BigInt(Math.floor(atime/1e3));HEAPU64[buf+56>>3]=BigInt(atime%1e3*1e3*1e3);HEAP64[buf+64>>3]=BigInt(Math.floor(mtime/1e3));HEAPU64[buf+72>>3]=BigInt(mtime%1e3*1e3*1e3);HEAP64[buf+80>>3]=BigInt(Math.floor(ctime/1e3));HEAPU64[buf+88>>3]=BigInt(ctime%1e3*1e3*1e3);HEAP64[buf+96>>3]=BigInt(stat.ino);return 0},writeStatFs(buf,stats){HEAPU32[buf+8>>2]=stats.bsize;HEAPU32[buf+72>>2]=stats.bsize;HEAP64[buf+16>>3]=BigInt(stats.blocks);HEAP64[buf+24>>3]=BigInt(stats.bfree);HEAP64[buf+32>>3]=BigInt(stats.bavail);HEAP64[buf+40>>3]=BigInt(stats.files);HEAP64[buf+48>>3]=BigInt(stats.ffree);HEAPU32[buf+56>>2]=stats.fsid;HEAPU32[buf+80>>2]=stats.flags;HEAPU32[buf+64>>2]=stats.namelen},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.subarray(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_chdir(path){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);FS.chdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_chmod(path,mode){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_connect(fd,addr,len,u1,u2,u3){addr=bigintToI53Checked(addr);try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,len);sock.sock_ops.connect(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_dup(fd){try{var old=SYSCALLS.getStreamFromFD(fd);return FS.dupStream(old).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_faccessat(dirfd,path,amode,flags){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchmod(fd,mode){try{FS.fchmod(fd,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchownat(dirfd,path,owner,group,flags){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);var nofollow=flags&256;flags=flags&~256;path=SYSCALLS.calculateAt(dirfd,path);(nofollow?FS.lchown:FS.chown)(path,owner,group);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var syscallGetVarargP=()=>{var ret=Number(HEAPU64[SYSCALLS.varargs>>3]);SYSCALLS.varargs+=8;return ret};var syscallGetVarargI=()=>{var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret};function ___syscall_fcntl64(fd,cmd,varargs){varargs=bigintToI53Checked(varargs);SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();var mask=289792;stream.flags=stream.flags&~mask|arg&mask;return 0}case 5:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fdatasync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){buf=bigintToI53Checked(buf);try{return SYSCALLS.writeStat(buf,FS.fstat(fd))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ftruncate64(fd,length){length=bigintToI53Checked(length);try{if(isNaN(length))return-22;FS.ftruncate(fd,length);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_getcwd(buf,size){buf=bigintToI53Checked(buf);size=bigintToI53Checked(size);try{if(!size)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>3]=BigInt(id);HEAP64[dirp+pos+8>>3]=BigInt((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var ___syscall_geteuid32=()=>0;var ___syscall_getgid32=()=>0;function ___syscall_getpeername(fd,addr,len,u1,u2,u3){addr=bigintToI53Checked(addr);len=bigintToI53Checked(len);try{var sock=getSocketFromFD(fd);if(!sock.daddr){return-53}var errno=writeSockaddr(addr,sock.family,sock.daddr,sock.dport,len);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockname(fd,addr,len,u1,u2,u3){addr=bigintToI53Checked(addr);len=bigintToI53Checked(len);try{var sock=getSocketFromFD(fd);var defaultAddr="0.0.0.0";var errno=writeSockaddr(addr,sock.family,sock.saddr||defaultAddr,sock.sport,len);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockopt(fd,level,optname,optval,optlen,unused){optval=bigintToI53Checked(optval);optlen=bigintToI53Checked(optlen);try{var sock=getSocketFromFD(fd);if(level===1){if(optname===4){HEAP32[optval>>2]=sock.error;HEAP32[optlen>>2]=4;sock.error=null;return 0}}return-50}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var ___syscall_getuid32=()=>0;function ___syscall_ioctl(fd,op,varargs){varargs=bigintToI53Checked(varargs);SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21537:case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_linkat(olddirfd,oldpath,newdirfd,newpath,flags){oldpath=bigintToI53Checked(oldpath);newpath=bigintToI53Checked(newpath);try{oldpath=SYSCALLS.getStr(oldpath);newpath=SYSCALLS.getStr(newpath);oldpath=SYSCALLS.calculateAt(olddirfd,oldpath);newpath=SYSCALLS.calculateAt(newdirfd,newpath);FS.link(oldpath,newpath,flags);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_listen(fd,backlog,u1,u2,u3,u4){try{var sock=getSocketFromFD(fd);sock.sock_ops.listen(sock,backlog);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){path=bigintToI53Checked(path);buf=bigintToI53Checked(buf);try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.lstat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);mode&=~SYSCALLS.currentUmask;FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){path=bigintToI53Checked(path);buf=bigintToI53Checked(buf);try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.writeStat(buf,nofollow?FS.lstat(path):FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){path=bigintToI53Checked(path);varargs=bigintToI53Checked(varargs);SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;if(flags&64){mode&=~SYSCALLS.currentUmask}return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var PIPEFS={BUCKET_BUFFER_SIZE:8192,mount(mount){return FS.createNode(null,"/",16384|511,0)},createPipe(){var pipe={buckets:[],writerCount:1,writeClosed:false,readerCount:1,readClosed:false,timestamp:new Date};pipe.buckets.push({buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:0,roffset:0});var rName=PIPEFS.nextname();var wName=PIPEFS.nextname();var rNode=FS.createNode(PIPEFS.root,rName,4096,0);var wNode=FS.createNode(PIPEFS.root,wName,4096,0);rNode.pipe=pipe;wNode.pipe=pipe;pipe.readNode=rNode;pipe.writeNode=wNode;var readableStream=FS.createStream({path:rName,node:rNode,flags:0,seekable:false,stream_ops:PIPEFS.stream_ops});rNode.stream=readableStream;var writableStream=FS.createStream({path:wName,node:wNode,flags:1,seekable:false,stream_ops:PIPEFS.stream_ops});wNode.stream=writableStream;return{readable_fd:readableStream.fd,writable_fd:writableStream.fd}},stream_ops:{getattr(stream){var node=stream.node;var timestamp=node.pipe.timestamp;return{dev:14,ino:node.id,mode:4480,nlink:1,uid:0,gid:0,rdev:0,size:0,atime:timestamp,mtime:timestamp,ctime:timestamp,blksize:4096,blocks:0}},poll(stream){var pipe=stream.node.pipe;if((stream.flags&2097155)===1){var mask=256|4;if(pipe.readClosed){mask|=8}return mask}var mask=0;for(var bucket of pipe.buckets){if(bucket.offset-bucket.roffset>0){mask=64|1;break}}if(pipe.writeClosed){mask|=16|1}return mask},dup(stream){var pipe=stream.node.pipe;if((stream.flags&2097155)===1){pipe.writerCount++}else{pipe.readerCount++}},ioctl(stream,request,argp){if(request==21531){var pipe=stream.node.pipe;var currentLength=0;for(var bucket of pipe.buckets){currentLength+=bucket.offset-bucket.roffset}HEAP32[argp>>2]=currentLength;return 0}return 28},fsync(stream){return 28},read(stream,buffer,offset,length,position){var pipe=stream.node.pipe;var currentLength=0;for(var bucket of pipe.buckets){currentLength+=bucket.offset-bucket.roffset}var data=buffer.subarray(offset,offset+length);if(length<=0){return 0}if(currentLength==0){throw new FS.ErrnoError(6)}var toRead=Math.min(currentLength,length);var totalRead=toRead;var toRemove=0;for(var bucket of pipe.buckets){var bucketSize=bucket.offset-bucket.roffset;if(toRead<=bucketSize){var tmpSlice=bucket.buffer.subarray(bucket.roffset,bucket.offset);if(toRead=dataLen){currBucket.buffer.set(data,currBucket.offset);currBucket.offset+=dataLen;pipe.readNode.notifyListeners(64|1);return dataLen}else if(freeBytesInCurrBuffer>0){currBucket.buffer.set(data.subarray(0,freeBytesInCurrBuffer),currBucket.offset);currBucket.offset+=freeBytesInCurrBuffer;data=data.subarray(freeBytesInCurrBuffer,data.byteLength)}var numBuckets=data.byteLength/PIPEFS.BUCKET_BUFFER_SIZE|0;var remElements=data.byteLength%PIPEFS.BUCKET_BUFFER_SIZE;for(var i=0;i0){var newBucket={buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:data.byteLength,roffset:0};pipe.buckets.push(newBucket);newBucket.buffer.set(data)}pipe.readNode.notifyListeners(64|1);return dataLen},close(stream){var pipe=stream.node.pipe;if((stream.flags&2097155)===1){if(!--pipe.writerCount){pipe.writeClosed=true;pipe.readNode.notifyListeners(16|64|1)}}else if(!--pipe.readerCount){pipe.readClosed=true;pipe.writeNode.notifyListeners(8|256|4)}if(!pipe.readerCount&&!pipe.writerCount){pipe.buckets=null}}},nextname(){if(!PIPEFS.nextname.current){PIPEFS.nextname.current=0}return"pipe["+PIPEFS.nextname.current+++"]"}};function ___syscall_pipe2(fdPtr,flags){fdPtr=bigintToI53Checked(fdPtr);try{if(fdPtr==0){throw new FS.ErrnoError(21)}var validFlags=524288|2048;if(flags&~validFlags){throw new FS.ErrnoError(138)}var res=PIPEFS.createPipe();if(flags&2048){FS.getStream(res.readable_fd).flags|=2048;FS.getStream(res.writable_fd).flags|=2048}HEAP32[fdPtr>>2]=res.readable_fd;HEAP32[fdPtr+4>>2]=res.writable_fd;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var pollOne=(fd,events)=>{var stream=FS.getStream(fd);if(!stream)return 32;var flags=stream.stream_ops?.poll?.(stream)??5;return flags&(events|8|16|32)};var doPollSync=(fds,nfds)=>{var count=0;for(var i=0,pollfd=fds;i>2],HEAP16[pollfd+4>>1]);if(revents)count++;HEAP16[pollfd+6>>1]=revents}return count};var doPollAsync=(fds,nfds,timeout)=>new Promise(resolve=>{var regs=[];var timer;var done=false;function derive(){var count=0;for(var i=0,pollfd=fds;i>2],HEAP16[pollfd+4>>1]);if(revents)count++;HEAP16[pollfd+6>>1]=revents}return count}function finish(count){if(done)return;done=true;for(var r of regs)r.listeners.delete(r.entry);if(timer)clearTimeout(timer);resolve(count)}var count=derive();if(count||!timeout){finish(count)}else{function recheck(){if(done)return;var c=derive();if(c)finish(c)}for(var i=0,pollfd=fds;i>2]);if(stream)regs.push(stream.node.addListener(recheck))}if(timeout>0)timer=setTimeout(()=>finish(0),timeout)}});var ___syscall_poll=function(fds,nfds,timeout){let innerFunc=()=>{fds=bigintToI53Checked(fds);try{const isAsyncContext=true;if(isAsyncContext){return doPollAsync(fds,nfds,timeout)}var count=doPollSync(fds,nfds);return count}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}};return Asyncify.handleAsync(innerFunc)};___syscall_poll.isAsync=true;function ___syscall_poll_nonblocking(fds,nfds){fds=bigintToI53Checked(fds);try{return doPollSync(fds,nfds)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){path=bigintToI53Checked(path);buf=bigintToI53Checked(buf);bufsize=bigintToI53Checked(bufsize);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_recvfrom(fd,buf,len,flags,addr,alen){buf=bigintToI53Checked(buf);len=bigintToI53Checked(len);addr=bigintToI53Checked(addr);alen=bigintToI53Checked(alen);try{var sock=getSocketFromFD(fd);var msg=sock.sock_ops.recvmsg(sock,len,flags);if(!msg)return 0;if(addr){var errno=writeSockaddr(addr,sock.family,msg.addr,msg.port,alen)}HEAPU8.set(msg.buffer,buf);return msg.buffer.byteLength}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_renameat(olddirfd,oldpath,newdirfd,newpath){oldpath=bigintToI53Checked(oldpath);newpath=bigintToI53Checked(newpath);try{oldpath=SYSCALLS.getStr(oldpath);newpath=SYSCALLS.getStr(newpath);oldpath=SYSCALLS.calculateAt(olddirfd,oldpath);newpath=SYSCALLS.calculateAt(newdirfd,newpath);FS.rename(oldpath,newpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_sendto(fd,buf,len,flags,addr,alen){buf=bigintToI53Checked(buf);len=bigintToI53Checked(len);addr=bigintToI53Checked(addr);try{var sock=getSocketFromFD(fd);if(!addr){return FS.write(sock.stream,HEAP8,buf,len)}var dest=getSocketAddress(addr,alen);return sock.sock_ops.sendmsg(sock,HEAP8,buf,len,dest.addr,dest.port)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_setsockopt(fd,level,optname,optval,optlen,unused){optval=bigintToI53Checked(optval);try{getSocketFromFD(fd);return-50}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_shutdown(fd,how,u1,u2,u3,u4){try{var sock=getSocketFromFD(fd);return-52}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_socket(domain,type,protocol,u1,u2,u3){try{var sock=SOCKFS.createSocket(domain,type,protocol);return sock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){path=bigintToI53Checked(path);buf=bigintToI53Checked(buf);try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_statfs64(path,size,buf){path=bigintToI53Checked(path);size=bigintToI53Checked(size);buf=bigintToI53Checked(buf);try{SYSCALLS.writeStatFs(buf,FS.statfs(SYSCALLS.getStr(path)));return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_symlinkat(target,dirfd,linkpath){target=bigintToI53Checked(target);linkpath=bigintToI53Checked(linkpath);try{target=SYSCALLS.getStr(target);linkpath=SYSCALLS.getStr(linkpath);linkpath=SYSCALLS.calculateAt(dirfd,linkpath);FS.symlink(target,linkpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_umask(mask){try{var old=SYSCALLS.currentUmask;SYSCALLS.currentUmask=mask;return old}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){path=bigintToI53Checked(path);try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(!flags){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{return-28}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var readI53FromI64=ptr=>HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296;function ___syscall_utimensat(dirfd,path,times,flags){path=bigintToI53Checked(path);times=bigintToI53Checked(times);try{var nofollow=flags&256;path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path,true);var now=Date.now(),atime,mtime;if(!times){atime=now;mtime=now}else{var seconds=readI53FromI64(times);var nanoseconds=HEAP32[times+8>>2];if(nanoseconds==1073741823){atime=now}else if(nanoseconds==1073741822){atime=null}else{atime=seconds*1e3+nanoseconds/(1e3*1e3)}times+=16;seconds=readI53FromI64(times);nanoseconds=HEAP32[times+8>>2];if(nanoseconds==1073741823){mtime=now}else if(nanoseconds==1073741822){mtime=null}else{mtime=seconds*1e3+nanoseconds/(1e3*1e3)}}if((mtime??atime)!==null){FS.utime(path,atime,mtime,nofollow)}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>abort("");function __emscripten_lookup_name(name){name=bigintToI53Checked(name);var nameString=UTF8ToString(name);return inetPton4(DNS.lookup_name(nameString))}var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var __emscripten_throw_longjmp=()=>{throw new EmscriptenSjLj};function __gmtime_js(time,tmPtr){time=bigintToI53Checked(time);tmPtr=bigintToI53Checked(tmPtr);var date=new Date(time*1e3);if(isNaN(date.getTime())){return 1}HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;return 0}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};function __localtime_js(time,tmPtr){time=bigintToI53Checked(time);tmPtr=bigintToI53Checked(tmPtr);var date=new Date(time*1e3);if(isNaN(date.getTime())){return 1}HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP64[tmPtr+40>>3]=BigInt(-(date.getTimezoneOffset()*60));var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst;return 0}var __mktime_js=function(tmPtr){tmPtr=bigintToI53Checked(tmPtr);var ret=(()=>{var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);if(isNaN(date.getTime())){return-1}var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){dst=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4);if(isNaN(date.getTime())){return-1}}HEAP32[tmPtr+32>>2]=dst;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();return date.getTime()/1e3})();return BigInt(ret)};function __mmap_js(len,prot,flags,fd,offset,allocated,addr){len=bigintToI53Checked(len);offset=bigintToI53Checked(offset);allocated=bigintToI53Checked(allocated);addr=bigintToI53Checked(addr);try{var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU64[addr>>3]=BigInt(ptr);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){addr=bigintToI53Checked(addr);len=bigintToI53Checked(len);offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{return func()}catch(e){handleException(e)}finally{maybeExit()}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var __tzset_js=function(timezone,daylight,std_name,dst_name){timezone=bigintToI53Checked(timezone);daylight=bigintToI53Checked(daylight);std_name=bigintToI53Checked(std_name);dst_name=bigintToI53Checked(dst_name);var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU64[timezone>>3]=BigInt(stdTimezoneOffset*60);HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);if(summerOffsetDate.now();var nowIsMonotonic=1;var checkWasiClock=clock_id=>clock_id>=0&&clock_id<=3;function _clock_time_get(clk_id,ignored_precision,ptime){ignored_precision=bigintToI53Checked(ignored_precision);ptime=bigintToI53Checked(ptime);if(!checkWasiClock(clk_id)){return 28}var now;if(clk_id===0){now=_emscripten_date_now()}else if(nowIsMonotonic){now=_emscripten_get_now()}else{return 52}var nsec=Math.round(now*1e3*1e3);HEAP64[ptime>>3]=BigInt(nsec);return 0}var runAndAbortIfError=func=>{try{return func()}catch(e){abort(e)}};var runtimeKeepalivePush=()=>{runtimeKeepaliveCounter+=1};var runtimeKeepalivePop=()=>{runtimeKeepaliveCounter-=1};var Asyncify={rewindArguments:new Map,instrumentWasmImports(imports){var importPattern=/^(invoke_.*|__asyncjs__.*)$/;for(let[x,original]of Object.entries(imports)){if(typeof original=="function"){let isAsyncifyImport=original.isAsync||importPattern.test(x)}}},saveRewindArguments(func,passedArguments){return Asyncify.rewindArguments.set(func,Array.from(passedArguments))},restoreRewindArguments(func){return Asyncify.rewindArguments.get(func)},instrumentFunction(original){var wrapper=(...args)=>{Asyncify.exportCallStack.push(original);try{Asyncify.saveRewindArguments(original,args);return original(...args)}finally{if(!ABORT){var top=Asyncify.exportCallStack.pop();Asyncify.maybeStopUnwind()}}};Asyncify.funcWrappers.set(original,wrapper);return wrapper},instrumentWasmExports(exports){var ret={};for(let[x,original]of Object.entries(exports)){if(typeof original=="function"){var wrapper=Asyncify.instrumentFunction(original);ret[x]=wrapper}else{ret[x]=original}}return ret},State:{Normal:0,Unwinding:1,Rewinding:2,Disabled:3},state:0,StackSize:4096,currData:null,handleSleepReturnValue:0,exportCallStack:[],callstackFuncToId:new Map,callStackIdToFunc:new Map,funcWrappers:new Map,callStackId:0,asyncPromiseHandlers:null,sleepCallbacks:[],getCallStackId(func){if(!Asyncify.callstackFuncToId.has(func)){var id=Asyncify.callStackId++;Asyncify.callstackFuncToId.set(func,id);Asyncify.callStackIdToFunc.set(id,func)}return Asyncify.callstackFuncToId.get(func)},maybeStopUnwind(){if(Asyncify.currData&&Asyncify.state===Asyncify.State.Unwinding&&!Asyncify.exportCallStack.length){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_unwind);if(typeof Fibers!="undefined"){Fibers.trampoline()}}},whenDone(){return new Promise((resolve,reject)=>{Asyncify.asyncPromiseHandlers={resolve,reject}})},allocateData(){var ptr=_malloc(24+Asyncify.StackSize);Asyncify.setDataHeader(ptr,ptr+24,Asyncify.StackSize);Asyncify.setDataRewindFunc(ptr);return ptr},setDataHeader(ptr,stack,stackSize){HEAPU64[ptr>>3]=BigInt(stack);HEAPU64[ptr+8>>3]=BigInt(stack+stackSize)},setDataRewindFunc(ptr){var bottomOfCallStack=Asyncify.exportCallStack[0];var rewindId=Asyncify.getCallStackId(bottomOfCallStack);HEAP32[ptr+16>>2]=rewindId},getDataRewindFunc(ptr){var id=HEAP32[ptr+16>>2];var func=Asyncify.callStackIdToFunc.get(id);return func},doRewind(ptr){var original=Asyncify.getDataRewindFunc(ptr);var func=Asyncify.funcWrappers.get(original);func=func.bind(0,...Asyncify.restoreRewindArguments(original));return callUserCallback(func)},handleSleep(startAsync){if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){var reachedCallback=false;var reachedAfterCallback=false;startAsync((handleSleepReturnValue=0)=>{if(ABORT)return;Asyncify.handleSleepReturnValue=handleSleepReturnValue;reachedCallback=true;if(!reachedAfterCallback){return}Asyncify.state=Asyncify.State.Rewinding;runAndAbortIfError(()=>_asyncify_start_rewind(Asyncify.currData));if(typeof MainLoop!="undefined"&&MainLoop.func){MainLoop.resume()}var asyncWasmReturnValue,isError=false;try{asyncWasmReturnValue=Asyncify.doRewind(Asyncify.currData)}catch(err){asyncWasmReturnValue=err;isError=true}var handled=false;if(!Asyncify.currData){var asyncPromiseHandlers=Asyncify.asyncPromiseHandlers;if(asyncPromiseHandlers){Asyncify.asyncPromiseHandlers=null;(isError?asyncPromiseHandlers.reject:asyncPromiseHandlers.resolve)(asyncWasmReturnValue);handled=true}}if(isError&&!handled){throw asyncWasmReturnValue}});reachedAfterCallback=true;if(!reachedCallback){Asyncify.state=Asyncify.State.Unwinding;Asyncify.currData=Asyncify.allocateData();if(typeof MainLoop!="undefined"&&MainLoop.func){MainLoop.pause()}runAndAbortIfError(()=>_asyncify_start_unwind(Asyncify.currData))}}else if(Asyncify.state===Asyncify.State.Rewinding){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_rewind);_free(Asyncify.currData);Asyncify.currData=null;Asyncify.sleepCallbacks.forEach(callUserCallback)}else{abort(`invalid state: ${Asyncify.state}`)}return Asyncify.handleSleepReturnValue},handleAsync:startAsync=>Asyncify.handleSleep(async wakeUp=>{wakeUp(await startAsync())})};var Fibers={nextFiber:0,trampolineRunning:false,trampoline(){if(!Fibers.trampolineRunning&&Fibers.nextFiber){Fibers.trampolineRunning=true;do{var fiber=Fibers.nextFiber;Fibers.nextFiber=0;Fibers.finishContextSwitch(fiber)}while(Fibers.nextFiber);Fibers.trampolineRunning=false}},finishContextSwitch(newFiber){var stack_base=Number(HEAPU64[newFiber>>3]);var stack_max=Number(HEAPU64[newFiber+8>>3]);_emscripten_stack_set_limits(stack_base,stack_max);stackRestore(Number(HEAPU64[newFiber+16>>3]));var entryPoint=Number(HEAPU64[newFiber+24>>3]);if(entryPoint){Asyncify.currData=null;HEAPU64[newFiber+24>>3]=0n;var userData=Number(HEAPU64[newFiber+32>>3]);(a1=>dynCall_vj(entryPoint,BigInt(a1)))(userData)}else{var asyncifyData=newFiber+40;Asyncify.currData=asyncifyData;Asyncify.state=Asyncify.State.Rewinding;_asyncify_start_rewind(asyncifyData);Asyncify.doRewind(asyncifyData)}}};function _emscripten_fiber_swap(oldFiber,newFiber){oldFiber=bigintToI53Checked(oldFiber);newFiber=bigintToI53Checked(newFiber);if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){Asyncify.state=Asyncify.State.Unwinding;var asyncifyData=oldFiber+40;Asyncify.setDataRewindFunc(asyncifyData);Asyncify.currData=asyncifyData;_asyncify_start_unwind(asyncifyData);var stackTop=stackSave();HEAPU64[oldFiber+16>>3]=BigInt(stackTop);Fibers.nextFiber=newFiber}else{Asyncify.state=Asyncify.State.Normal;_asyncify_stop_rewind();Asyncify.currData=null}}_emscripten_fiber_swap.isAsync=true;var _emscripten_force_exit=status=>{__emscripten_runtime_keepalive_clear();_exit(status)};var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>BigInt(getHeapMax());var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};function _emscripten_resize_heap(requestedSize){requestedSize=bigintToI53Checked(requestedSize);var oldSize=HEAPU8.length;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false}var ENV={};var getExecutableName=()=>thisProgram;var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};function _environ_get(__environ,environ_buf){__environ=bigintToI53Checked(__environ);environ_buf=bigintToI53Checked(environ_buf);var bufSize=0;var envp=0;for(var string of getEnvStrings()){var ptr=environ_buf+bufSize;HEAPU64[__environ+envp>>3]=BigInt(ptr);bufSize+=stringToUTF8(string,ptr,Infinity)+1;envp+=8}return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){penviron_count=bigintToI53Checked(penviron_count);penviron_buf_size=bigintToI53Checked(penviron_buf_size);var strings=getEnvStrings();HEAPU64[penviron_count>>3]=BigInt(strings.length);var bufSize=0;for(var string of strings){bufSize+=lengthBytesUTF8(string)+1}HEAPU64[penviron_buf_size>>3]=BigInt(bufSize);return 0}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){pbuf=bigintToI53Checked(pbuf);try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf]=type;HEAP16[pbuf+2>>1]=flags;HEAP64[pbuf+8>>3]=BigInt(rightsBase);HEAP64[pbuf+16>>3]=BigInt(rightsInheriting);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>3]);var len=Number(HEAPU64[iov+8>>3]);iov+=16;try{var curr=FS.read(stream,HEAP8,ptr,len,offset)}catch(e){if(ret>0&&e instanceof FS.ErrnoError&&(e.errno==6||e.errno==6)){break}throw e}if(curr<0)return-1;ret+=curr;if(curr>3]=BigInt(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset,whence,newOffset){offset=bigintToI53Checked(offset);newOffset=bigintToI53Checked(newOffset);try{if(isNaN(offset))return 22;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);HEAP64[newOffset>>3]=BigInt(stream.position);if(stream.getdents&&!offset&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _fd_sync=function(fd){let innerFunc=()=>{try{var stream=SYSCALLS.getStreamFromFD(fd);var rtn=stream.stream_ops?.fsync?.(stream);return new Promise(resolve=>{var mount=stream.node.mount;if(mount?.type.syncfs){mount.type.syncfs(mount,false,err=>resolve(err?29:0))}else{resolve(rtn)}})}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}};return Asyncify.handleAsync(innerFunc)};_fd_sync.isAsync=true;var doWritev=(stream,iov,iovcnt,offset)=>{if(iovcnt==1){return FS.write(stream,HEAP8,Number(HEAPU64[iov>>3]),Number(HEAPU64[iov+8>>3]),offset)}var total=0;for(var i=0,p=iov;i>3])}var view=new Uint8Array(total);var voff=0;for(var i=0;i>3]);var len=Number(HEAPU64[iov+8>>3]);view.set(HEAPU8.subarray(ptr,ptr+len),voff);voff+=len}return FS.write(stream,view,0,total,offset)};function _fd_write(fd,iov,iovcnt,pnum){iov=bigintToI53Checked(iov);iovcnt=bigintToI53Checked(iovcnt);pnum=bigintToI53Checked(pnum);try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU64[pnum>>3]=BigInt(num);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _getaddrinfo(node,service,hint,out){node=bigintToI53Checked(node);service=bigintToI53Checked(service);hint=bigintToI53Checked(hint);out=bigintToI53Checked(out);var addr=0;var port=0;var flags=0;var family=0;var type=0;var proto=0;var ai;function allocaddrinfo(family,type,proto,canon,addr,port){var sa,salen,ai;var errno;salen=family===10?28:16;addr=family===10?inetNtop6(addr):inetNtop4(addr);sa=_malloc(salen);errno=writeSockaddr(sa,family,addr,port);ai=_malloc(48);HEAP32[ai+4>>2]=family;HEAP32[ai+8>>2]=type;HEAP32[ai+12>>2]=proto;HEAPU64[ai+32>>3]=BigInt(canon);HEAPU64[ai+24>>3]=BigInt(sa);if(family===10){HEAP32[ai+16>>2]=28}else{HEAP32[ai+16>>2]=16}HEAP32[ai+40>>2]=0;return ai}if(hint){flags=HEAP32[hint>>2];family=HEAP32[hint+4>>2];type=HEAP32[hint+8>>2];proto=HEAP32[hint+12>>2]}if(type&&!proto){proto=type===2?17:6}if(!type&&proto){type=proto===17?2:1}if(!proto){proto=6}if(!type){type=1}if(!node&&!service){return-2}if(flags&~(1|2|4|1024|8|16|32)){return-1}if(hint&&HEAP32[hint>>2]&2&&!node){return-1}if(flags&32){return-2}if(type&&type!==1&&type!==2){return-7}if(family!==0&&family!==2&&family!==10){return-6}if(service){service=UTF8ToString(service);port=parseInt(service,10);if(isNaN(port)){if(flags&1024){return-2}return-8}}if(!node){if(family===0){family=2}if(!(flags&1)){if(family===2){addr=_htonl(2130706433)}else{addr=[0,0,0,_htonl(1)]}}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAPU64[out>>3]=BigInt(ai);return 0}node=UTF8ToString(node);addr=inetPton4(node);if(addr!==null){if(family===0||family===2){family=2}else if(family===10&&flags&8){addr=[0,0,_htonl(65535),addr];family=10}else{return-2}}else{addr=inetPton6(node);if(addr!==null){if(family===0||family===10){family=10}else{return-2}}}if(addr!=null){ai=allocaddrinfo(family,type,proto,node,addr,port);HEAPU64[out>>3]=BigInt(ai);return 0}if(flags&4){return-2}node=DNS.lookup_name(node);addr=inetPton4(node);if(family===0){family=2}else if(family===10){addr=[0,0,_htonl(65535),addr]}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAPU64[out>>3]=BigInt(ai);return 0}function _getnameinfo(sa,salen,node,nodelen,serv,servlen,flags){sa=bigintToI53Checked(sa);node=bigintToI53Checked(node);serv=bigintToI53Checked(serv);var info=readSockaddr(sa,salen);if(info.errno){return-6}var port=info.port;var addr=info.addr;var overflowed=false;if(node&&nodelen){var lookup;if(flags&1||!(lookup=DNS.lookup_addr(addr))){if(flags&8){return-2}}else{addr=lookup}var numBytesWrittenExclNull=stringToUTF8(addr,node,nodelen);if(numBytesWrittenExclNull+1>=nodelen){overflowed=true}}if(serv&&servlen){port=""+port;var numBytesWrittenExclNull=stringToUTF8(port,serv,servlen);if(numBytesWrittenExclNull+1>=servlen){overflowed=true}}if(overflowed){return-12}return 0}var Protocols={list:[],map:{}};var stringToAscii=(str,buffer)=>{for(var i=0;i{function allocprotoent(name,proto,aliases){var nameBuf=_malloc(name.length+1);stringToAscii(name,nameBuf);var j=0;var length=aliases.length;var aliasListBuf=_malloc((length+1)*4);for(var i=0;i>3]=BigInt(aliasBuf)}HEAPU64[aliasListBuf+j>>3]=0n;var pe=_malloc(24);HEAPU64[pe>>3]=BigInt(nameBuf);HEAPU64[pe+8>>3]=BigInt(aliasListBuf);HEAP32[pe+16>>2]=proto;return pe}var list=Protocols.list;var map=Protocols.map;if(!list.length){var entry=allocprotoent("tcp",6,["TCP"]);list.push(entry);map["tcp"]=map["6"]=entry;entry=allocprotoent("udp",17,["UDP"]);list.push(entry);map["udp"]=map["17"]=entry}_setprotoent.index=0};var _getprotobyname=function(name){name=bigintToI53Checked(name);var ret=(()=>{name=UTF8ToString(name);_setprotoent(true);var result=Protocols.map[name];return result})();return BigInt(ret)};var _getprotobynumber=function(number){var ret=(()=>{_setprotoent(true);var result=Protocols.map[number];return result})();return BigInt(ret)};var arraySum=(array,index)=>{var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum};var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];var addDays=(date,days)=>{var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate};var _strptime=function(buf,format,tm){buf=bigintToI53Checked(buf);format=bigintToI53Checked(format);tm=bigintToI53Checked(tm);var ret=(()=>{var pattern=UTF8ToString(format);var SPECIAL_CHARS="\\!@#$^&*()+=-[]/{}|:<>?,.";for(var i=0,ii=SPECIAL_CHARS.length;iEQUIVALENT_MATCHERS[c]||m).replace(/%(.)/g,(_,c)=>{let pat=DATE_PATTERNS[c];if(pat){capture.push(c);return`(${pat})`}else{return c}}).replace(/\s+/g,"\\s*");var matches=new RegExp("^"+pattern_out,"i").exec(UTF8ToString(buf));function initDate(){function fixup(value,min,max){return typeof value!="number"||isNaN(value)?min:value>=min?value<=max?value:max:min}return{year:fixup(HEAP32[tm+20>>2]+1900,1970,9999),month:fixup(HEAP32[tm+16>>2],0,11),day:fixup(HEAP32[tm+12>>2],1,31),hour:fixup(HEAP32[tm+8>>2],0,23),min:fixup(HEAP32[tm+4>>2],0,59),sec:fixup(HEAP32[tm>>2],0,59),gmtoff:0}}if(matches){var date=initDate();var value;var getMatch=symbol=>{var pos=capture.indexOf(symbol);if(pos>=0){return matches[pos+1]}return};if(value=getMatch("S")){date.sec=Number(value)}if(value=getMatch("M")){date.min=Number(value)}if(value=getMatch("H")){date.hour=Number(value)}else if(value=getMatch("I")){var hour=Number(value);if(value=getMatch("p")){hour+=value.toUpperCase()[0]==="P"?12:0}date.hour=hour}if(value=getMatch("Y")){date.year=Number(value)}else if(value=getMatch("y")){var year=Number(value);if(value=getMatch("C")){year+=Number(value)*100}else{year+=year<69?2e3:1900}date.year=year}if(value=getMatch("m")){date.month=Number(value)-1}else if(value=getMatch("b")){date.month=MONTH_NUMBERS[value.substring(0,3).toUpperCase()]||0}if(value=getMatch("d")){date.day=Number(value)}else if(value=getMatch("j")){var day=Number(value);var leapYear=isLeapYear(date.year);for(var month=0;month<12;++month){var daysUntilMonth=arraySum(leapYear?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,month-1);if(day<=daysUntilMonth+(leapYear?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[month]){date.day=day-daysUntilMonth}}}else if(value=getMatch("a")){var weekDay=value.substring(0,3).toUpperCase();if(value=getMatch("U")){var weekDayNumber=DAY_NUMBERS_SUN_FIRST[weekDay];var weekNumber=Number(value);var janFirst=new Date(date.year,0,1);var endDate;if(janFirst.getDay()===0){endDate=addDays(janFirst,weekDayNumber+7*(weekNumber-1))}else{endDate=addDays(janFirst,7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1))}date.day=endDate.getDate();date.month=endDate.getMonth()}else if(value=getMatch("W")){var weekDayNumber=DAY_NUMBERS_MON_FIRST[weekDay];var weekNumber=Number(value);var janFirst=new Date(date.year,0,1);var endDate;if(janFirst.getDay()===1){endDate=addDays(janFirst,weekDayNumber+7*(weekNumber-1))}else{endDate=addDays(janFirst,7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1))}date.day=endDate.getDate();date.month=endDate.getMonth()}}if(value=getMatch("z")){if(value.toLowerCase()==="z"){date.gmtoff=0}else{var match=value.match(/^((?:\-|\+)\d\d):?(\d\d)?/);date.gmtoff=match[1]*3600;if(match[2]){date.gmtoff+=date.gmtoff>0?match[2]*60:-match[2]*60}}}var fullDate=new Date(date.year,date.month,date.day,date.hour,date.min,date.sec,0);HEAP32[tm>>2]=fullDate.getSeconds();HEAP32[tm+4>>2]=fullDate.getMinutes();HEAP32[tm+8>>2]=fullDate.getHours();HEAP32[tm+12>>2]=fullDate.getDate();HEAP32[tm+16>>2]=fullDate.getMonth();HEAP32[tm+20>>2]=fullDate.getFullYear()-1900;HEAP32[tm+24>>2]=fullDate.getDay();HEAP32[tm+28>>2]=arraySum(isLeapYear(fullDate.getFullYear())?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,fullDate.getMonth()-1)+fullDate.getDate()-1;HEAP32[tm+32>>2]=0;HEAP64[tm+40>>3]=BigInt(date.gmtoff);return buf+lengthBytesUTF8(matches[0])}return 0})();return BigInt(ret)};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={pointer:p=>BigInt(p),string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return BigInt(ret)},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return BigInt(ret)}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(Number(ret))}if(returnType==="pointer")return Number(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP64[ptr>>3];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];case"*":return Number(HEAPU64[ptr>>3]);default:abort(`invalid type for getValue: ${type}`)}}function setValue(ptr,value,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":HEAP8[ptr]=value;break;case"i8":HEAP8[ptr]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":HEAP64[ptr>>3]=BigInt(value);break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;case"*":HEAPU64[ptr>>3]=BigInt(value);break;default:abort(`invalid type for setValue: ${type}`)}}FS.createPreloadedFile=FS_createPreloadedFile;FS.preloadFile=FS_preloadFile;FS.staticInit();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["arguments"])programArgs=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var preInit=Module["preInit"];if(preInit){if(typeof preInit=="function")Module["preInit"]=preInit=[preInit];while(preInit.length>0){preInit.shift()()}}}Module["ENV"]=ENV;Module["ccall"]=ccall;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;Module["FS"]=FS;var _pib_heap_bytes,_pib_eval,_free,_malloc,_htons,_ntohs,_htonl,_pib_force_exit,_emscripten_builtin_memalign,__emscripten_timeout,_setThrew,_emscripten_stack_set_limits,__emscripten_stack_restore,__emscripten_stack_alloc,_emscripten_stack_get_current,dynCall_vjj,dynCall_jjj,dynCall_ijjjj,dynCall_vjjj,dynCall_ijjj,dynCall_vj,dynCall_jj,dynCall_vjjjj,dynCall_ij,dynCall_jjjj,dynCall_vjjijjj,dynCall_vjjjiijj,dynCall_vjjij,dynCall_vjjjjj,dynCall_vjji,dynCall_vjjjjijiij,dynCall_ijj,dynCall_ijji,dynCall_jji,dynCall_jjji,dynCall_ii,dynCall_ijjjjj,dynCall_ijjjjjjj,dynCall_ijjjjjj,dynCall_vji,dynCall_j,dynCall_v,dynCall_jjjjj,dynCall_vjjiijjjjjjjjj,dynCall_jjjji,dynCall_iij,dynCall_vjij,dynCall_ji,dynCall_jjii,dynCall_vjjjji,dynCall_vjjii,dynCall_vjjji,dynCall_iji,dynCall_jjjiij,dynCall_jiij,dynCall_jjjjji,dynCall_ijjji,dynCall_iijj,dynCall_vjiji,dynCall_i,dynCall_vijj,dynCall_ijjii,dynCall_vi,dynCall_vii,dynCall_jjij,dynCall_vijij,dynCall_jjjjii,dynCall_jjjiiii,dynCall_vjjdi,dynCall_ijiijj,dynCall_vjjjij,dynCall_vjii,dynCall_iijjjj,dynCall_jjjjjjiijj,dynCall_ijjij,dynCall_jjjijj,dynCall_jjjij,dynCall_jijj,dynCall_vjjjjij,dynCall_vjjjjjj,dynCall_jjjjjj,dynCall_ijjiii,dynCall_jjjjijj,dynCall_jii,dynCall_vij,dynCall_ijjjjjji,dynCall_ijjjji,dynCall_ijiij,dynCall_vjijj,dynCall_vjiijijjj,dynCall_jjijj,dynCall_vjijjj,dynCall_iijjj,dynCall_ijij,dynCall_iiji,dynCall_ijdiiiii,dynCall_jij,dynCall_ijjjjijj,dynCall_ijjjjji,dynCall_vijijj,dynCall_ijii,dynCall_viiijjj,dynCall_vjdj,dynCall_iii,dynCall_jjjjjjj,dynCall_ijjijj,dynCall_ijjjij,dynCall_ijjiij,dynCall_jjjjij,dynCall_vjjjjii,dynCall_vjjjii,_asyncify_start_unwind,_asyncify_stop_unwind,_asyncify_start_rewind,_asyncify_stop_rewind,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){_pib_heap_bytes=Module["_pib_heap_bytes"]=wasmExports["Mb"];_pib_eval=Module["_pib_eval"]=wasmExports["Nb"];_free=wasmExports["Ob"];_malloc=wasmExports["Pb"];_htons=wasmExports["Qb"];_ntohs=wasmExports["Rb"];_htonl=wasmExports["Sb"];_pib_force_exit=Module["_pib_force_exit"]=wasmExports["Tb"];_emscripten_builtin_memalign=wasmExports["Vb"];__emscripten_timeout=wasmExports["Wb"];_setThrew=wasmExports["Xb"];_emscripten_stack_set_limits=wasmExports["Yb"];__emscripten_stack_restore=wasmExports["Zb"];__emscripten_stack_alloc=wasmExports["_b"];_emscripten_stack_get_current=wasmExports["$b"];dynCall_vjj=dynCalls["vjj"]=wasmExports["ac"];dynCall_jjj=dynCalls["jjj"]=wasmExports["bc"];dynCall_ijjjj=dynCalls["ijjjj"]=wasmExports["cc"];dynCall_vjjj=dynCalls["vjjj"]=wasmExports["dc"];dynCall_ijjj=dynCalls["ijjj"]=wasmExports["ec"];dynCall_vj=dynCalls["vj"]=wasmExports["fc"];dynCall_jj=dynCalls["jj"]=wasmExports["gc"];dynCall_vjjjj=dynCalls["vjjjj"]=wasmExports["hc"];dynCall_ij=dynCalls["ij"]=wasmExports["ic"];dynCall_jjjj=dynCalls["jjjj"]=wasmExports["jc"];dynCall_vjjijjj=dynCalls["vjjijjj"]=wasmExports["kc"];dynCall_vjjjiijj=dynCalls["vjjjiijj"]=wasmExports["lc"];dynCall_vjjij=dynCalls["vjjij"]=wasmExports["mc"];dynCall_vjjjjj=dynCalls["vjjjjj"]=wasmExports["nc"];dynCall_vjji=dynCalls["vjji"]=wasmExports["oc"];dynCall_vjjjjijiij=dynCalls["vjjjjijiij"]=wasmExports["pc"];dynCall_ijj=dynCalls["ijj"]=wasmExports["qc"];dynCall_ijji=dynCalls["ijji"]=wasmExports["rc"];dynCall_jji=dynCalls["jji"]=wasmExports["sc"];dynCall_jjji=dynCalls["jjji"]=wasmExports["tc"];dynCall_ii=dynCalls["ii"]=wasmExports["uc"];dynCall_ijjjjj=dynCalls["ijjjjj"]=wasmExports["vc"];dynCall_ijjjjjjj=dynCalls["ijjjjjjj"]=wasmExports["wc"];dynCall_ijjjjjj=dynCalls["ijjjjjj"]=wasmExports["xc"];dynCall_vji=dynCalls["vji"]=wasmExports["yc"];dynCall_j=dynCalls["j"]=wasmExports["zc"];dynCall_v=dynCalls["v"]=wasmExports["Ac"];dynCall_jjjjj=dynCalls["jjjjj"]=wasmExports["Bc"];dynCall_vjjiijjjjjjjjj=dynCalls["vjjiijjjjjjjjj"]=wasmExports["Cc"];dynCall_jjjji=dynCalls["jjjji"]=wasmExports["Dc"];dynCall_iij=dynCalls["iij"]=wasmExports["Ec"];dynCall_vjij=dynCalls["vjij"]=wasmExports["Fc"];dynCall_ji=dynCalls["ji"]=wasmExports["Gc"];dynCall_jjii=dynCalls["jjii"]=wasmExports["Hc"];dynCall_vjjjji=dynCalls["vjjjji"]=wasmExports["Ic"];dynCall_vjjii=dynCalls["vjjii"]=wasmExports["Jc"];dynCall_vjjji=dynCalls["vjjji"]=wasmExports["Kc"];dynCall_iji=dynCalls["iji"]=wasmExports["Lc"];dynCall_jjjiij=dynCalls["jjjiij"]=wasmExports["Mc"];dynCall_jiij=dynCalls["jiij"]=wasmExports["Nc"];dynCall_jjjjji=dynCalls["jjjjji"]=wasmExports["Oc"];dynCall_ijjji=dynCalls["ijjji"]=wasmExports["Pc"];dynCall_iijj=dynCalls["iijj"]=wasmExports["Qc"];dynCall_vjiji=dynCalls["vjiji"]=wasmExports["Rc"];dynCall_i=dynCalls["i"]=wasmExports["Sc"];dynCall_vijj=dynCalls["vijj"]=wasmExports["Tc"];dynCall_ijjii=dynCalls["ijjii"]=wasmExports["Uc"];dynCall_vi=dynCalls["vi"]=wasmExports["Vc"];dynCall_vii=dynCalls["vii"]=wasmExports["Wc"];dynCall_jjij=dynCalls["jjij"]=wasmExports["Xc"];dynCall_vijij=dynCalls["vijij"]=wasmExports["Yc"];dynCall_jjjjii=dynCalls["jjjjii"]=wasmExports["Zc"];dynCall_jjjiiii=dynCalls["jjjiiii"]=wasmExports["_c"];dynCall_vjjdi=dynCalls["vjjdi"]=wasmExports["$c"];dynCall_ijiijj=dynCalls["ijiijj"]=wasmExports["ad"];dynCall_vjjjij=dynCalls["vjjjij"]=wasmExports["bd"];dynCall_vjii=dynCalls["vjii"]=wasmExports["cd"];dynCall_iijjjj=dynCalls["iijjjj"]=wasmExports["dd"];dynCall_jjjjjjiijj=dynCalls["jjjjjjiijj"]=wasmExports["ed"];dynCall_ijjij=dynCalls["ijjij"]=wasmExports["fd"];dynCall_jjjijj=dynCalls["jjjijj"]=wasmExports["gd"];dynCall_jjjij=dynCalls["jjjij"]=wasmExports["hd"];dynCall_jijj=dynCalls["jijj"]=wasmExports["id"];dynCall_vjjjjij=dynCalls["vjjjjij"]=wasmExports["jd"];dynCall_vjjjjjj=dynCalls["vjjjjjj"]=wasmExports["kd"];dynCall_jjjjjj=dynCalls["jjjjjj"]=wasmExports["ld"];dynCall_ijjiii=dynCalls["ijjiii"]=wasmExports["md"];dynCall_jjjjijj=dynCalls["jjjjijj"]=wasmExports["nd"];dynCall_jii=dynCalls["jii"]=wasmExports["od"];dynCall_vij=dynCalls["vij"]=wasmExports["pd"];dynCall_ijjjjjji=dynCalls["ijjjjjji"]=wasmExports["qd"];dynCall_ijjjji=dynCalls["ijjjji"]=wasmExports["rd"];dynCall_ijiij=dynCalls["ijiij"]=wasmExports["sd"];dynCall_vjijj=dynCalls["vjijj"]=wasmExports["td"];dynCall_vjiijijjj=dynCalls["vjiijijjj"]=wasmExports["ud"];dynCall_jjijj=dynCalls["jjijj"]=wasmExports["vd"];dynCall_vjijjj=dynCalls["vjijjj"]=wasmExports["wd"];dynCall_iijjj=dynCalls["iijjj"]=wasmExports["xd"];dynCall_ijij=dynCalls["ijij"]=wasmExports["yd"];dynCall_iiji=dynCalls["iiji"]=wasmExports["zd"];dynCall_ijdiiiii=dynCalls["ijdiiiii"]=wasmExports["Ad"];dynCall_jij=dynCalls["jij"]=wasmExports["Bd"];dynCall_ijjjjijj=dynCalls["ijjjjijj"]=wasmExports["Cd"];dynCall_ijjjjji=dynCalls["ijjjjji"]=wasmExports["Dd"];dynCall_vijijj=dynCalls["vijijj"]=wasmExports["Ed"];dynCall_ijii=dynCalls["ijii"]=wasmExports["Fd"];dynCall_viiijjj=dynCalls["viiijjj"]=wasmExports["Gd"];dynCall_vjdj=dynCalls["vjdj"]=wasmExports["Hd"];dynCall_iii=dynCalls["iii"]=wasmExports["Id"];dynCall_jjjjjjj=dynCalls["jjjjjjj"]=wasmExports["Jd"];dynCall_ijjijj=dynCalls["ijjijj"]=wasmExports["Kd"];dynCall_ijjjij=dynCalls["ijjjij"]=wasmExports["Ld"];dynCall_ijjiij=dynCalls["ijjiij"]=wasmExports["Md"];dynCall_jjjjij=dynCalls["jjjjij"]=wasmExports["Nd"];dynCall_vjjjjii=dynCalls["vjjjjii"]=wasmExports["Od"];dynCall_vjjjii=dynCalls["vjjjii"]=wasmExports["Pd"];_asyncify_start_unwind=wasmExports["Qd"];_asyncify_stop_unwind=wasmExports["Rd"];_asyncify_start_rewind=wasmExports["Sd"];_asyncify_stop_rewind=wasmExports["Td"];memory=wasmMemory=wasmExports["Kb"];__indirect_function_table=wasmTable=wasmExports["Ub"]}var wasmImports={m:___assert_fail,Ka:___call_sighandler,za:___syscall_accept4,ya:___syscall_bind,ib:___syscall_chdir,fa:___syscall_chmod,Q:___syscall_connect,gb:___syscall_dup,jb:___syscall_faccessat,fb:___syscall_fchmod,ea:___syscall_fchownat,q:___syscall_fcntl64,eb:___syscall_fdatasync,db:___syscall_fstat64,_a:___syscall_ftruncate64,Za:___syscall_getcwd,Ja:___syscall_getdents64,Xa:___syscall_geteuid32,R:___syscall_getgid32,wa:___syscall_getpeername,va:___syscall_getsockname,ua:___syscall_getsockopt,F:___syscall_getuid32,ha:___syscall_ioctl,Wa:___syscall_linkat,ta:___syscall_listen,bb:___syscall_lstat64,Ua:___syscall_mkdirat,ab:___syscall_newfstatat,S:___syscall_openat,Na:___syscall_pipe2,ba:___syscall_poll,Ma:___syscall_poll_nonblocking,Ia:___syscall_readlinkat,P:___syscall_recvfrom,Ha:___syscall_renameat,$:___syscall_rmdir,I:___syscall_sendto,Ib:___syscall_setsockopt,Hb:___syscall_shutdown,sa:___syscall_socket,cb:___syscall_stat64,Ga:___syscall_statfs64,Fa:___syscall_symlinkat,Da:___syscall_umask,aa:___syscall_unlinkat,Ca:___syscall_utimensat,kb:__abort_js,xa:__emscripten_lookup_name,La:__emscripten_runtime_keepalive_clear,Aa:__emscripten_throw_longjmp,Qa:__gmtime_js,Sa:__localtime_js,Ta:__mktime_js,Oa:__mmap_js,Pa:__munmap_js,_:__setitimer_js,mb:__tzset_js,hb:_clock_time_get,da:_emscripten_date_now,Jb:_emscripten_fiber_swap,Ya:_emscripten_force_exit,Ea:_emscripten_get_heap_max,J:_emscripten_get_now,Ba:_emscripten_resize_heap,ob:_environ_get,pb:_environ_sizes_get,z:_exit,D:_fd_close,ca:_fd_fdstat_get,ga:_fd_read,Va:_fd_seek,$a:_fd_sync,T:_fd_write,Ra:_getaddrinfo,K:_getnameinfo,vb:_getprotobyname,sb:_getprotobynumber,C:invoke_i,u:invoke_ii,Y:invoke_iii,y:invoke_iij,Gb:invoke_iijj,t:invoke_ij,E:invoke_iji,wb:invoke_ijii,M:invoke_ijiij,W:invoke_ijiijj,v:invoke_ijij,e:invoke_ijj,Z:invoke_ijji,Fb:invoke_ijjii,na:invoke_ijjiii,zb:invoke_ijjijj,k:invoke_ijjj,H:invoke_ijjji,p:invoke_ijjjj,la:invoke_ijjjjijj,Db:invoke_ijjjjji,Bb:invoke_ijjjjjji,o:invoke_j,ia:invoke_ji,yb:invoke_jij,qa:invoke_jijj,b:invoke_jj,i:invoke_jji,rb:invoke_jjii,h:invoke_jjj,s:invoke_jjji,Eb:invoke_jjjiiii,l:invoke_jjjj,tb:invoke_jjjji,d:invoke_jjjjii,Cb:invoke_jjjjijj,n:invoke_jjjjj,xb:invoke_jjjjji,oa:invoke_jjjjjj,Ab:invoke_jjjjjjiijj,c:invoke_v,O:invoke_vi,ra:invoke_vii,V:invoke_vij,U:invoke_vijijj,g:invoke_vijj,a:invoke_vj,x:invoke_vji,B:invoke_vjii,r:invoke_vjij,j:invoke_vjiji,G:invoke_vjijj,f:invoke_vjj,X:invoke_vjjdi,ma:invoke_vjji,A:invoke_vjjii,ub:invoke_vjjiijjjjjjjjj,L:invoke_vjjij,w:invoke_vjjj,ja:invoke_vjjjj,qb:invoke_vjjjji,pa:invoke_vjjjjij,ka:invoke_vjjjjj,N:invoke_vjjjjjj,lb:_proc_exit,nb:_strptime};function invoke_j(index){var sp=stackSave();try{return dynCall_j(Number(index))}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_jj(index,a1){var sp=stackSave();try{return dynCall_jj(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vj(index,a1){var sp=stackSave();try{dynCall_vj(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjj(index,a1,a2,a3){var sp=stackSave();try{dynCall_vjjj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjj(index,a1,a2){var sp=stackSave();try{dynCall_vjj(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{dynCall_v(Number(index))}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jji(index,a1,a2){var sp=stackSave();try{return dynCall_jji(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijj(index,a1,a2){var sp=stackSave();try{return dynCall_ijj(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjjj(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjjjj(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjj(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jjjjj(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijjj(index,a1,a2,a3){var sp=stackSave();try{return dynCall_ijjj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ii(index,a1){var sp=stackSave();try{return dynCall_ii(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vji(index,a1,a2){var sp=stackSave();try{dynCall_vji(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjj(index,a1,a2){var sp=stackSave();try{return dynCall_jjj(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vjjij(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjjij(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjiijjjjjjjjj(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13){var sp=stackSave();try{dynCall_vjjiijjjjjjjjj(Number(index),a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjji(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jjjji(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_iij(index,a1,a2){var sp=stackSave();try{return dynCall_iij(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjij(index,a1,a2,a3){var sp=stackSave();try{dynCall_vjij(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ij(index,a1){var sp=stackSave();try{return dynCall_ij(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ji(index,a1){var sp=stackSave();try{return dynCall_ji(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_jjii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jjii(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vjjjji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vjjjji(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjii(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjjii(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_iijj(index,a1,a2,a3){var sp=stackSave();try{return dynCall_iijj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjiji(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjiji(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return dynCall_i(Number(index))}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjji(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jjji(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vijj(index,a1,a2,a3){var sp=stackSave();try{dynCall_vijj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjii(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_ijjii(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijji(index,a1,a2,a3){var sp=stackSave();try{return dynCall_ijji(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return dynCall_iii(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{dynCall_vi(Number(index),a1)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{dynCall_vii(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_jjjjii(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_jjjiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_jjjiiii(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_jjjj(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jjjj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijjji(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_ijjji(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjjj(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_ijjjj(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_iji(index,a1,a2){var sp=stackSave();try{return dynCall_iji(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjdi(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjjdi(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijiijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_ijiijj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjii(index,a1,a2,a3){var sp=stackSave();try{dynCall_vjii(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjjjji(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_ijjjjji(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jijj(index,a1,a2,a3){var sp=stackSave();try{return dynCall_jijj(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vjjjjij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_vjjjjij(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjjjjj(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{dynCall_vjjjjjj(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjjj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_jjjjjj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijjiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_ijjiii(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjijj(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_jjjjijj(Number(index),a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_vjji(index,a1,a2,a3){var sp=stackSave();try{dynCall_vjji(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2){var sp=stackSave();try{dynCall_vij(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjjjjji(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_ijjjjjji(Number(index),a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijiij(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_ijiij(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjijj(index,a1,a2,a3,a4){var sp=stackSave();try{dynCall_vjijj(Number(index),a1,a2,a3,a4)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjjjiijj(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return dynCall_jjjjjjiijj(Number(index),a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijij(index,a1,a2,a3){var sp=stackSave();try{return dynCall_ijij(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_ijjijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_ijjijj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jij(index,a1,a2){var sp=stackSave();try{return dynCall_jij(Number(index),a1,a2)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijjjjijj(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return dynCall_ijjjjijj(Number(index),a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vijijj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vijijj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_vjjjjj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{dynCall_vjjjjj(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function invoke_jjjjji(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return dynCall_jjjjji(Number(index),a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0);return 0n}}function invoke_ijii(index,a1,a2,a3){var sp=stackSave();try{return dynCall_ijii(Number(index),a1,a2,a3)}catch(e){stackRestore(sp);if(!(e instanceof EmscriptenEH))throw e;_setThrew(1,0)}}function applySignatureConversions(wasmExports){wasmExports=Object.assign({},wasmExports);var makeWrapper__p=f=>a0=>f(BigInt(a0));var makeWrapper_pp=f=>a0=>Number(f(BigInt(a0)));var makeWrapper_ppp=f=>(a0,a1)=>Number(f(BigInt(a0),BigInt(a1)));var makeWrapper__p_=f=>(a0,a1)=>f(BigInt(a0),a1);var makeWrapper__pp=f=>(a0,a1)=>f(BigInt(a0),BigInt(a1));var makeWrapper_p=f=>()=>Number(f());var makeWrapper__p__=f=>(a0,a1,a2)=>f(BigInt(a0),a1,a2);var makeWrapper__p____=f=>(a0,a1,a2,a3,a4)=>f(BigInt(a0),a1,a2,a3,a4);var makeWrapper__p___=f=>(a0,a1,a2,a3)=>f(BigInt(a0),a1,a2,a3);var makeWrapper__p______=f=>(a0,a1,a2,a3,a4,a5,a6)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6);var makeWrapper__p_______=f=>(a0,a1,a2,a3,a4,a5,a6,a7)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6,a7);var makeWrapper__p_____=f=>(a0,a1,a2,a3,a4,a5)=>f(BigInt(a0),a1,a2,a3,a4,a5);var makeWrapper__p_________=f=>(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6,a7,a8,a9);var makeWrapper__p_____________=f=>(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13);var makeWrapper__p________=f=>(a0,a1,a2,a3,a4,a5,a6,a7,a8)=>f(BigInt(a0),a1,a2,a3,a4,a5,a6,a7,a8);wasmExports["Ob"]=makeWrapper__p(wasmExports["Ob"]);wasmExports["Pb"]=makeWrapper_pp(wasmExports["Pb"]);wasmExports["Vb"]=makeWrapper_ppp(wasmExports["Vb"]);wasmExports["Xb"]=makeWrapper__p_(wasmExports["Xb"]);wasmExports["Yb"]=makeWrapper__pp(wasmExports["Yb"]);wasmExports["Zb"]=makeWrapper__p(wasmExports["Zb"]);wasmExports["_b"]=makeWrapper_pp(wasmExports["_b"]);wasmExports["$b"]=makeWrapper_p(wasmExports["$b"]);wasmExports["ac"]=makeWrapper__p__(wasmExports["ac"]);wasmExports["bc"]=makeWrapper__p__(wasmExports["bc"]);wasmExports["cc"]=makeWrapper__p____(wasmExports["cc"]);wasmExports["dc"]=makeWrapper__p___(wasmExports["dc"]);wasmExports["ec"]=makeWrapper__p___(wasmExports["ec"]);wasmExports["fc"]=makeWrapper__p_(wasmExports["fc"]);wasmExports["gc"]=makeWrapper__p_(wasmExports["gc"]);wasmExports["hc"]=makeWrapper__p____(wasmExports["hc"]);wasmExports["ic"]=makeWrapper__p_(wasmExports["ic"]);wasmExports["jc"]=makeWrapper__p___(wasmExports["jc"]);wasmExports["kc"]=makeWrapper__p______(wasmExports["kc"]);wasmExports["lc"]=makeWrapper__p_______(wasmExports["lc"]);wasmExports["mc"]=makeWrapper__p____(wasmExports["mc"]);wasmExports["nc"]=makeWrapper__p_____(wasmExports["nc"]);wasmExports["oc"]=makeWrapper__p___(wasmExports["oc"]);wasmExports["pc"]=makeWrapper__p_________(wasmExports["pc"]);wasmExports["qc"]=makeWrapper__p__(wasmExports["qc"]);wasmExports["rc"]=makeWrapper__p___(wasmExports["rc"]);wasmExports["sc"]=makeWrapper__p__(wasmExports["sc"]);wasmExports["tc"]=makeWrapper__p___(wasmExports["tc"]);wasmExports["uc"]=makeWrapper__p_(wasmExports["uc"]);wasmExports["vc"]=makeWrapper__p_____(wasmExports["vc"]);wasmExports["wc"]=makeWrapper__p_______(wasmExports["wc"]);wasmExports["xc"]=makeWrapper__p______(wasmExports["xc"]);wasmExports["yc"]=makeWrapper__p__(wasmExports["yc"]);wasmExports["zc"]=makeWrapper__p(wasmExports["zc"]);wasmExports["Ac"]=makeWrapper__p(wasmExports["Ac"]);wasmExports["Bc"]=makeWrapper__p____(wasmExports["Bc"]);wasmExports["Cc"]=makeWrapper__p_____________(wasmExports["Cc"]);wasmExports["Dc"]=makeWrapper__p____(wasmExports["Dc"]);wasmExports["Ec"]=makeWrapper__p__(wasmExports["Ec"]);wasmExports["Fc"]=makeWrapper__p___(wasmExports["Fc"]);wasmExports["Gc"]=makeWrapper__p_(wasmExports["Gc"]);wasmExports["Hc"]=makeWrapper__p___(wasmExports["Hc"]);wasmExports["Ic"]=makeWrapper__p_____(wasmExports["Ic"]);wasmExports["Jc"]=makeWrapper__p____(wasmExports["Jc"]);wasmExports["Kc"]=makeWrapper__p____(wasmExports["Kc"]);wasmExports["Lc"]=makeWrapper__p__(wasmExports["Lc"]);wasmExports["Mc"]=makeWrapper__p_____(wasmExports["Mc"]);wasmExports["Nc"]=makeWrapper__p___(wasmExports["Nc"]);wasmExports["Oc"]=makeWrapper__p_____(wasmExports["Oc"]);wasmExports["Pc"]=makeWrapper__p____(wasmExports["Pc"]);wasmExports["Qc"]=makeWrapper__p___(wasmExports["Qc"]);wasmExports["Rc"]=makeWrapper__p____(wasmExports["Rc"]);wasmExports["Sc"]=makeWrapper__p(wasmExports["Sc"]);wasmExports["Tc"]=makeWrapper__p___(wasmExports["Tc"]);wasmExports["Uc"]=makeWrapper__p____(wasmExports["Uc"]);wasmExports["Vc"]=makeWrapper__p_(wasmExports["Vc"]);wasmExports["Wc"]=makeWrapper__p__(wasmExports["Wc"]);wasmExports["Xc"]=makeWrapper__p___(wasmExports["Xc"]);wasmExports["Yc"]=makeWrapper__p____(wasmExports["Yc"]);wasmExports["Zc"]=makeWrapper__p_____(wasmExports["Zc"]);wasmExports["_c"]=makeWrapper__p______(wasmExports["_c"]);wasmExports["$c"]=makeWrapper__p____(wasmExports["$c"]);wasmExports["ad"]=makeWrapper__p_____(wasmExports["ad"]);wasmExports["bd"]=makeWrapper__p_____(wasmExports["bd"]);wasmExports["cd"]=makeWrapper__p___(wasmExports["cd"]);wasmExports["dd"]=makeWrapper__p_____(wasmExports["dd"]);wasmExports["ed"]=makeWrapper__p_________(wasmExports["ed"]);wasmExports["fd"]=makeWrapper__p____(wasmExports["fd"]);wasmExports["gd"]=makeWrapper__p_____(wasmExports["gd"]);wasmExports["hd"]=makeWrapper__p____(wasmExports["hd"]);wasmExports["id"]=makeWrapper__p___(wasmExports["id"]);wasmExports["jd"]=makeWrapper__p______(wasmExports["jd"]);wasmExports["kd"]=makeWrapper__p______(wasmExports["kd"]);wasmExports["ld"]=makeWrapper__p_____(wasmExports["ld"]);wasmExports["md"]=makeWrapper__p_____(wasmExports["md"]);wasmExports["nd"]=makeWrapper__p______(wasmExports["nd"]);wasmExports["od"]=makeWrapper__p__(wasmExports["od"]);wasmExports["pd"]=makeWrapper__p__(wasmExports["pd"]);wasmExports["qd"]=makeWrapper__p_______(wasmExports["qd"]);wasmExports["rd"]=makeWrapper__p_____(wasmExports["rd"]);wasmExports["sd"]=makeWrapper__p____(wasmExports["sd"]);wasmExports["td"]=makeWrapper__p____(wasmExports["td"]);wasmExports["ud"]=makeWrapper__p________(wasmExports["ud"]);wasmExports["vd"]=makeWrapper__p____(wasmExports["vd"]);wasmExports["wd"]=makeWrapper__p_____(wasmExports["wd"]);wasmExports["xd"]=makeWrapper__p____(wasmExports["xd"]);wasmExports["yd"]=makeWrapper__p___(wasmExports["yd"]);wasmExports["zd"]=makeWrapper__p___(wasmExports["zd"]);wasmExports["Ad"]=makeWrapper__p_______(wasmExports["Ad"]);wasmExports["Bd"]=makeWrapper__p__(wasmExports["Bd"]);wasmExports["Cd"]=makeWrapper__p_______(wasmExports["Cd"]);wasmExports["Dd"]=makeWrapper__p______(wasmExports["Dd"]);wasmExports["Ed"]=makeWrapper__p_____(wasmExports["Ed"]);wasmExports["Fd"]=makeWrapper__p___(wasmExports["Fd"]);wasmExports["Gd"]=makeWrapper__p______(wasmExports["Gd"]);wasmExports["Hd"]=makeWrapper__p___(wasmExports["Hd"]);wasmExports["Id"]=makeWrapper__p__(wasmExports["Id"]);wasmExports["Jd"]=makeWrapper__p______(wasmExports["Jd"]);wasmExports["Kd"]=makeWrapper__p_____(wasmExports["Kd"]);wasmExports["Ld"]=makeWrapper__p_____(wasmExports["Ld"]);wasmExports["Md"]=makeWrapper__p_____(wasmExports["Md"]);wasmExports["Nd"]=makeWrapper__p_____(wasmExports["Nd"]);wasmExports["Od"]=makeWrapper__p______(wasmExports["Od"]);wasmExports["Pd"]=makeWrapper__p_____(wasmExports["Pd"]);wasmExports["Qd"]=makeWrapper__p(wasmExports["Qd"]);wasmExports["Sd"]=makeWrapper__p(wasmExports["Sd"]);return wasmExports}async function run(){preRun();if(runDependencies){await resolveRunDependencies()}var setStatus=Module["setStatus"];if(setStatus){setStatus("Running...");await new Promise(resolve=>setTimeout(resolve,1));setTimeout(setStatus,1,"")}if(ABORT)return;initRuntime();Module["onRuntimeInitialized"]?.();postRun()}var wasmExports;wasmExports=await createWasm();await run(); +;return Module}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=PHP;module.exports.default=PHP}else if(typeof define==="function"&&define["amd"])define([],()=>PHP); diff --git a/web/landing/assets/wasm/php.wasm b/web/landing/assets/wasm/php.wasm index 733fb6246e2e309044f5f3519ac5f14e5b37a3d1..9f382069711b6ef7bf61f8514cec4535222012c3 100755 GIT binary patch literal 17089368 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

      5qmTRVKhHJ5Fwrj5Ih3C2Fndgb;vFDNJ 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ן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%0Av&riu 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

      +$S{ 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

      kkWW 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%0DC!qZO4$aZGxv6MNNBHIXiP7uz-O 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 z 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%0DxHm%(~Q_>`GY$<{k^i$mJTD^ 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

      xiy8)Z{{c*@E#$MkjbVPaEt1C&&B$ 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

      C#lusPj5KHJDnM>CUto+4S^Odpa}<0+r9m7Kc;$ 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�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%0ApjE5djm=N?bB_5wnxy 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�&Z`BVyM4<3wcCEB+zTPClK6T=Zx~ zm59`M3nGFNuW6_3WQW)AK89{(I*@+S%gv+iFVi=yt%tb7uI$hY0ZjK$-v6b`I93O| z>D_iEoxwNDOb&qDXj!*-4n~?*yDcR`w>TA|r{&Ow+O=)uf({AZM66&_2BXBfC4gz< z^7qrH&pD5rymEv@GMbVX-NJw2hTXDVHYU%oJ1+0|+^2B9D?X>)gQA-ftR*eM1{h%% zRyz#WNQ-*I8(rRPmq_(Qyh?fAE#}1A1R2eHH+%PKa|op2hq>Gz6_Ds8!USQ)o9U&) zvD_?|&l-+mvjH}A5s+?X>p-17o7*ACYCpqh+ve$%PpjRI2d#GpCxh}i3opC%v=Pi) zJIME(rY+>))_&S|G(=TD1sVcV@Tr4rDiUg@H340#7C7jqx=di>a7|m-nKjXcFB5vE z6nMxx_YFo1WEPw6B(2so#5ba{=ASvs?(1>T6y#j%gf)W7>5KDnJ3b%qE^u-hE}$TW zi8kQZ9Lmu(JekYx+l&(-O)V6ii|5lRL>@MT3#17^bGmTeTu;!Q(afVQ8n(cat8Gm5 z>`JLzFoVSY#oo;@Cc1<&rxdnGSHt4!X(-Stc8{%m<^p4?TFdks=)Z&mvRWKmK-aL7 zz1TeMja7BYuudHmoOcABKlb=>+b|4uPubL)5VoiS})frkk97y8S$}a7* zH)38TN6Zz!cCLXKsftkvPfMtAcpAlQ6FFb&VX6Pg+Q!NXmPj*hSlG%H~8RX90& zzl>i{Yv{ZqG9sHAV+xQ?s}{BNRI6cowTi2f1xT0ok6iP4dQ1up%tNgvtZOOig8NiF;n zraq9=0Z}4WTlzBc&b8U1N(P39=To?K+(4%!d9dzGVwg{yGRE2PcN_SXeOqb_PLq>N&eb8Jx<8oREF(w$%eT| zm)$UP+7bIRZ(@m#1A+UPg+ZJ6*)7Z|q&$+Ax1`yt@Idmj_^Ey)KFOr+Zd0vg)|zqiU{Qi8U-0y zqMAc&&2=9Y-Hv*rWhuJZX#IVPzi^*zO?mVr1)`-2j53!6_rXGUGlE${a_`(Vnv$qP z7Fpx;<$b%Z#Cfqt(15&>Wc}mI;cQz<7dV18675?tH<+M>p$q!kLYH#uXwI6zyJ0kM zzfkv#I#j?Lia=2Ndbm(M?7mQSA7RWfd{5ycXxIwgyd zdf2KF%b;n$(8KQY!&s#Ep-QSw5b+S7O}x^N7jQ?TMT7t_a_B%)r(=rHB&FkkIp5?? z(!_Stk$-HikjmP(4KqE1yjVy99ytSba}`sa|xX8L&M;&_C% zam@amjgHtf04RWd>?E5mB<282uDXgmbdhd@E$TqKuuVvM~Xk~n4Z2Zjeu4;)+Kr+1wh^sec&cu ztlGFTr*zj4W`w1P`DFfKq=$q(gmRYo_2sr#vHFD|8c=F@wFWN%AD_M0F4AAj`RCBE zttwI~q7SxS*f6RIy*z3&{?-xc;^~w1Lr}L~h@J}cs74H{uqYXA!q*nq6TaMXdyauY zP!Xh{>1(cvV4~Yjtd4+J+K+JPnY8M@KaU%2yfza0a`+_CY{PTzfb8X4PqIE<9PW#6 z*!{PU-|xoz?;O7`zZiS}mht;D@&3EV@6X2jw~pVRkN0mMzn{hXcZ}a(8}Gkw{QkOl z|IYFIC+dDue!%bM_%k>hHu(L!Chu?b`}a)V-yG||ude^B)>de{MTUyj-!^2+V6z-~ zQ47eYqbaZeM+CDgF}+Nsa07B;n1x#_Mpi9L<9dX0Jzusg7c?-wJjr9l=y&)l7b3PI zuaFM~ls=Z1vc#zF(#wkU^2;t`fU?@OE=Lw1ff>{vg=pvE5&LUfBwg7@sVIC?zbZx{ zM8b6>mqZ|3f{U;)Dvl`UZf?(-+HUZJEM0$1PduK@*d`IIcAk5=Gn9KmxmSY=I_-2n z05Q!gu9$Gt^tRFFvVGk!hpy0J$vd0NCx~ZWxNbP4qnl`Lv=!XnVrzGsR)YQ7d?ep2 zSO!Sy0cwov^Q~8omU+}!`4MWk<-XcdcCH+4$%iHeGb7WuJnARUd?7b#+N z(NR>x<%fzNvg+)~j?u}7V1UwtOKpC+-F*6JZtNyH%)#?v)r0d281(*p z?PZ&=2ZN?-fr?2Vl==FzS{*C%lQA-!)#~b^n{TuWft!n2yO{BdIlGwki+Q`4_lpI) z$owL+3pGUrYwTj3Uz}hUC;G*ScCo=PPO=LUrs$gucCpzn)ir%p1SkzlYKhJ~k z7%ggD2Lbw_6QG>s9w?7i`e?Js^LvSpu*1LL|^Db zlD{Ia%)cj?hegy zLpA$Uvp30EfD6TEx-Ynt&DKJ3tn-3PFT<+gG@N~&LvnZo=&tkMTl39iTe#sD04%qs z1z5_|ynD?18a)Ml-s(AMwBK;L(F(I5hM;Mvd4(t8F}ESvAvq#50gte{^#`w39Ply+ zc%44xW92Gn_pL&_LDgIz;N@XKc5YcvMeDi3f#sXkAFfIz9i1t)U)iT{*$2lM}=x>Z;o3N6a>W>?pk|Q z0@qA@R^2-o0t@^UI1(WP_%$uSKCW=&Gf8|0>>E`)RvC_ZK5TjH1y$y%#;)0=GHD6V z@g{J__NGvy+Wi=c8@9`47ExFB@SdW!T8xtoB)a)aZzF(L166ewglZ0kQm+?_i)`Uh ziX1Wh(zJmxS`7I7Uu_fD*03 z!4P4{EG(23{!WQo2>!A%1JDafa#AWDNt2VSlonH^LV0U#rX7}EAeJ-vdHV9(vhTD8 zUnL>-HSMKoKF)3|jrtgHLv;c*l~;%^BAR8HB= zt|bGKuim<&RC@KfqZA45)_D<*;+pfQM%^^1+C+HbZkAKWa$NA3Qz~MA!(?&iKhtR( z;nhUwwg=>oce}4{2Rj+zRh3gO-JTO zPw1(E*E8-0&{e6aEAYbpC&0^{pB%hy)f?}&fwzw48Uyci@h3F?0*V9z;AtO(@%d z(0q6<$O+&Po(w6wzPe?v*j@avbt$eS*i4;Q^NyC^T%vWa?+XIF(nP)=y4)brk``ND zpw}zD$m<29^K#l+TzurW31_zxXF2+WUs{w?RLf`bGG@GY^a$vqeD8WCHEnC%V)CJf z_B7npTXKukQ^XFvjAO*ik@6qEmRSJbk>WeM6^>w$e4X;KXoww@$G(5uP1^3cI30rK z+T}<7V>4Qt!I3q+>hKrR0D<b&M5on8wbXGH0nL}rQX8~Gz%^E!{ZHgXx4|+(&6!Ss8&VaO>UKqMzib&`#YiB8<7zy#i|4v(LTR!YhGn)~Zhv~yMRG^FK+zw3v$>0#G2cVSWRg<_&n zAXdDDTL`xJhq>>T`%%w0zJO|M^lDW5Q78T?A_u|P@R(8&Il8vEE=uqiHwSC)bd|(; z?X4@{C!rX309=|BPhk*l=EiI8CzVk~c&z*}p4rCj*Sar!Rw;Z|xf8tAdwW90npNU& zIA{c|`l8&1LEb5ws!I$nl;o?40iwLSr8STMViWI}!Q2s{ugElucq7V-pP4zzxyO-C zIReLL%5VJ;(|vZIF%i)q;scHG@UV?ch*hawQ%|c_RpnHL=Z@!}L#JS8!OWE3zWxNS zEFe2Ef)ka=L9n8f>N^y$>Z@D>shC_ZBYdHp29v+rDsPuxrl(WtX~63CSmo!^QzOFB zQEyi}Clkk2wl2s0Z{RELHFf0!cULL1LTMX#HrC_ zEG*!URHw%H`3atY4`_C@xbWtdyG@UQDp!$5v-Jau7r{vhss7At42lPS_6nb;`;jKu zrx1R^vZm_z*_p<6_Z>SDQ;nnDV=UoVXoPsBS z{!KxeAL^Vs#s8?dul3XYJkBXt;eNlYU#%Rp=M0AcI+ZzDn-OpDyCXH`<#*MdIxMt zrSI^?jJ5L@GoH0_AF55ge;{ZAR!Q8dz(q6wcl-;9Zgk){Yw%ZKtgJanR*{H>M4kzP zcanV;C1!;^6-D8@Q8(z9kid-yW&a&&#Y;oF8c%BzQ~k%1j)=w8BNqpXJ30? zK0Bf|RA3uZ7BDXB_!aomJS|%mR3k}cRHC1$xd7^O;gF({wh z_Nxq;Cd(T>N6+UpKHGe_z|t;I9A~Wa%F&aq)*Z#=<0aPjlxW`jp)>RRo7q*nWj6N(-QMMJ?c#pA6M1o@^IHpJZQ~ zD|iqj1$|Or8s)Sh?LK)sc%7;{!R53%Mo7Jf8>(6+Qjt3y)cuz-m(0IZw@Kk1WAMSM zbw8#lReizTv^vimCe+!_&_+VInrws<&J7~rNTzr`Cy?vcgxlvD`xLFin`IOJF3C*AW0o|S%wgzrH3kkm)s})oAvWxb z@$R`cf9d3yt)XHuM`jLlwnmh!Op3I8>vtJd_Q$P4DTUy^RfEF2$8%?u%-dR{eRjn5 z+GXBk^~SnSsNXzc;>~(amm37hMQX7nG#|;xI;*rLv|s0yf{-Xsn((BT>%(gRaQ#Hv zVI9R@o>=$t#ECao+e_Lz$!kFpP9*M}RCO(3+I7K{BtG#h0qqR=XoGjM{OWaU3i5ui zX1<*kq%U&tBM|cuJWoPWjk@i9wptg5&Bc0hXns&G9)*0YD^B)WAX`$q8aw;Nv1+gq z&RWEC?>g=eS%T`(Mym&ZxqLQzS6XcJTFAI$ixEl@)+F0(Y*@EEEu~{%= zW6kVp-|>Hp=9Czf^+S1(#iMk!ktJ=S&1>imx@(9wjPA&qpG%5OaRAx`J6)rHo4tQU zJNpC*cz*>l>br}nVvB(PmMrq z^QRS!s&IqGBZKUSK`vdA5p{E`%_vkJ+lm04K+0k07U(-{Htg&NK#c0TM*ae%D@=~+ zx{!GfgV=7b&We_7_gCxip=k+MipO5HIcg@zp_C?vQrdA}lxT@iQzD02elYl=%urmL zR)`X9(doJ-{n1{Pq&s3?X}j(NwS4+e%pm)rxwN~S*_O12NZEWKeNi(9y+l-9OGH&E z5mn_*_Ss6?y$8`$*Gk{4Yo+_q^*%&cl?N0q$o+$u;dT8I2)xRdA^@S0T`x32aC@*t)bJV{RT4oY^}e3vv2jCYb%5k%VN; zF`19CHzVj@`{1S2)~O>p1IO6R8?5o#rBZYvcuYF|S6tf>}Fv4NxNJZ$7Ps2oTc zLa8jWt_4$TBFc4p8YC^619y4#|2|?C(Y4cPf7C8;dCBhAu37sC>yDmC1!V8j4SN$5 zQ<=LKgo*dqDfT>2??HLj2ae-|ksaF=$S_rr!jmiO5J=dsr z4i$;Q^R`CKU`84Mq4)gvYj~Lk?n^gZdY#GsmZblY&ba*Nf)}4X)r{Hv{^w^+IUm&D zewejfQrC>#+EC%Fi_XLi1F4zp{#{XYMkQjD*N{OQlcxZ|K_;zMXmBtZq`}9f+zFas z1|KCymYShV3h*HJhBB1sEiKItEoHhN(f~2pBMCW7E`N#d@Qszpwp84udwNK~-ix)F zVoRr28EB0>xF1||M!H+LtcOA#`vkfsX*eW^Y9NpA4FCx26dhxB{ienqA>vKDyyit_ zzZ$Dv4iLK|E~$2TxuoCr$vuYer$+1ueRl?U^q7r`gvYLN=A@Z*~QWC^0 zqb6SI$WO5^9sMcxB^#vF!@6E2+wml9o?EMxCk4bG624gJLtr#gst|>&O_iubGD>v5 zmJm2WJ(lrPX=D6k_Lw*;&EAEpt1o?Q8KhQQMZ{ev0H4x;PierXG~iRpgj54<2gEfQ zyenNk8CEkW8^lkOp%&h%Arlc^D)5|TtyIz1{I_DO+~Ubf+_}Dd5RU6oTHBP}W)i6x zbR;82#1k`xBxfd~oRFjNohy}C2ub$lic?49kKO(nB;T<2Cl0H|2JyZ&!qGCwwQ}~H zp5`26N`DLo9JVZ@p7w{zm^DgaIqiK$xB&mpB-q@`{DKnZc73_{(Bfit9W?CHVUIlv zF70g`V(`MmV7X}&>}UKGwbN4_mIeoASKc72EHi1ZNJTN4Qe+P4Wb%}36>NDr)?T;F zf0g#SvAu)JGu5eHRa$_&&5Y#W$BO~_)Qg4e)_rQdiquy42#I#dHHQpPsL=0Aqry=3 zwgl%;y+Ah^GgmtFm6c*b>I#$w{%e|9N|4;tz(h7KldtCoQ#e~KbEeXshCBE*hNk)^7u1f>-OS6YPD_w zY}yUIO$i2iO9>`3Dy7kKO55;JLeqEXJ`8kcP22Z~wii(M&hiPrn*31a`(y~X0@|yT zxFa)vZf5^gQ~j7@zzv@`sVub_WOp<$-Qh^ObJy3HUA?P#SxI9XD(hfeEWwJ9Lutm1 z_Vui4#b88g!Dij=9u=iNHEF}{&O(c7UL;2rmn2BHy9eLW;{ctuWEyNoyE_(YIB9Kn z=gh*e(2iho4<;$k1Q)%AqSnhddg!DqeM7a&tAJoMurkv#BdjRoBcpD%_7MbDk?4^g z8uCz@AV6uzqn=A!KuN7j1c5KNmOmW4UsFm)l-1BZF=&_!)E8#!dbdfG8>z~b7pxq;ee=DML(|({ePK!qQct zAYnPd>`Il}SgT`)_%7E{cBovX)QEEnPOIi?+Kp-~*?A-%_Hm10pF6p9+#etT_10)z zJ3vry+k%54Is0@06PH@;X~c4)?cY9}ff`0gI!lI{_T)uSzaBIh<)6Q!jUfBhN{<2T ztqD6NFg6zaVq_eQf9w&wr90nlcM`D?gc&7HYc9#yx1jjYk_?N19d`k!kBqk ztWlC}b4kWTY%J%nBw63)69aYyQ1PgZ#-&GY?|$t;!CmO8e9K860R^oz;&^b|(3-20 zmu+=A@rZ8-gOOoYVO?e&uCz|6*VZZP)tt>MSR$S9Jrb*5WQ0@VX|oj|FK37kxy0Kt;ip6;)jP#My1Pf)&jflEnH1^s!|O$h1s5zaPSM)gBb7J+rbHuW=ScA?V3`Tl zoX{Yb!(fkunxJ(;46>TBNLoUZFrShe9)u8!iZbaRBNdqPHGxsEBJ|Ddg+K?o9SLK0 z6h>1aT->uxdF$ryqFfh>QwJS_#-miKu8wF+gNWGNUHkw@?*I zg{tU%JpCG;qkBy)@T3xqE)zA!GVH>L5xz67{N2tUE^pLcQAP2 zf@Y63(bMn{$|lvHcNKgdLizTy?^#y7U43^|W!PqpcbBBsCf<(YWbWt1{*<&*XEudV zOVN(9r9(as;DtBkOcxd5v5GAX7KEQYPi2 z56kF+pc5uJYLBG9fQ>(uj7cXyt|-T4I@zSt5)8$8RVsu_rAIl6PP^b31<4rQ=-$<< zj&iKMQUjHCr&KUY_9i#fI=wZSDZ9BnIb3tbL*pMvo%7^Q`J12JlD)seLA051_l&${ zh9K;A)0Oz=6mS{>4Ua)%ZoH_Sk5Z-J?tx#GivbkTCC#JvCz2Hc`;Kld6~RQxQ2T*( z^VoND!JiWmjESave+-bL6T^e94rDT5n1P?fK3+IhIMy|0_LujwxJVQu>1H{}A3 zkd!P4#q&J|*{AJ#2WD{H-;G2n!^Lpbxk;caN0+_Jws4bouq&?;`TL&n#%OFB#OfsbVrye$5*0}u z`=avG!I}~LzgKbCeW$VGlc2^mWNlU@vhzBX_RM-_t6b&c3MhaO4m0r3 zEciRY<18+r#*C5YSrfT^UJWD8Y#${)IXF|G3bVNx_^M$~|5g$V#mThFQdX<~F^G_0 zWCkUa@6E`Y$?N7dCk|x@Ax1v%g;1=|-p?+{tK*bI$AdvYoTNBRE)_*qXOC=&7&H?# zSDXW82T8VI?){o14+0YDtFN>p7U6vt_o7`uU@PDzU(7nLz1gvtly|DQCi`Y3iwr{N z0;&!|5D81&Ukjp090O~-%J%DSNP{4ibTK!HVFxjU;e-{T6~&>f4(%d_esr^&PmIz? zV-WW8s6RHFoSIR!X~F+M*@YG(bF>+xln6o#afQy$1|U!2HVlLnRktDa(2w)+4~qg zp6Mf-JzZ=bc4$?eQ>dCP`LlHj&?wd44%u4$C+!#f}k7xlH>ExVRGa9gqUNo zwuh=KxD>~C{UvGGS*avn=qVX4eZ62bUo2)yeuLo4-UKRpO7c=Wz=6F`kq*FqyFF~d z33xZRL^%?7URv}y=79|l5+v)q7;KY?F4Sz!&1C>(aBrs8NCkqMGW%wR9~_k%kAr)10A=t{j?V!l zF10#t&q3)P%BY%DSMX7e?^Z7b2jue0U+R~?{=~`I9cgqzCiI(nh?e%+qSJBMEd+OC zk42CmC;>5U)_X=;G2(0Q7AtUHV+;P&?k#v4SB|kx3*yV}P&`$B@QZ!*J~$M!>xnA{ z{}~*oBAt;humqfcK5m=6-~_zl>+TNBzNWa31p(5qg$>Jr-BR!m9`D&mQ#rXfn)loSZN3t2#CzxlFNsV0Ycbvu@ zUGP0Nx2iCU?n^vI2;!Cwl9oFmFgHy213l(pZTf0?!)IPy<0TeWwQYVoiucZxRx z)Qj{;DDiUC#LAHUazo3YFf7&-j*Hj-TPu68RRkF+W|SA`c-O$F5v+D@p((l&k@j^*WcE(0V#e8C5~x4{z*iI)n5V zH#cEALkANay2F8=3O`OFqG*mIa2#13M#S{V8X7#~R-r9G!ZOPjrCGitacS>NiETki zx!kjW5}QNAvmh#SUwuYHZbN^;TXNGat~#WoD49ew@`BZ*}%|IRbU$A{!FMCVn!%Eg9)B1*;%tA2O_OhdF%6!GM*{M>vkcmW^ z;ff(a9hBpX*l_lZVF{rbFaRCzxDsa;QHRaRXf5iT%k1cYT5FP_C-Jxf;kAb$8XV)G ze{>lJooDmAlXPl+Ff%(nw~+NuSl4T}+w0pM`*(f2-EIE2X6<^W2H<4okpT?XtM~bW z1Gs$s>$f&E*V}5za*k0Kq3AW&~eb1-DZygzc(T8}_P8t7XH}3gZHTwr7o7h_GwjymT0vGYlAE#zSrb zHzH`q$cAs}N8x3U$nAt}1~->~+W=HI;gPu*9wf1co$AsiW>08>C>s&-`{L0FR7FOn zQRdl~7Sr<}3u_0twq2D1Wx=oi(h$ZLkQsh5sU z*mSXeSURUswx5#;)}A|BcNv-137v_eLYyeu1QX%t{!3vOylJCDm}%vxyA$#rB>n_0 zu>PNdXDEn_$0=c^s@ZSf@knx(J>cLx9#{;zNX6K?;#HKp(@Hr>N&J!}WFQDKM}d*Y z^Xc-=RhX`PMf)DSLuAyq{zQA$A5=SW(8(k;Cw}TEvH1Fw1PhWbCYE&7^oG!M&@ab^ zd^g{r<3FIGX*CqK^h+A@A-EcNq41r(KKzXjND;z^VSmpQM(H0oz*h2gw#jd`feO44 zQBcN`>^51R6_%gKVH=RXaC8E~<=UJq*4b?^&DL!r4T%Z>gq^W~5I++G|2fYvP*-}l+;D~5LYT~OIr4XQsQ#HBq`*li|OYQ|;C2TKP z#ye#jKlCHT?Z-9WiW>9A){dh;I)oRCX)HzmiFsk+n^vMc{tt%!K_dYIMuTRg+G8!` z$PP{kg#J40nWF!Siy5TBY$=|5__egI67z$KV&jr##1f+faDo!}gG!u~CtL`2qxj2s zmyiiyv-5L=zQul^aX-wD@-V9;QYu%02$R1Fg7t(aK@nnjLTz(vh4hZ7)Jd{buhXm$ z3cXuYon%R=>U6zHTpdIR%}&{>Qs(;?Z$y}ue$58j$Gr+m#f1|r)*m9rF~X4lxt z;C<8PlwY`WR__O0&dEy)?UWL!p^lw1hMxA@kN$kI!``-5ECpc!cy!>ib z0x^+(;?A?$`Dnu%Mko1O8@}Uj&6SI9o4Wd*;mJ%(dS!l6e)1p1SE%g&0_D*7bwbVf z{kI0yZ(a_S<+pleo${v5SKl*Ufs&3_FDAe2FZRl_d2jIZ?MDrf!RX`m0})xT6#rn~Zp7`!PCLKBl!d(Woo6I_1{#@4i0o zh!iwiC)KUG2FqFv+AAJTwmKgsektuT^;T&KrJ-Fxops`p8jN<$&3mtLIV9Kh2rK3y zD(rF*z8rDim0O*%Ti$b5!2Kbpjp#(3j{6}2(9*7qB&$|k8Tn`HSLh1C&aN2Qpak68 ztT#8QH#aqUv)!d%dUJQ|&GxEV@6C#U*^$de<-iDE97YRWshZs5%e331wwkPVx~MAxxJBO9UwP)^~))eU|Q0 z%Xg?{$|hDnJ@jCEd0Xtk(|oC!v;}C z`m8Y0FQvt^;zM!iO6sg<6-r@UdU&!+pPB5^F?H$KGE=eJTcbb#ZH9iSHTQxs62{TNBw%on( z$uJ~*Fo56I1?LQgOIsCZq(|*ia%;HnFuE&TRWQ1b8|59#%-QMI%U=2H^2WG!POmx{ z=j`VKRG71$iw`H}%rpijU3U-M=|pRo#CxH_Dsn z{v=5~!+S>e|NTQ@ot;t5+wxO`U#8WwL#sRMR?qf|WA1mT?Jv}={zCO|vejU7UMQZc zx64=EvtE4Yx&FTCJE6}o!vLJ3g_5cI=6Q7s&+{*^!cVjiCb7^FI|LMCvgjPdOEAtY z<72v!I=7B5 z6d#GzxijfUCaaSdCwgxMVi3*Vp6k~=idEb{Ud8>PifK2T8~X&jK|7tFNbd0w{`UJX zGat5&LV-dHXdUnnJ^<^++0wKeJ*g79Qgsx2&a?M>C4uNYyF*Swx!x(~wA2uxfe3a7 z11V&e0$f^bdW6mU#ncd!mIK?5`bbRf{%9BmIlv6`b$(eXP~vQS%)jW_A=T*nJ{G>h zAs`N1rWMpHqGUAj@$dnmt-Sv6`gL!_V5+{!jM+|J88y}wLOx*MM@91k;d@N{)#5S} z4(+MI2zL)fTmp%DF5T~Bq4-3A0IXSt>`#RHD=)-g0g08%;9;1nnLysa^0Gby=FxlHr|A0ouV{nWJ=;)W$p1St&|q`N{Q_{*L};h%<=QjSm#HL+)`cohkXe>;9p*cg^Jk`)s9b+WdWFgp&q%MV zZQv+Xm{M%uztbbQW|>41V_CM8&@~x)BG`EJi;Q8qzZs-gsrW9HiW^WVhd`BQV+>Py z4swvn^Vz^jAJ|vB$v(6C6x}9mXuP zIL5X~vswX#wHPA9=(5{i+U2+2YXhy##5G)Optj`ag7=?-fEYlqw=5k%c-hS>?dZZ2 zOe`zD-Uv;=>lW_|!Z~|#ZdSZQFr>sl7>2_zhG`9lFwM)yCe)wVDpv5?D%?;|5!(`` zv?WYwOPCUa@;Y!-OL((N3tpo%Hxx>9L!o2|pRMOC;d4~l(xtSeONj@?%XEL?jP$~K zNqXX-!3S87%VlP69?67{m90mWp7l<96VH0Lnf0gp@@iKpuXdFjy=3Jo*H?$bQ<#kO zAPxhU2^ZT;4(?U@DSQDd`H8C-=`zNU6xRbtKY63bBV{~bkLlp$=qTJbY;Nx}(q1cD zoO*Y(TubZ}O~(|xp6rAX_mQlsaNZyxVbq36B(8SZA$2%@;yaAKlM=+1bU}({a|?Um z_tJ(#N^}fs1d>Zt5nSJuaDq(d2&g+aBZaRW8k`7u!baot8 zHLzm?Zt=|+gmg)I8{+trf!pZOB)9`vir@x*0`lIc0J}qYufT7EVqkqHpt9P>Dqz^4 zC3sj7bPopXL{3cv{R-Y@_#N6Zr!+qjO3O?^3I1$gsc2bmR>^YSp;G?zDwjXq|>w^bmNsm}pv$D60IoJQ!wu6ADTyb6&=YqoL7f;~Z4wP(6G zII@sK|FE>+-i~8+rY}dVgq`e!Y*-c#+_|RcPDOf_K+iy7Qb!CV9&$2-l33ZIKmmnd zs&l7Y7>H*>Ol5Dcyeg_Che&OKM_!%8LCb#7A#~|TaRcG)A-#lxRB601%CWI<8V##W zQx(D#vsZSaKtQ~q1Rl*SZg>ZQu+J+L{jsn6X)k0OAn+0n&u}e|c2Yk4pg$T$)Cs`@ z@MIIJCs znK}>5G`;@g2%UoEQN*SYdL!? zjq8|gawL@^T}R5r)O?kEf?@rEx9xXS5DFw=ak9dJ4^#cqOEP*)kXdGlG?R?73T!2M zP=h5VUablz5W{+7;&v3HZ|nlc!V>~uBwe6mt)&ZF7bI%~K>S}V2*YzYh*UF^+mWEw ziT>-gJ3TG>?$1jo>}rXeSed2g3!4e9*?BbB%(}p4{-C{ldaR!=L=6(V5y!^PV+hE$ zV$MU>c1MEeE=1cp-{JTIuOzvO9Ep$BV%(_pqHu5v8#9A`nUwE(unj{euStM>jGc(g z#4uL`%p?JN5Cu5)DW2C%>1Ta@1GejdWjGv2N?QdRTHOo{ex=pYk?Oc9rtN+3Wc6h; z&J)i&#Oc92czf$SU%z6Sd5SJk8xZyc@*$G;7~_UyXg=h?#VZwyKKS?)t7sVwYcn)R ze98Hl9~Y?WnxBb}f!agoW2@W{+BsQ0yx66{u?c`Yi$=_dL~mL(KTc!<)T?$5VTc{s)!rj~ zv=EvD*l&=OCgh}g7%oGGP$1|Bc}h@gRC*JHNVuD&Ivh1cEuwHt5mJ$fJMW!UmxDf} z+Cn)|I8Z0(^E2qgb44`-H__h%u6e3LdkR87vd7wSKWSN6BHWGgITH6 zL2)>)tJT7k8c3=)Q(^mu0wi+SDspnc{VMJ$IgD#yY+21B_k?R&{s3k8tGQ&1oB0Sw zH2-wa*u}F|qA|w}D?w$@LJqqz0RVX->#27Pwu~m_&T#~0_rMzMI?otMdEJn)8%(1{ z;gIE|!iU@6*;E=v;?+Rmid`5Y=-3D$gcw+4CqnC72r_}z3T8e)j4>KcQ_GBZuO6RE zmp$(~sO{&(2Gq9bSVm~8b8Li2c29-c)d^3YI_y9&8nd)LRfdFhM{V27M$~3gVipfh z1Y-|Uqqb=d9i6+DE2mP|)ky8Cie8n0zyo6gQUh8=)=Hfh*F_6yIW2lGz)C8{vc_Dsw_-6f1hXPG7Ze_K{vu{BQssfc^Dd*@riN3p#_ zS_Kyvs4vu>gOQ*dlqqSs94iO8oqCQHO$#ouffNn~Z$EkY^z_G?n>d|$E2hVG!ZvX# z#q?B48>&*9IK8(UYoV_9zyww9WwWDFXZNVo**z*d%*S^`Y?0a2J%%-Y3YCJA z2)vdMh)e5pU2+}Aqn-L59W#WS(=Vr9%7pjW@Qr%qCqC0Fr?OjGXhnRkEzgLKl?>Vs zNKZ7O!`U#Q<5G*Q|1^b-u(Cjs$3y+vL9*K1-PZW%z@;acF4gIb$x3R~fnJ>5C5}Fv zjnr_~7A@zrwdiE)S4Xq-$-7RP^jmNGoGbq}p9d2Zq48CkgyChQcKNd}8R?RKq8PMY zx{i1rNgWXSV`LKzD{|e$HXo;#L8o>_j zEkM#l^r`X&xx@x!_7JzUNaSL#bFS1C|Jd-IQN-1;r|J0$ncwy_lnavfT?v=_U5*NO_Tj2tzdGhU5Q4fcaq=oym2U`Pr6 z@;Q_y5}Gh^_>fj$xPqXDK6byhNQ@A$2aK5?1DJ|^6*QksMmGCEH*G#}#30BGHO zAfeSP9jIFebrk^$~LA{@oRPz$9T{{i9 zJmP9bD{{50y&C4}uKAQVbS7UXr(Maf`JyNYMC_xu72U zL58mAp*Z#sI3>7$`GW!O)xnt6TORjhE%Hd;*eW~M z!+GxdxEl=&Bd*}VT^v|&wXz^&Bt31B40Ql2h3oIH7?A@4K&#F*#bZRavGM}`dH56} zO7^ean9io*nASrl%GdWY3K;0%mbZ zK;(;Ra9#*F71tFz7J{h+&ZBP$j4VV`MKlHHv@o%_HqvqQ%P~Z&@P76 z2O9KKErVMcLp`ja9&QYEWc3;mc*{2ye5fO@x-oOx?JXPX_V_U1*x86hFzegn=8|FNM zzJH&t@z^*}Yc!yXh_yvBc*h(EGA)xpbZnQR6PC0~Q7K<5mE$KdX_tZ}h5NhNg{VAz zXs1i2N`|PDn$E!_rTYhn)mFJm-AAw*ZBIr6n5dm3YLqn_&6ZOyLBESEk3WZFl@6aZ znSG|(nV?RZ8ZjZ|6z3ITj3q4g0X8jNHZ6V_`b^m^<+XVVnx)gu-E^gXaIz6}^AX%= z_uJ`!vs~FZ@63Do=-t6w?fICO14uJp^pL&NF z0-y-HBS7JMsCWc~EtqQCqhY(q18MN8w{Z*Tn#u z{l#GKnnP=?*02O9i|^&50Ta%q7irLNX zh5#KI*MT@VjI3tR1B z;qUL`zzF_9MzbjrIMC8^U?G!4Kg_Vy>|Zi+f23$0mSay?oz;n&pI{eO5pQ1%VHNpO zs}R)pRa!w`=xi*2g4S}}ZHKjk8XlP+Ohpey1_s+tmUrAX=EuW^%GjiE_e1xD^$_-0 z(J3T=o5dLMJ!H3({2aDU-gKo`@a2)yDEsELxmJCKeM_W9zxHI0iIDS9*cG|C53KY( zO)CQ?VK-B&;y4bw6%5in_yzJHJY_}K2An@lrA}!sgp?ShL_1W% zh<2;QBlvWccm$uV5`En{Dskpt!l(w{=%v%kY2L@!RBeZqGR^I|X8`64o*8A#T6$5DTmV8cH zB$(ml91S7Lio2Ef(hg40Lw{lin}{H&?@}F7;&I|jdN%0b5mi6%cUUpA&sJ;zqU&RK z@;U3|-4Q}?rv7&JyHI`az3qY-9-vY*hmAH&YKS1vqy~Z>CDhpv7ciw~L045T_6`t0 zE_ILLRRjh=dn+Tq{7*!S7288;aw(XRK#-E?X z7qG{M7R19hcIt@JqVl1p_MGKpa;Zwmr79(ts>~q(DtCg(@>1I)?J}ie0Ca!v5MwUa z`w*v8o`ZCyQpvjYe3c8|v}qQDvxpYmU5@2fd0a97vUxq~!T(Bf!5x`L9*jRw>2=NP z5yOM&m~WY{C-Eh?DjQ9>jmr{ zqX^T7pkNT7FW|1J?RE92u9}K_gn|A`?K4My)DitnqFAj+n{ctEF2gmQ8mlKs_RdZu zI>zB4N9OSw54v@SW)2WDdeedvv1kLuF=@lA3v{I;)o86s51!n(VAF6KcVZmX)U2!$ zACWK6^aF*=NC1s+x@}C(hJI7MMZa0gjaBslK##USh5)HF96J<-8_je&c&Mf#fl`2; z1}8DSF=J=r_#umJd$28u@*aV0~NxSGYWI9Nk?6096w^yVFiPK(S?l@1DjKyHPH8`9t5*NMjed$jX zYr=y)_&L)94X@F%(08omO7@$MdimIJO|;Z7BT+b{3+Z5x*DT6=PNDIdU@iG9j+hBF zqE_DA%HC5^HR3oM+=6#Z;LN_(j-<^bYhjiKYU>Z`rpD9vp3*nV8$ME*|8<&Q8(AF)nuKbwTgp))~oe)zLm9*{hp8+yiYso0Oiu zptYQ5yk3sWzC!PG&P*=x3U;-xI5S~sTW#1E_?i`OSEsS|&q~mHcn4o+x984crxG>_ zj6I~m6JZaMZNpI`_z$rUz~mkrSPzZ*65RXjwPJqB>5$L8qgpgiwr_RWc{&KNX6C2_ zR{=NDf{=^dJ`U1q&0D%9MkbicjJanFqAUqNSiPI9$&zT&O_rpD+2l}XF`1nz84uc8`%iC z-a(A0o|BQ^N+dfgCBW*w1Xz_4U{xZ5T6qC{PS;Abs`4WEoXS=5xsVqNYq7L2edg7( zfF5qys1LVLRbWdmI+xKul8zGBcL6JKSNj4bj$8%03M68g8;D-D z^~(${u!{8{LrlK=KjyPHwMGl*P2#OTx_g#e`?;rJf9BiY{IfT&3Ack$It$+7o$U8J zk!RJR_Nr}gaM^lO|%UHgPU37^SQ8&7dM+8N9DFGT2uR zfU~At@1m)C6eYVh9}YV@kgn9Q1HigC*)S|IG;9<#2UXD+AUb6Kj1P@B4>b+>ar1>a zXMjq3Kz(h9SBNt~B5^Y`|@wN~FFRgRc^P)9eD9JMxpUFS5)|y^8^_JkMbtlcS4UkQTnV7m{>e=lD3-(a;nw}UW_9! z(VfGUZ(OUo4|G-TG>v5m5YKF*ZD#AK>>_Gis^$njS3qGi2YB=V-y`+)cDU5e zJyG5AQ-BNn$laF1<^Ex9A)I3c0}tl%#e>SJ;C6>GA^L~h!s%wj>u zEVLF8UNK6Is0!&FkURiokGDtxEhw zS)dJJ*p4`0p!@+Eb3SS%#@8QpM&y@n3?@fy`lC4Npg5x2ab8??G?mY(r$Kqtc#2ASL@-t}Y80lZRguXzRXFL!=cM>eQqAXS zdCM111}=;+dv6-8(a0xc7GTkswpas*5@*x#)O{qfV3d}|T&pu!qqViB4jrCF*9t33RV{m2*n z1uD}0nlVPab7MD@3^mC|Iz=#eqeP0+?bc^@$k`2Z(fSMsBi*&?VV>%v0R<=DLzSr{V^E*`o-zCQaC}JIwPnsAv0&gTKRzjwoF$IV z^NI3}Q_zr0lsrxL0+SOcsQ5E{Hm^p z%L+H2>m(JvVFEH52z&*%h0lYv##jFPu@Hh3OzR6Z@Qtr2mmBG^*x-vWaw&C6fn>AR|2b>>MO8@e4Hej zinTr^SZj8@EKq;%FnjHb0#Gl+klcZiAp`eKezKG(P+zy^N9cCPp-UAF=+2322TT9l za?ovLON!8SHvqY13cA4)z(1agwtNXvVWF}#Bo_*!nXQn*4P5=;>t|S~{%qI{(5+W0 z@4B#i0IbQoRU4XtI=h?{q`Gv)VCs6%YXau7kh!Y_&5%XuSAV6@K1M$ zF!aj)W_=M{BFOw@XyA?ljJbmkZ85DR=}Xsb18UN$IvER;fR_B;(jG(vcW;XZg6GbL zV;^YU5&WpM@y7nUvsKax(X!FPe78Hzf8B6^SQfl8yi&savp?t;L$8*sVm>t2#bm`O z$ox!GflIw!9r>$B{{CvD#O`h3wGu$0SGW7CNa@iw7<#)`*e_@V%3IkEC+D6(K(9{b{exn@IW^Ps>3+meaYW`Uci-uT#YR8vYN zioCM-K46u^cOsIn`ty(eWS_t5C;R+wZz8u@HNYRc^Pl+1K7ZpI#K`~Cp!@FUf1=M{ zbLVnYV$~CO{GXO1Zma(MOF!A?ul{GX&c1RS9gSAheSq;AzE6gkWQDmnDHP1(Om_HM zG)Y#gAViu>h#8aH&Oivw6-q%Bk~_;g?`|u$>S9Az1AUl|+}P zw_P`z{aHUcJE2L}f!}mU+n1%{sEH#tw<@W_eWJQ(5AAf!;1>mn3AAFVAhFYEm?8|s z>UKt&q+ZeAuzje!1#HQi6ja=b@@>VPIPPl@hdzAUs7mPTDbxcz?mw<&% z@SSVO`fIO>31Afun~%Aqc(jLZDe#yBMB!8)I;U9q!!NJ&q4S89Km5u{A3Aqf`NOZS z^r7>Gl|TI2N*_8$Soy<$Tj@jR1uK8}^_4z!F0k^4-&pBGr~fN|_}EGxI^|#a!*8zi zq0{`8Km69jhXLUNtzQx0{#~Di&9Y~PC_ee0Ax;M*UqPJM7s_)W5-0rnSYA!y^vR{f z>AN=t;&fVbQT-_5v@`=Y38;MW!YZDEIE8%H8N?~%u^#{M$01Ih=sFUoXa6UOljpdW zE35cO$Zq{(5hu?-9f?y&Jv~93u=$|xb;@(W7?DE7-D;!zq66BAO-q4qf-KqUD%%1I zeBIjvy>gMcp}_ad)(IMP6!;;xHRi@jflt$H_cP{2>hG&BExz76H_*sv>~LZq6H)*9 zlk?)_XGDakly|NgoMhdejJjgoXI7uB$htiRb)2}6g}UO3u8M<$>oAjGMv?qM#z&05 zf%5>24NJgSfv{!)f^G%QrvAyGO)WYcYpMRp6I}yS*FS}1*N7ugj|os&aCw{+ZGk6b z4b%ER^i<2)buxXlq2sc~1-4x}vwe`|tT>Ulo;_FgoK%Mh8`2#-6xXxlH`mMj^FM5I zVI!o`2CNPeU1ayeL zcUY7Wu;X{ab`rad&?%&SG|-^^F%7T{**_pzS)Fy|tk8exOY6}+RYtN@?f^;=uG>UqL zka-+kfa^Suq6u)Lf7Q5#h&ipr#1)^NRC?ChId{432cz0fCWj_J{*IHCy#k!3|G0rF z@--^WLY8t&n;6qvivMg>dA9UrSX!_DR8V<-r0QF>R7~fI^KH9Ew>YvYgE_J8;M@IU zA6MSxD}W^=4X?oR(eQN$mDg71CjrYl-w9ZD2C(FS1;5S+mXLjX1+ehtBv@j4@<~&g ze3F-fCFCjx*$gZ(S-F4gRu&tac3-#1$X7=eWQ8Xxmjjh!%L4%{jfjGu1T1&o0$8L* z7PdsP5we%B01rNCz@xA2Ud(UauuDWVX)T4vgPt5c!sEeeL=`=*9iUf{?Hq3|^N6He zDTk^>>hRnQ(Uf>b?!@&%PAq#=nnxt1c|=mmBU1NqkUppq2k8q`T9$K4vYKC1JF{R@ z5bQp%hSaN5OZ_Fsa+ot$X);WN$}7b2$iHODp384i@5w=0gVCSmH8GIQ2Ek!7}> zhu(`9>v%X3rYirr3^^@@$)cs`W#8Ex{Vbg2qK@A$1&tg8YMUbzTRbfxtH)`r`_fTI z?r{4@Q&WGIa@On6rlDEqCxDMEMlD}n}S$oqN^NPyufM^JplKrgHTR-UmH)ngaq!!fkD(0ciu%FlRI-OT+s*}V2mCZeob@)~(eza`dD_ss zSWGYF#7xnpzg|6rdZRr7i9foOc5&psE2bCUW0<%1__M=)LPmYdW-tTa~R z9uhO8a z3NdIAyVqO`=6qOp!(A_0*@J_4h%MUcC>M9ML^Nh~Jke6Yin<{znG7f*r$v-@w~Su7 zn3uOd3f0k?sl7AotqKP58}rg|7$o^@_Qp=J))Ao5hv4ZDT~Fsit^kb=*YGM^0Bc8S z+gSzC80)=`;PylTKw4i_E*biYd!XdNaMB^&dM>Qi*I;fGb4}hpc$q*EmajQyR8Wp{ z7o0R~?zVS4DIhY?i-DlXjc~iB-~pJzP0^nS5xG`eZLu&&zZTrN6M2TKu4gA{qQ)C+#ekU-R@v(qW~B z7uKqjTdc|r?BkR}Hb*?swZs;cI(kLrD#Z@B6!$%-0T~y4Of6fGhPLO1o?)*N4e}mX zAVmUJ72jxwT<^AhG^KD>S_BOJ$7UdvsAEswCOmF2xSiR+)s8y~KvrL<0fkB67EWMV^$$Si-flFSSHgGM-zXWsK ztQTT2?lrJRQ>E7RrpZjY&V(wMsv_uW#B?oVmW2MDN{h)>sdmqk(@tx-pOt- zWe-({IHU4tA|?|gWqdX|18#{oMXeW7Tz05vKYujGQbb>Z((J}cLCG*!0|tQiy#IHe z2r#tBh4RU_-+jZ!9cHWo-u%|T-uwBtIfz&u-1yQ%M~?ligCt!60xo*j5C{tw{b|Mb zmw~{|b1OsO6DK;F#;~U{7XX4RjBatQS4v5)@6AHXAR?tggqS3myc-+uiYGEqhV zdF=zQyXW`5`IUeDuY^)BkNduLXyp<2!~Ven>wG|CxNn$$mpT6gLOy}{ukv(P^HK0G z*J<9HUd<(p)CQGoj^^xl1=>)z8RZ5A4`;?myVEq~V)*6o|!FnRQ^xh#23VD$R=aAnlw&*4( zIB{~ku-}Nx;TZ)y%^8neh*FsBQ8ioZh^_e}&O~$`X%T&FZYYgMQd+WW)_222`?A#A><`&!GQBuC9{Sur7r|khWfCpXelL^zg zI@daAh~}6Ts`czbo=h0`z6$e)Rx_mBbqomOa)}H0O${uV9(!kN3cRTz7OBt_+nsvD z6vaQ){MH*5e7{tSfMYdlXq_YF(a+z{_Ul6Zyy-Lgd4YZ|+RpV zUj01wA^qeC96G_kj$B-P?q@F^Ax0h4E$k;d_0~~)E2kRmjPu^D4343ZL{oqvF?V_Y zr>4kmK^%IJJ5#6`s;szg>c~$SJZ}B3mGubve*EEfy6&0{?3U>(cu_@t-<3AD1Dg@T zv>i|>VNa!mJ(UvnR7%)Wspz=Ph(L<=*7e!LO;(;W++yYV!>#uGCGZ?QzhJn{$_t0N z-MJdNaYGBSQg?1_4WDK|Ue_A#upe)34WDlByuF3u zL+@Z+d4}D&L(Y}z-<>U_PW`y6h2B)}+}9fJv>zX94R_h2hg!q6cIQ}Y_)NR=aBFyi z{dlA`TxXAtw}#KMACI<%yX^-_L{G6FkGF=W+7I$ro@PI8NQZmu$4%+*XZW!*y*VA8 zXg}VZ4%gd{!|CuOd*|)x@Y#0f)^xbRe%z4`PqrU-ro)Z)&MHM?+jME!kG7SE&$w!| z6=cJ#Ij7YTHn-%Ea2=YT!UfVouEr&1=>_5ZA=|`AJS47sa6N?Ed2+dWHO766#I>!q zmYa)%=2^twd(*~ztH?vOE%OyrspYmFDGwiAy!O{$dBaUPasAWOr1YnMwT2(fClA^a zy_%kpe2RtjzXu&HpCRXX2}nE5kt*L_LJ)04hxcS%5VZk-nVX zLRTWxT+S2J{^g+!PWpnZM-BFpM;kD+9Jzv`b_T%b<@@isKP}rz94x(!#0;A{hVPoP z^0$KSdq3UCrHpM%tx11*;{6SZT7nDesU4KR{mB_g3l2t)BTup?s%%I2e*=(SzTIr# z6Vmz56=`j5IZ?o4w{+O0>wZv|ZYyto zPpj;fr)9@0h3Tv*y+Gh9d646M5N4=6j&o~y_{1wAV=^3E2yFcUUz!%QeEXYb^DUSm zK0Or$7{1+9bqpc(L}=ZngM7w1nt*{P5sLj=Q2#C$sQ-?bbL2-aGUlm9I6-Ibd}_GpYouKq+SCBBlZ}vFl9mU7#}kYb91xh z>z+7KzC4Z*9w)X<4F|O&u^TziV0F-0;I^GSJh~t*M4Z!gj$86=+0ky)IaV{}0bU8; zT!a3EoLWJBXmd3QS&z8dmVK#;w(_tM8u3`GFvyb}AQAC+?7>Q5kRenlKDI#)G{|!C z?m1?4)Z0{JsD~PD%f8+#LKIO%BdYa4A?r|x5~>E~2|7cIAwg&3OAqte9x3x??{R#A zE}4Y~YgvH0$K-_Zg@Bvzw!{)*3g>3Zx8IAwXDC_B){jWe9!L%rov76E*c(Vrj))>M z9l~!o1%8a+h_sSS<7fiw-#$$0O;}!jaC!1$jg~h)1?dSPEslrVe899jPAVbjMk*Iu zbX*~`kyv^-iiqVmKRM&XGOz0JzPs&`h!QDyz$R$c&|iU`f|eKga^j>XWp;zV+b9t?K{5}WcA?FUg6L5Am5a43j_eP z7Xfew^iBD85rAEB3<0s-g*@S#KmdXxxiQg60^n}r+eHAL75g6QaWC*N?%nZWMdjSR zJ52H^i(?TMJ|G~YLo^5gnOh~ z_xDVI!F^6c|ANBt{+(#Q9k4q^R zGJ54Ij8TM%uxl(%%Rv@|~?v$5<>EjX{65Jq|V`-`2I8WWyi!>s?`TkH&T zCN}ap_Z&^iuRQr{-hS{Mg$+c5^Ng}OBV+}Xa;MP%wKILf8gC;WXtXkB_6u`eM672ppL$y$Z)ZCksKp0k zoCS81dw;JSZ7SEw6dv^B?R{}1SB=uL^DB}|n5(pWvUdSrk@uSfn7m|zEso(Tm2bJK z{4hDwQ{}eDXx~F)q}<+Z^rHIW$Z1Kd_=_358vxS($J?6*$yFrjq9>PHREsLBN`O!y z>SSu61QLi|5Vz^+CesG!Ycq3O^zGZ$);2%-$NU(BYtIHA*2WJ31qcwk*u^f^5+H%t z#a`@U7rWStUF>2PtKRpyd&G&8bxKN9!)qEcvm(MH!sBxf4-bzB+$x7ftQ4-yjB|fQ z?x>v+C;F#+?W@zbui+Y>(p@E`#X=x9sWNdzZDa1pN*Oe^2EgR6TUA=*ueH{r7c2n1 zzCTskP^Hm|bAJZ;94#Tq-CWVn7C2OR1rr$)x9R0ysDd}=vZ^BP!ELiW(^ie^bR%M6 zorximjELY0BQo5?>YEa2)QC$NlM{w)On&FF830UpH77z80~&z~p$ASRxk$AuHLQm1vK%C>V};sAA;s%W&x^0snh#PnWnxd`^p= zGzV~@AB(4jfe9eKt^LAny-j(x_83(mN5-Yj5rqNR#f%3(IqCX7O>9b96p;fs}x$n~VBrW>#FQE%ZlS^{v&1G!C5xAVTUSj8V~{xk0!thH} zJ}lo`pg{<)k!Grrq*axP_`OT+R>16gMiC9>4y1hD+QN$Vhik4+c6E1#>5QpqCw#D9 z2m)1Uf){RT?X6>q3*aY&rfgmSZyff4k!44~mQLUj01?QjG~%+8#KAGPjoLjZz2{ya*1qS#|vOs<1_%!*8Q z?uy4Xu~K>@SA9H{D9EegrnWyAa-PtvJ22}L*;!XP(Ojc>XE5)Y?7V|6?~|I>RK}A& zx0+AV42D?3U{LXwi3a_8%F2~aDB!!QbnTav!9Hca0{`PEMTeqKyQ0{Lf7*&}iv=v0 zIQA6O$6-QrKh)z;?baK*aOo5^<>Fw5e1>#QQ@(VmO_9&|3R3YyUJtR8AFYF>fb zi`jWS)LzoO2DO)b?#)4sPYMVJ0kxNXDW~l)cwB#362A5BLTsY41$S4(B9#XS51YTa2qb)-~-7}+Sow7 z0R{`c5rU`EJ1fe3>d>s{IK0JuERG%V4|AfUn;}sAa!fM}2Yy-94AX&Mj%~*F54CLR zG3+9*B}>;fEx>)%rWWR70}%t}6;zd)JCKDr*~x zM8<~8v46WBUu)|zt-G0K9qHD~+B#psIAra;pvCWbg5!|2_XC3OXAm4i)^>@`Y_7Cr z?b>{x1O;Xv7(oxS4>eI>_F*b<6wE%-tOB!-va@=aeXMx}W*=wg^)UNH^BT-P@wqn# zv-MVvFkA0SH3YLyT~Wa7Q!Cmi%nl~X7JWCF7mER8fv@W`QmqHsXP*2xK=ygi-p@V3 zae(ZLfZ!Jy1nWS?M@{zvAlg<`rehPbwqaw-k)r=h!)GYBFSUl43+XR?4KQ=7XJS*> z#WO(*e&sS=ki&Op1d2UeMcg(bhu}+K$4E-s`(?{8wQt?2(SZS#aM|xeh@dD;q3lmHGw?KUbGdA*WG9$M zT7ToRx-pLQeI|`E1`?JX-I z$?#EHpFBQyl-1RzcMU*HkJeO?;iD~eid&K&qlqHJ$D|U`ptKAx(ySuGi?XwN89r9? ziVPo{o!86oahlg;_&A>%yme^LT#_GeW`U=J|t)3LL_#{to95Q@zK=9-Yf{6@wc3?@az+P;H;8c`A ztHoAu+r;InGgM_dg%*CosYAbvK5MF!vnH$Q4FG+53h1Y3{nM$*PDwW!KtEMe1?Z<* zst5XMnkYa&EtNP5=%;H|0s86LSv}Ct(7XclGqUq~pr5IE4d}EjxG^v#;hi~<>wQmW zSvdmzEMKZ2pf7Pn!LTJ(v{9h17NEcXIDkG(pbrN?Kbv&xfqu5HU>ra{Cus3Gp5Qou zer`bU+zf)Ff$k>)&Kt7@!e2BksBOPMttRvvfuo~v&Y8nyU((F%h*2r42E)8m#!^q# z-1xGt8GdsZewdhQy_5{wMC7rtS}(1;+Qny2sP*#wNxIg4x}cn=ofbhk&pJ&b#WiOD z9*yeZgT+7APl6Dm^R=vq(fLVP)c_Z0qKMH2sl-uYbfIPyF}g52s~4lCnpebVX?9*O zMi*&b6QhfK?#;~?7h5@s(Z#-0Lt=D^D+)2X#EL?*G&ElT_{AY^Ui zFVk8Cd&{f|Nt47zg%N1}$Fc z362AM*9HWy%^;YGz3Z%y3p=^a3Ic!5u%r&Bxo`No-b!F~Qq~~N>+8xuJKo?j*_P%F zVHT_fX2o+336=skGW%h1l+e7<7r@&*c-|``3IWyJq}9ZT6Pe3LVQ;chu(S}}?bP@z z%qhP4H@lYED&=NhQPAOEL-G3(tF%O!mszYza!>d4Q@L+(^ry#Vu4-;cN|gO(5;!;E zZ?f$u+e+}Cqe6t6RA$9xh6A`QrdzFl8ozgI(mNN%bem?78SFNnY$J8MCW@N4y*}{{ zO%ye8M=EiYnz&Q5iki4HJF8a{cWGWx6L)3j9dx}L*1V=BhJ9{75Mx++cUw8CiMxF% z8xAV%vA2HiaYdmf?y;hcs)=QyCa$=(B+p179wSf__mXbCnz+|jFb*|wU(n+FJV6KU zEtsP24+!3$L2$I15J1qpiXu7@PRKK!VF7l>;UL%_sKxOZEby=qwu^Wna2D0+iU+hV zI^xP$`(6e8U`9c#2-`=g762eh@b0LGx0F2vkIjL zbJf*8S#-wO+r~J1&TZpi8XChGMTA$$epA`S;yt95=3$1^zQV3nq4Y$)`jBUq2dEJ8 zr5?6YTz5U}Gn+6zqKP7mkJKkVs)-_ukERkw3FBj$RfO@e?5tiGAJ@DhjE`sM^}_gs z<~3n_!sqsV9YYw`SUC#g8egg*VSLgR1;3uOqUMl6x3LgVs;B|6d6RzLG&O8DwYw%TNK|cxnp{px@;eJ00|@ zk}}=)su6Q`88qW-nn5(2tK8>?cwl%+bNc?Cx!sk|Wcx+V&aUQZ>C!qFR= zRdDo1c26maE@<&OPcT9LPe$u|0m1h&2qtKCQ6NCe z`&y_Eb9!95s|~-^L${3!@Z{dX*|25->N(L8>|q~h_W_2XccZ_ju5<(NGz2e(;Q%v3 z;%WKSZ(^Bl@5PQ;6vA(nYAW1=R<4G&dK&< zxz@xJdCDLJEBc5U#?ice4DK0R-rQbo0tZ2RZ#H{M%m8&n3)h+sL9cY7|B&I5>>~O)j3pthSo_^xW%&bi$Pd>3SJB2)%NS@G{`b%N+^jg>7(4r*724g?HmJe5r z>q(ZYMq|Kw-xS(^qB@Y=LN6r#j|1V&)xnX%0TN<5Ct7z*5qo07hW9WAtp_m>`9SWG zRVTtHX?xUoA$I>N9xu|cXIYvVlh{z88&Z($O@HcIWS;*|twpo2F=;L0#y7V3qJ@x< ziIcjUn(@Du*209gQnA!tDwT*NUjw(XvD0OjKB7l~3zSr3qYyVd;Qzd=8Mi>fK1T$v z?quh6Cp*0h_L+`_?1Ft}%^T3^6TSF=?pxt($bbMA1_`@}?0RHgoydLmJXkG*S5kB|k0Dq*F zBjAtpr5XbKLRS=kUuZ?iutosCj`K=w*-H%F;7P0zTs`I1X-AQ6J>ZY>6^sM$M+YrF z+7oo3+XBEJ6A(NmgJ1&q$sOCcdV*PII8t=G1JFQs=g))gMcPt9_abX4aL0j$IzLuZ z1>MJ5>U4+h<1|sweOxNhL)M)$I9{^~x{uG!>d}3I<`s0Gke%0~`$Wxa=swZs-WdxjmWUzgM~ylpG&&+=snk0Fb?#d7qs|1Ptc)i3($LhK=Awwf(d%J z?%2xJ^RuA$0&R()_X2AP@M-A1P*VlH7g}n?p?9e!3VN5O5=Wu;BF!r3y(l}YNAJa& zSI~QLc3zL(OEj;c_Y$9bbLhR)$`QSn`ce&{_cB)$=)KH}l3|UYcZs0)uJu6gVxo6( zfZoeVw;sKh`wGT^-l3qyL!O{R)fS+4SwL`E2EhcqTXjrw_53X8y+T_e=)J;P0(=^J zuhdjQ@0FHXcIdrI69v6jr4mP>ce!R2^e)fN>e0JG^9p)bWasthy;}1cdaw4mH;3M9 ztQ^sMjW5*@dRMxlK<`Q`N`^Ip-erQ`qln(6MDNl7z1Na%J$kS86^sMD*99%U&J%Q~ z+5+@m9}v7ggJ6Q*Ngcheo}UH1H)u-)y*F4(fKNm3jhZUxz0p!*hu)hsQP6u+DsdEg zZ`Q1W-kYJD@XL+>Pt0*-rHPJp!YT_N`^Ip z-c^F$hd%*&R}#G|1N7cby7lP2-B&OU^xhG)_zq9dp=t}zduKrK&J2PHdV4#1Ts=Pv zdhgPf2zu|bmH?lI-eFA@^bT8UzeDfcnkeYKJC!&Jz4vHVLGL};Sv`91)x3hIiJh=!3k7}Zz_t8}1DD*z2Sp~h1WoPy1eO&VjdLPfu>(Tp!<~8&_;d5^ey=$x-(YwZ% zY6!hgx}reulU9@rYXrS(1-&193iPfade;Q#eTsDJ(fgFIU>xXuI%x6Jo}fe37NGZ; zfZ#J31QYajca&T`KMQ)F)s_f)pS6|%pN8J&G*!_1oTW~6=zU%j1-;Lw5=WtTt!5SU zuFcNs(ffkt74*K4o!6uHMa^sIebMLM9C}}}azyV-zEnf#ec2TSdSAApWLP8UT_@>e2g_<`wk5m7Uk4_ifE< z=zZJg-W+=0v2sN3JHAvy=zZ4}1$y7LqGVVj=-nXby@tAXJ<+>9K<_%ztw--VU%@!g z`(DuE_dLOIp!fZN;QJW_6ZCd<1Y31K!(QA6+7dzU2i6kc)6n~&rV4sLv{b|cTC{^E z3VJ_EC5}Sx$C_2p`*C(wkKRu-ub}sn?7SYm>ou>TcfHTOIrM&N<%r%-eW`}f`DHt7b6>$Y(ECNu;x9bGaiI6hfZ&%I1QYa5 z?C5m${4BcnD{YCO_bY3O#j9ek?Q2aH^nPurh)Y!TZqP(Q?}k+3DD-}#Sp~h{WM}p0 z{Z{h|dcV!i>(Tq2<~8(w=W}lkz293oqW61Wsv-3L;EDphKUmR5&s8oF^e(2)VKLFW zI6&`@q+5^PAAJSmK<~z&#Tz|AhpH{G90uLX17N|RJw1@bIQwW-ZV=l6VgTZ2LGR(( z5<&0b))I@G1$vLrR6*|%mg)nIkJLm#?~$p*QRrQ$Sp~fdv$J~i9;JB&y+>u|_2@lX z^BQ`O_PIBQ-easB(R++9)ew3YxuO`lMOL)ovm%1t4dU-5dY1<1J(hIq(R-|~U>xW@ zE@<&_p5Qppdwf9f_zZ%H?hV43e-`wfpe+&fo?tCuw63bx6E#)Pd!nWK8<9@ZL_zOK zsl-v}Jz28~dQZ;I>e0Jc^9p(wXXo|kJw@{xdQb7WH;3L+tsK#NsxQ?LdQWpjf!@=s zXrtlH>mbSUVE)xWJt2(0Eq(XfngkguH63yvz~T9^Du?gYcHJ8#X^y7UGJ-WxFx zz0)M|-FOGA8Mm2R8%3N&h#}Ryo|!p6b~%?d?_+;@-~DN2Gvn^@h->VFuk})Q>H&sV z$3yu4z?d=D>D$9DHBRtg;H3!<6r{D0rJv?`AhD7oK{T~q@9=@o4S9ca`ej0`7U2%` zZoIE>S(+ehxy!XWk><-SRcFId(mbSDMVg1QvwCS>rg=r0mu2Vm(tL&HHEF)W=iZz& zUuoqi%~$$T4N3D=t|*v%l@)Dt!dorUyzwz!;zDU24y1WG>DEj0a$mtXqygGwmBF({sr{`?S5D7Ua?`F1ZjF!8^=o+JkYxdm500VY!pMFxPQWRF! zQCPWo3bXq`5UvddYQjT^NP&hl%3bh{LPxzWd3HK+v8=7vl*+b9A$o$FV&FD z-{Oiw=5Mj04KL9|=2v}+8GI>ap06akQ1x3$w_fIN^%aam=5GsHe48gY4w=6_Ab5KQ z!9?cW5)Ej%LksPM6MT4t=?*LA=ZL9zIvN*X$PE|BeWz7{`!-j!;FrJBbGjJGIF>cm z6CrxPS?+hBrgu5b;;@3`T}pBmUI@Xn4R`r=>m&!rPWSU}S{SF}&QK?V&=C-Ge_6(` z(vCfEB@y#Usk?nY4T`2F{(FyO-J>;%(SDEB z$XQF-bg!n061g|k9yInoO%##8FO@h-DG($072M1_U3?Aee}}O!GKFiy0Jm-SWbj@Rb$7WYiS;n9vTNnS0D?`2T+jeO&t~ z=zrW=vE@_f6WTL3g+7rc2zgqg)rmZ8Zq$Z`MIlemTG2+Q&_yCo>p6uEQl16_d3ug?>*eV= zU%@!!>G`0=&wGO7kf*f)!L=C#6L|`z&=<6jO`$JXv9YGm7p)4NLSOW`F~?#>+Oj26 z=u1k{rqGvsyT>zyzN|E53Vqoq)=#0BL0gjNpz3GPSCoRxps)CD{+u)Dt6HPXps!ku z$qf3Mriu=EE!7@K{D>xs#E+yBN6nzGYgUo?*R!*FiGM@$ip0N>o!3kJo0``o{!O2I za}xiSm7~PJ{6$|FIQVUqFv3ExG z`$}WFTEOooG~{+P;4kq!r7hsl^HgU6f1osD`k6j3iqJ@2`gCQDH{SI5W(E0Rt{TOa z+7(~6;Btmra+UmiSP6EHzPj;8Ji;Z<+vV$CGOC^8U*5x8B|HSw;Rn&d%!P?-R`{^7l!0UN3*^HLuCvdY^l9 z^7pBgqx^m9OEn~apShwKrO&J=N2!sRj@{v`sC{ulJD+l%%BP&&iuH36trxz}J@s)2 z-xoo1zwiVdsJ6gM^<_Zt%M5~v@U?YJNa~4kiNXdxpaqoqZhs}TYJ>OVXl@iwi~Fjb zrPcZBS4MVgzDp_-EM3X8f5Y450J2}%`jl;Gt92-XH=u}Iwp%K{az$|=pkZ_*qrol~rS<4dR%bawcXPA~i@uLsg+TYFANxko;pS?wEVbXRv0C9n8p$Sq=Xtnb(Hp> z%)&??<(sL+z4PkmBpV!JM<=a{l5wO4jN{@^xjV7HeFRbJQp5U29HZ2sA=!vyLh1mN zZ^WV`8yc}F?5YQoG$Lpd9#kD5Ox3wt#dDo4v==N#75iCn6Q4xwh?|fJ53z<}PV&I4 zdfx=|KSRjrvDznD9vo{u+R8iFj?+|8l*d`>Bp0-Iye5iya(pULMm>DF=LF3v=E(`! zS-p93qUIIzc`1ej^@e9zLX!tP2G#P*cF9&ve=4} zVU3t4n4e*vh=XlC14q^efg`7oZoP$aimzZC7RsqXi%<0g6O8`kd+|;S2%eTfFtJct zI=t`rbS)H@K5nU=ZiRYnvkZFR43`Yo@)Hf5YZ=bOJAk@7yQKSY5YDNvKY@6OMUkI1G$?G zD}zrh?lOcw!?*r@TNLrNp6Q3+QHNQ7MoE0Igx%W z@;~KP@shhLUW&wRYlH?g7-};WdzN+@@1MXeay5cytkdq1XVfJNsT}%IhJu+B{c{!1 zb7iX8B|-}?{qlLTC7!<;sN)sf*^;aDA@1Es80%^E6a}J{q7Qx87qmg+i|)y_c;{+a6Yg`Zbi3bRP2PW} zSkX3&(J)*$=ZyaIlz`lP`#GLl7xU-5gpQv(FfK#I1=Ay3e;C-*(-0E=XNEZdE3KvV z6A>;E*WUS}1s4}C%k5QZN5b|)vvTjWmHY9fwsd&#@FNy3S{%>ApOAB~So&llqMWv8 z)9@!43~g~c<0fb`?^1fGQ0bo!nmOG1+}2lH_hd`ywLJcW428I#`#ad#-Fa`+!yD^# zNeWRo-?-v#q(9&KGa-2m8;t>w27A~ld|BkaEan%^DNFFBwzhjgr5`_Q14G}pN0RcJ z=(%qBvPbTj?znTWN*l(fS%@gFQ2zx<{dr!ic){rUY1iVG>)3F7VNycg`?)YIfzEGV zTiPQxR`#p)w$$>+{p2B{#+D`p`rE-o{$0#2@2!XO?c6J4{Q};@$Xq!Ab*!AQz=w!j z#2QT3uDZSpJ_gvu7g;UsFp+ZYKJUfW8ofjNV$0NKDC~5b{oB_rngo8e$T;>5 z`C5UW)`P@5A@8FP0F)hzIOh5N^!k4c=VjWxf#7lU%dCb8$%=@RD2?oD>py_lKDl4I z--h>crO=-|j(&MPfw#HobIR%88vw#y`68h57kqHH3i2G zf-n=a3Kxp0U1jf|&rwieJX#mx&GYSRcl7dg_w8%T@VP5K7vgg^KEIj7YuUH2ormAQ zz~>G4+_`#pgjaX(ooN=GH7cb53Q|ZNuiAmj9E$xT< zI|mowu}7)C$X3sZzL`|%Vu+XP)mu^N_Lj;_yfuWsLun_M5u(obwM>Uv)brX4iYkT6Y_z+kXg+^r#gxiaZ4chB?_S|SbA?ih;+b(j6~+}t zWa5-^#b%~Tt@SUM+WX_mzL}5qCGA|yb}kOud1cVfV{a{KJFgt8odD(bL$jl$J&e)8 zTL9gB1fXpN8Vp8m&G=aDN!))30C0%!!&R;i{TS1^=t(Y~13N?B0=O#a58Wb}ZviB{ zmRt8LSQjrtPlWYL*`=jHmzD=zdJe${q5zlIbqU&Gh31ph!3v)&$|=!3s060g*1Ve= z^DmE4Ibpuq_eo!RyE^QLqSKJsQk}aG)D>o6qM6XG;Uv(vS{PiPClc5Tur z%uX%I>{RDVOPVvx<}g;;Ny2qm&AD!LbChMOa-d%**ql2zwXR@n4= z);E*26*pKbO2PDt5pXwDcdtM%rDy2r=oAw)LXo2UzW^9Z>7Bn@utmgZ}H+Kw#tmSe?es?=HlOAji9)_Su2QQ zq!BDPC%m31V2NjDIFLYg^RIVKO~uo#ay@~ey~=l4mZh5*n#HXcn#Fjm#3At(lCh!j zf^mzdmsmz#FU$PF*(2_j$4;E=-|BkauL65((sO4s#h68ZosTO0SVjeCQk4I67TgxF z;5Ogn&9PuT(YZcA=j~Z6xZTqm%>vBQHcNWNcZcu1DTzCh-V1{uy0jDag`y&ee(Gr7 z8FckdBi*G=h)s<4AV+&J811{Vx_XzV7j(6)J?@GTVR|69`MLt*!W6_elVDBY-9Z>h zsDtxdf83uxtgvVGTsk_=&F$Nno1!W4R0>HvHQt3Q$T@g4rycSVw}T~9YjB86;?r|XV{pCwfa<MNdhWK|CFW*!wpLcODUH)!uW`!IDs(%LcQb~xFDPaXhyHkmS4Z9>nm?3X z!0HuVZVXn6i5x*0Bw-(UQpdIVaxXpxhF7Wg3iEmvIOgHyfL=hPt8WD=L-X-;Yq=j= zskNwmOx3+~6QIloiIzyHH zecFOPQTBNH;XZ3c=M<`XnDqOkmZ6)%fMcFY@j+gh&Q@RShbj)ftAQy7=GXlmPWJ+55$WT9byquDmw5lR<#F~ z5yD=cUj4QBi})22_OG#GvP4V3FTUfA#av5u*ZooH4$u`?#XwKz4@-72+a~6tJXSpe z@eY`!u~RpboB0ixH?_qR7U2DXcn7-0Fk1b;%P(@nHppQc42JDNWu7c|ZaQv?T0IXM z7vad{6pZ&6+MA4F?Yc(a#2|)a=RzGI6kxO1hUu|e9gN*-U#pH?XM1&5ktqVT`U{{` zA9#S_{g4(TW3cD(kQKzjYPwTY+#hbmI}al9m7T;Ig@+YR(%N85&D~e&{|kP~zA9LY zKfyHwx2yVBWwxly8j3L|ludK(#5{*oX8r|3HZ$G{?y<^F&~spg+(pUmlTMbc#Nb^uFKqzJDlg z+bt?VN5HWbb>K7Z-Ysh7XV-2~(SBnFgL;Na9PF7FO>#dL;m3CF$71}Lu0ICgpu0{}9QDr9gz1)%vnhu>Vy?cLcqML8>o=EL4IYhASbLT3d7W%|Xn zg4wI~-J))HdM#%j7eIqHV|k`k_Lz=gE}mJ-l@{fzk6C4yN+pyCm8AS)pNeB(t?gxLOa=NQ#^1w(tp;>0z<`qgR;Ij&?m09x&t?pM;DN}h0?(#7{>9HOV z=>n9V3OM~#iUCM`x{lLN`wZYTXI%K~xVWNotqxemyKIlwJAEScrd+QfW~ zwf0gP*GmKA`WZIQrs+ZF-g?H`xK+5yEg2$EzGnd%7I?Ovb$y(s>&IuUJa*0;TKlnt z)Pakq!CvO#GoFUHoqmSY%mfQW!~}D|3nO->F=EFj%O8GI_j`}J-|(C{a+1GOe^0ZB zo$l%{{|MwkGhF@hs@!h5r+VOqV8llB0L}BtP_h$S{m*-<AtWC;b4qR(xCQU&Z z8#y@r+(!R2Y(w#{sOtqccsr^pcp(`)f5c`IETYzbz>TqAd6N2K)e{Q_iOUuNAlPVv zUzRg7d}NF+#$M2-u{c7Ojsz@yF<|LN$I=(AIXxj3;X7)t!s&)pjr9$CPaQ=kkS}SM zMD@L7<*}c)srJB@-5}!)Az9Cctq&UZa?r2~hi$B1_Jk8#wsQiVacvT2YWqa5IQE){ z;T0>^;dcmQ?_n^H;MkBHX3K_ymc1IZ%zHv!wJJJ8mdPW6KtC&^ZtUl(9(#i#&CVV2 zns2Om1YR>z*w3u@2yp#7_S%4cJvMe_(Abfz#*X+J0yZ{##8xG;bs&js?MGxQ%`|S$ z@Ifyh+sbW9$dyVkPIsqcTY21jj&_`DQT#OcziwUDowL`iHE!n&^6`dd=qoL3#&u`U_9?gZ2-Z+B%4}#seHbr zG;(pCy5KF(F27{gY;PyoApUPBmH4$f#2>SkL|?)#!*qr}3fK^COe4m%3=w9A53HTA8~h~ue;RIuKd>?HFY zX=Uk#=IT4v!eIZ7QC<#-?@C6E3GGKaEX3_yUkW+FwEp=ij%^x{YdAb>Fg$MT*Rc|t z{8nJLkqw4*p2Hb{88>qzJDk$JPfN`yk-hmx$FAj(y;j(?oh@sEx4#6Z!G z>i8$4JN`*slhiGNv0krvW!xCAXydlt^1E@9IyM!r_^I~a;uSyj&9q^6`2Q@)2A%O) z(kke7)uVtjG`Ykpwt4Ry(B>=0caE|~ng%dNXFgZzrno*2se`yzz+WWU(1uBICi zvDR)ornI$E9n`BE#hXq_*uvQ|GAn?i4)<%f=!fPzw@ z&cD*qROcUToUH2ntAvI?z0=KI+r!YU-3`~u4j?iN7fgTkHCVN^-UZN5+McUtF0kmtBEAx7VU8AVH zqo`xJv(}x{4$yQ+E|O3L;`5OHpU?22ldimJ8W-iJ7o9D4k+1>8j%fF$j!f~ zDw$rfyvIIJ5RLdvG9H(oWsy_gBouT!T6KT)neH%p=Udm<{#t?S>u;0BVqQUsT0wTa z>Kgl9s4?6E?wAE{UNCiLo(4137(k^hvdgpFMqT` zNk|)p1a2%5kj3of;-HrsGkUo(p`g8ll{~dpSP=JDqj)Q6N2fTQ(T={#R@xYR1^(l$ z{M?Av!o%VBF$SA3cVoU~zXqF72EH3Kkr#~M#odj$1HdtotLxk0R!q&k!>wRoj3@ij zOWC)jLEnzhvJ`(mf=472v~O_4Pzv>RV{bFF@d&D0QR#ySf%k3I!`K&eh)b{|tx-;N zjx?g15uJspzAUstnWD3lqO&v*ouiVzc+oj3q2SPnzHDDhi_X!mvHki~^U+CTO>{Ku ztxj}~Nj3JEq^i-PGf2h{28>^nH1_eYOz$pAD7eNt(HY2#=o~&c_=`V^?n%S@*i=i7 zP3TxlYz}Zn{YtWKWx%@QlGdzWVp`|8go$rA;wKcB9GpMIdu!7-wES|A1SKn@mJ5h^N7|eR2Zx-lMZ>x6~XPDCFlMlv& z6p2?p{oL?LN>T!BPVy~q6`pKuRFOK_SE)uF;=}3|N#y5nz|X~6o?c?kt&-~mw12hmM?7!eWJoyQ8d*C? zqh8LpO0XTlP0Y9h?!Loh_Uv$jA`^i*Db2HWfl&c7CB*Ckqk>&RKkwBLJmMZh2LvzF zBEq^0ExX^7SZef?bxVD6z`8CoJJyhOYXa6?q-DvvcM<$3G4vND6qI!n)2!=Qq3%?) z>tZcFjk@__D+Xp*H);|1QQWW6vEmSoc}9s#tg&!R^X$0k^MhbkSP*82h@w5~lFViBz$IE;-ZFDc!#C}cym)9o_S!K%P zA)lPVQm22OZ`{eq*YiKHcW#E9Ax$DV_ z^u4|K`eZ(pME-RfnE?=hwh0E8anuP{k zZ&a0$*ZbsvkrRz`i<`i?#ZAc?`UWkVQgSyW6cj{qev{^k^-4j+Jr9D)f$2uqx&A7S zcA_Id(=^~oqLFV*I_h{tr3Sf^1v+|hQ_#hmd~O?-n^Rr9*(V2G>|_@`Ru-Y7f|Wt` zco02yAXt_3_=YPDE2|QMF54|uBe8OePZq352hieMElcgMii2A%8v-3%A05Xm5Zz6D zw^>QBDJBeVOG+9H;w%*0uEhiex2M{K*4$w<6$N+r*T7R{`?u8(@E9s^qW*~4=;c(EyVV~PTaCfSQcl+d^hjMPfgJ78h!BTd3 zX#j$Ik`6!S6vjOXK?j0+tww_2UY{%=aOU=XmZkO|3WEDA8*CWY$1y-~zm)`+CJ_Yp zCnXI8ld?eYfEE)FJdkP=K=7c^R1iGqlj~Uo5Ue3j)&w9}tz}anSe;N%5JYf+u})J&OQ>_2kL=00d8I*%Sz#N+>7@T-cuLQ?@2}+I0+bq)k0?C?kcg6EPBAK^go zTtd)+;CZW&Ab8#<3kYNh0Jg6UTD;b>w7Z4K3#k^r;FE(EI}gV&t()P%(0egy;umfq z@?t_k$HX?2gKgHmGghQ81#NuElQ6EnoND9CKH0U=JO|F%i0kPv@WEwOuO#h!%Wbc| zl2FlhCJQD8?X2x)l!8+#Gq9WJylT|l1~BG) zhRgj_hstY8GS9(%%{SO-_>mM_MtqfZY;nVf15Gfo0=B%Ku;q(S%%SpnLd6YVT*9)Z zXTP}ZU+8$M>+~Bzr{C~pIc{6*MS3&n^qZqP{Z^{eZ}}?6==4$vT?jh;cG79@MS44- z;yXPJ*JMqUt$=B9X!D|5eb}*q%egqe(i0c36;tYL!eSVv<)831!Zzx(xL7)}z#n$| zEQIi#RJ-3vYIJ^0LrA1CPD$90g6mx?P9(e=Fl7__vIT@)%fbXfJWJ(E2M$Zi7bsY~ zvjj8*!n}?(aFaW#J$s_LE7$p&k{cV)m-nR!Pr&|owl+yR38EQ zvCy=0+aLQT>-x#NA3pK9;QaU`snXx55X0|h=eB*72v*0RTX)N^!UA5t{J}m4`3HuJ z>6vbXWMeO+QuuSmAg$Lv3*6TGiU|N<@l#EV8Fuq&DshVy&}T|gM({Jw4yScL*Hjz9 z&wZ6+jNmXwa5xyjFSI;I&?}%X5-RBtMCdNu*ud~!I5<$E&n?uy=pp&mDihM^$lfot zCgIzcRzr)M_rKCa;oDcK#4YCA*Gf|O_O+30^~m3#sm8YrzREhjVNXYw$J9?eek%;Y zK!2mEv#>{K8Uvea1+wjsO5a~HX7O*e8e!VEMqV`n z+VGtw3e&zzC2ld(zE_gMwC{~%qAq^WRAbr?zREhLId!pyU|SP_?ME$7ru{f*o5?>W zRMKFZRNZ*t?FS!#(9K>R^gigoGH3p19}2PDm@gMOfDId!YCmQ|K$DNXY&4ohr#oYf zxbX4dF)#Hho6HV2%bsjGo>=?53$MlCUWCDB7*p7q-2?&dt+^H)t`z#JO>nvjfx|aV zpaYw|xq}de7s~|=j?NKAM=ogSU_*`=O~(bXWZijjq!O^;l_RZi^OU+vFBT@*5WKR` zvNbWA!LlWubRam7;C9*;P>uQDm7d@6B^ zxpIP%6t0|LBonTjsHw)46MdCqaAhgEvNYhzNm`y`5EL7Hgs~Y;h`aiy3x`k`#uWVk8rWovNwEuv2}N zV=!zb8MZQD*lAim1*6jvDrtsoKg0uj@f0i;2B2Yc`>((Zj{RDk+Qsof{Ivy#0(tJF zMNa&+t6UpvPB+$|XkQ8EGEcW!Flo3|7xeM~4)Ajh+zp$5R1*AA!L zyFtK~e%^uL{5og3)?&eTmhYQ0LYHW&2+tDV7emO|nkd3^b}Dg;h36b4DZ+EksMegT zsU|$<`YOi|o?!~la3DPAY5A1!oR?6k7ak7JYNCp92E#p&64)rR@Pr;dUuo@#6LB~w zOWWjpqZA4V*2e1uruZ_#FSsqc2X+p>tn87)ynyTAun?xeBp_5FLt@PHEBV^-b}JTs zpkIP?-I8Q#(nNvAMXAIshQ`G~Yc3wunoBg*pmB+>vJM*VNX-bLF%m%IQY}wt zTymFrB`!^ND26muhGHmH zCx&8~CdyDOOC@gcP+SqT=893Rxl&VYD6aHX)(wS=Xt)Pl6GZ;@E62ztN5x66&i)tV|}adoOrjKwvY zC}VL=DshX)0*^{E?o@xYd98bg0Z+x%X2Kwc+9NU>k=yU z8qZ_R$G>k-M&m|OOwYKs^adk?6&|8kdtl;fSVUdJ*l4}K6j^Y% z6%$C91CYB>2-|V}8;vUBJjG4noo+WtE*{sv$+F-Kg11<39vP+vPQMDm9^b+rJnu5Rv1#3$OZUl*d0g z-E?>U6G-}00}V?tW49sy`YPM(mF6PDfFkc|y<2ONYy9uF8tk|L?sRFMOsqYIU%vz5cby_#3}cdunqLk)!P(?sFleW^sx zKWD#;kbffq|L)hai?xHf3gy}nhsP;74`|tlfu9dpnU>^L zfM_T#a_Jb^(h;9HRWLY`p9dWpagxe`D9#h}mc!goJPrA6%0t2eJO-`T?0Iw4PfB$2 z`ANwM=!4Q4eV75kY@C-Kv_?S%NG{Y9B?}AU6Tjt8qTJ!9f!`E=Ox73?mAk)~d9~{> zmY=IVZMIL<1n5KZTI!zwz#rXgonE?&wn%_MwGbliA*(LNMj@ZN#)SQluhoXe^-D`a z59ug*)IRK*j4^uH3d6%H=n{7Db&XArQ9c->0#7}wS(1zMKY5HE(J``ftQ?~$)kmyV zUbzKBl;|gUay(2lcpi6k*Ou;h?jTe=&sB5&(zkJ`%GSfqT?k)h&dZ-CUnauCCSP`#mtQ7dy5QxKFQwh` zH^>)Ut^tDur3U8ZZ5`FEF|ul`lKa%i|mf^7QVOUn^f=#k?$EcAA$TkuS67 z@stJf%$dgn82GaDygX)HeAxwU&hyLMd3ikCh%dX&%Od~;U$#aNfPC3%xBPkXWg9pN z<;ySTlli|gaFWaK=@?{DdpHGHtRi0y3joObXepfbC64%Toem<4Llg4sKLpTPU1fYCM(zl>yl&(GhB3IZ11eSCrn+M4$lvgaT3H`)rV1{v&X$4!P` z7W0KeGq^uH;eMrHgU3$}9zQ3Si}D$lo4C`87l)eVcY}jz7K09E6SyLSrelmV_rgS2 zE{o;r7P2un1&JJJSRc(zm^$Y~t<~H<7(KuS*>x11=g7HxIu5j5Z7B%G$$*1D?yJDZNS$Z2;6%_fB=AORKK;-Cp_ zI);kI#3(8np8`#Mii*Z3RP$sYfvP#?C)hfWKy@~u3fMhe$m6!J(Lx{U42+QI3=U5T zaO3YuSV;1-L6|i$8Ym|hfAC;8cir>Ec|X5L6x1zzHnV6jV9ET5)d! zAT&);G);~|RCezACIdpQ^vYIF_6yz;t3{PUZT-jUqo9RRxoONn z#yyZS$oP~&#%GZ-f=|rD_4)^cx+<5?9hMtC5tIU50;b8J^3x5XE<}olB`~Se{Y`Pc z-E=|@hZ4@(%8eJ6xLxgKPD)}^Ks`1F*rcWs0oi^GwP0a19QS0ZQm-Uam})`(o(wqh zGX^|4wGEW1X=deT+tl`}GG4>N-+zk*EdTC$jA7i=RA+Ih$y7(E%>}I-ub9v!zyxCm z|9I?!9kmwdtUTNoh0?i&ggs8DcY zjZP4dABuHyR5}`Vx~i^%+-ZUrMw}9+4pqQTaDb(H^qQ_cZe%nse7gm7G99Wyz~w)@@yVvW)~2`>%e6u^e?VGG zaMnU)1 z%lCPbSeqDs=vVSatZEQYkAAX#jonhBiiQt}9zs>*S*%NgSoLha+6i;?-L8aN z2CZi3%*oXPbtVk7)<7BzcYn9tT{!BZ10BC4UMBFHxkPVu$pP(0l7 zRn5!4B})qkmIpXZ%NPyk=ih5<&P|yOUJJwI8Ci*VxzbHu8^cC1_XuVM=i0Zn|FuG6 zIjd{6x9%R1rX!J(KLISD(VnlJ^$;eG(*4D%7jb2z6Y|=!tF&!GyMi7Y0TJNR&Ba7~ zwIFO7DMHtcKH4R%`yyYpNJT9FT#z_b z+q}Xb)I-;*WHE5u0t37Lgco*T_;b2*CL~(r%sJlCHY%0UpGRxZ=Gu~5Z8TH~PpHy! zaww9c+65nMi!-Pg4eyqrt>Zc_?f7p4P>YTb0mN_`RlnH)N<#tSOyzqJfQfjWgW{%I z{?F)fUM42$*BoHmRLdPwfsu|rS6UXpTAHJ=OiVLps&)%lX|HvcJW)Br>;O1xl+9Q52zB zg+JimMY&2->1-^R&Bdq(04G!@NZX6_0#DGk2QUJs#KEXbJz4T4Z7;IzEgbegq2*{c z8gK4Jc;V2pxWxq!DIBq>YmGS=x}VF=-$d{u;mga2dRZ>tmfsick%N~Be>@f{Yze=y z4U6Rq%P%e??zVRB(VgzO_u`?o2q;5Rgm=Z4=A05~hQFID@kWg>EbjawklG)=F%Nd| z6Z0P8SjG6lR2?h^>950Y7-4gh*7OoO?m}TK+GbLDiK2 z(*n*LFascjC5{8qde-;}(*U2eLIE@U-VSP!pVJ{S{N%EPpAAlvc5E-SN*M;n z>-4xB!TEF|y682!Ss1OdGAUMph|-V2jH$`0yb*Kt2W+E?BmfVbyPbN0o(1_5*2~Z` z+(F<_QOhuj1WqUFnS#C1!SE{>GA5#`@!=K{5zSFV{R#!cqf}sHqH-MgH1&edL`0=S zFtMp#T2Li*5nHF~1qmjgiE^QHK$Qzy5*o1do;XNAIw7%trEFqpR7$1}@h;YPQly^7 zYIAKcJ`(pYVZF~M1#^hk=49JyW_DB>Zc7{4!X>y7N)O>$8mZh(yQrFK@nByyx`-N} zf}m`p+WK2k21Bb&=Wx~3jyZk`%=w#gQ{0TMjth=RVm7w|ywE2i@nbB(>(EZ#(n#bd zST$LAO|u!lVLngiC)aF=RQ!r+qWxPaiOqSNx$>e+aMse589hh3B5M%)3^9OjCQsiC z1gb*+F#hBf1QsB)cc5iU=eIbOAbaycsbnJ0)fTN+4#)Ww^vCeTPE+ZjBIDV22>%3jNjM=D{FT533>*1`>8;=~CKZeWJh{&_95-=pTH_LI$6hLP~@@ zMxfrogVpi9V<_lJfj&wcJnFSmM-QCzqgOojt6&Z5P{u~3XNr!k@cmK?J69Qpqd00f zjA583IUpwY8Z1%V(=iK^uOEk^8;8;z-_34kXFfPZL(QqS-;g-Sgez@ckl07{+qg|2}J^ttdc@ppp&cW0dmZ(2QETp#xT zR<~zlSfvf?k>!A?T%oDMqU)dnm8wmE7#2x_7!;sfYHK4omr}r&1!cWC#jRSf@lrYu zhMvxx;Hc_i{`o`hBTzfiP^gWZZHt2@TKA$IvldpEGIF)w9zx9H;>(R2k3>{C7Eoeq zmwH-}3kuPNvdpIobiJa&2^o zP9!j56)ZX8)ErybX?BYaT@B?*FXx=rbctH?F>s5E#Y9h;-A0cTKqlC1KogVI-E3sae(E|b!*cbGuExLFc)rJ86HndelwsW$A^m_~mVFPze~bH4L+y)~kEF4f-OE4`w%Ra9#c(4Yz`vuj5iHe8RD0~kLTv(~R@^9x z$;eY)oMSL^{|P}?^0%mV_2ucTb4jKytNbmh9s3F5!~&|jXJnPXMYVT^3bpnit2C~T zsx^4<8wD&{wzh~3H)%80;IMAkp9qrW+x!Q(%Z93liI1pJBYP7%nofAr)!XqC0x+GQ zm^BCZ2@hvrWXtRcn{p|4YYU^D^x@7+qJHRt(Rq`*wNx_=suv1TVNYkekqL1HVK;vQ z!s^!1ven8JS8G{s+R4kz%Dv(4w#X@)Kzwq0RdN<<1=x`Ee^z*z25G=CMBPGAi7po^ zScsbDF;`^XY5LMpQ=RZ4UeJMGD_|sq(NbwfTT1V@rpzEX3>%mj!Z9>A8Rl1UlVxn= zwm;gGFCL2B5Sjzwx@I7lWogAnWz1AEB5K|1-WZ)^YW;Ilg84eou?A*e)!5Cttx$S6 z*m*T=E!zWofx#TrDg@fSX4~wHm0%Cl&Ab>Nx}>;q$@!Yr@n6@wE@IZpny% zOQ_S&N+>m(Ygwpclfb;ofwB~#$I>fO?cG|zo*FyKg$9(CY$aEkRK;>CuUz1VtszD~DGSf%nf^YhgR3<2#*G3EU(TxZ&cw z!cC%oewx)Ty@FK^Td{-Ix#%B!!g?30ojWdxu`^(c`n$%k8AEq>f@a-O;cwXOjiA;R z_qs;SGb)6WG)-#al%uZjQiB7n6;^}Ct#niYnYvFU>-$<%d;A(KNP-RFa4VmYi)tW3 zt>;Q7Pjy-a{528D%RV~y5sGd>1QT$K1ra9*Zern6%x`>hA0c6(cn{kj%H=Yow>41) zq6!)kakHY~^q{>r8;$nNiAC#{R(k8siJ&)~5uk|GL2F|huF|ET->qW$UeTGKkmb*K zG)j6yRW7QHpO|boJ;)-CpWI&KCskWBx-bBnm%nF2n)&%#*u?z&=kf&k#Qtj|AhO{D zh_D|}1c=msH`zX^yk-^XhZV~O-bd`hN(2iY9_1>q1#q~?bIzN$m_}jgKz8X)XcPIT zEl^lM=)wOdzETR5`4W}^-~G8 z!uaCnWSz=zovQ*Ce+9PRek50G0f@P%kGM;mI7iIWgZ}OswN`Sq0v;-a_$0m;TpJH* z0tB#A(KfM=&qsJ(l5P@f*?(3hu(OpG&NbG2-(z%v4Fq*G?avY@tvpoUTDwgE$VD#N z6yOg72^SfI1YWA?N{&msHMhHknPB1sG8G(b5oRV1nxK*YHLgb528TA%rWk*oaO_6r z#%`q38m=(4xICSPfz$2GR?et4;Uv2~aJ9n;&MunTX{zDWERW496lf+>a`-t}RX!-{ zOoG2=LBS>!Oqnj0TcOYtLSZx@n#Kgg!If5ySS2rdSfNTlV8rC_0EF0;X+Y@msa-Zm z05>eX00`R}@h9~hy9fyHbVXbn@MCbmGD_4tHR{-K7|b=^MlSzE>|G0WGsRkH+bNll z4O<8Y;aDwnL+LsP4~)lxZkMzW3$|V2?EQ{Blb8p z7z3(03MCWKICha{0yM*3fQ;^Sef>7Cht6bn89lCssk&*AUFB8<-o2oX-E+(#o$R9Gf`Fgf3LX!B?zd|fzIfsHa%@soZ=8h4X%gqXkSd*>&8 z@BI7h@=a-gI4(d!!Aq=NiOFU;ImDBK`W*E_kLx z^^Q#|n1&`!EEbAQG@l75UH0iz(rFVO7e3v|vd>+?7qm`p)kZt!M5Ss85i%WkkB^}5 z)XAuH4wfb05w<4nSTz{nYQr>Zd38>Z+OSl$Ndd=M-1Xr!vswX&iEvkm29L7JbKGPH`8IFA=oeP@%6^nC5vJ15k5H-)dkCJ^-9shNP; z>`>h$GSVH-eCu34^COu5<tNmSMB*fs2aD)9xjB!7=Zmam zGMIRQwDD1846Xu3XRuCD?ywv&BNuB6@5$HNYjAKlz?ib1Q2$z)^@tJ-sM;tcBb}Sy z*@7fLuAOQncj84Gs2C0(gAO57I+^uo&s`9)xf0*Y&@uH z^@Md+J3Zm1+Wqx%+o^}OO=I&!W06J*czG>(4^F?UD^=ZF|Cg zWsQCRo<(oZI?#XZ;EzSyESj^nRnpIWbk!&Si&8=RNMr!oa(bYJU9Yw z%rJcrV*KF6Kl@d1UZ@q{@_03Z((cEtN7)4<_=a4SN5|1Nob3~>ChCQ89%{hBVMLvc zv3EMJR|=!os1=S>9H!%2@k+rtfrN3?4@52gYpRz^Q!cJ?0;t3=71W|`yQo6prtY)p z3;GQ1jTkzQyU4PI3$r!ie2or8|B5M(uD6aA zyUiQWo6Ex%8U-}hJ_q2)LViy9jN}+StpH_{q~~;r(gK*|N64m&HmNU9oM_J}km;#( zD`R{SSHisxfkC8wq8a(-SZW{=?dORm`p?PW)+9;&hues>IGcm%!&*gd;Se6zOwb={ zq^V@Mr$GKXN?~kc%|uvm?Gws%*vxIT9=Od7FJUt=v3Mojshgjj)yb}jlU-5QI2&^v zPzM(qR5cvveF4MmtPQ>s2KWPAzPh6AtZpmKZKj}Yt2LN6zOy<-l8PlbfTx5>igKyG z3daLZUay0xCtO>bq4}mqbW(M>Wdu&&jj@ct`Y_7_2g8#m|Ku18oSH6zX*&N7 zVV%uSIPPU%3CjuDG{SOXPyQXt3EBE-o0p%@-|akUh)*0s`a3^y@b5p8<;FT$ZnR$j zhf3C#aJa7yMthHc30UCo2G;^f02I+Bo2qq@+rns?s&XYD7A)21e{u4qRhL9O#svy8 zd^tp^%$s|~8W@%1(80k>XzQp7MPy6V3L+j{8DxVvz>@+jq;_WN1{}tcX&#MCrLe$( z<@O5@$e6uffVi8+c4nY)1OWJybtFFFSb_IxFafY($JCl-^P+)BeaPEb z@{Nu3O!>wpY7lZX*ETUm{+91Lv~{#MU{NkW0A?mZ06&QUhU84fs-3^LgBzHiI1eI! zpN;3)m_8Txee&Yh?^%WaLNBSUr=wE%;4~4j3($b`r8q5v@Sm6llv6NqkN6>0uk0&blXKbxuT-c> z(_=8o*IxLlqjbGj96<)fP`>us$W&%993g{+sZ`II2)40-=+FL1f7qh9dtyGy722ym zY*XGwCX=|w1;JJG@iv@W;qYGfK?j#eu>MZXyY+sjUy5QW){VO_R(`*R(;~EiD6AfH z=8`uwNo+B$@4)$`IDI@BY%aj+{hI_YgXu=j?FmMuJK9_(1JOoDGeqGzQS{^H6cS2y{SMEq@oDGU4SldAF>eB%wi_-BvdGR;kD< z(D9ttC1rE%jI+08Hnb9`?8NJ9c440XCdEfIn&AWOavWg#(8HyXl=^ z;B3KHH*m7la|36KJ#bTP%^q8HaZLs;+OjJcI9+GCfwM){SOcfaBpWzeCXE_6T@Lwy zv$aq-aJp>B?xQUtHal>-aBu@>D+NDrYR_|U{=HgA1TYc3VpPl*F`qisT7+K`B8ai& zXzh-3CbDWmyxv~&1+KbEGylfbT2yV`zncFS6hN3@X<0Xm0t*z>;hgvs@rPpEX<^Tu zG{>C$LZDd#_t$7)^;BiK!eDER(Be+FXbDD0*B+i*>z+bHfD>g~di1&|zfO>Dt%xS* z9u0O`cCaD=yRAL6Y^N+8ASl9+a<9{G+SX=>0UiYHmZq=CK?LiRPYn@fqJThwp+}uv z9i2|I%VNag)0QJZgX_O8NKl&iv?WQ9+$ZL%!zW&wFfAa(SsUj8buji+x6{lx<^x*W zrSobgI^XM>+U`7`J=Li!@0vPQ%XcSD-QLJcQ@0&YYRnKtsRO7IzaXN3O z+ao6Tfha6?flcfhb>qsm;@(^>)a!nt5*9+!KFL%YccV^Db(~W6;cUrW4uz=BAu1(m zVNh>T2=tfa!i4ds3W;d^{xEh4pjE_7-4nJG;Z7{bmp}ONEKA4Wi>Si6POu@AYh`z} ztX&i}p!H&#jHWr=8UKY(x;Kzt?c0Or6%Mv)4|acB2}a<}I+{a__Ca&BUHA)w=+h@M6GrTiZqJoB1?|~E+hZ?#nzIfylL96IuvXS) z-G;Dj_kkcbN!z$Vg`)~0cUxmVsKA`dMLBFY5R5VMp&^uCWa0>+Tr~#`>Lwf>6`zD5 zMp>GBO$ba5($FQDP`G9F@1lJ1mm)Gi7{sjPpXC?YiE9?!_hFF{aI)wWc$yajXyOVQChZq~h-s_^M2xCjYOO8UxA%QzT{|@gJ0dxRN zap4)}4b3<@7m8aU-R8uQ%@?Cx6%~g`1{xl58M9pJ#wO2_os6ZYp~;w*A9)C<(SJ%m zdwBrtCTLwa8R3xS?aIdMTBB3%@t@Z!s+Q4Ztxxob{9t*rg%32 zw@U_X;hL{O;3u@nPO-PBUgY!>=8efoyb@ecXvpLQS=6T(l{yWFX3W)Q)RvsnRQv9= zj?&6}b*?s~ZfU9J;iwgSbH+@xtI*`R49rBkI%?W;V8mt`w^bzkSqtlOez_MWOp9#A ztfeVt3zN7vm@uelaM>;QD4@;ij0O6c*5xd!uBZA7V=+JuGqk1j!B*8@Xlw9*Z7}bt z38BOC%YYvnPH!SVe(A~x(lws9r~0dqcr7CFUuj0D3?nYxL3hInem%N^U%PTrfkT#d zMo`pB0~Iz$cOUvjW2rEoE4S{v%_l0&DRZZOs6{rp>(WaPJRJO3vz&3!e1*5=fL#i6ZU26{0FoadGJ838v$KQ6VS7Hn;YX|F@LyKuOO$A?-< z>kHN0l{BnfH{^MQzF}ugidA|MKk~o95Zy(=lD(An(@q|*6dyZ-x#id z`&STkk(QK9GO>+J#JJIU(;A0L4~U(F8J%jcwX!vLYod7T74W{bNahaNx|uAIETwW6 zN2su8+=cfC{J2y~$XTjP*cao;uai+9Ty=&2+86p8Jjcu|ox|1`fx-Y#&gT*8;I`1@ zN(cT6&%e=bk^(m7lHSF1rO&U3c8poX(Vv*24~R^HD*+64?l)k;Lqvd#0skKc5iHIC zk^d1uL|Kh_6=uSi!z)S*WPYQ=3O`yahxIppSSQ(#$q*$AJPd3eV}YS=`#+rAe4rzZ zA4-6`rLw2GM;0Xa&+)6BMRcv_i>4zwlcn&!K=t zxHXKxHU=CZpiN-kQZ54g0$xlF$W*iv&{8Z(gv&P#l|Y85ou+0ljH_0Oh?;FJg`!Ch ziwSJPXmw#km~vEu{7x8-NkbU^J7u_<(&$3LtxWvJYpZCaxo!lM3*xINB$c?)|9xuo zf3L*VHWlVlx$RDDLV<1#FTjC_T?v$^(>5GV23vt!ZkWL@VGVZJi~GuWh!S$mjoL@c z=5WN;K!2-n4%=2wiLL?EpC6^b(L|_iT|FcAKpgdqKfspcbSJ5I3sJA)A2>5l6@RzU zHdmJOp9VK{h*qcR!md%%8cXV)1}jA#9rQ+2Gy+nt##(pz@Hdd#|_`k2^{(tPUinlvN&)LoUx~rR^nV>%CG6EJIRcmIFUk zQtpwVj(Mn^WlS3ty31&6MZc*I`p>qLJ#u!4mVg$B~`6H)nKdhj0f3^u^jqmpJ)sKa4xtPTcf zwUzJkn}Enorwmql93aMKtDd27)0f8s;h3Gc6BKXFhlC;2PH~&Y$gr+K_5Y*p-J|8Y zuR70Dr|RCi_tw4FCF@~XlF6yEATroQ)60o9OxB<}E3%y?JtGGvZPL9~XU(G5%8FSt zwwXW7EI$yfzzUy4;J@+Z>)F&gIhS{_vk~z}viiA)O<%cF6w#@+`hie%_S{*i zGw+K@^Ie&t{C@PY%T06QB+Cx-zG@xX2dJ#SSMnW7wdwrhQlNB?Eu;KK$;7BI`K>TX z)ENcs_^sH&gK>~-V1;tV6q-)iy2(UKXQTRWEY(htXpcIx7;)b@l!Vwv``G#*6ePW& zM?dXKrQw25ONPsm)2hcYJySiTQgP93k`!C0N=}5j@;xQo{4SllS0Nxh767ILtAKlG(6h>($VSk`ekEKr{igtRX%-} zRj|E{FHbfVHsb+S*!khu4=gOxI#s1Yq&I$G{EZ)oH||V)cQK&kW45|d@euZUNI0uB zt}TX-4=8uUL~ftuN^A`+U31eVlTBc_EGY~a%jS#ljp+-iZ>e@Neb6RV$$cOHz!j4F zJ~#ne!iBc3R>~M4evVl;T6g2UGC?l3Kzsgt=@JlFlWgS(+OCL#Eo-VkrNaXvTTHCfY7c*o;$37uGhQd!55sI7gS3yD55{+^H2@9_gY ziA2a9{zIoiBDU<}AW_9Nz$*Ix7z0hS@Gsn62y6bRO?wi}J{q%6YMP;$B&8iA!o+qD zcEsEj_5j6$iaiJLLCfQN5lpBz!1NdwSEB8}PM8^8fxrYm?(gDRu#9W6A5oM9PX;CR z%#$r}7~Mf~Gk?QA(Of0mgN1g92h)%cpljqT)1Prc`M2*_Lr>6i4v>4N-pgV1$9$v! z;_@4hTrNeT*l`0panJ3e{050k`7XRg<wloam9JlQhxxvQF@p?|M@&10AM$ggaV zzIIu~aUMz7{WbHjRhUhL%_9Nj@TEZJw+ImO+`2i^_e_Mk$==-FP#fkymfrBqH3&+p z{OpG#BFcH%$KoxQxW^{(G>5L-^}H6nxi&f(gzCqCeB$vR`|23W{P@hr3t{Xz*q$wm z4*rSsE7%`zNzwK{63h8SdIvli7?UcF_?!2?`IONoDi|@*fCtW1j%o!Gv@~Hrhx!=y zQrmV9Cd(5)1v$2?FXr8LMo5QHOBWIH;W1M7T)U)`XYH&C(uj$kY*oDRlQB_E50CYW z*C_nxMhEi_#{>`IvaV>M(ZtLElH9`Rz834@C|y1LQ~q$R9LD>p`oT%3bF{Cn|FmC^ z9<1v>U0} z__NVSjZL44XVrAo%&(=#lH_ME;RL^#IGSB|p#IujTz47eN#k0c+Y%4)V z3rr%&TG+`${&M0Wk9{kSizfJ&@sQ?OXv&*$SFs6-q9*@+4;Ua=l{ zAVe-tgCPYn_-6w`kSqmrRmhj90RIvVnXtZma8uP5~vsEp5RXa7IhH z%;KK6r@RK5_iT{YKtQ&|Ju5IU< zmB}Z+;pzHJe#0{~lHc$wjkFNDStEH4w`in+(DOBt@9?7HQ**|Cnln;(?y8! z4Ula$m^VsGy_X!W?!gJUj^2?7*@msyCyUX}6=pn6h)3wi#zqfV+Q^z`gh$dxR(|8B z*UJC$=q2*B)@Q-E(&%35#vmW?{MPN9*`b25Yo=d4_x{%SgOQ9dYGdlsqrdqDd-Ozx zh&|d_pE%lW!-c~vR_C^QL6sxo&-qiIqONGjgAGCYzD~rW)4&W>nlh zqQ1*+ZII<3TOIR-iXZjqNIyW29q_T4l)aMmiX)$_n7M zG{)IALEp{6oz?VZ-ug~+9NhN!!F_w<;Le%nL;Q}diqTfZIIGmsd%ja^aS{Zh`p;KX z^`z&nGdkyD-kP7g&jfZpBRm=v*01sW2oC0HY9`4%t;2}j8mi3kRVI)HQeshsVDow4 zM&~G`4VV7;-&4%?pR^L`sB@I!QE@{e35~`FRfQ$agv7R;{t}fh7edTIzHv_(LNKPp zFBK!M>8sb?`mgQT70H{$5~pFPv>ycD`C*w7awRuijS{I43}uNVg6aLLEWGW$3SMIc zx}r9&CHgBQN-FTu4NYQBIS8YzJmpg0{?68DECs7kBUcdBOmHN)^C6S-0a4+>p$gg= zC5%Q?Wl_HGL!{L7KbEI-8@4eSWyx2wg7Wu`UZ%=nqEq$&w&=pzPic#QtIF!`thZ{9 zM2Oz6 zS5NYf)sy^VJn1F^A5bRrX43JP4I>r_G?SfoVHM#&dH;S&)k@(|iI6r|^C$eLSm^!n z9OR%Dusnn9f&{GoqZNvR3l(SNpa}>TaOZy~pRvB*Ii&U#7=kKTGe1}|O?vQsX9I*b zVBaU>ho7}oK+~D_3pr{amIAebsE)Iu>WtmZK?g*v&Rv7A%zE!^QIt~>6)%&~ZgG_T zOPi^P9!5@nK-;bCtsa_r`VyIj^fyIj{7=o?`i(;sZwkA@jYHznZJ)nf38f- zEwq6{O@X7{YHvXJiz{?Bn7b;oYl+bR3+ZYg?MAy~8!v^2U27^&W804`AyBHU8>)su zI65C>Y=8gDd6M2xf|3*?Eu}x?go>2g?Q$IRH|oE|Ja>=pk`Jc`O??KZsFfIb78{j9OOFkEx*W$3HWtz zoFj$Tfh~{4&+zH&E+~0OtnEY~`oCGpOm&O(>U9I&oE~6~a=r0*eB%!+(YqoVy^HypmMUtRorI= z7J9NU^`B2KYsmha1I@(*-8`ge8+fLbur)6=er49%wFl_+F3WXRHxk( z)Ob%+(f0FG>CXDGI=U6IO>Z%8wvvXKwEb#VCr&kDCTucJbvyE|Go9*4x~6bqz-*zW z5-MqusD%FJ|IHq7tF&@GFYrD}Xxj4@60FkWDsV=Yb9p4!@rZI|bXoIKFzu07BjZH% zzq&o;G#dj$hNlRX`1l^#2t-0IXw)`eNBtE>xrKf}6!*!2!Ez!}XF zi-x!&Iw-TC#wECgM&hJxL~NO-T4F>rUWvxy1%O+l^;@Y{5_l#W3BhWucUpO#Ax8m8 zbPD}P$`&$R|Cd{KI1tngwXcYV${e~sS%WHhVtY>MrNNq_x}k-wl`QO~`6 z%Qxr|fEcr-n9*%M?V>eXx@Ko)%tyI#ytyVXIKj8T{hEx-9*%;T#c2* zvR8M7%=Vz}1K;`>Syz-~tbo7Hm9U(rR{23PuOaZ;GJXL+PCSj+mj}$++uY9EX zSQw@~+-6!H$G@KuKM94*7&H6zq4sdmxUIfnXO6bjm4=8#7l>f(*j1N;`D^PAs2HcB zKt1$#T0+LbbvB9NDi``NZ3=H5m*3$Ui-mqW$#2i2_iq@ltyDQ)@&23Ji3B96%`bt1 zk@>}qAQ0>-I2)mLs^*0yL50Rn=2p=U_IC)8*u`dunNC;vic9(@P^T)%*lsvFc7uuf zeD62B(r&0lX}e*m`2v?2;(B3i$PJYRP_R1DhIASXLW2PU%sR6;HroQlKb?SL7t0iz z#W|f7i_admcMn!LJIhsU+cGyiHGefv6V%8+p_Hoffs7vV3U8bUM{YjZE1jwFWP0%K z-cUfqM!+sl?_j-udhWw)miHq}G7bC1Ht4sB{R?p>b}$4QBvGRYjU5z7#&!_Gz$};2 zhH7&Ci#|CoN)wX{>1h7RRjKI92&{u;8LleyyQ+QvTpN6UY%tpDrW<^`{k+&*?18pb zc)8B8RSMf;tD<$}*jCv_71$c8gBIn>(OY%YLIN}gvt->A65}a1+Ndg>l8utRJT2X^ z=;BT-YT^3SqN2|HQ=7n{i#xTb#OqTFS$6)ZZH7S-Umt4E=^E&AzGV_*G}i#5InNnM z;ohn55q9=y#7VwaBhK-wHR2q)_v(fy+msMoG7vv> zi`#e+xw-kCLe-oshCM`Pu|>Hcp)(+y{xtWmu+0N4F?^+a7VRQ6-65JYeZZp$i@U0Q zFqzPdvmjmK7JbE9;w`8=NXi6MSR#^6L2c(TF7pCRih8LYr!fVAC5s%>gQ@)5muQqE z=SBI!KU(U4qT(-JX0SRe^xueD>l_y5ooETG$6QcpW-_D4QeII1dFS{8jbQr& zgIu#?DL|gp#}jeZT>MIVwT5uDIdA?CS|YaYEl<8GtT?hX(?)58PJ*3%_k)&Dh`w{v zA!HN|34)thMD&-X>nh<4u6DP=75JCmOb-Jyewb*C&!qPgxTzQJVO=QG!xpAof*nF- zJ4!R39O+a0Ch606-Z6ltWcJy!X?RO{#9K=6trGR+nlbLG5$o2S8kNzn5eJ3GnSb zkN0Zn_qRcVf<`)u+YlX2=az<93eITBo{}XTtgu+MUXKfSqPF)d33BOB<7RH`;DD2f z$~MsaHytPu`+x|O2##C>2+QHzxz*ZanZE!!MPtfEd;c$`KJ}a}7eQ@KA$is|9=*sN zMHk^kK>@V*IPv2zqMwH0*7>byYCTRXY&{|C)~}IE$0(EUq(btn(&-!rbi)1&0?FlI z-c%}{ZqsLJaT?XfOCzN)_e~zu|8z;daPQKzR`=oATAdrJrKN2P?QKtJZ+lI9Q(FuL z@?VwjA6P1Vet<%j`h1W=meK}q1S$3TStRXioD=E8B5);1{W9sSDn4P%aEP<$-a$u! zG`?$Kx$Mdb4I`|EZ_Vmv+ycD}ssud}UlR%#Mx-<3O50MgW-5bsa!?L7!C1H2gX=8T zgU+MUe~Wy5dzN+M|L`-m7x{Z(VFBma3Wmvlqa%Vv)r&bE29PN;Cr-%^@#7M@*@3&1 z?pptdAxQxNLn)}5Nd8P+xXaWcoHN;7s}yJ&yL`ArbB}cR{uNhu{p!Pft!!6K=YWFb z`Ni%m*fs&@Fn6BK?rPq;m~Q2J6+qIxH)6fy-o>f6(nO?r??Sql?@2D4deyPk*yVIl z7WfaVU9A$ywWg)U%xFm4d^&+yemUPOTU#97tVHE_?a`%OD2MiAP?_cO6CZ8X9&KFU z)M0s|_9z!b*)-K26-UuNki}48nvehl$g@`4YL9v{1yql{J3OC1 zmnS{AZiBIO7{E4i*3- z8CBD@xHvHh;_A~IT#!In?*Hd*Do08`0sEN;p^01eksibp-57ydWZCNh@X(RCEB)+x zN~`>v_pGUIUe#f#y1=!CRswkF3+V}dyajaev~vMHVzS%O@Q9P5IAVa_8V7n9%Yj~S zy_SI9h&cD)n6|gOKo0SOuTf1jB9W6Hz-x&v7ocnZuNOu<5iDyK_|HAMZ`Bwohh8pm za^Z^=+L*B-dSH_^m1F<=qu*aDKmG?xY;np;%y-Km*y(?&+kMeZ{wy$g)y?D`3oe<%Vu~g>rAdnC@;w^k zHjQYErb(hPnkGpYi)oUCQSaC9gi#;RNEkKY_Qtbs)JQn>vufV_Vbd^2S?_EYqibiH zJwLsnV~UGr1L?QP=ISD*xUED?eZP^-bx!W9=o9!YZW6UxRZx{fxD(nWP(F-+$*vTb z5cI}yzkH*L#`_+z*B9xtS>MzoGgdr&uKhOzaYfu7oM$8B#Fi+(s`#Z zF2Ec;->$`5WN6~HaVCRqv8Bbq_hV5DUY<@@aGqs4lX^Ad(Q2G%Ka9ohaXu#!QX&vf zi?@RjVrzXcY*BMREacL7*pxDAFo{J^&m^SHxOqz8)L{T6^bExhfrDZo_QrH(%wknP z*y%T3dW+-69N1(#PB$u@J;!;$v!yuflO!hSW)K~r0y+RXPJ3UN)Ae^jk6WH+-xKjE zbG-eHD@>Mp``c=d#NU~PD^5?%EtQHY5m^e|x87^?HgODEv)uYL{)=xj=))qCmqEf^ z_#ja-QYw@@n=7c1qdP?sMe6TcZD0fj!#GA`9e{^=1R^vRXHJFBH?^TbP=)`^#O zX%#(J<2JTcqr5B{b>cN%J?PqaEsNFX4h(lj``O9#1IeA7c%Al@bUx`BTAq@xqR1YE zthQf9Ng?|zGP_9O2>D+uR3bAx&>nW&7gC-4Zm~qvBUYrYiPgAvxmS#X4DS?}f~OP2 z)R}D{rouKmrd#S)N7jsE&upYaO9&f+ci0g^B3U-wHgD**6_>NO0*Al@rYUo}v@d_I zkh5Q2p4wY1hqNer4-o)yyc^aUUxn_%#<9UX!|y+1p1w*p+z?ONOp%gB}X60@92SiK&`&22~1Jci@lf0;wBgcQQLes`=9oBa#fO{Ye-n>8ugWH&|X*tqGv>^~8E$wTMfOF!K85m$R-9dV8vQ_lL=WoB;B z-{AdqnH7oBCr6Vl}Ov4t62(U>U?yzU`1!nC+$X4ZWWk{;Gpyyz~8Ejbk~+Wk* zgrMNI*oS3hd}=N`WeK&@Qi&k8LivIhKU;;8p`T2xA)wY4)GYeif)*4Z!PJQ`wV686 z6f5B&XBD6-KqH=%`|taw9*`~{dA-}G`#;&WunSDa7)HG7PX7;DCb9*nM1|u)j@EoC zPyKpzzrtfPtMJ4D;~}^oKK=3aa#4>#%~!Z2>=$AVg^l@utx)rQf_z^7?AO-I1$$@g zr}ii7iQ4Dok+1uE1dLYy?GsOos3ca%lQ3CZ{Bd6X)qly$uAWFt$vtIe@l*Chi|fhD zM`<74ne|2#Ma}RrL&%nnyDg|)zVCP2<+AQrs9fhhN23Yt^5y?;yIh_1MxzYv^0$6{ zgZqt+w9CJ`uU+%7ogDZ|!R~*~mieuFk$2Yj* zcy+~z4X!v*UGeY+S3F!@@yG^OJW^e8W`irvR98H-!4(fxSKPnB757(HoZ8@uQ`HqG zH@M+r^Sf_weV@;&!4(S)Pv2XOgBS#|Vbx)FG{mQe@7X6B$-q(#_TD0IKGPVq40=Y8q05y7ttZF17MVkw#PnPGRCu;1ufIEzL*qIQ??cetGWDdYdf@)?KN=5_KD^ z=3;-N{8!`iA*M@~j0{FRR1l>mDdqy8Tv=ai$nLe;52R>=+0ZM@4j{cE8RuMEU!+tP zdPT^!=oP6Rr^BIZaG0JIDy2+3vu5QIZdbDk`Lpd=nq=6 z>kqAQ{lScsDL$NXn6mLPm(U^1;s?Oc7^FqSV?l(_AoxQXge*4UP)*1wp$Tne4EU1> z&MpRmIGET2m$(=EZ`qQR|GI*M-cD@P;keDkGJTkdJl_F?@n~{Gm@tx$Z4C(1P+g`F z#;xdqFkwSSoN6LWpLVZFRUU&RJG3FfxbfW(CJgUQ5V~JnlQD$3r-3kiiW>9+Ujo(_ z4Qu40-vnzgA}k|l$wUDpbr`)r*kb=}D=7><<W%CY#E)e5Zn9L!Z3VX=z3j$Va;URW3tr$ z)8*tZ@lY!fekn_f4b5D0-9LM-dz*9hCfhOBzGKhST=!4Sb+6|78~`!NdHuco$V=`r z0*01)!{mh=aqlG8)nZh3%p7b9?y;KYMkw`05>G0uflkgtOTv&egSsCsqNE6jTF>1h zu_xNjb#{ro>3{ltA;Mp7cY*`_oR<=&Wwhv_mPI-TF^Ud#B1X}jZj2Z~7n~ZMY6Ur3 zP2^~GLvnOz0*CyRPSc{^cbXP?vpu6l(Oa+fsh*n_d7HhUMRh;!$4!g8>z&b}9gZyj zzoA9LidhU>I;cj^Gl+~4PtH6PZ;udLjE28gWo>dcqo1J6*PE16Noh_ZxkNXR$Y<9E zz4PXO-SU8VLEUJ)hQH+4b_Fcnk)>fz!v2y8`}Q{8%`eVy#n0zpxIGv4HO*sk7`U*{ zL!9BpV`ng2z$%6-HYuZ_R9xFyle{WrH<~LF{G^=hJ=LMD@vC18B|>oK&;QRBMXb>x zPXaK}X0bm0USF|_G1t5icV=J;8|NJvm->&bkG?DMoW{19q^0Oc4Bh*T10X_+n|Q0n zrT&|@jG|9tE$VM1G(6lwYLJpia>8=?SO$BJLt3~4R{W&!Sv2^`Q}biSMm$gGC})6% z(aujO@H~s3Xa|=j`H2n?El6j|wsyMc302vAMM;F@)9UpsICAj?sMmv7G+Q|EMc25^ zkrtr~6D4@!-iG{&q=$sk+^u5`(dGUkI8c~MO<-(BO%cl-2LD$Rr0ZeWTrCdc}{ zp(K83E&qG`exm&nuJ|f1KudeF!&O8m`asq^gIR$q$rPiuBB5E^+b#fC&S8p)$DSKk zbfK&!8}RFyjCvXYu*R_>;a$D$Fy)K9?fdF&-{;%bo7i@V48fEu5|Osudrii+U*-2x zoV2;^7i3WJ9+V~!NB7AwWMtb_f=?%BV%sr#oHvP>W7{{irPO8u-y7}wBz^D>l#A>h zjQRT#pa3iJri&hL+V53xy8u$}Z6?hy7Cj}K2Spa&idzdk#ipj^Iu5conp_mOjuw++ z$JnTIpaTYSJ?a3Mj%U!;Zh!f?JRsqSq^SBFjM?QWXs_gn#j-Do5#1Ai;iY1-1u%wsP}uX%649tS#A;3 zz(XqRnF^^`QbR7nl%Y63AL#$=%UWhzwif)*^$5$7O{a+ z1Z*~%SM&}Q+l`)~lLqa_+ChMo2X1_KAo%Kq6Eu9?=<^ux<&Z?ML5R54th%T&b z0XPu-S0|icXDSOfdjxvwrIzJvz}LXevfFjn1MRr-= zr1@z~k+r6%;@3JN(F~PL`eZt)9>smEJMH`g73Vb@d9l36wG~EaJq>DF*_x_%v0~na7irqf18;BYz|}39 z_5TP6;_YM&@X`$U{K*b8QmHca~>Z8L$b$u`N`KNprn=T@T{scq}#SOTE~OJ)(e zgeB3gHLxT#Y~2t`@Oqp-mP8*_!;*K-jU`sjY$Gh8v+)yyB~9wq-55`jY_TLI*HcR$ z*qFLS*Ve96x74(iu)}e2?j+5&z_nBDY1aue0dQ39XdiUp4)&}7@me~==7AnN5us?T z9Glp<6DAkkF^6CGxlmP}W(EqQa?_8ljkn_xCkLsDqnoHV8l7j&jF&pk!k}v% zO)F1SpduSnlupEBOznM_Q=zWwJgG-4>^j*U9jfurluC+0-aLscu^x#u$qv+ zf&kHo8srZ}4XT$;!7e%7+W`Eceis9UU;s;@O9&V`!4v3u0ecd?b8Syj6Y2SUg|j2UME#$KfU8BK1DS}zQZ#Cedu z7#d%7&dh_o^Dof|rkJFTzf+3IsfJ>5Rr@r2%wnWR%5$n&c0R?jCp<%8Ud);Sv57}d zI)E#k1a57y_%*kleripb#_iWlZjJogjKz;u!G=evQScZZX_ey}Vbh<`OQz02bQq3v zkQxe4Y}M(+NujCIO)em;AbJg3TtR9yJf@r2J6sxoZiE;DKsMsn)tolw*OQU`=gY4r zUNJ-dgkM*B$_5)Sp{)pjv#fRczV;*|;59tSHCZ)t!z|-q#p=cpiurA17K^6LroN<( z%o7L&IwkW{+7P*@W~(qMzSz4aCwpG%mb@uK$s%&z@oLdL*bpjp3!WFDQdGhOX>IQJ z2JHG`qLkS6v{f%qN@2I9DH)52VtM>iHA#R*#WD!wuzNEFJ|>G@$SpX;%PSdgETms$ za2{?=(l31r{!!1YNxu{iGwCmftXu&7`dDZMvZ;J57y>@`WCqHL2e&$e#+oz__6JD;Mjup4h#qDz$%wn_kg(X?1SlmxJ#ssfVEuW{<^wTx3 zpSNw~ihS8{S4OC}k|p6XWZpB9VZTiy8TNZLQu1i8Mzpf4HCm}7Mk{s1Nd1$8`ks+F0c9h=8S4lnBs6r?j zRR~3+3ZZCJAry^s7eMiIN2wE)Dxny7rN$}^{bB0xx4l$8e=E`wjk)Mrq@|8-qjE`y z99FBGfCIz=5vYr0ne04<-eLULYy)0K%&V5rCa3@Ad=xaGmfh+(=r%c29=OZuy{Lc* zAJb#|_5ypXrJNS2gb5`S^k7++$F0@b1Dmff1xE-ON#$K)!;o@7f(>goC~aKwnW{yo zb^{}+ysH|mb_1i;ZeX<94UDSYP-DWiR*T>pC1|iPom$(hhr?X*3^dTFOka(COa&VE zuuU5Gf);ALqOJq_ydSjC=K}-vAyQRlB3q|lGnv7=QaLMA4liWI{OPKlJ*3Ek&T6q@ zWe;!~$U__3n8J1IO;n0MZMTkgnmw^B3gf%*DBP|Y9ds<@xqL4hgvuN_5xd@gFO&t? zz&23a@hK+4J}XQ~)lTY-Z&*va4^W<k@G@RJu>en!jRn+6vWat@YXOOP zTHFEEGPFkqWAifepUNYoz{iJHOgHHu2EnH0%5ytfCPGzaFvoj z4Oh=Z4Y(2k78GIL1ypb)2ebdy6+jx9m5!?ORS7{iWC!kxl^eQ?ab5yJdZUN5H%`!Qe$T}T|n9y zoute$gX8GwqOJZfT``Ju(K=Eqm#os1G;~<@aag8E5G4hN-3R20>`cQ@wQ?ZxqG?St zLQYAVVe3Z(slv+9z_;}LR9|alcEHDujSA(=aco>dSQ&ZNYs)2sHOJp`9-Dg0XAm?KQX0ob zpIILFj2#*;YJ!e|X8lQd5&NYwC4tyumm zb&AkZpq!UZLa@0mlRmphpN(n7j_DOUt>zK$9%G}N8PAGs_rJEDvSJl0SOA6yMMgA5 zd>VN|X{-MyTSk#kx*4@nqLiN{YbmIMlro|?OUjpq3lT{)>nzy;pFB%iLx$vNYZ=gl zEwyOcoE25FOJYTy*-9xc0W>mO>oZk9*5xkfq!^L2hD{hz61*xll#iV!PkS}NE7D%a z*pTl}?t+&yJv&cRllQdHn0%y#)@h53rjeEUgoD|$K@H524LSy9TgouN?1j0;<=ccKo);REkG#5~&E%DXngxeX@djn`>uYsqL&_+Tcl;opJcV> zMb*QrXvt98Qb4Xa-M>$XPyRRBlmP1vYRSP zGaxG-jSCD|I&57M0lMQR7Ef9=*hb3g2Cx;krJT9*d>JIe*rN9|%!Df=Pgf0qK6z3C z6hJp!N&;v@Ya@oXs};t%t|Td^QBnp#@-gaD5!8J-0kcLLFW|tOeB1}dGfQJz_sxRE z6LMfYCDk@H5>heOO&%ClcR>fn^HO7fBQtf}8o242(*BA%p2XgKfd|HuNdvOqHw&_x zV%dcs7*8@a*hZ4+2C$v`z<9c805lR##{s(OQW8KL2ZpfB^E)uc9|(n;5^LzDh3$E_ zav@!i3W>t^jfNwVgC^`6a2>6k63#Rx8slH7Nci&zd9dT07qyaN_*c65^CM?A)A&6#!!)#-Kgfn~6tQiv`Wfqc{tfOvtI^~qXoiJ`I z^#@A&X|Nm_#HQsNPm&G!Cembi#k?y^8$LD_r_PTH;GT#X0FPA6?+Cy>h0_53FRGKg zF~F(wFQb1A@THo^&jz@sat6R7ne!q5oUnk$1#r)L41h=8<2b+@qT0p8aL<=CfJe6E zh8P}7T>>~-C>Y*97r;GlG5{W#lj8v2bY%&{(I$M^Xi5}>mwHckzZc?$756yRwr*{W zi}m9$Q7C+*u8LH`fCZ_k1UeyVbyi?~y%Vk36iws_OE~jMa-B%qm^~MYGDXBZ&oZ_+ z@+`*z(V*=YbBjGE)3!KrGGQs>XX^ChB4VDZ8Cx95n!Mt|h*(TTMC|-w>?x7~<4BTx zd@#0+Fvf6;kr{nHiBVlv=LVzjoJxanWK?bn<7v7zlRJ1OWdJsEDbEYA1sbP#cAj`P z<_kM8M2ED(e1U>V8LS6~i#JolwBUq{Ie-LZT_$I;-;3A2!lKs?i~v{C?O}vTSY7FCq0bd2jvbD zYcWTkjD?8SVYC+4jFeCB6WCC6)#93w*o!?HiM`mXk-&|sH4=NVUt{lS`GGq2!nzUl ze!WA7>&|pg#CQmf$6hED#{!{=t=NVN&8msL@KBt+7K-Ds7rJggRoC^q%InS%a}lPa zD>HTe?Ci~GnJ3f7iee(DLxchScQ2Y?H}YKcQ;TvQ!L z^j#Jc*gce!wGl*thAd{Flv~-RjeS`2DQ#DD&85Fd|Nbi^V7ud-pE~!d6pp>aOX2WL zqJr#oOSkhLA~DiD%$DPi<9>x`2(h=caU!KBR!X0HRjV2+ynZ((24V%ZOypRH&9-sJr&?dR2)D$G=M6IPh5ezWkFj zfkmf^rSjBFV4bdj6}Vi1E0B2>xH<-|P7N;5VdD9dU~-@mP{Jga415i+LB!-57BOS> zitWxpe)~yx=}Tm;R(a%0 zU-K8WrO`KKTj)xw$nS!sNUR`!N-iR!b$I%Jv(<>rGJMC4a3oE%jWjJ@T|b=|Iz5Sy zNdJX5Q&}m$i?(m=m)$Ku6PfGfncDqdqSCU>%k^q|tgWur?$fJebM;9^$m~jV{E{#F zZ#$_s0(ShdNjj|3+TkW3F|{aKK-gx6Yp4Qyv2eF$E)R{1g~bA&@1h+L+fO^7o_Co5 z&@GXzYU}7!pxT~Xb&~+N)Sw~d!*UCkXFl`yYQCff_L4G-?CyJ{ym*lAN_0+a3DyxN zMu2Vz^W{UC{(ac4k2?3pljRYmU(!`CWy>yBCsvlhB2%Vmu z#da#fN8CF2e`}Zj%3-m~6_A@L?tqYKQ0ho77eogPG{8knDAIjWY?&vBntDAs z2aVp4W~rQhqKAgcg`};B*wA=l&;g^qU?NXe7b;L)2fCKR_R$_|sHux5bcQRVBX7-a zSMOPUE=Ku?#zBaSt=o6MaJcf|fG$1UUWt>%@=e@~48RM38d_Jm^KLWDlUu7dDx2D- zAP(;669j?7E%`A>LX}n&n*=F~Nd}9qbcH61)UGWUzp8g_*>`QBSe~_OYEL<}YoY*Y z*I<_tT(Epj?4F06rrnFk)5h*COz&Pa(4F2l4?RuKirCY}vm6tuBo}QPa-7gBh4m0J zZDBnepa|<}PS=b%GZrd7ztfl(q{O6pNW$boy~m2IR6?qVAEoYM@?axEv9%SNx=2Q9 zJ4h589Nkpn2`CuS5U47eo&Y)uInoYKg%W7JWMkTL)vP4K0ku{S2b_PcRzqxh1ENz( z%rHVsSz}5*WsM+gwMGLKlR|ZBuG2$GDS=~<(xiNy^;0DJkTJuvHec<@w7VV&83B-S zN(*E}9kPhj8mBnErTJ`%<8h^m9@SQ|J2Al!B6y-Ci1B4YE*0^)c!N;|qZlER^djOj zEjWTc8|6j8Ta(oD`$mhSm#J2Psu-cBLi!O&CpNr3;|mHVS*Yy+<6sWwzF zx(sN7E~DzsI^pLJB@g^eP^u$8&jBS(Yy-ON5uJ%HM^Go{JK1r7lXRE_j~NhmD^zdf zF`em2bx`N{lQQ7r5SRM6F~n;kdOC5)iwIyGYV1~K2xN0OG+coau~^Gfl6hM~maQ6g z=mDS!>=6Nq=`(>HDq(_tV0iQ3c^8y)>lVlB#;uchJrS!^9(z}ySF1d(KV>lynNjMu zWRfC3Pt00q&Q4ua4oZBrQ+H`KyO2(F>X1k3Q#U!gqks2AAitw(Q2lB4=7FgR(V}BZ z17(@COp7(jYNt0qe-BEajlhJG)cARl)AG{=B%e^9a;5yE+JU&e>5@4l`o57ep*p4{=Nz>W6|QF`Ql1 zKJvcDa;MvnEDu#ps1&iPDCG$mkpVd*x~1@d24iVxnZ2ZCVrI^2g|H)q(0`J##k5RD z(=r*Mmfov&qSv$8u=ySB(t16UH+U@?o-$IOu91w?XK19a@w4ieowm%<-oJ058Ne_e zkdiC|^@tCn>|d&8bkTlbumA~ECMP5;vwTfTz_BQl?!!dpOQ{w83L}T7|3WYqq*}{5 zf>%>~{VSb3pJh5f*jO=&f$6v!rG06XNmOIO%rx#pzLylSADvd8rQ_=J(-C0xc}^30 z9PaYrpMkUjXUq)`*`H>4IQgm|xEad103%!=-FrVV1iRk^qB^^((gC$^dL?pvm>^wsbpE)qygPY*R2 z#rM7~D_OFuhjY=@Lz`T!5Jso+N=zVD@|R?L@P4B_6$}5;g1^kZ8=*~BPE*URp2J&% z0n#vChDg~{7|ou-X!aCFFuc(B*i-gt#J;j$qhUHDC*$cgW*?NnimALb&)fI5@4<3W z+&x^7qa+s+xB9ma^U4%sK~0>!2_SBzLrB%xqKFh-)RB_l2kmq*#N z_^_;FZ*m(a3=7?@gXQ)?ZpHpqp`O(TDO&VtNBi&O{LBT*>+4yzSp8q#vU+F;#RyL* zD~l!!o(6mPw7Q@&XIHfg{f5G7ztQ-c534Ak`pIqsqW04ZiuO(FU$ub626JHd*{r^& zcXRF}D=cUk*z6Q)j7~$rcZ})G$rbrnq{@Y~Zr6GX1UihpzjcKP8A?|&C7+D%Oiyk+ z>Bo7J-b1O3-mz8-AWnOACR3vAv|)65_=}jJowgi5&7Zcz7@%g8pXIU77<%A=7jI4jRWTAN~9pQwoNi z(Y@E>=u1}RHt6B=+^2a`Q=y2@`x!Cbs&_!Y=!{T8;okk%asLg(liLx-@zei!KCmaG zFPxmq{N-dk*9MF_<>y{;Ioau7$rJeT&}f6i^+@PNCSWu2v>7UkSd*Iu*VfK9e_ApN z?{7kfIDjTmKy()F^XK5cWfuN7MJ@z9O;t>6E+Bf)cUueSzh_^XIF?sinP$$$mS@_s z=Cg{UGItx&L19cKY4P(Ly7=+_p_RBnYnPJGvhrkZox3ols&khKLQsROd}CZ5)=Dl9 zAkAAy1LTLuBVrh+R5u|3L!hG0#qVz5JZ(DJp-;jz(JAU&C_T!Z?4o3QkOcI(KvK}S z4{Nx-S1WU)bO2!v3|;nxfuSc`cMsc`z0dp{Qo%J@CL8aVjm#houXRne@RAjI|D`+9 zmf+tA5wv_n58>MWe>52hKkmW&plFqY(O!Vj^(i+D)EBN`5)OR-SymssphsX$MX@k? zE7X(&FwFbEzQ|44|2FKcEmWva2as*oW3<8F3CuYNL!$zGFk8HKHp*a(^77A4?13VJ z{$V`#3N>pY8f}wx2m;M@Pk|k!qtg(2)B5api4f^Pl3Dt3 z^!fvuB@^4vlE~BX!@2B>XMVrT{OouJ;(0!_TNnfWl)yK#!m6S~LjPA<$q0^6?zLx@ z-P~LrDf+**n5@mUAB`21UwD#83V#^97+*wF_A`hinYTPKGlU(aW$(4!|N44edO+LO zDq2W=Q!SJ^kF6gd1(_utyt|sL8-F#8zprZFhS0;W={GF5%6T!K_K^L7c5uJ_f$i^v{wPla$>a8wrhi@gSc`K-@Cv#X zVsg7Y*20Sl)j7#5ODc>rQ!p6!=xYMw!Wvv>;6nt=oFzh%;#Xi(P_(dXQSeBw zq#a{mi5rGWV7as(L!;oyr^QzeCCL)YP6Ue zMx^>Z`i#_HXhgr=r;!b9cu_s(<~41^lNoem^Au~taZ^F zB<+wlGubhvE7)FlOe@Tk-Bo)+k<-C$qKDzzfsibAd@S-4jGO)9GqH3`r;LBqJ`c1pvr z|K_f}YXN$dvGR_yWmGRFR&(iwtRp|F?Vz)Cc@w2G_3Mkb1xx?pA~lO<#LYG1p~m;7 zYkM<0Zce4E6i2iV<^R0m=0Y*OQrb5P;UcIiBD!P(6ePUbF#kHK%g9GZb|ly%T_vv- zq1MnM1vozG#i$NvzZpgYgbwAFfvE8LVH@?lQE~wIg20quvUqN5V9b?wbNPZOZ2RUx zmtWEIL6n$=3tw$9vtWKr1TbSvUt11+1>Vp}4vcLtF<1(X%6w`r^7)B z^NDwK6Vr6*j)+dL?UMnCZ*NaLGs&6!Y_8CX$%HF3iH5L4A)^v#(7j~5mz!kqW_{3- zk<#ueiADL-4|mIj{{1b!Unsx+=wNdh+7|O5B(1%NOmgzHC&j= zUk1=-FR<35GFYiLt^$b6zMwa=_z@tL`Q~PFf&viEjl1PL{%kk=7=bAGagaGy8!Q)K zyzz?U4o!KL|PFiPM_I?Syi9Yr^2iphX(O0!^M8Ri2^=Drv?f$j?FVo9o4Ygd~?YDdREW_=R ziEaC=m0!@%RinvR+{nKAXr7KaGGA!w+=CHeAfaRQ$;({B9#`0TABCY=l&bcu2=-HAsh!GS_13>GNP@3QiD6&mH;;ZR!gjzCw+HD($P{xi+I= zc9=!w~;P-~evFal5Xh;8z?R1)<8kl70FawH;5phlr z6|3oNGgS(}_0M$E`R4K@#`oYCno+?%Fe3qqgq0S-9}lOgIk8#|QgAY3W8`8ETEMeV z4%n^3l8RYHQ>h6)S^+y2X$KL&0X6>p-sijhQ>}Cun`<@1kf^SAYLq6SQSzNenanjR z2uku^p%HF~rXkaK8@tneBg9#;-+lQX(Sgfba*G#&gSOcH=8d*LPqzju^}1cDSaqUM z9)QL)f+RpO3OmSrXdz95apcB!=hO7DAD^*ABKc@~j7F~*ZJLZWeL;V}IV0%Q$)klN zSg;gBae%&Z%+gje2~bl7DuDjvE0zS%2*zk=8=BK2ts3c^L#&QGL_$YENEbq}--qVs zqJzw62Nh7tR4OIVXC^qxn0`jsqu(EC0p@$^`>3O3cP|_^_!r|?QbXKSQt;Mf>QXWN zf_NoXqiF;2g(*bi4il~`0KDlBR|NpQ1~I!T1MHh|u-z9WS=OOxln$&;bXtsy->S?g;MNj2tPrVWHzE5DDBpSkY9B?5HV0HX zk|wePC_j-QwNrXV`EXZIIP!VfTVTuE4Uk#}GlnI3lP@u1SVtJ^$_uHcts0@G# z|2{{gitNIQD=o^Hfv-(_Q}op6uN{h(vjZ9rRA)5zQ|iot9(Rd3c<~&%HkW_!jdl3N zA#H+=hoGmg-}Txp@im&Y(?X9UfROZmsWXZ&f?87><29{B9MgpL`1V0&<5OI$IaZp1 zu9)ChnoxSVhY9HAZ|tOEQ%&&bMbwcJkkTt^C=`Zav9c4NT1pG{OQ%+xIEj1tdFQCr ze@iEopyI75WQoJ8U?qDDeAXCJTKVi*sNsoS-YvLeJXp`xX<6lj{d`c^!sGZKx&wHAEF$N*Vt(fNq~jI_j-tOzp|9-YO(kv z7qEDEy7-6*8HXdQ8lEsq${2ZQLM3NJY(hg=Z^#)Ro0KzZDMMi_^4g6_8NdF^mun_2 zWsn&mi$&r+9?*cwWWokVYxJ>N*x<$xHh$s#S0K?MY(&UIm4lFk4b0{hVM++%;Rs38 zh;W2j9=NkW7(ich5*g#)I@u@Wa4dSK|woKDcanmO2a-aG67|o;2XdZ1w)ZKJ0ndpp|6RmdOd?Z;xpE^v4Oy-j+=(EPZYo z$os$8tbi+%o|)z)k(o_T>_{5F8SFyiN4>D?!YUuvxngM7g<@E#A;O>xMIThIrf9@9 zj7Ii1i+0n)xVeh#f|vkCo`@k%+D|8mi~SQ-sII>h7mP>5TIbYS2gGeMhbaL`%us{T z%4?g1mao?8jhPa9pSU{j-_xCTq#U;t1;;=+3@hbk+BvWlr9~N5+e~?>Gpx4T=agY} zVBpHm!BBQ?3}xqVC_A?dTuFL9q4av+3kGX8-Zogb@y@{|jQjEb z1PLTIiC&?|GedM2fZ#w|*E)^489m25V<_7$WkkniKQ7dr*Q$ow#dpTm#aD}CE4zV} zbsCb7Ce;L3Oe!olC5Ck-6=yUFP#0lRGr(O>N=@0pFqasS6%&>?9EBqfr(`UGnDzO{ z>jF_o6VZM+*C)$F(GJ^-Mak5I?MV{b&eq9MKaMJ~ayKWvADbHD%u6aVLdj=b^rkpxMoELV~2)nTH`-|;TM7F|N1RNTPG{URDDonTr&4V+`6^-MCX!QEP z>^V29d46I#d^HOo>8*9df&{I;vT~HjWWE_HwoaTaB-JNiMmo`LVox@kOXYkizZ~#_ zRy`aJU8t)laBy3wZ<1qw_o)+C5__tv!rnM69Qj`tw=) zGt`-f2y}5Nv*S%rS`6UCg^#DcMaEz?OxX4Zq)81 z0xcHnH?a|tgDkmDB330{xo~7P(z8)6F4ij6%#?6H^}h5;e0V2P7G{PhzOWsKgEU72 z(eZqEslQeIalG^aDz7L22cl|!#(Lrb$MVttb^FuuW0roYPG9hI9!Fv&FIwUxh$Gc} z2ggIc>%u@6QpU;@9%Jriia4G<3tI2>G6Q^jDT^O&v!%W|w-OC1!@w+6V*m`=uBpaS zUQZy>3w2Ik-{cd4(dY)U6pihuK@mJj_S1j-{nYtY9!%ye9Sd#Rr%vvIOQpVzK5)-bFEu5pFM4q#*R zV+Lk+F5jscgw1*L8Gv__N+2g2u_W=J*I;Jd)=-uzX2(%dPd3Y{A!vNtLb0<>+zl#m zgLbl^>*)-hn_gfOF?zAHrWbDUZqSP`dS8(0RWC2mi)pr%TifqV=mqo)Vqr;S;~eZf zNylUDnWTeKBu+Z8K8d=XK3~#t%1Otm?-=Qrb;vd&9U_qLm0kB7gyWNmaC~wG;V{2O zO*q1%aX~6q?V$8}r zFn-RL;*{phMLlew0~+7?a_I(YCc_+G&Din8#US3N6}VR{T$1c32w?sDaN!cfa#=F$ zTq5rT(nkn9*k!Fg| z*GLn^7igq;;%ypfo_MFmo$RVYu!_r{hV4~<^siGeD}QXc4%=&OSw7y1D7D{i<*j>L zc%GqbJpQsEEf` z$V?rsVn)eFDxX#b{HS2lyqYC)xh5cEXfKnQBd~h2E{Lsj? zH3|!L74Ty-Qos)({*zv~R4FET;lhyI41&RjX(rdnfFFV(m@}4OnQkeqa)=8fn2(7P zdN&^M6Y6cD`Y)OhQ6`qiZp$a&XQ>Xu@aTeG1pGXP3^*O|Luj|fVN8_g$Qtn}0=BW6 zo}0O_u`;3m1ephghYr+yo z3rpfV2r?P;q3q)rQDc?I!}K-_?je3;3aQwmxq^Fq6E+F%@m+}Eo>bptMsQDcP%IP1 z*uAf}KD%it8;15EH3)A~>{L4({!}XfWES2dRNW9%=>TpL-ZSg`0jjyedmL1og!cfd zI=m-U@0bzZvr=KgSa^>g!x7b_ro($Wjwgmdf&k~#Y?ws+MtBd&M%7m-ya%F%y2(M3 z)wxrJ_i%n}1}uE;@E(;e3j7UTWn{1s-qWeWdpZ$d#7P|w@9_zxmv0c>Q-KG5qIVJD zVvYqdn}N+ zj?i)Po8*e=*q+|Vi+LoeB8qv`u|3@??^SUa=s8wEq9KPib3ustv;YpqjdJ+mRs~|D z;@S6VB*y1zjVXuUVte?k*q&P0eXqy#yskYv`*^jH-a~GIiMpy(N7KCdVtEWqE~;iE znkA-#+(q=6h#}PX}d6h6iK>hX7HWmk*}PgfDWii<=FCAdJl0u%QD%>_;bkrEdTb87yA!jP_`e+ zU%Y=y|3lPzrb&rC1I1=(H~c`)yGa#LD1q_4vOYlBRdmi60XcI72HlI0e(JY(6KC-n z%!3?3+y(hA;y$p^j9Rx!3R{-+?*HtxBX%sWck*^;!A0Go>*uz7`QPj+S4#{D{SUNu zrI;RfM4_H?FIRf>%d5DOdN^@q1k$;E-2>*i(!)`H|0}!7rRvJ4fa%6+*pfffgGD~^ zwdR!(W#=}zV12{~C={xE=*!KwM-mg{A|B^SOjZe_|4-|?l6%)3@W4A~?TdEe_`*ThCir-s}JQV%8ho)4!a` z8(y+R8KiUMPNCV!-2&2x=jcFq1}P&vW}7}!Cx*Os<28jwa;ElaR9tDzV?2ZOZK~2R z=Q?8{XqBh_+M}$7bXL-zsRUL_QC95&c5H5faZUjNG!NrsVGQI& z5>gKhgEvXzv<)_XQ9jJ`iSv7VcN8X&$oG}rD^Hfv53Qxb91)uMr;PzHlH_U0o&bF+ zLi2AiqRmP_yC61T!W_8#Xo_Tz4&NEJRY4LSk!Vsb>2O3zTCIx$MG>b%4!+`OEgm)2 zUtyrvnMS5jQSNh;SxLgr3?p3ck!R;y?pdBDu=h6uQW2g^F43rfRQWQt5hAJ2%DU5M z1*Gb;OmX^r^UBRKl{G? z#|S&s=i6|%YrK;HRgDCuUSfY(JgUAqrg&7n`gm)w%YJ%oYjCN3^ZM2R;>k~Q8UQa7 z4qB*cUY^aZM+FEhrD8qBA=(ARNKLsNF4Lx!Z&)wZ`v@#fs}b8HZLoF$E(%U=1$by8S}&gkQ3^GQ)R>vCV` zJz~9LHo7RiVi=2uG{p%AmVq#Ie3aM@k^O=efzAWsgzYls5j~xvC ziJH$1nnD%DXqJ)_IYrgqf8v!t{idTI9B#a?O%EmeT2(K(ETj$F*7twbx3#KYeU9UC zF}KxCw6U!btM){J(J^cDZ8iC+jBTys$IgXj3bQ{KrW0r1z;uhV2h*!ai}4e9KbGmQDl=N)4roAf(M2t0o@FeW6_ ze@=|?sHVUePL7n6Cu%<9grMR3zQNK2HfGMA?rO2f@WO72TVkH3ZzZ3-Lh&XD=mlan z-f*K+XP{F>rf9oqiDBenOtF=9z3y`zw#Pw#Hb4Asl8>#dt9?Hq^QpG7kX%w9!^ZIo z&gaoD0i}q2d7=<3NF;=3(61>|RU$=^U1}hxF&kzCk=rJp%7;puQv4E*V^vqV^TorZ z=gEd~&~dVbKu;tYA&t@XCmSro&>D-yQo4LMk6ywup>isy27J}pJ=hXp@W`4+7K<$i zm=Re67{U#6fdn$d%Ncapv`#NVz)ZGaEmK;JCD;sUw&u%-3N4u2lVh#1qL{ZwN4k#Z|=jTnEj+2O8qLP+*PS9*wQ$91(h!v^F%H{r%Y7d+#RJ+`I8~;UFt+_ zI^Jr6RLprUt8lAI+?yd@S%PyJNFPtH=oXViv&=mku(s^rbXQ%k{9Fh40%@G& z)X&NghV4rx=LWiuQM(ac#Bj?~duOI%YZ>sO7UF6P zr`R>wPw20@(y6{G?5l~G+RNNeQ~tO0{+^WPOrA`7??%G?ocmVAELM6N_Or1a3iL6j zP5FoGgw=*WW;!@|0_QJq3aznR$jabPMB4tl(4b$rHt1d;MXRX7B(-3X zox?u+a;!ajW6ar9{;^;Zo~D(lfb9vG%t;5TDD;XB)Wx{K&31)hS&=_?C=Mb&D{<*X z_B`f_S4N-d)!9Jw*hniVuL#JT2*{`>zj~3Ty;_?hLR;+y8?crsiv#74CwGlm-`d$~ z6^Slm|1&tM8V_D?yD>$hr`Kck>UBapbvt#_pdT|N-SgHhaZ*SLNO=aFd4|7>8*61bFIcUjJxQ8xLkd3fn z4f8MogkB4;I!d6%;XxBI12y*8wBNjLsIeza`(jQSAnr0CLZAi2PPO|@N~nsW#fHGW z!e)7Lop8>5qbq!t=cGk*p1THN2n1&DG)K~0Q0R8Eg)-nBT1!E08&aYD7LP*vsRmg(Nosyak;oe9%OJvg8w53{)7PR zIyAIGxpj)n=RCighH-PL7|MXT6hIgI0Ist^cb%^!+v`r&lZj*|Y_ z?fand69`Vu9TH;$&1DB4-TUKIxp$GLxNJ1A)xHHXWm%j9U-2d9(0ACTO{`E!U$|t7 zwyJc$1+>>jM!v|4UfMFa6)tHWZ&Rl-gmGi)KAg-|v|n|7V0C=V^pU4YKUBSm&gk2B zvnu^`sv>_e`%6n54l`aHS1@>YMS>Cj)qSJE+q0Tb$Ge4 zQ6Q_*9FyRD<@l7|zD`wkrgY_ZcuG~Jn#)FeZAR}1AoX{Q_CDcrvCTfwp2q(M2Av>g z5>34w)&L!ur{=Hb9uwr^3Fy}JNEy&4+lkvW-RTz><-WPdCzGr+#zUQB9NBT2&M73QX z_l{7`*`Pc@6sM7c9ZA>Dppxt|#Wvb?LaS}&{hJ@c`)3`(<70wt6Ko27@wm9${W@{995h&Mu(yD- z8ynQTuDP%AGn~cQAWV)Ou>9|fyaW5jcVOSe*nuQi%&`N|_Hml0FCG`oYwQ4~>Di}C z2;JC$bls*q;Ku;UXZ1}vjFSf;e?08xswxL1j6vZCfaAAb5 zu?>lEO%b_?ZAjNOw;|#GB!LSx;!-IPD;ANMDOlik6b=e%q<~r0HP#Agk*4-h^ya$u z$ys%;id+`A_9&wy!P{3FWfhvHgZblBT$R{Jd<;$Idu{JcllflX_lv8^jJ@8_e%z}k zE3owikvbN0`aYWz7N&Ojxld5>4hz%w%{w=A4w*TcAw2pFLM1g%Rpy9bSWSAhmtU~W z)FyIu*wD;iG{5O@hU4IBTS(~ISNjsyAE%<2=o{vk38U0X!vj>bXPN%Wtgh@cW%a%$ zO?DMKyrKT`!CMA(k9GU*Eu)A zI`9zQf|WyN4=JyM{-{mWrA~k$tcng3nL#TVaFp|*svH7JpUstX-LG=4^E&5xXNox_ zjd_EF3!-IoFJqc)@5n*Ni*VM3IqT*lRVCi1Bod zBw{>6BZ(N#(n#+0%^JzQ{+q*ni!Msl!k(?|~Xof^r(KB6e`NV(<@OS#rJ zyPigPq5in^y8N~F$8Ku8G_tYpPubWX%kz9zHg+@NLlN%TKmovWhbFqpZK3`B-&;%p zhK;(Z@?cCjH@yGcQTzq>MgOJ@wexhlHp4QJHU$$k6Ly8Tc*U_7m~ERrEd{S0p~G0@xWOpgr~{oXS)=#mCE8*x zOeebUZ{*Uz;0?5kOgE*CZzIV--|rbn3?+|?*j0VrM=YwwIio`(5SnCz(|G>X076Yc z_T%s;uuxIG$s?Ep8HJ5zL;BC&G|bm>CDG_r=rr<#GCo_?mvHrylZL;)ODV_u$rxx` zJXHB;DrwfWSI|4wpzeiuX(MUryqKuvav;W(WNCtPm0UW=t2y9-^f?fBt2wm%y-bOq z*>?XX<`}P5E(F|P?`Nt#o9hC2U?m}#CRo1!)UuJ?W}6FE#X=Hb{FkMVf~&eaj)bQl7)_Xjpr>`5VB2!}K9JQ66nLQi_Py;UG zA>>WCsKH~wW;?z_Wn+71opa$do~<#sB!SbA1w-W$!X*f9DeA4X6JUmKrc%^EgclC= zA~h{hGUEOi_r+T+k%K@M18@XY*44yE_abaMavp6z8i8hmEzZ#CUpraJt|`Ut3$LSL;&>xaWA)|z z>fGx8_041Js`8Q?VYw73P1-0SigrYT%3TMLqmREt?C@}6PJZ4>WRNz~rN1cxFtn&JbRH#06W*ij&f5uE;87AKev z$f;g2B z8Z;sp^m*kdFEc2N{Tu18<9~hy>Q-G^#AF&$-){^ngKwm+`ohhIJ0F~Z6KjGrI72$7~-?F^=3p8m5d}BQfNd1wX`hYW?gxd5?s@e zr;CR4{+|}98q=9Jlc|h?8LMtBlqVy~=uj-$oY6&g=#Jg=%l)G&MbV`yt-;o#jI#RG zmg3xdLyOMO204;is)n_*Q=0Jb0mZrM0+px#J8d~%c~!IJvy&SAV41lWUL0tZ^Io1k z`t`j3x%J*hNNt-XOz&(QK;;05`btKT#HUdW`1Jjp2Q1YRaMmy3B+*@1XLZe`~c>Fux=aAquLT0HXPkndQ0A!>AtXI$C?)hK5K0l};s$ z>!GW-N zRgzMCTALU5>NDr1|cILw}0x2n)P`0FtI+VRNP;c@``%lA0Ry%Djt#zU)(R^<`NF{a? z=2&mMx{X6@d%wLryBtANg{lvfb2NRf)BTj@r*uE*5lZ*-G`=|xTFBUS-5hTPWBJ!5 z3buD43(W>>(9cjM6-*UMpltZbfPQNa_ev540DBGEo-=*0s>Jl}S6ZX2T0M0dMfEaW z4kjqGo41;%D?w1znE37zz%IcM3F|hEFtk3eL)GJdg>-C-4=E(Y*ZPajNBf|x}qMz11yx6lzze#B+?(O3~oGMU&xoL zQD<4JiZVfw#SLGEKdZG>s3nxjP6V-|Y`#u2_e!h0an4nG>UUaYC?Gt2<5imGFuBUm zAX0_bSmlkC>1u;j-e}tl=v=YLY2an6tXfS^t`grH9eeSX2dqlbs+xcmY|QnL{9`U2RKlAGbf?zOPUOuVX`tez5R$ zNfn8uEyL0>r0|9E81XdF(()CIrWLf+yJw+1&SyuC73Y(n9kL-s3DLHXR%z{rvzuY|En8@A3)M1dES=lpv^4JgUgTiJ%407%nUAh4 z&uI9mR{!XZp~NwyZs6AcnH^G7dwVi{8vV{{dE{5$oR5AZFHgLd@!MJdZ@$0xz4l}O zy+>T?6?Xvg zs;ZaNFYzX~LSmuuXrjX*r^xDG+GU3L?3MbE>Ib#I^?GMC6ZE7hef63zR}KG!mq-?N z<#dO`I07B@Hw?rlfHY84FQEDyYNB;2jBnGl?YlU4ZDwxsi9(%IQzMRV{Ao%8(*wz( zcVlOUvPz%BkSd76t2Gw~W#t4W74LdTokSc;Gb`EeD# zst?-HjZ)^3qSO$0MM`{#B&lLK4;2(B|2EbT*liW5hp$9RwGXZ24*@((KGB(XbcGrM zhX?`5!{oilL=WCAFD=EW|P{cgB4_5I6&y?zqINV!VQ%G z1lHRc4w^BpU}jC3&z{BeC`OUC$`YuVL8t$TssIg=ovpZ9lNX|ii-OrVI+Rp$hl|J2 zGnR!R9|Nag^T2rXma*ljhj#aWyJ{873*20in!mQnZ~XmI|BbDb4coZDi$Au?zc>Tn zTdBx?x&RV;FH|Sgs9OiU(QDRgW4*{j(Ob{6R=YR))@7m3vO$(!3cXZ_6-WaGfA3K` zO6y<$=kie`oFeDN32q(6A=0UhJ!IdmqWCTNswqUTu2>R38iRX55A3I3TuxlildkB zEICHyD_(;A%ohIJdFq)Og_F`AMT^tX7ca9r{?=N_OE>acf+1PS)IQGa9&NQib9 zUJ0COAQ5v;xUf)Kb3;oSr*8?!UiHu@O#gU0RXwcq8mDgQVlQd9SU&cThP+YI5K3$p zFctQaRHPdP0U+;{2p1D7M`GLbX*o|$bp?~icdE3YahO;#5(3?~e#c-E=}6F>*)Xvr zATE#N9ce(*mxHbqOe`fwr*vNC1?Z__Xq3*l;94i4jIMk`9%mskIJ|(T9HNMPym5{bpae;K)iU z>5E=ne)aplrt+)vUj4~0ozK;eQ1g54XCwB0-L6;L(Q4{^8&dC@YM-+j$&Lm!-*&8= zv6AU^S2v6BrhC)%{OD^xG~;PE3T)NwR*xL3ZdAmBm zkEj2)D@NZldFHi6p|G&6l>)(Wz>8zYK@8!vHCgxF7a`39(@}rNFhTunD?F;O$iL$) zuqBDGO%{_x42wob3=6d)qR|`0hMmdieA1db)r*C+?6n46dyVi(ZxsQo8-F92-&cP1 zHPem1mw8IXPb?4{{)XfMsHni)?EcN&p;@T=_p&sLh}5o#j?E40T9d=1g;{j5Ho%0o zs~rA*r*9H?I|c0xfMn6CHIO1=wT@@tHtAj$1f-9=XQ#}w2rTlNHlbtjs2f3t+ZxcZ z`pMttYs41m2vb34MsIWr5v`yTF`~7zGzD9%nKxqHjci28ZRm~YhQWu?f-M-$Vaka6 zX(!eQIZpRz#PG9MBL<(VHKLkct5F6YjWl5=F3Cdpo}qD8pLFawPcwVYXmIPWHTuDS zRkn)OgD)%J{E{PQeg><||NUZ^$nEgoZ)UfS+RwZLra8js4-Y+<<@aK?$VN}Ob<}(2 zTDHqR{JYynZ{f;a_C?08KlnrZRKDoFM~)mj``RNf!Nl|6(fhdn_TFLMi|ETgE_+ey z)=}|H{`dxeEIjiLj$t->XY1DWb}OSiC`P1%FC6{gGZ}xC3qGAa^A5~X)dyL@^WLxJ zv#Sp`qXp%7%LYPbIo#l*(=OdfXL5KOYsZ7DP8L2`8JWY55{+G8w*`@c4I?vBhxq=a zk$J+OqHZvObCbqp?-P?J1X9RQZPaTP;YQ*xiy2&1ZL(OuP zYXPS<;3T4?&)YDDY1~6uNsW7vCiVN(*h=(yKV>B~9-ykE#)E^tjW<$LQlAe~NmAo2 zl)cpWe9B#Fe1Q^m8E+$LSL2<7%NVV1I(hp1@sie{Yky!GSh7oAp_b~p_SI^su0N<# zxy!D3eGA*2zWM*id-rI|s_Oo8?|sg_=iGbFx%bqQTXhTF_ki(|6jJ^~C<(^eXGm2M zBos*e5!x|+{ErX6&Tf~x#5O7cq-W6b-3MpK$tHvWE^7zb%fL?zKE@ezqi zEX4;tA@SJ;p+Da_*V=oZ$At@t>CvODgmuq;ti9G;bItdh>&+@ysXx|fybA?%&PWCw z1rTk-aw}52Yp{v`t`6qqdI+Ykya|JzXJqY*@aUwup2!E=bsWGZBR|N}y0&}JJpgV7 zX)>!Ha?n-Rx>8bm%Fuzw<%g+SS2g|81x1n{Mc~T{0HJrg!`H2w$7ev*rFfXI2)o zn{w+8Yb+I9nmAPN_{;Y2(|^^r%eSS)*?X5Q!?u54tHT1R7aaklc6GpUzZtJ2tn9o@ zfLYHDV1*3k4Xep{^3Ft7kbv%#Rar0*rx6T#3wcK-j)2zjbmCn4tAZOl!}rhYez3X4 z``qC$Q^iZ#hk~7qA?Vp)1dGp>ik{7~XdVpkg)liWft+Lu3rW%_|CgmOZLQW-00o+c z9M7sXxrFLvzYi+}?*qsn!J@Ub_y0&WCn z{`*XH`62GcNqR@^eB+P==YGI5^ZVs}xOYcZfnW-Z#T4?5+MMOX?#}BEU;o-g0h%tP zd-93JFwcz&dT&^K8MCu_$g6&<)pTl4W?%`40@v&cd$fFQOMGOLC%V51{@+=Ynv=9annyl)sE%3@U}TA??t%+l=T zZi7ZRc0^=F8zq?NWUzMWRC^;Cbe&uW1qcLmQyr2{|MjQG3RJb&DVHy9bKbRzdmUyr zXcx)PmKaa*d>@eP zDhj^4p$?|&2Dp#$7va8EScsejHFK%}c@3OT?Mq;Z;{JP9Tn%azZhXW(1c~{zUMvK) z$^8Hrm+(|VyHP!^!>P*WMb&`>NkYtnnWP7`4Ps7#%{^Oa!luNX^r-P>F~yrKghq zXIin+(^6bMjW$_H`H097TiGG{W;x8oMy1$wstsb4moK;lmMTuRL4pC+J1sR-kC{da z8qE7gB3`7dI9j`8oyvNk8SFM`sMn2nUMT=^W?opS&-4{%60Ejc>hK#+JHR$46qU*^ zk>kt&A~WKay1}2mYrcPXS_E6}Rs&8ix(_@oNeYY##kfROxHEj9~LP0?1x0L)$6rn}h=+EzFr73lfUYIcKU?@Z*Zu0yfEbs5?C z1{)4I7q+7P++{zFf=-g^-4jdTX3r8O&y0Za!An6XQBi*y8U#9)WhsO!(lN~&+;r-5 zjiM>EP`jWMwqSf%?Mq6aL<^`$+?&2Wf{(!(8t^ef(TtkKGvtR422Ie!Zk8M8nz(#* zo;Ghhtuzv76hdAg6rsw%!^|9wQ_aG-!9erldHZjUg8A(&18FQ#)6d#=H=32^soDf8W@c^=%kcTzwyLeP*l}M8w9pgtQv| zWF9t5g}wkfjd(u<>BCvj&}6UG#cTS1Ok%@+-m+iASG{68J81F1vL00slwCid*9W3# zRR@8eErrE*UD>y&!z;qaZLrAfAc3~1Hfh+R!Q8sRw?%E8MZzOs>g(J#n3aUu*I6Ro z$XBsy22!4sioZuG5Dvtak7rqN?iv-MCiHvtPw5sgYp7RHs(4R%n}G%Nw1-4s;5kb=MFNdLC|OV$LmxiQrTyg9}g>9Un_!f(00m$ zM76rtgpWve)9*?o|4+3UzW%R9_|<>%k9gsT(%9yEaB1%d`SAfi%lj&BQ7}$-___}x zYx+Nh2Ry6Z9q47_V9{-BmSqu4B-=A+a+?@T2J5R^LdT>ZVL(7NqDx zAJVy_L;Bbs3%~F0dz(2>7vCUf?gp z`pPc&)Qk%eRzGdMM9T5ga{1TjiTUolt8I>=54ymR%F@Wkq2URZ4 z{#&OP7y2wIfLWHvid$)~h2v#iRHD9yA?>JDiPHLtqz|r=v=t=lPXECzgGIl#DBiPR zqmiVb=U1nb0oQN=LMKGXFwWIO$yT#8Al z^z4MAeof&-IAJMXCl3dpOhnHJ*qxGO*?aMrs*Z>&P-Zr({*{5g(Cs9AqC<*YssUU=N?{lU@kf3SKljDOL_UrGhzEdtz-EU+0iJGzl?I#kT=3+#LehnNx$cu<@`x{KY>hTouvq;mNUi7NJx3n@Lq zy7Mh`&X?!) z%XE;G52Ag2OL2Dq?Hp%{X0rNKR4)$}$q6bs3C9xJMD;%A?3&~9u^7Y1i0%dp!u)T?w>;}mh?Z_6=51-`JW_}db!lf+uKiXS^n zua=Rl2GkFg1MGioOYx!qIG`?0t~fFtk~n}F)&7-YV*CiUj=C0Z+O9J}ZqUMQs4Zl2 z*KH|#;%t1y{8rkhoW@}OX}UrzfANf94Ur&*xhP8DFqPpgq&_*bL&gk9_u&X1#AdVg z;tr-J##d&G4+mJyR|uHNe=h5IvVRIL{GD|beV>09UN<7?2>ucORyzFp2hH>Jk;z9s z8XpN-*+<7734%#dr1&e==K#GY%&_!;ro;Q+!+tfEgX(rq_yor(1R`MKUoD_H(viOp zgA3f{@5{02z0w{2vG~1Liod19FMfByKj!l6$HH471UGK}kH@!u!{2((gSc+OAd!MU z9^R__fRXh7d+)04)9^MJ*Hh%uDd@YKGeWiH0xt+;!<7&-&bsJz)giazdfAl)+jz3SM${vwTZp>!Y^~cTSf9dTfPyt!B#%pcAarT{Hs&}KQpdT z+~>W|=Nrt(c3>tI9PdEsD|i7Rr11Pmp}*Zj|uU;L-hFaA^b zVrdgx2+;C2A#N#*guwL^gZaz(7*X*BE{^6~Sx(%6jXmXho0!h}1(BMCXDNKi1{?6R z0>RU+poc^#lB+UCQ2p6#pR<9L4$Dvf{poU8er^Q5y;uVdiQ(so5JYmn5sjFIFC9~c zLaf0xQUeLIVstK_%t}7-5G^^D2TkM?OIDy()!xA@B)KX1#9@hi(j;KWXmF5E_=uFP z9Pt9M6 z3!_W@h0t52XO_q{b)yI5^1TjntplC!AN}I};fssW7e9tv2EY+>^w=C!?!XpOp|LBNt)(X5@MXE2N2ms;SUggtKZj^Z2L!t49FgPPpse;Wkv=OfE(E&=8Q4Z$ilucf4BtJs|$-yjdJ`~ zd?qOYPp5VjUkNiQa|5e+fYN4#Ez?z5?qH`eY_HFQ3mW2M3~go#5%J23^X!yzB}U!( zn(^J~0QJP#xgL9QfdMFUdy5C1-4HhT12(h%mo^p;RO=Ii_=uDti0_6R(Pn~}fxZUZ zK5T0EP)ssj7~b=LpHi9}5k%n&Uk$Ju{_U+hK~*sjfegL%PjP5Y-d+Fv)6uYcWNU+DkC#^USM%Wx!3q07bIm`5}$spS^1l0tIgV^LW>Zd0)kd zd?EZ(yW`J|R)jP68h|q~@qi;9@0{>d%s!=bstc>>3pK(X*ZvrU88o(`Poa{zNlsJixY`=fncc8mS7bbj`0_Q$sKN#4*i+pP*Xe^9{Yjdo@Ee3Cb+?3UZD z9C(p*eq}Ce9&Jo!uAEt`w5OWXECD43&Z2&-s-UfAT}ZXs{)*SC-i#EW`#Y2c{rCw$ zmZGWXq44h}m5xncF}(FxUaJE=aN&QheJNQ^{PBO`Q9(AZud%r>bSBl(_ z!u05hKWQD@^QW%~9US|E^kDJmpQNFiV~;cr7GFv)kr?4m{@JUtBOMM8IVUByR;D2Y zn}&U&ICioD`!7DVK&BPK*rSg&4v`@BzZ7psUz%sv7O#IKy_V6W_C`4eoc6`3M;pqo z%804t*PE<(?PoP|mCDtXyOMn(jK!}%(y%&<#T}0{_Vs28yreue+bQm}KV~|`efCGQ zQ~b02(dZQaVt+8s58tJS`8*9GfQ`?%UNsg&fB%`w_{ceL$FfWE238!UbaLltV-Fej z|3qb6+T+FRKb>65@07D}fXHos_FKSduL^!|*HvmX@ICe?MNMAbxLho`eDoc9RI}pJ zk(IWdBV!QoMX(JT#T$;k6n%x#SJy%x+SgxOeC{8$I=~gPex6WP9BsoqgELwIe^*_k zmkbi>yQzdYa*oDhdpVy86?fA9z1(mDgD7Hj!T_A?=f!654{?Rmk(bfkp+Qpc<@A4p zb`)=iw4!2NynHQKtdAW6%PpqPJP|Bsa`C|;zm^10@b6j;Rjfm`xzy$>vq%R{nr5K* zO2?r#642Z*!&iJz6fFo@P|Q5pFCXVf7tT>;oIL>{b*rBQX)Wi)Lu;o3Kul&htn;LM)e~PbEyw?%C8PcKH zrN(kK3M>8R9JV&U5P`xJ^i2WMqF^WIYUxwuTtoJh&DG!=Ck$|X*p?kt4m->=wk1Z%x;RkJ@%}m0fyPFqC$KQ^jPmEX#|0S z)&vULSi2c1M8}ixe~8<|9oiIRmcG6Vf1aJ>&%0}zLVP!Ya;fdI8Prz%*w2tqeL?YS zC6?;`F6>77-3G(f!LI`i!c00NGwGZ(d!4tX1@c2b{(4I!!>lCgg-mh@PTs>8NjcT7 zh&xB**(wR_rxmK?6^fXF3-V^fba-1zj66@k0{kLpSPV`KtAsc|&9i9!4 z`L|1ac+2l?5I&S7R?{ezmX@ln-sV+TTPzpL@jK~&@*kYRqO~@&gKA%hi{=xbx3W%N zX(bC;moxoOogQ;8;ZZ^Mp(7O);iQ-YoUf$qrD7wcs7gr}9ffC~JHVpqvsaO-tJX6I zR>|%SE8sg@q?^stMlB0^1(gXXm=tz6tORP3lH#3SEAEjBj?7$QSe`Cq%>+_6C+zdt zO`98)q>%TmpV1Yavz2V;bFwmf^d@y%jU_T>G#nyB1L-IOEcC5*`LHKdwuf&xWq!v% z7I17@Zy*hah*JkH_U$Q??HCzarbw>wxMxNxGW0%5dI2ZZuyidC_hO(7qayN(u zL$=C50Aqwsyd~O8C~jB-hFYN=DQAYQs~G|RrWt@=V30PO+sP<^;rlftQi3b}Po5r& zt4;Y#)SB#Tc95IPURmL(m974R?O1xPW;~Hr*fP+C&v~+BOLVrXp=OB3*rZGD9wvxX zP7HR%(5NK{a zwr!%Z)WIhFU+iaHY^5TFXD7Rh#c7#&!rpu(bu4y?*M$G01^Iyzmynf%u$B=f)a;lM z1{A?+Q7yMZ260M{SSpMUNtz#(;7tOYSM3c)9%KUHF_NCwit9Nf)zDPR9noq3W{V2F~o`9(ph{EdvdxgnoC(nT@K>zE)WdKYK>ZmzR zJFF6Vu{;iWO7c{uFElUNY^N=pVqqjRua+GIAg{jzlOhONEPDuCJoaE>$Dzp0(U2$5 zK$W13CWeJ?1vVWPK5}XjdrR~6jBW0J+sY%~Z4MYvlk;NX`(N#Gl*^P2_u-@_=t1di z$ElS8Mr}MwLgje%+biFz94~AHHlcF7x~_7(YWE-r>iT}H>1x+00EVb*H&?e1|5}0J zx5V(hCZHFBE~_MlU0D|Arsyy1K0NA(fN9}N-`TD}+JFbhjDxbZ7*hTBA@DH zD~Nf}S?E@d8H_C|DyHx^ibJT3>-+zCyYkEY8r3GKs%qB|Z*0aAV}h{KN!61i&Y;E3Q6C~Qur}?PYquWk>SiAWI@L%1RtWNu~F@$SZ7vLv)Y;S)=BG z&NAek*(RKNhxrO>Pah^=#xU?8ULr!f5I7%7ZSb~c7UV~68yVznml2yG3OvY&Lm^yZRbJH|E(%t(d+vUE(bTPTi4P${DnDG)8=sbKR_te9U@tUx6+ z$&uD1M_M~oh1Lq!(^?%f+IVOI66H?Fyw@?KwK`_BNR}#zn|BGst|ZD2ClV<;cWjzo z8vcPgFG6`UUZl1UFH)=0@N-bc9A2c~Dh;nzrQvn`T#7R5_ilKTTAd`I>v+iQw@Sn7 z`ju>UU4Jp|b^X2uUZr-Oyvk~WU_7!z>$>nNc`zvnWo6KH8|LQqv1TzW( ziEbP&@!&AMWx)A0FJk00d2czN<=pq-w#f7PW{1|%9q&jhIn)ST^QOFoX-Iw2Bi1l5 zJf{~Ot2vk@@;xUHj*|B3k!v@0Fm5#VICiE^^GKN)uTQLyALN&Tj5i5z>zW4Dr2xdE zkG?OtlyS}un>w1IdNc2F_l$kg`FqYTYX3#XcMCv|ZAfICp51k@n7{1sV9^96@!b30 zo9v@{^K5bZJtWZ--~9;s0*~z-EYc+(LvKLnK@w;X$KqdN+$b zRYupN;l<*P4^g*PENP*5;QrRZV&kP00Ln!qDw7fD+Jlc;KZ9QJ6+O4<5{4MQE3irs z;e(3EnjaFX#rS!R$PBqE=8o@7?)m7SX2qNCZ(X~Wxy}vs^9YwyyO#Hu4iwjdw@7_6 zH--ku)aE%n!65z+uV|#Krt*x{%1UEIrypdR1=)-He~uB$$#gv3+E8H}4X*~QJ-hQn z5zm2xt;bL=h$;&eZ(Tp)t+dF^VhXTC+!G7MTik8+(Q;MZW*6?OF8tS%$-&~cpLQu= zTo^v|Yp=<0^7bFdSQv!=#U91trO7K)djV$JU8*-O+2YaSfl^D5qa zxKVqPYIxc~gG_@{^xE9@OH_TEK| zsZ6Bn5yH`B$BD-GKf*(7A^e#ny;Ev$nWz9QrY6Rj8umqeB5VrVJ>eF-qjy1q3@nFN zt4iPFl|{XRjcte*auzZIv1vm*YP->UcT&?fQqwk4gZJzfXwIDRtPWxQsE@@woxyzUj;rle&N21D;V7j4T zUVv8+&Jk;)Uh#xzA9y@{W)O-fo%Iot&_oF1SW`N~JZ;h$t+{q+&9y^|bhd;5qu7vK ztyP(&wJNi;RFyqf*OAtCt3^sPb2lYz_v^Q+%&H~EprCtytW0TwFRVQ;k5Drz;-$%KDk%7IQ4T%%*<-dRO8~A1Qs{d z=(kKY`n`nst2RgcRZC3GdVFvZ@;Y>QH;`qDe#k}57LYeoT@onkp$lzgrPlAp?kgG2 zigY)MUHgDv1Cdai>UiF_)qfChK@?r1_?M3+*XrifF2CYZ7)oC`1cK2M zwC1LhF_`;7ULC#95O(XnHbU{Xbl;%C{RFX!zZ~M9bRZ*00`Y(FAIL~a@rFAQ ztiC@$Mk0I?cU{JM=*x6)v&mRf zIym;t*g=u-`S5hTUgx%$4#TDN|iJ{BcwSr>!^)y8l;H-R})QbT}TE)N-8 z_r}AsVUZ)WY&`j=U9Y9p@v!<0Wn5AVWz4G$xf&uz-anHO&NS&HuWv}%Iz{qi17*Wm z>o(NtI9_c`-OptcpLBkVSFw(^j<6y3l^fF0QfobR8?pmHjfrje#gExGw4GNx=s(yJ zwhiC;G2e!!del+c&GLSzuMnD(szB&KEe)Z=Um#3ATjH2-|2-1HT8Y2KqLF0QHpm92h#%pnI%poFd zGQX?`U4<&{7h_}R=@FShvKOs1Szuy0b5+tCW>-V18mKQf-JB;!2FZ;ib^yuYz2EzR zNT`Sml=hJp^26X`*K2O9k#!@8an52uHUdnFjiMPuFOoZQC)S2KX1wQ^^8!_6Gz zCbbIPHB$Pl|3`H*N~G`*Ukd6e=tkVk&WrseB!yE5SO_uLQ{Z%jJY1o{Lri%3_`~xF zVn>=cj$j~>a8Ha*;1~RTIi`u)oRZ_uOcD|anBuX&3rB=Eo$H&__V|82lNk86M81kZ zMTy}Zovbt0XkHpd*Y~3`9Eo zl{>9gO5n1HaPa{%@33$okG%5a*#q#vqfArsA}spgN>{1ma#mL4t6SC5c3&Ni77u$Q z(nA3r1&BWU^ZRfh=%30Bmr;-r8!%MO;Fc+U2yV>jgpeA|TbA3PfY#6G;9IV?!T0)a zz}w*>DzaxRQ3RZjFdSvuGEaGUQz!T*px6DcHKKch_o81`hhww{cDR&E4fwxY&H;m1 z{GE3%V*3or>)J-0SWBGHpWoRUD~FR^Y}4{}V?nb6ETS7H_xLT|3^6in+qwRC3DfoY z5P?&Q+fl8{ZO`c*}wZlSdn_%OgPgf#>l4dFpe@kM+JU3(h^XH z^%f2m821nfS+9se?mcPAxeFCf&xwwacpCsUAtM;} zilbmq0*0vCw$FF%`GtbxVSb^&cszxzdM%D1gvA5|3oev!^jehlpqy)TJ9+YX_o@JNTa@5cDG%<`3Iwkl0ClHILjVm96_7SgC%8}; zE&vTKlX!aqpcOdL1*Bx>^X6jjMWTyJyav%l3M}Ji6kNe?)3a$!&!)u-lIuDy_f@sH zRCcOGirl3Zug7k+NRt<;#T)YcifFqRq)0md`2RtEJiKX`R6IGovCfgXpToXsu@Nq4u`Xu{i}8kDF=r_p22cC)}{d&#<1VI8tBemtwVeC zDhJUbah#p7PX%cr0@~LfUg<`f%`2TC4;`fXdb8P-Za$mOUxnYIAwLZQ6fZXHzp|g} zb&SQemoVp~=yx;6i=$F)d4C2BF6If_`oZ%K(LaYfAC{ObJsqA$r-VU~$>L9Pf{_A4 z>}Br4g#0d=g!)mJCgU@!D;U(=FunPJ&C{kBU$hhu$dC2T3wT9LdBvSIcO-Af@B#SP zfV8lc8;98|5f#H=<{6AM`oEmX=BG(PU#$BTCD0}-h-k3=K2nW-%W$GrF)q4(CPsVx zmNcYxmzK$-pauJVA&aT&&qo?k`vRmPwO6uQYF`Y9)vi-Ik|u952b>@XLW#~TgL&{# z5{3)XRI&P(-aAJmj>8`Ax@j>hp9!b2$uu=Ro&?u8d5xhiRpKYs$DeiB(Y(vlM0U9wKJ-Q7O#mm&{cR8 z-|p~n>kpLWD5AacwE=DM5k7omK#GOX18xM`Fq>tTnFHT-^YUelsyX1^6$S=6s(Nmh zJ?GuG4mdI#3(uhS^ZsCGv9q!mNj_H1HAuc}FDB_r4S?kH8^pC3d~FVqpRX3u{{pp`Sg%xziS@-5EBKBTYf&x&K$UACOhv9s?=E?d^#ZU%y(MsX^jrM{tcnH@IRw)(1VTYb=|0lsDSj=!jF z+X~y3#T(zYY%Oiu&b!hSmqVN?(Og>NK`T(jwoyg49aE(xXIz5)0z z-Qd4QC-P%mf|sToIW@ilXt=f&Me|mgYXRO2X(gfvhC&oxWxtM+>A2n>NV9aB)nW9A zH#eRsv^QF-(LEqT&7;+B8MBWuPE!zbBz|)1`rmv;BtC@Ulq!XZed{=bO?tghiB?9! z>Z{#g1pE)0NAlyI$8VpOwQri8v_77yb4fzsj7zGOtw6181&R>NVFGH;gnR0`xTIQf zNwtc;QLE@1J*Vg!{T7$h?<%ifa1vGit z6P#l$pvevRh->x_v<@L4|HK>T+3+>*ZVdnFb6th@2SY_DcBPO(@EF!?IesDOtmnpy;qQNVssFJJMKE2U zMw_0RH;CVhCozaVt_JC`4+s;TXzpg&9v$oRGR&s%Qalf_s93Odpj_*Oj>ypo7(kfV zFRk8(<-^eobkMVlsH?2EKHA6pSAq~Bq;u(@1Lf|Xa6{I+9!CCp@JF+qprQ4GWu&1x z2N~v&zc@u2J;Rk@gz9y{FhYer;8s=|$~b_pcxR7_y7Qf(f~iG>gmFFs=Y*?ZmagBE zN^PGK3mPYosVfsS5OLkX-{2CGL^AxsSGOUhXka#+U~mbwdE+}~aEU>g!QetcA&>j) z1-r@|6-o$73@&JH2UG~Akyx5HxQ)3VwQU1(eAula5V2Z-XY4B?R|xZ*iGi6R&XY=U zBD!6sCi^DK3nGS;pt1Q{qL#oP%omQ8zzeffr#C;YulIscLn|+{l(2+I&>AjFF)^`h z03fdzbU8E$m|ii0WQ(YI6+gujZvd#%C_Yb8Od zLLqJh=!L|fbokyMsyGN^q&P@0goFgCXybDHnJrC@RSuwUv7Sem4u2q$uN=T&AmNlf z1OdccCN*WBG_dya&hdvk5{eWyJQ^*`I=F?z0%C)Cgnb={1$(i8t}uW9sSJ+cqx_G< z=w70~F%9_vWW5lT+UVcQ3BkS??CBVX!0QD4VT15p;V>l}J@k>&>VYMFjgbZW3LD_7 z8>5A#LNEnimGVIied>=R z=P;><5x5ZtdZiHrBThe-ud00$a>G~Y6+CC`z8}CBhgS{;GB9vXH@V#PAoK8xHTpBu zQsu)ST0%Rpk^bmi3SX8|L3ZhJrsEK?@L7=r|5q&VX2H_4$h@HyMgdNSxBl)9BKA3i zIRx02WkQW)MFk&`2o!2)ai9 zkwFp8p97zQIl324nrrkwxmbi_=GX`U5HfuY8e)`ESQ>kZr1)$Ps;zyyEFJX#v665` zY@aRez|Wo8MCu!Nou5lbu|Cvd?A>qwA!OMBCdzV}qh&}oBp7qCSP@zBqrQ5DpZ>-P zjE#8q8%e5$5UiYWGuHz9!FhiU zbF=_%KR3|P+)XYV+DH(59{fy) zQ*#DgLC)~%Tn~AHXL9$q-nme_%RU~t`_;F1Yj^Q{+g*XlS#Ve7LBv19d^JA!OxHaM+f0I9bV&x%-64?|;!PF5}mR<7Ex`CcF zsPzi#Y#gx3`meB!JPUj2QoNsDPO8@mx2AR5&6~0Z|4JNU^)Ixr5HdB}@1NyBPBelx^ zm&q$?Z}12r0dI%uk_drsW@fWA;P?~(kU@!{|4pXv? zA}UDel7woHxzvb_F@gn?ktn>UjFB@6U9JT#SZ0fV0MPEIDrFgeIU^XVNK8pY`C?CT zOxg=BJIuTEUhFFS4FWv=h_a)mVO|Ruz=S{!)}RItDV2T;ueNKRw9-5QqXPM4nUsUU ztWczaZq{$ZL|RHS<@!zer8BEeW4Ow{%w#i1o0ES2b8GQqxBzX9)uMpGB4rMx><+(G z+d;o~KFn}dux_W&ouc2!%teAZmNNs$fT`4=#z z{@c^2Kh<5K;C!ZlKHC#)%p$iM|Cj~U`4UyYQzOh;B2^@Wb0F_7ue7o~V;`ia1lgfY z!9E4PLL@xfW(hoQ5idaTbply=U_i+xC=*gOuUMLxJ6Q9!s{4BSjY^wJ|ALJ7U%#~o zNI?9UZeyZsuxEN1Te~D~5f;kYYcdi(@W)3FVM2$D2f}4vmp_`I3r25P$|SOd7UunC zGf_ICjVG|nS>Fdz0X2xA_=Q0TU>JH1VWufV&qiN%ceY-Buq-0M_9!DG{AIQS0YzxG z6`fY_+p@YKPhw)C$!+Q@^3EJ1d+&H&|yr zHHTGWN`C7n>Q)WKUL`9K6p%*9uHTQH-+C4~MV{AsAp}nEJs-JAt>?GOs)5Uxex8^W z!&qyAEmkZxw}c&eh(u)CrH2Tokr^$HYWZuMhBa+4nmG_QJ2Gq>Rq{yVN|tQ=DRq|* zT09GKS4jY^yzwG!bx;Njk4XSQEi!usX5(7E5xAtA>=$z0txp@OyfHbwG&KAMRXMN^ zla4^A{IqQ9dUJ28CT&BKR&|J`KGaO;9Z z_9m*<4j)c$9%i@H?_jK!ld66F0JeXae1g$e2OWi<>k&3s|N6s4ckBU0-UlltrfuAC z#x!x9T`oO_8roJ5)_wNQ6RnkKKMNgb!H)L-}(R)}+-LF5b+o+rEEi7Qjjh z*e&H1K@t!GHv^;I;5puuiQTWtJLe>^qxd4$e}IdRHem?Z@QdclND%=iIz@KSCm6=7KF`{Brz%2^{ZC4 z+4UE*Ji7mjxDM666sxMUD?VXtJz)Y%IWsU-Ra6x?2iwpD^ImQNY+-q z!@7xYFf?Ejx~DAow0h7LlzFKEWv|aPF$)*^sOYwheP-R zx^(;MW#%bE!R+vFlB)(w%UEZicuRRJ@5_R;vQ+CrBob$*Vg3@KPOX)`iW#a%%^i@P zl@@}`HeS!HgJ6PM8m0YM$T-&s5p8&qZHGuUyo0uDlz9(}(;nWz#n9^7&XVFHiL!&|AG%l%K$h@mb`i(>wt~&Muzg|+0P#qydf9zP~-wHKeQ?{ z#=;yqssh$@aU~mj#sb~O=U|--mTVzk&q8kNxxlBv`nWYA;qo%|_!e0d;czozr`@+7BIOQB9QNv!;2QZ6CT%+|5VCERYF zNTdl~2+qXS5=jM6ovjj!=t5%^>D|Rt)ID*^%A9tbXt9C&{d+bHu)gGCa(Y)bPQyH@ zP0UvlUE=haA+|>;lJV6ImuoZFGhwdeefmt*#YUU!7@AR;TBGPGdDAATS#PvS_Ue;# zXGfT1@NIC+#?(pDg->$Ojnf>RWHmRBreIfvS+M6iLN@I6dFMqSE=hkKp<;kV`Fx(> z(qZEpIRT4>8a15dhvRIJ3?zQk_8Y&nlb~~h89{Ty3+bSxU2Fj3N_GoJo`86RWlWe$ zTu+7%V?cl2&5C4P;u`#vLu4`36Q`}zBjQ>d^#VB$3$cH&QLyOdt@`5hKt%SoFqtDj zn5tnTL?!Ryc^rO7SR9uQ7-vxHQQS=OO`OS+&%8+J`&38Yr;a{CDzbXRLLOEYJ0qVG z`i>Aoj{yb`gucNgwHEr)MIC+B{piXD^d;T0#7je8hANWJsYvS_m8WBdQ3X#JhjUg$ zy4+IJ$Hb0``yybQP^Y{qJcDu#;JPCy<_|dz8h&X5YVTG0b3nXOEo~21j|_k3*H32s z56!{2%kL6Cb%evtoI=eAZ1YEM#HfM|q5r#>SfK*L-P5U6jX=q{P?D~$EqCtAosTZ} zj5Hpt@c5F0zT->owFkpy4sOH{COtv1#=xuYr!M)EqF59;5K=f@gJxYmg%N6Em|IZ% z43mfHRqPG^X08(xbDw9JScw0|;Wm{@l@n8K%w6=>s?*`MNfZlW{xe&cla0~M6hg!$ zSp;9|RLNqAmxaK&wYH_CG3a7G18-xe+Ki+5nsNwrbthcl5+k4@LN7H&Fd zN?6Sa?00@WLhwASJ|GE10&%eSq_O{a@z;+eKb?R*3Z`xOuwBY^A>0YflK593F7jCh zX$o)X^Fku~>0Z1*zYP(Tw=WS>@}^`Q{7^uA_Q;K*8=pr&-&AzbjNGnDewsd2LI+d}5HikZrVuE|-=Eo838lGmsR0+V5mG-yUi&$@f79Gt6#7 zKZ&^pr906_AdJ?RH-?cAqA}8w=f9vAV6=*-`aZPuyKq{ zmc7EY|8RpnvqCP9IbSvN9u&Qm_pYY!QUlJ~!h0dT0`tR;V15{)|KvMP3?EHpY>*uS z=RnNZ1%HS%oV76DeDiTsO~k~j*ld-7beXa30FkX~{xaRB`&g2BZQhwH4r8&^o+ahp z#QZ_$ax{W`TcpvzS$sn38b;2G0Ig?F$o>xl@Vk&Np=s~)AEhZbq2&QfUuIr z%Cp@KR{6H@=wd#DZXgK)%@W6AGaCRg`sETh)& ziRvNw7O|<%z^49>OW^4~U$~>RTYl>Ri6D=$ATL8FOfOwoh7v60%gc~4t*2aK;UOe( zZM67`JStvrfgwximTsC_UVquG;Cr%x;90%q^tN^Ze%Mg14r!qHOtxbSGuPSnHC<=8 z118)E=d-NtKJc0ts&&in@tPR88LTD-M!5@hA7p;MT8wa36N5nQ1Nsf-UZs{=7%x`a zJ3sqHwVc25Qnf@*U$1t@c^T2Xb{@+SwVcQDa$@rAK$c&#KRA(v(^I&@kt}~;e{d$t z8|@DcVR@_l!RajTus=AS8+=nm)&iDJoUWn!}dphUUpCI%#}~rnJd(f zP{CfvO=cE_%q$7~x{{qJqbC^!94=^oBo`yx`Jc^8_>=Gzye)~+TC*$3ui(f^{K`gj zUyo05nt!EUC!QUfB`YQxV1-mlg{+YB569FBw?gXr&fqWh)QWXm@PZ!hQC%~j3dY;y z__MPe1M+wIMVLBn1`IYTmzhh#bPEh&aH8#4lP=1=#%wnH{I5{Ru>YPkTEprN#~eeP z8KLl+^Uy6>5e!jTRV`a+-Y$;*ub8Zh{vmAYjKqAzwgEKp6argXlQ;ne0OMI4abE-e znc<=_9<+7_7Y2-(yZ;xf(VIu2eJlnb+aZU??j7mH-*iJqDk>h#90XecliJk75e?b! z_kKU~$p>43m$2q&I5UbQwvU@Xld%`k(?f`-NV%MTxP0Ko!VL@l4s?UU{o1?f6LEWw zC0$@ZH+MJg?Ip0LOuDeW>+bHIx~_nW%1|EbRNvak<{me&nV2lYQMIy^D|TxMxk|s4 z{-aiwa$Vo)NivymRKGc1%m`TEt`KAX8 zc%2D*q2{&-;Gk)h=kTkXo%FHik={#0Gx*KFoAh5+ze$rXEHv;AW9uL@+g?KkQwX+@ z(#^r1uOq`Xaa{e6Z-}UmhtH$Ugjw=vC;c~;w%1zebzC0oGHhS7#VhE6xf|Js2DU2& z+`eAw6Jao#i5(srM`C!+u}m0h6nz;?qD@L{!!lN|bI2q_h5Ut!2*FG6$xW*;t*OQGyE)>BTVHi5YWs-}4F;_rPb2IF9IZk1hZpOLnacdcA2 zG8?Q(J8Q8BIp6)ymOBfG#T_|&ym%!68kQ+)L53we)D$Xycu-L|_Dx>Rn*=shCow_= zF4quQEzPP|oZIQBi&?uQ#0${VLDY)^KHcDC=>KLPpxIfK zeOCMjDH%vI4h&bR^zceQ5>nN6nW>(BQ@1l9o}w%1TzbkbicCJbNXcMLU4G>ddA%5d zxp8FoU$YRC*F>u{O3edf9LdQB}283(O?9K@)1BHKw~kFU}oU<3m|(OM#pe# z!3>C6i3QEg&4~-)kpdDIXrA@vSrJ+^J!<~R*jwc z(64GdO4c+29`YaZo)Op$Q8?PLrf>u|H{poZJe9N-(MAh4EkUB3z|tClr6s# z8?9xv(OOm;EyB|Cb)PC_FHnmo^MG1}rD+ju_s>obM7paUl)<^CMv>Jj5=pHnvs(Eu zb-b`5kn~$oW@>jrv331iD7D(%kWO8{P;QP%U+H*cQncp#hG=?>kJDN^Uqp^nu-&$) zPVExGRbhyd)PhJe5Zg4B!pHZa(TV^C+0!EuNZ3OluV^K{*my;BSeJkoRK}!ZUe_4r z1~bj0Al|IMO31KKuUX`WR60V!AAgIc+0$*(ZOF=HSY);+qDtE_@Bm?WsL*AjfDD&? zMgr`)4w8ayB8H?}KaOe^@{5LN83m#Z9P+H4%5aFW5`^I-bEQZ_T(-89NPxvt?IBzj zp`a@YFh?vEizGO9dX&0qj!G}j z5W!Z(?Rhv--d&liZ7l zHG=!(gOHR%YnzbPHX*GA^U+#>6D^zROg)FDu~RLJ3$dlE{b@_Q`>fe zMTjDZfQiUJ)ILWBWG5gY#2~lCMwNAf1gUZ_%=%tXg`%(*OnH)kj0DbJ zz|>Ri1q~tLZNJ9AN6yE{k+NO+=zp)=0tg(kh9SDOu9YeiX&5nx2N_QTJ*{FX0q;GI zKfy!|JrUlUSPxzig#aqE;f%AyuKb9Zxro#Rm#%@-&4ARjhSancsY+{+s)H|S^sz%agLaO{Ym&$%!tuCUPacKBnON7C@Uf6J+KnztK>bn z4=xEvJ)02ErD+Q$7;(Yy2r-xvLT@W2ddO)!%2>IQbA+}vD}kM1QY(=Uo=OzIr7^sO z3C-?h59%J06k;Vs21K(7*b1LObJZuR_*3y2beIg5(reg9B-wLcZ$+m(hh;(QoBh8o zCF`0ds-0&O^nh%GIFr`iak~;7x#OGjE&K1_07BoqDCsfycvcKdue5o^KkdRI!Nx<1 zZ}-2|j^ZM3MUlQK(KD(}=F{X$?($UJBw~F3jay>^An#!^kr}sX@jmcGA88ioSRc8- zi2+OiM zwrHlBjdcgxbA4yByHK4;-N|ku94HfsWOT6Zv?55S?#VY9Ml?*xMWXSp7MfxvS=iJ< z_cJrxaH`ob9UgVC2L~MBi#{n4{XTG)b=bpdC2xR<{Imt78~1PFc13}h>;K_gbZynv z{7JyleNF~Tutbx`8YFzNC7ixAj{!?heKdP|c_v2eu7u^-(o|rbSZOc(G^3>nKACEC z;)-?Xt6E#Bl*eyY$3U#38V2&|gx(-qx#U(wIMSjo>`;rIaHd-H3DXXnEtrpm`N*fRxGZLc(?p(sxAr z1uPDRIX@~n&v*`bK!LL~?|03+~JtdazckAUh%XsPoYs)6b$9QBkV6aaU1< z;fAMh4kbzG{+WKhTC0140-{|^SGi$cYHu6F8vv87u z_UVXzFUqLsLq}W{hyemfQN|+Xl}*qpLZ$#ka-xPPRwFs3EC**xT0jM~Si%LXt^~srYn+z0>jQ zwl(o9loRZqK%4fy7?Fb#0pYC1yViWunTIVxU>@b0lkkkEE;(j~lz30jwj(^m51%Mz zx-UDzGdQ!$r0@0aS9eiIc!pH?a#bebIXO4aevb$ioX3lfE3u;H6P=s8nd97om)ZM# z0=VLC;yAb9CoUnhp1FBCd7Rs3$BJkBkoo|lKstashEx+WW_^;REQ z38Bfk8G3nNl@eoo~fR~Z$y_B z0>GYS#^cXNI_`Pu5$Xyi;dzfSAX?fv?GweQkf|Qv6_V7;xP|pX-E+(%MunX6a_uIe zUcoNT&9lAZ+(LHuSn(Fkt^Wilt7n79^#}>!-scn8EuQ`z=cb_W66*9aIXA;7Vs*xm zCWuMZ)McWPpb^pGsUxVX@ZEKMX!qoY#;`MXpNH-p+j8%|sw`0!42~(csl=BNO2qhn z!amW^_lP{e$^3qxU zQYhjP>>!gb{p83?Kj|-xmRKI%@t5u4r~gXU6CKi0oV_;$m-_0o`}Yxoy@J>-vH7Re zU(u&z6y}(Ze*JX3(s!rDPkFy(sR(Qq=Vt9eY7v?$?pT-0{SanOJSBf`9kxr~Tvr8Tb@Em|%KOL)D`!%|b0IBZ;@>bcSKYG-B2*VA=HAE;IIfu6sH ztULYwMNFb<*J^U}YLsK3{>z~OI=`V& zZb1h_bgbbY|LS9=_?xfwqJb=%2{wc1#@E+&xWN)vyla08eNJZ!svnl0DB`#QY2F67 z#4Bb*K!Ue26KJoarA;w5$haBo^&3tAC`z$i3)~dTB0B;KdqXu()v8$ROsEhb8%~>% z;#uk(00z-w$Iypp;PSe4>=jPvt&CTTLFtt73Lygz*PF_GeN3{EhRv)*T#VuNU05j5n!j538X#1E@Z#R zyCqetIQB>bU%$RX6si3Gba|~FQpV0mA93`-+8f6H!_%Y1w^n4$#|{n=yzOxr`aB<0 z77*9)NN5bhldt+frmJOyqK#I@bFcnE(E98Fp-wM?UkC5iA)#Lrkl+kYLBgLe19A z8Qx+r6mwt$5f^XEqAE@?`ncTnNhv>jVp214Qo-NKh+SQ`*#uoZlq_<#wixWaIGFkB zE7~#L!rWNQxjbAc(h}^&ayn?=k5|MH7~{l9Rv`GP=IV0OW)r44(?D6K_9&?*{2*9pzIMlBBAU#$4V zH_X~enC64&^n=v;HODQ|hA|4Y>m=ZUKW-OFH3T0jdznk3Ju<*uls7IqtXO#&?4{;# zO>(XKoMa|77H_ueKw!BAZ*4@sAcZ;B@Cy=}XRxIeY^yo<;)Ii=BrqI?O@q_L>5=h#bP}8i)a%v>^6B`24#w8G48Je&yZS<+OVG^23-7 zS$OY`vrTW}#x4rY_!qEX?lV4NHtyl<!Y6Ex z<}Lp0h`lta0@`5~qVxE;f|o_E>^=Rz?Z-uhHI^&M{$K^l594 z*X*|C`P#u;EWoTcf)o*KT$Hn|%yrw!w1{vyVAmF2tk{E zk@a(F&=?;5<-B<%N2rDSxJhzSa-Hs4aI-uowfZf!^VsngvA|``3+q8ut(<1eA{6id zNT^j+uRxf5r-JGoEAS)fBgDWYbd@Px`*u`0@7ayJq!!2&z<8+TG(txhas^^ii& zr$lp&9BKs9HhQ5}lC)aU3ALgVYE?c~TW?oz&8YH)t}7@&tqwC%yG{ZdSP`!OlTGr& z5s=}S?5*2Hm9)83IMVV~LrFdG7%rv%_~O&)fEHCo%Z{nKixF0KI~dend=tg3|hQEte=Poxo*L2 zgQMEQ)(JHLx>QYKZ+oPH5SCqYJ3CW?m}a9(1RQ)wQ#{!uWZe+D6A>DvZVm4C1j!93 zCCzb{S|kRm{9^u4ej_P7ze0FF5QZ`Tb#uBzP-l?FLsk+)SU+EItr}MHMLL2%QMzO* zOP~#IWAK~_kOc5IEt|S%7D@ljTO+3dOYKRZYv-lK2q~9ALu6l}4$yW-Iw*yVV0Vid z5bP3rPT10aOQ|UFA)|DB$l}iji9!uVeTR8sB6y-_Y9e^6^wJ@M2c-x8cN|E%Y z_jeH&<6c1;u>LG6JfpvylPAT}S|Ru(lSp5No%VX>&yK#T0Go3M2l?2Y}KpVGN5$@XMgjO2yQJx~Jv_yxg3$BO3Z)x`1;Q8!H4 zg-XRN-gES4PaMH{oHo|l_GHStY%2Y-bL=?F?)FD+C7U*}r-untB2PN+LjRmr z=f7P^chJ~`)tf@o$0KxgWQ;hW#}6q71-{pKQEgQ&A}r*(E2zwdiNS6-;zreo#d`5lbLAFyP(C^W{g$GI|8U+Qqex z7F6{V_ofDU0~kf37-fFT88pB+fxbaaPD!pl)?f^-KPa4Q`>dfbxVHl$R2EBh5d7kk zFUDX2oVkGvjlRgKJO?UOV-$WS(jXN&UB-50>Y7Z2lB!3txgG<8vK33Vbh`>6aMp{$ z&D2XUPn3y2Gw!XfL9klSIF1+{=SpQTUX*JfP}^G8SK!{%eI;W6(y%o+ck@l$tUm1$ zud;jU0U;sMfKU70t)6#Y)DET#$eK+ySTCxGDj^49dFC&we?4GF)!(SU2opyDq9bz% zMkqlL4EZ%6vcVBep3Ij#L?I%42vJz;OVCh?9O+wk`?p4@XggN?S7?FmU<)W=QOz~N zE=0Bk*o9DpK>yYe4sQZ-mPlwd>kBO!1ohL5=h;!rW_{(`bjM}g( zVNs;6p_(z1L^jyaL@kTU@Q(mhZ7}udD5Z-8330gyOTC+;fg36Y5C4Cn>Qu*dpwPs+XH8p`&YC@$Rl$jo% zlEE;YWY6Og76qv$9~$T3wxP9i9=^vlQ&;seNm9eR*{9WNGwYzKE`< z)E+Ez=!ARilsK1?=tKgmR|^R}AzAUbq~7rI%$4$F@v?kCAeK7d?u<*iR01r;TN(d4 zACs+UN`c|JZdMn$Dz~0^vq%b?&`63lyL2;m*R9j&5CfDN1{bUdR70nSOjT_>G}=p@ z&yHFSqT7J8_8JCV>U?2Ll>dp{qBPHB(AaDB968=0u{PE_qLl^NOE{7z^hHBqX z>c!~_TTiAbiGnP~N(%_L4hVu*QEi1e+BftCz17rCEe)JhexTg3t&a?)et@=Hmeyfr zHkt_&(I+r7tBodnc9xqUwZpiMqO_`(omOKaQDOSpIoZNZ-O0W3)_QGKk_WP61*-~+ zrbX3n6^&M_jB&M+pVf*_=(%&Lv!ix5bxze@NSRaJ7wJ{2^b=h_K#f!VmMuuF4vthS zpRL-LDxZVruBTF^e&2u(SnaWtQbPLUmXzFcJ#nj5=i~}SRyWucimYz8KW?MEll}3= zl)5>3_{}P*s@KMhuc|MY%k zdC!ITQj~+7Dpzj~XyDm`MwmO)MK_kw?ZCp}bXbv_P_}e#jazzwA2R{|X5@%?F6N12!z{Ho7=)M$Wl*un~P7s;TpuiS%Tgw%|wTI!*7sdMTV2ShrvIa`M zDBf@vwYS3dz@29xlr1_urQw-d69CM`t6@ZBQO6amWh#q2h#J&)Rw!QJC_UI{ZS!Xb zo18xAST&B@p#(8N>upfZdcF}en9zP2o-t$BsmsL;N_DxoAz3UgZqT8*9j4_F!HO|X zjK;ROHjSYvTU@7V=yksCnlv0<@D7S}i8>hT5s z6cQ6W@DLn#bTiI2PWz|vCj&914OBEDNTrCq^-3L$7GF_0iccL zUWR4hC|lV`3k{`E+-7;*R<>5$cxyRS3fu65dTekSZ3#TQ`rBj!-w%N*b*~<5^~yDI zOWBL*%4x;F#+R+)q5q!J!IgASZY=GWzH;5~?x{VgL$|-uF+!9i6Z+MRCLzrX+-3x|s23i%!x)`bw;<>G(Sa`8wwfkdNfiGg(UF z98y_4c9;F{Nhu}g4OuB6wAVc=QC6qcI^kwlOiq`%ElOZPSzHv2)_L?%>TmC5Vw~XR z(C+Q4Ad(BVR_FtH_UweL>_f(b1e-nlzvNTi?R19k`uY#t>>$^?Z0!{N&;u(?zhzf* zxwK6x=N88d2kzkMGORWpA60zE7`Bwe@`@Ba57D5ZBW1@9ANrPm&cB~ZOkg@SDhp}T z?~=|^!{|V7p++C{_c(p%S+X7w_w<|j{twc4nq$bBB0TnS5DGDP5}{PfKVXqWm%t+t z*J}vn={bQQhU}a&A8L$|p(Krpa;U@-)FVQ9l1_gt(AUL!9a6!1jEY&3xNM>^kv3=BLV7n-G8*qN^%YiYLrM5*wxm ztBNUv8BorB6VQzt*IA!u^kfwrMVZuG8cGbGuB=V0K$&r#o64{{t=C**VtXXtJ&#YVI{M!R8X072RQ0M zTWl!N9nZ|c@@UK2r9nxdUl;JY3&Nwldj z-cVIafa5O3b!-Ty3-6Z)0(?zN@qDGQC{J~1G>#;OgLbNbKv@7mdo4^U!}#Vir!WlF z0-@{NuTC}?zf2<4$b{()^`z^Pd?G3EM5i#W+{fkID6&-sRc=N}^EHt>e$w~1=RgVR zP2^tj&SD|BEyciGa7g!2)E@W~gx8B$aH7p7QyHf+ymhdIN}u6mKUKyG;v>q7eoZil zsM30dlre~q9t8jbJM(0wo+>VeWTuc%6XE9xOZLFi;&eKt%pU-U%5f06YC~E73b)@z zqFrl@&Lmi8b6aD%J037I$Y87Mj4$B6LL?L#?Ul$Q1P_+$~?R6!8k zQe%;1C`pRp)p67_qe`mv6FwgoL7`fn3sq9Br{44SGSVI~d{|{Sn?eM*(G8i-xDQ8XvS<&m)wNmRcWI zswFD^#cCA|ua-i}FI9V*3MkW3Q27S6i|1qB)*n<*zQz8a1oN%-#|EpQ%q=QHQ$d+O zC^2)J{XzNVH`*W6OMY{$DDqpaC~}c>-q)ni#}vQV-SxaI`F3UN*Orj2U%#i9nv$*G zeZe{)(tX166|WLasy*;i>$R)TFQIe0mT zGk5@3V3cssCM?%>7!j!$vwepZ=x`SLhQmO1OE@q_abt&g(2RyvF63D;L5RN$A!TTH z=u)psGxj|L>lX{e+dQ2G3gKXYa{vX*R(REXL~Eid*FbA%Pw9Jo4it>vhSs#8^VHHc z_*|`Y4d{EWo(Fv|R7)IaEkyHfFH!Tr!N&a2#hWtfHAB?up#`_qT}BH5jTTr$Tr8Zy zAvEgJDrP*h-%9h-^;OhYwYzZSsNIeGM$hfR#iaK6$RxVHA1kL?)CFs=f|}^}HJq2H z_9YO1wbx<7)_XUAo@!-YT>u@A$sMEza2auS5qEGI&DkHgjOOju@5qUyXS!hCl)Woh{IegR)Ijg0X+Z)3wv6y@%Jmt!gq*n@ia#ZAzv zAhd1f>0$pUUMlLlve1kC6`$-^VY%ER}8idANk8W9{Q`TH!}&mOKI=4eCzPGKY2B~ zx})Gha3Cvg+GkV1V-HuCtxOfG@td4VTqG`Jt=-gzeR1jdFM(-e*su@ydd%D z%HmhE?gcCoCgR>xX*!o7cy(4zQ*vKgJXKZfDUwC)GD*_*#%RyHe!iZ}vGFZ5cAUF( zu72(E!R!ppUc|ZO?z34OHYpj*dbZg-_uLtK_|rBSillPuIhXcYG#BjSjdS&-ZaIew zy635Dj$F`}+RvJMmVW*yK;qk>{c_o=i)WXE5((&i(UIbdq!r@aa7>gn0rDWp1&)(bdcFTe1^u-VA$QKYm66M#?NP9 zgjFZ{wqfzeykj319JB(i-%T%(%B?;x;oYb4*E0l)vup_Vx}hiGJNP?=y}SIy`O84k zIljbK9&4nR05lDzdQp=l_l*HZxEYRqCK2>UF5Q=Oe`@T~zb4(E9J}w&=Tr zCQlh1nZYdc$?fQF72H0@#(2N&({1QHjiS*#P49>p2l@gDvbDQ8>soi7iI^N89^-%1 z$lhNc%_^N_BJYhN6N@$H9<`*Nsz)=N~)P@r21wYQsUJUCL3tdH&(C__6NE;kLyN&>R$qHZ@ zHxzXGg5ka23&wa`C!$FlZ09$27q?{Hp%(SCMpcPrfMN~k^fS_k8_;Q4FpkqE5$hi<8!;zU)N%aXiIP*wvWFq z?2^%u7XKVx{eE(&_;US56juJFe(^ho5$fc7i3r0_Yi?aBlqOziM-cKJ7=%Xf9DP(v zYJBUN`a>TVp7LHKWqPl{d-n9^k*774)3~x*pIi3VqBNt|n!I+>rnaQ_N`{m5p4r_N zftMC{rh4BkJ3w7{!dbO3Maa8_h1x87Pzb|er*MmkC~yMc*z2T!0g@Chudy~_6Gm%$ z-TC-vT71Fa`RsTh!p~5HABH}PPXf92Ln*^2(&D{|cE?#v@-FM4R=hba?hmW@`NRS6 zW!p+kF}t+*qCH>EeJbSdG!S-q`h2a}M*grBdwO?6HH5F&n*T(+FtsCJ3oU(pEuL0^ z+F^JNaugBUZ1OS+p^jbd$JzFiZnc^r(U_2&4_A1RG z%`;oQ7enm2-A%D?2|o4TY4HJrIoXwAZBMVxsZEOy+H&h=T+>-$@Qx}r0rDDF{e!kH zJHU4yzu#We7X6C-wFINAPBwoCxumbo`le z7us^6W|X9Y6r-?rHP1S}EY(3V^2O7pO$Odo(Sk6Y8YNf~-?#B0LygVA#1!bk`o^`j zKCU1Zw*;>(PhwbGA7fZsOx#)Tur^o2sslNI#lbuYmMxF*eOR;ggd1#>GR*|aR353k z=DKej0m(#1&CpR9)3s(tCHb8`qDJVb+|+A!v@kxR2}&~?m}B5iB-ICr=Io?ZxVjqv zL!4iEt8L=1ljU%Gu6BD4G=E=mF_`z2K%O6lJWG&c;~pBM2n(*ob%*o*T3EPw+aJDg z0olH1guOSqaE!9>inDf;$ZAiG-x}}13*o-j#SsgXr*1sCQLMy6#RT1Ur;^EE0)}n7Pph(%#16momh8*dv#e zx)U@1WzX_|rU}F!|F+hMOOW)(B=Ui@aE2|B+II}>Mu_1`HWD;uE|Z^e@tE|?=@3sy zdY15n^o%qdWoL?WF>jNcgS31xcTH+`n_85D>s(a451F~wl{9D@$p>10Mx6G$jCh6x zpg&|LZ2eJILRyTkO-M=TXY^W1N4-|ic-I=po}cT@imzCQL3j+SR*8^~_s*C&1 z7!pPgX)seoM}$fVE&klz9GYl=Rl-s5MpZA-Xq32!gWyEyrmxioSRa2P zF4?6@R_OKJJPhR>;riKSGRPS?rXhtkQiT)?>SK*(OT?6=Z}-JLiCnDif}0gJpixnX zZM%jT!hZITOc6qCXIBI2_@rvnBqpyu!0a(ZpXsm+@3H6e33vh;8OHALCYi6{;fipU5oD{0RwbcFuqr=1U99qW6QfEDqUz%^JCdHk zIAJYmDdY}%O7VkYa1c4|f=gE#b%`Z!3?U^aUNQWolPID5uj#%&OR~y}Z{hDq7h2hl z9XlF3nhZaq@X<`CkQX|`-f$3K)J${x_U%NH6zmRISJ9&(TxO02+i4dct6(&Vr8P3H zG+QIe22B7-t9>)$M~K3ckrKl;3>e8tO+~B!KenPjC&SKKJCax*MQc-|pk^=Ru5 z;xGz0>OrH}_%h6c^(``jk&XX{y?2kc>$>ZE*IN5|&ffc+ea_K&=p0F&dr6j${ECt| zmf|=>Yt^!q$bg)>86FwA_iA+Thlj)%jVur1F|J;TbQCK|8@CXeG_;uVP%cD`3#B8_ zTM!gzD7jn{LP-m>PQxvMav|YOFmONL-<)ghwf8xajvU9(JFt>7*ItkL_|4yI{^oD~ zei=yZkutSYsvC_U`RXxS$8fv~D9$o8Ns2C|;At;Xx(B+TwlGZ>1e_))Wy51j$WQqa zsAs#Q(z3kdENy4i`M%M$b;jG-#+4+Q%C4&>D-{=Q^mG_nSYpWk@-MY25^_u#@ z;^Ja$@oS+U_~dL7oBu!6548C_&?tu+$bP%XbcG;PueUD4{%41O{4#cwoOxz$O@MFx z+AJ(V3nPKvEmxoX7+rsIqco9P&%y$tu(hGN;ACmeR@I#?X>`N=D?YTvxaoPl;f_k1 z6&*G^AG)vV4uDtapq8=2GT`L-!9wW?doo_pF?B}1D!~=&j?(gS*MsQpLjlinK|KsG|vo#n7$2hexkk8SuchB&?>S&ejfMSuCuWxcV!kzwD4oq-sYD*s|^a zS)*`uU05Cj)25U@a^W73nz#IVHqbB1cfp%5HAEc!I;Z87>6u-q-_qY#&_Sw-@%pDTjOEJ)QWP zrb^qtp4PTCGx*}9j5qRV#0$~KcA<;q7C8&1{nCX!SZLpe!wV1%0rBRq3(<0;K*-B{ zRqz(z8{Ss&+dO=PrbE2+Fw>h=bW~uDPX3F%x608p1oDWP5G{tD;>l-wad4BI4cOi#a1EHN}cvFczicQ^n^|&vgq(|ec#p< zU#x7naiU6}6V|{SZ+%@_fW2U+Od!RW@TOPHDfD^VLm9IS@{k}t^IBakA69fe<=d1W z(hJ}F!6e0oCG)yEd1rL)`#zZ9h+NCIaF5SsaL=c~FD`3;HvD*DSuOVE(CcQDK%)g0 zboJw&bm&99;kM@Q{?yfrKQmD}tR`|;rE;MP4y$yGKoRN~Lz-c!i=S&Re_k(K-pi`E zds>lTcvmL?v0t|Jo_AGwn}kMf`Yh0{P~& z{tdX?)`3TDC9UJz#)~-0AGxiTZq|Hp0@fe{A^S9TuWoKa> zcsZ8rS$(&jcQ)*~dZk9KS0G=}Fo6!O;exvrkuLgbx*iq5F1D;|x)S6?fG}$K<=!J4 zn)8e&KEZZY&yM0Uo+6w?QEiAPF&C=!?=dc4RY?U!n2F-EGR{N^2z`Lt`ZROr!uSK9 zE@DXVt(#$vX6B+{D2ej>0LUp6de5YX70GeRD(6&HegGelP;n7KqT^`QEm*}Nki^V7 zFv(j~_!MSkf50b?Ey7)4OL-{bdN`vvB_lX8wC5@AAwmA=5Fg<5mac|F6(L=X;K#wznFf9D z!VAT(Ab8{boD}fakyvA2CnY#N(LJ5cinYRudij@zoHT#Y*sc_}=vZ2p2#|(RM;}3R zkO%24@G%o&H`D*Yg)Br&C?j8pd2;lEt_NUQNDf7Vv=inlHup3_k93}b9z4O} z9~*9h3i0*Qb+6EzWGg`rP;fcs@xpQuKff75GGG!^>meY64?S)mW0D3@F{6X7)K=bg z9Sh7*DsKf&A_)BuZGb*9Ycumv5fax`6FL?T_51UJA{a(S3tf$~D}fwl1h%AuIPyO1 z*m0CT2YGaoux%#^8^w_;w5n?yxtcgl(?^LQ^|=xr;-zX zt13C*w^t>{`u3|d2VqKR-~s)fRkm=-IkJVT+@icXl=J(Nqbe8nAw4M<_a*OC38_4# zlAwR5R4%_hIj6%{Zpls(azPkCP7-p#>gL<*V(Y%-!cXL=-!kN}IiC*)0*;R2{7}v2nv{la}U=sPY>(Mhr?C+gUahFK0;>=O2H@cal&L zD}y#WGx_ts75uz!^_TSeg@|rTH{{H=AH;nB50fk+#S2`>bDS2F)H>*+t10+d5pn>K zE5gfQD$`k0a-K~e&$=fDEaV1heikfB2HUuH{C_9^-^%}Q!7f5}B9Jwf3&fD&8ccbSaSrD8tF}MY^p4=W@V~~9Sf%QR;yTJeJLSitL6MtFnBi)dvAEE zyM1}E<9h5J=xn|}dxoeJ`g5D}DjCZyT07tgY@P+8OpcTAt>jTo&o{H^;U^9X zY}|q7wmG8EWp8>Aj^*Z|z?k4zL;1ygFYp+SLz<`sxAnA$wm=M9t9!)Q8W1DIrrZo- zTz@J8yXgg*$rFM&F@ncdq$1DrgPcv{v?`8Y`j=ORa7|>m84*_je_(pIjmx;S ziIlTW6ih5rJcCyDlN?lO_f{Bhiz6-%!L)Ss-|Q}7kh5Rl9>yG$w$V%^uSMT>J3}c3wcE{p-`(cViyfrX`7gnJe;Y(B(NH@ig;GjGgcGKBDcPr zOmEi^a|7s7a8gU7=K3C)!Np6kru8UTTsG08jc92dW%qn<5Lit^o%kz;JF-uB8UBm@I&&HUqG>ue+;jOeaqG#eBD*F?;X zMnaa_Qq41-X#{K-Pk>|1e!akysbGz!>MU}uU#zmq@;+g)Gx6-p6~GM6WB*UH;;8L!0&gO^Q7 zYKoso9yc*`RG{a!ha++YgE322{y7*^KhA=Q3;3)t0DuhX(gYdgL&F?8ro8OBoRA6yFrcEh zdcvnU_{DPO09Z5ouP}txid??7i^naivWA2_6{qIBB&!!J6 z8#&)3j~GnnNspEA1|NlYCiM>B&TF)Hn(3OPwfd7!bke3=s&5?)y4Bor*}<476cR5jW}NSdHgCsS)&6|Zev^YWa6NXos*@ea z#Egdde{Q;!ew1-f>!RDjUe+}UWb+fedq^N*f_HVx^D!+uRor`s@gN!@cjK}e2w<>r z8RuMKSR@c63l<*0Hca3n(Yd{1$k-Kh60m0g_H@fIxx9G_m@_|opwCYeO~WH__@&Bt zMUpq%*K*2V77|WypXEGtctPw32GHs)4i9x<2mSgiVinbVGJE%HPJl~TjSAH4fFg*G zPH$SeIy1@M3bDKdi0js6 zU6I4LETCF#!)nDq77!hZ%Q4TY(I5_6n`CiW9`IRk>FL4Ftcd_D=6T(cYH}iu7lunJ zQXxRAfP?){kr=^Fh6+#siy4N!T=FZcU>RPyF<3U@=IeO5)^$vJ)*Y2gOKjwXDc5>% z(94+lVp7FZP%2m>E>70#eochf>fsI-22_K8H{C5>PQ?I3pr9y3*NCxU!QFDYRPD^9 z?Nz&5f@&A6+Kl++lV5(+lBkC03oIdn9J7(b7u9*$UPsscl?ehRD*ZOo`e?s{Z9U8s zmeO|PWne76=LLC6zgjX)8^cAhB$CBph)Aw|m8tVYW)}RamJoh;)s+k>8H}+&{wlt=b!1h)a}fo{%m2pUV1s@Fxf@Sf;40Y^KL}~5V;_F zAHd2?##Z|0Ob!>Sg2f#66F=_;ECZ(tGxy>q7O9ZYx@F;p#t%qqtfO0C#7wNaCV~by znt9whnB$IX9SlZtAX%WyHCNG_?%)QHEI7ytlDdv8J~3n=Xkd!>J}ISVMFvGIS1Iuq zB0Z?UI*h@>3>U(hVDA#vOV<_F8}xgO_e~ze0k{OJBDpc`1?!fOYZiu^Zlyy|{njD3 zvQWf+@{5IN2uRH2hX8l}Y}0HBqVONHDpD!7W3F0IgOTcoXT|)={DL1Uzm}urSY~(-=ZM zv#_D33#h|~>&D}>(A1;j z456vn!F~D0iOqOyoD&Q%)&PaJqew=oP=7mgXlVc_G-WhPra4^9-zTWT*~c>ADudn;AfD-2m7iCMR5_ zHH`)>+QNY6Khy3fSqK7N96jEcCXEHbL`Dsh(nu>iJK{3KE(}4yJFWiZp%dC7TT{a= z)QMsXmA%JnY@u$s?6*)UEf_1M+^n^V^(6&eqsbq`vh)VW7A5%$m%Xg?`XY{B_wm~0P*}IpmRLbRj1ZAaM*~eBY z<+gpvg;*Ec_pwu`iyan=m5W>UDHbaiQx<}i3%8G*LfskcOP;ffbYJpGyV$uexoQ`? z_9dUPi|KpWDb&mTd)X<}#jX3;Db&Txy~zu9LCD!(uWZtOvDl>j*hJDe(^#Ls?Tgiz zuB4bqq5(THl-hk&sohtV+I>~2-B*=+wXQ=B??(~R@B4|6soxJ^hEaKljZocx7?G{= zQFdE({~c^~>i1DLH&kwNJG1YJZ)c>eY6N~|wUwXMvP)Rpw+KZzjS&O&+24HzYfb-O zSJSQcScf<*gDRU~KJ`K*i@$dZ=p)bBlfv(S6y;$zsth9RHM&su&rYUYm=6QBN(MN? zmX)*XRtxKZ>aLsX`?iVhPwipD214_r%GT{cR*YT*%tfnI3JFlY=2RwfB~-N9!8Dvi zo3+GQ!s!qbjrgVc@=mcr6jPeg%FDVB45lDc^?8ZOqn?TUPL3WEIref+qA!9samSrP z<+H?Y(<}U3(oehUpWQ_{#-Mm80TFLsSbsj5c3tI?e-saK=uLFR%$;cgO8uYg1y`&C*v zU`iO{1NseYtbebL7y4)y?5-oWqlt{z`O>-L_ zqkm4@0LEvyf6g?7xbO}jt15w{?Q1bGro<=iCT2lc=wze=vIx@3_|lhS@i2lkYQ6W+ z^65*#Wkrw<4jQeYQ@vGdXi};yw3)b;qDMpK^buCcHGd%LIz&yXo$qL9i;~5}ka}g` zK(()nvl}5d8;v>?=My7Fr|Di8gj!STS35V)QLjOXq;+X{Anveqg|Tcuol- z*(TcxE*M_B5k!WNfE!LottB%L%kgRsWhaHmr%>KR81F`)TS}u_N~2p!qgzU&TT1A4 z70j37vsb01P^LuNs-#dpa2jR`8UDlBWa3PHy~1#=>aL~4s8SeIiVjtZ4poW{RZ3w{ zCRHg6`mG@F`h7pHPWpWS^ip{Uj;0bvB76RrTxt0I4ip8I--Mu3`OP7*>ys!Fs>e+E z+}|WU&v-PzFRFv5a@q#i@S>Vx5w>w11s5Dy#rrEdv+ZJoSlvFZET zSBWZQN9tE$H25X~4&Gs>rlx%@vUb9iz^qgTyNcdpG~wF$>ZufQB{v21G-~3HlW=gB}uKdo2r~J|S67kbM3?ZGJs!z09QLJw5sqIfm+0eGjB{I+;sMYUcWcgo4 zZ?mTebSb6#Ew=+}RMAz9TPac;6}ZNM9yDBS_b^6I5tyu*VlzTYkA@vUB~nDjGD8HO z>)7YqTI&gZ(!9f5&pUt)yM_GuUqGJUd^UWXBWzR@8VPkd1< zqP7nE!r2Ep-v58=g)aw{nanEN^XC-w(!VM*ax$_qxFUnm^f?fr!^8;brO9w>ubVi{ zoxM&+rzWd?loDbIYywk78)p`tEB1m6H$g~`m{Tm3m7=^4VtS6R%Hb0Ql4)O35LQ+h z!=ynC6gEs9OeSY|#0;R>!l|pM3O7|piJ8wI#98%O2dxozn}E4Pyqz^cHrZ}R7(%VB zv`6jvdoMK@5Wz#NYw08sO6W?Xa`@%A77<4$%Rr;jIGL9?okioxevg-; z2pg1A{3*M!D$^Lfv$XEHGR(;MmnG>pBF?eY=6M^zLC(tpnHg4SQV8nNGrMLX`iO}aP4MZ6BAZdD( z2>o%5K!jmOj>e4$X?(&OH}G7a2s>d&c0TVQi2Eyl(DalD6aC7MfCn&&0tJL&17V-h z649c?ou$MSnB@1)q72}=cK=_-S=c#a-D|YDF~;~qA%-zw$4c*mtID&3bu7?$e&961 z)u*c8#0sPpG#N_MWGGFOp)^f~(li-LTY*qw+S!W^pnN)(X9v58<=0^)g5Q#@JPxU3 zf_=zYbpZ-=yE<)3N+Ic-vck9rE>@8m>&v6*iO~pF}0vz=rbMRT~QW zVj`7DrBou7Qi+s6R*6hh?m~speW^w&r5dS}Ek)%4R3w#$P>oa`K{e8MkKqfh-|}2n z`Aw)sDmSV6OnbaQ^=az#UW?gj1+NjBm|}NDh7vz}ETz%r_taL?<`FKH<8CRnyzNtx zdcu>6QlU2wDdDFcR;$p0i<5C$HT(L=-0WJcI2e)YY=_Ke)22u@-~?Loi>uDS+``(X zxlFxu%S$vEiY<<)XrzXqX;~czilUC7bTw3mD#7p&eZz^dsyr{84yu6Y0p`vY;_oJf zDo`E|K?UVJWpo6tr{?#j@ewl#_`Y~k(sWP*bTB2pJQGKSE>PN&+>{I;$3?AXpb0P& zWTz5YORTGSuX>YIMz9w;6sto)XDANj;87{Firz0FQ}iMnjm&CrPi$KHIyiiK8}A4d zI5mAFAOK|FTOln{A+CM)cV@8{M!lMn$+o96t9WQ}7zc*7lIo-oIKd?r3smFvD5A;t z1`OsH;5qQv;0Yd&&ZXB`G?y5DzzNw3XC5lgSb`B)je6Nx^?-DaGzb7(&)nct^MSO6 zuw{JQ4x_O-4j|eq!Q8XGE;B|+)i|0OzC(KcK*Xw{nS(@G)ynb~rldHZS?hnHRmfem z{^Ah0uL_-(6UM93ZAl*Lis>nl$5WJ$ClFVAP)wSa$3xT!LV0)us)f=H>3Y*n-zvvPi%w zPUUTms77!q<+_cGokpuvy(e;Ou6BBDjqLPM{@xFL;u9bK*Z<|C|LiO=1}|Kl(I*k}Iz5B#Ux_ZbvPhWF0!%B@ekWG(;G-~Y8Qf8_T*@&gOH<#bC{P9YS? zij}1D4F~x2Q8e;Vq>my#YHMwjNEPwX)pWBcfZ&=k+q+Kq?VrY zzn-{~yNj;2#&leM9TQ-aQa`P09xxQ(Pp!$t{7--D`R9M*XTR&$KaWL-@o64HFIkzo zMBR@$h#sqp@kkeI>S9e@)E9AH( zS+H>MNV%=_%3j!S(C9x2LwmgV@f<&nLVBF&<1eNJ*eH$=)mf*1AG0Y?|>Waz+*+F>cEk*1J93i;J|4XuA6CJdm5qrrD6Lz z>0Sar@}~lTL&XoZFW%z;K#RliLoSXHqXvX(W2nLzxbi%vB-ty zF~uMqJov}jPI<8k{FGfAu)+|Zt%#;5tT{qqO;K1ga1IEzUPU#nsZLkf2qgH0U;Pgs zdhzFf?+@3`p1B@Z!5CwxyADNxBika690W@lMc%lW5{(kE7n$N`z%VmkwB%(!l-nxc zAfSA>1d*Wf48HMFY>_g?t?t0m>3PuKOZ$ zkmQZ0ZI7v`5xaJE#Dv)NBlaVW!bq3AA#;4hPnWG~#OH=1X5GP9TZ|el-%Xs#|2(=e zEdcX!)J6>mB#(ojr^S8n=osWHNE%x-4DOcw&^$aa5=x1PhDrpNg%Y95p%M{Ql!&OJ zL`0<$L2^hb5%h=5q!KI=o33$Y?RtbNaT$BruP$O1=5L!WUQRouSaY2*v7fA+_5=3< zpD~tVKgwTyi2*HLT9dvpDx;CxbZ*^k6W!JkliP3|6T12oPB5*yjI=7@ujZ4rujW%=hy2@a;>;S;puG(dT&o+g(MoeBpW`5( zrbNxzb^}3-dIYuFkC5$A?Bb<8c@jqcUU;rIwxXqTN1xtkM}T=I!>8@y*eK{^Joc(!KW?XUF23w*o1cf2PUgQ`&3KhhH!l-k$sdGa2`11(gnClIbNSZflu4A_EHW3YC3yKg-SEI}x=I@%M`3Ap$MgbaQ+ zB)l3U0=^*u-&g|=p>jzi*0nSDMvz>n4BT%8j~SEFx)m)G=oPwi>6B{3MbYx(uzx|jp{GCm(zVu*KqMOG4? zJX`Pop9{Rl3zuI(4M``&tuv+iD<}b{bU^w)Q_wT>Vh0Cu;$juFT@jjs|l$? zT#I4)fxx?crNco)`O^$r{R5;dGl83a1SoRy*qZ2RP2SlxymIm;E6CHVxY#+Qx>HzMeOCrC zWWaC)6hWFVHmI)b3um2V1dn|krZoDm68j1$?xS}A<*EQc_w*u!&H}4IJV7OM1x%{UqmHi%L-YL&84tJJprB$y)Gw0_^onn~q712)^Ze?R)V zes9v|T;{z7QfbF%HDi2GNQY@Zfs71F$-Y@JO!IvbKCV9`=~sR3EVChY)pJ*){HK0- z8u`f>izz_)mVr1%x_TGW`W>>$+;d9&U^nt&=9%(RxxTnmIvAP z5xdb)xY-ePRC~t<#HfO2?PYsy?=U`+jV_P!KmKLZzy3du3k!8H>6#glZ+$CG4O$Q$ zsTz)FK4@X+Kk~;o%4z6BZ!~XBF6vijHep!~QpB*}&;F88-{8b)fQgXaiL+LDPlM%_3kRw1spfEZlOjaa-(}oje>#4YZBIj;-Iz-9a6JkmTJ*z*Li&7ZKoT zgF*1k)6@f}--iww?x<##0{bHMgvCbU7aR1EX01hbVmja6+1O$0bJg8RIX;T>tHguD z$|WR#etXABaej~%47wA0h3;#2Ql)k$Rcd!qrFJJ(YIjoQCMAMx`VX z{T+ODtzWz&PpqQ5>KU4qbrWZ8>!aIv-KJ2Y!91<*=At8hm zGE2yHv{UZ%TjMBJzDIwDrW4#03&tk50*QB(2f{v++^^LRN)H=@pS80ro}2j>$_dhH zMRwb|NUi2u_xv0ItT4=?sI$pGTYVa?^7`j)Y#y;B37uYxldgYz%vlhMihA2MeKG zj6yC$wwuLhto90M4b*rW-VA7q7`O)7Qm`={o|?Kh2U-pu;|x;(H|==vR*`fg(E2Ug z0<=}(crDNZQX4#YRPK;=#S(>1;BwfK6GaPPtOQ{1#xE3<7p}noixHZid#{in>}Os> zg1}O3GnBIMmql{)VPKLZODYS0SrqD3{qE`j5v6U0Qrc!HrEP{%+GZ%FHbd!v??e8% zV$<{QM&LYLI~J3IDq#Kme!CH|EM7_eL+3FBx-)C=;Yj>FGX7q?2ShbM0?FIr`yf1H5XB5hYhMG4k5 z=}=l25m2L{#fjFuSol&TuKLH~UcdvAIKsH*v6N((JaQQ-H^|mr;aU65oV#G1Z>K4O ztdoU7OykEESmDVzy7M#bq5G~hcEA~HGdNw%=G(eG`rGyT@yzDn&} zsZ=0ImHVMdm75f3KkzAgw02)jyQ_A85S!#rGzXOy!+J zeBH;g{FToxa-ZAikm4IlEWv@WF556DF8JSS@<7OX{eV5ukXuGA*yuggh(b8`D`t(KwDx$uu@98vzk|FVtadEZ$sfvUP3UwbYu@rVzalcQc`q2+s6ANJ5^ z04#fmlX=lYxr2KK=t~EwqXOG$QUZ8+xr9{)a~H6rt844K`hU>Xwz?YDT6EQOf;4sv*+HK3HEnIhcfq# z@~>ne@Z-&7+gU9Ipuzj`%Tu`@B}?T!hGaVOAdNzrbkoXJ7>s`Jg2AYiUZpZhw{X}& zSM_wB5I(wUrwi!5y6UEjXyUr+r%QNN>1s>570(A{omTj84E+4N`9&7Dk>(RTjLI z8ZlOX+n%@WdGjRp=dtH4d)~788z4XeL)GOdk2pL8=P zPcnA^c?J;I?e#jZPmaEc_nkee5j1?;NjGUfW|>En4+lMWz#%Sgu}kF4gj+c&3gfcv zmbtX_$1S&&OUo2Y06Z@HdZFPKxfH%4Y!bpsRvGzH}whEn?fdM5U zH+dCJi?Adb&@81E!zwo^^NR(7M9CpbG%5BS}c)7sa3@AWgWBxNS&`t zc#lT`pc?f2(^aF)MtHb{2vOW@$5LC*cY!x5B}!E4G^7QV2D9om%^+NnX?r1fzDpj>!L9LY$(fbpuC_I=P=P;h6nB%=Y;T;48K-XHtUpz@XoDKHe6L`V4FYH~D1EhPcXQ7r>$ zT+UhtPBTLd8Rk8fbpnRgbC>_yA45Co|9NRp2TQ{u!9%M2#3QCU+3f#jqrl9{>ytRE z3nb8Ip|@@xEM{b&$Leg_lJSP!;#2+r2@vu|g8(5@v_BM-SCm|VOu%~2uWWM@QnZ6r zp;WYOIbcdQho*GkX1Ex*+0L>y3`-VY22}JGcSHvx&(Xh_!Vj<4uK)C>R$N0J3>Jq{ zyB0bLVQYa!nOVVjb%CPrJtuUNO(AehL%ihe=ol~h@0~7ASQ+0d*qtfWfD^5?wjbr%Cb(%DwJF!=uZ41r=4r+e zZ=|H}rG3o&HcPF#Td*)}7dOYkU?S40@nbMdN79;By-Oup^_?p1;4mdx_5J#d0px)p z>-)4BKHz=t=^){kjbD&8IhEM?b`mY%{ZA1@V|FkVTns<#fxZ|3$Vp`SmqYk;vA$iJLuL}wxAX@(3Yn- zS=S>}Mt=}H{Lit_^KgbwC;6mLRnvryaM(fcnDY;Nl`rdjx!1njTYRZ6rudRAQ@*?! z*{4^d;kQ$?+MrdwrN!qXGnOQI@^tKv+JjCo_B{7f@8_vk#<7c_ zxT5`T|e~BZo{ks6hgbK{gfRr)P-4d5weKz5?a%r05q+8}v%n#jjh06%S zz8az9QOZ|>z0(RDB{KsY<8e3=Q{$wYI#Gg>%nAi4n+D2BK-m;1rvY*aO4Tz0O3t;P zbd3}GYoL??oHRfJW!pg6q@K3wp#_05_As3B5M_rEP}TuoBY<)WuoCQFdMwjh8O`;u zVwy@dp)(^Bx)EXkq2XwRT_dBxN!99M@nZ-!We8S5jHv>_O2jaX;55DvgG0k0!z82e zh|vZyCJMyZ{M>NV$L5B=2Gh#i08`Lha}!{Cy}4;=cI(4AzV_Vcbn=FCg8`D!^lWZW zFBr{KF*lw#N5Iz-MS0i-+N^-Cq)o-!Uq{zC5pw)ob2xqS*s<)t|Ks}fdS5N8J5msp~e6SOU|V+K+i&r z0rrfAu4jPbEF+A49l~LGWwn2z9DX55-UU#v$09hmZD@)?!G^Ez{P0@;^umc7>m-x2^l)ZrbUQh#I1g@pJ)9-x_cJ8AsK@f)B{?S z{7+c10ogLo4oeRLpgAO4`$)`JC{e;hsGzom8rF8_W0Mf%+!#Uj1Hp9z!LHqsHSZjuaHBIXyZxIhY2mCFmCR+Ih6{lgmzYgzjNSQtLcNM(l1wY*AeX(0Be`s<67qe7lj2%7lw?%H9CiWo4B+h#Rh&uG7B^8)YZHaX ziFS=(2^VmT-Upf`f!HxnsnlEMj~T(Qr`&O_buHC}^B;zB1&Au*u~mx4mOwPaps!6a zNM{qX;IDxQIw?Se3WOHe0z{?)jjApLoDqmbOVa$rlS+@K%W+%Q8n znwL5^SSn7sY2#*J-Q3i}+(@lN99@&=q0blVia>K4fsQ>>P-@+hq*zbP40#~#En|c$ zf-}NJsjLtj5g-MBttqYv|IWW}!YQZ5IHk^eN>%aaJ+&P4s!Igk2M#%tcEQtrItdh} zQ)Sqif?LW3_p4J$q_apRL1!6NNrHw`R)5nf3F?liB&7`Va^yxT3D|<7i%L?eGV4?l zj@1YGQ&CCUa4lnF#<)m7Sz%mtbQEN1U|dbOmTT~9J>wcD^&r~UAxcH%C{+hPJZa`7 zqtbUHYIQ~Bu;CS)T&hY%yn2;`rAQ&##~Etq*E%(@qH>IZebXw(7}zT+M;Ao#V*js$ z%JKK`s@|#NC^`|POt%S^5Jj1Y(NutY1cN9oaOAXYnu~b@w`4Y2vHAq3Qe6CM?G9!E zOmSD_W~Y4KGS9Msf)iQo$txFi&a~6{Hw{9~#so2Qi4=1leM_2L8MH-#_;%<#DA72> zFOIE-U-evvmtFg9`Y7T>{N;Em`=vEv{v@>K53{PG3)g<$A}g&l@H#_yb6H>hCAkzu z=k;9+Mt9qW}Fnx{bzWyM&tywmWTs11FqbbWwJ>e*xE+ z>pWk&;gC3H_KJ1ox?OcQ7|QAmp6|WE^ZlCv1qjRpi6ww!g9MzaVVw<=IFZ4ukEi(h z@NeSqN;<(z>hd^yeVAmf$S{*&*dHXgl1-S?Rp(+Isl&cuK`#Xk{|Si0W_392gRvIm zFOK;L!v~4zDiON(-)xRPur~;XQ!3`lhk4v+f!?Zdwk=~L9u#YxXEYCbZ4&BrHV?8- zMU`3(*lpGQ#p>;&cKax|pNT7PKdqxNoK_JUf2{i8S^wZ!$X$3{=?E#A3&&YI29#to zirbqcam02GKx!YKYVcFP1+wE=@{JguA;Pn3^7w#AIjDeZ#uaV<#Tt(1AO1*|7>rF6 zdsfwnVuD&Eaj*$$9+n*!@*C-if%K*JhT~WMa2DNZU9ld)(u!GQ7|c9vH$6URO27ku zlC$%XIEl~3XR=rm>*P3WddKr|xcC&CJ4`wq=4@>8X&iwu)7Q|Yq56{qFVsg@*}P%W z1+RhPt=Uzod0*uV&a$v+{f~)b!zWjU-*a+771%Rg&G8L9NBZYat8-vV()qn7lY7t1 zpUvXI{j{RWD!oeIz)7~j>)ji&{U-)*q=5Op;mY83e0)FTk+^#v6MP`XOuGib|AD$Z`OjCkiq)hwpBE2m=)dYv-yVx_qo>#$p-uRIemEWbrh|` zgEvvchX)5J8ixlNMg74+PSH6$_*)bchX)T(v>zNCr05+UJV?=faPSbt;^Dy|in+ss zH&e_U9=wI3|KQ*-#lo8h4^u2XIQV+^+QGd{!o6-E(L0#C`vh;&J=dO%-SQeB)HSCe zC)R+Xu8DuJxMpdq1xUBB1}t^|99yqzfK%5`xtTQ}s>^q}t!n^Pmyf&t8gSL+QP)`m zw7PuE&8`7mT^@1WH5u`^Jmh+7z*v_D{8>_65}nRS{^}(M1CcFqw(P!&w z&_@s9UodP*u@?1flU;C`n#)5Keh5Vs>&FISD7>NS_b?Ez)~~MtaNOTg&mPbp5;a&W zem08kt)C`vv*@0m&Z2vpo#zMDT2Y0^lcI|C2n4annMK3*h^Fb(um6cK&>hl<->g4x z(VxQs(t)4~P;W$Qkaq#8K$ZolZiZqX4iNkp=?K^0o`PRN{qT_jz|X~QX>G7nK=_lf zb8B#4y&WFe^+vVmotx>=*CU7Y&DGegtdX#i?YreQm;;0k(WcwUUqncY&Km3h(oWMn zzOC>3^Y$ArrMICjTu_z)T7p%< zc3>gtD%svu=h9kUyOi!(OLyRwcKcdBc`2QBsav&&T`JA@UrMn~!3Oi`OLXKc-(FZt zx2@sZ7+-Qb*Oc~mEx+wjx|Kmt-JVM+dy%Ruxs=YGXD}QYW+?d`ms0kK=|w(uDP5sQ zi);D(rF4;3b~1K)pKraCvLOj5^4UwNj-b+N`x569Y4sM~+qIV7s#bB`Sj)fe5(bp5 z_`Y@5@_m=mJM_|>yo5I$Fvz!EVr!_U8n#?YyKWDiz6-^J-z%3=&gH1DyDriDS-!cO zP1B{dv`3gJI)3LRh2_1lmd9%;JE*!9Um~k8>({lsc?spIPi?oa@n1Sg!~z=J?ebaE*z?T8l-P{F) z6&g8NDKEHN)|j2$bm}&0Sh5;8f^2m(+#NPG;L~olc>!~04M1%-ELwE0)}33|fO*e= zivlXh3%KAvkPG(*H+2CZF)O6az92H(#TNeJ1!zJDz-+Iji%j>V z+o=v|xU*o$*7JZ3w4Qb|7l15aU7+V}@bf+ICUo1~^t5|Hll7_*j1ZZDaFcH7g2dHn(sm;l-_nGvsR#p6=14f-}HeJF>HeB!s61Q$^gyQZ!U1A4`}`9ZM9k16U6p z96|_K52>eMJJffJPz|hv46M6^B``uGZXin~3vR%yL%V(9nN1jzb2n|zo!5lFidO6A z#pw4^<&4eItF5xvfNwAi@a+yb+783B9pG7d9!UVhSoRny8PaAN`42Cqz%UliJLi$p zaAML;pNCq~ZSWXa#!m2$X6G-6WA)&0;2yI)X>~v(9yJPvflenhpqYYUblhunr@}Be z*y>(w;ON;DF%)JNMn46_+6HbGv!Y1AErtQ&Y|JnKDsv@<0o$>84GaU>5*P-!z+CU5 z7J6`pdNO1fHtpcd5*${OZRCvL^9LVn7zSo^V;EB~4A?|Xv%?mUF^pRR!@vg! zl-VV$)^OJ`3@E#e&}aw+S=YYj+|vP3#W#9r1_j^f+LY3b3g6h}`3CYQ@Qs~gd;_r* z_(pHYH@r+*&o@9*1aIIQJ2WXYUgaB*BN|KK8@n~PaG7;{gXw1qq}QY=BSv|+A>Y`= zOx`NK0d`%7Z=eSSTwzX2z5zynORH*6N{ILdYy~Z1oNutvd2@W@{o>zZ7$8ny7%(c1fHf9(AH82d6kQVZ*&@jds#x~{`*sNn1 z%y-E!I65b`UNQ`X9pcH*@z%gFP!Gl!hDo`CVZcuU!$44!3}ffbFbud_!7y&QF2j(9 z;TguQBMiedA`SQY4CCD}3pmJTcm;SW9pko=S0IE&bc~mmS1=_*Ug56AE13C$S8Qjn z=_YtZsbhdx*WnerOEf9eROuKXgA`TqidzG(fR${(D^_ooSG*e?qhQ^mItKJpvWz{( zGN8(hSqAJI9b@N9VHsfDtuKXT>>OtqLmdM(ZTodt#+Z(QIwFx#mk{xS;zle3ey}mi z0Cxh*0C6^E82~k~4AWnk*PGNanD&xotd6k^uVWa?D0B=Eb&O?f7ZMdL1CFwRj*;FB z%Yd&HEaPjcV_ZVVu>a`(X7~okI?6Y;e@*!Y^D^Wcrax|^V=(>j4Ob&w##9Wnk&<6{VR0jV0W;W`Um)%SzW`x2<`)1p@C(yh zZ(hYpaxa} z!!ecdCRGb&ykr$AHGqUAtMICYA><}i3lMz+)#9dBBd?Td@jmp5O|C|QR2~QEzAPB+0{s?Re)I6;TA*71=BgERoH5z&?;W0)yVr67|dzOGQ5Ie3z0&>fTL`nVBGXV`_puxNh z`Nn1q8aK6J0(M=8Zww6@%xTFtyuR_Z*f4qDxv;r9^u~aCN=4%a=8Ttfr(~1njCBi? zm#Sz~7bwihCK$#mV$N8>Kn4%IRaV)mH^%q^Q|=M~(IaOB#-DH3L(roA*U1fp1QuhJcOWgR~sxpv8s zi>bhEMGk(Zih5V5;NZu0l^pz_DcLl5<#yS|+qPUKgoow{zCVp5!tqKwj6;_~I>du5n_`_+V1(y{4mn(x>=--YcwTy%B|PtVI))V#;6 zW;yxQ&5esO%P$nC8}G*DJ$@QSFyW)ODb+%!XT;vvkT9RJE;L=24V2>q8YjPfi_^S zcjcltkUUsJJO#cMUgGIxz8Q7l9av+oeqf$CADT0l;TMR*nQFfA-a2;)UHWq70~44c zKI}6=xP@N8H;7@w1I`QgoKWh#wzKaR4=@{+9606kyT~-+G-{gXR(VuRh}NeaLJ6wB zjm|9?Mt~j!mIz*(I}JAqFRm2NJ;Mc9M;pw#v$SdqY`LDP(&eNDDlj&;^E4hWpt5lS#Spv&&kb5n9|!HXy1 zLu&QlXfMBAa6uW`r_E{iPO%M>Hv%f|zHHa_;TXsa2-kajdUip>K;&+kl-z<>Z1wm7 z?-94g<Vtd0-O$k0bCkbVIA7bM~)QZ!_tD2h^_h)(*_z1UH z&Q1s$nKO_VJ^>+%Ap#hVvNhmsqJA+5xQR&$+sOb8Ud6X!oCpf$o-i0NRvovR*HnW) z^1@{{z@J$_55_TLlf0o38Gm8kkkTBx>hdP@3%1_In;;`tx`%hrI>FNIv;*x*N-%jT zprlVs-cENLwM{{^U^)b>*=Jgr{T)yeM2FuLhp_IJ1e<5h;GLW*!K?ecPL3^8KgbFG z0uS*b&Xv7NuP(qBa3$wxnYn*+dW$KR#DPL2>wywyFnFKW+-^L#b!=?Ae0le*aa8O! zCv=u)E+@oNxAOuLmQ!JMu~BGr9{qxo8Jq|+k66%?kTq_V_9VPo_UR5C4I}s_j(=`|i~REe@OI(>D}nQh8H( z`#v4pp=fu1=X>I~amI0m_ZSCCuULx7hHF{it%xjqI{X^DhD8Oa6H=gce-tV1dj0Zi zJtE3NHA{?ehyv@#wt`hD{=%WymI#;?%xHFwAT_wciHDih} z4~ro_BmvA8-PR&l@l+#FGZ5J_OUg32hf9ub77gYYA+#@#ud z&eCQ3`XIBLxaJ9t+ftl_8WxH8Xn`QV^n=83gd1hc@8Zw=yH4`A^{$h|vr&kwngVz! zc$p*T7m+ZJLCvjWG>)J=MSl|dqaaZY`Y@3u*$xtJW^+`M5On1vSdqB-6I8Zvj6?5% zrU(T?m=6n61{dPeBdo4u2X`Zmb&;hI zKq*$^5>rCd{|4uVG)$5mf-%aT$N;$5b~;>;OO-qHdRo2i`CfmE4L85Pc(zr~rtDdb zXKKrjUBgimTMd#N_O>pNeMOb(wXFit*6^CT=X)dUUG_1@33^||98an-$0N6_VB_)_ z5|mX%=e?a|QMnc)1`^_vcJ2JL0@Sn&x#~=Ukc_k2Ai^^Eqj}%TRS0#yV$G^=E2@8m zC)B@OOibdo@^u&eKxG}itg?;1t1?2kD?PY!Ea-RNq?*N(X`fJ3nS{84wRfe-G0}97 zZA*z7gYrWUmQq5-)a-IgN}L&D7TTxvVLOdbG3}^g{RE%YPSNa0J9|^&Z28LXObN2( zn_Nwau;ts?l@ea7Xh%I}JTz(*t6AF7@HS{iFKawS{r9H?`0|zRPZx`(?n#$a{}2S! zPmIWF{nQQ#m*Y@#%_jgK?6N_>9Y-Msjli7PNJYYO-PDrfPuYQtGwC>Fy{fy zRvt|FvDEF0>VsZ@-ny!a@i7LJGBs_pLbdBEw^kV!5BR&jRXt#&l?OL$6(DkyS*{>&3FCsZ~Rfy=Cr0sWF~D+Yl;b2JY=#wf)8(b z+B!+63=3+6a2h_GW^#wWiirbooIn>G3H~NR2~A(8b`}Qu2w8E%+Cc`y!A;f7J-}>)=Z(kC1KAZUD(e-RJBLB;t7-BVXG>-Z~ zh`MaYw`B2&;~&rK7nK;yM+gro8sh#xL&YmY?U%U-G@fXQP%0|>p=^gzGLum5MS=sL zuz~Ow{qG=Te^FNmFs|FbUDt=teEN?`G)E5lmp#wHmju-f(rs+3q}w1K4q}j=Q!3qt z!hbEH8R>VM&?XyvULStW%f!GBLyGbx@<>ae^hpQC6Z`t)7d54M4Ui?<1A+aeatWRa zQ$;$(v#!x_%HLk8i~C>(`7iwI0FNwZYKi|Jk|tx#4t$LIB2`ADmIB<@w?uB!P2`k7 zA+j__lw_jQL|aY?mEm92=4d`+^Z$EhK2QMWxqLmg@<3(!#JteI(eP2L==QqV>QC}me+}3U@T!GlwM+F z0Y<1+F^-~?ct&}A`h40vO_GQer7EqN`cD!y{}lDA{x;Tak=NGM7xglxmwS&ZH%&Hi zm?R=GsZEtHlD?F;d$CLM$uk7-$^SAwe~KJyv|iW8Xjn8$?p(h}fz_yY1jzZs1W7mQ z>+{3?YBlKw%MrsymD1EzDoLhF2UaR6fHI-#w~}tCRMHKVO1h!v53qtzd59H+?mvw3 zr}9x&94a@Nj3cCJ+$m%xgQ@Xn0mCd5klNLk)$_zS+^;F_NCWuaU_d}#mNT)_=qLHtj zVj>-XD3(t3e|QIi&Z4xX%`pEyVlD(&mxQ|D>MvN+ID*A1CzYGRpz+(?aTT#zBMI0R^%);AJo{RHdBbo2t` z1Uk}DrZG{D5#_4a(2;@j4=_Gi?iVun}+X!?RGt% zKx{Spza1ADO)LFD$5wVClCqa@K4NXRxC_ft`(z&@A|K;t!P?H7Zv!Y%azOt`*Gk~1 zv@_MLLBusg7Xx~2tTa7byw0+0a{+}xGhDnnibx2no|Cu65?a=NN`?mOxu%^rL++1m z$W<~yUOIXna_P`>^7^rqAb*%fYp#N-|_TtdbO=j}966uNEmn_n^L5&_$_B!AJzToAQFNvb8u^h|v1!+Qz9b zSBHXf!?adDosj2jH<2c&Nc`so3oMNYbw-kb1lpD^$jC9s*|bVjT1EZuDY-{ns0A3jMDS+HFi<13CzvXlq#;z<;k0cc5tQO)7Fkr3lW_R) zstNBujgxpIb!k^+8YMuaE~y+9P-vDWpoRkGpfPAfUa2IEX-=kF>sLCv=z#05(_y%h8^0afoD z?=WG!nptw##ekHQX2%9iB1NLyDA4TQ2Q%K*?ZZ#3@F7U(%`+%oOn}-WCoS1r9L+v5 z4d+&OiC0QpzTvw`lhx@kyzgUpXEBuuv-^BiBkC%zE)n%}5QWh;$;RaBZ%>mRe9mW` zzkDY{j|;75^37O%-4og8OIi5@uYQlx(dRS$Uy30DIuK{KK18ouk3NBp6iFj0zGw7t zUPBn@Zqk3&GFl1D$}KDkNjkrw{CF)N=TaI+!Zc*}kx=KCl+a!hCCcu$pXAq0yY;hK z)Tr51rFEjWfUmQ}Z>*Qhj0r&x-uoUB>@CwDwJO*mFA^~>bl^drDpM8;MskE{ zY`w+888YJ^w|UIYGLHy0O?yk-vI-s%O3*l|By7AcegqkVbirf`IIM{%IqMrqI|XvJ zvI&K)YiGoiZ#|(eJ6V`0)Y*ofVOrzqv25~~fBX}E9`%@+sXSIZX&?z95D}fud3)@J zV{mPaf!<-%%^JtEQ*TCl(op@dFpUq0QW;Ayx+eL`T5n-i41~!MY!+QX1Re{;(PBem z7aNcfQkH&j!@A*BX$41)4uMvg572pKK)gZhhv~$XL6oDtcuZibxL^bD5L1y5P_(9w8`6b~Pup9;9xF7mX^mKAz%?_HAt^Bi{8M?NF+=e;%Gyt|%(t9W`b{tf z{zQDimy zOhXCLGFFI&70F}u1N>+j0W**KvcZ?Us~@rb=+*Q-Y&3QW7@(J|9@JM~if%0ZY4#>K zH=Py7ZDeZ8e z(pIifmZ6i1qgyNJ*;8{Z`{n33t4vy~mCF|hnXRjA9}koQMscO}-}Kucth(te+^t{K z_8LsSs+Qi-|O~Xb=H7Z!uA32U$#RLW2tylbwoZtX%E+CtrM? z&shqXp~>5z@~bg&Y)0}~>q$%bDCS{W1tKO^=EtE)bXT zeb6Q>Z=x^j3#pn%LirdVSE6b?mIZF<-sFHnEbE=eDaG&}2*1y1!oFo1! zZDdT+Ms}M#>ij_m9exAz#OJE!2{ccedX>`tRLVRd&gUQ6yTaAwlWPEVFQNw_#^E57?w|#nNawI|_ zysCwv&&k=t5TPYKAG4&l6-2xLt8syQBv7|@a0^!JZ7Po-_*Cgx z%Sp2}m)08EefOAIS_|^CIWz>@I!F4*{ugJmU^*yMMOsIE?_@j)xj;$6o&@Zy6~+_l z4+tkp?14L|c_jC&1w%?tS$QW}g54FhF=z0ci>!Wv1u}^SPZ{YFpqLy3*flzqEY;(G zM}xzxQ!#+}URiqhEXm*Z1!$`OV!2vx*vh3>*go2(Z;}~)eGQgmlo~$x-&Dho$3>da zu^MdhSj7KStOWC8)riv{WDU+Pp|_)0d*GWHAUvEf&-j$0s8z1j|Hx$4@Z2OcRFHbp zU@|FIZejAxvVziLNMrfMg*4cNj7_zKJf#5&UCSen@t$r-5!w>^fKy^!&1IhgwnU#! zK%Xff++wL-pbu;F5`89YNx$SMamwgJyEbjd0fSGNkdQdRCW?y#t}|7S;<%1LFovX6 zgr6)W1eKda)W4V%2|*_?g)}=Tyndpa`8iBIt$e|oz0S2C!QgVPemd_y`ox$8%zr?i z@Kh;K+OmnlQj`4hZ{Zcx|Ci`!e&7?!1u+!8$97atu>Y2}63;#ng{AoA2(B{HC07p@%W3|Zrq1FHWI0LZ$V{j}GV^6AO4{==FAb%XXUWXO?CagS-uyCccg)605 zc__`wLkVMXFi2T>cB#b5BTKBTJY@bgE6;wFSa}YpRQ^+ySa%*)31(HSJnZ*q`o6ol zG1vcWmFr)B&F_uMyTaOk)F{1*QM!w*z;k`o^8j2%Wnq-wB)2bsD%GehLR7Zgu>`-S zN8)=xYju_y?gV@Rdn#8?up1YiO42AjQ2?6(+m zNGA`PeDMU(gK$ZoM)i{qraf)i2w$<5;{MY>9NZQ4d8ll>^mV+a{#{S>$(sYi&8oSn zO#m4O3Cd492q5@Vqu~3@s^kjX;AxhWj0igpxJZ;pA{402)av032@I08_3VE;p;a_f0Q{%z1-fCP z!y&D$8`K{Rz3fnlSUQE32Rwi2Rvub(;F(OLyHt*wM9DyWzwR5cP+}rA)2K|ML+j9I zJ(0XOCRdGF0+M|G5g?r8OJ~q}ykgHlYM1Xx{^Tp~OR#^KFJLYI62Ih41VR;-Q?8jT zGv%43nu)_^!$$D)fBrt>JpRS}Q{_*yv|cTLMxAf{-;>F+bFh4HvzoX4xwvAX>qA{q z&-+Y)bTs{zbD4f`qu2WFP!d$GBG6Rs#VJzH_k+4B?}z{D{sDYS_4^Q1tKSdf#HI34 z{JK=W12-|1--Mr-%5TPDQ{|I5e5pKzAFIj>F^)*8=mW~cpbIiF5SW;YZ;Me#^bScH zmhIwMrFPIA5;<(Mi%l|#a#cZqOx6`!y-HXUrx1=6^c;4$qpanZ0sY@i3N6p;UMv;Q zvS2G&yL6DFY4=E4)7rADi5yJXL<`ODN9z+dY2#QLAPgiy9N*kO<0->WTytunzhk*s zt0&DknwjhO``Z@gx6IAaE38Qq)9)NOMz`C4?vE6Z{I6JObeLtyvvOe-oh=4CG^=D=@3KgdC0lmvoI zqs0U#Q+2imBf(lzHn6>93?fZaqo!TA|3jr}ynT7#Wdk#>xA&$!>0n7Okv>>~;wlfx zjUEObvfO7oh9E=ZlUC-t>4{kLU+XR9&yCp^WRRmhvMpbpiLm5Vzw9lBMyEqRyyU8z z=6N9h(1&*PKM`j^^ITHzJtV^GMF+j&8TCIfodsQU$-{4^c)$PA#E{Ck3xivQD?^jX z$K5o_*(%q2Y7P#}J)E_*2YnD2dQ}wp+5bW-&wc+pzI>QryQih4Z7H~Xohxu6#-`)s(wIa7} zY7D(CFCBrVstBa@m(BM}LZIm|^6f(enyz-Uia_)02iPAOV88k$102DKun?SI@pUhZVoMMe*F=wbtEeEq`J#U|yqTAd9t)vb<1Y)oR%qj; z@R!9f)NR9|E>^o)MUUC_=&>|1z@_S!y^;Zp@t3Xora+Ia{*&2jqQ|oDpwMHvc-P=p z@JvGwkfU9)-xdFf*d8qSAMMCi{D(6_3@q!y11+6vH^zi*zN+k&A$Yd=%H~Efq2NcR zgj^FJwp(=tK5Q?#HG=L!#l0o}-x0jvyQ&U#AWg8?Xuxg%kW3=j5yGfk7*$t8 zcYajhNiYkl|7;foxF6Bp2*w3pS<$R|NcXz^VnRy$J1KELt}J9lTLWv0bgX8GANa<= zmwDmKye#l(RR;v-sqdZeGA;Txf|sU9rwsr*kI@@=U|sJFcL0pLQP0kimUosdFQCl1 z1#5XsmhBq0ylcajZ4wrSjRF=ACg~lVUI0Alq7(*5;R;KaB#Rzqju(MOq0##Hr|j4j zr$+6&o>bn1)S{m2OGwUvB7K}|51PpA4rZVzmXOSiW?1@CTEh);B8qTs>gC`6bLf5j zpQ~v%M^e8(m`cvr)giQ7+ci+;ooPKvr+Lxq7PxM`K}n)IH;~1wZ1No zHx;b$XgFI!%*|FnxDoi2BV6EfQeZa*o^b`pY4<4bc6;D$9RZ$zoq!2~Hvp)Wz+)XH z-~qYzVUQxuY`yrgnpQ%M;`IP8j-6G;Sb>+XbO{jPDlrqF=x+)EsRx!ab6FrAz*E!% zl+K6KHWzxqHf$COG%SD^$Ya_la<2%8W2UFlp8dug<4M)i$6mum&{{QuMzxi}78b=C zn-;}e7#mNfNlvb|Y>?dcOVqY)!D@+G3-7S1ELNvH6Kx(zr{K4?%+|WJo4dD_Z#QvQ zcHN7`^0a45bImk}NrTOX$G0g)Ag_ZQS6$+P^bdRHh(;g8)sa4;m zo9%z5ldbyJ=9azapbCTxON67YdnCx!FsHD`rEyN8Gs36R6+?H~7Lb23R!HEJZpZ8n zd&L@Ua{XJ#PhFIfYES5mNyRy#r&cAc=VU7?SjaB*oixAxW=55}^pj z4pzceRee2*Oqq<>3#QqMnVqA+DsL~R=7;Oq?H(9jMW;>=3Z*lZQg#$G5pAIJnU1hO z=pd61Y2a3WpZb63d+Ys=#*B-5Q-f(x(WYm(9={_XV0Wkx-m$J-9a=t`Mcr1xGt`yG zJ&>Ue<1vYZ?gmD??9Ot6-`mXY^mQ*5%-WCT@jws^60F^By>Ab2Da29l?4ZWXb}7mE zZK8Mwr|&D=n69*gv<)wK#-KSjgVk`NL1CL_fKkq_cx0H}xMTr+W>?bB^{bQGXSyV% z#wOIE6M>%%0k;P%maq=gShx$7E)Uuo1%g958Gc3Y_`2;Uk}Ba7^pQbBsBe$08f=}+HQW>+ieGnSkqPE2NdK-Xe%-Zho;9f^ z%m!W1iv1RO%C)6GxGr_kxd>k37m1Pe2OZjYw?~2Srp~~ue;LrDKH(N?ToQ#fi{3Iq z$%UR_JuqpM_Do+XdBxo&DnTB1`|f+|Odt<+{~iP$imygL^>;=_|ElnLuMZ}^YTf8X zRga?rlsla0Kdox`OYW(`{H?Wi)vjh6bB+kVT5JE-?>T?-J?Agxuqa{hF=<6<&1OEj zMn@XA$zf+_V3UPK!`%Ck;R{Uvs6Z(KQ{QTKA`KpQ5E}q+S0vV zalv_x86O0jSMo)P(_(97qzDq)dhRgzEHG+I1T=mhC!b;nr2jVnD0Tl&kGe)YYX$(3 z&!s~UPjv+G47GpBUm+hEmJIWT2(_#i@YIJ0CU+r!fN-!5jqOe8yDrh`VcHFkj3ggyjNB)eeuL>na6SyieJhK-Qx zs2>7cRBfpue3>Lf`z5te^%*<%E3spbs)+QjjBRb=A08V}wIrx|Y}!=jCQzC4Z8dg5 zmP1azmToUjlnv8*Xk12Z!`HXOB?i?%&f}u_d2x=9^X5_BBpAG)-ungR&&CwsQoJ7o zF_dGCNj%u0%@eSCd#9vN`|w2{8h8c<|RV zqbHP~8%QH8R&78k%pm1tOteT|o!AGA2_gDCw!5INse8y*u=^ae{&h z*_ab)+VV6kTNOpVJ&QJsDBTV^m2MmqoknU@sp5}p`V7PT-9^KHUi*cc=OB4Br=%w#l%P8I-zmM#oygz=QJ00bP zuj3Yp2W`PL&6}-?9p{y^4+2N&RWkM2DU}qP^ImtR@z~+Nvm8%(`ah5=VENMF`#@D? z-MO2@qA_NOqfh;VX=-D{?1RxBu4$@lZL$s@N|kHm>_btt=T*~^-jzmZQ@ATC5viCE z*gvKUF@=AusyGS_tD49~#k>Lf6&@9XyO%|mN2~uMp~QDY+kn(0EGudQky)p)Hc861 z1aO&${GnysqHQv1L2^(?@%ov@$R8$2h`;ENK{yA?crXuL=6D{8w=x6M7#)_#%~$%v zY4OHZ`ol48$3j4)497kN;mq<_7y@-}nT_~JT0A=zABi?V-GL14STGa>mnKu6K|%sW zWa(H48A~h!QjNi=j)zAY1kPV4`qS^-sb5gE;O_3K=L+sjVjiLXk`#iPUh-DSefz#J z8xDt^mpB@e#S!&T5w*xG$1?gldWGsgd0j(>yfRcn} zSKwp;!1c1pC(~%hfbWyhxijcB)D%dp&Qi-HQQ_rJrAZh7eyVI|BU5d784(@DDZ{Mc zWz#1I{uEx0!&gI~nn(TA0)YRN`VFk{PgT$B05E`Wp|xIT5~D z^ry=yCm2~rxJ@ll%E7j*c@J%Xj0x+cRys131A+W9MFh*0Q1oX~zlOs<6aCI_P+y8O zkW zo5AOz_l1fIeLhvdIY0>Q^Hr4uPg^E#TB0&S|E5w4disTEu#OhK5RF!j-i~_H{(dnH zq9H!;i&5JNDmxT>VA^fNouyLySo+q`*0K1uazuqd1+OSI$mK!~V~nIzQ{*#~N)mtO z6ziW;+qQcD9BsF&{jZ7U?$NiAp?6GzJYJD9JygQ^zobqKll)6L`5GxxfUiiIO7MtU zs^JkF-Aeurg;E?fvD_2AdA^kTlYO5Z|5Efg8?n?Sp8j%Fbf)ji)xd%=p(EqV6;mVc zIi!hXUIJ15YwE^$`+qGv353VDgoW-Eb3;4u)nZ6HoB&_>ucWVyA^pnO*9%7D>Ef%Y zQq1J5)euuuxWn1JuSuy;``Wq>zc%SZqv8qXVz~98S{IDs>!~pt>er*GaF|Y9<~O3! zxXR=kQ5k4u+U3IEn=02R>%CExh?H^#MOkB;*RTG4X;5~e?wjzjEx)$VWVYHC*s*6` z-%L%|yuKMtcr1huHNX(=o&eKc&}Vg{E%y+vClCd#qXf zNZ>y_ywK8Zp`6Zb1rGKRE*#aH$E8`d>#%w}K}jQDl)?RYG~AL^4U(?KmgHY&W5O-U zts>?rn_%w#Xic*E{gWXs_7J}s;~Vy~!1AX-gE`JYJ05u;4bOo1foO945E&?nJv|vH zO3TlJlcsW0aD=}LfSg>}1g;V+WjZs>CAiN(GPJisI|pT+0R|@kubzqz~ z4yYX+Oa{hMdSM^}i@n2^yuf8BW%2miEI@lprL6#&NqslL#Ny!S5>KuL17PO`u=CD? z)`;2W;QC;+ByfE&+F6Gnod9jofDF;<)S}geVhZsj*0+<=V6{izOQV|~+;av`K00`g zMAAC@zRCSf}mNXhKP_!SUBtQ3CR*44!H$ zc)vL^U=4qeMrmvKgXjqsVrxmAO8tOYp}eOh=?AWXkCD@gd=8Vg0!5*1;cZxiVw-;G zT`ZA24d3-2_eVdBUQjzFck0ZbRtEs17UKI> zvnsoQJH)Z{GM?>F#8_S&VXQ#I<`pjjvne_rD;fA&&cRs znnrKFPA`qov!9iQbb?r^qrK0VN|qwT%2NA%Lo_)q#M}@~r?XW%QVio|>6@A?^Rj9w zWw6kGt|M+fyKo8{Q-K+HNRq#79R+-O>WF}(ghXDxZfF3dNp;nUH=eGfqOX|H#w)79 z*2w4>pt__z<+8xmhcTw_UhE09o1JydkK-owqMTiUcpDd2LiGwNG}AIq|@%sY=B2jbL#~08|C(Kq{Ky zunkZki0;J?*1UAK)Fo*P3cz)xj_pOOT2RL;7Z`$=+#6$HVoh(1VWm6<8by5sN?BlH z)l*B-`nohPvuwUD8o=#YKV2lAkFfu@g6`qYlS?$dc_ibSYnsWgg51ZzO{P zF}ehq**I|S7koD@^#OXF!Od{CK6L~*F@~c?-ar803(kW`OUg6jsl%ITG2|Oq&A6T! zlZ*)lm6WWQ5)ugtm7v4F1<1ih?CN{SQ8FnJRy`LcDMGZf$~I$>_9~Uqw8etuFphej za=`-MpOpJnT`0#qneuW9T61>Et*=_ztq zxg~sv?K&FkB!B_aYyvQ?02oR`W0aPdh0;=~Qi7iH3Va}BJ#q2qt zjpx`Fu*?aj@asGJ`6VR2KPr(>0vHIJlCa0BD)#{b+(j#D2qawx8MeM>M1HTz+oAT{ zS7zyK(hmpqOnTcrD#@s(tQ)K3AM%{OE)mX^z*{BRCMQ=iR}kVxI-2?OQ|!{W;pB_=YA&gYx9F{it-HGWVcqr-CQH#;BaH6@|&a~xWAda?_L4obf{$z zk#~Y`JeV(%v8+RS3^7tfkk$`)%fW;OwQ~{v-%z^#I13e*!8(_@iR1@LwyVnFpg}0y z%;233`N1mxoKS=3mXY3?AVgvmwIzl+%Y5u}e!d3Bo9T3oucVWdV$CyZBYq zN(x3^9p%}9fqM2(iCPjM=+k8Y)pilU)bqf(Su*8BZUNK~+^X;R`N}+3A`NYUR(o-Fw$p5OI_*vdm!vgEP*OKT%hFY)DZz|TRU{?Qv8~M@twbasP*(FuKTwj6tWG*W zwB$lhW3>bW?DgM#eu<=ikex^`00BqvF?B+TZ6RQiNXRS&pihxwtsA7A(nvX_k#b7Q zu|{b*)+jA)6s4t&q9i@kc@SCUUb{dgX`=R3B>&EoG5`IoW?MI}t>>!idGJA1#x$yg zWE&b4=@&ZPz5+4gy;3o%%*6q2WFgjNQBU*-l8l1@=|&G-71jqZrb00c8Cf!bP5tbrjRAkO*PZg_n|yDCVfUu@1PA7!oaOgBVdIyq&Yd zzViWBz$Kaa2_hZcHldq~Z3HP1>OR;mAI>234QGS1bBB<{0F7?#`V{Df{m9VSBW_F8 z-bqm;*0;vlb;a3{dR!3Npfbn=+%+4V9Y2uZJ~+EMOQMOQTR~-H&=Z@NDd^Z&D7|it znhcf9X*-7!sVi2C@B26Zd~5kvT2&ho8w9U8hsJ^u#st|#7nSn<;I+SyxJB}SrrRre z^`$UgAYX*aiWJXiDN0W8r&tP7@};F<9axRD6qc)R(o)1iROVr$_>9CwFiFU=4u=#L z&MfJOYfs?}582lHI?A2HI799Y$et1$?qcHn2Cpu;Jys$yKrF3tiI!WV8-bi4EJntt znZZ4+#8NQ^$SzPz++qStau3*0I;K9HdB(6ogs*td9#s|MX)LX!hU|^DUS#7P(>iF; zsgB0Z_<}{!HfkeK)Wi6Fsaf$|0WKt%yPBgcmAY>I@-1T3oX>(OhrjI(-mtaew)7#( zp(goOqnAa5Pn`P_OKd$wUMYBxdROGR9~+)0mlE?2Qy9z^{^yBZ;~sj>1*~mqWDd#e zmH%K#f)k`mbr%vGqwuU!2CDQMsQjd$>YS5-YVb`U|LITde;}xOuBim7!JmaR!PJ~5 z>kn>kkAf$2PDEjX4zvX7i<9s>c@`bLqmE>ODk5LkBB66AuNg@?2wfV;dpL=KN;n9+ zn@99T&tz#`RSD;?MhxL>U~Nvkk9 zKfCA>cOXDlM3+2IyAtb8O;;4p0W70UIRM0tMObkZGea`eWAGaoeRrg6uN%F4ESWXCyM0RJv4j zf@Xay#|$jKA8dYd!WDf7*|Hz==2an(Q_B?tH~rb&_{g7* zLkL!e5D)y0lT{Pjf0zpk&=pHCNOF|Hai~?Z2CX5q=l&wqIL^mj+UC#z%K9pfM;M6P+oUhxj1v%(^h2$5M*v=B@%`}+7gT7HT&4fZuxeK$`K+qdqp>FO=MKt$mCdvyPv0Zot}mgbm}`wg=Ca?!bNn2`cqoD!>yMN^zoT@YmBbu%nCZ%9J+g_M|t zyw8y`jX4Jk-$6io{JY}&{}#+fR;+#3|Gap8H8+?J-dalXCZwTp&N}7yp$Ik*99<9h zB&PsY8J^O*C@X>;{Mg2ZYjioPZUm}ESqaW2jb_-LFdk4igjFMoQ*KvnOfw>B0v~2X zMuJOratf0#SSfKri9|pej6?u-+l3?nJFWpTu-jdOCviyqTRNm}nZO^`4Z%X-g0?{9 zluEtsh+aB9z261hpU}*DU0%sD7;snwNZm(HEQgtU#p0A0yFB%#^#?$#nr{OY$8Ld+ zja5xIhJ;$V#C!mW5I*Jmw>uH*LoX-kSlU)&vZ*+&Mi`$4ca>a}L-fBM*QP(O8-;-=}Ispjr&mfl4)R&YTSraP}FSkoPgs0zCL8{rDH@&-SGf1su zLT619t1=}k0$4&$#f7hQDurJsVy`pVqG}H;ERSw5&S%7VBuZTgJBAuZ*I2e*cBSLg z`f{lCIBga}mGUebyY-cO6isJSzlIrpp>z>3LMV>VY465sm`wt^gvKE}+Jev`a;($+ z%S6%mb*xZTUB@~?9CM&7?s?GBGgyFHhGCubS|tn=Q`}xkznc+EG>s*}T(|G2tG`Y< z{A=19?G9tU2AG=+NvV{^iN#O2WjQmQ|?W^jLr z7*R5otR-WJ5N~ZU9TvKHIuYa!1lcG%2TVN((X@ zebo?FhM?7uc6RVPOU0h&54q!8RAQC;3dht4`xup|n|C?vi!ZR_iEdJN-k>cK!|9#~ zTrk7$;y227Nh7L+t#jqY1Ch6jxLerU4#VUW-2RQkiRA5n3N7F}BP;~(jRJdBFm zS!-u4Bdb>X<}HmZVRT%uW72&)B6)R0Lowarr}x3%iOC z3Q=cc<8aDRjU%+?Wx@_{)aGlHdM4~^Y!_G&^)g^ov--`}NN<)k{PK+r$n5-R z0y$mMruzZ~adH=Px1t%U(VD2~ldVkj=yR`+%HPySg&9iAtrKL{fx>ck`y_m;3dv$TU1JMZ|_Ogi+1jM58>A8{;+ zgmS$?kWf_0=>SJje zH%P<*r=cQuS3B&Y z=Gqb{m3_rg0~zTKGe2~~RWaUjO++?EFutplS|iArZ!vA~fAo3iXHl8pIE;M7Zm>o24;gX9mX#+&9$PwtIV=+zk1&Q!yiQRt0p{ahU8y(} zzzDW-uD27$4;4;(a}|!6(T1}$fLj(_6jJ?RL+E2Z7~I-r^(FU0AnkVA?$fJ4K}g#? z+@pRz2(r+{wcXzs>Q(w@?#?&L1EeE!)y691^HBYjdL1URLUZ=|nI zOC?r^OMo5Bn3Fm_93+1sBq12N+T}g0LV^!R-t?)TO9`m_+0|C)n+I>~C$wt74MB63V zTPX3MN>JjV3I)cEjj#CkAwW473Gw+&heB+-3<1hsBgE*M>Hnn&5RG-GhW~KE?G$^! zf6MF{2hDYgb2ehRt}H@RVL5ZJ*!$C9xc254&eqB? zoN#FyT5LEClq;Op0jHfaY&%YCpA@I<+kn$*D9Tmy8!%XaTdm>#Z>5DF$^@4FhKOmfBu7$0AAe}Y- z*L%jsK|p_gdgdywjGczL;%pTc7}nvu?1xcx-bz@fH;#2={znJ6$mqwpE7%`7MqV(S zdlFS(9ugPy?;N{vUuoMeXK6i!KM!ca^HJRq; zoUJRB$HBzwW?+U6x-yPv9l9~r>tMK*!7oMC?%?&~%#%8*Om_Sj@@GOU6&`Z5)i3!X z=c7XI+*sYwRzLj0qyZD!(u%u%o;fo3$!ruZ@w@Hf>xINd5vjF_D;4;rw9c$!qX^10 zyak?0c+1!*@RhMq;IloTf)a1ZSg2>%rwdhr$7*-^T2xWi|6~hQ=>!+;x&sv_$k3Ha zIZ&yT@lbw^Q=*&DgMe=K)Uk~T*Ro)V>oLS5kK-{65cO(^fGP;Gw{yXmpT`s#EM+UEhAEa;46vfJDNRvB zY0?X&q?dKeJIeZRX*WBQ7PxL)QWT=dyrL7euzKE(`b5vWur$=88mBx*$we5?rBOo` z)P2o;E&g@%Ba;Lww+)#;-M|Da_6FShhZrxUg^n+5K_p*6} zP=aJFeu9&`iw(7inF?CW5DB!rw%Kf4)7WT`s{3N1^fqWwspF_pfIihR6p6JH#Y%p9 zHf?d5soKJkfb%ncZqR)WJ_aDAQxnRGR^ToU+u(*)iMePERlpR7NtjiKi89%1rS+_q z#e6OMFKZB>DBuNUWJGLwpq?O!AstZsW^wE-u*w7lg^$Q3@@Xy z^u{trNCO5q*wY?=%34xJfuYrf^iA^eP8GO1qi+{qKRtufV}Yox;b^_E*hYQ%sTkt1 zfvM(gZ;yfTP#c)KhQ!f~e9d#1267>AP+7_1Mb|YLdYebMhvFM=Zt*nA4)pt<1y@h< zsK_Tu3~sCx=bt2nDNzS8C-7E=t7j@)JyYW9wywq$DMLq~RSZ0B-W4aeP2+-5BI4%Y z?j1FNa(F9!9dZ_8@R`{}3ln?>o}S_)PGXP3uTgAK1!7_;GEUx!c5`NuJa*S)d2Ida zil9rrl3K|1Q7Ko_QHMtPTQ3*Q>&Vw>iUSS~Eu^mvwyDt@)1K2N;DK_m z$ErC#z~>8tl;l1^Opqx-`Qz)CIR3k{^SV&rI&O+ak-(4 z1E2%sH~_9V^jW9_IXg6ZB*@ad*>MzJ(S($a zLt=uAK7mYX{5@PYFdHldqn3`wv)-yzA5Q{G40^^THj3ka^r~hdEBZKGmTn3uNQx*+ zF*gocoD9ve5r7VVtPx9brLJ5qBsAN)U^4uSYzW+!MwKeUO&7>24WC<9dV*$xwxSuS4AZz4mEv(#%8N#&yl9jxXO(T&vrLLArNUA;{5U)f-nTG} zWGZb#6}P>K<+s0XE&sZu{OczFYb`&&^#=PBTWsrk|Epcxx~2q1N8bbm$HsV5Lq1N$ zUW=QjNquzZP1gFc>%I-9z0Dp>Q#K@6?{*&Lzruwgj9~QR6YzuQXe?Ac=HImnB8Eph zFBUX2U5=qHhDV&6*^zk8}yyYwx8!l26K~WyO!cT^h@nxsT4v{HjFpTR1e-D0af zu{bFU*UbmYDj9t!*Easrk}@Ij(u$R09?;mUgYqTsd?w8N9K!?#z-J>3%J+_s)idzO zL2)$V_%LCt6htFLs0etWlW^pT#x_hzgByIwr$ob>O-a4&QU3<-W%rK7BJjpK74)gw z&;YLQwj#t_W(gMSuSkIjK5iEr(h85wCOih}*#wV4Yc`19V(EBqJ`$ARv0TsKwN;g- zp{JCFzQS7<0Pte@?pvOWw#K~wFvuI;QmJ5dm2yp1DT=F7ET2l@EtSGsDixzL%jvif zR#4@Xc&wzj7{PAp9~pMd_@_*-y(`U^%~wzw@~#DG-`Y}^SXimfA;^UNjhp?U;oMGq zi<|rYWB##DIm?a3)kkG#HCye@Om8?l*PkCQ3>Sx6hFiC7KV`?M%ct+$^@uah%vVn9 zE)9l88Zq-rOLoIuI|mQgb(K;oJSw7?7tV^qY$9@NuS8?;%pL+Rkd9D+6t}h%BtY+Z zqR%tM*Sf`9?|lSXiXS)9iGE}-p$jWjgET}OJl3EM4LKFIhTieOE^jDK;qKH>KGx77 z8bTGip(R(uTTB1r)zMNM!Lw3JXU6bNWnR4Nu3cJ)I55Ms5UG-B%8Pe@+$x28!Ah!h z#@LuHV@yQ2ZWxnm&}~egdP9sU)aZE{)2^|WoDr5fB2s;d{0p10~cEj}C1I(uPhwqI+ zg+6{)8q{(%y&hy-Cq-~Yvchh0bV8f%A7*WS?!-<92%69wcBVE@t=goio75EaVZ-nu zzFTYdr=s~{+( zDLW*$s?A#`w7H{d^HmA2?C>^8!R{-YWOr}#&eZ1ZYV-C9ZJt`S`TxEkmiSa}lVtMV zW|FXcczDGDjuV<%uA2JBwLu-0y{X02lr>mx#4$B>Y(i6~RZacXH)Hiq^QOoa?W0Q4 zppWXfnmRtAsne^bj;5wg_om2K>`f)M&zo9RPufE zrjDwqqZ69iRWJi=)xzfBTcP^VB zouRtL2k)^%a)wtTXN~oQvfoeAnO5n|-!&R>rdJ|IhgWi+llf6@l^*(>wUm1$Bm}SI zxt8WfD^}@yFF!*hX~ip9J}^2;j>!S^IkU?*F8NR`_=$W)BJV?Q2v&DakcqW@PMIdp z&2DY&=eaKFuyk1ANWvp0)b-nWR@L_LHHX*JM`xwRE1*|~#n+Rwa*P$)?H_AmyZsX! zAIEp>7VX$AHTLO|@y*fs(Iac$XxTMMT?sC$*@b$_Y~&ZpZr93N@RiLX3o&4M*wYo! z5)pbxY^tiya`T7I?LEqKtt(-POj>+-c*D+*9%W-dV}))z!&b8m!z@jY5S--8IMQF_ z>r|q;NBI~xv$1odgwKZ_Wn+JISv@8Mxc0+vI)$chHpB}`Gn`UljF^XUmw2&VrKw3M zP18qd;svES08yGDoe~Y;1{du9MHw^R+;Ct^h}qzxSXqUZzeNU&b%uiftI>EqT(}lr zi=K^o2TU`M;}17{*!zL~7XiCyU43c1Lr<(bnTmJ5?GykNfIKMdM2SyUdC?F9+Q7~E?#j%#z!>A$=UuFj@P0N_&4cev0U&<6<{{#|ip*iW2eC@uq zwWDkKwE|M!Um`6sd3}~-PJv&LSqGosobS2uUYS8O0&6~7X}Yk~Le9yXT#%k*C#tY) z!E_sHOr4VqwL*`b~N?=%q48@lg9K$Rb1IQnCGh>16E zU#bf<&DMudt};0QV6HH*1;Fs5*RBYI@$b|5f;sco#Re%Ib;Jr75b7k&T{P_KK0!@O zs*k+;)~ksr%Yc?iZ8Vr@SUPed9nTRIj^1<4ufFx_oO@mxSDv&zVjR&HamXDxsuZ&9 ze;eSMWaF#*V@S!Ltq6ANMgWh|pHjsjRlQ^VMqyjT4rayL^>c%NIb)?^P+^f>DVELD zI5`P-cCwz0;zREm3_iLeDdr48d)%qOsX0ajmBz@>bfb`AldnPrSGu4(47yg2+Af;= zV5l8Zxx8U8D!0!0D^edG=>-;~{Ng6{fr zb-Q2Pv56H%)8;F$Qc7%E|3o`-QwB=(TIx+G}UG_7QaYZW)GTs?%p7rsTsiuRIlN+~4GJcLM0 z13d;gr(cbO$d&2vnp}2Zg|kY%hXq2iaFd%J=1CeF6jlvNnW!=3X$;M4){lZAn4D%q zjbnQ^#%{Gjp0U!mgHuL-oL2dW{w_8`?-a%+bvVC&h1~u_?(wi(H&O|iQcF^xKJfwSWi(2 zZ*XY^YoAM2z85G#<^;Fj8yhuSi6Vt{z*WjtqH;Xq*uhNiW!+OL6Pet4_N{ESXSw_8 z{Zjxpm6vMcDSs2NRQW6tWvcuw+=2DobGeR7&(B*Sfh^@(V@2u4&u(7dSlMDVjy6_y z*qbSFOz0!d$^ZddxuY*?|aNYGHGa;%wDR@_#SCfs7uO`%= zE9PauXp+6z_J24F5DoZq*-eat4{jZ`e{Hx`;6c*^42=9yJb;N$qj_w$s7D!C#0m|! zKCXd3YO!>+D3*+zP+2|$TuI@{A6!~#;GP{};neqV_Q;CsIZrXOBX>Ew zFjFG9ILnH)7rgLA*B`y<_O)xSHIEENiZ>@K$hR`6T66uwwg{NQx%`?BAy{}!f%ui7 zQ{=wS7f$VJ%Lh2wv;n8BqqVj7WltJz7dh7@qnQUsF@I(|es+iKyMgic>QQ55E9s!4f0M!UQxegjC+xOv zzRgmnK|yM(?-QEOw?cG;gGy0Q=u-1?;1kkPfE8$Qo&q$=A_Pp@u7SbQo{22I!Pyak z1$@3KR~VWrhzIO60T^`)4T5M|1>Y_~x^Vdd*qIEhD~s%VYG0U*bEpb|u>Cs9Qz8m( zKHmboaU*4Aia}&fYDVXe{PWx|3S?yNlb!KpGhYH?7t)HA!Ob;zg_rCY8<^)i$l<){Q zds$AfAOA{1WEgU8Ol+Q$k0cqG#yHr7Fp5`I{=qYxyjd z-1YNYDz`s|yLl+N^XGXg2j_#b^#_;zTyKBu(A_*03A#}t6(_!b{f_3+BocIeodi`b zsZN6QEE1$roQ_;lS68;#^Eq%ldVe0INaY36bnyFykQ6;1gaoN1^_i82IaPYTjANyG zmqSF(2Gh)(USe~Qxl$cv4$gn?&>gknSSjgkcqkV%$03@U6Npo zgOQ?b07_pZVYp-TZTt$A-QnDGiw0h-rfmo0lpjm0K^OAM1TJid!H4z`g`hg?Z-fo_@o#_>yvC+{hDT~fbT!=HndS?fJ>xQ+Ne<;5mtI+!ijEe=qnZJgw} zX9^>1(|YNjYFIO)3y2JwF{u!1rbbHCkto&7#r8B~yR~ifM4_E_zHRi22SBOip5~$~ z+eRw~_|-qaIi&FDYW&?7ZC;jF1x}+!qcA2uQS4S+wA>ka8;wT?-^*W=sNKG<)OVm;8E(JIY6hg>i+w7)c{Zl} zCH_WY1L~RK_Hx;`S4++!`Q+K7?`K!@Uo3({^4b(%qlBB3t#LR%_}4R>Qv>B}Vw6N%`RUR}VSo2q^k5QuGm6 zAGVH-A&tmO?dlK->*Q#FUI(u=ayhX#cylkwh}FHE7{VEZoQUi;PnA+Z+5j#m%7Y)V z;1_fBQrwBrtzFF7A`6N%$jkB$J6y~&M&6uS-1t#30Q1ygfmcpNTT{IE_vIYX<&}VJ zWjnNGTV8&@GH(hJeZ_XR50eD$A8y9k$v&XaWTaGM&4_YB!_%P(!xX%r-+{lR)f-J88=DEu}H!s+Tr z#%gBLZImsP9|J>FiVj`PwJp?KtO)uQXx6q-e#LP6VyoLgx69L`jrQ}$h+t=y4(Eys4T)o5lMIDCJ&2(S;QqYw8C+ZS7#=%#D|3VDoy^bmSsp_xIi%5m=t zWMr1^o?~KbV!Uj)Vavw|lZ--SG7_3W8LR=i@)(TS(VA%|Xg~WsQP{OGsWXgskptF(B6uGd{jANz2wZce(QUL=) zXkRL}u_gFXtTK%lXxrl3_lSy5U&v@-Hnm`C1$_mkaJ*j}d-=DedgFW_8Qk0z7BcMU z$`zyim{zL-Yi(K;v@7R;{ly)d zR>dqSJj3OhRt2v3pniu-KBN-v_^?X2t3!BF8Q}qo+|E`5^nitqvn;P#&7rUnwhLO z+^1#qHL8VgI}fqiv(+s70Bnn!VBAfBT2K@E6A> z7%Zn}paCn0*>eM|x;xq+-;Msbu`!%`Dm~QCH$%c5^tl=iSC#hO!u=L2-Qv!N?si_< zPdOncrmb$meQ@}ipzM;#)hf_ePX{WkgRYPBp7CsqW5=(Mq-WdJsMd|l19CEz7^3oe za~pR?*G(F=#Y2{$R$9DCOBZ3U9x}r%kgi?_AwJv+HnoC5TI=DZy2L@+^(mY%(a3D3 zU0?4^4v3jEIg;+GG&!7ci-+Kh@2$jAWeUjpA8s_J(19zu#rCwGy?A}7Y3x!%%kjnc z{OH7gg9bH{NkYQW{+v)@>=>hFar5g=BQ4!~8cAkKaYi{upNPMQPm;@aZbXB~*mra$ zUt(ELwXE=2KM{@{^ehqEql3ljxM!)#DX~B}e>fKKSPi3PfRjq0cR282>yT^?A!*G( z(wiwgxg7<5=bb6SCjN;9juchK33%(S0LowiWYn^>G_X=i1&1E2(vhk0gZ!I^n|Igr zrRbIDOQ{gq8_+@I$rsNMgDvlC?FP1J74Q7vA{%!v_0u=BDfTG`cUWRa(ac2L^KP7K zEQW(uZcRrzJV8dVD>bk0=(P+fRPR2NH0(HW=oxR}HhYaC&J==hnKe}_xQtY!CI4DWE zn(J9k4b`z!XhGKha&vOTVLffwRzFh_-b5aBK z&v?$To_VsbL-`yX1W(_F6nfamp>MjHs01B#11U-PSV{lN)%I&|g&cqOphK2s(w(>c zZ_c%5p5MMkRsi6%j@!mO(E$ouXq8n8Vx@;yl(^rTAk|#+=ATD3H!mPEZbGHF36=X+ zx>in!Pt19%B9_a(7yB)re`uyJ$&rtXRZx_aaNfL_v4kquHH$!&Iz5r`jjXLz!wT7& zsdY*PL=eqwdGzxK_|Z)jDIg^qe5{1P1@n7`IdRq_8?3bwib4QRfLXE#8Gbyg*zacN zxknyvMAfda+Vcz zRq121o5Xl2{oo(tmg0xEXfUsswMoa|wR2IL%$lz4!`T58(>7^_l*k`vvWHMKE7cy3 zBt`R5#P&*Y$45L%o3}DkT!T^sBNfT>kJu<0x&e?B zdJVbhw2Rwsy#bq*)K7@_?4Z1Gm`Fn|L1a|auciUyqx7qwuS{?Ni6Ca?k1?Io03Z2M zXl*c6|8cXb$V`C_V^V=N_w2V#42S+QtE1LepQffvH>Xo?Z~iHPExMn3PP|uD>wjJkRsL0*gs$EGDH`Og+PT z?yG1T+7F$MzwSZQ+8Y_kI&Zd-s7Z2j$;{(yCAoE33XfV;{V8#3qWXei^Byo=3}r z*PWTda^fp35C~JL9`JJZS%_tl?n=Rb8m*Ii+XWWMQ)V?_pg7nOz7uy_CeBwMt=?SR zvH-5Bqa%C!`}VeuyKF@^?q`X7(hf5iNA`i0q@6)TnCx~h8@dwo{}^a{M^@^SQa0E!nm-8hk*%@c@M$t`KWAv z?@o@-;15a%7I}ZwvfSdmh9cOssp9w?ep)oI9|ppVIPLJLF_Cgi?qtou$9Ks3<$u|j zZ5-B=ngikzMOPOuyA_f;**m&J^aLi;V7I@Ua6!qA#jI0Lsv@BJ$|Cv9NKbvT!4S`|an6W?3P83mBtL#Q#H4yw6#W027 zyZD8Q%ShL5m5{D;DiAzRlnW622^VEg@>YC!+U45B@f;CTgI)?M(W0UHxBp7)!1;`& zgwX2M0K*!%at1G<<4?Sj{|=tb!-*5G+IQtuDC_+-X$|)1b`0viEjaPUzHLf-IWnzHjsoU>f+%9&>11Rd8z9J3`E zJ)Belfac&U-2_$$GtTuU4T6!5PzjdWqM2#o;3TLBF?>TRhHC#43i{I>Xq{&^qM*9g zS#q9GkT$3XiqUg*nG*BkS-Fe#yY4ITjqKZdxp3(Df{-8Qp;c4p+!AVX_?VG@n)vK2 z#6;nfeK3P#dz$D)Yx6y|HaMLv?J8?0x7y_)NLn1a?W^%S2`$w59X1YIU)PD-N;hGr zt`TPO30?6C>#pJ}aYlWYoh{}k*RxJwPXKyss&xiI{73yC+?fC=u?s^H%^D`|j^+<= zzY3Cr<~Di=8I7ly)<$l{Z^2+N8@Uz2wklo;VX%}8)jGEwLhG^`+enhPtX&Q5-JKAZBYn1i>3uaeS5@`ipevvy7-;qTp(?L@w4WJ)+k}6@k37t_JAE zy~{Ss2+XC0+TKct759$9#2H=21{&@zwlb1*+FkwKWlT%Fyuc3d!fQQGe}0JLm_cU6^017ft)aDEo|&QdfWveRZL!`Oh{vqj+MboF z#TY#z)#e-#skBg=vs7~@p}dc*(DWnI6r*L28MT%lm4338OUfJT*)Ji&&JJWnC`KR; zLNUdl=>xl?uLJ+H`g-&oI|(RUk>~ryTSTWGTxv6Y^tzd@R=cs9emcoase+)58+<8e zvyf+3(>*)QDSH07s`;NwKaEc}mU3*mPV&?QCw^w|3G@A?qo1!j`gw0HDH$ZcM190X z(-sg zx1Le?oug8cf=crgp=8*#n{LgTjGXig4;yuU)EV3cr=oc?!AXtLi54y#&*qP{tFOGu zj|H)q$dY>1eiDE3(j^n|i>fwiT;(##Yc{d$)=gq{4t#*LG0uUD^PXDra#k?(gF+{n z?;-rH$M6Bf9hCXW`64z3LaC$HfpoCLb%s-FD_t>W)9wu(JcDx~#fpS&$=||sqOoE! z+?uQRvN!pA3t7aj7hZ6FXvo$;nO%+P zuQ$WRnN-#a4#4ttiUUhZP}6d|G$7CKoNOe4teh~u?| z&O`n3CX#tiTIjm^1qdHnt?uSJHFW@O!hCpm300$?>+ zo?K#GP3Cm0*n&hD8-UJGqWZWZ#1t^)2KbNc*+~>I)=H^>v5g(Fim)P?26=B98cI_Z zQ%-Q0fb!hXMME>ex-^!?b>m@lp9#IsjbO;Es(Mcl%hk*adtq@~uO{)w&2^Qvv318@l1p{Fg8477o!#@<$1ZJ;jjZQWAr z-Nkuk0iH!3`h;j(*AIXaE5b( z?@v9gDo5A+Y;}2q;`o70k&{v@`6;xNI$xT*(zmQ7_XtEw^2toL_)^pswY(x4fy?^rHAyp~&HBSVs*e#hSln`2W zCQ%xvfvPtp%^O$4;|l=ZQ?TJsdga6rr86hY7mRGEi>iae=?F@Lx~QTw3*C^jW@Jnl z2Vk8$XJ|}?5Qi%if+dVfq6-K`A*hxC{29q}?yAL{@i%~lBZtUn{tDsQp74gzApL=Z zT&vMWyEDq*6Xfo+Lg-eAa3~Z<4Vmbyrhdd1?Fv4~(3O>yX8VLCITOv8H?=u*C)*rq zt3gTvjTfaBsSO*1MLi*hWt1l^U{n`~J!pSeQ8SQBoM!!1MR33!xdOAB<(2;@al1y=;PzbU*B3RT}v=ikv#)e2XDF~dFxU($p%(rdGiQx#?^5Or-p$nvZvv6H?x1C zqbN~xz5~cf2c^KcSf-68kI*D`!{frZ{xEr(x%A2%4Zdb8`6gCxSo1DT`FabAWX5*didB+c2^x!jb)C+u~wwewv z;>~V&kdesP_^HRZgic zFrA?-8X|}<(~yYuPH}9F_;I2l-+v4NvRoTiE-K#{D}(e`txV#LB=v_DOz>kj2SB(< z5a;^+WFdwdb6@X8W|o!``ab*fCzhRX=;BBzV@;{L0})P;WxuK%U>!+T*Vua*{5 zrINO*lnaDP>0ne!2cuG6SU<%Dh4Q&ZCEOI-xzY$qoHrKu)0P?+EMM}&!-ny|5&>s8 zT097Z4;Mtq`~7Rn2jZ==?;bWh0x{9~G_qjPcy11gEh+V#YA8?LaU!lh3{RPhMJc(O z6j=x5I5ROX;Z7;vE)7z#OZW{pLK(a&$40~Y8j1z-PzR_XXxJ{15YP-*RTnBrGD0;@ z;+p=D%J_LI-^dw!j(*|A<$CeEytpiC98FbkvX22DVhR1@ThbqdmMjwps6|M6!V|&QhW-0&n`vw{L_( z^BqCc4wddKEhwt)?SsIIY4YtMl>#B;@Itd>C3nt|ODz@cIFhT?>CV8|{3N{RUm+64c5=mTVm`ePn82+#w|p z^q_H%AUF86xXXQM_K4esR6V4E`ZVDcHAc;k<55dOU}F(CHd;G=BE!G#*46=L&*Ez_ z=Zp3;#)gNzah|*-+A1Z-gSQI*r8LwKJEHFxDoem}>LZ4xk3t-%jX5OM5Ld)ike#Fr zv+g!?oJW0yuH+X@gE$qOdDBs@@4RcAOV8`H_YpXP+N0ci0vi<2Pi8k7)aX2zCV5bc zuFnpBzsv^(p7V$mkRpi@%MY~wo*~fh|C)l-7W*~NX%<0KDXgGUSYbY}f}VGS z4fL#ZOnTl!kiW{kq}x%sk1R?mr^E`Oy>cA5XpY9`X8*TY525!h(#4Td^(ywLlt%M5 zG){t8V?@N0Km1bG9QKPRUSdb@+-&VHjy6eza}mF?HztBXw{9MB&oOB7X1lDk1Cr4p zxMBr|w3V(2w&-b^`-E|j)&(ceRN4-c`G&KW=!0I>_Ha(E(^&_NEwaE9O&^QXDd}kJ z^AHZ3%AMC{p;`!Hj0CIbvw3nU@`+0FgYb{@1f$gW&@^#1;d6(b=MII~xd*lLTy@aC zihK(#w8&Hj_j2GFG}8j=!Q47N&s7c2H*5)C)RuXA+T@j;xs+V_Qy)r_*GPUTQ$$)U znCxRd5bRPq3p$I`p)#64?b2TMp}>wa0rxXJ+dR|J%CNhhigTNS6LaBSvcHR&V|wXVK^cZX<0(`YmMd z68WZRQ`jkhJQ4`a2`Lc8ue=_BCBQ#-?=FwdOjgvbC^oY;|wT zQV*3kG`7LDXC~iNF5EBzRo>lkvh@fBPFjziX#YhEG*Md*OW4>3Xu)rNA`e&+P^dT< zC5=<|?1kd&r!NdhezS0$CG{fh&yw^p91VWDgqlma<4k41^fhxLn)F0XY)~z&S?G$k z_?l_K^G=N~s-Kia7+8%&tPp^0tkA|CS~OPZWNQ#Ar?dv)YdZlZfc4Np)nMJ&rEEGRY{v*^mhtxpmfF|4PUVE$q6)p)8I_^q0xE%PQv+VAgy zSg>P^KRkrF;G_m>so`-DagX2_wW4!{}?U(W#(<|;rhbrDa@DSCiaaoNL!G2O2`$=i+C#A8Ul*WEi!glV4zmv<*IVwqov_~Z=koKx1 z1yYUu^jKIV-4`~8%^$9Y2mRn~Y_57k_bv3S(ze}0oR6LtLvDGper^kXWg zy8Z1y6EKp9+n6bqlXmGiBwZ)@vf6*@7%|<7l z_-pKHV}(5){bc6J7>=^h_ZwG?UflV03%}>_`0d$~DAw-Dt{5G?;@7XTfL~s`;8?~+ z^T$Vi)S?kpd7yR0Xzi&_GFgr1<3DOqBei~_WzDR$sk26#SK)X-rI+8HT`|l?=RKL6 zZ`WG3hPC-Td+YT#6XD(zC)|KLR~syu+&6AP?R-shqp-BSrb(57P_mL63f-VMpoJ+M zt&$Ie@a92WU{oG@roKhh0nKFdk?@nHx#ciXtn~(8s5`dE27`L2jnXz$YX`ZxAOL}Y zH1V)wPJ_uP@$mVE@YQl4Fx49xE=o}0pi+}=4>jrQPi?lZnc28fV`8N)snk-b?C8>c=C`0 zwkI!*;DU5!7I$skwq>w=`zfdF*m`Q#)FqYOo-V0eSX^2@jqAXBW*K32!xlXJuMK6$ z>T!VBl0vYS^Lj}Dt(PN(F*dFm&OA1=jLNOi%x{lw=Y>@_!IA1G>;Tm2>vA1?od507 zG5&|!gckv86&JsF1$tYKsAwES`FZ;y^Qu9Dc)0lSgN-Z!V-5FdOIoi`N`XH0jb_j$VgmZsCGt;yoCynAfWv)aVGW@?|Sj+ z@aSn7L-vXKRQ2U{A*T4j?<^PcX!Ioy)fP7z`WP+$JMEf?Qr!QSI|}p@Q8(liWJRxQ z7b#NL?B>Po|9nTYHi)pGBiMOmmnq4;AtQV7k$3K>)eYeU#@y?g{3j08>VEix%eA^8 zM!+3=U6bjkYrKB(?Z4Pks~ZeI9I@B+1oe`cHHH`edA+W!>_rRQ8t8THb`#n)=Dc{| zpH8c_8yq^f0eW3etdHPl?f%h6>ve-Gha2{~c5evn8q-|d{`Va6a)E<$CdH1|b+)eK zfpf(jbG53$D#QGGRcC%X&LbDUe_b6Of>DM8wz{B_*20`ol4UTdC`!KKUg(`*o_Sji zs^Xu$Cs%ZKM#jY!_rBwl+Ngq+MT1-QG`mSp&db(&3U)Sq?OJM4az?muq|WQszb`}P zVoj1i=m_V5I*dCpgSG9Y=nv91li^Dmr9GI)1TD)EJoM(;nrw)01p`vnDL)mGIb1FQ2DO- zTsWF^2}UQy%}G5UCpyCC5)>I^U~+)|qPV?8&BT-}uC93d*olb%yZXm+DM3g=0|w5u zq<7`$X_0xF_CMN;useQ8!>KNztZe{}F*GLO6uCuPVKI5@#!}rmS^Lr;RZGT75JxDT zzma9NcQKP|*ofe^z1;}X<7FC88LKx25K-L%_tx!lMDV3uj{74!amnP1K6Y9S^Pb_* zgBxH45n-s^a4J1`uMVpb!xvu%tb+KpKzRU=AgiQ+cq&aUR!KA9IBFrLRk{f0QBg2S2dAsDSiQ-V-9VjTG6^ z=VsA)#U0<+UZa?g_PPWNlnG`cak1n~1nwz9L$K3qYVVQWUiKV0L&}~L_8#>4$=B|&LEs)`{kOLW5SYLy*R#mTzdr*nsGNrnSGiqUdCFa89gw+){opyp2TUpa z${6W>@!F=taBnIP4cpJ;hdSzW7(6)C-3LYUCAg2A_;0w>jTR7JJIFlpfNNg2!u`4L zKgKv(_#fKdM6w5<#q;NaN2Ck2T`{=`dx>&BB!?0l4GuB}+T_+7T|S8+i1cdx@}Tlt z%Wil(Y-V^uNW#lx3WtEYt4;(OA}d>Rn7Xpnl<+|_aW%^FiN%dK?u%n?Nvm8 z9DB~q2x&k`0^rJ9h`cY;d@=#~}Z*?XIdC6xvL;j;XJf#!dtfC|l+^hmO zvL;Qf97%F&Rwh7YBQy!lot^WBO>ICTyL&&ZD@yI>_>l^Y;;nzYh1W*T@Lu^;yZqj< z6LrX@oe?e=QzoC`A!@gZ2fmxx8Vm;i*wN>-wTEivD5+B)5ofA5INDA=0%JkO)~mo! zBVkDnM%yJVO5+hwinE_MnuSjB{)d))EW>QG(S$6MsjkKof=u0AU-K$6^4WM$ftEU< za&b;Rm{#%b4{}Wyv)OcE{M@px)YMQy7OK1QYbb6vOiLqeEM%F}Y>R9D0Yt|ZUw-?% zlH`h);M}&z`Gj|IAU2FRKAOnaT`N%Arb%3q5ZKF{)HfRF%rGuJRld6)NQ|qw)gm<0>!2KCbd9cJtjT zH|2Hg`EXo-cUjzjcR7Bxsy8K~4a$oB{8p}(nBARK+16buG4)Y#yNvp^Z0k5A&WY2+ zeyqG~Lv3Y^Ar)HTX5SR?g;|i3NSVHtH_FMME>JZi;}@=Mq&@DJrLOHA;Cu=vmZJCAY^}DJLX7b1$Dpcs7@AY~hK? zZ8FH| zvc+upxLBTZ$z( z7^R$kxV6!RbVAvTcU;UHIhIT;DO*P$-?$L3`sZD~5TQ$PS9Rz0fDCy)t)he#nrek{ zxKTWC{legFJUW_!3M6~;z}6@q6d!%_B6FL#*&Wk+cZizWbiTeMOPkGGN>6S5^P+st z2yX-C&Yel+}sv{B(JJ`cn-Dgt{%}ww1p?xM6 z84wV@#`2~bImr&fA?te(|p$EDQ)BFWgUbtm!y-i?Xr zbO^Q7P7HioK#;0!w(bdm?2UEb!{p$3(&=%NI=7`kmK}ipU?Tv%^FwiZLIFo;L~uYF zz`le*-R#QXg-Jxi{5XXr9`yO8)`)jb^Ic4*vXHYx_nSvsM%$1n<+=q?QXF>|%xbg7 zGu8wjoP_bmmsN<@ms>t|JA7(1Z>IFJEm!i5<_5pZpWb1OQ2{_{?{ZC8c)vtVta3M2 zdA`C+n^V8EvNBp25sLYG-Yuw$EvXRF?`&MsPk&|?4uxRm&?h=(F3)5fqRa3cb&|_* z2}3OR7fG`;TO5TNq&0SvJxL>rzxmq%j-o$qB(r@o6|>T|XnxT#Sk7(r^PrCI;Opol z%Z*8Nt%(ovf5iH5N37gU8SZdVq#GCD3jW*&VA5jc+`kZK>xG{U_zTS^F^mC!0uKZl zb`m%k!(PnL9S0i4kARoKJJ5xuDe7w^RN^%CJ<<~23osKG#J6tKZxj#3x1kBGdS-`U zH9VyxYdZ@Mh6i>&H?0}~JBz6SD9zSN3C!z4WQqT}DOuwEE|pwOv|FXQeNvj+Cnfgx z3-liQ`-Lj8zduDK+^${h$%UPV^~`;pm#IXJaCyZA-)Fh15&NEPaW*+rxwQ{sF1jrN z5O+!f|8)wfo}j&$d_TRIa`TFZDaUR;J@cFdjhYl%I+{9)kszm6&gp<) z@U+%&H;R^c`PIa^ro=fpjjt0fBSI(%bD^~u7v|)e7@)0vK)4i=N*GV<)TiFqL-yrD zVVZaG*#Ca}-?hs3E+6~*-}!R4e1FrQSse{7^`fm96#jz^8ZbyqpKY-Cxwf);RT6NC zrPNM29W@0=rbW}(mOc8CZb?>Z+7Nm<_Lo0y4Bpw&1&P*s@rHk1WSQ*pYhGPULQAd8 z>JStp?>HQRtm2;3Hm^$eA&IEIX`wcn!t0xG4?F&pcKj)Ev(br>%SBCC-4(*>hZ}ZG z1&n#a#zLB0dG~Tib!Dd=Umj*IwId~GKkjkSO?jQ<>UT)@(I9rREwJ2{CI&BZW z+LbU#tj(y=|85&xFoJhxKtS?Kn#IiEwJpZfDBg2(t5{4AU-Od26|?C9g-zA;L-bRQ?Yi3*t5JXO)eBXpANcEj^$mB1a${)B=TrPr z&h(GJwNO>N?Y6ne)dC+ zYI1*aF99g2pU(pnCAi%C!TGA`R|kZM9e_kPADhYUV3>>$xUBys@|RAcF7>EVQ4xb- zrzS>Kr25f&d{(CMK}il^hJZjM=*EPKhV4Vx;l1UE{`l?dvZsEcsoAi))$&jWLH20o)vIE3rNqrYRXft$`Rq z1Ri>j_5O-39!c=9KTnVe>xQ!;&2ZDq|ckcjRh2y!~B%~==qzQ-vc;aeGgRkXk z9aHYS?>2#(2}@CT@*Q{G6x6#~U!~%=^}FttQ<)3BKK#nMzk!8H4c>5S1xJ-F18u^n zZJy1Q*}96{>A1@;{L%N$tbl8SJe$III)gt%CGDbY8LkaBj)ez%>)Ns4M5o9{$1yZc zl+y4sr3s>xm`}LJo#U%y6qFO3e@9vWo`#1q3mw+4mV3D4y5A5e$+N0cQyp-&Ba>Mu zfUYrkW2?5Z29e@0fw>@}$hUyn8e|V{983Jqd@zNG+Rg4HfZC^n>nB|&sbm%^Cc#Bg z07$2xxe9--QWQw#UL0LjPKmhccjV==z=D^|;>y{S&rmBYr=-M!5@P1Y8r0$LS-auriWB63_ZsWm7M<%D22*0*@`XQs_e-1Hq`Y6hro*8|lix^rPoDg~ zHI~5ZoT;Dvrdm5OU_G4}wpu2ClFvKAQ;BECh8t=RkW;0#56+^20E$0jMxuI&TFi;1 z*0LDd?iGL4Py!VIsD+o$#mtTxh-2~=##O8T0&Z}*rnS+mSvTX04|4v=(VzGxxqti= z{E-oqJd_%P>u1tlVqVl%qhG^4T`c%xn$O9b`*~G^FlH&=hKm*KYt|#1Ue{P#@^$uF z@L*eo1_2z2KMzLeI^!PZbTQ`{+8MTWXQoy3)Oy>Kop}%(BLfW6o>-U zw;76rv#AN|$+Gu?14jN<*MBS#I!OcwPNHf7@H}o z%%A#9qPF-1o2%ARFZC-T!^Iu&Z~wFZI}kAV;2-B|dt9Pm5jO>#Xs(WgzuySzGsV)v zg4ohdW{#NMt2QC(b#jxC*1w7AH4;&|K}1bJ)lXT93Y6DQT# zpGXfiKIv|;z5vg|<6&Ao@VW(H%;K7p*FufUNs6F@fhGh1JJ{xD=w&r@zujR zl&EqK&{1fGzro_*O=K2y<}*xIRsnK#TQYOHLwOkH<$W@1+Yy#`@0)YO5Hp5fY z5m!FtseA7EzGVK}ego1(Nb9CXn}PM#R0y7LOChYIez!XL?bC6XY5 zqQ1N%1)j6pv1^P2b5d)MoT(kqcv1U0MV;H%Vc9mdQB|9~35S@OkiR6$hQqBuq;8Ro zdzIj|vcUselF_@Sff75gk65TH0d%cYw1>~ojZ6M$S~9%rxjMe3<>_)9ve7lpK)4~g zCtI=+Q9bWbQmJJ)2TM4J$8IUt+NZ2RlXg!2k1YzFH5a$fFQWIEU7YK*7Bl{7lUS&` z=r;H;K`Ix7uc9)~YY071W0N=%`WmxNa$Yj_P*9*HON0cKk#=Mf@=^XJK~?GU6z9?n z_=11=0nK7<{>P2h=D$6@GoO>SISlxxdeDBN;SNgLx#BNhK@w^(k1um`f898dHNd0hMDey)>>_5KaWXl%3G65hz1^FC zp>f%;IXd!G5jCCTqkVKcJsT45%Q64w-vRq0F^Ox^Z!3}?;dPfRo(mVz4qSceY#hle$aHc_Bz{E4@na{ z34y+ZTzl=}(TYhL;!ROjsxE)r`V}QsUAljkMb%H~qaYyT5CTJoJNzXA1L#zwbzXiZp}`Ww z&G|B?m|8-ENBv1#G&C$gE)U^Y5ctLL0}Wqzd!Qkb0=72LP|t2(HM@Evzs)Y9^fo(R z4jIc-YNA20LHR$_43!+{eycg9M5Gyd)W12yhsS65zBI$g32^i+njY~uYtvybRgeFT z=R>A7dPOXS%UJ@-adPvdN-Aiq)f3}u^%Ec6MLh)8K%^XaQ4*spF?@+-<6HsRU^K+i zU0%nU4FMtkqd^B>9;Y=JM@?mGFYYw6gE6xM%#0koG%?@%h0ahhq5A^nqN$*&-*|IO zEcS&#Rm>r!ycoMVrLkNVV>!fFl&+Nq;~UAEgE=-1<@cw-#3nNcAVgZoh7lGL$F(89 zHaQE4&1LLy3>H$d>K7KHmj;awbN6*p(A6=wtC*Ye{nFh00JtW%|H$~<-te~p=-ANa zg=j{2Q@wiQN+k8oN-Yqj!D;qvfO}LPcvIi zuX%jJce$RT%$qQ?JJZZgXl5ryX4dyKo`&SRb9`o>`%utB--o#H_%pN3hu8|D2b)>! zJY)l_xoCX1=BdqW9Ao#SdEKpf-EH$ij|q(V#>FPaJ~}?HkN!h2tk~2zZ}Upk=1+yB z#)o%b8s13_@1zY6K@`LDosrGqeQ+#kFv5^=tosDkw-_aNvY=7f|CgBSFRR$q~!lv^cU`=gY2T6mT>JWN*&p1qW6&N zW=zW0qFvF`1snY9BSMkXmICUvgx9fQX%Q__1*&N+@4>Z?q0Qb1`* z1>LKbRM4~3k_vjBT3e8`q=FvQHL0M7)ROXfSsh=yH>G_3U*SW9_HaXUk_r|s3rT?^ zvUwudpg7M=zcaYz+QF+W;-DKu98|p@v!$Z|4DKQ8qeJus1O8#fTxJeSsRRD=|J^>r z2QCoY$G_0AI0jxx#WF}|vmV(rr|0d^#t*)lOHnIt@haS*Xow&%>js_I%uPYS}5fo``Tz=F?> z@>^~v9|;xBv7*i(r-f)GMvWEqYR-;v`R1Np{wF)rkyZGvDhIqQo>Ty7)%Tu=avD~p z6)~)BH3}IeiA;#o+!Y5cV_FC9%*diipmVpP4ghikW~qEfa8BZ@$)fq@O}i-7g{d~= zS9F&t6tBr0TWfOm`$~38JFMu;-H-YG)fwq=ZdVrPm{98}e`HH?;gL36fdR5$5o+W{ zRm9-&*s>0dof09!<@TpL(@E!6VZixY(J{bRAl%;X)wbXhLvDXSa37Gv!;m27o<1ty zk3p_s3x52;oesI!{St?5SRVno8ys>^c62i_I#1xq;*9p@upS*ZQD65rB-}UrWKI7s z5cN7U@Bg#u{EsRZ6)wy)YBH!u(YnFK8Fe3Roy60z4W;okJ_JkXN|J?Z5;w4odiiTR za{rI5^;j+NCiff8tp{7$k?L-_a1etn+;Rz9?#rT(u=#_i0#hciu%#i<`KRv)Y=yIH z=nSbF+Er)nl%1;nk(aN7vq;*FAqXZFmW>Nlr93oTW5D8ybW1eR)%c?VXMj1rv z-6yWDd$^|wkyJ-=Du46t;v05h8$J`5J9}5>tV^~Ark9V)Iom-=X z2BAkSp22tF(Aqgum7T1KRo<`Gb0@s(o)YFTU51ZjY!q-SPnyc&M0?9=3U7r!o!mmo zNU$Bed?`C1(IE*&azWc`-??*(n1Fn~vhKEAIA6)tGF%%35x&qV!>xe;31iOtmWNCW zi3)RM$*8OhJ(XKx|C!w-K*G-`Wu5JbdgIJ`wBmo=wxbMB1VazbYROW#z!Q>{J*7o^ zmAdkqSEYMbYu~fqyV~!qWH&;u2hsyK4WuddNc&r*wCdY)SJ((`M5 z^RA?C{>D@`JL#CjPc{`bBATYCsjZK-B^<%Ej#QELt_t+JUO|D=wMqo)`Yc$0TAfd! z_IwmMwa){)YS($LjqQqz#X*J!2s_cH2mSG`HeCvZGh|*r{ZbS|yyiNDi!=j{Fddxu z&=1()rUaxtzs&YU9^Bra8fYbarNM(5@a z|5`=@Reu3mp7UfV)9fs}YOu<$6hz^nOoNiBn1fT!a<@7+d97&NW>&kHjX+#*8o}-Y9#S*77fCIa|w4391-lV zbBtEUA?5q%)7*GUtao^B*i1z6l@sjr&H=qPtM6;SuCee`oxUxysf?0*1V3JAzCUYi+hKG1TSwde{IVE~7L&GyxMmDMcCq zDJG3lKxX#K&1QGm;kLTv25LCIKiiCOdpmkamf>Vp)&^W~NJkdOQ0=o~U zuIY^LKWS3EWm@$N3b!F$7@tHo)lP#T(rT}PjA!SV z#&W6tVEw=oqiS*9+|{a>yIOeddU$JMX@(M({3pk@W;0;{lDcW1m#n^`}rm}xiiewCxe;%FfKV6aM&ob(5X4L5AP%cS0Bi0`Qnpk&tZU)Y@zD3h9z zSs5Uo>@e?x7|A!mn-+_va{z}yB|Pa=Ue0o59j~hO=sC9N4QpC z4|a!3#_-h`h8@HpFPcc$71m^AYGI?Yvao}M8;P9NRy6E0+mZr7uVW*Ca$*$>qcwu2 zwO|;nIU#5vT#DwHeYHoe2)b4k&I-2qm)Yc9fNO0Ska^`wgDVN^G^3LDUEpz7LCbhn z-Vji+U+2y3ORSKHQK%OYf&UUp>t3P?8b*TE@xl2m6$!#E)3RXqU=SA>cAXs|mDaI| zlJ!2yC)l!5X<#+@()NP)`DT&~a)O{VyX{g~hzh< zZ4ch?r}GpGxMMdJUd*|0M(67K&l$SfdMRDBab2jQ1n;y4U;EWL9r(t{9u(T}TVJ|f zx9qGBk-FWT>9+G=I^)gkm%7-DSz>)RVG3|21|$P1>{9+ypA==Tg%{ zg1XirzG@X3lvS7<_~5n2cWFnESXWrma!mWbc<{3lRkUpBG2OGw+V{O_ z7m6C8s-_gIlJEF9&#z{-9|45~H{dN=70^!SnEt3@i*o32nWB!$U(bM05NFR1AM#qr z>#z^HL7lY8^N181_B?VNA-bQOGDS_Tc2qMF;QQCW_MVBBf%_G;*tdh-re&~BT__ek zSZ)i;9mDck_-!m~;TIE1YMm<~;8#C8e%nL%?F`{JD&QpSg3Yz@YoW-=_-)ttHL~d? zT||+rYBTY2+P#hQ3e2x!-wtD*%O>XA@Tb7MA3$8dr(pN%;7dkZuzL|(Xv^ky;~EQb zyY5R{t}(tx>>Z4MbB*otlh=3BihWbJuV>$ryH1R!LLTBt2T`ci>Hu#4tKis>mxXK7 zD{Qb>*vS2wsT~Q^m7teq19!k=({?$OOpF z`M>EP>ZWr6d^&7PGk~w-oUaLjASsN^&8juP(`o1*MAsQNLYkYqwUAoNViQse*X4vv zMk0zt{?6S-l77|^>m(U-@@j^!MT(kzrsh)+`Sa@_Ap)kRe8cGyF{W7Vb zR<@K{)f7>ynj&fycTl?zgel&%pE!W7&qI4sd%mJcwCkjP76Y zAN=OGb`?UPGDLz!VFL4US5J^o)%Gs0!H%f4@b-R`eDSqlJMcAJwuF-{TsbzX!7X>G zbh+Vs-Ur;^Y?~{|#bZN~%VP4Cs@WVDpO@QXU$iUH7SXC~fqu`Um5!_HGz80K0hDmT zDtU$dX%2N_cDOFo6~r~vg|jucEq`6hsMYlz*nqBASmtWixy+lk0-j&b-$1%bnB0j^c$#`K&zGKgpb!1oozx>o=XO(wZIQr$kbd6rMp$(F$$tjH~d$pH;M zxcUr+PWk9#d?I@eV|w(lY5jG?{+zFFZnT?zcXM_3wEEGV)y>`h==kB`>ilWdW6!ML z{qgGNv;1BA_)k}N4%+3MzpTK=pK1#a03&%Uy3Uu+c#4Itxy@%U8*m|$vN{nrdD z;Y=E}Vyr-1QHQQ@7ubVFgg?Bt97w$P@C7`ya4|-Z3@5P3fQpOBKwIPM&hPZ~X`v-} zo|jP``Z|l4?%veCnEjZsqFKS6+puoI^NnvLRGl5~Qy}JEM#5(=hIz62vh!N#G4-*j z{A6d{@l!hMPAA>jrJr<%nlsShyXwWyxf^;`Vwj)&oI9yR=~X|Aj?SzuwY{xTbawa? z>1T;=eyq>88-2h2KzfCubM#qFnpor*bvr``jD*1fV=(k8DmHz5@a?y}#?n1?j2)Nv z>+)Hx*3VihBn3S{D-K6zl~P)YY4qD0P`J^b;?rn}=+f&@?M!H({LmWrq&4nI3xYV` zE?g(H*#1^Z7B0E+w5sloMOo0T@1XM9(e`*nfTrt2K0VpaYQ-ky1N6#kr_2uJ|8Mo7 zsmI#aI$a&RXEo!ByQ6)-zs9(+zo?w+YV{~DDDIJ)Zl?2bwMct zcY307`LqjJP(!TMXkAjBc*%s9^{TLtI55tNcK+oosYav_B?XpKMKq@O*f@BKvsNq0 zvC)t&B6UNV>oCDOYu&NCjx2Gs3X_erhF#M#GAT5M-5QJL!2ydOZnrzv6xnTqm%rk= z8*V&yVzqtEaxXg|i-T|#r|KZ%EwlRg83O;{Rlonv`|f`8hpu0IW&Os>icaI=Ib;Vlst@XQ?q4@pO}CC-+wYKPZd?rqdj06N^`F-a z_TTVQel#I7e^@nC9HaZ>#{^HZfcB$tdD!Ow)aSqNkKcjxe*aC?g)i`zxOo8Rdk(r_ zY0u!Z<#Zhp)r|0GD&c(**}u2OA*2)7UUyq9?r*rfM(O>$J-=s ziVi8cq$K!vOthb7Y6pccD04DhVAB6_OJcP{WzXNbn8-1im;*Nk+mM9mTewsv>swAy zHRa5NZGAhwze(%=haT+UL_7cPPt@bB91TD0h`--{;!=Tbp32p*ZVr`Jx6pX39eTVQ zsO`ax1P~h*s{abDks=_!rrs%FkoZbCOW+FH5*<|~fXpU?K8>%h!zDiABdPIaMlCD- zPyVCuRn80^CXT%IKLBH|>VUBcrug1^K`8EPGDfXrj9SSUwW_J6tsJVUrt5X8;3?%( z*kP}PF?TE3hgb9+O>A1ZW9>(PS@(w%pa^-$Ahc6#ljF6(ivw$?NYL?3n_EfGH8a?S z`;^!a)qspHT48plG$vk_x1(~vh3trhypH01O$VynXk44=F%C+jKfFJ^qs|734Vao)2a(EMGqJA}TLTy`;$gZ;;Wc66}hsoYgP$ z`lWpNYWAY}cemRUoaK}G2X;=gT;OQIN(o?01;Vt#+5Xys6;Z;7FF3MOt1UlK#Y^CW zn43?M{aMw~NzAY5=|TV*VX9px;mM8f7LQ4<(P^;vN7HEMf6<(VCYVL!5KfZ6ze=$1 zIi6xt?*xz7?cLTNYaR z;o+x`Xdrq4w6`=C8(MZ>e-7 zIC2VZv<9=!M|Xozjc{8sw*3t}h)4`>4OWE)hLYE4Al0Qp1CbC3I&dwdC2W|a3`S&%(kX@! zCrH6@bo`eVRHDKYEt|h71*rEL(6UZ7U^q}!(bkbBt-%d?P_rvq^H(|F%mk}z1}EMf zGlU*{#zduht4J3NN;7|S+q~I560jHsz*;85icBy)sQ&c_*?Z|vHV?J!TMDjmWXkK- zpqyqkPr7J`C50NLH?1qDQ3(bxnx0G9)iwfNbFX;n1dc;l#K+?}%n?nyb0aHEW*Na^ zmf4M(lik+_7C(AI_iqkZYu3D|Pvao%z~p$<1rj@?>{ZdksvdX5@pLHME{W0?B$e2L zM_1}UkG3}QV1?^2y7_cUn_yuppH2%suPMnYea_z`WfpTyKHH`)vldH~GOOeQRhaf9 zgK64z>k>^r@-a{)wiPalY;a#|*etPMg#ZpniIrxUU4}A=2FoNd1EW)TH=%AoJtQi< zd1DzaTUM-SgbA{Z1V@*$p`BX_%c7GT+o9EZP#M<)KvzttQfuKNRd$`yG}hns&irX~F0X0q%vwcHv@&=1$Dx09rS~uuBR%Bv0R*GfE%4p)`IyFAauU!44b6K7kVcsF|Be$lj^pR<}u-FB;Z7d>2sf#P*W@z>$ zoDV=UyOehF->KM}#Gke^Ddps_p$WXuf$dXzfi@g*(W-G(%=qxkz_ATPfl%CEPI}p) z+B<9_5OcR{^@^rgoT^*oY~_|jt243Zf}~-D_#GR|a6mWH$K+S(+8T!xt(B}kqeCYi zdYXxNnt6ZJNw{C>q?Rq}#9eVrBkh!U`BK^`QN^jk)cWBvE>i#z4Qqd@Ro)J3@VH~Ju%I**w;yZmNJ%78uNEI$q)A%-pU}qp-59oQ$!r)_g7nT zAU-LgMMnn*707Dwn;=>&FFa7y5+Al)*P%juQiWQXf_=*f?-~p{6*}3n;PM@9g{<=@)efQhn+BvV1iC? zv7mrK<7%sg;xryQUEoKF7WwzLdK9Et1jKTN_Ra#GlArt#=ni=yV$$^Y=5x){E>ZOEbZ|HH-b`6>1U zOi(xuXt4lY>G9)>!9|-EMM0j5eou>GcqhyXc`WQ}UB5!&rGBe@DlWMqe+0!r$4oor zDYwD34@m}T-ovNNkx-|^C|C?dA}uST+GH}7KTt6wSbWlf?63nIauR{tamtYqb=T0R2Ty;#Hjh{a1+vmq0%T=( zu;~Tt+_}acLt1tsgw1$8w9A8JfU(^+)*l5osw`gnK(aO&JZU3W*=n4P)rjTGP6M>B z5R7D@S6c%Zi>7sT8mCe_D$X<;LXkW?v8E7-yq>=8U%Q&)+NxP0QK!AjU~jWYQZj{U zah+;kp+6v<9O)q_ITM+UtPwIxH>SOWLp3vqGaHwYqw_me{b5fnqPMo$R%Y)6i}Ld` z=be;o%kAV422}1EI<0Akv?+nm#4*=wzbO*uQEM9@Xte=C*SO`+t2xpEiQlp{|2>@Q zPv-QYb;NGcaVGiS3`=FFPYGs;S*K|#1z;8G@0IKd4(?2Uzv%4jMd_J)Fp2Jwt@9&` zD7Z368A8=#tSPQ?|AnH-sHiYD{K0jTA3GfrjT@K zl}to&5w4X?q*ghFYQ>B7`@UtBQa*#+LRAf1w{e&hmUfX*RS*(6v-QQcigB@a6ASDZ z8(zsC@T{OhdU^V-%c<|AGL(vEpV|6)o1=&CZy)aW%9HJjcB1v2k66+$JhG&YJhCqp$1RC|BQ5MTSl}_2Tlx#=~+A*r1eh!(B$qqk8O{{@4Op zGABESZBE~4m*jX%z4(aU(!4I@jfZ*TeroFXl*5xz!p(YL;a5gvvurKtLzv`Sz(vOS>RdEU&J1+wa{i%zY%Ix4V{@HkKpYlPM_B&!|q7`g+a`TRVe~ttg z03huU09e}3*V|WG3VlOX1 z?TgS+Mk|ze%0FikN*2*`S$Ti!h2>*V-tLR-rugAyo_9)M(X)$GIDStfyJ*7qvhq>- zc%Sv`e!IGpRKP4c2}wS3%6zZPeH>ju6wYCTV+z$3CBmwY$b68?04xYj3on+JxJ*ms z$dU5I?iy%bWS|0CqtF0ZQ{CI-+E015%gTlu%%8 z74y$;x}yZcR%B|iW7$0vseS==Eo90;6th(g19Zt40KAK{+@CLE%}6;h#?_%2Jz)yv=56erIGT;iuBLp)&u_9z z?E z-FaAd^v7yA@%!A+*2D1*8fh)Q^RS(NtcsOY>baA?QMpcU;yes zw9>S7|7tgDdMOz`|Nib|)(rc>QTA&`xWIHbl{b!;kgG+)Wv7`T-nm>c2t=RmP;)`# z%az`^9p&B36J5NEiSmUx1RY<$&G4l z_ znA-t;VKsTqjZcX4JHz)gyR!W2m8-`#LjayYF-zM}!6{V3$F;C%v8^qwk4eMT+4KrU znDJqv5x;v7WAc`^^OL8Qqf5a9UcxMazUl?{4cH5#E5ct8_Q}PlUPue$Bb6@zft5I; z1_+JVEBmWg(hA{~YK4rvvfo}gSiO>#3a?a4W#pBE_DZXI#RYp?5Uw|gBppbLs5Q9% zqbD_)`W<%yAS;`DMMf9pO#NQqGD?_=DmS%Sse-9&yHk$hjYg0Vo1&L1RtFV6>Pk||^6stAySci% z`ptb&8iCUKze3UHuf%WRztV?KqL*vXFVB9qZR)+|bJCwf8p{8xxxhqDwg>kOa}mqd z9JB{2$=5i4dWdet6)_UvMpb?$-saUTzmJkdiFSwi{@7=Hbu>N{3uHtw6$Il$!K(RC zM<0qs!t+U)!?YUzjB#r|BZWcpi4`;UncLH6V$BRz+xgoT)3SM@uNb#(d?nV<*jHk| zL$a6Tqt{oW-rEy>#frE!zM^VQ=7nqU6yfGXnoHDai?2kTwkP_El~!wfB@Qzin+s>y zI|W3=wD<})V^9seh+rW%BR#zp>O{pXt9oh9TBBmx5YaUl@pPOG7OXYurHwpYvDWF* z3nm+L<0t`*E-^R8rM-b6b*H0RvOO7xat%FMvDWF*>lfRT`Gh`UttrIl#fe*D!cm+! z^%?a=o}AtYXBzdICY$P(-!_}-pJyf~XzXu9z-yh+YYgeyYjb!#H>J<0#*prhp0B-5 zrW@w}({vK2m+YXn#=AcD5MIEO59^?b_Timi0rJ>S>bJPkKG5O?HwmZo*x@Rz-TvIq zp9QxHLb^tM9u%7yeEDB?5DxkavN{qntZo%q2}duK6J#d&UlnUo0B=8afX-~~Do?b= z3Ztc%SlJ$Y?Ko*9`THR>@7ArR;_NAg)%`dQxT|ow#{BslqWLs3%66xcM7brO7 z<99w-X7#6n5jF!nv0Mr=Z@1e~;FC*(0V2_J&i`iy+u3=eEm2yd5%(Ij1}CmnCAqg$ z`>;p9LcI;)f-F7Yrx}&(mQIoH6#Z)D4_B%OSt@B48QRy3{22Z|AFiwiHmV<9gkftW z#$WRw9NLD)2707G2xImqXX|J$dYZd2Zswg0e*KSTm735?XL;5km!21( zmfAJvo)wF=tr5uU2)0>^g^Yy2@}#xGPqcVvw&%yG!N=IBCeuWK)}@t+&N z*fDY2L(n3&FPEeKLC>yhSK+w5ivlJs7v zaU$Q+yW3HuR##`>$QDZYpO;PO$joUY!#n;?jPQ?%T{Sy|u%UG5$S9p~f_`nd4D=n! zxa7ar?r$tQW5@3no89Vx(f;+T*bF2_8){tyO^B(ne?p%mc+;~y9BR)k!sIXDWz+5Q zFYZZ7ogKR2>yRV^D$v=Q-5h36FTWY?5$L!PB`mhmqYaHa3lH0tNNNhDYJLn~fqAxA9SU6VpVp4wahPckX*D_(D8wg5Yaxu|B zca_W^C_dER3ajX6R*7qA(28g%cw4IRWk+=gU!mWb>@a-k1?5aY*nu-IiL3m@4{c7T zzw$gWpNbHM;pIwRS6B-rFI5Cq=SfIx4i&GP-=C-BFz6Nm4P+(}gX?*{{4WXOI4rzd zz~zdaeK8cf310+e#$r2Sy;5$xQoC|XJNZMNgR{BxGbuou5UJJdFc0)GJm)kFv4H~> zmN-6mD|@1`EBWhf{B?`|k^olvE6;ZQ0dDh`9>C7w2|2XiM&Qx@c)h*N&~8t6BnI@z zI~kF=TkqspckvACwx1EfQP<0$8?Mb-+e(IgCSA&=%lB=nHW#z$8x^vF|3tmmve z@Iu^)yjN7Ou_v*5UVr$w`2%|xFh&nW>Y%vNJ6I)XzSSWej}WrdN6I$i%LriFgY>Wz z^VZGmFdB-gX-a{<(!Sk2NmRx{o$Th!X1FgeZlMyQ~M|!IIse56%!;@W&>GC!_oyl59tKdVp(vTBa z0Dd2S{Z6q4!|Xc~&fldXW1^elW&Mqmlwn;$<967IPD_fTPGEo;$QOkgFYz2}uLmkn z?hgv7*0G;)g6nK>>@8L&FMoG+&`BttNoms<@92QhB<55@RN9hN0;6SQUCzP!Zw=P& z$DnlbFSXM#D6HnHwnHq1LlgSEOvPpO0X>uAWSi4LDTDhSy;~b%H?>=39GFt;czR>S z<~h=D06;(6xGAkH@!I_*`_RTd+Meck6IF5uOG{NglQ{jkEslYfT1de6+}2al-`TmX zr>4I<=eBki8wa~M`6B<$T%Y8Fno;`UD+VEm$Kh!WuWU8NahUZxd13sV*2J z{EIl^s8I4@GHLmKPgzETKjknaJEJ@feW{A4IA`(`VvM$p+f738TE3LHEtuTT|G}dGSDtrKAY8;RvDUGrAP^e%fb6p`>Mt3*mM;S7UAv!^XX--q zbY`m)7xoPnn4enP$zO4L8AsCk!I1pqhtGEMm!Dq7v9tWtVeRojAsl&h8Q2jSXMjAL-;V+TW{QnOyl^3P`F9WB8`>l>Kp#>X2sy1Mb9#*LnCe6n$4 zN;m$gabsFH?rz+e(TxxLjbLVeTrLXRo-)qD6|MuKYe4f!E)>CeoLUTZYtRb%k6`2E z;TJ(GF8v`0KbqHQB@X5FQ)&6hPu4YB+3o5BKmCYkrMEz_xgRa9_z}EDD}@iYIs&+= z>TSa4cH)C`SXSaSw`6@vB|Oj8U{geh!yU`QA+)(%wxCB>#pae1D3;TbMy zr2;m#9PW~&FOQxLThkxNOt!nZOzi6e4fcgmREmu?+1JM&MA)eiY(EV_FSAyPO|ZNh zvzJOg-&B*{1j$!3?#GdTPqWDyAfMI%WH7KzK&@3CbwU)&NdJx+YW24Y^NTfjoq07_ zsB)LJVKC2<>=?2*6%$`x!U{gX$w`JQ(*ukx=`A|DFp!oVtq=#7v@YpT%n@;9NWM$8 zxM51dk0gq?L~8-HA0&JXl@y`kPQuz*C=X$U{XHYd>G9T>aCyxaD0VCC>~WawtEA=8;@ew>FNiOoue9@m#kMazE2BPuKgK}@^z??*_Tz3bnH_YX)YeUH0!FAWS z)1QC+-kd*0;bw*z?s!kt?jda}%iZAwkXy2PJ0f07rfof=LGT7SEm?m7@`N=`t0oe6 zC|9a}t@2ZTau4CZs+)ui?_`T~lKNeWBzlK+ClhGSzj};1sCA{V!-aWV%-*ap5#a8~Dj4J5L_1yjzTS}}FsDkqmZxJqqbAyC#U)0~G zx|FIt2KK{akNZrin;G}F*nL~yB=!y=&nZtIP3NMkxSn;NDB$FtB6}X|)G6QBNHCNM zNN_u{LV|dTd9^`8xU>@t&U_qP2t|gAPrPB5^OiFmLOXC~Er~T##t*lMU>;bhm%PI| zVPG1@&PsqCPLgrZQyR}t7*0CnT}}ZC0$`c`gn#$+w6+72BfV?=+Ar&)hxEy3*(WKe z6lCzMk&l_TLhStR9-^W3+?o*1<`y5cZ{E`*AsF1RT=P;z)CN-a**l;UjqWr#nMld7 zsJF&RNkmbTk`YqT9U~Yzl*HrfW&N(gArN3j288bj{W;Pm$%}0 zn_pO%uYI8&v)f$mGeAI_W_Rs#Fq{^0L~o^Dr0>}WVnL-2e$qNH9q%X8+oL+3cQS!y z881YH$>Tbnsdl$;0CL5E-JAQKa(Rp&c?F^s&=$Jcf| zr%y6rxzE2n_nadbg>qM&d1ZfT11bNFe>zB_tSpW!>zI=mio6SG2)Z#ROcOKI)&gxL z>B7S)EHPhxk@5o0n(pin!qIb;686)E9_(to65ncmS4S8M#upwBPps>}S7(FiTT4$&k{T7v; zkY+G}(J$$~G5Vx6B(R6MZ0lk%?IcMo9_Ebq8~#;neJ=b1JH|mM>F9G8cwJ{q#`DkF zwD7@fFMlo}#)xs9#Q$II{Y3o#H37c4a2v$`Y{!>;0nbifJ9Xk;kH9$5(x=u-{U=aq z6ytH3w^)xp$bYWBGsH+Hs5SG0FI=C6%2Oc#3Y;H&?S9qgqL zf=qT168z``HgsZ5z5Lc`uF}x>n50i3Npjvra#(C}S>*q9TuWOuyAEED{}}bvY}4KP zgXmqkcrkxW$u3~8-(3VGxGjHD&0*z~ZkNxxh+jmlD+E?#C%SBrago0+BL`p_Q&mSN z7F+UP>*)anF3duZW@HXt*PN5#%ZH3vc|Ow?*bIqfRnB57tH9K~J_z0joxpH157 zE8ZX4=?4QwyK8=Lrb1njJ1bXj?>wi!4G65B=v-Mo`fOyd#>_SGAc}B5TYzblz!n%# z1R5#>QXMcPND2wT?h>2WKXLGf}AFMA#*cn7>ReQ zY(Vk8~zc=vnR=C<{_*S*J^beNvh zJr1zl8y={o^1kVVBOG?=wgk{XtkZz}OQ6@zw`=kP-3QTrT%WH$S*nKUv~M=HPvA&PMfPt|B>yUzXl_l}3UL{uxqw1QvX=~%dq$oBu5LF+&#g#Cz@kclDY z^HKj~FrSac*G?byzceHd>~JLF@eD<##C-^Cn3l`BuTYe1q2~@cEhV!whNUF*9dw+I zxwR5vTM=RkKAN1?g`UyUP>YC3i{nn8fEI@f>N{f&+iOBGu3ix;WYsY3`dinQ*UW07 zjo&S{n#Ar^hFP&yqJafgn$bMjT#l8kcGB5JFZOrl@C7&)W3?sZ?VBIrm7eb z>mj^lR?LX|7uXZ-!e#*iFtL6L@Yu7ySQKI$3iYHLRj4Q3s6svIMiuHwH>yxix>1FC zxDhh#V?kEsv8lnI{K>Atx8J!1e>?{M$6|upY=RKrU&oV*3jOuakIWt>qlk=XC94)w znu>>N(iiVa{Se8!YqX!lG1g<{yoEic@G7@%_D9QR)25gEZ|q|YZKGGdWva=$%$xG9 z&rnf7*3RDyjR)RY@vi0qXc#6|LH zN!HvwjxbybwX89Geef;2NEilRcaH)&@TCtA3p@+D`-o(%i(%E#YWZXuuYi`nOK1U; ze-|Iw+T>IBbWpX#;qLB`pQ$O2Wn}1A=fNuhSMoA?BY7ErpFTul#@|=70mZRCKaqYX zc=CyAAj@dlS+TgbT}lVlGBh$yIFODjsty-{179Z^2?;q4ZDh3{xPW)C>8j>|1rLTh#Z&HYa6rX0<9e2Zp`+^yq3wB#bxCyumV)*}&TaH%TY(A#1}d7w%hpQoEn(N`9U;&r4(ySsV<&)2#d zPM106OyB91;;oLq8-=zT8)*9{8}Sg|KNftS(Ih+NPV5vrh4i0dN)5kM71FQ*0)U49 ztq^)b6;}j`EH^Z6gU{&~_)HEX`|7y>5EOd(Cj)bfgA~+~ICduagv)ejy2dm`uB)1^ zs+J`x{pWQ}_giVY|6CDoMOD>w9T)Xv`?yIo-C#-3`CE*Mc;G$kVgX3d5_2A39@ z7NN!BI0HI`;i8ivb+d-vI^wiLpt(8-;VJ;5LZ3-d|Ma>5^QL64e)`GK0g&;5o7Y)u z?=0ZZpZX=i0ll&bg`|^v9ib&9m~Cr>wYNbTOLayPzZJ@=YlO9zlwh_EszRD?=JHi32lfXX1C_#(6+37q^j49803{)gj3h;~bV;7*EE$ z3h>Ter?ehEJC61VlIyqbiRJ&8>a9eC!>;~|Kmp&M14!|WdgM2+i{PMVIu-k2?t386Ys!VhEa&L``pkdYiWlIbz8ArUXQI8a7j&0-b#54ViVk6S@c_ z$c;t7M0Evc`c}Rv1zUN`ygd0K#cSF{Zew_GQR3A|budjeFaz&&A5>k;7MN`Vmey_8 z4_5D5UCpoMN!(1Z_N5+gAA8rfoVN{1RR57~GGG3jp~r zOWK7mjDJZ_FXmrfEdON)eL|{1JPnzPtJ3)O%M26P>Z{Xx`-1m2TPzYTLOtMU)GyRs z2F#!Z$e_#)3NR#cG??%(q6JT=V8lSJ&ECX7znH$txvC^6eKEd>LodF#HQbHIpDWPY zUAKn8|CiFsh};#i@3ee>&*9OUl++!udPF@g=Ey7A!(Q29W>O80x>pP@j+6BV>k}-#K0Hy^DmRzkXiW4Q z)l3W)3FhBS)1@BI_VSzY(4MN47~IQ*YvuXJ+_FU>S({{y1sTdSgkt;6CF;SL8Ub}h ztkW0oAD`J7V_5zkX@jO$-(QU=v5SzbweK4ju9B%O5e=f>pC07?Xd;^Ui?4@oCD5R9 zd@H`OER{oqlG5RrOi!5>#NLcOC)qr#P-*`Ut1v6KEpMq$l}_^a+dkdfB}jFKz_%+r zxRuNTj}8=NF$<<4e~ro4fOgBf%BPr^Gy9!U_&#nz#dl&j@B&Sp?*+m+hN+DkzFdvvqM`AUk!N+@<;_zOaGv88OkxWDCA^q%FZ z!JXf~+iL@*{vP!HNOMw;WCcGMJwC0Gm7%fViH8QN!4{;T-6JAU!2RxOBN`rPeaT`u zfJkCcr*+RrNWZXezq$5hCOE&U-Oi?is^cF4Q9U$@iN__XhhoCyt0tn-e5b}?|L`#E zAC4D8!83@$Z>qcu0)&-s>5<`AABk5zP*~;Mg@}~#F}C%>MPy}OKPf))T_1&|g?~4O zu&cpGLKhI{0JF)Rm$H)4EM<$4g;bktq#T;eC-;!}tt_l3v3F!`#`nF(fWH?5Ce&9k zzChT2G~B-57{>Qw803vq!|)|Ljlb9;ow)WQx88ri-D==e)`Qq@I3v0EpF3kJ~H~6!6aoB=%FCy%(tiKw=zP>T0 z>*LqWF8D+EU|wz~Zk2mRkFjtt6dOFtXZVJnU`mY19WtEH&BCw1=^*;m^sPtsl)qYy zga_koGu0uRIYhm7?||dg_AlZCzr4Ikf3J2)HQib2{$m?2?l0lAV_x|1vT~tZD)+^6^KyUNx$+^YHoAwglpr!!+L>f}3*~0&%JlHL zt%b6~odxo1sF!Ws>ay{`VoAyDrG9oBp+C=#2+-b;rhDIFc|$ebA>@(@BXuhBCF06m z7l~{9n)jlZzaA78e{HCh^-AjYi_0HdgdiA6sy?SDIHZkm-fIs0;lEIQC`I_jbm@~omme9XOCmmm;mQU3ed#6T^x^WVBW&e% zA}=b!hOA5F5Ul3I#5zjN_&HCRmTznz*zcBt5Ew#+m*luW$)g1v~GL>~ULC zDvvS%KEqorcS}HBEQ2B%^h)zBsaO3Xc#mcTT=QAY`BH@nvO2UJ==r3j6 ztx^)f^6*ROw;}`4qzc9h=sWSRGCmW1~u)F7`Vy?M4=mX+lj=qEY}r zKvR{C>Ks?1gxd~*bW<6YCUDKUG3E>xc0k{)FCEGRn-U{SAvyn33@iWa9`hU|zhNR4 zTV*ShxZp-&D3X6LL#+wj;?PL(2ld5rZ~<~tg9>koNjE~}aH)zp(Nmg`uV2k^|F7sVWI99ZLU>M#708rlxRCM;GtV>3$#_INT(ZM2lxOJM8>$~GZRvOY zqog(}&+vESdnncT5?Q$<8Jbe<*nt#H*#2m<{1%W>(!4Xv@@qI+q)r5GZyUvJ;80xp zKLN|HZD9GeHBJ)Ao(h(49>?;{(IdKk=?bX?|S{ZzIEl+Sj`W<@Mf4N*jEAqnDZ{8j1LC@aJtC${XTg zw)~&+J`_*su6&IX_inw>zSUsVkLwnCV?A_6PAXR#za?#M4T7u|zGqk|*OPKck@Jf2 zqf0hbBN3JHY9J6I#QsFl&FrQ=it@Wjh-GZXY;1OjbhGkih(VrT-f9Q#tOm# zk>k}Uo_wcF0l4ym0xCwsnH z&ZGGiwVX%uKh!Rslf6johI6tPtKE1`_ENR^IoWkobUj{dI)?(7`eXaq6u{IUr*pm$zkelWKlG&}!8DgmkmkvfM$i=@vim*b>&&_syg(t64`_pm|*IO2T zgEKDKG|RAbIO~+fD;_T5kNb-#>AA>_Vrp=|3VCuCrv83df9L#BWteWTa-NHWzkd%} zz;HQF@>>^+#VF^wn7H*K+*;`%_ru5!DF;>+ty6MTu>sANWSPgS=P4Dt=&LxeDW)6< zH`WbmBEy|r9(aR)42h}oz*8y@EH4rJ(?;qYEB6n@Ok;hxpja)m*>orIjh1SC&J^A8 zTAv%9xYlPubV~8&%EPxI4(UR^=5MWz+hFzMETY2wSe`Jjvhu>XIJ3cT+_b@KShCYZ zb4kS+tCFQ2<>H;FG@Rd79YbTE5Q8Dop{E;VmLD-3FpC0k8mmn zUX$g_|CH6&8r+!fF8ZH#m$JsUc9%EO{9$()>oNb|-DRq`=I`i2$M|V46+k_5ruOX= zc*xTqb_#(dn45IjkPh+4-?lqdC8lD#*O%N-dNI*f{s+4ob%dD@VJsV2L6zi|kJolc zQF`sx?hZ_%Kjgog8P^WB-MxeV&M7y32tE5-}vcRjS(VID=}oqm``qfD%Q*0lE) zB#SjEgHwdrB90N0@sjd$`H82N+!6Me%-Tq|!lG>KelvCCn}o~Qtd1y@edk}11t7|f zYVjkK-2%G&5BmM{r$U58K+;gWt|(`}=MQg7l|{V_Z1=#^TFCnQTQBR+?4isO%&kTC z$e|;{+r@pp2n-68?6ZkdJaDv%2&XkbC+C}9IO9K$LV2U5%(cosvuQyr-y}}br0kH} z8=^El59K#*Ohro}=x`k~0%e3>ZlBs7%E^W(W~znuuBlX~o|hJ#HQKN*Ps0wrrPYt7 zD{(k;D0JW%T#}%35p%m6-X0!U$!3V3Y`IwJb!-IX@6~HhwkX$);j{g)A__Y4aX-2h zx76PuKDF5H9AJB`8U3PxTy` zGA<)qm7B)$!87xcnxVnfC@TC7ud;uq0RWy7doJ4f7bfQtM+SJD;D#l}PVg>}BRh#k0%WD%)3XpzM_Y)23;|qdnc}3jLwNy&U8% zqUu4Z_Qr*v&bLHgVT8;RqABE^NIB7wk)bTs?jeNp^d*cc{Z4=L3%1_cq0>;KC$S3- znQBR2c9H2NO6T*3wxt54&OjkeD+TJDI|_YPKY4M^R{pP>Qf1D>c1@a;onmn(mB*7c zG&NXV4i#PJVwj4auc@Nrb6Kk#KB~EVtrCe=4j&c0&^0P~RSsX*Gg8rMH%djPH5Hu} zmHc_SMkRl~+D&Jpn$x1q{kWEw80&OC=svwO2UySd%*=J8OB`+Veu?KA*Uq?jH=5`%tLdmxaoG`SNM} zE>&BbkMJx}Dqro3mUq~DSB1)bb*T8OZR+l;!yDSB%#$wGUfyYUsJEZnAFo#hem%3! zdi$1#A*nmK5j}kxJ>7}?hUNHUHT{9+?nj7h<`=@arlc4CH)JB^-R|F@zjGd_ywFRg zyl=Kz{8Piq`{wy#GsdDHD6%;z@0$@>T4Jlq{i#FCdL~510TDl2aZf>cpBLFq=!Uh* zaE-h0#PHc3oc*XTz+|PoPp_%G*NW-piHhl#F~#&WS4_9NVtTqOraNM?Y=jPLzyhVq z6Rm+Mw+F_pflBXW5hT5nb7A#W-nm2SuuGt&b(s*hQ%0iNk_4!y?RwKX zO^7EuvfA#r|994BcPv$Q$KP*C2Msjr4p$qej(g(CPEFvB*Ai5RU&%p+5tq!0&-ziLN}Ff3vM%mtg%1@;uXLR(>f^SFpziHvv{okr6r1ff=O=FKe&}1U`MJ?G%m8i7=)FpdTP(QUVDX92?w64H?>!2BnNlC!P z0m3#bhs4b^tr$aK=fkpK)- z4waP$H*-=Us)xPEd@G@{Dl}iQFj5TRZV8oMW`i- z&Jrci8xL4Ha7Zp#Pt^NP4+OGd?N=^uDSv;1tw>NI6PrN0MiQYp??%9~%`+?K*+p{t%UXz}{#H&hl^*Xr_X{O}p z=9=hL&Jv(BbBHJ85`pj#j0GuK?4uPeZZ7{jvJgsir^2BMZC*@U31_%Xp_=z@Dx;|O z#^$nUY5n;Yx~0;JNheD9F$XhGCrYqV&tT*Gw;Cn<_}BwpgSn!FD8Zb1aQDUA~Fyn<_0sYtK1o|ij+jzh$zE+?=dl)xQ67*gMc1_xgy0FUY@o5?- zngDt)5Su_BHDW8!^DZ;A(ynNRf3vTQ!mVVb;OhX`uIh~PZL7tah&3v(HUQ#vR9k~@ zpRm;$^-~)Uc=gi?V(0xxAm+74*MwNqBYk3sc@5G8v8X}XgqY~9n7;(>F#1r_ zcy2Iu7tbrpU0n8?WiKRznG%?di)}}Vmp1L?U*4KZo6h=jNlLX|M@^6_rEE$CRs2Hq z08UT%#-djKkq!Lq04BX-vwfc5qb#U>;REq|%5S>K<%~&F-J|@R3CiWCH zBwK@bym3K`Bo&ZsJQ5WjE2O8IkLi&oxlX*y;}DN}Xw@AZW>BQUj?AsOQX1Zc#HFJ= zVnX~!0x0+w0t!*g&_I?-8G6{+gL9#8ToFL#QX6+LDmI6L!JS#V6CFlz!3}bqr@DgS zAYbBa4$~pbUQTuUsvn~O-c-K2v8s8O7-;ws$oxpYH|4Svrhxy*NneT0<#e8M- z<89BH-ge3oC2#xIpL5wr91+?xq zij$7qRy(uIkul@1ck9=ANLCBFw1QEd#FX@S>5HvCqQiRNUZieA}4AO z5IIq+Bqg;6iI}K;9uX6@hlq%%pLGT|65DngYhz`xZtSa)&?rK|!$!UVpf3{12m##c z;2@B(CgW}7whjf)`x^(Ze$b0T>rvf1825iS-KU%8{Xa|hBOV!)ls72JkzC2!o^(C`X=kP&`&}ri}aDgowZ?(@sclV{cDwX9}*X@-) zW_ud%M&xplivk+sr8A8em#)Se;fi{^TH=g1q*cm-jxRRG>%#^tRi4w-L{}>ULMcy; zJSRAh@|GbfK)a2X)bLQ{LNCqL-#(Z#`O&E;3T#`@lEveLw)Yo5eZjAx*l>N#|#&SVk2?Bv*m9Afb2pzo~4!Hb#UNva^=TA z+!ljzz}dmiAlm*d@{;XcrFjDMnC@C7&-cBFGd)$wGlDPft*n#)o%yc#$(^1};3*82 z(Pgz1{91k(g(eO$JEp|{38h+fG4SWd(C6}sM3{y-q|#$JEf*vnY3c7^j68C{iY$Ni zu9OAFOKx9x%GNJ%s4RI1N=Q-NlGbx~#&2Cu@B$UD*_C23NRPCLTwn34&@85F&4NAV z_ySC`m^IB}&NPep&@9a4g3MVPj8?plQeKM5Lb@AC=2>1$fjc<<}`vqDlz9Yt9Msy?RDb2eF1lS%SHLgkV>fJtBP)!}jqb@MAZF-MmwC zEBKX^IOo>0rb^5VUU&N(wDcG4q)@a~hagF!X)Rr_S+HoyO7*Z4@o_2@Xh|5q_XWmR z4DCET9N3OXKaj2HWQnF7{C3&=;t^OXZRULugAnEHF_lz*p@bD7wivg zOu^(rh_?oxC7ox^%faz6`Z+*V-PWb7r^Z+qTw`8v8D;ADyhv$N^4ubz6^G*ZG<~up zTPOc)J4wY#4@&{ORN-ZCG9{)`=}CVA966A)m)IHC;*%6`Q?Q@5;QvZ1^Y5g%daode z%I}*_YbB{S8pfXV6-^Web@ic{vMBq+EV644?K}dK{KNPNagp=En6zh)oe? z@uY-b@J+ce-y1NWm=%0t4Q7QIF=h&hS#h7lBjwg;Pe7rTprAInbWi1-duVfSmK3f%5C=LhIx_ zER-3fv=ok+#1dwp%4~TC8=!0letmWIg=#Ws4^ho5!|(3!pM`^Hp(-DyuZy0_9VpqP zrI~ct=E2C%Y{4UqAm@xNwer7MObiJsOm&j#*Jf-Y;(qa(a~Xu&qm|XtcySiDV@eT_ z^#Zm{jY`_O4XS6{)R+96uUg16%ip`0wAo~N8?#_WNSJe5dleYgsf9lNP-c0N!Q3*F zmTr2r?1*!r2zei3*e)n5dX?0gk#Y6Iks-Yp8QK;VC&xV^KV;z$8Dfz)$nbzf-2CTz z+0-QacQP4H+92W^J|2IA$hvJROMhoMV0|{_-*%XbC#SG;7DKb7+rCenu8m8&&%e#|o@I-!i@<9JTdMOd-*oQUe zRta2PYCqesf~~Uxg2r`N$q&V86-tGaQ;H`fJ<;i8yRdjpDV{Z_brOHWbk;dKHST9< zk~lhr>3C}4n5=Urb+ub?H|YL$7?Iin@TpyKT?AcE2_xdTQ|ogD8M}nUIemFr`3Xka z9nxC{@A}w7+2H<@4=W*|eR!u>r}R3@eB2MElMpGj&iRjfh&qGYU$q&1eMqg79a(gO z#yg3|Wmk)@sstxHj*^CBu@&hS`LllmqCBC!(sXCzj-J)H>x`Y{csN&!tq-db8)m~o~7 zb&*uXOj10hlCd7t>kKOIB>gP;I$S@SMLyK}+1e`%QZV(@f#o{a9HIVJ{;AoYXuMJ+zweQLEya&&pVH_O_S zBv8`>i%MzBQ>~V#T1>H1SZ+ne#*sm5qq$J?ce1=Lw6q|hfSu6^-nxXFNe?oN0RQmA zVz;A5@R}>FL9iP=kl>5r8rUGIAv!=amPED#g_lz|gBxaMAg{xd3MZSSbJn0U4=M); zKhVyyqwR6tmN)Fzru!P;tp{ituoI_NMg@#mFFD3AK3%!LSB$_`G`}JXeeTg2vho~M zNflz5K{M!0Qg*ULYEaJ_q=r1V`O}Kj>Urm;JAWd>X+Od1zN<0oCduS*a51F$6)QS#3h5RKSFybszY5nXN4nJ z=R;goZ@EKW;l}m3<1q~lh_tp|X*)7pXz`+KuYtPDfckJZ>r668&T0S^?ZMWeTDd~h z${Q~ew7}+6yGL3t_g4V6uJ@VNwr&m3jpAviB`v7@k!@puHt%7dqCyv%!5~s4JJRVC z_+=^3(n%nf{UO^02LhR2vK*7!pqLJ@L({~|`B(rR7E4z+6D-^^(o^RU{gkq3>1$_S z9z8nbPY~4;qB`LGw$M#hKBz2(bh}*$WXF@!|P^u z!|P`1S?CSUDF*-e2up5MJxkb=N+upq5Cp{QHfvf-E16Nu86~W5|ie`=Kv=_Tz_{ZSw!ZgFmWq)Ttk7M_r;nFs3EVh ze}REmkdPiRkhPv82w1P@hRb*%$wxv;Yskk*>idWz19@nU3|zzJtDCe}wO-fm$oNtR z4Q+zjyQiU{J)YVtm+>j6ze| zdDM(199?XO*W$X$$}fTNN>zf&yDCf48eDy?{2dfyDnclCj`MZEdX`G{H6sQc?Bo)IQItsc{KS?yLgHq_ zO(h~ww6w-kQ%T|@kEec14VS~VetD0SA!3sE&12onj7J9UYBliO)Q6Olr0e9U5}tLf z(16;#rXMLUM!_@X#YjI=UW^=9%8Q|ZBklR@1Xg>HjlgQxsW+K7%6zsra;_wLQ+6PO zBdEZH&|CAbbZ0X6npZ*rJYr5&IcR4Yh1v~_Qtg7r22iRYg8cq&!zj=P`J@#0q}Gcd zV1FVaVup<9C9e3;w{`ytgeDnT_uzU-m?@=kpaWTrv;0|xynD}*LLm_FJ zbCLH>7{H!wL1yXxSs{%AUl=_aYg{CP|9$C zkvCINt(U)N!;ZuSF$^Q?whO79*GujT{x$6yQVaF8-Ly6lOv#1`?f**TBIJa;_FBi zro_`>j_TDV(N8`)a~)!bhAaM{FvMZq&2*QrIM3==MM?#$>^fE`Oo^LtWI@G#=@tt+ zuLCUk7Z=DZ20gskpT%u;&sW$6>i;E~uulfdkv@i0h|!s37Dhmtqin}7>h(=_y$sDsNrIrh?0_#ITIC&G9|dE zTT4x<@CUmEe>bQIt%wKmwSB{|`8Rb^hKl<%4cSr)^TAOD8Bcq8A!_|}QhA|DA+Hv6 zqRPRIR#~oVjCx~Y)D(SKgHfYRSK7CHq+DCtA}!YJ7F}CpjTWhG+Be#`Yv0O7;XcUN zuNIh{rxw-VfLc;u&R4sEY?PYO-z5zfQ8fSOiv-^$2=x68MlTnN6m_*?^dJF+T`m{7 zUgTmqBP-1HBA3gwUGEDQOm}_WzB=pVBv~gt3}26rvT>Cuo4Q^2pTy0jo7-*aB>UpY z{eFw|R!Ly{+0^*$yp9>>{KV5xT7wULngSHV2C+$Db{1VI&e%%EaZ8L3nmgFX-J(Yt z)T&h#tou`U0m}yKt|>!uUkt}1b0e=COJ|4U@$2UO^`W?&ST%})T=U}tx@_?8pExc5 z97k)Cp&vSAO5ca)ZO#V=oqyy$I={zuEsmJ{hc$i6Bb_TcnQNSZKJ_bp6RfL7Xm%qBv?TKKA)f|TQ2^j!w=$G}Ygu&UUfdEYn-uTtiu`&Lv zVrU2?t1b|ZwOMCkNzYZHk%b3_P$c8>stE*KVNbL@xci$Fb17OWfp0eIB6P$}>CXGD zz>CKT?er?EUNC_~^+^sFn3Cc!wT$Ny0gh1aw}#Gd-|?KHRqnfzI_-zcx#t|YV1P8# zv6S}D4k+^wzyHL=M-EH-?Z}2R7a@$TRi1m15J_<%Rv2Bkk@xXu#;!NOgVFcZ&zv@x z%CGHQ&{!f?lVNc0eWz(&RpGa4UfS@&n0@@XJS8b+qy7Tl(=L>%7@Yl#hSX~8I)-<% zoCL3i8W_C=4~l{f9ip4kX*M`)E71dFq32po&3cgqX6w&KeFa#I1_xo@O~e*(w-S$w z3JQ35q32fq&`hI_g3%7ZBp^e~5&LBI-9Lct3Sd}rdd6P=!AXpHZ!$d+aO9sVQh~SH zA|+iaB{9t<8HX{shKxi0s;VK}y#25#$W1(_+tsMTt;t_8WRz%s?BSmdwWoGb<#kaBy=78b*F zVG&7vcV|EH8Tk`#L81#^Y*2fae|0x%llSh%1?w8ttDd^~W80FEfxjfF`C&=q-{~bm z!H)_SC_PvJ}Pxs6j>Yzn3^gzcnfAbC~Avt zYC@htv1e^kAsAjLiO zgg2DYYSJFkgYc$Bc%crlInb$}YzX6U9T8sWH~fh3X!CDogvSUqD5ua46qG2`AJju= zL$-~Q$DBT=wGcyj!B_=uOpU$9(U()>jEFdNkcOS9?~+)Lv0Ry&B4*=nGJ4Kzb=i7( z*bE>pQO!%v0Z=WaLa+E}J=MRJ|5hW_Uq4l9TXZSaPuy{M1)F(RwA>}7lEsbB6P4*( z%uBh_FA&t1b>dn*F#1c{v)lVN!ix~9o$#f(lRUH>I72UgXH&mPHAme7AYs>34cFhurJUXzR{I(dxY6qO*Au;OYGGGNXlf z+B;D?PzcTItvD*gnp=$=JGpwht? zZhC6|MWk9K(2{S31$q!~Euu<7Pyc^zpJ+Y`%GUg?J>Z&+hmngl;Ob#y zxlI*5UO~rjcj-F$b;=HrHkU6?vk%H4?g>NUdH*~NZ7s|a1|yDmP>eaNx5b6l0U$s9 zu^npy@}LD_+VW*Luwx8Dc9B@86p)5GU|Uqn&XxQmsbDK0J5XdBIxT_;Ae@)kfnk9f z<6iMLjDfs}{OwgfwDDVCKn&l??8L!HDSV4r!1k?I+USGTBQhFfpwV~ji-0RW<`SU# zSV(~h@5S?>s_>sOnByt>h}bQCJn~OA+K?3xZN(&Q1JjWns0OeImLCB@OQ`ptPnvQ5LwUj(&&tc%t$VdL?Tmw#L(mea>o;=)v7IenxG zpMfeY)mYwrt4oA;UkvsPy!twlc-<dyPoh=Pq+`qUE0fN+9Q(=|O#qTJrh1#U3N^s~J zf14lCx^p z$q{Rhvs4!6i?Siw$A2ck?Iyb8esp%D) z>X=#Uo^2{sEm12OhN))tAL%8l7t3xsJP+sQq{r!H=-us+;ZskV)`=IGy{ z-efidF0gqssAb9!lLB*8Gn31_t%~*n7PnOnB*F#ow#6naUCat=`mF(tz4CV&{^$0D zBuyis^PEr(`ARqspt|BJkI6zTP4RYE*;Pj25{0c?-6YaijPjomQLhW!$(kYM35!GzgI7!{n^ zK1@MZY{%%g6%ag!t8~Ln+AuQX5;`xl-6^b0-YI>)40U17V`fXF=;(dlwO6OdDj|Td z+^esCb@`XQanI@l7`@Lz|F9?%-BNyJ(Bf<0kUvE7?`6kl$bbP=SAy1Dh~?Z1ZlAEb zl@f3~A_7z331q7La)aK6$30a%k=QZx*wud7GX)mC&j`bH&){QB{dJS2#z z$mCWlLGwFjWCx%{=wl)wbaI!3f^VX!TM@7l0Sk@1?K9e@8Ci+C6+FQiOHsbQNQ^~R zWmv=l1P7_gfQ!+9i_wg4jEX6j)CH^Ph`SclGJ0^2$fYhTkRwy9K%-PMjbZ^Bm0hTD zK|w?aj%#4B^lSy6m`BsWf!1tkTWvQjl;m?=0o62H!&kXjlyRp`cX_jz;1t3v{N;wv zCp)j9_vr+dac)KV|Ku$uYf0ulvz2sRWfQ!_W@y1fjvx%Y2VH263TAzJ z6)-o3Ayk_&MVP}Z2r<7*r)gkG_-OhWYqXQaU>_z({852O(?84V-YY!@bwWD`v;F`V zB~OB*7ANhAJ8@o1Df9u2*V2&NuFz=Wfc=5f;1c^|L7;h> zPSKQABG1+?2R$v|V2mbAEnI5n*eO5FIQ_ozXPZQG&Ny0ARBPw!N|D8k=aizPKP>v> z(;s^T@I`cR8S!aO1nP6=avYQ@MbmuIx{Nv)FDdRN1yQnkrg*Nx0a*Y_6zmc#S<3o`li!~aw7rM7BqZlC@O zwh^0PXp%0T4wt53k6uiSmyc}6I>F53Tj!@){!WeAs{Z?bSlwE!AO8GZIpBO?E8`~8 zK`{0|UG;hUqk7CuAARr=Zo2#Jx{3Um`ZBJ4@>Tlbr|pL@^ZMBB((_!>ds?_WGFdJ{ zS)-tBf*;H%@Bj=g27+vE*FHXw*)QXPm_=A5EQiA2yhj_vN?8Vvs1wtAS~yLpB83s= zXV#OYtgWBRZUkIBbKzwM#5VCHH}J-dYMb7agG*PYXI{SkI-cZs)mRfG&u73d$|LrSN`T&a^Ubz zjoc$3l68X|)WY);pBC|PO90c~Hof+|RxjJ+RhIY?>F#fuZhLJ_QLX5K-gp&)vc77y z*je}5YI-4k{Zb(D>tyH;UWgsN04)_|Q}25ree8?lGy!pxdWqRJs%cbi3trh9upaZE z)Q@x0MrFc_GX07N*9Ux!IP$pHqvCZf=WV><)u#~7ARpX;;ZmDXKlZ+73b2S%1zAqr ztOoX~iloyp0J2IMP^|NkG+CkG$7AmBBhpFmH`XScyx18?*xBoYQ7@I-qop6a2*yTi z2Q_C6@MkcVGUZyGAmJriCAj;Yy_aH7wu@kJQ?1(I;Uz>ked`T0cDS{^=jR?Kipbsq zxITCo!yv@yq2K&kk7lX$)2s2&8`#lQTs2I z3SYsC5EVW|yEy($qhSI~KCg@YGKz;nc~F@^wDxUQV9;l`U>|I3zLOZKv6?Y&$sXbk z#emEYK}c~g{VC%M$Otq5Lp0@S-~}NebBN)t&G81j%b?Qfp#4^L9CZy-@KxpO04X^n z`I*3Gl;3LiyxgW@QLA+Z3vfV#{|exSqw#tW2Jmhp{xs}s@jmUoH%xg%U@Ph3fNwuL z#`;5+P;V1EyXqk1S=62&Ad`oovZ8mohWkNfE;)KhyGT@trFz2>2nYE5*S*xTWYDr7 z9%6KZks~N!iu+E7;IJpvN)NYgB%)d_8;Qt4ENC;)@HU;0M5mT&iN7dQS0RL__{L}F z4x?Hyzo1&{!uM69T9RB1RGezb3w^L!?@}%AbkZYg#;DfQd?72Hg*djle;+9IUME@k zp9hoZa}p&WThooULnUZ5R$3^KyKSeBS=;1>7ur6xXJev5?44aje4sf&LCPbP`ez^M zm-qGT>zR$ME{w>ZgL)DOJh!q3c?e~|K%5>&g~iD!AolzsJUKCoJU`TeV!{Ta>Crs{>|`T7xz zZyherB&uT=TxI{fCwtG6ef5vLYPEjb{Tq66^gZFM_B)BH_Mfls^hG9i%aix>q=^_E+XN_W@rftHa*}+^_`+xEgeI|KBP|u7Dx++Eb+S9JkGwF zlpI>miVBOiqzEWS2k{Zh9{pH|Wq!yg5M1ol+d5iw zu>cu}!Ss$+b_PV}xCgsFmzVEp!dJPwksu)%+GaXIE1-@4ZRZNyxp~ax&vk&~3JlY> z#3x#yQ?1St#uy z(iVxvwoO_2GlQgugDm!?(9?Lx&Lp2eN=?`ccwD%E55D?cKL5EvOTV-N{1v-{mb#P* z5!c{P%DCW9pH+We<7K$&H7-c0xp*=m{>HcfnPr%Q1lOV49`lq1+%k`I(gH(UJ(#iRv zTDqft#VgOflI+6U#bN2XC8O7pnPT#da-e^f^Hu$4d9Ye2$-nuw-yih*CjM6lnVi4Z zYZWF#w#v6XD?tyUx=EdH(W@#o@TGc>0GSBu3e19FO)k@mhxxB*gl5lY$I8!pkoR`^ zX@A1e^7a+MU-?t})|%$Ws^(*yBIDajIR~j7j`1M|Kp5Y=R=%Z)Q9&%4#^INO!kUWP z@Kj)P2q3-Sqa&)Iev3UiaIYiAKoLMPJz5@9ZquXP2}#^c3fJnDuU<}gg94G(1$x99 zmg{Hh6qhlGaHNN?=Rb#Tp^5+)xxS3R**T=8f`23zUvS+X_|>a_+}0gYU!9<|cHLr1 z+@^J>nz4)Ozs(-KJKVT^wCEGJ>Cs6x z1Y+I^Jx_a@a?v@42r$O+`EHUw8yTW=3`8$|a2T*#bOf zy?Mx2pOR~Mj!)<*uG!|eD6LlFZ55+5F*DIK3Z;=r&arWb9d`LfMxih)&j0wb{&4wN z7fj@V!VBfjA&T6ouSsX~^KRhOsNqA|GHEPd| zF2?njX#DpA*9D7_%`1t4e$fhKR?%+s?tSy4B9C<9QTC2G@JKd&pQ<8n66~=+>_O6_ z1yBzw)<8dla$Qg|vl?Y}uRaF+OiO01Fb^K_K(st!G>I{o748NOMLgtA6WwKNPyDoz z?~o+`Q^0%b0S;Y*M)*=-hgQ)FUx^$5>nMrG3>s4{u)IDuEFUFjwV5sHFw3xeN0*K$ znkF;)&uXifEL<2J+07?A8Iw8HX0i%HRrx9E#m<|r-IX+tk>t)iL6mpRBX|CBB9)!a z+B^^2JV9#tLFc`8&trtNGf&XcUGsPxz#!$g*JWLnAKRDm+-GKK9Ea&`+@gQ(95Q#; zq`zwx-GDWNn%iQLoPy5H$dgb|bWLLwqZ9&tKFZioHOE!HcrCaoFSRZxVzMQXz>?{S z`sVROBaK*AY#=7qF|(pxTc8od)zpLXW)l|GcHwiqb{}0}8Mv!}edG-s7dRI{Tct9S z#JOY+bE;$TAc|spgR=~C{dk#IUa?o+{a{ZRCE`7v+vbcW?FZLBZ{*s~AX)2KNcrc7 zlBs^?d}b7^fv1GB`ZP%-h4QoMNnC#!gpFQrt4W%a(D|U2w#ba@25P=TVP4-g$|NX5?MdBy!+J;a-C1=wtmvJLcBjc9t;r?wTdh zfiTK4OQm-SqwMr7Rle0LcB&p$1@X_vA;WMv!j`a=D2@!M#r$r->){*<6>{+Qk&2ecjmfM|s3M_h7}^W(yExv;;~_~vZy=z<{XMi>15%XXl#hJDg0RqJMq$*dK$cbT!cJi*> zlI7_J5dzK5S4oIq=0t21nQy6&>_c)wX@gjiVm*;t&Wu$trc%a+m~zUcAkMG}U~hbh z_|AkoitNR>C8zFI;qJ47ZMlzdsd$DfoXT>Q-n~XXMp8RFyJBc)WJBj*5roA~^9Ywg z__<=T8pScrqChcc=14TL^Fi)Y<}4dHPy{L_cDz1Er3>LTA@-)_vNs}Tk|TF)VNy0A?j4V_nw{;xJ*aTC{|eXZLdwV5QAY=H`NbL^p( z=g)OcX(|XG@qDg4b)zVu3{^(16QY1IO13h48eNd`v!vo^ zuZAxOGLQ;6_se&(yJ`D7yXq#n5<(Lf zWxLF1Mh->`S!PsNr6`zrv>26s)q;46gMTkN>Ae0CAL-WPn{T6)Nk!~#g;7ZoDj}=` zpriwzk8%+Dd?jpAvD&&@hLdoFGn#fU;2#yuQdNG9 zmHA6`VEmr|KFLCS^J-)v_`~`7F8)x&4Ach`Dg;nE1WCO?v+fd69qz zgF9j5Wf=V0xm+S3dK>cSgL1%|>}$QYZL>5mu@8$I)&@3t^tiezm1-~{Kp{0eqBR=z z6ek!OJulxrG(AjbXzE>C>eAnx$VtrZ>>rV!hZVLGJWa{NAcXyQ*q~MLcG7b}uXx=v zaP!83+UC(KMWHzYpWZ>qJu7|p?$obY17xUbH0f3~LExA4Km^K&b5poM1Dt?~sx)kI zL9g$I27a$H6=7vy15C2xYvbw6Q3IP5w$-)7*tv&dkCa7;=gYp4oa#Ca#ZXeilbz8v zxsgpJYKk4>{cwAe=uc4wLM=+#1|{sIEWKKyh#qTjv#|;~W)q+T0HDT27%GxMJ)EuF z?G}nvmAVMqL=s^5((SpcDsK@Mh>*NUV#rCNsg`dZ6I6fms9{?kv^Y``i?-OF$B?Dw zk83J}5z&Kfu1Zx{eG4ICbBgxLdm&O1`=&W=2TbIYg9iq^??>36Rli^c>8#OioBdCa z(oAgtB*{lt*a_43Cu{YqzZeC)Lg8-;c=<62hqH@9e(sjhK|dVsMt-$tZUo%fH+AHf zC^&=q9vT>^A7O!0SemdiVXM*32KDhy%tieO7ZmC@<*EMvM}4_Xrcghjc^CBo8u{yu zPNg&SY-rpRu;T@?9FU`p9W&1Q9FR24=YZsS8H`YYCzoqP^4!*lc4~4sfh1SzGl3*m zx9s{ODn1B57=5gm-_pBlLq^EXvn^8<%%!T&if7R1$wsEM+vf$@vE(H1by-PA>fX6z z99h}My=(cZONP*CiAxOgpvkBpQ2Dp}6Q4`+DHww+DC2F6mK4tCjL!lt*(qfEJE`x{ z>C8@Xrx`NbUVphx6&v)X;a8ZO5m~7j)FiSon`wF2Bti)+-}J1+b-D$|tZU-piHN94 zcG8Tqxnk%dmMdn07vFQT9lFz0_Gy*;6LSXTRbI5xzH|d(MY=jnqd&o6Mwow$^){?vt z$91r#@c|sDc*b_L3K79*Hpi2C0*O``N!%aE#{_k!wWHvVbLkHvqY3H*Drg_3Fw3j5 zx7b&R%a7`c0OS$>DiDh<1xV~XL+%~Pf8_M6z#Tnn8lJYIoae+FbBw_b&T|^%Ipk=~ z09Grpqy%58*pdx@$+burE0ipP-n#xTVV_=+i5V5hVpZ>Yq%?hflso|c+CFY0rDaeV zV_d2I9k~qvYq&8y9gnXhK2Tr0y!}uT9@L2mSqn(O-N~`(ETCiBZZ{BcnfUHI4?oaL=e@Y(P^vlNLf}x;LMxdS)SXP{P?hS$JLl z+u)n&)hIp06LK#%1yC(bRE+ux^pJs#!Uug`5FgrtWh7sT+DULcq6AtC!iYL`WM{F< zR!;%_x>ufW)WD`rt0ROM@M)wf#ZIe1t7(}2)v6OhSw`qOio`3NS*nLB_FzvBH6CH2$@@{@jHOTnvHYz@y6!9n$WhsCCabU((v?Mjs;Q|S)e$Bkxmr=` zlQIVLTn3I(u(kJwSW+M4#?Pkpx~OFDBt9?@(JC_DWlC2AUrY)vA8JyCc%P0th51D9 zO&zwhw;)BSTpF<B%;O+b8!fd~MyvgU8mbmJBQ=QB7iV@mC zkivWNB+}ZW{m9HFmpTl>iwI}DLA*%1J7azKV|T&FEJE0S;0z4|y9x%|Te1Nz82gL7 zY7P0YuNMg!x#f~MDuvNh9fw(X*Tm){1t@_!3y-etRVYg5L^8~0ss}wcFxE}-x+&Ql%yH&9J?NWD2ZBN@!7NK21u1_n zbfroh6sw?t56Mlzu>dKDZ~T;I7$iatzL1qaQY94T7U$DFqSoqLUl26{QYC-%9)b(~ z^;*bM$ry*M1qwLKgDgTN1TpZ3xt)H2umoAV%CNvS=0>=7BMjLmlcF?Aiqa@4N~Q`) zQTn_fS4a*6gM@mh>n6&FZJ**#L=8J!KQAu@fsV{s(PlH?i;%fQFZ;*&jd_=#xX2j%b~}I}rT1qj+Pr%C zAQ$`qyT4x_M!hot)fTo||2zv@^@X{>vJ=n~RT}Jhww?el%mP#Ev05q3dN!N&IP7UX zn9sDHU?1JzuMZmIjIU>G|b|(V&n*9j?C3J6UJ$*w#_Qwe3aw8eB zjylsi!hO>HorUx1{%a_(I!khv(<~`0Cm24amc;iwpmSvQ zz@veK%VAgP99?T&X`Zvb6g;304EpoTcAypO;r0QJQ9t$z|Ip**x%!-J-PeIcVN7TO z_fa#Y;5}|oNsPR{H3jKe!C!flBwsdOyKhD}7UrAm4(2nGgwd(cU{UO-ynnF=*O)R< zOSjE{eT_nLjng{s6}fx^@@A>7vc4DF(5PZ^8W$u2yG6s6dEmX-B_DDU2r~1Thu6C8 z$WptRhf8d*H+Yk=DgSdgM`G*FAyLG{4TtwA>r?wwnZ&mF{3XOSHx>r6gj@*$!KUvF zqva{aba+Qa_W-|1EP*54@k9X&II>2hlPfhMo$Ru%jQ(^9X42msuHLn+NCg+1X#`$O1y8EE!q#=YZP~a`d|qHu z$FgF&20#qhELlrNbJFq&ZB|whu0~5n?OTuw%cWq~|NQp-(D|v3*|SE!E6lmDd5ggm z@qjZT^MwGma5*L5$i)Boa3mQ;RjM+0WXxo)%_-sBXOi5N0`v1M-66nShNGs$B_T^1gmXk|Ph18(rxWE*9!JmzNcZ_{#ThUgM!iyw@ z?+#pYDZJA-Wj=IklIn?`W$JWSqTda=W>YmNtUAPfmb62#x}?2T#v|f2(8IKkIm$S; zPY*Sb!1W#~Ewv)Ni#8Ht#9B0P_O^r0LyIb?%OK<>Ea^28CUoZE2PjbYY4q{k`hZG^ zik2^+4?xU}mK$-)hazsN;JrDp`HcOv(sk@hyFmK+T8sAPa82g*R#rHI z!#7V!f}4NmQEs#>)mIesYM-N>cH1~~$$ujI(-v8Y8DawxGls?v78ENY6oK7s{CB7N zw@orBc+bg>KnO?Up;~PfByAyt1&whW0qnt$dzO=OfL*o`(45j?OUFzBV(*i3JEWrt zWnf6Tep?SKC|g5M!UM#H>uC5f>{Jg=-3tClsTXrnTlb<+ zPMKsNaEdf*Ah@`#heBcO+eM)iydPxABexP+`Z8o`>0-#zrgoN~xUc~{DeAL}Vi<+L z2#R4;sY@|-Qzb>6M=n)Rj8EieaSfM;UhEVW(=BA%doy$y9m)jGc&Ik@i>i|XOFVO1N{qb zuo9H!Yc{CFYI;4~lcD^x9#vJmTBBSP#X9E1Ed;-D3)Uo^ohN~TQB$UrYz1$hD{^2&u${w?rbuDHQwyw(1>Y7jN zTufz}PeAb`07C9Ay;i^8<5(09%iDNbtb}l4%0`M1)!?f3>lS zw_@pPgP2cJDwSf76l&EK7|rR;h_m~0UB}6NL?bSuD>Z_^$287!dXIi0pU;<{;(WZG zRW5m(67*A919$JFoM8NQ<)8KwhfUU0p_&^=*jo>{gzAAsuf(M5q7ls4K+$g{l3;;N z-Gkb-BE6-QVIBGPJkRIl_&-Iv15Oh+W!~L>NZDXOA2C6QEy=3=6Jin0&dQY0$q0uP zW~H!c0A5BF>ew%~BLvSzg-si1LJ%QzdvD>Bj6el0cW>dF`ovVs5&XJEK)ZU;v_7;j zr3bEX_SjY~w_CZ~?%({av?eEeY-O~YK2Eds1bTV-+udDj?1YL%Z~Damq30(corUhn zwWo+viGV$5nuqMW_M2*m=ABqQz`3#cNbrN)l3~KAe1=ZX8*@pRz93B-fHpNIRrD)T zz&rsAUJ0al(Ll(veCkYl^~sDqrcjt z&`LKZS$0F$nY?^~KCAP9M!BSAZ@fJ0i*A2h7+yjlfc*>A=&46DOb+p}N4)6|I!pZk zj!V11OFXxC#M&L^*Pfx0gXylH9rje-&3s!8u%&#K=PL zI?!=j&Df_J>2#_5qfVA*2$lYPhn=MOiXy9T>4VFS^6U1a{!Y;Dq~G?+yACC$Dt`Fn zEt2w=0`X|A2Q`|%lo7?}a($i?jy?K-5)OL14Uof5g0SkeD8y4^UqapP;>EMY$Abn; z2Eb)j{+R+T^($0jNO>OgXB$$E|8Z!IFei|AZaluu7I2Tq^l%Yr$BBkBOq?6j#6O~7 zncn8E7OppvnVCx*M*@YIC;tOJiIFhUHTpwUah{_#b}MkV1l$o-pAVWpSa*-vZG~_9N>`;r4h87DLcji&tnJ@yFkcAN_Sgt)->)oV1vY?V?WAK*{^$Mx5o2&i} zSh;0UBNw5=Ft|OLrN%=gK1c)G36;wm%w$YBDDU5wer6jd_*0;(*Ngj9g(vN6lWvr@ zb;frl=ly&4CF$pzV@=Y|z=9O03QMZ=85~Tk>4-kdS=Qp@)grc|ccX61la;&u{djki ziM;rn`P~;KsYR2lka=RNat3$9IpzQCT-@hnr!wU@jq}sy;+#*89G6k(S5!=cg#a8r zzko`?`I({9&JmGSBm{!iZj!a@8~vMJ?>6JGwsJbqG#qP&HKT)%6e2xYufOq&$nfPS zii9nI7i)@0V5TJxq4O9!i%B#p2Glm??f`id?kZ9!UQtmlT^Ei9xH+Zcg2Abw*P}g7 z)7J_q!S&fJwCso+V4t0*#vw#RP6>U( zj>V)%qV9U>gnSz={%G12m9|%}+arjeYgz8XEp%BpoUcI$HA+;_C{aP<J zfOU^RvmEPQ?|uk#f#Bsb5ZNzcH_J#}(9ojp-$7c}*!y@bpTMG8`4$5sAv6JT<+d37s|>TNr-RnN@CyWkm0xW(IxItW6Em6Izyvb!!;xSVD1Ft^bgx!~1behjhWRC* z2kz9r^Y0}`|5|fC-N!d#e7}56Bfb+hnda^tr}Zq4Ml`YaP1HTN05a(4@{7#luz+M? z{2_eN|-VMB$LjQ3lPWFt+RcB0B z{F~nQ(3Ai)+&nAC5(0Jk#{4+H<%Nh#$|>o_5B>>H9{ehWxZ|Jfc60&xF!<;3Z)7i0 zNd2wTHZu=d87?|RoetHDo?hw(YfzMoS|pC0?Jd&qcOI{Z~DT+53OzDj@=O_W11X%;iH zuxe1{ANXl;m5$p=VYV}Udu^4 z*x8A<;;(Z73Ku#H1x6(P?sB=a!)T1#o?spn2%lX`xUIsQ$!w}3>w=P5`=L+AGl)mhVAFU=GxL;TbO9Oi@iVPMt#S_2fq3+^b4BfCLJ@{*AyC~Qnak=&K#gPjXfTo&-d2f zfPzhH9HKFU#*kmqv?~s*<3EBBBe<7wYdVdo{$9z|yF_DBm$e4$7{p5N^MhboUvjo{%aq6Zk=dRAPyW zW4T_LSjIPy$;%IPN~^G&5bWF}KssQ|XS_WKAfRB+omJZWD+F*?BpIQoG7*X4b`;6v z-s=NAqrcpv!{A<`synEjs<0TBSumb;OiC%x4v|xJghKkXrj{~jbR%0h0ns~&DXvRI zPH+!3rDevb2?=mpV~o@ks&ULtteytML!A(*5+xN;l&I@uIq5109GFagyy4+9GwfPc z&^D-Zc{eQ9F&6j5#n)?}N5RB4MXBcGxU}rj!Zg8_|DZ^;Iri)e(=MI2z__(%FKAr! zs3s#>=;XcfT~&u*kuiYhjYE~hGh>Po#Y@|s2v@H|xH`@sw@pZNkd?A`3PM;j7xEM_ z`FgZcB%o&@M=ejuQOOHw&yJHZy;8&tR1U+3S#iEe>J{fBvvhkd<`5ixV-M3;w;WU} z#<(e1r;%F4E_fQjA=(}~9j8hytMxQP(YI_IwpMfj9a6}ionVCW?onbToJfOa=gqSy z71L_ikjIEEi(d4}ew3l7k0exBGcIpU$)DCKQkEr7@^WVZQgYFCm-S`TUP6CMKl$Ye@s?QUaHgd_kVy~{G~ zheB_Ze=5kJAsrq^!nC1xUafW~V6kqGazOWF5twX8R#`?X%3E$Laam?eMm#x+9>1bE zx|L%U(O<`iu=FZh_O-c&kdGBxfWquf2h&vW{R9Cqk4Mw>o&^cGPm1MrTppaC9v`na z>wY2K&syCojmfZr-m1RADc2d=n(G8QF!II zQ~K%)dtMZBcUJCA^oZPYXGjzC~_pNcYQR8aVe&;c93*huZqHm-f_f-$10m-I$F}M5mc7Xe@A|~s!&sN3&U;}QfsP> zn%C4aEAPzHQG)b|VMFa$PsS5Ogp_0O9eGtR-GKni)Yy5iSEw$i2ul|Us|#}`K#=TA zRp1Upl<^(6f+dbEMahwBeTE*(B!^gV!YZ2a5(Jxy?WETrI@koclen9y5KUzHFO9uO*5+pf7V{tI*8K z9otl)J^SEf>+S=`=d6kwq5bW8%W*7psP$U?o2ITS&t;+1mn(ntP|}xSd0|O{i0c>r zhQ|E)q1)Z4g(!~aZy3fme%Q1xSrWZl>d-sM!{ln4u>=O8P17C#RjM)@)mzHn=_Mx6 zc%7H)om)J1eu0Xq9d&b8#-s=(->3K_C64JcgfTgRkLt7PIcOx5S3JNQpE1JpPPKF+ zDyROD6V7DwTgQ>7|Cuh>M4{q zn{nrW(8t0>?0N9;9xrnRsq9*etv@!(iVL=qW&z^HVw{R!o6yzReQON2>Wv*j0aGQf z6u?dFrZ|bq(M_*xBdE+A#$PIOP=j*D_&bn%62v>nCk~c8KTdk#a_z>`n1s;?6Qk^4 z`pi*B1)$s{eFaSFx(dv+M}JI$3P=CpHPU-VyF(|xoORA#X*rVBH0tc1IK4-@;hNol zH6n?AcMToW^}FljP&84+(|%sCwa>o)S6j+_xFUb?)_xm*aO;4L3&KznFfgVl?JeUC z6K10F6nt1dW+eo54KW@+_{0f8$OWDV1T9esDitaKCi^=O^a9MagrHT?7ye(80%Hk5 ziYAzo5ERKkN(|~I1np0WI*_N`=|D8)-mho#|LJs~u-VmF{m|{p)yCfGK(@T`fiw$( z;@nvdbY_t}w*m2VUXWrGVyX+I1BFe~1f6W0dsLvANPu<=8dIe=rRw7rIROQ6p-JH| zXiEF+cdEj|2h|g@owj|>wp97th~xH{o~}0_%k4Wwuh*Mrs|$}Tjdis#7Wmtv!XoDx zuBSA;yxLd3zL8X@V3N|Obgp=dW!TZG#~_RPx91W=T;xe1(#lZh5h1g5A8}mSUk#WnKw`rj=84=B86QouGE*LD9ocduMec~|bC8MW?5;9aGG2C%#D6dPFF1Rx``jR^Rn+b=yg ztwvUQ@l{_d)0U@hIxaWa&Gv)N>l}<*h(fw)de>w*Pzhyx!!zGV)8`u&u~x0q4vxhu zVQm}ncfI0GZyB%Apnb%8b;FBPZqPa_Z=(nCVz-RB>xJAP-C@N_u_^UzMBtWoV59~i zeB=4RN5|O=4BEOdwQFa&vwP6CFe^mZoc*)wZ>{!M2VSU6dV&6P{o%t}zC{&y(wLCC zFi3U;O-W-ZI9}oXa1F#_lE#*#7hJ0d@gVve|42z=B#Bwl7%g_MhP0~1?ll@Q8eXRn z8RnEmTJF9;BdvD-l}1|azE~p-c7L#CAYaZ*)!iawkF7>QqA8?6Nx~16w6(PcZKFRp zocC{Ae*zA}=^KYxfh>r_XjD3gt}Et2qe6l;s#3bfqX2{MI|fJ5XC;toyauq>cpV%^ zqd1I4aTtv+hO=n=!L3VdT#&`F-!H^J^|i{UydaD6{j^)0~iitLd=lyZa9QTWTjH%gZi^s{U^VV zgjRm7m#mH(En6Jfc6_PfY6DQtxQ^9NFL*>;dah?BK z6@{MteR8}J@3#MXZrV6i?H4yP!DqAD(Chi#K!Kt+kze!(pG#C+%+@zhTW8NYirr&< zIJ1n3MXc;v1TsHQJ2~DTi&(jyoA#S@A%3jseJLzreZ}YI@yo%bPBF5amAPxn6~fkV90s`8D16lS$oGq~gDn(OFz6|T;Ti^=eW z_x0AF*K)V8)i$pC$Tq-kp_LYACi%bEd$Gk%{WterV7V+&@2jVLA1?@87wX#^%j*2J zt*Qsq8oa2Zjzg><7rT4|xn2%*D9HWjC!T@o2IMNZ3?94MK(6)+3=lGZN%T&##&8N; zr%q%bVbtceLlK-#vJ>{=U9fA9Db^NvYd;n6#X%`@*;e4^J-Akr?S8&sx*&*Dkm#^w z6G(*eEt;OCE%j$B4OGO|2T;bZD1|7yJ2+x%$Iha^jPQMtOFwT^EtQ=Kge6_;G#9bNKZmMLcCgA zYR}D9M5`kgoV26$7e4T`Kz0ta=|Zua*pDm#ORA`dJr59kc+e?K=zX(1&sq*t(s*@y z^c!eyhkpujbSe_ylhQCmFxiJXK(ng)al+AuFPIZPv#;*mF&@}mc*{o^~Yxy zklF}HIaUYH=p=xC0UopM#s zbDKlirT}+CO6y2UYhv=&`VggJU;Uv^23tFj*6at@KA7{6r2T%r~4)(Bj)ZYys2QC;?NV_zG+aDgsIKucAe{O z6$#K#5z5LBB{f4Bx$KZTRo0HhKEotOSc7t4pW%;*7cW{&Yw;sP(x1%nr_46KO%GgGkt}8Zb)wDxqqZA9Cpe%L8saEIZ-|K|i zElh`fIQGOd>JFz>q-E1DcJYv6x-FSam(dJZq2VSEQJ@7h>ruQ+L-p7c(_hMbYWS-vl7sdRN)Vm7^E6NP6kHrGj z(DH&bDlbUmW!TA+yQAYso=t~J#$GqENwNQqeA9e*3JHNmkX=N|rKm&%MB#U~7$*h2 z4Udo2!C2M-6|w8xeqIU3ScPxBoo(c5rZRUY#XgGWXYmEmJhFre9R63HQpn0r>`QSY zE)RZ)T*B=7v%jTfC!nvG zR8-qZ-hfn8w#ucAmV8m3srq7o8!w6(`qPMJ$tmlZ&Iic=B z%jFE^$GvrhY3~}{m90eHCA+?$mTji?D&k0qse5;o_M!3MX|q)pxj8D16p3dhQnizj zQ0OUP%})f6Gn6Q55nMV>qEke5m*~rA#~W=XmM|Emd2|~E5@qRFva$}j44L$F@6ODz zaBk7EDiU2#f$zP06ZbU5V;k?SC=ru6km}LQDAwn?l?IM=fm{PziAES0ceyA<5V#KF zSFPd3kM-9!^TBPayR9;hcJ2Nsm3FRc?3JuC8fBHy^-V~m#tJKpt}6pYpO3(}^;vCO z_4yd$nZ_LyXpJYa!e~5&onPZ=G-};{Bi0>_FUAI_>kGn5Yn4H-#W1K!V5>&eKQ1|6 z+Phx0 zv6b<{I122(Z5Hho-Vw(-ocz0+=+({>XH_2ulY0yn6zO9B5bpAp1RZEa+~WZ+=j`u@ zczL<5r-+xA>I1Z?QRsk6iXOn7I^bpXo8AW%615Qo!$M~4f>IYh-fMTau_N_&U|t)xS1V`6 z#RgWYEJJqXeO8j|B^x8jeZ@=Z@SF#7cdEl)E$wn#Ojf1d-exC&Y14A{5VW3?mB{fU zOP?e|cit(mA?L8o6YM;}9)h2u^**KYYkB?q52HI! z-g#LvW)U{CFNp3w(-#OQlDtO*QvD+zT%vUU2b-PgLLEZH?5mCZ)kagVHgG_+WsLO| zJs@r}*c5=%$O1rj(Pcb3i|Z#bm#iv13@LU|nHT9?Ub>rg;?5t zM-iNhXQ8%+Vfr({p<7P&;oTUOcU_i@CiD|9-TOF5NnuZAT=pU^u@C-;e4z7`=e|Al zN?}XGg;nhfdAbxs7V6HTS_yDvfFz4dpzdaXvV4dhg$}OK5t{RJt$knl#~Vpy_v7X( z)6gL+U;0_NzhFI-^ci?CpXt{ABy$V&ADTU2W9I7u@KyFwIok86gdHi%zYHVVxVXQ8 zvC!00{8=dKsB=l#@HqvS0EFn!Z7-YTKQt+Cx*wB`K?S0dzCmPydSSpd5mFFm_EM2E znl@hB;M664@R#_(FD0Ckv8Y3eGHMTqu9)+a_UG0JM_aJGo6hPiF`%V)}uZdHgxqhw1TxOQ^FD z9_coR1NGNN)drRXUKR53$KN^$+XG85k+WHX8w?KAf1ZICo%_RTz=~w~;R`@~)+oVr zVH8lTM;HUNKin^rm~+1y1PuDa5D@q8n}5G+{)Q2u_WS;ml8@%X2{6_2Bs+=ES2h!{ z)i*1bO{M(FZyRrjCP1vqcYGTX*+yh$CX!&b0>}Ycb65x<2MKu^1504}sH-)PoQf7A z8>rVJuAwupR~v0+W-H#H##{NiLVohXExu+dXv^)5ChRrQXQs#ze1oQIEsLGX?oSnRx7j8Y)RdFA`*Fw-4#cCRPy+3g?MqYpAc08CW*Dz(t(7O!@ z*$RH1xQy8>*wOo{WU+`u<^II25SaoI8!JTG&Q%1~FaRu|zO99v&uDT!qZt4g%>clN z!oP{^EQP<)h}^%e5k>!qM%2D5HKOnz(}=>qqY;Jwq(&UQr!=DYpVmk$_>CF~XL@m~ zKRoJ=-#4z1oIEGjs+*kL>V>X9=(F?(g(|E3gFYwyP_bkByrA4~W*&gsisLUK^rzmJ zF2N6^RWDg(d<%wB*sdfC>+G>yzx^|p*1w0%IS=El$Cp)uidq^S@tjmotgQoLU%X!a zAaP`6`-&e_tyqj6sCzra2VjwEFSgJBr+v5)Y!+hi6SRXsj@83EljpDq$_c?NjIEe1 zJ046nz6XaxuNwT&cxCd?1HGHn*m`pABiT(XSD`}Wwb(DV6p*_L{}XtY&yI z`x?CJ)^dKUnOZdGNtOh+(aUY7KM4Oe4_#(+oP-{Tr50XNUiCRbB$QAdJWdblr{CLy z0D)pND$2@PXftr_ls#P9IVT=6iN6c=9oLmtYU=z6+WH`^a8r5K7+@r8bS;FYaa9B# zxhmAD(Al9JZmLo4p<4(UTMJ+s ziNGmn+e57v$Vp)rciAy!N2~?_K=X7vVq()7du5WKae-}T3RN9a5y8{HWQCs1F5~xiK0yVl#Y6)ArUKU^U*g*&&-h8y; z9Ej8Wu>UpB#<+@M2T%+Q^b^kGJg%^La&sKrO*)Fmp z&QS5<_U~;KXV7RJbNk7b)$#OX)e zro?{jviPlSe+oe@Cfck1D^DG6w}Xvz4#*dd+Q9{J|8+cw`f0A8B{aUMPHLd0F)KzB z#u*bTn=ggW2+zA}t$+j;hOd#t$z!ch?L{I#w?`hve2VJ67U5N@Ur+@FRngRoz_*}y z$kM5eOS1J+6;*QQtXSKZxHC_zHNQ<9^Bz52fhVdnxznw&Dd(+2*py7L+SL}jw%bdTsXa5r?2D-t|tNx;jZ)hPPtnORHv80Zu}J0Mod%}li(9qt)4nfl}>bxNPAx8h{ejFv_Gv>inc4%Y!RDG5U0<-OMA3yz>jUvx8v<(#; zLD{(P4-eHvd9U?OD(b)e1OLQ%IY89~mHp}-PvDIS8e~RUXX~PV^M@|sho7MiqEiAc z_Uo_w=33q7BCt{1ptyO>(wRd6fpA2KtYJE@pZex3aLSqCwzf}xQ_RGi=A4?PpUcsM zd%KV2DbH(5>Yp(0W%^w4@zG7kwVGQwtzln{Ei{T&N3?oy-#_9X+L8hUE^>+GHaUsb6g!KaoG#CG{br zVD}WMPnxYDHQR#nh{)YC)+5P2at&Q?K|LfB+@hf`;)EhY)=~fTOLzZMUnF5!AJT&x zTF>CW+vBw=yWUD7%YuFrnFz*}!h{o(iJTZJ)I&ztL=8TU8(*;22k z*b{+IQUB!6bB~{1}kSi8NqfSEC zH&LoIin#0gHYcUeM3;pY+gSVo~u*%JT9GBVa0 zQL7K-m{BXog(;T8I85yXWRUs8sH#Tho|BbbaV3mvHPP*gD_N7F)5|0TJFoA0H7QHe z0-DG+2ki!GV8l<@BO|UTD$-#g@*=KyALkKy%`AGr|1U)3*Y-{`5}CZwCTQgO;T|&? z<%yX@=+_n@^fNl5raL`7-Q4^sUTk{0is|Ie?vm~%AG8t`@c+v8i9V%&b830n19eDWn$&AKD}kl9^~o#K1F?XZ_o8FHj*Jcf_^z!pRAt%T;Tuk+hQ`Z#rNB#8+TaBEzw#U8?kluUlD?2F$qlLffd7Q zz5HO+hE}*(1A{1-30m}=?0-iI!#&%tAS3)b-zntX6)_RibLUV*YTcL*`TZovl13~! znu9xWGryF&HmX1W-W*apD&ItfnSz(lTd)d?;ebz}KPbj&I)WoXiIP061P$>qOgJik zv(iHv(Z}L1*fHkt$3z6iw0t=Ei$B01Bv9w9H=cj9*kD2+c1csH9M1GrApa&1$ro!8 z5Q29ekd<#ZG>Oa#oJP6@yG9@5;LLM9-~+F`^X>e^%Z_uevvv%9nxOGMFHI~;g8eXb zj~IzPWIh&3Dzc-`^|-ffsflb@7zI+PJtsmb8hJ3ibra;nPd#XfZBWeGTy(TB3U(PO z!*@C2CprS6UOgSLshOOxMN@PSC&DOZXu1eBq!Ew;1iL)Ui6hmAfTTDFkFdx{QTz`} zDaN9qiAJ6yLu0AQw&2!7DbIpiZ3fPZtOP%n(Y4K?IC^PgkAgHBk2Of+u@@r=*;6SO zytiJU0>qWSj;Wx0!vRz(f(v>#-Hg##`OMPMgPD6qhJn(C`us$sMQmkg=)l=Xjb-hZ z<=bfr9`Ek~52)tluUwi!9xOZ7Ns2-mpyv%u5un)Q3H3e1fyw}Cixc4uOs%JLFYkF{KJvXEeEz z(TuE&7V*GHs>7zfH~F6txzl2BtxqbSE#;ljQr;QS1Fq5iL_k=KED;bEH%kP>=~gZ^ z`70a!*`a(mPd}Kd;-)e;sGV3ET`bjSiKQB4bI|q65kK`=ZV`=gi)d68H;t;|rcqVg zbpI&;NuL)KL*sxj-%1QshRx8N);Ah-A2GwmtT?*i;wa?~PD^hZy3A?m|6Dui*DTUQ zB%b(TS9rZ})LQ*PqKAuVIdn~>8rDJ%T}wE;1}qtFU>HOWMYx7_WT!~st3>Tv6-P75 z>c3kK9l2v9B(>q*a;PM=m)HdO=c!n4e^U5t?p!jOrMV=DlGC3=!;vqmD;n;0iwIZr zV$>-Tw_}s#V-X~188=EL6!VaoVfsBOSZ5L#D)#sAt2HFBJV{_PcUPmZFF>Is1%-gx zkX#tZ0CWV^$1{`ITFCWe8}y>tnEuZ*4;QXaJBAdqK5Qjqd{r`Tbhly33}KcRi~KG@c znTT=tHRJGX>hs5IQ#_smlW5hQg*hEFR~)d}k>HUA)JJH&ncNKNd{(BvyuSw=3!b`K;Z*#;u~ zF`hw;|BP9-#{;;Cv5t{P?_NO4 zsdzBu5Lufi8wlb^Vs(JDi=KAtp$XSym=;s^wL7>LemXc%3{M3y)G)w_tu<{!Ue}J> znk23Jzb%?ctm5ahSi#JZ)GPiSq9)yNVqVuJ@=1QiPAy(n&#u-s@?M6Tt?fJpVk>%$ zV4V|SknI6S9aq>8gC1XFCTAZyJtH*rs7AnkTX+Cp)ped{WzKk#B8a#NP2&`W2lUpY z?%ZI1>Wj@aY7XcJidV67g_r2Fm3B1X?vemr*29ufFjSR2MB?>GH}PZB`t6D7WL(1K zCmbUc=0m=xO8fu5wa;?1!%Z<3EY==6-l_H#6trb)cT0Z z8&K-ewS+&$4?PMuei(7M#5H$*h$(~}+iBj{Q+ER-B6Bx1de;X>lgp-g(q#_Fp#yHVj+AB6K64tPt1bveLe111RJl0dWOfDLjdw>6Fg{S;R; zKUI{1vxuAk3|^m&O`JlpiB@l|lfaJ=GLjN2c!m6lkcT_3;QweUsW+bv$47|94s&O zi@cYu+9~mn71hhuiSf79&W^tao$Je;zv*4o+~4o~U3C7=JAV_=*xauLGgp1pStijN zjXCD;#$T}oq|E!5m%Z&}RqqFOtvv6nTz{vP>+iI3{hd~>zthU~cUrmrPAk{nY32Gm ztz3V{%158ZpgIqiy74sAemwc_45titu$7?kU9e(uKUGZb)%OxESbpu>6DklQlRVJH zHxp^QJF*0*{KtK>_x&Tj*EGUct$KE5(7#3K9S{v~GkVuGiZ}Gm`bz@?P`g|L zWzag0&3GbO2U!!<9Eu}|fIi2YDxn@qj2n}+=>CZQ4^4jZlA8{552}?2p6HlKBq?|% zhXiEhTbou(DQ-Im-jnYI(-Jrf@&c5`i76dp*~XMi=7iJ1j$m8VTE0JjvfYyuZ76@Z zNBzR97C9pqMIwYAVu`W3-@z)W{-7m-4D?nfsq#Pbn)H0MY8eL5p$!((Sri#B5X`5r zciv1^!%kTYV;NLVen6d(=Y+p^i)K%g9c)679SNJnTqW-7#Yu^CVEkSZo zkoftTK4JZ7!<1o8h@pg*1+&Hrf{;Pe2Ovp@CCfy|x;L17o~ma<6dd-GC;+!;qz*Y+ z$N3KvK&f?vt&K#>$njF@(hpcILm(AUi{$_gT24xuQKu9DsBz-DbT4rO;MVe!v|lK+ zO50=*vYNzF;&HPUZTgZ6{3~?>pN((e4W{B7Oe|HL1L2+=o`QdmXhb}nQ*--^N}QM@ z{LN3D^Dtj@e!?6~_s^eX%G`iZ6M=({jKfz)@}L1tne{>Hjl@xWtZG3bkjg5rcF)ws-y=MIx%|<*8GJ;@uqq>yN{t*W;9ib2h(_r zBhS`K;R19u0FA*JX-*~k&Wxr+c~CYecKoJwVEZ_Iq0q#@NZJx9bBt@Us#&fwU-Q+n zw{Oy~H_hCsYxY5A0PjD9f!LEMvz*1yk%)Upy2XZdBSEx=xXK)`BVTQfe5riYsD)3c zFU3)O)+OpYO55R_7r?U%oHOTZ=S+#KO6P5AA0v2XO*Y6-y)xjT6I8#W!cC(O?4fFP z#Y2w5R4uPmg%r%^wTob5+I;OMM23SzMGq<{YSf{E?rrRmfNv^+Z4!H35F}m5!l-AQ zBDB}O_bpT)k6PDeUQL{fQA{Q)f4f1@uqT+cJeC5A*+B^q3^rt@3R>+Z1KilQG<2@F z9crm=99?fKi~5q>7c{o~c$MgD>oC-s6)qO|ynxKop{I(*7o9{|Q#TeTxb;C{=IBcb zte!(9=ZELHiY&gVWC#z-b3Tg2bP;hRMOOIx2q6>ev`}j&m4)@rv{RDL08Z`XjI)bC z8{rY`j`JMuOH?=QmG?_%UwrFyv)n@(8xLHB4Rca z>6>r!_2oU3n7xcRZoF{_6=zvc!o!|IY$P0eS%P9B;NWRPS_E$bH|0&&OWxE+9hl;M zaik^T$9^wdH7IRp!%sIHn-l?TT75kUp=o47ACK1Wq_9}k@B6bsJ=fv9eCGe z#Z2j~2qlo1;5~B8DZwQiT3o%(9wa^cFXu0^Z1jX1S2|PJ@!iKLGL5<)O-P<)=K!S6G`7 zUtC&ZRFVjcR)|3VL_bl8WO%4_`HOv#$BSd+;xX;kc^AaLF6J}vZZ;z;5Xv zW1WDlz(c4iBZh5DeqS0o2woIYpGX0r0lytW;F z?#ywzJ?LT*fNTCOU=K|){mLE`p$pj3*9F)b#esI~?+)0yevyDJG{?T9I-~<2Mu*0g z;TUr3+02p8NsqSjL+jHh-as?d0@i&mzOKZ&*(=8bf12T>p4xIG$A(ZEfWkkl5*W)> z1I<_f#6TA_rWnUS_-C}F9z&yPWquBbjXo;V$s9p)FS~J~DGP3K;xYoRifzTHscLP{ zR8-NK`|AE3<`ZYs( zsq+v)=n;{%s4a63{B7aatij;v=lk<5P*1H+Tz~N^k2r6W63~%X5!oNpSCTm-Ntlu_ z{e4rW-Ytc(*&NA!*kbIrfku_P>7*ZK=zvo>*JD=;A#10tQuf zs_LDxGKAxqx@g8?LY?$l-@Wp2{A0eO$TT9v&W-x#EwM`Ghf~D4A{Gy?%A9ZT_sUh7 zI$&42zIs)rF4*?>=qhQk{`cBd*;@L0{i;kIvhALYt1@D5jR;LCUe4z1pw)4-Ar5Zs zh9vX*C7qPt=%`PnB`a=8f7nK}(+$R;fif2X7(*Zpkq-SCk@Rw)D~gIBuSNMR>WuMOMzjAg8lPn}`wwGMf9CPo*9mK%G@nJb;3%oBXLN}weT`{v zwywYLhEezOGhID8*%4SLSRqC#^D4{&D@S=2&h8i}9`jNMzo$8Wlr?frDB&naW zbO+&vLqV#5G~iY>nwv&EsKF{-(5fZt3Z@`?TBi=vuf1HcBmZb}?(4-( zRetk#_KvWDIH`HkiJNEkNoJWHU!tux0-%$}lD91X%d9=UDPDwhPl6M%P%X38BGO8| z;a#tO;L$Z-E6z|@Q>UrqGFal7HVd>l7m`VVVuV--Vih*ErV(Ocg>B3O!)I(Im9FE7 z+15zF-BFDyXQYw#=U2DL;~to2d%ZH`4{R3H=+90IB!RAMa#R6filMtaYMLPr661q_ z>|dX;df}`8LhaCcqfg7CFh{}MZWTcnEzi^EuW$C=ITqyqOb6GO|WSdJ81g61##4q)$ik7wO^Cf|E;+X zlLEz<%{3;-v*y+qUfz`_4%kXB(2?a-YZ@qbUygB_5AhT~^^V!qG=PHbBOuK-S%D{) zxo4@|%2?Sl(Ove9)~GZMjzMde0iS*6p=W$)#Dt}4ISZKE;E9c1C#Mdd@h=$PHNS)L zOxN$=Lmj`vwyD$~>h+3SfqCM-JaX0SVPH_UHOQp|^={C5Z?K#W;yI0Ndp^ajQhZr> zohxyT?|SvQ-}uyX&y6W1FMlZ<_S}c>J;l>ClT4HYCX)V3rR4HYDhWw| z?glnq&(%}(4@=~_)t0ub9|)Kg4V#U~^ReHZmB!1;o3FJ3t!7mBa;-Y|FeHwZ zEzqgq3FNGXFFHK#m+w5J-v$;z({EwRDD!j+J}^0yzfbV`qvw9*++(kJXmESIO2lS8 zytBQ6YpO2qtiM6Y*2kW8J730M_2;r%_1!nVQQThN{kxfdSKWDb^o#vMzQ!I#@rfEy zw-l`FZIrDh+tSH=|5{+_>c@KHV8`W!(2Q*mMWma3qe zvR}{x?ASOZDAXjEGpJ3T5jk?-Mp6D;FOegwi#vhZz=2$sNp1-%Gutw1^n4STaU8)t zCHzvx3)W(l@L(wxP9-~)NTPuUV*#C!joRr=MHrc>Ath3E3u8-AT=r+{&5fwG)JK1H1~nxrheR(KC1l*?jZ`y+?ytYw`(u+lOV8QPpIIQx5kxSz1P!HIE zq+$OJ5+eIJ$wue)h>hr0%WbtohkAWh_b!bKLc4tHK>M;Hn(438K(h|gT$i0*$(R!D z^cyG;S*?N)yL+*5q4Q?tUsM822|wn2v)|U|-tDm8-0#Sfm0y|bt0XNjs1;;{-hYyw zkw7MQ!op;;GfqbG#-I@>ADmPeLe=Y*XIRK%6i*_dQ!KBo{+yHk7ma zJE}kWiX18Q3mtNyBa8+g5h(N!PYAbF``?W)<5*S7qQV?4>KbA{6dvdWM_`p7*u%| z;+1U$(~c3BG`+wL#h_k&k?~Qsd=(*O>99p`rMPJ-t&wm7RUbJSGi@VlF{&H1sh*9Z z>WoI!8O{E|2vy(Ib{OPSfXz^SYMbj zZ$na;_5P?_n5B@FqK?&6P zI72C>b&MS0!T&|EM(h2bg=5OzHM}$Es3C-y7F@U;4^EF)*YoB_(&o-j`e!!!y*vY| zYrv@fbP_~F>o=w8aFnJX8uu6Ydort>D~dl~_*c|cGM5ap%%T$^_k!|E<5eZ9Ex5P= z5-Kmf1yKvE7=_}+72-Ww#fv_#DdrCHZrXsLxjb)0)x;sipKZ;^Ky9yW19xeUww=DW zi0IDvD#UjhrHXX0*M4|G!PqLFKPVVMASrB(`K6U~+N-!!AM@)RLj1A=AWa!FkESnT z`ZSZdVHL9K`(T$!P|lhobQUMDf~JpGll3L44M;ch zi5tU*p8*7eR}@Khs>*>HlTzJTpM^LVDjIkb2HSb|CUz7-(hgyamEy9>Y!FJxAk~{t z9UTU7@v0oJe+}vrgr|`l@IkNF%ZpJTO>p`A5lk2T@21xTDO>hw4Bh>1$|Q;WLhqrJ ztLqrt?8fZ7jRWu<&^|~PuUofDw#_Z*r3M!EUvl?(&D(zD>{%=r%NB>vcDecpWC9^@ zi5`gM+8TV=o+iM}@2EeQ-)?R-YB=R}VY=NZ+KQuz$!!jM!JE0>SLgMi3}~I}ujt(* zNot9cvTcSNYEiP#5j%mN=UgJyY-r#ySWE{VC7bGO923$32n#&;jN{WS5H%Z7s{+!S zQV$LWQ8^6wvm5vs9ccmKVRLdugH*)O@vT{+^P?X4|Ly~cAMu!kFf7UO6EY;ISdm9I zEy6panMFp43~Wi88tX04jFQflPzWS!!7g493d8~NqGJBCNtjNQZlkW8@)0~rV*%EN ze6mYnnTdx7&MTOPO#GK?#ALc<98WIu94NdnA&bqe-J5 zS@?(Rzxo&lVeRr-A_T<sUHd9AutgU)2trsy0ExW9Gd7WFwSNa1~0W3oC2;4gM(Q%vM4$O z%%ug00`z1tVX06qtl^^r$O0iPW^>KaMGa6ao*fZ$O`oOlX_Ns$Bd)f~Tfi~XCusKY z@{?(#lC*I48wpa{xJR~17xavj1p&w+TG8h+ERXl(w~YJ1kn1UTOBoW)x>JXSatQ}B zMmepRn89eKq;<2~4jRf%BhlE7{`7?YpJKPNFiPTVl?o=V-;#T1s=#*;=g$vGKz}b_ zm8dZf@F#nl7IY=<(N9*6JL$Ly2Vu-@94stkf_BYvw`CRk97)Thk|pJ)eFg&aqL+;2 zATGO`3=5q9#H1vYte^SfK6FaxO~^?z)fj|4cjp1jgNVZbQe?FV0jI;+AjG!U#t8>e z7YRCCzNV>()VUkp+H{xVXXun@O!i^|Zrh7N(&i-g2PfrV?7lmvw%M7bp-WUZ@&iO{ zHantet!`tqKT`<#AS!E8q8i2Tw|c3GXp_6oitfq76SaUb4tzG=X0jf(7sjsjM4wU9 zrW$LYrp-nojy}1Ougr7T{z+F!6U~)5S2VZ8?>bG3os)TTrYmW>?@B5N>ps;1(zt`N zrtu^wr%^sl-FKQ2Zu-0+3Pv3%XgJ1T;h)j)v0R&%jj4`#?UolU6ww?>l7M7!sp_&x zY9h%%+;t;0XV~au3Ue`?%;K_f)+un+#OjV*)=*(o6cf_MMfp<)#*{8!A5|(Pl+;72 zm!)_Z0IZ?Tj+yOK7MQfv8dXkhlU)WGD1<{#IVy%sa#LRXk~93ZMkRvROC<}u#Y_?O zOiv(pO=d8OqRZzeOIKwmc94Jm|H8wZ*a)oF&XQhXI}5ZY288IkYo~Z13W)j%BG<8B z?V>MmGu6JNT!?I}MbO9cWVQU`#`T*HiO0%TEI}J}#H~4NK{AN@&@URD$ak1G@HfHr0%{D{G&3pwzg*wXKL^AgZEMN3#x!A$xuoRzGB}8yVojg3*7+}(dxvhXn35x7v#cf%e)*$;)rqlcMz29#4wOTD-$*`Saao zy6K?2z7`F5@>E}|`y^AMIYmM7xOf2&XJ*JT8v<^O4$E(__V!$R5ltuqY@sT3fz|efni`lGVMA-*a;}v@i(C9WxpVd@U|5@)~Nj@1wd?ZvlS}VqTrX!5aqtoZ4P|K zJl9hBSZ!kz_)518yHE3STK2RkrseAee7$Uz9YmDO;;YyNZ#h&!-MvNM0&yBhkj5Pu z&8W!;2~SCVCTSvhnxtu(AK#ni$4J$sE8$4e0FP-z1KiPw26$20x1c7-Az@OvR^lML-*6Zx@?-A`UyfU-T+_o6SHI(x z7|F^H^qRar-}e5FxsG@Q&+H)$&J>NPAAF5uHv9m=u%>>d7*Cf6dvPPeUGNqhaEm3z zNQz1EH2B?2ikXujb4gY!^p;mifzpRZkF4ayZT;Q75I)kCT!<$!$wi|aLK@`|(kO?J z3UJFIq|Zm-a~iKiGSR3AGmQ&MCardP)Qrg{nGDCo4&1PXbdEWtqy0^Cu?*1_zNSZB zVIPrUL^BZ)`3O*?ZI8hb7Z&V`AF41~`O}Nof1igr_y^h4*CVyi_$x z3x{$WB%W>^Jogv&C7EQI8Y4@{1I8Pclai7q57~q_QqUKZZyU8WiC{T|5R(W(Q*oV3 znh9@_cPaYD<%uZF2R?X~bCL{mLA$u5IZw-BRTh)?(WI3}?*llg$Q@gFh zbCy%tQ*9ax6heg5v>bIw4XmRssiY>Yr^AkxqoSux6vBf)!QNbl*|-%&f6xdgifRgO zvqHr>^opfL(DD>YJtyAulNO?O}= zuP2oDHi_KO*>0pw)$yOnW1RuQ@?a~JR-eo8XuIdztseS*K|*FRrfijv^WGlBGOO=I zfEj|4iGt~?yL*7VE=-Vl)I(Mv?>r|f-~ZfXS40m_(o7E}BA)y5tz4FKf6iFxX!`Ry z{tDjZWC~9A@9O{jtLx=IH0f7!lL(0XC_hUz>I5$EQl}pB+2}3Cz31D^GACc7(3?JC zg=Ub8SIT#2Vlkk&M8Dt9qGLiow2*9aYyGRY=UPOA?t1=IN3CCw=0atl+l+{SWZ%Wcj^_iK?=Pctz zD_$w?2`nA`_l^18?Yb%L;@Lt8jf!X0cyMdLC{%D6V7j@TQrjg1EQ}(i(&)SlGl&wb z-v@@MU`-cCz9T=0YZ(hiTi37>yG^_aMZ0%K+@jY4VQ+(C9u`9>!Nd{lI5Rnla3t6k z$G!W@zv+!p`j6_25YK+dE?5m^m6eiWd&5n~RZyG)#cxJ);6H0Jdl@JhOz8l&xlq4~ zwC9HfWdhPW(;uIuuBRO;_EQx0GV@?aKA23(_ z*z^8B-rhgjj_a!Ptg8F-y?gI_^&~y%>4%-VH|kk3*hDOnSd$n~T`WtE?L;;vxU=$y z__2CvNm(&;Gsl*+(0tG)hMM7y~(9KKcyUtcV|M zFvKKU=8u^xUyy%zU*sE<*{$(ah)O4ywLYD)koxfPG@KF93Y?-RlllBo$`G9kSPf+= zRI*>$=f>;xgP6+m_Zt*PqZ}v>Xp$xY`Gu+NBHL z6S|6xNK1d_!j-KruoOU+CvOQo9S`k6U0++nGq_Jz6bZUjo_0Pn7|}GJ-e6Z-U$~Ml ztlg){=mC|$629``*3h0b{GqF3VVHsg|A~8@gO|Wrhn(AdE-<53z;hD@fiqKsxLQ<% z!ANT z%rSX3UcT7l`5$LaHbtwFiqryV$V4wp-L}l5Kwl2BTN)C^AOe(Qq7uDDk#*OJC4%ZBOv(O+mVX2GOygB5X6in&?3Y7)4zCtIAH$EthURF+Sk;owsJf_ z*iFH2WYu}igMZ78@vXG>=Ei&c;-;dg9pZ+NLwg7KWjnM$xf!g_nB5P_QoxE*$80j(Smo&!r5jZ_H|q7JcNjGrmP<>yA5xN$82IZ-JH(gsZFQF#AA z_Ja&s?FpwXjzd#qMU4CfCHms@b3eZ;|NNi^b4`La6xgFnUKhc*HtDU>L#$^e=86iE z*oj1%%fmth{u9?`z7N`0h39$KMhaAgA$wazftqA|6Kc7==ea0wh6Hl51B?P`8J_K? z!Rpg#Mxwk%GIK05`{sVu-pYN|%z;3GFf{Rlb0m+2F1UyTy6F1~3X$4E_RQwPwKpWp zyE7i9dgmCBMI6EP(8j|Qu!K5hMsx5n7vat#Gf^P2)E8X3=?0-<%YjxzJ=IE}1&(PN z5|tI5e_nZWj^p($0jaCir+c#(Ia6uN`Nv5)j_ARUEIsy=(r=U|-4wR@-Hko~m%9D-|%;iA&!&pcnkvpK! zAHIfTL2M962JQLe&8eG;_6R=-`yD5xBHUp&7fvLYFZm~1S~$L!=cE{5d4<;`y3Xuw z75ts_%M{Zr80NJ$_HgA1Bj6S7(&7rk*Yw0aW-5>94U4XT@wF;-P z@dUMU_^8#^Dz!RBP2Sl)^e_W2s6E!?lp&X=_rD`-gi6S?S0C=(>Ff>KNqU-W`_ykk zgGRu5h}pc&`NLHiJusw79#n#UcmzrxhXXoJVM$LFHy z|M8v*>pjZCgk6Vivk+?GlRGyTiQG!d=8!vKE1)N$`b-fut5V)2yeo~=PMs>4eiOn;8$8(??!9-=9Os( z$HNBMxF1lCNY6x^5#55v3bhT@<#=Gt;>xf`;Br|Dxcdj-?jKN$^%0zQxa%XLVbZA} zpJsA!ux{DiswN~(0}8+!7N65me5)9$QZWH_qfso8kw+TySZ?$g4?cBtLj zd;F#Ot!tBfv>7t4SIwD&zN^rpR#9$awfl)Ysy)EI2>pIJO1WC?Oj3JQSlz3M#OV8s zs~jLfeyN?m*psPDo?IzkXSC(!wY<~2{yRIs@(&=_e7Ubkh%^%(Gg@H5ZTCVSk2HHJ zo@J}T{56vyikL7(ohyN#CAcEVDHLJ_K+5iE^Ir=kSkksIV}2n^*vJu{(zCHjr1SB1 zqoNzJ!WcI)X(F7{1Gc@wR-aL?X!m*$l|+oCKZMfRjd4R8lldc)A&D{b7ec|4K~TsU zIkDXPpmn#~2`aM-{7HDvW5T05q+z_F`a@pM#lT)0d}Dm~dj<@!rkiK?D)WscI zjWmKr5EtZVym-5>tO>LVWHBw69zw9aiuAkuX<#}84YA=RVIu73;G_{N)!^OYbWZX$ zK{$-fqVr`o{m}>6pR8&-b-p0GOvP-$=P=eDy}>l*jFZl=K?Y8_iIYm=J14bWh#+X8 z?`)LWuNGJyP>W@Axmw#OLyJXomA(_lySmmCJ{r@a-k2dTx3Ec?X;Cs^z$#e8%p4Q$ zgd@t8rHOFW$kX=FLldH=`v@-ZI{?ye0vE=n7oAVn7do|H0;5UvQ(!Vuy2)mm!3iV+ zHWNX-ZF8C5XQVD|0fVjeX@=Vj`fqgPNb;I#J$*QuJ%U4+r|XSr$a9uS&BR54Zd{E_O;f3%)LD`rTBl4Hg1~K+f$MrVPql~&5xZ1SEZ}RU<3s%K?!^UYIB2}eQ=dxWa&SJ^xV%ev@`jOZ zPL6P2p4Rn&wBa@tV_PAf$zU4GTj_SmQf}{@*rW3YY z-fZ*Td>diSUNO&>O?S6-LPSaY?a|5}N47_{hQK6Nj2gcAaBfu9D6N27kX9%own&Wx z4RvsziQX{1Fib@3gXZb+NO4aBTo#2-;{nWhu_M9~!6r6<99LHle7(D63sbIom(0C zfhmQFc%Rnl5H0^5$PSn3Z7)SzF?B+3{tk5E@Z~<~R{EmBAN&qjxWjOzY?rtK?RnvT z`^;X@v43Wgg}@P0=U>S&1M7Swvq6{abqi z`v&9ef_Zf-+@U6gAPdlo-dSjxEVcP2++PBPYn!^=V~8d&0_renRsj?`YfI`tV($F- zl1x^a;C4kq^ykbv9@z=0_@cW#QMQIXtWIoUnLNSXZwpy&l{@BZi_{?^6git(BR@}H8Uu!j~WY07BlEY4~Fp1V8KE>kvb zrL~rk^WoTH6!#?FeX)rH*&2eCn%L~h5p5pGZf9WnY5G)RwI{7+6Pq0^QY2!1Ka{JD zGu+J)N7maNhP_ zQogxc8h&IBDYVi~qGEyzFtSGwhl2vvjIL3H?+8OXS@aCMX4o9p zcKl)hriiJvoJ?A)X+n$sTIjlJx~f(Be~pikx_+A~>gQT_61v7kK18+F7O5|=dxBu= zBh&02a*t(7@;$j8&z6b}{BBwn95zNSLcbWW;tA#nZl$%hqSt5&ujIbqv(geLWtRWy zB2bd!${rwojS9~;?$()cpOx_q-D9E><9>EnL{%6JO1zVmq^V z`q|#8GXJ54@7%pK-{0A4=a*)C_U*|Q7q;oorTaR&m(o4_8O$wpyS-kwm+abgY2tr% zeb1id<>ehac95dXY;|Ti#wzo>AjDzTL&{C+2P-mG4EOpsw(tJxqC=&7{K#nca5>yH zv}bmQZ#w#`7_JN$sW64Tk4xAK>?>Ft?i#RHX6H4dOK7^M%lx|0E>Lu#T+m_NN-=m` zxkSYoLW2-=c^{6rWO%6_T0C7+8+O@8C9Ej)cDP{|93iW)Se4a^+xkbw6ZXF(#lnb$ zJqI!m;TvT4peDJt_TFa%y#IY+n8ZJ6n#RF<*NoGq?-Sd}H@!ghCV5Hz#_?#UVA6r6 zek(;~9xdsMI3&nyuVL$G7wJB!PPK7Pt>X~sqE$+D+#X=7rVtZk+Z~@Jt zL*?7|rsHiw2?%ObY{T&hjQU(377GB9<+4;1HjaI$OB6{}KCsmLY_UvFjYmc-mM}V5 z)Q^DiAC$X8&(hZ(PRTwja=>u+8}1-~-8xorz zv3MbRN6>q^y|quRHlyiU~a6m8$NdIWWnJnA)p>?^3X4Fl8hSh>q-nzps#HQaEPX zD^hy}yKbxgkBwN!9xu3joa4|kc(vJ=E4cN?Hq1cch7oP5#>mOI?MRUyxeXG`%k*@y zqci#86aO-YHjf%nq6^S@L2na1}?{U$to^kb(;yPkE+KjZ+Yb5Z)>9JxBFO0jycJ?~XT z7fy|lz2m-qD*6-e+xYuL8=n|sF?Y(|;i|@(70qK1c8|~MrP z&vs9}{~;ab(qV%T`@1hdHGzK-!M!k+KFMKWV^((z4`U=S3={28Tn1r?fr&;zWw;Mi zz^b5?o*JWp@$9#y@58fcHI~tX%AeIbaG4Pq&qVhmu@b$WMN(>$E+5FAR7oX$_+mO9 z8C+D=0+grNlKqRFb^C3Tx!X}>idXF|Mz>AaSNTO5X!F{MAujY%dMV}GAOXQHj80kf_cG~{q)Z3Dld)f>(@@r2!5ApqF+w*HlhnWL zCxtIA2ED3N3=m)hFYf7@wnK->Ga%9Uckx~ zF{I8hz$AO*EflBLqf#_q$~TBnm{#=A(s}@eFbs(>Ku{cU?x@tY1-6(9L5i+asi?id zoJR;LwkzKbvfphCS&-{99w`EbFw9bWjSvR*^7}Kf6bAbdqjv~2{9anBA7euQd|0$R zK(n;Gg7;HDTuF?k_xATE1Rj-IQr_u90gcLkPEL(m4mFI59%E=(sHuB{Y^4j+XVbfo zS)k^9pZWU~XFg=MI&H0@-dxyb74xyK%4d_)KsCRPnRjn5|L`5%GZdi*PVCl@iVHXA z76RhsUAQMt<#&y-E+lq`JazUu1Z$gy`@0Iz+1_aQf9ELNxqI|B)k-_9YL0OMKOEz4TLc$ z`DL#bud8oU&C$z~lqsT_bC$P2Bg@E!Tc+!VtC#S!22NzP{O>ZM5;OI*>~8F>5-JeR zmroI+1(tAX*$K{p;qB5+_CuS4Z|9lv&ypJy?JGZ(0G#rVM7>G*+xF!n{^e!*;pJ@L z8JFL}Z{Kq5Ufkt_!B23$u2MeYx&v&*o#dx*>yVsVOuC0tUwDRRj2Tok-M}uxJ7wgQ z?@5IfTm9vZhITzj2c2H0D?Z1cG-C%=n;ls5N!sdB>aW#F({yewog-E>=!d^{EB~}w z6d#iHC94JcISmdd>;3p>BoN7EJ){%|zntP1sY3P%a99jfYg=C#D!>CQ6VBD;6LIiF zB15GD3#~*$d*>oF+?V3f=N|A4tU+a^maC~OeQtoxczy~2mw)%{J7h~_*HSWo#S>6@ zO1T9x@N|K`sU>dmlre?X>9{>1qdJi=L9U*`kh6w|xLMiXwtD9TO~xHKJ3NY1is`{u-^Tuo zo-EL?^r3&g`l}~{g@t)rJN{wG(v+DF%HlLO-FIF$O^eZmd!}!AOqjx-b9Zq%1t9Dp zin}C*zz~@RQy;)mO@l->P}~vbo`1QmgenzX=y0%&3|e@0`R&*2<=>Z)sfRB?bM*=f z_LyK`rTXPn!^D0zov_e^%J(2r>?civZKJ>Xu6F(x0~tbd)1UvV+&`CX6Gn5>|8h@O z{rc0Nioa4%hP&VT+4{+c-=2p15THM4OqQA8C7_C+;`2B%RlkE(Hy^TAEBq*4hmW)Q zE1jP&|NIkg`aJ|i0#6pAG2aU&@-TyhV%)*}tm6otq?#&KUlE4m(e$rc=I=o{VXko0 zTQp65AhdiRk;g8TB@q7~{~v#!P9OX1->0igf;54{ASW)^K2;f#S4@VIMZF@yK4pQ( zH~eNFo#`jv%BPCEX2-{RXJ!-${ z#({t7pblDgh=UPG0n#@ciiR1Qn3|g&KD$2|d;%=H)6~BHnG)iFlX1vIR(8bQ?q7Ri z4Yw3;pqESv7u9ADWS>SH;Th4#$M{&Z&Kwz7f}{8aeCfewd#6P|DHIBC;i`Nc_I2C_ zkV!dU2Um8uOpE09iJa(2}RS%RGXH-iAZAE_{e+e*SdzkW(Vf1{8#lpKZO0x)){p_VNn}s<79V z@m~j+Dx7jKw1=3Dxff?h^aWjw#nKYzRZT*< z6&r;P<(wfJJK+4wEl*}|Cix303G1OY9>Tc(VAq)=n=qX&vX20rcFbAqwlJefdpzJo za?xtemP+>@aFfU>IDNmlv85Ks{|w4m%TO%v5p%obHC{r^uHwiDGJiuzLGq`(bNk%) z{=HY=QJ^WsbPqqA_^T`#sCbEkIu>$S(RX=rYtOCaQUm%P?^A~OQ(A&85VV<7T`z$w z_SBXlB5GZ8GMfcqp&O!W7qkRf3zFem+s?OMzX6Y&mexHe!~(dALrPC|XljduXwuV# z{2Lcgv(RqB_C9QEg$`qp4^kDvs#I|+`bQ$xWrZ+ILwLW=Yw#j1Gps=ebiWc7NDCvD z^=as?*7EIW@vd)5AO7W?+3?Q(W*UDW#imqPNOR|3!+y02=BQOLM{R+YEF1H{c*(vi zn4{~;veWge#@p<>O3UfGO3SG|K1O2F-eNZDW!VWNlkPu>+dW!ZiBknIDt4&=L=nGm--X}B643yW`8Hb(wfwOB+vLNz-OuDlm< zZ|FTVQek*2- z9q_&uFhC}JH(Y=E@4}8pITL=^;aJK=Wy2lQjJFMn>h)+IDvV`A@fUmEz>wKc z7JrJk$v<1wva`+aa`X8s>5m;A)9f`+3?5h6vh-K=&HGxuKSE<=^qN=9i6aUek^n|^ zwk7+b3DM=adL&O!;hQ@oy24a-$--}AF>x^91@y}1GIOzfR6-U79o@Db;f=a^`ssgq z%F(PV#kYs~tHeMaU^nf@p33TUVU%j~S)vPf*=oTMWS@};$O?fv0mnQgVMwX7Ph~MF zVW66H{EnYuzBA>tJW&wYrqgo_f$DpBq_!1{CPs-6I0Uz`H8^E8A)FhyX|nVPp#`Z) zaaFrTej{kkI5_;6{^NtYM1;kHj;?azkxvHq_M~mM3m*Ka>0!qKB&V#6Ywaa^wARpB zTnn;5lDwKwv9f<i9XUGv=3a=GonSf3K16v(%ip_W1Ft5X_ zUc*~)5wnhyp1FdqNG?^5&JsuZflTr%0e5E8Di0syUKDpgdKM!RRyy1)`<3Vgo(P^v%U2Ck0v-m{l}`l6VlQI z2aKiI#fwOoi(s830xU3U@=<GCyvs^@^&X>_Ko3xr@Y}vjw@nuA-Xw^$r zT6RwE!y?@+X2HXkO~1c5UsjhA$To4Q&ztwI)m)kJZJ<=+%Gm}=wJjVt9G5r>&$)7B z$pH*|K}wcifZ~P*(Jq-*>O{Mz6ozyV_maxl6lnB>@=P6=FPieB@|Hsnm!3N-Brc^C0I9%o+U7?pA(h z@0ya?zmGSSW)=BL#tF>Um1ebG?CY{jO0&NEF;|ym2T__8oIHf8sOwkBokOcb zbJSjsf~Z#2P1U{@?Mm$rN`}zB4&_TD-WgPeRhR|JwSm{!WPSpWqE5{(cRis5=CIvNNZUVGDI z*E%J-8XqwmDaAYS&mfDJoVAP>YAzpNJ8wYQpf2yyv>AXa2lH^Y1$5(Gk4eOb=hLG6x-; zA~L*tuh^Zzly}75b*|>EBsZx&IT@^1o2QA~{?HXh8lD&5Ib(N%fy=r!$pK-p>(qGn zG(p4jNqg$>?)*(veMa=2sFIG{C_5&F1{cZU@Qkb75&@WC#a@Ps8l3;~u9&>L5RT=O zQHQZ}P&{^|qW%-=4VlAYg!9t!GeVE9X)A#6=cFg?9<`~o_A!Gp!6>W9GTaXOHk59r%3w$<{Ii3+h@ zFYGIuHE4x-onDPJ+9ut0F6g$jm2O)T*jyCn8-}YK0^Bl3MVax$RjS~y>yJ-g!CD#w55?Aejdo((!{+zD81 ze&n%2-gxisfVv^~w}3qrikUhso4Oc!OVnG?7-Oxlsy9GN5Yfz1JYNCMb1HCDspbGp z77_osZf-cFpl^l$XiSR^J~-P%ah0G=n3$*gb@U%AOhg>?LhEw`C7^$~TA=@aqXt-WI*!TfMtM?K@0&niI8$>ho?%Vv+3Xpt3|ebp7VImD0=64`qRda`bu* zI>OSTgtJdB*rJzUi$**ep>HbLV&39Kd!l8s=c1MgP7!mU(^`pOT1!W#HOqw7EE8IS z83)jUWtkjQ3u8N^7K`L6wOAxqtHlzzUM-f%&1$hUUaJ;M7#?@1 z#qL;3^6~ukt;mxk?n^q7!^z{aKtxOx( zY9qOT>w*A#|G~>g zw$&4Pp2cyVvu2H*t;JyvWi!cad=G6SIV`4D#XPgBCZl-U_Y-bHfe zMZ7AO0ETi!`@H4N#k;uAco(gmph3$rC`ZV77cDynuGe>X*m1Rss#{A7FMDn668U^Q zTk*j;wvKc*bCUa-E)noGlS@RcIEh+u61CzaYQ;&^ij$}nCsC{Tq2$^zJR15gmxx-q zMAW_(PNUy{5dVhSlh~BHt~jFF+u=NF(QfT`;)grz!i+2@c!u$040Nj1yhMv>2Sgzu zPLi*IpY$fD!meq`5>YHW9#~^YsZo827g$Ozt2wX~HmpWZ1-$sz5^I9b!1?5*$!i1P8Ld=qtsZ=ajsEWgo#DB2}}?@P}YfHjvg$pw{x)wbzE^W ze+Bj6$RGd;d&E*Oew9atk~@d8nAv;)znEkMe=hHfR=ly^U<2txdN%?`?{+@MJ{4S8 zPgc>!I3KyEH$4(#g+MHSg8Zn4{*^b=QGq~#NDFp87hX;7Rn zxvs%8>0V$s?uVTV6g#ZQf9?q8*HF|>DmTQh;`!ltIY?QDR(C;ZvCk9qr%wL9s+Om#W8Gq8{H7cEjbJDz zq4AfAf8#EYzE48vo>8kL| z@X41<-PI_!sXJ$6Esb%Lf&~ljQl}{}v^g=MIaJ2QRVu)sU=2Y7?FfiBY{phCmxPt? zm4!$vZ0$?`R`N{1R@LLGv30J()}dpoW%D(#H6&9|-n`l*M7+G48<;SI-1;|HMv1+a)Z|7 z2Cc~rT9X^JpzJ~Tq~yVi)x!U;QrlNmLRz*e9aB3m#g!Jha9k}$^(|^Ks!yoJraoCK zuunz>_D>eF`K=V#hnfm3BGSZzT8Rg>5)W!69@I)asFiq7D+N}q6j-@JB^K0PkN&Ca zN`zB;3%IZL1Pn>PpCnkM@2^8_==<%sgY;doJ+*6!?db<%dpgAHvh2qcHGbJ=3_?B(1%P#Y4X6%#>L>!i-(ro%~} zX=v$<{3h_R52G<<*$5nmeB}5lFh>@E?lw~AUaX?PSNG@V0oCOxg1L6ETDmOWqAZ)fkVk>!7DaB;=(|Zt1HVR2!zJO zeYjeFmsLA9Ah0$h7hDVg^>Cgca0uts2#j#i)6y#IzJ~DiNDLeL@(|rna?j9%o!OP# z+bPksGpGxAlIPgp3ti%;0B^8bjZlG@9&D(~H3>;;5|Y*=B&|tE zT9c5pW?9jiWkqY26|G4|S^#@JVnLSGakWU&Tht;+PpBm^=A>FA=j+ts*1lb>xut2{ zEzJiqWk`_W1G4nT>;wMkx7Y`BOV{G{Ay1ik#~cTkZ{ZyxB?PYHW~Op4O}NU-C*i8^ zDw?kE`w)uyUY8CU+IKGC?7M`m?vt=pD`Bfv{${neAZ*pnC=cb-3CUxmi6ap^ zNW@Mkm?K5)a!Ptoy<_zT@u77tXvzj45nE*^KVL~hjBg{PG953J(M&QnOojmc$P`f$ zf@P)#9sy75P$-CTP|+c5%d!Miu-=Rha=r27Pe{I8!7+j}3USF!0xTBcE7b!&@nRcE?ju2;ry_hc5;u-Cl1w8BKI-Qj z$sKVd=xJZoNKiv;BvvwlQcxO6s~U+LQ5s20BMCxwi;<{Q2I5%cKMJNqF~Vv*N3B6E zV5u4s$#jhvFA+OHcOR~vYXGfQ53WD7O=}%l=i*4pkPYH250V-0ItMrWLDNH2FANwo zXQ-m1Rn-G9U|EUCB^_RSf4VxQybBKP$%3-?P`V^nU3hEj|7EQ{2(NaeQZz;N z!NewxhLZwS2xBP!$#Imcj;J6-s0U}Gfa{J;iNX&U5}`)CUMVsEv9g$|YHJ{(97*DK zi_wpS5BVZ~B>eZr?P!hL(UKwRRn1j#jqiBB$yYLNSE$8dUDbrrcO2F)R%_gk*0>+7 zr3ccQBbyfP*EkXy3};OS?3GRlgn{A~cBgbLH4-K*E53t9!A{E-+jEbab(xg=kKQ)v zP#RJ6iHYhyF;TVJvZMASG@$2hMf=ltx!Tpr)vgv-yJsPq zfubvBpy)$0`EZYQLh_;KB|Z|f5NG7ob*f=s<*Q`7xT9cs%iO@dh;m|HdptLAS&Tj? zWy=@I4P1cU8##fFDKV4C{QG36C^HZ;bla!Wv*j=Aq99o6QU1sKk)q!y5^qYS|HlUC-yGKGce ztOftZgv&F_7?ZnzyP;b5Hja9~IzSz#_P-7rA((^u(ke>$w*jMa^z-_bePJZSM z+C)DgeWp;q{J%@}2L`Y={<(ZL|EaM~qyzV*Ru=e3^^DSf>={xU5Dszy@EUYgh*(bH z%K`cFG5X&oyNNP&R1c>b4Gg=Wq=r5uXAvXKeof6)cs0M7MT*$ElU3st_joEFiG9Nl zPA(}fX=dbI^3L(4#U*6v6_s3HP;v+kZ;Pza{+1jctJR_uPBx~#mP>VjxW_`RGI=4{wfC6l5Z~0?Nk;uE=$7uJZB12n=gH9|!d{=HqRikV`$AP_P}@c2ezr z3lnW7Ugq$vhMF?<>tWq{RZQEFfa7VyBMy6;dc=C<~!u zZ)Z4m=Po(;okVsP%PPdUO|%fOnGr4)aJ#a>g>+ZZb-*qj>_%4A3-%%8JZ*U!uh!gMvJC}GuuRNl1XQYY!evV*>{~jacoFpzNhe$u z0GOYr6V7W(k&I|l+xz(Jx147f?H8_TN(K)VXvK~?*(Vb zx~xEyRrp`s{l@g&iKXu?7YS2do;`hU8HZSta~J^85w;wn`&evO~H_Mg|h}LS-+|!=iowIC7P;uQ(8y28fuzrmbH}EPK0wKJF z`~z_SC6ZdkQ_RW^8KeVckU}uhsG|KGGM-k#Rya#4l=1BjXE$1wJ7`lEODc39&O&2b z8x9|y6ZP2M>SAvrm2lvd?!5BE?r6-Aw099>rWcGES~F&7XU!zUXt7K}R^GO0#!NzF zh-DI*5kr46V&Hyq;ha#53+JR-TsF6=wV*gHt{aNWnd^qVO?+^V4IkWN!-p!7kkm*| zBqYc1VY``(!bcjR^haYT{dea$qGtuX>f2yavdC*3~CM>+%*19xoPTCdN;nW@b?w&jEV1aXN=z0bjED) zJ{$z|z(ve)E-IaNK+aS?85G;HeQh`~C%Qib2f0Kvrs|OmP-r@<+OApx1=l+@D)Wg1 z-4os`C=`R+>fQ45W#{OG6KZ%BZV>QF5aEb~wq*^}0M}Z>=F1MN(@})knG8ja%!k2q zta0srfrl!mxWt)>qdr9eXA!FdIq3GX)`6-ES1K*xvYD*o%bs{5yYF-j{+pc5-fTSf zKj&_gtsveVvCcr$xFK>xvPm`AvNQeEUs3l}hXVx#1Gl=yw>hEk)Py)_VdGV(T;nc+ z3uqYhfCL9nst6cbL_2@quBZbv&QCQWDR8pW7nTc}k(6>mEoexJ5@;Vj?`PpWI*nB~ zl}D&8k5G`uO^?vQ;1QZ3rIGXk^9a!z6Qwne5G{UhJ3kD+_deKy{M-B0GGjaSX7Ex! z^~U_+TsMyptvo_-Z)f1skGSW@4$d? z05eunFpFoC&|Ury4HvOv7pP}91-_85QqU=EN4TlDYCyu|c)hV(J|{AEY<#eqkVrrQ zNS4vOQnMbB)84`x$B9EV?CgBx!C$Bd))t^^9v8F$bhCggBokB#Kd#OJI{-)V(eCsd z%;7`SJ#$b{p(W~j&2XlYC*^$n`cDM<wcyw!Z+6h(+TK9 z!~c!duXN6j7W*I~L9LvLdj2rZKz-K^0JX}7Q>(mPwdBFif)p0bfN;n$Jv-^*+f(v= zUsahl1YTg1>3Eo(D{rt{@VRra<(~5UU=Rng_udHLbp@j_eg zR5Yh0>A`M$vx641zIgy#Ft`UQ4TF_F9o)kXBY-Fl-cmO1ob(4&pHt(ZIk$k7NE~L> zh?**&fc5s&q8S8-swDt?kV}H2s{5wzgbc_JFac5(CDV5V#R0Vl3fl>6S~%YcDIC^y z)52+OKM$=^Q)`0yOiUqqdn-*T38*thZeR`TC503tGcRg*e{OQZdqL(R%QrE*#iR(MLDDUB>C0De7u0-;^!_Wa?;vwz4#lo z$g5Yf0VBNg_V`X}C)xd@c)zN#X)dHZh0AT2UqJSCySemxZ!5t`wOt$1G!Sj{cfiPsV!Lr3_ufP?YmE+Ts zcKMw*OiAmY9O_s8+V!;)cY){}8X}x1pZ02wsTLvzdFHRhS(TNaOV5wYLxu(Q`8zePJu$3z@KF zM2C9V=Yr>J-c$$pahc?A$Qp`+XJkP)bFuCO$3B`}kmT=ZMo=o(cX`!O89T<-Wfn;% zsX7k)lZZ=oKQW)TeCY{ICmGNAN2?S!y+2-E@Q-$t@jcQWFVeiHtrJr6f7c#U%qsr{ z!pz~7W+6>~X#m0UUZ(U!o&4m*{>E z?!RB)U(#|lEn%J{7DinF!{04NKRjZgnwIv{bA)ObQ?!GA|Aln`dE>q2^;F01HKne{ zN;G0nW}`$ySi{7oKmGK4{?n}npxtwsOyBs#e10BBW~BwgO(>C~d}L&&<3isdf0Jv-Jr->~zrO|9NQsed{vE6gL4b9a$%oMos;($aN4Zy^ z5YyeDa^!E#9s%XuG3r8nKGah%p&p!rBsVmKIs*2&g?g(J>gY6aqcOar-XSb+21XU4 zyh?D=NIglA0}RM;+;V81&t*dcePqn6*EhaFLj&3>h!(wi?|u5?@DhCCk#s%ltH%;7 z!F+4)q3IygO}B?aSmE|iuOK)LK{~H4kmP@{7^?|1&0bSrkkROsGo1G-sdXg?L2H&T zEu?GJRLT5`3d}zJjs?75Eeg!#YEfWbtQH04Dzzv)SF0s=;+R_7)JIDq#&LaT&&|zh z+2GU2iExDmkuZeEluzOyyFa~l@GHnGRh{1`AHL=@?9yQTOrQ9YSlzqF4aOXpSU9Rq zK1d@J3HDm?YSfi-kkvoMqw0QRgqgF&2Io&T%^W;)aA!7axUjKSxe`h|E6|;FeLuoX ztqu`aE1{-VLQSpA8?`cT)Z+2{D$E*_^0$<|qxiX^!)yQrDSUI>40&xSrfw$YNOgR+ zwzwe9bq~lvOX}`qc;QY|4P^fiua)VRcNPmKqmYTpJwj>}XZ6^0#o}$H9Yd1&Z!`k* zz!QDh@q>n6+TZc15W|6&ypAuqPN&YMBGUPqdPS_%0x{^igP#^U0tJzd{aw-TOqEG1+nEj}^Vwkmbf}P1kzSHTr1kkiCg7 zMM7vQf7`eis)jxnbhP&bl?zzHv-Pqb`<#dlnwD6;Tvk>XYyxG=jydgij5;eaz)g4f zY*|KnLoSzPSQrZ}skzw5l=p2LB`);b&HOfXPQuR?C7k#zCY#*=&9 z&o0+v!({Y}lzUUYiw@*TWS6!CWz8h6k}Kj1jE(FzqRu+@qcN?-%Vv5(44s&Rgo5fk zn#q!uo9XAodd+( zZ5>MmB!YSH1>&-wIh4gC*EkLx9A(S7+mS)ztN6 zAC_}Rp(Y(EGc1d1Z#!e}_vN>D1{=yD8sqv{aCBe?Lqlo?Y{qC>wZ2v55jsjF4~lxo z^7e2d!|+-mGx!)#%{HYg;vfYFJvo~e``XeJ5zYH`9Z`L`S`*Q9MbV3jy}grT|lDEMd*$;<|XKO`$b~+J>}lovD=|Q!7EHR)S3JS8H_<4Qj^O zM6dt&$zA#9GD04N{}qy3pCD~U*;G!kKYcSUB$Z?i9^ESWUh7sHWKT5>GMoWqfZIOG zA+#=cD+@>-GcYzKR4)}0mTZ?+5^kAH$R?Zq{%?%%9{-;mP8l(@sBAbikY8v2W~Grr z6a!HhA&zikh)v~hY(;C!2a4?!eDDl5m`x=0Ci#ck(R9Kri^_LaqG&KU>L1GI;N#AW zproE!=}yyjT;aexAbEE}l${ft%}xoqQpCT^LbC{-j0Ym_OD`dq)AuNU*q?Im#`KA|{j+owBF)*JC`PItv=7%4x4-__$^scxlkak=>xGCzI!J8$PrYa{2|EB34?G^l$I&S%t=odJY|Tw zFXxMIouA^s%AX~bG(MtRfNgsI#l$P(1JU{O=l3p5(S!9sU>`LodEn~m0cRk|^rzo6 zH$}JA1Ho<6ctEy(Cgx@5Pl}pje1S0r?lOJr-;Jg?)$%v*i5#X$vZ!luvwZdL;G(IX zy!Sxl6e2D0A^fx*6$_ma;A_**cg# zBKHzO@)@FkonQc?Teb6l+r-eQz$E9*Y0zP~X8$tut?gfVVm8fJP6MthT)ttxWit3! zn(EjwTjZv@cO&=FP(Te12mClpLwfI#b(oRJ2FRamNBUw-jaa6i*6q{#pLM?r9BBH` zApgn#Nxv3JgAbK*Vy5{QD}A==!Cq*mTv*^*GdCzGyi-reya0pGwO}+`Os8lt8rkz= zG_ubLJ6b!$Y}9q%Xr?_9O5S;1sMuCY3rBL~TU+7C<91v_Afz4}D-gLNrbD(<*gp1A z=GW5|JO$N{4I>BDVsac%Yb6yq{}MCCpk+tMAYPN{PyQh`Nkda=?9&l{^1fC=AE=|s zcL{w2h^v>UKOTCik_q%0cWQetRW2UcL1K%hrv3T{ae?UNm76;%`E6?Dy2O})GBF%1 zK4&(Txi^&^r^8Qq+~SbCpzad=1!M+2KObYdqZ8n4ErrKf(;pd6};|at0f-WT&6( zujzfFH>tiRJ=mFp;y?#@Hm$zCe#^;qrjyq6{&4Tjs>WtGhOTQ1tzH=0J2z8f-M@Mw zbxF_pbSO>72W3rTVxk^N(KEZUF(_F^xMM~A14k;3`>0JZ7`w`=_%DHqhMnmH%}MdF z|86g?`j%N6C*jc%$PrfD$=|;#3fMp>b{pvYxZJ4c|~ml4~|sS))%$a zQq}=p4cE8{BQ2!aL?wZBs1mYm7QRS{aU*^TTWpL1xfs^NMYPp_38I-%HeaXce>9UF zdzx3k@u)J+;NK>oV6UgO06ncS00kQ4-=<~v^ggx7yFx7r_0INDF6P;^O zWa~sEOJZJCTQ6H5hn-!`H(s?B@m!}w^byq7T2;zSC73}qCjw$Bf#Si8s)ox@3>6jN z(Hxe##Y``607kMh%1pTyBrDlVN~?gceB|P!?h~KUWe{22#em|FBw0};SpPLd)-o?_ z>n6SUr`7B9`&pYKXvJB=Ie7WUdJ%51=y0s5Xe;$v=!^eoE#C=KUEdyXCRF}563<=zq()b^+3vR z-gCf^EPpgR!Uzhnf|}54(^-B^@npA5dLfGzK5iy-ura9G9|oZDU)DN-yL+a7PgMQ7 z`4RgK+p{+Idvex(Pgec9aT5Ctd~##Icg)%^$BBkjaGNFe8yM-ve(|i#28ZKSzs@dW zzky?J?Dv@W%SzV!9_l5ND_%<$5yqp|DN|y*7hxEJut+(`~?7-A;GYVBx1Wtm%k#(M7MJg8c0FAtth-%Ttc|M#6(BfOD|ep#zVL@x?n z-yJH0hr%$7bf=A!B$Gj@&CHf$;OMq-rW;wiSa1OV(z_;^l2Ov>op%valvW;bVwZ!V zkPg0-CZ&$H@HhA?B74>2LXg7~ooekNOoEpo?Zbeq+$$4Y<%)HR;|cBi!nj=VKHaTj z8ie3`BHq0_%~OTCE>NEJdMxoQXFz zkN3xH8YcyqE=qE|4{84^6 zWd9y7@89>jQ+Dei``0fJ-_a&7Vd*i=Nd)Jg@<&p6cI>Ce;AUKZEIs>ys}ucM`NzZW z{@JH3=RhVi|L1pIrg9M3UL1-j`d|+Z6Z=;?Yp8jPPpQ9}uf5Q2f3DkfPm=%THv0U_ zZRA2gEZ=$WB>55YEY368tV~`3yuX>T>finkoH?xnU(JmCQkJR?iYB65T?2=v#_lao+x0i$GhJHN#p%tC$s(155JIIx8avO{6eP7hF=5| zYyw?X=i%#(pr*bGR{Z-tcmY_$#tk=x!Gs&)S3wo?LHDn}+XqY9~A48b5IIZFYL0 zi;KL~X)|?#Y38!PwPrb*Q_BedPpvzr#l4oLu0)!bUBjC;-Z^Geq`1WAuA*|&^!|N! zu09?f6WOotdmMVoC=1khEUg|(r=L&GO{^O_`?+VIeRdIQS)E?h=(T*=QE+@y*BZ>a zUhBbZychMvU-S9o4Rnpzy#M!;b3O>Y_MG0i8fT&R(K(Rs_{WXi8638HH6!ZAc`8Y& zNCrRKVSDiwdy_uCbb%B+Sk@nB#HFBEs99|7|*$^y`FW+r*3~w4cAH)ey^77WWaQHnTg4 zv|^CHnOLlBHdiqVMxrv3LC0Z(umxL#r(+mA9SK@~Tcsm|__b`~AZRu9Ie(RSlyh;s ztfyEdB(BoZqf92*<20#2$Y_b+1yoP&x3txb0U!Tq%dl5N1hcB@Uu@KKWog+Zdbz$6 z+!srfZ}E^?g8w3X`4F#Gi?6ZaOQb5FnBeCZahdftMl7b6pCW(7F4z>p zX0xKj9yn$~@pyuv)@9BF)U|Tz)fUhkey;ookp%Hvdfl)UTI6(yB-2m@J|*|kR!9-@ zkW$hbqs@DQpNQ}<+xfF&lSSwv{=&xV`3u^B)-&=vwur|Re%);o&aWwkx0i2T zyXwr5+nAfZhWD-MHCD7xT~q;?_Vk`#+RNJcYbsI>NJH1!Cl#m~261$_PSZU=69@kM!Ontb$ik=9h{P;`GoSjtwXPQ0A_rlvu}W4TQnE8?rt9?F%*NgEP{t zISiOZ&J=^0fDo5lSAOM7&-??mXSCt$$ZZ>a^M)Rv#C<<|XMnt|1ssuYA9WrMKIzdgP8oop5e^9at$W~>To0nR+n>B&}oG(PV>$@Wx%-}rp+ zOl}Bbk#G9mzo%+3JrN472H@Vw^#ce#N&%AD;{!XwmO4km=#_+T)Z=r7~|BOJ^Dq_b=9QY)(%H8PLI+n!?_b=}+H(X%VRjq>}$6K*Z<{h!_c_M^zKA z?zNz|Dk?vS2eD7z(daFBH$(Ug%5oU`qB;oNQSBm*f?E zOF@HTc)gFq?owj1RkDaY!u_5O<~Xb1{fxO3fLcsf-6q!?+q1m@!wVD4e9VODV=2kI z1vg=rql3XjM8sU3B>eE%$#E1i$p+yVN`EV5myI(8|7abo0wJ@IOg3X=P&;3U zuEk%#kcD~RmBB2cNMcM4Rr)hq z+RLw`M~fDlLC%a@Y+E5AbiN1vCVn#qmC%Y&?$Ipj$&-CUcrhCm9gD+`Ji1lge$wQpbT z(%c_Hq3@l~T3b~#I@nlolvi7EIUzh0+N@7)3OibjLZQmCmQ&9y4?Q=dMNu!AFri;Q zlU@V-Ts?9L;AutrwZ}GKRc7m}-J+7rbF844WLQBI-3=?)A}ezJ3R=EoVOdBh2OV3# z;N(Nq32PMGHCjF)NZ%vjd~*jwx%N!!%n_29#lDS8Gk{azj``!Ax%V_*JcNCtfS&$6 zvrbx57ARUJ9N1bREyhOl^(og`FR@}ZeR_I2J*tGfew3hnkiMs@;V%DDWVi9%H?@S6 zC(%-+0mU3#rvTR2XX~^?5ox0(os(#^6jYl=?BW|mOJOBK9;if$&%hQpT z1b&Zs0KJd}$}lkqt9%rLUYQnI+yu>8Pr>*zFb9RD;e`!g7DxC-O)UaHq@sW#np&-{ z1TUMr3^;LGM||uWTUyAC4dfcYOq#GT|#wU@Ff=Q(4w@&E6V2 zB;_;T6!zIrV!OAY#5PCk9FU1FlezBnpjpEID-1KZ;E-9;$jE)2cJEn*`1c_ibO~q3 z6r%yPuyr0!hFox%!HRKpIi0IL&FpU6&RCDZ*@wHMb>H+UoLcE!s}eUw`#zkLX9n+^ zZ*|xRlX4V8xjvWt@uph{kAX31wPMnKpozGa7bwv8{n*@U58!ptbrmX5tF16#zqR}ZLPn%52PnK&IU_U->s-=5R~q-L7%{}^FPK>oU@%H z)Hf*5_bV$5wN5^_UfD;9mdZh7yEpC0Z>#fira$wOe8pf3!#UPo# z={DH0-T3(DTGM%M7IvZ%d1|N?9+EuWG-44LR7ADSWR<`nEbx1R%!eWU;@RcKwpSGF$ATS9-Kb?H;l|Y z$UaEZawW*%p_i-0Hd+x97X#Ldeg?Ah*k)*R2UA+?+bIT*OxyPq$?AmkM`0I7&gsZh zzM;-=-iAp)Eesdd(m>0<5y<>Kk zVn=FtTNtI)xP&SH(%mgJHfFN;2*GI;rLZt8JaB>N6Cs<8CgGNiYJsV(jL)T?5Jw!l z7Jh+ayL;1odWv|NCD+2BuTwC&(I+W0Fc#)Z^M|Sm&@M^&$>dl5ZxCc#8Es`U8Tevq z9@()_wvXproLQHZFvITvH2^T*;Du4-cpyi=hR$PQ=YrDkf*^|eaX=K@LY42bFCPWO zkLNO(>Cj#?r%;}0OEo@)^rONRO}vKk z`|l7fP6D>kPeq7~6GS~Y6wR91Z~})+IiRg@QOW_|!L=>6kNjR|>yzUTZD}yMEEa$9 zx(brTo-^uo6=W#MV7d%{xEoS4u4-NM2aiZB3@7Vo&TNP|S+)45*d1yvfh(3$2EA@kqV&_q#MjC*(k)2aL!>aqZH4{WETWOCJbBK2dSSPsl zX~Q7HA84($fR7=ul2&599T6Q^Hfdr1*xqPUMWjL5XoE2DLPq>l;50;*DFJ1z-M|;u zqFZJA=ozrik=24MOYnnYHK_=6_fdJ?e za4U43qO%G+U|q4;wcSv=5_Z!Tt(Q>@2a$V^vX2dn08VlMvrK%qD!(6)wQr2`Yt&>z z_KY!3G*&AON(=JZ?rSvJxcmBG%_t8A>;KWkR-3&gTb!x#{OIiHx;_3= zi`c;eRY!q4X0w`J$y>gL+E_n5!8}Mtda4YCmHrSwB#m>I|!G=WZDJq8s8zB&;R^vLTbvMV%{^hk|#d=1NGbcyu*(DZX!CWtLhwh^R3cfS|{h6ieuA8qy5#!)%5=uTL%uBlBk zq^knZO%A}Y0L{GbT0M%vk*ihKR;ux(3@6eY%l()v!Ixx1{2rbNM&byD<2mk`;&V1e za_bXI$po@#3t% ziXuvS3MOU#n~Ms9I^Wary5ZwmtN#3j%(eimrPFr~^t+kG(~tJ6d(p1r=ldF;A834j zu=x{O-VoAk0{8e+>GM@%j`#uo&~h3SDi zrF|zQg?6d$qVi-0fU@s)dU#SkJJ`8D3E$cDq-Bum9*P6ujICi^?mVqSM*)`ly;Oib zDuyS(vY-`cx#o}^u1cgdW@P9w@ENgAz+J0a&&tQve(tduB2b`$ZZ0t-GMrXil}g(+iy>P18=eOA0MKFn^a)TgtTP-L9>Cxs34CNc`Fe$kR*3G}YZvJ!3pZ_&~>J5#1 z%)N&by05ug{XnzEn0vRHduFi(Ikk^-mAQ{QBK?gY}oHqTNy%@*Pf7t86HOW=!-$~noZQH0q-~q zG?ONU*tM5riE$lxocNCU_=V^RNyZR>|KY$jdp!#*7mqkikJs?7zOrQ2vjV-0@{*fg z#@h&Jg+j+y3`fZ%vZnB?8+*yCWZlfmEvT`1)FQk~^M zNX86^R?3Uox<08p8sZ-8`aoZ5 zC!5c70F2fvNfC+)g>M+Bz|&MKJ7NLIr*P|T{^4ef|i32q!#yHz4K!Htj2XCp|5dnB}0jP{L_ zkkx%*vJl0b6f@8Qj8p~X7iaq<8OGEMt>gY$C5MGiHWSfGw5Ze7el8 zWt!ijmb$F;yi|S+bv#QUMf>)Z_>EtFCe?kwW2yW#|Jbs7K8zr2w>zDb0WX!`B%N}p z{BMaI?@Q&!(`)$m7a&8L-=l$amdba*-F1$ZB#Y^@;%KMK&h2G!3IY?l6Sqgmu^^H> zh-t#pvQIkq+=NhtB3;8>_mni|>Ck0wiqrhL`cOK-R(-%*>_ztMu<`zB=U#2U+WIMo zm2}dxaKorAOF#!^sTH2+T-2QWd7Xy3!f6O9kBg8GNbhqH2o~C!+Lw5Y?*ik2TB;Y^}jovzq-h2}Sf!W(H zsJrh#vvJG@ugoF0GTBik1^=7Q8t72#<8;_XQ!*5%-3FRVj}>*a&rg;)_f@J*P+})L zi|r87HqM(~f&_N*nITKx_3?H=cJ7_@xBx)5nHj1HZx?O=>mAJV-0LUXPT6f;Q@8mU z-Heh&-BGU5X!X=2k*seGW;y_H|YP~5=N7|tj)xGW zvJD-I?HSJ#$Fo;hex*hBU%ev*6xkyh^R(3rnVXRn&MDq zpWvwA=)+yfrpKQI#$huR0OuK;FEzwn{+-1BJtpmG3TvdqP zabL*%++5f0`8J%ST)gV&h`pIYfn&VhEVvh?N%>gs%n_7W4dC15BS;LXNb{(Xk(tRp38_&bcZ>BwR%e^IoiTMMQ;@?W3}dg(iI6 zQT9%k>2*+s#%7)ReR^BnX&kYQfx!nP*E|u7jy-sHgkJ?Xl>d&7Th>chhQa%^ZS;8@ zhSH6bu{fnW4Ar{ME!y*79+l)~(V2sz)H4p+`xy?SJb)~9OA%xK-0S5XJAeV96dbS~ zqI|k{rp#_DTII7n9pjXq*?Wc)d1uW4sc!|r&f7pYuVA;rBLtn@8Zv{9=h*whFVl`v`zU1 z@;yp2Hga7y`yT%vPhkPkTXKuI4hCX9B42{}36(K#oXmL(x?f`KMT!xJWe8*BJzsG} zu#4yc^=vIpPSPmKQoQa`<>dL1e{tt&di^$?0M+6IsAs>7*>K-l`!4#>$z8a=AX0Ao z7uRt|#vSiiTYKYu?YoYnsmS@I9lg1=FH2s4OfJus5*;XbbMEKmcNG>${7`5%nAXfRO+Gc<^XiCxxB}&tnJj@X52&?B3vZvTpmhtn`#RwE6TWMs&PJdb2&zxmOFR zTUy#xq^*7lvrlZshbCQDq}5LnwSAAHKsvuarE;jMuZ4&JWbe1{aoTyRlm3mFoHdR5rB-(d2bqHn_fD1^>`@?d?>n%93ie zw^P3#M-^1tpUoz>@)zyHQ@p9!Vc;V1jF0Y-qV>HdJSu0|WPx)+0G?0>*?c4Un7|w~ z0|^Z6+}^?OcFfXI!@?%yvEiQgJDp-M=#8ZZQe^#pYi#U07iDTe0d4*`^KBppxxWho zQWUf1-yjOtT|2BSFd^u|1dZib$ei7{Ep+Y?9B+6*Y~;*fsMC*R&Bz>{&(1MP&bwfm zIB>ClH4wica0|B7Nx(0ZYxx<<%b#Jtu_&f>o(;!NClf+qgVC~MJsu3h_+rk~r%5K9 zWMPdqpqEU-tF1cm^ z_Gv%jLV>4)>YhJt;u20}cbEbzV_%07GUh9h1|`_0P#-7xIoD5@z; zOGB%s?JLE!J=9j@AsObuEV_vHHFB$ugon!)>m{>HmTmvfJ=s_&_3N4P@-yB0ySX9pM>p zTOmG$(5gkQ5`dU-NC4W?oUxwW8qdR;`zhj*B^wajGr*r40+PSVC*MI$TPK?e4$ilX zUf0pxa904D1{N{>o3>bXe&;{*^p_=<_-E)|1RRldgqz5QEsoGu%!W46i9Z}>7Z#2a zK7*exV$f*ka}Xpy*5t^S3hvQ$QSlU4`u~5Kz(y9psJ33w&75ob>qc!`0wR$|N6XIX zjinzAXo$>+Aad`Z@=@DIEyATA6cU9WbD$3BWhxYpe~4g;rHq<_8Sg^5k9T3i(91Qt z3CEaZ#x0zwmtX-VQ!idA6YkMoM)1Lj zx?23d?7e%CT-SZy*?s#t)7>)-V1Svy41n8BkOC-BgeVY0k>I1-0!WdRL{hRPx%7v! ziK& zV_S5^j%lw!ad7ob zWwAR4M8@9D5-VUn=%2T_Y8XViW9w41D@=+8*|PKvr|2q{3{8j9ig8Hv%nW zvghM$2So>w`NZb+!jZ_?+wDXv^>$XEZF7ngM=J(|vfBX0oVu%t78cCN8dA39$3w2H zAv3I%&;+4dLNu->8C|sE63wo`P0ZIkM^G_>aUQsJK`92Pf=m~>kgQq4(^^)6NJxWx z7A|~Y9yQZxfwVwHX#m5_14{C)M+`m*VIadsK7_$Kt)%;zPQ%o*o#stzaB1EqYZiu) z*Mk$j1jtE+Qm#Rq}K8&@Sfid$_3CyMxHzj+HaATMLBEVU;L<$z6;{kUvyl+Yn zHy5ik?jnc-0v^PRjf4%Vlc3LeXOX1EF{cGYF#r#R8hB)I$PI|W)ObjgyCJivoNb(4 zR0oNI|61rWOMs*=(l&TG7|(&;Zl#|OIIWL^Q+6TJt1O&y3ehD@EbqiU=HS$}{<~e_ znW2gDXNJZ}b=jc_URyo9m|~!_f?Ul}7-bpyU&EH*WATJ_>9{`*jbGKCaj$=RKys3k zrx)VsV__A#+c7y$1~Ts`k72dajg@YLUN{Fq*Y2bylNSjsIc`4=|1v$c7ooPoxZbEP zbEDH9P-dl7`Oj2A-*aD1;(5!G=ZI=&M+i}L# zoU~lcNz2uCoN;9b+7XNra@ro()tt0kao(QNZ_Bg6)$(j`wLBYKaoXOKTJydVcBFk$ z$z%PY=kk9FrSDKcR4o%#REAc@<-s%9s-1(eEUPH1ih}PvCuolrK*h`u^MduSY+``3 zS2Yq31*fz_rp5cqgTHb$M3-N~|8zA}F29C9QDB%6XKWSto!$Mizb@HTv*NVhu3U$( zU)gB~Rcu1~p}p@hhoH)y{m-#yU#N?d$aGlt&SL;cXGSA$n4ekTX4YP8w%(Oy;+u?N z&U2>EWr+9yc!O6fzkTEDk{jws{_gvZIt|kp7!jvqTz*^v|Pg3_+@sov-PZnCOpDcS{6cFV+Q6Dc!tf_J6CV^u-wTbt*<9;!EqvfK%M8=rw z&_b;=o|<`HoNcgQ^}T1LM0G!|mACm7n6ce^qlIo$!bo4(=U=jY{)2ja_(9e~0#M3slV` zfIT=aKWq_MwILL$SGJXrjN$Sy8ENLz?q_>U4r^4tv2mNmQS7(f< zv&^Wxh~PILm7uVL^7@S>p&D-$VaNK)TFTv$U5yU9w%*JGpPMz5-o=(cS9;l(?#gt| zWH#TJl*ZK;Sr;?$dWwvSEAFY^R`Tq#+Eed<&?zq#9ODRpRjF7R>sc&lANYpj3eH%z zn==}f>T09DzsI2@M~CY^l@si0&`-d&Riv;aMbU)tR=~}klv~4J3<&`$?pE9EX%Mg7 zKc4NC{4?8!QyTIdo;W=JhLw4fpZWPT;SJhS>@rws3;-4X#&Lw{H;$aY$CiV|0C*v5 z%t)#AkIHN~E(^FK>!d?SAra0vd6fiCZGo|XT(r~qj(lNalpZ$+6FnUs-q4Im2?YWX zxvT=mK*c$>+ypVZ9ubA0RS`v^2d)A!|7J z2(F7ugGV+uABxVc*fW0ew0;hQuRbDRwLJJ>^<4GB_FsU&EkTju)~vy*zNxPBtfHv7 z(tiC$ZKaKdZ%$9t1ummqSf@Hy1>dj*?%YbNuK~?++UHZZo)aMHHFd4G{+4KCY4G$j zB#a;k{vkEYZ^3Bg95)nlmFamEyuE}I)IZs9Pc&*hDKlC@4Cr0yez6x<*XeVs^>dYS zjgxue$~t<=;sb+2e|zxmAEp`gqXvrLsKb@1q1r50Bxuyrk32U$>fuNOsdC*;F6&i7Keej=HKbouaNai8VR31Aj zl{l`^sbK3`7?QPV)IoSOkH;u3i;%vpSLPLD2c98%C8YV2|Em(sUD!98HQ?!TW&`?u zoN1+ADb`g^d|l2CPw;!xkB34}$IIF8RpzC@9XPnC2(A#6z+jMh&vclKI#-N1>W=bPo;iru`Y+*`FbkCw^p zs#otV_YT<2`^vq8cJqO9?~vU*R_?`i^9$u(&u%_g?)B{kW7rkk9EmvE+e&&I_r9MW%8{r4D*PYg+G^apSIQXPOQ$KJI6@XL@Wxfs zUr;~#dsI;ruU;I~AHY!43Kg8~uG0?)LXuVd~$@9LrZ~ z)V>*C!2`cXgKCKqk$7|`(8MLK69=`do&wCv@#?*5Pn7P*&#QBE2Q%v)Dj*n)iQ;Q= z>4+&zj7lT=VFeUCu<9m-w2SM#rjtTqSBtAcK_%+>9kaR*ji&tn?7>(JQ#&ALWnpuIqLVVSp#+8X<=`!dj5x@7_3N3xc=nO=>+}lB*@QgNBmUm0C+@a-PHpl& z-sdI^0)y7@I=XM`qF--`8+S7|?gRLaefu7&$yC_a&>1+j!(8lg#+q~7W>c3lHagm( zYMQ&IbYu{{0}k15zYdj1GGy|D(Z#I<#;a2zisYiLjr*Ut2t46~*nM&^rY zC#s-e?*+w}@e;Zsa38x=QeuxY-5-kv1n`Krb50d63HNfSu?KwygFy_$A;-*g|F}E} zqP4`p3gZK&y{QDyW)XX>0h@8SUlalY*NgG;ef=7;r-#aT(R4?}whE2~matHG6}l3o z9GI4spBG?qAVxv0XV4Sy~Bkwy?C`j-B?WVK^QCwR(wp1zw*=Sm zTmF`5OXi`l<*$PNx=e3M{Oc^{wiS%!Xgt6?+e1JkAiR4ioPH-@WIF(PL>>DSR3|Fv z6k$5(3A(+MF0AERRsmu1((vF0Y+NHhNN*I^>OX+`NT6YXfOG^%S2EO={i38I;VYyt zKP3t!!yeLW*bI)Dn%rhgO^w@(N#`^*^<-+Qqf?`^yO^5#1AttZ8bnb3HpFwV!?>w| zaLcp6qq3+#%VwrZ-BNPmeQ`ZI9af0`N+f*t5$(jmKaJJFZr4+S4hgB-)&k?TY%>x| zL_*Xg9x|YqG~#Y{cbi7sbz9rEAF+m{@zNt3Z+|{@pKu~@aG%)f?^9CwWR;N_{19X! zF%ahodBpU*O=WWbB-epH) z?!M5*?EKfsn7t2s>M=Vct%0P#KJ%8KDSQ&GS72~FFgv8SN$@Qh{yD+7WIE+wN#Pri zo(SLL7T@IxN+!ZPTHUd?Nj9HRfJd7LcaWpYXDzPV=;>{?Ljfyh=2y7?wp>j_6*HLo zOu3Z#ivkh86{G z26`%W4Ep*y(1S2yV2}aoxcXm9Vu5nw`f9MjAB?)Yy|KQXG)N1jpq)?D)kFie2DVjQn`CcbE z<(^C5sdw%{QlJ5{42+@mA)7U07OnR=LGN?=&1=0d3+QL`n+CML{kkl*Cn`q^(CECD zc9zXnsNrnDzGT#r(j$u&zf7BRPf&2B&G9lmj0m@-hPen!&8dou45ov-73jYm>!x^>K#AgJ%*R9EG#;!?SYx3Is zns`0qHAY`exJV#65g`hY)EGRP(WOV>nT?MteFL}GiQslo1M{HBdJE)U3jszv9S?Fo zBWw^ad_uB&-0<#Bho>}1aAc{}5--}X89ThYcQm{o-Ew#w7sc>yX8@YaL3_;b+8W+# zwi=$xd7em5K1JH=-0<$2JiNQJ!(-nG7?l?h%{2!7KoG{JvIIp68@|x_ymdw(XRzyi z65%-y-3O={9B(#;EP69f9qAU-m7yoxV(4M55|Zep(|~|jdlbQntp}mMj?FF@l*Doh z1X3o0u>{igVWAX3sJQh6GIRvPgt{V%k|B`1%^8S9AXQN4m_nrq%zaW$Ye})ZJ7{%g zJt?1%MlC1;vDB&Y@anSAX+e!d`Ydz>c*R(dfme}8znl^Syr!!qW##sHTOpQ0DM`+V zBZV3(A$D0S;biEB%M;^FJyq?9_l&NRF>P*iA-Z3Rj#CRj=E+8O4$frvb1 z<^yTbps`P;ARI*IumeJyZ?||ABsB3WL1FbA-WmShDRmjpZVYD54$i;Y6kg$hxpD&V zgd%m>J1+6nMo)D1QpEORt*$CE2ixX`yXPfNHY#lpT)RROYM>z}e$$eP`)}AusQyqC z{fT}>=O_UylmBSl6%-Sz4VJ|Da3Gmui8nm@1~y*VC;_jAIr6+8QZ`8V-#Vp&3}Y;` z*13zQWG}R2jIgaKgq9Z=i*#x!q_n_69E-er3l=#}gm-BaCBhre^r;kI>!|LXDb>x$ zF~&3R+K%dK#rX?{Z)g+r5d89M#Q8GLP!8>JYZS=lixd=%+Dzy^4`o6@Sq+)+3M}zO z3R;Fn3-P=9fM(f9=?u%su><6Y##QA!3K z-o~Ajku?^nxrA47D)nn|l62vRJ;D9-+|{pwbP)`AFbywTh<%KaEymF?mtj?O%!Cb} zWpztBmJ>F-s3F;(C6>_zMN#sOW+#Xmi$zfbi)3EZfUQfYM5z-;a{S)Jh~W2;dqq_y zl1GhFirO*>;q8(O^xY&+O6o^(z+(dbU4a#P&E?L}{~&#cXJ(`iT&4BSomuIlCP`*& z-FJFAKZxXzCJSUk&mUbz;Cz1T_kmI5A03ieR7}Rp=gE?Awc}YAR z^`PS&Ew?AGARi@wG%IyQZY16XCyY1i&vec>qkh)G-)x@=!b5Gq!KlzRjaFgo zDJUcGFLgheg3G*F)Dv*=$6DUC4Y+`Cq{0(|UM{%QGT?H@$mG-7wpHp7v2n0lnFv6`})-kk1UR zppX%0_O!#8MbMiB6{#-!yKt|bw}*-fAePR)QlTz|#KY~6ErIpUK+?hS_4a^Oq6f|x zF*E3^0iyR186DTazijqnlFv$yoBtXwKNGua>wMz)tjXGT_Pe%v+OFNww6kDM{;X z4!*QYV;l$~Gq!K_Ac*`i4ghPNTRZ^Xk_ABD%tRnWM=QdiRDKVMm`yaSF0k3Y+1O); z&552pI^G6$_|fF(`Q?%-VOchKKyeisZVA4ociM{xC-Uy}o|_X9DGUMp!PV^LCGOve zZNY^P=m0cH+yus1gheSsy-gU*(Qd{mRBM~9ivDk70FBUD6#jPD&+tSTJaG zztj_)AkL!>h(eq{M|2wZl#;?6Zk+)!lP zdJ-&#p=B^oZC|1r8H*ur3l_tU*$f-bW~k!?%tqLZJ7>7ZX4Ih>$?b(GF=U}#367cY zwQDSn;Wo+G1PeAWoBSkF@w?k5XmjB;$i#lEs0af@_8fYr(nm_-A?7#|zCJ?eIy5Gs zGY&INq$HxwMLY>XB}uTaT3{)50~X2pc%K6IPj*ieup-_gv zC}{KHPRTyld)GZP(6ZkXpw%(2zz#P1B)a>Tlntfi72JG7>Xzyn< zOA~y&EJ;)hK-!bQn{kvq4&Lr?@b)SXZ+S<&8L&~nkk7`+D~`kT2(wpkqt=Y14GNbQ zETEk33+E6Bf?^*g&+Yr8KH>J-lO+PNS;_wTnkdwm+px0 z?aLFseNzH`Fc+*qke1voB!>u2j)dz<$J8-FvHTtMHrW7_nyDdRB7F#0_d1Ye-N|;X z=zp#OWJ?1?&=onz4Q^b(FDCQUshwx{uYxL#SpHtv?A}4PW9I-mh8QE*CXU0`iAftr z!4bTW0y7j`xP#7PG@G45TSIs@{ODT);T{2Q&Z6Ly^UxlwuoSq$;aO|8^>Cj?yG5Yw#RT z!AX%8_a`W48pHmvC^xDxWTiw$k0pMYte7~9HH085E*Xo=#iea2D@thyQlKda;=rek zA#UL;{*I9q;bay|KFpI>o2hic3y_^7ua0kJ$Sckv(}NT8nyhn5T)zi4Hsp-s zDJuz17`0t-OMlwo#303qjQP<#?86{6vFq&tHqmQTU5rl1vKhM@En1X@vq6O*4%b&S zP0#tQh#Ap?*)?nMW#>M2RTxw&$Dq!#TtlG&nMiDNGl1C3!#*-+01c@P9x~h*JOgP8Sq4&TikO`w~;+fks~Foc(RS!2MYZfp1&(27pnh}Bv!e8p*$y)#G-pp>MZL+OQ6ZR?@yXfT|2@cBodG!H~C-1GlEYEJ5 zv`W;&QI=E`i4)X=lLXEo^)16342_&1BQJi?;PCQgn1hp|XA&)|sAF*ml-IJjv)CK$ zKma@gYZymLugFuKE5=eCpt-;++>*h2JY7Q3EuVvF66AQRF%a*+Z}8Kkzs%U>c+8A_ z=M)#pI+o%RA-5y%$>IFi54*7s9mTz6GR3_$jM^=?1d*%>z-Jwq(z={1wo-Dj_3(BN zBHo^sZmLz*9f=)@B_!iLa&NXZG+&vJE;D^xId;G-cER)!hHGf5MJABYFR~ZHZm}gz zMqF6Z;$j7+y4{FxD~>p0`_W8jyo5aN!1i-hvf?%YSGfroxD~%SUGc&Mv~LMhppm)! zEVO;|H)YhfPBCiYI46u62KAEsD!;@H@-{cfQRDL}?s@+5%5?ixl2^K)=(BUS{{^sV>B(f`*Lg~oSq$39X zM_os5aUHqQcVy2+XOK;$7qfoel<$n!ac=Z7Wr#lUJ3KE}#}5Vuj5DS#<>6vlML(!k zA}`+xML(fR1;H|To~UdSxf6?Xb+R}HC0CDKoGm;OMv%t|m0Rlc(6Y&!*KWE@onGHf zr_<9s7ToqtgY^oxi*krI4;EZ*%ZDXp^chiA2%?qq=bYSgrn;|c} zavHFHwaYxtjAev0IF+B+Lr-<1DgVHN0ycO)w5Y~a)+VkbZ0Xu$khXBwxD&62#=|s9pMNqsxyGkzn5B7UvC!jdEG$Ad46TB{= zWO0yZ5(RkDZF=5Fj5CSwZ-&JUnJTW|3Lsye4AlVgnDv}1gH?3!g%6PcJY>&YuTjo)(;ND|*t=g6ljjm~5sk-^0>f7hhS(0s*E@%vBG4VE42Rv(k|y zDJHjH(E_QNaeJ?0x6(tp39O=yF>{e@-ayP6DKX1 zTT8!Wg48is2@$m_u%b9QJzAYi+vKS(|QkVBtZe+p1nt!PuIgoDNM-5;f;L?~a;b z9OTWgQ)i5^xYOHmPLjSi0Q7G}>q;FMph_SNaK ziOgAuFUWK>%6s1w3D$4@|qi;i0roUGE)=TaWuvq`kHWk=IxR#&H3W(Zks8nz@|VVOm^rU)Cl zPC%^McWkGESxvT6srAdTQ{~8Q*oPIlJX+)SVYRO-%+1TE0g;zaH#aX2L|v=B)cx>0 zv9Km$q0utlhs3e<;*PjfBCEl2$hF~A2@f9D z8kNJ?uM|U06BcdQC=7cvu@pGmzA~+0`dJPzuQ{Fq<`0K;O+KP{s90`hIW!?^PK*+0W2?m&DWzAv0bq)hwmddMz zu%GPuCJ~e`^JfaJ4nCn%oI!k{usbG+sDKX z@-nbw9b+;)*~?3U2U~a@5T$eK1r=m?$|RL>$vV_jN&C2R$vT)ejpP8EeK^tdAw{sO zjuPo%?3evpcV+sWm6mPF=_nHFG`n3&Fa+CF(wExstoAhV(6T1g;+9T}CAtg9e(Kqh zVkFd(FaS_v(F6E?%fl*iiK2{$Cc6SW2)l=*YQshWW@?f%iK2L0NE9X1DyDpJVWUJ6 zDQy%KDbEj}3Q8h%E%QbLW0FY0L84*~kQ+QilY~cRkQ*FCzuZCeH7QNcm_aOj_GM#X z`Wm`4YoeKC2N58bm|TY3r#?jPat-Rc(2&cTTbyH) z7w4Mn;v^wS$Ale^aDcXH7R`J9CdL{up<^fdnyn}L#{5Lz=qCDFH_zSt^~=cfD`+%)AH_!aQV$d0AUEhBl3U8Z!Y@1~P3eYDLnCtdPO zCfzy^G=;U{rQ1lCzV4UiVRUSkQzua-88&7He_cAGRFwgYUp#VPyG@t~ho=$%wwRq$ zV*wbz$f!rTn4JWKU)*zfI@tYOrqEo*1PKu6LHN;h_dhJlD#DcHEeV6G2D_57Bs_8& z@8t*Cj(3Vpa202rV&4W=@pz}$&Ql}Z?19+JgEu=MewpKhS5M@G&yfmmspE^zU5<{g z@1~=|G_Sz3mlkyVtEZvDS8qdwece|FDlGM#C}TUa5v32LH-Wg{BH&D!F3%_hDRSE1 z#Vn@S@V|@9%;td=LMoMrcF^QBEqr8rq+_Dd0}i>Mjwn1-{_TU>cdXjXPa{Rjs+1mP z$^oh4pJ@<&PX1^+QiyO(ZqcIjM7ZQE2d+6%WvjVO(r(IT;7dr6v7FPKvPXvorS?h~ zq6{T%&Y+#(rsnARjw!Y_d?sLK@P*RZxoWvqE0<)0oEiMK{~eVyjDNv_Bh{9Y6VQ*R z8A;`wl_3Gyrm2_qLe_nBMT%U~5#{uB*2Yp@=b@_P)Dm(O*fY!>v+J!M2Na{Ex<{Bv zOkt^`O3u+%0~(~VB-WP=&GJ#J-tvAut>_(gXxLKN-C>0JR>dM zmchOSjCQSK>vUGN)?+&R(%`146Rk8pN<2icg!Mq$KB+hadzJOxoZXP_eOKI%50Ep1 zGs=gxM>r9^e?a#=o^qObe-FuaNhL|Dy@lwuiu2F2q4R*nJ;-5Crg2XDvdVR?dkU3t zU#x^U_>Yv%_ID3%dJTuhm*d@pOFZ1)Km0un?)~rCY`+WJF{i5UA3nPI(?9$W8ofQJ zQFPD4!_Cb{KU}g09ugMM&drx=l?wl_R%(@qKj6DLcz5|MEnRm5rL(qWP;Z3vU1w8X6aF82tKodb7)Q02+iv#3Q&WJlq?6)%vjS7%zF zqU#i%<>Bfu_7AFOINyDbEJL#WE5M+`huLXTHO|iRpvOYM9T*h^5wAkZ^GyqCnHhYR zscQ^&-DTFM!9yP)6)2Vzi`a}Rtasz+kWwWwaAJnOz+OL`zELHXnjiocSZf zfHN{1qwFY3>lPAv065>yBLRc@>1I&o(d3B0;56rnE0qax*w*-dOCnv)%TRNRW6ak$ z#(dN>=Dc({4^vARGqgyk_G0>Pw^>Uzxc_+J9A`#2sS!Z@-O}wV&MFC9eYSLle}A)d zW*yIzUY&DR$?0Td-kp#^ zXXuS|jFwK&P>LF8Rpf1RE(R`_AA}VBE<=b*6;6hbJtG-H93l0gl}G5*D2BnV{$_45 zgQ5hy3tQ{W$xjzO%A;aR3Yp90GcN5UfoxW*v*g(7x65@u~$TSQjEiI)H_j*OQo@c z$&(I~hZnK}9dfL*O`E$3w33xuVj>N8{1W5$9Cn8#x~8t#g68`WQ&7~ui9#WA1Ms*BYuEK z+yD+amQugz>Z8(RBJa)LHtqIPLhN8qrRQ1(r8wQ2cGnLXO|b*Jf%4d zhCNdXn`3;aHgpfEKyDhx%3WS<_Y-j#fqdd#R)pBhiRT=oxR@u zv1I?eShhm%^wt z0-w5j_~frVt%UK!Wd^gsy)LxwimW+ca^Tk$IlKu(ufHS0F#VC=hqpNL`--gy!^aEr z`Efs=SGxJ^O(qQeu>~C7qg6H~V!2u@GEBN1Zq+ojVVrI~L_%+}$zwWC}{Q zz2lP;5h$Y#B>OwsTkr4anR#Sq`#XBlJf_O>@7;Ewj^E!A!@alN-=P$JTg4yxT0xX7 zJ$w<^#>sIz-AeSS0tesesLUC$Ro`U^_GoupQb4 z*nF*r^1$XrxPv?4MuX`^DUJvOZ;R_WXp7k%n#hOH^*P>GA8ox}){q znWTAeiv6Sqwt|Jvq=PkM$!Gjv54pjvq=PLQ6jsL$cIBHm*aK6D)vH?#_KCt^pYVe{ z=mu;5BA1Ltbmv`ti9))6M}yt`(+|Dtyo{6_e^8J)rGozHhaNhQFDsaeR%I&U(HIQ3 z=fd)ptptRL(FH`wLLE4zQ}$}aC{u+y80R<6&wEJ9rTdUs!--Sc;V5Qw+}X0{Weq~APE{*@?`&F}bc1AQq0X`w=A z-(=#kICgCNUP!jdFBb;?}A>}k;~FhrOCF*ec8G88-+6D*&kkf9x-n( z+ek|~Jww(F$aV4bw8W-hdnsgu(`JfbptmE}abaeR^ueu`PY^L77B1`E`qsq4dB0jA zm0-qMHdQjgucUxrbml7_5SATV*qgA0q7N~WgbbXpUdC?bim* zKElI)BP^D8nf%617t2M9ex|I%yw1(wvoG`0MWwjIiEY6Szqnw}b-@%&!9tc|zhJ-V z7i`I4*TPiTrGr&juZ8%k;nSaZG9r4SM1)u6VYe~46i(%odG~R?*0F|DO=#^*yW46swEyc=lzNo zH9026+4E#!kimbS3&@kFmK~ikIO_w>5+yFr7d6N4GGhMxMo*&5HKkXuTZ}z)l%_J8 z{Vmrl;(tu12^;v#BF|jQONEvZVyp^wo>7{Wi1%oUpC~g>3w1dX{Scm5c3*3(kCyw( zYn871c}?j7mj}6D*W}lvOyoOuYTM2YB3eP-GIPq3jzN-=T0l+teh;Z zoCJPei13W~5Bv`4=WP(rIdbNOB%(9rV~s+1xRb~kW<{tn!t|I^L9cS(boTmL^kVg1 z-d)3*3Xv>R2Yc{oXd3ByubL_vFC$E56VAhJ6a6y69KKqhHDC2`vd__)-5wP(D_`sE zi7t4uZ}C|;ZX(5iHP5UoaM-v7&puC7V{I_^ngR47u01gL&^HL1R;;jj_9*|eL~}L< z)w{UGxkJ3L`N@9#d}|x)p0j}*u!GGX;`p_3N2e(IVDH4}gN4kR6%BdgIOu;aOwxZI zKS`r2-`*1ho-*V-i6_Y%Y5k*FNnsg_G6BEWeDJ`w<& zCQWIu?CU%b_6Q#+=X18~Tei+hA zj8H67$oWTLz0@B9rhCM|h}sOE#UjrQp+(Kagd$_sQ=v*>g%535E-h- z=0Hs_+5ytA`ToqhvtT*k7sHf0ZwdE63j8$>{CzlkQx0uaa{zsVJqI(^XEZrE7)-c1 zq^S2;Rxyp(?~E)vnU?67Y&Iiuq)2|@BsvsWCRU`u6NGqf8z~zUk^@j20T$CJ$WpEz0>m?0`EBb=8dWw{Vf87) z!x?fRSUi93_sH3w+09!n1geDXnS=*UBMxUj6}R%s(LU8yeia-SPUhnvM>cQaK9Y5l z6_z7uOzyOC=XS+(@@XA@bwoA`5#=}tvvfJ%~?A|%f!$DDt zlG-)VhBpo%{!0oF=FIvp9w7EOfS6AKqUg-(5~ngVC=;a8>X8Bk@y6!CodZyaPDwB| zb119F)QN|(CRpmsN&!nD47T`3qPGwtI)bHHvr-02XCW}6dtj;PPskagy+X2U5%g*M z)cBD}xWQW{l?Qe?)0=0zlM2qW?K$-~I0Ho|*|_0E<3xa(QD^h)Vtz;L;tv8`k_<@u0{+0mFcoGOCL_M9iwNl>t$ zWHT~%VPaN6YLNR-za5Ub(gsl`Lu{6j8h)yEZ@;D$^sPBq_mKkaG1L~V-i*%B+guQH zc1c_^9v8&iz=K@SaQy+xb3UjU=yG+&uO3rYY?#e$5@M!g!~Zp%SEIWB)z9m^o7XT> zcu$e)w!=F=el2rWN<$VJP3)_^dRqm4c^6a*ijD{dHW^XJq!oy|&kxh+NZJt=Axvg= z<$+~?GxrQJA!98cvpdwHzm~4IISsz%*Sqc3yEzt*EIww2E{J3KHQ~&`uqI;m7GodBt$xY^OLhVDWG^nW6)O#s`UpnZk3wtzlCMM zX(e*@-~2MP+%h!MW!NG)n{B$2VyK;`2Kn-jdDfDVZ>B+tM8w~dEH$)dr%Gd{ zN_8ZA;gi6tW9Y|D2{(PRB;3)PO-vrMSO)6UU5n?tU(()Jj}8hsAa+YBA`zy=BPNRb zGmpdSr7#^Z3KXQQl^%^ac0NwrKain8IdMOXotC-vN_isg3uc^@xQ)24f)e)y^0ui- z$pWl{S%JUsCT@AfoE>JA!n)AbJTv>&$rACcdDRZcUxZZr-+)DVeyB z7QD|1&Qe1(N8zNS15V+U*F^yU@(0yjnq-OU<$<=z^Uk7F>z%rRlG)~C)e^GxvWhBR z1#_e@o4gkH55&v&_GeXrUdQ-wEXKH%XwP+}i<16q4U;v}A6Ma}3$P}1Tkxj(SyHn8 zdM*7PSGlxyC(O`@B>>J>S`8AC8NM7k`XNcQL37`|gT=EewfW6u@_cF;O%x@Z`v9`e$Qh^e_OcVzGrcpmuVT3L^>W8^< z2h{J63n2W*9)xEc^)sI{80SGatdflEB%Dc!V7feY03uk&MF&;~D`#bsx*(H>=iKm> zx(<7&FbXX=2I#tH+FD(S6$sws5kos{41TeGZe3!*GfGcl<>6J5GQmwbur(;}>pf z$qkLcQ=EW)iOdohRm__$@5DbLdBr7?;y`EFgm#XuN^g0hgnoyspP*M-M*kkO&uq)C ze|@CuUr*KxFHsPTp4YB}nrYYZmtIlT;fq?f;)1kr>sc2ZG#Eo1_3izI%PhmhiRgpp ziUiOt#-eOY+c&{aU%DgpPq185x(8HnoO^%+kD6ro8gUO?rU&n-6cbHFddjbC(_v!O z%OQEOT$*Y?%8Y}+aoq(h1(4_(7`bx~o+$Q+qkk(8oo>^kCyk1^p8qsmf0IN1)USWt zt$&CQ%CCQx1iJ((?)(P~aZZjiqm;G+RI(h{{3`ug>QPZWf@BdTqn|;7VB^{C=VZez zIBYVt%WY#ToC1t@*@#?A21QLTG==imio1ggf|jm_>=hiGhf8sHo@`jXxhrZ?v@XVT z2;JPfpTp|LT17vlgYCZRJ@*ijDM$uJx1AFNA2doTJ&DKIk*zGgQ^)}p7% z=_Ec~)+`Q6t-GW0`SOJ;O2hcUe&sMBGrg)*zPKDmXtb4KbE9ACet0(kQD(;Ph$B;2 z;!^i>Jwn^C0>FVQZq=%--ymVy`6#U|si|Z&Q4iR}!)#UkvMC$1c2444nH3zA<>-U6 zN@9pByk7zdRgNoyy*_XDsZ-ZCDu9RELHWkg(oiJC{x0+wORI;BA`q!GeKd=jv!06-(9fE&Td4*UC#3+wO@H6cW0YD*xxm|S$9g6GiA{acUV=nS&|1P&F;2l zt0YkL&F&s;mMKuaz$|JtcQD?5-HrHmS*d_|yrY0(uC}y4!f8zdIHhQUdfc`CSRHO6 zcqpug9kB+xMtW8s*Ru&z(r=_aYgo_fg`PRAzN6oe$wob^hMqM-&s0a~nJQ_T^F7R2 zpe4_8w#K-gH8XZcTPz17qdn6h9~n}FQPizr(z9gFCibk$aVhDXWqQ^a*Rx4;Hk;1b ztj$@Y(6ff`+3d)i&4xKs9bwK?NmtQrwTrNh1Sew<3+?do5R0fBH#_tJ9+pB>8ClXp zRN4m~(w`;Bvd3(YYf{q_X2s2kaC)?94>H>{9oL7Y@5NYN&n)ua|6YaHG&86Y*B^Yd zO1_z>Rn3@qUN`fer2uD|8!dQyn9Jv9CLvK_Cac0tS)8jy+!TU~y*|G)Sqe>8`@ZQ? zXj)N74v@-Nsa?}?Lo9*5so8CTad)QKU7mg!rB|~BO0Q-E)e>{JzY9dNOwZZAwUmBG zRBMC>8Py8I+`K?6bFx4MO1}jU(#GL1XBm3BBT7Hgvq_X544jrbPNeiZ;*KMf-ne6C zoPj&;h|*)I`|hRmB8^7mQ^y7jqrO#3SjW=#b>ERX+W+}aZaWdU8s^4_LEzP5u z%Bq=h2CCl-v^A0Mn?X)g9YI!AB~7zthdIko!yR$TnY3p!)-%(IvbA~8nF&2h=4>YP zOm&2wsgiC^C(6_{mLE+3qy7lhpTv)LMD>YUF|Ysd)<-ae5(A~1cK1i3xJ8m%;F4I6 zct#KF?&0wb=wve#_a$RJR7qEeF~>S(f$Nc8+pfonO4aWhIFvwFIH6saIFUfVOBj@O zZT9AaeEdzInx?%lz8cPIQfJn)cwk11xv&n$vKSR!c!H-%=%r3E*Zu z@9T9ryTc)N+#T1036PoeV1KG)O{p4mopQjIvufNn*t@U43lFK_>%RVOOj2_OeE0RM z>+9`Wr=%o26x~$r=CuTfeC^_}B*k*2k2wnHByl9_NL+qBCUG7#i^%%_vTZj0QdeGENO0pCGEOgmNb`PNu4Z9nx{Jj zlT(fp8cUkg>~<@LDwT3Vr~i1Cq-F~&NzDfGnjzIYBCjJt^*7Vxv?G=@(z6#85$w0l zU^)SeMp@GHq=-D<9N>jxZAvg~9Q~bMQOFF~TV`g1Wu|Ceb4DRg_s6w5Veu2Hzhk1G zwFfy>s%TBS4+ZN2XZ1`^>>-~uJce=O0;C%C>q0{4C6(|rl5lb%A@Xh5LK|Y=#!+!A zrysrB*a4j2{Cz8NX#-IRM@8}+;XuzhBMH$bo`nZ=;wX8~+0O2}XanX^$vm&P?(`N@vS3DyxY52-Xzkn32x9(toM{qkFl`h+P|re$>t~ zBTkPhGNT+1G-foZ*=+%7v{}!L)NFwnxn`elacMgF@OeR&L`eH~iH6&a)l4Ez9NaNk zKu&A7Ge9(*5c-LF6ITiyj<5Ff%Eyxh4X9|ousg!3GF8JtgQc3U_f zmGwNFtJwmayJla6^XVM7iIXS6F0Y+$q4PagILAwo5X&9FIg0nzaNZh$^SR4~b8sr@ z;%pYq+oN!vLob8#NzHBx=M(9ZYuI(~;xutWt zaGpiQnJk>k#8ptDbLeGoKB?Jl;e3>hczUj83vlk5eG$&TbKx96*yX^vg2}g(TNLAw zhx7L3!a2Mn>0&br=Y+Br;XH?42IrHS-4@PA*@%a8HCupl*X)aM{+$cw1o|aFv;%rh z9P-w1-gM{X&TL>HWoyYeli^sy+yv{!XzaqahPlKeGsf5+qSP!xVAP8>)|fc~F-Ci~ ztuZt4Vr|hgi=V@Nq{zOEuV_b}zY#CiB*R?Bi)Dr)vy!{$p;0fEt>%t3!d@vmjL0nh z#97Msr&!2RFDk^TVcOvN9esQV0WN*tO2LSgh8JO^r*O9y5lM;z!zgT^v%_28Lsa?j z=J#A=11CO(TeykX`aC?vO_Kwr*5|sVcDdB%FKSn+rFN|ZFUOE1J4-W;x*y#wH$eFH z>x+Q21tn>tWvT5%c-_VkZxE35>F@$gUGSgQWkHSWuV))J8?=-6p=zv7t|6=1A~0NQ zNd>e`p{Q#Gw9nd;)Qm*+qEnc)@(#W49H;R1=#&YR-GPDS+l)@lfKH8oPW2o*wa7xr zU(^DfS~czk^MdgPK>X=N;Y#@Rk=-DL;gEX-%qIm5=BmTGg75=4^M8SJ_p3c^T_RtY?#8+HvPf9he#e?| z4yu5fQ$^)rAxT_%*g3y|auI!=R#fZ5h9-*7$RR}PC#x88D8j=d3CtiGj}T+QZfgBx z64+srcJk~r`bkDO*jCh=q@Ro+#5Z#n&5H;ju<|=E#_1=}_cUteUfXSnX#aX}0t|Vh zHe?eu%s&yquINO#GK4+#2Mt`KH>~vd3CP;k&Tbst)2XzE!iV~>{HB$jA&GX}fix0+ z;4sd;jNCOWyGnRsFz?EgX$gcP0@DRM!I9{NF(<3w!SC~>M{00g(3TcqsM`@qAW@4= z)7m23`t;tYe!j}~;X#BFn{I8rEwewkdhuvfqSsZNZf!P$>UXzSvFj2$z4be0^QPV( z>9I+X-^Yk4)b#|hgnE98*g{>KJ@&PXHdlQRA{i7k8A3Azl@Ba{82nq!%UY|VYkDlHlrcS z>)QV;8!cTW(SB=+E$n5su&bIDwGziky2#j$M=sP>u@3#j&zFa_Ol_5IYm3HJR<+6= z`I+*tk*Tb@ZDrMQmDQ}WpZRx{TxB{ngn8a#oOW1szc9?YRrb;Uqmmn@j*8y8vPZ{G zTElAlr(Z4QmY}h1ZDT9rBm_X>OaHkvtY#*Sw1wMrjlH`{LsA&%jMetU*JpEGBiryc zwXvIcOl`AP+o%4jG;C)2rd$aVr;T^f83%9%BMIELtgfH=ow;Essm zZ|RQp)7WxiL3#!q+E(o^{bnauZF{R~5q?33t_`?QTgPhq`9JFncV#-+*{U|{4k4;m zDf_E6jnul541CV&{Id@=ay^{es!m8RJ#^=;_dVeW_&;ye{rgYk2Rxstjycu53H`gG zf42qNWmWJ7;-r`Deq>n5 zU?`jF`6fNLj5;*3C++!9euz^p)bl+_Ux1}XTz-r?;>rdK)@xKmVris8z6yzsZy4VJ z*C12%L$vo)X@eMkH~NLNy?;%6O|?g26#;lPohe^ZYV;9KE0JbJxQMe$Jv+m=`a5iJJ!{weW4N6R~a(JE4@lGc$?aV z*Kg4l-!Sp4khNIy16oX5(&+1IX)!-~n_GbvGK{6aVUd=`&cjmZ;>bM2Fvikripr}7 z-N&i>c)D&YY2E)R^m}Du-N&}BJErbfQjCMsRqFOq$d9m6HLcWYsGFG$pkTs}6NNVV z!pP%WH^ZW{GbCx|K-!D|!kRhYngJawF%E>o_vxS&E}+By!NJh2kS(c>h(@}Z)_kis z>m@j)bD5B9rm93Dkz`4UW0DPH2!&)r<(eVi2b54bXSmkaqF7gQ!5q=Gu}01ruFW-a z&2Vj>j80_)R!NYppID1#E;P^6$GkZEbSV`u`*X;pl4o_r8^Kkitzy4d+1;SuhmmV_ zJ<@B~^%!!j${#0%zMkK}9vJ;T)$7{zRlQwyy}P&Du5aMDHNAfe=jy8b4jQ*^w8^lzOemY5_8!CDV+TbgKXeL#C_35swDixJ| zg1hKE3QYx%4GB>8b6Z7`-p}3;bb-nZoJXf$I_FK0tR6oyJbZqGIjgq%yX+tr8T3{; zH2!ntyWmGI&qdsPoDxp7RHiCMj+(}4GH@s; zboY;W=n$cn&nlI#J;}zHt<@oYePEJ4wUXwn`@1s(FXC6+Io!1Bg!f;6Y-I>XNcd4I zyptzPLyfyW|D7ap*V8J`YQ{k+tpS+m9#>r@U+oUO(2lfVopI8F!GRf6SGE36YW<&N z{Vib{l{k^z#E##Aaa9FMslcA3lC%XJa9r5nQ+BdoaWMq2Bve^oMfh9SK}G z=t#0B#~}-%1jKiW!WaK)DW`NW-;$$thtigP zjJlot|9?|Dt8;q!e^)4Nr?ODm$@gFVi+pJ>-*-c4J3WNbPICYF|F<-p$)JRn+~-4S zJJW&EPB8zer}L$~U_KX0w>^?Osrt`8n;)f@t2?1|APG*c{`6P#b$hwG9ZJvox=pwq z{=2_k8e#`ZP}z&vtx(#G9`xHu$v;w99WN)7TGJ4+<7C|Wz{$8zFell%y_7o>N;?U> zK9G=m+wk-6TF$MG7jgk(SGR#NJ#n(?qkoj26ECd-pssWvXinbz$$zn&Q+2(>Sr4V{ z8xYmNS!X?*wavg;Aa?fwlpAvmBp}37yp)3ML7S5Y=W4S&!D-3w_zXukDna0-lJ1l% zZ?mjBC@W{3=}uYQH>)}VH!O*y+}lQ$#7ns&pd_L7wqX%ryx2MdN)khF8x|493!)>S zB*F5wVG&`xXgLB(PE;%+j29M1K*>pbMTGG(-v}r1z%mEuj1OUG(ckM z{)hR&72yM6EhbyXP&}Oeuk2_wKy^#DXGn2?)*2b^jqnCaao9Td$pSVXc5RJJ z>Xlad{ohy`&SogZm9F&2q+VsEKL=fz&y>E(l^&VYmssil31!aK{SsGtWKxe<>5mlZ zKH^G;Np-WtWFEEBMchB?N~2sjN)d8zCb)lwDUHR*69ZCxaJ5zS^96Qu^@OT8^xXtG ztD26y)V}_$r}E_RrS5A49@i1nY|@k>Dpb#%ma@%Z2X0+;TyoO8b7OjU%+=3wW?9g& zLhqGrll1XLn7c zLaT20FF&<3{Aa&SGDRm$aPZ)Yn-Zq(TB<&el$h<-wV`5V8>A%D)*O7Ibob^1Ae)E_};(2oSX2MC!bnIXj@AR zu;Ug}H98mxb9kLq`RHFRVZD2#gQt{)(}6zampN z-zBSg!b<-KU_EPtJ>g1YQ)h6lCz7fUz%3D}fz zs^&rLq#YbGCtdZ8;E)jn5?g4B7CqJYsK@nc&3Y9SENCyTLgW@?@{%W@dRDI0_#>Ca;zG8N}kn1X<$gL1DyXqKB0r!qNMb4q=G zmp4R+0&Hd|z|Cpp{}5AzRep0AoU1%JynR*&-!Rn%B<>v`b&Jgp#}jCAdV^cs#|gkX z*tu1OGH`dRD}`R|CLs%V#nnfE6gre#3o{6m$;V1i&o7M9Nj=w;4mylf0D$47)WN{X zY^|03`9EOBuML`aVL>7vtq#+E7e|8NJE;{yK`@}V$)f9!)?uoC`s}0qU7#(tj{+uk zwV-xH=MoL<F&e=U_cYxrTCVxtPf z_kD&_n50I3*v~WatI6jHc2f;!q*I-&yrGJZWU6@PgT9K7_$m-;(G1v$9dJNeZDviV zk#m=^9_?|s;H>5tERWL&=H8&jel*j_AOG8>xT}7CG~0*+r-ml2A@g~HV_g=K*nka> z4|^Ow#MF<;H`M>JO#MIk&5Z+?e2Wrzm?H&A+`|=w4i6ZUZiOrP){I{slZmx5;zP(JGhBFijWy}`g5ylam%5gWn{Zh-#b5A~Br5ZTWB>-n zHdrcZn?!kXUrhS$=UGG~80g(99ZKZJFZm95OT8Byzf`P3 zIPFdTY0F=BGgpw{_7A>X{CcYnd}VA0zLHkqhxr?Bm}$7uZ}=jKza7CW@@}=6;8x@G zgb8l7Iqz2EYDYM5wIdw3R!-th)bMH|WX{4{y;G_uLQYiaYLpT{-gM2X*D>h6hsj+|wlml(qi4 z8F7ZdsDExLAyyRAhFThOlc-q%#pH~NM_rXtCITAWcW9?sb4M_wLxwtNQLFWg){v~mPe}qC#z81 z*OPUj{qk=t5nc;&dKVhD9amFuAt)}v2Bn))H4 zxw`j5I67Q$zNq1QP`)$%f&IZH<>pQKmVH z_=)`SKaPdtp){iVfv*?3A=w76h7%r~I)XdXxoLj#*_@ibf8aeee)1d%t9a+ikNkGd zzO#Sey(>(fn>QcerS%HpDJ?l)%Wq-r$e4Hb4}e2;OCMW#oB7RbJXgg#UY;$^mG`{3 zPbHcY$b{9aU-q`Uiub{M29sIF2(f?QoiJX#a*|}lyI}t8W4rT(y${A|Sw_uWNY^@k zU@?b^_s0C=XO@O5so`q>Ac>O-@@@?&+=UZV1Kq1mqE%F zDwbNmR*Nb+zCu$@>{W6a&T5AIpdlOiDI58zN=t|qhz`(|=+|k;kC#IrKkhsjWSVPA zUD=2&FWTHHb?wPPv>PN#&v@?Ay*6HZXKc~)YOsc0eBXw59dvwZ+D4zqHnkPRdW${s|w0myjinrSrq7K&>4t*8?nba?%7I z&apKX8p9QUZvt@Q;cZ^<#D% zhK~6|YvB0_JC4UiZaZ8+P8@Bn7`g2a0>1(Slc2u}^Oe16iP|MN5^p2>kqi@}o&j)~ zUkRkmUfbJ5yj`O8IGD$F;kVJL$lE2f&ufX!>8ddF$m|m6I-+z|Vcdutr==!&p;kC_ zI&NBs`0!`{^-4CtZ+}2A=$x#oL`=Ek1oHwh0W7=`6~Qbfz;=8DE#>oHxC6p!ml zVAly<#|3b0mdh2=X2+Gs`c=g=T9jJ}p~@hH_z-5l{xJCpkcbB7!6liw0H!K2wCF@{ zHX;(2;g5Dq4yAoyWcT-b{E#^k+m;}l|H%wm0l26}0v3`on_y3HDiq0eMVeQMuKRfD zcEusV&7Li>%W%IzGjiGO@u_Uwnf61Jdc;KWnc~j$TbxDL zRj^Rc4-*fj>k)D->-jO;S0QX{*zZ%AQS|&(tfH=W6a1v>8$b|!_ZH&QbbTxFXnOtw ze&59pD#nW6Q^uKvqvRk291;euJ*HV_F$TtFOT({`c+sT;cktI0?~37)h{ykNKHyZM z&1k0HTkdxhFdpoO5jvpiU+Q65`C_$@W5^dbfT~$b zmAH0ae+~v>-^$W7NAVW0!N=`Bht8GkLJ*vY`P2sqMH! zw!OOckhs2`w)!=wsL&mnagbg~qCe@}z0}Q4QGHB9Oj^8K@%Jlz#gb%*>8{iLNb8|q zW3trf*xgWFbweg)KYEZ& z@-D*U3J1yAnigh|>F<+v)6_j3+y2^~5=Od`ntd>{Glq(hu;zoQOqmWv%4 z>5hvJOuFMKzEi%K-z~e-raK8}O`MfYjMqgvaA#nIYn$%X)HiYgUuz9uQu%#DKveIM80Zd8dI_j>>ZacbG z;!r*nEDyU6(ncxPNrTDjX}IqsCY?v_wDshMBJFidp5bt^o28U16pc6-{)s zMMV=GeM-+~WVYctE3*yPmdrL>Az^RP6>{)aUE4Z=lk09y;7mnKjKUIB-dL`%ag9ND zwU5{4zw$QmTh@m4Kik(4hoWt9l`RDLjF@fsX}|KgRzMt7u5RPDHXgVxOt#&6_f?hd z`NoAZF{+S@tS0upaz+({S{cJ^ss}Wp-(r}$N_^E-;;XJ=l)8#h>Us(Wsq3p?khmWjLxH{Ad|gs+;$gaf<0? zN}jsx@BzuVDzj7@$ylnA;#E0@d;dwI-8IE;?JxY|t4j9Qz3r#_EAdLa@OZxgVe8j_ zDPH-h_y4WlUQUkB)BF0cu`zsFs!r)$Fho*?k&%TLI18Ln04S^sw z;+c&;2XK}I#gs*4CyoCS>5<<+h&ngFglAXGEq82K-5 z06hl9@&V$erU_n_=$Fp=M9A`d08yJ>G%gO{su#bZWK_&ZL+5!mxH1`~KBAV%XA7r$ z3vf`82RBQ5AJ@>nuL>*{{>z+zS9n87u(S3sQzXiBKgpg=%-cJ-`s~~-&6$~f{4euY ztwrUse%JQy+t;1nx3AsW$G?UD@qW+3f(0k;9sKvw*}3J}%D#P(l?#=%TYL9as}{jX zANCGDT0T2BS6-~nE-qFU`Dbx))>rUTylGb&O+C|_J=5$9{Iwb(Jy_`&*`%iZkSh|{+p+(78`+KEB?GvK!I~j2#b-efV+jnsn8Lj-W4irv#y!MSRSI#YF#BRq#s z|KZb?zN4>WR>H6Vjbv2N7OmJNWVhrr&S5+(F(3FsS2RpOzWcGVI|tN+e_Py=PNEPc z)$70P#fxeYH#$IRGuGS?eYaT}8Et+F_h~9@XUdYMaNlV+8=6LRf&4ViO*aQ*7oMgc ze%AdWF%j28CFSVreTP(NF>6imX!54=tNItmm_CfT(pnL9dSdKfHv&vOAkiAeZ(cLQ3*R-jt zN*IDZ8W5^bsqY(}<#cR`>l<( zoo61kc<*CxM)qsiINpzXAs;6AkKSl>Pcwi?RLH)U>4^8bMToQrESz)?sa8Q_gUC!S z?{so>(4BpNl$-rPjV3*Uf@gb#r^=>-(P*T-y-oy$jV{Fd-=_VXY6ATf_Gw@dpt?y_^xhuRH#(wWl;LH+aa> zyZiMwAhf|-IC7c;ec}1>vR5zb5+YKgba33)E+V&LVdIL9YC?o=B}AYOZ}fR-LWG2g zAVeqxiGI{2L{t+Y!ctvaV8!;^yWs_i&nhEtXq~f$B%pBR`C)%O=AW}^QntPml7NA* zg%*$_6O)nMxQfKV;yWHWqm_{a60;fj4qj9*vH}2f^sBe>L?BaldB$WY2={pSvE@=d3+0bj`^LPQK7IXayFu%o*zzKtc7#c58eX8OF#;$o28=`($4zz=t8>2XQd~wu26^m9*CmAT=8-XgS~fkP$lAp2e?}m2UKTY3QQH{5JwWv!!bRKWj+_ru z-nMx<61Oi7(PUywkcmHj*}2UJ<>6m`MZWzHmxCd`?JEn50KJF?lJjSp^=3nV7@qB+ zw1--SXH5`08oX3OKi8M(O3aLv`7~vsnyC`J`s?tEd#@yvxxED+HWz|~UGzW!HyZ{p z!bi^B87{er29Hb(u_-pzK^|1Es)60inY0Q)TKLf8SMEb2b6FA~VVNZnE0XEcseW2r zU`ECl5ZRHB=cfVMDhxIQ3`zLY`0;p%n|?e=1l;)gc051HhT-w`ja#TK=Q}Y}ZZRog zNmBmd*9aKD1fN_2*qv_QmfYz)pv%sCngw?6IK}&EOB{e*U!&4DJ<5d7&4KDaZwpua zR^s3?u!I83!F09^@TAtMs#vpog%iS=&bV6S6Ib9!HXHMr>S~csT+JWF)l6nw&1A+E zQ`sq%!&LSvT``s2t?S~+=ncAJB72jrowew#x?-xiU)MQBI&md(>H%GenBr_riA!P$1sWMdK_x4=O-|6>9>4F`aPwcDg+=&4L^XqhKDhh@wp%#UXlk!GEvh6Xq{Cy zbDFY2IIJLKOZzGH+w{R4ZERgOSQ7bGe589lOC8nW{JY#<>CKC8blJaL>H^5k%*9<$ ziNxaMfm0Idr7}eWLCN*S+*IL}26AwUfykW%-+cZD;)UKY6fgHCI}*kZCG;jYloE6G zR#9JPV2rNSSpJ8K#o$-JRXQ{!kFa&lQ@DfS(*OYF?+KpLU zRR4%>_3Tu?Vscn@(7FpLtjeB+gX~!#RHY)V&wY4H`r)zL`xR{FS_?vLog+oZp+()# zV&rkgLPFBa(*m)tobJ?8UQl6kn1Wzn!QUw94iDGhceyhV>dh#ISK_JT92^Gs{q_bg z0X;o%djaMMq-G>db*LO&7|;t!t#Z1mK~M4YZ#U_vfv z$ESK=vObWA3_i3?xTxN)NE`R#m&7rP>=?k?dM4G}bxams(f5S@@D zqC_>qH&4x-yD8arBv3t)xJj52;=Uz_yHxQtj2_(1TpV1GcY-To-zlzAZ;lBB)pvYm ze0Yk;->=&m^8o~`Hn_#ZkOv}T5HaA$yfBTPJrL+4AS%pBnU-!W9Rvl`;)1S+ZY-_p zN>9QLe~S;KM&u)EOacP~!%Ad4_mvPzwW${Mzb#)*BQPXlA0{v)ByjWPa5aX+)k1N( zS|~187|tpbSq$f}u0YQ*U0JH*y25Zy=t^krNQRpy|3wsaE-a05jX%nIPWD0WOTALO z4`7hzM86mCXz03%vZU)_92&YF!=IsYCxCKYZvdqA{1omDU0;R9pzGb(Lv)n~MdjXt z;aI=licwV8`+LiF{UMAp`u)z{3fCjiW*Oq72e?pH?FJXh0lUFqanNqwSMD9Mn-7$G zvE4jY?)B{E7s|apH%FomLhbDavOjA#A1n7-R_0gAy({eIiE{6--F&6oyVA-$S%yUF z^Z!!Dv!k1@m2vr~KU4C>*+s&*b>U)<|d_gq0aRy zN-;^P=CHXTZS-CRBcOa%JlUL&m)^j_Mpkjk9MZd7yd7k2p0S8*VszAD66t?NhV(P8 z&%IXXG4RI`g6(##rhoZc;IE>8GJo^U=0c;vtLj2IJf06X?m9n@(o-G$Tj+E&Sh=fT z@63Ydm{K=4KlKqZy3{*!adessLmSLXvze9tuZ|+8+@966VJ7olH0kT$YRL*r3niO_ z+Fg9>SDoj2`%E0}_=KiZ zBfbK6if~F~8qg06BC<}5ZNP0C^Kq1}0Ur>s*EL`XRs6DPHfUhp>Xdkv)(OsA7nm%A zOQ*BO2MN*G)%{2kI<}BTn=<23XAT#K=RaY(^>l0lzG9bi=pZa_SNC&^fuE3ECPWNa z#T^dj_7xlS3UoQ-{2-b}_s@I%?maZqi4U?8M7*A}AGYI>aoA2q0;d0e>fSwAj{Car zobGwtxsSPb?gPNZeW9lT;>Cv`5hQ4eq}Wpw35k?MN|csX=?^94s#O81S^-vhRkZ*C zg$e_CU2CoFt#T#a3YB#Vautwrs=T|3}WiX%C)A}ZZWF| z)Ft0}A2mT{ZdczH<^4#Di+`i--YEgKMSjNBTac%%quGUWXIQv(ezhL$0cikkDRUU6 z1Jvc#R{sZEQD!aq3Wa&%fzf^}$61t}-t~a!B5Se#LK@T9sh|@9s745bk2`OzgI00Z zV>GT6a#83s03t-XaB@IpPfL|u8Ce2eBi9ZY<|en{lAG>X_2VL#I;yZo?6jnM98i5z zA-Yab%fTQFWXKN45|i9`$od*ffpqMKM535fP`pBu5QP2?Ct=C{8WP*jnPt zbxk#^e%yI2Z6`tr1_p^0(_6gBwX`fjRt>FeGZVe=`KUB9w!~??Te>esG&g7lf{?By z07*;gDvHf3C~sX|X-2OWjaMgITumK=^#?qX)Xk)Zins$btqK+LwlVz7r}wzL4I3dA zoEl9j^ns~k4mSy{EubDX2W)0R6#cix>AW*PJ=K|+X}4!)+~?Mk>yF#p;vRq6=>9zH z-Zup*lmsA$9pgdaFa9HHuG02erttc`A2be4E)f*gw6QmPmRS}M4E9wKs&l%I^y6t( zq?8m(QKZevR`T*uZQst3CAd%*`+qrz+c?~z=~bg_+JOOSuad2Z%M8!1yq47a2OuMz znhX)^i892>a+wTKpTE4P2)jWjUKA17n7z(bicl63c$b}OLgS*3Da(E7c=^|pw-P2|Fby`M%iHb0Imd_di58|(Bwt}KHAs7;fvw{($VS3wGt8dj`u2}1GjkWrZJCmc8Co9P@lqH)V zBge%E-fAql&s_u=CTXS1OvFG&c#^a|a;*scTKX;ICk3GeJ}nKK;b&o>?(_$X5d4w?MjAlM-PXgy27B%kH0W$G zUsA)1-tbCj7){g&-D@nqhSTSvmerEyMy&U5)@)vEk5m^9mi#QpfjUfzI0T>r6Jcd(z$Y(?xx ziOC2KFxAn^n9V+LrwhP+PG#3t1TtT-(eE9mPveZDX^oi??Il?gvyuDf2N`R!l4Z)_ zTq*8XSLge`n&f+*v^kOKyRaI2l%F=t<8cq9;E8Em1%LK&ZVTJyf$X-*ILV>?=nqG;3izCSe z?vRMT%Vc8%oFFtHajB0@J|Zz2*`9D+E`REu2fXn)PF7e7Prw~b){09CM2jwC0gvD3 zYWMp=_IBf-RD9GhZ>3sA<9;PdI{8Np(W(_9D)v%~;x7iV7%oCkX$j~hYE;g*w2Shsd;fE&|m*s2YwCo0r2Hi zBl(>(4zg{kOE%S&YN{)>srrxGr@9nK(#kk8)g_ziZl}l{ry56+!%ij1%mK~nPQ;Ml z#pV1BTE+TR=D+dEB_-%M$xF$p7Yqt~rWE!zHA$F8FxQ&!elrIuOsJG0vGr}>8Pjxc z&1$i_m8ED6^(x%~%WTFmA&w+iEfTD9#+p~em|L*EW#o;|GIe>iD*t{#uGNJK=!oe%8>`CW8r7EAlnN7AP!@ps zv6OJ!xr+MKe4b%+iuY%4vKK}&f*6Taz(l(v5h0YlWRsd9n866QlozN8aKJaUaBldr zGLq$?g3}x*1A>~foLLkprUdXga*~_!CIPT)*V8s9d6)Fp8^eC^uLjcH-4lgrY8jvncA_i+f?JAzayqAgJ zc>Ow+kREHcpS;euR&hO#{_rf|REbz?h^d{FGdxdH^wm3{;Q13D`eFt99a zz(KB{lbz4|4`FLGW>HD*C~jvUw?Dd$chp8(8|s2mM5IH?0e93q9I#@IRC+nZln1It8Aav-gFd(iYwnH>uWQ`Zp7M8KuPHKZCjWdj5eT&hSs;Sa;*=4+Ayd#{3#o{ z-v*`r`wiW2YF0RPeL$n{mVnl?A^@#HR}-laa~uMp)k*WG#d7}JS|l*YkXprYDe{yf z4ehvlrv}GyG@z)l88FrO?1ph18=JIRaiPCGtzHi$CK6vMPR50a6-dsO`u}@UgsRBY z{Rkp-Mb)MDTj(4F^Vd} z?^YZac-MF?GJ+dO3EV2spA*%Mc<)nqcuZ96z{SqDC-Me{$Wz$T9g-T!pl=!PLIiUD`hE^r{ERku+5!rMXIEtuPV_8DW%VS zB^8FxU8U}X&yC!?hYsOP$Nr2?qRjP=Jxh_7`b4ls+fdL1F)YXA2k^-?Gs^mI zTNf!~O+1HVKQxQv`?RAD5|;CYGb#DED^tY2E#VFz&(t*4cMTS*wKmzoyzvvRNX{>r ziUt~yo4t(PDQi$Ur}~Uk^!keJ!U}s+m=RTPpN}0?&&(zo)Upaaxbm9ioN8^|Oows} zW!dMa4g=(*fzhc9MH>;C)?!H14zog~*=tH*RQy2Qg>0{s!CYakTI!LIZzJy%FE>ta z3uW3mRZYyVB+24pXNDD9^gn5{$*7?1PVp*|LFQMc!w-u|lSdb4dNWB99{3G>zs>n+ zoV@nT6nbW-_~+1;6vs~SFYObl@5R5ePg8vQ42}*G-iu$79@-<#+d^6()PmH*_VZ>k z$epp=|M~z89EX>!i#fi~)?1{jv>`UrQ;QcHj}fqK!G~z?%xvDgzp)p!zih}1GMVZm zph2UlD{;iO_=J9}=Rg=OiDAjgcuZNhyYk~H%_b0UCr=e^CBm3vOpKvph(d}$);dL&fS$?Nt=D`Vx-R~4R=2x;T3#>)-zr+~ zl_$pSERb6Erv*X*l-y+)d!t!pDstMuITpS_{^NF^%W5Fd%p$Za*{a#X znd7$yX&JN+0%Q*~UyVghF>uLGUR zA5~jK!6zjno9Od*WFhmBh0Jd_)cSa?x0rG1jSNN7c~kkxh@C}p&V_lH&Yvz3%7)p;Z5$DcUiYY6)o8PwI90H&_5SFEW9u8t`l+Q z0Vgq$6?H*ghqqbp$aH2i6t}V*yPc9u#Eve|AlU=8H{9H$TGn|Ia)t2Cc3rbyYzK^bjI^7U_5O&Z)T(s2M(w zp7~GHS0@`5IV!b-{f2N2v;*{#{Sn{bO+h^{kDkJl7Qs{_D0nsAAnjF2YW{=AHPuOo zXI8=zou5wSv+$NV7z?;aPl>V(xU5Lcv1kG)gfJu^iMV4cK`XT#1-7doiaWTs9+*YS z=?V55AmxC83o2C3mar6lZ0SBNrFilQmd=9Xk&Sw_9c6(yGyUj5gn-WXPcB}T_I z-uvj7<}f5VreEDawNv2*_ffAXn&Ix|s4qY)+MlH@9(rbP_}P6rLG19JX13GPuNuC$V>+1NLm+`n$#}Y7R;b6s7{BI#! zdfF_;1?GUpnk~uFGyjY^&xP4|sO{(+Y<`>yw>fW$`>xQ#-TGX_Ltfc$kX?*&%K);< zQ>B^XC~{pYk^bsD#?a7cq=^(0-WgJ$_=|j;WSr$(pJXJTjp;}Wu8|D&X@IJ%Y)a5; zp~`(i-1)C|r!deCJXDH6Z-{lRPvrwEOkt*8`(5qAQN zf0m$vGGq4=QLyC`VGQ;YtHrhMC%v@`JAEiiWE-($-#G%^=Kn(qiAB9o)ziXBo(xvkg2fH4nks*t>JHf7(uQ? z-y`0MrP7n;khXo2uu)C+W;AhaBerO8Bpjh*%6F{#_j$yAB3J{hRod}KH#%#n4#fwSq|XgVe=Sn)We zGN@e?}WiFW&_3-AzvG;c~us~R4T~Z!BGzRJFY)iEKMM7gSB-W$i-*g zvoP2=&?Rl+2Lpj{pA-o)-o1`iR%4#C6p%De*8wyUV7#e?I^YXs=*RBuG5gxrPYehO z3Ib*q9vH%RQy9SFwOd1kU_XtXTAtnwxfhQ&g*r`|$ zC5Rc0!eYlvZ7oe}x3%n>(}|CJd?ghs3y7%>BXIU0(cSuC!h3AOg)0AbisT7`d`m-> zZ!*vg)|v#ZE!YQ-S<9Af)4o`@RS$flj1h2KUJ3NU^(+%cD;B7G3Sye0wR1*x%2zDF%ybdx58xTj@|2+jC zO#f6^by6UpZlf)${^ETRhbQEzHw#_{qwklkd;Cg zC$;ErP1jL#bw9PvdV9E-vGTKhPUi~eyip__J$KkpTg%`rwJ@&gb3fRk>BG7S3wgqL z%9=WYGgJiQ#qmTtDhna3l{qs;I(e>gmpCqzv3GgUf$HcJhdd)!dL+3+A|`c#LL`j} z!2rEq{;L_xoTdtLi1@UVf(1Yow2^K+#mA-qFQW~vur3;6U(x#IY#%~o)7Ajbx0po$ zkRtIlH6mKveG(CDG`kp|u|X*kMq|=A^RH-i{ZEq%zJz9z8_i~#cFDWYFP)D5 z#gML?@4Ig0q*A`z_I7=<^B2NQfeG9F)b%dW6WdrQWsCbBO5@OO5f_VL zs&=V`>WFnVo^ijf%jxw#Nwh+L7kuae^0HA3R}>70Ho)6wvjq+g%Xam@Ht?q)P~gqZO}Ckab{MSo2`e&A7dR0 zPr`X*F3ByrPXTfNVyRjBVmpm3&=E<#C9Y|qMTSVRi~Ae<^xeEV+N@xo4U~!i1P_$} z>@II(a=sIOkFlL4bPG6Ec;gv;!`OTh@N0_^ov{}q?6OgPLlH@r^GO&P8#= zaX(3oPvF!uVQKo|let6!Kg&%_$6c-VpD^1*YrT}eiIy%=(|1+nz*T9q3vUv9YZNUAJkEbt^DDPP}e!e zbe@Pzw}d`1fq-PwYV_ZJ^s&Q8OZ2%n5=K}L2Orst;d>kjYD9%TjPC|`V}$j$!W%#L zG~!J-@U+64y*i+fOhjXZsSpy?2yLVi+I)JJzh)pz_?N2cH~KrG1!T?nN0-5Wl1LVY9gvex`;x9j)2Njv=TI~HwkO&vWt z9qwrFRdc?%deoWYC5x@6#XqrVI~D1R%NAunEUN^0fedypS(hl135L?LGQj|qo9F$I zo=0;eT7gT~UzJES_wUG?PJy0VjX+6z2LlD(Ee%Frq<~s3??EWtLl!%WjGfTupjf{t zMYl1WkTI;C-nQKX{1Y`ug141=z%vM5)WtoXetM9XJ7Odw76@9C9fC^|$L}_aaQ^Kp zrJEwDm*js^<$kNN_RJ?{Nol# zDJcZ0mR#&CfCwvSUnb8?WC&A|IN;K5@N<5b8SqafML6I0?)re^K(jD#!?jlN&Hn|7 zOF1p6v=iZA=l41s!m+(K3kO>c#a^ifC^wP8ff+Ar=KG|o$o7)P5N2!>15j~0n@f)! z7-}7w?rw9qmtbZ~#q-MQifE6&B+4>@9}zCBkdesP*2>p%qNj#5=NKk~w11bwQ1^t! z%BTHFr2hR4>a*Fx8u`lh|W92n|kJ;07UF7<$L*s+m{6tRGN<<9yz z5@mQV4L|Z@e{Ka`@KTlF^U0QYC>4 z^H>7ASqfu`J6m?x?2%#m&K-Kz+#NOv}q8Ccb&%xY_7e(h6yU$s4uQ!NH zdT#%uUJTFJfxu##pKm$%`EmuHdi%?MUzA)b=HGx(v1@K$H8IUY5-6qbkvZTg8<9Zy z$UC%!@KN5x4PL?$Fo8FSs4L$|)b|9GF4}dYc2SsREiZYOp{DM(RsVEwYAmQ3d)z(6$F&Wl$GSz zFFCZXqKlO7EW_h$p)xr)KsA2H`5@6?s+mvT*n;x41}bTfYwIytsQS&7M;%=QL2`fzSWlYjkmP;t+o`9w;EIbTWtvrI|`>=v;>$~D<~Nd=_9#5S~$MJ zzyxIe!z(?^K8Qa1EdiCK80~iD@1)!HS>$!|>hr_rp1*kMTBbr*Aa0)%AY5^rNKX9* zK)MC?upZfiX^nwFtV5%v=I|(#vJas{G)YN6VieGu09;awo{iKZLoZT`cI`Rj*trMH zL@hUX&GNaBP4$ew(Ml$YLR<#`^P-#p02H5{Ii!M1OP6g<&d?Bini-5BaLhVL)+&Hd zL(yWG`;1|(-DpN)sO5y}n^&rd7?5O?Q$LjQ3PR#ql-aXKO**DZHgtImdrluaYo=62 zr7zi?^I=-NZV?uxrM=PjySX))AeQSXXzM2sf`6A8>yaxcFj(KPg-b3N1+%*J z=0+lC0&MLr&1(6Vd~T(wB;uoW4iq9dj<gNnvjkEw{>Oo3 zz!(L>hRSWWdh9Kcr3L~+2xg}x4O5Kjc4ui-F3AGh%fk|ovMcXV;G&hRuWRQ-N|91I zEr?xG-AzgbJM&`mfPB39dQ8uZ)=AAb$C_7uf30~C;2tTQtC7_UGlGl3V?rTueNTK~ zug;;2&V#zA6PIFSio_A{HpYY&@*|w{X;0{aD!F|sEYF}8MDFd5IP{(Mo_=~1Q$8Jr zl8=$oB>!n(wE@+An2tgk+E#z)3| z!6jCF&imb?3N0$-`nk~WRvjmzoU7xR>A%~!#@`CqpC1MG=fhC;-3TYffNj;mEu0#G z`-L&!eqn5qy;$p}B)gQ855+rH>d=c|P->eeXT%PEF^(LwUX^x#F?6t5hvFn^{SH9! zr8pK(Phi;YL{2z)9&}nB%o% z8w#2HPJ3+p5c8B#W2p_Qm{cX!h@(m5LsZ`Zh<$MsVqYw$b88Tr0I6RdgVZmFrZ)m! zu#emsl|#x5dU+{LY?bZ+i!fN$NARhzhfpaMa>0=Rg_8x}$`Xv9;#|Nd>pyL70x9AT z64_-T#QhFuWL-9UobIU~9>N@lIqHWy%JkUai}S??KljaVPI;p|+uA;1=>F?>pIHZI1(vLN zCcw{XEMp32+*V`RK4YO7U8+=BP`FbPsdP;(LM8_2%Wy6vwJzJyXWp`6^Fk|?E!jaL zq11dE>F3{#($BvOcsO2cdz(0}^v985jwrg{#$kSGbeLbdnPFZ>(LJg?w2?$3ty^|w zRr)C{uF7cvFaD?}YqO=!3}FjLfiVHu)L?%UnX~0CKM6i9efLA{ds!) zKtd7kH-Y=*X3Gh=0oej+`^p;%qZ;wmL>Ulr&nmK-$V4oshic4W&qvUW_Qlapk}i;> zc07?luI(%;8=%M=8P!=&%DN|p>+H_;yoZZ9W^mE8Z+v2JyVtu^K#>xjRWn%WFmg~-TvXz?kFngh zQy^Zx`%JIFbi&R<(Q)4NqfqTZ-vU)Ws|i>gtsw7k4p6#LTTGT{gyT|Z)>yc#{B9QpxBf74H9ik&qz(-DLkrZ zv~rvI6~4?+_=){VWIkuD+APfZP)sRpjr zB3>+NBa+z40z@kG^bq-Gjy`II6VnVwPlr(&)sw6Tp2Zs|32X=f=#Q$73LYF)TTJ~K zR8D(CH|!a^!5g|^GaR<8$cTN`iF%Der&?q${Kg`qWZAYWat{_*WLsjDF=6TUL@};i zwEWPwG+}LiDVH9vpY|zcb|oA%vh=bs~hwnIKqYI!`$y@Yftr(wQL>e zfw2IGQxV>1gah8&Hf(yE9W+abuc4judwfBfn6@~TPmgRn|1}p{AO)2`IN$Zx#-tXl z?&5#1HvoR2I%I2B<-a+~G1sXFf#S)>+tF)Rr0*tw9CRHVw`w&Q+HIz3i-S&Tt>R zM>%QLlp2^vL-lQZFOF1dE2S@AUnUO1Q-Qs(?^=x1idaaUYk1LGu{n8yRoEGclLdi@mSd=KVd*-aDj=TEaw}0nO*&}mi?1Wz^ z5r-)UUG33<<$6xCTLqq=V4ksU?QlKmG0LStQj>$osRW`3kGEiKu>Z3kvwF?>poX08 zU7%=3r7J2N*LZ3Ge+_0lT4MPX-Csl;8-C)ko` zNE-#7>JWEThq$>u=$QE9!wk2Yrw3CbB5*g~`sW85TsZOIAj~NkyM*hPwVRwlqnAt) zj!wCifHd>9E+8oyECvFN!m|#FtH|{uzK&|czYVJqwp%}V9ccf_B`17dU1wI1*<=BY z*jrVr)8nnStVJE%N1OhfIvZ_qr1J4j0|PtCfyMH{)(lQ6nUo-w;0kXdd6IYSKuw(L42Evm<*zA78J_TUccv3A%> zyqiwSnAzTm)Xtiy4`iT~N{s2RuAlRUeH+zc_h1Y&|_V% z+>zAkdaSgOoQzM&$Td|LlWivX;oO}nMy6cJ$OKPx3JbvyV8)U#DcMRRr?a+;--s&2 zx^^J{M&QEzC{o;>(QZr?OA)>)00{B--F+c#*wz3gmI*>Ke03o&rAlh*hGe^b@?t6G zd;mq7+awPX?l(t9^P3Y#<9Ti4!y!az+!wY>VXE`0-=UHN^-&5#P+;J`Eg0iou&4`i zuv3@Re=^Bgn{`(l7M^N7EVYT3(GFC&2kpW(|4Tj41p1)If|(06$Y%nI>OFExuq%vi=^-$V?}kUglhrL$P+`g(UTYx@jjMU%)~ZuW_%08RjYRH2 ztw(jbT!{)}(gQ4r;-E4wZ&4hu+9f`_?ZYtYqCgCNA`{2JY}D{ktWrz?DGfQq0?M+35~$?^ z#u${XEXGjMtlJ^(H!FUqal^XqM2kh89^2ptRNUpq^sGz(W(Bb?MZTahEKzMYXHhMu$6{mz zA>!uq;0&`>r*S{PGH(2h0leReY-T~_E`KYqnT5J*+yV{sH#Lut9>I@O#u5J zDVu6W&;x44cn(vwDwWnS4wTNi4{3M-Xl>rhrv zL^*%$w(KtdVUD1aCpq~nVZ~;W;pXKC1N#ZLuiN=9JA_2_GjDe3hO75(4ivcK_BZU< zFzWX!^^&6hEWmOQLthDdO{Y>yeX^(|r3yG$^>i;961w+}YEDV$5^ zhwV!o%Ts&X3c{d$lw|DhmIM8rI8f4jf2SO1F!URyX1tSEl!^PU+K?p^=tVFZ#Icj?NW5qC8gpKqL=Pm@^k z=&$299`tiy=`2<07GCOMtMla($?5r4tKIel!lMc&r<@dvea!W<$|vOdQliZ%KS8kT zECMSn{uz#M!d0Sk3^_(#snBpoCN@{J-+L7-$f(e_B5fXFwIZwM=AMSoSB7(Xn%R;z z!C-FTZ3rg3eKRA2!#G`97w`vDSu`V%MM*uRwJ@Vq;{{s13*TFC`g{M()xj!EN^WUY z2-8s66l$NmTg93bK5;fFxVU-cU{RVjyzW$xX<{{WbdFs+IA?9 zA?@MxM-pv2l<&dS9%+EhEBS)FSu4~VNZ)QhR&@-d^|W;~@L48e^*H}y!0?$hFN(;0 z1(bdy88j;sjiWAy9IW;pB4R9Bd8V52@MfWja)g;=u>vVxc`&%kCHz(cdA^Wnnx-)B zv2_siv>rGDkhuf8g?3Id0!;uijjZ_!@2K1;#I1+sWLEQ8R!55^AvInrk?pFrrpMYv zV^-dS@TgYr`j1k?!&^n|i;t43T5s24XrbjfC`ADiEej4lV}8;&Wk1Ii@%(U!m>+?# z6u%$$dkZ;VNJ{SWl^XZ?O1U;A_fgKz3-}s*y-RK13-zLkim`+hK)SoX-;#-o|4YFv zQ_tseRV&v>sqSboHEv~X;f}5CuQH_4&h&Wl%vXK5R@U~bVYn*i z7stm5eL}_sXW51gm&yGE+f}qRV2kNRQe5BaMgj$7PT?coLhQm|zOe&74EdfLAq`l{DS zHqSjC1#_n3jMQLd;f0bc2sUvx>IFlSjsBku5Ou!GtrZ<-H#aa=Z**XPP#f4Egf^|V zvT%&m8yQ%bvIiLWRcn@wtl57F11%cEPyh99U$g%bnjK%WYpK@kVj35%fRn7FS2)D} zu$*%LRU1ACbv{7E))D59s?LAqE1~m0s$Q(2`RedPE$h4$JJ)nweaFPf`&b?l z7j~MbxHfhUr+Hp$yoqBE5uTC|@(h>7AAQU(`vB}*&zD2Toc0uRPF3Rcovd+1!-O5< z!Jduh>LSQ>EAbBFe5xLbo%OVovD6YtU=&KdB=JKrhj{cR{$N+iuwj?<<}*E+y$B~X zGA<})D$0R&0-Qkw${wMkxHX6)70zg!r{-W&7zrE3Rf5X%Mz(2}RCu_)=>kk?!rQYb z2l5#BkPv2;%i>mYJRwbXwb|0BwfY=SNHgcEcm%wIqSW6QMAI4fg4nltJ6M6HE246e zy)ys}pSagU)oCoe{B|3HX%#5~ofs$=i=b1UCkmCPFc@8A30evjv;1hRCV>&zeBniW zTTBUCU2ZN(>79PpQ38m4u}6sV9p6Vv1>uX7q6!rA==cA8pe1yPY$kg^ z$uUa{cEj;B;uj{q{x~2aoFY)bN?^DH3$s^3?@ucFdFhLR;r_{F`VrxFpL>$=zvX6#Rcyb^lxcICTGK)oUdW(Q&|RP((3xxl6)A*~Xt& zZT#{Fr<@7?d1wQg32kgi_@Q$y%nqjZx0wgF*A$q=Xa7q44Fd4b`R>bEL*7-c$qCSh zE6P`2*M$>!3c2=AkVDIL@kDw+*QFC=nsbGkkLwDF+^6gEiSz+oS5Bml=(_7f`h>1~ zPNYxkO3utXbX`3GNpanKB7K*xYbVn8=(>I)eV?xE;=h>a!^Vm91NLF_MEV2vVe5qS zLVntJBK+&&CWq*v@iej@!T`!IcP`ZM-n=HB$0eL%f^(LU@yk$%cP95|7_ zWFKxjk$%ZOpe=vdKFr^ne#JiY?oGdzRM7i_MBtnKDJtwfn_jT=lh(u4&;9cia48K1 zc{eg$y8{BV+aGULk2^156{SnJ1Jg;kN-30{Dwc~ZgIgPND1*a3@{JHsmYlP9t|jM( zEo^uqenKIg9aB9uH~th10corU_Z16gRA?m;D^Qj1Xb9#B+9<=SXC^8_^w9){#;hcx zny(dKNL1UcL`eUM+vUS~>Uu3biYH#O68_iy4FU+au$t{a zlbXs$6FkRAmd-dNadyyZ$E>z$v4h26aBTrucE^|Oq6S$(?OinpH-T_IWk7edVZkeC zH%n-n=Pg<#I5KSY@ZeCOT)y{`li51xIJ1C=c~hvUm2!0hT%B@Uy_Rf46eNaavod^| zmd5K%mr#*;b}h6Fq)nhRx$wKXV)*hYpq|*@41;|;{yQ>(#j=Q7@4b31OU_RqfZAj1 z^^A`h1xV-V6vy7+L5C9gl-5cLO>03VQ96`Fxp?ufC|7n3+0=NmoUxtaFDT|SRowpu z9+*KAyW|e3PVsTvOU)#ecd1kS8yx`WR7%19Gfz(R2m1f(R3vf9dZ?-$ zsj9uBlo+EbNFZyTpmVN>7K$-Jl1Pb)+71}CU0z5#&(3V8w$C+c~__1fuKVLEG*h8%*2vIO?08yKlf@FI*oO^tc{LAEum%zMmY-+xNb-i0$JT zXTCFzcqr=7s_~zb`J7!j?52A)Z~4(Eu(5BzmYUBonl2~b^xrg?5@k=-C_9@m%5B#; zVzUa%i66X!6S;Lgc`Bc~>c_GL?ImkR?R^U6JI%CtiV z3P1s#&A4Q$2ti4cC3E4OVLx^Q!|m_I}Bj=a#S>WEo&b^W+i|1s>w){k_kpZD>z zwDN%Y<;(WtMsctFH3P11&pCV25w(NVYjl$;(+dyYd} zPN}x!o{8D^n*~Bh#VnWUf+Kv>*fhPDKR^2T>#g$s`EnaF+UcFRU3`NT4%We5ui2Cz^aSJWz zwtPO8M7M>jKhJS~sg}ocsUzlgA7g?Q>1wJO^C#53o|k0Bx*~kn2T4;<4U@c>V237I z_sVx;;~8==K-6s%h*)q|pz{}|gn?3bG$JyOq>*Rb6vSDjrctb|k}{eRlhe@wW4vO} zjY82eObhReB}&VtufpKGrIuP6a&iLp!6oWYd25}uLA&%VC9KhL_)q$lk*WJYBg!*Q zyZ{$~j;-iL1WK&CAZ8k;1uS5KR#b%9p<>BoF9DF(rwx-};%N79vvT6?YU1s3;sFiA zRIBt>p%ze&KiT)LwgmaTfR)H`??+u`uH(%SFxv=)HPp%uV5nT@; za^-`#1AR`{V~B3uKMwoT^#NR_x;{c8g04?k>D(jf({|MM5l-*fW%s{lu$$}Q^xa5e zJ@+1^0Py{NAf&#Z8&E5R>j#p-Ui;w(5|jnq`A|Z|YJK?8gp@dacp)KCS1*4gA)8kp zt|Uk+{dALNSy1HB43;pjN%=t}yHc-{xg>)F^@z-`+eA_ zBT*&DWD<~nsG2R)Y50R?Jo=!2%M^sQ2fO{b ze!t!6ONCC0gQtrY@!sAH$emJUN{`?sx8FWwab14w*^e(-M`_9#@%DX>o^8`i!4-KqIc`RUZqwq`+TE_OFA?rsHA+bzWcyhWrv=NXIyr&$GdSBuoEM^OYHn@Q?KNf9klD5&{!!#D(Atb z1I_}g9slJo%?r)73%1Qt3#xMnF)5NrS0-kuy!9W)cV6`Z&|J?1w6^hTMAam?SoPIa z)7=qPY(GZcoN;tmBT1X>&J=^4B@MwKMG%7&c|e8?+@&l8i4k-TLkPk#U9GZDU|wrL z8FRc-Vcy0eQsi<>6IfxvQ2NyZT1`U-ZO?o=dlFCggoIj8QqIH!F=fAfbCS^5){{&C zjCyUxd=zXM#}koYfK{I=3m|Aj#{d@A-6^c6j3R~{W`WK~%fw?bSH&iQTvmb`U^BTA8IyFnLg+7bbnu$>@M61mdUs}ZtFzC4d#yT zZYg~_YaUiyK=n60 z0q6<~t3W8VYv!`uf>4P!x)odKi6a7`rEJ5Y*ie0KQ|z=Kx>QJkZ%Yv~K&(~gzhGep z(8?{MObIv8=4%F;A56w6hyK8{EV%x^NsDRMlsSB(U&CRRtT%SRdw zh^l7@lyS}AZD3pRsief9o-jxPrEV)!xC0OvxKWj88R>UxYZ+zYj9HeC2@)5=L)F3MwF4=UD8ohEMTD@rjAtJiY7-(eN3~-*cG4`|&+>xc+ zGgn6sL1H`8Ps`KNa!FGPo$_D|A5^`!R;@RfiMT4M)xJU>km5nqkgzv{TL2TnQdLr}QHg@Q(7kb-G^{XDcR_6OZ z+%8o8gC1F~vN%!?FYeEkwIYof)lq3&W|UwVOR1|bN1%%s`?^RdAh-UQ^l@!4+h=W6ru?xO(%Uzd%;SX%ZGaXDzdokbz zSSSLf(2QU(SLOOtD?B>4`U=N61%g|uR+uW`Y7c_bZ!Kx3lIk#`09+G+_rV>CSEDvXtYjSRM z1*Kg34Rd%ZYMV>ZlrZjP{@3n zZSS&JZ#;)|?lK5Xy)Q(t7>|AmRpwW0;7k3VpDI>-)KitWT4VZX0+^=WZDj(M$NXGc zD*3s5$?#s`=c*+DgNxGTO!|XhZVAqpKCY#w@hf7wl4n&G8s8O$gC)4jhr_A#H7^(B z7A(P~5le7KFIPCi3@;a{x13Z)oD?;B__7ZB(jqtCtDUOvU>xj%#HO8d6KD{MqFeY!9~_nC(Q{5pzrf3bnxIAYvIyKeF|@`~2{fpquo(f_)OyY*+Ww|jQ??skVy zi$JSWta=x90lwavTU~7?tE;-MuFmmCSN&Nwr(CD_h&kz&`nspz^=G#B`>W-&Tk5QK zbZ>ciURVC$@Pn0gR1J)BRf{eDtgiO_x5dR(&adRhzrc;B>QEi_Z)i`|9%SzrF!4uX z^))GC>a?{ow}$}pXc{`pm0EOYEQ8mKDd~uCMqJV|&~@0?!tgh+wbtxArN9GE-fbvL zl^yZlqM5Dre`cxJ?Z{iJ;_Rb1UX_#PhBnF&yOEn;rd_dWTSMQ$NS&vXZVKATLj;m! z;H0g;X7)zgXBpdMW}~fP4+X=4R=c6q-Bqi*h*yy;TDHAo%e%*0j^i|<3Eg zTe(ilj`o7)O3^gALiI!Tu=0Lw{CxBW$ktdX;ZpWjoI9hJ8gu1gS7~qgCOdUu7CK#- z&}pJ7E0a2XHgsB^`v7+c>#_sv`g2rut*?r0kGIt*=b~wpTjo@6cdAFa-i=#cn%Hvx zl(Vw9D%9NBj^IMln?(7!F_iC?D8FX}<*Di=l&9{C6q5BSHNw%eUrliWI2bgm`Hu2L zB8m=)!8>2v5#@D)(aiw2tbZGvuobTzC!!T<<&Lx%umIv2S+24sWbnCOuSJUqR7Ac* zi#RH^Oj+}+N$ePYBIni_5H43yge3yY*w(4X)d34~`|KUzOmM2enO1F?_L6pu3Rfh) zOsl?3wVJEGOe*HpVle5-w{H8jh$$46x-l5exWJWkDVV`Y~sdLnNUq$4ov1Tpy zXk3ULIO@tAF{G-4l2O;26-O=eD<(f{2v92Elb;zO`A!5$ip#$KeBkJjHc-4BboFPB zmlDkSEo<&p&(LI$cj7c-h+3A}+V(tvo$!3=Osk#`g;~-fjI$i2hluJa85Pbwi zS?0+Q&#}XPmIz^0<6}zevQte3$I|r3bfS*Y7^OFF6tB@H;RbkO!{Vk$+v{|QYtAaM ztU+c5Ab+NqI#s;Soemdk|_RraKf6CwM5I_8^@8nQ#a$s!{U zwN)(NgzwBq2^vKGK`X93W&d-XSN1G$Z0N&9YH*&Xm6U5SRgPgiyaoYR%v0UuB?5GB0)fPG+}z=!Mu z8wGyUKCnUH1^YnI<|FojIMJ0_uKrJYuKr&xrris(&jPa1&hKFK~WU7sQ8 zMb~$d^rGv#NP5wG?;)v0*Y}dbqWd?Qm0~VcIIE|KwL>DwjL{FVGFc+|@_8aPdf;R} zbv0k{4Azjpn)ka=7I*#j~3Ym z&?QTVhsB#WgCpYQ&2W!|u53ocb?F=1W^hK#WV71XHUno=Rck&j@&%G0Z8mG4CSNxs z`>8ADqP>4JmWSH+@EWNIDq^B;h>R<#-@DMBG^$a|guYQhEz>q-BK@}qEjCI60R_9wYPpg0#!x!W)Si*pn;pR1GpF0h0@^G*$S$j9{AP z+{&x@OibpDX|^+#$jf#sRW$~>WOkaO&hlZTcmXE8s>ES{o@VV+Rqkrm@l4nveWR5C z;yFsQ=utSn*K&~(%svkqA~`_Xb%sZ+sa%ophy;eyFk#I~G~zLRnn5p{$E=&ru=mo# z8-2(Hp$KwmiBsY{0zdRlk^g-kEI0>KD(`&x9QAnM<6?dKnNffK4gPj=JV91eg{aGhixRV&YK81`7KWKhLf^R9wZ# z?*^zP^s*si*lio>oV;Zkr6^oGowW~C1FeYs3W<)Mdl6UtzsEpfbg-YLn0TDesIU^) z!_YUVx*~s`LJ$Vc{#Ql)`r%%A_w-bKFF-zXIZ~(+1_}5W*|Fi+-af_a7Epkh!qF_V zp1m=hs6)vEU!~2~cbuVNnhwR)bSSQ-Lvfvv4#jm=IuuuQsRO#AOWmO>y3}!9(V_0s z6`jhQylljIMBmY=$TYT{mrv@7ZuN|==vMF472WDxx}rP1M^{v(_f~`ahUfPFzh6z8 zdoCQ9l-&E3w3ghv551!?Xi)m}i0MBnfw~I5>-z={OnpB9dNCQ? zW)ECa;;x<`%lDvtpyJ9Q`|xAQ;IKXO)47 z1XWHCe<~T=VIN*f26x(rFC~M!?3phosCjz$D+zj>9{yS~c!hmL;YZTJar^LN>EIsw@Z;&=Ui)w*9h~69;q<3cR6~9EXo_yA z4?mNl9O}chl$2rxhmJb^m2_~QefW)Z@Ll%d)^y4J z4UU3%_+0*~0}Z6NX8@|W4ICqy_%L`x{P3lQ$#@e$rUNEfqk!eJE3E%}gQ8Rhg9)TP z0U3oA@UE)?nRr`VL(w#rXKS#gUvFz?!ehNd`~jK#CCxviz&6 zlq5m`M<${IGzMBj2p`}9N0of-En{HV$_}Xf&Dyzq)0_82KS1n~1zu-?*8vp=8Rcu= z4cl)9*k%A0@iw?!Sdc!kSxvdk*S+f1 z_TF8iTo<|ojgow*tfXa4Jbhk}urr?4SY0N@raNk0ZJp0EhO^E&P56D(HD#^@+srHw z4i1-|d%F!~F3YmphjY|;Bcb@K16D_1A&tI~jxq-3g}C)AiIUa(bR&BKNH!I-R9$LKfIUG<($p8J7eI2* zQ92Ysxc}XP|ujn_S3j-1a}($Q{u>sDwwLrw)s; z?dI)7X$~|@9%oQgzK%rhg3nIgO_BF#3Xs$P?V9y#&SB*MSKp@0UL=yuH^7}BOtzS< z6TVs)Ng`ufo@aYRq#yEZA^j*RLhqrAxDR@)16Ij6gJ?g?jyPWsqsqjnA{eNn42DYH zI{W84^2MqxuVoC8FWn3=ZETrmz*XZM8^gJ0^TE#J_f*+|#vk%z8UJRy%c3Oo3=5Zz zW&Q^Z16g&zrrdxyo1#Qs5iem^H6_7;8Jpbo<>dMm^yBuG!3Ga(WcgG4)PhAc+u7~e zflLb;)s%C?JCtP5yfVmmRLP{3~R86tw`2HF@Ni)su^_8fvQQ_@dj zjK$nD8xW{i!bae=M$;P%{|SiLN5N4xJ`|IcSMtn=&SYNRBS%lu6rvxl)3V6#lLtBE*!KBym@q3UC1(-0Tw zh${ynOkuo>EuD!%htdmIX)(o2Y>c`^4?f9#sexT4njQ2-pDO<6GmxLw9{JGn)mIxR ze+j9pX4)SVQ?fw=N#OAW4Q*uyRPD4jp036NfBqlO6#cW>klPlkjvLW!lw|*y z?jnl8o1_rVs^)Dl)i`4zDL^7bDuE(s9WX@5+gb+PPXZz?2Zt!!n7mev2K)8^OCq4! z%4JP0uuV3zJ8U|2*_e;4je&tdDToo|Q6SCjI)!JNZ;D@rEOYo}piARNVy zM=JqSB{DWdPnnP%OtF;|6cJtKtjXvl<6Wthw|zJAM6aQhU_jPn1S{IOONpq7LNLu>#)v|o};YWULZMb`w3@`ram(%_)B{4aEHb?{($aBsc z{g3rxzPT58<|n0kKRf*TUvCc6S`#c3!mBqcr4cWkxC@4uD|coP=IhzoTgOKvlx1nm zXoN7&<(h7nH5qvjdSA07MwC{GXwT}#6$ZQh@*w7PlldReE=XOZ0XI0TlrhN^!#^1W zo*BXN9_V%#gMRHYm_W$_c{kHDG)(bZeI~Suw}{Fi!wEn#P)M6pH`I_mNm8K(NC@D=x5OU0TbiscZm0D)ws1bSaJkU%g7>|j# z(wOm>$lP0(@yH6ucw85l0Hdd?n>A1+sYjIn?ok(O{L)A1nXdvc4v-acYHs-A+x z`a$v6#Q7_zdhkT^7}RDEsvsqH_oQySV$->Vs;2r0PiIH6d4WGUd*xZ+4wMc=b7l-k zOu_Tq4@fHrdG2KP->LbPnfV}X6! z$MnoV9tCj{3iH06HQ~aVs8|fhh5JQ1^^xXb+&sEwIIVPD#l@s+9}knRUHnsyASd`v zMXkJhWpHTNpo)Sqwzn&VCObvTOGp(VD+^(v3EC$4?_J7R!HAe5JvF>x8AKDj5PJ5(Mz8^ zm#w+u`{*{5C zRu9cAEfZ+5+b`JdnR(r&fn+A!|9|X$YcVOG{H)z+tCy~IK$%(tWRp^f`b706Vmtbz zsLfxOziP>5*zMjdet?bDWGp(0bRXrQxJ5HnBJ{T$`tp^PODUX)Z#-s4%h@*`H5G8D zN7-@1hWUU<57zMUFku_woj1Uc*GjTGLT0TB10Q67HfI=VePHaqAZaf42AWp*e{=oi zeQK`Fpe9+nHp2&JwdZ2T4(GIUR*>|`%^4tWuCr~E)5~heCO0Q3!Q_;DX1Bw1^bKwN zroeZD>BzBZUEp)8rZ96W9n6sG=D=d#X$1VOgI%m8uCqq630n2KN-sl%V5r7hQ#xx+ z^S?P(0FGc(_#9FGZ|TKqK;~xC5Qu%lPpMr{j;EyvbNHre1g?Ozii_EqvpsF_2tUqq ztbp7c<0OTtEJq0wQrl-0AK&%}bm#ZFzUC#u$C_RKYk-LVswAmR*MHkyL=6#Veg!1F zOm8HV_zv1)bpIp9eUF$GnhYDnmeyQNDaH5(q6;zpGAS9VpN8Kgi17mZ#xxJxqAs^X z&^=_c?~>J?%{_`F)X{S5xwewTjv;Z%zaf z*t7U0Ho_)sdmI^;JTbsPptTn6#(j7z4>9q5*&(?b%LcMT=F}*g8Qjm%HU**Vs5%qi z^H)p#d_esT9?TxNoIRM`pS{`^;{yt406w9hk_Qgy;~~e!4O#y{y`hoG!HQ~gj-#)S zNue3*=9S*jA*OLCyWbTRv>^Y$nC-*x!ascO1NouRE)9}*WyhpNy)xVAe(kUO55r)6-+U_0j3MlUR3Fn9`FBlgAc@J}5&mmd?vA-p(g+3H3X*)CjF zLUg4oI3Eh=RTeMc2ma=_)Ff9OII{4RemXNaJsNvjKi;e2^*kh_l3=jIOBZp z>2%>c6U}t2b|$*TVSD4YnT}zPoHfBr%ywkaofc!{13!E6-9~EY+?x-9h?zo4u~XZ; zX7=pxYoCRB`~NtNyV%%yYiaPz=?)O-$g@M`buBz6TmnDL;DMrizgc7W(J#RE`Y$fU zU1yk;ut910X4Cpae5X%i_~D;KTI%7j%O^g3Tm50*BheWC+RJzr^>El9p@$Rx-e(U} z(@{p5XX-bGe?tZ1L=T57eI5<~De*hp03PO4&1^rr=axQb zXXf^d6SL0ngGh`%WSGcCv0%+0SR2vAU~7t*7@iL-q)iA`>}Qae36+Sp=>Ni_ z^0Jwz#OLE*?m(pQ(d^#K+0kr}-DO-OznhQu z*hjdBm~SLQF|5NOE+i@H#hTrLYb=a@_6v|mqV~8k-B;no0mtTg6;Zh#{O`Ej@bqny zv>|<)?H^kKljIc_he3L^v5N6zyiF8`q8T4xut5kbF;XrO$zf*SWIYba;8b|OjtI7# zcV&k$q_vzz=yMkUKqTF{D9Z|ecHmEZ9|rb?Bcg^HDKd>essGFXCQw9r7`4Pk&4FC z=IW`%|Ka9U{NFR@E&d-e=Qo1l#8~kvTF_qJ#Ss73M{7$m)UXd1jyj7g99%ex1w=-G zlXAl+Cr^k0fLWV^kxme)giu17fKyvn@rza9Lo0+KAK@xDCn`fYgpltF)H~o9iO$DF zemL3jp6Mrf!a|s1R+PZKpp}3#Pzp^XA|58BG=?~Qg#Ys{{NtVdVwd|($bqEhgu$z) zKu*my0y4O`Bf*YUI#vn=%g`Tw9+`(vv2>SifZ}*Nc2_cw`f|X+WZq`{Q8WWX-_lRp zWZqVM$|V>tH-R|+D4+LL4CgAOjDF$@#Ln2HO?3;_un8H8c% zvth{LYXWj00lCiyv04ep2xaSJ1oxRqW=(v0W=K9|35(3zSX=X+Twmwmfj#^yGee4O zmk$s8;k|lTArTYx?WWiV)OTi_eb7v9&HRgh3BJ_Y$!nbk)})a?%&;Bk`}JBzXcZIe zcczQ|v0s0R_4j}L>}Y=n{CxoB57Ks}W`+Ss`+aBL{AfrK8U{Zv zE~8|4;Mv@>gv1ZJIsl4?3t2iYxZzPOmZi5bsh(n<0FcKBaiG=kfQtkX4hdZ_I5i25k4UZ!3O+~m2O zVD^!!GqM;2F6zg&@E45?HtqH2pH}#&Ok=VZ& z{E=+Vq_^=nvM<0YtMA2qz>Di#3=p@u?+FW&t5z$%ZjN=b$KqOPSrv5F3-{sLHqM{F z609ouscFTfHuy*maw^dco0p{AN4OqOA7-@j1?WzLbQ)r&U6)t2-xQ>m2$SX_+{XhD zcWd014P?pfFWv7+rq6bIFM;)gaScHqf;-wWp!70%jpcBsu5)&qPWL2LLH9RNSm)2= z3p}jT9MFEcGAD_h25v;A5WUi_H?&9mCm#})BLeY72%)hnfkZgyY1IGYFJE9 z&n(zaJnnDkL-2L~DCajU&8+wjJv}zPdvO|1I6YE)f?~8iOJXf!dnJx0Biroy-}&4-kS~=yv5#ZUJEzwiPFW^ zlR53@xA${hWKrQ`mTw2lz1hXHuE{(fpW^kqChnrHdozlV5IGEAr?szsoQ#CNJ8?bU zh473LX8?t};t4*mdEVNevM_`QRi`#cNCy9YN5P1NUYp`kWrw6-i7(J#jv6Na194TX zFPzZfhSAN=tU&<fd>H+?M$jalj$_4*`Bxyb=8cg*B}ZnEr=-v$?m-dU6}`qaMWCBV zqwHS*L#Vr#D6NJEQhUIri#yTYrf$|LbhWFj)4AEfZBiNJRzW*id5aL@$qbjuo6oS> zX24yP5Ktmy8Jcp3nt}7n^d53tZ2yF*Dr-;T2=NrYZmxoIw7bUeo=}181|MO~(utIi zDD_LZ9BS9JietD<`9zAY^3nA4*aOD}f~5H{`6BYE;0<}JwR5ETPV=jvv#eDLR(`iP zi>kr81n-zSc!d5jdTE};ex#;>X<)qu)J(zrn)#|6xN0d~ulKYDu%TJGfGc>w~gME``? zDluR>p@|in>6nPX$N`z7IYArl5Vr6Rz7n%8Cpb%vn2~ivLBS(#WUUbtn%Y|shKf&a+lr?!4sT%NpY9Au{<6;@wZpi+5u&`XDY%J zTY1HJE3fcYmd0CAS`~R?oHf_~IF2y~|9VEUs`j%vogPt)!p|d;htzl=>_0}KX<^fx zfC@|I>k24ik`R@)HVfb0MCbtE>TEb$;NTj?r8S%F4)H=xiLu`f(FIn2Z3otv-_cSU z+{vDxn{ZkPA(D_nCeEWwvNfa`&YC+-p52af9a-;xtrO_GJ)gE@8n=p{z$Ov~wTe%w zFd`uivIWB12s^uD`EktNchV{0w}ty3j}`tezBJrSFyCJ32|Q+qa69nP_G!XS{Y$Ol zSX_w89VXYQM4f6u`{uR#8&B}P_^WSz^B+BnO@)3GR>r&EHSuZF+OT*oaQ$T14+;T6KKu!f@9E^e_`)Ren zjRAs>jicm4tPKyG$3f(4xpX@3TXIsaYp(WAld^n~xVgbmP zlJMbTl3w7!{jT_MwiyDM>JO&TCEAN|pS9(SE7uBM|MD(CzL=cre{29&TQfQP7HpJ@ z))2f)N-+^Fmfk#9FpREr-L>KIFtqWOkNeoO;U#=x8){ps!y9oGc?-g#vl3(}Gtk*p z@>adoK3__dK1t*({JHRfx18a7<1HdZlcJKO-)x+F>zT8-knM}#P51xM}p!2ZwjrO4efmP`~sE^u|TjY`G;_9^Ln`yJ5grIU| za*>*^moR{Rc&vq!trK3S#AL0-&ZPFL5!{_~QhQb8oRAuTYZbS}WSqK3QeI=r-&rdz z3@`Nm0FLC;W2_Qi>D{4i+;osJLP=zNx3|4AMi*0=xALE7tLnNV9V8PvI6kR^t;XTW>IKfQ4W9V(*s3Ew!<_FKgJ(-~zQ>0|epHYm z^bG9U;y?_lF=1-=j!n(lxp#XzfdyJCOik5;(U*$9Y}kq+G)7k}QZ_E%I{pZoM)5~? z?l77{r`&PsipZd7`_xa=rcMC}U+xpzhs@M9@$GEz{g*CYJXc)Qzi7x8U;gGlO3#8g zd`!-)=UonFUC*>f2j>d+TJp!mWr-+vUkz+3Y;7oa-}W&`)-uJi8{iQ-%G-qU`k&lm zpwzv-L9!kOFu_qma+DI=DRz7bOQ;#asCAZu1;hf)hj2TSulmXFK%mBN0kulGOfgel z5%+S1ockv^Wc|pw=4T z#)+z2*7R`#?`R=WP#5e7elHUfw>$@L18{m{n%Jzcfem4ROx9Pq=MFd<21y;&K4i$` zyK3tsM~SV|clkOkkC931X0S!L(L5^y2kaPSL-&vL6>#GI?R^O+w4vEnA09Db*sq?{ z)T_6nSIHS~gyh#5_5&k*1rR;3y{{6L1JXLrYjMDt&`We)qUtEo>)R;N>&_^4>P`(i z@6HKJUdEYKZeO zJd3B9@^|t3K}b2$RmA{BP!-b+80f4`IgT4|l;c=woVSeE8bc-EHFR)O5Sq62 zkUUK^n3LL?Q5*S;kNn|sEtpuKXIrsI&17V$aAJ#15#k|YDS-jRU&1a7p9On4YqLNx zy46`|b!)RgU&Ik3MMR@Qus{lK9YiU|Cy@$h+`!wNHKnfgJ>dYddl(qQT z&|(d14W&d1vTYi}R9wzd)Lj}!%pA7FR?X}@5MpF zlKLtOg;($GHTEg5yk&e1s&r7_%8N@L%YRE5U+a9X?dbhQpNMVg{lzc=((23nUQ=)g zAS)EJWjSAb+)~CDdqKP#Mwe~Xa=w(Vl4~pjG$GiC<%Scu7@TN69AWMGJDq~?ic%~a z+R#c0W63tZ!7gneS<{+ zk(8CK%fkz*AmUd!m~ha0$u3JlleZLYjPx^dmzpq0TNnIK`Z8K8jBIE8cW9cV=xr%= z4FqH@?o&)aFSJndcpI&7ptz6szsXM=!o8}cA@V^0SP!?foA)HriYhD8p6ngAJ&nAx zG5SuILxS ze~2mgfcujhn7io)R;&RtN7Xy9v!Q4d{i+dx(#OEHJ_hKOy&C}ElE*1~VU>qU9MPVK z3P)HcRuz;$g-rg3*28>;9f{Z!-E`dW$Qi55I7maIbP_)id{gx0aPg-&!&*Ga4yR+! zDt}Nn=gyqHzd;3}3WeHWPONCxx=^%~W-tF9zVMh5W}C3deO`Gp`U!52bHjgqZEE=c zvG?xLmfcmI?^yh(L)mrPEN=~3E6cFkZ0io6&B$W^Y6)s|$!5b=1?G_zsp(aXe-bHJ^F~P3z@N@-!l+}z+jyP z$Gr`bI2iz-E^S;yR%Kv?3Ww^kn^RkHs7T2xt7z2;B55!X|8iVTe*Yr!srJ}q$~Giw z8#do5x<1D39(5*>DDUvmz$9=d87Hq24*_tQc-Xl=$Hu4?(Mf`~BZiQSZ5DYXOGQ>j zgllO^aT~s-MQqhPU{-6Qi9~n-e88c&2Awd;LuqoB;$c~0jd%)Y16s^GEGe|QE?V8N zhmZ4=>-|h~U3i$6c<4ED3pXn2iG65$kogp==N7g^@pH<;;`93{VjG@%Cw6W}g?O!e z3 zTEjF8j+omPJV7|GU9b(6VgCmWuc}~(z0Rm8z_B(+eI%6kT5S!MdKrMzmY2lBmEyf= zny~Lse-5EcNjBP zu&M7qYKhp`0ju?;XIR&f=S%n~w^j1}0D{T43z`bQuJeq-uV!0<5x$%!&KlLk@>p4Y zlnwiiD;pBpa1vrD)yr_{I*_bxn#xbovK&)JhzbTEUC1uK!4`RqX5<`qDBH6@wQR|G zfhPW7SB_=h2%UAfMZuu&<7m=$8(%;A4Ae!BeH-P4$V!v}J$Nc%U!Krj9xaL=FQr^S{Rw-;gV1Mn!IyEuq|YIBHksa)8t3v{?`aDM z49yL*|KcODdh*3Bw|(p)t7T>9eG zVP<@PMc(EKdPPf+BaQzgw7zDeOxBA;$#3?ee{U$~?Hb6sn>qa-&#o$(%77cc z*&--2cJoNlR>*Jk$s>xmm!giwFKM*D^hAiLT8ri1tJGLk+tRuf$%Qu zZ^zUt&^OrTqkXt3|5R1zXu6umx5=$9yKWU|m=twfdj4Wr@;mlSQDPe(SU*obvx)JhBqWrLI zTq-VWH*yQDZIzd80Pfi$vCztvpXAr2s*vY$uErmiPJ8W`7C(`b{? znQV{)7EIBEya2ZL3b_OR>Tt)cIJ8##!PGBH3qv+Zm@zbYUzC*CLtaat`)&&UITs_qYj1ksg%7Zw#CJbqy10_fCAu%hZ8Z7Xd!OfbPigZmI zq*B83>(!d29B^Ohn}=y|9ZYZ?VZEj!)YP7Jb)u>S)=AI`6pz3zlSs4b)PT@D4zG|M zYEwWG!bUM)QkgFYLQX!4f z*?&`5^v!9^toxg6-@A`(wH%wxm&GF4j6votjjhrg5;LeJ9V@w!*5rmK5UW801z7X2 zU_lC-V9^*IJ}G1})x~HW7P?SxDMYjzB*5V{p6g$>F?;M%%^7p0sr}xR3p{CtVO*nd zAn+x_urVTcSnVKps9iIZJ8=yiBzgY3nE#OTPnPF&t{K?7Y%w zUFR_j=wP%4F}7;1kQ!M@j6q5OOS?|Z1L>%!n!MK~FEi}$RiIjRMeQeHkK+RgH6@iL zt|q$Hfb3Ht-i~rB5=F313@c<)BQ2P2MPr88W%j6?|AQIxLec z7-`zvj6z~g?=Jo=t-wt<8?uJrZ1JiQ2bGDp5kLCNDnI%r+l#GY=I(yPP>$1IPU69}mDGmE=93Az2|FYmfxx2jQ8BlP@I!CGXB1SXI4Cot4ao4T8n6w@ zJ6}esWiE+COh(6VD0DV6W2W2t?tAn7XT5XyTyo>8`I6n8X?=$Eex8L7Hq+-_7;J7e z()4*sT`x1Df7jqzPptmk09~)K-aLWWPtF^b0fd^DSI!0jKzq+M`9R~<Kc)wWQW z2bn`Gbkhn_o2BNl3`{li8X;)mMi@6ND5oZ|zN`2Hc|~^IOFbnkzJ)wuy-VcE8dI{C zr*G@IeH7sI3UX>2$i?ZXAcrvEPYDpxI=nZutIld~YQB z3I?e>q-+4nV~{D;DBeLv14#~SvAvQ1zf<1Qwyb-#uM&0ac0(7fzFGY{KdY>Nw->xi zlx?mDBKh~IR^j6=2Y5j3$_?B;gCJ-W|1sFHp?MSFtKb+=63}mQD&Ph^veZmk;iycnQnX7MDYovcqG*VG7+YG`N=?TSO%3?3P>U#0*=-2~>r zL&Bk#HhkGlTuP(D^+txeVt9fJDu)4tJy~eP;k6NL8%ohvfT~*w5I5RSyslol?YDGkRk{<8!xPyEo)(2Gh4gt zPv}K_yy_*qX%DlTynJu}g!hD&WA7O+X0;K+SP)O8l;H0<(=+Yi_bOpm%A|EPfy%); zD_{7mY`L@8azi1{qO%B`*xD2r66lsGz4 ziNNgsosY&qU%+5`M;?Dy(5c04xQ6Vv5OL#OV>8X0XzK?_QWmqn3V= zW#T-wL=|bZxL-8S1B&Jy^=Yd86CsFa!#H{`sf6Gfy1mtPws9N^;|MrtRAXF&so2Oh zZnM8d=j#_Tg+H!_k|Eoy>$nnS&q^btq^}lR^InSfG-yAVAH$&y0w0sW-ojgR-*%UJ zD)NWa!G_5G14jxgf%OLgDX1^BA$6pRW)f=CdaHOS6?e$B*cb)}woc`9VtG2fBi(WU zY*@!D-x@8 zN`o0#st}Wn$P@)15$o14M8dn39+MC!7qS8;Kc@IUWMFLIEh=Nx*UDo@v}dz%BIP;( zc-JCG6wlj8H!tK(kLWc5-bCrMgg5MW+v}mSO<`NP%J@~H{%>Udi;D-JCr;o^Gsd1T z??*&m4i|XoE5sS;)mSnuaa8ejrjF=|nS91A{+UN|38(Zbb19_k3>7|r;V#;S=(ScW zAD-K0w{*=;ceM%41a_;o`+tvZ@BjO08!$=a-3gqpGx72qCT>;L4TMqYV+XAA@?0fg z3T!o?NfXGQLXPTt`acko!CHP!X#+w_5^5>Ep@l_+6`A)oPxD8 z-qQ?3QiLTv@E}G2og15aJ{Y^Cf&=NHQ$Z2C%0~7wib@$bbcdY4Y8sT$wOU|sC5qY) zC_Q4I)!4kC9S<68?U8bDnz?DD_u2w=>9DSmf?zKv|B{b%8jbY%lG0*INRudiKCF`) zhr}vPN77oOcw9##rkV-~u>;4S8h#Fi5hca+@=}xjN+KrcA~^<5Ud;X%t#&7A2sm zgxLYt-z7GXELPSu98lL3TW&EuUOk*X*F*^rQ96R`63S4J*CdFUb?2(xqn$vx%4+JXDW(2J8VP>k(qQ3)E4@)uLbPw18^bJ7g-9Yi4#|t+ zCF|n^i6mEwiNH47s}K5xaF=1=Yv;PXKehe-KPAII!ZbT!yN}Xk*kG5ZULb z<*2c3RukO;tdVQKikYBFYo&Lr=ploqz!Vg$;bir`B|cW5dK&Lr1b@Fr@Z*USjmIV` zhI%0F3Y`K&#TuZa7kq!LGyu29&#?3jdMxL7(18TWJHmfraiaZjaLR9sb?(8+RHLy zh=G?(;x?|d9w6UFJ`mZ^QGQ5jD;|)m7!TKi!Xf!TA}OvMyEd-4_J0qpR8to_IzcMg zL{0Zj&$Ja!&9HQ} z38S(5lgDE}9Z18709?sDa$_F(Wad%vxD9bhS1QFLb1@GA^(OdlorJkvai}2+c?Qi) zU?dwQD{+3!Sd<61b1Z?KD9p@8_8L2(V7$+Il$~hBHJy^3jE*`tjk*#L-XRHB##98p zim8-h!kNl5YGs_Y?3_BGY$zU$8v1PQglx2`sW<{`##cTu?1IR3CvScysYW>GF zHvJGV;Bt%x$jCv+hdBuI5k{lKFS&6!M&s(3hJMN!jdKc;-F3^ql*|U|M;hZ|q(fk~xKX|zM^0PGhpHM{uwqHR0 z!Ftb8jQxyjjP**pGDE%6uQ1eSW^4pIxL#D_dhuns-X})5-df;#8>0#mU?1grD{3{M)a;@)aP2!y2a2q2WZ$~S})|>(YErzk|!tW57;&(hWK~<_q z6+mcLNtkfO>+tT5DN7}(SIW{i*u(@bhq^Q}hQQ-S#;^;AgIG1o9EfljU6?D;2@pr? zt2m@EdB#*waM={lY&hXj_MYuFX|>URCT$o!jVewfQx3dsWXeyOv#ktm(T$R`831s@ zw@lctlStzV)ChN@qI4UeI8xC{ZTfW$yyR}m9niDm;SVrj5_ii}0+1zd!^dh-5IBoW z%`qj)dD}=7gnq;mQIa<-cnU9Z%?J%h(V%rBJJSejkjyjJ34Kc16(h5v@)6f{!^pDL zBDYpEy7Qzs*VZO5&@}k{LvTN~gM`O!S}wztyewy_H7zb1c${V=y>1eR`$w(L%+Y_; z>gpQiEb31r_<#nG`ca~;|xhDQXV}V3B(ZxB24s0 z?p!+{=h`0y=NeTAL(<9-_-sxb%F8)55uUA@KPo-KaJu~eNVJr9SF^0RL>!}lcS0(2 zG>qp`9Ap-?JjW-fSltZQY)8U_Piz;#qIjK><7jC!x0qe&w{6^?Mdsk_PY%{S=Bp4X zg8Nul1@dd`pao>ULr&5-1nWBY>x`kbVX!XpV5J>T6M3voNg+CTpm9@1fIr2vWK}`A z?vtgo0fGk}}w$QVF3FcJLA6$Ge_(FyqQ$r2w(03jnQ>i_Cu z@yP)7D^~n5-tH(2O1}9J5X!^ripG7XZ&RxY*?4jnSp@0Es|0x%^C~MM%2&W4%Gag- zG#<7X3fD0y0Jyp~FVKkr8TDQs&HP!OogWqVz430g%8`N3S=o>-W-bS2>8%H|byw&b zO410)p)kYz~qQ__bM zLIF)t49S?SZ3t{a5#3vq2@flA`ubD}Ptn(5r>{>9vA8^!&uBn9Dm~K#wEuL8_VDXZ zhZm^68pd*@LT~_@44(MlW5Qy>N5P5sXq>ZmBeG&8eVhR)l-C6&s$uY=c*Z_`1D5zD z<#ZYN-M}ZkP;9@+DnIEo@4@3AdO|1^<&>*@Ys?+~I}+Vfd{sN-?$Hzc@W$}Dtp~iY zrJ^M2^7VOFxJIj%m~||9y$6bzyR!skUpi-ObYE&%`fXTz!?37l^@mu zUPVfe4)7N5H6MlVOC;f4E>M<3+oK_;BTi11UZb?VSoSa*1eGEu-?)4se;%Er-Dzr93p5E5D!FQ{c#{?2Ff=10v29&h`MJiqrLr4u^U~aU3^THd#+> zyycTJbp0RJei=4Laj+gI#raK|ZwX;2Sm!@px}Z;ww$|`xuddlyvVQ zbo%Zc=D0rNqXwNw+hg!w-jmN;yKlU^*w!f`FQG!~YSvHZNxD(N(Xam>%=F18S>)Bb zVK2(2k)l^F$SL2!-RI@I!&=PK+Zlj9ukHkJ@toA36BZ!m-T)hBpgJ@vojF4VRf`F* zf(U?9DT4l0XR>+q1d`6{t}e+k;&1CDrG&x1EK2)lvYAwC0XKe{@Gmfc6GdyuZz|%9 z3%rF5M7gg7$+z6ut4zs`N~^O8$r2RHbz1p09##Eh1hj38?4)~n1a!_r3&=4Y7s;4c zspO4p-UF8vuG_+Z?1r{Y1|ZE@`&@uk*sBYG)LTs#M1C;1iZ-5JSRTj{D|w#ctt#k=Bt)4gLGZ*UpH7U8ed{$ zX`3%hUu|kXvtVH}WjSpCJYv8^5)CU-F$y;S(a>HcfccQ9s^@^B+8KZ<-_nBs4a9(9 zU5uPb!ULVfp>{}tiC(c9SR`}TTE2W08Rfk49918=$wMz+JtKTcFQj{~kG@lDkhZUn ztPF6Pmt|~Gg2hm&R5x=s{8E=vYP-kce_?NAfNbVP@ps!7+sLo}P7+|gM{^PIB9?*a zb4gZ}grJ{C&3&{(l&${FQrb+EAZR}0g2qaqedfuqJ4V4g@3wszcTI#MN z6i}&5zd_bmx5J7Z+Kd*oQXY}kH)AQ|lyFmd8*qp{_!>~-1k1HzrM->Kr=~cGGm2|6 z7vF?sYS&t+Z3u0mV!Oe1V0m>CM61Y!@JH7F#Y{Wl;A5J&A0axUx&b(zuGu}a^0N+v zYowQdHUOb43DQ*hv3B6h>RiwU$Pk2Z1e2|H+Yifw=ph)!ib3d*Lujb{YDbh3J$)?3 z!%Uq>$JE}(eMIXT(c_i;ceR%hNzZ2T8j;Ym8qs~e;h;Iu;i~UGN>0ca;8|%X6}zf-7rEVFT4jVo)ojII<2d znT2CE`EGVK;Lt&{SMy_;siG4vh(dikk2$NmgUAN1Gu{>hY=zVg!HQ}ia_~yHcKo!8 z9PLl}vc3zC97|L|P+rq&Kg@yVymYNz(y)71Jsf*m$N%Gi^=!>LH|BCs`1N$sq+p zIF%FT70)*|&^nZmd)O1a#6(73DuL@T0_W;r>F|Zq+q7{u%6mF}11P=R+M)9jARK_lBO}qAW>~Fc@n~37Wcb=>(?9oD`pOER8JO$9Fe9_8X_7@}*6a zP?R8n8Q`2M)+CLbe3Ip8YY1M03`v5bK!#RQV3=eHo00|_^?8W~Ed;ic2I;<>kr5nI zDCf;&16d}HvCT4!sR{V3d`|TN`mAi}EYJyL$8p*Xc@M)LW%Xm zaEH2RfXtzd2%>AFRP*vRST|Id3i}sS*QMsob$uBRF8Xrm3*lALn5A%~p=X^pE=Ra~ z4^>t!y?Yk?-~ss|-O-@!dpE!yO_z4P^rkW=QunR=+EG<7!1!nuje9N@oqwi0UQAC{ z#~Uu4(br_XS54HEapg0rAY*XD;8X|o@&@>2Nk^{aaMF)#&izc@M2GTa*YJ>hAUd75 z=UQ>A)ow$;00NH)p&x5pFn>}})p9Q;sE zcjf5o^XFnN-`+m*?HwcE`reH>Z;3&`OErxd(g3B2GZ>#nddncj{qul~ z){pGDpS%`^iuG7UPZsenK zIGdz%`zt#)IC|bWfW1qZRBWuaso%%bo-%z(trExA$*?6*N1mZ{;jZCk73+@!)`_2iqLm zz(Duz;(%78e(_a)rF52g#aD5LcX5U@fXWr7#p}{0?EA|7Lg+=$ifaIGx+rZpD+ik_?!5i-YYe8Fi-^R z=xLD_byni4_iQaz>v+a*nq!Q>MVV5fVT%EPHri6a05XlaV#D-{n?*(Btn~vt$Dyg- z??FQWP{s~T5MhmkaU5M|Ds)xs=F;f;43=&3S}F3U>DfvNI)F-)`8*wABEp9<2lu@h z+~3}A+;4QxzP)u+=fZ`Ej*MX^$Z184p=`Ve6!in!DNiPG!{#^rlhK`dlInY`=aD z@LDr2`A{E;(9=;bWcg)sFH3ZQ{c4eSwT(b5p(jRYXU4>^!r{ZQ4Q9VT$#a5-o#Zr|RLh7@N=gdwiKU#lQsib2z{M}?D$7U>;-hyn1J_YJDEiU( z?qL*>;>1NnH;4z@Uw$m?lvNBz&Y3A=fEL0R#{p`wVe zsUz^xoe2bkfBoU5!9V|54@+qiwjx7imDDeKH>lvX@qRJ%LUu)&SE0%*wgAwO(2_)v zW64npwA2p1{F2%_Z_68H*tG2IRSVxu7=g0Qaf}L8^(-Z zJp;*Vqr95$<|$05jFyJue=WRaTVAe#T(6|VE7NOkLr>1|a%02b=H=BpoNS2&vBboJ zq(tMdl}k8;^5rCcl@u8|Tcu!pmtHxHW15co$SqF;azl2eS%B+v(H|!?dy5HW1y>u4;Ugunrz z=X~2kIXP}11YoIP+WdM82uByvd3*_6`&SMlWpsX>AH0y#Wt8$6ZxI3IGuh(oEk2?B zC4H`JC2RVG&NuYAx|M9|6Gz2SeXeaK*Xi@ht>ne}#6R{jeID3?ckr2RC8zY6Z6&ws z6aVHN`pmbI|3#maq|E+~%q0lPT7m3+u9j%+25+Qqe7 z$;a(t?pX4eUG$G7pR$YRY$cD|#nG+gi+1tct>g*2cpgJdG{QX$)h?dTQ0?M6hH4it zV5oL+Y%BQ@yV%-F9=40U$CCeG7yFJS@3xEm$C977iz^tjT`VwWyI4Gye8?`AjwK(q zi{)dUXdPsEMA_x8^xXU&1sJTZLc@%Y>jD`qZS zlSCQX6`%bqvCkz`Abn4f1T&EIX0~9ThqFbyf0O`>?jO&V?E8!H?dkcK!ButtTeD^R zeu`o#x_^5%WuJGDhNJIyW@vOg_j=q1`hE`zj6TnzIP3GxG3UqY;-Q$t3|+h}&h~Jz z2@0^mTzB3ESp#Xg|Fx&i2{GyW?!X{d6(TQoHkkIJ<(2XD1(y$yd@_ zzZqwlU3@&wa=ZBbI6Gt)kHy)#U3@A=aH`WTQeJh_@W|Bx+8n}@7O6Al6iR5eIe3)J z$|=ZHnJzgFvy9@*3+~e^U=BB=t2dlkg`?3hP!YOv0pwL zY1al`gVp zd?n`v@I9;;fYmC}kXCWeZmZ~ld0WNASFyc)jk9@M z=)x+hvvL*pNWokXW+27VJ)R0H2 z9YW}IeM-306;KB8o7Ha{d#=d?fFp;<_rn^vK8<83Dr!V}!)&V>I2r9AkTM$G{<~l&?EkS9vNLkdbW-%;6Mb z7@UpXv?lLF5~zXWJc&1C@H*aJpv-zX*QU*tf_J<$ePK^0Ds(h$HCqsBFnxm39&-J^pD*8qH|V5+Q8)IpMDdLimdLmxLlnba2waSFrD(dHE~N|o?`{_@?~}91 zpa9Uo>0qH?CCgQMBNMSzYKJD;RTJ1iKKdJ?qFo>T_*xCojkQ{qzi0tV$>FP#d6;m< zNLYziL6*kn3*O#Mjh0$|37671K zK^+`ZUOG?@5CF#<1T2hT58*n@7jD=Uz)c76C@OcYn+DlI2IuY=bi5N=)SRWbD_=;L zZbJ9qI$h*wvxl=bBA^Kd*zCEBWU{oOAX!Tc*BlKY1KJ%00GfLP^aOKYE6sqSCnteS z)K}tZLwJgQqbBck$(F7bQ#KJ=BGlJ4Je~5n%v4F#L3}8odpNIvl~}B!XK;bTTEmGz zn;r$)^hBTq1D`o`aU|m zRtx<i z^z&a@8NA~sv0N5dSYcz1KIm5SYO&v1H!%LkpWc&B35@%_Z4Om5)(jY%A`BlF|{ zrZRL$h_14VR;;UjAIz|XZM!hW<~^EoIs746foe(qx)=$DiXVI_j=7A#z!Gx^e8IgI>f zEJRd~bQ%9!H(h!p$T!}Q2A+0r69Pdx8%pmNw}wgioYT2%iC8~MZb=WhU3Mrqw#u&Ug^H@z0&P4I7i*6C^CDU{indGn(4z*vqcP^A zgoRm&U0B?#(97MBvkU`Av~+3WF|!Pt&=X$d1vnaj%$Cp|`k-b>Ox$5rz8=3)l%YMU zs1{tj3u)Bq|9Y19)e;U(>jGLT3Cxs#bQoj0HY!nBx{PF6LRHu|00~T>V*;YFDeN~b z*yJF8nI5r(T=nz_wgHOR?gZjZsn0k=I_b3LXeug0T0WUC6G`;t73wPxxT1jRa`Dnz z@-<6kSSFRBIr!^8yMOz!?T6lV;{LoN8%*ytl`En@jr#!({sT3jyoMY2IZ<9jH!Qk3 zl@taf%)G;XU8c3d0S4;n1?owmS*f894Br1Qx3}N*&=dWtBk_voDKTSC+o04?ROB9H zM5@!3C#hJA-%sFnd9K@RHc3TD;>i2?QM;>q&2WdB<~-ME>IMV(HTEQVJJ8yZs72sQ zQ|P4upO^-hN`}T^_My^oaFHPw+h3>HJ}V^DG{{1YdWv?Z1{bmPO^m^euQX%?%7~da zO%+#`2$?PS&|8(4wVGGS?2eLCjOABigQfxUV(g12S|AbrLaKgJ2FkT8_xbzbNi6yH zg>QGXrdtZNYjDhK4{$r+y?PMKWeC68!rzds0KyWV42e$WYy28iNEn&eTw7eWf8P`g zgNN<;CCztDU*$#@0_qd@d3xY34qpgVVJ(8E0(6CHUpEXmek)G66&>8xd-0pFAg-R`i`2k?(7^y9@zswl76%;E zqg21{T$oY`N<+68-z-d8qJsuiEsVho>b6xmnXl|vjaFEV68LKY_?EE{0B__ij$Kok zb#GHlUR?a!U_s+NJTPl9acR>CA8>JMOdEF>$q*+i{)|6__`TuF?f}R}0FYGx2*VC4 z$%e&I<^?OjrVRQxIqfNeVCTk95 zi1d&x!b1Q5N{U0?7gmLl604|3yT$qcy-4m6=U#XOC$-HTZ@+$9LM?Jh%B$v+EJ3{_ zA>M$uKNn2|mGm`yMX;f*qHPRyTo~iRT$^(;qD}(f-9b|d2Thg{US%UR)3*OWx46nj zxlr0ZWjKH0yI0rV{i&q5+TUg8db8x7OB&HqibO(|%4qCM!K+Zl=8-TW*QnYjvxAJ@ zSK%NKLQ?_1nTBgr?F)yaC2;G7FV7DmSVgIj3uy41Z_VxT;)pMbsD8P)-lgqd#W!oE zaQh08XQuWp7(p?>t4)TU30A_$k8ln)y`cnk4B^MGUBr67>x z-F`lcUx=@d)<%1~#(InB>%EQQ8t;oNijqos8O3qNcrpzjpElJHkOovXM?c*j|^NT+eqBYO<&T#qg?(CGeZ3@69#*LIlY0c&*7FO%8by9vw%YZ~` z+TxwAElLCIzyq)-aQaJ?GzRS|NuAK=>!qGo-gtA;v3@oQjsbvDOQJ7Y5_V*2NxEpecKg4wsK)H|{jhu1*Zj<#8$1DTRxI z8CE@H?whHyl+O6WMy#bWec0)AZ>dap&)Hnbv$40ruw?%f#2mYUxqu`NdC2%C!PdS; zDfLrCyFqh;N>7|)Hd4Bs>d`S!y>}>kCHoOEIRP&gSKflSKx(9m_ozI+YbUHY)&&ZU@+I7E|Qz`W$_VDavvX@_yB{$l-KkG z^@G^5ZERnCUnvf%{cCQ)u#rJy3~GD(q3y?DDbAkk7%4~Uwszxa9!*oW#~8=o#bO*S z5t$ypGIS#1)eZ}(=VNbt)d&^?thnwZ0gsj9@1m1;+qf>xskO?+(E0pjF4lw^%2>V3 zYb(WlmOC7L9fJ0+W&UOfd$q(sOwEMpjbdR-SeWnvymY1b9z41-2bCPkpv7$E1Jv@1 zUF-)A)}a}v>e7~%4wb1@Eq3T^1+L?rrH1h8O7xQwDBn-Z>9PbE^F1hy!V$Och-;*{ z8{R5*FQ-_k>|7f-LkF6`y1&+G0wdCBqKfrt;6jW;Mx6mMesFvHO%Jk5#PPz_4-leU zj7tN*L}?TcDKA40ZYQ0G$Z-7qYU%hZAI0g85?^~%5$oGw7n%~G!Sa_h58gGQ=Z>g~ zJIc6EW7R7>C@p7sXXJ*s<0c6}^5hD~?%-1i4yis#aM}4I8ksv@4j~EEi=W3$bGk#ZPJG2Dx9Z01|t+r(tt|x76n_Z7CrWm*R@abLgg5>{yBt-*(L5dBZt8?V&w1mYKqBe7l4n+Pd1}nocU1G& zh?YEpf(8{X;Dh9Nbv;=H`3dpZW8BR4lr94HBUTAN-juu*d)b5GDL&@AVPtzz)YCA! zwtCp0kG<(WD^)@ltGS#c!x1$w+ra!x2{o<;;^vRM2#&()46#c0!8YHI>i20lcW`Nh zg!v{afD+MB0W7~mSvNB5qnE?v_<+ehlJ$GE+n_-l9kjKf>ioDK= z#v)SUqEE#Y`2u@Aa#!RFyn$g%8)g3>lS$9424_PiG0aMs;KxOE%wNaX@TJn%aI9=Z znz1`27)wV&UFDek&5fZRz?xo>?$vS=Rg}QCrDi+L!&zU;Z!t31t#Z#;S00zw@J?`~ zuNV{#3HcY66!5g%5&Hp`Lic$^oO&^=Ewh^6AmNJYlF!p&?+D`l5CiCXN#?YNnw zaTxilprw>=tf=B5m(tD+)0MIJp+$WMQx@nzV=yh6XTuZT@FLG?U@3HCeJKg!R}^y% zzmIpUJ>=F`WQ{Vh;^>VeA+Ip_59lmhzkeleipAhhvv&*cDp;$X1uw6y*XyHOLP6pHP`p%l+h#?M;Kps*9P}ruEG6m6E~;D zk9Am$|7LP`E$*+Yk5$i!n;Q&#> zsgRIO0!w)HQ9li}&kZ)t=j7hb$c3ZKtTeqVlLuGCg*vI)pH1f{2UPp>0CdGKdrPuw zo@f|B1hSAE3b~iI&WlPsGrmeTL)RBw)iq#a(38&vC*M2+Gk2l(<`Xt&6J$*+46TRKSzlaE9vv_#RWRskc~ zdBHMg@sd4O9Job<0}orcr?_wXP1~Gk%!$t|6KqA&wi1(gxm*|`J%db?Sl7I8pc;nS z=!DimOm<5_;tzBuipkDUOm=RwV%&0I1qo^6F2Ofn5`xJp$4sfRS7<$|6quo$YZ^Q( zL{9h=cnE}&Oyu!i5`^|^3Bn+rB!Cb>%b^0*lEJijBe3>cLT1=w)8nT*c__cTkSi1uJ}zGW1|AQY?ofIzm2tGd5# zf!)_9T_-7CtjZIj7mJUr;p?_iV<49(-kAFiI!As6N|#@m?&zUAVX2L$I;w)qF4EmW?WEX`QhT>f?ZR$RI~hMJ{pR!@#^m(AVD!FR9Jn=GvXx#?*=RCyiwNRh zE{Q*1S-nBqp49?SbInZ)kB@p6^fuxfl~aNDxnKSY@xL8&9z$@O^V37{lA;5GFQP{) z^+sEDedYk7oI41PED>U_l(S>8!t9g*0UMb(!xg)vydEm`y_Npchfg>?mU= zrXjgF6nnGIrzQpG3yX|&rj ztr`CGW@bowYUUr0nGG)0-@UMyxpaLj;G6IIPvP|I!rJ&;{Yg%a@9ebfk*S3ztrKk~X z+dH1aiE#I?F%T*xn97hYOT~5jWYfzp5J2SD((g}W*5$B6vt@L!+zqqs87SVKR9`pE zw#T1kvUUWWZ@&m3veDiwG*@dwL4{qW7zo}2ZN9h6YbzkN(WYd9q9L}&Dbx^B9e>U$DMk;?qF&}k%B_Nl@$KQKd{;IgY-05WzBVolw%5vlX zR4pT_d5bZ2^R=R^=G}&|na|T$=CFLx+C8ujJv=omUbK|1mBot!tW>E(H#v zo4dVy2~&&!5^JVPM*mHXyip%Hds&7nRvY=(JCqrx`i`otz|Ty1o=c)w6??vktI&Lg ztB};^lI$`UDxO;iEuBpnYl9&Z90kRPr2E*iAJC&IRy;0Ep|^GK&ZXwR<#^PEM3l0wxq8y5gQ{}I;axi z5*yU=aKYgW!d8a>b2O zNSTD|?DNiMN``HY8aKc%IYIy##IL-sb)$kWZcAvnB@)+EUihy90g8YR|ciWH09DKK=M3>pqmHs^tvI)Xl!EW%OeAu zv}!)Eu~i#|A4C-3*DjS>GF+s@+rSj}zMPRg2_%lnV;~tNwo#BwL}fQ00_C~!Fv&VL zRCb{JL!z>IlKv5uhklKns9gFq{y|WA6rpy~SaF_2L^r~4q*ta}x;}L58!OT-@44|< zjjr!vf z*qUNh*l42KQ0mFaypkId0G=CZzLcQ{LmDNS&~?+T=1yZ1lsvC<=v0+S>pPzk@+8^1 zSm}#bK5(!v=b0|#c-ZCf6_H|Xk zy+dSXOzTH^spR{>Go-v+POeh*5APP}48xdmrW`yu658~b9chos>y>$e^`+EtWj||s zn2BmqB=ucC9t>CGIonmj%a+BGn*Bd&6kBBsDZ47UMCplc_u0PUT5YHr9l(g(|2Hr+Pa23x^|mp|?tw{!<#!_4N^5U%fjz zBFo()G@?vw1&E0x`CkLA;6K-8&yj3owhr*vUUDogVVdi&%99!3E<1@YnEw}WdkJMN zHC3`t+LrWAydkYrm@E?iAq__}97^aHM(TJ?9xIVA~Q%k>8lqecz-Gzmuc!J}f(hkS!T&T8!!A2pNF1DH`-&81w{raG~ zqp@^J9R833BHV`)6|#&{L0Q{}lojWNaKR8)OYkq~M`0+T&=(Jp<;4y&_7glMWcijl zvV2SRZn@_H^aWy44A7QY1*ZsM3TW^oI~^75m}^9x82!V|VMb~rKAW|9jy)pw_q+oM zb=J0KxMiKn3n8m#;o-9aLGuApooL35ZH_tNicM;jHLd!pVwWHYzYMME<$FLqyM;r& zDh5m-9D6!nwsOFMQTX#ubywNQ>5@W&!^}ZtwJA?lM5{F1g1rSZ zdJa12vg^rsE=Ycxjm}jZI_%Q7${NgLH)B<@;eJHZIbl zo*wHgNm#%Stnwws@Y<5}FR8@KQ(~1bt+UFPR_~_H69tb{G~$Ez(ALG+2Y)&C8O8E- zj4?|jD~^Xzv_Kt%RicJEzY)(JWtK}jnWeC2gd~mGAwZ&$^NrHa>yX9i!(xJAmdO?|svijF5vt`8mu@npRvG}d9X6V=G9vR?@!r9C|Ckh*zM05%;;Me6rImut5QPbopF?1=|I3*@?zq2~g`^cYu?C_9n!U_p4dlIVDwxrGy)6oF z@XP#JLyWE*%MUX?JUk?wrJNK?x||9PwE_~%X$MEoF#&m?rBC_PlJ5_n+G#Q}C8>>g zXtZ$&{Il5{qn6ku5XS^mfQc2qw^GYXb3G}|*V&3Jg%4aFQ{ff#xaOKmPdb5W*%W%8ylkNi0~l+| zCiYObTZd$PiHWK5hv&^Q!7wp#Np@vbRB5YXt7BI4*bkRqPoR%fGiAceWWHb0oG#g7 z>BF86gkQ?CZw1{9)SgmDG2#LIdHK7&^FIO6h0LZQ0B2 z+-?Q|C#8YK4{f(W`h6p7)B3q-!`E)KgAhdklJ5TBh1!{?XFFA#pa}IdFh7`O4XN3u?d;-HKo`?d=+;nT}%_TMKxW`l<}%|feCW~a(qxO<-(x! zkffk^p;cRW4V77(2 z*&QM0b@D(cjNQ%1@+7xq3t?lnv=yZhi7+Mfb=$JvAeUW1xrrs+*#2%i zQwEO_wy*ZSX47~grd1ULSIA(K+6bonTk;&OH+1}k@W8fEML8SIb%=M^)T3iEIBP_Q zbv5KuWE*R`@70PnFA5<;^iyFEUY9w_X&rCn7*C3OsBLZ`!&EO)ehS-?mM`Cu9puY$ zdXT-c$~Uk90tz27|6S&OsvAm3ST3V0m;X#cgvdK;jhpP&z*$%E88kuTDo; zTS^}B{A=nq@UjBisBWk@+BIIAcEhw8YK3XPkxF~wwN&vV?vtIuOgLbTL8!2*pG!d5 zmUC2MJrYGia=En#pEE@cKs?K-pFG#pN3;J#20;j%P%!%(Lq|$P_Vk)NFxJ8*W%j8X zCYf&eS_a`Kj^LAfIZhWoZ1Xb($g(c~^eBkNX=7ZlcgQb#=|0{JZNH6je-mD|7p*=r zRXJ^5@4)J_*sO7P_9_WQ#1rTjumKfYOzN0&6D8Pww?N*=6XGjEQDLUNHYccrrf5Mi zQ9Xfyx=Rb%SSn=fTE>!;aE}(6)~ib)yQ#UfFtmwyO8k!9#sYpi*Z*sHN>BMb+FveE z56RX*Z0xTmlEv)8X(t2&ml$4H=f=4~<1J@tRR;~jH-vq9itT%F4d%yN{`|<3lpFzP z)i-Ql+IMio*`F>QhBD!074L^Zt!Dd zx^Kp`4J2<@wdwTss4gU78>$wm78f#>|FB@Zf)UqRHR&{^z-x$l%Gx~e@r4$ScpV#c zF}j=S6=g9BVDo;5jZTf){^2Is_?#N`{s1G@Gj!22#qm>Tk(u+o?8&O9dGpg)^MB&p8h~v`^h~u-dg*Tkf<`(WwJ{k3$A1R0dah?&-%DN+d3eQ z&(2ozGJV3kzg3@I9T3Oo)E32o_?+HK?$Bp%E4fpj=#a11=j>K;k3Q$NlC%1p-{Md( zUG(i-I4<_sxo}*p9n-mRT(sU0|Cz++<9mZD zDv=YxCXg~Hq;m=B5~6fft8P-D38zOg_<#TQiNqf0bA~f|RxXoeXVgy_KQx> zHIi-|iMO^?n{h7bAY1L*7xk?vr&z1_7#mkQ77OZgYPS4VT{hx$jPAK}%6|0dJjXxa zoR9)YtdH7f_ZsF>B}}!b{0Gl=QDo_2%#*I;p0y}zrnnL9Y1$96;z|Dln&WJw!iXgt zs=IB?oo3z{_rIL^UM|f{`m?!yL^JByt8|QZm+Q$cX#k$9QjV;=eUiM7v7re3)o{ph z9S*1V3$el4kZfyMHKgX#0fr5Z>LwaQ3Yhxuoi{)Lm=ouoPD8a(+j^nE!*9q76f*(P zEjCqQ4at`1`x4(q&ALG}ul+ADDRL0288ob8z1>!ALZZl>u&R3+?>BBls>^E6LXgD&^CWdSug3DH+H>VNliPPO}UgLAKe z$7>o*2-q$uuA#-@Zki|y+eT$KToi)N^f9)MG!PYuJk*-Sc9J2YG!&at?{6AO>x?|-R>$%anb8ElJru`=NYr(ssBB#pnyw9I+}+3!dv`01Y1Bm~^u zteN2pXaYZ^OlsCiP5=#Q)7@fT>6mkkMjV;fST&M4?^#UA+wJ$%9!sb8vZh+l1E3dc zr1Kn}9tA}K;dohth6f6_o3gTKuvw5z6SH?rgS017pVO->gEDQIuFH#QiF@E2D0qWH zj%bW+AtA3~e9r^F-kq^zN9f9E&;&(YNJwn(?BhcrQG%Rqf{*~RdO6^j*5io=P|+%w zyoh>VX&|Q>HPOJZB^VmTvsFctQ?#v`<{9HcjpElO5n3)E8pYSjZ#?#Wl%-8>1|=HB zfA-6S2{elLvq;TGv)Mw5G>T_wdtHOG#^JeqJ{sT1|9_lnJAC|_itdnEUHmY-8$yUt zJ+#v7Ye+z_2B}~I{hhARqskVod!)@8>H6UnwlP#M+Jm|9GDZyT=go5vZtFo>ib{I` zIm)?-@wt~I`vb{c)Z;-G(Gy#g1xhS$#bk64sy>Is${)#EvcQ;;WvjLxt-1s;JlNO9mlx>i9t&Bnm+)HWl~|b>gF35MX%e=2#_JI~5_VcW zeb!e`ejlx#i6i?Idibi@vAEUZ(1tCJc$I;9bT|R_esjjhIMe&pxB{|`uRrLV%ag%W z$#hQ$@X$yC>peX;)o!=Zwc2d}Tf|ump5p3=2A}zj#-P)GXM6*s5e?q++toLjp?YTU z$OkAY&l7m)U@c8leCO%efaed_dJ*_Z;mzOTU*^?gIhMNj?k z+)&1of)lO+7zjIn&>V|y*EHZHl3oxI>YD$xUjld=b5pHuH|}=3Q4^5G0@;`TyfK&; zcyivB$KCG!)kkIxXxwZ|h{dv;(&i0kz>TDc`WN}1r#f*GYB&M1rUFVp=zJZXwjJ$) zp0KnjEo*GR3FZ{wh!}Rxi3w54IJ`H+u=OWH7h9FDvm6*6Y`FLoSRhj6Mf6)P*-gdQ zhj>=sBRhYgJM`RYUU@wDyOQ=E*413-O6 zJrMI7n3Eq@nrKepq|$b6PDsta`44XV_#6_rx}0sAsZULAgaSZyhg*vnPqZ}nhnHSvd6HO5kT}#K6k(iJS_<~ zWc$mnscfSTM-IzKQ!{+)zrUMPT34;vm~Ny4{7$hPrGTJaJb)|&a}23;BryQ7XYB?P z2r{6KS$>FPv+xs5W358VF{>HMpBLwA;QGs-a~?x6{Rh7gl(-TTYAYoztFV#YoK)>5K?OwqN5n=c|Zp1)|Hk;-Hq20m9|H=oD!4H`|FO-eJ zhlxnYnNyx5(wfH=pEcc?fqP?{v9QA9en05_o(Qva}kx)mcuYjQ8+HPlg7QRokz`I zS3@_7`Wd?EQ|PA8B{WxaCxd4C+{ik1e-rf6_oE5~J$3X8hncK1`@vfYn&5P`^_v1a zC>k^P-2Z)G(C+_uQsPL=fkH6x7Fw;y6vlZ&O2wgSU&-4MZq9~SC}ln9uVXk#7{#Y! z?Sgfr<~?KA^z!A<%SyS*E#qN4;X($A>(g=&Gf1>{z?gRNNn|8i;Gp^DENXxefJdqy zq#}MKe`|z`Vt8Nf+O= zi%*=+R;LqDkOE>6?S?*~woQGKUvzXxZP$s~VA%f@0*cQY4~eXrvh;jL|JoaX0mP!Z z7@&2L-ZH>$<3O72&*4+K|CF7&f$53FZkmi1Xr$KZQ)PUBmQB9f`*h;Y8uh{+``k_r zG7m@wOn8+0qUaOY{phOb>d2~w;k>O&c;3qQ>d1Rwra_5R)9!0*$>pa*LY|;8_AJC2 zI)E{LqP)?cIE%rmuqevQPl; zvE(|5967eR{hm0u!k`&h#0B3i2-l~Z6qFmh`)5BJ_kX(C`+=6h9jqnR)7EV2e`)$i z#A4V~jzk6Ki0%yX7I&1h^`aP>=kxkVC~+h@egi+aaOub}kPe`gZ!pY8ct_8c@A{+4 zT;z2%;}ka13>upMc3dlB3Yuhy3N;VcnFg8{Js#Io&JX?BC*;2^&s_2Fdj+Znzo|f& z^{c3#4%cLmLQjJm&(MR~&JoMPqQjteqhxD;8EaV^#fiHtvFIhYaDDz2<{sB7JTjof z_uv=fd((zpo*i6djphgM(f`$Xbo1)j!TTAp$Y z!N&%GwN3-WB_1hs1DKpBVPeEI1Oj!X%2)Im-cX~4^J=`p&H&D8seE0EcmHwp9fAnk z!aq0l9d|);)8BE|UB%CQ?K9Eo{+n~d-`>w))1Q}gG&*{*(6~fT?j4CPU(j@{VIy&~Td`#fIl4>P_O3gxDh7cu2NSn)H$)e6$X1URX}EevL-rgZW; z8aW6@B-+_hS35AdZQM#ok#=uqne1uOA8Y`xb%U(Nw?vFuwTgdXAcvPhQm1BZ^B6Xu zB^Ez&>J-Zx7LH-LVLvuiY0xnM10HUdHh? zx4?#5$}}X zXp3kfYl`!-jcH5onX{EF=5%1+5O&N&Axr+v!?Yj){a(!VMp^v3n!U$j%&qu*a^6@6 zCjQ_3Y;wBz^|wyl%=HI9@N3a6ghp114}KKpUi{GYH}Ylh(Kt&==_(0-JAjRe%Yf|{ z|L6;G))FKm{c?_4-bi?C)#}&0b&EaDwD1VLR_s=6Z1_M*`8cc1j-L;Js~6qG+gEEdja1E!S^LcoFpM;UZ=CM+J~o$h(eMQXNKI^FreqUFqPs8(E7ELq z8dhBdW5icSS7k>kosL0?Qb*_kjj6diqbRp%^NytGynsUcfbF%^4xP_tLU#f6@}{v1 z31Szs1xJ3kxb5+(;$RZD9uJ!!ZW*VrBZw~NSX6&-$^|*#0co4;DCv1U$-96zNZsQ? z&AHHtzQ1hr?v?Kw$8p5vjxa7XA>3o zB`=DP&+L)xb2UKNU1Pn@!~3tDl@|%Lbv46m6($7?dKX>MpiK$hA*WHE9pVGg7vBxM ziMWG)_AQ^~-bnyFi#lSvQzpMFHAQd27lml4%8X;la9K`>H8kvGXf}FR9yOgENE(K7 zNhDRBSBJt>n%qVoH$YG zMe{YiXjCNvIG0q3W~CAVJE=tU74Ulq@qpbt7O8$NNUFRoU?YB7gP}uj2ty%-R2Zo& zFBI^0eRCZ8tr6ZZ3G87^mj(Nd^?FJ#B8k{h_$ulJlVN66!5THb6q=B0YBFDvR%`ou zQT%R0UFpGNW+Cn-%MB{*(DM>8(*UUBhKNRF@*@s$Qbgvem56M>Z|R&Xk#&{uh2P+a zMS(VK>l2?#;Anx$P=0JIx5*+(n1%v7M(q;^;?xg)fh45~!Q(dZbl&t)Q%&dW(o|EU z;8FE7uOa4*hM0j^M**X#{Xl%q*>O6{YUqiG z2bE`?&X}s8RVvi>ydH%)@6;mx=MX`6Y6^U^Vub`gx^F;)NDC+#Q9k69X(F3X&t%Az z>H$Q%S!~?U1HC&fz{g>FR@2}60D;L_BF2Ypu)W>9xp}@IXS_vno$f-isRG~pa=Ms) zgUsSH{ReW{5hM^`7N5x)5;6#KJ;zV5#f!ZwBKwY58~k1}xcHg>9QXfyv)7EM4fxA3 zgJ|B1-jmU|l%SK%^HP5rrJO>sZ%X|M%82xi%#H?Nh-uT*A2t)#e$8X4KZ&pwtw-ul z0#6-LTPpP@HuZ}9+tv-;O?>S+JhZd?UIkMFpeX;Hlnq?d?&r{7i1fxATb#HF!=po6Lm@3M@_I! zLSBmP+{BB7t4ngFBTQ)D?g8qK5TIQm04jVP0lq6osjm<~t^^jp+2=OewRO+iIcNL{ zUs0EPORRhv^?!+cFxLG3Uy5#7Rj+sV_VJx}lL}3KM#(V%7HkHOU;oHp=H9b|8Jt*5 zM|W_5i~Qxu;YEer0XxrRU?0I7{F!8i@fIdw<-*3~t?P&fR+W zcz?}1C9py}6wCSX^SrH|MDbED zi2S9=U7R&U2IG0_FTsyix`y?p_Pd03{cG87>lQRTd;52y(^6&adh4{YCpCKXbm$60 z1g5@m@eK4P5g9q09N8WZUIYni!RM>462} zN8BfJ!eQ>j8dztjvM+};2v4vuDSgqz8+VEHpovt$LWLjsPH=E$=wse5k${i+x5U8A zMrAz3g)jAP!44(IEGjEb6lH#3v%2QI>d2S0O8m;~kW)c0JBZsz!Tu72h{ ziJp1vZT8G3p1gPX(06^MaVrlE-tj#j(EE>n-y1=Z(7?aAuM0C)10Q?ev>N#0PuN4B z``Z6DeCTao>gl2I3Zum3zcSc{VrlN<|MpI;PxQzjW&?&cwD)@74e82vZqf}ocfN6= z5Ho4Q*jADgq8ia)j)y-I*Bf$OVvqXL$E9mzGSmU&Pw&8mh2Fe3U%uz+tr&lT)?shC zOfGFfd$DN0p|}{IxeOQY6fZ@f+GC-cunLvhr+ylj>SyK+#bZyQABIzPrHKw9pcxN^ z*Mt$hzXI8C>di|HY400~FFu7KG4iK4q;GKWXh2Old^Fb-aW7|&N!_|m?SL?A&rJ2Y zp5F!qC`-DFk`Lfy4mLwN91;)w^8-ge1DWBs1n&|{iR2<4w6w{}GBS%J@{a4WUmU?s zHReMasMx21z5EPb@d}16JHM)X!jX8;d^POeA56~_PvFJ&ug!w5U#Pxz)wKUIW0!7x zd#f1?j?B(1X`E0;j4XggR6;tXG9Nkln-CjAZ}k67PB@5)nMsnwj55L1sYqe(wGf$w zRe!#<4I$yABA-^BKZSIUG@0PxR6gDE4zN2)7{g%$4tlEx!S3Ftw(@dvw>=5$f(pqT@ z3>s;D)Pl&26fdVGk3{TSIZeb?>#M)^VELu|Oxtry?J51~Oie{`GS!%xYT5Uxrnwye z2dXPsG~MD;(J&?i3h5-5&qb&6&fIjA%r)lt6VJ|>Xayti0qUL4@XidC{~+bz&Clv4 z2J6Vp$8{4Q!^q7)(M?QwyIGFoPr2#i52N^`jber~^2#%NqVd-MY*Oo=tG8Z``186s zKJ_n*cljyr67;e^Xp#!pj*R`!C$;{?dh2DEU(!wN?U7mjMb%}sRt|HY?Vc!ZwC3iT z0{dK>f5|xLzpPfrLH`xq90$%{>gM?H|4KJY(3d0qYuzk?Q{H?+H_PFdH~&UAaZilQ z>2J9?vT}|;-588Zz`ya9|87#tU#+)XcK0>ibX(sI%PuD;NR2WyHINmZd$OqtmQx7J zud5328_t+NDo-we$sHR>)EFPglamIr9oME<4&*-FEC*8Fe3NdvM|Ma~_j9uvPHmiX zvyrD*l4aRtJJA?gy?Iiv|9n!f57c`thw>KPlvN~xgrZOo(X|aqUye>HgT8G{r=ZSHa-BfCpsFXF`l9ynrgr|aT*{JE3WH7>>JfG5} zk8=yL9UELiLd74kTBXXrd@Icyx$z84GZCY7=9YF42ekx}yiI=YgG^YBlLZs9LCK2x z`J@QxGGw3H$Y(<`lmrc;lnBNMaK`#yx!L-!cXo!j2|l3Q$oBAE5 zhkCyu_my6E!uflDnIuTW6mV9f}ISufbJO$LH9o$eS2 zU;=}}wB0d_z&QLG1L^!C%s8y+#!V7p=nz5(-~<{ngTeFp?tRX^w|+dklul-**BZ&z zsj7SLx##S&_dfgg;qD>>xA;5$)gM1d;1_e83c}G35#aQe6=R-xX>V4%Db<9(4DX1)?^052KTKqoA%snW8o?B5Y1Emm+p@ zc>7&&PX05YD?twU3DLCZ4ve}9$hS~#{Pc&PakRAsE_xP%$(@F?LA@mixn6#yI^lJM zn1PnMkDfiur@q?bXQsLg%!R;Db(kn44)p?PW z&n1mT39jXaD7CYplnQiJDCI`L1;>da0Vj@a_U!lLA+++;=D@yhQzAvrou)#F`hDFd ze3$mSuzah1JqMMjeIwoswF?@)_BwPuBy&fGSD7}%de_FQuiYFWj>mmwB(=lT9oKBi z_(Lb?HuVqEZt5@6Z|n=oT6es&BLg`9>LqZ#a(Iqi2M&nTGR_`g61weZ{@_lUA4k1e z8jo%&H{iCY4$`oeRBQv&j+LZP&l~0uPjCqWIGMe>GRg5Md)fx>-ku7mlp7PI0ewrA z+Q8s&LpegdTG`x?c%XPhhDNkTdYY*hqsgay^sGmB%eJgI6%1-m9%+ab6Lf1H>jGj zI&WqxHeD-M+cayEQ7qXg25h{7Y8z*?5Qq2!-;jkc#kBG za#UR|)8(G(_wCC|ZeR}8Dp)&utQ>gcR?$0Gbarl4w-#^$ilWaI1B|~tf<@A?sw1qN zLq1qKeLx>iA1K$Q&YmA%S*)Kc2N%Bkv7&Q}z{50AK+z6)+9DyellIRQI{xpFu%X1y zkUhYgkx-b|_UK=fU_N`x4iywHsm_1TV;TqcbzeiRAfCyobq^~Dl1!{%U}Na0zJ@_c z3TucC-GS|HgK8=ZZleLw0$aKSGxMFS79%P8_h38*v@j$P5n-Dl-(OOpCLl<-!N}a{n=Z2ptN*)i4%3CbnI?JsWWlXr*%!^W2Dl<@mvDXKt354=ai19}S3E_b+RrB^HwU$fGLSP5 z7Hwh{5l?29qj~Q6!|fa=R?T5FjT%v-c`FG;>FN^ zknARxf+X;=)xh}~BFK>)&yE*T30hiOE$+H5<>D@!Z%W*ad>ctuX8=30G=gn-IG{)( zb~`25)*Va>w(1Ht>v}I^e=&iUwF>->$(bap6=Nd|axJlqpxy#PZ8xAEttC6qTCxMJ zr4rFvr5)P&LhU=V`RhDtF&xJ*q1?jjDAGh{Ve^#8KZ50}?cc`F^}-eAm%|hNV`Zdo z=uoS`wwr3(MfQs^!DMemp$ct4#tJFWrcXd4YWLscs=xv{e1PA`gjP^%2ympeK-B+S zhLL*?_O~;ZC!r$M$&;qkO50OAl0Z63MAJs?m}L}THGck{TP<5=($Hg*MYwzB!_Uw+ zJ3U_CF*{#ymF>TW*a!y_c}G|&gurkD>1Kg_2Jo_J!ftt5ffhg$nOlK7mWNZMn1_VU zJWtvJShy7TQ`F{NbnF&9!8)CQD!7i+TFMQrRI3Kg3MChuf8UFg7*e!d`v+UtC+^`~ z2ALsnnY|asRU+NG3e!sVwt2!&a>6c?EH^VDXiD$46k*r!ByQ~)>FEA$1ZG=*ZfUBD zJ8-RA)($NL&g{_#aMWnuI=R}`kNq*iH;i$N|NLh+#wbU6M^J`Yuv$mgTG>XY)!~_# zv6haWD5D$}?q`3@*dJMS-RLH(x4y6LycVPAJS=r)OP$B1R#thlTJ79L7>SV%ZOw3G zPH_gaw|VHGmYBWl*Yh-=rGTQfz*seGfz^(LmI#N+K2&=ULelRSzkSFy@E8<(1r7}EB;>hutLo|QW>J+$4BWfG zJu)gY*Nk_vTkP%iWm}edv#9#&r#5~x3CWmbr1TT4bF%ER_}U>@79?v!!RgfHiz8E8 zJIE4pbuyKlA~MAk)~sO>*6@G#82Tzztdhv!wpGF<-ur!-mCWspmp8kDE%+%LvR#IN zu0lUJf~%7-1}|RbwgZ?C=U9%P{M6e#jttisTI-0Pc7FDu41QB#Ni3M}X*=s)a*)(s z`vGe=ef?JnHUR!96B3RH>4upBdKdQ4f9Vd^*F}ON1Px)1WIQ~xz>WEt-?=yZ#0p~e z(kxoGr5iaV#dp+#e%8A4QWYt91&bp+TkRIIirT}d!D^Y!B78qcJ69xQYA@!9oZ>pc znMn`1V2b!ueJVLAOGevK5s`NE(`AFQ!cef!p7~^QM(Wp68|jy*)|P`pMc3jZChYIR zw()0oE|;Gp#i)M)%FCNF1_AFU?9+7=4UZKV`-GSlMPml)KpLK5+cLt>zV#hnSUsAP z5LmzUNHnknDw+RQ9-Dn@Af#a51{Ml?yw-Avxg;SiI1}``(U-EwIbqAewd{+qnF9OZ zs&{YEr<0Q^cqQ4xB=8CduXWNSNdYLkXHM;xYfG3tL?b+M6ucoIDO4jQH5UqxNp=89gX@Ilt&NGCyL~FiDcT%g#EWUv{e53# z3PK%Rb}5qxfHQAP9Q$~}g~<~|o3PD=8T>Idi5WIbV!I2J!dsW5z~k_;f$yFSV#)BA z!ffF0<<%fcM^PeavBI)@g4M(O$-hux*|*GU(Z%QlF3;M43J{N<^CG2#D9NB;?;^=y ze=|vj)^>bS7Yl`do2cXwXeX+ulsJ?#OTfU?ag&-F$*{oO}eRLI`^!)R`kq|hJIlgP=c!f6QXRPLk zx{6GyM@dnbBO*mNm@s5!O_2tE0@FpgVk+b2%GhJ`$FgUfm7#;X#?Sob`_r>n4H@qt zO@x=P@H=xT*Ce79GehJih@7!9x40#_YQ;2}Syrr!-d)E1clq+oRj?f8HR~3u+X!ub zz7G!*EGqmrQ6&W|y!j@sOKB`d@CVfXa*Z`p_LDJe_&$~%UT%pC{w%MnM}7;C5p$># z*_tIBh=71EAE~@m3{Fggd+uCwYOxwI;yAx7{A}T2bv68!n$DpgriHa5nGoX;mup@qhsay6iSU$J_;< zoE^yG(97=V<9l!?J@WJKOK(Q$lKAH9m1+y||r_)z@vm=5GRPPV23!i6aj0ti4Zy1-A#HOK;~td48NdKi=j zH!3&4ZEjfu`+vC9q(k533i@e1ciFu25q374QXeivXU&9Mechm!wAgcDqgVS9mTkwT z|JbXoZ?G%32I)%(q({ZbI8tISI$o;B71enxH*U41cjg6K^l8{x5o|v$O6l&6(GQhT zgc@p(^+gf^uQao>afm?q%|KRyKOMcCiR$Gx;R0n58KKl-0zs0F3MlHp=1S-kaJ9gM z&n>$D=s*!1GHNN+)smeB@BM=45p_?yMUGduwq4q-hK9zT!C;Q;l&>rpE|x;oF0U4Z z8C|G>4FWT|&9NmWYF*h%CgH2qFJV&RRVgo%X~eW*pyy#F;4$#S7sUEaNHxv+fpKB# zq65OtG!HfvAM%P3Nr~ketdD(r0Ex_3D_WVh^y4cNK}Bcwq(EdVAP~jZ$?e$=Kk%@F zC5o)eDg#W+N*kmZ!Vc(K%99yi8aZ)U`=Go_ULkA&cfc?R7PKZ<(3(w_)@-u0W|O6b zTW+yA%WHI4EncFl)#4?(RxMS_U!fK^!i{RFUcRlC;^n8+QoHl?x3 zFQZrKH*(b7Id;glSE;S;N;J{;-AaxfLG%b}@gi!j5`k?yD%hm33J=^WtOOfO16B=L zIh4{!A-^6mrZoXgcquLEq$)i+&-8ksA_P&KvHSz7&l z72MIsOc5S`Nc1{i(F##JhJsC>npq^+48*`xKI=?%4^Zl^53V)b2m zjlLg*Q1rb39%{Fcxz!@YEMi2NuL5{#oQMQBG)+S(T$zCJK6#xuVi%g)uHk71m35GgV3>XO}zTNVCOtp}p}l z9-2tx7nZ|tGzN9IlFZBM^MvMs(KOdRMCXwxAC zHxEvPVBla8TXD`jHZdz(*I&0UaSCYlOgMmCNMB8i*Lpn8tr`7LqD%~U(Z>|Y}@krHXUJ+M8iHqWg6lSF?! zsiyg)@BHdNEcNxZqkrs=QgD{}->&j#x2KQZs$=t6j^CiZ05hR&{SK-PEU!p0!!o&n_g)3`( ziQ7I^sw_U2p%H7SiuQ4xoY@=Z)M6J?tEDu%4;w1D+LutbxztEtZg;0(u`MCQ-8C6Z z5yxPU+4$j0C?zI^O?C+c+EQ48i0;WGksdZ?@S;uE?B6wA_a%HNNS2p|bfh@HNn%!2 zF**1>Ekurg(n12bKs3W1&}CX|3&|mpN#qD{UrAo=sn^@gmr)km;{!pPvzfFk6D=oC zUR~l(kH5Tgxtu(g_*3n3%AQR^ZpZ?0K)s-u(K08A@Y2KxEjCR|C#?$S?YuSOJPUm% z&U35Lu-)|kot9Kwq{vO<%#(nT-Y4_7$ma(TXjWxbU2_sTd5&|}L=D;SA70GkJnT>X z_o-E2)JrjYzW8f%-gq4h^P1~8w5du_TzKjxKB5@e$g=7RjuWuL72n2a$8ULLXXh=j zarCRl9=u>L<;0BPFQ^(vKI`YWvK7(MgzQKa@&G_N^~EyeI#(-qhuQ_*62X4%B-Im1 zq3!fxQ?4id9xj-o9y zg^IfCsrqG#L(^VT$qq}65_8Qf*e04)HHeYy(-nT+dc#A`kX9?z`jaNBvv5XHVMv)- z6l_2cqzqKa=zlJwdejn$X9lDp*xq3ilh$HkOcOf^!K@d?Km4yqVnpL}@!luzP?|4* zasPxwY_&0h&eRsbKxQ}Q8W2N7xT`ZZt{Qacv!BM0Ad{!_Q7@;Vs_6^V(tz>Qkw+p{ zk2qRUi@9X4TGr~ITH<6{!Dd$i+GKch8V`#YT}?TraOtiX+#Tzq{;If0e$TdPda|FHBJlZYVmNiL4mBmq)C|nH>4d zk+Fmff{Y)K)P}>?Kn_KU0qxvonjg2#BPV9|7MZzjBTbXdm3S2nggLEG=eW6h?zGNs z!(k&!HvHg>4L8IH-?xmtus0hXvs=x0BHkF6qPFOs_8>H`wt(i6!Wig zS<&>D%inxv?b0MgWSRaW0j5Jz29isc@DO?HZ~?~z<#wP)6J((=rDV@GmEdOvmLXNh z4MTj%$A9SOK9{_b!SWkF2)Se#^I`(LPy8Yl0aATtxGbQ*ouZ9gj>K& z8$>O`!{FLAlx(d(rnQDO_&SGC*k(F^iMfAbi93=j!#2SZ*KZf;nL(FF=GUBdYQAN2v9(<@E#EXxWwHe~ZI}P!P&}Ku4*um{G zNTG_yct$4Ujbbn&K^dQE=jvD%04^SOg>3?L+_~L4heg%=N@ZgJS%4QH2IWvzc-RUf z&{dXI12n-7Y{4=Y{X%s}?zqtF1BIYRwO^0>!WN)81cn*g>S3IgmCHw9i-+M$^#UbO z_)a@cnQ;q|p^mV&q7?Ag9a_pBfJw$+@XCX#7s%r1yts!51TFxJ^phBhG#!FeCBvup zWW9MQ${%b8At^B-*-YR`3RKn3AcqDxO{@Gd{eC6EM{2j&srCC|a7^vh;GEiP;kRlR zl-}#pU$Eqp%gP4c8Gi~hVDP57VolHraxa?&Sf-%2uuY_j%p}~VU!9F6z2)|Pu*??U zS4?BMTy4H;OcVx3a6G_XSlr9X-o>?->(@TNN}bu+d1z)5F6X#w=-bR$rcbkl%g<$9w=L>z zO`YLY{5403McoCC>IQYgSF^xzx?TIkwwAMmvw*%=PzcTvJmVa%Fc0djh**PrT|HwW zBKC+e&BMZWCr6!7`MT-tM6$kZMl1#)qpH2?hx6Fp4R0A@9Kzn$?beZ|QP`2*^v3G% zzgnw33)1#BCH^q}=)V~GHYNS{f)5p_da^?ss0TgZlOp@R@GAtnblRp+boquv%Kd5Gn?=_P0m|;jnQWKaNbFk9+=x6zqnZaSMflmcfc#SL< z!>5RVm1rN?l-ai@B)=DAQ^5uv=_#z;kx9DJ8C49{%FV#0?we*)iX%LlA7e5?fFo+f zbGAJ44s|~-Y8x#)W!XaUvjnRo_eCjp7D#S0uYnXy;ubT1vCLeo6u)8wk{PiV2U0L@ zx2R>xn=%EUd#3;tD9{YZZYQdZ$2EF4sE>W9Y+@j%ArmgxKswR8h#)LACgou2hS}zoiy|>abcuZ?0C0E$Q0E z!27`%LiL^uTTeP`64~D}drBa3!O8?9dOM^j??oa(Vy>AV;D=5G$IiyRvm7OgJ>dLX zi{v&ExJ3vk9UMr_-|UtHrQ!vri~V@EqQtvaWCuc&+0_BAh{?oO1MUJ=a?~ROF0BEV zR`E*>koL>Kh8^lhI`gw;54T{{B>Tzqi#Y-qN%&MN;Zv;?8nr8n!H!61Y?@&UmdAd= z@++kb3&hRrTa97^k|W2?e}o9TgtOaR(9H{Iym`*I0M?aG`d!j8I3Gm=SuVZ0oc1 zIGtMkqR0V`ML|UCT9{(+LhEXZQcf75apAbW4%D!|wYfg5Z-W$ZEn;S{KUS+1VO`US zb@fi9r)hmv&3KI9q1JXqolUan8nzTovy||iwPVM(HQle4wX>WTNPT7ve*h-P$?ryD z?R4#Su>h@^n4sDPwZq`sf$T^C(OG%Q{I3R95}4iGxgb;a6JLYFhQz2psBI0fx9Gc+ z002b14>WL-2-x!?*rcDcsVv}dnBsd4LR*ypwC%?;YA4Lu6WUb*b~oT0!hj>b5WytV zJhm0>gM?{&{sxs`>eJGvFq>f4p}DRI*BgDV6In}y1aL#Yh25iW$h;wHt?e1ou-h@M z4jzM>n85<6#4SX!J%R7q6NEtRnAT?WmhnIQcQSd+DR1-Do4hz(q=w)OUQU55$`|-y z9x3p?AYpiJL2CX3S-&P&eK@)}B~kRp%Lw2QZ>&&p-wiRr!ek;+~dAJR-`+ACti`!Pu5O9lKG>(Yd}SZ+Tf){Y$ zhp>COy-TI}be~G|sXZR-Weak)kn{nWY2R73{P0qzn{=XSZ&_ zl1|eAo+RBXBCiiH;AIhjH_ zBTw%J@XVYs_OL!v%l6Zk!M$|TxX18;QIA_u{bJAR1V<*X<`;|GrwAPp<3@2S#xs!@ zz0O9xVN!9b^a^np%P;u}g|69CunRvF(=M5tXdq0{C1o z!CEb0`!%%$b>xVCw>o3Asx#K${YRo&^3%%fn6m}7qcP-hO*R1__}eiCWumox-^;S< z_k%3$0@76A69J#aKr!)D```4KI9)pW=z2-0Tqm4eom8VYDV&5lf2>H^89$Fwa*mti zil)k}9dNDZbW#u~$B*YgzJ!C5{4qkHbT?hbyC?6X?=pD|TyEWF>n+C&avcjAD&Zir zO{{lI9g;EHMS=ykJzN5oqDjlPrvMh0foWM#k3m3wY8J|34`5KAUgn_T&aC9r&cJD( zVWSKjonfO49JNx7bY1p2wMsNldjvbZ+6DR1`u#zgW&4U+Z3h#*c3QZt_SklG4!&qNg#Qm;x@=7J zUu$o|Fw=Bk8e)E|>}`ipz#NMX|7+lx1gd&|3SK~JU=mpz3Yl|$T(tBu&&M^_@VsGjBYL_xfS)#eyLvHU?)YIY_QQ3-h3ww?|*aseluJGv4F|J za2cKrm=tG_2S7cT;%zVa<|JLYiSkG9zdT}CFhVkmh*r&`>=uH+Lun8nmpoXNAvld+ zu6S6Pq#NN+>l|G6-MBL<8NA_z?J`pRurtz{{y=N`11&*Z`{8K{;yS379k5WV$V;{4 zO150}o*Q@nayFRfO8o2w5=Y^~tw? z$nx1dc%v}oZ}emu^^(>)^3VfjqCpo{@OU(E)bAeMJHYME8`wH!>(9myzS~FTxWIX! zwSi*vQ<;PyEj9=jLb00rDSfOV119t^X0p_K8z`Cj=u+}bg84v%j0V`(%y(N&Fg zT6)r+sj-520}=K@b*bvk=VEf8o58{uJ@J!>M1C?k7orB+y-?jxnC_N2?B&Ff*rz;g zJEp_wE5u@3 zCQ*%q;9Fx0#I*sI^GHXX(c8Pxt=T~-Tpq@?wz;6D0N(0BLo1*pOdLP)Cq6CkXXpR) zkMvEDpI@nwMCKT>BJ=(Hk3tpR>Fc#z_UI$S&kHxj^*sw%;148a)h{92e_?AEiR!_;8CXJXJW!C^bM@G zIiowZxe8SD|;tg z^g036DBx7lyO}SRm*}!wPZ$OOc)WePM{90zf;yL}++MG-naRKh3zRa{Mq?S+8VBVU z$EVXTNa*A7HaabBAS54xutut~lDA}+=2dQ}SPgo!p_3{y2%UoFT>Dr(dgurYAiP>4 zz%iCXlb!9+)2%0Z46?*jOv^FsgW@R|Ld(fvQoKIE^mcY9B)im@jIyX7!XE2H6SJ>B zTC3hHbx`6eh@wcbuhuz=VF3_3C*?Vy9pbP?e>8|uSo3iP)d^*Qijmqma^7HwCHi%h z90SwnS@d&Jx0MKr@EUSX8Sj@&&G6g!m8w>ym>|~ShLyRYbv0<-g5+4ws}8l`MCVkj zvYP-)M>0`uL%j@M{i4XQY^Radbnrd}h~Z#+kx32ka4 zs?a9B+j!=YK$kig7B|EK0X*#aySX8hAJNE+v1a$LNsXA}4*0sM5n?KA@>o()48%~| z&o_Cm}Q}-Td*Sjn(AE@&mlWS9mni^3L~ zYUFt#_kdeNMkew-Fq`(&>Qn_#X90)DSEqKMi9WgjaZA%oHsKRS+_3&Y+!vvNP7*hW z4zx~7$d#3Y0P%tk5;R8t2?X!GP7u6$SJzlO%Irl5-o>RCAb0}xzQzRqBC9q_@Six4 z_0RWa-BX`!+fP@*a;cT!V8xb;P+YzrM9b6nE7AVc%73ok4^t3U-=+1bJ%-k&->;>p zq}o?d9#g;Hh!&_;N8Rc7Td0?*_H|TkRJ$Orul-x)P?@5u(s$t~!8{iYbZ+PNt?JiQ za=ZG6H&}#s%{mGtgAkJO*!^_$zars(sdujgIn^CS;Pu4#(Y@tRRbF|6>=2Yi`^N}M z;zXt<l#P?1IyCh zB2d)ottN}Sh~CHTH)$(sFH(yKZ|JcJb=SpArVWh9@H-XSt#P77HC474o@V8XsV*b0 zw*5`l5Icf491xn?j-acu=jS}`#^R(HYDB?YJpH&YW-Nb#Fh)}G@HK`OzPt^8j5}JR z#UW%5O?(ep9Jc5Qq_F88V~TSI=T_ci^t;PZF>^JFqmPv%tM%yS!Ei28UCpZmIj?gf zAh=|ojsz`~Y(mJV7DZD1v%60CsVP`jR)PD$lE9QII|bEZ;gK@frdfzvaSPGS7G1A~ zRY7r_BCx!oNL`P4X%r;`8~xE`9+if1ntwihl`>ek zoWEuQ(1zOixfW{2ydN7xaO~ED0JVG7(rYGA+q%fwT?DPtsU!Gzn=Xu)+PAw38Hg#U zkVEGy@mPgifGsgtF?}WhE^~tP(lmspobW(N?6VDFOP-OWC3FXQMJ@HK5RC+0!J-q{ zr(DOAFzpDYW#8WY4HRU`t_Lx6(~CkjdV=lcLFa710^YtjWTO&lT?7@h>0$=5(f4b& z2W7IJZc8^1HcPWn%+eblHM;}AqX0a4G}$?fy;PMQukmj*iJLZ~%eruoW8y%=Ym#+i zlQ4d(sDx{XRp_W~ipO={9*#Hwp!G`zg_Z5-fN{|PnMQv0L&YO{Z0p*1VDCW2ozmQnqTl|!{3 z(6|}(M^%BrSiQ6|V^QJAYY3xo z&I`zTh3aR)MombG+%9AwIW2~efEt$_DY_>hv<~Ec^6u3hkfb{tDy83~89r+NV3RR6`9MyPw`fDTo!nl5IT#$Get z2Ohb1LZS%XEMc{17EkGQLi8K&=7d|HeS;nF3-H$|CAkrY9e2N4OJMwBJ}p?#WW#`J zOcN6t?ZSkdaS795JhhNgKPuKHmLtlonar&g+hXEc#KwK?S?}{%PvoC1RhNcaOw_v6 zZ&8s71XzR zVSOjg<7%}et{qcL?eA;VQuF&2YKauRQ7tawZMD<@zeO!Iz+cyBbf1l`;I|FtheVTr zkM)-aWDS!8F4<&VX{FMsRmh>*!W?-DHI(B{MSEmcoOa-CnF^=h6#%DJDxBKW!ST1C z>ee{+sD&IHd+BybX5seT6wi+v$O?+t6VE**)jNs4D)*Kp_!L?hZ#Ztr_*$VPxFj8I z)h(%QGDn|8!-*<-!TB{NmdpQA?KZ3Oae_x$MU45i(q|Phwkmo-d+=ZbwmxSnOYqk5 z)1Ku@(f=9Wo;1cs)+6*?4a}zF~tq30wJi{Zvu{j2MWM`I30iPvt8mk{x*%l zE#O5wilNT}U6cG#gs`hBx!@aoNUfME-l_!guo$(J4?9{K{nly>Hwm2!bSuRQRlwT7 zbE({b7i97noq~p_lZpf0B=8dG?ez!@FUwwEWCl^hQ}M$sRFH66A2N}zz>g_jbBcy- z>>6{2ZNK&v93`fV@5ZBO@fGaXcYFnfT6_Z*PDREom6T_F1nVz@C-FPJf>Ubk)N5LJ z-06lFk;DtD!5H|{d;VWd`-z7Nr|6d;knbz*jVqKPWMWg}D#=lWkY;@9@R$3u=5)PMEyOdO|aS;A$C{Kt9%B^I0 z=V}6?4&8F7QRs|0)~9_lw*iKoEK8a{tDxXV*V=8H|*8CA}uDF~x>F!^v0~X@ltI>27UIR4sI%6wvQe!t7l9JV&t@c91ydx_9jbLtKMeY5;jf?Rj z2ywZ<99Z>g3(PtcZn&}>=jkge$DdwDVTnR}Ozl<)hwU+K+=_Cm)K;7DT9lq8kSsTA zV4EudgJ@|nd2-Uy5`DVO>ot4cEN|f`j$_I>;SsYvcj}LW?;MXHzVl#&;e4XF8a2uS z&m%5Iw3FPOUQL)|%7|n*D>x-Q<|xahZHyfRXvGuz5zrxhqFY;8rih(8TVzV^@Y|?9g|9 zfLEJ_nAeBOs)q8Nzh)Xg>xT;Bt(Vx1^Oe4;g(&bAhP!(|cllZF5it zo{v8nE>R%N!q8eAUtEs`&s_g^o<)kq62GxESe~6&3-u6cMiT7;qNv|mkI4eqjVC7J zE{R?h6?Dw3nn+O5xmy!KAYM|okp{^$VgV8GD`?VacwqvzgzgLF&Y&`no~_G7M{!HB z3Zc88C<|SKnq0?d1}Ev)=768+@@;d{Sdo+N%f9|aMlh|j`9T8OHorKNL0_cXWQ}X? zg0~2`xto;?nocW!&Rxk1L?OWWO#C$7i}*<^@v{*ZV;K>u49tx__ z5H<#Bi5b^%!0hD~_+j{F{3-c524j3IGvS%_N=T0sks*r^DS@-F>_C`eRr*d2Fh*~# z5j0BnHg;Yu@>$8DGHYt{+vHa@eyU`bQ#5r)D5Bk~zUexVInut}FIx*Y%lbpaf%Sv= zP9{9WD48qeI$5>=pqDA$XZbNsBEbp(6zfGUXxs^;bA?5rlQwLUjnSNM>D@Zud0YSp zi8~G5fq=NxWrx70gKxkA>j{Al(U3m$+y8REClHN4p-%}HJ;;^X@WMBlETR!emT_Zk zNI0WEtpj#qnhp3&5@I7H`SwG6v!1chLuMY}7kt1WASoI`fVkv5inC~C?K6T>E6!Dt z$nBLMFVWF#4=9$){3yAF;uoDojgMfzaaLM0KGI@jtgBx&s~+RK{SO=1|FxE^)T=oHGyFWlIKuZK#zgbpQ}#O4av+M7^k0PK16}E`+`> zNIk)RaYa&M>+&O+6OQU6*`a~0!ce5|!u`mEXk|V~;{*4XEWZZfPt|rgLJ-*6@quY} zoU1z6M%D@f>bu=EN$39Qrro)}haaVezR(?ZSze~T1=K5_J!~Rf52z>FW+I^8@5szU zzv~?enUM=fyuKf+_J`2+7I+i}Bh=eTOXccNJtZYXB`{mJkMu|HNF&#gOTcN-qsJfA z(^5oskVefXW)4EcW(Em>!(7+2KKbQY=Adfc$>Ui_T5XYMXZM@;@O&T2S^Pd}O{6|jGn74DZ zOCqX%N3tm=l?J^TGigzk%|^HIxN_zsjMX9tUJZ^A@cJkfUC-L?#ZuI<(d z#s=qOKi3|Tv+MpjoUlkS2ZyM~q~hRJ;&%uZu-&Cc$$Z;gdd=?A>+QC?^irU)o)I(j+Ftjz6ol=epouOp}2m zve&T3bV~i&TiBN~()H4*)I|Md_NG#aRjLW2~2g3<_L^O2h zK1Sl1JGFzU%C&|HS?!JgnNnwa%KLL;3?Wb^6=%xT5B6WvJba5`h)ks!v~AK1gICcuIZ65fCWyxh z1@Q{p1A#8shVfNSZ@xr~*c1lJM-0~Cb`$`kO5_+t4n+dD4|i;8e|IqHB3tntT+oIe z+uH-M-ScOC2RpF?o6)%~IFlGL<=-=6X;EI3MkEMJ3UPs#+FYgydeE+h!5Aq9p;5-V zu--=Cd5~VJHwNo)8xdRSX5CmQd-R)SwB#D-d|5dhi^URNgt9BlCK__dPh;vb=!0=rtVUHz`(5A=OOfjt;tqre`x?_7Z$3+a4;o%3c4 zZBDQ-tF|yz;JuUbJHUYwg8+=IY!;X0=B%LIW#R3x*`IDU`z5mtzK|q*8u}1jV3~h$ zIk*n8ZZW%nMS-xR9E@yfaxiU>gLPDb<9U-mn}aLNofw3FwQN)%ZVl`qI&PE!XnXl5b>y7mBm2lW zdo2P120Dr{*kxjS^@HtPWqO*JZm~Ad)N4H`sSe9WN?>Go?XQ$rKivFUZ;*0D_=tiA zWt&1Xq{WmR;x=q?X>D<7ZE zN%dq?WRfJ!&b-Q1*p6Sr8jyiidHqMy}F$!zkLC{MVU-HAruz zx!Ert-Ak|_2mYCTws&O$GQmLa+b%MT47Kmu<(d{tauW7;xdlR;`0mZk;0HV!R=Pg9wvG0vC|-7e2F-hU*%;~u`Gv=p1XB*jW0?Z zAKqypQZ|;39gnsvzwTo9vvp&Y(S{mFshbw`Ja!(K&8ag*aJ=}Clo#}_IR-A9!v z=I+jNsNCkHSS6L&O3yI!*6keV%}{J;+^m{Y^rtRdbgL&!v;z|k)1`6*6%K69Z@qPu zK~i}G%wKuzR+wg(2R}_rrO!l)mFsORoJ~a(i+mt9mx=K+pw9U39GugzTYdE0ZA{!@ zw;Es<2YW>D8xx+LvyY5%AY~O?8{F1RIPJpxKjnHgxZyytUj2vUh69_U04f?n$BWUO z<*J9vuUDTQOlIP7 zLIIP9Pzf786S{Ysf7friTjXyP+kog%=3(W01)??}H(LEEjuFtTQZqNg2UXg;0wkvl z+Kf}BXj*99S{6rJr!(tKIHE}(r$~>6rO&4*)e?z}ZeK${JJW9X|U=UD$20gz3K_@GCb*V)Rm0-nF3W^? zx@_z7Q0rS;nAO62g}g)#?s(eX#0(8?4>-2+*ycdo5mZw(AO#dH{=$G*kX*S0 zJgC0moPE&V()N-9G(EvvS1)ml=n}4tqn7Q8?nhb+Vq!oQU>qPJ_tJ`WHl7 zdPt9e{jZjZ4s*+esx@)H1C0R~<9EZ0W)q~k>NYk!^TnwGyvjvqE8tAzif|;+gYG-Q zTIlnRiW{CF%#Pda8h$0!!&!N?s5!_8>Ou_YLiKV%U-!K^^wg#PegK1GP{%Nc4KUE- zWH)&rO$CUJRPgUlPkC@dFTc4~=?GPi-iHlYX(8G;h{PYf2 z`x;5NA41V@1@UzAxnO?rwIq9b7w!%Sd;=@l5@L+dm3p`xgELqw3 zAr$AK`s0f8aR0->;D3+@TfZNM?&PPq8pD{{V|cVL!avb2+i`m+*zF-NgbiT!`s8vn zLx2YG70k>)jS~-|%9u&02OC4NZDEY!)KUx$Jw4r+3}Qe=cB1r$ao{khs~GlI(tW$DubTm3Ty&51Q`Yqf{+g3{>$0!1?wx2UI8cu8YbpLj_f zc;s{HV@8@8JINkeA$R?7UW6TpSx?WWbs`0JjAAhJLP1aWl*`*-vp$YClZmy^Z~c-gT&D$@Cfdi{ zJe;}NMEfi&M=DKXa5%Y_z6#Al9v0tmH^4X)b6U2Cf;%8qMJyP$7RQG^4_2sRbyYp4 z7KZLX^z!T0zcO_-s9^kW^)HCU5Qd)FM`X}8JBdOU>uWe?{0N->-Ol30+%UarDb49Z zs(hd(y$B zKseTL^=m^I+q?H=+4<#J_V%fEvSXXSakL!0iO=bL1@SrYF&X}yk6jt~-r>Oat`2+atWEky0%uF@im67NLb4Q(kqI; zPXf1E5Sx<$Dd9OzZw(z}$Kzk85p_j{&s5g73CkF?v26V5rPs-!X#MSHuIhILry#LZ zFCg>t=DV$L>rb6ytuvpA5suMdxvFzrtiFhJcD0}9(D8#jtpwBR!H)L_CEL%%%E zjK%RLyD>FP=|HTQ#b+&3G?>CuN_^YL*S_(bF?vgE`bLft)SXL8l4;mXpam7#!8 zP7JbFqe80HB#zBJl;S}a#0FLjRlwFf(K%d^)%7m?OX#nT!iyM1XKXSMGHc!Bcw6uF z_M(^UFIU+-W)~VfGHeJaicLf})ilG@$P!;w=h<-lc`{doz@7?07`wTd4RYgjTxg94 zN!(JGRn7))!_XE(0JU`kA=}#*FL0t`qY^C2-p$bZi=seNMW+zi2nE6>I|m=*I@>-u zxz2T(Q`r1%JrG6JVp+Wjgo$9B#hcbXrfeS#qE2#}*~j7_%$@CnAm!N}3j3IsACdh$ zI);F~=RfxAPmsL0Hwn6lwRf0ZbPh!O;xaai;hbe}CKHLZwf~WrW#ek<(@by5@u5~i zQ>5^TDmAQbfTXpINj`{Kh{pc>1ZUfXV}HC_ddu=Gn=ywSNZ6DuB@@xJs_N7w4V>T^ zkPZ)Yke+H(bY>nnBUmKT-hWYC(Nl|jH6vdP=|!yOZcuBLGmWzh6=;~H1`Gk<=ZoA~ zylisJv#aOFkQm_NI701`8gPInB2)Z?>|vbaj?mt21nW9MUh@Dpn>mZvlI!B?S$dKK zBhG8&t2alki>v1cAP2e2S1)8Lg<@OLU8?0Pb1-UZ!Q4(LqgA*%!Krn1!R;kdsO3V% zHFXLNIZ=$r*K{5%+gWj9$9E`sh1+3!Q>z(e?b&6tOy;1i2bK9x)a8LXAooY#2bXiTKLqFDtyP(CNWN)U=u<)e9eSV(%<9J zGbV&0l$sEVP-;RbLg}@7ZbhXzXer@wqgqOK+|mfApNfaH9ZqryP8h&+=z-2CN~$9S zu_N6f6iL*Pb%)D0J$7!mpHFTRk}kKEy`f4G&EGH_eppAn%?a9XJEoPIk!&WGq9M^% z- zYm2T9*s|dpez0c51W#`bQX1hQQ8=c{49`c7C`l433F=^g?1Qf3COXjpNaEZs?j}KZ zNuF-=BVB&|0omem0XKKxVp}s0F)b!)J_2!qQ>5h>PoU?853QV&ZDFT)DC;5|>Sx)0 ze4ld;a+M7KYfMGiajiG#z~t;h>UdFR^)z1cDn^ya%2(jrNYy~~%BF~cxEKkQQpu@ZF;hUA&T4c9-1d}F?f312RGY=KU z6V{s&CKILx@X5?N%ogj8GweKAcL>?klR-4MC!=MkYzr1e?h;&)kQ4UQdX%|6L#K1R z7Fv)5v4rp@n)oKS?SwaJGh<7C!8e60_$t?%f{|wSP2m0!on7a)peil0aPoxqfFmHO z!6#JC?SJ%d^xG!gp$6_EwyOg?& zR4S&Nhfr?CaVAKv6WE4w{Bq?%`xN;i4=ki%XA^7J@s23rRNCg42GNPG!AH4G#9{&iW|Y9snGOCO)V|JisBP zox_}+h!OG>AIb{E3bm^6tX3x^>%L=~azJj$W3Y$?EL0o5BEdyQPFt6NO$kO%W|Ku$ z+3>Z6m^~71e4-fG9>TAqPnB^GA=22mf^9=Co`_(rq$gXDggoV9!X=~h5-%s?_kw6z z<*n@f6k6gbw-ht1(I-n8QSGH+1HxG}`rWd%0Y%}c&&dvm+QJ!Csq071B%b$7S|Y~W zY;x0d_1I+m`PTb`Xk~+&9SMMVhMS$+5QJuCSw^c7Y4?M6;RDK6pt7G-F>%dkog!D- zcQ(wOqx<;c5BMP|UL%4x;#uui9TKvcMl%JVqgfoypEPpNH;%UB`$x=*ZJ@V%o=kPB ziomXWp5h*9LiT<95e=OwJUKgGcEg_ShRCO*-(C;<6UpIjc;?4Xw071Pn4vo}!VJUy z8LACO-E7_rU4SJLpQ7KAjD;vgdRkwR&iLszRjACgu}a?Twih~iQ7H9S6ld%G=mq+uuDJ3nzw3>UgP+@0{@hnmP~dF8);g7{ zj44cGaoA@P9X?p&q5E`nl~tfTW8Cg7lNOxzPU!o+J~!6x3qRD&J+ztLmh zMFtWBY3#XQ_3x_kHw8e5Q(?~Z*SM^Jut;t2-)Sd)?9L@zAP6I)8?lvk_6&pfy*yW8 zm9Ue?d?Q#cp+1Z^^5GzB4T3Zf1{$OR7eyuqT1*er_9l^Km&isK zi7&2K&C!zN>Ce6X6sUSe8eG4QfPxxaN3R}X1Q!MKgarL_-V%D z7N1Z$gZ;;66C{?Y+3XLf)jS<%69eddHbH!0Heer?1jZI!K|UKq=bU}2nHcW<8oII1 zpt{4X1))0iQ1pd2&mImSUPu3mxQ(#A3vSP`47KZUuuaQ--8!SQFjEu-e&&W#jpkzR z!iKxJkt8~&iexB}FIAMkQ`q))95a?U@q>I|y)9nvT3r!7j-QTr=#VnI&3I==n`W!R zE}=Pg-8hA0js5Jcyh|lD>1l`BC&ojFSo;os&>crYyJfAq1OkQpNQtV*2kwD6b}sy*r@l@}+I#ELEjUb;SMJB7489-5FJ*J7k%+b5qhkY+beKhpMkeQ6W zC>EwAQwM@C9T+GVKvp9AOueKvMyyCb%5eb&Gh;TOH6(?>{^&64&SS7wx6pJJw92XM z8E6j%5XD3I^rTqrt2;O>qEr!pm{hRC82P<0Z z^+C8^^!1N7ub0T(dVLVO=gj`W23=iPZbQGenk|Oki_cM#0Bj_OusZ#7M;Z14BNjR{kWlNW!i3{pptBFqG)QNfGxFWEs3*<;G|(%mqKqR7Yl?@^i%91BT~=j}vp-F!-R33fQn!!EMN z#`*ncb<^k%N<9CVGfKJqlt?iAABWf%=Y+ns?TeH0w>GV&lAN{&eUI)*Z4dgcljGDb zxHH#w#qmR=Bd1qt>}(hcf$J-}qOB9TF|kVV5?!cw4wp!AKRa5;D0!MQGEA?6UVSH^ z*NG@esyqqB=!!#ZM<1fc$c@!at22Pj!R37no&sZ;OD~vnf(d&t*GK%{AFC|pj@)89 zSY6za7Oa2cWc*`aLjfk_AeYXZzTUWWK?q zH95i3bRmX=fx=_1;?z=2E$nkMQ$qmJGJqln9YrP(gqKdeMuiVjb2r7Qxfd zg;P_@#~=9E@;D!T;030)G=F;163sChU+W=V6R!=M>27lbksv8#o^zVBP|F1~d^xV7 z4MGJI#4;^ag<1B(##RzdT=2@MQeZ`;(DWjxkfise>VEmc zwz3X+*moUZlMX{Mo;rH6=A@8}A&c>mMmVTh6{o0Z+t3rW^`U-(7r8iL0)nWm(G8bk zseI=s9B}gMR7a|DFLGr;&9QZbz$B4+OP-UNZZ{TwBUoL1#cnlxOS{lmb48i z0O#Vh;ww-zmDA>K)FAK7(pz87(-)C_9Tr!!PF;w`vcG#2r(qeB%$MmULp5`~0ZhDfXIqNo7A zEZY}$pmt%c6@JWzRk}&2~wJ-i{$_RnVPux16s=Xkzj~^ zYX?L09MNm5!DlGVNnCtC8lruFaCelh7r|P(py(Cd?rtTWIt>OMENNqRD=CD4{wi)8 zWiE$$FEDtFmZLweD;iH^Xd_Q4k8L*Bb$^*`E24ms7Kn0hzE`S%TUO$ENfz!H{6R=0 zaf9fH4%!?Dy*wM7U!P5?d}rFi zVGbC!ZE6S(gQKMXC^&)IG=|ek36spD>{;QoP8t+WuUNZ9@}#~W;kbFV$2N7)_@V6h z=7zPWHuunO5uHLw3))-2PF+8}d5N{RZ|=4Bj?H~`{SC-cy8gz^ORYV-d6~8MrJMWh z!}q6zM$93~=}jgWk-(^}><$9V&ueFy&Y#r98#%H!xp6ZW;WS&1(4C7!?%%bUnw4#Y z;jCOS(%LoyTDc)B-3E8;HMK($OFbY46{DJ6K0p>|@GJR3kCrR1)dhn+oIMj{F=|u^r*(T2B!H z694!3zppR+8S?)?AC~oxO4C$-M^;GpdL+cO`YazWz5ec1OlcLAFkB&+Ijz3HuitPz z#plv$`MT9*PUs6icKoR?ho{!~8RQ+Ts2WbSc4qCLuCDgK4u4kbKkB^xGVuXI@qtf` zkrl4iuA>r;P5leW^{Yz+a`NM!@v+O1czpaaA3LgrlUDy1A9K!bzw3A0Omn zYE^QozfEo+5FC`q&KR-<=~^paVarV6^BSu&Rwe#wu@z=-HTQDSq`#Zm00~bdPieaDvz$|*XxYeEQ68Xe6l1cWko-h z*$MBm;1|2C`evq{ALpfPG%FBVX8AzRCGxQu4`Ji6oM)oV;Ub=sE|z6K@{stXb$k;%dJxRpyRy_8*(ljB9L%r>*aeG~ZK zh{wez@{^3@p1UwamD$}>3`OfoC4kmbm)TQ{^h}k5B$U3pjH$p=vICnGU4b`{*#vG} z#+B?q=`YE}f0W!1nNcYf4DNEW#P%W4k{>!eMJUF}vI{`T-?-G%k^`zlM3Z48hmv3t8L1c$65JpoBoaEJ09r=A0c6AyWQ6s z1*Pfjb6>X;okGNpuSR%c<&`9%s~(GQsNMicl5y{i`L0nmmg5Ru2wYOlU zy=?Rs^-)Zhv{ZpAd3A}vq1UUFarZ8kQ-<~;zw7R@vx+CtMzZp1W<*Io@@Op`K1lqL zRKi!28CE1Sto$QSG_`cbtm{PA1W#lVF2oAT)o`OYrG=YC_h1TGj1;%Zjy=8w9Z|%; zK2~z$f|3Fxr&`;PyU7X=Ac7hZ94;Cb>7ybx0G5pYuwl*U#bt}{(gVjsCn;9gTnvA*v01M*BsY%*E3&0;aBAug+<9A zEF=6@ri@G(0AiSw{NVci+KV#~8v`ONfU0LQyL#|bFZyIkvMkP2XJ181TOpsA8&{wq z*>)|1$||#AM#WuXs1MPRX5tGBs!_bCLFr&KKFJKsJ&ube2n>b%w>@d;!d`+S`aA^! z>!b*oc-5b(bDC+FNQ((GGFdJ0EZyZ*a_cs;s?)p}>vDpyVXTBB3V5>|&)xBp@A_-P z2699J5J4lmqa;#ZJWb|mBxNgs=-p+T{pu3y5)Nr&goa2zR^Fow8w5Gr#21>;XHpL6 z;Qeg=JOlvDiY+hwaJUI;&@=)RiNj`CMR)WoY4j-XXrTS zZ7TW619XQ&M^vaHJCR`y*|24SPhgqU4TkTLcQpFko>}{LsMUv+VA}_q7dq9G9tJ_{(2Y+BgJlL}!U;L{;eAX>!bHWMNx! zy*Z0M8VbRcLPpwBO(Xac&Q#}KMVY!nj_TcMBx}(Kg(PhCK#~3gjhKIhpbaqcG=foc zc6u>jU6&$_V73Z0g4+AyG{V`((P%NKX{3I!(TL+cZw>_V_zM#V8!RGx=qp3IyTm3^ z6A0Hm54k1~B50jJknNp7sNx5S%gr;NK$gK{d_OG$2?=Q-y57jI&(7M@P_oOBZo7VB zv-^}po#fgP)9Hl5x^Y9?)^xY`0D}n}rcFJHAH!`hmwKSe;I;qyP!CjN)B_c9a<@^9 zQ4dtqDsSf0^DKoQ&WnG8dTm!@JEmF3M;+A27iwV^i4{wd)z;`ij4u>$9Q{(-+ zvY)UIz~e?gQd^s2wy^9;J&?HXfpuZ31ka^fo)9YTfUKf zZh4yIF=XB9dD(CES;))2FK(rC@iO=~ZwWu5o3 zC=zd`^8u=4_|JEVV&C5~yiWQD6`HST_KR9!tpZ2^Fjy1*FIbG$LgIc`UPR+R_?|6q?n=n*e5Jo)j&qdRu4sT3v#a= zWm0y@)gu(YIEfLAr*-6k7y5-L5-o>yqfSoVJ^b?e{Gfo(+nqrOL?1FzRVz}JKBRMp z^j#KmwFTe+D1G@*_Bsp%y8c~Q()E2o z(zipuO-Lk`V8{k&ZWbM*AQf)4z`?U7g_ix&Z~^G9nL)V=ub?`vti?$Jn7IJ!9et_P z3C`lua@5F*2zy3BwcE?Js<^IL1NwKxn>LqNh1SpTEtV7*=z)~Ec2PR$LM2d&mFgOd z&i|I2W3dq%mv(VFXfY-5m16a0)eFVm$1mY&tu#FqOSg%qP2S9&b-^>p+| z771zCRP<1R!)ua_rXbTaV3<~g4yY*|C>65|v*ja03y{!&HUfuY;fz2BsG8R#BO_%_ zY!C8cK7Qo0Y@nkbFzH?_l7d@fNvx}Ey1JQOCm(f52lhYy{C^0K2JT9c2!Aw|QYd=W z*}JMo6>3%eTz00)uD{z7zv&Qq*@*owjeaO4S?sS~e%fNbCl^X}B~%1ISQ;BE7Tb+d zr^p-aojgD#8@<1dy+VeH*>pT6 z=VMGq(^s-<3N1Hej}{3hH*X^*l}XS^(f_NLBWMTkd&-4i`001x#S-`t>ji$-qBxkr zGpIXaogs2GDp-n1JT!ad7sfnJa24p1Mi~-pgC-D(jh%rt!w}}L5jU(`Ml0=jp;#W~r zV}z_u)C1XS+%Ta>d}_*=%S=2;I~jeUuC2?!!-MICZ%uEP8_^?l*S%iL_@{mz?+}rA zpWv82MS8V4hoPh+J!4l=$vxt*YEUg8~(wd@5i-qTEUFS@fDK>IW|XwxCq80%PR^mP@AdL3&iQ-L zax&gK{_-zgI^H|_WU7s*euYbQ{-P{R;nRAN-q7@HoW|-9>W%gWQ&U80p;UTNh@>ffT*h(^4)omOk~6SXE(?~|c#J>G<*NYe&LP|sNmNuV~^8%uhK63~|v5ryB9 zZ+(k)q3XO*{{r^nmd0Sz z&-a+S3Ux1+iYlzt~k)!M6(+4cQeWOiMD1<@+{ehQ zW`bDs{VX!Qz7y5*68k`s-R1Uy@RkGifm&7v?ZZ3M&A-QoZ^=l8EBSCJdn6^OMvuQY z-TVgo@MyaEjdtnrl(-t*^F&HujqZ6e-Q2VfA51q3yR@JpajCE96^hb)eC1rZj4rWk z;=xyz!-r?$ho|*HQsNGZfud>lNqyL73xZB5in`Q@E$WbYF5%NMcyI zoK74AG|vf8bZ=pIRQT#aT$V)sRKh;Ns<83XZ!-R+98wuwphf0Z`69orgA(leQ!=}A z{VC*}LPlI0E-!kCR80E9@Gj`{|5iC1f8v9Q4?4WLUo9!*$b=qWppqCUAC+ZvunjY; zmv9IF;S9#5Sd!(D6#MY}=0m%-Ps@^FjI_b+H@#eS?4OiEKmNeZ^7vhU)hoX7K*?{9 z>o;4zqxln{E?qB=ABT`5M#Y4+fAcv`5g7gZT15bmG3|XH4raGv;(sVu6WQN3_ce3h zH)rmHX6}sEXQD*=zr1NNzw-I#8T)8_I4A2bfOsV1?M2IUwV2AjVTm(6Kmpty_)h?~u zfutdc%=>Lo5i^yNDCkQ2+}ezlj00{C$3Op6DvYFhu z|MXA3_gDV>VPyYDz{&9=s&o`47N!1t{MYYK5lLYaLG<4RaFhjvtePy|B-*Ibvd zlMUUX$vm9omKw_O`B!TSzChpCn?W(H$ z-+lHux9?6mxXBH&?*a89Ah8NbEGa8z4+4~rvSL@ouZDl{#;ErO1E^Pqa{Pwl_Y34I zT|lV13Z=0Wy>=DKN+en~Af<*z33dcQh#eIWHMT@hK}30<@0@Gxz0bMlVvri|5t4n* z*?Z5m)?9PVHM=z@#{9!$wSVwJ(oRTh){cYGNo*z57xOaGnuCA@mY2uVHD^jE% zZr5V??59z^HF4o|dm(g+v}_R?Z8-+C95HJQIfFa5rR4~Ni{#*k-iKtA2+5&Jtu*fB zVfBUuwL%MOdMdKxj2)tbLX3mz#}&4;pnP9i#j3WP;`~OFA(uD<5Own8k=aVa?IubO zl^c}C;GNkfyQj<#bED?t&^xPHTS;pwY+qu@*Su@Yc7nj|IMxLnXmgotk*sD`Fz9l? zRbxxLzppX^Rp3K?Ci~RZQ33&usguW@jc`Td!aUJ)K;gVUlQT<_uE^Of<#{$_8v?B} zy31F#L(+4nSg2!#2^52JoM^?mZ77>+%L_j;JryW6p9Ajld~n*Vw7hnhy~ZyR^$+tG zizyd1Z5ws-FG%ryj_y&zWApa>*7w}_$UO(Zpd#unGeq*PW-BNq19DX$yv74eCV&Tk?BFj6Ha79 z7tn77=r&s;ydHedYYOzikY)ZQp*rgFnfnU1%IhL7v z#YxGLG7a9w_hT>!OgPC&R%*g4klI!QIXV#;j=PJIdFu2LBiRw19Wu1A zCm3XH7javd3UoKo{6(wHGS$jOWIG~Y;s`-50>M_aYjha$AK5IU+n{V15oOk8pCicx z;%c_qA!)T2naS#6K4?!^qdkn)wu7MF4;6G`Y-xR-dTrV;K}CFkiqe|9$f)2oF89%~ z?&&`wG-s<^IB~`l*b#j$*-9}IahG682s8^(hDBW&$#V=e!Y(Z2-_rJT95}mS6nAZw z=;h!mwfK3kon+J66Q^3!JnU|eDOT)s;rz%n0~I=2j73Lm9_hntK6!NeNN>LsFYxt1 ziP}>?d>b}Y?WvhRQ!wpm9|D0axFV>n5Otha{baX{n9(qHIqLlxiXD@V2&-47XVtSq*VA}LNKi=#y zJ%dPnQ>J5wVa(W@L!yfrf3FlnIN!W!`Uo_*DOL+8XIsVhFk_WTF=F6$dmzomqwT?0 zik5S|oo!OvRe_v=A7f38=iNwNViov7T`s;)oj>Ed%(3)!h!zM{-ZwUQ-fxnCj z_S=c}3*rbRgsx^ym~I%fLy2|9RG3`0o)OzCS~4wH&1ySvCzRiZ;>m`vNg?LizUywAX{|EH6iHw} z$B1O0q5PrCmXfXIIxH}&+ycXaon*4T=ZZ_--#AS#I2YYF>?O-qWrM7Ri1Ssz(V3}c zYYE~)*mn01w_S4aZ)uRXh<=71>h_659hwL_jAuW z-6;U@4g!ESS{MPwa^L#t!-%$i8o^!r9Am2DcG>{wk}w?h{})=P!v6olN~bhIzS-;> zM)nCEl4z*~ks(=ywF=nK`9WV4)^%n8=|3lkQ^p<55aLo!;pd`*W4s+rbYvh zyDavc-gerjBB+sr`PrXQ&tFvS`HQ^gX7qWwp4S%i976OO)@9FyYmkS!DIy%~R46jZ zIsu31JK7HZ$a=!kmDu@5oj44#u*fd114&dZ(sxkj{P6f&m|oCWi1%yE+ya^h<*XRe zrs@3}?6nvc_UeyAuS^*JWABw&M!-+4Tnxs>m{UfJBt+SB9el9m8)%J&HI-}rz-c(xu@v(gM_Ww{NkDehWpeJJ@auA(qU^P_2d ztwZrTdG@{$L0G?4Hb@+~*q|@tAqnRIchVf`V1u!(bpdU*KGwzF1}0okzV?ctIJ-`b z?%^w*u(eSx)4@_ZWcF-}DCLzN%k(9o8@3=`QWTBGkB|QoylaE2QYkVjy)3UX3bZ*pjvFNJ&(RYt!{*FRB=hYzh{t zj%)!Ps-uMpRs}hcq-&(7PGeG%qFmWVOyXJ`TwU^^^}1y+I}By?zof73CV9tz@1Lw{`jzO>Sx za?6M+V!7Fwlz_9#i4plkYc$enP?9McY)Z0;{60R{L43PW?LP1bf5lki#6mm17wKvC zkdvJ_(awG|(LOm6r>iPqzM@w`{(Js6KTlx>^*FJ^+JEYBWRv{U2t`e}ozx&nzO3xQ z@y(Z2d+;)U7iGOzl0ngTMYqZpOj?(%x0v@o3wW+IAFH+htN<15S)JD1a?Ltjga$(9 zji{^bP7LOdidF4K4U_hY|E91JfDscL&8EtfRda7x-(Xm-2_h{^>I8#s%j5hy9L(cV zO6Fo_=GJ7p_7`$_1S5<^;Uewub3lCW&fZ+cQ(?Xh6f9-HSZ*RzTLM; z+#eA>|G-U$H6Lx+$0zNhH2v@1cv$nX5eAl?pJ7SOzhmF0_+ik0cq@-SHliOI{=;`a z9e-&04}$AYP{&X(1l@nwo%kkmOBu_Te3SJXY9o?UikXh9o46unq0_q=v<-d_G(001!?k2?nv3Tp!us1+p1}TSmdh zs`x7#kt`1D&D6n{R_$*XRU)_qDf>7fpBQ?KHMD>t{$PPd&J=EOI$EODd`qAsM7V5; z8*F;7CtpRvH)E zOh`6My!TTxZ(ETNgi_fr0wHM75Y!}vg^T;njd8Y=`)N;krnC27 z=;-|yLhqyUM)kg;i*#+oHFw4!eG9CrtH#<`ZHCYZAyz$#d@+nnLij@dC;=_}>M>Xq z;mtJ_EcT|UMEio+C^0FpSX-*4d#`xFbVJ+L#0F>~>;aK-ZjS>VR1oy-#emD{3EV## z5x6QIg47KE+bmHH@pnz41Fl#O_5`BT_Od4cX7ej71pya$o)E#bomWyj`Rrk^CtgM> z3-Y>XFiJ8)tF)JZ-YCk5UBw+;Ix+uOcJ#>Gk>Vk*ZAEdj=reR$l9f}l8Q1h35kW)E zUoCCl5ynBOr*KZfC<1M(x_gUOv2CoF9+OZnl94d&iy4#B3OfH+&Xi5zw z=Zm4O4(rDLVdzW{)uh%(DNGpout~r3iB)p4tWBP)E&H1IEz`Fv<2Ml)QLVPTmExh< zS}K~gMP4qn9uohTVjpdNf2rC>)^}JTv2*1LS?V&V33XyJS{WS7uE?PFPBc^%GAM}q z{W|2AW1mb2{c=~IN{!eMR!X5lSd>8vl)AdOy4%An9Rm^14J?9_6tngfZ@tm3cbG~& z4E-x*XTm1&Re#)E++PiM3r_6`cvf0iik9oj!c9J*2$aH2ey0PO&@Ogo2}I^tq>fF& z^jmCO`L-AY5k?S)yU-v9C#`CtDD%HZ6Wtq;Z>s3ta=hMpY^evWqVWB2=Tt>~{~q5u z)pv=N5NX-}F>^|r@*fvgw?Qtb&l0kl9 z+|OdRhi5$FcgK#~jNe`DxLZjU=Nw!;8(h?dFrl=l_ryzo%oy@2Ph2_szI% z;Ibzghgy8jC7on&-_o#fB(q~0U7g+Vrn-XZEM{|vAjMaykfG7sL7?ElL%OANTm8m#XC$RtyIpAzRWw|lBd@k%%sCXOCH$O+Q zi^0B$NE*zSFz|e-%%b!)Us~Eoz7dv)B+hSy(T1X&K3RaBCup+({y3lPswzY=lQIK>+=McZ_xgNp{l>)@Ktt~veY5vRI12~>PT5Es1 zB#^L1zY`IPnDLzgC9!E#W(`>O5#?v>QqNZFgyCthy-9*^HpG~{s$x>wZEw9c(1p!u zFr>P|Vzi+hFnYIwK+(gOh%Bu2VQU^$p;u-Ydk`48EwV88ID z?>byFn|(Jx4WUxtOnw>af}U>)a3eDNVb8Y2Iqa=SzOcwgHnwy}Mmsx(;9pRvY>}g% z=m+B&oS_O6$Ewz;Xyd>nJgV8bhyKtI?71Ipn|Qu*cO25{FBBK1uipYSB!U!t|DlK~ z6JsB$65fK{v9Q>il8qQ!S^a!lxcZSB&Fd^~Z6jN_`j;GM`t$XCZj&5nw?ey?} zKce5({r9`N^|b50YtyJZUdo%umbC}N) zpP2bP<3<#P859`V;yNOIf8wnuK(?j;*`I`V$S@FX0Rv*98#-2+ulb+ayQ(Sl)9@B@ zaQRj!Dnv3qn&m`HHpNMUQ8OFqqybFhXQA=t=lb{z@Ab%55}b#_i-y2Vym~mF9r0j@ zJ(Z(G4;Q`9pF+Y{`02v|4sN^H6=(N&@sSk~B{93X{In-!(-{664)G9Me{pND`QHA% zYy~HGimiGw?k=uad^Cm`@_SfS2fYV&DDhxu8uw;V1As$HjZN*L|C#k8D-e>Z%+Mr< zMPglHJX3fTg~W{~T`%vGqvz)p^!z-)o)GNchn7bcqUDkD{Z6#l(lJc*8ySL&`))rx z?`!+rcNpCK&YhY=$Bpg+%LRTc>dL)XwGapSMO?a{=}@zf;L|kO)!Hv&Ym`95IY5qf{ox_y{rE*_%+)4#eedBf1KvGU`2{Bu}-`%MZZ^h0G=#gKPCqmD<~5VKhE+t*ysG592at zQXcn*sQ**rvoB#YG{a9r2;CkG%F|&wh^!61p}2s49RZ+D|2hDG`BYr)W}8hAZP?z- ziNm$5&kAaBLBe2!p|1&agMfR>DY ze6l|!=GsD{z0+@UXyZPrHaUp#eIPna!hqd3_@%Ed;+oWEPIJqcx zwx0j|!LYzU@h`*J3>YYYA1(wM9NAmXU=)W(GRc*ZX8q6x8pfdAfsA8XV3ihxGJK2yCl2*zRUSbhXjQ-2{rtu7iQEW23p$hrx;THe9poSi+@Y zTtP2|1zzTl2Rgbe+=qw7jat~^*o$Z`z`dvLHs0$lIi89$)&rE? z6=Gp&!G?(&-}z4%wwlR5ci?bKM~8ZwjZeN}SjKT} zB21s~(wd!Jb?G?}Z$~6S(=@Fas8_*sr8+?LA;IDa+I49avW>_iZDu+Y1tUxC#FJpv zaHKCQ?Gxbyw0=M;gEg|YzF#u&ek{z|AF49(TLL}73m&92iz-5xSzQ%z$HJq3GM7VhH96Dj1tw~-Ga5d2dt|~Sa(NQR|Qx|&kifH z4X3yR1VkGWBu@CGYcU{@dQeWrTiVz%9kHue(Q7!#UTLH)^7DKiO4O%xmQs(m+1Tmq zoP7{kuB~si&k`-HA~pgAgNVCPB&vTb2Ql|G&Zh~{|F{@JRLWW1@QGj8jT>S&c2&A@ zU8NiIe9q^4bmO0TbmN~E!=>ZEJ29yd84g~rtB>|XoyNb(PA;$z(_`nrI==-w*s8EIUGyD@U{Ra#xfw^P%Q@w zYoR4v?N1j;bFMDlAZrff(NEHxj%_v4k_a|q$XV&?xyE5hthxP$ewNZzY5SUvkvNAD z!z=l!F~q=@>`n)V^)xPnJyt$Qw~fd`@tmj!?KHTQcFj%;EuGHEeVUD*X*4Zf$nHGu(T&n@J{Z4q28BSj=~9Ld>8F#XF`ds_fHsFWXJF}%~CHht@z;l3}1D(^K7 zNMti?X&1x0{}NlO=hs8dmU-o00u1HcfR0T3wA?zjA}z)O-SJh@VEZ~5t1_(lHe428 z=!3r{$|@Hk;zE*}$T8m)I-qU%U6qF85)=dAz*V3==lf*uGL5OL18m#xc4($Cy*ofF z56}ilsaNND_u5KNuC2Ta@-dB?++7_mZ@kCfFfR0-${XHyJFMKt6nNil8O1L!og?I- zR&|ABn$=2XNDxGJy^~U_48o{4LKCyUt8dbCB?6TQL^cbsAJ?BS?4qj|yEJJe(>ogQ zKBUaG^_d6)ANl#pQfDcGrae*YVeR+&NE+>d7)mC+gNJ0 zh6^(09R%lzv&_#E&lm5JK{QO@xOI*VmJv_+*UhL*^8Da;9x$f(nuDQypHzrPD*dZR$u`$I>{9HZpi8YQWJHg0JK506Pk4`({d zyq=9pxt3AZ%-U30|Ja36W%2VggIq1iC|64|$`ztHTKAD~XLKdM`*FIGWb{N`Niuq} zuAJXKMOVt%oUSX$Myar+a7>7f>$u9%aHX8h*}78B=JmQxo|L{(SIXLK)|KeHhY!;yrMvAzc2asUU*M)K!@i z_4{$tXxMyTL*_(XmF-;D^$0tB{9DY_k1 zO2K^FXCF^1^$MtwZHyzI=XZP9SLY}uaA|{yD2(;j*IwR+ezh9}Dx(&z!R4U_92moV zM`cI{$SpA#XeY6jmE{xW)1ndq!i;g6)(8-=&5ISGGM&>R-B2=;@A~oMsj-{Da1b`U zl#cQ$!^sqAK%rfDqUsg}gZxJ!nWCq0u(4>V4bn~3Ye>pu*cA6udZP4I zE!uZuIC-GGyhlTj#IbN(bS8*2M6C-vcQj@J_s%k(pP5+|a~PIvgK9A18iU3)4xt(d zxxp7yeW08HlANa}=sU5DcAa6)^?i*M=$&B!dcoe4NlmKXPeH8L zduOmf_5BbRVo2D)LfobJLXe4RkqQk2dDYunps`3wb*M$Y=C$=Va@AsmOZkVhxk?Z@ zU02ajll1K2w~buEdDthSGUdcjJU7VexC-)FM*1_c#3GBR*yEfB-0NeLj;XIxxV!SC4^r*zY^uHK$2ZEAeLQ6_Y0OVoq!hbDx)MgM z$en%_bGOH!9i0|gZ}Xe3*B@&DOgE6H1o2FQ`7kW%D{S=@d?4rh4prKvBrW%;XRH%f zBm+6!9@6nZKcG8m&*~zCdcnM&VxR*1g-h3!XQmzuQVyIX2@YKS74QlPYS8+b z>ckWsG%)m>%|@fH^EdRHob>iZWs4`R^y5xS_JaLUoh*QPlNWkeb^9E584a%S(Il<9 zMuUpZV-40pdOBF_V_RvQHr-H0Q41Sm8oLQd7E~jc%kNp8AC+ThZ{Ag~OtY`I<#!s3 z+ZcV-?2THVnLQbk#nOE;O4=lW`yeL-W#cC0BjpvHkLF26hT`VWAxY<@xE9=}))zP@ zD?+?>L%mF~tOq?G{bB?l13&tM zubETYHE}q+j$}&|c%oz{?{#bgfEr(0hgpIRO3FGeJT2^~a3TK(+v{P5 z3rYYe10wsB-mnomq&FHQh>$9DE?SACHtSa%NsVx=HbqHp>LRdLl;q|KUjw<}WeK;V zJDDbh8<2U9$~&EcFva_5dZEp_aY9v(P0yGTQK>#S_ISq+bV;Upr!Vm%%LeD`x;U8b zsO+X*iX?{?;(eT60EN0=t~FgcZ0g!Um@Xah=K+Y}T;r3PFC1*3m&s4%3DawqG|nl^ zNGhcYtLh6ffqKp{97uRNErlZA*~ma){P+|ty$D-lMQA+@N(f6dO95r9P74$6v*COi zC!U5UwJ?m}v|iNV$yewe)F^WBL*%NAB%ydn!ydQ~X(9 zq-w5dg)gk(QBYMN3O1?&#H^*^%38+v50%kLTS_(vruFLw_9TB1__A#-olF`AVC&M3 zez8-q2n+5rj5L5%&AAW$E)x+9(|DuT@tigu+Y<-4X*gOQR^-`6b7z-x9qt$`%sIJF*MB}Omp5e-H8rVgtdHEApizEDDN`r z6}?tnG(8Q;o2ue#)tapA20K~_Eh(6|qpGg8N_Tv`WiwGI^i0e(C{oRYB+R8fMX#?T ze#WFf+aPTGOc@yHLQVf;$o zudB6ZcRtv7Ii;AiJJo5^#{p~DRgQ8(-rf{$+}`bIYn2hK%7xF>Izdk8EGW>mXWyz zMcVoonh&bQ^$`5iWSX&YzrOdaGZ4%DNm0wK}BN0))!PKvkGDOq?5VX|DP&-NnyK>AGXj9j~V~ zF}l7sM*vtAeTu;%YGTc~t-<#2pQGFK#Trh-f3E$BdoLu&XG zw?@;x->XM!aVMaj<(G~k$m#oXmrK!kjF+HCo3u{}5HaT&^k|7iUcOK7twXQYbv^pD zt}5TBYXfd@2nMZ2klbyqT_rgRbx7td73=f*Tg(V89>?tWS!L&{@mB2Is&uxg)lex` z8^c%IH7j#pENQt%C9ElK;7qoAQ-`|rWZS-7DQi;EbKlMTQ`%2X)&4=<)^At88y^+d zgpZQ)a{g@?=$lU#dM$29=Oy%mVnI9+D{^YPD+I0%w*)#-O6$Td~o$f5`RqUv0n+=7e z;-Ju4R|pndgUJhuS09)K5tJ;UwscUx+-ByHPz)LS42o3YwyEVf%Xvqt+Z1Gna&%F- z&->8Q^~hQ{0jNs%ztKT262beqw z6AmB^03tReP%50Mc9AsRI@m1Fm+7H=e^~S07T{fQVv}fob}-6K zl?js+D9auUTD&W9xn2`^xn__Lx?eG4g+9eLN6bR2YO{wRbsz#u_J{9E>X6>2T|svyD&1!mfj?+s9qt-es)`2VaT zo6U@Fw@H1h^D52n$61@)Ui1_VgT-|pX@&w43O4DYfNt6n)2p`#H_ z(RvQW3`F>Qw!KBwQ#Uia*&67)-GWLS20gKIqxl*|Ud8XQr5tPs#K*aC~L%cujs)nES!=2}~Q zV4m)lp?T+aRunRDI=@9f4OrkINTRN|C`chNGifczmMpC)@2=i)XU%{)YlfnXNR{

      mb95~fBz{i3va;pjqcbzQX@ULBEDqOh*GfVg7vqO6?0Pcjl+Gel%v zXApsPT|m(6>b3A-irw%+&WY5uF9^EK1Pn`nMc7(e>=2!R#7i~m{-L-efXg25b48m@@gM~ z1is8k-MQ)5(Meu7i9Ei1nR%5DAZAs)Luh)kO>m4ewIH`86){A_VS-ANt0cCB0PFnv z(n++;d8eE~{-@$3;xXnsY4gXNL}L{vQCvm{RMOPL8fE89@&kz_tcM3$lg?83jGZZL zxB7jf^BnvAWW}q5=hw^8W}opKE8HRcepah*ZGBC=b9Re*sq5mm*Pn!bzNEe7)aj*k z1UAq40LltY!5qZ+mqo_kysN0EhkT%fdN@Por6ZObU zOP@55^X!xScbRNW`Z>tq@r&}9^_`|W}nXx%=wHRzx~tggJfH z>0Fj4ooX$yeD>-IUZs}{HkkJThJw@0pDv9%KoKli*qNMZE(uqNUa}JvxPFoKyz!UQBsD?Y z$U50GzhUgkpQKv(z(q72uvJnofxR$cxf)%ta@)ePQ1eZJ6{6;*69Q+)toiEedQFuh zxWS;joLhWNeSv-!drc_-{k2f9Ewl!2?fsg&z9)n9x2)|o*JOxSCqvn_*c!uX$lBP? zL?B!=U?Xx}IQ|C2NZD6}U@>Io+HVAGi1$o4%5la?^NMH+{8Edd6q;8e)m|uTA3>P~ zDOii$IExI!3#U=$++ZmQ4Y(?TrWdR=FPIkBTBw+|_~TyXEV83e=4|oDy$V@eYoQET z@wnDnJP%$XB@V>Pf5oOk{jV66zwmJ{%oWESDs%C8w$!Lx)3LO=SfTU2L!$G(NayY> z5m$)BZRXZ#jQr6n5+~HFU@1~h6IztP3S{C!e2>>+F)M#)n9eiP zeInsz4r_7pn6}3wB~EueE=ojolqA)zonx|8m@C^Q5epiU4jQi&Yu9S$C}XX!y@f2H zdZBgrhSu`2#;WY_9atq%=S3uxQ9fq}_Jl22Z5I8bHSkxwObAj&am3DD*AHqgYqzYA z3Idi~)$%^F>&DZ0{Tm$u`!4YN5nI`1h-JdC5X7ruQ<5a<0%YjS4l3_0+0klVDDHkK z1}QNjl;p^}k(F#`F_&!8TJCabb;0y!%d^AJYpvX&4T#5VQ*82<*t}U*TPn(Ah9rGJ z5I95V0;$W-o90+447OhEmx_AMTH=&)%&M^VU~8!wT|N>UUCz6TWl37($kCS(B$kBM zrNGJYAa|Jjd?OoW`hAtsqh(|+kkmPeKwKUFk_~jFPMXy%S#vh8huNr?Vy;`Dm$ki0 zn2uO$4vz9UAdX1)k-L{-W!5YxrJ>EjfM&rW%2ctOQH+>4F9Hz4R-R+%(pI4$K_zt< z%$C}3`U;8gc$p8%Cu?c8;#8YyX(rMbG&()kIjQB!Hfsa>q*ohbqpr$&sazL!=^st9a*|S^1$~8Nevd_)G-~e9rN_BHH+804q0sN z1&h6g{fE{{j_gIo6!TfcZ{%OXh~?C(fVl&u(g~lgrTnmr`Aej z9TAHu&0Ap&80WQsmpgyLh-r+;m!3$6AP9TV<$al%7Op)ATKr2)VByVj)z}CbgI5iU z0&FN7Rt5$M7`2!V5tx_!ioin6uL4-vcoc)Z{+0p`MOAAG9Cl*g_1=cCU&ynrNmouj z21J4~*NFl$qba3qJ8o%SLCdx@+J2F@jj|Qmb_OSJhRn<|=L)Nia+{Yfmd69GVS;pE zVKZ4BZ6;CFHV_p`k3I1UTEw&WxBtky5rqXK^Pu@pwn_}J$2VkVp-UrJ=8Ztg5k~&$ zHL&FS7j{Dttm+6A0eBW*6s*5d*M9kReB?49Y2;=+LZv%X_YWfyX<<8FgBBh3_aK_T0%@m*U;5JvO?q zU7;iv5^$8>RXj=t7*|6={U{C)bYU?*?zN(#^d1UD@%W+c6A(*pE%gtP-o2Pql-@%% zsTg1$Hi#Z#xEFtluZ8MQ9k2D2-eUzLXZoRpQGBgLY`668g@z*M4wZ)DYf(!rr1!9< z5neX&5sEkNS&NG%C^V3IhkhF6cCQ>1<@S@EmI_~Qw|=U&7Mo|U9TcVZP(EmJvhadI zQEGpgH!QM%Ym5CychQ);I6Ta1D!MpSUA>HKsfJngaB;AG$s#VpimdE9k0P77TpyXP zoJ*O}wO?UYTsfDrPFKRR*6WIc^mJWukZ#l!2kDu*F4wUNuAFlFTU}Y*XX}ci^gLa0 zl)gb%j@)h56^H4p+y^?|w$(mx?u}Dy{KCOE4zKZnlWy;}51e$Hw+|d}`(Wif+I8_f z+PmrmcGb3ECEtDVpXx7DzlJ(0xW`**^XC|(@{{wE@tD*&P2T+rhnB)KWFEI?$RgS2 zZ;j>(FyXWjoR42%GsGHW;Hu?g+)22DXWM?4(prZPNUYLKipCOf*3Zsd2X%S!KTwNs zl+~Hl5uLUqj*Bx7dGgmJdBTsFUMlZT*1z+D7B(gK0bPa<$ecrPF!_quI?s1s5O+wS zgrcyyRTo2R1g|Dg`D&q3u~pe@vwGFF^z>lqQ*bf$gstvhpzebXal&X5a9&AGJS#UnsS&Ns{eY{{h@XweU501z(ZFa8D3V-`I>b zD7j%i>z~j1=HZ&3$_Cz-^}jFcd*8@QkgFa|(|Rxe`q4sxuZ|Y`TFOMQ;V6s`+-ql5 z2l%c-h`Ju)S*9q2S#|@Qc1-d57W29=hs=OQ{nh2LWc|uA71us*X#-mC64L;;w0{7x zaF17F0~4l=XPL*ooh_oYU&Eu;YF1al9{qcKk~Hs66-390qI3MX-yudr$af?ECs*@- zawS$y!il0Cv}N02wUViy=8$+<@)4uQ#cjiWfiFCdH zq1UDbDkd?h5tXCwjrQyZ`p(-y9H73j%>36@yoC3ZS#*Q9Ku>$4OhYGeba zG8cUu(_oijg3poblV(^EHq_I#Iq-{(5O-%k$l~wIr*@i2B4J8Vr(X#}K+<7pYrP3W z_B@FV_({f4TTHZO=mIe>efg%HK&_p-V{^`<7or(b9QoR`)^{O($^GPwYa9(LfGZ)! z1Ye)lJ(PM~t%dKjKBK^{bfaqvc0;leQN_|F^T7-FDEUZpa!g$e{ls)lzWhSvXa_D) zZqVuu+_o&yW9qNRv{<{q+H3VU-^G4{iWNUF0Q;OvDuyXSzy!0NNhBXH5R(NDovzm} z%oDx!N|+jkgu2v{0aHk_+G`O^i=M(07?s_rc26o-L%*(5Cvi6mZJHFY-vA*5C6DY$ z)5exM{v1n9Z-XTP(w(Dv<_&UX%v4(V=p`W@c zSXR%i!?UmNC$k6WdWx0~*E5I|(DgM$3h24l;ojHx#3(d=5Yk#nu=vx;8(iGdL4`9oq@9kQyo8qGzvYjS(cuCL!4NJm-sEVPDkh zaWq5kM+;lxC@yV`ywP4{&92Fc{ank-H?EDraD)?%&I<`ICsAQ0uc8NHbs1QU$}`rK z%$R-KUyK=(AdXjpi3}Oo-*Jre*&!7d<4N9V{93p#)t=fxvs&xb2wo z{>XrXjj{QadfYqBCxuaxgJ#y-@<7?>4$;3Pk;ZHNFt}MSNpoq~A<3l+=wQI4l@XqQ zbqgfL-}P7`SEkUbJ_65X+}AGJD^ZB00cU%goss2hN}{5)bRN2>C`NAxd{ImFqBmNq zqA)eU%(#HKv0{lamPda>gWa?x5+M%2J1FwWEOK`t-b)S2Edk?Ew1E3AN!Y$z4#5}@ zQ39|vhYZY#A{sbCSY83FY~0NSWZpBmMkkTgc!-^dvF30lUxu2LLLq-fxNIk|l+m3S z`06ZLVYv?x8peyW>r%Fw$|SO0I~Iu11|+|sHO6a!0#1c0?A$cRN)&DClctr}w|#m- zGgmZZOPP7rO3=^sROvN4v$MM#@lLLmwxSqs7bdIo&{v5j87cEy$O5B{iW4IXW(I#UN^lh^>e_*%#<`dVr^4 zt}sfFF`~VwhH0CP^>^-HAJ%>T_8CO1`-Wi&Ey6Hh6s%=f^N%{cZNC~?!9NdRWiFqc z5r+NQtokhMrAD<1Is-3K*@`}(v&UMbdu-Pn`cRX#tkHy)^)a*z-Zh~VZVCKF2`OL} zEHJp$NMA%2qRr?|sFP>|8y{n=(_3;-{3V!3qu*879PmwExD1sQs_Somxud{tBegu3kOICiitZo#wnBwK+oRxJ!m?=hJ; z0-d2SB3lh{{zcBCwnTvos$is}j8KbAq`~5NIpZ4J$yRSG%BZPsbI&elb8ooTlbUCn z5IdIOlOYkC{*D!LPi&Y?#UA$#)YuIr`xslcKGV@SG>glW9Ewzr6Rw@oP>F@O-#Z@E z86|^Zk-)!7cw!bztAWl&Hbh2WunR|N>**Lg8HNL1Ri8DVACV)75f)AJvILu4u8Du9&uFbj74)sa3}08{s=9 zt&?@dq;-m}n6%E&6_eI$be%XUeO;;bl5i1WdE}FWSeSam@~^4b8WfzGOb134f?$_R z6zBKVh`3^4M?>%WJ`;js5s?o?gjLL;v6X>7G`%%tQlmdfPJjyBxGqM19Qthfm(@x4 znEiIru2qhGd5EZ%&;TLz=3+|M$1Q9Cdeou5Gu!F8xSom|tek=I6p>cS)d?gQLQT~v zF}H4qNdL@C5zQ~5XuHTk=)Ei_?OHZqF_JpFcmh~JmL&eTc_|&h5$5C=jsdi5ZN&5D z7q~cOEk|3^%iU4=iR6A>b|5b5#pwK6{=i$ta`aHWSVrkfw&%2|NrOrAUxwQu z$g-e67v37IR!w0G;{Le(XQP5^i=01mI5tbMjANm<7wwvEb+eTZmu=$MGAT6c5 z;nl1edX?WB*n}|%z;OP+;{m~T4r4LfIgCXi6O|<@$~wBGE$VT zr=TV4_cI7}*LQRYyPk=zrSE6yupRf$CIVjH&(m2zu5Un_)^#(n^15DJBgR!92%}$W z9|)sgW*-QnU(SaRJ+Ei3Q=NDHva2?Iggx`|8d1jjGMwTS&`4kLP#77MB$=z+ub)87EUhXE>VETGbvsZJJ7n)=y3d zZGtv4#OW-PB{8!zi!!(=j9?Ok>q@vMzh|3ArVoo_O1EV6KU=kdG9GpE_lGwU!i;D| zzozYE1Y%fDHvbLNtBsLo3b!+D&hbJf$mL?hWQv_3G$C7VNZ^Q3#^Dp*$)@$jRBM_| zqWYePomg#yY|51PF~tEje=*!noJDe!b|rIz6%T!!LLe^K-vVemE%K=y8f#r4V^93Ylbhqb0i7&g!2(*#NO*J zA8Ev~(h^~2ELnwy%@D*ZxE0(|lE;;8&XqTRG7)z`vi4h+LAGr1!Kt8O>!DjF}7yyEqD~hR5-u@gnW+o>&JhkJPMZ1`xa-3sDs4mk?93&D8Wkl`OGrGc8b?W z?&k_ncJe2GH11ixi}MAZQd%*E6&i155crS}mU_3LMuI1UoC?R#26aF$Y@CTGg%cx9(iw1+#T%RWqZ4*{zi)B^()|2_CUb3R)kF&wXskCp`||k5VXJPkksR zJ#66-6_ttc?uv;*<=v#~JG~NR3YwDuBouc2PH519AD1W}g<2qQX;~bGFQ~;2N{q;z z7EVbN0U^eL8*o&W)dhVCX;Ir5No^Y=xtWN>3gz5c$yXPmc`PjEG?6dLRtuRj7KlVELt)gy+E#wc|TEXc~>nBp4wu&a8nB}`XLM%Ij~`{u5{92pn2I* z?QkBW3}j#FCCrt|o#AkUMK{ChVVt3Dff`{s`Z`j^Xhzk{ zmRP|y$}=3!$_iBOZ%o)Gph#PGY4~WF+p6IkbuvAnWD7>VttHdVayJlwK}_Z07R7~H z&A&2U91!OxD{5I&T@D8;;#ru`;R$s(%p5%x?zn{dr>b4VvR=~NVKPx-7xHB%eTQhF zm9XDc*-~B?`&EE`d$ATDFYgH#6DlDv+IOUlS zdn?1olJ#od88@c%mm>TNkY1Ke57yZGa5StDi*Dp@b#oLxJ)AHq#~M2eG7ngbOEOz2J-pnoVdO(PRws(GMWlTl zd6j9GsHa>c&DKa>@0e`KAA#omgbabS>UTIGQ^o@FwlcSL&^-J}IqLFz-?IW{Mrxi_ zw36S$w-dD6yfm3C`>q);7a+Oa)HRIO$Zp;>Ng}@XnQjSb5xIk}sjf^vm=mxY&gB$b z(J&SE0SLq1Au)OaoD!4BVDEuYT>nQZfVjSe1RifE3(JWid0F9QTXt~PYU)Pb$%GmKNY?WB_Is@ zB2+WL=02+`^McoWM@@%Wm|7UCAB(b`F`S8V5MyX=E3=7S>!>z8s&(Xi5>(1UJle5q z`0*wT!&*V%bW_nYr_G5-_Kr9*43P$e4W%B=O4oF{yM0w#eqojW~wCAODS}-%T(JAU*+$8H_BG?N40i1edT-* zo?{EFaFoV|G}B??qkiD0u{7gDKI7p)78Ya&k{uzv>j3A@@`055 zggElSA{+H##ad;)<^wtWz4XvwYtxV0FQo4OPy3Kretw>rR(^gxeAG*@spv!Nq;#)+ zID9QO75y@~HvM)bX7VA6nH;%9sqlK(v%kDpEQhR8in)jx{AHEWcUh%$?VY)QCVhsP z`@^KWk$V7J4yS}kF2GePpgSQ(%-+zKXZbh3KaMWt3ckTO%~es9x*m;LQumL;oT%?22whdmLBFrZyr}CbSQq=S0iKRc zQTI0@8|r$dg@(vXiGz*rXTzj)MGdp-A=(2i*eB>YA?OF&U_Y^I7qsdizrH;uq)V~M zGAW%Nu8MKi_cf+a9@m;^_n+JTUw>g~C!z?SO_+#3jp`KwR@zwgD^3;S8$^heEZpuz zAtzlkxJs1A&v<3lgq9j4HB7NHal3Aw6hFolV>eh}IBiHy7YG&gS$Q#}=W;fh^l%f^ zbmagKQPbD8w~Wm6rtx8g zCRZN$>Vi|IM|VsW@*YmK>wm7sEj6C{Qn$Y3oz zz9dQ5dD?x37Sn|@oYyxAbP_rUrO{V|uqM4A5MJ!?Q z%z1_jM4HyJm(?22)N`!#>bYCG8tQqlb5*oy zBxBsGFs*(Zr1V@t_!v%M7>uOU=Iur+)h%$%0QEy+yjkIoid9Wb4@=pJ66s;V=rA4( zT(1x0XH4tjdTt$%efUVGPerSfEPt7))3`HJV3dD{*YV&V&uO-Si6^ z!E)n{XYIXV{ycbs`GeBj-qJy7K0{C2CpWY-noll^W|pVvk=r}0N5R?=dzA0{mG20BoUBPP&P!u@OqDt_DR^*hDfhydmGY&6cpOH1i@&kl{uF%eNOy0$Ot1(=3AY zH?luL8=iO*G1u0-&Hf3sv)aw`Us^jWK3>O14~A#MsrkqKX}@D=|37>1yIES5&ff`rcIfdafK_J4M%JFG)|=6;+LjeHO!W zrmm=JXX%QncDAmlYOgOl_qfOO+&7jE^onOcP!)Zp+a$1VU6uS8VU_B=fy?#FfxklfW`A%15zSH$A_5|HOL{V2V50iHk9^X8} z=!A6JU@6SJ42Wg&WIv!1WlhbaM2a z-eNo83qRG2US`tQ6PmY0*}XB!i$mx|qEDg*HGpeM8L-d9seN9V3L-s~wsfL_JETjb zCm5NFpiia>A@H2ml5Ffe&ndxk4a9K^B-KlpzZDKRK)wy++jA?B8>jMnBOA98X41nr zvp|1B;JG$1OxGSzZPg=K61dxyhMTUiQxu_%JN^eQ>hY{eJ0lW^%P|Q>8IQBy*)R%h zuzJAUSVI;idr03fg$lN12pOmL+SXdWn=OcZi){WHbUUHhXtq>;GxD%gMUBW}MY<2R z$a#HwIUP(!&5xTXRfxVQG03E{-1!|vsoqN^jC1Xs(ri37o|4L6hS~fb2k}{;f^KhL z(IWIH-}~$R7X2_ioF9zoee9rHHep)!aDMX>tFhIPC}bdsYIbne#$%}wEJbm*x32>1 zWKXcPFC9KW4~n?MA7CVc9~7OizZv6dtOv=$#;77eUlDlKAmkX3fwZEJW^*DOl$|4- zrXpm+GcxGyMr-U9t?@BCu;qkq^qd+#o7s37M#}F@mNl86Ip_-#f@OD5yezy0a5D;P z(1a0^gBibrv|5T{G%{v(1AnbSO_9EgCR*b=TEnm2jPj6cM9Pvaxo zKv+Y0vaa%~Dz1<3*dE2xeWT-Q8y#2dHAm}r zHn`(-B{=m&U7;NdQZ*YS-^~Wem5nb3sczJBcJ7)h8{Apt#)je!F^*i-N8;%o2cy>O zt`9?bV^ZyFy2`evt89C^%C@Jgf>d?wH02y}XjU}ExxlGb6^0I^(^`o51O$`_N zhn@LTwTocXApPK%zJM;$9{ivG05yhGJSlFn=~O;|EE#z)P19bc>Z}ra4JR~e))nc= zc_36Q*0&rg*6))Nn-`v5?5-UfY{Bh1uX!r%#<^xPEBDjJI5A*}wgn^R+VPp zQ__mlfXo2PNq3q-{q(w#{FY;~;9xF)nzM~amVtuW$nGk#0=dh;rkKMhnya+%pu$!U zq4Ei=&ZdrQ%xZ0FD&K)(VXM&NWI08d(Z#!m(xD3n79yv^3XB$HNY+&>Lszj3kGfX) zh2q-@%jI{u1$0%gs;;tt=(-+JSkIk~l~`Aa!unlSV0}N6_yB!>9ip+m|1DNxeLou! zS=ZMiBI|mHB66^oQZR|Sf-c!c{vnY`vvj&dHUD@Paupw4m~C=b{h5Gt*^npLxVl8K ziJf$2P+}O4Tgf2H76Msj&8&a9%X2)fvp+ChG07~I z$ALK2F*=~iJ_(8i)qv~BM1+ruUl0IxT5DWSu|JQsUvO$`j3e#3(Hh@Cg*BWr8Nb-0 z?H8N|r2hK)_LBlM(CR}3eyX;KuO{ZKvb~#$>f`+yf{%Ewd?&I}`;WY)13-{sxFeaA zRci3nO^Lr5iK{vMdJ-y`xP7xlB&p2uLCgWe!aFCgC20xWh%S%`_Sy4D-#4`V9E2m# zfd9tNf(MatN#N;eHULlK{K+_r$ys|PibZOLZSWoiC9|3@q&8{75hWECy41A>PXgGs zgSz#;q=Cgbskl?+HfjyoQQdf`izrt0cD80#C*ZbYa1YTBMRFjkBBG3mAyBGbJ%JhQ zA>4KgZK@o$!J-Z;2r{p*$d>-0NPi#AuO@2Bf( zQVUm8&$(hFI8(oK)aG@%E>pG`u1GUy>xwk9KuvEaBOlNXP+Q2I2Fo1)mXOE{&O;ul z+}Kj`xGok?_78I*Hs5n}Bp`f%W(AhEkzc10;4Hv=3(GIxRelq9hI#8(dxlAQaVmYv zAF{8@_4Nk5!&fv=ecfGrUC&pN2-w@rBX<_BHjmZk5i$8R&X~+Ml`)jEo6lEyYtUHu zV@Ia_y{s9F34PioCEU62r#N=^*QqkJem~lTK>73JpOZ1ek8Ym~Cw8H*|4_Em5F?3^ zqCekDXiVLGa7ajdR3<>8(r&j!s+5-T3l>4T9+5#YsO9>CX%J!A8rU#B+!;DQvXi}N zM7lg1G8(3Ia4{IwBk*llTdzXr>2P2|!|)yKXe2LJXlkVq_DQP%0vY+isr*Bq;yj{C zUj$wgW505gce97@POpM_Ie7)(KM^LoBI7xsjTW05IUo7h12 zIx5L9Kqj9a$meSA5I0kXqgMHk-$R##^>E;-fK98`7l}x;tK&uP-t*pkgs6YJoeP}kE)|zl27QI531L_+2zkY8hZ#e2?P=5xf za|c|3y5M)~>TH^qO)P>sdSL!0^C-nZSZI8SyWlu0fcL&k1&>+RunXMDT`t@) zdHMPa3f!6Fti)Z29Uphx1qKjt*Ps8>X9qY~U}QJ&%y1W@%LCbksPeAPrg_=KBDkXm zYwNFP3|O&?LHNP4g6_1r*G?TPfcL+Jy=_xgZ1U|-N#Xw z$E>8h5T0H@?}0scY!%oGuC1UMtd@Rm%z@h%KAPtHfXMdU>=X;eWpR1OC$d zw%Nfv1%C?$2OqKM?EH$`2GGxlaSINtE=Xyf<{$VW%-APE@$S!H^}GM7Sp6MY_lwD{ zHnE_e&N%78+B)H3byZ$1P+{(_auR~et3YXwNpRm)F$p0|xNFG8BwQCKVO}lIS6Vi= zRyhg5wdFa_edjB=XFb0R{M8+Q+M=HU{@jOE;IAXJwU}&DEfh^Gf7}QFNCjljl00#o`}EQYI%31Ws6@e@z)u{8U=$u#KZYVpBT@F zdl4~6en#l@2-gCg9U1&9=zRJX*~jV7+WJ8a>R@G17QI@cbG38Sr$eWw_%F~IqD&V< z=YfdM{c3rCrDcmUEzucbOhZU;L}!{0=kNbipJ5UaNM^EUK#88@zd+rQKDe%~R-0Ia z66pc#R6@<1a*~K&!HO*He~G%R3wjSqjG6z%-VuVP{f(|67nHbFvbV8QwLDvCxh18w zL|x0_c+jyIg)3JwHObhHMtmj9=JgEl=Nae={2kS^zoeQhnpgyX^Z-t%QS7RW!cxSS z_zOAW3vBej-*Zh_FG%mXJ;z<(@4AS;d9^%WY594b_)T8_23v#66}y@_xxF4l9U zpzyi!y_4_-(|(W%6w8F}rkbj1ST-)A9!z7Ds)b^T8$BbFiGp}1i?`5X6~tRJ^U7dU z)(00;*0JR+YD_2Kd=gz+W)_Qnz^HD~4`_@Q{b1%5?hnf;#FdOECzoo!8Q1e<svSdC_jr&3leFo*-nrw>|dk+m%9Jv>VjxboSzE2BfvZZJ9YY}LkFd=@JH8?NMA0ss zQ`U(d?Y=CXDck+n&l{LpXjfM21>Cs}*CS@WA#nJ`)BGj7G{R1Mjb|PvLEmz- z9V-?yxGPB0OeeCsr9oysFu0K5(35m>Qow(}Bl9WE2{K2LucxNX(Mh^KKco4TbURVQ z9%s~^oy#_D$al;=AQybns<&@RPRr`;)u(Mbe=I2P#9j(kDyCG+6y(zl?ZL=$V{!KT-i)H zy$-7aQ=E28> z%HpFm8MYB=R$VB`u^PdvPO5)gkyZ6VpxIH;EcEc!M(-GnbrozW!d2MPRZb^eJ5Li5 zY$nGtzn77;9yxo6GO9-twRODI4>=4fm$O#$kU5VT0Ys5BuYF!z%XXBad^`%TVSR6G z^|{WLp+UfZ*RvE!X*-;Vbvgr%Gnxn2F;BW^H@5Yq5nirU>#r$w3wcd>G$JjM=pA$=xSSOM|E!n!r0$N@n31{1^ zONQpv84fwJ162cy4ci*1Y)PC2>zdRJS!2WbQ(`9auvIxWPw$ML`|#dj$uxP zJp8bSuq6y|Ms3H;4_uF%TOCCjAl+K4f5Z8Z-IP1v1AQ|ajrGlIkBU=al`sI* z*H^qwGzkbGRHctMr&^NLqem8wXcLq_zUPR1Mf1VJXBtB#!s&+aM*f|jPUWL|EGSki zJB6pHf3;0LfLosG<|pfM@Jq|xv-2ZyOO?<`VdRp0vP z*C>QFr?=)RZ<%+|-uhaR3DVzUgys@#exe@JJaWUkoc8Ln`S{f3AmdjXzv;3xzm~t{ z#BhLXR-KuxbjEysaR@=J-o6#(V}ivWTHtP0>8pTWm_odNjxZy3$I0L)hanC~kB2%fJh zfV=Nu2-^(6!7Jpp6M(r20CRao0Kwr^1@NP5>GxIxaIXN&3czdyfH|}xfZ)!m0{HcB z5vU&@)_VG!0376FesH)XEAv@J0KsEb1#r*%dFy}y*!^KX?iYal6#(YKiU5KGs|w&9 z!ofZR@R?tO#JvKrw*tU?R}nz)TsZ*Nra7EM*umAr4PTp$UTf1FNTT-OIx4`JpD2Id zhx$bA!An%_q*41G>!eZpZgp~ZrIY3$vQ9$n!97$3@Ys`+(3%0bQ)t>H0J|yx%+(V| z85})T06VS+H`f_}pB{kP=LKNC0>HdE5kTIod5kOYuXuf59??L=v`wYO9{|T(U0oDHo{#D%oz|?AzupC7+^tUT zu5{8|A=XJ~?YY%X`Y1p00Ic~21MtP~GwHhoU{?iz`9R_*g9oJAgYSI|pVxH;;GXv! z4y_5mdM{ZGI> zb_>An3V`FQ0FGbSgGW9J>TfUrZ~4Ru=s*B=RRCB$*f@kx4z}8Zryc-_*BO9!d|W(7 z0Ol(IPN??agoQo$x^|as2H@(iu-VQDz+45unks-b3jusZqRv(Wu;X$m-$yb!>< z-wJ>m48WuR&brzq0J|yxPO1VpsRw}10^m9WF#l!nIWGY76##3i0M;%9@YqLrYnuVM z=?Om03BX(hfYmyUvk*$1Rw?n}z4TzK0eDI?Ix7IP6#!QCGy-_Z!XA9W1FpQs0Q~e)0PGfk-4y^<)ieU=Dr%~Mf8`(P_YDT% z%9{YNO8|CN09c*V2;gN4dvN(BOP~V-aNB)ww|N1WuK@V7DjodULI5AR1{`cN0H4!Z zm=l1x3V_{76~gXd9;l-6-uH+S48)uF@o`olW-B0W?f`Lf4-h-9q8E?jS=*jp_mBc( z_?RD55-AyF*r9Lf0C7tX5Vk)ZFc3e}K=up7{tAd&J3!pp1H_Ie;f?zY#I6s+o%agF z-U^7@IzZgk1H`Ys00QE9w6@4 zX1CQqeD$X=xmkgjt$?_r1H>IYK)5cXLuvVczJp#I7khyCrqFr7 zKs^2<#<;;tSb z9=eN}e7r8Yc-#G=3qIxt>m^-$tpmi@dVqLDi~WFs_~17Iv0oteS3um|0pji+Ain!) z*#ABQaq!d3$Xi}_I4-f|*<-KhN;$sgmra6I_ ztANGCRn}{9qAl)@XmT z1H?CbfVlEb@e2d-gSVq;?H35@q82RYTOA<2)dPg}VxNKd==-#f2m~=u1&D8VfcSO~ z5D#3#q;lMcf&9n2pt9Wpq4Ok>@qMQQ#CLjt_}u}tv>Ob>4}T1;6Y&RKR6yL{0pk81 zAg-2(M&KU3xcpK&G%pZk=w74!UmYO+s|Sef{|q{}8Hi6^&c``{n5*<+e+P*DJwW{O zHW0AYK-~C6*8QwN%vL}=&;jCs9w5FT_4)Cd2J#NcSp?of7e)AMqy1n9hzEOsxcDYO z5I+lu-M29iB50wD3W)D^fcS0?5dZcqcENoHV*YAC5KRqTR6sn`0pg(^AZ``QAt;(& zJSyQ}w?LF((T(=^IzW7{2Z-Gt6I~dHJ-?tAy98oar5E4t0P+1EAg=iU?_FmguD%EX zbY39lDX0S_uoG#JK>Ky zZoBQ}KW3raZPr<{8#Qk~`!sCs^#CZ3(lpvX?Evu89surm5@vL^0Q`6-0L}tHc_yaO{#gfrpLGBL z;}6?yVf^9pmK+S}shM0oBrdDE_zwExApBtYI0$!)-uqh^{6;!Jmf?aS{oFec+&n+; z@!E|yL%aBi%5zYS_9Nw6xD+1gc#Cd7T6Fu-@)o{%dQ4Vpd8hPq#r5@zqT|0PUvNtK zrQOQ6{c1>*^2?6fKCVaqg=t=t3gOTI@%Dbwt2fF&J9`AqUt-L>@_rI+< z&Un8#F4t&3*75#hJ>LJ8-k;R_*WRQ|*t}mv1~=M|cf9|2kN4mI?<`BR%v`GXJ<6fc z{&jpYRmXqb@gg{W!fuN+o+xh#$NlmxPABmIXhO7c^pX`m#NXJ<`QEp?uW?oTHx(Fx zVDep~A=c**9K=M>gcMtf`BC~$In_!0Xijv?#z0nv1rbmGR>Na_2wqv?1XpUUbfs?a zRS-~P#|{PW&^h+!=rFyC(e z$n-epC>V~QOWp+RKF^l_tuI{rpPUUOt zesEJ3_ss>F|10nBa|8u9WbuF>k9!yZP6ENpSll-+V}3DHe55rHoQ=hOKbSVp4BhGt z1pi|3fcqCeIh0>nGXTNGSlsvXWw(Iguc!7va3K~Cn0qk)KAg`ML2wZIZT6Ge_WaX7 zJ1lbHr0qw$e!F`G`v+?#xC0AlUM=9G|8ZFUQfn=E`-=O1KI=bNl7n_XIP;48=BUdb zV@Xcg{ot!ByJPWdzmGXZzEvaKvgBKyE#Y5kY`fd@uYZOL2uX5MGN5l?<=ZhyvNo}M zx5jU6-TPvE@^pQ>V&aBju&ZrS|pqI}Z1+x7yb`_T-M>V!rMNG;3pkO*|Qe26oI+U26a5ffhyQ?0; zA@dgyUD|xlQSB|Kc4ir1dwAE?LzbP3psN=sm34xccPM-qX3 zR!1W_5_Y6W-Tdo6<20^Hf`%P}gkKiqtE@Bxg66=I3=q%%HJb0NQ6kyXhI!5w@~vyL zAabuP4?qY}JVvB#+s-&y+6u*ARx*51vs#ItLb6Cg!5TbWDIs9ThzOc?Iie<`2H~G| z3&DK4E!L@+#D5+(EWnD-Q>>YCa&aXaOGSjRgigfYZ5tvVNDm>R8j@K(7UU6PN^WXt z%G0u9G5If`s#vjD$>0=0c8DRFMg9*|DvKJksAR>#<&R!GkdHN=>Lb)V-~S2ExkB6> zlyyS$A5$-et%yz)E-RCPWMpVyPnWo?jjj-v2b~JqY5v`}Q*Nvh02|Ut#?xXx#Yyv> zX*Gu0rGCv(XH-k=WN@B-k z5@NgwF(z=8o^gzsNt`^;sL{kYhRMu0k!YJSUdOA3h#DV6?(hG7Yt^p3&pFKz$>ZKj zH+0pm$Evly^{wx?heZ)@2 zsW8!r(7~j9_szJR3IaiTiplz1Hm};-6GneQXm=;0ClSSHyC!m3yYG$dR*^WYe~|;F zV|8-CP>3NkDU9i5luI4!_}UI~9*E@Fiqp?K(>}_x6db#IJ84u*OR{N7bQxOVY0^~} z&`1@VsBL0^Tjz1r&RW}=8Jh)C0#`_ zC7MT)DMknKJ~PXG#v0oR45)Pcw&*GD(m(&F;;MI$#h6!73#xqbL6j0%NDQTx+HzSmOFeImJpY)sI3A-E5T+}Q4`O~R+}=9G1roP9X~ zy3I1ZvOgu}t{N91H&HvhoRw+!omAZQK706ec=;U21q`jRlUE%01_ot&V|_zW@-cE~ zPOETFlUSPSq3QdGZK=;fb}2M5l1$Jk}3)uGFQN`Hr4rYqCX4NZ9kQHQ=QPUx0T zJ=Gm#mhr?+?Lg~&(lbqZP1 z7S}G8zVS8&X$vlJHR}lBio_P$0OOKFyc;Yz7I1(IY4k-AY|+IvNeW<+g$v2z6?!is z7sdW|V3|qz`|oB&3tI<_Gk!%@UFUOcr}-oqTrmcw1)oz;21j&8Vrqi9jw7RatzbEFQ=#galLsAS{OG8IKSm%tA_>-Q{SCKhd^DAiv3feL>CTL59Rpk$4;q;uZ zIx6R@j;qudv<$*uItg&L5@4c;y$J>8(f+BhjmF;M@Fhc%w^9I#|7qrP%l}MyuB=v` z3!D@WtC!~zcJ!O5&5F*ssu{mp0`MLIWIZIsT-d#dVJaDiY?pK@-}{Z9nV_~!`P2_{~DK^g)Y zaXxNP5R9Q?g0VAz@nV9&tZz{(%wM-yJsyx)vWI^N{$vSEKq7#IVa7o=QizW`$PcS$ z5{41ff$mQ)MiP!BJW`vg{MZ}+PGWuH6pBtbfkoTvzBOAPm4Xlhf8JxClD>);SKEs)EaaX%Ai-lzia@EiwM9UWj-+QJLI2k&r^$YIe1HyeOTo z6b2b9#CH^>%W)-z0RoEnX$19D9ih@^>S(EDIV!d6fPhjkO{jBs10g>pxUPIH)}(Qc z_rNs3n({L&l1aw#)Z~XHJ~p5zEaj<7@yVu2F+re|qr)RZSwo?_<@chMBil6K(JV3E zI`hSpr-ONw4GXv?A98N7d&q=hk*ILLzSV@=hS*f2olMITma|Nlz?2lu4IU#gy(p-$ zR8cf;i_kQ5S%hptn9Q-wim|W$M%qJ43EddGw4=OM?Hl+<-^ioXoKMq$;k@F%iP~kr z09Fm2g;u5(yHGhhnde00CS3II&d2ZFo-O?z;pgFd<3UQVe~&?FBJF#pB~0qPH9etV z>}n`V5e=0i@{Uku*7x-E?`2kQ6xg=_gMffFMQ@yz{6-qjZqGOix1UNdp&ro8U=h-c z^fG2A%`?ElLo(=TZVb-(ScEh)>d+OhTjWKD|GCLJkqJ*PA16y+U#z~Eky_TiDAaKz z_~9NxZ7;RYHZ>c(e_LoIr<#GKN0Z^h;m*_e#dW*WAQt)8 zw+29@h7DY|FkfnG%nN*&OE}(@`=?LO z+BclEl)b+rttq}T6DK{;*x52iv3Zh78W93wkHp{fnWJx_^03#uBAe#{$CfrIgLq@#@|NJHDc~(T>;j zHrer&z0Dkz@_pQn*R!zo`$)>l){D2Ny)AZfN7~En*3lHDUC&^YQqbCt>@IkzJ#$am z>)FY@X|Hc5^GZs-6i%ZN`*Y67wg27B;tPNLXRoIaX-8CQ#0ZdJU`%ijAz)8)J9kNT&6hJLwRRFG3T-wbv))U#j-n5y?o_WSMG zZ#Sss^S?j+Z+{b!OVQ7{w)|X9SwkB8|9$`Oa7W5(bzRTs&hZc3GCq9AC4x@z;QfF0 ze~&4{eU@)7Xw5$KyA5m}7xve5I{YMadjoiOj;Ztfy4`C$V9RS%!|+aE0*AlOB0&d9 zX-%!p#~y1;gM|Fp^wVbdms^yndL+H5zc$>KZ5A9@b8hkij-n2G^t*Fz!omdx?`x3l zzN1=A5_;xB9ssiVci%V`1uZ^XP3kU&)@oPjmA#4HhT8N*wE5stvDi z$bycSLI!mFY6_jv3G2DL%pe|EW)LP977*wB*#c4${paEp&>B z3pvq>Gt_b%1LNWfaWRyf-tZ)$Rxl^zl~jyaYp+`icQ(*F0)A1LN%%E`J3~nks_=7u z*M1&fYe=_|{QoNDFn-Z~s<}^M{#oNSR@(4LxZr${63E~$cABr1c}pb&dTZKKQO4`+ zqW_y#?7s`dNr_Zq{SQWmEkjGgUuQwJ@Wx5iYebMu`8=QMZ_GOv=?ekj-Ec5yFUZTI z?S*F6shO4<+I#E}78P_LDms8T`Fe^r%^OY7u6CS8R+O962OkLLf!<)dr?scE#WcBJ zZsqHCbFR`6piF;ve|;xwZ>ek#EL@C(Q2KTG+I)WhegpdYe4zsR48=Ca^92XG1QP-M z+(cWv`MPtHv;z8qfWFWkuYgXWWPq}9MX|qOF^AOtT^@uhVS(1R0F`DDa zJ~E2(3CERnwQkQN1&?$awVCpFMR(r@?|wnuS$^l#37tnHoAHvNGs}#Los~$8H(l79 zM|v5Q{Xpi7BZQ+lDfUg*xv+`RC^sR*YGKfdINFLM#2m2ckak~~kEHy$zZ>t~o9;q- z>cW237DqDRxdEYNZGKYD$w|cz^=6R%bYPL5dLgTt=_o(@mf3Ps_nuTg14jCmNuyM4 z8g(S>n=I3jR(Wb%oQr%lDPQwzv-Dy^Z?U+XQAarBGuI+j4KeUg`j)~iqVvI3W|PQQ zpgp4VlWkQbMd}mlmtri#1sLr~yu-V}jb>x*-OjkZ2q5%QH+G|Fz-C6eVNN%E!nzSW zZr0bEYPHAc!)R0a#-&YpD(}!#aL!q*H`QRve`!<2#L}kBl_&Np`0<=nYf8YWY%8FA z7Xz6PD_=Y}xm3r6b746;IqBTwG9BT+Urn{HDUH(^Yp;!SLy?+m;Ze@x9)QQ~?Vk)H z1d#FKDx0>UEuAUzIbt9uYnFq<(OhjHP?tvdSkZ(fo?J99q=OV&H~wfGWXVGD^x=)N z8SpbWD$Nd&0_vSJ+0G++>!~E*lF&yHH#YQ08iZuT$vP;R_~D;7$c%#I(mJ@mzqaUI z+w0})NHWyla*X-Zy5^pFh@{U|BmyhjBYg|1CH;jY*DzJ;Co>nnhq+ z$k#6?taXiSZb4Rp6y@jdM?PyX6Pw8uzHw@Ey&<`wXnV_k2SWZ zGnbF$>)MsB^6ds1W@kP&Fz`Tb3B z{;Hdsta}iC>)xi$$-)x4=jqeY%tQBr-`9qr?k&=%dAgVP_w_f4Z{!>G?|wuE)`T+* zSq#SR&Nqsva@-{D%*wmA*TrupprkX7d`+)2U>=}pR6vBU6fW=N%wY%Cc#F~?6;@=wBl4>9DTlzrlJ=UUDsp~%7-`Ki~ zDQ;`Rml6PTm5T%*_{o9aL)5V%0M)9lDDDPB>JQp--Vl~^v~Sw2_aXm{P(n{CAIMj5 zz3Yq!-i>w*4wB_>PKR}j(0G516aaLoz~Sr!J;St)Cnw8z@8 zx9@E95!nzZjNh5cAn8{cM_7nAMPZv2Ns(0Jy2wRqK=6g-mY?$@DV7qlM-@5qC4@*c znILo=DRRM`5KSSnlrAem%hVb#dj2uM~Znbqpq z?pf+0$-%>smIgyYwWTx6))LX({2e8H2N`UmODMyHS7Qmikd*GKAxja`DVe0Zp}&sh zX;zxz%YX5jTgK5ZHh_(5AY0uHk}EgBkWR`M_f}o@g!oOyL6?IUWxdNSL zywSsWu7eAyRyTI|T#9LR~c!1@ip9hOf z^wF{MPFCuqak8K@JL|nwtapR>3EZz)Hg7W?XDZP;spY-(0W2AM5*?1H zP0KM_&G>*C-Y|KxSFMjB!Ywb*fG7imYzNzF?|UntYIM&-Uz=nk&X^&!?7J@@ZdK=a5!>BdFtVDqS}(&uL-L&&=TJ=Bj1}?p21F3HXC_;s zW)GGTt4wyP$p{NK(!I-=*5=5x#+H-+w}o$S7CqSJ;F%a&c62M;=i?K9C=;w)=Ui3?|eNBllX8}uAcR>?w+Z0KLCv?SL?V@r3*Q3IxD+I$IWMDuhfzKs#odAe%19lvhk1T!^xJjFj(s(KP$V#PN;&Y z@I9Od&c<+1K(sJ~gY9PrPZ{#ebqSM4O$p7m8OLd&#i&C@2m4d!5~c={3_>21}?r49Km ze&{%F*E{X|?AGbv{slOOzVNXK55AzSgyU|q2>B?1CSbt!M7StHx~T(= zf)`4eD$ti-NXjp=6ubXvvv!Vl5TEULbPkx~bLM;~_E-K50;o*4EO)$MUF6s9y@TMh znjrP;(|8v!Wh#CgN03uQLm5mHNKhp(xaa#Sg6JUEMg%w-5#VT>$sB3ZymDByqaN@@ zGX3yaHuh+1WFo8)9orDV2@paa@H#4B9l#fW_|C3poxsfpbaH6?qP5$tPmPxN#%Pi#QQD znf9amBR9fcL(=`kRNQH>-bt)!L?=Mq3@BB*>8=^%%Uz6a8Sy4qg~x(Cku>kL6YSl3 zG?==VJnCK(R$@!*-jqdW3wvCYrT}U&lXD}uSXk#PCu%@zv5>7+=mZAQU0kXI zH<*LFf6$7KVqvLR3}v1|2b5!ZyJ!WFwSb4gIyNi z7+;%>VAm85tS{6T$ea@nfa9h{zZcAm6;WyOY0S{+b7e&5%PoRdC<~54j*Zz6vR=mq zpet>DPO4`!M+$Hr-VI;9D~d)$rjQIE*ukK)p2A>Cs+VtZEYR-+PseB zfnL;+5Y~+Y78T=9{`+J$wVVU?19dkuZPAKF>DY$1Xj^yQc5KC>n)W-#dZYW>Y@b=V z!L^_44%j-%0b9rC*tYPF?BcKoe7S7_uX@>reKrq19YabPE6JJbi@D>z&^SgkyT6{* z7BqYfU$?S(nZ%rSWQzE6knvgj`D2WyjfYm;v1ceV_-R$U_L9TxndyG}SUGVxelM^w z)Nfx96%pvkU!3L8j?1Cr7~XwdRfaVNEMe<*zCtVbuhQ?pTX+Dkf;NsSnfl!q`c*Wj z6PABNAq5pj5n{QOTwH~TNQ-3mvHlcWpzJXuthHl(SiJoxCNL$oi}ov}~K*3JAr~gg?Wko2PzT;j|%7 z9vpbY>ZW+Ti5m@80e5e0^U}1RQW2cmNju};5h4_K4aZJi;%vee4ernHm1XA-MV7 zTaTIdNc?p#Vc6bD)Rc*Xd0P-ZlI@+zQphbBb@P4tk)&z@cO=j%k$0qAY>Bdy6;Gt0 z69}!5hH?-XEA3s6o4keE>(*-N(y zqzHIxPJiv&OB{8_%)Kmc8hKh1$rHl;3gii4xzY?op7@OhAXg80j+thF24I>2nnJGY zNdDV&L|8agM|0KXXs)^(k<_1~>xkv10U(uMJ|Jrkn8z8C_y3r{eRi45>mz|BQS^=l zwnfjpuyzidC6aH4PU(0mbV{Q589^jJ2Qfsy+jIFTG@6N=ZmjFg(tJv!db11v1Na0YTpT72#7 z?)x_Ovps#agcpfgqKd4{+4#6Tc(#08ctMp!q<0nX`j)i~oY_xxNx>scn#G##A8w4a zl{H@XI`_4$GT0XYMIHA9A`wGR;32ZjrSz$e*A>z7LFMX7lR$c$x1a(^K7K0-1xeBg zZ(%ydX|xdt$&{!GBYlKFYxJz2y?8_4B4+rW=oC-DVRkWkoZaKY?9_&b`&0HfJN`V5 zJK=O7@G(rKi38aGnvPlp;z*R4r`4pszdg$hsPRUVlJmJbFJh@56RORQnU>4K4~C$L*-IQpb^C%ClrRX%8O*`}`jN$mCky(4$CxYw zOcL$fXx6YNb36w+CTd_q(I&8ghOA&o*2I(%npL>6E~kAc?pE4|2n<8_n8YT*X6>h`^&`w6v_0TwX^1p6H8V4A;O~KC=!??G)Sk{?|BG@ zes7eN$nPA?&~ZDMq2n1~wvOi@Sn0SEf}`UF7#DS1C1D9RI2_?7$}H;tD3Hk&9DMUlHE3>GW@nQ>jr#utxZ9sGqTKn@8u?=v2mip99S@6?h_cG{!v>iVL#La#p@g;6J-Qf| z5l($oUpk7Ghq%I_CAC#x^>=Lnxveg&9o~&~>nBC9vDNu8!YHb8=y}15idS4CYgNh{ za0y~ptuK?NIhX;FZU^N}`eKkNmOL6;4K6==Gzb(+9(A68iZ+;-AT2C;6dez)gxl4A zcB7id%CCu3A9B)r3meq{J3uz5X~fc+ei>9X8nljy8tnqx#)7SsF{3w$Y#}8}Kh0#T?5Mur$CI`O|?81@y@jMc5fBaG-{P(5#^i>$jo8GWE zHgC!UbUbfg4jdSp2FI`E2Ir0=6VeZY+lYsqxzq?OS&&(AoP~p#1~a)rN=?XTknSlm zUUtieexDWF{V!P&{6%WuH9>{1k1IjLw93~_$-+2f=@UKRHXw2IcfXO8w0 z;5|a;!ZYrYVI7}~bE;cG+-()^USX3SJSzyq7YY?=p4II79WrUbLnd9}mOpN&xrS=J ziVARS@SE()(F|G~&7j2*RxuAvmWsVmM_5L#BP_#8E+Ly*;0K1{b95aUb*GM;(n4wGAwc4=GQkD<(nnAi6O#&g7B40xap4W>3Y*tzi*ivvMZZ%vYR zdMKFdJe6!HKRKem&ZqN_QY5IUTfGOn?kH&HknMNx>tNZyZGM&oo)w;X*No+~d zdQj4Q3(0#DEQvtvSUa*K09@@YN?4eY8Q;I8MNMZi_6JPryr$!(=118XomG7u74AFhy+ARMrF^9+iSm)DP6fKS2R^0iWb#lP6 zako|;cbCSH7$X!t%h}Md1MgmMn?0TAAcY>29PATv_N%}1?mvIe%|A7DDZO?9r{i4Q z4ESGo%_P$d@B%kq=dCQ%XA%kE?rNxNg<#XS)h{Ue^w;VafB>nb4i@iy6V4S`2dSX^ z?fU&GhY%<-QT|bNBh1Sv{=3{D;7!)#hPwA!IjO;E6$!b|pz$*X5c9NcLl6rB!3H0z zyUBGT*XKK_z7se;&Zc3K(v>F(`OYYEoFz~7HuTNF=j-1z+};kDKJ>=_)8GVH2#z{f z{OOx+`e-J=nc~ic5B&0nK8K%w)|m-U964e?XZh~eSQH)!+bLXj7|*fuX$V1nUzbPw%m_a*QIfFF;yir$=NQIZ}h0Qfi6k&AS z&JWXYl83-|xx>l;F;c|P~BD5O32*+2gEU!u>tTwVA>`pkuh9PWrHqBeV@LelZM45a@akY5fz@gO=d=2ZX1rV6epY-$Yzuy|Y{f55V zE$>l$G#szjmAG5p6~mE3L1LwTp3IE~qAst-xJKN-(kLhD4{efx&w^MKi+( zA3&b9IW{P{Zg1Q0nBkF3#3GJpBR2lHnIAIDpNfN*0lr}8e53Bp6hxAy*XnrPzCNb% zMR~}>Iu(Y#RAjL6XVuDa$3h0uJ+`$7j)k#noe(%V@`^d}8K&_{aNonh-$vtZ-=>u+ z3_4=5yV;GGL3z(zvc(5{gk}!G*xk_tW8-Z-e~B**U_5y_lW)QdE1+)%BZG0jdUhDb zLhfN$Yr!8$p>ehSJpmPLueSI!4SMd@M}5u$vlL!VE-}Qu#ej1~1MPCQhJZEDY&G3u zyi_s@kZ-H^oM5=+K;w3wju(hSk(j_-1TWiG!E*qbTof*XW~mz(upb7^kQ*4A#YIxI zy04kM8_=|_g|NP6l52zsbJCwYT+Sb1V+cJxD;lqi51@(YLVA!3eIUrAD3|VBVqRt3 z*PHzon@kZjO+eEPKY((1A2jfz7-cN1J>t)khk^8DAMe@|1L+ih2_W5Pdyl77pdCQz zK9klXn6?`Ry(f_cXZzBpwH@-F#J59?3q{dlhkdC<<^cQFy<3YN)!UlJAxaOXJ|zqX zAZyN_;tzw_bxVb723A9k#dc%&*m&_>)q|DH;wsLB5>JrWga#TrqZHDFDBE=OvwQnU zvTXD#VaYTs;jVuB@739T}6wxv@ z!0_+3ZklB%l&L#8`deUH61Ua~hM#QYwAm7u5Ph>@)#zGda@AVw`0te@sDu{a0I z%*3sTQC7{)fpuo}Y{Vz0&r5-|Iyx;5`RH`o)qNK%ix$v`u_q(Yu&Q~iy#S3+HxK9i z6G6i&shm+hJNMPn6LG~vbg>y}sdvjgH2dtJ0SJ^g9C9D1141SDRr zbI>uSDF)7Knu>8|!AYbQ_QQ6Ubl<+U2!;J{I5$WQy)sd~Vx|1d+{Y{DI&h=Ue(hl}as#2wRG51!mk3|rK<7ZXCir~L5aiSr}+{ehY(-L8+d8`a# zI<1Y~tMHkj<=_9(lp9*!6W*VR#L6aNin))T_PP*dan21=^wR6`4T#WtLqqIG;wU9q zctWypFN@64wO`SS;zM`7_H#|}oz6P-C_Z}YZ{3_}1wi1%PnVfHuij^qXXb=I9E^OF z?9u9J`p)7(WT`}JPKx+x$xo&rzfNu=>D$5noSnZWExHHy=h^=K2=wVby6DNB*gGw(iG{iQoLTEb=pMgSTQiJ7MrfgNSmaA&|`d+_~*L) z?@{j^tE8RWtR8WXe{^p~_Y_hVq+e-n<|T_i!kh;uF-=}=&?!l*HCX@nh;Z)i$fo5G z6ksA`%zglE&`Qv<%8u2r%8L;WF#H39c`<|)Pz=SjK^74*umaRfi@ip3QH#Mo>9q;H z&#^M$^lAvPh@!*}Y4x%L4JkKXu22XI-NI533l`F{BoW_57~Uc76d&@XhU+d^TVeQ; zajan+>`()mQHtZ`2?ZTl31WG|+IG2wq$6n$z(8Wr>=lS&gkgns=fw&&4EIlrDL@y05lerp;=yu@l`ejYrzKRa$ZdlzH-mjBGyu5 zf7m$?POQU7>xC1gq=Q~aa}FFgYxX&?iW*e zA&I}3fyZ{X@`@IFxkMq^-Ls7ZH+km?Y!AoDv%R?9ShXp#0&;oLM4PBNG00dpku9DH zt&xdxZYfc3m46bA<`stBB084ug-D%q5mkfOB0F}QrR_U%zCq=u*t|Qq=daZesx^zhJ zlJ`Korq%$T?)uxOCvQk~XIkiqzyT#DGadE}+M6>*8qvBAI04%rFw zy+ItgLYBhs&642m(%T@@M~OJ#n%)S;PvJAir&zGIp;&i3bZ_sojrs`RyR9 zM;<8#W~qFLPxmMwy%HtgeCN*)gbHAer&On0uEC9~YtZXb(%{#>(8RUc8vOWhgZbDV zGc0%i!`5nd!)sA8sJ9*M(2ue1f69tjk#b~$LaY}{uI@?2G!3K3Upm)pmH(dP7WmP1 zZ)p~P89EXQOT@MBB`Ep0JzDuIH_vuLO!pGR~hH%{@pstzgx%cSTuEC?w2~A$xfNBuhQ2g80m;d$-OQ>x~Gp< z@R-dH(xEcvin&|e6A7cvtHb0FI^|9*1sm*g=?Lis%jX&44EZ=xj}kuh#{q?$iZ=4_ z6k0<0Z+{J)m0MgNBXu}|-SV6BM_9Vi;ucGqSV4{8Ea|QdGE&(K-Y}b)4SfDlD&u0$SmR0;HlIf2%iN#!|PT;nhBO1lGY;m!#YWspZDqdMf1%v6R zxzfyB6@@R*xy2nilMSUGeJ zRuVe9Y;^?{KKl*k8}m!S8YQAHz8}4Q`B3Gw+(1f(1<-m-?9Ro;?om`X|0H9gb1#HX}Ay@7vN}Iz+H;vqU=$<94)Gmqv8v79T_qo zVAeJfZ7}QnG`*pCrz4uxMN|<}B zY~05ANB`)+^tlwJX-NF$KQ;-FkmH^nLhI0G9tJlhNW#-^Z$Bjw^Yr~N4jlKnLSQes zJZ|fEY2xVTzDz6`_KoW5tgil*UF{C8&gkl2*ww}B?CmwWaz9s+>Q%fPvZH@&mud}8 z>*{;$YOTSxuD;u@h6X#j^3E?~7P3DqA?x7Vc*gql7EY`iZ{ozh{zgvho3G=*%>&@w3Z(ma7xj2COJLv7*Mxvscxi%w4dF}8mm9M|deb;Xh6 zYxXg~esX~4S-=O2XX;MlV0e0*^zh;77NX4(MwVAgWdy`!aGjCJ(My?D{$tLl2 zcB$5&&FIZ`wbr2K=IA$=d2&=aZc30j`lSk$Sl*JStdpPPZR^)xabjKh3r?&D_j6+3 z{bNq-Q}5-(T7Neu*62IG646QIq@j5&qnZP6L`4*`N9TLLg`K)w~ zghp#u3mT9&_HD?U`$0FJx()*AjU5a8WVxS~jQ2&zPD{r6 zEmQEL5I{NRxI!5MK40>60 z?4vhxV&D1}vuU6B1}E0?S2?i;zf{eymUa1I{9%-0T4X~B+3w)?3`fXEir7X#S1)0T z@fWhh>zqJW*N{h|Rcs`hPVoQen-5&uZ|v=lU59AckO{DufvzSs8vGyWSXL|yu3Deo zsg;}I@lri(J$$!cjt#687=B;Zh>JbQKbS)JM6I!TJ@HGGHwmlMtY0&oE7a5E-@;OfIBcI{KI`LPWSbsmki4Ep2 zII)@d@0{4E@8>iA$3NE2tB)iK6HY8I{`7ynC|kI3@&@#dck~YT*KI>{&|k3hv?M9E z35|7{7T*(3GenYa5haY)l?Ja1%p_Rs5V+BM(iss7Ua2p@vG^DERd&B;k|h3Mf>)L2gdMbVKJ5W9{m)-r5k}5h?61utIq}f zD5hSSx2`RYHuoM>xVkl5jvwl6$k&y3_73&7fMgqNXqfmKs2te%^2RZ)-1mV4bm>|8 ztp`%s0GB+_@CP>KTMqR%LSAGvBZJ0u`;}m7Q#o@bB9-3G^tN<&HP;+zo)>us6e}{l z=-+Fc=zAN)9XI59k+;SU@>a&@$Pu>5W^pMz@-5_$e&<#QG58}oJG_4{%=+~DXP4(h($`5w?A^L$rAhP+voY=YbISI};lYNd0AI@!|OBmn^ z^@XGhnG4(KY;@K2{hPGpu&Cv z9rhC_v7bPT*VCtP8@581Z_jPPJ#M7<&ED)C`4Ay~+{kcj=sPCDv7zCK)v6mt2(g?K zGKSdD6Fpj)c|HLn3?2VJ#G}WZ*pAZKiIwPV8!`9uTQ28cB;ie%{u)u@-BiwAi6=Cn zPh2{Z_clvB=6_i!{_&;Zx?C7n$zvc%Q3`I;=R)=qc?rti-Y|=0^SJH5fZxU2^vk~&Q_ArEqqTkiS z{GpRK_weP=$(=npKR~P3T-Dr}=bU7eKjORVxrtTeKp^(|$<_-$o1*>tNn$&G!chDt z`_24p(*ox3&5H2m1NMy%%4l*H#*}ygD~ekBaE??yW>2yMwwG*&isjy9?|e89J;ekw zZdcwXHxqUFJ{e_n^1FFpRKK0GeWfe!%Gtlt$vbj3uyk^7PGw7-+>;Z2u9LUsq!!Z2 zU3qWLPTrj3`>iW?<`kyX$uj(Q&(=!dy4>UQ`r*0HfeuoGnYU5 z{sTaCQ<>hXD|xumB95jv#p8if!ZSNWOsyg6V>X{tl^LpX@d3A=H}b`rJvu52kHPGK z3Fzb}tmL8@O9Y^0HW;2@$cAc9!0I1@$^3s^c!9C7886xwNI0x#GaInxIhN#G@|;t7 zo{3ayM^t>_ajbkey`{`8A+#$@uoHzDsYx%+VAF$G`;)?8} zYg;%qAn3!j2iP%ZAm_F6+?mRH+j9_WLD|ZCwnX8X3HPZZd24^g`vW*nxBgM|t}W^? zfJJUlcbkD<9*Ats$Kbs4aodVGfVA<%hU*gyPV3_zU=uMINS@HnE4#)2+XSZ}L)hc7 z4eWHeu9L}*6V#*ScYCZH?^oC{Xe9hO~@0Eu&>0y@xze#q$(Q2}+ zt~?l#2A}=8huj5Su2=3mE_ZP_qj9h9U#^k+bxD0W#VF%$?~e2Ge=M@S78V%Z%Xa1& z#VkUaA1@Zx{VZ;Q9&SMpTP-w#Jb5AeP{Yy%-Gqzi@k{|m3IIPh*}}2>)sNwjnj~WW z{CaErMTri&1&ft~V-x2-@_Slbs$EE=AetP}>R1J9h1=kxDS!X&?`6dxZf4LOeKFTJ zKK1GUYl0!{|xJW~vm@Jz=pu$T9*N^R-55ye~AbNTOboan8pJe?;u9P{vw?$1)p!7+s>D1w`D z4pqkVUMr$y3$$zq=vWtQ;-xe1BWfl-Fs=s}BR35Rh<(AMoQo}sj%Weo20#uW$nwdx z7!a$O6R?7qpcp{0hZhwZzrD}gU8c}>MHW@LS_pyS?Hgqgx3qRu5DEExXaXl~#p|GF9WHdDyeyfidYcnTtHU#t#z++-Bm~EmkgR{zsDq}EcWP6y= zAIwr}s8RSYV^w;HDiSH9A;w*@CBA_82kVevS&=a%ZS17G4Y}=t#;W~xTEZc3+R1_a zkQSn-C6dbB9pd!oQ`z`(Nb|mWmTF;#V+|FRFvbk9Csv9Q)(DF{OSO(?7&dJuOSRaa@1G(y&$tqF72J=~vwn#wEv)FRuh`Z~(BTTLXPUF-p8Lz$*y&}orc^;Te1 z#jOJc<(h63lMF{LwO19ByJ=vCwL!t?Lg-cA_u!Z4dBaLB@yIn~5@s-Isf4{vNb`VV zPJ@(`M+HX>*?g)}cb;x_KbiI?J1W;pUAM|!_|W94@0l8 zK&T=k;Vq=3mcu#(x`zDu<%b7d7Stw4L)|3!M!mqMg>U(E)fo?hO3P2alPI$8`>B># z4We2}^+9;GFUlck@C>3+{>IPDmd!YbDj*QhGl-^9mB~mnfUiyC_FVu|5%QsD1|QHz zeQQE)N3kXZ6sFzJQSi$9NA83{{FMgQR~qVW-&bDVZ(R!VRo`XeHG1j`31e7#^gF#u zsl5fC9ZaPmm_5N;BS;&978M2l1p>^x17zSZSU`Hj^r+V01dfMD8m_G}R4Lo^^iH%AcDa=~_${>6f^6UZ!G zv?O>03u&2>M=Bv40z$lDx)%W8Nw(Q}#IA~sy8CCyHi|dTgOPDV+AWhEOTAAFldez2F;OB%X4&H6|4r7`+XkH{OfD8&T>@s&a}ph zK`W!GIw}>bj;d3oqj<26iepyQLDi?y?=uy-#P9PkT{UNimM=CGFVmRRh6orlkZ#O>ZRYgVt&m#&UtrTsN$H?{{N z-_NDq|2F~=8N-4pb|aiD^>%<=4Zyn(}}4@0z*;q#&Z~E zf1X$e{aEaG#A7r*eH$1M1(#gOePwzSaXQqW(d0BBPYGCrtUJX;DvhV~M)5B53ZLLv z0|duTDXg_>lc7n$OYDrWGU0z1o^2YC>mG>2{J{q1Jj_fI?Y}Pgk29ovjbtbkqy46>B{>Zs=xTkpcgwp z-O0n$aug0vv6dl;gFeEAjLpO=XgYxZ&Wc;PWP(B_iEs@#>$vV{VdAflYIuSiK~Xp1 z6I5^Ecuv1#s|G|He$-GpAh=hJUx=(p*$fPmrwoe&k0K-1yoT#**H#K08(kt3 zBSxi1)UkxIdf2r5NhzQ%o-Kq53zN!8(e(+LsPxa4L@d@8JkOBsurxdLkSaOb?|gX- zoQ$HJ=^;ZjG`R;l(1?w*P zpoBkq9#(_p0FjGDZ{R1DJ^I$X>AELHiRz>kC93hD>vA+*mm_u{2^o^8R0`Wm^>MVM z6&z8V&(L)ws55n(KPx*=M-s`ffzC=)LK%)ElG&ppiDRzPk$Ov4>o`Lq86DT0oxMuO z?%CP(I?kSrSfi7Vdi zV)iVgOtIa=s->0eK?OmhY4ShGFadZ!$UmG~q3K;r39^MIxV3A)ax5j?yRw>1B~~(% zun(i2UNhZWMaBmN)lpLfrp)dDCT2vMeoK~R%Vi4b*2LBUNLCGsh{6~f6N%kPdGlXR zl~!F0#xb11Ia3ivB)gcZNvd4){Ao9?X(@$uryB2+xFqq;Z54PL>j~(W0^v9eh{Tup z|B4OdJf9Y#w4msRiV2`3XVK4$Bs-0&cPePk*RE>ZN7O z(`VM^d|;k-RYkv*6-Gun`RnMnN`&jE65%?oa+wTLEn(tmL2@9O)T^B!2KvF&tBjF^ zOocqk~j4&L}|!ay3~2!toc=Co<9#0R0G^Q`RC__cit? z!j*pP)DMo^jh1>IC$w5p7~OMvZMDVXP)T`%4C&IR&*-y$Ic~r77%)YrJ#40KKudko zR3?9NP!1CR2!Fs@$lQvw6Mftej-$~|jz&8L2mxSgtR1EvHZ2H_mPCN;=-=JwZBEMzdr;L4Fa+O>t; z4)A(=6VzXZ1Jn~E4U;<=I^1He>l*_{Kzm=!PED}gf!Qd^4G<;KB23Hw^~Q^rD2Fe!RPJJ z7?e_%9-`SiE5H5-X?nYVuvJ7?fTlqbo+Ca$fm^NefvqEl z{6=}?q2pP3{I{V1-8W_HqdMz3x+*omUnD1)H0JnzG(i6TyT|CxhtjAHhIz-%?*_$8 za#qmt2Ae4+t%$yl$K|GNgTV@^o8`q8&d$sjg=k_XD_d?{H?zDr>)F}H!ONEIX!>uP z@Wz&MGmsMwTXcErLt{#v#*%0hH=N(xDT*#lfe(kJlHGkql9Wfj_$BvSVGZ05fKje- z=&*Xq4dj64ef`$nd*M^$6TW~v*TreYQ4GoKesSfr=WjSBi{`QSmJdEiGd(#Ml2YUa zO??;6a4F4^P~;HhWs<%OS>i>ww4C3;aFjRhm750R5!Xf0zEX6)tE~*G<>WOUZ8`A zkd5WcjCyysl^^|zfC{1M{{B`>90>qXN81f{A&g%#`YGDv`%3FGZnAUoLZ0%R2~6^s zn0LPcpTxuiPiMSO+Re8xkg^CEl0A_Y4<)-1-&+^&7t*5)<}HWnGCjeH=lO6-@#_+( zj;V%L3OA2iE-39{OZJC-Ei|t_gdiV(0fo>Lwt8e%@x*bB={HY}9N_e$8N``du6j;CTh)Nz$`KN|gy{OaG@J_yy?>7L_)OIQF(BC*++MV^{Qw#NaS z@&^YBW$6a}`LR99!&av$NIYKO6O$uG_N=`A77;1s5E(EEX6EOiPUu4R5vUYf1c)%0 z2?Nn0&9A9r&=?-3j#%}qaT=b5VusB<+XoTVQX59Yx*Vlfy7^iz&q%6Phr#yPNHvL+ z%F~#!WjN;@w-C5i=DIfoZVQGO#SI22A4yrhbDiqjLeP043`)T){rloHkktV()V0rpT z!>M4dTNzlsA!EP_rmk-rryN+zg319Un*cZ=%v%O0Y&{AVR;RgIHQxquxTVd;8_a7f zkJs&2Hr}cl>0p!W+h0Q!YJ>#@(T_F1ALtYkGhmZ0G&FZs^H2V*LqXIIt9J=5Apoqx zqXK!bk_#mO@Y@6cjxg^<{YJjts3W^Q+jPW6F)D9QzkYmq#c6rzQT79E3hp4SrrQxV zLi_Yv#Z8vcznTM~T_UzpwxZoeXNq9(%;ioYv(T$Z)ygTn*nVEG%&lyBvi1-pwaZLi zvb`qQWk?SG*GQl-^|>U;8k3Wg&DP}DWNUI_Vq$zkq(x|U0ZNroKa@JQ7xbggS8Z3n z(Uk(q^}Ar`_H;K2bjAtL5E14cn2W5SZeFYAHM}1MK_~7>`L;hviyOOtTaoyfGM_br zzENR-eLKGE#6BtCLK<>=H<0|85C25(hE$;C-@PmIcLQ~1Sy=NYdN(BeEN?#+-VO8? zvhb+yI^|8uzan3?^*PXA*yhrAH6e>Ww-wk%Jz7G+=JIXFo8Dm9qgdJ?Lba1UpnaVA z(@X{8$G%%MO3GDf7~CUM9d-f0JpW#xi6|1a0VGtJjI#O4E;G=QD4Vk+jUOYEi$6;y zpVtwYeN;Bb`RO;XTrH={)m2|DwxpNPh&kDp%as3E$t*v#sCR63qR zB$bXk38d2Tg5Dy>?M9b$yd2?F*RSfWv+GwQr0Vx8dh6}@%H9S$9_($jBf$h5Rg?;a zNGEJrPua;Gs)MU5>|M9*`Kw@0NFMJlvm0 zU7t50@oO8x$%A%s#2g&v%e!#UU(ZlDV~cfD?LZLfDrRij_2|X`qc=kf(wILrjor^Ee)eD;O%YRc!BqHb?Jj0$r=zcz~X zDqKs29#p6PMpuZ*(<_xVDK0zTR!xm1S*BxcN2ci204LXq3l<~Ec=P3h8xHkwGz7p& zZ-HZj|HsPXQSP2Cj|6i{@8t6KXcED}S$bu-{lWdg+3*u5`t_*qRG3$ORzqZyq#?XH8Kh&X=Bm*;c52E16NQmE zAmwUS+dnKxfbd269G;xd5z*4`Ud8!b`ML=!JlV2=O?%~=u5lP zCZpzQ3AO+_L?yL^;^A}nu4DxzS?FA2XZ*0xJr3?lZrz-cf|ED^#CP*6BQZdbgv%FpcKEt9%QcwPAk3OY+au5QB zXO+kPG`R${$%<`$X!~K}5+eXv=cd#LXbN?ht+_Z`?bk_=bnru77;#oit7}Kn_G|3c z7H_Vj5p(fYySP=;b)yJMR-Ee(JlPLV(jA_|KQz;p3pHAw-zUXu_4qUVxu@^#Co_%f zZhZBPdXU;k*h4>FJ(C4w z*Q93Q8I>zaIzL`Edb8DYTB};|dae+0-cm0bt@>kQJ2kB?h`H7YL@sUJ`A%`6Y z7a3itXQglcSo?rR_VqBLFI$`Y?22`1yL#Mv@C)#a@b5SY2O}=87r^P8!L)2sfo+kt24UMag?DTpD!6hP;t6h5sR#NdO#_S zbxZqS>e4fGzPY_O3eJw%Q$mmCj~_gE{lR!6E4KRETkVt7{1dJo^vN+~KG42y@NmH1 zfb&E69o})ozV^Vsuqk;UVCKgS#s?gJpG-6o&3Vim+|<uU|;!{?N<)kas0Zbx^x0s;GDXE)tB!IJR6cv(Y2(wIb#No#2FNoty3We0{zCK zqA5c_i1)Z~x&ycGhd`PpovvkqLIYO}p6dv`l&-q3iE9Ni6KKjdyH<@nG8(NZ40G(? zUW5-3CGe8YzorGYb2Zj}ZQA}3UHwErx(A#b{%GT0XxE`QZfiK< z?3;#wKWwbL{i8Ultzry^M;B**JS@+^cj~M38a^_u>Ag*GGTw1b`!;IQq$D^`QCOI0 zBh@$j=#TuUjnWb16rsUu^o|YtM*|Of!20_mT!y6c#49-agptc1nGRShzlI3;Y9>Y) zJGHAoW9MMsG%R^VdnLLL-teIx7LjQnef1VX<0jV6iloo_-2NL9j3ee0r?Bx8XK4Xn zg1#OKq6NYm3c=ldbG|S+K+UUK>FcQz+DIZ%f+qnoJ9i( z@)BbXpkQn-tqHsV3`vnO=}Z(Xd_*Wh=w<6?n6U7r$D6F&V$#d%$qF=0WaWqHij$Qe zf~>qk5Q40T;C*LgWuuEpkCm*{MC@hAim09m+Arh8$;$2N5B?zktN$yJ6}!2Fth`jO zI9Zu988MKSmtFM(SLxO$X?cm0mY1y#gAY|09Qgi;NXz&0IU_AbCXBRvzsSTA(sKA^ zFMXMfw1)AwR;1-+fetun(c*K`@?smP*zrr-jxA0pUh*iE;-&x4l;TQ_#VExKI2ooC zFIpX(ADvRXnMRiJXWd+HrPE09YaAHb9GmwEX4w5c< z$kMVPRYJyz&P?&DKafkomMqxqEud6qGdCtLkAE63e|Z+q2gk|DpGjXn_43K-$w@A@ z+b{1_e_lTJ@)@pOsy}P&-%Bs;&gx`N|E#@~o0FHG=>Fu(Ctn_UhH-ZBjP^B}&7jUl zRwk2yB#AdfNrDKR^Rdt5un}X!DQg|IhRYYCS*I)!L=-OW<`;vFUsEZSe50?{0Lp4IcJ2=n;ql?g_af5f!txfS0T&Kx)@spC} zeNKVVWz9Htp9Xb)zX_saLa}ouyt?G}|u{!Er+S z!ZxVnP+7hmr+wd#OopjPxV;iqA$!^YmWpPQ^M{79R5a_hUl4my(-lmn^QEcNFtBt) zS9pGSvy!VTp)qvT-VO32EXkxM6q!*bewtI@V1Y5S&=tTbnuR1^U)eU+ybY1Bvxj?6 zk~D`&$<%=>+VJ5Fsn^>HYVvnWu+_6B0)z%kUk=Yd9G<77D^I?JCm%LpIo$r1{kXjS z;s_rz@S0<>!_-fMz9NEFDUOe>cBRF6>TE?xruoVLH3gt>=UkmXn@66mF|)S`T>UG1c--#m;b*rmAg0p3@b?B*weyHQ^g=ol z@V$mecxa$JlPPEYlh8&1(+-pEh6CEOn1cvSJPR)Edr&)WSgeLlkGuMHyS*%ht%^V=0% z9X6sX4x1OW&yRSMvf(6&mKV+`vtBoHQCV3QwBW@+(Q(z{IqmO@uSIHlA`0PaA&9NZ zFq_Ni1>YV5=?k2C38dUIR8zMNoG;+Sz$dkh9u* zbTKmH$l#2MsRdt)XLII+>P#Q3GiJ5o;5y6NP*3)>&r^euPC4i_c`0?lvn@Zo4mmlxs~sDLxkzE;+q~y`T2BYKG!g z6fp5Eg)|}5FtCWhcFDFA7*$@iJnV-wL=@fbFDw>)#(4db)?E(_q@-UBaA3~PS1@JE z2DO?!vT^Bg!+T_7?H||0x-ENbbksG)yV@et-is^VPr;V`U24OOiL#6iS+iS}h#i1F zDq^Q2n`B+LW@|f6A7PU$5BHPohb;5#6w3#|=Bwed8hozyysm z;>fV^i1}+D)YHyRG+Kl`u&fU*@xy72yaj}MX}hnBzE9TU%xMJ91{fdPTUTdp-51bG zb59dFTcj)Rm~G<;lW_hGCuY^-Qx?i?`Yj3NKSzJ2I+>di&FxcuS@qmrXd#%Cr z!B`$~M%QcaxA&zQt>jxo?yEI5yLxzqd)*!UP7oTsgaJ)$=DSR*0n_C~ptW9w${X z{apOGiT6Osp=R=jypGHmaB>}S23DQoG&S7{CJmJ%ZZGO9&(K%cAaN6mKErR9HR2wE zupd2&*TZeco>y`CTfVK|UKotTmi7EFt*cCD@v?Im+ehr)Z5CHZhi!lt=d$r=r%dK< zI8)MA%AJN8$nh7O?RTlp71yp7hsK!s?P%aTckfIyZH={(vvlGM#?82RO>w$(&&gR6foF7k~w?2qm1B+Sv3(5c8v}`oXM=IfBBXNnK23YD zd_`IwHwu2piH%LB)}4WePShMqCIDa<5+ssM2VbGK)Gh7V0IO_UVNRT(N@o&2YzEs( z9tmns6M*;xn%#ND-Hh)CN^xOLv9OXfO@!&FvD`t1dp-j^ff`%ilEL3sFp!qJ%&yEr zbXi>zkF zvaG=zsU*kjo()V83zLlvU(M_taVa8R_N|g*c$P2klY0Khb{Gq5Xurzi zQf$8}M5G*yKB^*(L)%pzmSS2&2uL~bPqSNPTE#1d(YV5jczHli!=(6zAuD^Oh4Dhr ziCtjDsm=zXTnn`CVN$9C`Gnhm9*k&U4S_fRdPT5$(4T=d1pWQ1#|Bmw(+Rf#M|88- zOEc7(Ws}8Ykfe5bgRsldZ$9=Vcmrweblo1GLWP$i}YmY$Qwb4aH#7VRCdCHy_b; zayW@lH>R=LiOQ4cK;m8XHDN+3+vN*LC2&Ri@`%*VD2zDFLL6d8FGlQ{6(@0V`6?ph zWo;3H>AH2bVrP42Nb?Opm;c|30hLR~C|B%ig{!t_hK{`-0jrB;L;fb_Z2{Xz;r#65 z8wFWf~n&}=mboqrZ~2u zho|L7G(Zqc6DU$ymPqojDW5{ho?gm@P$Ep`IAlm|AGEgL*3^ipKCAv10tb&_kNW?UH~&5YaU#LT!0?G6f$ZE?F9 zw>R$@0n=by8SFi}4Mt74k$XmK*k5%+u5JZGZojiY%+ZjMn`ITvxbuULx{^(ZYB1yW z=y+wqY6gE?hf1a8H_`k&i0JS47rFM#wSdxM2lU8hHFXt(w9leYMpL$m3ZiaGeF{6u zO__^;o7}>KX||`|Vi(F?8z!T21JU}IH`nt51ypN#J{T2}>2|L6wmPA0h|s3(ExP2s z9Ej7_9cM`7P1Y@Q;RugCYy?#>)IPu#?z#&{xa~W$o2Luq<6OH81_?m1)87^b1#B6@ zpdO!~2lf3j&5~h{z+~7n-)`$6#~cdv*(=L$01)|AcsxqOUviw$<$yE!G=t)2+!%St zz>wJ$0c5Uiw;f~f6AKu#r9C$ci%JcwuO<=vbTz9fjC%+cIiKKrqpL}MH+bZn7(CX} z#i7--Wp0bTx;#uYi1*tl8-o`eF1i)qvSn(HIEDdSd^>gkms!FbhBl05dDu5aHn(So zVPoRgD4rP2Te7C)aG@2&!4!6_Ci7xTiS#hE4&i^&jhUXNtc5HGf5nUwoAukJFXQ^M zGR5VgS2oc-E-kk_LTk1>8tqMbYCcA$wv*t)L0&erqt*xKejU%|4e3{igF3fQ_%X|4DNNW+G-NR$@(oS)H;F0@az={&Pi%7l0;X{ zOqg4qB-+z~B-&%cBvJC0OAHMc2_s1y-ltIFv004D4mh;11|#(!G~gRfYXxxN9-gWH z;2AT^&gzlkJe2%spygeDRWBXaFH6cSi@H)WyJej`&!%WsHi1gQstYec*g89a4x513 z)H_V#bCZBEC(PhtI9X&)S!b$Eb{%Zzg60e-wknHVw+S;jF%RPy(>>Mh`p8D&A|0$Y!U>0$jd0unvC;^`Z6D#7kFZH? zD1FxK5!Mk~A_dxhPpUOiG^IfJX`R$t^bGq{HA>K86CxX#sW zfy3bfC)Bq+ExYO4Au0QFSJbyXCA#U`Ar<NmS&teXFjor?K&71v;Q>k)vg+^v zGq|1`S20K+EM!$+teNv{~`Vi7Pxb%nDmR_;Z&Wh{6fA=fOFMfcblo+yqA zZ_ZlX_^}v%2jjQo{XTw3jZA1ZDp`H83=Qw0tQD*@{QJN|_@{sn*X*(2lkjGs#)ogTydzd_?a zb7=e(MKC4m?$w2kounS;Rp=OLOf|xCm?1n4kz*&@cZ@NdT!YQBP+Sbp5;(RP`}0o{ zH+HLl{Inq;i{X+pXO+-hHw@i%KAPfjhwl0Tbl2A)wk&iv44}Iq_UE4jx~~y*zh?-# zj|qi04g-0k4{GP*4&+S(AaAMxZdo929sqfB?9V?5kZ%)^pBjO@#HwDg%yx7=4Z?M> z8oSM=zKyjbNE4M|%bay(qL6vmc9DWjOVS0G^YbMdV?Xq;p1oz zL@~yf<2!3)E< zyH(Gxgu9!+9o$_XXErzzJPPjiS}m10&VnC7z6|c>+zq&!`>@PdV{BDtELM()A-ULQno zw56~OFi|uHdRyvAxSj#?8f;0ND41j|WGjBH=3M|k`bYObj2R9BNvZ-eY*RXB*YhCD zR`pB_29YT`X4eZA@#>l7GV6IjV)W7!^#$d=08i`w#`J(0(qSVgcDxE>oN*vJswsAZ+}8-1ZM9eUIXk3EuU*^+@72J`cu& zH`V-Ml=$-7umfz7NauR+78mKZuV@D#ZHw!{xj%VI&;w<=L(5;K7F-TT8=13q6T5SGrI>nX_++8p4=-M)-itI7e4J)=p!;Gbhqil;jkCdDdlu7V~HtUVYt&gwVoH8-GH^d-}XE_`X&pbME z4+zdGk$YxkCRwXsL=)|toXtd({VTGcoAdyNe9XQvsOb1y=qnGD$lsn3!Ybsd2D=q%r@fc_^C&8le;tkenj%ya=IOSreYEXPdeh{ zS0-3qF!CFo9>&m?@B4wF^vU&qwm1) zdB{cZgu4`52iU&VahN>np1OF6NpoAo_HF)T@A1HPv);*JXLN^wI0TqX@R_KPCTNvY z4iPpDQsg3`dd-jZ>-&o?n+9$mS0SxuI^Z{H7puX{4$S2%!+c^Hm`iO9K@&pJ(Xa_I ze2-&5&KrtK%0|Njq=I@>lG*VYJ+Vn@lkf$wTB3;}ld@xnf{2n|Lga#_Z}Gq+g)a0P z`;;a?+&;Cq8RzJVR

      5;9Y15z}(znDYS-=1HZ;vJi!T33lJW=Y5bG6(|Mf4!( zDMEOaVPrm6C41k4`C45Znef@Cs2)aUu`LRE8J?Hbhafjc4AxEgW+BONTS0|EY3t@f+B$w)+B)334Z-IIY3m$a z*zFlgTIaib^2i=6W5sNGHi4+g1+W?Ia&}PZkqXNHd+me%KkU7Elpj}h?^{*BvHRDp zF3GaomXu5NPXgLt;SLB(0Vh$_LXw$+OdN1nymh_q;}4d_Tg%oZd0y*jXkr4+3jvV< zoLq8a5`uie1`|SJoZLhV0W$>?0+=ufLT=1(gPDRu68t{jz0awt?*2(`lfWNu1sk8P z`c<7eXP z#b2D<{SQY*5I_ShD2d*9_bvmwAvAsI^P0kdx-jlIKOw_+^KE-Q%{nqh( zbw*F=VAt{a$2d7hFI?0a%FcZgQ&7H!!YKIMNnR+s$XLMuAeH$C^N$fj^t5EdV>!pI zdugvf7*0*2pl+DUH*Pv_^Z8pYn7?rAw(URipB`2$jCbsO_#+;)gc38xPME9C;wKWyl6j!zZmsS{+w5xyJjrN#lLo>hZe6pYdMWjQ7%Z@3W5$Y-&rjbZlW$Gi+u43@z

      3eF>D`Lu9;>Pr$g;VSTAc3Rw1|PJi)u7Mu87`i=m%T zq`{iUPMXAHS5Lwt0+_@Tn@K#e-FqCU_NG2Fj2kt4QyW!IS!DIi)yedzh!(L$!uZQV zmmErYnRoek8}RHUVc6&BvN4}$B2<^~d7VNg^ML-|mE4q;{rJm8jKK&GK!%F(L{LBk z)BN4+#Ld<6_M@Q8=IUj%+ci|$2;?8PfwCoKqkyt)uabPZTmHBYdbdvWHaLs?aE5b_ zLx_?TRkBz1G=!zleNIA7&j$Lk?YceEXOx7(cTk;wKu2aA04cga+D6 zqOf)jV9h*cJrC_#&qFwrC#>X8HY@p)KH?=`$wxKgJ}YuOYGRkClcvwpusVh6JjOd+ z44oSJ+!%lu*XkYNJt)$a{LC~3f&ATF=h_R4tI?jqTaKgejKhFhzH>!avyVL2Fy6Il z81D-2UVN@$JaY9g+~3bud3S3V?_SZ>>?0;E2*LEOGqSh-B0T?Shu*{2u_Q4-;+&g$ zXB%JOWar@2)Koebuqak)qm66!o-pD^o(ovx)xh#^0Ic`M$+KqfUD4I-!nuZV*Q#OM z72bWsxrVW@dKlw~I`3-@<9#c-nl0iQg#GUvY^6N#et+Glju83%p^Jyd(F93o1yPs# zc?A<%h@<&HYcwBN(beq3;%Lr6!SPi)D>)aLiN1G3n+L&&Ivil)F8<)ErTAbNF{dB; zFeY)d?W-s6-vA>%)SCQM{&GQobue z%nz^VYBqKlIl?52xZ7W^G2-sf#lzyulQ2SQ3M(+e9S@A=BdyVVWJOoA7p`NmqjwIh zMJikkxxcc`$!&mJh!THxj#|4;iGRd~J9|M5_zAC*J_e-9M>KDLG`zjt-`;YrxBuGT z{%q^xe;r=m=C6|!vsNCVdbK|KJ-voRr7?djytdU}BUgIuYajR5h?R(MeLTEHu_&;0 z_PiD}A7ocxClA}KrVK3=;S=^H;7OIM{9QZBPlWGWVBbLwoP+?IRwICa0|dCoyUTSd z{5>nWnhjM`Y5~PIsT39@?Z|0AS&s$-5~KNK=wi!RN3%+ZUWJ&oy!1JQ+cpT)p zI*s|F=lt?)jS1(V$}vmmoIOP+(m5ZB>2W5*>r~$PqvaC}pYrjh{9`HB$mE$}{ZRLk zZPbtgQ-SbjA~1gSLjLwGZk7;7WGlobg=tqZ)M2nv*ZmjQqg)dPTw2lLSkf)xH`y&n zx114QE`JXv$f~zCg~eydk;b!f?mCJujk9e?|EwogNS*C-=(N?-gD0 zuzbiHBi5SoupN;;;9F1i%gPZWuX`!x%=j`^Do;E(7f5_Abj#*^d5^2uF{9tnB`u;S z;UCRp`zR_5%uk*7%|og0(aV`Qxc}ARZ|@`Ld};&QY8$8Nb=#%Ius~iUM2F65c;Nt( zUZ@g9y(#tndGFnzdRm<8+t|CWIm9ozjp7o0+K znm;<;-nJ57a5U5k+3W|KxNf7>m&FP#Yz(=Jm?xvO&_))hliODjfrqG-|80ab)bDTW zxy4nVBwtLgrZT>>fa(`peSIgv+Bj)?8}X5itgrWsKt?4alEOxFgsBm#{_x&z-+P=16EqTGUE_La>#ER zpN|pIjEzbD&K=s8oefz^5f!{OS$N-EnG7ETf{xmD@27|}AA#XrSm@Ppq7$nzj*V5P z6{j#qhT8$*wrZ>c8Nt4>-?4+geeX4byhDwiLCe_0a?==QroM^3P63dSa||OL3tp)m><( zr7G{cA_^!K5+z7c@#@nTD_*n;1*`x2>J2CtjQFH)Y7U7S?1 zkxn}YV&{kN5mGi^-TbX+R^3$n5Br;QTN~4_s3??(N9A~eNCg8h$#K>4H+WUh-c6O4t?e1DaKBsCW$oKn9PvV%WZD(OmZ`7L(jc7qw4g@xtxW$H_VATT6|SLJPLvW zK5*xt7DGQrs!F#)q^CnY)7u=2IQ*PcF%Uzil$)Fa%)S)YV58RHOU)O^`J?N+xbT@1 zy1r0$W?xgAk+~A-?aQ$@ThT9v-eMSsEhWda`@-6M9RPNkJH(1X%i;>a47qi^$*y@| z`_Y}idX5N%h2f5#$oHvYh{cw_{j%yF#X;tOkIyrQTT;;Gd!VbdDTh3%#mShf-MA;) ztaj6$Y`fadrP)rkoA+dkYR})3EvenIC)=y`f;}Jy?fjnXa<$OwLu&h%W>>1ca8GuX z+QFsS)oQoy$)2Zn+n($NYPavnUa0m*_GCxZPF(#|E=qac53Ms+sf6sU}?}qi<#z*n7e-pu4YmVDqsCD4Cc$7=TSZ>n^ad zX=hY&aqVl}<~4h%D^idhD0+lvbe;i5uyKtq?&ps(tNv_x1I+t<_)mNj$5L6UVXhT?<9=&HM{FdLgM0lMiS#bdIzi{p%~)b-+YjFW$B&oOQRoxGh;tGUR4^AmMJA81i%-LrxXlvm#F?AP;RSWHT+G2B5#ClXWKneRl)B zaR(p^=xTGetJ?Vmb$U@&Knm0@F7#;^v!#WBT@Ue2tz%J!F52u!q#O0w9_gva^9|KW z@O`E0&Esy-d)5L0UMg7GA`g9LDXvlU%v;pe-{TH|D)^-n!QVYm_BBWwpCm(|R+4i$ z2F-_sUP=~(9Q%u*Pyt6+x9I0@$|53kw))Tf)DxL=67Iw6Lj`vxqq%kMXf4Vf95lWt zL$xeQuC}`;n^)W0lNDBGzz8Vi|%@5dhl@1Dk}tkq7W0aLqCHs-F2ZJE!gNUHl2M#`=h zk}QrphlB$DiTvH^I5|YX8EC$bmD-gg<)aSpyZ%fqWw_(W$^7zHbto3btLmq)|IUv) z`P;1vG!!AR2E8kR!J+YJrYkYs=Vu^Y1yFWpn5!X__({=%wgc5SP0`U@l_1Vsdr_@m zK0eT~NDO}ls%20uVGYAFT^JICp@yINwfDIrG@>ynTm!d(&M)7ZT2^8C^4IoO>K15#Z#z2BRjO714Q8I$o3N6!TdGz zk(hB{h)Fuk+?k0uF-v5^#pEgbgqsfyMQ5sH^m8^|mUQpYg``7&vJzzMhU8F@R^J`` zv<{3n)JnLzVwP`IEOt{&3$x#NAQw65zP@qM<99zKRz)kSU zDj~drf*{97C*({7tJ{FODQzGy?mMht1R{WxJ>_~c#7FIRc$eCpP$B((@xq+7OVm@> z{oN2i-M*aJ|o?GPwOPU8;!=IlEDsu_Ksvsstw9U z2bAtuni9+dVszS2{1d-N` zeIHS{{=T0otM7O657$(2x;6b->KUmvjzgmj(wh}_I#r3zjlkJW8lAZ2!lrr=;Ku^e zjd;p^p_ci!3aw6Fq#F%NT^r?%tx-Cm)hN4yQXsZd?NM@fVRJdvjC8K-2~<7+x$1oY z0{+O>i-YKK##E>n_R}!>45yke8=O{bXGr4Ctp4$)godN-fDbWXksjCTHSJ@N zB1FeGrsKgOeKEj#&c-jV$(+TF`Fxm?%TnW9QloCpnJZfET4s@_(k@f=?emLackF4anRf zLbcU0%)MWI>9?k;K6BsCbc?o8-jLy<&ho!ED7>_ofg+R@`*#L~*A_ESgxX?jK><0e zK{2TM)nC42#-IR@I{~G<>{ycDjE}@2I_uOxQW*f96Gf}pM}X(Bdet|RYB&j=V5yae zVh7P>C=s=$%i~R#gKAj)(yz@}Z;UG|hO1F>2r9Hua)>N_4wM|OKuN1XRSboap$Zj_ z^pz-iP~h;LHXeed5f8h3CVuG}$HN$79(VAl`t}#+s*yI;W(cS6QY#VV^B0|j(TuiI z2-|3C_;Tlz5zMOvVZn4y=lPH#i6D^_S?#Fm_rA5kNl~aE)h0zi+KMsp0NWuHV}g{| zUVu%aM4KQUu=&kmy0CdP50N$5Q+=>jqX}aMmE(%ds8;_oEkm`YTFnhoBV*l_97hON zdqOM*5`vIQ7NXG-#9IAvbBZjXKTf7@{6TbENVua^$h)FYc{=`aNBraV_{S}2Avsr+ zFCV9(-eR->GMaRlxYcPw;`?+~h8j%>m;$h^0hntVWUqSFTes!k>y6PPp1GO}(2G@J zD%0ww4{k;K`SY|4wU}1*)jc#uaoc}n;ryCXo)3}Ix>c_ZA2>ATR#<;4*o3b7@ehP< zL)oUfTMGM*4oT3WbUcG*xax1TvcE0d3TUzfZY(vZVP%x6cYa{2qedvB)bzfkn6}=x z#NO4_^vd2ZXnHT`y=Z#3;z`w)-yeDp1(cfJFF<5mzTqPeym|1mOkpgL#f3470b)0* z`^M7hD^*|n{1(g#u+&gvsqW6ao)`3pv`w!ANz?yIdt^U=T+^wNk~;E)#2sRVj;fnp zhqXaHheAhn&sg+x)L%RdH5)E+MriEYFv9c#`n&}JX{wsR6zN;SD;seqe{EWZ+D3!u zs}W}3l8&tx6u@pVILbx!t~YHvwU{KACIug;{)DTGl4K9n>%#McQ`L-S;8>khGrVQL z-JXtTo`b@>q9Px-=_Qk<*pUn(6iqVG385!7W2%NR&?XuA$PMc)TMjAYD9epWL44G6 z=E69z;vlFoj_N%`+G|^0)L{rc4Z(npR|v`=t9JqZ2{wYER5u1?N&nnWG^mI1JhUwi zs#_0A78nL)60ddB)o2V#AG+XF^#mJ{*^?Ma5FU8W7h<-x5QT{o+|lO>|D3O{9`}VX z2%t$13P1{!TMNO}x)x$4K;bzPNQ7mA7aT~aA%t9T!-ap_GO#d?4%KXH71EU>n6Ln2 zgGg9_u|p&dhu8s!NfSFjh6TR!AAdq}K?5#{NVyR&bd!vOsC-9&Ly%dPzTSAOw`B&) zmYIKbt_-=s=(e?KNDDpg(ob9rv+dMWQgt-gAodg)-~QO`>6IkOg7CiHano61F*EK7 z&>^|l{IV{G*rxNfhMzgn?0U>VjqOJB2eKKgM){s^y~x`6Jo|!wgIsIbvKo_PxhJ`r zS@7X49B(m~g4x9FyK?guY^k_u67SCQU=!cTArm%k8tiWobiQdKXvMLt4oTA5%jwFA zF$L}A2o5y)X9HPr4TDy4h&>%xfR+}`W_qD3FRdP6(}PB~G`(t?>8QSGy(*E$dR}Q5 zd&n$ZO$x0Ol&-KU!a2nG>No#r%c)Be@_3#IP2~EOTtgGbX^Sex891OUF}3>Dk8P~Z z$AF*YFB_C0LAAdc=Xyc35D7dd&c#)lh;x?K3C}vv*28B<BNdE-h0kl*3o2QPweZ2KaN%-IYxscU=7ld(c z!*uwds~-d_Tl9zuy%q3@tM6%|Vf7z989u)H^`1<$HMH7)Y^xvE{+GB~$qyrdI@Q-? zrU5^<{!4$1ZTP2+w9DN1HTFP}U`{Al?ascUD|V|833CukFOR3He@xMap>Rt_bf`~K zO+BlaTA-W-F2E|&gXJ!MaFq8hV_)rl29x?3SU={CIR>9Jo;C)v&2P!>S+(ug@=DK} zg*b_zh0NJCq>}A^k5|tM8fQ;uh0t3BP74BCIK!D)kwgOI?BwdPqO7rDB1@6s*lI3S}2lu zBFa3nq4SA{Kvg}T^MPNZ6gYdKs9Rpdzg;yc) zTE68eyzD+L{8DRJGP~7$DKAPiqB3XHuq>TI4Y=N*?2%=%s4`B;<9&FeG zArm$dnMU6+;J5UhW(%0&gAK{mp9w^!-U6t;*O|7u0{DrAxpW2l2~eJODBI_8=%GnW zly)LF_iWq%lW6MU}+WQ4;2YRRZb09c<{I*g)uwqJQR*jDrlOJ%HW3y&NiyYQqSbv#Z9n zN#l|u>ue&QC;!^WLh>(R2(8ayoBqB(w+0NJO>7?v*~HDqhKCrXTU$+JwX0|WJv?4H z5qe%}Y4to~v$TffVq)XsG;lYE2&nU7B*A&Wr3n{k$22NnOA%1C7Cb>~v5X4WQY<4a zK@;265;U<>EsKA#T3i%MY6+g$t(Gxgrgo^9M%pRGG}3NXOe5|2ifN>sR!k%9Xis*v z+L=As^VM#-G`m*q1(y=jNW1mNvg_5(Uz#mbhL^y_Jqm8*j}3bi)5sqeDwMIA7|v<} zAx3W;WP{_qwc%KIC#`S<#Zx8FSH)rFm{E1Da0Ip6QF+uV96{~HAr4Dn2)e#3#BV(b zJFMQn9HWTZrx84$-`5!`5aP6;Rr1RbTp?1AO}VqLU@dFofL0&5375`z78m8h6i0O` z1jpQR`-+*{80`!}bPS@0(N5ezve-O>Hkpi{d*-Zbg@3U^Q}jDatw4Eri@xhx31N1G zQAy9^7m-2~wtwIT*ovTU9~~SRPf2^#h}4G#tHhY6Ys?^R@m)k-(9Md-DTR7hXTEfQ zrtn|p;k-{{A=-o(3oIO+YVb_@=Td~cQ@#52oABD*LMpjFDijX^X*_|r^vyczVX&1L z710*^uZ>FqXuL+~8eJ!Ghzdc2N-6{`#7Gr&z|Q(1kKU&V==3S8NP?~- zGMGJ?xoHZ})TwPEp*oVuMfvG61S{m9#(TW7GwY^&slvGEk6lKHR~J~iD`W~nfEMDP zpd^_^%GqZbO4#8xo#5r3CXPS`M1uJ85ABGdTKE&fvxI^iUeFmRBZWjxM}k0j@L31~ z(NL?SsThMrQyD?vcOwY2Mi6KTjl3AVcS1l50k}-pgls)YEs@8Ut0nOGY0YNE8LZ8E zE8(su%n!RVb|`P{RVHkEwFlsdEoMDQPLdUE?H*qnV~nhoL|Lnrwt%vD`L*NzAu~{2 z)VY4#LxU@`1qe&Qw#UXy0u-ol7{JS{t$&PF>5rnbVRJG}JNjRj+Kb&@zuzDBDS23? zCHY9aJYQyq%VXDV!wK5Y-%e;uN>H<6sO-amEq6U2EPwlAjNSo{1GbeLN(y@NeppK4 z)cvn=s{U)b{)^Z#C`buJnld!0h0t~4q7#gMmPI%15H29?On6BP7ia}1=US^W8GWOZ z^(F-;FSb?-GG?o#mcTKQH49EwtKej{Ln+G-zIq`Jz=M%3lC^rpTQ^qI3e@ZzTIffc zThXV!KfmO+bhV5W)lslV^pzBY5O(M9{#JKu1a=*R=rTwz|4sT0nOkn69AJ0X{>oI8 zE0Be(k($72Hn4VwTyBaztX{OdynKczVpt0#40P%^ZAC8wtes%I;&x26!gOL0o7(q^ zG}j^*gFrzNpD?@oeHn>7PD&bP->sva`*D>aEN59|(@+@~E#u>$P~-8rT8nn3RkU-n zMHg*{{_-%JniSpq={7q>RtbiLWF)y7VBy%Ub4_F~wm+TE~GJ%1UTOV|6{ zn+ZELKPORr(t{R>=G$PuuXD@K`Yr)!3Ia!VCe7yrO*|Q zcCV6!X_z&&NsOk5A8s2HV0~^Sq9wfKM5F<7Fz?4&>e&R`06 zqe77D@97jgGP-I!gB(+T2njUowpqe~*yR@X{J!s9fFbcMb?BV?=Aqpu7B)0N)!Hj8 zBm;>3Ni*r%FcOTbGQ<#I3$eH7> zc4>L5^A^OUxz7&Xtk#$`EzEhRu94C&Rtt09trn(ynOdZDxS2`im#al8CsYd=`_k;H z=Hs6>W(@XW}*>_kjO)vw4m3)41n^uHB@|S1mdHN|)clIucLfl{o=_x7(jkBtFR+SdnOR8ln z0ei@LvcaWDd4!I^Z9ii@W!6(hPm;YgMlACoi|(0xBaXV`U$kLIJ^)OL^cWLHldz#w z+_9;XD?b)5XYTk7x0$6=!h?+K%5Pzu<>%~gKn=)J3&y?>xa5Deqq^sh?pGEc(SRw; zlKnrrHcR2$bgpbch|qqhu);=29W=lxzoUDrXjhM{3P@K^vq9KGw$vbc$4*@%t4Gnj zeA}%^qH*tXYz_R< zyESlIQ20_d2qS!Dhvc>iT4K=>WyF<|1&zQ3PhIECQ`ge3)NVI!wr+tmx*sgVQ%iv6 zc59%IJtOB`i5iJhJCXw;F-NXF=i^00+8dd5=szi$7I;fJQ zNV=93sTOKv)Cu9lvZ~0U+TKu?LUIQA3m;9hY*NBSTNjY@s3lRmPJy7#9?CzuV?WY- zAyxv*lAJ}Xk=d`ZF5%}I1oXMENuT2YM17BAvxCgq)DwqBS5fitAVR0^^LQv)a1=$D+L;~ zlNC{_*1}}1_U61kv6Z6&yrRj&%Aq=im4kG2BulKA<2q6@F(BC-X=~e;@RVyM3^j8$ z{2V|P?zRmbnvd|F?JJda1C1x~2t520>1`8441MHAgkX*7c+>7^t z2SR7li_!1<0POM3TFCsnVavyMD9}$t1wcwRL16@Av=G?;0R?tMAF+t^Xy@!cNq> zQUX&?hldQU4zV72*mJn2o(g;e!~C`LGG>Wd+C3O!_?Zt$s2I>aIZq4y4j+=Z)~|-- z!J4ee7RQ&3CqM=5d0(F4!g|`3TqujVcs*ZQj9-#*A$)0Z&6nV|_9eKlf2pT0^(KD_ z33id5EZ@;(UB;`|?SoQXl&B?vIIu~>x}>^SeqL_!n8sL8!MnaNQosURS2vqcw&8amSmjlX3cv4RV@~ED-C&$SJ#)z&jM{Cvf)2KwI_DVvS)joIOJZqmvaI~I#0h+$tP*1E!&ZdIj|Z-KyLYW;GkKJByn~`^w8@P z2H#;|{qlhaRNV-}$O1>}D2Jw{*UlmhJuww>$~HSc?w8B#cr9NK35w+*&t1qzX=Egy zYB@*wY2i-6`sI|g;B|NA9L#j+l{T0S0 zV(qD<9pWXancGbw^CM)?(tSKanpeYT?A7sX{*ul79<1fxMmmFYxsnvvmAszKYdg;)m1OK^~X(v3iOmeV%iQSFM_2u)Q^t z42B0%xXwArH}u+*%vuAtVUPQbkC9oj2u1cRZi>^`B1HgorK+>CtgERR+UW+!{4+aP z#uy^fVZ97@#>4%f>kNW8aVGo6L%=_){wav|EP9_s8wZ6-sZRZOl*#4Wz`XN-aK?5z zj|V}*jSI83w+H*j171Im4LG}y)?X+u5o}S&)Gf}YX4rHLDfYfP>dRg<8vEDNhaKpRLg7@GqtiO328`^{Q$EzeHVR3g~jqQe2;-jrlAB5JjJkBfTi5j zu4F!}^J+v^xwy-N?Hh-%nO3E%ZR{kCDae1XF}R!GKF_UywE7f0joq9;ERr?GUWTWS zEJ06M(hgP7`wY-AG4)~2c74`(alm=oOu^8km0>U&ld`rp`4jZ29qLo-vh8)QjgP4M z_B6z*p7gknxTF#6>lNpZ$YYSw=HKwt%nLZlL(>hJneBK>7#`H9kGBRApdO85HzY

      If+3HmzjlwTEnnYQpfYXJX5na(*{bQuX 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 z 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�@mdN4OKFgvHVxfvqZLenCUk9PlmhyK$B|;zxyS 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 z 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�iDvg!E;9*FNb|Bj%S!4Zfj^Ean_=GL-9l=3K76_+1xP-2yG29 z0(WsuU)OnGd2u`{!t;0W+r`uacLLTVRPF;}&+|4C#GY3*p$4kRrqDKt2JKPVZ0pbW z))RQ2AFc1)a6Mk&A0+U;VB`a){6c>|W-C-1MQZTH`K* zdH2QfZn3p@&#CL`Z}26|gncFI?S%~Bn3n5N>ND1{e-y_ZdASSJX^2d(FAcEwVB;^1UXPQq=Tlm! zx)f2Eitme26Gez5+Im^E#X7TuFN@a9>x^Nu0WWM13+IJeaDXclXo@1sEtv+%$ar~l z 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

      FLM8SQ2e00r$C^DaMaFWZ7|xMW>~ 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≪~0Y2;@ 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

      }Ub74cnt7% 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�JwGmd`T7E-cr#`=Q`$|fU^3t_s9hDewJGECP-XgfNtea{l6@k z`F)`2z5_&c|DN))6bv|vYB|sAc9hj;|I3;`F3=$c4*0*qwPN>1mQu$6-V#Q1NP4Fw zVMcU*XDL|mPDRbtz)nU$0lPgdSnm7YIYgzJw2rU+E*{QB3gmpT&KB@q&Or=F4cLa& zhzUQdSGG}N0|5UA4cDxjae4i6*(5DfJqmTjIRfqCLU0%My;vw0=)IoURoJ`c3+03P z+8^__%dq$9gy@=GHL{>j>?$RC#<~|=NB{*3o|w__JsY;{xA3=Ueb!*Fc49euxHY^0 z$rL52rlLB*ulz|Srig=$THwFGz9Fg>yYD@(Sz)aDUG=ThULEfI zYt5a%dj-rkE$R`y>IIP4>O{ctYJewSJQz7(SOGXB5b^Fdd}qXm5xA@tVxyw^&wqRw z7NIG(!&2V+P%WhVO-UYRTFg;2#9sySk9UZt@9i8gnPcza$Re=#pg6?`4Z8w>`>;X+JR+ZdX>diE0H{c`y zjlLlLEJXa`AX-aFw|W|v$ITYua(l0plm@M65FvGi3P7~3 zm35(4dGkFHJ-@f9HVlkwW^$fr4LPavz|$x?=~xfe_Feu(R?(QyIAv$JZeTs`Q}64u zgq<4w!q5n<0d!i6;g{YKE`4&R&7}`IF_%8T++6wq^J{B#a=p;W+UI1|Gr@7F5EWEY|Oa(#dZZd@oxW=X`(aknO60`{lJ-Jk>?JU)p|ZtG{pyc=a$!S zIwRt<*Q4|_lRE9>{L)RTC$wd6PIHr(hU-5r_P^<$*?BLEsAkSvQE8{>rE}iI$6sVd z(`mtsDrB}ogw;n;yj`qg89JDgzpL^OTA zNCJ@4!sE_Lb!%Dw|@FRQS+k#p+AYFip{HRAhauxv3lGMO#s7hhR~)+MQiCtPv54I+l}Dt(=_t z{#tfj*D>W&tvw3t)3J7ESIZvO)}EwdkdBuWFB>jzamqjNZua-ABXsV6x0smZ^xb@N z)XXNQ#Lyu&t9#$At)LNuoWmg}vnr4H0q1jY*bnZr1Ka(ysNQA=BQ5}7I|AA;S+-vN z+D9&fs-^(8cDtrrkB7&uCp@(d%0Qf!+^hQQ-@bJCM+GYd(@t}5Y%NTjl2$dgU486F zfr^URSiG8bGrFAmGjWShYxoy=r&}m|Jz&W?l*{8aERVfQpHg4OeDknF{`z_I>it5p}@N#v;O55@@UGYJk#BcYHx#AHWRP^R?`{0*8oX&WYI{lcA zt}3A+B9G>0k{35CP6^FP-$u!qpKDh!%IaAoUOvzTh;47{dHi4U&_oCE@>yB zc4@6l$a^KM#vM`Xa*<71TkEmK+(y_1SB7ueN=CtSJulrtAWhnwjn*o}?~3ZUtKr8T zw=Sle2a?H|A4slC+R%6pOQt1dH#|0Msofg!rOD5Ya7tSMK-1>PE1LP<*Rr{$nc1J* zn~DIN{49>9KlZ|V5T#r+-jjAg+=#vL`oj-hk*WiuUG0h0te!!gOz?}My;W8RC>W$& z94(JBfBv583X>?d;z`KBo$B;x_|{^=y#&=(>PQ-9j$6Kvp=*67Z*NnHckLuoKQ-mt zTl)y>8QOIaPtyb$Qx>kJr^GLS;7CKA=_0eV{Iu z896V(up|pTq`y%va5QSsB>#eTvdz^zHY$!w+1M zw%?0Ov;=BOu$}mZA6ZHJ@HMpT!XgzJe{L+^%+#Ll+*J+l27e)rb$I&p;4T7#oOGZ9 z-+vFk3ae}nlIy-J(ms5R{z3@EE0O+CvKYSoIW6b!e0NRj1{d_v| z^S6r^jaewaAO=56HCgCH7|Z(GtMcX5wxSgj#dKl_t!Lcv|`fA($!7={Z-xF&$ z{KQ(?{4YDei4PEfN*n)e#KwR9;RjahP5*p~ZH%bilEw5C_q_+o9`Q2Y#akDXhVRqIbomow zv%c8N&z>S~&lDjS^BnnRd^Sh*7JNQloXsS`?*tIIOmo5tZsIpB0Nd`*hhD2BWW%~- z1M?Al!8Yk*3<(a4ZTb-C@tg0Fx8j<@75?7Hu;3NdqhZ|5UAF!3M$9zoO>6jt!DN)L zNpC5ez7}hB`k^laSw{40Qaq=nP44;O%xKSZTGyn{EVE5FU?Iez1A$Pagy+&g09#fv ztTp@@KBfnyu8-|ETV7-T%~J`u>`ME|-|Di-mCavc8eR+nf?%_Jwa>M5of*MH(G5oM zP`+7O%EJ7iDec8J0Pi?6+RF^oc7hK0Ooy`U;)XX(iPkhF+GgP~w2l!EAF0Kjc1SH6 z)YWR?WY?<2+jm4Q_BGsy=J>u*Et=E`wWQ9RtRHTwerxSBJA^4Wqh_V?AWpc4yhyGw z?MKwOCbU!?x*Y$mN;{=Y5X|ZJ?O?1=T+Z-bRUSrDQ_GfG*7CgS%b)Kd;I!-GVBDJ= z{#PP?abr$<{FC<-taoV0;|*yEzS2%5LI-dLTO`QhGuF=lke=tzk`$~S`OpDq|CcXK zVV^0&4rY}~mn;#hY?f436)nCSOU)rT+&1?Zd`q#v9&WPTy2W z=9^=}>@l?a{@`#GF0ol^6MuiD=BFR?bMK!sKS;cHuO^+q7I@bvXOn4EI>AUS3wv8F zahiwKuCTysN;)F0vG$RDOPE3w&#i^4R;Cb-_eOK!Sngl7v+>^7GGRLJ`mMe8yG$WE zPo@yHGKHv>DMam(B$rJg6rH*E%~QsZC*LGlW?Da=vN432s~$(4%+?Oh;~=aZkJ-V9 z3pwoxJFuwZqB{L%ofar9FmTvG-o0Bp2v5l{+M^uJbdgCR3B*yubn&3S&O1K@echK| z?SuXaT6-jade}bk3Rjgph@66Cw0JaMc6a`CI)8fdjf~Qi(IS46(SjetXu-1?hkNs7 zPjHzJ^W*l(p37j#xbm3)<_3gE?L7Z%<_1m83prhujiYf7l=d@~fkj$3YnYlR8^uX} zV^$v1^H1nJzt@d?ci#e&hS@!I{ubvOu8~ROZH-=>)@RQ6A*NRQK;Ez8tI8)CG^-UY z05l8a9YjMw6hK6?CJ|uXuwndX(lBhu%!<0%+-n)8CV^4FKnNY>4H#CG_0R0f4mQ3N z0kWQSlBr}m$y81TwpKOWVvQU%%LS@t?XC^j6}Dw*;wo)qa{C5(7bS>eJv1YrczTjkSj#SMYZBHhmj=KEg~* z-{hTfWLD5uXubL%wHI2fH5WHo%QPgtcK{O)oi}o)i3+PV(a<>FMnAh!Axz6>*lhOs zR%4%WR*bnlpUzc~w|C5*?-66kCIh(O`O<|4(t>Lnc>QdH%@R`#Te>)6`=teEGm3Rr zvr=opW=N41oTK}5EO1)n-K71_>b`sFx%TA_O0XmVI@@Q~_Yz=?3Y@FE<$+>R$Xxczp{0dw8c7zIiPdd{1!VWJQgGPVoO|Xlm3Jgki8%#&wn$BoFq>wgSg**`Q zjy%#C?YQ2gb;C=4S<2b2XVMDZD>7YdQAWM*?f1~76L z`E9d`bFoyCR1fgt{9|4$$lky#dtCD{{b2{C#LzV8me!OKTEi@~C?h-Okm!7rk!#gL zW7n%SrGyqY&y6}ZrG$2&Qt}hs-Q`ZsdjEGF+GeZ~H%%xfD5=;^WB}rmh3-2lku?SV zK>LcCiXlUY#HXW-lvw$dkAa}3y)BAhQ%>a#X6j7ZdKdl-gtEsd-o*qJ7WkQXH)79{ zwTvrxJ5xt?3}#WHL0l?(27dOQ@Lr4x@j%X zl-BZ0X&1!dt^H83I8Juh(Ba@o0PnUWB>>q26_^D|fppLKva2LjL-~gplZC>7kik}p zVW3x-I!tQ!F`vKNq^44n<=AZp7*l-b!}pEmG*@xL7BJGxJ>P@M$h;8~E8T5!ce7|m zq@ONP4v#x9HZ9$WmEYK**7nw&wAOx1`Sc51vWM%}Q!1vZAs#hsz-%rGRceTSSB!&? z8lIMUPw(ugWxK-DlULs(JAc$>K^8}WERfrQvE;w4vk_!ZVzpK@tMM2buxkid3z?pu z;~(d~_~qrk8uf0&y@}2=va<)r{644rY9`eJV4)e2{V24K$h&9t^8N6M>@;m^yFAz( zbnKG}-+6Cd!1c1I^WIky(?_S=f$2l`v&+Iv8ooSoc&e~~S)yn$bzEIjwhA_}YfpRm zf?nrb8jM=WfF0N>6Yneo+YT&oVc=#v4bqn{H_l@FYIFGem!xHqhhu5#_kpNi%qoFF z^KV=w)p`NVPu0_W_iyX>c=m5cei;sjgX2F8oadKl1BFB!`$Sm1-r!KVyOArIR8| z)m>8qlyp68+{Z-`HeI_OO4s$-L7jn`Q7d*I($9HvB|XwQO5eId(HJv5;F1#q+?rW- z#F?;9+sarmjaVaGm7>cj356jFx#x-_KPA14Aqv5Uev^ktX)SpQZWym>v@|`aM1#q} z<6<*2<}qgIxH_&Oqvvf33faLXhU05+O^j}ve6n>s4H0_!&{n}pL<+SujUg@FSwtT_ z8px(G^dQ_WjXuKp5}Dj!flAB~wZQ0EGQ_WB|1!4^#mN0$+};zO?e?J#;iA#)k#YkV zS{?+_nXR*W^;7PhU{;)nWqOeG0g<1nUWa{yfyl|?H8Hue??Ut#&vxwzOZD*kyGd_K z2|^2KCo~?c(VR|Sr1La=G@cM-otglA-{Sc}D|Hp@>OWwQ9{%wqNykA6uLshvgM#jt ziCfMfp=gx9gz_uz8p%jNLncq@`1N#>$O1EOHnHrw7>|Ha}TkX|-vH3p8mI!kX? zU*^Z*m)8T!>$G3QdZeS!Rje|~vl!=bTvgAG$pV|ef0WRRM=sn2JcMtY_I z*$rB;3E5?>+zHZ*p)e`Zq+y=!#;cMkd-U?erIAKB*fW-OVozf;(nb|Se=V+eMqW5ASH> zN(Y=hYxsV#lh|{_o~5DJp!g)3PQ49ZSTXU1XLZv0KekpU?SMhvH=&-++ksc+eBRnq z5u8(M0TFMqj*HP^JybJE<7=-$i}zD^`)W|K_#`^zhB#gP1HBYP)L4`n zsu!Uu;b}cKwHW*j^>RTS;#K#zDKlkM>$Adxc(N~SXQ9l#o9}Ej*QUFC6L!`kCMyo9 zgBQlFCDQOHnQ20h)`TFf8MkOL18gEqMoh*??Ycbfv^eChR*R54tX7UWwe0S9L@mN{ zP8hCzL(3>c!RCi~Bn{dM|1wg-v4(JvnE%XS&cMI0^J>Vm_CIA1^iu*s`8H0P=`QWH z_e&jLkWJC70#&>7UF^!O?*Y>C3VLAlA+Wm6lh}1P|5ECB?O4W=*0oFnDIkF)CkJjI zU}Pk4Zlc5|U1RZh8~oEfQ~lZl_ps)MgzX>$-4rgT?@Qo3uYCln8oqubX(I(Ya1u(I z7=YQqxd}*c_}iC&E_Z&C@*e1w{x+YAZU7~q(I=jTa0;E|uJ?T%2H@9k9 zA`(JvU83|)Cn%fND4W(On-+7>CKD`&SFV`a}5nXmHzpic6)&h=IKcY|H+Nv z-!(IjQcT)YpAddmmmrJc4k(fCr!Zi@8`F|0fLO^a?D z=~G}Y`qmpZ%FAfK>G%e^GB=oX0EkAUtq>C_mAXCr*d+;RBCgYNYb&b;yl9M!$NoDh zH5|E~BGKrtx9(ai{i0XLZI5hvl}y!OXB5Y*>|-Pss-j8={|Z5fPob<72b)T-7}n^_~SchaEDcFgax9ZReu zG!_(J`22-Sd#iqOqdKEOX=_k|il|LEGnX?eCNp^ADbI*|Yp=b)Zq|%715DY%t1C=w zV=H!>@she-f|O2y7ad0uXmL%z7FNtkG`kJ9G2%U%WU-f3mQWxzF(Ubs5fLJdVGGo* zg@~UG`aNBy)zKugv#$=8n)PkWwYOj#_9a>~fZm=02H>QfjLis$;iFlyU~e=2nC)vN zK0y_U7e$+e!d`CMEeb40TSBaL?=`~atsBGteo4}*SlE6$BMB;!%v-h`#57w#`1_>r+M1O5l}lbZvAj+)TJg%icS+Kh&{({WZhYw^^A#uk?j=cYntl;u zQ45A6X(+}R%ROb;Zef_8V+zg^=dZWHLb(Jas7OIl$Y>*&W@cn}e zuuQ@Pl1cHRCMh=Ornje4lw}88Qcl)Yu6U|gF@s!UPJsAqdPZ&<5xIUoi*pQrK6lM$ zZce^=4h|v!(!yfRg@Ge1ig~x+;ooLI$lQ&WS=&8d4av;V6ewZhP9_9f-eE#$nz+xt zycwXm<(*`Eb7?1&LM-jD6VJU;ENz9w&eLMbDo8d4?p3|TmUdWs=QzbOBNY51*(Pj+ z!bBX=8_BBB8vb>*DNHXurZQQ8naUgxV~i+S18jWju$CEtbbed}#%UL#JiS$_QasRY z2pVcw3f~DyO|z7pxJ3Z5Zf)%q!%@r(w}AJhdTCDyH(4U5cGukGHG3CVIBU9SRSrhp zDz!4jYWElEggQQm$yLYF33aT^SJf^pjx{p%pJbkJLd3fA7Sm|ck^vCUNks5#Z%^6V z0Kf84QgaMbDmOM(j454Yhn@BHl48KR&nA-f8`FL2rPnR@?Ag;wf_2WnwbwRGM8qW) z1fK~Ov^O!Zw&V8va(Uf3{KAO`*IlbyWZztuY~V z!w>Nf)&+k9Dvs$oqXdB@=rCD_!<@P4o~LX^*w3OQeUHP3MYLb zn?dQTi-z#zr-2;)&E*8?&yA-0tO|{0Fr@XV(OmJ-JjYmq`I}>@=tb&Erf#~ul=7%- z2m5FJWHIGA>Zqg04Y(`O7z;SudLp6}z-J>8JTC5WY{TM-M3(xN(+;^j`4$w;?42l#EM7ofD&CFNHqN7flM4ddMOI~qE; zNa!FoY?^pDor#nPr^~PGF>@vqB3h1DUQ#Gv|1=IFL_H5Jvrxbz-Vh6&6iMe|A!6wk zkmLfv8y3+{r1MF#AQmFxZf>ePZ?Bfl`(1o6DNg}Vq27FZ!9T;6YjRj-cl84 z`@??2{wHKI!qpei>MfHi{_k;T&uXhP7!11njr~~@yl;esIL~2H8BE!uOn}rl9u5>j zw8?=)uI5&7df3^LlnalfY`8sT2n$oyRGft2M!y6JI%5b6Kym`b$(B|!gmpHY zi7!$@2+)uj?AS)KA9HiN|E}Jhd{N{8$_wT+{ykY0O^5col zA$zYLdS$((q33f^4?Wie&m?$8Q4O^N+Lq>->dgkuogXZ}@Xlg))2r1BEY;NdQn9;T zLF5vU4GIvvO#ESUVX;F+lWq)Owue8}Pqw4l=3p5t73t3J_Pz?2Ke}q0sZ-f+Pj2p7_JJ7v)Rn%ZtJAvr*Nfeq|U&?Xc0|GPJ_ndHi!3X{vHXXTa) zLM|tV()0z2sCD@`X!pfAz*x zuxsQJyV3J%%~!AGqGe62eONUY7C6=q?J{TLJixzWhXpqLCLOv7pJe$tI%EWUNo70- z`6LY>m_UOH8N($ohE&VzFw+=rfqZBer6JT~d&trb9$Of)uy`NwbC8TJN?W1?%Tvgu z8K}h9fnzNwx%QqrSGMgLAf8ucuI$SX6dqXj+_^XY{`LE%?1R&IV-~55S2w6D`SPuR@F_H#b(@QA#&w~2%a;hx*+E(fwey-& z(br0_sVU%UQFzr_BU&h#MJDaFA1K-j3<&2%@d=HX5da%HG_TaB#5pZrkwDI-(C~eG zA$5$9!6%!^Nj9J|#b``L1-B4%WY;;`UNtgNtoQN2=F z@8s-`y1K!QK;pH@C0o7XX!?VF=vlYy>352DQ5HS)Z0tpfbLy>4$aj)lunXDjGPbfg zN#-Y2un58*bqT)`??h*}k{KPVO>^Ujz=DZ5;1rwe4ez<4USYh5f$34#Sr&*Y^GAOo zvBlSwcCR?IX57_JV0#e{k<}n^Y|LG8qQ^BXQT*sEj4TB~!O$!SN~LXTMz$S{Y)j(3 zy2pAW>!J8MbD|O3lzF+m_NpDI=iK(uT?w}&ZFWH|4B}P^Ep!tlq!xlwa$Vo(qTg*7 zy{_ypq;ekL7>FuV`_AXctU4RSwsI?dCAMfI07cBs528;z)W}B>yRFG)kPnk+%cfh zeb%gykgA$o(`ru!-+SBS;ja|8Odg(m8!jB8p9fqs{L6g^`Zh7bDj=>@emhgN3fsAt=GfVTB+7dYQ z>iIDvc*86ko@&6Pq`~Iv#9lAdIR4EJ@t~s}P(5^M;!wdF5{m?D?8aX0DXm+2%jD9D zw|^p&)Eu^5LTft*9n~v&6e3_R({g5V*|$)lP^l+te*ASa$Cu>eGsWWS3s2KHY4Lpo zfj=GdHZx=|%Yqpm*-!_PJUuh{s2pQ@QDQSs&?@3WyrGSv1UGy72KHHb;C}f651ewF zGHwlW*40V{)$w_?|W*7H??f)1J3s zJA*U5-?V5XHCN~OO=K~{FzM2;rlRwa*JxX_R@PJl36-tkPoI|8n|U^Tb}r4we=dL7 zIn@2L&yFuX)cs{@0j~qn@*}D;G=v@S0iFW^1i+ z?-(=Ldpn<>c>6utvAy>&^Zn7*aW3yoS~t?D@DF1TLbv^8WZSg)TX<`wJZ8FZnZZLQ z8_%1NuK2x^(~q}K9lMRkF#ij$w{(#S;SDY?Yr82b?r=(8<{IH%@F%t^TVipZg$#iG zia%94Q)6)^4gO_&ite4A`Q4MJ>O8En>RPC5YK2$TD!6zRHCARF9Umg7SnbtYR2ZSX zmbwr6{rauGwJJla?{~+PT_0PAF4luCRt$J)p1C0-j-lcNQ(q$DM+B+Es7qG7{dq~W z;sC6)(aOyVe3f(3jL5ENt=O#=B;JckAetM-ebES&cKB!gmPzq#r}#!1xGdt+em`Pb zhc7FVk!PO;{yE8FMmZ4`^Z9~!)jP&(RqH!gBU2?M8ho8<8pFRSlI3roC)z`B9jaAY ztxL{zTX@ULw^pT24=3NSk(a-*zP_5Yp|d?Wr5445!|5A$iU+6rFc~Xaq-(xN*G>`( z*7wmSjaqAv0lQ_~-_uzsR+O8=;5%Qnobt7;m34}_@}yw0t5nc9z?TYnI>zt<*EDVjx8_*GFG{oe7Zj42Ep{K{fN+VELiQccTq}S<8PCxOL z)~U(q2g>8tLDf$fs6fe9vA$tvG1`$h)p$Z=d=Olo4DX!{ssi}MaUs)<>-1suynSk} zp4U)4g2(bFr?9~&i^^JU?88hs=Pys-sEa8g>$Da zM$$?=GiaFT=)@@;NkyP{V_qZLoA~!UuM|VrSgRM()auXmEyxhi`lmB`RpRX(^m+H0 z;_tMONq=hEwnl`_Xhw)Q!Pk0Zbk!5+ku)jmkAU{qQFqnvPmHp~WJhE+)g1h^#*0L$ zRRT8~cTGk>tw@-;7GvZK^(-J<)+tu(@DDCYrB(;nrdTXnj3)*#v0`yy@iPr2Q)qlQ zUN-RtI|VxoC$T-M&Pcfz>u!@-Syq8q4U9u;!Me0&+oH8X53~r^5#mMFNe`)|D(Tf~ zDg1D)T5@==S4-iCqcuYHYDYlSKkP2fuxXa{r`~`GLA4TsY9$1f?I9tkV+ldES5wSL z->Vk8j+YjCA{84dNwfreOhmyzR&FudnE0$sgg%V=d%E3jj|@mfi;h%@s3Y^Vt(euS zHM3$?N2@Vi&^T&@=g=^Vt0Kbi|B=DgAeUrX7s=mfH4avlgCdSD3xQZaS`rUbH`{m@ zot0+`+>$*B4>0h``x5F5k-Ck(B+^ZNA+~a&-Yg_U>mPjY1?r(k`$N1y2C96V$ZK+u z3=X+USDHdKswBnQY>V9CbV+QseQk!=Y$$|T_md-fIa?8%sTioIHG-!#f~Pftr!|77 zHG-$59PibTnh1S%s{!cyPuHRE1t{;RjCiaE+`40dvvY$y2XWeX+(DkeUIKZ$pmU?& zD@mFX>|c|iTf_w5e*x2-$=iww4TL91S~A|L>3jBK_^b&u0ThHrNlZy7T+TC?G7h#V8@Uidkv8eXN{msh93dq8Us-5@m77NgNHUa#$Y`K`!C&>wDh7c zvGmCPX>g1rb7nb4Jpu+eRjbYiBH_*+*y5bH(*_Wz2s~x@*z9T%H;FiXhHRiA3s}0K zn`gtA0SqL5J7fadaw(A989Pxs56CJ_rHN&As&{P`J2Co!oj_({WC?3VHv?-<0}@J( zaYGYOeo2sqI!Sbs&_jh-5*&7h&ci`?B-NPxv@+|m?8S@TN8&8#{G*ef6( zNmuc77zS0IT=VWl5i_%z2}uReL*QBNpr`dQ#A!7wn$DDn98||+1ooz7roB328X&JR zJc0A3#To_%Mm+>GdtkCQ;=tTnzD(tfloOGvZw{wYis+idsll?+1sG(~h4x%<%659^ zJfw`lDPUEGQ#Fh_Di;@0=1Q4BoQW=A(MGdt|D1D9h$<8#0NWSU-cE;PEzR{??OO`B z^2U?a+Qm98&ewM>zI$Q2pr#ZT6PJtp*|yK5*YM3~_(NB)sTz;)+aLDdhCg_PndlU( zF|w~(T- zx=H&Ml@KDoZd7cw?bQ#9Ia7;HiFNS>C9(*M8ObED)h1QM;|n$!D#nNrt$xJa>u!6d z{<0N3A)x3_a!KVmi{rV2w=`%?i(^d&78?s0{APD?b>$|QW`=F(>~#UjI^GYMR-20d zdqr{I<5}ljD4lg(#Br!Z+P;I(uk#E5WeUoK{#9m(n_tr!O**IG zM+yB?irH>Uf1!X;|2B>#%{KXaI6WexXPezX0Mv7scV?zb_4=Ko7LlpN=h;V$QSwyS zGep()3L*C`8!BWz5Z8WWNVFSChqw1MCM`JXlG!RF=)lvOc)Ou&yF6%{*HPP`Q6iRt zT{lM8&&l^P_O|L^)hhJ~xcVW!J#OcpXXz7?(a>747Qpku^5?b@ALpSRE&$K3Y`44U z#2RuVqiv+D=2`S%^q>WYkLOJF%8lxW$a-N8Z#};W`^uD&u~W7UK{)EHwnzNz8ytkC{XqU%Hn`$rauBE4a+Xfw1+S5mT|GC)9ZG416!$D z{>FK=F;QXj$H)40G$rJ{s~ z?R*Z|M^j_!5rlF}s8X&yuN&Xt*U-|6{GSoLVfZ=3owEjDR}%fjF>cpEHSiTOX#wAp zay>zGi1XL0M`b1sX;sI1(yQVR%`YWgk52OHq_fuj@(3EhW6~v}JGB-*)g2Et+(>g1 z4`GZNx7S98>9tiM)m}FE2q3^;H+Tt!T=M;S*PK^wH)cpTE0^MjZI>Tki``LAn0GYl zGW-X|J?&JLrp`55drR%RXx+GhM@*3jZ<{oT=uK!4B)Y3NllG{<*q&apOKnm@|1{b@ z`DtkV#S+SoTLsEb5lUi`67_{F5$Yw07=@?m>z(wpansB**r zotH(cV5Fme&gsv>X`Lgq#6e)wqX>Xs0s@d7ZxDbsXU~hpa*VfWzgk$TWzP#i)_ghz zz&mGhJ|iY+{3r37vv4M7u(O=$k9SDNX*!ez9K@N_`ffw!NVel8IZ;#pAPt9ZD=Q%; zlcX%s!#2osYBH0Btv!5Y4l;r$=Hzl|Y;084)2S+woesW}xG#K&uw(;(X@*^%nj8(W zu&fR+1L7D4S(Z#lE_NF~)Y}cHOJl5pG!E_@)NLF0*Bopk71SPv9jje(4yHk!FY_j- zJA779rw}{m+-_b)wmNW;K)w<9*%y-@;L1fk71(C6+DGlnAb1_pSI-@Bx@IOJKYcd@ z4XT|+ev05#1jBhDKiw`PKRjb?XMTLU2>U@}UnTZS98}EXZ0HXfPUz1EQO?+m`p~f~ znH@kS)F+W6^#v{np&10^WKh##QMaJYc3{K9BNgrCJev^@ua?f6IIcrEVsjII%ygfb zUY;XAC->^Bz>jHZfFqMDof7_r7Z0h0>20fp=^d__o$d3AKJ>Rcl&d{=2s}>f<(Edy zo42)!IynGhCtSw+PI15_-xDW7JW(z)m;gC4nCwe-XkT3 z?v=R;xM{NGBYV}a033+;`lcJ*8N}h`X}IkXz3kL&1IRS({&wGh4gi^a-;H9XpP-87 zNZQRc6}itblF641*RXpBmT2BP#xfIqLzJ_uOqA!}W+5SL?1zj%k}9~gUjmiHD7E5mV z-CVjXDLrC|5LBWv-ikId4i1}PKjUuIx!Kfitq7<0ff!NsaYR7@g}~ZbG;xZZ0R9?K z#;()qnsgAyEP>?VwoUdHOq!n}?8t#VgqQfH)Om=jHGE@PhlUv6wcy(Oyd3kl6u0V@ zH7QBxvm=C_i~Z`Nm4rSZ67l&_%}Onl5Q6zUoatOT zC=%1?MMeqfpgL9oVzmdM7q!ws)h7OET+pLdm+C`kqrRj9@{niU+SrHYg9ut(8?nE^KC|Fa7l! z`d43TB$#N!vSe!n%)=T<#M}#N^VFCn>TQA+jB6QcfNRlGKaf2NOknRi!dBQX$W-G+7rbN6iPKn`Y(7Zu->}koiJ#a=C#Sb7yPDUJ6(|FLJ zF%W>?B}|=kZza=n(eFaf&hxaVP_WL_dzEnP58t?vm`++7_Ha$&tx~8JVFBlr-|FwT z{9xQa!BZ<((xk=Si@f@QvGiyLg^vfs1u*6K7%?0TOTb`w|3;$2=sLSs^i?wtB6$>GNu)8Y$<-`N-6pqWm!grxvhWou6?i|t1tdtZCBthxOj4@{c52*bUtkL;(fB4fVL@si%0Hyes zY`WC$2e*O^tYbG~6*Xh!e7F3`ZgEVE9XqH$TbuzGrq|B4wFP(p%LY^bZ@qOsz9XWQD|(p7brhcCB@nnxzP(&GM~@j<)LrLNW)}Zk8ITgoHycGW?I(o-WC)k0 z{F1TR#!I#h4(iCOvnz%aYcq{^ga3KgMrI@qt89~IZ_M{|Prc~vpNZb4s)5`6l(uq0 zgOin%+*je7`kj0<^&?U6`3>lKj8hPBa_M)6ue~DG;BCBs^|%o5jp^}<7$@pOo9Y+J zD{*py(L4Qs+|O5_q4|U^*XIW9#CSKmAN}^C=OT2dDZ&XdI1WmnGpP?Clc)%@1Qa1a z%h(}p4(t*X;n)nPv}QP^g+0z1PJtpH>Ytkp3R;K_PD2rg90I@&MI4gsjtyR^B_h=+ zqYz_>jtGqM#S$0&nWLWS2ipk|kMzNJ#7ZJ917k;?!5qE5x5r~cvi*u!r%S~v0Ums&U7#_#KVe7nK&ejS1(S{V)BRT|5w z-e4M0j-xkCPzLwz>LA-9(w9Z2lOxO1cO7cK0d<0C;@gdW!|ovTvQKQqG&!-~5o|*3 zw#ynZX>&+08pj%delYxrTr($utpMwiiVA0jQ(I<(4fme_Q5w)oAmvqgh~p5kwn-6(>PO<|#vra4=>Z}yf< zhG#=Re*X-51axc2lex=ax7r1WWhaDVOPb$JyP#dHUHmV+age>fC zNnf(4UBK|rWs9s%sCEg45OmqPdcRgO!^TYa_}h^dizS5Q3^tmKjc@E{@CN1lyZsj0 zDS}mCS@b0v?(jtCB~{C6d9ceZB4aJ=5Oo$*(>wygPgufKzrGXhLST&|nRMF8NHd=e zhQ7?ylbRNj;&Kcpif8W(dEG@N{qh?mZbape{GhfTG_?-A5U{O=>gCdh?73453I%>j zJGL`2H^AD_Q0I%LIxoW+Tq zEG?><`2;7cPhwF;tb^{dHl0qa16mVpv}QJ^wOTT?*a~N>1tQX3ei=Ir@0rg)du6*( zIbl9HS%mKyXmTy-_fce?ZCmD%2pKyVh2TqM09u!G>=l(!zvL zU%PNY!+o6L3D;gcvOQC`*6SX}^L>?8o1+cuK`c@hx|L;P-H54ORDx3FoAB@Gj@@7xg}nTp@Wbw z8C}E(j4!&Gdo+AS`$p^wabRm-ec3*{Y`-qUJ<@z4-pNb(dN5v}{aOzhj5nZN&QY3| zF13RVI}lYf#_1tz3T@mlL}?VKq{mkJ(JtS5R*;4Z^k-P`qLV1OfH&y83|LdI4k=z(Wl>f*TK=VhHq#mMQx8U zYKKX-W;C8QgoP#e!Sie+x7HdFDw>QTowk9F3A3-B%8A$?6XE*aexHbe^O>ojG%)6y&T`+inedDeXU%&HRktUu_$wi}eAB0G#B>jPvZ#LaFImQZdNlpLe9!Eud&TxV)A!fN2#ZbQy8^)Gz1n1JYEo}6vp==1;ghJ)x3 ztl!v?XnK!~25)ce#M?7xNAXHsNn-h;Pz(?T=jg*weTWT;%$$TaFR?~|myn5R7`FDU zOGxZimWCHA%^688!PA;wf6g&n!XkJrnS@&&7_T&a90;`s5|&I9d$ILi3ws|acCq!5 znSt?nM0ld)nNvW0y~inZC%!3?oI<)jwnPdOHbk%{o(GVOjg4mSlE%=tOu86?(OqKK zq+D*9IX`;GA*#r%Z7tzhK3i^!f_L~GNqtZ)xh$44Op5Tfj@bkLu-ZM>6-U$#uVdlU z?!B(KQSH9#$Qq@+=(^&h+KaC%UZ@sN^^4T*zpnWAYKeLJUbWAx#SW1Nlhzwy(^=>#ww=mbLq2+Ea}|XrWmMy%{DXpS4VT;k%}7`nW0ed+xG0d2NLw z540k>I?+)3gP@qfUek<*Q?t6_j;eS8_9EM5rxymelLl={3R{Bw)yp>V~3{Vdxs`xxG5#7)xw<`CNNC)@?d5Cf7*u7WBtDo=Hqr_F3Z|H zo9?|fYZKtp^)r6022$UO!3cY z5GKR|nOl;FPuur1b!3MKkXZDQZFeEPmN&wm!(vx2%(Mm38+M3NY9=%(P){pUt$dFP zid5{Yj=f;JVqZybTR9uU>R)taDt+a;848*e4bq3-kWHX)P1LW8P z2v6Dt5uVWQOUuPuUhKrWMId6`vS0-(Uxsz3$U+f7%sG}!=Da+x(~K9@#`8f0!Foq* zFlZDra`F+OeC+h9O(8$o+V)70qWa+nFRnHklZVMDPu_`fDdU3YQ%=v3F#Uo#N>ZmZ zbK(-7GJ67HjB33fw*E57Y zdwN;DtbG@ysW-?#EO9oE;R!4UwV6&tZo@})&+5m_-+xm1YfFG|gk zcvXj4gi#i9lbETKE_p)ffZ=$k{rpi`{X&~(@JgBnZPZeT$FN3L+ z$CDp?h34s$%3UG1?deI_B}Ug`D8EianUPIH*!l1U9mFjAIEf-$Pp2lzJO)8h({Q1J_OYRT>f| zh*kq#&sKI?Vrgc!W_&9R88>}d22p-lz^JtENdTG^@CYMdqG*SV*F}Ivypr#6!ECBk zIIUXb*devZw?>fFwUJf-I;D7)^D0O)9GkcgSC%wC3@F#dfjB|8TD>_=W%+fhHyS_S8{}{GE;xau3L*}N zU)X0-Fe@Xd2*0tK0F3Qs+|tpcg@;_M9(m*o#qeixR97R@a|$)r zE>FdWXSE^0{k3w?@Au0=*=OsD;0pCX7XPJN zLbXb2;7*#%d9e%pK4EKWpN(BC0j>H0t!U4dy; z@CSO3N8u|5Q|Dd%)kNXfAxNsguz+#Q(s0L^My~>DvF>fHjQiEQio0a@>sK$^cNd39 zdeMa9DEXjF7#T{d6J(!xU)?kcyjKv9gi#N6<;0V8@X6qM0p7tK!ym_D z;ud-g8>SjCOli|wvu?Omh0aqIC_%QFmoX`6YD+e|Fk4e>qYfsb7Yc-H#6k?rjYdx3 z85aL_pf&&Eh_mRt{08c*jHtL1rgnA~4)+QRX1-ym!%9KbskfP}GH{(57gBjUL`aU& zFg6o8zos7mV_Yu)?}1;mp|7(03;P4R0?U(OB-E9eEpe^YgM3Tf#hXoty`$|prXCOv z=Y;MA6H8op#s#bs!eJGaGZD=RjD~fmlm~ znlI8ABh3S}V`&~1TgiEftz>`|khK5>y?d}YDXm%PLYiS~t7RJEv?eL7-U`gX?z~?4 zq2)Bl1Tq~Bl{HgK@mRLZk<)BGb+^*Cc;I`B+O5?#UsC?T3OB*%w<8K_V28HZ3DGu!nEZ* zn8HZ2V4y2(3&_6W4)8 zT!cF|LFO)z+3LY_WVq?Sy!yVEoqpNr)Aye4I5;~+XI#Xle>3)>@0aSzLGniFjH!;Z zKuO%uIT146HSbp6gT$o?{=N%wKJniC`(N4?AKqWzlMsJ)9SL&8nj_k%#z#?7$lXPh z@Mft(fJj=D!K^BAQ%g*ZRYA=6FV%(0=;^V&R z6-~W)LshY8@mQXVRL?pRTykj6@wC!Fs{Ec7UK3zk)G&dBP8jiyMi7c7#3LcNoV%x*=52+8 zM^4Pt1>41~wiGaw4u5=aSD3MLrwN6E{UYbZ=(uPA2DaP8APM0ij3$?K`Qf51LNeLN`Dv?Pc@j#LIm zSh`W;!y+-Xq8mUuQDcOXw=IfwqTKp3Us|KnXR0f}>@m=(+_{Zc1nI!fgECmDQA@3H zf6z-BG=*1qj=32qV(zCQ;u4xKhOe(KR{uS{#Rjs)j-IA(-ZkE*-Y^#Y&-4kUyaYFE z`szDU(0Wsx&;9y6qWvLml`4bt7;ClLiEk3l-|e=1iW?jsVI1mf$`0nqVdsF3GLIj= zK6~h z{TOcTM5Q%*r~lc6&B!EXWBu3oq&ILPwKoVN9k*Br#iVuIS6aHV$t<(oXfn_u4R-7) zi%8I!#hJ}TzBog7BO5eJ9l?I7h4tcTjN(pKsM?&gqD};3&2cxn1F=6#tg1y=DHJah zt^KtfDY@z%S|XQs88h=PD+z|V`ASTmGw5ic>3K?m+WOkI6f)P{f6?MFtkk|tvUA1d zL?05MW0@auxkVa`86!a!HQ-(|L+qfsDrI@efh6*h9aJuR0JltzcDpQZ69k*`v_-5; zGOPEp;nl!(h?OjKn*^EHt(z7Dn}x2H+|E6jH0XL0U@Zb!y=vQRA@Cfxm%?BKsCbRE zg9fZ3FEzKY$6^DLB(N}(<7{Rd22{3QlbsG|i&Muay=Xc!=9TM|zH82adtY|%{ih!` z%l>U>!Wn%f`+3z``lW5W3i0!_h|cSIvetk~j%X+$FthseGWFFT%d`nKwEFu~tG~t* zX9bEqrz~ENF-Z0p1Bd~gFs9A0K2J1GlHZwlJ~G6J<=)wEZ`Mkb3GlpD1|dp54|#1Y zUKur{^R*G64(2LD7x9)tj$VCnW`X1&B)3j5CN;sEzVZFwr-QsaUF`(x9_(jBuOPn^!t(kCDsH&HFitR+NDP% zxfjWGwAze8snh};>n6pfE-)Oq?|q2Xl&rkzP2XgpumB^hQ7Kr#yzCsy)HTB%JrDs1 z>gJv)gL~3YDXj%3!4xCGDMszKr=1NWZ3sv)R^sPca{i_Ry%5}5G%we<7BHywE-Q?Z zz=vIwcz4se-z>m1V;QqRgU)+C$X>BE&&Fx#ctMmq#*Uy2!aA~QAHoRBJkO*l6<7t z3H7%dMoQi%aa60U5d4&=dOgm=p6dsyL@p1+I_^TiD1dk&*}$?$X>xb8&TQte$qi1r z=2;`jd^JUJ9(wEZ*aOFfoo?DJ*C8t-ez?i7p2T+=Lf2xm^(|N)&kWI}#|`FcG==wr z5vlncR*m3u4cIPwGE;1w4)KdVZuTUJ-<1%*1>zTW!nQjeWRpZN75hqR1aZCL)7&Yk zx|vc6ldgmzN`iKp(p5}D(zQUk*0*;FOUF*J5T|D#Yt1fSLvN09JH#XR&Ev7fC>`V7 zv%)NkPN>Tk3hWbNimxIct?zYzryrU1=gF2tI>Rpgxv6zqs{hQRvrg=yJ+$Jabt|KQ zw@V;j`cfLY*c{#i9+xPIPT->Hy|m`>rA>AF%$mt@3V39tS->NKk5;FhfRP0*lK)E1 z`ndu{fVw7z)FM_;GMkmLQaK9v{Jb>l)G>Qp)WUxflK~wQn~|2I^AG0M~D9 zFDiJ|t-QvA+a-k~jrAMxywC%&oj2WG0M~J&ID4_k5Dz%dMY8y5U#FEc;bf7qC6Y?n zNHb`xzH>g#SsSW}f)dHbLEg2}8p`Jq zUcV&~Rjq`kV1|#h*@d`0PkWm+?FkYX39A(es|8UR$+}SK+*#jwhH42PT}x^jEbI&G z)nBa-zwph8YUZ}ySVGg@VI9|9*i;}FbvJ*WT!5D>SXfOv)nb^qD;Sv8B@^0K0VPlx zEA-xM=8`1Y`Dk+`fx=TC>VuZIy6ntspoB4(oeW`BSSX ze|>*7ZeSfR38~XtO0KrX<>dNXD1Fl+yQe%Ai;`MN)#_HS`yw2}$DTZ2cxESLn$DLtm7 ze_Zw|yDUq3)yet{F-$jb-c0J7(a8O622#Xw(hXd6(D@0v>}0R@*PODK1u!`Zyiumg z2`JI7KHVO(vDqjc-rXLvA*J>Siiap)o^76Pq8CZCBm|xxuW9{hdonz=DBCnN_u)Hp zjHjUr$h_^z5l7c*qnzQR_9+_;#tP+!eji|Fe9!}h4u3nF-gds1Mq@KZW$4>zGAbEq z>OIcvTWKYaM+3fSWolOtVF}1Y@3&n%-nRLa*X8kcvfeU|Z9EgndLQfdG*`2BlZCgN zwCl8^6$>@cCicjB-d)COgARXL2bcn=*JuI*Vm9OntU$Dt5e{Ty-;D5ABoR>?GDYjl z@_|JHLY`c{S0aI0!a!`V0;@pCF_@@fjOWWy% zV2ZcjzV^5Zg)WGny+AA^v199-(Y3fobBzTZPOcXOa8hL6gNNAk)%%f5F%L+po?T-G zUu-gi22`2iA@j_@dC2)Qg8(g~%nUNyNkD?Nasik@203B|!H{-dz^*Lq#0+wUP%(or z@9%uCMa-bFWk_ZQq1irt%pg|~Z7_pSchABMI>ACRGsyfSPvChngDx`NBIT(!v_qu) zQ^pK_lWe0!E4^ul!_HyoQLXH7DoZM`pyPvp1ht1^qhNsr{jNR4^!+YDgR}Yjl)nnI zFIgRhsX!vk2FR}&L(LQ75uj9B4}x*(Lzd9Rhwd;7VyKzQYf@16N60aT9G={#`t(ejmSMZP?c{jt!|pUL^%)MIDOOJ;efD+}}+X?(iLmxeFa4DRT9?^1il?R$9 z@<9B+cdEG%S+IKf><-YgV)ak)O|jc^LZ%f?YC!GkSQ~RyvP=FNifnVVI&|E zFEay~*!Oo=kSRclxMc7K^HQA)GL0}#OG_1VNCeDSMYx9eWU!5$@8*2c$7Q&+8Z(P)9bk>;Rf%Xxcq!GJqPyD%yySgq5nnJHt>lH}{%W+xLb6aBCGrHD8b%Y!55wrPD1XK9kE<@>lSLixPOg+}>|?s=m8Fy9Bt zhlswmD1RkTKCPjAT0{A?W;&%c(Go>6rNz7DmX=i}+|p|oDFu8CSdafqd$mzt?H0@%^epP+( z)tgn>a6RI&u5DQIXjG=(GzJqH627zQ@42{W%nD(G^~EAuAM+WAx}3JX>#@Di+Vra~ zm^S_T3+vc6gDF&lE8Do$XB*tgmT_`hzw_glO)cYw+gg_vTjn5i8o&VhRazN#c4A*> zX#T48>Mt%BG(Uz1j>T(}f`@$TI3rt5o_*Zhn$>3-bEEb4=QGE~^G5BpufY&~dVToh zg$ew)&@2Dd7i{HU=xKZPdiALbM%l@?{K@s|)jRl>zXtFB_yr@|hscay6tA>wFcv<7 zX35-{NGt+rh%P2B%6wu{lES5cO}y)#oYq(o60(dZZ^L}OWass`)~rr(#3xbJ!WGro z>c|b3xSbzpP5D)nGJeW}z1BW5T$~YbeIt$yzo^+O)C%*e73NhtQZzLfcsm#6QIVeQ z;#%w%YL9GLEs|yJ7Aac>yiVwdc_bBtP#ncC*$2?NU$W`efr-0PP*&f1Gf~)nI{$*> zkMSdg{RjzGtqR|hk8(RYX}&b#v#liIh})=oorf~!OaR#*V#?T*AcdCq$sL+fE9~fz z_U-cIm3Lse(XR}V3HubePt|no4!4pJcS3Pi> zMeadZEx2I{{^*>DcREVZJi_v?qN-v?aZ!4c7qej>2@|Rx`M`Q?e?cD?xgZ+>_WZiOL51UzY(U8)m zb*rt#v`}T|9MHw#@{}()e4VR1MI|y*7u#4}KjodWbf$|Va9_UQaD%SCTXPqusQs#o z^$2_oE4tWfVnzU6(aCIvwjyj!kG1aCA1_af@E#;C^Ahn$6lR{&{JG!ZjqiIA<>hPL zxFG9z^++60M@G_sy}IN{dZhQBii^6H&sDzdMN1tP8(w%;O1g?^RZN@Z8R`35u>SIl zjO{H*m0X&UUUn43M-EbRJw5fMFYtcrOqlKYz z)Kp0$YR}JvOLcosEO`>en44M#8MH=wYZL%&%D|3lHC6zW-^uTopwC6j?dwP>tW!E} zy{L1uj-wZK&Q#9pTO*GAYJ<)ZZ95qixLT?uxf zln#v#lc24_;8R3bKrNNHKwoA`SwRohi>S>zj)KPY+>hEjQ41Mm$|LueYWw1i$L4< zVm7%u_QG(h)P4ewZSHo5{SG-eL+yP*{?F`hp68Dae|+O@o-E^_x(4Ku$st1&Ky&WC z>jk}p;zFES(DyQmbBIF+bVLC~&ocCCzxKAWo(qGO_{H(( zv0i<-m+`q((bp&2+JXo=_z7u{GAZ)_LuFaSk(_^EgItV7gF=v%%f8ki+xTey+t#3^ zNVnU<%23p&(x-0fKHQE(sAN_W-#yz^9!&_kA~Z_&hW4bqbJn|$g@ir;@D=t1vsr=3 zX0e{5-xAveybkfDQOI(OcSgz#!vOX>kMeYsOedN8UfoSbaGsdS&_k$K^2|*CM;+|C6|cTZ!kKhT=cpWe;u|@%2e8j zN@z+>xL!R>bEHbVc5R$|mb}p1!=2p2^N%lJlnT*HhMUW0jmnd~5X2l!5OXxAJ4c4{ z1hUR6Pja-)X*k;EG#tV5r}aD7{$?G)^tV=+{;UW=9Ivn5ezpo`$>5d3xe(2Rr$IEE zWW5~GZ1sI0zb;!e7nr+AG>hhn6#zT6(t53z|`EYmbt1Qy$fNkkGF&T$RvwW-JT+V8<5J>Uu(-8TwyLu{Ur% z&nPwUOR93-P)Vx9=glPoFysuMi^aSNd@c>GI9F|M=lERT3!m$=@VP!88J|;6fPzMa zOUMNY`x4;}qC!l#gH&S;;B7^t7Fd0z3pdcOjLN0p@k|G5zMjQg$(*!7CsK%NuqQYT zt$@JeX$9c%uv_5EDCA*9v4*oMJBx711?ivDTZ=2@(%{t!*rVIW3IOd=b!i15?K3bp zVNv*iG~JbwQtuNsr^6j_20mX{8kdMTm-U5p_@xM+gxKl&P$Pb;Rl)}o$VQ~{w*(OZ zjUaz$kxhRH;#@=c7~WhVdR*&B^xRY+`T}n*!OGegf-#|p*MOBc8djA6GFWMj2;cM2 z_K4y$@bVN(*I^|`gOwbcVdZbNuWmh+-`<{e=D)i=`eLr%WPooKR{>^9toqy}zCFMA$urFt9x{0w- zkrdYqJ>tN+Vr*8{P1zWTv+16j_TXr`;%s^-hpsrA5YSVlYMAldC0j#b&N7~}@+eX< zEq+&tm?yMugTN`Qgp4$olarI40Ca_(z&OZ4S(;`uX&S+Dw1N_{D+4>1UXi8=1(D2) z&8%rGWi*iY3A$bisEUwJxeuEY2mup!A=)u7sw>IjMAK}dVksUX+u9s@HTEaBI~bM% znFqy@(eCCdy;PP}OFGGml~{*c(=!W_GN#q{#)1U@vq~ocoby1&pfE$|QLe-BQDZ^+ zsW_lmkeVWSFdJ@(1xZ5#9AXMN3sM`TWor9iopgfr;)9g3eJg5PxkS=QnejOg5MLq- zQV<(mqMY*VcVa_LyVLi8CGI(eCj?It)=$=3M7YMpXkbCsNW>#ic-;hJ_H(xcV^R?I zkuOR?(2h~s-~DDCQEv?_$kmqSpW2?a=fCq+tgb#8FL>3|)qi=`s;iX>D{)w4j!XcZc z7Mc>X0V$kSmHaj;QYJ5W+oZB;k4gj{s)q`;sm8`%t{$>+!Zu0-;$`R|ztt++=m>hK zskl(l@im~(Ow25HyL8NQ)v)JlzLs8ziulU3OoPg*v=A8XlXY5#Z$71OlAdZXtDXsZ z>Z6p8cm-7^g#ybE=Q6xk^ol^ajsoSPUF1g9XD|4@NYmVe8`bHVGk}gG(KCwVO#+Ol zC98dH8^Kc#&4K}I-aTZNT%wBNV)bMkoxyR%*sOGlF07}5gbDs7m3vO^#00M^8Ya#6 zW*SEO^*QcZrePM`qRjV-zzG^g{8NU;6%kVl=yG9lp8i?vokj<7dXoU@s~w}rfJ{lP zh(t{!3%wCQIrYY2zBqeR9D~8Fz>LTPFBBTccwZOnWmm-3?t^g^9kInx?CWLO+G%pH zu(kWx+Vy{KdG~kP1Vza9p7u$49eQ=rX&G zl}IWT63iBTtn{N;^w8eO>Sc>Ql^e7$o3Ne}%X~y6)k{XNCPWEFm=LREY2BjlRXe&V z3d3Y+xbqHSnV)uxzL(;GJYvN#Z-eTmR+5~2NbSRZ}9gs2q# z)|b(jM5szk2T|#zY?p{iOLB^Ou7m=y9Zp45UMUeeO!yrx*BJ^*p5TR~J6g+3M2(`-_M5tLEm8HpU zcFoSZ22wOk(IUjFG%D2$DUHHLO_Ei^Z(QlJWIaHGE=NQlIkPTs<2J|lHt^J!A~4;^ z9$SprIlPV$N(T5;Rds>SXQ03|^YkkqFxg(uYAjmeYNtM}#v)W`QDgB;By)W7DtqXD zb9;XABVTHdzi@R@->>%T{l@nEv0uJ=ulF!0`9A)`oaHJi z!QF2}c1TWghm`)i6wv`^nV>?;k^uF3Pzf3TOVLM6N1gXorQMjkT!>#jiI;j4cwASx;8;%xRjuP68S#_TCRZ|wG3-EJGRnYHvW0V4hJg||HCmhN4t ztk$omuYdI?u8XgAhMqKjeNXH05fgz*u%;a(Tw9sF->}R2*No;|7bl-%*|v1PG{VC9 zznRXr7rPMj?`Ej}A$DD7{H`04-Z$ed!Np|xZie+D)Ac&Rwot~klMDAInPYj?^VT~o(xoSQoCyhsEL&dysp zFRntqKimq{|FIR@MwTqHl4!&t>*&ciUL-y3;(jEGKO&yVv za1eYxZv9lk)P6XFoam%A0N$fh)1=&#q_|4voE(lG;0Yjw% z_*f^4^JA-U4h!vOwRXJ*0=V5I2P=Tix0OJC&qV$3Yqk<=o)DQ6N@16*Ax+q>;5hIr zvQS(gwh=PRnj)#rM7xYU=v*yJRwTD+uBWi9DpubuxO^KSxc%tj6yH~+I)yD%#G5l8 z4@h+~7JFqty;00A3wZk+xuNvdtQ3j?)x0~%D-ffEq@e2`ZYyae75}vHkQc zjhG5e^0BZKSz9?(<)*H(>2&96MztTvIRI{R^;wKvP2e!Nihg1yB^pA>r#3TU4jnKf zmSfG+7`6jDjB-><>DMry$x``;<#6-Wchj4mh&Qfsj8=x5^QH%dn^(Z>2!0Kl9#c9g zN`qGA7(V;lRE`1AQmy!e>e6U?^#zT#IYXlKLLJrFSO~-4P8|t@?TUW6Jz)_o>`-h~ zDyi31$f=}JSE0-10K=ut0Wzl1W|&VRt1bF;4UGpnFpbA?F{#N46!1L_4HNr5M7t-60f?-$4S1l={}?;vw*l;USwH;2ZGKjTOGx z7rbHH?k^~%ZMZxS-e20r!Y6fnvzTn0@Qo)k2-kSBv2c##n=^rX&hBj=4ezY5iEAaV zGODS=mjDY1>M+pKC&`SG_Vj{RauK+$&dG@agbfj_AyO=YRRZO?1u<+w)YZoUqCDBf zt0P!TmEJ7C!!jen z)}<^tGpU;(i)1hjs#F&rY(iZGTLlg}8yZwN*S3TKW+m8yo(`)Ld{F6WpOncEEfa`M zPfMCwEsCP?{uBi+g`NhAOHb39`A3%__&Si&UhRMdyIe796-ALo+jHV%!$46)M%=25 zcEdp{dQ%$T$%S~eY%dpZ#6{mq9wv>v6LX|6RG#Ff`a&Q2iheJx?S4w#3Ct3a3 zHd@~1bDE1?6Y!!$riFm7^fR;VmwdLFqF!UOC(~qx;6i!-+6wmhIkFqOJva>S`G^~b`Fe_4==4iSF%#j$25Kc{}w1MRJ^3MWY|Om zkUp?+n-xDiFt#kIUzAH=KeHtoGt>)Z?%;5t5J`$tL$`zmUVSe$up)AkbslU1nk7Zt z1-)E|oUF==2vc>bljJ6Yjvy+13*rUMV`9|Cz&bL=`lcW_4aSZJBmBAxgMo!z4Mu!m zFtGae`QZTZoKi&?j8M+01DBO^VH!6MM)KM+7@2rrjvf%C;;OVVjB{>B&cm)K>Lo?L zdN5Xs^8^A=uHoLT)=g+`!eO$CJqJ_f*^`wvt}e)KSG!==wnBhaE9dX?^;X+PxV4s9 za)1(9WwfF^PDxoP_^*ZhN%+V3k{HXaZ7s#I}ASUoJ-%Y1s%T zH?AMjoonj{myK3QGJynpmty@acC2yE=k+7m!%eWdxmzk;GxXcmqW)IjOU)*Q*jkNH zGgUCG?BeW|3aQAB64lHUE<&*v>qoXlAE@`j^Tq~S=eRinECGreI4?SHE6Sya}UKE`*}f5e|Xzpdr(o+>S^kGl52A12NvOFT`!1cKFbFmW$(kKBjPlKHQYN^G= z+C+6j<8AV;An7)tx{D1(I$V?Xb}^;1YJAp+tXqM~=qlf)hob^TivA9-(Dy!bAy@^# z#CHI}_Etc!^Ojm5h{hk4Gsjk>{1$~ki4W_bBcBC|yAMH?9Mj9x#9`PdiKZ%qVD-IR zoVZ1q#K{3g+5nenS~g*$1)h3sY&8Fs+T;fF#NP`d&Vui}BY zUi3Ow8OZCtYYyr8FZ+rumYm>}YI(9jxpwhR)kZ@a`Rzh2m5x2%X}!Tll?=GN&DJ%+ zcX_kpveJB*aN;6{QP@<;4t2KD3ps~RUHGb%lD78e-fii-gTYWFBz-3A;!L*7}tB~43uu&koutL{{ zjVUtK@kAqu_SYcKYRO(%5}*Qkc`wmt1IYU=gw2E9Wip^-x(IPKm%WY(NmR}g{z#5u zx(ICGsB|rTuaHE2UNZ#IxSCKN5rPOCgJg&RM6H!XFiG+&lor$l0$BK^JKHh(z;#gb zmIR4ZP%v0FC<_cHOKtwo>iDSIkRV~Uau4mo^iztMB*5#0^&XjReM76oXPUznR;Cj5 z2|#S`(8iq!;TS*g-NH82A$A-eX2DZ5Rnj3j$rn(F^`?WEl^YUROE0#k3p-F7zG2_= zBW*gJybeH~kZh|Xz_L+Cn>|IXw&ewoCp-`eM+oC{_1zru2+T_GCiDY?2p1E>0}zR!Y=@}uheBNqq>s4Rgw1*Uy7L__DS|MQ=`g6rlx zr$rH0kI~jyi_uLzwhFh5APTuk&}CHD;7(JAH*Ty@q`OK$<;0&A6wfkemlFS*(|(r0 zSCXUb-B#aNfnf3j(|*qFbjw{6*rpG6aapXJE%EeCkrEV1Lb<@`$|@LDMya-{NOC;Y zks_wa1R74y6#C*4mak`H!R3q}lSrs)yGatJxPuh?t;mCkuFF1&kR%MEy_WJ!3gKc) zxmuaa3d@6$z{nF_0-Luu*sR!n^ryuNwg9o9R)_PP`^+IZ$iE}kS;;$~kR`D9A?adW@xhab~DOg{Yd^!F-Y;3o)i*l8w5#UKS z-KACpdVveOr>7lsE?QMP-B^dASRVP}R*RG<{l0JifBJsXu^mCpe^Cp~U>(zR(zd_! z`aJm@fFUjMGG}9%O8d_V)qU9SR-5tD;iU8T09Q3k$*q&=X19)2cfhTE2dkmqx`Hy3 zq3~ubzM})iVFO^~yAm)O;yV}(DulxNdwCvnwNKU)i7IoslZ$X7KTPf{Ceer3;Z0Lg zhjr8{kmJal0s)yF3VN#mNEz)cKwU{SBg%Q0Q(AO^1Ejz@hXN#pIAnkn;SEnSJ9MhUYQLZ5EqnUs!1?6;EQ1)B>e!uhAvNG{m%L45` zJ$A7$nYF5Ank?@KDsxMufXpow78h+bvZKOQ z_4#HpO7#1!m|Z%aCDujXuSsWxO;N*)xJbL>>ByOe6_{~kn2~NcI%b>>RBOGgXJqD` z*>K(6jrMRb91gpKmN>J)>{hF5G#K=NTLaZK!ZMmY(NbX}k~e0y{hs03fhs1oznQCMPt&3$PL==;_Ip;H0CC(|g;pJqSp1Sh+nJ6|j;A z*#44W6mDhvWNt0NN_B9Cm0QcO(tcO%sP29NE5r1mB@M7LNXJRMZZL3w-0F3QyxIIi zt3+iokmKFfLXruSUrOgWZ5EvuSQE*JRN-Rel$n8F@qa#_PUQKN!aFv|$r+X5 z9rR0)`3_^piW@X0MRtPa3)-KGS< z1L~R&_#9Uy0A7@5(&7woyJTuO0IwLzTx+fX;Nfdsy0&5{d$BiPW+<8B^0c}KeWwbn z)Fu8xk_j6@aQ0%?bQQq(@5M^wy`@SHV#&KpylRQxBN1jLeqW}Y6_T2)Gn(`Sk;hyPT}#jC9RpP)w41QEzy8D7=mqpN0eZ-3m1sQ z6@?3eC1}WUY^D;IixDRgUQvnJ+p$a~Hi{GILxR#*NRt}3D7Av>$-<=wcu2237nE*A zK)!XvTpUMhyR5Doo#cWF-v9DgJxkewwM#`&7Fj(@*>ZO8=87Osd)R+z*j#G2B*>A9 z=4jMWj>hI~ZM?MZKElOI?GB}!tOkmXYa+D<$D`~{?_MnpkdI1ci9RPF?C!n6?7v&2 z&<$e^cDubn+u&7KWh43A?rUAJzm0ZS_3%9lFu zdKf)s;bpa}pl#OT>0Cwe;O~ds$&61dy+TdZ$+(%=uyZ@rkV@_(w$hOi!9?(I6$y^E zDi%km8wQ_-X8)mdY2cS4WL(oi?|k48I3bpYAP@|9u~yM*M;w9=`Va(I?NH7j*iV6+ z%xVRDwo)su;r0_?msT_kidN)kZafg_+Rw_vq8)9+7sP{Y_=1*fSpL6! zMGELID#Oe0k7>1sHmj?`#m&gcYnhzC?;Jx{ML($u=Irm>EgE`LQozK9iG$7Ej--L_ zNKUAPRyWy+T1VzFvKdamSD_^vRNqPuTE>31>`D*X3dNU{XBGFJaCEccTTbs!3wN#3 zd5wzCLI_uCzUYxyj!C$bQR;15a3JV|9b!3#v-F2GbgtKnOYSic!>U!>s;eE6Bp*(Q=`95uq6J;w(2lV|IQ^bKu`E$krxJUoHN{?762`pDTNA zwU_QYSD@RYM=5%u@F{w`s%5se9!~<*HT4DwD50en9oQSQPqs9v5S?Nl%#fd04H#MZ zi+M&VDt{@5qQJIAUW*caC+aKL3{&cI?W-Eb9TjAz{EO!C%K2DTxvX&R>R7{r(_KU*ipi_5;MDzjA8qsYQydXw}4Sub+S-_K0wdInvr>~$g-u_7V>X#SZWJ2vkq z`767v9S@*9{Ymrx=xgT^7R8FF4yBAPrj)V>tPT>cYfC8w*g1<;piF zi|O(J2tfDuYT9D+SDcnCcz|K+S#+P zbni->tLFP(114yu3np+}%tfSX{D}(vpNuFV$_(_I!VGUNI%t`%^)N$yuP{R$Z#16P z!wkjGo<15so8Fy?i%7m=PI4rhdi{eHwvzI#Q72a^_otVas&pVdQA`w~NhKlN|N#J>enGbWTN%@+OCoqwc!U zh_4QkTuqafXeyUll3R;3Q}YerMENTVOxCwt!G0{Cz+zQTs{U%z${V zpe`B4wc?2m4tP=(i^Ia-HM^?vFbu*WvnzzAlKX;cS)Gn2wRk5**QJ=K{h=5>38}PJ zc*#i3)9ecIwfb(FUDf8%PHh!lpNX8<#iksLOy!3Wz5q!Smia;6P z!Uselv~=qHU5c-)vQu zX8y0=^&Cp(V^W50fRC-Jv-mjWwgz9V*7nreK*&WUgr(N{Xx)`4Byi7qE|-2xNscxp zIog!u$kaPQ;JUk9IAWdNSQ%HR0%<%tU@G*N$F8Je%BkQ}pv*n+9D`JUS5>JsMNWf2 zbo8xB)?D_5sqW{Po*5rb}9!h^{dlDaLcG&2gol~*sHS>#~ zy?Al_s%c-MtapK}4ET2bjd$$yaD$oHL5J`caV=}qKeBz8S}ui(QPon-bwUSH4~&8K z^a|908(UdilINS}N`bz*`q6`vf!k7X=aJ1iCK&e903_u*a{%Noz4%d;`QTLLk%}L& zxJvCHoFBOiZMt=p!;+fHd7WxNtCi!1msZXVg~z2<@bLXm;sd5t7@sUKaOMgi9OPh?ry&$2S@ngC9ml#&wKD6Q(@ITN)~On2EFSWn0?B&!&s zMZdC@0_A+Dw<4b`nN@GPV!U(H9vVj-I@XSREUZ%y9(!Gtpg#TRTP2TEPRf*FEE<^&M^6BCWEI_%S65Z;I_OxzLC-@xX>)Py zWsvZbGtyL1?Abz?|9CMWh3`aVXOsAT&rC2p>5Y)Hhf z@Z21vhozT*QVkI5zsmS%5IAK4iDrRQ+Mf#Sa7g9G$JzqOqZ$`NIk3A;Yg!O{=bKVs z`+fXjp&TW!VlECMlw;UATZD3;+J~f7DwqR{LNOcz1#=8`%!2W#D24Q8(?Eu5vVT_w za1L3n zv+$H=VKA4)3#8};gB^N~H7(Xe*kI95o^KVuN2F)fTdN~7pv3ZxoBGTBD)opA*st7Q za04dZs{V@Gi7TzbzN}&P`Xyvz8K0SYKwOI-{dLJfrAv@nzCj*W`r2D#`<(;Uo*DZ5 zo?ho zm)ozhaH@yi`g#ISXItO)52tAOPsjxJsnQ;a&lxZp@XAID9KBGloZ}kSa+s^(wS9Ev ztDN#lyDT8QEb!e zzUQG1Q_q3TB~Lr2D_2cBr+bb*?fSK8H|zc1KFet3!V66L_cczyH8}1AN`CG1A26VnSj3R`(*Y)6F1QC54Qkz03}640rj^RqM!~uXUtWK&M&( z=f4WN^5=S&QlL!2Muo{d)3aWn46A4Txe7>unwGlX5IV$c=%W8OUZy#^;QZc@0GfAS zgMN7U*DrP`6Y}M@f<%y8=Kn)iy1WvB49};VZfb^xZH#o=EUKL^xK|YwVk(mxE<9K^ zN7@Q2nZ#7Tnw{422oPBUDHn;XfT%>1ZR~pyqZ`t88}h|!^+>KxHvS$yeU;Nuc5A--3OkwTU`Sk1u!Oc*kBcjOtSu$22Se$iwH~tE*K}>HbNDow#6BC-?(~ll#CDW`GhOo# zP7WN!oYlRb6JJ_O@$gPgRPu2AgV!VrnDTv+f?iKn)5_nM2^}qRS28WCwpP|ic=H|; zP95GayK=yQ3ies`qvE9)u8vNc4lrNoZtz@(zU6{Q%8q&Hx0*7acmW{X>ojSZG0PHn zDceHTo3U$~tw}bUFFLkri@`d~K_e_p>n$Eb-cSjU z-t51$&Jz^#{+9BBYDuw-R&Vz4)_I1zC-02F0vRF>ymg0A|LB{dwszQ@)~x?F&{ zyx^)p4($6iu*m`DmF)X!1*G8j?Lj&!>U zB%~A9h;Ab+$FKd`gfltMva~cv7YN;WaQ5VoL4Eww+M${2TF;;TzP|X$;)_4f7w;>+ z_(Og1w&IJ=>Wg1{sF&~YNBZIe#TS39FaE_3Y~(ZkL|^>b?^a(tr7ynw-|pr!KBq69 z_|#VZ;=k&P&s1OV>7V?Tex@4a>`#X{Fqm4JV`Ckm=u$pfxGd?k*7&o3qly(mHdIa* z>)TXQZv2ktCUug^o~tap0-d1O5c{kF?LM6mBmLP2K1Bc)9UtNCvlbV?e^N>PKb}mv zGH58Hb(4F6AxGC-uoN8yw~$I_?tE?&f$4smdCPAjONHP(d?r!+rP{ZacIRwXUT*dv zR}QY1#>oK!9u~sAQ@kYCM7$)tlPzn#Yiq6D--xp_wZw5LUQcBj_#RGUqN9a;aD+>x z#EcElqQ7F+8vPZegPMY+YNdnV_-r-mC=aQQT8$cl35KOU-^i-eQ86F-UQtr|EJUl% zXZOH^d|q>Prf^_aF{5`nR(j~|ukTEIprw}>2$MBcP6>qmJ3_Eq?a72irUTBO_+;UH zC2BB4xJr{ymH0%CS)Lk4NZAQ6BLx}e2y29C`NWhjSM11?9CQcx`6YK28$s;Ca%Sr4 zdr6{KB^jI+&Pi?xM+bf={xxGn!`C1*^BZc(f})5RGu6@H@T5aw~j;MJQxt~cs2|maC2{DD>Q$ISw zN7OUmyzl|@ryeEeU5XF5!vAVOHMnV4mhNn%!POG89SJn!lFVil0+{%vouZ|W z>skmTU0XyvERWsOAqY}LxP~%9!B>ar?6 zQoQFRwY_uNeN7cHY*w1URsDi4Rn2t)EYUYAgIPkzgXgpqQ)o*qacNY9LPpKINtphj zBM_b42Vxh}6w?CFz!vTwLF@Va<}NuAQSs}97i@1Du>o$%a8k)Oq0+X>#|nqu)IIRA zu0Qf)#Tc`!xJ!QQ1zL~Orn_IJD5My~lx^U3&vVO~aw@6Om!Y5STXsmx9C7BBg&rtN z30@!+;n0?O{q>DR2Ko7+L?YHQMN?j&yE3F%hU7_+AjtySTAlhN{cF-EOEPX_*q$V& zVoDXDml&qdCadqJQLJQ{B`0%-tQ~+geS#2(}n=uy|-q*Fu zQd1tRah?%eTpDVdVMP7$Fa)CK5m#y~?;4FNvii`WigJJmLeE!G(iOgrLR*jkSWO#2 z4Z}3DVQ zBxyvksq_WrEWNU(IXi8Uiy&VxL*!kK0gKmcWaT3U9wGz%My=hWa1!-hw%7u&iS$!{! zXO)lO9NT8HdVzpqhKe1j8Wnmun!{}vm_m^!w6kFTCqwZnEtZs@t?muPloI2QzFZPX zSmCAB_iA1)EAdj)7&vIT3>3jzbZ`h8v{7jJqb(QEi?VhrkVIWow{3wV|3hJ~N44A( z7vVWXvv$egq?GHQeDt}lTLU;j?k1xtxnNf@ICYV^xV{Po$5z%_3{EoD8F~o>17rL_ zA0M5;38P&rt3qij?&U-8FEkFUw`rgaM*~Pg9zm_Fs0!Dw`z9O;({QtJD9ppHI<8S~9zLz+vPlkclZhBjxL~%l!rKIsU(86znfcU%vvdv>53v#O;p4Iw_YqVl~`;mG8LM5A+AjeyQyr*B@~&W z&*b&M*8i-9uPjH(S-~g|s@P!O^XP}w$L=yFaAeEAyGU$`_CwfkO4|o5Io!OL0|_*| zOP0kKx${Icxxb;dhTONtMf$@+>u}*M7l}&9@c`M%ZD30@=SpsiyCqr!=^9FU_1#>$ zI`dy`9-fLsDfF*aBr2q1Jl-xErw%`iJ*z2V+%(!PEf@bu+#Z{_Yo%* z(FL0+x*&297NQG?c&nld6gzXlE-eb~@`(Ay{StbRVO97WGMvfT9sk60lHfzbCbM%h zBGfi4o`nd&PFXKqZY!q`F<4yAS@0T(@7ygcE*h5ZrZu8&sv6~{53N;np$D6f!t}6Y zix7AXseUbwh~>e~sPY=)@1;nSD+3;?THa)6QfJD&a2wP1OZY02-CXI?!X6YHDi4yZ zvV};Figzhzx+JhOLlPu+(TpU}bJW;-#rf-bWV(1hzMrApGFD~{1OY_0+0W5tKS!JW z9L;CJ(OmQ#%|*}ABE~opL3W1u=Lmu$vAu=Q;)5;4r_EZU-|3KJct{X0<(_Oc=mUh4BK5x+74VN!u%4CnPMtZ_6bR@{sM>dL>jo&*+I@^L77!j~%$0IhfcUNrmTibgc zA0h=Wvl+NI{zx~?(=-I&R%xMpZqm4&@vAACo+d<$&D=MxT_Z?IdPgFOBZGm2w80qb z*c_zvwzZOusB^zw(os98!SNqIx7J_G&UlG-@`klndBgk_Dj$|*9}!XbbT##r*FI~S z`pa8ays4jCk+V`3lu|s4RF01IxENPCihJ3&c$l?SibpFW>xTUZQI?^)1&&s1xgSV1jRrA^|vA zZH;kU<*YTq$M3`>6?vRixCy!TbWP+RzUGS0j{n#_Tm*MwcIYS(tSA_zoa*xi+USTP z7@_FVEG~N6^T*obw-2i~^IsV-RWFiIF@ZfX*)J=Y&>IGbxxjySO#9^Pc$8C3+(s1A z{Hd1i9mW&x3r#MU?X3%-jx5(_R7rR>i$DWRWYtm- zbL+N&Wd!gA#=>3vAg21n`gNEU0V^qQK}kq?j;P$Rj?Gg3o$cn`*cX#ak1prm-zi4M zmL?tJ>gv)Z{nOXnM^|qP|4eM|d!Jp+{gFZdxtzWNli}A^%-wNe6O|}%O_Ag9u6=>z zH-)9LcqbiCm|ieaLMj-(2Je}cI6Q?~u?V(CIZ8`ZaAq9n_UW7CzxeE$HGfh-#Va;z zp1$6F{uyf{$WR2nrYtY#kp_6JATG0it*vG$WJD%~iG%`?z z@IlHUyPBPQo1qRL{W~-Kt+k`epXY zi=A&9{W~g8JgBTBfLB=?qf`N)EwfQ{+`v=Ru$UGNe@Gn~B%HU`No$~EDNz>2eYfZX zEC>H*OQgdq?2cN4Zg)WaqkgX+i4tuub2hFJxRI{0IT<`@}ATDO3I`Gh!bz!p(={W=^av)>7=gS8{FNEeUo(K1v~R z{vM%T5VLtqW6&AZ{_a+5*wL2BjOoxiAZ?~Ht^_{rnt-_T)|6hmFzpkRX4oOIJxH?g zf6motxIi9dih3A)aF`Kv9-Yo~3G*RE&n5GL5UJ!uX^;QY4Qa^n!4w!f9$ZCde&~iY z^icK7Cx)Ye7Jl%CG}^e8mro2I0w;d>hU7(nU|l{jy9&l1xFN+omZ@M73g}hOt!m2n z7j8&_?_STF5O3E$T|-uD$aQLVBIPVnKz5(pPxi`d(0U7C5@~K+YxSxp1S(l*pSZTueQ>xe zDL-6#5VT)rYp*5mi_tmt{Wg7{P1R-7?@HX)QE}cn-byH#jxS~#3LV!(+Ywjsf)>fm z_z<>k)XtgyuN&xt9`8=31O9(J-JZAa&=BzF5G{7^ISF*mPeNEbh-_c5@)WwDHQ6R_ z>i+r01Ntx>+AlcB_;h04Ax(eYewpo0F(Brjt=6}|@<34L* ztyP&qPVEY&q70k1?c50%a-q$wIxpcyY!+F*Ug($V1+(0tO|kwKUXX#(jc_|h^Wy{W z#B0B&?LXF^;xemxN@%Lmb*!g!h*pcI4#z)wgO6^sf|2!p8!CIadUpDr3E?k@@~*w1 zi^1yIp#&SBt(YvP7@B{vnoIqjE-|ZnhKg*wr?)>fxM8S=^Y3O>59gCRNFUdHUYrZV z`43sIx@nqRxjcRR_AG{1jXa)T7sfjMZCMzvn!udyPE?)#)+~|_c(LL9Z)qWY1X=aO%K)A#gV#p(Qd z>dt$G`gF5bzUG79`O3$J`r+RD_~|cOy0G(7tq9%dpV*ChFI&-Tud{CbZ)pWFL3DXn zOTI%d$D(KB>S3R%j+$M!^SkXHeX)Az(DugpOTaB z_qF3>I=ue@o1e%?xr8=Zm)%!P2lwwew&+K2yzdqJU4xWNwVOF>Tgxv>kogIszDK(+|kFU^zrLkt-o#ObSY0k zYxaiQEyAy373zhfrAC=EJv`!zj2axHKeUsgzILii5*ZaQ>fAHw?r5VTIY~#ApSAOd zqU7({&fY~or*%I9en!KT@y<>gxR5!M(mD5F_jM;DVezIFxzIL`AXCe5tVImj$i`zQ zxoy<}cPO$>aW(O924!#CyHb%JM6ohEhB8E%4u8_VLrP^bd|=-FU-^})C32dlEQGhV z^&KKQ&?kH~yh+{u_V6J>Xgpc=EXX)_sgw1ve(OtD{%E; zb4Y`(e*Buwu!*IqC6TYDX_Q6hWsvGwbSdCo=*k1~*F;se^>CXG)Bmc-wW&Lsj1<}M&Xw55$$V}is0o)=?)u9R0(_Wjz zUw~D+biN5&U9zvDOn2Ews<>WIh(`I_eD5W6!{YUW`H7csW|#In)sl3TKs+7Ed|LsY zkhzdw$m+mO+tsF;a`oJ!XPMdB9qZ4nxQRp@&B`}(jAS>PY>Yp+lWaR~7w$^CAR15g zDj?=^lN{~jCI#48XwpTJms6V*669~?@M0^Be{V=f4GDC^P3)8`OPgEZMq+M3gqV=w zm}02aDc*vfJ=uC?Gxf$oV;sB`jfpHe?&pn3@w1dGfM;a89b~7CmeDs%8{%0Kq`_v; zI7R*(kjZYrLa}j*SrK=jbBjB8*meiGZ+FPKZM8dGq)-#{maYx@XDhUMcMLm|6WywX zVe-<}%XY4a+#dg?R-P$8o8tSb=tP%IrnoJsFI8PGLqjcpisvdqYH{{z!QJjHq!V0m zb1#bQAnRG3tU>L#m6n#Ar1W2kG)n7s1{$!!g!EJF02e)W7q2_kvMFT8PRly;<&p*d zC()eOQFVF#=8v(AZ0P6LjbGK3&^M8gv=Li-n!b=W>Z^r0Wjo%O<*lGEGX*i`?8WUd zGgL1>sxdq>w(B7bfbaCcmuq0Rb})nYq(NF}dg?Nw)%l}6zvT{=cYEG@%~aj>!4FYj zg9ULXuh^PD#;5!F)?efvR{86DJAI&{lhOi8oW-RCKy<&KlP4X4h5r1Z`i0~7T?1do zsVvx*;VWwx5vJ|=H*m%LdwzB|`bMWp$AL4fsk}pLuDi}VT*@!`d5=C$Q$1(*)QFC7nAA7TW_f;eK5Ypf6sgPMtr#aC7wq zC4y!hZlaMa-pwPq?y^YK@karb>Oz$5EnVQ8%{HkAl=qdXLq^nCV_sy6M<<2dlL*X2BuTpK5s`yB5or?P z1P|9hC8g?>aG9)xyP#4lt|AD!Id*}_Nou=0Ia$Vv*T_jJoXMahCkZ|a9{B)rvcE1l zS#HOBAUT<%puxijl9S0QW>60%CzCy_6AvUO-4b4loLnO~sDYeJp&3@}o!Bv|d9BI)ba`~-x9gx>`_w~l3boHWi@3wVCw{;9mAl8z*em{(|y{&^M3aQwr# ziIVZ86LLuyNfCbsp5`n(7yCLzurQbpO%f>0-W%TSH1WJD_`ZhiM68cko zV>2ys>Z3=QtWBluN{1X0%fzXUNo=08t~oHdJj&KHg0uGc*NRAn^-9+t5_fTxTHbmZ zTK#p=|gugUHM)ov@2u)ooY(EXBv6@%pUAzCrfeV=by&+We^}{zAqGYhhn=tUtG) z?+JfQ?hhopZ3}X1{?otnd}erUL2dz@K)Svlx6*I( zr&TJ0vD+{%ue%F!cX9qPrmF>8S{Vy)dN$E`#H58Hsf{J=jYOsK2fE1^ z^%3AFvo!5hKK)biDq(H;LN_|?MKtCci;kg z`Kt;+k+{_H54IDN%8gSnKu@)?SRg$cNbzg)SK^6y0&bA181x%rk^xY3lE52hN2m;6 zqpgkD6`oMyP;2%Y+NsJ2QsCP&V`Xg+zx@k4J|Badr9+TVhyZ2S_>gc5Qf7_E;L@OE z$N#OD=vZdHoyw1%61<^#6Ey5XEQgC!j6s7rw=%zN+H$FpvE!$DiHOY!C;j=Y_sgBI zi>Nq@*t&ohO7p0kN#0Pln;OBI^~OJZT@q5uC$+}^T=G(9MrT|bhQptCX4m?xfHusl zi5@P_y-w%OhO@uiLQ1{+J5NH6e6T&cE?wq5rnjp4`nWEcf97Yd8}oqUekNfK3lH!J z?d{of?Cj5dbW3MHr#L$r`&?^mM@#>?{wq@^@o$6Z04+CGHv7WuR0H=syHbmwmlnbE z(j8)?nQ}yYr;$G47iij_NGIk=A=n7>BjZqiPMC}XrgoqI-@hNG2VFJ(a(CMK#*XQQ z@gMY9pOOQuJXyZR?ynX7vz^)3cb?jfh_zPch$h-pznR&m4u5 z<@Tqwh{UzYCKSjgq zlwtxV+X@rn6P*=SmDbZ_ibj*E|ZkvKw0rwUJwWGN$MCqP1 z;s%IOQ^@416fPe&>;p@$hNm_d0KMLXRW{jD(Qfjjpq=S1?gQJN5~aFM#z^D`%A*OK zLO~v6E(&N`_6*M)x#XtL0ugl*BI-sE;YdO=kQ*X4QSTd);h4QzQ1q}Nw^D|WB*Vjr z0Hok$VHn8Vjq}}Mu*LI#@VW%s!UdUb>0W@X`Qv}`T%8m?fWS;(D6Q0_0)pKyOKa5I z=LjoQK*m-yC)yL0Rwf%%zy8aegoThvAu(pCpNXoOuaZ@ek7B zXqG)knl#pD1k7^7?pI`Zw|LL`z?WQ2sCrhU58bFCa%{2jP^!YeUm5wL(#&*1M@0k65 z3a&=qpWeIHj%W6+v*X#lf4g)H!yDNvF)4oNQzN5ECn)>+dy}c2KAMNd7Cyw9N+uMN>gfAQ4 z*qT3@Fu18&u!LC-#9r{6V_4aNrHnc=C}UX~i$G@l$oxxxeoaNEC)NvkL;q&an{{Sg zjxC*L-{|k3fAh)7c>Lx?PRt;PAu`T+s`bbhaa@MJ9fMNUY#KLz3qfn+^oP1d(Fm={ zwF0u&g`W4=jO!-5Fr~2f&SA(3&1oPaNl#yTY!C!IVouLv~?$%)hRIS{kPx z?{t(SD7edi$He9U%dF}05$@6`A4qsj3{=I?v$*H#^72#(Ws zC*#R6>#*;@h_fE^9<=`Y>A~c<`YVuKK(=IeALC*7Ovlab)sJ`aBdD?Kjpxk`M0$8o zH;RlbJ-09(k4V$9oAoV%1moQaCn0 zFPRJ6SF7Znz1iS1o@2Yn+X+L*uDfe*9M^gHh+4qg1mvUz z_Oms9GUjb66Et1tQ1lpglL?wD{^d?kp!%^i9is=+RI!#L3ZQQn3>dm3>h|eH-tzy& zi*Q$g)P-@>ZSKk)5Ky&tU0_y6d0Y!0+{Z5>{8zLNKjLVS$eFMLhGuQ^o(sTL;x?)aaND~7GA zOs$QvcE{h>%>(Npj#T=TCMJ_rwP_%n5sAW-|dX%M%9ME|W89B^v98!+O_NM$mq| zEiF&4D+)lj)4Z-2sO4K3C75p&oS@%|5v zuyQmzjHB6M9Cu}haU9DI<9JMV7)Ol1Q#xLI3&Y9rx?4JDbUZF%h$D8{?K(0F-=ZS} zb3sQ4rkCnyRVO&I@5JBNXIQIm)sX_@|DYn0o^&GVhx_bS)<7hcyOqIE0tT4b%-FFe zGoO!xfpk0xNYL>{u#=9bz)t21fXC41qhh4_1dbX7=}e@`tGW{$dvpkCFD*P=W{>{r zuSi!~mpy{l>YjiB!W(dLgMI1@u8#7P}(KVOcJ z5U2E6;W2s79AJOw{4>L{+l{V#|3a(n~>y(f%ZOLbemV^a-mOX$G9UfM2CXV}| z-iC5Pcg#;R@joT_PWYeN+nhKA2^O0!u`SQ|*tL zy(C0ulW1d6INJ0Z4j-AWq_6#1?_SW{6N#J{`kxAVCsIX=i@c6m`(DOTH@FAtM?!AG ze>_3U~0syBu31KzhYm zW-{ur=2%ofylVXj9be zlzkDxG!E$Y!{1K?eqF-KNN5fUR;Yf;9ShR|@8EajGJ{AEWN&9OvK zWF9o=5;B*?D`~iBshHG3yhpBCG7b9UcV)H{$|5BvV2ALcDOJOzp!vh65{Rv-VZx+3 zL`@o+{MrK{IffW=;Q&3W%2C!*7&d3Z#daY{-gASI2I3M%0#Pq$Bj^R;GBw? z1Dk(lC$WQ0P0&?N_hBKzguIn)hy4*%;6^)(*EOJ$u&x5aI4)W$h*Psv3?}kB7R!y5 zIJKglqwniB*Y7IB+|fO@1axGIql;vjSXLfZG%PSBb`OzD0TZ1_*OYgw80&>lFuOWT zJOhr+?gMBO+eQeTXBL2sb>{*-?vu|g1Qtj$_Lt1#A)&?(h+20X>+2|P%|QLjYb$a; z;dw>juZ`!?XN#EDs=x3(*!C+Hss7tnT+dw{eb5?T`IeJM)|y>>taJD5q0Mg^{l*5` zVX&+n$_S-OJNVM56HJR*q9mA11tzJ0f^#UI=$c;*-N`yz zA$)5K?*qsf)3Oa@jPZedj}cSwfwt@A=wI)2wq8Ltk(C4g3q! zZ4(40C2rFPB`XQTs`A19{d9C!q5l5u>9Ej=ISvmVX(qUy-jNIG;X955q)GijT0=WK z-P!KmHc9yQjQxDKRFi=va6B3M7Whb4dLl~MNt4~kaS527D^1zT2zU)4p>ed8dVwc< zuFV+c#XjU7fJE8J@^gn#>bb74Yg-Bd%JkqB)@F<_v5ng>~mR7 z7|<#1z~31E;xKvdT^09O(#0ySI)20SQl{y0a@bCEmAmn`aS@Xo7GC^xOYvm5hc==Y zc)YvuG0X|E1`R~rqRPbUW)trkEHb3dBa>@ZhUSZzl!?dDOgxS$H5(79k*vm`@jaf> z8+9H^XE|ykGN6j+9g## zO~nVqLF;#E2%RquTA$Al^P|tVhPHZfXsd4tZMCL$@?;=cq4;9ZQKui6_L7MyJhYHW zIkA$Lvkq0!DvS(nkWxSrC@9Ov|@s9+;{~ z{9a8-gb6fCFBYpWHxD2aM_B`^7pUyT7H9)sas1n_E}JqHuqq%W9X+E~~G& zMPX{yr1euI+gB#VUC2HWsoxsM3yfl6T3F1F%nrb{X{m|-4UHjpqkV4~`C)Xpzi}sw zj!!(H$}>kYI+SJ=p$4mr4oSOZc}9#%K{p;|bnJopP@?|sENkn7GaMCDi{S$m!yBJ{ zz^sZhvMM}0#H%t<6*N+fjelYvU0df=WH;?Il&Jw~+a15LAThJV(?iZ8ykv3B+LP_X zPPq2C%}3`X6qQ$PGYS~k6#}MH>j1)arviK}$!i0WL-^QC)GPqY*2s8j(jb5|{EM$Im z=bu2WT1g44IQpA=-)`_b?wNRdDi2|*{EKT7=YZVQJVS+UyRZH4#|W6RQ2KQP9FBXs zpjHy8WK{_2Wf<&`0NXMybIcFNW|u|4?h*_pH_S$&HU92y0`^IKB8b<|>D!6;TFR-~ z4Kl;VT$Ib3k~|)Aw#qZeYJO)K06_lwaR|QMjG#7O#5hc8jxXFFvZhVzVDh zMTKTu_o)i+ZK3N_?WR^}#?;yeq~cEV6RXBl9I8*2hKmF*fb0jTIFqE@qJ@neAvl9Io|LJ>1kg;K#p8_hZT2%O1d&I9 z8#ZQ}ck@QUB_i^+cKfYPr_+i;7-8NR1M)j=j^n1 zNA-+}Y%xmgxKjMOmJCKl8vt!e5tS&SYis=GYYV@#4WVv~X3LL*0`J)?bZ&!B(+J$I zlwLjjc2PvC8YHR`O=UmwJx57#f55~3mC(y4^$YV~&W zrpwQ3z+=;%k|K>pLBVlwT(dWL{!uvdaRhYAL7noFxxl7Q7Y{`GNM>=A?qFei@2U~t4eq^bnS zR6Q#2uOlnBopE|OsLgOHR$OJF4zh*120-Y?n&4=xB1a2x=g8bY&W!W;VvZJH%n=K8 zDZcnis^ih%C9jnhXY7n5JX#?SZ3!=ukjZEyAvNwVVHFS=gxh?S)`6U?pjPw!Li9a2 zkrTvbk;HV9`&`tZypEyr}m5I)mQ*h(V?85i9y*Dc3$%L4|KvA~6%YA84nNUB4P z2!y3i#*MC0rCOeWCDDmuQq%~+q1yFo9#bk!VUUb}pgrBjR|<2;V~ngL(MjoG*Q;it zUc=vrIY#Mw90Qx8?V6Qkv3$2#S=zXvVfl_$FJD_Cp_E6W?P|*;@jljYtXC5eRAly6 zx}m6~TUKv)qpslUb(1nyZ*55xdNzBfy-3-P`_Gg6(Y^2~s@MF;Ht2)~xTo8!|FC@1 z3Wcg0Ka7{k%_GdiREUJ}!!4(z)+8j{rj!cBftQtH{@K;w#`wG2$u=zMG{)Ht!A%ea z*M}WwW;Q+CBxRatyag$fJTp)M1&vopnNfC}uaP}Qte$CJjwWR|nv~&)G&!(}2U%pf ziU%uSdmAj3Nxn+uJlf;WELdRAmay5@)6nuyDQtG_Y^H|z7w#bU7guCp68zW zv&~88bxXO=+jz>gIcf;}z*F=0{F3w_O>0&bqA~aPEKd`xmt>`D3wj7R_NL>7zR(Fx z!mf!@To86&DM*FzyHOAeXte~X9_w{_O}s@JmR`{oH+8DuAg3qlZr8Q#28+l@4pgxc zZa0V!#RT;5bNkcn1`FzO^1*l59n57nERYYB7R6AGpq@d}s)Mj-!)`ExT4CEd+lJCn zF%xPf`9LV5sK@{w2apfuUN>%Cc7xld!@x&O=J5xfpVmhK&N1yp5eGOQ&V1emIB%G< zL`M4T6gck{0f3d-R4|lNo!Vyuz*>PVHUmMgOTqD{$;LZzL1has>`)Mu-dk||mhH1ndjJ(2lur(p?gG;}Sm|ybP{wg2z4vLqtpLv7Hur^~!T(Flq zz?|GD%*n21?2((~nyk(F336x@)>Ia13;Bwgud8Os;D|!av?}{L*<5dp z-$xnmLng-Ha8brK%znQEL|K{`m$vKeK@+2z5H8BTYlE%J8bn!*U#QD64|QFZWv(5` znQtWV*PJO4w}Wg$0T%q4WSce`s_k(!v0cfIDBJROMUzdF2TT_&FyeX?V1`AXrQFtP zDJKgXDYu!VT^1h!#;OGcz0#>he=56xobrgyFwVb)VESC z>njAbN25YO5u~WaCCVX>jIFzg=fpqipd-MeQG{9WxOs0HEz96C?aiZ7zb z0IPK|MzMj2#Cpy&WU<@yq|5Z9j;oXMRQ?|$J&c#!Vi<#$6pBEhsRT<6C&5dm;N-4t zd>p}3^Ojtll6A`zzlSAyV-%KHTCaM07E1UnsolY%}-FmnttKiQva~U}#>HuS6XPbMl z`GiEGTp5`pp^RH)qgrvRfyYYYGFqh?gvxOm>zy6T^&$?jihisKkhEfC2Y;0m9i}*3^ zVby>-j~DfM>KLPI7$RYYbGC*L+#aas9(p=t{sZs7X8h*o$fqC-&pu6gsja(iQD5#+ zmOx9CQSm`bv=1F+v(|uhno`j<7|*u6XAc&ewcgZyUE7i*_WJW*|Fgg7FvGNWxh%fx z^$<+dT1qh-L5}paj)snKp{JAtMO}rzQKq_X#zNH#@a;KHbuMv0JZ9D6!Kku`5sRHvv72JMl&+*NQjCT&Z0cm0 zU|-y7DbHiVrj)+7H?r|HO5|WhX*Wn#P;KJjExr(el2ST-W3fB|EHG5em+{Ya(rgJS z>Pl*!im=jBIS-2#`hG1h(3gMwC<>$1x}~K8UGvZLX}{HaQR@bY?%X`-v7&kWM4=e` z;FmEGQ&I^NGAETRPsBHNjw&mAHCcIx2uZR~0)zf$z`*1UPFi>nwyMg4B2+67%J58k z{4glR1uP?w0&H3g{5Q0=1I$Ecb$Lgb0orVPeJqQ2szKiVPc7tKH2s2)d3udfT{BuL zPAS;7tpb&-?`MCv?mm;cb@!{LTT_DdGh()mqFb$&(LMLhE`G6l{;Oc>ZatHx?$%e$ z)Fq9~@tbRhp07IUP^BD{1}M(G-`shiBgwFMy_#4LGZz1$QaH1bu59OBiq-ItRlf zIyU37Mgz`pbZ3?ImOOh)ArGogMz-a=Yjr}*P~+1(KKi_QS4sRHp)h~^gT-eXQbHmO z70#c09os*S|DdoQYR&VoJH6Xo20Z!E%|Gjh%8E2+QHry`d>EJ&nLRI9k+SlOf(3** zgomc8XI5-pEvMlv-MiLb&N5zX6UYdv;W zJZnpdAa%OusSzJ5V~v=*g_TiRuj3%ZzWdqO8`)gkS6}=ut{P1DUx_aHNs5!N&n#VG zj<8ZP1u=LumartAjo)@MaDk|i@~~21#@%HOu&o^fgDAjzme>cQx6+y6of$t)TMi6A|)K}atNBb2)`(fJ?S9Y<4$)Y8nZWHfoQx(3n5N7@8|rFer)6# zEjtksh=DR~jrN{SM)DmimQqQYH$js%8ORul`9rEK{&lTZxRYk>qS~BA4qbe#HUISc zl)Uw!CEziC>W_WDc8lCjJaPgA($nK7Z%E^hO3uOf>mus~fg{x`Ra^<4#Kgas-fCK9 zCmLN07PM!y8Gvq`kSlXcAHckKB#v=m0NXl+IJR<|hqLY-<(Vb#k~3`L-P!$Zv+6ue z%xsjbk$|Eo7@-)B78=g6Awv~v>_^+}h645*RmU0r^~kg}JTV>j#4uOJ|9O&-YRc_c zTh&;j3%YP46wI@HoZp0((@8)Q&dOfJZoEcK|2%3BqcgQ0TE_a9q26WCueCFDZ|y{&lYdvRKL7$ zCZyMJAFmM764r9MRl|2u!#8h@{&a;uxD?jqt8UvX?(>TBDQad)8WH-#{PO*)j`rHj z?@4F;N0;@|rFfM~%f+jeXvB9>ytM75!ApPUs*f)s*hcsAUi8SL`z5(j8$t?8PNnkp zUjZxF6eF>vlzaDVe^t0qb(cAH%$3rweWNMcg*;KM8zRG)m{vP8O4=y+o{Bd5R>Ai+ zn5wf`MYEXuoW$;rd}hdUsg<}P<(s0m5rW@O?24S1OyO>-$d{brtpX66?@}Ip5Cbmp zsX(TIVO}V^##@WHSZ*)f`Aqoa67p@Slza{cv>&-!b$jBFtfQh?2{t<}?#TfkxH#&q z=s5^r%B$Qne>`nJlddv&jPRf+BEay^b0K%DapjM3HyyS2FTVFnc=0E4uXetnbt(Y1 z1<{N@o~ui8W##tAsV5cCJwc_lIN!o(5|oM%n$k3(!z}b~)|tQdT|({b#?_G4o_5w4 zx<;{0G76Y+NXYdXE?n167hi#T`r7mH;Xyu}JU{xuwSX2i(bkjV?U3T*AKj^I*min1 z?QK#?-{RdI8dg6Ux*Gi?5~>Lx97biVp>YBf${_e}h1k6^J7j!%Ku~+1PFvtqR;Ocl zsPbYIPE|)ybw?DV=%LPQT2ut0M_$X`pt8FMnWw?%)d#KJAa@6ewy_MKG`UxkyW&pw zDg5VV0C!UOEhRW8bbdDdv&9FgJfIW@bYv?QP~`KZz1_kj_f1Q=T|ELwxpH1z))rq% z=jka1H%xSPFHK&5z0g@V?a9+|Di$+*{*PY6?u!a|3!%g%2`gGxKnxJ2s3#b$K(Dw2 zD3X1^C*xN?uMkX0M6}hH^6;DcpZ^~#6%J`+0&8px`o6c2+qtx2@*%JK4x>e6WBgnccDFZ!FEm6)^F zD*#+SXURW|;J&UNz7*KEX{cyZsG?GwH<{|npt*)c6pqW8#*Z8TLDQ;|#)J8B(JjLcTJ z;+p{;01*KY;Q)Yx)nM7THI*``aQ2KZPLh>hs83EFL_wmVVVA1mnm>C{%fQ!;92`vV zM`i;em<;ChD3x-rn9Q`mdUO`ifXep}Zkh4wqssr}dfnbEZ-* zR+F9iGs2+L22B^QIX`;Oimic87q%$U&WxRdcWP8-fl!@_wV6@04xK|>INfA{l#PD4 zf%vSJCyPy~@t|1eqxs>C4-I+Nji@PZ=<+P2FND~}Xhty#iWUg}b-?Q^75ynFhCtv? zZ4MkZT}E(&`4d0>rS|x}-E%V05&bSh<58+trB24Si(DrIX0%aT=~^obS!IG-^VBDGH>CfNNBmjdanzR-q@Y7h zexw&Ze?yY$HMtsfTBu5d>=Pc&6;6}TW)nJMVi zbw^<6YSSQM6H!{Ih$>23q4)~Qzgy2W@y}~_)@3lw`v{l8@vu5DDQQ{z`&P?GHU3*H zANM*5N}f1B+GQ=F&N}n&-5x*uoa*C0uYY`lef-~B-~k20eYS0wUgO;%Yh2n=8uX$C z+1j6Hm1xLE3`hU%t$Z+@p%dRNNUog?=AB!*DjhoiXWJ%tss?YzGxTz;zvnagZuGN)0L=)6bH+h0Z)Pjy*wMFNeC~`8tK5<#UB~o zJ$r)ESx+31CHK_#wZ&?kCC`G1zOKAaT`}d3flFQ7#FW>vvJzp+#f8GOj4Z~{Z0LJ^ z*lKWA`&HQ#ZPJY~4r`F=xn`8J?_m3oz~V!$OxRlR~j?rl|1Piac- z^%#<-RBnM(rYTt=_YTQI{ang@gCZJQRpbt7F|+U(Zc?%K({l8jDQ}l@rluV~$F7>9 zCnnkoN89}EkslQ{Oh9o`zUw(tD8elLDdbK=DCQoh03*jjP%P^Zbum1wkh=;WtLX}P zU(WT?Ye=y0-(pskDbab$%DCGuYuTGA5tLSd3p;|AeDA{(ab#CRMe6I7$x++pTSulk zPNI}zN}r0d#`QApN`R}4E2&7XV*xpeObTPET)K3*h&MX(Jg>_2G9i<-V?U}9+Ra&+ zqEsOReDz*2Z>d7ciTjx{LuS`GasZy=ut??h`j4BMwNFScGCR=w*$xgd) zpCLDThK9ODwln{oKUHI?juKW`i9iq@Emj^A#}U>Z_>dMMvovSM)2;c*m*@j6V-xAvcU#p@tw;O>y}b7U zsymWAX{A9-?kfB4LV`jUTTJfOyCsR@;-55W9;!`?L@j2sW#a9uZ7OB zR4OQXP@W{Zhfbz_s;P29Jj`(X?axaTTn4Xt>o?Zpu{FO|!osW~57bwy4{%%qesF4m=adg28&%2sN%Mcw5VV1X{H(P_{jCxr|_<~Qo7 z0xUYJ#%+ZZeT%vu=rtQf&75^|k|i>2A2Q7skaN~YE+JGEqoT-0-p!|BnV1RGyi5qt z0)T1YCQ~bNEnBDsJuRhD==a{LMN+RZWqZ;zFB0ZH0FU6(k{9 zEEBT>tQ@ba!^Bm$na^zHQeP%9rM1nCmt?py#u`&*qA8IWS51*>YIu#FH+GvtnaV(b z(q2Y3a!bin=ULa>GZ?=mE7>@(UgfUn$zZf`>|B`Y15aX571YGXK)Zbl3>!J(Td<24 zT?tGLU21FJ?kuKWC_+7~eVa_nb;d9>nHG!Am(~U#3$Zdr{)Tat(^Lwc>5U&7C;7M# zWwb`<0xaudkd!hHMb$R!8jOASGe?T%OzT$WUA=hRnhK3UI?$&?h_`%7K4R9>*{8J5 zAm#pVjb9HYc8CEjDQl4>%(HDP4<{Zu*}6UXslpSKbV@Ps4cW#0l&4OKyL3_hezA;SmgqsHkmx) zH6`?|W+U7{+Uj`2e!m%xKY&u+^=@XWFDyvkcw3 zK2rm_4U57h3omW2go!;g`hb@N1gg4?wvUKHh>7#2stT2iR4Do%W!MCm17*D;a8~vK z2yZ1+#_In6*?a$B$*!xu_wI7YEeJQ&9aOv3OZ zK_-4=5)2F=5)(gS`i!BoqMn(r>fGPDbAI&Y z<3EzGs-*;bY1=>x;j0qMS37J+^mP6ZyI02>QQ34%^?0>w^?A3u*7j^}Jm7}%W$)RI z?e?rD&UO!0dR-XJ?QKMbEgtsvZuaa(r}B^f)ZJDAHux>}>?I1L3C5_{vvL@XSdaDC zTD+}ot##YHa8vEA#GqVk0K@XS6wPn$VWK|Rq3Aelj9KQJ>_TapGFOC5PSXaZe3Nj+ zVuONUZ@)o{FTISA2C-3WD`!b!v+xO&U6nmp*Z!63R~W4`J9`~GXZCh!qxuE}BE;dv zMqSx}>$}>3GKIAPIVL|B%B>0Ux^>u}Bc_8>aJ6V9^7J zPVSKLv!pZD>boUD$xmkr0#3Wxl z76!6)2Hg*HPFnjY3?z?Tlxx}Qkk+s3v|$QUh*9A<`h zEE5IlwAi1FV)5lI;rRww5vp@vrw!p($Led&#HOqxh zQQQiaQCyeodmW|f>38ZtucOD6+=LrQ@gzt3#{tZBzM~MySaKd1iZafnt8VL2O3AVm+szN{1{VCnb&&h^ArHzH&O;=nrZ zJ!$MPMJptbD8K`8WbDi)R?L?FH%Zlm_h<4Nj@01~;qa zFipVB)n^zlM-H>qzQ|Z!4O1Wvq!q)6X=HIyC>DZ#fODO4pP*Z6d+V>Zxfkw>Jd*uR zx%t~>oUq?ALUYQEOox^U%{MS~|1}jaaTmmuD6w)xSh&X~CORu*9)3IC9y>b~{^U_A zxtX0tJ`skw@s;k2NiE}daQn2+wQ1wqEjQwpF0i6RC`KaKEmG+}(*W2lNL1VGDLVy$ zs&)O>AWqf81x=;wOvyB%_uqA5redu6-QV?3yxt1hs`si_&fQLEq*K6&$s0#WsZBmZ z_ovuhxeS^;cK75R%-O378VKbZkdxo_7w>!Ta~T6Z)){)uH@|!G28uH>A)14_5GlWV z@LlKnlkb|Q7?I+MOvLEj6ubiC5V4~V=*m!a?K(@q_1o@?$<2v5DkTr&v^K9@FC?bBS;G%d2cj*W=1 z+yksbJ<=tq2vf3jGaW5bfun(690?D*QRh+6kLZY=pddNv2a4KPr{3eWXo$L`AKimv zePcDxy3uVA-LbFjwAu*i2x>T3INwj?0VI_HzjR+3ViytdYmW?a7h9jsHdR+t zMLYrf+PvXBUxxgusU9$M@PF%$Bn_OHv2X$;cuCJ;!t(4Ku`;F4mOFi>LY72$6Z`tiP{69Q1HobAE3+GobY$zt?mf;boX= z6dL30o4R7H>i7GpJ7UBP%z?oRnX+j`8TST29~bxBbM7?3S|i9vsYRy>v;X~9Q} z(`Q@?3?v0M12pG5^VPcApUSINiscR|u<2#)pKkr_1I}BaPjRao;$dF zeHmXuR)gS_5fPAJ!iWg)_i{nAXDzWD)sDpui)SSphly6$cZA@LYPbH@DV{=HO!5b8 z+)I7$bv)`}hs=s| zbf6a7UxW(=L*EKWb8iZc*JTI8l1x=wb(v5PE{g~NrqW2&Wfu4M#=`c)$@d&cta{|M z5yB!1=NMv4qW707hQ@hq39C7*-|*TNJ3z@@Ut;&xTNmT-(?|G*9)y=?07%1Y$isOU zmFsYSjzl_)pb>qz=Y4?S!)j*TsMZ_q_ZrF>XD>zMWtPyGG8>YUANMOt;(eBFbC^zJ3 zwS=EqZe)Mlynh=m-A2!rsRymE$PHUp6vEzITB0v=Eh^++4FQ5X!NA(g;+dj#NP@V$ zo-MO86Uhf3#=Zf$qe%`Vx(HL8U7t_!FHogXwW5tA zlX!Ck;I~hci>OK2>t<9rWuw~jMxtyu)(L4+b_0|F^jk?$C_D82nzC#E;FZnDpoN3E zkWrP62u?s%TJaP9nXrXj=;V*;CtN43t{W5rhysYNNu*&<*@gBBNB? z)s`XUO@7Z0U&jnKtU@8z(orpW@;04q2vhoo+@XN8NR0}XgmpC<)>kO@3mJeKrWf6i-6yIoRg z6$-fW6gyQs2gVf7;Wc@VB1ag~l(}B!3Q1GlK>iX8HMuX-Ps)U&0E}Bx5R|bWgQugDGaO7<4KX~6Oct~SZ&nKnqo#CR|T#W}<`LMwHM@$$SGCIbb^i!3=>xE4nX z*W!pQJficE?{e;zXWmdS;rv&g96vBX?6q)>_6|ToBH3t==CT7j1)g*y)jHsW_~W_* zkR?ey6qMi&V5E%lvDx6f9D8|2c#|uLsSny4-}D^BQiGYartyjWvpVDf+HuO}Dp?77 zw{iFiVo+XSO$;?Nxtd+Y-nXmjabha2Xw)%u9{0t*HlAZVQFiV`?I947g5s5B|?Wt$rk6nNd(TDMBoUXu_6&Zy+I!(if(B8GpV^^ z$rDw9^h-UINYJs~SFSdC0eOjpE&E=8uYM=MS4RQ9I%1jGvEwR-D)_>HB;0Kn>%7vn zXKEScJFPPzNw-7h} zZq+FdLKksY ztI79eQ8b zBl&D#Bu4`yIU;8p+gYM%{O#*RZ?^3AV>@nk-^8g~M6=>Rz1cf%?i}vC!opWO>up+R zy)G;q1=P3pYG*xEeWOTzajAIc&P;rRE??-__B{T3kj*4#iNF-wsWQYO3>t8O(3Hvd zWd2^#&X7zblm!?>+PfA<+<`%i8Vn*uPV*#Z5ZT~!j0!o1+ltMa9us&Ln-zK#r)Wes zrkH8$3mbf6tC~H-4GFvsmJ@R!pRd2TZ&U^K$ankR_3P_>8hqU>FPCkXXMm<{fx+3> z7HkJIK*8)ShFRO9mTJdr7yPxt@&=_c)7k17C@eKW*Szj(C@fE_hizvTCT-JMS5w=R zzT*1Gvc9rg7UnJ!&)5k4nC7Zl8m9BTq0?ssh_~a21!40 z-idyqG=|GyKgo6s_7irag$kO&Jnb*y}hiE9Fs!gNff4#V4=dw-gH3f zh_D4%d(U-@o0JDxsg8EW6ikl`eJcS80+zAUYTlcg&91?FE0jzdkX)Y9-dfbY zRFQ8W%P8~CRgJAfO3{$pUj{z?MDOw{xv@Sac(LpP2*=~%fdt*Ueb<+1fs)#rym6Y= z^GZciS|GM+y#if6%Wrl6)qAU7rbK3&|DXh66&j8_B^u2A2l~9GE;`J(k#o}>=I$?<>8l}N=pt`d=c)%HY+hP*A2 zrgE$uXcXU;(J051;gft~C_?5F6OGoiX{}wyA6x^NZ&84Dh{Tq|%OkIa)uASss;{F; z6X^INR!GNNVJA9vB;Gm#TRga*d9b_y)4p6BV!ZaZGhX{M7_a>ujJGdZHV^RBW3M+C zAATusLpuZX`?i`CishsQv+#dz0KI`{`M${Q?Z;LY6AOr zIZ}hpof^iH`-GS~h5%>wy}1>{ZY~{wKk?-^ml_#uWkK*Qce#Ei9J2kxDvO9;R;cW79K7Ax7q^cr4^&K zKckj*O`I061lRi5Dsc*%QQ;L!4A>BH;&0f1#kG?s%j1OM+5?YkC(Q^i3LIy!GikDY z2UFkHc#E9|QvgxWprYGry`aW!*&?J}!H6s{RvB0Y<<#EeP1X}L#t3WoK8x+ZSrJZ6 zC|*6_H+obLXvsJ#YwMSE;s&4SrIUddAt#Fmld>Ekz{vzanK`p$1a#o-T1uHY9F4bg zZ0S`pzDn=*XsUL8HQ(*Mmua${aF_GFH61KjZHV90?g5~hSmXN+TxlciYK^^m7RK(S zD)-$vKSzDUkE)DO3n+dZp{#9dNJKDM$$Z6iDGTdh=m1S!LCA;e5Y4Qu%g`0hHFO0b z?&u2A4?VbrE6>>^7GO<~DPcLgY`aA5=c#*j$ChB?Si&H8D7vG^MOYE0MQh>xr}REs8~| zd6BdwVeWP_`XK)KCl4smiZd3TF*rJT>vh&1v1LXK8#>aj$R(l>zu|>jp?k=6Pd@JC zf$Ng`v6QiZBvHe8MV+~{ODCcPOUmc++x%{S)dDnK(k;MernZ2mn`~cJTTo|AZINqG zoLe6AnhS|ItMRXIVHvJ<4V1KvfhAZ5Og1eJ_#bxBc)s=bQlCb>+CV@S!eH+I=e@6!+g9%hDXTQ zM++wCcx#97d8@K4%+jq>l|N<|YlP`}^{hu|>+twMCv56fy-b0zm=6|j1N~bpD)Xq9 z1Sz73Gm!#RQ;hFlt;{n`J5e}ViHz>J<_ZEYs$58>i& z;vu5mPC#@klV%iMnDplMCZ{v$Ez@u;rV#2rg>sT;dkE1--ng)3kFdX;l~JUMc+dE^#)##Zucy zwX-y@R%;rbM}A>ng~M*vcqQ5j;d16ca6n;f*Dynq!+TyS~(}G+2pJ;frjdOx+XOyJ;NjCnzv+QoCDc4{Jk(-F%n4%dW zUfzCP%1StHkHFB&V4cc#vWD@e`u)L{Z^7yShxsnYY& z1#XyC|IkK&ri^~VM|3ftq}Q+^_Q3sFx>9MVrq}SEGmL^8m`>;0o({Q1A>ut!T66`% zl$3oiL~v=t5SJWME`4nGX=Jr%Nr{q(mPnK&Bh$&piGVqM=lP-Z8=)zB^`sZY+PvCk zU1EAVPCwNry-t`GdM@IY3f2p@h~M|r4br7JZOPlkd8%S3#WXT8wG$zC5;Ofx$w=*u zW$>Sfq-aK>TySVzDEVh%@RZh|%y#^zb~t5}nM)B2JLH{U6_{3NjSu_O%L%QJBdJ~c^_ev1LpoBS^hO;?cRr#c>CQ)WB+dDl zju0MJ!rAFQ(w=p^<|X~F({b{W{x|3docv9-p^n-hOa09o{ZX5Lp;2F>1dda0kY;KzgsThEkBvgzs#I7oz=xygNRvB=9stDx+9KiLnC!@OAy2$sf+fv?D(ml4*!{* z4*wb9;>myJ_~=#}Dz-I-FK&g4Vk_j>*4k8gBI0yY_!sFg4h;^MOCR$*lWqL48K5+7 z1TI{{MPYHQ=7DtYnOqfjxaScTj^|O{GXoj%o_Rb&%5o9LWWFk_+!0^Gjh6tz{ zY$FoAV!S4OWjiLwiAqCH{)wmBAeK0r3Xj86E2VWd>b<)ABqhD974=>V^+0HcAuFcE z3Ncu`{`Be7=Ry4u^-@-pOl}cY__*K0c1}@d>YGZ@;YGiy!g5 z_%_vv-2pX&;>@z^5+0N)PVU-5n-;}kL5(P-pvD(kIIBS#@iP%g@tOOcg8|(!l0pc` zLH?!j(t?FQJ^IJXd>TP(!9DZd;_SDN33{NR>o#%r+-J&t*oWAmQZ3s6HU=-CU^Oi* zfUQMkJyopWYqpZa%9GY!`@E90Oo7sLx$Gy)2O>{6hueBd#+cNtk|ii>1adOZk@)?-n?4cH3xusof~4USx8bt(d6f+{ktP*4%_MFAiTKLr|LMHhW%48vpqL-foK_G$#Pl+8Rk z>*AjJMIiC2k6LPHs}2x}pP>VoldTR5%W{kNahYimfG8T2JW$V3Ddm_$@oElny6!zt z+)zNAXa@QTHZ*Nhl;_<|_m;w);)@h(Fam$j9M#S;-iiM=9nH}n2Lr%TQ{-rF_>sb| zL0eR_Vf{zAk;7wCYsSwsODiRqCdC+UvMI(Xd8Jg0Yem?bOSHTGHw%^by) zrPXtRT)7{NN~sZW+awuR@%i!RJ7`kvl#_CJ>&fwV?*$8MsowqZ(zRL( zYB3%!+Oi$vxil7br2loeY?MZN3TMbJ1i7_fEvg5?tFh`*Ncp^f8&0^XEUF|cyui!6 zPu0Czm=k#=e1XOJ3Mf?hBlAMAc4ON zcDjI)V6TL57|R^G#~|b|>cGnCxHL{x#zPk8G5P$vrURUqP)E>?r5l-^0@B-tc0@6j z5Exd3r{UU6Xa|k~({0oXG+>oY9%N#u0=Y<@EdimMff=gk4NjC#4Efzqz{1kxxocFl zEGR)9o>6Nr&pKJnM@6&YZQ7#5nzN2^)VzjuaMfFL)oT<*t98dJffCAtz4R!@7hqqL z@5}B<53ytY-6uFu&oRka{DJ-z^CoteTw~+tW2zXMkByScFI*v_qg4B}n!I_C{B7y$ zP_V}HaIZmXJ??{(BOGkJxZy}V6bF;doGlqGc<^B-hy#zqD{ad-<+>BBr}Ew50V}D4 zA-NkYl?*|UhcnESPZZAf39}cMYDrL~_NPD0-C{9^;TFrD98FZJR5A{i7zwXi$sxuM z<2LU0(h6>v*Mlp9K z-0FZjk9wd;JLs$Sj!^2B`Ev;~c?x^iSrgJT^NF(y932y8QPCZW&?~$qmAOT}R40i+ zID4e3UR)j2r$_j7OI6J_URoWB&=?JN^44BBj7A}!xXPOo+8JwNV z;bKayd2dXkbugUv3ohfh@u!P6;68Q*_~E))Ti}ONykM203`GyZ>zNe&c{_%Qj+0>j zqg*+R(u0$CUQHAcXv#D$z>EBAQ%r2D5C3L7(Cwtx&_*p`S zOpil9rOJf8iR%-tTbL3dNlntoEA?_|^g8}g> zyGt1(qRpkO8rD=>FY`xTC&dvK2#ANCg!)`VAhjZKd4-JYN$!Wtosf&lyO(VgPRh3+X^ z5dPd`ct&HfXWWBrUX6c^_it-RzrP5Mu9>RzC6zg@Awr^JH5Hdis~hIDI-7=nUQUBC zG7;r9<7#}kgNKe~H4hy}^U!ew6q(erV!xtvc(LEzrb_U%^~LOk?8VXx9>iDNvD!Pl zW{r(+2!J>W9RyA^`OV@?N&|Jy?d9IpG~i#-Jq|V@+p6$B69!{$0&4XKZ$kK+8sGb7 z6a9)^Qcw%kK;-GgXi)SAK}D8BMYo{E^d8&amE=4>V$17Kg5HD1atpiKn;ul=;{bzo z>;UdGdHXcE6YAXy6-XuFp>WB1RM-+{=V!{um!Q@TEiHHnTU?H|xEyVdb0pwp+ctQw z!&munT$R5pT5d_{ofJ!sN@?LBIwqaI0}T&q8vf`zhs~`VTIc-UIa77&2BYKw1j+Om zadyjNt|?e80z|=AcWdgkuF}^0=YyRax1$x(Xs4wIgrAByRB1+b+M*vVX0ErmSlvBaXDXy~d7JNP zfARj^WH!o@{kBy8DWvHn2Fa?i7 zQz4*xFQSYYa@!o}6vYr^>R-}K%S9YkvUy0j(YmFz*?nF!+pIs_0j=~FpgE3(b2A5p zeOzP3S_d%9&B6x5W4Jl_WJ)opL!s?!?%?_`$1C)OSAi z$F$(SM!(?J+bp)d(zmclicR4-v52ofd3=&kV$47B0`4dKZ(7^S){Z-2T}n%{KueM} z^>aq(P;oW+)vc625x3$yPnW15=4$c~Hmgs4t#I{Vhuy>Y2;($eilgaL9ND>SOzt~ZB3P!5!giC>HUx}wdz16HtVtB(fRSny zm0e-~JRb4QS!2mOkjgH ()36oyd1jlOF;|@rw6hMZ#Hi1 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 NOf4HfdL^{*1dC!FMF*cSp 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%0DULO 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

      L|8?%tBsSREIT-DTu4g$4&s-=ld`BWlr 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/nvk@n~#>#ZSoph~6yI?j?-6ne^%9p<`# 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 p(f6Lgn(FnlAdZd~ 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≶GVduReY* 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 %B5fNBV4%w2_TS~CWO0^2ExaA2H~ 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≀%D-Pn`13dZ4fF4N{tfZ(=19e)f0cTG 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%0DA&^0eb_rZqfpj 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

      iEWk&HtK>2mYmx^tO75Oq>;j65~%B;ew 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

      5Z!OU_=# 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

      Q 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 z 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�pEuRc(X88;*kHq_mWBu@Ou7pgbld8BLK`Ze zhMf|_+PeytLiy_A!2khvV=~|gQ?w5ZkCVzkQSYf zP&wz&r6;-rmDtj)pXbRP@l@TrniTGzj;bS@;GOq2p(!8-*23%trq?g>b+y=M=bSO~ zE>8OZw9E$?^R6LCLSdcJ@#AkhK_H8b== z1~oJEf*Z&khF%D!H1wW{{}!1)kyLu<<-nG{OBM}1-Hqm#0*B)sgMe%C04#z zJ9jJG9XXRR>Tm(20uKNx-Fa|?fb?xvP+`D&w*h1BJUCJ?d~?wRsDLRNCS->8PhOr> ze8Yhcj@M~skW*%;zYAcT z`t|SMzt2%a#vD3~ejD;G3bJQK%m#gS*l)}be%WDr`k`4MmnlcC)wgfoKBJE~h_VPo z_i}{xH*DzeL&)FVgjt~+v*!-mBd!hl4Bzk2!J|j+H)t?<1hz*xmOUPI=&<3V`;b$B zRy#_@+0jxSBjvGD9w+60YpMV4p&C7p7s&}ydQy&+@DNmR33_{!o#D^9QL4KSms zLOH&u3jX30{t`JJFXg3DUPes~?x&_&D^uRU^gCyq4yk^qo@w-_;`%$E(Ab~px0r?f zw4Q#cH1_~i?DAKr6>9&IVlospa+7>vurZh|LcY^}pXv%;NufO(j~hLuvr{j6{4f(9 z^f$u%_-;dChG@eyZxkLxBwNv@jUNY;6h&4XTM&zbw1WOu!h48n^y|8scIru^rM~

      `3-0)<7j)N--9o=(mFWXRaq* zX8PLvHpf5u=>!!d9cWwu79W>4!k&aOAGu;hzm0T^Ua4p3_k2;~x^*Q_5**$GumZo} zibs7EwKo|xI`5?wN}OYXV#VH*wU2^CO`GNd6gzdAAf`lNdUr`_{#ws#re4k!u}}Xc zs2`6!CWfU|WH|R28SeMgs~X@*MRP9D-(d6OTe$_UAgx}2^7J@W?7Eba1g0u3OCbZ$ zsn_Ad4;XwP{puKwEXr>P#{6iBnW)r$gT@R!f@b;gPY7%xm~Jv2N-%T0->@-clCji= z>0p+VL05(yG-SU~qX!dy{FAUvJvkAK`~)<%>iS{IK|=-)I%MzxWZ&SYgXv+CZE&U> zG;F`oqsjVHuuemABA6a#q#2Yc2aOmuViegn=;>gV>y(NiLJuD^csOEz8rBgzm~N(j z49=7X425mRA}?U-%%4UYj42NoI(onThoPb4pMh~2eiOlTU!Y1b2l6^RmBBQ+r-SKX z{(i?;HRXXL1|5#9JPXsv3YczY{xT?29>_UiEaC>Utoca0s*U`;7cBMooF>;lsuZ9XSlA=ZkQGkpiaI z5>+aU97aQB$cSMFaOSxVEi}`?bT@OAF>cC{BSz2;bo@(jfXstg)=XRmWXh3;?>}tl zAZh@^X$(vUQ@3=Lct#E0?|>1*haFA!1K39cz|?iET7f!h6i))C!gMgpnhDVaV#?7p zYaEIMy$t&plwj(*Rk1&M@UX#y#;|>^Kmkn$)4hAO3PX>9^;cjW*#XnNM>X)U5ttqg zcsiJF%T@!AqCAd&6^7~5n+T@Ia@DY7j>agM%IFNm3})H7YUra!j~RR@8GjANkrOaI zmahUIGjt3aXEcn1>E5#%`sk5J$m=kTgn;SMs|xtYp$G7AXEaQM>9Rr@I_tjydrQ)? z2&T(RC&{8RO7Et+)2j9+6u-%zd)JTFiXODsvtn`CmDWp*o@8n&YW#4S>|G*L-rG=| zzkv>;aF{kljmfd%w}*8NPiibfK3HM4%AVAq%;w&KsUzgdyppI^pw$)%i{c*pE-_}$ ztj0vXAn&r8{Azdo;aWjCD!d29l8;CbQiFzwSA=4){D^yfWXhWcMJYN70@1Oe^W~BO zsX;z+AEHJn15$%BP-Ml)CjAl>InRGYH5M>u9lgDu4nfs@0y;1|{$qk52NS_`(@~VK z`&-bb@$}=Uz*4VGXRO&kMGkdmp>ML|KLM7yWg?hv)%FMI`Rr82QVi1>TWxo6IrU(6 z{HL%>oi`Cow`zL>jKSuJTxe~nPCpHKIB!_!(} zQg1efb^B;T{!>~{tqxJK%Qf=GvLUY(G%EdXpcqrou7XRoVj*(HiYE^gQxXH!2v~97 zk~)T(n{^G^S%s{4=WYq^p2)|y@NrCM-R=G*T7jvB74G}GhJS-rAaks^^i-WW|8lLM z5fQS&yqygumlS>oA45m#8V#brX~&BGA4)E7(>2fzDEe(Dmo921X@%Lkn{CkR=Sp+# zh+NHptGBn4%*a5YPgnA+SU@hTG)OLK8y2v_yesveESU;f@w}XB!L3?Br?&qcd~C3j zM18*rj&1`b#ZDi}XH^Y3Q$q)1b{sS6^&qNwSnG8glrkgbP+1s)E3}?6>wgcA85yj; zj1W@fp*YXFM=o>t;!-CX*Ld|~tIs4K6014K&3lUT38i#-(|u za+>IatF_)V*}UH{D|PT#Qg7Z|nD_oQVxLC5{}V!9WRL_V1Di&Co)tks$KXffH(578pVy;75#Bqo)w?Uef%|7Y6VRa0TlfPouqvPkC^7@ zV{;vF9|^8Tf}@K5uT*iTj~~~~_2oP^U1r{-;rA@?@C!-9vJ|LOw~;o;>_q#75Qe+l zRpffgf7DdW`oF>BH9JTR8FyxOHt*bWuj`7zO}e7Vv;Os9rFNBlUc>ELPlF(Y;VuW8 zino}GS^sw^-dIRHO4cxmvEosgaspW}7N&Hv;*U_WBC8oDd{$hwlr~j!nf5_7{F&tA zc5C`pG6ZEZGR-pYFIPQK>ucn6H8Y2K`?kb`a=OZ#rTr*n-mR^+pspWWr9B(_=H1o; z?@A+OqS0ujdg^Sd1LgXnFJp>Uq~H%^=W$0W#uf!ujQ+QHyjXjr8vdWC(dR^MvmrK% zLeX!nX7>fDVt2WE z?8~Bn=CA@kR)$B7%rTg~SkZZ~j>5lJHwRO+_b2(l@512G@Sw?THqVMf4$?JhWTa7z z0E&J)-YF@QsX!kowUWlGb^p{+2eQc1@bSmORp0kDA}CFe^qaO&Yv4@8em!ifmw;?pD) z=?iLg$cl{z=&ChR1GDc*s9`=AsgWA!BvyQRuQpW^%>e-v{f3z-Q8qhfFt01Yb-hl4 zm*o_b@Hn_S_ZYD#eTC(e701^}4Y7#*2o(L6eNEeJka2IOla0mIO)@NMWEX{DaWY(; zH%eRdC+Y-ZO@ZRDz2r=)kqOFN5ZqKOUT*qQ&H~f8twn#@#S)QtG}kJ(7yW3l-yj=b zTA1^vAfhL7(sp5=c{M2j!m%i+kN77G=_)ftqK< zj1#mX5LYy<2dv0U)2AWM(d_Y>jLRh4WqxSpl{~_V6NT-vfUt8 z{yB)@s@-(7z6^T2VPeHGGEX(g8jbVwT+}#D_RoRL=NMN|^xJ&8&PqO-w24~pI8>W(kdHcnMm9QV7#AkD$g zTCw8hXSBkXA&7nF`7m|A%;yc!o3`)*cK(8{5y*BNXZ?jxTsK5UPIQijP;~A6o^FRP zv!_YGe<-?(Q1hg5l5APOU=oUcGgp<7AY)G-DK${zRjsV#zO0Ct6EB9vjrWpRqW25| zD^`(nwIO<+n7;%yc9ggOeyNwTArxJ|l$pFn&MXuC{*}Fb%12bk@tNKrPV_#4kF7i&}HWzrCX!+=O>V&-(hkOXM?;eFw4tuvAo&^(tPoZ zZP^vD_{;hl(IC?zI)@e8$thGLQw}LYR{Zo2>F(G>dL>LPC%qO#C%&H}Mb}rvlrP&6 zbAFE`lUJkWB$;g*VsFu|fugsWWMs_YbY;aC^5?68EQh2BSkdDx-JU>BE;?2GMg(!J z89Fk}n;;IOngDcpX^n)>_RWAE zBg1Y{v-6U97#44YtNU)&$qr;A3X7~5trrbd6TRaIq3E~zIub)^I@Lao5?3EREx|{7 zx%^FV)mfSyL>c@)_TB`njjH|sPBQFi)p565s&!Y~_qfHq?n|}qN?Tg1-R$DNP)aGK zh=_=YNGVd9QbeQ_DIy|8L_|ca6%lJitcZw+h=_>)@AuA3GNr#f|L1w;y57FO_jRsI z^O>A`JNLQInKP5nG_v84*Oq!zle|m1=ln6mvVodERA}24-_nqj&sg5N#3Q+n_Xfjr z{_%_mVJEdb<%54^nNM8%`-lZt|aXCq0ycyy1XNJ$5%@2k;L>M!6fH2-; zdiTfplNLulf=|EP1vHH%r<8E0UgjgUCe6U-)N|z{_72fN@eUCDKAb)@JRH_vr*({0 zDPf{sLL;po3hRsIgQ^Zu!1Np-9O6mn?!iaEbRkV+s+1DO>7_K%bi}l2_*AZS1oo#OUk&LH9qg+I2#4!ywm+TO@}Z)8BORd{N(qPS5B7Fbnl~FC zJw$5Xy6DiA1_(#!x7dD^=FVR{d;UE1shF!e4k;iCT79y z=l~Uu+}p3>y!neG=qp@4pKx!YKWv9e2@~`Oe7pHufRE%+=^Y}DNi;whr~31P55duw z652+=loA~Jld9cpFI+r(x=cEeN5Kpb#_Lb6c9UN;dj_Vc`%PNsq$7;ipGxf}y=2Dh z`3PK>9v~c|KkOMPJq>nCX_s??;P)#8(;^meoe*Kp3BpAE+4*i}Av|+Fzgy$pOzW&! z!q|iTByie{*)T4$nD_%Ct3QC+&G-!T&s|2lTqFn%{bAH@va=S=$CspFTjZH*!dQRb z9hf$I7Hq$z+a`?HA7t%j+wlrG#<% zv;5s0%%6cz3_C=aDJP6^_{$(xEce^Aiwj^WVZuazqDvMp=G^NLaTd3TAL>VZdc?ek zBCuY$D`*|!r3A-ee#IAfrgn$OGv$N{ll;l!0>Q7cxZlyu6UH6xPaI1WLKk5sg)s35 zf5LNSFIXU-j=C#popneUcceds`J8GUB24Rqu}Aq8o`bO8rC}B#VdByLWoIp%zXaRS z4pBfP1B7wM_)(Y0+RVeIk# zL?hA54w2>5B#aC9E4yeq3|G@IgC;oi2Y(~Wdq(8qh}m;^AryHQ3Sq4NAaFPNnY>=S zN83y{VZurN0+}5#XFjHKhlsPp31d(8E6xI}(M=P^p5j*)Uoz{^Wd{gjPW30t0(qZi znP$S6)BK5Y@O04u5!D|$j!Xo<_v5bBtrEs-fAY86_t7HfPU9D$Iz*al6v3h0kL@Ns zGZNof< zD;|psi0pZOobWjczG0}zmJ*KCKM2~*ZX~`Ax;SFq;yIo#S9XXR_81Gv~~o&mk9iPAZXi`IlcZZ#q|+2HNM46C4-) zOZjQAugedJ{KfxL9y8JXv2LH>(C%*jhfdE#JluWj@&kk;FZFAGR>YD;i)Kg6n>J?& zCvhX)aDPW|T;^8|Ti01!>P4Pu68X#h%Fm5lNO|`sw9hmVCSCEb<>z@WC!)i;B^*B4 zzs~%H3-Ha(`Ll4@cQ?@y$D1(mO210;XU>#wV0VZDSAN3bSNT;~Fn_kU6y2ZdUI=6L zC;cNUn4kON3yGB77Y+!Mv?p%=!w4=~Fkdfq_g3nl>!pMV`g8x0_Gd;e_S}YwIG1a} z;riq8|3Q4o!f8veR`HLQ+@H}0Gewwqy}ypnj+`^YlPOVPrU-}K;8$VR^ayP)_;Z#zSCf}RkunQbGJXMr^Bi)Iv}F=_!B(?R=?7% z62{%@PZZz9hFuZn@DV0N{0m{(cyFg|6jUi;!Zd&4`u3=_u9 z@FyyNAK4+ojGAyrq#t42C%SjgEUv$$gb6eKNzU}tXNQP$!Vt#K@+a=OAh^GwaaJ>7 ztoBjHZnZXhF0N@EBFkMdVf<`=mgg;4!YSCMTPBRX->)>c#3D<}1jhsZWEaiGUjSk2 z<^Gnod08Tio#RLTfoUuck)>_I1pQgc$YOpV^3hq5+;O+lG|Pi9UVqv@QhZLtG`Ud_ zX{2v}Fk!x*K;}fkHezvqryD1XS>R8cPX|PlGn;VagMLNlMMf-~wJ>7FY;K^sn{+e26e>klUR-rR_Vh{xSQ`@HNB#y;d%h4+;r%V8yqd)Tk682*8V5lbn-p+Df>J@ADOE{Vh% z-y!no=m25dqkfI^o5=1?-8f;~WB!CA=PiL{U3fr*^~c-0MS`0}SpHGBOc<|!ru{z% z%au~3S&Ib6lm6nE$$bQiv5VF@nuG~Y`IFZk$99M~*A>E;r~Qd@#rlbsxeyY@MEMhC zmFS`aBD&O{D4&6K>sAS4qWy_-J<&x62;-Oe6V;yY|4hSN0|^sj{7Lgqm+eiY_K;MUpQL*uB^Qo@8-f3ozz3VcZIT;`8~)-u(-0v#be@IKRUB zeX+>1tO*lW`jwYU3G(Rfr33Cn2ovM|DlD45aP|V;((4KXgbAzsD0sJNztTPzTf&$G zf8xx!h;lt7Onk5}= ze#E&@i6k!H1BCI<`IC&m4LAUK})Cp>%lV%ev=f2VQI zc*3D6{^aLi0ryOe4$%mO2g2AF{Autmz&$|gtaQRe?b}tmZ6y{goIgwZL`W1kjR=Rl z=*KudPImu6)7%0Pj!g3-$*W+*9N)#TL)36F93YH&$)DOZco?JyE?I;z>Hb7Hpt|UQ zh`#JklzX5*b*qH28Gc2l!>q{if<_qkia*&U(|Ef)M8lloe{o!B-O;qoiXlwM^CygF zn-5?zcZfKLR>U{>7oRUX!)3J2$O+@~{ff&UeRha6(?S^gnm_3!oR~4R%vFWpDDW#g z7kfy4ekAfN8p7Du{mQf4m+Q6(V+;Ms^53B8&}9b*1y^`jc8N!%Sf6`blIz$wG9UzR~>{nDC1GwXL z!-R2V{-kH~Ax?(~^U6sW|CV22`8#6wD%~_;Ou0X4&Pfqv%!Ki8`xT9t&KsTt-7sNH zg+FQTtVEQC35UGnM-;ah?q_I}7fZsJN`I1EpG1^K31i>&Bl=JTH=Btx%ZW%BU*%60 zpWgEWd6C924-m#~@gx1PY-69*EfdC8`;mQwSEvqMc7TvvV|~w$^qT!V4f<>Lh;#k@ zfA{r2)qhp<_uszeX!`o=+7aja`~F^YHTnPcb)BaF-@cB_t6Q@-^8J7J{6EeANV|Jl zf4#~6|D(U_d>%Qz|F`o!oxePjX7#I0#{Zs4eY5e`nDqbt z9@eil>3>h(f14dYv+LgnCi7QkQvXAf`eyrIZ_@uqCiVC9_&4m~_&+x3-|YA|n)LsP zN&P01`eyt8kG{G6%bw2Po?bu9`v2dq|EbCOyVa!rXD0QxnbiN>q<*tW{Vz=Fo1MQc zCjFbOf3y3KFHOd8_VZ`6`8S)tfAq~=|IFsE)nxsBWm4a4{M$|X|JtPf4wL$3`~Qte z|7PcZn@Rs>`)^kN+yCY9o9(~Z@ozVozwb=y?=-3Zy-EEJllo@!zo+wO*8dMC^Vexo z|3{PhT_*L-&R?_oKkec8yZ5mF|8)QUvlg%Z+B4!@fB)Zo{ZI9O(fs|luf3YS{`%{P zbNzjPuYH>QfBX8IrvKl*j?8PnW^d&C|L*yJn*Wh@_q6`+Cj0-7zUTgHEG=52b%P6w*NsU{Rf-W4>749YEs{9{>jL>hEhZ{{2kqn~i^ell~9b!}~zr&>dM3eev`~Q!= zx&6zY&flJ1Kg|07->!eC$@zPjN&QJC^$$0xe}qZ>BTecbWm4bl{5{&Ff3x*(cK>mV z$@tBF{%kh?X7l%tzPan4+58=Avi^=Usc$y^<4yVxH>rPuNqw{ZKhdOrv-AHXlm5;2 z->m-0|I6by+kdm;e~QWcooZ75G?V(Lo76wUq`ukw@9F%R^?#=k8(u|H1yJ%Kz?J9e2+w$16pPJr zx<&ud>j{?e*f?CPwFO!NEVn8*YiIje_O(0{c)4~KYzeZ=2)ar;+siWA@^R25+F7V2 z#PV~{W!f2+sQW@L($4IbFw5GIi}9mkKOhX{n-G`9RU_CEda1>=mFPGt>>5p6#cN&I zWbJGp%ifkh!mhNqhDGBc`xO>fLMQDc+po5`(uvNm?YC;;V=RYQ5=P&sogIKb=y+-L z6z%L_yl&a+dhP5W%Yl|N_rAg6+9B35_rA{J>K1%$@0%>HA)@1?eQwvp$KiFHI#oLx zi`Q$_TP&{J9~sJY^)`#Em^gK_s{aV~ah78(->CYJtxvQ#ESvXzK+`|Ua-`*o{UWuq z!z_nd7VI}mJ39iev-Y2^ogHqOWI6Q!{3u{*7d;gpIL+e95o|wbro~l6bR-@!R}()5 zuLq2|UpqS*uX$teW6iCi@!=T!99$>SxoYeqn#?JdlP!Bs(0@Zb+;Y5S$%MsP+evsm zYT^Rz>_p26mO~H4FSQo_#83`A3_k%^A$ZAQ_z}{2qQgE(|84BkpmypJ`fqlhinIHV zz;7k@i^lUu;Ab3Tx}h=omLv62JkxT9<)Pf)1jsBVVwgo@;m_&5cSo9IQ z#B#CaLyO+si!3fng9Sf|S0)-eE$D8oV5j9_i))+UFBbf4UprA9f=SQ8X>hp(V;0qe zhVUhD>p3P{uCQF|?cg<*s}ZSQ1Xo$EgaHgtDV0z+&bGKLsA=27$1qXYpxn=p+63pp zl&eSZI=UMsPQD%;_8d3hO14_eEQB_^PTDSIvsD#zyP{Ze`Vm27U!1bcnj;D9Ei4v4UU;iN;cl}S>rFs zYG){Xu3M__LJbx_G7bAZzSUb}tABO42yyp2E_K$mqpELXkI$P({L&4Pj z#+aT)!}<(g1J3w+$eMZlmTVuzlqXpR(fvU6DQdjnlR>FwvO$UB%*Yp9%H)>`Msq^e z5*^E^ndZ~fhbz{y+_J)gg`ih7;!uFDsNd-;(c(N7@^V+p7tGrXHYh9UAdl#X_fDNv zkVt@!m2m*A2Uw=Iim7MV@Qkkk!_~uv$H)@<#_7-`n951AgXnnC;%tx~lGTb(SLP2@r^~GQgUT6HP9v%> z!+FdmG;3YKm=%l6E6i1uU?x-2NOZ0qAwCV8$g#X?$>Y$b z4$|WWn20mf8h&83hz&|UtGkjod7WkY7ET$@WO8F_`OYjBXJeta4QH@cztIxtafY*Z zKw57wD^mW1LC0&B$f{zmQh~*3IJ0mete}`uXuEy zePehMS!_^#r+9(j0JB{#_y^yu6C9M8 zK~(>Qk+_XMBM|QsnZG!Hqhn}qn9EEOajErhl;*1t*CMt$jc0J?ITWkSdWcnDj`y+d zZJlVHuC)bP1FYv-XKH7o@MFa{TW`_Mf~`T;sn%)QSr{rQ!g{rK7HSQ#-fz7Tb7VP# zim_gf%ZOki_A9PZq9ets@7DK%a;Y^^Qyz`8YAd?YCK^9lF=9PL=g(Gs?|7i~0Bf*K z-{|dYRjsN`ALjj`zrRi2yY7dx({1--cEmE21vaFtKAiiWfmXqf7-Vq^?8Iz#Kqc$k`iwpE6G3eNaL+FBv( zs;7_1Vb(*fhg(rSgEX&(BWa#v5)7VVb>T`9hX&D+P~Yx*G(K z#u&R=1&<+i3La}kJ_ZDjvtpkeyOIu%N6fJ=`=W$+HXD=^tSGudV)%*P0Xqpnoy=Zt z@M+-8uw#UNhv=V5&;8=#G;fuiVLjb?CY>k8)9_g%oIBfcHrAK=E^o1~_|9Ohj!Mco zG~7&dI-$SfSzjpna(ce?Jgdv9U!gBV&{uf7Z~@LHGgq0bXzdylnk!%MCM%|5nczjt zb}i9yG3wKETmsEY;c?{(qeoY-Xk5mTh)STw<&atbnlEx^qx_J$wwR#W^C+fV$pn`Q zUS-9st`X&{tCbyj@;JX1&abm#>F*JZ8#$Q6g4Z+bglFja1}Jl@rYj?kWjNCc zkk<{0sZ$tWw66jAY!dxjtlW=bYy)V7TYk@RE1chEy#$kkV#-}iUwk6*b}MF2n&2HQ z%Uq&*Cmh5ZZcQLwB{FwYyixETif<=6?xnclGNVuZX>dE88gb9k*L_xO%~AztFcUe% zsgd51oeA+-Ftsw#ko&fk&-%_5RAsS4lG@o;r{RqIBF{0$`hayV2QxN_PUpeAD~0HM z5VlvP`K;;p9`oUM0sZE+ElUpaSmBvZ5?7xVv9^$gJBaEcl(FYn4E-fcY0Pu<_%!Px zS@0p2VV2;-Ojm*6BQ#Pj_$bxt1Rs-WA^13Pr{EK;lRm*GIq#yA>H8@}yCM|M8PA^ruttER(gT$ax%)|Ff~ zC>iWyG12h~lHfTqVRAJzUNTG*ECSmp7M_Ko_Z({=mOVlYH!+60MYu^#rJEe)I!ACV zi?)cU=3+^Rp)GAafsY1}adSLciIdkea>JsgUz_r+8?3LRub!g-p}b+eR6BbOXPcn6 zawXo-$_V3E_##6o;WfR2s1{OYl`q{$MT^K3akx7KH(IfU>?b;kN0`JyRp?X3QjnEK zu{Y5xI@Ws?p+!|@-E4h}qfQ1L+@bLSwFBgASBOGYklAP83!RToo<@h z^DLhmq$H0G$~RW*oJ$42mnkAx&(YpWbbLh3Bwv>F;rkdv)W}L07L6t@p9wG1*C*77 z_GuspHye~s*`*SZ*$SB)!($>eG>ObM%IpxC&mptoMPJNl7?OrBAmce&5X6^U5YjRj z>(}Uk=V(R4SJ00&=wsGbQB2)FqTvC|3~AWGsB&OID>LAbKjC&|OXLehd zZ4~$KrE6eb-P`7zB;7GvGR*^ae^vo`~5aGZ!Fc#h*? z_$27Z<>Fim8d=F+OR*Esu;J~tWox|~r#QpH1hIOGDJL_JErO@8n;n9u^4)%-^Ry8T z^cDC_+ZncVy)im%=h)7->DREcZD-kB9INtN`nbsE!i7WdQud=+@Cv%yDR?c1xR0ow z2X|3xef`1ECat593vjFI$|O22gv`ofpA61&eQAfOTG6Jcv_5xUXi(s zGEr{GgkKIB;|@$;0wyENSJI>5a)zi%spPy0o$wr2L+l!et=i?Yf>rsxF!d$idfRoj z8#%d##qS-qnVN|kVB&6iGCWAqm8RHkvfWIjlJ!i%EhEHsO#udP2gQ`B9E5JcTRAm` z1aIRY#OE>o+hJ$@+rH%KHFqaMxobq*t|@?tMw(FXK?*&`y-o-A7TaRozdD0Ak8hOk5Jt@ib&sZSoD^G|h0dZK-XU4ZSK8jTq*)mgrngjW;2ttr$2f zF`gMcqHVL!Hik3tb(jc`L&TnACBlqnmm6H!eCdX5(n zaT;r|TdZcFIy}cqXh=t3v4)En$|da$>c2dq0sE$6X?O(4e zS&XAg#Me-KolhJMaYYn=l`^SBM-F6G7=oCi1-Qa3w1qFeZ!l^BKX`$nGTV8 zi*vnSu$V?-is@w&^PDVL!jjD*I^OiInWZqY86g^q`bFyvrB{EbA@y|95t}fan;2{;D;;5Omvr+6HYyERJT;uqqhToq~HS zD5O47{>$6bVTAJch)^&QR+q!a1ZCHt^nNLdO$o#^dRHx_!h@7cwSEOC7Rz2xieK)F z3ulJQ6T**rn>`6uP#K9tM~I>u4uyUg^_Tgc$?i= zdZwFKm3@@`7tB0LI-!bR6i7`yfaiO#SFx z;vS-y^AK;`V<0w`Vg|#AbonlE8_qBTs@|c~2?~m+k?3?l-&o+YJn>l$Qw~**ftcqw zN;y&qSM;mj;mRcC3CS;`ff*bxZmT;&o>9yTZ!GB=eXa|ylz;yI3n%;j8R zTBYG8^xtzFi-zNn0@nZ=!jD&+=cD)Dn#Gh@>&u3&bOMx4R9v`%yi1R#vSSs3C(%c} z;K{VwLR3#-x;FXjK)hdMPNQZ_6=hC`OwKX{1=~DO`&rU(CK^^g<5NaH%h{lu&5qUy zo}=LM(=6gn`Z6s05bqP2^XMyj3pLLtCK1&O=+;m$5YHDG7p<2GUPSA)B7QNg8!lDo zZM(=^s$c=?B|0vHOkBAyV7+iBD_1C2vhXsh8N^jgU>-62dT6Z7@oDG^2=?M$V^dik*yZInWNVv zc#8so9Yp6;Xs*LIOmt2CCgyhKHYLJaNcSjrE7O(f96B6#Dt9RNF~Hm!I$!Lq;=AC! zR>5~BtJt7?q+nHS6q!aO+;iLunNJj4iMm8)D?2eLGSd`(y7HVc8L98n&J0w#D@QPr zbEJqEK2wR@0%7g)K1*>L&V1h^xL=vAJfPrSpi}hcBUaad-~yV8t)+uGOiha5T>8o; zI_4?P_qa;x_YKZQeh*4NL)i7A@gO_XBDj!w?GWWfQ0CJTU0m<}L&_56VFeq~tndQ{%6^vyTqdugU6^uGjFpdHlf-5u->nf$pzKz`XK1WVFp=v0c`WzB`iALf-qP=v5pJ)rdOe48OHA9)=(Y9nN zuPCdPTTtmDQ>a{nN*8>a>&bS(EZXZ5%{2(hb7W)eUd2>$#Wm2;dgUf8`hqzMmc<;w zwaiJ8U@m1V1=lf>2BPXlBBBf*v*SjlQ)KdJZ$NMZ?ZtjfFZr~WBKR8ZWeXP2ULjF^ zeS|$U)Qij;On!@C5vNgy;6^0E)h}4g{>C)Y%O>_WS+InIkR|vgBPtLqWkltIn;B7^ zU>PH77JQ2l?Ifz@yGIoL3B6QsMkEQoLx-7ym0WA`1>farT_#vX-?f5U=zE)BHGQ`W zzDM7^f;IFV)kNR#kMIqd3^phq&`X|R9qXo4@Iz|Wh-N*e{W1!3{*U11pv1_yKl0d3oy;nSBBlq40^}KYAC+pOh};7w@F) zfyQs%9p%qTw=&4Zsc;(&|Bb{LpADjL>e-+K1;BZWU@w=+4#8iE{i4}NO~a?zoCKd! zv!B0f@gwa8v-|-zqqo7TN^&3V_`nqPjO68Xs7~UP22UssR}FbisWYpIdOh z03@|UaDUpX7Ce9vH3=RVFbg{x!Gq|fTkv3Zc8I7R5^#}LH)8|F1dL4ASEt~y?AL(cam3iKD0_SWYAi)C zoRcA&sGbm@PwJBbP7FAO>8)Uc<6Q6jJ{iHd5UBB97d_|@Q>U_D{eq`4-!a?i>vUE? zvfvraWtQNX>`{T>Sn z^8~MCe@lsutGs!;8hN{hdE50~xJ@*!WiUO0*D;u3!Rr}J!Z+;34b(K;9>cAh4a!Y) zTOv4xZmWroo4sytf!nE6-t|_tTQqK^+abZ*=r+EMCU2+PG@^P3H4S&S5HA*)yC_~I zcsJA0D0mNp*)Di5D#_I)7(p+CM0Fa9)pJZoTr*g&so&D)0&3<6M$%r9;7q2sQg9Xp z8U*iSKU;~8+1`HM4|@+VTEl1e80*+}TA#xRQUvER@NB_(>}MfSoexdpLov9m7nuj? zwncCu-F6Tii@a_Z!|f8f-F3nze@C|u(QTIC!*p99_z2yW6CIDzZ8j2uYYh+mfyfg9 zj|V&%fG;iV6pa^Q5{uE6n2|i7MOrj$SbJlY#MQG7*urdqhngh(6TG3cW zjctN4oHy-)%h}srq8dw0!-t2^O#Gg1_!fd7ef}1XH;3Rg3rw-T_HPuV3UAV~5CO zaFOX2Ok?VX1Yct6;(wsMbS5H=sJ_fD8^#fLYQ-Y+N&s%bssu9`ZKL37Y;s)N1+!?n zOK=V28x+iDd~uyH?Rb@@4d0~GSN64tHa7r{iYTURphl(OI&7L;4T5e)+bX!80-Z!P zk0uSz9}rjUk2I3ct6PfTYn)2if&~n*Q1Epoze2E(-KiIRgUN3pszo$yC`-iGFEYh6 z64OO5n>crq1xuL1EWtNvxH?? zz}2YnpXvEG`bZaSqGz|@rwpw`a4SQr7W|9?O@iB~wu7jCPA`Tp<6#_zMCJ<`iSMD8 z77lTm;Fq+QE7*#_UB!Z5af(z4Zs+(m3Vuxs+XZ(p`CUZy8#pw6=LDK@ztGFK)Jzp@ zr)G}echoE*syi9#8@`nY;te9xL77&;ABdfTos4fl@JGfM+e9e0JTbAJO!~&u^Kykz8 zKoGAJnL&6ztKrB-%S(@2}I8`1Vj05o?uuYmu{kJ57h7CMhA`x z+$-=VEZx$uAAB0WCW8^_5#_xDF(Si)`!L#se)?1c(VKLlx-T@1UywmViOB3v@oK>X z0#Tw(f(HhoM0W@tgkW6Vf(Hk};gH}VbQu3Ty^NuSG{LcSm`ikwgG1xDb!KamcS4}W z;$W{EMdS29tdiRWCkEo7M3>;9bU!F~Sl|>C_W&JDV)9c34-Z61

      @@_eFw7vICWZ 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

      q))w5ZX)?cHL+d-Ucz;CiSM;lo>r}rO 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

      ve`)#`Cvb!Y^Q;Q>4X7xNS;@x8@yeyG?0s{j=6 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�$(=0h8x9g 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

      `Zni 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

      O2$KRP%v^R7s4(-{448($=CHbRwF}vVPL)^* zEoN=reC@cZ0IZnliWak+E!9dQGr)`ynuCft;Km4jOWB3mMWDy5WIdW?Ajs@!^xoC% zfg=;KuVpuCWs%KVfpa6fp53b5uDxi=?AIQuXemePuDv9tY-W!GGsWUPQFju^DSX#W z6+2}-5>F*lx78(5m}Vk1nMx>c2b#)w>dv~mfT(g0FjZ11jy#jP56CK8x(Djiu?Oq2 zsfU2Ca;olh-L~c{E=sX>p-q||N2!=}gUo~U~gEUSj~Zrt^gPvXFx7mQx5Jzig-8 z1NI9S=r6oW{tHLbBM}1wrmwEQZh(+fmPaIY(mIEHF(m_{%2rBI7qYLVl)zP4Pi>|) zQflCWvp%|bs(?orn0teofj-j z>Y4BZgM~j4tQ+-&fW#813#!bMQ9@+lOeE^K6G=j5Q933Fo28`65I&1=A`ccdO@U=i zf{9|Cc!DRzz|tmx|-;OU!q3@ohrUmGUj)NA!a6a5pf*UOD>)L(GD2{e

      jx&P>dz9M2^okc)%7*? zt}%_3T2HI5C1ewWV{oE@&`mZX#Q^;;gp)pNRMqi!m6P|KkVxvH6f!P7utK7#zpaJD zQkwd*7h=@DFNRp^M}Qh)t+&mBvZ`muVm^B`K_C9(x3*O)U#hD0kVj^L zJ%S|#{=9b{2qg2#tZK1d6IuciiB7Xpze;E%n!Gx{QNOC#te^Arc~;b0^|HilP^aCl z7rJ)pFVw5OyFe(hhNesbeNMGsZ%ZGlh#U5_K6Rua87#XSMZ3?spg!6#p}rmn9J{7$ z{CLBncmHl*!kAEUR}d`ZY?14f40+CeB8+@jvqRgp3ZhEa{67!3^hU|?p5i;^PRAPBJ= zdJO}`_b%xfLq&c=&@2Fgh9@K<3=N_F?Yv(dj%tX#r~qn zFj$lq4Zzlr6-^agLscAY7%o~XzQ&^UK-h3v%f`lxadE8dY^aO=h9%X3wJ|mNVQr%n zRusn@l*Lp7*ZID>VJPMr@(qOsO>ydyU177A^@?S$t~mQQ1Pgs}z2U&HDCxEvb{Z}; z>^AH*>^B^0G!_q690_gl+Q#b|)#ks}7ahR8=OVBajb|m`if{{pvZ1~uaVOjEOHxr8hMTGVpPd*^b`e+!bX2l z)F^IDS$iAp#XcZB3^Wcl4mEm)1QGT~Fw9hooHqJFhi}Q_J$%V$n##nKwak+5?MBCSZ3A)j^*%&Ww zfqeT;;{}j#-)r1&Jk)gf65nuL)6u4Ie6o0bQ@R*81tQ0qV)3G4(LG)qP59#6!0{&k z=nYLLnleSBengWh3WFyB^}yBoM{a8BOWaI=53{a?>D!tninlkdtM91L4@KuaP4_mf zTkit^glu}>`asjJTRz<%eXwaEoN&n`4>kGRGv0@rPBqPFPZKnRa{93*#q{G%trD@)@Ax*o>w1iFndXrVZ6Pg&EFul?AX46|uZ#U_NtD4R>oogBy zeYa^)%Z-r1;;%9}K_$?Mx~BT3v}4FRCu?X5Y8soGnsn1nOBtaUioVZK=%?G8jME1g zMOTHRz!VYHh+7iWE6XrN(uFqV)og%MOpS4x`V3{D!suIyUqmW60Z~(OtPE9LP$i0a zeP5GN-rp1$8)!-vx$?mZ{NPE;nw(*8THeGBT?8O}>EQ|i;Wd^K2!Hy3f#`SbhBES* z>712gl=)VyF{8*{kd<+Wu(8ZT>^f#WbB0Nu4KNW}m&HCetq&Y<5t`@$7%@NXt&kCG zu3(edYa0nQEl!7h~tCZ&6XC~yi;oQz8Y9bUoL|5gMxmn9$ z`qjWzQs<7)&5>*AvfOoaZB8XQO2mea(-pZJ=-Z|fbWQFg{YJVjcN6_)f@-*pemmWm zyMulwKpXA`Iih>%`rLi=`{@tR9|VZQ!*pBh6#X>)5&EM5ba)&r$Taz%1gwK0XUcg; zo~F;Lo}q7rp9RY_y^iMr^DwPGLr@Pd(_f*#N`H<1I)Ogy8{fLbKDl$UeH zbKCSCu%I)M+okUT*5MGbaPykxBLu>5wE23ll=FD=4Ikhb%8NR0BS?nv+yTmP&);Af zQn^P6nBj4PW_YTZ<9izL49_+{2Z)9jz>?4xn_p^v87v8X6)X; nU}DJElO^gtGr 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 z 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

      cxBwF-ho9`crA(y_*^5FZFf5`bf6+N8qb%WK zsgkLJ5_@XM8%?jKo@rzP*dAq;W=4Tm;NbDa7=*tT2!{CUMP7>6B2$1HLWtLYv*kx)Cu( zUnsIF;;JcU@&xe77dbRBKTMIXj$|foxwlx%Src*e*)+)|w7F!6c96uAb!PDgu|GtR zJZrW9TUnCgwsU@RsJpZI7X_4t?4i$|HIl>yy`M3?_ew)wwmfuTn0QH2e6dUAUiJW( zPyEloeCkmVrYm$es>A(kk83hc^x280<_MEQ0C|aXk7)?XpY`dmyx}eD72*ehNMx%o zqS*%7V%<=C5zAV#b&|)kNwS1dPxVx`Ic&aYy=YU-g04(+^45cX8g~yP1izM@LAZbP z4TSrJ$09(Bc&y<;*dAt~B*dC^H0)q?wCF|my9Av#@zD~mGc08bz~r)XqTY)=O_`h& zk>|5@qHEb|wnEh4#SpH zUopiJaQ83JeV_P+f-+{plAB9-LWu>aNm4;Gc%bB5!}*{U zms9gjZWGk1FsozuRoN0*lYyt=kjuo;pr*YPgTFG;kwglbB@tKZ!QGPz4f0%FZv<`0 ztwPg~Q;~daWFjr|r7ky8#qa~k#+)_hl>5<+9xwKxIfmGx)SPrx~HP7L)L1Ue~ zGd~)#6OmMH8^o*O=I?qMG|=j~&5`}mmUCRrbl6~X_M8*wp~-`MYve%ggslUIlh$h| zjp{fyQ`e;%vZ;sJXUPqeD~Iol|1oaW7auq1!MDl@qpl@iinl5j2!PB~Y~&1TpR z=%Bhm!zYMnLR{=cV5+%Fu8|90w#b4?S)(#?8NF=hj&f31?BrylQBG;@<>Hs!Tt7De zVu&jNE6K}oZh{W{%>RK7w7AgSQ%GjH3|`)g^^^01S$3JfoXcZ4K14X5U&t@!3ztiH zb72{{)%*(NIE&7|Xd?Z|T?JrIV`?9z?yo_pzl=I6cx%}+jZ=8dD6 zGXvu+9k`|5`Im0FCx4)FLvisX&Yds4`8Di`OQ81*%P)7qH;-KMm6rk6UfxGe_9-U| zM6CjAfy+aVzlJ(X>r}48nsroj*|@L+dHYC+TMOSJQQz-k7N4{^Cia*GOHaHzU}o_e`l zP}4rdcqRIbNhPuAEZ%KbKYyTOTqUghfLZbBpy@#z`{EI7VVxmMjGE+)M4OP0NoJ<{ z6!bD$pn(r9hvsAZV#)e)p@2i+zk%gnn=jn+yrUUuAL2gb>`UM-7Ix+P_=$`68Sd_p zxUkC&3{369dSP$m8`)vFiD9!pT7|+uzCy+}IFka?ykmje=rJq|I|b)UUSYG~e(9lr zwt(B_uo%R&@8Q`190756fy!f(t~yugp_NZuQ9;P*n4D5HhO% z$^8WvhIJNtEM;E?3%QqeL)WU61qw^l<9ROf5Qo7Kds%on!T=~jQsJaESp6Zh8g9Id z6vBlV(5;tIfmLu zFy!bFJbd%}@bK>VWg8Q&RESfrV@oScAo~j@^Aza*qMy+lRd`4+-=oxMO(@_^U(Q~p zQLhy01&=i|GQp=`Fn6`$oWG*hk7ClOWZ|k-SiC9=a-;kRUk&?ru=@6br~vwVjFzv3vvd1`Mwkx389pi>S@xwVfHv=CNU=*o0(<(_SXc)`)kt2C5B7Q-8>9 zaabkztHqXVi$Pf6}plk zJln=L?U#fR9I$k(E;$<8Du3R(WN?ejUToX(-M{s;jv%7G!}M zt`4yLn>ln?p#f*l>?qDd&XShvsJdfetp7Pm;Fqo0ov3MvV?(Y3&WF-S9LzrGn~Dkx zHrTP9c*|o;anN%V)zQZo1p0&V( z=i_Re5V za;_h}-g(Or`X6@{_$qqivpOe^X+zxUCexS@3`!G32itrP!Y0m7DBz#h$SOo9B_lNnUq3>o`AhQPhn-;wfR* z&GGiZQK3Gvs9z~~=+(c3mu(F=+E*EYue4v%Q50D7QF@@IRfD7(ZG`F)oy986ybavmVzYL zH3#WLOHPz7Tv~8bWH(kyQi-;_QeXyn2pK0{qGZE=h^JYP{uExaQ$w}n9~Vo3ad2G0 zUX%xF-C01s`zl-7dzCAdOSMu6ZK{-fu(SWFRLYbN$RcY`(0KT&!*pnc@`E416~xsh zf9Q4i`ow>RujLSF)rsGvJp8IfW#m<(6eVd4efCETJ)hTMoO%b44+#^8e69>n*q+9v z#H$(XzR!^HUa3on`Ev4A>Qxl2n4rD@EK5_8g~w^=k3b8tj`WF#qX+pc(!E*X@Yv+W z(QyHiA}%F1ia+}qygV);viBL)TrQU(S$e?d$qH8Aa%>z&Ppxti9?Aqa8ql+DA?oYp z8qgc%2I=g8BPjDZ{2G-_NH#&KIc^Fg;{E@^{I*|7h}Qw4`>ID4(3V$&SLyK(H4#b0 zl($|f%1Th{7!`*5IYImpaARDH2<#f4A%OaDPxsI=l=dmb> zuZ7o=>r7cp2eWKB2RqX1tRs(7r@%1AH~+4F9ey8I5W&Y86_;JhudC&trd+O(t%AEi zQIyJR-3)z!VS8N!r$*cb2jetA*Qt)}3xi_A+2m^23dgN+8Wi{}#jYNwMi*>zX zxyJkZ=u-jABe9j7Z&n5fvZB;mw}9NG^^>`=LAp)4tj4SKVQZ&iK^O9gE2!9k5LWiM zPdFT8O++#=a!EysaQ^fu!uiM^td8Kt35*Mu403rz0r|-Z?ZNA33 z$Rr;-)HS_Q!b2Gkq?r)uzh*E%$2Y|=b%0~o=6gs2B+5l07I<=}cc=1UK+XJc)p zZ`h*gZh+K?D}-ZZ;CgOSgO=&R#-@`sIH6-XwpnO&T@HQl+FY5RFpgE*G=`xWLIl{@ zIlb_;y|OTIJXncbF9NMm81Oqam?avGouQ+oV+ChvQdMHh;4e=+l_1T#I_emg$lYFd z#Z_6stZ<8sUWG6UZ!6>*3n-ONblq1^(LvvOybEJ{6)*B2IzvZOrJ-D*bvu520KQI# zH43{U?g^v;a9FAWt<~)_y-H1XSn*fZCO%G<*4ZsFgt`N*nBX3dE&-=W)7ywnNnVTS z)ER+Ji1b|K1D&t)iNfGSwCf1gfr-qL&YPmfM=OPj7@GOY#w1gzRI)%OaZOAKvI37N z=iE)|juhy4WfOL`Cb>!nLtT%!)37wcGG%s#`DrXHOO_lsCDPA=DpvB>dEEXQXEBYk zTB#%7l$9%fdExp{1=Mw;5~TiO@wFlC68@+nwwEvhKXr}{e%wS?e~wX}Bz;oGupPqn zke8`Ve7Y$k;`WgbD+A-nXfYI z3ssX?pC96;FQQ(*uH$=EUt-t~Eur4HUamG_S);^98H~H`3Ae6SAX&vFKo6}|*Q@R8 zqw5XS(cmC1hkNI|AmoC9T54a(xwRJ9yu<@NGw9Y-6gt1z{WYfD(bAS&6@iU9jSfgE`4 z34zCEuI`Htb*8GlIy7cnn6Fh^bsGcLQO#Hr^od%_rZ!t((dw)UT-8;t!DRNb;95#2 zxO~DytE;pt4KR#$am%(|Z<3Gg*WRjD*~Z|E;|Ard^2wIWQ*}eHOfwu!!_dOoWM(<< zHJ`K;G(fQTpxmqaszLc~RW-rCY+s`bc>C1@==-Y+2I1?&Y90$}uqt{TsD{AROd{17 z$~dn3q=nw;4fIz1I_%%71Sjzc#jle@_w*^0>1u@{+QI+veud%R&5%^`T0#?-S&Q)T zAu^M_Bc(X;=^bv&$t^e^Y*9O8;PjqVXn0Em7K9~^!0 z4*oyTuIeD|BI>WR`n(>sqiUxb!o=2)-il?wSu~<}VSNiyA*S;tr-?0jvi(5s5GAPbQSyiu z)r2T}u6xfC(BhhuBp8jaWgLY)hgzV3&zt`iKK=5VO{;|T;B`%+s%bzS0^xrh;982& zNR$>5$3v@iH8tvbTz-|I#uE!^8N;IRdK-5wf?oa!v;JWt5G*w@k8nrKCiuPk7$lFa zpniu@>mpU`wQFLjnQLLG4fq84+ZVzgX(wMt6?RZQX#6SDc+XYy)N&3dcqw4rDEDgK z8ei<5>;iM~*MRZulWy1=^rV6DAaW6UlcfWac)^)>`#~R4Jyg@XGe8DWs|f?OC~+gT zEO_CXz#N0+?=#EuyVMKuS`HGH5`?T`9a@qmYpGfq$e;WMkWU`jwHXMvR9S*x!Kf9W zURT%opT+|cT0gg zptAWoPMx2^{?vNyceFVvmPZ8g)uSUYD=>O6Dc6z$w0Y9ARBL@W6q@~$TFs~K zkXobGMQL!&YOPwk)&p&)v7I#FpABEH;x0C8hnTGa>Vsiz@VZx9s;^m+#v@ptnfA?{ z+Mt%i8LVJ+k)}b{uWcI^4c*!rZ=RdOBLw!bzmCAZ^C&n;(Sj>hJLq^msf}yH*A3p3 zdSC}j*h-!CRK!xzj$cn+htLxPv~;;Hb!*vUkRv6StIyXL>Wg)yWx<%?tpdMRU+6F` zwPE^t9rYu=3(NTqhGy8!_#5?2TA*P|A5d+QhaJju>aF^QejVs6P8LoNAKbQ0SQpfJ z^=#%qG=GCdsTQ7y>mo=NP{X;ZzIY=eyNDAV6U7z76~|Kj>wg2yWv(nBs3KDHCUX(Zv_1=)04121+DV!mbJzOC8z{gy0_tG0q6jN3ArGyLmTS{A1RaJ^@Sb9+*Wp z;u`@ZT4+j8N^danm~2xAPGwS^)SxZ9(UWC45DHu@)h7)ujwagvvA@aMFpr*YO^o&S z!~pye$(6vXZq%gJ0rKk%xv9C)-gGDX7E>Mnb*73~Til7Vt-|QX=rGrHHV1S_ zfw4T+1vk`PxbSHdI1LOGqmEjHj7NuFR+9rc;2P)!I)O6)OE&2E>bvzJWcHgqNJgL> zHwX3ox)ZVyaEIWIIbDA}fST*Z4cV@3Uy)J;Q4iG@J!W;?4(E+q&}G}pbI@W z@%ljML^ni%jp0g~W|O(;p>y(p-Mg8e`d||SbINjH>M0=a({z#`I)i*49r1^sLPyLm z67qnw5*8zd#?rJvxNJRNKfLh+`7?%moUY?<34aUJ2fPhtF^Br6SiKs&sdyMCEL)zg zOjluXjjT56>nKAv8&i?F44dJbTD?+_+%(C4^k#F~s>jGP(~jSiz)#%t>K#mM3{ljQ zH>sN~^nbOUzDa5_H(5mUiQi(;MC8~%7`3}azOdrl6mM+K(oL57!=lCzyPtB?GUubh zm0OtJ9ayi|kLuMMqpNl!Gj;22imDC|mwy{}mm3_qiEdL)#g+N5wOSjnbL2csE;M>eNc^y{4VQ9!o2zqt)8E#sb~J)!VgO z$#krdPUjno;K-)?lJ#4&eFM0(Y5}YDtUkaeEm#UbW6>ooMlCf~8aTiHHoRn~)Nk9j z@~L8~oR-k%huq@2L;eET2R0i#qWQN*<0@xmjVo1CHP?D9UsJ*D7Phku$h1=-bVRs# zcm(?5XW;7>*TGNWYtr9fHJ^-Z%5R4lwOE9x#wZ@sRt)K$IZQgTt|X}#xt{Z;BrS&D zZtOISh;j>U`rO}v<+u3_!xZOcM*oryI#P<&IMv@OfcY-t3*?P0uAO*LY6u$=!eIBj zl{HLLGrZ^|M(8RVVn|H4B4~c%v(S7;OR->l-r@`2jPr|jaIEn7HCFqOwqcblVg2P75Y`8)_9brGb-=s&d*J;_7nmF-R2=qujXr7Eor&8d8wd>X zu2Y|e4A1^Nry+AY0HS8c-$9w|gX6}qk-&r>H4K;#KVrO3{X&G?n;p}}Tyxf#Z{mn> zJI4=dC+d)B0X3HLIOi>K^gOy@v1!6+cY8K0lg6?K&%D_0aCG60Fu)^(=yWI%LAHw7 zm^RE6F#DUE!Ui4E7}_sfg~hezN;4}h-o_LeO`IZGp!F)`NlcTdZ#1{-mD_dBH`ejn z?dE24t696<0gu6g7{OlBSUCtSVFF zNzvTG=cDagzwhX_uaz}Bw`t;|t)3RG{LIb~FY&Te;sI>JV|*W5pH!Kn}ReOw34fN<{44=SXsl6C-eZMw)kuwj-oqu_*b z-KPjqN5W7u_P~pSvhlDvH_v~f~Itw1_OTBAWK6yZDlFRK>f3iapgPkE zut#KvcZYN5mtnVEZ7yKgqlfS6O{JhaZ8e)@m+=<40ic&4Vu!*suMpfNSy22H*$? z#hvnQm;Cjc9g1MjUUm=A{;xB%VAxc1tr<7VhKMjK91&_VolZ+4fowLNo0UcLvxS+K z25Az1_Bi`JX#U#LOmi2dsf*FjT%NI(O`EgkTnh)l)_e=A&i@3Qt&fxcVoM7zI$TRF z{oOJU_i3eNyfcBjGBe**R;+%_nkoO zfrb~?8gLt}-MdZbZTgh4ecRrh?{3W7zfzKh&N?}RN8Xh}h#t1RxYvGTA))yb~C)j-+A zHO07X-MI`weqDlx5lI{VzWa~iZ~4gRX*Iz+x@*u<<8F0;cfzWx)xC3&^&sy1$G!&i z2feLbaQb(9EgyKl!+4g1)&Ls&ts!!(2^jH*tVR_lEglY5q;5#h>BHmT5+lz{GLIT8Y-e zn<%LJB!Jf9n{-RaSrk#3f;`(=f-R#Y!(nq&=8+d$1&&v0Ra#{>?*A!#e0cJ3U#gI= zys1I*877$*&(_|kgc}rFozrc!B=9AjwXgzgy}`dxGGtUXYqqxEv|2lF+O4A&?~NRo zG-p=;{Z6af5~A$2`miHBL*BHK$|hBMC0Z=`M0%<{$xt{(UPYhQ<#x8-d!=x;LmJqxF+;aNc` z+8YiT`Bk=6=%1f4%rDwz>b3^8i+_&Vr+>lr#y-;mRCjJE?Qceko%?hC8#kQjNEuJd zZ;Tv;rHMIjJ05~GwRgd3$qXFAIWvQ@w5`aUxYn`s_<+EW!*Jdw3KOhtZ`<0AwhML+ z-Xx@$IB)zU3%&`w*=>8imwS^ZiQOJ)AMujy;+r%iES27r zA!!KRZ7HACv&7%yBB;E{v{UUZWBpBovy9fx_91OL4`wamg*|PQx%SbU>YEOz?wdT> zI0VX%tAJYXP5;dRvf-N%@-eOnE)4ZI#dcs;0%C?iclJlPWs6GF+(*mcNO3@Ev@2u_ zOC-wqkMf=WA9sKK*T(bx51`wI3T>&oAqDC!Qg`=eBO4Lb-3#?nO<#3#2j2aD{(<|;eca7scg~zSGdnw(-8nlu=Xn-^0RRU+CY^1S zB?r4@ZRrW}IZNW@5B}KfZDc&3UEvU zZ7Y{Y%o-g5-iL02(%X-7gBzih3gEWg#L4m`Ag7a0a7P(5fYQt91_KBu0=cKHavehy z!3qZGu3uVXt3nm6wHO~Bs0dPoxs}tWuL^fZ8%DHoTT>!IjV8Gx+HRV$3MOc)k%}p8 zwVdjn))tNfvMj)#4$g3)0hBp#MjL-L;Ez(UK?=CJ0f*7LR<||13#W}Y%ROEJ-t=w( z4q#HV(Py#XS9Wj-Tc;?DwedB(^~FQ_p&y6dE0T8LI_%>z=2WufVzS z?gik=x7`J4YuYVrD`wKPMIa=&;|z;IIB^!@Uh=PaQd?n5+hWTU%l~n~?WOAPmKz6l4WT5|xgDz>nDhy!srMO`Q9!N?I1aOT1S0RwoAZw#>3d!` z1_NDD(N@>!X+VPp(kPJPf<`tz0O>xf=Zk=>yOr)N2C1M_khZHeZf?g1qDq6n9S9Uh zpv;w>4vwSkk7jN);lvOd$rTDud*o3}`Yy$rTEPQX#`8w3Vb% zs6m+EP6S7dLeVCv1V`QfQr$@kEvVZ4hoCCsrnLPv>VJQL#*hqT694b-&?}I(8W;dq z3wq+Iry$Rd&R#DB9fK0vO=|zC{SHiwPjH8)9m+aVJN4~+t+UN{Sr?zKr@AJ0o95^7 z+tXd#V^q(ko@;tBdJpW=(8tktRlm;ty98FKMehN_hZ2) z+~;mzE__M-I?waRbLgA$zp(G`zi;`$`x)@-;V<`Zp>?(0phC zv=CYZErymrOQB`Za%cs#5?TeVhOiI};UGLjfQS$RksvZefv6A-ih}461B!;25DQ{M z90-ND5D(%*0!RqOK(SC9B!a|{1d4~GkPJ$Ihd21}FtG zLMF%zS)f!X4N8YHpiC$WvO?LA4a$LXAv@%NoKPN=4;4U#kP9k;+)y!80+m8#P&rfq zRYGf^wa_|fJ+uMZ2yKEkLtCJ&&^Bm0v;*1+?Sghgd!Q<4FH{ZfgZ4uQpo7pM=rD8y zIts46b^FvFgJB1E#{^=O!Q(KKFzS)>G0QQT!B`9p!wy6-5{xX+idl~-3vRuAfzpIw z{|Eyu+q%^O8UbzBx-kGv1?|(i$pD=QuC;ZW?!*3(ALtBhrG0%kKfu@xS`fU0VK_j3 zd0P%Cpc6r>wdRPzpl$r+AT1uyt^C$sPzUsfuMp=N4A0Sy0Q6d0Bl(v22zCdi4%5*m zz$e0IzE6yg(dUrQYoBf%@Ez_AAL#$Ze`5gK(>5~>t@#%|{TD*t{>Pv9FWmG0;{W}R zf9hXY7Fiit9=RrRL*#1j+Q^NO6_M*Ab0e2}?U83AU6DnReFEK))scH6t0MPA`UW;c z)<-%b(<0L&Ga}hPTCcf(;N{4`K+X?ds4$chiiWa7xuN_}K`5A(eghsr9RtF;hx&jw z-lwfG!tl_cp~FJ`L(d1E4Lldf{_#5SW#Fs8H-Y~z42u{OF*agc#Q2B_5fdZkMNExY z5U~)rkDL(^9x*3kQba_=%!nxwkr9(4W<|`7m>V$-j4`L)f|6H^r1fBIh}amhDPnWP zmWZtpu88socSJ?RW^QrB^2ngb)scN8`$u+&jEuxaVj`zR4vg# zazW&X$k51{kz*sF`Ni)*iN2A;BgaIBM*=Ur^Y^qeIvXPOk;#!jkD7nKHQp^H68(Yx zm=NS2bTSC6LwOH)KEuNN!Nu-rrTZ2D?e}}wkFcL%zW@au1Yzw#+T%94MsH*bm{D$} z=lux_Z|ND(Dls&ye*nW98W7gf8f)Dqw@hi7-ZG@m%EB~+j=y#lV+;{WeEqKR%SNVSJ z`}OZPzTf=*^!sP;8{fZp|Ni~F<^|1*nwK;$Yet(b&1uaU&AH8m&8}wpJJUPKyZCqL zJKQ@jv@(5hx-%m$qdcP_{Z{(T^xNtGSH6j3;+p207MR$kO7mLtdhVzZ$eEtQ?x0=oMV3B++jy@uBBg3 zznXsI|H@|viUP6V>5~MWLhN8g@Td05;0*Aj$_#b{&j-(={lQl7v@(nwhxraV5Vpex z(5sL5fcN>YpsD+^!TmM{+#4>?$DzoE$S}|uK*wuM8!_+K|L$?zztHh7-19GF|5*WU z$X3w}?R*1kFnt1#VfqJl^a%{?>~l77s?WK=X+Gxzr}(@Koayr_aF);Oz!^So0%!a9 z2ZeN)5ER_uWKd{_?xFrZLqj8dhJ{Y@86Fzp;~zTN$0sZR+yK)$_=ipJ5D+%pryy)q zhweVzeEfWR_;m5<>C?-nt52*?oR7#y>?84s2hTH=PohtfkH#n2N9Q90Pd9~+(nsr~ z_c8dWeNud+K0r0{k+)v+H&EH$r$D^M=Nve;Zl`_DfRsJ0Dczddcvrx&9`G)<^4i}4 z)ZJF9OP$YkpNk;v8sNNd-8NopJzfLqyiY@0{DRNrw(us9d)zA5{x+aCeFs#R9v!-O@axd6LtqE6 zx}cTQ@jRv$a{&Y9KHFjkFo!VbK+x{tWjFhoCoLZ|C3M zzmtDwe~iD6e=q;u{$2gM`TP2J@%QuZ?%%_|r#}R=76|Aq5YSxaulWrM+1vjA-?hoq zpm`(yj5rjm3<(Q;AG&2EZ&bkOhojwNkg@;MCS>gr+R57~+9}&zX?L~VwRYFr-Dr2S zT|>KD?Z&siin)ntz}&*z#@xZ&#oWW($9%$k2LHy>zo6+dJAVD@`TFhae_y|U{qgnZ z*I!?MfBp0I@7I>EYdz~c>pdGh8$Fvmn>|}RtAfs~+v?fo+3wll+3AT1YHWD&@J-W? z#i^iyT@~M@5{Z-d%x}dv$x8#zxr@AXuBPVKARcWvL}efvDy z_V4%X-hX!g>-`5jH3ypxzCQTs;6cwJ&tcD%L(dLU9 z?8p(%yCc;{4;?+~xp?%L=eXzE(Z@$UN538Yd9>+R^Rbp=Cp5V zMbE8shtA(Q|MdLZ^Nr`%)^4w@tvyp)UwgIoUTwYSlILaZhuS~2?`l8QR$X{;;m3td zb=&K9)?M~oth-tFrmnH>Po1akTiq2;^~K{CKVJNNaaa9S&&B$e^>6Dx)qCnc)Nj1> zvwr)fU6*!V+Iy+y(zQ$XE?x5+y?ots^vVs-kt=7e-1L08@~HaO)#q2=Ty4JE;JM|w z?YZN5aqX_>&9&Fp?|JTf-d{g@Xl^ttg%V|~-moi)$~Qzj*uN-HXqjFP^WS*DpW5-0{le+4bt1r|Q*zp1rTCULSb<-Sflq==D#} zFVFQizdg-wF2DWbdGPk-+qZ8wzWe>|*So)-+wWUE(EQJq9qqf`#DsP8wkikRy}!eT zcn5p^z3seVEujG+0k{@?3!&v8gtU-a$SstX@Rq&-5iNZJz>}zL>+JRQw(3Q6Z*-eZ z)HkeOSgVfIGptuwt3K2v3;;X=9jSAeZ&<6o)Gf>}tW{s?9@ZnQRcE5LM77Xc7%kB) z%$9)xg93&I3=0?*HasjMU~&M)+tJ&_J2PN2gbAw;xf)U(vNz;PNXO6)p|v6BL)M0@ z2{|5eEM$E|hrl@jU|Jcx+%9if(XzS)+p@A{RSTh<&9fxd&+lEFbky~Dl3 zyn-NM5Ibmi5Fv;Ygtl;7crAh!e#@+&(LrN^HUX^=M}uSbpznh-QOXj0I;&;_CM zLw!S?f%$=XfsQ~|U{PRkpgXWtJM7_|ao+LX3Eqj`FmJdw!W-$G0n9-#ULVG^j?>4$NPPl~!ly8& zF=sGm!6^Q}k-ZMnA-rRFr|{09uOWF9uz(zJUBcgJT!b{_^9yF;rH6twZGWDwtanjFejD` z8hI8wm=lZ!bAx%o{9r+_FgPYSHdq;~3RVYef)j(a!Mfn2;N)O^F!%%-C=XNwDg#x4 z>Of6kVxTq zN3e78e7p$%6wEEOBa{;Q5$6*b#0x}UY*%b&Y!~cU>@@5%{9^1fEDOuT=3>`k=ixDg zUxbCkI$|TypYo2{5BQ>2&~S7-ok;&d@4*OSOk*T49!0;1{v7=!`fGGcw4B+(?8@rH zT8;L?_Qd*O$792=)3GbD(;1mqC$T!k)pN$JSymV=rRsv1hRh@$>OQ zyaXSQ7vqcY|KU3lIuSY(eiK>62+nu`5F8o{s#VG{tNymL1*D8VSoq~X+`y- z2GIji5Ah_iNH#`3MLrXJU7^Y8@*M#0co4QfwjZ`Hb|7{pb~P5pVzDo_u;WQ;p zO(W4Q^jVD8(XXOkMz?2Tm%t5BLuy%0a7GlD_7BOQ_6$W!uT@*{F2C5$qPGM+MyGLbTxGKe;qHkCGwmP$*c zS!jBimS(1zXcRh?oH=3 zQ_(5>H~iQ9_xxu57r|G7uW+_-k}zC2Sr`b6yOKoxf&EIWEelJ`7URSuF-J@X_A*$p zOvVD=vJC2GLvIWpXo9vI1QZ*e%%AFbpq+DKHbB1k+&>90ucHJUkno0Z)S$!U#MIUIKGr z2F!*h!dQ3;OoOB0WpEU{3cnJ+8n411z#qhi5P}J#31bMO2-^u;3EK!e2qTCJqKY^S z8IKG{<{+U678!{wK^7vB$TDOBG6WfotU#tCGm&Y?1Y|NY1qncAA@h)MWGv#3j6>d% zKarcr@5n1Cc*;D=YRXaymNJKeqrjAzl#kRov~pS=Z40e}ww_i@bJ22W8)*47D{Uh! zn$Dm{(dl#>J)3T)k7LXO-cRQ;<}e%#C!>I2W4w#*#nv5DyEvi8CP$}w0OY0IYA)#cFYmxIpX{o5gBbvP>^al%e3OBU^q}UL$uY z#;L{vf78=cX7xvPqvo{sl=h@nt^1u!N^u$UjpatSvD8>%+-sDY^UT>`G9f$b2ADsc zYFh%3lFMzp99d3v&i34kxuy0!_8R+n`#Jkr`?F}LW1VB0W0PaOW4ZIZ^O7^dHNh3` z8si%03dNGK3T!sE6kCDaj@^Nk!sT!dtbkKsF9tF?XVNp z!3ds!C*fo98oU~xh(C`1i=RoDMwm*NK?oyEAWR|5C!8Q0B@l=Rkx0Z71w;)ok*Fo! zCN>c75EY0DaUqFFA!0<55Dk)wczZ5eG54WXT&9i=tU4%2qguG7xbuF)>j>S;G=7iqg`)wCP5b2Jv6 zN9WRu=p}SFy^LN=FQpF#j%OD$mM{)7)-nz;wlcOesu*;NAOXykjBwB+WMsJ`G(Cz3=v;nP0FQ8k{dKbNo-a*f!JJ2iW9R6nhG5#-pUqK&1H$g{1dqH;rBGvxKaFC z{8d~fz9fDjt`;8`pAa7tKNoKo-xA*x9}=Gx9~Pe$?-Jh;pA&x;pA;VzKNCL?Uli{U ze-u9y-xfa=7s_&Fc`~c4ST;^RUOo+c_ZP}z<)`FVm8z~$e^GnXFEoEObF}lc^R;!_3tF8{tNW#ENk&p^DcLCp;ZWB+*IcmBY>{h$>#*y!i%`TYs>JTZ?!rEU z_rts4lkijcI(!v=1fPKqz<1#%@J09zybHbtpM`7S`|uU`F?!&#W)EWrutV70*`wI2*)nzv8)X9nCAOF?V#l$0?D^ z3m*w@2;)Q+QMzcq=!WQy$X{G1?kb6pjFHR-7K7b@4c~Cd0Le^XQ8!02MKVP4O*|dg z1WuETmQ0XLmUNelm28(CkyXof$ac$i$_~kP$u`Ksga998U9 zTvnV?R4WFn#;ah}Div0>Qng*RLA6n}PPJZ@s7_aBs58|U)aTV_)aTUgG(Xip)V`Xo znilmRbtlb3P5Z>YiQN+Y5|?O~YnN%4Y7c9VXs>H;XzR5pI+M<;`>WF@x7T;jLwa9* zC%uopqkdXSZpz7&o<=`oFXI&BZQ~2$ed8J9S>q++Gvfo}72{)Llkt(!V+u0AGGi>(W8*ZnWMR@TrY~{&f!kvlDG>1usjR^_-Al&+}YeQ+_BtI+|}Gw++_eIx0rvLe~!OEuv`EG zJW_&S6~G;xFZdzoE9@s60N#41#Vm_i5<`rc95-YJutP-sxO~RKHNG{6m%9>>NWEW&tWz*$a`5*aD`Cs`D`FDA`qFLdq{GfQM zc&m5}2IpuMLlvc>sZOZQscKbwRn@BFs$;6dsv6ZHRknJM`l9->`igqA#$OYl8Krrn z2}>NAI4yBl;w0eVDFnEq3P|)%j7TJDaay*Pr6p^b+Gs6B8>Ma1HfmpKpJ-od-)Qe@ zQ+1iTd%BKEy^^wkt=0g2SA7?KfIdjySKm|LPd`{cRPU!Bq#vT6k-|zTNI92sI;Er0 z$2ic~&p609z&P7D*ZA4k-t@`X!PIQ@7(1GN7{3}joBkTRnEn_)8kz_tguY8;4I56lP!}huqDDW-7>{8z%tJgZW(1+XhG7g>D$ut(>J7V zO}C}5PcKWC0e`WkOmn6_Q=2)^+SA(I+RfU}+QmA++Q-`8+QZt*y3D4tX>Dt5>uj2w z9l1Ah8*;DaR@vJ*Iy%0Cui3xs9y`YI*WSVL!(Qlk=6K|I?jSf}vt(jmT9 zQZLypxh~lyc`W%UIVAZm`6f9hxgi-Gzh81+@=kJB@>cR$@AxU&?Vuo?4xY9TrW4thbo3B`YZY<1}QQW9h6;^7-dIgi^5O&RQaFsyK<;1NX1tP zRH#a(va1?Yw^aL87gd*4x#|Y>4fO-{RLvaCEX@?nG|dc+C~;vTHj%H5(Mq(xwRyTi zT|m;Pq#;S;l0uUPB@IuSkd&8Plw6p+M88mKExJ>KEuEfW_bJ zl!}y+luIdBQf{OSHLfr&F-|n~H;pijHH|ifnSxF2&6CYj%~Q+`l<8->1WgTr=L%+Pp?YfonDtt%&f@F z%-o)tm+8vP$;{5o&$4HYu@1A2u!dN}fhS9U>kw;@b-69dw$--7w%xYHw#~NLCd?7! zoX9zn^C0(0?jVPsW3Xd@V}!%sG0f4^(a$m55#Z?I2y*my3~}^zymmA@{yHemE6#7u zm(E7#D`&IwjWeq-&ZTlGT!}83OX*U(G%m60l)B zOe!O7BNdP`NZBL{shYHlR7sjc+Dj@S9VP7`Rgny&EYfyTG0BfIkvfJti5g4|qlQxh zsl%uN)SuK}R5nc$RT7mFl^0bSwHd6mOQ7GNU!vcnU!!+nbY+AyRz>5YCq*xf{u{lR zIh#3;xsYjKUSytT)-ca9XR#!#t*mXVEv)P8XY9S~1MH{lp_~z%U+jLIPwd}p4?BkQ zncbc9AKRA$ae8z7(dFoRu8n(@dy4ypTgN@mz0AGAZRB3#KI7izHgi94)m#tvE%yPJ zz`M`=$z}2d07#w7ck&(l-TZg}+pH9*1yX@ipc5Db8bOP|EAST%6aI?174tOaZp@vS z4zW*SzQufqc@^_B=0?nyn8uj;n9DJKvAtuv$JWK%kBN`{9Ww_&D$N$TMJ~}X(MQn) z@kH@B@x=IP@ko3iFkcq}L+F6`5MU@jB%U5m1?KYP`1tto@uBfjV9LHaen$Mb_=WMq z;^)NI$7jV4ipR!t;}-#&*w}bh{Gf!v384vL34sYy65W6Ar)2xY36emg({dApmU3DFFkj||u(z$dmbd9>@N#vv@Nw_3J5|Xq!X=M_egioqW z-k8kPQRnqyjJ zBAS$@-sYj^Hx^9l4~t*wQ_DF^*VNONkCx9CkA;%jCH0e~Tk0jtU&|NEMa#6*?x{Yh z4=tTi8!S&O^zF=of1FOqJe^sSS(RzYa%Ii5vVr$crgfHez7?_3 ztvKrv>m=(8>l7>5%CVVkyKTp8)wbid)3&3wQ?`A!gSG>`-+9&9H?Lpbh&}J@Y!{^~x(Kv=?R$K~f>#Xa%tJd|= z^~H6msDrzsyR-Y1`>p$<`;GgHyV<>~cxUmMipv$(E6muPxc#`jxN6)v+zH$c+(Fz? z+-_VgE`^{W=m}2 zL8>G5ru3mOsdy@tN})zk5vqu~iYlS5prTX)btP3uI~`RQbt&pZ)bXfeQPoj3QG26e zqovWSm|A8X^8&Lsi^kf)+Qk~o=>c3T`g6Xrhj4zf+i^N`u$)z#MV!@~Ih;wHksLox zN6u96oh1nE!<)k!&KtuU&zlXr&h+37<@M$H@uu+l^9Jxb^2Gc~{vNPwK1+}x$P~B) zsRFkkM}QF)02s%pSPg)NL;zf3SgbjAMQlv0D3%F;EVZ%evC#n5ksiBLBp00$ofO>^ z{S~c?-yMH5{y=<9yd%CmzBc|`{Kj~9{IU2W@!R9C$GhUo;?Kr6#BYn=9KSCfn?Os5 zP2eRg2SzH41aX2OVO0V@ftj!*Atr&GFaxakpQ>1_n5&qhkSe2;BqdA9RL)nar~siM^7sp3?6>a5hsshm`9YHX?`bxA5SosrH;|C!z= zqjN^53@D=|{dao%3`|DHj4m0p%qN)*nfEduX5P(wl=&?4V&<*P8<}NUjaeeA+^Vn& ztg%*^HN%>0zt1{Uvqxtyv=FKd6}~}7i0Iex8!!QSK9a5R{}U=qGN#ram;d%95}~P2kgK) zRy**HIga^`-p&C|u`|vY>#TE5&7b%8y)AQ!$ zMdi5*-L3*xq3g1%-c{$i==$#Z?fU8Z&qW4S6zZa$?q2Rb?k?`$?r!csZjbw~yTx5y zTvfcU_*u!DGIK@u%086=m9KCga4>am~2zVmNa;^eQ4LfJHJ@swYN=^dJ@qd& zgcd{#rp3`>Y0siwM!ku;6LmZ4Zd7BGivF1XivEoLg8q{Jn*N;LM1Ml}W1x)G=!|GO zlglJADNKZUlX;ujg|&nwV;yEK<;>-*qXCJQh#K z!vl9clXwzd5>L)w%fG|F&0i#cqi$j6EH@EB0n=eQas$!Puj*+hg~|UW>gP zyEFDu?55Z=vFl@(0|dNCaip}bv?ace)Du5iI!78H9VhJ}Z7&UydgDLFca(-pr%59K zl0iS|SYW@ODIFtyAKy;;CH_+U_xOT@;skwyH6b-2FJX>6PwtX0Qs5LkC07}zlqn@j zAC*%zQthYis`gd)Q9n~Rs#7(3O^Sx2Ih|OUxH+*packoG#9Xaio1>ke3)gMaZPhjF zKI+yc6((gTsgjD4%99F`>`8}`GLll04ksT^K9PJ>zeiuDKdwKaU!%XM->2WJuhJjU zuhXB@@7EvF@6_MW*XnoZWhqZno~1lVVH%^18AhDRXtJ9!O;%Hi$!vOM`eo{5?rR=y zUTLmNJ(+qw^=xW!YDMba)Uwq2)I+JKQg5a@QjeuxPraBrH)CkV%#5Inkc>$g12ae& zQ!_?qe9dg1<;nb+`6Kgh=IhMCSsybuS#8z|>w0UBb*(kuy1}~5y3xAD>b5$qCDzT> zI9ra*X1i&-Zo6R<=KRU&YwvCEXYXTQZ)ZEG4u*s4pgEWT#yT26U=MN*bPji_ z0IaIUsdOgh?Z`9crRBNvTzN@(`FUk|Tk?|goOx>tw-jzITwl1ca6@6StISpEy5zb6 zRyijZr4{{GG{8O3z1v*{zB_j)?pEwue7bmd$)1vzCG$%clzPhkEBjh@tYT*6ib@|m zg#V5EhWm+YkME54#dp9z#AgsP30Z_3f|c-zu$MT2Jd-?~96_E-o zLY_zt1COdoY6Z2LT1MSP-Adg=mC$_YzoWX+zeRPUccy=!zo);UzoYXQd`5Y6K{U!_ zF*(fV%=^qI%ty>d=2PY}Rs!oFYd=fP5pv==(Hs)T%t_|Rfah8RXEVpa+0M!3?BJAe zHgF0!yEqfjSe}%pV#Re*Z5+Fu>44pj%LgVZJJBkCq~t|mic(>OKRn)<|ZiANGICZ0&Vm3S=i zTH;*YEZscaY~57dOx0S_UO!RR$4!kc`gknbj$)cUGUQ zepy|zj#+P5YprLkh1PoO59?lQowde#(z?fb+j`l0zc#c$2&(l!<`wIrHs^&B;xHjF-ro=E>h@6K4k z+RJfrwsNeT%bWw86P$~j3!E_Y9Pc!*o_CaYjCY@RmRHNG;a%pPFYDo2Av#Q_{oI1JX^>HPU_36A5(**Ai|dTu8W;a5&*g!o7rt31x0`CQpe<)@mYo~E9mex-h)UZbhdRBASAUMJp9e4qF#ag%nn4y#+DTcum6JEFUn z)GN6zsVV6}(zB#DNiUObCErf&V(4Y)Y#0Je=7$@G8GH>r4ce5wDW6h4r+i2mWvn)B zHEl8dHgz^r%{23hG+NrSw3xKmw1sKQ(IVd16z)V)>qaK))s5K?DpB;tY;A1&PM+Tz;gy5;I#)T^j}kzY}tq8>%`A_lPjbQgsIo5GpysqXRa z>F!{6&*D+V!;6O$2Nn-5ZZ3Xa{JHp0$+42(CCw$HN}Z+s%14xkmX9j$T|T7zZbd^y zPGwo;7`#6|5Fdg6M#v=_$qsTFIfHB`-=f~6UZ-B6hSA5+gXuc@R7MQrSoD$T9N%A2r_-eEYDq;yDWD_?jrjf`vUu7`&@g9L+?m+m>gz@(J|e*-dW)+bFR)e z=a0%)<*&%+=da8km~Y4z=hO3L`BC{u{>8%j!b^o03eOi-xemE*yM`7GFIrP{vuKI? zfO~RryAp5luF~zL+e&wq&Mco>o?UUZ;&H{piboX>D&|zKtb9%^B<~{Mqu!-Xqcd5J zoJiEe`@(DCb>#oz{pNk=9ppb0gbJ(UcEp{DI~sQ=t|o3*-0nCQ0K(lZ@|AU!wMaY4 zeo1@DddPk!{7Gm@_>rJds1%!(CzbtFWHnVyP#@Qv)Ew0u({$JF0v_2>9b0!+cTP7p zd1UgKSs6WvGLbBgB{&n})&ys@}@$!V~%u45@&iY;ATda<;w^l#~f z(o?1Q^5}AQ`O}JimE$TS@f*oo$d9Q{sL!e2=#I+w%rBhpoc}oAI1s-F|Eb`S;6>b{ zxchN8+^0egH$y1Z(C5sFagVqphh%+b*X(znQh5U#4kMeKlKhM9Me>cA=|4#nv{D+16T#c?VMI(V_ z`@^E&MNBuZM(`WhhWv`#D_SKRBHt{(t!z-ns&8s=$##Rya4cm&`uOz0=_4|OG6OUHGvl(v zS;w=K*_v#9cAp$;Zcc7?F3Y~#e#AMUAQFH!&M24$fE&jaJTIJ9G`%RI$Xg_I^WBu< z#U%?%=9SDTxmtph;!DSug_P|s-&bB!eyF^>;$y|2N=BuiQdl_)KNEj}e34v7PN6qM z--yPtyqsWu7ZFEGHDhvN>fl%Wjt6DW6m+u8gZJsJukJ z9Sxx)fM?P%{P%*MqWj8=Iv#+!*P1oaeSsMK`mF`(cn@tQ>J82&qOoxv-7fD z*&6eZoKw!Yf(1p(09eKOBAJ_25>!epWtIIb|5ct`p|9vvsi~A#er5I-ab@D<_~e zU^DRDu@kWQ*cxmd_5#+8|3eTH4-*3@7}_{mPlh-88NXU|Nz_+7S00X?g?){Eh<$^7 zhJA#+kL^bAB@895A_h@LPzKN@(oFPJdT+)|hLWLR_%Mx3GqaB6i{j9J;wj>V0A72h zc$a(+m{~cbwHk-Jy2AtEaqu^6U-&aHko}JB3=f0b!yVutxDV_Dd$7IXDtsS8Pr@cb z5YeBwnrJ0aP$p4k(TucYS{f~hW}sTO5 zfg{Kj>5J=cb*hTOq za*1+cF40a5L#85Q5CmC_3_^w?A;>^vHUcB_kx@u6vK0A1enoyko=;g!Sw&e+SxF&K zI@0FRHqqR)HMAmHE^QsnL9^2~)7H{*>3Q@~j4_NHhMkeg$Yx|Q@)%Y|IwPM^$aosv zh1s2%&CFujn3>ERW(U?VRw7Hyy1}~6y2ff|y=Hx2ePumkHL)65zgQnx-&wzbd9sH! z1GS(wG#9m_1!xAEfF_|jREC<+OjLvFQ8}taKk+^Mulz6kZ~Vo=r9zsJBwPg?2Sx*r z7*W6-;5E@8@nCVHSP0;`Q^nb0yEp+rZO4jB#1e6axKLas7KjyMJ^;SX6)R;r8CQN% zeq4S=eqMfBenfswUZ^Ni8b)%p~|G5t({~nG!`2j#yn%0(P6fm)6BVM zr#atjHCxQ7=0sba{iMCpvDUHCQQ_F^SmOwDjRFW><6V(hH=GQo!Ft#TXTWM$31`8n zum)ZQ7r}9G39N-pa3bu0%isdI0?vcYa3L&$5HpYz#Dq8zGm?pj5FKJb_=p%$A_61_ks=&~jkpmmB1Cw|ck)lNlp?1{C?ZM% zMMhCmj1(0miK3t=DJUg|qNjADEvD_K9id&NU7_uzU80?)9iSbfouS>PRnd;qPSGyV z_R(r-D4kEwrx(%}F_toRF*Y#PF!nQcGqx~xFe(}A89N#47~2?|8Rd+Pj0224j7^LI z%)ZP)%u%c$)(BQG3t^dA29}=nnDv4+o*l{_#ExKhWlv&vVGm$OvInz=v&XT6*naGu z>|X3{Y+v?Jc3*Thx)a@pUPn)$+t35(MRXThjqXN|qFd2D=pl4Ae+&O8-&gR5 z?<43f=q&in#|XL#`~)2YfBC%xJq7;>x(L&RVqvZ@PpB3q3EjeUVX9Cm%n{mzI$@>I zDJ&LRgnFR~xERz53xpveqsSn7EE*=x7rz(36Mqoj6CV&ahe;(cPPxLj-$KNg=7hepdih;>o&2HvhP*+3Uw%n`UA{rFRcxr<$X( zsobjF>aXh0>QCx#>K~dvnxC5AnqQjlng!aq+H=}OU6Ss%PL=#Od9u-N++|#EJY?K& z+-VFjuQ8u8Z#S2i-R4sBeqiUi%Y4jSVLoEsXWjyAU$>fT%p1&S%m>Wt%(8T8x+Fb5 zoou^dueaZ{U$)=2-?HDa?{(~R>~>T;_Bf`yX1iv&X1Er*F2m>GoA6$^4z7n!!wv95 z_#S)|u7)4LweW5D2z&}Y48MmL5tb895o!ptiOIwwqKjBebQ6ytYmuGEM&v4T2Jy2T zM0O#!kpsv%vo6G2=d?j#10F$hgh8$!K6)Wn5sKXIx=CVf&$xYwdl` z40qjLX3m+p%}UPRKwe5-Oiq)Rke88bQ3g`56bEG#bquwTDy5RCGpGgBS=2dHB6U7> zGIc7ILhVkSPQ_DMR3UY0$+VJlB@O8H=$}g((yP&5mV7U1M6XZ(R`LauU1&ycPXAHT zg8sAQUC9(6@V$z;k2#Xn1qd#WV6_Lj&Rv1vazEBsRtF%xJcc!p)rj4geSrOeeVo0M zeT%(|{f&K%y`Q~}eT4mz{fK>+y@h>-{V)3~`wROG`yu-vdk6b0`ziY!dlUN?`zZT0 z`!stU`w9Cd`v?03`y~4i`vvY6D4tI)cW6ZQ`7G zuXv+)gLsj6vv`a6AMq4WP-?EUR4SIrq(bRQ=_Bbg=}YNd=?m!-=|d?bJ1sjXJ1#pS z+acR3+alX6dnwx|J0{yJJ0v?Q+b%mLdnJD(AE=n6n5|f$Sf$V?4=Zb{s;R20YN+a} zzAAqze<+`-o~df8o2Z+rYp5Hm8>t(r>!_=#o2ln&=4<9@W@x5sE^E$c&S|b_&T7nB zqxJ$QVNnI>U8?mOy-9D@TlCcowGCAacvINqH|;gmGB-3gGB-DmGG8+vGv6~`FdsJ` zG@mygF+Vh4H{UX!G+#EKFrPDDH9s+*G5@u6vBs>|t$(cFt+i~=Ksk)d*0Hvi)+^Re z;4jJVTR&JoTkG3?TEAG|SzlNmS?^hYSU*}{TU8FZL+_9|rnvH4Y!}bPbzO8<_tf%8 z{SSlpgKvWOg6~6nLi<9OLq|e;L&rj=LdQdw!WYAZ@%%U{UJ#!f&x?0N)^e$M}tKMXkv*&q2O|7(6LWP4<1WH00hJmBvNMnChaMsS&D$3R7*=GHRNdpgO4;YJl3NWM;{SlE!o_ zy+3_AeFl9beH#4{eGGjbeJ*`Gy$^i~eK;LYFQgaI2heBHhtUai6n!)uN1sfeO`pr0 z$vnzD#5~MA$ehcfux7DPtfuT{>`t7voH?AKoMD`CoOzslPD{=ZPJ7M>PCuY0JBX9V zna&x`>A-2qY0l}%>CG9)S-=^~>A~sD>CYd;AHW~NAI=x>t!5Yh3I7rQ8UG>w0skq# zN2yjo7cc}$K?5M55E0;kh=M>M5`+bQ!CQez;1G}nYynk}5QqhO0YzXHlnVw4I0CQ0 zC@>4`f|dds&8bnl79w&T1He*6dM!=6uT6M75f$Y6k8QL6&~dYWd~I|Rby2%RZ~?r zRTEVURU1`XRaaFnRX25ibyxKW^&oX`^+0t$br*FX^)Pi`^$>NThN#Kc6l)4JXbnp9 zQu9i4PxD6eTJu74OLIqaTjS8WwUE}U^=Um?r}mn*v97wVnXZPek*>C`uCAf3j;^WB zt`F-ydY|5<_v;~jM?(ig6GKBoYeP#zGeajsQ$r&|eM7N{W+I!YCX$J0ikl*)L#BhK z{ic@YiRLlpALb9{@8-|uDwdz1d`%VWAZrinFxvo7@1cziW$R(X+9uhi*m~O9+q!}( z5P7zCw!XI7w(+(FwwAW;w$8Ruwn4T&wpq3rw)wUKTSr@e+dNw@P${Cofp#o*taQX3 zen;4mbvPXfhr{7@q#TfAnIq{~tf z*F!f#4?}lDk3-i&H$zuLw?dCX$Z%dbKYTg-AbcZS3@U`~jz28Fn;Mih<%y9zBn?SM zQjrD7c}NmcikyvHfSiIPBIhDYkS&likQ5{r$w$(W4CGAYWTX%&L*kGqq^7Qy()F!^Gra#$aY+24Kcv zCS&Gd>f&nQe&U+rAK<>=Zs9(Gazw9jzj3wk-*ENtA93e!weW9n4{;xGk8!VX_i+vJ zzi^H5PjOZ7_3`g<&vEZ?4e-_R#YI#Co`4~+31q@(!U%$ZfFw`|OhPH4fWRQ&2-658 z0-7+LKqSm21PBue3kYKf^9f=CmoSTfB47zq3B?2{QAj*M+)pej?ntUf>Og8s>P)In z>P>1u>PhNBYD5}LYD(%x>O>kynn)f_-bmg|-a+0({+B$GGMbX6#3?z7hZ>?fsC%g! zs5_|_sh6ndsE?@Eskf=esT-*`soSV0sr#shsAs7AsYB^Zx`%G18|ZuJS^8Q!Oi$2P z(*tx7-AND8h4l4w1wBI-(AUxR^riH1^c-DHhv*i1nC_>G=>^O)OeTxQBC?8D#jFxm zYqo~tGu#DB##CCwxV$v5#AaXm>@NkfSd zlqb|nP0|jsRcRHB2=@)k8H-H9|F8 zjaJW5FHp}_&sXOdYLN`t~T-QT4 zSl3n8T{leETGv*M+*`VpYS|7gQVAP_La(BII< zFvT#-Fwro{Fc%00^fu5HP=CUPh8*C=qa!}7^olR*ga$p_% z9NQcR9S0mo96KEw9LF6y9RE7DJ5D<`J9asCI}SPaIQBZwF1M@9wbHfNwaS%pg+Z|$!Jb~8{+^DWF}`uWVjsz8@GbKh{5rqJ zzuSM%zr(-Jf53k&a3^p(a4T>%a4&E_&^=Ty)FjkCR6o=u^fvS&^e*%%^da;ybSd;Q z^eXf`gbm}vgm6I^6Mhx`6n-E682%Q16#gE55q=r|8h#dj6V{eF%3NjoxByfwmc&Kz zeQ{o*dimq>L^6#mL&lI9BABHZ1ICA0jxk}%FpDq&OnqD*{3v`Id`EmQd^db= z{Ab*3d=Gqkd^`Lw{3QHH{6PE|{Am0De1H5nJgsOwAx6j%w1mZkEJ00JPS6vU5!MjO z2JI8@>I3Ro>S1bg+6QV~T1#3D+GlDr+BfPi>L2O>YBgGGS_fKV+FxpQT0Pp_ zk{Ep>eFOb0{W1L+{Vn|v9cFx_pQPWTf1zKdf1rP+(-?Q@d+E37x9ErI*XS4N2kFP? zr|GBY$La6rSLxU3Lz!$QkI7&bGdWBq)5nCFS>`(CdFFpiJ*$+ZW0_eJmWIV+Nm*6c z^|=>0)w#DgeYvkVFF5Zxjks4hUpX&1k2qgA&A5%ZA366qwYaA_wYg&MW=<3CTh38V zbM80JdCqUnFU~VgJ#JlYEACm&an5bd9nKTZC(Z>s4Q zjGy2q`DOe){CE5h{Ez&>rN0C-g|md6gmZ*0;dtQ$;S6Dku%B>}aEg!wgj3oJhY9Bi zCks)+al&fCfkLv7BP<4TGed;Eg;b#g2)&E}x=e$C1P)W!OQ;qygeoCMs1c%ptjq}E zNFhPkS<+E5Nb*xWP%=c)P0|BYEFUWA1gegYm9&%0lMTDFCQ%LCvPclEAJv7ARi*{F7GDqAnzmZEFUWWDIcT| zDM}Sj6*m<36;Bkm6?YYn6jv2x%82rYa;9pQYPxEHYKCgADo-^}HD7f{^-4umGt^9V zv09*(sCjCkTCC=(Icl=HL@n3IG*XRNQ&n46TTNSETV0#fKG8nX&IRh;({;0T^L2T; z$v`c7hHkMwt6!;Kq{kaX2D+iZfHkl|?f!g&z))=98_pcwKD6HSv$OcTqr z*tF2J$aK|&GUuC-=0E03=4qC>7PKYbGRrc-vcNLd^2GAS^40Rq^4(J1I^H_LI?1ZA zjeX%vRAGIB~y|g{F?Xy*}-?lxrU9fyhkU!mIJ@1dWeDq%#pR=7sE z8c@V$gel>YFg08yQa92gQZ3Rp(lgR1Qa^%-G>!ZX{|?uTRFCwERE@NcbdR)&w2IV- zw2bJ={AIqfP?Fo!YEG5aw8Vf>hLn9G<4m@Am$m=BmUnCqB>nC7?wJO|If=i?XP=io(n z3_cG}!WZG0cp`oRo{pE`f8mc24iiohb`rJ|HWIcFHW2m^juUnfjuN&J_7hGLHWRiI z&JcDGLWC>CYsBlsPQ}BDB_uj&E{RE!l1fQr5{JYlm5|<%^2vGRx#R`pdE_JH)8wP% zQ{-dh$&~e!wUn>aIkdU7ezY01k+h+-fwY;lL9~2YAKGME=Mql1TS${og?z-4mZan#)5TrPJqSHzvpRRX2?DO@>sK6e~<9(NSC zn41rD=!bIA+(BF&cRY6{e+GXVe=2`Ae+oa%|H=Qw|IYu)|He-XuLzF|gTnp7oG>bk z2^R`C3U>&P3jY)C5grg`g(rmDgd2osgv*8JgqwtWg@=TgAm|zp`h`n{i-h}x z{|e6wPYM&lb;2dWS&~9fr=KpN0__2kq(mZ>s6j1z8c-#`OQuQYNyMO1K2lO3nJ!r% zAxQG2eyL9ymWHGO>3G>x**Mu)*xDPJHj zl;4;CmH(0dmUmES6e@*{`&Q9NSxxy>@kjAX@m=vv(OCIY@kQ}k@mcX(kyLI`-d18% z6cts4R$)~H6<5Vp6{?C<0@Xd0Q=L-B)IqgfU8aWA4)r3nO|4NU)n;{Etph(mvT6(( zji!mVwYH76skW82g|@46WRBnE`4Ssw~A8u7wEd5lSsx*kp^+!nTMk(?NB^4%Ru=>DI~Csn!|R_x4G4tX*l> z*n@VzooPqeC)*u%wtcXDf!$yy*o*9PyUb3q*Mi9QQTDO+;dZTknq6%lYM){6W4~^j zXCGvrY9C;y*v0lS_B{K1JK8R?AF&7Q4PS;hIq(ZE^5dBt_gb;fnpb;otnb;EVqb>0QJ)9$e& z`|f-02ku+$CvK(3;W2q=o=F~+$Lg_r6ds$$;*oo_p7FkUzPUc8kKtqa96q}b@}2f^ z{9J$7@AC)zLBHQ0^~d}nf5iXJf6xEQ|K9(`f8PJx|Iq)y|J47%|I+`-Uo-eOP$h^6 z)(F-L)(%z;)(fITlS0!&b3zkBjl&JXjlxaBEyK;j^}-Fq!mubjJAwv+?qee?AlA-| zkR!Ipz{uRl%!nXT8p)4PBkYJMGBQGoh$BNHg%NrL8IeZvA_bB85o}~=Bv+Ox%a*0f zBJpTE98bj0#(%_r$G^ot$7Pk}<)w*6Se2A|E2}A+Mp#Xbbu|`XzdB!J2|z z*cRCO*rwQDm`2$4*ecj&*s9ncm=4(L*uR+X7&l&z58=!44!i|#!preqycX}ohw%Zt z5^u%3@H%`9AH@H`^NVf~-Vh!WE)!l5ZV+A*UJ^bM9uV#kZW3M*?htMht`nXS?h;hQ zd&GxCda;#cCK*T$l9ps4sYo7@o8%%HNqUl>q#>C|cybZBfP9U7fqa#GmVAqRnS7o6 zANdk_I%OI~MA=H|PwP#aLL<{8G#L#|E1*efr8F~5PAjBoX+#>6Hjc)l(P&s&pORiB z{Yv^V7BGkm5<|{VGNcR{!@y85Sd8V2JcgA)W)w5#F$x$|29jZ7Ok$KW_>3Y3lc53y z#TPOcu@#LaTAa}(SU_aJu*cNzC6cP@Vce;z-}&+!-X5AhH4 z|M1TWKMUUrtBHDuz6nQ(ehLSQ>WK10ZA5K>s9bB&I8js4Yhhg=rzR797rqe=5KR^h z7L5lYYA=PgL=8pLL^VXegOLbP=F8x0JZv9UE3d1(TLBkTmD#HQ8e!~$1Y&dH;Y&dE-WjJkEZ`fgo z8+IFVhUJEJhJOr;3?~dS(*x5((__;eQ+G4TTx@n*92T3!Y4KZp7O$m+HDOBo6*u!=jD2Uw6+1tr?PIeA-c64@ewsE#|PILBmPH|3j&UAKm z4t4f*4seclHg%454snifPIdNl_HvGPc6YXQ4t6$iesw){y?1?Z{c!zpy>b0=eR2JC zy>q>Cy>!9uMedwC>wfNj>3-&3?MZsPo`@&tiF+paI6kiLvhSSlsxR)Z6Q~;a>u(VF z?XMfC7N`}d8K@EX14?XH4>S%o2{sHi2zCp%4|fiC4R;E62)7M)4|fT-3v0vDuqG@E zFN-XVC?n~JHnK1hi>!+HBg-SH$m)nDl8BfhOCoO~frvFy7FirIL|llRTE(n0lCcnwprNl%}R>X-fKi=0oOlW<~ZdvKneI>Kn2q zsut=C@(;2esy^yBvM$Pt_MzXS-=b$@r()-0M_{L5=VIqzXJYYK0(LTX79rAth9Lgq&mu91BXd7u8 zXp3oXTACK6t*5P}Fno+9j2wf* z*vKenD4ANOhN)w2V*bnA!rH+4hqZ~djkSuko`vAmV0;JxQQ;&$f!<-X!R z;I`v+;QitD;(g%0;Wp=e_)GYU`OEoLN)e@h`Bh7&hq!g8ktRjp^ zDng5pBAh5Dii&{fAW#+Liwq*RC?qNnc|}~2NmM4H0~J4>NGIAPSuaUTHb@pqQj&ip zTO_b#nItP&Dp@31CCNxuNdA?SOH)$33@szeC^D*y1oR(hKmno%s5&_1Zn;P9kXz&i zIV5+<^>U58wxX88sOX{WsBEL`plq+~rfjS1t!$^vC}Cw*nO6E$L6uwOQk_xnQlC?w zR$ow`RbNscS07RzR-aI(G>bF~H5tufO8kOTyC9nr|(zqOC}4o)u;74vm8vK?tZ1)DWrzHGn!n zb)jBRd+4XVAN0ds8>$a|viF5P*jqqf?Jw;g?Z50zp%?b&_Lk5edvB-%G!Uu^{kC_6 zzSxIAJ)x)eXZCmYxAyP$)=+0?FjNm}0}X;o99Spa$#ANi_nk5)-dX4*I?+y=li)-- z$xeZj=R`X5oD?U?DRP!NwN9b4*vWL}J9SQlv&6}Ea-9TM4R?Kab9X&=D|c&m8+T22 zOLr4@Lw6nbV)s(_68CHOJNGO1InPngcF#r61PR}0C zbF)VI)|@h|eH{hb5d0zCrV0|Nss0__4V15E;L0zCu0 z0?h+W1FZwi0__8>0&N5RgWZFzgKdMIgWZBHgRO$HkT@g?u|xdOpm4u%pK#ys&~VT2 zz%Uecggs$P*c!Hn&EfNrLy^Og{gLaDt&ww)_mR7iYmw)XtC8E0(~-B4gOO*Elab?* zvymr}Gm*=Y6Ont7JCUc63z3VFEs^_?9?_$b%@KXsnzGep>&iBiEsZaZUyRpC)J{}Q z5E7n5AmK`!Pn=71Ebma>v%C)w+v!~1uDnI`=A;?v()6#) zkIe7P-^|xcEf@iR&-~2PhHJppVO#cMwo$Heu05(5suij&stM{2YIwo@0x_0~6=G#r z7M6|`V5L|xR)uYkYll0I--ADa--q9cKZxIrKZ_Ti#Y({KMY)R}*Y)kA+ z>_~h|TtnJO`iHcFw1u>Rw2rijw34)mw3f7CJJjQp59kFuMx zivrVD(&Druw9T}mv;(x$w4JnlwCyw>?JDC6<2>UW;{;<5!_7FvxXJj)xXu{HG%@we z#mwWZy{!GLldMy$bF4kAU96p~)2wdn;XD>^4v)j^bv_y1Fv|DsmbX-Ih9Tx2oWkn}ND@E1C%S7u$J4I_mt3>BS`$XGCi$y0yt3_u- z>qVPH8$?GW2POL?+a*^d`y~e?rzDpoCnd)u=OlY1*Ce|oMJ+^KOo zolBgMGvo||8vJ%=%$aefoNi}FcTe|V_W<`mcQ5x4cUN~GcQ^MScYk*$_j~s}&jZf~ z&nM4k&uve0?<3D$&pXd?&mGTw&oj?o&s)z=PuLgng?yiVZ+!24?|dJ9rGBA*nSX_U zSYTpcbYOB|Mqp%Md|*OgN?>qcQeaPDWN=_`L~v+uOmI|icu*PAgmfWC=tpQ+ctm() zI2sOx!(o3o815DA7_A-c6s;L;6xBvYN5@CoMY~0tMyo_;Mh8S2MjJ#=MLI-(M4Cmv zN4`deN2^A=NB>6pM8`x&MEgdYN9#xHMgK(VL=n-Sk(SZjWoOFvmhC9pS+=!oU)h$j zJ!SvIFU9L6nkE`2l8HnjmUx%=mKae!sC;O7_hhGJuVkNOHu)y`D)~71DETh=F!>_+ zJoz-aBegHJIkhYGCG{iqJ@qv;ENxChX=hrWHl}rHYdV^aq(fSq3;yep)8PCnj z@zT6Sye!Yji}C`zGM=9zfQc_|*m^YJ1)B7ZHvPU&gUKcY{fOQMIOTcX#Z zr=lmKJE9Mw+oA`eXQKO(_mXFl50XcccajGZnM^1X$rAES^40Q?e3g8ye4~7se7(G} zqKTrZqLIR`n5LYqoTHqjT&jGo+@e~o+N9d1+N#>D+NfHodZ+rR{;jU6`KkV;{;U3= zuA%v^{-dt0S*=;ADb^CTSS?;#s3mCkYWHgoXlv*j=|2D&oWHuCx`z5sx_bJLx~lp* z`fB$wLo`k| zjy29OnM_8L!Su=W!PMWp%W~Lq+H%rz#B$8C+w$B(v=XevRvTo7g3t=63|a_zp(T(G zS_-A0ETn?;kQ-VAX(2U)g91<-azK743BiyBS`1ks7X(2XNC}lgAt(oN9DALsoNJv& zoEw~LoI9LboV%UtoF|-zoClq!o!gx2orj$#otvFoo%@{IoqL>joSU2@+{4`C-4oqY z+-UbG_f+><_j>m__Xqb!cSmn)Z%c0zZw+rfZ&z<4Z&PmzZ!K>FZ*6Z)Z+mYuZ(DD^ zPwbQWBtDU^%op>0_lf*@fdzqr05UK?Fe@-EI5`M~jG@utRCsYX9ZrUG;YDFMyfC~d zYKyLqGNRb%tf)SUj}}Lj(K%6M6cwdL1<_!1ev}v0L~&6}6dlcvN}{T$E=r4%qx2{{ zninmK9xK~lcB1T1*^#nsW$WS_;%nla6P*&R6CDz55~;+ZL?)3W=Y1)xqoL-n-pB@HJf!Xj#cpy9o z9s-Ys2g5Vqsqi#-B0LJ73{QYRn+Cw1tUK$^Zpa?b-pKyU{>^sJb<1_l73LP^hM)$Z z2BONb8EgWZ!ot`jR$Mfm$Svj-??rz zH%1j^HRdlyjCqrJgLRX2jdg^#gSUrwpLdkEled+(jdzTJimOQfO1?{~Nq0S)@cN3zRq|LAhMHNBK&5P_h zm2BM%9fkHohoFPdzt9$F4|EJV4DEwXL1&@k&=F`Ov=#af>h9PMZG-kgT*p)A6Xyfx zP3KGJ3+H3!UFS#VBj+XOE$2n&Yv(oRL+4fJb!QdVC+9QgZD)ado;%+?-#ycfbfesJ z+hyxqLRyo0?XytBN6yyLwSy+gb`yraB5y(7H?z1_Xzyc4`*y;FS(U(#3ZOZfiy zs{5<@5&q&pNq`!_1+W2ffEi#1hyg-?79a(6;Jje(@YwLU@Wk-S@UrlV z@cQto@Rq1A8i{U;rlWAw9bFL(L{~+#(dE&ys4JR`=A!1PKe{m*j&6!BjjoJtjxLG* zS9Y=NLfOCZtMME0gQUChYw_FhZi%jm9*H%Hb%~XU)rqBvRf)xkWr?ea>xnCgYl$C; z3aLSK`S$WD$??gt$wsMqsXD0!sp_dFsk*5esamO;sr{*2soLr4=^E)i=@IF<>G|n- z>0{}m=|ky#=>zF4>Fw!@>80-D5&WGp1M0g%t1Y_a(Fb+n;g)jxi!vr{x z^=0p7tK<;5mbo6ee!0H6KDpkx`8iB(IBEotP5z4BT(BCu7P}m~0=o*k273d48-Eku zv}gixB5@M&5J^nlNBK#s#ca%Mz^ucp&uqxFGw(2OGw-mT^6v3Y^DgkN^G@;Z@^10Y z^Ir1K@y_t>@TmL^{Q9MBfMk1TaZ7POaTjq{aW`=vaVv3maeHxnXI!l(v1i7KPWs5MHBawEq$&otL$GdWD#OutQkOltF0%VkSFE5k~&(ycF{ z_t0zTI&>d;2Hk+JLa(3?&^PEBbQgLE-GVMa@1Q5pTj&n-07AHaIIFq7IKMjUxazxr zzKH9Wv$pH6v#zVEtHe!k6WusB&0XxqyGiaMx68fFz1982jr7j;&h<|A7I?AVLhn2; z#*6Y!^`gBv?=+vvr}U+KHT|{xb^L4mtNd&ItNnt2Iv@-10-}H}a4>)lqJsHBWUwH( zIXF2yDZC-PHhd>~EP5__FnS|;KKecSDtbD4J^D}dN%Um&QuIyqVf1qJaP(|+fAqiT zvgp&Oq3lN4&9eLPK8b#b{)yg+o{4`G+Y(z7w-a{~cN4|sMdhS&T=~B8J>|Q~_mEsVwoSE2^+P$8!TyVVh@U|` zN;*b*Lw-x%PdPyOPHV+%$!x)F#=OgX#(Kzl#QMm4$9uth#{15D&wImr%Ns8qAs!?i zB_1vwBAzN9EuJJED;^{6E1oPKCmtrAB5o#aE?p@#$n>(E^3}>!%Du|h%G0W|s&lF{ zst>9jnr@n2n%v* zZsAzD)~=4fP!-1?sGS4h_ySdT)N#~s)OY-b+PE6Knz&lInz>rK=x&yKhx@CW>g9P! zUXGXUWqR3Ofp?wX5pV_UfubNbhznwZ_#h$Z4^0bC32zH;32zGj8?F~?7W*0P9BUM7 z9{Uq*5o;Xl9cvS75c>>d{k}$P#Tv$1#+t@{MC-)9MaReL#{NcsMeE1DM4QBF#_p8e zE4y1ZFfk~xBe5&-JMkw$EiWmjms83QlpicdCi9X-$@$57$%5q2)bP}hRR2`p)W}qy z)WFo})PU5n)XCJ*RO58hbdz+wOzq6qbd5~Y%(wL9Os!1AOwCNIO!G{gOb$-MOJNv} zz~yiVPQwe~7@UDu!3lT~oPrm_E8#4>1l|Y#1IOXz@CrDYO=nZt$Js~Or`adj!MTAs zVvd?4=SaDtTsSutH3n>s3G^ZC9_(K1Y~n29DbhL8d-88uJ7!h>FJ3kNHz1HWO*~yZ zS3FxhM?6D3Q`|w?R@z2tl(kaul;>3gG($9lG==&C{Rh3r=rp>FUZcb4H!d*kG7UE0 zwzPKib@X&}a&&XFceHWzatw5IaddX{addR_aP)C?aJ6%Fc6E2PclC44bqU;Dx6sXZ z|8Q%(YVQoM)~oY2_BZ#h_Xh&L069nul7chC)59~uJHnG<<6B19+f>T8<7~B*q6AUV3eOIKU%)O9G}D{$D}5tW~Qd6rlzK(#-=8v&ZJtT zTcum4Tc*dR(dmAf4w?3u{+Vu>-kCm`?wKx`ZSYojH+%p-2A_n_!F%B&@F92?yahfB z?|^s0YvAMXMtCiJ8vYkP18;)0*-Z9j_D%M6wq34uu5E5eE-%N-F>;aIj=ZDTBiK_| zNzpvweBx!&1=0s{7iMQ>Pi9wUJ$`L|9e#sSj2J7%iP7SY(oWKUq$b%l`DOWa`Bk|< zxmGzsvsok7O0+nAvA#%8)D!fd^zZdyW4_60x?|y6hdV|%hB^8>hB`(%`n!6&db;|$ zdblL+eeS*PpKhbq?zMUyUdU_mw(yq)Vu4g35(ow2fkc2BED6pE&yOKvb7S*j`LS8C z8L`>1IkB0sNr{IEUOBh?RC!^Nn9NHRqzY5>Q~9acskx~+DRc^%I-hEj?w1~y#-=gp znVH#{Ntx-HF_~eRDVgz^QJLYHp_vJpk(rzDfAAgn27C%W58r|>z<1&2@OAhadCS0% z2A@G@=4KXT=4CLMqRjkEUgjtK6@CjpgkQqn;79Nm_&)pwegc1h-@y;ySMVqJBm4}0 z4Ij*&&wj{$%+}1c&yCKF%8krT%jM@JIdM*y6Xh;q&tUV2g5m+p*Q__JW_*g6CMJog z;%?HL^2hSas?nNlnynh1K4Em51lDPe(XLUh5w3Zzn77QE4dem~18`t(cu)9Xm>=WB zxUt9anTcsYjr~~Sae|z>oGMDwGwcj2Q<5QPsF|wSKX9#VwQS97jVvNtC0i%^7yb=b z&o0b%%+1WnbBdfYcL_U?xt-aX--h3c-9U8aRt#|9(f8FKYq<2|hX<$h}7!$-qF-c4oo0E{1Q<9vFFeAv+%Qnb1 z&Nj+6%{Iv{%6`t)$<4~CbGn>1r^$81vBV<%c-JQX^1z|6Jf@B*V~Q9xH83sD$TE_Q zBGWwEEc+!}H@7s$5i`YK^*qN!*96xjSJs>H{S!D5n3s^1%gaxf(~_%`j1()yPIXVW z$hOMP&ebaE$nPbc?^qeI#>_EGjGN-5+GOWBa$Z|Zli8M4DETRErbCu1=85}Amu8K* zIl1y2(BZSKt6J|zmEL(H^Csm%c{TE?gP(oJQKJjE1zQXH<~j4`~=-+5W!B`*^G_!zI;3(Jzywd<@3%cOIMdbRFQ6-~GhBHSn?=cYwzbuh= zuTnetDc~oSUd6qxVZA6HDv5dw?pzN%3lO_2s8&!5+^1s!r9e>NF4$Rc9`wExd@cA6 z>?Z&OqC2j7QR||iMT3im7Xfu=04wo3v3W5N;Df*v?5t)X+sF+lXbJ*xl5&hPrUZz0 zmpo+-Vr%(hN-J(Ks&snkj8dO0qEITMp-8A=tV>?!ysmkiJa=As-uJw>m5=x>uV#L= z{9k!*@>&9|?%w(B^K0d|&Hs_tDt|6`U@5?6)W4`rz&-JY7{mrYym6+@en%#Hxf4lHx%~%jd zgIGXmU5r3XC{_dhzh(wrZSw!`eI_>q-?gG$q}%}BO@Kxvq!LOAy98H)%pnjjnJ>UH zjAA1YL)jzQUHNDEKm)uKRjMi-4`ze_P*5roOT|KQ#a(3LjnYk01R^M_=phi}HDC$N z0W*-Ww*oy#|BhfhlmfHXJx>CjIFmOce{TMm{83ws2_SyuvPEWO(76LS$jr!bydwLPFsnF!CJx0s9gA7W*3e3i|{*8${rA+$7w1 zTmcRXd&_6<3JE;NIgu;NRiv6)n%c$4&s#9V_wy&Qwl(4saU4 zU6cass)%DE0s%zNh`)*bzyjEd1I3xjC4q`Rlj>A1M?Jt1a)?|FEI~&K9q?1iAIcNT zEy`Ko|DxQbyrO&o-UrG%%6DL!f#5_S#+8gOu~vFOPrSqnylly`l5|O?Bw6AwflA;K z#s5D20-mCxeP$8CVivN|fbs0LWwsdi+2G~Uat4bFF z)`(SNBUomISSMzHMcyUdEj=dPA>Aw83VH}c`TrIjfru*1Krh**+^;-Pp_`2Or24D^ zS*|^!{h`m9!{&rJW(GlO^;r>!GJsMbthyz*H+U=vq(OuKgqDI3sc0)hz2ZIN{o=#o z!{dG86F|todC`0i2oWG@pC8Cyn7=rGQGPCe2^f(A`0}xp;S#E31mZR74{8tyk@4u^ z=rQOW=q>1dXbeatWr4OJ3haS`g9VohAP@(X!f2tpP*eCP8!Y4&3cyILkXPsd_BZw? z_8S(g0QL)(iL>D7I5vm@Ax@1m0gFI<#Lp|5U%BcC#9Ckv0~{>c@V^lRVju8M6m2hB z^S_a8MOT4G1@RCkW{ELkjtB!EQQW379_AF!1$I~Qfyy2Nv7nDy%=is}CZD&yKUL zY!C3304!z)0e@$k***Ea_#8eLY!4RxX8r|WfhKY(VoEFo(sFy1L}_X1T@XYs03MZI zE8SFjw)8mgy<(R*Bo2bGa*Ewzzt{pi9{|_|DuaqCWl1@e-Wlmd=}q9Bldh00k!3-! zt*;EYRk94QQx(${;}laAAn_Dgz=t)5G)FZR_c;dmWTkgbtJKT&fAzog72`#wmF5b& z0r0;7OU+x&E6i(vx7^GwXlOlbooLHg5mT;&!58>cbrp!y69C|2>!wNzB06|Icrth` zcrLgNMC{toj?gG@{!NKbjBkyj67&QvPm{MPZ$sYtyp4JPmql-j-W6RgYCxz?_+C_%@U7@U(efMXCM1A`wyFL z`w2!iva4`va1flU!0*fFSB7iF_4g~iZi2t1%>^|C%>*?CT?7b33&Hx*Po-4_Gl1U{ zU^+l|!7>o1O8^#&cZnB@S5-#sO7T|lCh>|&e}{M=h}ZD|0syd~OJ4)~O8Qv(0NBH_ zJ+gDM6S4!c^B{iD%3jM~$`OdS@;M5mVy0p)h~Wi_<$x>N%1V1o`4?=bzm-o^b=Ba7 zM_o@{3)mLw+JG-=E@{qdu4?q!it7zpo7M`vOWMoYi`w(r|FnO!zqBg7UateiTQ(=a zr0%R0G+i_U(Pi_0fa_QunD3g80r zlwi+R1Az0uVE}fji{%2T>#pGedlEp-hd{g!J`Fw(z6~A>?G6E<<ATC2EfISRg zDFf4y8H)U#-vRkIzdG_=el;X`uSEXJ|B&AuSsOVLIS}+4BS$00Ab;m$kw5d7pq8T+ zfgAx#iaLR!q8aESG!xB6oM{pN#Cvp2LKj}i~OF$qx z0MrBczt*+V>kha%VF=(sgtmmHm18|Cc{gzvaT~Elam`|MaY5z2{-gLMupf&*7e6n4 z3%tJM!Q_GD{^UXA_2hp*uKXqsr35HZN|2IIO;QmEBY>Pbk1C@ofCtWI>OWL3bvf{( z)OFM>bp>@sNyYd;kQ`|GU^)@lHuQECsX`~wN6|;n3xHotpG2Pr5(aF#fKyB)YbGm? zH5sJJJl1T$RMvFX0$@jRx^pV7YR4G~Y=2H04wf^EGm+B~^jdJba(Z!!ICu_*Gnmtj zGmzhpKbT(%lEw@0od1IVn9m2v0bT_KxJpYBUtRL`zj8z(D&|)lbz>)gAa|H^|JP{cCz7Y75$3VrP6C{!`l#3zGXoQ_qIE7jwBH_KQ5K{n{05BFa3DXbr0ta?F0C1S${s4Oi_XO}W++SQZ{8#*P zPNyOSf>=Z(42qJ<4jL8W72}OiL zLOy|BdBt&XNF4$o7SlkQbs^Oy)ggh9Ce;QE(vH*u*v6!0fCrIU1Aa&vLmojMOCDNz zU{zeRi@cLOoHFKr2Nrn!qJnJ@prT!+uA+j&jk*-@8-S+(;JZ|^k?sX42j+?Hphtlx zqw@fl0+;|c(RTtyAXs!cumq5fdCUb&KQq8w3;biulYmbEJY?cPLeg1mR$F!(c1v(p zffszvR!%ub29hzw32?S?ZgQ4!N;wBOb}#~7r#V_q5_sD=J2+xsM}V{p@ptiGSDtI& z1w(L1aJDl2)(WZ%!3!qvp90ht)&#w}!VSRxCa4emjlioatR<`?tRieB{3~b*#(=K8 zq?V+Lx8{H8+E&(B)=*Ye{;@JWe^xTsL=@c=GzCY2K(G}T0fVPe zR`6xzRpk}sU==t|0VV@<1gL1UKpM_dqtyB8sp^@)7ivm1A3*ZG*L>D|)O`P68m9gq zPv-&OR(1Yw+W|s>hE>XjdhflrulKgRWLdIo%a&zJvNdd3)^r@=B({?{@gR2M3<_bd zutUQL1=^HC%Z37_fwC!(mQmV5`+v@je*g3NJoo#)?>YC}bI-c>%Axfvc@{kHdBho^ z-mAPn_g?DF@?Ps@OZ4sa?epzt8P@puKLVxnFRMm3{7RE{{j4W`}Br54~l_Jv;8+F|d<|0{C`r-09i*I95>5@twzZ-aUWs z{Oj}lzYO2Xa^D*Ar+JZa(e4eqBU$tp@BWhGoxA_Zv2&qq;U5d97Cv0~PTmN%UC%U> z7rjM3a&zc=s~@ehV;y|?;8Y{~cH=I^ieg4Fs}QwrQuNBt;nMC`WPQ2$_2w})0bAgy zdt2)*thILEDcq*MNqwDqM*U0m7WFDieJ{+aH>vlir{smdARk5je^dua_uNi* z96n>4`Ub*o*s8u$eTVw6dZ&64?=^M^k*?|L>FVw(*A{7+C)%qxYP1a;8B30>+9r1Y9Zbd)q4GLPX3)7va6SX|h`+D!oME=_Q zVeh9XXX$>F^%~tTbfLOyc!|8Dd|5X2z{r~KLslR8ScRY3W2e zV9KK47;AA_;w<%+I6FI#J;9!BzZxqjD2HQ)J>H&fkG4l(C)(3SH;-O7x^48Vv52vp zvAD5>v3Pcl{t*L(P4@chIR zB)xk#lVy6{$Da2+?QADOL1o?!@36Pj+lnX2kz0K?_-^qX_Bs5_Wa#yG_=o+Iem%C@ zujMF`)8F79$9`qw>l=mNJJmQReq}iS%NS97mZvNTyE1S=pzIHlf`sdRxZ2pLH+O4l`eJ`-J@bKAMHB&hwN+09+ zHAJ^vZrk8ogD{O&mRm6+YJyAx2B!S0mZ z*}LGnNq;-S zU|jI!o-gqKwx?&sy26xO36f^+BR&;;YW4IoXVp)0XagJ`9` zO7`;f>rpcsfNfxe;|Bvv^0F6a?2@fTj`L7yfnCyO+v|nq#fq%(2PdVRy(eo{sir`v`XPsA9Bn zlx4;qkTh1wF`Ct1?PzrrqFRTN<28;dN0~$AsKKsxR5*&z;PGqZ)$bYqay-Pj;#_6z zi=>^`Ca!bscFnQ!JuW}T?JgHbew201xE5WTT$Aq2@?OC170~n94S3pf{H5nG z$4@<(A_NfIoR&s>%Sh|=6Cs5{ImX5Y>{q~w*q=; zW5*Qx(I(TTVYUE~w427UdcePFM2<<CtKZbkcO!bSn{Q`UJ8a_W>CMx2?Aqz}X%#Bc4_klSddW6EdA9v;>*?+$`xx0FI#qN^b z_41lOZ{gyFOBR@&3xf;V#rDNaR(9uN@?yc_uEnlJ(_-IZ&!TzJvY5YEz9=p3W5w?U zk#@1Z_kc*>?D+w!ot5qek-l8{7VF$qzL|k{8%TO{>OKcdJ%Z*Q+K}qpCfsovI7i zB!=N*H7gU?-PKW?9Tap*?bY&|I50W1J5ZOlg%=05k?udD5A-}J?+`prbqtGcldeEl zs>{)(!k6OKtBfX^W)7$kXy;7gA-$bNIKdIO2gQSO#F<3W- z*yZmCML&h78F9%}p8DBFVknL5D z4)ZVB0Zv)Ime=%^*7K}aTQjUN)=RB?9a>ARXIL+^{@YS(U9iuyhPT^y+Be#F*eC5i z`)2$Z;F-*-ZXatMYZ_}C8+Hsh3=W;c>=<%5S-rjBaGW*1!AYkBUnLwLalX&dF)=aW zoEV>=yC&=$Jrf$ccj6Y;J+7lJQIbcN>t3u`_cnR$#rJk;5PrA93Sw%!10g%!yH*_8?77d8-t|9 zCn)<}aQKvFijUE$o~cdpLY>}pG0*SX>*_g*^!W7kEW^d=r#bGKzIpng=?A87n*Lz= z&FR;OJTiUv^jp(Q(^)J}kqWoPZ>!pti&wGjYL5S#`HW@ytyrqFU(BqV{ZwAGpUv{_ zJU2ggBg=FD-16M+x!dRN!agJ~+XG_JvQU{#J6_-M>WsQt{Zppj>2ly?e5{oUk(<$3(f`K0vB8SZt=dwyB8N1H!V)Ha_?E(y?786>Bj4C zy`I}Y&h49S*mGddp*=6|p}T+;&f3(2NSCkjE7(^;&|?^lC4KC$<)y^rjD zc<*uSqae~V=#%i)z7O_&y6=;HpY8i_AD=^OBCljENSb?!D;`<*_(2g6X+ty1p9TDb z;-}5Q&2KgTsrl{Ztu6B{U$&&T-pAstQYI?flzc%dTa>BFa-~wKP{!joD6^GK${SUW zsQCJZJ5&#;j-U^!4y$fOqdNbqW?R!xGkTWh9L>MgKh*?jHV_eMLCYqk-K|~K9@egD zZ_@73exOy$%eR~3(Vh-nm+ltb^|~3B>rJ{{9QDwtb8+0F+on5+^6PKG$NK;)lPMt|U*LGZH%MB2mb%_q_l)la->-eY@jdPPo$t3iYQJY`e&K&#UZ6oi z@AyL|gD3d~5&r}Ke?@fi2mg=gxBmZe{M`Sc-?j0cjUV#>9+)ys8K#D&%={~fUv665 zv}e=OCUM!|E!4^i{T9x^KAo=IvTjTImW(Z55an}*_?iDd&mUOBcC>5eqnYz(uVkIx zK6~@*m$UcH@hUp^2ab=xLvx?bJ%~Oq_tf0IbI;Aah%M5*ylOw)@izMTj>D|k8+RTE ztXzh3K1P1t9-V)9{?YkI=EHWy?~2}a`L4ses0r-5P4X(9S=h1g{l#HFZ3vN${^{w-!aIG!B4B6Qyo(s zS3RQ&?z~oWndU;xB^u_o<|>Y18n@;aEjO;cQ~MdKP9r}sAJP3m_o(i1-5+(wb$fLy ztgmCb7j@6*Qh8LqqCd`BI-TCpzob8b_nQ7`Rugl~@GSa*;VHvegZ$ZJu-{Z_YBBM- zXG-TdZ0g`xZ?c$zq=V1Vv}>~Q?WS5&7TO9GCL2eF-J~*in1iGfqSU)*9%I?C*U3jl z-TI345cVV1Z>^88c#gqK@GE%O{yaw-X&ke7GuxTv%y+V9 z16v2nXb*_=y6bb6(K~Rn`*wH6YOAM$CDa6udyaYjj`G;^e!=pgc2>%Ja5-y3r0B^g z*|JRCE6@46Io`49vcQvzH;*m#%eYIdUX*G}8TnG=XhV2dC`-{C-?Y)|rd;@&7_mjP! z2WI$tdq0w`@ArMn?B;!KZFy~)*}Z*j7snki3-cgS#DVjf?-w69hvVrKci;-_=mS4L z5Q=U&c-O(-9DMfR8wXnt@gCV6-Taqkc97NwnE!K1zjBt@|AOj86>CG2u8GxTYEm`X znyjuTw5(S+2Jh?M*8N%cj_xfc_Md>i&B{~yJ&s?(Lj$iGUSlG^Xn4u+2g4ik)b^X^ zn3}i3Uek4^8I;!@j;p2vvb~Gr9iZibaLzCvz}DBT9|mUZpR8|LKg0e`_W#NZ{S-d8 ze`WvL{+XSBEcPPPoHxrco(@dg2jDJw`feVta5g&2oi{mecHS~^c!F(k;$Ds-opOEe z`a9FLMxL4sqvs!GG}7GAWzPxw%xbww^$`?#l^F^9LqqYJJD;m|781l z+l5!c^xOmA?f56h%K0XFt7V$(l6D!ETua&|5P6?B)3LaSvlD-p>!)M-jdbaKR zTGnsnuf(-FR+E!F1GO#fIVpRQO9Epw#M1)Y;u0?Jj(Ds zI`P!R@rfrU&UN$h?mowTHu_WdS?){R_hO0ktvu*S4D6L~g)c%L;*WfPl~p_0G-;UB zOjd1tkSDW9|K6B1CG-#SfL|`}OwVt*pJ6_><*C46f4c3?M1Dvxxjp0p%42a$CU~u^H%Z`N{dG=4*G|#r`w9yKtdk;r4|a z7|`9Yw6uNc?xkZ(N3nU+UV8KTHv)T&cIEb!xBmYSw=tyct92ZUS0CkgI_2!m+FQbS z=I_njdl==noqgxAlUxAn8OxX9*K5bto?rXDJhBZ3`VTZRriugY9J^un!TS&1$M`;X zFyv75p(w`pUgb&EJF1|dTzO=Dny+OwcRiy$ci`-Sa~Mya1@iGd!(R-4FuiK}tLY8X z`|=2iyf;m+nO>H?YitR&NZZ%eGe*xIy=0UL?D(DIw~iBz+nv9ecy{74_Z9A6FlGji z-ecm2&|BVQvd#o&`ZDB!8fHCOChZ(w-SqmVE3WIiZs0oSb#HHZogw*H9+q!7{cLi)1}Xre!ukW(r@VU zFP2{6_@UhSZ!dkmbaLq_+5R)1AIJYhgZ2d9zw+S9eJc;G{39?H%0Taz)8A41uHARp zzR-P_(%(Okd-&P4zo37GPuISbBZdPW`q^?|;lSnt&I6MNM)0mb_*eRzS#szMdi+wz zVtr+`@+8!Vc)6xhGpTt_dqVrX_Ea}J`@n~WkLA6V_aOTAQ(hBJzD4s=3Rx*x@N@e2 zqS5n5FCD#b^jvHZd0lM#P&O3hA#z{N9lRV{_@=p1t z#0h+hY`I`-$W~!}xn&*t)2$b8J$vilJce@f|fgzTHO;UAXfi{x58fEiiQQ+)AV$_-NRZy^^&uxbnox z<16p446PbgPpm$-`rFla=!d4gx9=_B{`2?!f#c8CTDj*W?(bUp9>v*54m>X3=RF6W zIpCG2(m{@AGLejjetGD(%BwqSHLq}=qdg(KmuB`w4_q^FE%(c|U_MK}*EZW#qrVva zo_o^zRNT|zWaCDW&+7#3-?V)*EiaeHRm4h{8r*l9l6u1wkM0ZKj=n z2DU@mSg}8kV`iYWf2UCMEM+1Z`jw{73O{feD??v9T)S@)1MdThn(o)AH>Nu4GfA_JK+N`1iv^ns)Z^Q)O>;FAqNREwt*a2~m;+qBwmX zH5yr=^j+r^*ZGk0m(9tqlTUkp?ft(p-|gma=DZXALFAwDf_<+eNP0)u=atfLr_(gQ zx&1>ve*@#CljCEIUo`!$T7G>Zk)Md}|A=$`v)<4&)bw#vF-^Edaei}AOGN8H>ssr^ z=HIuCwcFdx?ccPADSx3{RQ^i2pgf}N?3n8~Uv-h{VpWxDO%>GH(D{=374@K|qidq; zwXSjPy!K}8!`dgc1Klrlf6=|%v#;k@J&`(v?xw!petrML{p<7(>#rDy^n`Z3ZwMJY zJb2gO1w&^Ibq}eB5{$9NMAL-HV|vc?k?C90Pt6<5@0kB={?2^OaR2blBj;P@EYp_l z7N4cwT5YYd9yE7j|AYS~XTZ_SM)$j(o>q$4RS~Z?Z4VSL$o@4f$^Oec^l2zkc!+zkaf0BTILxf9lxO zg@ciU)z@9Hxo`7Dn?t9snSOuz-RbwH$F{t><=ZXUTPwDXZmr#R`?j06eY-7VMlrK( zrfqh5b{+qVUT^L=Z|7w@kL-MG{bptz2P%r495BfoTV2HiJ0AjBi z0``O;6PRHbM!*7MXRv`CMqvybz$;Ra6T}WC2Hy=H@PZHgFbV7t&ws@pu+A1593-6* z=6Y9Ha8L$FJ5Gt5RFSje@4`%zqyG?Qx-g%gx;Nz9i>;Bt)I^(53)nzf-bB{AVPSr= z6|;XlA~?ti6W{_jc)$xj@WUj8a!MG4Lj*)Z6hwnaF=#BrK|CZtA|!$I%{FnVWXu#u zg)~Tq49J8m$c7xqg*?cI0w{zcCqiI4=zkOHZY2I-IinUDq9kOR4p2l-F{g-`^= zPy!-JsC4p9+7lg0M~6W;L_j1&K{UibEX09y9y0+FAqkQp1yUgm(jfz+lSe3i zZf^ML3+AEH?)wO>D-h-lvRNq1BeGc}%;U0IEX)^WGh3LaWHU>cyYCk@WD4_$Y-Y%1 zWiwrvH#{H;lne7s*{l%e2eMfu%$Wy8fl6U63-ihnVL};{LOnDwsgMH6kOYa40Me0%sA7E%X1;Jw%C3(^<`oO=wueRTIHp6mFUsyDreC<< z%dQ90E!-WCPLA9UeG}w^n)G-zyO0V1V%7{8KfWH5X}q~J$Tz+ zFxQV`I)!^uxaZn1?Jz1r--ysUhcKt!6Xt|4ZPJ(!qDXq|GHi1-3nemyJN}&N zqr(EH<&ixQI8D#h%PCqCefkpNl#$*P#j`^RM+S-&peba<5G%w^3RGnXH0ih~c77N&M&TAikqEyj!s{!!K!s?_DcRN2 z6H!zqEq_7oxg~)PF;J)Upa`uCr)uehFz*butC*naAwk2r8-gql*UyBMLV`LVf=Z*g zP9i#l4g~smkg8(vV`)zbno7P%Mr^a}Qy*#qk%q}PaBeiM5^0F@OKDaq9cjcKY&sp6 zC_e&Kl#iio9K;6B8D@N>AHJl`;U-Qo!w{z#A&T3HglLF>NqSAX?JJ57s(3(^gzxLk*cAvMD= zjDQhrP|K+zRiZUuCl+2w8BVPZ5#c`kGuhOr$mik(1y66AwODX58fI+_Y; z;K82&3nb&)IClcf_=))A*dmRgW5lF4|G|B%a|-j6Y>tv6O?^%DFYAU0$Aq8msfZfR zX2=yxlWK@1K8oLj9YtOx>cOu--KaM#B*>4tAdIqc&?w5HHK><(9a;vH*j9+89zW-m z6RU?pmj4LxNa7aM2@?=O9g~#vVLQNsZ9}7pM^iQq#_+??7_ehUk{6C0kNPMdiXDnA zQnh|VP&jrC>Si7nbKN?yV^^^x>amBhogh*ZF)Ma1@d-2sEr2qRAhez~5l_d?1Ru5y zvam~`2FCI8(F|~4XQM7O4=tzuG3;j4f>xt`w4A(2;iF~5D$!c-5-UQ}K%^3Mlvo8i zf>xpRl&^t0sD%cQX8y@Ie;n*$%??8%Yc&bNVi_;U!Zs5hgHQ$UDEKMFlOPsE>hIeS z6iudDh+m1Oq9WB{*FY7RI4_R48EwKZ4wT74Lm><%$&2XZ-GlsO z{3IAAmWFoo2#7@|@N>{?NCYds3o1Crh$awoqnYRk8jd!S7llTGhgdoq0|ih74r2Le zGv$2P7VtwE{wOMv7ggYop>1e8NXP#pc8hpUm7W*oe}e1iRs&5{LqP@`98a%evBonidpMoYp zDr6Ebfg;EO>COMrg!Qpx4Qs16Fr)1t}bY0ylx7afFdFhCY%ioiF>d@OyGO*N3i{<6K&v}D9*8Ak3%H(BzX?XI?++ojrvg^ zYNt#XWt{k95P=;IUTl#(;#|sv5AzMs#Ja275Y&uD;ENQ7#uHN!YllV%C6-7m5^cht zG_%IATd-Rp3OgD)v6avP36zh9M#d-I#%r#U{zOaAG&BSFzj+Rl@KdoxD#gwuRxHY* z86tm-m!U2e3R;DVRE<_b1xRfhf=ZwkyM!|7oFh`Xj(lk8*bththD15IY`6;xgpBls=M*j`>qdC@8b7l<^0j)}J6n{unb0H_GaAi8^r2oTXR13{8Gh`^K|mwBc@EKz z4Bpb*XbIPjq`vHUu8;2n4|qXZ-g1OhBT>X7UUv=)_u?d47tI+_5Ch&MvW|7?4BIbrtt|n3fFBSX-TY6?ImoM(1pBi|E=W;KRoT6c4ETc)CVoyd(L5(d^1DlgbS%D@xX@azS z8`VUY(E=|uPjb(G@Ifb4Cv)Q|pvF$5b<%NB{M<&a7)w7iq0*}&v=p3A3ksn~w1h@S zK_yr3=IYVdJ!k}4MXUnKAqKyRR+-sa8&N+a=Ya}FQKU(1lO*2U*g@*(KuCeuVMdR; zC}-xEGMf|Wn0!d4V=|!`yrPp%&Cs@WVSK7dQ?r=sHQY$2c)!^#-1t~}Hk}<(q|hP8 zTr73b4^$?Sn=YCVBPF`(8F7j=j{8##+t z5;KrS`SB~TE5U~yK`aWY@yj7vH2nA+mn}}B_nUZuNk)6P2_2+hi`0dk#weviH?|fs zvC|;~dhw;1?Nn2iLhCiOJ{fIe^qQdsx``>!RN{${06oN#(0I@W?zl-$Rj-Pw^3w>5 z6wS0tiwy}XX5d??A_2byJDpezc09yEEJQ&WdD7|*syG%B&jc7^V$?DjlCZ1MfxvX_ zL*t0m5vzfENWf2oUh-nmWH4aspdUoiqY5TdHscz{_zp9{h{xoCD^8_peINZ3{tFlnJL*-}%OSlLXTHfRMOlgSIxJM;A6x*Fz* z^ocOTCqqxSB8F*`&A8`47UV)Ib0rO={ktf7Za-6^4|I&H^q>eG3h51uaYnuPt&118 zJ_ZrHk9Y=ynZn>@qRD7AgIEb7CE|;egjNM&Rt6!3!5KzPFaj1xp!4kvLJJ+8jBOJG zqM@U(6G5ar212AFfwPH;b-pr?Vrmqdj05b>5o+UAeH+{fhu;j%D~Q+!+@u9t!T~<<<|v~(kK%V7{UfL zjChoMExysHzYaqAKFwn|6|BPn#!sXg`ds>ck+!XCV2w!AOPF5=kJ7aw712crbV&sB zG@S0qpi3&)ILp~MGkBz%hM3FTUJOm?Kn+x@;uf+P>P(uH4jGU}b498^izArhl<%Z` z92yIeG&cg`n0<{jKb)qD6px<>IZUNY$c8NF4@|c-x~VoWZSn&{pUySZ)SW=R(R4wy z=n4=iBe3f=(*?QI(-jvOe#%Qz*K_aYY%U+eX|bFV0}b?CBV=-FKD{@{Ef$~yG$D^F z@}U3>_~|q!n_I67G^vp;tqRPr$iV0%(kziQ;*#HpOP(9cv`HE)Xe)dy1p+arBdPVuj1B zOBMIauZ~7^NnZ&h}6uD*KtRcOw@cQBfxbMXkk8Nfk>%n3S>hjBtZcrLp9as~M1 z*p+A%>LXT%x=;sXB~PFJ@IfA?c`WhKuO)!u%@O!i+GpBuvoEtQbM9 zpoc-QKnrmPP_ftVzGsDd)EQ@)RQC3YROK|g*MRA6h- z9uTP-f0**MsD@ZC*zn!ZN~{Tnh_$0*#Ol#*{2J7XKLO>~r6AHUc_JzBr4t9m3=8gJ zrfZ>wHWxxYbl`VFF?NC279j^}K!Qrhf+F(Ep#ochR-qcsD@5DSZm1+)2KmIA@e8o4 zvFp$hv;nO{v!N7TjazYJT64uDAc_+Ikb@I7cXegTv~Cow$~V)vk>XbnVUganOIwhG%oycLSE zv%pDQgD>56BlmcICZS0}ku)U_Tlz$VS3=UU`zaPW$nRckpC0!1A+(0=G>+=4&~gaH zER6Uzz2VzD)pE5=X6 zR$)(2M>KXRF&DNM!tndZ(?J<=2^ydSKZ~tjkBU@HtQ)%kb*fKaw-DP$9kpl$L{V2B zDpF_Qyj=VaCXuv!GyQX=5;KghX-7qJaQZkj@@$iiiXvYH7jW4^ZnFeBiMOF$Xc5|u zmZP;$relYvYz|c8w~*J4N>Br8e4oS!qpcuPE!qLiP(>Lnn#B2WP=?76N^B*xK!YfQ<`WmG6}t)QAemSj`O?u_x$pJibW1Z~ z>3QMa8|X(mp$_6>V24OzWyJj0qfm+MMJ03sorEyT zG*YifQP{QQ*@%~;<7hlhE5;V74h^MD6sJ1x{?A(ys8w`Fk>MGI}ME^9tHW>(P$=`4YB0sp;>4G@dPv-O$3qR z@KeZ7!cT^D>BHRX=N~{oygyLtQM)I;y9a?~v6Cc4&$F`zrs7NO4VaUWE zLi?ZxL@MH(CT7Y2el~VDs)v5a$L~eU&|J=~KuaK#HWr{c#Bx!QiqSlLgE-G7{-z?yLQjJ#Ys2}Q}22{kV&|2uk?tm_kKDdWIxhXh--$IK9=mSW^7O4cg z03;|BPyc6XCl=cq}fIU(*9`=f%A3 z7J*2;yrK3$bQn))Gzt}|h&NRYZ*w)gx+U<=R*i}jh22TK3*xckpo+X$R86cJjfNPI zZo7|54~E6?XYxp%Xwm$o9#z)!w7?D}?nOnaSMb1&=e3KcW*rRjCPyiezK1w=n;jL83p^ zcIFk|7`gP2jvi`46_COAf%G>~WpPa(FF$n7AjAebXaHLeG57|w4@ zKzi%}s_`1=pH%v#2>P*8&>pmw{wu-Gf@G+}FFdCni$EI~@(%K(??q8>FO6&@)E*lW zWMn1`fd+dR9Rw4!k>5$I2kiJtR1ICw4Jxn^??79i6`DB5OspAIKpQbFj1U_I3rJIs z(1ddhm?E`OOgbz=n}eGv+RlWGVBPcf!3o&RHQQOY$ygZu?DmbBq)GP7-C_iqiX8PLp5jzq+nM<4p=#N9I~)$ zKt;Y2zX`hqyA6u4b76%0XvNRRu7yUZ03AbKg^JXN-4Chw(ve?rzlVZrS=9Zsr2-vB z&Ctt&*P~U$bl5$hz%~%;!ZxAx_yg!5=s-<8tDmn_>@l!GCowH_Lj!$0LQI3*Njt6B zeJ~1kXr#VzvPw!^|(V4)TZi6hk%S5X+}bBesNH4kZHNKlTLuIyOLemT|dJ@p6KefCJkNm30gWsz6=B zC$AYh$;M@|>#*&_C!knVPt1wkKzt0XK}(4>q4gkA6)GKll1rC$@NB46(2HoBu&Gvw z))A}0R$*6T*9-8~A`fjv+o6WIG<}?^o(!pLV`Jl8M8!KuJ$3_jr?Aluv<_9GA{Fxv zQ3Ry}ygNa%nl3<-c;`rlBz%!lur0h(7~H2vHiq|zFe|@-LpLt~BGvFrOAY*5S;j+X zkf%fi+kY99Ln3={Z!BFDf4a^IRm1*77j+YAgz1NWB8b25)- zWG2tZa_Uy_^byHJU2e!DzmjW&v+wJ;hK3bpVHc=mD0&B&5!{nVgS_L^(#{gzMw+QF zi~5Fmcp5>Zo_c21^S`Da2i-KUi^VBYDNX7T6CRbIm65BX8j;et z9I7wH&PGMb4QLg&VB(Tykd8mi3ZvR#CTH-XLi)nO=WaJKDSUDgRI5XnSr z6za$q$%@@hUMpBcdE%|m2uA#2XvS_MUjrR5Ld*^hXu(&58C#nAEzS6Ah(ykDMYzvHn6UJZ|tPoFrEEur|sKbn!U>v&e4X7TCqf8GP zgG%50j=r9l@q56A-wXYaB=U)kU=N5m_7KDoH{lOKGIl<6Vq2gOw2()v z6}3VSv_LK~1Ly0p?Vy8pP(w3BlRrRy0oskP0UdrDnnG+C?Zc19?!s0^_-3Cc)ZzZizt9Su-}T>`aG2}Mv3g-{Lyl+i;!l;T%GFZQ5--8CQIAa+?a z56VDCUNu?(eb{xVo-$_IV?u{`0*GV`XnPIUXNRtVI?&;FfEHSy7kZ!{x}cIW8nhm* zXGd?tuEMUx?!&IeR-&EI4Jv4bCh}WB+W!*kxTKMPC*}Hhoh0u#e=hk zxC-?XZ$rIkHyTBL1cZSSKL%B!(P#tbRD%Y;7Oe*@b`Qjouj3s^p`abmi`@gw*nOx5 zny|Z2J!qi~ztP56VK-tApxvOv*79!D%sY|>?S&rbCr{DFlahEN+D%LieV~IT;w{9x zgpD>)cQYzdD_X)kR;rpg&Tl;3(7+S2l6R6SsD?rJ=_h9veGUy8<_nFWAb@97WKJRa>yf78=mQYE%+ps5Svw|o7IO+sf z;2u1*+YM?S)m=P}z1Y&~>&(4uEp86YuIF}g(OT5St$4r(Zt#N_8p*4J29Vwqr(bE} z4hO*qW*8E1r>BDe>Du zdR`RgFOu}zIDO`T5p0P)a~L&)6--bZ*hh2OYqG#X|7N0jAd(F~2YUpyLN@j!dqN}o zgM`bL%q#t6NuD^4zezqZR}-? z=>TLht|F!KyC8&B915Wp8lV~^h$g=ZjX_J%3MhaQsE1hMBE_NI z)LTrf4kGZQpo>@!bb$2gUuecUl`uaM=2$`;Er584fGC(`IDJseOiIL$0}p;a{wTv6 zgC7ec^kp>aC(jFZ^1|^$p@6cb5Qd!uA{F6Ff)7rLOP665f=KDih<;{D8rp+em?_EF zHdK$Ffo;bYNr#_}--l+RqoORAaG>49Qbk!-T#Cp;t;EM53t#%=Judx5$OJRY33be} zYN!GiGtvi>;36+PlTC!U4?7aO1$z>^3H6{6YF0OPDC*%HH?eqTuN!*;qB+NlR#L`G zUKD;9Wy8==2*>u5?o7NQXb9>RszB zf#<%ZhW7y8@5a$#Xu}>uO)v^hFv187fs*`AHWZP}_-brBY6B~DlCK7b@VUkS?{Eg_ zha@(g6liA?N=41Y63{_39?b+Jb~@TdnJhFB(jWtp!9@NL*r;2j;Qg3qlnqQ^1r4zw zbQCNw1|whuJE+Nbpu@ta4g=3M6&qm(o4OM1MB9ZA?bxG~QLsVw@m^P?X9#(p%MCmS zZM?(Tp^*0+vzvz%+QGYA5o+|D?jsd`BG1Ws-s!q|7b@c&Pm9*!XY$)xN-vu=?|RZ> zpD-@j1-vSW)Xu)^V{^?5ul>8@lk<9cCX7ez&uOz>g=S>Y%gY<(qeO)vgr8M&? z=H}oW7OF^EG4d2wK_}$1wGXm`_OgAAvDb){!osg$6DbdDBrYbbnzDs#`Tc<=)p416 z=p-hRKkx|dVxJ$PJ~PcUqcOBWq+zjPFMmc`T2t6S`?#DAn%Gp6@DrgCJ04Y_31~8i ze9KC{W?6L3-wMQKg5QkENJMUhEE*l$-y6z=y3AHk!vO&4g}bI`@qa{)1f`k z4g9y>VlYCqED1MDqKD<84J@B-bb^=*Mi^5KejZai2W`;z_+qP zJ!k>yLe0dpC>zgECP6YJKq4ca0C5lxiNth_elLhr%#bD#FF}hSw1bL#kuFX4B6J z43Ck%HiL)$tf!yrz(T)uiM1bi1#DtU6oxUh3}GVYj5535q2WYNzc*v@ezGtJq3x^h-GPcL&B#&-oI+CWxfh@$$j>DWcEmk7U%({VBLNKldY2 zI`zbA*(A|4h~yq3s4tqf>S<>$ZLHvllfd#VrjJD$r+-ta%Ymk$((!NUyOrP~`cXw2 zJD?Cd9|}N;@1))15ZcT=)BXr_lD0&lVGs_Hpzq_!On;ApMBkS{G1&2)%uA8d>Gw?9 zngdxdK|GCEKDJ2NXa;^BnhVkg-_gE!HQm(-bqr4ow;2V|pdn_b8%+$?C~8Ed)qirz zv5*pmr=KOLhd#O@hHlZJqwKB&bdQTmhjp+dLBsGF**)vnF&!+OaY*LDT@skCErF@p zAcm9M?4nESu|>+D8?(U0FqP8HF1mICoM2$+C1NEI$rR6|TslNx50Ynu3C=5~t2^mx zFLnvGpL0bDjbK~AR*PXE&jB9%NroejdUC)=%uUP-;gk=HVu=$EMSaAgiIs{vDHnmA zOI|p6Vc3!2Auf?Wj+UWO#H7Fdi$45)u#4-2#j-7MeI4|`2n<0yLtajKBla*v~I@j-kw)4P!=7DucLzn*vkb^}@ijbI?I0TWc> zPtZmU=XK-vLoZYj_Yg0kE|DZudgede)4EV@M|x41Zv@v74o~JXXd0JkLMtE@y9yno z>D6d2)w`L+wb+T|De=efE12CK*jlJ0uM{eYO_C>)Ld5Vxxke3k8|5Zhz2(>q(1Wjo z6zVLaTozi6Hj@{|Im!6d_?c)1q(c>c3;8u@623@f_#Uq50xw9%e-uj~xQn_)auO?G zHAPWp42Tqm)>4N8vRQFS_>oXVxlH`9R9@G}Yk-u%Ia$O-iWX(bZzL}syBSSHhuBda zT&o^G0Y4dHA)2yv#EPlgPMHW|h1jFmB88J510}>lQ7dt2=6~G7*TGTvBIR=JQix~S zx3LYBQnm^b@XLueVr$tB@~|thYoHu*gby_^Ouk4}*gEVA^6NnX60t53LnZuf>}u>@ zv=BAXrdY0}-P@jr(ipc9k%gA$5 zMkFm7l38s}v}Kj%)c&1GN@V&|adQoe7n-NaMy)4_z_O+9AR4tc~p z=78k_v43ht`8k2 z<_WYlnL1J+69##d6rf`~PAr@=iH@Mz#2nZL@)NL!iP^bsKDG(l3_kL6@SAx==_!{< zpNvu_kC+)h4Hans+eF-iCK5}9B**|O_4E@rqM`N7BkIZ`K16vV@iBB56)By#8Gi`B zlyV}4bB=>p1Uf-`s)%>+HY1@)JQ5YCjq)DyENDA<4a91|f$t<9Nx2~fYnM6((NW^n zUo~$@#}e>yQ;dos=BMI=jwT?o<&=7M2E7; zNHj=WOw1s1cx)Xl#l%WXM<)@J$PgW#M1sY{gvG=PEWk=gKysMhI=dF|$Md}J zTHmy$@2lR2pg8Ng_2L|@rN{I{-7eiwUnjTESJSlD{IR+dafP@F8M%~pDY{9wX^ni6 z-_dRlc|>3Sj5Yc0VW0gV*e|}_%)WoL6`J+uf-R(wK^j*swW{unhO#L)>;vyYe2y)b zI;EFLX_v$XLRq8nqF<*8wE4i_^N|=zC*Of~ocQy@oiCPCI_nGO_|Xq|AO3l|?Sr(# zpBk#pb-$0nYFdMV?ECZ7T-ok?<)lk|%oe|LDkrr^1@gX7s%f9EhF+9c_{j5yUGj!q zL@2pBza?$yOSZCQL?8W!`serF>{{-9ruMxhRAo6; z6~laI`0Grew4pdP1X=wxqW^a2q-Pm+-+LvN8s>eCRrzwMa(~shbdM|UZyBrT^r~E` zF&+q|+H0l7JuiDLt+?lY_jzN>8YzD9ZH;<;@Qcoy(KiWw6UQpn5PkRyo^j+{_tfd0 zshGC`YWWd*B0ow`=`&=Mnoy9a-JW3-vF)8k%-5x9A z+xZ55f^X)VFvfS#ak}PlhiI#~CUghw7kBcDv_ag4VSW^i@-^ZPT1)E?%7VHn%%fgz zjt*h~GicX7lvdh?E;Pgcq}=oT>6@qGuGtduzPf6Vb8jz(<_;PD5?A~Kp74qjxe9F` z`D+}D3$#kEq|(QqxSW5M+v9g}%dgWm`4(*Op(JUm_<|l{2XWkMpQQ;L;R5 zhDvdcR?~Fuj1$jHZ0p{^wyCpTx`*^tZeF}Vx=6kFnXJo^N!l|PZ&3+<5&9=m+0 zx&+-9Z)28!am=9e9`I|(%O^t{9P?$4xh;OWCB!T8DSCiVc4$g&8H?D#s@x%x7;x@w zxph92HM)x}q_L{*h%V6#Hc)WAJJh>&^uZTHcfN-1{Pj<4L&$zB*dM-G(7L)We7MTF z(na`a6hAwz(Ti5}YhSPZ(6sB*1`Nt~pe3mKR#ftj z-s$bMU7LE^7Oq7nY59bAIBir{i#6x#4s8%h6^(xI%bx$Ayc^YS458fZzt=_W@5l8K zokf-Nt%RIwF6q@J{+fT)rcB)x6LOo zAYZ3`i@$Nr5`M=049d5mOx#baXbmb+fgZV6=h<=G6Rnr)mJ1~o=JGfGrm_6oo6ce` z8$Pko=6Uk;5Es7lw&*@OC^L_OPG*53+#u|Cw+=t>*dN01g34ceA=f_3b zM|-fuFJKwnj-98?{&E@0qu&JQeiJ;W&4PH&G66ufgnxi0FF zH_0RafGgbM9ye&yK9pYfc`07CU)Xdgo9rZe`VZu{0e9k+uI z+pp&MChPaby4kd5PRz3g>tNTKXrxWp=l5`cK7AB@`)`?lzx%eAe@xkDaB2>nVa0ex z{vjunas8Y0SK4l0m7xrI{sH&Vjk(oMB zVies`wzV|1RKrb23-5uc7-Os84G6iJi7f%S~aWtXfJxuAE*es-`{rW z&%Mp~qw<}nuJQC0XvB!#7{H7CFnyx6@|9@7qqub5uFaPt#@EpY`Fi?HU(w7rp$hln z0!p+EWypCWgz~DlA910_?@(Ir%^6l1PQ_PvRv#D7<5IjtSMeYp%8lF$zYuc#GA(hQ zHF_q#MgiwIL7BR8-1E1H@tuy3e&<*9%gne5d1avUIK!;?l8(}Z!Jnch;x&Gfzu@QS z7*6>SnpAhrM<0IZl)w6BxHw_XOptOD18pa7ta4AE%>ucAg#aE1eLRIWGF%-*wO5 zeHRrM(3s-}_(AkzI-CdN7!hxpnsH2ux1DR9U&5?-0z=yLVHh*wHk(o??X=uV2xV*9 z3kGSF7IWR|ThUo;UnYNIA)lk=)OgI=?9j|#$mP+-pVCOal|SZ(_%nJHUc?x;p^RZf zev}U4#mjeymM*=&w@2}Xwy*S*USdG~8I9;LCJ@v9(xx)PpVJGxq~32HC;Vy1**vf4 zp=Ex~@6!X!+Jt(&DC3s=NO+0z!?eN+@x>PKis6*=dr6MaXYu*t`~GS;x1__1@4`~Y zVAe~sxT&_-23oOZ`A3#}izS$_6t2z38gt11pU5Z6zjOWlxps}&9$Ng@1GDBprR$Fx ztE{ouMp>~>W}Uw+oZI=zE#)ywxQtd>K94oFEwt?WNHv!?aN~Nnm^63q=%u+l!H=WP zeS~u0y4B{~KAkr=qH#a+Tys)?R=94f^Udj}D}69me7=+|FpW)Quz_V;Vkn*NuV6b& z*aAEFF5HW6u`IWQRjeS6cJ+&N4bk_$u3rk1x@^EsxuyFC=?F6Xl>7ugj4>qSl32$E z#?)u&D2>#o_#I4$hs5I;<~KtdK277;#&kI5``>W+cL|$v^rK+E`=&?lPUz)!Jzi1V zJez1Us?m#D^sDcnU9^r)&`AuTJ0Lek+h_}xopW3~MMr60s6#L6)o;0nRywV|k`Brb zpaToxe&mMvPIU28w2DruYotBmkxt`~mqn|WFpH(zLzd?U)Rqz8v+n{##3P+It;cHOiS(f9wM z+xS!$TN^t2^Z!Wrt8Z(Hy?ti2HaPV;O*i|q5iJ!rA|XzRSLhx+#U{T=?@+L^GvZw= z;#TegTl^(0agI71@Nv0AdW9q8#Jec`C4>E|hA%2`}2z z(!4hH^ijO7%>zx#g_5OZ>aOWAc2FfQN27ju()JZQj!PELpQYQV4}JF0H}%=Ox?uk- z*xz_t)nVfZo12ZTfG2E+%}u@<^L&h!pw)&~PTO#$-KM&Bz7pN2M~gPK!P8-MA)#F# z?Zvg@LTS;a3r*-mC`;Ov@i*FZ&8su)ZACR9B57B11h&JL` zU8{Ii-F=(;l^evXe2x4AeL;`hJ#C=`GIr4Vu6quEd9UMP7W2 zX6G12H+s>AMl7g1)viFdkVU8bS;%7!_v#<9#;3502k|C7z#~FAr+to%e)GT8&p$cJ zhSC~R-w&yGPg+EO67283Z8WQwibpmSH-#Zh?>*tHPk}w3b9a0e``AK3?usrUiBK-+ zBX)48ek~|Yv5vglF^wb5-y+RtFz-5-^c>gn%k(A?+R*}*wVB4b+@l${A$NjJOvop2 z&9BiVEb>$ILHiXx&foJnegSvqxt%PI}!RQof2Mtz=6(mlFD zQ}hAH+B_lp_@CUmr zeoUK5)bjUobNnbmS@pGE=3LQtKKi8ZX62uK)eqBqdV`uJ&xuZ7{=3?5qe1)>+R2si z3vx>+$d!r*bA5=pjKRuUhPWgqq<9UiH8tMlYGQq$#?M8XvBcroO3Lq zPCP+d=_Vaf7pMKST<$KMlU~zi+9N-${zW`RUum~o2Oju7x-8#LcW8@a+7ZK=ujh>1 zIzq|PrtsqW(r@d#AHSJXU$^AHk)jvh7L8~Rq7VK@{qU(}spilvzaGMOEx~>(*nj!%*6+1@ zztx)4Mw`aylUzN$7PrxoH8Y+*%a_qR8cI9=n)1hOTB*&W_Dy^TYH%g4qa}FYOG6vS zwu&ooD_160#h2qrTuE`uAv}TlC*)-dGVFH zd;XkWU|H^%o?(f9RhQ=kFjC?f!7xhE{BgJ86n$a9R8f zzTl70^H}i*=~e7JS&=l94(IPg^SRaFcX}gjLeGV9^oQ$EO8uAcrI%p^hS}{oFqE}R zB0{bIASRS~zk9p=PJQqjwy*drYTB=;6(9bq7_YT^`^DDhD|Wxx&gRSZ0ek#CJ)n1Sxt=_hpal}k+0P_Fqz)Ix*?N_H?iN)zjZru5lr)YJ@(XW5k;a~rWQIliOomRM= zO1Cqk<2H5J1}fZAD9vuA1ru&z5*My_j#~rOa&Gg`i9@cjZIB*K)?I@%=`S4{u6gU4 zDd$?&CX{K{zmuDxp}e}^6?I(}O*iKBdMLB%hYf0ZldeJxXL`AWR-hCo;!})yhH>nB zj!-H+OI5LJt7#49iW8#8H7a#?6)J*y#xh!twEJxJoI|>J5Ce#C1^k&}X8Bl8l+CW&Twck@~d0n)mFz?ysPK z<~;v=v5(q}R~IThb0=*_2SOP!!zMg?jc1>10fIH~RWCxof@d*;r+e4F+RTiC|9=bAu@AEqzn!3JOM zycs$ox8|>11N2$lAT3olMmN>>(|y+(q7gK% z7v>4#+OE=h>m$#P@pypKI~S@8yDF^nU*3A*iC z32jFBGkPGuL>H04a!_^M)$i6&($Tkr{pGjgsxodPi$#8y zu49s)#sPnf6U6c0v0qVV*)=)kp4=(YSi_WKCNLK?Y)RVe$ZsHpD)FQ3X^W5X%k&U4 z+UMyQP2j~fR%op@3-a~!Nv@e5iI>p8N3L<`c}n<4^-1|fG>R*c~uOtoEI> zpY~xC(-@JPqHT22R(bDwvwSNWFsyDKy{L4~Ub!K>X!nF?MBo2cVLJ8OjiMg~``LHL zPBmutox-^{PeQzgN4})fCHM(-kw7jz7^hOLK_JWw6K3V+$)dKu&%JStP}AB#;y@(HuMM!{2D!_ zH?DC&r^UN;2YIB#`?OuRrTIO6mrm1lnxb=blRi7gI$gpd>b$A;)uqGROTR7f6|@wQ zx(n@>wJXpvxjR};A805qH2Q`AD-6#-7@jYEVynZ^9|rr?ca{9Avrl+0ZaGss?RDl6 zx-8$wx9|;^Tge^_oBZQ^<~ATHlTo8|lInRt+&M3O%Wv3vpxsFz=(-E?1FC*7r+avl6w zsKW^6#8Y$}?U)j;&_yKCBp#)+bkjLz_?}@il<$%2M~a`8pW%Dxq)}XwJHe`W8F7TN zBR5=pujlws4r%ng|J!)|;oG5NU4QO`EF}+KVy6&nh?sV z{5*e1M`^1z)$~lfi!Qza&6q+)ZjnynfbXYQw83#5xa9K~;zLN=?#m)Q??GO)PI@F^RJMs}dr~7E*_h>Ec#vI1;}?r`L!>8KI-DJAerci~DKx`+po(%~-HM2=-6k4)US&(($5SbeUC`9HY~i;^Tgq zbntOL!4J{)5F^QVhj!Rg*Gt#2h5>bx*z{SwM#s@9pVMxYPK%dl2K^Yvz2AQnqO z#+m#y?4~qM-fKayNheIAi*bpaail*r%Mzr0c6Lh|KTvy14Pkx%wHj-b#B1SPI z--jiBj?M%{AJW<{$W5RJvvLW#ff3B(#yt)-0 zAH%*}C?mxwKcL;LW8#=~jy0OaJikIiNzirii)+pEOZ+vz!9V%wk`|`|;u-8CAK7oTkTinC*9L4e}YBv0hZN2h}YS{ z^>h3J9iz*kk7&;F-=Wi(#H#uy$8GZkIziWw#2yxc*Cvz+eHMM||J9%W^P6%0)w9Q! zEW=Abk5HHNGgPjYFXLNiJz{)s+P52RKqYRpE2m9pL6vsRw1Ku^)p?s~lGcWHdQG=zFzx2~4w4wzasK$c28||CF?r32_g`K4j;C&(6D@|$?b`qxc5;7^Z(i2G|n^qGI>k|R}qq*q|l5Atlx zjNxmMDRcLJl*ar>-lF9+L$~B}v{YP%Z9e)=IMqSHZ@7CuU>e|tXZgk*E-6eL_w~24~Tja!Nv`g-gZ>4D(ee`3O{?vu4IsG4fFN8n;rpnKX zjV67K6jtKy)GaK~C2@`Vb(+DdT&;M4U&B0-XqIclD!-`BGSYmt++4^Zj(Tx|Zeay= z;w5bt!u|Z{(|^w!e?HjH`~~)lZ<<(z-S6-xTON#rwF(k@H)@TBemmspX% zriI|$*P;4V8p>Kxmx~(rQI*CP_K@)P6x%br{49U(qimjTi(mMCdPA4wa(t4m&|NGe zlrqOJ%V)&5+8)rpNzcG1_!9LybPXvav5JEFS3KhZrP|%mO?3;-_r$N$RnIp?v-0bn zW1WVwB9{;+5yysn^v%CyJpSB6^a33_34gOf&CtmJ+$(+GGu5g2lH~tyDL(QC@h`8miQO!TltTq?4 zfGW8yaXF14FL#PlAE_9;}gK|S?<%iLa zZgB_t_#Wh(Hzw1z3iNps z&(e0eHZ)^eJRm=UA#}=hpcRpLPW=>SFf8s0`LF$DYQ;OW ziZ;ks(mQX<8XEV;EbtTFq_;F74&{blPuW}Oq`EEl9v2t98IyDk-QJ2lNIGUkoIqB) z_p>!3%GGud-oOT-t}c%ErCshG=5!{hT`Rk~qXs zeesu$oja76{UG|4&wA#szU%S)$zuB>ZP()Fi#4<^mv`K?J#5Q-94_(KG%uz?t@&fC z4JAMGUVEKmL;GXL->ZMXaliht=0ZtZV~5sNif*F9`A>?+Hkg+?=3_mb(pQ_|x{giJ zP^P_$cVfnjR(Z!(q9VL&%j_TCw;L`uJyl zpx7Td&$ELp;-0_5dm`59ubjB?{3WyuNzZdDF4KRdNQlqf>lw<$C-fAdT+n0Be1ubk zazgXi4(ofy7~2QVXjXhmpRB`1{qRh4`XrPwYhWDFcmAsJN<5oV)4J)2KH?q^xCn`%)v*jC~bNbJ{IpX)rylUtHcKBnO zrKh@fkJjk^9Id7YbQg!(gi=!FHK%J|3_%57VMxv#S3@sprCcd0#bq>aNi==X%;)V%L;?Fr{{P>tyO zU(gr7`ew!wn8Z|A3SJ2lbPltaMktGEpEu~U9ZlKV`{{x>l)XDY26x;eow0sGnWgu( z5BYrfqk&oS-&-PWaxIvUdlJ|1?I`ed zv;(cE#iQJac3pfm#`#yd2RtK`TjxDN0Rz^~Ieo+vPVs;{+~6KNdUi;=Z8|~wa3w!Z z&uBz1=`*g8)vnpK`{mR87Iw|b=*xfI^XL05s(ypif+lpC@Xd5k^Da81zMHlqmhy*7 z+KD#wse3iZt^6}BQQyH2AmcJGa(#R+O4UVQ`Wr6!OYinvK9mmE>Ot9nuBW|dLAiL} z0_^5%`BRIjov-IBu&u6!RwK(FU{{+%S|^vGrL+Wsxd2i8dQ9q69BU&9UCc3Iu1z3SHI?}FTc+_3nBj?*zL%C90X zHzGc8?sdlv*}L}dOfNcsxZElh>}v@+LpSK4x+Gn}oZOM)8|`x~DB1TMw9#klfc>qN zZ{p|dd(HfT^EZSX+7Q!z!{_Mh-uoRQ#iy}}dB?oSXMConu!RSEXPRy!lzxA_x%VBi zWe+XTEX`mWef}~tbfI7Dn@x7C7pwRcWtLF6DKp{O7hL1u$un!0*DjQ1ZDXbHeXPN< zwdzY~4=tn7m;Y1a@Uw3xE$xzKZBg!=6$qu@bPuJ`@(88MwJK48C)1>0Dn8Q}9GOa= zv@vzsjdvURjp?beSu;kH?r{od;*9>@L<(ti=)ZOx>eEvFc#=o)8K&%zqqdbw_f+k= z_pW(btSfcDRq|u%2i)tCWqMp(x@X#)V?Smby*%nL?OeT{y~*=jsJp}!t`U9spXrN( z2F)6AR%Vw$rx!yg1uu*?-PwXxbji0D>pF^BsZ0C9#)@*j3iB>GiyD58&Y*&izVa(B zSIF5E=k@*^7O{W>xqXy*x;?s!CHZo3DC3^C)>9AJLDfg*;k3>4=^g zMl)Zh-6$V@@V8w4&$ZhFYISM{tqFswbE9vCs@$tF?J$OU>o#uuE{t0!%ht)3F$-nM zoLfXFJLd7B`FEo)+jUSVW3E*1iY2q=uKBSU^A`33Ki9Drh`#opyVOs2X#SvoAJJ3n z%X_|;k3J4fDwlQJ3Kp@1T3tAxn;U5;gZzSg^!cx9zEz>C61ps}>rSx7H@T6zVi#V@ zough{g){yXho}|Tpb{72Wye#9H2P7vOrbgSrV$uJ3m?%DOkfKYMB zk5RZZG8bs$&uA!}{1x9tuW36yrRV78C-h|pZAJ8Rf7|6ZyNuYg5v!+NMz9w>7{ma& zkRGj;(U#A(I16N4AxrBrAF_}=vC5FT1HQ3wYmmP+fgAG z%DH?MUyc}}Z~Psn8R-t20S3{F9(3W%97U#rS>>&E| zhoRZ1bSSHuw0R5k*sWS={!X{^(FdW~Pag^UgvYd-_M=6!&d}uBp~=_ZEL$*THn|o0 z=p_(Jm-?roAM_#^z=M~-sf{p{V+(7?i{Oa%`Wr^K59{o+9FD!TLg~4(p;};h@v5aT zRQLYa8x!a@U}4VqJHSEAH;P4gX#qCb>F)R^t1Xl@$HkGrl*!v*-d~0J{+a*6y^pk- z!;{i;#a*V)Tr4>Cthw3C-|?>|P|1kcthhF8BZhAX5r%_)C!Ff1?hHjJaUHs=pA&Q- z^wOV%>OY_H)*SNI9YiQO4}a$YI&Br#;fB8aYnq+Ux$wP<_PJOnO{QeEY1cq+TzuO= zpXiUlaAv0}I7Pwp-s9ObZ+Ol~KW)-=wAfCPw9#|lxXgyNzlmG^E?o9YUvt?%eABKY zrgcOcUDO%NSSohPf_v)M86D~#+*`kU8?v$@gmPg{H@m+}dg~tNP0XzOoGVV$J-snz zy0x1(L+*Rnec!w9W@FXk@w@Tj-n-~)*d=Kw6P_dE-qV=kC$Yn~d!{UHEpC-5K9mvl zqZq@81Usb;xy?ZS;mV(i+sG1y^!)G?apwIAM8?W7KEcqxc@9;yXGP>f|5z z=vV%}%m41%BeV9&I?mGvdQ5k)k3HnDXjU&_0lVS@9Ae#iUzSVKX|w&*tl#7(_yc~5 z&LEVO{3L%Oe~58DPxo<*BXn3TT^P1v&hET6ae`jCQ`$qj5vdQQ(hj_Bli9**@e`(8 zt^%QqSastV#Td@)#KU&wP#*2fJ$B$>pV}?EX6mz--lY#QwE8RZgVnlg^&FXT6J}1r zjG8ixpB$^M#YzsPWWl@Gs+_L#lLSw3ef#NusBb4G9rk3x%^S{Hk9+13tK8azTX}Md zr?7z`l*k6qhXD*>5dDZbee`iS-NK%`S#^bOS6iU7=;a5n!gtah9B6llWw|9RVh;0I z!@jzH?V@k|Bd7hD)8eb=tf(akKR@?u)lS^5SFX2Ju#xQ{q^rKw; zFdf3PHj}hUZk)#GAU$=SQvNlZ<6FPsHr}1PeDra!GdmXefW;n4+LdzRG~#>`8`u(W z(sc}Kn-ypHZJMALPInnj`L%C`vtI@Ko53b#jmoo8S*58ks5F!{x-OokGf4BHtnkZN zK))-!IChR-#4Eo<=MjDIUpf6Rz1b)p*KA){HDT&$lCGHr4Sd(Er{Lpqo#JY&@bg&2 z5~k5Ezp7m=Z3=DpHo8FP)YtHFzJn&{tlR<;SQ0N|jh{jE(SPmUHhWyUV87_2%hCh% zNjyk1U zo)ybHp6GCcfowop;ef-nN(R;MRgZ$AVn+ z;eX@#|IM2@KC7-EKhIy$Yh2(SHwa}(-DS}~&^wIS+XgU%aeLe#?ZXH^OfT-<_v3_k z3X>ScSWxw$)Z1XP_QN&%;SQ}4*P$8>2qh<9%inpPDVxzOCh_d+b(+p#4lm*o`{XM< zw|9=&J1^-7y`ZBs`jvm;xqV&uxC^Dvm+go>wdT_KY;vKr`jhaLFV#|;*@#W8jFw}V z4`rjy(!-IR=>&NkBQBRj0)^t3&e%R`Y#j@99&?yNwOl=#aBh3KKr=tBZWfJv1L{zV zJ)6XpHaWV5Axk@B>2CAUCmV|QAis-!o64}<9t~yPa^KQ6NfU@;SG)eD)_& z*4Mgq@=1Gs6J3_-hFm}0q#JVGe9m#9+VuOfj*?e5L(3iCW+o-do1Pv&B!c!huDXUwl@T$+Dl z=2@e;6F0x+&5^ucGkeCq-?)z%_fZ^_*y4@f8TR$xlWU|s?~D1+?!DQD*5dnfz~2Y@ zF={Rh(qUAZ8xh7z0Tz?FcjWo*p$y;gzqxGH^%lF4~QH8Bob&> zw@mNkpU^69L4og}ZMf$<>6&(nSi&k+5X!UqBXi*Z`Qn^7rbnLj7>79dq~86QH_^BM zdvoG*Z}yCHdG`IB*f3{O$e^s4+gBgskLad+DW9e#^iVD`SN6@BG`6vetbX00p=4BGp=UYF=pHo|A<|?=B(4FYu<-i86%pnzr5GTDM$U zIyJf}tDCCnHocGwWlEn+<5>T!n$zX_VpTs>&^2+B=Q(o!$Hixuvi+61_hqwV&3}wC z>yI%tMt;J`FS)l{BfUs(XwJRwBKqDxbHBg)X2<>RqR%~tvd=vuGr?@Gd_fX64 z&=$H+o9O{QsEBZdH84U*iH-I75v|P@wzT+|ecNqVN23m;KzExXH0=q9kdvc3b>* zm@r}D@S!AVwKzpLkwJraohGrNeFpV%RoIZLrQ37|p`>XXb@B;q(`XAjsyLLCIHx}P z^mpA?XVx06SDmtUb9^Wb;yrO1P5gc_pP`LTvrD6o!r?R9?6zhHp14)hgPaWzjeIE0 zw58~`E&Dy~x6m$^bKDLeN{Jtk(N{ip%1_nVDJl_tErf|?Hsi=@x)U}IT7gouVAIBt zlW*Y5kmalB9xbOe*yZbK6Iw0MHbkHQU!DH5Z@MzRsZfn3G$52y3wYhR+r_nx%Zuyy zGulCu>S}2X+R%(vgi=X65!dEI`xd?zjo6S&pq{Tn54POjrFPNR{x|pZd+*Nq1+St- zo5wun_!T_b43|P4&wQLdg`74CeiirPH9C(6zJPYGtYz`6b}>Dj8UByb+@UW+@Oq&XnYahxJKWifo z<=XFpD}*v5cj(obv{4?@6XbD(gxsLl>8bC>6NEA#9(?w%1sFn~zt8ld!gXpdee3$R ztfS@rJ~JBrt3R3&htlJ(pEKe)8}gKw$D|E;k}lhf_v>u3*u$!L1$Q>+P!8peaEwrz zZL)cr?IjxcCYk)F~} zcI*mSv{>GUvz{CWXcf0%pN~Ecr~COg=hp2dPQ$vlelO@X4*4tEVQnAtM>rFg7XLB2 z!z$_wD==tSg>>J{KR`PlO4iD_HT!Rn=68_6Hd5$z+!kFklcOJe&;9)P%_{$5miJ}e zpQEcdb3193Zb+Jim1bNO&dj76v+c-iIOT`Tp!!Sqjd?R6l$cM7P9JMCX2X21nEq%f`e?uQ}k1_EC3j7egqce08vzWrQ z+!Y=$A|AvjLg_S{dc%zRlQk|l#ahE2&X_w+&^afK)J z$X(NF?apZhZNRm8c`t6{JGFV`tM~za2$$kIaVUf08*w*%rnh)Njrs!ZlfR%5U2(7d zbQopo+tFG)&w=%E?z&~;?gLe*L#_H4eYIXLi|eH_7* zmyx@m_2M&HLwDsKtgSPPr{I!N2`$am3hL^v0pA&*e5=>={uuKv(@ zV(zb(zm>bgrQ8+0rq$MBo{p)n4cpTPKk%IY;7x2^zuPN%J?AKfa3X%Tcl7fS?!}$- zg5Jvy@@0-|#I@WR2IPiu$~VaO@da%Q;%@$q-eQdJUG!|UR=XRye5liQT<(hRp;hXt zQI0xP;#Hd$Txt{j(f{fGKl`@EvmD#Q&T)uQds#0gFo-c+$RDALAHXCcjH3sk^xE5o z`Mh>R^o*XOkMBn}MsOlGO{XyAm_dXxkx`E$`{RTCv!BoL*O=n-^Z-Nr8NI{|zfXth zIh~`^7{IZ37grb)pVC2kNN4E@-NQJ4K}Tuy=|9pZzx{TSe{>I_tS9|$-|?M@@`A55 z`f9%};Wzmmq){O*4LR-C#Yq|yZ}C}_@fn&zojwm`Lz_^B_npUANe)}M@-?$fZ|H!! zKHTy{bXPv2J?KV1dXbeMr0d=nwcZsq*x*lm!KCOW>f}OM$@mip9=uELP{5M-mfqt< zyGOb#_gp;Y-1}z3S4{NmubSu&|C&T6e5EvA+Go*#CUpBU38mdvO7y|M)u-nR#n;oT zSIlygUtJ0R$k+A$@waSiG23h@>UB-QG7DwK6uB`p^M>QaaHMosrEUym)T54|-t9fP z)lIi{;TCt@(oxJ%e&tVG_EUA=|FzrPjcHDPA&C!SsU=X|F&H;Zz@|GM!7hmm}qHq4l zeSi0DhiB=;m1nFpMl;523ezYPmlwyaf|jlrW6xJcr#)i{ef69%`a*9#>!N4ArZ-qI zhPS5dGHuIhYufJXg9B6*!hbd4Ug(`Rllo)|8U4|qFP8Pilj*-gS3Gy4@m;1@`lq9~ zR7Um1xMy0`rc9q*tGhudUye2TP;TYc99yFw6Lb}EbUM$NKHAeq-TWv&f>65jNhq-? z{~chl4`w`bD0iN1Im}g*#C?@{zEE~N&$%7u#dttwRka z^h)(X*l$AhSKmCDsn_3P z572(x^Sv~bQuU#m^hNz6vg$Hu zF!ts0mFlZ#L0ybiiyKhNx6mf+Y5$7VL|6QSY{9)VIntV^eNkJcl&DjRihOb8cmiMql}h;qs$q zM^g=$3K`b%zOCg$)^R^9C)D(w_&w0_R)E$$k1 zd;^x{Yv~GYrcG!>C`)qDm;M8%oamkRaf@!$*kJl-JzcWZ*3m^ei#g1rTCNHUe2=!Z zd?lhEgwuWX?V1f~3lFyFdraAw*2SBc;Nx_ZZqQYvQP3_$lL#e4OKn^U`f3wfv%PPk z?AC^YQp6BS34PHfu6`ZQ{6=W&_;PhgK9mHlD_C?%&qwn%#UmUel!6c1*?k|JbcP=J zG|1X08@&p*X(+E=D_5sBPn%_n56f1JKHHpZf}!--R60$dxbCfV?UZY#igia;)FHam zPnd|&m;SQ;`r(^x&zRPx)uIn&QeC$;J?KTkxgPaTrg)xS*Ql*`-_F%$C7)X^Q;zA= zw$@AuCFz(a$5gq82G2U@dA1zi=h$>{Bg{KKZrQDxb+x9>x?@^Qj|O8I%Cs>$)K?Gs zW81N7+D)338`@>XOE%Iv_t93o@52Tgv-=4pVJA6r{vrRb7sH~lqsLfJNj;@_`<6;J~?qHDbG3Nxt^Wl{qM)htrk3al~#F$Mn4Ma#uBMv7pj&Tq0g!x@qiaZa<8=BAl8P%zV=rg z_VqV$13PGzIc_6sT;xuKS8H4iWBwy zG$WtH9%jXp7(rTmVbW~UNIZj3R>Yy~&|PGlC;F4mx%YR6!G8Yp>}TKJnU7=U<{&08 ziZ+khi6Q=2eFGm#w|E43xp6ufVs$;Zm+KM_^L?}j?Pw8Ssf%a_x-pI$xheHSd_;Tc z7`o7hK^$pwh9-U#12`8yqLB}!l@2?;A06R5=)^Rd)lFDK1AHhCj_VKYtL>$HDDB1X z*Us>f^T98E(kIi7dDW#m)?rU^t&WAYh&k`sRl2TjmTu8ux+yFL2w@s=BPWOk9o={u&QhRJTt7qF6+CzMXPou+mTEtmChbxq8-!0!I-$R?|ntThtPD|AH z@}acScJ!fA{$Bkx`W(}UZGH>Q>X-h1_TD?XvFiN$m8=Q%7h32^7)!ET)#WDlW7(Ev zTar~=WZ9A}Tb6t8?IptyAPg`B14Esm1enkXEn$H1FoZJnP7(s4*+~cxAk-k;&z@1< zKkmAB-Lmfc$6f39Xnpd1o@eiK&OW=HBh4^D^=Lopg_ww`Bdi@?#qrt1)?`jc-D3RA zWZX&}Y3sH0|3fK$`~~nqAMYA%PWp`ZjVf^9ThKzV;CrBxI+bVxbmLc}U1&b)hdii- z5{}75t*EdXd^b2jf)Xf#O3I5-7X-it5zbdkz6`$z^`a6QC0~kP0CwmnHj@|Df!_<| zmc`@du#?>d93=A^4yQ2FSOdF|-*i=RA#Q6O<*dWkXwur6+fZ z*~LX+|5+8t{u_D2s63D)Plp20c&>B~SzfAS^k(?+ z4i0<|c=5Z?DERT~Id6sVp%qFY0zt}zwV`>$AvB1VgAc4=he~LstOc6zd!ZZJK$w&B zyTA+5o*U>xcYdM^inRCyelMn$l*U?j!$+@z?fZs!Y3UtIO%4hKhz(ko2=I{q0jj|{@ z3JVZ}eh`*Ny>5I9YMkX~1ysxVj38~hSuBaejO21DTaIwAtvoW(5txD%Nb9D3kWZaF z7@>}^Y05O@=g=`2B|m|V!z?U`9L&HXSU6VLJpLecO~ecM2Gk6lz4SNd6IR9;49_uN z_#)Fvz8(C~0?XvW=pf}iXa@*uLZc9Z5z0m(g0Bj)6wv|VA@JY_zz2)`a@mb`ffw39 zn1*A@X~O_tzQ#BvNZ!nsvRp91jQGWqvKU06A9`Vq{1Ob}4?`Yx3qaMu7c$~P{CpU} zU!k5bHD$B-7V^TB#KM9he&7HlKNKj3n6IG5@8j5X{C3K8Xd2`|HuO-YK~?ml9#umo zv{F|q^3aSwJB-h{vWQ!Vh1vLWIY)j5reGT8p@M#>UgEbN%FCe&D#6Cz)Tl;lD62pX z#5Mdajyk@e3X?c4mmfFsARp|MEkWJ{a~eifY@NyPWA(`|A#J=|2SC%xTHtL{X%%mv zY@M*en`IX|#sj~c2WeNC_>)Ag4Z?y>#)G{{Bi1&ggRp$&w}v&6PM=KDjws)Lb$nOt z=X>7(^g#?Hv94)ru> z8kj&woQ@jMY{#V%p`NO_`=dShYA*nmqCd?Nu559k#4-3Cd3R}Di3nN1QL@+huYC9 z-b$*W2HzokG?%hk5koe90o37FfekFg^=KBVg?uoBw0aMh`=fl($p!+I)Dc$0d22z~ zgn0X*Y#yR8Ozh@eC4w((5bcIh@*U_LjNwnCGZ2Dl;$gIo<6`Itbb+u1bOMH;9mc6U ziB?m03V#;A0e>7FAs$5?#Qo?HaVOdbQ_u^-T$B&s*Q3(czu_LAm)lr0!UlLDFmmtn zEW$KD?M0_x90n;HMJG9LAKFhmg7%@4=oqLtW)Yo+1?Zt{0?i=bj}CwuKT19mjiFiS zEcq~PT1IC;Np1-h*1>y=uwmi|_0uWqMhA&|Q8Syw3ciNCuz+~adF4Lt>k_$vvM%am z^P*tI&r5D77E}+V5ah+71BB_R7sk&fpAQ9~11%JRFe91+CWuhC1kHkCC`6p;pQZQJwH17m7g(Wt5eI z9=`bD)s=x#*NQKmIf- z%!+RyUj#MuS3eK&0npNxsW~=G{Bd*?%^)|8KaSrER*soO`#{(PWh3}m)Eh$wVFHF> z2qr0?<+?ePkMj_o5D#J=JUEn?&P7|ORfQ}hZz3B>n*dl z@KBtFDVTv?9+34q&cy?6oCnDS3>32N*+%;zoo!WEKG$}Mb5Y;TL$QHl#(4nMay?H8;fi3bW>h(Qf8@4+t|b@B3(DALo`f_AsXwGiZ*J zOEmJFcB3xgb6H`NG;xYcFQEEX-i^^2m?gI?%3vA{lueMcpp)n{tdKVoFQM}=3r1oS zEaJ~lNBZdDgUimrt>tq|dED9rT~dr+jbDV?(GhY}B9C84t_B?<&PT1pm1r4MKoLkV zNV%{)%1enSiA&Hz7{<4uqv$x4;}^gfzE$`fQ-w;akJ3K-61{6lj?Ne(H30@<6KEj^ zvS66J5jBGzMu~Ok0>>|c^o2NGcOEG}17&4XFNY#11{VWZfeLF*KG$b=V3AmjdZ^b7xwLPVTr0k?944X}Mwx`d^6@9}^{5tv<)K}) zafEy>{unwAI{XRLf*QaGCRpbD5%Dm2av%5ikfMwYybgrrGP$eq?GRB@}*$IuYpS8Q+BW} z8=kQFR(^8AUqH*y3RuElgmU~!ut62am!fsa#XdL32FOOZ0820pGcXT}LPa^uz#Q=u z%&-X-voU6gZ$S8&$!|V|Y%G~&=ws##{L*VBH9Iaw?o7Hr7m?KswgedbQpYiNX zZhk$)dBio0PYvT^r>`AQ3oDGnGL+C>W#G^_n`pN(Mj34vHb-BU(68C_XIF@IL|>^# zc)^0qW#+_=C%K;=RdaidY@%Meqn_??h>hf4QS|5!>hO!Wm11yk8`k7)+3@X91GUh~ z?Ny^yPzQdNwTas^Ks(FJh?a1RMbOJ_2`k30XA0MGJM~b?t(dt5Rg7su(@Sak!FmjN z8cm)|4!e^fE@n7uXtyvw?QQ}O_mIsnX~B!{BPYz-%5KKyU4Sm2`DiKRK^Z75oDUUN zh?YPRZVVsP_>mGX`lwb0)$EEJoTK^SwuCImyuJUE^;<}WA~wR zHV{`5FHlcdPK4`;9T*k1j9*57Yl)ShfwXddR1n)HeOy6VI=L0ZU&78{z_0R}G>hzOu!5=_7p`Bb8ILS4mO{fR_;DsLQ zG@xO$gL3KL&oYnCk>@i1RD<*(gqe@|#675vI1fJq?IxaM3ojrRrX^>=*P|iIA}|PQ z;yw{`jdc7@{4_KZvOx(3$bl$jS*V%w^x{j~o~J#J9X`bxP>#|U=pxsgK*wMN(#Q{? z<*W}4emzpyLjXJ;y!qUl=uoZbYXAAhD0b0Qc18iA7bPz3|UMU2KN4Z9foRxS4wV`DY zq^t>w@LgyX>P8!(8ov@2M4LIL5WkcbRsjVf7F3oB!rm{3&l`J@YJRu)zM&NI!&G zn;j4W2kq*n9T9NTuN}0b9fDw?El$R0jxnmEf0}s*(DOdff>zQt8>G`d4K&d{Bkgq2 zXAR&0C)7h7m?<*}XmcZNH_+}W+Gimy1TVQF)CwiwA$CDNz8P}COj$I(*M#k}y*Pff5wpP3oIX8at~ zi)N#_U<4EBz(Zb(wxE7k<~R$n%FR!)r~$g@?`ihjZZrau_&sPHW6+6u=zlLXGbef& z4AGs$n4?u8R8XitX~&%KziqW*5`LA^~?hc$I3Zd&;qm>%|i>p&zP4p)>h_A zF8GMc#2mmkf(4q$m69vOkJ6St=!F;zLJtf3g#xfb8hf*ie)Z6o!a}SeCwh}u zc67o{KjRlu-a=f4cA#z03C$1!8+B?Rh%ceS=2<@@96yInqf?-a9V%0yGsFv&O`-ahBGsXDA%F$wS!ZOL166??s za@itAOOkc9#1;4%sPxJ|Xm8BU_T+#99?uypp;~+mnnjg#w1(Kg7G;8JmX{H&LWLPe zm}bNVbPm;_S}=hb{A_9UY-xIYY5&Ju?kc&TR}>F;!3SB(3>Dj51FLBh1UzFvYM6%VS9D z=-zx(qD#u@CTZgn+NdZLZ+Kq_w|jxByScK*&ET_<1e2R-EiDnIWkadK*P(XQ#}y=6 z7Gd)UfgN9%kIkivxD&$QC+E_KePYVM|w&7cx%4{Rz~@2-HF)IG_q9$qTbkX9|A|>d4nX9ywvv z_;$!89;H0Z#~;8jf?gJ=3SS9xVxbZ*qO&j!3*aL+j|%hPYp5Gwv4&W{T`zq*73NPq0}E-ok!EGFh%H>o!#N#H(=5(q*fiMFU*fWL~aCp_~W7;Ou!^{ z#zA`FYc6YV;iaVs!mKkt+JkmM2uucEHc&I#iFSjq2--|t3;7OwBP#9shSNPEcXP7_ z)@B|wi1i7YTwa<{Gr3&w;OkKnIPvSih~J1>P%l~!!ZJ8E9fb9=cKe~3wOr3S??l@n zMy`(71wF(a5P?<@)`Ye|H}p|Ah=!mI!Z1Lt3k^UNzk%~epMJ~zJRo;785+R}4d8(Z z)^`IFWeRN~cHuXIut{=Gd=E5J=1%7Q_$^>yB4pKymnbF>y37PC#Mi+*eg?TEbOFrd z7ST*{Ir!PILY#-@f(1;F4;t!dQ9T$zy6fMx-%v5gdk3V|G51gjYM=@-$d#k%Xf;|1 z(nsR311SqEeJ9&MJ(Rfl-b*aZMce@M#B)$gSsQC$7QYp3fhD#8H+2H|%lPf+3K~Sa zS?;4O{RkR^DD;AhW!{61P^JuWZDKbR1$dyap3ERj&(aoF$2+?NTIv}}71I!=RcuR4 zo02q!2!9gBp_F(EZAz}uY*tSOXdx3?IY$ukSY27fZTLB;l{gmy#2%)Euvu1)u<1;; zK4@{Xt)eq91x>`QFipK?bPkpFCg{`pJXT47Rnq}&P)OXz>d8g>(K581d;uClJD~)> zm$ERvuwvpEv9#;Vds)2WVlq>d&!Q=ZQYZu~ltBeF(<50dpkn+2Xd-TbB76x-gnlYc z_p&0&0+`~QLofl8&`ZwE-4EgqLo3%CMaN(Sd`$2mzL9&AJ+#OIP%(l_=sd(YzKJ?> z_$#msUShRG58|uPX;g_Wpnl2%EEHoc56WuZyigNpAscjHWrC+sX292=dbEg~V~~d) zH1m)QfCrkOj+`I$LM!;75n3Rd*{^P*Y?OQFp|iqFRuV6xGqlG;K8<*ZxDnq6Dq=PF z*ujiWLp6}Y(_oC*+s7=P<~%b{!t5=ES$qdOe=Qi3GuVLE@nEV42jq=#|2#3;nQem% z@c^_jP64nnMpaM=*^Ff?xjFj2i9Vl4r=gF2oH}+;^pX>t&FWLo$k$qG{}Hv zx> z&Lz%LOwsw{FbRVU!Yn!<1_Pag8JK{6a>C{r6k!YK9F#IpOK2n8jtA-)tX#I8MRIlc z7JLhXmMaF1$GbT>kfx+IFo?MfU>|QCExcJY^RC?lE4+`7uvKL*v+#&JdBYv%UAu(1 zqn-hFA8JoovbXCwcZmED6QG|#ZDoYKw5KguFTw)sf@&s%k;%}(WC%hS?BsOhLip`q zz}JHbgw;?!#5t8kECeRXApS6<6OW>5Gz}J*KqJH%_`+JKyF{)TT}BsSfbsybhB_<6 zDpcBk9%FHjNeZ# zfZqmX#3c|RSB&Z)if=`Qbx=oGNF2jL=thI&iYU(kJrscS?_Y>1+M0YisN6J<$*yMs zrnoQ4aYU{BnE=oKQeqK;8hA#8uz|8(7In@0`yiE|M4GH;^l*zOY=hj<^i1 zK^xI})P+_;1Jn}dp>C*yY|i09E65Ae5xeoL!Gxa$#gylwHq;Il{CeS2rwA>CDv-Y3 zM!Pc16z73Nssi%ytI=8z=0w}XR&vV);x-QJWPuBFv)~8tBhZ8&fJyvC7y=J*E}Os@ zehKHu!}pS#C0>FlFp!%;m2~?Y+6$v#qz#3XwNc-KHlsb{$H9+3i2BfZv=6$Vg?I(E zQeRj%{xnR$FoYolF<5|B>Mx^F=!ZsPGshMrkI#;=a`3y^kwV~PcXEIU+K4OJr5Zt4 zfH(}oY~&;`P_KhrF{%SSv=TRJZ{tex{z<5!TYffC4vAbD@HP6IkZUlfs#khh@1oaBSdfp##` zClc-LVmGcp%b*dW#Chzu9~2#nBAePQ|d z_#M>CM`LIvng>1j z1?UpTjZ-g3Tu9u9hCquyh)z?Mh2MoQY?jze93k$8FpQE*BWHnjVjXJYesWPIbdsB* z&H!rYIW%#Gi5IxGv~ekYa6lfWKZI#1*MOf#n=QZ(Av|V{#2Jvyxhlw+@s&`C@1tH0 zeiPaOLC_JmqiWPaoisEH^iW1T&vlzAFCfl^E*|6AXgcIUGjS#=EI_>~j%h^~Ij#*g zQD%V_{CsqoHVRYW*HBm5b2;~Pv!WWmi~EW|XY&5SoV$^qxZG$VuMQn(6>&8<@vX^k zG_CkHa(=XoTnKf62l9zK(OSv_XgidUlb{@$h#SF4c@c3jG!Pe{ZgP2ODFn$?pmpS0 z@FP%3ED=|N3w-44Xd4<$-a|Lq0}{W_4e(kc@v74ZHmCzHb!*WAa0z&IDMp=83BqjR zPa(;dpyl8tUj=3O4zvOCzzr2p4OS=x57;3eil78)pp;`9IA=M26@E3?L0BbP1cj6d z>!tlM=o9zx(UpwXS1C1=mr>rxE1MsRd2MS(hq=c*d|_VVRwyFQPv#0xH@POT;``7- z)P>e_J`XC)iMAyD{xBOVEK;vzgpCY}p%luX5Uh|71JoOWBK!ha;+SO+Hb_3eYo(Xh z$slU#Ids2G#C~XoHuCM@#&6)2(}%Va*W)|Iw`Jl1`k@~Jyo$ELDEU@Y#Vctguci{% zK)cL(Ky%P)vr(_ctpaAm44{f*oivIs`(0%BZ z)O>BsAcnj|2O;(thx7aM|w_EvEfR1$>%J=YA zCvlDn=)>=ZO8h7qgIKY?xCqi}~x4 zGw3|bg0NzKM=1h5zpIp^k$O&zcB4jeou~oTK^J})N+~Y`>9$+BRKa}qp%%|&@`eeW zTzUbWhb79w#35M3kDyEByHM$Carj_N{BFTy8iR4@Bkq9_{3t4{7wt~^`N^+LF(zLw zeuzoegI~*6s3_V84txt`-S}M)fnJclzKu&>boe+ERL4Y}N401d=P;nt#CkD-nUs_G zGcWLy=s12cle3D+=U`7>X6PK$S5el@&}rBp`svR)`q`Qs z4ti|FAnap9;WaoVH#$jj$AYM&;m`+L;L+`kb4tmr~M9yl5e8z?X-20wyMQH zK23WnpofK0ibm0Hknnraa#UC^izY%`P20zKZUoswHSC23_PHK0{b=JN2wS25mtYZQ zX`hq!HNYIcup0V3OxuFAu@yr2ZD>0hK<$)wB-^f`-+O7duvXeGtap^>7k&)wgBJXL zw39LE;NBYP(^>9s3g#h9ZW;}tbEuQ@2AIM3pf!w7Ele>!(~w5L*oif0HChG2Z1hDX z#OQ}AbdWx=(;ow93~KQE(0&ls%%;);jchD##=D%&r2%z8JDbY{{WuP#EZ^aM}Tfzpi36P&3@TSePsoYP`b93Tbp3(Q0CBl>Iz$; z-XzU;arsHgOiWc_E`~ad;~G&F>PCfiGo+o+k-TmQ?IMmqJ?+V)9Xg0H+!<&V7$FA? zpoMJELtk=AL>TgR+TD$|p+mH_2Y(O^5)Y%&)%SDHhx-`m2s1#sO@!et+-2^d6Lm1a z3k-Zc>VyVZBu-}n)Zy1N*nJGT18snQd|`I{MtZ6at%YhBpsWU!Rv+LpFU!L`WjbJp zNfAOjVFZ5|8kq>KOb`zmK!r`yqf-!KGE6e?YI;|g3hfx>959I=X5cfK1o_K6AsOK* zMqr)=W~O&c5aRATKv)yEp25Aixfd6>X`d4s!37@fL70P49;IDlFb=}Pv}1<$NKC{m zuGh(RrLDi^-ga)9=9+FsE=rGg(~pguyNmmqAup_vvi{^q^-w-Y-*~uQ9oO-3&u!du z5Gt7LVeV^|xrrJ!q7f(+fQiChml8=mI~pv1TS$jMCq3?W=1C(hJM=LgN~4k;g7Hpr%xWbhc5EH&Z*(yu=7!x(Whby^|HcuX^v4fOeBa!j3KHRDe~J${%mXoqZG zvOCZabTaOhjLV!Ddvq4HF$XFkP0U3$q!6@&n|KOz%tbpJ&=M?z^ywpF<<0qM9z!Ud z`6%Hz@)*OF%dq6ZP;z<gESHd>{7~WJ;zH3sa&wY<%tH)cAh1mnj)Q`?&WOw1a8b zkKfNd3yV@7gFa}bynwz5Q70cAN%qkw8YEXpu21w8@kFw}#*%dwXs56Yrq}>=rYN6; zLHrRIf?=2zIi|9fdf5=Azk5ZWAcBWO4Dk!xY<2^+xAq-+pvBiAaXB!pm^ zG3r1&Aq?#h1Yy~XXM}MS)`j*$D`Oi)ThJ+voq$Q`Cf7`Eocmc~jQg3!ZpK~MBJlz= zCgWblJqoRieK)$oSVmAE^S}!+{A$Ks!xW7&4{S{59<+!299wJ+WsQ_&v%Tq=!nMo~ zVM@NoNw@r-Ir5Nv(Z_o+qJaVC!w?KG2L{F55DLTi-Hdw#dZC2tl|deCQN9Mjz;z9~1P+7>vR=xoLC|okAyJ2!90CQFj;}ARb2z#KLmv!(RHZ z038s03H{IqQ5b{~7=mHYGQTX;%|UyJN1=l`)Cm#jf&s=Oh=!pJ28r9zS;i=U4ikq^ zY1h;A+1n|)K3-zL!(1C>4i1ACUr8<B}_kpl}w3Xa2+JcUuz0BPqNMjzUAck*eP7k9s=pZ@()%g8r721ai zYhbRszzM?Y&1j>j{l8Z@ch4_+IED7S_dU!8CD{wKKsw zDqtN=qH5-NA$}UF0SlPHPOcc0K7EdUK3_h>Ixw(j3LC9W_ES-3uDZIS>kTSbdE9BC&!?Rz7{q`e@;LraR?^yrL8Z} zrUz0+=rav{QA_`M=!a(RFBAOG1QG7pzrGe>*IVS+Zu+Nz=ZBel z8)7YYv2WP8k5TGP!Zi0)MLdo_1{1K%{Vjoodr*$?It0R0&3uo970Twh?`hV{0{6BI zQ}|2hBA7XDiu;~`aS&EaUrgecp!4)YFYSxL0{$p-K8ioi95vEE1~7waj>__OcY3^6e z{pHf;KH3mr41AnNPhAVIBfZQgC;gYnv$>YzMmc7Mdo1HV`l&C>LL0l2<2gw?{2V_< zy$F3>P2bkQ9M_qluV*2RKGbl{G*IIUo2GBdIp+Z99D+eurf-&D5qda(9rIv{^JjAJ z4*X`W(*y?EI?H`^GauBvx{lQzI%jwC8R6jicBlnmD~z2kdEHFW7SO^Hd0~sFo>PwUb7M1RLjmw578R#lHZ-&#&gRpAiIs6J#)y2fbSE7}~ z%lJ#M0K#UIYGC8mgD@ki12xA;H@?ngx+fTuX%IGv&L;gS=C821WITqZ&GCB+I!W0m zIs;S8?-6tu)RZe>g|VHX&NSF)nzZ8$F10vLI7PJ*rdB01vlL2EVHIc2y{zcQxW0?Ta~#*@=KhW3Ms zrVpS~Fb%>+lG=wZa*UdPLR$&*_~~db`8oUr^~saa^46NP-;>Be7G&%?MlxK6SwE9O*Ys+Ebbg_uq zp%XN0nB8a?R;U(4)#P;43*kpViysi>w73J6-Vvv2X~R`fwFMQ{ie^)_Z-)1AjYkqKF#g=`R(mQ*K;I|JVYIZ#V1 z%#_@3EaZ$}CN`rQ(1QW$sH;PzFT|w=r^R;?His3lk3{KJHj708@iMAmacamf5T~On zg)CU$_)@eC z3ZNLwAj~j~4|!}8PIeU&Y9h{uTyT-gL6xw=&eKS&!`DMLsKCrI8E8@RoN9bG^|H`> z$}&-5X{a&jYtTOS77LmOT1ba}a)S^BJ)4BE3H&iI5RalG5Q82VfJx|uArLmpezOD< zFb!=SH;)Qav9Sy%>rIkd1~s`kbQ~5z*aE5~zasL~pFzi93g$WAf@ll=5PRMf^#)-Q z#$X%K%h6h>eO^4Os!P+<+p9n6V#kawdl@IWIB!60O?i)FEkWuitj7p-Q8bBJAz zxRkg~?0Pr;gE^$ou*pgH3imsCkY`Z=-CDpfEYjp95SC7zsam?5jc$ZZu$awA%jRQc zGbmwGD1~AuV7cUjg%zE{(kjHyMunxZ+&Y=M9Zco006&YVD=b8;(r815_}Re9eRKX|5LU#w zg=HqsZK8WKsiza0H+`YuxGds9aU6YD%4S+YyCf(TeMl^#B zr%!3$DcN+Hjqa(0YN&z^ZbSOFDE=Q-dhOtu&?4~CgVWq$785UBv>w{&O&>iu43)H0 zSd)ZLYf5NAgu9)tWkK*qqou@pTA+h0?oP+$^-v-fD(70}Twx}opL30Xbna&~<1xi3 zv!s+eEdyaT&OJtMfEkp<-55BZk@J+&Mjve~LrWlwb9QpRSyb3K#|W#S9pz94Mvl#) zE!mKZZviuyAe(b{(|$YM5~5pb&~nZ@M<2|BQOqP%%lUI48;0o{VM~mOUsHT^j*?jqg&^%0sqzZp zLKRd)EjXY7oX`j!@Iw={LIB#K1Eke&IL-O;3>AwJazG1NkPX80)H8q)gqcwb3Y}@8&z#A6ozH<~{4bU%%{@C)S@>-*d}T z>(8vO-SX`EU)KM2%e(9EuD9-fZ~eXX;O_U=KV0wF{l&U$XBf6mQJLZ5y_YmAHSSX=8i5XQO9h zSDb&bS(YZ#$kJt6nNDVsnPrVKkE~S|kcDJnKAo~|S&yt&7UR>$r(ZTC87ae%U+O~U!!%>KCd1O8qkRtJHs|exIsTs+4I;jnberDr=Pv<(0~-lVUdU-K&nN`_%*LN%fTaEcI6P`RZ-zOVq3C%hZ>vcc`yW|5|;k`YH9( z>I3R$)bg|xK8myot)#8g+O*Z$8m(PhtMzET+D>hkHlpp;Mzy`#e(ivEP&=d@(T-}D zw9DG-bl2;CrMrpG&AMB4x9M)z-Jx64?bAJ`+pl|CcR=@y?pfW7x|ejX>)y~ktA9@a zivCr7wV}pfFdB`;#u8(xvCJ4Yb{hMP{l)>~pmE4JY<$c3XX6p3BTZ(r#eALldh>1O z+s(W4ew`Q3OXP*}!}&w`!}*DPS;3nHe<=96@SDPZ>wxvoC2yB}Sh`;NaQP$UrV4XK zUPXRIXGK>cC+mk+c&mvZAVreRkg4BvFb0X|5g2E^;gy3 zR)5Fm-_^&~99MHf&5vp_YqDzAYd30-aUAPdcC0v#uREbGQrBI#XUoHU9^v!omIGU! z;q&a47q`5$<&7xX9@bJi=Dyn0FMs&ch> zwPbbM>IJKpu3ol!=jvU2?&fpP>bYk$sJGed794w zKF{pvyrS!hzg+R|72jQPa7*HU&XoO3b`~q)=dyET=gGFoE|hJTU3_p|Tq?UvcDZba z>*RX5L2i_bbtTqRg}hGgl6&R8gDa_7-Xagm+vOedh`d`KllRH{ zEU$x6|(){H6Ul-!iOl!BDvl+u*4l=75{ z6e*=L#gPkVvFJ|#a6}Hik~aaQJkkZU$ISbf#M>?cEzQNs}9^|7)t|55roUW&v;NomJM_QN->-i_|B(J^{ilY18a^|8Zur9RFTQ_@@!mI`dQ+3vQzWqYlvp{A=w zZO^hV*)Oo$9Sh9VEsnDsXFGoGxXQ89alhjM$85vShFuNUHC*3tL&J}pCpu4Zp6oou zd8+d?=N(SI)W`ktmUwHtBOZzm#z*4g@yYm9d^$cK-x~kL?(=tV+kL_A3wK|%d;9K- zcmHztCA(L5U%LCe-Ocf)cw4+Z9*lR!!|_Nw8t;zx#QWm?@qzegd@Mc@pNr4N7vhWY z<@i$k%=pjZTjFQM&yN2*eop+{_<8YP#Ltgk5Z@NRD1Kr5viK$O)%d0H%j3U{?}%R! zzcPMR{Ob5M@oVEdc{-fQTop5Q_rV?he%XVv*JN+V-j=;9TbKQv&&RTV%D#|&Df^nw zcYMB=$>b^W6XYk#PnZAX;QY18tL1jNL*Brw9gq*npOrt)=S4m*^Ldre>wMni^G7~! z$-kC=D{oBkrgWx6QhuNEB%fze-bndF%67%|e15ICOR9 zWh%SMp{iFoRUVa36;?%5-Ksv-uxd=Ts=7?ILv^L>bZ)I6(9}jr~ifi0{vzB9r~N}x9E54Z`I$fzf*sY{$Blk`UmyD z)9=wgr9Ytm#PDxJ!m!D>$#|;qC&tajRAV-Kez~#2xN5x8xYM}H_?7WHW5T$}lx^B< z&Nds(W_J7=%@P^OhGZFI!%*yk@D%t<9atoyxr?Z)e^Q z^N-CxE&s>)r&v$34qHd9&skrz{@MDDb)smh$XV$?%twrizw|kkl#V+X`*B z+HSYqWxL1rC)=NGuU5TYRbS(*>8y#=sO)L>OnbI{(Y|coX1~y0G}-=6mE8Q-e-XueJVHv3yc+{~vsUK{uEY2_2+GZdF4 z!il#NA0`qBnRL&UydWNS^2RB=m&v4kB1$;}?Hl zwyVTZHoUupw@JLY@#W}Xwg>MW;ax93^b$J6OXz$5AHRf(ZhZ9r;#E|1^LhUVFQg~& zve_7~;x+TkIPc5X(A14h&Nu%3;5mP4d-Jx3?zs2;M^?XI{r+FS|McNI_CB}&g^N4x z3a>3c^VYui_MP|k13Nz0_wwG)*Wcgw(%v2aod4O2`~GmnnY)Ic34Zt63#zYOJka;j z?R%>pzxMej_ddP%z}_eJUj6+)e)j&}KWzQvlHFHK?egCJ{NB1}R-bub-~Ibmzu58Z zefuuC&;H0Sp1A7$-|oBQ)yL2K_2caiRXq0G-aqX1zxn#!N6vd`+Y>t+SMT2U$GuCB z{(9f5d*9w`+q$u~>;CRX-d+3K+T80~e)+(Tw%2aF@4{`jKmPQ-?RVUL_r>?VclWaw zJ#^0>9=mV#s{_}c{oRw-J-zZ|@2l5e`S5Q(d+M&Izj*THeXs0WTYKuPYrg;8THBsI zYZtxx=-S6ypF8`G$2%^1Y+v)WZTD^YYvbqJzuVY*)7p!d&Rp5?=fCY=xcJSBU%sUO znqTg8+-@;^@%MWJ_doEj&cFX|`+>E`*YxCEYd-xYG{d#XjT#8r5ZSm&ws^aTURL5)LRa^Vt`0yor z{GU(#_4ykfeDIN5ANlm<+PEWL7x%wbA8&}i_0pdEopD#(9Y6PzOFs#H>iPE2D*Dfg z+j6~FJNNFCNxu}{>G$pY&nmlr=L7%KH*GvfjXekJiWT?FLGQQZJ{8`k-|ZADZu<@5 zTn~}mCA@o&{=fgV@Bi#e-v7I=ccu-~|NJu7#Aa|Yk7!~4{h0pm$MpXnAJZ4CU$A~5 zpNsfx=SLCo)5rh*(Jg+`5RY&1qlS2diwCB7jGOuV=TR6WZ=)Kptq7Pov7=8E}@kQ|2Yy8o-u4#^b zbj|;RuY=NG?qKu2^DyIoCFI5w<1qW>qrCpIVK31d7xRg>Bn?@4&$56Jv{y=vxb zS$pC~siydesTOwGTplz>B#unv#q;CAL`R|^UKl^oc#_c?FNz;$JlS?JzN&RW+PmO07^HR;J zio{`wqY}lbH_H^p1DfYGztP;Ic}{a!`VZ2d(EMI=oo1KjVa*=R4dx#x%ToE*{u2CW z06YrC15i8+!+a6!iXWZ$Vd8b!SF*chr>lOFI3w}XM6W8Q>QtSf@~XO2k%M0nqw(H& zi7HE#t@@QJRkd05sOlxlins;qF0$;m+$9Tm zf}W74!_(#I_N+Jkb?UjLpJ}#e&eCkvoUQq}<{Ztrnu|0SYA(=h)10sQh2}g>i6&R0 z)ud^DqFL3*G%1=(HUFhKPIIE>RL!tvL^Gxt)ii2CngLCh=3UKunh!MZYsNJbnn}%Z ziQ^L|Bz}}QF>zAjO@*XlSofwBr+3OiR?s9LYvSf^a(@4m@p;G2}>e3k(bC%6eJ20 z)nCniK;|(q9$Qa)FvE>xmB867ED}!jteOd*e{OedO7GM#KX#dNCaG}Gy(ADez+`l;y*(`LRW zD@`hs+LUI}n9@xdrc6_o>CKduJ{k*M67H zBY9$;Vb6$X$aA^pOV456!@Wm%zw^eu3Gc~1tFP8)_f`8szOB9kzNdZ9`aWvS3giT` z1G<1eczkowQwuJ>H;yWVvD*;VbS@|@@Sh37WUH=b`jUwe-7?(**R{=j#b?-bup zeQ&$!d=6iiuhTc`8}U8l`^5LY?{nWrzK?x>^=1G0 zeE;x$=lf&xADT}N=mVy}RA4616g(?f(!SBL-tl2aN=Ol!3@wG^;Zwt>gdYzd74b#< z5pTp3`Bn78s6M8RWyf-2x>)z%vxCPE9XC`sBn?#zl?~lFv32si$v;hfICbju=IPAo ztZC!4Y1%w(nLdAddFGCpM`u2s`Qz-nv!Blv%|9|fwQykJ4A*9t*X48dyRLBE=(@@E zD_6pGr291YQSOu6KXf1GKHhz-`!m;?vr?+GD_amkf=zGT;{jljB z-yOqU0oNW^Rri1HdhRCfA#RsD$DQjAx*vI7dOmr6d+K@HdOLbmUY$3?tMpCu&-J5z zS5D{n;MC=*^FR=s0kT06I27cAOb`HRARQbBjs{19Q$PqD3r+`7PyoW0(hPaEl`P=|^30KG$@OgYbKgiGJ zNBI2&69tn569nT0Q9(>lAP5Rx3G0a>qHIw>^i7l^?kJXu5wTfp6<-&h7GD#e5q}WB z5`P!J6gNQ{Bbi77i6d^rgybM35hs>KFB`H z#aJo^Vl<472{0BW!e(L9F&In3*qBUtPC1zn5k-WD@Dn*i7EwZ^6E-4BXow(z6LBJs za1s=uBQgjB;Ui2$h$tYEgqJXB92%#_qCs>L9jrU7JE)86`x*NhM;J#My{31jN9F_8 z{nmX}lkJy->59Aa-DU2iyTo1W-so0)^SrsLElDj; zU6r~zRSlMbAy5yxKmsfQb3q?Sff~>V`auO~2jgG{7y)CT4TR_nI+L!To9QOHg}#UW zhdzcek}-lYngK8dForWGG4?WcF&Jr3T3Q-CO`c{>v!q$muBKg1yOyShj8Gi1K!uPS zvO{Jl6Uu{pkOPWBTF3+ip<)Pua3~jYLSg79i(;GE>1+jC!j`k8YzMm?cNTXBcP4i# z7vk>a?&4nN?%=NFUf>?(p68z7p5k8Op5(6MZsK0#9^s1lQa;L0@Qe9Leks3*U&3!A zm?@Yhm@e2RSRmLgSRq&?*dW*>XeDYRY9VSaYAb3ivWSXB2~nx2P!tz^74;DJ6!#Xp z#U8Os>=54(-xvQ8e-Zx^H-wwP1L0wC3%C#59PSMFgnPq%;kIxKq&YGH8IMdvT*wLJ zG;$c(ha5z9AQzEa$SUL#av3>=97mQTdyw78dE^Fi3^{{rL2e=&kn6}*&a`#tH~S4tH>M5o6GCSYs%|mbukjl#R@SkR*LB{GnS2&VF^r) zX)qU-gJob*%!n0Z`IrMs$8=a%rCf)ftR~(Ow~4F7eWFkk*5qjdnj%d_W_3 z=q_v*pBSGI9}}M%pBe;#KfM2U*jHK}V;AAnoHb>KemK6n8<2i^e>fm^}r;63mp zcnw?&o(B(u2f>@*S@15n4P?{v=rQ_ydMaZIV>V+RV=iM3V+P|G;{@Xn;{c<68avIN zR-AS#Z8fwXS`M9sPC(nCrO+nm7<3TY1FeJ(K!>5@&^l-pv;o=$t$>z6`=Ea;FFTh# zpS_5^kbRcDmYvULa_L-kCO-sC>zR^|QTD)@`|OZkiW z3;9bbSzf9D6wDLM5!?`56nqo57j+kP6gfrnMN36LMYY8J#WJy9oFxv3bH&->pg2d| z1a1#^f-8k=xEDMR*1$N7z|-L=Faay!bXW>cLT)21(Awy4@s#9dyQ?y z)?r_;7uY-OFm?gkjNQbZVB4{C*j?-swjR5IJ;d%{7qN6DrSvJcC@(6nDLWD;h`Qup zvJW|l>`vAr2az4fmgE?6966pGPPQe#5TnSR4F6>ojXL z+cj%7i#32wr&H?;x)-|px(B*#`jh%y`i=TC`u+M%`ZmV?M$kCdm};D3TxDErTw+{k zTx7JEe5P!Z-*nt`)O5&nq>_UEFnu@GHrF-(HT^c#G~YH?voy2Rv(&dtx6ZQ8w9c^Z zu8uwJyDvbt;@+dtbMo3oO6R(Do$)^^r(rZ{UjN4mnUeXbODBX@mwWA||PRreG3 zP4^-9VfShG1NSZWS@&J{WA`2RXHOUJvr4{MoqFWG<$dZ+p`LiFQMIXy-fP|u-m27X z@8wEleb;-*d#@5x*Pv)VtIzJU`R4hReoxNjoLYfuf&T*K!TCW$NFUl9Iukw}ejj-n zc^G*ac@lXOc@=pac^)|#JsUj`Jrtc2n;kn7^A^(LbK-O3^WsQCkvNrjllYXVnp~c| zmAsdX7Znw8Qa7d6qt&N%rM&}t(7MyUgS}}jXf`SXnbI=#lm(Ul|&(KfPkJ3-kSquRKV(=M4MxQiST18q} z+P%sPm`2R1%n{7r&=cq*RD<~wYQ}s4y@4J;wV7|Bm(WwFC$lE=57dzPA3KG8kbRkb zihYP(o70fX=5n|^Zew06UOQe#URz#M-fM0rURPdkUUyzSUTvO|&k?NWZ{ly|Z|1M% zZ{hFYZ|A27=mMsICU_(GBlsnFDR?e;FZf!?!aob%3j2%tidKo%h?a>4iSxuUaa7EO zQCJ4kU?xn$3Rn$i!WD2a9D)nrAe;rq;Tgy$q!#)QNkzw_15qYA8J&)T=qz+JN<+t? zebByWFLWL{7oAxNrHf<-WJhF^<+J3Ve2SbQpDUjxpCtb-Z-zC;T2_8)j>Ko;)A2NX z6h0Y;@ZR_)yd^#tr{m-B&lnA#h>yjm;C=9EcvHL;J_!#fbClbZU5TDVFQNz0jd)L_ zlZB+8%qHceg*1~~GM^;K98yK{NCT-LgJgiTl3ApTEFe#6u4^7^ZfK5c&S^&Jth(R2 zAG$xf@49a~pZ<-$w&AV*zW$~DZsqG)XcQQEMy_$M@rd!5aiejQagTAgafk7sal0|s zwBB^mbjEbn)Z5(A+{xU_{K5=adRj(W+FOQNMp(LA`dd0#I$8!>m{yt&} zvaLMpW9uX9GwVI;Q|k-sb!(>0Z@XcuVQ*~DaddXJbk=p&advWcaW-={ayECiakg{T zceZx6b&ht4T?MWqt^=+b?pE&R?$+*>?s4u3?ho#2p7-wRo;U8#?i!x&?oaMoo;!zd#* zFE%%JJ$5H{Eq1#S<4}c29F0rj{J1bKjdS9n_^$ZFwh+FTlsHj5^snP{mrCe27Q(9ATD){v&Aku(9lkp7;Y&QLQhGHx)gGp;Zir8P`z zoi-tDV%qq$LutR|)0yc^Iddvg#FQ|nFlRFdF>N|_^>1DFD4KPJi?!kolp zGi$NyvTL*Nv8!|HaB6Vwvmdj6va4~1alWyCusd-P?r`2D-YlM+m(H8W8_Pp@Jl=HP zY@UXHjDLiGn17JJkAIY3TTn|-QveGD0->O$u!gXKu&uC#u#2## za`+Uy8GZ`yfsequ;4ScNcsG0`l^MHz8bz6+8MhTWk$IXF=~tv z<7ML&;}+vd;~8VvblG&#bjvitJl;IkJls6eJld?ZOtGX|WLDftT7OydY=yQ?_Fne3 z_I~yr_SW_e_5t=hN5WC)nC_h7)H(+^M>)qjCprP=5a(3qK<8xVVCNv`I9Iu=*mc@< z)^*X<&OO^b-96CL!qe5$*VEerc)EG2d53vNc!zsOdBapWm82}xLMl$}p;l3ORDjB- za;W)~nX*$3%114un7(xJG2edQR^MUY7T;0dDc=U)I^PLjn!nud_pkEj`Q!eOKi8k1 z6UpflXdmbr=pGmp=pX19XdCDfm=)v&R|HoFR|S^`R|b~_v5-8pH?%W!D||29I$A&4 zCfYLEHQF)SKH4bSJlY}JDcUgFCE6m|Hrg!uJo+a3C(4eUjeUtdjXjDzi@k}xh~*Tf z$Bl7)+!EKs4RKT494F%Y<1gbc;`eR$Y}JzgC3z)JN{!{N@+IZF$`{f?v@BW?Ek<+G z;7}8q$4s5 zS%e1BbLf8b1$qKKik?9)qL0w?=mYdB`UZWAn$XYaOY|1XklsXppdy)EhE$4LF0$A02h@ca06{2E?eaS#83zr~;7Kk$qANBj|f z3O|F_S2R&HP@KST;wr^2e7thBa-1@$j4O95-zf(W1BrgbK-EYUr0T31tin{YRh?Ab zRb5qWReTjk)lJ1xsZ{+{JydGdP}MxuXjMPe6jgiGc-1LYj;ggPRfVdis&p!aN~~(F zZKLg>1+<;D!?h}HJMCOurp~P!uJ5iNs_(5IZRledV(4P%ZWv}5ZWwA9XlQHbVd!P( zZtP)H8qp4cAQX4zTx>2{i(VTbJV>~rj(oo=siEOCgOG$-z4I{P|RPMuTYlsgfp#;JE^ zGB3NXxaztY?kqRc19|3n=$=&1D9?1yc+Xr}^F38B^ECB``beFmMrJn1Ov$`W)y%w1-J|%vd%hdKH@?fhTfWD>^S--2 zw*P?tpnrp(%8BQU3BUnnKol4om=u5l`~WR5JuoydIxsxI3P^(9;JV=M;HKc7;DO+- z;Qrv|;I`n_;J)DYU?7wg@`TQY?u1T-ZiX&|PKR!Vj)s1PzlVQ^OCtlK!=i(tBcp?( z!=u$=U!t{Rf1_wj7CRSfme)M5YhLZV4te$S8s*i@Yn)e57%9vxj1}e=<`squ1MzS? zH|~sQ#eMNmTo=!bABZ1`AC4c5AB(?>e~h0_R8Q7O)=EB0zD&MLzDRydzDcevT2pkW z{7m_Ua&PJy+7{YI+9ui&+Fsgf+BVuQ+B(`Xnu}p(I2rdCPZ^IH4;hab1JmwR0{2VI zr_8g=+stFk3(QB%$IN%ko6HByBg~`BC(IMfChVqc5r@vb2%huHV5G_ zICD4{_WdtfCX5Fu6VV0t+5hkc_BA8(om5((%#`(mvAu(s9y$(uUG@(q_{7 z(&5q;(w5R1QbJZCTQ5tiJnW(BN(6h;N0@G532aD`GK zQlu%Y3ZFu#Koxw&45d!FU%5|tN%=>)P_<5VNwrmVP!&~`sg9|RsFtXbs@s z^=bppz%+;rBEuxZ1OwN=HwX+Sqs3Uo^uE$s{b>AP{Av7W{A~PWylc8=;+vIbxmjdJ z%~o@|nJ^2?GBa*Q%x}$M%X&+~lC%UZITnW{X34j>EHaq6A++%HLYh&wVYi8?c z>tL&}&9|BD`|Yq@WykCr9Ge_l9QjVGGv@R-BTl|k6s#*z$fshFJHCn|FUaj*U9Gk@A)tLZ}@Nfulw)#ANWuDulO(e zOLHFOCmW7!ga4DPkvLBl6gJBlE`PP0Smg$IqLSC(Wbh4b7XC zH!p8m-l)6@dAz)2VKQD2FN~jwpNgM|pNxNt|BC;Je~q&ehJ-26DA_pKG+8IvBv~){ zJNY^JC;2zIsc1vd=AsA1FG{`T4Jw*ebgFnpdrNylyGnaQyGgr3J4d@f`#?KOdqG3! zpXe0B%NUflChae?3ac%vCF>8f8LI}XHmg3X0qYyH1*;>g7ON5KE3*~51>4BU;82`= zPJmst2pPs++6(st2n5>OSh%s;cUbs?(}(sse41)~O9>Gqriz@wz-+TsKuu(@PDg zA>E)ckcJdv%-GXZ-&EIB+tk$b!1TzJX?B`jW{LTLrNXkzvdOZ-vd9v)Myw(00NWtj zO4|zC8{0eE0(+r7*KV{Y>}B=>d&Iuoo^8*x?{MsK>~-vNu6LF?_c-@D=Q~e2H#;{v zH#m1X7drPjw>Y;u*Elaak2zO6HLm-v2d;ZAk(=kvcGEm=PsHQ*1UxQ}*YnKt(^J#i z%-g{`$9p1kU*^%w!twM0W4&PyT8-pZ!1l-~E65&;4z3-uagXf`RhDqChCHAdnwe99S7x5?CHc24aEY zz_LJkFcb_1F9k0IF9wyNqEKPzcc@vUNu+tCX=G6Zj&h=cC>rHPMNuRwjPj$cW36Hx zV#b&yW{w$RmOOV}R$ekMo@dX?&nwMap6AGm&Ubv!gQQ?xp#f3%j(s)Vybo^qa z`R_<%CB7zFCR-)fB{x)p-s(m5ifR`fC|Xy%zW8bJq>{-cpG&`%ek$EvKBi)JMGCzN z{TJ;E?FX$Iy%xPTy*m9iJ)7ZYW*Jz+ zSp!)>DANUC>p2Jl&Q+a$|K67$_Z+R zI#W$o%hizDrzX{WwMDH`ht)QcVO)AZOBHfNiI=9oFxe9CgfveRw$8TJw#L4}e%QX*e$;-ES?;{y{OJ7QG`h^Lb*>k#9_|uPsi({{-&5>KdRk_U%W9MLHnU$=|E#82 zjkCIDbXV1+}tHhB)f1{k5IZbk!<}}Z# zle0T;F>ow!I8Yck75E<57&s9)7}ytBAGjJg6WAKq5x5nY8%zxn!TZ6x!KcB;!Pmhz z!H2;|!P~)?!3RMyR1sPf>KkqpZXfOvZW!(z?ilVI?hxJ?ZXanI=@{u9=@ID@X&31b z=^jx;RZ%=jM$J(m)<4!WHYk=I%ZcU2sMwLbU3uH`UgoXNdz^P5Z&Tjxyo-6q^4{ld z%v)2qp)e&;BT+L^I{_y`iQGga(K*>S*)F*$S*NIJQIn!pMR$tM7u_qmRdk`~O3}rl z8%5iS-xj|s?pZReWNL}IL|sy&tajOdWh=_}mY*$O&S6wEp|_$pqc@^Ar@QGZ>38Tc zMn2;cgUeE~tSkjf%CfN1SvX6^(z4Vnf`zb5tOK0AoMW6L92K`ce<cZD%1_95 z$Pdep$+yeLrH@P>oz6{HrgPFqrB6*q(k1D0(r2U(OBbilOy?@i%Id^H^#=6<^&$0Q z^#S!V^(OUx^$zt`^-}eG^=9>6?FsF9?M3Zz?G^0~?OE*&?QQKL?O`phFEuPOBn=gY za>GMIJ!5_2P}4}$Xwx&(6VrTixw*o;#QfZH)AHK#%(B!v&z5SNZkubHW7}!FVQ=g> zVSjADWq)9QVSj4B;<)OllhHV%Rz};5t{ELN+Go_xXp~`fZFIeNeQ>>X^>T0Wtne)N z{PNWDa=cvc>@059%q%=hku@c2Ru-9+o+ZknvMaL7vlnKEvL*gLIfHY$=k(3#oU<}# zY0lHY&%mp|hd`Cw+kt0+w}HQbs=3v2zXjd|J_Wu8eg~96GMFFy9Gn^+6doF$93B-O z79JBB7#SHE5?LNu8Zkxr zY*f^%s6$cPqRvHair!R?vOW}TFWz1JtN2ZEuaa0v^RljGJ<58OH7RRbcD?*^d8nea zq7S_zy)%6<{R<<^aC+#}pBREp+` z_lQqO4oZ$mo=Q$h1|vg}v(l5&>(cwu_tK}**U}HthtfAvuZ)u2kYAO%(+kow(-)?f zrr%0ml%A2ENROt^PZucHDsL)l5!clp)c4f))wk4-)vwg=)Nb`_^#k<_^%eD7^?UU* z?LF;V?NjX&?HlcD?Pu+M?J(VRokp+IuQ04PEHx}QOgBw7%{9F=Z8EPkuQ#tYFEg(( zzcYWc{IqDw^&I!@_Z_z#cO4HM_Z&AIcN_yU#%D~= z7?CkJV@gKfjBy!*GNxrr${3n4Dr08Gu#5>A12d+&KDmCov~HbS<5s)%?xUVVo}He9 zp8cMEo;{uup1q#up4wimcV$*)Rz_B7RxGO^Yh6}JR(96%tUwm#+n;?QdsFts?4#MM zvUg?g%s!rdDtk=M@SLeRBXh>(tj=kW+cLLxZrj{Cxt(&`=ceQ~%AFLP5Yz{M2LA+q z2fqh@1(%0rh3AB4hG&PTM#e`bN2Wz4L|jp4G&AandZX^>sMw-dd8{-xFW;NrE8mzu zJ71PRC%;vGMm~|x&)4Mh@}c~bg{KNn7alJ>TDT#;J$^ObF3}+|KXEBBJ-IbGtf*@7 zzoNAzt4dautSK2&HlZxH{9O6n^4sNi%5RmAub5NuFs+camUV-3oimaz6hD#-K|V`A zO8-i0$bL$HNxwixNu{ zYZ5;a^O9h4ZZb8QmfV>fUo@d;T+x7{B}EO24^+x*HA=ve)RK86CreJ0{3$tJvcH60 zCM<)??w2>O=vOg>zJzs`bC2_o^MxO+crE%U`6l@)`68(zYbd)fzaxK=ekc8A`la-? znvR-Ynl_sDn&z5Tni{(LI*x9k&Z4*J_ZUtZ9vQNYK4ax^#dOTv+PcB2v?*-k9TOZQ z9pfA$91|VN3^K!-p~y(j$a3j3wz_t>w!5x-US!?LdYN@4>v7hTtZ!Mrva9>+`+sEr z&4zQtIjkH}&ZJyHE+=Zx=DNKZIVM7>-q(;_60@2*) zhS=KJgZvBm_woZzo`1V=bNo@fPoif+lDM7tl@KL4 zNq%y7a$3=>q87!ii|dy>FL_pSwd7VwPMM@kSC(Ezl;xEt%Ja)Nmw#t0XKiC`Wo>5d zWEktkX0WD_&aOXaKuj`I4{IN5KWks> zG22($T*nm0JjXl7d&k;{GsBVL&6w+|;=bvTdw*s9$ZG8SnN`DA*H_b5$Jfl?+%L`9 zne#nIlS|~vbJe-xTxD*)Tyw57 zw`nL44ux~W;>fzl&e(v0AqB$cVlqK0k(~74QPb?l^ ze6AQOp_lY8?OwXBY;)Pcvh8JMG;wyrI*UCl?|;RD$*+oDo(Sm3acPpWqoCR zWUu9ols640ZBhs7kU8=*;u!@Q4?QD&6MTdGf!t^`5=9H(0%-xBP$vaNykdSayZBP^ z<>Cv)P$|2VRr;i?qWp9D1=b5rKbc6QHR(*(%ruwZHQYbSkNER*^K#?4W^dcj{#bg! z`Brme;H>SLiA}iCQR84dGBZ#`yQ=EC?Tn=?XLj z+N7xHYH`<+)8$glO>=Rsx!^9=wy=qhMa-bwyixMqm@L8Q21B1-1d(fgQk3U>C3(*aPeZ_5u5W z1HeJx5O5ec0vrX70mp$8z)9c~a2hxRoCVGS=Yb2rMc@)}8Mp#m1+D?tfg8Y0;1+QE z|Hk(BfcwA$;34n`cnmxNo&wK+=fDf#CGZM(4ZH!~0`GwLzz5(X@Co<~d;z`!%~G1D zR847-(lVu0O6!z1DQ#2QrF2c{mQuMEP3f7^E2VczpOn5S{Zjg;3`qIk?dPDB!6`#h zhNcWlp{EQ_8IdwFWmL-Olrbq|Q^uu?PnnQ1F=bN94ZdP1;S?P2LUbhIdnRGjua{Gj%g}vvjj|vvsp~b98fdtDH?m zw^plr+%h>;kotw*Ce52xGqqmojMPx-HCDZ!DuG_yFg2UrAay`$e(J&06RF2jll0#V zB5g-nC-#5be%wZaf5Hc{P0G{CX2b;DpwzLIV}RS0V}J*#cT#Vr)?>6wo14~!-Id*v zJCN()XY!i}#s~}oy&y&87I{S{#I+F`(wrDhOd%!^V~Dl7^_6#N+pPh2hj;_971$5_ zlG+UXkXi-&mRbvJ4^{)KgI&O;U<&v-wF$U^-jq?B(TK5>(Iu^8+Pt(tT21Hy>mF+W zyAOLPdo0(@b#Sw|c5VjO%yn^D{N{r00*AmRunRH-_k>1Krl^{@jo2W*BEBp>Cl(+g zM2bidIf5Wu1V(s>40$JeD;tlE!bW0au+i8AY%DeeYeh^a7=(ZTiP;21%pv9yT8&7z zS+_+O*7q^GOhy~sW$`+^Zm-kp^3L;RZD`*@9LX)6gP&a4>^p^FE^@KHvJ&iq=J&Qeu&0yEyPUJ4-Cb{#u32vCXkQ?Pj zxXZW;xM6-Czn7qoAS8$g{DNFTjv!AE5cmZ7fTw5T6&n5kD8d6@L;x5I+__68{vx6Mqx`s?3gj7LP_KB#4BO2vUG#BU;3c*boik zLHvjraUwdzfQ*p6mwlFfl6{nYkxj#9U|fue&BbP7LTnz!!{%V;m92?3goVHeC6P(w z5)nd6s0js8Opru2QAm^$azanY2s;rb3>upT)$P;m(H+tq)g937)E&_k>J$2WeStnt zKiW9TSYRwPdQ9W2L*0e$B6rlC=Pq?ey%BGgH|&jh^SuEt<<0b3f+r&TA{EgE(IwIH z=(6biC=l-z9~kc+ACj5`9bgvd1l?dZXaWsj4wwm=!MR`pOb3fWE9e0&U=%C`3&3(P z5A=eCpb}Jp<@DY3z4T#>!Hgk{>5M^)-HbYEb<@VC<)sy*WkW8=1H~XOs2e@0gySazBSGgOwd${|#$GMxi$G8Yz#?R*$@}~-B2-XS~3+4;9 z2-XRf3sws%1d9Y~1PcW#1f|jCYqSm5b;x6LK@w*rjd&L=Ir}(b; ziMT)918xluhU>yZ;W}_jcnI7E?g00LyTJ9~M(_Z*Dcl&Y2iJz%!Of6y$QoobaskRbVl!2%|73=D{qO6)V8HE8WTr$(%V+q#Ro%etGo)4B_~#rg&M zHTtFch5GsW)%r619m8|O1mi^Gcw^9*G_Es!GJP<;H+?aEH~%*OF#j_DG=DQswob4f zv07|)+b^5Z@y9XD9dWO9FLG~pZ*i}2ck<5n?)R?p7JHN467Lr8GVfaNZg07Fr+2e= zxp#qgh4-L$vGtZi=ptj*5?q zkByIxPl=xakARoJjo=CJ6nFr<4BiHBfV;p=;4SbNcop0U?gw{(ufeH|S&aRRgN$)$ zj?b{>-V*P2)b`-sQgKR^ff%-r@e_{^9=Se&s&q ze&l}R-r~OCe&T-N-sk@1e&)X6F6Yk`oEKadoEBUYoD$p;+!fpuoDdunoD^IYToPOs zoD&=u92J}u+!K5k{1A2)brE$HbrN+Gtrsm8EfkfA7KxUKYKjMlSz@1f1Uw3cU>z)i zr@?9P40smIhv&i*;mNQV?gmeVIj|g7!IP0G$T_4wS{MC-G(i7DUm-t`hG;$XJMtB& zf;L5)p+Ax4=r80wGD$W?wo>joSJA-Y)zF}Xnx7Z`>AhrWLi#@~MV;iyG z*iq~ab{boYJ;iQeKd}?oN$e2z5<7+UQhJq{%B{+)%InJe%1%UQq8B-o>`!(i$C4As zCS)D*CNYFeAzPE9$u?wTvI^OroJ>|FTahEk|Hy{qM6xE?iR?$#BD;{a$wuThO@(H! zW`kzEW`Sn2W{YNpW|D4}ZnlolX>@v>N_SHCSod7_N_S89QukE%NSCEQtv{$gu0NvR zq2H?CqTj54rQfGNrr)bSq(7?Pu0N%JZFp-KV4Pu`XAaTbfv^TN+s!S{hhtTmG{&wam88wa&3lvre^Mv7WJ>vtG5HwYqH? zwhOi@_NsQ9!{V?yTn@LxQ<`@Z{v`?&j{ z`@H*z`;q&G`?mX}`-=O7`<(ll`>Fek`=6(?x1h2+^w;~tTa$WTSsS|I9ZkLRUiE(V zzOL*Lee{0u)}wxTzgD)0UV0x_wuydvKY8DH%|3(A;nVvj`BVLvKi#kJU&=`d)C}lC zk0K8uZzK03AEJAr`=VE(N1}V9$D*gA$D@~Hmts&HjML+3@!9dzcn4Z_T1{G0S{E8X zYfJkAeg=ooM$r1vzJlMtmb7-XPPCr1VYGp?L9_-m9=(8`Pd`aNOg}m<)t*hS4CcJgo=wA=HxDg!v5m1U-h@F#ka*%v#J>P-A9w<_D+_^B43D`VQTP z8ZiH3)@4>@S7V=M59VB9Uu5rOA7$@h?`CgjZ)NXeA7h_q?_eKbH{j0Zw&u0q_2&)X zHRm|b>I!*5&UKRHT>25{{$=nBzP_OCwMFPAowPzBK#rfE$Ss&E?O&EDOxQW zA_l~mSP1iA44wopg#EA^&VxO08BD>2a0#4%v*A)W47Wz6BOj4QC=2a}PDQ7o!_g_| zV{{Zc2c3b@{`;||XkCo4rkCYFU&y?K>8;O!q(nQuLC1f7SArX=! z)ntqek?%+s=_5rXM#5x*)Q}EROnS*AIgrH3Trz`nlbK`-k|OP-lQfc1^0wxZ=7Q#q z=9FfX>!IeF=A!1V=Dy~#=8Wcu=BVbF=BDPX=7DCi&Z0BxOu8!ipSsVwzq+rwPr6^a zs`^X%8~P{utNPvgXZlC_7y8@!i~3vo%lbR|oBC_|>-y*VyM}v)&xS9C&PKjbY+P?V zVBBRqY}{|$XWVMsX$+W7nA)4$nj4v$nwyxrnj4#&n_HXPn7f#Jn!8&1S-Mz;Sq55q zSq518S~^>LTZUNrSO!@jE8hxQ1=chx!%DZlvc9(7x4yN$vA(q4w%)bgvHEN|wk%t& zEockavTfIGjqEA*ruORghW1+aI`#(k+V&>)Oh?QSa0DHGN63-o=-_PcZ0u~{Y~^g> zZ0hXjY~pO_tmhQCBrcH)b_rd4SKO87I^;U&+V5)N9`7FI{^|bc{^9=OuIl;auHvcc z9q8@u9YXb|rc$jbI@O(GQ4^?1R1c~h)rFc&rBZFFK2$AgEH#g6L3N`#Q6s2nrwU`Ih*Kd<%Tbe1*QG zFYGJxMSTUnDgLQ`(r@&e{5rqeul2k9YCq-A@EiONf0MwBAUkLeE)FgVnnIS)me97) z*3gCUrSRX#mq@kfzsRphO7wT+YvgM5e)LB4X7o|?Ui3-ydh}NGTJ(1Gag-KIje)T% zv4^pnF+p4$-yMIHyjMK1#FeU{rPCxd5e=rL(dN*EG#zawZ60kBjZd3RLuk!u(`aIv zf~KUQG%0O5Z6ZxY)6>{AI_*4N$sid7L&dntxWwq6R+?sHnwVpm^O!W|P-Y({ory4q zGlww&CWASRS&uoGDPyKGM=@tI`!mNdCo<#%FGf3cf!9Ty1>U$Eb^>vK{#0xrzs@R&S| zC*qCd4danK8c)oV@d#cTPs(HSrtpM325%~l&zs2$^TzY$@ka6H@-#dJZw8OfWAP^Q z1UwyI#XrE`&*us{2C;Q--y(NNI_(Pq&O z(MHjx%IMulafvuCt`G;{DC~px!t3Fk@Fn;%d=7pL-+=GH$Keg|EqEJz65apfNOr zYS7A&yG$mR$oX=vTp&l}tuQN|jYsiPoWxc5T6`7GQmFAo_-cFwZp01vMm&O>@jTpt zD{&pZ5_jWTJOeMm<9IGUAJ4%T;}+bG$M7H?z@7MT^vm&q!sw(`OV?iCQeRWwSl>!tM_)_-PuEc2LGRap)qmH2(We-y8vf{O8mbt6 z>VND1>FXKl8b0f58Kg$kc-DB)c+Pmrc-nZuc-|N><(Mv+Mwthi`dmDRKdx0bAh&vWJhB?PMM>>Z) zM?0rE`#F0%Cpl+0$2%uDXFJC@dpS{8p{vwY<|=WWbe(dYah-Qva2<1_HFj<^6mB=^6l~M^)dW8{zCt9|3d#t zf3ZL2U*NCsC;iL(Mg9_h!oS$R+8^}i`@?>3&efb7Iaez0)_Ml|1v&&q1;+#hL1EAt zToQDK>>+Dtcj#bfM`&N@Ka`aX7b@WA)730Ksv9uU7_B!@C_96Bu_C5AE_9ON(_A2%*_B{4BW-Ig+`U@R# zGOmnk-kW=>-*Wacyd%m{M})5BcE%wsNQI+;P{Ql^Vp$Xvh-GwZQ?b4GAl zb2@N(a=LPQalWu;a=LTcaoTc*a3*kua|UomaYl0bbNX?{a3tJyyaHYY&&FHGE9Y5w zOL-3765eWFA#W{j1TT{p;3aqzFPFE1XXiP2L0%~@!prBC@m})J@K5nC^DppE^3U?? z2>`(e;S`}#I7v81I6*i}NEfCGnZhB$(L#oBoN$nkE1WDGC7dN3DI6;tEF3PJD4Zso zDw-tXh?k0&h*ybEz&qg6@I&}4d>C#f`3TpMw2)Mne1V%vzQe!azwiP0KS?V|dr2e7 zKR88FS27zZKsTW4(X;3i^f~$tJ%pA?KcOel`{-Bn3i=WKf=ZE5Ad3b(|9d~MzI-htayhX z#hWR<xj= zC=<#eWubD9^1bq-@>6B*^fx(OHAB@=HB04Jja7|PO;aJNzN!hTNh+aAuWF|nqMDEEyN}!Uc2B~_fV3k&-RE<(~Q30wnl}y!BWl>30W))LqRWVd@)iBj? z6;IVk+d(@}`%5!GJ4oAA+g;m5J6PLM+eY;|n^+3ML+Y(=)Gw#T;F_A&OU_L=s%_Eh^s zJI6lFzR*$bSngQh;5gMz)S2dFIWcFt6LgYJfm7*ZI3cIPNq35!sm}4P2`-sS?po-Y z?^@ux=AyenH_iRmec3(5Guy-PfSwtiah`de(VnNCx1MjF@17r?6z^E?IPV0n(L07Z zNByYG=kBMTQ%y3TQIDzL)K{ue=27Z6^@@5#?W3w@-l3jQ*QtNh1L_oYmbyxPp-xb> zGaF{!r5b0}$UI1WqOMRssbkay>Lt}Q^APo#dP^Oqeo@z`hg93lThw3by6>Uysqd2S zk?*GOrSFdKmG8FiweN-Rn(w*qf^Vju7qpGn@4yd`-?GGD?fD=I52D=Fib zbIS9}1?B&i?u5B6=d65uFiz5v>vK zi1vt~h$9gvBZ?wUM4XPe5^*Ntc*J-_cf`4fwupI=;plB>JbDv)19}abjE+EWL}Srg z&Qb}M!*HUXQ8O~%Gxw_%g8@z_!9rkIT}YhyOVtc&T0>58$%IAiQF zL9u&cYhx$l*5KCSzQ(P<{fzq&w-~n)_Z@B%ZV@gBw;+C-_|y1>@t?(aY#rNrbL*@4 z*YVHe7vMj`FTpRve}sP%|2FSeRIrSdu7AEJ&0mmL_HGbzVY zic?xsG%3=Q(v+Pk^(odATgu6l!zo8o)G3aX{VA4|?i6FniIlx5Eh)!RyeXa(d5R=O zlv0$UPpL{dlG2dUlhTR4g@~no7;25~(=qQYxCdjJl3W zp~g}}sNvM*)D6@q>Za79)WTG8YDuan_0P1WX@8{so)(n0Hf>GXa@tzjI$9Vllom+~ zqHUsu&^FSR(pJ(o&^FV2v?sJ_+GE-W>5TM@^nVE>>95eAqEDtzr$0)cO241}D*a*l zMEb4td+CqU<@9~@K6*q(Y(`v0SOzL1Dua-bl(9KuOUCw$%NhJkMP_McaV9sjER&a+ zmsyqhZzdyCp1C8lJd*`qA>}f%7!1a1%(t2EFkffB#e9?b3G)r+d(2mvI;NJXX5M5b zvhb|!EEti9|;_8xYAR$kVQtfH*!EM68fOO(aR`ZtT6 zRhU(p#m&mfl4NbqCS@mOZ_7^3Hf9^LP1zT+z1bh{z~{u}WaLEW5OOd%@j0nEA1B4+ z&~uV<$T`b%a5*33uE|}V86tAr}>k4FY+JcoyohGw}F2@?`8h; z{8{{oyqEaT@XzEs^Skq1`4{sqh%Zbm%q!#;@(Q~Ow-phJ#6^WgqN3uW zq9SQgX;Dd$q-eD0a?xq$uZ6fn&V~$z+zGi5awDWKq(9_T$Z*JL$VkZ5kjo*S&>dkpVMAdz;Vgx!Q@f|wvDhzKS^ z5ut|ALfAt%LTD!(Cg=%nf|bxoP!LWK8VFLtE95gWpwFWppyy<;Gk6)f87Ub%GRPU6jDIusX70*t%&g6< z&g5j8Gu4@f%$=FLGqsue%nC*UL&zv+lrc&fQihC?&yX-m7+*8jGQVej$NZA{IkTE+ zX6|O*X6CahSp_UHtAtg~DqOO;%NwBP%WYO7_+4f$WRfpY6cz zh~6Q{$;1`;@;~Ok!+(#zjQg(nKn7M2%1FPbfSQuLDOanTE+r$lo^&x)QAO&1}er$w(8zgGNm z@k_;@ir*J65Pu^6Nc@5LUGZn)kHznanc`G2L!2fyNc0lAL@8lPc1lVmyCg*tqeLMw zOBfQFBwM1B+?I$Wxso!8R+1&jmsCj#BzclTiCkima3p+5jYK68O1_n-%d5(tl%r)? zGNz0p`&YI@mMde)xUw8sw#+5#md&rIt*EP*El1>YC`LtY3Kh82d5 zg^h%*MlD6HNBx8fMy*AyL9IlgQBkNM)DqNRsBchzqkctwh58-!ZloElLf4~rqIKv! z=-p@ox(W?%+l#sz^*CxWY9i_>%>Ag@n5n2)m^qkdFt1>eqUBf_R)dvbwOA>(47(Fs ziLJsauxczJ1{)I>6CHCW>q5-M7+=hq*uAkr+`l*mt{!K>X>kIa5+}v&!PVk4I0HzhOfjI+uzMdIB?nk-$pWo6wN3 zFVT`%lejl=f8wshJ&6eMS>jv70m6O4o5V3fKVbp!31OIUh43En1L8E{3*tE8Henud zl5m|6M0}2Tjqs5067dn?CgFMF)5N!l3yH4~CkUSt=Me7_<`Y9n29l1XB^gPxl9A*m zq}j>A>GMDOpO!k`XeF zOd@BIlgK6HaI%n0AZL@y$Xm%7WFnbG-b>v>RZ=a~om2(2hPsccq8g}bs-9X!-9@dW zny3xbid01^IxQ?MCM`BCE)AQ8NyDW@rEN)zPvg@Bv;tZlEr*sx6}J zPWnRnhxB*oAJE^Ye@cIs{w4iAdL>;&SJRdBqKx7UK}LQ?cjlqY6PaC^y_v2|cjocT zW0~!lj!Xrkim{VX$TiG|WZ)6W=U&|iM#_vel zq078*@W*KjZzudxeMa7V%!@J{AUC&3g!vs3f>aDEqF)p ztYE(2HNne*=LK4UUZ4})5{wFl1t$t@1qTXF74#Ok3r-gtDmYuvQqWq^QQ#>!R&cQ3 zaKX8PzY8}M78ec_UMf6SI9PbTu&?lX;m)GUqN*Zg(E`z@qJ^T*M2kgliry2=7riEW zNA$Vq3(-8$>!P5_~{ z+9ZRLPRVhJOL9%pEjcZ5NG?k*O0G+KC8s3&BtD5v(kNkmVXG23DiW5_W>G1p_R z#SF#_#H@>Lj#c5RapkxUTqDkgJBsVV9mE~M9l#ah&f?GDd+;al4*X%f0DlaB0e=U7 z4!M5{PlcKZ!9!6fuIhfw+;lk{ChSOhS=Nq+KL4 z={U(wdOG>3$xgD4Y$rF9UF75B7;-!LFj-CRBv+H4rWnX|}7Nga zjjqU0WmIKUW+*eX8M=(J40(nuqc3wPb0G6Z=EcmbnHMsBnO8DzWnRj>oT+ClXRceY-V3oaFm7920QSl}xdEO=5dQt+@qTqr3l zDZE#ByKt;sklTe78i+&#a~E2ls+f@Ncybw6)98ttMpIl zd(uy(uS;i1S4zK?zASx7>XdvSeIQvVeM34WnUwrbI$Qdg^oeAV^f&2G(yyfRq%TV6 zN~a~yOA+Zq$$V*ZS$A1WnYHX-SyS1OvVCQT%WBHq<#T1P%U+eqWinZ*Y*cn%_EW`o z6+c#dCjUtOg?y1*Ex#=vmJi7L<)iYe@*DCY`E|KfaYWImIHZ_RJWxz2CKXGRJCr;n zU&&T-lq_YgQmT|FOO#AynKDb6uUx2lOSM4tp=zFLk?I50+p14gud3creWc1)=c)PX zI(4o3wEB$tf%~Z!lkAKF55AS&U&}#xUcU{n+FfVoXcyq1a=%eYj@ab=+m#0InZ5 zh`Wdz!4KiD;&0;n;T`Nb2|E&+63!=_Oe`Xn6LW|LqJXF&Dv4D@HIYx05=F!^;=jad zqMj%wW)qD>1(8QABua=FQZ4EEfYjsiV{@)U>peG;*4ZwwGq6mC$z4YH9T}18ooO)%4fWUr&D}otwUlzM8&Al_BT5Y z<+SH?<#gtBe3jP)Z3&I4y2$l+J1$zW_ zf^oqe!H2@Ph4Y2437-+p6@DUoMfke#P2n8jOTy=b&kElcz9D>9xT%m*m|93JBo~$y zmKIJGl8ZKqHi*JSA)@u7Rib6ZLB+fhPRXxgg;*;u_5GKH*4Rw+}QOI6EMf2)2`1*!g0-OK(~RiGBAi_{kNarJriL-iB&XPQqnpJ+B~c4~eI{Wf%Q zXa%YgB||AtDwG^W+43ib5KWA3#cq#DiSghr;cnq>BIE4jDs0ZGGAo8!I;N*p7AQB6UrW)~qv(V}=!oG4O+62*uTL`foyC`yDAVMPSdX3@&xRmH1|*A;&$ z{$2cs_-}Ew*dR8E_lS3i_el$-66t=aQmT>)q$a6Ix=X5-8l`2@e5qWjkrqkorDEw` zsa{$wZItSy2IZ+bye;Rm;pWy=<3ED>KN> z%FfBo$UL$KvXF|`iS`}W!bIPZc z&nOoue^Rbhu2-&8+LbotG362EQRP160p%%Wld@fDRUTGGtHM>ARBKfj)jHJ{6-u>U z6{!kSZC1sq(5fhvNL{GDq@JZgH1jnJHD7DK(k#+^saday(EKm-r_l1S$*{(7GpZJ4 zM43>#P`gp*(S7I(=-0RWh4~xv59Sz_5_2T>A#P5>s|hb9JfHAl!pjNVgo_D%2^SNu z6E73Hh`q#fL?`hQ(M#+h-XxwNb`viW<46|Li^=a$zMw3i%%^-!`Izzv;Lh78<*{RQ@8d8m^`cz$NRjQNLLEBF|Mw_1=M|Wg&X0&IFWqiPRkMS|% zea2gi4;dCl5_21K3Hwj>Z|rZ_f3SzyH`sJeIwzAu;bd^g9404~L*s1Ytjk`T{cm<& z_Wtb0+0)sXJI>~u&cWy6a<}H*03(PL-~`bEv;ZsE zBFGo)7c>bb1R=uJ!nML6VYm<_+$>xtj1YzjmkPs#k-}w#8HMyhMd7nWbBdlX+Fi7( zsJ6&lv|W@bN)r)9WD!f$CJHMKE#6cdQXF2~SR5q&M{E(-iZ4p-(i74)>3M07bV@ob z?UJ68)<~~OJEd;vZRu6GQ?p&_lD0}uO0P?^%FdTvDD#ysl6@`vM)sxbb6JCIzpP2t zC%Y)SB#W-tQh}|AtT<9}xZ+SnOT}vWD)}PSSt^o>rb<^)R0I`Im8N2;a#ds%LzS)KtG201)naw4 z`jPruO^_y7vq6K>L~78QU&8mI_MsY3SJ5jlHmn_cJ7y%NHTG!i6z;8r`3Y|(ypeDz zVKDJ(Vt?Wt;wbS3agaDg93$Q)ju8K({6zVV@(bmElpiQdDZf(wq5MwyjS@upgR+DY zOnD=9UTSq}RvJ6)Ak9qQMQ@?sqIYGuGEQW4XN+eoWPHl_g7GEeGsYsuUPcNN{#lec z$y~!;&0fo1#a_X_&1P{poE**$&cW;_*^C_*a?a(<&E1wu$o(Ym32#>3H1EAUByWQE zbl&rM&*Z(B_n7xi{;T<~<-e8xM*jT#t%5{>RWK=t6B313;Wpt`VS+G8xLsIRlqbp; zaYb8-QN@wP5yj}@sN$lMW#VA*e(^r>UU7qXZs{AP58>|AS4!uVPD|e`eYNz<(sxQ< zD!m6+|4vHhl)hX#zx4Ie2h!(D?@M1OeIk7%eX(>x`daC;r5DRCmt87bEc;Gol^v2j zmQBmzD&i})R>W2ut!S$Vk#Cf5k*}AplZVTHRQylzgW?;-SBjq%ixi6$zbd{}*cF`$ zo8ndF>&n-Zb1R>#oK!wj`FiDjWl-gu%9ksjt$eF;Ugh(Z8kJn7SE*DIRfVcVrBv-y zm8vRLyHqk&l}e$~s;X6Ll}>d;Rii3b8C52gT&+|q)C1~%^>y_%_4k^^8jL1R6QjXu zwrIqf-$Q?cz$gnlhB}ODL9NED!Z@)fuwyZgaqlI}COv}dP45#C(lW|&%38{5${NZF z%1X)ysqdz~lgdeZE1gL1$@rG>1LHf!W_CDxoL#`-bMiStP9CR-vmyHs{0^}%=k2_& z@;=Y|DDTs}_w(M#`yy{~-p6?h@)qTNn71%*QT_+{@8vJZ|1AIg{IB!Z=5H4e1StZN z;DLZ4%oMH=GKDPRt3~sQ_7sUkg`${ZOfj~2rFgk`h1e?o2X40gxpYzKUvR(e_ocs; zepUKQ={Kc8r9YGol=YWgE&ECKyX=U}C&R;Swzi7a3bY(0|4s3iVx?laVyPln@w?(5 zMYrNjPq!Z^=OeVB)Gg~U>oKRXz1Z=Xj}sOoe4g-0!d%jGq~}R5B}Y(Dlt@Y#<-^pEQfpGP z(>%1(v~#qxwC(g-`cI5T28BswMzW*XTi6(O6#FiFj4kGD%I0TZ%pv9eFYl+kC3)ZE z{h0T2-Z%MQ=6|05RsOs7zEUQivp?5>dHGCWAllE^Kh3?KsVkff8 zILW!c=LO~cmiK4g4|#v&{hjxH{*U>K^Oxk)1vEjLU|LWp6bXgGeBp}1cZw=R_~Na_ z&Eojdh*E56WNA!kyQ~8)Fh(i1C_Yqvq+Fm3t3+3ZRIaVuP`R!$qH;^+`pS)!4^@+@ z5!F@IP1Su>ziL9|Q{7fwQ;n-eRaaEQs=KN?szKE)Rhzm;J+8i^epd6o=2y)xnx8ex zG@CS34MmfpA!|;dx=|Z3+oQitxRrQ2@eNWe1xLYB;wYb{UZ4%oPG|he*w1KU5ZN-0 zAbWf6vb~ml}VL}mGPA^m2s7`)zhju>ZjDts-ICK>RIaN)lXE9RZpvTsz21M)X+5P8oI`f zTAXko;ce18q_;@#lHw_!r|wGiWSqMHd; z_4ArlnoJE#!_+V|A4Vop$m~D!_ZAsN$HcVK%u;%3dTE@3R+&~wtxT_+r+z~{p?*Q5 z*KDICP$t>Lyub7R%Ks-{Evzi85jjNbWN8&NxThK?H_P#gL`9O~Gv%A=x74dObK*ZF zeUZ98uUeE_x}!9wl%UwASgd?Uy(o2Eo<{g@DWh_~I-O2ZFe^V$6DUNAUd_?0(Nt)1 zGOdym`G?S9aVGYIsLcx#7e+3OTbR6X>%ypogoW6JVGHpKBWA8-LN82Oh*=oEFkvBT zVeCTE!uW+-7H(S@y)YCmZTi3Ko1_c<*GNIS{OZ-92h-E9UEO~>NHo3kz-`M!P|kEw z{lv?YRkmr{E0e452id2O!_BFJ{j=vjo;3@ZjliA1$TP^Z$Qeb1fxputbR+}GL>LJCQVC%rSqKNoMuNG8 zV1*Y~YFBChGhclb+(qf9J&o3$0=&+T&kh0Xb^z=3(~A7GlYqHO0ehiEhakA@-T&`Q8Td7;6TdiB8TdP~ATd&)o+o;>53(;h`YAgILqjgwaj4oCer^D&st*|=0E`nIl_5*gS{UC7i6u^l&WN)?~wzt@i*jw#K z?QQmB_I7)R-DbDjkJ}ygPP^0IW$(71u=m(|?I-Q0>~8yM`x*OLyT^Xce%^k;?zQ*X zFWN8JFWY_gEB34Qe*1v^8r(8CXh#qij8d+IQNBb~p{xG0tD(vmz)V%uGZX|_5x~}0 ztpiKC{qoQ44p7WczZR%l0`)eiPpE*D>qciQ-Y2o(Xoj{#u)gIIy(l%=kYg@EO zw5{5s+BV>oRQY)mRd=fNenmeth;-z)JOg%nO*skG*=ns&A$>f_SRV0sWxCFL4d9+W~CI zFS{FP^M>p<>^JSh_FMMb_7VH2eat=%cJl;yckFlV_v{n)N&9{Kl>LGIq5To?M(d#6 zvl(E6OqgH(9;ki7obg-MOv#=pvu4V4kUZd*oJ|AlcmPWS%oD&;0UHcpRKQ9sAh%kt zy+3trYGkSp?rR>Kx->OBb#LnG)a|Lssevhjc6{pclu3Jc>dMr0xXta<$zZf&i$4*DDS_xDx2cB>Yzg|{|pleF8k1T95N)~0B;Ym>DkEpbN6 z=_$IF0WB=`(BkRCRn1@}cK~my+6VYx06$XI0{A08KJQS~!5K?81j_wYjlgT%3%uv5 zwKZC^b{F*bz+ZpCT6G{Ga|a|w8-VicXw`Vt7}RzgfZ8`fRZFXuRqX{Cz0L2f)T-2~ z?NupN=~eV9MisM)P(`d-0h+=;xj>tP{x=)?@3nowS{@xoxLyXKZI}9@{zF zdD{h>*VbpdXuD*)Z1dT!*sj|8Z3DJzw(GV*+mP*s?WS$mcFT6#HewsKjoHR+cWifU z_iPikNgGV)AgJ3oOKZ~wW`Ex{WqV+IXnSOP49|-od$4_}eVKi^eT99ceU*K+eT{vs zeVu*1eS>|YeUm-J9%>J>hub&XBkU-9q#bSFVvn+8?9q0tJ;okukF(?K@%F8Dygk95 zXiu_lvlHw@JIS7G-)>K_lkF5c)t+ikv(xP9c6jTMJ<|?v*|D?iYO zZm=8eCVREL#=gsLw(qvr+Ux9l>=xJ)j}C$Iv#Vel1h|fHbo+G&bXMI# zh^DqSf8VXJ=9MV091p@fSn1q1v#3_ihGSzTGbw30S2cdo?`3xmk51;3J!W zZgB!VC`i9lk08qc{Aq;)rQfWN)JN!7I&}I?jtvg2zAC_5Y6vz289>r7JtGSbc7x9V z^Y!<$_*nISJs=1g_t&SVUdguRfw&;z(TW-KRU|)1Wt3QJr%YlLcSmlU@ z96?NwuQ04Ktc0-;P_>+mA8p zEbH9<_Q#s)y?ea~vJzU>1X|mwSLs(fVgvXt{ce4zqgHPY)DUC<#xjJHj3N^i5D}1R0NC=9{&Kb%ynZ4Td#_5CakHmFOTiLJc?=Ya7%y8a5eL2WFq( zNCJzMoPaio_Y4-txM9L@&{5~OW7rFF{&W}QCIN;F^^W_7eL%H3ngYBA#|^`3n3IG{$vq0~tKPgMidy<89+A6Bg2&tMa&$SJ)u#i?;;Obf z&r~09Ham|wk2)__pQ~y9!H zbq{oJGDn-k&Fjsp&0yYBFy83w5fD0Cd$blodI8SV_Vk?Sard0=X@^=jfIppw(lvvF z|Ml2wJ9}VCKsi<0QhTJfujhybj8yBab@rU7#kg&?XL?T8x@$XYT|H+(@_3J<*3)yc zwyUQV+8nEGt3B7#Q`=E{uJ%IhsU8o|F7$NwctNrk;5@)dfdA6*nQ^zeBVj)^SP&%I z9q-<2iEuYrwz$LGjTV&KYH0y_67WL-4g#JS*n9gdXm`CO+`Y+-b%(e&x})52Zk&5R z@L|V$V%!_tu^@NUf_JxC)&sWLo#1Y^9I_m+91h6r3FMYQe!KxeVmy%^1nB@Q7D|7L z@Sr{I4O;>=djl5Aa8H=W0TP`JwgzWIs3+PJ<=H$VeXIfH0mGjG!|!^kv#Gslzqh;T zu(#D~YqB>T^ma5I^E#W_VIv>$b~V9v@H(3IL9NBx4EX`?@unuPtLc!p&1>}@4Q%%& zYl9W!0H!XFUEXWmV;#TjSF7H756Z~^J{`y(U%r32&N_N|xAo5D{niPfJ-BSK)>pn$LXyQvJU9O4Pk~yhKGj7h6fNX z)|%Fs)X#z8NS85)_CT2(sSPUwyTD0J#3tH{*D_Tae(EbFgHeZG`Z&*$@#3R>9DQ2r(kg z9BaPZbE)STI7y2>0>aj?Uv_D?6G3pG%Vp^0V(q1wz7V7qtb>{fcT0`U|3BbuFl~g{ zkOHyC<-AsX0wThJ^U%|uS9-4YT!r@iJ+RMv`fIP$`f3LN-xhFj7$x9b9o`_{e|k?J zs%x1VgxTn$Ak3FsfIcc_wOhKuC#|s1OC3jG(pwCX26RA;>w)QR&~F54e83#7`lI?b zeTyRs_#{wpB~0~*W4UpK@o+%hRmNpA21AhK&f#6#14^d^@(|Oez@mhkLQP>a%X14x z7_N3Zdz~l2C_T>G)iuac%>%jdkPAN#;azf;k>) z{xk?vzFvE?XJE#Z*LwzQuhkCK4)xps&b6N59(Wq}L0^TldK)?{1UJb|bSJxQ7Jp+G zO#Vbe59B>fcGx*K?{Tlg+Y5W_L{qSDsqc{Wpf&2MUoxmUxOr*w^5*gWJN?U={S*Y* z18ZghK#*Hw$L_V=>jl5u6fhM8BLgO2#?=9nv<3_mVM3WUn<7o*PD&>dY`h3c70eo| zJ`J-Ug?Wy5C!6ndlV;{cfRZ?a--4O^m+Y1lSl&*{cK1NN!*U!Z;RfYTHJofX2}&c# z>83MHZop0jYRh2hm(MK!z5W%=cl#j(v>X{`w8EofETSE3t3RekfpYEo4seQtmq4Yz zv4$8>eT|XYdB%AbblYye-P2`pTDE%P11=S!x9MX+qT8|zS|&T<0B>`wGp;orb)Ze~ zEx~2zg?S^e9%Rt=Y|{!~Gk6$;i$Q<>_zs+90%r0!?{@cCT$U4-P^jbe-P%ql9s1+? zt%i8$b-UwOz;Fn1uX?=tZuK3o5`v@zta2LW9R|`)fCK{`q*DW)HUYkq?*k2fjD)sH zhD5`9;|60|=N9m~D1gc8`_)s>57~SVyb8Q6pyzUs?E(w5`&;7MXGW!UrU&{w2Ua)_ zFxfrPJ=J}`n*th8+_!2+dWL7b4z%~20gV!7B0B62-{HWV{bQ^IhZ%t&_FqCn@7v&H z*mMQPn%^66L_a57pP+Z?yJ0>j{O2$~m-7%beNg=B&%+7d|u`>ZM0)Rio znY00$`*8+rlhJ)ogG*uD<4+ zu3lfWq9z#lSDedh*3^X6Ty=V#%WC?Zmq2zU&{x-7a9$3y3$58uGw2Kl+S;0n&Q*av zm(~P9ISl-bH8A=Bj2^ez^{{)L%RkcN?o4yFnPxVbv&?#Ps`*j(GMCQ0$z?EuwgB)6 z!L`(t0oa3Xqj{~1ZC>xHF{hb1W|ld~Rb^i3TIFJzwPt!i)-RuKp6*71z1Luz*~?w< znDArFjWF8s-iNhgu=6K+?$!p?-R&8vovNL#eF&5XwT}aSH{Elu_8!#zX=(4WUhvS` z;NCm6%j)2v4fHXPTG>0*^SEcCc4^&%o=3Goy{mewU{9{-U0yd@`>5v*NZk+gH6G|^ z5~Ag!>!3lwtkIre=mtSDK)l~#a$m7rvasD3EL!(93*F6fGu`90K8pdk)$TON2f_Vo z+}AA#a?Wzb!f~Gh%n0=JmR*q3+}8|a?1UY3Up@`;`_&vuWmfe~oi*D%&_1C+hg;D!7;0MnD~N%hb?+dLVba}7x# zb-7`*VYq?dxdvPa?+rr@1AtNBlxDmEs>Iw3&>`M>d*QKh+1u$om6)5 z;dObtycfORCXctX-UkcDx*SDT#PzNQ|ic_2>rH=XxhZt^u^oxJ=nH{*I6ymaoz{*( z)LG-RS?$*KzAmV(^=A?Etss1p)R}QRcUOliHuw?@)2G%tP4?O6f?DtQI!b?xMR3|IIH#8FsIc|_ot)7ZNtpg zs#bQZzt##T%aArWWsV#iIWlq>&XtEoT1Mc@u3Iqeidk{T#>eiAq1xeCIyO3XZ)|KV z6omb0`cClOE$u;f(e07I{Vzqecigkx1D9?;*M6bB9Wc+t*$H?~b&xw!I?hcT?=ar~ zPjajSzGJw5J5XEW@YAvkYy*5gFvb||4y@4@pfOA}5bLS~@h-!}3`9T^)H2~IsvZFa z*`rR_#m>z&|Md!oYKR-Fd)M@?s9PD>oV(pamYWu{`-X+>8K3bP83M^(?e%;O>mbVn*u4bIRav^Z47$*dAE5p#6;*T zki$0@X0$5?@Cery7siEkMFNg;g}TCAwPrY)nd{8qu4ss-h2zkAc0GKsRrs-`A+B(U zlVQD)y&Itn?G1r^GXT1GRo&V;{|K9UBcSe2YwFelW-%XhqoCXXu)1!2FMPx5@9Frg z`amQbwv1Yiy7#ybyT>d?fYJfr2yj~6jqYZ^I^D^CHsCkCHv_Q= zPG(J`-hS^bpdrZBKt2YXI{<@F8w*gdz8>pV2rv*Yt+BpDU!?D>wbvT$i)hC9@V=Aa zp=Yd7zBpfk59M=PV*--#zHL6V4+r=uYf^v$=av5}o7W9QHlvz141_^I*$5Ci5Zw$r zt_1`6+JO+DL^W@Md_4fV8UBVb0TWcr+Awr(YSYl#p`$J9hafhzY=j)XcxVY3YHL|D zv@THdQw*(L5I6L#-NU+8=diZ56KdgYVQmv*_s8HNJBB+Jf6Onp_1Mz8m_T?qHFWNj!%M$>z8)LxwiDK z4>;l!jOA@7=s5-oNF^D!!Pdmq_~k(d@R##oxC_>EkP~6dUi~TkNj=8l)>j#*Ag_fZ zrushg**}Y5BnEahJRg8j4XV}8>|`=ay8+Iax<+hy7tpzJa2>ul((n=xpO zX*XbvorgO2ch;KfO^v3#od-M35HSlMz+`vNN~$4)jW%_y?xNI$cP;N)7YHYbH7mOC zHS4=Vy0!v0v}-L;Hvpv85NbAeg#ngQlU%c=i&V3!Yh@R)W?K!lW_wKn$ZiCl6^zho zCc6%plU!S2J=0wAkRLK9yIRagf!A!NxQ;-Hs-wH`z=0!&YrBi;N_VBY;5WDd$~M%xGt zwKu#jG9ZVBJSu>}&X_5&y)iSZ2oW7Hw|mOc<~ilQ7Ff5SdN^$WHf?!ex#jM2Uj}?x z{SEgO_e0Ba;9YkQ1mw=RZ@MqJ&ja4$9(H@(CjeVo?{nXFUv!^zpLM&S9t`pq+#dHM zOE1)h+>gN<&bdzm4m;lsuJ;%w_I^;~AqX=EJPyxcPbXkY8~uEEfP0QX*lG96R?453U-1MmFp*Og1swsFsJcJ-HO?&TnA9)`% zE$zGKeb}_34+%a$4GNV!mEyZ%^;xf4nLdh-?j!jazDyt6m+rf0rTO|{yKVPff}G{M zY$f|reHlKgFL@?1fou3825`;jfyjZVf#?D6R4ha!6m0g*0N4S{z!oTD0b&NWHpc)j zt~nlZCxp6a@TuV~P&2i{ccR0t z;WNXhhmC;u41;ZFj!BzmPBKSF9*jL4do&gu2vk_em)!-k-Lu2_1=euFJ8^o_bRRy+ z>$gJ~NztFy8w{r$sm3(evHML2OiiYJu;bEd{L&F!={2+(6l@89Y6mCA)+K444VfR6-*GzT4erWwfH+79~;;K zadq)^_&OZmiFFBe@ZSfy&@OXr{kVI~y#_pXb^WUPb@eL&gJ+TFq-RZIujdT7&bmgo zXLaM+##4Z=1{Yk@w-)mM(lzUCE5|oz9ky2aZdr${H>}sKH?4`yJ)WfI1Xw$KGj`~B zi)Z*8%oJ+JVqvyquw*8De%|{pjQ?m>Cm4#*n-oxSWBrEu_4Vr;H#DC0j948l6n(Vg zjGhLjf$i#GfJyv`9Wb{aTNhA-3LT!+pAJa1KyW+)&>S!s96~)C!RYH}6yDXEs;}02 z^yv3>Ez)+hYAGKuI5z!UI>U+&j!u=w#^*e+d7 zLf6)==q^H6a#vDUT$iCHvCCM4>%waK3TXxEN6Om`$!~D2*<*i|IOH*19-QgR_*Y7LJKK_|UfS8FC%$0D$CP zQe6s|f>K9@93}`fY8|Dw&Xo%F?S2V>?Y-3AR4D&T;q_r)D1W-=o^n5QZ?2yPGotH* zPeYsr4yrx|a!mcCI|9lH_g(k0)AvClvVQ65==#U*M{aEW1NWAhKH!5Gv z)f3uy$ur_P=Nb0g@brU^-tt_7{Gw;n;dcfg7fd zJs$Jp%kQqZ3vsj^j^7a3E<)MqFDFtvVC_2kCLB+TiDQ1hxweRyMMauFueC>d%9NL+piZyvOCoz^8}|IQK7xB_UX#yhZ_k&WY?&9LDArKrB>z7_j1eOvm_ zGYi+~o3!481)8w#^)G4*u1IvxLys5kp*Eb8*b zy1wqtmGTGVArDb>m4`g!A&T-sjkcEtB4& zw_)*zxRiPRH!R`wFLxON1`n%-{V>F4K80a7ux62Y-@Iog%&zTu&NS9OYn$cZC-$5f z;6ihiqt;R9sCM-8`glFOUS16r{W}d%s`x1AfEb?ypM76_UA}5jm8f0N>HC6(iz)lt z3rRzF`?3%by5ARtgds_2Tsj%u4^2p?qCccl(&^}!bP_>rGVvoZo|s6CB}$|B;d1{v zUj=J2+y)9C4oW;BLr+=7DYZ{H{Ws2F6WmQ7mTuT0v0RDSjk<^ZCCXM1SSWj_5iM`{ zHvHi6Hg{lM{^K?9?PzbL#`|HMFis-m?J-1*aijQIGoEcJ>9F{N-O$_qt9Yef^ z=hc6H-t2B_gB2k;*7_5hI4zxt>g7`jo)Rn4o&Nu}j`3yYVP5{U7TZ@!AD-_9cs~Fs zOj}+^zKD57d6m20c_a9fvp70JkNY#wP5p5IYjo%>TPJ!eC9{+^cIHP zCHN}n6ckVEL_NNG(Kl*!voKVgrBYRB7P9=pD*cz!3BJ;IS(dBL*I*ZRI^A-juUqfc zhd?=ipXsA|CH5t(cYzA(Bj77Qs~G1vwAB9x47{6bTr;j1IYx#tzO803jcj9Nn`P86 zju;1wb&S1a+%%dPJI3>E8mQ>@F@uiMWR7hw8ug5eZ3E+wVPtF>7mV9REyl+E$+%%$ zHR^yXUJ9;jdFBMA^>ygmbFVY2%p1V)%w=BT zEZdIIX33^88>zOJ+pC=1_8P}(Ua_UNX`Jir?Dp06CdX#p;v_MO8nbc!Pt4Xl!`raY zU>9^7ox|b0cd%^hwmIHg*dd#<&EcTt9q>(*EDpoQ!erI%M)#zk8BS8`ZgN+;zX1Cn znh=z`-=OxhXk5@JY5+DRc;$XN9THRkuLCrQ-ii7J^}yadJJiNh(}@6qOM_d|C=`6Ak)CeNX#MqCQ{0ubgNVwToIrV^sg6 z&~eBdT9!J{vWh^kBCNocq`J^6P$!{E;w4I3h#6gweupIX(7M!s7K?D9HR(Y}A36+~ zLe<2)v;yrGq88MxqHY6V1im7jkCwh53x)mdi?-I6k-8&S4&J-QTKj2h(I(S=0t(uya9HS}5m zgf1bld==PILZA$Qnoleygi5=7S4ql6%H@OwAGn|WBSiWSEI9QK@e=p4ME#pT#4nGo zBItngP#wKIzuZ%XFJqV1E8~?J4Uez%$W2#GV2x5sp*zBF96?eQ;yxco#v1M%$uoB52TQo-H@rpJ%i%%#2bSu8qy(Je&2jV8Yia z>Jm-)W_;7wAs2M$4Al^)C|OYsRB?i(ij}SEeI=Iqd_cqyND#V=Hinf!GH$j>vz>C! z9or6v%bO9rb%)V%Wg~)o`B=2Mw<*{ZLZ(vMrX`M3$4pw}7?1RT1!qmOLm_2*l5hJWiCytv+r^<}m$ z^*McTD-8Ss+=M=fJiQg)y4*_XQ(L~Rv#kWq^}qgSj6W1&$c-Z78RLqvYb1AgBh1({x_~3VB6k8Zj2I)xIAQD?0}KZv&d4%O%;yZD(ZldD z{HVWVq!}qjl#yU~8F{=Z`QyJUt;l08XWeZ-Y?rZO=3m=98;?`Ta+w3>r)|I4YmS(s z=Hm9x?F!Z|CuqLke#LTA8pXS}Z9b=f(B?Gz%ntLZ`OM6>y<}l8%whAn`4;2<^}omX zeJYOJrr;OxX*E5Q-Tr!j%|cZ%2{^EY;ukewFaBQCgzB3Lff8gpQE!G zZ4!>uCb4NaYL0+IaAce#^g>9ri8#A9y-j7)*beau`Jpu1KfdTkY!dMdJUtI_9x(5i zc1$>E4uZ!Ah1-yWF4*I(qLq<%%v*E}0mDU$x9%8p$apH=8t6%fnkVHA0GktRI(|3~ zc~g!J#{v4kLqOW)jXA_T4JbKp&hgzb;#hI)@U%PuZ&tA65Q5L+DR~m!K5yKiEfL_y$D_=(*_Y77dFweBVW5qD|0z zpV&8qwmqVC-?ESJ(R~cxicjF%_6dD#)c18ORq2c(NxHMSdB2ORxmVP(31NDb*3z;Ce$Bp|emt)I_90 z-P8i`rZ*G`y(5Sy7yh3OU4@znc63L|L2wL&f+1fh9P)>5LX8AZ`iA&`(Lxv}4Zzn{ zsGNtEwS+**OzcI4Q4uJ-_>2lMnnWr_zAxoQ`B7<9B~^ghjed0VrTftxv{OsP(FQ^! zJ*UPYP%D=zr821$*q&4p-IZ$aQk+J^()RxHRPL5D5@C4&A<8ND$+r_;xdZqafS!;j zT`2u>Lb;WoC2;=%6#{G~HWE@LC*hH^!2O+MN=&UxUS1*?D}bjj6TniJN~H$W#id-S zQnstvi8ku?`9*z#!2C)5S?#*AUwu^Du7))ZaGX~p@(y)H4)2rzINowEb5*$!O(jJ& z=6kda`TBfa{+qT}i_m@>)`n0*u0pU7DHwFqI$tqdC~?k;CY@1tqhs7%-JK(h;%U*% zrQ~JNiu&uVD}=c$KxMpUyhb>PBV1ens#sE0AH7)2oQqUyPyt03qm<=i=c%a=Rx)x1m;o zkFnw#;!T(zLv2I=H&?UVkaEc_6ih-6Ra8wGQugwzI(v74F*L>-Mh(`U#JUeTq|Iux z*^W3CTWRJ}^777jbcc`U;Vnas6}OyPM?29*Il%R$8@pATtI0Lx@!Wn~i;*zv#y%wA z(Ad;{n@iiFWscLwclzAcPyK`bUjK+g<#)<6j*U8_8Is}|hJnxh7<%J@(PX@1lrfKt zTH_PLU@S6>#s|hD!)mk`4~+%JE#ntn_grkleE-`k^DX3l!)jn%ny-PqXVtN?=0?_A zN{$RET@CQ$EKX>-n8FlWpuaPbj}IgfiTpM_EWGb`tqW8`3e0S>HO&#@yngF=W$ z?zEZkJRUB!{ks<|M}W8OU_1Q02=4^Vm<|qtZ;;1ugn2MRz!ns>2G|o20+C?TO$RQ9 zf$R(9f#PePg2fluX|6HSR0 zL^^5%;5yiVyHGJy2z?}QesLh&&L27mUGyk=1V_hiN{^%3s9t)29Y2<8kRL`9@|awb zAYdi?2?25;pp@e9>2vvod^Zu5?gqu0x$<6hs=sUMV5g(h zr3!z-2fN>=#ZKhUkq3%q9rJGc4ps#VVYqv7)cg+M7V?lPc& zCDB9Zo(fi}ja?dPtYG4`Kj7Z{V8(UIc4{LzcI?9mhfAG+F^r*xT2z7~-$LMLNJh!o zrS8{WVm|4nY*Vr+-y~pz*aX;M;aEr$QMPz}oISod&K=(#3usrzd0dr<9VqUve(8U0 zJ?SeAkC3yUK)OG<+q-275X1|=s(g5 zX-|xm$QziA%-75|W;OH7_@3!9)-YqnxG`WnHMTI%jc=JvXcL9KM~q&h-RLpaf_?*d z$@Ck2Mh9x%F+)bD@dNY1_zL`brrQ`cHUq0-)*%lX@mUuib8fuouzX?-!n9i~^_Ff{ zt)+wY%F@evXL&N0TS`kWrI(hU=C_tEODF5Kr48I)=C77c%QwqMOP%GtrH|Fl>SB$u zT3Brur<5u!L#%JC&z3UF2&eLEAYe1g@KN1~2}j5aRs(3oQ&u;1D|YQ64#T$mI^1Bh6Detd1Q} zHiyRHa2z`>d54ZT?~#||!HjsfJRa)IjuVH`VF!jgu7mF&9co9CS40bgBa6J0^p0J} z9q~9>E_m0x3{TJEFb<0bA z+OSFM;#EuhR%;)f}ig=>5 zk1N_1>3!?qn|wRSeZFI~W{5&Qn~y2-_*O)xf{0JyHdEtX_%=mR-e^#z9asKf|ZMZrN>kYp~-WFaKeI+WwpMh6}KZJXT&xp4jpvuA@ zk&h8?!(HJ~q9*)>s0+7;`-zv~VWNv@2v>$55z1P_14L)|SEv`g-lKgV@hbc#Tpw-( z-bs87eW`YJC?AcUL{Ft&@UihxPt+mJ08d4IQ8UF0N6(`+>1os+)kn=zC;G&rE~z1!js~N# z=m|AO1TB*QHz>RGENY2fMUByms1>vmd{@*WHA=}S3EBWiL@%T6s6K&TbxI-Dk{a<> zo+#i9!OZfk{8DaAxDrXZHepHxqGl>OU!&HSxRu|@m7w#Wyos{}370*l>g@?n!VT<7 zo|YRDN5FK6(?n73Ox(zGXl(^Ykx(Tx2}i<`$bfSI&Ix4rCmCe;!yzzM31hvmC|{+I zl(&}%+iAVBI*sQ);6(sF+DqSDJ^`~SU#4r*zb=oJW$FB-RavU5O5a}^f&IL^yCjtl zmjR0!G_FaXp zqR+gyxyD>8j?I=_bFK;Hga+3NIfVY(fAJ>wLt|3D&y8!^a_@2tx!`k`F`TgVxt2U$ zMdd%_25`Ez=Rf9~^KIa~2mDU9+tz$s8`WBFf72vN^R4wZhW4ctEyM~lx^wDQjA&Z4 z=z_&ik%bc)!W`V(UEk&I@)U)~i+kMNH^ewE+i~6`jHNa`mQs$-wroWk0wLhe_KW9o z+yiquP91KC$L$q(-9Go3z#}+A9C+~E`HJwsg74PH7v1~DiErWF@DHLV?1cq+q*=;3 z0||d3h<(JFiXE*>+m*P1Uk$0-bF;e4hGKJ{Rzd&B?0_8j6opmFA28$ZvXx#*enI+~A$C<()f2+I2OiE>2!5u10R{d$bsJ*(exMV&%VJZ!!o zjB$h_0VUgDcqr_X`lZptc_MKYDP}i1kCmG^Wa-toMNF{vMAwjdz%t1igq#j#4isV~ zWFG=uL6(zGSnV%cC0Rz6YRdTK{8AYdL@>*_JBqxN%Ka7oGCx}So_r$FaJU#PL~o;a z(Rd=3_$j}D)J|ms3^;k!k&D9yZZ_1LD#-Df*>${fEP>XF$2Epp!x!i|joGJI!}$gZ|m@#?Xj1@97!iCwi;l9q`Ze*YsvX9lg!)65q%E;{jaqpI;0y7nrxkA5co2 zsT+AOv%&=B8H>hI<{0zAIKv!Z_A&dJ)66Q24)A*e^$$T`{qSZ8O9zDJ>Yk)VH z?u<>QGSdh%ZyaVWGbd1!GfrFPm`luZ(`&R?Va_rKnP0*00Thg#%tmmt#w+75- zdCQq%J{h}EM}sk!Qa!}nIfR&he6eI%#a?Y#W|8CJ!@{(%EK`;l)*`EhWV1FcY|El$ zlB&b-sPfj)W71>9AB>TxO@;%v& z`cGsp`HigMHk0?9J5D*birY!P=DsB>;SPi38?ugk;?!}A7`2W3OyW|mhbZC~z5I|P z3O|3xe?$3A6+hw#J34@0I6feMa8x;8@{5kFqn{r{yGK9|zm5Nm-^jmoJUI%ECVmb7 zl@oUAD09B$xAQBUNyksemE)!J3;#9$6F=|BIc^;9`58yrQO%D#UOQ{~*Ny><-OZ0V zzVbiw`}lW`F8(|6-qFb~cfR7^I$HS&M+;gs^XvI_{J6Ukh`w?!Jbf*MyL5(LZxE5RrZUqgVm!49`Yxjd7FZks?7u0$xJr{zayD0eJ zX+d37Q0=)F{B)od@48HDM{t7nklbY6^VL=kN5t_RA0-^vRV$qPl+piL}`i)dPHHdV-b2(JTLZf4~1putT)?N5XCXKL3HJ$xn#%qO9~KdVdC#(kDOs-vW{O zFPLFAu^iqAuMs$W!d&FD#AtXY%p-n;*Kt5hhIhl<@HDYXypM5+Wnv6GPI#Tz4vWLn z;T2GL{0y_gOX!J*-0%!BMbIgHAv_zNLp>iL3Jb#v#C~{%*h1ZS_#rwE?i|4)7{ns6 z8J-F=iLLMkK_ezn&j_!EC&HTqFDwWzhUsWIPXwg2@I8)GHtvZ=D@6ah7c=3PvBp?f z+7N4xolEOt_yjg~g>(0HEROtLEStEI=A_NB%Gj4!8k~r<6>U0Vov{zGnpjMlkX}nK z!LN_4VG4XS7W*2z0G*O{#e&k7*w5&vSU`z4Kj;;bzKTVqkI`+S9Ms2HMXW5AMB6q{ zPtmurH?hyLs#pfE94~DptNx3d1nyyqCwW;il_*yf6V-}J#ciS~{WDRKd`Kh`cZrwD z*U4YEM<1M?|^%I5UB(yxpvPnB(H zJemV=JYJRZAL{&70oa&2cXe}>p?HPF)z!E<1$V9io5h80O7kVxmFv!Z%k|}Osk-`{o7VK?26COCO6hZcNZXko)(+&q z=0D}}Op@=;_vU-@{rL`1gW7NTzWiXmD{sF&xjnsg-{OG3b=^8pCbYjtfCcGN)OGKo zkSHVz^E$+X;&~CDT;1h$?7N*i&fV=@>p}0q`u)f~-dEjQ?``+D)CHt8!Xd3(Un;-g zNd1ZfvK#OfcqhFJ*zeS4`e^!KdS`0JSyf6KIG;*sjVfDA>&*A2H>Oo)E9&2xHks|u z?I42%Z>#~Z{^#=yo&uW7;=+&N{&T{c012)cW~GcPMA{JEICKc zlW({%RPJ{YuVTqX@-3(la)KNtr@_Ilkqz7??gH>3a+I7zIYlm!<0u=s_^FKx<4le6 z8>t}t##xWD%~|Vgbq?~YogJQc&JjMY3eFbrKLVNn%>azXALh3^8=N)H4$yBY-Ulkj zeF0^)utwPHX+qFz_jG&OJoUm(&leB0=&1$o8zSTXdWyOK<4>NCo;u-YPZ#P+sR6a6 z)PolMQj4B(|Ez!Bzls3m5e*|J5#|>BF43Cb3~U*kQU8j61mzj%Ilo1;4*W#)!|xU? z`N#Y-{t5qgzfE*1a*FICugEHzM!f@V8!^`+@JR%{fA7Xz7k@bg5^vVv^#X(&+|9z8 zumaQ`ArGs=1Tbk>NY#{Tm0<}uBG7z_rvbv zbA)oZq5Lo$^LIMC_1-4I_1s<-(uEQ)R^(C7R)st1{rthfeF1JpV{TDyBL0&DTq%p- z)0ywMKG7Yp?|d=QeGKhdmSL{y=-=p_aNSa3V$N-52ON>GU~er1OM-HrCACN(#~Qgxu8{A!2tdv+ z&N2Qc=U3-D;W!)s1}+@-40-Uh;u%Cf;-UFB{S3@b_iy?4iDS%v6eftn@FaF|Ds~S^ z+LIrtU7E-(YkuU$bKi4gxs-M!pD7ffjYmkhd3?A@!wO5OQvXu_8^g;IO4@GZT?Q7j z*U(S@X6U2$8+s`ISCicG+0=tIu(6sQX0NFWcsJmaiOc+A;xNAf?*!m2u|>v`V`Vyv z0_)TQlolyVV^JZ5{Cxlh|DVvwO=x$EY~!|aKX5ll2HDJQ;nK){=Q_#6RZ?DRwf2W@ zXCHjJ*ZJKukL5!RpuRarJyVo&Ciz{?9_KXh3H}d$r*jasr8MrDMeAnajAs&M%d=-s zQzMLdet4!l6P^#kInR4x0N#iN`B{D@lo}R=L>!dcetlR%1gSbK)z1ab6gGq(pk66q z49`$5Q|kFsIvrbyEyotYS%}TX=3?`)rPwM}|26q3`8nCD=ty=YJCk3qDLv`l^tBRC zAa(VHauQE zZ`Ful$S`aeFbvQK4fqCc2&&q6F$&G^GKWq5rXgT`CLwbWC7;Q|ZV8wprU6jDlbWSt znJp%Z(V}2EEC%e3ip9llkQS>&i(Nai*um3VPAoRdacS>ZPRpT1^CyoHklW-Q+H=T# zk|0^6m=xlt@FMan7Zwb_0fJgKV26~DeDVv|f>AzlKOyk{Lj=P9*K^KM=P)*F1TYDh za*jI}`P0q`=NPDY{&(jre}VtQIq&S?&hclRGtMR4&d*AH`G3Ab?IX12>BP=%Q53_o z=J_b3c{V*A!Y**Tg>+AwaM`oyS@$e>z6zH-8y=>oUHC=#N%;BM9$KGEoZcdl|3W0e zF7p6VKq>M4yTD|A!Y}sk`-Of1D7ilhtJnjU6rGDwqDxS5QH-(_b68Huh*D2G-11SX zpl}s&5{`(Jgf&ctE#TXzkO3Q`Y=jxxij~Q_ljSlR=qK10J+>KJi!oyBv5nX-(7)4Q z8e0kr>P_||?@NC~nEeK<4do|AhoUDr0ID6-X!=&Upe`tHltbwO^cn_yPv?~*>3(2% zy^(#Doz9hIai7Y+M!u$bnO#(uXDhQ+*_j-+0`NPnYbKxZ@7n*5m)2evF10s>Y#~>$ z>iBp1&F>~DDI=Hp3jb%thGtQ>duPB)i7`{>TB(l<8-EI?|A#oX?jK*sNd>vWU*-QE zZW~*t_N)9#zXM8fhFxJbr80JmMJZ=6i9Z33B~7Hq(&OnL>6&bHc1b;(^WPdV#X%`@ z@-^5B6DTFQPL29a*n@2~Z(25A>xbxr^h1{0!tz)*ZJXq#9qmeKm_9=PZWyJa+8%Sl zG;aEV$9nk%L~Qn0ybu}hTUo~#U(Y)Flht=pmR+jr;eO+)$Zl>IIBK%Qq45`;3(gJx z=JU$>guOxzRtGQeY{7E>DS@%iU!+Ake@3K*$fa}|=EN#wL)f=cn#AtVG@I1nwxm1R zoHUiVbiO;Rp_DRa7^eiDGKrb{%u=0*%1fAqWo4OIW{7%53GcHQ|0K2s0uFEoA?h~& z82ESY2v<+)$YJgfx0icF9+Fye6txFrAM$67F~gpyXZ8h*01e74kg&!a<=B%jJ8xxIO)Csus|CzGSeiR4(aQ}KgR zbQkQY8!(>yPSK^7cgiWsHHymF^mKZL!ta%(8e9wEBCF~~)6*UBU@acnfd>hll!imlV4Z9VD}R@r$h#bPK&oh`w|6ap)14wd&ne(@ox50)IEy8mirjvW-%Pv~KS2vG#gC$Z|CQM9FBkt5Rfxm>Soi{O1=g-HzW5Ji=zwSa zu#rfFO+-8#4oAbuuz@(oZZygiF*%~$TUnD#8f%crfWLXR;AQO7Dqtl!lUzv7Cufs= zihf0}VlKIuTmpXp3NKTwWA7i8i|Hq2xvDhJFXdW#Dg9HqnqEk+q?ajc{*cA1XZ4yI zKU4M*_&i9PDhhC4Eb8v=?(g~z+?ye6iv~)H zKoy?NG1#n}i8p$dgk_FWy4Eu-tP)qKHquMExxDu|)~=csOiQK})3RyNq(J-MDa^`Y z!_$@|a=c2T@^e;{m9<=1GM1F((sE;o;6v=>4HWoSOBjEHyUq=fUeb-tUghpP7r1^h zOrDcL(nGFs1Ei0f=SIm*ZiHOso}tYOcM-RZy*&E=r~7>P7v)L2PN7o-Ozhlq65vXJ z3!L~?OR3#|apaj1TCqYMzy>(*93qDqddwb!N6eoU9(#F2mR1+i(UnUf-a1Dohe-7}rJt^Z%PaZR7u>OC78SvDRl3!$XyV4pUl7(vqwsJIP2glUtxS z03(V)#d>lR*sx+7`D@C&nCZ>*D+;Sb&Pu;j(bJ4HEzM51z^JNJTQE3IdYdvkT>7Y> z)QX%2!|TX?&VI_aW!ow4dJYdpFu#@DT5dVF0Sa4-d?CM_pU?l$F6Ni=EBOiSly*`Z zf>A~QVaho1uD(!eExdcUJEIJ3!k}cXn^a6SbIpW+ZYf$~tOVD>T z_mWJJNis&#xJ)h^W(8TfaWX-&xZ7L?m(EqgAe2t2Qv&0VIi-BLQ{hyBCj*V>19Ld> z*gYg=79~!>{|;Mnv6a=-HF=heIfwD&x)v6sRu|~yBf6ac$Zb5yUxor*pSg@{$#f$Ft z?&!x!R*I#8cr9Yz<^=r*ef;?)(FT-&=Pss(iLd;^ZyzkbEI*-yOIDf+uJ@KlP(n%p z5TCpy^CX{pMV5N)aJk^`a(T!F+#H!EGvqayC2@=SS+e*8=b=-FIkiqXrIb>iWg+fw zo>PyAp|Vfn4skomU(bF} z11(hp5LT)Dl&Fflj<^Z@y7>|F|Ce82x+JvpRn{T<4E&?))3Y&ip|^1bFS&#ARb)c( zL-AcProdlyD)r005JH{1=~|TlXl zQ^NlxvAa+G>5>hh&$BK(`;$bkAjcWe5b;6b|MdT$<-v;??IzS>Rk_A2`;dx?WUVXw45kp#EeUjEF%Ba!off9BLc4G!laauvYp^f_%# zvr`9L4LEVSoLc^=^N8iH2eGl?JSwHd_g)ioc4FU7u26$Q;ZAqDwz$|cfC8rd!Nwq~lBZ?q!?ZSi0Gdea z)Ab1Xy0kg1PQOt#sFZ0*+LWG#hlT%p$ne*H_(sL`u55pHN8Ow4$@0}hSsrY1I6IK# zs0Xv%S+1I`-p=(=?MA4ao-2ugX9vxWh6$XNW8`=mj)tq*)s*;iuxBRBkCDe8oz2sM z&1&Z<8_!aC^!EI=)b0U3`dD}>{3`qehKr7FjkUimI_UQD)p=mvHNV)!Q4N&AQfp472q+ z4g8=}&kx`tarr+&5&zMJhYOQSdg7iC%ytL3_dWpw{MUa(?Z0e+x%G&f1HIx8fj$^q zDJ6)m$d^cGBuS)*uP_m!)KdB)Kv_Z%`LHY;3!&^ue+X?1(-9Mg z8mr!#XVqHoS+}eQ)*Y+PT4X7>a_&d_A@{w#-LB!jv$xq>>}sx-`@t^bHrtQ5I_@#| zfcw_|#@=dIa;01q0?l9lPgul1yvRBe(1K8Sf!xA(^6h*#|CE0M&4ry&@Xno9e$090 zwDBX(OJ~|i@{>*%-^6$D<4z+#g%&u(s2n@!$$9v~dr!fW@f1A*;T6I_iV6iI;yg;8 z@Bz74NC?vucVC$G>0b5LdYW83O*R0rBU+*FaaG7yHr? zXb%iwPdWoVflq-pa9W>(LwDd~;7ec_b%Wx*K)?7K_!HQvi_#d%7a3wGGAEmgToZGV zBGF65g6T*%%GpRC@+aaaF%ub&q={Q1Pe2sn9{IP(1MwqLATEi?$Q6+#?uda%f20TP zMDYp7B038CG8RG2qAVF3li{xXzhEJPKP15Voz@gviWS9a(vtKh z?MZi%u2{uSjmYF#(vkEe%`iKJtK_=kBuP_jDy&Ic(v);1Hx&M)kE%m>N;}hEVTjgr zyJ}E%mhMu0R@u`%s(zI}{Ym9W_o{+vU)q-LRDDzps7}-0RAl;#Dv<70b*S9wK9viG z3*Vt~JTzygvis`UtUxVPk7Z}FKeB{cgy=GgII^dn%uZ*;>WS<)6;(?8#5s{htPyBn zdjLU>5A)y45gJi$C&$h0=6Jb1jWEZ`uV|OGY{V6Ao|9jtVhU{P_Tn}H7m42{Z*$s9 zVArUrfWtU+E?uVR)a~Du-B;W{-Id>u9N?t<-=RG6FU&NUC~J(=Q#UIQ|IzcyQxXN= z;ze)79upEsmMf)a|W-3Ob$k4*OU8XS;#>#r_H5<{A$0 z-gm?IEzjn|IX>>KRWN756%GQkqZ?<+#@hkDUAij;b1F~N=dn-Lb4cH!upmY z_n7e^wkj*e3bDJ`ZH%orPi`w%idcGB6;0ExaP!PAW~I=uOg*BK=M*_!eqC$Bu8_1R zmXT@UzNNH_OTN%fD`&s6zPFaKE7&J!(QLJG`|NhEl}kd-a#s*CmARfE?++>jtU`h{ zXqTgiC8IF#__JoOu!}GY+N6PLs$_q__yf;cJmL1+9h47?h5$v(1Xt!Wr>v4D6yYj!$WBs%G0XgSU#ahFO^2lwk(> zJbl`*NME4O8RjT+#A7Ja!epE9Qk7X63s*U&gGmD4F|kZelvd^vTAnbuXan^iH!*Q# z`g@37+hMI@SF=AuDXrFz)^FA>U^VQ1YdyQi`pMc(ZAOi^+xn8-Yi+T9wZ3N8u{*6z z>;^X8ZCh)Rf3Y^QU$OgehyB}sixK~o2MUdFPq|L+kloMqaz`j-`?$mQLHl=mm>c9) z!-U4{qjndidN=nBWdIPuk>n|j@mGzmb8NsXR~5FR8t}$d@2W-F;Ckzd@)P{mz?%SZ zw2JZTTs6QW{0qD>TKfm||8I_jZz(fv^6H;A4wp#pD$L|q*htmXd38dA@QwFS*x;>_ z90=>ZMxj=y!I={)jW9GDm`3YGz+_-8Fo$v?uqa*^F9VwatWYktBwh*3i|54ifn~7? zGc5(C0t@0*@fuZI(ssS18avt`p}{z@84My?`=9L6wk{8MABv+A5UV_R2 zQpqXRMLLt7Q!S`wRWmTWY1O1Ek-kh%sM2W|kSc{dnO4FJRqEC3a&{$K5>A~1os(+> z`3>zZOf-A@sz}pS-oLy*)p=lyF6KLLqhwKamG**)a?iQ%DOKWI%gHm^8<+xo)ce8P z;%$=f6+W~%We!+l+;Mvn+tljafKuK_b`?u1wOW|>)7;Ebk2v?8%M8`Mm25{|K?A>2 zfMyY{2i{47G@fbD`j#4df-&F)2_871!x(ItLxCXV;(^ zE%c(xX^?N?h}p}FpqtmltD@vCL|cYqEvv#VL1GPT!!9&>Hpi6uo9x zH!M;g50q+G4Xfz4Mqe^480HPjh86mXVTf`yjBh$)3QZytj#Z}A6kzgAO4ETU#?+W1 z(AU06VN#(^UY zFtdej_9u1^yNmt9I%WOL#+?Q8wy-;aePj2s*Q~RkKd@J=?d(?eJN6i;73-vR#<~ft zkG*XD!k)8kSf{P?)+KOoxLen)ixf73eBAn#{gM5i-NtTa_p`rSH|-r58ByO_j$f6X z{X0nTH!tY+2W;L9wr<_NjGPZ(0#*PF`<#8rF0}vRvh5r8G1*u3!8o{(x)DH4Ovm1`Gml$n4I#CR`8vJN|dq zkn5A{ir?jGM@^A`&+l`6bLIJyu4{geYr!=F?yxJ1v3>$>_#a(gUE{79SNU#-tKT*1 zDu9b)*!9CTSLwVOtvj z*uHSpJMCq8$Gu0eW3D$Q{O(=wCWI%#2`}3_?CtT6q1`ucm)9!X^bUFHpcvj$p-<=* zhJ-6#k8sA@2OcT>;$8D@dwab>;g0tQIHLfYFj@*@-Z=6(@0rjk^b766bK$(V-@EAT z_R_ovkn0fp4;)|x3i}G|Z#KY_zBq(PzQ6~u5v4vL3^2sHfIFZH@WiJ9MIa)y1e5`1 zU`I@c8!`iYv@!%VfwRCtU{CA<#RmU4U<>R8te`>xUVuay0Bi@m5NSUk4sg*%8juG} z0e^rGd>612*cJ-{o`3*23qL#;ih}`rz>I!)g&ZIPOff64CDsPm0X4-F1-w*=R}bh> zO1pT8px?wI{`mzr;0SO6of110vei`1is&P45=lfC>5#}H?GkRp6yZcvsAE(0ipWvq zAVNfhkzLS&$YF$xNFyI5cmV|30QfA~i|j;{kuLDyVUjNrafAYH=SJoLHh%;n!@um1S#%_%d$H(H$@%cC(6i-$k7s@8$E%BlFoA{S_dz>xf$VTGJ z@rC%0IDS7(hj^SnZ@_R&SxpM=ld426QM^jsC(Bb+DX~JT*i)2*_?fIn4WcRX$K;1p zQ|d1HI`fnip|%#h=9B{1+tjb*%T#r$BGr<5pL&zpR}c!h;vw0Zk|`Rf{&iH2&uUWd zGi8}qnRl6&nV;$M3}P%!zkIqO)0DYMud3c=YBF@yn@mN9sk%?UOVwtoGPmgunGLi; zbXOJA)#%flsmuIIZ>iQ*^_i!1OXeCq#x7RNp&I3P-)dGRF6_Gn(9csn}v^M zH?qvEAS=#_vU>F~&Q=(0c0bF>(ojp!Ze`h7es(j<%JQ;@sO5sIQ}1Lo>I1bSCj^B! zt-;kSXUiSuj5%D`a!QRmM*`F5JUM$#qtR+ypbR;MMx{B(nR7>=PIJ!OVa@`ql;nAx z#+uvGGPE?DRhqmczn_=o3F^YB$gA>9Eem{Qo~_;1s-Lf+kWP!AN^E1>j4$%q>)YaO zK`YG{Zt);+o4@^e`*17H-{LRYKHc8j-humgn?qh(yw%>Lgo2B8#hPMOvAS4a#E+$P zxnj0>Tf6~YD0+0)DB-bprTo?X>-#F|z0Tpi?7m5#!~r#c143*U*~@k+c9#%8aqB{! z6pG=QBJn=*lgLWEE%hONVCbdXBF$xukxB_oRh+9xV=H+=Wg?rvBA>kE!bHWt3 zI2ye|Zx+}tTFSjrugJUam3Y&*rv4)rOWSyH5y%A21IYj(#`lh?Sf)TO7pDU%v05An zWCI$pOe_^&2DIXEAR4#|q^QW3k0c@zs(opiA&D=Ni})kG2u@yvn)Aq6q+jBUTt@~Z znaEYd6&aPpzz;^^5f93nNGcMII3k0ROHd<{Eb?TePjZ1W9O;p`BcVt-5&(sJIYQRa z4utJg$r1s6ToUKS*>PrEEu+VWC983zY%8vivEq#Qeq0de#CPKo*>+qWUyHBDiMUjz zh|6Wl_)h#ZvKQyZ#c|%)lvt)z45#{GFTJVG z)Yx-)&?1<8N)4n2Q(seGQX}AYr#`2?q5PieNR6h3Qfh??ZQwYHzLX)0-%Ic@9{(@e zGd$Jj%*RYura$uu5n?>UQ4M9jW`;9;nbFLb%&v;B>dbu4v}HyzEJTK$%(u)yrX#Zh zT%hXC3}%F?UiAB&*eb5-Fsq|H-k3eknt;i(2U%NoEThg^)SGcxR-e^oRat3PlC`2% znN?&>>LXxADz2E-nydwsKNo=CA8XEX2byzWdQB|n&6%?oIUlG)O$2!~7tF%OAk+kMbNXS9_d41g-^C6kZj|3wUpa?__sB@f!Ez!T0;Ed)htyK1yR+@fy)?r923-!*Z(%%DWhC zguRWLQsTK9;R$N5%6kLb)`?Yd4GtD9pp`ui0_h zPk?#tq}^_>-GPJvd?aFT*zwq1c89%gr+&x%JUgB^cKPtP54&nt^R5;cf{p9lt_Iky z>;106C2`4IBA1-1Y1$=F?z@D@l@v$n5}@33z1>w&bg6$qXu_IG>DX)V9(Z+L4QRdB z=siMt=*R-^2ARaJoaWS$rMPdiCNXaWPN`9E%O& z+rR;8jAEScrJjO6FGQv!rAaEz%g=FCMrI^s=f%ifiBW|0O~Zw^)g*t1CKERbTUKyPlg2L~15=sF;8u|Hz0`vzdMB5ZqHuW(d_3W!}@7 zIh11Xo!OG?Zshi?gTha;uIy=cCPPw`NpqRI%3bG@xl}Hb%jV1)qsE{~=Mp)6eg{XC zfjXRO3O}`Vg-305p|(JWnY}A+>3$U-i_ixEq58h&zV5yjC(0ZB1x)5UTjwgmq#goR zI7$xYk7tbMwz>a=dYmUm*?iVHEt>Ci;4q~1EoYY zpIOW-P%E@i4u~@^cZ1Q5c^+iNZfKi}?~5IH&v-&$^Zw~yY|y#ZG4_$`fU=rH*NNBR ztqj^R;bWjYSQe}Z+Qd(RUxAlFyaG6{!qnC0_PC7-ZDf2owUk-TkeKQ=XUg+2MSbBz zkpTrf73=Rev7jI93HFY)G&RpU4&P|rfpP$EciMK|?6mLr>@A?)@3iiG*l7ZWPh+v{ z_Fbdv3#Eq6-H#|c0D4NoHed$VXR7Yl^@%E9?%`$zfY*6n?cEE1L9yrJnxMz~1Pm8_ zuismV`XE*n21L9ruhV<(t=J2B1E9 z6FDgkiT&arFqimDY!{!1-vk?iuY$Efj4pl~jELP-k1Ehj!Mb2$us-M$zYd;KTxjTg zPO>OLG=MHQB@O4xz%8;SP#coEa~h~pnn&psFCkx$tVq@*vyv^zI;d4iEn5CgPB;$v z9E;p2opFyW9QVczvPj$)cgXzMr4v~wZk7e&jyS$Mm9nFi6>thTLG5YWD09W#aZlVO zJBtV7=iqr|q+&C*oua2!QmoV}oNEhUQrH!2l#msM=2o02xG6@;s#r^T6zi#tlvi=8 zuwhiQVkdQm77hg`Wm7m6F5nu~MuweXW>_#xrD_xTc1Eh&%4k*V8G44Bp`{p^wTw)) znvtt^G71$ZqgJh;l?v`j%baDC*=RPN^=9p`Gf&p3cA!jTLs@_JJd5201hN;|7|IiM zI-AOdvzOTjsQa8nQ+`vDxvAjP1hd5)skzJjqMYqSbtT7ynMTFyzfUj3SitH-Q#-- zS~#ix&uMTZ6U^W2dKY|i9*rMBF*;Qy`x1+LdACLP+duAf?KTJB2hU`&xKGB*xSqX# z=73H&m;(0FRNZhEi_3~}qF%W1UJM4=68sQs4Zo}5abFzAcuWZcMjDUrrg$lSDxeT$ z_OOw;>~%Jqt%9`7dj@?HVPJ~=dFRVc*dDTz7;j*=Z};17|8DPY4`jsEb1w-A)8hKQ zw|ke~_j~X5KJ2Bu7v845y1jyqZ6l)CjcG6QvYVS2us42 zY(tj!z&`+z@k}e<|V*k2xZg)UI zCjdL8_>8xWice{8D^+5Hye+`K2D^iu!LDF$@Jp~S_$}BI+>x|k*?4|~5_0h@7Kk^l zva9$tuuCjef`v&_CTwy2P2)}7O#?orX{N*;yJyj7*-?Ak9>a#8x<;@mPRu^M>qhQz zxhP3~dOP=Sy!Y5BsD1CtUe4RT_y1CNA7D{k`~UCv$P7tLPGY)=2_YsVrfL#Xj3xnl z7klr$WADb8W^z(Y?}=c;f}$vbNH2CpQ9&Jb)KN!4U>s%`Z27;xn=c;D@BHs`?(^Jx zpL_54yyi2r_L@Cwuf2Ae&49k+;~f2IjhoW)<7LOM9xpxaKi)5XV7&KuAIh&JjB>aW zCORfK{H&~sgb0TxVZ5U}VX|YigZVqk5=J`4I3_u~2~!+=FKstnb-sp=svDB}ItM#@ zJBP4Hy`24>L!E=11DykS*3;R~T+BY)yOWEPuU!apHFJf!{1>iXXyIz=x_+UhtKvd) zS4pxr*^}(KP?lVpTz0{C!F%Dxg`0H66}sXwXfV%m3ePb9lMBzLo=?r7gHj96@tj>) zVOC*E;r7C`!t6pPC8txHE`Dij#`BGSZVlw-&c>pUk*cdX*7!G$YI% z>Mk#B=DuEfBBP?TsoP(AEW@60qx5*jO{O<@cVW9Ync0c^u3!h8+1cY@ES*3&C8sjG zd5)Q5%ba&sN)~f1OU}wKvu75RC1o|sZjs%?*F3vBD{pXlO!lDib=d>T`$<=H?$a$H(}%lldp| z?fDbp9Qmis683=hFnbGoOM81eJ0N>o?wi`LGgjL0i0>2Io7-F2ZyX;IA8NmOd~p0w zM$C5e&$YYc;#j;W4Wj@gdu2{#kwI{1>ga|Ek>m~*%@E@^Yp#-vS29b6q< zZCva^T>j)6$>qs6lPi+j@tjfaYV8V5xn?fZ)#U4BE6R5jy37^4r|?qh{=(gbI}7&} zUQFG~LSHb;^U{x`r?XNIrKc4iOh267(%s74+U=k_+PE188D}zkd3t+#dU|;Jcur@Y zC_7$eFFRRwtn5@-FIGoyUr%4l>|y2Wvxk?r_P6qLP4WO8*l>OHFqVxok3_lWSdt|7 zMZ9C7`L6QpZ06joR@t%9!(zjz)tAoaw`4d|U$I-JZeTyLDLO8CBguILWqbFsd*55a zB?dNx)qD2t+grN&z~0=w2f3nNDzE(95}&&%cWz8v?$Vg~F>_dT%P=n{iu=fz&AFUv z@JMcBVhi)!c_U*dutG=27Uz}bjf=gMcR6oV?C{v4ys@z*dE;Y8m@8XqpUpp?9}&l^ z2*OWg$M3b^=bg&PP z@5I_489$mH>1ZDjKZYD-_6}<(ajBzI;(P}iLShSgA(BU|TOLI@nk6@*$oXkFv9dE9O?z<+^EnRkX-PL&)haqst+r4u4+TGE+w?uEH&Z^ys(QC{#m|(s_ zY8>91zqf34-rgg75AD6O+RGaBm}^m{CFE|)O=Q)qWYt6?iO0#gsoXD*N#UL|q!_-r zb%f5`SED$8Ywnf2Yk3uU{9pV})axW2K`r9lwf_Xh)aC^rW<;3C>B*(a!PCjHGeSG0q6*Sm!9`L^jsm zuGT4S-921AUEN)s?X6P!xVpJornE`v=EYjO*zp$u^a8}inWdyTFvX7)0{a;nGBKaq^zW=&dE;xKF3kIwccRY z0M|fQhm=9CzOH_*whWwhDg9mT$>X%uUU;%)qgk;tSoxK=W{0BVuG1ka<5tBrEm#wGGe5MTJb!guvjUl3!IZ1{{`?gThOmNb z`8Txd#81rWwmP>sxRUS4bnJ1&IR?u@IeI4cP8^=N zfpRX@B=$=jk=U2=%Gy{DNA;wbD!-Pn7GNY(UHRA%3G3SE00qh8QgD&+-5R9wCQ;!Cg=X7EzWt)rOqz=IqdIGN=I1wq;yYN=8ANUbcHjh@+%lA zDLr^3x8bgCDU)17UBg@*QVHg{6hf zi>`4P3M=v#HY>VV=wp=M;Q49tRAJL14qHVx3ojQI6`m;!O=JI2c%|@0VY9RrOmU^R zNV}POo|+|vCkq{g-qfaPS5q$(mKVAU!_rO^o=vYPyk2-+4s?ah(<<~}=TG$(UMuwR z%vpGq*YXL4t!bNsMma5)3J-Gp%`ZNeej)ut@#*xU;AdQM%Ji-Z1@0@i`u!Dn46yzBrFZ z7kNb?c_w|I*5ONh?%wW;?DM<1hr0W^?UWC9cV|0xWejv*%D9qInlaez&ge-=FL!_U z5OQyEVa6EuNcULx0CykvDEAmoKT3<4$K{Ou#U&ZT+#}pY8Kd1@Ded8AS96Ai9Wcei z`IM(Ha}vqPoTrE*%s3v8^0+f6dxm(1doE^9<@tC|gr_94Eb~g{XwNX7U(PJf9OSt~ zZC7S#=0uN&M`JzHJYG_6BdIfiGl*Z$@-A&XWlg=_vg>6dJXgyumW6sVvo4q2EGuKr z!?n&Vxo__E@$6dJjj{`6VcsicN4fc)jb;=&)V-Ln&Y?yD1uVZ#w9<|FJn9|mND*Loq zgB^f>kH2}&E~a#?=u*+GVqi}9iUB!2DkfJ6F4v{NeD_nh3qS-W8x%%nm z*rBLhk%ytxrl@UE%e0n79gA8QwJ$0$2cet$E5)Al;^HgmrNt%brRnbUR%~y43eA|{ z9_JqK_GI`n${1d9o8g)1@v-V#cw2c}db6^^v&Z|!`NsPAj%gu_`SMkkX*IvL-)q;! z6+L$K-qmwge9kV+vI)(p`JF19R)h^h3eD96b$MzoG%f-Rf z*O*7>8vEXxd_yZsroWMsyDnyZOl-_{uAjujWaYBg&CTFmZp+O6i;Qh?C@OY&Y)cML z^JC}6&Wl~j=Z=pq^XjaCn7B3to8wy3#qA0<#I-G06Td!gW8Av9xVTMmv2?lIS{1B} zpT}`!DL4nTuZ@q6Ull*sKHnZ`UlzZDRj@jKxw#_p90wc+9b*#5vN{eqMkf}~>Bo|e za-U@GmbW?A(D|#uT+>>obt-C;#_0pyTn2A(8GC_=?sDCJyy;mAVG2al&!TF^$(wPdx6hJ2*3NW;;(Nr8?7{ zJDi!$?anM`hBL=`if-V?BXq zap-dEl2(*7&up66BC}a$w0o6%wY#NmGpjwJSfzYq-0M8c(m0b+T%*io zxK0b!(6OyDV?0f>)_T@?)_A7*x_GDxJ-Fe0#&(1p1=&pH*k%>{1?Ppx?bDpD7=aK77 zb-9v8)3gg_r}Gosv~<_llrbq8u54GPE6X*GX@k=SrpcTJr1htR2bqui6}6)i2Nd;B z8(7q_q+JDxu()Z z5h*#Y@#I8sHk3A^XjsuuS~D7>ibirjq-aRmU~+iTur#UDN4l@1Z%O}>ekHw229^vd z8B{X3B$Q42W_quZp(Szdcz1$(i*%NIvpbgD=E}qSv7FqJBW!5H7q9@g} z#gjs}CSfbr3==%@Jlcjq-T~fSS^d33y@Tn>-C6y-eaODvy;%djd$NXjXZq&*WInTe zeX}EdeX{5I=K6YP&++xjo=y3@^2qY}Z1!`?ld@-)&n;idwmH*TMPp>wQZY7XQ^n?r%!-VP**SY<>$u5E%LrIy9#t}BPbvbSZs zvM**I@(jsjIi7fw(@t-<`#`fn^QEKY4gqLQfExbc(c#OaX+@74*y%aq*-P&B9P;e(w8?6n z#ph$s4$lF~%(?TC;?ED6$KB(+6V3G|r9GJQRw*sAjQ39QPV$cRPG{m6?9ZC4)h2lN zWlb|5Pt_9k=DyYD*28v6#`t1=gUpq`&bOZDt9)yH19dQ@W^XEAUmnLQiZ9>D{W_#) zZz$hfo|e6~Ji;5xbLPPPYOEmS4r>W!W#%IV?x88o) z!6|-XA@^L>HSaluIL|uWNhL{6XK9j)VN&Qi=PGhJUFUgx!F9<9s$?mpk>(VschG&voo|k! z1Kjt{JnGJMALG#xcY)jPKI}f>&U5c~_hFkk?(Un}fiLFWTts6_Ys@Thdt9DQSx!$l z!-Y-GbHQ`M(=qFk=bYy}1E;`q%2P}h;w(x$Cp||!MLat0x#)3tNbQ0)1EVw z$!#7ZWDcUR&b!<@*E`d@(mUU~)H~a|+B?G=>0RNC_O9{HV)}Y-tap_+#=DHi>Aoz+ z&0xk%rf-KY$2TN9*%#;A=o^-u>Pz!&^KD{kqHirVH~WTWC-H16;(Zz1Z}BCSXZyDM zQhW)%ZRIKD3FR5gC%ZheJTp6^JiUBt`IhqJ@|^O-@>E9HX#WKNF#kw@arRh7&18QX zWyAdw{Zss7{6qcYDI4dX?-Bc@x{fvoN2yUn_Mf{eSu zS>Ufkr>O|DZs8dmnsMAqrqRvJ+qs~R0kGc@$isG|5IBfEc7o#pk6-E_BU5+Y_ zDv2tMaz|Z>@=fR)OV@7Qd-UwpyU*YuLx&9? zF>=)CF=NM#pD;0E(&Q;qr%j(RbJpwzue|zN!`I(<^Q}fN)UTYMVbtM4)iUP(F3UJp z-*X)A#NG;8l^c= zUte37D}wnf_>-FdSC{L>%2pW0V?3x@E{Dvy<|KX31X)vNiAA#wKq&K zOJus#lSbv5CDW?aaY;!XnJ%}loRtHrDr2QlizBNy>h{Hzje1LSy3XuT8nr`e)_jc_ zRW-_CmdvR3hJLd|rb|7ur=sLlGpp5!mXbO$U2g01DjQXmxn@sEm0LZvLmT7QoTW3X zBR#cLX5Ww*RW)jfSu(rY8zz_~GF|GKJ!O{6saD4&C3R%F+&1m4Y*ba2nmx6wdZQM7 zQ`u7qnsaq#k4aBS&6=+>qpC(Z%#wN4-q3HB$aJY^_SABD)%6r&h@9-(W^njap)sEU5N|31*2*mwIMTnI#`otK*WA zIx<~ukET~Pswx{uqZY5M-l*HZ(=nyFP-hk-JtZ}3zR8TL8s#ucKCJeJezQcTOFgrv zqUBW|RjU&%C3R%F+%~1?>eCE2drGR@>Zu*t7{BJnIvhJb!58Sw(0J?DkIFET3x+Si@w(}rMXCF7A!p_HET9vMpcb+ zm?fW8dqcljBGaXw*;8xeRi9U@6D=imWV(4vsO%|2bFtY|Qsq`pwf;fJl;%HmW=~2_ zt(Doo&77(lwZts>qS_lKm?bh@>X|)dmV8;Qj>{}*Tx~uJVr0%=Rjc!}St9e1dNQ9_ zv*hb)b#_Qe9hok-Mi(m=t}1h7;Yy{-t%V!)W97pAthrcc_7n>jy-u3Ygc(&WT$)+( zO|>^HFiT{*)RRV)nkC;>tFvgmG)kt+t&8qjs$xsAz3Wf#xqdvuC8Iq-M?b%&4kS3*w~Y*J^M0vsoh3rJmVSX31~W>g)*fEiUaYC*h|EUET} zKbs{oUFw-VWtK!%tFuE&>d17ttv*oMsHz-f_LNk))hL%XruJ`@jf>KmJtsZ2MVjym zGpcG-npv{6+8Y*_B{E&=nLTBeEUQ*$QGzr|rpwKfQQ4@fj4*pjs@!T+v^J(dbGgp! zdFd&sS+fl@s%q4NL@8NO?G1l6OJus#GkeM`Sy`>l4k@W4)8%$Dsj^X3x!CL}sdB4P zqkh*hr5UX=dqH|?t29BTS2ZflELm0U4GYW?nJ)Fro-#{TSF5uqNg7r8K5V6~%0^XX ztl3jia3O-j~Qd&8g25^0pwGkeM`iK$j+hm_Qj z>2jN}q4Ko4Ds#=Ak}9_v<vU!>Nlzt96WTGOTRml#tgrTl1!jp%mwIMT znI*B+>MTl;M#*%!{c}uZqpH$j_LNk))u?D~Oo8SGo!QIMQ&O{L2WC{&s0FD~va#A5 z{%n@Wbg5_dlvxs2tZ{69v!|rWtwxRdtFniF*4(5st52h1)2R7b z;1a`XDX0-0?=GL>q%F11!TVvn(;jJj)zQtYNbpuhG=9$#~b&*Rs7vf-%@K z&@$XI+j64De9K%*H%q#aVbri>8I3G~mhHw}mYqgz%WmUQ%U)xjakr(GrJ1FbCC@ly zgjSja|lWV~-*2 z-_Mi-#z8~cA8fY&G0Rcom~q^&8{;hfXurdd_H(h&xYKe6?ROa$jY~$MQDjK_vZbp3A2R#@dHTPFrM=}1%OT^iA^l%qOs4;( z{i7^nXurkm|Fg9JoN?Z$Z>j44ht2+ff&Oo4>0o)&Qf7D!>3_d5h5ncJkG708+i$Vf zum)JIR+}}@dYkoj>mAmb);q0tS!0a5t@l`KS?{&pXT9J0fb~J^L)M3_wXKg>AGOx8 zK4yK~8f1OK8f<;iTG#rN^=WH}^%?84)_T_Gtj}9tu)b)0$@;RjzO{k%73-_k*Q^b# zuUp@+zG;2S+Q|C0wXwB{^&RWG*7vNT)-Y>RYcp$eYYS^jYb$GOYa44@YddRuYX@sb zYbWbNPj@pP`gxW->@t(Y6m|Oywq45ygqn^A)DkXV|KtAW33@W`oZ8>V}l_>`lEo4 z13n4ZVk`>yEa3BiB;$*KWaF!VuLBkbd=v0(z;^-P2mBE5W57=VKL`90@N2+t0lx?Q z5%6cgUja)3A_KT=8L%v1dBBQ*l>yNKs{&RBtO-~f5EHO2V0}Prz=nX00dWDF0yYQ4 z2W$yQ2uKXr8juvQEg(4{B_K5*Eg(H0BOo&%D+BH;dT2;FS*#%YY8mcy}|J*e^VX4|R zRBc*Sy9U`s{Z0F=7TFa%Z>h%yywYgQ#yp4}!#s8kW7zy<*C4xs7c9@Qfo?IHu(1wi z$1vaWVDQ-gx@*{P?pK;LBQZ)|Fv-B^sdkf^ylFcFIK6BSL z%kmIC@&jA6$(AqlQH;>W5QrZ7gEKNDYjpfiXmp*(Xc!^OXC?IGl2ZlQ>HG@_f3xZY|3xnf`Xn13bs6H2@MJhiZ^-$eGt?$=)<5vL7t$Gf<6u!9Q5DD&(wb#KVyOl zjH>Z-!kGSlV*E_|xA8MJ$Zu4QpBu&ubNp0}|Fyx(IjFDXz`e@&-;MuymdgI0Z%H&{ z{CBZ*wam2q_wk>5>(KZ=$A9JcsXR3PACLdiTZhK~IsRq*RE~ce>vU~!P;gcIYu8v~ z$f?O}^VDPmryEUK*N+Fweq=st_>me_?XNnt%c)7ACCB*B?N?4sDi7^)YSPCNaqG}t z+wy3Qs_i#`@pGHyyz!sgubi4x9@^#9q_1VttwZ}GmO3^5HsrAQXmD3+Q1COs!NE@k zuMKVxe22ABa7_-5cXDX#VwL^;W5JIH*A2cu_yP76DnBe#E&mEWJ}d~y;~08~4-a0BubbJUoisl<9OZ+{3C@BxaW=QXcsMwPbD))+ z|0HlcjAk#E$eGv1gWca_o6Jo#>Eo_aUu6uiZMoP2k>b^84VC+Y1u?S7LJ@D7}Ux8fxHWpfYojCtz+ zG#>#%{^R7o{;kvhhxm~2BB%Wi^8w%`J_0<;hk*aPmcN^|TZo+c|7-cbu~uJxt959I ze02HO@-Mdje_{ETuowH(_L=QDqaLGmjqyP6%SM0Oi^faF=eB2p``P;12H0M)4Ys{% z8)AFSHq_S8Hq7?AZMf|X+X&m6wvo2CY@=+AY@=;&+s4=$+s4|O*v8r3v5mLAYnxzu z&oU+h*F@*k;+<+Gg9@+2+{V z+veIj*yh+ZNb5+di;$u`RT9wS8#oX8Xw2-S)AqhwT$vAI`&YRdu|w0ZS#M)yc`waHnhBaN&DwF5^;&Dr z)Ql$iPwIG!W^!#sZqKc#@oyRYYA^HogWSuM%BhBNms!f^_ec3m!|kU|{2<#UvwG@z zo=P?Sd}#bbrgPglqVmQ418VTDPN~|0;_6lJGb{4F6rF3=VN~5ARqM9;A64(ys>`%$ z_i%nrZO*i**1Sz?RJEh`rpotkA~TIX$4tA(Plj0+MpadLEVuWDS5|GesB-BVXfMd6 z`Rer_Fl%#BQ5WrwKKxARyeyeqv8!HF`cG~nv}Soz`YS=I)|KmM)vN02HzKrZ#C!Ct zInxgRqvpdhM{a|4$(H|Vp=U2J(>vs6O_ehZiqz28Z)<9MnCHatIt}?w#2s17HivR+hp6yzk-^# z*Ltkh)>=gmOn&h92ai42@8Q{x-xu_9P-sv@(88eKgH{Bs4cZ!1>!~lE+WJ)MkdK~u zT1Jgw(A^X9p_Ppr->?YDNLBK~R=I*LKMBspc2$dY{3zOCAR^Qe(vDMb;sRW_gv+>> z6)zf~Emj~Fh4A2pdgyk;cm#Fu6hiPUp2JJ%jlTE^e_5p=gQLXp0W$ zjvg3-q4+>;BSospA;li-#TlH1?3*lTj3x*}b97Kc$f5W^?IOiN9KsRx%H8}31`Y8x zTA?F0s7>TH?7%+MzK8LI*VUV(Xrv~Q^RWOQ;S+p{FYyz8!8YWmmufMF@haX#BfO1w z@Gg3xHwIu3CSfWTs*lM}@TK~L6#d!D4#a)zX&%6aJUokfcvUqb8{=WV8&(_g9Wl{E^&$sgkQzdY;TVT0n2YyS zESZc{oPYy`kne2;prLw$d>c(vQ&Nn@6fD38h{AG2V-?mQ2IrNFyok%HgmmLYzAyC} z-oTs4#X%f`183mEWmQHBKPr&+INKp|gW1pFv^qzYqU1&12k*aB$wB^&=Nqu!!Y}w0 z6IWE4O3uTd_zR_QqegV4KvLYPLda+EqRJw(;eZ=|t7lg6erScxSb&9yQ}JXXwjmkk z)N`v1<7K>pSMfUDKr_{z6mwN9DK=sg3$@E!6;0#32D&RVtZ=3}j;CgBD{mwjmj*NP`_G@Y+MHFTA7P zBSW!9#gHNvo3TYb{;>iCERR}@ zns^Owp)uY?E7h6of!^qg&+#LE#xEFDr_vB|7)GcDk6G9UF;BdM_tdxKN~}gKHX;t2 z5sz0M=XH2nH6h=@duV}HYBBi@eo#M=!V_dM%3wUf_`n-@8=ZmU*Gm#7bY2-@>W>*k&>Qgt4F3q5)cBxt%)vr@jDKP^V$k#; z;|<0!=8wi0hiU2~Qv8O$5Q+6L9PAHpJ8Gj2p2Sml8qeT)e61RsX8u@rrcx1Ef+8o0 z;&UXjPun-?21!>rh z9oUUM$X5Y1nIGOoC_YpvWEys=-Q*tBxRd&LSA~+I65sK9n(u1ct*LeXA@j6bca#Fn9fa5Zr;(X(2JgXLvA7B$Q(Pb6q zt@u!FA~$0zl8}Nl)L%{C;59Tv2Q`Nj^OXFxbWsfXvu5&#vBcRmeBQ))T);(KLXk2! z9*Y`kAt_?95nGUe7w@gqf^3O}DvsQYRHR{_dXZ!8%Xk&9;dSL8&!7g!&H%iN_Yj8W zXoc2jhYskehLA&%fUU?-*`(NxUD$)Y*sorHfa4rO5r!5jmfVO$l|-f>U9IQXy8#JE zLW*j@@%2?SMiacN){jJH$+j;pWZO}vG7R46H$ssm&m z>^KFdYV;__a`Z$m{G>t4OgyZ6d|z92>vFclaJZDlf-M9|AZY ziiUU{@8Ug#spkhXZqRw6#rPDZaAWuZj`jJSi(4>*q!jHtp+{tsCM+ru-pPh*FD8UH!l@oCu zB?#v;a&P3~D1zC4K8H~Db#1U1zrevh?ILRN`SB67WFOWExj2diEYoLLj9(DWzN9x| zk%&Vf-ry(kTmj|v>?@9fpL!T~AQwkbiVB3Urans7@Eo=N=KZn6%KAhD&gB~+ z6m2kqZFwR}QGqw^WqlzRM^VbQS%Gl2gWkx+QG_#|dm{}yk&Clvz<6#12jlo6!Woaf zQOX#rKsaNlH^Lb=y|DzV;J`(MGfsM=0b`^Q264_b8fn;xaL%22BVxS8n1#|k%oqFe z`CNj~(<~QCIVY(=Dd!{=aC1&_72%v~^hW75%2CWU%~A|{l4Air#vu21fdo_7a)w!R-&ysKpqBPYBMIFjIr&*MpjuI64f>`1!Z@zo-moQHv^@(f|-oH z`RK)%8-NJR#Pf``*D#uEA9GR47^}cB#*~N%t~8aLg$4Kw;VjcYe5M9HZ5Y4d68^^Y zXAR>!+<39lw|p=62Ly8=`Z=^lCv?U@EWl^jfK)VKOumlW=#$ql4KwjM{)y8yEXFki z(>G6{*Xb|(~WV7F?|Jn7{lX`##lXs zzGK<1V!;IViAX!hei;sUFes0qT4xy*S#>f;?4Za%AnRcKm5 z3i;h2^Y?>-4WlONtAV62cZ`hJdOQ}-DSpOk{C$e)4$@B=_ZT<+WxL(ui6yGTJ7o9IgO)Z#u;unRG<%P<68YT_`(cTo9t zJ|!Q)M6jw$3N|g%Go+}eo+rhN>Sa~d(@F8Z`h*nnGCdFE{juf$KBPlkicv2*&t)$qdQb>`8bnx5jrfgDd zS360uTkR!9t~yAHL+S`A3e+)D*wsl=IMf+ZIMsPlxYQ+56sclTl&UMFC{sRC_|;WX zTvs2QA1ft5vXn_MNM@VDehLaNO7NffD{j@+N5|?Jw}Qk6-SkHe}UQ#UKT-S@w_$(wAV=I!83L~ge4N_QDASrHFHA!)ox|TOaqQSXu> zR5c|qrr+Hj-kKiYG;a+DeLTDuonjDuWbRDu)z1)Gku&QTs@ds}7RlkUBz&0(FcO zc6E{z4t0hUPIaCXE_I0%MXHz-rRoYP%9M{3esz@;*VRo@-2McgR8Sj_qaNzxExd=; z=z!j;FDd$~futCPiAX>ac3?LOa2zfa!H;XG@nogjNO33rfm*l^52{DV$MLj!h7|SG z^W;ltfYaaD7B0fD^xToR;#t7Sf^r1u~BUzMZ8KN#a6YA z6e%i=6d5Xu6gg@KDR!wnq}Zo&NpVmeBE=C^K#F6^PKuMtL5ee~kQA5I6;g!CwInoE z%}LQxwI)Sd)t(d`RX8cSsBWa_p?Z;`kLpK?0csE_hNxkr7@Qz!SRBw>tE%i1j zny7b45vrP!qPc2Giq@(vDcY-!qzG4CNYPF8AVn|LhZOzP08$K6Lr5`9jUdG+HHH-9 z)C5w@QgcW#5A(4=EhNQ9>Jw7@Q+-K_#p+v9{HT5=#jomjQv9iwkRnPgBgG08O^Vf6 zhgfVvyhyO3P^EG*-7D5PyWp~fn4-@ z7O}`fgpKdlU@kt#7x)(6;|DCbi)+6K{|DC-v7|OX8$&1;Xa-^l5?~y%7>}SKI$#t& z!0+l$@-IZG<>U&i!dk4uX5```tX%N0;WpI7Kkxt^!ee*~jnEkHA{5QhQne++F%BPN z2@-J#mvQ?Metv}}=#B_{hG?YW46foaF19p84@|&fL}QmSE;1hsrfX+ovpPlkAeShm z+bwjF2vBsbA#PK5km627SMxjRoHM9P*0NLDHTGB zXVr70ctO2Hiu&pmQoN>KC&in13va6?q90Nnzodo8UJeOg2*7 zrtToco$4Q?xJTVfiu=`rq`Yf_jM*_0=n+cnyuv zM7>9bqN!>{iZ-epDLSZ5oJMzbz+K|L5ew;hsA0wDZf0Qivu`}d>mEBNpV7* zBE@NSmK5jI1yWp8g`~KwN=Og9%1?@GxQ+%~3mS;QYA7j&tC6G_t;UjKyqZXgNoooy zrl}dEn5E{BVxD@R6d$O6lHyDCH7UMP-;v@6^%E(6QNNMm5A_!*BGpn-ELST@u}ZBW zMT}Zc3i)$2B2H~4#TJ!FiX@dxid2s!61nqNb5zhMGl+ zIcgp$-d7)x;zRW@DLz%7k>a1~OHzETz9GeT>Id=<{G}pEu~aQ5#Y(k`6l+urDb}kE zq=-|SNwGyGk|IeZlOk26lOj`PlVZEtNs8TSFDdq`1Ek1Phe?sIj*{ZIIzft4>NF|N zs&k~cpe~Z4P+cZPiE@*|qr9XjR~4kVrf!hpZ`}3-*Z1%sg7GXG;7x?01;Wu2gD?^i zn1==U6pQf_mS81fu?g|mf)tfOW+4aLk&8SWK|UO~fGa4259O%&WTm^wdvL$1Pl|@B z5hU24b)pPL9ARHHH-9)Fe_&!BkAg9DJZYB*n+-Q&N1U{z-~2 z)z_r>Mtw($AJk8z_(lCjia*p}q=-~YNwHk5B*iMVh7>VsJt;P*I8tm@TS$?pl1P!P zQc01nGD(rGwv%F~+D(eRYCkCss60{}R{5kjs*aQ5ggQlv)9NhgM3E{cg-01LalF8@ z>LpTyaji`>Q!Pl*O0^+HJJo>{om6L1bXDC+(Npy%MPJpQ6a&>@QVdnYNikB5CdF7a zo)jOb4@vQ{`jix(seh8V+?3yBc*EGeE-FOcFTRiAtX zuc_Bb@uq4-ipJ_4QoN_aNYPBSAVn+Hh7|2o2U2uWok`JEbtgqn)teN3Rew?pRD($| zR1GJ^NHv-iW7T+4OjMJ|nV7BSlHz^!0VzIIACux!^#v)uQs0o`JN$s3)Gws?P5nWN zzf>eCma65XSgBT#V!hf-iY+RU6iF(X6sanm6q#xVDR!y7q}ZwrkB&G*bPXae7>L=y7wC>J_jLq~K&4~)b@{DycWB1t8anaIX|TtdKMz8jA> z(FJ4i3I4)Xct5q|H*tA`mwDI#Ap@qH}&u*{=$OW*lzGCVzCih(UEOQOjOx-Glp>V z@k*g%8CM7$&+mF*EXLtGF0B3q2TtRxxTv9l28WqZRC)*3|K`q>mdUzfU z@G4%z>u7{`R6nvm24XNKsSio&>w>^7z@2Jm3ME^i4aQ*+z5u@_U_6iaR5;lkeb66+)o^kI zCLjXS@BzM3#=ZOu{XX^;=zwtaKrhvY?2kcMgwOFM79$oLu^9LI@CriF8G|qm z6A*y~h=W}Pb9`)y=9q~E_z0gO8mm<->4m}X@B|?o))`M;_jLNL0) zR)=wc7HE$Tu>|X|9$Rq^2FK>7&;gy$2QzRHMJR>`UiffTz5XQoBs6&Gf3bHL;87&~ z-uHVZt~e~7KyXQLhv4qEcyM=HJhk4F1hgn1n-kj`!&FiSG@1-~(E4E!Gj8F$-bX zg}pe0qd0{#xQHvb20nGe3qDAT^vI8bD1;)Yh$?7+P`uOBPV5H45COx9u{V$f!6=5Z zsDkbY#Vmwj9}eRbs&J1s3kLUM=@5jb2*)cJuH4gbJsFIe2tiAzGnNb7O`c41ArJDR zps5Jcng~G;gkm-#@e;q_H56Qt0Dj1aVAMesjPP!W|)p2}KZ$Pz=Ke(J%7= z5~fh5%do|yz?~!rMk%QCU?xPtH8J<xI8sxYmFnxNd7vXq}h`ZEHA>tnUgXgAj?wM~O61Q;|_wW;*;yHf7CsX84jDv#*c#Nm` z8PD+v>QuNN>PYAW7o>zgQX#;Uj;UlocH~4J^htH*PMX zqG7S!NWR5x_+jNqyRin5kL|{DG*AWDTb93LYB(9?;yLl#11T$9Vv*y=xgfF zRJcs}Y%NpKC5pT;{YrhBxVrME6eawkRbwi>(HEmI2H*Hc3uamZ6wa8=F_m8smC7*uQq%5_zNQ&W*W(&)VRM>jdzi{wM4@BaXyNI&-@_r? z!*fKz$iTHLrr{#4;XOVfDkDD!9Ly3ZjS9%X^_Mi^+De+C1-!Usl4MAM`lg0V<+kY| z(c~_^nwBz^eWvG}OD_=dmfuGNuΞ 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�j~qZ!kb}q} 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

      8SRXi2s7FlAqXi_4P@O*i>R|a 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

      {~1gfLZ357+|1DmIX{Cn>b+lhMuzA0JA&_ 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%0D4`&?fpH^X~L=hWxRnJ5f;6PNvx=(Wp4X-sHY8 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

      LRR~%UNL!%H;$cIfj~11V-ID6% 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%0A=tQ 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�u9?FmHro&YH4+o` z2$m_*o#elhdCrju&u8}G0W(?bj8&?w8H;rqGh0qfJsS#k?hBLgyOwi;{m{KfDe`I5)RWC0l&HX(-L7qeiMhaC=Dfz7ObGSRf??gdP>G2f2T>t0VY{# z5pS>rth{pJ*Hr#aNVF#PrZJ$FAZ_%UeI1!HocP^RZ)kC3?&um&9#?BeebW+5d8w{3 zsBUOT`-4u}|FF{`mU8iIIWa=~HDo^jvi9g$edOt{=+A4(TAy{9)P*7u)$8+aJA*b{ z8nx~s8|_BFI$Z3WYzOwWu|S+=@m3n&h%mpEW=W0`xqFy#$L|{V#8J*@vw^Tg=VPl* zv=oupn~NH~vkonBW1#qDt5L>ydZi7S+Dku -}ITkj6Dd^nKPQ{aR#g%I!H&! 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
      sZnpQ*Ns0v7n8 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%0Aa<-O@K~i+|}sh-Ni*5 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%0D#GiiSs9Qz|~>)xxM|*VNcTjU}=U) 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 z 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 z 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

      3!!1;jlA;vRo6pavlB=YY8H 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
        t8`Ks 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

        UIYn6b8sr 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�(HKylZC)710H!H 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

        %lerBTJ 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�W(uv<-i<3UUoN;$;)PZ@Jj1$%&{X0KF28uc0*bB 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�O5G{epH1c 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

        $s!@Qg>>Mzo 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

        DXAaW`6SXg2grE=X1KxlO6dI_qGLc{ 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

        1i3gW+Ia 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%0AjY#y-|Q&OY8g!9LMG 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

        • {{ nav.nav_link('/documentation/components/core/building-blocks', 'Building Blocks', currentPath) }}
        • +
        • {{ nav.nav_link('/documentation/components/core/column-backend', 'Column Backend', currentPath) }}
        • {{ nav.nav_link('/documentation/components/core/data-retrieval', 'Data Retrieval', currentPath) }}
        • {{ nav.nav_link('/documentation/components/core/data-manipulation', 'Data Manipulation', currentPath) }}
        • {{ nav.nav_link('/documentation/components/core/select-drop', 'Select / Drop', currentPath) }}
        • diff --git a/web/landing/tests/Flow/Website/Tests/Functional/PlaygroundBranchSinkTest.php b/web/landing/tests/Flow/Website/Tests/Functional/PlaygroundBranchSinkTest.php new file mode 100644 index 0000000000..5f0849ea88 --- /dev/null +++ b/web/landing/tests/Flow/Website/Tests/Functional/PlaygroundBranchSinkTest.php @@ -0,0 +1,46 @@ +openPlayground('/playground'); + $page = $this->pageOf($browser); + + $this->setPlaygroundCode($page, <<<'PHP' + read(from_sequence_number('id', 1, 9)) + ->batchSize(3) + ->write(to_branch(ref('id')->isEven(), to_array($even))) + ->write(to_branch(ref('id')->isOdd(), to_array($odd))) + ->run(); + echo 'even=' . implode(',', array_column($even, 'id')) . ';odd=' . implode(',', array_column($odd, 'id')) . ';'; + PHP); + + $page->evaluate('() => document.getElementById("action-run").click()'); + + $browser->waitUntilVisible('[data-playground-output-target="container"] .output-message'); + + static::assertSame( + '', + type_string()->assert($page->evaluate( + '() => Array.from(document.querySelectorAll(\'[data-playground-output-target="container"] .output-error\')).map(e => e.textContent).join("\n")', + )), + ); + $browser->assertSeeIn('[data-playground-output-target="container"]', 'even=2,4,6,8;odd=1,3,5,7,9;'); + } +} From 82c46006c31fefd510e6689475fe77b72b230c98 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sat, 3 Oct 2026 19:56:12 +0200 Subject: [PATCH 17/21] chore(flow-php/etl-adapter-doctrine): require doctrine/dbal 4.5, drop its deprecated schema API - doctrine/dbal raised to ^4.5, dependencies updated - tables built through TableEditor instead of deprecated Table::addPrimaryKeyConstraint/addIndex/addUniqueIndex - Column::getType() replaced by getTypeName() --- .../Service/Doctrine/DoctrineConnection.php | 7 +- composer.json | 2 +- composer.lock | 546 +++++++++--------- .../etl-adapter-doctrine/composer.json | 2 +- .../ETL/Adapter/Doctrine/SchemaConverter.php | 38 +- .../Doctrine/Tests/Context/PlannedTable.php | 5 +- .../Integration/DbalDataFrameFactoryTest.php | 10 +- .../DbalLimitOffsetExtractorTest.php | 13 +- .../Tests/Integration/DbalLoaderTest.php | 45 +- .../MySQLDbalLimitOffsetExtractorTest.php | 137 +++-- .../Dialects/MySQLDbalLoaderTest.php | 178 ++++-- .../Dialects/MySQLDbalQueryExtractorTest.php | 45 +- .../Dialects/MySQLSchemaDerivationTest.php | 5 +- .../Dialects/MySQLTransactionSinkTest.php | 20 +- .../PosgreSQLDbalLimitOffsetExtractorTest.php | 137 +++-- .../Dialects/PostgreSQLDbalLoaderTest.php | 193 +++++-- .../PostgreSQLDbalQueryExtractorTest.php | 45 +- .../PostgreSQLSchemaDerivationTest.php | 5 +- .../PostgreSQLTransactionSinkTest.php | 20 +- .../SqliteDbalLimitOffsetExtractorTest.php | 137 +++-- .../Dialects/SqliteDbalLoaderTest.php | 193 +++++-- .../Dialects/SqliteDbalQueryExtractorTest.php | 45 +- .../Dialects/SqliteSchemaDerivationTest.php | 5 +- .../Dialects/SqliteTransactionSinkTest.php | 20 +- .../Tests/Unit/SchemaConverterTest.php | 43 +- .../symfony/telemetry-bundle/composer.json | 4 +- .../DatabaseTableListCommandTest.php | 43 +- .../DatabaseTableSchemaCommandTest.php | 81 ++- src/lib/doctrine-dbal-bulk/composer.json | 2 +- .../src/Flow/Doctrine/Bulk/BulkData.php | 8 +- .../Flow/Doctrine/Bulk/TableDefinition.php | 5 +- .../Bulk/Tests/Mother/WideTableMother.php | 4 +- .../Bulk/Tests/Unit/TableDefinitionTest.php | 7 +- tools/infection/composer.lock | 12 +- tools/mago/composer.lock | 12 +- tools/phpunit/composer.lock | 44 +- 36 files changed, 1327 insertions(+), 791 deletions(-) diff --git a/benchmarks/src/Service/Doctrine/DoctrineConnection.php b/benchmarks/src/Service/Doctrine/DoctrineConnection.php index c9b90adfcb..be523853f7 100644 --- a/benchmarks/src/Service/Doctrine/DoctrineConnection.php +++ b/benchmarks/src/Service/Doctrine/DoctrineConnection.php @@ -47,9 +47,10 @@ public static function createTable(Connection $connection, string $table, bool $ $definition = to_dbal_schema_table((new FakeRandomOrdersExtractor())->schema(), $table); if ($keyed) { - $definition->addPrimaryKeyConstraint( - PrimaryKeyConstraint::editor()->setUnquotedColumnNames('order_id')->create(), - ); + $definition = $definition + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('order_id')->create()) + ->create(); } $connection->createSchemaManager()->createTable($definition); diff --git a/composer.json b/composer.json index 492a42067e..5879bd35cb 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "cmsig/seal": "^0.12", "coduo/php-humanizer": "^5.0", "cuyz/valinor": "^2.4", - "doctrine/dbal": "^4.4", + "doctrine/dbal": "^4.5", "google/apiclient": "^2.13", "google/protobuf": "^4.0 || ^5.0", "halaxa/json-machine": "^1.2", diff --git a/composer.lock b/composer.lock index f0f55c9063..cb7b675cc3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2a326b7adbd5bb2d7624c82921172673", + "content-hash": "9cfb96472f0a2797d94d07502009edb1", "packages": [ { "name": "async-aws/core", @@ -427,16 +427,16 @@ }, { "name": "doctrine/dbal", - "version": "4.4.4", + "version": "4.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "fb9e0ffe15e1590e24dc61c0c0a23f9a33ee42ce" + "reference": "c435cd7ea33e17d2a89288caf994cf3d4549b879" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/fb9e0ffe15e1590e24dc61c0c0a23f9a33ee42ce", - "reference": "fb9e0ffe15e1590e24dc61c0c0a23f9a33ee42ce", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/c435cd7ea33e17d2a89288caf994cf3d4549b879", + "reference": "c435cd7ea33e17d2a89288caf994cf3d4549b879", "shasum": "" }, "require": { @@ -452,9 +452,9 @@ "phpstan/phpstan": "2.1.30", "phpstan/phpstan-phpunit": "2.0.7", "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "11.5.50", - "slevomat/coding-standard": "8.27.1", - "squizlabs/php_codesniffer": "4.0.1", + "phpunit/phpunit": "11.5.56", + "slevomat/coding-standard": "8.31.1", + "squizlabs/php_codesniffer": "4.0.4", "symfony/cache": "^6.3.8|^7.0|^8.0", "symfony/console": "^5.4|^6.3|^7.0|^8.0" }, @@ -513,7 +513,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.4.4" + "source": "https://github.com/doctrine/dbal/tree/4.5.0" }, "funding": [ { @@ -529,7 +529,7 @@ "type": "tidelift" } ], - "time": "2026-07-21T14:34:40+00:00" + "time": "2026-09-24T16:11:26+00:00" }, { "name": "doctrine/deprecations", @@ -581,26 +581,26 @@ }, { "name": "firebase/php-jwt", - "version": "v7.1.0", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/googleapis/php-jwt.git", - "reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0" + "reference": "0501f5729b9e2448516674aff07c7d1727869b8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/b374a5d1a4f1f67fadc2165cdb284645945e2fc0", - "reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/0501f5729b9e2448516674aff07c7d1727869b8e", + "reference": "0501f5729b9e2448516674aff07c7d1727869b8e", "shasum": "" }, "require": { "php": "^8.0" }, "require-dev": { - "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/guzzle": "^7.4||^8.0", "phpfastcache/phpfastcache": "^9.2", "phpseclib/phpseclib": "~3.0", - "phpspec/prophecy-phpunit": "^2.0", + "phpspec/prophecy-phpunit": "^2.2", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", "psr/http-client": "^1.0", @@ -612,6 +612,14 @@ "phpseclib/phpseclib": "Support PS256 (RSASSA-PSS) signatures" }, "type": "library", + "extra": { + "component": { + "id": "jwt", + "path": "Jwt", + "entry": "README.md", + "target": "googleapis/php-jwt.git" + } + }, "autoload": { "psr-4": { "Firebase\\JWT\\": "src" @@ -641,30 +649,30 @@ ], "support": { "issues": "https://github.com/googleapis/php-jwt/issues", - "source": "https://github.com/googleapis/php-jwt/tree/v7.1.0" + "source": "https://github.com/googleapis/php-jwt/tree/v7.2.1" }, - "time": "2026-06-11T17:54:14+00:00" + "time": "2026-09-28T17:51:46+00:00" }, { "name": "google/apiclient", - "version": "v2.19.4", + "version": "v2.20.1", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client.git", - "reference": "f745b310113d556c19d5e54ccc48b5821d1e2622" + "reference": "31b577e7012c4e68d5289d63aaf7e6d471ec1ff1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/f745b310113d556c19d5e54ccc48b5821d1e2622", - "reference": "f745b310113d556c19d5e54ccc48b5821d1e2622", + "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/31b577e7012c4e68d5289d63aaf7e6d471ec1ff1", + "reference": "31b577e7012c4e68d5289d63aaf7e6d471ec1ff1", "shasum": "" }, "require": { "firebase/php-jwt": "^6.0||^7.0", "google/apiclient-services": "~0.350", - "google/auth": "^1.37", - "guzzlehttp/guzzle": "^7.4.5", - "guzzlehttp/psr7": "^2.6", + "google/auth": "^1.53", + "guzzlehttp/guzzle": "^7.8.2||^8.0", + "guzzlehttp/psr7": "^2.6.3||^3.0", "monolog/monolog": "^2.9||^3.0", "php": "^8.1" }, @@ -712,22 +720,22 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client/issues", - "source": "https://github.com/googleapis/google-api-php-client/tree/v2.19.4" + "source": "https://github.com/googleapis/google-api-php-client/tree/v2.20.1" }, - "time": "2026-06-29T08:12:37+00:00" + "time": "2026-09-25T18:54:19+00:00" }, { "name": "google/apiclient-services", - "version": "v0.459.0", + "version": "v0.461.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "3b45be50c8420dea56b6f2326ff745175c3cafb8" + "reference": "653eec9b7767d34f0cbe2a702cf2c2b825a4857d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/3b45be50c8420dea56b6f2326ff745175c3cafb8", - "reference": "3b45be50c8420dea56b6f2326ff745175c3cafb8", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/653eec9b7767d34f0cbe2a702cf2c2b825a4857d", + "reference": "653eec9b7767d34f0cbe2a702cf2c2b825a4857d", "shasum": "" }, "require": { @@ -756,22 +764,22 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.459.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.461.0" }, - "time": "2026-09-14T01:22:23+00:00" + "time": "2026-09-25T22:00:27+00:00" }, { "name": "google/auth", - "version": "v1.53.0", + "version": "v1.55.1", "source": { "type": "git", "url": "https://github.com/googleapis/google-auth-library-php.git", - "reference": "d677d0b0c4bd52ab222a85df8e74e0d491c0cc5a" + "reference": "ef1b92cb42470b09b3caaf23bb9b4bb9a2dc787e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/d677d0b0c4bd52ab222a85df8e74e0d491c0cc5a", - "reference": "d677d0b0c4bd52ab222a85df8e74e0d491c0cc5a", + "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/ef1b92cb42470b09b3caaf23bb9b4bb9a2dc787e", + "reference": "ef1b92cb42470b09b3caaf23bb9b4bb9a2dc787e", "shasum": "" }, "require": { @@ -789,17 +797,25 @@ "kelvinmo/simplejwt": "^1.1.0", "phpseclib/phpseclib": "^3.0.35", "phpspec/prophecy-phpunit": "^2.1", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^9.6.34", "sebastian/comparator": ">=1.2.3", "squizlabs/php_codesniffer": "^4.0", - "symfony/filesystem": "^6.3||^7.3", - "symfony/process": "^6.0||^7.0", + "symfony/filesystem": "^6.4.39||^7.3", + "symfony/process": "^6.4.41||^7.0", "webmozart/assert": "^1.11||^2.0" }, "suggest": { "phpseclib/phpseclib": "May be used in place of OpenSSL for signing strings or for token management. Please require version ^2." }, "type": "library", + "extra": { + "component": { + "id": "auth", + "path": "Auth", + "entry": "README.md", + "target": "googleapis/google-auth-library-php.git" + } + }, "autoload": { "psr-4": { "Google\\Auth\\": "src" @@ -810,7 +826,7 @@ "Apache-2.0" ], "description": "Google Auth Library for PHP", - "homepage": "https://github.com/google/google-auth-library-php", + "homepage": "https://github.com/googleapis/google-auth-library-php", "keywords": [ "Authentication", "google", @@ -819,9 +835,9 @@ "support": { "docs": "https://cloud.google.com/php/docs/reference/auth/latest", "issues": "https://github.com/googleapis/google-auth-library-php/issues", - "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.53.0" + "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.55.1" }, - "time": "2026-07-22T22:36:10+00:00" + "time": "2026-09-28T17:51:46+00:00" }, { "name": "google/protobuf", @@ -1262,16 +1278,16 @@ }, { "name": "monolog/monolog", - "version": "3.12.0", + "version": "3.12.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "72c534fc0ab181ef52d92a68382318631e301608" + "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/72c534fc0ab181ef52d92a68382318631e301608", - "reference": "72c534fc0ab181ef52d92a68382318631e301608", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d7059e4c691d05ea1222b5124bed0f961be46e15", + "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15", "shasum": "" }, "require": { @@ -1351,7 +1367,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.12.0" + "source": "https://github.com/Seldaek/monolog/tree/3.12.1" }, "funding": [ { @@ -1363,7 +1379,7 @@ "type": "tidelift" } ], - "time": "2026-09-09T08:34:20+00:00" + "time": "2026-09-29T19:21:12+00:00" }, { "name": "openspout/openspout", @@ -2350,16 +2366,16 @@ }, { "name": "symfony/console", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "23d6f88a29f6d0eac45bd77d70307adf83ba7ab0" + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/23d6f88a29f6d0eac45bd77d70307adf83ba7ab0", - "reference": "23d6f88a29f6d0eac45bd77d70307adf83ba7ab0", + "url": "https://api.github.com/repos/symfony/console/zipball/d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", + "reference": "d7bca2fe05241dc7732d0c8b6d551b879f5d0a7d", "shasum": "" }, "require": { @@ -2424,7 +2440,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.18" + "source": "https://github.com/symfony/console/tree/v7.4.20" }, "funding": [ { @@ -2444,20 +2460,20 @@ "type": "tidelift" } ], - "time": "2026-08-25T14:18:37+00:00" + "time": "2026-09-18T15:55:00+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.4.17", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f318ac9da5aba0be2cf43ecdd562c05a33bc11c0" + "reference": "a7faee783a87b55f27460fc571f8c639bf9d93a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f318ac9da5aba0be2cf43ecdd562c05a33bc11c0", - "reference": "f318ac9da5aba0be2cf43ecdd562c05a33bc11c0", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a7faee783a87b55f27460fc571f8c639bf9d93a2", + "reference": "a7faee783a87b55f27460fc571f8c639bf9d93a2", "shasum": "" }, "require": { @@ -2508,7 +2524,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.4.17" + "source": "https://github.com/symfony/dependency-injection/tree/v7.4.20" }, "funding": [ { @@ -2528,7 +2544,7 @@ "type": "tidelift" } ], - "time": "2026-08-21T17:40:08+00:00" + "time": "2026-09-29T12:35:16+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2603,16 +2619,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.4.17", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8373921e231e190a88e2ad526951bbaa791576fa" + "reference": "82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8373921e231e190a88e2ad526951bbaa791576fa", - "reference": "8373921e231e190a88e2ad526951bbaa791576fa", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0", + "reference": "82239fe00f7cdc9f17c4166fff4ebdc22bd26ec0", "shasum": "" }, "require": { @@ -2661,7 +2677,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.4.17" + "source": "https://github.com/symfony/error-handler/tree/v7.4.20" }, "funding": [ { @@ -2681,7 +2697,7 @@ "type": "tidelift" } ], - "time": "2026-08-21T17:40:08+00:00" + "time": "2026-09-22T18:56:40+00:00" }, { "name": "symfony/event-dispatcher", @@ -2920,16 +2936,16 @@ }, { "name": "symfony/http-client", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "68d81f78d127984ff2e741f0e0d9cb1078f8f3ea" + "reference": "750a420b8dd0af3d6e1c6c1412802abf2cdd2b6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/68d81f78d127984ff2e741f0e0d9cb1078f8f3ea", - "reference": "68d81f78d127984ff2e741f0e0d9cb1078f8f3ea", + "url": "https://api.github.com/repos/symfony/http-client/zipball/750a420b8dd0af3d6e1c6c1412802abf2cdd2b6c", + "reference": "750a420b8dd0af3d6e1c6c1412802abf2cdd2b6c", "shasum": "" }, "require": { @@ -2997,7 +3013,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.4.18" + "source": "https://github.com/symfony/http-client/tree/v7.4.20" }, "funding": [ { @@ -3017,7 +3033,7 @@ "type": "tidelift" } ], - "time": "2026-08-30T13:49:59+00:00" + "time": "2026-09-24T11:02:13+00:00" }, { "name": "symfony/http-client-contracts", @@ -3103,16 +3119,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "d070b716a32fbe3bf04204db0f58ace73b86d133" + "reference": "9d0761c0da6bd5b801b401666834901a9a1ffc33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d070b716a32fbe3bf04204db0f58ace73b86d133", - "reference": "d070b716a32fbe3bf04204db0f58ace73b86d133", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9d0761c0da6bd5b801b401666834901a9a1ffc33", + "reference": "9d0761c0da6bd5b801b401666834901a9a1ffc33", "shasum": "" }, "require": { @@ -3161,7 +3177,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.18" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.20" }, "funding": [ { @@ -3181,20 +3197,20 @@ "type": "tidelift" } ], - "time": "2026-08-30T20:10:52+00:00" + "time": "2026-09-24T07:12:44+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "275d2d2d24530f2a0eaf17704a3a93860a036351" + "reference": "392784b5d7b959b8d872542a2530c50c540a788f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/275d2d2d24530f2a0eaf17704a3a93860a036351", - "reference": "275d2d2d24530f2a0eaf17704a3a93860a036351", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/392784b5d7b959b8d872542a2530c50c540a788f", + "reference": "392784b5d7b959b8d872542a2530c50c540a788f", "shasum": "" }, "require": { @@ -3280,7 +3296,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.18" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.20" }, "funding": [ { @@ -3300,7 +3316,7 @@ "type": "tidelift" } ], - "time": "2026-08-30T21:24:29+00:00" + "time": "2026-09-29T14:05:16+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3387,16 +3403,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75", + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75", "shasum": "" }, "require": { @@ -3445,7 +3461,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0" }, "funding": [ { @@ -3465,20 +3481,20 @@ "type": "tidelift" } ], - "time": "2026-07-28T08:25:59+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.42.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b", + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b", "shasum": "" }, "require": { @@ -3530,7 +3546,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0" }, "funding": [ { @@ -3550,20 +3566,20 @@ "type": "tidelift" } ], - "time": "2026-08-07T06:33:24+00:00" + "time": "2026-09-23T22:02:09+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.38.2", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", "shasum": "" }, "require": { @@ -3615,7 +3631,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0" }, "funding": [ { @@ -3635,20 +3651,20 @@ "type": "tidelift" } ], - "time": "2026-05-27T06:59:30+00:00" + "time": "2026-09-24T15:19:04+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.37.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" + "reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", - "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74", + "reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74", "shasum": "" }, "require": { @@ -3699,7 +3715,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.43.0" }, "funding": [ { @@ -3719,20 +3735,20 @@ "type": "tidelift" } ], - "time": "2026-04-10T16:19:22+00:00" + "time": "2026-09-25T15:50:05+00:00" }, { "name": "symfony/polyfill-php82", - "version": "v1.38.1", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php82.git", - "reference": "002dc0cfe5fd4ed6033d48f27d4f19a486c4b04b" + "reference": "843bbe8b2a7934307b749751eede0f111f5d1cfc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/002dc0cfe5fd4ed6033d48f27d4f19a486c4b04b", - "reference": "002dc0cfe5fd4ed6033d48f27d4f19a486c4b04b", + "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/843bbe8b2a7934307b749751eede0f111f5d1cfc", + "reference": "843bbe8b2a7934307b749751eede0f111f5d1cfc", "shasum": "" }, "require": { @@ -3779,7 +3795,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php82/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-php82/tree/v1.43.0" }, "funding": [ { @@ -3799,20 +3815,20 @@ "type": "tidelift" } ], - "time": "2026-05-26T12:45:58+00:00" + "time": "2026-09-25T15:50:05+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6" + "reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/5ea99087fb99c273a9b9236ed4c31e78b16103c6", - "reference": "5ea99087fb99c273a9b9236ed4c31e78b16103c6", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/80ccff923a8d61f73ebe9da0aa94e25232f004ce", + "reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce", "shasum": "" }, "require": { @@ -3859,7 +3875,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.43.0" }, "funding": [ { @@ -3879,20 +3895,20 @@ "type": "tidelift" } ], - "time": "2026-07-01T12:47:55+00:00" + "time": "2026-09-25T15:50:05+00:00" }, { "name": "symfony/polyfill-php85", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a" + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a", - "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/86a42cbcc07adc331481a5ab310a4024bfc227f6", + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6", "shasum": "" }, "require": { @@ -3939,7 +3955,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.43.0" }, "funding": [ { @@ -3959,20 +3975,20 @@ "type": "tidelift" } ], - "time": "2026-07-01T12:47:55+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.37.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94" + "reference": "b23ff8245cc5c4479ea2be3d0132d2e6dd433993" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94", - "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/b23ff8245cc5c4479ea2be3d0132d2e6dd433993", + "reference": "b23ff8245cc5c4479ea2be3d0132d2e6dd433993", "shasum": "" }, "require": { @@ -4022,7 +4038,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.43.0" }, "funding": [ { @@ -4042,7 +4058,7 @@ "type": "tidelift" } ], - "time": "2026-04-10T16:19:22+00:00" + "time": "2026-09-24T05:20:52+00:00" }, { "name": "symfony/service-contracts", @@ -4133,16 +4149,16 @@ }, { "name": "symfony/string", - "version": "v7.4.15", + "version": "v7.4.19", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "e394af32256bf9e7bf80849d95e589167c10097b" + "reference": "02731ce2bd26514bec9efc0baef2cd0b0cf67f46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/e394af32256bf9e7bf80849d95e589167c10097b", - "reference": "e394af32256bf9e7bf80849d95e589167c10097b", + "url": "https://api.github.com/repos/symfony/string/zipball/02731ce2bd26514bec9efc0baef2cd0b0cf67f46", + "reference": "02731ce2bd26514bec9efc0baef2cd0b0cf67f46", "shasum": "" }, "require": { @@ -4200,7 +4216,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.15" + "source": "https://github.com/symfony/string/tree/v7.4.19" }, "funding": [ { @@ -4220,7 +4236,7 @@ "type": "tidelift" } ], - "time": "2026-07-28T07:33:02+00:00" + "time": "2026-09-11T14:46:58+00:00" }, { "name": "symfony/translation", @@ -4406,16 +4422,16 @@ }, { "name": "symfony/uid", - "version": "v7.4.17", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "69d732355a139c6f8881337d28515aa01f12b8be" + "reference": "a96bbdb02a04ff3b5592cee6741b03edc78b56aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/69d732355a139c6f8881337d28515aa01f12b8be", - "reference": "69d732355a139c6f8881337d28515aa01f12b8be", + "url": "https://api.github.com/repos/symfony/uid/zipball/a96bbdb02a04ff3b5592cee6741b03edc78b56aa", + "reference": "a96bbdb02a04ff3b5592cee6741b03edc78b56aa", "shasum": "" }, "require": { @@ -4460,7 +4476,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.4.17" + "source": "https://github.com/symfony/uid/tree/v7.4.20" }, "funding": [ { @@ -4480,7 +4496,7 @@ "type": "tidelift" } ], - "time": "2026-08-11T07:38:58+00:00" + "time": "2026-09-23T16:18:28+00:00" }, { "name": "symfony/var-dumper", @@ -4868,16 +4884,16 @@ }, { "name": "composer/semver", - "version": "3.4.4", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" + "reference": "f7a296f4c4cf8cb8bb83e35d6951a406bb11afa5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", - "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "url": "https://api.github.com/repos/composer/semver/zipball/f7a296f4c4cf8cb8bb83e35d6951a406bb11afa5", + "reference": "f7a296f4c4cf8cb8bb83e35d6951a406bb11afa5", "shasum": "" }, "require": { @@ -4919,7 +4935,7 @@ "homepage": "http://robbast.nl" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "Version comparison library that offers utilities, version constraint parsing and validation.", "keywords": [ "semantic", "semver", @@ -4929,7 +4945,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.4" + "source": "https://github.com/composer/semver/tree/3.5.0" }, "funding": [ { @@ -4941,7 +4957,7 @@ "type": "github" } ], - "time": "2025-08-20T19:15:30+00:00" + "time": "2026-09-24T14:38:51+00:00" }, { "name": "elastic/transport", @@ -5852,11 +5868,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.2.14", + "version": "2.2.16", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9c672e7a8e791dfc3d30e55f683e73fc0b63a3ac", - "reference": "9c672e7a8e791dfc3d30e55f683e73fc0b63a3ac", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46a6d9060e5a7763adfcc21ebcb8b504ebdbcb92", + "reference": "46a6d9060e5a7763adfcc21ebcb8b504ebdbcb92", "shasum": "" }, "require": { @@ -5912,7 +5928,7 @@ "type": "github" } ], - "time": "2026-09-12T21:39:33+00:00" + "time": "2026-09-25T09:31:51+00:00" }, { "name": "ramsey/collection", @@ -6070,16 +6086,16 @@ }, { "name": "symfony/cache", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "6c521e19a99e8ae57e22aa85b9271534513ee850" + "reference": "e7e604eab58639503495a46f5c194cc69a9c80a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/6c521e19a99e8ae57e22aa85b9271534513ee850", - "reference": "6c521e19a99e8ae57e22aa85b9271534513ee850", + "url": "https://api.github.com/repos/symfony/cache/zipball/e7e604eab58639503495a46f5c194cc69a9c80a8", + "reference": "e7e604eab58639503495a46f5c194cc69a9c80a8", "shasum": "" }, "require": { @@ -6149,7 +6165,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.4.18" + "source": "https://github.com/symfony/cache/tree/v7.4.20" }, "funding": [ { @@ -6169,7 +6185,7 @@ "type": "tidelift" } ], - "time": "2026-08-30T20:10:52+00:00" + "time": "2026-09-29T12:35:16+00:00" }, { "name": "symfony/cache-contracts", @@ -6409,16 +6425,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.17", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "5ce28827081f6d1f0c32eaf3882750f19cb5bbe6" + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/5ce28827081f6d1f0c32eaf3882750f19cb5bbe6", - "reference": "5ce28827081f6d1f0c32eaf3882750f19cb5bbe6", + "url": "https://api.github.com/repos/symfony/finder/zipball/2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", + "reference": "2dd31e5208db7a0fda7bfc998ad727b79c2e4d1e", "shasum": "" }, "require": { @@ -6453,7 +6469,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.17" + "source": "https://github.com/symfony/finder/tree/v7.4.20" }, "funding": [ { @@ -6473,20 +6489,20 @@ "type": "tidelift" } ], - "time": "2026-08-21T12:09:28+00:00" + "time": "2026-09-26T06:31:10+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "45d6d66b6ea1ef7a3c4193dfe606370f0f80c9bf" + "reference": "99786f9338c24770ce4de6a95d049675aa75b129" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/45d6d66b6ea1ef7a3c4193dfe606370f0f80c9bf", - "reference": "45d6d66b6ea1ef7a3c4193dfe606370f0f80c9bf", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/99786f9338c24770ce4de6a95d049675aa75b129", + "reference": "99786f9338c24770ce4de6a95d049675aa75b129", "shasum": "" }, "require": { @@ -6540,7 +6556,6 @@ "symfony/workflow": "<7.4" }, "require-dev": { - "doctrine/persistence": "^1.3|^2|^3", "dragonmantank/cron-expression": "^3.1", "phpdocumentor/reflection-docblock": "^5.2|^6.0", "seld/jsonlint": "^1.10", @@ -6611,7 +6626,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.4.18" + "source": "https://github.com/symfony/framework-bundle/tree/v7.4.20" }, "funding": [ { @@ -6631,20 +6646,20 @@ "type": "tidelift" } ], - "time": "2026-08-30T20:10:52+00:00" + "time": "2026-09-28T19:09:50+00:00" }, { "name": "symfony/messenger", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "b109f9f4e54470ee6835751bc39318fe3d8275e6" + "reference": "4cf94f12c9e899a87e6b6bf800dffcb709585410" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/b109f9f4e54470ee6835751bc39318fe3d8275e6", - "reference": "b109f9f4e54470ee6835751bc39318fe3d8275e6", + "url": "https://api.github.com/repos/symfony/messenger/zipball/4cf94f12c9e899a87e6b6bf800dffcb709585410", + "reference": "4cf94f12c9e899a87e6b6bf800dffcb709585410", "shasum": "" }, "require": { @@ -6705,7 +6720,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.4.18" + "source": "https://github.com/symfony/messenger/tree/v7.4.20" }, "funding": [ { @@ -6725,7 +6740,7 @@ "type": "tidelift" } ], - "time": "2026-08-30T00:47:26+00:00" + "time": "2026-09-29T06:38:53+00:00" }, { "name": "symfony/options-resolver", @@ -6876,16 +6891,16 @@ }, { "name": "symfony/polyfill-php84", - "version": "v1.38.1", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa" + "reference": "22c6548499cbe5c5bb072fc0c42312dff062a015" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa", - "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/22c6548499cbe5c5bb072fc0c42312dff062a015", + "reference": "22c6548499cbe5c5bb072fc0c42312dff062a015", "shasum": "" }, "require": { @@ -6932,7 +6947,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.43.0" }, "funding": [ { @@ -6952,20 +6967,20 @@ "type": "tidelift" } ], - "time": "2026-05-26T12:51:13+00:00" + "time": "2026-09-23T22:01:09+00:00" }, { "name": "symfony/process", - "version": "v7.4.18", + "version": "v7.4.19", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "058d17fc284cce14efb2385783b55014a461b176" + "reference": "ed0ae095b86994d370d5791612e55984f15aa30e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/058d17fc284cce14efb2385783b55014a461b176", - "reference": "058d17fc284cce14efb2385783b55014a461b176", + "url": "https://api.github.com/repos/symfony/process/zipball/ed0ae095b86994d370d5791612e55984f15aa30e", + "reference": "ed0ae095b86994d370d5791612e55984f15aa30e", "shasum": "" }, "require": { @@ -6997,7 +7012,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.18" + "source": "https://github.com/symfony/process/tree/v7.4.19" }, "funding": [ { @@ -7017,7 +7032,7 @@ "type": "tidelift" } ], - "time": "2026-08-21T17:40:08+00:00" + "time": "2026-09-02T12:38:34+00:00" }, { "name": "symfony/property-access", @@ -7102,16 +7117,16 @@ }, { "name": "symfony/property-info", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "52420d499b03ec20c0d38f0dc2f940bc9c43dc8e" + "reference": "d24c4c810b1285c5d8d77c6fd7b25e714479bd48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/52420d499b03ec20c0d38f0dc2f940bc9c43dc8e", - "reference": "52420d499b03ec20c0d38f0dc2f940bc9c43dc8e", + "url": "https://api.github.com/repos/symfony/property-info/zipball/d24c4c810b1285c5d8d77c6fd7b25e714479bd48", + "reference": "d24c4c810b1285c5d8d77c6fd7b25e714479bd48", "shasum": "" }, "require": { @@ -7168,7 +7183,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v7.4.18" + "source": "https://github.com/symfony/property-info/tree/v7.4.20" }, "funding": [ { @@ -7188,20 +7203,20 @@ "type": "tidelift" } ], - "time": "2026-08-25T14:18:37+00:00" + "time": "2026-09-28T09:47:41+00:00" }, { "name": "symfony/routing", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "ddd558991e98f693ae6bf5063cc1b0362c6bbec3" + "reference": "2bacb72be5eadeaf9874d5accb75bfb33d21c74b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/ddd558991e98f693ae6bf5063cc1b0362c6bbec3", - "reference": "ddd558991e98f693ae6bf5063cc1b0362c6bbec3", + "url": "https://api.github.com/repos/symfony/routing/zipball/2bacb72be5eadeaf9874d5accb75bfb33d21c74b", + "reference": "2bacb72be5eadeaf9874d5accb75bfb33d21c74b", "shasum": "" }, "require": { @@ -7253,7 +7268,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.18" + "source": "https://github.com/symfony/routing/tree/v7.4.20" }, "funding": [ { @@ -7273,20 +7288,20 @@ "type": "tidelift" } ], - "time": "2026-08-17T13:12:36+00:00" + "time": "2026-09-28T19:09:50+00:00" }, { "name": "symfony/security-bundle", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "caaa8b92f2657a6b99057f4da36ee89f3baab506" + "reference": "a2a8dc7ab9d5d90d5937963a4ef1b9c8e3e7258c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/caaa8b92f2657a6b99057f4da36ee89f3baab506", - "reference": "caaa8b92f2657a6b99057f4da36ee89f3baab506", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/a2a8dc7ab9d5d90d5937963a4ef1b9c8e3e7258c", + "reference": "a2a8dc7ab9d5d90d5937963a4ef1b9c8e3e7258c", "shasum": "" }, "require": { @@ -7327,6 +7342,7 @@ "symfony/framework-bundle": "^6.4.13|^7.1.6|^8.0", "symfony/http-client": "^6.4|^7.0|^8.0", "symfony/ldap": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", "symfony/process": "^6.4|^7.0|^8.0", "symfony/rate-limiter": "^6.4|^7.0|^8.0", "symfony/runtime": "^6.4.13|^7.1.6|^8.0", @@ -7365,7 +7381,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v7.4.18" + "source": "https://github.com/symfony/security-bundle/tree/v7.4.20" }, "funding": [ { @@ -7385,20 +7401,20 @@ "type": "tidelift" } ], - "time": "2026-08-30T17:23:54+00:00" + "time": "2026-09-24T11:02:13+00:00" }, { "name": "symfony/security-core", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "4fac226354298b8d66f680275b0daef1d3f580d2" + "reference": "4e5c01656aa79e6d463fde45117041ebccbaf829" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/4fac226354298b8d66f680275b0daef1d3f580d2", - "reference": "4fac226354298b8d66f680275b0daef1d3f580d2", + "url": "https://api.github.com/repos/symfony/security-core/zipball/4e5c01656aa79e6d463fde45117041ebccbaf829", + "reference": "4e5c01656aa79e6d463fde45117041ebccbaf829", "shasum": "" }, "require": { @@ -7457,7 +7473,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v7.4.18" + "source": "https://github.com/symfony/security-core/tree/v7.4.20" }, "funding": [ { @@ -7477,7 +7493,7 @@ "type": "tidelift" } ], - "time": "2026-08-30T00:47:26+00:00" + "time": "2026-09-28T16:00:27+00:00" }, { "name": "symfony/security-csrf", @@ -7555,16 +7571,16 @@ }, { "name": "symfony/security-http", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "ca575e23a2b5e068ce0cdf157767b63b438125e0" + "reference": "5fa566b8bfbb398cded6988f059c3d97506ed692" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/ca575e23a2b5e068ce0cdf157767b63b438125e0", - "reference": "ca575e23a2b5e068ce0cdf157767b63b438125e0", + "url": "https://api.github.com/repos/symfony/security-http/zipball/5fa566b8bfbb398cded6988f059c3d97506ed692", + "reference": "5fa566b8bfbb398cded6988f059c3d97506ed692", "shasum": "" }, "require": { @@ -7623,7 +7639,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v7.4.18" + "source": "https://github.com/symfony/security-http/tree/v7.4.20" }, "funding": [ { @@ -7643,20 +7659,20 @@ "type": "tidelift" } ], - "time": "2026-08-30T17:23:54+00:00" + "time": "2026-09-28T18:33:58+00:00" }, { "name": "symfony/serializer", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "1f31d4e902c85b820af5dce27dbe17435524bed0" + "reference": "67c5b0b2ef39863835f43b9c34dcb3af80b892cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/1f31d4e902c85b820af5dce27dbe17435524bed0", - "reference": "1f31d4e902c85b820af5dce27dbe17435524bed0", + "url": "https://api.github.com/repos/symfony/serializer/zipball/67c5b0b2ef39863835f43b9c34dcb3af80b892cf", + "reference": "67c5b0b2ef39863835f43b9c34dcb3af80b892cf", "shasum": "" }, "require": { @@ -7727,7 +7743,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v7.4.18" + "source": "https://github.com/symfony/serializer/tree/v7.4.20" }, "funding": [ { @@ -7747,20 +7763,20 @@ "type": "tidelift" } ], - "time": "2026-08-30T00:47:26+00:00" + "time": "2026-09-28T09:39:38+00:00" }, { "name": "symfony/twig-bridge", - "version": "v7.4.17", + "version": "v7.4.19", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "413485ee177ad5b321ad9a689a90fd3f2d3fefd7" + "reference": "10d369dd3845bb650a9450e643d6d9027e8a86af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/413485ee177ad5b321ad9a689a90fd3f2d3fefd7", - "reference": "413485ee177ad5b321ad9a689a90fd3f2d3fefd7", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/10d369dd3845bb650a9450e643d6d9027e8a86af", + "reference": "10d369dd3845bb650a9450e643d6d9027e8a86af", "shasum": "" }, "require": { @@ -7842,7 +7858,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v7.4.17" + "source": "https://github.com/symfony/twig-bridge/tree/v7.4.19" }, "funding": [ { @@ -7862,20 +7878,20 @@ "type": "tidelift" } ], - "time": "2026-08-22T09:04:42+00:00" + "time": "2026-09-14T12:19:06+00:00" }, { "name": "symfony/twig-bundle", - "version": "v7.4.15", + "version": "v7.4.19", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "e3d2bea0b594aa50c3482a278a5cd09d83d94517" + "reference": "231c0b37dada053458d47281261a3af0270a634d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/e3d2bea0b594aa50c3482a278a5cd09d83d94517", - "reference": "e3d2bea0b594aa50c3482a278a5cd09d83d94517", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/231c0b37dada053458d47281261a3af0270a634d", + "reference": "231c0b37dada053458d47281261a3af0270a634d", "shasum": "" }, "require": { @@ -7932,7 +7948,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v7.4.15" + "source": "https://github.com/symfony/twig-bundle/tree/v7.4.19" }, "funding": [ { @@ -7952,20 +7968,20 @@ "type": "tidelift" } ], - "time": "2026-07-21T15:13:06+00:00" + "time": "2026-09-11T14:46:58+00:00" }, { "name": "symfony/type-info", - "version": "v7.4.17", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/type-info.git", - "reference": "62d0ad6995630a4f7ea8fd270aadb3e2545c8e31" + "reference": "bbaaf3366400f5c85f66800b955c77b46e8abad2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/type-info/zipball/62d0ad6995630a4f7ea8fd270aadb3e2545c8e31", - "reference": "62d0ad6995630a4f7ea8fd270aadb3e2545c8e31", + "url": "https://api.github.com/repos/symfony/type-info/zipball/bbaaf3366400f5c85f66800b955c77b46e8abad2", + "reference": "bbaaf3366400f5c85f66800b955c77b46e8abad2", "shasum": "" }, "require": { @@ -8015,7 +8031,7 @@ "type" ], "support": { - "source": "https://github.com/symfony/type-info/tree/v7.4.17" + "source": "https://github.com/symfony/type-info/tree/v7.4.20" }, "funding": [ { @@ -8035,20 +8051,20 @@ "type": "tidelift" } ], - "time": "2026-08-21T15:52:48+00:00" + "time": "2026-09-28T12:19:37+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v7.4.17", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "3abb070d460c61924c23edfda9e2e5af34e43a19" + "reference": "916c2a4edf51270a5173a57d8d3936c02a4543a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/3abb070d460c61924c23edfda9e2e5af34e43a19", - "reference": "3abb070d460c61924c23edfda9e2e5af34e43a19", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/916c2a4edf51270a5173a57d8d3936c02a4543a1", + "reference": "916c2a4edf51270a5173a57d8d3936c02a4543a1", "shasum": "" }, "require": { @@ -8105,7 +8121,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.4.17" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.4.20" }, "funding": [ { @@ -8125,20 +8141,20 @@ "type": "tidelift" } ], - "time": "2026-08-22T09:04:42+00:00" + "time": "2026-09-28T19:09:50+00:00" }, { "name": "symfony/yaml", - "version": "v7.4.18", + "version": "v7.4.20", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4cef939e55b8a21c5780418de0d98ab00d0736e1" + "reference": "0222bf4dfaa1e3ceb8fff579635d655f2950d5a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4cef939e55b8a21c5780418de0d98ab00d0736e1", - "reference": "4cef939e55b8a21c5780418de0d98ab00d0736e1", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0222bf4dfaa1e3ceb8fff579635d655f2950d5a7", + "reference": "0222bf4dfaa1e3ceb8fff579635d655f2950d5a7", "shasum": "" }, "require": { @@ -8181,7 +8197,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.4.18" + "source": "https://github.com/symfony/yaml/tree/v7.4.20" }, "funding": [ { @@ -8201,20 +8217,20 @@ "type": "tidelift" } ], - "time": "2026-08-30T00:47:26+00:00" + "time": "2026-09-26T06:31:10+00:00" }, { "name": "twig/twig", - "version": "v3.29.0", + "version": "v3.30.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "45a3c6e9224c3377a39c7b150bb29d5d97d2c75d" + "reference": "8c737079b726af72ff8ef3c595be9f6a810ea1ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/45a3c6e9224c3377a39c7b150bb29d5d97d2c75d", - "reference": "45a3c6e9224c3377a39c7b150bb29d5d97d2c75d", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/8c737079b726af72ff8ef3c595be9f6a810ea1ef", + "reference": "8c737079b726af72ff8ef3c595be9f6a810ea1ef", "shasum": "" }, "require": { @@ -8269,7 +8285,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.29.0" + "source": "https://github.com/twigphp/Twig/tree/v3.30.0" }, "funding": [ { @@ -8281,7 +8297,7 @@ "type": "tidelift" } ], - "time": "2026-09-18T09:10:14+00:00" + "time": "2026-09-25T13:20:01+00:00" } ], "aliases": [], diff --git a/src/adapter/etl-adapter-doctrine/composer.json b/src/adapter/etl-adapter-doctrine/composer.json index 9576487746..1e69804b9c 100644 --- a/src/adapter/etl-adapter-doctrine/composer.json +++ b/src/adapter/etl-adapter-doctrine/composer.json @@ -14,7 +14,7 @@ ], "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "doctrine/dbal": "^4.4", + "doctrine/dbal": "^4.5", "flow-php/doctrine-dbal-bulk": "self.version", "flow-php/etl": "self.version" }, diff --git a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/SchemaConverter.php b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/SchemaConverter.php index a3a0d91dcf..590afff256 100644 --- a/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/SchemaConverter.php +++ b/src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/SchemaConverter.php @@ -59,10 +59,7 @@ public function toDbalTable(Schema $schema, string $tableName, array $tableOptio $columns[$column->getObjectName()->getIdentifier()->getValue()] = $column; } - $table = new Table($tableName, $columns, options: $tableOptions); - $this->updateIndexes($schema, $table); - - return $table; + return $this->withIndexes($schema, new Table($tableName, $columns, options: $tableOptions)); } public function toFlowSchema(Table $table): Schema @@ -81,7 +78,7 @@ public function toFlowSchema(Table $table): Schema */ private function columnToFlow(Column $column, Table $table): Definition { - $type = $this->typesMap->toFlowType($column->getType()::class); + $type = $this->typesMap->toFlowType(DbalType::getType($column->getTypeName())::class); $nullable = !$column->getNotnull(); @@ -252,10 +249,7 @@ private function flowToColumn(string $name, Type $type, bool $nullable, ?Metadat return new Column($name, $dbalType, $options); } - /** - * @return array - */ - private function updateIndexes(Schema $schema, Table $table): array + private function withIndexes(Schema $schema, Table $table): Table { $indexesData = []; $uniqueIndexesData = []; @@ -300,28 +294,38 @@ private function updateIndexes(Schema $schema, Table $table): array } } - $indexes = []; + $editor = $table->edit(); foreach ($indexesData as $name => $columns) { - $table->addIndex($columns, $name); + /** @var non-empty-list $columns */ + $indexEditor = Index::editor()->setUnquotedColumnNames($columns[0], ...array_slice($columns, 1)); + + $editor->addIndex($name === '' ? $indexEditor : $indexEditor->setUnquotedName($name)); } foreach ($uniqueIndexesData as $name => $columns) { - $indexes[] = new Index($name, $columns, isUnique: true); - $table->addUniqueIndex($columns, $name); + /** @var non-empty-list $columns */ + $indexEditor = Index::editor() + ->setType(IndexType::UNIQUE) + ->setUnquotedColumnNames($columns[0], ...array_slice($columns, 1)); + + $editor->addIndex($name === '' ? $indexEditor : $indexEditor->setUnquotedName($name)); } foreach ($primaryKey as $name => $columns) { /** @var non-empty-list $columns */ - $editor = PrimaryKeyConstraint::editor()->setUnquotedColumnNames($columns[0], ...array_slice($columns, 1)); + $primaryKeyEditor = PrimaryKeyConstraint::editor()->setUnquotedColumnNames($columns[0], ...array_slice( + $columns, + 1, + )); if ($name !== '') { - $editor = $editor->setUnquotedName($name); + $primaryKeyEditor = $primaryKeyEditor->setUnquotedName($name); } - $table->addPrimaryKeyConstraint($editor->create()); + $editor->addPrimaryKeyConstraint($primaryKeyEditor->create()); } - return $indexes; + return $editor->create(); } } diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/PlannedTable.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/PlannedTable.php index 7e070d7b0d..2abed612f6 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/PlannedTable.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Context/PlannedTable.php @@ -22,7 +22,10 @@ public static function create(DatabaseContext $context, string $name, int $rows) (new Table($name, [ new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('grp', Type::getType(Types::INTEGER), ['notnull' => true]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), ); for ($id = 1; $id <= $rows; $id++) { diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalDataFrameFactoryTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalDataFrameFactoryTest.php index 437fdc9e72..37a2dc8788 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalDataFrameFactoryTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalDataFrameFactoryTest.php @@ -33,7 +33,10 @@ public function test_dataframe_factory(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), ); $this->pgsqlDatabaseContext->insert('flow_doctrine_data_factory_test', [ @@ -87,7 +90,10 @@ public function test_dataframe_factory_with_schema(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), ); $this->pgsqlDatabaseContext->insert('flow_doctrine_data_factory_test', [ diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalLimitOffsetExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalLimitOffsetExtractorTest.php index 4c0d80f521..dfb070151c 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalLimitOffsetExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalLimitOffsetExtractorTest.php @@ -31,10 +31,15 @@ final class DbalLimitOffsetExtractorTest extends IntegrationTestCase { public function test_creating_limit_offset_extractor_for_table(): void { - $this->pgsqlDatabaseContext->createTable((new DoctrineTable($table = 'flow_doctrine_order_by_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('code', Type::getType(Types::INTEGER), ['notnull' => true]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new DoctrineTable($table = 'flow_doctrine_order_by_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('code', Type::getType(Types::INTEGER), ['notnull' => true]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $customTypesMap = new TypesMap([ StringType::class => TextType::class, diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalLoaderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalLoaderTest.php index 5271124970..407eacb488 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalLoaderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/DbalLoaderTest.php @@ -26,11 +26,16 @@ final class DbalLoaderTest extends IntegrationTestCase { public function test_create_loader_with_invalid_operation(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Operation can be insert, update, or delete, invalid given.'); @@ -40,11 +45,16 @@ public function test_create_loader_with_invalid_operation(): void public function test_create_loader_with_invalid_operation_from_connection(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Operation can be insert, update, or delete, invalid given.'); @@ -59,11 +69,16 @@ public function test_create_loader_with_invalid_operation_from_connection(): voi public function test_loader_with_custom_types_map(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::TEXT), ['notnull' => false]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::TEXT), ['notnull' => false]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $customTypesMap = new TypesMap([ StringType::class => TextType::class, diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalLimitOffsetExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalLimitOffsetExtractorTest.php index ac8252b451..a9139f1053 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalLimitOffsetExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalLimitOffsetExtractorTest.php @@ -30,11 +30,16 @@ final class MySQLDbalLimitOffsetExtractorTest extends IntegrationTestCase { public function test_extracting_entire_table(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->mysqlDatabaseContext->insert($table, [ @@ -70,11 +75,16 @@ public function test_extracting_entire_table(): void public function test_extracting_entire_table_using_qb(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->mysqlDatabaseContext->insert($table, [ @@ -114,11 +124,16 @@ public function test_extracting_entire_table_using_qb(): void public function test_extracting_entire_table_using_qb_with_maximum_and_offset_set_on_extractor(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->mysqlDatabaseContext->insert($table, [ @@ -160,11 +175,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_and_offset_se public function test_extracting_entire_table_using_qb_with_maximum_and_offset_set_on_query(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->mysqlDatabaseContext->insert($table, [ @@ -199,11 +219,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_and_offset_se public function test_extracting_entire_table_using_qb_with_maximum_set_on_query(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->mysqlDatabaseContext->insert($table, [ @@ -240,11 +265,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_set_on_query( public function test_extracting_entire_table_using_qb_with_schema(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->mysqlDatabaseContext->insert($table, [ @@ -310,12 +340,17 @@ public function test_extracting_entire_table_using_qb_with_schema(): void public function test_extracting_entire_table_with_group_by(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('type', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('type', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 10; $i++) { $this->mysqlDatabaseContext->insert($table, [ @@ -359,11 +394,16 @@ public function test_extracting_entire_table_with_group_by(): void public function test_extracting_limited_number_of_rows_from_table(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->mysqlDatabaseContext->insert($table, [ @@ -399,11 +439,16 @@ public function test_extracting_limited_number_of_rows_from_table(): void public function test_extracting_selected_columns(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->mysqlDatabaseContext->insert($table, [ diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalLoaderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalLoaderTest.php index a8ccd09b4e..a034ec3d12 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalLoaderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalLoaderTest.php @@ -25,10 +25,15 @@ final class MySQLDbalLoaderTest extends IntegrationTestCase { public function test_delete_non_existent_rows(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -60,10 +65,15 @@ public function test_delete_non_existent_rows(): void public function test_delete_rows_using_existing_connection(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -95,11 +105,18 @@ public function test_delete_rows_using_existing_connection(): void public function test_delete_with_composite_keys(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('group_id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id', 'group_id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('group_id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id', 'group_id')->create(), + ) + ->create(), + ); data_frame() ->read(from_array([ @@ -133,11 +150,16 @@ public function test_delete_with_composite_keys(): void public function test_deletes_rows_by_single_key(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); // Insert test data data_frame() @@ -172,11 +194,16 @@ public function test_deletes_rows_by_single_key(): void public function test_inserts_empty_rows(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->mysqlConnectionParams(), $table); @@ -196,11 +223,16 @@ public function test_inserts_empty_rows(): void public function test_inserts_multiple_rows_at_once(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->mysqlConnectionParams(), $table); @@ -218,11 +250,16 @@ public function test_inserts_multiple_rows_at_once(): void public function test_inserts_multiple_rows_at_once_using_existing_connection(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->mysqlDatabaseContext->connection(), $table); @@ -241,11 +278,16 @@ public function test_inserts_multiple_rows_at_once_using_existing_connection(): public function test_inserts_multiple_rows_in_two_insert_queries(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -261,11 +303,16 @@ public function test_inserts_multiple_rows_in_two_insert_queries(): void public function test_inserts_new_rows_and_skip_already_existed(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ ['id' => 1, 'name' => 'Name One', 'description' => 'Description One'], @@ -302,11 +349,16 @@ public function test_inserts_new_rows_and_skip_already_existed(): void public function test_inserts_xml_element_entry(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->mysqlConnectionParams(), $table); @@ -341,11 +393,16 @@ public function test_inserts_xml_element_entry(): void public function test_inserts_xml_entry(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->mysqlConnectionParams(), $table); @@ -380,11 +437,16 @@ public function test_inserts_xml_entry(): void public function test_update_multiple_rows_at_once(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $insertLoader = to_dbal_table_insert($this->mysqlConnectionParams(), $table); $updateLoader = to_dbal_table_update($this->mysqlConnectionParams(), $table, MySQLUpdateOptions::new()); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalQueryExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalQueryExtractorTest.php index 409286c660..54c39f096b 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalQueryExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLDbalQueryExtractorTest.php @@ -30,11 +30,16 @@ final class MySQLDbalQueryExtractorTest extends IntegrationTestCase { public function test_extracting_multiple_rows_at_once(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ @@ -61,11 +66,16 @@ public function test_extracting_multiple_rows_at_once(): void public function test_extracting_multiple_rows_multiple_times(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ @@ -117,11 +127,16 @@ public function test_extracting_multiple_rows_multiple_times(): void public function test_extracting_multiple_rows_with_schema(): void { - $this->mysqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->mysqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLSchemaDerivationTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLSchemaDerivationTest.php index 68720eee0d..2e0b1505e4 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLSchemaDerivationTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLSchemaDerivationTest.php @@ -56,7 +56,10 @@ protected function setUp(): void ]), new Column('placed_at', Type::getType(Types::DATETIME_MUTABLE), ['notnull' => false]), new Column('opens_at', Type::getType(Types::TIME_MUTABLE), ['notnull' => false]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), ); for ($i = 1; $i <= 3; $i++) { diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php index 44b30c650a..0843a25d9e 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/MySQLTransactionSinkTest.php @@ -39,7 +39,10 @@ public function test_multiple_batches_in_separate_transactions(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('value', Type::getType(Types::INTEGER), ['notnull' => true]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->mysqlDatabaseContext->createTable($table); @@ -75,7 +78,10 @@ public function test_rollback_on_failure(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->mysqlDatabaseContext->createTable($table); $this->mysqlDatabaseContext->insert('test_table', ['id' => 1, 'name' => 'Initial']); @@ -122,7 +128,10 @@ public function test_transactional_delete_and_insert(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->mysqlDatabaseContext->createTable($table); @@ -159,7 +168,10 @@ public function test_with_isolation_level(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->mysqlDatabaseContext->createTable($table); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PosgreSQLDbalLimitOffsetExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PosgreSQLDbalLimitOffsetExtractorTest.php index 05a7c3d5b6..d229bbb04c 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PosgreSQLDbalLimitOffsetExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PosgreSQLDbalLimitOffsetExtractorTest.php @@ -32,11 +32,16 @@ final class PosgreSQLDbalLimitOffsetExtractorTest extends IntegrationTestCase { public function test_extracting_entire_table(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->pgsqlDatabaseContext->insert($table, [ @@ -72,11 +77,16 @@ public function test_extracting_entire_table(): void public function test_extracting_entire_table_using_qb(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->pgsqlDatabaseContext->insert($table, [ @@ -116,11 +126,16 @@ public function test_extracting_entire_table_using_qb(): void public function test_extracting_entire_table_using_qb_with_maximum_and_offset_set_on_extractor(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->pgsqlDatabaseContext->insert($table, [ @@ -162,11 +177,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_and_offset_se public function test_extracting_entire_table_using_qb_with_maximum_and_offset_set_on_query(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->pgsqlDatabaseContext->insert($table, [ @@ -201,11 +221,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_and_offset_se public function test_extracting_entire_table_using_qb_with_maximum_set_on_query(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->pgsqlDatabaseContext->insert($table, [ @@ -242,11 +267,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_set_on_query( public function test_extracting_entire_table_using_qb_with_schema(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->pgsqlDatabaseContext->insert($table, [ @@ -312,12 +342,17 @@ public function test_extracting_entire_table_using_qb_with_schema(): void public function test_extracting_entire_table_with_group_by(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('type', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('type', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 10; $i++) { $this->pgsqlDatabaseContext->insert($table, [ @@ -361,11 +396,16 @@ public function test_extracting_entire_table_with_group_by(): void public function test_extracting_limited_number_of_rows_from_table(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->pgsqlDatabaseContext->insert($table, [ @@ -401,11 +441,16 @@ public function test_extracting_limited_number_of_rows_from_table(): void public function test_extracting_selected_columns(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->pgsqlDatabaseContext->insert($table, [ diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLDbalLoaderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLDbalLoaderTest.php index 08b3cad48c..b5b83a77a6 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLDbalLoaderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLDbalLoaderTest.php @@ -25,10 +25,15 @@ final class PostgreSQLDbalLoaderTest extends IntegrationTestCase { public function test_delete_non_existent_rows(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -60,10 +65,15 @@ public function test_delete_non_existent_rows(): void public function test_delete_rows_using_existing_connection(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -95,11 +105,18 @@ public function test_delete_rows_using_existing_connection(): void public function test_delete_with_composite_keys(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('group_id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id', 'group_id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('group_id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id', 'group_id')->create(), + ) + ->create(), + ); data_frame() ->read(from_array([ @@ -133,11 +150,16 @@ public function test_delete_with_composite_keys(): void public function test_deletes_rows_by_single_key(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -171,11 +193,16 @@ public function test_deletes_rows_by_single_key(): void public function test_inserts_empty_rows(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->postgresqlConnectionParams(), $table); @@ -195,11 +222,16 @@ public function test_inserts_empty_rows(): void public function test_inserts_multiple_rows_at_once(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->postgresqlConnectionParams(), $table); @@ -217,11 +249,16 @@ public function test_inserts_multiple_rows_at_once(): void public function test_inserts_multiple_rows_at_once_using_existing_connection(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->pgsqlDatabaseContext->connection(), $table); @@ -240,11 +277,16 @@ public function test_inserts_multiple_rows_at_once_using_existing_connection(): public function test_inserts_multiple_rows_in_two_insert_queries(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -260,11 +302,16 @@ public function test_inserts_multiple_rows_in_two_insert_queries(): void public function test_inserts_new_rows_and_skip_already_existed(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ ['id' => 1, 'name' => 'Name One', 'description' => 'Description One'], @@ -301,11 +348,16 @@ public function test_inserts_new_rows_and_skip_already_existed(): void public function test_inserts_new_rows_or_updates_already_existed_based_on_primary_key(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -343,11 +395,16 @@ public function test_inserts_new_rows_or_updates_already_existed_based_on_primar public function test_inserts_xml_element_entry(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->postgresqlConnectionParams(), $table); @@ -382,11 +439,16 @@ public function test_inserts_xml_element_entry(): void public function test_inserts_xml_entry(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->postgresqlConnectionParams(), $table); @@ -421,11 +483,16 @@ public function test_inserts_xml_entry(): void public function test_update_multiple_rows_at_once(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $insertLoader = to_dbal_table_insert($this->postgresqlConnectionParams(), $table); $updateLoader = to_dbal_table_update( diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLDbalQueryExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLDbalQueryExtractorTest.php index a4042bc3cd..55fe437fdd 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLDbalQueryExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLDbalQueryExtractorTest.php @@ -33,11 +33,16 @@ final class PostgreSQLDbalQueryExtractorTest extends IntegrationTestCase { public function test_extracting_multiple_rows_at_once(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ @@ -64,11 +69,16 @@ public function test_extracting_multiple_rows_at_once(): void public function test_extracting_multiple_rows_multiple_times(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ @@ -120,11 +130,16 @@ public function test_extracting_multiple_rows_multiple_times(): void public function test_extracting_multiple_rows_with_schema(): void { - $this->pgsqlDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->pgsqlDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLSchemaDerivationTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLSchemaDerivationTest.php index bd9d6c2342..558ac6afb8 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLSchemaDerivationTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLSchemaDerivationTest.php @@ -49,7 +49,10 @@ protected function setUp(): void 'scale' => 2, ]), new Column('placed_at', Type::getType(Types::DATETIME_MUTABLE), ['notnull' => false]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), ); for ($i = 1; $i <= 3; $i++) { diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php index 3953a3089d..b01adb0aa8 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/PostgreSQLTransactionSinkTest.php @@ -39,7 +39,10 @@ public function test_multiple_batches_in_separate_transactions(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('value', Type::getType(Types::INTEGER), ['notnull' => true]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->pgsqlDatabaseContext->createTable($table); @@ -75,7 +78,10 @@ public function test_rollback_on_failure(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->pgsqlDatabaseContext->createTable($table); $this->pgsqlDatabaseContext->insert('test_table', ['id' => 1, 'name' => 'Initial']); @@ -122,7 +128,10 @@ public function test_transactional_delete_and_insert(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->pgsqlDatabaseContext->createTable($table); @@ -159,7 +168,10 @@ public function test_with_isolation_level(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->pgsqlDatabaseContext->createTable($table); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalLimitOffsetExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalLimitOffsetExtractorTest.php index 1db9269730..6a4bbd79a2 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalLimitOffsetExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalLimitOffsetExtractorTest.php @@ -30,11 +30,16 @@ final class SqliteDbalLimitOffsetExtractorTest extends IntegrationTestCase { public function test_extracting_entire_table(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->sqliteDatabaseContext->insert($table, [ @@ -70,11 +75,16 @@ public function test_extracting_entire_table(): void public function test_extracting_entire_table_using_qb(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->sqliteDatabaseContext->insert($table, [ @@ -114,11 +124,16 @@ public function test_extracting_entire_table_using_qb(): void public function test_extracting_entire_table_using_qb_with_maximum_and_offset_set_on_extractor(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->sqliteDatabaseContext->insert($table, [ @@ -160,11 +175,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_and_offset_se public function test_extracting_entire_table_using_qb_with_maximum_and_offset_set_on_query(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->sqliteDatabaseContext->insert($table, [ @@ -199,11 +219,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_and_offset_se public function test_extracting_entire_table_using_qb_with_maximum_set_on_query(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 25; $i++) { $this->sqliteDatabaseContext->insert($table, [ @@ -240,11 +265,16 @@ public function test_extracting_entire_table_using_qb_with_maximum_set_on_query( public function test_extracting_entire_table_using_qb_with_schema(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->sqliteDatabaseContext->insert($table, [ @@ -310,12 +340,17 @@ public function test_extracting_entire_table_using_qb_with_schema(): void public function test_extracting_entire_table_with_group_by(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('type', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('type', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 10; $i++) { $this->sqliteDatabaseContext->insert($table, [ @@ -359,11 +394,16 @@ public function test_extracting_entire_table_with_group_by(): void public function test_extracting_limited_number_of_rows_from_table(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->sqliteDatabaseContext->insert($table, [ @@ -399,11 +439,16 @@ public function test_extracting_limited_number_of_rows_from_table(): void public function test_extracting_selected_columns(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); for ($i = 1; $i <= 8; $i++) { $this->sqliteDatabaseContext->insert($table, [ diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalLoaderTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalLoaderTest.php index 647b6b9956..c4efbf4c06 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalLoaderTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalLoaderTest.php @@ -24,10 +24,15 @@ final class SqliteDbalLoaderTest extends IntegrationTestCase { public function test_delete_non_existent_rows(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -59,10 +64,15 @@ public function test_delete_non_existent_rows(): void public function test_delete_rows_using_existing_connection(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -94,11 +104,18 @@ public function test_delete_rows_using_existing_connection(): void public function test_delete_with_composite_keys(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('group_id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id', 'group_id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('group_id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id', 'group_id')->create(), + ) + ->create(), + ); data_frame() ->read(from_array([ @@ -132,11 +149,16 @@ public function test_delete_with_composite_keys(): void public function test_deletes_rows_by_single_key(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -170,11 +192,16 @@ public function test_deletes_rows_by_single_key(): void public function test_inserts_empty_rows(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->sqliteConnectionParams(), $table); @@ -194,11 +221,16 @@ public function test_inserts_empty_rows(): void public function test_inserts_multiple_rows_at_once(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->sqliteConnectionParams(), $table); @@ -216,11 +248,16 @@ public function test_inserts_multiple_rows_at_once(): void public function test_inserts_multiple_rows_at_once_using_existing_connection(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->sqliteDatabaseContext->connection(), $table); @@ -239,11 +276,16 @@ public function test_inserts_multiple_rows_at_once_using_existing_connection(): public function test_inserts_multiple_rows_in_two_insert_queries(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -259,11 +301,16 @@ public function test_inserts_multiple_rows_in_two_insert_queries(): void public function test_inserts_new_rows_and_skip_already_existed(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ ['id' => 1, 'name' => 'Name One', 'description' => 'Description One'], @@ -300,11 +347,16 @@ public function test_inserts_new_rows_and_skip_already_existed(): void public function test_inserts_new_rows_or_updates_already_existed_based_on_primary_key(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->read(from_array([ @@ -338,11 +390,16 @@ public function test_inserts_new_rows_or_updates_already_existed_based_on_primar public function test_inserts_xml_element_entry(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->sqliteConnectionParams(), $table); @@ -377,11 +434,16 @@ public function test_inserts_xml_element_entry(): void public function test_inserts_xml_entry(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $loader = to_dbal_table_insert($this->sqliteConnectionParams(), $table); @@ -416,11 +478,16 @@ public function test_inserts_xml_entry(): void public function test_update_multiple_rows_at_once(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); $insertLoader = to_dbal_table_insert($this->sqliteConnectionParams(), $table); $updateLoader = to_dbal_table_update($this->sqliteConnectionParams(), $table); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalQueryExtractorTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalQueryExtractorTest.php index 76b25693df..94b5b14820 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalQueryExtractorTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteDbalQueryExtractorTest.php @@ -30,11 +30,16 @@ final class SqliteDbalQueryExtractorTest extends IntegrationTestCase { public function test_extracting_multiple_rows_at_once(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ @@ -61,11 +66,16 @@ public function test_extracting_multiple_rows_at_once(): void public function test_extracting_multiple_rows_multiple_times(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ @@ -117,11 +127,16 @@ public function test_extracting_multiple_rows_multiple_times(): void public function test_extracting_multiple_rows_with_schema(): void { - $this->sqliteDatabaseContext->createTable((new Table($table = 'flow_doctrine_bulk_test', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create())); + $this->sqliteDatabaseContext->createTable( + (new Table($table = 'flow_doctrine_bulk_test', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), + ); data_frame() ->extract(from_array([ diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteSchemaDerivationTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteSchemaDerivationTest.php index 8016b858ad..4d898a40ec 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteSchemaDerivationTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteSchemaDerivationTest.php @@ -32,7 +32,10 @@ protected function setUp(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), new Column('amount', Type::getType(Types::FLOAT), ['notnull' => true]), - ]))->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()), + ])) + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(), ); for ($i = 1; $i <= 3; $i++) { diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php index 2e906a6795..0104726e2a 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Integration/Dialects/SqliteTransactionSinkTest.php @@ -39,7 +39,10 @@ public function test_multiple_batches_in_separate_transactions(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('value', Type::getType(Types::INTEGER), ['notnull' => true]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->sqliteDatabaseContext->createTable($table); @@ -75,7 +78,10 @@ public function test_rollback_on_failure(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->sqliteDatabaseContext->createTable($table); $this->sqliteDatabaseContext->insert('test_table', ['id' => 1, 'name' => 'Initial']); @@ -122,7 +128,10 @@ public function test_transactional_delete_and_insert(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->sqliteDatabaseContext->createTable($table); @@ -159,7 +168,10 @@ public function test_with_isolation_level(): void new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), ]); - $table->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()); + $table = $table + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('id')->create()) + ->create(); $this->sqliteDatabaseContext->createTable($table); diff --git a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/SchemaConverterTest.php b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/SchemaConverterTest.php index f208a20a71..8343c849fe 100644 --- a/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/SchemaConverterTest.php +++ b/src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/SchemaConverterTest.php @@ -76,9 +76,15 @@ public function test_converting_flow_to_dbal_schema(): void new Index('idx_str_unique', ['str_unique'], true, false), ], ); - $expectedTable->addPrimaryKeyConstraint( - PrimaryKeyConstraint::editor()->setUnquotedName('pk_test')->setUnquotedColumnNames('int', 'str')->create(), - ); + $expectedTable = $expectedTable + ->edit() + ->addPrimaryKeyConstraint( + PrimaryKeyConstraint::editor() + ->setUnquotedName('pk_test') + ->setUnquotedColumnNames('int', 'str') + ->create(), + ) + ->create(); static::assertEquals($expectedTable, to_dbal_schema_table($flowSchema, 'test')); } @@ -94,9 +100,10 @@ public function test_converting_flow_to_dbal_schema_without_providing_pk_name(): new Column('int', Type::getType('integer'), ['notnull' => true]), new Column('str', Type::getType('string'), ['notnull' => true]), ]); - $expectedTable->addPrimaryKeyConstraint( - PrimaryKeyConstraint::editor()->setUnquotedColumnNames('int', 'str')->create(), - ); + $expectedTable = $expectedTable + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('int', 'str')->create()) + ->create(); static::assertEquals($expectedTable, to_dbal_schema_table($flowSchema, 'test')); } @@ -142,9 +149,15 @@ public function test_dbal_schema_to_flow_schema_dbal_36(): void new Index('idx_str_unique', ['str_unique'], true, false), ], ); - $inputTable->addPrimaryKeyConstraint( - PrimaryKeyConstraint::editor()->setUnquotedName('pk_test')->setUnquotedColumnNames('int', 'str')->create(), - ); + $inputTable = $inputTable + ->edit() + ->addPrimaryKeyConstraint( + PrimaryKeyConstraint::editor() + ->setUnquotedName('pk_test') + ->setUnquotedColumnNames('int', 'str') + ->create(), + ) + ->create(); static::assertEquals( schema( @@ -242,9 +255,15 @@ public function test_dbal_schema_to_flow_schema_dbal_40(): void new Index('idx_str_unique', ['str_unique'], true, false), ], ); - $inputTable->addPrimaryKeyConstraint( - PrimaryKeyConstraint::editor()->setUnquotedName('pk_test')->setUnquotedColumnNames('int', 'str')->create(), - ); + $inputTable = $inputTable + ->edit() + ->addPrimaryKeyConstraint( + PrimaryKeyConstraint::editor() + ->setUnquotedName('pk_test') + ->setUnquotedColumnNames('int', 'str') + ->create(), + ) + ->create(); static::assertEquals( schema( diff --git a/src/bridge/symfony/telemetry-bundle/composer.json b/src/bridge/symfony/telemetry-bundle/composer.json index 545c85e3c8..0c9ad6d707 100644 --- a/src/bridge/symfony/telemetry-bundle/composer.json +++ b/src/bridge/symfony/telemetry-bundle/composer.json @@ -29,7 +29,7 @@ "require-dev": { "composer-runtime-api": "^2.2", "composer/semver": "^3.4", - "doctrine/dbal": "^4.4", + "doctrine/dbal": "^4.5", "flow-php/psr18-telemetry-bridge": "self.version", "flow-php/symfony-http-foundation-telemetry-bridge": "self.version", "flow-php/telemetry-otlp-bridge": "self.version", @@ -46,7 +46,7 @@ "twig/twig": "^3.0" }, "suggest": { - "doctrine/dbal": "Required for Doctrine DBAL tracing (^4.4)", + "doctrine/dbal": "Required for Doctrine DBAL tracing (^4.5)", "flow-php/psr18-telemetry-bridge": "Required for PSR-18 HTTP client tracing", "flow-php/symfony-http-foundation-telemetry-bridge": "Required for HTTP trace context propagation (extract incoming / inject outgoing W3C trace headers)", "flow-php/telemetry-otlp-bridge": "Required for OTLP exporter support", diff --git a/src/cli/tests/Flow/CLI/Tests/Integration/DatabaseTableListCommandTest.php b/src/cli/tests/Flow/CLI/Tests/Integration/DatabaseTableListCommandTest.php index 75a5022dbf..40422c0130 100644 --- a/src/cli/tests/Flow/CLI/Tests/Integration/DatabaseTableListCommandTest.php +++ b/src/cli/tests/Flow/CLI/Tests/Integration/DatabaseTableListCommandTest.php @@ -38,21 +38,34 @@ protected function setUp(): void public function test_run_db_table_list(): void { - $this->dbContext()->createTable((new Table('table_01', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint( - new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), - )); - - $this->dbContext()->createTable((new Table('table_02', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('created_at', Type::getType(Types::DATETIME_IMMUTABLE), ['notnull' => true]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'platformOptions' => ['jsonb' => true]]), - ]))->addPrimaryKeyConstraint( - new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), - )); + $this->dbContext()->createTable( + (new Table('table_01', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), + ) + ->create(), + ); + + $this->dbContext()->createTable( + (new Table('table_02', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('created_at', Type::getType(Types::DATETIME_IMMUTABLE), ['notnull' => true]), + new Column('tags', Type::getType(Types::JSON), [ + 'notnull' => true, + 'platformOptions' => ['jsonb' => true], + ]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), + ) + ->create(), + ); $tester = new CommandTester(new DatabaseTableListCommand('db:table:list')); diff --git a/src/cli/tests/Flow/CLI/Tests/Integration/DatabaseTableSchemaCommandTest.php b/src/cli/tests/Flow/CLI/Tests/Integration/DatabaseTableSchemaCommandTest.php index dc2d58badf..905d3da6a9 100644 --- a/src/cli/tests/Flow/CLI/Tests/Integration/DatabaseTableSchemaCommandTest.php +++ b/src/cli/tests/Flow/CLI/Tests/Integration/DatabaseTableSchemaCommandTest.php @@ -40,21 +40,34 @@ protected function setUp(): void public function test_run_db_table_list(): void { - $this->dbContext()->createTable((new Table('table_01', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint( - new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), - )); - - $this->dbContext()->createTable((new Table('table_02', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('created_at', Type::getType(Types::DATETIME_IMMUTABLE), ['notnull' => true]), - new Column('tags', Type::getType(Types::JSON), ['notnull' => true, 'platformOptions' => ['jsonb' => true]]), - ]))->addPrimaryKeyConstraint( - new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), - )); + $this->dbContext()->createTable( + (new Table('table_01', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), + ) + ->create(), + ); + + $this->dbContext()->createTable( + (new Table('table_02', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('created_at', Type::getType(Types::DATETIME_IMMUTABLE), ['notnull' => true]), + new Column('tags', Type::getType(Types::JSON), [ + 'notnull' => true, + 'platformOptions' => ['jsonb' => true], + ]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), + ) + ->create(), + ); $tester = new CommandTester(new DatabaseTableSchemaCommand('db:table:schema')); @@ -98,13 +111,18 @@ public function test_selecting_specific_columns_only(): void static::markTestSkipped('This test is not supported in doctrine/dbal 4.0'); } - $this->dbContext()->createTable((new Table('table_01', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint( - new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), - )); + $this->dbContext()->createTable( + (new Table('table_01', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), + ) + ->create(), + ); $tester = new CommandTester(new DatabaseTableSchemaCommand('db:table:schema')); @@ -133,13 +151,18 @@ public function test_selecting_not_existing_column(): void static::markTestSkipped('This test is not supported in doctrine/dbal 4.0'); } - $this->dbContext()->createTable((new Table('table_01', [ - new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), - new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), - ]))->addPrimaryKeyConstraint( - new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), - )); + $this->dbContext()->createTable( + (new Table('table_01', [ + new Column('id', Type::getType(Types::INTEGER), ['notnull' => true]), + new Column('name', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + new Column('description', Type::getType(Types::STRING), ['notnull' => true, 'length' => 255]), + ])) + ->edit() + ->addPrimaryKeyConstraint( + new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true), + ) + ->create(), + ); $tester = new CommandTester(new DatabaseTableSchemaCommand('db:table:schema')); diff --git a/src/lib/doctrine-dbal-bulk/composer.json b/src/lib/doctrine-dbal-bulk/composer.json index 99f2e3e7a3..bbc98353bd 100644 --- a/src/lib/doctrine-dbal-bulk/composer.json +++ b/src/lib/doctrine-dbal-bulk/composer.json @@ -12,7 +12,7 @@ ], "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "doctrine/dbal": "^4.4", + "doctrine/dbal": "^4.5", "flow-php/types": "self.version" }, "autoload": { diff --git a/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/BulkData.php b/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/BulkData.php index a36bf8c072..75a0c50750 100644 --- a/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/BulkData.php +++ b/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/BulkData.php @@ -182,7 +182,7 @@ function (int $index, array $row) use ($table): string { if (array_key_exists($columnName, $this->types)) { $type = $this->types[$columnName]; } else { - $type = $table->dbalColumn($columnName)->getType(); + $type = Type::getType($table->dbalColumn($columnName)->getTypeName()); } $keys[] = @@ -226,7 +226,7 @@ public function toSqlNamedParameters(TableDefinition $table): array $type = $types[$column] ??= array_key_exists($column, $this->types) ? $this->types[$column] - : $table->dbalColumn($column)->getType(); + : Type::getType($table->dbalColumn($column)->getTypeName()); $rows[$index][$column . '_' . $index] = $type->convertToDatabaseValue($entry, $platform); } } @@ -284,7 +284,7 @@ function (array $row) use ($table): string { $type = $this->types[$columnName]; } else { $dbColumn = $table->dbalColumn($columnName); - $type = $dbColumn->getType(); + $type = Type::getType($dbColumn->getTypeName()); } $keys[] = 'CAST(? as ' . $type->getSQLDeclaration([], $table->platform()) . ')'; @@ -317,7 +317,7 @@ public function toSqlPositionalParameters(TableDefinition $table): array $type = $types[$column] ??= array_key_exists($column, $this->types) ? $this->types[$column] - : $table->dbalColumn($column)->getType(); + : Type::getType($table->dbalColumn($column)->getTypeName()); $parameters[] = $type->convertToDatabaseValue($entry, $platform); } } diff --git a/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/TableDefinition.php b/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/TableDefinition.php index 4c37301833..9865514ebc 100644 --- a/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/TableDefinition.php +++ b/src/lib/doctrine-dbal-bulk/src/Flow/Doctrine/Bulk/TableDefinition.php @@ -7,7 +7,6 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Schema\Column; -use Doctrine\DBAL\Types\Type; use Flow\Doctrine\Bulk\Exception\RuntimeException; use function array_filter; @@ -69,7 +68,7 @@ public function dbalPositionalTypes(BulkData $bulkData): array for ($i = 0; $i < $bulkData->count(); $i++) { foreach ($bulkData->columns()->all() as $columnName) { $dbColumn = $this->dbalColumn($columnName); - $types[] = Type::getTypeRegistry()->lookupName($dbColumn->getType()); + $types[] = $dbColumn->getTypeName(); } } @@ -91,7 +90,7 @@ public function dbalTypes(BulkData $bulkData): array $dbColumn = $this->dbalColumn($columnName); for ($i = 0; $i < $bulkData->count(); $i++) { - $types[$columnName . '_' . $i] = Type::getTypeRegistry()->lookupName($dbColumn->getType()); + $types[$columnName . '_' . $i] = $dbColumn->getTypeName(); } } diff --git a/src/lib/doctrine-dbal-bulk/tests/Flow/Doctrine/Bulk/Tests/Mother/WideTableMother.php b/src/lib/doctrine-dbal-bulk/tests/Flow/Doctrine/Bulk/Tests/Mother/WideTableMother.php index 9d121d8994..5a49c56a04 100644 --- a/src/lib/doctrine-dbal-bulk/tests/Flow/Doctrine/Bulk/Tests/Mother/WideTableMother.php +++ b/src/lib/doctrine-dbal-bulk/tests/Flow/Doctrine/Bulk/Tests/Mother/WideTableMother.php @@ -66,6 +66,8 @@ public static function table(string $name, int $columns): Table public static function tableWithPrimaryKey(string $name, int $columns): Table { return self::table($name, $columns) - ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('c1')->create()); + ->edit() + ->addPrimaryKeyConstraint(PrimaryKeyConstraint::editor()->setUnquotedColumnNames('c1')->create()) + ->create(); } } diff --git a/src/lib/doctrine-dbal-bulk/tests/Flow/Doctrine/Bulk/Tests/Unit/TableDefinitionTest.php b/src/lib/doctrine-dbal-bulk/tests/Flow/Doctrine/Bulk/Tests/Unit/TableDefinitionTest.php index e650fbab70..770e61f0d8 100644 --- a/src/lib/doctrine-dbal-bulk/tests/Flow/Doctrine/Bulk/Tests/Unit/TableDefinitionTest.php +++ b/src/lib/doctrine-dbal-bulk/tests/Flow/Doctrine/Bulk/Tests/Unit/TableDefinitionTest.php @@ -53,10 +53,7 @@ public function test_column_caching_works_correctly(): void // @mago-expect analysis:deprecated-method // @mago-expect analysis:deprecated-method static::assertSame($column1->getName(), $column2->getName()); - static::assertSame( - Type::getTypeRegistry()->lookupName($column1->getType()), - Type::getTypeRegistry()->lookupName($column2->getType()), - ); + static::assertSame($column1->getTypeName(), $column2->getTypeName()); } public function test_column_retrieval_from_non_existent_table(): void @@ -99,7 +96,7 @@ public function test_dbal_column_returns_column_with_correct_type(): void // @mago-expect analysis:deprecated-method static::assertSame('name', $nameColumn->getName()); - static::assertSame(Types::STRING, Type::getTypeRegistry()->lookupName($nameColumn->getType())); + static::assertSame(Types::STRING, $nameColumn->getTypeName()); } public function test_dbal_column_returns_existing_column(): void diff --git a/tools/infection/composer.lock b/tools/infection/composer.lock index fcad45ff58..a0a2889e7e 100644 --- a/tools/infection/composer.lock +++ b/tools/infection/composer.lock @@ -480,16 +480,16 @@ }, { "name": "infection/infection", - "version": "0.35.5", + "version": "0.35.6", "source": { "type": "git", "url": "https://github.com/infection/infection.git", - "reference": "0db852996c8de64d908a4ed2112c36853232d992" + "reference": "1b89ae38246fcac2774a8591612f0a863b20e181" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/infection/infection/zipball/0db852996c8de64d908a4ed2112c36853232d992", - "reference": "0db852996c8de64d908a4ed2112c36853232d992", + "url": "https://api.github.com/repos/infection/infection/zipball/1b89ae38246fcac2774a8591612f0a863b20e181", + "reference": "1b89ae38246fcac2774a8591612f0a863b20e181", "shasum": "" }, "require": { @@ -604,7 +604,7 @@ ], "support": { "issues": "https://github.com/infection/infection/issues", - "source": "https://github.com/infection/infection/tree/0.35.5" + "source": "https://github.com/infection/infection/tree/0.35.6" }, "funding": [ { @@ -616,7 +616,7 @@ "type": "open_collective" } ], - "time": "2026-09-27T14:35:40+00:00" + "time": "2026-10-02T12:18:24+00:00" }, { "name": "infection/mutator", diff --git a/tools/mago/composer.lock b/tools/mago/composer.lock index 1692db3ad7..6124220fd9 100644 --- a/tools/mago/composer.lock +++ b/tools/mago/composer.lock @@ -9,16 +9,16 @@ "packages-dev": [ { "name": "carthage-software/mago", - "version": "1.51.0", + "version": "1.51.2", "source": { "type": "git", "url": "https://github.com/carthage-software/mago.git", - "reference": "9a62f0a1829490dcff31f62808589f7ab86779b5" + "reference": "5415d6900d330a5a6a70728aaa7f9c52c7672495" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/carthage-software/mago/zipball/9a62f0a1829490dcff31f62808589f7ab86779b5", - "reference": "9a62f0a1829490dcff31f62808589f7ab86779b5", + "url": "https://api.github.com/repos/carthage-software/mago/zipball/5415d6900d330a5a6a70728aaa7f9c52c7672495", + "reference": "5415d6900d330a5a6a70728aaa7f9c52c7672495", "shasum": "" }, "require": { @@ -60,7 +60,7 @@ ], "support": { "issues": "https://github.com/carthage-software/mago/issues", - "source": "https://github.com/carthage-software/mago/tree/1.51.0" + "source": "https://github.com/carthage-software/mago/tree/1.51.2" }, "funding": [ { @@ -68,7 +68,7 @@ "type": "github" } ], - "time": "2026-10-01T20:37:34+00:00" + "time": "2026-10-03T09:05:17+00:00" }, { "name": "revolt/event-loop", diff --git a/tools/phpunit/composer.lock b/tools/phpunit/composer.lock index 6e158ed9d9..be5401f0f4 100644 --- a/tools/phpunit/composer.lock +++ b/tools/phpunit/composer.lock @@ -244,25 +244,25 @@ }, { "name": "phpunit/php-code-coverage", - "version": "12.5.7", + "version": "12.5.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "186dab580576598076de6818596d12b61801880e" + "reference": "7440368d94738d54f2c1de24dbd3871793bbb0dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/186dab580576598076de6818596d12b61801880e", - "reference": "186dab580576598076de6818596d12b61801880e", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7440368d94738d54f2c1de24dbd3871793bbb0dd", + "reference": "7440368d94738d54f2c1de24dbd3871793bbb0dd", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^5.7.0", + "nikic/php-parser": "^5.9.0", "php": ">=8.3", - "phpunit/php-text-template": "^5.0", + "phpunit/php-text-template": "^5.0.1", "sebastian/complexity": "^5.0", "sebastian/environment": "^8.1.2", "sebastian/lines-of-code": "^4.0.1", @@ -270,7 +270,7 @@ "theseer/tokenizer": "^2.0.1" }, "require-dev": { - "phpunit/phpunit": "^12.5.28" + "phpunit/phpunit": "^12.5.37" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -308,7 +308,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.7" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.8" }, "funding": [ { @@ -328,7 +328,7 @@ "type": "tidelift" } ], - "time": "2026-06-01T13:24:19+00:00" + "time": "2026-10-03T14:03:50+00:00" }, { "name": "phpunit/php-file-iterator", @@ -469,23 +469,23 @@ }, { "name": "phpunit/php-text-template", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53" + "reference": "babab73b7ef9fae406f2eb3ee11323a61caa63d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53", - "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/babab73b7ef9fae406f2eb3ee11323a61caa63d5", + "reference": "babab73b7ef9fae406f2eb3ee11323a61caa63d5", "shasum": "" }, "require": { "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.37" }, "type": "library", "extra": { @@ -517,15 +517,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-text-template", + "type": "tidelift" } ], - "time": "2025-02-07T04:59:16+00:00" + "time": "2026-10-03T04:51:29+00:00" }, { "name": "phpunit/php-timer", From 16b69bb0c830e3688c978ef5855dd182748eac86 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sun, 4 Oct 2026 10:01:10 +0200 Subject: [PATCH 18/21] fix: same XML text on every libxml2, pinned libpg_query, pg-query-ext built from source in CI - XML physicals and node texts decode non-ASCII character references older libxml2 emits - libpg_query pinned to the 18.0.0 tag instead of the moving 18-latest branch - CI builds pg-query-ext from the checked-out source, cached by its source hash - Parquet tests use GZIP instead of optional zstd / lz4 codecs - mutation runs register the Rows comparator extension --- .github/actions/pg-query-ext/action.yml | 36 ++++++++++++++++ .github/workflows/baseline.yml | 8 +++- .../workflows/job-phpunit-telemetry-tests.yml | 4 +- .github/workflows/job-tests.yml | 4 +- .github/workflows/release.yml | 4 +- .github/workflows/test-website.yml | 4 +- documentation/contributing/c.md | 5 ++- documentation/contributing/wasm.md | 5 +-- .../Unit/AdaptiveParquetOpenSinkTest.php | 2 +- .../src/Flow/ETL/Adapter/XML/XMLNodes.php | 4 +- .../Physical/XmlCharacterReferences.php | 43 +++++++++++++++++++ .../Column/Physical/XmlDocumentPhysical.php | 2 +- .../Column/Physical/XmlElementPhysical.php | 3 ++ .../Physical/XmlCharacterReferencesTest.php | 24 +++++++++++ ..._parquet_file_reader_writer_contracts.phpt | 2 +- src/extension/pg-query-ext/Makefile | 2 +- src/extension/pg-query-ext/ext/config.m4 | 6 +-- tools/infection/phpunit.xml | 3 ++ 18 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 .github/actions/pg-query-ext/action.yml create mode 100644 src/core/etl/src/Flow/ETL/Column/Physical/XmlCharacterReferences.php create mode 100644 src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlCharacterReferencesTest.php diff --git a/.github/actions/pg-query-ext/action.yml b/.github/actions/pg-query-ext/action.yml new file mode 100644 index 0000000000..626a845772 --- /dev/null +++ b/.github/actions/pg-query-ext/action.yml @@ -0,0 +1,36 @@ +name: "pg-query-ext from source" +description: "Builds src/extension/pg-query-ext from the checked-out source, cached by its source hash, and enables it" + +runs: + using: "composite" + steps: + - name: "Resolve PHP version" + id: php + shell: bash + run: echo "version=$(php -r 'echo PHP_VERSION;')" >> "$GITHUB_OUTPUT" + + - name: "Cache pg_query.so" + id: cache + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 + with: + path: src/extension/pg-query-ext/ext/modules/pg_query.so + key: pg-query-ext-${{ runner.os }}-${{ runner.arch }}-php-${{ steps.php.outputs.version }}-${{ hashFiles('src/extension/pg-query-ext/**') }} + + - name: "Install build dependencies" + if: ${{ steps.cache.outputs.cache-hit != 'true' }} + shell: bash + run: sudo apt-get update && sudo apt-get install -y build-essential autoconf automake libtool protobuf-compiler libprotobuf-c-dev + + - name: "Build pg-query-ext" + if: ${{ steps.cache.outputs.cache-hit != 'true' }} + shell: bash + working-directory: src/extension/pg-query-ext + run: make build + + - name: "Enable pg-query-ext" + shell: bash + working-directory: src/extension/pg-query-ext + run: | + sudo cp ext/modules/pg_query.so "$(php -r 'echo ini_get("extension_dir");')/" + echo "extension=pg_query.so" | sudo tee -a "$(php -r 'echo php_ini_loaded_file();')" + php -m | grep -x pg_query diff --git a/.github/workflows/baseline.yml b/.github/workflows/baseline.yml index c165593a27..7613bd28c4 100644 --- a/.github/workflows/baseline.yml +++ b/.github/workflows/baseline.yml @@ -46,7 +46,9 @@ jobs: extensions: ':psr, bcmath, dom, hash, json, mbstring, xml, xmlwriter, xmlreader, zlib' cache-key-suffix: "-locked-phar" apt-packages: "build-essential autoconf automake libtool protobuf-compiler libprotobuf-c-dev" - pie-extensions: "flow-php/pg-query-ext:1.x-dev" + + - name: "Build pg-query-ext from source" + uses: "./.github/actions/pg-query-ext" - name: "Build PHAR file" run: "just phar" @@ -116,11 +118,13 @@ jobs: extensions: ':psr, bcmath, dom, hash, json, mbstring, xml, xmlwriter, xmlreader, zlib' cache-key-suffix: "-website-phar" apt-packages: "build-essential autoconf automake libtool protobuf-compiler libprotobuf-c-dev" - pie-extensions: "flow-php/pg-query-ext:1.x-dev" extra-working-directory: "web/landing" extra-cache-key-suffix: "-website" extra-composer-file: "web/landing/composer.lock" + - name: "Build pg-query-ext from source" + uses: "./.github/actions/pg-query-ext" + - name: "Generate documentation" run: "just docs" diff --git a/.github/workflows/job-phpunit-telemetry-tests.yml b/.github/workflows/job-phpunit-telemetry-tests.yml index 7276369bf1..a98e3da236 100644 --- a/.github/workflows/job-phpunit-telemetry-tests.yml +++ b/.github/workflows/job-phpunit-telemetry-tests.yml @@ -54,7 +54,9 @@ jobs: extensions: ':psr, bcmath, dom, hash, json, mbstring, xml, xmlwriter, xmlreader, zlib, curl, pgsql, grpc, protobuf' ini-values: 'memory_limit=-1' apt-packages: "build-essential autoconf automake libtool protobuf-compiler libprotobuf-c-dev" - pie-extensions: "flow-php/pg-query-ext:1.x-dev" + + - name: "Build pg-query-ext from source" + uses: "./.github/actions/pg-query-ext" - name: "Install PHPUnit ${{ matrix.phpunit-version }}" if: ${{ matrix.phpunit-version != '11' }} diff --git a/.github/workflows/job-tests.yml b/.github/workflows/job-tests.yml index 418f578b17..646c98a24a 100644 --- a/.github/workflows/job-tests.yml +++ b/.github/workflows/job-tests.yml @@ -113,7 +113,9 @@ jobs: extensions: ':psr, apcu, bcmath, dom, hash, json, mbstring, xml, xmlwriter, xmlreader, zlib, curl, pgsql, grpc, protobuf' ini-values: 'memory_limit=-1, post_max_size=32M, upload_max_filesize=32M, apc.enable_cli=1' apt-packages: "build-essential autoconf automake libtool protobuf-compiler libprotobuf-c-dev" - pie-extensions: "flow-php/pg-query-ext:1.x-dev" + + - name: "Build pg-query-ext from source" + uses: "./.github/actions/pg-query-ext" - name: Set up Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a7057e7595..f6e5b1ce95 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,9 @@ jobs: extensions: ':psr, bcmath, dom, hash, json, mbstring, xml, xmlwriter, xmlreader, zlib' cache-key-suffix: "-locked-phar" apt-packages: "build-essential autoconf automake libtool protobuf-compiler libprotobuf-c-dev" - pie-extensions: "flow-php/pg-query-ext:1.x-dev" + + - name: "Build pg-query-ext from source" + uses: "./.github/actions/pg-query-ext" - name: "Build PHAR file" run: "just phar" diff --git a/.github/workflows/test-website.yml b/.github/workflows/test-website.yml index ab4055a26f..10611881e9 100644 --- a/.github/workflows/test-website.yml +++ b/.github/workflows/test-website.yml @@ -38,7 +38,9 @@ jobs: extensions: ':psr, bcmath, dom, hash, json, mbstring, xml, xmlwriter, xmlreader, zlib' cache-key-suffix: "-locked-phar" apt-packages: "build-essential autoconf automake libtool protobuf-compiler libprotobuf-c-dev" - pie-extensions: "flow-php/pg-query-ext:1.x-dev" + + - name: "Build pg-query-ext from source" + uses: "./.github/actions/pg-query-ext" - name: "Build PHAR file" run: "just phar" diff --git a/documentation/contributing/c.md b/documentation/contributing/c.md index dfd2d9ca97..8e835e656b 100644 --- a/documentation/contributing/c.md +++ b/documentation/contributing/c.md @@ -95,7 +95,7 @@ The extension is only half of the story. A given `libpg_query` version pins a sp | Place | What it is | Used by | |---------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|-----------------------------------| -| `src/extension/pg-query-ext/vendor/libpg_query` (Makefile `PG_VERSION`) | the C library compiled into the extension | CI (`pie` build) | +| `src/extension/pg-query-ext/vendor/libpg_query` (`LIBPG_QUERY_VERSION`) | the C library compiled into the extension | CI (`pie` build) | | `.nix/pkgs/php-pg-query-ext/package.nix` (`libpg_query` `version`/`rev`/`hash`) | the C library compiled into the **nix dev shell** | local `nix-shell` | | `src/lib/postgresql/resources/proto/pg_query.proto` + the generated stubs in `src/lib/postgresql/src/Flow/PostgreSql/Protobuf/` | the protobuf schema the PHP side serializes/deserializes parse trees with | the `flow-php/postgresql` library | @@ -107,7 +107,8 @@ incident: PG17→PG18 left the stubs stale and crashed CI intermittently, while When you change the `libpg_query` version, do **all** of the following, then run the full PHP suite: -1. Bump the C side (`src/extension/pg-query-ext/Makefile` `PG_VERSION` / vendored copy). +1. Bump the C side: `LIBPG_QUERY_VERSION` in `src/extension/pg-query-ext/Makefile` and `ext/config.m4` (a release tag, never a + branch - `18-latest` moved under CI once), then `make distclean build`. 2. Bump the nix pin in `.nix/pkgs/php-pg-query-ext/package.nix` to the **same** `libpg_query` tag, and update its `hash` (`nix-prefetch-url --unpack ` → `nix hash convert --to sri`). 3. Regenerate the PHP stubs from the new grammar - sync `resources/proto/pg_query.proto` from diff --git a/documentation/contributing/wasm.md b/documentation/contributing/wasm.md index 91eae3c0fe..7a87725ab7 100644 --- a/documentation/contributing/wasm.md +++ b/documentation/contributing/wasm.md @@ -56,8 +56,7 @@ check), which is what triggers the rebuild. `src/extension/pg-query-ext/Makefile`, so the playground and the native extension can never disagree about which PostgreSQL grammar parses, and fails fast if that variable cannot be read. -The pin is a **branch** (`18-latest`), not a tag. Changing it re-clones automatically; upstream -moving the branch under a fixed version does not, and needs `rm -rf wasm/libpg_query-*`. +The pin is a release tag (`18.0.0`), so a build is reproducible. Changing it re-clones automatically. ## Included PHP Extensions @@ -334,7 +333,7 @@ Two consequences worth knowing before changing any of this: file of the *wrong* architecture, which the existing `[ ! -f ]` guard cannot detect. - **Switching target does not invalidate the dependency guards.** Each guard tests its own build output (`libxml2-2.11.4/` the source dir, `libzip-1.11.3/install/lib/libzip.a`, - `libpg_query-18-latest/libpg_query.a`), and none of them knows about the target. libzip + `libpg_query-18.0.0/libpg_query.a`), and none of them knows about the target. libzip additionally caches the resolved zlib path in `build/CMakeCache.txt`, which is why `build.sh` removes that directory before configuring. diff --git a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php index 28bb753c98..bc700258b9 100644 --- a/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php +++ b/src/adapter/etl-adapter-parquet/tests/Flow/ETL/Adapter/Parquet/Tests/Unit/AdaptiveParquetOpenSinkTest.php @@ -48,7 +48,7 @@ public function test_a_default_engine_writes_a_file_php_reads(?ParquetEngine $en $sink = new AdaptiveParquetOpenSink( $filesystem->writeTo(path('memory://out.parquet')), (new SchemaConverter())->toParquet($schema), - Compressions::ZSTD, + Compressions::GZIP, Options::default(), $engine, ); diff --git a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLNodes.php b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLNodes.php index fc0c840e1b..bc1e7b82f5 100644 --- a/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLNodes.php +++ b/src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/XMLNodes.php @@ -5,6 +5,7 @@ namespace Flow\ETL\Adapter\XML; use DOMDocument; +use Flow\ETL\Column\Physical\XmlCharacterReferences; use Flow\Filesystem\SourceStream; use Generator; @@ -62,6 +63,7 @@ public function documents(SourceStream $stream, int $bufferSize): Generator public function texts(SourceStream $stream, int $bufferSize): Generator { $internalErrors = libxml_use_internal_errors(); + $references = new XmlCharacterReferences(); foreach ($this->cursor->of($stream, $bufferSize) as $reader) { $text = @$reader->readOuterXml(); @@ -72,7 +74,7 @@ public function texts(SourceStream $stream, int $bufferSize): Generator libxml_use_internal_errors($internalErrors); - yield $text; + yield $references->decoded($text); } } } diff --git a/src/core/etl/src/Flow/ETL/Column/Physical/XmlCharacterReferences.php b/src/core/etl/src/Flow/ETL/Column/Physical/XmlCharacterReferences.php new file mode 100644 index 0000000000..ad0eee99a2 --- /dev/null +++ b/src/core/etl/src/Flow/ETL/Column/Physical/XmlCharacterReferences.php @@ -0,0 +1,43 @@ +||&#(x[0-9A-Fa-f]+|[0-9]+);/s', + static function (array $match): string { + if (!array_key_exists(1, $match)) { + return $match[0]; + } + + $codepoint = str_starts_with($match[1], 'x') ? hexdec(substr($match[1], 1)) : intval($match[1]); + + return $codepoint < 0x80 ? $match[0] : html_entity_decode($match[0], ENT_XML1 | ENT_QUOTES, 'UTF-8'); + }, + $xml, + ); + } +} diff --git a/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php index 5fc8b20c7c..e8702f5296 100644 --- a/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php @@ -56,7 +56,7 @@ public function toPhysical(mixed $value): mixed throw new InvalidArgumentException('Floe failed to convert DOMDocument to XML string'); } - return $xml; + return (new XmlCharacterReferences())->decoded($xml); } public function fromPhysical(mixed $physical): mixed diff --git a/src/core/etl/src/Flow/ETL/Column/Physical/XmlElementPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/XmlElementPhysical.php index ddba6bea49..aa443b8032 100644 --- a/src/core/etl/src/Flow/ETL/Column/Physical/XmlElementPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/XmlElementPhysical.php @@ -34,6 +34,8 @@ public function toPhysical(mixed $value): mixed throw new InvalidArgumentException('Floe failed to convert DOMElement to XML string'); } + $xml = (new XmlCharacterReferences())->decoded($xml); + return $path === null ? $xml : $this->position->physical($path, $this->canonical($value), $xml); } @@ -43,6 +45,7 @@ public function toPhysical(mixed $value): mixed // @mago-ignore analysis:mixed-assignment $markup = $value->ownerDocument?->saveXml($path === null ? $value : null); assert(is_string($markup)); + $markup = (new XmlCharacterReferences())->decoded($markup); return $path === null ? $markup : $this->position->physical($path, $this->canonical($value), $markup); } diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlCharacterReferencesTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlCharacterReferencesTest.php new file mode 100644 index 0000000000..43acc0d390 --- /dev/null +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Column/Physical/XmlCharacterReferencesTest.php @@ -0,0 +1,24 @@ +', ''])] + #[TestWith(['', ''])] + #[TestWith(['', ''])] + #[TestWith(['', ''])] + #[TestWith(['', ''])] + #[TestWith(['', ''])] + #[TestWith(['&', '&'])] + public function test_decodes_non_ascii_references_outside_cdata_and_comments(string $xml, string $decoded): void + { + static::assertSame($decoded, (new XmlCharacterReferences())->decoded($xml)); + } +} diff --git a/src/extension/arrow-ext/tests/phpt/052_parquet_file_reader_writer_contracts.phpt b/src/extension/arrow-ext/tests/phpt/052_parquet_file_reader_writer_contracts.phpt index d047472fdf..35320738f6 100644 --- a/src/extension/arrow-ext/tests/phpt/052_parquet_file_reader_writer_contracts.phpt +++ b/src/extension/arrow-ext/tests/phpt/052_parquet_file_reader_writer_contracts.phpt @@ -88,7 +88,7 @@ $writer = static fn($stream, Compressions $compression = Compressions::SNAPPY, i ); $values = static fn(string $uri): string => json_encode(iterator_to_array(Reader::php()->readStream($filesystem->readFrom(path($uri)))->values(), false)); -$file = $writer($filesystem->writeTo(path('memory://doors.parquet')), Compressions::LZ4, 2); +$file = $writer($filesystem->writeTo(path('memory://doors.parquet')), Compressions::GZIP, 2); var_dump($file instanceof ParquetFileWriter); $file->writeRow(['id' => 1]); $file->writeBatch([['id' => 2], 'key' => ['id' => 3, 'name' => 'c']]); diff --git a/src/extension/pg-query-ext/Makefile b/src/extension/pg-query-ext/Makefile index 8164b79ef1..76872ec6a2 100644 --- a/src/extension/pg-query-ext/Makefile +++ b/src/extension/pg-query-ext/Makefile @@ -1,5 +1,5 @@ # Flow PHP pg_query Extension Makefile -LIBPG_QUERY_VERSION := 18-latest +LIBPG_QUERY_VERSION := 18.0.0 LIBPG_QUERY_DIR := ./vendor/libpg_query LIBPG_QUERY_LIB := $(LIBPG_QUERY_DIR)/libpg_query.a EXTENSION_DIR := ./ext diff --git a/src/extension/pg-query-ext/ext/config.m4 b/src/extension/pg-query-ext/ext/config.m4 index c2ac294b4d..10f0d454cc 100644 --- a/src/extension/pg-query-ext/ext/config.m4 +++ b/src/extension/pg-query-ext/ext/config.m4 @@ -6,13 +6,13 @@ PHP_ARG_WITH([pg-query], [Include pg_query support. DIR is the libpg_query install prefix (optional - will download if not found)])]) if test "$PHP_PG_QUERY" != "no"; then - dnl libpg_query 18-latest is required for postgres_deparse.h support - LIBPG_QUERY_VERSION="18-latest" + dnl libpg_query 18.0.0 (PostgreSQL 18 grammar) is required for postgres_deparse.h support + LIBPG_QUERY_VERSION="18.0.0" AC_MSG_NOTICE([Using libpg_query $LIBPG_QUERY_VERSION (PostgreSQL 18 grammar)]) PG_QUERY_DIR="" - dnl Expected PostgreSQL major derived from the pinned version ("18-latest" -> "18", "18.0.0" -> "18") + dnl Expected PostgreSQL major derived from the pinned version ("18.0.0" -> "18") PG_EXPECTED_MAJOR=`echo "$LIBPG_QUERY_VERSION" | sed -E 's/^([[0-9]]+).*/\1/'` dnl Search for existing libpg_query installation diff --git a/tools/infection/phpunit.xml b/tools/infection/phpunit.xml index b150360b53..27447a2060 100644 --- a/tools/infection/phpunit.xml +++ b/tools/infection/phpunit.xml @@ -21,4 +21,7 @@ ../../src/core/etl/src/Flow/ETL/DSL + + + From 4900c248e1e917c345ae5ca9624db1573d98d8ee Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sun, 4 Oct 2026 10:12:30 +0200 Subject: [PATCH 19/21] fix(flow-php/etl): XML column text decodes non-ASCII character references - CI builds pg-query-ext with a dev version when the checkout has no tags --- .github/actions/pg-query-ext/action.yml | 7 ++++++- src/core/etl/src/Flow/ETL/Column/TextValues.php | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/actions/pg-query-ext/action.yml b/.github/actions/pg-query-ext/action.yml index 626a845772..fd757eb010 100644 --- a/.github/actions/pg-query-ext/action.yml +++ b/.github/actions/pg-query-ext/action.yml @@ -25,7 +25,12 @@ runs: if: ${{ steps.cache.outputs.cache-hit != 'true' }} shell: bash working-directory: src/extension/pg-query-ext - run: make build + # a shallow checkout has no tags for config.m4 to describe; this build only runs the test suite + run: | + if ! git describe --tags --match '[0-9]*' >/dev/null 2>&1; then + export PG_QUERY_EXT_VERSION="0.0.0-0-g$(git rev-parse --short HEAD)" + fi + make build - name: "Enable pg-query-ext" shell: bash diff --git a/src/core/etl/src/Flow/ETL/Column/TextValues.php b/src/core/etl/src/Flow/ETL/Column/TextValues.php index 4757e9c272..76138623dc 100644 --- a/src/core/etl/src/Flow/ETL/Column/TextValues.php +++ b/src/core/etl/src/Flow/ETL/Column/TextValues.php @@ -8,6 +8,7 @@ use DOMDocument; use Flow\ETL\Column\Physical\HtmlElementPhysical; use Flow\ETL\Column\Physical\PhysicalFor; +use Flow\ETL\Column\Physical\XmlCharacterReferences; use Flow\ETL\Column\Physical\XmlDocumentPhysical; use Flow\ETL\Column\Physical\XmlElementPhysical; use Flow\ETL\Exception\RuntimeException; @@ -119,6 +120,7 @@ public function of(Type $type, array $physicals): array if ($bare instanceof XMLType) { $nodes = (new PhysicalFor())->type($bare); $documents = new XmlDocumentPhysical(); + $references = new XmlCharacterReferences(); $values = []; // @mago-ignore analysis:mixed-assignment @@ -140,7 +142,7 @@ public function of(Type $type, array $physicals): array throw new RuntimeException('Failed to serialize XML document.'); } - $values[] = $text; + $values[] = $references->decoded($text); } return $values; From de456ddb47f8b33e27044780b63458b7a7712319 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sun, 4 Oct 2026 10:51:18 +0200 Subject: [PATCH 20/21] fix(flow-php/etl): XML text on libxml2 before 2.13 and PHP 8.4/8.5 extension tests - restored XML documents without an encoding are UTF-8 - mismatch messages name NAN and INF instead of coercing them - flow_php phpts: a valid html document, self resolved to its interface on PHP 8.5 --- .../src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php | 3 +++ .../src/Flow/ETL/Exception/ColumnMismatchException.php | 4 ++++ src/extension/flow-php-ext/tests/phpt/bootstrap.php | 8 +++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php b/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php index e8702f5296..9f97ee11c6 100644 --- a/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php +++ b/src/core/etl/src/Flow/ETL/Column/Physical/XmlDocumentPhysical.php @@ -69,6 +69,9 @@ public function fromPhysical(mixed $physical): mixed throw new InvalidArgumentException(sprintf('Floe failed to restore DOMDocument from "%s"', $physical)); } + // libxml2 before 2.13 writes non-ASCII attribute characters of a document without an encoding as references + $document->encoding ??= 'UTF-8'; + return $document; } diff --git a/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php b/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php index e112e792d2..b6c1988cbe 100644 --- a/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php +++ b/src/core/etl/src/Flow/ETL/Exception/ColumnMismatchException.php @@ -13,7 +13,9 @@ use function get_debug_type; use function is_bool; use function is_float; +use function is_infinite; use function is_int; +use function is_nan; use function is_string; use function sprintf; use function strlen; @@ -105,6 +107,8 @@ private static function describe(mixed $value): string return match (true) { is_string($value) => "'" . (strlen($value) > 32 ? substr($value, 0, 32) . '...' : $value) . "'", is_bool($value) => $value ? 'true' : 'false', + is_float($value) && is_nan($value) => 'NAN', + is_float($value) && is_infinite($value) => $value > 0 ? 'INF' : '-INF', is_int($value), is_float($value) => (string) $value, $value instanceof DateTimeInterface => $value->format('Y-m-d\TH:i:s.uP'), default => get_debug_type($value), diff --git a/src/extension/flow-php-ext/tests/phpt/bootstrap.php b/src/extension/flow-php-ext/tests/phpt/bootstrap.php index 35fb5ab463..28a1cd3bdd 100644 --- a/src/extension/flow-php-ext/tests/phpt/bootstrap.php +++ b/src/extension/flow-php-ext/tests/phpt/bootstrap.php @@ -190,7 +190,7 @@ function all_types_values(): array if (class_exists('\\Dom\\HTMLDocument')) { foreach ($rows as $index => $row) { - $rows[$index] = $row + ['html' => '

          html

          ']; + $rows[$index] = $row + ['html' => '

          html

          ']; } } @@ -319,14 +319,16 @@ function interfaces_reflection(): string 'Flow\\ETL\\Adapter\\Parquet\\ParquetOpenSource', ] as $name) { $class = new ReflectionClass($name); + // PHP 8.5 reports a userland `self` resolved to the class, an internal one stays `self` - the same type + $type = static fn(?ReflectionType $type): string => (string) $type === 'self' ? $name : (string) $type; $interfaces[$name] = [ $class->isInterface(), array_map(static fn(ReflectionMethod $method): array => [ $method->getName(), - (string) $method->getReturnType(), + $type($method->getReturnType()), array_map(static fn(ReflectionParameter $parameter): array => [ $parameter->getName(), - (string) $parameter->getType(), + $type($parameter->getType()), $parameter->isOptional(), $parameter->isVariadic(), $parameter->isPassedByReference(), From b41fe2f43858eeb18390f2dc8f2afcefc6c55a3b Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sun, 4 Oct 2026 11:03:18 +0200 Subject: [PATCH 21/21] fix(flow-php/flow-php-ext): a zone transition at the batch's last instant is applied on system tzdata --- src/extension/flow-php-ext/src/text/date.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/extension/flow-php-ext/src/text/date.rs b/src/extension/flow-php-ext/src/text/date.rs index 17e58d80e2..c574140c00 100644 --- a/src/extension/flow-php-ext/src/text/date.rs +++ b/src/extension/flow-php-ext/src/text/date.rs @@ -93,8 +93,9 @@ impl Zone { } } - /// A named zone reads `DateTimeZone::getTransitions($min, $max)`: the offset in force at `$min`, then every change - /// up to `$max`. Once per batch per column. + /// A named zone reads `DateTimeZone::getTransitions($min, $max + 1)`: the offset in force at `$min`, then every + /// change up to and including `$max`. PHP built against the system tzdata (Debian, Ubuntu) leaves out a transition + /// at exactly the end of the range, PHP's bundled database keeps it. Once per batch per column. pub fn resolve(&mut self, min_second: i64, max_second: i64) -> Result<(), PhpException> { let Zone::Named { id, transitions } = self else { return Ok(()); @@ -103,7 +104,7 @@ impl Zone { let listed = call_method( &ctx::timezone(id)?, "getTransitions", - &mut [zval_long(min_second), zval_long(max_second)], + &mut [zval_long(min_second), zval_long(max_second.saturating_add(1))], )?; let listed = listed .array()

        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%0D;jq^amY5pRQ#Ri4NMuL(1wp^AEVBUjkxjb|Rx` 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 z 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

      R0CyaF(!v${09A()I7isSD+12utt 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%0Dj@s=>E9AmuzrW0nwZ?mU;MK+#)tq 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 z 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%0AF_SPptv!;8 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�sVJs`;Q4zGr1 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

      %i)CR@^@fT@J=HitnU1j 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

      cbTr7m8DS{~LiOU5+C00gT!H3|A?L9|Me? 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 literal 17080387 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

      Nz^*(oJb5ue{P%i^M3PWdmp7-K9X14IV5#=c7r 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�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
      wHb8LEUc%aF>lFf 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
      @C9zf5_M7hZsdVz**w{GpzM5L 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